All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/8] fb: hisilicon: Add framebuffer driver for hi3660 SoC
@ 2017-02-07  2:35   ` cailiwei
  0 siblings, 0 replies; 15+ messages in thread
From: cailiwei @ 2017-02-07  2:35 UTC (permalink / raw)
  To: linux-fbdev, linux-kernel, b.zolnierkie, guodong.xu
  Cc: suzhuangluan, dengqingshan, xuhongtao8, zhengwanchun,
	shizongxuan, cailiwei

From: Levy-Cai <cailiwei@hisilicon.com>

Add framebuffer driver for hi3660 SoC, this driver include lcd
driver & Hdmi adv7533/adv7535 driver, support lcd display at
1080p@60 and hdmi display at 1080p@60.

Signed-off-by: cailiwei <cailiwei@hisilicon.com>
---
 drivers/video/fbdev/Kconfig           | 11 ++++++++++
 drivers/video/fbdev/Makefile          |  1 +
 drivers/video/fbdev/hisi/Kconfig      |  6 +++++
 drivers/video/fbdev/hisi/dss/Makefile | 41 +++++++++++++++++++++++++++++++++++
 4 files changed, 59 insertions(+)
 mode change 100644 => 100755 drivers/video/fbdev/Kconfig
 mode change 100644 => 100755 drivers/video/fbdev/Makefile
 create mode 100755 drivers/video/fbdev/hisi/Kconfig
 create mode 100755 drivers/video/fbdev/hisi/dss/Makefile

diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
old mode 100644
new mode 100755
index 5d3b0db5ce0a..85c46cc75908
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -2429,6 +2429,16 @@ config FB_HYPERV
 	help
 	  This framebuffer driver supports Microsoft Hyper-V Synthetic Video.
 
+config FB_HISI
+	tristate "Hisilicon Framebuffer support"
+	depends on FB
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select REGMAP
+	help
+	  This framebuffer driver supports Hisilicon FB.
+
 config FB_SIMPLE
 	bool "Simple framebuffer support"
 	depends on (FB = y)
@@ -2448,6 +2458,7 @@ config FB_SIMPLE
 source "drivers/video/fbdev/omap/Kconfig"
 source "drivers/video/fbdev/omap2/Kconfig"
 source "drivers/video/fbdev/mmp/Kconfig"
+source "drivers/video/fbdev/hisi/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 ee8c81405a7f..a10d3d2793e3
--- a/drivers/video/fbdev/Makefile
+++ b/drivers/video/fbdev/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_FB_I740)		  += i740fb.o
 obj-$(CONFIG_FB_MATROX)		  += matrox/
 obj-$(CONFIG_FB_RIVA)		  += riva/
 obj-$(CONFIG_FB_NVIDIA)		  += nvidia/
+obj-$(CONFIG_FB_HISI)             += hisi/dss/
 obj-$(CONFIG_FB_ATY)		  += aty/ macmodes.o
 obj-$(CONFIG_FB_ATY128)		  += aty/ macmodes.o
 obj-$(CONFIG_FB_RADEON)		  += aty/
diff --git a/drivers/video/fbdev/hisi/Kconfig b/drivers/video/fbdev/hisi/Kconfig
new file mode 100755
index 000000000000..c30747d52a38
--- /dev/null
+++ b/drivers/video/fbdev/hisi/Kconfig
@@ -0,0 +1,6 @@
+config HISI_FB_KIRIN960
+	tristate "HISI FB KIRIN960 Framebuffer support"
+	depends on FB_HISI
+
+	help
+	  This framebuffer driver supports KIRIN960 FB.
diff --git a/drivers/video/fbdev/hisi/dss/Makefile b/drivers/video/fbdev/hisi/dss/Makefile
new file mode 100755
index 000000000000..60004880dd80
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/Makefile
@@ -0,0 +1,41 @@
+ifeq ($(CONFIG_HISI_FB_KIRIN960),y)
+obj-$(CONFIG_HISI_FB_KIRIN960) := hisifb.o
+endif
+
+hisifb-objs := \
+	hisi_mipi_dsi_host.o \
+	hisi_mipi_dsi.o \
+	hisi_dpe.o \
+	hisi_fb_panel.o \
+	hisi_fb_isr.o \
+	hisi_fb_vsync.o \
+	hisi_fb_buf_sync.o \
+	hisi_fb_bl.o \
+	hisi_fb_utils.o \
+	hisi_fb.o \
+	hisi_overlay_utils.o \
+	hisi_block_algorithm.o \
+	hisi_overlay_online.o \
+	hisi_overlay_cmdlist_utils.o
+
+ifeq ($(CONFIG_HISI_FB_KIRIN960),y)
+hisifb-objs += \
+	hisi_dpe_utils_hi3660.o \
+	hisi_overlay_utils_hi3660.o \
+	panel/mipi_hikey_nte300nts.o \
+	hdmi/adv75xx.o \
+	hdmi/mipi_adi_hdmi.o
+endif
+
+EXTRA_CFLAGS += -Idrivers/video/hisi/dss \
+		-Idrivers/video/hisi/panel \
+		-Idrivers/video/hisi \
+		-Iinclude \
+		-Idrivers/staging/android
+
+ifeq ($(CONFIG_HISI_PERIDVFS),y)
+EXTRA_CFLAGS += -Idrivers/clk/hisi/peri_dvfs
+endif
+
+clean:
+	rm *.o .*cmd
-- 
2.12.0-rc0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 1/8] fb: hisilicon: Add framebuffer driver for hi3660 SoC
@ 2017-02-07  2:35   ` cailiwei
  0 siblings, 0 replies; 15+ messages in thread
From: cailiwei @ 2017-02-07  2:35 UTC (permalink / raw)
  To: linux-fbdev, linux-kernel, b.zolnierkie, guodong.xu
  Cc: suzhuangluan, dengqingshan, xuhongtao8, zhengwanchun,
	shizongxuan, cailiwei

From: Levy-Cai <cailiwei@hisilicon.com>

Add framebuffer driver for hi3660 SoC, this driver include lcd
driver & Hdmi adv7533/adv7535 driver, support lcd display at
1080p@60 and hdmi display at 1080p@60.

Signed-off-by: cailiwei <cailiwei@hisilicon.com>
---
 drivers/video/fbdev/Kconfig           | 11 ++++++++++
 drivers/video/fbdev/Makefile          |  1 +
 drivers/video/fbdev/hisi/Kconfig      |  6 +++++
 drivers/video/fbdev/hisi/dss/Makefile | 41 +++++++++++++++++++++++++++++++++++
 4 files changed, 59 insertions(+)
 mode change 100644 => 100755 drivers/video/fbdev/Kconfig
 mode change 100644 => 100755 drivers/video/fbdev/Makefile
 create mode 100755 drivers/video/fbdev/hisi/Kconfig
 create mode 100755 drivers/video/fbdev/hisi/dss/Makefile

diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
old mode 100644
new mode 100755
index 5d3b0db5ce0a..85c46cc75908
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -2429,6 +2429,16 @@ config FB_HYPERV
 	help
 	  This framebuffer driver supports Microsoft Hyper-V Synthetic Video.
 
+config FB_HISI
+	tristate "Hisilicon Framebuffer support"
+	depends on FB
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select REGMAP
+	help
+	  This framebuffer driver supports Hisilicon FB.
+
 config FB_SIMPLE
 	bool "Simple framebuffer support"
 	depends on (FB = y)
@@ -2448,6 +2458,7 @@ config FB_SIMPLE
 source "drivers/video/fbdev/omap/Kconfig"
 source "drivers/video/fbdev/omap2/Kconfig"
 source "drivers/video/fbdev/mmp/Kconfig"
+source "drivers/video/fbdev/hisi/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 ee8c81405a7f..a10d3d2793e3
--- a/drivers/video/fbdev/Makefile
+++ b/drivers/video/fbdev/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_FB_I740)		  += i740fb.o
 obj-$(CONFIG_FB_MATROX)		  += matrox/
 obj-$(CONFIG_FB_RIVA)		  += riva/
 obj-$(CONFIG_FB_NVIDIA)		  += nvidia/
+obj-$(CONFIG_FB_HISI)             += hisi/dss/
 obj-$(CONFIG_FB_ATY)		  += aty/ macmodes.o
 obj-$(CONFIG_FB_ATY128)		  += aty/ macmodes.o
 obj-$(CONFIG_FB_RADEON)		  += aty/
diff --git a/drivers/video/fbdev/hisi/Kconfig b/drivers/video/fbdev/hisi/Kconfig
new file mode 100755
index 000000000000..c30747d52a38
--- /dev/null
+++ b/drivers/video/fbdev/hisi/Kconfig
@@ -0,0 +1,6 @@
+config HISI_FB_KIRIN960
+	tristate "HISI FB KIRIN960 Framebuffer support"
+	depends on FB_HISI
+
+	help
+	  This framebuffer driver supports KIRIN960 FB.
diff --git a/drivers/video/fbdev/hisi/dss/Makefile b/drivers/video/fbdev/hisi/dss/Makefile
new file mode 100755
index 000000000000..60004880dd80
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/Makefile
@@ -0,0 +1,41 @@
+ifeq ($(CONFIG_HISI_FB_KIRIN960),y)
+obj-$(CONFIG_HISI_FB_KIRIN960) := hisifb.o
+endif
+
+hisifb-objs := \
+	hisi_mipi_dsi_host.o \
+	hisi_mipi_dsi.o \
+	hisi_dpe.o \
+	hisi_fb_panel.o \
+	hisi_fb_isr.o \
+	hisi_fb_vsync.o \
+	hisi_fb_buf_sync.o \
+	hisi_fb_bl.o \
+	hisi_fb_utils.o \
+	hisi_fb.o \
+	hisi_overlay_utils.o \
+	hisi_block_algorithm.o \
+	hisi_overlay_online.o \
+	hisi_overlay_cmdlist_utils.o
+
+ifeq ($(CONFIG_HISI_FB_KIRIN960),y)
+hisifb-objs += \
+	hisi_dpe_utils_hi3660.o \
+	hisi_overlay_utils_hi3660.o \
+	panel/mipi_hikey_nte300nts.o \
+	hdmi/adv75xx.o \
+	hdmi/mipi_adi_hdmi.o
+endif
+
+EXTRA_CFLAGS += -Idrivers/video/hisi/dss \
+		-Idrivers/video/hisi/panel \
+		-Idrivers/video/hisi \
+		-Iinclude \
+		-Idrivers/staging/android
+
+ifeq ($(CONFIG_HISI_PERIDVFS),y)
+EXTRA_CFLAGS += -Idrivers/clk/hisi/peri_dvfs
+endif
+
+clean:
+	rm *.o .*cmd
-- 
2.12.0-rc0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/8] fb: hisilicon: Add framebuffer driver for hi3660 SoC
  2017-02-07  2:35   ` cailiwei
@ 2017-02-07  2:35     ` cailiwei
  -1 siblings, 0 replies; 15+ messages in thread
From: cailiwei @ 2017-02-07  2:35 UTC (permalink / raw)
  To: linux-fbdev, linux-kernel, b.zolnierkie, guodong.xu
  Cc: suzhuangluan, dengqingshan, xuhongtao8, zhengwanchun,
	shizongxuan, cailiwei

From: Levy-Cai <cailiwei@hisilicon.com>

Add framebuffer driver for hi3660 SoC, this driver include lcd
driver & Hdmi adv7533/adv7535 driver, support lcd display at
1080p@60 and hdmi display at 1080p@60.

Signed-off-by: cailiwei <cailiwei@hisilicon.com>
---
 drivers/video/fbdev/hisi/dss/hdmi/adv75xx.c        | 1522 ++++++++++++++++++++
 drivers/video/fbdev/hisi/dss/hdmi/adv75xx.h        |  496 +++++++
 drivers/video/fbdev/hisi/dss/hdmi/adv75xx_audio.c  |  310 ++++
 drivers/video/fbdev/hisi/dss/hdmi/mipi_adi_hdmi.c  |  314 ++++
 .../fbdev/hisi/dss/panel/mipi_hikey_nte300nts.c    |  525 +++++++
 5 files changed, 3167 insertions(+)
 create mode 100755 drivers/video/fbdev/hisi/dss/hdmi/adv75xx.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hdmi/adv75xx.h
 create mode 100755 drivers/video/fbdev/hisi/dss/hdmi/adv75xx_audio.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hdmi/mipi_adi_hdmi.c
 create mode 100755 drivers/video/fbdev/hisi/dss/panel/mipi_hikey_nte300nts.c

diff --git a/drivers/video/fbdev/hisi/dss/hdmi/adv75xx.c b/drivers/video/fbdev/hisi/dss/hdmi/adv75xx.c
new file mode 100755
index 000000000000..328cd6869149
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hdmi/adv75xx.c
@@ -0,0 +1,1522 @@
+/**
+ *
+ *
+ **/
+
+#include "adv75xx.h"
+#define HPD_ENABLE	0
+/* #define TEST_COLORBAR_DISPLAY */
+
+static void adv75xx_power_on(struct adi_hdmi *adv75xx);
+static void adv75xx_power_off(struct adi_hdmi *adv75xx);
+
+/* ADI recommended values for proper operation. */
+static const struct reg_sequence adv7511_fixed_registers[] = {
+	{0x98, 0x03},
+	{0x9a, 0xe0},
+	{0x9c, 0x30},
+	{0x9d, 0x61},
+	{0xa2, 0xa4},
+	{0xa3, 0xa4},
+	{0xe0, 0xd0},
+	{0xf9, 0x00},
+	{0x55, 0x02},
+};
+
+/* ADI recommended values for proper operation. */
+static const struct reg_sequence adv7533_fixed_registers[] = {
+	{0x16, 0x20},
+	{0x9a, 0xe0},
+	{0xba, 0x70},
+	{0xde, 0x82},
+	{0xe4, 0x40},
+	{0xe5, 0x80},
+};
+
+static const struct reg_sequence adv7533_cec_fixed_registers[] = {
+	{0x15, 0xd0},
+	{0x17, 0xd0},
+	{0x24, 0x20},
+	{0x57, 0x11},
+	{0x05, 0xc8},
+};
+
+/* -----------------------------------------------------------------------------
+ * Register access
+ */
+
+static const uint8_t adv75xx_register_defaults[] = {
+	0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 00 */
+	0x00, 0x00, 0x01, 0x0e, 0xbc, 0x18, 0x01, 0x13,
+	0x25, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 10 */
+	0x46, 0x62, 0x04, 0xa8, 0x00, 0x00, 0x1c, 0x84,
+	0x1c, 0xbf, 0x04, 0xa8, 0x1e, 0x70, 0x02, 0x1e,	/* 20 */
+	0x00, 0x00, 0x04, 0xa8, 0x08, 0x12, 0x1b, 0xac,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 30 */
+	0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0,
+	0x00, 0x50, 0x90, 0x7e, 0x79, 0x70, 0x00, 0x00,	/* 40 */
+	0x00, 0xa8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x00, 0x00,	/* 50 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 60 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 70 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 80 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,	/* 90 */
+	0x0b, 0x02, 0x00, 0x18, 0x5a, 0x60, 0x00, 0x00,
+	0x00, 0x00, 0x80, 0x80, 0x08, 0x04, 0x00, 0x00,	/* a0 */
+	0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x14,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* b0 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* c0 */
+	0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x01, 0x04,
+	0x30, 0xff, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,	/* d0 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01,
+	0x80, 0x75, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,	/* e0 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x11, 0x00,	/* f0 */
+	0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static bool adv7511_register_volatile(struct device *dev, unsigned int reg)
+{
+	int ret = 0;
+
+	switch (reg) {
+	case ADV7533_REG_CHIP_REVISION:
+	case ADV7533_REG_SPDIF_FREQ:
+	case ADV7533_REG_CTS_AUTOMATIC1:
+	case ADV7533_REG_CTS_AUTOMATIC2:
+	case ADV7533_REG_VIC_DETECTED:
+	case ADV7533_REG_VIC_SEND:
+	case ADV7533_REG_AUX_VIC_DETECTED:
+	case ADV7533_REG_STATUS:
+	case ADV7533_REG_GC(1):
+	case ADV7533_REG_INT(0):
+	case ADV7533_REG_INT(1):
+	case ADV7533_REG_PLL_STATUS:
+	case ADV7533_REG_AN(0):
+	case ADV7533_REG_AN(1):
+	case ADV7533_REG_AN(2):
+	case ADV7533_REG_AN(3):
+	case ADV7533_REG_AN(4):
+	case ADV7533_REG_AN(5):
+	case ADV7533_REG_AN(6):
+	case ADV7533_REG_AN(7):
+	case ADV7533_REG_HDCP_STATUS:
+	case ADV7533_REG_BCAPS:
+	case ADV7533_REG_BKSV(0):
+	case ADV7533_REG_BKSV(1):
+	case ADV7533_REG_BKSV(2):
+	case ADV7533_REG_BKSV(3):
+	case ADV7533_REG_BKSV(4):
+	case ADV7533_REG_DDC_STATUS:
+	case ADV7533_REG_BSTATUS(0):
+	case ADV7533_REG_BSTATUS(1):
+	case ADV7533_REG_CHIP_ID_HIGH:
+	case ADV7533_REG_CHIP_ID_LOW:
+		ret = 1;
+		break;
+	default:
+		ret = 0;
+		break;
+	}
+
+	return ret ? true : false;
+}
+
+static const struct regmap_config adv75xx_regmap_config = {
+	.name = "adv75xx",
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = 0xff,
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults_raw = adv75xx_register_defaults,
+	.num_reg_defaults_raw = ARRAY_SIZE(adv75xx_register_defaults),
+	.volatile_reg = adv7511_register_volatile,
+};
+
+static const struct regmap_config adv7533_cec_regmap_config = {
+	.name = "adv7533_cec",
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = 0xff,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+static const struct regmap_config adv7533_packet_regmap_config = {
+	.name = "adv7533_packet",
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = 0xff,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+/* -----------------------------------------------------------------------------
+ * Hardware configuration
+ */
+static void adv75xx_set_colormap(struct adi_hdmi *adv75xx, bool enable,
+				 const u16 *coeff, unsigned int scaling_factor)
+{
+	unsigned int i;
+
+	HISI_FB_INFO("+.\n");
+
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_CSC_UPPER(1),
+			   ADV7533_CSC_UPDATE_MODE, ADV7533_CSC_UPDATE_MODE);
+
+	if (enable) {
+		for (i = 0; i < 12; ++i) {
+			regmap_update_bits(adv75xx->regmap,
+					   ADV7533_REG_CSC_UPPER(i),
+					   0x1f, coeff[i] >> 8);
+			regmap_write(adv75xx->regmap,
+				     ADV7533_REG_CSC_LOWER(i), coeff[i] & 0xff);
+		}
+	}
+
+	if (enable)
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_CSC_UPPER(0),
+				   0xe0, 0x80 | (scaling_factor << 5));
+	else
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_CSC_UPPER(0),
+				   0x80, 0x00);
+
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_CSC_UPPER(1),
+			   ADV7533_CSC_UPDATE_MODE, 0);
+
+	HISI_FB_INFO("-.\n");
+}
+
+int adv75xx_packet_enable(struct adi_hdmi *adv75xx, unsigned int packet)
+{
+	HISI_FB_INFO("+.\n");
+
+	if (packet & 0xff)
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_PACKET_ENABLE0,
+				   packet, 0xff);
+
+	if (packet & 0xff00) {
+		packet >>= 8;
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_PACKET_ENABLE1,
+				   packet, 0xff);
+	}
+
+	HISI_FB_INFO("-.\n");
+
+	return 0;
+}
+
+int adv75xx_packet_disable(struct adi_hdmi *adv75xx, unsigned int packet)
+{
+	HISI_FB_INFO("+.\n");
+
+	if (packet & 0xff)
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_PACKET_ENABLE0,
+				   packet, 0x00);
+
+	if (packet & 0xff00) {
+		packet >>= 8;
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_PACKET_ENABLE1,
+				   packet, 0x00);
+	}
+
+	HISI_FB_INFO("-.\n");
+
+	return 0;
+}
+
+/* Coefficients for adv75xx color space conversion */
+static const uint16_t adv75xx_csc_ycbcr_to_rgb[] = {
+	0x0734, 0x04ad, 0x0000, 0x1c1b,
+	0x1ddc, 0x04ad, 0x1f24, 0x0135,
+	0x0000, 0x04ad, 0x087c, 0x1b77,
+};
+
+static void adv75xx_set_config_csc(struct adi_hdmi *adv75xx, bool rgb)
+{
+	struct adv75xx_video_config config;
+	bool output_format_422, output_format_ycbcr;
+	unsigned int mode;
+	uint8_t infoframe[17];
+
+	HISI_FB_INFO("+.\n");
+
+	if (adv75xx->edid)
+		config.hdmi_mode = true;
+	else
+		config.hdmi_mode = false;
+
+	config.avi_infoframe.scan_mode = HDMI_SCAN_MODE_UNDERSCAN;
+
+	HISI_FB_INFO("adv75xx->rgb is %d\n", adv75xx->rgb);
+
+	if (rgb) {
+		config.csc_enable = false;
+		config.avi_infoframe.colorspace = HDMI_COLORSPACE_RGB;
+	} else {
+		config.csc_scaling_factor = ADV75xx_CSC_SCALING_4;
+		config.csc_coefficents = adv75xx_csc_ycbcr_to_rgb;
+	}
+
+	HISI_FB_INFO("config.avi_infoframe.colorspace = %d\n",
+		     config.avi_infoframe.colorspace);
+
+	if (config.hdmi_mode) {
+		mode = ADV7533_HDMI_CFG_MODE_HDMI;
+
+		switch (config.avi_infoframe.colorspace) {
+		case HDMI_COLORSPACE_YUV444:
+			output_format_422 = false;
+			output_format_ycbcr = true;
+			break;
+		case HDMI_COLORSPACE_YUV422:
+			output_format_422 = true;
+			output_format_ycbcr = true;
+			break;
+		default:
+			output_format_422 = false;
+			output_format_ycbcr = false;
+			break;
+		}
+	} else {
+		mode = ADV7533_HDMI_CFG_MODE_DVI;
+		output_format_422 = false;
+		output_format_ycbcr = false;
+	}
+
+	adv75xx_packet_disable(adv75xx, ADV7533_PACKET_ENABLE_AVI_INFOFRAME);
+
+	adv75xx_set_colormap(adv75xx, config.csc_enable,
+			     config.csc_coefficents, config.csc_scaling_factor);
+
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_VIDEO_INPUT_CFG1, 0x81,
+			   (output_format_422 << 7) | output_format_ycbcr);
+
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_HDCP_HDMI_CFG,
+			   ADV7533_HDMI_CFG_MODE_MASK, mode);
+
+	/* The AVI infoframe id is not configurable */
+	regmap_bulk_write(adv75xx->regmap, ADV7533_REG_AVI_INFOFRAME_VERSION,
+			  infoframe + 1, sizeof(infoframe) - 1);
+
+	adv75xx_packet_enable(adv75xx, ADV7533_PACKET_ENABLE_AVI_INFOFRAME);
+
+	HISI_FB_INFO("-.\n");
+}
+
+static void adv75xx_dsi_config_tgen(struct adi_hdmi *adv75xx)
+{
+	u8 clock_div_by_lanes[] = { 6, 4, 3 };	/* 2, 3, 4 lanes */
+	unsigned int hsw, hfp, hbp, vsw, vfp, vbp;
+
+	HISI_FB_INFO("+.\n");
+
+	hsw = adv75xx->mode->hsync_pulse_width;
+	hfp = adv75xx->mode->hsync_offset;
+	hbp = adv75xx->mode->htotal - adv75xx->mode->hsync_end;
+	vsw = adv75xx->mode->vsync_pulse_width;
+	vfp = adv75xx->mode->vsync_offset;
+	vbp = adv75xx->mode->vtotal - adv75xx->mode->vsync_end;
+
+	HISI_FB_INFO
+	    ("hsw = %d, hfp = %d, hbp = %d, vsw = %d, vfp= %d, vbp = %d\n",
+	     hsw, hfp, hbp, vsw, vfp, vbp);
+
+#ifdef TEST_COLORBAR_DISPLAY
+	/* set pixel clock auto mode */
+	regmap_write(adv75xx->regmap_cec, ADV7533_REG_CEC_PIXEL_CLOCK_DIV, 0x00);
+#else
+	/* set pixel clock divider mode */
+	regmap_write(adv75xx->regmap_cec, ADV7533_REG_CEC_PIXEL_CLOCK_DIV,
+		     clock_div_by_lanes[adv75xx->num_dsi_lanes - 2] << 3);
+#endif
+
+	HISI_FB_INFO("dsi->lanes = %d, htotal = %d, vtotal = %d\n",
+		     adv75xx->num_dsi_lanes, adv75xx->mode->htotal,
+		     adv75xx->mode->vtotal);
+
+	/* horizontal porch params */
+	regmap_write(adv75xx->regmap_cec, 0x28, adv75xx->mode->htotal >> 4);
+	regmap_write(adv75xx->regmap_cec, 0x29,
+		     (adv75xx->mode->htotal << 4) & 0xff);
+	regmap_write(adv75xx->regmap_cec, 0x2a, hsw >> 4);
+	regmap_write(adv75xx->regmap_cec, 0x2b, (hsw << 4) & 0xff);
+	regmap_write(adv75xx->regmap_cec, 0x2c, hfp >> 4);
+	regmap_write(adv75xx->regmap_cec, 0x2d, (hfp << 4) & 0xff);
+	regmap_write(adv75xx->regmap_cec, 0x2e, hbp >> 4);
+	regmap_write(adv75xx->regmap_cec, 0x2f, (hbp << 4) & 0xff);
+
+	/* vertical porch params */
+	regmap_write(adv75xx->regmap_cec, 0x30, adv75xx->mode->vtotal >> 4);
+	regmap_write(adv75xx->regmap_cec, 0x31,
+		     (adv75xx->mode->vtotal << 4) & 0xff);
+	regmap_write(adv75xx->regmap_cec, 0x32, vsw >> 4);
+	regmap_write(adv75xx->regmap_cec, 0x33, (vsw << 4) & 0xff);
+	regmap_write(adv75xx->regmap_cec, 0x34, vfp >> 4);
+	regmap_write(adv75xx->regmap_cec, 0x35, (vfp << 4) & 0xff);
+	regmap_write(adv75xx->regmap_cec, 0x36, vbp >> 4);
+	regmap_write(adv75xx->regmap_cec, 0x37, (vbp << 4) & 0xff);
+
+	/* 30Hz Low Refresh Rate (VIC Detection) */
+
+
+	HISI_FB_INFO("-.\n");
+}
+
+static void adv75xx_dsi_receiver_dpms(struct adi_hdmi *adv75xx)
+{
+	HISI_FB_INFO("+.\n");
+
+	if (adv75xx->type != ADV7533)
+		return;
+
+	if (adv75xx->powered) {
+		adv75xx_dsi_config_tgen(adv75xx);
+
+		/* set number of dsi lanes */
+		regmap_write(adv75xx->regmap_cec, ADV7533_REG_DSI_DATA_LANES,
+			     adv75xx->num_dsi_lanes << 4);
+
+#ifdef TEST_COLORBAR_DISPLAY
+		/* reset internal timing generator */
+		regmap_write(adv75xx->regmap_cec, 0x27, 0xcb);
+		regmap_write(adv75xx->regmap_cec, 0x27, 0x8b);
+		regmap_write(adv75xx->regmap_cec, 0x27, 0xcb);
+#else
+		/* disable internal timing generator */
+		regmap_write(adv75xx->regmap_cec, 0x27, 0x0b);
+#endif
+
+		/* 09-03 AVI Infoframe - RGB - 16-9 Aspect Ratio */
+		regmap_write(adv75xx->regmap, 0x55, 0x10);
+		regmap_write(adv75xx->regmap, 0x56, 0x28);
+
+		/* 04-04 GC Packet Enable */
+		regmap_write(adv75xx->regmap, 0x40, 0x80);
+
+		/* 04-06 GC Colour Depth - 24 Bit */
+		regmap_write(adv75xx->regmap, 0x4c, 0x04);
+
+		/* 04-09 Down Dither Output Colour Depth - 8 Bit (default) */
+		regmap_write(adv75xx->regmap, 0x49, 0x00);
+
+		/* 07-01 CEC Power Mode - Always Active */
+		regmap_write(adv75xx->regmap_cec, 0xbe, 0x3d);
+
+		/* enable hdmi */
+		regmap_write(adv75xx->regmap_cec, 0x03, 0x89);
+
+#ifdef TEST_COLORBAR_DISPLAY
+		/*enable test mode */
+		regmap_write(adv75xx->regmap_cec, 0x55, 0x80);
+#else
+		/* disable test mode */
+		regmap_write(adv75xx->regmap_cec, 0x55, 0x00);
+#endif
+		/* SPD */
+		{
+			static const unsigned char spd_if[] = {
+				0x83, 0x01, 25, 0x00,
+				'L', 'i', 'n', 'a', 'r', 'o', 0, 0,
+				'9', '6', 'b', 'o', 'a', 'r', 'd', 's',
+				':', 'H', 'i', 'k', 'e', 'y', 0, 0,
+			};
+			int n;
+
+			for (n = 0; n < sizeof(spd_if); n++)
+				regmap_write(adv75xx->regmap_packet, n,
+					     spd_if[n]);
+
+			/* enable send SPD */
+			regmap_update_bits(adv75xx->regmap, 0x40, BIT(6), BIT(6));
+		}
+
+		/* force audio */
+		/* hide Audio infoframe updates */
+		regmap_update_bits(adv75xx->regmap, 0x4a, BIT(5), BIT(5));
+
+		/* i2s, internal mclk, mclk-256 */
+		regmap_update_bits(adv75xx->regmap, 0x0a, 0x1f, 1);
+		regmap_update_bits(adv75xx->regmap, 0x0b, 0xe0, 0);
+		/* enable i2s, use i2s format, sample rate from i2s */
+		regmap_update_bits(adv75xx->regmap, 0x0c, 0xc7, BIT(2));
+		/* 16 bit audio */
+		regmap_update_bits(adv75xx->regmap, 0x0d, 0xff, 16);
+		/* 16-bit audio */
+		regmap_update_bits(adv75xx->regmap, 0x14, 0x0f, 2 << 4);
+		/* 48kHz */
+		regmap_update_bits(adv75xx->regmap, 0x15, 0xf0, 2 << 4);
+		/* enable N/CTS, enable Audio sample packets */
+		regmap_update_bits(adv75xx->regmap, 0x44, BIT(5), BIT(5));
+		/* N = 6144 */
+		regmap_write(adv75xx->regmap, 1, (6144 >> 16) & 0xf);
+		regmap_write(adv75xx->regmap, 2, (6144 >> 8) & 0xff);
+		regmap_write(adv75xx->regmap, 3, (6144) & 0xff);
+		/* automatic cts */
+		regmap_update_bits(adv75xx->regmap, 0x0a, BIT(7), 0);
+		/* enable N/CTS */
+		regmap_update_bits(adv75xx->regmap, 0x44, BIT(6), BIT(6));
+		/* not copyrighted */
+		regmap_update_bits(adv75xx->regmap, 0x12, BIT(5), BIT(5));
+
+		/* left source */
+		regmap_update_bits(adv75xx->regmap, 0x0e, 7 << 3, 0);
+		/* right source */
+		regmap_update_bits(adv75xx->regmap, 0x0e, 7 << 0, 1);
+		/* number of channels: sect 4.5.4: set to 0 */
+		regmap_update_bits(adv75xx->regmap, 0x73, 7, 1);
+		/* number of channels: sect 4.5.4: set to 0 */
+		regmap_update_bits(adv75xx->regmap, 0x73, 0xf0, 1 << 4);
+		/* sample rate: 48kHz */
+		regmap_update_bits(adv75xx->regmap, 0x74, 7 << 2, 3 << 2);
+		/* channel allocation reg: sect 4.5.4: set to 0 */
+		regmap_update_bits(adv75xx->regmap, 0x76, 0xff, 0);
+		/* enable audio infoframes */
+		regmap_update_bits(adv75xx->regmap, 0x44, BIT(3), BIT(3));
+
+		/* AV mute disable */
+		regmap_update_bits(adv75xx->regmap, 0x4b, BIT(7) | BIT(6), BIT(7));
+
+		/* use Audio infoframe updated info */
+		regmap_update_bits(adv75xx->regmap, 0x4a, BIT(5), 0);
+	} else {
+		regmap_write(adv75xx->regmap_cec, 0x03, 0x0b);
+		regmap_write(adv75xx->regmap_cec, 0x27, 0x0b);
+	}
+
+	HISI_FB_INFO("-.\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Interrupt and hotplug detection
+ */
+
+#if HPD_ENABLE
+static bool adv75xx_hpd(struct adi_hdmi *adv75xx)
+{
+	unsigned int irq0;
+	int ret;
+
+	HISI_FB_INFO("+.\n");
+
+	ret = regmap_read(adv75xx->regmap, ADV7533_REG_INT(0), &irq0);
+	if (ret < 0)
+		return false;
+
+	HISI_FB_INFO("irq0 = 0x%x\n", irq0);
+
+	if (irq0 & ADV7533_INT0_HDP) {
+		HISI_FB_INFO("HPD interrupt detected!\n");
+		regmap_write(adv75xx->regmap, ADV7533_REG_INT(0),
+			     ADV7533_INT0_HDP);
+		return true;
+	}
+
+	HISI_FB_INFO("-.\n");
+
+	return false;
+}
+#endif
+
+static int adv75xx_irq_process(struct adi_hdmi *adv75xx, bool process_hpd)
+{
+	unsigned int irq0, irq1;
+	int ret;
+
+	HISI_FB_INFO("+.\n");
+
+	ret = regmap_read(adv75xx->regmap, ADV7533_REG_INT(0), &irq0);
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_read(adv75xx->regmap, ADV7533_REG_INT(1), &irq1);
+	if (ret < 0)
+		return ret;
+
+	regmap_write(adv75xx->regmap, ADV7533_REG_INT(0), irq0);
+	regmap_write(adv75xx->regmap, ADV7533_REG_INT(1), irq1);
+
+	HISI_FB_INFO("adv7511_irq_process --> irq0 = 0x%x \n", irq0);
+	HISI_FB_INFO("adv7511_irq_process --> irq1 = 0x%x \n", irq1);
+
+	if (irq0 & ADV7533_INT0_EDID_READY || irq1 & ADV7533_INT1_DDC_ERROR) {
+		adv75xx->edid_read = true;
+		if (adv75xx->i2c_main->irq)
+			HISI_FB_INFO("adv7511_irq_process -->get i2c_main irq \n");
+
+		wake_up_all(&adv75xx->wq);
+	}
+
+	HISI_FB_INFO("-.\n");
+
+	return 0;
+}
+
+static irqreturn_t adv75xx_irq_handler(int irq, void *devid)
+{
+	struct adi_hdmi *adv75xx = devid;
+	int ret;
+
+	HISI_FB_INFO("+.\n");
+
+	ret = adv75xx_irq_process(adv75xx, true);
+
+	HISI_FB_INFO("-.\n");
+
+	return ret < 0 ? IRQ_NONE : IRQ_HANDLED;
+}
+
+/* -----------------------------------------------------------------------------
+ * EDID retrieval
+ */
+
+static int adv75xx_wait_for_edid(struct adi_hdmi *adv75xx, int timeout)
+{
+	int ret;
+
+	HISI_FB_INFO("+.\n");
+
+	if (adv75xx->i2c_main->irq) {
+		ret = wait_event_interruptible_timeout(adv75xx->wq,
+						       adv75xx->edid_read,
+						       msecs_to_jiffies(timeout));
+	} else {
+		for (; timeout > 0; timeout -= 25) {
+			ret = adv75xx_irq_process(adv75xx, false);
+			if (ret < 0)
+				break;
+
+			if (adv75xx->edid_read)
+				break;
+
+			msleep(25);
+		}
+	}
+
+	HISI_FB_INFO("-.\n");
+
+	return adv75xx->edid_read ? 0 : -EIO;
+}
+
+static void print_edid_info(u8 *block)
+{
+	int step, count;
+
+	count = 0x0;
+	while (count < EDID_LENGTH) {
+		step = 0;
+		do {
+			if (step == 0) {
+				HISI_FB_INFO("------ edid[%d]: 0x%2x \t", count,
+					     block[count]);
+			} else {
+				HISI_FB_INFO(" 0x%2x \t", block[count]);
+			}
+			step++;
+			count++;
+		} while (step < 8);
+
+		HISI_FB_INFO("\n");
+	}
+}
+
+struct hisi_display_mode *hisi_set_mode_info(void)
+{
+	struct hisi_display_mode *mode;
+	unsigned int hsw, hfp, hbp, vsw, vfp, vbp;
+
+	mode = kzalloc(sizeof(struct hisi_display_mode), GFP_KERNEL);
+	if (!mode)
+		return NULL;
+
+	mode->width_mm = 160 * 100;
+	mode->height_mm = 90 * 100;
+	mode->clock = 148500;
+	mode->hdisplay = 1920;
+	mode->vdisplay = 1080;
+	mode->hsync_offset = 88;
+	mode->hsync_pulse_width = 44;
+	mode->hsync_start = 2008;
+	mode->hsync_end = 2052;
+	mode->htotal = 2200;
+
+	mode->vsync_offset = 4;
+	mode->vsync_pulse_width = 5;
+	mode->vsync_start = 1084;
+	mode->vsync_end = 1089;
+	mode->vtotal = 1125;
+
+	hsw = mode->hsync_pulse_width;
+	hfp = mode->hsync_offset;
+	hbp = mode->htotal - mode->hsync_end;
+	vsw = mode->vsync_pulse_width;
+	vfp = mode->vsync_offset;
+	vbp = mode->vtotal - mode->vsync_end;
+
+	HISI_FB_INFO("The pixel clock is %d!!\n", mode->clock);
+	HISI_FB_INFO("The resolution is %d x %d !!\n", mode->hdisplay,
+		     mode->vdisplay);
+	HISI_FB_INFO
+	    ("hsw = %d, hfp = %d, hbp = %d, vsw = %d, vfp= %d, vbp = %d\n",
+	     hsw, hfp, hbp, vsw, vfp, vbp);
+
+
+	return mode;
+}
+
+struct hisi_display_mode *hisi_parse_edid_base_info(u8 *block)
+{
+	struct hisi_display_mode *mode;
+	char edid_vendor[3];
+	unsigned hblank;
+	unsigned vblank;
+	unsigned int hsw, hfp, hbp, vsw, vfp, vbp;
+
+	mode = kzalloc(sizeof(struct hisi_display_mode), GFP_KERNEL);
+	if (!mode)
+		return NULL;
+
+	edid_vendor[0] = ((block[8] & 0x7c) >> 2) + '@';
+	edid_vendor[1] = (((block[8] & 0x3) << 3) |
+			  ((block[1] & 0xe0) >> 5)) + '@';
+	edid_vendor[2] = (block[9] & 0x1f) + '@';
+
+	mode->width_mm = block[21] * 100;
+	mode->height_mm = block[22] * 100;
+	HISI_FB_INFO("The product vender is %c%c%c !!!\n", edid_vendor[0],
+		     edid_vendor[1], edid_vendor[2]);
+	HISI_FB_INFO
+	    ("The screen supported max width is %d cm, max height is %d cm !!\n",
+	     block[21], block[22]);
+	HISI_FB_INFO("The display gamma is %d !!\n", block[23]);
+	HISI_FB_INFO("The display is RGB or YCbCr is 0x%x !!\n",
+		     (block[24] & 0x18) >> 3);
+	/******** Detailed Timing Descriptor **********/
+	mode->clock = (block[55] << 8 | block[54]) * 10;
+	mode->hdisplay = ((block[58] & 0xf0) << 4) | block[56];
+	hblank = ((block[58] & 0x0f) << 8) | block[57];
+	mode->vdisplay = ((block[61] & 0xf0) << 4) | block[59];
+	vblank = ((block[61] & 0x0f) << 8) | block[60];
+	mode->hsync_offset = block[62];
+	mode->hsync_pulse_width = block[63];
+	mode->vsync_offset = (block[64] & 0xf0) >> 4;
+	mode->vsync_pulse_width = block[64] & 0x0f;
+
+	mode->hsync_start = mode->hdisplay + mode->hsync_offset;
+	mode->hsync_end = mode->hsync_start + mode->hsync_pulse_width;
+	mode->htotal = mode->hdisplay + hblank;
+	mode->vsync_start = mode->vdisplay + mode->vsync_offset;
+	mode->vsync_end = mode->vsync_start + mode->vsync_pulse_width;
+	mode->vtotal = mode->vdisplay + vblank;
+
+	hsw = mode->hsync_pulse_width;
+	hfp = mode->hsync_offset;
+	hbp = mode->htotal - mode->hsync_end;
+	vsw = mode->vsync_pulse_width;
+	vfp = mode->vsync_offset;
+	vbp = mode->vtotal - mode->vsync_end;
+
+	HISI_FB_INFO("The pixel clock is %d!!\n", mode->clock);
+	HISI_FB_INFO("The resolution is %d x %d !!\n", mode->hdisplay,
+		     mode->vdisplay);
+	HISI_FB_INFO
+	    ("hsw = %d, hfp = %d, hbp = %d, vsw = %d, vfp= %d, vbp = %d\n",
+	     hsw, hfp, hbp, vsw, vfp, vbp);
+
+
+	return mode;
+}
+
+static int adv75xx_get_edid_block(void *data, u8 *buf, unsigned int block,
+				  size_t len)
+{
+	struct adi_hdmi *adv75xx = data;
+	struct i2c_msg xfer[2];
+	uint8_t offset, edid_buf[256];
+	unsigned int i;
+	int ret;
+
+	if (len > EDID_LENGTH)
+		return -EINVAL;
+
+	HISI_FB_INFO("+.\n");
+
+	if (adv75xx->current_edid_segment != block) {
+		unsigned int status;
+
+		ret = regmap_read(adv75xx->regmap, ADV7533_REG_DDC_STATUS,
+				  &status);
+		if (ret < 0)
+			return ret;
+
+		if (status != IDLE) {
+			adv75xx->edid_read = false;
+			regmap_write(adv75xx->regmap, ADV7533_REG_EDID_SEGMENT,
+				     block);
+			ret = adv75xx_wait_for_edid(adv75xx, 200);
+			if (ret < 0)
+				return ret;
+		}
+
+		/* Break this apart, hopefully more I2C controllers will
+		 * support 64 byte transfers than 256 byte transfers
+		 */
+
+		xfer[0].addr = adv75xx->i2c_edid->addr;
+		xfer[0].flags = 0;
+		xfer[0].len = 1;
+		xfer[0].buf = &offset;
+		xfer[1].addr = adv75xx->i2c_edid->addr;
+		xfer[1].flags = I2C_M_RD;
+		xfer[1].len = 64;
+		xfer[1].buf = edid_buf;
+
+		offset = 0;
+
+		for (i = 0; i < 4; ++i) {
+			ret = i2c_transfer(adv75xx->i2c_edid->adapter, xfer,
+					   ARRAY_SIZE(xfer));
+			if (ret < 0)
+				return ret;
+			else if (ret != 2)
+				return -EIO;
+
+			xfer[1].buf += 64;
+			offset += 64;
+		}
+
+		adv75xx->current_edid_segment = block;
+	}
+
+	if (block % 2 == 0)
+		memcpy(buf, edid_buf, len);
+	else
+		memcpy(buf, edid_buf + EDID_LENGTH, len);
+
+	HISI_FB_INFO("-.\n");
+
+	return 0;
+}
+
+static bool edid_is_zero(const u8 *in_edid, int length)
+{
+	if (memchr_inv(in_edid, 0, length))
+		return false;
+
+	return true;
+}
+
+/**
+ * hisi_do_get_edid - get EDID data using a custom EDID block read function
+ * @get_edid_block: EDID block read function
+ * @data: private data passed to the block read function
+ *
+ * When the I2C adapter connected to the DDC bus is hidden behind a device that
+ * exposes a different interface to read EDID blocks this function can be used
+ * to get EDID data using a custom block read function.
+ *
+ * As in the general case the DDC bus is accessible by the kernel at the I2C
+ * level, drivers must make all reasonable efforts to expose it as an I2C
+ * adapter and use drm_get_edid() instead of abusing this function.
+ *
+ * Return: Pointer to valid EDID or NULL if we couldn't find any.
+ */
+struct edid *hisi_do_get_edid(int (*get_edid_block) (void *data, u8 *buf,
+						     unsigned int block,
+						     size_t len), void *data)
+{
+	u8 *block;
+	bool print_bad_edid = true;
+
+	HISI_FB_INFO("+.\n");
+
+	if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
+		return NULL;
+
+	HISI_FB_INFO("EDID_LENGTH = %d \n", EDID_LENGTH);
+	/* base block fetch */
+	if (get_edid_block(data, block, 0, EDID_LENGTH))
+		goto out;
+
+	if (edid_is_zero(block, EDID_LENGTH))
+		goto carp;
+
+	HISI_FB_INFO("edid_block read success!!!\n");
+
+	print_edid_info(block);
+
+	return (struct edid *)block;
+
+ carp:
+	if (print_bad_edid)
+		HISI_FB_ERR("EDID block invalid.\n");
+ out:
+	kfree(block);
+	return NULL;
+}
+
+struct hisi_display_mode *adv75xx_get_modes(struct adi_hdmi *adv75xx)
+{
+	struct edid *edid;
+	struct hisi_display_mode *mode;
+
+	HISI_FB_INFO("+.\n");
+
+	/* Reading the EDID only works if the device is powered */
+	if (!adv75xx->powered) {
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_POWER2,
+				ADV7533_REG_POWER2_HDP_SRC_MASK,
+				ADV7533_REG_POWER2_HDP_SRC_NONE);	/* 0xc0 */
+
+		regmap_write(adv75xx->regmap, ADV7533_REG_INT(0),
+				ADV7533_INT0_EDID_READY);
+		regmap_write(adv75xx->regmap, ADV7533_REG_INT(1),
+				ADV7533_INT1_DDC_ERROR);
+
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_POWER,
+				ADV7533_POWER_POWER_DOWN, 0);	/* 0x41 0x10 */
+
+		adv75xx->current_edid_segment = -1;
+		/* wait some time for edid is ready */
+		msleep(200);
+	}
+
+	edid = hisi_do_get_edid(adv75xx_get_edid_block, adv75xx);
+
+	if (!adv75xx->powered)
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_POWER,
+				   ADV7533_POWER_POWER_DOWN,
+				   ADV7533_POWER_POWER_DOWN);
+
+	kfree(adv75xx->edid);
+	adv75xx->edid = edid;
+	if (!edid) {
+		HISI_FB_ERR("Fail to get really edid info !!!\n");
+		mode = hisi_set_mode_info();
+		return mode;
+	}
+
+	mode = hisi_parse_edid_base_info((u8 *) adv75xx->edid);
+
+	adv75xx_set_config_csc(adv75xx, adv75xx->rgb);
+
+	HISI_FB_INFO("-.\n");
+
+	return mode;
+}
+
+/*==========================================================*/
+static enum connector_status adv75xx_detect(struct adi_hdmi *adv75xx)
+{
+	enum connector_status status;
+	unsigned int val;
+#if HPD_ENABLE
+	bool hpd;
+#endif
+	int ret;
+
+	HISI_FB_INFO("+.\n");
+
+	ret = regmap_read(adv75xx->regmap, ADV7533_REG_STATUS, &val);
+	if (ret < 0) {
+		HISI_FB_INFO("HDMI connector status is disconnected !!!\n");
+		return connector_status_disconnected;
+	}
+
+	if (val & ADV7533_STATUS_HPD)
+		status = connector_status_connected;
+	else
+		status = connector_status_disconnected;
+
+#if HPD_ENABLE
+	hpd = adv75xx_hpd(adv75xx);
+
+	/* The chip resets itself when the cable is disconnected, so in case
+	 * there is a pending HPD interrupt and the cable is connected there was
+	 * at least one transition from disconnected to connected and the chip
+	 * has to be reinitialized. */
+	if (status == connector_status_connected && hpd && adv75xx->powered) {
+		regcache_mark_dirty(adv75xx->regmap);
+		adv75xx_power_on(adv75xx);
+		adv75xx_get_modes(adv75xx);
+		if (adv75xx->status == connector_status_connected)
+			status = connector_status_disconnected;
+	} else {
+		/* Renable HDP sensing */
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_POWER2,
+				   ADV7533_REG_POWER2_HDP_SRC_MASK,
+				   ADV7533_REG_POWER2_HDP_SRC_BOTH);
+	}
+#endif
+
+	adv75xx->status = status;
+
+	HISI_FB_INFO("adv7511->status = %d <1-connected,2-disconnected>\n",
+		     status);
+	HISI_FB_INFO("-.\n");
+
+	return status;
+}
+
+/**
+ * mode_vrefresh - get the vrefresh of a mode
+ * @mode: mode
+ *
+ * Returns:
+ * @modes's vrefresh rate in Hz, rounded to the nearest integer. Calculates the
+ * value first if it is not yet set.
+ */
+static int mode_vrefresh(const struct hisi_display_mode *mode)
+{
+	int refresh = 0;
+	unsigned int calc_val;
+
+	if (mode->vrefresh > 0)
+		refresh = mode->vrefresh;
+	else if (mode->htotal > 0 && mode->vtotal > 0) {
+		int vtotal;
+		vtotal = mode->vtotal;
+		/* work out vrefresh the value will be x1000 */
+		calc_val = (mode->clock * 1000);
+		calc_val /= mode->htotal;
+		refresh = (calc_val + vtotal / 2) / vtotal;
+	}
+	return refresh;
+}
+
+static int adv75xx_mode_valid(struct hisi_display_mode *mode)
+{
+	if (NULL == mode) {
+		HISI_FB_ERR("mode is null\n");
+		return MODE_NOMODE;
+	}
+
+	if (mode->clock > 165000)
+		return MODE_CLOCK_HIGH;
+	/*
+	 * some work well modes which want to put in the front of the mode list.
+	 */
+	HISI_FB_INFO("Checking mode %ix%i@%i clock: %i...",
+		     mode->hdisplay, mode->vdisplay, mode_vrefresh(mode),
+		     mode->clock);
+	if ((mode->hdisplay == 1920 && mode->vdisplay == 1080
+	     	&& mode->clock == 148500)
+		|| (mode->hdisplay == 1280 && mode->vdisplay == 800
+			&& mode->clock == 83496)
+		|| (mode->hdisplay == 1280 && mode->vdisplay == 720
+			&& mode->clock == 74440)
+		|| (mode->hdisplay == 1280 && mode->vdisplay == 720
+			&& mode->clock == 74250)
+	    || (mode->hdisplay == 1024 && mode->vdisplay == 768
+			&& mode->clock == 75000)
+		|| (mode->hdisplay == 1024 && mode->vdisplay == 768
+			&& mode->clock == 81833)
+	    || (mode->hdisplay == 800 && mode->vdisplay == 600
+			&& mode->clock == 40000)) {
+		HISI_FB_INFO("OK\n");
+		return MODE_OK;
+	}
+	HISI_FB_INFO("BAD\n");
+
+	return MODE_BAD;
+}
+
+static void adv75xx_mode_set(struct adi_hdmi *adv75xx,
+			     struct hisi_display_mode *mode)
+{
+	unsigned int low_refresh_rate;
+	unsigned int hsync_polarity = 0;
+	unsigned int vsync_polarity = 0;
+
+	HISI_FB_INFO("+.\n");
+
+	if (adv75xx->embedded_sync) {
+		unsigned int hsync_offset, hsync_len;
+		unsigned int vsync_offset, vsync_len;
+
+		hsync_offset = mode->hsync_offset;
+		vsync_offset = mode->vsync_offset;
+		hsync_len = mode->hsync_end - mode->hsync_start;
+		vsync_len = mode->vsync_end - mode->vsync_start;
+
+		/* The hardware vsync generator has a off-by-one bug */
+		vsync_offset += 1;
+
+		regmap_write(adv75xx->regmap, ADV7533_REG_HSYNC_PLACEMENT_MSB,
+			     ((hsync_offset >> 10) & 0x7) << 5);
+		regmap_write(adv75xx->regmap, ADV7533_REG_SYNC_DECODER(0),
+			     (hsync_offset >> 2) & 0xff);
+		regmap_write(adv75xx->regmap, ADV7533_REG_SYNC_DECODER(1),
+			     ((hsync_offset & 0x3) << 6) |
+			     ((hsync_len >> 4) & 0x3f));
+		regmap_write(adv75xx->regmap, ADV7533_REG_SYNC_DECODER(2),
+			     ((hsync_len & 0xf) << 4) |
+			     ((vsync_offset >> 6) & 0xf));
+		regmap_write(adv75xx->regmap, ADV7533_REG_SYNC_DECODER(3),
+			     ((vsync_offset & 0x3f) << 2) |
+			     ((vsync_len >> 8) & 0x3));
+		regmap_write(adv75xx->regmap, ADV7533_REG_SYNC_DECODER(4),
+			     vsync_len & 0xff);
+
+		hsync_polarity = !(mode->flags & MODE_FLAG_PHSYNC);
+		vsync_polarity = !(mode->flags & MODE_FLAG_PVSYNC);
+	} else {
+		/**
+		 * If the input signal is always low or always high we want to
+		 * invert or let it passthrough depending on the polarity of the
+		 * current mode.
+		 **/
+		adv75xx->hsync_polarity = ADV7533_SYNC_POLARITY_PASSTHROUGH;
+		adv75xx->vsync_polarity = ADV7533_SYNC_POLARITY_PASSTHROUGH;
+
+		hsync_polarity = adv75xx->hsync_polarity;
+		vsync_polarity = adv75xx->vsync_polarity;
+	}
+	mode->vrefresh = mode_vrefresh(mode);
+	HISI_FB_INFO("hsync_polarity = %d; vsync_polarity = %d\n",
+		     hsync_polarity, vsync_polarity);
+	HISI_FB_INFO("mode->vrefresh = %d \n", mode->vrefresh);
+
+	if (mode->vrefresh <= 24000)
+		low_refresh_rate = ADV7533_LOW_REFRESH_RATE_24HZ;
+	else if (mode->vrefresh <= 25000)
+		low_refresh_rate = ADV7533_LOW_REFRESH_RATE_25HZ;
+	else if (mode->vrefresh <= 30000)
+		low_refresh_rate = ADV7533_LOW_REFRESH_RATE_30HZ;
+	else
+		low_refresh_rate = ADV7533_LOW_REFRESH_RATE_NONE;
+
+	HISI_FB_INFO("low_refresh_rate = %d \n", low_refresh_rate);
+
+	regmap_update_bits(adv75xx->regmap, 0xfb, 0x6, low_refresh_rate << 1);
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_SYNC_POLARITY,
+			   0x60, (vsync_polarity << 6) | (hsync_polarity << 5));
+
+	/*
+	 * TODO Test first order 4:2:2 to 4:4:4 up conversion method, which is
+	 * supposed to give better results.
+	 */
+
+	adv75xx->f_tmds = mode->clock;
+
+	HISI_FB_INFO("-.\n");
+}
+
+static void adv75xx_power_on(struct adi_hdmi *adv75xx)
+{
+	HISI_FB_INFO("+.\n");
+
+	adv75xx->current_edid_segment = -1;
+
+	regmap_write(adv75xx->regmap, ADV7533_REG_INT(0),
+		     ADV7533_INT0_EDID_READY);
+	regmap_write(adv75xx->regmap, ADV7533_REG_INT(1),
+		     ADV7533_INT1_DDC_ERROR);
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_POWER,
+			   ADV7533_POWER_POWER_DOWN, 0);
+
+	/*
+	 * Per spec it is allowed to pulse the HDP signal to indicate that the
+	 * EDID information has changed. Some monitors do this when they wakeup
+	 * from standby or are enabled. When the HDP goes low the adv7511 is
+	 * reset and the outputs are disabled which might cause the monitor to
+	 * go to standby again. To avoid this we ignore the HDP pin for the
+	 * first few seconds after enabling the output.
+	 */
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_POWER2,
+			   ADV7533_REG_POWER2_HDP_SRC_MASK,
+			   ADV7533_REG_POWER2_HDP_SRC_NONE);
+
+	/*
+	 * Most of the registers are reset during power down or when HPD is low.
+	 */
+	regcache_sync(adv75xx->regmap);
+
+	regmap_register_patch(adv75xx->regmap_cec,
+			      adv7533_cec_fixed_registers,
+			      ARRAY_SIZE(adv7533_cec_fixed_registers));
+	adv75xx->powered = true;
+
+	adv75xx_dsi_receiver_dpms(adv75xx);
+
+	HISI_FB_INFO("-.\n");
+}
+
+static void adv75xx_power_off(struct adi_hdmi *adv75xx)
+{
+	HISI_FB_INFO("+.\n");
+
+	/* TODO: setup additional power down modes */
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_POWER,
+			   ADV7533_POWER_POWER_DOWN,
+			   ADV7533_POWER_POWER_DOWN);
+	regcache_mark_dirty(adv75xx->regmap);
+
+	adv75xx->powered = false;
+
+	adv75xx_dsi_receiver_dpms(adv75xx);
+
+	HISI_FB_INFO("-.\n");
+}
+
+/* =========================================================*/
+static int adv7533_init_regulators(struct adi_hdmi *adv75xx)
+{
+	int ret;
+	struct device *dev = &adv75xx->i2c_main->dev;
+
+	adv75xx->vdd = devm_regulator_get(dev, "vdd");
+	if (IS_ERR(adv75xx->vdd)) {
+		ret = PTR_ERR(adv75xx->vdd);
+		dev_err(dev, "failed to get vdd regulator %d\n", ret);
+		return ret;
+	}
+
+	adv75xx->v1p2 = devm_regulator_get(dev, "v1p2");
+	if (IS_ERR(adv75xx->v1p2)) {
+		ret = PTR_ERR(adv75xx->v1p2);
+		dev_err(dev, "failed to get v1p2 regulator %d\n", ret);
+		return ret;
+	}
+
+	ret = regulator_set_voltage(adv75xx->vdd, 1800000, 1800000);
+	if (ret) {
+		dev_err(dev, "failed to set avdd voltage %d\n", ret);
+		return ret;
+	}
+
+	ret = regulator_set_voltage(adv75xx->v1p2, 1200000, 1200000);
+	if (ret) {
+		dev_err(dev, "failed to set v1p2 voltage %d\n", ret);
+		return ret;
+	}
+
+	/* keep the regulators always on */
+	ret = regulator_enable(adv75xx->vdd);
+	if (ret) {
+		dev_err(dev, "failed to enable vdd %d\n", ret);
+		return ret;
+	}
+
+	ret = regulator_enable(adv75xx->v1p2);
+	if (ret) {
+		dev_err(dev, "failed to enable v1p2 %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int adv7533_parse_dt(struct device_node *np, struct adi_hdmi *adv75xx)
+{
+	int ret;
+	u32 num_lanes;
+
+	ret = of_property_read_u32(np, "adi,dsi-lanes", &num_lanes);
+	if (ret) {
+		HISI_FB_WARNING("get 'adi,dsi-lanes' resource failed!\n");
+		return ret;
+	}
+
+	if (num_lanes < 1 || num_lanes > 4)
+		return -EINVAL;
+
+	adv75xx->num_dsi_lanes = num_lanes;
+
+	/* TODO: Check if these need to be parsed by DT or not */
+	adv75xx->rgb = true;
+	adv75xx->embedded_sync = false;
+
+	return 0;
+}
+
+static const int edid_i2c_addr = 0x7e;
+static const int packet_i2c_addr = 0x70;
+static const int cec_i2c_addr = 0x78;
+
+static const struct of_device_id adv75xx_of_ids[] = {
+	{.compatible = "adi,adv7511", .data = (void *)ADV7511},
+	{.compatible = "adi,adv7511w", .data = (void *)ADV7511},
+	{.compatible = "adi,adv7513", .data = (void *)ADV7511},
+	{.compatible = "adi,adv7533", .data = (void *)ADV7533},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, adv75xx_of_ids);
+
+static const struct i2c_device_id adv75xx_i2c_ids[] = {
+	{"adv7511", ADV7511},
+	{"adv7511w", ADV7511},
+	{"adv7513", ADV7511},
+	{"adv7533", ADV7533},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, adv75xx_i2c_ids);
+
+static struct adi_operation_funcs opt_funcs = {
+	.power_on = adv75xx_power_on,
+	.power_off = adv75xx_power_off,
+	.mode_set = adv75xx_mode_set,
+};
+
+static int adv75xx_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+{
+	struct adi_hdmi *adv75xx;
+	struct device *dev = &i2c->dev;
+	enum connector_status status;
+	struct hisi_display_mode *mode;
+	struct platform_device *hdmi_pdev = NULL;
+	unsigned int val;
+	int ret;
+
+	if (!dev) {
+		HISI_FB_ERR("dev is  NULL!\n");
+		return -ENOMEM;
+	}
+
+	adv75xx = devm_kzalloc(dev, sizeof(struct adi_hdmi), GFP_KERNEL);
+	if (!adv75xx) {
+		HISI_FB_ERR("adv75xx alloc  failed!\n");
+		return -ENOMEM;
+	}
+	adv75xx->powered = false;
+	adv75xx->status = connector_status_disconnected;
+
+	if (dev->of_node) {
+		const struct of_device_id *of_id;
+
+		of_id = of_match_node(adv75xx_of_ids, dev->of_node);
+		adv75xx->type = (enum adv75xx_type)of_id->data;
+	} else {
+		adv75xx->type = ADV7533;
+	}
+
+	ret = adv7533_parse_dt(dev->of_node, adv75xx);
+	if (ret) {
+		HISI_FB_ERR("parse dts error!\n");
+		goto err_return;
+	}
+
+	adv75xx->i2c_main = i2c;
+
+	if (adv75xx->type == ADV7533) {
+		ret = adv7533_init_regulators(adv75xx);	/* adv7533 vdd--1.8v  v1p2--1.2v */
+		if (ret)
+			return ret;
+	}
+
+	/*
+	 * The power down GPIO is optional. If present, toggle it from active(1) to
+	 * inactive(0) to wake up the encoder.
+	 */
+	adv75xx->gpio_pd = devm_gpiod_get_optional(dev, "pd", GPIOD_OUT_HIGH);
+	if (IS_ERR(adv75xx->gpio_pd)) {
+		HISI_FB_ERR("get gpio pd error!\n");
+		return PTR_ERR(adv75xx->gpio_pd);
+	}
+	HISI_FB_INFO("adv75xx->gpio_pd = %s!\n", adv75xx->gpio_pd->label);
+
+	if (adv75xx->gpio_pd) {
+		mdelay(5);
+		gpiod_set_value_cansleep(adv75xx->gpio_pd, 0);
+	}
+
+	adv75xx->regmap = devm_regmap_init_i2c(i2c, &adv75xx_regmap_config);
+	if (IS_ERR(adv75xx->regmap)) {
+		HISI_FB_ERR("regmap init i2c failed!\n");
+		return PTR_ERR(adv75xx->regmap);
+	}
+
+	ret = regmap_read(adv75xx->regmap, ADV7533_REG_CHIP_REVISION, &val);
+	if (ret) {
+		HISI_FB_ERR("regmap read failed, ret = %d!\n", ret);
+		goto err_return;
+	}
+	/* the corect val is 20. */
+	HISI_FB_INFO("%s of the Chip reversion is %d\n", dev_name(dev), val);
+	dev_err(dev, "Rev. %d\n", val);
+
+	ret = regmap_register_patch(adv75xx->regmap,
+				    adv7533_fixed_registers,
+				    ARRAY_SIZE(adv7533_fixed_registers));
+	if (ret) {
+		HISI_FB_ERR("regmap register failed!\n");
+		goto err_return;
+	}
+
+	regmap_write(adv75xx->regmap, ADV7533_REG_EDID_I2C_ADDR, edid_i2c_addr);
+	regmap_write(adv75xx->regmap, ADV7533_REG_PACKET_I2C_ADDR,
+		     packet_i2c_addr);
+	regmap_write(adv75xx->regmap, ADV7533_REG_CEC_I2C_ADDR, cec_i2c_addr);
+	adv75xx_packet_disable(adv75xx, 0xffff);
+
+	adv75xx->i2c_packet = i2c_new_dummy(i2c->adapter, packet_i2c_addr >> 1);
+	if (!adv75xx->i2c_packet) {
+		HISI_FB_ERR("i2c_new_dummy i2c_packet failed!\n");
+		return -ENOMEM;
+	}
+
+	adv75xx->i2c_edid = i2c_new_dummy(i2c->adapter, edid_i2c_addr >> 1);
+	if (!adv75xx->i2c_edid) {
+		HISI_FB_ERR("i2c_new_dummy i2c_edid failed!\n");
+		goto err_i2c_unregister_packet;
+	}
+
+	adv75xx->i2c_cec = i2c_new_dummy(i2c->adapter, cec_i2c_addr >> 1);
+	if (!adv75xx->i2c_cec) {
+		ret = -ENOMEM;
+		HISI_FB_ERR("i2c_new_dummy i2c_cec failed!\n");
+		goto err_i2c_unregister_edid;
+	}
+
+	adv75xx->regmap_cec = devm_regmap_init_i2c(adv75xx->i2c_cec,
+						   &adv7533_cec_regmap_config);
+	if (IS_ERR(adv75xx->regmap_cec)) {
+		ret = PTR_ERR(adv75xx->regmap_cec);
+		HISI_FB_ERR("devm_regmap_init_i2c regmap_cec failed!\n");
+		goto err_i2c_unregister_cec;
+	}
+
+	adv75xx->regmap_packet = devm_regmap_init_i2c(adv75xx->i2c_packet,
+						      &adv7533_packet_regmap_config);
+	if (IS_ERR(adv75xx->regmap_packet)) {
+		ret = PTR_ERR(adv75xx->regmap_packet);
+		HISI_FB_ERR("devm_regmap_init_i2c regmap_packet failed!\n");
+		goto err_i2c_unregister_cec;
+	}
+
+	if (adv75xx->type == ADV7533) {
+		ret = regmap_register_patch(adv75xx->regmap_cec,
+					    adv7533_cec_fixed_registers,
+					    ARRAY_SIZE(adv7533_cec_fixed_registers));
+		if (ret) {
+			HISI_FB_ERR
+			    ("regmap_register_patch cec_fixed_registers failed!\n");
+			goto err_return;
+		}
+	}
+
+	HISI_FB_INFO("i2c->irq = %d!\n", i2c->irq);
+	if (i2c->irq) {
+		init_waitqueue_head(&adv75xx->wq);
+		ret = devm_request_threaded_irq(dev, i2c->irq, NULL,
+						adv75xx_irq_handler,
+						IRQF_ONESHOT, dev_name(dev), adv75xx);
+		if (ret) {
+			HISI_FB_ERR("adv7511_irq_handler registers failed!\n");
+			goto err_i2c_unregister_cec;
+		}
+	}
+
+	/* CEC is unused for now */
+	regmap_write(adv75xx->regmap, ADV7533_REG_CEC_CTRL,
+		     ADV7533_CEC_CTRL_POWER_DOWN);
+
+	adv75xx_power_off(adv75xx);
+
+	i2c_set_clientdata(i2c, adv75xx);
+
+	/* adv7511_audio_init(dev); */
+	status = adv75xx_detect(adv75xx);
+	if (status != connector_status_connected) {
+		HISI_FB_ERR("adv75xx connector not connected !\n");
+	}
+
+	mode = adv75xx_get_modes(adv75xx);
+
+	ret = adv75xx_mode_valid(mode);
+	if (ret) {
+		HISI_FB_ERR("adv75xx not supported this mode !!\n");
+		kfree(mode);
+		mode = hisi_set_mode_info();
+	}
+	adv75xx->mode = mode;
+	adv75xx->opt_funcs = &opt_funcs;
+
+	hdmi_pdev =
+	    platform_device_alloc("adi_hdmi",
+				  (((uint32_t) PANEL_MIPI_VIDEO << 16) |
+				    (uint32_t) 1));
+	if (hdmi_pdev) {
+		if (platform_device_add_data
+		    (hdmi_pdev, adv75xx, sizeof(struct adi_hdmi))) {
+			HISI_FB_ERR("failed to platform_device_add_data!\n");
+			platform_device_put(hdmi_pdev);
+		}
+	}
+	HISI_FB_INFO("platform_device_add_data ok !\n");
+
+	/* set driver data */
+	platform_set_drvdata(hdmi_pdev, adv75xx);
+	if (platform_device_add(hdmi_pdev)) {
+		HISI_FB_ERR("platform_device_add failed!\n");
+		goto err_device_put;
+	}
+
+	return 0;
+
+ err_i2c_unregister_cec:
+	i2c_unregister_device(adv75xx->i2c_cec);
+ err_i2c_unregister_edid:
+	i2c_unregister_device(adv75xx->i2c_edid);
+ err_i2c_unregister_packet:
+	i2c_unregister_device(adv75xx->i2c_packet);
+ err_device_put:
+	platform_device_put(hdmi_pdev);
+ err_return:
+	kfree(adv75xx);
+	return ret;
+}
+
+static int adv75xx_remove(struct i2c_client *i2c)
+{
+	struct adi_hdmi *adv75xx = i2c_get_clientdata(i2c);
+
+	i2c_unregister_device(adv75xx->i2c_cec);
+	i2c_unregister_device(adv75xx->i2c_edid);
+
+	kfree(adv75xx->edid);
+	kfree(adv75xx->mode);
+	kfree(adv75xx);
+
+	return 0;
+}
+
+static struct i2c_driver adv75xx_driver = {
+	.driver = {
+		   .owner = THIS_MODULE,
+		   .name = "adv75xx",
+		   .of_match_table = adv75xx_of_ids,
+		   },
+	.id_table = adv75xx_i2c_ids,
+	.probe = adv75xx_probe,
+	.remove = adv75xx_remove,
+};
+
+static int __init adv75xx_init(void)
+{
+	int ret = 0;
+
+	ret = i2c_add_driver(&adv75xx_driver);
+	if (ret) {
+		HISI_FB_ERR("i2c_add_driver error!\n");
+	}
+	return ret;
+}
+
+module_init(adv75xx_init);
+
+static void __exit adv75xx_exit(void)
+{
+	i2c_del_driver(&adv75xx_driver);
+}
+
+module_exit(adv75xx_exit);
+
+MODULE_AUTHOR("Hisilicon Inc");
+MODULE_DESCRIPTION("ADV75XX HDMI transmitter driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/hisi/dss/hdmi/adv75xx.h b/drivers/video/fbdev/hisi/dss/hdmi/adv75xx.h
new file mode 100755
index 000000000000..d2f84d846271
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hdmi/adv75xx.h
@@ -0,0 +1,496 @@
+/**
+ *
+ *
+ **/
+
+#ifndef __ADV75XX_H__
+#define __ADV75XX_H__
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/hdmi.h>
+
+#include "../hisi_fb.h"
+
+#define DISPLAY_MODE_LEN	32
+
+#define ADV7533_REG_CHIP_REVISION		0x00
+#define ADV7533_REG_N0					0x01
+#define ADV7533_REG_N1					0x02
+#define ADV7533_REG_N2					0x03
+#define ADV7533_REG_SPDIF_FREQ			0x04
+#define ADV7533_REG_CTS_AUTOMATIC1		0x05
+#define ADV7533_REG_CTS_AUTOMATIC2		0x06
+#define ADV7533_REG_CTS_MANUAL0			0x07
+#define ADV7533_REG_CTS_MANUAL1			0x08
+#define ADV7533_REG_CTS_MANUAL2			0x09
+#define ADV7533_REG_AUDIO_SOURCE		0x0a
+#define ADV7533_REG_AUDIO_CONFIG		0x0b
+#define ADV7533_REG_I2S_CONFIG			0x0c
+#define ADV7533_REG_I2S_WIDTH			0x0d
+#define ADV7533_REG_AUDIO_SUB_SRC0		0x0e
+#define ADV7533_REG_AUDIO_SUB_SRC1		0x0f
+#define ADV7533_REG_AUDIO_SUB_SRC2		0x10
+#define ADV7533_REG_AUDIO_SUB_SRC3		0x11
+#define ADV7533_REG_AUDIO_CFG1			0x12
+#define ADV7533_REG_AUDIO_CFG2			0x13
+#define ADV7533_REG_AUDIO_CFG3			0x14
+#define ADV7533_REG_I2C_FREQ_ID_CFG		0x15
+#define ADV7533_REG_VIDEO_INPUT_CFG1		0x16
+#define ADV7533_REG_CEC_PIXEL_CLOCK_DIV		0x16
+#define ADV7533_REG_SYNC_POLARITY		0x17
+#define ADV7533_REG_DSI_DATA_LANES		0x1c
+#define ADV7533_REG_CSC_UPPER(x)		(0x18 + (x) * 2)
+#define ADV7533_REG_CSC_LOWER(x)		(0x19 + (x) * 2)
+#define ADV7533_REG_SYNC_DECODER(x)		(0x30 + (x))
+#define ADV7533_REG_DE_GENERATOR		(0x35 + (x))
+#define ADV7533_REG_PIXEL_REPETITION		0x3b
+#define ADV7533_REG_VIC_MANUAL			0x3c
+#define ADV7533_REG_VIC_SEND			0x3d
+#define ADV7533_REG_VIC_DETECTED		0x3e
+#define ADV7533_REG_AUX_VIC_DETECTED		0x3f
+#define ADV7533_REG_PACKET_ENABLE0		0x40
+#define ADV7533_REG_POWER			0x41
+#define ADV7533_REG_STATUS			0x42
+#define ADV7533_REG_EDID_I2C_ADDR		0x43
+#define ADV7533_REG_PACKET_ENABLE1		0x44
+#define ADV7533_REG_PACKET_I2C_ADDR		0x45
+#define ADV7533_REG_DSD_ENABLE			0x46
+#define ADV7533_REG_VIDEO_INPUT_CFG2		0x48
+#define ADV7533_REG_INFOFRAME_UPDATE		0x4a
+#define ADV7533_REG_GC(x)			(0x4b + (x))	/* 0x4b - 0x51 */
+#define ADV7533_REG_AVI_INFOFRAME_VERSION	0x52
+#define ADV7533_REG_AVI_INFOFRAME_LENGTH	0x53
+#define ADV7533_REG_AVI_INFOFRAME_CHECKSUM	0x54
+#define ADV7533_REG_AVI_INFOFRAME(x)		(0x55 + (x))	/* 0x55 - 0x6f */
+#define ADV7533_REG_AUDIO_INFOFRAME_VERSION	0x70
+#define ADV7533_REG_AUDIO_INFOFRAME_LENGTH	0x71
+#define ADV7533_REG_AUDIO_INFOFRAME_CHECKSUM	0x72
+#define ADV7533_REG_AUDIO_INFOFRAME(x)		(0x73 + (x))	/* 0x73 - 0x7c */
+#define ADV7533_REG_INT_ENABLE(x)		(0x94 + (x))
+#define ADV7533_REG_INT(x)			(0x96 + (x))
+#define ADV7533_REG_INPUT_CLK_DIV		0x9d
+#define ADV7533_REG_PLL_STATUS			0x9e
+#define ADV7533_REG_HDMI_POWER			0xa1
+#define ADV7533_REG_HDCP_HDMI_CFG		0xaf
+#define ADV7533_REG_AN(x)			(0xb0 + (x))	/* 0xb0 - 0xb7 */
+#define ADV7533_REG_HDCP_STATUS			0xb8
+#define ADV7533_REG_BCAPS			0xbe
+#define ADV7533_REG_BKSV(x)			(0xc0 + (x))	/* 0xc0 - 0xc3 */
+#define ADV7533_REG_EDID_SEGMENT		0xc4
+#define ADV7533_REG_DDC_STATUS			0xc8
+#define ADV7533_REG_EDID_READ_CTRL		0xc9
+#define ADV7533_REG_BSTATUS(x)			(0xca + (x))	/* 0xca - 0xcb */
+#define ADV7533_REG_TIMING_GEN_SEQ		0xd0
+#define ADV7533_REG_POWER2			0xd6
+#define ADV7533_REG_HSYNC_PLACEMENT_MSB		0xfa
+
+#define ADV7533_REG_SYNC_ADJUSTMENT(x)		(0xd7 + (x))	/* 0xd7 - 0xdc */
+#define ADV7533_REG_TMDS_CLOCK_INV		0xde
+#define ADV7533_REG_ARC_CTRL			0xdf
+#define ADV7533_REG_CEC_I2C_ADDR		0xe1
+#define ADV7533_REG_CEC_CTRL			0xe2
+#define ADV7533_REG_CHIP_ID_HIGH		0xf5
+#define ADV7533_REG_CHIP_ID_LOW			0xf6
+
+#define ADV7533_CSC_ENABLE			BIT(7)
+#define ADV7533_CSC_UPDATE_MODE			BIT(5)
+
+#define ADV7533_INT0_HDP			BIT(7)
+#define ADV7533_INT0_VSYNC			BIT(5)
+#define ADV7533_INT0_AUDIO_FIFO_FULL		BIT(4)
+#define ADV7533_INT0_EDID_READY			BIT(2)
+#define ADV7533_INT0_HDCP_AUTHENTICATED		BIT(1)
+
+#define ADV7533_INT1_DDC_ERROR			BIT(7)
+#define ADV7533_INT1_BKSV			BIT(6)
+#define ADV7533_INT1_CEC_TX_READY		BIT(5)
+#define ADV7533_INT1_CEC_TX_ARBIT_LOST		BIT(4)
+#define ADV7533_INT1_CEC_TX_RETRY_TIMEOUT	BIT(3)
+#define ADV7533_INT1_CEC_RX_READY3		BIT(2)
+#define ADV7533_INT1_CEC_RX_READY2		BIT(1)
+#define ADV7533_INT1_CEC_RX_READY1		BIT(0)
+
+#define ADV7533_ARC_CTRL_POWER_DOWN		BIT(0)
+
+#define ADV7533_CEC_CTRL_POWER_DOWN		BIT(0)
+
+#define ADV7533_POWER_POWER_DOWN		BIT(6)
+
+#define ADV7533_HDMI_CFG_MODE_MASK		0x2
+#define ADV7533_HDMI_CFG_MODE_DVI		0x0
+#define ADV7533_HDMI_CFG_MODE_HDMI		0x2
+
+#define ADV7533_AUDIO_SELECT_I2C		0x0
+#define ADV7533_AUDIO_SELECT_SPDIF		0x1
+#define ADV7533_AUDIO_SELECT_DSD		0x2
+#define ADV7533_AUDIO_SELECT_HBR		0x3
+#define ADV7533_AUDIO_SELECT_DST		0x4
+
+#define ADV7533_I2S_SAMPLE_LEN_16		0x2
+#define ADV7533_I2S_SAMPLE_LEN_20		0x3
+#define ADV7533_I2S_SAMPLE_LEN_18		0x4
+#define ADV7533_I2S_SAMPLE_LEN_22		0x5
+#define ADV7533_I2S_SAMPLE_LEN_19		0x8
+#define ADV7533_I2S_SAMPLE_LEN_23		0x9
+#define ADV7533_I2S_SAMPLE_LEN_24		0xb
+#define ADV7533_I2S_SAMPLE_LEN_17		0xc
+#define ADV7533_I2S_SAMPLE_LEN_21		0xd
+
+#define ADV7533_SAMPLE_FREQ_44100		0x0
+#define ADV7533_SAMPLE_FREQ_48000		0x2
+#define ADV7533_SAMPLE_FREQ_32000		0x3
+#define ADV7533_SAMPLE_FREQ_88200		0x8
+#define ADV7533_SAMPLE_FREQ_96000		0xa
+#define ADV7533_SAMPLE_FREQ_176400		0xc
+#define ADV7533_SAMPLE_FREQ_192000		0xe
+
+#define ADV7533_STATUS_POWER_DOWN_POLARITY	BIT(7)
+#define ADV7533_STATUS_HPD			BIT(6)
+#define ADV7533_STATUS_MONITOR_SENSE		BIT(5)
+#define ADV7533_STATUS_I2S_32BIT_MODE		BIT(3)
+
+#define ADV7533_PACKET_ENABLE_N_CTS		BIT(8+6)
+#define ADV7533_PACKET_ENABLE_AUDIO_SAMPLE	BIT(8+5)
+#define ADV7533_PACKET_ENABLE_AVI_INFOFRAME	BIT(8+4)
+#define ADV7533_PACKET_ENABLE_AUDIO_INFOFRAME	BIT(8+3)
+#define ADV7533_PACKET_ENABLE_GC		BIT(7)
+#define ADV7533_PACKET_ENABLE_SPD		BIT(6)
+#define ADV7533_PACKET_ENABLE_MPEG		BIT(5)
+#define ADV7533_PACKET_ENABLE_ACP		BIT(4)
+#define ADV7533_PACKET_ENABLE_ISRC		BIT(3)
+#define ADV7533_PACKET_ENABLE_GM		BIT(2)
+#define ADV7533_PACKET_ENABLE_SPARE2		BIT(1)
+#define ADV7533_PACKET_ENABLE_SPARE1		BIT(0)
+
+#define ADV7533_REG_POWER2_HDP_SRC_MASK		0xc0
+#define ADV7533_REG_POWER2_HDP_SRC_BOTH		0x00
+#define ADV7533_REG_POWER2_HDP_SRC_HDP		0x40
+#define ADV7533_REG_POWER2_HDP_SRC_CEC		0x80
+#define ADV7533_REG_POWER2_HDP_SRC_NONE		0xc0
+#define ADV7533_REG_POWER2_TDMS_ENABLE		BIT(4)
+#define ADV7533_REG_POWER2_GATE_INPUT_CLK	BIT(0)
+
+#define ADV7533_LOW_REFRESH_RATE_NONE		0x0
+#define ADV7533_LOW_REFRESH_RATE_24HZ		0x1
+#define ADV7533_LOW_REFRESH_RATE_25HZ		0x2
+#define ADV7533_LOW_REFRESH_RATE_30HZ		0x3
+
+#define ADV7533_AUDIO_CFG3_LEN_MASK		0x0f
+#define ADV7533_I2C_FREQ_ID_CFG_RATE_MASK	0xf0
+
+#define ADV7533_AUDIO_SOURCE_I2S		0
+#define ADV7533_AUDIO_SOURCE_SPDIF		1
+
+#define ADV7533_I2S_FORMAT_I2S			0
+#define ADV7533_I2S_FORMAT_RIGHT_J		1
+#define ADV7533_I2S_FORMAT_LEFT_J		2
+
+#define ADV7533_PACKET(p, x)	    ((p) * 0x20 + (x))
+#define ADV7533_PACKET_SDP(x)	    ADV7533_PACKET(0, x)
+#define ADV7533_PACKET_MPEG(x)	    ADV7533_PACKET(1, x)
+#define ADV7533_PACKET_ACP(x)	    ADV7533_PACKET(2, x)
+#define ADV7533_PACKET_ISRC1(x)	    ADV7533_PACKET(3, x)
+#define ADV7533_PACKET_ISRC2(x)	    ADV7533_PACKET(4, x)
+#define ADV7533_PACKET_GM(x)	    ADV7533_PACKET(5, x)
+#define ADV7533_PACKET_SPARE(x)	    ADV7533_PACKET(6, x)
+
+#define EDID_LENGTH				0x80
+#define EDID_EXTENSION_NUM				0x7e
+
+/* Video mode flags */
+/* bit compatible with the xorg definitions. */
+#define MODE_FLAG_PHSYNC			(1<<0)
+#define MODE_FLAG_NHSYNC			(1<<1)
+#define MODE_FLAG_PVSYNC			(1<<2)
+#define MODE_FLAG_NVSYNC			(1<<3)
+#define MODE_FLAG_INTERLACE			(1<<4)
+#define MODE_FLAG_DBLSCAN			(1<<5)
+#define MODE_FLAG_CSYNC			(1<<6)
+#define MODE_FLAG_PCSYNC			(1<<7)
+#define MODE_FLAG_NCSYNC			(1<<8)
+#define MODE_FLAG_HSKEW			(1<<9)	/* hskew provided */
+#define MODE_FLAG_BCAST			(1<<10)
+#define MODE_FLAG_PIXMUX			(1<<11)
+#define MODE_FLAG_DBLCLK			(1<<12)
+#define MODE_FLAG_CLKDIV2			(1<<13)
+
+/*
+ * Note on terminology:  here, for brevity and convenience, we refer to connector
+ * control chips as 'CRTCs'.  They can control any type of connector, VGA, LVDS,
+ * DVI, etc.  And 'screen' refers to the whole of the visible display, which
+ * may span multiple monitors (and therefore multiple CRTC and connector
+ * structures).
+ */
+
+enum mode_status {
+	MODE_OK = 0,		/* Mode OK */
+	MODE_HSYNC,		/* hsync out of range */
+	MODE_VSYNC,		/* vsync out of range */
+	MODE_H_ILLEGAL,		/* mode has illegal horizontal timings */
+	MODE_V_ILLEGAL,		/* mode has illegal horizontal timings */
+	MODE_BAD_WIDTH,		/* requires an unsupported linepitch */
+	MODE_NOMODE,		/* no mode with a matching name */
+	MODE_NO_INTERLACE,	/* interlaced mode not supported */
+	MODE_NO_DBLESCAN,	/* doublescan mode not supported */
+	MODE_NO_VSCAN,		/* multiscan mode not supported */
+	MODE_MEM,		/* insufficient video memory */
+	MODE_VIRTUAL_X,		/* mode width too large for specified virtual size */
+	MODE_VIRTUAL_Y,		/* mode height too large for specified virtual size */
+	MODE_MEM_VIRT,		/* insufficient video memory given virtual size */
+	MODE_NOCLOCK,		/* no fixed clock available */
+	MODE_CLOCK_HIGH,	/* clock required is too high */
+	MODE_CLOCK_LOW,		/* clock required is too low */
+	MODE_CLOCK_RANGE,	/* clock/mode isn't in a ClockRange */
+	MODE_BAD_HVALUE,	/* horizontal timing was out of range */
+	MODE_BAD_VVALUE,	/* vertical timing was out of range */
+	MODE_BAD_VSCAN,		/* VScan value out of range */
+	MODE_HSYNC_NARROW,	/* horizontal sync too narrow */
+	MODE_HSYNC_WIDE,	/* horizontal sync too wide */
+	MODE_HBLANK_NARROW,	/* horizontal blanking too narrow */
+	MODE_HBLANK_WIDE,	/* horizontal blanking too wide */
+	MODE_VSYNC_NARROW,	/* vertical sync too narrow */
+	MODE_VSYNC_WIDE,	/* vertical sync too wide */
+	MODE_VBLANK_NARROW,	/* vertical blanking too narrow */
+	MODE_VBLANK_WIDE,	/* vertical blanking too wide */
+	MODE_PANEL,		/* exceeds panel dimensions */
+	MODE_INTERLACE_WIDTH,	/* width too large for interlaced mode */
+	MODE_ONE_WIDTH,		/* only one width is supported */
+	MODE_ONE_HEIGHT,	/* only one height is supported */
+	MODE_ONE_SIZE,		/* only one resolution is supported */
+	MODE_NO_REDUCED,	/* monitor doesn't accept reduced blanking */
+	MODE_NO_STEREO,		/* stereo modes not supported */
+	MODE_UNVERIFIED = -3,	/* mode needs to reverified */
+	MODE_BAD = -2,		/* unspecified reason */
+	MODE_ERROR = -1		/* error condition */
+};
+
+enum DDC_controller_status {
+	IN_RESET = 0,		/* In Reset (No Hot Plug Detected) */
+	READING_EDID,		/* Reading EDID */
+	IDLE,			/* IDLE (Waiting for HDCP Requested) */
+	INIT_HDCP,		/* Initializing HDCP */
+	HDCP_ENABLE,		/* HDCP Enabled */
+	INIT_HDCP_REPEAT	/* Initializing HDCP Repeater */
+};
+
+/* If detailed data is pixel timing */
+struct detailed_pixel_timing {
+	u8 hactive_lo;
+	u8 hblank_lo;
+	u8 hactive_hblank_hi;
+	u8 vactive_lo;
+	u8 vblank_lo;
+	u8 vactive_vblank_hi;
+	u8 hsync_offset_lo;
+	u8 hsync_pulse_width_lo;
+	u8 vsync_offset_pulse_width_lo;
+	u8 hsync_vsync_offset_pulse_width_hi;
+	u8 width_mm_lo;
+	u8 height_mm_lo;
+	u8 width_height_mm_hi;
+	u8 hborder;
+	u8 vborder;
+	u8 misc;
+} __attribute__ ((packed));
+
+struct est_timings {
+	u8 t1;
+	u8 t2;
+	u8 mfg_rsvd;
+} __attribute__ ((packed));
+
+struct std_timing {
+	u8 hsize;		/* need to multiply by 8 then add 248 */
+	u8 vfreq_aspect;
+} __attribute__ ((packed));
+
+struct detailed_timing {
+	__le16 pixel_clock;	/* need to multiply by 10 KHz */
+	union {
+		struct detailed_pixel_timing pixel_data;
+		/* struct detailed_non_pixel other_data;*/
+	} data;
+} __attribute__ ((packed));
+
+struct edid {
+	u8 header[8];
+	/* Vendor & product info */
+	u8 mfg_id[2];
+	u8 prod_code[2];
+	u32 serial;		/* FIXME: byte order */
+	u8 mfg_week;
+	u8 mfg_year;
+	/* EDID version */
+	u8 version;
+	u8 revision;
+	/* Display info: */
+	u8 input;
+	u8 width_cm;
+	u8 height_cm;
+	u8 gamma;
+	u8 features;
+	/* Color characteristics */
+	u8 red_green_lo;
+	u8 black_white_lo;
+	u8 red_x;
+	u8 red_y;
+	u8 green_x;
+	u8 green_y;
+	u8 blue_x;
+	u8 blue_y;
+	u8 white_x;
+	u8 white_y;
+	/* Est. timings and mfg rsvd timings */
+	struct est_timings established_timings;
+	/* Standard timings 1-8 */
+	struct std_timing standard_timings[8];
+	/* Detailing timings 1-4 */
+	struct detailed_timing detailed_timings[4];
+	/* Number of 128 byte ext. blocks */
+	u8 extensions;
+	/* Checksum */
+	u8 checksum;
+} __attribute__ ((packed));
+
+/**
+ * enum adv75xx_csc_scaling - Scaling factor for the ADV75xx CSC
+ * @ADV75xx_CSC_SCALING_1: CSC results are not scaled
+ * @ADV75xx_CSC_SCALING_2: CSC results are scaled by a factor of two
+ * @ADV75xx_CSC_SCALING_4: CSC results are scalled by a factor of four
+ */
+enum adv75xx_csc_scaling {
+	ADV75xx_CSC_SCALING_1 = 0,
+	ADV75xx_CSC_SCALING_2 = 1,
+	ADV75xx_CSC_SCALING_4 = 2,
+};
+
+/**
+ * struct adv75xx_video_config - Describes adv75xx hardware configuration
+ * @csc_enable:			Whether to enable color space conversion
+ * @csc_scaling_factor:		Color space conversion scaling factor
+ * @csc_coefficents:		Color space conversion coefficents
+ * @hdmi_mode:			Whether to use HDMI or DVI output mode
+ * @avi_infoframe:		HDMI infoframe
+ */
+struct adv75xx_video_config {
+	bool csc_enable;
+	enum adv75xx_csc_scaling csc_scaling_factor;
+	const uint16_t *csc_coefficents;
+
+	bool hdmi_mode;
+	struct hdmi_avi_infoframe avi_infoframe;
+};
+
+struct hisi_display_mode {
+
+	unsigned int type;
+
+	/* Proposed mode values */
+	int clock;		/* in kHz */
+	int hdisplay;
+	int hsync_start;
+	int hsync_end;
+	int hsync_pulse_width;
+	int hsync_offset;
+	int htotal;
+
+	int vdisplay;
+	int vsync_start;
+	int vsync_end;
+	int vsync_pulse_width;
+	int vsync_offset;
+	int vtotal;
+	int vscan;
+	unsigned int flags;
+
+	/* Addressable image size (may be 0 for projectors, etc.) */
+	int width_mm;
+	int height_mm;
+
+	int vrefresh;		/* in Hz */
+	int hsync;		/* in kHz */
+	enum hdmi_picture_aspect picture_aspect_ratio;
+};
+
+/**
+ * enum adv7511_sync_polarity - Polarity for the input sync signals
+ * @ADV7533_SYNC_POLARITY_PASSTHROUGH:  Sync polarity matches that of
+ *				       the currently configured mode.
+ * @ADV7533_SYNC_POLARITY_LOW:	    Sync polarity is low
+ * @ADV7533_SYNC_POLARITY_HIGH:	    Sync polarity is high
+ *
+ * If the polarity is set to either LOW or HIGH the driver will configure the
+ * ADV7533 to internally invert the sync signal if required to match the sync
+ * polarity setting for the currently selected output mode.
+ *
+ * If the polarity is set to PASSTHROUGH, the ADV7533 will route the signal
+ * unchanged. This is used when the upstream graphics core already generates
+ * the sync signals with the correct polarity.
+ */
+enum adi_sync_polarity {
+	ADV7533_SYNC_POLARITY_PASSTHROUGH,
+	ADV7533_SYNC_POLARITY_LOW,
+	ADV7533_SYNC_POLARITY_HIGH,
+};
+
+enum adv75xx_type {
+	ADV7511,
+	ADV7533,
+	ADV7535,
+};
+
+enum connector_status {
+	connector_status_connected = 1,
+	connector_status_disconnected = 2,
+	connector_status_unknown = 3,
+};
+
+struct adi_hdmi {
+	enum adv75xx_type type;
+	bool powered;
+
+	struct regulator *vdd;
+	struct regulator *v1p2;
+
+	struct i2c_client *i2c_main;
+	struct i2c_client *i2c_edid;
+	struct i2c_client *i2c_cec;
+	struct i2c_client *i2c_packet;
+
+	struct regmap *regmap;
+	struct regmap *regmap_cec;
+	struct regmap *regmap_packet;
+	enum connector_status status;
+
+	unsigned int f_tmds;
+	unsigned int f_audio;
+	unsigned int audio_source;
+
+	bool edid_read;
+	unsigned int current_edid_segment;
+
+	wait_queue_head_t wq;
+
+	bool rgb;
+	bool embedded_sync;
+	enum adi_sync_polarity vsync_polarity;
+	enum adi_sync_polarity hsync_polarity;
+	uint8_t num_dsi_lanes;
+
+	struct edid *edid;
+	struct gpio_desc *gpio_pd;
+
+	struct hisi_display_mode *mode;
+	struct adi_operation_funcs *opt_funcs;
+};
+
+struct adi_operation_funcs {
+	void (*power_on)(struct adi_hdmi *adv75xx);
+	void (*power_off)(struct adi_hdmi *adv75xx);
+	void (*mode_set)(struct adi_hdmi *adv75xx,
+			  struct hisi_display_mode *mode);
+};
+
+#endif				/* __ADV75XX_H__ */
diff --git a/drivers/video/fbdev/hisi/dss/hdmi/adv75xx_audio.c b/drivers/video/fbdev/hisi/dss/hdmi/adv75xx_audio.c
new file mode 100755
index 000000000000..8242579107b2
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hdmi/adv75xx_audio.c
@@ -0,0 +1,310 @@
+/*
+ * Analog Devices ADV7511 HDMI transmitter driver
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "adv75xx.h"
+
+static const struct snd_soc_dapm_widget adv75xx_dapm_widgets[] = {
+	SND_SOC_DAPM_OUTPUT("TMDS"),
+	SND_SOC_DAPM_AIF_IN("AIFIN", "Playback", 0, SND_SOC_NOPM, 0, 0),
+};
+
+static const struct snd_soc_dapm_route adv75xx_routes[] = {
+	{"TMDS", NULL, "AIFIN"},
+};
+
+static void adv75xx_calc_cts_n(unsigned int f_tmds, unsigned int fs,
+			       unsigned int *cts, unsigned int *n)
+{
+	switch (fs) {
+	case 32000:
+		*n = 4096;
+		break;
+	case 44100:
+		*n = 6272;
+		break;
+	case 48000:
+		*n = 6144;
+		break;
+	}
+
+	*cts = ((f_tmds * *n) / (128 * fs)) * 1000;
+}
+
+static int adv75xx_update_cts_n(struct adi_hdmi *adv75xx)
+{
+	unsigned int cts = 0;
+	unsigned int n = 0;
+
+	adv75xx_calc_cts_n(adv75xx->f_tmds, adv75xx->f_audio, &cts, &n);
+
+	regmap_write(adv75xx->regmap, ADV7533_REG_N0, (n >> 16) & 0xf);
+	regmap_write(adv75xx->regmap, ADV7533_REG_N1, (n >> 8) & 0xff);
+	regmap_write(adv75xx->regmap, ADV7533_REG_N2, n & 0xff);
+
+	regmap_write(adv75xx->regmap, ADV7533_REG_CTS_MANUAL0,
+		     (cts >> 16) & 0xf);
+	regmap_write(adv75xx->regmap, ADV7533_REG_CTS_MANUAL1,
+		     (cts >> 8) & 0xff);
+	regmap_write(adv75xx->regmap, ADV7533_REG_CTS_MANUAL2, cts & 0xff);
+
+	return 0;
+}
+
+static int adv75xx_hw_params(struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *params,
+			     struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->codec;
+	struct adi_hdmi *adv75xx = snd_soc_codec_get_drvdata(codec);
+	unsigned int rate;
+	unsigned int len;
+	switch (params_rate(params)) {
+	case 32000:
+		rate = ADV7533_SAMPLE_FREQ_32000;
+		break;
+	case 44100:
+		rate = ADV7533_SAMPLE_FREQ_44100;
+		break;
+	case 48000:
+		rate = ADV7533_SAMPLE_FREQ_48000;
+		break;
+	case 88200:
+		rate = ADV7533_SAMPLE_FREQ_88200;
+		break;
+	case 96000:
+		rate = ADV7533_SAMPLE_FREQ_96000;
+		break;
+	case 176400:
+		rate = ADV7533_SAMPLE_FREQ_176400;
+		break;
+	case 192000:
+		rate = ADV7533_SAMPLE_FREQ_192000;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		len = ADV7533_I2S_SAMPLE_LEN_16;
+		break;
+	case SNDRV_PCM_FORMAT_S18_3LE:
+		len = ADV7533_I2S_SAMPLE_LEN_18;
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		len = ADV7533_I2S_SAMPLE_LEN_20;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		len = ADV7533_I2S_SAMPLE_LEN_24;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	adv75xx->f_audio = params_rate(params);
+
+	adv75xx_update_cts_n(adv75xx);
+
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_AUDIO_CFG3,
+			   ADV7533_AUDIO_CFG3_LEN_MASK, len);
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_I2C_FREQ_ID_CFG,
+			   ADV7533_I2C_FREQ_ID_CFG_RATE_MASK, rate << 4);
+	regmap_write(adv75xx->regmap, 0x73, 0x1);
+
+	return 0;
+}
+
+static int adv75xx_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct adi_hdmi *adv75xx = snd_soc_codec_get_drvdata(codec);
+	unsigned int audio_source, i2s_format = 0;
+	unsigned int invert_clock;
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		audio_source = ADV7533_AUDIO_SOURCE_I2S;
+		i2s_format = ADV7533_I2S_FORMAT_I2S;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		audio_source = ADV7533_AUDIO_SOURCE_I2S;
+		i2s_format = ADV7533_I2S_FORMAT_RIGHT_J;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		audio_source = ADV7533_AUDIO_SOURCE_I2S;
+		i2s_format = ADV7533_I2S_FORMAT_LEFT_J;
+		break;
+	/*
+	case SND_SOC_DAIFMT_SPDIF:
+	   audio_source = ADV7533_AUDIO_SOURCE_SPDIF;
+	   break;
+	*/
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		invert_clock = 0;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		invert_clock = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_AUDIO_SOURCE, 0x70,
+			   audio_source << 4);
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_AUDIO_CONFIG, BIT(6),
+			   invert_clock << 6);
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_I2S_CONFIG, 0x03,
+			   i2s_format);
+
+	adv75xx->audio_source = audio_source;
+
+	return 0;
+}
+
+static int adv75xx_set_bias_level(struct snd_soc_codec *codec,
+				  enum snd_soc_bias_level level)
+{
+	struct adi_hdmi *adv75xx = snd_soc_codec_get_drvdata(codec);
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		switch (adv75xx->audio_source) {
+		case ADV7533_AUDIO_SOURCE_I2S:
+			break;
+		case ADV7533_AUDIO_SOURCE_SPDIF:
+			regmap_update_bits(adv75xx->regmap,
+					   ADV7533_REG_AUDIO_CONFIG, BIT(7),
+					   BIT(7));
+			break;
+		}
+		break;
+	case SND_SOC_BIAS_PREPARE:
+		if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
+			adv75xx_packet_enable(adv75xx,
+					      ADV7533_PACKET_ENABLE_AUDIO_SAMPLE);
+			adv75xx_packet_enable(adv75xx,
+					      ADV7533_PACKET_ENABLE_AUDIO_INFOFRAME);
+			adv75xx_packet_enable(adv75xx,
+					      ADV7533_PACKET_ENABLE_N_CTS);
+		} else {
+			adv75xx_packet_disable(adv75xx,
+					       ADV7533_PACKET_ENABLE_AUDIO_SAMPLE);
+			adv75xx_packet_disable(adv75xx,
+					       ADV7533_PACKET_ENABLE_AUDIO_INFOFRAME);
+			adv75xx_packet_disable(adv75xx,
+					       ADV7533_PACKET_ENABLE_N_CTS);
+		}
+		break;
+	case SND_SOC_BIAS_STANDBY:
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_AUDIO_CONFIG,
+				   BIT(7), 0);
+		break;
+	case SND_SOC_BIAS_OFF:
+		break;
+	}
+	dapm->bias_level = level;
+	return 0;
+}
+
+#define ADV7533_RATES (SNDRV_PCM_RATE_32000 |\
+		SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
+		SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |\
+		SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
+
+#define ADV7533_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE |\
+		SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE)
+
+static const struct snd_soc_dai_ops adv75xx_dai_ops = {
+	.hw_params = adv75xx_hw_params,
+	/*.set_sysclk   = adv75xx_set_dai_sysclk, */
+	.set_fmt = adv75xx_set_dai_fmt,
+};
+
+static struct snd_soc_dai_driver adv75xx_dai = {
+	.name = "adv75xx",
+	.playback = {
+		     .stream_name = "Playback",
+		     .channels_min = 2,
+		     .channels_max = 2,
+		     .rates = ADV7533_RATES,
+		     .formats = ADV7533_FORMATS,
+		     },
+	.ops = &adv75xx_dai_ops,
+};
+
+static int adv75xx_suspend(struct snd_soc_codec *codec)
+{
+	return adv75xx_set_bias_level(codec, SND_SOC_BIAS_OFF);
+}
+
+static int adv75xx_resume(struct snd_soc_codec *codec)
+{
+	return adv75xx_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+}
+
+static int adv75xx_probe(struct snd_soc_codec *codec)
+{
+	return adv75xx_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+}
+
+static int adv75xx_remove(struct snd_soc_codec *codec)
+{
+	adv75xx_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	return 0;
+}
+
+static struct snd_soc_codec_driver adv75xx_codec_driver = {
+	.probe = adv75xx_probe,
+	.remove = adv75xx_remove,
+	.suspend = adv75xx_suspend,
+	.resume = adv75xx_resume,
+	.set_bias_level = adv75xx_set_bias_level,
+
+	.dapm_widgets = adv75xx_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(adv75xx_dapm_widgets),
+	.dapm_routes = adv75xx_routes,
+	.num_dapm_routes = ARRAY_SIZE(adv75xx_routes),
+};
+
+int adv75xx_audio_init(struct device *dev)
+{
+	return snd_soc_register_codec(dev, &adv75xx_codec_driver,
+				      &adv75xx_dai, 1);
+}
+
+void adv75xx_audio_exit(struct device *dev)
+{
+	snd_soc_unregister_codec(dev);
+}
diff --git a/drivers/video/fbdev/hisi/dss/hdmi/mipi_adi_hdmi.c b/drivers/video/fbdev/hisi/dss/hdmi/mipi_adi_hdmi.c
new file mode 100755
index 000000000000..65313f54878d
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hdmi/mipi_adi_hdmi.c
@@ -0,0 +1,314 @@
+/* Copyright (c) 2008-2011, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *	 * Redistributions of source code must retain the above copyright
+ *	   notice, this list of conditions and the following disclaimer.
+ *	 * Redistributions in binary form must reproduce the above
+ *	   copyright notice, this list of conditions and the following
+ *	   disclaimer in the documentation and/or other materials provided
+ *	   with the distribution.
+ *	 * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *	   contributors may be used to endorse or promote products derived
+ *	   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "../hisi_fb.h"
+#include "adv75xx.h"
+
+/*******************************************************************************
+ **
+ */
+static int mipi_adi_hdmi_on(struct platform_device *pdev)
+{
+	struct adi_hdmi *adv75xx = NULL;
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct hisi_panel_info *pinfo = NULL;
+
+	HISI_FB_INFO("+.\n");
+
+	if (pdev == NULL) {
+		HISI_FB_ERR("pdev is NULL!\n");
+		return -1;
+	}
+
+	HISI_FB_INFO("pdev->name = %s, pdev->id = %d\n", pdev->name, pdev->id);
+
+	hisifd = platform_get_drvdata(pdev);
+	if (hisifd == NULL) {
+		HISI_FB_ERR("platform get drivre data failed!!\n");
+		return -1;
+	}
+
+	HISI_FB_INFO("fb%d, +!\n", hisifd->index);
+
+	pinfo = &(hisifd->panel_info);
+
+	pdata = dev_get_platdata(&pdev->dev);
+	if (pdata == NULL) {
+		HISI_FB_ERR("devices get platform data failed!!\n");
+		return -1;
+	}
+
+	if (pdata->next) {
+		adv75xx = platform_get_drvdata(pdata->next);
+		if (!adv75xx) {
+			HISI_FB_ERR("platform get drivre data failed!\n");
+			return -1;
+		}
+	} else {
+		HISI_FB_ERR("pdata->next is NULL!!\n");
+		return -1;
+	}
+
+	HISI_FB_INFO("adv75xx->i2c_main->name is %s!\n",
+		     adv75xx->i2c_main->name);
+	HISI_FB_INFO("adv75xx->mode->vdisplay is %d!\n",
+		     adv75xx->mode->vdisplay);
+
+	if (pinfo->lcd_init_step == LCD_INIT_POWER_ON) {
+		pinfo->lcd_init_step = LCD_INIT_MIPI_LP_SEND_SEQUENCE;
+	} else if (pinfo->lcd_init_step == LCD_INIT_MIPI_LP_SEND_SEQUENCE) {
+		pinfo->lcd_init_step = LCD_INIT_MIPI_HS_SEND_SEQUENCE;
+	} else if (pinfo->lcd_init_step == LCD_INIT_MIPI_HS_SEND_SEQUENCE) {
+		adv75xx->opt_funcs->mode_set(adv75xx, adv75xx->mode);
+		adv75xx->opt_funcs->power_on(adv75xx);
+	} else {
+		HISI_FB_ERR("failed to init hdmi!\n");
+	}
+
+	HISI_FB_INFO("-.\n");
+
+	return 0;
+}
+
+static int mipi_adi_hdmi_off(struct platform_device *pdev)
+{
+	struct adi_hdmi *adv75xx = NULL;
+	struct hisi_fb_panel_data *pdata = NULL;
+
+	HISI_FB_INFO("+.\n");
+
+	BUG_ON(pdev == NULL);
+	pdata = dev_get_platdata(&pdev->dev);
+	BUG_ON(pdata == NULL);
+
+	HISI_FB_INFO("pdev->name = %s, pdev->id = %d +.\n", pdev->name,
+		     pdev->id);
+
+	if (pdata->next) {
+		adv75xx = platform_get_drvdata(pdata->next);
+		if (!adv75xx) {
+			HISI_FB_ERR("platform get drivre data failed!\n");
+			return -1;
+		}
+	}
+
+	HISI_FB_INFO("adv75xx->i2c_main->name is %s!\n",
+		     adv75xx->i2c_main->name);
+	HISI_FB_INFO("adv75xx->mode->vdisplay is %d!\n",
+		     adv75xx->mode->vdisplay);
+
+	adv75xx->opt_funcs->power_off(adv75xx);
+
+	HISI_FB_INFO("-.\n");
+
+	return 0;
+}
+
+static int mipi_adi_hdmi_remove(struct platform_device *pdev)
+{
+
+	return 0;
+}
+
+/*******************************************************************************
+ **
+ */
+static struct hisi_panel_info g_adi_hdmi_info = { 0 };
+
+static struct hisi_fb_panel_data g_adi_hdmi_data = {
+	.panel_info = &g_adi_hdmi_info,
+	.on = mipi_adi_hdmi_on,
+	.off = mipi_adi_hdmi_off,
+};
+
+/*******************************************************************************
+ **
+ */
+static int mipi_adi_hdmi_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct adi_hdmi *adv75xx = NULL;
+	struct hisi_panel_info *pinfo = NULL;
+	struct hisi_display_mode *mode = NULL;
+
+	if (pdev == NULL)
+		HISI_FB_ERR("platform device is NULL!\n");
+
+	HISI_FB_INFO("pdev->name = %s, pdev->id = %d +.\n", pdev->name,
+		     pdev->id);
+
+	adv75xx = platform_get_drvdata(pdev);
+	if (!adv75xx) {
+		HISI_FB_ERR("platform get drivre data failed!\n");
+		goto err_probe_defer;
+	}
+
+	HISI_FB_INFO("adv75xx->i2c_main->name is %s!\n",
+		     adv75xx->i2c_main->name);
+
+	HISI_FB_INFO("adv75xx->mode->vdisplay is %d!\n",
+		     adv75xx->mode->vdisplay);
+
+	if (adv75xx->mode) {
+		mode = adv75xx->mode;
+		/* init hdmi display info */
+		pinfo = g_adi_hdmi_data.panel_info;
+		pinfo->xres = mode->hdisplay;
+		pinfo->yres = mode->vdisplay;
+		pinfo->width = mode->width_mm;
+		pinfo->height = mode->height_mm;
+		pinfo->orientation = LCD_PORTRAIT;
+		pinfo->bpp = LCD_RGB888;
+		pinfo->bgr_fmt = LCD_RGB;
+		pinfo->bl_set_type = BL_SET_BY_MIPI;
+
+		pinfo->type = PANEL_MIPI_VIDEO;
+
+		pinfo->bl_min = 1;
+		pinfo->bl_max = 255;
+		pinfo->bl_default = 102;
+
+		pinfo->pxl_clk_rate = mode->clock * 1000UL;
+		pinfo->ldi.h_back_porch = mode->htotal - mode->hsync_end;
+		pinfo->ldi.h_front_porch = mode->hsync_offset;
+		pinfo->ldi.h_pulse_width = mode->hsync_pulse_width;
+		pinfo->ldi.v_back_porch = mode->vtotal - mode->vsync_end;
+		pinfo->ldi.v_front_porch = mode->vsync_offset;
+		pinfo->ldi.v_pulse_width = mode->vsync_pulse_width;
+	} else {
+		/* init hdmi display info */
+		pinfo = g_adi_hdmi_data.panel_info;
+		pinfo->xres = 1920;
+		pinfo->yres = 1080;
+		pinfo->width = 16000;
+		pinfo->height = 9000;
+
+		pinfo->orientation = LCD_PORTRAIT;
+		pinfo->bpp = LCD_RGB888;
+		pinfo->bgr_fmt = LCD_RGB;
+		pinfo->bl_set_type = BL_SET_BY_MIPI;
+
+		pinfo->type = PANEL_MIPI_VIDEO;
+
+		pinfo->bl_min = 1;
+		pinfo->bl_max = 255;
+		pinfo->bl_default = 102;
+
+		pinfo->ldi.h_back_porch = 148;
+		pinfo->ldi.h_front_porch = 88;
+		pinfo->ldi.h_pulse_width = 44;
+		pinfo->ldi.v_back_porch = 36;
+		pinfo->ldi.v_front_porch = 4;
+		pinfo->ldi.v_pulse_width = 5;
+	}
+
+
+	pinfo->mipi.dsi_bit_clk = 480;
+
+
+	pinfo->dsi_bit_clk_upt_support = 0;
+	pinfo->mipi.dsi_bit_clk_upt = pinfo->mipi.dsi_bit_clk;
+
+	pinfo->mipi.non_continue_en = 0;
+
+	pinfo->pxl_clk_rate = 160 * 1000000UL;
+
+
+	pinfo->mipi.lane_nums = DSI_4_LANES;
+	pinfo->mipi.color_mode = DSI_24BITS_1;
+	pinfo->mipi.vc = 0;
+	pinfo->mipi.max_tx_esc_clk = 10 * 1000000;
+	pinfo->mipi.burst_mode = DSI_NON_BURST_SYNC_PULSES;
+
+	pinfo->mipi.clk_post_adjust = 120;
+	pinfo->mipi.clk_pre_adjust = 0;
+	pinfo->mipi.clk_t_hs_prepare_adjust = 0;
+	pinfo->mipi.clk_t_lpx_adjust = 0;
+	pinfo->mipi.clk_t_hs_trial_adjust = 0;
+	pinfo->mipi.clk_t_hs_exit_adjust = 0;
+	pinfo->mipi.clk_t_hs_zero_adjust = 0;
+
+	pinfo->pxl_clk_rate_div = 1;
+
+	g_adi_hdmi_data.next = pdev;
+	HISI_FB_INFO("The pixel clock is %llu !\n", pinfo->pxl_clk_rate);
+	HISI_FB_INFO("The resolution is %d x %d !\n", pinfo->xres, pinfo->yres);
+	HISI_FB_INFO
+	    ("hsw = %d, hfp = %d, hbp = %d, vsw = %d, vfp= %d, vbp = %d\n",
+	     pinfo->ldi.h_pulse_width, pinfo->ldi.h_front_porch,
+	     pinfo->ldi.h_back_porch, pinfo->ldi.v_pulse_width,
+	     pinfo->ldi.v_front_porch, pinfo->ldi.v_back_porch);
+
+
+	ret = platform_device_add_data(pdev, &g_adi_hdmi_data,
+				       sizeof(struct hisi_fb_panel_data));
+	if (ret) {
+		HISI_FB_ERR("platform_device_add_data failed!\n");
+		goto err_device_put;
+	}
+
+	hisi_fb_add_device(pdev);
+
+	HISI_FB_INFO("-.\n");
+
+	return 0;
+
+ err_device_put:
+	platform_device_put(pdev);
+ err_probe_defer:
+	return -EPROBE_DEFER;
+}
+
+static struct platform_driver this_driver = {
+	.probe = mipi_adi_hdmi_probe,
+	.remove = mipi_adi_hdmi_remove,
+	.suspend = NULL,
+	.resume = NULL,
+	.shutdown = NULL,
+	.driver = {
+		   .name = "adi_hdmi",
+		   }
+};
+
+static int __init mipi_adi_hdmi_init(void)
+{
+	int ret = 0;
+
+	ret = platform_driver_register(&this_driver);
+	if (ret) {
+		HISI_FB_ERR("platform_driver_register failed, error=%d!\n",
+			    ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+module_init(mipi_adi_hdmi_init);
diff --git a/drivers/video/fbdev/hisi/dss/panel/mipi_hikey_nte300nts.c b/drivers/video/fbdev/hisi/dss/panel/mipi_hikey_nte300nts.c
new file mode 100755
index 000000000000..7e1fbd0ee5c6
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/panel/mipi_hikey_nte300nts.c
@@ -0,0 +1,525 @@
+/* Copyright (c) 2008-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "../hisi_fb.h"
+
+#define DTS_COMP_MIPI_HIKEY	"hisilicon,mipi_hikey"
+
+/********************************Hikey start***********************
+ **Power ON Sequence(sleep mode to Normal mode)
+ */
+static char hikey_power_on_param1[] = {
+	0x01,
+};
+
+static char hikey_power_on_param2[] = {
+	0xB0,
+	0x00,
+};
+
+static char hikey_power_on_param3[] = {
+	0xD6,
+	0x01,
+};
+
+static char hikey_power_on_param4[] = {
+	0xB3,
+	0x14, 0x08, 0x00, 0x22, 0x00,
+};
+
+static char hikey_power_on_param5[] = {
+	0xB4,
+	0x0C,
+};
+
+static char hikey_power_on_param6[] = {
+	0xB6,
+	0x3A, 0xC3,
+};
+
+static char hikey_power_on_param7[] = {
+	0x2A,
+	0x00, 0x00, 0X04, 0XAF,
+};
+
+static char hikey_power_on_param8[] = {
+	0x2B,
+	0x00, 0x00, 0X07, 0X7F,
+};
+
+static char hikey_power_on_param9[] = {
+	0x51,
+	0xA6,
+};
+
+static char hikey_power_on_param10[] = {
+	0x53,
+	0x2C,
+};
+
+static char hikey_power_on_param11[] = {
+	0x3A,
+	0x66,
+};
+
+static char hikey_power_on_param12[] = {
+	0x29,
+};
+
+static char hikey_power_on_param13[] = {
+	0x11,
+};
+
+static char hikey_display_off[] = {
+	0x28,
+};
+
+static char hikey_enter_sleep[] = {
+	0x10,
+};
+
+static struct dsi_cmd_desc hikey_display_off_cmds[] = {
+	{DTYPE_DCS_WRITE, 0, 20, WAIT_TYPE_MS,
+	 sizeof(hikey_display_off), hikey_display_off}
+	,
+	{DTYPE_DCS_WRITE, 0, 80, WAIT_TYPE_MS,
+	 sizeof(hikey_enter_sleep), hikey_enter_sleep}
+	,
+};
+
+/*short or long packet*/
+static struct dsi_cmd_desc hikey_display_on_cmds[] = {
+	{DTYPE_DCS_WRITE, 0, 5, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param1), hikey_power_on_param1}
+	,
+	{DTYPE_DCS_WRITE1, 0, 2, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param2), hikey_power_on_param2}
+	,
+	{DTYPE_DCS_WRITE1, 0, 2, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param3), hikey_power_on_param3}
+	,
+	{DTYPE_DCS_LWRITE, 0, 2, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param4), hikey_power_on_param4}
+	,
+	{DTYPE_DCS_WRITE1, 0, 2, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param5), hikey_power_on_param5}
+	,
+	{DTYPE_DCS_LWRITE, 0, 2, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param6), hikey_power_on_param6}
+	,
+	{DTYPE_DCS_LWRITE, 0, 2, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param7), hikey_power_on_param7}
+	,
+	{DTYPE_DCS_LWRITE, 0, 2, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param8), hikey_power_on_param8}
+	,
+	{DTYPE_DCS_WRITE1, 0, 2, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param9), hikey_power_on_param9}
+	,
+	{DTYPE_DCS_WRITE1, 0, 2, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param10), hikey_power_on_param10}
+	,
+	{DTYPE_DCS_WRITE1, 0, 2, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param11), hikey_power_on_param11}
+	,
+	{DTYPE_DCS_WRITE, 0, 20, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param12), hikey_power_on_param12}
+	,
+	{DTYPE_DCS_WRITE, 0, 150, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param13), hikey_power_on_param13}
+	,
+};
+
+/********************************hikey end*************************/
+
+/*******************************************************************************
+ ** LCD GPIO
+ */
+#define GPIO_LCD_PWR_ENABLE_NAME "gpio_lcd_pwr_enable"
+#define GPIO_LCD_BL_ENABLE_NAME "gpio_lcd_bl_enable"
+#define GPIO_LCD_PWM_NAME "gpio_lcd_pwm"
+#define GPIO_SWITCH_DSI_HDMI "gpio_switch_dsi_hdmi"
+
+static uint32_t gpio_lcd_pwr_enable;
+static uint32_t gpio_lcd_bl_enable;
+static uint32_t gpio_lcd_pwm;
+static uint32_t gpio_switch_dsi_hdmi;
+
+static struct gpio_desc hikey_lcd_gpio_request_cmds[] = {
+	{DTYPE_GPIO_REQUEST, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_PWR_ENABLE_NAME, &gpio_lcd_pwr_enable, 0},
+	{DTYPE_GPIO_REQUEST, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_BL_ENABLE_NAME, &gpio_lcd_bl_enable, 0},
+	{DTYPE_GPIO_REQUEST, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_PWM_NAME, &gpio_lcd_pwm, 0},
+	{DTYPE_GPIO_REQUEST, WAIT_TYPE_MS, 0,
+	 GPIO_SWITCH_DSI_HDMI, &gpio_switch_dsi_hdmi, 0},
+};
+
+static struct gpio_desc hikey_lcd_gpio_free_cmds[] = {
+	{DTYPE_GPIO_FREE, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_PWR_ENABLE_NAME, &gpio_lcd_pwr_enable, 0},
+	{DTYPE_GPIO_FREE, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_BL_ENABLE_NAME, &gpio_lcd_bl_enable, 0},
+	{DTYPE_GPIO_FREE, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_PWM_NAME, &gpio_lcd_pwm, 0},
+	{DTYPE_GPIO_FREE, WAIT_TYPE_MS, 0,
+	 GPIO_SWITCH_DSI_HDMI, &gpio_switch_dsi_hdmi, 0},
+};
+
+static struct gpio_desc hikey_lcd_gpio_normal_cmds[] = {
+	{DTYPE_GPIO_OUTPUT, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_PWR_ENABLE_NAME, &gpio_lcd_pwr_enable, 1},
+	{DTYPE_GPIO_OUTPUT, WAIT_TYPE_MS, 0,
+	 GPIO_SWITCH_DSI_HDMI, &gpio_switch_dsi_hdmi, 1},
+};
+
+static struct gpio_desc hikey_lcd_gpio_off_cmds[] = {
+	{DTYPE_GPIO_OUTPUT, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_PWR_ENABLE_NAME, &gpio_lcd_pwr_enable, 0},
+	{DTYPE_GPIO_OUTPUT, WAIT_TYPE_MS, 0,
+	 GPIO_SWITCH_DSI_HDMI, &gpio_switch_dsi_hdmi, 0},
+};
+
+static struct gpio_desc hikey_lcd_backlight_enable_cmds[] = {
+	{DTYPE_GPIO_OUTPUT, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_BL_ENABLE_NAME, &gpio_lcd_bl_enable, 1},
+	{DTYPE_GPIO_OUTPUT, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_PWM_NAME, &gpio_lcd_pwm, 1},
+};
+
+static struct gpio_desc hikey_lcd_backlight_disable_cmds[] = {
+	{DTYPE_GPIO_OUTPUT, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_BL_ENABLE_NAME, &gpio_lcd_bl_enable, 0},
+	{DTYPE_GPIO_OUTPUT, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_PWM_NAME, &gpio_lcd_pwm, 0},
+};
+
+static struct hisi_fb_panel_data g_panel_data;
+
+static void hikey_set_backlight_on(void)
+{
+	msleep(200);
+	gpio_cmds_tx(hikey_lcd_backlight_enable_cmds,
+		     ARRAY_SIZE(hikey_lcd_backlight_enable_cmds));
+	return;
+}
+
+static void hikey_set_backlight_off(void)
+{
+	gpio_cmds_tx(hikey_lcd_backlight_disable_cmds,
+		     ARRAY_SIZE(hikey_lcd_backlight_disable_cmds));
+	return;
+}
+
+static int hikey_panel_on(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct hisi_panel_info *pinfo = NULL;
+	char __iomem *mipi_dsi0_base = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+	pinfo = &(hisifd->panel_info);
+	BUG_ON(pinfo == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	mipi_dsi0_base = hisifd->mipi_dsi0_base;
+
+	if (pinfo->lcd_init_step == LCD_INIT_POWER_ON) {
+		pinfo->lcd_init_step = LCD_INIT_MIPI_LP_SEND_SEQUENCE;
+	} else if (pinfo->lcd_init_step == LCD_INIT_MIPI_LP_SEND_SEQUENCE) {
+		/*lcd gpio request */
+		gpio_cmds_tx(hikey_lcd_gpio_request_cmds,
+			     ARRAY_SIZE(hikey_lcd_gpio_request_cmds));
+		/*lcd gpio normal */
+		gpio_cmds_tx(hikey_lcd_gpio_normal_cmds,
+			     ARRAY_SIZE(hikey_lcd_gpio_normal_cmds));
+		/*lcd display on sequence */
+		msleep(250);
+		mipi_dsi_cmds_tx(hikey_display_on_cmds,
+				 ARRAY_SIZE(hikey_display_on_cmds),
+				 mipi_dsi0_base);
+
+		pinfo->lcd_init_step = LCD_INIT_MIPI_HS_SEND_SEQUENCE;
+	} else if (pinfo->lcd_init_step == LCD_INIT_MIPI_HS_SEND_SEQUENCE) {
+		;
+	} else {
+		HISI_FB_ERR("failed to init lcd!\n");
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return 0;
+}
+
+static int hikey_panel_off(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct hisi_panel_info *pinfo = NULL;
+	char __iomem *mipi_dsi0_base = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+	pinfo = &(hisifd->panel_info);
+	BUG_ON(pinfo == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+	mipi_dsi0_base = hisifd->mipi_dsi0_base;
+	/*lcd enter sleep */
+	mipi_dsi_cmds_tx(hikey_display_off_cmds,
+			 ARRAY_SIZE(hikey_display_off_cmds), mipi_dsi0_base);
+	gpio_cmds_tx(hikey_lcd_gpio_off_cmds,
+		     ARRAY_SIZE(hikey_lcd_gpio_off_cmds));
+	gpio_cmds_tx(hikey_lcd_gpio_free_cmds,
+		     ARRAY_SIZE(hikey_lcd_gpio_free_cmds));
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return 0;
+}
+
+static int hikey_panel_remove(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return 0;
+}
+
+static int hikey_panel_set_backlight(struct platform_device *pdev,
+				     uint32_t bl_level)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	int ret = 0;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	if (bl_level == 0) {
+		hikey_set_backlight_off();
+	} else {
+		hikey_set_backlight_on();
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return ret;
+}
+
+static struct hisi_panel_info g_panel_info = { 0 };
+
+static struct hisi_fb_panel_data g_panel_data = {
+	.panel_info = &g_panel_info,
+	.on = hikey_panel_on,
+	.off = hikey_panel_off,
+	.remove = hikey_panel_remove,
+	.set_backlight = hikey_panel_set_backlight,
+};
+
+static int hikey_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct hisi_panel_info *pinfo = NULL;
+	struct device_node *np = NULL;
+	uint32_t bl_type = 0;
+
+	uint32_t lcd_display_type = 0;
+	uint32_t lcd_ifbc_type = 0;
+
+	HISI_FB_DEBUG("+.\n");
+
+	np = of_find_compatible_node(NULL, NULL, DTS_COMP_MIPI_HIKEY);
+	if (!np) {
+		HISI_FB_ERR("NOT FOUND device node %s!\n", DTS_COMP_MIPI_HIKEY);
+		goto err_return;
+	}
+
+	ret = of_property_read_u32(np, LCD_BL_TYPE_NAME, &bl_type);
+	if (ret) {
+		HISI_FB_ERR("get lcd_bl_type failed!\n");
+		bl_type = BL_SET_BY_BLPWM;
+	}
+
+	ret =
+	    of_property_read_u32(np, LCD_DISPLAY_TYPE_NAME, &lcd_display_type);
+	if (ret) {
+		HISI_FB_ERR("get lcd_display_type failed!\n");
+		lcd_display_type = PANEL_MIPI_VIDEO;
+	}
+
+	ret = of_property_read_u32(np, LCD_IFBC_TYPE_NAME, &lcd_ifbc_type);
+	if (ret) {
+		HISI_FB_ERR("get ifbc_type failed!\n");
+		lcd_ifbc_type = IFBC_TYPE_NONE;
+	}
+
+	/*GPIO_26_8 GPIO_216 */
+	gpio_lcd_pwr_enable = of_get_named_gpio(np, "gpios", 0);
+	/*GPIO_27_2 GPIO_218 */
+	gpio_lcd_bl_enable = of_get_named_gpio(np, "gpios", 1);
+	/*GPIO_22_6 GPIO_182 */
+	gpio_lcd_pwm = of_get_named_gpio(np, "gpios", 2);
+	/*GPIO_2_4 GPIO_020 */
+	gpio_switch_dsi_hdmi = of_get_named_gpio(np, "gpios", 3);
+
+	if (hisi_fb_device_probe_defer(lcd_display_type, bl_type)) {
+		goto err_probe_defer;
+	}
+
+	pdev->id = 1;
+	/*init lcd panel info */
+	pinfo = g_panel_data.panel_info;
+	memset(pinfo, 0, sizeof(struct hisi_panel_info));
+	pinfo->xres = 1200;
+	pinfo->yres = 1920;
+	pinfo->width = 94;
+	pinfo->height = 151;
+	pinfo->orientation = LCD_PORTRAIT;
+	pinfo->bpp = LCD_RGB888;
+	pinfo->bgr_fmt = LCD_RGB;
+	pinfo->bl_set_type = bl_type;
+
+	pinfo->type = PANEL_MIPI_VIDEO;
+	pinfo->ifbc_type = 0;
+
+	if (pinfo->bl_set_type == BL_SET_BY_BLPWM)
+		pinfo->blpwm_input_ena = 0;
+
+	pinfo->bl_min = 1;
+	pinfo->bl_max = 255;
+	pinfo->bl_default = 102;
+	pinfo->esd_enable = 0;
+
+	/*ldi */
+	pinfo->ldi.h_back_porch = 60;
+	pinfo->ldi.h_front_porch = 200;
+	pinfo->ldi.h_pulse_width = 12;
+	pinfo->ldi.v_back_porch = 8;
+	pinfo->ldi.v_front_porch = 8;
+	pinfo->ldi.v_pulse_width = 2;
+
+	/*
+	   pinfo->ldi.hsync_plr = 0;
+	   pinfo->ldi.vsync_plr = 0;
+	   pinfo->ldi.pixelclk_plr = 1;
+	   pinfo->ldi.data_en_plr = 0;
+	 */
+
+	/*mipi */
+	pinfo->mipi.lane_nums = DSI_4_LANES;
+	pinfo->mipi.color_mode = DSI_24BITS_1;
+	pinfo->mipi.vc = 0;
+	pinfo->mipi.max_tx_esc_clk = 10 * 1000000;
+	pinfo->mipi.burst_mode = DSI_BURST_SYNC_PULSES_1;
+
+	pinfo->mipi.dsi_bit_clk = 480;
+	pinfo->mipi.dsi_bit_clk_upt = pinfo->mipi.dsi_bit_clk;
+
+	pinfo->pxl_clk_rate = 146 * 1000000UL;
+	pinfo->pxl_clk_rate_div = 1;
+	pinfo->fps = 50;
+
+	pinfo->vsync_ctrl_type = 0;
+	pinfo->dirty_region_updt_support = 0;
+	pinfo->dsi_bit_clk_upt_support = 0;
+
+	/*alloc panel device data */
+	ret = platform_device_add_data(pdev, &g_panel_data,
+				       sizeof(struct hisi_fb_panel_data));
+	if (ret) {
+		HISI_FB_ERR("platform_device_add_data failed!\n");
+		goto err_device_put;
+	}
+
+	hisi_fb_add_device(pdev);
+
+	/*
+	   vdd = devm_regulator_get(&(pdev->dev), "vdd");
+	   if (IS_ERR(vdd)) {
+	   ret = PTR_ERR(vdd);
+	   HISI_FB_ERR("vdd regulator get fail\n");
+	   return ret;
+	   }
+
+	   ret = regulator_set_voltage(vdd, 1800000, 1800000);
+	   if (ret) {
+	   HISI_FB_ERR("vdd regulator set voltage fail\n");
+	   return ret;
+	   }
+
+	   ret = regulator_enable(vdd);
+	   if (ret) {
+	   HISI_FB_ERR("vdd regulator enable fail\n");
+	   return ret;
+	   }
+	 */
+
+	HISI_FB_DEBUG("-.\n");
+	return 0;
+
+ err_device_put:
+	platform_device_put(pdev);
+ err_return:
+	return ret;
+ err_probe_defer:
+	return -EPROBE_DEFER;
+}
+
+static const struct of_device_id hisi_panel_match_table[] = {
+	{
+	 .compatible = DTS_COMP_MIPI_HIKEY,
+	 .data = NULL,
+	 },
+	{},
+};
+
+static struct platform_driver this_driver = {
+	.probe = hikey_probe,
+	.remove = NULL,
+	.suspend = NULL,
+	.resume = NULL,
+	.shutdown = NULL,
+	.driver = {
+		   .name = "mipi_hikey",
+		   .owner = THIS_MODULE,
+		   .of_match_table = of_match_ptr(hisi_panel_match_table),
+		   },
+};
+
+static int __init hikey_panel_init(void)
+{
+	int ret = 0;
+
+	ret = platform_driver_register(&this_driver);
+	if (ret) {
+		HISI_FB_ERR("platform_driver_register failed, error=%d!\n",
+			    ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+module_init(hikey_panel_init);
-- 
2.12.0-rc0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/8] fb: hisilicon: Add framebuffer driver for hi3660 SoC
@ 2017-02-07  2:35     ` cailiwei
  0 siblings, 0 replies; 15+ messages in thread
From: cailiwei @ 2017-02-07  2:35 UTC (permalink / raw)
  To: linux-fbdev, linux-kernel, b.zolnierkie, guodong.xu
  Cc: suzhuangluan, dengqingshan, xuhongtao8, zhengwanchun,
	shizongxuan, cailiwei

From: Levy-Cai <cailiwei@hisilicon.com>

Add framebuffer driver for hi3660 SoC, this driver include lcd
driver & Hdmi adv7533/adv7535 driver, support lcd display at
1080p@60 and hdmi display at 1080p@60.

Signed-off-by: cailiwei <cailiwei@hisilicon.com>
---
 drivers/video/fbdev/hisi/dss/hdmi/adv75xx.c        | 1522 ++++++++++++++++++++
 drivers/video/fbdev/hisi/dss/hdmi/adv75xx.h        |  496 +++++++
 drivers/video/fbdev/hisi/dss/hdmi/adv75xx_audio.c  |  310 ++++
 drivers/video/fbdev/hisi/dss/hdmi/mipi_adi_hdmi.c  |  314 ++++
 .../fbdev/hisi/dss/panel/mipi_hikey_nte300nts.c    |  525 +++++++
 5 files changed, 3167 insertions(+)
 create mode 100755 drivers/video/fbdev/hisi/dss/hdmi/adv75xx.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hdmi/adv75xx.h
 create mode 100755 drivers/video/fbdev/hisi/dss/hdmi/adv75xx_audio.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hdmi/mipi_adi_hdmi.c
 create mode 100755 drivers/video/fbdev/hisi/dss/panel/mipi_hikey_nte300nts.c

diff --git a/drivers/video/fbdev/hisi/dss/hdmi/adv75xx.c b/drivers/video/fbdev/hisi/dss/hdmi/adv75xx.c
new file mode 100755
index 000000000000..328cd6869149
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hdmi/adv75xx.c
@@ -0,0 +1,1522 @@
+/**
+ *
+ *
+ **/
+
+#include "adv75xx.h"
+#define HPD_ENABLE	0
+/* #define TEST_COLORBAR_DISPLAY */
+
+static void adv75xx_power_on(struct adi_hdmi *adv75xx);
+static void adv75xx_power_off(struct adi_hdmi *adv75xx);
+
+/* ADI recommended values for proper operation. */
+static const struct reg_sequence adv7511_fixed_registers[] = {
+	{0x98, 0x03},
+	{0x9a, 0xe0},
+	{0x9c, 0x30},
+	{0x9d, 0x61},
+	{0xa2, 0xa4},
+	{0xa3, 0xa4},
+	{0xe0, 0xd0},
+	{0xf9, 0x00},
+	{0x55, 0x02},
+};
+
+/* ADI recommended values for proper operation. */
+static const struct reg_sequence adv7533_fixed_registers[] = {
+	{0x16, 0x20},
+	{0x9a, 0xe0},
+	{0xba, 0x70},
+	{0xde, 0x82},
+	{0xe4, 0x40},
+	{0xe5, 0x80},
+};
+
+static const struct reg_sequence adv7533_cec_fixed_registers[] = {
+	{0x15, 0xd0},
+	{0x17, 0xd0},
+	{0x24, 0x20},
+	{0x57, 0x11},
+	{0x05, 0xc8},
+};
+
+/* -----------------------------------------------------------------------------
+ * Register access
+ */
+
+static const uint8_t adv75xx_register_defaults[] = {
+	0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 00 */
+	0x00, 0x00, 0x01, 0x0e, 0xbc, 0x18, 0x01, 0x13,
+	0x25, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 10 */
+	0x46, 0x62, 0x04, 0xa8, 0x00, 0x00, 0x1c, 0x84,
+	0x1c, 0xbf, 0x04, 0xa8, 0x1e, 0x70, 0x02, 0x1e,	/* 20 */
+	0x00, 0x00, 0x04, 0xa8, 0x08, 0x12, 0x1b, 0xac,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 30 */
+	0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0,
+	0x00, 0x50, 0x90, 0x7e, 0x79, 0x70, 0x00, 0x00,	/* 40 */
+	0x00, 0xa8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x00, 0x00,	/* 50 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 60 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 70 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 80 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,	/* 90 */
+	0x0b, 0x02, 0x00, 0x18, 0x5a, 0x60, 0x00, 0x00,
+	0x00, 0x00, 0x80, 0x80, 0x08, 0x04, 0x00, 0x00,	/* a0 */
+	0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x14,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* b0 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* c0 */
+	0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x01, 0x04,
+	0x30, 0xff, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,	/* d0 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01,
+	0x80, 0x75, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,	/* e0 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x11, 0x00,	/* f0 */
+	0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static bool adv7511_register_volatile(struct device *dev, unsigned int reg)
+{
+	int ret = 0;
+
+	switch (reg) {
+	case ADV7533_REG_CHIP_REVISION:
+	case ADV7533_REG_SPDIF_FREQ:
+	case ADV7533_REG_CTS_AUTOMATIC1:
+	case ADV7533_REG_CTS_AUTOMATIC2:
+	case ADV7533_REG_VIC_DETECTED:
+	case ADV7533_REG_VIC_SEND:
+	case ADV7533_REG_AUX_VIC_DETECTED:
+	case ADV7533_REG_STATUS:
+	case ADV7533_REG_GC(1):
+	case ADV7533_REG_INT(0):
+	case ADV7533_REG_INT(1):
+	case ADV7533_REG_PLL_STATUS:
+	case ADV7533_REG_AN(0):
+	case ADV7533_REG_AN(1):
+	case ADV7533_REG_AN(2):
+	case ADV7533_REG_AN(3):
+	case ADV7533_REG_AN(4):
+	case ADV7533_REG_AN(5):
+	case ADV7533_REG_AN(6):
+	case ADV7533_REG_AN(7):
+	case ADV7533_REG_HDCP_STATUS:
+	case ADV7533_REG_BCAPS:
+	case ADV7533_REG_BKSV(0):
+	case ADV7533_REG_BKSV(1):
+	case ADV7533_REG_BKSV(2):
+	case ADV7533_REG_BKSV(3):
+	case ADV7533_REG_BKSV(4):
+	case ADV7533_REG_DDC_STATUS:
+	case ADV7533_REG_BSTATUS(0):
+	case ADV7533_REG_BSTATUS(1):
+	case ADV7533_REG_CHIP_ID_HIGH:
+	case ADV7533_REG_CHIP_ID_LOW:
+		ret = 1;
+		break;
+	default:
+		ret = 0;
+		break;
+	}
+
+	return ret ? true : false;
+}
+
+static const struct regmap_config adv75xx_regmap_config = {
+	.name = "adv75xx",
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = 0xff,
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults_raw = adv75xx_register_defaults,
+	.num_reg_defaults_raw = ARRAY_SIZE(adv75xx_register_defaults),
+	.volatile_reg = adv7511_register_volatile,
+};
+
+static const struct regmap_config adv7533_cec_regmap_config = {
+	.name = "adv7533_cec",
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = 0xff,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+static const struct regmap_config adv7533_packet_regmap_config = {
+	.name = "adv7533_packet",
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = 0xff,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+/* -----------------------------------------------------------------------------
+ * Hardware configuration
+ */
+static void adv75xx_set_colormap(struct adi_hdmi *adv75xx, bool enable,
+				 const u16 *coeff, unsigned int scaling_factor)
+{
+	unsigned int i;
+
+	HISI_FB_INFO("+.\n");
+
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_CSC_UPPER(1),
+			   ADV7533_CSC_UPDATE_MODE, ADV7533_CSC_UPDATE_MODE);
+
+	if (enable) {
+		for (i = 0; i < 12; ++i) {
+			regmap_update_bits(adv75xx->regmap,
+					   ADV7533_REG_CSC_UPPER(i),
+					   0x1f, coeff[i] >> 8);
+			regmap_write(adv75xx->regmap,
+				     ADV7533_REG_CSC_LOWER(i), coeff[i] & 0xff);
+		}
+	}
+
+	if (enable)
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_CSC_UPPER(0),
+				   0xe0, 0x80 | (scaling_factor << 5));
+	else
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_CSC_UPPER(0),
+				   0x80, 0x00);
+
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_CSC_UPPER(1),
+			   ADV7533_CSC_UPDATE_MODE, 0);
+
+	HISI_FB_INFO("-.\n");
+}
+
+int adv75xx_packet_enable(struct adi_hdmi *adv75xx, unsigned int packet)
+{
+	HISI_FB_INFO("+.\n");
+
+	if (packet & 0xff)
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_PACKET_ENABLE0,
+				   packet, 0xff);
+
+	if (packet & 0xff00) {
+		packet >>= 8;
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_PACKET_ENABLE1,
+				   packet, 0xff);
+	}
+
+	HISI_FB_INFO("-.\n");
+
+	return 0;
+}
+
+int adv75xx_packet_disable(struct adi_hdmi *adv75xx, unsigned int packet)
+{
+	HISI_FB_INFO("+.\n");
+
+	if (packet & 0xff)
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_PACKET_ENABLE0,
+				   packet, 0x00);
+
+	if (packet & 0xff00) {
+		packet >>= 8;
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_PACKET_ENABLE1,
+				   packet, 0x00);
+	}
+
+	HISI_FB_INFO("-.\n");
+
+	return 0;
+}
+
+/* Coefficients for adv75xx color space conversion */
+static const uint16_t adv75xx_csc_ycbcr_to_rgb[] = {
+	0x0734, 0x04ad, 0x0000, 0x1c1b,
+	0x1ddc, 0x04ad, 0x1f24, 0x0135,
+	0x0000, 0x04ad, 0x087c, 0x1b77,
+};
+
+static void adv75xx_set_config_csc(struct adi_hdmi *adv75xx, bool rgb)
+{
+	struct adv75xx_video_config config;
+	bool output_format_422, output_format_ycbcr;
+	unsigned int mode;
+	uint8_t infoframe[17];
+
+	HISI_FB_INFO("+.\n");
+
+	if (adv75xx->edid)
+		config.hdmi_mode = true;
+	else
+		config.hdmi_mode = false;
+
+	config.avi_infoframe.scan_mode = HDMI_SCAN_MODE_UNDERSCAN;
+
+	HISI_FB_INFO("adv75xx->rgb is %d\n", adv75xx->rgb);
+
+	if (rgb) {
+		config.csc_enable = false;
+		config.avi_infoframe.colorspace = HDMI_COLORSPACE_RGB;
+	} else {
+		config.csc_scaling_factor = ADV75xx_CSC_SCALING_4;
+		config.csc_coefficents = adv75xx_csc_ycbcr_to_rgb;
+	}
+
+	HISI_FB_INFO("config.avi_infoframe.colorspace = %d\n",
+		     config.avi_infoframe.colorspace);
+
+	if (config.hdmi_mode) {
+		mode = ADV7533_HDMI_CFG_MODE_HDMI;
+
+		switch (config.avi_infoframe.colorspace) {
+		case HDMI_COLORSPACE_YUV444:
+			output_format_422 = false;
+			output_format_ycbcr = true;
+			break;
+		case HDMI_COLORSPACE_YUV422:
+			output_format_422 = true;
+			output_format_ycbcr = true;
+			break;
+		default:
+			output_format_422 = false;
+			output_format_ycbcr = false;
+			break;
+		}
+	} else {
+		mode = ADV7533_HDMI_CFG_MODE_DVI;
+		output_format_422 = false;
+		output_format_ycbcr = false;
+	}
+
+	adv75xx_packet_disable(adv75xx, ADV7533_PACKET_ENABLE_AVI_INFOFRAME);
+
+	adv75xx_set_colormap(adv75xx, config.csc_enable,
+			     config.csc_coefficents, config.csc_scaling_factor);
+
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_VIDEO_INPUT_CFG1, 0x81,
+			   (output_format_422 << 7) | output_format_ycbcr);
+
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_HDCP_HDMI_CFG,
+			   ADV7533_HDMI_CFG_MODE_MASK, mode);
+
+	/* The AVI infoframe id is not configurable */
+	regmap_bulk_write(adv75xx->regmap, ADV7533_REG_AVI_INFOFRAME_VERSION,
+			  infoframe + 1, sizeof(infoframe) - 1);
+
+	adv75xx_packet_enable(adv75xx, ADV7533_PACKET_ENABLE_AVI_INFOFRAME);
+
+	HISI_FB_INFO("-.\n");
+}
+
+static void adv75xx_dsi_config_tgen(struct adi_hdmi *adv75xx)
+{
+	u8 clock_div_by_lanes[] = { 6, 4, 3 };	/* 2, 3, 4 lanes */
+	unsigned int hsw, hfp, hbp, vsw, vfp, vbp;
+
+	HISI_FB_INFO("+.\n");
+
+	hsw = adv75xx->mode->hsync_pulse_width;
+	hfp = adv75xx->mode->hsync_offset;
+	hbp = adv75xx->mode->htotal - adv75xx->mode->hsync_end;
+	vsw = adv75xx->mode->vsync_pulse_width;
+	vfp = adv75xx->mode->vsync_offset;
+	vbp = adv75xx->mode->vtotal - adv75xx->mode->vsync_end;
+
+	HISI_FB_INFO
+	    ("hsw = %d, hfp = %d, hbp = %d, vsw = %d, vfp= %d, vbp = %d\n",
+	     hsw, hfp, hbp, vsw, vfp, vbp);
+
+#ifdef TEST_COLORBAR_DISPLAY
+	/* set pixel clock auto mode */
+	regmap_write(adv75xx->regmap_cec, ADV7533_REG_CEC_PIXEL_CLOCK_DIV, 0x00);
+#else
+	/* set pixel clock divider mode */
+	regmap_write(adv75xx->regmap_cec, ADV7533_REG_CEC_PIXEL_CLOCK_DIV,
+		     clock_div_by_lanes[adv75xx->num_dsi_lanes - 2] << 3);
+#endif
+
+	HISI_FB_INFO("dsi->lanes = %d, htotal = %d, vtotal = %d\n",
+		     adv75xx->num_dsi_lanes, adv75xx->mode->htotal,
+		     adv75xx->mode->vtotal);
+
+	/* horizontal porch params */
+	regmap_write(adv75xx->regmap_cec, 0x28, adv75xx->mode->htotal >> 4);
+	regmap_write(adv75xx->regmap_cec, 0x29,
+		     (adv75xx->mode->htotal << 4) & 0xff);
+	regmap_write(adv75xx->regmap_cec, 0x2a, hsw >> 4);
+	regmap_write(adv75xx->regmap_cec, 0x2b, (hsw << 4) & 0xff);
+	regmap_write(adv75xx->regmap_cec, 0x2c, hfp >> 4);
+	regmap_write(adv75xx->regmap_cec, 0x2d, (hfp << 4) & 0xff);
+	regmap_write(adv75xx->regmap_cec, 0x2e, hbp >> 4);
+	regmap_write(adv75xx->regmap_cec, 0x2f, (hbp << 4) & 0xff);
+
+	/* vertical porch params */
+	regmap_write(adv75xx->regmap_cec, 0x30, adv75xx->mode->vtotal >> 4);
+	regmap_write(adv75xx->regmap_cec, 0x31,
+		     (adv75xx->mode->vtotal << 4) & 0xff);
+	regmap_write(adv75xx->regmap_cec, 0x32, vsw >> 4);
+	regmap_write(adv75xx->regmap_cec, 0x33, (vsw << 4) & 0xff);
+	regmap_write(adv75xx->regmap_cec, 0x34, vfp >> 4);
+	regmap_write(adv75xx->regmap_cec, 0x35, (vfp << 4) & 0xff);
+	regmap_write(adv75xx->regmap_cec, 0x36, vbp >> 4);
+	regmap_write(adv75xx->regmap_cec, 0x37, (vbp << 4) & 0xff);
+
+	/* 30Hz Low Refresh Rate (VIC Detection) */
+
+
+	HISI_FB_INFO("-.\n");
+}
+
+static void adv75xx_dsi_receiver_dpms(struct adi_hdmi *adv75xx)
+{
+	HISI_FB_INFO("+.\n");
+
+	if (adv75xx->type != ADV7533)
+		return;
+
+	if (adv75xx->powered) {
+		adv75xx_dsi_config_tgen(adv75xx);
+
+		/* set number of dsi lanes */
+		regmap_write(adv75xx->regmap_cec, ADV7533_REG_DSI_DATA_LANES,
+			     adv75xx->num_dsi_lanes << 4);
+
+#ifdef TEST_COLORBAR_DISPLAY
+		/* reset internal timing generator */
+		regmap_write(adv75xx->regmap_cec, 0x27, 0xcb);
+		regmap_write(adv75xx->regmap_cec, 0x27, 0x8b);
+		regmap_write(adv75xx->regmap_cec, 0x27, 0xcb);
+#else
+		/* disable internal timing generator */
+		regmap_write(adv75xx->regmap_cec, 0x27, 0x0b);
+#endif
+
+		/* 09-03 AVI Infoframe - RGB - 16-9 Aspect Ratio */
+		regmap_write(adv75xx->regmap, 0x55, 0x10);
+		regmap_write(adv75xx->regmap, 0x56, 0x28);
+
+		/* 04-04 GC Packet Enable */
+		regmap_write(adv75xx->regmap, 0x40, 0x80);
+
+		/* 04-06 GC Colour Depth - 24 Bit */
+		regmap_write(adv75xx->regmap, 0x4c, 0x04);
+
+		/* 04-09 Down Dither Output Colour Depth - 8 Bit (default) */
+		regmap_write(adv75xx->regmap, 0x49, 0x00);
+
+		/* 07-01 CEC Power Mode - Always Active */
+		regmap_write(adv75xx->regmap_cec, 0xbe, 0x3d);
+
+		/* enable hdmi */
+		regmap_write(adv75xx->regmap_cec, 0x03, 0x89);
+
+#ifdef TEST_COLORBAR_DISPLAY
+		/*enable test mode */
+		regmap_write(adv75xx->regmap_cec, 0x55, 0x80);
+#else
+		/* disable test mode */
+		regmap_write(adv75xx->regmap_cec, 0x55, 0x00);
+#endif
+		/* SPD */
+		{
+			static const unsigned char spd_if[] = {
+				0x83, 0x01, 25, 0x00,
+				'L', 'i', 'n', 'a', 'r', 'o', 0, 0,
+				'9', '6', 'b', 'o', 'a', 'r', 'd', 's',
+				':', 'H', 'i', 'k', 'e', 'y', 0, 0,
+			};
+			int n;
+
+			for (n = 0; n < sizeof(spd_if); n++)
+				regmap_write(adv75xx->regmap_packet, n,
+					     spd_if[n]);
+
+			/* enable send SPD */
+			regmap_update_bits(adv75xx->regmap, 0x40, BIT(6), BIT(6));
+		}
+
+		/* force audio */
+		/* hide Audio infoframe updates */
+		regmap_update_bits(adv75xx->regmap, 0x4a, BIT(5), BIT(5));
+
+		/* i2s, internal mclk, mclk-256 */
+		regmap_update_bits(adv75xx->regmap, 0x0a, 0x1f, 1);
+		regmap_update_bits(adv75xx->regmap, 0x0b, 0xe0, 0);
+		/* enable i2s, use i2s format, sample rate from i2s */
+		regmap_update_bits(adv75xx->regmap, 0x0c, 0xc7, BIT(2));
+		/* 16 bit audio */
+		regmap_update_bits(adv75xx->regmap, 0x0d, 0xff, 16);
+		/* 16-bit audio */
+		regmap_update_bits(adv75xx->regmap, 0x14, 0x0f, 2 << 4);
+		/* 48kHz */
+		regmap_update_bits(adv75xx->regmap, 0x15, 0xf0, 2 << 4);
+		/* enable N/CTS, enable Audio sample packets */
+		regmap_update_bits(adv75xx->regmap, 0x44, BIT(5), BIT(5));
+		/* N = 6144 */
+		regmap_write(adv75xx->regmap, 1, (6144 >> 16) & 0xf);
+		regmap_write(adv75xx->regmap, 2, (6144 >> 8) & 0xff);
+		regmap_write(adv75xx->regmap, 3, (6144) & 0xff);
+		/* automatic cts */
+		regmap_update_bits(adv75xx->regmap, 0x0a, BIT(7), 0);
+		/* enable N/CTS */
+		regmap_update_bits(adv75xx->regmap, 0x44, BIT(6), BIT(6));
+		/* not copyrighted */
+		regmap_update_bits(adv75xx->regmap, 0x12, BIT(5), BIT(5));
+
+		/* left source */
+		regmap_update_bits(adv75xx->regmap, 0x0e, 7 << 3, 0);
+		/* right source */
+		regmap_update_bits(adv75xx->regmap, 0x0e, 7 << 0, 1);
+		/* number of channels: sect 4.5.4: set to 0 */
+		regmap_update_bits(adv75xx->regmap, 0x73, 7, 1);
+		/* number of channels: sect 4.5.4: set to 0 */
+		regmap_update_bits(adv75xx->regmap, 0x73, 0xf0, 1 << 4);
+		/* sample rate: 48kHz */
+		regmap_update_bits(adv75xx->regmap, 0x74, 7 << 2, 3 << 2);
+		/* channel allocation reg: sect 4.5.4: set to 0 */
+		regmap_update_bits(adv75xx->regmap, 0x76, 0xff, 0);
+		/* enable audio infoframes */
+		regmap_update_bits(adv75xx->regmap, 0x44, BIT(3), BIT(3));
+
+		/* AV mute disable */
+		regmap_update_bits(adv75xx->regmap, 0x4b, BIT(7) | BIT(6), BIT(7));
+
+		/* use Audio infoframe updated info */
+		regmap_update_bits(adv75xx->regmap, 0x4a, BIT(5), 0);
+	} else {
+		regmap_write(adv75xx->regmap_cec, 0x03, 0x0b);
+		regmap_write(adv75xx->regmap_cec, 0x27, 0x0b);
+	}
+
+	HISI_FB_INFO("-.\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Interrupt and hotplug detection
+ */
+
+#if HPD_ENABLE
+static bool adv75xx_hpd(struct adi_hdmi *adv75xx)
+{
+	unsigned int irq0;
+	int ret;
+
+	HISI_FB_INFO("+.\n");
+
+	ret = regmap_read(adv75xx->regmap, ADV7533_REG_INT(0), &irq0);
+	if (ret < 0)
+		return false;
+
+	HISI_FB_INFO("irq0 = 0x%x\n", irq0);
+
+	if (irq0 & ADV7533_INT0_HDP) {
+		HISI_FB_INFO("HPD interrupt detected!\n");
+		regmap_write(adv75xx->regmap, ADV7533_REG_INT(0),
+			     ADV7533_INT0_HDP);
+		return true;
+	}
+
+	HISI_FB_INFO("-.\n");
+
+	return false;
+}
+#endif
+
+static int adv75xx_irq_process(struct adi_hdmi *adv75xx, bool process_hpd)
+{
+	unsigned int irq0, irq1;
+	int ret;
+
+	HISI_FB_INFO("+.\n");
+
+	ret = regmap_read(adv75xx->regmap, ADV7533_REG_INT(0), &irq0);
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_read(adv75xx->regmap, ADV7533_REG_INT(1), &irq1);
+	if (ret < 0)
+		return ret;
+
+	regmap_write(adv75xx->regmap, ADV7533_REG_INT(0), irq0);
+	regmap_write(adv75xx->regmap, ADV7533_REG_INT(1), irq1);
+
+	HISI_FB_INFO("adv7511_irq_process --> irq0 = 0x%x \n", irq0);
+	HISI_FB_INFO("adv7511_irq_process --> irq1 = 0x%x \n", irq1);
+
+	if (irq0 & ADV7533_INT0_EDID_READY || irq1 & ADV7533_INT1_DDC_ERROR) {
+		adv75xx->edid_read = true;
+		if (adv75xx->i2c_main->irq)
+			HISI_FB_INFO("adv7511_irq_process -->get i2c_main irq \n");
+
+		wake_up_all(&adv75xx->wq);
+	}
+
+	HISI_FB_INFO("-.\n");
+
+	return 0;
+}
+
+static irqreturn_t adv75xx_irq_handler(int irq, void *devid)
+{
+	struct adi_hdmi *adv75xx = devid;
+	int ret;
+
+	HISI_FB_INFO("+.\n");
+
+	ret = adv75xx_irq_process(adv75xx, true);
+
+	HISI_FB_INFO("-.\n");
+
+	return ret < 0 ? IRQ_NONE : IRQ_HANDLED;
+}
+
+/* -----------------------------------------------------------------------------
+ * EDID retrieval
+ */
+
+static int adv75xx_wait_for_edid(struct adi_hdmi *adv75xx, int timeout)
+{
+	int ret;
+
+	HISI_FB_INFO("+.\n");
+
+	if (adv75xx->i2c_main->irq) {
+		ret = wait_event_interruptible_timeout(adv75xx->wq,
+						       adv75xx->edid_read,
+						       msecs_to_jiffies(timeout));
+	} else {
+		for (; timeout > 0; timeout -= 25) {
+			ret = adv75xx_irq_process(adv75xx, false);
+			if (ret < 0)
+				break;
+
+			if (adv75xx->edid_read)
+				break;
+
+			msleep(25);
+		}
+	}
+
+	HISI_FB_INFO("-.\n");
+
+	return adv75xx->edid_read ? 0 : -EIO;
+}
+
+static void print_edid_info(u8 *block)
+{
+	int step, count;
+
+	count = 0x0;
+	while (count < EDID_LENGTH) {
+		step = 0;
+		do {
+			if (step = 0) {
+				HISI_FB_INFO("------ edid[%d]: 0x%2x \t", count,
+					     block[count]);
+			} else {
+				HISI_FB_INFO(" 0x%2x \t", block[count]);
+			}
+			step++;
+			count++;
+		} while (step < 8);
+
+		HISI_FB_INFO("\n");
+	}
+}
+
+struct hisi_display_mode *hisi_set_mode_info(void)
+{
+	struct hisi_display_mode *mode;
+	unsigned int hsw, hfp, hbp, vsw, vfp, vbp;
+
+	mode = kzalloc(sizeof(struct hisi_display_mode), GFP_KERNEL);
+	if (!mode)
+		return NULL;
+
+	mode->width_mm = 160 * 100;
+	mode->height_mm = 90 * 100;
+	mode->clock = 148500;
+	mode->hdisplay = 1920;
+	mode->vdisplay = 1080;
+	mode->hsync_offset = 88;
+	mode->hsync_pulse_width = 44;
+	mode->hsync_start = 2008;
+	mode->hsync_end = 2052;
+	mode->htotal = 2200;
+
+	mode->vsync_offset = 4;
+	mode->vsync_pulse_width = 5;
+	mode->vsync_start = 1084;
+	mode->vsync_end = 1089;
+	mode->vtotal = 1125;
+
+	hsw = mode->hsync_pulse_width;
+	hfp = mode->hsync_offset;
+	hbp = mode->htotal - mode->hsync_end;
+	vsw = mode->vsync_pulse_width;
+	vfp = mode->vsync_offset;
+	vbp = mode->vtotal - mode->vsync_end;
+
+	HISI_FB_INFO("The pixel clock is %d!!\n", mode->clock);
+	HISI_FB_INFO("The resolution is %d x %d !!\n", mode->hdisplay,
+		     mode->vdisplay);
+	HISI_FB_INFO
+	    ("hsw = %d, hfp = %d, hbp = %d, vsw = %d, vfp= %d, vbp = %d\n",
+	     hsw, hfp, hbp, vsw, vfp, vbp);
+
+
+	return mode;
+}
+
+struct hisi_display_mode *hisi_parse_edid_base_info(u8 *block)
+{
+	struct hisi_display_mode *mode;
+	char edid_vendor[3];
+	unsigned hblank;
+	unsigned vblank;
+	unsigned int hsw, hfp, hbp, vsw, vfp, vbp;
+
+	mode = kzalloc(sizeof(struct hisi_display_mode), GFP_KERNEL);
+	if (!mode)
+		return NULL;
+
+	edid_vendor[0] = ((block[8] & 0x7c) >> 2) + '@';
+	edid_vendor[1] = (((block[8] & 0x3) << 3) |
+			  ((block[1] & 0xe0) >> 5)) + '@';
+	edid_vendor[2] = (block[9] & 0x1f) + '@';
+
+	mode->width_mm = block[21] * 100;
+	mode->height_mm = block[22] * 100;
+	HISI_FB_INFO("The product vender is %c%c%c !!!\n", edid_vendor[0],
+		     edid_vendor[1], edid_vendor[2]);
+	HISI_FB_INFO
+	    ("The screen supported max width is %d cm, max height is %d cm !!\n",
+	     block[21], block[22]);
+	HISI_FB_INFO("The display gamma is %d !!\n", block[23]);
+	HISI_FB_INFO("The display is RGB or YCbCr is 0x%x !!\n",
+		     (block[24] & 0x18) >> 3);
+	/******** Detailed Timing Descriptor **********/
+	mode->clock = (block[55] << 8 | block[54]) * 10;
+	mode->hdisplay = ((block[58] & 0xf0) << 4) | block[56];
+	hblank = ((block[58] & 0x0f) << 8) | block[57];
+	mode->vdisplay = ((block[61] & 0xf0) << 4) | block[59];
+	vblank = ((block[61] & 0x0f) << 8) | block[60];
+	mode->hsync_offset = block[62];
+	mode->hsync_pulse_width = block[63];
+	mode->vsync_offset = (block[64] & 0xf0) >> 4;
+	mode->vsync_pulse_width = block[64] & 0x0f;
+
+	mode->hsync_start = mode->hdisplay + mode->hsync_offset;
+	mode->hsync_end = mode->hsync_start + mode->hsync_pulse_width;
+	mode->htotal = mode->hdisplay + hblank;
+	mode->vsync_start = mode->vdisplay + mode->vsync_offset;
+	mode->vsync_end = mode->vsync_start + mode->vsync_pulse_width;
+	mode->vtotal = mode->vdisplay + vblank;
+
+	hsw = mode->hsync_pulse_width;
+	hfp = mode->hsync_offset;
+	hbp = mode->htotal - mode->hsync_end;
+	vsw = mode->vsync_pulse_width;
+	vfp = mode->vsync_offset;
+	vbp = mode->vtotal - mode->vsync_end;
+
+	HISI_FB_INFO("The pixel clock is %d!!\n", mode->clock);
+	HISI_FB_INFO("The resolution is %d x %d !!\n", mode->hdisplay,
+		     mode->vdisplay);
+	HISI_FB_INFO
+	    ("hsw = %d, hfp = %d, hbp = %d, vsw = %d, vfp= %d, vbp = %d\n",
+	     hsw, hfp, hbp, vsw, vfp, vbp);
+
+
+	return mode;
+}
+
+static int adv75xx_get_edid_block(void *data, u8 *buf, unsigned int block,
+				  size_t len)
+{
+	struct adi_hdmi *adv75xx = data;
+	struct i2c_msg xfer[2];
+	uint8_t offset, edid_buf[256];
+	unsigned int i;
+	int ret;
+
+	if (len > EDID_LENGTH)
+		return -EINVAL;
+
+	HISI_FB_INFO("+.\n");
+
+	if (adv75xx->current_edid_segment != block) {
+		unsigned int status;
+
+		ret = regmap_read(adv75xx->regmap, ADV7533_REG_DDC_STATUS,
+				  &status);
+		if (ret < 0)
+			return ret;
+
+		if (status != IDLE) {
+			adv75xx->edid_read = false;
+			regmap_write(adv75xx->regmap, ADV7533_REG_EDID_SEGMENT,
+				     block);
+			ret = adv75xx_wait_for_edid(adv75xx, 200);
+			if (ret < 0)
+				return ret;
+		}
+
+		/* Break this apart, hopefully more I2C controllers will
+		 * support 64 byte transfers than 256 byte transfers
+		 */
+
+		xfer[0].addr = adv75xx->i2c_edid->addr;
+		xfer[0].flags = 0;
+		xfer[0].len = 1;
+		xfer[0].buf = &offset;
+		xfer[1].addr = adv75xx->i2c_edid->addr;
+		xfer[1].flags = I2C_M_RD;
+		xfer[1].len = 64;
+		xfer[1].buf = edid_buf;
+
+		offset = 0;
+
+		for (i = 0; i < 4; ++i) {
+			ret = i2c_transfer(adv75xx->i2c_edid->adapter, xfer,
+					   ARRAY_SIZE(xfer));
+			if (ret < 0)
+				return ret;
+			else if (ret != 2)
+				return -EIO;
+
+			xfer[1].buf += 64;
+			offset += 64;
+		}
+
+		adv75xx->current_edid_segment = block;
+	}
+
+	if (block % 2 = 0)
+		memcpy(buf, edid_buf, len);
+	else
+		memcpy(buf, edid_buf + EDID_LENGTH, len);
+
+	HISI_FB_INFO("-.\n");
+
+	return 0;
+}
+
+static bool edid_is_zero(const u8 *in_edid, int length)
+{
+	if (memchr_inv(in_edid, 0, length))
+		return false;
+
+	return true;
+}
+
+/**
+ * hisi_do_get_edid - get EDID data using a custom EDID block read function
+ * @get_edid_block: EDID block read function
+ * @data: private data passed to the block read function
+ *
+ * When the I2C adapter connected to the DDC bus is hidden behind a device that
+ * exposes a different interface to read EDID blocks this function can be used
+ * to get EDID data using a custom block read function.
+ *
+ * As in the general case the DDC bus is accessible by the kernel at the I2C
+ * level, drivers must make all reasonable efforts to expose it as an I2C
+ * adapter and use drm_get_edid() instead of abusing this function.
+ *
+ * Return: Pointer to valid EDID or NULL if we couldn't find any.
+ */
+struct edid *hisi_do_get_edid(int (*get_edid_block) (void *data, u8 *buf,
+						     unsigned int block,
+						     size_t len), void *data)
+{
+	u8 *block;
+	bool print_bad_edid = true;
+
+	HISI_FB_INFO("+.\n");
+
+	if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) = NULL)
+		return NULL;
+
+	HISI_FB_INFO("EDID_LENGTH = %d \n", EDID_LENGTH);
+	/* base block fetch */
+	if (get_edid_block(data, block, 0, EDID_LENGTH))
+		goto out;
+
+	if (edid_is_zero(block, EDID_LENGTH))
+		goto carp;
+
+	HISI_FB_INFO("edid_block read success!!!\n");
+
+	print_edid_info(block);
+
+	return (struct edid *)block;
+
+ carp:
+	if (print_bad_edid)
+		HISI_FB_ERR("EDID block invalid.\n");
+ out:
+	kfree(block);
+	return NULL;
+}
+
+struct hisi_display_mode *adv75xx_get_modes(struct adi_hdmi *adv75xx)
+{
+	struct edid *edid;
+	struct hisi_display_mode *mode;
+
+	HISI_FB_INFO("+.\n");
+
+	/* Reading the EDID only works if the device is powered */
+	if (!adv75xx->powered) {
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_POWER2,
+				ADV7533_REG_POWER2_HDP_SRC_MASK,
+				ADV7533_REG_POWER2_HDP_SRC_NONE);	/* 0xc0 */
+
+		regmap_write(adv75xx->regmap, ADV7533_REG_INT(0),
+				ADV7533_INT0_EDID_READY);
+		regmap_write(adv75xx->regmap, ADV7533_REG_INT(1),
+				ADV7533_INT1_DDC_ERROR);
+
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_POWER,
+				ADV7533_POWER_POWER_DOWN, 0);	/* 0x41 0x10 */
+
+		adv75xx->current_edid_segment = -1;
+		/* wait some time for edid is ready */
+		msleep(200);
+	}
+
+	edid = hisi_do_get_edid(adv75xx_get_edid_block, adv75xx);
+
+	if (!adv75xx->powered)
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_POWER,
+				   ADV7533_POWER_POWER_DOWN,
+				   ADV7533_POWER_POWER_DOWN);
+
+	kfree(adv75xx->edid);
+	adv75xx->edid = edid;
+	if (!edid) {
+		HISI_FB_ERR("Fail to get really edid info !!!\n");
+		mode = hisi_set_mode_info();
+		return mode;
+	}
+
+	mode = hisi_parse_edid_base_info((u8 *) adv75xx->edid);
+
+	adv75xx_set_config_csc(adv75xx, adv75xx->rgb);
+
+	HISI_FB_INFO("-.\n");
+
+	return mode;
+}
+
+/*=============================*/
+static enum connector_status adv75xx_detect(struct adi_hdmi *adv75xx)
+{
+	enum connector_status status;
+	unsigned int val;
+#if HPD_ENABLE
+	bool hpd;
+#endif
+	int ret;
+
+	HISI_FB_INFO("+.\n");
+
+	ret = regmap_read(adv75xx->regmap, ADV7533_REG_STATUS, &val);
+	if (ret < 0) {
+		HISI_FB_INFO("HDMI connector status is disconnected !!!\n");
+		return connector_status_disconnected;
+	}
+
+	if (val & ADV7533_STATUS_HPD)
+		status = connector_status_connected;
+	else
+		status = connector_status_disconnected;
+
+#if HPD_ENABLE
+	hpd = adv75xx_hpd(adv75xx);
+
+	/* The chip resets itself when the cable is disconnected, so in case
+	 * there is a pending HPD interrupt and the cable is connected there was
+	 * at least one transition from disconnected to connected and the chip
+	 * has to be reinitialized. */
+	if (status = connector_status_connected && hpd && adv75xx->powered) {
+		regcache_mark_dirty(adv75xx->regmap);
+		adv75xx_power_on(adv75xx);
+		adv75xx_get_modes(adv75xx);
+		if (adv75xx->status = connector_status_connected)
+			status = connector_status_disconnected;
+	} else {
+		/* Renable HDP sensing */
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_POWER2,
+				   ADV7533_REG_POWER2_HDP_SRC_MASK,
+				   ADV7533_REG_POWER2_HDP_SRC_BOTH);
+	}
+#endif
+
+	adv75xx->status = status;
+
+	HISI_FB_INFO("adv7511->status = %d <1-connected,2-disconnected>\n",
+		     status);
+	HISI_FB_INFO("-.\n");
+
+	return status;
+}
+
+/**
+ * mode_vrefresh - get the vrefresh of a mode
+ * @mode: mode
+ *
+ * Returns:
+ * @modes's vrefresh rate in Hz, rounded to the nearest integer. Calculates the
+ * value first if it is not yet set.
+ */
+static int mode_vrefresh(const struct hisi_display_mode *mode)
+{
+	int refresh = 0;
+	unsigned int calc_val;
+
+	if (mode->vrefresh > 0)
+		refresh = mode->vrefresh;
+	else if (mode->htotal > 0 && mode->vtotal > 0) {
+		int vtotal;
+		vtotal = mode->vtotal;
+		/* work out vrefresh the value will be x1000 */
+		calc_val = (mode->clock * 1000);
+		calc_val /= mode->htotal;
+		refresh = (calc_val + vtotal / 2) / vtotal;
+	}
+	return refresh;
+}
+
+static int adv75xx_mode_valid(struct hisi_display_mode *mode)
+{
+	if (NULL = mode) {
+		HISI_FB_ERR("mode is null\n");
+		return MODE_NOMODE;
+	}
+
+	if (mode->clock > 165000)
+		return MODE_CLOCK_HIGH;
+	/*
+	 * some work well modes which want to put in the front of the mode list.
+	 */
+	HISI_FB_INFO("Checking mode %ix%i@%i clock: %i...",
+		     mode->hdisplay, mode->vdisplay, mode_vrefresh(mode),
+		     mode->clock);
+	if ((mode->hdisplay = 1920 && mode->vdisplay = 1080
+	     	&& mode->clock = 148500)
+		|| (mode->hdisplay = 1280 && mode->vdisplay = 800
+			&& mode->clock = 83496)
+		|| (mode->hdisplay = 1280 && mode->vdisplay = 720
+			&& mode->clock = 74440)
+		|| (mode->hdisplay = 1280 && mode->vdisplay = 720
+			&& mode->clock = 74250)
+	    || (mode->hdisplay = 1024 && mode->vdisplay = 768
+			&& mode->clock = 75000)
+		|| (mode->hdisplay = 1024 && mode->vdisplay = 768
+			&& mode->clock = 81833)
+	    || (mode->hdisplay = 800 && mode->vdisplay = 600
+			&& mode->clock = 40000)) {
+		HISI_FB_INFO("OK\n");
+		return MODE_OK;
+	}
+	HISI_FB_INFO("BAD\n");
+
+	return MODE_BAD;
+}
+
+static void adv75xx_mode_set(struct adi_hdmi *adv75xx,
+			     struct hisi_display_mode *mode)
+{
+	unsigned int low_refresh_rate;
+	unsigned int hsync_polarity = 0;
+	unsigned int vsync_polarity = 0;
+
+	HISI_FB_INFO("+.\n");
+
+	if (adv75xx->embedded_sync) {
+		unsigned int hsync_offset, hsync_len;
+		unsigned int vsync_offset, vsync_len;
+
+		hsync_offset = mode->hsync_offset;
+		vsync_offset = mode->vsync_offset;
+		hsync_len = mode->hsync_end - mode->hsync_start;
+		vsync_len = mode->vsync_end - mode->vsync_start;
+
+		/* The hardware vsync generator has a off-by-one bug */
+		vsync_offset += 1;
+
+		regmap_write(adv75xx->regmap, ADV7533_REG_HSYNC_PLACEMENT_MSB,
+			     ((hsync_offset >> 10) & 0x7) << 5);
+		regmap_write(adv75xx->regmap, ADV7533_REG_SYNC_DECODER(0),
+			     (hsync_offset >> 2) & 0xff);
+		regmap_write(adv75xx->regmap, ADV7533_REG_SYNC_DECODER(1),
+			     ((hsync_offset & 0x3) << 6) |
+			     ((hsync_len >> 4) & 0x3f));
+		regmap_write(adv75xx->regmap, ADV7533_REG_SYNC_DECODER(2),
+			     ((hsync_len & 0xf) << 4) |
+			     ((vsync_offset >> 6) & 0xf));
+		regmap_write(adv75xx->regmap, ADV7533_REG_SYNC_DECODER(3),
+			     ((vsync_offset & 0x3f) << 2) |
+			     ((vsync_len >> 8) & 0x3));
+		regmap_write(adv75xx->regmap, ADV7533_REG_SYNC_DECODER(4),
+			     vsync_len & 0xff);
+
+		hsync_polarity = !(mode->flags & MODE_FLAG_PHSYNC);
+		vsync_polarity = !(mode->flags & MODE_FLAG_PVSYNC);
+	} else {
+		/**
+		 * If the input signal is always low or always high we want to
+		 * invert or let it passthrough depending on the polarity of the
+		 * current mode.
+		 **/
+		adv75xx->hsync_polarity = ADV7533_SYNC_POLARITY_PASSTHROUGH;
+		adv75xx->vsync_polarity = ADV7533_SYNC_POLARITY_PASSTHROUGH;
+
+		hsync_polarity = adv75xx->hsync_polarity;
+		vsync_polarity = adv75xx->vsync_polarity;
+	}
+	mode->vrefresh = mode_vrefresh(mode);
+	HISI_FB_INFO("hsync_polarity = %d; vsync_polarity = %d\n",
+		     hsync_polarity, vsync_polarity);
+	HISI_FB_INFO("mode->vrefresh = %d \n", mode->vrefresh);
+
+	if (mode->vrefresh <= 24000)
+		low_refresh_rate = ADV7533_LOW_REFRESH_RATE_24HZ;
+	else if (mode->vrefresh <= 25000)
+		low_refresh_rate = ADV7533_LOW_REFRESH_RATE_25HZ;
+	else if (mode->vrefresh <= 30000)
+		low_refresh_rate = ADV7533_LOW_REFRESH_RATE_30HZ;
+	else
+		low_refresh_rate = ADV7533_LOW_REFRESH_RATE_NONE;
+
+	HISI_FB_INFO("low_refresh_rate = %d \n", low_refresh_rate);
+
+	regmap_update_bits(adv75xx->regmap, 0xfb, 0x6, low_refresh_rate << 1);
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_SYNC_POLARITY,
+			   0x60, (vsync_polarity << 6) | (hsync_polarity << 5));
+
+	/*
+	 * TODO Test first order 4:2:2 to 4:4:4 up conversion method, which is
+	 * supposed to give better results.
+	 */
+
+	adv75xx->f_tmds = mode->clock;
+
+	HISI_FB_INFO("-.\n");
+}
+
+static void adv75xx_power_on(struct adi_hdmi *adv75xx)
+{
+	HISI_FB_INFO("+.\n");
+
+	adv75xx->current_edid_segment = -1;
+
+	regmap_write(adv75xx->regmap, ADV7533_REG_INT(0),
+		     ADV7533_INT0_EDID_READY);
+	regmap_write(adv75xx->regmap, ADV7533_REG_INT(1),
+		     ADV7533_INT1_DDC_ERROR);
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_POWER,
+			   ADV7533_POWER_POWER_DOWN, 0);
+
+	/*
+	 * Per spec it is allowed to pulse the HDP signal to indicate that the
+	 * EDID information has changed. Some monitors do this when they wakeup
+	 * from standby or are enabled. When the HDP goes low the adv7511 is
+	 * reset and the outputs are disabled which might cause the monitor to
+	 * go to standby again. To avoid this we ignore the HDP pin for the
+	 * first few seconds after enabling the output.
+	 */
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_POWER2,
+			   ADV7533_REG_POWER2_HDP_SRC_MASK,
+			   ADV7533_REG_POWER2_HDP_SRC_NONE);
+
+	/*
+	 * Most of the registers are reset during power down or when HPD is low.
+	 */
+	regcache_sync(adv75xx->regmap);
+
+	regmap_register_patch(adv75xx->regmap_cec,
+			      adv7533_cec_fixed_registers,
+			      ARRAY_SIZE(adv7533_cec_fixed_registers));
+	adv75xx->powered = true;
+
+	adv75xx_dsi_receiver_dpms(adv75xx);
+
+	HISI_FB_INFO("-.\n");
+}
+
+static void adv75xx_power_off(struct adi_hdmi *adv75xx)
+{
+	HISI_FB_INFO("+.\n");
+
+	/* TODO: setup additional power down modes */
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_POWER,
+			   ADV7533_POWER_POWER_DOWN,
+			   ADV7533_POWER_POWER_DOWN);
+	regcache_mark_dirty(adv75xx->regmap);
+
+	adv75xx->powered = false;
+
+	adv75xx_dsi_receiver_dpms(adv75xx);
+
+	HISI_FB_INFO("-.\n");
+}
+
+/* =============================*/
+static int adv7533_init_regulators(struct adi_hdmi *adv75xx)
+{
+	int ret;
+	struct device *dev = &adv75xx->i2c_main->dev;
+
+	adv75xx->vdd = devm_regulator_get(dev, "vdd");
+	if (IS_ERR(adv75xx->vdd)) {
+		ret = PTR_ERR(adv75xx->vdd);
+		dev_err(dev, "failed to get vdd regulator %d\n", ret);
+		return ret;
+	}
+
+	adv75xx->v1p2 = devm_regulator_get(dev, "v1p2");
+	if (IS_ERR(adv75xx->v1p2)) {
+		ret = PTR_ERR(adv75xx->v1p2);
+		dev_err(dev, "failed to get v1p2 regulator %d\n", ret);
+		return ret;
+	}
+
+	ret = regulator_set_voltage(adv75xx->vdd, 1800000, 1800000);
+	if (ret) {
+		dev_err(dev, "failed to set avdd voltage %d\n", ret);
+		return ret;
+	}
+
+	ret = regulator_set_voltage(adv75xx->v1p2, 1200000, 1200000);
+	if (ret) {
+		dev_err(dev, "failed to set v1p2 voltage %d\n", ret);
+		return ret;
+	}
+
+	/* keep the regulators always on */
+	ret = regulator_enable(adv75xx->vdd);
+	if (ret) {
+		dev_err(dev, "failed to enable vdd %d\n", ret);
+		return ret;
+	}
+
+	ret = regulator_enable(adv75xx->v1p2);
+	if (ret) {
+		dev_err(dev, "failed to enable v1p2 %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int adv7533_parse_dt(struct device_node *np, struct adi_hdmi *adv75xx)
+{
+	int ret;
+	u32 num_lanes;
+
+	ret = of_property_read_u32(np, "adi,dsi-lanes", &num_lanes);
+	if (ret) {
+		HISI_FB_WARNING("get 'adi,dsi-lanes' resource failed!\n");
+		return ret;
+	}
+
+	if (num_lanes < 1 || num_lanes > 4)
+		return -EINVAL;
+
+	adv75xx->num_dsi_lanes = num_lanes;
+
+	/* TODO: Check if these need to be parsed by DT or not */
+	adv75xx->rgb = true;
+	adv75xx->embedded_sync = false;
+
+	return 0;
+}
+
+static const int edid_i2c_addr = 0x7e;
+static const int packet_i2c_addr = 0x70;
+static const int cec_i2c_addr = 0x78;
+
+static const struct of_device_id adv75xx_of_ids[] = {
+	{.compatible = "adi,adv7511", .data = (void *)ADV7511},
+	{.compatible = "adi,adv7511w", .data = (void *)ADV7511},
+	{.compatible = "adi,adv7513", .data = (void *)ADV7511},
+	{.compatible = "adi,adv7533", .data = (void *)ADV7533},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, adv75xx_of_ids);
+
+static const struct i2c_device_id adv75xx_i2c_ids[] = {
+	{"adv7511", ADV7511},
+	{"adv7511w", ADV7511},
+	{"adv7513", ADV7511},
+	{"adv7533", ADV7533},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, adv75xx_i2c_ids);
+
+static struct adi_operation_funcs opt_funcs = {
+	.power_on = adv75xx_power_on,
+	.power_off = adv75xx_power_off,
+	.mode_set = adv75xx_mode_set,
+};
+
+static int adv75xx_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+{
+	struct adi_hdmi *adv75xx;
+	struct device *dev = &i2c->dev;
+	enum connector_status status;
+	struct hisi_display_mode *mode;
+	struct platform_device *hdmi_pdev = NULL;
+	unsigned int val;
+	int ret;
+
+	if (!dev) {
+		HISI_FB_ERR("dev is  NULL!\n");
+		return -ENOMEM;
+	}
+
+	adv75xx = devm_kzalloc(dev, sizeof(struct adi_hdmi), GFP_KERNEL);
+	if (!adv75xx) {
+		HISI_FB_ERR("adv75xx alloc  failed!\n");
+		return -ENOMEM;
+	}
+	adv75xx->powered = false;
+	adv75xx->status = connector_status_disconnected;
+
+	if (dev->of_node) {
+		const struct of_device_id *of_id;
+
+		of_id = of_match_node(adv75xx_of_ids, dev->of_node);
+		adv75xx->type = (enum adv75xx_type)of_id->data;
+	} else {
+		adv75xx->type = ADV7533;
+	}
+
+	ret = adv7533_parse_dt(dev->of_node, adv75xx);
+	if (ret) {
+		HISI_FB_ERR("parse dts error!\n");
+		goto err_return;
+	}
+
+	adv75xx->i2c_main = i2c;
+
+	if (adv75xx->type = ADV7533) {
+		ret = adv7533_init_regulators(adv75xx);	/* adv7533 vdd--1.8v  v1p2--1.2v */
+		if (ret)
+			return ret;
+	}
+
+	/*
+	 * The power down GPIO is optional. If present, toggle it from active(1) to
+	 * inactive(0) to wake up the encoder.
+	 */
+	adv75xx->gpio_pd = devm_gpiod_get_optional(dev, "pd", GPIOD_OUT_HIGH);
+	if (IS_ERR(adv75xx->gpio_pd)) {
+		HISI_FB_ERR("get gpio pd error!\n");
+		return PTR_ERR(adv75xx->gpio_pd);
+	}
+	HISI_FB_INFO("adv75xx->gpio_pd = %s!\n", adv75xx->gpio_pd->label);
+
+	if (adv75xx->gpio_pd) {
+		mdelay(5);
+		gpiod_set_value_cansleep(adv75xx->gpio_pd, 0);
+	}
+
+	adv75xx->regmap = devm_regmap_init_i2c(i2c, &adv75xx_regmap_config);
+	if (IS_ERR(adv75xx->regmap)) {
+		HISI_FB_ERR("regmap init i2c failed!\n");
+		return PTR_ERR(adv75xx->regmap);
+	}
+
+	ret = regmap_read(adv75xx->regmap, ADV7533_REG_CHIP_REVISION, &val);
+	if (ret) {
+		HISI_FB_ERR("regmap read failed, ret = %d!\n", ret);
+		goto err_return;
+	}
+	/* the corect val is 20. */
+	HISI_FB_INFO("%s of the Chip reversion is %d\n", dev_name(dev), val);
+	dev_err(dev, "Rev. %d\n", val);
+
+	ret = regmap_register_patch(adv75xx->regmap,
+				    adv7533_fixed_registers,
+				    ARRAY_SIZE(adv7533_fixed_registers));
+	if (ret) {
+		HISI_FB_ERR("regmap register failed!\n");
+		goto err_return;
+	}
+
+	regmap_write(adv75xx->regmap, ADV7533_REG_EDID_I2C_ADDR, edid_i2c_addr);
+	regmap_write(adv75xx->regmap, ADV7533_REG_PACKET_I2C_ADDR,
+		     packet_i2c_addr);
+	regmap_write(adv75xx->regmap, ADV7533_REG_CEC_I2C_ADDR, cec_i2c_addr);
+	adv75xx_packet_disable(adv75xx, 0xffff);
+
+	adv75xx->i2c_packet = i2c_new_dummy(i2c->adapter, packet_i2c_addr >> 1);
+	if (!adv75xx->i2c_packet) {
+		HISI_FB_ERR("i2c_new_dummy i2c_packet failed!\n");
+		return -ENOMEM;
+	}
+
+	adv75xx->i2c_edid = i2c_new_dummy(i2c->adapter, edid_i2c_addr >> 1);
+	if (!adv75xx->i2c_edid) {
+		HISI_FB_ERR("i2c_new_dummy i2c_edid failed!\n");
+		goto err_i2c_unregister_packet;
+	}
+
+	adv75xx->i2c_cec = i2c_new_dummy(i2c->adapter, cec_i2c_addr >> 1);
+	if (!adv75xx->i2c_cec) {
+		ret = -ENOMEM;
+		HISI_FB_ERR("i2c_new_dummy i2c_cec failed!\n");
+		goto err_i2c_unregister_edid;
+	}
+
+	adv75xx->regmap_cec = devm_regmap_init_i2c(adv75xx->i2c_cec,
+						   &adv7533_cec_regmap_config);
+	if (IS_ERR(adv75xx->regmap_cec)) {
+		ret = PTR_ERR(adv75xx->regmap_cec);
+		HISI_FB_ERR("devm_regmap_init_i2c regmap_cec failed!\n");
+		goto err_i2c_unregister_cec;
+	}
+
+	adv75xx->regmap_packet = devm_regmap_init_i2c(adv75xx->i2c_packet,
+						      &adv7533_packet_regmap_config);
+	if (IS_ERR(adv75xx->regmap_packet)) {
+		ret = PTR_ERR(adv75xx->regmap_packet);
+		HISI_FB_ERR("devm_regmap_init_i2c regmap_packet failed!\n");
+		goto err_i2c_unregister_cec;
+	}
+
+	if (adv75xx->type = ADV7533) {
+		ret = regmap_register_patch(adv75xx->regmap_cec,
+					    adv7533_cec_fixed_registers,
+					    ARRAY_SIZE(adv7533_cec_fixed_registers));
+		if (ret) {
+			HISI_FB_ERR
+			    ("regmap_register_patch cec_fixed_registers failed!\n");
+			goto err_return;
+		}
+	}
+
+	HISI_FB_INFO("i2c->irq = %d!\n", i2c->irq);
+	if (i2c->irq) {
+		init_waitqueue_head(&adv75xx->wq);
+		ret = devm_request_threaded_irq(dev, i2c->irq, NULL,
+						adv75xx_irq_handler,
+						IRQF_ONESHOT, dev_name(dev), adv75xx);
+		if (ret) {
+			HISI_FB_ERR("adv7511_irq_handler registers failed!\n");
+			goto err_i2c_unregister_cec;
+		}
+	}
+
+	/* CEC is unused for now */
+	regmap_write(adv75xx->regmap, ADV7533_REG_CEC_CTRL,
+		     ADV7533_CEC_CTRL_POWER_DOWN);
+
+	adv75xx_power_off(adv75xx);
+
+	i2c_set_clientdata(i2c, adv75xx);
+
+	/* adv7511_audio_init(dev); */
+	status = adv75xx_detect(adv75xx);
+	if (status != connector_status_connected) {
+		HISI_FB_ERR("adv75xx connector not connected !\n");
+	}
+
+	mode = adv75xx_get_modes(adv75xx);
+
+	ret = adv75xx_mode_valid(mode);
+	if (ret) {
+		HISI_FB_ERR("adv75xx not supported this mode !!\n");
+		kfree(mode);
+		mode = hisi_set_mode_info();
+	}
+	adv75xx->mode = mode;
+	adv75xx->opt_funcs = &opt_funcs;
+
+	hdmi_pdev +	    platform_device_alloc("adi_hdmi",
+				  (((uint32_t) PANEL_MIPI_VIDEO << 16) |
+				    (uint32_t) 1));
+	if (hdmi_pdev) {
+		if (platform_device_add_data
+		    (hdmi_pdev, adv75xx, sizeof(struct adi_hdmi))) {
+			HISI_FB_ERR("failed to platform_device_add_data!\n");
+			platform_device_put(hdmi_pdev);
+		}
+	}
+	HISI_FB_INFO("platform_device_add_data ok !\n");
+
+	/* set driver data */
+	platform_set_drvdata(hdmi_pdev, adv75xx);
+	if (platform_device_add(hdmi_pdev)) {
+		HISI_FB_ERR("platform_device_add failed!\n");
+		goto err_device_put;
+	}
+
+	return 0;
+
+ err_i2c_unregister_cec:
+	i2c_unregister_device(adv75xx->i2c_cec);
+ err_i2c_unregister_edid:
+	i2c_unregister_device(adv75xx->i2c_edid);
+ err_i2c_unregister_packet:
+	i2c_unregister_device(adv75xx->i2c_packet);
+ err_device_put:
+	platform_device_put(hdmi_pdev);
+ err_return:
+	kfree(adv75xx);
+	return ret;
+}
+
+static int adv75xx_remove(struct i2c_client *i2c)
+{
+	struct adi_hdmi *adv75xx = i2c_get_clientdata(i2c);
+
+	i2c_unregister_device(adv75xx->i2c_cec);
+	i2c_unregister_device(adv75xx->i2c_edid);
+
+	kfree(adv75xx->edid);
+	kfree(adv75xx->mode);
+	kfree(adv75xx);
+
+	return 0;
+}
+
+static struct i2c_driver adv75xx_driver = {
+	.driver = {
+		   .owner = THIS_MODULE,
+		   .name = "adv75xx",
+		   .of_match_table = adv75xx_of_ids,
+		   },
+	.id_table = adv75xx_i2c_ids,
+	.probe = adv75xx_probe,
+	.remove = adv75xx_remove,
+};
+
+static int __init adv75xx_init(void)
+{
+	int ret = 0;
+
+	ret = i2c_add_driver(&adv75xx_driver);
+	if (ret) {
+		HISI_FB_ERR("i2c_add_driver error!\n");
+	}
+	return ret;
+}
+
+module_init(adv75xx_init);
+
+static void __exit adv75xx_exit(void)
+{
+	i2c_del_driver(&adv75xx_driver);
+}
+
+module_exit(adv75xx_exit);
+
+MODULE_AUTHOR("Hisilicon Inc");
+MODULE_DESCRIPTION("ADV75XX HDMI transmitter driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/hisi/dss/hdmi/adv75xx.h b/drivers/video/fbdev/hisi/dss/hdmi/adv75xx.h
new file mode 100755
index 000000000000..d2f84d846271
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hdmi/adv75xx.h
@@ -0,0 +1,496 @@
+/**
+ *
+ *
+ **/
+
+#ifndef __ADV75XX_H__
+#define __ADV75XX_H__
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/hdmi.h>
+
+#include "../hisi_fb.h"
+
+#define DISPLAY_MODE_LEN	32
+
+#define ADV7533_REG_CHIP_REVISION		0x00
+#define ADV7533_REG_N0					0x01
+#define ADV7533_REG_N1					0x02
+#define ADV7533_REG_N2					0x03
+#define ADV7533_REG_SPDIF_FREQ			0x04
+#define ADV7533_REG_CTS_AUTOMATIC1		0x05
+#define ADV7533_REG_CTS_AUTOMATIC2		0x06
+#define ADV7533_REG_CTS_MANUAL0			0x07
+#define ADV7533_REG_CTS_MANUAL1			0x08
+#define ADV7533_REG_CTS_MANUAL2			0x09
+#define ADV7533_REG_AUDIO_SOURCE		0x0a
+#define ADV7533_REG_AUDIO_CONFIG		0x0b
+#define ADV7533_REG_I2S_CONFIG			0x0c
+#define ADV7533_REG_I2S_WIDTH			0x0d
+#define ADV7533_REG_AUDIO_SUB_SRC0		0x0e
+#define ADV7533_REG_AUDIO_SUB_SRC1		0x0f
+#define ADV7533_REG_AUDIO_SUB_SRC2		0x10
+#define ADV7533_REG_AUDIO_SUB_SRC3		0x11
+#define ADV7533_REG_AUDIO_CFG1			0x12
+#define ADV7533_REG_AUDIO_CFG2			0x13
+#define ADV7533_REG_AUDIO_CFG3			0x14
+#define ADV7533_REG_I2C_FREQ_ID_CFG		0x15
+#define ADV7533_REG_VIDEO_INPUT_CFG1		0x16
+#define ADV7533_REG_CEC_PIXEL_CLOCK_DIV		0x16
+#define ADV7533_REG_SYNC_POLARITY		0x17
+#define ADV7533_REG_DSI_DATA_LANES		0x1c
+#define ADV7533_REG_CSC_UPPER(x)		(0x18 + (x) * 2)
+#define ADV7533_REG_CSC_LOWER(x)		(0x19 + (x) * 2)
+#define ADV7533_REG_SYNC_DECODER(x)		(0x30 + (x))
+#define ADV7533_REG_DE_GENERATOR		(0x35 + (x))
+#define ADV7533_REG_PIXEL_REPETITION		0x3b
+#define ADV7533_REG_VIC_MANUAL			0x3c
+#define ADV7533_REG_VIC_SEND			0x3d
+#define ADV7533_REG_VIC_DETECTED		0x3e
+#define ADV7533_REG_AUX_VIC_DETECTED		0x3f
+#define ADV7533_REG_PACKET_ENABLE0		0x40
+#define ADV7533_REG_POWER			0x41
+#define ADV7533_REG_STATUS			0x42
+#define ADV7533_REG_EDID_I2C_ADDR		0x43
+#define ADV7533_REG_PACKET_ENABLE1		0x44
+#define ADV7533_REG_PACKET_I2C_ADDR		0x45
+#define ADV7533_REG_DSD_ENABLE			0x46
+#define ADV7533_REG_VIDEO_INPUT_CFG2		0x48
+#define ADV7533_REG_INFOFRAME_UPDATE		0x4a
+#define ADV7533_REG_GC(x)			(0x4b + (x))	/* 0x4b - 0x51 */
+#define ADV7533_REG_AVI_INFOFRAME_VERSION	0x52
+#define ADV7533_REG_AVI_INFOFRAME_LENGTH	0x53
+#define ADV7533_REG_AVI_INFOFRAME_CHECKSUM	0x54
+#define ADV7533_REG_AVI_INFOFRAME(x)		(0x55 + (x))	/* 0x55 - 0x6f */
+#define ADV7533_REG_AUDIO_INFOFRAME_VERSION	0x70
+#define ADV7533_REG_AUDIO_INFOFRAME_LENGTH	0x71
+#define ADV7533_REG_AUDIO_INFOFRAME_CHECKSUM	0x72
+#define ADV7533_REG_AUDIO_INFOFRAME(x)		(0x73 + (x))	/* 0x73 - 0x7c */
+#define ADV7533_REG_INT_ENABLE(x)		(0x94 + (x))
+#define ADV7533_REG_INT(x)			(0x96 + (x))
+#define ADV7533_REG_INPUT_CLK_DIV		0x9d
+#define ADV7533_REG_PLL_STATUS			0x9e
+#define ADV7533_REG_HDMI_POWER			0xa1
+#define ADV7533_REG_HDCP_HDMI_CFG		0xaf
+#define ADV7533_REG_AN(x)			(0xb0 + (x))	/* 0xb0 - 0xb7 */
+#define ADV7533_REG_HDCP_STATUS			0xb8
+#define ADV7533_REG_BCAPS			0xbe
+#define ADV7533_REG_BKSV(x)			(0xc0 + (x))	/* 0xc0 - 0xc3 */
+#define ADV7533_REG_EDID_SEGMENT		0xc4
+#define ADV7533_REG_DDC_STATUS			0xc8
+#define ADV7533_REG_EDID_READ_CTRL		0xc9
+#define ADV7533_REG_BSTATUS(x)			(0xca + (x))	/* 0xca - 0xcb */
+#define ADV7533_REG_TIMING_GEN_SEQ		0xd0
+#define ADV7533_REG_POWER2			0xd6
+#define ADV7533_REG_HSYNC_PLACEMENT_MSB		0xfa
+
+#define ADV7533_REG_SYNC_ADJUSTMENT(x)		(0xd7 + (x))	/* 0xd7 - 0xdc */
+#define ADV7533_REG_TMDS_CLOCK_INV		0xde
+#define ADV7533_REG_ARC_CTRL			0xdf
+#define ADV7533_REG_CEC_I2C_ADDR		0xe1
+#define ADV7533_REG_CEC_CTRL			0xe2
+#define ADV7533_REG_CHIP_ID_HIGH		0xf5
+#define ADV7533_REG_CHIP_ID_LOW			0xf6
+
+#define ADV7533_CSC_ENABLE			BIT(7)
+#define ADV7533_CSC_UPDATE_MODE			BIT(5)
+
+#define ADV7533_INT0_HDP			BIT(7)
+#define ADV7533_INT0_VSYNC			BIT(5)
+#define ADV7533_INT0_AUDIO_FIFO_FULL		BIT(4)
+#define ADV7533_INT0_EDID_READY			BIT(2)
+#define ADV7533_INT0_HDCP_AUTHENTICATED		BIT(1)
+
+#define ADV7533_INT1_DDC_ERROR			BIT(7)
+#define ADV7533_INT1_BKSV			BIT(6)
+#define ADV7533_INT1_CEC_TX_READY		BIT(5)
+#define ADV7533_INT1_CEC_TX_ARBIT_LOST		BIT(4)
+#define ADV7533_INT1_CEC_TX_RETRY_TIMEOUT	BIT(3)
+#define ADV7533_INT1_CEC_RX_READY3		BIT(2)
+#define ADV7533_INT1_CEC_RX_READY2		BIT(1)
+#define ADV7533_INT1_CEC_RX_READY1		BIT(0)
+
+#define ADV7533_ARC_CTRL_POWER_DOWN		BIT(0)
+
+#define ADV7533_CEC_CTRL_POWER_DOWN		BIT(0)
+
+#define ADV7533_POWER_POWER_DOWN		BIT(6)
+
+#define ADV7533_HDMI_CFG_MODE_MASK		0x2
+#define ADV7533_HDMI_CFG_MODE_DVI		0x0
+#define ADV7533_HDMI_CFG_MODE_HDMI		0x2
+
+#define ADV7533_AUDIO_SELECT_I2C		0x0
+#define ADV7533_AUDIO_SELECT_SPDIF		0x1
+#define ADV7533_AUDIO_SELECT_DSD		0x2
+#define ADV7533_AUDIO_SELECT_HBR		0x3
+#define ADV7533_AUDIO_SELECT_DST		0x4
+
+#define ADV7533_I2S_SAMPLE_LEN_16		0x2
+#define ADV7533_I2S_SAMPLE_LEN_20		0x3
+#define ADV7533_I2S_SAMPLE_LEN_18		0x4
+#define ADV7533_I2S_SAMPLE_LEN_22		0x5
+#define ADV7533_I2S_SAMPLE_LEN_19		0x8
+#define ADV7533_I2S_SAMPLE_LEN_23		0x9
+#define ADV7533_I2S_SAMPLE_LEN_24		0xb
+#define ADV7533_I2S_SAMPLE_LEN_17		0xc
+#define ADV7533_I2S_SAMPLE_LEN_21		0xd
+
+#define ADV7533_SAMPLE_FREQ_44100		0x0
+#define ADV7533_SAMPLE_FREQ_48000		0x2
+#define ADV7533_SAMPLE_FREQ_32000		0x3
+#define ADV7533_SAMPLE_FREQ_88200		0x8
+#define ADV7533_SAMPLE_FREQ_96000		0xa
+#define ADV7533_SAMPLE_FREQ_176400		0xc
+#define ADV7533_SAMPLE_FREQ_192000		0xe
+
+#define ADV7533_STATUS_POWER_DOWN_POLARITY	BIT(7)
+#define ADV7533_STATUS_HPD			BIT(6)
+#define ADV7533_STATUS_MONITOR_SENSE		BIT(5)
+#define ADV7533_STATUS_I2S_32BIT_MODE		BIT(3)
+
+#define ADV7533_PACKET_ENABLE_N_CTS		BIT(8+6)
+#define ADV7533_PACKET_ENABLE_AUDIO_SAMPLE	BIT(8+5)
+#define ADV7533_PACKET_ENABLE_AVI_INFOFRAME	BIT(8+4)
+#define ADV7533_PACKET_ENABLE_AUDIO_INFOFRAME	BIT(8+3)
+#define ADV7533_PACKET_ENABLE_GC		BIT(7)
+#define ADV7533_PACKET_ENABLE_SPD		BIT(6)
+#define ADV7533_PACKET_ENABLE_MPEG		BIT(5)
+#define ADV7533_PACKET_ENABLE_ACP		BIT(4)
+#define ADV7533_PACKET_ENABLE_ISRC		BIT(3)
+#define ADV7533_PACKET_ENABLE_GM		BIT(2)
+#define ADV7533_PACKET_ENABLE_SPARE2		BIT(1)
+#define ADV7533_PACKET_ENABLE_SPARE1		BIT(0)
+
+#define ADV7533_REG_POWER2_HDP_SRC_MASK		0xc0
+#define ADV7533_REG_POWER2_HDP_SRC_BOTH		0x00
+#define ADV7533_REG_POWER2_HDP_SRC_HDP		0x40
+#define ADV7533_REG_POWER2_HDP_SRC_CEC		0x80
+#define ADV7533_REG_POWER2_HDP_SRC_NONE		0xc0
+#define ADV7533_REG_POWER2_TDMS_ENABLE		BIT(4)
+#define ADV7533_REG_POWER2_GATE_INPUT_CLK	BIT(0)
+
+#define ADV7533_LOW_REFRESH_RATE_NONE		0x0
+#define ADV7533_LOW_REFRESH_RATE_24HZ		0x1
+#define ADV7533_LOW_REFRESH_RATE_25HZ		0x2
+#define ADV7533_LOW_REFRESH_RATE_30HZ		0x3
+
+#define ADV7533_AUDIO_CFG3_LEN_MASK		0x0f
+#define ADV7533_I2C_FREQ_ID_CFG_RATE_MASK	0xf0
+
+#define ADV7533_AUDIO_SOURCE_I2S		0
+#define ADV7533_AUDIO_SOURCE_SPDIF		1
+
+#define ADV7533_I2S_FORMAT_I2S			0
+#define ADV7533_I2S_FORMAT_RIGHT_J		1
+#define ADV7533_I2S_FORMAT_LEFT_J		2
+
+#define ADV7533_PACKET(p, x)	    ((p) * 0x20 + (x))
+#define ADV7533_PACKET_SDP(x)	    ADV7533_PACKET(0, x)
+#define ADV7533_PACKET_MPEG(x)	    ADV7533_PACKET(1, x)
+#define ADV7533_PACKET_ACP(x)	    ADV7533_PACKET(2, x)
+#define ADV7533_PACKET_ISRC1(x)	    ADV7533_PACKET(3, x)
+#define ADV7533_PACKET_ISRC2(x)	    ADV7533_PACKET(4, x)
+#define ADV7533_PACKET_GM(x)	    ADV7533_PACKET(5, x)
+#define ADV7533_PACKET_SPARE(x)	    ADV7533_PACKET(6, x)
+
+#define EDID_LENGTH				0x80
+#define EDID_EXTENSION_NUM				0x7e
+
+/* Video mode flags */
+/* bit compatible with the xorg definitions. */
+#define MODE_FLAG_PHSYNC			(1<<0)
+#define MODE_FLAG_NHSYNC			(1<<1)
+#define MODE_FLAG_PVSYNC			(1<<2)
+#define MODE_FLAG_NVSYNC			(1<<3)
+#define MODE_FLAG_INTERLACE			(1<<4)
+#define MODE_FLAG_DBLSCAN			(1<<5)
+#define MODE_FLAG_CSYNC			(1<<6)
+#define MODE_FLAG_PCSYNC			(1<<7)
+#define MODE_FLAG_NCSYNC			(1<<8)
+#define MODE_FLAG_HSKEW			(1<<9)	/* hskew provided */
+#define MODE_FLAG_BCAST			(1<<10)
+#define MODE_FLAG_PIXMUX			(1<<11)
+#define MODE_FLAG_DBLCLK			(1<<12)
+#define MODE_FLAG_CLKDIV2			(1<<13)
+
+/*
+ * Note on terminology:  here, for brevity and convenience, we refer to connector
+ * control chips as 'CRTCs'.  They can control any type of connector, VGA, LVDS,
+ * DVI, etc.  And 'screen' refers to the whole of the visible display, which
+ * may span multiple monitors (and therefore multiple CRTC and connector
+ * structures).
+ */
+
+enum mode_status {
+	MODE_OK = 0,		/* Mode OK */
+	MODE_HSYNC,		/* hsync out of range */
+	MODE_VSYNC,		/* vsync out of range */
+	MODE_H_ILLEGAL,		/* mode has illegal horizontal timings */
+	MODE_V_ILLEGAL,		/* mode has illegal horizontal timings */
+	MODE_BAD_WIDTH,		/* requires an unsupported linepitch */
+	MODE_NOMODE,		/* no mode with a matching name */
+	MODE_NO_INTERLACE,	/* interlaced mode not supported */
+	MODE_NO_DBLESCAN,	/* doublescan mode not supported */
+	MODE_NO_VSCAN,		/* multiscan mode not supported */
+	MODE_MEM,		/* insufficient video memory */
+	MODE_VIRTUAL_X,		/* mode width too large for specified virtual size */
+	MODE_VIRTUAL_Y,		/* mode height too large for specified virtual size */
+	MODE_MEM_VIRT,		/* insufficient video memory given virtual size */
+	MODE_NOCLOCK,		/* no fixed clock available */
+	MODE_CLOCK_HIGH,	/* clock required is too high */
+	MODE_CLOCK_LOW,		/* clock required is too low */
+	MODE_CLOCK_RANGE,	/* clock/mode isn't in a ClockRange */
+	MODE_BAD_HVALUE,	/* horizontal timing was out of range */
+	MODE_BAD_VVALUE,	/* vertical timing was out of range */
+	MODE_BAD_VSCAN,		/* VScan value out of range */
+	MODE_HSYNC_NARROW,	/* horizontal sync too narrow */
+	MODE_HSYNC_WIDE,	/* horizontal sync too wide */
+	MODE_HBLANK_NARROW,	/* horizontal blanking too narrow */
+	MODE_HBLANK_WIDE,	/* horizontal blanking too wide */
+	MODE_VSYNC_NARROW,	/* vertical sync too narrow */
+	MODE_VSYNC_WIDE,	/* vertical sync too wide */
+	MODE_VBLANK_NARROW,	/* vertical blanking too narrow */
+	MODE_VBLANK_WIDE,	/* vertical blanking too wide */
+	MODE_PANEL,		/* exceeds panel dimensions */
+	MODE_INTERLACE_WIDTH,	/* width too large for interlaced mode */
+	MODE_ONE_WIDTH,		/* only one width is supported */
+	MODE_ONE_HEIGHT,	/* only one height is supported */
+	MODE_ONE_SIZE,		/* only one resolution is supported */
+	MODE_NO_REDUCED,	/* monitor doesn't accept reduced blanking */
+	MODE_NO_STEREO,		/* stereo modes not supported */
+	MODE_UNVERIFIED = -3,	/* mode needs to reverified */
+	MODE_BAD = -2,		/* unspecified reason */
+	MODE_ERROR = -1		/* error condition */
+};
+
+enum DDC_controller_status {
+	IN_RESET = 0,		/* In Reset (No Hot Plug Detected) */
+	READING_EDID,		/* Reading EDID */
+	IDLE,			/* IDLE (Waiting for HDCP Requested) */
+	INIT_HDCP,		/* Initializing HDCP */
+	HDCP_ENABLE,		/* HDCP Enabled */
+	INIT_HDCP_REPEAT	/* Initializing HDCP Repeater */
+};
+
+/* If detailed data is pixel timing */
+struct detailed_pixel_timing {
+	u8 hactive_lo;
+	u8 hblank_lo;
+	u8 hactive_hblank_hi;
+	u8 vactive_lo;
+	u8 vblank_lo;
+	u8 vactive_vblank_hi;
+	u8 hsync_offset_lo;
+	u8 hsync_pulse_width_lo;
+	u8 vsync_offset_pulse_width_lo;
+	u8 hsync_vsync_offset_pulse_width_hi;
+	u8 width_mm_lo;
+	u8 height_mm_lo;
+	u8 width_height_mm_hi;
+	u8 hborder;
+	u8 vborder;
+	u8 misc;
+} __attribute__ ((packed));
+
+struct est_timings {
+	u8 t1;
+	u8 t2;
+	u8 mfg_rsvd;
+} __attribute__ ((packed));
+
+struct std_timing {
+	u8 hsize;		/* need to multiply by 8 then add 248 */
+	u8 vfreq_aspect;
+} __attribute__ ((packed));
+
+struct detailed_timing {
+	__le16 pixel_clock;	/* need to multiply by 10 KHz */
+	union {
+		struct detailed_pixel_timing pixel_data;
+		/* struct detailed_non_pixel other_data;*/
+	} data;
+} __attribute__ ((packed));
+
+struct edid {
+	u8 header[8];
+	/* Vendor & product info */
+	u8 mfg_id[2];
+	u8 prod_code[2];
+	u32 serial;		/* FIXME: byte order */
+	u8 mfg_week;
+	u8 mfg_year;
+	/* EDID version */
+	u8 version;
+	u8 revision;
+	/* Display info: */
+	u8 input;
+	u8 width_cm;
+	u8 height_cm;
+	u8 gamma;
+	u8 features;
+	/* Color characteristics */
+	u8 red_green_lo;
+	u8 black_white_lo;
+	u8 red_x;
+	u8 red_y;
+	u8 green_x;
+	u8 green_y;
+	u8 blue_x;
+	u8 blue_y;
+	u8 white_x;
+	u8 white_y;
+	/* Est. timings and mfg rsvd timings */
+	struct est_timings established_timings;
+	/* Standard timings 1-8 */
+	struct std_timing standard_timings[8];
+	/* Detailing timings 1-4 */
+	struct detailed_timing detailed_timings[4];
+	/* Number of 128 byte ext. blocks */
+	u8 extensions;
+	/* Checksum */
+	u8 checksum;
+} __attribute__ ((packed));
+
+/**
+ * enum adv75xx_csc_scaling - Scaling factor for the ADV75xx CSC
+ * @ADV75xx_CSC_SCALING_1: CSC results are not scaled
+ * @ADV75xx_CSC_SCALING_2: CSC results are scaled by a factor of two
+ * @ADV75xx_CSC_SCALING_4: CSC results are scalled by a factor of four
+ */
+enum adv75xx_csc_scaling {
+	ADV75xx_CSC_SCALING_1 = 0,
+	ADV75xx_CSC_SCALING_2 = 1,
+	ADV75xx_CSC_SCALING_4 = 2,
+};
+
+/**
+ * struct adv75xx_video_config - Describes adv75xx hardware configuration
+ * @csc_enable:			Whether to enable color space conversion
+ * @csc_scaling_factor:		Color space conversion scaling factor
+ * @csc_coefficents:		Color space conversion coefficents
+ * @hdmi_mode:			Whether to use HDMI or DVI output mode
+ * @avi_infoframe:		HDMI infoframe
+ */
+struct adv75xx_video_config {
+	bool csc_enable;
+	enum adv75xx_csc_scaling csc_scaling_factor;
+	const uint16_t *csc_coefficents;
+
+	bool hdmi_mode;
+	struct hdmi_avi_infoframe avi_infoframe;
+};
+
+struct hisi_display_mode {
+
+	unsigned int type;
+
+	/* Proposed mode values */
+	int clock;		/* in kHz */
+	int hdisplay;
+	int hsync_start;
+	int hsync_end;
+	int hsync_pulse_width;
+	int hsync_offset;
+	int htotal;
+
+	int vdisplay;
+	int vsync_start;
+	int vsync_end;
+	int vsync_pulse_width;
+	int vsync_offset;
+	int vtotal;
+	int vscan;
+	unsigned int flags;
+
+	/* Addressable image size (may be 0 for projectors, etc.) */
+	int width_mm;
+	int height_mm;
+
+	int vrefresh;		/* in Hz */
+	int hsync;		/* in kHz */
+	enum hdmi_picture_aspect picture_aspect_ratio;
+};
+
+/**
+ * enum adv7511_sync_polarity - Polarity for the input sync signals
+ * @ADV7533_SYNC_POLARITY_PASSTHROUGH:  Sync polarity matches that of
+ *				       the currently configured mode.
+ * @ADV7533_SYNC_POLARITY_LOW:	    Sync polarity is low
+ * @ADV7533_SYNC_POLARITY_HIGH:	    Sync polarity is high
+ *
+ * If the polarity is set to either LOW or HIGH the driver will configure the
+ * ADV7533 to internally invert the sync signal if required to match the sync
+ * polarity setting for the currently selected output mode.
+ *
+ * If the polarity is set to PASSTHROUGH, the ADV7533 will route the signal
+ * unchanged. This is used when the upstream graphics core already generates
+ * the sync signals with the correct polarity.
+ */
+enum adi_sync_polarity {
+	ADV7533_SYNC_POLARITY_PASSTHROUGH,
+	ADV7533_SYNC_POLARITY_LOW,
+	ADV7533_SYNC_POLARITY_HIGH,
+};
+
+enum adv75xx_type {
+	ADV7511,
+	ADV7533,
+	ADV7535,
+};
+
+enum connector_status {
+	connector_status_connected = 1,
+	connector_status_disconnected = 2,
+	connector_status_unknown = 3,
+};
+
+struct adi_hdmi {
+	enum adv75xx_type type;
+	bool powered;
+
+	struct regulator *vdd;
+	struct regulator *v1p2;
+
+	struct i2c_client *i2c_main;
+	struct i2c_client *i2c_edid;
+	struct i2c_client *i2c_cec;
+	struct i2c_client *i2c_packet;
+
+	struct regmap *regmap;
+	struct regmap *regmap_cec;
+	struct regmap *regmap_packet;
+	enum connector_status status;
+
+	unsigned int f_tmds;
+	unsigned int f_audio;
+	unsigned int audio_source;
+
+	bool edid_read;
+	unsigned int current_edid_segment;
+
+	wait_queue_head_t wq;
+
+	bool rgb;
+	bool embedded_sync;
+	enum adi_sync_polarity vsync_polarity;
+	enum adi_sync_polarity hsync_polarity;
+	uint8_t num_dsi_lanes;
+
+	struct edid *edid;
+	struct gpio_desc *gpio_pd;
+
+	struct hisi_display_mode *mode;
+	struct adi_operation_funcs *opt_funcs;
+};
+
+struct adi_operation_funcs {
+	void (*power_on)(struct adi_hdmi *adv75xx);
+	void (*power_off)(struct adi_hdmi *adv75xx);
+	void (*mode_set)(struct adi_hdmi *adv75xx,
+			  struct hisi_display_mode *mode);
+};
+
+#endif				/* __ADV75XX_H__ */
diff --git a/drivers/video/fbdev/hisi/dss/hdmi/adv75xx_audio.c b/drivers/video/fbdev/hisi/dss/hdmi/adv75xx_audio.c
new file mode 100755
index 000000000000..8242579107b2
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hdmi/adv75xx_audio.c
@@ -0,0 +1,310 @@
+/*
+ * Analog Devices ADV7511 HDMI transmitter driver
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "adv75xx.h"
+
+static const struct snd_soc_dapm_widget adv75xx_dapm_widgets[] = {
+	SND_SOC_DAPM_OUTPUT("TMDS"),
+	SND_SOC_DAPM_AIF_IN("AIFIN", "Playback", 0, SND_SOC_NOPM, 0, 0),
+};
+
+static const struct snd_soc_dapm_route adv75xx_routes[] = {
+	{"TMDS", NULL, "AIFIN"},
+};
+
+static void adv75xx_calc_cts_n(unsigned int f_tmds, unsigned int fs,
+			       unsigned int *cts, unsigned int *n)
+{
+	switch (fs) {
+	case 32000:
+		*n = 4096;
+		break;
+	case 44100:
+		*n = 6272;
+		break;
+	case 48000:
+		*n = 6144;
+		break;
+	}
+
+	*cts = ((f_tmds * *n) / (128 * fs)) * 1000;
+}
+
+static int adv75xx_update_cts_n(struct adi_hdmi *adv75xx)
+{
+	unsigned int cts = 0;
+	unsigned int n = 0;
+
+	adv75xx_calc_cts_n(adv75xx->f_tmds, adv75xx->f_audio, &cts, &n);
+
+	regmap_write(adv75xx->regmap, ADV7533_REG_N0, (n >> 16) & 0xf);
+	regmap_write(adv75xx->regmap, ADV7533_REG_N1, (n >> 8) & 0xff);
+	regmap_write(adv75xx->regmap, ADV7533_REG_N2, n & 0xff);
+
+	regmap_write(adv75xx->regmap, ADV7533_REG_CTS_MANUAL0,
+		     (cts >> 16) & 0xf);
+	regmap_write(adv75xx->regmap, ADV7533_REG_CTS_MANUAL1,
+		     (cts >> 8) & 0xff);
+	regmap_write(adv75xx->regmap, ADV7533_REG_CTS_MANUAL2, cts & 0xff);
+
+	return 0;
+}
+
+static int adv75xx_hw_params(struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *params,
+			     struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->codec;
+	struct adi_hdmi *adv75xx = snd_soc_codec_get_drvdata(codec);
+	unsigned int rate;
+	unsigned int len;
+	switch (params_rate(params)) {
+	case 32000:
+		rate = ADV7533_SAMPLE_FREQ_32000;
+		break;
+	case 44100:
+		rate = ADV7533_SAMPLE_FREQ_44100;
+		break;
+	case 48000:
+		rate = ADV7533_SAMPLE_FREQ_48000;
+		break;
+	case 88200:
+		rate = ADV7533_SAMPLE_FREQ_88200;
+		break;
+	case 96000:
+		rate = ADV7533_SAMPLE_FREQ_96000;
+		break;
+	case 176400:
+		rate = ADV7533_SAMPLE_FREQ_176400;
+		break;
+	case 192000:
+		rate = ADV7533_SAMPLE_FREQ_192000;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		len = ADV7533_I2S_SAMPLE_LEN_16;
+		break;
+	case SNDRV_PCM_FORMAT_S18_3LE:
+		len = ADV7533_I2S_SAMPLE_LEN_18;
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		len = ADV7533_I2S_SAMPLE_LEN_20;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		len = ADV7533_I2S_SAMPLE_LEN_24;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	adv75xx->f_audio = params_rate(params);
+
+	adv75xx_update_cts_n(adv75xx);
+
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_AUDIO_CFG3,
+			   ADV7533_AUDIO_CFG3_LEN_MASK, len);
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_I2C_FREQ_ID_CFG,
+			   ADV7533_I2C_FREQ_ID_CFG_RATE_MASK, rate << 4);
+	regmap_write(adv75xx->regmap, 0x73, 0x1);
+
+	return 0;
+}
+
+static int adv75xx_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct adi_hdmi *adv75xx = snd_soc_codec_get_drvdata(codec);
+	unsigned int audio_source, i2s_format = 0;
+	unsigned int invert_clock;
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		audio_source = ADV7533_AUDIO_SOURCE_I2S;
+		i2s_format = ADV7533_I2S_FORMAT_I2S;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		audio_source = ADV7533_AUDIO_SOURCE_I2S;
+		i2s_format = ADV7533_I2S_FORMAT_RIGHT_J;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		audio_source = ADV7533_AUDIO_SOURCE_I2S;
+		i2s_format = ADV7533_I2S_FORMAT_LEFT_J;
+		break;
+	/*
+	case SND_SOC_DAIFMT_SPDIF:
+	   audio_source = ADV7533_AUDIO_SOURCE_SPDIF;
+	   break;
+	*/
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		invert_clock = 0;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		invert_clock = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_AUDIO_SOURCE, 0x70,
+			   audio_source << 4);
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_AUDIO_CONFIG, BIT(6),
+			   invert_clock << 6);
+	regmap_update_bits(adv75xx->regmap, ADV7533_REG_I2S_CONFIG, 0x03,
+			   i2s_format);
+
+	adv75xx->audio_source = audio_source;
+
+	return 0;
+}
+
+static int adv75xx_set_bias_level(struct snd_soc_codec *codec,
+				  enum snd_soc_bias_level level)
+{
+	struct adi_hdmi *adv75xx = snd_soc_codec_get_drvdata(codec);
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		switch (adv75xx->audio_source) {
+		case ADV7533_AUDIO_SOURCE_I2S:
+			break;
+		case ADV7533_AUDIO_SOURCE_SPDIF:
+			regmap_update_bits(adv75xx->regmap,
+					   ADV7533_REG_AUDIO_CONFIG, BIT(7),
+					   BIT(7));
+			break;
+		}
+		break;
+	case SND_SOC_BIAS_PREPARE:
+		if (dapm->bias_level = SND_SOC_BIAS_STANDBY) {
+			adv75xx_packet_enable(adv75xx,
+					      ADV7533_PACKET_ENABLE_AUDIO_SAMPLE);
+			adv75xx_packet_enable(adv75xx,
+					      ADV7533_PACKET_ENABLE_AUDIO_INFOFRAME);
+			adv75xx_packet_enable(adv75xx,
+					      ADV7533_PACKET_ENABLE_N_CTS);
+		} else {
+			adv75xx_packet_disable(adv75xx,
+					       ADV7533_PACKET_ENABLE_AUDIO_SAMPLE);
+			adv75xx_packet_disable(adv75xx,
+					       ADV7533_PACKET_ENABLE_AUDIO_INFOFRAME);
+			adv75xx_packet_disable(adv75xx,
+					       ADV7533_PACKET_ENABLE_N_CTS);
+		}
+		break;
+	case SND_SOC_BIAS_STANDBY:
+		regmap_update_bits(adv75xx->regmap, ADV7533_REG_AUDIO_CONFIG,
+				   BIT(7), 0);
+		break;
+	case SND_SOC_BIAS_OFF:
+		break;
+	}
+	dapm->bias_level = level;
+	return 0;
+}
+
+#define ADV7533_RATES (SNDRV_PCM_RATE_32000 |\
+		SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
+		SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |\
+		SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
+
+#define ADV7533_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE |\
+		SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE)
+
+static const struct snd_soc_dai_ops adv75xx_dai_ops = {
+	.hw_params = adv75xx_hw_params,
+	/*.set_sysclk   = adv75xx_set_dai_sysclk, */
+	.set_fmt = adv75xx_set_dai_fmt,
+};
+
+static struct snd_soc_dai_driver adv75xx_dai = {
+	.name = "adv75xx",
+	.playback = {
+		     .stream_name = "Playback",
+		     .channels_min = 2,
+		     .channels_max = 2,
+		     .rates = ADV7533_RATES,
+		     .formats = ADV7533_FORMATS,
+		     },
+	.ops = &adv75xx_dai_ops,
+};
+
+static int adv75xx_suspend(struct snd_soc_codec *codec)
+{
+	return adv75xx_set_bias_level(codec, SND_SOC_BIAS_OFF);
+}
+
+static int adv75xx_resume(struct snd_soc_codec *codec)
+{
+	return adv75xx_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+}
+
+static int adv75xx_probe(struct snd_soc_codec *codec)
+{
+	return adv75xx_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+}
+
+static int adv75xx_remove(struct snd_soc_codec *codec)
+{
+	adv75xx_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	return 0;
+}
+
+static struct snd_soc_codec_driver adv75xx_codec_driver = {
+	.probe = adv75xx_probe,
+	.remove = adv75xx_remove,
+	.suspend = adv75xx_suspend,
+	.resume = adv75xx_resume,
+	.set_bias_level = adv75xx_set_bias_level,
+
+	.dapm_widgets = adv75xx_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(adv75xx_dapm_widgets),
+	.dapm_routes = adv75xx_routes,
+	.num_dapm_routes = ARRAY_SIZE(adv75xx_routes),
+};
+
+int adv75xx_audio_init(struct device *dev)
+{
+	return snd_soc_register_codec(dev, &adv75xx_codec_driver,
+				      &adv75xx_dai, 1);
+}
+
+void adv75xx_audio_exit(struct device *dev)
+{
+	snd_soc_unregister_codec(dev);
+}
diff --git a/drivers/video/fbdev/hisi/dss/hdmi/mipi_adi_hdmi.c b/drivers/video/fbdev/hisi/dss/hdmi/mipi_adi_hdmi.c
new file mode 100755
index 000000000000..65313f54878d
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hdmi/mipi_adi_hdmi.c
@@ -0,0 +1,314 @@
+/* Copyright (c) 2008-2011, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *	 * Redistributions of source code must retain the above copyright
+ *	   notice, this list of conditions and the following disclaimer.
+ *	 * Redistributions in binary form must reproduce the above
+ *	   copyright notice, this list of conditions and the following
+ *	   disclaimer in the documentation and/or other materials provided
+ *	   with the distribution.
+ *	 * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *	   contributors may be used to endorse or promote products derived
+ *	   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "../hisi_fb.h"
+#include "adv75xx.h"
+
+/*******************************************************************************
+ **
+ */
+static int mipi_adi_hdmi_on(struct platform_device *pdev)
+{
+	struct adi_hdmi *adv75xx = NULL;
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct hisi_panel_info *pinfo = NULL;
+
+	HISI_FB_INFO("+.\n");
+
+	if (pdev = NULL) {
+		HISI_FB_ERR("pdev is NULL!\n");
+		return -1;
+	}
+
+	HISI_FB_INFO("pdev->name = %s, pdev->id = %d\n", pdev->name, pdev->id);
+
+	hisifd = platform_get_drvdata(pdev);
+	if (hisifd = NULL) {
+		HISI_FB_ERR("platform get drivre data failed!!\n");
+		return -1;
+	}
+
+	HISI_FB_INFO("fb%d, +!\n", hisifd->index);
+
+	pinfo = &(hisifd->panel_info);
+
+	pdata = dev_get_platdata(&pdev->dev);
+	if (pdata = NULL) {
+		HISI_FB_ERR("devices get platform data failed!!\n");
+		return -1;
+	}
+
+	if (pdata->next) {
+		adv75xx = platform_get_drvdata(pdata->next);
+		if (!adv75xx) {
+			HISI_FB_ERR("platform get drivre data failed!\n");
+			return -1;
+		}
+	} else {
+		HISI_FB_ERR("pdata->next is NULL!!\n");
+		return -1;
+	}
+
+	HISI_FB_INFO("adv75xx->i2c_main->name is %s!\n",
+		     adv75xx->i2c_main->name);
+	HISI_FB_INFO("adv75xx->mode->vdisplay is %d!\n",
+		     adv75xx->mode->vdisplay);
+
+	if (pinfo->lcd_init_step = LCD_INIT_POWER_ON) {
+		pinfo->lcd_init_step = LCD_INIT_MIPI_LP_SEND_SEQUENCE;
+	} else if (pinfo->lcd_init_step = LCD_INIT_MIPI_LP_SEND_SEQUENCE) {
+		pinfo->lcd_init_step = LCD_INIT_MIPI_HS_SEND_SEQUENCE;
+	} else if (pinfo->lcd_init_step = LCD_INIT_MIPI_HS_SEND_SEQUENCE) {
+		adv75xx->opt_funcs->mode_set(adv75xx, adv75xx->mode);
+		adv75xx->opt_funcs->power_on(adv75xx);
+	} else {
+		HISI_FB_ERR("failed to init hdmi!\n");
+	}
+
+	HISI_FB_INFO("-.\n");
+
+	return 0;
+}
+
+static int mipi_adi_hdmi_off(struct platform_device *pdev)
+{
+	struct adi_hdmi *adv75xx = NULL;
+	struct hisi_fb_panel_data *pdata = NULL;
+
+	HISI_FB_INFO("+.\n");
+
+	BUG_ON(pdev = NULL);
+	pdata = dev_get_platdata(&pdev->dev);
+	BUG_ON(pdata = NULL);
+
+	HISI_FB_INFO("pdev->name = %s, pdev->id = %d +.\n", pdev->name,
+		     pdev->id);
+
+	if (pdata->next) {
+		adv75xx = platform_get_drvdata(pdata->next);
+		if (!adv75xx) {
+			HISI_FB_ERR("platform get drivre data failed!\n");
+			return -1;
+		}
+	}
+
+	HISI_FB_INFO("adv75xx->i2c_main->name is %s!\n",
+		     adv75xx->i2c_main->name);
+	HISI_FB_INFO("adv75xx->mode->vdisplay is %d!\n",
+		     adv75xx->mode->vdisplay);
+
+	adv75xx->opt_funcs->power_off(adv75xx);
+
+	HISI_FB_INFO("-.\n");
+
+	return 0;
+}
+
+static int mipi_adi_hdmi_remove(struct platform_device *pdev)
+{
+
+	return 0;
+}
+
+/*******************************************************************************
+ **
+ */
+static struct hisi_panel_info g_adi_hdmi_info = { 0 };
+
+static struct hisi_fb_panel_data g_adi_hdmi_data = {
+	.panel_info = &g_adi_hdmi_info,
+	.on = mipi_adi_hdmi_on,
+	.off = mipi_adi_hdmi_off,
+};
+
+/*******************************************************************************
+ **
+ */
+static int mipi_adi_hdmi_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct adi_hdmi *adv75xx = NULL;
+	struct hisi_panel_info *pinfo = NULL;
+	struct hisi_display_mode *mode = NULL;
+
+	if (pdev = NULL)
+		HISI_FB_ERR("platform device is NULL!\n");
+
+	HISI_FB_INFO("pdev->name = %s, pdev->id = %d +.\n", pdev->name,
+		     pdev->id);
+
+	adv75xx = platform_get_drvdata(pdev);
+	if (!adv75xx) {
+		HISI_FB_ERR("platform get drivre data failed!\n");
+		goto err_probe_defer;
+	}
+
+	HISI_FB_INFO("adv75xx->i2c_main->name is %s!\n",
+		     adv75xx->i2c_main->name);
+
+	HISI_FB_INFO("adv75xx->mode->vdisplay is %d!\n",
+		     adv75xx->mode->vdisplay);
+
+	if (adv75xx->mode) {
+		mode = adv75xx->mode;
+		/* init hdmi display info */
+		pinfo = g_adi_hdmi_data.panel_info;
+		pinfo->xres = mode->hdisplay;
+		pinfo->yres = mode->vdisplay;
+		pinfo->width = mode->width_mm;
+		pinfo->height = mode->height_mm;
+		pinfo->orientation = LCD_PORTRAIT;
+		pinfo->bpp = LCD_RGB888;
+		pinfo->bgr_fmt = LCD_RGB;
+		pinfo->bl_set_type = BL_SET_BY_MIPI;
+
+		pinfo->type = PANEL_MIPI_VIDEO;
+
+		pinfo->bl_min = 1;
+		pinfo->bl_max = 255;
+		pinfo->bl_default = 102;
+
+		pinfo->pxl_clk_rate = mode->clock * 1000UL;
+		pinfo->ldi.h_back_porch = mode->htotal - mode->hsync_end;
+		pinfo->ldi.h_front_porch = mode->hsync_offset;
+		pinfo->ldi.h_pulse_width = mode->hsync_pulse_width;
+		pinfo->ldi.v_back_porch = mode->vtotal - mode->vsync_end;
+		pinfo->ldi.v_front_porch = mode->vsync_offset;
+		pinfo->ldi.v_pulse_width = mode->vsync_pulse_width;
+	} else {
+		/* init hdmi display info */
+		pinfo = g_adi_hdmi_data.panel_info;
+		pinfo->xres = 1920;
+		pinfo->yres = 1080;
+		pinfo->width = 16000;
+		pinfo->height = 9000;
+
+		pinfo->orientation = LCD_PORTRAIT;
+		pinfo->bpp = LCD_RGB888;
+		pinfo->bgr_fmt = LCD_RGB;
+		pinfo->bl_set_type = BL_SET_BY_MIPI;
+
+		pinfo->type = PANEL_MIPI_VIDEO;
+
+		pinfo->bl_min = 1;
+		pinfo->bl_max = 255;
+		pinfo->bl_default = 102;
+
+		pinfo->ldi.h_back_porch = 148;
+		pinfo->ldi.h_front_porch = 88;
+		pinfo->ldi.h_pulse_width = 44;
+		pinfo->ldi.v_back_porch = 36;
+		pinfo->ldi.v_front_porch = 4;
+		pinfo->ldi.v_pulse_width = 5;
+	}
+
+
+	pinfo->mipi.dsi_bit_clk = 480;
+
+
+	pinfo->dsi_bit_clk_upt_support = 0;
+	pinfo->mipi.dsi_bit_clk_upt = pinfo->mipi.dsi_bit_clk;
+
+	pinfo->mipi.non_continue_en = 0;
+
+	pinfo->pxl_clk_rate = 160 * 1000000UL;
+
+
+	pinfo->mipi.lane_nums = DSI_4_LANES;
+	pinfo->mipi.color_mode = DSI_24BITS_1;
+	pinfo->mipi.vc = 0;
+	pinfo->mipi.max_tx_esc_clk = 10 * 1000000;
+	pinfo->mipi.burst_mode = DSI_NON_BURST_SYNC_PULSES;
+
+	pinfo->mipi.clk_post_adjust = 120;
+	pinfo->mipi.clk_pre_adjust = 0;
+	pinfo->mipi.clk_t_hs_prepare_adjust = 0;
+	pinfo->mipi.clk_t_lpx_adjust = 0;
+	pinfo->mipi.clk_t_hs_trial_adjust = 0;
+	pinfo->mipi.clk_t_hs_exit_adjust = 0;
+	pinfo->mipi.clk_t_hs_zero_adjust = 0;
+
+	pinfo->pxl_clk_rate_div = 1;
+
+	g_adi_hdmi_data.next = pdev;
+	HISI_FB_INFO("The pixel clock is %llu !\n", pinfo->pxl_clk_rate);
+	HISI_FB_INFO("The resolution is %d x %d !\n", pinfo->xres, pinfo->yres);
+	HISI_FB_INFO
+	    ("hsw = %d, hfp = %d, hbp = %d, vsw = %d, vfp= %d, vbp = %d\n",
+	     pinfo->ldi.h_pulse_width, pinfo->ldi.h_front_porch,
+	     pinfo->ldi.h_back_porch, pinfo->ldi.v_pulse_width,
+	     pinfo->ldi.v_front_porch, pinfo->ldi.v_back_porch);
+
+
+	ret = platform_device_add_data(pdev, &g_adi_hdmi_data,
+				       sizeof(struct hisi_fb_panel_data));
+	if (ret) {
+		HISI_FB_ERR("platform_device_add_data failed!\n");
+		goto err_device_put;
+	}
+
+	hisi_fb_add_device(pdev);
+
+	HISI_FB_INFO("-.\n");
+
+	return 0;
+
+ err_device_put:
+	platform_device_put(pdev);
+ err_probe_defer:
+	return -EPROBE_DEFER;
+}
+
+static struct platform_driver this_driver = {
+	.probe = mipi_adi_hdmi_probe,
+	.remove = mipi_adi_hdmi_remove,
+	.suspend = NULL,
+	.resume = NULL,
+	.shutdown = NULL,
+	.driver = {
+		   .name = "adi_hdmi",
+		   }
+};
+
+static int __init mipi_adi_hdmi_init(void)
+{
+	int ret = 0;
+
+	ret = platform_driver_register(&this_driver);
+	if (ret) {
+		HISI_FB_ERR("platform_driver_register failed, error=%d!\n",
+			    ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+module_init(mipi_adi_hdmi_init);
diff --git a/drivers/video/fbdev/hisi/dss/panel/mipi_hikey_nte300nts.c b/drivers/video/fbdev/hisi/dss/panel/mipi_hikey_nte300nts.c
new file mode 100755
index 000000000000..7e1fbd0ee5c6
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/panel/mipi_hikey_nte300nts.c
@@ -0,0 +1,525 @@
+/* Copyright (c) 2008-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "../hisi_fb.h"
+
+#define DTS_COMP_MIPI_HIKEY	"hisilicon,mipi_hikey"
+
+/********************************Hikey start***********************
+ **Power ON Sequence(sleep mode to Normal mode)
+ */
+static char hikey_power_on_param1[] = {
+	0x01,
+};
+
+static char hikey_power_on_param2[] = {
+	0xB0,
+	0x00,
+};
+
+static char hikey_power_on_param3[] = {
+	0xD6,
+	0x01,
+};
+
+static char hikey_power_on_param4[] = {
+	0xB3,
+	0x14, 0x08, 0x00, 0x22, 0x00,
+};
+
+static char hikey_power_on_param5[] = {
+	0xB4,
+	0x0C,
+};
+
+static char hikey_power_on_param6[] = {
+	0xB6,
+	0x3A, 0xC3,
+};
+
+static char hikey_power_on_param7[] = {
+	0x2A,
+	0x00, 0x00, 0X04, 0XAF,
+};
+
+static char hikey_power_on_param8[] = {
+	0x2B,
+	0x00, 0x00, 0X07, 0X7F,
+};
+
+static char hikey_power_on_param9[] = {
+	0x51,
+	0xA6,
+};
+
+static char hikey_power_on_param10[] = {
+	0x53,
+	0x2C,
+};
+
+static char hikey_power_on_param11[] = {
+	0x3A,
+	0x66,
+};
+
+static char hikey_power_on_param12[] = {
+	0x29,
+};
+
+static char hikey_power_on_param13[] = {
+	0x11,
+};
+
+static char hikey_display_off[] = {
+	0x28,
+};
+
+static char hikey_enter_sleep[] = {
+	0x10,
+};
+
+static struct dsi_cmd_desc hikey_display_off_cmds[] = {
+	{DTYPE_DCS_WRITE, 0, 20, WAIT_TYPE_MS,
+	 sizeof(hikey_display_off), hikey_display_off}
+	,
+	{DTYPE_DCS_WRITE, 0, 80, WAIT_TYPE_MS,
+	 sizeof(hikey_enter_sleep), hikey_enter_sleep}
+	,
+};
+
+/*short or long packet*/
+static struct dsi_cmd_desc hikey_display_on_cmds[] = {
+	{DTYPE_DCS_WRITE, 0, 5, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param1), hikey_power_on_param1}
+	,
+	{DTYPE_DCS_WRITE1, 0, 2, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param2), hikey_power_on_param2}
+	,
+	{DTYPE_DCS_WRITE1, 0, 2, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param3), hikey_power_on_param3}
+	,
+	{DTYPE_DCS_LWRITE, 0, 2, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param4), hikey_power_on_param4}
+	,
+	{DTYPE_DCS_WRITE1, 0, 2, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param5), hikey_power_on_param5}
+	,
+	{DTYPE_DCS_LWRITE, 0, 2, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param6), hikey_power_on_param6}
+	,
+	{DTYPE_DCS_LWRITE, 0, 2, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param7), hikey_power_on_param7}
+	,
+	{DTYPE_DCS_LWRITE, 0, 2, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param8), hikey_power_on_param8}
+	,
+	{DTYPE_DCS_WRITE1, 0, 2, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param9), hikey_power_on_param9}
+	,
+	{DTYPE_DCS_WRITE1, 0, 2, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param10), hikey_power_on_param10}
+	,
+	{DTYPE_DCS_WRITE1, 0, 2, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param11), hikey_power_on_param11}
+	,
+	{DTYPE_DCS_WRITE, 0, 20, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param12), hikey_power_on_param12}
+	,
+	{DTYPE_DCS_WRITE, 0, 150, WAIT_TYPE_MS,
+	 sizeof(hikey_power_on_param13), hikey_power_on_param13}
+	,
+};
+
+/********************************hikey end*************************/
+
+/*******************************************************************************
+ ** LCD GPIO
+ */
+#define GPIO_LCD_PWR_ENABLE_NAME "gpio_lcd_pwr_enable"
+#define GPIO_LCD_BL_ENABLE_NAME "gpio_lcd_bl_enable"
+#define GPIO_LCD_PWM_NAME "gpio_lcd_pwm"
+#define GPIO_SWITCH_DSI_HDMI "gpio_switch_dsi_hdmi"
+
+static uint32_t gpio_lcd_pwr_enable;
+static uint32_t gpio_lcd_bl_enable;
+static uint32_t gpio_lcd_pwm;
+static uint32_t gpio_switch_dsi_hdmi;
+
+static struct gpio_desc hikey_lcd_gpio_request_cmds[] = {
+	{DTYPE_GPIO_REQUEST, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_PWR_ENABLE_NAME, &gpio_lcd_pwr_enable, 0},
+	{DTYPE_GPIO_REQUEST, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_BL_ENABLE_NAME, &gpio_lcd_bl_enable, 0},
+	{DTYPE_GPIO_REQUEST, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_PWM_NAME, &gpio_lcd_pwm, 0},
+	{DTYPE_GPIO_REQUEST, WAIT_TYPE_MS, 0,
+	 GPIO_SWITCH_DSI_HDMI, &gpio_switch_dsi_hdmi, 0},
+};
+
+static struct gpio_desc hikey_lcd_gpio_free_cmds[] = {
+	{DTYPE_GPIO_FREE, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_PWR_ENABLE_NAME, &gpio_lcd_pwr_enable, 0},
+	{DTYPE_GPIO_FREE, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_BL_ENABLE_NAME, &gpio_lcd_bl_enable, 0},
+	{DTYPE_GPIO_FREE, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_PWM_NAME, &gpio_lcd_pwm, 0},
+	{DTYPE_GPIO_FREE, WAIT_TYPE_MS, 0,
+	 GPIO_SWITCH_DSI_HDMI, &gpio_switch_dsi_hdmi, 0},
+};
+
+static struct gpio_desc hikey_lcd_gpio_normal_cmds[] = {
+	{DTYPE_GPIO_OUTPUT, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_PWR_ENABLE_NAME, &gpio_lcd_pwr_enable, 1},
+	{DTYPE_GPIO_OUTPUT, WAIT_TYPE_MS, 0,
+	 GPIO_SWITCH_DSI_HDMI, &gpio_switch_dsi_hdmi, 1},
+};
+
+static struct gpio_desc hikey_lcd_gpio_off_cmds[] = {
+	{DTYPE_GPIO_OUTPUT, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_PWR_ENABLE_NAME, &gpio_lcd_pwr_enable, 0},
+	{DTYPE_GPIO_OUTPUT, WAIT_TYPE_MS, 0,
+	 GPIO_SWITCH_DSI_HDMI, &gpio_switch_dsi_hdmi, 0},
+};
+
+static struct gpio_desc hikey_lcd_backlight_enable_cmds[] = {
+	{DTYPE_GPIO_OUTPUT, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_BL_ENABLE_NAME, &gpio_lcd_bl_enable, 1},
+	{DTYPE_GPIO_OUTPUT, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_PWM_NAME, &gpio_lcd_pwm, 1},
+};
+
+static struct gpio_desc hikey_lcd_backlight_disable_cmds[] = {
+	{DTYPE_GPIO_OUTPUT, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_BL_ENABLE_NAME, &gpio_lcd_bl_enable, 0},
+	{DTYPE_GPIO_OUTPUT, WAIT_TYPE_MS, 0,
+	 GPIO_LCD_PWM_NAME, &gpio_lcd_pwm, 0},
+};
+
+static struct hisi_fb_panel_data g_panel_data;
+
+static void hikey_set_backlight_on(void)
+{
+	msleep(200);
+	gpio_cmds_tx(hikey_lcd_backlight_enable_cmds,
+		     ARRAY_SIZE(hikey_lcd_backlight_enable_cmds));
+	return;
+}
+
+static void hikey_set_backlight_off(void)
+{
+	gpio_cmds_tx(hikey_lcd_backlight_disable_cmds,
+		     ARRAY_SIZE(hikey_lcd_backlight_disable_cmds));
+	return;
+}
+
+static int hikey_panel_on(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct hisi_panel_info *pinfo = NULL;
+	char __iomem *mipi_dsi0_base = NULL;
+
+	BUG_ON(pdev = NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd = NULL);
+	pinfo = &(hisifd->panel_info);
+	BUG_ON(pinfo = NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	mipi_dsi0_base = hisifd->mipi_dsi0_base;
+
+	if (pinfo->lcd_init_step = LCD_INIT_POWER_ON) {
+		pinfo->lcd_init_step = LCD_INIT_MIPI_LP_SEND_SEQUENCE;
+	} else if (pinfo->lcd_init_step = LCD_INIT_MIPI_LP_SEND_SEQUENCE) {
+		/*lcd gpio request */
+		gpio_cmds_tx(hikey_lcd_gpio_request_cmds,
+			     ARRAY_SIZE(hikey_lcd_gpio_request_cmds));
+		/*lcd gpio normal */
+		gpio_cmds_tx(hikey_lcd_gpio_normal_cmds,
+			     ARRAY_SIZE(hikey_lcd_gpio_normal_cmds));
+		/*lcd display on sequence */
+		msleep(250);
+		mipi_dsi_cmds_tx(hikey_display_on_cmds,
+				 ARRAY_SIZE(hikey_display_on_cmds),
+				 mipi_dsi0_base);
+
+		pinfo->lcd_init_step = LCD_INIT_MIPI_HS_SEND_SEQUENCE;
+	} else if (pinfo->lcd_init_step = LCD_INIT_MIPI_HS_SEND_SEQUENCE) {
+		;
+	} else {
+		HISI_FB_ERR("failed to init lcd!\n");
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return 0;
+}
+
+static int hikey_panel_off(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct hisi_panel_info *pinfo = NULL;
+	char __iomem *mipi_dsi0_base = NULL;
+
+	BUG_ON(pdev = NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd = NULL);
+	pinfo = &(hisifd->panel_info);
+	BUG_ON(pinfo = NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+	mipi_dsi0_base = hisifd->mipi_dsi0_base;
+	/*lcd enter sleep */
+	mipi_dsi_cmds_tx(hikey_display_off_cmds,
+			 ARRAY_SIZE(hikey_display_off_cmds), mipi_dsi0_base);
+	gpio_cmds_tx(hikey_lcd_gpio_off_cmds,
+		     ARRAY_SIZE(hikey_lcd_gpio_off_cmds));
+	gpio_cmds_tx(hikey_lcd_gpio_free_cmds,
+		     ARRAY_SIZE(hikey_lcd_gpio_free_cmds));
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return 0;
+}
+
+static int hikey_panel_remove(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev = NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd = NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return 0;
+}
+
+static int hikey_panel_set_backlight(struct platform_device *pdev,
+				     uint32_t bl_level)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	int ret = 0;
+
+	BUG_ON(pdev = NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd = NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	if (bl_level = 0) {
+		hikey_set_backlight_off();
+	} else {
+		hikey_set_backlight_on();
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return ret;
+}
+
+static struct hisi_panel_info g_panel_info = { 0 };
+
+static struct hisi_fb_panel_data g_panel_data = {
+	.panel_info = &g_panel_info,
+	.on = hikey_panel_on,
+	.off = hikey_panel_off,
+	.remove = hikey_panel_remove,
+	.set_backlight = hikey_panel_set_backlight,
+};
+
+static int hikey_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct hisi_panel_info *pinfo = NULL;
+	struct device_node *np = NULL;
+	uint32_t bl_type = 0;
+
+	uint32_t lcd_display_type = 0;
+	uint32_t lcd_ifbc_type = 0;
+
+	HISI_FB_DEBUG("+.\n");
+
+	np = of_find_compatible_node(NULL, NULL, DTS_COMP_MIPI_HIKEY);
+	if (!np) {
+		HISI_FB_ERR("NOT FOUND device node %s!\n", DTS_COMP_MIPI_HIKEY);
+		goto err_return;
+	}
+
+	ret = of_property_read_u32(np, LCD_BL_TYPE_NAME, &bl_type);
+	if (ret) {
+		HISI_FB_ERR("get lcd_bl_type failed!\n");
+		bl_type = BL_SET_BY_BLPWM;
+	}
+
+	ret +	    of_property_read_u32(np, LCD_DISPLAY_TYPE_NAME, &lcd_display_type);
+	if (ret) {
+		HISI_FB_ERR("get lcd_display_type failed!\n");
+		lcd_display_type = PANEL_MIPI_VIDEO;
+	}
+
+	ret = of_property_read_u32(np, LCD_IFBC_TYPE_NAME, &lcd_ifbc_type);
+	if (ret) {
+		HISI_FB_ERR("get ifbc_type failed!\n");
+		lcd_ifbc_type = IFBC_TYPE_NONE;
+	}
+
+	/*GPIO_26_8 GPIO_216 */
+	gpio_lcd_pwr_enable = of_get_named_gpio(np, "gpios", 0);
+	/*GPIO_27_2 GPIO_218 */
+	gpio_lcd_bl_enable = of_get_named_gpio(np, "gpios", 1);
+	/*GPIO_22_6 GPIO_182 */
+	gpio_lcd_pwm = of_get_named_gpio(np, "gpios", 2);
+	/*GPIO_2_4 GPIO_020 */
+	gpio_switch_dsi_hdmi = of_get_named_gpio(np, "gpios", 3);
+
+	if (hisi_fb_device_probe_defer(lcd_display_type, bl_type)) {
+		goto err_probe_defer;
+	}
+
+	pdev->id = 1;
+	/*init lcd panel info */
+	pinfo = g_panel_data.panel_info;
+	memset(pinfo, 0, sizeof(struct hisi_panel_info));
+	pinfo->xres = 1200;
+	pinfo->yres = 1920;
+	pinfo->width = 94;
+	pinfo->height = 151;
+	pinfo->orientation = LCD_PORTRAIT;
+	pinfo->bpp = LCD_RGB888;
+	pinfo->bgr_fmt = LCD_RGB;
+	pinfo->bl_set_type = bl_type;
+
+	pinfo->type = PANEL_MIPI_VIDEO;
+	pinfo->ifbc_type = 0;
+
+	if (pinfo->bl_set_type = BL_SET_BY_BLPWM)
+		pinfo->blpwm_input_ena = 0;
+
+	pinfo->bl_min = 1;
+	pinfo->bl_max = 255;
+	pinfo->bl_default = 102;
+	pinfo->esd_enable = 0;
+
+	/*ldi */
+	pinfo->ldi.h_back_porch = 60;
+	pinfo->ldi.h_front_porch = 200;
+	pinfo->ldi.h_pulse_width = 12;
+	pinfo->ldi.v_back_porch = 8;
+	pinfo->ldi.v_front_porch = 8;
+	pinfo->ldi.v_pulse_width = 2;
+
+	/*
+	   pinfo->ldi.hsync_plr = 0;
+	   pinfo->ldi.vsync_plr = 0;
+	   pinfo->ldi.pixelclk_plr = 1;
+	   pinfo->ldi.data_en_plr = 0;
+	 */
+
+	/*mipi */
+	pinfo->mipi.lane_nums = DSI_4_LANES;
+	pinfo->mipi.color_mode = DSI_24BITS_1;
+	pinfo->mipi.vc = 0;
+	pinfo->mipi.max_tx_esc_clk = 10 * 1000000;
+	pinfo->mipi.burst_mode = DSI_BURST_SYNC_PULSES_1;
+
+	pinfo->mipi.dsi_bit_clk = 480;
+	pinfo->mipi.dsi_bit_clk_upt = pinfo->mipi.dsi_bit_clk;
+
+	pinfo->pxl_clk_rate = 146 * 1000000UL;
+	pinfo->pxl_clk_rate_div = 1;
+	pinfo->fps = 50;
+
+	pinfo->vsync_ctrl_type = 0;
+	pinfo->dirty_region_updt_support = 0;
+	pinfo->dsi_bit_clk_upt_support = 0;
+
+	/*alloc panel device data */
+	ret = platform_device_add_data(pdev, &g_panel_data,
+				       sizeof(struct hisi_fb_panel_data));
+	if (ret) {
+		HISI_FB_ERR("platform_device_add_data failed!\n");
+		goto err_device_put;
+	}
+
+	hisi_fb_add_device(pdev);
+
+	/*
+	   vdd = devm_regulator_get(&(pdev->dev), "vdd");
+	   if (IS_ERR(vdd)) {
+	   ret = PTR_ERR(vdd);
+	   HISI_FB_ERR("vdd regulator get fail\n");
+	   return ret;
+	   }
+
+	   ret = regulator_set_voltage(vdd, 1800000, 1800000);
+	   if (ret) {
+	   HISI_FB_ERR("vdd regulator set voltage fail\n");
+	   return ret;
+	   }
+
+	   ret = regulator_enable(vdd);
+	   if (ret) {
+	   HISI_FB_ERR("vdd regulator enable fail\n");
+	   return ret;
+	   }
+	 */
+
+	HISI_FB_DEBUG("-.\n");
+	return 0;
+
+ err_device_put:
+	platform_device_put(pdev);
+ err_return:
+	return ret;
+ err_probe_defer:
+	return -EPROBE_DEFER;
+}
+
+static const struct of_device_id hisi_panel_match_table[] = {
+	{
+	 .compatible = DTS_COMP_MIPI_HIKEY,
+	 .data = NULL,
+	 },
+	{},
+};
+
+static struct platform_driver this_driver = {
+	.probe = hikey_probe,
+	.remove = NULL,
+	.suspend = NULL,
+	.resume = NULL,
+	.shutdown = NULL,
+	.driver = {
+		   .name = "mipi_hikey",
+		   .owner = THIS_MODULE,
+		   .of_match_table = of_match_ptr(hisi_panel_match_table),
+		   },
+};
+
+static int __init hikey_panel_init(void)
+{
+	int ret = 0;
+
+	ret = platform_driver_register(&this_driver);
+	if (ret) {
+		HISI_FB_ERR("platform_driver_register failed, error=%d!\n",
+			    ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+module_init(hikey_panel_init);
-- 
2.12.0-rc0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/8] fb: hisilicon: Add framebuffer driver for hi3660 SoC
  2017-02-07  2:35   ` cailiwei
  (?)
  (?)
@ 2017-02-07  2:35   ` cailiwei
  -1 siblings, 0 replies; 15+ messages in thread
From: cailiwei @ 2017-02-07  2:35 UTC (permalink / raw)
  To: linux-fbdev, linux-kernel, b.zolnierkie, guodong.xu
  Cc: suzhuangluan, dengqingshan, xuhongtao8, zhengwanchun,
	shizongxuan, cailiwei

From: Levy-Cai <cailiwei@hisilicon.com>

Add framebuffer driver for hi3660 SoC, this driver include lcd
driver & Hdmi adv7533/adv7535 driver, support lcd display at
1080p@60 and hdmi display at 1080p@60.

Signed-off-by: cailiwei <cailiwei@hisilicon.com>
---
 drivers/video/fbdev/hisi/dss/hisi_dpe.c       |  763 +++++++++
 drivers/video/fbdev/hisi/dss/hisi_dpe_utils.h |   64 +
 drivers/video/fbdev/hisi/dss/hisi_fb.c        | 2232 +++++++++++++++++++++++++
 drivers/video/fbdev/hisi/dss/hisi_fb.h        |  559 +++++++
 drivers/video/fbdev/hisi/dss/hisi_mipi_dsi.c  | 1686 +++++++++++++++++++
 drivers/video/fbdev/hisi/dss/hisi_mipi_dsi.h  |  152 ++
 6 files changed, 5456 insertions(+)
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_dpe.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_dpe_utils.h
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_fb.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_fb.h
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_mipi_dsi.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_mipi_dsi.h

diff --git a/drivers/video/fbdev/hisi/dss/hisi_dpe.c b/drivers/video/fbdev/hisi/dss/hisi_dpe.c
new file mode 100755
index 000000000000..fef13287c933
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_dpe.c
@@ -0,0 +1,763 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_fb.h"
+#include "hisi_dpe_utils.h"
+#include "hisi_overlay_utils.h"
+#ifdef CONFIG_HISI_OCBC
+#include <linux/hisi/ocbc.h>
+#endif
+
+static int dpe_init(struct hisi_fb_data_type *hisifd, bool fastboot_enable)
+{
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		init_post_scf(hisifd);
+		init_dbuf(hisifd);
+		init_dpp(hisifd);
+		/* init_sbl(hisifd); */
+		init_acm(hisifd);
+		init_dpp_csc(hisifd);
+		init_igm_gmp_xcc_gm(hisifd);
+
+		init_ifbc(hisifd);
+		init_ldi(hisifd, fastboot_enable);
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		if (hisifd->dss_pxl1_clk)
+			clk_disable(hisifd->dss_pxl1_clk);
+
+		set_reg(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_DSI1_CLK_SEL,
+			0x1, 1, 0);
+
+		if (hisifd->dss_pxl1_clk)
+			clk_enable(hisifd->dss_pxl1_clk);
+
+		set_reg(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_DSI1_RST_SEL,
+			0x1, 1, 0);
+		/* dual lcd: dsi_mux_sel=1, dual mipi: dsi_mux_sel=0 */
+		set_reg(hisifd->dss_base + DSS_MCTRL_SYS_OFFSET +
+			MCTL_DSI_MUX_SEL, 0x1, 1, 0);
+
+		init_dbuf(hisifd);
+		init_ldi(hisifd, fastboot_enable);
+	} else if (hisifd->index == AUXILIARY_PANEL_IDX) {
+		;
+	} else {
+		HISI_FB_ERR("fb%d, not support this device!\n", hisifd->index);
+	}
+
+	return 0;
+}
+
+static int dpe_deinit(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		deinit_ldi(hisifd);
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		deinit_ldi(hisifd);
+	} else if (hisifd->index == AUXILIARY_PANEL_IDX) {
+		;
+	} else {
+		HISI_FB_ERR("fb%d, not support this device!\n", hisifd->index);
+	}
+
+	return 0;
+}
+
+static void dpe_check_itf_status(struct hisi_fb_data_type *hisifd)
+{
+	int tmp = 0;
+	int delay_count = 0;
+	bool is_timeout = true;
+	int itf_idx = 0;
+	char __iomem *mctl_sys_base = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	if ((hisifd->index == PRIMARY_PANEL_IDX) ||
+	    (hisifd->index == EXTERNAL_PANEL_IDX)) {
+		itf_idx = hisifd->index;
+		mctl_sys_base = hisifd->dss_base + DSS_MCTRL_SYS_OFFSET;
+
+		while (1) {
+			tmp =
+			    inp32(mctl_sys_base + MCTL_MOD17_STATUS +
+				  itf_idx * 0x4);
+			if (((tmp & 0x10) == 0x10) || delay_count > 100) {
+				is_timeout = (delay_count > 100) ? true : false;
+				delay_count = 0;
+				break;
+			} else {
+				mdelay(1);
+				++delay_count;
+			}
+		}
+
+		if (is_timeout) {
+			HISI_FB_DEBUG
+			    ("mctl_itf%d not in idle status,ints=0x%x !\n",
+			     hisifd->index, tmp);
+		}
+	}
+}
+
+static int dpe_irq_enable(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->dpe_irq)
+		enable_irq(hisifd->dpe_irq);
+
+	return 0;
+}
+
+static int dpe_irq_disable(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->dpe_irq)
+		disable_irq(hisifd->dpe_irq);
+
+	return 0;
+}
+
+static int dpe_irq_disable_nosync(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->dpe_irq)
+		disable_irq_nosync(hisifd->dpe_irq);
+
+	return 0;
+}
+
+int dpe_common_clk_enable(struct hisi_fb_data_type *hisifd)
+{
+	int ret = 0;
+	struct clk *clk_tmp = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+#ifdef CONFIG_DSS_MMBUF_CLK_USED
+	clk_tmp = hisifd->dss_mmbuf_clk;
+	if (clk_tmp) {
+		ret = clk_prepare(clk_tmp);
+		if (ret) {
+			HISI_FB_ERR
+			    ("fb%d dss_mmbuf_clk clk_prepare failed, error=%d!\n",
+			     hisifd->index, ret);
+			return -EINVAL;
+		}
+
+		ret = clk_enable(clk_tmp);
+		if (ret) {
+			HISI_FB_ERR
+			    ("fb%d dss_mmbuf_clk clk_enable failed, error=%d!\n",
+			     hisifd->index, ret);
+			return -EINVAL;
+		}
+	}
+#endif
+
+	clk_tmp = hisifd->dss_axi_clk;
+	if (clk_tmp) {
+		ret = clk_prepare(clk_tmp);
+		if (ret) {
+			HISI_FB_ERR
+			    ("fb%d dss_axi_clk clk_prepare failed, error=%d!\n",
+			     hisifd->index, ret);
+			return -EINVAL;
+		}
+
+		ret = clk_enable(clk_tmp);
+		if (ret) {
+			HISI_FB_ERR
+			    ("fb%d dss_axi_clk clk_enable failed, error=%d!\n",
+			     hisifd->index, ret);
+			return -EINVAL;
+		}
+	}
+
+	clk_tmp = hisifd->dss_pclk_dss_clk;
+	if (clk_tmp) {
+		ret = clk_prepare(clk_tmp);
+		if (ret) {
+			HISI_FB_ERR
+			    ("fb%d dss_pclk_dss_clk clk_prepare failed, error=%d!\n",
+			     hisifd->index, ret);
+			return -EINVAL;
+		}
+
+		ret = clk_enable(clk_tmp);
+		if (ret) {
+			HISI_FB_ERR
+			    ("fb%d dss_pclk_dss_clk clk_enable failed, error=%d!\n",
+			     hisifd->index, ret);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+int dpe_inner_clk_enable(struct hisi_fb_data_type *hisifd)
+{
+	int ret = 0;
+	struct clk *clk_tmp = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	clk_tmp = hisifd->dss_pri_clk;
+	if (clk_tmp) {
+		ret = clk_prepare(clk_tmp);
+		if (ret) {
+			HISI_FB_ERR
+			    ("fb%d dss_pri_clk clk_prepare failed, error=%d!\n",
+			     hisifd->index, ret);
+			return -EINVAL;
+		}
+
+		ret = clk_enable(clk_tmp);
+		if (ret) {
+			HISI_FB_ERR
+			    ("fb%d dss_pri_clk clk_enable failed, error=%d!\n",
+			     hisifd->index, ret);
+			return -EINVAL;
+		}
+	}
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		clk_tmp = hisifd->dss_pxl0_clk;
+		if (clk_tmp) {
+			ret = clk_prepare(clk_tmp);
+			if (ret) {
+				HISI_FB_ERR
+				    ("fb%d dss_pxl0_clk clk_prepare failed, error=%d!\n",
+				     hisifd->index, ret);
+				return -EINVAL;
+			}
+
+			ret = clk_enable(clk_tmp);
+			if (ret) {
+				HISI_FB_ERR
+				    ("fb%d dss_pxl0_clk clk_enable failed, error=%d!\n",
+				     hisifd->index, ret);
+				return -EINVAL;
+			}
+		}
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		clk_tmp = hisifd->dss_pxl1_clk;
+		if (clk_tmp) {
+			ret = clk_prepare(clk_tmp);
+			if (ret) {
+				HISI_FB_ERR
+				    ("fb%d dss_pxl1_clk clk_prepare failed, error=%d!\n",
+				     hisifd->index, ret);
+				return -EINVAL;
+			}
+
+			ret = clk_enable(clk_tmp);
+			if (ret) {
+				HISI_FB_ERR
+				    ("fb%d dss_pxl1_clk clk_enable failed, error=%d!\n",
+				     hisifd->index, ret);
+				return -EINVAL;
+			}
+		}
+	} else {
+		;
+	}
+
+	return 0;
+}
+
+int dpe_common_clk_disable(struct hisi_fb_data_type *hisifd)
+{
+	struct clk *clk_tmp = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	clk_tmp = hisifd->dss_pclk_dss_clk;
+	if (clk_tmp) {
+		clk_disable(clk_tmp);
+		clk_unprepare(clk_tmp);
+	}
+
+	clk_tmp = hisifd->dss_axi_clk;
+	if (clk_tmp) {
+		clk_disable(clk_tmp);
+		clk_unprepare(clk_tmp);
+	}
+#ifdef CONFIG_DSS_MMBUF_CLK_USED
+	clk_tmp = hisifd->dss_mmbuf_clk;
+	if (clk_tmp) {
+		clk_disable(clk_tmp);
+		clk_unprepare(clk_tmp);
+	}
+#endif
+
+	return 0;
+}
+
+int dpe_inner_clk_disable(struct hisi_fb_data_type *hisifd)
+{
+	struct clk *clk_tmp = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		clk_tmp = hisifd->dss_pxl0_clk;
+		if (clk_tmp) {
+			clk_disable(clk_tmp);
+			clk_unprepare(clk_tmp);
+		}
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		clk_tmp = hisifd->dss_pxl1_clk;
+		if (clk_tmp) {
+			clk_disable(clk_tmp);
+			clk_unprepare(clk_tmp);
+		}
+	} else {
+		;
+	}
+
+	clk_tmp = hisifd->dss_pri_clk;
+	if (clk_tmp) {
+		clk_disable(clk_tmp);
+		clk_unprepare(clk_tmp);
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+ **
+ */
+static int dpe_on(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	dpe_common_clk_enable(hisifd);
+	dpe_inner_clk_enable(hisifd);
+	/*DSS regulator are already enabled in fastboot, kernel don't care */
+	/*dpe_regulator_enable(hisifd); */
+
+	dss_inner_clk_common_enable(hisifd, false);
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		dss_inner_clk_pdp_enable(hisifd, false);
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		dss_inner_clk_sdp_enable(hisifd);
+	} else {
+		;
+	}
+
+	dpe_init(hisifd, false);
+	if (dpe_recover_pxl_clock(hisifd)) {
+		HISI_FB_ERR
+		    ("fb%d failed to recover pixel clock which is larger than 288M!\n",
+		     hisifd->index);
+		return -EINVAL;
+	}
+
+	if (is_ldi_panel(hisifd)) {
+		hisifd->panel_info.lcd_init_step = LCD_INIT_POWER_ON;
+		ret = panel_next_on(pdev);
+		if (ret) {
+			HISI_FB_ERR("fb%d failed ret %d\n", hisifd->index, ret);
+			return -EINVAL;
+		}
+	}
+
+	ret = panel_next_on(pdev);
+	if (hisifd->panel_info.vsync_ctrl_type == VSYNC_CTRL_NONE) {
+		dpe_interrupt_mask(hisifd);
+		dpe_interrupt_clear(hisifd);
+		dpe_irq_enable(hisifd);
+		dpe_interrupt_unmask(hisifd);
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return ret;
+}
+
+static int dpe_off(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	if (hisifd->panel_info.vsync_ctrl_type == VSYNC_CTRL_NONE) {
+		dpe_interrupt_mask(hisifd);
+		dpe_irq_disable(hisifd);
+	} else {
+		if (hisifd->vsync_ctrl.vsync_ctrl_enabled == 1) {
+			if (hisifd->panel_info.
+			    vsync_ctrl_type & VSYNC_CTRL_ISR_OFF) {
+				dpe_interrupt_mask(hisifd);
+				dpe_irq_disable(hisifd);
+				HISI_FB_INFO
+				    ("fb%d, need to disable dpe irq! vsync_ctrl_enabled=%d.\n",
+				     hisifd->index,
+				     hisifd->vsync_ctrl.vsync_ctrl_enabled);
+			}
+		}
+	}
+
+	ret = panel_next_off(pdev);
+
+	dpe_deinit(hisifd);
+	dpe_check_itf_status(hisifd);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		dss_inner_clk_pdp_disable(hisifd);
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		dss_inner_clk_sdp_disable(hisifd);
+	} else {
+		;
+	}
+	dss_inner_clk_common_disable(hisifd);
+
+	/*dpe_regulator_disable(hisifd); */
+	dpe_inner_clk_disable(hisifd);
+	dpe_common_clk_disable(hisifd);
+
+	if (hisifd->vsync_ctrl_type != VSYNC_CTRL_NONE) {
+		if (!is_dss_idle_enable())
+			hisifd->panel_info.vsync_ctrl_type = VSYNC_CTRL_NONE;
+		else
+			hisifd->panel_info.vsync_ctrl_type =
+			    hisifd->vsync_ctrl_type;
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return ret;
+}
+
+static int dpe_remove(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	ret = panel_next_remove(pdev);
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return ret;
+}
+
+static int dpe_set_backlight(struct platform_device *pdev, uint32_t bl_level)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct hisi_panel_info *pinfo = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+	pinfo = &(hisifd->panel_info);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	HISI_FB_DEBUG("fb%d, bl_level=%d.\n", hisifd->index, bl_level);
+
+	if (pinfo->bl_max < 1) {
+		HISI_FB_ERR("bl_max(%d) is out of range!!", pinfo->bl_max);
+		return -EINVAL;
+	}
+
+	if (bl_level > pinfo->bl_max) {
+		bl_level = pinfo->bl_max;
+	}
+
+	if (bl_level < pinfo->bl_min && bl_level) {
+		bl_level = pinfo->bl_min;
+	}
+
+	ret = panel_next_set_backlight(pdev, bl_level);
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return ret;
+}
+
+static int dpe_vsync_ctrl(struct platform_device *pdev, int enable)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	if (enable) {
+		ret = panel_next_vsync_ctrl(pdev, enable);
+		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_ISR_OFF) {
+			dpe_interrupt_mask(hisifd);
+			dpe_interrupt_clear(hisifd);
+			dpe_irq_enable(hisifd);
+			dpe_interrupt_unmask(hisifd);
+		}
+	} else {
+		ret = panel_next_vsync_ctrl(pdev, enable);
+		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_ISR_OFF) {
+			dpe_interrupt_mask(hisifd);
+			dpe_interrupt_clear(hisifd);
+			dpe_irq_disable_nosync(hisifd);
+		}
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return ret;
+}
+
+static int dpe_regulator_clk_irq_setup(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct hisi_panel_info *pinfo = NULL;
+	struct dss_clk_rate *pdss_clk_rate = NULL;
+	const char *irq_name = NULL;
+	irqreturn_t(*isr_fnc)(int irq, void *ptr);
+	int ret = 0;
+	uint64_t pxl_clk_rate = 0;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	pinfo = &(hisifd->panel_info);
+	pdss_clk_rate = get_dss_clk_rate(hisifd);
+	BUG_ON(pdss_clk_rate == NULL);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		irq_name = IRQ_PDP_NAME;
+		isr_fnc = dss_pdp_isr;
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		irq_name = IRQ_SDP_NAME;
+		isr_fnc = dss_sdp_isr;
+	} else if (hisifd->index == AUXILIARY_PANEL_IDX) {
+		irq_name = IRQ_ADP_NAME;
+		isr_fnc = dss_adp_isr;
+	} else {
+		HISI_FB_ERR("fb%d, not support this device!\n", hisifd->index);
+		return -EINVAL;
+	}
+
+	HISI_FB_INFO("dss_pclk_dss_clk:[%llu]->[%llu].\n",
+		     pdss_clk_rate->dss_pclk_dss_rate,
+		     (uint64_t) clk_get_rate(hisifd->dss_pclk_dss_clk));
+
+	ret =
+	    clk_set_rate(hisifd->dss_pri_clk, pdss_clk_rate->dss_pri_clk_rate);
+	if (ret < 0) {
+		HISI_FB_ERR
+		    ("fb%d dss_pri_clk clk_set_rate(%llu) failed, error=%d!\n",
+		     hisifd->index, pdss_clk_rate->dss_pri_clk_rate, ret);
+		return -EINVAL;
+	}
+	HISI_FB_INFO("dss_pri_clk:[%llu]->[%llu].\n",
+		     pdss_clk_rate->dss_pri_clk_rate,
+		     (uint64_t) clk_get_rate(hisifd->dss_pri_clk));
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		pxl_clk_rate =
+		    (pinfo->pxl_clk_rate >
+		     DSS_MAX_PXL0_CLK_288M) ? DSS_MAX_PXL0_CLK_288M : pinfo->
+		    pxl_clk_rate;
+		if (pinfo->pxl_clk_rate_adjust > 0) {
+			ret =
+			    clk_set_rate(hisifd->dss_pxl0_clk,
+					 pinfo->pxl_clk_rate_adjust);
+		} else {
+			ret = clk_set_rate(hisifd->dss_pxl0_clk, pxl_clk_rate);
+		}
+
+		if (ret < 0) {
+			HISI_FB_ERR
+			    ("fb%d dss_pxl0_clk clk_set_rate(%llu) failed, error=%d!\n",
+			     hisifd->index, pinfo->pxl_clk_rate, ret);
+		}
+		HISI_FB_INFO("dss_pxl0_clk:[%llu]->[%llu].\n",
+			     pinfo->pxl_clk_rate,
+			     (uint64_t) clk_get_rate(hisifd->dss_pxl0_clk));
+	} else if ((hisifd->index == EXTERNAL_PANEL_IDX)
+		   && !hisifd->panel_info.fake_hdmi) {
+		ret = clk_set_rate(hisifd->dss_pxl1_clk, pinfo->pxl_clk_rate);
+		if (ret < 0) {
+			HISI_FB_ERR
+			    ("fb%d dss_pxl1_clk clk_set_rate(%llu) failed, error=%d!\n",
+			     hisifd->index, pinfo->pxl_clk_rate, ret);
+		}
+		HISI_FB_INFO("dss_pxl1_clk:[%llu]->[%llu].\n",
+			     pinfo->pxl_clk_rate,
+			     (uint64_t) clk_get_rate(hisifd->dss_pxl1_clk));
+	} else {
+		;
+	}
+
+	if (hisifd->dpe_irq) {
+		ret =
+		    request_irq(hisifd->dpe_irq, isr_fnc, 0, irq_name,
+				(void *)hisifd);
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("fb%d request_irq failed, irq_no=%d error=%d!\n",
+			     hisifd->index, hisifd->dpe_irq, ret);
+			return ret;
+		} else {
+			disable_irq(hisifd->dpe_irq);
+		}
+	}
+	return 0;
+}
+
+static int dpe_probe(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct platform_device *hisi_fb_dev = NULL;
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct fb_info *fbi = NULL;
+	int ret = 0;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	ret = dpe_regulator_clk_irq_setup(pdev);
+	if (ret) {
+		HISI_FB_ERR("fb%d dpe_irq_clk_setup failed, error=%d!\n",
+			    hisifd->index, ret);
+		goto err;
+	}
+
+	/* alloc device */
+	hisi_fb_dev = platform_device_alloc(DEV_NAME_FB, pdev->id);
+	if (!hisi_fb_dev) {
+		HISI_FB_ERR("fb%d platform_device_alloc failed, error=%d!\n",
+			    hisifd->index, ret);
+		ret = -ENOMEM;
+		goto err_device_alloc;
+	}
+
+	/* link to the latest pdev */
+	hisifd->pdev = hisi_fb_dev;
+
+	/* alloc panel device data */
+	ret =
+	    platform_device_add_data(hisi_fb_dev, dev_get_platdata(&pdev->dev),
+				     sizeof(struct hisi_fb_panel_data));
+	if (ret) {
+		HISI_FB_ERR("fb%d platform_device_add_data failed, error=%d!\n",
+			    hisifd->index, ret);
+		goto err_device_put;
+	}
+
+	/* data chain */
+	pdata = dev_get_platdata(&hisi_fb_dev->dev);
+	pdata->on = dpe_on;
+	pdata->off = dpe_off;
+	pdata->remove = dpe_remove;
+	pdata->set_backlight = dpe_set_backlight;
+	pdata->vsync_ctrl = dpe_vsync_ctrl;
+	pdata->next = pdev;
+
+	/* get/set panel info */
+	memcpy(&hisifd->panel_info, pdata->panel_info,
+	       sizeof(struct hisi_panel_info));
+
+	fbi = hisifd->fbi;
+	fbi->var.pixclock = hisifd->panel_info.pxl_clk_rate;
+	/*fbi->var.pixclock = clk_round_rate(hisifd->dpe_clk,
+			hisifd->panel_info.pxl_clk_rate); */
+	fbi->var.left_margin = hisifd->panel_info.ldi.h_back_porch;
+	fbi->var.right_margin = hisifd->panel_info.ldi.h_front_porch;
+	fbi->var.upper_margin = hisifd->panel_info.ldi.v_back_porch;
+	fbi->var.lower_margin = hisifd->panel_info.ldi.v_front_porch;
+	fbi->var.hsync_len = hisifd->panel_info.ldi.h_pulse_width;
+	fbi->var.vsync_len = hisifd->panel_info.ldi.v_pulse_width;
+
+	hisifd->vsync_ctrl_type = hisifd->panel_info.vsync_ctrl_type;
+
+	/* set driver data */
+	platform_set_drvdata(hisi_fb_dev, hisifd);
+	ret = platform_device_add(hisi_fb_dev);
+	if (ret) {
+		HISI_FB_ERR("fb%d platform_device_add failed, error=%d!\n",
+			    hisifd->index, ret);
+		goto err_device_put;
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return 0;
+
+ err_device_put:
+	platform_device_put(hisi_fb_dev);
+ err_device_alloc:
+ err:
+	return ret;
+}
+
+static struct platform_driver this_driver = {
+	.probe = dpe_probe,
+	.remove = NULL,
+	.suspend = NULL,
+	.resume = NULL,
+	.shutdown = NULL,
+	.driver = {
+		   .name = DEV_NAME_DSS_DPE,
+		   },
+};
+
+static int __init dpe_driver_init(void)
+{
+	int ret = 0;
+
+	ret = platform_driver_register(&this_driver);
+	if (ret) {
+		HISI_FB_ERR("platform_driver_register failed, error=%d!\n",
+			    ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+module_init(dpe_driver_init);
diff --git a/drivers/video/fbdev/hisi/dss/hisi_dpe_utils.h b/drivers/video/fbdev/hisi/dss/hisi_dpe_utils.h
new file mode 100755
index 000000000000..5cacb874c39b
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_dpe_utils.h
@@ -0,0 +1,64 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#ifndef HISI_DPE_UTILS_H
+#define HISI_DPE_UTILS_H
+
+#include "hisi_fb.h"
+
+#define COMFORM_MAX	80
+#define CHANGE_MAX	100
+#define DISCOUNT_COEFFICIENT(value)  (CHANGE_MAX - value) / CHANGE_MAX
+
+struct dss_clk_rate *get_dss_clk_rate(struct hisi_fb_data_type *hisifd);
+int set_dss_clk_rate(struct hisi_fb_data_type *hisifd,
+		     dss_clk_rate_t dss_clk_rate);
+
+void init_post_scf(struct hisi_fb_data_type *hisifd);
+void init_dbuf(struct hisi_fb_data_type *hisifd);
+void init_dpp(struct hisi_fb_data_type *hisifd);
+void init_acm(struct hisi_fb_data_type *hisifd);
+void init_igm_gmp_xcc_gm(struct hisi_fb_data_type *hisifd);
+void init_ifbc(struct hisi_fb_data_type *hisifd);
+void init_ldi(struct hisi_fb_data_type *hisifd, bool fastboot_enable);
+void deinit_ldi(struct hisi_fb_data_type *hisifd);
+void enable_ldi(struct hisi_fb_data_type *hisifd);
+void disable_ldi(struct hisi_fb_data_type *hisifd);
+void ldi_frame_update(struct hisi_fb_data_type *hisifd, bool update);
+void single_frame_update(struct hisi_fb_data_type *hisifd);
+void ldi_data_gate(struct hisi_fb_data_type *hisifd, bool enble);
+int dpe_recover_pxl_clock(struct hisi_fb_data_type *hisifd);
+void init_dpp_csc(struct hisi_fb_data_type *hisifd);
+
+/* isr */
+irqreturn_t dss_pdp_isr(int irq, void *ptr);
+irqreturn_t dss_sdp_isr(int irq, void *ptr);
+irqreturn_t dss_adp_isr(int irq, void *ptr);
+
+void dpe_interrupt_clear(struct hisi_fb_data_type *hisifd);
+void dpe_interrupt_unmask(struct hisi_fb_data_type *hisifd);
+void dpe_interrupt_mask(struct hisi_fb_data_type *hisifd);
+int dpe_common_clk_enable(struct hisi_fb_data_type *hisifd);
+int dpe_inner_clk_enable(struct hisi_fb_data_type *hisifd);
+int dpe_common_clk_disable(struct hisi_fb_data_type *hisifd);
+int dpe_inner_clk_disable(struct hisi_fb_data_type *hisifd);
+void dss_inner_clk_common_enable(struct hisi_fb_data_type *hisifd,
+				 bool fastboot_enable);
+void dss_inner_clk_common_disable(struct hisi_fb_data_type *hisifd);
+void dss_inner_clk_pdp_enable(struct hisi_fb_data_type *hisifd,
+			      bool fastboot_enable);
+void dss_inner_clk_pdp_disable(struct hisi_fb_data_type *hisifd);
+void dss_inner_clk_sdp_enable(struct hisi_fb_data_type *hisifd);
+void dss_inner_clk_sdp_disable(struct hisi_fb_data_type *hisifd);
+
+#endif
diff --git a/drivers/video/fbdev/hisi/dss/hisi_fb.c b/drivers/video/fbdev/hisi/dss/hisi_fb.c
new file mode 100755
index 000000000000..e3ff413e5d42
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_fb.c
@@ -0,0 +1,2232 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_fb.h"
+#include "hisi_overlay_utils.h"
+#include <linux/init.h>
+
+static int hisi_fb_resource_initialized;
+static struct platform_device *pdev_list[HISI_FB_MAX_DEV_LIST] = { 0 };
+
+static int pdev_list_cnt;
+struct fb_info *fbi_list[HISI_FB_MAX_FBI_LIST] = { 0 };
+
+static int fbi_list_index;
+
+struct hisi_fb_data_type *hisifd_list[HISI_FB_MAX_FBI_LIST] = { 0 };
+
+static int hisifd_list_index;
+
+#define HISI_FB_ION_CLIENT_NAME	"hisi_fb_ion"
+
+uint32_t g_dts_resouce_ready = 0;
+uint32_t g_dss_base_phy = 0;
+uint32_t g_dss_module_resource_initialized = 0;
+
+struct iommu_domain *g_hisi_domain;
+
+static char __iomem *hisifd_dss_base;
+static char __iomem *hisifd_peri_crg_base;
+static char __iomem *hisifd_sctrl_base;
+static char __iomem *hisifd_pctrl_base;
+static char __iomem *hisifd_noc_dss_base;
+static char __iomem *hisifd_mmbuf_crg_base;
+static char __iomem *hisifd_mmbuf_asc0_base;
+static char __iomem *hisifd_pmctrl_base;
+
+static uint32_t hisifd_irq_pdp;
+static uint32_t hisifd_irq_sdp;
+static uint32_t hisifd_irq_adp;
+static uint32_t hisifd_irq_dsi0;
+static uint32_t hisifd_irq_dsi1;
+
+/*DSS regulators are already enabled in fastboot, so kernel don't care*/
+/*
+#define MAX_DPE_NUM	(2)
+static struct regulator_bulk_data g_dpe_regulator[MAX_DPE_NUM] = {{0}, {0}};
+*/
+
+static struct clk *dss_aclk_dss;
+static struct clk *dss_pclk_dss;
+static struct clk *dss_clk_edc0;
+static struct clk *dss_clk_ldi0;
+static struct clk *dss_clk_ldi1;
+static struct clk *dss_clk_dss_axi_mm;
+static struct clk *dss_pclk_mmbuf;
+static struct clk *dss_clk_txdphy0_ref;
+static struct clk *dss_clk_txdphy1_ref;
+static struct clk *dss_clk_txdphy0_cfg;
+static struct clk *dss_clk_txdphy1_cfg;
+static struct clk *dss_pclk_dsi0;
+static struct clk *dss_pclk_dsi1;
+
+int g_debug_enable_lcd_sleep_in = 0;
+int g_err_status = 0;
+
+/*
+ ** for debug, S_IRUGO
+ ** /sys/module/hisifb/parameters
+ */
+unsigned hisi_fb_msg_level = 7;
+module_param_named(debug_msg_level, hisi_fb_msg_level, int, 0644);
+MODULE_PARM_DESC(debug_msg_level, "hisi fb msg level");
+
+int g_debug_mmu_error = 0;
+module_param_named(debug_mmu_error, g_debug_mmu_error, int, 0644);
+MODULE_PARM_DESC(debug_mmu_error, "hisi mmu error debug");
+
+int g_debug_ldi_underflow = 0;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(debug_ldi_underflow, g_debug_ldi_underflow, int, 0644);
+MODULE_PARM_DESC(debug_ldi_underflow, "hisi ldi_underflow debug");
+#endif
+
+int g_debug_ldi_underflow_clear = 1;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(debug_ldi_underflow_clear,
+		g_debug_ldi_underflow_clear, int, 0644);
+MODULE_PARM_DESC(debug_ldi_underflow_clear, "hisi ldi_underflow_clear debug");
+#endif
+
+int g_debug_set_reg_val = 0;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(debug_set_reg_val, g_debug_set_reg_val, int, 0644);
+MODULE_PARM_DESC(debug_set_reg_val, "hisi set reg val debug");
+#endif
+
+int g_debug_online_vsync = 0;
+module_param_named(debug_online_vsync, g_debug_online_vsync, int, 0644);
+MODULE_PARM_DESC(debug_online_vsync, "hisi online vsync debug");
+
+int g_debug_ovl_online_composer = 0;
+module_param_named(debug_ovl_online_composer,
+		g_debug_ovl_online_composer, int, 0644);
+MODULE_PARM_DESC(debug_ovl_online_composer,
+		"hisi overlay online composer debug");
+
+int g_debug_ovl_online_composer_hold = 0;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(debug_ovl_online_composer_hold,
+		g_debug_ovl_online_composer_hold, int, 0644);
+MODULE_PARM_DESC(debug_ovl_online_composer_hold,
+		"hisi overlay online composer hold debug");
+#endif
+
+int g_debug_ovl_online_composer_return = 0;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(debug_ovl_online_composer_return,
+		g_debug_ovl_online_composer_return, int, 0644);
+MODULE_PARM_DESC(debug_ovl_online_composer_return,
+		"hisi overlay online composer return debug");
+#endif
+
+int g_debug_ovl_online_composer_timediff = 0;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(debug_ovl_online_composer_timediff,
+		g_debug_ovl_online_composer_timediff, int, 0644);
+MODULE_PARM_DESC(debug_ovl_online_composer_timediff,
+		"hisi overlay online composer timediff debug");
+#endif
+
+int g_debug_ovl_online_composer_time_threshold = 6000;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(debug_ovl_online_composer_time_threshold,
+		g_debug_ovl_online_composer_time_threshold, int, 0644);
+MODULE_PARM_DESC(debug_ovl_online_composer_time_threshold,
+		"hisi overlay online composer time threshold debug");
+#endif
+
+int g_debug_ovl_block_composer = 0;
+module_param_named(debug_ovl_block_composer,
+		g_debug_ovl_block_composer, int, 0644);
+MODULE_PARM_DESC(debug_ovl_block_composer,
+		"hisi overlay block composer debug");
+
+int g_debug_ovl_cmdlist = 0;
+module_param_named(debug_ovl_cmdlist, g_debug_ovl_cmdlist, int, 0644);
+MODULE_PARM_DESC(debug_ovl_cmdlist, "hisi overlay cmdlist debug");
+
+int g_dump_cmdlist_content = 0;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(dump_cmdlist_content, g_dump_cmdlist_content, int, 0644);
+MODULE_PARM_DESC(dump_cmdlist_content, "hisi overlay dump cmdlist content");
+#endif
+
+int g_enable_ovl_cmdlist_online = 1;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(enable_ovl_cmdlist_online,
+		g_enable_ovl_cmdlist_online, int, 0644);
+MODULE_PARM_DESC(enable_ovl_cmdlist_online,
+		"hisi overlay cmdlist online enable");
+#endif
+
+int g_enable_ovl_cmdlist_offline = 1;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(enable_ovl_cmdlist_offline,
+		g_enable_ovl_cmdlist_offline, int, 0644);
+MODULE_PARM_DESC(enable_ovl_cmdlist_offline,
+		"hisi overlay cmdlist offline enable");
+#endif
+
+int g_rdma_stretch_threshold = RDMA_STRETCH_THRESHOLD;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(rdma_stretch_threshold,
+		g_rdma_stretch_threshold, int, 0644);
+MODULE_PARM_DESC(rdma_stretch_threshold, "hisi rdma stretch threshold");
+#endif
+
+int g_enable_dirty_region_updt = 1;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(enable_dirty_region_updt,
+		g_enable_dirty_region_updt, int, 0644);
+MODULE_PARM_DESC(enable_dirty_region_updt,
+		"hisi dss dirty_region_updt enable");
+#endif
+
+int g_debug_dirty_region_updt = 0;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(debug_dirty_region_updt,
+		g_debug_dirty_region_updt, int, 0644);
+MODULE_PARM_DESC(debug_dirty_region_updt,
+		"hisi dss dirty_region_updt debug");
+#endif
+
+int g_enable_crc_debug = 0;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(enable_crc_debug, g_enable_crc_debug, int, 0644);
+MODULE_PARM_DESC(enable_crc_debug, "hisi dss crc debug enable");
+#endif
+
+int g_ldi_data_gate_en = 0;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(enable_ldi_data_gate, g_ldi_data_gate_en, int, 0644);
+MODULE_PARM_DESC(enable_ldi_data_gate, "hisi dss ldi data gate enable");
+#endif
+
+int g_debug_need_save_file = 0;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(debug_need_save_file, g_debug_need_save_file, int, 0644);
+MODULE_PARM_DESC(debug_need_save_file, "hisi dss debug need to save file");
+#endif
+
+int g_debug_ovl_credit_step = 0;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(debug_ovl_credit_step, g_debug_ovl_credit_step, int, 0644);
+MODULE_PARM_DESC(debug_ovl_credit_step, "hisi overlay debug_ovl_credit_step");
+#endif
+
+int g_debug_layerbuf_sync = 0;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(debug_layerbuf_sync, g_debug_layerbuf_sync, int, 0644);
+MODULE_PARM_DESC(debug_layerbuf_sync, "hisi dss debug_layerbuf_sync");
+#endif
+
+int g_enable_dss_idle;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(enable_dss_idle, g_enable_dss_idle, int, 0644);
+MODULE_PARM_DESC(enable_dss_idle, "hisi dss enable_dss_idle");
+#endif
+
+unsigned int g_dss_smmu_outstanding = DSS_SMMU_OUTSTANDING_VAL + 1;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(dss_smmu_outstanding, g_dss_smmu_outstanding, int, 0644);
+MODULE_PARM_DESC(dss_smmu_outstanding, "hisi dss smmu outstanding");
+#endif
+
+int g_debug_dump_mmbuf = 0;
+module_param_named(debug_dump_mmbuf, g_debug_dump_mmbuf, int, 0644);
+MODULE_PARM_DESC(debug_dump_mmbuf, "hisi dump mmbuf debug");
+
+uint32_t g_underflow_stop_perf_stat = 0;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(underflow_stop_perf, g_underflow_stop_perf_stat, int, 0600);
+MODULE_PARM_DESC(underflow_stop_perf, "hisi underflow stop perf stat");
+#endif
+
+uint32_t g_dss_min_bandwidth_inbusbusy = 200;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(dss_min_bandwidth_inbusbusy,
+		g_dss_min_bandwidth_inbusbusy, int, 0644);
+MODULE_PARM_DESC(dss_min_bandwidth_inbusbusy,
+		"hisi overlay dss_min_bandwidth_inbusbusy");
+#endif
+
+uint32_t g_mmbuf_addr_test = 0;
+#ifdef CONFIG_FB_DEBUG_USED
+module_param_named(mmbuf_addr_test, g_mmbuf_addr_test, int, 0600);
+MODULE_PARM_DESC(mmbuf_addr_test, "hisi mmbuf addr test");
+#endif
+
+/******************************************************************************
+ ** FUNCTIONS PROTOTYPES
+ */
+static int hisi_fb_register(struct hisi_fb_data_type *hisifd);
+
+static int hisi_fb_open(struct fb_info *info, int user);
+static int hisi_fb_release(struct fb_info *info, int user);
+static int hisi_fb_pan_display(struct fb_var_screeninfo *var,
+			       struct fb_info *info);
+static int hisi_fb_check_var(struct fb_var_screeninfo *var,
+			     struct fb_info *info);
+static int hisi_fb_set_par(struct fb_info *info);
+static int hisi_fb_ioctl(struct fb_info *info, unsigned int cmd,
+			 unsigned long arg);
+static int hisi_fb_mmap(struct fb_info *info, struct vm_area_struct *vma);
+
+static int hisi_fb_suspend_sub(struct hisi_fb_data_type *hisifd);
+static int hisi_fb_resume_sub(struct hisi_fb_data_type *hisifd);
+
+/*******************************************************************************
+ **
+ */
+struct platform_device *hisi_fb_add_device(struct platform_device *pdev)
+{
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct platform_device *this_dev = NULL;
+	struct fb_info *fbi = NULL;
+	struct hisi_fb_data_type *hisifd = NULL;
+	uint32_t type = 0;
+	uint32_t id = 0;
+
+	BUG_ON(pdev == NULL);
+	pdata = dev_get_platdata(&pdev->dev);
+	BUG_ON(pdata == NULL);
+
+	if (fbi_list_index >= HISI_FB_MAX_FBI_LIST) {
+		HISI_FB_ERR("no more framebuffer info list!\n");
+		return NULL;
+	}
+
+	id = pdev->id;
+	type = pdata->panel_info->type;
+
+	/* alloc panel device data */
+	this_dev = hisi_fb_device_alloc(pdata, type, id);
+	if (!this_dev) {
+		HISI_FB_ERR("failed to hisi_fb_device_alloc!\n");
+		return NULL;
+	}
+
+	/* alloc framebuffer info + par data */
+	fbi = framebuffer_alloc(sizeof(struct hisi_fb_data_type), NULL);
+	if (fbi == NULL) {
+		HISI_FB_ERR("can't alloc framebuffer info data!\n");
+		platform_device_put(this_dev);
+		return NULL;
+	}
+
+	/* data chain */
+	pdata = dev_get_platdata(&this_dev->dev);
+	pdata->next = pdev;
+
+	hisifd = (struct hisi_fb_data_type *)fbi->par;
+	memset(hisifd, 0, sizeof(struct hisi_fb_data_type));
+	hisifd->fbi = fbi;
+
+	hisifd->fb_imgType = HISI_FB_PIXEL_FORMAT_BGRA_8888;
+	hisifd->index = fbi_list_index;
+	hisifd->dss_base = hisifd_dss_base;
+	hisifd->peri_crg_base = hisifd_peri_crg_base;
+	hisifd->sctrl_base = hisifd_sctrl_base;
+	hisifd->pctrl_base = hisifd_pctrl_base;
+	hisifd->noc_dss_base = hisifd_noc_dss_base;
+	hisifd->mmbuf_crg_base = hisifd_mmbuf_crg_base;
+	hisifd->mmbuf_asc0_base = hisifd_mmbuf_asc0_base;
+	hisifd->pmctrl_base = hisifd_pmctrl_base;
+
+	hisifd->mipi_dsi0_base = hisifd->dss_base + DSS_MIPI_DSI0_OFFSET;
+	hisifd->mipi_dsi1_base = hisifd->dss_base + DSS_MIPI_DSI1_OFFSET;
+	hisifd->dss_base_phy = g_dss_base_phy;
+
+	hisifd->dss_axi_clk = dss_aclk_dss;
+	hisifd->dss_pclk_dss_clk = dss_pclk_dss;
+	hisifd->dss_pri_clk = dss_clk_edc0;
+	hisifd->dss_pxl0_clk = dss_clk_ldi0;
+	hisifd->dss_pxl1_clk = dss_clk_ldi1;
+	hisifd->dss_mmbuf_clk = dss_clk_dss_axi_mm;
+	hisifd->dss_pclk_mmbuf_clk = dss_pclk_mmbuf;
+	hisifd->dss_dphy0_ref_clk = dss_clk_txdphy0_ref;
+	hisifd->dss_dphy1_ref_clk = dss_clk_txdphy1_ref;
+	hisifd->dss_dphy0_cfg_clk = dss_clk_txdphy0_cfg;
+	hisifd->dss_dphy1_cfg_clk = dss_clk_txdphy1_cfg;
+	hisifd->dss_pclk_dsi0_clk = dss_pclk_dsi0;
+	hisifd->dss_pclk_dsi1_clk = dss_pclk_dsi1;
+
+	hisifd->dsi0_irq = hisifd_irq_dsi0;
+	hisifd->dsi1_irq = hisifd_irq_dsi1;
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		hisifd->fb_num = HISI_FB0_NUM;
+		hisifd->dpe_irq = hisifd_irq_pdp;
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		hisifd->fb_num = HISI_FB1_NUM;
+		hisifd->dpe_irq = hisifd_irq_sdp;
+	} else if (hisifd->index == AUXILIARY_PANEL_IDX) {
+		hisifd->fb_num = HISI_FB2_NUM;
+		hisifd->dpe_irq = hisifd_irq_adp;
+	} else {
+		HISI_FB_ERR("fb%d not support now!\n", hisifd->index);
+		platform_device_put(this_dev);
+		framebuffer_release(fbi);
+		return NULL;
+	}
+
+	/* link to the latest pdev */
+	hisifd->pdev = this_dev;
+
+	hisifd_list[hisifd_list_index++] = hisifd;
+	fbi_list[fbi_list_index++] = fbi;
+
+	/* get/set panel info */
+	memcpy(&hisifd->panel_info, pdata->panel_info,
+	       sizeof(struct hisi_panel_info));
+
+	/* set driver data */
+	platform_set_drvdata(this_dev, hisifd);
+
+	if (platform_device_add(this_dev)) {
+		HISI_FB_ERR("failed to platform_device_add!\n");
+		framebuffer_release(fbi);
+		platform_device_put(this_dev);
+		hisifd_list_index--;
+		fbi_list_index--;
+		return NULL;
+	}
+
+	return this_dev;
+}
+
+int hisi_fb_blank_sub(int blank_mode, struct fb_info *info)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	int ret = 0;
+	int curr_pwr_state = 0;
+
+	hisifd = (struct hisi_fb_data_type *)info->par;
+	BUG_ON(hisifd == NULL);
+
+	down(&hisifd->blank_sem);
+	down(&hisifd->blank_sem0);
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		if (!hisifd->panel_power_on) {
+			ret = hisifd->on_fnc(hisifd);
+			if (ret == 0) {
+				hisifd->panel_power_on = true;
+			}
+		}
+		break;
+
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_NORMAL:
+	case FB_BLANK_POWERDOWN:
+	default:
+		if (hisifd->panel_power_on) {
+			curr_pwr_state = hisifd->panel_power_on;
+			hisifd->panel_power_on = false;
+
+			if (hisifd->bl_cancel) {
+				hisifd->bl_cancel(hisifd);
+			}
+
+			ret = hisifd->off_fnc(hisifd);
+			if (ret)
+				hisifd->panel_power_on = curr_pwr_state;
+
+			if (hisifd->buf_sync_suspend)
+				hisifd->buf_sync_suspend(hisifd);
+		}
+		break;
+	}
+	up(&hisifd->blank_sem);
+	up(&hisifd->blank_sem0);
+
+	return ret;
+}
+
+static int hisi_fb_open_sub(struct fb_info *info)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	int ret = 0;
+	bool needed = false;
+
+	BUG_ON(info == NULL);
+	hisifd = (struct hisi_fb_data_type *)info->par;
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->set_fastboot_fnc) {
+		needed = hisifd->set_fastboot_fnc(info);
+	}
+
+	if (!needed) {
+		ret = hisi_fb_blank_sub(FB_BLANK_UNBLANK, info);
+		if (ret != 0) {
+			HISI_FB_ERR("can't turn on display!\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int hisi_fb_release_sub(struct fb_info *info)
+{
+	int ret = 0;
+
+	BUG_ON(info == NULL);
+
+	ret = hisi_fb_blank_sub(FB_BLANK_POWERDOWN, info);
+	if (ret != 0) {
+		HISI_FB_ERR("can't turn off display!\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+ **
+ */
+static int hisi_fb_blank(int blank_mode, struct fb_info *info)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	if (NULL == info) {
+		HISI_FB_ERR("NULL Pointer\n");
+		return -EINVAL;
+	}
+
+	hisifd = (struct hisi_fb_data_type *)info->par;
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL Pointer\n");
+		return -EINVAL;
+	}
+
+	if (hisifd->panel_info.fake_hdmi
+	    && (hisifd->index == EXTERNAL_PANEL_IDX)) {
+		HISI_FB_INFO("it is fake, blank it fail \n");
+		return -EINVAL;
+	}
+#if 0
+	if (blank_mode == FB_BLANK_POWERDOWN) {
+		struct fb_event event;
+		event.info = info;
+		event.data = &blank_mode;
+		fb_notifier_call_chain(FB_EVENT_BLANK, &event);
+	}
+#endif
+
+	if (hisifd->index == AUXILIARY_PANEL_IDX) {
+		HISI_FB_DEBUG("fb%d, blank_mode(%d) +.\n", hisifd->index,
+			      blank_mode);
+	} else {
+		HISI_FB_INFO("fb%d, blank_mode(%d) +.\n", hisifd->index,
+			     blank_mode);
+	}
+
+	ret = hisi_fb_blank_sub(blank_mode, info);
+	if (ret != 0) {
+		HISI_FB_ERR("fb%d, blank_mode(%d) failed!\n", hisifd->index,
+			    blank_mode);
+		return ret;
+	}
+
+	if (hisifd->index == AUXILIARY_PANEL_IDX) {
+		HISI_FB_DEBUG("fb%d, blank_mode(%d) -.\n", hisifd->index,
+			      blank_mode);
+	} else {
+		HISI_FB_INFO("fb%d, blank_mode(%d) -.\n", hisifd->index,
+			     blank_mode);
+	}
+
+	return 0;
+}
+
+static int hisi_fb_open(struct fb_info *info, int user)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	if (NULL == info) {
+		HISI_FB_ERR("NULL Pointer\n");
+		return -EINVAL;
+	}
+
+	hisifd = (struct hisi_fb_data_type *)info->par;
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL Pointer\n");
+		return -EINVAL;
+	}
+
+	if (hisifd->panel_info.fake_hdmi
+	    && (hisifd->index == EXTERNAL_PANEL_IDX)) {
+		HISI_FB_INFO("fb%d, is fake, open it fail \n", hisifd->index);
+		return -EINVAL;
+	}
+
+	if (!hisifd->ref_cnt) {
+		HISI_FB_DEBUG("fb%d, +!\n", hisifd->index);
+		if (hisifd->open_sub_fnc) {
+			ret = hisifd->open_sub_fnc(info);
+		}
+		HISI_FB_DEBUG("fb%d, -!\n", hisifd->index);
+	}
+
+	hisifd->ref_cnt++;
+
+	return ret;
+}
+
+static int hisi_fb_release(struct fb_info *info, int user)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	if (NULL == info) {
+		HISI_FB_ERR("NULL Pointer\n");
+		return -EINVAL;
+	}
+
+	hisifd = (struct hisi_fb_data_type *)info->par;
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL Pointer\n");
+		return -EINVAL;
+	}
+
+	if (hisifd->panel_info.fake_hdmi
+	    && (hisifd->index == EXTERNAL_PANEL_IDX)) {
+		HISI_FB_INFO("fb%d, is fake, release it fail \n",
+			     hisifd->index);
+		return -EINVAL;
+	}
+
+	if (!hisifd->ref_cnt) {
+		HISI_FB_INFO("try to close unopened fb%d!\n", hisifd->index);
+		return -EINVAL;
+	}
+
+	hisifd->ref_cnt--;
+
+	if (!hisifd->ref_cnt) {
+		HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+		if (hisifd->release_sub_fnc) {
+			ret = hisifd->release_sub_fnc(info);
+		}
+		HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+		if (hisifd->index == PRIMARY_PANEL_IDX) {
+			if (hisifd->fb_mem_free_flag)
+				hisifb_free_fb_buffer(hisifd);
+		}
+	}
+	return ret;
+}
+
+static int hisi_fb_check_var(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	if (NULL == info) {
+		HISI_FB_ERR("NULL Pointer\n");
+		return -EINVAL;
+	}
+
+	hisifd = (struct hisi_fb_data_type *)info->par;
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL Pointer\n");
+		return -EINVAL;
+	}
+
+	if (var->rotate != FB_ROTATE_UR) {
+		HISI_FB_ERR("error rotate %d!\n", var->rotate);
+		return -EINVAL;
+	}
+
+	if (var->grayscale != info->var.grayscale) {
+		HISI_FB_DEBUG("error grayscale %d!\n", var->grayscale);
+		return -EINVAL;
+	}
+
+	if ((var->xres_virtual <= 0) || (var->yres_virtual <= 0)) {
+		HISI_FB_ERR("xres_virtual=%d yres_virtual=%d out of range!",
+			    var->xres_virtual, var->yres_virtual);
+		return -EINVAL;
+	}
+#if 0
+	if (info->fix.smem_len <
+	    (hisifb_line_length
+	     (hisifd->index, var->xres_virtual,
+	      (var->bits_per_pixel >> 3)) * var->yres_virtual)) {
+		HISI_FB_ERR("fb%d smem_len=%d is out of range!\n",
+			    hisifd->index, info->fix.smem_len);
+		return -EINVAL;
+	}
+#endif
+
+	if ((var->xres == 0) || (var->yres == 0)) {
+		HISI_FB_ERR("xres=%d, yres=%d is invalid!\n", var->xres,
+			    var->yres);
+		return -EINVAL;
+	}
+
+	if (var->xoffset > (var->xres_virtual - var->xres)) {
+		HISI_FB_ERR
+		    ("xoffset=%d(xres_virtual=%d, xres=%d) out of range!\n",
+		     var->xoffset, var->xres_virtual, var->xres);
+		return -EINVAL;
+	}
+
+	if (var->yoffset > (var->yres_virtual - var->yres)) {
+		HISI_FB_ERR
+		    ("yoffset=%d(yres_virtual=%d, yres=%d) out of range!\n",
+		     var->yoffset, var->yres_virtual, var->yres);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int hisi_fb_set_par(struct fb_info *info)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct fb_var_screeninfo *var = NULL;
+
+	if (NULL == info) {
+		HISI_FB_ERR("NULL Pointer\n");
+		return -EINVAL;
+	}
+
+	hisifd = (struct hisi_fb_data_type *)info->par;
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL Pointer\n");
+		return -EINVAL;
+	}
+
+	var = &info->var;
+
+	hisifd->fbi->fix.line_length =
+	    hisifb_line_length(hisifd->index, var->xres_virtual,
+			       var->bits_per_pixel >> 3);
+
+	return 0;
+}
+
+static int hisi_fb_pan_display(struct fb_var_screeninfo *var,
+			       struct fb_info *info)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	if (NULL == var || NULL == info) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	hisifd = (struct hisi_fb_data_type *)info->par;
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	down(&hisifd->blank_sem);
+
+	if (!hisifd->panel_power_on) {
+		HISI_FB_INFO("fb%d, panel power off!\n", hisifd->index);
+		ret = -EPERM;
+		goto err_out;
+	}
+
+	if (var->xoffset > (info->var.xres_virtual - info->var.xres)) {
+		ret = -EINVAL;
+		goto err_out;
+	}
+
+	if (var->yoffset > (info->var.yres_virtual - info->var.yres)) {
+		ret = -EINVAL;
+		goto err_out;
+	}
+
+	if (info->fix.xpanstep)
+		info->var.xoffset =
+		    (var->xoffset / info->fix.xpanstep) * info->fix.xpanstep;
+
+	if (info->fix.ypanstep)
+		info->var.yoffset =
+		    (var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
+
+	if (hisifd->pan_display_fnc) {
+		hisifd->pan_display_fnc(hisifd);
+	} else {
+		HISI_FB_ERR("fb%d pan_display_fnc not set!\n", hisifd->index);
+	}
+
+	up(&hisifd->blank_sem);
+
+	if (hisifd->bl_update) {
+		hisifd->bl_update(hisifd);
+	}
+
+	return ret;
+
+ err_out:
+	up(&hisifd->blank_sem);
+	return 0;
+}
+
+static int hisifb_lcd_dirty_region_info_get(struct fb_info *info,
+					    void __user *argp)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	if (NULL == info) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	hisifd = (struct hisi_fb_data_type *)info->par;
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	if (NULL == argp) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	if (copy_to_user(argp, &(hisifd->panel_info.dirty_region_info),
+			 sizeof(struct lcd_dirty_region_info))) {
+		HISI_FB_ERR("copy to user fail");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int hisifb_dirty_region_updt_set(struct fb_info *info,
+					void __user *argp)
+{
+	int enable = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	if (NULL == info) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	hisifd = (struct hisi_fb_data_type *)info->par;
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	if (hisifd->index != PRIMARY_PANEL_IDX) {
+		HISI_FB_ERR("fb%d, not supported!\n", hisifd->index);
+		return -EINVAL;
+	}
+
+	if (NULL == argp) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	if (g_enable_dirty_region_updt
+	    && hisifd->panel_info.dirty_region_updt_support
+	    && !hisifd->sbl_enable
+	    && !hisifd->color_temperature_flag && !hisifd->esd_happened) {
+		enable = 1;
+	}
+
+	if (copy_to_user(argp, &enable, sizeof(enable))) {
+		HISI_FB_ERR("copy to user fail");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int hisifb_dss_mmbuf_alloc(struct fb_info *info, void __user *argp)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+	dss_mmbuf_t mmbuf_info;
+
+	if (NULL == info) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	hisifd = (struct hisi_fb_data_type *)info->par;
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	if (NULL == argp) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	ret = copy_from_user(&mmbuf_info, argp, sizeof(dss_mmbuf_t));
+	if (ret) {
+		HISI_FB_ERR("fb%d, copy for user failed!ret=%d.\n",
+			    hisifd->index, ret);
+		ret = -EINVAL;
+		goto err_out;
+	}
+
+	if ((mmbuf_info.size <= 0) || (mmbuf_info.size > MMBUF_SIZE_MAX)
+	    || (mmbuf_info.size & (MMBUF_ADDR_ALIGN - 1))) {
+		HISI_FB_ERR("fb%d, mmbuf size is invalid, size=%d!\n",
+			    hisifd->index, mmbuf_info.size);
+		ret = -EINVAL;
+		goto err_out;
+	}
+
+	if (g_mmbuf_addr_test > 0) {
+		if (g_mmbuf_addr_test >= (MMBUF_SIZE_MAX + 0x40)) {
+			HISI_FB_ERR
+			    ("g_mmbuf_addr_test(0x%x) is overflow max mmbuf size + 0x40(0x%x)\n",
+			     g_mmbuf_addr_test, MMBUF_SIZE_MAX + 0x40);
+
+			HISI_FB_ERR("remain buff size if %d \n",
+				    (MMBUF_SIZE_MAX + 0x40) -
+				    (g_mmbuf_addr_test - mmbuf_info.size));
+
+			g_mmbuf_addr_test = 0;
+		} else {
+			mmbuf_info.addr = g_mmbuf_addr_test;
+			g_mmbuf_addr_test += mmbuf_info.size;
+		}
+
+		HISI_FB_INFO
+		    ("addr = 0x%x, size =%d, g_mmbuf_addr_test = 0x%x, MAX_SIZE= 0x%x\n",
+		     mmbuf_info.addr, mmbuf_info.size, g_mmbuf_addr_test,
+		     MMBUF_SIZE_MAX + 0x40);
+	}
+
+	if (0 == g_mmbuf_addr_test) {
+		mmbuf_info.addr =
+		    hisi_dss_mmbuf_alloc(hisifd->mmbuf_gen_pool,
+					 mmbuf_info.size);
+		if (mmbuf_info.addr < MMBUF_BASE) {
+			ret = -EINVAL;
+			goto err_out;
+		}
+	}
+
+	ret = copy_to_user(argp, &mmbuf_info, sizeof(dss_mmbuf_t));
+	if (ret) {
+		HISI_FB_ERR("fb%d, copy to user failed!ret=%d.",
+					hisifd->index, ret);
+		hisi_dss_mmbuf_free(hisifd->mmbuf_gen_pool,
+					mmbuf_info.addr, mmbuf_info.size);
+		ret = -EFAULT;
+		goto err_out;
+	}
+
+	return 0;
+
+ err_out:
+	return ret;
+}
+
+static int hisifb_dss_mmbuf_free(struct fb_info *info, void __user *argp)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct hisi_fb_panel_data *pdata = NULL;
+	dss_mmbuf_t mmbuf_info;
+
+	if (NULL == info) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	hisifd = (struct hisi_fb_data_type *)info->par;
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	if (NULL == pdata) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	if (NULL == argp) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	ret = copy_from_user(&mmbuf_info, argp, sizeof(dss_mmbuf_t));
+	if (ret) {
+		HISI_FB_ERR("fb%d, copy for user failed!ret=%d.", hisifd->index,
+			    ret);
+		ret = -EINVAL;
+		goto err_out;
+	}
+
+	if ((mmbuf_info.addr <= 0) || (mmbuf_info.size <= 0)) {
+		HISI_FB_ERR("fb%d, addr=0x%x, size=%d is invalid!\n",
+			    hisifd->index, mmbuf_info.addr, mmbuf_info.size);
+		ret = -EINVAL;
+		goto err_out;
+	}
+
+	hisi_dss_mmbuf_free(hisifd->mmbuf_gen_pool, mmbuf_info.addr,
+			    mmbuf_info.size);
+
+	return 0;
+
+ err_out:
+	return ret;
+}
+
+static int hisifb_dss_get_platform_type(struct fb_info *info,
+					void __user *argp)
+{
+	int type;
+	int ret = 0;
+
+	type = HISIFB_DSS_PLATFORM_TYPE;
+
+	if (NULL == argp) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+	ret = copy_to_user(argp, &type, sizeof(type));
+	if (ret) {
+		HISI_FB_ERR("copy to user failed! ret=%d.", ret);
+		ret = -EFAULT;
+	}
+
+	return ret;
+}
+
+static int hisi_fb_ioctl(struct fb_info *info, unsigned int cmd,
+			 unsigned long arg)
+{
+	int ret = -ENOSYS;
+	struct hisi_fb_data_type *hisifd = NULL;
+	void __user *argp = (void __user *)arg;
+
+	if (NULL == info) {
+		HISI_FB_ERR("NULL Pointer");
+		return -EINVAL;
+	}
+
+	hisifd = (struct hisi_fb_data_type *)info->par;
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL Pointer");
+		return -EINVAL;
+	}
+
+	switch (cmd) {
+	case HISIFB_VSYNC_CTRL:
+		if (hisifd->vsync_ctrl_fnc) {
+			ret = hisifd->vsync_ctrl_fnc(info, argp);
+		}
+		break;
+
+	case HISIFB_DSS_CLK_RATE_SET:
+		ret = hisifb_ctrl_dss_clk_rate_set(info, argp);
+		break;
+
+	case HISIFB_LCD_DIRTY_REGION_INFO_GET:
+		ret = hisifb_lcd_dirty_region_info_get(info, argp);
+		break;
+
+	case HISIFB_DIRTY_REGION_UPDT_SET:
+		ret = hisifb_dirty_region_updt_set(info, argp);
+		break;
+
+	case HISIFB_DSS_MMBUF_ALLOC:
+		ret = hisifb_dss_mmbuf_alloc(info, argp);
+		break;
+
+	case HISIFB_DSS_MMBUF_FREE:
+		ret = hisifb_dss_mmbuf_free(info, argp);
+		break;
+
+	case HISIFB_PLATFORM_TYPE_GET:
+		ret = hisifb_dss_get_platform_type(info, argp);
+		break;
+
+	default:
+		if (hisifd->ov_ioctl_handler)
+			ret = hisifd->ov_ioctl_handler(hisifd, cmd, argp);
+		break;
+	}
+
+	if (ret == -ENOSYS)
+		HISI_FB_ERR("unsupported ioctl (%x)\n", cmd);
+
+	return ret;
+}
+
+static int hisi_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct sg_table *table = NULL;
+	struct scatterlist *sg = NULL;
+	struct page *page = NULL;
+	unsigned long remainder = 0;
+	unsigned long len = 0;
+	unsigned long addr = 0;
+	unsigned long offset = 0;
+	int i = 0;
+	int ret = 0;
+
+	if (NULL == info) {
+		HISI_FB_ERR("NULL Pointer");
+		return -EINVAL;
+	}
+
+	hisifd = (struct hisi_fb_data_type *)info->par;
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL Pointer");
+		return -EINVAL;
+	}
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		if (hisifd->fb_mem_free_flag) {
+			if (!hisifb_alloc_fb_buffer(hisifd)) {
+				HISI_FB_ERR("fb%d, hisifb_alloc_buffer failed!\n",
+				     hisifd->index);
+				return -ENOMEM;
+			}
+		}
+	} else {
+		HISI_FB_ERR("fb%d, no fb buffer!\n", hisifd->index);
+		return -EFAULT;;
+	}
+
+	table = ion_sg_table(hisifd->ion_client, hisifd->ion_handle);
+	BUG_ON(table == NULL);
+
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+	addr = vma->vm_start;
+	offset = vma->vm_pgoff * PAGE_SIZE;
+
+	for_each_sg(table->sgl, sg, table->nents, i) {
+		page = sg_page(sg);
+		remainder = vma->vm_end - addr;
+		len = sg->length;
+
+		if (offset >= sg->length) {
+			offset -= sg->length;
+			continue;
+		} else if (offset) {
+			page += offset / PAGE_SIZE;
+			len = sg->length - offset;
+			offset = 0;
+		}
+		len = min(len, remainder);
+		ret = remap_pfn_range(vma, addr, page_to_pfn(page), len,
+				      vma->vm_page_prot);
+		if (ret != 0) {
+			HISI_FB_ERR("fb%d, failed to remap_pfn_range! ret=%d\n",
+				    hisifd->index, ret);
+		}
+
+		addr += len;
+		if (addr >= vma->vm_end)
+			return 0;
+	}
+
+	return 0;
+}
+
+unsigned long hisifb_alloc_fb_buffer(struct hisi_fb_data_type *hisifd)
+{
+	struct fb_info *fbi = NULL;
+	struct ion_client *client = NULL;
+	struct ion_handle *handle = NULL;
+	size_t buf_len = 0;
+	unsigned long buf_addr = 0;
+
+	BUG_ON(hisifd == NULL);
+	fbi = hisifd->fbi;
+	BUG_ON(fbi == NULL);
+
+	if (hisifd->ion_handle != NULL)
+		return fbi->fix.smem_start;
+
+	client = hisifd->ion_client;
+	if (IS_ERR_OR_NULL(client)) {
+		HISI_FB_ERR("failed to create ion client!\n");
+		goto err_return;
+	}
+
+	buf_len = fbi->fix.smem_len;
+	handle =
+	    ion_alloc(client, buf_len, PAGE_SIZE, ION_HEAP(ION_SYSTEM_HEAP_ID), 0);
+
+	if (IS_ERR_OR_NULL(handle)) {
+		HISI_FB_ERR("failed to ion_alloc!\n");
+		goto err_return;
+	}
+
+	fbi->screen_base = ion_map_kernel(client, handle);
+	if (!fbi->screen_base) {
+		HISI_FB_ERR("failed to ion_map_kernel!\n");
+		goto err_ion_map;
+	}
+
+	if (ion_map_iommu(client, handle, &(hisifd->iommu_format))) {
+		HISI_FB_ERR("failed to ion_map_iommu!\n");
+		goto err_ion_get_addr;
+	}
+
+	buf_addr = hisifd->iommu_format.iova_start;
+
+	fbi->fix.smem_start = buf_addr;
+	fbi->screen_size = fbi->fix.smem_len;
+
+
+	hisifd->ion_handle = handle;
+
+	return buf_addr;
+
+ err_ion_get_addr:
+	ion_unmap_kernel(hisifd->ion_client, handle);
+ err_ion_map:
+	ion_free(hisifd->ion_client, handle);
+ err_return:
+	return 0;
+}
+
+void hisifb_free_fb_buffer(struct hisi_fb_data_type *hisifd)
+{
+	struct fb_info *fbi = NULL;
+
+	BUG_ON(hisifd == NULL);
+	fbi = hisifd->fbi;
+	BUG_ON(fbi == NULL);
+
+	if (hisifd->ion_client != NULL && hisifd->ion_handle != NULL) {
+		ion_unmap_iommu(hisifd->ion_client, hisifd->ion_handle);
+		ion_unmap_kernel(hisifd->ion_client, hisifd->ion_handle);
+		ion_free(hisifd->ion_client, hisifd->ion_handle);
+		hisifd->ion_handle = NULL;
+		fbi->screen_base = 0;
+		fbi->fix.smem_start = 0;
+	}
+}
+
+/*******************************************************************************
+ ** fb sys fs
+ */
+static void hisifb_sysfs_init(struct hisi_fb_data_type *hisifd)
+{
+	int i = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	hisifd->sysfs_index = 0;
+	for (i = 0; i < HISI_FB_SYSFS_ATTRS_NUM; i++) {
+		hisifd->sysfs_attrs[i] = NULL;
+	}
+	hisifd->sysfs_attr_group.attrs = hisifd->sysfs_attrs;
+}
+
+static void hisifb_sysfs_attrs_append(struct hisi_fb_data_type *hisifd,
+				      struct attribute *attr)
+{
+	BUG_ON(hisifd == NULL);
+	BUG_ON(attr == NULL);
+
+	if (hisifd->sysfs_index >= HISI_FB_SYSFS_ATTRS_NUM) {
+		HISI_FB_ERR("fb%d, sysfs_atts_num(%d) is out of range(%d)!\n",
+			    hisifd->index, hisifd->sysfs_index,
+			    HISI_FB_SYSFS_ATTRS_NUM);
+		BUG_ON(1);
+		return;
+	}
+
+	hisifd->sysfs_attrs[hisifd->sysfs_index] = attr;
+	hisifd->sysfs_index++;
+}
+
+static int hisifb_sysfs_create(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	ret =
+	    sysfs_create_group(&hisifd->fbi->dev->kobj,
+			       &(hisifd->sysfs_attr_group));
+	if (ret) {
+		HISI_FB_ERR("fb%d sysfs group creation failed, error=%d!\n",
+			    hisifd->index, ret);
+	}
+
+	return ret;
+}
+
+static void hisifb_sysfs_remove(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	sysfs_remove_group(&hisifd->fbi->dev->kobj,
+			   &(hisifd->sysfs_attr_group));
+
+	hisifb_sysfs_init(hisifd);
+}
+
+/*******************************************************************************
+ **
+ */
+static struct fb_ops hisi_fb_ops = {
+	.owner = THIS_MODULE,
+	.fb_open = hisi_fb_open,
+	.fb_release = hisi_fb_release,
+	.fb_read = NULL,
+	.fb_write = NULL,
+	.fb_cursor = NULL,
+	.fb_check_var = hisi_fb_check_var,
+	.fb_set_par = hisi_fb_set_par,
+	.fb_setcolreg = NULL,
+	.fb_blank = hisi_fb_blank,
+	.fb_pan_display = hisi_fb_pan_display,
+	.fb_fillrect = NULL,
+	.fb_copyarea = NULL,
+	.fb_imageblit = NULL,
+	.fb_rotate = NULL,
+	.fb_sync = NULL,
+	.fb_ioctl = hisi_fb_ioctl,
+	.fb_compat_ioctl = hisi_fb_ioctl,
+	.fb_mmap = hisi_fb_mmap,
+};
+
+static int hisi_fb_register(struct hisi_fb_data_type *hisifd)
+{
+	int bpp = 0;
+	struct hisi_panel_info *panel_info = NULL;
+	struct fb_info *fbi = NULL;
+	struct fb_fix_screeninfo *fix = NULL;
+	struct fb_var_screeninfo *var = NULL;
+
+	BUG_ON(hisifd == NULL);
+	panel_info = &hisifd->panel_info;
+	BUG_ON(panel_info == NULL);
+
+	/*
+	 * fb info initialization
+	 */
+	fbi = hisifd->fbi;
+	fix = &fbi->fix;
+	var = &fbi->var;
+
+	fix->type_aux = 0;
+	fix->visual = FB_VISUAL_TRUECOLOR;
+	fix->ywrapstep = 0;
+	fix->mmio_start = 0;
+	fix->mmio_len = 0;
+	fix->accel = FB_ACCEL_NONE;
+
+	var->xoffset = 0;
+	var->yoffset = 0;
+	var->grayscale = 0;
+	var->nonstd = 0;
+	var->activate = FB_ACTIVATE_VBL;
+	var->height = panel_info->height;
+	var->width = panel_info->width;
+	var->accel_flags = 0;
+	var->sync = 0;
+	var->rotate = 0;
+
+	switch (hisifd->fb_imgType) {
+	case HISI_FB_PIXEL_FORMAT_BGR_565:
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->xpanstep = 1;
+		fix->ypanstep = 1;
+		var->vmode = FB_VMODE_NONINTERLACED;
+
+		var->blue.offset = 0;
+		var->green.offset = 5;
+		var->red.offset = 11;
+		var->transp.offset = 0;
+
+		var->blue.length = 5;
+		var->green.length = 6;
+		var->red.length = 5;
+		var->transp.length = 0;
+
+		var->blue.msb_right = 0;
+		var->green.msb_right = 0;
+		var->red.msb_right = 0;
+		var->transp.msb_right = 0;
+		bpp = 2;
+		break;
+
+	case HISI_FB_PIXEL_FORMAT_BGRX_4444:
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->xpanstep = 1;
+		fix->ypanstep = 1;
+		var->vmode = FB_VMODE_NONINTERLACED;
+
+		var->blue.offset = 0;
+		var->green.offset = 4;
+		var->red.offset = 8;
+		var->transp.offset = 0;
+
+		var->blue.length = 4;
+		var->green.length = 4;
+		var->red.length = 4;
+		var->transp.length = 0;
+
+		var->blue.msb_right = 0;
+		var->green.msb_right = 0;
+		var->red.msb_right = 0;
+		var->transp.msb_right = 0;
+		bpp = 2;
+		break;
+
+	case HISI_FB_PIXEL_FORMAT_BGRA_4444:
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->xpanstep = 1;
+		fix->ypanstep = 1;
+		var->vmode = FB_VMODE_NONINTERLACED;
+
+		var->blue.offset = 0;
+		var->green.offset = 4;
+		var->red.offset = 8;
+		var->transp.offset = 12;
+
+		var->blue.length = 4;
+		var->green.length = 4;
+		var->red.length = 4;
+		var->transp.length = 4;
+
+		var->blue.msb_right = 0;
+		var->green.msb_right = 0;
+		var->red.msb_right = 0;
+		var->transp.msb_right = 0;
+		bpp = 2;
+		break;
+
+	case HISI_FB_PIXEL_FORMAT_BGRX_5551:
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->xpanstep = 1;
+		fix->ypanstep = 1;
+		var->vmode = FB_VMODE_NONINTERLACED;
+
+		var->blue.offset = 0;
+		var->green.offset = 5;
+		var->red.offset = 10;
+		var->transp.offset = 0;
+
+		var->blue.length = 5;
+		var->green.length = 5;
+		var->red.length = 5;
+		var->transp.length = 0;
+
+		var->blue.msb_right = 0;
+		var->green.msb_right = 0;
+		var->red.msb_right = 0;
+		var->transp.msb_right = 0;
+		bpp = 2;
+		break;
+
+	case HISI_FB_PIXEL_FORMAT_BGRA_5551:
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->xpanstep = 1;
+		fix->ypanstep = 1;
+		var->vmode = FB_VMODE_NONINTERLACED;
+
+		var->blue.offset = 0;
+		var->green.offset = 5;
+		var->red.offset = 10;
+		var->transp.offset = 15;
+
+		var->blue.length = 5;
+		var->green.length = 5;
+		var->red.length = 5;
+		var->transp.length = 1;
+
+		var->blue.msb_right = 0;
+		var->green.msb_right = 0;
+		var->red.msb_right = 0;
+		var->transp.msb_right = 0;
+		bpp = 2;
+		break;
+
+	case HISI_FB_PIXEL_FORMAT_BGRA_8888:
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->xpanstep = 1;
+		fix->ypanstep = 1;
+		var->vmode = FB_VMODE_NONINTERLACED;
+
+		var->blue.offset = 0;
+		var->green.offset = 8;
+		var->red.offset = 16;
+		var->transp.offset = 24;
+
+		var->blue.length = 8;
+		var->green.length = 8;
+		var->red.length = 8;
+		var->transp.length = 8;
+
+		var->blue.msb_right = 0;
+		var->green.msb_right = 0;
+		var->red.msb_right = 0;
+		var->transp.msb_right = 0;
+
+		bpp = 4;
+		break;
+
+	case HISI_FB_PIXEL_FORMAT_YUV_422_I:
+		fix->type = FB_TYPE_INTERLEAVED_PLANES;
+		fix->xpanstep = 2;
+		fix->ypanstep = 1;
+		var->vmode = FB_VMODE_NONINTERLACED;
+
+		/* FIXME: R/G/B offset? */
+		var->blue.offset = 0;
+		var->green.offset = 5;
+		var->red.offset = 11;
+		var->transp.offset = 0;
+
+		var->blue.length = 5;
+		var->green.length = 6;
+		var->red.length = 5;
+		var->transp.length = 0;
+
+		var->blue.msb_right = 0;
+		var->green.msb_right = 0;
+		var->red.msb_right = 0;
+		var->transp.msb_right = 0;
+
+		bpp = 2;
+		break;
+
+	default:
+		HISI_FB_ERR("fb%d, unkown image type!\n", hisifd->index);
+		return -EINVAL;
+	}
+
+
+	memset(&(hisifd->resolution_rect), 0, sizeof(dss_rect_t));
+	memset(&(hisifd->res_updt_rect), 0, sizeof(dss_rect_t));
+
+	var->xres = panel_info->xres;
+	var->yres = panel_info->yres;
+	var->xres_virtual = var->xres;
+	var->yres_virtual = var->yres * hisifd->fb_num;
+	var->bits_per_pixel = bpp * 8;
+
+	snprintf(fix->id, sizeof(fix->id), "hisifb%d", hisifd->index);
+	fix->line_length =
+	    hisifb_line_length(hisifd->index, var->xres_virtual, bpp);
+	fix->smem_len =
+	    roundup(fix->line_length * var->yres_virtual, PAGE_SIZE);
+	fix->smem_start = 0;
+
+	fbi->screen_base = 0;
+	fbi->fbops = &hisi_fb_ops;
+	fbi->flags = FBINFO_FLAG_DEFAULT;
+	fbi->pseudo_palette = NULL;
+
+	fix->reserved[0] = is_mipi_cmd_panel(hisifd) ? 1 : 0;
+
+	hisifd->ion_client = hisi_ion_client_create(HISI_FB_ION_CLIENT_NAME);
+	if (IS_ERR_OR_NULL(hisifd->ion_client)) {
+		HISI_FB_ERR("failed to create ion client!\n");
+		return -ENOMEM;
+	}
+	hisifd->ion_handle = NULL;
+	memset(&hisifd->iommu_format, 0, sizeof(struct iommu_map_format));
+
+	if (fix->smem_len > 0) {
+		if (!hisifb_alloc_fb_buffer(hisifd)) {
+			HISI_FB_ERR("hisifb_alloc_buffer failed!\n");
+			return -ENOMEM;
+		}
+	}
+
+	hisifd->ref_cnt = 0;
+	hisifd->panel_power_on = false;
+	hisifd->aod_function = 0;
+	sema_init(&hisifd->blank_sem, 1);
+	sema_init(&hisifd->blank_sem0, 1);
+
+	hisifb_sysfs_init(hisifd);
+
+	hisifd->on_fnc = hisifb_ctrl_on;
+	hisifd->off_fnc = hisifb_ctrl_off;
+	hisifd->hisi_domain = g_hisi_domain;
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		hisifd->fb_mem_free_flag = false;
+		hisifd->open_sub_fnc = hisi_fb_open_sub;
+		hisifd->release_sub_fnc = hisi_fb_release_sub;
+		hisifd->sysfs_attrs_add_fnc = hisifb_sysfs_attrs_add;
+		hisifd->sysfs_attrs_append_fnc = hisifb_sysfs_attrs_append;
+		hisifd->sysfs_create_fnc = hisifb_sysfs_create;
+		hisifd->sysfs_remove_fnc = hisifb_sysfs_remove;
+		hisifd->bl_register = hisifb_backlight_register;
+		hisifd->bl_unregister = hisifb_backlight_unregister;
+		hisifd->bl_update = hisifb_backlight_update;
+		hisifd->bl_cancel = hisifb_backlight_cancel;
+		hisifd->vsync_register = hisifb_vsync_register;
+		hisifd->vsync_unregister = hisifb_vsync_unregister;
+		hisifd->vsync_ctrl_fnc = hisifb_vsync_ctrl;
+		hisifd->vsync_isr_handler = hisifb_vsync_isr_handler;
+		hisifd->buf_sync_register = hisifb_buf_sync_register;
+		hisifd->buf_sync_unregister = hisifb_buf_sync_unregister;
+		hisifd->buf_sync_signal = hisifb_buf_sync_signal;
+		hisifd->buf_sync_suspend = hisifb_buf_sync_suspend;
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		hisifd->fb_mem_free_flag = true;
+		hisifd->release_sub_fnc = hisi_fb_release_sub;
+		hisifd->bl_register = hisifb_backlight_register;
+		hisifd->bl_unregister = hisifb_backlight_unregister;
+		hisifd->bl_update = hisifb_backlight_update;
+		hisifd->bl_cancel = hisifb_backlight_cancel;
+		hisifd->vsync_register = hisifb_vsync_register;
+		hisifd->vsync_unregister = hisifb_vsync_unregister;
+		hisifd->vsync_ctrl_fnc = hisifb_vsync_ctrl;
+		hisifd->vsync_isr_handler = hisifb_vsync_isr_handler;
+		hisifd->buf_sync_register = hisifb_buf_sync_register;
+		hisifd->buf_sync_unregister = hisifb_buf_sync_unregister;
+		hisifd->buf_sync_signal = hisifb_buf_sync_signal;
+		hisifd->buf_sync_suspend = hisifb_buf_sync_suspend;
+
+	} else {
+		sema_init(&hisifd->offline_composer_sr_sem, 1);
+		hisifd->offline_composer_sr_refcount = 0;
+		hisifd->fb_mem_free_flag = true;
+	}
+
+	if (hisi_overlay_init(hisifd)) {
+		HISI_FB_ERR("unable to init overlay!\n");
+		return -EPERM;
+	}
+
+	if (register_framebuffer(fbi) < 0) {
+		HISI_FB_ERR("fb%d failed to register_framebuffer!",
+			    hisifd->index);
+		return -EPERM;
+	}
+
+	if (hisifd->sysfs_attrs_add_fnc) {
+		hisifd->sysfs_attrs_add_fnc(hisifd);
+	}
+
+	/* backlight register */
+	if (hisifd->bl_register)
+		hisifd->bl_register(hisifd->pdev);
+	/* vsync register */
+	if (hisifd->vsync_register)
+		hisifd->vsync_register(hisifd->pdev);
+	/* buf_sync register */
+	if (hisifd->buf_sync_register)
+		hisifd->buf_sync_register(hisifd->pdev);
+	/* fb sysfs create */
+	if (hisifd->sysfs_create_fnc)
+		hisifd->sysfs_create_fnc(hisifd->pdev);
+
+	HISI_FB_INFO
+	    ("FrameBuffer[%d] %dx%d size=%d bytes phy_addr=%lu virt_addr=%p "
+	     "is registered successfully!\n", hisifd->index, var->xres,
+	     var->yres, fbi->fix.smem_len, fix->smem_start, fbi->screen_base);
+
+	return 0;
+}
+
+/*******************************************************************************
+ **
+ */
+static int hisi_fb_enable_iommu(struct platform_device *pdev)
+{
+	struct iommu_domain *hisi_domain = NULL;
+	struct device *dev = NULL;
+
+	BUG_ON(pdev == NULL);
+
+	dev = &pdev->dev;
+
+	/* create iommu domain */
+	hisi_domain = iommu_domain_alloc(dev->bus);
+	if (!hisi_domain) {
+		HISI_FB_ERR("iommu_domain_alloc failed!\n");
+		return -EINVAL;
+	}
+
+	iommu_attach_device(hisi_domain, dev);
+
+	g_hisi_domain = hisi_domain;
+
+	return 0;
+}
+
+static int hisi_fb_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct device_node *np = NULL;
+
+	if (!hisi_fb_resource_initialized) {
+		HISI_FB_DEBUG("initialized=%d, +.\n",
+			      hisi_fb_resource_initialized);
+
+		pdev->id = 0;
+		np = of_find_compatible_node(NULL, NULL, DTS_COMP_FB_NAME);
+		if (!np) {
+			HISI_FB_ERR("NOT FOUND device node %s!\n",
+				    DTS_COMP_FB_NAME);
+			return -ENXIO;
+		}
+
+		dss_aclk_dss = devm_clk_get(&pdev->dev, "aclk_dss");
+		if (IS_ERR(dss_aclk_dss)) {
+			ret = PTR_ERR(dss_aclk_dss);
+			HISI_FB_ERR("dss_aclk_dss error, ret = %d", ret);
+			return ret;
+		}
+
+		dss_pclk_dss = devm_clk_get(&pdev->dev, "pclk_dss");
+		if (IS_ERR(dss_pclk_dss)) {
+			ret = PTR_ERR(dss_pclk_dss);
+			HISI_FB_ERR("dss_pclk_dss error, ret = %d", ret);
+			return ret;
+		}
+
+		dss_clk_edc0 = devm_clk_get(&pdev->dev, "clk_edc0");
+		if (IS_ERR(dss_clk_edc0)) {
+			ret = PTR_ERR(dss_clk_edc0);
+			HISI_FB_ERR("dss_clk_edc0 error, ret = %d", ret);
+			return ret;
+		}
+
+		dss_clk_ldi0 = devm_clk_get(&pdev->dev, "clk_ldi0");
+		if (IS_ERR(dss_clk_ldi0)) {
+			ret = PTR_ERR(dss_clk_ldi0);
+			HISI_FB_ERR("dss_clk_ldi0 error, ret = %d", ret);
+			return ret;
+		}
+
+		dss_clk_ldi1 = devm_clk_get(&pdev->dev, "clk_ldi1");
+		if (IS_ERR(dss_clk_ldi1)) {
+			ret = PTR_ERR(dss_clk_ldi1);
+			HISI_FB_ERR("dss_clk_ldi1 error, ret = %d", ret);
+			return ret;
+		}
+
+		dss_clk_dss_axi_mm = devm_clk_get(&pdev->dev, "clk_dss_axi_mm");
+		if (IS_ERR(dss_clk_dss_axi_mm)) {
+			ret = PTR_ERR(dss_clk_dss_axi_mm);
+			HISI_FB_ERR("dss_clk_dss_axi_mm error, ret = %d", ret);
+			return ret;
+		}
+
+		dss_pclk_mmbuf = devm_clk_get(&pdev->dev, "pclk_mmbuf");
+		if (IS_ERR(dss_pclk_mmbuf)) {
+			ret = PTR_ERR(dss_pclk_mmbuf);
+			HISI_FB_ERR("dss_pclk_mmbuf error, ret = %d", ret);
+			return ret;
+		}
+
+		dss_clk_txdphy0_ref =
+		    devm_clk_get(&pdev->dev, "clk_txdphy0_ref");
+		if (IS_ERR(dss_clk_txdphy0_ref)) {
+			ret = PTR_ERR(dss_clk_txdphy0_ref);
+			HISI_FB_ERR("dss_clk_txdphy0_ref error, ret = %d", ret);
+			return ret;
+		}
+
+		dss_clk_txdphy1_ref =
+		    devm_clk_get(&pdev->dev, "clk_txdphy1_ref");
+		if (IS_ERR(dss_clk_txdphy1_ref)) {
+			ret = PTR_ERR(dss_clk_txdphy1_ref);
+			HISI_FB_ERR("dss_clk_txdphy1_ref error, ret = %d", ret);
+			return ret;
+		}
+
+		dss_clk_txdphy0_cfg =
+		    devm_clk_get(&pdev->dev, "clk_txdphy0_cfg");
+		if (IS_ERR(dss_clk_txdphy0_cfg)) {
+			ret = PTR_ERR(dss_clk_txdphy0_cfg);
+			HISI_FB_ERR("dss_clk_txdphy0_cfg error, ret = %d", ret);
+			return ret;
+		}
+
+		dss_clk_txdphy1_cfg =
+		    devm_clk_get(&pdev->dev, "clk_txdphy1_cfg");
+		if (IS_ERR(dss_clk_txdphy1_cfg)) {
+			ret = PTR_ERR(dss_clk_txdphy1_cfg);
+			HISI_FB_ERR("dss_clk_txdphy1_cfg error, ret = %d", ret);
+			return ret;
+		}
+
+		dss_pclk_dsi0 = devm_clk_get(&pdev->dev, "pclk_dsi0");
+		if (IS_ERR(dss_pclk_dsi0)) {
+			ret = PTR_ERR(dss_pclk_dsi0);
+			HISI_FB_ERR("dss_pclk_dsi0 error, ret = %d", ret);
+			return ret;
+		}
+
+		dss_pclk_dsi1 = devm_clk_get(&pdev->dev, "pclk_dsi1");
+		if (IS_ERR(dss_pclk_dsi1)) {
+			ret = PTR_ERR(dss_pclk_dsi1);
+			HISI_FB_ERR("dss_pclk_dsi1 error, ret = %d", ret);
+			return ret;
+		}
+
+		ret = of_property_read_u32(np, "dss_base_phy", &g_dss_base_phy);
+		if (ret) {
+			HISI_FB_ERR("failed to get dss_base_phy.\n");
+			return -ENXIO;
+		}
+		HISI_FB_INFO("g_dss_base_phy=0x%x.\n", g_dss_base_phy);
+
+		/* get irq no */
+		hisifd_irq_pdp = irq_of_parse_and_map(np, 0);
+		if (!hisifd_irq_pdp) {
+			HISI_FB_ERR("failed to get hisifd_irq_pdp resource.\n");
+			return -ENXIO;
+		}
+
+		hisifd_irq_sdp = irq_of_parse_and_map(np, 1);
+		if (!hisifd_irq_sdp) {
+			HISI_FB_ERR("failed to get hisifd_irq_sdp resource.\n");
+			return -ENXIO;
+		}
+
+		hisifd_irq_adp = irq_of_parse_and_map(np, 2);
+		if (!hisifd_irq_sdp) {
+			HISI_FB_ERR("failed to get hisifd_irq_sdp resource.\n");
+			return -ENXIO;
+		}
+
+		hisifd_irq_dsi0 = irq_of_parse_and_map(np, 3);
+		if (!hisifd_irq_dsi0) {
+			HISI_FB_ERR
+			    ("failed to get hisifd_irq_dsi0 resource.\n");
+			return -ENXIO;
+		}
+
+		hisifd_irq_dsi1 = irq_of_parse_and_map(np, 4);
+		if (!hisifd_irq_dsi1) {
+			HISI_FB_ERR
+			    ("failed to get hisifd_irq_dsi1 resource.\n");
+			return -ENXIO;
+		}
+
+		/* get dss reg base */
+		hisifd_dss_base = of_iomap(np, 0);
+		if (!hisifd_dss_base) {
+			HISI_FB_ERR
+			    ("failed to get hisifd_dss_base resource.\n");
+			return -ENXIO;
+		}
+
+		hisifd_peri_crg_base = of_iomap(np, 1);
+		if (!hisifd_peri_crg_base) {
+			HISI_FB_ERR
+			    ("failed to get hisifd_peri_crg_base resource.\n");
+			return -ENXIO;
+		}
+
+		hisifd_sctrl_base = of_iomap(np, 2);
+		if (!hisifd_sctrl_base) {
+			HISI_FB_ERR
+			    ("failed to get hisifd_sctrl_base resource.\n");
+			return -ENXIO;
+		}
+
+		hisifd_pctrl_base = of_iomap(np, 3);
+		if (!hisifd_pctrl_base) {
+			HISI_FB_ERR
+			    ("failed to get hisifd_pctrl_base resource.\n");
+			return -ENXIO;
+		}
+
+		hisifd_noc_dss_base = of_iomap(np, 4);
+		if (!hisifd_noc_dss_base) {
+			HISI_FB_ERR
+			    ("failed to get hisifd_noc_dss_base resource.\n");
+			return -ENXIO;
+		}
+
+		hisifd_mmbuf_crg_base = of_iomap(np, 5);
+		if (!hisifd_mmbuf_crg_base) {
+			HISI_FB_ERR
+			    ("failed to get hisifd_mmbuf_crg_base resource.\n");
+			return -ENXIO;
+		}
+
+		hisifd_pmctrl_base = of_iomap(np, 6);
+		if (!hisifd_pmctrl_base) {
+			HISI_FB_ERR
+			    ("failed to get hisifd_pmctrl_base resource.\n");
+			return -ENXIO;
+		}
+
+		/* get regulator resource, DSS regulator is already enabled in fastboot, so kernel dont care */
+		/*
+			g_dpe_regulator[0].supply = REGULATOR_PDP_NAME;
+			g_dpe_regulator[1].supply = REGULATOR_MMBUF;
+			ret = devm_regulator_bulk_get(&(pdev->dev),
+			ARRAY_SIZE(g_dpe_regulator), g_dpe_regulator);
+			if (ret) {
+				HISI_FB_ERR("failed to get regulator resource! ret=%d.\n", ret);
+				return -ENXIO;
+			}
+		*/
+
+		ret = hisi_fb_enable_iommu(pdev);
+		if (ret != 0) {
+			HISI_FB_ERR("failed to hisi_fb_enable_iommu! ret=%d.\n",
+				    ret);
+			return -ENXIO;
+		}
+
+		hisi_fb_resource_initialized = 1;
+		hisi_fb_device_set_status0(DTS_FB_RESOURCE_INIT_READY);
+
+		HISI_FB_DEBUG("initialized = %d, -.\n",
+			      hisi_fb_resource_initialized);
+		return 0;
+	}
+
+	if (pdev->id < 0) {
+		HISI_FB_ERR("WARNING: id=%d, name=%s!\n", pdev->id, pdev->name);
+		return 0;
+	}
+
+	if (!hisi_fb_resource_initialized) {
+		HISI_FB_ERR("fb resource not initialized!\n");
+		return -EPERM;
+	}
+
+	if (pdev_list_cnt >= HISI_FB_MAX_DEV_LIST) {
+		HISI_FB_ERR("too many fb devices, num=%d!\n", pdev_list_cnt);
+		return -ENOMEM;
+	}
+
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	ret = hisi_fb_register(hisifd);
+	if (ret) {
+		HISI_FB_ERR("fb%d hisi_fb_register failed, error=%d!\n",
+			    hisifd->index, ret);
+		return ret;
+	}
+
+	pdev_list[pdev_list_cnt++] = pdev;
+
+	/* set device probe status */
+	hisi_fb_device_set_status1(hisifd);
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return 0;
+}
+
+static int hisi_fb_remove(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	/* stop the device */
+	if (hisi_fb_suspend_sub(hisifd) != 0)
+		HISI_FB_ERR("fb%d hisi_fb_suspend_sub failed!\n",
+			    hisifd->index);
+
+	/* overlay destroy */
+	hisi_overlay_deinit(hisifd);
+
+	/* free framebuffer */
+	hisifb_free_fb_buffer(hisifd);
+	if (hisifd->ion_client) {
+		ion_client_destroy(hisifd->ion_client);
+		hisifd->ion_client = NULL;
+	}
+
+	/* remove /dev/fb* */
+	unregister_framebuffer(hisifd->fbi);
+
+	/* unregister buf_sync */
+	if (hisifd->buf_sync_unregister)
+		hisifd->buf_sync_unregister(pdev);
+	/* unregister vsync */
+	if (hisifd->vsync_unregister)
+		hisifd->vsync_unregister(pdev);
+	/* unregister backlight */
+	if (hisifd->bl_unregister)
+		hisifd->bl_unregister(pdev);
+	/* fb sysfs remove */
+	if (hisifd->sysfs_remove_fnc)
+		hisifd->sysfs_remove_fnc(hisifd->pdev);
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return 0;
+}
+
+static int hisi_fb_suspend_sub(struct hisi_fb_data_type *hisifd)
+{
+	int ret = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	ret = hisi_fb_blank_sub(FB_BLANK_POWERDOWN, hisifd->fbi);
+	if (ret) {
+		HISI_FB_ERR("fb%d can't turn off display, error=%d!\n",
+			    hisifd->index, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int hisi_fb_resume_sub(struct hisi_fb_data_type *hisifd)
+{
+	int ret = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	ret = hisi_fb_blank_sub(FB_BLANK_UNBLANK, hisifd->fbi);
+	if (ret) {
+		HISI_FB_ERR("fb%d can't turn on display, error=%d!\n",
+			    hisifd->index, ret);
+	}
+
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int hisi_fb_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_INFO("fb%d, +.\n", hisifd->index);
+
+	console_lock();
+	fb_set_suspend(hisifd->fbi, FBINFO_STATE_SUSPENDED);
+	ret = hisi_fb_suspend_sub(hisifd);
+	if (ret != 0) {
+		HISI_FB_ERR("fb%d hisi_fb_suspend_sub failed, error=%d!\n",
+			    hisifd->index, ret);
+		fb_set_suspend(hisifd->fbi, FBINFO_STATE_RUNNING);
+	} else {
+		pdev->dev.power.power_state = state;
+	}
+	console_unlock();
+
+	HISI_FB_INFO("fb%d, -.\n", hisifd->index);
+
+	return ret;
+}
+
+static int hisi_fb_resume(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_INFO("fb%d, +.\n", hisifd->index);
+
+	console_lock();
+	ret = hisi_fb_resume_sub(hisifd);
+	pdev->dev.power.power_state = PMSG_ON;
+	fb_set_suspend(hisifd->fbi, FBINFO_STATE_RUNNING);
+	console_unlock();
+
+	HISI_FB_INFO("fb%d, -.\n", hisifd->index);
+
+	return ret;
+}
+#else
+#define hisi_fb_suspend NULL
+#define hisi_fb_resume NULL
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+static int hisi_fb_pm_suspend(struct device *dev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	int ret = 0;
+
+	if (NULL == dev) {
+		HISI_FB_ERR("NULL Poniter\n");
+		return 0;
+	}
+
+	hisifd = dev_get_drvdata(dev);
+	if (!hisifd)
+		return 0;
+
+	if (hisifd->index != PRIMARY_PANEL_IDX)
+		return 0;
+
+	HISI_FB_INFO("fb%d, +.\n", hisifd->index);
+
+	ret = hisi_fb_suspend_sub(hisifd);
+	if (ret != 0) {
+		HISI_FB_ERR("fb%d, failed to hisi_fb_suspend_sub! ret=%d\n",
+			    hisifd->index, ret);
+	}
+
+	HISI_FB_INFO("fb%d, -.\n", hisifd->index);
+
+	return 0;
+}
+
+#if 0
+static int hisi_fb_pm_resume(struct device *dev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	int ret = 0;
+
+	hisifd = dev_get_drvdata(dev);
+	if (!hisifd)
+		return 0;
+
+	if (hisifd->index != PRIMARY_PANEL_IDX)
+		return 0;
+
+	HISI_FB_INFO("fb%d, +.\n", hisifd->index);
+
+	ret = hisi_fb_resume_sub(hisifd);
+	if (ret != 0) {
+		HISI_FB_ERR("fb%d, failed to hisi_fb_resume_sub! ret=%d\n",
+			    hisifd->index, ret);
+	}
+
+	HISI_FB_INFO("fb%d, -.\n", hisifd->index);
+
+	return 0;
+}
+#endif
+#endif
+
+static void hisi_fb_shutdown(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	if (NULL == pdev) {
+		HISI_FB_ERR("pdev NULL Pointer\n");
+		return;
+	}
+
+	hisifd = platform_get_drvdata(pdev);
+	if (!hisifd) {
+		if (pdev->id) {
+			HISI_FB_ERR("hisifd NULL Pointer,pdev->id=%d\n",
+				    pdev->id);
+		}
+		return;
+	}
+
+	if (hisifd->index != PRIMARY_PANEL_IDX) {
+		HISI_FB_DEBUG("fb%d do not shutdown\n", hisifd->index);
+		return;
+	}
+
+	HISI_FB_INFO("fb%d shutdown +\n", hisifd->index);
+	hisifd->fb_shutdown = true;
+
+	ret = hisi_fb_blank_sub(FB_BLANK_POWERDOWN, hisifd->fbi);
+	if (ret) {
+		HISI_FB_ERR("fb%d can't turn off display, error=%d!\n",
+			    hisifd->index, ret);
+	}
+
+	HISI_FB_INFO("fb%d shutdown -\n", hisifd->index);
+}
+
+/*******************************************************************************
+ **
+ */
+static struct dev_pm_ops hisi_fb_dev_pm_ops = {
+#ifdef CONFIG_PM_SLEEP
+	.suspend = hisi_fb_pm_suspend,
+	.resume = NULL,
+#endif
+};
+
+static const struct of_device_id hisi_fb_match_table[] = {
+	{
+	 .compatible = DTS_COMP_FB_NAME,
+	 .data = NULL,
+	 },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, hisi_fb_match_table);
+
+static struct platform_driver hisi_fb_driver = {
+	.probe = hisi_fb_probe,
+	.remove = hisi_fb_remove,
+	.suspend = hisi_fb_suspend,
+	.resume = hisi_fb_resume,
+	.shutdown = hisi_fb_shutdown,
+	.driver = {
+		   .name = DEV_NAME_FB,
+		   .owner = THIS_MODULE,
+		   .of_match_table = of_match_ptr(hisi_fb_match_table),
+		   .pm = &hisi_fb_dev_pm_ops,
+		   },
+};
+
+static int __init hisi_fb_init(void)
+{
+	int ret = 0;
+
+	ret = platform_driver_register(&hisi_fb_driver);
+	if (ret) {
+		HISI_FB_ERR("platform_driver_register failed, error=%d!\n",
+			    ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+module_init(hisi_fb_init);
+
+MODULE_DESCRIPTION("Hisilicon Framebuffer Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/hisi/dss/hisi_fb.h b/drivers/video/fbdev/hisi/dss/hisi_fb.h
new file mode 100755
index 000000000000..d13ca97797d7
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_fb.h
@@ -0,0 +1,559 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+#ifndef HISI_FB_H
+#define HISI_FB_H
+
+#include <linux/console.h>
+#include <linux/uaccess.h>
+#include <linux/leds.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/fb.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/raid/pq.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/time.h>
+#include <linux/kthread.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/backlight.h>
+#include <linux/pwm.h>
+#include <linux/pm_runtime.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/memblock.h>
+
+#include <linux/spi/spi.h>
+
+#include <linux/ion.h>
+#include <linux/hisi/hisi_ion.h>
+#include <linux/gpio.h>
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/file.h>
+#include <linux/dma-buf.h>
+#include <linux/genalloc.h>
+#include <linux/hisi/hisi-iommu.h>
+
+
+
+#include "hisi_fb_def.h"
+#include "hisi_fb_panel.h"
+#include "hisi_dss.h"
+#include "hisi_mipi_dsi.h"
+#include "hisi_overlay_cmdlist_utils.h"
+
+#include "hisi_dss_regs_hi3660.h"
+#include "hisi_overlay_utils_hi3660.h"
+#include "hisi_dpe_utils.h"
+#include "hisi_overlay_utils.h"
+
+#define CONFIG_HISI_FB_BACKLIGHT_DELAY
+#define CONFIG_BUF_SYNC_USED
+#define CONFIG_FB_DEBUG_USED
+#define CONFIG_SMMU_RWERRADDR_USED
+#define CONFIG_DSS_MMBUF_CLK_USED
+#define CONFIG_BACKLIGHT_2048
+
+#define HISI_DSS_COMPOSER_HOLD_TIME	(1000 * 3600 * 24 * 7)
+
+#define HISI_FB0_NUM	(3)
+#define HISI_FB1_NUM	(0)
+#define HISI_FB2_NUM	(0)
+
+#define HISI_FB_SYSFS_ATTRS_NUM	(64)
+
+#define HISI_FB_MAX_DEV_LIST (32)
+#define HISI_FB_MAX_FBI_LIST (32)
+
+#define HISI_DSS_OFFLINE_MAX_BLOCK	(64)
+#define HISI_DSS_OFFLINE_MAX_LIST	(128)
+
+#define ESD_CHECK_TIME_PERIOD	(5000)
+
+struct hisifb_vsync {
+	wait_queue_head_t vsync_wait;
+	ktime_t vsync_timestamp;
+	int vsync_created;
+	int vsync_enabled;
+	int vsync_infinite;
+	int vsync_infinite_count;
+
+	int vsync_ctrl_expire_count;
+	int vsync_ctrl_enabled;
+	int vsync_ctrl_disabled_set;
+	int vsync_ctrl_isr_enabled;
+	int vsync_ctrl_offline_enabled;
+	struct work_struct vsync_ctrl_work;
+	spinlock_t spin_lock;
+
+	struct mutex vsync_lock;
+#ifdef CONFIG_HISI_FB_VSYNC_THREAD
+	struct task_struct *vsync_thread;
+#endif
+
+	atomic_t buffer_updated;
+	void (*vsync_report_fnc) (int buffer_updated);
+
+	struct hisi_fb_data_type *hisifd;
+};
+
+enum bl_control_mode {
+	REG_ONLY_MODE = 1,
+	PWM_ONLY_MODE,
+	MUTI_THEN_RAMP_MODE,
+	RAMP_THEN_MUTI_MODE,
+};
+
+enum ESD_RECOVER_STATE {
+	ESD_RECOVER_STATE_NONE = 0,
+	ESD_RECOVER_STATE_START = 1,
+	ESD_RECOVER_STATE_COMPLETE = 2,
+};
+
+/* esd func define */
+struct hisifb_esd {
+	int esd_inited;
+	struct hrtimer esd_hrtimer;
+	struct workqueue_struct *esd_check_wq;
+	struct work_struct esd_check_work;
+	struct task_struct *esd_handle_thread;
+	wait_queue_head_t esd_handle_wait;
+
+	struct hisi_fb_data_type *hisifd;
+};
+
+#ifdef CONFIG_BUF_SYNC_USED
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0)
+#include "sync.h"
+#include "sw_sync.h"
+#else
+#include <linux/sync.h>
+#include <linux/sw_sync.h>
+#endif
+#endif
+
+struct hisifb_buf_sync {
+#ifdef CONFIG_BUF_SYNC_USED
+	struct sw_sync_timeline *timeline;
+	int timeline_max;
+	int refresh;
+	spinlock_t refresh_lock;
+#endif
+	struct workqueue_struct *free_layerbuf_queue;
+	struct work_struct free_layerbuf_work;
+	struct list_head layerbuf_list;
+	bool layerbuf_flushed;
+	spinlock_t layerbuf_spinlock;
+};
+
+struct hisifb_layerbuf {
+	struct ion_handle *ion_handle;
+	struct list_head list_node;
+	int timeline;
+	bool has_map_iommu;
+
+	int32_t shared_fd;
+	uint32_t frame_no;
+	dss_mmbuf_t mmbuf;
+	uint64_t vir_addr;
+	int32_t chn_idx;
+};
+
+struct hisifb_backlight {
+#ifdef CONFIG_HISI_FB_BACKLIGHT_DELAY
+	struct delayed_work bl_worker;
+#endif
+	struct semaphore bl_sem;
+	int bl_updated;
+	int bl_level_old;
+	int frame_updated;
+
+	struct workqueue_struct *sbl_queue;
+	struct work_struct sbl_work;
+};
+
+struct hisi_fb_data_type {
+	uint32_t index;
+	uint32_t ref_cnt;
+	uint32_t fb_num;
+	uint32_t fb_imgType;
+	uint32_t bl_level;
+
+	char __iomem *dss_base;
+	char __iomem *peri_crg_base;
+	char __iomem *sctrl_base;
+	char __iomem *pctrl_base;
+	char __iomem *noc_dss_base;
+	char __iomem *mmbuf_crg_base;
+	char __iomem *pmctrl_base;
+	char __iomem *mmbuf_asc0_base;
+	char __iomem *mipi_dsi0_base;
+	char __iomem *mipi_dsi1_base;
+
+	uint32_t dss_base_phy;
+
+	uint32_t dpe_irq;
+	uint32_t dsi0_irq;
+	uint32_t dsi1_irq;
+	uint32_t mmbuf_asc0_irq;
+
+	struct regulator_bulk_data *dpe_regulator;
+	struct regulator_bulk_data *mmbuf_regulator;
+
+	const char *dss_axi_clk_name;
+	const char *dss_pclk_dss_name;
+	const char *dss_pri_clk_name;
+	const char *dss_pxl0_clk_name;
+	const char *dss_pxl1_clk_name;
+	const char *dss_mmbuf_clk_name;
+	const char *dss_pclk_mmbuf_name;
+	const char *dss_dphy0_ref_clk_name;
+	const char *dss_dphy1_ref_clk_name;
+	const char *dss_dphy0_cfg_clk_name;
+	const char *dss_dphy1_cfg_clk_name;
+	const char *dss_pclk_dsi0_name;
+	const char *dss_pclk_dsi1_name;
+	const char *dss_pclk_pctrl_name;
+
+	struct clk *dss_axi_clk;
+	struct clk *dss_pclk_dss_clk;
+	struct clk *dss_pri_clk;
+	struct clk *dss_pxl0_clk;
+	struct clk *dss_pxl1_clk;
+	struct clk *dss_mmbuf_clk;
+	struct clk *dss_pclk_mmbuf_clk;
+	struct clk *dss_dphy0_ref_clk;
+	struct clk *dss_dphy1_ref_clk;
+	struct clk *dss_dphy0_cfg_clk;
+	struct clk *dss_dphy1_cfg_clk;
+	struct clk *dss_pclk_dsi0_clk;
+	struct clk *dss_pclk_dsi1_clk;
+	struct clk *dss_pclk_pctrl_clk;
+
+	struct hisi_panel_info panel_info;
+	bool panel_power_on;
+	bool fb_shutdown;
+	bool lcd_self_testing;
+	bool video_ldi_dis_at_vac_start;
+	unsigned int aod_function;
+
+	struct semaphore blank_sem;
+	struct semaphore blank_sem0;
+	struct semaphore offline_composer_sr_sem;
+	uint32_t offline_composer_sr_refcount;
+
+	void (*sysfs_attrs_append_fnc) (struct hisi_fb_data_type *hisifd,
+					struct attribute *attr);
+	int (*sysfs_create_fnc) (struct platform_device *pdev);
+	void (*sysfs_remove_fnc) (struct platform_device *pdev);
+	void (*pm_runtime_register) (struct platform_device *pdev);
+	void (*pm_runtime_unregister) (struct platform_device *pdev);
+	void (*pm_runtime_get) (struct hisi_fb_data_type *hisifd);
+	void (*pm_runtime_put) (struct hisi_fb_data_type *hisifd);
+	void (*bl_register) (struct platform_device *pdev);
+	void (*bl_unregister) (struct platform_device *pdev);
+	void (*bl_update) (struct hisi_fb_data_type *hisifd);
+	void (*bl_cancel) (struct hisi_fb_data_type *hisifd);
+	void (*vsync_register) (struct platform_device *pdev);
+	void (*vsync_unregister) (struct platform_device *pdev);
+	int (*vsync_ctrl_fnc) (struct fb_info *info, void __user *argp);
+	void (*vsync_isr_handler) (struct hisi_fb_data_type *hisifd);
+	void (*secure_register) (struct platform_device *pdev);
+	void (*secure_unregister) (struct platform_device *pdev);
+	void (*buf_sync_register) (struct platform_device *pdev);
+	void (*buf_sync_unregister) (struct platform_device *pdev);
+	void (*buf_sync_signal) (struct hisi_fb_data_type *hisifd);
+	void (*buf_sync_suspend) (struct hisi_fb_data_type *hisifd);
+	void (*esd_register) (struct platform_device *pdev);
+	void (*esd_unregister) (struct platform_device *pdev);
+	void (*debug_register) (struct platform_device *pdev);
+	void (*debug_unregister) (struct platform_device *pdev);
+	int (*cabc_update) (struct hisi_fb_data_type *hisifd);
+
+	 bool(*set_fastboot_fnc) (struct fb_info *info);
+	int (*open_sub_fnc) (struct fb_info *info);
+	int (*release_sub_fnc) (struct fb_info *info);
+	int (*on_fnc) (struct hisi_fb_data_type *hisifd);
+	int (*off_fnc) (struct hisi_fb_data_type *hisifd);
+	int (*lp_fnc) (struct hisi_fb_data_type *hisifd, bool lp_enter);
+	int (*esd_fnc) (struct hisi_fb_data_type *hisifd);
+	int (*sbl_ctrl_fnc) (struct fb_info *info, int value);
+	void (*sbl_isr_handler) (struct hisi_fb_data_type *hisifd);
+	int (*mipi_dsi_bit_clk_upt_isr_handler) (struct hisi_fb_data_type *hisifd);
+	void (*crc_isr_handler) (struct hisi_fb_data_type *hisifd);
+	void (*ov_ldi_underflow_isr_handle) (struct hisi_fb_data_type *hisifd);
+
+	int (*pan_display_fnc) (struct hisi_fb_data_type *hisifd);
+	int (*ov_ioctl_handler) (struct hisi_fb_data_type *hisifd,
+				 uint32_t cmd, void __user *argp);
+	int (*ov_online_play) (struct hisi_fb_data_type *hisifd,
+			       void __user *argp);
+	void (*ov_wb_isr_handler) (struct hisi_fb_data_type *hisifd);
+	void (*ov_vactive0_start_isr_handler) (struct hisi_fb_data_type *hisifd);
+	void (*set_reg) (struct hisi_fb_data_type *hisifd, char __iomem *addr,
+			 uint32_t val, uint8_t bw, uint8_t bs);
+
+	void (*sysfs_attrs_add_fnc) (struct hisi_fb_data_type *hisifd);
+
+	struct hisifb_backlight backlight;
+	int sbl_enable;
+	int sbl_lsensor_value;
+	int sbl_level;
+	dss_sbl_t sbl;
+	int color_temperature_flag;
+
+	int sysfs_index;
+	struct attribute *sysfs_attrs[HISI_FB_SYSFS_ATTRS_NUM];
+	struct attribute_group sysfs_attr_group;
+
+	struct hisifb_vsync vsync_ctrl;
+	struct hisifb_buf_sync buf_sync_ctrl;
+	struct dss_clk_rate dss_clk_rate;
+	struct hisifb_esd esd_ctrl;
+
+#ifdef CONFIG_FAKE_VSYNC_USED
+	bool fake_vsync_used;
+	struct hrtimer fake_vsync_hrtimer;
+#endif
+	dss_module_reg_t dss_module;
+	dss_overlay_t ov_req;
+	dss_overlay_block_t ov_block_infos[HISI_DSS_OV_BLOCK_NUMS];
+	dss_overlay_t ov_req_prev;
+	dss_overlay_block_t ov_block_infos_prev[HISI_DSS_OV_BLOCK_NUMS];
+	dss_overlay_t ov_req_prev_prev;
+	dss_overlay_block_t ov_block_infos_prev_prev[HISI_DSS_OV_BLOCK_NUMS];
+
+	dss_rect_t *ov_block_rects[HISI_DSS_OFFLINE_MAX_BLOCK];
+	dss_wb_info_t wb_info;
+
+	dss_cmdlist_data_t *cmdlist_data_tmp[HISI_DSS_CMDLIST_DATA_MAX];
+	dss_cmdlist_data_t *cmdlist_data;
+	dss_cmdlist_info_t *cmdlist_info;
+	int32_t cmdlist_idx;
+
+	dss_copybit_info_t *copybit_info;
+
+	struct gen_pool *mmbuf_gen_pool;
+	dss_mmbuf_info_t mmbuf_infos[HISI_DSS_CMDLIST_DATA_MAX];
+	dss_mmbuf_info_t *mmbuf_info;
+	struct list_head *mmbuf_list;
+
+	bool dss_module_resource_initialized;
+	dss_module_reg_t dss_module_default;
+
+	struct dss_rect dirty_region_updt;
+	uint32_t esd_happened;
+	uint32_t esd_recover_state;
+
+	struct ion_client *ion_client;
+	struct ion_handle *ion_handle;
+	struct iommu_map_format iommu_format;
+	struct iommu_domain *hisi_domain;
+
+	struct fb_info *fbi;
+	struct platform_device *pdev;
+
+	wait_queue_head_t vactive0_start_wq;
+	uint32_t vactive0_start_flag;
+	uint32_t vactive0_end_flag;
+	uint32_t ldi_data_gate_en;
+
+	wait_queue_head_t crc_wq;
+	uint32_t crc_flag;
+	struct workqueue_struct *dss_debug_wq;
+	struct work_struct dss_debug_work;
+
+	struct workqueue_struct *ldi_underflow_wq;
+	struct work_struct ldi_underflow_work;
+	struct workqueue_struct *rch2_ce_end_wq;
+	struct work_struct rch2_ce_end_work;
+	struct workqueue_struct *rch4_ce_end_wq;
+	struct work_struct rch4_ce_end_work;
+	struct workqueue_struct *dpp_ce_end_wq;
+	struct work_struct dpp_ce_end_work;
+	struct workqueue_struct *hiace_end_wq;
+	struct work_struct hiace_end_work;
+
+	dss_rect_t res_updt_rect;
+	dss_rect_t resolution_rect;
+
+	uint32_t frame_count;
+	uint32_t frame_update_flag;
+	bool fb_mem_free_flag;
+
+	uint8_t core_clk_upt_support;
+
+	uint32_t vactive_start_event;
+
+	uint32_t vsync_ctrl_type;
+	struct notifier_block nb;
+	struct notifier_block lcd_int_nb;
+};
+
+/******************************************************************************
+ ** FUNCTIONS PROTOTYPES
+ */
+extern int g_primary_lcd_xres;
+extern int g_primary_lcd_yres;
+extern uint64_t g_pxl_clk_rate;
+
+extern uint32_t g_online_cmdlist_idxs;
+extern uint32_t g_offline_cmdlist_idxs;
+
+extern uint32_t g_dss_version_tag;
+extern uint32_t g_dss_module_resource_initialized;
+extern uint32_t g_logo_buffer_base;
+extern uint32_t g_logo_buffer_size;
+extern uint32_t g_underflow_stop_perf_stat;
+
+/* for debug */
+extern int g_debug_ldi_underflow;
+extern int g_debug_ldi_underflow_clear;
+
+extern int g_debug_mmu_error;
+extern int g_debug_set_reg_val;
+extern int g_debug_online_vsync;
+extern int g_debug_ovl_online_composer;
+extern int g_debug_ovl_online_composer_hold;
+extern int g_debug_ovl_online_composer_return;
+extern int g_debug_ovl_online_composer_timediff;
+extern int g_debug_ovl_online_composer_time_threshold;
+
+extern int g_debug_ovl_offline_composer;
+extern int g_debug_ovl_block_composer;
+extern int g_debug_ovl_offline_composer_hold;
+extern int g_debug_ovl_offline_composer_timediff;
+extern int g_debug_ovl_offline_composer_time_threshold;
+extern int g_debug_ovl_offline_block_num;
+extern int g_debug_ovl_copybit_composer;
+extern int g_debug_ovl_copybit_composer_hold;
+extern int g_debug_ovl_copybit_composer_timediff;
+extern int g_debug_ovl_copybit_composer_time_threshold;
+
+extern int g_debug_ovl_cmdlist;
+extern int g_dump_cmdlist_content;
+extern int g_enable_ovl_cmdlist_online;
+extern int g_enable_ovl_cmdlist_offline;
+extern int g_rdma_stretch_threshold;
+extern int g_enable_dirty_region_updt;
+extern int g_debug_dirty_region_updt;
+extern int g_enable_crc_debug;
+extern int g_ldi_data_gate_en;
+extern int g_debug_need_save_file;
+extern int g_debug_ovl_credit_step;
+extern int g_debug_layerbuf_sync;
+extern int g_enable_dss_idle;
+extern int g_debug_dump_mmbuf;
+extern uint32_t g_mmbuf_addr_test;
+extern uint32_t g_dss_min_bandwidth_inbusbusy;
+
+extern int g_err_status;
+extern int g_debug_enable_lcd_sleep_in;
+
+extern struct fb_info *fbi_list[HISI_FB_MAX_FBI_LIST];
+extern struct hisi_fb_data_type *hisifd_list[HISI_FB_MAX_FBI_LIST];
+
+uint32_t get_panel_xres(struct hisi_fb_data_type *hisifd);
+uint32_t get_panel_yres(struct hisi_fb_data_type *hisifd);
+
+bool is_dss_idle_enable(void);
+
+/* fb buffer */
+unsigned long hisifb_alloc_fb_buffer(struct hisi_fb_data_type *hisifd);
+void hisifb_free_fb_buffer(struct hisi_fb_data_type *hisifd);
+void hisifb_free_logo_buffer(struct hisi_fb_data_type *hisifd);
+
+int hisi_fb_blank_sub(int blank_mode, struct fb_info *info);
+
+/* backlight */
+void hisifb_backlight_update(struct hisi_fb_data_type *hisifd);
+void hisifb_backlight_cancel(struct hisi_fb_data_type *hisifd);
+void hisifb_backlight_register(struct platform_device *pdev);
+void hisifb_backlight_unregister(struct platform_device *pdev);
+void hisifb_set_backlight(struct hisi_fb_data_type *hisifd, uint32_t bkl_lvl);
+
+/* vsync */
+void hisifb_frame_updated(struct hisi_fb_data_type *hisifd);
+#ifdef CONFIG_FAKE_VSYNC_USED
+enum hrtimer_restart hisifb_fake_vsync(struct hrtimer *timer);
+#endif
+void hisifb_set_vsync_activate_state(struct hisi_fb_data_type *hisifd,
+				     bool infinite);
+void hisifb_activate_vsync(struct hisi_fb_data_type *hisifd);
+void hisifb_deactivate_vsync(struct hisi_fb_data_type *hisifd);
+int hisifb_vsync_ctrl(struct fb_info *info, void __user *argp);
+int hisifb_vsync_resume(struct hisi_fb_data_type *hisifd);
+int hisifb_vsync_suspend(struct hisi_fb_data_type *hisifd);
+void hisifb_vsync_isr_handler(struct hisi_fb_data_type *hisifd);
+void hisifb_vsync_register(struct platform_device *pdev);
+void hisifb_vsync_unregister(struct platform_device *pdev);
+/* buffer sync */
+int hisifb_layerbuf_lock(struct hisi_fb_data_type *hisifd,
+			 dss_overlay_t *pov_req, struct list_head *lock_list);
+void hisifb_layerbuf_flush(struct hisi_fb_data_type *hisifd,
+			   struct list_head *lock_list);
+void hisifb_layerbuf_unlock(struct hisi_fb_data_type *hisifd,
+			    struct list_head *pfree_list);
+void hisifb_layerbuf_lock_exception(struct hisi_fb_data_type *hisifd,
+				    struct list_head *lock_list);
+
+int hisifb_buf_sync_wait(int fence_fd);
+int hisifb_buf_sync_handle(struct hisi_fb_data_type *hisifd,
+			   dss_overlay_t *pov_req);
+void hisifb_buf_sync_signal(struct hisi_fb_data_type *hisifd);
+void hisifb_buf_sync_suspend(struct hisi_fb_data_type *hisifd);
+int hisifb_buf_sync_create_fence(struct hisi_fb_data_type *hisifd,
+				 unsigned value);
+void hisifb_buf_sync_register(struct platform_device *pdev);
+void hisifb_buf_sync_unregister(struct platform_device *pdev);
+
+/* control */
+int hisifb_ctrl_on(struct hisi_fb_data_type *hisifd);
+int hisifb_ctrl_off(struct hisi_fb_data_type *hisifd);
+int hisifb_ctrl_dss_clk_rate_set(struct fb_info *info, void __user *argp);
+void hisifb_sysfs_attrs_add(struct hisi_fb_data_type *hisifd);
+
+void set_reg(char __iomem *addr, uint32_t val, uint8_t bw, uint8_t bs);
+uint32_t set_bits32(uint32_t old_val, uint32_t val, uint8_t bw, uint8_t bs);
+void hisifb_set_reg(struct hisi_fb_data_type *hisifd,
+		    char __iomem *addr, uint32_t val, uint8_t bw, uint8_t bs);
+uint32_t hisifb_line_length(int index, uint32_t xres, int bpp);
+void hisifb_get_timestamp(struct timeval *tv);
+uint32_t hisifb_timestamp_diff(struct timeval *lasttime,
+			       struct timeval *curtime);
+void hisifb_save_file(char *filename, char *buf, uint32_t buf_len);
+struct platform_device *hisi_fb_device_alloc(struct hisi_fb_panel_data *pdata,
+					     uint32_t type, uint32_t id);
+struct platform_device *hisi_fb_add_device(struct platform_device *pdev);
+#endif				/* HISI_FB_H */
diff --git a/drivers/video/fbdev/hisi/dss/hisi_mipi_dsi.c b/drivers/video/fbdev/hisi/dss/hisi_mipi_dsi.c
new file mode 100755
index 000000000000..54c43a3e85a5
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_mipi_dsi.c
@@ -0,0 +1,1686 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_mipi_dsi.h"
+
+#define DEFAULT_MAX_TX_ESC_CLK	(10 * 1000000UL)
+#define DEFAULT_MIPI_CLK_RATE	(192 * 100000L)
+#define DEFAULT_PCLK_DSI_RATE	(120 * 1000000L)
+
+#define ROUND1(x,y)	((x) / (y) + ((x) % (y) > 0 ? 1 : 0))
+#define DSS_REDUCE(x)	((x) > 0 ? ((x) - 1) : (x))
+
+struct dsi_phy_seq_info {
+	uint32_t min_range;
+	uint32_t max_range;
+	uint32_t rg_pll_vco_750M;
+	uint32_t rg_hstx_ckg_sel;
+};
+
+struct dsi_phy_seq_info dphy_seq_info[] = {
+	{47, 94, 0, 7},
+	{94, 188, 0, 6},
+	{188, 375, 0, 5},
+	{375, 750, 0, 4},
+	{750, 1500, 0, 0}
+};
+
+static void get_dsi_phy_ctrl(struct hisi_fb_data_type *hisifd,
+			     struct mipi_dsi_phy_ctrl *phy_ctrl)
+{
+	struct hisi_panel_info *pinfo = NULL;
+	uint32_t dsi_bit_clk = 0;
+
+	uint32_t ui = 0;
+	uint32_t m_pll = 0;
+	uint32_t n_pll = 0;
+	uint32_t m_n_fract = 0;
+	uint32_t m_n_int = 0;
+	uint64_t lane_clock = 0;
+	uint64_t vco_div = 1;
+
+	uint32_t accuracy = 0;
+	uint32_t unit_tx_byte_clk_hs = 0;
+	uint32_t clk_post = 0;
+	uint32_t clk_pre = 0;
+	uint32_t clk_t_hs_exit = 0;
+	uint32_t clk_pre_delay = 0;
+	uint32_t clk_t_hs_prepare = 0;
+	uint32_t clk_t_lpx = 0;
+	uint32_t clk_t_hs_zero = 0;
+	uint32_t clk_t_hs_trial = 0;
+	uint32_t data_post_delay = 0;
+	uint32_t data_t_hs_prepare = 0;
+	uint32_t data_t_hs_zero = 0;
+	uint32_t data_t_hs_trial = 0;
+	uint32_t data_t_lpx = 0;
+	uint32_t clk_pre_delay_reality = 0;
+	uint32_t clk_t_hs_zero_reality = 0;
+	uint32_t clk_post_delay_reality = 0;
+	uint32_t data_t_hs_zero_reality = 0;
+	uint32_t data_post_delay_reality = 0;
+	uint32_t data_pre_delay_reality = 0;
+
+	BUG_ON(phy_ctrl == NULL);
+	BUG_ON(hisifd == NULL);
+	pinfo = &(hisifd->panel_info);
+
+	dsi_bit_clk = pinfo->mipi.dsi_bit_clk_upt;
+	lane_clock = 2 * dsi_bit_clk;
+	HISI_FB_DEBUG("Expected : lane_clock = %llu M\n", lane_clock);
+
+	/************************  PLL parameters config  *********************/
+	if ((320 <= lane_clock) && (lane_clock <= 2500)) {
+		phy_ctrl->rg_band_sel = 0;
+		vco_div = 1;
+	} else if ((80 <= lane_clock) && (lane_clock < 320)) {
+		phy_ctrl->rg_band_sel = 1;
+		vco_div = 4;
+	} else {
+		HISI_FB_ERR
+		    ("80M <= lane_clock< = 2500M, not support lane_clock = %llu M\n",
+		     lane_clock);
+	}
+
+	m_n_int = lane_clock * vco_div * 1000000UL / DEFAULT_MIPI_CLK_RATE;
+	m_n_fract = ((lane_clock * vco_div * 1000000UL * 1000UL /
+	      DEFAULT_MIPI_CLK_RATE) % 1000) * 10 / 1000;
+
+	if (m_n_int % 2 == 0) {
+		if (m_n_fract * 6 >= 50) {
+			n_pll = 2;
+			m_pll = (m_n_int + 1) * n_pll;
+		} else if (m_n_fract * 6 >= 30) {
+			n_pll = 3;
+			m_pll = m_n_int * n_pll + 2;
+		} else {
+			n_pll = 1;
+			m_pll = m_n_int * n_pll;
+		}
+	} else {
+		if (m_n_fract * 6 >= 50) {
+			n_pll = 1;
+			m_pll = (m_n_int + 1) * n_pll;
+		} else if (m_n_fract * 6 >= 30) {
+			n_pll = 1;
+			m_pll = (m_n_int + 1) * n_pll;
+		} else if (m_n_fract * 6 >= 10) {
+			n_pll = 3;
+			m_pll = m_n_int * n_pll + 1;
+		} else {
+			n_pll = 2;
+			m_pll = m_n_int * n_pll;
+		}
+	}
+
+	if (m_pll <= 8) {
+		phy_ctrl->rg_pll_fbd_s = 1;
+		phy_ctrl->rg_pll_enswc = 0;
+
+		if (m_pll % 2 == 0) {
+			phy_ctrl->rg_pll_fbd_p = m_pll / 2;
+		} else {
+			if (n_pll == 1) {
+				n_pll *= 2;
+				phy_ctrl->rg_pll_fbd_p = (m_pll * 2) / 2;
+			} else {
+				HISI_FB_ERR
+				    ("phy m_pll not support!m_pll = %d\n", m_pll);
+				return;
+			}
+		}
+	} else if (m_pll <= 300) {
+		if (m_pll % 2 == 0) {
+			phy_ctrl->rg_pll_enswc = 0;
+		} else {
+			phy_ctrl->rg_pll_enswc = 1;
+		}
+		phy_ctrl->rg_pll_fbd_s = 1;
+		phy_ctrl->rg_pll_fbd_p = m_pll / 2;
+	} else if (m_pll <= 315) {
+		phy_ctrl->rg_pll_fbd_p = 150;
+		phy_ctrl->rg_pll_fbd_s = m_pll - 2 * phy_ctrl->rg_pll_fbd_p;
+		phy_ctrl->rg_pll_enswc = 1;
+	} else {
+		HISI_FB_ERR("phy m_pll not support!m_pll = %d\n", m_pll);
+		return;
+	}
+
+	phy_ctrl->rg_pll_pre_p = n_pll;
+
+	lane_clock = m_pll * (DEFAULT_MIPI_CLK_RATE / n_pll) / vco_div;
+	HISI_FB_DEBUG("Config : lane_clock = %llu\n", lane_clock);
+
+	phy_ctrl->rg_pll_cp = 1;
+	phy_ctrl->rg_pll_cp_p = 3;
+
+	phy_ctrl->rg_pll_enbwt = 0;
+	phy_ctrl->rg_pll_chp = 0;
+
+	phy_ctrl->rg_pll_lpf_cs = 0;
+	phy_ctrl->rg_pll_refsel = 1;
+
+	phy_ctrl->reload_sel = 1;
+	phy_ctrl->rg_phase_gen_en = 1;
+	phy_ctrl->pll_power_down = 0;
+	phy_ctrl->pll_register_override = 1;
+
+	phy_ctrl->rg_vrefsel_vcm = 0x55;
+	if (pinfo->mipi.rg_vrefsel_vcm_clk_adjust != 0)
+		phy_ctrl->rg_vrefsel_vcm = (phy_ctrl->rg_vrefsel_vcm & 0x0F) |
+		    ((pinfo->mipi.rg_vrefsel_vcm_clk_adjust & 0x0F) << 4);
+
+	if (pinfo->mipi.rg_vrefsel_vcm_data_adjust != 0)
+		phy_ctrl->rg_vrefsel_vcm = (phy_ctrl->rg_vrefsel_vcm & 0xF0) |
+		    (pinfo->mipi.rg_vrefsel_vcm_data_adjust & 0x0F);
+
+	phy_ctrl->load_command = 0x5A;
+
+	/********************  clock/data lane parameters config  ******************/
+	accuracy = 10;
+	ui = 10 * 1000000000UL * accuracy / lane_clock;
+	unit_tx_byte_clk_hs = 8 * ui;
+
+	clk_post = 600 * accuracy + 52 * ui + pinfo->mipi.clk_post_adjust * ui;
+
+	clk_pre = 8 * ui + pinfo->mipi.clk_pre_adjust * ui;
+
+	clk_t_hs_exit = 1000 * accuracy + pinfo->mipi.clk_t_hs_exit_adjust * ui;
+
+	clk_pre_delay = 0 + pinfo->mipi.clk_pre_delay_adjust * ui;
+
+	clk_t_hs_trial =
+	    600 * accuracy + 3 * unit_tx_byte_clk_hs +
+	    pinfo->mipi.clk_t_hs_trial_adjust * ui;
+
+	if (pinfo->mipi.clk_t_hs_prepare_adjust == 0)
+		pinfo->mipi.clk_t_hs_prepare_adjust = 43;
+
+	clk_t_hs_prepare =
+	    ((380 * accuracy + pinfo->mipi.clk_t_hs_prepare_adjust * ui) <=
+	     (950 * accuracy - 8 * ui)) ? (380 * accuracy +
+					   pinfo->mipi.clk_t_hs_prepare_adjust *
+					   ui) : (950 * accuracy - 8 * ui);
+
+	data_post_delay = 0 + pinfo->mipi.data_post_delay_adjust * ui;
+
+	data_t_hs_trial =
+	    ((600 * accuracy + 4 * ui) >=
+	     (8 * ui) ? (600 * accuracy + 4 * ui) : (8 * ui)) + 8 * ui +
+	    3 * unit_tx_byte_clk_hs + pinfo->mipi.data_t_hs_trial_adjust * ui;
+
+	if (pinfo->mipi.data_t_hs_prepare_adjust == 0)
+		pinfo->mipi.data_t_hs_prepare_adjust = 35;
+
+	data_t_hs_prepare =
+	    ((400 * accuracy + 4 * ui +
+	      pinfo->mipi.data_t_hs_prepare_adjust * ui) <=
+	     (850 * accuracy + 6 * ui - 8 * ui)) ? (400 * accuracy + 4 * ui +
+						    pinfo->mipi.data_t_hs_prepare_adjust *
+						    ui) : (850 * accuracy + 6 * ui - 8 * ui);
+
+	clk_t_lpx = (((2000 * accuracy - clk_t_hs_prepare) >= 500 * accuracy) ?
+		     ((2000 * accuracy - clk_t_hs_prepare)) : (500 * accuracy)) +
+				pinfo->mipi.clk_t_lpx_adjust * ui;
+
+	clk_t_hs_zero =
+	    3000 * accuracy - clk_t_hs_prepare + 3 * unit_tx_byte_clk_hs +
+	    pinfo->mipi.clk_t_hs_zero_adjust * ui;
+
+	data_t_lpx = clk_t_lpx + pinfo->mipi.data_t_lpx_adjust * ui;
+
+	data_t_hs_zero = 1450 * accuracy + 10 * ui - data_t_hs_prepare +
+	    3 * unit_tx_byte_clk_hs + pinfo->mipi.data_t_hs_zero_adjust * ui;
+
+	phy_ctrl->clk_pre_delay = ROUND1(clk_pre_delay, unit_tx_byte_clk_hs);
+	phy_ctrl->clk_t_hs_prepare =
+	    ROUND1(clk_t_hs_prepare, unit_tx_byte_clk_hs);
+	phy_ctrl->clk_t_lpx = ROUND1(clk_t_lpx, unit_tx_byte_clk_hs);
+	phy_ctrl->clk_t_hs_zero = ROUND1(clk_t_hs_zero, unit_tx_byte_clk_hs);
+	phy_ctrl->clk_t_hs_trial = ROUND1(clk_t_hs_trial, unit_tx_byte_clk_hs);
+
+	phy_ctrl->data_post_delay =
+	    ROUND1(data_post_delay, unit_tx_byte_clk_hs);
+	phy_ctrl->data_t_hs_prepare =
+	    ROUND1(data_t_hs_prepare, unit_tx_byte_clk_hs);
+	phy_ctrl->data_t_lpx = ROUND1(data_t_lpx, unit_tx_byte_clk_hs);
+	phy_ctrl->data_t_hs_zero = ROUND1(data_t_hs_zero, unit_tx_byte_clk_hs);
+	phy_ctrl->data_t_hs_trial =
+	    ROUND1(data_t_hs_trial, unit_tx_byte_clk_hs);
+	phy_ctrl->data_t_ta_go = 4;
+	phy_ctrl->data_t_ta_get = 5;
+
+	clk_pre_delay_reality = phy_ctrl->clk_pre_delay + 2;
+	clk_t_hs_zero_reality = phy_ctrl->clk_t_hs_zero + 8;
+	data_t_hs_zero_reality = phy_ctrl->data_t_hs_zero + 4;
+	data_post_delay_reality = phy_ctrl->data_post_delay + 4;
+
+	phy_ctrl->clk_post_delay =
+	    phy_ctrl->data_t_hs_trial + ROUND1(clk_post, unit_tx_byte_clk_hs);
+	phy_ctrl->data_pre_delay =
+	    clk_pre_delay_reality + phy_ctrl->clk_t_lpx +
+	    phy_ctrl->clk_t_hs_prepare + clk_t_hs_zero_reality +
+	    ROUND1(clk_pre, unit_tx_byte_clk_hs);
+
+	clk_post_delay_reality = phy_ctrl->clk_post_delay + 4;
+	data_pre_delay_reality = phy_ctrl->data_pre_delay + 2;
+
+	phy_ctrl->clk_lane_lp2hs_time =
+	    clk_pre_delay_reality + phy_ctrl->clk_t_lpx +
+	    phy_ctrl->clk_t_hs_prepare + clk_t_hs_zero_reality + 3;
+	phy_ctrl->clk_lane_hs2lp_time =
+	    clk_post_delay_reality + phy_ctrl->clk_t_hs_trial + 3;
+	phy_ctrl->data_lane_lp2hs_time =
+	    data_pre_delay_reality + phy_ctrl->data_t_lpx +
+	    phy_ctrl->data_t_hs_prepare + data_t_hs_zero_reality + 3;
+	phy_ctrl->data_lane_hs2lp_time =
+	    data_post_delay_reality + phy_ctrl->data_t_hs_trial + 3;
+	phy_ctrl->phy_stop_wait_time =
+	    clk_post_delay_reality + phy_ctrl->clk_t_hs_trial +
+	    ROUND1(clk_t_hs_exit, unit_tx_byte_clk_hs) -
+	    (data_post_delay_reality + phy_ctrl->data_t_hs_trial) + 3;
+
+	phy_ctrl->lane_byte_clk = lane_clock / 8;
+	phy_ctrl->clk_division =
+	    (((phy_ctrl->lane_byte_clk / 2) % pinfo->mipi.max_tx_esc_clk) >
+	     0) ? (phy_ctrl->lane_byte_clk / 2 / pinfo->mipi.max_tx_esc_clk +
+		   1) : (phy_ctrl->lane_byte_clk / 2 /
+			 pinfo->mipi.max_tx_esc_clk);
+
+	HISI_FB_DEBUG("PHY clock_lane and data_lane config : \n"
+		      "rg_vrefsel_vcm=%u\n"
+		      "clk_pre_delay=%u\n"
+		      "clk_post_delay=%u\n"
+		      "clk_t_hs_prepare=%u\n"
+		      "clk_t_lpx=%u\n"
+		      "clk_t_hs_zero=%u\n"
+		      "clk_t_hs_trial=%u\n"
+		      "data_pre_delay=%u\n"
+		      "data_post_delay=%u\n"
+		      "data_t_hs_prepare=%u\n"
+		      "data_t_lpx=%u\n"
+		      "data_t_hs_zero=%u\n"
+		      "data_t_hs_trial=%u\n"
+		      "data_t_ta_go=%u\n"
+		      "data_t_ta_get=%u\n",
+		      phy_ctrl->rg_vrefsel_vcm,
+		      phy_ctrl->clk_pre_delay,
+		      phy_ctrl->clk_post_delay,
+		      phy_ctrl->clk_t_hs_prepare,
+		      phy_ctrl->clk_t_lpx,
+		      phy_ctrl->clk_t_hs_zero,
+		      phy_ctrl->clk_t_hs_trial,
+		      phy_ctrl->data_pre_delay,
+		      phy_ctrl->data_post_delay,
+		      phy_ctrl->data_t_hs_prepare,
+		      phy_ctrl->data_t_lpx,
+		      phy_ctrl->data_t_hs_zero,
+		      phy_ctrl->data_t_hs_trial,
+		      phy_ctrl->data_t_ta_go, phy_ctrl->data_t_ta_get);
+	HISI_FB_DEBUG("clk_lane_lp2hs_time=%u\n"
+		      "clk_lane_hs2lp_time=%u\n"
+		      "data_lane_lp2hs_time=%u\n"
+		      "data_lane_hs2lp_time=%u\n"
+		      "phy_stop_wait_time=%u\n",
+		      phy_ctrl->clk_lane_lp2hs_time,
+		      phy_ctrl->clk_lane_hs2lp_time,
+		      phy_ctrl->data_lane_lp2hs_time,
+		      phy_ctrl->data_lane_hs2lp_time,
+		      phy_ctrl->phy_stop_wait_time);
+}
+
+static uint32_t mipi_pixel_clk(struct hisi_fb_data_type *hisifd)
+{
+	struct hisi_panel_info *pinfo = NULL;
+
+	BUG_ON(hisifd == NULL);
+	pinfo = &(hisifd->panel_info);
+
+	if (pinfo->pxl_clk_rate_div == 0) {
+		return pinfo->pxl_clk_rate;
+	}
+
+	if ((pinfo->ifbc_type == IFBC_TYPE_NONE) && !is_dual_mipi_panel(hisifd)) {
+		pinfo->pxl_clk_rate_div = 1;
+	}
+
+	return pinfo->pxl_clk_rate / pinfo->pxl_clk_rate_div;
+}
+
+static void mipi_init(struct hisi_fb_data_type *hisifd, char __iomem *mipi_dsi_base)
+{
+	uint32_t hline_time = 0;
+	uint32_t hsa_time = 0;
+	uint32_t hbp_time = 0;
+	uint64_t pixel_clk = 0;
+	uint32_t i = 0;
+	unsigned long dw_jiffies = 0;
+	uint32_t tmp = 0;
+	bool is_ready = false;
+	struct hisi_panel_info *pinfo = NULL;
+	dss_rect_t rect;
+	uint32_t cmp_stopstate_val = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(mipi_dsi_base == NULL);
+
+	pinfo = &(hisifd->panel_info);
+
+	if (pinfo->mipi.max_tx_esc_clk == 0) {
+		HISI_FB_ERR("fb%d, max_tx_esc_clk is invalid!", hisifd->index);
+		pinfo->mipi.max_tx_esc_clk = DEFAULT_MAX_TX_ESC_CLK;
+	}
+
+	memset(&(pinfo->dsi_phy_ctrl), 0, sizeof(struct mipi_dsi_phy_ctrl));
+	get_dsi_phy_ctrl(hisifd, &(pinfo->dsi_phy_ctrl));
+
+	rect.x = 0;
+	rect.y = 0;
+	rect.w = pinfo->xres;
+	rect.h = pinfo->yres;
+
+	mipi_ifbc_get_rect(hisifd, &rect);
+
+	/*************************Configure the DPHY start*************************/
+	set_reg(mipi_dsi_base + MIPIDSI_PHY_IF_CFG_OFFSET,
+		pinfo->mipi.lane_nums, 2, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_CLKMGR_CFG_OFFSET,
+		pinfo->dsi_phy_ctrl.clk_division, 8, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_CLKMGR_CFG_OFFSET,
+		pinfo->dsi_phy_ctrl.clk_division, 8, 8);
+
+	outp32(mipi_dsi_base + MIPIDSI_PHY_RSTZ_OFFSET, 0x00000000);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000001);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010014);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+	       (pinfo->dsi_phy_ctrl.rg_pll_fbd_s << 4) +
+	       (pinfo->dsi_phy_ctrl.rg_pll_enswc << 3) +
+	       (pinfo->dsi_phy_ctrl.rg_pll_enbwt << 2) +
+	       pinfo->dsi_phy_ctrl.rg_pll_chp);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010015);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+	       pinfo->dsi_phy_ctrl.rg_pll_fbd_p);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010016);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+	       (pinfo->dsi_phy_ctrl.rg_pll_cp << 5) +
+	       (pinfo->dsi_phy_ctrl.rg_pll_lpf_cs << 4) +
+	       pinfo->dsi_phy_ctrl.rg_pll_refsel);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010017);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+	       pinfo->dsi_phy_ctrl.rg_pll_pre_p);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x0001001D);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+	       pinfo->dsi_phy_ctrl.rg_vrefsel_vcm);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x0001001E);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+	       (pinfo->dsi_phy_ctrl.rg_pll_cp_p << 5) +
+	       (pinfo->dsi_phy_ctrl.reload_sel << 4) +
+	       (pinfo->dsi_phy_ctrl.rg_phase_gen_en << 3) +
+	       (pinfo->dsi_phy_ctrl.rg_band_sel << 2) +
+	       (pinfo->dsi_phy_ctrl.pll_power_down << 1) +
+	       pinfo->dsi_phy_ctrl.pll_register_override);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x0001001F);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+	       pinfo->dsi_phy_ctrl.load_command);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010020);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+	       DSS_REDUCE(pinfo->dsi_phy_ctrl.clk_pre_delay));
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010021);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+	       DSS_REDUCE(pinfo->dsi_phy_ctrl.clk_post_delay));
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010022);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+	       DSS_REDUCE(pinfo->dsi_phy_ctrl.clk_t_lpx));
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010023);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+	       DSS_REDUCE(pinfo->dsi_phy_ctrl.clk_t_hs_prepare));
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010024);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+	       DSS_REDUCE(pinfo->dsi_phy_ctrl.clk_t_hs_zero));
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010025);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+	       pinfo->dsi_phy_ctrl.clk_t_hs_trial);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
+
+	for (i = 0; i <= pinfo->mipi.lane_nums; i++) {
+		tmp = 0x10030 + (i << 4);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, tmp);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000002);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000000);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+		       DSS_REDUCE(pinfo->dsi_phy_ctrl.data_pre_delay));
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000002);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000000);
+
+		tmp = 0x10031 + (i << 4);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, tmp);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000002);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000000);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+		       DSS_REDUCE(pinfo->dsi_phy_ctrl.data_post_delay));
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000002);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000000);
+
+		tmp = 0x10032 + (i << 4);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, tmp);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000002);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000000);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+		       DSS_REDUCE(pinfo->dsi_phy_ctrl.data_t_lpx));
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000002);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000000);
+
+		tmp = 0x10033 + (i << 4);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, tmp);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000002);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000000);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+		       DSS_REDUCE(pinfo->dsi_phy_ctrl.data_t_hs_prepare));
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000002);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000000);
+
+		tmp = 0x10034 + (i << 4);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, tmp);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000002);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000000);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+		       DSS_REDUCE(pinfo->dsi_phy_ctrl.data_t_hs_zero));
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000002);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000000);
+
+		tmp = 0x10035 + (i << 4);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, tmp);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000002);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000000);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+		       pinfo->dsi_phy_ctrl.data_t_hs_trial);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000002);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000000);
+
+		tmp = 0x10036 + (i << 4);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, tmp);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000002);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000000);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+		       DSS_REDUCE(pinfo->dsi_phy_ctrl.data_t_ta_go));
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000002);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000000);
+
+		tmp = 0x10037 + (i << 4);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, tmp);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000002);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000000);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET,
+		       DSS_REDUCE(pinfo->dsi_phy_ctrl.data_t_ta_get));
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000002);
+		outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET,
+		       0x00000000);
+	}
+
+	outp32(mipi_dsi_base + MIPIDSI_PHY_RSTZ_OFFSET, 0x00000007);
+
+	is_ready = false;
+	dw_jiffies = jiffies + HZ / 2;
+	do {
+		tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+		if ((tmp & 0x00000001) == 0x00000001) {
+			is_ready = true;
+			break;
+		}
+	} while (time_after(dw_jiffies, jiffies));
+
+	if (!is_ready) {
+		HISI_FB_INFO
+		    ("fb%d, phylock is not ready!MIPIDSI_PHY_STATUS_OFFSET=0x%x.\n",
+		     hisifd->index, tmp);
+	}
+
+	if (pinfo->mipi.lane_nums >= DSI_4_LANES) {
+		cmp_stopstate_val = (BIT(4) | BIT(7) | BIT(9) | BIT(11));
+	} else if (pinfo->mipi.lane_nums >= DSI_3_LANES) {
+		cmp_stopstate_val = (BIT(4) | BIT(7) | BIT(9));
+	} else if (pinfo->mipi.lane_nums >= DSI_2_LANES) {
+		cmp_stopstate_val = (BIT(4) | BIT(7));
+	} else {
+		cmp_stopstate_val = (BIT(4));
+	}
+
+	is_ready = false;
+	dw_jiffies = jiffies + HZ / 2;
+	do {
+		tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+		if ((tmp & cmp_stopstate_val) == cmp_stopstate_val) {
+			is_ready = true;
+			break;
+		}
+	} while (time_after(dw_jiffies, jiffies));
+
+	if (!is_ready) {
+		HISI_FB_INFO
+		    ("fb%d, phystopstateclklane is not ready! "
+		     "MIPIDSI_PHY_STATUS_OFFSET=0x%x.\n",
+		     hisifd->index, tmp);
+	}
+
+	/*************************Configure the DPHY end*************************/
+
+	if (is_mipi_cmd_panel(hisifd)) {
+
+		set_reg(mipi_dsi_base + MIPIDSI_MODE_CFG_OFFSET, 0x1, 1, 0);
+		set_reg(mipi_dsi_base + MIPIDSI_EDPI_CMD_SIZE_OFFSET, rect.w, 16, 0);
+
+		if (pinfo->mipi.hs_wr_to_time == 0) {
+			set_reg(mipi_dsi_base + MIPIDSI_HS_WR_TO_CNT_OFFSET,
+				0x1000002, 25, 0);
+		} else {
+			set_reg(mipi_dsi_base + MIPIDSI_HS_WR_TO_CNT_OFFSET,
+				(0x1 << 24) | (pinfo->mipi.hs_wr_to_time *
+				 pinfo->dsi_phy_ctrl.lane_byte_clk / 1000000000UL), 25, 0);
+		}
+	}
+
+	set_reg(mipi_dsi_base + MIPIDSI_PHY_IF_CFG_OFFSET,
+		pinfo->dsi_phy_ctrl.phy_stop_wait_time, 8, 8);
+
+	/*
+	 ** 2. Configure the DPI Interface:
+	 ** This defines how the DPI interface interacts with the controller.
+	 */
+	set_reg(mipi_dsi_base + MIPIDSI_DPI_VCID_OFFSET, pinfo->mipi.vc, 2, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_DPI_COLOR_CODING_OFFSET,
+		pinfo->mipi.color_mode, 4, 0);
+
+	set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET,
+		pinfo->ldi.data_en_plr, 1, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET,
+		pinfo->ldi.vsync_plr, 1, 1);
+	set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET,
+		pinfo->ldi.hsync_plr, 1, 2);
+	set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET, 0x0, 1, 3);
+	set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET, 0x0, 1, 4);
+
+	/*
+	 ** 3. Select the Video Transmission Mode:
+	 ** This defines how the processor requires the video line to be
+	 ** transported through the DSI link.
+	 */
+
+	set_reg(mipi_dsi_base + MIPIDSI_VID_MODE_CFG_OFFSET, 0x3f, 6, 8);
+	/* set_reg(mipi_dsi_base + MIPIDSI_VID_MODE_CFG_OFFSET, 0x0, 1, 14); */
+	if (is_mipi_video_panel(hisifd)) {
+		set_reg(mipi_dsi_base + MIPIDSI_DPI_LP_CMD_TIM_OFFSET, 0x4, 8, 16);
+		set_reg(mipi_dsi_base + MIPIDSI_VID_MODE_CFG_OFFSET, 0x1, 1, 15);
+	}
+
+	if ((pinfo->mipi.dsi_version == DSI_1_2_VERSION)
+	    && (is_mipi_video_panel(hisifd))
+	    && ((pinfo->ifbc_type == IFBC_TYPE_VESA3X_SINGLE)
+		 || (pinfo->ifbc_type == IFBC_TYPE_VESA3X_DUAL))) {
+
+		set_reg(mipi_dsi_base + MIPIDSI_VID_PKT_SIZE_OFFSET,
+			rect.w * pinfo->pxl_clk_rate_div, 14, 0);
+
+		if (pinfo->mipi.burst_mode < DSI_BURST_SYNC_PULSES_1) {
+			HISI_FB_INFO
+			    ("pinfo->mipi.burst_mode = %d. video need config BURST mode\n",
+			     pinfo->mipi.burst_mode);
+			pinfo->mipi.burst_mode = DSI_BURST_SYNC_PULSES_1;
+		}
+	} else {
+		set_reg(mipi_dsi_base + MIPIDSI_VID_PKT_SIZE_OFFSET, rect.w, 14, 0);
+	}
+
+	set_reg(mipi_dsi_base + MIPIDSI_VID_MODE_CFG_OFFSET,
+		pinfo->mipi.burst_mode, 2, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_PCKHDL_CFG_OFFSET, 0x1, 1, 2);
+
+	/*
+	 ** 4. Define the DPI Horizontal timing configuration:
+	 **
+	 ** Hsa_time = HSA*(PCLK period/Clk Lane Byte Period);
+	 ** Hbp_time = HBP*(PCLK period/Clk Lane Byte Period);
+	 ** Hline_time = (HSA+HBP+HACT+HFP)*(PCLK period/Clk Lane Byte Period);
+	 */
+	pixel_clk = mipi_pixel_clk(hisifd);
+	hsa_time =
+	    pinfo->ldi.h_pulse_width * pinfo->dsi_phy_ctrl.lane_byte_clk /
+	    pixel_clk;
+	hbp_time =
+	    pinfo->ldi.h_back_porch * pinfo->dsi_phy_ctrl.lane_byte_clk /
+	    pixel_clk;
+	hline_time =
+	    (pinfo->ldi.h_pulse_width + pinfo->ldi.h_back_porch + rect.w +
+	     pinfo->ldi.h_front_porch) * pinfo->dsi_phy_ctrl.lane_byte_clk /
+	    pixel_clk;
+	set_reg(mipi_dsi_base + MIPIDSI_VID_HSA_TIME_OFFSET, hsa_time, 12, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_VID_HBP_TIME_OFFSET, hbp_time, 12, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_VID_HLINE_TIME_OFFSET, hline_time, 15, 0);
+
+	set_reg(mipi_dsi_base + MIPIDSI_VID_VSA_LINES_OFFSET,
+		pinfo->ldi.v_pulse_width, 10, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_VID_VBP_LINES_OFFSET,
+		pinfo->ldi.v_back_porch, 10, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_VID_VFP_LINES_OFFSET,
+		pinfo->ldi.v_front_porch, 10, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_VID_VACTIVE_LINES_OFFSET, rect.h, 14, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_TO_CNT_CFG_OFFSET, 0x7FF, 16, 0);
+
+	set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_LPCLK_CFG_OFFSET,
+		pinfo->dsi_phy_ctrl.clk_lane_lp2hs_time, 10, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_LPCLK_CFG_OFFSET,
+		pinfo->dsi_phy_ctrl.clk_lane_hs2lp_time, 10, 16);
+	set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_RD_CFG_OFFSET, 0x7FFF, 15, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_CFG_OFFSET,
+		pinfo->dsi_phy_ctrl.data_lane_lp2hs_time, 10, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_CFG_OFFSET,
+		pinfo->dsi_phy_ctrl.data_lane_hs2lp_time, 10, 16);
+
+	set_reg(mipi_dsi_base + MIPIDSI_PWR_UP_OFFSET, 0x1, 1, 0);
+}
+
+int mipi_dsi_clk_enable(struct hisi_fb_data_type *hisifd)
+{
+	int ret = 0;
+	struct clk *clk_tmp = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		clk_tmp = hisifd->dss_dphy0_ref_clk;
+		if (clk_tmp) {
+			ret = clk_prepare(clk_tmp);
+			if (ret) {
+				HISI_FB_ERR
+				    ("fb%d dss_dphy0_ref_clk clk_prepare failed, error=%d!\n",
+				     hisifd->index, ret);
+				return -EINVAL;
+			}
+
+			ret = clk_enable(clk_tmp);
+			if (ret) {
+				HISI_FB_ERR
+				    ("fb%d dss_dphy0_ref_clk clk_enable failed, error=%d!\n",
+				     hisifd->index, ret);
+				return -EINVAL;
+			}
+		}
+
+		clk_tmp = hisifd->dss_dphy0_cfg_clk;
+		if (clk_tmp) {
+			ret = clk_prepare(clk_tmp);
+			if (ret) {
+				HISI_FB_ERR
+				    ("fb%d dss_dphy0_cfg_clk clk_prepare failed, error=%d!\n",
+				     hisifd->index, ret);
+				return -EINVAL;
+			}
+
+			ret = clk_enable(clk_tmp);
+			if (ret) {
+				HISI_FB_ERR
+				    ("fb%d dss_dphy0_cfg_clk clk_enable failed, error=%d!\n",
+				     hisifd->index, ret);
+				return -EINVAL;
+			}
+		}
+
+		clk_tmp = hisifd->dss_pclk_dsi0_clk;
+		if (clk_tmp) {
+			ret = clk_prepare(clk_tmp);
+			if (ret) {
+				HISI_FB_ERR
+				    ("fb%d dss_pclk_dsi0_clk clk_prepare failed, error=%d!\n",
+				     hisifd->index, ret);
+				return -EINVAL;
+			}
+
+			ret = clk_enable(clk_tmp);
+			if (ret) {
+				HISI_FB_ERR
+				    ("fb%d dss_pclk_dsi0_clk clk_enable failed, error=%d!\n",
+				     hisifd->index, ret);
+				return -EINVAL;
+			}
+		}
+	}
+#ifdef CONFIG_PCLK_PCTRL_USED
+	clk_tmp = hisifd->dss_pclk_pctrl_clk;
+	if (clk_tmp) {
+		ret = clk_prepare(clk_tmp);
+		if (ret) {
+			HISI_FB_ERR
+			    ("fb%d dss_pclk_pctrl_clk clk_prepare failed, error=%d!\n",
+			     hisifd->index, ret);
+			return -EINVAL;
+		}
+
+		ret = clk_enable(clk_tmp);
+		if (ret) {
+			HISI_FB_ERR
+			    ("fb%d dss_pclk_pctrl_clk clk_enable failed, error=%d!\n",
+			     hisifd->index, ret);
+			return -EINVAL;
+		}
+	}
+#endif
+
+	if (is_dual_mipi_panel(hisifd) || (hisifd->index == EXTERNAL_PANEL_IDX)) {
+		clk_tmp = hisifd->dss_dphy1_ref_clk;
+		if (clk_tmp) {
+			ret = clk_prepare(clk_tmp);
+			if (ret) {
+				HISI_FB_ERR
+				    ("fb%d dss_dphy1_ref_clk clk_prepare failed, error=%d!\n",
+				     hisifd->index, ret);
+				return -EINVAL;
+			}
+
+			ret = clk_enable(clk_tmp);
+			if (ret) {
+				HISI_FB_ERR
+				    ("fb%d dss_dphy1_ref_clk clk_enable failed, error=%d!\n",
+				     hisifd->index, ret);
+				return -EINVAL;
+			}
+		}
+
+		clk_tmp = hisifd->dss_dphy1_cfg_clk;
+		if (clk_tmp) {
+			ret = clk_prepare(clk_tmp);
+			if (ret) {
+				HISI_FB_ERR
+				    ("fb%d dss_dphy1_cfg_clk clk_prepare failed, error=%d!\n",
+				     hisifd->index, ret);
+				return -EINVAL;
+			}
+
+			ret = clk_enable(clk_tmp);
+			if (ret) {
+				HISI_FB_ERR
+				    ("fb%d dss_dphy1_cfg_clk clk_enable failed, error=%d!\n",
+				     hisifd->index, ret);
+				return -EINVAL;
+			}
+		}
+
+		clk_tmp = hisifd->dss_pclk_dsi1_clk;
+		if (clk_tmp) {
+			ret = clk_prepare(clk_tmp);
+			if (ret) {
+				HISI_FB_ERR
+				    ("fb%d dss_pclk_dsi1_clk clk_prepare failed, error=%d!\n",
+				     hisifd->index, ret);
+				return -EINVAL;
+			}
+
+			ret = clk_enable(clk_tmp);
+			if (ret) {
+				HISI_FB_ERR
+				    ("fb%d dss_pclk_dsi1_clk clk_enable failed, error=%d!\n",
+				     hisifd->index, ret);
+				return -EINVAL;
+			}
+		}
+	}
+
+	return 0;
+}
+
+int mipi_dsi_clk_disable(struct hisi_fb_data_type *hisifd)
+{
+	struct clk *clk_tmp = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		clk_tmp = hisifd->dss_dphy0_ref_clk;
+		if (clk_tmp) {
+			clk_disable(clk_tmp);
+			clk_unprepare(clk_tmp);
+		}
+
+		clk_tmp = hisifd->dss_dphy0_cfg_clk;
+		if (clk_tmp) {
+			clk_disable(clk_tmp);
+			clk_unprepare(clk_tmp);
+		}
+
+		clk_tmp = hisifd->dss_pclk_dsi0_clk;
+		if (clk_tmp) {
+			clk_disable(clk_tmp);
+			clk_unprepare(clk_tmp);
+		}
+	}
+#ifdef CONFIG_PCLK_PCTRL_USED
+	clk_tmp = hisifd->dss_pclk_pctrl_clk;
+	if (clk_tmp) {
+		clk_disable(clk_tmp);
+		clk_unprepare(clk_tmp);
+	}
+#endif
+
+	if (is_dual_mipi_panel(hisifd) || (hisifd->index == EXTERNAL_PANEL_IDX)) {
+		clk_tmp = hisifd->dss_dphy1_ref_clk;
+		if (clk_tmp) {
+			clk_disable(clk_tmp);
+			clk_unprepare(clk_tmp);
+		}
+
+		clk_tmp = hisifd->dss_dphy1_cfg_clk;
+		if (clk_tmp) {
+			clk_disable(clk_tmp);
+			clk_unprepare(clk_tmp);
+		}
+
+		clk_tmp = hisifd->dss_pclk_dsi1_clk;
+		if (clk_tmp) {
+			clk_disable(clk_tmp);
+			clk_unprepare(clk_tmp);
+		}
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+ **
+ */
+static int mipi_dsi_on_sub1(struct hisi_fb_data_type *hisifd,
+			    char __iomem *mipi_dsi_base)
+{
+	BUG_ON(mipi_dsi_base == NULL);
+
+	/* mipi init */
+	mipi_init(hisifd, mipi_dsi_base);
+
+	/* switch to cmd mode */
+	set_reg(mipi_dsi_base + MIPIDSI_MODE_CFG_OFFSET, 0x1, 1, 0);
+	/* cmd mode: low power mode */
+	set_reg(mipi_dsi_base + MIPIDSI_CMD_MODE_CFG_OFFSET, 0x7f, 7, 8);
+	set_reg(mipi_dsi_base + MIPIDSI_CMD_MODE_CFG_OFFSET, 0xf, 4, 16);
+	set_reg(mipi_dsi_base + MIPIDSI_CMD_MODE_CFG_OFFSET, 0x1, 1, 24);
+	/* disable generate High Speed clock */
+	/* delete? */
+	set_reg(mipi_dsi_base + MIPIDSI_LPCLK_CTRL_OFFSET, 0x0, 1, 0);
+
+	return 0;
+}
+
+static int mipi_dsi_on_sub2(struct hisi_fb_data_type *hisifd,
+			    char __iomem *mipi_dsi_base)
+{
+	struct hisi_panel_info *pinfo = NULL;
+	uint32_t pctrl_dphytx_stopcnt = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(mipi_dsi_base == NULL);
+
+	pinfo = &(hisifd->panel_info);
+
+	if (is_mipi_video_panel(hisifd)) {
+		/* switch to video mode */
+		set_reg(mipi_dsi_base + MIPIDSI_MODE_CFG_OFFSET, 0x0, 1, 0);
+	}
+
+	if (is_mipi_cmd_panel(hisifd)) {
+		/* cmd mode: high speed mode */
+		set_reg(mipi_dsi_base + MIPIDSI_CMD_MODE_CFG_OFFSET, 0x0, 7, 8);
+		set_reg(mipi_dsi_base + MIPIDSI_CMD_MODE_CFG_OFFSET, 0x0, 4, 16);
+		set_reg(mipi_dsi_base + MIPIDSI_CMD_MODE_CFG_OFFSET, 0x0, 1, 24);
+	}
+
+	/* enable EOTP TX */
+	set_reg(mipi_dsi_base + MIPIDSI_PCKHDL_CFG_OFFSET, 0x1, 1, 0);
+
+	/* enable generate High Speed clock, non continue */
+	if (pinfo->mipi.non_continue_en) {
+		set_reg(mipi_dsi_base + MIPIDSI_LPCLK_CTRL_OFFSET, 0x3, 2, 0);
+	} else {
+		set_reg(mipi_dsi_base + MIPIDSI_LPCLK_CTRL_OFFSET, 0x1, 2, 0);
+	}
+
+	if ((pinfo->mipi.dsi_version == DSI_1_2_VERSION)
+	    && (pinfo->ifbc_type == IFBC_TYPE_VESA3X_SINGLE)) {
+		set_reg(mipi_dsi_base + MIPIDSI_DSC_PARAMETER_OFFSET, 0x01, 32,
+			0);
+	}
+
+	pctrl_dphytx_stopcnt = (uint64_t) (pinfo->ldi.h_back_porch +
+					   pinfo->ldi.h_front_porch +
+					   pinfo->ldi.h_pulse_width +
+					   5) *
+	    hisifd->dss_clk_rate.dss_pclk_pctrl_rate / pinfo->pxl_clk_rate;
+
+	outp32(hisifd->pctrl_base + PERI_CTRL29, pctrl_dphytx_stopcnt);
+	if (is_dual_mipi_panel(hisifd)) {
+		outp32(hisifd->pctrl_base + PERI_CTRL32, pctrl_dphytx_stopcnt);
+	}
+
+	return 0;
+}
+
+int mipi_dsi_off_sub(struct hisi_fb_data_type *hisifd,
+		     char __iomem *mipi_dsi_base)
+{
+	BUG_ON(hisifd == NULL);
+	BUG_ON(mipi_dsi_base == NULL);
+
+	/* switch to cmd mode */
+	set_reg(mipi_dsi_base + MIPIDSI_MODE_CFG_OFFSET, 0x1, 1, 0);
+	/* cmd mode: low power mode */
+	set_reg(mipi_dsi_base + MIPIDSI_CMD_MODE_CFG_OFFSET, 0x7f, 7, 8);
+	set_reg(mipi_dsi_base + MIPIDSI_CMD_MODE_CFG_OFFSET, 0xf, 4, 16);
+	set_reg(mipi_dsi_base + MIPIDSI_CMD_MODE_CFG_OFFSET, 0x1, 1, 24);
+
+	/* disable generate High Speed clock */
+	set_reg(mipi_dsi_base + MIPIDSI_LPCLK_CTRL_OFFSET, 0x0, 1, 0);
+
+	/* shutdown d_phy */
+	set_reg(mipi_dsi_base + MIPIDSI_PHY_RSTZ_OFFSET, 0x0, 3, 0);
+
+	return 0;
+}
+
+static int mipi_dsi_ulps_enter(struct hisi_fb_data_type *hisifd,
+			       char __iomem *mipi_dsi_base)
+{
+	uint32_t tmp = 0;
+	uint32_t cmp_ulpsactivenot_val = 0;
+	uint32_t cmp_stopstate_val = 0;
+	uint32_t try_times = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(mipi_dsi_base == NULL);
+
+	HISI_FB_DEBUG("fb%d, +!\n", hisifd->index);
+
+	if (hisifd->panel_info.mipi.lane_nums >= DSI_4_LANES) {
+		cmp_ulpsactivenot_val = (BIT(5) | BIT(8) | BIT(10) | BIT(12));
+		cmp_stopstate_val = (BIT(4) | BIT(7) | BIT(9) | BIT(11));
+	} else if (hisifd->panel_info.mipi.lane_nums >= DSI_3_LANES) {
+		cmp_ulpsactivenot_val = (BIT(5) | BIT(8) | BIT(10));
+		cmp_stopstate_val = (BIT(4) | BIT(7) | BIT(9));
+	} else if (hisifd->panel_info.mipi.lane_nums >= DSI_2_LANES) {
+		cmp_ulpsactivenot_val = (BIT(5) | BIT(8));
+		cmp_stopstate_val = (BIT(4) | BIT(7));
+	} else {
+		cmp_ulpsactivenot_val = (BIT(5));
+		cmp_stopstate_val = (BIT(4));
+	}
+
+	if (inp32(mipi_dsi_base + MIPIDSI_LPCLK_CTRL_OFFSET) & (BIT(1)))
+		cmp_stopstate_val |= (BIT(2));
+
+	try_times = 0;
+	tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+	while ((tmp & cmp_stopstate_val) != cmp_stopstate_val) {
+		udelay(10);
+		if (++try_times > 100) {
+			HISI_FB_ERR
+			    ("fb%d, check DPHY data and clock lane stopstate failed! MIPIDSI_PHY_STATUS=0x%x.\n",
+			     hisifd->index, tmp);
+			return 0;
+		}
+
+		tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+	}
+
+	if (mipi_dsi_base == hisifd->mipi_dsi0_base) {
+		set_reg(hisifd->pctrl_base + PERI_CTRL23, 0x0, 1, 3);
+	} else {
+		set_reg(hisifd->pctrl_base + PERI_CTRL23, 0x0, 1, 4);
+	}
+	set_reg(mipi_dsi_base + MIPIDSI_LPCLK_CTRL_OFFSET, 0x0, 1, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_PHY_ULPS_CTRL_OFFSET, 0x4, 4, 0);
+
+	try_times = 0;
+	tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+	while ((tmp & cmp_ulpsactivenot_val) != 0) {
+		udelay(10);
+		if (++try_times > 100) {
+			HISI_FB_ERR
+			    ("fb%d, check DPHY data lane ulpsactivenot_status failed! MIPIDSI_PHY_STATUS=0x%x.\n",
+			     hisifd->index, tmp);
+			break;
+		}
+		tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+	}
+	set_reg(mipi_dsi_base + MIPIDSI_PHY_ULPS_CTRL_OFFSET, 0x5, 4, 0);
+
+	try_times = 0;
+	tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+	while ((tmp & BIT(3)) != 0) {
+		udelay(10);
+		if (++try_times > 100) {
+			HISI_FB_ERR
+			    ("fb%d, check DPHY clock lane ulpsactivenot_status failed! MIPIDSI_PHY_STATUS=0x%x.\n",
+			     hisifd->index, tmp);
+			break;
+		}
+		tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+	}
+	outp32(mipi_dsi_base + MIPIDSI_PHY_RSTZ_OFFSET, 0x7);
+
+	try_times = 0;
+	tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+	while ((tmp & BIT(0)) != 0) {
+		udelay(10);
+		if (++try_times > 100) {
+			HISI_FB_ERR
+			    ("fb%d, check DPHY clock lane phy_lock failed! MIPIDSI_PHY_STATUS=0x%x.\n",
+			     hisifd->index, tmp);
+			break;
+		}
+		tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+	}
+
+	set_reg(hisifd->peri_crg_base + PERDIS3, 0x1, 4, 28);
+	HISI_FB_DEBUG("fb%d, -!\n", hisifd->index);
+
+	return 0;
+}
+
+static int mipi_dsi_ulps_exit(struct hisi_fb_data_type *hisifd,
+			      char __iomem *mipi_dsi_base)
+{
+	uint32_t tmp = 0;
+	uint32_t cmp_ulpsactivenot_val = 0;
+	uint32_t try_times = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(mipi_dsi_base == NULL);
+
+	HISI_FB_DEBUG("fb%d, +!\n", hisifd->index);
+
+	set_reg(hisifd->peri_crg_base + PEREN3, 0x1, 4, 28);
+	set_reg(mipi_dsi_base + MIPIDSI_PHY_RSTZ_OFFSET, 0x1, 1, 3);
+
+	try_times = 0;
+	tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+	while ((tmp & BIT(0)) != 1) {
+		udelay(10);
+		if (++try_times > 100) {
+			HISI_FB_ERR
+			    ("fb%d, check DPHY clock lane phy_lock failed! MIPIDSI_PHY_STATUS=0x%x.\n",
+			     hisifd->index, tmp);
+			break;
+		}
+		tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+	}
+
+	if (hisifd->panel_info.mipi.lane_nums >= DSI_4_LANES) {
+		cmp_ulpsactivenot_val =
+		    (BIT(3) | BIT(5) | BIT(8) | BIT(10) | BIT(12));
+	} else if (hisifd->panel_info.mipi.lane_nums >= DSI_3_LANES) {
+		cmp_ulpsactivenot_val = (BIT(3) | BIT(5) | BIT(8) | BIT(10));
+	} else if (hisifd->panel_info.mipi.lane_nums >= DSI_2_LANES) {
+		cmp_ulpsactivenot_val = (BIT(3) | BIT(5) | BIT(8));
+	} else {
+		cmp_ulpsactivenot_val = (BIT(3) | BIT(5));
+	}
+
+	if (mipi_dsi_base == hisifd->mipi_dsi0_base) {
+		set_reg(hisifd->pctrl_base + PERI_CTRL23, 0x1, 1, 3);
+	} else {
+		set_reg(hisifd->pctrl_base + PERI_CTRL23, 0x1, 1, 4);
+	}
+
+	outp32(mipi_dsi_base + MIPIDSI_PHY_ULPS_CTRL_OFFSET, 0xF);
+	try_times = 0;
+	tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+	while ((tmp & cmp_ulpsactivenot_val) != cmp_ulpsactivenot_val) {
+		udelay(10);
+		if (++try_times > 100) {
+			HISI_FB_ERR
+			    ("fb%d, failed to request that data lane and clock lane exit ULPS!MIPIDSI_PHY_STATUS=0x%x.\n",
+			     hisifd->index, tmp);
+			break;
+		}
+		tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+	}
+	mdelay(1);
+	outp32(mipi_dsi_base + MIPIDSI_PHY_ULPS_CTRL_OFFSET, 0x0);
+
+	try_times = 0;
+	tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+	while ((tmp & BIT(0)) != 0x1) {
+		udelay(10);
+		if (++try_times > 100) {
+			HISI_FB_ERR
+			    ("fb%d, failed to wait DPHY PLL Lock!MIPIDSI_PHY_STATUS=0x%x.\n",
+			     hisifd->index, tmp);
+			break;
+		}
+		tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+	}
+
+	set_reg(mipi_dsi_base + MIPIDSI_LPCLK_CTRL_OFFSET, 0x1, 1, 0);
+	HISI_FB_DEBUG("fb%d, -!\n", hisifd->index);
+
+	return 0;
+}
+
+int mipi_dsi_ulps_cfg(struct hisi_fb_data_type *hisifd, int enable)
+{
+	int ret = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	if (enable) {
+		mipi_dsi_ulps_exit(hisifd, hisifd->mipi_dsi0_base);
+		if (is_dual_mipi_panel(hisifd))
+			mipi_dsi_ulps_exit(hisifd, hisifd->mipi_dsi1_base);
+	} else {
+		mipi_dsi_ulps_enter(hisifd, hisifd->mipi_dsi0_base);
+		if (is_dual_mipi_panel(hisifd))
+			mipi_dsi_ulps_enter(hisifd, hisifd->mipi_dsi1_base);
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return ret;
+}
+
+void mipi_dsi_reset(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+	set_reg(hisifd->mipi_dsi0_base + MIPIDSI_PWR_UP_OFFSET, 0x0, 1, 0);
+	msleep(2);
+	set_reg(hisifd->mipi_dsi0_base + MIPIDSI_PWR_UP_OFFSET, 0x1, 1, 0);
+}
+
+/*******************************************************************************
+ **
+ */
+static int mipi_dsi_on(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	/* set LCD init step before LCD on */
+	hisifd->panel_info.lcd_init_step = LCD_INIT_POWER_ON;
+	ret = panel_next_on(pdev);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		if (is_dual_mipi_panel(hisifd))
+			outp32(hisifd->peri_crg_base + PERRSTDIS3, 0x30000000);
+		else
+			outp32(hisifd->peri_crg_base + PERRSTDIS3, 0x10000000);
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		outp32(hisifd->peri_crg_base + PERRSTDIS3, 0x20000000);
+	} else {
+		HISI_FB_ERR("fb%d, not supported!\n", hisifd->index);
+	}
+
+	mipi_dsi_clk_enable(hisifd);
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		mipi_dsi_on_sub1(hisifd, hisifd->mipi_dsi0_base);
+		if (is_dual_mipi_panel(hisifd))
+			mipi_dsi_on_sub1(hisifd, hisifd->mipi_dsi1_base);
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		mipi_dsi_on_sub1(hisifd, hisifd->mipi_dsi1_base);
+	} else {
+		HISI_FB_ERR("fb%d, not supported!\n", hisifd->index);
+	}
+
+	ret = panel_next_on(pdev);
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		mipi_dsi_on_sub2(hisifd, hisifd->mipi_dsi0_base);
+		if (is_dual_mipi_panel(hisifd))
+			mipi_dsi_on_sub2(hisifd, hisifd->mipi_dsi1_base);
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		mipi_dsi_on_sub2(hisifd, hisifd->mipi_dsi1_base);
+	} else {
+		HISI_FB_ERR("fb%d, not supported!\n", hisifd->index);
+	}
+
+	/* mipi hs video/command mode */
+	ret = panel_next_on(pdev);
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return ret;
+}
+
+static int mipi_dsi_off(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	/* set LCD uninit step before LCD off */
+	hisifd->panel_info.lcd_uninit_step = LCD_UNINIT_MIPI_HS_SEND_SEQUENCE;
+	ret = panel_next_off(pdev);
+
+	if (hisifd->panel_info.lcd_uninit_step_support) {
+		/* TODO: add MIPI LP mode here if necessary */
+		/* MIPI LP mode end */
+		ret = panel_next_off(pdev);
+	}
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		mipi_dsi_off_sub(hisifd, hisifd->mipi_dsi0_base);
+		if (is_dual_mipi_panel(hisifd))
+			mipi_dsi_off_sub(hisifd, hisifd->mipi_dsi1_base);
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		mipi_dsi_off_sub(hisifd, hisifd->mipi_dsi1_base);
+	} else {
+		HISI_FB_ERR("fb%d, not supported!\n", hisifd->index);
+	}
+
+	mipi_dsi_clk_disable(hisifd);
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		if (is_dual_mipi_panel(hisifd))
+			outp32(hisifd->peri_crg_base + PERRSTEN3, 0x30000000);
+		else
+			outp32(hisifd->peri_crg_base + PERRSTEN3, 0x10000000);
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		outp32(hisifd->peri_crg_base + PERRSTEN3, 0x20000000);
+	} else {
+		HISI_FB_ERR("fb%d, not supported!\n", hisifd->index);
+	}
+
+	if (hisifd->panel_info.lcd_uninit_step_support) {
+		ret = panel_next_off(pdev);
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return ret;
+}
+
+static int mipi_dsi_remove(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	ret = panel_next_remove(pdev);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		if (hisifd->dss_dphy0_ref_clk) {
+			clk_put(hisifd->dss_dphy0_ref_clk);
+			hisifd->dss_dphy0_ref_clk = NULL;
+		}
+
+		if (hisifd->dss_dphy0_cfg_clk) {
+			clk_put(hisifd->dss_dphy0_cfg_clk);
+			hisifd->dss_dphy0_cfg_clk = NULL;
+		}
+
+		if (is_dual_mipi_panel(hisifd)) {
+			if (hisifd->dss_dphy1_ref_clk) {
+				clk_put(hisifd->dss_dphy1_ref_clk);
+				hisifd->dss_dphy1_ref_clk = NULL;
+			}
+
+			if (hisifd->dss_dphy1_cfg_clk) {
+				clk_put(hisifd->dss_dphy1_cfg_clk);
+				hisifd->dss_dphy1_cfg_clk = NULL;
+			}
+		}
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		if (hisifd->dss_dphy1_ref_clk) {
+			clk_put(hisifd->dss_dphy1_ref_clk);
+			hisifd->dss_dphy1_ref_clk = NULL;
+		}
+
+		if (hisifd->dss_dphy1_cfg_clk) {
+			clk_put(hisifd->dss_dphy1_cfg_clk);
+			hisifd->dss_dphy1_cfg_clk = NULL;
+		}
+	} else {
+		HISI_FB_ERR("fb%d, not supported!\n", hisifd->index);
+	}
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return ret;
+}
+
+static int mipi_dsi_set_backlight(struct platform_device *pdev,
+				  uint32_t bl_level)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	ret = panel_next_set_backlight(pdev, bl_level);
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return ret;
+}
+
+static int mipi_dsi_vsync_ctrl(struct platform_device *pdev, int enable)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	ret = panel_next_vsync_ctrl(pdev, enable);
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return ret;
+}
+
+static int mipi_dsi_clk_irq_setup(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	int ret = 0;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		ret =
+		    clk_set_rate(hisifd->dss_dphy0_ref_clk,
+				 DEFAULT_MIPI_CLK_RATE);
+		if (ret < 0) {
+			HISI_FB_ERR
+			    ("fb%d dss_dphy0_ref_clk clk_set_rate(%lu) failed, error=%d!\n",
+			     hisifd->index, DEFAULT_MIPI_CLK_RATE, ret);
+			return -EINVAL;
+		}
+		HISI_FB_INFO("dss_dphy0_ref_clk:[%lu]->[%lu].\n",
+			     DEFAULT_MIPI_CLK_RATE,
+			     clk_get_rate(hisifd->dss_dphy0_ref_clk));
+
+		ret =
+		    clk_set_rate(hisifd->dss_dphy0_cfg_clk,
+				 DEFAULT_MIPI_CLK_RATE);
+		if (ret < 0) {
+			HISI_FB_ERR
+			    ("fb%d dss_dphy0_cfg_clk clk_set_rate(%lu) failed, error=%d!\n",
+			     hisifd->index, DEFAULT_MIPI_CLK_RATE, ret);
+			return -EINVAL;
+		}
+		HISI_FB_INFO("dss_dphy0_cfg_clk:[%lu]->[%lu].\n",
+			     DEFAULT_MIPI_CLK_RATE,
+			     clk_get_rate(hisifd->dss_dphy0_cfg_clk));
+		HISI_FB_INFO("dss_pclk_dsi0_clk:[%lu]->[%lu].\n",
+			     DEFAULT_PCLK_DSI_RATE,
+			     clk_get_rate(hisifd->dss_pclk_dsi0_clk));
+	}
+#ifdef CONFIG_PCLK_PCTRL_USED
+	ret = clk_set_rate(hisifd->dss_pclk_pctrl_clk, DEFAULT_PCLK_PCTRL_RATE);
+	if (ret < 0) {
+		HISI_FB_ERR
+		    ("fb%d dss_pclk_pctrl clk_set_rate(%lu) failed, error=%d!\n",
+		     hisifd->index, DEFAULT_PCLK_PCTRL_RATE, ret);
+		return -EINVAL;
+	}
+	HISI_FB_INFO("dss_pclk_pctrl_clk:[%lu]->[%lu].\n",
+		     DEFAULT_PCLK_PCTRL_RATE,
+		     clk_get_rate(hisifd->dss_pclk_pctrl_clk));
+#endif
+
+	if (is_dual_mipi_panel(hisifd) || (hisifd->index == EXTERNAL_PANEL_IDX)) {
+		ret =
+		    clk_set_rate(hisifd->dss_dphy1_ref_clk,
+				 DEFAULT_MIPI_CLK_RATE);
+		if (ret < 0) {
+			HISI_FB_ERR
+			    ("fb%d dss_dphy1_ref_clk clk_set_rate(%lu) failed, error=%d!\n",
+			     hisifd->index, DEFAULT_MIPI_CLK_RATE, ret);
+			return -EINVAL;
+		}
+		HISI_FB_INFO("dss_dphy1_ref_clk:[%lu]->[%lu].\n",
+			     DEFAULT_MIPI_CLK_RATE,
+			     clk_get_rate(hisifd->dss_dphy1_ref_clk));
+
+		ret =
+		    clk_set_rate(hisifd->dss_dphy1_cfg_clk,
+				 DEFAULT_MIPI_CLK_RATE);
+		if (ret < 0) {
+			HISI_FB_ERR
+			    ("fb%d dss_dphy1_cfg_clk clk_set_rate(%lu) failed, "
+			     "error=%d!\n",
+			     hisifd->index, DEFAULT_MIPI_CLK_RATE, ret);
+			return -EINVAL;
+		}
+		HISI_FB_INFO("dss_dphy1_cfg_clk:[%lu]->[%lu].\n",
+			     DEFAULT_MIPI_CLK_RATE,
+			     clk_get_rate(hisifd->dss_dphy1_cfg_clk));
+		HISI_FB_INFO("dss_pclk_dsi1_clk:[%lu]->[%lu].\n",
+			     DEFAULT_PCLK_DSI_RATE,
+			     clk_get_rate(hisifd->dss_pclk_dsi1_clk));
+	}
+
+	return ret;
+}
+
+static int mipi_dsi_probe(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct platform_device *dpp_dev = NULL;
+	struct hisi_fb_panel_data *pdata = NULL;
+	int ret = 0;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	ret = mipi_dsi_clk_irq_setup(pdev);
+	if (ret) {
+		HISI_FB_ERR("fb%d mipi_dsi_irq_clk_setup failed, error=%d!\n",
+			    hisifd->index, ret);
+		goto err;
+	}
+	/* alloc device */
+	dpp_dev = platform_device_alloc(DEV_NAME_DSS_DPE, pdev->id);
+	if (!dpp_dev) {
+		HISI_FB_ERR("fb%d platform_device_alloc failed, error=%d!\n",
+			    hisifd->index, ret);
+		ret = -ENOMEM;
+		goto err_device_alloc;
+	}
+	/* link to the latest pdev */
+	hisifd->pdev = dpp_dev;
+
+	/* alloc panel device data */
+	ret = platform_device_add_data(dpp_dev, dev_get_platdata(&pdev->dev),
+				       sizeof(struct hisi_fb_panel_data));
+	if (ret) {
+		HISI_FB_ERR("fb%d platform_device_add_data failed error=%d!\n",
+			    hisifd->index, ret);
+		goto err_device_put;
+	}
+
+	/* data chain */
+	pdata = dev_get_platdata(&dpp_dev->dev);
+	pdata->on = mipi_dsi_on;
+	pdata->off = mipi_dsi_off;
+	pdata->remove = mipi_dsi_remove;
+	pdata->set_backlight = mipi_dsi_set_backlight;
+	pdata->vsync_ctrl = mipi_dsi_vsync_ctrl;
+	pdata->next = pdev;
+
+	/* get/set panel info */
+	memcpy(&hisifd->panel_info, pdata->panel_info,
+	       sizeof(struct hisi_panel_info));
+
+	/* set driver data */
+	platform_set_drvdata(dpp_dev, hisifd);
+	/* device add */
+	ret = platform_device_add(dpp_dev);
+	if (ret) {
+		HISI_FB_ERR("fb%d platform_device_add failed, error=%d!\n",
+			    hisifd->index, ret);
+		goto err_device_put;
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+
+	return 0;
+
+ err_device_put:
+	platform_device_put(dpp_dev);
+ err_device_alloc:
+ err:
+	return ret;
+}
+
+static struct platform_driver this_driver = {
+	.probe = mipi_dsi_probe,
+	.remove = NULL,
+	.suspend = NULL,
+	.resume = NULL,
+	.shutdown = NULL,
+	.driver = {
+		   .name = DEV_NAME_MIPIDSI,
+		   },
+};
+
+static int __init mipi_dsi_driver_init(void)
+{
+	int ret = 0;
+
+	ret = platform_driver_register(&this_driver);
+	if (ret) {
+		HISI_FB_ERR("platform_driver_register failed, error=%d!\n",
+			    ret);
+		return ret;
+	}
+	return ret;
+}
+
+module_init(mipi_dsi_driver_init);
diff --git a/drivers/video/fbdev/hisi/dss/hisi_mipi_dsi.h b/drivers/video/fbdev/hisi/dss/hisi_mipi_dsi.h
new file mode 100755
index 000000000000..06fd0d3a22ed
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_mipi_dsi.h
@@ -0,0 +1,152 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+#ifndef HISI_MIPI_DSI_H
+#define HISI_MIPI_DSI_H
+
+#include "hisi_fb.h"
+
+/* mipi dsi panel */
+enum {
+	DSI_VIDEO_MODE,
+	DSI_CMD_MODE,
+};
+
+enum {
+	DSI_1_1_VERSION = 0,
+	DSI_1_2_VERSION,
+};
+
+enum {
+	DSI_1_LANES = 0,
+	DSI_2_LANES,
+	DSI_3_LANES,
+	DSI_4_LANES,
+};
+
+enum {
+	DSI_LANE_NUMS_DEFAULT = 0,
+	DSI_1_LANES_SUPPORT = BIT(0),
+	DSI_2_LANES_SUPPORT = BIT(1),
+	DSI_3_LANES_SUPPORT = BIT(2),
+	DSI_4_LANES_SUPPORT = BIT(3),
+};
+
+enum {
+	DSI_16BITS_1 = 0,
+	DSI_16BITS_2,
+	DSI_16BITS_3,
+	DSI_18BITS_1,
+	DSI_18BITS_2,
+	DSI_24BITS_1,
+	DSI_24BITS_2,
+	DSI_24BITS_3,
+	DSI_DSC24_COMPRESSED_DATA = 0xF,
+};
+
+enum {
+	DSI_NON_BURST_SYNC_PULSES = 0,
+	DSI_NON_BURST_SYNC_EVENTS,
+	DSI_BURST_SYNC_PULSES_1,
+	DSI_BURST_SYNC_PULSES_2,
+};
+
+#define DSI_VIDEO_DST_FORMAT_RGB565			0
+#define DSI_VIDEO_DST_FORMAT_RGB666			1
+#define DSI_VIDEO_DST_FORMAT_RGB666_LOOSE	2
+#define DSI_VIDEO_DST_FORMAT_RGB888			3
+
+#define DSI_CMD_DST_FORMAT_RGB565	0
+#define DSI_CMD_DST_FORMAT_RGB666	1
+#define DSI_CMD_DST_FORMAT_RGB888	2
+
+/* dcs read/write */
+#define DTYPE_DCS_WRITE		0x05	/* short write, 0 parameter */
+#define DTYPE_DCS_WRITE1	0x15	/* short write, 1 parameter */
+#define DTYPE_DCS_READ		0x06	/* read */
+#define DTYPE_DCS_LWRITE	0x39	/* long write */
+#define DTYPE_DSC_LWRITE	0x0A	/* dsc dsi1.2 vase3x long write */
+
+/* generic read/write */
+#define DTYPE_GEN_WRITE		0x03	/* short write, 0 parameter */
+#define DTYPE_GEN_WRITE1	0x13	/* short write, 1 parameter */
+#define DTYPE_GEN_WRITE2	0x23	/* short write, 2 parameter */
+#define DTYPE_GEN_LWRITE	0x29	/* long write */
+#define DTYPE_GEN_READ		0x04	/* long read, 0 parameter */
+#define DTYPE_GEN_READ1		0x14	/* long read, 1 parameter */
+#define DTYPE_GEN_READ2		0x24	/* long read, 2 parameter */
+
+#define DTYPE_TEAR_ON		0x35	/* set tear on */
+#define DTYPE_MAX_PKTSIZE	0x37	/* set max packet size */
+#define DTYPE_NULL_PKT		0x09	/* null packet, no data */
+#define DTYPE_BLANK_PKT		0x19	/* blankiing packet, no data */
+
+#define DTYPE_CM_ON				0x02	/* color mode off */
+#define DTYPE_CM_OFF			0x12	/* color mode on */
+#define DTYPE_PERIPHERAL_OFF	0x22
+#define DTYPE_PERIPHERAL_ON		0x32
+
+#define DSI_HDR_DTYPE(dtype)	((dtype) & 0x03f)
+#define DSI_HDR_VC(vc)			(((vc) & 0x03) << 6)
+#define DSI_HDR_DATA1(data)		(((data) & 0x0ff) << 8)
+#define DSI_HDR_DATA2(data)		(((data) & 0x0ff) << 16)
+#define DSI_HDR_WC(wc)			(((wc) & 0x0ffff) << 8)
+
+#define DSI_PLD_DATA1(data)		((data) & 0x0ff)
+#define DSI_PLD_DATA2(data)		(((data) & 0x0ff) << 8)
+#define DSI_PLD_DATA3(data)		(((data) & 0x0ff) << 16)
+#define DSI_PLD_DATA4(data)		(((data) & 0x0ff) << 24)
+
+struct dsi_cmd_desc {
+	int dtype;
+	int vc;
+	int wait;
+	int waittype;
+	int dlen;
+	char *payload;
+};
+
+struct mipi_dsi_read_compare_data {
+	uint32_t *read_value;
+	uint32_t *expected_value;
+	uint32_t *read_mask;
+	char **reg_name;
+	int log_on;
+	struct dsi_cmd_desc *cmds;
+	int cnt;
+};
+
+/******************************************************************************
+ ** FUNCTIONS PROTOTYPES
+ */
+void mipi_dsi_max_return_packet_size(struct dsi_cmd_desc *cm,
+				     char __iomem *dsi_base);
+void mipi_dsi_sread(uint32_t *out, char __iomem *dsi_base);
+void mipi_dsi_lread(uint32_t *out, char __iomem *dsi_base);
+uint32_t mipi_dsi_read(uint32_t *out, char __iomem *dsi_base);
+int mipi_dsi_swrite(struct dsi_cmd_desc *cm, char __iomem *dsi_base);
+int mipi_dsi_lwrite(struct dsi_cmd_desc *cm, char __iomem *dsi_base);
+void mipi_dsi_check_0lane_is_ready(char __iomem *dsi_base);
+int mipi_dsi_cmds_tx(struct dsi_cmd_desc *cmds, int cnt,
+		     char __iomem *dsi_base);
+int mipi_dsi_cmds_rx(uint32_t *out, struct dsi_cmd_desc *cmds, int cnt,
+		     char __iomem *dsi_base);
+
+int mipi_dsi_read_compare(struct mipi_dsi_read_compare_data *data,
+			  char __iomem *dsi_base);
+
+struct hisi_fb_data_type;
+int mipi_dsi_clk_enable(struct hisi_fb_data_type *hisifd);
+int mipi_dsi_clk_disable(struct hisi_fb_data_type *hisifd);
+void mipi_dsi_reset(struct hisi_fb_data_type *hisifd);
+
+#endif				/* HISI_MIPI_DSI_H */
-- 
2.12.0-rc0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/8] fb: hisilicon: Add framebuffer driver for hi3660 SoC
  2017-02-07  2:35   ` cailiwei
                     ` (2 preceding siblings ...)
  (?)
@ 2017-02-07  2:35   ` cailiwei
  -1 siblings, 0 replies; 15+ messages in thread
From: cailiwei @ 2017-02-07  2:35 UTC (permalink / raw)
  To: linux-fbdev, linux-kernel, b.zolnierkie, guodong.xu
  Cc: suzhuangluan, dengqingshan, xuhongtao8, zhengwanchun,
	shizongxuan, cailiwei

From: Levy-Cai <cailiwei@hisilicon.com>

Add framebuffer driver for hi3660 SoC, this driver include lcd
driver & Hdmi adv7533/adv7535 driver, support lcd display at
1080p@60 and hdmi display at 1080p@60.

Signed-off-by: cailiwei <cailiwei@hisilicon.com>
---
 .../video/fbdev/hisi/dss/hisi_block_algorithm.c    |  714 +++++
 .../video/fbdev/hisi/dss/hisi_block_algorithm.h    |   29 +
 .../video/fbdev/hisi/dss/hisi_dpe_utils_hi3660.c   | 1549 ++++++++++
 drivers/video/fbdev/hisi/dss/hisi_dss.h            |  493 +++
 .../video/fbdev/hisi/dss/hisi_dss_regs_hi3660.h    | 3164 ++++++++++++++++++++
 5 files changed, 5949 insertions(+)
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_block_algorithm.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_block_algorithm.h
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_dpe_utils_hi3660.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_dss.h
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_dss_regs_hi3660.h

diff --git a/drivers/video/fbdev/hisi/dss/hisi_block_algorithm.c b/drivers/video/fbdev/hisi/dss/hisi_block_algorithm.c
new file mode 100755
index 000000000000..28dcfbd1fe13
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_block_algorithm.c
@@ -0,0 +1,714 @@
+/*
+ * Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_fb.h"
+#include "hisi_block_algorithm.h"
+#include "hisi_overlay_utils.h"
+
+#define SCF_INPUT_OV  (16)
+
+#define WDMA_ROT_LINEBUF	(480)
+#define AFBCE_LINEBUF	(480)
+
+#define RCHN_V2_SCF_LINE_BUF (512)
+#define SHARPNESS_LINE_BUF	(2560)
+
+#define MAX_OFFLINE_SCF 4
+#define MAX_OFFLINE_LAYER_NUMBER 6
+#define BLOCK_SIZE_INVALID	(0xFFFF)
+
+int rect_across_rect(dss_rect_t rect1, dss_rect_t rect2,
+		     dss_rect_t *cross_rect)
+{
+	uint32_t center_x = 0;
+	uint32_t center_y = 0;
+
+	BUG_ON(cross_rect == NULL);
+
+	memset(cross_rect, 0x0, sizeof(dss_rect_t));
+
+	if (rect1.w == 0 || rect1.h == 0 || rect2.w == 0 || rect2.h == 0)
+		return 0;
+
+	center_x =
+	    abs(rect2.x + rect2.w - 1 + rect2.x -
+		(rect1.x + rect1.w - 1 + rect1.x));
+	center_y =
+	    abs(rect2.y + rect2.h - 1 + rect2.y -
+		(rect1.y + rect1.h - 1 + rect1.y));
+
+	if ((center_x < rect2.w + rect1.w) && (center_y < rect2.h + rect1.h)) {
+
+		cross_rect->x = MAX(rect1.x, rect2.x);
+		cross_rect->y = MAX(rect1.y, rect2.y);
+		cross_rect->w =
+		    MIN(rect1.x + rect1.w - 1,
+			rect2.x + rect2.w - 1) - cross_rect->x + 1;
+		cross_rect->h =
+		    MIN(rect1.y + rect1.h - 1,
+			rect2.y + rect2.h - 1) - cross_rect->y + 1;
+
+		return 1;
+	}
+
+	return 0;
+}
+
+uint32_t calc_dest_block_size(dss_overlay_t *pov_req,
+			      dss_overlay_block_t *pov_h_block)
+{
+	uint32_t i = 0;
+	uint32_t block_width = BLOCK_SIZE_INVALID;
+	int32_t scf_line_buffer = SCF_LINE_BUF;
+	dss_layer_t *layer = NULL;
+	dss_wb_layer_t *wb_layer = NULL;
+
+	BUG_ON(pov_req == NULL);
+	BUG_ON(pov_h_block == NULL);
+
+	for (i = 0; i < pov_h_block->layer_nums; i++) {
+		layer = &(pov_h_block->layer_infos[i]);
+
+		if (layer->need_cap & (CAP_DIM | CAP_BASE))
+			continue;
+
+		/* sharpenss line buffer is 1600 for austin and dallas, but 2560 for chicago */
+		if ((layer->need_cap & CAP_2D_SHARPNESS) &&
+		    (layer->src_rect.w > SHARPNESS_LINE_BUF)) {
+			block_width = MIN(block_width, SHARPNESS_LINE_BUF);
+		}
+
+		/* scaler line buffer, default value is 2560, but line buffer of rchn_v2 is 512,
+		   scaler line buffer should be subtracted by 32 according to scale algorithm */
+		if (layer->chn_idx == DSS_RCHN_V2) {
+			scf_line_buffer = RCHN_V2_SCF_LINE_BUF;
+		} else {
+			scf_line_buffer = SCF_LINE_BUF;
+		}
+
+		scf_line_buffer = scf_line_buffer - 32;
+
+		if (layer->src_rect.h != layer->dst_rect.h) {
+			if (((layer->src_rect.w >= layer->dst_rect.w)
+			     && (layer->dst_rect.w > scf_line_buffer))
+			    || ((layer->src_rect.w < layer->dst_rect.w)
+				&& (layer->src_rect.w > scf_line_buffer))) {
+				block_width = MIN(block_width, scf_line_buffer);
+			}
+		}
+	}
+
+	for (i = 0; i < pov_req->wb_layer_nums; i++) {
+		wb_layer = &(pov_req->wb_layer_infos[i]);
+
+		/* maximum of rot linebuffer is 480 */
+		if (wb_layer->transform & HISI_FB_TRANSFORM_ROT_90) {
+			block_width = MIN(block_width, WDMA_ROT_LINEBUF);
+		}
+
+		/* maximum of afbce linebuffer is 480 */
+		if (wb_layer->need_cap & CAP_AFBCE) {
+			block_width = MIN(block_width, AFBCE_LINEBUF);
+		}
+	}
+
+	return block_width;
+}
+
+int scf_output_suitable(uint32_t x_start, uint32_t x_end, uint32_t pos)
+{
+	if ((x_start > pos) || (x_end < pos))
+		return 0;
+
+	/* if distance between layer start/end and pos, return 1 for adjust */
+	if ((pos - x_start < SCF_MIN_OUTPUT)
+	    || (x_end - pos + 1 < SCF_MIN_OUTPUT))
+		return 1;
+
+	return 0;
+}
+
+int block_fix_scf_constraint(dss_overlay_t *pov_req,
+			     dss_overlay_block_t *pov_h_block,
+			     uint32_t block_size, uint32_t end_pos,
+			     uint32_t *fix_size)
+{
+	uint32_t i = 0;
+	uint32_t end = end_pos;
+	uint32_t scf_layer_num = 0;
+
+	dss_rect_t scf_dst_rect[MAX_OFFLINE_LAYER_NUMBER];
+	dss_layer_t *layer = NULL;
+
+	BUG_ON(pov_h_block == NULL);
+	BUG_ON(fix_size == NULL);
+
+	*fix_size = block_size;
+
+	if (block_size <= SCF_MIN_OUTPUT) {
+		HISI_FB_ERR("block size[%d] is too small!\n", block_size);
+		return -1;
+	}
+
+	for (i = 0; i < pov_h_block->layer_nums; i++) {
+		layer = &(pov_h_block->layer_infos[i]);
+
+		if (layer->need_cap & (CAP_BASE | CAP_DIM | CAP_PURE_COLOR)) {
+			continue;
+		}
+
+		if (scf_layer_num >= MAX_OFFLINE_LAYER_NUMBER) {
+			HISI_FB_ERR
+			    ("layer number in offline [%d] is more than scf moudle [%d]\n",
+			     scf_layer_num, MAX_OFFLINE_LAYER_NUMBER);
+			return -1;
+		}
+
+		/* get all scaler layers for austin and dallas */
+		/* get all layers for chicago */
+		scf_dst_rect[scf_layer_num].x = layer->dst_rect.x;
+		scf_dst_rect[scf_layer_num].y = layer->dst_rect.y;
+		scf_dst_rect[scf_layer_num].w = layer->dst_rect.w;
+		scf_dst_rect[scf_layer_num].h = layer->dst_rect.h;
+		scf_layer_num++;
+	}
+
+	if (scf_layer_num == 0)
+		return 0;
+
+ REDO:
+	for (i = 0; i < scf_layer_num; i++) {
+		if (scf_output_suitable(scf_dst_rect[i].x,
+					scf_dst_rect[i].x + scf_dst_rect[i].w -
+					1, pov_req->wb_ov_rect.x + end)) {
+			end = end - SCF_MIN_OUTPUT;
+			goto REDO;
+		}
+	}
+
+	*fix_size = block_size - (end_pos - end);
+	return 0;
+}
+
+int adjust_layers_cap(dss_overlay_t *pov_req,
+		      dss_overlay_block_t *pov_h_block,
+		      dss_wb_layer_t *wb_layer)
+{
+	int i = 0;
+	int temp = 0;
+	dss_layer_t *layer = NULL;
+	bool has_rot = false;
+
+	BUG_ON(pov_h_block == NULL);
+	BUG_ON(wb_layer == NULL);
+
+	for (i = 0; i < pov_h_block->layer_nums; i++) {
+		layer = &pov_h_block->layer_infos[i];
+
+		if (layer->transform & HISI_FB_TRANSFORM_ROT_90) {
+			temp = layer->dst_rect.x;
+			layer->dst_rect.x =
+			    pov_req->wb_ov_rect.x + (layer->dst_rect.y -
+						     pov_req->wb_ov_rect.y);
+			layer->dst_rect.y =
+			    pov_req->wb_ov_rect.y + temp -
+			    pov_req->wb_ov_rect.x;
+
+			temp = layer->dst_rect.w;
+			layer->dst_rect.w = layer->dst_rect.h;
+			layer->dst_rect.h = temp;
+
+			if (layer->transform == HISI_FB_TRANSFORM_ROT_90) {
+				layer->transform = HISI_FB_TRANSFORM_FLIP_V;
+
+			} else if (layer->transform ==
+				   HISI_FB_TRANSFORM_ROT_270) {
+				layer->transform = HISI_FB_TRANSFORM_FLIP_H;
+
+			} else if (layer->transform ==
+				   (HISI_FB_TRANSFORM_ROT_90 |
+				    HISI_FB_TRANSFORM_FLIP_H)) {
+				layer->transform = HISI_FB_TRANSFORM_ROT_180;
+
+			} else if (layer->transform ==
+				   (HISI_FB_TRANSFORM_ROT_90 |
+				    HISI_FB_TRANSFORM_FLIP_V)) {
+				layer->transform = HISI_FB_TRANSFORM_NOP;
+
+			} else {
+				;
+			}
+
+			has_rot = true;
+		}
+	}
+
+
+	if (has_rot) {
+		for (i = 0; i < pov_req->wb_layer_nums; i++) {
+			wb_layer = &(pov_req->wb_layer_infos[i]);
+			temp = wb_layer->src_rect.w;
+			wb_layer->src_rect.w = wb_layer->src_rect.h;
+			wb_layer->src_rect.h = temp;
+
+			wb_layer->transform =
+			    (HISI_FB_TRANSFORM_ROT_90 |
+			     HISI_FB_TRANSFORM_FLIP_V);
+		}
+	}
+
+	return 0;
+}
+
+int get_ov_block_rect(dss_overlay_t *pov_req,
+		      dss_overlay_block_t *pov_h_block,
+		      dss_wb_layer_t *wb_layer, int *block_num,
+		      dss_rect_t *ov_block_rects[])
+{
+	int ret = 0;
+	uint32_t block_size = 0xFFFF;
+	uint32_t current_offset = 0;
+	uint32_t last_offset = 0;
+	uint32_t fix_scf_span = 0;
+	dss_layer_t *layer = NULL;
+	uint32_t i = 0;
+	int block_has_layer = 0;
+	int w = 0;
+	int h = 0;
+
+	BUG_ON(pov_req == NULL);
+	BUG_ON(pov_h_block == NULL);
+	BUG_ON(ov_block_rects == NULL);
+	BUG_ON(block_num == NULL);
+	BUG_ON(wb_layer == NULL);
+
+	*block_num = 0;
+
+	/* adjust layer transform cap, source layer dst_rect and writeback layer src_rect */
+	adjust_layers_cap(pov_req, pov_h_block, wb_layer);
+	w = wb_layer->src_rect.w;
+	h = wb_layer->src_rect.h;
+
+	/* init block size according to source layer dst_rect */
+	block_size = calc_dest_block_size(pov_req, pov_h_block);
+
+	/* if block size is invalid or larger than write back width, block is not needed.
+	   Then block num is set to 1, and block rect is set to write back layer rect */
+	if ((block_size == BLOCK_SIZE_INVALID) || (block_size >= w)) {
+		ov_block_rects[*block_num]->x = wb_layer->src_rect.x;
+		ov_block_rects[*block_num]->y = wb_layer->src_rect.y;
+		ov_block_rects[*block_num]->w = wb_layer->src_rect.w;
+		ov_block_rects[*block_num]->h = wb_layer->src_rect.h;
+
+		*block_num = 1;
+		return ret;
+	}
+
+	current_offset = block_size;
+	fix_scf_span = block_size;
+
+	for (current_offset = block_size; last_offset < w;
+	     last_offset = current_offset, current_offset += block_size) {
+		/* make sure each block of scaler layer is larger than 16 */
+		if (block_fix_scf_constraint
+		    (pov_req, pov_h_block, block_size, current_offset,
+		     &fix_scf_span) != 0) {
+			HISI_FB_ERR("block_fix_scf_constraint err!\n");
+			return -3;
+		}
+
+		/* recalculate the block size, the final value */
+		current_offset = current_offset - (block_size - fix_scf_span);
+		block_has_layer = 0;
+
+		for (i = 0; i < pov_h_block->layer_nums; i++) {
+			layer = &(pov_h_block->layer_infos[i]);
+
+			if (((last_offset + pov_req->wb_ov_rect.x) <=
+			     (layer->dst_rect.x + layer->dst_rect.w - 1))
+			    && (layer->dst_rect.x <
+				(current_offset + pov_req->wb_ov_rect.x))) {
+				block_has_layer = 1;
+				if ((*block_num) >= HISI_DSS_OFFLINE_MAX_BLOCK)
+					return -5;
+
+				/* get the block rectangles */
+				ov_block_rects[*block_num]->x =
+				    wb_layer->src_rect.x + last_offset;
+				ov_block_rects[*block_num]->y =
+				    wb_layer->src_rect.y;
+				ov_block_rects[*block_num]->w =
+				    MIN(current_offset - last_offset,
+					w - last_offset);
+				ov_block_rects[*block_num]->h = h;
+
+				(*block_num)++;
+				break;
+			}
+		}
+
+		if (block_has_layer == 0) {
+			if ((*block_num) >= HISI_DSS_OFFLINE_MAX_BLOCK)
+				return -6;
+
+			ov_block_rects[*block_num]->x =
+			    wb_layer->src_rect.x + last_offset;
+			ov_block_rects[*block_num]->y = wb_layer->src_rect.y;
+			ov_block_rects[*block_num]->w =
+			    MIN(current_offset - last_offset, w - last_offset);
+			ov_block_rects[*block_num]->h = h;
+
+			(*block_num)++;
+		}
+
+		if (g_debug_ovl_block_composer) {
+			HISI_FB_INFO
+			    ("ov_block_rects[%d]:[%d:%d:%d:%d], current_offset=%d, "
+			     "fix_scf_span=%d, last_offset=%d, w=%d!\n",
+			     *block_num, ov_block_rects[*block_num - 1]->x,
+			     ov_block_rects[*block_num - 1]->y,
+			     ov_block_rects[*block_num - 1]->w,
+			     ov_block_rects[*block_num - 1]->h, current_offset,
+			     fix_scf_span, last_offset, w);
+		}
+	}
+
+	hisifb_adjust_block_rect(*block_num, ov_block_rects, wb_layer);
+
+	return ret;
+}
+
+static int create_h_v_block_layer(dss_layer_t *h_layer,
+				  dss_layer_t *h_v_layer,
+				  dss_rect_t dst_cross_rect,
+				  dss_rect_t ov_block_rect)
+{
+	int input_startpos = 0;
+	int input_span = 0;
+	uint32_t output_startpos = 0;
+	uint32_t output_span = 0;
+	int h_ratio = 0;
+	int acc_hscl = 0;
+	int scf_read_start = 0;
+	int scf_read_end = 0;
+	dss_rect_t rect_transform = { 0 };
+	dss_rect_t src_rect = { 0 };
+	int scf_int = 0;
+	int scf_rem = 0;
+
+	dss_rect_t dst_rect = { 0 };
+	int first_block = 0;
+	int last_block = 0;
+	int scf_in_start = 0;
+	int scf_in_end = 0;
+
+	BUG_ON(h_layer == NULL);
+	BUG_ON(h_v_layer == NULL);
+
+	first_block = (h_layer->dst_rect.x >= ov_block_rect.x) ? 1 : 0;
+	last_block =
+	    ((ov_block_rect.x + ov_block_rect.w) >=
+	     (h_layer->dst_rect.x + h_layer->dst_rect.w)) ? 1 : 0;
+
+	output_startpos = dst_cross_rect.x - h_layer->dst_rect.x;
+	output_span = dst_cross_rect.w;
+	input_startpos = output_startpos;
+	input_span = output_span;
+
+	/* handle arsr2p layer */
+#define ARSR2P_OVERLAPH 16
+
+	if (h_layer->chn_idx == DSS_RCHN_V0
+	    && (h_layer->src_rect.w < h_layer->dst_rect.w
+		|| h_layer->src_rect.h != h_layer->dst_rect.h
+		|| (h_layer->need_cap & CAP_2D_SHARPNESS))) {
+
+		if ((!first_block) && (output_startpos % 2)) {
+			h_v_layer->block_info.arsr2p_left_clip = 1;
+			dst_cross_rect.x =
+			    dst_cross_rect.x -
+			    h_v_layer->block_info.arsr2p_left_clip;
+			dst_cross_rect.w =
+			    dst_cross_rect.w +
+			    h_v_layer->block_info.arsr2p_left_clip;
+
+			output_startpos =
+			    output_startpos -
+			    h_v_layer->block_info.arsr2p_left_clip;
+			output_span = dst_cross_rect.w;
+			input_startpos = output_startpos;
+			input_span = output_span;
+		}
+
+		if (h_layer->src_rect.w > h_layer->dst_rect.w) {
+			src_rect.x = h_layer->src_rect.x;
+			src_rect.y = h_layer->src_rect.y;
+			src_rect.w = h_layer->dst_rect.w;
+			src_rect.h = h_layer->src_rect.h;
+		} else {
+			src_rect = h_layer->src_rect;
+		}
+
+		h_ratio =
+		    (DSS_WIDTH(src_rect.w) * ARSR2P_INC_FACTOR +
+		     ARSR2P_INC_FACTOR - acc_hscl) / h_layer->dst_rect.w;
+
+		scf_int = output_startpos * h_ratio / ARSR2P_INC_FACTOR;
+		scf_rem = output_startpos * h_ratio % ARSR2P_INC_FACTOR;
+		scf_in_start = (scf_rem > 0) ? (scf_int + 1) : scf_int;
+
+		scf_int =
+		    (output_startpos +
+		     output_span) * h_ratio / ARSR2P_INC_FACTOR;
+		scf_rem =
+		    (output_startpos +
+		     output_span) * h_ratio % ARSR2P_INC_FACTOR;
+		scf_in_end = (scf_rem > 0) ? (scf_int + 1) : scf_int;
+
+		if ((first_block == 1) && (last_block == 1)) {
+			scf_read_start = 0;
+			scf_read_end = DSS_WIDTH(src_rect.w);
+			h_v_layer->block_info.last_tile = 1;
+		} else if (first_block == 1) {
+			scf_read_start = 0;
+			scf_read_end = scf_in_end + ARSR2P_OVERLAPH - 1;
+		} else {
+			scf_read_start = scf_in_start - ARSR2P_OVERLAPH;
+			if (scf_read_start < 0)
+				scf_read_start = 0;
+
+			if (last_block == 1) {
+				scf_read_end = DSS_WIDTH(src_rect.w);
+				h_v_layer->block_info.last_tile = 1;
+			} else {
+				scf_read_end = scf_in_end + ARSR2P_OVERLAPH - 1;
+			}
+		}
+
+		if (scf_read_end > DSS_WIDTH(src_rect.w))
+			scf_read_end = DSS_WIDTH(src_rect.w);
+
+		input_startpos = scf_read_start;
+		input_span = scf_read_end - scf_read_start + 1;
+		h_v_layer->block_info.h_ratio_arsr2p = h_ratio;
+		h_v_layer->block_info.arsr2p_src_x = h_layer->src_rect.x;
+		h_v_layer->block_info.arsr2p_src_y = h_layer->src_rect.y;
+		h_v_layer->block_info.arsr2p_dst_x = h_layer->dst_rect.x;
+		h_v_layer->block_info.arsr2p_dst_y = h_layer->dst_rect.y;
+		h_v_layer->block_info.arsr2p_dst_w = h_layer->dst_rect.w;
+
+		rect_transform.x = h_layer->src_rect.x + input_startpos;
+		rect_transform.y = h_layer->src_rect.y;
+		rect_transform.w = input_span;
+		rect_transform.h = h_layer->src_rect.h;
+		h_v_layer->block_info.arsr2p_in_rect = rect_transform;
+		h_v_layer->src_rect = rect_transform;
+		rect_across_rect(h_v_layer->src_rect, h_v_layer->src_rect_mask,
+				 &h_v_layer->src_rect_mask);
+		h_v_layer->dst_rect = dst_cross_rect;
+	}
+	/* scaling not in rchn v0 or scaling down in rchn v0 */
+	if (((h_layer->src_rect.w != h_layer->dst_rect.w)
+	     && (h_layer->chn_idx != DSS_RCHN_V0))
+	    || ((h_layer->src_rect.w > h_layer->dst_rect.w)
+		 && (h_layer->chn_idx == DSS_RCHN_V0))) {
+		/* check if arsr2p input has already extened width */
+		if (h_v_layer->block_info.h_ratio_arsr2p) {
+			dst_rect = rect_transform;
+			h_v_layer->block_info.both_vscfh_arsr2p_used = 1;
+			output_startpos = input_startpos;
+			output_span = dst_rect.w;
+			input_startpos = output_startpos;
+			input_span = output_span;
+		} else {
+			dst_rect = h_layer->dst_rect;
+		}
+
+		h_ratio =
+		    (DSS_WIDTH(h_layer->src_rect.w) * SCF_INC_FACTOR +
+		     SCF_INC_FACTOR / 2 -
+		     acc_hscl) / DSS_WIDTH(h_layer->dst_rect.w);
+
+		scf_in_start = output_startpos * h_ratio / SCF_INC_FACTOR;
+		scf_in_end =
+		    DSS_WIDTH(output_startpos +
+			      output_span) * h_ratio / SCF_INC_FACTOR;
+
+		if ((first_block == 1) && (last_block == 1)) {
+			acc_hscl = 0;
+			scf_read_start = 0;
+			scf_read_end = DSS_WIDTH(h_layer->src_rect.w);
+		} else if (first_block == 1) {
+			acc_hscl = 0;
+			scf_read_start = 0;
+			scf_read_end = scf_in_end + SCF_INPUT_OV;
+		} else {
+			scf_read_start = scf_in_start - SCF_INPUT_OV;
+			if (scf_read_start < 0)
+				scf_read_start = 0;
+			acc_hscl =
+			    output_startpos * h_ratio -
+			    scf_read_start * SCF_INC_FACTOR;
+
+			if (last_block == 1) {
+				scf_read_end = DSS_WIDTH(h_layer->src_rect.w);
+			} else {
+				scf_read_end = scf_in_end + SCF_INPUT_OV;
+			}
+		}
+
+		if (scf_read_end > DSS_WIDTH(h_layer->src_rect.w))
+			scf_read_end = DSS_WIDTH(h_layer->src_rect.w);
+
+		input_startpos = scf_read_start;
+		input_span = scf_read_end - scf_read_start + 1;
+		h_v_layer->block_info.h_ratio = h_ratio;
+		h_v_layer->block_info.acc_hscl = acc_hscl;
+
+		if (g_debug_ovl_block_composer) {
+			HISI_FB_INFO
+			    ("first_block=%d, last_block=%d, output_startpos=%d, output_span=%d, "
+			     "h_ratio=%d, acc_hscl=%d, scf_read_start=%d,"
+			     "scf_read_end=%d, input_startpos=%d, input_span=%d\n",
+			     first_block, last_block, output_startpos,
+			     output_span, h_ratio, acc_hscl, scf_read_start,
+			     scf_read_end, input_startpos, input_span);
+		}
+	}
+
+	switch (h_v_layer->transform) {
+	case HISI_FB_TRANSFORM_NOP:
+	case HISI_FB_TRANSFORM_FLIP_V:
+		rect_transform.x = h_layer->src_rect.x + input_startpos;
+		rect_transform.y = h_layer->src_rect.y;
+		rect_transform.w = input_span;
+		rect_transform.h = h_layer->src_rect.h;
+		break;
+	case HISI_FB_TRANSFORM_ROT_180:
+	case HISI_FB_TRANSFORM_FLIP_H:
+		rect_transform.x =
+		    h_layer->src_rect.x + h_layer->src_rect.w - input_startpos -
+		    input_span;
+		rect_transform.y = h_layer->src_rect.y;
+		rect_transform.w = input_span;
+		rect_transform.h = h_layer->src_rect.h;
+		break;
+	default:
+		HISI_FB_ERR("unknown h_v_layer->transform=%d!\n",
+			    h_v_layer->transform);
+		return -EINVAL;
+	}
+
+	h_v_layer->src_rect = rect_transform;
+	rect_across_rect(h_v_layer->src_rect, h_v_layer->src_rect_mask,
+			 &h_v_layer->src_rect_mask);
+
+	if (!h_v_layer->block_info.both_vscfh_arsr2p_used)
+		h_v_layer->dst_rect = dst_cross_rect;
+
+	return 0;
+}
+
+int get_block_layers(dss_overlay_t *pov_req, dss_overlay_block_t *pov_h_block,
+		     dss_rect_t ov_block_rect, dss_overlay_t *pov_req_h_v)
+{
+	uint32_t i = 0;
+	int ret = 0;
+	dss_rect_t dst_cross_rect;
+	dss_rect_t wb_ov_rect;
+	dss_overlay_block_t *pov_h_v_block = NULL;
+	dss_layer_t *h_layer = NULL;
+	dss_layer_t *h_v_layer = NULL;
+	int h_v_layer_idx = 0;
+
+	BUG_ON(pov_req == NULL);
+	BUG_ON(pov_h_block == NULL);
+	BUG_ON(pov_req_h_v == NULL);
+
+	if (!ov_block_rect.w || !ov_block_rect.h) {
+		HISI_FB_ERR("invaild args, ov_block_rect(%d,%d,%d,%d)!\n",
+			    ov_block_rect.x, ov_block_rect.y, ov_block_rect.w,
+			    ov_block_rect.y);
+		return -1;
+	}
+
+	pov_h_v_block = (dss_overlay_block_t *) pov_req_h_v->ov_block_infos_ptr;
+	memcpy(pov_req_h_v, pov_req, sizeof(dss_overlay_t));
+	pov_req_h_v->ov_block_infos_ptr = (uint64_t) (pov_h_v_block);
+
+	if (calc_dest_block_size(pov_req, pov_h_block) == BLOCK_SIZE_INVALID) {
+		pov_req_h_v->ov_block_nums = 1;
+		memcpy(pov_h_v_block, pov_h_block, sizeof(dss_overlay_block_t));
+		return 0;
+	}
+
+	pov_h_v_block->layer_nums = 0;
+	h_v_layer_idx = 0;
+	memcpy(&pov_h_v_block->ov_block_rect, &pov_h_block->ov_block_rect,
+	       sizeof(dss_rect_t));
+	wb_ov_rect.x = pov_req->wb_ov_rect.x + ov_block_rect.x;
+	wb_ov_rect.y = pov_req->wb_ov_rect.y;
+	wb_ov_rect.w = ov_block_rect.w;
+	wb_ov_rect.h = ov_block_rect.h;
+
+	for (i = 0; i < pov_h_block->layer_nums; i++) {
+		h_layer = &(pov_h_block->layer_infos[i]);
+
+		ret =
+		    rect_across_rect(h_layer->dst_rect, wb_ov_rect,
+				     &dst_cross_rect);
+		if (ret == 0)
+			continue;
+
+		h_v_layer = &(pov_h_v_block->layer_infos[h_v_layer_idx]);
+		memcpy(h_v_layer, h_layer, sizeof(dss_layer_t));
+		h_v_layer->layer_idx = h_v_layer_idx;
+
+		ret =
+		    create_h_v_block_layer(h_layer, h_v_layer, dst_cross_rect,
+					   wb_ov_rect);
+		if ((ret != 0) || g_debug_ovl_block_composer) {
+			HISI_FB_INFO
+			    ("h_layer[%d](transform[%d], wb_ov_rect[%d,%d,%d,%d], "
+			     "src_rect[%d,%d,%d,%d], dst_rect[%d,%d,%d,%d]), "
+			     "h_v_layer[%d](transform[%d], src_rect[%d,%d,%d,%d], "
+			     "dst_rect[%d,%d,%d,%d], dst_cross_rect[%d,%d,%d,%d])\n",
+			     i, h_layer->transform, wb_ov_rect.x, wb_ov_rect.y,
+			     wb_ov_rect.w, wb_ov_rect.h, h_layer->src_rect.x,
+			     h_layer->src_rect.y, h_layer->src_rect.w,
+			     h_layer->src_rect.h, h_layer->dst_rect.x,
+			     h_layer->dst_rect.y, h_layer->dst_rect.w,
+			     h_layer->dst_rect.h, h_v_layer_idx,
+			     h_v_layer->transform, h_v_layer->src_rect.x,
+			     h_v_layer->src_rect.y, h_v_layer->src_rect.w,
+			     h_v_layer->src_rect.h, h_v_layer->dst_rect.x,
+			     h_v_layer->dst_rect.y, h_v_layer->dst_rect.w,
+			     h_v_layer->dst_rect.h, dst_cross_rect.x,
+			     dst_cross_rect.y, dst_cross_rect.w,
+			     dst_cross_rect.h);
+		}
+
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("create_h_v_block_layer failed, h_layer[%d], h_v_layer[%d]!\n",
+			     i, h_v_layer_idx);
+			break;
+		}
+
+		h_v_layer_idx++;
+		pov_h_v_block->layer_nums = h_v_layer_idx;
+	}
+
+	return ret;
+}
diff --git a/drivers/video/fbdev/hisi/dss/hisi_block_algorithm.h b/drivers/video/fbdev/hisi/dss/hisi_block_algorithm.h
new file mode 100755
index 000000000000..dcbd01650814
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_block_algorithm.h
@@ -0,0 +1,29 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#ifndef __HISI_BLOCK_ALGORITHM_H__
+#define __HISI_BLOCK_ALGORITHM_H__
+
+#include "hisi_dss.h"
+
+int get_ov_block_rect(dss_overlay_t *pov_req_h,
+		      dss_overlay_block_t *pov_h_block,
+		      dss_wb_layer_t *wb_layer, int *block_num,
+		      dss_rect_t *ov_block_rects[]);
+int get_block_layers(dss_overlay_t *pov_req_h,
+		     dss_overlay_block_t *pov_h_block,
+		     dss_rect_t ov_block_rect, dss_overlay_t *pov_req_v_block);
+int rect_across_rect(dss_rect_t rect1, dss_rect_t rect2,
+		     dss_rect_t *cross_rect);
+
+#endif
diff --git a/drivers/video/fbdev/hisi/dss/hisi_dpe_utils_hi3660.c b/drivers/video/fbdev/hisi/dss/hisi_dpe_utils_hi3660.c
new file mode 100755
index 000000000000..87b9768de329
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_dpe_utils_hi3660.c
@@ -0,0 +1,1549 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_dpe_utils.h"
+
+DEFINE_SEMAPHORE(hisi_fb_dss_inner_clk_sem);
+
+static int dss_inner_clk_refcount = 0;
+
+#define OFFSET_FRACTIONAL_BITS	(11)
+#define ROUND1(x,y)	((x) / (y) + ((x) % (y)  ? 1 : 0))
+
+static int get_lcd_frame_rate(struct hisi_panel_info *pinfo)
+{
+	return pinfo->pxl_clk_rate / (pinfo->xres + pinfo->pxl_clk_rate_div *
+				      (pinfo->ldi.h_back_porch +
+				       pinfo->ldi.h_front_porch +
+				       pinfo->ldi.h_pulse_width)) /
+	    (pinfo->yres + pinfo->ldi.v_back_porch + pinfo->ldi.v_front_porch +
+	     pinfo->ldi.v_pulse_width);
+}
+
+struct dss_clk_rate *get_dss_clk_rate(struct hisi_fb_data_type *hisifd)
+{
+	struct hisi_panel_info *pinfo = NULL;
+	struct dss_clk_rate *pdss_clk_rate = NULL;
+	int frame_rate = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	pinfo = &(hisifd->panel_info);
+	pdss_clk_rate = &(hisifd->dss_clk_rate);
+	frame_rate = get_lcd_frame_rate(pinfo);
+
+	if (pdss_clk_rate->dss_pclk_dss_rate == 0) {
+		if ((pinfo->xres * pinfo->yres) >= (RES_4K_PHONE)) {
+			pdss_clk_rate->dss_pri_clk_rate =
+			    DEFAULT_DSS_CORE_CLK_08V_RATE;
+			pdss_clk_rate->dss_pclk_dss_rate =
+			    DEFAULT_PCLK_DSS_RATE;
+			pdss_clk_rate->dss_pclk_pctrl_rate =
+			    DEFAULT_PCLK_PCTRL_RATE;
+			hisifd->core_clk_upt_support = 0;
+
+		} else if ((pinfo->xres * pinfo->yres) >= (RES_1440P)) {
+			if (frame_rate >= 110) {
+				pdss_clk_rate->dss_pri_clk_rate =
+				    DEFAULT_DSS_CORE_CLK_08V_RATE;
+				pdss_clk_rate->dss_pclk_dss_rate =
+				    DEFAULT_PCLK_DSS_RATE;
+				pdss_clk_rate->dss_pclk_pctrl_rate =
+				    DEFAULT_PCLK_PCTRL_RATE;
+				hisifd->core_clk_upt_support = 0;
+			} else {
+				pdss_clk_rate->dss_pri_clk_rate =
+				    DEFAULT_DSS_CORE_CLK_07V_RATE;
+				pdss_clk_rate->dss_pclk_dss_rate =
+				    DEFAULT_PCLK_DSS_RATE;
+				pdss_clk_rate->dss_pclk_pctrl_rate =
+				    DEFAULT_PCLK_PCTRL_RATE;
+				hisifd->core_clk_upt_support = 1;
+			}
+
+		} else if ((pinfo->xres * pinfo->yres) >= (RES_1080P)) {
+			pdss_clk_rate->dss_pri_clk_rate =
+			    DEFAULT_DSS_CORE_CLK_07V_RATE;
+			pdss_clk_rate->dss_pclk_dss_rate =
+			    DEFAULT_PCLK_DSS_RATE;
+			pdss_clk_rate->dss_pclk_pctrl_rate =
+			    DEFAULT_PCLK_PCTRL_RATE;
+			hisifd->core_clk_upt_support = 1;
+
+		} else {
+			pdss_clk_rate->dss_pri_clk_rate =
+			    DEFAULT_DSS_CORE_CLK_07V_RATE;
+			pdss_clk_rate->dss_pclk_dss_rate =
+			    DEFAULT_PCLK_DSS_RATE;
+			pdss_clk_rate->dss_pclk_pctrl_rate =
+			    DEFAULT_PCLK_PCTRL_RATE;
+			hisifd->core_clk_upt_support = 1;
+		}
+	}
+
+	return pdss_clk_rate;
+}
+
+int set_dss_clk_rate(struct hisi_fb_data_type *hisifd,
+		     dss_clk_rate_t dss_clk_rate)
+{
+	int ret = 0;
+
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -1;
+	}
+
+	if ((dss_clk_rate.dss_pri_clk_rate != DEFAULT_DSS_CORE_CLK_08V_RATE)
+	    && (dss_clk_rate.dss_pri_clk_rate != DEFAULT_DSS_CORE_CLK_07V_RATE)) {
+		HISI_FB_ERR("no support set dss_pri_clk_rate(%llu)!\n",
+			    dss_clk_rate.dss_pri_clk_rate);
+		return -1;
+	}
+
+	if (dss_clk_rate.dss_pri_clk_rate ==
+	    hisifd->dss_clk_rate.dss_pri_clk_rate) {
+		return ret;
+	}
+
+	ret = clk_set_rate(hisifd->dss_pri_clk, dss_clk_rate.dss_pri_clk_rate);
+	if (ret < 0) {
+		HISI_FB_ERR("set dss_pri_clk_rate(%llu) failed, error=%d!\n",
+			    dss_clk_rate.dss_pri_clk_rate, ret);
+		return -1;
+	}
+
+	hisifd->dss_clk_rate.dss_pri_clk_rate = dss_clk_rate.dss_pri_clk_rate;
+
+	return ret;
+}
+
+void dss_inner_clk_common_enable(struct hisi_fb_data_type *hisifd,
+				 bool fastboot_enable)
+{
+	char __iomem *dss_base = NULL;
+	int prev_refcount = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	dss_base = hisifd->dss_base;
+
+	down(&hisi_fb_dss_inner_clk_sem);
+
+	prev_refcount = dss_inner_clk_refcount++;
+	if (!prev_refcount && !fastboot_enable) {
+		outp32(dss_base + DSS_CMDLIST_OFFSET + CMD_MEM_CTRL,
+		       0x00000008);
+		outp32(dss_base + DSS_RCH_VG0_SCL_OFFSET + SCF_COEF_MEM_CTRL,
+		       0x00000088);
+		outp32(dss_base + DSS_RCH_VG0_SCL_OFFSET + SCF_LB_MEM_CTRL,
+		       0x00000008);
+		outp32(dss_base + DSS_RCH_VG0_ARSR_OFFSET + ARSR2P_LB_MEM_CTRL,
+		       0x00000008);
+		outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + VPP_MEM_CTRL,
+		       0x00000008);
+		outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + DMA_BUF_MEM_CTRL,
+		       0x00000008);
+		outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + AFBCD_MEM_CTRL,
+		       0x00008888);
+
+		outp32(dss_base + DSS_RCH_VG1_SCL_OFFSET + SCF_COEF_MEM_CTRL,
+		       0x00000088);
+		outp32(dss_base + DSS_RCH_VG1_SCL_OFFSET + SCF_LB_MEM_CTRL,
+		       0x00000008);
+		outp32(dss_base + DSS_RCH_VG1_DMA_OFFSET + DMA_BUF_MEM_CTRL,
+		       0x00000008);
+		outp32(dss_base + DSS_RCH_VG1_DMA_OFFSET + AFBCD_MEM_CTRL,
+		       0x00008888);
+
+		outp32(dss_base + DSS_RCH_VG2_SCL_OFFSET + SCF_COEF_MEM_CTRL,
+		       0x00000088);
+		outp32(dss_base + DSS_RCH_VG2_SCL_OFFSET + SCF_LB_MEM_CTRL,
+		       0x00000008);
+		outp32(dss_base + DSS_RCH_VG2_DMA_OFFSET + DMA_BUF_MEM_CTRL,
+		       0x00000008);
+
+		outp32(dss_base + DSS_RCH_G0_SCL_OFFSET + SCF_COEF_MEM_CTRL,
+		       0x00000088);
+		outp32(dss_base + DSS_RCH_G0_SCL_OFFSET + SCF_LB_MEM_CTRL,
+		       0x0000008);
+		outp32(dss_base + DSS_RCH_G0_DMA_OFFSET + DMA_BUF_MEM_CTRL,
+		       0x00000008);
+		outp32(dss_base + DSS_RCH_G0_DMA_OFFSET + AFBCD_MEM_CTRL,
+		       0x00008888);
+
+		outp32(dss_base + DSS_RCH_G1_SCL_OFFSET + SCF_COEF_MEM_CTRL,
+		       0x00000088);
+		outp32(dss_base + DSS_RCH_G1_SCL_OFFSET + SCF_LB_MEM_CTRL,
+		       0x0000008);
+		outp32(dss_base + DSS_RCH_G1_DMA_OFFSET + DMA_BUF_MEM_CTRL,
+		       0x00000008);
+		outp32(dss_base + DSS_RCH_G1_DMA_OFFSET + AFBCD_MEM_CTRL,
+		       0x00008888);
+
+		outp32(dss_base + DSS_RCH_D0_DMA_OFFSET + DMA_BUF_MEM_CTRL,
+		       0x00000008);
+		outp32(dss_base + DSS_RCH_D0_DMA_OFFSET + AFBCD_MEM_CTRL,
+		       0x00008888);
+		outp32(dss_base + DSS_RCH_D1_DMA_OFFSET + DMA_BUF_MEM_CTRL,
+		       0x00000008);
+		outp32(dss_base + DSS_RCH_D2_DMA_OFFSET + DMA_BUF_MEM_CTRL,
+		       0x00000008);
+		outp32(dss_base + DSS_RCH_D3_DMA_OFFSET + DMA_BUF_MEM_CTRL,
+		       0x00000008);
+
+		outp32(dss_base + DSS_WCH0_DMA_OFFSET + DMA_BUF_MEM_CTRL,
+		       0x00000008);
+		outp32(dss_base + DSS_WCH0_DMA_OFFSET + AFBCE_MEM_CTRL,
+		       0x00000888);
+		outp32(dss_base + DSS_WCH0_DMA_OFFSET + ROT_MEM_CTRL,
+		       0x00000008);
+		outp32(dss_base + DSS_WCH1_DMA_OFFSET + DMA_BUF_MEM_CTRL,
+		       0x00000008);
+		outp32(dss_base + DSS_WCH1_DMA_OFFSET + AFBCE_MEM_CTRL,
+		       0x00000888);
+		outp32(dss_base + DSS_WCH1_DMA_OFFSET + ROT_MEM_CTRL,
+		       0x00000008);
+		outp32(dss_base + DSS_WCH2_DMA_OFFSET + DMA_BUF_MEM_CTRL,
+		       0x00000008);
+		outp32(dss_base + DSS_WCH2_DMA_OFFSET + ROT_MEM_CTRL,
+		       0x00000008);
+	}
+
+	HISI_FB_DEBUG("fb%d, dss_inner_clk_refcount=%d\n",
+		      hisifd->index, dss_inner_clk_refcount);
+
+	up(&hisi_fb_dss_inner_clk_sem);
+}
+
+void dss_inner_clk_common_disable(struct hisi_fb_data_type *hisifd)
+{
+	int new_refcount = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	down(&hisi_fb_dss_inner_clk_sem);
+	new_refcount = --dss_inner_clk_refcount;
+	WARN_ON(new_refcount < 0);
+	if (!new_refcount) {
+		;
+	}
+
+	HISI_FB_DEBUG("fb%d, dss_inner_clk_refcount=%d\n",
+		      hisifd->index, dss_inner_clk_refcount);
+	up(&hisi_fb_dss_inner_clk_sem);
+}
+
+void dss_inner_clk_pdp_enable(struct hisi_fb_data_type *hisifd,
+			      bool fastboot_enable)
+{
+	char __iomem *dss_base = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	dss_base = hisifd->dss_base;
+
+	if (fastboot_enable) return;
+
+	outp32(dss_base + DSS_IFBC_OFFSET + IFBC_MEM_CTRL, 0x00000088);
+	outp32(dss_base + DSS_DSC_OFFSET + DSC_MEM_CTRL, 0x00000888);
+	outp32(dss_base + DSS_LDI0_OFFSET + LDI_MEM_CTRL, 0x00000008);
+	outp32(dss_base + DSS_DBUF0_OFFSET + DBUF_MEM_CTRL, 0x00000008);
+	outp32(dss_base + DSS_DPP_DITHER_OFFSET + DITHER_MEM_CTRL, 0x00000008);
+}
+
+void dss_inner_clk_pdp_disable(struct hisi_fb_data_type *hisifd)
+{
+}
+
+void dss_inner_clk_sdp_enable(struct hisi_fb_data_type *hisifd)
+{
+	char __iomem *dss_base = NULL;
+
+	BUG_ON(hisifd == NULL);
+	dss_base = hisifd->dss_base;
+
+	outp32(dss_base + DSS_LDI1_OFFSET + LDI_MEM_CTRL, 0x00000008);
+	outp32(dss_base + DSS_DBUF1_OFFSET + DBUF_MEM_CTRL, 0x00000008);
+}
+
+void dss_inner_clk_sdp_disable(struct hisi_fb_data_type *hisifd)
+{
+}
+
+void init_dpp(struct hisi_fb_data_type *hisifd)
+{
+	char __iomem *dpp_base = NULL;
+	struct hisi_panel_info *pinfo = NULL;
+
+	BUG_ON(hisifd == NULL);
+	pinfo = &(hisifd->panel_info);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		dpp_base = hisifd->dss_base + DSS_DPP_OFFSET;
+	} else {
+		HISI_FB_ERR("fb%d, not support!", hisifd->index);
+		return;
+	}
+
+	outp32(dpp_base + DPP_IMG_SIZE_BEF_SR,
+	       (DSS_HEIGHT(pinfo->yres) << 16) | DSS_WIDTH(pinfo->xres));
+	outp32(dpp_base + DPP_IMG_SIZE_AFT_SR,
+	       (DSS_HEIGHT(pinfo->yres) << 16) | DSS_WIDTH(pinfo->xres));
+
+#ifdef CONFIG_HISI_FB_COLORBAR_USED
+	outp32(dpp_base + DPP_CLRBAR_CTRL, (0x30 << 24) | (0 << 1) | 0x1);
+	set_reg(dpp_base + DPP_CLRBAR_1ST_CLR, 0xFF, 8, 16);
+	set_reg(dpp_base + DPP_CLRBAR_2ND_CLR, 0xFF, 8, 8);
+	set_reg(dpp_base + DPP_CLRBAR_3RD_CLR, 0xFF, 8, 0);
+#endif
+}
+
+static void init_dsc(struct hisi_fb_data_type *hisifd)
+{
+	char __iomem *dsc_base = NULL;
+	struct hisi_panel_info *pinfo = NULL;
+	struct dsc_panel_info *dsc = NULL;
+
+	uint32_t dsc_en = 0;
+	uint32_t pic_width = 0;
+	uint32_t pic_height = 0;
+	uint32_t chunk_size = 0;
+	uint32_t groups_per_line = 0;
+	uint32_t rbs_min = 0;
+	uint32_t hrd_delay = 0;
+	uint32_t target_bpp_x16 = 0;
+	uint32_t num_extra_mux_bits = 0;
+	uint32_t slice_bits = 0;
+	uint32_t final_offset = 0;
+	uint32_t final_scale = 0;
+	uint32_t nfl_bpg_offset = 0;
+	uint32_t groups_total = 0;
+	uint32_t slice_bpg_offset = 0;
+	uint32_t scale_increment_interval = 0;
+	uint32_t initial_scale_value = 0;
+	uint32_t scale_decrement_interval = 0;
+	uint32_t adjustment_bits = 0;
+	uint32_t adj_bits_per_grp = 0;
+	uint32_t bits_per_grp = 0;
+	uint32_t slices_per_line = 0;
+	uint32_t pic_line_grp_num = 0;
+
+	BUG_ON(hisifd == NULL);
+	pinfo = &(hisifd->panel_info);
+	dsc = &(pinfo->vesa_dsc);
+
+	dsc_base = hisifd->dss_base + DSS_DSC_OFFSET;
+
+	if ((pinfo->ifbc_type == IFBC_TYPE_VESA2X_SINGLE) ||
+	    (pinfo->ifbc_type == IFBC_TYPE_VESA3X_SINGLE)) {
+
+		dsc_en = 0x5;
+		pic_width = DSS_WIDTH(pinfo->xres);
+		outp32(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_VESA_CLK_SEL,
+		       0);
+	} else {
+
+		dsc_en = 0xb;
+		pic_width = DSS_WIDTH(pinfo->xres / 2);
+		outp32(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_VESA_CLK_SEL,
+		       1);
+	}
+
+	pic_height = DSS_HEIGHT(pinfo->yres);
+	chunk_size = ROUND1((dsc->slice_width + 1) * dsc->bits_per_pixel, 8);
+
+	groups_per_line = (dsc->slice_width + 3) / 3;
+	rbs_min =
+	    dsc->rc_model_size - dsc->initial_offset +
+	    dsc->initial_xmit_delay * dsc->bits_per_pixel +
+	    groups_per_line * dsc->first_line_bpg_offset;
+	hrd_delay = ROUND1(rbs_min, dsc->bits_per_pixel);
+
+	target_bpp_x16 = dsc->bits_per_pixel * 16;
+	slice_bits = 8 * chunk_size * (dsc->slice_height + 1);
+
+	num_extra_mux_bits =
+	    3 * (dsc->mux_word_size + (4 * dsc->bits_per_component + 4) - 2);
+	while ((num_extra_mux_bits > 0)
+	       && ((slice_bits - num_extra_mux_bits) % dsc->mux_word_size))
+		num_extra_mux_bits--;
+
+	final_offset = dsc->rc_model_size -
+		((dsc->initial_xmit_delay * target_bpp_x16 + 8) >> 4) +
+		num_extra_mux_bits;
+
+	final_scale =
+	    8 * dsc->rc_model_size / (dsc->rc_model_size - final_offset);
+
+	nfl_bpg_offset =
+		ROUND1(dsc->first_line_bpg_offset << OFFSET_FRACTIONAL_BITS, dsc->slice_height);
+
+	groups_total = groups_per_line * (dsc->slice_height + 1);
+	slice_bpg_offset =
+		ROUND1((1 << OFFSET_FRACTIONAL_BITS) *
+			(dsc->rc_model_size - dsc->initial_offset + num_extra_mux_bits),
+			groups_total);
+
+	scale_increment_interval =
+		(1 << OFFSET_FRACTIONAL_BITS) * final_offset /
+		 ((final_scale - 9) * (nfl_bpg_offset + slice_bpg_offset));
+
+	initial_scale_value =
+	    8 * dsc->rc_model_size / (dsc->rc_model_size - dsc->initial_offset);
+	if (groups_per_line < initial_scale_value - 8) {
+		initial_scale_value = groups_per_line + 8;
+	}
+
+	if (initial_scale_value > 8) {
+		scale_decrement_interval =
+		    groups_per_line / (initial_scale_value - 8);
+	} else {
+		scale_decrement_interval = 4095;
+	}
+
+	adjustment_bits =
+	    (8 - (dsc->bits_per_pixel * (dsc->slice_width + 1)) % 8) % 8;
+
+	adj_bits_per_grp = dsc->bits_per_pixel * 3 - 3;
+	bits_per_grp = dsc->bits_per_pixel * 3;
+	slices_per_line = (pic_width > dsc->slice_width) ? 1 : 0;
+
+	pic_line_grp_num =
+	    ((dsc->slice_width + 3) / 3) * (slices_per_line + 1) - 1;
+
+	set_reg(dsc_base + DSC_REG_DEFAULT, 0x1, 1, 0);
+	set_reg(dsc_base + DSC_EN, dsc_en, 4, 0);
+	set_reg(dsc_base + DSC_CTRL,
+		dsc->bits_per_component | (dsc->linebuf_depth << 4) |
+		(dsc->block_pred_enable << 10) |
+		(0x1 << 11) | (dsc->bits_per_pixel << 16), 26, 0);
+
+	set_reg(dsc_base + DSC_PIC_SIZE, (pic_width << 16) | pic_height, 32, 0);
+
+	set_reg(dsc_base + DSC_SLICE_SIZE,
+		(dsc->slice_width << 16) | dsc->slice_height, 32, 0);
+
+	set_reg(dsc_base + DSC_CHUNK_SIZE, chunk_size, 16, 0);
+
+	set_reg(dsc_base + DSC_INITIAL_DELAY, dsc->initial_xmit_delay |
+		((hrd_delay - dsc->initial_xmit_delay) << 16), 32, 0);
+
+	set_reg(dsc_base + DSC_RC_PARAM0,
+		initial_scale_value | (scale_increment_interval << 16), 32, 0);
+
+	set_reg(dsc_base + DSC_RC_PARAM1,
+		(dsc->first_line_bpg_offset << 16) | scale_decrement_interval,
+		21, 0);
+
+	set_reg(dsc_base + DSC_RC_PARAM2,
+		nfl_bpg_offset | (slice_bpg_offset << 16), 32, 0);
+
+	set_reg(dsc_base + DSC_RC_PARAM3,
+		((final_offset << 16) | dsc->initial_offset), 32, 0);
+
+	set_reg(dsc_base + DSC_FLATNESS_QP_TH,
+		((dsc->flatness_max_qp << 16) | (dsc->flatness_min_qp << 0)),
+		24, 0);
+
+	set_reg(dsc_base + DSC_RC_PARAM4,
+		((dsc->rc_edge_factor << 20) | (dsc->rc_model_size << 0)), 24,
+		0);
+
+	set_reg(dsc_base + DSC_RC_PARAM5,
+		((dsc->rc_tgt_offset_lo << 20) | (dsc->rc_tgt_offset_hi << 16) |
+		 (dsc->rc_quant_incr_limit1 << 8) |
+		 (dsc->rc_quant_incr_limit0 << 0)), 24, 0);
+
+	set_reg(dsc_base + DSC_RC_BUF_THRESH0,
+		((dsc->rc_buf_thresh0 << 24) | (dsc->rc_buf_thresh1 << 16) |
+		 (dsc->rc_buf_thresh2 << 8) | (dsc->rc_buf_thresh3 << 0)), 32, 0);
+
+	set_reg(dsc_base + DSC_RC_BUF_THRESH1,
+		((dsc->rc_buf_thresh4 << 24) | (dsc->rc_buf_thresh5 << 16) |
+		 (dsc->rc_buf_thresh6 << 8) |
+		 (dsc->rc_buf_thresh7 << 0)), 32, 0);
+
+	set_reg(dsc_base + DSC_RC_BUF_THRESH2,
+		((dsc->rc_buf_thresh8 << 24) | (dsc->rc_buf_thresh9 << 16) |
+		 (dsc->rc_buf_thresh10 << 8) |
+		 (dsc->rc_buf_thresh11 << 0)), 32, 0);
+
+	set_reg(dsc_base + DSC_RC_BUF_THRESH3,
+		((dsc->rc_buf_thresh12 << 24) |
+		 (dsc->rc_buf_thresh13 << 16)), 32, 0);
+
+	set_reg(dsc_base + DSC_RC_RANGE_PARAM0,
+		((dsc->range_min_qp0 << 27) | (dsc->range_max_qp0 << 22) |
+		 (dsc->range_bpg_offset0 << 16) | (dsc->range_min_qp1 << 11) |
+		 (dsc->range_max_qp1 << 6) | (dsc->range_bpg_offset1 << 0)), 32, 0);
+
+	set_reg(dsc_base + DSC_RC_RANGE_PARAM1,
+		((dsc->range_min_qp2 << 27) | (dsc->range_max_qp2 << 22) |
+		 (dsc->range_bpg_offset2 << 16) |
+		 (dsc->range_min_qp3 << 11) | (dsc->range_max_qp3 << 6) |
+		 (dsc->range_bpg_offset3 << 0)), 32, 0);
+
+	set_reg(dsc_base + DSC_RC_RANGE_PARAM2,
+		((dsc->range_min_qp4 << 27) | (dsc->range_max_qp4 << 22) |
+		 (dsc->range_bpg_offset4 << 16) |
+		 (dsc->range_min_qp5 << 11) | (dsc->range_max_qp5 << 6) |
+		 (dsc->range_bpg_offset5 << 0)), 32, 0);
+
+	set_reg(dsc_base + DSC_RC_RANGE_PARAM3,
+		((dsc->range_min_qp6 << 27) | (dsc->range_max_qp6 << 22) |
+		 (dsc->range_bpg_offset6 << 16) |
+		 (dsc->range_min_qp7 << 11) | (dsc->range_max_qp7 << 6) |
+		 (dsc->range_bpg_offset7 << 0)), 32, 0);
+
+	set_reg(dsc_base + DSC_RC_RANGE_PARAM4,
+		((dsc->range_min_qp8 << 27) | (dsc->range_max_qp8 << 22) |
+		 (dsc->range_bpg_offset8 << 16) |
+		 (dsc->range_min_qp9 << 11) | (dsc->range_max_qp9 << 6) |
+		 (dsc->range_bpg_offset9 << 0)), 32, 0);
+
+	set_reg(dsc_base + DSC_RC_RANGE_PARAM5,
+		((dsc->range_min_qp10 << 27) | (dsc->range_max_qp10 << 22) |
+		 (dsc->range_bpg_offset10 << 16) |
+		 (dsc->range_min_qp11 << 11) | (dsc->range_max_qp11 << 6) |
+		 (dsc->range_bpg_offset11 << 0)), 32, 0);
+
+	set_reg(dsc_base + DSC_RC_RANGE_PARAM6,
+		((dsc->range_min_qp12 << 27) | (dsc->range_max_qp12 << 22) |
+		 (dsc->range_bpg_offset12 << 16) |
+		 (dsc->range_min_qp13 << 11) | (dsc->range_max_qp13 << 6) |
+		 (dsc->range_bpg_offset13 << 0)), 32, 0);
+
+	set_reg(dsc_base + DSC_RC_RANGE_PARAM7,
+		((dsc->range_min_qp14 << 27) | (dsc->range_max_qp14 << 22) |
+		 (dsc->range_bpg_offset14 << 16)), 32, 0);
+
+	set_reg(dsc_base + DSC_ADJUSTMENT_BITS, adjustment_bits, 4, 0);
+
+	set_reg(dsc_base + DSC_BITS_PER_GRP,
+		bits_per_grp | (adj_bits_per_grp << 8), 14, 0);
+
+	set_reg(dsc_base + DSC_MULTI_SLICE_CTL, slices_per_line |
+		(pic_line_grp_num << 16), 32, 0);
+
+	if ((chunk_size % 3 == 0)) {
+		set_reg(dsc_base + DSC_OUT_CTRL, 0x0, 1, 0);
+
+	} else if ((chunk_size % 2 == 0)) {
+		set_reg(dsc_base + DSC_OUT_CTRL, 0x1, 1, 0);
+
+	} else {
+		HISI_FB_ERR
+		    ("fb%d, chunk_size should be mode by 3 or 2,"
+		     " but chunk_size = %u\n",
+		     hisifd->index, chunk_size);
+		return;
+	}
+
+	set_reg(dsc_base + DSC_CLK_SEL, 0x0, 32, 0);
+	set_reg(dsc_base + DSC_CLK_EN, 0x7, 32, 0);
+	set_reg(dsc_base + DSC_MEM_CTRL, 0x0, 32, 0);
+	set_reg(dsc_base + DSC_ST_DATAIN, 0x0, 28, 0);
+	set_reg(dsc_base + DSC_ST_DATAOUT, 0x0, 16, 0);
+	set_reg(dsc_base + DSC0_ST_SLC_POS, 0x0, 28, 0);
+	set_reg(dsc_base + DSC1_ST_SLC_POS, 0x0, 28, 0);
+	set_reg(dsc_base + DSC0_ST_PIC_POS, 0x0, 28, 0);
+	set_reg(dsc_base + DSC1_ST_PIC_POS, 0x0, 28, 0);
+	set_reg(dsc_base + DSC0_ST_FIFO, 0x0, 14, 0);
+	set_reg(dsc_base + DSC1_ST_FIFO, 0x0, 14, 0);
+	set_reg(dsc_base + DSC0_ST_LINEBUF, 0x0, 24, 0);
+	set_reg(dsc_base + DSC1_ST_LINEBUF, 0x0, 24, 0);
+	set_reg(dsc_base + DSC_ST_ITFC, 0x0, 10, 0);
+	set_reg(dsc_base + DSC_RD_SHADOW_SEL, 0x1, 1, 0);
+	set_reg(dsc_base + DSC_REG_DEFAULT, 0x0, 1, 0);
+}
+
+void init_ifbc(struct hisi_fb_data_type *hisifd)
+{
+	char __iomem *ifbc_base = NULL;
+	struct hisi_panel_info *pinfo = NULL;
+	uint32_t mipi_idx = 0;
+	uint32_t comp_mode = 0;
+
+	uint32_t ifbc_out_mode = 0;
+	uint32_t dpk_mode_sel = 0;
+	uint32_t dup_mode_sel = 0;
+	uint32_t porch_num = 0;
+	uint32_t insert_byte_num = 0;
+	uint32_t insert_byte = 0;
+	uint32_t num_pad = 0;
+
+	BUG_ON(hisifd == NULL);
+	pinfo = &(hisifd->panel_info);
+	BUG_ON((pinfo->ifbc_type < IFBC_TYPE_NONE)
+	       || (pinfo->ifbc_type >= IFBC_TYPE_MAX));
+
+	/* VESA_CLK_SEL is set to 0 for initial, 1 is needed only by vesa dual pipe compress */
+	set_reg(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_VESA_CLK_SEL, 0, 1, 0);
+
+	if (pinfo->ifbc_type == IFBC_TYPE_NONE)
+		return;
+
+	if (!HISI_DSS_SUPPORT_DPP_MODULE_BIT(DPP_MODULE_IFBC))
+		return;
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		ifbc_base = hisifd->dss_base + DSS_IFBC_OFFSET;
+	} else {
+		HISI_FB_ERR("fb%d, not support!", hisifd->index);
+		return;
+	}
+
+	mipi_idx = is_dual_mipi_panel(hisifd) ? 1 : 0;
+	comp_mode = g_mipi_ifbc_division[mipi_idx][pinfo->ifbc_type].comp_mode;
+
+	if (is_ifbc_vesa_panel(hisifd)) {
+		init_dsc(hisifd);
+		set_reg(ifbc_base + IFBC_CTRL, comp_mode, 3, 0);
+		return;
+	}
+
+	if (pinfo->bpp == LCD_RGB888)
+		ifbc_out_mode = 1;
+	else if (pinfo->bpp == LCD_RGB565)
+		ifbc_out_mode = 0;
+
+	if (((pinfo->ifbc_type == IFBC_TYPE_ORISE2X)
+	     && (pinfo->ifbc_cmp_dat_rev0 == 1))
+	    || ((pinfo->ifbc_type == IFBC_TYPE_RSP3X)
+		 && (pinfo->type != PANEL_MIPI_VIDEO) && (pinfo->xres % 3 != 0)))
+		if (pinfo->ifbc_auto_sel != 0) {
+			HISI_FB_ERR("fb%d, auto_sel = %u not support!",
+				    hisifd->index, pinfo->ifbc_auto_sel);
+			return;
+		}
+
+	if (pinfo->ifbc_type == IFBC_TYPE_ORISE2X) {
+		if ((pinfo->xres % 2 != 0) && (pinfo->yres % 2 != 0)) {
+			HISI_FB_ERR
+			    ("fb%d, IFBC_ORISE2X not support (xres = %u, yres = %u)!",
+			     hisifd->index, pinfo->xres, pinfo->yres);
+			return;
+		}
+
+		dpk_mode_sel = 1;
+		dup_mode_sel = 2;
+		porch_num = 0;
+	} else if (pinfo->ifbc_type == IFBC_TYPE_ORISE3X) {
+		dpk_mode_sel = 0;
+		dup_mode_sel = 3;
+		porch_num = 5;
+	} else if (pinfo->ifbc_type == IFBC_TYPE_HIMAX2X) {
+		if ((pinfo->xres % 2 != 0) && (pinfo->yres % 2 != 0)) {
+			HISI_FB_ERR
+			    ("fb%d, IFBC_HIMAX2X not support (xres = %u, yres = %u)!",
+			     hisifd->index, pinfo->xres, pinfo->yres);
+			return;
+		}
+
+		dpk_mode_sel = 1;
+		dup_mode_sel = 2;
+		porch_num = 0;
+	} else if (pinfo->ifbc_type == IFBC_TYPE_RSP2X) {
+		dpk_mode_sel = 1;
+		dup_mode_sel = 0;
+		porch_num = 0;
+
+		if ((pinfo->type == PANEL_MIPI_CMD) ||
+		    (pinfo->type == PANEL_DUAL_MIPI_CMD)) {
+			num_pad = (4 - pinfo->xres % 4) % 4;
+		} else {
+			num_pad = 0;
+		}
+	} else if (pinfo->ifbc_type == IFBC_TYPE_RSP3X) {
+		if ((pinfo->yres % 2 != 0) || (pinfo->yres < 8)) {
+			HISI_FB_ERR
+			    ("fb%d, IFBC_RSP3X not support (xres = %u, yres = %u)!",
+			     hisifd->index, pinfo->xres, pinfo->yres);
+			return;
+		}
+
+		dpk_mode_sel = 2;
+		dup_mode_sel = 1;
+		porch_num = 0;
+
+		insert_byte = DSS_WIDTH(pinfo->xres) / (mipi_idx + 1) + 1;
+
+		if ((pinfo->type == PANEL_MIPI_VIDEO) ||
+		    (pinfo->type == PANEL_DUAL_MIPI_VIDEO)) {
+			insert_byte_num = (3 - insert_byte % 3) % 3;
+			num_pad = (8 - pinfo->xres % 8) % 8;
+		} else if ((pinfo->type == PANEL_MIPI_CMD) ||
+			   (pinfo->type == PANEL_DUAL_MIPI_CMD)) {
+			insert_byte_num = 0;
+			num_pad = (4 - pinfo->xres % 4) % 4;
+		}
+	}
+	set_reg(ifbc_base + IFBC_SIZE,
+		((DSS_WIDTH(pinfo->xres) << 16) | DSS_HEIGHT(pinfo->yres)), 32, 0);
+
+	set_reg(ifbc_base + IFBC_CTRL, comp_mode, 3, 0);
+	set_reg(ifbc_base + IFBC_CTRL, ifbc_out_mode, 1, 3);
+	set_reg(ifbc_base + IFBC_CTRL, pinfo->ifbc_cmp_dat_rev0, 1, 4);
+	set_reg(ifbc_base + IFBC_CTRL, pinfo->ifbc_cmp_dat_rev1, 1, 5);
+	set_reg(ifbc_base + IFBC_CTRL, pinfo->ifbc_auto_sel, 1, 6);
+
+	if (pinfo->ifbc_auto_sel == 0) {
+		set_reg(ifbc_base + IFBC_CTRL, dpk_mode_sel, 3, 7);
+		set_reg(ifbc_base + IFBC_CTRL, dup_mode_sel, 3, 10);
+		set_reg(ifbc_base + IFBC_CTRL, porch_num, 8, 13);
+		set_reg(ifbc_base + IFBC_INSERT,
+			insert_byte_num | (insert_byte << 16), 32, 0);
+
+		set_reg(ifbc_base + IFBC_PAD, num_pad, 3, 0);
+	}
+
+	if (pinfo->ifbc_type == IFBC_TYPE_ORISE3X) {
+		if (pinfo->ifbc_orise_ctr == 1) {
+			set_reg(ifbc_base + IFBC_CORE_GT, 0x0, 2, 0);
+
+			if (pinfo->ifbc_orise_ctl == IFBC_ORISE_CTL_8LINE) {
+				set_reg(ifbc_base + IFBC_ORISE_CTL, 0x0208, 32, 0);
+
+			} else if (pinfo->ifbc_orise_ctl == IFBC_ORISE_CTL_16LINE) {
+				set_reg(ifbc_base + IFBC_ORISE_CTL, 0x0210, 32, 0);
+			} else if (pinfo->ifbc_orise_ctl == IFBC_ORISE_CTL_32LINE) {
+				set_reg(ifbc_base + IFBC_ORISE_CTL, 0x0220, 32, 0);
+			} else {
+				set_reg(ifbc_base + IFBC_ORISE_CTL, 0x0200, 32, 0);
+			}
+
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x0300, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x0419, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x0500, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x063f, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x0700, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x0801, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x0900, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x0a64, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x0b00, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x0c5c, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x0d00, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x0e01, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x0f00, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x10a0, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x1100, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x125f, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x1300, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x14a0, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x1500, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x16ff, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x1700, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x200c, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x2100, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x4000, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x4100, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x4200, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x4300, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x4800, 32, 0);
+			set_reg(ifbc_base + IFBC_ORISE_CTL, 0x4900, 32, 0);
+		} else {
+			set_reg(ifbc_base + IFBC_CORE_GT, 0x2, 2, 0);
+		}
+	}
+
+	set_reg(ifbc_base + IFBC_CLK_SEL, 0x0, 32, 0);
+	set_reg(ifbc_base + IFBC_EN, 0x3, 2, 0);
+}
+
+void init_post_scf(struct hisi_fb_data_type *hisifd)
+{
+	char __iomem *dpp_base = NULL;
+	char __iomem *scf_lut_base = NULL;
+
+	struct hisi_panel_info *pinfo = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	pinfo = &(hisifd->panel_info);
+
+	dpp_base = hisifd->dss_base + DSS_DPP_OFFSET;
+	scf_lut_base = hisifd->dss_base + DSS_POST_SCF_LUT_OFFSET;
+
+	if (!HISI_DSS_SUPPORT_DPP_MODULE_BIT(DPP_MODULE_POST_SCF)) {
+		return;
+	}
+
+	/* ARSR1P memory shutdown
+	   outp32(dpp_base + DPP_ARSR1P_MEM_CTRL, 0X4); */
+
+	pinfo->post_scf_support = 1;
+	hisi_dss_post_scl_load_filter_coef(hisifd, false, scf_lut_base,
+					   SCL_COEF_RGB_IDX);
+
+	return;
+}
+
+void init_dbuf(struct hisi_fb_data_type *hisifd)
+{
+	char __iomem *dbuf_base = NULL;
+	struct hisi_panel_info *pinfo = NULL;
+	int sram_valid_num = 0;
+	int sram_max_mem_depth = 0;
+	int sram_min_support_depth = 0;
+
+	uint32_t thd_rqos_in = 0;
+	uint32_t thd_rqos_out = 0;
+	uint32_t thd_wqos_in = 0;
+	uint32_t thd_wqos_out = 0;
+	uint32_t thd_cg_in = 0;
+	uint32_t thd_cg_out = 0;
+	uint32_t thd_wr_wait = 0;
+	uint32_t thd_cg_hold = 0;
+	uint32_t thd_flux_req_befdfs_in = 0;
+	uint32_t thd_flux_req_befdfs_out = 0;
+	uint32_t thd_flux_req_aftdfs_in = 0;
+	uint32_t thd_flux_req_aftdfs_out = 0;
+	uint32_t thd_dfs_ok = 0;
+	uint32_t dfs_ok_mask = 0;
+	uint32_t thd_flux_req_sw_en = 1;
+
+	int dfs_time = 0;
+	int dfs_time_min = 0;
+	int depth = 0;
+
+	BUG_ON(hisifd == NULL);
+	pinfo = &(hisifd->panel_info);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		dbuf_base = hisifd->dss_base + DSS_DBUF0_OFFSET;
+		if (!HISI_DSS_SUPPORT_DPP_MODULE_BIT(DPP_MODULE_DBUF)) {
+			return;
+		}
+
+		if (pinfo->xres * pinfo->yres >= RES_4K_PHONE) {
+			dfs_time_min = DFS_TIME_MIN_4K;
+		} else {
+			dfs_time_min = DFS_TIME_MIN;
+		}
+
+		dfs_time = DFS_TIME;
+		depth = DBUF0_DEPTH;
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		dbuf_base = hisifd->dss_base + DSS_DBUF1_OFFSET;
+
+		dfs_time = DFS_TIME;
+		dfs_time_min = DFS_TIME_MIN;
+		depth = DBUF1_DEPTH;
+	} else {
+		HISI_FB_ERR("fb%d, not support!", hisifd->index);
+		return;
+	}
+
+	/*
+	 ** int K = 0;
+	 ** int Tp = 1000000  / pinfo->pxl_clk_rate;
+	 ** K = (pinfo->ldi.h_pulse_width + pinfo->ldi.h_back_porch + pinfo->xres +
+	 **     pinfo->ldi.h_front_porch) / pinfo->xres;
+	 ** thd_cg_out = dfs_time / (Tp * K * 6);
+	 */
+	if (pinfo->pxl_clk_rate_div <= 0)
+		pinfo->pxl_clk_rate_div = 1;
+
+	thd_cg_out = (dfs_time * pinfo->pxl_clk_rate * pinfo->xres) /
+	    (((pinfo->ldi.h_pulse_width + pinfo->ldi.h_back_porch +
+	       pinfo->ldi.h_front_porch) * pinfo->pxl_clk_rate_div +
+	      pinfo->xres) * 6 * 1000000UL);
+	sram_valid_num = thd_cg_out / depth;
+	thd_cg_in = (sram_valid_num + 1) * depth - 1;
+
+	sram_max_mem_depth = (sram_valid_num + 1) * depth;
+
+	thd_rqos_in = thd_cg_out * 85 / 100;
+	thd_rqos_out = thd_cg_out;
+	thd_flux_req_befdfs_in = GET_FLUX_REQ_IN(sram_max_mem_depth);
+	thd_flux_req_befdfs_out = GET_FLUX_REQ_OUT(sram_max_mem_depth);
+
+	sram_min_support_depth =
+	    dfs_time_min * pinfo->xres / (1000000 / 60 /
+					  (pinfo->yres +
+					   pinfo->ldi.v_back_porch +
+					   pinfo->ldi.v_front_porch +
+					   pinfo->ldi.v_pulse_width) *
+					  (DBUF_WIDTH_BIT / 3 / BITS_PER_BYTE));
+
+	/* thd_flux_req_aftdfs_in   =[(sram_valid_num+1)*depth - 50*HSIZE/((1000000/60/(VSIZE+VFP+VBP+VSW))*6)]/3 */
+	thd_flux_req_aftdfs_in =
+	    (sram_max_mem_depth - sram_min_support_depth) / 3;
+	/* thd_flux_req_aftdfs_out  =  2*[(sram_valid_num+1)* depth - 50*HSIZE/((1000000/60/(VSIZE+VFP+VBP+VSW))*6)]/3 */
+	thd_flux_req_aftdfs_out =
+	    2 * (sram_max_mem_depth - sram_min_support_depth) / 3;
+
+	thd_dfs_ok = thd_flux_req_befdfs_in;
+
+	HISI_FB_DEBUG("sram_valid_num=%d,\n"
+		      "thd_rqos_in=0x%x\n"
+		      "thd_rqos_out=0x%x\n"
+		      "thd_cg_in=0x%x\n"
+		      "thd_cg_out=0x%x\n"
+		      "thd_flux_req_befdfs_in=0x%x\n"
+		      "thd_flux_req_befdfs_out=0x%x\n"
+		      "thd_flux_req_aftdfs_in=0x%x\n"
+		      "thd_flux_req_aftdfs_out=0x%x\n"
+		      "thd_dfs_ok=0x%x\n",
+		      sram_valid_num,
+		      thd_rqos_in,
+		      thd_rqos_out,
+		      thd_cg_in,
+		      thd_cg_out,
+		      thd_flux_req_befdfs_in,
+		      thd_flux_req_befdfs_out,
+		      thd_flux_req_aftdfs_in,
+		      thd_flux_req_aftdfs_out, thd_dfs_ok);
+
+	outp32(dbuf_base + DBUF_FRM_SIZE, pinfo->xres * pinfo->yres);
+	outp32(dbuf_base + DBUF_FRM_HSIZE, DSS_WIDTH(pinfo->xres));
+	outp32(dbuf_base + DBUF_SRAM_VALID_NUM, sram_valid_num);
+
+	outp32(dbuf_base + DBUF_THD_RQOS, (thd_rqos_out << 16) | thd_rqos_in);
+	outp32(dbuf_base + DBUF_THD_WQOS, (thd_wqos_out << 16) | thd_wqos_in);
+	outp32(dbuf_base + DBUF_THD_CG, (thd_cg_out << 16) | thd_cg_in);
+	outp32(dbuf_base + DBUF_THD_OTHER, (thd_cg_hold << 16) | thd_wr_wait);
+	outp32(dbuf_base + DBUF_THD_FLUX_REQ_BEF,
+	       (thd_flux_req_befdfs_out << 16) | thd_flux_req_befdfs_in);
+	outp32(dbuf_base + DBUF_THD_FLUX_REQ_AFT,
+	       (thd_flux_req_aftdfs_out << 16) | thd_flux_req_aftdfs_in);
+	outp32(dbuf_base + DBUF_THD_DFS_OK, thd_dfs_ok);
+	outp32(dbuf_base + DBUF_FLUX_REQ_CTRL,
+	       (dfs_ok_mask << 1) | thd_flux_req_sw_en);
+
+	outp32(dbuf_base + DBUF_DFS_LP_CTRL, 0x1);
+}
+
+static void init_ldi_pxl_div(struct hisi_fb_data_type *hisifd)
+{
+	struct hisi_panel_info *pinfo = NULL;
+	char __iomem *ldi_base = NULL;
+	uint32_t ifbc_type = 0;
+	uint32_t mipi_idx = 0;
+	uint32_t pxl0_div2_gt_en = 0;
+	uint32_t pxl0_div4_gt_en = 0;
+	uint32_t pxl0_divxcfg = 0;
+	uint32_t pxl0_dsi_gt_en = 0;
+
+	BUG_ON(hisifd == NULL);
+	pinfo = &(hisifd->panel_info);
+
+	if (hisifd->index == EXTERNAL_PANEL_IDX)
+		return;
+
+	ldi_base = hisifd->dss_base + DSS_LDI0_OFFSET;
+
+	ifbc_type = pinfo->ifbc_type;
+	BUG_ON((ifbc_type < IFBC_TYPE_NONE) || (ifbc_type >= IFBC_TYPE_MAX));
+
+	mipi_idx = is_dual_mipi_panel(hisifd) ? 1 : 0;
+
+	pxl0_div2_gt_en =
+	    g_mipi_ifbc_division[mipi_idx][ifbc_type].pxl0_div2_gt_en;
+	pxl0_div4_gt_en =
+	    g_mipi_ifbc_division[mipi_idx][ifbc_type].pxl0_div4_gt_en;
+	pxl0_divxcfg = g_mipi_ifbc_division[mipi_idx][ifbc_type].pxl0_divxcfg;
+	pxl0_dsi_gt_en =
+	    g_mipi_ifbc_division[mipi_idx][ifbc_type].pxl0_dsi_gt_en;
+
+	set_reg(ldi_base + LDI_PXL0_DIV2_GT_EN, pxl0_div2_gt_en, 1, 0);
+	set_reg(ldi_base + LDI_PXL0_DIV4_GT_EN, pxl0_div4_gt_en, 1, 0);
+	set_reg(ldi_base + LDI_PXL0_GT_EN, 0x1, 1, 0);
+	set_reg(ldi_base + LDI_PXL0_DSI_GT_EN, pxl0_dsi_gt_en, 2, 0);
+	set_reg(ldi_base + LDI_PXL0_DIVXCFG, pxl0_divxcfg, 3, 0);
+}
+
+void init_ldi(struct hisi_fb_data_type *hisifd, bool fastboot_enable)
+{
+	char __iomem *ldi_base = NULL;
+	struct hisi_panel_info *pinfo = NULL;
+	dss_rect_t rect = { 0, 0, 0, 0 };
+	uint32_t te0_enable = 0;
+	uint32_t te1_enable = 0;
+	uint32_t te_source = 0;
+
+	BUG_ON(hisifd == NULL);
+	pinfo = &(hisifd->panel_info);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		ldi_base = hisifd->dss_base + DSS_LDI0_OFFSET;
+		te0_enable = 1;
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		te1_enable = 1;
+		ldi_base = hisifd->dss_base + DSS_LDI1_OFFSET;
+	} else {
+		HISI_FB_ERR("fb%d, not support!", hisifd->index);
+		return;
+	}
+
+	rect.x = 0;
+	rect.y = 0;
+	rect.w = pinfo->xres;
+	rect.h = pinfo->yres;
+	mipi_ifbc_get_rect(hisifd, &rect);
+
+	init_ldi_pxl_div(hisifd);
+
+	if (is_dual_mipi_panel(hisifd)) {
+		if (is_mipi_video_panel(hisifd)) {
+			outp32(ldi_base + LDI_DPI1_HRZ_CTRL0,
+			       (pinfo->ldi.h_back_porch +
+				DSS_WIDTH(pinfo->ldi.h_pulse_width)) << 16);
+			outp32(ldi_base + LDI_DPI1_HRZ_CTRL1, 0);
+			outp32(ldi_base + LDI_DPI1_HRZ_CTRL2,
+			       DSS_WIDTH(rect.w));
+		} else {
+			outp32(ldi_base + LDI_DPI1_HRZ_CTRL0,
+			       pinfo->ldi.h_back_porch << 16);
+			outp32(ldi_base + LDI_DPI1_HRZ_CTRL1,
+			       DSS_WIDTH(pinfo->ldi.h_pulse_width));
+			outp32(ldi_base + LDI_DPI1_HRZ_CTRL2,
+			       DSS_WIDTH(rect.w));
+		}
+
+		outp32(ldi_base + LDI_OVERLAP_SIZE,
+		       pinfo->ldi.dpi0_overlap_size |
+		       (pinfo->ldi.dpi1_overlap_size << 16));
+
+		/* dual_mode_en */
+		set_reg(ldi_base + LDI_CTRL, 1, 1, 5);
+
+		/* split mode */
+		set_reg(ldi_base + LDI_CTRL, 0, 1, 16);
+
+		/* dual lcd: 0x1, dual mipi: 0x0 */
+		set_reg(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_DSI1_CLK_SEL,
+			0x0, 1, 0);
+	}
+	if (is_mipi_video_panel(hisifd)) {
+		outp32(ldi_base + LDI_DPI0_HRZ_CTRL0,
+		       pinfo->ldi.h_front_porch |
+		       ((pinfo->ldi.h_back_porch +
+				DSS_WIDTH(pinfo->ldi.h_pulse_width)) << 16));
+
+		outp32(ldi_base + LDI_DPI0_HRZ_CTRL1, 0);
+		outp32(ldi_base + LDI_DPI0_HRZ_CTRL2, DSS_WIDTH(rect.w));
+	} else {
+		outp32(ldi_base + LDI_DPI0_HRZ_CTRL0,
+		       pinfo->ldi.h_front_porch | (pinfo->ldi.h_back_porch << 16));
+		outp32(ldi_base + LDI_DPI0_HRZ_CTRL1,
+		       DSS_WIDTH(pinfo->ldi.h_pulse_width));
+		outp32(ldi_base + LDI_DPI0_HRZ_CTRL2, DSS_WIDTH(rect.w));
+	}
+	outp32(ldi_base + LDI_VRT_CTRL0,
+	       pinfo->ldi.v_front_porch | (pinfo->ldi.v_back_porch << 16));
+	outp32(ldi_base + LDI_VRT_CTRL1, DSS_HEIGHT(pinfo->ldi.v_pulse_width));
+	outp32(ldi_base + LDI_VRT_CTRL2, DSS_HEIGHT(rect.h));
+
+	outp32(ldi_base + LDI_PLR_CTRL,
+	       pinfo->ldi.vsync_plr | (pinfo->ldi.hsync_plr << 1) |
+	       (pinfo->ldi.pixelclk_plr << 2) | (pinfo->ldi.data_en_plr << 3));
+
+	set_reg(ldi_base + LDI_CTRL, pinfo->bpp, 2, 3);
+	set_reg(ldi_base + LDI_CTRL, pinfo->bgr_fmt, 1, 13);
+
+	outp32(ldi_base + LDI_VINACT_MSK_LEN, pinfo->ldi.v_front_porch);
+	outp32(ldi_base + LDI_CMD_EVENT_SEL, 0x1);
+
+	/* for 1Hz LCD and mipi command LCD */
+	if (is_mipi_cmd_panel(hisifd)) {
+		set_reg(ldi_base + LDI_DSI_CMD_MOD_CTRL, 0x1, 1, 0);
+
+		/* DSI_TE_CTRL
+		 * te_source = 0, select te_pin
+		 * te_source = 1, select te_triger
+		 */
+		te_source = 0;
+
+		set_reg(ldi_base + LDI_DSI_TE_CTRL, 0x1, 1, 0);
+		set_reg(ldi_base + LDI_DSI_TE_CTRL, 0x0, 2, 1);
+		set_reg(ldi_base + LDI_DSI_TE_CTRL, te_source, 1, 3);
+		if (te_source == 0) {
+			set_reg(ldi_base + LDI_DSI_TE_CTRL, te0_enable, 1, 6);
+			set_reg(ldi_base + LDI_DSI_TE_CTRL, te1_enable, 1, 7);
+		} else {
+			set_reg(ldi_base + LDI_DSI_TE_CTRL, te0_enable, 1, 4);
+			set_reg(ldi_base + LDI_DSI_TE_CTRL, te1_enable, 1, 5);
+		}
+		set_reg(ldi_base + LDI_DSI_TE_CTRL, 0x0, 1, 8);
+		set_reg(ldi_base + LDI_DSI_TE_CTRL, 0x0, 4, 9);
+		set_reg(ldi_base + LDI_DSI_TE_CTRL, 0x0, 4, 13);
+		set_reg(ldi_base + LDI_DSI_TE_CTRL, 0x1, 1, 17);
+
+		/* TBD:(dsi_te_hs_num+vactive)*htotal/clk_pxl0_div+0.00004<1/60+vs_te_time+(vactive*hotal) /clk_ddic_rd */
+		set_reg(ldi_base + LDI_DSI_TE_HS_NUM, 0x0, 32, 0);
+		set_reg(ldi_base + LDI_DSI_TE_HS_WD, 0x24024, 32, 0);
+
+		/* dsi_te0_vs_wd = lcd_te_width / T_pxl_clk, experience lcd_te_width = 2us */
+		if (pinfo->pxl_clk_rate_div == 0) {
+			HISI_FB_ERR("pxl_clk_rate_div is NULL, not support !\n");
+			pinfo->pxl_clk_rate_div = 1;
+		}
+		set_reg(ldi_base + LDI_DSI_TE_VS_WD,
+			(0x3FC << 12) | (2 * pinfo->pxl_clk_rate /
+					 pinfo->pxl_clk_rate_div / 1000000), 32, 0);
+	} else {
+		set_reg(ldi_base + LDI_DSI_CMD_MOD_CTRL, 0x1, 1, 1);
+	}
+
+#ifdef CONFIG_HISI_FB_COLORBAR_USED
+	set_reg(ldi_base + LDI_CTRL, DSS_WIDTH(0x3c), 7, 6);
+	set_reg(ldi_base + LDI_WORK_MODE, 0x0, 1, 1);
+	set_reg(ldi_base + LDI_WORK_MODE, 0x0, 1, 0);
+#else
+	set_reg(ldi_base + LDI_WORK_MODE, 0x1, 1, 0);
+#endif
+
+	if (is_mipi_cmd_panel(hisifd)) {
+		set_reg(ldi_base + LDI_FRM_MSK,
+			(hisifd->frame_update_flag == 1) ? 0x0 : 0x1, 1, 0);
+	}
+
+	if (!fastboot_enable)
+		set_reg(ldi_base + LDI_CTRL, 0x0, 1, 0);
+
+	HISI_FB_DEBUG("-.!\n");
+}
+
+void deinit_ldi(struct hisi_fb_data_type *hisifd)
+{
+	char __iomem *ldi_base = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		ldi_base = hisifd->dss_base + DSS_LDI0_OFFSET;
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		ldi_base = hisifd->dss_base + DSS_LDI1_OFFSET;
+	} else {
+		HISI_FB_ERR("fb%d, not support!", hisifd->index);
+		return;
+	}
+
+	set_reg(ldi_base + LDI_CTRL, 0, 1, 0);
+}
+
+void enable_ldi(struct hisi_fb_data_type *hisifd)
+{
+	char __iomem *ldi_base = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		ldi_base = hisifd->dss_base + DSS_LDI0_OFFSET;
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		ldi_base = hisifd->dss_base + DSS_LDI1_OFFSET;
+	} else {
+		HISI_FB_ERR("fb%d, not support!", hisifd->index);
+		return;
+	}
+
+	/* ldi enable */
+	set_reg(ldi_base + LDI_CTRL, 0x1, 1, 0);
+}
+
+void disable_ldi(struct hisi_fb_data_type *hisifd)
+{
+	char __iomem *ldi_base = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		ldi_base = hisifd->dss_base + DSS_LDI0_OFFSET;
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		ldi_base = hisifd->dss_base + DSS_LDI1_OFFSET;
+	} else {
+		HISI_FB_ERR("fb%d, not support!", hisifd->index);
+		return;
+	}
+
+	/* ldi disable */
+	set_reg(ldi_base + LDI_CTRL, 0x0, 1, 0);
+}
+
+/* set pixel clock to the exact value which is larger than 288M */
+int dpe_recover_pxl_clock(struct hisi_fb_data_type *hisifd)
+{
+	if ((hisifd->panel_info.pxl_clk_rate > DSS_MAX_PXL0_CLK_288M)
+	    && (hisifd->index == PRIMARY_PANEL_IDX)) {
+		if (clk_set_rate(hisifd->dss_pxl0_clk,
+		     hisifd->panel_info.pxl_clk_rate) < 0) {
+			HISI_FB_ERR
+			    ("fb%d dss_pxl0_clk clk_set_rate(%llu) failed!\n",
+			     hisifd->index, hisifd->panel_info.pxl_clk_rate);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+void ldi_frame_update(struct hisi_fb_data_type *hisifd, bool update)
+{
+	char __iomem *ldi_base = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		ldi_base = hisifd->dss_base + DSS_LDI0_OFFSET;
+
+		if (is_mipi_cmd_panel(hisifd)) {
+			set_reg(ldi_base + LDI_FRM_MSK, (update ? 0x0 : 0x1), 1, 0);
+			if (update)
+				set_reg(ldi_base + LDI_CTRL, 0x1, 1, 0);
+		}
+	} else {
+		HISI_FB_ERR("fb%d, not support!", hisifd->index);
+	}
+}
+
+void single_frame_update(struct hisi_fb_data_type *hisifd)
+{
+	char __iomem *ldi_base = NULL;
+	struct hisi_panel_info *pinfo = NULL;
+
+	BUG_ON(hisifd == NULL);
+	pinfo = &(hisifd->panel_info);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		ldi_base = hisifd->dss_base + DSS_LDI0_OFFSET;
+		if (is_mipi_cmd_panel(hisifd)) {
+			set_reg(ldi_base + LDI_FRM_MSK_UP, 0x1, 1, 0);
+			set_reg(ldi_base + LDI_CTRL, 0x1, 1, 0);
+		} else {
+			set_reg(ldi_base + LDI_CTRL, 0x1, 1, 0);
+		}
+
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		ldi_base = hisifd->dss_base + DSS_LDI1_OFFSET;
+
+		if (is_mipi_cmd_panel(hisifd)) {
+			set_reg(ldi_base + LDI_FRM_MSK_UP, 0x1, 1, 0);
+			set_reg(ldi_base + LDI_CTRL, 0x1, 1, 0);
+		} else {
+			set_reg(ldi_base + LDI_CTRL, 0x1, 1, 0);
+		}
+	} else {
+		;
+	}
+}
+
+void dpe_interrupt_clear(struct hisi_fb_data_type *hisifd)
+{
+	char __iomem *dss_base = 0;
+	uint32_t clear = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	dss_base = hisifd->dss_base;
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		clear = ~0;
+		outp32(dss_base + GLB_CPU_PDP_INTS, clear);
+		outp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS, clear);
+		outp32(dss_base + DSS_DPP_OFFSET + DPP_INTS, clear);
+
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_MCTL_INTS, clear);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_WCH0_INTS, clear);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_WCH1_INTS, clear);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH0_INTS, clear);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH1_INTS, clear);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH2_INTS, clear);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH3_INTS, clear);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH4_INTS, clear);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH5_INTS, clear);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH6_INTS, clear);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH7_INTS, clear);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_DSS_GLB_INTS, clear);
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		clear = ~0;
+		outp32(dss_base + GLB_CPU_SDP_INTS, clear);
+		outp32(dss_base + DSS_LDI1_OFFSET + LDI_CPU_ITF_INTS, clear);
+	} else if (hisifd->index == AUXILIARY_PANEL_IDX) {
+		clear = ~0;
+		outp32(dss_base + GLB_CPU_OFF_INTS, clear);
+	} else {
+		HISI_FB_ERR("fb%d, not support this device!\n", hisifd->index);
+	}
+
+}
+
+void dpe_interrupt_unmask(struct hisi_fb_data_type *hisifd)
+{
+	char __iomem *dss_base = 0;
+	uint32_t unmask = 0;
+	struct hisi_panel_info *pinfo = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	pinfo = &(hisifd->panel_info);
+	dss_base = hisifd->dss_base;
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		unmask = ~0;
+		/* unmask &= ~(BIT_DPP_INTS | BIT_ITF0_INTS | BIT_DSS_GLB_INTS | BIT_MMU_IRPT_NS); */
+		unmask &= ~(BIT_DPP_INTS | BIT_ITF0_INTS | BIT_MMU_IRPT_NS);
+		outp32(dss_base + GLB_CPU_PDP_INT_MSK, unmask);
+
+		unmask = ~0;
+		if (is_mipi_cmd_panel(hisifd)) {
+			unmask &=
+			    ~(BIT_LCD_TE0_PIN | BIT_VACTIVE0_START |
+			      BIT_VACTIVE0_END | BIT_FRM_END);
+		} else {
+			unmask &=
+			    ~(BIT_VSYNC | BIT_VACTIVE0_START | BIT_VACTIVE0_END
+			      | BIT_FRM_END);
+		}
+		outp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK,
+		       unmask);
+
+		unmask = ~0;
+		/* unmask &= ~(BIT_CE_END_IND | BIT_BACKLIGHT_INTP); */
+		if ((pinfo->acm_ce_support == 1)
+		    && HISI_DSS_SUPPORT_DPP_MODULE_BIT(DPP_MODULE_ACE))
+			unmask &= ~(BIT_CE_END_IND);
+		if (pinfo->hiace_support == 1)
+			unmask &= ~(BIT_HIACE_IND);
+
+		outp32(dss_base + DSS_DPP_OFFSET + DPP_INT_MSK, unmask);
+
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		unmask = ~0;
+		/* unmask &= ~(BIT_SDP_ITF1_INTS  | BIT_SDP_DSS_GLB_INTS | BIT_SDP_MMU_IRPT_NS); */
+		unmask &= ~(BIT_SDP_ITF1_INTS | BIT_SDP_MMU_IRPT_NS);
+		outp32(dss_base + GLB_CPU_SDP_INT_MSK, unmask);
+
+		unmask = ~0;
+		unmask &= ~(BIT_VSYNC | BIT_VACTIVE0_START | BIT_VACTIVE0_END);
+		outp32(dss_base + DSS_LDI1_OFFSET + LDI_CPU_ITF_INT_MSK,
+		       unmask);
+	} else if (hisifd->index == AUXILIARY_PANEL_IDX) {
+		unmask = ~0;
+		unmask &=
+		    ~(BIT_OFF_WCH0_INTS | BIT_OFF_WCH1_INTS |
+		      BIT_OFF_WCH0_WCH1_FRM_END_INT | BIT_OFF_MMU_IRPT_NS);
+		outp32(dss_base + GLB_CPU_OFF_INT_MSK, unmask);
+
+		unmask = ~0;
+		unmask &= ~(BIT_OFF_CAM_WCH2_FRMEND_INTS);
+		outp32(dss_base + GLB_CPU_OFF_CAM_INT_MSK, unmask);
+	} else {
+		HISI_FB_ERR("fb%d, not support this device!\n", hisifd->index);
+	}
+
+}
+
+void dpe_interrupt_mask(struct hisi_fb_data_type *hisifd)
+{
+	char __iomem *dss_base = 0;
+	uint32_t mask = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	dss_base = hisifd->dss_base;
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		mask = ~0;
+		outp32(dss_base + GLB_CPU_PDP_INT_MSK, mask);
+		outp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK, mask);
+		outp32(dss_base + DSS_DPP_OFFSET + DPP_INT_MSK, mask);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_DSS_GLB_INT_MSK, mask);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_MCTL_INT_MSK, mask);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_WCH0_INT_MSK, mask);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_WCH1_INT_MSK, mask);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH0_INT_MSK, mask);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH1_INT_MSK, mask);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH2_INT_MSK, mask);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH3_INT_MSK, mask);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH4_INT_MSK, mask);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH5_INT_MSK, mask);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH6_INT_MSK, mask);
+		outp32(dss_base + DSS_DBG_OFFSET + DBG_RCH7_INT_MSK, mask);
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		mask = ~0;
+		outp32(dss_base + GLB_CPU_SDP_INT_MSK, mask);
+		outp32(dss_base + DSS_LDI1_OFFSET + LDI_CPU_ITF_INT_MSK, mask);
+	} else if (hisifd->index == AUXILIARY_PANEL_IDX) {
+		mask = ~0;
+		outp32(dss_base + GLB_CPU_OFF_INT_MSK, mask);
+		outp32(dss_base + GLB_CPU_OFF_CAM_INT_MSK, mask);
+	} else {
+		HISI_FB_ERR("fb%d, not support this device!\n", hisifd->index);
+	}
+
+}
+
+void ldi_data_gate(struct hisi_fb_data_type *hisifd, bool enble)
+{
+	char __iomem *ldi_base = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	if (!is_mipi_cmd_panel(hisifd)) {
+		hisifd->ldi_data_gate_en = (enble ? 1 : 0);
+		return;
+	}
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		ldi_base = hisifd->dss_base + DSS_LDI0_OFFSET;
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		ldi_base = hisifd->dss_base + DSS_LDI1_OFFSET;
+	} else {
+		HISI_FB_ERR("fb%d, not support!", hisifd->index);
+		return;
+	}
+
+	if (g_ldi_data_gate_en == 1) {
+		hisifd->ldi_data_gate_en = (enble ? 1 : 0);
+		set_reg(ldi_base + LDI_CTRL, (enble ? 0x1 : 0x0), 1, 2);
+	} else {
+		hisifd->ldi_data_gate_en = 0;
+		set_reg(ldi_base + LDI_CTRL, 0x0, 1, 2);
+	}
+
+	HISI_FB_DEBUG("ldi_data_gate_en=%d!\n", hisifd->ldi_data_gate_en);
+}
+
+/* dpp csc config */
+#define CSC_ROW	(3)
+#define CSC_COL	(5)
+
+/*
+ ** Rec.601 for Computer
+ ** [ p00 p01 p02 cscidc2 cscodc2 ]
+ ** [ p10 p11 p12 cscidc1 cscodc1 ]
+ ** [ p20 p21 p22 cscidc0 cscodc0 ]
+ */
+static int CSC10B_YUV2RGB709_WIDE_MPREC0[CSC_ROW][CSC_COL] = {
+	{0x400, 0x000, 0x64d, 0x000, 0x000},
+	{0x400, 0x1f40, 0x1e21, 0x5fe, 0x000},
+	{0x400, 0x76c, 0x000, 0x5fe, 0x000}
+};
+
+static int CSC10B_RGB2YUV709_WIDE_MPREC2[CSC_ROW][CSC_COL] = {
+	{0x367, 0xb71, 0x128, 0x000, 0x000},
+	{0x1e2b, 0x19d5, 0x800, 0x000, 0x202},
+	{0x800, 0x18bc, 0x1f44, 0x000, 0x202},
+};
+
+static void init_csc10b(struct hisi_fb_data_type *hisifd,
+			char __iomem *dpp_csc10b_base)
+{
+	int (*csc_coe)[CSC_COL];
+
+	if (hisifd == NULL || dpp_csc10b_base == NULL) {
+		HISI_FB_ERR("hisifd or dpp_csc10b_base is NULL!\n");
+		return;
+	}
+
+	if (dpp_csc10b_base ==
+	    (hisifd->dss_base + DSS_DPP_CSC_RGB2YUV10B_OFFSET)) {
+		csc_coe = CSC10B_RGB2YUV709_WIDE_MPREC2;
+		outp32(dpp_csc10b_base + CSC10B_MPREC, 0x2);
+	} else if (dpp_csc10b_base ==
+		   (hisifd->dss_base + DSS_DPP_CSC_YUV2RGB10B_OFFSET)) {
+		csc_coe = CSC10B_YUV2RGB709_WIDE_MPREC0;
+		outp32(dpp_csc10b_base + CSC10B_MPREC, 0x0);
+	} else {
+		return;
+	}
+
+	outp32(dpp_csc10b_base + CSC10B_IDC0, csc_coe[2][3]);
+	outp32(dpp_csc10b_base + CSC10B_IDC1, csc_coe[1][3]);
+	outp32(dpp_csc10b_base + CSC10B_IDC2, csc_coe[0][3]);
+	outp32(dpp_csc10b_base + CSC10B_ODC0, csc_coe[2][4]);
+	outp32(dpp_csc10b_base + CSC10B_ODC1, csc_coe[1][4]);
+	outp32(dpp_csc10b_base + CSC10B_ODC2, csc_coe[0][4]);
+	outp32(dpp_csc10b_base + CSC10B_P00, csc_coe[0][0]);
+	outp32(dpp_csc10b_base + CSC10B_P01, csc_coe[0][1]);
+	outp32(dpp_csc10b_base + CSC10B_P02, csc_coe[0][2]);
+	outp32(dpp_csc10b_base + CSC10B_P10, csc_coe[1][0]);
+	outp32(dpp_csc10b_base + CSC10B_P11, csc_coe[1][1]);
+	outp32(dpp_csc10b_base + CSC10B_P12, csc_coe[1][2]);
+	outp32(dpp_csc10b_base + CSC10B_P20, csc_coe[2][0]);
+	outp32(dpp_csc10b_base + CSC10B_P21, csc_coe[2][1]);
+	outp32(dpp_csc10b_base + CSC10B_P22, csc_coe[2][2]);
+
+	outp32(dpp_csc10b_base + CSC10B_MODULE_EN, 0x1);
+}
+
+void init_dpp_csc(struct hisi_fb_data_type *hisifd)
+{
+	struct hisi_panel_info *pinfo = NULL;
+
+	if (hisifd == NULL) {
+		HISI_FB_ERR("init_dpp_csc hisifd is NULL!\n");
+		return;
+	}
+
+	pinfo = &(hisifd->panel_info);
+
+	if (pinfo->acm_support || pinfo->arsr1p_sharpness_support
+	    || pinfo->post_scf_support) {
+		init_csc10b(hisifd,
+			    hisifd->dss_base + DSS_DPP_CSC_RGB2YUV10B_OFFSET);
+		init_csc10b(hisifd,
+			    hisifd->dss_base + DSS_DPP_CSC_YUV2RGB10B_OFFSET);
+
+		set_reg(hisifd->dss_base + DSS_DPP_BITEXT0_OFFSET +
+			BIT_EXT0_CTL, 1, 1, 0);
+	}
+}
+
+void init_acm(struct hisi_fb_data_type *hisifd)
+{
+	char __iomem *acm_base = NULL;
+	struct hisi_panel_info *pinfo = NULL;
+
+	if (hisifd == NULL) {
+		HISI_FB_DEBUG("init_acm hisifd is NULL!\n");
+		return;
+	}
+
+	pinfo = &(hisifd->panel_info);
+	acm_base = hisifd->dss_base + DSS_DPP_ACM_OFFSET;
+
+	if (pinfo->acm_support != 1) {
+		outp32(acm_base + ACM_MEM_CTRL, 0x4);
+		HISI_FB_DEBUG("fb%d, not support acm!\n", hisifd->index);
+		return;
+	}
+	/* not support */
+	outp32(acm_base + ACM_MEM_CTRL, 0x4);
+}
+
+void init_igm_gmp_xcc_gm(struct hisi_fb_data_type *hisifd)
+{
+	char __iomem *dpp_base = NULL;
+	char __iomem *lcp_base = NULL;
+	char __iomem *gamma_base = NULL;
+
+	if (hisifd == NULL) {
+		HISI_FB_ERR("init_degmma_xcc_gmp hisifd is NULL!\n");
+		return;
+	}
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		dpp_base = hisifd->dss_base + DSS_DPP_OFFSET;
+		lcp_base = hisifd->dss_base + DSS_DPP_LCP_OFFSET;
+		gamma_base = hisifd->dss_base + DSS_DPP_GAMA_OFFSET;
+	} else {
+		HISI_FB_ERR("fb%d, not support!\n", hisifd->index);
+		return;
+	}
+	outp32(lcp_base + LCP_DEGAMA_MEM_CTRL, 0x4);
+	outp32(lcp_base + LCP_GMP_MEM_CTRL, 0x4);
+	outp32(gamma_base + GAMA_MEM_CTRL, 0x4);
+}
diff --git a/drivers/video/fbdev/hisi/dss/hisi_dss.h b/drivers/video/fbdev/hisi/dss/hisi_dss.h
new file mode 100755
index 000000000000..8bcb1192c64e
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_dss.h
@@ -0,0 +1,493 @@
+/* include/linux/hisi_dss.h
+ *
+ * Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#ifndef _HISI_DSS_H_
+#define _HISI_DSS_H_
+
+#include <linux/types.h>
+#include <linux/fb.h>
+
+#define HISIFB_IOCTL_MAGIC 'M'
+
+#define FB_ACCEL_HI62xx     0x1
+#define FB_ACCEL_HI363x     0x2
+#define FB_ACCEL_HI365x     0x4
+#define FB_ACCEL_HI625x     0x8
+#define FB_ACCEL_HI366x     0x10
+#define FB_ACCEL_PLATFORM_TYPE_FPGA     0x10000000
+#define FB_ACCEL_PLATFORM_TYPE_ASIC     0x20000000
+
+#define HISIFB_LCD_DIRTY_REGION_INFO_GET _IOW(HISIFB_IOCTL_MAGIC, 801, struct lcd_dirty_region_info)
+#define HISIFB_PLATFORM_TYPE_GET _IOW(HISIFB_IOCTL_MAGIC, 802, int)
+
+#define HISIFB_VSYNC_CTRL _IOW(HISIFB_IOCTL_MAGIC, 0x02, unsigned int)
+#define HISIFB_DSS_CLK_RATE_SET _IOW(HISIFB_IOCTL_MAGIC, 0x04, struct dss_clk_rate)
+#define HISIFB_DIRTY_REGION_UPDT_SET _IOW(HISIFB_IOCTL_MAGIC, 0x06, int)
+#define HISIFB_DSS_MMBUF_ALLOC _IOW(HISIFB_IOCTL_MAGIC, 0x08, struct dss_mmbuf)
+#define HISIFB_DSS_MMBUF_FREE _IOW(HISIFB_IOCTL_MAGIC, 0x09, struct dss_mmbuf)
+#define HISIFB_DSS_VOLTAGE_GET _IOW(HISIFB_IOCTL_MAGIC, 0x10, struct dss_clk_rate)
+#define HISIFB_DSS_VOLTAGE_SET _IOW(HISIFB_IOCTL_MAGIC, 0x11, struct dss_clk_rate)
+
+#define HISIFB_OV_ONLINE_PLAY _IOW(HISIFB_IOCTL_MAGIC, 0x21, struct dss_overlay)
+
+#define HISIFB_IDLE_IS_ALLOWED  _IOW(HISIFB_IOCTL_MAGIC, 0x42, int)
+
+#ifndef BIT
+#define BIT(x)  (1<<(x))
+#endif
+
+/* for fb0 fb1 fb2 and so on */
+#define PRIMARY_PANEL_IDX	(0)
+#define EXTERNAL_PANEL_IDX	(1)
+#define AUXILIARY_PANEL_IDX	(2)
+
+/* lcd fps scence */
+#define LCD_FPS_SCENCE_NORMAL   (0)
+#define LCD_FPS_SCENCE_IDLE     BIT(0)
+#define LCD_FPS_SCENCE_VIDEO    BIT(1)
+#define LCD_FPS_SCENCE_GAME     BIT(2)
+#define LCD_FPS_SCENCE_WEB      BIT(3)
+#define LCD_FPS_SCENCE_EBOOK    BIT(4)
+
+#define DSS_WCH_MAX  (2)
+
+/* for YUV */
+#define MAX_PLANES	(3)
+
+enum dss_wb_compose_type {
+	DSS_WB_COMPOSE_PRIMARY = 0,
+	DSS_WB_COMPOSE_COPYBIT,
+	DSS_WB_COMPOSE_TYPE_MAX,
+};
+
+enum hisi_fb_pixel_format {
+	HISI_FB_PIXEL_FORMAT_RGB_565 = 0,
+	HISI_FB_PIXEL_FORMAT_RGBX_4444,
+	HISI_FB_PIXEL_FORMAT_RGBA_4444,
+	HISI_FB_PIXEL_FORMAT_RGBX_5551,
+	HISI_FB_PIXEL_FORMAT_RGBA_5551,
+	HISI_FB_PIXEL_FORMAT_RGBX_8888,
+	HISI_FB_PIXEL_FORMAT_RGBA_8888,
+
+	HISI_FB_PIXEL_FORMAT_BGR_565,
+	HISI_FB_PIXEL_FORMAT_BGRX_4444,
+	HISI_FB_PIXEL_FORMAT_BGRA_4444,
+	HISI_FB_PIXEL_FORMAT_BGRX_5551,
+	HISI_FB_PIXEL_FORMAT_BGRA_5551,
+	HISI_FB_PIXEL_FORMAT_BGRX_8888,
+	HISI_FB_PIXEL_FORMAT_BGRA_8888,
+
+	HISI_FB_PIXEL_FORMAT_YUV_422_I,
+
+	/* YUV Semi-planar */
+	HISI_FB_PIXEL_FORMAT_YCbCr_422_SP,	/* NV16 */
+	HISI_FB_PIXEL_FORMAT_YCrCb_422_SP,
+	HISI_FB_PIXEL_FORMAT_YCbCr_420_SP,
+	HISI_FB_PIXEL_FORMAT_YCrCb_420_SP,	/* NV21 */
+
+	/* YUV Planar */
+	HISI_FB_PIXEL_FORMAT_YCbCr_422_P,
+	HISI_FB_PIXEL_FORMAT_YCrCb_422_P,
+	HISI_FB_PIXEL_FORMAT_YCbCr_420_P,
+	HISI_FB_PIXEL_FORMAT_YCrCb_420_P,	/* HISI_FB_PIXEL_FORMAT_YV12 */
+
+	/* YUV Package */
+	HISI_FB_PIXEL_FORMAT_YUYV_422_Pkg,
+	HISI_FB_PIXEL_FORMAT_UYVY_422_Pkg,
+	HISI_FB_PIXEL_FORMAT_YVYU_422_Pkg,
+	HISI_FB_PIXEL_FORMAT_VYUY_422_Pkg,
+	HISI_FB_PIXEL_FORMAT_MAX,
+};
+
+enum hisi_fb_blending {
+	HISI_FB_BLENDING_NONE = 0,
+	HISI_FB_BLENDING_PREMULT = 1,
+	HISI_FB_BLENDING_COVERAGE = 2,
+	HISI_FB_BLENDING_MAX = 3,
+};
+
+enum hisi_fb_transform {
+	HISI_FB_TRANSFORM_NOP = 0x0,
+	/* flip source image horizontally (around the vertical axis) */
+	HISI_FB_TRANSFORM_FLIP_H = 0x01,
+	/* flip source image vertically (around the horizontal axis) */
+	HISI_FB_TRANSFORM_FLIP_V = 0x02,
+	/* rotate source image 90 degrees clockwise */
+	HISI_FB_TRANSFORM_ROT_90 = 0x04,
+	/* rotate source image 180 degrees */
+	HISI_FB_TRANSFORM_ROT_180 = 0x03,
+	/* rotate source image 270 degrees clockwise */
+	HISI_FB_TRANSFORM_ROT_270 = 0x07,
+};
+
+enum dss_csc_mode {
+	DSS_CSC_601_WIDE = 0,
+	DSS_CSC_601_NARROW,
+	DSS_CSC_709_WIDE,
+	DSS_CSC_709_NARROW,
+	DSS_CSC_MOD_MAX,
+};
+
+enum dss_afbc_scramble_mode {
+	DSS_AFBC_SCRAMBLE_NONE = 0,
+	DSS_AFBC_SCRAMBLE_MODE1,
+	DSS_AFBC_SCRAMBLE_MODE2,
+	DSS_AFBC_SCRAMBLE_MODE3,
+	DSS_AFBC_SCRAMBLE_MODE_MAX,
+};
+
+enum dss_chn_idx {
+	DSS_RCHN_NONE = -1,
+	DSS_RCHN_D2 = 0,
+	DSS_RCHN_D3,
+	DSS_RCHN_V0,
+	DSS_RCHN_G0,
+	DSS_RCHN_V1,
+	DSS_RCHN_G1,
+	DSS_RCHN_D0,
+	DSS_RCHN_D1,
+
+	DSS_WCHN_W0,
+	DSS_WCHN_W1,
+
+	DSS_CHN_MAX,
+
+	DSS_RCHN_V2 = DSS_CHN_MAX,
+	DSS_WCHN_W2,
+
+	DSS_COPYBIT_MAX,
+};
+
+enum dss_ovl_idx {
+	DSS_OVL0 = 0,
+	DSS_OVL1,
+	DSS_OVL2,
+	DSS_OVL3,
+	DSS_OVL_IDX_MAX,
+};
+
+/* dss capability priority description */
+#define CAP_1D_SHARPNESS	BIT(13)
+#define CAP_2D_SHARPNESS	BIT(12)
+#define CAP_TILE	BIT(11)
+#define CAP_AFBCD	BIT(10)
+#define CAP_AFBCE	BIT(9)
+#define CAP_YUV_DEINTERLACE	BIT(8)
+#define CAP_YUV_PLANAR	BIT(7)
+#define CAP_YUV_SEMI_PLANAR	BIT(6)
+#define CAP_YUV_PACKAGE	BIT(5)
+#define CAP_SCL	BIT(4)
+#define CAP_ROT	BIT(3)
+#define CAP_PURE_COLOR	BIT(2)
+#define CAP_DIM	BIT(1)
+#define CAP_BASE	BIT(0)
+
+/*this head file to save the structs that both ade and dss will use
+**note: if the left_align is 8,right_align is 8,and w_min is larger than 802,then w_min should be set to 808,
+**make sure that it is 8 align,if w_min is set to 802,there will be an error.left_align,right_align,top_align
+**bottom_align,w_align,h_align,w_min and h_min's valid value should be larger than 0,top_start and bottom_start
+**maybe equal to 0. if it's not surpport partial update, these value should set to invalid value(-1).
+*/
+typedef struct lcd_dirty_region_info {
+	int left_align;
+	int right_align;
+	int top_align;
+	int bottom_align;
+
+	int w_align;
+	int h_align;
+	int w_min;
+	int h_min;
+
+	int top_start;
+	int bottom_start;
+} lcd_dirty_region_info_t;
+
+typedef struct dss_rect {
+	int32_t x;
+	int32_t y;
+	int32_t w;
+	int32_t h;
+} dss_rect_t;
+
+typedef struct dss_rect_ltrb {
+	int32_t left;
+	int32_t top;
+	int32_t right;
+	int32_t bottom;
+} dss_rect_ltrb_t;
+
+typedef struct dss_mmbuf {
+	uint32_t addr;
+	int32_t size;
+} dss_mmbuf_t;
+
+typedef struct dss_img {
+	uint32_t format;
+	uint32_t width;
+	uint32_t height;
+	uint32_t bpp;		/* bytes per pixel */
+	uint32_t buf_size;
+	uint32_t stride;
+	uint32_t stride_plane1;
+	uint32_t stride_plane2;
+	uint64_t phy_addr;
+	uint64_t vir_addr;
+	uint32_t offset_plane1;
+	uint32_t offset_plane2;
+
+	uint64_t afbc_header_addr;
+	uint64_t afbc_payload_addr;
+	uint32_t afbc_header_stride;
+	uint32_t afbc_payload_stride;
+	uint32_t afbc_scramble_mode;
+	uint32_t mmbuf_base;
+	uint32_t mmbuf_size;
+
+	uint32_t mmu_enable;
+	uint32_t csc_mode;
+	uint32_t secure_mode;
+	int32_t shared_fd;
+	uint32_t reserved0;
+} dss_img_t;
+
+typedef struct dss_block_info {
+	int32_t first_tile;
+	int32_t last_tile;
+	uint32_t acc_hscl;
+	uint32_t h_ratio;
+	uint32_t v_ratio;
+	uint32_t h_ratio_arsr2p;
+	uint32_t arsr2p_left_clip;
+	uint32_t both_vscfh_arsr2p_used;
+	dss_rect_t arsr2p_in_rect;
+	uint32_t arsr2p_src_x;
+	uint32_t arsr2p_src_y;
+	uint32_t arsr2p_dst_x;
+	uint32_t arsr2p_dst_y;
+	uint32_t arsr2p_dst_w;
+	int32_t h_v_order;
+} dss_block_info_t;
+
+typedef struct dss_layer {
+	dss_img_t img;
+	dss_rect_t src_rect;
+	dss_rect_t src_rect_mask;
+	dss_rect_t dst_rect;
+	uint32_t transform;
+	int32_t blending;
+	uint32_t glb_alpha;
+	uint32_t color;		/* background color or dim color */
+	int32_t layer_idx;
+	int32_t chn_idx;
+	uint32_t need_cap;
+	int32_t acquire_fence;
+
+	dss_block_info_t block_info;
+} dss_layer_t;
+
+typedef struct dss_wb_layer {
+	dss_img_t dst;
+	dss_rect_t src_rect;
+	dss_rect_t dst_rect;
+	uint32_t transform;
+	int32_t chn_idx;
+	uint32_t need_cap;
+	uint32_t reserved0;
+
+	int32_t acquire_fence;
+	int32_t release_fence;
+} dss_wb_layer_t;
+
+/*
+ ** dss error status
+ */
+#define DSS_PDP_LDI_UNDERFLOW		BIT(0)
+#define DSS_SDP_LDI_UNDERFLOW		BIT(1)
+#define DSS_PDP_SMMU_ERR			BIT(2)
+#define DSS_SDP_SMMU_ERR			BIT(3)
+
+/*
+ ** crc enable status
+ */
+enum dss_crc_enable_status {
+	DSS_CRC_NONE = 0,
+	DSS_CRC_OV_EN = 1,
+	DSS_CRC_LDI_EN,
+	DSS_CRC_SUM_EN,
+};
+
+/*
+ ** sec enable status
+ */
+enum dss_sec_enable_status {
+	DSS_SEC_STOP = 0,
+	DSS_SEC_RUN = 1,
+};
+
+typedef struct dss_crc_info {
+	uint32_t crc_ov_result;
+	uint32_t crc_ldi_result;
+	uint32_t crc_sum_result;
+	uint32_t crc_ov_frm;
+	uint32_t crc_ldi_frm;
+	uint32_t crc_sum_frm;
+
+	uint32_t err_status;
+	uint32_t reserved0;
+} dss_crc_info_t;
+
+enum dss_to_be_continued_type {
+	DSS_LAYER_SERIAL_COMPOSE = 0,
+	DSS_LAYER_PARALLEL_COMPOSE = 1,
+};
+
+/* Max multi-src channel number of the DSS. */
+#define MAX_DSS_SRC_NUM	(7)
+#define MAX_DSS_DST_NUM	(2)
+
+#define HISI_DSS_OV_BLOCK_NUMS	(23)
+
+typedef struct dss_overlay_block {
+	dss_layer_t layer_infos[MAX_DSS_SRC_NUM];
+	dss_rect_t ov_block_rect;
+	uint32_t layer_nums;
+	uint32_t reserved0;
+} dss_overlay_block_t;
+
+typedef struct dss_overlay {
+	dss_wb_layer_t wb_layer_infos[MAX_DSS_DST_NUM];
+	dss_rect_t wb_ov_rect;
+	uint32_t wb_layer_nums;
+	uint32_t wb_compose_type;
+
+	uint64_t ov_block_infos_ptr;
+	uint32_t ov_block_nums;
+	int32_t ovl_idx;
+	uint32_t wb_enable;
+	uint32_t frame_no;
+
+	dss_rect_t dirty_rect;
+
+	struct dss_rect res_updt_rect;
+
+	dss_crc_info_t crc_info;
+	int32_t crc_enable_status;
+	uint32_t sec_enable_status;
+
+	uint32_t to_be_continued;
+	int32_t release_fence;
+} dss_overlay_t;
+
+typedef struct dss_clk_rate {
+	uint64_t dss_pri_clk_rate;
+	uint64_t dss_pclk_dss_rate;
+	uint64_t dss_pclk_pctrl_rate;
+	uint32_t dss_voltage_value;
+} dss_clk_rate_t;
+
+typedef struct ce_algorithm_parameter {
+	int iDiffMaxTH;
+	int iDiffMinTH;
+	int iAlphaMinTH;
+	int iFlatDiffTH;
+	int iBinDiffMaxTH;
+
+	int iDarkPixelMinTH;
+	int iDarkPixelMaxTH;
+	int iDarkAvePixelMinTH;
+	int iDarkAvePixelMaxTH;
+	int iWhitePixelTH;
+	int fweight;
+	int fDarkRatio;
+	int fWhiteRatio;
+
+	int iDarkPixelTH;
+	int fDarkSlopeMinTH;
+	int fDarkSlopeMaxTH;
+	int fDarkRatioMinTH;
+	int fDarkRatioMaxTH;
+
+	int iBrightPixelTH;
+	int fBrightSlopeMinTH;
+	int fBrightSlopeMaxTH;
+	int fBrightRatioMinTH;
+	int fBrightRatioMaxTH;
+
+	int iZeroPos0MaxTH;
+	int iZeroPos1MaxTH;
+
+	int iDarkFMaxTH;
+	int iDarkFMinTH;
+	int iPos0MaxTH;
+	int iPos0MinTH;
+
+	int fKeepRatio;
+} ce_algorithm_parameter_t;
+
+typedef struct ce_parameter {
+	int width;
+	int height;
+	int hist_mode;
+	int mode;
+	int result;
+	uint32_t reserved0;
+	uint32_t *histogram;
+	uint8_t *lut_table;
+	void *service;
+	ce_algorithm_parameter_t ce_alg_param;
+} ce_parameter_t;
+
+typedef struct hiace_alg_parameter {
+	int iGlobalHistBlackPos;
+	int iGlobalHistWhitePos;
+	int iGlobalHistBlackWeight;
+	int iGlobalHistWhiteWeight;
+	int iGlobalHistZeroCutRatio;
+	int iGlobalHistSlopeCutRatio;
+
+	char Classifieresult[1024];
+	int iResultLen;
+
+	int iDoLCE;
+	int iDoSRE;
+	int iDoAPLC;
+
+	int iLaSensorSREOnTH;
+	int iWidth;
+	int iHeight;
+	int bitWidth;
+	int iMode;
+	int iLevel;
+	int ilhist_sft;
+
+	int iMaxLcdLuminance;
+	int iMinLcdLuminance;
+	int iMaxBackLight;
+	int iMinBackLight;
+	int iAmbientLight;
+	int iBackLight;
+	long lTimestamp;
+
+	char chCfgName[512];
+} hiace_alg_parameter_t;
+
+typedef struct hiace_interface_set {
+	int result;
+	unsigned int *lut;
+	int backlight;
+} hiace_interface_set_t;
+
+#endif /*_HISI_DSS_H_*/
diff --git a/drivers/video/fbdev/hisi/dss/hisi_dss_regs_hi3660.h b/drivers/video/fbdev/hisi/dss/hisi_dss_regs_hi3660.h
new file mode 100755
index 000000000000..a5490bb63dc3
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_dss_regs_hi3660.h
@@ -0,0 +1,3164 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+#ifndef HISI_DSS_REGS_H
+#define HISI_DSS_REGS_H
+
+#include "hisi_fb.h"
+
+/* MACROS */
+#define DSS_WIDTH(width)	((width) - 1)
+#define DSS_HEIGHT(height)	((height) - 1)
+
+#define RES_540P	(960 * 540)
+#define RES_720P	(1280 * 720)
+#define RES_1080P	(1920 * 1080)
+#define RES_1200P	(1920 * 1200)
+#define RES_1440P	(2560 * 1440)
+#define RES_1600P	(2560 * 1600)
+#define RES_4K_PHONE	(3840 * 2160)
+#define RES_4K_PAD	(3840 * 2400)
+
+#define DFC_MAX_CLIP_NUM	(31)
+
+/* for DFS */
+/* 1480 * 144bits */
+#define DFS_TIME	(80)
+#define DFS_TIME_MIN	(50)
+#define DFS_TIME_MIN_4K	(10)
+#define DBUF0_DEPTH	(1408)
+#define DBUF1_DEPTH	(512)
+#define DBUF_WIDTH_BIT	(144)
+
+#define GET_THD_RQOS_IN(max_depth)	((max_depth) * 10 / 100)
+#define GET_THD_RQOS_OUT(max_depth)	((max_depth) * 30 / 100)
+#define GET_THD_WQOS_IN(max_depth)	((max_depth) * 95 / 100)
+#define GET_THD_WQOS_OUT(max_depth)	((max_depth) * 70 / 100)
+#define GET_THD_CG_IN(max_depth)	((max_depth) -1)
+#define GET_THD_CG_OUT(max_depth)	((max_depth) * 70 / 100)
+#define GET_FLUX_REQ_IN(max_depth)	((max_depth) * 50 / 100)
+#define GET_FLUX_REQ_OUT(max_depth)	((max_depth) * 90 / 100)
+#define GET_THD_OTHER_DFS_CG_HOLD(max_depth)	(0x20)
+#define GET_THD_OTHER_WR_WAIT(max_depth)	((max_depth) * 90 / 100)
+
+#define GET_RDMA_ROT_HQOS_ASSERT_LEV(max_depth)	((max_depth) * 30 /100)
+#define GET_RDMA_ROT_HQOS_REMOVE_LEV(max_depth)	((max_depth)* 60 / 100)
+
+enum lcd_orientation {
+	LCD_LANDSCAPE = 0,
+	LCD_PORTRAIT,
+};
+
+enum lcd_format {
+	LCD_RGB888 = 0,
+	LCD_RGB101010,
+	LCD_RGB565,
+};
+
+enum lcd_rgb_order {
+	LCD_RGB = 0,
+	LCD_BGR,
+};
+
+enum dss_addr {
+	DSS_ADDR_PLANE0 = 0,
+	DSS_ADDR_PLANE1,
+	DSS_ADDR_PLANE2,
+};
+
+enum dss_transform {
+	DSS_TRANSFORM_NOP = 0x0,
+	DSS_TRANSFORM_FLIP_H = 0x01,
+	DSS_TRANSFORM_FLIP_V = 0x02,
+	DSS_TRANSFORM_ROT = 0x04,
+};
+
+enum dss_dfc_format {
+	DFC_PIXEL_FORMAT_RGB_565 = 0,
+	DFC_PIXEL_FORMAT_XRGB_4444,
+	DFC_PIXEL_FORMAT_ARGB_4444,
+	DFC_PIXEL_FORMAT_XRGB_5551,
+	DFC_PIXEL_FORMAT_ARGB_5551,
+	DFC_PIXEL_FORMAT_XRGB_8888,
+	DFC_PIXEL_FORMAT_ARGB_8888,
+	DFC_PIXEL_FORMAT_BGR_565,
+	DFC_PIXEL_FORMAT_XBGR_4444,
+	DFC_PIXEL_FORMAT_ABGR_4444,
+	DFC_PIXEL_FORMAT_XBGR_5551,
+	DFC_PIXEL_FORMAT_ABGR_5551,
+	DFC_PIXEL_FORMAT_XBGR_8888,
+	DFC_PIXEL_FORMAT_ABGR_8888,
+
+	DFC_PIXEL_FORMAT_YUV444,
+	DFC_PIXEL_FORMAT_YVU444,
+	DFC_PIXEL_FORMAT_YUYV422,
+	DFC_PIXEL_FORMAT_YVYU422,
+	DFC_PIXEL_FORMAT_VYUY422,
+	DFC_PIXEL_FORMAT_UYVY422,
+};
+
+enum dss_dma_format {
+	DMA_PIXEL_FORMAT_RGB_565 = 0,
+	DMA_PIXEL_FORMAT_ARGB_4444,
+	DMA_PIXEL_FORMAT_XRGB_4444,
+	DMA_PIXEL_FORMAT_ARGB_5551,
+	DMA_PIXEL_FORMAT_XRGB_5551,
+	DMA_PIXEL_FORMAT_ARGB_8888,
+	DMA_PIXEL_FORMAT_XRGB_8888,
+
+	DMA_PIXEL_FORMAT_RESERVED0,
+
+	DMA_PIXEL_FORMAT_YUYV_422_Pkg,
+	DMA_PIXEL_FORMAT_YUV_420_SP_HP,
+	DMA_PIXEL_FORMAT_YUV_420_P_HP,
+	DMA_PIXEL_FORMAT_YUV_422_SP_HP,
+	DMA_PIXEL_FORMAT_YUV_422_P_HP,
+	DMA_PIXEL_FORMAT_AYUV_4444,
+};
+
+enum dss_buf_format {
+	DSS_BUF_LINEAR = 0,
+	DSS_BUF_TILE,
+};
+
+enum dss_blend_mode {
+	DSS_BLEND_CLEAR = 0,
+	DSS_BLEND_SRC,
+	DSS_BLEND_DST,
+	DSS_BLEND_SRC_OVER_DST,
+	DSS_BLEND_DST_OVER_SRC,
+	DSS_BLEND_SRC_IN_DST,
+	DSS_BLEND_DST_IN_SRC,
+	DSS_BLEND_SRC_OUT_DST,
+	DSS_BLEND_DST_OUT_SRC,
+	DSS_BLEND_SRC_ATOP_DST,
+	DSS_BLEND_DST_ATOP_SRC,
+	DSS_BLEND_SRC_XOR_DST,
+	DSS_BLEND_SRC_ADD_DST,
+	DSS_BLEND_FIX_OVER,
+	DSS_BLEND_FIX_PER0,
+	DSS_BLEND_FIX_PER1,
+	DSS_BLEND_FIX_PER2,
+	DSS_BLEND_FIX_PER3,
+	DSS_BLEND_FIX_PER4,
+	DSS_BLEND_FIX_PER5,
+	DSS_BLEND_FIX_PER6,
+	DSS_BLEND_FIX_PER7,
+	DSS_BLEND_FIX_PER8,
+	DSS_BLEND_FIX_PER9,
+	DSS_BLEND_FIX_PER10,
+	DSS_BLEND_FIX_PER11,
+	DSS_BLEND_FIX_PER12,
+	DSS_BLEND_FIX_PER13,
+	DSS_BLEND_FIX_PER14,
+	DSS_BLEND_FIX_PER15,
+	DSS_BLEND_FIX_PER16,
+	DSS_BLEND_FIX_PER17,
+
+	DSS_BLEND_MAX,
+};
+
+enum dss_chn_module {
+	MODULE_MIF_CHN,
+	MODULE_AIF0_CHN,
+	MODULE_AIF1_CHN,
+	MODULE_MCTL_CHN_MUTEX,
+	MODULE_MCTL_CHN_FLUSH_EN,
+	MODULE_MCTL_CHN_OV_OEN,
+	MODULE_MCTL_CHN_STARTY,
+	MODULE_MCTL_CHN_MOD_DBG,
+	MODULE_DMA,
+	MODULE_DFC,
+	MODULE_SCL,
+	MODULE_SCL_LUT,
+	MODULE_ARSR2P,
+	MODULE_ARSR2P_LUT,
+	MODULE_POST_CLIP,
+	MODULE_PCSC,
+	MODULE_CSC,
+	MODULE_CHN_MAX,
+};
+
+enum dss_chn_cap {
+	MODULE_CAP_ROT,
+	MODULE_CAP_SCL,
+	MODULE_CAP_CSC,
+	MODULE_CAP_SHARPNESS_1D,
+	MODULE_CAP_SHARPNESS_2D,
+	MODULE_CAP_CE,
+	MODULE_CAP_AFBCD,
+	MODULE_CAP_AFBCE,
+	MODULE_CAP_YUV_PLANAR,
+	MODULE_CAP_YUV_SEMI_PLANAR,
+	MODULE_CAP_YUV_PACKAGE,
+	MODULE_CAP_MAX,
+};
+
+enum dss_ovl_module {
+	MODULE_OVL_BASE,
+	MODULE_MCTL_BASE,
+	MODULE_OVL_MAX,
+};
+
+enum dss_axi_idx {
+	AXI_CHN0 = 0,
+	AXI_CHN1,
+	AXI_CHN_MAX,
+};
+
+#define AXI0_MAX_DSS_CHN_THRESHOLD	(3)
+#define AXI1_MAX_DSS_CHN_THRESHOLD	(3)
+
+#define DEFAULT_AXI_CLK_RATE0	(120 * 1000000)
+#define DEFAULT_AXI_CLK_RATE1	(240 * 1000000)
+#define DEFAULT_AXI_CLK_RATE2	(360 * 1000000)
+#define DEFAULT_AXI_CLK_RATE3	(480 * 1000000)
+#define DEFAULT_AXI_CLK_RATE4	(667 * 1000000)
+#define DEFAULT_AXI_CLK_RATE5	(800 * 1000000)
+
+enum dss_rdma_idx {
+	DSS_RDMA0 = 0,
+	DSS_RDMA1,
+	DSS_RDMA2,
+	DSS_RDMA3,
+	DSS_RDMA4,
+	DSS_RDMA_MAX,
+};
+
+/*******************************************************************************
+ **
+ */
+
+#define PEREN0	(0x000)
+#define PERDIS0	(0x004)
+#define PEREN2	(0x020)
+#define PERDIS2	(0x024)
+#define PERCLKEN2	(0x028)
+#define PERSTAT2	(0x02C)
+#define PEREN3	(0x030)
+#define PERDIS3	(0x034)
+#define PERCLKEN3	(0x038)
+#define PERSTAT3	(0x03C)
+#define PEREN5	(0x050)
+#define PERDIS5	(0x054)
+#define PERCLKEN5	(0x058)
+#define PERSTAT5	(0x05C)
+#define PERRSTDIS0	(0x064)
+#define PERRSTEN2	(0x078)
+#define PERRSTDIS2	(0x07C)
+#define PERRSTEN3	(0x084)
+#define PERRSTDIS3	(0x088)
+#define PERRSTSTAT3 (0x08c)
+#define PERRSTEN4	(0x090)
+#define PERRSTDIS4	(0x094)
+#define PERRSTSTAT4 (0x098)
+#define CLKDIV3	(0x0B4)
+#define CLKDIV5	(0x0BC)
+#define CLKDIV10	(0x0D0)
+#define CLKDIV18	(0x0F0)
+#define CLKDIV20	(0x0F8)
+#define ISOEN	(0x144)
+#define ISODIS	(0x148)
+#define ISOSTAT	(0x14c)
+#define PERPWREN	(0x150)
+#define PERPWRDIS	(0x154)
+#define PERPWRSTAT 	(0x158)
+#define PERI_AUTODIV8	(0x380)
+#define PERI_AUTODIV9	(0x384)
+#define PERI_AUTODIV10	(0x388)
+
+
+#define NOC_POWER_IDLEREQ	(0x380)
+#define NOC_POWER_IDLEACK	(0x384)
+#define NOC_POWER_IDLE	(0x388)
+
+
+#define SCPWREN 	(0x0D0)
+#define SCPEREN1 (0x040)
+#define SCPERDIS1  (0x044)
+#define SCPERCLKEN1 (0x048)
+#define SCPERRSTDIS1	(0x090)
+#define SCISODIS	(0x0C4)
+#define SCCLKDIV2	(0x258)
+
+
+#define PERI_CTRL23	(0x060)
+#define PERI_CTRL29	(0x078)
+#define PERI_CTRL30	(0x07C)
+#define PERI_CTRL32	(0x084)
+#define PERI_STAT0	(0x094)
+#define PERI_STAT1	(0x098)
+#define PERI_STAT16	(0x0D4)
+
+
+#define PCTRL_DPHYTX_ULPSEXIT1	BIT(4)
+#define PCTRL_DPHYTX_ULPSEXIT0	BIT(3)
+
+
+
+
+
+
+
+
+#define PCTRL_DPHYTX_CTRL1	BIT(1)
+#define PCTRL_DPHYTX_CTRL0	BIT(0)
+
+/*******************************************************************************
+ **
+ */
+
+
+#define BIT_DSS_GLB_INTS	BIT(30)
+#define BIT_MMU_IRPT_S	BIT(29)
+#define BIT_MMU_IRPT_NS	BIT(28)
+#define BIT_DBG_MCTL_INTS	BIT(27)
+#define BIT_DBG_WCH1_INTS	BIT(26)
+#define BIT_DBG_WCH0_INTS	BIT(25)
+#define BIT_DBG_RCH7_INTS	BIT(24)
+#define BIT_DBG_RCH6_INTS	BIT(23)
+#define BIT_DBG_RCH5_INTS	BIT(22)
+#define BIT_DBG_RCH4_INTS	BIT(21)
+#define BIT_DBG_RCH3_INTS	BIT(20)
+#define BIT_DBG_RCH2_INTS	BIT(19)
+#define BIT_DBG_RCH1_INTS	BIT(18)
+#define BIT_DBG_RCH0_INTS	BIT(17)
+#define BIT_ITF0_INTS	BIT(16)
+#define BIT_DPP_INTS	BIT(15)
+#define BIT_CMDLIST13	BIT(14)
+#define BIT_CMDLIST12	BIT(13)
+#define BIT_CMDLIST11	BIT(12)
+#define BIT_CMDLIST10	BIT(11)
+#define BIT_CMDLIST9	BIT(10)
+#define BIT_CMDLIST8	BIT(9)
+#define BIT_CMDLIST7	BIT(8)
+#define BIT_CMDLIST6	BIT(7)
+#define BIT_CMDLIST5	BIT(6)
+#define BIT_CMDLIST4	BIT(5)
+#define BIT_CMDLIST3	BIT(4)
+#define BIT_CMDLIST2	BIT(3)
+#define BIT_CMDLIST1	BIT(2)
+#define BIT_CMDLIST0	BIT(1)
+
+
+
+#define BIT_SDP_DSS_GLB_INTS	BIT(29)
+#define BIT_SDP_MMU_IRPT_S	BIT(28)
+#define BIT_SDP_MMU_IRPT_NS	BIT(27)
+#define BIT_SDP_DBG_MCTL_INTS	BIT(26)
+#define BIT_SDP_DBG_WCH1_INTS	BIT(25)
+#define BIT_SDP_DBG_WCH0_INTS	BIT(24)
+#define BIT_SDP_DBG_RCH7_INTS	BIT(23)
+#define BIT_SDP_DBG_RCH6_INTS	BIT(22)
+#define BIT_SDP_DBG_RCH5_INTS	BIT(21)
+#define BIT_SDP_DBG_RCH4_INTS	BIT(20)
+#define BIT_SDP_DBG_RCH3_INTS	BIT(19)
+#define BIT_SDP_DBG_RCH2_INTS	BIT(18)
+#define BIT_SDP_DBG_RCH1_INTS	BIT(17)
+#define BIT_SDP_DBG_RCH0_INTS	BIT(16)
+#define BIT_SDP_ITF1_INTS	BIT(15)
+#define BIT_SDP_CMDLIST13	BIT(14)
+#define BIT_SDP_CMDLIST12	BIT(13)
+#define BIT_SDP_CMDLIST11	BIT(12)
+#define BIT_SDP_CMDLIST10	BIT(11)
+#define BIT_SDP_CMDLIST9	BIT(10)
+#define BIT_SDP_CMDLIST8	BIT(9)
+#define BIT_SDP_CMDLIST7	BIT(8)
+#define BIT_SDP_CMDLIST6	BIT(7)
+#define BIT_SDP_CMDLIST5	BIT(6)
+#define BIT_SDP_CMDLIST4	BIT(5)
+#define BIT_SDP_CMDLIST3	BIT(4)
+#define BIT_SDP_SDP_CMDLIST2	BIT(3)
+#define BIT_SDP_CMDLIST1	BIT(2)
+#define BIT_SDP_CMDLIST0	BIT(1)
+#define BIT_SDP_RCH_CE_INTS	BIT(0)
+
+
+
+#define BIT_OFF_DSS_GLB_INTS	BIT(31)
+#define BIT_OFF_MMU_IRPT_S	BIT(30)
+#define BIT_OFF_MMU_IRPT_NS	BIT(29)
+#define BIT_OFF_DBG_MCTL_INTS	BIT(28)
+#define BIT_OFF_DBG_WCH1_INTS	BIT(27)
+#define BIT_OFF_DBG_WCH0_INTS	BIT(26)
+#define BIT_OFF_DBG_RCH7_INTS	BIT(25)
+#define BIT_OFF_DBG_RCH6_INTS	BIT(24)
+#define BIT_OFF_DBG_RCH5_INTS	BIT(23)
+#define BIT_OFF_DBG_RCH4_INTS	BIT(22)
+#define BIT_OFF_DBG_RCH3_INTS	BIT(21)
+#define BIT_OFF_DBG_RCH2_INTS	BIT(20)
+#define BIT_OFF_DBG_RCH1_INTS	BIT(19)
+#define BIT_OFF_DBG_RCH0_INTS	BIT(18)
+#define BIT_OFF_WCH1_INTS	BIT(17)
+#define BIT_OFF_WCH0_INTS	BIT(16)
+#define BIT_OFF_WCH0_WCH1_FRM_END_INT	BIT(15)
+#define BIT_OFF_CMDLIST13	BIT(14)
+#define BIT_OFF_CMDLIST12	BIT(13)
+#define BIT_OFF_CMDLIST11	BIT(12)
+#define BIT_OFF_CMDLIST10	BIT(11)
+#define BIT_OFF_CMDLIST9	BIT(10)
+#define BIT_OFF_CMDLIST8	BIT(9)
+#define BIT_OFF_CMDLIST7	BIT(8)
+#define BIT_OFF_CMDLIST6	BIT(7)
+#define BIT_OFF_CMDLIST5	BIT(6)
+#define BIT_OFF_CMDLIST4	BIT(5)
+#define BIT_OFF_CMDLIST3	BIT(4)
+#define BIT_OFF_CMDLIST2	BIT(3)
+#define BIT_OFF_CMDLIST1	BIT(2)
+#define BIT_OFF_CMDLIST0	BIT(1)
+#define BIT_OFF_RCH_CE_INTS	BIT(0)
+
+
+
+#define BIT_OFF_CAM_DBG_WCH2_INTS	BIT(4)
+#define BIT_OFF_CAM_DBG_RCH8_INTS	BIT(3)
+#define BIT_OFF_CAM_WCH2_FRMEND_INTS  BIT(2)
+#define BIT_OFF_CAM_CMDLIST15_INTS	BIT(1)
+#define BIT_OFF_CAM_CMDLIST14_INTS	BIT(0)
+
+
+
+
+
+#define BIT_VACTIVE_CNT	BIT(14)
+#define BIT_DSI_TE_TRI	BIT(13)
+#define BIT_LCD_TE0_PIN	BIT(12)
+#define BIT_LCD_TE1_PIN	BIT(11)
+#define BIT_VACTIVE1_END	BIT(10)
+#define BIT_VACTIVE1_START	BIT(9)
+#define BIT_VACTIVE0_END	BIT(8)
+#define BIT_VACTIVE0_START	BIT(7)
+#define BIT_VFRONTPORCH	BIT(6)
+#define BIT_VBACKPORCH	BIT(5)
+#define BIT_VSYNC	BIT(4)
+#define BIT_VFRONTPORCH_END	BIT(3)
+#define BIT_LDI_UNFLOW	BIT(2)
+#define BIT_FRM_END	BIT(1)
+#define BIT_FRM_START	BIT(0)
+
+
+#define BIT_CTL_FLUSH_EN	BIT(21)
+#define BIT_SCF_FLUSH_EN	BIT(19)
+#define BIT_DPP0_FLUSH_EN	BIT(18)
+#define BIT_DBUF1_FLUSH_EN	BIT(17)
+#define BIT_DBUF0_FLUSH_EN	BIT(16)
+#define BIT_OV3_FLUSH_EN	BIT(15)
+#define BIT_OV2_FLUSH_EN	BIT(14)
+#define BIT_OV1_FLUSH_EN	BIT(13)
+#define BIT_OV0_FLUSH_EN	BIT(12)
+#define BIT_WB1_FLUSH_EN	BIT(11)
+#define BIT_WB0_FLUSH_EN	BIT(10)
+#define BIT_DMA3_FLUSH_EN	BIT(9)
+#define BIT_DMA2_FLUSH_EN	BIT(8)
+#define BIT_DMA1_FLUSH_EN	BIT(7)
+#define BIT_DMA0_FLUSH_EN	BIT(6)
+#define BIT_RGB1_FLUSH_EN	BIT(4)
+#define BIT_RGB0_FLUSH_EN	BIT(3)
+#define BIT_VIG1_FLUSH_EN	BIT(1)
+#define BIT_VIG0_FLUSH_EN	BIT(0)
+
+
+
+#define BIT_BUS_DBG_INT	BIT(5)
+#define BIT_CRC_SUM_INT	BIT(4)
+#define BIT_CRC_ITF1_INT	BIT(3)
+#define BIT_CRC_ITF0_INT	BIT(2)
+#define BIT_CRC_OV1_INT	BIT(1)
+#define BIT_CRC_OV0_INT	BIT(0)
+
+
+#define BIT_SBL_SEND_FRAME_OUT	BIT(19)
+#define BIT_SBL_STOP_FRAME_OUT	BIT(18)
+#define BIT_SBL_BACKLIGHT_OUT	BIT(17)
+#define BIT_SBL_DARKENH_OUT		BIT(16)
+#define BIT_SBL_BRIGHTPTR_OUT	BIT(15)
+#define BIT_STRENGTH_INROI_OUT	BIT(14)
+#define BIT_STRENGTH_OUTROI_OUT	BIT(13)
+#define BIT_DONE_OUT			BIT(12)
+#define BIT_PPROC_DONE_OUT		BIT(11)
+
+#define BIT_HIACE_IND	BIT(8)
+#define BIT_STRENGTH_INTP	BIT(7)
+#define BIT_BACKLIGHT_INTP	BIT(6)
+#define BIT_CE_END_IND	BIT(5)
+#define BIT_CE_CANCEL_IND	BIT(4)
+#define BIT_CE_LUT1_RW_COLLIDE_IND	BIT(3)
+#define BIT_CE_LUT0_RW_COLLIDE_IND	BIT(2)
+#define BIT_CE_HIST1_RW_COLLIDE_IND	BIT(1)
+#define BIT_CE_HIST0_RW_COLLIDE_IND	BIT(0)
+
+/*******************************************************************************
+ ** MODULE BASE ADDRESS
+ */
+
+#define DSS_MIPI_DSI0_OFFSET	(0x00001000)
+#define DSS_MIPI_DSI1_OFFSET	(0x00001400)
+
+#define DSS_GLB0_OFFSET	(0x12000)
+
+#define DSS_DBG_OFFSET	(0x11000)
+
+
+#define DSS_CMDLIST_OFFSET	(0x2000)
+
+
+#define DSS_SMMU_OFFSET	(0x8000)
+
+
+#define DSS_VBIF0_AIF	(0x7000)
+#define DSS_VBIF1_AIF	(0x9000)
+
+
+#define DSS_MIF_OFFSET	(0xA000)
+
+
+#define DSS_MCTRL_SYS_OFFSET	(0x10000)
+
+
+#define DSS_MCTRL_CTL0_OFFSET	(0x10800)
+#define DSS_MCTRL_CTL1_OFFSET	(0x10900)
+#define DSS_MCTRL_CTL2_OFFSET	(0x10A00)
+#define DSS_MCTRL_CTL3_OFFSET	(0x10B00)
+#define DSS_MCTRL_CTL4_OFFSET	(0x10C00)
+#define DSS_MCTRL_CTL5_OFFSET	(0x10D00)
+
+
+#define DSS_RCH_VG0_DMA_OFFSET	(0x20000)
+#define DSS_RCH_VG0_DFC_OFFSET (0x20100)
+#define DSS_RCH_VG0_SCL_OFFSET	(0x20200)
+#define DSS_RCH_VG0_ARSR_OFFSET	(0x20300)
+#define DSS_RCH_VG0_POST_CLIP_OFFSET	(0x203A0)
+#define DSS_RCH_VG0_PCSC_OFFSET	(0x20400)
+#define DSS_RCH_VG0_CSC_OFFSET	(0x20500)
+#define DSS_RCH_VG0_DEBUG_OFFSET	(0x20600)
+#define DSS_RCH_VG0_VPP_OFFSET	(0x20700)
+#define DSS_RCH_VG0_DMA_BUF_OFFSET	(0x20800)
+#define DSS_RCH_VG0_AFBCD_OFFSET	(0x20900)
+#define DSS_RCH_VG0_REG_DEFAULT_OFFSET	(0x20A00)
+#define DSS_RCH_VG0_SCL_LUT_OFFSET	(0x21000)
+#define DSS_RCH_VG0_ARSR_LUT_OFFSET	(0x25000)
+
+#define DSS_RCH_VG1_DMA_OFFSET	(0x28000)
+#define DSS_RCH_VG1_DFC_OFFSET (0x28100)
+#define DSS_RCH_VG1_SCL_OFFSET	(0x28200)
+#define DSS_RCH_VG1_POST_CLIP_OFFSET	(0x283A0)
+#define DSS_RCH_VG1_CSC_OFFSET	(0x28500)
+#define DSS_RCH_VG1_DEBUG_OFFSET	(0x28600)
+#define DSS_RCH_VG1_VPP_OFFSET	(0x28700)
+#define DSS_RCH_VG1_DMA_BUF_OFFSET	(0x28800)
+#define DSS_RCH_VG1_AFBCD_OFFSET	(0x28900)
+#define DSS_RCH_VG1_REG_DEFAULT_OFFSET	(0x28A00)
+#define DSS_RCH_VG1_SCL_LUT_OFFSET	(0x29000)
+
+#define DSS_RCH_VG2_DMA_OFFSET	(0x30000)
+#define DSS_RCH_VG2_DFC_OFFSET (0x30100)
+#define DSS_RCH_VG2_SCL_OFFSET	(0x30200)
+#define DSS_RCH_VG2_POST_CLIP_OFFSET	(0x303A0)
+#define DSS_RCH_VG2_CSC_OFFSET	(0x30500)
+#define DSS_RCH_VG2_DEBUG_OFFSET	(0x30600)
+#define DSS_RCH_VG2_VPP_OFFSET	(0x30700)
+#define DSS_RCH_VG2_DMA_BUF_OFFSET	(0x30800)
+#define DSS_RCH_VG2_AFBCD_OFFSET	(0x30900)
+#define DSS_RCH_VG2_REG_DEFAULT_OFFSET	(0x30A00)
+#define DSS_RCH_VG2_SCL_LUT_OFFSET	(0x31000)
+
+
+#define DSS_RCH_G0_DMA_OFFSET	(0x38000)
+#define DSS_RCH_G0_DFC_OFFSET	(0x38100)
+#define DSS_RCH_G0_SCL_OFFSET	(0x38200)
+#define DSS_RCH_G0_POST_CLIP_OFFSET (0x383A0)
+#define DSS_RCH_G0_CSC_OFFSET (0x38500)
+#define DSS_RCH_G0_DEBUG_OFFSET (0x38600)
+#define DSS_RCH_G0_DMA_BUF_OFFSET (0x38800)
+#define DSS_RCH_G0_AFBCD_OFFSET (0x38900)
+#define DSS_RCH_G0_REG_DEFAULT_OFFSET (0x38A00)
+
+#define DSS_RCH_G1_DMA_OFFSET	(0x40000)
+#define DSS_RCH_G1_DFC_OFFSET	(0x40100)
+#define DSS_RCH_G1_SCL_OFFSET	(0x40200)
+#define DSS_RCH_G1_POST_CLIP_OFFSET (0x403A0)
+#define DSS_RCH_G1_CSC_OFFSET (0x40500)
+#define DSS_RCH_G1_DEBUG_OFFSET (0x40600)
+#define DSS_RCH_G1_DMA_BUF_OFFSET (0x40800)
+#define DSS_RCH_G1_AFBCD_OFFSET (0x40900)
+#define DSS_RCH_G1_REG_DEFAULT_OFFSET (0x40A00)
+
+
+#define DSS_RCH_D2_DMA_OFFSET	(0x50000)
+#define DSS_RCH_D2_DFC_OFFSET	(0x50100)
+#define DSS_RCH_D2_CSC_OFFSET	(0x50500)
+#define DSS_RCH_D2_DEBUG_OFFSET	(0x50600)
+#define DSS_RCH_D2_DMA_BUF_OFFSET	(0x50800)
+#define DSS_RCH_D2_AFBCD_OFFSET	(0x50900)
+
+#define DSS_RCH_D3_DMA_OFFSET	(0x51000)
+#define DSS_RCH_D3_DFC_OFFSET	(0x51100)
+#define DSS_RCH_D3_CSC_OFFSET	(0x51500)
+#define DSS_RCH_D3_DEBUG_OFFSET	(0x51600)
+#define DSS_RCH_D3_DMA_BUF_OFFSET	(0x51800)
+#define DSS_RCH_D3_AFBCD_OFFSET	(0x51900)
+
+#define DSS_RCH_D0_DMA_OFFSET	(0x52000)
+#define DSS_RCH_D0_DFC_OFFSET	(0x52100)
+#define DSS_RCH_D0_CSC_OFFSET	(0x52500)
+#define DSS_RCH_D0_DEBUG_OFFSET	(0x52600)
+#define DSS_RCH_D0_DMA_BUF_OFFSET	(0x52800)
+#define DSS_RCH_D0_AFBCD_OFFSET	(0x52900)
+
+#define DSS_RCH_D1_DMA_OFFSET	(0x53000)
+#define DSS_RCH_D1_DFC_OFFSET	(0x53100)
+#define DSS_RCH_D1_CSC_OFFSET	(0x53500)
+#define DSS_RCH_D1_DEBUG_OFFSET	(0x53600)
+#define DSS_RCH_D1_DMA_BUF_OFFSET	(0x53800)
+#define DSS_RCH_D1_AFBCD_OFFSET	(0x53900)
+
+
+#define DSS_WCH0_DMA_OFFSET	(0x5A000)
+#define DSS_WCH0_DFC_OFFSET	(0x5A100)
+#define DSS_WCH0_CSC_OFFSET	(0x5A500)
+#define DSS_WCH0_ROT_OFFSET	(0x5A500)
+#define DSS_WCH0_DEBUG_OFFSET	(0x5A600)
+#define DSS_WCH0_DMA_BUFFER_OFFSET	(0x5A800)
+#define DSS_WCH0_AFBCE_OFFSET	(0x5A900)
+
+#define DSS_WCH1_DMA_OFFSET	(0x5C000)
+#define DSS_WCH1_DFC_OFFSET	(0x5C100)
+#define DSS_WCH1_CSC_OFFSET	(0x5C500)
+#define DSS_WCH1_ROT_OFFSET	(0x5C500)
+#define DSS_WCH1_DEBUG_OFFSET	(0x5C600)
+#define DSS_WCH1_DMA_BUFFER_OFFSET	(0x5C800)
+#define DSS_WCH1_AFBCE_OFFSET	(0x5C900)
+
+#define DSS_WCH2_DMA_OFFSET	(0x5E000)
+#define DSS_WCH2_DFC_OFFSET	(0x5E100)
+#define DSS_WCH2_CSC_OFFSET	(0x5E500)
+#define DSS_WCH2_ROT_OFFSET	(0x5E500)
+#define DSS_WCH2_DEBUG_OFFSET	(0x5E600)
+#define DSS_WCH2_DMA_BUFFER_OFFSET	(0x5E800)
+#define DSS_WCH2_AFBCE_OFFSET	(0x5E900)
+
+
+#define DSS_OVL0_OFFSET	(0x60000)
+#define DSS_OVL1_OFFSET	(0x60400)
+#define DSS_OVL2_OFFSET	(0x60800)
+#define DSS_OVL3_OFFSET	(0x60C00)
+
+
+#define DSS_DBUF0_OFFSET	(0x6D000)
+#define DSS_DBUF1_OFFSET	(0x6E000)
+
+
+#define DSS_HI_ACE_OFFSET	(0x6F000)
+
+
+#define DSS_DPP_OFFSET	(0x70000)
+#define DSS_TOP_OFFSET	(0x70000)
+#define DSS_DPP_COLORBAR_OFFSET	(0x70100)
+#define DSS_DPP_DITHER_OFFSET	(0x70200)
+#define DSS_DPP_CSC_RGB2YUV10B_OFFSET	(0x70300)
+#define DSS_DPP_CSC_YUV2RGB10B_OFFSET	(0x70400)
+#define DSS_DPP_DEGAMA_OFFSET	(0x70500)
+#define DSS_DPP_GAMA_OFFSET	(0x70600)
+#define DSS_DPP_ACM_OFFSET	(0x70700)
+#define DSS_DPP_ACE_OFFSET	(0x70800)
+#define DSS_DPP_LCP_OFFSET	(0x70900)
+#define DSS_DPP_ARSR1P_OFFSET	(0x70A00)
+#define DSS_DPP_BITEXT0_OFFSET	(0x70B00)
+#define DSS_DPP_GAMA_LUT_OFFSET	(0x71000)
+#define DSS_DPP_ACM_LUT_OFFSET	(0x72000)
+#define DSS_DPP_LCP_LUT_OFFSET	(0x73000)
+#define DSS_DPP_ACE_LUT_OFFSET	(0x79000)
+#define DSS_DPP_ARSR1P_LUT_OFFSET	(0x7B000)
+
+
+#define DSS_POST_SCF_OFFSET	DSS_DPP_ARSR1P_OFFSET
+#define DSS_POST_SCF_LUT_OFFSET	DSS_DPP_ARSR1P_LUT_OFFSET
+
+#define DSS_DPP_SBL_OFFSET	(0x7C000)
+#define DSS_LDI0_OFFSET	(0x7D000)
+#define DSS_IFBC_OFFSET	(0x7D800)
+#define DSS_DSC_OFFSET	(0x7DC00)
+#define DSS_LDI1_OFFSET	(0x7E000)
+
+/*******************************************************************************
+ ** GLB
+ */
+#define GLB_DSS_TAG	 (DSS_GLB0_OFFSET + 0x0000)
+
+#define GLB_APB_CTL	 (DSS_GLB0_OFFSET + 0x0004)
+
+#define GLB_DSS_AXI_RST_EN	(DSS_GLB0_OFFSET + 0x0118)
+#define GLB_DSS_APB_RST_EN	(DSS_GLB0_OFFSET + 0x011C)
+#define GLB_DSS_CORE_RST_EN	(DSS_GLB0_OFFSET + 0x0120)
+#define GLB_PXL0_DIV2_RST_EN	(DSS_GLB0_OFFSET + 0x0124)
+#define GLB_PXL0_DIV4_RST_EN	(DSS_GLB0_OFFSET + 0x0128)
+#define GLB_PXL0_RST_EN	(DSS_GLB0_OFFSET + 0x012C)
+#define GLB_PXL0_DSI_RST_EN	(DSS_GLB0_OFFSET + 0x0130)
+#define GLB_DSS_PXL1_RST_EN	(DSS_GLB0_OFFSET + 0x0134)
+#define GLB_MM_AXI_CLK_RST_EN	(DSS_GLB0_OFFSET + 0x0138)
+#define GLB_AFBCD0_IP_RST_EN	(DSS_GLB0_OFFSET + 0x0140)
+#define GLB_AFBCD1_IP_RST_EN	(DSS_GLB0_OFFSET + 0x0144)
+#define GLB_AFBCD2_IP_RST_EN	(DSS_GLB0_OFFSET + 0x0148)
+#define GLB_AFBCD3_IP_RST_EN	(DSS_GLB0_OFFSET + 0x014C)
+#define GLB_AFBCD4_IP_RST_EN	(DSS_GLB0_OFFSET + 0x0150)
+#define GLB_AFBCD5_IP_RST_EN	(DSS_GLB0_OFFSET + 0x0154)
+#define GLB_AFBCD6_IP_RST_EN	(DSS_GLB0_OFFSET + 0x0158)
+#define GLB_AFBCD7_IP_RST_EN	(DSS_GLB0_OFFSET + 0x015C)
+#define GLB_AFBCE0_IP_RST_EN	(DSS_GLB0_OFFSET + 0x0160)
+#define GLB_AFBCE1_IP_RST_EN	(DSS_GLB0_OFFSET + 0x0164)
+
+
+#define GLB_MCU_PDP_INTS	(DSS_GLB0_OFFSET + 0x20C)
+#define GLB_MCU_PDP_INT_MSK	(DSS_GLB0_OFFSET + 0x210)
+#define GLB_MCU_SDP_INTS	(DSS_GLB0_OFFSET + 0x214)
+#define GLB_MCU_SDP_INT_MSK	(DSS_GLB0_OFFSET + 0x218)
+#define GLB_MCU_OFF_INTS	(DSS_GLB0_OFFSET + 0x21C)
+#define GLB_MCU_OFF_INT_MSK	(DSS_GLB0_OFFSET + 0x220)
+#define GLB_MCU_OFF_CAM_INTS	(DSS_GLB0_OFFSET + 0x2B4)
+#define GLB_MCU_OFF_CAM_INT_MSK	(DSS_GLB0_OFFSET + 0x2B8)
+#define GLB_CPU_PDP_INTS	(DSS_GLB0_OFFSET + 0x224)
+#define GLB_CPU_PDP_INT_MSK	(DSS_GLB0_OFFSET + 0x228)
+#define GLB_CPU_SDP_INTS	(DSS_GLB0_OFFSET + 0x22C)
+#define GLB_CPU_SDP_INT_MSK	(DSS_GLB0_OFFSET + 0x230)
+#define GLB_CPU_OFF_INTS	(DSS_GLB0_OFFSET + 0x234)
+#define GLB_CPU_OFF_INT_MSK	(DSS_GLB0_OFFSET + 0x238)
+#define GLB_CPU_OFF_CAM_INTS	(DSS_GLB0_OFFSET + 0x2AC)
+#define GLB_CPU_OFF_CAM_INT_MSK	(DSS_GLB0_OFFSET + 0x2B0)
+
+
+#define GLB_MODULE_CLK_SEL	(DSS_GLB0_OFFSET + 0x0300)
+#define GLB_MODULE_CLK_EN	(DSS_GLB0_OFFSET + 0x0304)
+
+#define GLB_GLB0_DBG_SEL	(DSS_GLB0_OFFSET + 0x310)
+#define GLB_GLB1_DBG_SEL	(DSS_GLB0_OFFSET + 0x314)
+#define GLB_DBG_IRQ_CPU	(DSS_GLB0_OFFSET + 0x320)
+#define GLB_DBG_IRQ_MCU	(DSS_GLB0_OFFSET + 0x324)
+
+#define GLB_TP_SEL	(DSS_GLB0_OFFSET + 0x0400)
+#define GLB_CRC_DBG_LDI0	(DSS_GLB0_OFFSET + 0x0404)
+#define GLB_CRC_DBG_LDI1	(DSS_GLB0_OFFSET + 0x0408)
+#define GLB_CRC_LDI0_EN	(DSS_GLB0_OFFSET + 0x040C)
+#define GLB_CRC_LDI0_FRM	(DSS_GLB0_OFFSET + 0x0410)
+#define GLB_CRC_LDI1_EN	(DSS_GLB0_OFFSET + 0x0414)
+#define GLB_CRC_LDI1_FRM	(DSS_GLB0_OFFSET + 0x0418)
+
+#define GLB_DSS_MEM_CTRL	(DSS_GLB0_OFFSET + 0x0600)
+#define GLB_DSS_PM_CTRL	(DSS_GLB0_OFFSET + 0x0604)
+
+/*******************************************************************************
+ ** DBG
+ */
+#define DBG_CRC_DBG_OV0	(0x0000)
+#define DBG_CRC_DBG_OV1	(0x0004)
+#define DBG_CRC_DBG_SUM	(0x0008)
+#define DBG_CRC_OV0_EN	(0x000C)
+#define DBG_DSS_GLB_DBG_O	(0x0010)
+#define DBG_DSS_GLB_DBG_I	(0x0014)
+#define DBG_CRC_OV0_FRM	(0x0018)
+#define DBG_CRC_OV1_EN	(0x001C)
+#define DBG_CRC_OV1_FRM	(0x0020)
+#define DBG_CRC_SUM_EN	(0x0024)
+#define DBG_CRC_SUM_FRM	(0x0028)
+
+#define DBG_MCTL_INTS	(0x023C)
+#define DBG_MCTL_INT_MSK	(0x0240)
+#define DBG_WCH0_INTS	(0x0244)
+#define DBG_WCH0_INT_MSK	(0x0248)
+#define DBG_WCH1_INTS	(0x024C)
+#define DBG_WCH1_INT_MSK	(0x0250)
+#define DBG_RCH0_INTS	(0x0254)
+#define DBG_RCH0_INT_MSK	(0x0258)
+#define DBG_RCH1_INTS	(0x025C)
+#define DBG_RCH1_INT_MSK	(0x0260)
+#define DBG_RCH2_INTS	(0x0264)
+#define DBG_RCH2_INT_MSK	(0x0268)
+#define DBG_RCH3_INTS	(0x026C)
+#define DBG_RCH3_INT_MSK	(0x0270)
+#define DBG_RCH4_INTS	(0x0274)
+#define DBG_RCH4_INT_MSK	(0x0278)
+#define DBG_RCH5_INTS	(0x027C)
+#define DBG_RCH5_INT_MSK	(0x0280)
+#define DBG_RCH6_INTS	(0x0284)
+#define DBG_RCH6_INT_MSK	(0x0288)
+#define DBG_RCH7_INTS	(0x028C)
+#define DBG_RCH7_INT_MSK	(0x0290)
+#define DBG_DSS_GLB_INTS	(0x0294)
+#define DBG_DSS_GLB_INT_MSK	(0x0298)
+#define DBG_WCH2_INTS	(0x029C)
+#define DBG_WCH2_INT_MSK	(0x02A0)
+#define DBG_RCH8_INTS	(0x02A4)
+#define DBG_RCH8_INT_MSK	(0x02A8)
+
+/*******************************************************************************
+ ** CMDLIST
+ */
+
+#define CMDLIST_CH0_PENDING_CLR	(0x0000)
+#define CMDLIST_CH0_CTRL	(0x0004)
+#define CMDLIST_CH0_STATUS	(0x0008)
+#define CMDLIST_CH0_STAAD	(0x000C)
+#define CMDLIST_CH0_CURAD	(0x0010)
+#define CMDLIST_CH0_INTE	(0x0014)
+#define CMDLIST_CH0_INTC	(0x0018)
+#define CMDLIST_CH0_INTS	(0x001C)
+#define CMDLIST_CH0_SCENE	(0x0020)
+#define CMDLIST_CH0_DBG	(0x0028)
+
+#define CMDLIST_DBG	(0x0700)
+#define CMDLIST_BUF_DBG_EN	(0x0704)
+#define CMDLIST_BUF_DBG_CNT_CLR	(0x0708)
+#define CMDLIST_BUF_DBG_CNT	(0x070C)
+#define CMDLIST_TIMEOUT_TH	(0x0710)
+#define CMDLIST_START	(0x0714)
+#define CMDLIST_ADDR_MASK_EN	(0x0718)
+#define CMDLIST_ADDR_MASK_DIS	(0x071C)
+#define CMDLIST_ADDR_MASK_STATUS	(0x0720)
+#define CMDLIST_TASK_CONTINUE	(0x0724)
+#define CMDLIST_TASK_STATUS	(0x0728)
+#define CMDLIST_CTRL	(0x072C)
+#define CMDLIST_SECU	(0x0730)
+#define CMDLIST_INTS	(0x0734)
+#define CMDLIST_SWRST	(0x0738)
+#define CMD_MEM_CTRL	(0x073C)
+#define CMD_CLK_SEL		(0x0740)
+#define CMD_CLK_EN	(0x0744)
+
+#define HISI_DSS_MIN_ROT_AFBCE_BLOCK_SIZE (256)
+#define HISI_DSS_MAX_ROT_AFBCE_BLOCK_SIZE (480)
+
+
+#define BIT_CMDLIST_CH_TASKDONE_INTS	    BIT(7)
+#define BIT_CMDLIST_CH_TIMEOUT_INTS	    BIT(6)
+#define BIT_CMDLIST_CH_BADCMD_INTS	    BIT(5)
+#define BIT_CMDLIST_CH_START_INTS	           BIT(4)
+#define BIT_CMDLIST_CH_PENDING_INTS	    BIT(3)
+#define BIT_CMDLIST_CH_AXIERR_INTS	    BIT(2)
+#define BIT_CMDLIST_CH_ALLDONE_INTS	    BIT(1)
+#define BIT_CMDLIST_CH_ONEDONE_INTS	    BIT(0)
+
+#define BIT_CMDLIST_CH15_INTS	BIT(15)
+#define BIT_CMDLIST_CH14_INTS	BIT(14)
+#define BIT_CMDLIST_CH13_INTS	BIT(13)
+#define BIT_CMDLIST_CH12_INTS	BIT(12)
+#define BIT_CMDLIST_CH11_INTS	BIT(11)
+#define BIT_CMDLIST_CH10_INTS	BIT(10)
+#define BIT_CMDLIST_CH9_INTS	BIT(9)
+#define BIT_CMDLIST_CH8_INTS	BIT(8)
+#define BIT_CMDLIST_CH7_INTS	BIT(7)
+#define BIT_CMDLIST_CH6_INTS	BIT(6)
+#define BIT_CMDLIST_CH5_INTS	BIT(5)
+#define BIT_CMDLIST_CH4_INTS	BIT(4)
+#define BIT_CMDLIST_CH3_INTS	BIT(3)
+#define BIT_CMDLIST_CH2_INTS	BIT(2)
+#define BIT_CMDLIST_CH1_INTS	BIT(1)
+#define BIT_CMDLIST_CH0_INTS	BIT(0)
+
+/*******************************************************************************
+ ** AIF
+ */
+#define AIF0_CH0_OFFSET	(DSS_VBIF0_AIF + 0x00)
+#define AIF0_CH0_ADD_OFFSET	(DSS_VBIF0_AIF + 0x04)
+#define AIF0_CH1_OFFSET	(DSS_VBIF0_AIF + 0x20)
+#define AIF0_CH1_ADD_OFFSET	(DSS_VBIF0_AIF + 0x24)
+#define AIF0_CH2_OFFSET	(DSS_VBIF0_AIF + 0x40)
+#define AIF0_CH2_ADD_OFFSET	(DSS_VBIF0_AIF + 0x44)
+#define AIF0_CH3_OFFSET	(DSS_VBIF0_AIF + 0x60)
+#define AIF0_CH3_ADD_OFFSET	(DSS_VBIF0_AIF + 0x64)
+#define AIF0_CH4_OFFSET	(DSS_VBIF0_AIF + 0x80)
+#define AIF0_CH4_ADD_OFFSET	(DSS_VBIF0_AIF + 0x84)
+#define AIF0_CH5_OFFSET	(DSS_VBIF0_AIF + 0xA0)
+#define AIF0_CH5_ADD_OFFSET	(DSS_VBIF0_AIF + 0xa4)
+#define AIF0_CH6_OFFSET	(DSS_VBIF0_AIF + 0xC0)
+#define AIF0_CH6_ADD_OFFSET	(DSS_VBIF0_AIF + 0xc4)
+#define AIF0_CH7_OFFSET	(DSS_VBIF0_AIF + 0xE0)
+#define AIF0_CH7_ADD_OFFSET	(DSS_VBIF0_AIF + 0xe4)
+#define AIF0_CH8_OFFSET	(DSS_VBIF0_AIF + 0x100)
+#define AIF0_CH8_ADD_OFFSET	(DSS_VBIF0_AIF + 0x104)
+#define AIF0_CH9_OFFSET	(DSS_VBIF0_AIF + 0x120)
+#define AIF0_CH9_ADD_OFFSET	(DSS_VBIF0_AIF + 0x124)
+#define AIF0_CH10_OFFSET	(DSS_VBIF0_AIF + 0x140)
+#define AIF0_CH10_ADD_OFFSET	(DSS_VBIF0_AIF + 0x144)
+#define AIF0_CH11_OFFSET	(DSS_VBIF0_AIF + 0x160)
+#define AIF0_CH11_ADD_OFFSET	(DSS_VBIF0_AIF + 0x164)
+#define AIF0_CH12_OFFSET	(DSS_VBIF0_AIF + 0x180)
+#define AIF0_CH12_ADD_OFFSET	(DSS_VBIF0_AIF + 0x184)
+
+#define AIF1_CH0_OFFSET	(DSS_VBIF1_AIF + 0x00)
+#define AIF1_CH0_ADD_OFFSET	(DSS_VBIF1_AIF + 0x04)
+#define AIF1_CH1_OFFSET	(DSS_VBIF1_AIF + 0x20)
+#define AIF1_CH1_ADD_OFFSET	(DSS_VBIF1_AIF + 0x24)
+#define AIF1_CH2_OFFSET	(DSS_VBIF1_AIF + 0x40)
+#define AIF1_CH2_ADD_OFFSET	(DSS_VBIF1_AIF + 0x44)
+#define AIF1_CH3_OFFSET	(DSS_VBIF1_AIF + 0x60)
+#define AIF1_CH3_ADD_OFFSET	(DSS_VBIF1_AIF + 0x64)
+#define AIF1_CH4_OFFSET	(DSS_VBIF1_AIF + 0x80)
+#define AIF1_CH4_ADD_OFFSET	(DSS_VBIF1_AIF + 0x84)
+#define AIF1_CH5_OFFSET	(DSS_VBIF1_AIF + 0xA0)
+#define AIF1_CH5_ADD_OFFSET	(DSS_VBIF1_AIF + 0xa4)
+#define AIF1_CH6_OFFSET	(DSS_VBIF1_AIF + 0xC0)
+#define AIF1_CH6_ADD_OFFSET	(DSS_VBIF1_AIF + 0xc4)
+#define AIF1_CH7_OFFSET	(DSS_VBIF1_AIF + 0xE0)
+#define AIF1_CH7_ADD_OFFSET	(DSS_VBIF1_AIF + 0xe4)
+#define AIF1_CH8_OFFSET	(DSS_VBIF1_AIF + 0x100)
+#define AIF1_CH8_ADD_OFFSET	(DSS_VBIF1_AIF + 0x104)
+#define AIF1_CH9_OFFSET	(DSS_VBIF1_AIF + 0x120)
+#define AIF1_CH9_ADD_OFFSET	(DSS_VBIF1_AIF + 0x124)
+#define AIF1_CH10_OFFSET	(DSS_VBIF1_AIF + 0x140)
+#define AIF1_CH10_ADD_OFFSET	(DSS_VBIF1_AIF + 0x144)
+#define AIF1_CH11_OFFSET	(DSS_VBIF1_AIF + 0x160)
+#define AIF1_CH11_ADD_OFFSET	(DSS_VBIF1_AIF + 0x164)
+#define AIF1_CH12_OFFSET	(DSS_VBIF1_AIF + 0x180)
+#define AIF1_CH12_ADD_OFFSET	(DSS_VBIF1_AIF + 0x184)
+
+/* aif dmax */
+
+#define AIF_CH_CTL	(0x0000)
+
+#define AIF_CH_CTL_ADD (0x0004)
+
+
+/* aif common */
+#define AXI0_RID_MSK0	(0x0800)
+#define AXI0_RID_MSK1	(0x0804)
+#define AXI0_WID_MSK	(0x0808)
+#define AXI0_R_QOS_MAP	(0x080c)
+#define AXI1_RID_MSK0	(0x0810)
+#define AXI1_RID_MSK1	(0x0814)
+#define AXI1_WID_MSK	(0x0818)
+#define AXI1_R_QOS_MAP	(0x081c)
+#define AIF_CLK_SEL0	(0x0820)
+#define AIF_CLK_SEL1	(0x0824)
+#define AIF_CLK_EN0	(0x0828)
+#define AIF_CLK_EN1	(0x082c)
+#define MONITOR_CTRL	(0x0830)
+#define MONITOR_TIMER_INI	(0x0834)
+#define DEBUG_BUF_BASE	(0x0838)
+#define DEBUG_CTRL	(0x083C)
+#define AIF_SHADOW_READ	(0x0840)
+#define AIF_MEM_CTRL	(0x0844)
+#define AIF_MONITOR_EN	(0x0848)
+#define AIF_MONITOR_CTRL	(0x084C)
+#define AIF_MONITOR_SAMPLE_MUN	(0x0850)
+#define AIF_MONITOR_SAMPLE_TIME	(0x0854)
+#define AIF_MONITOR_SAMPLE_FLOW	(0x0858)
+
+/* aif debug */
+#define AIF_MONITOR_READ_DATA	(0x0880)
+#define AIF_MONITOR_WRITE_DATA	(0x0884)
+#define AIF_MONITOR_WINDOW_CYCLE	(0x0888)
+#define AIF_MONITOR_WBURST_CNT	(0x088C)
+#define AIF_MONITOR_MIN_WR_CYCLE	(0x0890)
+#define AIF_MONITOR_MAX_WR_CYCLE	(0x0894)
+#define AIF_MONITOR_AVR_WR_CYCLE	(0x0898)
+#define AIF_MONITOR_MIN_WRW_CYCLE	(0x089C)
+#define AIF_MONITOR_MAX_WRW_CYCLE	(0x08A0)
+#define AIF_MONITOR_AVR_WRW_CYCLE	(0x08A4)
+#define AIF_MONITOR_RBURST_CNT	(0x08A8)
+#define AIF_MONITOR_MIN_RD_CYCLE	(0x08AC)
+#define AIF_MONITOR_MAX_RD_CYCLE	(0x08B0)
+#define AIF_MONITOR_AVR_RD_CYCLE	(0x08B4)
+#define AIF_MONITOR_MIN_RDW_CYCLE	(0x08B8)
+#define AIF_MONITOR_MAX_RDW_CYCLE	(0x08BC)
+#define AIF_MONITOR_AVR_RDW_CYCLE	(0x08C0)
+#define AIF_CH_STAT_0	(0x08C4)
+#define AIF_CH_STAT_1	(0x08C8)
+
+#define AIF_MODULE_CLK_SEL	(0x0A04)
+#define AIF_MODULE_CLK_EN	(0x0A08)
+
+typedef struct dss_aif {
+	uint32_t aif_ch_ctl;
+	uint32_t aif_ch_ctl_add;
+} dss_aif_t;
+
+typedef struct dss_aif_bw {
+	uint64_t bw;
+	uint8_t chn_idx;
+	int8_t axi_sel;
+	uint8_t is_used;
+} dss_aif_bw_t;
+
+/*******************************************************************************
+ ** MIF
+ */
+#define MIF_ENABLE	(0x0000)
+#define MIF_MEM_CTRL	(0x0004)
+
+#define MIF_CTRL0	(0x000)
+#define MIF_CTRL1	(0x004)
+#define MIF_CTRL2	(0x008)
+#define MIF_CTRL3	(0x00C)
+#define MIF_CTRL4	(0x010)
+#define MIF_CTRL5	(0x014)
+#define REG_DEFAULT (0x0500)
+#define MIF_SHADOW_READ	(0x0504)
+#define MIF_CLK_CTL	(0x0508)
+
+#define MIF_STAT0	(0x0600)
+
+#define MIF_STAT1	(0x0604)
+
+#define MIF_STAT2	(0x0608)
+
+#define MIF_CTRL_OFFSET	(0x20)
+#define MIF_CH0_OFFSET	(DSS_MIF_OFFSET + MIF_CTRL_OFFSET*1)
+#define MIF_CH1_OFFSET	(DSS_MIF_OFFSET + MIF_CTRL_OFFSET*2)
+#define MIF_CH2_OFFSET	(DSS_MIF_OFFSET + MIF_CTRL_OFFSET*3)
+#define MIF_CH3_OFFSET	(DSS_MIF_OFFSET + MIF_CTRL_OFFSET*4)
+#define MIF_CH4_OFFSET	(DSS_MIF_OFFSET + MIF_CTRL_OFFSET*5)
+#define MIF_CH5_OFFSET	(DSS_MIF_OFFSET + MIF_CTRL_OFFSET*6)
+#define MIF_CH6_OFFSET	(DSS_MIF_OFFSET + MIF_CTRL_OFFSET*7)
+#define MIF_CH7_OFFSET	(DSS_MIF_OFFSET + MIF_CTRL_OFFSET*8)
+#define MIF_CH8_OFFSET	(DSS_MIF_OFFSET + MIF_CTRL_OFFSET*9)
+#define MIF_CH9_OFFSET	(DSS_MIF_OFFSET + MIF_CTRL_OFFSET*10)
+#define MIF_CH10_OFFSET	(DSS_MIF_OFFSET + MIF_CTRL_OFFSET*11)
+#define MIF_CH11_OFFSET	(DSS_MIF_OFFSET + MIF_CTRL_OFFSET*12)
+#define MIF_CTRL_NUM	(12)
+
+#define LITTLE_LAYER_BUF_SIZE	(256 * 1024)
+#define MIF_STRIDE_UNIT (4 * 1024)
+
+typedef struct dss_mif {
+	uint32_t mif_ctrl1;
+	uint32_t mif_ctrl2;
+	uint32_t mif_ctrl3;
+	uint32_t mif_ctrl4;
+	uint32_t mif_ctrl5;
+} dss_mif_t;
+
+/*
+ ** stretch blt, linear/tile, rotation, pixel format
+ ** 0 0 000
+ */
+enum dss_mmu_tlb_tag_org {
+	MMU_TLB_TAG_ORG_0x0 = 0x0,
+	MMU_TLB_TAG_ORG_0x1 = 0x1,
+	MMU_TLB_TAG_ORG_0x2 = 0x2,
+	MMU_TLB_TAG_ORG_0x3 = 0x3,
+	MMU_TLB_TAG_ORG_0x4 = 0x4,
+	MMU_TLB_TAG_ORG_0x7 = 0x7,
+
+	MMU_TLB_TAG_ORG_0x8 = 0x8,
+	MMU_TLB_TAG_ORG_0x9 = 0x9,
+	MMU_TLB_TAG_ORG_0xA = 0xA,
+	MMU_TLB_TAG_ORG_0xB = 0xB,
+	MMU_TLB_TAG_ORG_0xC = 0xC,
+	MMU_TLB_TAG_ORG_0xF = 0xF,
+
+	MMU_TLB_TAG_ORG_0x10 = 0x10,
+	MMU_TLB_TAG_ORG_0x11 = 0x11,
+	MMU_TLB_TAG_ORG_0x12 = 0x12,
+	MMU_TLB_TAG_ORG_0x13 = 0x13,
+	MMU_TLB_TAG_ORG_0x14 = 0x14,
+	MMU_TLB_TAG_ORG_0x17 = 0x17,
+
+	MMU_TLB_TAG_ORG_0x18 = 0x18,
+	MMU_TLB_TAG_ORG_0x19 = 0x19,
+	MMU_TLB_TAG_ORG_0x1A = 0x1A,
+	MMU_TLB_TAG_ORG_0x1B = 0x1B,
+	MMU_TLB_TAG_ORG_0x1C = 0x1C,
+	MMU_TLB_TAG_ORG_0x1F = 0x1F,
+};
+
+/*******************************************************************************
+ **SMMU
+ */
+#define SMMU_SCR	(0x0000)
+#define SMMU_MEMCTRL	(0x0004)
+#define SMMU_LP_CTRL	(0x0008)
+#define SMMU_PRESS_REMAP	(0x000C)
+#define SMMU_INTMASK_NS	(0x0010)
+#define SMMU_INTRAW_NS	(0x0014)
+#define SMMU_INTSTAT_NS	(0x0018)
+#define SMMU_INTCLR_NS	(0x001C)
+
+#define SMMU_SMRx_NS	(0x0020)
+#define SMMU_RLD_EN0_NS	(0x01F0)
+#define SMMU_RLD_EN1_NS	(0x01F4)
+#define SMMU_RLD_EN2_NS	(0x01F8)
+#define SMMU_CB_SCTRL	(0x0200)
+#define SMMU_CB_TTBR0	(0x0204)
+#define SMMU_CB_TTBR1	(0x0208)
+#define SMMU_CB_TTBCR	(0x020C)
+#define SMMU_OFFSET_ADDR_NS	(0x0210)
+#define SMMU_SCACHEI_ALL	(0x0214)
+#define SMMU_SCACHEI_L1	(0x0218)
+#define SMMU_SCACHEI_L2L3	(0x021C)
+#define SMMU_FAMA_CTRL0	(0x0220)
+#define SMMU_FAMA_CTRL1	(0x0224)
+#define SMMU_ADDR_MSB	(0x0300)
+#define SMMU_ERR_RDADDR	(0x0304)
+#define SMMU_ERR_WRADDR	(0x0308)
+#define SMMU_FAULT_ADDR_TCU (0x0310)
+#define SMMU_FAULT_ID_TCU	(0x0314)
+
+#define SMMU_FAULT_ADDR_TBUx	(0x0320)
+#define SMMU_FAULT_ID_TBUx	(0x0324)
+#define SMMU_FAULT_INFOx	(0x0328)
+#define SMMU_DBGRPTR_TLB	(0x0380)
+#define SMMU_DBGRDATA_TLB	(0x0380)
+#define SMMU_DBGRDATA0_CACHE	(0x038C)
+#define SMMU_DBGRDATA1_CACHE	(0x0390)
+#define SMMU_DBGAXI_CTRL	(0x0394)
+#define SMMU_OVA_ADDR	(0x0398)
+#define SMMU_OPA_ADDR	(0x039C)
+#define SMMU_OVA_CTRL	(0x03A0)
+#define SMMU_OPREF_ADDR	(0x03A4)
+#define SMMU_OPREF_CTRL	(0x03A8)
+#define SMMU_OPREF_CNT	(0x03AC)
+
+#define SMMU_SMRx_S	(0x0500)
+#define SMMU_RLD_EN0_S	(0x06F0)
+#define SMMU_RLD_EN1_S	(0x06F4)
+#define SMMU_RLD_EN2_S	(0x06F8)
+#define SMMU_INTMAS_S	(0x0700)
+#define SMMU_INTRAW_S	(0x0704)
+#define SMMU_INTSTAT_S	(0x0708)
+#define SMMU_INTCLR_S	(0x070C)
+#define SMMU_SCR_S	(0x0710)
+#define SMMU_SCB_SCTRL	(0x0714)
+#define SMMU_SCB_TTBR	(0x0718)
+#define SMMU_SCB_TTBCR	(0x071C)
+#define SMMU_OFFSET_ADDR_S	(0x0720)
+
+#define SMMU_SID_NUM	(64)
+
+typedef struct dss_smmu {
+	uint32_t smmu_scr;
+	uint32_t smmu_memctrl;
+	uint32_t smmu_lp_ctrl;
+	uint32_t smmu_press_remap;
+	uint32_t smmu_intmask_ns;
+	uint32_t smmu_intraw_ns;
+	uint32_t smmu_intstat_ns;
+	uint32_t smmu_intclr_ns;
+	uint32_t smmu_smrx_ns[SMMU_SID_NUM];
+	uint32_t smmu_rld_en0_ns;
+	uint32_t smmu_rld_en1_ns;
+	uint32_t smmu_rld_en2_ns;
+	uint32_t smmu_cb_sctrl;
+	uint32_t smmu_cb_ttbr0;
+	uint32_t smmu_cb_ttbr1;
+	uint32_t smmu_cb_ttbcr;
+	uint32_t smmu_offset_addr_ns;
+	uint32_t smmu_scachei_all;
+	uint32_t smmu_scachei_l1;
+	uint32_t smmu_scachei_l2l3;
+	uint32_t smmu_fama_ctrl0_ns;
+	uint32_t smmu_fama_ctrl1_ns;
+	uint32_t smmu_addr_msb;
+	uint32_t smmu_err_rdaddr;
+	uint32_t smmu_err_wraddr;
+	uint32_t smmu_fault_addr_tcu;
+	uint32_t smmu_fault_id_tcu;
+	uint32_t smmu_fault_addr_tbux;
+	uint32_t smmu_fault_id_tbux;
+	uint32_t smmu_fault_infox;
+	uint32_t smmu_dbgrptr_tlb;
+	uint32_t smmu_dbgrdata_tlb;
+	uint32_t smmu_dbgrptr_cache;
+	uint32_t smmu_dbgrdata0_cache;
+	uint32_t smmu_dbgrdata1_cache;
+	uint32_t smmu_dbgaxi_ctrl;
+	uint32_t smmu_ova_addr;
+	uint32_t smmu_opa_addr;
+	uint32_t smmu_ova_ctrl;
+	uint32_t smmu_opref_addr;
+	uint32_t smmu_opref_ctrl;
+	uint32_t smmu_opref_cnt;
+	uint32_t smmu_smrx_s[SMMU_SID_NUM];
+	uint32_t smmu_rld_en0_s;
+	uint32_t smmu_rld_en1_s;
+	uint32_t smmu_rld_en2_s;
+	uint32_t smmu_intmas_s;
+	uint32_t smmu_intraw_s;
+	uint32_t smmu_intstat_s;
+	uint32_t smmu_intclr_s;
+	uint32_t smmu_scr_s;
+	uint32_t smmu_scb_sctrl;
+	uint32_t smmu_scb_ttbr;
+	uint32_t smmu_scb_ttbcr;
+	uint32_t smmu_offset_addr_s;
+
+	uint8_t smmu_smrx_ns_used[DSS_CHN_MAX_DEFINE];
+} dss_smmu_t;
+
+/*******************************************************************************
+ ** RDMA
+ */
+
+
+#define DMA_OFT_X0	(0x0000)
+#define DMA_OFT_Y0	(0x0004)
+#define DMA_OFT_X1	(0x0008)
+#define DMA_OFT_Y1	(0x000C)
+#define DMA_MASK0	(0x0010)
+#define DMA_MASK1	(0x0014)
+#define DMA_STRETCH_SIZE_VRT	(0x0018)
+#define DMA_CTRL	(0x001C)
+#define DMA_TILE_SCRAM	(0x0020)
+
+#define DMA_PULSE	(0x0028)
+#define DMA_CORE_GT	(0x002C)
+#define RWCH_CFG0	(0x0030)
+
+
+#define WDMA_DMA_SW_MASK_EN	(0x004C)
+#define WDMA_DMA_START_MASK0	(0x0050)
+#define WDMA_DMA_END_MASK0	(0x0054)
+#define WDMA_DMA_START_MASK1	(0x0058)
+#define WDMA_DMA_END_MASK1	(0x005C)
+
+
+#define DMA_DATA_ADDR0	(0x0060)
+#define DMA_STRIDE0	(0x0064)
+#define DMA_STRETCH_STRIDE0	(0x0068)
+#define DMA_DATA_NUM0	(0x006C)
+
+#define DMA_TEST0	(0x0070)
+#define DMA_TEST1	(0x0074)
+#define DMA_TEST3	(0x0078)
+#define DMA_TEST4	(0x007C)
+#define DMA_STATUS_Y	(0x0080)
+
+
+#define DMA_DATA_ADDR1	(0x0084)
+#define DMA_STRIDE1	(0x0088)
+#define DMA_STRETCH_STRIDE1	(0x008C)
+#define DMA_DATA_NUM1	(0x0090)
+
+#define DMA_TEST0_U	(0x0094)
+#define DMA_TEST1_U	(0x0098)
+#define DMA_TEST3_U	(0x009C)
+#define DMA_TEST4_U	(0x00A0)
+#define DMA_STATUS_U	(0x00A4)
+
+
+#define DMA_DATA_ADDR2	(0x00A8)
+#define DMA_STRIDE2	(0x00AC)
+#define DMA_STRETCH_STRIDE2	(0x00B0)
+#define DMA_DATA_NUM2	(0x00B4)
+
+#define DMA_TEST0_V	(0x00B8)
+#define DMA_TEST1_V	(0x00BC)
+#define DMA_TEST3_V	(0x00C0)
+#define DMA_TEST4_V	(0x00C4)
+#define DMA_STATUS_V	(0x00C8)
+
+
+#define CH_RD_SHADOW	(0x00D0)
+#define CH_CTL	(0x00D4)
+#define CH_SECU_EN	(0x00D8)
+#define CH_SW_END_REQ	(0x00DC)
+#define CH_CLK_SEL	(0x00E0)
+#define CH_CLK_EN	(0x00E4)
+
+/*******************************************************************************
+ ** DFC
+ */
+#define DFC_DISP_SIZE	(0x0000)
+#define DFC_PIX_IN_NUM	(0x0004)
+#define DFC_GLB_ALPHA	(0x0008)
+#define DFC_DISP_FMT	(0x000C)
+#define DFC_CLIP_CTL_HRZ	(0x0010)
+#define DFC_CLIP_CTL_VRZ	(0x0014)
+#define DFC_CTL_CLIP_EN	(0x0018)
+#define DFC_ICG_MODULE	(0x001C)
+#define DFC_DITHER_ENABLE	(0x0020)
+#define DFC_PADDING_CTL	(0x0024)
+
+typedef struct dss_dfc {
+	uint32_t disp_size;
+	uint32_t pix_in_num;
+	uint32_t disp_fmt;
+	uint32_t clip_ctl_hrz;
+	uint32_t clip_ctl_vrz;
+	uint32_t ctl_clip_en;
+	uint32_t icg_module;
+	uint32_t dither_enable;
+	uint32_t padding_ctl;
+} dss_dfc_t;
+
+/*******************************************************************************
+ ** SCF
+ */
+#define DSS_SCF_H0_Y_COEF_OFFSET	(0x0000)
+#define DSS_SCF_Y_COEF_OFFSET	(0x2000)
+#define DSS_SCF_UV_COEF_OFFSET	(0x2800)
+
+#define SCF_EN_HSCL_STR	(0x0000)
+#define SCF_EN_VSCL_STR	(0x0004)
+#define SCF_H_V_ORDER	(0x0008)
+#define SCF_SCF_CORE_GT	(0x000C)
+#define SCF_INPUT_WIDTH_HEIGHT	(0x0010)
+#define SCF_OUTPUT_WIDTH_HEIGHT	(0x0014)
+#define SCF_COEF_MEM_CTRL  (0x0018)
+#define SCF_EN_HSCL	(0x001C)
+#define SCF_EN_VSCL	(0x0020)
+#define SCF_ACC_HSCL	(0x0024)
+#define SCF_ACC_HSCL1	(0x0028)
+#define SCF_INC_HSCL	(0x0034)
+#define SCF_ACC_VSCL	(0x0038)
+#define SCF_ACC_VSCL1	(0x003C)
+#define SCF_INC_VSCL	(0x0048)
+#define SCF_EN_NONLINEAR	(0x004C)
+#define SCF_EN_MMP	(0x007C)
+#define SCF_DB_H0	(0x0080)
+#define SCF_DB_H1	(0x0084)
+#define SCF_DB_V0	(0x0088)
+#define SCF_DB_V1	(0x008C)
+#define SCF_LB_MEM_CTRL	(0x0090)
+#define SCF_RD_SHADOW	(0x00F0)
+#define SCF_CLK_SEL	(0x00F8)
+#define SCF_CLK_EN	(0x00FC)
+
+/* MACROS */
+#define SCF_MIN_INPUT	(16)
+#define SCF_MIN_OUTPUT	(16)
+
+/* Threshold for SCF Stretch and SCF filter */
+#define RDMA_STRETCH_THRESHOLD	(2)
+#define SCF_INC_FACTOR	(1 << 18)
+#define SCF_UPSCALE_MAX	(60)
+#define SCF_DOWNSCALE_MAX	  (60)
+#define SCF_EDGE_FACTOR (3)
+#define ARSR2P_INC_FACTOR (65536)
+
+typedef struct dss_scl {
+	uint32_t en_hscl_str;
+	uint32_t en_vscl_str;
+	uint32_t h_v_order;
+	uint32_t input_width_height;
+	uint32_t output_width_height;
+	uint32_t en_hscl;
+	uint32_t en_vscl;
+	uint32_t acc_hscl;
+	uint32_t inc_hscl;
+	uint32_t inc_vscl;
+	uint32_t en_mmp;
+	uint32_t scf_ch_core_gt;
+	uint32_t fmt;
+} dss_scl_t;
+
+enum scl_coef_lut_idx {
+	SCL_COEF_NONE_IDX = -1,
+	SCL_COEF_YUV_IDX = 0,
+	SCL_COEF_RGB_IDX = 1,
+	SCL_COEF_IDX_MAX = 2,
+};
+
+/*******************************************************************************
+ ** ARSR2P  v0
+ */
+#define ARSR2P_INPUT_WIDTH_HEIGHT		(0x000)
+#define ARSR2P_OUTPUT_WIDTH_HEIGHT		(0x004)
+#define ARSR2P_IHLEFT		(0x008)
+#define ARSR2P_IHRIGHT		(0x00C)
+#define ARSR2P_IVTOP		(0x010)
+#define ARSR2P_IVBOTTOM		(0x014)
+#define ARSR2P_IHINC		(0x018)
+#define ARSR2P_IVINC		(0x01C)
+#define ARSR2P_UV_OFFSET		(0x020)
+#define ARSR2P_MODE		(0x024)
+#define ARSR2P_SKIN_THRES_Y		(0x028)
+#define ARSR2P_SKIN_THRES_U		(0x02C)
+#define ARSR2P_SKIN_THRES_V		(0x030)
+#define ARSR2P_SKIN_CFG0		(0x034)
+#define ARSR2P_SKIN_CFG1		(0x038)
+#define ARSR2P_SKIN_CFG2		(0x03C)
+#define ARSR2P_SHOOT_CFG1		(0x040)
+#define ARSR2P_SHOOT_CFG2		(0x044)
+#define ARSR2P_SHARP_CFG1		(0x048)
+#define ARSR2P_SHARP_CFG2		(0x04C)
+#define ARSR2P_SHARP_CFG3		(0x050)
+#define ARSR2P_SHARP_CFG4		(0x054)
+#define ARSR2P_SHARP_CFG5		(0x058)
+#define ARSR2P_SHARP_CFG6		(0x05C)
+#define ARSR2P_SHARP_CFG7		(0x060)
+#define ARSR2P_SHARP_CFG8		(0x064)
+#define ARSR2P_SHARP_CFG9		(0x068)
+#define ARSR2P_TEXTURW_ANALYSTS		(0x06C)
+#define ARSR2P_INTPLSHOOTCTRL		(0x070)
+#define ARSR2P_DEBUG0		(0x074)
+#define ARSR2P_DEBUG1		(0x078)
+#define ARSR2P_DEBUG2		(0x07C)
+#define ARSR2P_DEBUG3		(0x080)
+#define ARSR2P_LB_MEM_CTRL		(0x084)
+#define ARSR2P_IHLEFT1		(0x088)
+#define ARSR2P_IHRIGHT1		(0x090)
+#define ARSR2P_IVBOTTOM1		(0x094)
+
+#define ARSR2P_LUT_COEFY_V_OFFSET (0x0000)
+#define ARSR2P_LUT_COEFY_H_OFFSET (0x0100)
+#define ARSR2P_LUT_COEFA_V_OFFSET (0x0300)
+#define ARSR2P_LUT_COEFA_H_OFFSET (0x0400)
+#define ARSR2P_LUT_COEFUV_V_OFFSET (0x0600)
+#define ARSR2P_LUT_COEFUV_H_OFFSET (0x0700)
+
+typedef struct dss_arsr2p_effect {
+	uint32_t skin_thres_y;
+	uint32_t skin_thres_u;
+	uint32_t skin_thres_v;
+	uint32_t skin_cfg0;
+	uint32_t skin_cfg1;
+	uint32_t skin_cfg2;
+	uint32_t shoot_cfg1;
+	uint32_t shoot_cfg2;
+	uint32_t sharp_cfg1;
+	uint32_t sharp_cfg2;
+	uint32_t sharp_cfg3;
+	uint32_t sharp_cfg4;
+	uint32_t sharp_cfg5;
+	uint32_t sharp_cfg6;
+	uint32_t sharp_cfg7;
+	uint32_t sharp_cfg8;
+	uint32_t sharp_cfg9;
+	uint32_t texturw_analysts;
+	uint32_t intplshootctrl;
+} dss_arsr2p_effect_t;
+
+typedef struct dss_arsr2p {
+	uint32_t arsr_input_width_height;
+	uint32_t arsr_output_width_height;
+	uint32_t ihleft;
+	uint32_t ihright;
+	uint32_t ivtop;
+	uint32_t ivbottom;
+	uint32_t ihinc;
+	uint32_t ivinc;
+	uint32_t offset;
+	uint32_t mode;
+	dss_arsr2p_effect_t arsr2p_effect;
+	uint32_t ihleft1;
+	uint32_t ihright1;
+	uint32_t ivbottom1;
+} dss_arsr2p_t;
+
+/*******************************************************************************
+ ** POST_CLIP  v g
+ */
+#define POST_CLIP_DISP_SIZE	(0x0000)
+#define POST_CLIP_CTL_HRZ	(0x0010)
+#define POST_CLIP_CTL_VRZ	(0x0014)
+#define POST_CLIP_EN	(0x0018)
+
+typedef struct dss_post_clip {
+	uint32_t disp_size;
+	uint32_t clip_ctl_hrz;
+	uint32_t clip_ctl_vrz;
+	uint32_t ctl_clip_en;
+} dss_post_clip_t;
+
+/*******************************************************************************
+ ** PCSC v
+ */
+#define PCSC_IDC0	(0x0000)
+#define PCSC_IDC2	(0x0004)
+#define PCSC_ODC0	(0x0008)
+#define PCSC_ODC2	(0x000C)
+#define PCSC_P0	(0x0010)
+#define PCSC_P1	(0x0014)
+#define PCSC_P2	(0x0018)
+#define PCSC_P3	(0x001C)
+#define PCSC_P4	(0x0020)
+#define PCSC_ICG_MODULE	(0x0024)
+#define PCSC_MPREC	(0x0028)
+
+typedef struct dss_pcsc {
+	uint32_t pcsc_idc0;
+} dss_pcsc_t;
+
+/*******************************************************************************
+ ** CSC
+ */
+#define CSC_IDC0	(0x0000)
+#define CSC_IDC2	(0x0004)
+#define CSC_ODC0	(0x0008)
+#define CSC_ODC2	(0x000C)
+#define CSC_P0	(0x0010)
+#define CSC_P1	(0x0014)
+#define CSC_P2	(0x0018)
+#define CSC_P3	(0x001C)
+#define CSC_P4	(0x0020)
+#define CSC_ICG_MODULE	(0x0024)
+#define CSC_MPREC	(0x0028)
+
+typedef struct dss_csc {
+	uint32_t idc0;
+	uint32_t idc2;
+	uint32_t odc0;
+	uint32_t odc2;
+	uint32_t p0;
+	uint32_t p1;
+	uint32_t p2;
+	uint32_t p3;
+	uint32_t p4;
+	uint32_t icg_module;
+	uint32_t mprec;
+} dss_csc_t;
+
+/*******************************************************************************
+ **channel DEBUG
+ */
+#define CH_DEBUG_SEL (0x600)
+
+/*******************************************************************************
+ ** VPP
+ */
+#define VPP_CTRL (0x700)
+#define VPP_MEM_CTRL (0x704)
+
+/*******************************************************************************
+ **DMA BUF
+ */
+#define DMA_BUF_CTRL	(0x800)
+#define DMA_BUF_SIZE  (0x850)
+#define DMA_BUF_MEM_CTRL	(0x854)
+#define DMA_BUF_DBG0 (0x0838)
+#define DMA_BUF_DBG1 (0x083c)
+
+
+#define AFBCD_HREG_HDR_PTR_LO	(0x900)
+#define AFBCD_HREG_PIC_WIDTH	(0x904)
+#define AFBCD_HREG_PIC_HEIGHT	(0x90C)
+#define AFBCD_HREG_FORMAT	(0x910)
+#define AFBCD_CTL		(0x914)
+#define AFBCD_STR	(0x918)
+#define AFBCD_LINE_CROP	(0x91C)
+#define AFBCD_INPUT_HEADER_STRIDE	(0x920)
+#define AFBCD_PAYLOAD_STRIDE	(0x924)
+#define AFBCD_MM_BASE_0	(0x928)
+#define AFBCD_AFBCD_PAYLOAD_POINTER	(0x930)
+#define AFBCD_HEIGHT_BF_STR	(0x934)
+#define AFBCD_OS_CFG	(0x938)
+#define AFBCD_MEM_CTRL	(0x93C)
+#define AFBCD_SCRAMBLE_MODE	(0x940)
+#define AFBCD_HEADER_POINTER_OFFSET	(0x944)
+#define AFBCD_MONITOR_REG1_OFFSET	(0x948)
+#define AFBCD_MONITOR_REG2_OFFSET	(0x94C)
+#define AFBCD_MONITOR_REG3_OFFSET	(0x950)
+#define AFBCD_DEBUG_REG0_OFFSET	(0x954)
+
+
+#define AFBCE_HREG_PIC_BLKS	(0x900)
+#define AFBCE_HREG_FORMAT	(0x904)
+#define AFBCE_HREG_HDR_PTR_LO	(0x908)
+#define AFBCE_HREG_PLD_PTR_LO	(0x90C)
+#define AFBCE_PICTURE_SIZE	(0x910)
+#define AFBCE_CTL	(0x914)
+#define AFBCE_HEADER_SRTIDE	(0x918)
+#define AFBCE_PAYLOAD_STRIDE	(0x91C)
+#define AFBCE_ENC_OS_CFG	(0x920)
+#define AFBCE_MEM_CTRL	(0x924)
+#define AFBCE_QOS_CFG	(0x928)
+#define AFBCE_THRESHOLD	(0x92C)
+#define AFBCE_SCRAMBLE_MODE	(0x930)
+#define AFBCE_HEADER_POINTER_OFFSET	(0x934)
+
+
+#define ROT_FIRST_LNS	(0x530)
+#define ROT_STATE	(0x534)
+#define ROT_MEM_CTRL		(0x538)
+#define ROT_SIZE	(0x53C)
+#define ROT_CPU_CTL0	(0x540)
+#define ROT_CPU_START0	(0x544)
+#define ROT_CPU_ADDR0	(0x548)
+#define ROT_CPU_RDATA0	(0x54C)
+#define ROT_CPU_RDATA1	(0x550)
+#define ROT_CPU_WDATA0	(0x554)
+#define ROT_CPU_WDATA1	(0x558)
+#define ROT_CPU_CTL1	(0x55C)
+#define ROT_CPU_START1	(0x560)
+#define ROT_CPU_ADDR1	(0x564)
+#define ROT_CPU_RDATA2	(0x568)
+#define ROT_CPU_RDATA3	(0x56C)
+#define ROT_CPU_WDATA2	(0x570)
+#define ROT_CPU_WDATA3	(0x574)
+
+
+#define CH_REG_DEFAULT (0x0A00)
+
+/* MACROS */
+#define MIN_INTERLEAVE	(7)
+#define MAX_TILE_SURPORT_NUM	(6)
+
+/* DMA aligned limited:  128bits aligned */
+#define DMA_ALIGN_BYTES	(128 / BITS_PER_BYTE)
+#define DMA_ADDR_ALIGN	(128 / BITS_PER_BYTE)
+#define DMA_STRIDE_ALIGN	(128 / BITS_PER_BYTE)
+
+#define TILE_DMA_ADDR_ALIGN	(256 * 1024)
+
+#define DMA_IN_WIDTH_MAX	(2048)
+#define DMA_IN_HEIGHT_MAX	(8192)
+
+#define AFBC_PIC_WIDTH_MIN	(16)
+#define AFBC_PIC_WIDTH_MAX	(8192)
+#define AFBC_PIC_HEIGHT_MIN	(16)
+#define AFBC_PIC_HEIGHT_MAX	(4096)
+
+#define AFBCD_TOP_CROP_MAX	(15)
+#define AFBCD_BOTTOM_CROP_MAX	(15)
+
+
+#define AFBC_HEADER_STRIDE_BLOCK	(16)
+
+#define AFBC_PAYLOAD_STRIDE_BLOCK	(1024)
+
+#define AFBC_SUPER_GRAPH_HEADER_ADDR_ALIGN	(128)
+#define AFBC_HEADER_ADDR_ALIGN	(64)
+#define AFBC_HEADER_STRIDE_ALIGN	(64)
+
+#define AFBC_PAYLOAD_ADDR_ALIGN_32	(1024)
+#define AFBC_PAYLOAD_STRIDE_ALIGN_32	(1024)
+#define AFBC_PAYLOAD_ADDR_ALIGN_16	(512)
+#define AFBC_PAYLOAD_STRIDE_ALIGN_16	(512)
+
+
+#define AFBC_BLOCK_ALIGN	(16)
+
+#define AFBCE_IN_WIDTH_MAX	(512)
+#define WROT_IN_WIDTH_MAX	(512)
+
+#define MMBUF_BASE	(0x40)
+#define MMBUF_LINE_NUM	(8)
+#define MMBUF_ADDR_ALIGN	(64)
+
+enum DSS_AFBC_HALF_BLOCK_MODE {
+	AFBC_HALF_BLOCK_UPPER_LOWER_ALL = 0,
+	AFBC_HALF_BLOCK_LOWER_UPPER_ALL,
+	AFBC_HALF_BLOCK_UPPER_ONLY,
+	AFBC_HALF_BLOCK_LOWER_ONLY,
+};
+
+typedef struct dss_rdma {
+	uint32_t oft_x0;
+	uint32_t oft_y0;
+	uint32_t oft_x1;
+	uint32_t oft_y1;
+	uint32_t mask0;
+	uint32_t mask1;
+	uint32_t stretch_size_vrt;
+	uint32_t ctrl;
+	uint32_t tile_scram;
+
+	uint32_t data_addr0;
+	uint32_t stride0;
+	uint32_t stretch_stride0;
+	uint32_t data_num0;
+
+	uint32_t data_addr1;
+	uint32_t stride1;
+	uint32_t stretch_stride1;
+	uint32_t data_num1;
+
+	uint32_t data_addr2;
+	uint32_t stride2;
+	uint32_t stretch_stride2;
+	uint32_t data_num2;
+
+	uint32_t ch_rd_shadow;
+	uint32_t ch_ctl;
+
+	uint32_t dma_buf_ctrl;
+
+	uint32_t vpp_ctrl;
+	uint32_t vpp_mem_ctrl;
+
+	uint32_t afbcd_hreg_hdr_ptr_lo;
+	uint32_t afbcd_hreg_pic_width;
+	uint32_t afbcd_hreg_pic_height;
+	uint32_t afbcd_hreg_format;
+	uint32_t afbcd_ctl;
+	uint32_t afbcd_str;
+	uint32_t afbcd_line_crop;
+	uint32_t afbcd_input_header_stride;
+	uint32_t afbcd_payload_stride;
+	uint32_t afbcd_mm_base_0;
+
+	uint32_t afbcd_afbcd_payload_pointer;
+	uint32_t afbcd_height_bf_str;
+	uint32_t afbcd_os_cfg;
+	uint32_t afbcd_mem_ctrl;
+	uint32_t afbcd_scramble_mode;
+	uint32_t afbcd_header_pointer_offset;
+
+	uint8_t vpp_used;
+	uint8_t afbc_used;
+} dss_rdma_t;
+
+typedef struct dss_wdma {
+	uint32_t oft_x0;
+	uint32_t oft_y0;
+	uint32_t oft_x1;
+	uint32_t oft_y1;
+
+	uint32_t mask0;
+	uint32_t mask1;
+	uint32_t stretch_size_vrt;
+	uint32_t ctrl;
+	uint32_t tile_scram;
+
+	uint32_t sw_mask_en;
+	uint32_t start_mask0;
+	uint32_t end_mask0;
+	uint32_t start_mask1;
+	uint32_t end_mask1;
+
+	uint32_t data_addr;
+	uint32_t stride0;
+	uint32_t data1_addr;
+	uint32_t stride1;
+
+	uint32_t stretch_stride;
+	uint32_t data_num;
+
+	uint32_t ch_rd_shadow;
+	uint32_t ch_ctl;
+	uint32_t ch_secu_en;
+	uint32_t ch_sw_end_req;
+
+	uint32_t dma_buf_ctrl;
+	uint32_t dma_buf_size;
+
+	uint32_t rot_size;
+
+	uint32_t afbce_hreg_pic_blks;
+	uint32_t afbce_hreg_format;
+	uint32_t afbce_hreg_hdr_ptr_lo;
+	uint32_t afbce_hreg_pld_ptr_lo;
+	uint32_t afbce_picture_size;
+	uint32_t afbce_ctl;
+	uint32_t afbce_header_srtide;
+	uint32_t afbce_payload_stride;
+	uint32_t afbce_enc_os_cfg;
+	uint32_t afbce_mem_ctrl;
+	uint32_t afbce_qos_cfg;
+	uint32_t afbce_threshold;
+	uint32_t afbce_scramble_mode;
+	uint32_t afbce_header_pointer_offset;
+
+	uint8_t afbc_used;
+	uint8_t rot_used;
+} dss_wdma_t;
+
+/*******************************************************************************
+ ** CE
+
+#define CE_HIST_RESET	(0x00)
+#define CE_HIST_CTL	(0x04)
+#define CE_HIST_FRAME_CNT	(0x08)
+#define CE_SIZE	(0x0C)
+#define CE_NO_STAT_LINES	(0x10)
+#define CE_BLACK_REGION_THRE	(0x14)
+#define CE_WHITE_REGION_THRE	(0x18)
+#define CE_LUT_SEL	(0x1C)
+#define CE_LUT_ENABLE	(0x20)
+#define CE_LUT_USING_IND	(0x54)
+#define CE_STATE_IND	(0x58)
+#define CE_MEM_CTRL	(0x5C)
+
+#define CE_TOTALGRAY	(0x30)
+#define CE_TOTALPIXL	(0x34)
+#define CE_MEAN	(0x38)
+#define CE_PEC0_3	(0x3C)
+#define CE_PEC4_7	(0x40)
+#define CE_PEC8	(0x44)
+#define CE_BLACK_NUM	(0x48)
+#define CE_WHITE_NUM	(0x4C)
+#define CE_HIST_RPT_IND	(0x50)
+
+typedef struct dss_ce {
+uint32_t hist_reset;
+uint32_t hist_ctl;
+uint32_t hist_frame_cnt;
+uint32_t size;
+uint32_t no_stat_lines;
+uint32_t black_region_thre;
+uint32_t white_region_thre;
+uint32_t lut_sel;
+uint32_t lut_enable;
+uint32_t mem_ctrl;
+
+uint32_t totalgray;
+uint32_t totalpixl;
+uint32_t mean;
+uint32_t pec0_3;
+uint32_t pec4_7;
+uint32_t pec8;
+uint32_t black_num;
+uint32_t white_num;
+uint32_t hist_rpt_ind;
+char __iomem *lut_base;
+uint8_t *lut_table;
+} dss_ce_t;*/
+
+/*******************************************************************************
+ ** MCTL  MUTEX0 1 2 3 4 5
+ */
+#define MCTL_CTL_EN	(0x0000)
+#define MCTL_CTL_MUTEX	(0x0004)
+#define MCTL_CTL_MUTEX_STATUS	(0x0008)
+#define MCTL_CTL_MUTEX_ITF	(0x000C)
+#define MCTL_CTL_MUTEX_DBUF	(0x0010)
+#define MCTL_CTL_MUTEX_SCF	(0x0014)
+#define MCTL_CTL_MUTEX_OV	(0x0018)
+#define MCTL_CTL_MUTEX_WCH0	(0x0020)
+#define MCTL_CTL_MUTEX_WCH1	(0x0024)
+#define MCTL_CTL_MUTEX_WCH2	(0x0028)
+#define MCTL_CTL_MUTEX_RCH8	(0x002C)
+#define MCTL_CTL_MUTEX_RCH0	(0x0030)
+#define MCTL_CTL_MUTEX_RCH1	(0x0034)
+#define MCTL_CTL_MUTEX_RCH2	(0x0038)
+#define MCTL_CTL_MUTEX_RCH3	(0x003C)
+#define MCTL_CTL_MUTEX_RCH4	(0x0040)
+#define MCTL_CTL_MUTEX_RCH5	(0x0044)
+#define MCTL_CTL_MUTEX_RCH6	(0x0048)
+#define MCTL_CTL_MUTEX_RCH7	(0x004C)
+#define MCTL_CTL_TOP	(0x0050)
+#define MCTL_CTL_FLUSH_STATUS	(0x0054)
+#define MCTL_CTL_CLEAR	(0x0058)
+#define MCTL_CTL_CACK_TOUT	(0x0060)
+#define MCTL_CTL_MUTEX_TOUT	(0x0064)
+#define MCTL_CTL_STATUS	(0x0068)
+#define MCTL_CTL_INTEN	(0x006C)
+#define MCTL_CTL_SW_ST	(0x0070)
+#define MCTL_CTL_ST_SEL	(0x0074)
+#define MCTL_CTL_END_SEL	(0x0078)
+#define MCTL_CTL_CLK_SEL	(0x0080)
+#define MCTL_CTL_CLK_EN	(0x0084)
+#define MCTL_CTL_DBG	(0x00E0)
+
+/*******************************************************************************
+ ** MCTL  SYS
+ */
+
+#define MCTL_CTL_SECU_CFG	(0x0000)
+#define MCTL_PAY_SECU_FLUSH_EN  (0x0018)
+#define MCTL_CTL_SECU_GATE0	(0x0080)
+#define MCTL_CTL_SECU_GATE1	(0x0084)
+#define MCTL_CTL_SECU_GATE2	(0x0088)
+#define MCTL_DSI0_SECU_CFG_EN	(0x00A0)
+#define MCTL_DSI1_SECU_CFG_EN	(0x00A4)
+
+#define MCTL_RCH0_FLUSH_EN	(0x0100)
+#define MCTL_RCH1_FLUSH_EN	(0x0104)
+#define MCTL_RCH2_FLUSH_EN	(0x0108)
+#define MCTL_RCH3_FLUSH_EN	(0x010C)
+#define MCTL_RCH4_FLUSH_EN	(0x0110)
+#define MCTL_RCH5_FLUSH_EN	(0x0114)
+#define MCTL_RCH6_FLUSH_EN	(0x0118)
+#define MCTL_RCH7_FLUSH_EN	(0x011C)
+#define MCTL_WCH0_FLUSH_EN	(0x0120)
+#define MCTL_WCH1_FLUSH_EN	(0x0124)
+#define MCTL_OV0_FLUSH_EN	(0x0128)
+#define MCTL_OV1_FLUSH_EN	(0x012C)
+#define MCTL_OV2_FLUSH_EN	(0x0130)
+#define MCTL_OV3_FLUSH_EN	(0x0134)
+#define MCTL_RCH8_FLUSH_EN	(0x0138)
+#define MCTL_WCH2_FLUSH_EN	(0x013C)
+
+#define MCTL_RCH0_OV_OEN	(0x0160)
+#define MCTL_RCH1_OV_OEN	(0x0164)
+#define MCTL_RCH2_OV_OEN	(0x0168)
+#define MCTL_RCH3_OV_OEN	(0x016C)
+#define MCTL_RCH4_OV_OEN	(0x0170)
+#define MCTL_RCH5_OV_OEN	(0x0174)
+#define MCTL_RCH6_OV_OEN	(0x0178)
+#define MCTL_RCH7_OV_OEN	(0x017C)
+
+#define MCTL_RCH_OV0_SEL	(0x0180)
+#define MCTL_RCH_OV1_SEL	(0x0184)
+#define MCTL_RCH_OV2_SEL	(0x0188)
+#define MCTL_RCH_OV3_SEL	(0x018C)
+
+#define MCTL_WCH0_OV_IEN   (0x01A0)
+#define MCTL_WCH1_OV_IEN   (0x01A4)
+
+#define MCTL_WCH_OV2_SEL   (0x01A8)
+#define MCTL_WCH_OV3_SEL   (0x01AC)
+
+#define MCTL_WB_ENC_SEL	(0x01B0)
+#define MCTL_DSI_MUX_SEL	(0x01B4)
+
+#define MCTL_RCH0_STARTY	(0x01C0)
+#define MCTL_RCH1_STARTY	(0x01C4)
+#define MCTL_RCH2_STARTY	(0x01C8)
+#define MCTL_RCH3_STARTY	(0x01CC)
+#define MCTL_RCH4_STARTY	(0x01D0)
+#define MCTL_RCH5_STARTY	(0x01D4)
+#define MCTL_RCH6_STARTY	(0x01D8)
+#define MCTL_RCH7_STARTY	(0x01DC)
+
+#define MCTL_MCTL_CLK_SEL	(0x01F0)
+#define MCTL_MCTL_CLK_EN	(0x01F4)
+#define MCTL_MOD_CLK_SEL	(0x01F8)
+#define MCTL_MOD_CLK_EN	(0x01FC)
+
+#define MCTL_MOD0_DBG	(0x0200)
+#define MCTL_MOD1_DBG	(0x0204)
+#define MCTL_MOD2_DBG	(0x0208)
+#define MCTL_MOD3_DBG	(0x020C)
+#define MCTL_MOD4_DBG	(0x0210)
+#define MCTL_MOD5_DBG	(0x0214)
+#define MCTL_MOD6_DBG	(0x0218)
+#define MCTL_MOD7_DBG	(0x021C)
+#define MCTL_MOD8_DBG	(0x0220)
+#define MCTL_MOD9_DBG	(0x0224)
+#define MCTL_MOD10_DBG	(0x0228)
+#define MCTL_MOD11_DBG	(0x022C)
+#define MCTL_MOD12_DBG	(0x0230)
+#define MCTL_MOD13_DBG	(0x0234)
+#define MCTL_MOD14_DBG	(0x0238)
+#define MCTL_MOD15_DBG	(0x023C)
+#define MCTL_MOD16_DBG	(0x0240)
+#define MCTL_MOD17_DBG	(0x0244)
+#define MCTL_MOD18_DBG	(0x0248)
+#define MCTL_MOD19_DBG	(0x024C)
+#define MCTL_MOD20_DBG	(0x0250)
+#define MCTL_MOD0_STATUS	(0x0280)
+#define MCTL_MOD1_STATUS	(0x0284)
+#define MCTL_MOD2_STATUS	(0x0288)
+#define MCTL_MOD3_STATUS	(0x028C)
+#define MCTL_MOD4_STATUS	(0x0290)
+#define MCTL_MOD5_STATUS	(0x0294)
+#define MCTL_MOD6_STATUS	(0x0298)
+#define MCTL_MOD7_STATUS	(0x029C)
+#define MCTL_MOD8_STATUS	(0x02A0)
+#define MCTL_MOD9_STATUS	(0x02A4)
+#define MCTL_MOD10_STATUS	(0x02A8)
+#define MCTL_MOD11_STATUS	(0x02AC)
+#define MCTL_MOD12_STATUS	(0x02B0)
+#define MCTL_MOD13_STATUS	(0x02B4)
+#define MCTL_MOD14_STATUS	(0x02B8)
+#define MCTL_MOD15_STATUS	(0x02BC)
+#define MCTL_MOD16_STATUS	(0x02C0)
+#define MCTL_MOD17_STATUS	(0x02C4)
+#define MCTL_MOD18_STATUS	(0x02C8)
+#define MCTL_MOD19_STATUS	(0x02CC)
+#define MCTL_MOD20_STATUS	(0x02D0)
+#define MCTL_SW_DBG	(0x0300)
+#define MCTL_SW0_STATUS0	(0x0304)
+#define MCTL_SW0_STATUS1	(0x0308)
+#define MCTL_SW0_STATUS2	(0x030C)
+#define MCTL_SW0_STATUS3	(0x0310)
+#define MCTL_SW0_STATUS4	(0x0314)
+#define MCTL_SW0_STATUS5	(0x0318)
+#define MCTL_SW0_STATUS6	(0x031C)
+#define MCTL_SW0_STATUS7	(0x0320)
+#define MCTL_SW1_STATUS	(0x0324)
+
+
+#define MCTL_MOD_DBG_CH_NUM (10)
+#define MCTL_MOD_DBG_OV_NUM (4)
+#define MCTL_MOD_DBG_DBUF_NUM (2)
+#define MCTL_MOD_DBG_SCF_NUM (1)
+#define MCTL_MOD_DBG_ITF_NUM (2)
+#define MCTL_MOD_DBG_ADD_CH_NUM (2)
+
+enum dss_mctl_idx {
+	DSS_MCTL0 = 0,
+	DSS_MCTL1,
+	DSS_MCTL2,
+	DSS_MCTL3,
+	DSS_MCTL4,
+	DSS_MCTL5,
+	DSS_MCTL_IDX_MAX,
+};
+
+typedef struct dss_mctl {
+	uint32_t ctl_mutex_itf;
+	uint32_t ctl_mutex_dbuf;
+	uint32_t ctl_mutex_scf;
+	uint32_t ctl_mutex_ov;
+} dss_mctl_t;
+
+typedef struct dss_mctl_ch_base {
+	char __iomem *chn_mutex_base;
+	char __iomem *chn_flush_en_base;
+	char __iomem *chn_ov_en_base;
+	char __iomem *chn_starty_base;
+	char __iomem *chn_mod_dbg_base;
+} dss_mctl_ch_base_t;
+
+typedef struct dss_mctl_ch {
+	uint32_t chn_mutex;
+	uint32_t chn_flush_en;
+	uint32_t chn_ov_oen;
+	uint32_t chn_starty;
+	uint32_t chn_mod_dbg;
+} dss_mctl_ch_t;
+
+typedef struct dss_mctl_sys {
+	uint32_t ov_flush_en[DSS_OVL_IDX_MAX];
+	uint32_t chn_ov_sel[DSS_OVL_IDX_MAX];
+	uint32_t wchn_ov_sel[DSS_WCH_MAX];
+	uint8_t ov_flush_en_used[DSS_OVL_IDX_MAX];
+	uint8_t chn_ov_sel_used[DSS_OVL_IDX_MAX];
+	uint8_t wch_ov_sel_used[DSS_WCH_MAX];
+} dss_mctl_sys_t;
+
+/*******************************************************************************
+ ** OVL
+ */
+#define OVL_SIZE	(0x0000)
+#define OVL_BG_COLOR	(0x4)
+#define OVL_DST_STARTPOS	(0x8)
+#define OVL_DST_ENDPOS	(0xC)
+#define OVL_GCFG	(0x10)
+#define OVL_LAYER0_POS	(0x14)
+#define OVL_LAYER0_SIZE	(0x18)
+#define OVL_LAYER0_SRCLOKEY	(0x1C)
+#define OVL_LAYER0_SRCHIKEY	(0x20)
+#define OVL_LAYER0_DSTLOKEY	(0x24)
+#define OVL_LAYER0_DSTHIKEY	(0x28)
+#define OVL_LAYER0_PATTERN	(0x2C)
+#define OVL_LAYER0_ALPHA	(0x30)
+#define OVL_LAYER0_CFG	(0x34)
+#define OVL_LAYER0_INFO_ALPHA	(0x40)
+#define OVL_LAYER0_INFO_SRCCOLOR	(0x44)
+#define OVL_LAYER1_POS	(0x50)
+#define OVL_LAYER1_SIZE	(0x54)
+#define OVL_LAYER1_SRCLOKEY	(0x58)
+#define OVL_LAYER1_SRCHIKEY	(0x5C)
+#define OVL_LAYER1_DSTLOKEY	(0x60)
+#define OVL_LAYER1_DSTHIKEY	(0x64)
+#define OVL_LAYER1_PATTERN	(0x68)
+#define OVL_LAYER1_ALPHA	(0x6C)
+#define OVL_LAYER1_CFG	(0x70)
+#define OVL_LAYER1_INFO_ALPHA	(0x7C)
+#define OVL_LAYER1_INFO_SRCCOLOR	(0x80)
+#define OVL_LAYER2_POS	(0x8C)
+#define OVL_LAYER2_SIZE	(0x90)
+#define OVL_LAYER2_SRCLOKEY	(0x94)
+#define OVL_LAYER2_SRCHIKEY	(0x98)
+#define OVL_LAYER2_DSTLOKEY	(0x9C)
+#define OVL_LAYER2_DSTHIKEY	(0xA0)
+#define OVL_LAYER2_PATTERN	(0xA4)
+#define OVL_LAYER2_ALPHA	(0xA8)
+#define OVL_LAYER2_CFG	(0xAC)
+#define OVL_LAYER2_INFO_ALPHA	(0xB8)
+#define OVL_LAYER2_INFO_SRCCOLOR	(0xBC)
+#define OVL_LAYER3_POS	(0xC8)
+#define OVL_LAYER3_SIZE	(0xCC)
+#define OVL_LAYER3_SRCLOKEY	(0xD0)
+#define OVL_LAYER3_SRCHIKEY	(0xD4)
+#define OVL_LAYER3_DSTLOKEY	(0xD8)
+#define OVL_LAYER3_DSTHIKEY	(0xDC)
+#define OVL_LAYER3_PATTERN	(0xE0)
+#define OVL_LAYER3_ALPHA	(0xE4)
+#define OVL_LAYER3_CFG	(0xE8)
+#define OVL_LAYER3_INFO_ALPHA	(0xF4)
+#define OVL_LAYER3_INFO_SRCCOLOR	(0xF8)
+#define OVL_LAYER4_POS	(0x104)
+#define OVL_LAYER4_SIZE	(0x108)
+#define OVL_LAYER4_SRCLOKEY	(0x10C)
+#define OVL_LAYER4_SRCHIKEY	(0x110)
+#define OVL_LAYER4_DSTLOKEY	(0x114)
+#define OVL_LAYER4_DSTHIKEY	(0x118)
+#define OVL_LAYER4_PATTERN	(0x11C)
+#define OVL_LAYER4_ALPHA	(0x120)
+#define OVL_LAYER4_CFG	(0x124)
+#define OVL_LAYER4_INFO_ALPHA	(0x130)
+#define OVL_LAYER4_INFO_SRCCOLOR	(0x134)
+#define OVL_LAYER5_POS	(0x140)
+#define OVL_LAYER5_SIZE	(0x144)
+#define OVL_LAYER5_SRCLOKEY	(0x148)
+#define OVL_LAYER5_SRCHIKEY	(0x14C)
+#define OVL_LAYER5_DSTLOKEY	(0x150)
+#define OVL_LAYER5_DSTHIKEY	(0x154)
+#define OVL_LAYER5_PATTERN	(0x158)
+#define OVL_LAYER5_ALPHA	(0x15C)
+#define OVL_LAYER5_CFG	(0x160)
+#define OVL_LAYER5_INFO_ALPHA	(0x16C)
+#define OVL_LAYER5_INFO_SRCCOLOR	(0x170)
+#define OVL_LAYER6_POS	(0x14)
+#define OVL_LAYER6_SIZE	(0x18)
+#define OVL_LAYER6_SRCLOKEY	(0x1C)
+#define OVL_LAYER6_SRCHIKEY	(0x20)
+#define OVL_LAYER6_DSTLOKEY	(0x24)
+#define OVL_LAYER6_DSTHIKEY	(0x28)
+#define OVL_LAYER6_PATTERN	(0x2C)
+#define OVL_LAYER6_ALPHA	(0x30)
+#define OVL_LAYER6_CFG	(0x34)
+#define OVL_LAYER6_INFO_ALPHA	(0x40)
+#define OVL_LAYER6_INFO_SRCCOLOR	(0x44)
+#define OVL_LAYER7_POS	(0x50)
+#define OVL_LAYER7_SIZE	(0x54)
+#define OVL_LAYER7_SRCLOKEY	(0x58)
+#define OVL_LAYER7_SRCHIKEY	(0x5C)
+#define OVL_LAYER7_DSTLOKEY	(0x60)
+#define OVL_LAYER7_DSTHIKEY	(0x64)
+#define OVL_LAYER7_PATTERN	(0x68)
+#define OVL_LAYER7_ALPHA	(0x6C)
+#define OVL_LAYER7_CFG	(0x70)
+#define OVL_LAYER7_INFO_ALPHA	(0x7C)
+#define OVL_LAYER7_INFO_SRCCOLOR	(0x80)
+#define OVL_LAYER0_ST_INFO	(0x48)
+#define OVL_LAYER1_ST_INFO	(0x84)
+#define OVL_LAYER2_ST_INFO	(0xC0)
+#define OVL_LAYER3_ST_INFO	(0xFC)
+#define OVL_LAYER4_ST_INFO	(0x138)
+#define OVL_LAYER5_ST_INFO	(0x174)
+#define OVL_LAYER6_ST_INFO	(0x48)
+#define OVL_LAYER7_ST_INFO	(0x84)
+#define OVL_LAYER0_IST_INFO	(0x4C)
+#define OVL_LAYER1_IST_INFO	(0x88)
+#define OVL_LAYER2_IST_INFO	(0xC4)
+#define OVL_LAYER3_IST_INFO	(0x100)
+#define OVL_LAYER4_IST_INFO	(0x13C)
+#define OVL_LAYER5_IST_INFO	(0x178)
+#define OVL_LAYER6_IST_INFO	(0x4C)
+#define OVL_LAYER7_IST_INFO	(0x88)
+#define OVL_LAYER0_PSPOS	(0x38)
+#define OVL_LAYER0_PEPOS	(0x3C)
+#define OVL_LAYER1_PSPOS	(0x74)
+#define OVL_LAYER1_PEPOS	(0x78)
+#define OVL_LAYER2_PSPOS	(0xB0)
+#define OVL_LAYER2_PEPOS	(0xB4)
+#define OVL_LAYER3_PSPOS	(0xEC)
+#define OVL_LAYER3_PEPOS	(0xF0)
+#define OVL_LAYER4_PSPOS	(0x128)
+#define OVL_LAYER4_PEPOS	(0x12C)
+#define OVL_LAYER5_PSPOS	(0x164)
+#define OVL_LAYER5_PEPOS	(0x168)
+#define OVL_LAYER6_PSPOS	(0x38)
+#define OVL_LAYER6_PEPOS	(0x3C)
+#define OVL_LAYER7_PSPOS	(0x74)
+#define OVL_LAYER7_PEPOS	(0x78)
+
+#define OVL6_BASE_ST_INFO	(0x17C)
+#define OVL6_BASE_IST_INFO	(0x180)
+#define OVL6_GATE_CTRL	(0x184)
+#define OVL6_RD_SHADOW_SEL	(0x188)
+#define OVL6_OV_CLK_SEL	(0x18C)
+#define OVL6_OV_CLK_EN	(0x190)
+#define OVL6_BLOCK_SIZE	(0x1A0)
+#define OVL6_BLOCK_DBG	(0x1A4)
+#define OVL6_REG_DEFAULT (0x1A8)
+
+#define OVL2_BASE_ST_INFO	(0x8C)
+#define OVL2_BASE_IST_INFO	(0x90)
+#define OVL2_GATE_CTRL	(0x94)
+#define OVL2_OV_RD_SHADOW_SEL	(0x98)
+#define OVL2_OV_CLK_SEL	(0x9C)
+#define OVL2_OV_CLK_EN	(0xA0)
+#define OVL2_BLOCK_SIZE	(0xB0)
+#define OVL2_BLOCK_DBG	(0xB4)
+#define OVL2_REG_DEFAULT	(0xB8)
+
+/* LAYER0_CFG */
+#define BIT_OVL_LAYER_SRC_CFG	BIT(8)
+#define BIT_OVL_LAYER_ENABLE	BIT(0)
+
+/* LAYER0_INFO_ALPHA */
+#define BIT_OVL_LAYER_SRCALPHA_FLAG	BIT(3)
+#define BIT_OVL_LAYER_DSTALPHA_FLAG	BIT(2)
+
+/* LAYER0_INFO_SRCCOLOR */
+#define BIT_OVL_LAYER_SRCCOLOR_FLAG	BIT(0)
+
+#define OVL_6LAYER_NUM		(6)
+#define OVL_2LAYER_NUM		(2)
+
+typedef struct dss_ovl_layer {
+	uint32_t layer_pos;
+	uint32_t layer_size;
+	uint32_t layer_pattern;
+	uint32_t layer_alpha;
+	uint32_t layer_cfg;
+
+} dss_ovl_layer_t;
+
+typedef struct dss_ovl_layer_pos {
+	uint32_t layer_pspos;
+	uint32_t layer_pepos;
+
+} dss_ovl_layer_pos_t;
+
+typedef struct dss_ovl {
+	uint32_t ovl_size;
+	uint32_t ovl_bg_color;
+	uint32_t ovl_dst_startpos;
+	uint32_t ovl_dst_endpos;
+	uint32_t ovl_gcfg;
+	uint32_t ovl_block_size;
+	dss_ovl_layer_t ovl_layer[OVL_6LAYER_NUM];
+	dss_ovl_layer_pos_t ovl_layer_pos[OVL_6LAYER_NUM];
+	uint8_t ovl_layer_used[OVL_6LAYER_NUM];
+} dss_ovl_t;
+
+typedef struct dss_ovl_alpha {
+	uint32_t src_amode;
+	uint32_t src_gmode;
+	uint32_t alpha_offsrc;
+	uint32_t src_lmode;
+	uint32_t src_pmode;
+
+	uint32_t alpha_smode;
+
+	uint32_t dst_amode;
+	uint32_t dst_gmode;
+	uint32_t alpha_offdst;
+	uint32_t dst_pmode;
+
+	uint32_t fix_mode;
+} dss_ovl_alpha_t;
+
+/*******************************************************************************
+ ** DBUF
+ */
+#define DBUF_FRM_SIZE	(0x0000)
+#define DBUF_FRM_HSIZE	(0x0004)
+#define DBUF_SRAM_VALID_NUM	(0x0008)
+#define DBUF_WBE_EN	(0x000C)
+#define DBUF_THD_FILL_LEV0	(0x0010)
+#define DBUF_DFS_FILL_LEV1	(0x0014)
+#define DBUF_THD_RQOS	(0x0018)
+#define DBUF_THD_WQOS	(0x001C)
+#define DBUF_THD_CG	(0x0020)
+#define DBUF_THD_OTHER	(0x0024)
+#define DBUF_FILL_LEV0_CNT	(0x0028)
+#define DBUF_FILL_LEV1_CNT	(0x002C)
+#define DBUF_FILL_LEV2_CNT	(0x0030)
+#define DBUF_FILL_LEV3_CNT	(0x0034)
+#define DBUF_FILL_LEV4_CNT	(0x0038)
+#define DBUF_ONLINE_FILL_LEVEL	(0x003C)
+#define DBUF_WB_FILL_LEVEL	(0x0040)
+#define DBUF_DFS_STATUS	(0x0044)
+#define DBUF_THD_FLUX_REQ_BEF	(0x0048)
+#define DBUF_DFS_LP_CTRL	(0x004C)
+#define DBUF_RD_SHADOW_SEL	(0x0050)
+#define DBUF_MEM_CTRL	(0x0054)
+#define DBUF_PM_CTRL	(0x0058)
+#define DBUF_CLK_SEL	(0x005C)
+#define DBUF_CLK_EN  	(0x0060)
+#define DBUF_THD_FLUX_REQ_AFT (0x0064)
+#define DBUF_THD_DFS_OK (0x0068)
+#define DBUF_FLUX_REQ_CTRL (0x006C)
+#define DBUF_REG_DEFAULT  (0x00A4)
+
+/*******************************************************************************
+ ** SBL
+ */
+
+#define SBL_REG_FRMT_MODE                                (0x0000)
+#define SBL_REG_FRMT_DBUF_CTRL                           (0x0008)
+#define SBL_REG_FRMT_FRAME_WIDTH_7_TO_0                  (0x0010)
+#define SBL_REG_FRMT_FRAME_WIDTH_15_TO_8                 (0x0014)
+#define SBL_REG_FRMT_FRAME_HEIGHT_7_TO_0                 (0x0018)
+#define SBL_REG_FRMT_FRAME_HEIGHT_15_TO_8                (0x001c)
+#define SBL_REG_FRMT_ROI_HOR_START_7_TO_0                (0x0080)
+#define SBL_REG_FRMT_ROI_HOR_START_15_TO_8               (0x0084)
+#define SBL_REG_FRMT_ROI_HOR_END_7_TO_0                  (0x0088)
+#define SBL_REG_FRMT_ROI_HOR_END_15_TO_8                 (0x008c)
+#define SBL_REG_FRMT_ROI_VER_START_7_TO_0                (0x0090)
+#define SBL_REG_FRMT_ROI_VER_START_15_TO_8               (0x0094)
+#define SBL_REG_FRMT_ROI_VER_END_7_TO_0                  (0x0098)
+#define SBL_REG_FRMT_ROI_VER_END_15_TO_8                 (0x009c)
+#define SBL_REG_CALC_CONTROL_0                           (0x0400)
+#define SBL_REG_CALC_CONTROL_1                           (0x0404)
+#define SBL_REG_CALC_AMBIENT_LIGHT_7_TO_0                (0x0408)
+#define SBL_REG_CALC_AMBIENT_LIGHT_15_TO_8               (0x040c)
+#define SBL_REG_CALC_BACKLIGHT_7_TO_0                    (0x0410)
+#define SBL_REG_CALC_BACKLIGHT_15_TO_8                   (0x0414)
+#define SBL_REG_CALC_ASSERTIVENESS                       (0x0418)
+#define SBL_REG_CALC_TF_CONTROL                          (0x041c)
+#define SBL_REG_CALC_STRENGTH_MANUAL_7_TO_0              (0x0420)
+#define SBL_REG_CALC_STRENGTH_MANUAL_9_TO_8              (0x0424)
+#define SBL_REG_CALC_GAIN_AA_MANUAL_7_TO_0               (0x0428)
+#define SBL_REG_CALC_GAIN_AA_MANUAL_11_TO_8              (0x042c)
+#define SBL_REG_CALC_ROI_FACTOR_IN_7_TO_0                (0x0430)
+#define SBL_REG_CALC_ROI_FACTOR_IN_15_TO_8               (0x0434)
+#define SBL_REG_CALC_ROI_FACTOR_OUT_7_TO_0               (0x0438)
+#define SBL_REG_CALC_ROI_FACTOR_OUT_15_TO_8              (0x043c)
+#define SBL_REG_CALC_PSR_DELTA_CHANGE_7_TO_0             (0x0448)
+#define SBL_REG_CALC_PSR_DELTA_CHANGE_15_TO_8            (0x044c)
+#define SBL_REG_CALC_PSR_DELTA_SETTLE_7_TO_0             (0x0450)
+#define SBL_REG_CALC_PSR_DELTA_SETTLE_15_TO_8            (0x0454)
+#define SBL_REG_CALC_AL_SCALE_7_TO_0                     (0x0458)
+#define SBL_REG_CALC_AL_SCALE_15_TO_8                    (0x045c)
+#define SBL_REG_CALC_AL_TF_STEP_SAMPLE                   (0x0460)
+#define SBL_REG_CALC_AL_TF_STEP_WAIT_7_TO_0              (0x0468)
+#define SBL_REG_CALC_AL_TF_STEP_WAIT_11_TO_8             (0x046c)
+#define SBL_REG_CALC_AL_TF_STEP_WAITUP_7_TO_0            (0x0470)
+#define SBL_REG_CALC_AL_TF_STEP_WAITUP_11_TO_8           (0x0474)
+#define SBL_REG_CALC_AL_TF_STEP_SIZE_7_TO_0              (0x0478)
+#define SBL_REG_CALC_AL_TF_STEP_SIZE_11_TO_8             (0x047c)
+#define SBL_REG_CALC_AL_TF_LIMIT_7_TO_0                  (0x0480)
+#define SBL_REG_CALC_AL_TF_LIMIT_15_TO_8                 (0x0484)
+#define SBL_REG_CALC_AL_TF_ALPHA                         (0x0488)
+#define SBL_REG_CALC_AL_TF_ALPHA_UP                      (0x048c)
+#define SBL_REG_CALC_AL_TF_NOISE_7_TO_0                  (0x0490)
+#define SBL_REG_CALC_AL_TF_NOISE_15_TO_8                 (0x0494)
+#define SBL_REG_CALC_AL_TF_M_INC_7_TO_0                  (0x0498)
+#define SBL_REG_CALC_AL_TF_M_INC_15_TO_8                 (0x049c)
+#define SBL_REG_CALC_AL_TF_K_INC_7_TO_0                  (0x04a0)
+#define SBL_REG_CALC_AL_TF_K_INC_15_TO_8                 (0x04a4)
+#define SBL_REG_CALC_AL_TF_M_DEC_7_TO_0                  (0x04a8)
+#define SBL_REG_CALC_AL_TF_M_DEC_15_TO_8                 (0x04ac)
+#define SBL_REG_CALC_AL_TF_K_DEC_7_TO_0                  (0x04b0)
+#define SBL_REG_CALC_AL_TF_K_DEC_15_TO_8                 (0x04b4)
+#define SBL_REG_CALC_AL_TF_AGGRESSIVENESS                (0x04b8)
+#define SBL_REG_CALC_AL_RTF_FILTER_A_7_TO_0              (0x04c0)
+#define SBL_REG_CALC_AL_RTF_FILTER_A_15_TO_8             (0x04c4)
+#define SBL_REG_CALC_AL_RTF_FILTER_B_7_TO_0              (0x04c8)
+#define SBL_REG_CALC_AL_RTF_FILTER_B_15_TO_8             (0x04cc)
+#define SBL_REG_CALC_AL_RTF_FILTER_C_7_TO_0              (0x04d0)
+#define SBL_REG_CALC_AL_RTF_FILTER_C_15_TO_8             (0x04d4)
+#define SBL_REG_CALC_AB_AL_KNEE1_7_TO_0                  (0x04d8)
+#define SBL_REG_CALC_AB_AL_KNEE1_15_TO_8                 (0x04dc)
+#define SBL_REG_CALC_AB_AL_KNEE2_7_TO_0                  (0x04e0)
+#define SBL_REG_CALC_AB_AL_KNEE2_15_TO_8                 (0x04e4)
+#define SBL_REG_CALC_AB_BL_KNEE1_7_TO_0                  (0x04e8)
+#define SBL_REG_CALC_AB_BL_KNEE1_15_TO_8                 (0x04ec)
+#define SBL_REG_CALC_AB_BL_KNEE2_7_TO_0                  (0x04f0)
+#define SBL_REG_CALC_AB_BL_KNEE2_15_TO_8                 (0x04f4)
+#define SBL_REG_CALC_BL_PANEL_MAX_7_TO_0                 (0x04f8)
+#define SBL_REG_CALC_BL_PANEL_MAX_15_TO_8                (0x04fc)
+#define SBL_REG_CALC_BL_OFFSET_7_TO_0                    (0x0500)
+#define SBL_REG_CALC_BL_OFFSET_15_TO_8                   (0x0504)
+#define SBL_REG_CALC_BL_MIN_7_TO_0                       (0x0508)
+#define SBL_REG_CALC_BL_MIN_15_TO_8                      (0x050c)
+#define SBL_REG_CALC_BL_ATTEN_ALPHA_7_TO_0               (0x0510)
+#define SBL_REG_CALC_BL_ATTEN_ALPHA_9_TO_8               (0x0514)
+#define SBL_REG_CALC_SBC1_TF_DEPTH_7_TO_0                (0x0518)
+#define SBL_REG_CALC_SBC1_TF_DEPTH_15_TO_8               (0x051c)
+#define SBL_REG_CALC_SBC1_TF_STEP_7_TO_0                 (0x0520)
+#define SBL_REG_CALC_SBC1_TF_STEP_15_TO_8                (0x0524)
+#define SBL_REG_CALC_SBC1_TF_ASYM                        (0x0528)
+#define SBL_REG_CALC_SBC1_TF_DEPTH_LOG_7_TO_0            (0x0530)
+#define SBL_REG_CALC_SBC1_TF_DEPTH_LOG_15_TO_8           (0x0534)
+#define SBL_REG_CALC_SBC1_TF_STEP_LOG_7_TO_0             (0x0538)
+#define SBL_REG_CALC_SBC1_TF_STEP_LOG_15_TO_8            (0x053c)
+#define SBL_REG_CALC_SBC1_TF_ASYM_LOG                    (0x0540)
+#define SBL_REG_CALC_SBC2_TF_DEPTH_7_TO_0                (0x0548)
+#define SBL_REG_CALC_SBC2_TF_DEPTH_15_TO_8               (0x054c)
+#define SBL_REG_CALC_SBC2_TF_STEP_7_TO_0                 (0x0550)
+#define SBL_REG_CALC_SBC2_TF_STEP_15_TO_8                (0x0554)
+#define SBL_REG_CALC_SBC2_TF_ASYM                        (0x0558)
+#define SBL_REG_CALC_SBC2_TF_DEPTH_LOG_7_TO_0            (0x0560)
+#define SBL_REG_CALC_SBC2_TF_DEPTH_LOG_15_TO_8           (0x0564)
+#define SBL_REG_CALC_SBC2_TF_STEP_LOG_7_TO_0             (0x0568)
+#define SBL_REG_CALC_SBC2_TF_STEP_LOG_15_TO_8            (0x056c)
+#define SBL_REG_CALC_SBC2_TF_ASYM_LOG                    (0x0570)
+#define SBL_REG_CALC_CALIBRATION_A_7_TO_0                (0x05b8)
+#define SBL_REG_CALC_CALIBRATION_A_15_TO_8               (0x05bc)
+#define SBL_REG_CALC_CALIBRATION_B_7_TO_0                (0x05c0)
+#define SBL_REG_CALC_CALIBRATION_B_15_TO_8               (0x05c4)
+#define SBL_REG_CALC_CALIBRATION_C_7_TO_0                (0x05c8)
+#define SBL_REG_CALC_CALIBRATION_C_15_TO_8               (0x05cc)
+#define SBL_REG_CALC_CALIBRATION_D_7_TO_0                (0x05d0)
+#define SBL_REG_CALC_CALIBRATION_D_15_TO_8               (0x05d4)
+#define SBL_REG_CALC_CALIBRATION_E_7_TO_0                (0x05d8)
+#define SBL_REG_CALC_CALIBRATION_E_15_TO_8               (0x05dc)
+#define SBL_REG_CALC_BACKLIGHT_SCALE_7_TO_0              (0x05e0)
+#define SBL_REG_CALC_BACKLIGHT_SCALE_15_TO_8             (0x05e4)
+#define SBL_REG_CALC_GAIN_AA_TF_DEPTH_7_TO_0             (0x05e8)
+#define SBL_REG_CALC_GAIN_AA_TF_DEPTH_15_TO_8            (0x05ec)
+#define SBL_REG_CALC_GAIN_AA_TF_STEP_7_TO_0              (0x05f0)
+#define SBL_REG_CALC_GAIN_AA_TF_STEP_11_TO_8             (0x05f4)
+#define SBL_REG_CALC_GAIN_AA_TF_ASYM                     (0x05f8)
+#define SBL_REG_CALC_STRENGTH_LIMIT_7_TO_0               (0x0600)
+#define SBL_REG_CALC_STRENGTH_LIMIT_9_TO_8               (0x0604)
+#define SBL_REG_CALC_ICUT_HIST_MIN                       (0x0608)
+#define SBL_REG_CALC_ICUT_BL_MIN_7_TO_0                  (0x0610)
+#define SBL_REG_CALC_ICUT_BL_MIN_15_TO_8                 (0x0614)
+#define SBL_REG_CALC_GAIN_CA_TF_DEPTH_7_TO_0             (0x0618)
+#define SBL_REG_CALC_GAIN_CA_TF_DEPTH_15_TO_8            (0x061c)
+#define SBL_REG_CALC_GAIN_CA_TF_STEP_7_TO_0              (0x0620)
+#define SBL_REG_CALC_GAIN_CA_TF_STEP_11_TO_8             (0x0624)
+#define SBL_REG_CALC_GAIN_CA_TF_ASYM                     (0x0628)
+#define SBL_REG_CALC_GAIN_MAX_7_TO_0                     (0x0630)
+#define SBL_REG_CALC_GAIN_MAX_11_TO_8                    (0x0634)
+#define SBL_REG_CALC_GAIN_MIDDLE_7_TO_0                  (0x0638)
+#define SBL_REG_CALC_GAIN_MIDDLE_11_TO_8                 (0x063c)
+#define SBL_REG_CALC_BRIGHTPR                            (0x0640)
+#define SBL_REG_CALC_BPR_CORRECT                         (0x0648)
+#define SBL_CALC_BACKLIGHT_OUT_7_TO_0                    (0x0650)
+#define SBL_CALC_BACKLIGHT_OUT_15_TO_8                   (0x0654)
+#define SBL_CALC_STRENGTH_INROI_OUT_7_TO_0               (0x0658)
+#define SBL_CALC_STRENGTH_INROI_OUT_9_TO_8               (0x065c)
+#define SBL_CALC_STRENGTH_OUTROI_OUT_7_TO_0              (0x0660)
+#define SBL_CALC_STRENGTH_OUTROI_OUT_9_TO_8              (0x0664)
+#define SBL_CALC_DARKENH_OUT_7_TO_0                      (0x0668)
+#define SBL_CALC_DARKENH_OUT_15_TO_8                     (0x066c)
+#define SBL_CALC_BRIGHTPR_OUT                            (0x0670)
+#define SBL_CALC_STAT_OUT_7_TO_0                         (0x0678)
+#define SBL_CALC_STAT_OUT_15_TO_8                        (0x067c)
+#define SBL_REG_CALC_AL_DELTA_SETTLE_7_TO_0              (0x0680)
+#define SBL_REG_CALC_AL_DELTA_SETTLE_15_TO_8             (0x0684)
+#define SBL_REG_CALC_BL_DELTA_SETTLE_7_TO_0              (0x0688)
+#define SBL_REG_CALC_BL_DELTA_SETTLE_15_TO_8             (0x068c)
+#define SBL_CALC_AL_CALIB_LUT_ADDR_I                     (0x06c0)
+#define SBL_CALC_AL_CALIB_LUT_DATA_W_7_TO_0              (0x06d0)
+#define SBL_CALC_AL_CALIB_LUT_DATA_W_15_TO_8             (0x06d4)
+#define SBL_CALC_BL_IN_LUT_ADDR_I                        (0x0700)
+#define SBL_CALC_BL_IN_LUT_DATA_W_7_TO_0                 (0x0710)
+#define SBL_CALC_BL_IN_LUT_DATA_W_15_TO_8                (0x0714)
+#define SBL_CALC_BL_OUT_LUT_ADDR_I                       (0x0740)
+#define SBL_CALC_BL_OUT_LUT_DATA_W_7_TO_0                (0x0750)
+#define SBL_CALC_BL_OUT_LUT_DATA_W_15_TO_8               (0x0754)
+#define SBL_CALC_BL_ATTEN_LUT_ADDR_I                     (0x0780)
+#define SBL_CALC_BL_ATTEN_LUT_DATA_W_7_TO_0              (0x0790)
+#define SBL_CALC_BL_ATTEN_LUT_DATA_W_15_TO_8             (0x0794)
+#define SBL_CALC_BL_AUTO_LUT_ADDR_I                      (0x07c0)
+#define SBL_CALC_BL_AUTO_LUT_DATA_W_7_TO_0               (0x07d0)
+#define SBL_CALC_BL_AUTO_LUT_DATA_W_15_TO_8              (0x07d4)
+#define SBL_CALC_AL_CHANGE_LUT_ADDR_I                    (0x0800)
+#define SBL_CALC_AL_CHANGE_LUT_DATA_W_7_TO_0             (0x0810)
+#define SBL_CALC_AL_CHANGE_LUT_DATA_W_15_TO_8            (0x0814)
+#define SBL_REG_CABC_INTENSITY_7_TO_0                    (0x0900)
+#define SBL_REG_CABC_INTENSITY_11_TO_8                   (0x0904)
+#define SBL_REG_CABC_ICUT_SELECT                         (0x0908)
+#define SBL_REG_CABC_ICUT_MANUAL                         (0x090c)
+#define SBL_CABC_ICUT_OUT                                (0x0910)
+#define SBL_REG_CORE1_VC_CONTROL_0                       (0x0c00)
+#define SBL_REG_CORE1_IRDX_CONTROL_0                     (0x0c40)
+#define SBL_REG_CORE1_IRDX_CONTROL_1                     (0x0c44)
+#define SBL_REG_CORE1_IRDX_VARIANCE                      (0x0c4c)
+#define SBL_REG_CORE1_IRDX_SLOPE_MAX                     (0x0c50)
+#define SBL_REG_CORE1_IRDX_SLOPE_MIN                     (0x0c54)
+#define SBL_REG_CORE1_IRDX_BLACK_LEVEL_7_TO_0            (0x0c58)
+#define SBL_REG_CORE1_IRDX_BLACK_LEVEL_9_TO_8            (0x0c5c)
+#define SBL_REG_CORE1_IRDX_WHITE_LEVEL_7_TO_0            (0x0c60)
+#define SBL_REG_CORE1_IRDX_WHITE_LEVEL_9_TO_8            (0x0c64)
+#define SBL_REG_CORE1_IRDX_LIMIT_AMPL                    (0x0c68)
+#define SBL_REG_CORE1_IRDX_DITHER                        (0x0c6c)
+#define SBL_REG_CORE1_IRDX_STRENGTH_INROI_7_TO_0         (0x0c70)
+#define SBL_REG_CORE1_IRDX_STRENGTH_INROI_9_TO_8         (0x0c74)
+#define SBL_REG_CORE1_IRDX_STRENGTH_OUTROI_7_TO_0        (0x0c78)
+#define SBL_REG_CORE1_IRDX_STRENGTH_OUTROI_9_TO_8        (0x0c7c)
+#define SBL_CORE1_IRDX_ASYMMETRY_LUT_ADDR_I              (0x0c80)
+#define SBL_CORE1_IRDX_ASYMMETRY_LUT_DATA_W_7_TO_0       (0x0c84)
+#define SBL_CORE1_IRDX_ASYMMETRY_LUT_DATA_W_11_TO_8      (0x0c88)
+#define SBL_CORE1_IRDX_COLOR_LUT_ADDR_I                  (0x0cc0)
+#define SBL_CORE1_IRDX_COLOR_LUT_DATA_W_7_TO_0           (0x0cc4)
+#define SBL_CORE1_IRDX_COLOR_LUT_DATA_W_11_TO_8          (0x0cc8)
+#define SBL_REG_CORE1_IRDX_FILTER_CTRL                   (0x0d00)
+#define SBL_REG_CORE1_IRDX_SVARIANCE                     (0x0d04)
+#define SBL_REG_CORE1_IRDX_BRIGHTPR                      (0x0d08)
+#define SBL_REG_CORE1_IRDX_CONTRAST                      (0x0d0c)
+#define SBL_REG_CORE1_IRDX_DARKENH_7_TO_0                (0x0d10)
+#define SBL_REG_CORE1_IRDX_DARKENH_15_TO_8               (0x0d14)
+#define SBL_REG_CORE1_DTHR_CONTROL                       (0x0dc0)
+#define SBL_REG_CORE1_LOGO_TOP                           (0x0dd0)
+#define SBL_REG_CORE1_LOGO_LEFT                          (0x0dd4)
+#define SBL_REG_CORE1_CA_D_ARTITHRESH_7_TO_0             (0x0e00)
+#define SBL_REG_CORE1_CA_D_ARTITHRESH_9_TO_8             (0x0e04)
+#define SBL_CORE1_CA_STR_ATTEN_7_TO_0                    (0x0e10)
+#define SBL_CORE1_CA_STR_ATTEN_15_TO_8                   (0x0e14)
+#define SBL_CORE1_CA_STR_ATTEN_16                        (0x0e18)
+#define SBL_REG_CORE1_FRD_D_THRESH_7_TO_0                (0x0e20)
+#define SBL_REG_CORE1_FRD_D_THRESH_9_TO_8                (0x0e24)
+#define SBL_REG_CORE1_REG0_7_TO_0                        (0x0e28)
+#define SBL_REG_CORE1_REG0_15_TO_8                       (0x0e2c)
+#define SBL_REG_CORE1_REG1_7_TO_0                        (0x0e30)
+#define SBL_REG_CORE1_REG1_15_TO_8                       (0x0e34)
+#define SBL_REG_CORE1_REG2_7_TO_0                        (0x0e38)
+#define SBL_REG_CORE1_REG2_15_TO_8                       (0x0e3c)
+#define SBL_REG_CORE1_REG3_7_TO_0                        (0x0e40)
+#define SBL_REG_CORE1_REG3_15_TO_8                       (0x0e44)
+#define SBL_REG_CORE1_REG4_7_TO_0                        (0x0e48)
+#define SBL_REG_CORE1_REG4_15_TO_8                       (0x0e4c)
+#define SBL_REG_CORE1_REG5_7_TO_0                        (0x0e50)
+#define SBL_REG_CORE1_REG5_15_TO_8                       (0x0e54)
+#define SBL_CORE1_REG_OUT0_7_TO_0                        (0x0e58)
+#define SBL_CORE1_REG_OUT0_15_TO_8                       (0x0e5c)
+#define SBL_CORE1_REG_OUT1_7_TO_0                        (0x0e60)
+#define SBL_CORE1_REG_OUT1_15_TO_8                       (0x0e64)
+
+typedef struct dss_sbl {
+	int sbl_backlight_l;
+	int sbl_backlight_h;
+	int sbl_ambient_light_l;
+	int sbl_ambient_light_h;
+	int sbl_calibration_a_l;
+	int sbl_calibration_a_h;
+	int sbl_calibration_b_l;
+	int sbl_calibration_b_h;
+	int sbl_calibration_c_l;
+	int sbl_calibration_c_h;
+	int sbl_calibration_d_l;
+	int sbl_calibration_d_h;
+	int sbl_enable;
+} dss_sbl_t;
+
+/*******************************************************************************
+ ** DPP
+ */
+
+#define DPP_RD_SHADOW_SEL	(0x000)
+#define DPP_DEFAULT	(0x004)
+#define DPP_ID	(0x008)
+#define DPP_IMG_SIZE_BEF_SR	(0x00C)
+#define DPP_IMG_SIZE_AFT_SR	(0x010)
+#define DPP_SBL	(0x014)
+#define DPP_SBL_MEM_CTRL	(0x018)
+#define DPP_ARSR1P_MEM_CTRL	(0x01C)
+#define DPP_CLK_SEL	(0x020)
+#define DPP_CLK_EN	(0x024)
+#define DPP_DBG1_CNT	(0x028)
+#define DPP_DBG2_CNT	(0x02C)
+#define DPP_DBG1	(0x030)
+#define DPP_DBG2	(0x034)
+#define DPP_DBG3	(0x038)
+#define DPP_DBG4	(0x03C)
+#define DPP_INTS	(0x040)
+#define DPP_INT_MSK	(0x044)
+#define DPP_ARSR1P	(0x048)
+#define DPP_DBG_CNT  DPP_DBG1_CNT
+
+
+#define DPP_CLRBAR_CTRL (0x100)
+#define DPP_CLRBAR_1ST_CLR (0x104)
+#define DPP_CLRBAR_2ND_CLR (0x108)
+#define DPP_CLRBAR_3RD_CLR (0x10C)
+
+
+#define DPP_CLIP_TOP (0x180)
+#define DPP_CLIP_BOTTOM (0x184)
+#define DPP_CLIP_LEFT (0x188)
+#define DPP_CLIP_RIGHT (0x18C)
+#define DPP_CLIP_EN (0x190)
+#define DPP_CLIP_DBG (0x194)
+
+
+#define DITHER_PARA (0x000)
+#define DITHER_CTL (0x004)
+#define DITHER_MATRIX_PART1 (0x008)
+#define DITHER_MATRIX_PART0 (0x00C)
+#define DITHER_ERRDIFF_WEIGHT (0x010)
+#define DITHER_FRC_01_PART1 (0x014)
+#define DITHER_FRC_01_PART0 (0x018)
+#define DITHER_FRC_10_PART1 (0x01C)
+#define DITHER_FRC_10_PART0 (0x020)
+#define DITHER_FRC_11_PART1 (0x024)
+#define DITHER_FRC_11_PART0 (0x028)
+#define DITHER_MEM_CTRL (0x02C)
+#define DITHER_DBG0 (0x030)
+#define DITHER_DBG1 (0x034)
+#define DITHER_DBG2 (0x038)
+
+
+#define CSC10B_IDC0	(0x000)
+#define CSC10B_IDC1	(0x004)
+#define CSC10B_IDC2	(0x008)
+#define CSC10B_ODC0	(0x00C)
+#define CSC10B_ODC1	(0x010)
+#define CSC10B_ODC2	(0x014)
+#define CSC10B_P00	(0x018)
+#define CSC10B_P01	(0x01C)
+#define CSC10B_P02	(0x020)
+#define CSC10B_P10	(0x024)
+#define CSC10B_P11	(0x028)
+#define CSC10B_P12	(0x02C)
+#define CSC10B_P20	(0x030)
+#define CSC10B_P21	(0x034)
+#define CSC10B_P22	(0x038)
+#define CSC10B_MODULE_EN	(0x03C)
+#define CSC10B_MPREC	(0x040)
+
+
+#define GAMA_EN	(0x000)
+#define GAMA_MEM_CTRL	(0x004)
+
+
+#define ACM_EN	(0x000)
+#define ACM_SATA_OFFSET	(0x004)
+#define ACM_HUESEL	(0x008)
+#define ACM_CSC_IDC0	(0x00C)
+#define ACM_CSC_IDC1	(0x010)
+#define ACM_CSC_IDC2	(0x014)
+#define ACM_CSC_P00	(0x018)
+#define ACM_CSC_P01	(0x01C)
+#define ACM_CSC_P02	(0x020)
+#define ACM_CSC_P10	(0x024)
+#define ACM_CSC_P11	(0x028)
+#define ACM_CSC_P12	(0x02C)
+#define ACM_CSC_P20	(0x030)
+#define ACM_CSC_P21	(0x034)
+#define ACM_CSC_P22	(0x038)
+#define ACM_CSC_MRREC	(0x03C)
+#define ACM_R0_H	(0x040)
+#define ACM_R1_H	(0x044)
+#define ACM_R2_H	(0x048)
+#define ACM_R3_H	(0x04C)
+#define ACM_R4_H	(0x050)
+#define ACM_R5_H	(0x054)
+#define ACM_R6_H	(0x058)
+#define ACM_LUT_DIS0	(0x05C)
+#define ACM_LUT_DIS1	(0x060)
+#define ACM_LUT_DIS2	(0x064)
+#define ACM_LUT_DIS3	(0x068)
+#define ACM_LUT_DIS4	(0x06C)
+#define ACM_LUT_DIS5	(0x070)
+#define ACM_LUT_DIS6	(0x074)
+#define ACM_LUT_DIS7	(0x078)
+#define ACM_LUT_PARAM0	(0x07C)
+#define ACM_LUT_PARAM1	(0x080)
+#define ACM_LUT_PARAM2	(0x084)
+#define ACM_LUT_PARAM3	(0x088)
+#define ACM_LUT_PARAM4	(0x08C)
+#define ACM_LUT_PARAM5	(0x090)
+#define ACM_LUT_PARAM6	(0x094)
+#define ACM_LUT_PARAM7	(0x098)
+#define ACM_LUT_SEL	(0x09C)
+#define ACM_MEM_CTRL	(0x0A0)
+#define ACM_DEBUG_TOP	(0x0A4)
+#define ACM_DEBUG_CFG	(0x0A8)
+#define ACM_DEBUG_W	(0x0AC)
+
+
+#define ACE_EN	(0x000)
+#define ACE_SKIN_CFG	(0x004)
+#define ACE_LUT_SEL	(0x008)
+#define ACE_HIST_IND	(0x00C)
+#define ACE_ACTIVE	(0x010)
+#define ACE_DBG	(0x014)
+#define ACE_MEM_CTRL	(0x018)
+#define ACE_IN_SEL	(0x01C)
+#define ACE_R2Y	(0x020)
+#define ACE_G2Y	(0x024)
+#define ACE_B2Y	(0x028)
+#define ACE_Y_OFFSET	(0x02C)
+#define ACE_Y_CEN	(0x030)
+#define ACE_U_CEN	(0x034)
+#define ACE_V_CEN	(0x038)
+#define ACE_Y_EXT	(0x03C)
+#define ACE_U_EXT	(0x040)
+#define ACE_V_EXT	(0x044)
+#define ACE_Y_ATTENU 	(0x048)
+#define ACE_U_ATTENU	(0x04C)
+#define ACE_V_ATTENU	(0x050)
+#define ACE_ROTA	(0x054)
+#define ACE_ROTB 	(0x058)
+#define ACE_Y_CORE	(0x05C)
+#define ACE_U_CORE	(0x060)
+#define ACE_V_CORE	(0x064)
+
+
+#define LCP_XCC_COEF_00	(0x000)
+#define LCP_XCC_COEF_01	(0x004)
+#define LCP_XCC_COEF_02	(0x008)
+#define LCP_XCC_COEF_03	(0x00C)
+#define LCP_XCC_COEF_10	(0x010)
+#define LCP_XCC_COEF_11	(0x014)
+#define LCP_XCC_COEF_12	(0x018)
+#define LCP_XCC_COEF_13	(0x01C)
+#define LCP_XCC_COEF_20	(0x020)
+#define LCP_XCC_COEF_21	(0x024)
+#define LCP_XCC_COEF_22	(0x028)
+#define LCP_XCC_COEF_23	(0x02C)
+#define LCP_GMP_BYPASS_EN	(0x030)
+#define LCP_XCC_BYPASS_EN	(0x034)
+#define LCP_DEGAMA_EN	(0x038)
+#define LCP_DEGAMA_MEM_CTRL	(0x03C)
+#define LCP_GMP_MEM_CTRL	(0x040)
+
+
+typedef struct dss_arsr1p {
+	uint32_t ihleft;
+	uint32_t ihright;
+	uint32_t ihleft1;
+	uint32_t ihright1;
+	uint32_t ivtop;
+	uint32_t ivbottom;
+	uint32_t uv_offset;
+	uint32_t ihinc;
+	uint32_t ivinc;
+	uint32_t mode;
+	uint32_t format;
+
+	uint32_t skin_thres_y;
+	uint32_t skin_thres_u;
+	uint32_t skin_thres_v;
+	uint32_t skin_expected;
+	uint32_t skin_cfg;
+	uint32_t shoot_cfg1;
+	uint32_t shoot_cfg2;
+	uint32_t sharp_cfg1;
+	uint32_t sharp_cfg2;
+	uint32_t sharp_cfg3;
+	uint32_t sharp_cfg4;
+	uint32_t sharp_cfg5;
+	uint32_t sharp_cfg6;
+	uint32_t sharp_cfg7;
+	uint32_t sharp_cfg8;
+	uint32_t sharp_cfg9;
+	uint32_t sharp_cfg10;
+	uint32_t sharp_cfg11;
+	uint32_t diff_ctrl;
+	uint32_t lsc_cfg1;
+	uint32_t lsc_cfg2;
+	uint32_t lsc_cfg3;
+	uint32_t force_clk_on_cfg;
+
+	uint32_t dpp_img_hrz_bef_sr;
+	uint32_t dpp_img_vrt_bef_sr;
+	uint32_t dpp_img_hrz_aft_sr;
+	uint32_t dpp_img_vrt_aft_sr;
+} dss_arsr1p_t;
+
+#define ARSR1P_INC_FACTOR (65536)
+
+#define ARSR1P_IHLEFT		(0x000)
+#define ARSR1P_IHRIGHT		(0x004)
+#define ARSR1P_IHLEFT1		(0x008)
+#define ARSR1P_IHRIGHT1		(0x00C)
+#define ARSR1P_IVTOP		(0x010)
+#define ARSR1P_IVBOTTOM		(0x014)
+#define ARSR1P_UV_OFFSET		(0x018)
+#define ARSR1P_IHINC		(0x01C)
+#define ARSR1P_IVINC		(0x020)
+#define ARSR1P_MODE			(0x024)
+#define ARSR1P_FORMAT		(0x028)
+#define ARSR1P_SKIN_THRES_Y		(0x02C)
+#define ARSR1P_SKIN_THRES_U		(0x030)
+#define ARSR1P_SKIN_THRES_V		(0x034)
+#define ARSR1P_SKIN_EXPECTED	(0x038)
+#define ARSR1P_SKIN_CFG			(0x03C)
+#define ARSR1P_SHOOT_CFG1		(0x040)
+#define ARSR1P_SHOOT_CFG2		(0x044)
+#define ARSR1P_SHARP_CFG1		(0x048)
+#define ARSR1P_SHARP_CFG2		(0x04C)
+#define ARSR1P_SHARP_CFG3		(0x050)
+#define ARSR1P_SHARP_CFG4		(0x054)
+#define ARSR1P_SHARP_CFG5		(0x058)
+#define ARSR1P_SHARP_CFG6		(0x05C)
+#define ARSR1P_SHARP_CFG7		(0x060)
+#define ARSR1P_SHARP_CFG8		(0x064)
+#define ARSR1P_SHARP_CFG9		(0x068)
+#define ARSR1P_SHARP_CFG10		(0x06C)
+#define ARSR1P_SHARP_CFG11		(0x070)
+#define ARSR1P_DIFF_CTRL		(0x074)
+#define ARSR1P_LSC_CFG1		(0x078)
+#define ARSR1P_LSC_CFG2		(0x07C)
+#define ARSR1P_LSC_CFG3		(0x080)
+#define ARSR1P_FORCE_CLK_ON_CFG		(0x084)
+
+/*******************************************************************************
+ ** BIT EXT
+ */
+#define BIT_EXT0_CTL (0x000)
+
+
+#define U_GAMA_R_COEF	(0x000)
+#define U_GAMA_G_COEF	(0x400)
+#define U_GAMA_B_COEF	(0x800)
+#define U_GAMA_R_LAST_COEF (0x200)
+#define U_GAMA_G_LAST_COEF (0x600)
+#define U_GAMA_B_LAST_COEF (0xA00)
+
+
+#define ACM_U_H_COEF	(0x000)
+#define ACM_U_SATA_COEF	(0x200)
+#define ACM_U_SATR0_COEF	(0x300)
+#define ACM_U_SATR1_COEF	(0x340)
+#define ACM_U_SATR2_COEF	(0x380)
+#define ACM_U_SATR3_COEF	(0x3C0)
+#define ACM_U_SATR4_COEF	(0x400)
+#define ACM_U_SATR5_COEF	(0x440)
+#define ACM_U_SATR6_COEF	(0x480)
+#define ACM_U_SATR7_COEF	(0x4C0)
+
+
+#define LCP_U_GMP_COEF	(0x0000)
+#define LCP_U_DEGAMA_R_COEF	(0x5000)
+#define LCP_U_DEGAMA_G_COEF	(0x5400)
+#define LCP_U_DEGAMA_B_COEF	(0x5800)
+#define LCP_U_DEGAMA_R_LAST_COEF (0x5200)
+#define LCP_U_DEGAMA_G_LAST_COEF (0x5600)
+#define LCP_U_DEGAMA_B_LAST_COEF (0x5A00)
+
+
+#define ACE_HIST0	(0x000)
+#define ACE_HIST1	(0x400)
+#define ACE_LUT0	(0x800)
+#define ACE_LUT1	(0xA00)
+
+
+#define ARSR1P_LSC_GAIN		(0x084)
+#define ARSR1P_COEFF_H_Y0	(0x0F0)
+#define ARSR1P_COEFF_H_Y1	(0x114)
+#define ARSR1P_COEFF_V_Y0	(0x138)
+#define ARSR1P_COEFF_V_Y1	(0x15C)
+#define ARSR1P_COEFF_H_UV0	(0x180)
+#define ARSR1P_COEFF_H_UV1	(0x1A4)
+#define ARSR1P_COEFF_V_UV0	(0x1C8)
+#define ARSR1P_COEFF_V_UV1	(0x1EC)
+
+
+#define HIACE_INT_STAT (0x0000)
+#define HIACE_INT_UNMASK (0x0004)
+#define HIACE_BYPASS_ACE (0x0008)
+#define HIACE_BYPASS_ACE_STAT (0x000c)
+#define HIACE_UPDATE_LOCAL (0x0010)
+#define HIACE_LOCAL_VALID (0x0014)
+#define HIACE_GAMMA_AB_SHADOW (0x0018)
+#define HIACE_GAMMA_AB_WORK (0x001c)
+#define HIACE_GLOBAL_HIST_AB_SHADOW (0x0020)
+#define HIACE_GLOBAL_HIST_AB_WORK (0x0024)
+#define HIACE_IMAGE_INFO (0x0030)
+#define HIACE_HALF_BLOCK_H_W (0x0034)
+#define HIACE_XYWEIGHT (0x0038)
+#define HIACE_LHIST_SFT (0x003c)
+#define HIACE_HUE (0x0050)
+#define HIACE_SATURATION (0x0054)
+#define HIACE_VALUE (0x0058)
+#define HIACE_SKIN_GAIN (0x005c)
+#define HIACE_UP_LOW_TH (0x0060)
+#define HIACE_UP_CNT (0x0070)
+#define HIACE_LOW_CNT (0x0074)
+#define HIACE_GLOBAL_HIST_LUT_ADDR (0x0080)
+#define HIACE_LHIST_EN (0x0100)
+#define HIACE_LOCAL_HIST_VxHy_2z_2z1 (0x0104)
+#define HIACE_GAMMA_EN (0x0108)
+#define HIACE_GAMMA_VxHy_3z2_3z1_3z_W (0x010c)
+#define HIACE_GAMMA_EN_HV_R (0x0110)
+#define HIACE_GAMMA_VxHy_3z2_3z1_3z_R (0x0114)
+#define HIACE_INIT_GAMMA (0x0120)
+#define HIACE_MANUAL_RELOAD (0x0124)
+#define HIACE_RAMCLK_FUNC (0x0128)
+#define HIACE_CLK_GATE (0x012c)
+#define HIACE_GAMMA_RAM_A_CFG_MEM_CTRL (0x0130)
+#define HIACE_GAMMA_RAM_B_CFG_MEM_CTRL (0x0134)
+#define HIACE_LHIST_RAM_CFG_MEM_CTRL (0x0138)
+#define HIACE_GAMMA_RAM_A_CFG_PM_CTRL (0x0140)
+#define HIACE_GAMMA_RAM_B_CFG_PM_CTRL (0x0144)
+#define HIACE_LHIST_RAM_CFG_PM_CTRL (0x0148)
+
+/*******************************************************************************
+ ** IFBC
+ */
+#define IFBC_SIZE	(0x0000)
+#define IFBC_CTRL	(0x0004)
+#define IFBC_HIMAX_CTRL0	(0x0008)
+#define IFBC_HIMAX_CTRL1	(0x000C)
+#define IFBC_HIMAX_CTRL2	(0x0010)
+#define IFBC_HIMAX_CTRL3	(0x0014)
+#define IFBC_EN	(0x0018)
+#define IFBC_MEM_CTRL	(0x001C)
+#define IFBC_INSERT	(0x0020)
+#define IFBC_HIMAX_TEST_MODE	(0x0024)
+#define IFBC_CORE_GT	(0x0028)
+#define IFBC_PM_CTRL	(0x002C)
+#define IFBC_RD_SHADOW	(0x0030)
+#define IFBC_ORISE_CTL	(0x0034)
+#define IFBC_ORSISE_DEBUG0	(0x0038)
+#define IFBC_ORSISE_DEBUG1	(0x003C)
+#define IFBC_RSP_COMP_TEST	(0x0040)
+#define IFBC_CLK_SEL	(0x044)
+#define IFBC_CLK_EN	(0x048)
+#define IFBC_PAD	(0x004C)
+#define IFBC_REG_DEFAULT	(0x0050)
+
+/*******************************************************************************
+ ** DSC
+ */
+#define DSC_VERSION	(0x0000)
+#define DSC_PPS_IDENTIFIER	(0x0004)
+#define DSC_EN	(0x0008)
+#define DSC_CTRL	(0x000C)
+#define DSC_PIC_SIZE	(0x0010)
+#define DSC_SLICE_SIZE	(0x0014)
+#define DSC_CHUNK_SIZE	(0x0018)
+#define DSC_INITIAL_DELAY	(0x001C)
+#define DSC_RC_PARAM0	(0x0020)
+#define DSC_RC_PARAM1	(0x0024)
+#define DSC_RC_PARAM2	(0x0028)
+#define DSC_RC_PARAM3	(0x002C)
+#define DSC_FLATNESS_QP_TH	(0x0030)
+#define DSC_RC_PARAM4	(0x0034)
+#define DSC_RC_PARAM5	(0x0038)
+#define DSC_RC_BUF_THRESH0	(0x003C)
+#define DSC_RC_BUF_THRESH1	(0x0040)
+#define DSC_RC_BUF_THRESH2	(0x0044)
+#define DSC_RC_BUF_THRESH3	(0x0048)
+#define DSC_RC_RANGE_PARAM0	(0x004C)
+#define DSC_RC_RANGE_PARAM1	(0x0050)
+#define DSC_RC_RANGE_PARAM2	(0x0054)
+#define DSC_RC_RANGE_PARAM3	(0x0058)
+#define DSC_RC_RANGE_PARAM4	(0x005C)
+#define DSC_RC_RANGE_PARAM5	(0x0060)
+#define DSC_RC_RANGE_PARAM6	(0x0064)
+#define DSC_RC_RANGE_PARAM7	(0x0068)
+#define DSC_ADJUSTMENT_BITS	(0x006C)
+#define DSC_BITS_PER_GRP	(0x0070)
+#define DSC_MULTI_SLICE_CTL	(0x0074)
+#define DSC_OUT_CTRL	(0x0078)
+#define DSC_CLK_SEL	(0x007C)
+#define DSC_CLK_EN	(0x0080)
+#define DSC_MEM_CTRL	(0x0084)
+#define DSC_ST_DATAIN	(0x0088)
+#define DSC_ST_DATAOUT	(0x008C)
+#define DSC0_ST_SLC_POS	(0x0090)
+#define DSC1_ST_SLC_POS	(0x0094)
+#define DSC0_ST_PIC_POS	(0x0098)
+#define DSC1_ST_PIC_POS	(0x009C)
+#define DSC0_ST_FIFO	(0x00A0)
+#define DSC1_ST_FIFO	(0x00A4)
+#define DSC0_ST_LINEBUF	(0x00A8)
+#define DSC1_ST_LINEBUF	(0x00AC)
+#define DSC_ST_ITFC	(0x00B0)
+#define DSC_RD_SHADOW_SEL	(0x00B4)
+#define DSC_REG_DEFAULT	(0x00B8)
+
+/*******************************************************************************
+ ** LDI
+ */
+#define LDI_DPI0_HRZ_CTRL0	(0x0000)
+#define LDI_DPI0_HRZ_CTRL1	(0x0004)
+#define LDI_DPI0_HRZ_CTRL2	(0x0008)
+#define LDI_VRT_CTRL0	(0x000C)
+#define LDI_VRT_CTRL1	(0x0010)
+#define LDI_VRT_CTRL2	(0x0014)
+#define LDI_PLR_CTRL	(0x0018)
+#define LDI_SH_MASK_INT	(0x001C)
+#define LDI_3D_CTRL	(0x0020)
+#define LDI_CTRL	(0x0024)
+#define LDI_WORK_MODE	(0x0028)
+#define LDI_DE_SPACE_LOW	(0x002C)
+#define LDI_DSI_CMD_MOD_CTRL	(0x0030)
+#define LDI_DSI_TE_CTRL	(0x0034)
+#define LDI_DSI_TE_HS_NUM	(0x0038)
+#define LDI_DSI_TE_HS_WD	(0x003C)
+#define LDI_DSI_TE_VS_WD	(0x0040)
+#define LDI_FRM_MSK	(0x0044)
+#define LDI_FRM_MSK_UP	(0x0048)
+#define LDI_VINACT_MSK_LEN	(0x0050)
+#define LDI_VSTATE	(0x0054)
+#define LDI_DPI0_HSTATE	(0x0058)
+#define LDI_DPI1_HSTATE	(0x005C)
+#define LDI_CMD_EVENT_SEL	(0x0060)
+#define LDI_SRAM_LP_CTRL	(0x0064)
+#define LDI_ITF_RD_SHADOW	(0x006C)
+#define LDI_DPI1_HRZ_CTRL0	(0x00F0)
+#define LDI_DPI1_HRZ_CTRL1	(0x00F4)
+#define LDI_DPI1_HRZ_CTRL2	(0x00F8)
+#define LDI_OVERLAP_SIZE	(0x00FC)
+#define LDI_MEM_CTRL	(0x0100)
+#define LDI_PM_CTRL	(0x0104)
+#define LDI_CLK_SEL	(0x0108)
+#define LDI_CLK_EN	(0x010C)
+#define LDI_IF_BYPASS	(0x0110)
+#define LDI_FRM_VALID_DBG (0x0118)
+/* LDI GLB*/
+#define LDI_PXL0_DIV2_GT_EN (0x0210)
+#define LDI_PXL0_DIV4_GT_EN (0x0214)
+#define LDI_PXL0_GT_EN (0x0218)
+#define LDI_PXL0_DSI_GT_EN (0x021C)
+#define LDI_PXL0_DIVXCFG (0x0220)
+#define LDI_DSI1_CLK_SEL (0x0224)
+#define LDI_VESA_CLK_SEL (0x0228)
+/* DSI1 RST*/
+#define LDI_DSI1_RST_SEL (0x0238)
+/* LDI INTERRUPT*/
+#define LDI_MCU_ITF_INTS (0x0240)
+#define LDI_MCU_ITF_INT_MSK (0x0244)
+#define LDI_CPU_ITF_INTS (0x0248)
+#define LDI_CPU_ITF_INT_MSK (0x024C)
+/* LDI MODULE CLOCK GATING*/
+#define LDI_MODULE_CLK_SEL (0x0258)
+#define LDI_MODULE_CLK_EN (0x025C)
+
+/*******************************************************************************
+ ** MIPI DSI
+ */
+#define MIPIDSI_VERSION_OFFSET	(0x0000)
+#define MIPIDSI_PWR_UP_OFFSET	(0x0004)
+#define MIPIDSI_CLKMGR_CFG_OFFSET	(0x0008)
+#define MIPIDSI_DPI_VCID_OFFSET	(0x000c)
+#define MIPIDSI_DPI_COLOR_CODING_OFFSET	(0x0010)
+#define MIPIDSI_DPI_CFG_POL_OFFSET	(0x0014)
+#define MIPIDSI_DPI_LP_CMD_TIM_OFFSET	(0x0018)
+#define MIPIDSI_PCKHDL_CFG_OFFSET	(0x002c)
+#define MIPIDSI_GEN_VCID_OFFSET	(0x0030)
+#define MIPIDSI_MODE_CFG_OFFSET	(0x0034)
+#define MIPIDSI_VID_MODE_CFG_OFFSET	(0x0038)
+#define MIPIDSI_VID_PKT_SIZE_OFFSET	(0x003c)
+#define MIPIDSI_VID_NUM_CHUNKS_OFFSET	(0x0040)
+#define MIPIDSI_VID_NULL_SIZE_OFFSET	(0x0044)
+#define MIPIDSI_VID_HSA_TIME_OFFSET	(0x0048)
+#define MIPIDSI_VID_HBP_TIME_OFFSET	(0x004c)
+#define MIPIDSI_VID_HLINE_TIME_OFFSET	(0x0050)
+#define MIPIDSI_VID_VSA_LINES_OFFSET	(0x0054)
+#define MIPIDSI_VID_VBP_LINES_OFFSET	(0x0058)
+#define MIPIDSI_VID_VFP_LINES_OFFSET	(0x005c)
+#define MIPIDSI_VID_VACTIVE_LINES_OFFSET	(0x0060)
+#define MIPIDSI_EDPI_CMD_SIZE_OFFSET	(0x0064)
+#define MIPIDSI_CMD_MODE_CFG_OFFSET	(0x0068)
+#define MIPIDSI_GEN_HDR_OFFSET	(0x006c)
+#define MIPIDSI_GEN_PLD_DATA_OFFSET	(0x0070)
+#define MIPIDSI_CMD_PKT_STATUS_OFFSET	(0x0074)
+#define MIPIDSI_TO_CNT_CFG_OFFSET	(0x0078)
+#define MIPIDSI_HS_RD_TO_CNT_OFFSET	(0x007C)
+#define MIPIDSI_LP_RD_TO_CNT_OFFSET	(0x0080)
+#define MIPIDSI_HS_WR_TO_CNT_OFFSET	(0x0084)
+#define MIPIDSI_LP_WR_TO_CNT_OFFSET	(0x0088)
+#define MIPIDSI_BTA_TO_CNT_OFFSET	(0x008C)
+#define MIPIDSI_SDF_3D_OFFSET	(0x0090)
+#define MIPIDSI_LPCLK_CTRL_OFFSET	(0x0094)
+#define MIPIDSI_PHY_TMR_LPCLK_CFG_OFFSET	(0x0098)
+#define MIPIDSI_PHY_TMR_CFG_OFFSET	(0x009c)
+#define MIPIDSI_PHY_RSTZ_OFFSET	(0x00a0)
+#define MIPIDSI_PHY_IF_CFG_OFFSET	(0x00a4)
+#define MIPIDSI_PHY_ULPS_CTRL_OFFSET	(0x00a8)
+#define MIPIDSI_PHY_TX_TRIGGERS_OFFSET	(0x00ac)
+#define MIPIDSI_PHY_STATUS_OFFSET	(0x00b0)
+#define MIPIDSI_PHY_TST_CTRL0_OFFSET	(0x00b4)
+#define MIPIDSI_PHY_TST_CTRL1_OFFSET	(0x00b8)
+#define MIPIDSI_INT_ST0_OFFSET	(0x00bc)
+#define MIPIDSI_INT_ST1_OFFSET	(0x00c0)
+#define MIPIDSI_INT_MSK0_OFFSET	(0x00c4)
+#define MIPIDSI_INT_MSK1_OFFSET	(0x00c8)
+#define INT_FORCE0	(0x00D8)
+#define INT_FORCE1	(0x00DC)
+#define MIPIDSI_DSC_PARAMETER_OFFSET	(0x00f0)
+#define MIPIDSI_PHY_TMR_RD_CFG_OFFSET	(0x00f4)
+#define VID_SHADOW_CTRL	(0x0100)
+#define DPI_VCID_ACT	(0x010C)
+#define DPI_COLOR_CODING_ACT	(0x0110)
+#define DPI_LP_CMD_TIM_ACT	(0x0118)
+#define VID_MODE_CFG_ACT	(0x0138)
+#define VID_PKT_SIZE_ACT	(0x013C)
+#define VID_NUM_CHUNKS_ACT	(0x0140)
+#define VID_NULL_SIZE_ACT	(0x0144)
+#define VID_HSA_TIME_ACT	(0x0148)
+#define VID_HBP_TIME_ACT	(0x014C)
+#define VID_HLINE_TIME_ACT	(0x0150)
+#define VID_VSA_LINES_ACT	(0x0154)
+#define VID_VBP_LINES_ACT	(0x0158)
+#define VID_VFP_LINES_ACT	(0x015C)
+#define VID_VACTIVE_LINES_ACT	(0x0160)
+#define SDF_3D_ACT	(0x0190)
+
+/*******************************************************************************
+ ** MMBUF
+ */
+#define SMC_LOCK	(0x0000)
+#define SMC_MEM_LP	(0x0004)
+#define SMC_GCLK_CS	(0x000C)
+#define SMC_QOS_BACKDOOR	(0x0010)
+#define SMC_DFX_WCMD_CNT_1ST	(0x0014)
+#define SMC_DFX_WCMD_CNT_2ND	(0x0018)
+#define SMC_DFX_WCMD_CNT_3RD	(0x001C)
+#define SMC_DFX_WCMD_CNT_4TH	(0x0020)
+#define SMC_DFX_RCMD_CNT_1ST	(0x0024)
+#define SMC_DFX_RCMD_CNT_2ND	(0x0028)
+#define SMC_DFX_RCMD_CNT_3RD	(0x002C)
+#define SMC_DFX_RCMD_CNT_4TH	(0x0030)
+#define SMC_CS_IDLE	(0x0034)
+#define SMC_DFX_BFIFO_CNT0	(0x0038)
+#define SMC_DFX_RDFIFO_CNT1	(0x003C)
+#define SMC_SP_SRAM_STATE0	(0x0040)
+#define SMC_SP_SRAM_STATE1	(0x0044)
+
+/*******************************************************************************
+ ** dirty_region_updt
+ */
+typedef struct dirty_region_updt {
+	uint32_t dbuf_frm_size;
+	uint32_t dbuf_frm_hsize;
+	uint32_t dpp_img_hrz_bef_sr;
+	uint32_t dpp_img_vrt_bef_sr;
+	uint32_t dpp_img_hrz_aft_sr;
+	uint32_t dpp_img_vrt_aft_sr;
+	uint32_t ldi_dpi0_hrz_ctrl0;
+	uint32_t ldi_dpi0_hrz_ctrl1;
+	uint32_t ldi_dpi0_hrz_ctrl2;
+	uint32_t ldi_dpi1_hrz_ctrl0;
+	uint32_t ldi_dpi1_hrz_ctrl1;
+	uint32_t ldi_dpi1_hrz_ctrl2;
+	uint32_t ldi_vrt_ctrl0;
+	uint32_t ldi_vrt_ctrl1;
+	uint32_t ldi_vrt_ctrl2;
+	uint32_t ldi_ctrl;
+	uint32_t ifbc_size;
+	uint32_t edpi_cmd_size;
+	dss_arsr1p_t s_arsr1p;
+} dirty_region_updt_t;
+
+/*******************************************************************************
+ ** dss module reg
+ */
+typedef struct dss_module_reg {
+	char __iomem *mif_ch_base[DSS_CHN_MAX_DEFINE];
+	char __iomem *aif_ch_base[DSS_CHN_MAX_DEFINE];
+	char __iomem *aif1_ch_base[DSS_CHN_MAX_DEFINE];
+	dss_mctl_ch_base_t mctl_ch_base[DSS_CHN_MAX_DEFINE];
+	char __iomem *dma_base[DSS_CHN_MAX_DEFINE];
+	char __iomem *dfc_base[DSS_CHN_MAX_DEFINE];
+	char __iomem *scl_base[DSS_CHN_MAX_DEFINE];
+	char __iomem *scl_lut_base[DSS_CHN_MAX_DEFINE];
+	char __iomem *arsr2p_base[DSS_CHN_MAX_DEFINE];
+	char __iomem *arsr2p_lut_base[DSS_CHN_MAX_DEFINE];
+	char __iomem *post_clip_base[DSS_CHN_MAX_DEFINE];
+	char __iomem *pcsc_base[DSS_CHN_MAX_DEFINE];
+	char __iomem *csc_base[DSS_CHN_MAX_DEFINE];
+
+	char __iomem *ov_base[DSS_OVL_IDX_MAX];
+	char __iomem *mctl_base[DSS_MCTL_IDX_MAX];
+	char __iomem *mctl_sys_base;
+	char __iomem *smmu_base;
+	char __iomem *post_scf_base;
+
+	dss_mif_t mif[DSS_CHN_MAX_DEFINE];
+	dss_aif_t aif[DSS_CHN_MAX_DEFINE];
+	dss_aif_t aif1[DSS_CHN_MAX_DEFINE];
+	dss_aif_bw_t aif_bw[DSS_CHN_MAX_DEFINE];
+	dss_aif_bw_t aif1_bw[DSS_CHN_MAX_DEFINE];
+	dss_rdma_t rdma[DSS_CHN_MAX_DEFINE];
+	dss_wdma_t wdma[DSS_CHN_MAX_DEFINE];
+	dss_dfc_t dfc[DSS_CHN_MAX_DEFINE];
+	dss_scl_t scl[DSS_CHN_MAX_DEFINE];
+	dss_arsr2p_t arsr2p[DSS_CHN_MAX_DEFINE];
+	dss_post_clip_t post_clip[DSS_CHN_MAX_DEFINE];
+	dss_csc_t pcsc[DSS_CHN_MAX_DEFINE];
+	dss_csc_t csc[DSS_CHN_MAX_DEFINE];
+	dss_ovl_t ov[DSS_OVL_IDX_MAX];
+	dss_mctl_t mctl[DSS_MCTL_IDX_MAX];
+	dss_mctl_ch_t mctl_ch[DSS_CHN_MAX_DEFINE];
+	dss_mctl_sys_t mctl_sys;
+	dss_smmu_t smmu;
+	dirty_region_updt_t dirty_region_updt;
+	dss_arsr1p_t post_scf;
+
+	uint8_t mif_used[DSS_CHN_MAX_DEFINE];
+	uint8_t aif_ch_used[DSS_CHN_MAX_DEFINE];
+	uint8_t aif1_ch_used[DSS_CHN_MAX_DEFINE];
+	uint8_t dma_used[DSS_CHN_MAX_DEFINE];
+	uint8_t dfc_used[DSS_CHN_MAX_DEFINE];
+	uint8_t scl_used[DSS_CHN_MAX_DEFINE];
+	uint8_t arsr2p_used[DSS_CHN_MAX_DEFINE];
+	uint8_t arsr2p_effect_used[DSS_CHN_MAX_DEFINE];
+	uint8_t post_cilp_used[DSS_CHN_MAX_DEFINE];
+	uint8_t pcsc_used[DSS_CHN_MAX_DEFINE];
+	uint8_t csc_used[DSS_CHN_MAX_DEFINE];
+	uint8_t ov_used[DSS_OVL_IDX_MAX];
+	uint8_t ch_reg_default_used[DSS_CHN_MAX_DEFINE];
+	uint8_t mctl_used[DSS_MCTL_IDX_MAX];
+	uint8_t mctl_ch_used[DSS_CHN_MAX_DEFINE];
+	uint8_t mctl_sys_used;
+	uint8_t smmu_used;
+	uint8_t dirty_region_updt_used;
+	uint8_t post_scf_used;
+} dss_module_reg_t;
+
+typedef struct dss_mmbuf_info {
+	uint32_t mm_base[DSS_CHN_MAX_DEFINE];
+	uint32_t mm_size[DSS_CHN_MAX_DEFINE];
+
+	uint8_t mm_used[DSS_CHN_MAX_DEFINE];
+} dss_mmbuf_info_t;
+
+#endif				/* HISI_DSS_REGS_H */
-- 
2.12.0-rc0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/8] fb: hisilicon: Add framebuffer driver for hi3660 SoC
  2017-02-07  2:35   ` cailiwei
@ 2017-02-07  2:35     ` cailiwei
  -1 siblings, 0 replies; 15+ messages in thread
From: cailiwei @ 2017-02-07  2:35 UTC (permalink / raw)
  To: linux-fbdev, linux-kernel, b.zolnierkie, guodong.xu
  Cc: suzhuangluan, dengqingshan, xuhongtao8, zhengwanchun,
	shizongxuan, cailiwei

From: Levy-Cai <cailiwei@hisilicon.com>

Add framebuffer driver for hi3660 SoC, this driver include lcd
driver & Hdmi adv7533/adv7535 driver, support lcd display at
1080p@60 and hdmi display at 1080p@60.

Signed-off-by: cailiwei <cailiwei@hisilicon.com>
---
 drivers/video/fbdev/hisi/dss/hisi_fb_bl.c       | 323 +++++++++
 drivers/video/fbdev/hisi/dss/hisi_fb_buf_sync.c | 507 ++++++++++++++
 drivers/video/fbdev/hisi/dss/hisi_fb_def.h      | 125 ++++
 drivers/video/fbdev/hisi/dss/hisi_fb_isr.c      | 327 +++++++++
 drivers/video/fbdev/hisi/dss/hisi_fb_panel.c    | 835 +++++++++++++++++++++++
 drivers/video/fbdev/hisi/dss/hisi_fb_panel.h    | 839 ++++++++++++++++++++++++
 6 files changed, 2956 insertions(+)
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_fb_bl.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_fb_buf_sync.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_fb_def.h
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_fb_isr.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_fb_panel.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_fb_panel.h

diff --git a/drivers/video/fbdev/hisi/dss/hisi_fb_bl.c b/drivers/video/fbdev/hisi/dss/hisi_fb_bl.c
new file mode 100755
index 000000000000..ee4b8c7f4abb
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_fb_bl.c
@@ -0,0 +1,323 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_fb.h"
+#include <linux/leds.h>
+#define K3_DSS_SBL_WORKQUEUE	"k3_dss_sbl_workqueue"
+
+static int lcd_backlight_registered;
+static unsigned int is_recovery_mode;
+static int is_no_fastboot_bl_enable;
+
+#ifdef CONFIG_HISI_FB_BACKLIGHT_DELAY
+unsigned long backlight_duration = (3 * HZ / 60);
+#endif
+
+void hisifb_set_backlight(struct hisi_fb_data_type *hisifd, uint32_t bkl_lvl)
+{
+	struct hisi_fb_panel_data *pdata = NULL;
+	uint32_t temp = bkl_lvl;
+
+	BUG_ON(hisifd == NULL);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata == NULL);
+
+	if (!hisifd->panel_power_on || !hisifd->backlight.bl_updated) {
+		hisifd->bl_level = bkl_lvl;
+		return;
+	}
+
+	if (pdata->set_backlight) {
+		if (hisifd->backlight.bl_level_old == temp) {
+			hisifd->bl_level = bkl_lvl;
+			return;
+		}
+		if (hisifd->backlight.bl_level_old == 0) {
+			HISI_FB_INFO("backlight level = %d", bkl_lvl);
+		}
+		hisifd->bl_level = bkl_lvl;
+		if (hisifd->panel_info.bl_set_type & BL_SET_BY_MIPI) {
+			hisifb_set_vsync_activate_state(hisifd, true);
+			hisifb_activate_vsync(hisifd);
+		}
+		pdata->set_backlight(hisifd->pdev, bkl_lvl);
+		if (hisifd->panel_info.bl_set_type & BL_SET_BY_MIPI) {
+			hisifb_set_vsync_activate_state(hisifd, false);
+			hisifb_deactivate_vsync(hisifd);
+		}
+		hisifd->backlight.bl_level_old = temp;
+	}
+}
+
+#ifdef CONFIG_HISI_FB_BACKLIGHT_DELAY
+static void hisifb_bl_workqueue_handler(struct work_struct *work)
+#else
+static void hisifb_bl_workqueue_handler(struct hisi_fb_data_type *hisifd)
+#endif
+{
+	struct hisi_fb_panel_data *pdata = NULL;
+#ifdef CONFIG_HISI_FB_BACKLIGHT_DELAY
+	struct hisifb_backlight *pbacklight = NULL;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	pbacklight =
+	    container_of(to_delayed_work(work), struct hisifb_backlight,
+			 bl_worker);
+	BUG_ON(pbacklight == NULL);
+
+	hisifd = container_of(pbacklight, struct hisi_fb_data_type, backlight);
+#endif
+
+	BUG_ON(hisifd == NULL);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata == NULL);
+
+	if (!hisifd->backlight.bl_updated) {
+		down(&hisifd->blank_sem);
+
+		if (hisifd->backlight.frame_updated == 0) {
+			up(&hisifd->blank_sem);
+			return;
+		}
+
+		hisifd->backlight.frame_updated = 0;
+		hisifd->backlight.bl_updated = 1;
+		if (is_recovery_mode) {
+			hisifd->bl_level = hisifd->panel_info.bl_default;
+		} else {
+			if (!is_no_fastboot_bl_enable) {
+				is_no_fastboot_bl_enable = 1;
+				hisifd->bl_level =
+				    hisifd->panel_info.bl_default;
+			}
+		}
+
+		hisifb_set_backlight(hisifd, hisifd->bl_level);
+		up(&hisifd->blank_sem);
+	}
+}
+
+void hisifb_backlight_update(struct hisi_fb_data_type *hisifd)
+{
+	struct hisi_fb_panel_data *pdata = NULL;
+
+	BUG_ON(hisifd == NULL);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata == NULL);
+
+	if (!hisifd->backlight.bl_updated) {
+		hisifd->backlight.frame_updated = 1;
+#ifdef CONFIG_HISI_FB_BACKLIGHT_DELAY
+		schedule_delayed_work(&hisifd->backlight.bl_worker,
+				      backlight_duration);
+#else
+		hisifb_bl_workqueue_handler(hisifd);
+#endif
+	}
+}
+
+void hisifb_backlight_cancel(struct hisi_fb_data_type *hisifd)
+{
+	struct hisi_fb_panel_data *pdata = NULL;
+
+	BUG_ON(hisifd == NULL);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata == NULL);
+
+#ifdef CONFIG_HISI_FB_BACKLIGHT_DELAY
+	cancel_delayed_work(&hisifd->backlight.bl_worker);
+#endif
+	hisifd->backlight.bl_updated = 0;
+	hisifd->backlight.bl_level_old = 0;
+	hisifd->backlight.frame_updated = 0;
+
+	if (pdata->set_backlight) {
+		hisifd->bl_level = 0;
+		if (hisifd->panel_info.bl_set_type & BL_SET_BY_MIPI)
+			hisifb_activate_vsync(hisifd);
+		pdata->set_backlight(hisifd->pdev, hisifd->bl_level);
+		if (hisifd->panel_info.bl_set_type & BL_SET_BY_MIPI)
+			hisifb_deactivate_vsync(hisifd);
+	}
+}
+
+#ifdef CONFIG_FB_BACKLIGHT
+static int hisi_fb_bl_get_brightness(struct backlight_device *pbd)
+{
+	if (NULL == pbd) {
+		HISI_FB_ERR("NULL pointer!\n");
+		return 0;
+	}
+	return pbd->props.brightness;
+}
+
+static int hisi_fb_bl_update_status(struct backlight_device *pbd)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	uint32_t bl_lvl = 0;
+
+	if (NULL == pbd) {
+		HISI_FB_ERR("NULL pointer!\n");
+		return 0;
+	}
+
+	hisifd = bl_get_data(pbd);
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL pointer!\n");
+		return 0;
+	}
+
+	bl_lvl = pbd->props.brightness;
+	bl_lvl = hisifd->fbi->bl_curve[bl_lvl];
+
+	down(&hisifd->blank_sem);
+	hisifb_set_backlight(hisifd, bl_lvl);
+	up(&hisifd->blank_sem);
+
+	return 0;
+}
+
+static struct backlight_ops hisi_fb_bl_ops = {
+	.get_brightness = hisi_fb_bl_get_brightness,
+	.update_status = hisi_fb_bl_update_status,
+};
+#else
+static void hisi_fb_set_bl_brightness(struct led_classdev *led_cdev,
+				      enum led_brightness value)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	int bl_lvl = 0;
+
+	if (NULL == led_cdev) {
+		HISI_FB_ERR("NULL pointer!\n");
+		return;
+	}
+
+	hisifd = dev_get_drvdata(led_cdev->dev->parent);
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL pointer!\n");
+		return;
+	}
+
+	if (value < 0)
+		value = 0;
+
+	if (value > hisifd->panel_info.bl_max)
+		value = hisifd->panel_info.bl_max;
+
+	/* This maps android backlight level 0 to 255 into
+	   driver backlight level 0 to bl_max with rounding */
+	bl_lvl =
+	    (2 * value * hisifd->panel_info.bl_max + hisifd->panel_info.bl_max)
+	    / (2 * hisifd->panel_info.bl_max);
+	if (!bl_lvl && value)
+		bl_lvl = 1;
+	hisifb_set_backlight(hisifd, bl_lvl);
+}
+
+static struct led_classdev backlight_led = {
+	.name = DEV_NAME_LCD_BKL,
+	.brightness_set = hisi_fb_set_bl_brightness,
+};
+#endif
+
+void hisifb_backlight_register(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+#ifdef CONFIG_FB_BACKLIGHT
+	struct backlight_device *pbd = NULL;
+	struct fb_info *fbi = NULL;
+	char name[16] = { 0 };
+	struct backlight_properties props;
+#endif
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	hisifd->backlight.bl_updated = 0;
+	hisifd->backlight.frame_updated = 0;
+	hisifd->backlight.bl_level_old = 0;
+	sema_init(&hisifd->backlight.bl_sem, 1);
+#ifdef CONFIG_HISI_FB_BACKLIGHT_DELAY
+	INIT_DELAYED_WORK(&hisifd->backlight.bl_worker,
+			  hisifb_bl_workqueue_handler);
+#endif
+
+	if (lcd_backlight_registered) return;
+
+#ifdef CONFIG_FB_BACKLIGHT
+	fbi = hisifd->fbi;
+
+	snprintf(name, sizeof(name), "hisifb%d_bl", hisifd->index);
+	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+	props.brightness = FB_BACKLIGHT_LEVELS - 1;
+	pbd = backlight_device_register(name, fbi->dev, hisifd,
+					&hisi_fb_bl_ops, &props);
+	if (IS_ERR(pbd)) {
+		fbi->bl_dev = NULL;
+		HISI_FB_ERR("backlight_device_register failed!\n");
+	}
+
+	fbi->bl_dev = pbd;
+	fb_bl_default_curve(fbi, 0,
+			    hisifd->panel_info.bl_min,
+			    hisifd->panel_info.bl_max);
+#else
+	backlight_led.brightness = hisifd->panel_info.bl_default;
+	backlight_led.max_brightness = hisifd->panel_info.bl_max;
+	/* android supports only one lcd-backlight/lcd for now */
+#ifdef CONFIG_LEDS_CLASS
+	if (led_classdev_register(&pdev->dev, &backlight_led)) {
+		HISI_FB_ERR("led_classdev_register failed!\n");
+		return;
+	}
+#endif
+#endif
+
+	if (HISI_DSS_SUPPORT_DPP_MODULE_BIT(DPP_MODULE_SBL)) {
+		hisifd->backlight.sbl_queue =
+		    create_singlethread_workqueue(K3_DSS_SBL_WORKQUEUE);
+		if (!hisifd->backlight.sbl_queue) {
+			HISI_FB_ERR("failed to create sbl_queue!\n");
+			return;
+		}
+	}
+
+	lcd_backlight_registered = 1;
+}
+
+void hisifb_backlight_unregister(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	if (lcd_backlight_registered) {
+		lcd_backlight_registered = 0;
+#ifdef CONFIG_FB_BACKLIGHT
+		/* remove /sys/class/backlight */
+		backlight_device_unregister(hisifd->fbi->bl_dev);
+#else
+#ifdef CONFIG_LEDS_CLASS
+		led_classdev_unregister(&backlight_led);
+#endif
+#endif
+		if (hisifd->backlight.sbl_queue) {
+			destroy_workqueue(hisifd->backlight.sbl_queue);
+			hisifd->backlight.sbl_queue = NULL;
+		}
+	}
+}
diff --git a/drivers/video/fbdev/hisi/dss/hisi_fb_buf_sync.c b/drivers/video/fbdev/hisi/dss/hisi_fb_buf_sync.c
new file mode 100755
index 000000000000..e36a39ad4d31
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_fb_buf_sync.c
@@ -0,0 +1,507 @@
+/* Copyright (c) 2008-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_fb.h"
+
+#define HISI_DSS_LAYERBUF_FREE	"hisi-dss-layerbuf-free"
+
+int hisifb_layerbuf_lock(struct hisi_fb_data_type *hisifd,
+			 dss_overlay_t *pov_req, struct list_head *plock_list)
+{
+	dss_overlay_block_t *pov_h_block_infos = NULL;
+	dss_overlay_block_t *pov_h_block = NULL;
+	dss_layer_t *layer = NULL;
+	int i = 0;
+	int m = 0;
+	struct hisifb_layerbuf *node = NULL;
+	struct ion_handle *ionhnd = NULL;
+	struct iommu_map_format iommu_format;
+	bool add_tail = false;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_req == NULL);
+	BUG_ON(plock_list == NULL);
+
+	pov_h_block_infos =
+	    (dss_overlay_block_t *) (pov_req->ov_block_infos_ptr);
+	for (m = 0; m < pov_req->ov_block_nums; m++) {
+		pov_h_block = &(pov_h_block_infos[m]);
+
+		for (i = 0; i < pov_h_block->layer_nums; i++) {
+			layer = &(pov_h_block->layer_infos[i]);
+			add_tail = false;
+			ionhnd = NULL;
+
+			if (layer->dst_rect.y < pov_h_block->ov_block_rect.y)
+				continue;
+
+			if (layer->img.shared_fd < 0)
+				continue;
+
+			if ((layer->img.phy_addr == 0) &&
+			    (layer->img.vir_addr == 0) &&
+			    (layer->img.afbc_payload_addr == 0)) {
+				HISI_FB_ERR
+				    ("fb%d, layer_idx%d, chn_idx%d, no buffer!\n",
+				     hisifd->index, layer->layer_idx,
+				     layer->chn_idx);
+				continue;
+			}
+
+			if (layer->img.shared_fd >= 0) {
+				ionhnd =
+				    ion_import_dma_buf(hisifd->ion_client,
+						       layer->img.shared_fd);
+				if (IS_ERR(ionhnd)) {
+					ionhnd = NULL;
+					HISI_FB_ERR
+					    ("fb%d, layer_idx%d, failed to ion_import_dma_buf, "
+					     "ionclient %p, share_fd %d!\n",
+					     hisifd->index, i,
+					     hisifd->ion_client,
+					     layer->img.shared_fd);
+				} else {
+					if (layer->img.mmu_enable == 1) {
+						memset(&iommu_format, 0,
+						       sizeof(struct iommu_map_format));
+								ion_map_iommu(hisifd->ion_client,ionhnd,
+							      &iommu_format);
+					}
+					add_tail = true;
+				}
+			}
+
+			if (add_tail) {
+				node =
+				    kzalloc(sizeof(struct hisifb_layerbuf),
+					    GFP_KERNEL);
+				if (node == NULL) {
+					HISI_FB_ERR
+					    ("fb%d, layer_idx%d, failed to kzalloc!\n",
+					     hisifd->index, layer->layer_idx);
+
+					if (ionhnd) {
+						ion_free(hisifd->ion_client,
+							 ionhnd);
+						ionhnd = NULL;
+					}
+					continue;
+				}
+
+				node->shared_fd = layer->img.shared_fd;
+				node->frame_no = pov_req->frame_no;
+				node->ion_handle = ionhnd;
+				node->has_map_iommu = (ionhnd
+							&& (layer->img.mmu_enable == 1)) ? true : false;
+				node->timeline = 0;
+
+				node->mmbuf.addr = layer->img.mmbuf_base;
+				node->mmbuf.size = layer->img.mmbuf_size;
+
+				node->vir_addr = layer->img.vir_addr;
+				node->chn_idx = layer->chn_idx;
+
+				list_add_tail(&node->list_node, plock_list);
+				if (g_debug_layerbuf_sync) {
+					HISI_FB_INFO
+					    ("fb%d, frame_no=%d, layer_idx(%d), "
+					     "shared_fd=%d, ion_handle=%p, "
+					     "has_map_iommu=%d, timeline=%d, mmbuf(0x%x, %d).\n",
+					     hisifd->index, node->frame_no, i,
+					     node->shared_fd, node->ion_handle,
+					     node->has_map_iommu,
+					     node->timeline, node->mmbuf.addr,
+					     node->mmbuf.size);
+				}
+			}
+		}
+	}
+
+	return 0;
+}
+
+void hisifb_layerbuf_flush(struct hisi_fb_data_type *hisifd,
+			   struct list_head *plock_list)
+{
+	struct hisifb_layerbuf *node, *_node_;
+	unsigned long flags = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(hisifd->ion_client == NULL);
+	BUG_ON(plock_list == NULL);
+
+	spin_lock_irqsave(&(hisifd->buf_sync_ctrl.layerbuf_spinlock), flags);
+	hisifd->buf_sync_ctrl.layerbuf_flushed = true;
+	list_for_each_entry_safe(node, _node_, plock_list, list_node) {
+		list_del(&node->list_node);
+		list_add_tail(&node->list_node,
+			      &(hisifd->buf_sync_ctrl.layerbuf_list));
+	}
+	spin_unlock_irqrestore(&(hisifd->buf_sync_ctrl.layerbuf_spinlock),
+			       flags);
+}
+
+void hisifb_layerbuf_unlock(struct hisi_fb_data_type *hisifd,
+			    struct list_head *pfree_list)
+{
+	struct hisifb_layerbuf *node, *_node_;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(hisifd->ion_client == NULL);
+	BUG_ON(hisifd->mmbuf_gen_pool == NULL);
+	BUG_ON(pfree_list == NULL);
+
+	list_for_each_entry_safe(node, _node_, pfree_list, list_node) {
+		list_del(&node->list_node);
+
+		if (g_debug_layerbuf_sync) {
+			HISI_FB_INFO
+			    ("fb%d, frame_no=%d, share_fd=%d, "
+			     "ion_handle=%p, has_map_iommu=%d, "
+			     "timeline=%d, mmbuf(0x%x, %d). "
+			     "vir_addr = 0x%llx, chn_idx = %d\n",
+			     hisifd->index, node->frame_no, node->shared_fd,
+			     node->ion_handle, node->has_map_iommu,
+			     node->timeline, node->mmbuf.addr, node->mmbuf.size,
+			     node->vir_addr, node->chn_idx);
+		}
+
+		node->timeline = 0;
+		if (node->ion_handle) {
+			if (node->has_map_iommu) {
+				ion_unmap_iommu(hisifd->ion_client,
+						node->ion_handle);
+			}
+			ion_free(hisifd->ion_client, node->ion_handle);
+		}
+		kfree(node);
+	}
+}
+
+void hisifb_layerbuf_lock_exception(struct hisi_fb_data_type *hisifd,
+				    struct list_head *plock_list)
+{
+	unsigned long flags = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(plock_list == NULL);
+
+	spin_lock_irqsave(&(hisifd->buf_sync_ctrl.layerbuf_spinlock), flags);
+	hisifd->buf_sync_ctrl.layerbuf_flushed = false;
+	spin_unlock_irqrestore(&(hisifd->buf_sync_ctrl.layerbuf_spinlock), flags);
+
+	hisifb_layerbuf_unlock(hisifd, plock_list);
+}
+
+static void hisifb_layerbuf_unlock_work(struct work_struct *work)
+{
+	struct hisifb_buf_sync *pbuf_sync = NULL;
+	struct hisi_fb_data_type *hisifd = NULL;
+	unsigned long flags;
+	struct hisifb_layerbuf *node, *_node_;
+	struct list_head free_list;
+
+	pbuf_sync =
+	    container_of(work, struct hisifb_buf_sync, free_layerbuf_work);
+	BUG_ON(pbuf_sync == NULL);
+	hisifd =
+	    container_of(pbuf_sync, struct hisi_fb_data_type, buf_sync_ctrl);
+	BUG_ON(hisifd == NULL);
+	BUG_ON(hisifd->ion_client == NULL);
+
+	INIT_LIST_HEAD(&free_list);
+	spin_lock_irqsave(&pbuf_sync->layerbuf_spinlock, flags);
+	list_for_each_entry_safe(node, _node_, &pbuf_sync->layerbuf_list,
+				 list_node) {
+		if (node->timeline >= 2) {
+			list_del(&node->list_node);
+			list_add_tail(&node->list_node, &free_list);
+		}
+	}
+	spin_unlock_irqrestore(&pbuf_sync->layerbuf_spinlock, flags);
+
+	hisifb_layerbuf_unlock(hisifd, &free_list);
+}
+
+#ifdef CONFIG_BUF_SYNC_USED
+#define BUF_SYNC_TIMEOUT_MSEC	(10 * MSEC_PER_SEC)
+#define BUF_SYNC_FENCE_NAME	"hisi-dss-fence"
+#define BUF_SYNC_TIMELINE_NAME	"hisi-dss-timeline"
+int hisifb_buf_sync_create_fence(struct hisi_fb_data_type *hisifd,
+				 unsigned value)
+{
+	int fd = -1;
+	struct sync_fence *fence = NULL;
+	struct sync_pt *pt = NULL;
+
+	BUG_ON(hisifd == NULL);
+	fd = get_unused_fd_flags(0);
+	if (fd < 0) {
+		HISI_FB_ERR("get_unused_fd failed!\n");
+		return fd;
+	}
+
+	pt = sw_sync_pt_create(hisifd->buf_sync_ctrl.timeline, value);
+	if (pt == NULL) {
+		return -ENOMEM;
+	}
+
+	fence = sync_fence_create(BUF_SYNC_FENCE_NAME, pt);
+	if (fence == NULL) {
+		sync_pt_free(pt);
+		return -ENOMEM;
+	}
+
+	sync_fence_install(fence, fd);
+
+	return fd;
+}
+
+int hisifb_buf_sync_wait(int fence_fd)
+{
+	int ret = 0;
+	struct sync_fence *fence = NULL;
+
+	fence = sync_fence_fdget(fence_fd);
+	if (fence == NULL) {
+		HISI_FB_ERR("fence_fd=%d, sync_fence_fdget failed!\n",
+			    fence_fd);
+		return -EINVAL;
+	}
+
+	ret = sync_fence_wait(fence, BUF_SYNC_TIMEOUT_MSEC);
+	if (ret < 0) {
+		HISI_FB_ERR("Waiting on fence failed, fence_fd: %d, ret: %d.\n",
+			    fence_fd, ret);
+	}
+	sync_fence_put(fence);
+
+	return ret;
+}
+
+int hisifb_buf_sync_handle(struct hisi_fb_data_type *hisifd,
+			   dss_overlay_t *pov_req)
+{
+	dss_overlay_block_t *pov_h_block_infos = NULL;
+	dss_overlay_block_t *pov_h_block = NULL;
+	dss_layer_t *layer = NULL;
+	int i = 0;
+	int m = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_req == NULL);
+
+	pov_h_block_infos =
+	    (dss_overlay_block_t *) (pov_req->ov_block_infos_ptr);
+	for (m = 0; m < pov_req->ov_block_nums; m++) {
+		pov_h_block = &(pov_h_block_infos[m]);
+
+		for (i = 0; i < pov_h_block->layer_nums; i++) {
+			layer = &(pov_h_block->layer_infos[i]);
+
+			if (layer->dst_rect.y < pov_h_block->ov_block_rect.y)
+				continue;
+
+			if (layer->acquire_fence >= 0) {
+				hisifb_buf_sync_wait(layer->acquire_fence);
+			}
+		}
+	}
+
+	return 0;
+}
+
+void hisifb_buf_sync_signal(struct hisi_fb_data_type *hisifd)
+{
+	struct hisifb_layerbuf *node = NULL;
+	struct hisifb_layerbuf *_node_ = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	spin_lock(&hisifd->buf_sync_ctrl.refresh_lock);
+	if (hisifd->buf_sync_ctrl.refresh) {
+		sw_sync_timeline_inc(hisifd->buf_sync_ctrl.timeline,
+				     hisifd->buf_sync_ctrl.refresh);
+		hisifd->buf_sync_ctrl.refresh = 0;
+	}
+	spin_unlock(&hisifd->buf_sync_ctrl.refresh_lock);
+
+	spin_lock(&(hisifd->buf_sync_ctrl.layerbuf_spinlock));
+	list_for_each_entry_safe(node, _node_,
+				 &(hisifd->buf_sync_ctrl.layerbuf_list),
+				 list_node) {
+		if (hisifd->buf_sync_ctrl.layerbuf_flushed) {
+			node->timeline++;
+		}
+	}
+	hisifd->buf_sync_ctrl.layerbuf_flushed = false;
+	spin_unlock(&(hisifd->buf_sync_ctrl.layerbuf_spinlock));
+
+	queue_work(hisifd->buf_sync_ctrl.free_layerbuf_queue,
+		   &(hisifd->buf_sync_ctrl.free_layerbuf_work));
+}
+
+void hisifb_buf_sync_suspend(struct hisi_fb_data_type *hisifd)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hisifd->buf_sync_ctrl.refresh_lock, flags);
+	sw_sync_timeline_inc(hisifd->buf_sync_ctrl.timeline,
+			     hisifd->buf_sync_ctrl.refresh + 1);
+	hisifd->buf_sync_ctrl.refresh = 0;
+	hisifd->buf_sync_ctrl.timeline_max++;
+	spin_unlock_irqrestore(&hisifd->buf_sync_ctrl.refresh_lock, flags);
+}
+
+void hisifb_buf_sync_register(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	spin_lock_init(&hisifd->buf_sync_ctrl.refresh_lock);
+	hisifd->buf_sync_ctrl.refresh = 0;
+	hisifd->buf_sync_ctrl.timeline_max = 1;
+	hisifd->buf_sync_ctrl.timeline =
+	    sw_sync_timeline_create(BUF_SYNC_TIMELINE_NAME);
+	if (hisifd->buf_sync_ctrl.timeline == NULL) {
+		HISI_FB_ERR("cannot create time line!");
+		return;		/* -ENOMEM */
+	}
+
+	spin_lock_init(&(hisifd->buf_sync_ctrl.layerbuf_spinlock));
+	INIT_LIST_HEAD(&(hisifd->buf_sync_ctrl.layerbuf_list));
+	hisifd->buf_sync_ctrl.layerbuf_flushed = false;
+
+	INIT_WORK(&(hisifd->buf_sync_ctrl.free_layerbuf_work),
+		  hisifb_layerbuf_unlock_work);
+	hisifd->buf_sync_ctrl.free_layerbuf_queue =
+	    create_singlethread_workqueue(HISI_DSS_LAYERBUF_FREE);
+	if (!hisifd->buf_sync_ctrl.free_layerbuf_queue) {
+		HISI_FB_ERR("failed to create free_layerbuf_queue!\n");
+		return;
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+}
+
+void hisifb_buf_sync_unregister(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	if (hisifd->buf_sync_ctrl.timeline) {
+		sync_timeline_destroy((struct sync_timeline *)
+					hisifd->buf_sync_ctrl.timeline);
+		hisifd->buf_sync_ctrl.timeline = NULL;
+	}
+
+	if (hisifd->buf_sync_ctrl.free_layerbuf_queue) {
+		destroy_workqueue(hisifd->buf_sync_ctrl.free_layerbuf_queue);
+		hisifd->buf_sync_ctrl.free_layerbuf_queue = NULL;
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+}
+#else
+int hisifb_buf_sync_wait(int fence_fd)
+{
+	return 0;
+}
+
+int hisifb_buf_sync_handle(struct hisi_fb_data_type *hisifd,
+			   dss_overlay_t *pov_req)
+{
+	return 0;
+}
+
+void hisifb_buf_sync_signal(struct hisi_fb_data_type *hisifd)
+{
+	struct hisifb_layerbuf *node = NULL;
+	struct hisifb_layerbuf *_node_ = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+
+
+	spin_lock(&(hisifd->buf_sync_ctrl.layerbuf_spinlock));
+	list_for_each_entry_safe(node, _node_,
+				 &(hisifd->buf_sync_ctrl.layerbuf_list),
+				 list_node) {
+		if (hisifd->buf_sync_ctrl.layerbuf_flushed) {
+			node->timeline++;
+		}
+	}
+	hisifd->buf_sync_ctrl.layerbuf_flushed = false;
+	spin_unlock(&(hisifd->buf_sync_ctrl.layerbuf_spinlock));
+
+	queue_work(hisifd->buf_sync_ctrl.free_layerbuf_queue,
+		   &(hisifd->buf_sync_ctrl.free_layerbuf_work));
+}
+
+void hisifb_buf_sync_suspend(struct hisi_fb_data_type *hisifd)
+{
+}
+
+void hisifb_buf_sync_register(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+	spin_lock_init(&(hisifd->buf_sync_ctrl.layerbuf_spinlock));
+	INIT_LIST_HEAD(&(hisifd->buf_sync_ctrl.layerbuf_list));
+	hisifd->buf_sync_ctrl.layerbuf_flushed = false;
+
+	INIT_WORK(&(hisifd->buf_sync_ctrl.free_layerbuf_work),
+		  hisifb_layerbuf_unlock_work);
+	hisifd->buf_sync_ctrl.free_layerbuf_queue =
+	    create_singlethread_workqueue(HISI_DSS_LAYERBUF_FREE);
+	if (!hisifd->buf_sync_ctrl.free_layerbuf_queue) {
+		HISI_FB_ERR("failed to create free_layerbuf_queue!\n");
+		return;
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+}
+
+void hisifb_buf_sync_unregister(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	if (hisifd->buf_sync_ctrl.free_layerbuf_queue) {
+		destroy_workqueue(hisifd->buf_sync_ctrl.free_layerbuf_queue);
+		hisifd->buf_sync_ctrl.free_layerbuf_queue = NULL;
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+}
+#endif
diff --git a/drivers/video/fbdev/hisi/dss/hisi_fb_def.h b/drivers/video/fbdev/hisi/dss/hisi_fb_def.h
new file mode 100755
index 000000000000..3496be2e1838
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_fb_def.h
@@ -0,0 +1,125 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+#ifndef HISI_FB_DEF_H
+#define HISI_FB_DEF_H
+
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <asm/bug.h>
+
+#ifndef MAX
+#define MAX(x, y) (((x) > (y)) ? (x) : (y))
+#endif
+
+#ifndef MIN
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+#endif
+
+/* align */
+#ifndef ALIGN_DOWN
+#define ALIGN_DOWN(val, al)  ((val) & ~((al)-1))
+#endif
+#ifndef ALIGN_UP
+#define ALIGN_UP(val, al)    (((val) + ((al)-1)) & ~((al)-1))
+#endif
+
+#ifndef BIT
+#define BIT(x)  (1<<(x))
+#endif
+
+#ifndef IS_EVEN
+#define IS_EVEN(x)  ((x) % 2 == 0)
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define KHZ	(1000)
+#define MHZ	(1000 * 1000)
+
+enum {
+	WAIT_TYPE_US = 0,
+	WAIT_TYPE_MS,
+};
+
+/*--------------------------------------------------------------------------*/
+extern uint32_t hisi_fb_msg_level;
+
+/*
+ * Message printing priorities:
+ * LEVEL 0 KERN_EMERG (highest priority)
+ * LEVEL 1 KERN_ALERT
+ * LEVEL 2 KERN_CRIT
+ * LEVEL 3 KERN_ERR
+ * LEVEL 4 KERN_WARNING
+ * LEVEL 5 KERN_NOTICE
+ * LEVEL 6 KERN_INFO
+ * LEVEL 7 KERN_DEBUG (Lowest priority)
+ */
+#define HISI_FB_EMERG(msg, ...)    \
+	do { if (hisi_fb_msg_level > 0)  \
+		printk(KERN_EMERG "[hisifb]%s: "msg, __func__, ## __VA_ARGS__); } while (0)
+#define HISI_FB_ALERT(msg, ...)    \
+	do { if (hisi_fb_msg_level > 1)  \
+		printk(KERN_ALERT "[hisifb]%s: "msg, __func__, ## __VA_ARGS__); } while (0)
+#define HISI_FB_CRIT(msg, ...)    \
+	do { if (hisi_fb_msg_level > 2)  \
+		printk(KERN_CRIT "[hisifb]%s: "msg, __func__, ## __VA_ARGS__); } while (0)
+#define HISI_FB_ERR(msg, ...)    \
+	do { if (hisi_fb_msg_level > 3)  \
+		printk(KERN_ERR "[hisifb]%s: "msg, __func__, ## __VA_ARGS__); } while (0)
+#define HISI_FB_WARNING(msg, ...)    \
+	do { if (hisi_fb_msg_level > 4)  \
+		printk(KERN_WARNING "[hisifb]%s: "msg, __func__, ## __VA_ARGS__); } while (0)
+#define HISI_FB_NOTICE(msg, ...)    \
+	do { if (hisi_fb_msg_level > 5)  \
+		printk(KERN_NOTICE "[hisifb]%s: "msg, __func__, ## __VA_ARGS__); } while (0)
+#define HISI_FB_INFO(msg, ...)    \
+	do { if (hisi_fb_msg_level > 6)  \
+		printk(KERN_INFO "[hisifb]%s: "msg, __func__, ## __VA_ARGS__); } while (0)
+#define HISI_FB_DEBUG(msg, ...)    \
+	do { if (hisi_fb_msg_level > 7)  \
+		printk(KERN_INFO "[hisifb]%s: "msg, __func__, ## __VA_ARGS__); } while (0)
+
+#define assert(expr) \
+	if(!(expr)) { \
+		printk(KERN_ERR "[hisifb]: assertion failed! %s,%s,%s,line=%d\n",\
+		#expr, __FILE__, __func__, __LINE__); \
+	}
+
+#define HISI_FB_ASSERT(x)   assert(x)
+
+#define outp32(addr, val) writel(val, addr)
+#define outp16(addr, val) writew(val, addr)
+#define outp8(addr, val) writeb(val, addr)
+#define outp(addr, val) outp32(addr, val)
+
+#define inp32(addr) readl(addr)
+#define inp16(addr) readw(addr)
+#define inp8(addr) readb(addr)
+#define inp(addr) inp32(addr)
+
+#define inpw(port) readw(port)
+#define outpw(port, val) writew(val, port)
+#define inpdw(port) readl(port)
+#define outpdw(port, val) writel(val, port)
+
+#endif
diff --git a/drivers/video/fbdev/hisi/dss/hisi_fb_isr.c b/drivers/video/fbdev/hisi/dss/hisi_fb_isr.c
new file mode 100755
index 000000000000..ca361f8028b9
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_fb_isr.c
@@ -0,0 +1,327 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_fb.h"
+#include "hisi_overlay_utils.h"
+
+/*******************************************************************************
+ ** handle isr
+ */
+irqreturn_t dss_pdp_isr(int irq, void *ptr)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	uint32_t isr_s1 = 0;
+	uint32_t isr_s2 = 0;
+	uint32_t isr_s2_dpp = 0;
+	uint32_t isr_s2_smmu = 0;
+	uint32_t mask = 0;
+	uint32_t isr_te_vsync = 0;
+	uint32_t i = 0;
+	uint32_t temp = 0;
+	struct timeval tv;
+	dss_module_reg_t *dss_module = NULL;
+
+	hisifd = (struct hisi_fb_data_type *)ptr;
+	BUG_ON(hisifd == NULL);
+	dss_module = &(hisifd->dss_module);
+
+	isr_s1 = inp32(hisifd->dss_base + GLB_CPU_PDP_INTS);
+	isr_s2 = inp32(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS);
+	isr_s2_dpp = inp32(hisifd->dss_base + DSS_DPP_OFFSET + DPP_INTS);
+	isr_s2_smmu =
+	    inp32(hisifd->dss_base + DSS_SMMU_OFFSET + SMMU_INTSTAT_NS);
+
+	outp32(hisifd->dss_base + DSS_SMMU_OFFSET + SMMU_INTCLR_NS,
+	       isr_s2_smmu);
+	outp32(hisifd->dss_base + DSS_DPP_OFFSET + DPP_INTS, isr_s2_dpp);
+	outp32(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS, isr_s2);
+	outp32(hisifd->dss_base + GLB_CPU_PDP_INTS, isr_s1);
+
+	isr_s1 &= ~(inp32(hisifd->dss_base + GLB_CPU_PDP_INT_MSK));
+	isr_s2 &=
+	    ~(inp32(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK));
+	isr_s2_dpp &= ~(inp32(hisifd->dss_base + DSS_DPP_OFFSET + DPP_INT_MSK));
+
+	if (is_mipi_cmd_panel(hisifd)) {
+		isr_te_vsync = BIT_LCD_TE0_PIN;
+	} else {
+		isr_te_vsync = BIT_VSYNC;
+	}
+
+	if (isr_s2 & BIT_VACTIVE0_END) {
+		hisifd->vactive0_end_flag = 1;
+		if (g_err_status & DSS_PDP_LDI_UNDERFLOW) {
+			temp =
+			    inp32(hisifd->dss_base + DSS_DPP_OFFSET +
+				  DPP_DBG_CNT);
+			HISI_FB_INFO
+			    ("fb%d, BIT_VACTIVE0_END: frame_no=%d, dpp_dbg =0x%x\n",
+			     hisifd->index, hisifd->ov_req.frame_no, temp);
+			g_err_status &= ~DSS_PDP_LDI_UNDERFLOW;
+		}
+	}
+
+	if (isr_s2 & BIT_VACTIVE0_START) {
+		if (hisifd->ov_vactive0_start_isr_handler) {
+			hisifd->ov_vactive0_start_isr_handler(hisifd);
+		}
+
+		if (g_err_status & DSS_PDP_LDI_UNDERFLOW) {
+			temp =
+			    inp32(hisifd->dss_base + DSS_DPP_OFFSET +
+				  DPP_DBG_CNT);
+			HISI_FB_INFO
+			    ("fb%d, BIT_VACTIVE0_START: frame_no=%d, dpp_dbg=0x%x\n",
+			     hisifd->index, hisifd->ov_req.frame_no, temp);
+		}
+	}
+
+	if (isr_s2 & isr_te_vsync) {
+		if (hisifd->vsync_isr_handler) {
+			hisifd->vsync_isr_handler(hisifd);
+		}
+
+		if (hisifd->buf_sync_signal) {
+			hisifd->buf_sync_signal(hisifd);
+		}
+
+		if (g_err_status &
+		    (DSS_PDP_LDI_UNDERFLOW | DSS_PDP_SMMU_ERR |
+		     DSS_SDP_SMMU_ERR)) {
+			temp =
+			    inp32(hisifd->dss_base + DSS_DPP_OFFSET +
+				  DPP_DBG_CNT);
+			HISI_FB_INFO
+			    ("isr_te_vsync:frame_no = %d,dpp_dbg = 0x%x\n",
+			     hisifd->ov_req.frame_no, temp);
+		}
+
+		if (g_debug_ldi_underflow) {
+			hisifb_get_timestamp(&tv);
+			HISI_FB_INFO
+			    ("isr_te_vsync:frame_no = %d,isr_s2 = 0x%x\n",
+			     hisifd->ov_req.frame_no, isr_s2);
+		}
+	}
+
+	if (isr_s2 & BIT_LDI_UNFLOW) {
+		mask = inp32(hisifd->dss_base + DSS_LDI0_OFFSET +
+			  LDI_CPU_ITF_INT_MSK);
+		mask |= BIT_LDI_UNFLOW;
+		outp32(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK, mask);
+
+		if (g_debug_ldi_underflow_clear) {
+			if (is_mipi_cmd_panel(hisifd)) {
+				if (g_ldi_data_gate_en == 0) {
+					if (hisifd->ldi_underflow_wq) {
+						disable_ldi(hisifd);
+						queue_work(hisifd->ldi_underflow_wq,
+							   &hisifd->ldi_underflow_work);
+					}
+				}
+			} else {
+				if (hisifd->ldi_underflow_wq) {
+					disable_ldi(hisifd);
+					queue_work(hisifd->ldi_underflow_wq,
+						   &hisifd->ldi_underflow_work);
+				}
+			}
+		}
+
+		if (g_debug_ldi_underflow) {
+			if (g_debug_ovl_online_composer) {
+				if (hisifd->dss_debug_wq)
+					queue_work(hisifd->dss_debug_wq,
+						   &hisifd->dss_debug_work);
+			}
+		}
+		g_err_status |= DSS_PDP_LDI_UNDERFLOW;
+
+		if (hisifd->ldi_data_gate_en == 0) {
+			temp =
+			    inp32(hisifd->dss_base + DSS_DPP_OFFSET +
+				  DPP_DBG_CNT);
+			HISI_FB_INFO
+			    ("ldi underflow! frame_no = %d,dpp_dbg = 0x%x!\n",
+			     hisifd->ov_req.frame_no, temp);
+
+			for (i = 0; i < DSS_WCHN_W0; i++) {
+				if ((i != DSS_RCHN_V0) && (i != DSS_RCHN_G0)) {
+					HISI_FB_INFO
+					    ("RCH[%d], DMA_BUF_DBG0 = 0x%x,DMA_BUF_DBG1 = 0x%x!!\n",
+					     i, inp32(dss_module->dma_base[i] +
+						   DMA_BUF_DBG0),
+					     inp32(dss_module->dma_base[i] +
+						   DMA_BUF_DBG1));
+				}
+			}
+			for (i = 0; i < 18; i++) {
+				HISI_FB_INFO("MCTL_MOD%d_STATUS = 0x%x\n",
+					     i, inp32(dss_module->mctl_sys_base +
+						   MCTL_MOD0_STATUS + i * 0x4));
+			}
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+irqreturn_t dss_sdp_isr(int irq, void *ptr)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	uint32_t isr_s1 = 0;
+	uint32_t isr_s2 = 0;
+	uint32_t isr_s2_smmu = 0;
+	uint32_t mask = 0;
+
+	hisifd = (struct hisi_fb_data_type *)ptr;
+	BUG_ON(hisifd == NULL);
+
+	isr_s1 = inp32(hisifd->dss_base + GLB_CPU_SDP_INTS);
+	isr_s2 = inp32(hisifd->dss_base + DSS_LDI1_OFFSET + LDI_CPU_ITF_INTS);
+	isr_s2_smmu =
+	    inp32(hisifd->dss_base + DSS_SMMU_OFFSET + SMMU_INTSTAT_NS);
+
+	outp32(hisifd->dss_base + DSS_SMMU_OFFSET + SMMU_INTCLR_NS,
+	       isr_s2_smmu);
+	outp32(hisifd->dss_base + DSS_LDI1_OFFSET + LDI_CPU_ITF_INTS, isr_s2);
+	outp32(hisifd->dss_base + GLB_CPU_SDP_INTS, isr_s1);
+
+	isr_s1 &= ~(inp32(hisifd->dss_base + GLB_CPU_SDP_INT_MSK));
+	isr_s2 &=
+	    ~(inp32(hisifd->dss_base + DSS_LDI1_OFFSET + LDI_CPU_ITF_INT_MSK));
+
+	if (isr_s2 & BIT_VACTIVE0_END) {
+		hisifd->vactive0_end_flag = 1;
+	}
+
+	if (isr_s2 & BIT_VACTIVE0_START) {
+		if (hisifd->ov_vactive0_start_isr_handler)
+			hisifd->ov_vactive0_start_isr_handler(hisifd);
+	}
+
+	if (isr_s2 & BIT_VSYNC) {
+		if (hisifd->vsync_isr_handler) {
+			hisifd->vsync_isr_handler(hisifd);
+		}
+
+		if (hisifd->buf_sync_signal) {
+			hisifd->buf_sync_signal(hisifd);
+		}
+	}
+
+	if (isr_s2 & BIT_LDI_UNFLOW) {
+		mask =
+		    inp32(hisifd->dss_base + DSS_LDI1_OFFSET +
+			  LDI_CPU_ITF_INT_MSK);
+		mask |= BIT_LDI_UNFLOW;
+		outp32(hisifd->dss_base + DSS_LDI1_OFFSET + LDI_CPU_ITF_INT_MSK,
+		       mask);
+		if (g_debug_ldi_underflow_clear) {
+			if (is_mipi_cmd_panel(hisifd)) {
+				if (g_ldi_data_gate_en == 0) {
+					if (hisifd->ldi_underflow_wq) {
+						disable_ldi(hisifd);
+						queue_work(hisifd->ldi_underflow_wq,
+							   &hisifd->ldi_underflow_work);
+					}
+				}
+			} else {
+				if (hisifd->ldi_underflow_wq) {
+					disable_ldi(hisifd);
+					queue_work(hisifd->ldi_underflow_wq,
+						   &hisifd->ldi_underflow_work);
+				}
+			}
+		}
+		if (g_debug_ldi_underflow) {
+			if (g_debug_ovl_online_composer) {
+				if (hisifd->dss_debug_wq)
+					queue_work(hisifd->dss_debug_wq,
+						   &hisifd->dss_debug_work);
+			}
+		}
+		g_err_status |= DSS_SDP_LDI_UNDERFLOW;
+		if (hisifd->ldi_data_gate_en == 0)
+			HISI_FB_ERR("ldi underflow!\n");
+	}
+	return IRQ_HANDLED;
+}
+
+irqreturn_t dss_adp_isr(int irq, void *ptr)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	uint32_t isr_s1 = 0;
+	uint32_t isr_s2_smmu = 0;
+	uint32_t isr_s3_copybit = 0;
+
+	hisifd = (struct hisi_fb_data_type *)ptr;
+	BUG_ON(hisifd == NULL);
+
+	isr_s1 = inp32(hisifd->dss_base + GLB_CPU_OFF_INTS);
+	isr_s2_smmu =
+	    inp32(hisifd->dss_base + DSS_SMMU_OFFSET + SMMU_INTSTAT_NS);
+
+	outp32(hisifd->dss_base + DSS_SMMU_OFFSET + SMMU_INTCLR_NS,
+	       isr_s2_smmu);
+	outp32(hisifd->dss_base + GLB_CPU_OFF_INTS, isr_s1);
+
+	isr_s1 &= ~(inp32(hisifd->dss_base + GLB_CPU_OFF_INT_MSK));
+	isr_s3_copybit = inp32(hisifd->dss_base + GLB_CPU_OFF_CAM_INTS);
+	outp32(hisifd->dss_base + GLB_CPU_OFF_CAM_INTS, isr_s3_copybit);
+	isr_s3_copybit &= ~(inp32(hisifd->dss_base + GLB_CPU_OFF_CAM_INT_MSK));
+
+	if (isr_s1 & BIT_OFF_WCH0_INTS) {
+		if (hisifd->cmdlist_info->cmdlist_wb_flag[WB_TYPE_WCH0] == 1) {
+			hisifd->cmdlist_info->cmdlist_wb_done[WB_TYPE_WCH0] = 1;
+			wake_up_interruptible_all(&
+						  (hisifd->cmdlist_info->cmdlist_wb_wq
+						   [WB_TYPE_WCH0]));
+		}
+	}
+	if (isr_s1 & BIT_OFF_WCH1_INTS) {
+		if (hisifd->cmdlist_info->cmdlist_wb_flag[WB_TYPE_WCH1] == 1) {
+			hisifd->cmdlist_info->cmdlist_wb_done[WB_TYPE_WCH1] = 1;
+			wake_up_interruptible_all(&
+						  (hisifd->cmdlist_info->cmdlist_wb_wq
+						   [WB_TYPE_WCH1]));
+		}
+	}
+	if (isr_s1 & BIT_OFF_WCH0_WCH1_FRM_END_INT) {
+		if (hisifd->cmdlist_info->cmdlist_wb_flag[WB_TYPE_WCH0_WCH1] ==
+		    1) {
+			hisifd->cmdlist_info->
+			    cmdlist_wb_done[WB_TYPE_WCH0_WCH1] = 1;
+			wake_up_interruptible_all(&
+						  (hisifd->cmdlist_info->cmdlist_wb_wq
+						   [WB_TYPE_WCH0_WCH1]));
+		}
+	}
+
+	if (isr_s3_copybit & BIT_OFF_CAM_WCH2_FRMEND_INTS) {
+		if (hisifd->copybit_info->copybit_flag == 1) {
+			hisifd->copybit_info->copybit_done = 1;
+			wake_up_interruptible_all(&
+						  (hisifd->copybit_info->copybit_wq));
+		}
+
+		if (hisifd->cmdlist_info->cmdlist_wb_flag[WB_TYPE_WCH2] == 1) {
+			hisifd->cmdlist_info->cmdlist_wb_done[WB_TYPE_WCH2] = 1;
+			wake_up_interruptible_all(&
+						  (hisifd->cmdlist_info->cmdlist_wb_wq
+						   [WB_TYPE_WCH2]));
+		}
+	}
+
+	return IRQ_HANDLED;
+}
diff --git a/drivers/video/fbdev/hisi/dss/hisi_fb_panel.c b/drivers/video/fbdev/hisi/dss/hisi_fb_panel.c
new file mode 100755
index 000000000000..a26035e8beba
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_fb_panel.c
@@ -0,0 +1,835 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_fb.h"
+#include "hisi_fb_panel.h"
+
+DEFINE_SEMAPHORE(hisi_fb_dts_resource_sem);
+mipi_ifbc_division_t g_mipi_ifbc_division[MIPI_DPHY_NUM][IFBC_TYPE_MAX] = {
+
+	{
+	 {XRES_DIV_1, YRES_DIV_1, IFBC_COMP_MODE_0, PXL0_DIV2_GT_EN_CLOSE,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_0, PXL0_DSI_GT_EN_1}
+	 ,
+
+	 {XRES_DIV_2, YRES_DIV_1, IFBC_COMP_MODE_0, PXL0_DIV2_GT_EN_OPEN,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_1, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_3, YRES_DIV_1, IFBC_COMP_MODE_1, PXL0_DIV2_GT_EN_OPEN,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_2, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_2, YRES_DIV_1, IFBC_COMP_MODE_2, PXL0_DIV2_GT_EN_OPEN,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_1, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_2, YRES_DIV_1, IFBC_COMP_MODE_3, PXL0_DIV2_GT_EN_CLOSE,
+	  PXL0_DIV4_GT_EN_OPEN, PXL0_DIVCFG_1, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_3, YRES_DIV_1, IFBC_COMP_MODE_4, PXL0_DIV2_GT_EN_CLOSE,
+	  PXL0_DIV4_GT_EN_OPEN, PXL0_DIVCFG_2, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_2, YRES_DIV_1, IFBC_COMP_MODE_5, PXL0_DIV2_GT_EN_CLOSE,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_1, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_3, YRES_DIV_1, IFBC_COMP_MODE_5, PXL0_DIV2_GT_EN_CLOSE,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_2, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_2, YRES_DIV_1, IFBC_COMP_MODE_6, PXL0_DIV2_GT_EN_OPEN,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_1, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_3, YRES_DIV_1, IFBC_COMP_MODE_6, PXL0_DIV2_GT_EN_OPEN,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_2, PXL0_DSI_GT_EN_3}
+	 }
+	,
+
+	{
+	 {XRES_DIV_2, YRES_DIV_1, IFBC_COMP_MODE_0, PXL0_DIV2_GT_EN_CLOSE,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_1, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_4, YRES_DIV_1, IFBC_COMP_MODE_0, PXL0_DIV2_GT_EN_OPEN,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_3, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_6, YRES_DIV_1, IFBC_COMP_MODE_1, PXL0_DIV2_GT_EN_OPEN,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_5, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_4, YRES_DIV_1, IFBC_COMP_MODE_2, PXL0_DIV2_GT_EN_OPEN,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_3, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_4, YRES_DIV_1, IFBC_COMP_MODE_3, PXL0_DIV2_GT_EN_CLOSE,
+	  PXL0_DIV4_GT_EN_OPEN, PXL0_DIVCFG_3, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_3, YRES_DIV_2, IFBC_COMP_MODE_4, PXL0_DIV2_GT_EN_CLOSE,
+	  PXL0_DIV4_GT_EN_OPEN, PXL0_DIVCFG_5, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_4, YRES_DIV_1, IFBC_COMP_MODE_5, PXL0_DIV2_GT_EN_CLOSE,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_3, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_6, YRES_DIV_1, IFBC_COMP_MODE_5, PXL0_DIV2_GT_EN_CLOSE,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_5, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_4, YRES_DIV_1, IFBC_COMP_MODE_6, PXL0_DIV2_GT_EN_OPEN,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_3, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_6, YRES_DIV_1, IFBC_COMP_MODE_6, PXL0_DIV2_GT_EN_OPEN,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_5, 3}
+	 }
+};
+
+int gpio_cmds_tx(struct gpio_desc *cmds, int cnt)
+{
+	int ret = 0;
+	struct gpio_desc *cm = NULL;
+	int i = 0;
+
+	cm = cmds;
+	for (i = 0; i < cnt; i++) {
+		if ((cm == NULL) || (cm->label == NULL)) {
+			HISI_FB_ERR("cm or cm->label is null! index=%d\n", i);
+			ret = -1;
+			goto error;
+		}
+
+		if (!gpio_is_valid(*(cm->gpio))) {
+			HISI_FB_ERR
+			    ("gpio invalid, dtype=%d, lable=%s, gpio=%d!\n",
+			     cm->dtype, cm->label, *(cm->gpio));
+			ret = -1;
+			goto error;
+		}
+
+		if (cm->dtype == DTYPE_GPIO_INPUT) {
+			if (gpio_direction_input(*(cm->gpio)) != 0) {
+				HISI_FB_ERR
+				    ("failed to gpio_direction_input, lable=%s, gpio=%d!\n",
+				     cm->label, *(cm->gpio));
+				ret = -1;
+				goto error;
+			}
+		} else if (cm->dtype == DTYPE_GPIO_OUTPUT) {
+			if (gpio_direction_output(*(cm->gpio), cm->value) != 0) {
+				HISI_FB_ERR
+				    ("failed to gpio_direction_output, label%s, gpio=%d!\n",
+				     cm->label, *(cm->gpio));
+				ret = -1;
+				goto error;
+			}
+		} else if (cm->dtype == DTYPE_GPIO_REQUEST) {
+			if (gpio_request(*(cm->gpio), cm->label) != 0) {
+				HISI_FB_ERR
+				    ("failed to gpio_request, lable=%s, gpio=%d!\n",
+				     cm->label, *(cm->gpio));
+				ret = -1;
+				goto error;
+			}
+		} else if (cm->dtype == DTYPE_GPIO_FREE) {
+			gpio_free(*(cm->gpio));
+		} else {
+			HISI_FB_ERR("dtype=%x NOT supported\n", cm->dtype);
+			ret = -1;
+			goto error;
+		}
+
+		if (cm->wait) {
+			if (cm->waittype == WAIT_TYPE_US)
+				udelay(cm->wait);
+			else if (cm->waittype == WAIT_TYPE_MS)
+				mdelay(cm->wait);
+			else
+				mdelay(cm->wait * 1000);
+		}
+
+		cm++;
+	}
+
+	return 0;
+
+ error:
+	return ret;
+}
+
+int resource_cmds_tx(struct platform_device *pdev,
+		     struct resource_desc *cmds, int cnt)
+{
+	int ret = 0;
+	struct resource *res = NULL;
+	struct resource_desc *cm = NULL;
+	int i = 0;
+
+	BUG_ON(pdev == NULL);
+	cm = cmds;
+
+	for (i = 0; i < cnt; i++) {
+		if ((cm == NULL) || (cm->name == NULL)) {
+			HISI_FB_ERR("cm or cm->name is null! index=%d\n", i);
+			ret = -1;
+			goto error;
+		}
+
+		res = platform_get_resource_byname(pdev, cm->flag, cm->name);
+		if (!res) {
+			HISI_FB_ERR("failed to get %s resource!\n", cm->name);
+			ret = -1;
+			goto error;
+		}
+		*(cm->value) = res->start;
+		cm++;
+	}
+
+ error:
+	return ret;
+}
+
+int vcc_cmds_tx(struct platform_device *pdev, struct vcc_desc *cmds, int cnt)
+{
+	int ret = 0;
+	struct vcc_desc *cm = NULL;
+	int i = 0;
+
+	cm = cmds;
+	for (i = 0; i < cnt; i++) {
+		if ((cm == NULL) || (cm->id == NULL)) {
+			HISI_FB_ERR("cm or cm->id is null! index=%d\n", i);
+			ret = -1;
+			goto error;
+		}
+
+		if (cm->dtype == DTYPE_VCC_GET) {
+			BUG_ON(pdev == NULL);
+			*(cm->regulator) =
+			    devm_regulator_get(&pdev->dev, cm->id);
+			if (IS_ERR(*(cm->regulator))) {
+				HISI_FB_ERR("failed to get %s regulator!\n",
+					    cm->id);
+				ret = -1;
+				goto error;
+			}
+		} else if (cm->dtype == DTYPE_VCC_PUT) {
+			if (!IS_ERR(*(cm->regulator))) {
+				devm_regulator_put(*(cm->regulator));
+			}
+		} else if (cm->dtype == DTYPE_VCC_ENABLE) {
+			if (!IS_ERR(*(cm->regulator))) {
+				if (regulator_enable(*(cm->regulator)) != 0) {
+					HISI_FB_ERR
+					    ("failed to enable %s regulator!\n",
+					     cm->id);
+					ret = -1;
+					goto error;
+				}
+			}
+		} else if (cm->dtype == DTYPE_VCC_DISABLE) {
+			if (!IS_ERR(*(cm->regulator))) {
+				if (regulator_disable(*(cm->regulator)) != 0) {
+					HISI_FB_ERR
+					    ("failed to disable %s regulator!\n",
+					     cm->id);
+					ret = -1;
+					goto error;
+				}
+			}
+		} else if (cm->dtype == DTYPE_VCC_SET_VOLTAGE) {
+			if (!IS_ERR(*(cm->regulator))) {
+				if (regulator_set_voltage
+				    (*(cm->regulator), cm->min_uV,
+				     cm->max_uV) != 0) {
+					HISI_FB_ERR
+					    ("failed to set %s regulator voltage!\n",
+					     cm->id);
+					ret = -1;
+					goto error;
+				}
+			}
+		} else {
+			HISI_FB_ERR("dtype=%x NOT supported\n", cm->dtype);
+			ret = -1;
+			goto error;
+		}
+
+		if (cm->wait) {
+			if (cm->waittype == WAIT_TYPE_US)
+				udelay(cm->wait);
+			else if (cm->waittype == WAIT_TYPE_MS)
+				mdelay(cm->wait);
+			else
+				mdelay(cm->wait * 1000);
+		}
+
+		cm++;
+	}
+
+	return 0;
+
+ error:
+	return ret;
+}
+
+int pinctrl_cmds_tx(struct platform_device *pdev, struct pinctrl_cmd_desc *cmds,
+		    int cnt)
+{
+	int ret = 0;
+
+	int i = 0;
+	struct pinctrl_cmd_desc *cm = NULL;
+
+	cm = cmds;
+	for (i = 0; i < cnt; i++) {
+		if (cm == NULL) {
+			HISI_FB_ERR("cm is null! index=%d\n", i);
+			continue;
+		}
+		if (cm->dtype == DTYPE_PINCTRL_GET) {
+			BUG_ON(pdev == NULL);
+			cm->pctrl_data->p = devm_pinctrl_get(&pdev->dev);
+			if (IS_ERR(cm->pctrl_data->p)) {
+				ret = -1;
+				HISI_FB_ERR("failed to get p, index=%d!\n", i);
+				goto err;
+			}
+		} else if (cm->dtype == DTYPE_PINCTRL_STATE_GET) {
+			if (cm->mode == DTYPE_PINCTRL_STATE_DEFAULT) {
+				cm->pctrl_data->pinctrl_def =
+				    pinctrl_lookup_state(cm->pctrl_data->p,
+							 PINCTRL_STATE_DEFAULT);
+				if (IS_ERR(cm->pctrl_data->pinctrl_def)) {
+					ret = -1;
+					HISI_FB_ERR
+					    ("failed to get pinctrl_def, index=%d!\n",
+					     i);
+					goto err;
+				}
+			} else if (cm->mode == DTYPE_PINCTRL_STATE_IDLE) {
+				cm->pctrl_data->pinctrl_idle =
+				    pinctrl_lookup_state(cm->pctrl_data->p,
+							 PINCTRL_STATE_IDLE);
+				if (IS_ERR(cm->pctrl_data->pinctrl_idle)) {
+					ret = -1;
+					HISI_FB_ERR
+					    ("failed to get pinctrl_idle, index=%d!\n",
+					     i);
+					goto err;
+				}
+			} else {
+				ret = -1;
+				HISI_FB_ERR("unknown pinctrl type to get!\n");
+				goto err;
+			}
+		} else if (cm->dtype == DTYPE_PINCTRL_SET) {
+			if (cm->mode == DTYPE_PINCTRL_STATE_DEFAULT) {
+				if (cm->pctrl_data->p
+				    && cm->pctrl_data->pinctrl_def) {
+					ret =
+					    pinctrl_select_state(cm->pctrl_data->p,
+								 cm->pctrl_data->pinctrl_def);
+					if (ret) {
+						HISI_FB_ERR
+						    ("could not set this pin to default state!\n");
+						ret = -1;
+						goto err;
+					}
+				}
+			} else if (cm->mode == DTYPE_PINCTRL_STATE_IDLE) {
+				if (cm->pctrl_data->p
+				    && cm->pctrl_data->pinctrl_idle) {
+					ret =
+					    pinctrl_select_state(cm->pctrl_data->p,
+								 cm->pctrl_data->pinctrl_idle);
+					if (ret) {
+						HISI_FB_ERR
+						    ("could not set this pin to idle state!\n");
+						ret = -1;
+						goto err;
+					}
+				}
+			} else {
+				ret = -1;
+				HISI_FB_ERR("unknown pinctrl type to set!\n");
+				goto err;
+			}
+		} else if (cm->dtype == DTYPE_PINCTRL_PUT) {
+			if (cm->pctrl_data->p)
+				pinctrl_put(cm->pctrl_data->p);
+		} else {
+			HISI_FB_ERR("not supported command type!\n");
+			ret = -1;
+			goto err;
+		}
+
+		cm++;
+	}
+
+	return 0;
+
+ err:
+	return ret;
+}
+
+int panel_next_on(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct hisi_fb_panel_data *next_pdata = NULL;
+	struct platform_device *next_pdev = NULL;
+
+	BUG_ON(pdev == NULL);
+	pdata = dev_get_platdata(&pdev->dev);
+	BUG_ON(pdata == NULL);
+
+	next_pdev = pdata->next;
+	if (next_pdev) {
+		next_pdata = dev_get_platdata(&next_pdev->dev);
+		if ((next_pdata) && (next_pdata->on))
+			ret = next_pdata->on(next_pdev);
+	}
+
+	return ret;
+}
+
+int panel_next_off(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct hisi_fb_panel_data *next_pdata = NULL;
+	struct platform_device *next_pdev = NULL;
+
+	BUG_ON(pdev == NULL);
+	pdata = dev_get_platdata(&pdev->dev);
+	BUG_ON(pdata == NULL);
+
+	next_pdev = pdata->next;
+	if (next_pdev) {
+		next_pdata = dev_get_platdata(&next_pdev->dev);
+		if ((next_pdata) && (next_pdata->off))
+			ret = next_pdata->off(next_pdev);
+	}
+
+	return ret;
+}
+
+int panel_next_remove(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct hisi_fb_panel_data *next_pdata = NULL;
+	struct platform_device *next_pdev = NULL;
+
+	BUG_ON(pdev == NULL);
+	pdata = dev_get_platdata(&pdev->dev);
+	BUG_ON(pdata == NULL);
+
+	next_pdev = pdata->next;
+	if (next_pdev) {
+		next_pdata = dev_get_platdata(&next_pdev->dev);
+		if ((next_pdata) && (next_pdata->remove))
+			ret = next_pdata->remove(next_pdev);
+	}
+
+	return ret;
+}
+
+int panel_next_set_backlight(struct platform_device *pdev, uint32_t bl_level)
+{
+	int ret = 0;
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct hisi_fb_panel_data *next_pdata = NULL;
+	struct platform_device *next_pdev = NULL;
+
+	BUG_ON(pdev == NULL);
+	pdata = dev_get_platdata(&pdev->dev);
+	BUG_ON(pdata == NULL);
+
+	next_pdev = pdata->next;
+	if (next_pdev) {
+		next_pdata = dev_get_platdata(&next_pdev->dev);
+		if ((next_pdata) && (next_pdata->set_backlight))
+			ret = next_pdata->set_backlight(next_pdev, bl_level);
+	}
+
+	return ret;
+}
+
+int panel_next_vsync_ctrl(struct platform_device *pdev, int enable)
+{
+	int ret = 0;
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct hisi_fb_panel_data *next_pdata = NULL;
+	struct platform_device *next_pdev = NULL;
+
+	BUG_ON(pdev == NULL);
+	pdata = dev_get_platdata(&pdev->dev);
+	BUG_ON(pdata == NULL);
+
+	next_pdev = pdata->next;
+	if (next_pdev) {
+		next_pdata = dev_get_platdata(&next_pdev->dev);
+		if ((next_pdata) && (next_pdata->vsync_ctrl))
+			ret = next_pdata->vsync_ctrl(next_pdev, enable);
+	}
+
+	return ret;
+}
+
+bool is_ldi_panel(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+	if (hisifd->panel_info.type & PANEL_LCDC)
+		return true;
+
+	return false;
+}
+
+bool is_mipi_cmd_panel(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->panel_info.type & (PANEL_MIPI_CMD | PANEL_DUAL_MIPI_CMD))
+		return true;
+
+	return false;
+}
+
+bool is_mipi_cmd_panel_ext(struct hisi_panel_info *pinfo)
+{
+	BUG_ON(pinfo == NULL);
+
+	if (pinfo->type & (PANEL_MIPI_CMD | PANEL_DUAL_MIPI_CMD))
+		return true;
+
+	return false;
+}
+
+bool is_mipi_video_panel(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->panel_info.
+	    type & (PANEL_MIPI_VIDEO | PANEL_DUAL_MIPI_VIDEO | PANEL_RGB2MIPI))
+		return true;
+
+	return false;
+}
+
+bool is_mipi_panel(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->panel_info.type & (PANEL_MIPI_VIDEO | PANEL_MIPI_CMD |
+				       PANEL_DUAL_MIPI_VIDEO |
+				       PANEL_DUAL_MIPI_CMD))
+		return true;
+
+	return false;
+}
+
+bool is_dual_mipi_panel(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->panel_info.
+	    type & (PANEL_DUAL_MIPI_VIDEO | PANEL_DUAL_MIPI_CMD))
+		return true;
+
+	return false;
+}
+
+bool is_dual_mipi_panel_ext(struct hisi_panel_info *pinfo)
+{
+	BUG_ON(pinfo == NULL);
+
+	if (pinfo->type & (PANEL_DUAL_MIPI_VIDEO | PANEL_DUAL_MIPI_CMD))
+		return true;
+
+	return false;
+}
+
+bool is_hisi_writeback_panel(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->panel_info.type & PANEL_WRITEBACK)
+		return true;
+
+	return false;
+}
+
+bool is_ifbc_panel(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->panel_info.ifbc_type != IFBC_TYPE_NONE)
+		return true;
+
+	return false;
+}
+
+bool is_ifbc_vesa_panel(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+
+	if ((hisifd->panel_info.ifbc_type == IFBC_TYPE_VESA2X_SINGLE) ||
+	    (hisifd->panel_info.ifbc_type == IFBC_TYPE_VESA3X_SINGLE) ||
+	    (hisifd->panel_info.ifbc_type == IFBC_TYPE_VESA2X_DUAL) ||
+	    (hisifd->panel_info.ifbc_type == IFBC_TYPE_VESA3X_DUAL))
+		return true;
+
+	return false;
+}
+
+bool mipi_panel_check_reg(struct hisi_fb_data_type *hisifd,
+			  uint32_t *read_value)
+{
+	int ret = 0;
+	char lcd_reg_05[] = { 0x05 };
+	char lcd_reg_0a[] = { 0x0a };
+	char lcd_reg_0e[] = { 0x0e };
+	char lcd_reg_0f[] = { 0x0f };
+
+	struct dsi_cmd_desc lcd_check_reg[] = {
+		{DTYPE_GEN_WRITE1, 0, 10, WAIT_TYPE_US,
+		 sizeof(lcd_reg_05), lcd_reg_05}
+		,
+		{DTYPE_GEN_WRITE1, 0, 10, WAIT_TYPE_US,
+		 sizeof(lcd_reg_0a), lcd_reg_0a}
+		,
+		{DTYPE_GEN_WRITE1, 0, 10, WAIT_TYPE_US,
+		 sizeof(lcd_reg_0e), lcd_reg_0e}
+		,
+		{DTYPE_GEN_WRITE1, 0, 10, WAIT_TYPE_US,
+		 sizeof(lcd_reg_0f), lcd_reg_0f}
+		,
+	};
+
+	ret = mipi_dsi_cmds_rx(read_value, lcd_check_reg,
+			       ARRAY_SIZE(lcd_check_reg),
+			       hisifd->mipi_dsi0_base);
+	if (ret) {
+		HISI_FB_ERR("Read error number: %d\n", ret);
+		return false;
+	}
+
+	return true;
+}
+
+int mipi_ifbc_get_rect(struct hisi_fb_data_type *hisifd, struct dss_rect *rect)
+{
+	uint32_t ifbc_type = 0;
+	uint32_t mipi_idx = 0;
+	uint32_t xres_div = 1;
+	uint32_t yres_div = 1;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(rect == NULL);
+
+	ifbc_type = hisifd->panel_info.ifbc_type;
+	BUG_ON((ifbc_type < IFBC_TYPE_NONE) || (ifbc_type >= IFBC_TYPE_MAX));
+
+	mipi_idx = is_dual_mipi_panel(hisifd) ? 1 : 0;
+
+	xres_div = g_mipi_ifbc_division[mipi_idx][ifbc_type].xres_div;
+	yres_div = g_mipi_ifbc_division[mipi_idx][ifbc_type].yres_div;
+
+	if ((rect->w % xres_div) > 0) {
+		HISI_FB_ERR
+		    ("fb%d, xres(%d) is not division_h(%d) pixel aligned!\n",
+		     hisifd->index, rect->w, xres_div);
+	}
+
+	if ((rect->h % yres_div) > 0) {
+		HISI_FB_ERR
+		    ("fb%d, yres(%d) is not division_v(%d) pixel aligned!\n",
+		     hisifd->index, rect->h, yres_div);
+	}
+
+	if ((mipi_idx == 0) && (ifbc_type == IFBC_TYPE_RSP3X)
+	    && (hisifd->panel_info.type == PANEL_MIPI_CMD)) {
+		rect->w *= 2;
+		rect->h /= 2;
+	}
+
+	rect->w /= xres_div;
+	rect->h /= yres_div;
+
+	return 0;
+}
+
+bool hisi_fb_device_probe_defer(uint32_t panel_type, uint32_t bl_type)
+{
+	bool flag = true;
+
+	down(&hisi_fb_dts_resource_sem);
+
+	switch (panel_type) {
+	case PANEL_NO:
+		if (g_dts_resouce_ready & DTS_FB_RESOURCE_INIT_READY) {
+			flag = false;
+		}
+		break;
+	case PANEL_LCDC:
+	case PANEL_MIPI2RGB:
+	case PANEL_RGB2MIPI:
+		if ((g_dts_resouce_ready & DTS_FB_RESOURCE_INIT_READY) &&
+		    (g_dts_resouce_ready & DTS_SPI_READY)) {
+			if (bl_type & (BL_SET_BY_PWM | BL_SET_BY_BLPWM)) {
+				if (g_dts_resouce_ready & DTS_PWM_READY)
+					flag = false;
+			} else {
+				flag = false;
+			}
+		}
+		break;
+	case PANEL_MIPI_VIDEO:
+	case PANEL_MIPI_CMD:
+	case PANEL_DUAL_MIPI_VIDEO:
+	case PANEL_DUAL_MIPI_CMD:
+	case PANEL_EDP:
+		if (g_dts_resouce_ready & DTS_FB_RESOURCE_INIT_READY) {
+			if (bl_type & (BL_SET_BY_PWM | BL_SET_BY_BLPWM)) {
+				if (g_dts_resouce_ready & DTS_PWM_READY)
+					flag = false;
+			} else {
+				flag = false;
+			}
+		}
+		break;
+	case PANEL_HDMI:
+		if (g_dts_resouce_ready & DTS_PANEL_PRIMARY_READY)
+			flag = false;
+		break;
+	case PANEL_WRITEBACK:
+		if (g_dts_resouce_ready & DTS_PANEL_OFFLINECOMPOSER_READY)
+			flag = false;
+		break;
+	default:
+		HISI_FB_ERR("not support this panel type(%d).\n", panel_type);
+		break;
+	}
+
+	up(&hisi_fb_dts_resource_sem);
+
+	return flag;
+}
+
+void hisi_fb_device_set_status0(uint32_t status)
+{
+	down(&hisi_fb_dts_resource_sem);
+	g_dts_resouce_ready |= status;
+	up(&hisi_fb_dts_resource_sem);
+}
+
+int hisi_fb_device_set_status1(struct hisi_fb_data_type *hisifd)
+{
+	int ret = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	down(&hisi_fb_dts_resource_sem);
+
+	switch (hisifd->panel_info.type) {
+	case PANEL_LCDC:
+	case PANEL_MIPI_VIDEO:
+	case PANEL_MIPI_CMD:
+	case PANEL_DUAL_MIPI_VIDEO:
+	case PANEL_DUAL_MIPI_CMD:
+	case PANEL_EDP:
+	case PANEL_MIPI2RGB:
+	case PANEL_RGB2MIPI:
+	case PANEL_HDMI:
+		if (hisifd->index == PRIMARY_PANEL_IDX) {
+			g_dts_resouce_ready |= DTS_PANEL_PRIMARY_READY;
+		} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+			g_dts_resouce_ready |= DTS_PANEL_EXTERNAL_READY;
+		} else {
+			HISI_FB_ERR("not support fb(%d).\n", hisifd->index);
+		}
+		break;
+	case PANEL_WRITEBACK:
+		g_dts_resouce_ready |= DTS_PANEL_WRITEBACK_READY;
+		break;
+	default:
+		HISI_FB_ERR("not support this panel type(%d).\n",
+			    hisifd->panel_info.type);
+		ret = -1;
+		break;
+	}
+
+	up(&hisi_fb_dts_resource_sem);
+
+	return ret;
+}
+
+struct platform_device *hisi_fb_device_alloc(struct hisi_fb_panel_data *pdata,
+					     uint32_t type, uint32_t id)
+{
+	struct platform_device *this_dev = NULL;
+	char dev_name[32] = { 0 };
+
+	BUG_ON(pdata == NULL);
+
+	switch (type) {
+	case PANEL_MIPI_VIDEO:
+	case PANEL_MIPI_CMD:
+	case PANEL_DUAL_MIPI_VIDEO:
+	case PANEL_DUAL_MIPI_CMD:
+		snprintf(dev_name, sizeof(dev_name), DEV_NAME_MIPIDSI);
+		break;
+	case PANEL_EDP:
+		snprintf(dev_name, sizeof(dev_name), DEV_NAME_EDP);
+		break;
+	case PANEL_NO:
+	case PANEL_LCDC:
+	case PANEL_HDMI:
+	case PANEL_WRITEBACK:
+		snprintf(dev_name, sizeof(dev_name), DEV_NAME_DSS_DPE);
+		break;
+	case PANEL_RGB2MIPI:
+		snprintf(dev_name, sizeof(dev_name), DEV_NAME_RGB2MIPI);
+		break;
+	default:
+		HISI_FB_ERR("invalid panel type = %d!\n", type);
+		return NULL;
+	}
+
+	if (pdata != NULL)
+		pdata->next = NULL;
+	else
+		return NULL;
+
+	this_dev =
+	    platform_device_alloc(dev_name,
+				  (((uint32_t) type << 16) | (uint32_t) id));
+	if (this_dev) {
+		if (platform_device_add_data
+		    (this_dev, pdata, sizeof(struct hisi_fb_panel_data))) {
+			HISI_FB_ERR("failed to platform_device_add_data!\n");
+			platform_device_put(this_dev);
+			return NULL;
+		}
+	}
+
+	return this_dev;
+}
diff --git a/drivers/video/fbdev/hisi/dss/hisi_fb_panel.h b/drivers/video/fbdev/hisi/dss/hisi_fb_panel.h
new file mode 100755
index 000000000000..8afb1f42a8c5
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_fb_panel.h
@@ -0,0 +1,839 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+#ifndef HISI_FB_PANEL_H
+#define HISI_FB_PANEL_H
+
+#include "hisi_fb_def.h"
+#include "hisi_mipi_dsi.h"
+#include "hisi_dss.h"
+
+/* panel type list */
+#define PANEL_NO	BIT(0)	/* No Panel */
+#define PANEL_LCDC	BIT(1)	/* internal LCDC type */
+#define PANEL_HDMI	BIT(2)	/* HDMI TV */
+#define PANEL_MIPI_VIDEO	BIT(3)	/* MIPI */
+#define PANEL_MIPI_CMD	BIT(4)	/* MIPI */
+#define PANEL_DUAL_MIPI_VIDEO	BIT(5)	/* DUAL MIPI */
+#define PANEL_DUAL_MIPI_CMD	BIT(6)	/* DUAL MIPI */
+#define PANEL_EDP	BIT(7)	/* LVDS */
+#define PANEL_MIPI2RGB	BIT(8)	/* MIPI to RGB */
+#define PANEL_RGB2MIPI	BIT(9)	/* RGB to MIPI */
+#define PANEL_WRITEBACK	BIT(11)	/* Wifi display */
+
+/* dts initial */
+#define DTS_FB_RESOURCE_INIT_READY	BIT(0)
+#define DTS_PWM_READY	BIT(1)
+
+#define DTS_SPI_READY	BIT(3)
+#define DTS_PANEL_PRIMARY_READY	BIT(4)
+#define DTS_PANEL_EXTERNAL_READY	BIT(5)
+#define DTS_PANEL_OFFLINECOMPOSER_READY	BIT(6)
+#define DTS_PANEL_WRITEBACK_READY	BIT(7)
+
+/* device name */
+#define DEV_NAME_DSS_DPE		"dss_dpe"
+#define DEV_NAME_SPI			"spi_dev0"
+#define DEV_NAME_HDMI			"hdmi"
+#define DEV_NAME_EDP			"edp"
+#define DEV_NAME_MIPI2RGB		"mipi2rgb"
+#define DEV_NAME_RGB2MIPI		"rgb2mipi"
+#define DEV_NAME_MIPIDSI		"mipi_dsi"
+#define DEV_NAME_FB				"hisi_fb"
+#define DEV_NAME_PWM			"hisi_pwm"
+#define DEV_NAME_BLPWM			"hisi_blpwm"
+#define DEV_NAME_LCD_BKL		"lcd_backlight0"
+
+/* vcc name */
+#define REGULATOR_PDP_NAME	"regulator_dsssubsys"
+#define REGULATOR_MMBUF	"regulator_mmbuf"
+
+/* irq name */
+#define IRQ_PDP_NAME	"irq_pdp"
+#define IRQ_SDP_NAME	"irq_sdp"
+#define IRQ_ADP_NAME	"irq_adp"
+#define IRQ_DSI0_NAME	"irq_dsi0"
+#define IRQ_DSI1_NAME	"irq_dsi1"
+
+/* dts compatible */
+#define DTS_COMP_FB_NAME	"hisilicon,hisifb"
+#define DTS_COMP_PWM_NAME	"hisilicon,hisipwm"
+#define DTS_COMP_BLPWM_NAME	"hisilicon,hisiblpwm"
+#define DTS_PATH_LOGO_BUFFER	"/reserved-memory/logo-buffer"
+
+/* lcd resource name */
+#define LCD_BL_TYPE_NAME	"lcd-bl-type"
+#define FPGA_FLAG_NAME "fpga_flag"
+#define LCD_DISPLAY_TYPE_NAME	"lcd-display-type"
+#define LCD_IFBC_TYPE_NAME	"lcd-ifbc-type"
+
+/* backlight type */
+#define BL_SET_BY_NONE	BIT(0)
+#define BL_SET_BY_PWM	BIT(1)
+#define BL_SET_BY_BLPWM	BIT(2)
+#define BL_SET_BY_MIPI	BIT(3)
+#define BL_SET_BY_SH_BLPWM	BIT(4)
+
+/* supported display effect type */
+#define COMFORM_MODE			BIT(0)
+#define ACM_COLOR_ENHANCE_MODE	BIT(1)
+#define IC_COLOR_ENHANCE_MODE	BIT(2)
+#define CINEMA_MODE				BIT(3)
+#define VR_MODE                     BIT(4)
+#define LED_RG_COLOR_TEMP_MODE	BIT(16)
+#define GAMMA_MAP    BIT(19)
+
+#define LCD_BL_IC_NAME_MAX	(50)
+#define DEV_DSS_VOLTAGE_ID (20)
+
+enum BLPWM_PRECISION_TYPE {
+	BLPWM_PRECISION_DEFAULT_TYPE = 0,
+	BLPWM_PRECISION_10000_TYPE = 1,
+	BLPWM_PRECISION_2048_TYPE = 2,
+};
+
+enum LCD_INIT_STEP {
+	LCD_INIT_NONE = 0,
+	LCD_INIT_POWER_ON,
+	LCD_INIT_LDI_SEND_SEQUENCE,
+	LCD_INIT_MIPI_LP_SEND_SEQUENCE,
+	LCD_INIT_MIPI_HS_SEND_SEQUENCE,
+};
+
+enum LCD_UNINIT_STEP {
+	LCD_UNINIT_NONE = 0,
+	LCD_UNINIT_POWER_OFF,
+	LCD_UNINIT_LDI_SEND_SEQUENCE,
+	LCD_UNINIT_MIPI_LP_SEND_SEQUENCE,
+	LCD_UNINIT_MIPI_HS_SEND_SEQUENCE,
+};
+
+enum LCD_ESD_RECOVER_STEP {
+	LCD_ESD_RECOVER_NONE = 0,
+	LCD_ESD_RECOVER_POWER_OFF,
+	LCD_ESD_RECOVER_POWER_ON,
+};
+
+enum LCD_REFRESH_DIRECTION {
+	LCD_REFRESH_LEFT_TOP = 0,
+	LCD_REFRESH_RIGHT_TOP,
+	LCD_REFRESH_LEFT_BOTTOM,
+	LCD_REFRESH_RIGHT_BOTTOM,
+};
+
+enum IFBC_TYPE {
+	IFBC_TYPE_NONE = 0,
+	IFBC_TYPE_ORISE2X,
+	IFBC_TYPE_ORISE3X,
+	IFBC_TYPE_HIMAX2X,
+	IFBC_TYPE_RSP2X,
+	IFBC_TYPE_RSP3X,
+	IFBC_TYPE_VESA2X_SINGLE,
+	IFBC_TYPE_VESA3X_SINGLE,
+	IFBC_TYPE_VESA2X_DUAL,
+	IFBC_TYPE_VESA3X_DUAL,
+
+	IFBC_TYPE_MAX
+};
+
+enum IFBC_COMP_MODE {
+	IFBC_COMP_MODE_0 = 0,
+	IFBC_COMP_MODE_1,
+	IFBC_COMP_MODE_2,
+	IFBC_COMP_MODE_3,
+	IFBC_COMP_MODE_4,
+	IFBC_COMP_MODE_5,
+	IFBC_COMP_MODE_6,
+};
+
+enum XRES_DIV {
+	XRES_DIV_1 = 1,
+	XRES_DIV_2,
+	XRES_DIV_3,
+	XRES_DIV_4,
+	XRES_DIV_5,
+	XRES_DIV_6,
+};
+
+enum YRES_DIV {
+	YRES_DIV_1 = 1,
+	YRES_DIV_2,
+	YRES_DIV_3,
+	YRES_DIV_4,
+	YRES_DIV_5,
+	YRES_DIV_6,
+};
+
+enum PXL0_DIVCFG {
+	PXL0_DIVCFG_0 = 0,
+	PXL0_DIVCFG_1,
+	PXL0_DIVCFG_2,
+	PXL0_DIVCFG_3,
+	PXL0_DIVCFG_4,
+	PXL0_DIVCFG_5,
+	PXL0_DIVCFG_6,
+	PXL0_DIVCFG_7,
+};
+
+enum PXL0_DIV2_GT_EN {
+	PXL0_DIV2_GT_EN_CLOSE = 0,
+	PXL0_DIV2_GT_EN_OPEN,
+};
+
+enum PXL0_DIV4_GT_EN {
+	PXL0_DIV4_GT_EN_CLOSE = 0,
+	PXL0_DIV4_GT_EN_OPEN,
+};
+
+enum PXL0_DSI_GT_EN {
+	PXL0_DSI_GT_EN_0 = 0,
+	PXL0_DSI_GT_EN_1,
+	PXL0_DSI_GT_EN_2,
+	PXL0_DSI_GT_EN_3,
+};
+
+enum VSYNC_CTRL_TYPE {
+	VSYNC_CTRL_NONE = 0x0,
+	VSYNC_CTRL_ISR_OFF = BIT(0),
+	VSYNC_CTRL_MIPI_ULPS = BIT(1),
+	VSYNC_CTRL_CLK_OFF = BIT(2),
+	VSYNC_CTRL_VCC_OFF = BIT(3),
+};
+
+enum PERI_VOLTAGE_VALUE {
+	PERI_VOLTAGE_07V = 0x0,
+	PERI_VOLTAGE_08V = 0x2,
+};
+
+#define MIPI_DSI_BIT_CLK_STR1	"00001"
+#define MIPI_DSI_BIT_CLK_STR2	"00010"
+#define MIPI_DSI_BIT_CLK_STR3	"00100"
+#define MIPI_DSI_BIT_CLK_STR4	"01000"
+#define MIPI_DSI_BIT_CLK_STR5	"10000"
+
+/* resource desc */
+struct resource_desc {
+	uint32_t flag;
+	char *name;
+	uint32_t *value;
+};
+
+/* dtype for vcc */
+enum {
+	DTYPE_VCC_GET,
+	DTYPE_VCC_PUT,
+	DTYPE_VCC_ENABLE,
+	DTYPE_VCC_DISABLE,
+	DTYPE_VCC_SET_VOLTAGE,
+};
+
+/* vcc desc */
+struct vcc_desc {
+	int dtype;
+	char *id;
+	struct regulator **regulator;
+	int min_uV;
+	int max_uV;
+	int waittype;
+	int wait;
+};
+
+/* pinctrl operation */
+enum {
+	DTYPE_PINCTRL_GET,
+	DTYPE_PINCTRL_STATE_GET,
+	DTYPE_PINCTRL_SET,
+	DTYPE_PINCTRL_PUT,
+};
+
+/* pinctrl state */
+enum {
+	DTYPE_PINCTRL_STATE_DEFAULT,
+	DTYPE_PINCTRL_STATE_IDLE,
+};
+
+/* pinctrl data */
+struct pinctrl_data {
+	struct pinctrl *p;
+	struct pinctrl_state *pinctrl_def;
+	struct pinctrl_state *pinctrl_idle;
+};
+struct pinctrl_cmd_desc {
+	int dtype;
+	struct pinctrl_data *pctrl_data;
+	int mode;
+};
+
+/* dtype for gpio */
+enum {
+	DTYPE_GPIO_REQUEST,
+	DTYPE_GPIO_FREE,
+	DTYPE_GPIO_INPUT,
+	DTYPE_GPIO_OUTPUT,
+};
+
+/* gpio desc */
+struct gpio_desc {
+	int dtype;
+	int waittype;
+	int wait;
+	char *label;
+	uint32_t *gpio;
+	int value;
+};
+
+struct spi_cmd_desc {
+	int reg_len;
+	char *reg;
+	int val_len;
+	char *val;
+	int waittype;
+	int wait;
+};
+
+enum {
+	IFBC_ORISE_CTL_8LINE = 0,
+	IFBC_ORISE_CTL_16LINE,
+	IFBC_ORISE_CTL_32LINE,
+	IFBC_ORISE_CTL_FRAME,
+};
+
+typedef struct mipi_ifbc_division {
+	uint32_t xres_div;
+	uint32_t yres_div;
+	uint32_t comp_mode;
+	uint32_t pxl0_div2_gt_en;
+	uint32_t pxl0_div4_gt_en;
+	uint32_t pxl0_divxcfg;
+	uint32_t pxl0_dsi_gt_en;
+} mipi_ifbc_division_t;
+
+struct ldi_panel_info {
+	uint32_t h_back_porch;
+	uint32_t h_front_porch;
+	uint32_t h_pulse_width;
+
+	/*
+	 ** note: vbp > 8 if used overlay compose,
+	 ** also lcd vbp > 8 in lcd power on sequence
+	 */
+	uint32_t v_back_porch;
+	uint32_t v_front_porch;
+	uint32_t v_pulse_width;
+
+	uint8_t hsync_plr;
+	uint8_t vsync_plr;
+	uint8_t pixelclk_plr;
+	uint8_t data_en_plr;
+
+	/* for cabc */
+	uint8_t dpi0_overlap_size;
+	uint8_t dpi1_overlap_size;
+};
+
+/* DSI PHY configuration */
+struct mipi_dsi_phy_ctrl {
+	uint64_t lane_byte_clk;
+	uint32_t clk_division;
+
+	uint32_t clk_lane_lp2hs_time;
+	uint32_t clk_lane_hs2lp_time;
+	uint32_t data_lane_lp2hs_time;
+	uint32_t data_lane_hs2lp_time;
+	uint32_t clk2data_delay;
+	uint32_t data2clk_delay;
+
+	uint32_t clk_pre_delay;
+	uint32_t clk_post_delay;
+	uint32_t clk_t_lpx;
+	uint32_t clk_t_hs_prepare;
+	uint32_t clk_t_hs_zero;
+	uint32_t clk_t_hs_trial;
+	uint32_t clk_t_wakeup;
+	uint32_t data_pre_delay;
+	uint32_t data_post_delay;
+	uint32_t data_t_lpx;
+	uint32_t data_t_hs_prepare;
+	uint32_t data_t_hs_zero;
+	uint32_t data_t_hs_trial;
+	uint32_t data_t_ta_go;
+	uint32_t data_t_ta_get;
+	uint32_t data_t_wakeup;
+
+	uint32_t phy_stop_wait_time;
+
+	uint32_t rg_vrefsel_vcm;
+	uint32_t rg_hstx_ckg_sel;
+	uint32_t rg_pll_fbd_div5f;
+	uint32_t rg_pll_fbd_div1f;
+	uint32_t rg_pll_fbd_2p;
+	uint32_t rg_pll_enbwt;
+	uint32_t rg_pll_fbd_p;
+	uint32_t rg_pll_fbd_s;
+	uint32_t rg_pll_pre_div1p;
+	uint32_t rg_pll_pre_p;
+	uint32_t rg_pll_vco_750m;
+	uint32_t rg_pll_lpf_rs;
+	uint32_t rg_pll_lpf_cs;
+	uint32_t rg_pll_enswc;
+	uint32_t rg_pll_chp;
+
+
+	uint32_t pll_register_override;
+	uint32_t pll_power_down;
+	uint32_t rg_band_sel;
+	uint32_t rg_phase_gen_en;
+	uint32_t reload_sel;
+	uint32_t rg_pll_cp_p;
+	uint32_t rg_pll_refsel;
+	uint32_t rg_pll_cp;
+	uint32_t load_command;
+};
+
+struct mipi_panel_info {
+	uint8_t dsi_version;
+	uint8_t vc;
+	uint8_t lane_nums;
+	uint8_t lane_nums_select_support;
+	uint8_t color_mode;
+	uint32_t dsi_bit_clk;	/* clock lane(p/n) */
+	uint32_t burst_mode;
+	uint32_t max_tx_esc_clk;
+	uint8_t non_continue_en;
+
+	uint32_t dsi_bit_clk_val1;
+	uint32_t dsi_bit_clk_val2;
+	uint32_t dsi_bit_clk_val3;
+	uint32_t dsi_bit_clk_val4;
+	uint32_t dsi_bit_clk_val5;
+	uint32_t dsi_bit_clk_upt;
+	/*uint32_t dsi_pclk_rate; */
+
+	uint32_t hs_wr_to_time;
+
+	uint32_t clk_post_adjust;
+	uint32_t clk_pre_adjust;
+	uint32_t clk_pre_delay_adjust;
+	uint32_t clk_t_hs_exit_adjust;
+	uint32_t clk_t_hs_trial_adjust;
+	uint32_t clk_t_hs_prepare_adjust;
+	int clk_t_lpx_adjust;
+	uint32_t clk_t_hs_zero_adjust;
+	uint32_t data_post_delay_adjust;
+	int data_t_lpx_adjust;
+	uint32_t data_t_hs_prepare_adjust;
+	uint32_t data_t_hs_zero_adjust;
+	uint32_t data_t_hs_trial_adjust;
+	uint32_t rg_vrefsel_vcm_adjust;
+
+	uint32_t rg_vrefsel_vcm_clk_adjust;
+	uint32_t rg_vrefsel_vcm_data_adjust;
+};
+
+struct sbl_panel_info {
+	uint32_t strength_limit;
+	uint32_t calibration_a;
+	uint32_t calibration_b;
+	uint32_t calibration_c;
+	uint32_t calibration_d;
+	uint32_t t_filter_control;
+	uint32_t backlight_min;
+	uint32_t backlight_max;
+	uint32_t backlight_scale;
+	uint32_t ambient_light_min;
+	uint32_t filter_a;
+	uint32_t filter_b;
+	uint32_t logo_left;
+	uint32_t logo_top;
+	uint32_t variance_intensity_space;
+	uint32_t slope_max;
+	uint32_t slope_min;
+};
+
+typedef struct dss_sharpness_bit {
+	uint32_t sharp_en;
+	uint32_t sharp_mode;
+
+	uint32_t flt0_c0;
+	uint32_t flt0_c1;
+	uint32_t flt0_c2;
+
+	uint32_t flt1_c0;
+	uint32_t flt1_c1;
+	uint32_t flt1_c2;
+
+	uint32_t flt2_c0;
+	uint32_t flt2_c1;
+	uint32_t flt2_c2;
+
+	uint32_t ungain;
+	uint32_t ovgain;
+
+	uint32_t lineamt1;
+	uint32_t linedeten;
+	uint32_t linethd2;
+	uint32_t linethd1;
+
+	uint32_t sharpthd1;
+	uint32_t sharpthd1mul;
+	uint32_t sharpamt1;
+
+	uint32_t edgethd1;
+	uint32_t edgethd1mul;
+	uint32_t edgeamt1;
+} sharp2d_t;
+
+struct dsc_panel_info {
+
+	uint32_t bits_per_pixel;
+	uint32_t block_pred_enable;
+	uint32_t linebuf_depth;
+	uint32_t bits_per_component;
+	uint32_t slice_width;
+	uint32_t slice_height;
+	uint32_t initial_xmit_delay;
+	uint32_t first_line_bpg_offset;
+	uint32_t mux_word_size;
+	uint32_t initial_offset;
+	uint32_t flatness_max_qp;
+	uint32_t flatness_min_qp;
+	uint32_t rc_edge_factor;
+	uint32_t rc_model_size;
+	uint32_t rc_tgt_offset_lo;
+	uint32_t rc_tgt_offset_hi;
+	uint32_t rc_quant_incr_limit1;
+	uint32_t rc_quant_incr_limit0;
+	uint32_t rc_buf_thresh0;
+	uint32_t rc_buf_thresh1;
+	uint32_t rc_buf_thresh2;
+	uint32_t rc_buf_thresh3;
+	uint32_t rc_buf_thresh4;
+	uint32_t rc_buf_thresh5;
+	uint32_t rc_buf_thresh6;
+	uint32_t rc_buf_thresh7;
+	uint32_t rc_buf_thresh8;
+	uint32_t rc_buf_thresh9;
+	uint32_t rc_buf_thresh10;
+	uint32_t rc_buf_thresh11;
+	uint32_t rc_buf_thresh12;
+	uint32_t rc_buf_thresh13;
+	uint32_t range_min_qp0;
+	uint32_t range_max_qp0;
+	uint32_t range_bpg_offset0;
+	uint32_t range_min_qp1;
+	uint32_t range_max_qp1;
+	uint32_t range_bpg_offset1;
+	uint32_t range_min_qp2;
+	uint32_t range_max_qp2;
+	uint32_t range_bpg_offset2;
+	uint32_t range_min_qp3;
+	uint32_t range_max_qp3;
+	uint32_t range_bpg_offset3;
+	uint32_t range_min_qp4;
+	uint32_t range_max_qp4;
+	uint32_t range_bpg_offset4;
+	uint32_t range_min_qp5;
+	uint32_t range_max_qp5;
+	uint32_t range_bpg_offset5;
+	uint32_t range_min_qp6;
+	uint32_t range_max_qp6;
+	uint32_t range_bpg_offset6;
+	uint32_t range_min_qp7;
+	uint32_t range_max_qp7;
+	uint32_t range_bpg_offset7;
+	uint32_t range_min_qp8;
+	uint32_t range_max_qp8;
+	uint32_t range_bpg_offset8;
+	uint32_t range_min_qp9;
+	uint32_t range_max_qp9;
+	uint32_t range_bpg_offset9;
+	uint32_t range_min_qp10;
+	uint32_t range_max_qp10;
+	uint32_t range_bpg_offset10;
+	uint32_t range_min_qp11;
+	uint32_t range_max_qp11;
+	uint32_t range_bpg_offset11;
+	uint32_t range_min_qp12;
+	uint32_t range_max_qp12;
+	uint32_t range_bpg_offset12;
+	uint32_t range_min_qp13;
+	uint32_t range_max_qp13;
+	uint32_t range_bpg_offset13;
+	uint32_t range_min_qp14;
+	uint32_t range_max_qp14;
+	uint32_t range_bpg_offset14;
+};
+
+struct hisi_panel_info {
+	uint32_t type;
+	uint32_t xres;
+	uint32_t yres;
+	uint32_t width;
+	uint32_t height;
+	uint32_t bpp;
+	uint32_t fps;
+	uint32_t fps_updt;
+	uint32_t orientation;
+	uint32_t bgr_fmt;
+	uint32_t bl_set_type;
+	uint32_t bl_min;
+	uint32_t bl_max;
+	uint32_t bl_default;
+	uint32_t blpwm_precision_type;
+	uint32_t blpwm_out_div_value;
+	uint32_t blpwm_input_ena;
+	uint32_t blpwm_in_num;
+	uint32_t blpwm_input_precision;
+	uint32_t bl_ic_ctrl_mode;
+	uint64_t pxl_clk_rate;
+	uint64_t pxl_clk_rate_adjust;
+	uint32_t pxl_clk_rate_div;
+	uint32_t vsync_ctrl_type;
+	uint8_t fake_hdmi;
+	uint8_t reserved[3];
+
+	uint32_t ifbc_type;
+	uint32_t ifbc_cmp_dat_rev0;
+	uint32_t ifbc_cmp_dat_rev1;
+	uint32_t ifbc_auto_sel;
+	uint32_t ifbc_orise_ctl;
+	uint32_t ifbc_orise_ctr;
+
+	uint8_t lcd_init_step;
+	uint8_t lcd_uninit_step;
+	uint8_t lcd_uninit_step_support;
+	uint8_t lcd_refresh_direction_ctrl;
+	uint8_t lcd_adjust_support;
+
+	uint8_t sbl_support;
+	uint8_t color_temperature_support;
+	uint8_t color_temp_rectify_support;
+	uint32_t color_temp_rectify_R;
+	uint32_t color_temp_rectify_G;
+	uint32_t color_temp_rectify_B;
+	uint8_t comform_mode_support;
+	uint8_t cinema_mode_support;
+	uint8_t frc_enable;
+	uint8_t esd_enable;
+	uint8_t esd_skip_mipi_check;
+	uint8_t esd_recover_step;
+	uint8_t dirty_region_updt_support;
+	uint8_t dsi_bit_clk_upt_support;
+	uint8_t fps_updt_support;
+	uint8_t panel_effect_support;
+
+	uint8_t prefix_ce_support;
+	uint8_t prefix_sharpness1D_support;
+	uint8_t prefix_sharpness2D_support;
+	sharp2d_t *sharp2d_table;
+
+	uint8_t gmp_support;
+	uint8_t gamma_support;
+	uint8_t gamma_type;
+	uint8_t xcc_support;
+	uint8_t acm_support;
+	uint8_t acm_ce_support;
+	uint8_t hiace_support;
+	uint8_t dither_support;
+	uint8_t arsr1p_sharpness_support;
+	uint8_t post_scf_support;
+	uint8_t default_gmp_off;
+
+	uint32_t acm_valid_num;
+	uint32_t r0_hh;
+	uint32_t r0_lh;
+	uint32_t r1_hh;
+	uint32_t r1_lh;
+	uint32_t r2_hh;
+	uint32_t r2_lh;
+	uint32_t r3_hh;
+	uint32_t r3_lh;
+	uint32_t r4_hh;
+	uint32_t r4_lh;
+	uint32_t r5_hh;
+	uint32_t r5_lh;
+	uint32_t r6_hh;
+	uint32_t r6_lh;
+
+	uint32_t cinema_acm_valid_num;
+	uint32_t cinema_r0_hh;
+	uint32_t cinema_r0_lh;
+	uint32_t cinema_r1_hh;
+	uint32_t cinema_r1_lh;
+	uint32_t cinema_r2_hh;
+	uint32_t cinema_r2_lh;
+	uint32_t cinema_r3_hh;
+	uint32_t cinema_r3_lh;
+	uint32_t cinema_r4_hh;
+	uint32_t cinema_r4_lh;
+	uint32_t cinema_r5_hh;
+	uint32_t cinema_r5_lh;
+	uint32_t cinema_r6_hh;
+	uint32_t cinema_r6_lh;
+
+	uint32_t *acm_lut_hue_table;
+	uint32_t acm_lut_hue_table_len;
+	uint32_t *acm_lut_value_table;
+	uint32_t acm_lut_value_table_len;
+	uint32_t *acm_lut_sata_table;
+	uint32_t acm_lut_sata_table_len;
+	uint32_t *acm_lut_satr_table;
+	uint32_t acm_lut_satr_table_len;
+
+	uint32_t *cinema_acm_lut_hue_table;
+	uint32_t cinema_acm_lut_hue_table_len;
+	uint32_t *cinema_acm_lut_value_table;
+	uint32_t cinema_acm_lut_value_table_len;
+	uint32_t *cinema_acm_lut_sata_table;
+	uint32_t cinema_acm_lut_sata_table_len;
+	uint32_t *cinema_acm_lut_satr_table;
+	uint32_t cinema_acm_lut_satr_table_len;
+
+	uint32_t *acm_lut_satr0_table;
+	uint32_t acm_lut_satr0_table_len;
+	uint32_t *acm_lut_satr1_table;
+	uint32_t acm_lut_satr1_table_len;
+	uint32_t *acm_lut_satr2_table;
+	uint32_t acm_lut_satr2_table_len;
+	uint32_t *acm_lut_satr3_table;
+	uint32_t acm_lut_satr3_table_len;
+	uint32_t *acm_lut_satr4_table;
+	uint32_t acm_lut_satr4_table_len;
+	uint32_t *acm_lut_satr5_table;
+	uint32_t acm_lut_satr5_table_len;
+	uint32_t *acm_lut_satr6_table;
+	uint32_t acm_lut_satr6_table_len;
+	uint32_t *acm_lut_satr7_table;
+	uint32_t acm_lut_satr7_table_len;
+
+	uint32_t *cinema_acm_lut_satr0_table;
+	uint32_t *cinema_acm_lut_satr1_table;
+	uint32_t *cinema_acm_lut_satr2_table;
+	uint32_t *cinema_acm_lut_satr3_table;
+	uint32_t *cinema_acm_lut_satr4_table;
+	uint32_t *cinema_acm_lut_satr5_table;
+	uint32_t *cinema_acm_lut_satr6_table;
+	uint32_t *cinema_acm_lut_satr7_table;
+
+	uint32_t *gamma_lut_table_R;
+	uint32_t *gamma_lut_table_G;
+	uint32_t *gamma_lut_table_B;
+	uint32_t gamma_lut_table_len;
+	uint32_t *cinema_gamma_lut_table_R;
+	uint32_t *cinema_gamma_lut_table_G;
+	uint32_t *cinema_gamma_lut_table_B;
+	uint32_t cinema_gamma_lut_table_len;
+	uint32_t *igm_lut_table_R;
+	uint32_t *igm_lut_table_G;
+	uint32_t *igm_lut_table_B;
+	uint32_t igm_lut_table_len;
+	uint32_t *gmp_lut_table_low32bit;
+	uint32_t *gmp_lut_table_high4bit;
+	uint32_t gmp_lut_table_len;
+	uint32_t *xcc_table;
+	uint32_t xcc_table_len;
+
+	uint32_t *pgainlsc0;
+	uint32_t *pgainlsc1;
+	uint32_t pgainlsc_len;
+	uint32_t *hcoeff0y;
+	uint32_t *hcoeff1y;
+	uint32_t *hcoeff2y;
+	uint32_t *hcoeff3y;
+	uint32_t *hcoeff4y;
+	uint32_t *hcoeff5y;
+	uint32_t hcoeffy_len;
+	uint32_t *vcoeff0y;
+	uint32_t *vcoeff1y;
+	uint32_t *vcoeff2y;
+	uint32_t *vcoeff3y;
+	uint32_t *vcoeff4y;
+	uint32_t *vcoeff5y;
+	uint32_t vcoeffy_len;
+	uint32_t *hcoeff0uv;
+	uint32_t *hcoeff1uv;
+	uint32_t *hcoeff2uv;
+	uint32_t *hcoeff3uv;
+	uint32_t hcoeffuv_len;
+	uint32_t *vcoeff0uv;
+	uint32_t *vcoeff1uv;
+	uint32_t *vcoeff2uv;
+	uint32_t *vcoeff3uv;
+	uint32_t vcoeffuv_len;
+
+	struct spi_device *spi_dev;
+	struct ldi_panel_info ldi;
+	struct ldi_panel_info ldi_updt;
+	struct ldi_panel_info ldi_lfps;
+	struct mipi_panel_info mipi;
+	struct sbl_panel_info smart_bl;
+	struct dsc_panel_info vesa_dsc;
+	struct lcd_dirty_region_info dirty_region_info;
+
+	struct mipi_dsi_phy_ctrl dsi_phy_ctrl;
+
+	struct hiace_alg_parameter hiace_param;
+	struct ce_algorithm_parameter ce_alg_param;
+};
+
+struct hisi_fb_data_type;
+struct hisi_fb_panel_data {
+	struct hisi_panel_info *panel_info;
+
+	/* function entry chain */
+	int (*on) (struct platform_device *pdev);
+	int (*off) (struct platform_device *pdev);
+	int (*remove) (struct platform_device *pdev);
+	int (*set_backlight) (struct platform_device *pdev, uint32_t bl_level);
+	int (*vsync_ctrl) (struct platform_device *pdev, int enable);
+
+	struct platform_device *next;
+};
+
+/*******************************************************************************
+ ** FUNCTIONS PROTOTYPES
+ */
+#define MIPI_DPHY_NUM	(2)
+
+extern uint32_t g_dts_resouce_ready;
+extern mipi_ifbc_division_t g_mipi_ifbc_division[MIPI_DPHY_NUM][IFBC_TYPE_MAX];
+int resource_cmds_tx(struct platform_device *pdev,
+		     struct resource_desc *cmds, int cnt);
+int vcc_cmds_tx(struct platform_device *pdev, struct vcc_desc *cmds, int cnt);
+int pinctrl_cmds_tx(struct platform_device *pdev, struct pinctrl_cmd_desc *cmds,
+		    int cnt);
+int gpio_cmds_tx(struct gpio_desc *cmds, int cnt);
+extern struct spi_device *g_spi_dev;
+
+int panel_next_on(struct platform_device *pdev);
+int panel_next_off(struct platform_device *pdev);
+int panel_next_remove(struct platform_device *pdev);
+int panel_next_set_backlight(struct platform_device *pdev, uint32_t bl_level);
+int panel_next_vsync_ctrl(struct platform_device *pdev, int enable);
+
+bool is_ldi_panel(struct hisi_fb_data_type *hisifd);
+bool is_mipi_cmd_panel(struct hisi_fb_data_type *hisifd);
+bool is_mipi_cmd_panel_ext(struct hisi_panel_info *pinfo);
+bool is_mipi_video_panel(struct hisi_fb_data_type *hisifd);
+bool is_mipi_panel(struct hisi_fb_data_type *hisifd);
+bool is_dual_mipi_panel(struct hisi_fb_data_type *hisifd);
+bool is_dual_mipi_panel_ext(struct hisi_panel_info *pinfo);
+bool is_ifbc_panel(struct hisi_fb_data_type *hisifd);
+bool is_ifbc_vesa_panel(struct hisi_fb_data_type *hisifd);
+bool mipi_panel_check_reg(struct hisi_fb_data_type *hisifd,
+			  uint32_t *read_value);
+int mipi_ifbc_get_rect(struct hisi_fb_data_type *hisifd, struct dss_rect *rect);
+bool is_hisi_writeback_panel(struct hisi_fb_data_type *hisifd);
+void hisi_fb_device_set_status0(uint32_t status);
+int hisi_fb_device_set_status1(struct hisi_fb_data_type *hisifd);
+bool hisi_fb_device_probe_defer(uint32_t panel_type, uint32_t bl_type);
+#endif				/* HISI_FB_PANEL_H */
-- 
2.12.0-rc0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/8] fb: hisilicon: Add framebuffer driver for hi3660 SoC
@ 2017-02-07  2:35     ` cailiwei
  0 siblings, 0 replies; 15+ messages in thread
From: cailiwei @ 2017-02-07  2:35 UTC (permalink / raw)
  To: linux-fbdev, linux-kernel, b.zolnierkie, guodong.xu
  Cc: suzhuangluan, dengqingshan, xuhongtao8, zhengwanchun,
	shizongxuan, cailiwei

From: Levy-Cai <cailiwei@hisilicon.com>

Add framebuffer driver for hi3660 SoC, this driver include lcd
driver & Hdmi adv7533/adv7535 driver, support lcd display at
1080p@60 and hdmi display at 1080p@60.

Signed-off-by: cailiwei <cailiwei@hisilicon.com>
---
 drivers/video/fbdev/hisi/dss/hisi_fb_bl.c       | 323 +++++++++
 drivers/video/fbdev/hisi/dss/hisi_fb_buf_sync.c | 507 ++++++++++++++
 drivers/video/fbdev/hisi/dss/hisi_fb_def.h      | 125 ++++
 drivers/video/fbdev/hisi/dss/hisi_fb_isr.c      | 327 +++++++++
 drivers/video/fbdev/hisi/dss/hisi_fb_panel.c    | 835 +++++++++++++++++++++++
 drivers/video/fbdev/hisi/dss/hisi_fb_panel.h    | 839 ++++++++++++++++++++++++
 6 files changed, 2956 insertions(+)
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_fb_bl.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_fb_buf_sync.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_fb_def.h
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_fb_isr.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_fb_panel.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_fb_panel.h

diff --git a/drivers/video/fbdev/hisi/dss/hisi_fb_bl.c b/drivers/video/fbdev/hisi/dss/hisi_fb_bl.c
new file mode 100755
index 000000000000..ee4b8c7f4abb
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_fb_bl.c
@@ -0,0 +1,323 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_fb.h"
+#include <linux/leds.h>
+#define K3_DSS_SBL_WORKQUEUE	"k3_dss_sbl_workqueue"
+
+static int lcd_backlight_registered;
+static unsigned int is_recovery_mode;
+static int is_no_fastboot_bl_enable;
+
+#ifdef CONFIG_HISI_FB_BACKLIGHT_DELAY
+unsigned long backlight_duration = (3 * HZ / 60);
+#endif
+
+void hisifb_set_backlight(struct hisi_fb_data_type *hisifd, uint32_t bkl_lvl)
+{
+	struct hisi_fb_panel_data *pdata = NULL;
+	uint32_t temp = bkl_lvl;
+
+	BUG_ON(hisifd = NULL);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata = NULL);
+
+	if (!hisifd->panel_power_on || !hisifd->backlight.bl_updated) {
+		hisifd->bl_level = bkl_lvl;
+		return;
+	}
+
+	if (pdata->set_backlight) {
+		if (hisifd->backlight.bl_level_old = temp) {
+			hisifd->bl_level = bkl_lvl;
+			return;
+		}
+		if (hisifd->backlight.bl_level_old = 0) {
+			HISI_FB_INFO("backlight level = %d", bkl_lvl);
+		}
+		hisifd->bl_level = bkl_lvl;
+		if (hisifd->panel_info.bl_set_type & BL_SET_BY_MIPI) {
+			hisifb_set_vsync_activate_state(hisifd, true);
+			hisifb_activate_vsync(hisifd);
+		}
+		pdata->set_backlight(hisifd->pdev, bkl_lvl);
+		if (hisifd->panel_info.bl_set_type & BL_SET_BY_MIPI) {
+			hisifb_set_vsync_activate_state(hisifd, false);
+			hisifb_deactivate_vsync(hisifd);
+		}
+		hisifd->backlight.bl_level_old = temp;
+	}
+}
+
+#ifdef CONFIG_HISI_FB_BACKLIGHT_DELAY
+static void hisifb_bl_workqueue_handler(struct work_struct *work)
+#else
+static void hisifb_bl_workqueue_handler(struct hisi_fb_data_type *hisifd)
+#endif
+{
+	struct hisi_fb_panel_data *pdata = NULL;
+#ifdef CONFIG_HISI_FB_BACKLIGHT_DELAY
+	struct hisifb_backlight *pbacklight = NULL;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	pbacklight +	    container_of(to_delayed_work(work), struct hisifb_backlight,
+			 bl_worker);
+	BUG_ON(pbacklight = NULL);
+
+	hisifd = container_of(pbacklight, struct hisi_fb_data_type, backlight);
+#endif
+
+	BUG_ON(hisifd = NULL);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata = NULL);
+
+	if (!hisifd->backlight.bl_updated) {
+		down(&hisifd->blank_sem);
+
+		if (hisifd->backlight.frame_updated = 0) {
+			up(&hisifd->blank_sem);
+			return;
+		}
+
+		hisifd->backlight.frame_updated = 0;
+		hisifd->backlight.bl_updated = 1;
+		if (is_recovery_mode) {
+			hisifd->bl_level = hisifd->panel_info.bl_default;
+		} else {
+			if (!is_no_fastboot_bl_enable) {
+				is_no_fastboot_bl_enable = 1;
+				hisifd->bl_level +				    hisifd->panel_info.bl_default;
+			}
+		}
+
+		hisifb_set_backlight(hisifd, hisifd->bl_level);
+		up(&hisifd->blank_sem);
+	}
+}
+
+void hisifb_backlight_update(struct hisi_fb_data_type *hisifd)
+{
+	struct hisi_fb_panel_data *pdata = NULL;
+
+	BUG_ON(hisifd = NULL);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata = NULL);
+
+	if (!hisifd->backlight.bl_updated) {
+		hisifd->backlight.frame_updated = 1;
+#ifdef CONFIG_HISI_FB_BACKLIGHT_DELAY
+		schedule_delayed_work(&hisifd->backlight.bl_worker,
+				      backlight_duration);
+#else
+		hisifb_bl_workqueue_handler(hisifd);
+#endif
+	}
+}
+
+void hisifb_backlight_cancel(struct hisi_fb_data_type *hisifd)
+{
+	struct hisi_fb_panel_data *pdata = NULL;
+
+	BUG_ON(hisifd = NULL);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata = NULL);
+
+#ifdef CONFIG_HISI_FB_BACKLIGHT_DELAY
+	cancel_delayed_work(&hisifd->backlight.bl_worker);
+#endif
+	hisifd->backlight.bl_updated = 0;
+	hisifd->backlight.bl_level_old = 0;
+	hisifd->backlight.frame_updated = 0;
+
+	if (pdata->set_backlight) {
+		hisifd->bl_level = 0;
+		if (hisifd->panel_info.bl_set_type & BL_SET_BY_MIPI)
+			hisifb_activate_vsync(hisifd);
+		pdata->set_backlight(hisifd->pdev, hisifd->bl_level);
+		if (hisifd->panel_info.bl_set_type & BL_SET_BY_MIPI)
+			hisifb_deactivate_vsync(hisifd);
+	}
+}
+
+#ifdef CONFIG_FB_BACKLIGHT
+static int hisi_fb_bl_get_brightness(struct backlight_device *pbd)
+{
+	if (NULL = pbd) {
+		HISI_FB_ERR("NULL pointer!\n");
+		return 0;
+	}
+	return pbd->props.brightness;
+}
+
+static int hisi_fb_bl_update_status(struct backlight_device *pbd)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	uint32_t bl_lvl = 0;
+
+	if (NULL = pbd) {
+		HISI_FB_ERR("NULL pointer!\n");
+		return 0;
+	}
+
+	hisifd = bl_get_data(pbd);
+	if (NULL = hisifd) {
+		HISI_FB_ERR("NULL pointer!\n");
+		return 0;
+	}
+
+	bl_lvl = pbd->props.brightness;
+	bl_lvl = hisifd->fbi->bl_curve[bl_lvl];
+
+	down(&hisifd->blank_sem);
+	hisifb_set_backlight(hisifd, bl_lvl);
+	up(&hisifd->blank_sem);
+
+	return 0;
+}
+
+static struct backlight_ops hisi_fb_bl_ops = {
+	.get_brightness = hisi_fb_bl_get_brightness,
+	.update_status = hisi_fb_bl_update_status,
+};
+#else
+static void hisi_fb_set_bl_brightness(struct led_classdev *led_cdev,
+				      enum led_brightness value)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	int bl_lvl = 0;
+
+	if (NULL = led_cdev) {
+		HISI_FB_ERR("NULL pointer!\n");
+		return;
+	}
+
+	hisifd = dev_get_drvdata(led_cdev->dev->parent);
+	if (NULL = hisifd) {
+		HISI_FB_ERR("NULL pointer!\n");
+		return;
+	}
+
+	if (value < 0)
+		value = 0;
+
+	if (value > hisifd->panel_info.bl_max)
+		value = hisifd->panel_info.bl_max;
+
+	/* This maps android backlight level 0 to 255 into
+	   driver backlight level 0 to bl_max with rounding */
+	bl_lvl +	    (2 * value * hisifd->panel_info.bl_max + hisifd->panel_info.bl_max)
+	    / (2 * hisifd->panel_info.bl_max);
+	if (!bl_lvl && value)
+		bl_lvl = 1;
+	hisifb_set_backlight(hisifd, bl_lvl);
+}
+
+static struct led_classdev backlight_led = {
+	.name = DEV_NAME_LCD_BKL,
+	.brightness_set = hisi_fb_set_bl_brightness,
+};
+#endif
+
+void hisifb_backlight_register(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+#ifdef CONFIG_FB_BACKLIGHT
+	struct backlight_device *pbd = NULL;
+	struct fb_info *fbi = NULL;
+	char name[16] = { 0 };
+	struct backlight_properties props;
+#endif
+
+	BUG_ON(pdev = NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd = NULL);
+
+	hisifd->backlight.bl_updated = 0;
+	hisifd->backlight.frame_updated = 0;
+	hisifd->backlight.bl_level_old = 0;
+	sema_init(&hisifd->backlight.bl_sem, 1);
+#ifdef CONFIG_HISI_FB_BACKLIGHT_DELAY
+	INIT_DELAYED_WORK(&hisifd->backlight.bl_worker,
+			  hisifb_bl_workqueue_handler);
+#endif
+
+	if (lcd_backlight_registered) return;
+
+#ifdef CONFIG_FB_BACKLIGHT
+	fbi = hisifd->fbi;
+
+	snprintf(name, sizeof(name), "hisifb%d_bl", hisifd->index);
+	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+	props.brightness = FB_BACKLIGHT_LEVELS - 1;
+	pbd = backlight_device_register(name, fbi->dev, hisifd,
+					&hisi_fb_bl_ops, &props);
+	if (IS_ERR(pbd)) {
+		fbi->bl_dev = NULL;
+		HISI_FB_ERR("backlight_device_register failed!\n");
+	}
+
+	fbi->bl_dev = pbd;
+	fb_bl_default_curve(fbi, 0,
+			    hisifd->panel_info.bl_min,
+			    hisifd->panel_info.bl_max);
+#else
+	backlight_led.brightness = hisifd->panel_info.bl_default;
+	backlight_led.max_brightness = hisifd->panel_info.bl_max;
+	/* android supports only one lcd-backlight/lcd for now */
+#ifdef CONFIG_LEDS_CLASS
+	if (led_classdev_register(&pdev->dev, &backlight_led)) {
+		HISI_FB_ERR("led_classdev_register failed!\n");
+		return;
+	}
+#endif
+#endif
+
+	if (HISI_DSS_SUPPORT_DPP_MODULE_BIT(DPP_MODULE_SBL)) {
+		hisifd->backlight.sbl_queue +		    create_singlethread_workqueue(K3_DSS_SBL_WORKQUEUE);
+		if (!hisifd->backlight.sbl_queue) {
+			HISI_FB_ERR("failed to create sbl_queue!\n");
+			return;
+		}
+	}
+
+	lcd_backlight_registered = 1;
+}
+
+void hisifb_backlight_unregister(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev = NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd = NULL);
+
+	if (lcd_backlight_registered) {
+		lcd_backlight_registered = 0;
+#ifdef CONFIG_FB_BACKLIGHT
+		/* remove /sys/class/backlight */
+		backlight_device_unregister(hisifd->fbi->bl_dev);
+#else
+#ifdef CONFIG_LEDS_CLASS
+		led_classdev_unregister(&backlight_led);
+#endif
+#endif
+		if (hisifd->backlight.sbl_queue) {
+			destroy_workqueue(hisifd->backlight.sbl_queue);
+			hisifd->backlight.sbl_queue = NULL;
+		}
+	}
+}
diff --git a/drivers/video/fbdev/hisi/dss/hisi_fb_buf_sync.c b/drivers/video/fbdev/hisi/dss/hisi_fb_buf_sync.c
new file mode 100755
index 000000000000..e36a39ad4d31
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_fb_buf_sync.c
@@ -0,0 +1,507 @@
+/* Copyright (c) 2008-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_fb.h"
+
+#define HISI_DSS_LAYERBUF_FREE	"hisi-dss-layerbuf-free"
+
+int hisifb_layerbuf_lock(struct hisi_fb_data_type *hisifd,
+			 dss_overlay_t *pov_req, struct list_head *plock_list)
+{
+	dss_overlay_block_t *pov_h_block_infos = NULL;
+	dss_overlay_block_t *pov_h_block = NULL;
+	dss_layer_t *layer = NULL;
+	int i = 0;
+	int m = 0;
+	struct hisifb_layerbuf *node = NULL;
+	struct ion_handle *ionhnd = NULL;
+	struct iommu_map_format iommu_format;
+	bool add_tail = false;
+
+	BUG_ON(hisifd = NULL);
+	BUG_ON(pov_req = NULL);
+	BUG_ON(plock_list = NULL);
+
+	pov_h_block_infos +	    (dss_overlay_block_t *) (pov_req->ov_block_infos_ptr);
+	for (m = 0; m < pov_req->ov_block_nums; m++) {
+		pov_h_block = &(pov_h_block_infos[m]);
+
+		for (i = 0; i < pov_h_block->layer_nums; i++) {
+			layer = &(pov_h_block->layer_infos[i]);
+			add_tail = false;
+			ionhnd = NULL;
+
+			if (layer->dst_rect.y < pov_h_block->ov_block_rect.y)
+				continue;
+
+			if (layer->img.shared_fd < 0)
+				continue;
+
+			if ((layer->img.phy_addr = 0) &&
+			    (layer->img.vir_addr = 0) &&
+			    (layer->img.afbc_payload_addr = 0)) {
+				HISI_FB_ERR
+				    ("fb%d, layer_idx%d, chn_idx%d, no buffer!\n",
+				     hisifd->index, layer->layer_idx,
+				     layer->chn_idx);
+				continue;
+			}
+
+			if (layer->img.shared_fd >= 0) {
+				ionhnd +				    ion_import_dma_buf(hisifd->ion_client,
+						       layer->img.shared_fd);
+				if (IS_ERR(ionhnd)) {
+					ionhnd = NULL;
+					HISI_FB_ERR
+					    ("fb%d, layer_idx%d, failed to ion_import_dma_buf, "
+					     "ionclient %p, share_fd %d!\n",
+					     hisifd->index, i,
+					     hisifd->ion_client,
+					     layer->img.shared_fd);
+				} else {
+					if (layer->img.mmu_enable = 1) {
+						memset(&iommu_format, 0,
+						       sizeof(struct iommu_map_format));
+								ion_map_iommu(hisifd->ion_client,ionhnd,
+							      &iommu_format);
+					}
+					add_tail = true;
+				}
+			}
+
+			if (add_tail) {
+				node +				    kzalloc(sizeof(struct hisifb_layerbuf),
+					    GFP_KERNEL);
+				if (node = NULL) {
+					HISI_FB_ERR
+					    ("fb%d, layer_idx%d, failed to kzalloc!\n",
+					     hisifd->index, layer->layer_idx);
+
+					if (ionhnd) {
+						ion_free(hisifd->ion_client,
+							 ionhnd);
+						ionhnd = NULL;
+					}
+					continue;
+				}
+
+				node->shared_fd = layer->img.shared_fd;
+				node->frame_no = pov_req->frame_no;
+				node->ion_handle = ionhnd;
+				node->has_map_iommu = (ionhnd
+							&& (layer->img.mmu_enable = 1)) ? true : false;
+				node->timeline = 0;
+
+				node->mmbuf.addr = layer->img.mmbuf_base;
+				node->mmbuf.size = layer->img.mmbuf_size;
+
+				node->vir_addr = layer->img.vir_addr;
+				node->chn_idx = layer->chn_idx;
+
+				list_add_tail(&node->list_node, plock_list);
+				if (g_debug_layerbuf_sync) {
+					HISI_FB_INFO
+					    ("fb%d, frame_no=%d, layer_idx(%d), "
+					     "shared_fd=%d, ion_handle=%p, "
+					     "has_map_iommu=%d, timeline=%d, mmbuf(0x%x, %d).\n",
+					     hisifd->index, node->frame_no, i,
+					     node->shared_fd, node->ion_handle,
+					     node->has_map_iommu,
+					     node->timeline, node->mmbuf.addr,
+					     node->mmbuf.size);
+				}
+			}
+		}
+	}
+
+	return 0;
+}
+
+void hisifb_layerbuf_flush(struct hisi_fb_data_type *hisifd,
+			   struct list_head *plock_list)
+{
+	struct hisifb_layerbuf *node, *_node_;
+	unsigned long flags = 0;
+
+	BUG_ON(hisifd = NULL);
+	BUG_ON(hisifd->ion_client = NULL);
+	BUG_ON(plock_list = NULL);
+
+	spin_lock_irqsave(&(hisifd->buf_sync_ctrl.layerbuf_spinlock), flags);
+	hisifd->buf_sync_ctrl.layerbuf_flushed = true;
+	list_for_each_entry_safe(node, _node_, plock_list, list_node) {
+		list_del(&node->list_node);
+		list_add_tail(&node->list_node,
+			      &(hisifd->buf_sync_ctrl.layerbuf_list));
+	}
+	spin_unlock_irqrestore(&(hisifd->buf_sync_ctrl.layerbuf_spinlock),
+			       flags);
+}
+
+void hisifb_layerbuf_unlock(struct hisi_fb_data_type *hisifd,
+			    struct list_head *pfree_list)
+{
+	struct hisifb_layerbuf *node, *_node_;
+
+	BUG_ON(hisifd = NULL);
+	BUG_ON(hisifd->ion_client = NULL);
+	BUG_ON(hisifd->mmbuf_gen_pool = NULL);
+	BUG_ON(pfree_list = NULL);
+
+	list_for_each_entry_safe(node, _node_, pfree_list, list_node) {
+		list_del(&node->list_node);
+
+		if (g_debug_layerbuf_sync) {
+			HISI_FB_INFO
+			    ("fb%d, frame_no=%d, share_fd=%d, "
+			     "ion_handle=%p, has_map_iommu=%d, "
+			     "timeline=%d, mmbuf(0x%x, %d). "
+			     "vir_addr = 0x%llx, chn_idx = %d\n",
+			     hisifd->index, node->frame_no, node->shared_fd,
+			     node->ion_handle, node->has_map_iommu,
+			     node->timeline, node->mmbuf.addr, node->mmbuf.size,
+			     node->vir_addr, node->chn_idx);
+		}
+
+		node->timeline = 0;
+		if (node->ion_handle) {
+			if (node->has_map_iommu) {
+				ion_unmap_iommu(hisifd->ion_client,
+						node->ion_handle);
+			}
+			ion_free(hisifd->ion_client, node->ion_handle);
+		}
+		kfree(node);
+	}
+}
+
+void hisifb_layerbuf_lock_exception(struct hisi_fb_data_type *hisifd,
+				    struct list_head *plock_list)
+{
+	unsigned long flags = 0;
+
+	BUG_ON(hisifd = NULL);
+	BUG_ON(plock_list = NULL);
+
+	spin_lock_irqsave(&(hisifd->buf_sync_ctrl.layerbuf_spinlock), flags);
+	hisifd->buf_sync_ctrl.layerbuf_flushed = false;
+	spin_unlock_irqrestore(&(hisifd->buf_sync_ctrl.layerbuf_spinlock), flags);
+
+	hisifb_layerbuf_unlock(hisifd, plock_list);
+}
+
+static void hisifb_layerbuf_unlock_work(struct work_struct *work)
+{
+	struct hisifb_buf_sync *pbuf_sync = NULL;
+	struct hisi_fb_data_type *hisifd = NULL;
+	unsigned long flags;
+	struct hisifb_layerbuf *node, *_node_;
+	struct list_head free_list;
+
+	pbuf_sync +	    container_of(work, struct hisifb_buf_sync, free_layerbuf_work);
+	BUG_ON(pbuf_sync = NULL);
+	hisifd +	    container_of(pbuf_sync, struct hisi_fb_data_type, buf_sync_ctrl);
+	BUG_ON(hisifd = NULL);
+	BUG_ON(hisifd->ion_client = NULL);
+
+	INIT_LIST_HEAD(&free_list);
+	spin_lock_irqsave(&pbuf_sync->layerbuf_spinlock, flags);
+	list_for_each_entry_safe(node, _node_, &pbuf_sync->layerbuf_list,
+				 list_node) {
+		if (node->timeline >= 2) {
+			list_del(&node->list_node);
+			list_add_tail(&node->list_node, &free_list);
+		}
+	}
+	spin_unlock_irqrestore(&pbuf_sync->layerbuf_spinlock, flags);
+
+	hisifb_layerbuf_unlock(hisifd, &free_list);
+}
+
+#ifdef CONFIG_BUF_SYNC_USED
+#define BUF_SYNC_TIMEOUT_MSEC	(10 * MSEC_PER_SEC)
+#define BUF_SYNC_FENCE_NAME	"hisi-dss-fence"
+#define BUF_SYNC_TIMELINE_NAME	"hisi-dss-timeline"
+int hisifb_buf_sync_create_fence(struct hisi_fb_data_type *hisifd,
+				 unsigned value)
+{
+	int fd = -1;
+	struct sync_fence *fence = NULL;
+	struct sync_pt *pt = NULL;
+
+	BUG_ON(hisifd = NULL);
+	fd = get_unused_fd_flags(0);
+	if (fd < 0) {
+		HISI_FB_ERR("get_unused_fd failed!\n");
+		return fd;
+	}
+
+	pt = sw_sync_pt_create(hisifd->buf_sync_ctrl.timeline, value);
+	if (pt = NULL) {
+		return -ENOMEM;
+	}
+
+	fence = sync_fence_create(BUF_SYNC_FENCE_NAME, pt);
+	if (fence = NULL) {
+		sync_pt_free(pt);
+		return -ENOMEM;
+	}
+
+	sync_fence_install(fence, fd);
+
+	return fd;
+}
+
+int hisifb_buf_sync_wait(int fence_fd)
+{
+	int ret = 0;
+	struct sync_fence *fence = NULL;
+
+	fence = sync_fence_fdget(fence_fd);
+	if (fence = NULL) {
+		HISI_FB_ERR("fence_fd=%d, sync_fence_fdget failed!\n",
+			    fence_fd);
+		return -EINVAL;
+	}
+
+	ret = sync_fence_wait(fence, BUF_SYNC_TIMEOUT_MSEC);
+	if (ret < 0) {
+		HISI_FB_ERR("Waiting on fence failed, fence_fd: %d, ret: %d.\n",
+			    fence_fd, ret);
+	}
+	sync_fence_put(fence);
+
+	return ret;
+}
+
+int hisifb_buf_sync_handle(struct hisi_fb_data_type *hisifd,
+			   dss_overlay_t *pov_req)
+{
+	dss_overlay_block_t *pov_h_block_infos = NULL;
+	dss_overlay_block_t *pov_h_block = NULL;
+	dss_layer_t *layer = NULL;
+	int i = 0;
+	int m = 0;
+
+	BUG_ON(hisifd = NULL);
+	BUG_ON(pov_req = NULL);
+
+	pov_h_block_infos +	    (dss_overlay_block_t *) (pov_req->ov_block_infos_ptr);
+	for (m = 0; m < pov_req->ov_block_nums; m++) {
+		pov_h_block = &(pov_h_block_infos[m]);
+
+		for (i = 0; i < pov_h_block->layer_nums; i++) {
+			layer = &(pov_h_block->layer_infos[i]);
+
+			if (layer->dst_rect.y < pov_h_block->ov_block_rect.y)
+				continue;
+
+			if (layer->acquire_fence >= 0) {
+				hisifb_buf_sync_wait(layer->acquire_fence);
+			}
+		}
+	}
+
+	return 0;
+}
+
+void hisifb_buf_sync_signal(struct hisi_fb_data_type *hisifd)
+{
+	struct hisifb_layerbuf *node = NULL;
+	struct hisifb_layerbuf *_node_ = NULL;
+
+	BUG_ON(hisifd = NULL);
+
+	spin_lock(&hisifd->buf_sync_ctrl.refresh_lock);
+	if (hisifd->buf_sync_ctrl.refresh) {
+		sw_sync_timeline_inc(hisifd->buf_sync_ctrl.timeline,
+				     hisifd->buf_sync_ctrl.refresh);
+		hisifd->buf_sync_ctrl.refresh = 0;
+	}
+	spin_unlock(&hisifd->buf_sync_ctrl.refresh_lock);
+
+	spin_lock(&(hisifd->buf_sync_ctrl.layerbuf_spinlock));
+	list_for_each_entry_safe(node, _node_,
+				 &(hisifd->buf_sync_ctrl.layerbuf_list),
+				 list_node) {
+		if (hisifd->buf_sync_ctrl.layerbuf_flushed) {
+			node->timeline++;
+		}
+	}
+	hisifd->buf_sync_ctrl.layerbuf_flushed = false;
+	spin_unlock(&(hisifd->buf_sync_ctrl.layerbuf_spinlock));
+
+	queue_work(hisifd->buf_sync_ctrl.free_layerbuf_queue,
+		   &(hisifd->buf_sync_ctrl.free_layerbuf_work));
+}
+
+void hisifb_buf_sync_suspend(struct hisi_fb_data_type *hisifd)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hisifd->buf_sync_ctrl.refresh_lock, flags);
+	sw_sync_timeline_inc(hisifd->buf_sync_ctrl.timeline,
+			     hisifd->buf_sync_ctrl.refresh + 1);
+	hisifd->buf_sync_ctrl.refresh = 0;
+	hisifd->buf_sync_ctrl.timeline_max++;
+	spin_unlock_irqrestore(&hisifd->buf_sync_ctrl.refresh_lock, flags);
+}
+
+void hisifb_buf_sync_register(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev = NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd = NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	spin_lock_init(&hisifd->buf_sync_ctrl.refresh_lock);
+	hisifd->buf_sync_ctrl.refresh = 0;
+	hisifd->buf_sync_ctrl.timeline_max = 1;
+	hisifd->buf_sync_ctrl.timeline +	    sw_sync_timeline_create(BUF_SYNC_TIMELINE_NAME);
+	if (hisifd->buf_sync_ctrl.timeline = NULL) {
+		HISI_FB_ERR("cannot create time line!");
+		return;		/* -ENOMEM */
+	}
+
+	spin_lock_init(&(hisifd->buf_sync_ctrl.layerbuf_spinlock));
+	INIT_LIST_HEAD(&(hisifd->buf_sync_ctrl.layerbuf_list));
+	hisifd->buf_sync_ctrl.layerbuf_flushed = false;
+
+	INIT_WORK(&(hisifd->buf_sync_ctrl.free_layerbuf_work),
+		  hisifb_layerbuf_unlock_work);
+	hisifd->buf_sync_ctrl.free_layerbuf_queue +	    create_singlethread_workqueue(HISI_DSS_LAYERBUF_FREE);
+	if (!hisifd->buf_sync_ctrl.free_layerbuf_queue) {
+		HISI_FB_ERR("failed to create free_layerbuf_queue!\n");
+		return;
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+}
+
+void hisifb_buf_sync_unregister(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev = NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd = NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	if (hisifd->buf_sync_ctrl.timeline) {
+		sync_timeline_destroy((struct sync_timeline *)
+					hisifd->buf_sync_ctrl.timeline);
+		hisifd->buf_sync_ctrl.timeline = NULL;
+	}
+
+	if (hisifd->buf_sync_ctrl.free_layerbuf_queue) {
+		destroy_workqueue(hisifd->buf_sync_ctrl.free_layerbuf_queue);
+		hisifd->buf_sync_ctrl.free_layerbuf_queue = NULL;
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+}
+#else
+int hisifb_buf_sync_wait(int fence_fd)
+{
+	return 0;
+}
+
+int hisifb_buf_sync_handle(struct hisi_fb_data_type *hisifd,
+			   dss_overlay_t *pov_req)
+{
+	return 0;
+}
+
+void hisifb_buf_sync_signal(struct hisi_fb_data_type *hisifd)
+{
+	struct hisifb_layerbuf *node = NULL;
+	struct hisifb_layerbuf *_node_ = NULL;
+
+	BUG_ON(hisifd = NULL);
+
+
+
+	spin_lock(&(hisifd->buf_sync_ctrl.layerbuf_spinlock));
+	list_for_each_entry_safe(node, _node_,
+				 &(hisifd->buf_sync_ctrl.layerbuf_list),
+				 list_node) {
+		if (hisifd->buf_sync_ctrl.layerbuf_flushed) {
+			node->timeline++;
+		}
+	}
+	hisifd->buf_sync_ctrl.layerbuf_flushed = false;
+	spin_unlock(&(hisifd->buf_sync_ctrl.layerbuf_spinlock));
+
+	queue_work(hisifd->buf_sync_ctrl.free_layerbuf_queue,
+		   &(hisifd->buf_sync_ctrl.free_layerbuf_work));
+}
+
+void hisifb_buf_sync_suspend(struct hisi_fb_data_type *hisifd)
+{
+}
+
+void hisifb_buf_sync_register(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev = NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd = NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+	spin_lock_init(&(hisifd->buf_sync_ctrl.layerbuf_spinlock));
+	INIT_LIST_HEAD(&(hisifd->buf_sync_ctrl.layerbuf_list));
+	hisifd->buf_sync_ctrl.layerbuf_flushed = false;
+
+	INIT_WORK(&(hisifd->buf_sync_ctrl.free_layerbuf_work),
+		  hisifb_layerbuf_unlock_work);
+	hisifd->buf_sync_ctrl.free_layerbuf_queue +	    create_singlethread_workqueue(HISI_DSS_LAYERBUF_FREE);
+	if (!hisifd->buf_sync_ctrl.free_layerbuf_queue) {
+		HISI_FB_ERR("failed to create free_layerbuf_queue!\n");
+		return;
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+}
+
+void hisifb_buf_sync_unregister(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	BUG_ON(pdev = NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd = NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	if (hisifd->buf_sync_ctrl.free_layerbuf_queue) {
+		destroy_workqueue(hisifd->buf_sync_ctrl.free_layerbuf_queue);
+		hisifd->buf_sync_ctrl.free_layerbuf_queue = NULL;
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+}
+#endif
diff --git a/drivers/video/fbdev/hisi/dss/hisi_fb_def.h b/drivers/video/fbdev/hisi/dss/hisi_fb_def.h
new file mode 100755
index 000000000000..3496be2e1838
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_fb_def.h
@@ -0,0 +1,125 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+#ifndef HISI_FB_DEF_H
+#define HISI_FB_DEF_H
+
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <asm/bug.h>
+
+#ifndef MAX
+#define MAX(x, y) (((x) > (y)) ? (x) : (y))
+#endif
+
+#ifndef MIN
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+#endif
+
+/* align */
+#ifndef ALIGN_DOWN
+#define ALIGN_DOWN(val, al)  ((val) & ~((al)-1))
+#endif
+#ifndef ALIGN_UP
+#define ALIGN_UP(val, al)    (((val) + ((al)-1)) & ~((al)-1))
+#endif
+
+#ifndef BIT
+#define BIT(x)  (1<<(x))
+#endif
+
+#ifndef IS_EVEN
+#define IS_EVEN(x)  ((x) % 2 = 0)
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define KHZ	(1000)
+#define MHZ	(1000 * 1000)
+
+enum {
+	WAIT_TYPE_US = 0,
+	WAIT_TYPE_MS,
+};
+
+/*--------------------------------------------------------------------------*/
+extern uint32_t hisi_fb_msg_level;
+
+/*
+ * Message printing priorities:
+ * LEVEL 0 KERN_EMERG (highest priority)
+ * LEVEL 1 KERN_ALERT
+ * LEVEL 2 KERN_CRIT
+ * LEVEL 3 KERN_ERR
+ * LEVEL 4 KERN_WARNING
+ * LEVEL 5 KERN_NOTICE
+ * LEVEL 6 KERN_INFO
+ * LEVEL 7 KERN_DEBUG (Lowest priority)
+ */
+#define HISI_FB_EMERG(msg, ...)    \
+	do { if (hisi_fb_msg_level > 0)  \
+		printk(KERN_EMERG "[hisifb]%s: "msg, __func__, ## __VA_ARGS__); } while (0)
+#define HISI_FB_ALERT(msg, ...)    \
+	do { if (hisi_fb_msg_level > 1)  \
+		printk(KERN_ALERT "[hisifb]%s: "msg, __func__, ## __VA_ARGS__); } while (0)
+#define HISI_FB_CRIT(msg, ...)    \
+	do { if (hisi_fb_msg_level > 2)  \
+		printk(KERN_CRIT "[hisifb]%s: "msg, __func__, ## __VA_ARGS__); } while (0)
+#define HISI_FB_ERR(msg, ...)    \
+	do { if (hisi_fb_msg_level > 3)  \
+		printk(KERN_ERR "[hisifb]%s: "msg, __func__, ## __VA_ARGS__); } while (0)
+#define HISI_FB_WARNING(msg, ...)    \
+	do { if (hisi_fb_msg_level > 4)  \
+		printk(KERN_WARNING "[hisifb]%s: "msg, __func__, ## __VA_ARGS__); } while (0)
+#define HISI_FB_NOTICE(msg, ...)    \
+	do { if (hisi_fb_msg_level > 5)  \
+		printk(KERN_NOTICE "[hisifb]%s: "msg, __func__, ## __VA_ARGS__); } while (0)
+#define HISI_FB_INFO(msg, ...)    \
+	do { if (hisi_fb_msg_level > 6)  \
+		printk(KERN_INFO "[hisifb]%s: "msg, __func__, ## __VA_ARGS__); } while (0)
+#define HISI_FB_DEBUG(msg, ...)    \
+	do { if (hisi_fb_msg_level > 7)  \
+		printk(KERN_INFO "[hisifb]%s: "msg, __func__, ## __VA_ARGS__); } while (0)
+
+#define assert(expr) \
+	if(!(expr)) { \
+		printk(KERN_ERR "[hisifb]: assertion failed! %s,%s,%s,line=%d\n",\
+		#expr, __FILE__, __func__, __LINE__); \
+	}
+
+#define HISI_FB_ASSERT(x)   assert(x)
+
+#define outp32(addr, val) writel(val, addr)
+#define outp16(addr, val) writew(val, addr)
+#define outp8(addr, val) writeb(val, addr)
+#define outp(addr, val) outp32(addr, val)
+
+#define inp32(addr) readl(addr)
+#define inp16(addr) readw(addr)
+#define inp8(addr) readb(addr)
+#define inp(addr) inp32(addr)
+
+#define inpw(port) readw(port)
+#define outpw(port, val) writew(val, port)
+#define inpdw(port) readl(port)
+#define outpdw(port, val) writel(val, port)
+
+#endif
diff --git a/drivers/video/fbdev/hisi/dss/hisi_fb_isr.c b/drivers/video/fbdev/hisi/dss/hisi_fb_isr.c
new file mode 100755
index 000000000000..ca361f8028b9
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_fb_isr.c
@@ -0,0 +1,327 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_fb.h"
+#include "hisi_overlay_utils.h"
+
+/*******************************************************************************
+ ** handle isr
+ */
+irqreturn_t dss_pdp_isr(int irq, void *ptr)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	uint32_t isr_s1 = 0;
+	uint32_t isr_s2 = 0;
+	uint32_t isr_s2_dpp = 0;
+	uint32_t isr_s2_smmu = 0;
+	uint32_t mask = 0;
+	uint32_t isr_te_vsync = 0;
+	uint32_t i = 0;
+	uint32_t temp = 0;
+	struct timeval tv;
+	dss_module_reg_t *dss_module = NULL;
+
+	hisifd = (struct hisi_fb_data_type *)ptr;
+	BUG_ON(hisifd = NULL);
+	dss_module = &(hisifd->dss_module);
+
+	isr_s1 = inp32(hisifd->dss_base + GLB_CPU_PDP_INTS);
+	isr_s2 = inp32(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS);
+	isr_s2_dpp = inp32(hisifd->dss_base + DSS_DPP_OFFSET + DPP_INTS);
+	isr_s2_smmu +	    inp32(hisifd->dss_base + DSS_SMMU_OFFSET + SMMU_INTSTAT_NS);
+
+	outp32(hisifd->dss_base + DSS_SMMU_OFFSET + SMMU_INTCLR_NS,
+	       isr_s2_smmu);
+	outp32(hisifd->dss_base + DSS_DPP_OFFSET + DPP_INTS, isr_s2_dpp);
+	outp32(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS, isr_s2);
+	outp32(hisifd->dss_base + GLB_CPU_PDP_INTS, isr_s1);
+
+	isr_s1 &= ~(inp32(hisifd->dss_base + GLB_CPU_PDP_INT_MSK));
+	isr_s2 &+	    ~(inp32(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK));
+	isr_s2_dpp &= ~(inp32(hisifd->dss_base + DSS_DPP_OFFSET + DPP_INT_MSK));
+
+	if (is_mipi_cmd_panel(hisifd)) {
+		isr_te_vsync = BIT_LCD_TE0_PIN;
+	} else {
+		isr_te_vsync = BIT_VSYNC;
+	}
+
+	if (isr_s2 & BIT_VACTIVE0_END) {
+		hisifd->vactive0_end_flag = 1;
+		if (g_err_status & DSS_PDP_LDI_UNDERFLOW) {
+			temp +			    inp32(hisifd->dss_base + DSS_DPP_OFFSET +
+				  DPP_DBG_CNT);
+			HISI_FB_INFO
+			    ("fb%d, BIT_VACTIVE0_END: frame_no=%d, dpp_dbg =0x%x\n",
+			     hisifd->index, hisifd->ov_req.frame_no, temp);
+			g_err_status &= ~DSS_PDP_LDI_UNDERFLOW;
+		}
+	}
+
+	if (isr_s2 & BIT_VACTIVE0_START) {
+		if (hisifd->ov_vactive0_start_isr_handler) {
+			hisifd->ov_vactive0_start_isr_handler(hisifd);
+		}
+
+		if (g_err_status & DSS_PDP_LDI_UNDERFLOW) {
+			temp +			    inp32(hisifd->dss_base + DSS_DPP_OFFSET +
+				  DPP_DBG_CNT);
+			HISI_FB_INFO
+			    ("fb%d, BIT_VACTIVE0_START: frame_no=%d, dpp_dbg=0x%x\n",
+			     hisifd->index, hisifd->ov_req.frame_no, temp);
+		}
+	}
+
+	if (isr_s2 & isr_te_vsync) {
+		if (hisifd->vsync_isr_handler) {
+			hisifd->vsync_isr_handler(hisifd);
+		}
+
+		if (hisifd->buf_sync_signal) {
+			hisifd->buf_sync_signal(hisifd);
+		}
+
+		if (g_err_status &
+		    (DSS_PDP_LDI_UNDERFLOW | DSS_PDP_SMMU_ERR |
+		     DSS_SDP_SMMU_ERR)) {
+			temp +			    inp32(hisifd->dss_base + DSS_DPP_OFFSET +
+				  DPP_DBG_CNT);
+			HISI_FB_INFO
+			    ("isr_te_vsync:frame_no = %d,dpp_dbg = 0x%x\n",
+			     hisifd->ov_req.frame_no, temp);
+		}
+
+		if (g_debug_ldi_underflow) {
+			hisifb_get_timestamp(&tv);
+			HISI_FB_INFO
+			    ("isr_te_vsync:frame_no = %d,isr_s2 = 0x%x\n",
+			     hisifd->ov_req.frame_no, isr_s2);
+		}
+	}
+
+	if (isr_s2 & BIT_LDI_UNFLOW) {
+		mask = inp32(hisifd->dss_base + DSS_LDI0_OFFSET +
+			  LDI_CPU_ITF_INT_MSK);
+		mask |= BIT_LDI_UNFLOW;
+		outp32(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK, mask);
+
+		if (g_debug_ldi_underflow_clear) {
+			if (is_mipi_cmd_panel(hisifd)) {
+				if (g_ldi_data_gate_en = 0) {
+					if (hisifd->ldi_underflow_wq) {
+						disable_ldi(hisifd);
+						queue_work(hisifd->ldi_underflow_wq,
+							   &hisifd->ldi_underflow_work);
+					}
+				}
+			} else {
+				if (hisifd->ldi_underflow_wq) {
+					disable_ldi(hisifd);
+					queue_work(hisifd->ldi_underflow_wq,
+						   &hisifd->ldi_underflow_work);
+				}
+			}
+		}
+
+		if (g_debug_ldi_underflow) {
+			if (g_debug_ovl_online_composer) {
+				if (hisifd->dss_debug_wq)
+					queue_work(hisifd->dss_debug_wq,
+						   &hisifd->dss_debug_work);
+			}
+		}
+		g_err_status |= DSS_PDP_LDI_UNDERFLOW;
+
+		if (hisifd->ldi_data_gate_en = 0) {
+			temp +			    inp32(hisifd->dss_base + DSS_DPP_OFFSET +
+				  DPP_DBG_CNT);
+			HISI_FB_INFO
+			    ("ldi underflow! frame_no = %d,dpp_dbg = 0x%x!\n",
+			     hisifd->ov_req.frame_no, temp);
+
+			for (i = 0; i < DSS_WCHN_W0; i++) {
+				if ((i != DSS_RCHN_V0) && (i != DSS_RCHN_G0)) {
+					HISI_FB_INFO
+					    ("RCH[%d], DMA_BUF_DBG0 = 0x%x,DMA_BUF_DBG1 = 0x%x!!\n",
+					     i, inp32(dss_module->dma_base[i] +
+						   DMA_BUF_DBG0),
+					     inp32(dss_module->dma_base[i] +
+						   DMA_BUF_DBG1));
+				}
+			}
+			for (i = 0; i < 18; i++) {
+				HISI_FB_INFO("MCTL_MOD%d_STATUS = 0x%x\n",
+					     i, inp32(dss_module->mctl_sys_base +
+						   MCTL_MOD0_STATUS + i * 0x4));
+			}
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+irqreturn_t dss_sdp_isr(int irq, void *ptr)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	uint32_t isr_s1 = 0;
+	uint32_t isr_s2 = 0;
+	uint32_t isr_s2_smmu = 0;
+	uint32_t mask = 0;
+
+	hisifd = (struct hisi_fb_data_type *)ptr;
+	BUG_ON(hisifd = NULL);
+
+	isr_s1 = inp32(hisifd->dss_base + GLB_CPU_SDP_INTS);
+	isr_s2 = inp32(hisifd->dss_base + DSS_LDI1_OFFSET + LDI_CPU_ITF_INTS);
+	isr_s2_smmu +	    inp32(hisifd->dss_base + DSS_SMMU_OFFSET + SMMU_INTSTAT_NS);
+
+	outp32(hisifd->dss_base + DSS_SMMU_OFFSET + SMMU_INTCLR_NS,
+	       isr_s2_smmu);
+	outp32(hisifd->dss_base + DSS_LDI1_OFFSET + LDI_CPU_ITF_INTS, isr_s2);
+	outp32(hisifd->dss_base + GLB_CPU_SDP_INTS, isr_s1);
+
+	isr_s1 &= ~(inp32(hisifd->dss_base + GLB_CPU_SDP_INT_MSK));
+	isr_s2 &+	    ~(inp32(hisifd->dss_base + DSS_LDI1_OFFSET + LDI_CPU_ITF_INT_MSK));
+
+	if (isr_s2 & BIT_VACTIVE0_END) {
+		hisifd->vactive0_end_flag = 1;
+	}
+
+	if (isr_s2 & BIT_VACTIVE0_START) {
+		if (hisifd->ov_vactive0_start_isr_handler)
+			hisifd->ov_vactive0_start_isr_handler(hisifd);
+	}
+
+	if (isr_s2 & BIT_VSYNC) {
+		if (hisifd->vsync_isr_handler) {
+			hisifd->vsync_isr_handler(hisifd);
+		}
+
+		if (hisifd->buf_sync_signal) {
+			hisifd->buf_sync_signal(hisifd);
+		}
+	}
+
+	if (isr_s2 & BIT_LDI_UNFLOW) {
+		mask +		    inp32(hisifd->dss_base + DSS_LDI1_OFFSET +
+			  LDI_CPU_ITF_INT_MSK);
+		mask |= BIT_LDI_UNFLOW;
+		outp32(hisifd->dss_base + DSS_LDI1_OFFSET + LDI_CPU_ITF_INT_MSK,
+		       mask);
+		if (g_debug_ldi_underflow_clear) {
+			if (is_mipi_cmd_panel(hisifd)) {
+				if (g_ldi_data_gate_en = 0) {
+					if (hisifd->ldi_underflow_wq) {
+						disable_ldi(hisifd);
+						queue_work(hisifd->ldi_underflow_wq,
+							   &hisifd->ldi_underflow_work);
+					}
+				}
+			} else {
+				if (hisifd->ldi_underflow_wq) {
+					disable_ldi(hisifd);
+					queue_work(hisifd->ldi_underflow_wq,
+						   &hisifd->ldi_underflow_work);
+				}
+			}
+		}
+		if (g_debug_ldi_underflow) {
+			if (g_debug_ovl_online_composer) {
+				if (hisifd->dss_debug_wq)
+					queue_work(hisifd->dss_debug_wq,
+						   &hisifd->dss_debug_work);
+			}
+		}
+		g_err_status |= DSS_SDP_LDI_UNDERFLOW;
+		if (hisifd->ldi_data_gate_en = 0)
+			HISI_FB_ERR("ldi underflow!\n");
+	}
+	return IRQ_HANDLED;
+}
+
+irqreturn_t dss_adp_isr(int irq, void *ptr)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	uint32_t isr_s1 = 0;
+	uint32_t isr_s2_smmu = 0;
+	uint32_t isr_s3_copybit = 0;
+
+	hisifd = (struct hisi_fb_data_type *)ptr;
+	BUG_ON(hisifd = NULL);
+
+	isr_s1 = inp32(hisifd->dss_base + GLB_CPU_OFF_INTS);
+	isr_s2_smmu +	    inp32(hisifd->dss_base + DSS_SMMU_OFFSET + SMMU_INTSTAT_NS);
+
+	outp32(hisifd->dss_base + DSS_SMMU_OFFSET + SMMU_INTCLR_NS,
+	       isr_s2_smmu);
+	outp32(hisifd->dss_base + GLB_CPU_OFF_INTS, isr_s1);
+
+	isr_s1 &= ~(inp32(hisifd->dss_base + GLB_CPU_OFF_INT_MSK));
+	isr_s3_copybit = inp32(hisifd->dss_base + GLB_CPU_OFF_CAM_INTS);
+	outp32(hisifd->dss_base + GLB_CPU_OFF_CAM_INTS, isr_s3_copybit);
+	isr_s3_copybit &= ~(inp32(hisifd->dss_base + GLB_CPU_OFF_CAM_INT_MSK));
+
+	if (isr_s1 & BIT_OFF_WCH0_INTS) {
+		if (hisifd->cmdlist_info->cmdlist_wb_flag[WB_TYPE_WCH0] = 1) {
+			hisifd->cmdlist_info->cmdlist_wb_done[WB_TYPE_WCH0] = 1;
+			wake_up_interruptible_all(&
+						  (hisifd->cmdlist_info->cmdlist_wb_wq
+						   [WB_TYPE_WCH0]));
+		}
+	}
+	if (isr_s1 & BIT_OFF_WCH1_INTS) {
+		if (hisifd->cmdlist_info->cmdlist_wb_flag[WB_TYPE_WCH1] = 1) {
+			hisifd->cmdlist_info->cmdlist_wb_done[WB_TYPE_WCH1] = 1;
+			wake_up_interruptible_all(&
+						  (hisifd->cmdlist_info->cmdlist_wb_wq
+						   [WB_TYPE_WCH1]));
+		}
+	}
+	if (isr_s1 & BIT_OFF_WCH0_WCH1_FRM_END_INT) {
+		if (hisifd->cmdlist_info->cmdlist_wb_flag[WB_TYPE_WCH0_WCH1] =
+		    1) {
+			hisifd->cmdlist_info->
+			    cmdlist_wb_done[WB_TYPE_WCH0_WCH1] = 1;
+			wake_up_interruptible_all(&
+						  (hisifd->cmdlist_info->cmdlist_wb_wq
+						   [WB_TYPE_WCH0_WCH1]));
+		}
+	}
+
+	if (isr_s3_copybit & BIT_OFF_CAM_WCH2_FRMEND_INTS) {
+		if (hisifd->copybit_info->copybit_flag = 1) {
+			hisifd->copybit_info->copybit_done = 1;
+			wake_up_interruptible_all(&
+						  (hisifd->copybit_info->copybit_wq));
+		}
+
+		if (hisifd->cmdlist_info->cmdlist_wb_flag[WB_TYPE_WCH2] = 1) {
+			hisifd->cmdlist_info->cmdlist_wb_done[WB_TYPE_WCH2] = 1;
+			wake_up_interruptible_all(&
+						  (hisifd->cmdlist_info->cmdlist_wb_wq
+						   [WB_TYPE_WCH2]));
+		}
+	}
+
+	return IRQ_HANDLED;
+}
diff --git a/drivers/video/fbdev/hisi/dss/hisi_fb_panel.c b/drivers/video/fbdev/hisi/dss/hisi_fb_panel.c
new file mode 100755
index 000000000000..a26035e8beba
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_fb_panel.c
@@ -0,0 +1,835 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_fb.h"
+#include "hisi_fb_panel.h"
+
+DEFINE_SEMAPHORE(hisi_fb_dts_resource_sem);
+mipi_ifbc_division_t g_mipi_ifbc_division[MIPI_DPHY_NUM][IFBC_TYPE_MAX] = {
+
+	{
+	 {XRES_DIV_1, YRES_DIV_1, IFBC_COMP_MODE_0, PXL0_DIV2_GT_EN_CLOSE,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_0, PXL0_DSI_GT_EN_1}
+	 ,
+
+	 {XRES_DIV_2, YRES_DIV_1, IFBC_COMP_MODE_0, PXL0_DIV2_GT_EN_OPEN,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_1, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_3, YRES_DIV_1, IFBC_COMP_MODE_1, PXL0_DIV2_GT_EN_OPEN,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_2, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_2, YRES_DIV_1, IFBC_COMP_MODE_2, PXL0_DIV2_GT_EN_OPEN,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_1, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_2, YRES_DIV_1, IFBC_COMP_MODE_3, PXL0_DIV2_GT_EN_CLOSE,
+	  PXL0_DIV4_GT_EN_OPEN, PXL0_DIVCFG_1, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_3, YRES_DIV_1, IFBC_COMP_MODE_4, PXL0_DIV2_GT_EN_CLOSE,
+	  PXL0_DIV4_GT_EN_OPEN, PXL0_DIVCFG_2, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_2, YRES_DIV_1, IFBC_COMP_MODE_5, PXL0_DIV2_GT_EN_CLOSE,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_1, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_3, YRES_DIV_1, IFBC_COMP_MODE_5, PXL0_DIV2_GT_EN_CLOSE,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_2, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_2, YRES_DIV_1, IFBC_COMP_MODE_6, PXL0_DIV2_GT_EN_OPEN,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_1, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_3, YRES_DIV_1, IFBC_COMP_MODE_6, PXL0_DIV2_GT_EN_OPEN,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_2, PXL0_DSI_GT_EN_3}
+	 }
+	,
+
+	{
+	 {XRES_DIV_2, YRES_DIV_1, IFBC_COMP_MODE_0, PXL0_DIV2_GT_EN_CLOSE,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_1, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_4, YRES_DIV_1, IFBC_COMP_MODE_0, PXL0_DIV2_GT_EN_OPEN,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_3, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_6, YRES_DIV_1, IFBC_COMP_MODE_1, PXL0_DIV2_GT_EN_OPEN,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_5, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_4, YRES_DIV_1, IFBC_COMP_MODE_2, PXL0_DIV2_GT_EN_OPEN,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_3, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_4, YRES_DIV_1, IFBC_COMP_MODE_3, PXL0_DIV2_GT_EN_CLOSE,
+	  PXL0_DIV4_GT_EN_OPEN, PXL0_DIVCFG_3, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_3, YRES_DIV_2, IFBC_COMP_MODE_4, PXL0_DIV2_GT_EN_CLOSE,
+	  PXL0_DIV4_GT_EN_OPEN, PXL0_DIVCFG_5, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_4, YRES_DIV_1, IFBC_COMP_MODE_5, PXL0_DIV2_GT_EN_CLOSE,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_3, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_6, YRES_DIV_1, IFBC_COMP_MODE_5, PXL0_DIV2_GT_EN_CLOSE,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_5, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_4, YRES_DIV_1, IFBC_COMP_MODE_6, PXL0_DIV2_GT_EN_OPEN,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_3, PXL0_DSI_GT_EN_3}
+	 ,
+
+	 {XRES_DIV_6, YRES_DIV_1, IFBC_COMP_MODE_6, PXL0_DIV2_GT_EN_OPEN,
+	  PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_5, 3}
+	 }
+};
+
+int gpio_cmds_tx(struct gpio_desc *cmds, int cnt)
+{
+	int ret = 0;
+	struct gpio_desc *cm = NULL;
+	int i = 0;
+
+	cm = cmds;
+	for (i = 0; i < cnt; i++) {
+		if ((cm = NULL) || (cm->label = NULL)) {
+			HISI_FB_ERR("cm or cm->label is null! index=%d\n", i);
+			ret = -1;
+			goto error;
+		}
+
+		if (!gpio_is_valid(*(cm->gpio))) {
+			HISI_FB_ERR
+			    ("gpio invalid, dtype=%d, lable=%s, gpio=%d!\n",
+			     cm->dtype, cm->label, *(cm->gpio));
+			ret = -1;
+			goto error;
+		}
+
+		if (cm->dtype = DTYPE_GPIO_INPUT) {
+			if (gpio_direction_input(*(cm->gpio)) != 0) {
+				HISI_FB_ERR
+				    ("failed to gpio_direction_input, lable=%s, gpio=%d!\n",
+				     cm->label, *(cm->gpio));
+				ret = -1;
+				goto error;
+			}
+		} else if (cm->dtype = DTYPE_GPIO_OUTPUT) {
+			if (gpio_direction_output(*(cm->gpio), cm->value) != 0) {
+				HISI_FB_ERR
+				    ("failed to gpio_direction_output, label%s, gpio=%d!\n",
+				     cm->label, *(cm->gpio));
+				ret = -1;
+				goto error;
+			}
+		} else if (cm->dtype = DTYPE_GPIO_REQUEST) {
+			if (gpio_request(*(cm->gpio), cm->label) != 0) {
+				HISI_FB_ERR
+				    ("failed to gpio_request, lable=%s, gpio=%d!\n",
+				     cm->label, *(cm->gpio));
+				ret = -1;
+				goto error;
+			}
+		} else if (cm->dtype = DTYPE_GPIO_FREE) {
+			gpio_free(*(cm->gpio));
+		} else {
+			HISI_FB_ERR("dtype=%x NOT supported\n", cm->dtype);
+			ret = -1;
+			goto error;
+		}
+
+		if (cm->wait) {
+			if (cm->waittype = WAIT_TYPE_US)
+				udelay(cm->wait);
+			else if (cm->waittype = WAIT_TYPE_MS)
+				mdelay(cm->wait);
+			else
+				mdelay(cm->wait * 1000);
+		}
+
+		cm++;
+	}
+
+	return 0;
+
+ error:
+	return ret;
+}
+
+int resource_cmds_tx(struct platform_device *pdev,
+		     struct resource_desc *cmds, int cnt)
+{
+	int ret = 0;
+	struct resource *res = NULL;
+	struct resource_desc *cm = NULL;
+	int i = 0;
+
+	BUG_ON(pdev = NULL);
+	cm = cmds;
+
+	for (i = 0; i < cnt; i++) {
+		if ((cm = NULL) || (cm->name = NULL)) {
+			HISI_FB_ERR("cm or cm->name is null! index=%d\n", i);
+			ret = -1;
+			goto error;
+		}
+
+		res = platform_get_resource_byname(pdev, cm->flag, cm->name);
+		if (!res) {
+			HISI_FB_ERR("failed to get %s resource!\n", cm->name);
+			ret = -1;
+			goto error;
+		}
+		*(cm->value) = res->start;
+		cm++;
+	}
+
+ error:
+	return ret;
+}
+
+int vcc_cmds_tx(struct platform_device *pdev, struct vcc_desc *cmds, int cnt)
+{
+	int ret = 0;
+	struct vcc_desc *cm = NULL;
+	int i = 0;
+
+	cm = cmds;
+	for (i = 0; i < cnt; i++) {
+		if ((cm = NULL) || (cm->id = NULL)) {
+			HISI_FB_ERR("cm or cm->id is null! index=%d\n", i);
+			ret = -1;
+			goto error;
+		}
+
+		if (cm->dtype = DTYPE_VCC_GET) {
+			BUG_ON(pdev = NULL);
+			*(cm->regulator) +			    devm_regulator_get(&pdev->dev, cm->id);
+			if (IS_ERR(*(cm->regulator))) {
+				HISI_FB_ERR("failed to get %s regulator!\n",
+					    cm->id);
+				ret = -1;
+				goto error;
+			}
+		} else if (cm->dtype = DTYPE_VCC_PUT) {
+			if (!IS_ERR(*(cm->regulator))) {
+				devm_regulator_put(*(cm->regulator));
+			}
+		} else if (cm->dtype = DTYPE_VCC_ENABLE) {
+			if (!IS_ERR(*(cm->regulator))) {
+				if (regulator_enable(*(cm->regulator)) != 0) {
+					HISI_FB_ERR
+					    ("failed to enable %s regulator!\n",
+					     cm->id);
+					ret = -1;
+					goto error;
+				}
+			}
+		} else if (cm->dtype = DTYPE_VCC_DISABLE) {
+			if (!IS_ERR(*(cm->regulator))) {
+				if (regulator_disable(*(cm->regulator)) != 0) {
+					HISI_FB_ERR
+					    ("failed to disable %s regulator!\n",
+					     cm->id);
+					ret = -1;
+					goto error;
+				}
+			}
+		} else if (cm->dtype = DTYPE_VCC_SET_VOLTAGE) {
+			if (!IS_ERR(*(cm->regulator))) {
+				if (regulator_set_voltage
+				    (*(cm->regulator), cm->min_uV,
+				     cm->max_uV) != 0) {
+					HISI_FB_ERR
+					    ("failed to set %s regulator voltage!\n",
+					     cm->id);
+					ret = -1;
+					goto error;
+				}
+			}
+		} else {
+			HISI_FB_ERR("dtype=%x NOT supported\n", cm->dtype);
+			ret = -1;
+			goto error;
+		}
+
+		if (cm->wait) {
+			if (cm->waittype = WAIT_TYPE_US)
+				udelay(cm->wait);
+			else if (cm->waittype = WAIT_TYPE_MS)
+				mdelay(cm->wait);
+			else
+				mdelay(cm->wait * 1000);
+		}
+
+		cm++;
+	}
+
+	return 0;
+
+ error:
+	return ret;
+}
+
+int pinctrl_cmds_tx(struct platform_device *pdev, struct pinctrl_cmd_desc *cmds,
+		    int cnt)
+{
+	int ret = 0;
+
+	int i = 0;
+	struct pinctrl_cmd_desc *cm = NULL;
+
+	cm = cmds;
+	for (i = 0; i < cnt; i++) {
+		if (cm = NULL) {
+			HISI_FB_ERR("cm is null! index=%d\n", i);
+			continue;
+		}
+		if (cm->dtype = DTYPE_PINCTRL_GET) {
+			BUG_ON(pdev = NULL);
+			cm->pctrl_data->p = devm_pinctrl_get(&pdev->dev);
+			if (IS_ERR(cm->pctrl_data->p)) {
+				ret = -1;
+				HISI_FB_ERR("failed to get p, index=%d!\n", i);
+				goto err;
+			}
+		} else if (cm->dtype = DTYPE_PINCTRL_STATE_GET) {
+			if (cm->mode = DTYPE_PINCTRL_STATE_DEFAULT) {
+				cm->pctrl_data->pinctrl_def +				    pinctrl_lookup_state(cm->pctrl_data->p,
+							 PINCTRL_STATE_DEFAULT);
+				if (IS_ERR(cm->pctrl_data->pinctrl_def)) {
+					ret = -1;
+					HISI_FB_ERR
+					    ("failed to get pinctrl_def, index=%d!\n",
+					     i);
+					goto err;
+				}
+			} else if (cm->mode = DTYPE_PINCTRL_STATE_IDLE) {
+				cm->pctrl_data->pinctrl_idle +				    pinctrl_lookup_state(cm->pctrl_data->p,
+							 PINCTRL_STATE_IDLE);
+				if (IS_ERR(cm->pctrl_data->pinctrl_idle)) {
+					ret = -1;
+					HISI_FB_ERR
+					    ("failed to get pinctrl_idle, index=%d!\n",
+					     i);
+					goto err;
+				}
+			} else {
+				ret = -1;
+				HISI_FB_ERR("unknown pinctrl type to get!\n");
+				goto err;
+			}
+		} else if (cm->dtype = DTYPE_PINCTRL_SET) {
+			if (cm->mode = DTYPE_PINCTRL_STATE_DEFAULT) {
+				if (cm->pctrl_data->p
+				    && cm->pctrl_data->pinctrl_def) {
+					ret +					    pinctrl_select_state(cm->pctrl_data->p,
+								 cm->pctrl_data->pinctrl_def);
+					if (ret) {
+						HISI_FB_ERR
+						    ("could not set this pin to default state!\n");
+						ret = -1;
+						goto err;
+					}
+				}
+			} else if (cm->mode = DTYPE_PINCTRL_STATE_IDLE) {
+				if (cm->pctrl_data->p
+				    && cm->pctrl_data->pinctrl_idle) {
+					ret +					    pinctrl_select_state(cm->pctrl_data->p,
+								 cm->pctrl_data->pinctrl_idle);
+					if (ret) {
+						HISI_FB_ERR
+						    ("could not set this pin to idle state!\n");
+						ret = -1;
+						goto err;
+					}
+				}
+			} else {
+				ret = -1;
+				HISI_FB_ERR("unknown pinctrl type to set!\n");
+				goto err;
+			}
+		} else if (cm->dtype = DTYPE_PINCTRL_PUT) {
+			if (cm->pctrl_data->p)
+				pinctrl_put(cm->pctrl_data->p);
+		} else {
+			HISI_FB_ERR("not supported command type!\n");
+			ret = -1;
+			goto err;
+		}
+
+		cm++;
+	}
+
+	return 0;
+
+ err:
+	return ret;
+}
+
+int panel_next_on(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct hisi_fb_panel_data *next_pdata = NULL;
+	struct platform_device *next_pdev = NULL;
+
+	BUG_ON(pdev = NULL);
+	pdata = dev_get_platdata(&pdev->dev);
+	BUG_ON(pdata = NULL);
+
+	next_pdev = pdata->next;
+	if (next_pdev) {
+		next_pdata = dev_get_platdata(&next_pdev->dev);
+		if ((next_pdata) && (next_pdata->on))
+			ret = next_pdata->on(next_pdev);
+	}
+
+	return ret;
+}
+
+int panel_next_off(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct hisi_fb_panel_data *next_pdata = NULL;
+	struct platform_device *next_pdev = NULL;
+
+	BUG_ON(pdev = NULL);
+	pdata = dev_get_platdata(&pdev->dev);
+	BUG_ON(pdata = NULL);
+
+	next_pdev = pdata->next;
+	if (next_pdev) {
+		next_pdata = dev_get_platdata(&next_pdev->dev);
+		if ((next_pdata) && (next_pdata->off))
+			ret = next_pdata->off(next_pdev);
+	}
+
+	return ret;
+}
+
+int panel_next_remove(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct hisi_fb_panel_data *next_pdata = NULL;
+	struct platform_device *next_pdev = NULL;
+
+	BUG_ON(pdev = NULL);
+	pdata = dev_get_platdata(&pdev->dev);
+	BUG_ON(pdata = NULL);
+
+	next_pdev = pdata->next;
+	if (next_pdev) {
+		next_pdata = dev_get_platdata(&next_pdev->dev);
+		if ((next_pdata) && (next_pdata->remove))
+			ret = next_pdata->remove(next_pdev);
+	}
+
+	return ret;
+}
+
+int panel_next_set_backlight(struct platform_device *pdev, uint32_t bl_level)
+{
+	int ret = 0;
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct hisi_fb_panel_data *next_pdata = NULL;
+	struct platform_device *next_pdev = NULL;
+
+	BUG_ON(pdev = NULL);
+	pdata = dev_get_platdata(&pdev->dev);
+	BUG_ON(pdata = NULL);
+
+	next_pdev = pdata->next;
+	if (next_pdev) {
+		next_pdata = dev_get_platdata(&next_pdev->dev);
+		if ((next_pdata) && (next_pdata->set_backlight))
+			ret = next_pdata->set_backlight(next_pdev, bl_level);
+	}
+
+	return ret;
+}
+
+int panel_next_vsync_ctrl(struct platform_device *pdev, int enable)
+{
+	int ret = 0;
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct hisi_fb_panel_data *next_pdata = NULL;
+	struct platform_device *next_pdev = NULL;
+
+	BUG_ON(pdev = NULL);
+	pdata = dev_get_platdata(&pdev->dev);
+	BUG_ON(pdata = NULL);
+
+	next_pdev = pdata->next;
+	if (next_pdev) {
+		next_pdata = dev_get_platdata(&next_pdev->dev);
+		if ((next_pdata) && (next_pdata->vsync_ctrl))
+			ret = next_pdata->vsync_ctrl(next_pdev, enable);
+	}
+
+	return ret;
+}
+
+bool is_ldi_panel(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd = NULL);
+	if (hisifd->panel_info.type & PANEL_LCDC)
+		return true;
+
+	return false;
+}
+
+bool is_mipi_cmd_panel(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd = NULL);
+
+	if (hisifd->panel_info.type & (PANEL_MIPI_CMD | PANEL_DUAL_MIPI_CMD))
+		return true;
+
+	return false;
+}
+
+bool is_mipi_cmd_panel_ext(struct hisi_panel_info *pinfo)
+{
+	BUG_ON(pinfo = NULL);
+
+	if (pinfo->type & (PANEL_MIPI_CMD | PANEL_DUAL_MIPI_CMD))
+		return true;
+
+	return false;
+}
+
+bool is_mipi_video_panel(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd = NULL);
+
+	if (hisifd->panel_info.
+	    type & (PANEL_MIPI_VIDEO | PANEL_DUAL_MIPI_VIDEO | PANEL_RGB2MIPI))
+		return true;
+
+	return false;
+}
+
+bool is_mipi_panel(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd = NULL);
+
+	if (hisifd->panel_info.type & (PANEL_MIPI_VIDEO | PANEL_MIPI_CMD |
+				       PANEL_DUAL_MIPI_VIDEO |
+				       PANEL_DUAL_MIPI_CMD))
+		return true;
+
+	return false;
+}
+
+bool is_dual_mipi_panel(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd = NULL);
+
+	if (hisifd->panel_info.
+	    type & (PANEL_DUAL_MIPI_VIDEO | PANEL_DUAL_MIPI_CMD))
+		return true;
+
+	return false;
+}
+
+bool is_dual_mipi_panel_ext(struct hisi_panel_info *pinfo)
+{
+	BUG_ON(pinfo = NULL);
+
+	if (pinfo->type & (PANEL_DUAL_MIPI_VIDEO | PANEL_DUAL_MIPI_CMD))
+		return true;
+
+	return false;
+}
+
+bool is_hisi_writeback_panel(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd = NULL);
+
+	if (hisifd->panel_info.type & PANEL_WRITEBACK)
+		return true;
+
+	return false;
+}
+
+bool is_ifbc_panel(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd = NULL);
+
+	if (hisifd->panel_info.ifbc_type != IFBC_TYPE_NONE)
+		return true;
+
+	return false;
+}
+
+bool is_ifbc_vesa_panel(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd = NULL);
+
+	if ((hisifd->panel_info.ifbc_type = IFBC_TYPE_VESA2X_SINGLE) ||
+	    (hisifd->panel_info.ifbc_type = IFBC_TYPE_VESA3X_SINGLE) ||
+	    (hisifd->panel_info.ifbc_type = IFBC_TYPE_VESA2X_DUAL) ||
+	    (hisifd->panel_info.ifbc_type = IFBC_TYPE_VESA3X_DUAL))
+		return true;
+
+	return false;
+}
+
+bool mipi_panel_check_reg(struct hisi_fb_data_type *hisifd,
+			  uint32_t *read_value)
+{
+	int ret = 0;
+	char lcd_reg_05[] = { 0x05 };
+	char lcd_reg_0a[] = { 0x0a };
+	char lcd_reg_0e[] = { 0x0e };
+	char lcd_reg_0f[] = { 0x0f };
+
+	struct dsi_cmd_desc lcd_check_reg[] = {
+		{DTYPE_GEN_WRITE1, 0, 10, WAIT_TYPE_US,
+		 sizeof(lcd_reg_05), lcd_reg_05}
+		,
+		{DTYPE_GEN_WRITE1, 0, 10, WAIT_TYPE_US,
+		 sizeof(lcd_reg_0a), lcd_reg_0a}
+		,
+		{DTYPE_GEN_WRITE1, 0, 10, WAIT_TYPE_US,
+		 sizeof(lcd_reg_0e), lcd_reg_0e}
+		,
+		{DTYPE_GEN_WRITE1, 0, 10, WAIT_TYPE_US,
+		 sizeof(lcd_reg_0f), lcd_reg_0f}
+		,
+	};
+
+	ret = mipi_dsi_cmds_rx(read_value, lcd_check_reg,
+			       ARRAY_SIZE(lcd_check_reg),
+			       hisifd->mipi_dsi0_base);
+	if (ret) {
+		HISI_FB_ERR("Read error number: %d\n", ret);
+		return false;
+	}
+
+	return true;
+}
+
+int mipi_ifbc_get_rect(struct hisi_fb_data_type *hisifd, struct dss_rect *rect)
+{
+	uint32_t ifbc_type = 0;
+	uint32_t mipi_idx = 0;
+	uint32_t xres_div = 1;
+	uint32_t yres_div = 1;
+
+	BUG_ON(hisifd = NULL);
+	BUG_ON(rect = NULL);
+
+	ifbc_type = hisifd->panel_info.ifbc_type;
+	BUG_ON((ifbc_type < IFBC_TYPE_NONE) || (ifbc_type >= IFBC_TYPE_MAX));
+
+	mipi_idx = is_dual_mipi_panel(hisifd) ? 1 : 0;
+
+	xres_div = g_mipi_ifbc_division[mipi_idx][ifbc_type].xres_div;
+	yres_div = g_mipi_ifbc_division[mipi_idx][ifbc_type].yres_div;
+
+	if ((rect->w % xres_div) > 0) {
+		HISI_FB_ERR
+		    ("fb%d, xres(%d) is not division_h(%d) pixel aligned!\n",
+		     hisifd->index, rect->w, xres_div);
+	}
+
+	if ((rect->h % yres_div) > 0) {
+		HISI_FB_ERR
+		    ("fb%d, yres(%d) is not division_v(%d) pixel aligned!\n",
+		     hisifd->index, rect->h, yres_div);
+	}
+
+	if ((mipi_idx = 0) && (ifbc_type = IFBC_TYPE_RSP3X)
+	    && (hisifd->panel_info.type = PANEL_MIPI_CMD)) {
+		rect->w *= 2;
+		rect->h /= 2;
+	}
+
+	rect->w /= xres_div;
+	rect->h /= yres_div;
+
+	return 0;
+}
+
+bool hisi_fb_device_probe_defer(uint32_t panel_type, uint32_t bl_type)
+{
+	bool flag = true;
+
+	down(&hisi_fb_dts_resource_sem);
+
+	switch (panel_type) {
+	case PANEL_NO:
+		if (g_dts_resouce_ready & DTS_FB_RESOURCE_INIT_READY) {
+			flag = false;
+		}
+		break;
+	case PANEL_LCDC:
+	case PANEL_MIPI2RGB:
+	case PANEL_RGB2MIPI:
+		if ((g_dts_resouce_ready & DTS_FB_RESOURCE_INIT_READY) &&
+		    (g_dts_resouce_ready & DTS_SPI_READY)) {
+			if (bl_type & (BL_SET_BY_PWM | BL_SET_BY_BLPWM)) {
+				if (g_dts_resouce_ready & DTS_PWM_READY)
+					flag = false;
+			} else {
+				flag = false;
+			}
+		}
+		break;
+	case PANEL_MIPI_VIDEO:
+	case PANEL_MIPI_CMD:
+	case PANEL_DUAL_MIPI_VIDEO:
+	case PANEL_DUAL_MIPI_CMD:
+	case PANEL_EDP:
+		if (g_dts_resouce_ready & DTS_FB_RESOURCE_INIT_READY) {
+			if (bl_type & (BL_SET_BY_PWM | BL_SET_BY_BLPWM)) {
+				if (g_dts_resouce_ready & DTS_PWM_READY)
+					flag = false;
+			} else {
+				flag = false;
+			}
+		}
+		break;
+	case PANEL_HDMI:
+		if (g_dts_resouce_ready & DTS_PANEL_PRIMARY_READY)
+			flag = false;
+		break;
+	case PANEL_WRITEBACK:
+		if (g_dts_resouce_ready & DTS_PANEL_OFFLINECOMPOSER_READY)
+			flag = false;
+		break;
+	default:
+		HISI_FB_ERR("not support this panel type(%d).\n", panel_type);
+		break;
+	}
+
+	up(&hisi_fb_dts_resource_sem);
+
+	return flag;
+}
+
+void hisi_fb_device_set_status0(uint32_t status)
+{
+	down(&hisi_fb_dts_resource_sem);
+	g_dts_resouce_ready |= status;
+	up(&hisi_fb_dts_resource_sem);
+}
+
+int hisi_fb_device_set_status1(struct hisi_fb_data_type *hisifd)
+{
+	int ret = 0;
+
+	BUG_ON(hisifd = NULL);
+
+	down(&hisi_fb_dts_resource_sem);
+
+	switch (hisifd->panel_info.type) {
+	case PANEL_LCDC:
+	case PANEL_MIPI_VIDEO:
+	case PANEL_MIPI_CMD:
+	case PANEL_DUAL_MIPI_VIDEO:
+	case PANEL_DUAL_MIPI_CMD:
+	case PANEL_EDP:
+	case PANEL_MIPI2RGB:
+	case PANEL_RGB2MIPI:
+	case PANEL_HDMI:
+		if (hisifd->index = PRIMARY_PANEL_IDX) {
+			g_dts_resouce_ready |= DTS_PANEL_PRIMARY_READY;
+		} else if (hisifd->index = EXTERNAL_PANEL_IDX) {
+			g_dts_resouce_ready |= DTS_PANEL_EXTERNAL_READY;
+		} else {
+			HISI_FB_ERR("not support fb(%d).\n", hisifd->index);
+		}
+		break;
+	case PANEL_WRITEBACK:
+		g_dts_resouce_ready |= DTS_PANEL_WRITEBACK_READY;
+		break;
+	default:
+		HISI_FB_ERR("not support this panel type(%d).\n",
+			    hisifd->panel_info.type);
+		ret = -1;
+		break;
+	}
+
+	up(&hisi_fb_dts_resource_sem);
+
+	return ret;
+}
+
+struct platform_device *hisi_fb_device_alloc(struct hisi_fb_panel_data *pdata,
+					     uint32_t type, uint32_t id)
+{
+	struct platform_device *this_dev = NULL;
+	char dev_name[32] = { 0 };
+
+	BUG_ON(pdata = NULL);
+
+	switch (type) {
+	case PANEL_MIPI_VIDEO:
+	case PANEL_MIPI_CMD:
+	case PANEL_DUAL_MIPI_VIDEO:
+	case PANEL_DUAL_MIPI_CMD:
+		snprintf(dev_name, sizeof(dev_name), DEV_NAME_MIPIDSI);
+		break;
+	case PANEL_EDP:
+		snprintf(dev_name, sizeof(dev_name), DEV_NAME_EDP);
+		break;
+	case PANEL_NO:
+	case PANEL_LCDC:
+	case PANEL_HDMI:
+	case PANEL_WRITEBACK:
+		snprintf(dev_name, sizeof(dev_name), DEV_NAME_DSS_DPE);
+		break;
+	case PANEL_RGB2MIPI:
+		snprintf(dev_name, sizeof(dev_name), DEV_NAME_RGB2MIPI);
+		break;
+	default:
+		HISI_FB_ERR("invalid panel type = %d!\n", type);
+		return NULL;
+	}
+
+	if (pdata != NULL)
+		pdata->next = NULL;
+	else
+		return NULL;
+
+	this_dev +	    platform_device_alloc(dev_name,
+				  (((uint32_t) type << 16) | (uint32_t) id));
+	if (this_dev) {
+		if (platform_device_add_data
+		    (this_dev, pdata, sizeof(struct hisi_fb_panel_data))) {
+			HISI_FB_ERR("failed to platform_device_add_data!\n");
+			platform_device_put(this_dev);
+			return NULL;
+		}
+	}
+
+	return this_dev;
+}
diff --git a/drivers/video/fbdev/hisi/dss/hisi_fb_panel.h b/drivers/video/fbdev/hisi/dss/hisi_fb_panel.h
new file mode 100755
index 000000000000..8afb1f42a8c5
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_fb_panel.h
@@ -0,0 +1,839 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+#ifndef HISI_FB_PANEL_H
+#define HISI_FB_PANEL_H
+
+#include "hisi_fb_def.h"
+#include "hisi_mipi_dsi.h"
+#include "hisi_dss.h"
+
+/* panel type list */
+#define PANEL_NO	BIT(0)	/* No Panel */
+#define PANEL_LCDC	BIT(1)	/* internal LCDC type */
+#define PANEL_HDMI	BIT(2)	/* HDMI TV */
+#define PANEL_MIPI_VIDEO	BIT(3)	/* MIPI */
+#define PANEL_MIPI_CMD	BIT(4)	/* MIPI */
+#define PANEL_DUAL_MIPI_VIDEO	BIT(5)	/* DUAL MIPI */
+#define PANEL_DUAL_MIPI_CMD	BIT(6)	/* DUAL MIPI */
+#define PANEL_EDP	BIT(7)	/* LVDS */
+#define PANEL_MIPI2RGB	BIT(8)	/* MIPI to RGB */
+#define PANEL_RGB2MIPI	BIT(9)	/* RGB to MIPI */
+#define PANEL_WRITEBACK	BIT(11)	/* Wifi display */
+
+/* dts initial */
+#define DTS_FB_RESOURCE_INIT_READY	BIT(0)
+#define DTS_PWM_READY	BIT(1)
+
+#define DTS_SPI_READY	BIT(3)
+#define DTS_PANEL_PRIMARY_READY	BIT(4)
+#define DTS_PANEL_EXTERNAL_READY	BIT(5)
+#define DTS_PANEL_OFFLINECOMPOSER_READY	BIT(6)
+#define DTS_PANEL_WRITEBACK_READY	BIT(7)
+
+/* device name */
+#define DEV_NAME_DSS_DPE		"dss_dpe"
+#define DEV_NAME_SPI			"spi_dev0"
+#define DEV_NAME_HDMI			"hdmi"
+#define DEV_NAME_EDP			"edp"
+#define DEV_NAME_MIPI2RGB		"mipi2rgb"
+#define DEV_NAME_RGB2MIPI		"rgb2mipi"
+#define DEV_NAME_MIPIDSI		"mipi_dsi"
+#define DEV_NAME_FB				"hisi_fb"
+#define DEV_NAME_PWM			"hisi_pwm"
+#define DEV_NAME_BLPWM			"hisi_blpwm"
+#define DEV_NAME_LCD_BKL		"lcd_backlight0"
+
+/* vcc name */
+#define REGULATOR_PDP_NAME	"regulator_dsssubsys"
+#define REGULATOR_MMBUF	"regulator_mmbuf"
+
+/* irq name */
+#define IRQ_PDP_NAME	"irq_pdp"
+#define IRQ_SDP_NAME	"irq_sdp"
+#define IRQ_ADP_NAME	"irq_adp"
+#define IRQ_DSI0_NAME	"irq_dsi0"
+#define IRQ_DSI1_NAME	"irq_dsi1"
+
+/* dts compatible */
+#define DTS_COMP_FB_NAME	"hisilicon,hisifb"
+#define DTS_COMP_PWM_NAME	"hisilicon,hisipwm"
+#define DTS_COMP_BLPWM_NAME	"hisilicon,hisiblpwm"
+#define DTS_PATH_LOGO_BUFFER	"/reserved-memory/logo-buffer"
+
+/* lcd resource name */
+#define LCD_BL_TYPE_NAME	"lcd-bl-type"
+#define FPGA_FLAG_NAME "fpga_flag"
+#define LCD_DISPLAY_TYPE_NAME	"lcd-display-type"
+#define LCD_IFBC_TYPE_NAME	"lcd-ifbc-type"
+
+/* backlight type */
+#define BL_SET_BY_NONE	BIT(0)
+#define BL_SET_BY_PWM	BIT(1)
+#define BL_SET_BY_BLPWM	BIT(2)
+#define BL_SET_BY_MIPI	BIT(3)
+#define BL_SET_BY_SH_BLPWM	BIT(4)
+
+/* supported display effect type */
+#define COMFORM_MODE			BIT(0)
+#define ACM_COLOR_ENHANCE_MODE	BIT(1)
+#define IC_COLOR_ENHANCE_MODE	BIT(2)
+#define CINEMA_MODE				BIT(3)
+#define VR_MODE                     BIT(4)
+#define LED_RG_COLOR_TEMP_MODE	BIT(16)
+#define GAMMA_MAP    BIT(19)
+
+#define LCD_BL_IC_NAME_MAX	(50)
+#define DEV_DSS_VOLTAGE_ID (20)
+
+enum BLPWM_PRECISION_TYPE {
+	BLPWM_PRECISION_DEFAULT_TYPE = 0,
+	BLPWM_PRECISION_10000_TYPE = 1,
+	BLPWM_PRECISION_2048_TYPE = 2,
+};
+
+enum LCD_INIT_STEP {
+	LCD_INIT_NONE = 0,
+	LCD_INIT_POWER_ON,
+	LCD_INIT_LDI_SEND_SEQUENCE,
+	LCD_INIT_MIPI_LP_SEND_SEQUENCE,
+	LCD_INIT_MIPI_HS_SEND_SEQUENCE,
+};
+
+enum LCD_UNINIT_STEP {
+	LCD_UNINIT_NONE = 0,
+	LCD_UNINIT_POWER_OFF,
+	LCD_UNINIT_LDI_SEND_SEQUENCE,
+	LCD_UNINIT_MIPI_LP_SEND_SEQUENCE,
+	LCD_UNINIT_MIPI_HS_SEND_SEQUENCE,
+};
+
+enum LCD_ESD_RECOVER_STEP {
+	LCD_ESD_RECOVER_NONE = 0,
+	LCD_ESD_RECOVER_POWER_OFF,
+	LCD_ESD_RECOVER_POWER_ON,
+};
+
+enum LCD_REFRESH_DIRECTION {
+	LCD_REFRESH_LEFT_TOP = 0,
+	LCD_REFRESH_RIGHT_TOP,
+	LCD_REFRESH_LEFT_BOTTOM,
+	LCD_REFRESH_RIGHT_BOTTOM,
+};
+
+enum IFBC_TYPE {
+	IFBC_TYPE_NONE = 0,
+	IFBC_TYPE_ORISE2X,
+	IFBC_TYPE_ORISE3X,
+	IFBC_TYPE_HIMAX2X,
+	IFBC_TYPE_RSP2X,
+	IFBC_TYPE_RSP3X,
+	IFBC_TYPE_VESA2X_SINGLE,
+	IFBC_TYPE_VESA3X_SINGLE,
+	IFBC_TYPE_VESA2X_DUAL,
+	IFBC_TYPE_VESA3X_DUAL,
+
+	IFBC_TYPE_MAX
+};
+
+enum IFBC_COMP_MODE {
+	IFBC_COMP_MODE_0 = 0,
+	IFBC_COMP_MODE_1,
+	IFBC_COMP_MODE_2,
+	IFBC_COMP_MODE_3,
+	IFBC_COMP_MODE_4,
+	IFBC_COMP_MODE_5,
+	IFBC_COMP_MODE_6,
+};
+
+enum XRES_DIV {
+	XRES_DIV_1 = 1,
+	XRES_DIV_2,
+	XRES_DIV_3,
+	XRES_DIV_4,
+	XRES_DIV_5,
+	XRES_DIV_6,
+};
+
+enum YRES_DIV {
+	YRES_DIV_1 = 1,
+	YRES_DIV_2,
+	YRES_DIV_3,
+	YRES_DIV_4,
+	YRES_DIV_5,
+	YRES_DIV_6,
+};
+
+enum PXL0_DIVCFG {
+	PXL0_DIVCFG_0 = 0,
+	PXL0_DIVCFG_1,
+	PXL0_DIVCFG_2,
+	PXL0_DIVCFG_3,
+	PXL0_DIVCFG_4,
+	PXL0_DIVCFG_5,
+	PXL0_DIVCFG_6,
+	PXL0_DIVCFG_7,
+};
+
+enum PXL0_DIV2_GT_EN {
+	PXL0_DIV2_GT_EN_CLOSE = 0,
+	PXL0_DIV2_GT_EN_OPEN,
+};
+
+enum PXL0_DIV4_GT_EN {
+	PXL0_DIV4_GT_EN_CLOSE = 0,
+	PXL0_DIV4_GT_EN_OPEN,
+};
+
+enum PXL0_DSI_GT_EN {
+	PXL0_DSI_GT_EN_0 = 0,
+	PXL0_DSI_GT_EN_1,
+	PXL0_DSI_GT_EN_2,
+	PXL0_DSI_GT_EN_3,
+};
+
+enum VSYNC_CTRL_TYPE {
+	VSYNC_CTRL_NONE = 0x0,
+	VSYNC_CTRL_ISR_OFF = BIT(0),
+	VSYNC_CTRL_MIPI_ULPS = BIT(1),
+	VSYNC_CTRL_CLK_OFF = BIT(2),
+	VSYNC_CTRL_VCC_OFF = BIT(3),
+};
+
+enum PERI_VOLTAGE_VALUE {
+	PERI_VOLTAGE_07V = 0x0,
+	PERI_VOLTAGE_08V = 0x2,
+};
+
+#define MIPI_DSI_BIT_CLK_STR1	"00001"
+#define MIPI_DSI_BIT_CLK_STR2	"00010"
+#define MIPI_DSI_BIT_CLK_STR3	"00100"
+#define MIPI_DSI_BIT_CLK_STR4	"01000"
+#define MIPI_DSI_BIT_CLK_STR5	"10000"
+
+/* resource desc */
+struct resource_desc {
+	uint32_t flag;
+	char *name;
+	uint32_t *value;
+};
+
+/* dtype for vcc */
+enum {
+	DTYPE_VCC_GET,
+	DTYPE_VCC_PUT,
+	DTYPE_VCC_ENABLE,
+	DTYPE_VCC_DISABLE,
+	DTYPE_VCC_SET_VOLTAGE,
+};
+
+/* vcc desc */
+struct vcc_desc {
+	int dtype;
+	char *id;
+	struct regulator **regulator;
+	int min_uV;
+	int max_uV;
+	int waittype;
+	int wait;
+};
+
+/* pinctrl operation */
+enum {
+	DTYPE_PINCTRL_GET,
+	DTYPE_PINCTRL_STATE_GET,
+	DTYPE_PINCTRL_SET,
+	DTYPE_PINCTRL_PUT,
+};
+
+/* pinctrl state */
+enum {
+	DTYPE_PINCTRL_STATE_DEFAULT,
+	DTYPE_PINCTRL_STATE_IDLE,
+};
+
+/* pinctrl data */
+struct pinctrl_data {
+	struct pinctrl *p;
+	struct pinctrl_state *pinctrl_def;
+	struct pinctrl_state *pinctrl_idle;
+};
+struct pinctrl_cmd_desc {
+	int dtype;
+	struct pinctrl_data *pctrl_data;
+	int mode;
+};
+
+/* dtype for gpio */
+enum {
+	DTYPE_GPIO_REQUEST,
+	DTYPE_GPIO_FREE,
+	DTYPE_GPIO_INPUT,
+	DTYPE_GPIO_OUTPUT,
+};
+
+/* gpio desc */
+struct gpio_desc {
+	int dtype;
+	int waittype;
+	int wait;
+	char *label;
+	uint32_t *gpio;
+	int value;
+};
+
+struct spi_cmd_desc {
+	int reg_len;
+	char *reg;
+	int val_len;
+	char *val;
+	int waittype;
+	int wait;
+};
+
+enum {
+	IFBC_ORISE_CTL_8LINE = 0,
+	IFBC_ORISE_CTL_16LINE,
+	IFBC_ORISE_CTL_32LINE,
+	IFBC_ORISE_CTL_FRAME,
+};
+
+typedef struct mipi_ifbc_division {
+	uint32_t xres_div;
+	uint32_t yres_div;
+	uint32_t comp_mode;
+	uint32_t pxl0_div2_gt_en;
+	uint32_t pxl0_div4_gt_en;
+	uint32_t pxl0_divxcfg;
+	uint32_t pxl0_dsi_gt_en;
+} mipi_ifbc_division_t;
+
+struct ldi_panel_info {
+	uint32_t h_back_porch;
+	uint32_t h_front_porch;
+	uint32_t h_pulse_width;
+
+	/*
+	 ** note: vbp > 8 if used overlay compose,
+	 ** also lcd vbp > 8 in lcd power on sequence
+	 */
+	uint32_t v_back_porch;
+	uint32_t v_front_porch;
+	uint32_t v_pulse_width;
+
+	uint8_t hsync_plr;
+	uint8_t vsync_plr;
+	uint8_t pixelclk_plr;
+	uint8_t data_en_plr;
+
+	/* for cabc */
+	uint8_t dpi0_overlap_size;
+	uint8_t dpi1_overlap_size;
+};
+
+/* DSI PHY configuration */
+struct mipi_dsi_phy_ctrl {
+	uint64_t lane_byte_clk;
+	uint32_t clk_division;
+
+	uint32_t clk_lane_lp2hs_time;
+	uint32_t clk_lane_hs2lp_time;
+	uint32_t data_lane_lp2hs_time;
+	uint32_t data_lane_hs2lp_time;
+	uint32_t clk2data_delay;
+	uint32_t data2clk_delay;
+
+	uint32_t clk_pre_delay;
+	uint32_t clk_post_delay;
+	uint32_t clk_t_lpx;
+	uint32_t clk_t_hs_prepare;
+	uint32_t clk_t_hs_zero;
+	uint32_t clk_t_hs_trial;
+	uint32_t clk_t_wakeup;
+	uint32_t data_pre_delay;
+	uint32_t data_post_delay;
+	uint32_t data_t_lpx;
+	uint32_t data_t_hs_prepare;
+	uint32_t data_t_hs_zero;
+	uint32_t data_t_hs_trial;
+	uint32_t data_t_ta_go;
+	uint32_t data_t_ta_get;
+	uint32_t data_t_wakeup;
+
+	uint32_t phy_stop_wait_time;
+
+	uint32_t rg_vrefsel_vcm;
+	uint32_t rg_hstx_ckg_sel;
+	uint32_t rg_pll_fbd_div5f;
+	uint32_t rg_pll_fbd_div1f;
+	uint32_t rg_pll_fbd_2p;
+	uint32_t rg_pll_enbwt;
+	uint32_t rg_pll_fbd_p;
+	uint32_t rg_pll_fbd_s;
+	uint32_t rg_pll_pre_div1p;
+	uint32_t rg_pll_pre_p;
+	uint32_t rg_pll_vco_750m;
+	uint32_t rg_pll_lpf_rs;
+	uint32_t rg_pll_lpf_cs;
+	uint32_t rg_pll_enswc;
+	uint32_t rg_pll_chp;
+
+
+	uint32_t pll_register_override;
+	uint32_t pll_power_down;
+	uint32_t rg_band_sel;
+	uint32_t rg_phase_gen_en;
+	uint32_t reload_sel;
+	uint32_t rg_pll_cp_p;
+	uint32_t rg_pll_refsel;
+	uint32_t rg_pll_cp;
+	uint32_t load_command;
+};
+
+struct mipi_panel_info {
+	uint8_t dsi_version;
+	uint8_t vc;
+	uint8_t lane_nums;
+	uint8_t lane_nums_select_support;
+	uint8_t color_mode;
+	uint32_t dsi_bit_clk;	/* clock lane(p/n) */
+	uint32_t burst_mode;
+	uint32_t max_tx_esc_clk;
+	uint8_t non_continue_en;
+
+	uint32_t dsi_bit_clk_val1;
+	uint32_t dsi_bit_clk_val2;
+	uint32_t dsi_bit_clk_val3;
+	uint32_t dsi_bit_clk_val4;
+	uint32_t dsi_bit_clk_val5;
+	uint32_t dsi_bit_clk_upt;
+	/*uint32_t dsi_pclk_rate; */
+
+	uint32_t hs_wr_to_time;
+
+	uint32_t clk_post_adjust;
+	uint32_t clk_pre_adjust;
+	uint32_t clk_pre_delay_adjust;
+	uint32_t clk_t_hs_exit_adjust;
+	uint32_t clk_t_hs_trial_adjust;
+	uint32_t clk_t_hs_prepare_adjust;
+	int clk_t_lpx_adjust;
+	uint32_t clk_t_hs_zero_adjust;
+	uint32_t data_post_delay_adjust;
+	int data_t_lpx_adjust;
+	uint32_t data_t_hs_prepare_adjust;
+	uint32_t data_t_hs_zero_adjust;
+	uint32_t data_t_hs_trial_adjust;
+	uint32_t rg_vrefsel_vcm_adjust;
+
+	uint32_t rg_vrefsel_vcm_clk_adjust;
+	uint32_t rg_vrefsel_vcm_data_adjust;
+};
+
+struct sbl_panel_info {
+	uint32_t strength_limit;
+	uint32_t calibration_a;
+	uint32_t calibration_b;
+	uint32_t calibration_c;
+	uint32_t calibration_d;
+	uint32_t t_filter_control;
+	uint32_t backlight_min;
+	uint32_t backlight_max;
+	uint32_t backlight_scale;
+	uint32_t ambient_light_min;
+	uint32_t filter_a;
+	uint32_t filter_b;
+	uint32_t logo_left;
+	uint32_t logo_top;
+	uint32_t variance_intensity_space;
+	uint32_t slope_max;
+	uint32_t slope_min;
+};
+
+typedef struct dss_sharpness_bit {
+	uint32_t sharp_en;
+	uint32_t sharp_mode;
+
+	uint32_t flt0_c0;
+	uint32_t flt0_c1;
+	uint32_t flt0_c2;
+
+	uint32_t flt1_c0;
+	uint32_t flt1_c1;
+	uint32_t flt1_c2;
+
+	uint32_t flt2_c0;
+	uint32_t flt2_c1;
+	uint32_t flt2_c2;
+
+	uint32_t ungain;
+	uint32_t ovgain;
+
+	uint32_t lineamt1;
+	uint32_t linedeten;
+	uint32_t linethd2;
+	uint32_t linethd1;
+
+	uint32_t sharpthd1;
+	uint32_t sharpthd1mul;
+	uint32_t sharpamt1;
+
+	uint32_t edgethd1;
+	uint32_t edgethd1mul;
+	uint32_t edgeamt1;
+} sharp2d_t;
+
+struct dsc_panel_info {
+
+	uint32_t bits_per_pixel;
+	uint32_t block_pred_enable;
+	uint32_t linebuf_depth;
+	uint32_t bits_per_component;
+	uint32_t slice_width;
+	uint32_t slice_height;
+	uint32_t initial_xmit_delay;
+	uint32_t first_line_bpg_offset;
+	uint32_t mux_word_size;
+	uint32_t initial_offset;
+	uint32_t flatness_max_qp;
+	uint32_t flatness_min_qp;
+	uint32_t rc_edge_factor;
+	uint32_t rc_model_size;
+	uint32_t rc_tgt_offset_lo;
+	uint32_t rc_tgt_offset_hi;
+	uint32_t rc_quant_incr_limit1;
+	uint32_t rc_quant_incr_limit0;
+	uint32_t rc_buf_thresh0;
+	uint32_t rc_buf_thresh1;
+	uint32_t rc_buf_thresh2;
+	uint32_t rc_buf_thresh3;
+	uint32_t rc_buf_thresh4;
+	uint32_t rc_buf_thresh5;
+	uint32_t rc_buf_thresh6;
+	uint32_t rc_buf_thresh7;
+	uint32_t rc_buf_thresh8;
+	uint32_t rc_buf_thresh9;
+	uint32_t rc_buf_thresh10;
+	uint32_t rc_buf_thresh11;
+	uint32_t rc_buf_thresh12;
+	uint32_t rc_buf_thresh13;
+	uint32_t range_min_qp0;
+	uint32_t range_max_qp0;
+	uint32_t range_bpg_offset0;
+	uint32_t range_min_qp1;
+	uint32_t range_max_qp1;
+	uint32_t range_bpg_offset1;
+	uint32_t range_min_qp2;
+	uint32_t range_max_qp2;
+	uint32_t range_bpg_offset2;
+	uint32_t range_min_qp3;
+	uint32_t range_max_qp3;
+	uint32_t range_bpg_offset3;
+	uint32_t range_min_qp4;
+	uint32_t range_max_qp4;
+	uint32_t range_bpg_offset4;
+	uint32_t range_min_qp5;
+	uint32_t range_max_qp5;
+	uint32_t range_bpg_offset5;
+	uint32_t range_min_qp6;
+	uint32_t range_max_qp6;
+	uint32_t range_bpg_offset6;
+	uint32_t range_min_qp7;
+	uint32_t range_max_qp7;
+	uint32_t range_bpg_offset7;
+	uint32_t range_min_qp8;
+	uint32_t range_max_qp8;
+	uint32_t range_bpg_offset8;
+	uint32_t range_min_qp9;
+	uint32_t range_max_qp9;
+	uint32_t range_bpg_offset9;
+	uint32_t range_min_qp10;
+	uint32_t range_max_qp10;
+	uint32_t range_bpg_offset10;
+	uint32_t range_min_qp11;
+	uint32_t range_max_qp11;
+	uint32_t range_bpg_offset11;
+	uint32_t range_min_qp12;
+	uint32_t range_max_qp12;
+	uint32_t range_bpg_offset12;
+	uint32_t range_min_qp13;
+	uint32_t range_max_qp13;
+	uint32_t range_bpg_offset13;
+	uint32_t range_min_qp14;
+	uint32_t range_max_qp14;
+	uint32_t range_bpg_offset14;
+};
+
+struct hisi_panel_info {
+	uint32_t type;
+	uint32_t xres;
+	uint32_t yres;
+	uint32_t width;
+	uint32_t height;
+	uint32_t bpp;
+	uint32_t fps;
+	uint32_t fps_updt;
+	uint32_t orientation;
+	uint32_t bgr_fmt;
+	uint32_t bl_set_type;
+	uint32_t bl_min;
+	uint32_t bl_max;
+	uint32_t bl_default;
+	uint32_t blpwm_precision_type;
+	uint32_t blpwm_out_div_value;
+	uint32_t blpwm_input_ena;
+	uint32_t blpwm_in_num;
+	uint32_t blpwm_input_precision;
+	uint32_t bl_ic_ctrl_mode;
+	uint64_t pxl_clk_rate;
+	uint64_t pxl_clk_rate_adjust;
+	uint32_t pxl_clk_rate_div;
+	uint32_t vsync_ctrl_type;
+	uint8_t fake_hdmi;
+	uint8_t reserved[3];
+
+	uint32_t ifbc_type;
+	uint32_t ifbc_cmp_dat_rev0;
+	uint32_t ifbc_cmp_dat_rev1;
+	uint32_t ifbc_auto_sel;
+	uint32_t ifbc_orise_ctl;
+	uint32_t ifbc_orise_ctr;
+
+	uint8_t lcd_init_step;
+	uint8_t lcd_uninit_step;
+	uint8_t lcd_uninit_step_support;
+	uint8_t lcd_refresh_direction_ctrl;
+	uint8_t lcd_adjust_support;
+
+	uint8_t sbl_support;
+	uint8_t color_temperature_support;
+	uint8_t color_temp_rectify_support;
+	uint32_t color_temp_rectify_R;
+	uint32_t color_temp_rectify_G;
+	uint32_t color_temp_rectify_B;
+	uint8_t comform_mode_support;
+	uint8_t cinema_mode_support;
+	uint8_t frc_enable;
+	uint8_t esd_enable;
+	uint8_t esd_skip_mipi_check;
+	uint8_t esd_recover_step;
+	uint8_t dirty_region_updt_support;
+	uint8_t dsi_bit_clk_upt_support;
+	uint8_t fps_updt_support;
+	uint8_t panel_effect_support;
+
+	uint8_t prefix_ce_support;
+	uint8_t prefix_sharpness1D_support;
+	uint8_t prefix_sharpness2D_support;
+	sharp2d_t *sharp2d_table;
+
+	uint8_t gmp_support;
+	uint8_t gamma_support;
+	uint8_t gamma_type;
+	uint8_t xcc_support;
+	uint8_t acm_support;
+	uint8_t acm_ce_support;
+	uint8_t hiace_support;
+	uint8_t dither_support;
+	uint8_t arsr1p_sharpness_support;
+	uint8_t post_scf_support;
+	uint8_t default_gmp_off;
+
+	uint32_t acm_valid_num;
+	uint32_t r0_hh;
+	uint32_t r0_lh;
+	uint32_t r1_hh;
+	uint32_t r1_lh;
+	uint32_t r2_hh;
+	uint32_t r2_lh;
+	uint32_t r3_hh;
+	uint32_t r3_lh;
+	uint32_t r4_hh;
+	uint32_t r4_lh;
+	uint32_t r5_hh;
+	uint32_t r5_lh;
+	uint32_t r6_hh;
+	uint32_t r6_lh;
+
+	uint32_t cinema_acm_valid_num;
+	uint32_t cinema_r0_hh;
+	uint32_t cinema_r0_lh;
+	uint32_t cinema_r1_hh;
+	uint32_t cinema_r1_lh;
+	uint32_t cinema_r2_hh;
+	uint32_t cinema_r2_lh;
+	uint32_t cinema_r3_hh;
+	uint32_t cinema_r3_lh;
+	uint32_t cinema_r4_hh;
+	uint32_t cinema_r4_lh;
+	uint32_t cinema_r5_hh;
+	uint32_t cinema_r5_lh;
+	uint32_t cinema_r6_hh;
+	uint32_t cinema_r6_lh;
+
+	uint32_t *acm_lut_hue_table;
+	uint32_t acm_lut_hue_table_len;
+	uint32_t *acm_lut_value_table;
+	uint32_t acm_lut_value_table_len;
+	uint32_t *acm_lut_sata_table;
+	uint32_t acm_lut_sata_table_len;
+	uint32_t *acm_lut_satr_table;
+	uint32_t acm_lut_satr_table_len;
+
+	uint32_t *cinema_acm_lut_hue_table;
+	uint32_t cinema_acm_lut_hue_table_len;
+	uint32_t *cinema_acm_lut_value_table;
+	uint32_t cinema_acm_lut_value_table_len;
+	uint32_t *cinema_acm_lut_sata_table;
+	uint32_t cinema_acm_lut_sata_table_len;
+	uint32_t *cinema_acm_lut_satr_table;
+	uint32_t cinema_acm_lut_satr_table_len;
+
+	uint32_t *acm_lut_satr0_table;
+	uint32_t acm_lut_satr0_table_len;
+	uint32_t *acm_lut_satr1_table;
+	uint32_t acm_lut_satr1_table_len;
+	uint32_t *acm_lut_satr2_table;
+	uint32_t acm_lut_satr2_table_len;
+	uint32_t *acm_lut_satr3_table;
+	uint32_t acm_lut_satr3_table_len;
+	uint32_t *acm_lut_satr4_table;
+	uint32_t acm_lut_satr4_table_len;
+	uint32_t *acm_lut_satr5_table;
+	uint32_t acm_lut_satr5_table_len;
+	uint32_t *acm_lut_satr6_table;
+	uint32_t acm_lut_satr6_table_len;
+	uint32_t *acm_lut_satr7_table;
+	uint32_t acm_lut_satr7_table_len;
+
+	uint32_t *cinema_acm_lut_satr0_table;
+	uint32_t *cinema_acm_lut_satr1_table;
+	uint32_t *cinema_acm_lut_satr2_table;
+	uint32_t *cinema_acm_lut_satr3_table;
+	uint32_t *cinema_acm_lut_satr4_table;
+	uint32_t *cinema_acm_lut_satr5_table;
+	uint32_t *cinema_acm_lut_satr6_table;
+	uint32_t *cinema_acm_lut_satr7_table;
+
+	uint32_t *gamma_lut_table_R;
+	uint32_t *gamma_lut_table_G;
+	uint32_t *gamma_lut_table_B;
+	uint32_t gamma_lut_table_len;
+	uint32_t *cinema_gamma_lut_table_R;
+	uint32_t *cinema_gamma_lut_table_G;
+	uint32_t *cinema_gamma_lut_table_B;
+	uint32_t cinema_gamma_lut_table_len;
+	uint32_t *igm_lut_table_R;
+	uint32_t *igm_lut_table_G;
+	uint32_t *igm_lut_table_B;
+	uint32_t igm_lut_table_len;
+	uint32_t *gmp_lut_table_low32bit;
+	uint32_t *gmp_lut_table_high4bit;
+	uint32_t gmp_lut_table_len;
+	uint32_t *xcc_table;
+	uint32_t xcc_table_len;
+
+	uint32_t *pgainlsc0;
+	uint32_t *pgainlsc1;
+	uint32_t pgainlsc_len;
+	uint32_t *hcoeff0y;
+	uint32_t *hcoeff1y;
+	uint32_t *hcoeff2y;
+	uint32_t *hcoeff3y;
+	uint32_t *hcoeff4y;
+	uint32_t *hcoeff5y;
+	uint32_t hcoeffy_len;
+	uint32_t *vcoeff0y;
+	uint32_t *vcoeff1y;
+	uint32_t *vcoeff2y;
+	uint32_t *vcoeff3y;
+	uint32_t *vcoeff4y;
+	uint32_t *vcoeff5y;
+	uint32_t vcoeffy_len;
+	uint32_t *hcoeff0uv;
+	uint32_t *hcoeff1uv;
+	uint32_t *hcoeff2uv;
+	uint32_t *hcoeff3uv;
+	uint32_t hcoeffuv_len;
+	uint32_t *vcoeff0uv;
+	uint32_t *vcoeff1uv;
+	uint32_t *vcoeff2uv;
+	uint32_t *vcoeff3uv;
+	uint32_t vcoeffuv_len;
+
+	struct spi_device *spi_dev;
+	struct ldi_panel_info ldi;
+	struct ldi_panel_info ldi_updt;
+	struct ldi_panel_info ldi_lfps;
+	struct mipi_panel_info mipi;
+	struct sbl_panel_info smart_bl;
+	struct dsc_panel_info vesa_dsc;
+	struct lcd_dirty_region_info dirty_region_info;
+
+	struct mipi_dsi_phy_ctrl dsi_phy_ctrl;
+
+	struct hiace_alg_parameter hiace_param;
+	struct ce_algorithm_parameter ce_alg_param;
+};
+
+struct hisi_fb_data_type;
+struct hisi_fb_panel_data {
+	struct hisi_panel_info *panel_info;
+
+	/* function entry chain */
+	int (*on) (struct platform_device *pdev);
+	int (*off) (struct platform_device *pdev);
+	int (*remove) (struct platform_device *pdev);
+	int (*set_backlight) (struct platform_device *pdev, uint32_t bl_level);
+	int (*vsync_ctrl) (struct platform_device *pdev, int enable);
+
+	struct platform_device *next;
+};
+
+/*******************************************************************************
+ ** FUNCTIONS PROTOTYPES
+ */
+#define MIPI_DPHY_NUM	(2)
+
+extern uint32_t g_dts_resouce_ready;
+extern mipi_ifbc_division_t g_mipi_ifbc_division[MIPI_DPHY_NUM][IFBC_TYPE_MAX];
+int resource_cmds_tx(struct platform_device *pdev,
+		     struct resource_desc *cmds, int cnt);
+int vcc_cmds_tx(struct platform_device *pdev, struct vcc_desc *cmds, int cnt);
+int pinctrl_cmds_tx(struct platform_device *pdev, struct pinctrl_cmd_desc *cmds,
+		    int cnt);
+int gpio_cmds_tx(struct gpio_desc *cmds, int cnt);
+extern struct spi_device *g_spi_dev;
+
+int panel_next_on(struct platform_device *pdev);
+int panel_next_off(struct platform_device *pdev);
+int panel_next_remove(struct platform_device *pdev);
+int panel_next_set_backlight(struct platform_device *pdev, uint32_t bl_level);
+int panel_next_vsync_ctrl(struct platform_device *pdev, int enable);
+
+bool is_ldi_panel(struct hisi_fb_data_type *hisifd);
+bool is_mipi_cmd_panel(struct hisi_fb_data_type *hisifd);
+bool is_mipi_cmd_panel_ext(struct hisi_panel_info *pinfo);
+bool is_mipi_video_panel(struct hisi_fb_data_type *hisifd);
+bool is_mipi_panel(struct hisi_fb_data_type *hisifd);
+bool is_dual_mipi_panel(struct hisi_fb_data_type *hisifd);
+bool is_dual_mipi_panel_ext(struct hisi_panel_info *pinfo);
+bool is_ifbc_panel(struct hisi_fb_data_type *hisifd);
+bool is_ifbc_vesa_panel(struct hisi_fb_data_type *hisifd);
+bool mipi_panel_check_reg(struct hisi_fb_data_type *hisifd,
+			  uint32_t *read_value);
+int mipi_ifbc_get_rect(struct hisi_fb_data_type *hisifd, struct dss_rect *rect);
+bool is_hisi_writeback_panel(struct hisi_fb_data_type *hisifd);
+void hisi_fb_device_set_status0(uint32_t status);
+int hisi_fb_device_set_status1(struct hisi_fb_data_type *hisifd);
+bool hisi_fb_device_probe_defer(uint32_t panel_type, uint32_t bl_type);
+#endif				/* HISI_FB_PANEL_H */
-- 
2.12.0-rc0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 6/8] fb: hisilicon: Add framebuffer driver for hi3660 SoC
  2017-02-07  2:35   ` cailiwei
@ 2017-02-07  2:35     ` cailiwei
  -1 siblings, 0 replies; 15+ messages in thread
From: cailiwei @ 2017-02-07  2:35 UTC (permalink / raw)
  To: linux-fbdev, linux-kernel, b.zolnierkie, guodong.xu
  Cc: suzhuangluan, dengqingshan, xuhongtao8, zhengwanchun,
	shizongxuan, cailiwei

From: Levy-Cai <cailiwei@hisilicon.com>

Add framebuffer driver for hi3660 SoC, this driver include lcd
driver & Hdmi adv7533/adv7535 driver, support lcd display at
1080p@60 and hdmi display at 1080p@60.

Signed-off-by: cailiwei <cailiwei@hisilicon.com>
---
 drivers/video/fbdev/hisi/dss/hisi_fb_utils.c       |  249 ++++
 drivers/video/fbdev/hisi/dss/hisi_fb_vsync.c       |  680 +++++++++
 drivers/video/fbdev/hisi/dss/hisi_mipi_dsi_host.c  |  401 ++++++
 .../fbdev/hisi/dss/hisi_overlay_cmdlist_utils.c    | 1450 ++++++++++++++++++++
 .../fbdev/hisi/dss/hisi_overlay_cmdlist_utils.h    |  249 ++++
 5 files changed, 3029 insertions(+)
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_fb_utils.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_fb_vsync.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_mipi_dsi_host.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_overlay_cmdlist_utils.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_overlay_cmdlist_utils.h

diff --git a/drivers/video/fbdev/hisi/dss/hisi_fb_utils.c b/drivers/video/fbdev/hisi/dss/hisi_fb_utils.c
new file mode 100755
index 000000000000..3c7965716890
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_fb_utils.c
@@ -0,0 +1,249 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_fb.h"
+#include "hisi_overlay_utils.h"
+#if defined (CONFIG_HISI_PERIDVFS)
+#include "peri_volt_poll.h"
+#endif
+
+#define MAX_BUF 60
+void set_reg(char __iomem *addr, uint32_t val, uint8_t bw, uint8_t bs)
+{
+	uint32_t mask = (1UL << bw) - 1UL;
+	uint32_t tmp = 0;
+
+	tmp = inp32(addr);
+	tmp &= ~(mask << bs);
+
+	outp32(addr, tmp | ((val & mask) << bs));
+
+	if (g_debug_set_reg_val) {
+		HISI_FB_INFO("writel: [%p] = 0x%x\n", addr,
+			     tmp | ((val & mask) << bs));
+	}
+}
+
+uint32_t set_bits32(uint32_t old_val, uint32_t val, uint8_t bw, uint8_t bs)
+{
+	uint32_t mask = (1UL << bw) - 1UL;
+	uint32_t tmp = 0;
+
+	tmp = old_val;
+	tmp &= ~(mask << bs);
+
+	return (tmp | ((val & mask) << bs));
+}
+
+void hisifb_set_reg(struct hisi_fb_data_type *hisifd,
+		    char __iomem *addr, uint32_t val, uint8_t bw, uint8_t bs)
+{
+	set_reg(addr, val, bw, bs);
+}
+
+bool is_dss_idle_enable(void)
+{
+	return ((g_enable_dss_idle == 1) ? true : false);
+}
+
+uint32_t get_panel_xres(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+
+	return ((hisifd->resolution_rect.w >
+		 0) ? hisifd->resolution_rect.w : hisifd->panel_info.xres);
+}
+
+uint32_t get_panel_yres(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+
+	return ((hisifd->resolution_rect.h >
+		 0) ? hisifd->resolution_rect.h : hisifd->panel_info.yres);
+}
+
+uint32_t hisifb_line_length(int index, uint32_t xres, int bpp)
+{
+	return ALIGN_UP(xres * bpp, DMA_STRIDE_ALIGN);
+}
+
+void hisifb_get_timestamp(struct timeval *tv)
+{
+	struct timespec ts;
+
+	ktime_get_ts(&ts);
+	tv->tv_sec = ts.tv_sec;
+	tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+}
+
+uint32_t hisifb_timestamp_diff(struct timeval *lasttime,
+			       struct timeval *curtime)
+{
+	uint32_t ret;
+	ret = (curtime->tv_usec >= lasttime->tv_usec) ?
+	    curtime->tv_usec - lasttime->tv_usec :
+	    1000000 - (lasttime->tv_usec - curtime->tv_usec);
+
+	return ret;
+}
+
+void hisifb_save_file(char *filename, char *buf, uint32_t buf_len)
+{
+	ssize_t write_len = 0;
+	struct file *fd = NULL;
+	mm_segment_t old_fs;
+	loff_t pos = 0;
+
+	BUG_ON(filename == NULL);
+	BUG_ON(buf == NULL);
+
+	fd = filp_open(filename, O_CREAT | O_RDWR, 0644);
+	if (IS_ERR(fd)) {
+		HISI_FB_ERR("filp_open returned:filename %s, error %ld\n",
+			    filename, PTR_ERR(fd));
+		return;
+	}
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	write_len = vfs_write(fd, (char __user *)buf, buf_len, &pos);
+
+	pos = 0;
+	set_fs(old_fs);
+	filp_close(fd, NULL);
+}
+
+int hisifb_ctrl_on(struct hisi_fb_data_type *hisifd)
+{
+	struct hisi_fb_panel_data *pdata = NULL;
+	int ret = 0;
+
+	BUG_ON(hisifd == NULL);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata == NULL);
+
+	if (pdata->on) {
+		ret = pdata->on(hisifd->pdev);
+	}
+
+	hisifb_vsync_resume(hisifd);
+	hisi_overlay_on(hisifd, false);
+
+	if (hisifd->panel_info.esd_enable) {
+		hrtimer_start(&hisifd->esd_ctrl.esd_hrtimer,
+			      ktime_set(ESD_CHECK_TIME_PERIOD / 1000,
+					(ESD_CHECK_TIME_PERIOD % 1000) *
+					1000000), HRTIMER_MODE_REL);
+	}
+
+	return ret;
+}
+
+int hisifb_ctrl_off(struct hisi_fb_data_type *hisifd)
+{
+	struct hisi_fb_panel_data *pdata = NULL;
+	int ret = 0;
+
+	BUG_ON(hisifd == NULL);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata == NULL);
+
+	if (hisifd->panel_info.esd_enable) {
+		hrtimer_cancel(&hisifd->esd_ctrl.esd_hrtimer);
+	}
+
+	hisifb_vsync_suspend(hisifd);
+	hisi_overlay_off(hisifd);
+
+	if (pdata->off) {
+		ret = pdata->off(hisifd->pdev);
+	}
+
+	if ((hisifd->index == PRIMARY_PANEL_IDX) ||
+	    (hisifd->index == EXTERNAL_PANEL_IDX)) {
+
+		hisifb_layerbuf_unlock(hisifd,
+				       &(hisifd->buf_sync_ctrl.layerbuf_list));
+	}
+
+	return ret;
+}
+
+int hisifb_ctrl_dss_clk_rate_set(struct fb_info *info, void __user *argp)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+	dss_clk_rate_t dss_clk_rate;
+
+	if (NULL == info) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	hisifd = (struct hisi_fb_data_type *)info->par;
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	if (hisifd->index != PRIMARY_PANEL_IDX) {
+		HISI_FB_ERR("fb%d, not supported!\n", hisifd->index);
+		return -EINVAL;
+	}
+
+	if (NULL == argp) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	if (hisifd->core_clk_upt_support == 0) {
+		HISI_FB_DEBUG("no support core_clk_upt\n");
+		return ret;
+	}
+
+	ret = copy_from_user(&dss_clk_rate, argp, sizeof(dss_clk_rate_t));
+	if (ret) {
+		HISI_FB_ERR("copy_from_user failed!ret=%d.", ret);
+		return ret;
+	}
+
+	down(&hisifd->blank_sem);
+
+	if (!hisifd->panel_power_on) {
+		HISI_FB_DEBUG("fb%d, panel power off!\n", hisifd->index);
+		ret = -EPERM;
+		goto err_out;
+	}
+
+	ret = set_dss_clk_rate(hisifd, dss_clk_rate);
+
+ err_out:
+	up(&hisifd->blank_sem);
+
+	return ret;
+}
+
+/*lint +e665, +e514, +e84, +e886, +e846, +e778*/
+void hisifb_sysfs_attrs_add(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	if (hisifd->sysfs_attrs_append_fnc) {
+		/* hisifd->sysfs_attrs_append_fnc(hisifd, &dev_attr_lcd_model.attr); */
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+}
diff --git a/drivers/video/fbdev/hisi/dss/hisi_fb_vsync.c b/drivers/video/fbdev/hisi/dss/hisi_fb_vsync.c
new file mode 100755
index 000000000000..3778ac0b4b2c
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_fb_vsync.c
@@ -0,0 +1,680 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat"
+#include "hisi_fb.h"
+
+/*
+ ** /sys/class/graphics/fb0/vsync_event
+ */
+#if defined(CONFIG_HISI_FB_VSYNC_THREAD)
+#define VSYNC_TIMEOUT_MSEC (100)
+#endif
+#define VSYNC_CTRL_EXPIRE_COUNT	(4)
+
+#ifdef CONFIG_REPORT_VSYNC
+extern void mali_kbase_pm_report_vsync(int);
+#endif
+extern int mipi_dsi_ulps_cfg(struct hisi_fb_data_type *hisifd, int enable);
+extern bool hisi_dss_check_reg_reload_status(struct hisi_fb_data_type *hisifd);
+
+void hisifb_frame_updated(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->vsync_ctrl.vsync_report_fnc) {
+		atomic_inc(&(hisifd->vsync_ctrl.buffer_updated));
+	}
+}
+
+void hisifb_vsync_isr_handler(struct hisi_fb_data_type *hisifd)
+{
+	struct hisifb_vsync *vsync_ctrl = NULL;
+	struct hisi_fb_panel_data *pdata = NULL;
+	int buffer_updated = 0;
+	ktime_t pre_vsync_timestamp;
+
+	BUG_ON(hisifd == NULL);
+	vsync_ctrl = &(hisifd->vsync_ctrl);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata == NULL);
+
+	pre_vsync_timestamp = vsync_ctrl->vsync_timestamp;
+	vsync_ctrl->vsync_timestamp = ktime_get();
+	wake_up_interruptible_all(&(vsync_ctrl->vsync_wait));
+
+	if (hisifd->panel_info.vsync_ctrl_type != VSYNC_CTRL_NONE) {
+		spin_lock(&vsync_ctrl->spin_lock);
+		if (vsync_ctrl->vsync_ctrl_expire_count) {
+			vsync_ctrl->vsync_ctrl_expire_count--;
+			if (vsync_ctrl->vsync_ctrl_expire_count == 0)
+				schedule_work(&vsync_ctrl->vsync_ctrl_work);
+		}
+		spin_unlock(&vsync_ctrl->spin_lock);
+	}
+
+	if (vsync_ctrl->vsync_report_fnc) {
+		if (hisifd->vsync_ctrl.vsync_enabled) {
+			buffer_updated =
+			    atomic_dec_return(&(vsync_ctrl->buffer_updated));
+		} else {
+			buffer_updated = 1;
+		}
+
+		if (buffer_updated < 0) {
+			atomic_cmpxchg(&(vsync_ctrl->buffer_updated),
+				       buffer_updated, 1);
+		} else {
+			vsync_ctrl->vsync_report_fnc(buffer_updated);
+		}
+	}
+
+	if (g_debug_online_vsync) {
+		HISI_FB_INFO("fb%d, VSYNC=%llu, time_diff=%llu.\n",
+			     hisifd->index,
+			     ktime_to_ns(hisifd->vsync_ctrl.vsync_timestamp),
+			     (ktime_to_ns(hisifd->vsync_ctrl.vsync_timestamp) -
+			      ktime_to_ns(pre_vsync_timestamp)));
+	}
+}
+
+static int vsync_timestamp_changed(struct hisi_fb_data_type *hisifd,
+				   ktime_t prev_timestamp)
+{
+	BUG_ON(hisifd == NULL);
+	return !ktime_equal(prev_timestamp, hisifd->vsync_ctrl.vsync_timestamp);
+}
+
+#if defined(CONFIG_HISI_FB_VSYNC_THREAD)
+static int wait_for_vsync_thread(void *data)
+{
+	struct hisi_fb_data_type *hisifd = (struct hisi_fb_data_type *)data;
+	ktime_t prev_timestamp;
+	int ret = 0;
+
+	while (!kthread_should_stop()) {
+		prev_timestamp = hisifd->vsync_ctrl.vsync_timestamp;
+		ret =
+		    wait_event_interruptible_timeout(hisifd->vsync_ctrl.
+						     vsync_wait,
+						     vsync_timestamp_changed
+						     (hisifd, prev_timestamp)
+						     && hisifd->vsync_ctrl.
+						     vsync_enabled,
+						     msecs_to_jiffies
+						     (VSYNC_TIMEOUT_MSEC));
+
+		/*if (ret == 0) {
+		   HISI_FB_ERR("wait vsync timeout!");
+		   return -ETIMEDOUT;
+		   }
+		*/
+
+		if (ret > 0) {
+			char *envp[2];
+			char buf[64];
+			/* fb%d_VSYNC=%llu */
+			snprintf(buf, sizeof(buf), "VSYNC=%llu",
+				 ktime_to_ns(hisifd->vsync_ctrl.
+					     vsync_timestamp));
+			envp[0] = buf;
+			envp[1] = NULL;
+			kobject_uevent_env(&hisifd->pdev->dev.kobj, KOBJ_CHANGE,
+					   envp);
+		}
+	}
+
+	return 0;
+}
+#else
+static ssize_t vsync_show_event(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	ssize_t ret = -1;
+	int vsync_flag = 0;
+	struct fb_info *fbi = NULL;
+	struct hisi_fb_data_type *hisifd = NULL;
+	ktime_t prev_timestamp;
+
+	if (NULL == dev) {
+		HISI_FB_ERR("NULL Pointer.\n");
+		return -1;
+	}
+
+	fbi = dev_get_drvdata(dev);
+	if (NULL == fbi) {
+		HISI_FB_ERR("NULL Pointer.\n");
+		return -1;
+	}
+
+	hisifd = (struct hisi_fb_data_type *)fbi->par;
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL Pointer.\n");
+		return -1;
+	}
+
+	if (NULL == buf) {
+		HISI_FB_ERR("NULL Pointer.\n");
+		return -1;
+	}
+
+	prev_timestamp = hisifd->vsync_ctrl.vsync_timestamp;
+
+	/*lint -e666 */
+	ret = wait_event_interruptible(hisifd->vsync_ctrl.vsync_wait,
+				       (vsync_timestamp_changed
+					(hisifd, prev_timestamp)
+					&& hisifd->vsync_ctrl.vsync_enabled));
+	/*lint +e666 */
+	vsync_flag = (vsync_timestamp_changed(hisifd, prev_timestamp) &&
+		      hisifd->vsync_ctrl.vsync_enabled);
+
+	if (vsync_flag) {
+		ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu, xxxxxxEvent=x \n",
+			       ktime_to_ns(hisifd->vsync_ctrl.vsync_timestamp));
+		buf[strlen(buf) + 1] = '\0';
+
+	} else {
+		return -1;
+	}
+
+	return ret;
+}
+
+static ssize_t vsync_timestamp_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	ssize_t ret = -1;
+	struct fb_info *fbi = NULL;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	if (NULL == dev) {
+		HISI_FB_ERR("NULL Pointer.\n");
+		return -1;
+	}
+
+	fbi = dev_get_drvdata(dev);
+	if (NULL == fbi) {
+		HISI_FB_ERR("NULL Pointer.\n");
+		return -1;
+	}
+
+	hisifd = (struct hisi_fb_data_type *)fbi->par;
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL Pointer.\n");
+		return -1;
+	}
+
+	if (NULL == buf) {
+		HISI_FB_ERR("NULL Pointer.\n");
+		return -1;
+	}
+
+	ret = snprintf(buf, PAGE_SIZE, "%llu \n",
+		       ktime_to_ns(hisifd->vsync_ctrl.vsync_timestamp));
+	buf[strlen(buf) + 1] = '\0';
+
+	return ret;
+}
+
+static DEVICE_ATTR(vsync_event, S_IRUGO, vsync_show_event, NULL);
+static DEVICE_ATTR(vsync_timestamp, S_IRUGO, vsync_timestamp_show, NULL);
+#endif
+
+#ifdef CONFIG_FAKE_VSYNC_USED
+enum hrtimer_restart hisifb_fake_vsync(struct hrtimer *timer)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	int fps = 60;
+
+	hisifd =
+	    container_of(timer, struct hisi_fb_data_type, fake_vsync_hrtimer);
+	BUG_ON(hisifd == NULL);
+
+	if (!hisifd->panel_power_on)
+		goto error;
+
+	if (hisifd->fake_vsync_used && hisifd->vsync_ctrl.vsync_enabled) {
+		hisifd->vsync_ctrl.vsync_timestamp = ktime_get();
+		wake_up_interruptible_all(&hisifd->vsync_ctrl.vsync_wait);
+	}
+
+ error:
+	hrtimer_start(&hisifd->fake_vsync_hrtimer,
+		      ktime_set(0, NSEC_PER_SEC / fps), HRTIMER_MODE_REL);
+
+	return HRTIMER_NORESTART;
+}
+#endif
+
+static void hisifb_vsync_ctrl_workqueue_handler(struct work_struct *work)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct hisifb_vsync *vsync_ctrl = NULL;
+	struct hisi_fb_panel_data *pdata = NULL;
+	unsigned long flags = 0;
+
+	vsync_ctrl = container_of(work, typeof(*vsync_ctrl), vsync_ctrl_work);
+	BUG_ON(vsync_ctrl == NULL);
+	hisifd = vsync_ctrl->hisifd;
+	BUG_ON(hisifd == NULL);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata == NULL);
+
+	down(&(hisifd->blank_sem));
+
+	if (!hisifd->panel_power_on) {
+		HISI_FB_INFO("fb%d, panel is power off!", hisifd->index);
+		up(&(hisifd->blank_sem));
+		return;
+	}
+
+	mutex_lock(&(vsync_ctrl->vsync_lock));
+	if (vsync_ctrl->vsync_ctrl_disabled_set &&
+	    (vsync_ctrl->vsync_ctrl_expire_count == 0) &&
+	    vsync_ctrl->vsync_ctrl_enabled &&
+	    !vsync_ctrl->vsync_enabled
+	    && !vsync_ctrl->vsync_ctrl_offline_enabled) {
+		HISI_FB_DEBUG("fb%d, dss clk off!\n", hisifd->index);
+
+		spin_lock_irqsave(&(vsync_ctrl->spin_lock), flags);
+		if (pdata->vsync_ctrl) {
+			pdata->vsync_ctrl(hisifd->pdev, 0);
+		} else {
+			HISI_FB_ERR("fb%d, vsync_ctrl not supported!\n",
+				    hisifd->index);
+		}
+		vsync_ctrl->vsync_ctrl_enabled = 0;
+		vsync_ctrl->vsync_ctrl_disabled_set = 0;
+		spin_unlock_irqrestore(&(vsync_ctrl->spin_lock), flags);
+
+		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_MIPI_ULPS) {
+			mipi_dsi_ulps_cfg(hisifd, 0);
+		}
+
+		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_VCC_OFF) {
+			if (hisifd->lp_fnc)
+				hisifd->lp_fnc(hisifd, true);
+		}
+
+		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_CLK_OFF) {
+			dpe_inner_clk_disable(hisifd);
+			dpe_common_clk_disable(hisifd);
+			mipi_dsi_clk_disable(hisifd);
+		}
+
+		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_VCC_OFF) {
+			/* dpe_regulator_disable(hisifd); */
+		}
+	}
+	mutex_unlock(&(vsync_ctrl->vsync_lock));
+
+	if (vsync_ctrl->vsync_report_fnc) {
+		vsync_ctrl->vsync_report_fnc(1);
+	}
+
+	up(&(hisifd->blank_sem));
+}
+
+void hisifb_vsync_register(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct hisifb_vsync *vsync_ctrl = NULL;
+#if defined(CONFIG_HISI_FB_VSYNC_THREAD)
+	char name[64] = { 0 };
+#endif
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+	vsync_ctrl = &(hisifd->vsync_ctrl);
+	BUG_ON(vsync_ctrl == NULL);
+
+	if (vsync_ctrl->vsync_created)
+		return;
+
+	vsync_ctrl->hisifd = hisifd;
+	vsync_ctrl->vsync_infinite = 0;
+	vsync_ctrl->vsync_enabled = 0;
+	vsync_ctrl->vsync_ctrl_offline_enabled = 0;
+	vsync_ctrl->vsync_timestamp = ktime_get();
+	init_waitqueue_head(&(vsync_ctrl->vsync_wait));
+	spin_lock_init(&(vsync_ctrl->spin_lock));
+	INIT_WORK(&vsync_ctrl->vsync_ctrl_work,
+		  hisifb_vsync_ctrl_workqueue_handler);
+
+	mutex_init(&(vsync_ctrl->vsync_lock));
+
+	atomic_set(&(vsync_ctrl->buffer_updated), 1);
+#ifdef CONFIG_REPORT_VSYNC
+	vsync_ctrl->vsync_report_fnc = mali_kbase_pm_report_vsync;
+#else
+	vsync_ctrl->vsync_report_fnc = NULL;
+#endif
+
+#ifdef CONFIG_FAKE_VSYNC_USED
+	/* hrtimer for fake vsync timing */
+	hisifd->fake_vsync_used = false;
+	hrtimer_init(&hisifd->fake_vsync_hrtimer, CLOCK_MONOTONIC,
+		     HRTIMER_MODE_REL);
+	hisifd->fake_vsync_hrtimer.function = hisifb_fake_vsync;
+	hrtimer_start(&hisifd->fake_vsync_hrtimer,
+		      ktime_set(0, NSEC_PER_SEC / 60), HRTIMER_MODE_REL);
+#endif
+
+#if defined(CONFIG_HISI_FB_VSYNC_THREAD)
+	snprintf(name, sizeof(name), "hisifb%d_vsync", hisifd->index);
+	vsync_ctrl->vsync_thread =
+	    kthread_run(wait_for_vsync_thread, hisifd, name);
+	if (IS_ERR(vsync_ctrl->vsync_thread)) {
+		vsync_ctrl->vsync_thread = NULL;
+		HISI_FB_ERR("failed to run vsync thread!\n");
+		return;
+	}
+#else
+	if (hisifd->sysfs_attrs_append_fnc) {
+		hisifd->sysfs_attrs_append_fnc(hisifd,
+					       &dev_attr_vsync_event.attr);
+		hisifd->sysfs_attrs_append_fnc(hisifd,
+					       &dev_attr_vsync_timestamp.attr);
+	}
+#endif
+
+	vsync_ctrl->vsync_created = 1;
+}
+
+void hisifb_vsync_unregister(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct hisifb_vsync *vsync_ctrl = NULL;
+
+	BUG_ON(pdev == NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd == NULL);
+	vsync_ctrl = &(hisifd->vsync_ctrl);
+	BUG_ON(vsync_ctrl == NULL);
+
+	if (!vsync_ctrl->vsync_created)
+		return;
+
+#ifdef CONFIG_FAKE_VSYNC_USED
+	hisifd->fake_vsync_used = false;
+	hrtimer_cancel(&hisifd->fake_vsync_hrtimer);
+#endif
+
+#if defined(CONFIG_HISI_FB_VSYNC_THREAD)
+	if (vsync_ctrl->vsync_thread)
+		kthread_stop(vsync_ctrl->vsync_thread);
+#endif
+
+	vsync_ctrl->vsync_created = 0;
+}
+
+void hisifb_set_vsync_activate_state(struct hisi_fb_data_type *hisifd,
+				     bool infinite)
+{
+	struct hisifb_vsync *vsync_ctrl = NULL;
+
+	BUG_ON(hisifd == NULL);
+	vsync_ctrl = &(hisifd->vsync_ctrl);
+	BUG_ON(vsync_ctrl == NULL);
+
+	if (hisifd->panel_info.vsync_ctrl_type == VSYNC_CTRL_NONE)
+		return;
+
+	mutex_lock(&(vsync_ctrl->vsync_lock));
+
+	if (infinite) {
+		vsync_ctrl->vsync_infinite_count += 1;
+	} else {
+		vsync_ctrl->vsync_infinite_count -= 1;
+	}
+
+	if (vsync_ctrl->vsync_infinite_count >= 1) {
+		vsync_ctrl->vsync_infinite = 1;
+	}
+
+	if (vsync_ctrl->vsync_infinite_count == 0) {
+		vsync_ctrl->vsync_infinite = 0;
+	}
+
+	mutex_unlock(&(vsync_ctrl->vsync_lock));
+}
+
+void hisifb_activate_vsync(struct hisi_fb_data_type *hisifd)
+{
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct hisifb_vsync *vsync_ctrl = NULL;
+	unsigned long flags = 0;
+	int clk_enabled = 0;
+
+	BUG_ON(hisifd == NULL);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata == NULL);
+	vsync_ctrl = &(hisifd->vsync_ctrl);
+	BUG_ON(vsync_ctrl == NULL);
+
+	if (hisifd->panel_info.vsync_ctrl_type == VSYNC_CTRL_NONE)
+		return;
+
+	mutex_lock(&(vsync_ctrl->vsync_lock));
+
+	if (vsync_ctrl->vsync_ctrl_enabled == 0) {
+		HISI_FB_DEBUG("fb%d, dss clk on!\n", hisifd->index);
+
+		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_VCC_OFF) {
+			/* dpe_regulator_enable(hisifd); */
+		}
+
+		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_CLK_OFF) {
+			mipi_dsi_clk_enable(hisifd);
+			dpe_common_clk_enable(hisifd);
+			dpe_inner_clk_enable(hisifd);
+		}
+
+		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_VCC_OFF) {
+			if (hisifd->lp_fnc)
+				hisifd->lp_fnc(hisifd, false);
+		}
+
+		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_MIPI_ULPS) {
+			mipi_dsi_ulps_cfg(hisifd, 1);
+		}
+
+		vsync_ctrl->vsync_ctrl_enabled = 1;
+		clk_enabled = 1;
+	} else if (vsync_ctrl->vsync_ctrl_isr_enabled) {
+		clk_enabled = 1;
+		vsync_ctrl->vsync_ctrl_isr_enabled = 0;
+	} else {
+		;
+	}
+
+	spin_lock_irqsave(&(vsync_ctrl->spin_lock), flags);
+	vsync_ctrl->vsync_ctrl_disabled_set = 0;
+	vsync_ctrl->vsync_ctrl_expire_count = 0;
+	if (clk_enabled) {
+		if (pdata->vsync_ctrl) {
+			pdata->vsync_ctrl(hisifd->pdev, 1);
+		} else {
+			HISI_FB_ERR("fb%d, vsync_ctrl not supported!\n",
+				    hisifd->index);
+		}
+	}
+	spin_unlock_irqrestore(&(vsync_ctrl->spin_lock), flags);
+
+	mutex_unlock(&(vsync_ctrl->vsync_lock));
+}
+
+void hisifb_deactivate_vsync(struct hisi_fb_data_type *hisifd)
+{
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct hisifb_vsync *vsync_ctrl = NULL;
+	unsigned long flags = 0;
+
+	BUG_ON(hisifd == NULL);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata == NULL);
+	vsync_ctrl = &(hisifd->vsync_ctrl);
+	BUG_ON(vsync_ctrl == NULL);
+
+	if (hisifd->panel_info.vsync_ctrl_type == VSYNC_CTRL_NONE)
+		return;
+
+	mutex_lock(&(vsync_ctrl->vsync_lock));
+
+	spin_lock_irqsave(&(vsync_ctrl->spin_lock), flags);
+	if (vsync_ctrl->vsync_infinite == 0)
+		vsync_ctrl->vsync_ctrl_disabled_set = 1;
+
+	if (vsync_ctrl->vsync_ctrl_enabled)
+		vsync_ctrl->vsync_ctrl_expire_count = VSYNC_CTRL_EXPIRE_COUNT;
+	spin_unlock_irqrestore(&(vsync_ctrl->spin_lock), flags);
+
+	mutex_unlock(&(vsync_ctrl->vsync_lock));
+}
+
+int hisifb_vsync_ctrl(struct fb_info *info, void __user *argp)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct hisifb_vsync *vsync_ctrl = NULL;
+	int enable = 0;
+
+	if (NULL == info) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	hisifd = (struct hisi_fb_data_type *)info->par;
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	if (hisifd->index != PRIMARY_PANEL_IDX) {
+		HISI_FB_ERR("fb%d, not supported!\n", hisifd->index);
+		return -EINVAL;
+	}
+
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	if (NULL == pdata) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	vsync_ctrl = &(hisifd->vsync_ctrl);
+	if (NULL == vsync_ctrl) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	if (NULL == argp) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	ret = copy_from_user(&enable, argp, sizeof(enable));
+	if (ret) {
+		HISI_FB_ERR("hisifb_vsync_ctrl ioctl failed!\n");
+		return ret;
+	}
+
+	enable = (enable) ? 1 : 0;
+
+	mutex_lock(&(vsync_ctrl->vsync_lock));
+
+	if (vsync_ctrl->vsync_enabled == enable) {
+		mutex_unlock(&(vsync_ctrl->vsync_lock));
+		return 0;
+	}
+
+	if (g_debug_online_vsync)
+		HISI_FB_INFO("fb%d, enable=%d!\n", hisifd->index, enable);
+
+	vsync_ctrl->vsync_enabled = enable;
+
+	mutex_unlock(&(vsync_ctrl->vsync_lock));
+
+	down(&hisifd->blank_sem);
+
+	if (!hisifd->panel_power_on) {
+		HISI_FB_INFO("fb%d, panel is power off!", hisifd->index);
+		up(&hisifd->blank_sem);
+		return 0;
+	}
+
+	if (enable) {
+		hisifb_activate_vsync(hisifd);
+	} else {
+		hisifb_deactivate_vsync(hisifd);
+	}
+
+	up(&hisifd->blank_sem);
+
+	return 0;
+}
+
+int hisifb_vsync_resume(struct hisi_fb_data_type *hisifd)
+{
+	struct hisifb_vsync *vsync_ctrl = NULL;
+
+	BUG_ON(hisifd == NULL);
+	vsync_ctrl = &(hisifd->vsync_ctrl);
+	BUG_ON(vsync_ctrl == NULL);
+
+	vsync_ctrl->vsync_enabled = 0;
+	vsync_ctrl->vsync_ctrl_expire_count = 0;
+	vsync_ctrl->vsync_ctrl_disabled_set = 0;
+	vsync_ctrl->vsync_ctrl_enabled = 1;
+	vsync_ctrl->vsync_ctrl_isr_enabled = 1;
+
+	atomic_set(&(vsync_ctrl->buffer_updated), 1);
+
+#if 0
+	if (hisifd->panel_info.vsync_ctrl_type != VSYNC_CTRL_NONE) {
+		if ((hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_MIPI_ULPS)
+		    || (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_CLK_OFF)
+		    || (hisifd->panel_info.
+			vsync_ctrl_type & VSYNC_CTRL_VCC_OFF)) {
+
+			if (hisifd->panel_info.
+			    vsync_ctrl_type & VSYNC_CTRL_MIPI_ULPS) {
+				mipi_dsi_ulps_cfg(hisifd, 0);
+			}
+
+			if (hisifd->panel_info.
+			    vsync_ctrl_type & VSYNC_CTRL_CLK_OFF) {
+				dpe_inner_clk_disable(hisifd);
+				dpe_common_clk_disable(hisifd);
+				mipi_dsi_clk_disable(hisifd);
+			}
+
+			if (hisifd->panel_info.
+			    vsync_ctrl_type & VSYNC_CTRL_VCC_OFF) {
+				dpe_regulator_disable(hisifd);
+			}
+		}
+	}
+#endif
+
+	return 0;
+}
+
+int hisifb_vsync_suspend(struct hisi_fb_data_type *hisifd)
+{
+	return 0;
+}
+
+#pragma GCC diagnostic pop
diff --git a/drivers/video/fbdev/hisi/dss/hisi_mipi_dsi_host.c b/drivers/video/fbdev/hisi/dss/hisi_mipi_dsi_host.c
new file mode 100755
index 000000000000..0d00d3fd9c60
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_mipi_dsi_host.c
@@ -0,0 +1,401 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_mipi_dsi.h"
+
+/*
+ * mipi dsi short write with 0, 1 2 parameters
+ * Write to GEN_HDR 24 bit register the value:
+ * 1. 00h, MCS_command[15:8] ,VC[7:6],13h
+ * 2. Data1[23:16], MCS_command[15:8] ,VC[7:6],23h
+ */
+int mipi_dsi_swrite(struct dsi_cmd_desc *cm, char __iomem *dsi_base)
+{
+	uint32_t hdr = 0;
+	int len = 0;
+
+	if (cm->dlen && cm->payload == 0) {
+		HISI_FB_ERR("NO payload error!\n");
+		return 0;
+	}
+
+	BUG_ON(cm->dlen > 2);
+	len = cm->dlen;
+	hdr |= DSI_HDR_DTYPE(cm->dtype);
+	hdr |= DSI_HDR_VC(cm->vc);
+	if (len == 1) {
+		hdr |= DSI_HDR_DATA1(cm->payload[0]);
+		hdr |= DSI_HDR_DATA2(0);
+	} else if (len == 2) {
+		hdr |= DSI_HDR_DATA1(cm->payload[0]);
+		hdr |= DSI_HDR_DATA2(cm->payload[1]);
+	} else {
+		hdr |= DSI_HDR_DATA1(0);
+		hdr |= DSI_HDR_DATA2(0);
+	}
+
+	set_reg(dsi_base + MIPIDSI_GEN_HDR_OFFSET, hdr, 24, 0);
+
+	return len;		/* 4 bytes */
+}
+
+/*
+ * mipi dsi long write
+ * Write to GEN_PLD_DATA 32 bit register the value:
+ * Data3[31:24], Data2[23:16], Data1[15:8], MCS_command[7:0]
+ * If need write again to GEN_PLD_DATA 32 bit register the value:
+ * Data7[31:24], Data6[23:16], Data5[15:8], Data4[7:0]
+ *
+ * Write to GEN_HDR 24 bit register the value: WC[23:8] ,VC[7:6],29h
+ */
+int mipi_dsi_lwrite(struct dsi_cmd_desc *cm, char __iomem *dsi_base)
+{
+	uint32_t hdr = 0;
+	int i = 0;
+
+	if (cm->dlen && cm->payload == 0) {
+		HISI_FB_ERR("NO payload error!\n");
+		return 0;
+	}
+
+	/* fill up payload */
+	for (i = 0; i < cm->dlen; i += 4) {
+		set_reg(dsi_base + MIPIDSI_GEN_PLD_DATA_OFFSET,
+			*((uint32_t *) (cm->payload + i)), 32, 0);
+	}
+
+	/* fill up header */
+	hdr |= DSI_HDR_DTYPE(cm->dtype);
+	hdr |= DSI_HDR_VC(cm->vc);
+	hdr |= DSI_HDR_WC(cm->dlen);
+	set_reg(dsi_base + MIPIDSI_GEN_HDR_OFFSET, hdr, 24, 0);
+
+	return cm->dlen;
+}
+
+void mipi_dsi_max_return_packet_size(struct dsi_cmd_desc *cm,
+				     char __iomem *dsi_base)
+{
+	uint32_t hdr = 0;
+
+	/* fill up header */
+	hdr |= DSI_HDR_DTYPE(cm->dtype);
+	hdr |= DSI_HDR_VC(cm->vc);
+	hdr |= DSI_HDR_WC(cm->dlen);
+	set_reg(dsi_base + MIPIDSI_GEN_HDR_OFFSET, hdr, 24, 0);
+}
+
+uint32_t mipi_dsi_read(uint32_t *out, char __iomem *dsi_base)
+{
+	uint32_t pkg_status;
+	uint32_t try_times = 700;
+
+	do {
+		pkg_status = inp32(dsi_base + MIPIDSI_CMD_PKT_STATUS_OFFSET);
+		if (!(pkg_status & 0x10))
+			break;
+		udelay(50);
+	} while (--try_times);
+
+	*out = inp32(dsi_base + MIPIDSI_GEN_PLD_DATA_OFFSET);
+	if (!try_times)
+		HISI_FB_ERR("mipi_dsi_read timeout\n"
+			    "MIPIDSI_CMD_PKT_STATUS = 0x%x \n"
+			    "MIPIDSI_PHY_STATUS = 0x%x \n",
+			    inp32(dsi_base + MIPIDSI_CMD_PKT_STATUS_OFFSET),
+			    inp32(dsi_base + MIPIDSI_PHY_STATUS_OFFSET));
+
+	return try_times;
+}
+
+void mipi_dsi_sread(uint32_t *out, char __iomem *dsi_base)
+{
+	unsigned long dw_jiffies = 0;
+	uint32_t tmp = 0;
+
+	dw_jiffies = jiffies + HZ / 2;
+	do {
+		tmp = inp32(dsi_base + MIPIDSI_CMD_PKT_STATUS_OFFSET);
+		if ((tmp & 0x00000040) == 0x00000040) {
+			break;
+		}
+	} while (time_after(dw_jiffies, jiffies));
+
+	dw_jiffies = jiffies + HZ / 2;
+	do {
+		tmp = inp32(dsi_base + MIPIDSI_CMD_PKT_STATUS_OFFSET);
+		if ((tmp & 0x00000040) != 0x00000040) {
+			break;
+		}
+	} while (time_after(dw_jiffies, jiffies));
+
+	*out = inp32(dsi_base + MIPIDSI_GEN_PLD_DATA_OFFSET);
+}
+
+void mipi_dsi_lread(uint32_t *out, char __iomem *dsi_base)
+{
+	/* do something here */
+}
+
+/*
+ * prepare cmd buffer to be txed
+ */
+int mipi_dsi_cmd_add(struct dsi_cmd_desc *cm, char __iomem *dsi_base)
+{
+	int len = 0;
+
+	BUG_ON(cm == NULL);
+	BUG_ON(dsi_base == NULL);
+
+	switch (cm->dtype) {
+	case DTYPE_GEN_WRITE:
+	case DTYPE_GEN_WRITE1:
+	case DTYPE_GEN_WRITE2:
+
+	case DTYPE_DCS_WRITE:
+	case DTYPE_DCS_WRITE1:
+		len = mipi_dsi_swrite(cm, dsi_base);
+		break;
+	case DTYPE_GEN_LWRITE:
+	case DTYPE_DCS_LWRITE:
+	case DTYPE_DSC_LWRITE:
+
+		len = mipi_dsi_lwrite(cm, dsi_base);
+		break;
+	default:
+		HISI_FB_ERR("dtype=%x NOT supported!\n", cm->dtype);
+		break;
+	}
+
+	return len;
+}
+
+int mipi_dsi_cmds_tx(struct dsi_cmd_desc *cmds, int cnt,
+		     char __iomem *dsi_base)
+{
+	struct dsi_cmd_desc *cm = NULL;
+	int i = 0;
+
+	BUG_ON(cmds == NULL);
+	BUG_ON(dsi_base == NULL);
+
+	cm = cmds;
+
+	for (i = 0; i < cnt; i++) {
+		mipi_dsi_cmd_add(cm, dsi_base);
+
+		if (cm->wait) {
+			if (cm->waittype == WAIT_TYPE_US)
+				udelay(cm->wait);
+			else if (cm->waittype == WAIT_TYPE_MS)
+				mdelay(cm->wait);
+			else
+				mdelay(cm->wait * 1000);
+		}
+		cm++;
+	}
+
+	return cnt;
+}
+
+void mipi_dsi_check_0lane_is_ready(char __iomem *dsi_base)
+{
+	unsigned long dw_jiffies = 0;
+	uint32_t tmp = 0;
+
+	dw_jiffies = jiffies + HZ / 10;
+	do {
+		tmp = inp32(dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+		if ((tmp & 0x10) == 0x10) {
+			HISI_FB_INFO("0 lane is stopping state");
+			return;
+		}
+	} while (time_after(dw_jiffies, jiffies));
+
+	HISI_FB_ERR("0 lane is not stopping state:tmp=0x%x", tmp);
+}
+
+static void mipi_dsi_sread_request(struct dsi_cmd_desc *cm,
+				   char __iomem *dsi_base)
+{
+	uint32_t hdr = 0;
+
+	/* fill up header */
+	hdr |= DSI_HDR_DTYPE(cm->dtype);
+	hdr |= DSI_HDR_VC(cm->vc);
+	hdr |= DSI_HDR_DATA1(cm->payload[0]);
+	hdr |= DSI_HDR_DATA2(0);
+	set_reg(dsi_base + MIPIDSI_GEN_HDR_OFFSET, hdr, 24, 0);
+}
+
+static int mipi_dsi_read_add(uint32_t *out, struct dsi_cmd_desc *cm,
+			     char __iomem *dsi_base)
+{
+	unsigned long dw_jiffies = 0;
+	uint32_t pkg_status = 0;
+	uint32_t phy_status = 0;
+	int is_timeout = 1;
+	int ret = 0;
+
+	BUG_ON(cm == NULL);
+	BUG_ON(dsi_base == NULL);
+
+	if (cm->dtype == DTYPE_DCS_READ) {
+		mipi_dsi_sread_request(cm, dsi_base);
+
+		if (!mipi_dsi_read(out, dsi_base)) {
+			HISI_FB_ERR("Read register 0x%X timeout\n",
+				    cm->payload[0]);
+			return -1;
+		}
+	} else if (cm->dtype == DTYPE_GEN_READ1) {
+
+		/*read status register */
+		dw_jiffies = jiffies + HZ;
+		do {
+			pkg_status =
+			    inp32(dsi_base + MIPIDSI_CMD_PKT_STATUS_OFFSET);
+			phy_status =
+			    inp32(dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+			if ((pkg_status & 0x1) == 0x1 && !(phy_status & 0x2)) {
+				is_timeout = 0;
+				break;
+			}
+		} while (time_after(dw_jiffies, jiffies));
+
+		if (is_timeout) {
+			HISI_FB_ERR("mipi_dsi_read timeout :0x%x\n"
+					"MIPIDSI_CMD_PKT_STATUS = 0x%x\n"
+					"MIPIDSI_PHY_STATUS = 0x%x \n"
+					"MIPIDSI_INT_ST1_OFFSET = 0x%x \n",
+					cm->payload[0],
+					inp32(dsi_base + MIPIDSI_CMD_PKT_STATUS_OFFSET),
+					inp32(dsi_base + MIPIDSI_PHY_STATUS_OFFSET),
+					inp32(dsi_base + MIPIDSI_INT_ST1_OFFSET));
+			return -1;
+		}
+		/*send read cmd to fifo */
+		set_reg(dsi_base + MIPIDSI_GEN_HDR_OFFSET,
+			((cm->payload[0] << 8) | cm->dtype), 24, 0);
+
+		is_timeout = 1;
+		/*wait dsi read data */
+		dw_jiffies = jiffies + HZ;
+		do {
+			pkg_status =
+			    inp32(dsi_base + MIPIDSI_CMD_PKT_STATUS_OFFSET);
+			if (!(pkg_status & 0x10)) {
+				is_timeout = 0;
+				break;
+			}
+		} while (time_after(dw_jiffies, jiffies));
+
+		if (is_timeout) {
+			HISI_FB_ERR("mipi_dsi_read timeout :0x%x\n"
+					"MIPIDSI_CMD_PKT_STATUS = 0x%x\n"
+					"MIPIDSI_PHY_STATUS = 0x%x \n"
+					"MIPIDSI_INT_ST1_OFFSET = 0x%x \n",
+					cm->payload[0],
+					inp32(dsi_base + MIPIDSI_CMD_PKT_STATUS_OFFSET),
+					inp32(dsi_base + MIPIDSI_PHY_STATUS_OFFSET),
+					inp32(dsi_base + MIPIDSI_INT_ST1_OFFSET));
+			return -1;
+		}
+		/*get read data */
+		*out = inp32(dsi_base + MIPIDSI_GEN_PLD_DATA_OFFSET);
+	} else {
+		ret = -1;
+		HISI_FB_ERR("dtype=%x NOT supported!\n", cm->dtype);
+	}
+
+	return ret;
+}
+
+int mipi_dsi_cmds_rx(uint32_t *out, struct dsi_cmd_desc *cmds, int cnt,
+		     char __iomem *dsi_base)
+{
+	struct dsi_cmd_desc *cm = NULL;
+	int i = 0;
+	int err_num = 0;
+
+	BUG_ON(cmds == NULL);
+	BUG_ON(dsi_base == NULL);
+
+	cm = cmds;
+
+	for (i = 0; i < cnt; i++) {
+		if (mipi_dsi_read_add(&(out[i]), cm, dsi_base)) {
+			err_num++;
+		}
+
+		if (cm->wait) {
+			if (cm->waittype == WAIT_TYPE_US)
+				udelay(cm->wait);
+			else if (cm->waittype == WAIT_TYPE_MS)
+				mdelay(cm->wait);
+			else
+				mdelay(cm->wait * 1000);
+		}
+		cm++;
+	}
+
+	return err_num;
+}
+
+int mipi_dsi_read_compare(struct mipi_dsi_read_compare_data *data,
+			  char __iomem *dsi_base)
+{
+	uint32_t *read_value = NULL;
+	uint32_t *expected_value = NULL;
+	uint32_t *read_mask = NULL;
+	char **reg_name = NULL;
+	int log_on = 0;
+	struct dsi_cmd_desc *cmds = NULL;
+
+	int cnt = 0;
+	int cnt_not_match = 0;
+	int ret = 0;
+	int i;
+
+	BUG_ON(data == NULL);
+	BUG_ON(dsi_base == NULL);
+
+	read_value = data->read_value;
+	expected_value = data->expected_value;
+	read_mask = data->read_mask;
+	reg_name = data->reg_name;
+	log_on = data->log_on;
+
+	cmds = data->cmds;
+	cnt = data->cnt;
+
+	ret = mipi_dsi_cmds_rx(read_value, cmds, cnt, dsi_base);
+	if (ret) {
+		HISI_FB_ERR("Read error number: %d\n", ret);
+		return cnt;
+	}
+
+	for (i = 0; i < cnt; i++) {
+		if (log_on) {
+			HISI_FB_INFO("Read reg %s: 0x%x, value = 0x%x\n",
+				     reg_name[i], cmds[i].payload[0],
+				     read_value[i]);
+		}
+
+		if (expected_value[i] != (read_value[i] & read_mask[i])) {
+			cnt_not_match++;
+		}
+	}
+
+	return cnt_not_match;
+}
diff --git a/drivers/video/fbdev/hisi/dss/hisi_overlay_cmdlist_utils.c b/drivers/video/fbdev/hisi/dss/hisi_overlay_cmdlist_utils.c
new file mode 100755
index 000000000000..6b1832f49e3c
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_overlay_cmdlist_utils.c
@@ -0,0 +1,1450 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_fb.h"
+
+#define MAX_ITEM_OFFSET	(0x3F)
+#define CMDLIST_ADDR_OFFSET	(0x3FFFF)
+
+#define CMDLIST_HEADER_LEN	(SZ_1K)
+#define CMDLIST_ITEM_LEN	(SZ_8K)
+#define MAX_ITEM_INDEX	(SZ_1K)
+
+dss_cmdlist_data_t *g_cmdlist_data = NULL;
+uint32_t g_online_cmdlist_idxs = 0;
+uint32_t g_offline_cmdlist_idxs = 0;
+
+/* get cmdlist indexs */
+int hisi_cmdlist_get_cmdlist_idxs(dss_overlay_t *pov_req,
+				  uint32_t *cmdlist_pre_idxs,
+				  uint32_t *cmdlist_idxs)
+{
+	uint32_t cmdlist_idxs_temp = 0;
+	int i = 0;
+	int k = 0;
+	int m = 0;
+	dss_layer_t *layer = NULL;
+	dss_wb_layer_t *wb_layer = NULL;
+	dss_overlay_block_t *pov_h_block_infos = NULL;
+	dss_overlay_block_t *pov_h_block = NULL;
+	bool no_ovl_idx = false;
+
+	BUG_ON(pov_req == NULL);
+
+	pov_h_block_infos = (dss_overlay_block_t *) pov_req->ov_block_infos_ptr;
+	for (m = 0; m < pov_req->ov_block_nums; m++) {
+		pov_h_block = &(pov_h_block_infos[m]);
+		for (i = 0; i < pov_h_block->layer_nums; i++) {
+			layer = &(pov_h_block->layer_infos[i]);
+
+			if (layer->need_cap & (CAP_BASE | CAP_DIM | CAP_PURE_COLOR))
+				continue;
+
+			if (layer->chn_idx == DSS_RCHN_V2) {
+				cmdlist_idxs_temp |= (1 << DSS_CMDLIST_V2);
+			} else {
+				cmdlist_idxs_temp |= (1 << layer->chn_idx);
+			}
+		}
+	}
+
+	if (pov_req->wb_enable == 1) {
+		for (k = 0; k < pov_req->wb_layer_nums; k++) {
+			wb_layer = &(pov_req->wb_layer_infos[k]);
+
+			if (wb_layer->chn_idx == DSS_WCHN_W2) {
+				no_ovl_idx = true;
+				cmdlist_idxs_temp |= (1 << DSS_CMDLIST_W2);
+			} else {
+				cmdlist_idxs_temp |= (1 << wb_layer->chn_idx);
+			}
+		}
+	}
+
+	if (no_ovl_idx == false) {
+		cmdlist_idxs_temp |=
+		    (1 << (DSS_CMDLIST_OV0 + pov_req->ovl_idx));
+	}
+
+	if (cmdlist_idxs_temp & (~HISI_DSS_CMDLIST_IDXS_MAX)) {
+		HISI_FB_ERR("cmdlist_idxs_temp(0x%x) is invalid!\n",
+			    cmdlist_idxs_temp);
+		return -EINVAL;
+	}
+
+	if (cmdlist_idxs && cmdlist_pre_idxs) {
+		*cmdlist_idxs = cmdlist_idxs_temp;
+		*cmdlist_pre_idxs &= (~(*cmdlist_idxs));
+	} else if (cmdlist_idxs) {
+		*cmdlist_idxs = cmdlist_idxs_temp;
+	} else if (cmdlist_pre_idxs) {
+		*cmdlist_pre_idxs = cmdlist_idxs_temp;
+	} else {
+		HISI_FB_ERR("cmdlist_idxs && cmdlist_pre_idxs is NULL!\n");
+		return -EINVAL;
+	}
+
+	if (g_debug_ovl_cmdlist) {
+		HISI_FB_INFO("cmdlist_pre_idxs(0x%x), cmdlist_idxs(0x%x).\n",
+			     (cmdlist_pre_idxs ? *cmdlist_pre_idxs : 0),
+			     (cmdlist_idxs ? *cmdlist_idxs : 0));
+	}
+
+	return 0;
+}
+
+uint32_t hisi_cmdlist_get_cmdlist_need_start(struct hisi_fb_data_type *hisifd,
+					     uint32_t cmdlist_idxs)
+{
+	uint32_t cmdlist_idxs_temp = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	cmdlist_idxs_temp = g_offline_cmdlist_idxs;
+	g_offline_cmdlist_idxs |= cmdlist_idxs;
+	cmdlist_idxs_temp = (g_offline_cmdlist_idxs & (~cmdlist_idxs_temp));
+
+	cmdlist_idxs_temp |= (cmdlist_idxs & g_online_cmdlist_idxs);
+	g_online_cmdlist_idxs &= (~cmdlist_idxs_temp);
+
+	if (g_debug_ovl_cmdlist) {
+		HISI_FB_INFO
+		    ("g_online_cmdlist_idxs=0x%x, cmdlist_idxs_need_start=0x%x\n",
+		     g_online_cmdlist_idxs, cmdlist_idxs_temp);
+	}
+
+	return cmdlist_idxs_temp;
+}
+
+/*
+ ** data0: addr0[17:0]
+ ** data1: addr0[17:0] + addr1[5:0]
+ ** data2: addr0[17:0] + addr2[5:0]
+ **
+ ** cnt[1:0]:
+ ** 2'b00:	reg0
+ ** 2'b01: reg0, reg1
+ ** 2'b10: reg0, reg1, reg2
+ ** 2'b11: ((inp32(addr0) & data1) | data2) -> addr0
+ */
+void hisi_cmdlist_set_reg(struct hisi_fb_data_type *hisifd, char __iomem *addr,
+			  uint32_t value, uint8_t bw, uint8_t bs)
+{
+	uint32_t mask = (1 << bw) - 1;
+	dss_cmdlist_node_t *node = NULL;
+	int cmdlist_idx = -1;
+	int index = 0;
+	uint32_t new_addr = 0;
+	uint32_t old_addr = 0;
+	int condition = 0;
+
+	BUG_ON(addr == NULL);
+	BUG_ON(hisifd == NULL);
+
+	cmdlist_idx = hisifd->cmdlist_idx;
+	BUG_ON((cmdlist_idx < 0) || (cmdlist_idx >= HISI_DSS_CMDLIST_MAX));
+
+	node =
+	    list_entry(hisifd->cmdlist_data->cmdlist_head_temp[cmdlist_idx].prev,
+	    	dss_cmdlist_node_t, list_node);
+	BUG_ON(node == NULL);
+
+	if (node->node_type == CMDLIST_NODE_NOP) {
+		HISI_FB_ERR("can't set register value to NOP node!");
+		return;
+	}
+
+	index = node->item_index;
+	new_addr = (uint32_t) (addr - hisifd->dss_base + hisifd->dss_base_phy);
+	new_addr = (new_addr >> 2) & CMDLIST_ADDR_OFFSET;
+	old_addr = node->list_item[index].reg_addr.ul32 & CMDLIST_ADDR_OFFSET;
+	condition = (((new_addr - old_addr) < MAX_ITEM_OFFSET)
+		     && (new_addr >= old_addr));
+
+	if (bw != 32) {
+		if (node->item_flag != 0)
+			index++;
+
+		node->list_item[index].reg_addr.bits.add0 = new_addr;
+		node->list_item[index].data0 = value;
+		node->list_item[index].data1 = ~(mask << bs);
+		node->list_item[index].data2 = (mask & value) << bs;
+		node->list_item[index].reg_addr.bits.cnt = 3;
+		node->item_flag = 3;
+	} else {
+		if (node->item_flag == 0) {
+			node->list_item[index].reg_addr.bits.add0 = new_addr;
+			node->list_item[index].data0 = value;
+			node->list_item[index].reg_addr.bits.cnt = 0;
+			node->item_flag = 1;
+		} else if (node->item_flag == 1 && condition) {
+			node->list_item[index].reg_addr.bits.add1 =
+			    new_addr - old_addr;
+			node->list_item[index].data1 = value;
+			node->list_item[index].reg_addr.bits.cnt = 1;
+			node->item_flag = 2;
+		} else if (node->item_flag == 2 && condition) {
+			node->list_item[index].reg_addr.bits.add2 =
+			    new_addr - old_addr;
+			node->list_item[index].data2 = value;
+			node->list_item[index].reg_addr.bits.cnt = 2;
+			node->item_flag = 3;
+		} else {
+			index++;
+			node->list_item[index].reg_addr.bits.add0 = new_addr;
+			node->list_item[index].data0 = value;
+			node->list_item[index].reg_addr.bits.cnt = 0;
+			node->item_flag = 1;
+		}
+	}
+
+	BUG_ON(index >= MAX_ITEM_INDEX);
+
+	node->item_index = index;
+	node->list_header->total_items.bits.count = node->item_index + 1;
+}
+
+/*
+ ** flush cache for cmdlist, make sure that
+ ** cmdlist has writen through to memory before config register
+ */
+void hisi_cmdlist_flush_cache(struct hisi_fb_data_type *hisifd,
+			      struct ion_client *ion_client,
+			      uint32_t cmdlist_idxs)
+{
+	uint32_t i = 0;
+	uint32_t cmdlist_idxs_temp = 0;
+	dss_cmdlist_node_t *node = NULL;
+	dss_cmdlist_node_t *_node_ = NULL;
+	struct sg_table *table = NULL;
+	struct list_head *cmdlist_heads = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	cmdlist_idxs_temp = cmdlist_idxs;
+
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if ((cmdlist_idxs_temp & 0x1) == 0x1) {
+			cmdlist_heads =
+			    &(hisifd->cmdlist_data->cmdlist_head_temp[i]);
+			if (!cmdlist_heads) {
+				HISI_FB_ERR("cmdlist_data is NULL!\n");
+				continue;
+			}
+
+			list_for_each_entry_safe_reverse(node, _node_,
+							 cmdlist_heads,
+							 list_node) {
+
+				if (!node->header_ion_handle) {
+					HISI_FB_ERR
+					    ("header_ion_handle is NULL!\n");
+				} else {
+					table = ion_sg_table(ion_client,
+							 node->header_ion_handle);
+					BUG_ON(table == NULL);
+					dma_sync_sg_for_device(NULL, table->sgl,
+							       table->nents,
+							       DMA_TO_DEVICE);
+				}
+
+				if (!node->item_ion_handle) {
+					HISI_FB_ERR("item_ion_handle is NULL!\n");
+				} else {
+					table = ion_sg_table(ion_client,
+							 node->item_ion_handle);
+					BUG_ON(table == NULL);
+					dma_sync_sg_for_device(NULL, table->sgl,
+							       table->nents,
+							       DMA_TO_DEVICE);
+				}
+			}
+		}
+
+		cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+	}
+}
+
+dss_cmdlist_node_t *hisi_cmdlist_node_alloc(struct ion_client *ion_client)
+{
+	int ret = 0;
+	dss_cmdlist_node_t *node = NULL;
+	size_t header_len = CMDLIST_HEADER_LEN;
+	size_t item_len = CMDLIST_ITEM_LEN;
+
+	BUG_ON(ion_client == NULL);
+
+	node =
+	    (dss_cmdlist_node_t *) kzalloc(sizeof(dss_cmdlist_node_t),
+					   GFP_KERNEL);
+	if (IS_ERR(node)) {
+		HISI_FB_ERR("failed to alloc dss_cmdlist_node_t!");
+		goto err_alloc_cmdlist_node;
+	}
+
+	memset(node, 0, sizeof(dss_cmdlist_node_t));
+
+	/*alloc buffer for header */
+	node->header_ion_handle =
+	    ion_alloc(ion_client, header_len, 0, ION_HEAP(ION_GRALLOC_HEAP_ID), 0);
+	if (IS_ERR(node->header_ion_handle)) {
+		HISI_FB_ERR("failed to ion_alloc node->header_ion_handle!");
+		goto err_header_ion_handle;
+	}
+
+	node->list_header =
+	    (cmd_header_t *) ion_map_kernel(ion_client,
+					    node->header_ion_handle);
+	if (!node->list_header) {
+		HISI_FB_ERR("failed to ion_map_kernel node->list_header!");
+		goto err_header_ion_map;
+	}
+	memset(node->list_header, 0, header_len);
+
+	ret =
+	    ion_phys(ion_client, node->header_ion_handle, &node->header_phys,
+		     &header_len);
+	if (ret < 0) {
+		HISI_FB_ERR("failed to ion_phys node->header_phys!");
+		goto err_header_ion_phys;
+	}
+
+	/*alloc buffer for items */
+	node->item_ion_handle =
+	    ion_alloc(ion_client, item_len, 0, ION_HEAP(ION_GRALLOC_HEAP_ID), 0);
+	if (!node->item_ion_handle) {
+		HISI_FB_ERR("failed to ion_alloc node->item_ion_handle!");
+		goto err_item_ion_handle;
+	}
+
+	node->list_item =
+	    (cmd_item_t *) ion_map_kernel(ion_client, node->item_ion_handle);
+	if (!node->list_item) {
+		HISI_FB_ERR("failed to ion_map_kernel node->list_item!");
+		goto err_item_ion_map;
+	}
+
+	memset(node->list_item, 0, item_len);
+	ret =
+	    ion_phys(ion_client, node->item_ion_handle, &node->item_phys,
+		     &item_len);
+	if (ret < 0) {
+		HISI_FB_ERR("failed to ion_phys node->item_phys!");
+		goto err_item_ion_phys;
+	}
+
+	/* fill node info */
+	node->item_flag = 0;
+	node->item_index = 0;
+
+	node->is_used = 0;
+	node->node_type = CMDLIST_NODE_NONE;
+	return node;
+
+ err_item_ion_phys:
+	if (node->item_ion_handle)
+		ion_unmap_kernel(ion_client, node->item_ion_handle);
+ err_item_ion_map:
+	if (node->item_ion_handle)
+		ion_free(ion_client, node->item_ion_handle);
+ err_item_ion_handle:
+ err_header_ion_phys:
+	if (node->header_ion_handle)
+		ion_unmap_kernel(ion_client, node->header_ion_handle);
+ err_header_ion_map:
+	if (node->header_ion_handle)
+		ion_free(ion_client, node->header_ion_handle);
+ err_header_ion_handle:
+	if (node)
+		kfree(node);
+ err_alloc_cmdlist_node:
+	return NULL;
+}
+
+void hisi_cmdlist_node_free(struct ion_client *ion_client,
+			    dss_cmdlist_node_t *node)
+{
+	BUG_ON(ion_client == NULL);
+	BUG_ON(node == NULL);
+
+	if (node->header_ion_handle) {
+		ion_unmap_kernel(ion_client, node->header_ion_handle);
+		ion_free(ion_client, node->header_ion_handle);
+	}
+
+	if (node->item_ion_handle) {
+		ion_unmap_kernel(ion_client, node->item_ion_handle);
+		ion_free(ion_client, node->item_ion_handle);
+	}
+
+	kfree(node);
+	node = NULL;
+}
+
+static dss_cmdlist_node_t *hisi_cmdlist_get_free_node(dss_cmdlist_node_t *
+						      node[], int *id)
+{
+	int i = 0;
+
+	for (i = 0; i < HISI_DSS_CMDLIST_NODE_MAX; i++) {
+		if (node[i] && (node[i]->is_used == 0)) {
+			node[i]->is_used = 1;
+			*id = i + 1;
+			return node[i];
+		}
+	}
+
+	return NULL;
+}
+
+int hisi_cmdlist_add_nop_node(struct hisi_fb_data_type *hisifd,
+			      uint32_t cmdlist_idxs, int pending, int reserved)
+{
+	dss_cmdlist_node_t *node = NULL;
+	uint32_t cmdlist_idxs_temp = 0;
+	int i = 0;
+	int id = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	cmdlist_idxs_temp = cmdlist_idxs;
+
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if ((cmdlist_idxs_temp & 0x1) == 0x1) {
+			node =
+			    hisi_cmdlist_get_free_node(hisifd->cmdlist_data->
+						       cmdlist_nodes_temp[i],
+						       &id);
+			if (!node) {
+				HISI_FB_ERR
+				    ("failed to hisi_get_free_cmdlist_node!\n");
+				return -EINVAL;
+			}
+
+			node->list_header->flag.bits.id = id;
+			node->list_header->flag.bits.nop = 0x1;
+			node->list_header->flag.bits.pending =
+			    pending ? 0x1 : 0x0;
+			node->list_header->flag.bits.valid_flag =
+			    CMDLIST_NODE_VALID;
+			node->list_header->next_list = node->header_phys;
+
+			node->is_used = 1;
+			node->node_type = CMDLIST_NODE_NOP;
+			node->reserved = reserved ? 0x1 : 0x0;
+
+			/*add this nop to list */
+			list_add_tail(&(node->list_node),
+				      &(hisifd->cmdlist_data->cmdlist_head_temp[i]));
+
+			if (node->list_node.prev !=
+			    &(hisifd->cmdlist_data->cmdlist_head_temp[i])) {
+				dss_cmdlist_node_t *pre_node = NULL;
+				pre_node =
+				    list_entry(node->list_node.prev,
+					       dss_cmdlist_node_t, list_node);
+				pre_node->list_header->next_list =
+				    node->header_phys;
+				if (node->list_header->flag.bits.pending == 0x1) {
+					pre_node->reserved = 0x0;
+				}
+
+				pre_node->list_header->flag.bits.task_end = 0x1;
+
+				if (g_debug_ovl_cmdlist) {
+					HISI_FB_DEBUG
+					    ("i = %d, next_list = 0x%x\n", i,
+					     (uint32_t) (node->header_phys));
+				}
+			}
+		}
+
+		cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+	}
+
+	return 0;
+}
+
+int hisi_cmdlist_add_new_node(struct hisi_fb_data_type *hisifd,
+			      uint32_t cmdlist_idxs, int pending, int task_end,
+			      int remove, int last, uint32_t wb_type)
+{
+	char __iomem *cmdlist_base = NULL;
+	dss_cmdlist_node_t *node = NULL;
+	uint32_t cmdlist_idxs_temp = 0;
+	int i = 0;
+	int id = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	cmdlist_base = hisifd->dss_base + DSS_CMDLIST_OFFSET;
+	cmdlist_idxs_temp = cmdlist_idxs;
+
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if ((cmdlist_idxs_temp & 0x1) == 0x1) {
+			node =
+			    hisi_cmdlist_get_free_node(hisifd->cmdlist_data->
+						       cmdlist_nodes_temp[i],
+						       &id);
+			if (!node) {
+				HISI_FB_ERR
+				    ("failed to hisi_get_free_cmdnode!\n");
+				return -EINVAL;
+			}
+
+			/*fill the header and item info */
+			node->list_header->flag.bits.id = id;
+			node->list_header->flag.bits.pending =
+			    pending ? 0x1 : 0x0;
+
+			if (i < DSS_CMDLIST_W0) {
+				node->list_header->flag.bits.event_list =
+				    remove ? 0x8 : (0xE + i);
+			} else if (i < DSS_CMDLIST_OV0) {
+				node->list_header->flag.bits.event_list =
+				    remove ? 0x8 : (0x16 + i);
+			} else if (i == DSS_CMDLIST_V2) {
+				node->list_header->flag.bits.event_list =
+				    remove ? 0x8 : 0x16;
+			} else if (i == DSS_CMDLIST_W2) {
+				node->list_header->flag.bits.event_list =
+				    remove ? 0x8 : 0x20;
+			} else {
+				node->list_header->flag.bits.event_list =
+				    remove ? 0x8 : (0xE + i);
+			}
+
+			node->list_header->flag.bits.task_end =
+			    task_end ? 0x1 : 0x0;
+			node->list_header->flag.bits.last = last ? 0x1 : 0x0;
+
+			node->list_header->flag.bits.valid_flag =
+			    CMDLIST_NODE_VALID;
+			node->list_header->flag.bits.exec = 0x1;
+			node->list_header->list_addr = node->item_phys;
+			node->list_header->next_list = node->item_phys;
+
+			node->is_used = 1;
+			node->node_type = CMDLIST_NODE_FRAME;
+			node->item_flag = 0;
+			node->reserved = 0;
+
+			/* add this nop to list */
+			list_add_tail(&(node->list_node),
+				      &(hisifd->cmdlist_data->cmdlist_head_temp[i]));
+
+			if (node->list_node.prev !=
+			    &(hisifd->cmdlist_data->cmdlist_head_temp[i])) {
+				dss_cmdlist_node_t *pre_node = NULL;
+				pre_node =
+				    list_entry(node->list_node.prev,
+					       dss_cmdlist_node_t, list_node);
+				pre_node->list_header->next_list =
+				    node->header_phys;
+				pre_node->reserved = 0x0;
+				if (g_debug_ovl_cmdlist) {
+					HISI_FB_DEBUG
+					    ("i = %d, next_list = 0x%x\n", i,
+					     (uint32_t) node->header_phys);
+				}
+			}
+		}
+
+		cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+	}
+
+	return 0;
+}
+
+int hisi_cmdlist_del_all_node(struct list_head *cmdlist_heads)
+{
+	dss_cmdlist_node_t *node = NULL;
+	dss_cmdlist_node_t *_node_ = NULL;
+
+	BUG_ON(cmdlist_heads == NULL);
+
+	list_for_each_entry_safe(node, _node_, cmdlist_heads, list_node) {
+		if (node->reserved != 0x1) {
+			list_del(&node->list_node);
+
+			memset(node->list_header, 0, CMDLIST_HEADER_LEN);
+			memset(node->list_item, 0, CMDLIST_ITEM_LEN);
+
+			node->item_index = 0;
+			node->item_flag = 0;
+			node->node_type = CMDLIST_NODE_NONE;
+			node->is_used = 0;
+		}
+	}
+
+	return 0;
+}
+
+int hisi_cmdlist_check_cmdlist_state(struct hisi_fb_data_type *hisifd,
+				     uint32_t cmdlist_idxs)
+{
+	char __iomem *cmdlist_base = NULL;
+	uint32_t offset = 0;
+	uint32_t tmp = 0;
+	uint32_t cmdlist_idxs_temp = 0;
+	int i = 0;
+	int delay_count = 0;
+	bool is_timeout = true;
+	int ret = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	cmdlist_base = hisifd->dss_base + DSS_CMDLIST_OFFSET;
+	offset = 0x40;
+	cmdlist_idxs_temp = cmdlist_idxs;
+
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if ((cmdlist_idxs_temp & 0x1) == 0x1) {
+			while (1) {
+				tmp =
+				    inp32(cmdlist_base + CMDLIST_CH0_STATUS +
+					  i * offset);
+				if (((tmp & 0xF) == 0x0) || delay_count > 5000) {
+					is_timeout =
+					    (delay_count > 5000) ? true : false;
+					delay_count = 0;
+					break;
+				} else {
+					udelay(1);
+					++delay_count;
+				}
+			}
+
+			if (is_timeout) {
+				HISI_FB_ERR
+				    ("cmdlist_ch%d not in idle state,ints=0x%x !\n",
+				     i, tmp);
+				ret = -1;
+			}
+		}
+
+		cmdlist_idxs_temp = (cmdlist_idxs_temp >> 1);
+	}
+
+	return ret;
+}
+
+/*
+ ** stop the pending state for one new frame
+ ** if the current cmdlist status is e_status_wait.
+ */
+int hisi_cmdlist_exec(struct hisi_fb_data_type *hisifd, uint32_t cmdlist_idxs)
+{
+	char __iomem *cmdlist_base = NULL;
+	uint32_t offset = 0;
+	uint32_t tmp = 0;
+	uint32_t cmdlist_idxs_temp = 0;
+	int i = 0;
+	int delay_count = 0;
+	bool is_timeout = true;
+
+	BUG_ON(hisifd == NULL);
+
+	cmdlist_base = hisifd->dss_base + DSS_CMDLIST_OFFSET;
+	offset = 0x40;
+	cmdlist_idxs_temp = cmdlist_idxs;
+
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if ((cmdlist_idxs_temp & 0x1) == 0x1) {
+			while (1) {
+				tmp =
+				    inp32(cmdlist_base + CMDLIST_CH0_STATUS +
+					  i * offset);
+				if (((tmp & 0xF) == 0x0) || delay_count > 500) {
+					is_timeout =
+					    (delay_count > 500) ? true : false;
+					delay_count = 0;
+					break;
+				} else {
+					udelay(1);
+					++delay_count;
+				}
+			}
+
+			if (is_timeout) {
+				HISI_FB_ERR
+				    ("cmdlist_ch%d not in idle state,ints=0x%x !\n",
+				     i, tmp);
+				if (g_debug_ovl_cmdlist) {
+					hisi_cmdlist_dump_all_node(hisifd, NULL,
+								   cmdlist_idxs);
+				}
+			}
+		}
+
+		cmdlist_idxs_temp = (cmdlist_idxs_temp >> 1);
+	}
+	return 0;
+}
+
+/*
+ **start cmdlist.
+ **it will set cmdlist into pending state.
+ */
+extern uint32_t g_dss_module_ovl_base[DSS_MCTL_IDX_MAX][MODULE_OVL_MAX];
+int hisi_cmdlist_config_start(struct hisi_fb_data_type *hisifd, int mctl_idx,
+			      uint32_t cmdlist_idxs, uint32_t wb_compose_type)
+{
+	char __iomem *mctl_base = NULL;
+	char __iomem *cmdlist_base = NULL;
+	dss_cmdlist_node_t *cmdlist_node = NULL;
+	uint32_t offset = 0;
+	uint32_t list_addr = 0;
+	uint32_t cmdlist_idxs_temp = 0;
+	int i = 0;
+	int temp = 0;
+	int status_temp = 0;
+	int ints_temp = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	mctl_base =
+	    hisifd->dss_base +
+	    g_dss_module_ovl_base[mctl_idx][MODULE_MCTL_BASE];
+	cmdlist_base = hisifd->dss_base + DSS_CMDLIST_OFFSET;
+	offset = 0x40;
+	cmdlist_idxs_temp = cmdlist_idxs;
+
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if ((cmdlist_idxs_temp & 0x1) == 0x1) {
+			status_temp =
+			    inp32(cmdlist_base + CMDLIST_CH0_STATUS +
+				  i * offset);
+			ints_temp =
+			    inp32(cmdlist_base + CMDLIST_CH0_INTS + i * offset);
+
+			if (mctl_idx >= DSS_MCTL2) {
+				cmdlist_node =
+				    list_first_entry(&(hisifd->cmdlist_data_tmp
+						      [wb_compose_type]->cmdlist_head_temp[i]),
+						     dss_cmdlist_node_t,
+						     list_node);
+			} else {
+				cmdlist_node =
+				    list_first_entry(&(hisifd->cmdlist_data->
+				    		 cmdlist_head_temp[i]),
+						     dss_cmdlist_node_t,
+						     list_node);
+			}
+
+			list_addr = cmdlist_node->header_phys;
+			if (g_debug_ovl_cmdlist) {
+				HISI_FB_INFO
+				    ("list_addr:0x%x, i=%d, ints_temp=0x%x\n",
+				     list_addr, i, ints_temp);
+			}
+
+			temp |= (1 << i);
+			outp32(cmdlist_base + CMDLIST_ADDR_MASK_EN, BIT(i));
+			if (g_debug_set_reg_val) {
+				HISI_FB_INFO("writel: [%p] = 0x%lx\n",
+					     cmdlist_base +
+					     CMDLIST_ADDR_MASK_EN, BIT(i));
+			}
+
+			set_reg(cmdlist_base + CMDLIST_CH0_CTRL + i*offset,
+					mctl_idx, 3, 2);
+			if (mctl_idx <= DSS_MCTL1) {
+				set_reg(cmdlist_base + CMDLIST_CH0_CTRL + i*offset, 0x1, 1, 6);
+			} else {
+				set_reg(cmdlist_base + CMDLIST_CH0_CTRL + i*offset, 0x0, 1, 6);
+			}
+
+			set_reg(cmdlist_base + CMDLIST_CH0_STAAD + i*offset,
+					list_addr, 32, 0);
+			set_reg(cmdlist_base + CMDLIST_CH0_CTRL + i*offset, 0x1, 1, 0);
+			if ((mctl_idx <= DSS_MCTL1)
+			    && ((ints_temp & 0x2) == 0x2)) {
+				set_reg(cmdlist_base + CMDLIST_SWRST, 0x1, 1, i);
+			}
+
+			if (mctl_idx >= DSS_MCTL2) {
+				if (((status_temp & 0xF) == 0x0)
+				    || ((ints_temp & 0x2) == 0x2)) {
+					set_reg(cmdlist_base + CMDLIST_SWRST,
+						0x1, 1, i);
+				} else {
+					HISI_FB_INFO
+					    ("i=%d, status_temp=0x%x, ints_temp=0x%x\n",
+					     i, status_temp, ints_temp);
+				}
+			}
+		}
+		cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+	}
+
+	outp32(cmdlist_base + CMDLIST_ADDR_MASK_DIS, temp);
+	if (g_debug_set_reg_val) {
+		HISI_FB_INFO("writel: [%p] = 0x%x\n",
+			     cmdlist_base + CMDLIST_ADDR_MASK_DIS, temp);
+	}
+
+	if (mctl_idx >= DSS_MCTL2) {
+		set_reg(mctl_base + MCTL_CTL_ST_SEL, 0x1, 1, 0);
+		set_reg(mctl_base + MCTL_CTL_SW_ST, 0x1, 1, 0);
+	}
+
+	return 0;
+}
+
+void hisi_cmdlist_config_mif_reset(struct hisi_fb_data_type *hisifd,
+				   dss_overlay_t *pov_req,
+				   uint32_t cmdlist_idxs, int mctl_idx)
+{
+	char __iomem *dss_base = NULL;
+	char __iomem *tmp_base = NULL;
+
+	uint32_t cmdlist_idxs_temp = 0;
+	int delay_count = 0;
+	bool is_timeout = true;
+	int i = 0;
+	int j = 0;
+	int mif_sub_ch_nums = 4;
+	int tmp = 0;
+	int mif_nums_max = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_req == NULL);
+
+	dss_base = hisifd->dss_base;
+
+	if (mctl_idx <= DSS_MCTL1) {
+		mif_nums_max = DSS_WCHN_W0;
+	} else {
+		mif_nums_max = DSS_CHN_MAX;
+	}
+
+	if (mctl_idx == DSS_MCTL5) {
+		for (i = DSS_RCHN_V2; i < DSS_CHN_MAX_DEFINE; i++) {
+			is_timeout = false;
+
+			while (1) {
+				for (j = 1; j <= mif_sub_ch_nums; j++) {
+					tmp |=
+					    inp32(dss_base + DSS_MIF_OFFSET +
+						  MIF_STAT1 +
+						  0x10 * (i * mif_sub_ch_nums +j));
+				}
+
+				if (((tmp & 0x1f) == 0x0) || delay_count > 500) {
+					is_timeout =
+					    (delay_count > 500) ? true : false;
+					delay_count = 0;
+					break;
+				} else {
+					udelay(10);
+					++delay_count;
+				}
+			}
+
+			if (is_timeout) {
+				HISI_FB_ERR("mif_ch%d MIF_STAT1=0x%x !\n", i,
+					    tmp);
+			}
+		}
+
+		tmp_base = hisifd->dss_module.mif_ch_base[DSS_RCHN_V2];
+		if (tmp_base) {
+			set_reg(tmp_base + MIF_CTRL0, 0x0, 1, 0);
+		}
+
+		tmp_base = hisifd->dss_module.mif_ch_base[DSS_WCHN_W2];
+		if (tmp_base) {
+			set_reg(tmp_base + MIF_CTRL0, 0x0, 1, 0);
+		}
+	} else {
+		cmdlist_idxs_temp = cmdlist_idxs;
+		for (i = 0; i < mif_nums_max; i++) {
+			if ((cmdlist_idxs_temp & 0x1) == 0x1) {
+				is_timeout = false;
+
+				while (1) {
+					for (j = 1; j <= mif_sub_ch_nums; j++) {
+						tmp |=
+						    inp32(dss_base + DSS_MIF_OFFSET + MIF_STAT1 +
+							  0x10 * (i * mif_sub_ch_nums + j));
+					}
+					if (((tmp & 0x1f) == 0x0)
+					    || delay_count > 500) {
+						is_timeout =
+						    (delay_count > 500) ? true : false;
+						delay_count = 0;
+						break;
+					} else {
+						udelay(10);
+						++delay_count;
+					}
+				}
+
+				if (is_timeout) {
+					HISI_FB_ERR
+					    ("mif_ch%d MIF_STAT1=0x%x !\n", i, tmp);
+				}
+			}
+
+			cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+		}
+
+		cmdlist_idxs_temp = cmdlist_idxs;
+		for (i = 0; i < mif_nums_max; i++) {
+			if ((cmdlist_idxs_temp & 0x1) == 0x1) {
+				tmp_base = hisifd->dss_module.mif_ch_base[i];
+				if (tmp_base) {
+					set_reg(tmp_base + MIF_CTRL0, 0x0, 1,
+						0);
+				}
+			}
+			cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+		}
+	}
+	mdelay(5);
+
+	if (mctl_idx == DSS_MCTL5) {
+		tmp_base = hisifd->dss_module.mif_ch_base[DSS_RCHN_V2];
+		if (tmp_base) {
+			set_reg(tmp_base + MIF_CTRL0, 0x1, 1, 0);
+		}
+
+		tmp_base = hisifd->dss_module.mif_ch_base[DSS_WCHN_W2];
+		if (tmp_base) {
+			set_reg(tmp_base + MIF_CTRL0, 0x1, 1, 0);
+		}
+	} else {
+		cmdlist_idxs_temp = cmdlist_idxs;
+		for (i = 0; i < mif_nums_max; i++) {
+			if ((cmdlist_idxs_temp & 0x1) == 0x1) {
+				tmp_base = hisifd->dss_module.mif_ch_base[i];
+				if (tmp_base) {
+					set_reg(tmp_base + MIF_CTRL0, 0x1, 1,
+						0);
+				}
+			}
+			cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+		}
+	}
+}
+
+void hisi_cmdlist_config_reset(struct hisi_fb_data_type *hisifd,
+			       dss_overlay_t *pov_req, uint32_t cmdlist_idxs)
+{
+	char __iomem *dss_base = NULL;
+	char __iomem *cmdlist_base = NULL;
+	char __iomem *tmp_base = NULL;
+	struct hisi_panel_info *pinfo = NULL;
+
+	uint32_t offset = 0;
+	uint32_t cmdlist_idxs_temp = 0;
+	int i = 0;
+	int ovl_idx = 0;
+	int mctl_idx = 0;
+	int ints_temp = 0;
+	int start_sel = 0;
+	uint32_t start_sel_temp = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_req == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	dss_base = hisifd->dss_base;
+	cmdlist_base = dss_base + DSS_CMDLIST_OFFSET;
+	ovl_idx = pov_req->ovl_idx;
+	pinfo = &(hisifd->panel_info);
+
+	if (cmdlist_idxs == 0) return;
+
+	mctl_idx = ovl_idx;
+	if (pov_req->wb_compose_type == DSS_WB_COMPOSE_COPYBIT) {
+		mctl_idx = DSS_MCTL5;
+	}
+
+	offset = 0x40;
+	cmdlist_idxs_temp = HISI_DSS_CMDLIST_IDXS_MAX;
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if ((cmdlist_idxs_temp & 0x1) == 0x1) {
+			ints_temp =
+			    inp32(cmdlist_base + CMDLIST_CH0_INTS + i * offset);
+			start_sel =
+			    inp32(cmdlist_base + CMDLIST_CH0_CTRL + i * offset);
+
+			if (((ints_temp & 0x2) == 0x2)
+			    && ((start_sel & 0x1c) == 0)) {
+				set_reg(cmdlist_base + CMDLIST_CH0_CTRL + i * offset, 0x6, 3, 2);
+				start_sel_temp |= (1 << i);
+			}
+		}
+		cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+	}
+
+	tmp_base = hisifd->dss_module.mctl_base[mctl_idx];
+	if (tmp_base) {
+		set_reg(tmp_base + MCTL_CTL_CLEAR, 0x1, 1, 0);
+	}
+
+	hisi_cmdlist_config_mif_reset(hisifd, pov_req, cmdlist_idxs, mctl_idx);
+	cmdlist_idxs_temp = start_sel_temp;
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if ((cmdlist_idxs_temp & 0x1) == 0x1) {
+			set_reg(cmdlist_base + CMDLIST_CH0_CTRL + i * offset, mctl_idx, 3, 2);
+		}
+		cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+	}
+
+	if (mctl_idx >= DSS_MCTL2) {
+		offset = 0x40;
+		cmdlist_idxs_temp = cmdlist_idxs;
+		for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+			if ((cmdlist_idxs_temp & 0x1) == 0x1) {
+				set_reg(cmdlist_base + CMDLIST_CH0_CTRL +
+					i * offset, 0x6, 3, 2);
+				set_reg(cmdlist_base + CMDLIST_CH0_CTRL +
+					i * offset, 0x0, 1, 0);
+			}
+			cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+		}
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+	return;
+}
+
+int hisi_cmdlist_config_stop(struct hisi_fb_data_type *hisifd,
+			     uint32_t cmdlist_pre_idxs)
+{
+	dss_overlay_t *pov_req = NULL;
+	char __iomem *cmdlist_base = NULL;
+	int i = 0;
+	uint32_t tmp = 0;
+	uint32_t offset = 0;
+	int ret = 0;
+
+	BUG_ON(hisifd == NULL);
+	pov_req = &(hisifd->ov_req);
+	cmdlist_base = hisifd->dss_base + DSS_CMDLIST_OFFSET;
+	offset = 0x40;
+
+	ret =
+	    hisi_cmdlist_add_new_node(hisifd, cmdlist_pre_idxs, 0, 1, 1, 1, 0);
+	if (ret != 0) {
+		HISI_FB_ERR("fb%d, hisi_cmdlist_add_new_node err:%d \n",
+			    hisifd->index, ret);
+		goto err_return;
+	}
+
+	for (i = 0; i < DSS_WCHN_W0; i++) {
+		tmp = (0x1 << i);
+		hisifd->cmdlist_idx = i;
+
+		if ((cmdlist_pre_idxs & tmp) == tmp) {
+			hisifd->set_reg(hisifd,
+					hisifd->dss_module.mctl_base[pov_req->
+								     ovl_idx] +
+					MCTL_CTL_MUTEX_RCH0 + i * 0x4, 0, 32,
+					0);
+			hisifd->set_reg(hisifd, cmdlist_base + CMDLIST_CH0_CTRL + i * offset, 0x6, 3, 2);
+		}
+	}
+
+	return 0;
+
+ err_return:
+	return ret;
+}
+
+void hisi_dss_cmdlist_qos_on(struct hisi_fb_data_type *hisifd)
+{
+	char __iomem *cmdlist_base = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	cmdlist_base = hisifd->dss_base + DSS_CMDLIST_OFFSET;
+	set_reg(cmdlist_base + CMDLIST_CTRL, 0x3, 2, 4);
+}
+
+void hisi_dump_cmdlist_node_items(cmd_item_t *item, uint32_t count)
+{
+	uint32_t index = 0;
+	uint32_t addr = 0;
+
+	for (index = 0; index < count; index++) {
+		addr = item[index].reg_addr.bits.add0;
+		addr = addr & CMDLIST_ADDR_OFFSET;
+		addr = addr << 2;
+		HISI_FB_INFO
+		    ("set addr:0x%x value:0x%x add1:0x%x value:0x%x "
+		     "add2:0x%x value:0x%x \n",
+		     addr, item[index].data0,
+		     item[index].reg_addr.bits.add1 << 2, item[index].data1,
+		     item[index].reg_addr.bits.add2 << 2, item[index].data2);
+	}
+}
+
+static void hisi_dump_cmdlist_content(struct list_head *cmdlist_head,
+				      char *filename, uint32_t addr)
+{
+	dss_cmdlist_node_t *node = NULL;
+	dss_cmdlist_node_t *_node_ = NULL;
+
+	BUG_ON(cmdlist_head == NULL);
+	BUG_ON(filename == NULL);
+
+	if (g_dump_cmdlist_content == 0)
+		return;
+
+	HISI_FB_INFO("%s\n", filename);
+
+	list_for_each_entry_safe(node, _node_, cmdlist_head, list_node) {
+		if (node->header_phys == addr) {
+			hisifb_save_file(filename, (char *)(node->list_header),
+					 CMDLIST_HEADER_LEN);
+		}
+
+		if (node->item_phys == addr) {
+			hisifb_save_file(filename, (char *)(node->list_item),
+					 CMDLIST_ITEM_LEN);
+		}
+	}
+}
+
+static void hisi_dump_cmdlist_one_node(struct list_head *cmdlist_head,
+				       uint32_t cmdlist_idx)
+{
+	dss_cmdlist_node_t *node = NULL;
+	dss_cmdlist_node_t *_node_ = NULL;
+	uint32_t count = 0;
+	int i = 0;
+	char filename[256] = { 0 };
+
+	BUG_ON(cmdlist_head == NULL);
+
+	list_for_each_entry_safe(node, _node_, cmdlist_head, list_node) {
+		if (node->node_type == CMDLIST_NODE_NOP) {
+			HISI_FB_INFO("node type = NOP node\n");
+		} else if (node->node_type == CMDLIST_NODE_FRAME) {
+			HISI_FB_INFO("node type = Frame node\n");
+		}
+
+		HISI_FB_INFO
+		    ("\t qos  | flag | pending | tast_end | last  | event_list | list_addr  | next_list  | count | id | is_used | reserved | cmdlist_idx\n");
+		HISI_FB_INFO
+		    ("\t ------+---------+------------+------------+------------+------------\n");
+		HISI_FB_INFO
+		    ("\t 0x%2x | 0x%2x |0x%6x | 0x%5x | 0x%3x | 0x%8x | 0x%8x | 0x%8x | 0x%3x | 0x%2x | 0x%2x | 0x%2x | 0x%2x\n",
+		     node->list_header->flag.bits.qos,
+		     node->list_header->flag.bits.valid_flag,
+		     node->list_header->flag.bits.pending,
+		     node->list_header->flag.bits.task_end,
+		     node->list_header->flag.bits.last,
+		     node->list_header->flag.bits.event_list,
+		     node->list_header->list_addr, node->list_header->next_list,
+		     node->list_header->total_items.bits.count,
+		     node->list_header->flag.bits.id, node->is_used,
+		     node->reserved, cmdlist_idx);
+
+		if (i == 0) {
+			snprintf(filename, 256,
+				 "/data/dssdump/list_start_0x%x.txt",
+				 (uint32_t) node->header_phys);
+			hisi_dump_cmdlist_content(cmdlist_head, filename,
+						  node->header_phys);
+		}
+#if 0
+		if ((node->list_header->next_list != 0x0) &&
+		    (node->list_header->next_list != 0xFFFFFFFF)) {
+			snprintf(filename, 256,
+				 "/data/dssdump/next_list_0x%x.txt",
+				 node->list_header->next_list);
+			hisi_dump_cmdlist_content(cmdlist_head, filename,
+						  node->list_header->next_list);
+		}
+
+		if ((node->list_header->list_addr != 0x0) &&
+		    (node->list_header->list_addr != 0xFFFFFFFF)) {
+			snprintf(filename, 256,
+				 "/data/dssdump/list_addr_0x%x.txt",
+				 node->list_header->list_addr);
+			hisi_dump_cmdlist_content(cmdlist_head, filename,
+						  node->list_header->list_addr);
+		}
+#endif
+		count = node->list_header->total_items.bits.count;
+		hisi_dump_cmdlist_node_items(node->list_item, count);
+
+		i++;
+	}
+}
+
+int hisi_cmdlist_dump_all_node(struct hisi_fb_data_type *hisifd,
+			       dss_overlay_t *pov_req, uint32_t cmdlist_idxs)
+{
+	int i = 0;
+	uint32_t cmdlist_idxs_temp = 0;
+	uint32_t wb_compose_type = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	if (pov_req) {
+		if (pov_req->wb_enable)
+			wb_compose_type = pov_req->wb_compose_type;
+	}
+
+	cmdlist_idxs_temp = cmdlist_idxs;
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if (0x1 == (cmdlist_idxs_temp & 0x1)) {
+			if (pov_req && pov_req->wb_enable) {
+				hisi_dump_cmdlist_one_node(&(hisifd->cmdlist_data_tmp
+							    [wb_compose_type]->cmdlist_head_temp[i]), i);
+			} else {
+				hisi_dump_cmdlist_one_node(&
+							   (hisifd->cmdlist_data->cmdlist_head_temp[i]), i);
+			}
+		}
+		cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+	}
+
+	return 0;
+}
+
+int hisi_cmdlist_del_node(struct hisi_fb_data_type *hisifd,
+			  dss_overlay_t *pov_req, uint32_t cmdlist_idxs)
+{
+	int i = 0;
+	uint32_t cmdlist_idxs_temp = 0;
+	uint32_t wb_compose_type = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	if (pov_req) {
+		if (pov_req->wb_enable)
+			wb_compose_type = pov_req->wb_compose_type;
+	}
+
+	cmdlist_idxs_temp = cmdlist_idxs;
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if ((cmdlist_idxs_temp & 0x1) == 0x1) {
+			if (pov_req && pov_req->wb_enable) {
+				hisi_cmdlist_del_all_node(&(hisifd->cmdlist_data_tmp
+							   [wb_compose_type]->cmdlist_head_temp[i]));
+			} else {
+				hisi_cmdlist_del_all_node(&
+							  (hisifd->cmdlist_data->cmdlist_head_temp[i]));
+			}
+		}
+		cmdlist_idxs_temp = (cmdlist_idxs_temp >> 1);
+	}
+
+	return 0;
+}
+
+static dss_cmdlist_data_t *hisi_cmdlist_data_alloc(struct hisi_fb_data_type
+						   *hisifd)
+{
+	int i = 0;
+	int j = 0;
+	dss_cmdlist_data_t *cmdlist_data = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	cmdlist_data =
+	    (dss_cmdlist_data_t *) kmalloc(sizeof(dss_cmdlist_data_t),
+					   GFP_ATOMIC);
+	if (cmdlist_data) {
+		memset(cmdlist_data, 0, sizeof(dss_cmdlist_data_t));
+	} else {
+		HISI_FB_ERR("failed to kmalloc cmdlist_data!\n");
+		return NULL;
+	}
+
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		INIT_LIST_HEAD(&(cmdlist_data->cmdlist_head_temp[i]));
+
+		for (j = 0; j < HISI_DSS_CMDLIST_NODE_MAX; j++) {
+			cmdlist_data->cmdlist_nodes_temp[i][j] =
+			    hisi_cmdlist_node_alloc(hisifd->ion_client);
+			if (cmdlist_data->cmdlist_nodes_temp[i][j] == NULL) {
+				HISI_FB_ERR
+				    ("failed to hisi_cmdlist_node_alloc!\n");
+				kfree(cmdlist_data);
+				return NULL;
+			}
+		}
+	}
+
+	return cmdlist_data;
+}
+
+static void hisi_cmdlist_data_free(struct hisi_fb_data_type *hisifd,
+				   dss_cmdlist_data_t *cmdlist_data)
+{
+	int i = 0;
+	int j = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(cmdlist_data == NULL);
+
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		for (j = 0; j < HISI_DSS_CMDLIST_NODE_MAX; j++) {
+			hisi_cmdlist_node_free(hisifd->ion_client,
+					       hisifd->cmdlist_data->cmdlist_nodes_temp[i][j]);
+		}
+	}
+}
+
+static dss_cmdlist_info_t *hisi_cmdlist_info_alloc(struct hisi_fb_data_type
+						   *hisifd)
+{
+	int i = 0;
+	dss_cmdlist_info_t *cmdlist_info = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	cmdlist_info =
+	    (dss_cmdlist_info_t *) kmalloc(sizeof(dss_cmdlist_info_t), GFP_ATOMIC);
+	if (cmdlist_info) {
+		memset(cmdlist_info, 0, sizeof(dss_cmdlist_info_t));
+	} else {
+		HISI_FB_ERR("failed to kmalloc cmdlist_info!\n");
+		return NULL;
+	}
+
+	sema_init(&(cmdlist_info->cmdlist_wb_common_sem), 1);
+
+	for (i = 0; i < WB_TYPE_MAX; i++) {
+		sema_init(&(cmdlist_info->cmdlist_wb_sem[i]), 1);
+		init_waitqueue_head(&(cmdlist_info->cmdlist_wb_wq[i]));
+		cmdlist_info->cmdlist_wb_done[i] = 0;
+		cmdlist_info->cmdlist_wb_flag[i] = 0;
+	}
+
+	return cmdlist_info;
+}
+
+static dss_copybit_info_t *hisi_copybit_info_alloc(struct hisi_fb_data_type
+						   *hisifd)
+{
+	dss_copybit_info_t *copybit_info = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	copybit_info =
+	    (dss_copybit_info_t *) kmalloc(sizeof(dss_copybit_info_t),
+					   GFP_ATOMIC);
+	if (copybit_info) {
+		memset(copybit_info, 0, sizeof(dss_copybit_info_t));
+	} else {
+		HISI_FB_ERR("failed to kmalloc copybit_info!\n");
+		return NULL;
+	}
+
+	sema_init(&(copybit_info->copybit_sem), 1);
+
+	init_waitqueue_head(&(copybit_info->copybit_wq));
+	copybit_info->copybit_done = 0;
+
+	return copybit_info;
+}
+
+void hisi_cmdlist_data_get_online(struct hisi_fb_data_type *hisifd)
+{
+	int tmp = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	tmp = (hisifd->frame_count + 1) % HISI_DSS_CMDLIST_DATA_MAX;
+	hisifd->cmdlist_data = hisifd->cmdlist_data_tmp[tmp];
+	hisi_cmdlist_del_node(hisifd, NULL, HISI_DSS_CMDLIST_IDXS_MAX);
+
+	tmp = hisifd->frame_count % HISI_DSS_CMDLIST_DATA_MAX;
+	hisifd->cmdlist_data = hisifd->cmdlist_data_tmp[tmp];
+	hisi_cmdlist_del_node(hisifd, NULL, HISI_DSS_CMDLIST_IDXS_MAX);
+}
+
+int hisi_cmdlist_init(struct hisi_fb_data_type *hisifd)
+{
+	int ret = 0;
+	int i = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	for (i = 0; i < HISI_DSS_CMDLIST_BLOCK_MAX; i++) {
+		hisifd->ov_block_rects[i] =
+		    (dss_rect_t *) kmalloc(sizeof(dss_rect_t), GFP_ATOMIC);
+		if (!hisifd->ov_block_rects[i]) {
+			HISI_FB_ERR("ov_block_rects[%d] failed to alloc!", i);
+			return -EINVAL;
+		}
+	}
+
+	if (hisifd->index == AUXILIARY_PANEL_IDX) {
+		hisifd->cmdlist_data_tmp[0] = hisi_cmdlist_data_alloc(hisifd);
+		hisifd->cmdlist_data_tmp[1] = hisi_cmdlist_data_alloc(hisifd);
+		hisifd->cmdlist_info = hisi_cmdlist_info_alloc(hisifd);
+		hisifd->copybit_info = hisi_copybit_info_alloc(hisifd);
+	} else {
+		if (hisifd->index == PRIMARY_PANEL_IDX
+		    || (hisifd->index == EXTERNAL_PANEL_IDX
+			&& !hisifd->panel_info.fake_hdmi)) {
+			for (i = 0; i < HISI_DSS_CMDLIST_DATA_MAX; i++) {
+				hisifd->cmdlist_data_tmp[i] =
+				    hisi_cmdlist_data_alloc(hisifd);
+			}
+		}
+	}
+
+	hisifd->cmdlist_data = hisifd->cmdlist_data_tmp[0];
+	hisifd->cmdlist_idx = -1;
+
+	return ret;
+}
+
+int hisi_cmdlist_deinit(struct hisi_fb_data_type *hisifd)
+{
+	int i = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	for (i = 0; i < HISI_DSS_CMDLIST_BLOCK_MAX; i++) {
+		if (hisifd->ov_block_rects[i]) {
+			kfree(hisifd->ov_block_rects[i]);
+			hisifd->ov_block_rects[i] = NULL;
+		}
+	}
+
+	for (i = 0; i < HISI_DSS_CMDLIST_DATA_MAX; i++) {
+		if (hisifd->cmdlist_data_tmp[i]) {
+			hisi_cmdlist_data_free(hisifd,
+					       hisifd->cmdlist_data_tmp[i]);
+			kfree(hisifd->cmdlist_data_tmp[i]);
+			hisifd->cmdlist_data_tmp[i] = NULL;
+		}
+	}
+
+	if (hisifd->index == AUXILIARY_PANEL_IDX) {
+		if (hisifd->cmdlist_info) {
+			kfree(hisifd->cmdlist_info);
+			hisifd->cmdlist_info = NULL;
+		}
+
+		if (hisifd->copybit_info) {
+			kfree(hisifd->copybit_info);
+			hisifd->copybit_info = NULL;
+		}
+	}
+
+	return 0;
+}
diff --git a/drivers/video/fbdev/hisi/dss/hisi_overlay_cmdlist_utils.h b/drivers/video/fbdev/hisi/dss/hisi_overlay_cmdlist_utils.h
new file mode 100755
index 000000000000..5f5d8c0fd506
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_overlay_cmdlist_utils.h
@@ -0,0 +1,249 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+#ifndef _CMD_LIST_UTILS_H_
+#define _CMD_LIST_UTILS_H_
+#include "hisi_overlay_utils_hi3660.h"
+
+#define HISI_DSS_CMDLIST_DATA_MAX	(3)
+#define HISI_DSS_CMDLIST_NODE_MAX	(32)
+#define HISI_DSS_CMDLIST_BLOCK_MAX	(32)
+
+#define HISI_DSS_SUPPORT_DPP_MODULE_BIT(module) \
+	(BIT(module) & HISI_DSS_DPP_MAX_SUPPORT_BIT)
+
+enum dpp_module_idx {
+	DPP_MODULE_POST_SCF = 0,
+	DPP_MODULE_DBUF,
+	DPP_MODULE_SBL,
+	DPP_MODULE_ACM,
+	DPP_MODULE_ACE,
+	DPP_MODULE_LCP_IGM,
+	DPP_MODULE_LCP_GMP,
+	DPP_MODULE_LCP_XCC,
+	DPP_MODULE_GAMA,
+	DPP_MODULE_DITHER,
+	DPP_MODULE_IFBC,
+	DPP_MODULE_MAX
+};
+
+enum wb_type {
+	WB_TYPE_WCH0,
+	WB_TYPE_WCH1,
+	WB_TYPE_WCH2,
+	WB_TYPE_WCH0_WCH1,
+
+	WB_TYPE_MAX,
+};
+
+enum dss_cmdlist_idx {
+	DSS_CMDLIST_NONE = -1,
+	DSS_CMDLIST_D2 = 0,
+	DSS_CMDLIST_D3,
+	DSS_CMDLIST_V0,
+	DSS_CMDLIST_G0,
+	DSS_CMDLIST_V1,
+	DSS_CMDLIST_G1,
+	DSS_CMDLIST_D0,
+	DSS_CMDLIST_D1,
+
+	DSS_CMDLIST_W0,
+	DSS_CMDLIST_W1,
+
+	DSS_CMDLIST_OV0,
+	DSS_CMDLIST_OV1,
+	DSS_CMDLIST_OV2,
+	DSS_CMDLIST_OV3,
+
+	DSS_CMDLIST_V2,
+	DSS_CMDLIST_W2,
+	DSS_CMDLIST_MAX,
+};
+
+typedef union {
+	struct {
+		uint32_t exec:1;
+		uint32_t last:1;
+		uint32_t nop:1;
+		uint32_t interrupt:1;
+		uint32_t pending:1;
+		uint32_t id:10;
+		uint32_t event_list:6;
+		uint32_t qos:1;
+		uint32_t task_end:1;
+		uint32_t reserved:1;
+		uint32_t valid_flag:8;
+	} bits;
+	uint32_t ul32;
+} cmd_flag_t;
+
+typedef union {
+	struct {
+		uint32_t count:14;
+		uint32_t reserved:18;
+	} bits;
+	uint32_t ul32;
+} total_items_t;
+
+typedef union {
+	struct {
+		uint32_t add0:18;
+		uint32_t add1:6;
+		uint32_t add2:6;
+		uint32_t cnt:2;
+	} bits;
+	uint32_t ul32;
+} reg_addr_t;
+
+typedef struct cmd_item {
+	reg_addr_t reg_addr;
+	uint32_t data0;
+	uint32_t data1;
+	uint32_t data2;
+} cmd_item_t;
+
+typedef struct cmd_header {
+	cmd_flag_t flag;
+	uint32_t next_list;
+	total_items_t total_items;
+	uint32_t list_addr;
+} cmd_header_t;
+
+enum dss_cmdlist_node_valid {
+	CMDLIST_NODE_INVALID = 0x0,
+	CMDLIST_NODE_VALID = 0xA5,
+};
+
+enum dss_cmdlist_node_type {
+	CMDLIST_NODE_NONE = 0x0,
+	CMDLIST_NODE_NOP = 0x1,
+	CMDLIST_NODE_FRAME = 0x2,
+};
+
+enum dss_cmdlist_status {
+	e_status_idle = 0x0,
+	e_status_wait = 0x1,
+	e_status_other,
+};
+
+/*
+ ** for normal node,all variable should be filled.
+ ** for NOP node, just the list_header,header_ion_handle, list_node, node_flag should be filled.
+ ** node_type must be CMDLIST_NODE_NOP when it is NOP node.
+ ** And item_ion_handle in NOP node should be NULL.
+ */
+typedef struct dss_cmdlist_node {
+	struct list_head list_node;
+
+	struct ion_handle *header_ion_handle;
+	ion_phys_addr_t header_phys;
+	cmd_header_t *list_header;
+
+	struct ion_handle *item_ion_handle;
+	ion_phys_addr_t item_phys;
+	cmd_item_t *list_item;
+
+	uint32_t item_index;
+	int item_flag;
+	uint32_t node_type;
+	int is_used;
+	int reserved;
+} dss_cmdlist_node_t;
+
+typedef struct dss_cmdlist_heads {
+	struct list_head cmdlist_head;
+
+	dss_cmdlist_node_t *cmdlist_nodes[HISI_DSS_CMDLIST_NODE_MAX];
+} dss_cmdlist_heads_t;
+
+typedef struct dss_cmdlist_data {
+	dss_cmdlist_heads_t *cmdlist_heads[HISI_DSS_CMDLIST_MAX];
+	struct list_head cmdlist_head_temp[HISI_DSS_CMDLIST_MAX];
+	dss_cmdlist_node_t
+	    *cmdlist_nodes_temp[HISI_DSS_CMDLIST_MAX]
+	    [HISI_DSS_CMDLIST_NODE_MAX];
+} dss_cmdlist_data_t;
+
+typedef struct dss_cmdlist_info {
+	struct semaphore cmdlist_wb_common_sem;
+	struct semaphore cmdlist_wb_sem[WB_TYPE_MAX];
+	wait_queue_head_t cmdlist_wb_wq[WB_TYPE_MAX];
+	uint32_t cmdlist_wb_done[WB_TYPE_MAX];
+	uint32_t cmdlist_wb_flag[WB_TYPE_MAX];
+} dss_cmdlist_info_t;
+
+typedef struct dss_copybit_info {
+	struct semaphore copybit_sem;
+	wait_queue_head_t copybit_wq;
+	uint32_t copybit_flag;
+	uint32_t copybit_done;
+} dss_copybit_info_t;
+
+typedef struct dss_wb_info {
+	uint32_t to_be_continued;
+	uint32_t cmdlist_idxs;
+	uint32_t wb_compose_type;
+	uint32_t mctl_idx;
+} dss_wb_info_t;
+
+extern dss_cmdlist_data_t *g_cmdlist_data;
+
+/******************************************************************************
+ ** FUNCTIONS PROTOTYPES
+ */
+void hisi_cmdlist_set_reg(struct hisi_fb_data_type *hisifd,
+			  char __iomem *addr, uint32_t value, uint8_t bw,
+			  uint8_t bs);
+void hisi_cmdlist_flush_cache(struct hisi_fb_data_type *hisifd,
+			      struct ion_client *ion_client,
+			      uint32_t cmdlist_idxs);
+
+dss_cmdlist_node_t *hisi_cmdlist_node_alloc(struct ion_client *ion_client);
+void hisi_cmdlist_node_free(struct ion_client *ion_client,
+			    dss_cmdlist_node_t *node);
+
+uint32_t hisi_cmdlist_get_cmdlist_need_start(struct hisi_fb_data_type *hisifd,
+					     uint32_t cmdlist_idxs);
+
+int hisi_cmdlist_get_cmdlist_idxs(dss_overlay_t *pov_req,
+				  uint32_t *cmdlist_pre_idxs,
+				  uint32_t *cmdlist_idxs);
+void hisi_cmdlist_data_get_online(struct hisi_fb_data_type *hisifd);
+
+int hisi_cmdlist_add_nop_node(struct hisi_fb_data_type *hisifd,
+			      uint32_t cmdlist_idxs, int pending, int reserved);
+int hisi_cmdlist_add_new_node(struct hisi_fb_data_type *hisifd,
+			      uint32_t cmdlist_idxs, int pending, int task_end,
+			      int remove, int last, uint32_t wb_type);
+int hisi_cmdlist_del_all_node(struct list_head *cmdlist_heads);
+
+int hisi_cmdlist_config_start(struct hisi_fb_data_type *hisifd, int mctl_idx,
+			      uint32_t cmdlist_idxs, uint32_t wb_compose_type);
+int hisi_cmdlist_config_stop(struct hisi_fb_data_type *hisifd,
+			     uint32_t cmdlist_idxs);
+void hisi_cmdlist_config_reset(struct hisi_fb_data_type *hisifd,
+			       dss_overlay_t *pov_req, uint32_t cmdlist_idxs);
+
+int hisi_cmdlist_del_node(struct hisi_fb_data_type *hisifd,
+			  dss_overlay_t *pov_req, uint32_t cmdlist_idxs);
+int hisi_cmdlist_check_cmdlist_state(struct hisi_fb_data_type *hisifd,
+				     uint32_t cmdlist_idxs);
+
+int hisi_cmdlist_exec(struct hisi_fb_data_type *hisifd, uint32_t cmdlist_idxs);
+void hisi_dss_cmdlist_qos_on(struct hisi_fb_data_type *hisifd);
+int hisi_cmdlist_dump_all_node(struct hisi_fb_data_type *hisifd,
+			       dss_overlay_t *pov_req, uint32_t cmdlist_idxs);
+
+int hisi_cmdlist_init(struct hisi_fb_data_type *hisifd);
+int hisi_cmdlist_deinit(struct hisi_fb_data_type *hisifd);
+
+#endif
-- 
2.12.0-rc0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 6/8] fb: hisilicon: Add framebuffer driver for hi3660 SoC
@ 2017-02-07  2:35     ` cailiwei
  0 siblings, 0 replies; 15+ messages in thread
From: cailiwei @ 2017-02-07  2:35 UTC (permalink / raw)
  To: linux-fbdev, linux-kernel, b.zolnierkie, guodong.xu
  Cc: suzhuangluan, dengqingshan, xuhongtao8, zhengwanchun,
	shizongxuan, cailiwei

From: Levy-Cai <cailiwei@hisilicon.com>

Add framebuffer driver for hi3660 SoC, this driver include lcd
driver & Hdmi adv7533/adv7535 driver, support lcd display at
1080p@60 and hdmi display at 1080p@60.

Signed-off-by: cailiwei <cailiwei@hisilicon.com>
---
 drivers/video/fbdev/hisi/dss/hisi_fb_utils.c       |  249 ++++
 drivers/video/fbdev/hisi/dss/hisi_fb_vsync.c       |  680 +++++++++
 drivers/video/fbdev/hisi/dss/hisi_mipi_dsi_host.c  |  401 ++++++
 .../fbdev/hisi/dss/hisi_overlay_cmdlist_utils.c    | 1450 ++++++++++++++++++++
 .../fbdev/hisi/dss/hisi_overlay_cmdlist_utils.h    |  249 ++++
 5 files changed, 3029 insertions(+)
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_fb_utils.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_fb_vsync.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_mipi_dsi_host.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_overlay_cmdlist_utils.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_overlay_cmdlist_utils.h

diff --git a/drivers/video/fbdev/hisi/dss/hisi_fb_utils.c b/drivers/video/fbdev/hisi/dss/hisi_fb_utils.c
new file mode 100755
index 000000000000..3c7965716890
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_fb_utils.c
@@ -0,0 +1,249 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_fb.h"
+#include "hisi_overlay_utils.h"
+#if defined (CONFIG_HISI_PERIDVFS)
+#include "peri_volt_poll.h"
+#endif
+
+#define MAX_BUF 60
+void set_reg(char __iomem *addr, uint32_t val, uint8_t bw, uint8_t bs)
+{
+	uint32_t mask = (1UL << bw) - 1UL;
+	uint32_t tmp = 0;
+
+	tmp = inp32(addr);
+	tmp &= ~(mask << bs);
+
+	outp32(addr, tmp | ((val & mask) << bs));
+
+	if (g_debug_set_reg_val) {
+		HISI_FB_INFO("writel: [%p] = 0x%x\n", addr,
+			     tmp | ((val & mask) << bs));
+	}
+}
+
+uint32_t set_bits32(uint32_t old_val, uint32_t val, uint8_t bw, uint8_t bs)
+{
+	uint32_t mask = (1UL << bw) - 1UL;
+	uint32_t tmp = 0;
+
+	tmp = old_val;
+	tmp &= ~(mask << bs);
+
+	return (tmp | ((val & mask) << bs));
+}
+
+void hisifb_set_reg(struct hisi_fb_data_type *hisifd,
+		    char __iomem *addr, uint32_t val, uint8_t bw, uint8_t bs)
+{
+	set_reg(addr, val, bw, bs);
+}
+
+bool is_dss_idle_enable(void)
+{
+	return ((g_enable_dss_idle = 1) ? true : false);
+}
+
+uint32_t get_panel_xres(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd = NULL);
+
+	return ((hisifd->resolution_rect.w >
+		 0) ? hisifd->resolution_rect.w : hisifd->panel_info.xres);
+}
+
+uint32_t get_panel_yres(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd = NULL);
+
+	return ((hisifd->resolution_rect.h >
+		 0) ? hisifd->resolution_rect.h : hisifd->panel_info.yres);
+}
+
+uint32_t hisifb_line_length(int index, uint32_t xres, int bpp)
+{
+	return ALIGN_UP(xres * bpp, DMA_STRIDE_ALIGN);
+}
+
+void hisifb_get_timestamp(struct timeval *tv)
+{
+	struct timespec ts;
+
+	ktime_get_ts(&ts);
+	tv->tv_sec = ts.tv_sec;
+	tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+}
+
+uint32_t hisifb_timestamp_diff(struct timeval *lasttime,
+			       struct timeval *curtime)
+{
+	uint32_t ret;
+	ret = (curtime->tv_usec >= lasttime->tv_usec) ?
+	    curtime->tv_usec - lasttime->tv_usec :
+	    1000000 - (lasttime->tv_usec - curtime->tv_usec);
+
+	return ret;
+}
+
+void hisifb_save_file(char *filename, char *buf, uint32_t buf_len)
+{
+	ssize_t write_len = 0;
+	struct file *fd = NULL;
+	mm_segment_t old_fs;
+	loff_t pos = 0;
+
+	BUG_ON(filename = NULL);
+	BUG_ON(buf = NULL);
+
+	fd = filp_open(filename, O_CREAT | O_RDWR, 0644);
+	if (IS_ERR(fd)) {
+		HISI_FB_ERR("filp_open returned:filename %s, error %ld\n",
+			    filename, PTR_ERR(fd));
+		return;
+	}
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	write_len = vfs_write(fd, (char __user *)buf, buf_len, &pos);
+
+	pos = 0;
+	set_fs(old_fs);
+	filp_close(fd, NULL);
+}
+
+int hisifb_ctrl_on(struct hisi_fb_data_type *hisifd)
+{
+	struct hisi_fb_panel_data *pdata = NULL;
+	int ret = 0;
+
+	BUG_ON(hisifd = NULL);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata = NULL);
+
+	if (pdata->on) {
+		ret = pdata->on(hisifd->pdev);
+	}
+
+	hisifb_vsync_resume(hisifd);
+	hisi_overlay_on(hisifd, false);
+
+	if (hisifd->panel_info.esd_enable) {
+		hrtimer_start(&hisifd->esd_ctrl.esd_hrtimer,
+			      ktime_set(ESD_CHECK_TIME_PERIOD / 1000,
+					(ESD_CHECK_TIME_PERIOD % 1000) *
+					1000000), HRTIMER_MODE_REL);
+	}
+
+	return ret;
+}
+
+int hisifb_ctrl_off(struct hisi_fb_data_type *hisifd)
+{
+	struct hisi_fb_panel_data *pdata = NULL;
+	int ret = 0;
+
+	BUG_ON(hisifd = NULL);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata = NULL);
+
+	if (hisifd->panel_info.esd_enable) {
+		hrtimer_cancel(&hisifd->esd_ctrl.esd_hrtimer);
+	}
+
+	hisifb_vsync_suspend(hisifd);
+	hisi_overlay_off(hisifd);
+
+	if (pdata->off) {
+		ret = pdata->off(hisifd->pdev);
+	}
+
+	if ((hisifd->index = PRIMARY_PANEL_IDX) ||
+	    (hisifd->index = EXTERNAL_PANEL_IDX)) {
+
+		hisifb_layerbuf_unlock(hisifd,
+				       &(hisifd->buf_sync_ctrl.layerbuf_list));
+	}
+
+	return ret;
+}
+
+int hisifb_ctrl_dss_clk_rate_set(struct fb_info *info, void __user *argp)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+	dss_clk_rate_t dss_clk_rate;
+
+	if (NULL = info) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	hisifd = (struct hisi_fb_data_type *)info->par;
+	if (NULL = hisifd) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	if (hisifd->index != PRIMARY_PANEL_IDX) {
+		HISI_FB_ERR("fb%d, not supported!\n", hisifd->index);
+		return -EINVAL;
+	}
+
+	if (NULL = argp) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	if (hisifd->core_clk_upt_support = 0) {
+		HISI_FB_DEBUG("no support core_clk_upt\n");
+		return ret;
+	}
+
+	ret = copy_from_user(&dss_clk_rate, argp, sizeof(dss_clk_rate_t));
+	if (ret) {
+		HISI_FB_ERR("copy_from_user failed!ret=%d.", ret);
+		return ret;
+	}
+
+	down(&hisifd->blank_sem);
+
+	if (!hisifd->panel_power_on) {
+		HISI_FB_DEBUG("fb%d, panel power off!\n", hisifd->index);
+		ret = -EPERM;
+		goto err_out;
+	}
+
+	ret = set_dss_clk_rate(hisifd, dss_clk_rate);
+
+ err_out:
+	up(&hisifd->blank_sem);
+
+	return ret;
+}
+
+/*lint +e665, +e514, +e84, +e886, +e846, +e778*/
+void hisifb_sysfs_attrs_add(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd = NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	if (hisifd->sysfs_attrs_append_fnc) {
+		/* hisifd->sysfs_attrs_append_fnc(hisifd, &dev_attr_lcd_model.attr); */
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+}
diff --git a/drivers/video/fbdev/hisi/dss/hisi_fb_vsync.c b/drivers/video/fbdev/hisi/dss/hisi_fb_vsync.c
new file mode 100755
index 000000000000..3778ac0b4b2c
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_fb_vsync.c
@@ -0,0 +1,680 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat"
+#include "hisi_fb.h"
+
+/*
+ ** /sys/class/graphics/fb0/vsync_event
+ */
+#if defined(CONFIG_HISI_FB_VSYNC_THREAD)
+#define VSYNC_TIMEOUT_MSEC (100)
+#endif
+#define VSYNC_CTRL_EXPIRE_COUNT	(4)
+
+#ifdef CONFIG_REPORT_VSYNC
+extern void mali_kbase_pm_report_vsync(int);
+#endif
+extern int mipi_dsi_ulps_cfg(struct hisi_fb_data_type *hisifd, int enable);
+extern bool hisi_dss_check_reg_reload_status(struct hisi_fb_data_type *hisifd);
+
+void hisifb_frame_updated(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd = NULL);
+
+	if (hisifd->vsync_ctrl.vsync_report_fnc) {
+		atomic_inc(&(hisifd->vsync_ctrl.buffer_updated));
+	}
+}
+
+void hisifb_vsync_isr_handler(struct hisi_fb_data_type *hisifd)
+{
+	struct hisifb_vsync *vsync_ctrl = NULL;
+	struct hisi_fb_panel_data *pdata = NULL;
+	int buffer_updated = 0;
+	ktime_t pre_vsync_timestamp;
+
+	BUG_ON(hisifd = NULL);
+	vsync_ctrl = &(hisifd->vsync_ctrl);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata = NULL);
+
+	pre_vsync_timestamp = vsync_ctrl->vsync_timestamp;
+	vsync_ctrl->vsync_timestamp = ktime_get();
+	wake_up_interruptible_all(&(vsync_ctrl->vsync_wait));
+
+	if (hisifd->panel_info.vsync_ctrl_type != VSYNC_CTRL_NONE) {
+		spin_lock(&vsync_ctrl->spin_lock);
+		if (vsync_ctrl->vsync_ctrl_expire_count) {
+			vsync_ctrl->vsync_ctrl_expire_count--;
+			if (vsync_ctrl->vsync_ctrl_expire_count = 0)
+				schedule_work(&vsync_ctrl->vsync_ctrl_work);
+		}
+		spin_unlock(&vsync_ctrl->spin_lock);
+	}
+
+	if (vsync_ctrl->vsync_report_fnc) {
+		if (hisifd->vsync_ctrl.vsync_enabled) {
+			buffer_updated +			    atomic_dec_return(&(vsync_ctrl->buffer_updated));
+		} else {
+			buffer_updated = 1;
+		}
+
+		if (buffer_updated < 0) {
+			atomic_cmpxchg(&(vsync_ctrl->buffer_updated),
+				       buffer_updated, 1);
+		} else {
+			vsync_ctrl->vsync_report_fnc(buffer_updated);
+		}
+	}
+
+	if (g_debug_online_vsync) {
+		HISI_FB_INFO("fb%d, VSYNC=%llu, time_diff=%llu.\n",
+			     hisifd->index,
+			     ktime_to_ns(hisifd->vsync_ctrl.vsync_timestamp),
+			     (ktime_to_ns(hisifd->vsync_ctrl.vsync_timestamp) -
+			      ktime_to_ns(pre_vsync_timestamp)));
+	}
+}
+
+static int vsync_timestamp_changed(struct hisi_fb_data_type *hisifd,
+				   ktime_t prev_timestamp)
+{
+	BUG_ON(hisifd = NULL);
+	return !ktime_equal(prev_timestamp, hisifd->vsync_ctrl.vsync_timestamp);
+}
+
+#if defined(CONFIG_HISI_FB_VSYNC_THREAD)
+static int wait_for_vsync_thread(void *data)
+{
+	struct hisi_fb_data_type *hisifd = (struct hisi_fb_data_type *)data;
+	ktime_t prev_timestamp;
+	int ret = 0;
+
+	while (!kthread_should_stop()) {
+		prev_timestamp = hisifd->vsync_ctrl.vsync_timestamp;
+		ret +		    wait_event_interruptible_timeout(hisifd->vsync_ctrl.
+						     vsync_wait,
+						     vsync_timestamp_changed
+						     (hisifd, prev_timestamp)
+						     && hisifd->vsync_ctrl.
+						     vsync_enabled,
+						     msecs_to_jiffies
+						     (VSYNC_TIMEOUT_MSEC));
+
+		/*if (ret = 0) {
+		   HISI_FB_ERR("wait vsync timeout!");
+		   return -ETIMEDOUT;
+		   }
+		*/
+
+		if (ret > 0) {
+			char *envp[2];
+			char buf[64];
+			/* fb%d_VSYNC=%llu */
+			snprintf(buf, sizeof(buf), "VSYNC=%llu",
+				 ktime_to_ns(hisifd->vsync_ctrl.
+					     vsync_timestamp));
+			envp[0] = buf;
+			envp[1] = NULL;
+			kobject_uevent_env(&hisifd->pdev->dev.kobj, KOBJ_CHANGE,
+					   envp);
+		}
+	}
+
+	return 0;
+}
+#else
+static ssize_t vsync_show_event(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	ssize_t ret = -1;
+	int vsync_flag = 0;
+	struct fb_info *fbi = NULL;
+	struct hisi_fb_data_type *hisifd = NULL;
+	ktime_t prev_timestamp;
+
+	if (NULL = dev) {
+		HISI_FB_ERR("NULL Pointer.\n");
+		return -1;
+	}
+
+	fbi = dev_get_drvdata(dev);
+	if (NULL = fbi) {
+		HISI_FB_ERR("NULL Pointer.\n");
+		return -1;
+	}
+
+	hisifd = (struct hisi_fb_data_type *)fbi->par;
+	if (NULL = hisifd) {
+		HISI_FB_ERR("NULL Pointer.\n");
+		return -1;
+	}
+
+	if (NULL = buf) {
+		HISI_FB_ERR("NULL Pointer.\n");
+		return -1;
+	}
+
+	prev_timestamp = hisifd->vsync_ctrl.vsync_timestamp;
+
+	/*lint -e666 */
+	ret = wait_event_interruptible(hisifd->vsync_ctrl.vsync_wait,
+				       (vsync_timestamp_changed
+					(hisifd, prev_timestamp)
+					&& hisifd->vsync_ctrl.vsync_enabled));
+	/*lint +e666 */
+	vsync_flag = (vsync_timestamp_changed(hisifd, prev_timestamp) &&
+		      hisifd->vsync_ctrl.vsync_enabled);
+
+	if (vsync_flag) {
+		ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu, xxxxxxEvent=x \n",
+			       ktime_to_ns(hisifd->vsync_ctrl.vsync_timestamp));
+		buf[strlen(buf) + 1] = '\0';
+
+	} else {
+		return -1;
+	}
+
+	return ret;
+}
+
+static ssize_t vsync_timestamp_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	ssize_t ret = -1;
+	struct fb_info *fbi = NULL;
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	if (NULL = dev) {
+		HISI_FB_ERR("NULL Pointer.\n");
+		return -1;
+	}
+
+	fbi = dev_get_drvdata(dev);
+	if (NULL = fbi) {
+		HISI_FB_ERR("NULL Pointer.\n");
+		return -1;
+	}
+
+	hisifd = (struct hisi_fb_data_type *)fbi->par;
+	if (NULL = hisifd) {
+		HISI_FB_ERR("NULL Pointer.\n");
+		return -1;
+	}
+
+	if (NULL = buf) {
+		HISI_FB_ERR("NULL Pointer.\n");
+		return -1;
+	}
+
+	ret = snprintf(buf, PAGE_SIZE, "%llu \n",
+		       ktime_to_ns(hisifd->vsync_ctrl.vsync_timestamp));
+	buf[strlen(buf) + 1] = '\0';
+
+	return ret;
+}
+
+static DEVICE_ATTR(vsync_event, S_IRUGO, vsync_show_event, NULL);
+static DEVICE_ATTR(vsync_timestamp, S_IRUGO, vsync_timestamp_show, NULL);
+#endif
+
+#ifdef CONFIG_FAKE_VSYNC_USED
+enum hrtimer_restart hisifb_fake_vsync(struct hrtimer *timer)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	int fps = 60;
+
+	hisifd +	    container_of(timer, struct hisi_fb_data_type, fake_vsync_hrtimer);
+	BUG_ON(hisifd = NULL);
+
+	if (!hisifd->panel_power_on)
+		goto error;
+
+	if (hisifd->fake_vsync_used && hisifd->vsync_ctrl.vsync_enabled) {
+		hisifd->vsync_ctrl.vsync_timestamp = ktime_get();
+		wake_up_interruptible_all(&hisifd->vsync_ctrl.vsync_wait);
+	}
+
+ error:
+	hrtimer_start(&hisifd->fake_vsync_hrtimer,
+		      ktime_set(0, NSEC_PER_SEC / fps), HRTIMER_MODE_REL);
+
+	return HRTIMER_NORESTART;
+}
+#endif
+
+static void hisifb_vsync_ctrl_workqueue_handler(struct work_struct *work)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct hisifb_vsync *vsync_ctrl = NULL;
+	struct hisi_fb_panel_data *pdata = NULL;
+	unsigned long flags = 0;
+
+	vsync_ctrl = container_of(work, typeof(*vsync_ctrl), vsync_ctrl_work);
+	BUG_ON(vsync_ctrl = NULL);
+	hisifd = vsync_ctrl->hisifd;
+	BUG_ON(hisifd = NULL);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata = NULL);
+
+	down(&(hisifd->blank_sem));
+
+	if (!hisifd->panel_power_on) {
+		HISI_FB_INFO("fb%d, panel is power off!", hisifd->index);
+		up(&(hisifd->blank_sem));
+		return;
+	}
+
+	mutex_lock(&(vsync_ctrl->vsync_lock));
+	if (vsync_ctrl->vsync_ctrl_disabled_set &&
+	    (vsync_ctrl->vsync_ctrl_expire_count = 0) &&
+	    vsync_ctrl->vsync_ctrl_enabled &&
+	    !vsync_ctrl->vsync_enabled
+	    && !vsync_ctrl->vsync_ctrl_offline_enabled) {
+		HISI_FB_DEBUG("fb%d, dss clk off!\n", hisifd->index);
+
+		spin_lock_irqsave(&(vsync_ctrl->spin_lock), flags);
+		if (pdata->vsync_ctrl) {
+			pdata->vsync_ctrl(hisifd->pdev, 0);
+		} else {
+			HISI_FB_ERR("fb%d, vsync_ctrl not supported!\n",
+				    hisifd->index);
+		}
+		vsync_ctrl->vsync_ctrl_enabled = 0;
+		vsync_ctrl->vsync_ctrl_disabled_set = 0;
+		spin_unlock_irqrestore(&(vsync_ctrl->spin_lock), flags);
+
+		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_MIPI_ULPS) {
+			mipi_dsi_ulps_cfg(hisifd, 0);
+		}
+
+		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_VCC_OFF) {
+			if (hisifd->lp_fnc)
+				hisifd->lp_fnc(hisifd, true);
+		}
+
+		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_CLK_OFF) {
+			dpe_inner_clk_disable(hisifd);
+			dpe_common_clk_disable(hisifd);
+			mipi_dsi_clk_disable(hisifd);
+		}
+
+		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_VCC_OFF) {
+			/* dpe_regulator_disable(hisifd); */
+		}
+	}
+	mutex_unlock(&(vsync_ctrl->vsync_lock));
+
+	if (vsync_ctrl->vsync_report_fnc) {
+		vsync_ctrl->vsync_report_fnc(1);
+	}
+
+	up(&(hisifd->blank_sem));
+}
+
+void hisifb_vsync_register(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct hisifb_vsync *vsync_ctrl = NULL;
+#if defined(CONFIG_HISI_FB_VSYNC_THREAD)
+	char name[64] = { 0 };
+#endif
+
+	BUG_ON(pdev = NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd = NULL);
+	vsync_ctrl = &(hisifd->vsync_ctrl);
+	BUG_ON(vsync_ctrl = NULL);
+
+	if (vsync_ctrl->vsync_created)
+		return;
+
+	vsync_ctrl->hisifd = hisifd;
+	vsync_ctrl->vsync_infinite = 0;
+	vsync_ctrl->vsync_enabled = 0;
+	vsync_ctrl->vsync_ctrl_offline_enabled = 0;
+	vsync_ctrl->vsync_timestamp = ktime_get();
+	init_waitqueue_head(&(vsync_ctrl->vsync_wait));
+	spin_lock_init(&(vsync_ctrl->spin_lock));
+	INIT_WORK(&vsync_ctrl->vsync_ctrl_work,
+		  hisifb_vsync_ctrl_workqueue_handler);
+
+	mutex_init(&(vsync_ctrl->vsync_lock));
+
+	atomic_set(&(vsync_ctrl->buffer_updated), 1);
+#ifdef CONFIG_REPORT_VSYNC
+	vsync_ctrl->vsync_report_fnc = mali_kbase_pm_report_vsync;
+#else
+	vsync_ctrl->vsync_report_fnc = NULL;
+#endif
+
+#ifdef CONFIG_FAKE_VSYNC_USED
+	/* hrtimer for fake vsync timing */
+	hisifd->fake_vsync_used = false;
+	hrtimer_init(&hisifd->fake_vsync_hrtimer, CLOCK_MONOTONIC,
+		     HRTIMER_MODE_REL);
+	hisifd->fake_vsync_hrtimer.function = hisifb_fake_vsync;
+	hrtimer_start(&hisifd->fake_vsync_hrtimer,
+		      ktime_set(0, NSEC_PER_SEC / 60), HRTIMER_MODE_REL);
+#endif
+
+#if defined(CONFIG_HISI_FB_VSYNC_THREAD)
+	snprintf(name, sizeof(name), "hisifb%d_vsync", hisifd->index);
+	vsync_ctrl->vsync_thread +	    kthread_run(wait_for_vsync_thread, hisifd, name);
+	if (IS_ERR(vsync_ctrl->vsync_thread)) {
+		vsync_ctrl->vsync_thread = NULL;
+		HISI_FB_ERR("failed to run vsync thread!\n");
+		return;
+	}
+#else
+	if (hisifd->sysfs_attrs_append_fnc) {
+		hisifd->sysfs_attrs_append_fnc(hisifd,
+					       &dev_attr_vsync_event.attr);
+		hisifd->sysfs_attrs_append_fnc(hisifd,
+					       &dev_attr_vsync_timestamp.attr);
+	}
+#endif
+
+	vsync_ctrl->vsync_created = 1;
+}
+
+void hisifb_vsync_unregister(struct platform_device *pdev)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct hisifb_vsync *vsync_ctrl = NULL;
+
+	BUG_ON(pdev = NULL);
+	hisifd = platform_get_drvdata(pdev);
+	BUG_ON(hisifd = NULL);
+	vsync_ctrl = &(hisifd->vsync_ctrl);
+	BUG_ON(vsync_ctrl = NULL);
+
+	if (!vsync_ctrl->vsync_created)
+		return;
+
+#ifdef CONFIG_FAKE_VSYNC_USED
+	hisifd->fake_vsync_used = false;
+	hrtimer_cancel(&hisifd->fake_vsync_hrtimer);
+#endif
+
+#if defined(CONFIG_HISI_FB_VSYNC_THREAD)
+	if (vsync_ctrl->vsync_thread)
+		kthread_stop(vsync_ctrl->vsync_thread);
+#endif
+
+	vsync_ctrl->vsync_created = 0;
+}
+
+void hisifb_set_vsync_activate_state(struct hisi_fb_data_type *hisifd,
+				     bool infinite)
+{
+	struct hisifb_vsync *vsync_ctrl = NULL;
+
+	BUG_ON(hisifd = NULL);
+	vsync_ctrl = &(hisifd->vsync_ctrl);
+	BUG_ON(vsync_ctrl = NULL);
+
+	if (hisifd->panel_info.vsync_ctrl_type = VSYNC_CTRL_NONE)
+		return;
+
+	mutex_lock(&(vsync_ctrl->vsync_lock));
+
+	if (infinite) {
+		vsync_ctrl->vsync_infinite_count += 1;
+	} else {
+		vsync_ctrl->vsync_infinite_count -= 1;
+	}
+
+	if (vsync_ctrl->vsync_infinite_count >= 1) {
+		vsync_ctrl->vsync_infinite = 1;
+	}
+
+	if (vsync_ctrl->vsync_infinite_count = 0) {
+		vsync_ctrl->vsync_infinite = 0;
+	}
+
+	mutex_unlock(&(vsync_ctrl->vsync_lock));
+}
+
+void hisifb_activate_vsync(struct hisi_fb_data_type *hisifd)
+{
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct hisifb_vsync *vsync_ctrl = NULL;
+	unsigned long flags = 0;
+	int clk_enabled = 0;
+
+	BUG_ON(hisifd = NULL);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata = NULL);
+	vsync_ctrl = &(hisifd->vsync_ctrl);
+	BUG_ON(vsync_ctrl = NULL);
+
+	if (hisifd->panel_info.vsync_ctrl_type = VSYNC_CTRL_NONE)
+		return;
+
+	mutex_lock(&(vsync_ctrl->vsync_lock));
+
+	if (vsync_ctrl->vsync_ctrl_enabled = 0) {
+		HISI_FB_DEBUG("fb%d, dss clk on!\n", hisifd->index);
+
+		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_VCC_OFF) {
+			/* dpe_regulator_enable(hisifd); */
+		}
+
+		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_CLK_OFF) {
+			mipi_dsi_clk_enable(hisifd);
+			dpe_common_clk_enable(hisifd);
+			dpe_inner_clk_enable(hisifd);
+		}
+
+		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_VCC_OFF) {
+			if (hisifd->lp_fnc)
+				hisifd->lp_fnc(hisifd, false);
+		}
+
+		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_MIPI_ULPS) {
+			mipi_dsi_ulps_cfg(hisifd, 1);
+		}
+
+		vsync_ctrl->vsync_ctrl_enabled = 1;
+		clk_enabled = 1;
+	} else if (vsync_ctrl->vsync_ctrl_isr_enabled) {
+		clk_enabled = 1;
+		vsync_ctrl->vsync_ctrl_isr_enabled = 0;
+	} else {
+		;
+	}
+
+	spin_lock_irqsave(&(vsync_ctrl->spin_lock), flags);
+	vsync_ctrl->vsync_ctrl_disabled_set = 0;
+	vsync_ctrl->vsync_ctrl_expire_count = 0;
+	if (clk_enabled) {
+		if (pdata->vsync_ctrl) {
+			pdata->vsync_ctrl(hisifd->pdev, 1);
+		} else {
+			HISI_FB_ERR("fb%d, vsync_ctrl not supported!\n",
+				    hisifd->index);
+		}
+	}
+	spin_unlock_irqrestore(&(vsync_ctrl->spin_lock), flags);
+
+	mutex_unlock(&(vsync_ctrl->vsync_lock));
+}
+
+void hisifb_deactivate_vsync(struct hisi_fb_data_type *hisifd)
+{
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct hisifb_vsync *vsync_ctrl = NULL;
+	unsigned long flags = 0;
+
+	BUG_ON(hisifd = NULL);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata = NULL);
+	vsync_ctrl = &(hisifd->vsync_ctrl);
+	BUG_ON(vsync_ctrl = NULL);
+
+	if (hisifd->panel_info.vsync_ctrl_type = VSYNC_CTRL_NONE)
+		return;
+
+	mutex_lock(&(vsync_ctrl->vsync_lock));
+
+	spin_lock_irqsave(&(vsync_ctrl->spin_lock), flags);
+	if (vsync_ctrl->vsync_infinite = 0)
+		vsync_ctrl->vsync_ctrl_disabled_set = 1;
+
+	if (vsync_ctrl->vsync_ctrl_enabled)
+		vsync_ctrl->vsync_ctrl_expire_count = VSYNC_CTRL_EXPIRE_COUNT;
+	spin_unlock_irqrestore(&(vsync_ctrl->spin_lock), flags);
+
+	mutex_unlock(&(vsync_ctrl->vsync_lock));
+}
+
+int hisifb_vsync_ctrl(struct fb_info *info, void __user *argp)
+{
+	int ret = 0;
+	struct hisi_fb_data_type *hisifd = NULL;
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct hisifb_vsync *vsync_ctrl = NULL;
+	int enable = 0;
+
+	if (NULL = info) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	hisifd = (struct hisi_fb_data_type *)info->par;
+	if (NULL = hisifd) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	if (hisifd->index != PRIMARY_PANEL_IDX) {
+		HISI_FB_ERR("fb%d, not supported!\n", hisifd->index);
+		return -EINVAL;
+	}
+
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	if (NULL = pdata) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	vsync_ctrl = &(hisifd->vsync_ctrl);
+	if (NULL = vsync_ctrl) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	if (NULL = argp) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	ret = copy_from_user(&enable, argp, sizeof(enable));
+	if (ret) {
+		HISI_FB_ERR("hisifb_vsync_ctrl ioctl failed!\n");
+		return ret;
+	}
+
+	enable = (enable) ? 1 : 0;
+
+	mutex_lock(&(vsync_ctrl->vsync_lock));
+
+	if (vsync_ctrl->vsync_enabled = enable) {
+		mutex_unlock(&(vsync_ctrl->vsync_lock));
+		return 0;
+	}
+
+	if (g_debug_online_vsync)
+		HISI_FB_INFO("fb%d, enable=%d!\n", hisifd->index, enable);
+
+	vsync_ctrl->vsync_enabled = enable;
+
+	mutex_unlock(&(vsync_ctrl->vsync_lock));
+
+	down(&hisifd->blank_sem);
+
+	if (!hisifd->panel_power_on) {
+		HISI_FB_INFO("fb%d, panel is power off!", hisifd->index);
+		up(&hisifd->blank_sem);
+		return 0;
+	}
+
+	if (enable) {
+		hisifb_activate_vsync(hisifd);
+	} else {
+		hisifb_deactivate_vsync(hisifd);
+	}
+
+	up(&hisifd->blank_sem);
+
+	return 0;
+}
+
+int hisifb_vsync_resume(struct hisi_fb_data_type *hisifd)
+{
+	struct hisifb_vsync *vsync_ctrl = NULL;
+
+	BUG_ON(hisifd = NULL);
+	vsync_ctrl = &(hisifd->vsync_ctrl);
+	BUG_ON(vsync_ctrl = NULL);
+
+	vsync_ctrl->vsync_enabled = 0;
+	vsync_ctrl->vsync_ctrl_expire_count = 0;
+	vsync_ctrl->vsync_ctrl_disabled_set = 0;
+	vsync_ctrl->vsync_ctrl_enabled = 1;
+	vsync_ctrl->vsync_ctrl_isr_enabled = 1;
+
+	atomic_set(&(vsync_ctrl->buffer_updated), 1);
+
+#if 0
+	if (hisifd->panel_info.vsync_ctrl_type != VSYNC_CTRL_NONE) {
+		if ((hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_MIPI_ULPS)
+		    || (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_CLK_OFF)
+		    || (hisifd->panel_info.
+			vsync_ctrl_type & VSYNC_CTRL_VCC_OFF)) {
+
+			if (hisifd->panel_info.
+			    vsync_ctrl_type & VSYNC_CTRL_MIPI_ULPS) {
+				mipi_dsi_ulps_cfg(hisifd, 0);
+			}
+
+			if (hisifd->panel_info.
+			    vsync_ctrl_type & VSYNC_CTRL_CLK_OFF) {
+				dpe_inner_clk_disable(hisifd);
+				dpe_common_clk_disable(hisifd);
+				mipi_dsi_clk_disable(hisifd);
+			}
+
+			if (hisifd->panel_info.
+			    vsync_ctrl_type & VSYNC_CTRL_VCC_OFF) {
+				dpe_regulator_disable(hisifd);
+			}
+		}
+	}
+#endif
+
+	return 0;
+}
+
+int hisifb_vsync_suspend(struct hisi_fb_data_type *hisifd)
+{
+	return 0;
+}
+
+#pragma GCC diagnostic pop
diff --git a/drivers/video/fbdev/hisi/dss/hisi_mipi_dsi_host.c b/drivers/video/fbdev/hisi/dss/hisi_mipi_dsi_host.c
new file mode 100755
index 000000000000..0d00d3fd9c60
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_mipi_dsi_host.c
@@ -0,0 +1,401 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_mipi_dsi.h"
+
+/*
+ * mipi dsi short write with 0, 1 2 parameters
+ * Write to GEN_HDR 24 bit register the value:
+ * 1. 00h, MCS_command[15:8] ,VC[7:6],13h
+ * 2. Data1[23:16], MCS_command[15:8] ,VC[7:6],23h
+ */
+int mipi_dsi_swrite(struct dsi_cmd_desc *cm, char __iomem *dsi_base)
+{
+	uint32_t hdr = 0;
+	int len = 0;
+
+	if (cm->dlen && cm->payload = 0) {
+		HISI_FB_ERR("NO payload error!\n");
+		return 0;
+	}
+
+	BUG_ON(cm->dlen > 2);
+	len = cm->dlen;
+	hdr |= DSI_HDR_DTYPE(cm->dtype);
+	hdr |= DSI_HDR_VC(cm->vc);
+	if (len = 1) {
+		hdr |= DSI_HDR_DATA1(cm->payload[0]);
+		hdr |= DSI_HDR_DATA2(0);
+	} else if (len = 2) {
+		hdr |= DSI_HDR_DATA1(cm->payload[0]);
+		hdr |= DSI_HDR_DATA2(cm->payload[1]);
+	} else {
+		hdr |= DSI_HDR_DATA1(0);
+		hdr |= DSI_HDR_DATA2(0);
+	}
+
+	set_reg(dsi_base + MIPIDSI_GEN_HDR_OFFSET, hdr, 24, 0);
+
+	return len;		/* 4 bytes */
+}
+
+/*
+ * mipi dsi long write
+ * Write to GEN_PLD_DATA 32 bit register the value:
+ * Data3[31:24], Data2[23:16], Data1[15:8], MCS_command[7:0]
+ * If need write again to GEN_PLD_DATA 32 bit register the value:
+ * Data7[31:24], Data6[23:16], Data5[15:8], Data4[7:0]
+ *
+ * Write to GEN_HDR 24 bit register the value: WC[23:8] ,VC[7:6],29h
+ */
+int mipi_dsi_lwrite(struct dsi_cmd_desc *cm, char __iomem *dsi_base)
+{
+	uint32_t hdr = 0;
+	int i = 0;
+
+	if (cm->dlen && cm->payload = 0) {
+		HISI_FB_ERR("NO payload error!\n");
+		return 0;
+	}
+
+	/* fill up payload */
+	for (i = 0; i < cm->dlen; i += 4) {
+		set_reg(dsi_base + MIPIDSI_GEN_PLD_DATA_OFFSET,
+			*((uint32_t *) (cm->payload + i)), 32, 0);
+	}
+
+	/* fill up header */
+	hdr |= DSI_HDR_DTYPE(cm->dtype);
+	hdr |= DSI_HDR_VC(cm->vc);
+	hdr |= DSI_HDR_WC(cm->dlen);
+	set_reg(dsi_base + MIPIDSI_GEN_HDR_OFFSET, hdr, 24, 0);
+
+	return cm->dlen;
+}
+
+void mipi_dsi_max_return_packet_size(struct dsi_cmd_desc *cm,
+				     char __iomem *dsi_base)
+{
+	uint32_t hdr = 0;
+
+	/* fill up header */
+	hdr |= DSI_HDR_DTYPE(cm->dtype);
+	hdr |= DSI_HDR_VC(cm->vc);
+	hdr |= DSI_HDR_WC(cm->dlen);
+	set_reg(dsi_base + MIPIDSI_GEN_HDR_OFFSET, hdr, 24, 0);
+}
+
+uint32_t mipi_dsi_read(uint32_t *out, char __iomem *dsi_base)
+{
+	uint32_t pkg_status;
+	uint32_t try_times = 700;
+
+	do {
+		pkg_status = inp32(dsi_base + MIPIDSI_CMD_PKT_STATUS_OFFSET);
+		if (!(pkg_status & 0x10))
+			break;
+		udelay(50);
+	} while (--try_times);
+
+	*out = inp32(dsi_base + MIPIDSI_GEN_PLD_DATA_OFFSET);
+	if (!try_times)
+		HISI_FB_ERR("mipi_dsi_read timeout\n"
+			    "MIPIDSI_CMD_PKT_STATUS = 0x%x \n"
+			    "MIPIDSI_PHY_STATUS = 0x%x \n",
+			    inp32(dsi_base + MIPIDSI_CMD_PKT_STATUS_OFFSET),
+			    inp32(dsi_base + MIPIDSI_PHY_STATUS_OFFSET));
+
+	return try_times;
+}
+
+void mipi_dsi_sread(uint32_t *out, char __iomem *dsi_base)
+{
+	unsigned long dw_jiffies = 0;
+	uint32_t tmp = 0;
+
+	dw_jiffies = jiffies + HZ / 2;
+	do {
+		tmp = inp32(dsi_base + MIPIDSI_CMD_PKT_STATUS_OFFSET);
+		if ((tmp & 0x00000040) = 0x00000040) {
+			break;
+		}
+	} while (time_after(dw_jiffies, jiffies));
+
+	dw_jiffies = jiffies + HZ / 2;
+	do {
+		tmp = inp32(dsi_base + MIPIDSI_CMD_PKT_STATUS_OFFSET);
+		if ((tmp & 0x00000040) != 0x00000040) {
+			break;
+		}
+	} while (time_after(dw_jiffies, jiffies));
+
+	*out = inp32(dsi_base + MIPIDSI_GEN_PLD_DATA_OFFSET);
+}
+
+void mipi_dsi_lread(uint32_t *out, char __iomem *dsi_base)
+{
+	/* do something here */
+}
+
+/*
+ * prepare cmd buffer to be txed
+ */
+int mipi_dsi_cmd_add(struct dsi_cmd_desc *cm, char __iomem *dsi_base)
+{
+	int len = 0;
+
+	BUG_ON(cm = NULL);
+	BUG_ON(dsi_base = NULL);
+
+	switch (cm->dtype) {
+	case DTYPE_GEN_WRITE:
+	case DTYPE_GEN_WRITE1:
+	case DTYPE_GEN_WRITE2:
+
+	case DTYPE_DCS_WRITE:
+	case DTYPE_DCS_WRITE1:
+		len = mipi_dsi_swrite(cm, dsi_base);
+		break;
+	case DTYPE_GEN_LWRITE:
+	case DTYPE_DCS_LWRITE:
+	case DTYPE_DSC_LWRITE:
+
+		len = mipi_dsi_lwrite(cm, dsi_base);
+		break;
+	default:
+		HISI_FB_ERR("dtype=%x NOT supported!\n", cm->dtype);
+		break;
+	}
+
+	return len;
+}
+
+int mipi_dsi_cmds_tx(struct dsi_cmd_desc *cmds, int cnt,
+		     char __iomem *dsi_base)
+{
+	struct dsi_cmd_desc *cm = NULL;
+	int i = 0;
+
+	BUG_ON(cmds = NULL);
+	BUG_ON(dsi_base = NULL);
+
+	cm = cmds;
+
+	for (i = 0; i < cnt; i++) {
+		mipi_dsi_cmd_add(cm, dsi_base);
+
+		if (cm->wait) {
+			if (cm->waittype = WAIT_TYPE_US)
+				udelay(cm->wait);
+			else if (cm->waittype = WAIT_TYPE_MS)
+				mdelay(cm->wait);
+			else
+				mdelay(cm->wait * 1000);
+		}
+		cm++;
+	}
+
+	return cnt;
+}
+
+void mipi_dsi_check_0lane_is_ready(char __iomem *dsi_base)
+{
+	unsigned long dw_jiffies = 0;
+	uint32_t tmp = 0;
+
+	dw_jiffies = jiffies + HZ / 10;
+	do {
+		tmp = inp32(dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+		if ((tmp & 0x10) = 0x10) {
+			HISI_FB_INFO("0 lane is stopping state");
+			return;
+		}
+	} while (time_after(dw_jiffies, jiffies));
+
+	HISI_FB_ERR("0 lane is not stopping state:tmp=0x%x", tmp);
+}
+
+static void mipi_dsi_sread_request(struct dsi_cmd_desc *cm,
+				   char __iomem *dsi_base)
+{
+	uint32_t hdr = 0;
+
+	/* fill up header */
+	hdr |= DSI_HDR_DTYPE(cm->dtype);
+	hdr |= DSI_HDR_VC(cm->vc);
+	hdr |= DSI_HDR_DATA1(cm->payload[0]);
+	hdr |= DSI_HDR_DATA2(0);
+	set_reg(dsi_base + MIPIDSI_GEN_HDR_OFFSET, hdr, 24, 0);
+}
+
+static int mipi_dsi_read_add(uint32_t *out, struct dsi_cmd_desc *cm,
+			     char __iomem *dsi_base)
+{
+	unsigned long dw_jiffies = 0;
+	uint32_t pkg_status = 0;
+	uint32_t phy_status = 0;
+	int is_timeout = 1;
+	int ret = 0;
+
+	BUG_ON(cm = NULL);
+	BUG_ON(dsi_base = NULL);
+
+	if (cm->dtype = DTYPE_DCS_READ) {
+		mipi_dsi_sread_request(cm, dsi_base);
+
+		if (!mipi_dsi_read(out, dsi_base)) {
+			HISI_FB_ERR("Read register 0x%X timeout\n",
+				    cm->payload[0]);
+			return -1;
+		}
+	} else if (cm->dtype = DTYPE_GEN_READ1) {
+
+		/*read status register */
+		dw_jiffies = jiffies + HZ;
+		do {
+			pkg_status +			    inp32(dsi_base + MIPIDSI_CMD_PKT_STATUS_OFFSET);
+			phy_status +			    inp32(dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+			if ((pkg_status & 0x1) = 0x1 && !(phy_status & 0x2)) {
+				is_timeout = 0;
+				break;
+			}
+		} while (time_after(dw_jiffies, jiffies));
+
+		if (is_timeout) {
+			HISI_FB_ERR("mipi_dsi_read timeout :0x%x\n"
+					"MIPIDSI_CMD_PKT_STATUS = 0x%x\n"
+					"MIPIDSI_PHY_STATUS = 0x%x \n"
+					"MIPIDSI_INT_ST1_OFFSET = 0x%x \n",
+					cm->payload[0],
+					inp32(dsi_base + MIPIDSI_CMD_PKT_STATUS_OFFSET),
+					inp32(dsi_base + MIPIDSI_PHY_STATUS_OFFSET),
+					inp32(dsi_base + MIPIDSI_INT_ST1_OFFSET));
+			return -1;
+		}
+		/*send read cmd to fifo */
+		set_reg(dsi_base + MIPIDSI_GEN_HDR_OFFSET,
+			((cm->payload[0] << 8) | cm->dtype), 24, 0);
+
+		is_timeout = 1;
+		/*wait dsi read data */
+		dw_jiffies = jiffies + HZ;
+		do {
+			pkg_status +			    inp32(dsi_base + MIPIDSI_CMD_PKT_STATUS_OFFSET);
+			if (!(pkg_status & 0x10)) {
+				is_timeout = 0;
+				break;
+			}
+		} while (time_after(dw_jiffies, jiffies));
+
+		if (is_timeout) {
+			HISI_FB_ERR("mipi_dsi_read timeout :0x%x\n"
+					"MIPIDSI_CMD_PKT_STATUS = 0x%x\n"
+					"MIPIDSI_PHY_STATUS = 0x%x \n"
+					"MIPIDSI_INT_ST1_OFFSET = 0x%x \n",
+					cm->payload[0],
+					inp32(dsi_base + MIPIDSI_CMD_PKT_STATUS_OFFSET),
+					inp32(dsi_base + MIPIDSI_PHY_STATUS_OFFSET),
+					inp32(dsi_base + MIPIDSI_INT_ST1_OFFSET));
+			return -1;
+		}
+		/*get read data */
+		*out = inp32(dsi_base + MIPIDSI_GEN_PLD_DATA_OFFSET);
+	} else {
+		ret = -1;
+		HISI_FB_ERR("dtype=%x NOT supported!\n", cm->dtype);
+	}
+
+	return ret;
+}
+
+int mipi_dsi_cmds_rx(uint32_t *out, struct dsi_cmd_desc *cmds, int cnt,
+		     char __iomem *dsi_base)
+{
+	struct dsi_cmd_desc *cm = NULL;
+	int i = 0;
+	int err_num = 0;
+
+	BUG_ON(cmds = NULL);
+	BUG_ON(dsi_base = NULL);
+
+	cm = cmds;
+
+	for (i = 0; i < cnt; i++) {
+		if (mipi_dsi_read_add(&(out[i]), cm, dsi_base)) {
+			err_num++;
+		}
+
+		if (cm->wait) {
+			if (cm->waittype = WAIT_TYPE_US)
+				udelay(cm->wait);
+			else if (cm->waittype = WAIT_TYPE_MS)
+				mdelay(cm->wait);
+			else
+				mdelay(cm->wait * 1000);
+		}
+		cm++;
+	}
+
+	return err_num;
+}
+
+int mipi_dsi_read_compare(struct mipi_dsi_read_compare_data *data,
+			  char __iomem *dsi_base)
+{
+	uint32_t *read_value = NULL;
+	uint32_t *expected_value = NULL;
+	uint32_t *read_mask = NULL;
+	char **reg_name = NULL;
+	int log_on = 0;
+	struct dsi_cmd_desc *cmds = NULL;
+
+	int cnt = 0;
+	int cnt_not_match = 0;
+	int ret = 0;
+	int i;
+
+	BUG_ON(data = NULL);
+	BUG_ON(dsi_base = NULL);
+
+	read_value = data->read_value;
+	expected_value = data->expected_value;
+	read_mask = data->read_mask;
+	reg_name = data->reg_name;
+	log_on = data->log_on;
+
+	cmds = data->cmds;
+	cnt = data->cnt;
+
+	ret = mipi_dsi_cmds_rx(read_value, cmds, cnt, dsi_base);
+	if (ret) {
+		HISI_FB_ERR("Read error number: %d\n", ret);
+		return cnt;
+	}
+
+	for (i = 0; i < cnt; i++) {
+		if (log_on) {
+			HISI_FB_INFO("Read reg %s: 0x%x, value = 0x%x\n",
+				     reg_name[i], cmds[i].payload[0],
+				     read_value[i]);
+		}
+
+		if (expected_value[i] != (read_value[i] & read_mask[i])) {
+			cnt_not_match++;
+		}
+	}
+
+	return cnt_not_match;
+}
diff --git a/drivers/video/fbdev/hisi/dss/hisi_overlay_cmdlist_utils.c b/drivers/video/fbdev/hisi/dss/hisi_overlay_cmdlist_utils.c
new file mode 100755
index 000000000000..6b1832f49e3c
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_overlay_cmdlist_utils.c
@@ -0,0 +1,1450 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_fb.h"
+
+#define MAX_ITEM_OFFSET	(0x3F)
+#define CMDLIST_ADDR_OFFSET	(0x3FFFF)
+
+#define CMDLIST_HEADER_LEN	(SZ_1K)
+#define CMDLIST_ITEM_LEN	(SZ_8K)
+#define MAX_ITEM_INDEX	(SZ_1K)
+
+dss_cmdlist_data_t *g_cmdlist_data = NULL;
+uint32_t g_online_cmdlist_idxs = 0;
+uint32_t g_offline_cmdlist_idxs = 0;
+
+/* get cmdlist indexs */
+int hisi_cmdlist_get_cmdlist_idxs(dss_overlay_t *pov_req,
+				  uint32_t *cmdlist_pre_idxs,
+				  uint32_t *cmdlist_idxs)
+{
+	uint32_t cmdlist_idxs_temp = 0;
+	int i = 0;
+	int k = 0;
+	int m = 0;
+	dss_layer_t *layer = NULL;
+	dss_wb_layer_t *wb_layer = NULL;
+	dss_overlay_block_t *pov_h_block_infos = NULL;
+	dss_overlay_block_t *pov_h_block = NULL;
+	bool no_ovl_idx = false;
+
+	BUG_ON(pov_req = NULL);
+
+	pov_h_block_infos = (dss_overlay_block_t *) pov_req->ov_block_infos_ptr;
+	for (m = 0; m < pov_req->ov_block_nums; m++) {
+		pov_h_block = &(pov_h_block_infos[m]);
+		for (i = 0; i < pov_h_block->layer_nums; i++) {
+			layer = &(pov_h_block->layer_infos[i]);
+
+			if (layer->need_cap & (CAP_BASE | CAP_DIM | CAP_PURE_COLOR))
+				continue;
+
+			if (layer->chn_idx = DSS_RCHN_V2) {
+				cmdlist_idxs_temp |= (1 << DSS_CMDLIST_V2);
+			} else {
+				cmdlist_idxs_temp |= (1 << layer->chn_idx);
+			}
+		}
+	}
+
+	if (pov_req->wb_enable = 1) {
+		for (k = 0; k < pov_req->wb_layer_nums; k++) {
+			wb_layer = &(pov_req->wb_layer_infos[k]);
+
+			if (wb_layer->chn_idx = DSS_WCHN_W2) {
+				no_ovl_idx = true;
+				cmdlist_idxs_temp |= (1 << DSS_CMDLIST_W2);
+			} else {
+				cmdlist_idxs_temp |= (1 << wb_layer->chn_idx);
+			}
+		}
+	}
+
+	if (no_ovl_idx = false) {
+		cmdlist_idxs_temp |+		    (1 << (DSS_CMDLIST_OV0 + pov_req->ovl_idx));
+	}
+
+	if (cmdlist_idxs_temp & (~HISI_DSS_CMDLIST_IDXS_MAX)) {
+		HISI_FB_ERR("cmdlist_idxs_temp(0x%x) is invalid!\n",
+			    cmdlist_idxs_temp);
+		return -EINVAL;
+	}
+
+	if (cmdlist_idxs && cmdlist_pre_idxs) {
+		*cmdlist_idxs = cmdlist_idxs_temp;
+		*cmdlist_pre_idxs &= (~(*cmdlist_idxs));
+	} else if (cmdlist_idxs) {
+		*cmdlist_idxs = cmdlist_idxs_temp;
+	} else if (cmdlist_pre_idxs) {
+		*cmdlist_pre_idxs = cmdlist_idxs_temp;
+	} else {
+		HISI_FB_ERR("cmdlist_idxs && cmdlist_pre_idxs is NULL!\n");
+		return -EINVAL;
+	}
+
+	if (g_debug_ovl_cmdlist) {
+		HISI_FB_INFO("cmdlist_pre_idxs(0x%x), cmdlist_idxs(0x%x).\n",
+			     (cmdlist_pre_idxs ? *cmdlist_pre_idxs : 0),
+			     (cmdlist_idxs ? *cmdlist_idxs : 0));
+	}
+
+	return 0;
+}
+
+uint32_t hisi_cmdlist_get_cmdlist_need_start(struct hisi_fb_data_type *hisifd,
+					     uint32_t cmdlist_idxs)
+{
+	uint32_t cmdlist_idxs_temp = 0;
+
+	BUG_ON(hisifd = NULL);
+
+	cmdlist_idxs_temp = g_offline_cmdlist_idxs;
+	g_offline_cmdlist_idxs |= cmdlist_idxs;
+	cmdlist_idxs_temp = (g_offline_cmdlist_idxs & (~cmdlist_idxs_temp));
+
+	cmdlist_idxs_temp |= (cmdlist_idxs & g_online_cmdlist_idxs);
+	g_online_cmdlist_idxs &= (~cmdlist_idxs_temp);
+
+	if (g_debug_ovl_cmdlist) {
+		HISI_FB_INFO
+		    ("g_online_cmdlist_idxs=0x%x, cmdlist_idxs_need_start=0x%x\n",
+		     g_online_cmdlist_idxs, cmdlist_idxs_temp);
+	}
+
+	return cmdlist_idxs_temp;
+}
+
+/*
+ ** data0: addr0[17:0]
+ ** data1: addr0[17:0] + addr1[5:0]
+ ** data2: addr0[17:0] + addr2[5:0]
+ **
+ ** cnt[1:0]:
+ ** 2'b00:	reg0
+ ** 2'b01: reg0, reg1
+ ** 2'b10: reg0, reg1, reg2
+ ** 2'b11: ((inp32(addr0) & data1) | data2) -> addr0
+ */
+void hisi_cmdlist_set_reg(struct hisi_fb_data_type *hisifd, char __iomem *addr,
+			  uint32_t value, uint8_t bw, uint8_t bs)
+{
+	uint32_t mask = (1 << bw) - 1;
+	dss_cmdlist_node_t *node = NULL;
+	int cmdlist_idx = -1;
+	int index = 0;
+	uint32_t new_addr = 0;
+	uint32_t old_addr = 0;
+	int condition = 0;
+
+	BUG_ON(addr = NULL);
+	BUG_ON(hisifd = NULL);
+
+	cmdlist_idx = hisifd->cmdlist_idx;
+	BUG_ON((cmdlist_idx < 0) || (cmdlist_idx >= HISI_DSS_CMDLIST_MAX));
+
+	node +	    list_entry(hisifd->cmdlist_data->cmdlist_head_temp[cmdlist_idx].prev,
+	    	dss_cmdlist_node_t, list_node);
+	BUG_ON(node = NULL);
+
+	if (node->node_type = CMDLIST_NODE_NOP) {
+		HISI_FB_ERR("can't set register value to NOP node!");
+		return;
+	}
+
+	index = node->item_index;
+	new_addr = (uint32_t) (addr - hisifd->dss_base + hisifd->dss_base_phy);
+	new_addr = (new_addr >> 2) & CMDLIST_ADDR_OFFSET;
+	old_addr = node->list_item[index].reg_addr.ul32 & CMDLIST_ADDR_OFFSET;
+	condition = (((new_addr - old_addr) < MAX_ITEM_OFFSET)
+		     && (new_addr >= old_addr));
+
+	if (bw != 32) {
+		if (node->item_flag != 0)
+			index++;
+
+		node->list_item[index].reg_addr.bits.add0 = new_addr;
+		node->list_item[index].data0 = value;
+		node->list_item[index].data1 = ~(mask << bs);
+		node->list_item[index].data2 = (mask & value) << bs;
+		node->list_item[index].reg_addr.bits.cnt = 3;
+		node->item_flag = 3;
+	} else {
+		if (node->item_flag = 0) {
+			node->list_item[index].reg_addr.bits.add0 = new_addr;
+			node->list_item[index].data0 = value;
+			node->list_item[index].reg_addr.bits.cnt = 0;
+			node->item_flag = 1;
+		} else if (node->item_flag = 1 && condition) {
+			node->list_item[index].reg_addr.bits.add1 +			    new_addr - old_addr;
+			node->list_item[index].data1 = value;
+			node->list_item[index].reg_addr.bits.cnt = 1;
+			node->item_flag = 2;
+		} else if (node->item_flag = 2 && condition) {
+			node->list_item[index].reg_addr.bits.add2 +			    new_addr - old_addr;
+			node->list_item[index].data2 = value;
+			node->list_item[index].reg_addr.bits.cnt = 2;
+			node->item_flag = 3;
+		} else {
+			index++;
+			node->list_item[index].reg_addr.bits.add0 = new_addr;
+			node->list_item[index].data0 = value;
+			node->list_item[index].reg_addr.bits.cnt = 0;
+			node->item_flag = 1;
+		}
+	}
+
+	BUG_ON(index >= MAX_ITEM_INDEX);
+
+	node->item_index = index;
+	node->list_header->total_items.bits.count = node->item_index + 1;
+}
+
+/*
+ ** flush cache for cmdlist, make sure that
+ ** cmdlist has writen through to memory before config register
+ */
+void hisi_cmdlist_flush_cache(struct hisi_fb_data_type *hisifd,
+			      struct ion_client *ion_client,
+			      uint32_t cmdlist_idxs)
+{
+	uint32_t i = 0;
+	uint32_t cmdlist_idxs_temp = 0;
+	dss_cmdlist_node_t *node = NULL;
+	dss_cmdlist_node_t *_node_ = NULL;
+	struct sg_table *table = NULL;
+	struct list_head *cmdlist_heads = NULL;
+
+	BUG_ON(hisifd = NULL);
+
+	cmdlist_idxs_temp = cmdlist_idxs;
+
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if ((cmdlist_idxs_temp & 0x1) = 0x1) {
+			cmdlist_heads +			    &(hisifd->cmdlist_data->cmdlist_head_temp[i]);
+			if (!cmdlist_heads) {
+				HISI_FB_ERR("cmdlist_data is NULL!\n");
+				continue;
+			}
+
+			list_for_each_entry_safe_reverse(node, _node_,
+							 cmdlist_heads,
+							 list_node) {
+
+				if (!node->header_ion_handle) {
+					HISI_FB_ERR
+					    ("header_ion_handle is NULL!\n");
+				} else {
+					table = ion_sg_table(ion_client,
+							 node->header_ion_handle);
+					BUG_ON(table = NULL);
+					dma_sync_sg_for_device(NULL, table->sgl,
+							       table->nents,
+							       DMA_TO_DEVICE);
+				}
+
+				if (!node->item_ion_handle) {
+					HISI_FB_ERR("item_ion_handle is NULL!\n");
+				} else {
+					table = ion_sg_table(ion_client,
+							 node->item_ion_handle);
+					BUG_ON(table = NULL);
+					dma_sync_sg_for_device(NULL, table->sgl,
+							       table->nents,
+							       DMA_TO_DEVICE);
+				}
+			}
+		}
+
+		cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+	}
+}
+
+dss_cmdlist_node_t *hisi_cmdlist_node_alloc(struct ion_client *ion_client)
+{
+	int ret = 0;
+	dss_cmdlist_node_t *node = NULL;
+	size_t header_len = CMDLIST_HEADER_LEN;
+	size_t item_len = CMDLIST_ITEM_LEN;
+
+	BUG_ON(ion_client = NULL);
+
+	node +	    (dss_cmdlist_node_t *) kzalloc(sizeof(dss_cmdlist_node_t),
+					   GFP_KERNEL);
+	if (IS_ERR(node)) {
+		HISI_FB_ERR("failed to alloc dss_cmdlist_node_t!");
+		goto err_alloc_cmdlist_node;
+	}
+
+	memset(node, 0, sizeof(dss_cmdlist_node_t));
+
+	/*alloc buffer for header */
+	node->header_ion_handle +	    ion_alloc(ion_client, header_len, 0, ION_HEAP(ION_GRALLOC_HEAP_ID), 0);
+	if (IS_ERR(node->header_ion_handle)) {
+		HISI_FB_ERR("failed to ion_alloc node->header_ion_handle!");
+		goto err_header_ion_handle;
+	}
+
+	node->list_header +	    (cmd_header_t *) ion_map_kernel(ion_client,
+					    node->header_ion_handle);
+	if (!node->list_header) {
+		HISI_FB_ERR("failed to ion_map_kernel node->list_header!");
+		goto err_header_ion_map;
+	}
+	memset(node->list_header, 0, header_len);
+
+	ret +	    ion_phys(ion_client, node->header_ion_handle, &node->header_phys,
+		     &header_len);
+	if (ret < 0) {
+		HISI_FB_ERR("failed to ion_phys node->header_phys!");
+		goto err_header_ion_phys;
+	}
+
+	/*alloc buffer for items */
+	node->item_ion_handle +	    ion_alloc(ion_client, item_len, 0, ION_HEAP(ION_GRALLOC_HEAP_ID), 0);
+	if (!node->item_ion_handle) {
+		HISI_FB_ERR("failed to ion_alloc node->item_ion_handle!");
+		goto err_item_ion_handle;
+	}
+
+	node->list_item +	    (cmd_item_t *) ion_map_kernel(ion_client, node->item_ion_handle);
+	if (!node->list_item) {
+		HISI_FB_ERR("failed to ion_map_kernel node->list_item!");
+		goto err_item_ion_map;
+	}
+
+	memset(node->list_item, 0, item_len);
+	ret +	    ion_phys(ion_client, node->item_ion_handle, &node->item_phys,
+		     &item_len);
+	if (ret < 0) {
+		HISI_FB_ERR("failed to ion_phys node->item_phys!");
+		goto err_item_ion_phys;
+	}
+
+	/* fill node info */
+	node->item_flag = 0;
+	node->item_index = 0;
+
+	node->is_used = 0;
+	node->node_type = CMDLIST_NODE_NONE;
+	return node;
+
+ err_item_ion_phys:
+	if (node->item_ion_handle)
+		ion_unmap_kernel(ion_client, node->item_ion_handle);
+ err_item_ion_map:
+	if (node->item_ion_handle)
+		ion_free(ion_client, node->item_ion_handle);
+ err_item_ion_handle:
+ err_header_ion_phys:
+	if (node->header_ion_handle)
+		ion_unmap_kernel(ion_client, node->header_ion_handle);
+ err_header_ion_map:
+	if (node->header_ion_handle)
+		ion_free(ion_client, node->header_ion_handle);
+ err_header_ion_handle:
+	if (node)
+		kfree(node);
+ err_alloc_cmdlist_node:
+	return NULL;
+}
+
+void hisi_cmdlist_node_free(struct ion_client *ion_client,
+			    dss_cmdlist_node_t *node)
+{
+	BUG_ON(ion_client = NULL);
+	BUG_ON(node = NULL);
+
+	if (node->header_ion_handle) {
+		ion_unmap_kernel(ion_client, node->header_ion_handle);
+		ion_free(ion_client, node->header_ion_handle);
+	}
+
+	if (node->item_ion_handle) {
+		ion_unmap_kernel(ion_client, node->item_ion_handle);
+		ion_free(ion_client, node->item_ion_handle);
+	}
+
+	kfree(node);
+	node = NULL;
+}
+
+static dss_cmdlist_node_t *hisi_cmdlist_get_free_node(dss_cmdlist_node_t *
+						      node[], int *id)
+{
+	int i = 0;
+
+	for (i = 0; i < HISI_DSS_CMDLIST_NODE_MAX; i++) {
+		if (node[i] && (node[i]->is_used = 0)) {
+			node[i]->is_used = 1;
+			*id = i + 1;
+			return node[i];
+		}
+	}
+
+	return NULL;
+}
+
+int hisi_cmdlist_add_nop_node(struct hisi_fb_data_type *hisifd,
+			      uint32_t cmdlist_idxs, int pending, int reserved)
+{
+	dss_cmdlist_node_t *node = NULL;
+	uint32_t cmdlist_idxs_temp = 0;
+	int i = 0;
+	int id = 0;
+
+	BUG_ON(hisifd = NULL);
+
+	cmdlist_idxs_temp = cmdlist_idxs;
+
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if ((cmdlist_idxs_temp & 0x1) = 0x1) {
+			node +			    hisi_cmdlist_get_free_node(hisifd->cmdlist_data->
+						       cmdlist_nodes_temp[i],
+						       &id);
+			if (!node) {
+				HISI_FB_ERR
+				    ("failed to hisi_get_free_cmdlist_node!\n");
+				return -EINVAL;
+			}
+
+			node->list_header->flag.bits.id = id;
+			node->list_header->flag.bits.nop = 0x1;
+			node->list_header->flag.bits.pending +			    pending ? 0x1 : 0x0;
+			node->list_header->flag.bits.valid_flag +			    CMDLIST_NODE_VALID;
+			node->list_header->next_list = node->header_phys;
+
+			node->is_used = 1;
+			node->node_type = CMDLIST_NODE_NOP;
+			node->reserved = reserved ? 0x1 : 0x0;
+
+			/*add this nop to list */
+			list_add_tail(&(node->list_node),
+				      &(hisifd->cmdlist_data->cmdlist_head_temp[i]));
+
+			if (node->list_node.prev !+			    &(hisifd->cmdlist_data->cmdlist_head_temp[i])) {
+				dss_cmdlist_node_t *pre_node = NULL;
+				pre_node +				    list_entry(node->list_node.prev,
+					       dss_cmdlist_node_t, list_node);
+				pre_node->list_header->next_list +				    node->header_phys;
+				if (node->list_header->flag.bits.pending = 0x1) {
+					pre_node->reserved = 0x0;
+				}
+
+				pre_node->list_header->flag.bits.task_end = 0x1;
+
+				if (g_debug_ovl_cmdlist) {
+					HISI_FB_DEBUG
+					    ("i = %d, next_list = 0x%x\n", i,
+					     (uint32_t) (node->header_phys));
+				}
+			}
+		}
+
+		cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+	}
+
+	return 0;
+}
+
+int hisi_cmdlist_add_new_node(struct hisi_fb_data_type *hisifd,
+			      uint32_t cmdlist_idxs, int pending, int task_end,
+			      int remove, int last, uint32_t wb_type)
+{
+	char __iomem *cmdlist_base = NULL;
+	dss_cmdlist_node_t *node = NULL;
+	uint32_t cmdlist_idxs_temp = 0;
+	int i = 0;
+	int id = 0;
+
+	BUG_ON(hisifd = NULL);
+
+	cmdlist_base = hisifd->dss_base + DSS_CMDLIST_OFFSET;
+	cmdlist_idxs_temp = cmdlist_idxs;
+
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if ((cmdlist_idxs_temp & 0x1) = 0x1) {
+			node +			    hisi_cmdlist_get_free_node(hisifd->cmdlist_data->
+						       cmdlist_nodes_temp[i],
+						       &id);
+			if (!node) {
+				HISI_FB_ERR
+				    ("failed to hisi_get_free_cmdnode!\n");
+				return -EINVAL;
+			}
+
+			/*fill the header and item info */
+			node->list_header->flag.bits.id = id;
+			node->list_header->flag.bits.pending +			    pending ? 0x1 : 0x0;
+
+			if (i < DSS_CMDLIST_W0) {
+				node->list_header->flag.bits.event_list +				    remove ? 0x8 : (0xE + i);
+			} else if (i < DSS_CMDLIST_OV0) {
+				node->list_header->flag.bits.event_list +				    remove ? 0x8 : (0x16 + i);
+			} else if (i = DSS_CMDLIST_V2) {
+				node->list_header->flag.bits.event_list +				    remove ? 0x8 : 0x16;
+			} else if (i = DSS_CMDLIST_W2) {
+				node->list_header->flag.bits.event_list +				    remove ? 0x8 : 0x20;
+			} else {
+				node->list_header->flag.bits.event_list +				    remove ? 0x8 : (0xE + i);
+			}
+
+			node->list_header->flag.bits.task_end +			    task_end ? 0x1 : 0x0;
+			node->list_header->flag.bits.last = last ? 0x1 : 0x0;
+
+			node->list_header->flag.bits.valid_flag +			    CMDLIST_NODE_VALID;
+			node->list_header->flag.bits.exec = 0x1;
+			node->list_header->list_addr = node->item_phys;
+			node->list_header->next_list = node->item_phys;
+
+			node->is_used = 1;
+			node->node_type = CMDLIST_NODE_FRAME;
+			node->item_flag = 0;
+			node->reserved = 0;
+
+			/* add this nop to list */
+			list_add_tail(&(node->list_node),
+				      &(hisifd->cmdlist_data->cmdlist_head_temp[i]));
+
+			if (node->list_node.prev !+			    &(hisifd->cmdlist_data->cmdlist_head_temp[i])) {
+				dss_cmdlist_node_t *pre_node = NULL;
+				pre_node +				    list_entry(node->list_node.prev,
+					       dss_cmdlist_node_t, list_node);
+				pre_node->list_header->next_list +				    node->header_phys;
+				pre_node->reserved = 0x0;
+				if (g_debug_ovl_cmdlist) {
+					HISI_FB_DEBUG
+					    ("i = %d, next_list = 0x%x\n", i,
+					     (uint32_t) node->header_phys);
+				}
+			}
+		}
+
+		cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+	}
+
+	return 0;
+}
+
+int hisi_cmdlist_del_all_node(struct list_head *cmdlist_heads)
+{
+	dss_cmdlist_node_t *node = NULL;
+	dss_cmdlist_node_t *_node_ = NULL;
+
+	BUG_ON(cmdlist_heads = NULL);
+
+	list_for_each_entry_safe(node, _node_, cmdlist_heads, list_node) {
+		if (node->reserved != 0x1) {
+			list_del(&node->list_node);
+
+			memset(node->list_header, 0, CMDLIST_HEADER_LEN);
+			memset(node->list_item, 0, CMDLIST_ITEM_LEN);
+
+			node->item_index = 0;
+			node->item_flag = 0;
+			node->node_type = CMDLIST_NODE_NONE;
+			node->is_used = 0;
+		}
+	}
+
+	return 0;
+}
+
+int hisi_cmdlist_check_cmdlist_state(struct hisi_fb_data_type *hisifd,
+				     uint32_t cmdlist_idxs)
+{
+	char __iomem *cmdlist_base = NULL;
+	uint32_t offset = 0;
+	uint32_t tmp = 0;
+	uint32_t cmdlist_idxs_temp = 0;
+	int i = 0;
+	int delay_count = 0;
+	bool is_timeout = true;
+	int ret = 0;
+
+	BUG_ON(hisifd = NULL);
+
+	cmdlist_base = hisifd->dss_base + DSS_CMDLIST_OFFSET;
+	offset = 0x40;
+	cmdlist_idxs_temp = cmdlist_idxs;
+
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if ((cmdlist_idxs_temp & 0x1) = 0x1) {
+			while (1) {
+				tmp +				    inp32(cmdlist_base + CMDLIST_CH0_STATUS +
+					  i * offset);
+				if (((tmp & 0xF) = 0x0) || delay_count > 5000) {
+					is_timeout +					    (delay_count > 5000) ? true : false;
+					delay_count = 0;
+					break;
+				} else {
+					udelay(1);
+					++delay_count;
+				}
+			}
+
+			if (is_timeout) {
+				HISI_FB_ERR
+				    ("cmdlist_ch%d not in idle state,ints=0x%x !\n",
+				     i, tmp);
+				ret = -1;
+			}
+		}
+
+		cmdlist_idxs_temp = (cmdlist_idxs_temp >> 1);
+	}
+
+	return ret;
+}
+
+/*
+ ** stop the pending state for one new frame
+ ** if the current cmdlist status is e_status_wait.
+ */
+int hisi_cmdlist_exec(struct hisi_fb_data_type *hisifd, uint32_t cmdlist_idxs)
+{
+	char __iomem *cmdlist_base = NULL;
+	uint32_t offset = 0;
+	uint32_t tmp = 0;
+	uint32_t cmdlist_idxs_temp = 0;
+	int i = 0;
+	int delay_count = 0;
+	bool is_timeout = true;
+
+	BUG_ON(hisifd = NULL);
+
+	cmdlist_base = hisifd->dss_base + DSS_CMDLIST_OFFSET;
+	offset = 0x40;
+	cmdlist_idxs_temp = cmdlist_idxs;
+
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if ((cmdlist_idxs_temp & 0x1) = 0x1) {
+			while (1) {
+				tmp +				    inp32(cmdlist_base + CMDLIST_CH0_STATUS +
+					  i * offset);
+				if (((tmp & 0xF) = 0x0) || delay_count > 500) {
+					is_timeout +					    (delay_count > 500) ? true : false;
+					delay_count = 0;
+					break;
+				} else {
+					udelay(1);
+					++delay_count;
+				}
+			}
+
+			if (is_timeout) {
+				HISI_FB_ERR
+				    ("cmdlist_ch%d not in idle state,ints=0x%x !\n",
+				     i, tmp);
+				if (g_debug_ovl_cmdlist) {
+					hisi_cmdlist_dump_all_node(hisifd, NULL,
+								   cmdlist_idxs);
+				}
+			}
+		}
+
+		cmdlist_idxs_temp = (cmdlist_idxs_temp >> 1);
+	}
+	return 0;
+}
+
+/*
+ **start cmdlist.
+ **it will set cmdlist into pending state.
+ */
+extern uint32_t g_dss_module_ovl_base[DSS_MCTL_IDX_MAX][MODULE_OVL_MAX];
+int hisi_cmdlist_config_start(struct hisi_fb_data_type *hisifd, int mctl_idx,
+			      uint32_t cmdlist_idxs, uint32_t wb_compose_type)
+{
+	char __iomem *mctl_base = NULL;
+	char __iomem *cmdlist_base = NULL;
+	dss_cmdlist_node_t *cmdlist_node = NULL;
+	uint32_t offset = 0;
+	uint32_t list_addr = 0;
+	uint32_t cmdlist_idxs_temp = 0;
+	int i = 0;
+	int temp = 0;
+	int status_temp = 0;
+	int ints_temp = 0;
+
+	BUG_ON(hisifd = NULL);
+
+	mctl_base +	    hisifd->dss_base +
+	    g_dss_module_ovl_base[mctl_idx][MODULE_MCTL_BASE];
+	cmdlist_base = hisifd->dss_base + DSS_CMDLIST_OFFSET;
+	offset = 0x40;
+	cmdlist_idxs_temp = cmdlist_idxs;
+
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if ((cmdlist_idxs_temp & 0x1) = 0x1) {
+			status_temp +			    inp32(cmdlist_base + CMDLIST_CH0_STATUS +
+				  i * offset);
+			ints_temp +			    inp32(cmdlist_base + CMDLIST_CH0_INTS + i * offset);
+
+			if (mctl_idx >= DSS_MCTL2) {
+				cmdlist_node +				    list_first_entry(&(hisifd->cmdlist_data_tmp
+						      [wb_compose_type]->cmdlist_head_temp[i]),
+						     dss_cmdlist_node_t,
+						     list_node);
+			} else {
+				cmdlist_node +				    list_first_entry(&(hisifd->cmdlist_data->
+				    		 cmdlist_head_temp[i]),
+						     dss_cmdlist_node_t,
+						     list_node);
+			}
+
+			list_addr = cmdlist_node->header_phys;
+			if (g_debug_ovl_cmdlist) {
+				HISI_FB_INFO
+				    ("list_addr:0x%x, i=%d, ints_temp=0x%x\n",
+				     list_addr, i, ints_temp);
+			}
+
+			temp |= (1 << i);
+			outp32(cmdlist_base + CMDLIST_ADDR_MASK_EN, BIT(i));
+			if (g_debug_set_reg_val) {
+				HISI_FB_INFO("writel: [%p] = 0x%lx\n",
+					     cmdlist_base +
+					     CMDLIST_ADDR_MASK_EN, BIT(i));
+			}
+
+			set_reg(cmdlist_base + CMDLIST_CH0_CTRL + i*offset,
+					mctl_idx, 3, 2);
+			if (mctl_idx <= DSS_MCTL1) {
+				set_reg(cmdlist_base + CMDLIST_CH0_CTRL + i*offset, 0x1, 1, 6);
+			} else {
+				set_reg(cmdlist_base + CMDLIST_CH0_CTRL + i*offset, 0x0, 1, 6);
+			}
+
+			set_reg(cmdlist_base + CMDLIST_CH0_STAAD + i*offset,
+					list_addr, 32, 0);
+			set_reg(cmdlist_base + CMDLIST_CH0_CTRL + i*offset, 0x1, 1, 0);
+			if ((mctl_idx <= DSS_MCTL1)
+			    && ((ints_temp & 0x2) = 0x2)) {
+				set_reg(cmdlist_base + CMDLIST_SWRST, 0x1, 1, i);
+			}
+
+			if (mctl_idx >= DSS_MCTL2) {
+				if (((status_temp & 0xF) = 0x0)
+				    || ((ints_temp & 0x2) = 0x2)) {
+					set_reg(cmdlist_base + CMDLIST_SWRST,
+						0x1, 1, i);
+				} else {
+					HISI_FB_INFO
+					    ("i=%d, status_temp=0x%x, ints_temp=0x%x\n",
+					     i, status_temp, ints_temp);
+				}
+			}
+		}
+		cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+	}
+
+	outp32(cmdlist_base + CMDLIST_ADDR_MASK_DIS, temp);
+	if (g_debug_set_reg_val) {
+		HISI_FB_INFO("writel: [%p] = 0x%x\n",
+			     cmdlist_base + CMDLIST_ADDR_MASK_DIS, temp);
+	}
+
+	if (mctl_idx >= DSS_MCTL2) {
+		set_reg(mctl_base + MCTL_CTL_ST_SEL, 0x1, 1, 0);
+		set_reg(mctl_base + MCTL_CTL_SW_ST, 0x1, 1, 0);
+	}
+
+	return 0;
+}
+
+void hisi_cmdlist_config_mif_reset(struct hisi_fb_data_type *hisifd,
+				   dss_overlay_t *pov_req,
+				   uint32_t cmdlist_idxs, int mctl_idx)
+{
+	char __iomem *dss_base = NULL;
+	char __iomem *tmp_base = NULL;
+
+	uint32_t cmdlist_idxs_temp = 0;
+	int delay_count = 0;
+	bool is_timeout = true;
+	int i = 0;
+	int j = 0;
+	int mif_sub_ch_nums = 4;
+	int tmp = 0;
+	int mif_nums_max = 0;
+
+	BUG_ON(hisifd = NULL);
+	BUG_ON(pov_req = NULL);
+
+	dss_base = hisifd->dss_base;
+
+	if (mctl_idx <= DSS_MCTL1) {
+		mif_nums_max = DSS_WCHN_W0;
+	} else {
+		mif_nums_max = DSS_CHN_MAX;
+	}
+
+	if (mctl_idx = DSS_MCTL5) {
+		for (i = DSS_RCHN_V2; i < DSS_CHN_MAX_DEFINE; i++) {
+			is_timeout = false;
+
+			while (1) {
+				for (j = 1; j <= mif_sub_ch_nums; j++) {
+					tmp |+					    inp32(dss_base + DSS_MIF_OFFSET +
+						  MIF_STAT1 +
+						  0x10 * (i * mif_sub_ch_nums +j));
+				}
+
+				if (((tmp & 0x1f) = 0x0) || delay_count > 500) {
+					is_timeout +					    (delay_count > 500) ? true : false;
+					delay_count = 0;
+					break;
+				} else {
+					udelay(10);
+					++delay_count;
+				}
+			}
+
+			if (is_timeout) {
+				HISI_FB_ERR("mif_ch%d MIF_STAT1=0x%x !\n", i,
+					    tmp);
+			}
+		}
+
+		tmp_base = hisifd->dss_module.mif_ch_base[DSS_RCHN_V2];
+		if (tmp_base) {
+			set_reg(tmp_base + MIF_CTRL0, 0x0, 1, 0);
+		}
+
+		tmp_base = hisifd->dss_module.mif_ch_base[DSS_WCHN_W2];
+		if (tmp_base) {
+			set_reg(tmp_base + MIF_CTRL0, 0x0, 1, 0);
+		}
+	} else {
+		cmdlist_idxs_temp = cmdlist_idxs;
+		for (i = 0; i < mif_nums_max; i++) {
+			if ((cmdlist_idxs_temp & 0x1) = 0x1) {
+				is_timeout = false;
+
+				while (1) {
+					for (j = 1; j <= mif_sub_ch_nums; j++) {
+						tmp |+						    inp32(dss_base + DSS_MIF_OFFSET + MIF_STAT1 +
+							  0x10 * (i * mif_sub_ch_nums + j));
+					}
+					if (((tmp & 0x1f) = 0x0)
+					    || delay_count > 500) {
+						is_timeout +						    (delay_count > 500) ? true : false;
+						delay_count = 0;
+						break;
+					} else {
+						udelay(10);
+						++delay_count;
+					}
+				}
+
+				if (is_timeout) {
+					HISI_FB_ERR
+					    ("mif_ch%d MIF_STAT1=0x%x !\n", i, tmp);
+				}
+			}
+
+			cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+		}
+
+		cmdlist_idxs_temp = cmdlist_idxs;
+		for (i = 0; i < mif_nums_max; i++) {
+			if ((cmdlist_idxs_temp & 0x1) = 0x1) {
+				tmp_base = hisifd->dss_module.mif_ch_base[i];
+				if (tmp_base) {
+					set_reg(tmp_base + MIF_CTRL0, 0x0, 1,
+						0);
+				}
+			}
+			cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+		}
+	}
+	mdelay(5);
+
+	if (mctl_idx = DSS_MCTL5) {
+		tmp_base = hisifd->dss_module.mif_ch_base[DSS_RCHN_V2];
+		if (tmp_base) {
+			set_reg(tmp_base + MIF_CTRL0, 0x1, 1, 0);
+		}
+
+		tmp_base = hisifd->dss_module.mif_ch_base[DSS_WCHN_W2];
+		if (tmp_base) {
+			set_reg(tmp_base + MIF_CTRL0, 0x1, 1, 0);
+		}
+	} else {
+		cmdlist_idxs_temp = cmdlist_idxs;
+		for (i = 0; i < mif_nums_max; i++) {
+			if ((cmdlist_idxs_temp & 0x1) = 0x1) {
+				tmp_base = hisifd->dss_module.mif_ch_base[i];
+				if (tmp_base) {
+					set_reg(tmp_base + MIF_CTRL0, 0x1, 1,
+						0);
+				}
+			}
+			cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+		}
+	}
+}
+
+void hisi_cmdlist_config_reset(struct hisi_fb_data_type *hisifd,
+			       dss_overlay_t *pov_req, uint32_t cmdlist_idxs)
+{
+	char __iomem *dss_base = NULL;
+	char __iomem *cmdlist_base = NULL;
+	char __iomem *tmp_base = NULL;
+	struct hisi_panel_info *pinfo = NULL;
+
+	uint32_t offset = 0;
+	uint32_t cmdlist_idxs_temp = 0;
+	int i = 0;
+	int ovl_idx = 0;
+	int mctl_idx = 0;
+	int ints_temp = 0;
+	int start_sel = 0;
+	uint32_t start_sel_temp = 0;
+
+	BUG_ON(hisifd = NULL);
+	BUG_ON(pov_req = NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	dss_base = hisifd->dss_base;
+	cmdlist_base = dss_base + DSS_CMDLIST_OFFSET;
+	ovl_idx = pov_req->ovl_idx;
+	pinfo = &(hisifd->panel_info);
+
+	if (cmdlist_idxs = 0) return;
+
+	mctl_idx = ovl_idx;
+	if (pov_req->wb_compose_type = DSS_WB_COMPOSE_COPYBIT) {
+		mctl_idx = DSS_MCTL5;
+	}
+
+	offset = 0x40;
+	cmdlist_idxs_temp = HISI_DSS_CMDLIST_IDXS_MAX;
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if ((cmdlist_idxs_temp & 0x1) = 0x1) {
+			ints_temp +			    inp32(cmdlist_base + CMDLIST_CH0_INTS + i * offset);
+			start_sel +			    inp32(cmdlist_base + CMDLIST_CH0_CTRL + i * offset);
+
+			if (((ints_temp & 0x2) = 0x2)
+			    && ((start_sel & 0x1c) = 0)) {
+				set_reg(cmdlist_base + CMDLIST_CH0_CTRL + i * offset, 0x6, 3, 2);
+				start_sel_temp |= (1 << i);
+			}
+		}
+		cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+	}
+
+	tmp_base = hisifd->dss_module.mctl_base[mctl_idx];
+	if (tmp_base) {
+		set_reg(tmp_base + MCTL_CTL_CLEAR, 0x1, 1, 0);
+	}
+
+	hisi_cmdlist_config_mif_reset(hisifd, pov_req, cmdlist_idxs, mctl_idx);
+	cmdlist_idxs_temp = start_sel_temp;
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if ((cmdlist_idxs_temp & 0x1) = 0x1) {
+			set_reg(cmdlist_base + CMDLIST_CH0_CTRL + i * offset, mctl_idx, 3, 2);
+		}
+		cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+	}
+
+	if (mctl_idx >= DSS_MCTL2) {
+		offset = 0x40;
+		cmdlist_idxs_temp = cmdlist_idxs;
+		for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+			if ((cmdlist_idxs_temp & 0x1) = 0x1) {
+				set_reg(cmdlist_base + CMDLIST_CH0_CTRL +
+					i * offset, 0x6, 3, 2);
+				set_reg(cmdlist_base + CMDLIST_CH0_CTRL +
+					i * offset, 0x0, 1, 0);
+			}
+			cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+		}
+	}
+
+	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
+	return;
+}
+
+int hisi_cmdlist_config_stop(struct hisi_fb_data_type *hisifd,
+			     uint32_t cmdlist_pre_idxs)
+{
+	dss_overlay_t *pov_req = NULL;
+	char __iomem *cmdlist_base = NULL;
+	int i = 0;
+	uint32_t tmp = 0;
+	uint32_t offset = 0;
+	int ret = 0;
+
+	BUG_ON(hisifd = NULL);
+	pov_req = &(hisifd->ov_req);
+	cmdlist_base = hisifd->dss_base + DSS_CMDLIST_OFFSET;
+	offset = 0x40;
+
+	ret +	    hisi_cmdlist_add_new_node(hisifd, cmdlist_pre_idxs, 0, 1, 1, 1, 0);
+	if (ret != 0) {
+		HISI_FB_ERR("fb%d, hisi_cmdlist_add_new_node err:%d \n",
+			    hisifd->index, ret);
+		goto err_return;
+	}
+
+	for (i = 0; i < DSS_WCHN_W0; i++) {
+		tmp = (0x1 << i);
+		hisifd->cmdlist_idx = i;
+
+		if ((cmdlist_pre_idxs & tmp) = tmp) {
+			hisifd->set_reg(hisifd,
+					hisifd->dss_module.mctl_base[pov_req->
+								     ovl_idx] +
+					MCTL_CTL_MUTEX_RCH0 + i * 0x4, 0, 32,
+					0);
+			hisifd->set_reg(hisifd, cmdlist_base + CMDLIST_CH0_CTRL + i * offset, 0x6, 3, 2);
+		}
+	}
+
+	return 0;
+
+ err_return:
+	return ret;
+}
+
+void hisi_dss_cmdlist_qos_on(struct hisi_fb_data_type *hisifd)
+{
+	char __iomem *cmdlist_base = NULL;
+
+	BUG_ON(hisifd = NULL);
+
+	cmdlist_base = hisifd->dss_base + DSS_CMDLIST_OFFSET;
+	set_reg(cmdlist_base + CMDLIST_CTRL, 0x3, 2, 4);
+}
+
+void hisi_dump_cmdlist_node_items(cmd_item_t *item, uint32_t count)
+{
+	uint32_t index = 0;
+	uint32_t addr = 0;
+
+	for (index = 0; index < count; index++) {
+		addr = item[index].reg_addr.bits.add0;
+		addr = addr & CMDLIST_ADDR_OFFSET;
+		addr = addr << 2;
+		HISI_FB_INFO
+		    ("set addr:0x%x value:0x%x add1:0x%x value:0x%x "
+		     "add2:0x%x value:0x%x \n",
+		     addr, item[index].data0,
+		     item[index].reg_addr.bits.add1 << 2, item[index].data1,
+		     item[index].reg_addr.bits.add2 << 2, item[index].data2);
+	}
+}
+
+static void hisi_dump_cmdlist_content(struct list_head *cmdlist_head,
+				      char *filename, uint32_t addr)
+{
+	dss_cmdlist_node_t *node = NULL;
+	dss_cmdlist_node_t *_node_ = NULL;
+
+	BUG_ON(cmdlist_head = NULL);
+	BUG_ON(filename = NULL);
+
+	if (g_dump_cmdlist_content = 0)
+		return;
+
+	HISI_FB_INFO("%s\n", filename);
+
+	list_for_each_entry_safe(node, _node_, cmdlist_head, list_node) {
+		if (node->header_phys = addr) {
+			hisifb_save_file(filename, (char *)(node->list_header),
+					 CMDLIST_HEADER_LEN);
+		}
+
+		if (node->item_phys = addr) {
+			hisifb_save_file(filename, (char *)(node->list_item),
+					 CMDLIST_ITEM_LEN);
+		}
+	}
+}
+
+static void hisi_dump_cmdlist_one_node(struct list_head *cmdlist_head,
+				       uint32_t cmdlist_idx)
+{
+	dss_cmdlist_node_t *node = NULL;
+	dss_cmdlist_node_t *_node_ = NULL;
+	uint32_t count = 0;
+	int i = 0;
+	char filename[256] = { 0 };
+
+	BUG_ON(cmdlist_head = NULL);
+
+	list_for_each_entry_safe(node, _node_, cmdlist_head, list_node) {
+		if (node->node_type = CMDLIST_NODE_NOP) {
+			HISI_FB_INFO("node type = NOP node\n");
+		} else if (node->node_type = CMDLIST_NODE_FRAME) {
+			HISI_FB_INFO("node type = Frame node\n");
+		}
+
+		HISI_FB_INFO
+		    ("\t qos  | flag | pending | tast_end | last  | event_list | list_addr  | next_list  | count | id | is_used | reserved | cmdlist_idx\n");
+		HISI_FB_INFO
+		    ("\t ------+---------+------------+------------+------------+------------\n");
+		HISI_FB_INFO
+		    ("\t 0x%2x | 0x%2x |0x%6x | 0x%5x | 0x%3x | 0x%8x | 0x%8x | 0x%8x | 0x%3x | 0x%2x | 0x%2x | 0x%2x | 0x%2x\n",
+		     node->list_header->flag.bits.qos,
+		     node->list_header->flag.bits.valid_flag,
+		     node->list_header->flag.bits.pending,
+		     node->list_header->flag.bits.task_end,
+		     node->list_header->flag.bits.last,
+		     node->list_header->flag.bits.event_list,
+		     node->list_header->list_addr, node->list_header->next_list,
+		     node->list_header->total_items.bits.count,
+		     node->list_header->flag.bits.id, node->is_used,
+		     node->reserved, cmdlist_idx);
+
+		if (i = 0) {
+			snprintf(filename, 256,
+				 "/data/dssdump/list_start_0x%x.txt",
+				 (uint32_t) node->header_phys);
+			hisi_dump_cmdlist_content(cmdlist_head, filename,
+						  node->header_phys);
+		}
+#if 0
+		if ((node->list_header->next_list != 0x0) &&
+		    (node->list_header->next_list != 0xFFFFFFFF)) {
+			snprintf(filename, 256,
+				 "/data/dssdump/next_list_0x%x.txt",
+				 node->list_header->next_list);
+			hisi_dump_cmdlist_content(cmdlist_head, filename,
+						  node->list_header->next_list);
+		}
+
+		if ((node->list_header->list_addr != 0x0) &&
+		    (node->list_header->list_addr != 0xFFFFFFFF)) {
+			snprintf(filename, 256,
+				 "/data/dssdump/list_addr_0x%x.txt",
+				 node->list_header->list_addr);
+			hisi_dump_cmdlist_content(cmdlist_head, filename,
+						  node->list_header->list_addr);
+		}
+#endif
+		count = node->list_header->total_items.bits.count;
+		hisi_dump_cmdlist_node_items(node->list_item, count);
+
+		i++;
+	}
+}
+
+int hisi_cmdlist_dump_all_node(struct hisi_fb_data_type *hisifd,
+			       dss_overlay_t *pov_req, uint32_t cmdlist_idxs)
+{
+	int i = 0;
+	uint32_t cmdlist_idxs_temp = 0;
+	uint32_t wb_compose_type = 0;
+
+	BUG_ON(hisifd = NULL);
+
+	if (pov_req) {
+		if (pov_req->wb_enable)
+			wb_compose_type = pov_req->wb_compose_type;
+	}
+
+	cmdlist_idxs_temp = cmdlist_idxs;
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if (0x1 = (cmdlist_idxs_temp & 0x1)) {
+			if (pov_req && pov_req->wb_enable) {
+				hisi_dump_cmdlist_one_node(&(hisifd->cmdlist_data_tmp
+							    [wb_compose_type]->cmdlist_head_temp[i]), i);
+			} else {
+				hisi_dump_cmdlist_one_node(&
+							   (hisifd->cmdlist_data->cmdlist_head_temp[i]), i);
+			}
+		}
+		cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+	}
+
+	return 0;
+}
+
+int hisi_cmdlist_del_node(struct hisi_fb_data_type *hisifd,
+			  dss_overlay_t *pov_req, uint32_t cmdlist_idxs)
+{
+	int i = 0;
+	uint32_t cmdlist_idxs_temp = 0;
+	uint32_t wb_compose_type = 0;
+
+	BUG_ON(hisifd = NULL);
+
+	if (pov_req) {
+		if (pov_req->wb_enable)
+			wb_compose_type = pov_req->wb_compose_type;
+	}
+
+	cmdlist_idxs_temp = cmdlist_idxs;
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if ((cmdlist_idxs_temp & 0x1) = 0x1) {
+			if (pov_req && pov_req->wb_enable) {
+				hisi_cmdlist_del_all_node(&(hisifd->cmdlist_data_tmp
+							   [wb_compose_type]->cmdlist_head_temp[i]));
+			} else {
+				hisi_cmdlist_del_all_node(&
+							  (hisifd->cmdlist_data->cmdlist_head_temp[i]));
+			}
+		}
+		cmdlist_idxs_temp = (cmdlist_idxs_temp >> 1);
+	}
+
+	return 0;
+}
+
+static dss_cmdlist_data_t *hisi_cmdlist_data_alloc(struct hisi_fb_data_type
+						   *hisifd)
+{
+	int i = 0;
+	int j = 0;
+	dss_cmdlist_data_t *cmdlist_data = NULL;
+
+	BUG_ON(hisifd = NULL);
+
+	cmdlist_data +	    (dss_cmdlist_data_t *) kmalloc(sizeof(dss_cmdlist_data_t),
+					   GFP_ATOMIC);
+	if (cmdlist_data) {
+		memset(cmdlist_data, 0, sizeof(dss_cmdlist_data_t));
+	} else {
+		HISI_FB_ERR("failed to kmalloc cmdlist_data!\n");
+		return NULL;
+	}
+
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		INIT_LIST_HEAD(&(cmdlist_data->cmdlist_head_temp[i]));
+
+		for (j = 0; j < HISI_DSS_CMDLIST_NODE_MAX; j++) {
+			cmdlist_data->cmdlist_nodes_temp[i][j] +			    hisi_cmdlist_node_alloc(hisifd->ion_client);
+			if (cmdlist_data->cmdlist_nodes_temp[i][j] = NULL) {
+				HISI_FB_ERR
+				    ("failed to hisi_cmdlist_node_alloc!\n");
+				kfree(cmdlist_data);
+				return NULL;
+			}
+		}
+	}
+
+	return cmdlist_data;
+}
+
+static void hisi_cmdlist_data_free(struct hisi_fb_data_type *hisifd,
+				   dss_cmdlist_data_t *cmdlist_data)
+{
+	int i = 0;
+	int j = 0;
+
+	BUG_ON(hisifd = NULL);
+	BUG_ON(cmdlist_data = NULL);
+
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		for (j = 0; j < HISI_DSS_CMDLIST_NODE_MAX; j++) {
+			hisi_cmdlist_node_free(hisifd->ion_client,
+					       hisifd->cmdlist_data->cmdlist_nodes_temp[i][j]);
+		}
+	}
+}
+
+static dss_cmdlist_info_t *hisi_cmdlist_info_alloc(struct hisi_fb_data_type
+						   *hisifd)
+{
+	int i = 0;
+	dss_cmdlist_info_t *cmdlist_info = NULL;
+
+	BUG_ON(hisifd = NULL);
+
+	cmdlist_info +	    (dss_cmdlist_info_t *) kmalloc(sizeof(dss_cmdlist_info_t), GFP_ATOMIC);
+	if (cmdlist_info) {
+		memset(cmdlist_info, 0, sizeof(dss_cmdlist_info_t));
+	} else {
+		HISI_FB_ERR("failed to kmalloc cmdlist_info!\n");
+		return NULL;
+	}
+
+	sema_init(&(cmdlist_info->cmdlist_wb_common_sem), 1);
+
+	for (i = 0; i < WB_TYPE_MAX; i++) {
+		sema_init(&(cmdlist_info->cmdlist_wb_sem[i]), 1);
+		init_waitqueue_head(&(cmdlist_info->cmdlist_wb_wq[i]));
+		cmdlist_info->cmdlist_wb_done[i] = 0;
+		cmdlist_info->cmdlist_wb_flag[i] = 0;
+	}
+
+	return cmdlist_info;
+}
+
+static dss_copybit_info_t *hisi_copybit_info_alloc(struct hisi_fb_data_type
+						   *hisifd)
+{
+	dss_copybit_info_t *copybit_info = NULL;
+
+	BUG_ON(hisifd = NULL);
+
+	copybit_info +	    (dss_copybit_info_t *) kmalloc(sizeof(dss_copybit_info_t),
+					   GFP_ATOMIC);
+	if (copybit_info) {
+		memset(copybit_info, 0, sizeof(dss_copybit_info_t));
+	} else {
+		HISI_FB_ERR("failed to kmalloc copybit_info!\n");
+		return NULL;
+	}
+
+	sema_init(&(copybit_info->copybit_sem), 1);
+
+	init_waitqueue_head(&(copybit_info->copybit_wq));
+	copybit_info->copybit_done = 0;
+
+	return copybit_info;
+}
+
+void hisi_cmdlist_data_get_online(struct hisi_fb_data_type *hisifd)
+{
+	int tmp = 0;
+
+	BUG_ON(hisifd = NULL);
+
+	tmp = (hisifd->frame_count + 1) % HISI_DSS_CMDLIST_DATA_MAX;
+	hisifd->cmdlist_data = hisifd->cmdlist_data_tmp[tmp];
+	hisi_cmdlist_del_node(hisifd, NULL, HISI_DSS_CMDLIST_IDXS_MAX);
+
+	tmp = hisifd->frame_count % HISI_DSS_CMDLIST_DATA_MAX;
+	hisifd->cmdlist_data = hisifd->cmdlist_data_tmp[tmp];
+	hisi_cmdlist_del_node(hisifd, NULL, HISI_DSS_CMDLIST_IDXS_MAX);
+}
+
+int hisi_cmdlist_init(struct hisi_fb_data_type *hisifd)
+{
+	int ret = 0;
+	int i = 0;
+
+	BUG_ON(hisifd = NULL);
+
+	for (i = 0; i < HISI_DSS_CMDLIST_BLOCK_MAX; i++) {
+		hisifd->ov_block_rects[i] +		    (dss_rect_t *) kmalloc(sizeof(dss_rect_t), GFP_ATOMIC);
+		if (!hisifd->ov_block_rects[i]) {
+			HISI_FB_ERR("ov_block_rects[%d] failed to alloc!", i);
+			return -EINVAL;
+		}
+	}
+
+	if (hisifd->index = AUXILIARY_PANEL_IDX) {
+		hisifd->cmdlist_data_tmp[0] = hisi_cmdlist_data_alloc(hisifd);
+		hisifd->cmdlist_data_tmp[1] = hisi_cmdlist_data_alloc(hisifd);
+		hisifd->cmdlist_info = hisi_cmdlist_info_alloc(hisifd);
+		hisifd->copybit_info = hisi_copybit_info_alloc(hisifd);
+	} else {
+		if (hisifd->index = PRIMARY_PANEL_IDX
+		    || (hisifd->index = EXTERNAL_PANEL_IDX
+			&& !hisifd->panel_info.fake_hdmi)) {
+			for (i = 0; i < HISI_DSS_CMDLIST_DATA_MAX; i++) {
+				hisifd->cmdlist_data_tmp[i] +				    hisi_cmdlist_data_alloc(hisifd);
+			}
+		}
+	}
+
+	hisifd->cmdlist_data = hisifd->cmdlist_data_tmp[0];
+	hisifd->cmdlist_idx = -1;
+
+	return ret;
+}
+
+int hisi_cmdlist_deinit(struct hisi_fb_data_type *hisifd)
+{
+	int i = 0;
+
+	BUG_ON(hisifd = NULL);
+
+	for (i = 0; i < HISI_DSS_CMDLIST_BLOCK_MAX; i++) {
+		if (hisifd->ov_block_rects[i]) {
+			kfree(hisifd->ov_block_rects[i]);
+			hisifd->ov_block_rects[i] = NULL;
+		}
+	}
+
+	for (i = 0; i < HISI_DSS_CMDLIST_DATA_MAX; i++) {
+		if (hisifd->cmdlist_data_tmp[i]) {
+			hisi_cmdlist_data_free(hisifd,
+					       hisifd->cmdlist_data_tmp[i]);
+			kfree(hisifd->cmdlist_data_tmp[i]);
+			hisifd->cmdlist_data_tmp[i] = NULL;
+		}
+	}
+
+	if (hisifd->index = AUXILIARY_PANEL_IDX) {
+		if (hisifd->cmdlist_info) {
+			kfree(hisifd->cmdlist_info);
+			hisifd->cmdlist_info = NULL;
+		}
+
+		if (hisifd->copybit_info) {
+			kfree(hisifd->copybit_info);
+			hisifd->copybit_info = NULL;
+		}
+	}
+
+	return 0;
+}
diff --git a/drivers/video/fbdev/hisi/dss/hisi_overlay_cmdlist_utils.h b/drivers/video/fbdev/hisi/dss/hisi_overlay_cmdlist_utils.h
new file mode 100755
index 000000000000..5f5d8c0fd506
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_overlay_cmdlist_utils.h
@@ -0,0 +1,249 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+#ifndef _CMD_LIST_UTILS_H_
+#define _CMD_LIST_UTILS_H_
+#include "hisi_overlay_utils_hi3660.h"
+
+#define HISI_DSS_CMDLIST_DATA_MAX	(3)
+#define HISI_DSS_CMDLIST_NODE_MAX	(32)
+#define HISI_DSS_CMDLIST_BLOCK_MAX	(32)
+
+#define HISI_DSS_SUPPORT_DPP_MODULE_BIT(module) \
+	(BIT(module) & HISI_DSS_DPP_MAX_SUPPORT_BIT)
+
+enum dpp_module_idx {
+	DPP_MODULE_POST_SCF = 0,
+	DPP_MODULE_DBUF,
+	DPP_MODULE_SBL,
+	DPP_MODULE_ACM,
+	DPP_MODULE_ACE,
+	DPP_MODULE_LCP_IGM,
+	DPP_MODULE_LCP_GMP,
+	DPP_MODULE_LCP_XCC,
+	DPP_MODULE_GAMA,
+	DPP_MODULE_DITHER,
+	DPP_MODULE_IFBC,
+	DPP_MODULE_MAX
+};
+
+enum wb_type {
+	WB_TYPE_WCH0,
+	WB_TYPE_WCH1,
+	WB_TYPE_WCH2,
+	WB_TYPE_WCH0_WCH1,
+
+	WB_TYPE_MAX,
+};
+
+enum dss_cmdlist_idx {
+	DSS_CMDLIST_NONE = -1,
+	DSS_CMDLIST_D2 = 0,
+	DSS_CMDLIST_D3,
+	DSS_CMDLIST_V0,
+	DSS_CMDLIST_G0,
+	DSS_CMDLIST_V1,
+	DSS_CMDLIST_G1,
+	DSS_CMDLIST_D0,
+	DSS_CMDLIST_D1,
+
+	DSS_CMDLIST_W0,
+	DSS_CMDLIST_W1,
+
+	DSS_CMDLIST_OV0,
+	DSS_CMDLIST_OV1,
+	DSS_CMDLIST_OV2,
+	DSS_CMDLIST_OV3,
+
+	DSS_CMDLIST_V2,
+	DSS_CMDLIST_W2,
+	DSS_CMDLIST_MAX,
+};
+
+typedef union {
+	struct {
+		uint32_t exec:1;
+		uint32_t last:1;
+		uint32_t nop:1;
+		uint32_t interrupt:1;
+		uint32_t pending:1;
+		uint32_t id:10;
+		uint32_t event_list:6;
+		uint32_t qos:1;
+		uint32_t task_end:1;
+		uint32_t reserved:1;
+		uint32_t valid_flag:8;
+	} bits;
+	uint32_t ul32;
+} cmd_flag_t;
+
+typedef union {
+	struct {
+		uint32_t count:14;
+		uint32_t reserved:18;
+	} bits;
+	uint32_t ul32;
+} total_items_t;
+
+typedef union {
+	struct {
+		uint32_t add0:18;
+		uint32_t add1:6;
+		uint32_t add2:6;
+		uint32_t cnt:2;
+	} bits;
+	uint32_t ul32;
+} reg_addr_t;
+
+typedef struct cmd_item {
+	reg_addr_t reg_addr;
+	uint32_t data0;
+	uint32_t data1;
+	uint32_t data2;
+} cmd_item_t;
+
+typedef struct cmd_header {
+	cmd_flag_t flag;
+	uint32_t next_list;
+	total_items_t total_items;
+	uint32_t list_addr;
+} cmd_header_t;
+
+enum dss_cmdlist_node_valid {
+	CMDLIST_NODE_INVALID = 0x0,
+	CMDLIST_NODE_VALID = 0xA5,
+};
+
+enum dss_cmdlist_node_type {
+	CMDLIST_NODE_NONE = 0x0,
+	CMDLIST_NODE_NOP = 0x1,
+	CMDLIST_NODE_FRAME = 0x2,
+};
+
+enum dss_cmdlist_status {
+	e_status_idle = 0x0,
+	e_status_wait = 0x1,
+	e_status_other,
+};
+
+/*
+ ** for normal node,all variable should be filled.
+ ** for NOP node, just the list_header,header_ion_handle, list_node, node_flag should be filled.
+ ** node_type must be CMDLIST_NODE_NOP when it is NOP node.
+ ** And item_ion_handle in NOP node should be NULL.
+ */
+typedef struct dss_cmdlist_node {
+	struct list_head list_node;
+
+	struct ion_handle *header_ion_handle;
+	ion_phys_addr_t header_phys;
+	cmd_header_t *list_header;
+
+	struct ion_handle *item_ion_handle;
+	ion_phys_addr_t item_phys;
+	cmd_item_t *list_item;
+
+	uint32_t item_index;
+	int item_flag;
+	uint32_t node_type;
+	int is_used;
+	int reserved;
+} dss_cmdlist_node_t;
+
+typedef struct dss_cmdlist_heads {
+	struct list_head cmdlist_head;
+
+	dss_cmdlist_node_t *cmdlist_nodes[HISI_DSS_CMDLIST_NODE_MAX];
+} dss_cmdlist_heads_t;
+
+typedef struct dss_cmdlist_data {
+	dss_cmdlist_heads_t *cmdlist_heads[HISI_DSS_CMDLIST_MAX];
+	struct list_head cmdlist_head_temp[HISI_DSS_CMDLIST_MAX];
+	dss_cmdlist_node_t
+	    *cmdlist_nodes_temp[HISI_DSS_CMDLIST_MAX]
+	    [HISI_DSS_CMDLIST_NODE_MAX];
+} dss_cmdlist_data_t;
+
+typedef struct dss_cmdlist_info {
+	struct semaphore cmdlist_wb_common_sem;
+	struct semaphore cmdlist_wb_sem[WB_TYPE_MAX];
+	wait_queue_head_t cmdlist_wb_wq[WB_TYPE_MAX];
+	uint32_t cmdlist_wb_done[WB_TYPE_MAX];
+	uint32_t cmdlist_wb_flag[WB_TYPE_MAX];
+} dss_cmdlist_info_t;
+
+typedef struct dss_copybit_info {
+	struct semaphore copybit_sem;
+	wait_queue_head_t copybit_wq;
+	uint32_t copybit_flag;
+	uint32_t copybit_done;
+} dss_copybit_info_t;
+
+typedef struct dss_wb_info {
+	uint32_t to_be_continued;
+	uint32_t cmdlist_idxs;
+	uint32_t wb_compose_type;
+	uint32_t mctl_idx;
+} dss_wb_info_t;
+
+extern dss_cmdlist_data_t *g_cmdlist_data;
+
+/******************************************************************************
+ ** FUNCTIONS PROTOTYPES
+ */
+void hisi_cmdlist_set_reg(struct hisi_fb_data_type *hisifd,
+			  char __iomem *addr, uint32_t value, uint8_t bw,
+			  uint8_t bs);
+void hisi_cmdlist_flush_cache(struct hisi_fb_data_type *hisifd,
+			      struct ion_client *ion_client,
+			      uint32_t cmdlist_idxs);
+
+dss_cmdlist_node_t *hisi_cmdlist_node_alloc(struct ion_client *ion_client);
+void hisi_cmdlist_node_free(struct ion_client *ion_client,
+			    dss_cmdlist_node_t *node);
+
+uint32_t hisi_cmdlist_get_cmdlist_need_start(struct hisi_fb_data_type *hisifd,
+					     uint32_t cmdlist_idxs);
+
+int hisi_cmdlist_get_cmdlist_idxs(dss_overlay_t *pov_req,
+				  uint32_t *cmdlist_pre_idxs,
+				  uint32_t *cmdlist_idxs);
+void hisi_cmdlist_data_get_online(struct hisi_fb_data_type *hisifd);
+
+int hisi_cmdlist_add_nop_node(struct hisi_fb_data_type *hisifd,
+			      uint32_t cmdlist_idxs, int pending, int reserved);
+int hisi_cmdlist_add_new_node(struct hisi_fb_data_type *hisifd,
+			      uint32_t cmdlist_idxs, int pending, int task_end,
+			      int remove, int last, uint32_t wb_type);
+int hisi_cmdlist_del_all_node(struct list_head *cmdlist_heads);
+
+int hisi_cmdlist_config_start(struct hisi_fb_data_type *hisifd, int mctl_idx,
+			      uint32_t cmdlist_idxs, uint32_t wb_compose_type);
+int hisi_cmdlist_config_stop(struct hisi_fb_data_type *hisifd,
+			     uint32_t cmdlist_idxs);
+void hisi_cmdlist_config_reset(struct hisi_fb_data_type *hisifd,
+			       dss_overlay_t *pov_req, uint32_t cmdlist_idxs);
+
+int hisi_cmdlist_del_node(struct hisi_fb_data_type *hisifd,
+			  dss_overlay_t *pov_req, uint32_t cmdlist_idxs);
+int hisi_cmdlist_check_cmdlist_state(struct hisi_fb_data_type *hisifd,
+				     uint32_t cmdlist_idxs);
+
+int hisi_cmdlist_exec(struct hisi_fb_data_type *hisifd, uint32_t cmdlist_idxs);
+void hisi_dss_cmdlist_qos_on(struct hisi_fb_data_type *hisifd);
+int hisi_cmdlist_dump_all_node(struct hisi_fb_data_type *hisifd,
+			       dss_overlay_t *pov_req, uint32_t cmdlist_idxs);
+
+int hisi_cmdlist_init(struct hisi_fb_data_type *hisifd);
+int hisi_cmdlist_deinit(struct hisi_fb_data_type *hisifd);
+
+#endif
-- 
2.12.0-rc0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 7/8] fb: hisilicon: Add framebuffer driver for hi3660 SoC
  2017-02-07  2:35   ` cailiwei
                     ` (5 preceding siblings ...)
  (?)
@ 2017-02-07  2:35   ` cailiwei
  -1 siblings, 0 replies; 15+ messages in thread
From: cailiwei @ 2017-02-07  2:35 UTC (permalink / raw)
  To: linux-fbdev, linux-kernel, b.zolnierkie, guodong.xu
  Cc: suzhuangluan, dengqingshan, xuhongtao8, zhengwanchun,
	shizongxuan, cailiwei

From: Levy-Cai <cailiwei@hisilicon.com>

Add framebuffer driver for hi3660 SoC, this driver include lcd
driver & Hdmi adv7533/adv7535 driver, support lcd display at
1080p@60 and hdmi display at 1080p@60.

Signed-off-by: cailiwei <cailiwei@hisilicon.com>
---
 drivers/video/fbdev/hisi/dss/hisi_overlay_online.c |  733 ++
 drivers/video/fbdev/hisi/dss/hisi_overlay_utils.c  | 8495 ++++++++++++++++++++
 drivers/video/fbdev/hisi/dss/hisi_overlay_utils.h  |  269 +
 .../fbdev/hisi/dss/hisi_overlay_utils_hi3660.c     | 2741 +++++++
 .../fbdev/hisi/dss/hisi_overlay_utils_hi3660.h     |   73 +
 5 files changed, 12311 insertions(+)
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_overlay_online.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_overlay_utils.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_overlay_utils.h
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_overlay_utils_hi3660.c
 create mode 100755 drivers/video/fbdev/hisi/dss/hisi_overlay_utils_hi3660.h

diff --git a/drivers/video/fbdev/hisi/dss/hisi_overlay_online.c b/drivers/video/fbdev/hisi/dss/hisi_overlay_online.c
new file mode 100755
index 000000000000..9cb65225dc63
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_overlay_online.c
@@ -0,0 +1,733 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_overlay_utils.h"
+#include "hisi_dpe_utils.h"
+
+static int hisi_get_ov_data_from_user(struct hisi_fb_data_type *hisifd,
+				      dss_overlay_t *pov_req,
+				      void __user *argp)
+{
+	int ret = 0;
+	dss_overlay_block_t *pov_h_block_infos = NULL;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_req == NULL);
+
+	if (NULL == argp) {
+		HISI_FB_ERR("user data is invalid\n");
+		return -EINVAL;
+	}
+	pov_h_block_infos = hisifd->ov_block_infos;
+
+	ret = copy_from_user(pov_req, argp, sizeof(dss_overlay_t));
+	if (ret) {
+		HISI_FB_ERR("fb%d, copy_from_user failed!\n", hisifd->index);
+		return -EINVAL;
+	}
+
+	if ((pov_req->ov_block_nums <= 0) ||
+	    (pov_req->ov_block_nums > HISI_DSS_OV_BLOCK_NUMS)) {
+		HISI_FB_ERR("fb%d, ov_block_nums(%d) is out of range!\n",
+			    hisifd->index, pov_req->ov_block_nums);
+		return -EINVAL;
+	}
+
+	ret =
+	    copy_from_user(pov_h_block_infos,
+			   (dss_overlay_block_t *) pov_req->ov_block_infos_ptr,
+			   pov_req->ov_block_nums *
+			   sizeof(dss_overlay_block_t));
+	if (ret) {
+		HISI_FB_ERR
+		    ("fb%d, dss_overlay_block_t copy_from_user failed!\n",
+		     hisifd->index);
+		return -EINVAL;
+	}
+
+	ret = hisi_dss_check_userdata(hisifd, pov_req, pov_h_block_infos);
+	if (ret != 0) {
+		HISI_FB_ERR("fb%d, hisi_dss_check_userdata failed!\n",
+			    hisifd->index);
+		return -EINVAL;
+	}
+
+	pov_req->ov_block_infos_ptr = (uint64_t) pov_h_block_infos;
+
+	return ret;
+}
+
+int hisi_overlay_pan_display(struct hisi_fb_data_type *hisifd)
+{
+	int ret = 0;
+	struct fb_info *fbi = NULL;
+	dss_overlay_t *pov_req = NULL;
+	dss_overlay_t *pov_req_prev = NULL;
+	dss_overlay_block_t *pov_h_block_infos = NULL;
+	dss_overlay_block_t *pov_h_block = NULL;
+	dss_layer_t *layer = NULL;
+	dss_rect_ltrb_t clip_rect;
+	dss_rect_t aligned_rect;
+	bool rdma_stretch_enable = false;
+	uint32_t offset = 0;
+	uint32_t addr = 0;
+	int hal_format = 0;
+	uint32_t cmdlist_pre_idxs = 0;
+	uint32_t cmdlist_idxs = 0;
+	int enable_cmdlist = 0;
+	bool has_base = false;
+
+	if (NULL == hisifd) {
+		HISI_FB_ERR("hisi fd is invalid\n");
+		return -EINVAL;
+	}
+	fbi = hisifd->fbi;
+	if (NULL == fbi) {
+		HISI_FB_ERR("hisifd fbi is invalid\n");
+		return -EINVAL;
+	}
+
+	pov_req = &(hisifd->ov_req);
+	pov_req_prev = &(hisifd->ov_req_prev);
+
+	if (!hisifd->panel_power_on) {
+		HISI_FB_INFO("fb%d, panel is power off!", hisifd->index);
+		return 0;
+	}
+
+	if (g_debug_ldi_underflow) {
+		if (g_err_status &
+		    (DSS_PDP_LDI_UNDERFLOW | DSS_SDP_LDI_UNDERFLOW))
+			return 0;
+	}
+
+	offset = fbi->var.xoffset * (fbi->var.bits_per_pixel >> 3) +
+	    fbi->var.yoffset * fbi->fix.line_length;
+	addr = fbi->fix.smem_start + offset;
+	if (!fbi->fix.smem_start) {
+		HISI_FB_ERR("fb%d, smem_start is null!\n", hisifd->index);
+		return -EINVAL;
+	}
+
+	if (fbi->fix.smem_len <= 0) {
+		HISI_FB_ERR("fb%d, smem_len(%d) is out of range!\n",
+			    hisifd->index, fbi->fix.smem_len);
+		return -EINVAL;
+	}
+
+	hal_format = hisi_get_hal_format(fbi);
+	if (hal_format < 0) {
+		HISI_FB_ERR("fb%d, not support this fb_info's format!\n",
+			    hisifd->index);
+		return -EINVAL;
+	}
+
+	enable_cmdlist = g_enable_ovl_cmdlist_online;
+	if ((hisifd->index == EXTERNAL_PANEL_IDX)
+	    && hisifd->panel_info.fake_hdmi)
+		enable_cmdlist = 0;
+
+	hisifb_activate_vsync(hisifd);
+
+	ret = hisi_vactive0_start_config(hisifd, pov_req);
+	if (ret != 0) {
+		HISI_FB_ERR
+		    ("fb%d, hisi_vactive0_start_config failed! ret = %d\n",
+		     hisifd->index, ret);
+		goto err_return;
+	}
+
+	if (g_debug_ovl_online_composer == 1) {
+		dumpDssOverlay(hisifd, pov_req, false);
+	}
+
+	memset(pov_req, 0, sizeof(dss_overlay_t));
+	pov_req->ov_block_infos_ptr = (uint64_t) (&(hisifd->ov_block_infos));
+	pov_req->ov_block_nums = 1;
+	pov_req->ovl_idx = DSS_OVL0;
+	pov_req->dirty_rect.x = 0;
+	pov_req->dirty_rect.y = 0;
+	pov_req->dirty_rect.w = fbi->var.xres;
+	pov_req->dirty_rect.h = fbi->var.yres;
+
+	pov_req->res_updt_rect.x = 0;
+	pov_req->res_updt_rect.y = 0;
+	pov_req->res_updt_rect.w = fbi->var.xres;
+	pov_req->res_updt_rect.h = fbi->var.yres;
+
+	pov_h_block_infos =
+	    (dss_overlay_block_t *) (pov_req->ov_block_infos_ptr);
+	pov_h_block = &(pov_h_block_infos[0]);
+	pov_h_block->layer_nums = 1;
+
+	layer = &(pov_h_block->layer_infos[0]);
+	layer->img.format = hal_format;
+	layer->img.width = fbi->var.xres;
+	layer->img.height = fbi->var.yres;
+	layer->img.bpp = fbi->var.bits_per_pixel >> 3;
+	layer->img.stride = fbi->fix.line_length;
+	layer->img.buf_size = layer->img.stride * layer->img.height;
+	layer->img.phy_addr = addr;
+	layer->img.vir_addr = addr;
+	layer->img.mmu_enable = 1;
+	layer->src_rect.x = 0;
+	layer->src_rect.y = 0;
+	layer->src_rect.w = fbi->var.xres;
+	layer->src_rect.h = fbi->var.yres;
+	layer->dst_rect.x = 0;
+	layer->dst_rect.y = 0;
+	layer->dst_rect.w = fbi->var.xres;
+	layer->dst_rect.h = fbi->var.yres;
+	layer->transform = HISI_FB_TRANSFORM_NOP;
+	layer->blending = HISI_FB_BLENDING_NONE;
+	layer->glb_alpha = 0xFF;
+	layer->color = 0x0;
+	layer->layer_idx = 0x0;
+	layer->chn_idx = DSS_RCHN_D2;
+	layer->need_cap = 0;
+
+	hisi_dss_handle_cur_ovl_req(hisifd, pov_req);
+
+	ret = hisi_dss_module_init(hisifd);
+	if (ret != 0) {
+		HISI_FB_ERR("fb%d, hisi_dss_module_init failed! ret = %d\n",
+			    hisifd->index, ret);
+		goto err_return;
+	}
+
+	hisi_mmbuf_info_get_online(hisifd);
+
+	if (enable_cmdlist) {
+		hisifd->set_reg = hisi_cmdlist_set_reg;
+
+		hisi_cmdlist_data_get_online(hisifd);
+
+		ret =
+		    hisi_cmdlist_get_cmdlist_idxs(pov_req_prev,
+						  &cmdlist_pre_idxs, NULL);
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("fb%d, hisi_cmdlist_get_cmdlist_idxs pov_req_prev failed! "
+			     "ret = %d\n",
+			     hisifd->index, ret);
+			goto err_return;
+		}
+
+		ret =
+		    hisi_cmdlist_get_cmdlist_idxs(pov_req, &cmdlist_pre_idxs,
+						  &cmdlist_idxs);
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("fb%d, hisi_cmdlist_get_cmdlist_idxs pov_req failed! "
+			     "ret = %d\n",
+			     hisifd->index, ret);
+			goto err_return;
+		}
+
+		hisi_cmdlist_add_nop_node(hisifd, cmdlist_pre_idxs, 0, 0);
+		hisi_cmdlist_add_nop_node(hisifd, cmdlist_idxs, 0, 0);
+	} else {
+		hisifd->set_reg = hisifb_set_reg;
+
+		hisi_dss_mctl_mutex_lock(hisifd, pov_req->ovl_idx);
+		cmdlist_pre_idxs = ~0;
+	}
+
+	hisi_dss_prev_module_set_regs(hisifd, pov_req_prev, cmdlist_pre_idxs,
+				      enable_cmdlist, NULL);
+
+	hisi_dss_aif_handler(hisifd, pov_req, pov_h_block);
+
+	ret =
+	    hisi_dss_ovl_base_config(hisifd, pov_req, NULL, NULL,
+				     pov_req->ovl_idx, 0);
+	if (ret != 0) {
+		HISI_FB_ERR("fb%d, hisi_dss_ovl_init failed! ret = %d\n",
+			    hisifd->index, ret);
+		goto err_return;
+	}
+
+	ret =
+	    hisi_ov_compose_handler(hisifd, pov_req, pov_h_block, layer, NULL,
+				    NULL, &clip_rect, &aligned_rect,
+				    &rdma_stretch_enable, &has_base, true,
+				    enable_cmdlist);
+	if (ret != 0) {
+		HISI_FB_ERR("hisi_ov_compose_handler failed! ret = %d\n", ret);
+		goto err_return;
+	}
+
+	ret =
+	    hisi_dss_mctl_ov_config(hisifd, pov_req, pov_req->ovl_idx, has_base,
+				    true);
+	if (ret != 0) {
+		HISI_FB_ERR("fb%d, hisi_dss_mctl_config failed! ret = %d\n",
+			    hisifd->index, ret);
+		goto err_return;
+	}
+
+	if (hisifd->panel_info.dirty_region_updt_support) {
+		ret = hisi_dss_dirty_region_dbuf_config(hisifd, pov_req);
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("fb%d, hisi_dss_dirty_region_dbuf_config failed! ret = %d\n",
+			     hisifd->index, ret);
+			goto err_return;
+		}
+	}
+
+	ret = hisi_dss_post_scf_config(hisifd, pov_req);
+	if (ret != 0) {
+		HISI_FB_ERR("fb%d, hisi_dss_post_scf_config failed! ret = %d\n",
+			    hisifd->index, ret);
+		goto err_return;
+	}
+
+	ret =
+	    hisi_dss_ov_module_set_regs(hisifd, pov_req, pov_req->ovl_idx,
+					enable_cmdlist, 0, 0, true);
+	if (ret != 0) {
+		HISI_FB_ERR("fb%d, hisi_dss_module_config failed! ret = %d\n",
+			    hisifd->index, ret);
+		goto err_return;
+	}
+	hisi_dss_unflow_handler(hisifd, pov_req, true);
+
+	if (enable_cmdlist) {
+		hisi_cmdlist_add_nop_node(hisifd, cmdlist_idxs, 0, 0);
+		hisi_cmdlist_config_stop(hisifd, cmdlist_pre_idxs);
+
+		cmdlist_idxs |= cmdlist_pre_idxs;
+		hisi_cmdlist_flush_cache(hisifd, hisifd->ion_client,
+					 cmdlist_idxs);
+
+		if (g_debug_ovl_cmdlist) {
+			hisi_cmdlist_dump_all_node(hisifd, NULL, cmdlist_idxs);
+		}
+
+		hisi_cmdlist_config_start(hisifd, pov_req->ovl_idx,
+					  cmdlist_idxs, 0);
+	} else {
+		hisi_dss_mctl_mutex_unlock(hisifd, pov_req->ovl_idx);
+	}
+
+	if (hisifd->panel_info.dirty_region_updt_support) {
+		hisi_dss_dirty_region_updt_config(hisifd, pov_req);
+	}
+
+	single_frame_update(hisifd);
+	hisifb_frame_updated(hisifd);
+
+	hisifb_deactivate_vsync(hisifd);
+
+	hisifd->frame_count++;
+	memcpy(&hisifd->ov_req_prev_prev, &hisifd->ov_req_prev,
+	       sizeof(dss_overlay_t));
+	memcpy(&(hisifd->ov_block_infos_prev_prev),
+	       &(hisifd->ov_block_infos_prev),
+	       hisifd->ov_req_prev.ov_block_nums * sizeof(dss_overlay_block_t));
+	hisifd->ov_req_prev_prev.ov_block_infos_ptr =
+	    (uint64_t) (&(hisifd->ov_block_infos_prev_prev));
+
+	memcpy(&hisifd->ov_req_prev, pov_req, sizeof(dss_overlay_t));
+	memcpy(&(hisifd->ov_block_infos_prev), &(hisifd->ov_block_infos),
+	       pov_req->ov_block_nums * sizeof(dss_overlay_block_t));
+	hisifd->ov_req_prev.ov_block_infos_ptr =
+	    (uint64_t) (&(hisifd->ov_block_infos_prev));
+
+	return 0;
+
+ err_return:
+	if (is_mipi_cmd_panel(hisifd)) {
+		hisifd->vactive0_start_flag = 1;
+	} else {
+		single_frame_update(hisifd);
+	}
+	hisifb_deactivate_vsync(hisifd);
+
+	return ret;
+}
+
+int hisi_ov_online_play(struct hisi_fb_data_type *hisifd, void __user *argp)
+{
+	static int dss_free_buffer_refcount;
+	dss_overlay_t *pov_req = NULL;
+	dss_overlay_t *pov_req_prev = NULL;
+	dss_overlay_block_t *pov_h_block_infos = NULL;
+	dss_overlay_block_t *pov_h_block = NULL;
+	dss_layer_t *layer = NULL;
+	dss_rect_ltrb_t clip_rect;
+	dss_rect_t aligned_rect;
+	bool rdma_stretch_enable = false;
+	uint32_t cmdlist_pre_idxs = 0;
+	uint32_t cmdlist_idxs = 0;
+	int enable_cmdlist = 0;
+	bool has_base = false;
+#ifdef CONFIG_BUF_SYNC_USED
+	unsigned long flags = 0;
+#endif
+	int need_skip = 0;
+	int i = 0;
+	int m = 0;
+	int ret = 0;
+	uint32_t timediff = 0;
+	struct list_head lock_list;
+	struct timeval tv0;
+	struct timeval tv1;
+	struct timeval tv2;
+	struct timeval tv3;
+
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	if (NULL == argp) {
+		HISI_FB_ERR("NULL Pointer!\n");
+		return -EINVAL;
+	}
+
+	pov_req = &(hisifd->ov_req);
+	pov_req_prev = &(hisifd->ov_req_prev);
+	INIT_LIST_HEAD(&lock_list);
+
+	if (!hisifd->panel_power_on) {
+		HISI_FB_INFO("fb%d, panel is power off!\n", hisifd->index);
+		return 0;
+	}
+
+	if (g_debug_ovl_online_composer_return) {
+		return 0;
+	}
+
+	if (g_debug_ovl_online_composer_timediff & 0x2) {
+		hisifb_get_timestamp(&tv0);
+	}
+
+	enable_cmdlist = g_enable_ovl_cmdlist_online;
+	if ((hisifd->index == EXTERNAL_PANEL_IDX)
+	    && hisifd->panel_info.fake_hdmi) {
+		enable_cmdlist = 0;
+	}
+
+	hisifb_activate_vsync(hisifd);
+
+	if (g_debug_ovl_online_composer_timediff & 0x4) {
+		hisifb_get_timestamp(&tv2);
+	}
+
+	ret = hisi_get_ov_data_from_user(hisifd, pov_req, argp);
+	if (ret != 0) {
+		HISI_FB_ERR("fb%d, hisi_get_ov_data_from_user failed! ret=%d\n",
+			    hisifd->index, ret);
+		need_skip = 1;
+		goto err_return;
+	}
+#ifdef CONFIG_BUF_SYNC_USED
+	if (is_mipi_video_panel(hisifd)) {
+		ret = hisifb_buf_sync_handle(hisifd, pov_req);
+		if (ret < 0) {
+			HISI_FB_ERR
+			    ("fb%d, hisifb_buf_sync_handle failed! ret=%d\n",
+			     hisifd->index, ret);
+			need_skip = 1;
+			goto err_return;
+		}
+	}
+#endif
+
+	ret = hisi_vactive0_start_config(hisifd, pov_req);
+	if (ret != 0) {
+		HISI_FB_ERR("fb%d, hisi_vactive0_start_config failed! ret=%d\n",
+			    hisifd->index, ret);
+		need_skip = 1;
+		goto err_return;
+	}
+	down(&hisifd->blank_sem0);
+
+	if (g_debug_ovl_online_composer_timediff & 0x4) {
+		hisifb_get_timestamp(&tv3);
+		timediff = hisifb_timestamp_diff(&tv2, &tv3);
+		if (timediff >= g_debug_ovl_online_composer_time_threshold)
+			HISI_FB_ERR("ONLINE_VACTIVE_TIMEDIFF is %u us!\n",
+				    timediff);
+	}
+
+	if (g_debug_ovl_online_composer == 1) {
+		dumpDssOverlay(hisifd, pov_req, false);
+	}
+
+	ret = hisifb_layerbuf_lock(hisifd, pov_req, &lock_list);
+	if (ret != 0) {
+		HISI_FB_ERR("fb%d, hisifb_layerbuf_lock failed! ret=%d\n",
+			    hisifd->index, ret);
+		goto err_return;
+	}
+
+	hisi_dss_handle_cur_ovl_req(hisifd, pov_req);
+
+	ret = hisi_dss_module_init(hisifd);
+	if (ret != 0) {
+		HISI_FB_ERR("fb%d, hisi_dss_module_init failed! ret = %d\n",
+			    hisifd->index, ret);
+		goto err_return;
+	}
+	hisi_mmbuf_info_get_online(hisifd);
+
+	if (enable_cmdlist) {
+		hisifd->set_reg = hisi_cmdlist_set_reg;
+		hisi_cmdlist_data_get_online(hisifd);
+
+		ret =
+		    hisi_cmdlist_get_cmdlist_idxs(pov_req_prev,
+						  &cmdlist_pre_idxs, NULL);
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("fb%d, hisi_cmdlist_get_cmdlist_idxs pov_req_prev failed! "
+			     "ret = %d\n",
+			     hisifd->index, ret);
+			goto err_return;
+		}
+
+		ret =
+		    hisi_cmdlist_get_cmdlist_idxs(pov_req, &cmdlist_pre_idxs,
+						  &cmdlist_idxs);
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("fb%d, hisi_cmdlist_get_cmdlist_idxs pov_req failed! ret = %d\n",
+			     hisifd->index, ret);
+			goto err_return;
+		}
+
+		hisi_cmdlist_add_nop_node(hisifd, cmdlist_pre_idxs, 0, 0);
+		hisi_cmdlist_add_nop_node(hisifd, cmdlist_idxs, 0, 0);
+	} else {
+		hisifd->set_reg = hisifb_set_reg;
+		hisi_dss_mctl_mutex_lock(hisifd, pov_req->ovl_idx);
+		cmdlist_pre_idxs = ~0;
+	}
+
+	hisi_dss_prev_module_set_regs(hisifd, pov_req_prev, cmdlist_pre_idxs,
+				      enable_cmdlist, NULL);
+
+	pov_h_block_infos =
+	    (dss_overlay_block_t *) (pov_req->ov_block_infos_ptr);
+	for (m = 0; m < pov_req->ov_block_nums; m++) {
+		pov_h_block = &(pov_h_block_infos[m]);
+
+		ret = hisi_dss_module_init(hisifd);
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("fb%d, hisi_dss_module_init failed! ret = %d\n",
+			     hisifd->index, ret);
+			goto err_return;
+		}
+		hisi_dss_aif_handler(hisifd, pov_req, pov_h_block);
+
+		ret =
+		    hisi_dss_ovl_base_config(hisifd, pov_req, pov_h_block, NULL,
+					     pov_req->ovl_idx, m);
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("fb%d, hisi_dss_ovl_init failed! ret = %d\n",
+			     hisifd->index, ret);
+			goto err_return;
+		}
+
+		for (i = 0; i < pov_h_block->layer_nums; i++) {
+			layer = &(pov_h_block->layer_infos[i]);
+			memset(&clip_rect, 0, sizeof(dss_rect_ltrb_t));
+			memset(&aligned_rect, 0, sizeof(dss_rect_ltrb_t));
+			rdma_stretch_enable = false;
+
+			ret =
+			    hisi_ov_compose_handler(hisifd, pov_req,
+						    pov_h_block, layer, NULL,
+						    NULL, &clip_rect,
+						    &aligned_rect,
+						    &rdma_stretch_enable,
+						    &has_base, true,
+						    enable_cmdlist);
+			if (ret != 0) {
+				HISI_FB_ERR
+				    ("fb%d, hisi_ov_compose_handler failed! ret = %d\n",
+				     hisifd->index, ret);
+				goto err_return;
+			}
+		}
+
+		ret =
+		    hisi_dss_mctl_ov_config(hisifd, pov_req, pov_req->ovl_idx,
+					    has_base, (m == 0));
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("fb%d, hisi_dss_mctl_config failed! ret = %d\n",
+			     hisifd->index, ret);
+			goto err_return;
+		}
+
+		if (m == 0) {
+			if (hisifd->panel_info.dirty_region_updt_support) {
+				ret =
+				    hisi_dss_dirty_region_dbuf_config(hisifd, pov_req);
+				if (ret != 0) {
+					HISI_FB_ERR
+					    ("fb%d, hisi_dss_dirty_region_dbuf_config failed! ret = %d\n",
+					     hisifd->index, ret);
+					goto err_return;
+				}
+			}
+		}
+
+		ret = hisi_dss_post_scf_config(hisifd, pov_req);
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("fb%d, hisi_dss_post_scf_config failed! ret = %d\n",
+			     hisifd->index, ret);
+			goto err_return;
+		}
+
+		ret =
+		    hisi_dss_ov_module_set_regs(hisifd, pov_req,
+						pov_req->ovl_idx,
+						enable_cmdlist, 0, 0, (m == 0));
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("fb%d, hisi_dss_module_config failed! ret = %d\n",
+			     hisifd->index, ret);
+			goto err_return;
+		}
+	}
+
+	if (enable_cmdlist) {
+		g_online_cmdlist_idxs |= cmdlist_idxs;
+		hisi_cmdlist_add_nop_node(hisifd, cmdlist_idxs, 0, 0);
+		hisi_cmdlist_config_stop(hisifd, cmdlist_pre_idxs);
+
+		cmdlist_idxs |= cmdlist_pre_idxs;
+		hisi_cmdlist_flush_cache(hisifd, hisifd->ion_client,
+					 cmdlist_idxs);
+	}
+
+	ret = hisi_crc_enable(hisifd, pov_req);
+	if (ret != 0) {
+		HISI_FB_ERR("fb%d, hisi_crc_enable failed!\n", hisifd->index);
+		goto err_return;
+	}
+	hisi_dss_unflow_handler(hisifd, pov_req, true);
+
+#ifdef CONFIG_BUF_SYNC_USED
+	if (is_mipi_cmd_panel(hisifd)) {
+		ret = hisifb_buf_sync_handle(hisifd, pov_req);
+		if (ret < 0) {
+			HISI_FB_ERR
+			    ("fb%d, hisifb_buf_sync_handle failed! ret=%d\n",
+			     hisifd->index, ret);
+			goto err_return;
+		}
+	}
+
+	pov_req->release_fence =
+	    hisifb_buf_sync_create_fence(hisifd,
+					 ++hisifd->buf_sync_ctrl.timeline_max);
+	if (pov_req->release_fence < 0) {
+		HISI_FB_INFO
+		    ("fb%d, hisi_create_fence failed! pov_req->release_fence = 0x%x\n",
+		     hisifd->index, pov_req->release_fence);
+	}
+
+	spin_lock_irqsave(&hisifd->buf_sync_ctrl.refresh_lock, flags);
+	hisifd->buf_sync_ctrl.refresh++;
+	spin_unlock_irqrestore(&hisifd->buf_sync_ctrl.refresh_lock, flags);
+#endif
+
+	if (enable_cmdlist) {
+		hisi_cmdlist_config_start(hisifd, pov_req->ovl_idx,
+					  cmdlist_idxs, 0);
+	} else {
+		hisi_dss_mctl_mutex_unlock(hisifd, pov_req->ovl_idx);
+	}
+
+	if (hisifd->panel_info.dirty_region_updt_support) {
+		hisi_dss_dirty_region_updt_config(hisifd, pov_req);
+	}
+
+	single_frame_update(hisifd);
+	hisifb_frame_updated(hisifd);
+	hisi_crc_config(hisifd, pov_req);
+
+	if (copy_to_user((struct dss_overlay_t __user *)argp,
+			 pov_req, sizeof(dss_overlay_t))) {
+		ret = -EFAULT;
+
+		if (pov_req->release_fence >= 0)
+			put_unused_fd(pov_req->release_fence);
+
+		goto err_return;
+	}
+
+	hisifb_deactivate_vsync(hisifd);
+	hisifb_layerbuf_flush(hisifd, &lock_list);
+
+	if ((hisifd->index == PRIMARY_PANEL_IDX)
+	    && (dss_free_buffer_refcount > 1)) {
+		if (!hisifd->fb_mem_free_flag) {
+			hisifb_free_fb_buffer(hisifd);
+			hisifd->fb_mem_free_flag = true;
+		}
+	}
+
+	if (g_debug_ovl_online_composer == 2) {
+		dumpDssOverlay(hisifd, pov_req, true);
+	}
+
+	if (g_debug_ovl_cmdlist && enable_cmdlist)
+		hisi_cmdlist_dump_all_node(hisifd, NULL, cmdlist_idxs);
+
+	hisifd->frame_count++;
+	dss_free_buffer_refcount++;
+	memcpy(&hisifd->ov_req_prev_prev, &hisifd->ov_req_prev,
+	       sizeof(dss_overlay_t));
+	memcpy(&(hisifd->ov_block_infos_prev_prev),
+	       &(hisifd->ov_block_infos_prev),
+	       hisifd->ov_req_prev.ov_block_nums * sizeof(dss_overlay_block_t));
+	hisifd->ov_req_prev_prev.ov_block_infos_ptr =
+	    (uint64_t) (&(hisifd->ov_block_infos_prev_prev));
+
+	memcpy(&hisifd->ov_req_prev, pov_req, sizeof(dss_overlay_t));
+	memcpy(&(hisifd->ov_block_infos_prev), &(hisifd->ov_block_infos),
+	       pov_req->ov_block_nums * sizeof(dss_overlay_block_t));
+	hisifd->ov_req_prev.ov_block_infos_ptr =
+	    (uint64_t) (&(hisifd->ov_block_infos_prev));
+
+	if (g_debug_ovl_online_composer_timediff & 0x2) {
+		hisifb_get_timestamp(&tv1);
+		timediff = hisifb_timestamp_diff(&tv0, &tv1);
+		if (timediff >= g_debug_ovl_online_composer_time_threshold)
+			HISI_FB_ERR("ONLINE_TIMEDIFF is %u us!\n", timediff);
+	}
+	up(&hisifd->blank_sem0);
+
+	return 0;
+
+ err_return:
+	if (is_mipi_cmd_panel(hisifd)) {
+		hisifd->vactive0_start_flag = 1;
+	}
+	hisifb_layerbuf_lock_exception(hisifd, &lock_list);
+	hisifb_deactivate_vsync(hisifd);
+	if (!need_skip) {
+		up(&hisifd->blank_sem0);
+	}
+	return ret;
+}
diff --git a/drivers/video/fbdev/hisi/dss/hisi_overlay_utils.c b/drivers/video/fbdev/hisi/dss/hisi_overlay_utils.c
new file mode 100755
index 000000000000..97d71df5a38d
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_overlay_utils.c
@@ -0,0 +1,8495 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+/*lint -e778 -e732*/
+
+#include "hisi_overlay_utils.h"
+#include "hisi_dpe_utils.h"
+
+#define SMMU_RW_ERR_ADDR_SIZE	(128)
+
+/* mmbuf gen pool */
+static struct gen_pool *g_mmbuf_gen_pool = NULL;
+static dss_mmbuf_t g_pre_online_mmbuf[DSS_CHN_MAX_DEFINE] = { {0, 0} };
+
+static uint32_t vactive_timeout_count = 0;
+
+static inline bool hisi_dss_is_sharpness_support(int32_t width, int32_t height)
+{
+	return ((16 <= width) && (width <= 1600) && (4 <= height)
+		&& (height <= 2560));
+}
+
+/*******************************************************************************
+ **
+ */
+static int32_t hisi_transform2degree(uint32_t transform)
+{
+	int ret = 0;
+
+	switch (transform) {
+	case HISI_FB_TRANSFORM_NOP:
+	case HISI_FB_TRANSFORM_FLIP_H:
+	case HISI_FB_TRANSFORM_FLIP_V:
+		ret = 0;
+		break;
+	case HISI_FB_TRANSFORM_ROT_90:
+		ret = 90;
+		break;
+	case HISI_FB_TRANSFORM_ROT_180:
+		ret = 180;
+		break;
+	case HISI_FB_TRANSFORM_ROT_270:
+		ret = 270;
+		break;
+	default:
+		ret = -1;
+		HISI_FB_ERR("not support transform(%d)!", transform);
+		break;
+	}
+
+	return ret;
+}
+
+#define DUMP_BUF_SIZE	SZ_256K
+
+struct dss_dump_data_type {
+	char *dss_buf;
+	uint32_t dss_buf_len;
+	char dss_filename[256];
+
+	char *scene_buf;
+	uint32_t scene_buf_len;
+	char scene_filename[256];
+
+	char image_bin_filename[MAX_DSS_SRC_NUM][256];
+};
+
+void dumpDssOverlay(struct hisi_fb_data_type *hisifd, dss_overlay_t *pov_req,
+		    bool isNeedSaveFile)
+{
+	uint32_t i = 0;
+	uint32_t k = 0;
+	dss_layer_t const *layer = NULL;
+	dss_wb_layer_t const *wb_layer = NULL;
+	struct timeval tv;
+	dss_overlay_block_t *pov_h_block_infos = NULL;
+	dss_overlay_block_t *pov_block_info = NULL;
+
+	struct dss_dump_data_type *dumpDss = NULL;
+	char *image_src_addr = NULL;
+	struct ion_handle *ionhnd = NULL;
+
+	static const char *const layer_format[] = {
+		"RGB565", "RGBX4444", "RGBA4444", "RGBX5551", "RGBA5551",
+		    "RGBX8888", "RGBA8888",
+		"BGR565", "BGRX4444", "BGRA4444", "BGRX5551", "BGRA5551",
+		    "BGRX8888", "BGRA8888",
+		"YCbYCr", "", "", "NV12", "NV21", "", "", "", "YV12", "", ""
+	};
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_req == NULL);
+	BUG_ON((pov_req->ovl_idx < DSS_OVL0)
+	       || (pov_req->ovl_idx >= DSS_OVL_IDX_MAX));
+
+	dumpDss = kmalloc(sizeof(struct dss_dump_data_type), GFP_KERNEL);
+	if (IS_ERR_OR_NULL(dumpDss)) {
+		HISI_FB_ERR("alloc dumpDss failed!\n");
+		goto alloc_dump_dss_data_err;
+	}
+	memset(dumpDss, 0, sizeof(struct dss_dump_data_type));
+
+	if (isNeedSaveFile) {
+		hisifb_get_timestamp(&tv);
+		snprintf(dumpDss->scene_filename,
+			 sizeof(dumpDss->scene_filename),
+			 "/data/dssdump/Scene_%ld.sce", tv.tv_sec);
+		snprintf(dumpDss->dss_filename, sizeof(dumpDss->dss_filename),
+			 "/data/dssdump/Dss_%ld.txt", tv.tv_sec);
+
+
+		dumpDss->scene_buf_len = 0;
+		dumpDss->scene_buf = kmalloc(DUMP_BUF_SIZE, GFP_KERNEL);
+		if (IS_ERR_OR_NULL(dumpDss->scene_buf)) {
+			HISI_FB_ERR("alloc scene_buf failed!\n");
+			goto alloc_scene_buf_err;
+		}
+		memset(dumpDss->scene_buf, 0, DUMP_BUF_SIZE);
+	}
+
+	dumpDss->dss_buf_len = 0;
+	dumpDss->dss_buf = kmalloc(DUMP_BUF_SIZE, GFP_KERNEL);
+	if (IS_ERR_OR_NULL(dumpDss->dss_buf)) {
+		HISI_FB_ERR("alloc dss_buf failed!\n");
+		goto alloc_dss_buf_err;
+	}
+	memset(dumpDss->dss_buf, 0, DUMP_BUF_SIZE);
+
+	dumpDss->dss_buf_len +=
+	    snprintf(dumpDss->dss_buf + dumpDss->dss_buf_len, 4 * SZ_1K,
+		     "\n\n----------------------------<dump begin>----------------------------\n"
+		     "frame_no=%d\n" "ovl_idx=%d\n"
+		     "res_updt_rect(%d, %d, %d, %d)\n"
+		     "dirty_rect(%d,%d, %d,%d)\n" "release_fence=%d\n"
+		     "crc_enable_status=%d\n" "crc_info(%d,%d)\n"
+		     "ov_block_nums=%d\n" "ov_block_infos_ptr=0x%llx\n"
+		     "wb_enable=%d\n" "wb_layer_nums=%d\n"
+		     "wb_ov_rect(%d,%d, %d,%d)\n", pov_req->frame_no,
+		     pov_req->ovl_idx, pov_req->res_updt_rect.x,
+		     pov_req->res_updt_rect.y, pov_req->res_updt_rect.w,
+		     pov_req->res_updt_rect.h, pov_req->dirty_rect.x,
+		     pov_req->dirty_rect.y, pov_req->dirty_rect.w,
+		     pov_req->dirty_rect.h, pov_req->release_fence,
+		     pov_req->crc_enable_status,
+		     pov_req->crc_info.crc_ov_result,
+		     pov_req->crc_info.err_status, pov_req->ov_block_nums,
+		     pov_req->ov_block_infos_ptr, pov_req->wb_enable,
+		     pov_req->wb_layer_nums, pov_req->wb_ov_rect.x,
+		     pov_req->wb_ov_rect.y, pov_req->wb_ov_rect.w,
+		     pov_req->wb_ov_rect.h);
+
+	for (i = 0; i < pov_req->ov_block_nums; i++) {
+		pov_h_block_infos =
+		    (dss_overlay_block_t *) (pov_req->ov_block_infos_ptr);
+		pov_block_info = &(pov_h_block_infos[i]);
+
+		dumpDss->dss_buf_len +=
+		    snprintf(dumpDss->dss_buf + dumpDss->dss_buf_len, 4 * SZ_1K,
+			     "\nov_block_rect(%d,%d, %d,%d)\n"
+			     "layer_nums=%d\n", pov_block_info->ov_block_rect.x,
+			     pov_block_info->ov_block_rect.y,
+			     pov_block_info->ov_block_rect.w,
+			     pov_block_info->ov_block_rect.h,
+			     pov_block_info->layer_nums);
+
+		for (k = 0; k < pov_block_info->layer_nums; k++) {
+			layer = &(pov_block_info->layer_infos[k]);
+
+			dumpDss->dss_buf_len +=
+			    snprintf(dumpDss->dss_buf + dumpDss->dss_buf_len,
+				     4 * SZ_1K,
+				     "\nLayerInfo[%d]:\n" "format=%d\n"
+				     "width=%d\n" "height=%d\n" "bpp=%d\n"
+				     "buf_size=%d\n" "stride=%d\n"
+				     "stride_plane1=0x%x\n"
+				     "stride_plane2=0x%x\n" "phy_addr=0x%llx\n"
+				     "vir_addr=0x%llx\n" "offset_plane1=%d\n"
+				     "offset_plane2=%d\n"
+				     "afbc_header_addr=0x%llx\n"
+				     "afbc_payload_addr=0x%llx\n"
+				     "afbc_header_stride=%d\n"
+				     "afbc_payload_stride=%d\n"
+				     "afbc_scramble_mode=%d\n"
+				     "mmbuf_base=0x%x\n" "mmbuf_size=%d\n"
+				     "mmu_enable=%d\n" "csc_mode=%d\n"
+				     "secure_mode=%d\n" "shared_fd=%d\n"
+				     "src_rect(%d,%d, %d,%d)\n"
+				     "src_rect_mask(%d,%d, %d,%d)\n"
+				     "dst_rect(%d,%d, %d,%d)\n" "transform=%d\n"
+				     "blending=%d\n" "glb_alpha=0x%x\n"
+				     "color=0x%x\n" "layer_idx=%d\n"
+				     "chn_idx=%d\n" "need_cap=0x%x\n"
+				     "acquire_fence=%d\n", k, layer->img.format,
+				     layer->img.width, layer->img.height,
+				     layer->img.bpp, layer->img.buf_size,
+				     layer->img.stride,
+				     layer->img.stride_plane1,
+				     layer->img.stride_plane2,
+				     layer->img.phy_addr, layer->img.vir_addr,
+				     layer->img.offset_plane1,
+				     layer->img.offset_plane2,
+				     layer->img.afbc_header_addr,
+				     layer->img.afbc_payload_addr,
+				     layer->img.afbc_header_stride,
+				     layer->img.afbc_payload_stride,
+				     layer->img.afbc_scramble_mode,
+				     layer->img.mmbuf_base,
+				     layer->img.mmbuf_size,
+				     layer->img.mmu_enable, layer->img.csc_mode,
+				     layer->img.secure_mode,
+				     layer->img.shared_fd, layer->src_rect.x,
+				     layer->src_rect.y, layer->src_rect.w,
+				     layer->src_rect.h, layer->src_rect_mask.x,
+				     layer->src_rect_mask.y,
+				     layer->src_rect_mask.w,
+				     layer->src_rect_mask.h, layer->dst_rect.x,
+				     layer->dst_rect.y, layer->dst_rect.w,
+				     layer->dst_rect.h, layer->transform,
+				     layer->blending, layer->glb_alpha,
+				     layer->color, layer->layer_idx,
+				     layer->chn_idx, layer->need_cap,
+				     layer->acquire_fence);
+
+
+			if (isNeedSaveFile) {
+				if (layer->dst_rect.y <
+				    pov_block_info->ov_block_rect.y)
+					continue;
+
+				dumpDss->scene_buf_len +=
+				    snprintf(dumpDss->scene_buf +
+					     dumpDss->scene_buf_len, SZ_1K,
+					     "[BaseColor]=0x%x\n"
+					     "[ScreenSize]=(%u,%u)\n\n"
+					     "[BlendMode]=%d\n" "[Caption]=\n"
+					     "[Channel]=%u\n"
+					     "[CropLoc]=(%u,%u)\n"
+					     "[CropSize]=(%u,%u)\n"
+					     "[FlipHV]=(%u,%u)\n"
+					     "[Format]=%s\n"
+					     "[GlobalAlpha]=%u\n",
+					     hisifd->dss_module.ov[pov_req->
+								   ovl_idx].
+					     ovl_bg_color,
+					     get_panel_xres(hisifd),
+					     get_panel_yres(hisifd),
+					     layer->blending, layer->chn_idx, 0,
+					     0, layer->src_rect.w,
+					     layer->src_rect.h,
+					     (layer->
+					      transform &
+					      HISI_FB_TRANSFORM_FLIP_H),
+					     (layer->
+					      transform &
+					      HISI_FB_TRANSFORM_FLIP_V),
+					     layer_format[layer->img.format],
+					     layer->glb_alpha);
+
+				if (layer->need_cap & (CAP_DIM | CAP_PURE_COLOR |
+						CAP_BASE)) {
+					if (layer->need_cap & CAP_BASE) {
+						dumpDss->scene_buf_len +=
+						    snprintf(dumpDss->scene_buf +
+							     dumpDss->scene_buf_len,
+							     SZ_1K,
+							     "[BaseColor]=0x%x\n",
+							     layer->color);
+					} else if (layer->need_cap & CAP_PURE_COLOR) {
+						dumpDss->scene_buf_len +=
+						    snprintf(dumpDss->scene_buf +
+							     dumpDss->scene_buf_len,
+							     SZ_1K,
+							     "[Color]=0x%x\n",
+							     layer->color);
+					}
+				} else {
+					dumpDss->scene_buf_len +=
+					    snprintf(dumpDss->scene_buf +
+						     dumpDss->scene_buf_len,
+						     SZ_1K,
+						     "[ImageSource]=pic%d_%ld.bin\n",
+						     k, tv.tv_sec);
+				}
+
+				dumpDss->scene_buf_len +=
+				    snprintf(dumpDss->scene_buf +
+					     dumpDss->scene_buf_len, SZ_1K,
+					     "[Location]=(%u,%u)\n"
+					     "[Rotate]=%u\n" "[Scale]=(%u,%u)\n"
+					     "[Size]=(%u,%u)\n\n",
+					     layer->dst_rect.x,
+					     layer->dst_rect.y,
+					     hisi_transform2degree(layer->transform),
+					     layer->dst_rect.w,
+					     layer->dst_rect.h,
+					     layer->dst_rect.w,
+					     layer->dst_rect.h);
+
+
+				if (layer->need_cap & (CAP_DIM | CAP_PURE_COLOR |
+						CAP_BASE))
+					continue;
+
+				if (layer->img.shared_fd < 0)
+					continue;
+
+				ionhnd =
+				    ion_import_dma_buf(hisifd->ion_client,
+						       layer->img.shared_fd);
+				if (IS_ERR(ionhnd)) {
+					HISI_FB_ERR
+					    ("ion import dma buf err, ionclient %p, share_fd %d, layer index %d",
+					     hisifd->ion_client,
+					     layer->img.shared_fd, i);
+					continue;
+				}
+
+				snprintf(dumpDss->image_bin_filename[k],
+					 sizeof(dumpDss->image_bin_filename[k]),
+					 "/data/dssdump/pic%d_%ld.bin", k,
+					 tv.tv_sec);
+
+				image_src_addr =
+				    ion_map_kernel(hisifd->ion_client, ionhnd);
+				if (image_src_addr) {
+					hisifb_save_file(dumpDss->image_bin_filename[k],
+							 image_src_addr,
+							 layer->img.buf_size);
+					ion_unmap_kernel(hisifd->ion_client, ionhnd);
+				}
+
+				ion_free(hisifd->ion_client, ionhnd);
+				ionhnd = NULL;
+			}
+		}
+	}
+
+	for (k = 0; k < pov_req->wb_layer_nums; k++) {
+		wb_layer = &(pov_req->wb_layer_infos[k]);
+
+		dumpDss->dss_buf_len +=
+		    snprintf(dumpDss->dss_buf + dumpDss->dss_buf_len, 4 * SZ_1K,
+			     "\nWbLayerInfo[%d]:\n" "format=%d\n" "width=%d\n"
+			     "height=%d\n" "bpp=%d\n" "buf_size=%d\n"
+			     "stride=%d\n" "stride_plane1=%d\n"
+			     "stride_plane2=%d\n" "phy_addr=0x%llx\n"
+			     "vir_addr=0x%llx\n" "offset_plane1=%d\n"
+			     "offset_plane2=%d\n" "afbc_header_addr=0x%llx\n"
+			     "afbc_payload_addr=0x%llx\n"
+			     "afbc_header_stride=%d\n"
+			     "afbc_payload_stride=%d\n"
+			     "afbc_scramble_mode=%d\n" "mmbuf_base=0x%x\n"
+			     "mmbuf_size=%d\n" "mmu_enable=%d\n" "csc_mode=%d\n"
+			     "secure_mode=%d\n" "shared_fd=%d\n"
+			     "src_rect(%d,%d, %d,%d)\n"
+			     "dst_rect(%d,%d, %d,%d)\n" "transform=%d\n"
+			     "chn_idx=%d\n" "need_cap=0x%x\n"
+			     "acquire_fence=%d\n" "release_fence=%d\n", k,
+			     wb_layer->dst.format, wb_layer->dst.width,
+			     wb_layer->dst.height, wb_layer->dst.bpp,
+			     wb_layer->dst.buf_size, wb_layer->dst.stride,
+			     wb_layer->dst.stride_plane1,
+			     wb_layer->dst.stride_plane2,
+			     wb_layer->dst.phy_addr, wb_layer->dst.vir_addr,
+			     wb_layer->dst.offset_plane1,
+			     wb_layer->dst.offset_plane2,
+			     wb_layer->dst.afbc_header_addr,
+			     wb_layer->dst.afbc_payload_addr,
+			     wb_layer->dst.afbc_header_stride,
+			     wb_layer->dst.afbc_payload_stride,
+			     wb_layer->dst.afbc_scramble_mode,
+			     wb_layer->dst.mmbuf_base, wb_layer->dst.mmbuf_size,
+			     wb_layer->dst.mmu_enable, wb_layer->dst.csc_mode,
+			     wb_layer->dst.secure_mode, wb_layer->dst.shared_fd,
+			     wb_layer->src_rect.x, wb_layer->src_rect.y,
+			     wb_layer->src_rect.w, wb_layer->src_rect.h,
+			     wb_layer->dst_rect.x, wb_layer->dst_rect.y,
+			     wb_layer->dst_rect.w, wb_layer->dst_rect.h,
+			     wb_layer->transform, wb_layer->chn_idx,
+			     wb_layer->need_cap, wb_layer->acquire_fence,
+			     wb_layer->release_fence);
+	}
+
+	dumpDss->dss_buf_len +=
+	    snprintf(dumpDss->dss_buf + dumpDss->dss_buf_len, 4 * SZ_1K,
+		     "----------------------------<dump end>----------------------------\n\n");
+
+	for (k = 0; k < dumpDss->dss_buf_len; k += 255) {
+		printk("%.255s", dumpDss->dss_buf + k);
+	}
+
+	if (isNeedSaveFile) {
+		if (dumpDss->scene_buf)
+			hisifb_save_file(dumpDss->scene_filename,
+					 dumpDss->scene_buf,
+					 dumpDss->scene_buf_len);
+
+		if (dumpDss->dss_buf)
+			hisifb_save_file(dumpDss->dss_filename,
+					 dumpDss->dss_buf,
+					 dumpDss->dss_buf_len);
+	}
+
+	if (dumpDss->dss_buf) {
+		kfree(dumpDss->dss_buf);
+		dumpDss->dss_buf = NULL;
+		dumpDss->dss_buf_len = 0;
+	}
+
+ alloc_dss_buf_err:
+	if (dumpDss->scene_buf) {
+		kfree(dumpDss->scene_buf);
+		dumpDss->scene_buf = NULL;
+		dumpDss->scene_buf_len = 0;
+	}
+
+ alloc_scene_buf_err:
+	if (dumpDss) {
+		kfree(dumpDss);
+		dumpDss = NULL;
+	}
+
+ alloc_dump_dss_data_err:
+	return;
+}
+
+static int hisi_dss_lcd_refresh_direction_layer(struct hisi_fb_data_type
+						*hisifd,
+						dss_overlay_t *pov_req,
+						dss_layer_t *layer)
+{
+	struct hisi_panel_info *pinfo = NULL;
+	int ret = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_req == NULL);
+	BUG_ON(layer == NULL);
+
+	pinfo = &(hisifd->panel_info);
+
+	if ((pov_req->ovl_idx != DSS_OVL0) && (pov_req->ovl_idx != DSS_OVL1))
+		return 0;
+
+	if (pinfo->lcd_refresh_direction_ctrl == LCD_REFRESH_LEFT_TOP) {
+		;
+	} else if (pinfo->lcd_refresh_direction_ctrl == LCD_REFRESH_RIGHT_TOP) {
+		switch (layer->transform) {
+		case HISI_FB_TRANSFORM_NOP:
+			layer->transform = HISI_FB_TRANSFORM_FLIP_H;
+			break;
+		case HISI_FB_TRANSFORM_FLIP_H:
+			layer->transform = HISI_FB_TRANSFORM_NOP;
+			break;
+		case HISI_FB_TRANSFORM_FLIP_V:
+			layer->transform = HISI_FB_TRANSFORM_ROT_180;
+			break;
+		case HISI_FB_TRANSFORM_ROT_90:
+			layer->transform =
+			    (HISI_FB_TRANSFORM_ROT_90 |
+			     HISI_FB_TRANSFORM_FLIP_H);
+			break;
+		case HISI_FB_TRANSFORM_ROT_180:
+			layer->transform = HISI_FB_TRANSFORM_FLIP_V;
+			break;
+		case HISI_FB_TRANSFORM_ROT_270:
+			layer->transform =
+			    (HISI_FB_TRANSFORM_ROT_90 |
+			     HISI_FB_TRANSFORM_FLIP_V);
+			break;
+
+		case (HISI_FB_TRANSFORM_ROT_90 | HISI_FB_TRANSFORM_FLIP_H):
+			layer->transform = HISI_FB_TRANSFORM_ROT_90;
+			break;
+		case (HISI_FB_TRANSFORM_ROT_90 | HISI_FB_TRANSFORM_FLIP_V):
+			layer->transform = HISI_FB_TRANSFORM_ROT_270;
+			break;
+
+		default:
+			HISI_FB_ERR("not support this transform(%d).\n",
+				    layer->transform);
+			ret = -1;
+			break;
+		}
+
+		if (ret == 0) {
+			if ((pinfo->dirty_region_updt_support == 1) &&
+			    (pov_req->dirty_rect.w > 0) &&
+			    (pov_req->dirty_rect.h > 0)) {
+				layer->dst_rect.x =
+				    (pov_req->dirty_rect.w -
+				     (layer->dst_rect.x + layer->dst_rect.w));
+			} else {
+				layer->dst_rect.x =
+				    (get_panel_xres(hisifd) -
+				     (layer->dst_rect.x + layer->dst_rect.w));
+			}
+		}
+	} else if (pinfo->lcd_refresh_direction_ctrl == LCD_REFRESH_LEFT_BOTTOM) {
+		switch (layer->transform) {
+		case HISI_FB_TRANSFORM_NOP:
+			layer->transform = HISI_FB_TRANSFORM_FLIP_V;
+			break;
+		case HISI_FB_TRANSFORM_FLIP_H:
+			layer->transform = HISI_FB_TRANSFORM_ROT_180;
+			break;
+		case HISI_FB_TRANSFORM_FLIP_V:
+			layer->transform = HISI_FB_TRANSFORM_NOP;
+			break;
+		case HISI_FB_TRANSFORM_ROT_90:
+			layer->transform =
+			    (HISI_FB_TRANSFORM_ROT_90 |
+			     HISI_FB_TRANSFORM_FLIP_V);
+			break;
+		case HISI_FB_TRANSFORM_ROT_180:
+			layer->transform = HISI_FB_TRANSFORM_FLIP_H;
+			break;
+		case HISI_FB_TRANSFORM_ROT_270:
+			layer->transform =
+			    (HISI_FB_TRANSFORM_ROT_90 |
+			     HISI_FB_TRANSFORM_FLIP_H);
+			break;
+
+		case (HISI_FB_TRANSFORM_ROT_90 | HISI_FB_TRANSFORM_FLIP_H):
+			layer->transform = HISI_FB_TRANSFORM_ROT_270;
+			break;
+		case (HISI_FB_TRANSFORM_ROT_90 | HISI_FB_TRANSFORM_FLIP_V):
+			layer->transform = HISI_FB_TRANSFORM_ROT_90;
+			break;
+
+		default:
+			HISI_FB_ERR("not support this transform(%d).\n",
+				    layer->transform);
+			ret = -1;
+			break;
+		}
+
+		if (ret == 0) {
+			if ((pinfo->dirty_region_updt_support == 1) &&
+			    (pov_req->dirty_rect.w > 0) &&
+			    (pov_req->dirty_rect.h > 0)) {
+				layer->dst_rect.y =
+				    (pov_req->dirty_rect.h -
+				     (layer->dst_rect.y + layer->dst_rect.h));
+			} else {
+				layer->dst_rect.y =
+				    (get_panel_yres(hisifd) -
+				     (layer->dst_rect.y + layer->dst_rect.h));
+			}
+		}
+	} else if (pinfo->lcd_refresh_direction_ctrl ==
+		   LCD_REFRESH_RIGHT_BOTTOM) {
+		switch (layer->transform) {
+		case HISI_FB_TRANSFORM_NOP:
+			layer->transform = HISI_FB_TRANSFORM_ROT_180;
+			break;
+		case HISI_FB_TRANSFORM_FLIP_H:
+			layer->transform = HISI_FB_TRANSFORM_FLIP_V;
+			break;
+		case HISI_FB_TRANSFORM_FLIP_V:
+			layer->transform = HISI_FB_TRANSFORM_FLIP_H;
+			break;
+		case HISI_FB_TRANSFORM_ROT_90:
+			layer->transform = HISI_FB_TRANSFORM_ROT_270;
+			break;
+		case HISI_FB_TRANSFORM_ROT_180:
+			layer->transform = HISI_FB_TRANSFORM_NOP;
+			break;
+		case HISI_FB_TRANSFORM_ROT_270:
+			layer->transform = HISI_FB_TRANSFORM_ROT_90;
+			break;
+
+		case (HISI_FB_TRANSFORM_ROT_90 | HISI_FB_TRANSFORM_FLIP_H):
+			layer->transform =
+			    (HISI_FB_TRANSFORM_ROT_90 |
+			     HISI_FB_TRANSFORM_FLIP_V);
+			break;
+		case (HISI_FB_TRANSFORM_ROT_90 | HISI_FB_TRANSFORM_FLIP_V):
+			layer->transform =
+			    (HISI_FB_TRANSFORM_ROT_90 |
+			     HISI_FB_TRANSFORM_FLIP_H);
+			break;
+
+		default:
+			HISI_FB_ERR("not support this transform(%d).\n",
+				    layer->transform);
+			ret = -1;
+			break;
+		}
+
+		if (ret == 0) {
+			if ((pinfo->dirty_region_updt_support == 1) &&
+			    (pov_req->dirty_rect.w > 0) &&
+			    (pov_req->dirty_rect.h > 0)) {
+				layer->dst_rect.x =
+				    (pov_req->dirty_rect.w -
+				     (layer->dst_rect.x + layer->dst_rect.w));
+				layer->dst_rect.y =
+				    (pov_req->dirty_rect.h -
+				     (layer->dst_rect.y + layer->dst_rect.h));
+			} else {
+				layer->dst_rect.x =
+				    (get_panel_xres(hisifd) -
+				     (layer->dst_rect.x + layer->dst_rect.w));
+				layer->dst_rect.y =
+				    (get_panel_yres(hisifd) -
+				     (layer->dst_rect.y + layer->dst_rect.h));
+			}
+		}
+	} else {
+		HISI_FB_ERR
+		    ("fb%d, not support this lcd_refresh_direction_ctrl(%d)!\n",
+		     hisifd->index, pinfo->lcd_refresh_direction_ctrl);
+		ret = -1;
+	}
+
+	return ret;
+}
+
+static int hisi_dss_lcd_refresh_direction_dirty_region(struct hisi_fb_data_type
+						       *hisifd,
+						       dss_overlay_t *pov_req)
+{
+	struct hisi_panel_info *pinfo = NULL;
+	int ret = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_req == NULL);
+
+	pinfo = &(hisifd->panel_info);
+	if ((pov_req->ovl_idx != DSS_OVL0) && (pov_req->ovl_idx != DSS_OVL1))
+		return 0;
+
+	if (pinfo->lcd_refresh_direction_ctrl == LCD_REFRESH_LEFT_TOP) {
+		;
+	} else if (pinfo->lcd_refresh_direction_ctrl == LCD_REFRESH_RIGHT_TOP) {
+		if (pinfo->dirty_region_updt_support == 1) {
+			pov_req->dirty_rect.x =
+			    (get_panel_xres(hisifd) -
+			     (pov_req->dirty_rect.x + pov_req->dirty_rect.w));
+		}
+	} else if (pinfo->lcd_refresh_direction_ctrl == LCD_REFRESH_LEFT_BOTTOM) {
+		if (pinfo->dirty_region_updt_support == 1) {
+			pov_req->dirty_rect.y =
+			    (get_panel_yres(hisifd) -
+			     (pov_req->dirty_rect.y + pov_req->dirty_rect.h));
+		}
+	} else if (pinfo->lcd_refresh_direction_ctrl ==
+		   LCD_REFRESH_RIGHT_BOTTOM) {
+		if (pinfo->dirty_region_updt_support == 1) {
+			pov_req->dirty_rect.x =
+			    (get_panel_xres(hisifd) -
+			     (pov_req->dirty_rect.x + pov_req->dirty_rect.w));
+			pov_req->dirty_rect.y =
+			    (get_panel_yres(hisifd) -
+			     (pov_req->dirty_rect.y + pov_req->dirty_rect.h));
+		}
+	} else {
+		HISI_FB_ERR
+		    ("fb%d, not support this lcd_refresh_direction_ctrl(%d)!\n",
+		     hisifd->index, pinfo->lcd_refresh_direction_ctrl);
+		ret = -1;
+	}
+
+	return ret;
+}
+
+int hisi_dss_handle_cur_ovl_req(struct hisi_fb_data_type *hisifd,
+				dss_overlay_t *pov_req)
+{
+	struct hisi_panel_info *pinfo = NULL;
+	dss_overlay_block_t *pov_h_block_infos = NULL;
+	dss_overlay_block_t *pov_h_block = NULL;
+	dss_layer_t *layer = NULL;
+	int i = 0;
+	int m = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_req == NULL);
+	pinfo = &(hisifd->panel_info);
+
+	hisifd->resolution_rect = pov_req->res_updt_rect;
+
+	pov_h_block_infos =
+	    (dss_overlay_block_t *) (pov_req->ov_block_infos_ptr);
+	for (m = 0; m < pov_req->ov_block_nums; m++) {
+		pov_h_block = &(pov_h_block_infos[m]);
+
+		for (i = 0; i < pov_h_block->layer_nums; i++) {
+			layer = &(pov_h_block->layer_infos[i]);
+
+			hisi_dss_lcd_refresh_direction_layer(hisifd, pov_req,
+							     layer);
+		}
+	}
+	hisi_dss_lcd_refresh_direction_dirty_region(hisifd, pov_req);
+
+	return 0;
+}
+
+/*******************************************************************************
+ **
+ */
+int hisi_get_hal_format(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = NULL;
+	int hal_format = 0;
+
+	BUG_ON(info == NULL);
+	var = &info->var;
+
+	switch (var->bits_per_pixel) {
+	case 16:
+		if (var->blue.offset == 0) {
+			if (var->red.offset == 8) {
+				hal_format = (var->transp.offset == 12) ?
+				    HISI_FB_PIXEL_FORMAT_BGRA_4444 :
+				    HISI_FB_PIXEL_FORMAT_BGRX_4444;
+			} else if (var->red.offset == 10) {
+				hal_format = (var->transp.offset == 12) ?
+				    HISI_FB_PIXEL_FORMAT_BGRA_5551 :
+				    HISI_FB_PIXEL_FORMAT_BGRX_5551;
+			} else if (var->red.offset == 11) {
+				hal_format = HISI_FB_PIXEL_FORMAT_RGB_565;
+			}
+		}
+		break;
+
+	case 32:
+		if (var->blue.offset == 0) {
+			/* BUGFIX: Modified for Standard Android Format */
+			/* hal_format = (var->transp.length == 8) ?
+				HISI_FB_PIXEL_FORMAT_BGRA_8888 : HISI_FB_PIXEL_FORMAT_BGRX_8888; */
+			hal_format = (var->transp.length == 8) ?
+				HISI_FB_PIXEL_FORMAT_RGBA_8888 :
+				HISI_FB_PIXEL_FORMAT_RGBX_8888;
+		} else {
+			hal_format = (var->transp.length == 8) ?
+			    HISI_FB_PIXEL_FORMAT_RGBA_8888 :
+			    HISI_FB_PIXEL_FORMAT_RGBX_8888;
+		}
+		break;
+
+	default:
+		goto err_return;
+	}
+
+	return hal_format;
+
+ err_return:
+	HISI_FB_ERR("not support this bits_per_pixel(%d)!\n",
+		    var->bits_per_pixel);
+	return -1;
+}
+
+static bool hal_format_has_alpha(uint32_t format)
+{
+	switch (format) {
+	case HISI_FB_PIXEL_FORMAT_RGBA_4444:
+	case HISI_FB_PIXEL_FORMAT_RGBA_5551:
+	case HISI_FB_PIXEL_FORMAT_RGBA_8888:
+
+	case HISI_FB_PIXEL_FORMAT_BGRA_4444:
+	case HISI_FB_PIXEL_FORMAT_BGRA_5551:
+	case HISI_FB_PIXEL_FORMAT_BGRA_8888:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+bool isYUVPackage(uint32_t format)
+{
+	switch (format) {
+	case HISI_FB_PIXEL_FORMAT_YUV_422_I:
+	case HISI_FB_PIXEL_FORMAT_YUYV_422_Pkg:
+	case HISI_FB_PIXEL_FORMAT_YVYU_422_Pkg:
+	case HISI_FB_PIXEL_FORMAT_UYVY_422_Pkg:
+	case HISI_FB_PIXEL_FORMAT_VYUY_422_Pkg:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+bool isYUVSemiPlanar(uint32_t format)
+{
+	switch (format) {
+	case HISI_FB_PIXEL_FORMAT_YCbCr_422_SP:
+	case HISI_FB_PIXEL_FORMAT_YCrCb_422_SP:
+	case HISI_FB_PIXEL_FORMAT_YCbCr_420_SP:
+	case HISI_FB_PIXEL_FORMAT_YCrCb_420_SP:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+bool isYUVPlanar(uint32_t format)
+{
+	switch (format) {
+	case HISI_FB_PIXEL_FORMAT_YCbCr_422_P:
+	case HISI_FB_PIXEL_FORMAT_YCrCb_422_P:
+	case HISI_FB_PIXEL_FORMAT_YCbCr_420_P:
+	case HISI_FB_PIXEL_FORMAT_YCrCb_420_P:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+bool isYUV(uint32_t format)
+{
+	return isYUVPackage(format) ||
+	    isYUVSemiPlanar(format) || isYUVPlanar(format);
+}
+
+bool is_YUV_SP_420(uint32_t format)
+{
+	switch (format) {
+	case HISI_FB_PIXEL_FORMAT_YCbCr_420_SP:
+	case HISI_FB_PIXEL_FORMAT_YCrCb_420_SP:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+bool is_YUV_SP_422(uint32_t format)
+{
+	switch (format) {
+	case HISI_FB_PIXEL_FORMAT_YCbCr_422_SP:
+	case HISI_FB_PIXEL_FORMAT_YCrCb_422_SP:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+bool is_YUV_P_420(uint32_t format)
+{
+	switch (format) {
+	case HISI_FB_PIXEL_FORMAT_YCbCr_420_P:
+	case HISI_FB_PIXEL_FORMAT_YCrCb_420_P:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+bool is_YUV_P_422(uint32_t format)
+{
+	switch (format) {
+	case HISI_FB_PIXEL_FORMAT_YCbCr_422_P:
+	case HISI_FB_PIXEL_FORMAT_YCrCb_422_P:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+bool is_RGBX(uint32_t format)
+{
+	switch (format) {
+	case HISI_FB_PIXEL_FORMAT_RGBX_4444:
+	case HISI_FB_PIXEL_FORMAT_BGRX_4444:
+	case HISI_FB_PIXEL_FORMAT_RGBX_5551:
+	case HISI_FB_PIXEL_FORMAT_BGRX_5551:
+	case HISI_FB_PIXEL_FORMAT_RGBX_8888:
+	case HISI_FB_PIXEL_FORMAT_BGRX_8888:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+bool isNeedDither(int fmt)
+{
+	return (fmt == DFC_PIXEL_FORMAT_RGB_565) ||
+	    (fmt == DFC_PIXEL_FORMAT_BGR_565);
+}
+
+static bool isNeedRectClip(dss_rect_ltrb_t clip_rect)
+{
+	return ((clip_rect.left > 0) || (clip_rect.top > 0) ||
+		(clip_rect.right > 0) || (clip_rect.bottom > 0));
+}
+
+static bool isSrcRectMasked(dss_layer_t *layer, int aligned_pixel)
+{
+	BUG_ON(layer == NULL);
+
+	return ((layer->src_rect_mask.w != 0) &&
+		(layer->src_rect_mask.h != 0) &&
+		(ALIGN_DOWN
+		 (layer->src_rect_mask.x + layer->src_rect_mask.w,
+		  aligned_pixel) > 1));
+}
+
+static uint32_t isNeedRdmaStretchBlt(struct hisi_fb_data_type *hisifd,
+				     dss_layer_t *layer)
+{
+	uint32_t v_stretch_ratio_threshold = 0;
+	uint32_t v_stretch_ratio = 0;
+
+	BUG_ON(layer == NULL);
+
+	if (layer->need_cap & CAP_AFBCD) {
+#if 0
+		v_stretch_ratio = layer->src_rect.h / layer->dst_rect.h;
+		if (v_stretch_ratio < 2)
+			v_stretch_ratio = 0;
+#else
+		v_stretch_ratio = 0;
+#endif
+	} else {
+		if (is_YUV_SP_420(layer->img.format)
+		    || is_YUV_P_420(layer->img.format)) {
+			v_stretch_ratio_threshold =
+			    ((layer->src_rect.h + layer->dst_rect.h -
+			      1) / layer->dst_rect.h);
+			v_stretch_ratio =
+			    ((layer->src_rect.h / layer->dst_rect.h) / 2) * 2;
+		} else {
+			v_stretch_ratio_threshold =
+			    ((layer->src_rect.h + layer->dst_rect.h -
+			      1) / layer->dst_rect.h);
+			v_stretch_ratio =
+			    (layer->src_rect.h / layer->dst_rect.h);
+		}
+
+		if (v_stretch_ratio_threshold <= g_rdma_stretch_threshold)
+			v_stretch_ratio = 0;
+	}
+
+	return v_stretch_ratio;
+}
+
+static int hisi_adjust_clip_rect(dss_layer_t *layer,
+				 dss_rect_ltrb_t *clip_rect)
+{
+	int ret = 0;
+	uint32_t temp = 0;
+
+	BUG_ON(layer == NULL);
+	BUG_ON(clip_rect == NULL);
+
+	if ((clip_rect->left < 0 || clip_rect->left > DFC_MAX_CLIP_NUM) ||
+	    (clip_rect->right < 0 || clip_rect->right > DFC_MAX_CLIP_NUM) ||
+	    (clip_rect->top < 0 || clip_rect->top > DFC_MAX_CLIP_NUM) ||
+	    (clip_rect->bottom < 0 || clip_rect->bottom > DFC_MAX_CLIP_NUM)) {
+		return -EINVAL;
+	}
+
+	switch (layer->transform) {
+	case HISI_FB_TRANSFORM_NOP:
+
+		break;
+	case HISI_FB_TRANSFORM_FLIP_H:
+		{
+			temp = clip_rect->left;
+			clip_rect->left = clip_rect->right;
+			clip_rect->right = temp;
+		}
+		break;
+	case HISI_FB_TRANSFORM_FLIP_V:
+		{
+			temp = clip_rect->top;
+			clip_rect->top = clip_rect->bottom;
+			clip_rect->bottom = temp;
+		}
+		break;
+	case HISI_FB_TRANSFORM_ROT_180:
+		{
+			temp = clip_rect->left;
+			clip_rect->left = clip_rect->right;
+			clip_rect->right = temp;
+
+			temp = clip_rect->top;
+			clip_rect->top = clip_rect->bottom;
+			clip_rect->bottom = temp;
+		}
+		break;
+	default:
+		HISI_FB_ERR("not supported this transform(%d)!",
+			    layer->transform);
+		break;
+	}
+
+	return ret;
+}
+
+static int hisi_pixel_format_hal2dma(int format)
+{
+	int ret = 0;
+
+	switch (format) {
+	case HISI_FB_PIXEL_FORMAT_RGB_565:
+	case HISI_FB_PIXEL_FORMAT_BGR_565:
+		ret = DMA_PIXEL_FORMAT_RGB_565;
+		break;
+	case HISI_FB_PIXEL_FORMAT_RGBX_4444:
+	case HISI_FB_PIXEL_FORMAT_BGRX_4444:
+		ret = DMA_PIXEL_FORMAT_XRGB_4444;
+		break;
+	case HISI_FB_PIXEL_FORMAT_RGBA_4444:
+	case HISI_FB_PIXEL_FORMAT_BGRA_4444:
+		ret = DMA_PIXEL_FORMAT_ARGB_4444;
+		break;
+	case HISI_FB_PIXEL_FORMAT_RGBX_5551:
+	case HISI_FB_PIXEL_FORMAT_BGRX_5551:
+		ret = DMA_PIXEL_FORMAT_XRGB_5551;
+		break;
+	case HISI_FB_PIXEL_FORMAT_RGBA_5551:
+	case HISI_FB_PIXEL_FORMAT_BGRA_5551:
+		ret = DMA_PIXEL_FORMAT_ARGB_5551;
+		break;
+
+	case HISI_FB_PIXEL_FORMAT_RGBX_8888:
+	case HISI_FB_PIXEL_FORMAT_BGRX_8888:
+		ret = DMA_PIXEL_FORMAT_XRGB_8888;
+		break;
+	case HISI_FB_PIXEL_FORMAT_RGBA_8888:
+	case HISI_FB_PIXEL_FORMAT_BGRA_8888:
+		ret = DMA_PIXEL_FORMAT_ARGB_8888;
+		break;
+
+	case HISI_FB_PIXEL_FORMAT_YUV_422_I:
+	case HISI_FB_PIXEL_FORMAT_YUYV_422_Pkg:
+	case HISI_FB_PIXEL_FORMAT_YVYU_422_Pkg:
+	case HISI_FB_PIXEL_FORMAT_UYVY_422_Pkg:
+	case HISI_FB_PIXEL_FORMAT_VYUY_422_Pkg:
+		ret = DMA_PIXEL_FORMAT_YUYV_422_Pkg;
+		break;
+
+	case HISI_FB_PIXEL_FORMAT_YCbCr_422_P:
+	case HISI_FB_PIXEL_FORMAT_YCrCb_422_P:
+		ret = DMA_PIXEL_FORMAT_YUV_422_P_HP;
+		break;
+	case HISI_FB_PIXEL_FORMAT_YCbCr_420_P:
+	case HISI_FB_PIXEL_FORMAT_YCrCb_420_P:
+		ret = DMA_PIXEL_FORMAT_YUV_420_P_HP;
+		break;
+
+	case HISI_FB_PIXEL_FORMAT_YCbCr_422_SP:
+	case HISI_FB_PIXEL_FORMAT_YCrCb_422_SP:
+		ret = DMA_PIXEL_FORMAT_YUV_422_SP_HP;
+		break;
+	case HISI_FB_PIXEL_FORMAT_YCbCr_420_SP:
+	case HISI_FB_PIXEL_FORMAT_YCrCb_420_SP:
+		ret = DMA_PIXEL_FORMAT_YUV_420_SP_HP;
+		break;
+
+	default:
+		HISI_FB_ERR("not support format(%d)!\n", format);
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int hisi_transform_hal2dma(int transform, int chn_idx)
+{
+	int ret = 0;
+
+	if (chn_idx < DSS_WCHN_W0 || chn_idx == DSS_RCHN_V2) {
+		switch (transform) {
+		case HISI_FB_TRANSFORM_NOP:
+			ret = DSS_TRANSFORM_NOP;
+			break;
+		case HISI_FB_TRANSFORM_FLIP_H:
+			ret = DSS_TRANSFORM_FLIP_H;
+			break;
+		case HISI_FB_TRANSFORM_FLIP_V:
+			ret = DSS_TRANSFORM_FLIP_V;
+			break;
+		case HISI_FB_TRANSFORM_ROT_180:
+			ret = DSS_TRANSFORM_FLIP_V | DSS_TRANSFORM_FLIP_H;
+			break;
+		default:
+			ret = -1;
+			HISI_FB_ERR("Transform %d is not supported", transform);
+			break;
+		}
+	} else {
+		if (transform == HISI_FB_TRANSFORM_NOP) {
+			ret = DSS_TRANSFORM_NOP;
+		} else if (transform ==
+			   (HISI_FB_TRANSFORM_ROT_90 |
+			    HISI_FB_TRANSFORM_FLIP_V)) {
+			ret = DSS_TRANSFORM_ROT;
+		} else {
+			ret = -1;
+			HISI_FB_ERR("Transform %d is not supported", transform);
+		}
+	}
+
+	return ret;
+}
+
+static int hisi_pixel_format_hal2dfc(int format)
+{
+	int ret = 0;
+
+	switch (format) {
+	case HISI_FB_PIXEL_FORMAT_RGB_565:
+		ret = DFC_PIXEL_FORMAT_RGB_565;
+		break;
+	case HISI_FB_PIXEL_FORMAT_RGBX_4444:
+		ret = DFC_PIXEL_FORMAT_XBGR_4444;
+		break;
+	case HISI_FB_PIXEL_FORMAT_RGBA_4444:
+		ret = DFC_PIXEL_FORMAT_ABGR_4444;
+		break;
+	case HISI_FB_PIXEL_FORMAT_RGBX_5551:
+		ret = DFC_PIXEL_FORMAT_XBGR_5551;
+		break;
+	case HISI_FB_PIXEL_FORMAT_RGBA_5551:
+		ret = DFC_PIXEL_FORMAT_ABGR_5551;
+		break;
+	case HISI_FB_PIXEL_FORMAT_RGBX_8888:
+		ret = DFC_PIXEL_FORMAT_XBGR_8888;
+		break;
+	case HISI_FB_PIXEL_FORMAT_RGBA_8888:
+		ret = DFC_PIXEL_FORMAT_ABGR_8888;
+		break;
+
+	case HISI_FB_PIXEL_FORMAT_BGR_565:
+		ret = DFC_PIXEL_FORMAT_BGR_565;
+		break;
+	case HISI_FB_PIXEL_FORMAT_BGRX_4444:
+		ret = DFC_PIXEL_FORMAT_XRGB_4444;
+		break;
+	case HISI_FB_PIXEL_FORMAT_BGRA_4444:
+		ret = DFC_PIXEL_FORMAT_ARGB_4444;
+		break;
+	case HISI_FB_PIXEL_FORMAT_BGRX_5551:
+		ret = DFC_PIXEL_FORMAT_XRGB_5551;
+		break;
+	case HISI_FB_PIXEL_FORMAT_BGRA_5551:
+		ret = DFC_PIXEL_FORMAT_ARGB_5551;
+		break;
+	case HISI_FB_PIXEL_FORMAT_BGRX_8888:
+		ret = DFC_PIXEL_FORMAT_XRGB_8888;
+		break;
+	case HISI_FB_PIXEL_FORMAT_BGRA_8888:
+		ret = DFC_PIXEL_FORMAT_ARGB_8888;
+		break;
+
+	case HISI_FB_PIXEL_FORMAT_YUV_422_I:
+	case HISI_FB_PIXEL_FORMAT_YUYV_422_Pkg:
+		ret = DFC_PIXEL_FORMAT_YUYV422;
+		break;
+	case HISI_FB_PIXEL_FORMAT_YVYU_422_Pkg:
+		ret = DFC_PIXEL_FORMAT_YVYU422;
+		break;
+	case HISI_FB_PIXEL_FORMAT_UYVY_422_Pkg:
+		ret = DFC_PIXEL_FORMAT_UYVY422;
+		break;
+	case HISI_FB_PIXEL_FORMAT_VYUY_422_Pkg:
+		ret = DFC_PIXEL_FORMAT_VYUY422;
+		break;
+
+	case HISI_FB_PIXEL_FORMAT_YCbCr_422_SP:
+		ret = DFC_PIXEL_FORMAT_YUYV422;
+		break;
+	case HISI_FB_PIXEL_FORMAT_YCrCb_422_SP:
+		ret = DFC_PIXEL_FORMAT_YVYU422;
+		break;
+	case HISI_FB_PIXEL_FORMAT_YCbCr_420_SP:
+		ret = DFC_PIXEL_FORMAT_YUYV422;
+		break;
+	case HISI_FB_PIXEL_FORMAT_YCrCb_420_SP:
+		ret = DFC_PIXEL_FORMAT_YVYU422;
+		break;
+
+	case HISI_FB_PIXEL_FORMAT_YCbCr_422_P:
+	case HISI_FB_PIXEL_FORMAT_YCbCr_420_P:
+		ret = DFC_PIXEL_FORMAT_YUYV422;
+		break;
+	case HISI_FB_PIXEL_FORMAT_YCrCb_422_P:
+	case HISI_FB_PIXEL_FORMAT_YCrCb_420_P:
+		ret = DFC_PIXEL_FORMAT_YVYU422;
+		break;
+
+	default:
+		HISI_FB_ERR("not support format(%d)!\n", format);
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int hisi_rb_swap(int format)
+{
+	switch (format) {
+	case HISI_FB_PIXEL_FORMAT_BGR_565:
+	case HISI_FB_PIXEL_FORMAT_BGRX_4444:
+	case HISI_FB_PIXEL_FORMAT_BGRA_4444:
+	case HISI_FB_PIXEL_FORMAT_BGRX_5551:
+	case HISI_FB_PIXEL_FORMAT_BGRA_5551:
+	case HISI_FB_PIXEL_FORMAT_BGRX_8888:
+	case HISI_FB_PIXEL_FORMAT_BGRA_8888:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static int hisi_uv_swap(int format)
+{
+	switch (format) {
+	case HISI_FB_PIXEL_FORMAT_YCrCb_422_SP:
+	case HISI_FB_PIXEL_FORMAT_YCrCb_420_SP:
+	case HISI_FB_PIXEL_FORMAT_YCrCb_422_P:
+	case HISI_FB_PIXEL_FORMAT_YCrCb_420_P:
+		return 1;
+
+	default:
+		return 0;
+	}
+}
+
+static int hisi_dfc_get_bpp(int dfc_format)
+{
+	int ret = 0;
+
+	switch (dfc_format) {
+	case DFC_PIXEL_FORMAT_RGB_565:
+	case DFC_PIXEL_FORMAT_XRGB_4444:
+	case DFC_PIXEL_FORMAT_ARGB_4444:
+	case DFC_PIXEL_FORMAT_XRGB_5551:
+	case DFC_PIXEL_FORMAT_ARGB_5551:
+
+	case DFC_PIXEL_FORMAT_BGR_565:
+	case DFC_PIXEL_FORMAT_XBGR_4444:
+	case DFC_PIXEL_FORMAT_ABGR_4444:
+	case DFC_PIXEL_FORMAT_XBGR_5551:
+	case DFC_PIXEL_FORMAT_ABGR_5551:
+		ret = 2;
+		break;
+
+	case DFC_PIXEL_FORMAT_XRGB_8888:
+	case DFC_PIXEL_FORMAT_ARGB_8888:
+	case DFC_PIXEL_FORMAT_XBGR_8888:
+	case DFC_PIXEL_FORMAT_ABGR_8888:
+		ret = 4;
+		break;
+
+	case DFC_PIXEL_FORMAT_YUV444:
+	case DFC_PIXEL_FORMAT_YVU444:
+		ret = 3;
+		break;
+
+	case DFC_PIXEL_FORMAT_YUYV422:
+	case DFC_PIXEL_FORMAT_YVYU422:
+	case DFC_PIXEL_FORMAT_VYUY422:
+	case DFC_PIXEL_FORMAT_UYVY422:
+		ret = 2;
+		break;
+
+	default:
+		HISI_FB_ERR("not support format(%d)!\n", dfc_format);
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static uint32_t hisi_calculate_display_addr(bool mmu_enable,
+					    dss_layer_t *layer,
+					    dss_rect_ltrb_t *aligned_rect,
+					    int add_type)
+{
+	uint32_t addr = 0;
+	uint32_t src_addr = 0;
+	uint32_t stride = 0;
+	uint32_t offset = 0;
+	int bpp = 0;
+	int left = 0;
+	int right = 0;
+	int top = 0;
+	int bottom = 0;
+
+	left = aligned_rect->left;
+	right = aligned_rect->right;
+	top = aligned_rect->top;
+	bottom = aligned_rect->bottom;
+
+	if (add_type == DSS_ADDR_PLANE0) {
+		stride = layer->img.stride;
+		offset = 0;
+		src_addr =
+		    mmu_enable ? layer->img.vir_addr : layer->img.phy_addr;
+		bpp = layer->img.bpp;
+	} else if (add_type == DSS_ADDR_PLANE1) {
+		stride = layer->img.stride_plane1;
+		offset = layer->img.offset_plane1;
+		src_addr = mmu_enable ? (layer->img.vir_addr + offset) :
+		    (layer->img.phy_addr + offset);
+		bpp = 1;
+
+		if (is_YUV_P_420(layer->img.format)
+		    || is_YUV_P_422(layer->img.format)) {
+			left /= 2;
+			right /= 2;
+		}
+
+		if (is_YUV_SP_420(layer->img.format)
+		    || is_YUV_P_420(layer->img.format)) {
+			top /= 2;
+			bottom /= 2;
+		}
+	} else if (add_type == DSS_ADDR_PLANE2) {
+		stride = layer->img.stride_plane2;
+		offset = layer->img.offset_plane2;
+		src_addr = mmu_enable ? (layer->img.vir_addr + offset) :
+		    (layer->img.phy_addr + offset);
+		bpp = 1;
+
+		if (is_YUV_P_420(layer->img.format)
+		    || is_YUV_P_422(layer->img.format)) {
+			left /= 2;
+			right /= 2;
+		}
+
+		if (is_YUV_SP_420(layer->img.format)
+		    || is_YUV_P_420(layer->img.format)) {
+			top /= 2;
+			bottom /= 2;
+		}
+	} else {
+		HISI_FB_ERR("NOT SUPPORT this add_type(%d).\n", add_type);
+		BUG_ON(1);
+	}
+
+	switch (layer->transform) {
+	case HISI_FB_TRANSFORM_NOP:
+		addr = src_addr + top * stride + left * bpp;
+		break;
+	case HISI_FB_TRANSFORM_FLIP_H:
+		addr = src_addr + top * stride + right * bpp;
+		break;
+	case HISI_FB_TRANSFORM_FLIP_V:
+		addr = src_addr + bottom * stride + left * bpp;
+		break;
+	case HISI_FB_TRANSFORM_ROT_180:
+		addr = src_addr + bottom * stride + right * bpp;
+		break;
+	default:
+		HISI_FB_ERR("not supported this transform(%d)!",
+			    layer->transform);
+		break;
+	}
+
+	return addr;
+}
+
+/*******************************************************************************
+ ** DSS MIF
+ */
+static void hisi_dss_mif_init(char __iomem *mif_ch_base,
+			      dss_mif_t *s_mif, int chn_idx)
+{
+	uint32_t rw_type = 0;
+
+	BUG_ON(mif_ch_base == NULL);
+	BUG_ON(s_mif == NULL);
+
+	memset(s_mif, 0, sizeof(dss_mif_t));
+
+	s_mif->mif_ctrl1 = 0x00000020;
+	s_mif->mif_ctrl2 = 0x0;
+	s_mif->mif_ctrl3 = 0x0;
+	s_mif->mif_ctrl4 = 0x0;
+	s_mif->mif_ctrl5 = 0x0;
+	rw_type = (chn_idx < DSS_WCHN_W0 || chn_idx == DSS_RCHN_V2) ? 0x0 : 0x1;
+
+	s_mif->mif_ctrl1 = set_bits32(s_mif->mif_ctrl1, 0x0, 1, 5);
+	s_mif->mif_ctrl1 = set_bits32(s_mif->mif_ctrl1, rw_type, 1, 17);
+}
+
+static void hisi_dss_mif_set_reg(struct hisi_fb_data_type *hisifd,
+				 char __iomem *mif_ch_base, dss_mif_t *s_mif,
+				 int chn_idx)
+{
+	BUG_ON(hisifd == NULL);
+	BUG_ON(mif_ch_base == NULL);
+	BUG_ON(s_mif == NULL);
+
+	hisifd->set_reg(hisifd, mif_ch_base + MIF_CTRL1,
+			s_mif->mif_ctrl1, 32, 0);
+	hisifd->set_reg(hisifd, mif_ch_base + MIF_CTRL2,
+			s_mif->mif_ctrl2, 32, 0);
+	hisifd->set_reg(hisifd, mif_ch_base + MIF_CTRL3,
+			s_mif->mif_ctrl3, 32, 0);
+	hisifd->set_reg(hisifd, mif_ch_base + MIF_CTRL4,
+			s_mif->mif_ctrl4, 32, 0);
+	hisifd->set_reg(hisifd, mif_ch_base + MIF_CTRL5,
+			s_mif->mif_ctrl5, 32, 0);
+}
+
+void hisi_dss_mif_on(struct hisi_fb_data_type *hisifd)
+{
+	char __iomem *mif_base = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	mif_base = hisifd->dss_base + DSS_MIF_OFFSET;
+
+	set_reg(mif_base + MIF_ENABLE, 0x1, 1, 0);
+	set_reg(hisifd->dss_base + MIF_CH0_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+	set_reg(hisifd->dss_base + MIF_CH1_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+	set_reg(hisifd->dss_base + MIF_CH2_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+	set_reg(hisifd->dss_base + MIF_CH3_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+	set_reg(hisifd->dss_base + MIF_CH4_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+	set_reg(hisifd->dss_base + MIF_CH5_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+	set_reg(hisifd->dss_base + MIF_CH6_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+	set_reg(hisifd->dss_base + MIF_CH7_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+	set_reg(hisifd->dss_base + MIF_CH8_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+	set_reg(hisifd->dss_base + MIF_CH9_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+
+	set_reg(hisifd->dss_base + MIF_CH10_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+	set_reg(hisifd->dss_base + MIF_CH11_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+}
+
+int hisi_dss_mif_config(struct hisi_fb_data_type *hisifd,
+			dss_layer_t *layer, dss_wb_layer_t *wb_layer,
+			bool rdma_stretch_enable)
+{
+	dss_mif_t *mif = NULL;
+	int chn_idx = 0;
+	dss_img_t *img = NULL;
+	uint32_t transform = 0;
+	uint32_t invalid_sel = 0;
+	uint32_t need_cap = 0;
+	uint32_t *semi_plane1 = NULL;
+	int v_scaling_factor = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON((layer == NULL) && (wb_layer == NULL));
+
+	if (wb_layer) {
+		img = &(wb_layer->dst);
+		chn_idx = wb_layer->chn_idx;
+		transform = wb_layer->transform;
+		need_cap = wb_layer->need_cap;
+		v_scaling_factor = 1;
+	} else {
+		img = &(layer->img);
+		chn_idx = layer->chn_idx;
+		transform = layer->transform;
+		need_cap = layer->need_cap;
+		v_scaling_factor =
+		    layer->src_rect.h / layer->dst_rect.h +
+		    ((layer->src_rect.h % layer->dst_rect.h) > 0 ? 1 : 0);
+	}
+
+	mif = &(hisifd->dss_module.mif[chn_idx]);
+	hisifd->dss_module.mif_used[chn_idx] = 1;
+
+	semi_plane1 = &mif->mif_ctrl4;
+
+	if (img->mmu_enable == 0) {
+		mif->mif_ctrl1 = set_bits32(mif->mif_ctrl1, 0x1, 1, 5);
+	} else {
+		if (need_cap & (CAP_AFBCD | CAP_AFBCE)) {
+			invalid_sel = 0;
+		} else {
+			invalid_sel =
+			    hisi_dss_mif_get_invalid_sel(img, transform,
+							 v_scaling_factor,
+							 ((need_cap & CAP_TILE)
+							  ? 1 : 0),
+							 rdma_stretch_enable);
+		}
+
+		mif->mif_ctrl1 = set_bits32(mif->mif_ctrl1, 0x0, 1, 5);
+		mif->mif_ctrl1 = set_bits32(mif->mif_ctrl1, invalid_sel, 2, 10);
+		mif->mif_ctrl1 =
+		    set_bits32(mif->mif_ctrl1, ((invalid_sel == 0) ? 0x1 : 0x0),
+			       1, 19);
+
+		if (invalid_sel == 0) {
+			mif->mif_ctrl2 = set_bits32(mif->mif_ctrl2, 0x0, 20, 0);
+			mif->mif_ctrl3 = set_bits32(mif->mif_ctrl3, 0x0, 20, 0);
+			mif->mif_ctrl4 = set_bits32(mif->mif_ctrl4, 0x0, 20, 0);
+			mif->mif_ctrl5 = set_bits32(mif->mif_ctrl5, 0x0, 20, 0);
+		} else if ((invalid_sel == 1) || (invalid_sel == 2)) {
+			if (img->stride > 0) {
+				mif->mif_ctrl5 = set_bits32(mif->mif_ctrl5,
+							    ((img->stride /MIF_STRIDE_UNIT) +
+							     (((img->stride % MIF_STRIDE_UNIT) > 0) ?
+							        1 : 0)), 20, 0);
+			}
+
+			if (isYUVSemiPlanar(img->format)) {
+				if (img->stride_plane1 > 0) {
+					*semi_plane1 = set_bits32(*semi_plane1,
+							((img->stride_plane1 / MIF_STRIDE_UNIT) +
+							 (((img->stride_plane1 % MIF_STRIDE_UNIT) >0) ?
+							   1 : 0)), 20, 0);
+				}
+			} else if (isYUVPlanar(img->format)) {
+				if (img->stride_plane1 > 0) {
+					mif->mif_ctrl4 =
+					    set_bits32(mif->mif_ctrl4,
+						       ((img->stride_plane1 /
+							 MIF_STRIDE_UNIT) +
+							(((img->stride_plane1 %
+							   MIF_STRIDE_UNIT) >
+							  0) ? 1 : 0)), 20, 0);
+				}
+
+				if (img->stride_plane2 > 0) {
+					mif->mif_ctrl3 =
+					    set_bits32(mif->mif_ctrl3,
+						       ((img->stride_plane2 /
+							 MIF_STRIDE_UNIT) +
+							(((img->stride_plane2 %
+							   MIF_STRIDE_UNIT) >
+							  0) ? 1 : 0)), 20, 0);
+				}
+			} else {
+				;
+			}
+		} else if (invalid_sel == 3) {
+			if (img->stride > 0) {
+				mif->mif_ctrl5 =
+				    set_bits32(mif->mif_ctrl5,
+					       DSS_MIF_CTRL2_INVAL_SEL3_STRIDE_MASK, 4, 16);
+			}
+			if (isYUVSemiPlanar(img->format)) {
+				if (img->stride_plane1 > 0)
+					*semi_plane1 =
+					    set_bits32(*semi_plane1, 0xE, 4, 16);
+
+			} else if (isYUVPlanar(img->format)) {
+				if (img->stride_plane1 > 0)
+					mif->mif_ctrl3 =
+					    set_bits32(mif->mif_ctrl3, 0xE, 4, 16);
+
+				if (img->stride_plane2 > 0)
+					mif->mif_ctrl4 =
+					    set_bits32(mif->mif_ctrl4, 0xE, 4, 16);
+			} else {
+				;
+			}
+		} else {
+			HISI_FB_ERR("fb%d, invalid_sel(%d) not support!\n",
+				    hisifd->index, invalid_sel);
+		}
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+ ** DSS RDMA
+ */
+static void hisi_dss_rdma_init(char __iomem *dma_base, dss_rdma_t *s_dma)
+{
+	BUG_ON(dma_base == NULL);
+	BUG_ON(s_dma == NULL);
+
+	memset(s_dma, 0, sizeof(dss_rdma_t));
+
+	s_dma->oft_x0 = inp32(dma_base + DMA_OFT_X0);
+	s_dma->oft_y0 = inp32(dma_base + DMA_OFT_Y0);
+	s_dma->oft_x1 = inp32(dma_base + DMA_OFT_X1);
+	s_dma->oft_y1 = inp32(dma_base + DMA_OFT_Y1);
+	s_dma->mask0 = inp32(dma_base + DMA_MASK0);
+	s_dma->mask1 = inp32(dma_base + DMA_MASK1);
+	s_dma->stretch_size_vrt = inp32(dma_base + DMA_STRETCH_SIZE_VRT);
+	s_dma->ctrl = inp32(dma_base + DMA_CTRL);
+	s_dma->tile_scram = inp32(dma_base + DMA_TILE_SCRAM);
+
+	s_dma->ch_rd_shadow = inp32(dma_base + CH_RD_SHADOW);
+	s_dma->ch_ctl = inp32(dma_base + CH_CTL);
+
+	s_dma->data_addr0 = inp32(dma_base + DMA_DATA_ADDR0);
+	s_dma->stride0 = inp32(dma_base + DMA_STRIDE0);
+	s_dma->stretch_stride0 = inp32(dma_base + DMA_STRETCH_STRIDE0);
+	s_dma->data_num0 = inp32(dma_base + DMA_DATA_NUM0);
+
+	s_dma->vpp_ctrl = inp32(dma_base + VPP_CTRL);
+	s_dma->vpp_mem_ctrl = inp32(dma_base + VPP_MEM_CTRL);
+
+	s_dma->dma_buf_ctrl = inp32(dma_base + DMA_BUF_CTRL);
+
+	s_dma->afbcd_hreg_hdr_ptr_lo = inp32(dma_base + AFBCD_HREG_HDR_PTR_LO);
+	s_dma->afbcd_hreg_pic_width = inp32(dma_base + AFBCD_HREG_PIC_WIDTH);
+	s_dma->afbcd_hreg_pic_height = inp32(dma_base + AFBCD_HREG_PIC_HEIGHT);
+	s_dma->afbcd_hreg_format = inp32(dma_base + AFBCD_HREG_FORMAT);
+	s_dma->afbcd_ctl = inp32(dma_base + AFBCD_CTL);
+	s_dma->afbcd_str = inp32(dma_base + AFBCD_STR);
+	s_dma->afbcd_line_crop = inp32(dma_base + AFBCD_LINE_CROP);
+	s_dma->afbcd_input_header_stride =
+	    inp32(dma_base + AFBCD_INPUT_HEADER_STRIDE);
+	s_dma->afbcd_payload_stride = inp32(dma_base + AFBCD_PAYLOAD_STRIDE);
+	s_dma->afbcd_mm_base_0 = inp32(dma_base + AFBCD_MM_BASE_0);
+	s_dma->afbcd_afbcd_payload_pointer =
+	    inp32(dma_base + AFBCD_AFBCD_PAYLOAD_POINTER);
+	s_dma->afbcd_height_bf_str = inp32(dma_base + AFBCD_HEIGHT_BF_STR);
+	s_dma->afbcd_os_cfg = inp32(dma_base + AFBCD_OS_CFG);
+	s_dma->afbcd_mem_ctrl = inp32(dma_base + AFBCD_MEM_CTRL);
+}
+
+static void hisi_dss_rdma_u_init(char __iomem *dma_base, dss_rdma_t *s_dma)
+{
+	BUG_ON(dma_base == NULL);
+	BUG_ON(s_dma == NULL);
+
+	s_dma->data_addr1 = inp32(dma_base + DMA_DATA_ADDR1);
+	s_dma->stride1 = inp32(dma_base + DMA_STRIDE1);
+	s_dma->stretch_stride1 = inp32(dma_base + DMA_STRETCH_STRIDE1);
+	s_dma->data_num1 = inp32(dma_base + DMA_DATA_NUM1);
+}
+
+static void hisi_dss_rdma_v_init(char __iomem *dma_base, dss_rdma_t *s_dma)
+{
+	BUG_ON(dma_base == NULL);
+	BUG_ON(s_dma == NULL);
+
+	s_dma->data_addr2 = inp32(dma_base + DMA_DATA_ADDR2);
+	s_dma->stride2 = inp32(dma_base + DMA_STRIDE2);
+	s_dma->stretch_stride2 = inp32(dma_base + DMA_STRETCH_STRIDE2);
+	s_dma->data_num2 = inp32(dma_base + DMA_DATA_NUM2);
+}
+
+void hisi_dss_chn_set_reg_default_value(struct hisi_fb_data_type *hisifd,
+					char __iomem *dma_base)
+{
+	BUG_ON(hisifd == NULL);
+	BUG_ON(dma_base == NULL);
+
+	hisifd->set_reg(hisifd, dma_base + CH_REG_DEFAULT, 0x1, 32, 0);
+	hisifd->set_reg(hisifd, dma_base + CH_REG_DEFAULT, 0x0, 32, 0);
+}
+
+static void hisi_dss_rdma_set_reg(struct hisi_fb_data_type *hisifd,
+				  char __iomem *dma_base, dss_rdma_t *s_dma)
+{
+	BUG_ON(hisifd == NULL);
+	BUG_ON(dma_base == NULL);
+	BUG_ON(s_dma == NULL);
+
+	hisifd->set_reg(hisifd, dma_base + CH_REG_DEFAULT, 0x1, 32, 0);
+	hisifd->set_reg(hisifd, dma_base + CH_REG_DEFAULT, 0x0, 32, 0);
+
+	hisifd->set_reg(hisifd, dma_base + DMA_OFT_X0, s_dma->oft_x0, 32, 0);
+	hisifd->set_reg(hisifd, dma_base + DMA_OFT_Y0, s_dma->oft_y0, 32, 0);
+	hisifd->set_reg(hisifd, dma_base + DMA_OFT_X1, s_dma->oft_x1, 32, 0);
+	hisifd->set_reg(hisifd, dma_base + DMA_OFT_Y1, s_dma->oft_y1, 32, 0);
+	hisifd->set_reg(hisifd, dma_base + DMA_MASK0, s_dma->mask0, 32, 0);
+	hisifd->set_reg(hisifd, dma_base + DMA_MASK1, s_dma->mask1, 32, 0);
+	hisifd->set_reg(hisifd, dma_base + DMA_STRETCH_SIZE_VRT,
+			s_dma->stretch_size_vrt, 32, 0);
+	hisifd->set_reg(hisifd, dma_base + DMA_CTRL, s_dma->ctrl, 32, 0);
+	hisifd->set_reg(hisifd, dma_base + DMA_TILE_SCRAM, s_dma->tile_scram,
+			32, 0);
+	hisifd->set_reg(hisifd, dma_base + DMA_DATA_ADDR0, s_dma->data_addr0,
+			32, 0);
+	hisifd->set_reg(hisifd, dma_base + DMA_STRIDE0, s_dma->stride0, 32, 0);
+	hisifd->set_reg(hisifd, dma_base + DMA_STRETCH_STRIDE0,
+			s_dma->stretch_stride0, 32, 0);
+
+	hisifd->set_reg(hisifd, dma_base + CH_RD_SHADOW, s_dma->ch_rd_shadow,
+			32, 0);
+	hisifd->set_reg(hisifd, dma_base + CH_CTL, s_dma->ch_ctl, 32, 0);
+
+	if (s_dma->vpp_used) {
+		hisifd->set_reg(hisifd, dma_base + VPP_CTRL, s_dma->vpp_ctrl,
+				32, 0);
+	}
+
+	hisifd->set_reg(hisifd, dma_base + DMA_BUF_CTRL, s_dma->dma_buf_ctrl,
+			32, 0);
+
+	if (s_dma->afbc_used) {
+		hisifd->set_reg(hisifd, dma_base + AFBCD_HREG_HDR_PTR_LO,
+				s_dma->afbcd_hreg_hdr_ptr_lo, 32, 0);
+		hisifd->set_reg(hisifd, dma_base + AFBCD_HREG_PIC_WIDTH,
+				s_dma->afbcd_hreg_pic_width, 32, 0);
+		hisifd->set_reg(hisifd, dma_base + AFBCD_HREG_PIC_HEIGHT,
+				s_dma->afbcd_hreg_pic_height, 32, 0);
+		hisifd->set_reg(hisifd, dma_base + AFBCD_HREG_FORMAT,
+				s_dma->afbcd_hreg_format, 32, 0);
+		hisifd->set_reg(hisifd, dma_base + AFBCD_CTL, s_dma->afbcd_ctl,
+				32, 0);
+		hisifd->set_reg(hisifd, dma_base + AFBCD_STR, s_dma->afbcd_str,
+				32, 0);
+		hisifd->set_reg(hisifd, dma_base + AFBCD_LINE_CROP,
+				s_dma->afbcd_line_crop, 32, 0);
+		hisifd->set_reg(hisifd, dma_base + AFBCD_INPUT_HEADER_STRIDE,
+				s_dma->afbcd_input_header_stride, 32, 0);
+		hisifd->set_reg(hisifd, dma_base + AFBCD_PAYLOAD_STRIDE,
+				s_dma->afbcd_payload_stride, 32, 0);
+		hisifd->set_reg(hisifd, dma_base + AFBCD_MM_BASE_0,
+				s_dma->afbcd_mm_base_0, 32, 0);
+		hisifd->set_reg(hisifd, dma_base + AFBCD_AFBCD_PAYLOAD_POINTER,
+				s_dma->afbcd_afbcd_payload_pointer, 32, 0);
+		hisifd->set_reg(hisifd, dma_base + AFBCD_HEIGHT_BF_STR,
+				s_dma->afbcd_height_bf_str, 32, 0);
+		hisifd->set_reg(hisifd, dma_base + AFBCD_OS_CFG,
+				s_dma->afbcd_os_cfg, 32, 0);
+		hisifd->set_reg(hisifd, dma_base + AFBCD_SCRAMBLE_MODE,
+				s_dma->afbcd_scramble_mode, 32, 0);
+		hisifd->set_reg(hisifd, dma_base + AFBCD_HEADER_POINTER_OFFSET,
+				s_dma->afbcd_header_pointer_offset, 32, 0);
+	}
+}
+
+static void hisi_dss_rdma_u_set_reg(struct hisi_fb_data_type *hisifd,
+				    char __iomem *dma_base, dss_rdma_t *s_dma)
+{
+	BUG_ON(hisifd == NULL);
+	BUG_ON(dma_base == NULL);
+	BUG_ON(s_dma == NULL);
+
+	hisifd->set_reg(hisifd, dma_base + DMA_DATA_ADDR1, s_dma->data_addr1,
+			32, 0);
+	hisifd->set_reg(hisifd, dma_base + DMA_STRIDE1, s_dma->stride1, 32, 0);
+	hisifd->set_reg(hisifd, dma_base + DMA_STRETCH_STRIDE1,
+			s_dma->stretch_stride1, 32, 0);
+}
+
+static void hisi_dss_rdma_v_set_reg(struct hisi_fb_data_type *hisifd,
+				    char __iomem *dma_base, dss_rdma_t *s_dma)
+{
+	BUG_ON(hisifd == NULL);
+	BUG_ON(dma_base == NULL);
+	BUG_ON(s_dma == NULL);
+
+	hisifd->set_reg(hisifd, dma_base + DMA_DATA_ADDR2, s_dma->data_addr2,
+			32, 0);
+	hisifd->set_reg(hisifd, dma_base + DMA_STRIDE2, s_dma->stride2, 32, 0);
+	hisifd->set_reg(hisifd, dma_base + DMA_STRETCH_STRIDE2,
+			s_dma->stretch_stride2, 32, 0);
+}
+
+static int hisi_get_rdma_tile_interleave(uint32_t stride)
+{
+	int i = 0;
+	uint32_t interleave[MAX_TILE_SURPORT_NUM] = {
+		256, 512, 1024, 2048, 4096, 8192,
+	};
+
+	for (i = 0; i < MAX_TILE_SURPORT_NUM; i++) {
+		if (interleave[i] == stride)
+			return MIN_INTERLEAVE + i;
+	}
+
+	return 0;
+}
+
+int hisi_dss_rdma_config(struct hisi_fb_data_type *hisifd, int ovl_idx,
+			 dss_layer_t *layer, dss_rect_ltrb_t *clip_rect,
+			 dss_rect_t *out_aligned_rect,
+			 bool *rdma_stretch_enable)
+{
+	dss_rdma_t *dma = NULL;
+
+	bool mmu_enable = false;
+	bool is_yuv_semi_planar = false;
+	bool is_yuv_planar = false;
+	bool src_rect_mask_enable = false;
+
+	uint32_t rdma_addr = 0;
+	uint32_t rdma_stride = 0;
+	int rdma_format = 0;
+	int rdma_transform = 0;
+	int rdma_data_num = 0;
+	uint32_t stretch_size_vrt = 0;
+	uint32_t stretched_line_num = 0;
+	uint32_t stretched_stride = 0;
+
+	int bpp = 0;
+	int aligned_pixel = 0;
+	int rdma_oft_x0 = 0;
+	int rdma_oft_y0 = 0;
+	int rdma_oft_x1 = 0;
+	int rdma_oft_y1 = 0;
+	int rdma_mask_x0 = 0;
+	int rdma_mask_y0 = 0;
+	int rdma_mask_x1 = 0;
+	int rdma_mask_y1 = 0;
+
+	int chn_idx = 0;
+	uint32_t l2t_interleave_n = 0;
+	dss_rect_ltrb_t aligned_rect = { 0, 0, 0, 0 };
+	dss_rect_ltrb_t aligned_mask_rect = { 0, 0, 0, 0 };
+	dss_rect_t new_src_rect;
+
+	uint32_t afbcd_half_block_mode = 0;
+	uint32_t afbcd_stretch_acc = 0;
+	uint32_t afbcd_stretch_inc = 0;
+	uint32_t afbcd_height_bf_str = 0;
+	uint32_t afbcd_top_crop_num = 0;
+	uint32_t afbcd_bottom_crop_num = 0;
+	uint32_t afbc_header_addr = 0;
+	uint32_t afbc_header_stride = 0;
+	uint32_t afbc_payload_addr = 0;
+	uint32_t afbc_payload_stride = 0;
+	uint32_t afbc_header_start_pos = 0;
+	uint32_t afbc_header_pointer_offset = 0;
+	uint32_t stride_align = 0;
+	uint32_t addr_align = 0;
+	dss_rect_ltrb_t afbc_rect;
+	uint32_t mm_base_0 = 0;
+	uint32_t mm_base_1 = 0;
+	bool mm_alloc_needed = false;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(layer == NULL);
+	BUG_ON((ovl_idx < DSS_OVL0) || (ovl_idx >= DSS_OVL_IDX_MAX));
+
+	chn_idx = layer->chn_idx;
+	new_src_rect = layer->src_rect;
+
+	stretched_line_num = isNeedRdmaStretchBlt(hisifd, layer);
+	*rdma_stretch_enable = (stretched_line_num > 0) ? true : false;
+
+	mmu_enable = (layer->img.mmu_enable == 1) ? true : false;
+	is_yuv_semi_planar = isYUVSemiPlanar(layer->img.format);
+	is_yuv_planar = isYUVPlanar(layer->img.format);
+
+	rdma_format = hisi_pixel_format_hal2dma(layer->img.format);
+	if (rdma_format < 0) {
+		HISI_FB_ERR("layer format(%d) not support !\n",
+			    layer->img.format);
+		return -EINVAL;
+	}
+
+	rdma_transform = hisi_transform_hal2dma(layer->transform, chn_idx);
+	if (rdma_transform < 0) {
+		HISI_FB_ERR("layer transform(%d) not support!\n",
+			    layer->transform);
+		return -EINVAL;
+	}
+
+	bpp = (is_yuv_semi_planar || is_yuv_planar) ? 1 : layer->img.bpp;
+	aligned_pixel = DMA_ALIGN_BYTES / bpp;
+
+	src_rect_mask_enable = isSrcRectMasked(layer, aligned_pixel);
+
+	dma = &(hisifd->dss_module.rdma[chn_idx]);
+	hisifd->dss_module.dma_used[chn_idx] = 1;
+
+	if (layer->need_cap & CAP_YUV_DEINTERLACE) {
+		dma->vpp_used = 1;
+
+		if (layer->transform & HISI_FB_TRANSFORM_ROT_90) {
+			dma->vpp_ctrl = set_bits32(dma->vpp_ctrl, 0x2, 2, 0);
+		} else {
+			dma->vpp_ctrl = set_bits32(dma->vpp_ctrl, 0x3, 2, 0);
+		}
+	}
+
+	if (layer->need_cap & CAP_AFBCD) {
+		if ((layer->img.mmbuf_base > 0) && (layer->img.mmbuf_size > 0)) {
+			mm_base_0 = layer->img.mmbuf_base;
+			mm_base_1 =
+			    layer->img.mmbuf_base + layer->img.mmbuf_size / 2;
+		} else {
+			BUG_ON(hisifd->mmbuf_info == NULL);
+
+			if (ovl_idx <= DSS_OVL1) {
+				mm_alloc_needed = true;
+			} else {
+				if (hisifd->mmbuf_info->mm_used[chn_idx] == 1)
+					mm_alloc_needed = false;
+				else
+					mm_alloc_needed = true;
+			}
+
+			if (mm_alloc_needed) {
+				afbc_rect.left =
+				    ALIGN_DOWN(new_src_rect.x,
+					       MMBUF_ADDR_ALIGN);
+				afbc_rect.right =
+				    ALIGN_UP(new_src_rect.x - afbc_rect.left +
+					     new_src_rect.w, MMBUF_ADDR_ALIGN);
+				hisifd->mmbuf_info->mm_size[chn_idx] =
+				    afbc_rect.right * layer->img.bpp *
+				    MMBUF_LINE_NUM;
+				hisifd->mmbuf_info->mm_base[chn_idx] =
+				    hisi_dss_mmbuf_alloc(g_mmbuf_gen_pool,
+							 hisifd->mmbuf_info->mm_size[chn_idx]);
+				if (hisifd->mmbuf_info->mm_base[chn_idx] <
+				    MMBUF_BASE) {
+					HISI_FB_ERR
+					    ("fb%d, chn%d failed to alloc mmbuf, mm_base=0x%x.\n",
+					     hisifd->index, chn_idx,
+					     hisifd->mmbuf_info->mm_base[chn_idx]);
+					return -EINVAL;
+				}
+			}
+
+			mm_base_0 = hisifd->mmbuf_info->mm_base[chn_idx];
+			mm_base_1 = hisifd->mmbuf_info->mm_base[chn_idx] +
+			    hisifd->mmbuf_info->mm_size[chn_idx] / 2;
+			hisifd->mmbuf_info->mm_used[chn_idx] = 1;
+		}
+
+		mm_base_0 -= MMBUF_BASE;
+		mm_base_1 -= MMBUF_BASE;
+
+		if ((layer->img.width & (AFBC_HEADER_ADDR_ALIGN - 1)) ||
+		    (layer->img.height & (AFBC_BLOCK_ALIGN - 1))) {
+			HISI_FB_ERR
+			    ("layer%d img width(%d) is not %d bytes aligned, or "
+			     "img heigh(%d) is not %d bytes aligned!\n",
+			     layer->layer_idx, layer->img.width,
+			     AFBC_HEADER_ADDR_ALIGN, layer->img.height,
+			     AFBC_BLOCK_ALIGN);
+			return -EINVAL;
+		}
+
+		if ((mm_base_0 & (MMBUF_ADDR_ALIGN - 1)) ||
+		    (mm_base_1 & (MMBUF_ADDR_ALIGN - 1)) ||
+		    (layer->img.mmbuf_size & (MMBUF_ADDR_ALIGN - 1))) {
+			HISI_FB_ERR
+			    ("layer%d mm_base_0(0x%x) is not %d bytes aligned, or "
+			     "mm_base_1(0x%x) is not %d bytes aligned, or mmbuf_size(0x%x) is "
+			     "not %d bytes aligned!\n", layer->layer_idx,
+			     mm_base_0, MMBUF_ADDR_ALIGN, mm_base_1,
+			     MMBUF_ADDR_ALIGN, layer->img.mmbuf_size,
+			     MMBUF_ADDR_ALIGN);
+			return -EINVAL;
+		}
+
+		dma->afbc_used = 1;
+
+		aligned_rect.left =
+		    ALIGN_DOWN(new_src_rect.x, AFBC_BLOCK_ALIGN);
+		aligned_rect.right =
+		    ALIGN_UP(new_src_rect.x + new_src_rect.w,
+			     AFBC_BLOCK_ALIGN) - 1;
+		aligned_rect.top = ALIGN_DOWN(new_src_rect.y, AFBC_BLOCK_ALIGN);
+		aligned_rect.bottom =
+		    ALIGN_UP(new_src_rect.y + new_src_rect.h,
+			     AFBC_BLOCK_ALIGN) - 1;
+
+		out_aligned_rect->x = 0;
+		out_aligned_rect->y = 0;
+		out_aligned_rect->w =
+		    aligned_rect.right - aligned_rect.left + 1;
+		out_aligned_rect->h =
+		    aligned_rect.bottom - aligned_rect.top + 1;
+
+		afbcd_height_bf_str =
+		    aligned_rect.bottom - aligned_rect.top + 1;
+
+		if (*rdma_stretch_enable) {
+			afbcd_stretch_inc = 0;
+			afbcd_stretch_acc = 0;
+
+			out_aligned_rect->h /= 2;
+			if (layer->transform & HISI_FB_TRANSFORM_FLIP_V) {
+				afbcd_half_block_mode =
+				    AFBC_HALF_BLOCK_LOWER_ONLY;
+			} else {
+				afbcd_half_block_mode =
+				    AFBC_HALF_BLOCK_UPPER_ONLY;
+			}
+		} else {
+			if (layer->transform & HISI_FB_TRANSFORM_FLIP_V) {
+				afbcd_half_block_mode =
+				    AFBC_HALF_BLOCK_LOWER_UPPER_ALL;
+			} else {
+				afbcd_half_block_mode =
+				    AFBC_HALF_BLOCK_UPPER_LOWER_ALL;
+			}
+		}
+
+		if (layer->img.
+		    afbc_header_addr & (AFBC_SUPER_GRAPH_HEADER_ADDR_ALIGN -
+					1)) {
+			HISI_FB_ERR
+			    ("layer%d super graph afbc_header_addr(0x%x) "
+			     "is not %d bytes aligned!\n",
+			     layer->layer_idx, afbc_header_addr,
+			     AFBC_SUPER_GRAPH_HEADER_ADDR_ALIGN);
+			return -EINVAL;
+		}
+
+		clip_rect->left = new_src_rect.x - aligned_rect.left;
+		clip_rect->right =
+		    aligned_rect.right - DSS_WIDTH(new_src_rect.x +
+						   new_src_rect.w);
+		clip_rect->top = new_src_rect.y - aligned_rect.top;
+		clip_rect->bottom =
+		    aligned_rect.bottom - DSS_HEIGHT(new_src_rect.y +
+						     new_src_rect.h);
+		if (hisi_adjust_clip_rect(layer, clip_rect) < 0) {
+			HISI_FB_ERR
+			    ("clip rect invalid => layer_idx=%d, chn_idx=%d, "
+			     "clip_rect(%d, %d, %d, %d).\n",
+			     layer->layer_idx, chn_idx, clip_rect->left,
+			     clip_rect->right, clip_rect->top,
+			     clip_rect->bottom);
+			return -EINVAL;
+		}
+
+		afbcd_top_crop_num = (clip_rect->top > AFBCD_TOP_CROP_MAX) ?
+		    AFBCD_TOP_CROP_MAX : clip_rect->top;
+		afbcd_bottom_crop_num =
+		    (clip_rect->bottom >
+		     AFBCD_BOTTOM_CROP_MAX) ? AFBCD_BOTTOM_CROP_MAX :
+		    clip_rect->bottom;
+
+		clip_rect->top -= afbcd_top_crop_num;
+		BUG_ON(clip_rect->top < 0);
+		clip_rect->bottom -= afbcd_bottom_crop_num;
+		BUG_ON(clip_rect->bottom < 0);
+
+		out_aligned_rect->h -=
+		    (afbcd_top_crop_num + afbcd_bottom_crop_num);
+
+		rdma_oft_x0 = aligned_rect.left / aligned_pixel;
+		rdma_oft_x1 = aligned_rect.right / aligned_pixel;
+		stretch_size_vrt = DSS_HEIGHT(out_aligned_rect->h);
+		stretched_line_num = 0;
+
+		afbc_rect = aligned_rect;
+		afbc_rect.left =
+		    ALIGN_DOWN(new_src_rect.x, AFBC_HEADER_ADDR_ALIGN);
+		afbc_rect.right =
+		    ALIGN_UP(new_src_rect.x + new_src_rect.w,
+			     AFBC_HEADER_ADDR_ALIGN) - 1;
+
+		afbc_header_stride =
+		    (layer->img.width / AFBC_BLOCK_ALIGN) *
+		    AFBC_HEADER_STRIDE_BLOCK;
+		afbc_header_pointer_offset =
+		    (afbc_rect.top / AFBC_BLOCK_ALIGN) * afbc_header_stride +
+		    (afbc_rect.left / AFBC_BLOCK_ALIGN) *
+		    AFBC_HEADER_STRIDE_BLOCK;
+		afbc_header_addr =
+		    layer->img.afbc_header_addr + afbc_header_pointer_offset;
+
+		if ((afbc_header_addr & (AFBC_HEADER_ADDR_ALIGN - 1)) ||
+		    (afbc_header_stride & (AFBC_HEADER_STRIDE_ALIGN - 1))) {
+			HISI_FB_ERR
+			    ("layer%d afbc_header_addr(0x%x) is not %d bytes aligned, or "
+			     "afbc_header_stride(0x%x) is not %d bytes aligned!\n",
+			     layer->layer_idx, afbc_header_addr,
+			     AFBC_HEADER_ADDR_ALIGN, afbc_header_stride,
+			     AFBC_HEADER_STRIDE_ALIGN);
+			return -EINVAL;
+		}
+
+		BUG_ON((aligned_rect.left - afbc_rect.left) < 0);
+		afbc_header_start_pos =
+		    (aligned_rect.left - afbc_rect.left) / AFBC_BLOCK_ALIGN;
+
+		if (layer->img.bpp == 4) {
+			stride_align = AFBC_PAYLOAD_STRIDE_ALIGN_32;
+			addr_align = AFBC_PAYLOAD_ADDR_ALIGN_32;
+		} else if (layer->img.bpp == 2) {
+			stride_align = AFBC_PAYLOAD_STRIDE_ALIGN_16;
+			addr_align = AFBC_PAYLOAD_ADDR_ALIGN_16;
+		} else {
+			HISI_FB_ERR("bpp(%d) not supported!\n", layer->img.bpp);
+			return -EINVAL;
+		}
+
+		afbc_payload_stride = layer->img.afbc_payload_stride;
+		if (layer->img.afbc_scramble_mode != DSS_AFBC_SCRAMBLE_MODE2) {
+			afbc_payload_stride =
+			    (layer->img.width / AFBC_BLOCK_ALIGN) *
+			    stride_align;
+		}
+		afbc_payload_addr = layer->img.afbc_payload_addr +
+		    (aligned_rect.top / AFBC_BLOCK_ALIGN) *
+		    afbc_payload_stride +
+		    (aligned_rect.left / AFBC_BLOCK_ALIGN) * stride_align;
+
+		if ((afbc_payload_addr & (addr_align - 1)) ||
+		    (afbc_payload_stride & (stride_align - 1))) {
+			HISI_FB_ERR
+			    ("layer%d afbc_payload_addr(0x%x) is not %d bytes aligned, or "
+			     "afbc_payload_stride(0x%x) is not %d bytes aligned!\n",
+			     layer->layer_idx, afbc_payload_addr, addr_align,
+			     afbc_payload_stride, stride_align);
+			return -EINVAL;
+		}
+
+		if (g_debug_ovl_online_composer) {
+			HISI_FB_INFO
+			    ("fb%d, mm_base_0=0x%x, mm_base_1=0x%x, mmbuf_size=%d, "
+			     "aligned_rect(%d,%d,%d,%d), afbc_rect(%d,%d,%d,%d)!\n",
+			     hisifd->index, mm_base_0, mm_base_1,
+			     layer->img.mmbuf_size, aligned_rect.left,
+			     aligned_rect.top, aligned_rect.right,
+			     aligned_rect.bottom, afbc_rect.left, afbc_rect.top,
+			     afbc_rect.right, afbc_rect.bottom);
+		}
+
+		dma->oft_x0 = set_bits32(dma->oft_x0, rdma_oft_x0, 16, 0);
+		dma->oft_x1 = set_bits32(dma->oft_x1, rdma_oft_x1, 16, 0);
+		dma->stretch_size_vrt = set_bits32(dma->stretch_size_vrt,
+						   (stretch_size_vrt |
+						    (stretched_line_num << 13)),
+						   19, 0);
+		dma->ctrl = set_bits32(dma->ctrl, rdma_format, 5, 3);
+		dma->ctrl =
+		    set_bits32(dma->ctrl, (mmu_enable ? 0x1 : 0x0), 1, 8);
+		dma->ctrl = set_bits32(dma->ctrl, rdma_transform, 3, 9);
+		dma->ctrl =
+		    set_bits32(dma->ctrl, (*rdma_stretch_enable ? 1 : 0), 1,
+			       12);
+		dma->ch_ctl = set_bits32(dma->ch_ctl, 0x1, 1, 0);
+		dma->ch_ctl = set_bits32(dma->ch_ctl, 0x1, 1, 2);
+
+		dma->afbcd_hreg_pic_width =
+		    set_bits32(dma->afbcd_hreg_pic_width,
+			       (aligned_rect.right - aligned_rect.left), 16, 0);
+		dma->afbcd_hreg_pic_height =
+		    set_bits32(dma->afbcd_hreg_pic_height,
+			       (aligned_rect.bottom - aligned_rect.top), 16, 0);
+		dma->afbcd_hreg_format =
+		    set_bits32(dma->afbcd_hreg_format, 0x1, 1, 0);
+		dma->afbcd_hreg_format =
+		    set_bits32(dma->afbcd_hreg_format,
+			       (isYUVPackage(layer->img.format) ? 0x0 : 0x1), 1,
+			       21);
+		dma->afbcd_ctl =
+		    set_bits32(dma->afbcd_ctl, afbcd_half_block_mode, 2, 6);
+		dma->afbcd_str =
+		    set_bits32(dma->afbcd_str,
+			       (afbcd_stretch_acc << 8 | afbcd_stretch_inc), 12,
+			       0);
+		dma->afbcd_line_crop =
+		    set_bits32(dma->afbcd_line_crop,
+			       (afbcd_top_crop_num << 4 |
+				afbcd_bottom_crop_num), 8, 0);
+		dma->afbcd_hreg_hdr_ptr_lo =
+		    set_bits32(dma->afbcd_hreg_hdr_ptr_lo, afbc_header_addr, 32,
+			       0);
+		dma->afbcd_input_header_stride =
+		    set_bits32(dma->afbcd_input_header_stride,
+			       (afbc_header_start_pos << 14) |
+			       afbc_header_stride, 16, 0);
+		dma->afbcd_payload_stride =
+		    set_bits32(dma->afbcd_payload_stride, afbc_payload_stride,
+			       20, 0);
+		dma->afbcd_mm_base_0 =
+		    set_bits32(dma->afbcd_mm_base_0, mm_base_0, 32, 0);
+		dma->afbcd_afbcd_payload_pointer =
+		    set_bits32(dma->afbcd_afbcd_payload_pointer,
+			       afbc_payload_addr, 32, 0);
+		dma->afbcd_height_bf_str =
+		    set_bits32(dma->afbcd_height_bf_str,
+			       DSS_HEIGHT(afbcd_height_bf_str), 16, 0);
+		dma->afbcd_header_pointer_offset =
+		    set_bits32(dma->afbcd_header_pointer_offset,
+			       afbc_header_pointer_offset, 32, 0);
+		dma->afbcd_scramble_mode =
+		    set_bits32(dma->afbcd_scramble_mode,
+			       layer->img.afbc_scramble_mode, 2, 0);
+
+		return 0;
+	}
+
+	rdma_addr = mmu_enable ? layer->img.vir_addr : layer->img.phy_addr;
+	if (rdma_addr & (DMA_ADDR_ALIGN - 1)) {
+		HISI_FB_ERR
+		    ("layer%d rdma_addr(0x%x) is not %d bytes aligned.\n",
+		     layer->layer_idx, rdma_addr, DMA_ADDR_ALIGN);
+		return -EINVAL;
+	}
+
+	if (layer->img.stride & (DMA_STRIDE_ALIGN - 1)) {
+		HISI_FB_ERR("layer%d stride(0x%x) is not %d bytes aligned.\n",
+			    layer->layer_idx, layer->img.stride,
+			    DMA_STRIDE_ALIGN);
+		return -EINVAL;
+	}
+
+	if (layer->need_cap & CAP_TILE) {
+		l2t_interleave_n =
+		    hisi_get_rdma_tile_interleave(layer->img.stride);
+		if (l2t_interleave_n < MIN_INTERLEAVE) {
+			HISI_FB_ERR
+			    ("tile stride should be 256*2^n, error stride:%d!\n",
+			     layer->img.stride);
+			return -EINVAL;
+		}
+
+		if (rdma_addr & (TILE_DMA_ADDR_ALIGN - 1)) {
+			HISI_FB_ERR
+			    ("layer%d tile rdma_addr(0x%x) is not %d bytes aligned.\n",
+			     layer->layer_idx, rdma_addr, TILE_DMA_ADDR_ALIGN);
+			return -EINVAL;
+		}
+	}
+
+	if (is_YUV_P_420(layer->img.format) || is_YUV_P_422(layer->img.format)) {
+		aligned_rect.left =
+		    ALIGN_DOWN(new_src_rect.x, 2 * aligned_pixel);
+		aligned_rect.right =
+		    ALIGN_UP(new_src_rect.x + new_src_rect.w,
+			     2 * aligned_pixel) - 1;
+	} else {
+		aligned_rect.left = ALIGN_DOWN(new_src_rect.x, aligned_pixel);
+		aligned_rect.right =
+		    ALIGN_UP(new_src_rect.x + new_src_rect.w,
+			     aligned_pixel) - 1;
+	}
+
+	if (is_YUV_SP_420(layer->img.format) || is_YUV_P_420(layer->img.format)) {
+		aligned_rect.top = ALIGN_DOWN(new_src_rect.y, 2);
+		aligned_rect.bottom =
+		    ALIGN_UP(new_src_rect.y + new_src_rect.h, 2) - 1;
+	} else {
+		aligned_rect.top = new_src_rect.y;
+		aligned_rect.bottom =
+		    DSS_HEIGHT(new_src_rect.y + new_src_rect.h);
+	}
+
+	if (src_rect_mask_enable) {
+		if (is_YUV_P_420(layer->img.format)
+		    || is_YUV_P_422(layer->img.format)) {
+			aligned_mask_rect.left =
+			    ALIGN_UP(layer->src_rect_mask.x, 2 * aligned_pixel);
+			aligned_mask_rect.right =
+			    ALIGN_DOWN(layer->src_rect_mask.x +
+				       layer->src_rect_mask.w,
+				       2 * aligned_pixel) - 1;
+		} else {
+			aligned_mask_rect.left =
+			    ALIGN_UP(layer->src_rect_mask.x, aligned_pixel);
+			aligned_mask_rect.right =
+			    ALIGN_DOWN(layer->src_rect_mask.x +
+				       layer->src_rect_mask.w,
+				       aligned_pixel) - 1;
+		}
+
+		if (is_YUV_SP_420(layer->img.format)
+		    || is_YUV_P_420(layer->img.format)) {
+			aligned_mask_rect.top =
+			    ALIGN_UP(layer->src_rect_mask.y, 2);
+			aligned_mask_rect.bottom =
+			    ALIGN_DOWN(layer->src_rect_mask.y +
+				       layer->src_rect_mask.h, 2) - 1;
+		} else {
+			aligned_mask_rect.top = layer->src_rect_mask.y;
+			aligned_mask_rect.bottom =
+			    DSS_HEIGHT(layer->src_rect_mask.y +
+				       layer->src_rect_mask.h);
+		}
+	}
+
+	out_aligned_rect->x = 0;
+	out_aligned_rect->y = 0;
+	out_aligned_rect->w = aligned_rect.right - aligned_rect.left + 1;
+	out_aligned_rect->h = aligned_rect.bottom - aligned_rect.top + 1;
+	if (stretched_line_num > 0) {
+		stretch_size_vrt = (out_aligned_rect->h / stretched_line_num) +
+		    ((out_aligned_rect->h % stretched_line_num) ? 1 : 0) - 1;
+
+		out_aligned_rect->h = stretch_size_vrt + 1;
+	} else {
+		stretch_size_vrt = 0x0;
+	}
+
+	clip_rect->left = new_src_rect.x - aligned_rect.left;
+	clip_rect->right =
+	    aligned_rect.right - DSS_WIDTH(new_src_rect.x + new_src_rect.w);
+	clip_rect->top = new_src_rect.y - aligned_rect.top;
+	clip_rect->bottom =
+	    aligned_rect.bottom - DSS_HEIGHT(new_src_rect.y + new_src_rect.h);
+
+	if (hisi_adjust_clip_rect(layer, clip_rect) < 0) {
+		HISI_FB_ERR
+		    ("clip rect invalid => layer_idx=%d, chn_idx=%d, "
+		     "clip_rect(%d, %d, %d, %d).\n",
+		     layer->layer_idx, chn_idx, clip_rect->left,
+		     clip_rect->right, clip_rect->top, clip_rect->bottom);
+		return -EINVAL;
+	}
+
+	rdma_oft_y0 = aligned_rect.top;
+	rdma_oft_y1 = aligned_rect.bottom;
+	rdma_oft_x0 = aligned_rect.left / aligned_pixel;
+	rdma_oft_x1 = aligned_rect.right / aligned_pixel;
+
+	if ((rdma_oft_x1 - rdma_oft_x0) < 0 ||
+	    (rdma_oft_x1 - rdma_oft_x0 + 1) > DMA_IN_WIDTH_MAX) {
+		HISI_FB_ERR
+		    ("out of range, rdma_oft_x0 = %d, rdma_oft_x1 = %d!\n",
+		     rdma_oft_x0, rdma_oft_x1);
+		return -EINVAL;
+	}
+
+	if ((rdma_oft_y1 - rdma_oft_y0) < 0 ||
+	    (rdma_oft_y1 - rdma_oft_y0 + 1) > DMA_IN_HEIGHT_MAX) {
+		HISI_FB_ERR
+		    ("out of range, rdma_oft_y0 = %d, rdma_oft_y1 = %d\n",
+		     rdma_oft_y0, rdma_oft_y1);
+		return -EINVAL;
+	}
+
+	rdma_addr =
+	    hisi_calculate_display_addr(mmu_enable, layer, &aligned_rect,
+					DSS_ADDR_PLANE0);
+	rdma_stride = layer->img.stride;
+	rdma_data_num =
+	    (rdma_oft_x1 - rdma_oft_x0 + 1) * (rdma_oft_y1 - rdma_oft_y0 + 1);
+
+	if (src_rect_mask_enable) {
+		rdma_mask_y0 = aligned_mask_rect.top;
+		rdma_mask_y1 = aligned_mask_rect.bottom;
+		rdma_mask_x0 = aligned_mask_rect.left / aligned_pixel;
+		rdma_mask_x1 = aligned_mask_rect.right / aligned_pixel;
+
+		if ((rdma_mask_x1 - rdma_mask_x0) > 2)
+			rdma_mask_x0 += 2;
+
+		if ((rdma_mask_x0 <= rdma_oft_x0)
+		    || (rdma_mask_x1 >= rdma_oft_x1)
+		    || (rdma_mask_y0 <= rdma_oft_y0)
+		    || (rdma_mask_y1 >= rdma_oft_y1)) {
+			src_rect_mask_enable = false;
+			rdma_mask_x0 = 0;
+			rdma_mask_y0 = 0;
+			rdma_mask_x1 = 0;
+			rdma_mask_y1 = 0;
+		}
+	}
+
+	if (stretched_line_num > 0) {
+		stretched_stride =
+		    stretched_line_num * rdma_stride / DMA_ALIGN_BYTES;
+		rdma_data_num =
+		    (stretch_size_vrt + 1) * (rdma_oft_x1 - rdma_oft_x0 + 1);
+	} else {
+		stretch_size_vrt = rdma_oft_y1 - rdma_oft_y0;
+		stretched_line_num = 0x0;
+		stretched_stride = 0x0;
+	}
+
+	dma->oft_x0 = set_bits32(dma->oft_x0, rdma_oft_x0, 16, 0);
+	dma->oft_y0 = set_bits32(dma->oft_y0, rdma_oft_y0, 16, 0);
+	dma->oft_x1 = set_bits32(dma->oft_x1, rdma_oft_x1, 16, 0);
+	dma->oft_y1 = set_bits32(dma->oft_y1, rdma_oft_y1, 16, 0);
+	dma->mask0 = set_bits32(dma->mask0,
+				(rdma_mask_y0 | (rdma_mask_x0 << 16)), 32, 0);
+	dma->mask1 = set_bits32(dma->mask1,
+				(rdma_mask_y1 | (rdma_mask_x1 << 16)), 32, 0);
+	dma->stretch_size_vrt = set_bits32(dma->stretch_size_vrt,
+					   (stretch_size_vrt |
+					    (stretched_line_num << 13)), 19, 0);
+	dma->ctrl =
+	    set_bits32(dma->ctrl, ((layer->need_cap & CAP_TILE) ? 0x1 : 0x0), 1,
+		       1);
+	dma->ctrl = set_bits32(dma->ctrl, rdma_format, 5, 3);
+	dma->ctrl = set_bits32(dma->ctrl, (mmu_enable ? 0x1 : 0x0), 1, 8);
+	dma->ctrl = set_bits32(dma->ctrl, rdma_transform, 3, 9);
+	dma->ctrl =
+	    set_bits32(dma->ctrl, ((stretched_line_num > 0) ? 0x1 : 0x0), 1,
+		       12);
+	dma->ctrl =
+	    set_bits32(dma->ctrl, (src_rect_mask_enable ? 0x1 : 0x0), 1, 17);
+	dma->tile_scram =
+	    set_bits32(dma->tile_scram,
+		       ((layer->need_cap & CAP_TILE) ? 0x1 : 0x0), 1, 0);
+	dma->ch_ctl = set_bits32(dma->ch_ctl, 0x1, 1, 0);
+
+	dma->data_addr0 = set_bits32(dma->data_addr0, rdma_addr, 32, 0);
+	dma->stride0 = set_bits32(dma->stride0,
+				  ((rdma_stride /
+				    DMA_ALIGN_BYTES) | (l2t_interleave_n <<
+							16)), 20, 0);
+	dma->stretch_stride0 =
+	    set_bits32(dma->stretch_stride0, stretched_stride, 19, 0);
+	dma->data_num0 = set_bits32(dma->data_num0, rdma_data_num, 30, 0);
+
+	if (is_yuv_semi_planar || is_yuv_planar) {
+		if (is_YUV_P_420(layer->img.format)
+		    || is_YUV_P_422(layer->img.format)) {
+			rdma_oft_x0 /= 2;
+			rdma_oft_x1 = (rdma_oft_x1 + 1) / 2 - 1;
+		}
+
+		if (is_YUV_SP_420(layer->img.format)
+		    || is_YUV_P_420(layer->img.format)) {
+			rdma_oft_y0 /= 2;
+			rdma_oft_y1 = (rdma_oft_y1 + 1) / 2 - 1;
+
+			stretched_line_num /= 2;
+		}
+
+		rdma_addr =
+		    hisi_calculate_display_addr(mmu_enable, layer,
+						&aligned_rect, DSS_ADDR_PLANE1);
+		rdma_stride = layer->img.stride_plane1;
+		rdma_data_num =
+		    (rdma_oft_x1 - rdma_oft_x0 + 1) * (rdma_oft_y1 -
+						       rdma_oft_y0 + 1) * 2;
+
+		if (*rdma_stretch_enable) {
+			stretched_stride =
+			    stretched_line_num * rdma_stride / DMA_ALIGN_BYTES;
+			rdma_data_num =
+			    (stretch_size_vrt + 1) * (rdma_oft_x1 -
+						      rdma_oft_x0 + 1) * 2;
+		} else {
+			stretch_size_vrt = 0;
+			stretched_line_num = 0;
+			stretched_stride = 0;
+		}
+
+		dma->data_addr1 = set_bits32(dma->data_addr1, rdma_addr, 32, 0);
+		dma->stride1 = set_bits32(dma->stride1,
+					  ((rdma_stride /
+					    DMA_ALIGN_BYTES) | (l2t_interleave_n << 16)), 20, 0);
+		dma->stretch_stride1 =
+		    set_bits32(dma->stretch_stride1, stretched_stride, 19, 0);
+		dma->data_num1 =
+		    set_bits32(dma->data_num1, rdma_data_num, 30, 0);
+
+		if (is_yuv_planar) {
+			rdma_addr =
+			    hisi_calculate_display_addr(mmu_enable, layer,
+							&aligned_rect,
+							DSS_ADDR_PLANE2);
+			rdma_stride = layer->img.stride_plane2;
+
+			dma->data_addr2 =
+			    set_bits32(dma->data_addr2, rdma_addr, 32, 0);
+			dma->stride2 =
+			    set_bits32(dma->stride2,
+				       ((rdma_stride /
+					     DMA_ALIGN_BYTES) | (l2t_interleave_n << 16)), 20, 0);
+			dma->stretch_stride2 =
+			    set_bits32(dma->stretch_stride1, stretched_stride,
+				       19, 0);
+			dma->data_num2 =
+			    set_bits32(dma->data_num1, rdma_data_num, 30, 0);
+		}
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+ ** DSS DFC
+ */
+static void hisi_dss_dfc_init(char __iomem *dfc_base, dss_dfc_t *s_dfc)
+{
+	BUG_ON(dfc_base == NULL);
+	BUG_ON(s_dfc == NULL);
+
+	memset(s_dfc, 0, sizeof(dss_dfc_t));
+
+	s_dfc->disp_size = inp32(dfc_base + DFC_DISP_SIZE);
+	s_dfc->pix_in_num = inp32(dfc_base + DFC_PIX_IN_NUM);
+	s_dfc->disp_fmt = inp32(dfc_base + DFC_DISP_FMT);
+	s_dfc->clip_ctl_hrz = inp32(dfc_base + DFC_CLIP_CTL_HRZ);
+	s_dfc->clip_ctl_vrz = inp32(dfc_base + DFC_CLIP_CTL_VRZ);
+	s_dfc->ctl_clip_en = inp32(dfc_base + DFC_CTL_CLIP_EN);
+	s_dfc->icg_module = inp32(dfc_base + DFC_ICG_MODULE);
+	s_dfc->dither_enable = inp32(dfc_base + DFC_DITHER_ENABLE);
+	s_dfc->padding_ctl = inp32(dfc_base + DFC_PADDING_CTL);
+}
+
+static void hisi_dss_dfc_set_reg(struct hisi_fb_data_type *hisifd,
+				 char __iomem *dfc_base, dss_dfc_t *s_dfc)
+{
+	BUG_ON(hisifd == NULL);
+	BUG_ON(dfc_base == NULL);
+	BUG_ON(s_dfc == NULL);
+
+	hisifd->set_reg(hisifd, dfc_base + DFC_DISP_SIZE, s_dfc->disp_size, 32,
+			0);
+	hisifd->set_reg(hisifd, dfc_base + DFC_PIX_IN_NUM, s_dfc->pix_in_num,
+			32, 0);
+	hisifd->set_reg(hisifd, dfc_base + DFC_DISP_FMT, s_dfc->disp_fmt, 32,
+			0);
+	hisifd->set_reg(hisifd, dfc_base + DFC_CLIP_CTL_HRZ,
+			s_dfc->clip_ctl_hrz, 32, 0);
+	hisifd->set_reg(hisifd, dfc_base + DFC_CLIP_CTL_VRZ,
+			s_dfc->clip_ctl_vrz, 32, 0);
+	hisifd->set_reg(hisifd, dfc_base + DFC_CTL_CLIP_EN, s_dfc->ctl_clip_en,
+			32, 0);
+	hisifd->set_reg(hisifd, dfc_base + DFC_ICG_MODULE, s_dfc->icg_module,
+			32, 0);
+	hisifd->set_reg(hisifd, dfc_base + DFC_DITHER_ENABLE,
+			s_dfc->dither_enable, 32, 0);
+	hisifd->set_reg(hisifd, dfc_base + DFC_PADDING_CTL, s_dfc->padding_ctl,
+			32, 0);
+}
+
+int hisi_dss_rdfc_config(struct hisi_fb_data_type *hisifd, dss_layer_t *layer,
+			 dss_rect_t *aligned_rect, dss_rect_ltrb_t clip_rect)
+{
+	dss_dfc_t *dfc = NULL;
+	int chn_idx = 0;
+	int dfc_fmt = 0;
+	int dfc_bpp = 0;
+	int dfc_pix_in_num = 0;
+	int dfc_aligned = 0;
+	int size_hrz = 0;
+	int size_vrt = 0;
+	int dfc_hrz_clip = 0;
+	bool need_clip = false;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(layer == NULL);
+
+	chn_idx = layer->chn_idx;
+
+	dfc = &(hisifd->dss_module.dfc[chn_idx]);
+	hisifd->dss_module.dfc_used[chn_idx] = 1;
+
+	dfc_fmt = hisi_pixel_format_hal2dfc(layer->img.format);
+	if (dfc_fmt < 0) {
+		HISI_FB_ERR("layer format (%d) not support !\n",
+			    layer->img.format);
+		return -EINVAL;
+	}
+
+	dfc_bpp = hisi_dfc_get_bpp(dfc_fmt);
+	if (dfc_bpp <= 0) {
+		HISI_FB_ERR("dfc_bpp(%d) not support !\n", dfc_bpp);
+		return -EINVAL;
+	}
+
+	dfc_pix_in_num = (dfc_bpp <= 2) ? 0x1 : 0x0;
+	dfc_aligned = (dfc_bpp <= 2) ? 4 : 2;
+
+	need_clip = isNeedRectClip(clip_rect);
+
+	size_hrz = DSS_WIDTH(aligned_rect->w);
+	size_vrt = DSS_HEIGHT(aligned_rect->h);
+
+	if (((size_hrz + 1) % dfc_aligned) != 0) {
+		size_hrz -= 1;
+		HISI_FB_ERR("SIZE_HRT=%d mismatch!bpp=%d\n", size_hrz,
+			    layer->img.bpp);
+
+		HISI_FB_ERR("layer_idx%d, format=%d, transform=%d, "
+			    "original_src_rect(%d,%d,%d,%d), rdma_out_rect(%d,%d,%d,%d), "
+			    "dst_rect(%d,%d,%d,%d)!\n",
+			    layer->layer_idx, layer->img.format,
+			    layer->transform, layer->src_rect.x,
+			    layer->src_rect.y, layer->src_rect.w,
+			    layer->src_rect.h, aligned_rect->x, aligned_rect->y,
+			    aligned_rect->w, aligned_rect->h, layer->dst_rect.x,
+			    layer->dst_rect.y, layer->dst_rect.w,
+			    layer->dst_rect.h);
+	}
+
+	dfc_hrz_clip = (size_hrz + 1) % dfc_aligned;
+	if (dfc_hrz_clip) {
+		clip_rect.right += dfc_hrz_clip;
+		size_hrz += dfc_hrz_clip;
+		need_clip = true;
+	}
+
+	dfc->disp_size =
+	    set_bits32(dfc->disp_size, (size_vrt | (size_hrz << 16)), 29, 0);
+	dfc->pix_in_num = set_bits32(dfc->pix_in_num, dfc_pix_in_num, 1, 0);
+	dfc->disp_fmt = set_bits32(dfc->disp_fmt,
+				   ((dfc_fmt << 1) |
+				    (hisi_uv_swap(layer->img.format) << 6) |
+				    (hisi_rb_swap(layer->img.format) << 7)), 8, 0);
+
+	if (need_clip) {
+		dfc->clip_ctl_hrz = set_bits32(dfc->clip_ctl_hrz,
+					       (clip_rect.right | (clip_rect.left << 16)),
+					       32, 0);
+		dfc->clip_ctl_vrz =
+		    set_bits32(dfc->clip_ctl_vrz,
+			       (clip_rect.bottom | (clip_rect.top << 16)), 32, 0);
+		dfc->ctl_clip_en = set_bits32(dfc->ctl_clip_en, 0x1, 1, 0);
+	} else {
+		dfc->clip_ctl_hrz = set_bits32(dfc->clip_ctl_hrz, 0x0, 32, 0);
+		dfc->clip_ctl_vrz = set_bits32(dfc->clip_ctl_vrz, 0x0, 32, 0);
+		dfc->ctl_clip_en = set_bits32(dfc->ctl_clip_en, 0x1, 1, 0);
+	}
+	dfc->icg_module = set_bits32(dfc->icg_module, 0x1, 1, 0);
+	dfc->dither_enable = set_bits32(dfc->dither_enable, 0x0, 1, 0);
+	dfc->padding_ctl = set_bits32(dfc->padding_ctl, 0x0, 17, 0);
+
+	if (need_clip) {
+		aligned_rect->w -= (clip_rect.left + clip_rect.right);
+		aligned_rect->h -= (clip_rect.top + clip_rect.bottom);
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+ ** DSS SCF
+ */
+
+/* Filter coefficients for SCF */
+#define PHASE_NUM	(66)
+#define TAP4	(4)
+#define TAP5	(5)
+#define TAP6	(6)
+#define COEF_LUT_NUM	(2)
+
+static const int COEF_LUT_TAP4[SCL_COEF_IDX_MAX][PHASE_NUM][TAP4] = {
+	/* YUV_COEF_IDX */
+	{
+	 {214, 599, 214, -3},
+	 {207, 597, 223, -3},
+	 {200, 596, 231, -3},
+	 {193, 596, 238, -3},
+	 {186, 595, 246, -3},
+	 {178, 594, 255, -3},
+	 {171, 593, 263, -3},
+	 {165, 591, 271, -3},
+	 {158, 589, 279, -2},
+	 {151, 587, 288, -2},
+	 {145, 584, 296, -1},
+	 {139, 582, 304, -1},
+	 {133, 578, 312, 1},
+	 {127, 575, 321, 1},
+	 {121, 572, 329, 2},
+	 {115, 568, 337, 4},
+	 {109, 564, 346, 5},
+	 {104, 560, 354, 6},
+	 {98, 555, 362, 9},
+	 {94, 550, 370, 10},
+	 {88, 546, 379, 11},
+	 {84, 540, 387, 13},
+	 {79, 535, 395, 15},
+	 {74, 530, 403, 17},
+	 {70, 524, 411, 19},
+	 {66, 518, 419, 21},
+	 {62, 512, 427, 23},
+	 {57, 506, 435, 26},
+	 {54, 499, 443, 28},
+	 {50, 492, 451, 31},
+	 {47, 486, 457, 34},
+	 {43, 479, 465, 37},
+	 {40, 472, 472, 40},
+	 {214, 599, 214, -3},
+	 {207, 597, 223, -3},
+	 {200, 596, 231, -3},
+	 {193, 596, 238, -3},
+	 {186, 595, 246, -3},
+	 {178, 594, 255, -3},
+	 {171, 593, 263, -3},
+	 {165, 591, 271, -3},
+	 {158, 589, 279, -2},
+	 {151, 587, 288, -2},
+	 {145, 584, 296, -1},
+	 {139, 582, 304, -1},
+	 {133, 578, 312, 1},
+	 {127, 575, 321, 1},
+	 {121, 572, 329, 2},
+	 {115, 568, 337, 4},
+	 {109, 564, 346, 5},
+	 {104, 560, 354, 6},
+	 {98, 555, 362, 9},
+	 {94, 550, 370, 10},
+	 {88, 546, 379, 11},
+	 {84, 540, 387, 13},
+	 {79, 535, 395, 15},
+	 {74, 530, 403, 17},
+	 {70, 524, 411, 19},
+	 {66, 518, 419, 21},
+	 {62, 512, 427, 23},
+	 {57, 506, 435, 26},
+	 {54, 499, 443, 28},
+	 {50, 492, 451, 31},
+	 {47, 486, 457, 34},
+	 {43, 479, 465, 37},
+	 {40, 472, 472, 40}
+	 },
+
+	/* RGB_COEF_IDX */
+	{
+	 {0, 1024, 0, 0},
+	 {0, 1008, 16, 0},
+	 {0, 992, 32, 0},
+	 {0, 976, 48, 0},
+	 {0, 960, 64, 0},
+	 {0, 944, 80, 0},
+	 {0, 928, 96, 0},
+	 {0, 912, 112, 0},
+	 {0, 896, 128, 0},
+	 {0, 880, 144, 0},
+	 {0, 864, 160, 0},
+	 {0, 848, 176, 0},
+	 {0, 832, 192, 0},
+	 {0, 816, 208, 0},
+	 {0, 800, 224, 0},
+	 {0, 784, 240, 0},
+	 {0, 768, 256, 0},
+	 {0, 752, 272, 0},
+	 {0, 736, 288, 0},
+	 {0, 720, 304, 0},
+	 {0, 704, 320, 0},
+	 {0, 688, 336, 0},
+	 {0, 672, 352, 0},
+	 {0, 656, 368, 0},
+	 {0, 640, 384, 0},
+	 {0, 624, 400, 0},
+	 {0, 608, 416, 0},
+	 {0, 592, 432, 0},
+	 {0, 576, 448, 0},
+	 {0, 560, 464, 0},
+	 {0, 544, 480, 0},
+	 {0, 528, 496, 0},
+	 {0, 512, 512, 0},
+	 {0, 1024, 0, 0},
+	 {0, 1008, 16, 0},
+	 {0, 992, 32, 0},
+	 {0, 976, 48, 0},
+	 {0, 960, 64, 0},
+	 {0, 944, 80, 0},
+	 {0, 928, 96, 0},
+	 {0, 912, 112, 0},
+	 {0, 896, 128, 0},
+	 {0, 880, 144, 0},
+	 {0, 864, 160, 0},
+	 {0, 848, 176, 0},
+	 {0, 832, 192, 0},
+	 {0, 816, 208, 0},
+	 {0, 800, 224, 0},
+	 {0, 784, 240, 0},
+	 {0, 768, 256, 0},
+	 {0, 752, 272, 0},
+	 {0, 736, 288, 0},
+	 {0, 720, 304, 0},
+	 {0, 704, 320, 0},
+	 {0, 688, 336, 0},
+	 {0, 672, 352, 0},
+	 {0, 656, 368, 0},
+	 {0, 640, 384, 0},
+	 {0, 624, 400, 0},
+	 {0, 608, 416, 0},
+	 {0, 592, 432, 0},
+	 {0, 576, 448, 0},
+	 {0, 560, 464, 0},
+	 {0, 544, 480, 0},
+	 {0, 528, 496, 0},
+	 {0, 512, 512, 0}
+	 }
+};
+
+static const int COEF_LUT_TAP5[SCL_COEF_IDX_MAX][PHASE_NUM][TAP5] = {
+	/* YUV_COEF_IDX */
+	{
+	 {98, 415, 415, 98, -2},
+	 {95, 412, 418, 103, -4},
+	 {91, 408, 422, 107, -4},
+	 {87, 404, 426, 111, -4},
+	 {84, 399, 430, 115, -4},
+	 {80, 395, 434, 119, -4},
+	 {76, 390, 438, 124, -4},
+	 {73, 386, 440, 128, -3},
+	 {70, 381, 444, 132, -3},
+	 {66, 376, 448, 137, -3},
+	 {63, 371, 451, 142, -3},
+	 {60, 366, 455, 146, -3},
+	 {57, 361, 457, 151, -2},
+	 {54, 356, 460, 156, -2},
+	 {51, 351, 463, 161, -2},
+	 {49, 346, 465, 165, -1},
+	 {46, 341, 468, 170, -1},
+	 {43, 336, 470, 175, 0},
+	 {41, 331, 472, 180, 0},
+	 {38, 325, 474, 186, 1},
+	 {36, 320, 476, 191, 1},
+	 {34, 315, 477, 196, 2},
+	 {32, 309, 479, 201, 3},
+	 {29, 304, 481, 206, 4},
+	 {27, 299, 481, 212, 5},
+	 {26, 293, 482, 217, 6},
+	 {24, 288, 484, 222, 6},
+	 {22, 282, 484, 228, 8},
+	 {20, 277, 485, 233, 9},
+	 {19, 271, 485, 238, 11},
+	 {17, 266, 485, 244, 12},
+	 {16, 260, 485, 250, 13},
+	 {14, 255, 486, 255, 14},
+	 {-94, 608, 608, -94, -4},
+	 {-94, 594, 619, -91, -4},
+	 {-96, 579, 635, -89, -5},
+	 {-96, 563, 650, -87, -6},
+	 {-97, 548, 665, -85, -7},
+	 {-97, 532, 678, -82, -7},
+	 {-98, 516, 693, -79, -8},
+	 {-97, 500, 705, -75, -9},
+	 {-97, 484, 720, -72, -11},
+	 {-97, 468, 733, -68, -12},
+	 {-96, 452, 744, -63, -13},
+	 {-95, 436, 755, -58, -14},
+	 {-94, 419, 768, -53, -16},
+	 {-93, 403, 779, -48, -17},
+	 {-92, 387, 789, -42, -18},
+	 {-90, 371, 799, -36, -20},
+	 {-89, 355, 809, -29, -22},
+	 {-87, 339, 817, -22, -23},
+	 {-86, 324, 826, -15, -25},
+	 {-84, 308, 835, -8, -27},
+	 {-82, 293, 842, 0, -29},
+	 {-80, 277, 849, 9, -31},
+	 {-78, 262, 855, 18, -33},
+	 {-75, 247, 860, 27, -35},
+	 {-73, 233, 865, 36, -37},
+	 {-71, 218, 870, 46, -39},
+	 {-69, 204, 874, 56, -41},
+	 {-66, 190, 876, 67, -43},
+	 {-64, 176, 879, 78, -45},
+	 {-62, 163, 882, 89, -48},
+	 {-59, 150, 883, 100, -50},
+	 {-57, 137, 883, 112, -51},
+	 {-55, 125, 884, 125, -55}
+	 },
+
+	/* RGB_COEF_IDX */
+	{
+	 {0, 512, 512, 0, 0},
+	 {0, 496, 528, 0, 0},
+	 {0, 480, 544, 0, 0},
+	 {0, 464, 560, 0, 0},
+	 {0, 448, 576, 0, 0},
+	 {0, 432, 592, 0, 0},
+	 {0, 416, 608, 0, 0},
+	 {0, 400, 624, 0, 0},
+	 {0, 384, 640, 0, 0},
+	 {0, 368, 656, 0, 0},
+	 {0, 352, 672, 0, 0},
+	 {0, 336, 688, 0, 0},
+	 {0, 320, 704, 0, 0},
+	 {0, 304, 720, 0, 0},
+	 {0, 288, 736, 0, 0},
+	 {0, 272, 752, 0, 0},
+	 {0, 256, 768, 0, 0},
+	 {0, 240, 784, 0, 0},
+	 {0, 224, 800, 0, 0},
+	 {0, 208, 816, 0, 0},
+	 {0, 192, 832, 0, 0},
+	 {0, 176, 848, 0, 0},
+	 {0, 160, 864, 0, 0},
+	 {0, 144, 880, 0, 0},
+	 {0, 128, 896, 0, 0},
+	 {0, 112, 912, 0, 0},
+	 {0, 96, 928, 0, 0},
+	 {0, 80, 944, 0, 0},
+	 {0, 64, 960, 0, 0},
+	 {0, 48, 976, 0, 0},
+	 {0, 32, 992, 0, 0},
+	 {0, 16, 1008, 0, 0},
+	 {0, 0, 1024, 0, 0},
+	 {0, 512, 512, 0, 0},
+	 {0, 496, 528, 0, 0},
+	 {0, 480, 544, 0, 0},
+	 {0, 464, 560, 0, 0},
+	 {0, 448, 576, 0, 0},
+	 {0, 432, 592, 0, 0},
+	 {0, 416, 608, 0, 0},
+	 {0, 400, 624, 0, 0},
+	 {0, 384, 640, 0, 0},
+	 {0, 368, 656, 0, 0},
+	 {0, 352, 672, 0, 0},
+	 {0, 336, 688, 0, 0},
+	 {0, 320, 704, 0, 0},
+	 {0, 304, 720, 0, 0},
+	 {0, 288, 736, 0, 0},
+	 {0, 272, 752, 0, 0},
+	 {0, 256, 768, 0, 0},
+	 {0, 240, 784, 0, 0},
+	 {0, 224, 800, 0, 0},
+	 {0, 208, 816, 0, 0},
+	 {0, 192, 832, 0, 0},
+	 {0, 176, 848, 0, 0},
+	 {0, 160, 864, 0, 0},
+	 {0, 144, 880, 0, 0},
+	 {0, 128, 896, 0, 0},
+	 {0, 112, 912, 0, 0},
+	 {0, 96, 928, 0, 0},
+	 {0, 80, 944, 0, 0},
+	 {0, 64, 960, 0, 0},
+	 {0, 48, 976, 0, 0},
+	 {0, 32, 992, 0, 0},
+	 {0, 16, 1008, 0, 0},
+	 {0, 0, 1024, 0, 0}
+	 }
+};
+
+static const int COEF_LUT_TAP6[SCL_COEF_IDX_MAX][PHASE_NUM][TAP6] = {
+	/* YUV_COEF_IDX */
+	{
+	 {2, 264, 500, 264, 2, -8},
+	 {2, 257, 499, 268, 6, -8},
+	 {1, 252, 498, 274, 8, -9},
+	 {-1, 246, 498, 281, 9, -9},
+	 {-2, 241, 497, 286, 12, -10},
+	 {-3, 235, 497, 292, 13, -10},
+	 {-5, 230, 496, 298, 15, -10},
+	 {-6, 225, 495, 303, 18, -11},
+	 {-7, 219, 494, 309, 20, -11},
+	 {-7, 213, 493, 314, 23, -12},
+	 {-9, 208, 491, 320, 26, -12},
+	 {-10, 203, 490, 325, 28, -12},
+	 {-10, 197, 488, 331, 31, -13},
+	 {-10, 192, 486, 336, 33, -13},
+	 {-12, 186, 485, 342, 36, -13},
+	 {-12, 181, 482, 347, 39, -13},
+	 {-13, 176, 480, 352, 42, -13},
+	 {-14, 171, 478, 358, 45, -14},
+	 {-14, 166, 476, 363, 48, -15},
+	 {-14, 160, 473, 368, 52, -15},
+	 {-14, 155, 470, 373, 55, -15},
+	 {-15, 150, 467, 378, 59, -15},
+	 {-15, 145, 464, 383, 62, -15},
+	 {-16, 141, 461, 388, 65, -15},
+	 {-16, 136, 458, 393, 68, -15},
+	 {-16, 131, 455, 398, 72, -16},
+	 {-16, 126, 451, 402, 77, -16},
+	 {-16, 122, 448, 407, 79, -16},
+	 {-16, 117, 444, 411, 84, -16},
+	 {-17, 113, 441, 416, 87, -16},
+	 {-17, 108, 437, 420, 92, -16},
+	 {-17, 104, 433, 424, 96, -16},
+	 {-17, 100, 429, 429, 100, -17},
+	 {-187, 105, 1186, 105, -187, 2},
+	 {-182, 86, 1186, 124, -192, 2},
+	 {-176, 67, 1185, 143, -197, 2},
+	 {-170, 49, 1182, 163, -202, 2},
+	 {-166, 32, 1180, 184, -207, 1},
+	 {-160, 15, 1176, 204, -212, 1},
+	 {-155, -2, 1171, 225, -216, 1},
+	 {-149, -18, 1166, 246, -221, 0},
+	 {-145, -34, 1160, 268, -225, 0},
+	 {-139, -49, 1153, 290, -230, -1},
+	 {-134, -63, 1145, 312, -234, -2},
+	 {-129, -78, 1137, 334, -238, -2},
+	 {-124, -91, 1128, 357, -241, -5},
+	 {-119, -104, 1118, 379, -245, -5},
+	 {-114, -117, 1107, 402, -248, -6},
+	 {-109, -129, 1096, 425, -251, -8},
+	 {-104, -141, 1083, 448, -254, -8},
+	 {-100, -152, 1071, 471, -257, -9},
+	 {-95, -162, 1057, 494, -259, -11},
+	 {-90, -172, 1043, 517, -261, -13},
+	 {-86, -181, 1028, 540, -263, -14},
+	 {-82, -190, 1013, 563, -264, -16},
+	 {-77, -199, 997, 586, -265, -18},
+	 {-73, -207, 980, 609, -266, -19},
+	 {-69, -214, 963, 632, -266, -22},
+	 {-65, -221, 945, 655, -266, -24},
+	 {-62, -227, 927, 678, -266, -26},
+	 {-58, -233, 908, 700, -265, -28},
+	 {-54, -238, 889, 722, -264, -31},
+	 {-51, -243, 870, 744, -262, -34},
+	 {-48, -247, 850, 766, -260, -37},
+	 {-45, -251, 829, 787, -257, -39},
+	 {-42, -255, 809, 809, -255, -42}
+	 },
+
+	/* RGB_COEF_IDX */
+	{
+	 {0, 0, 1024, 0, 0, 0},
+	 {0, 0, 1008, 16, 0, 0},
+	 {0, 0, 992, 32, 0, 0},
+	 {0, 0, 976, 48, 0, 0},
+	 {0, 0, 960, 64, 0, 0},
+	 {0, 0, 944, 80, 0, 0},
+	 {0, 0, 928, 96, 0, 0},
+	 {0, 0, 912, 112, 0, 0},
+	 {0, 0, 896, 128, 0, 0},
+	 {0, 0, 880, 144, 0, 0},
+	 {0, 0, 864, 160, 0, 0},
+	 {0, 0, 848, 176, 0, 0},
+	 {0, 0, 832, 192, 0, 0},
+	 {0, 0, 816, 208, 0, 0},
+	 {0, 0, 800, 224, 0, 0},
+	 {0, 0, 784, 240, 0, 0},
+	 {0, 0, 768, 256, 0, 0},
+	 {0, 0, 752, 272, 0, 0},
+	 {0, 0, 736, 288, 0, 0},
+	 {0, 0, 720, 304, 0, 0},
+	 {0, 0, 704, 320, 0, 0},
+	 {0, 0, 688, 336, 0, 0},
+	 {0, 0, 672, 352, 0, 0},
+	 {0, 0, 656, 368, 0, 0},
+	 {0, 0, 640, 384, 0, 0},
+	 {0, 0, 624, 400, 0, 0},
+	 {0, 0, 608, 416, 0, 0},
+	 {0, 0, 592, 432, 0, 0},
+	 {0, 0, 576, 448, 0, 0},
+	 {0, 0, 560, 464, 0, 0},
+	 {0, 0, 544, 480, 0, 0},
+	 {0, 0, 528, 496, 0, 0},
+	 {0, 0, 512, 512, 0, 0},
+	 {0, 0, 1024, 0, 0, 0},
+	 {0, 0, 1008, 16, 0, 0},
+	 {0, 0, 992, 32, 0, 0},
+	 {0, 0, 976, 48, 0, 0},
+	 {0, 0, 960, 64, 0, 0},
+	 {0, 0, 944, 80, 0, 0},
+	 {0, 0, 928, 96, 0, 0},
+	 {0, 0, 912, 112, 0, 0},
+	 {0, 0, 896, 128, 0, 0},
+	 {0, 0, 880, 144, 0, 0},
+	 {0, 0, 864, 160, 0, 0},
+	 {0, 0, 848, 176, 0, 0},
+	 {0, 0, 832, 192, 0, 0},
+	 {0, 0, 816, 208, 0, 0},
+	 {0, 0, 800, 224, 0, 0},
+	 {0, 0, 784, 240, 0, 0},
+	 {0, 0, 768, 256, 0, 0},
+	 {0, 0, 752, 272, 0, 0},
+	 {0, 0, 736, 288, 0, 0},
+	 {0, 0, 720, 304, 0, 0},
+	 {0, 0, 704, 320, 0, 0},
+	 {0, 0, 688, 336, 0, 0},
+	 {0, 0, 672, 352, 0, 0},
+	 {0, 0, 656, 368, 0, 0},
+	 {0, 0, 640, 384, 0, 0},
+	 {0, 0, 624, 400, 0, 0},
+	 {0, 0, 608, 416, 0, 0},
+	 {0, 0, 592, 432, 0, 0},
+	 {0, 0, 576, 448, 0, 0},
+	 {0, 0, 560, 464, 0, 0},
+	 {0, 0, 544, 480, 0, 0},
+	 {0, 0, 528, 496, 0, 0},
+	 {0, 0, 512, 512, 0, 0}
+	 }
+};
+
+static void hisi_dss_scl_init(char __iomem *scl_base, dss_scl_t *s_scl)
+{
+	BUG_ON(scl_base == NULL);
+	BUG_ON(s_scl == NULL);
+
+	memset(s_scl, 0, sizeof(dss_scl_t));
+
+	s_scl->en_hscl_str = inp32(scl_base + SCF_EN_HSCL_STR);
+	s_scl->en_vscl_str = inp32(scl_base + SCF_EN_VSCL_STR);
+	s_scl->h_v_order = inp32(scl_base + SCF_H_V_ORDER);
+	s_scl->input_width_height = inp32(scl_base + SCF_INPUT_WIDTH_HEIGHT);
+	s_scl->output_width_height = inp32(scl_base + SCF_OUTPUT_WIDTH_HEIGHT);
+	s_scl->en_hscl = inp32(scl_base + SCF_EN_HSCL);
+	s_scl->en_vscl = inp32(scl_base + SCF_EN_VSCL);
+	s_scl->acc_hscl = inp32(scl_base + SCF_ACC_HSCL);
+	s_scl->inc_hscl = inp32(scl_base + SCF_INC_HSCL);
+	s_scl->inc_vscl = inp32(scl_base + SCF_INC_VSCL);
+	s_scl->en_mmp = inp32(scl_base + SCF_EN_MMP);
+}
+
+void hisi_dss_scl_set_reg(struct hisi_fb_data_type *hisifd,
+			  char __iomem *scl_base, dss_scl_t *s_scl)
+{
+	BUG_ON(scl_base == NULL);
+	BUG_ON(s_scl == NULL);
+
+	if (hisifd) {
+		hisifd->set_reg(hisifd, scl_base + SCF_EN_HSCL_STR,
+				s_scl->en_hscl_str, 32, 0);
+		hisifd->set_reg(hisifd, scl_base + SCF_EN_VSCL_STR,
+				s_scl->en_vscl_str, 32, 0);
+		hisifd->set_reg(hisifd, scl_base + SCF_H_V_ORDER,
+				s_scl->h_v_order, 32, 0);
+		hisifd->set_reg(hisifd, scl_base + SCF_INPUT_WIDTH_HEIGHT,
+				s_scl->input_width_height, 32, 0);
+		hisifd->set_reg(hisifd, scl_base + SCF_OUTPUT_WIDTH_HEIGHT,
+				s_scl->output_width_height, 32, 0);
+		hisifd->set_reg(hisifd, scl_base + SCF_EN_HSCL,
+				s_scl->en_hscl, 32, 0);
+		hisifd->set_reg(hisifd, scl_base + SCF_EN_VSCL,
+				s_scl->en_vscl, 32, 0);
+		hisifd->set_reg(hisifd, scl_base + SCF_ACC_HSCL,
+				s_scl->acc_hscl, 32, 0);
+		hisifd->set_reg(hisifd, scl_base + SCF_INC_HSCL,
+				s_scl->inc_hscl, 32, 0);
+		hisifd->set_reg(hisifd, scl_base + SCF_INC_VSCL,
+				s_scl->inc_vscl, 32, 0);
+		hisifd->set_reg(hisifd, scl_base + SCF_EN_MMP,
+				s_scl->en_mmp, 32, 0);
+	} else {
+		set_reg(scl_base + SCF_EN_HSCL_STR, s_scl->en_hscl_str, 32, 0);
+		set_reg(scl_base + SCF_EN_VSCL_STR, s_scl->en_vscl_str, 32, 0);
+		set_reg(scl_base + SCF_H_V_ORDER, s_scl->h_v_order, 32, 0);
+		set_reg(scl_base + SCF_INPUT_WIDTH_HEIGHT,
+			s_scl->input_width_height, 32, 0);
+		set_reg(scl_base + SCF_OUTPUT_WIDTH_HEIGHT,
+			s_scl->output_width_height, 32, 0);
+		set_reg(scl_base + SCF_EN_HSCL, s_scl->en_hscl, 32, 0);
+		set_reg(scl_base + SCF_EN_VSCL, s_scl->en_vscl, 32, 0);
+		set_reg(scl_base + SCF_ACC_HSCL, s_scl->acc_hscl, 32, 0);
+		set_reg(scl_base + SCF_INC_HSCL, s_scl->inc_hscl, 32, 0);
+		set_reg(scl_base + SCF_INC_VSCL, s_scl->inc_vscl, 32, 0);
+		set_reg(scl_base + SCF_EN_MMP, s_scl->en_mmp, 32, 0);
+	}
+}
+
+int hisi_dss_scl_write_coefs(struct hisi_fb_data_type *hisifd,
+			     bool enable_cmdlist, char __iomem *addr,
+			     const int **p, int row, int col)
+{
+	int groups[3] = { 0 };
+	int offset = 0;
+	int valid_num = 0;
+	int i = 0;
+	int j = 0;
+	int k = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(addr == NULL);
+
+	if ((row != PHASE_NUM) || (col < TAP4 || col > TAP6)) {
+		HISI_FB_ERR
+		    ("SCF filter coefficients is err, phase_num = %d, tap_num = %d\n",
+		     row, col);
+		return -EINVAL;
+	}
+
+	/*byte */
+	offset = (col == TAP4) ? 8 : 16;
+	valid_num = (offset == 16) ? 3 : 2;
+
+	for (i = 0; i < row; i++) {
+		for (j = 0; j < col; j += 2) {
+			if ((col % 2) && (j == col - 1)) {
+				groups[j / 2] =
+				    (*((int *)p + i * col + j) & 0xFFF) | (0 <<
+									   16);
+			} else {
+				groups[j / 2] =
+				    (*((int *)p + i * col + j) & 0xFFF) |
+				    (*((int *)p + i * col + j + 1) << 16);
+			}
+		}
+
+		for (k = 0; k < valid_num; k++) {
+			if (enable_cmdlist) {
+				hisifd->set_reg(hisifd,
+						addr + offset * i +
+						k * sizeof(int), groups[k], 32,
+						0);
+			} else {
+				set_reg(addr + offset * i + k * sizeof(int),
+					groups[k], 32, 0);
+			}
+			groups[k] = 0;
+		}
+	}
+
+	return 0;
+}
+
+int hisi_dss_chn_scl_load_filter_coef_set_reg(struct hisi_fb_data_type *hisifd,
+					      bool enable_cmdlist, int chn_idx,
+					      uint32_t format)
+{
+	uint32_t module_base = 0;
+	char __iomem *h0_y_addr = NULL;
+	char __iomem *y_addr = NULL;
+	char __iomem *uv_addr = NULL;
+	int ret = 0;
+	int chn_coef_idx = SCL_COEF_YUV_IDX;
+
+	BUG_ON(hisifd == NULL);
+	if ((chn_idx != DSS_RCHN_V0) && (chn_idx != DSS_RCHN_V1)
+	    && (chn_idx != DSS_RCHN_V2))
+		return 0;
+
+	if (isYUV(format)) {
+		chn_coef_idx = SCL_COEF_YUV_IDX;
+	} else {
+		chn_coef_idx = SCL_COEF_RGB_IDX;
+	}
+
+	if (g_scf_lut_chn_coef_idx[chn_idx] == chn_coef_idx)
+		return 0;
+
+	g_scf_lut_chn_coef_idx[chn_idx] = chn_coef_idx;
+
+	module_base = g_dss_module_base[chn_idx][MODULE_SCL_LUT];
+	BUG_ON(module_base == 0);
+
+	h0_y_addr = hisifd->dss_base + module_base + DSS_SCF_H0_Y_COEF_OFFSET;
+	y_addr = hisifd->dss_base + module_base + DSS_SCF_Y_COEF_OFFSET;
+	uv_addr = hisifd->dss_base + module_base + DSS_SCF_UV_COEF_OFFSET;
+
+	ret =
+	    hisi_dss_scl_write_coefs(hisifd, enable_cmdlist, h0_y_addr,
+				     (const int **)COEF_LUT_TAP6[chn_coef_idx],
+				     PHASE_NUM, TAP6);
+	if (ret < 0) {
+		HISI_FB_ERR("Error to write H0_Y_COEF coefficients.\n");
+	}
+
+	ret =
+	    hisi_dss_scl_write_coefs(hisifd, enable_cmdlist, y_addr,
+				     (const int **)COEF_LUT_TAP5[chn_coef_idx],
+				     PHASE_NUM, TAP5);
+	if (ret < 0) {
+		HISI_FB_ERR("Error to write Y_COEF coefficients.\n");
+	}
+
+	ret =
+	    hisi_dss_scl_write_coefs(hisifd, enable_cmdlist, uv_addr,
+				     (const int **)COEF_LUT_TAP4[chn_coef_idx],
+				     PHASE_NUM, TAP4);
+	if (ret < 0) {
+		HISI_FB_ERR("Error to write UV_COEF coefficients.\n");
+	}
+
+	return ret;
+}
+
+int hisi_dss_scl_coef_on(struct hisi_fb_data_type *hisifd, bool enable_cmdlist,
+			 int coef_lut_idx)
+{
+	int i = 0;
+	uint32_t module_base = 0;
+	char __iomem *h0_y_addr = NULL;
+	char __iomem *y_addr = NULL;
+	char __iomem *uv_addr = NULL;
+	int ret = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	for (i = 0; i < DSS_CHN_MAX_DEFINE; i++) {
+		module_base = g_dss_module_base[i][MODULE_SCL_LUT];
+		if (module_base != 0) {
+			h0_y_addr =
+			    hisifd->dss_base + module_base +
+			    DSS_SCF_H0_Y_COEF_OFFSET;
+			y_addr =
+			    hisifd->dss_base + module_base +
+			    DSS_SCF_Y_COEF_OFFSET;
+			uv_addr =
+			    hisifd->dss_base + module_base +
+			    DSS_SCF_UV_COEF_OFFSET;
+
+			g_scf_lut_chn_coef_idx[i] = coef_lut_idx;
+
+			ret =
+			    hisi_dss_scl_write_coefs(hisifd, enable_cmdlist,
+						     h0_y_addr,
+						     (const int **)
+						     COEF_LUT_TAP6
+						     [coef_lut_idx], PHASE_NUM,
+						     TAP6);
+			if (ret < 0) {
+				HISI_FB_ERR
+				    ("Error to write H0_Y_COEF coefficients.\n");
+			}
+
+			if (i == DSS_RCHN_V0) {
+				hisi_dss_arsr2p_coef_on(hisifd, enable_cmdlist);
+				continue;
+			}
+
+			ret =
+			    hisi_dss_scl_write_coefs(hisifd, enable_cmdlist, y_addr,
+						     (const int **)COEF_LUT_TAP5[coef_lut_idx],
+						     PHASE_NUM, TAP5);
+			if (ret < 0) {
+				HISI_FB_ERR
+				    ("Error to write Y_COEF coefficients.\n");
+			}
+
+			ret =
+			    hisi_dss_scl_write_coefs(hisifd, enable_cmdlist, uv_addr,
+						     (const int **)COEF_LUT_TAP4[coef_lut_idx],
+						     PHASE_NUM, TAP4);
+			if (ret < 0) {
+				HISI_FB_ERR
+				    ("Error to write UV_COEF coefficients.\n");
+			}
+		}
+	}
+
+	return 0;
+}
+
+int hisi_dss_scl_config(struct hisi_fb_data_type *hisifd,
+			dss_layer_t *layer, dss_rect_t *aligned_rect,
+			bool rdma_stretch_enable)
+{
+	dss_scl_t *scl = NULL;
+	dss_rect_t src_rect;
+	dss_rect_t dst_rect;
+	uint32_t need_cap = 0;
+	int chn_idx = 0;
+	uint32_t transform = 0;
+	dss_block_info_t *pblock_info = NULL;
+
+	bool has_pixel_alpha = false;
+	bool en_hscl = false;
+	bool en_vscl = false;
+	bool en_mmp = false;
+	uint32_t h_ratio = 0;
+	uint32_t v_ratio = 0;
+	uint32_t h_v_order = 0;
+	uint32_t acc_hscl = 0;
+	uint32_t acc_vscl = 0;
+	uint32_t scf_en_vscl = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(layer == NULL);
+
+	need_cap = layer->need_cap;
+	chn_idx = layer->chn_idx;
+	transform = layer->transform;
+	if (aligned_rect)
+		src_rect = *aligned_rect;
+	else
+		src_rect = layer->src_rect;
+	dst_rect = layer->dst_rect;
+	pblock_info = &(layer->block_info);
+
+	if (pblock_info && pblock_info->both_vscfh_arsr2p_used) {
+		dst_rect = pblock_info->arsr2p_in_rect;
+	}
+
+	if (chn_idx == DSS_RCHN_V0) {
+		dst_rect.h = src_rect.h;
+	}
+
+	do {
+		if (chn_idx == DSS_RCHN_V0 && pblock_info->h_ratio_arsr2p
+		    && pblock_info->h_ratio) {
+			h_ratio = pblock_info->h_ratio;
+			en_hscl = true;
+			break;
+		} else if (chn_idx == DSS_RCHN_V0 && !pblock_info->h_ratio
+			   && pblock_info->h_ratio_arsr2p) {
+			break;
+		}
+
+		if (pblock_info && (pblock_info->h_ratio != 0)
+		    && (pblock_info->h_ratio != SCF_INC_FACTOR)) {
+			h_ratio = pblock_info->h_ratio;
+			en_hscl = true;
+			break;
+		}
+
+		if (chn_idx == DSS_RCHN_V0) {
+			dst_rect.w =
+			    (src_rect.w > dst_rect.w ? dst_rect.w : src_rect.w);
+		}
+
+		if (src_rect.w == dst_rect.w)
+			break;
+
+		en_hscl = true;
+
+		if ((src_rect.w < SCF_MIN_INPUT)
+		    || (dst_rect.w < SCF_MIN_OUTPUT)) {
+			HISI_FB_ERR
+			    ("src_rect.w(%d) small than 16, "
+			     "or dst_rect.w(%d) small than 16\n",
+			     src_rect.w, dst_rect.w);
+			return -EINVAL;
+		}
+
+		h_ratio =
+		    (DSS_HEIGHT(src_rect.w) * SCF_INC_FACTOR +
+		     SCF_INC_FACTOR / 2 - acc_hscl) / DSS_HEIGHT(dst_rect.w);
+
+		if ((dst_rect.w > (src_rect.w * SCF_UPSCALE_MAX))
+		    || (src_rect.w > (dst_rect.w * SCF_DOWNSCALE_MAX))) {
+			HISI_FB_ERR
+			    ("width out of range, original_src_rec(%d, %d, %d, %d) "
+			     "new_src_rect(%d, %d, %d, %d), "
+			     "dst_rect(%d, %d, %d, %d), rdma_stretch_enable=%d\n",
+			     layer->src_rect.x, layer->src_rect.y,
+			     layer->src_rect.w, layer->src_rect.h, src_rect.x,
+			     src_rect.y, src_rect.w, src_rect.h, dst_rect.x,
+			     dst_rect.y, dst_rect.w, dst_rect.h,
+			     rdma_stretch_enable);
+
+			return -EINVAL;
+		}
+	} while (0);
+
+	do {
+		if (src_rect.h == dst_rect.h)
+			break;
+
+		en_vscl = true;
+		scf_en_vscl = 1;
+
+		v_ratio =
+		    (DSS_HEIGHT(src_rect.h) * SCF_INC_FACTOR +
+		     SCF_INC_FACTOR / 2 - acc_vscl) / DSS_HEIGHT(dst_rect.h);
+
+		if ((dst_rect.h > (src_rect.h * SCF_UPSCALE_MAX))
+		    || (src_rect.h > (dst_rect.h * SCF_DOWNSCALE_MAX))) {
+			HISI_FB_ERR
+			    ("height out of range, original_src_rec(%d, %d, %d, %d) "
+			     "new_src_rect(%d, %d, %d, %d), "
+			     "dst_rect(%d, %d, %d, %d), rdma_stretch_enable=%d.\n",
+			     layer->src_rect.x, layer->src_rect.y,
+			     layer->src_rect.w, layer->src_rect.h, src_rect.x,
+			     src_rect.y, src_rect.w, src_rect.h, dst_rect.x,
+			     dst_rect.y, dst_rect.w, dst_rect.h,
+			     rdma_stretch_enable);
+			return -EINVAL;
+		}
+	} while (0);
+
+	if (!en_hscl && !en_vscl) {
+		return 0;
+	}
+
+	/* scale down, do hscl first; scale up, do vscl first */
+	h_v_order = (src_rect.w > dst_rect.w) ? 0 : 1;
+
+	if (pblock_info && (pblock_info->acc_hscl != 0)) {
+		acc_hscl = pblock_info->acc_hscl;
+	}
+
+	scl = &(hisifd->dss_module.scl[chn_idx]);
+	hisifd->dss_module.scl_used[chn_idx] = 1;
+
+	has_pixel_alpha = hal_format_has_alpha(layer->img.format);
+
+	scl->en_hscl_str = set_bits32(scl->en_hscl_str, 0x0, 1, 0);
+
+	if (v_ratio >= 2 * SCF_INC_FACTOR) {
+		if (has_pixel_alpha)
+			scl->en_vscl_str =
+			    set_bits32(scl->en_vscl_str, 0x3, 2, 0);
+		else
+			scl->en_vscl_str =
+			    set_bits32(scl->en_vscl_str, 0x1, 2, 0);
+	} else {
+		scl->en_vscl_str = set_bits32(scl->en_vscl_str, 0x0, 1, 0);
+	}
+
+	if (src_rect.h > dst_rect.h) {
+		scf_en_vscl = 0x3;
+	}
+	en_mmp = 0x1;
+
+	scl->h_v_order = set_bits32(scl->h_v_order, h_v_order, 1, 0);
+	scl->input_width_height = set_bits32(scl->input_width_height,
+					     DSS_HEIGHT(src_rect.h), 13, 0);
+	scl->input_width_height = set_bits32(scl->input_width_height,
+					     DSS_WIDTH(src_rect.w), 13, 16);
+	scl->output_width_height = set_bits32(scl->output_width_height,
+					      DSS_HEIGHT(dst_rect.h), 13, 0);
+	scl->output_width_height = set_bits32(scl->output_width_height,
+					      DSS_WIDTH(dst_rect.w), 13, 16);
+	scl->en_hscl = set_bits32(scl->en_hscl, (en_hscl ? 0x1 : 0x0), 1, 0);
+	scl->en_vscl = set_bits32(scl->en_vscl, scf_en_vscl, 2, 0);
+	scl->acc_hscl = set_bits32(scl->acc_hscl, acc_hscl, 31, 0);
+	scl->inc_hscl = set_bits32(scl->inc_hscl, h_ratio, 24, 0);
+	scl->inc_vscl = set_bits32(scl->inc_vscl, v_ratio, 24, 0);
+	scl->en_mmp = set_bits32(scl->en_mmp, en_mmp, 1, 0);
+	scl->fmt = layer->img.format;
+
+	return 0;
+}
+
+static void hisi_dss_post_scf_init(char __iomem *post_scf_base,
+				   dss_arsr1p_t *s_post_scf)
+{
+	BUG_ON(post_scf_base == NULL);
+	BUG_ON(s_post_scf == NULL);
+
+	memset(s_post_scf, 0, sizeof(dss_arsr1p_t));
+
+	s_post_scf->ihleft = inp32(post_scf_base + ARSR1P_IHLEFT);
+	s_post_scf->ihright = inp32(post_scf_base + ARSR1P_IHRIGHT);
+	s_post_scf->ihleft1 = inp32(post_scf_base + ARSR1P_IHLEFT1);
+	s_post_scf->ihright1 = inp32(post_scf_base + ARSR1P_IHRIGHT1);
+	s_post_scf->ivtop = inp32(post_scf_base + ARSR1P_IVTOP);
+	s_post_scf->ivbottom = inp32(post_scf_base + ARSR1P_IVBOTTOM);
+	s_post_scf->uv_offset = inp32(post_scf_base + ARSR1P_UV_OFFSET);
+	s_post_scf->ihinc = inp32(post_scf_base + ARSR1P_IHINC);
+	s_post_scf->ivinc = inp32(post_scf_base + ARSR1P_IVINC);
+	s_post_scf->mode = inp32(post_scf_base + ARSR1P_MODE);
+	s_post_scf->format = inp32(post_scf_base + ARSR1P_FORMAT);
+
+	s_post_scf->skin_thres_y = inp32(post_scf_base + ARSR1P_SKIN_THRES_Y);
+	s_post_scf->skin_thres_u = inp32(post_scf_base + ARSR1P_SKIN_THRES_U);
+	s_post_scf->skin_thres_v = inp32(post_scf_base + ARSR1P_SKIN_THRES_V);
+	s_post_scf->skin_expected = inp32(post_scf_base + ARSR1P_SKIN_EXPECTED);
+	s_post_scf->skin_cfg = inp32(post_scf_base + ARSR1P_SKIN_CFG);
+	s_post_scf->shoot_cfg1 = inp32(post_scf_base + ARSR1P_SHOOT_CFG1);
+	s_post_scf->shoot_cfg2 = inp32(post_scf_base + ARSR1P_SHOOT_CFG2);
+	s_post_scf->sharp_cfg1 = inp32(post_scf_base + ARSR1P_SHARP_CFG1);
+	s_post_scf->sharp_cfg2 = inp32(post_scf_base + ARSR1P_SHARP_CFG2);
+	s_post_scf->sharp_cfg3 = inp32(post_scf_base + ARSR1P_SHARP_CFG3);
+	s_post_scf->sharp_cfg4 = inp32(post_scf_base + ARSR1P_SHARP_CFG4);
+	s_post_scf->sharp_cfg5 = inp32(post_scf_base + ARSR1P_SHARP_CFG5);
+	s_post_scf->sharp_cfg6 = inp32(post_scf_base + ARSR1P_SHARP_CFG6);
+	s_post_scf->sharp_cfg7 = inp32(post_scf_base + ARSR1P_SHARP_CFG7);
+	s_post_scf->sharp_cfg8 = inp32(post_scf_base + ARSR1P_SHARP_CFG8);
+	s_post_scf->sharp_cfg9 = inp32(post_scf_base + ARSR1P_SHARP_CFG9);
+	s_post_scf->sharp_cfg10 = inp32(post_scf_base + ARSR1P_SHARP_CFG10);
+	s_post_scf->sharp_cfg11 = inp32(post_scf_base + ARSR1P_SHARP_CFG11);
+	s_post_scf->diff_ctrl = inp32(post_scf_base + ARSR1P_DIFF_CTRL);
+	s_post_scf->lsc_cfg1 = inp32(post_scf_base + ARSR1P_LSC_CFG1);
+	s_post_scf->lsc_cfg2 = inp32(post_scf_base + ARSR1P_LSC_CFG2);
+	s_post_scf->lsc_cfg3 = inp32(post_scf_base + ARSR1P_LSC_CFG3);
+	s_post_scf->force_clk_on_cfg =
+	    inp32(post_scf_base + ARSR1P_FORCE_CLK_ON_CFG);
+}
+
+static void hisi_dss_post_scf_set_reg(struct hisi_fb_data_type *hisifd,
+				      char __iomem *post_scf_base,
+				      dss_arsr1p_t *s_post_scf)
+{
+	BUG_ON(hisifd == NULL);
+	BUG_ON(post_scf_base == NULL);
+	BUG_ON(s_post_scf == NULL);
+
+	hisifd->set_reg(hisifd,
+			hisifd->dss_base + DSS_DPP_OFFSET + DPP_IMG_SIZE_BEF_SR,
+			((DSS_HEIGHT(s_post_scf->dpp_img_vrt_bef_sr) << 16) |
+			 (DSS_WIDTH(s_post_scf->dpp_img_hrz_bef_sr))), 32, 0);
+	hisifd->set_reg(hisifd,
+			hisifd->dss_base + DSS_DPP_OFFSET + DPP_IMG_SIZE_AFT_SR,
+			((DSS_HEIGHT(s_post_scf->dpp_img_vrt_aft_sr) << 16) |
+			 (DSS_WIDTH(s_post_scf->dpp_img_hrz_aft_sr))), 32, 0);
+
+	outp32(post_scf_base + ARSR1P_IHLEFT, s_post_scf->ihleft);
+	outp32(post_scf_base + ARSR1P_IHRIGHT, s_post_scf->ihright);
+	outp32(post_scf_base + ARSR1P_IHLEFT1, s_post_scf->ihleft1);
+	outp32(post_scf_base + ARSR1P_IHRIGHT1, s_post_scf->ihright1);
+	outp32(post_scf_base + ARSR1P_IVTOP, s_post_scf->ivtop);
+	outp32(post_scf_base + ARSR1P_IVBOTTOM, s_post_scf->ivbottom);
+	outp32(post_scf_base + ARSR1P_UV_OFFSET, s_post_scf->uv_offset);
+	outp32(post_scf_base + ARSR1P_IHINC, s_post_scf->ihinc);
+	outp32(post_scf_base + ARSR1P_IVINC, s_post_scf->ivinc);
+	outp32(post_scf_base + ARSR1P_MODE, s_post_scf->mode);
+	outp32(post_scf_base + ARSR1P_FORMAT, s_post_scf->format);
+
+	outp32(post_scf_base + ARSR1P_SKIN_THRES_Y, s_post_scf->skin_thres_y);
+	outp32(post_scf_base + ARSR1P_SKIN_THRES_U, s_post_scf->skin_thres_u);
+	outp32(post_scf_base + ARSR1P_SKIN_THRES_V, s_post_scf->skin_thres_v);
+	outp32(post_scf_base + ARSR1P_SKIN_EXPECTED, s_post_scf->skin_expected);
+	outp32(post_scf_base + ARSR1P_SKIN_CFG, s_post_scf->skin_cfg);
+	outp32(post_scf_base + ARSR1P_SHOOT_CFG1, s_post_scf->shoot_cfg1);
+	outp32(post_scf_base + ARSR1P_SHOOT_CFG2, s_post_scf->shoot_cfg2);
+	outp32(post_scf_base + ARSR1P_SHARP_CFG1, s_post_scf->sharp_cfg1);
+	outp32(post_scf_base + ARSR1P_SHARP_CFG2, s_post_scf->sharp_cfg2);
+	outp32(post_scf_base + ARSR1P_SHARP_CFG3, s_post_scf->sharp_cfg3);
+	outp32(post_scf_base + ARSR1P_SHARP_CFG4, s_post_scf->sharp_cfg4);
+	outp32(post_scf_base + ARSR1P_SHARP_CFG5, s_post_scf->sharp_cfg5);
+	outp32(post_scf_base + ARSR1P_SHARP_CFG6, s_post_scf->sharp_cfg6);
+	outp32(post_scf_base + ARSR1P_SHARP_CFG7, s_post_scf->sharp_cfg7);
+	outp32(post_scf_base + ARSR1P_SHARP_CFG8, s_post_scf->sharp_cfg8);
+	outp32(post_scf_base + ARSR1P_SHARP_CFG9, s_post_scf->sharp_cfg9);
+	outp32(post_scf_base + ARSR1P_SHARP_CFG10, s_post_scf->sharp_cfg10);
+	outp32(post_scf_base + ARSR1P_SHARP_CFG11, s_post_scf->sharp_cfg11);
+	outp32(post_scf_base + ARSR1P_DIFF_CTRL, s_post_scf->diff_ctrl);
+	outp32(post_scf_base + ARSR1P_LSC_CFG1, s_post_scf->lsc_cfg1);
+	outp32(post_scf_base + ARSR1P_LSC_CFG2, s_post_scf->lsc_cfg2);
+	outp32(post_scf_base + ARSR1P_LSC_CFG3, s_post_scf->lsc_cfg3);
+	outp32(post_scf_base + ARSR1P_FORCE_CLK_ON_CFG,
+	       s_post_scf->force_clk_on_cfg);
+}
+
+int hisi_dss_post_scf_config(struct hisi_fb_data_type *hisifd,
+			     dss_overlay_t *pov_req)
+{
+	struct hisi_panel_info *pinfo = NULL;
+	dss_rect_t src_rect = { 0 };
+	dss_rect_t dst_rect = { 0 };
+	dss_arsr1p_t *post_scf = NULL;
+
+	int32_t ihinc = 0;
+	int32_t ivinc = 0;
+	int32_t ihleft = 0;
+	int32_t ihright = 0;
+	int32_t ihleft1 = 0;
+	int32_t ihright1 = 0;
+	int32_t ivtop = 0;
+	int32_t ivbottom = 0;
+	int32_t extraw = 0;
+	int32_t extraw_left = 0;
+	int32_t extraw_right = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_req == NULL);
+	pinfo = &(hisifd->panel_info);
+
+	if (!HISI_DSS_SUPPORT_DPP_MODULE_BIT(DPP_MODULE_POST_SCF)) {
+		return 0;
+	}
+
+	if ((pov_req->res_updt_rect.w == 0) && (pov_req->res_updt_rect.h == 0)) {
+		return 0;
+	}
+
+	if ((pov_req->res_updt_rect.w < 0) || (pov_req->res_updt_rect.h < 0)) {
+		HISI_FB_ERR("fb%d, res_updt_rect[%d,%d, %d,%d] is invalid!\n",
+			    hisifd->index, pov_req->res_updt_rect.x,
+			    pov_req->res_updt_rect.y, pov_req->res_updt_rect.w,
+			    pov_req->res_updt_rect.h);
+		return 0;
+	}
+
+	if ((pov_req->res_updt_rect.w == hisifd->res_updt_rect.w)
+	    && (pov_req->res_updt_rect.h == hisifd->res_updt_rect.h)) {
+
+		return 0;
+	}
+
+	HISI_FB_DEBUG
+	    ("fb%d, post scf res_updt_rect[%d, %d]->lcd_rect[%d, %d]\n",
+	     hisifd->index, pov_req->res_updt_rect.w, pov_req->res_updt_rect.h,
+	     pinfo->xres, pinfo->yres);
+
+	hisifd->res_updt_rect = pov_req->res_updt_rect;
+
+	src_rect = pov_req->res_updt_rect;
+	dst_rect.x = 0;
+	dst_rect.y = 0;
+	dst_rect.w = pinfo->xres;
+	dst_rect.h = pinfo->yres;
+
+	post_scf = &(hisifd->dss_module.post_scf);
+	hisifd->dss_module.post_scf_used = 1;
+
+	if ((src_rect.w < 16) || (src_rect.h < 16)
+	    || (src_rect.w > 3840) || (src_rect.h > 8192)
+	    || (dst_rect.w > 8192) || (dst_rect.h > 8192)) {
+		HISI_FB_ERR
+		    ("invalid input size: src_rect(%d,%d,%d,%d) "
+		     "should be larger than 16*16, less than 3840*8192!\n"
+		     "invalid output size: dst_rect(%d,%d,%d,%d) "
+		     "should be less than 8192*8192!\n",
+		     src_rect.x, src_rect.y, src_rect.w, src_rect.h, dst_rect.x,
+		     dst_rect.y, dst_rect.w, dst_rect.h);
+		post_scf->mode = 0x1;
+		return 0;
+	}
+
+	ihinc = ARSR1P_INC_FACTOR * src_rect.w / dst_rect.w;
+	ivinc = ARSR1P_INC_FACTOR * src_rect.h / dst_rect.h;
+
+	if ((ihinc == ARSR1P_INC_FACTOR)
+	    && (ivinc == ARSR1P_INC_FACTOR)
+	    && (pinfo->arsr1p_sharpness_support != 1)) {
+		post_scf->mode = 0x1;
+		return 0;
+	}
+
+	/* 0x2000<=ihinc<=0x80000; 0x2000<=ivinc<=0x80000; */
+	if ((ihinc < 0x2000) || (ihinc > ARSR1P_INC_FACTOR)
+	    || (ivinc < 0x2000) || (ivinc > ARSR1P_INC_FACTOR)) {
+		HISI_FB_ERR("invalid ihinc(0x%x), ivinc(0x%x)!\n", ihinc,
+			    ivinc);
+		post_scf->mode = 0x1;
+		return -1;
+	}
+
+	if ((ihinc > ARSR1P_INC_FACTOR) || (ivinc > ARSR1P_INC_FACTOR)) {
+		HISI_FB_ERR
+		    ("scaling down is not supported by ARSR1P, "
+		     "ihinc = 0x%x, ivinc = 0x%x\n",
+		     ihinc, ivinc);
+		post_scf->mode = 0x1;
+		return -1;
+	}
+
+	post_scf->mode = 0x0;
+	if (pinfo->arsr1p_sharpness_support) {
+		post_scf->mode |= 0xe;
+	}
+
+	post_scf->mode |= 0x20;
+	if ((ihinc < ARSR1P_INC_FACTOR) || (ivinc < ARSR1P_INC_FACTOR)) {
+		post_scf->mode |= 0x10;
+	} else {
+		post_scf->mode |= 0x40;
+	}
+
+	post_scf->dpp_img_hrz_bef_sr = src_rect.w;
+	post_scf->dpp_img_vrt_bef_sr = src_rect.h;
+	post_scf->dpp_img_hrz_aft_sr = dst_rect.w;
+	post_scf->dpp_img_vrt_aft_sr = dst_rect.h;
+
+	extraw = (8 * ARSR1P_INC_FACTOR) / ihinc;
+	extraw_left = (extraw % 2) ? (extraw + 1) : (extraw);
+	extraw = (2 * ARSR1P_INC_FACTOR) / ihinc;
+	extraw_right = (extraw % 2) ? (extraw + 1) : (extraw);
+
+	ihleft1 = dst_rect.x * ihinc - src_rect.x * ARSR1P_INC_FACTOR;
+	if (ihleft1 < 0)
+		ihleft1 = 0;
+	ihleft = ihleft1 - extraw_left * ihinc;
+	if (ihleft < 0)
+		ihleft = 0;
+
+	ihright1 = ihleft1 + (dst_rect.w - 1) * ihinc;
+	ihright = ihright1 + extraw_right * ihinc;
+	if (ihright >= src_rect.w * ARSR1P_INC_FACTOR)
+		ihright = src_rect.w * ARSR1P_INC_FACTOR - 1;
+
+	ivtop = dst_rect.y * ivinc - src_rect.y * ARSR1P_INC_FACTOR;
+	if (ivtop < 0)
+		ivtop = 0;
+	ivbottom = ivtop + (dst_rect.h - 1) * ivinc;
+	if (ivbottom >= src_rect.h * ARSR1P_INC_FACTOR)
+		ivbottom = src_rect.h * ARSR1P_INC_FACTOR - 1;
+
+	if ((ihleft1 - ihleft) % (ihinc)) {
+		HISI_FB_ERR
+		    ("(ihleft1(%d)-ihleft(%d))  ihinc(%d) != 0, invalid!\n",
+		     ihleft1, ihleft, ihinc);
+		post_scf->mode = 0x1;
+		return -1;
+	}
+
+	if ((ihright1 - ihleft1) % ihinc) {
+		HISI_FB_ERR
+		    ("(ihright1(%d)-ihleft1(%d))  ihinc(%d) != 0, invalid!\n",
+		     ihright1, ihleft1, ihinc);
+		post_scf->mode = 0x1;
+		return -1;
+	}
+
+	post_scf->ihleft = set_bits32(post_scf->ihleft, ihleft, 32, 0);
+	post_scf->ihright = set_bits32(post_scf->ihright, ihright, 32, 0);
+	post_scf->ihleft1 = set_bits32(post_scf->ihleft1, ihleft1, 32, 0);
+	post_scf->ihright1 = set_bits32(post_scf->ihright1, ihright1, 32, 0);
+	post_scf->ivtop = set_bits32(post_scf->ivtop, ivtop, 32, 0);
+	post_scf->ivbottom = set_bits32(post_scf->ivbottom, ivbottom, 32, 0);
+	post_scf->ihinc = set_bits32(post_scf->ihinc, ihinc, 32, 0);
+	post_scf->ivinc = set_bits32(post_scf->ivinc, ivinc, 32, 0);
+
+	post_scf->skin_thres_y =
+	    set_bits32(post_scf->skin_thres_y, 0x534b, 32, 0);
+	post_scf->skin_thres_u =
+	    set_bits32(post_scf->skin_thres_u, 0x330a05, 32, 0);
+	post_scf->skin_thres_v =
+	    set_bits32(post_scf->skin_thres_v, 0xaa0c06, 32, 0);
+	post_scf->skin_expected =
+	    set_bits32(post_scf->skin_expected, 0x917198, 32, 0);
+	post_scf->skin_cfg = set_bits32(post_scf->skin_cfg, 0x30a06, 32, 0);
+	post_scf->shoot_cfg1 = set_bits32(post_scf->shoot_cfg1, 0x14, 32, 0);
+	post_scf->shoot_cfg2 = set_bits32(post_scf->shoot_cfg2, 0x1f0, 32, 0);
+	post_scf->sharp_cfg1 =
+	    set_bits32(post_scf->sharp_cfg1, 0x40300602, 32, 0);
+	post_scf->sharp_cfg2 =
+	    set_bits32(post_scf->sharp_cfg2, 0x40300602, 32, 0);
+	post_scf->sharp_cfg3 =
+	    set_bits32(post_scf->sharp_cfg3, 0x12c0000, 32, 0);
+	post_scf->sharp_cfg4 = set_bits32(post_scf->sharp_cfg4, 0x0, 32, 0);
+	post_scf->sharp_cfg5 =
+	    set_bits32(post_scf->sharp_cfg5, 0x1900000, 32, 0);
+	post_scf->sharp_cfg6 =
+	    set_bits32(post_scf->sharp_cfg6, 0xffff641e, 32, 0);
+	post_scf->sharp_cfg7 =
+	    set_bits32(post_scf->sharp_cfg7, 0x1a00018, 32, 0);
+	post_scf->sharp_cfg8 =
+	    set_bits32(post_scf->sharp_cfg8, 0x200640, 32, 0);
+	post_scf->sharp_cfg9 =
+	    set_bits32(post_scf->sharp_cfg9, 0x2006400, 32, 0);
+	post_scf->sharp_cfg10 = set_bits32(post_scf->sharp_cfg10, 0x0, 32, 0);
+	post_scf->sharp_cfg11 = set_bits32(post_scf->sharp_cfg11, 0x0, 32, 0);
+
+	post_scf->diff_ctrl = set_bits32(post_scf->diff_ctrl, 0x1410, 32, 0);
+	post_scf->lsc_cfg1 = set_bits32(post_scf->lsc_cfg1, 0x3c618410, 32, 0);
+	post_scf->lsc_cfg2 = set_bits32(post_scf->lsc_cfg2, 0x0, 32, 0);
+	post_scf->lsc_cfg3 = set_bits32(post_scf->lsc_cfg3, 0x800600, 32, 0);
+
+	return 0;
+}
+
+/*******************************************************************************
+ ** DSS POST_CLIP
+ */
+static void hisi_dss_post_clip_init(char __iomem *post_clip_base,
+				    dss_post_clip_t *s_post_clip)
+{
+	BUG_ON(post_clip_base == NULL);
+	BUG_ON(s_post_clip == NULL);
+
+	memset(s_post_clip, 0, sizeof(dss_post_clip_t));
+}
+
+int hisi_dss_post_clip_config(struct hisi_fb_data_type *hisifd,
+			      dss_layer_t *layer)
+{
+	dss_post_clip_t *post_clip = NULL;
+	int chn_idx = 0;
+	dss_rect_t post_clip_rect;
+
+	chn_idx = layer->chn_idx;
+	post_clip_rect = layer->dst_rect;
+
+	if (((chn_idx >= DSS_RCHN_V0) && (chn_idx <= DSS_RCHN_G1))
+	    || (chn_idx == DSS_RCHN_V2)) {
+		post_clip = &(hisifd->dss_module.post_clip[chn_idx]);
+		hisifd->dss_module.post_cilp_used[chn_idx] = 1;
+
+		post_clip->disp_size =
+		    set_bits32(post_clip->disp_size,
+			       DSS_HEIGHT(post_clip_rect.h), 13, 0);
+		post_clip->disp_size =
+		    set_bits32(post_clip->disp_size,
+			       DSS_WIDTH(post_clip_rect.w), 13, 16);
+
+		if ((chn_idx == DSS_RCHN_V0)
+		    && layer->block_info.arsr2p_left_clip) {
+			post_clip->clip_ctl_hrz =
+			    set_bits32(post_clip->clip_ctl_hrz,
+				       layer->block_info.arsr2p_left_clip, 6, 16);
+			post_clip->clip_ctl_hrz =
+			    set_bits32(post_clip->clip_ctl_hrz, 0x0, 6, 0);
+		} else {
+			post_clip->clip_ctl_hrz =
+			    set_bits32(post_clip->clip_ctl_hrz, 0x0, 32, 0);
+		}
+
+		post_clip->clip_ctl_vrz =
+		    set_bits32(post_clip->clip_ctl_vrz, 0x0, 32, 0);
+		post_clip->ctl_clip_en =
+		    set_bits32(post_clip->ctl_clip_en, 0x1, 32, 0);
+	}
+
+	return 0;
+}
+
+void hisi_dss_post_clip_set_reg(struct hisi_fb_data_type *hisifd,
+				char __iomem *post_clip_base,
+				dss_post_clip_t *s_post_clip)
+{
+	BUG_ON(hisifd == NULL);
+	BUG_ON(post_clip_base == NULL);
+	BUG_ON(s_post_clip == NULL);
+
+	hisifd->set_reg(hisifd, post_clip_base + POST_CLIP_DISP_SIZE,
+			s_post_clip->disp_size, 32, 0);
+	hisifd->set_reg(hisifd, post_clip_base + POST_CLIP_CTL_HRZ,
+			s_post_clip->clip_ctl_hrz, 32, 0);
+	hisifd->set_reg(hisifd, post_clip_base + POST_CLIP_CTL_VRZ,
+			s_post_clip->clip_ctl_vrz, 32, 0);
+	hisifd->set_reg(hisifd, post_clip_base + POST_CLIP_EN,
+			s_post_clip->ctl_clip_en, 32, 0);
+}
+
+/*******************************************************************************
+ ** DSS MCTL
+ */
+static void hisi_dss_mctl_init(char __iomem *mctl_base, dss_mctl_t *s_mctl)
+{
+	BUG_ON(mctl_base == NULL);
+	BUG_ON(s_mctl == NULL);
+
+	memset(s_mctl, 0, sizeof(dss_mctl_t));
+}
+
+static void hisi_dss_mctl_ch_starty_init(char __iomem *mctl_ch_starty_base,
+					 dss_mctl_ch_t *s_mctl_ch)
+{
+	BUG_ON(mctl_ch_starty_base == NULL);
+	BUG_ON(s_mctl_ch == NULL);
+
+	memset(s_mctl_ch, 0, sizeof(dss_mctl_ch_t));
+
+	s_mctl_ch->chn_starty = inp32(mctl_ch_starty_base);
+}
+
+static void hisi_dss_mctl_ch_mod_dbg_init(char __iomem *mctl_ch_dbg_base,
+					  dss_mctl_ch_t *s_mctl_ch)
+{
+	BUG_ON(mctl_ch_dbg_base == NULL);
+	BUG_ON(s_mctl_ch == NULL);
+
+	s_mctl_ch->chn_mod_dbg = inp32(mctl_ch_dbg_base);
+}
+
+static void hisi_dss_mctl_sys_init(char __iomem *mctl_sys_base,
+				   dss_mctl_sys_t *s_mctl_sys)
+{
+	int i = 0;
+
+	BUG_ON(mctl_sys_base == NULL);
+	BUG_ON(s_mctl_sys == NULL);
+
+	memset(s_mctl_sys, 0, sizeof(dss_mctl_sys_t));
+
+	for (i = 0; i < DSS_OVL_IDX_MAX; i++) {
+		s_mctl_sys->chn_ov_sel[i] = 0xFFFFFFFF;
+	}
+
+	for (i = 0; i < DSS_WCH_MAX; i++) {
+		s_mctl_sys->wchn_ov_sel[i] = 0x0;
+	}
+}
+
+static void hisi_dss_mctl_sys_set_reg(struct hisi_fb_data_type *hisifd,
+				      char __iomem *mctl_sys_base,
+				      dss_mctl_sys_t *s_mctl_sys, int ovl_idx)
+{
+	int k = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(mctl_sys_base == NULL);
+	BUG_ON(s_mctl_sys == NULL);
+	BUG_ON((ovl_idx < DSS_OVL0) || (ovl_idx >= DSS_OVL_IDX_MAX));
+
+	if (s_mctl_sys->chn_ov_sel_used[ovl_idx]) {
+		hisifd->set_reg(hisifd,
+				mctl_sys_base + MCTL_RCH_OV0_SEL + ovl_idx * 0x4,
+				s_mctl_sys->chn_ov_sel[ovl_idx], 32, 0);
+	}
+
+	for (k = 0; k < DSS_WCH_MAX; k++) {
+		if (s_mctl_sys->wch_ov_sel_used[k]) {
+			hisifd->set_reg(hisifd,
+					mctl_sys_base + MCTL_WCH_OV2_SEL + k * 0x4,
+					s_mctl_sys->wchn_ov_sel[k], 32, 0);
+		}
+	}
+
+	if (s_mctl_sys->ov_flush_en_used[ovl_idx]) {
+		hisifd->set_reg(hisifd,
+				mctl_sys_base + MCTL_OV0_FLUSH_EN + ovl_idx * 0x4,
+				s_mctl_sys->ov_flush_en[ovl_idx], 32, 0);
+	}
+}
+
+static void hisi_dss_mctl_ov_set_reg(struct hisi_fb_data_type *hisifd,
+				     char __iomem *mctl_base,
+				     dss_mctl_t *s_mctl, int ovl_idx,
+				     bool enable_cmdlist)
+{
+	BUG_ON(hisifd == NULL);
+	BUG_ON(mctl_base == NULL);
+	BUG_ON(s_mctl == NULL);
+	BUG_ON((ovl_idx < DSS_OVL0) || (ovl_idx >= DSS_OVL_IDX_MAX));
+
+	if ((ovl_idx == DSS_OVL0) || (ovl_idx == DSS_OVL1)) {
+		hisifd->set_reg(hisifd, mctl_base + MCTL_CTL_MUTEX_DBUF,
+				s_mctl->ctl_mutex_dbuf, 32, 0);
+		hisi_dss_mctl_ov_set_ctl_dbg_reg(hisifd, mctl_base,
+						 enable_cmdlist);
+	}
+
+	hisifd->set_reg(hisifd, mctl_base + MCTL_CTL_MUTEX_OV,
+			s_mctl->ctl_mutex_ov, 32, 0);
+}
+
+static void hisi_dss_mctl_ch_set_reg(struct hisi_fb_data_type *hisifd,
+				     dss_mctl_ch_base_t *mctl_ch_base,
+				     dss_mctl_ch_t *s_mctl_ch,
+				     int32_t mctl_idx)
+{
+	char __iomem *chn_mutex_base = NULL;
+	int i = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(mctl_ch_base == NULL);
+	BUG_ON(s_mctl_ch == NULL);
+	BUG_ON((mctl_idx < DSS_MCTL0) || (mctl_idx >= DSS_MCTL_IDX_MAX));
+
+	for (i = 0; i < DSS_MCTL_IDX_MAX; i++) {
+		if (g_dss_module_ovl_base[i][MODULE_MCTL_BASE] == 0)
+			continue;
+		chn_mutex_base = mctl_ch_base->chn_mutex_base +
+		    g_dss_module_ovl_base[i][MODULE_MCTL_BASE];
+
+		if (i != mctl_idx) {
+			hisifd->set_reg(hisifd, chn_mutex_base, 0, 32, 0);
+		}
+	}
+
+	chn_mutex_base = mctl_ch_base->chn_mutex_base +
+	    g_dss_module_ovl_base[mctl_idx][MODULE_MCTL_BASE];
+	BUG_ON(chn_mutex_base == NULL);
+
+	hisifd->set_reg(hisifd, chn_mutex_base, s_mctl_ch->chn_mutex, 32, 0);
+}
+
+static void hisi_dss_mctl_sys_ch_set_reg(struct hisi_fb_data_type *hisifd,
+					 dss_mctl_ch_base_t *mctl_ch_base,
+					 dss_mctl_ch_t *s_mctl_ch, int chn_idx,
+					 bool normal)
+{
+	char __iomem *mctl_sys_base = NULL;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(mctl_ch_base == NULL);
+	BUG_ON(s_mctl_ch == NULL);
+
+	mctl_sys_base = hisifd->dss_base + DSS_MCTRL_SYS_OFFSET;
+
+	if (normal == true) {
+		if (chn_idx == DSS_RCHN_V2) {
+			hisifd->set_reg(hisifd, mctl_sys_base + MCTL_MOD19_DBG,
+					0xA0000, 32, 0);
+		}
+
+		if (chn_idx == DSS_WCHN_W2) {
+			hisifd->set_reg(hisifd, mctl_sys_base + MCTL_MOD20_DBG,
+					0xA0000, 32, 0);
+		}
+	}
+
+	if (normal == false) {
+		if (chn_idx == DSS_RCHN_V2) {
+			hisifd->set_reg(hisifd, mctl_sys_base + MCTL_MOD19_DBG,
+					0xA0002, 32, 0);
+		}
+
+		if (chn_idx == DSS_WCHN_W2) {
+			hisifd->set_reg(hisifd, mctl_sys_base + MCTL_MOD20_DBG,
+					0xA0002, 32, 0);
+		}
+	}
+
+	if (mctl_ch_base->chn_ov_en_base) {
+		hisifd->set_reg(hisifd, mctl_ch_base->chn_ov_en_base,
+				s_mctl_ch->chn_ov_oen, 32, 0);
+	}
+
+	hisifd->set_reg(hisifd, mctl_ch_base->chn_flush_en_base,
+			s_mctl_ch->chn_flush_en, 32, 0);
+}
+
+void hisi_dss_mctl_mutex_lock(struct hisi_fb_data_type *hisifd, int ovl_idx)
+{
+	char __iomem *mctl_base = NULL;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON((ovl_idx < DSS_OVL0) || (ovl_idx >= DSS_OVL_IDX_MAX));
+
+	mctl_base = hisifd->dss_module.mctl_base[ovl_idx];
+
+	hisifd->set_reg(hisifd, mctl_base + MCTL_CTL_MUTEX, 0x1, 1, 0);
+}
+
+void hisi_dss_mctl_mutex_unlock(struct hisi_fb_data_type *hisifd, int ovl_idx)
+{
+	char __iomem *mctl_base = NULL;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON((ovl_idx < DSS_OVL0) || (ovl_idx >= DSS_OVL_IDX_MAX));
+
+	mctl_base = hisifd->dss_module.mctl_base[ovl_idx];
+
+	hisifd->set_reg(hisifd, mctl_base + MCTL_CTL_MUTEX, 0x0, 1, 0);
+}
+
+void hisi_dss_mctl_on(struct hisi_fb_data_type *hisifd, int mctl_idx,
+		      bool enable_cmdlist, bool fastboot_enable)
+{
+	char __iomem *mctl_base = NULL;
+	char __iomem *mctl_sys_base = NULL;
+	int i = 0;
+	int tmp = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON((mctl_idx < DSS_MCTL0) || (mctl_idx >= DSS_MCTL_IDX_MAX));
+
+	mctl_base = hisifd->dss_base +
+	    g_dss_module_ovl_base[mctl_idx][MODULE_MCTL_BASE];
+	mctl_sys_base = hisifd->dss_base + DSS_MCTRL_SYS_OFFSET;
+
+	set_reg(mctl_base + MCTL_CTL_EN, 0x1, 32, 0);
+
+	if ((mctl_idx == DSS_MCTL0) || (mctl_idx == DSS_MCTL1)) {
+		set_reg(mctl_base + MCTL_CTL_MUTEX_ITF, mctl_idx + 1, 32, 0);
+	}
+
+	if (enable_cmdlist) {
+		tmp = MCTL_MOD_DBG_CH_NUM + MCTL_MOD_DBG_OV_NUM +
+		    MCTL_MOD_DBG_DBUF_NUM + MCTL_MOD_DBG_SCF_NUM;
+		for (i = 0; i < tmp; i++) {
+			set_reg(mctl_sys_base + MCTL_MOD0_DBG + i * 0x4,
+				0xA0000, 32, 0);
+		}
+
+		for (i = 0; i < MCTL_MOD_DBG_ITF_NUM; i++) {
+			set_reg(mctl_sys_base + MCTL_MOD17_DBG + i * 0x4,
+				0xA0F00, 32, 0);
+		}
+
+		if (!fastboot_enable) {
+			set_reg(mctl_base + MCTL_CTL_TOP, 0x1, 32, 0);
+		}
+	} else {
+		set_reg(mctl_base + MCTL_CTL_DBG, 0xB13A00, 32, 0);
+		if (is_mipi_cmd_panel(hisifd)) {
+			set_reg(mctl_base + MCTL_CTL_TOP, 0x1, 32, 0);
+		} else {
+			if (mctl_idx == DSS_MCTL0) {
+				set_reg(mctl_base + MCTL_CTL_TOP, 0x2, 32, 0);
+			} else if (mctl_idx == DSS_MCTL1) {
+				set_reg(mctl_base + MCTL_CTL_TOP, 0x3, 32, 0);
+			} else {
+				set_reg(mctl_base + MCTL_CTL_TOP, 0x1, 32, 0);
+			}
+		}
+	}
+}
+
+int hisi_dss_mctl_ch_config(struct hisi_fb_data_type *hisifd,
+			    dss_overlay_t *pov_req, dss_layer_t *layer,
+			    dss_wb_layer_t *wb_layer, int ovl_idx,
+			    dss_rect_t *wb_ov_block_rect, bool has_base)
+{
+	int chn_idx = 0;
+	int layer_idx = 0;
+	dss_mctl_ch_t *mctl_ch = NULL;
+	dss_mctl_sys_t *mctl_sys = NULL;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_req == NULL);
+	BUG_ON((layer == NULL) && (wb_layer == NULL));
+
+	if (wb_layer) {
+		chn_idx = wb_layer->chn_idx;
+
+		mctl_sys = &(hisifd->dss_module.mctl_sys);
+		hisifd->dss_module.mctl_sys_used = 1;
+
+		mctl_ch = &(hisifd->dss_module.mctl_ch[chn_idx]);
+		hisifd->dss_module.mctl_ch_used[chn_idx] = 1;
+
+		if (chn_idx != DSS_WCHN_W2) {
+			mctl_ch->chn_ov_oen = set_bits32(mctl_ch->chn_ov_oen,
+							 (ovl_idx - 1), 32, 0);
+
+			if (pov_req->wb_layer_nums == MAX_DSS_DST_NUM) {
+				mctl_sys->wchn_ov_sel[0] =
+				    set_bits32(mctl_sys->wchn_ov_sel[0], 3, 32, 0);
+				mctl_sys->wch_ov_sel_used[0] = 1;
+				mctl_sys->wchn_ov_sel[1] =
+				    set_bits32(mctl_sys->wchn_ov_sel[1], 3, 32, 0);
+				mctl_sys->wch_ov_sel_used[1] = 1;
+			} else {
+				mctl_sys->wchn_ov_sel[ovl_idx - DSS_OVL2] =
+				    set_bits32(mctl_sys->wchn_ov_sel[ovl_idx - DSS_OVL2],
+					       (chn_idx - DSS_WCHN_W0 + 1), 32, 0);
+				mctl_sys->wch_ov_sel_used[ovl_idx - DSS_OVL2] = 1;
+			}
+		}
+
+		mctl_ch->chn_mutex = set_bits32(mctl_ch->chn_mutex, 0x1, 1, 0);
+		mctl_ch->chn_flush_en =
+		    set_bits32(mctl_ch->chn_flush_en, 0x1, 1, 0);
+	} else {
+		chn_idx = layer->chn_idx;
+		layer_idx = layer->layer_idx;
+
+		if (layer->need_cap & CAP_BASE)
+			return 0;
+
+		if (has_base) {
+			layer_idx -= 1;
+			if (layer_idx < 0) {
+				HISI_FB_ERR
+				    ("fb%d, layer_idx(%d) is out of range!",
+				     hisifd->index, layer_idx);
+				return -EINVAL;
+			}
+		}
+
+		mctl_sys = &(hisifd->dss_module.mctl_sys);
+		hisifd->dss_module.mctl_sys_used = 1;
+
+		if (layer->need_cap & (CAP_DIM | CAP_PURE_COLOR)) {
+			mctl_sys->chn_ov_sel[ovl_idx] =
+			    set_bits32(mctl_sys->chn_ov_sel[ovl_idx], 0x8, 4,
+				       (layer_idx + 1) * 4);
+			mctl_sys->chn_ov_sel_used[ovl_idx] = 1;
+		} else {
+			mctl_ch = &(hisifd->dss_module.mctl_ch[chn_idx]);
+			hisifd->dss_module.mctl_ch_used[chn_idx] = 1;
+
+			mctl_ch->chn_mutex =
+			    set_bits32(mctl_ch->chn_mutex, 0x1, 1, 0);
+			mctl_ch->chn_flush_en =
+			    set_bits32(mctl_ch->chn_flush_en, 0x1, 1, 0);
+
+			if (chn_idx != DSS_RCHN_V2) {
+				mctl_ch->chn_ov_oen =
+				    set_bits32(mctl_ch->chn_ov_oen,
+					       ((1 << (layer_idx + 1)) |
+						(0x100 << ovl_idx)), 32, 0);
+
+				if (wb_ov_block_rect) {
+					mctl_ch->chn_starty =
+					    set_bits32(mctl_ch->chn_starty,
+						       ((layer->dst_rect.y -
+							 wb_ov_block_rect->y) | (0x8 << 16)), 32, 0);
+				} else {
+					mctl_ch->chn_starty =
+					    set_bits32(mctl_ch->chn_starty,
+						       (layer->dst_rect.y | (0x8 << 16)), 32, 0);
+				}
+
+				mctl_sys->chn_ov_sel[ovl_idx] =
+				    set_bits32(mctl_sys->chn_ov_sel[ovl_idx],
+					       chn_idx, 4, (layer_idx + 1) * 4);
+				mctl_sys->chn_ov_sel_used[ovl_idx] = 1;
+			}
+		}
+	}
+
+	return 0;
+}
+
+int hisi_dss_mctl_ov_config(struct hisi_fb_data_type *hisifd,
+			    dss_overlay_t *pov_req, int ovl_idx, bool has_base,
+			    bool is_first_ov_block)
+{
+	dss_mctl_t *mctl = NULL;
+	dss_mctl_sys_t *mctl_sys = NULL;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON((ovl_idx < DSS_OVL0) || (ovl_idx >= DSS_OVL_IDX_MAX));
+
+	if (pov_req && pov_req->wb_layer_infos[0].chn_idx == DSS_WCHN_W2) {
+		return 0;
+	}
+
+	mctl = &(hisifd->dss_module.mctl[ovl_idx]);
+	hisifd->dss_module.mctl_used[ovl_idx] = 1;
+
+	if (ovl_idx == DSS_OVL0) {
+		mctl->ctl_mutex_itf =
+		    set_bits32(mctl->ctl_mutex_itf, 0x1, 2, 0);
+		mctl->ctl_mutex_dbuf =
+		    set_bits32(mctl->ctl_mutex_dbuf, 0x1, 2, 0);
+	} else if (ovl_idx == DSS_OVL1) {
+		mctl->ctl_mutex_itf =
+		    set_bits32(mctl->ctl_mutex_itf, 0x2, 2, 0);
+		mctl->ctl_mutex_dbuf =
+		    set_bits32(mctl->ctl_mutex_dbuf, 0x2, 2, 0);
+	} else {
+		;
+	}
+
+	mctl->ctl_mutex_ov = set_bits32(mctl->ctl_mutex_ov, 1 << ovl_idx, 4, 0);
+
+	mctl_sys = &(hisifd->dss_module.mctl_sys);
+	hisifd->dss_module.mctl_sys_used = 1;
+
+	mctl_sys->chn_ov_sel[ovl_idx] =
+	    set_bits32(mctl_sys->chn_ov_sel[ovl_idx], 0x8, 4, 0);
+	mctl_sys->chn_ov_sel_used[ovl_idx] = 1;
+
+	if ((ovl_idx == DSS_OVL0) || (ovl_idx == DSS_OVL1)) {
+		if (is_first_ov_block) {
+			mctl_sys->ov_flush_en[ovl_idx] =
+			    set_bits32(mctl_sys->ov_flush_en[ovl_idx], 0xd, 4, 0);
+		} else {
+			mctl_sys->ov_flush_en[ovl_idx] =
+			    set_bits32(mctl_sys->ov_flush_en[ovl_idx], 0x1, 1, 0);
+		}
+		mctl_sys->ov_flush_en_used[ovl_idx] = 1;
+	} else {
+		mctl_sys->ov_flush_en[ovl_idx] =
+		    set_bits32(mctl_sys->ov_flush_en[ovl_idx], 0x1, 1, 0);
+		mctl_sys->ov_flush_en_used[ovl_idx] = 1;
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+ ** DSS OVL
+ */
+static dss_ovl_alpha_t g_ovl_alpha[DSS_BLEND_MAX] = {
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0},
+	{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{3, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0},
+	{1, 0, 0, 0, 0, 0, 3, 0, 0, 1, 0},
+	{0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0},
+	{3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 0},
+	{3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
+	{3, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0},
+	{3, 0, 0, 0, 0, 0, 3, 0, 0, 1, 0},
+	{3, 0, 0, 0, 1, 0, 3, 0, 0, 1, 0},
+	{1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0},
+	{3, 0, 0, 0, 1, 0, 3, 0, 0, 0, 1},
+	{3, 0, 0, 0, 1, 0, 3, 2, 0, 0, 0},
+	{3, 0, 0, 0, 1, 1, 3, 1, 0, 0, 1},
+	{2, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0},
+	{1, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0},
+	{0, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0},
+	{3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0},
+	{2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{2, 2, 0, 0, 0, 0, 3, 2, 0, 0, 0},
+	{3, 2, 0, 0, 0, 0, 2, 2, 0, 0, 0},
+	{2, 2, 0, 0, 0, 0, 2, 2, 0, 0, 0},
+	{3, 2, 0, 0, 0, 0, 3, 2, 0, 0, 0},
+	{2, 1, 0, 0, 0, 0, 3, 2, 0, 0, 0},
+	{2, 1, 0, 0, 0, 0, 3, 1, 0, 0, 1},
+	{0, 0, 0, 0, 0, 1, 3, 0, 1, 0, 0},
+
+	{2, 1, 0, 0, 0, 1, 3, 2, 0, 0, 0},
+	{2, 1, 0, 0, 0, 1, 3, 1, 0, 0, 1},
+	{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0},
+};
+
+static uint32_t get_ovl_blending_mode(dss_overlay_t *pov_req,
+				      dss_layer_t *layer)
+{
+	uint32_t blend_mode = 0;
+	bool has_per_pixel_alpha = false;
+
+	BUG_ON(layer == NULL);
+
+	has_per_pixel_alpha = hal_format_has_alpha(layer->img.format);
+
+	/* delete it for DTS2015061204735 and DTS2015060408590 */
+	/*
+	   if (layer->layer_idx == 0) {
+	   if (has_per_pixel_alpha) {
+	   blend_mode = DSS_BLEND_SRC;
+	   } else {
+	   blend_mode= DSS_BLEND_FIX_PER17;
+	   }
+	   } else
+	 */
+	{
+		if (layer->blending == HISI_FB_BLENDING_PREMULT) {
+			if (has_per_pixel_alpha) {
+				blend_mode =
+				    (layer->glb_alpha <
+				     0xFF) ? DSS_BLEND_FIX_PER12 :
+				    DSS_BLEND_SRC_OVER_DST;
+			} else {
+				blend_mode =
+				    (layer->glb_alpha <
+				     0xFF) ? DSS_BLEND_FIX_PER8 : DSS_BLEND_SRC;
+			}
+		} else if (layer->blending == HISI_FB_BLENDING_COVERAGE) {
+			if (has_per_pixel_alpha) {
+				blend_mode =
+				    (layer->glb_alpha <
+				     0xFF) ? DSS_BLEND_FIX_PER13 :
+				    DSS_BLEND_FIX_OVER;
+			} else {
+				blend_mode =
+				    (layer->glb_alpha <
+				     0xFF) ? DSS_BLEND_FIX_PER8 : DSS_BLEND_SRC;
+			}
+		} else {
+			if (has_per_pixel_alpha) {
+				blend_mode = DSS_BLEND_SRC;
+			} else {
+				blend_mode = DSS_BLEND_FIX_PER17;
+			}
+		}
+	}
+
+	if (g_debug_ovl_online_composer) {
+		HISI_FB_INFO
+		    ("layer_idx(%d), blending=%d, fomat=%d, "
+		     "has_per_pixel_alpha=%d, blend_mode=%d.\n",
+		     layer->layer_idx, layer->blending, layer->img.format,
+		     has_per_pixel_alpha, blend_mode);
+	}
+
+	return blend_mode;
+}
+
+static void hisi_dss_ovl_init(char __iomem *ovl_base, dss_ovl_t *s_ovl,
+			      int ovl_idx)
+{
+	int i = 0;
+
+	BUG_ON(ovl_base == NULL);
+	BUG_ON(s_ovl == NULL);
+
+	memset(s_ovl, 0, sizeof(dss_ovl_t));
+
+	s_ovl->ovl_size = inp32(ovl_base + OVL_SIZE);
+	s_ovl->ovl_bg_color = inp32(ovl_base + OVL_BG_COLOR);
+	s_ovl->ovl_dst_startpos = inp32(ovl_base + OVL_DST_STARTPOS);
+	s_ovl->ovl_dst_endpos = inp32(ovl_base + OVL_DST_ENDPOS);
+	s_ovl->ovl_gcfg = inp32(ovl_base + OVL_GCFG);
+
+	if ((ovl_idx == DSS_OVL1) || (ovl_idx == DSS_OVL3)) {
+		for (i = 0; i < OVL_2LAYER_NUM; i++) {
+			s_ovl->ovl_layer[i].layer_pos =
+			    inp32(ovl_base + OVL_LAYER0_POS + i * 0x3C);
+			s_ovl->ovl_layer[i].layer_size =
+			    inp32(ovl_base + OVL_LAYER0_SIZE + i * 0x3C);
+			s_ovl->ovl_layer[i].layer_pattern =
+			    inp32(ovl_base + OVL_LAYER0_PATTERN + i * 0x3C);
+			s_ovl->ovl_layer[i].layer_alpha =
+			    inp32(ovl_base + OVL_LAYER0_ALPHA + i * 0x3C);
+			s_ovl->ovl_layer[i].layer_cfg =
+			    inp32(ovl_base + OVL_LAYER0_CFG + i * 0x3C);
+
+			s_ovl->ovl_layer_pos[i].layer_pspos =
+			    inp32(ovl_base + OVL_LAYER0_PSPOS + i * 0x3C);
+			s_ovl->ovl_layer_pos[i].layer_pepos =
+			    inp32(ovl_base + OVL_LAYER0_PEPOS + i * 0x3C);
+		}
+
+		s_ovl->ovl_block_size = inp32(ovl_base + OVL2_BLOCK_SIZE);
+	} else {
+		for (i = 0; i < OVL_6LAYER_NUM; i++) {
+			s_ovl->ovl_layer[i].layer_pos =
+			    inp32(ovl_base + OVL_LAYER0_POS + i * 0x3C);
+			s_ovl->ovl_layer[i].layer_size =
+			    inp32(ovl_base + OVL_LAYER0_SIZE + i * 0x3C);
+			s_ovl->ovl_layer[i].layer_pattern =
+			    inp32(ovl_base + OVL_LAYER0_PATTERN + i * 0x3C);
+			s_ovl->ovl_layer[i].layer_alpha =
+			    inp32(ovl_base + OVL_LAYER0_ALPHA + i * 0x3C);
+			s_ovl->ovl_layer[i].layer_cfg =
+			    inp32(ovl_base + OVL_LAYER0_CFG + i * 0x3C);
+
+			s_ovl->ovl_layer_pos[i].layer_pspos =
+			    inp32(ovl_base + OVL_LAYER0_PSPOS + i * 0x3C);
+			s_ovl->ovl_layer_pos[i].layer_pepos =
+			    inp32(ovl_base + OVL_LAYER0_PEPOS + i * 0x3C);
+		}
+
+		s_ovl->ovl_block_size = inp32(ovl_base + OVL6_BLOCK_SIZE);
+	}
+}
+
+static void hisi_dss_ovl_set_reg(struct hisi_fb_data_type *hisifd,
+				 char __iomem *ovl_base, dss_ovl_t *s_ovl,
+				 int ovl_idx)
+{
+	int i = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(ovl_base == NULL);
+	BUG_ON(s_ovl == NULL);
+
+	if ((ovl_idx == DSS_OVL1) || (ovl_idx == DSS_OVL3)) {
+		hisifd->set_reg(hisifd, ovl_base + OVL2_REG_DEFAULT, 0x1, 32, 0);
+		hisifd->set_reg(hisifd, ovl_base + OVL2_REG_DEFAULT, 0x0, 32, 0);
+	} else {
+		hisifd->set_reg(hisifd, ovl_base + OVL6_REG_DEFAULT, 0x1, 32, 0);
+		hisifd->set_reg(hisifd, ovl_base + OVL6_REG_DEFAULT, 0x0, 32, 0);
+	}
+
+	hisifd->set_reg(hisifd, ovl_base + OVL_SIZE, s_ovl->ovl_size, 32, 0);
+	hisifd->set_reg(hisifd, ovl_base + OVL_BG_COLOR,
+			s_ovl->ovl_bg_color, 32, 0);
+	hisifd->set_reg(hisifd, ovl_base + OVL_DST_STARTPOS,
+			s_ovl->ovl_dst_startpos, 32, 0);
+	hisifd->set_reg(hisifd, ovl_base + OVL_DST_ENDPOS,
+			s_ovl->ovl_dst_endpos, 32, 0);
+	hisifd->set_reg(hisifd, ovl_base + OVL_GCFG, s_ovl->ovl_gcfg, 32, 0);
+
+	if ((ovl_idx == DSS_OVL1) || (ovl_idx == DSS_OVL3)) {
+		for (i = 0; i < OVL_2LAYER_NUM; i++) {
+			if (s_ovl->ovl_layer_used[i] == 1) {
+				hisifd->set_reg(hisifd,
+						ovl_base + OVL_LAYER0_POS + i * 0x3C,
+						s_ovl->ovl_layer[i].layer_pos, 32, 0);
+				hisifd->set_reg(hisifd,
+						ovl_base + OVL_LAYER0_SIZE + i * 0x3C,
+						s_ovl->ovl_layer[i].layer_size, 32, 0);
+				hisifd->set_reg(hisifd,
+						ovl_base + OVL_LAYER0_PATTERN + i * 0x3C,
+						s_ovl->ovl_layer[i].layer_pattern, 32, 0);
+				hisifd->set_reg(hisifd,
+						ovl_base + OVL_LAYER0_ALPHA + i * 0x3C,
+						s_ovl->ovl_layer[i].layer_alpha, 32, 0);
+				hisifd->set_reg(hisifd,
+						ovl_base + OVL_LAYER0_CFG + i * 0x3C,
+						s_ovl->ovl_layer[i].layer_cfg, 32, 0);
+
+				hisifd->set_reg(hisifd,
+						ovl_base + OVL_LAYER0_PSPOS + i * 0x3C,
+						s_ovl->ovl_layer_pos[i].layer_pspos, 32, 0);
+				hisifd->set_reg(hisifd,
+						ovl_base + OVL_LAYER0_PEPOS + i * 0x3C,
+						s_ovl->ovl_layer_pos[i].layer_pepos, 32, 0);
+			} else {
+				hisifd->set_reg(hisifd,
+						ovl_base + OVL_LAYER0_POS + i * 0x3C,
+						s_ovl->ovl_layer[i].layer_pos, 32, 0);
+				hisifd->set_reg(hisifd,
+						ovl_base + OVL_LAYER0_SIZE + i * 0x3C,
+						s_ovl->ovl_layer[i].layer_size, 32, 0);
+				hisifd->set_reg(hisifd,
+						ovl_base + OVL_LAYER0_CFG + i * 0x3C,
+						s_ovl->ovl_layer[i].layer_cfg, 32, 0);
+			}
+		}
+
+		hisifd->set_reg(hisifd, ovl_base + OVL2_BLOCK_SIZE,
+				s_ovl->ovl_block_size, 32, 0);
+	} else {
+		for (i = 0; i < OVL_6LAYER_NUM; i++) {
+			if (s_ovl->ovl_layer_used[i] == 1) {
+				hisifd->set_reg(hisifd,
+						ovl_base + OVL_LAYER0_POS + i * 0x3C,
+						s_ovl->ovl_layer[i].layer_pos, 32, 0);
+				hisifd->set_reg(hisifd,
+						ovl_base + OVL_LAYER0_SIZE + i * 0x3C,
+						s_ovl->ovl_layer[i].layer_size, 32, 0);
+				hisifd->set_reg(hisifd,
+						ovl_base + OVL_LAYER0_PATTERN + i * 0x3C,
+						s_ovl->ovl_layer[i].layer_pattern, 32, 0);
+				hisifd->set_reg(hisifd,
+						ovl_base + OVL_LAYER0_ALPHA + i * 0x3C,
+						s_ovl->ovl_layer[i].layer_alpha, 32, 0);
+				hisifd->set_reg(hisifd,
+						ovl_base + OVL_LAYER0_CFG + i * 0x3C,
+						s_ovl->ovl_layer[i].layer_cfg, 32, 0);
+
+				hisifd->set_reg(hisifd,
+						ovl_base + OVL_LAYER0_PSPOS + i * 0x3C,
+						s_ovl->ovl_layer_pos[i].layer_pspos, 32, 0);
+				hisifd->set_reg(hisifd,
+						ovl_base + OVL_LAYER0_PEPOS +i * 0x3C,
+						s_ovl->ovl_layer_pos[i].layer_pepos, 32, 0);
+			} else {
+				hisifd->set_reg(hisifd,
+						ovl_base + OVL_LAYER0_POS +i * 0x3C,
+						s_ovl->ovl_layer[i].layer_pos, 32, 0);
+				hisifd->set_reg(hisifd,
+						ovl_base + OVL_LAYER0_SIZE + i * 0x3C,
+						s_ovl->ovl_layer[i].layer_size, 32, 0);
+				hisifd->set_reg(hisifd,
+						ovl_base + OVL_LAYER0_CFG + i * 0x3C,
+						s_ovl->ovl_layer[i].layer_cfg, 32, 0);
+			}
+		}
+
+		hisifd->set_reg(hisifd, ovl_base + OVL6_BLOCK_SIZE,
+				s_ovl->ovl_block_size, 32, 0);
+	}
+}
+
+void hisi_dss_ov_set_reg_default_value(struct hisi_fb_data_type *hisifd,
+				       char __iomem *ovl_base, int ovl_idx)
+{
+	BUG_ON(hisifd == NULL);
+	BUG_ON(ovl_base == NULL);
+
+	if ((ovl_idx == DSS_OVL1) || (ovl_idx == DSS_OVL3)) {
+		hisifd->set_reg(hisifd, ovl_base + OVL2_REG_DEFAULT, 0x1, 32,
+				0);
+		hisifd->set_reg(hisifd, ovl_base + OVL2_REG_DEFAULT, 0x0, 32,
+				0);
+	} else {
+		hisifd->set_reg(hisifd, ovl_base + OVL6_REG_DEFAULT, 0x1, 32,
+				0);
+		hisifd->set_reg(hisifd, ovl_base + OVL6_REG_DEFAULT, 0x0, 32,
+				0);
+	}
+}
+
+int hisi_dss_ovl_base_config(struct hisi_fb_data_type *hisifd,
+			     dss_overlay_t *pov_req,
+			     dss_overlay_block_t *pov_h_block,
+			     dss_rect_t *wb_ov_block_rect, int ovl_idx,
+			     int ov_h_block_idx)
+{
+	dss_ovl_t *ovl = NULL;
+	int img_width = 0;
+	int img_height = 0;
+	int block_size = 0x7FFF;
+	int temp = 0;
+	int i = 0;
+	int m = 0;
+
+	dss_overlay_block_t *pov_h_block_infos_tmp = NULL;
+	dss_overlay_block_t *pov_h_block_tmp = NULL;
+	dss_layer_t *layer = NULL;
+	int pov_h_block_idx = 0;
+	int layer_idx = 0;
+	bool has_base = false;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON((ovl_idx < DSS_OVL0) || (ovl_idx >= DSS_OVL_IDX_MAX));
+
+	if (pov_req && pov_req->wb_layer_infos[0].chn_idx == DSS_WCHN_W2) {
+		return 0;
+	}
+
+	ovl = &(hisifd->dss_module.ov[ovl_idx]);
+	hisifd->dss_module.ov_used[ovl_idx] = 1;
+
+	if (wb_ov_block_rect) {
+		img_width = wb_ov_block_rect->w;
+		img_height = wb_ov_block_rect->h;
+	} else {
+		if ((!pov_req)
+		    || (pov_req->dirty_rect.x == 0 && pov_req->dirty_rect.y == 0
+			&& pov_req->dirty_rect.w == 0
+			&& pov_req->dirty_rect.h == 0)) {
+			img_width = get_panel_xres(hisifd);
+			img_height = get_panel_yres(hisifd);
+		} else {
+			img_width = pov_req->dirty_rect.w;
+			img_height = pov_req->dirty_rect.h;
+		}
+	}
+
+	if (pov_h_block && (pov_req->ov_block_nums != 0)) {
+		if (pov_req->ov_block_nums > 1) {
+			pov_h_block_infos_tmp =
+			    (dss_overlay_block_t *) (pov_req->ov_block_infos_ptr);
+			for (m = ov_h_block_idx; m < pov_req->ov_block_nums;
+			     m++) {
+				pov_h_block_tmp = &(pov_h_block_infos_tmp[m]);
+				has_base = false;
+
+				for (i = 0; i < pov_h_block_tmp->layer_nums;
+				     i++) {
+					layer =
+					    &(pov_h_block_tmp->layer_infos[i]);
+					if (layer->need_cap & CAP_BASE) {
+						HISI_FB_INFO
+						    ("layer%d is base, i=%d!\n",
+						     layer->layer_idx, i);
+						has_base = true;
+						continue;
+					}
+
+					layer_idx = i;
+					if (has_base) {
+						layer_idx = i - 1;
+					}
+
+					if (layer_idx >= pov_h_block_idx) {
+						ovl->ovl_layer[layer_idx].layer_pos =
+						    set_bits32(ovl->ovl_layer
+							       [layer_idx].layer_pos, 0, 15, 0);
+						ovl->ovl_layer[layer_idx].layer_pos =
+						    set_bits32(ovl->ovl_layer
+							       [layer_idx].layer_pos,
+							       img_height, 15, 16);
+
+						ovl->ovl_layer[layer_idx].layer_size =
+						    set_bits32(ovl->ovl_layer
+							       [layer_idx].layer_size,
+							       img_width, 15, 0);
+						ovl->ovl_layer[layer_idx].layer_size =
+						    set_bits32(ovl->ovl_layer
+							       [layer_idx].layer_size,
+							       img_height + 1, 15, 16);
+						ovl->ovl_layer[layer_idx].layer_cfg =
+						    set_bits32(ovl->ovl_layer
+							       [layer_idx].layer_cfg,
+							       0x1, 1, 0);
+
+						if (layer->need_cap & (CAP_DIM |
+								CAP_PURE_COLOR)) {
+
+							ovl->ovl_layer[layer_idx].layer_pattern =
+							    set_bits32(ovl->ovl_layer
+								       [layer_idx].layer_pattern,
+								       layer->color, 32, 0);
+							ovl->ovl_layer[layer_idx].layer_cfg =
+							    set_bits32(ovl->ovl_layer
+								       [layer_idx].layer_cfg,
+								       0x1, 1, 0);
+							ovl->ovl_layer[layer_idx].layer_cfg =
+							    set_bits32(ovl->ovl_layer
+								       [layer_idx].layer_cfg,
+								       0x1, 1, 8);
+						} else {
+							ovl->ovl_layer[layer_idx].layer_pattern =
+							    set_bits32(ovl->ovl_layer
+								       [layer_idx].layer_pattern,
+								       0x0, 32, 0);
+							ovl->ovl_layer[layer_idx].layer_cfg =
+							    set_bits32(ovl->ovl_layer
+								       [layer_idx].layer_cfg,
+								       0x1, 1, 0);
+							ovl->ovl_layer[layer_idx].layer_cfg =
+							    set_bits32(ovl->ovl_layer
+								       [layer_idx].layer_cfg,
+								       0x0, 1, 8);
+						}
+
+						ovl->ovl_layer_used[layer_idx] = 1;
+						pov_h_block_idx = layer_idx + 1;
+					}
+				}
+			}
+		}
+
+		if (wb_ov_block_rect) {
+			if ((pov_req->wb_layer_infos[0].transform &
+					HISI_FB_TRANSFORM_ROT_90)
+			   || (pov_req->wb_layer_infos[1].transform &
+			   		HISI_FB_TRANSFORM_ROT_90)) {
+				block_size = DSS_HEIGHT(wb_ov_block_rect->h);
+			} else {
+				temp =
+				    pov_h_block->ov_block_rect.y +
+				    DSS_HEIGHT(pov_h_block->ov_block_rect.h) -
+				    wb_ov_block_rect->y;
+				if (temp >= wb_ov_block_rect->h) {
+					block_size =
+					    DSS_HEIGHT(wb_ov_block_rect->h);
+				} else {
+					block_size = temp;
+				}
+			}
+		} else {
+			block_size =
+			    pov_h_block->ov_block_rect.y +
+			    DSS_HEIGHT(pov_h_block->ov_block_rect.h);
+		}
+	}
+
+	ovl->ovl_size = set_bits32(ovl->ovl_size, DSS_WIDTH(img_width), 15, 0);
+	ovl->ovl_size =
+	    set_bits32(ovl->ovl_size, DSS_HEIGHT(img_height), 15, 16);
+#ifdef CONFIG_HISI_FB_OV_BASE_USED
+	ovl->ovl_bg_color = set_bits32(ovl->ovl_bg_color, 0xFFFF0000, 32, 0);
+#else
+	ovl->ovl_bg_color = set_bits32(ovl->ovl_bg_color, 0xFF000000, 32, 0);
+#endif
+	ovl->ovl_dst_startpos = set_bits32(ovl->ovl_dst_startpos, 0x0, 32, 0);
+	ovl->ovl_dst_endpos =
+	    set_bits32(ovl->ovl_dst_endpos, DSS_WIDTH(img_width), 15, 0);
+	ovl->ovl_dst_endpos =
+	    set_bits32(ovl->ovl_dst_endpos, DSS_HEIGHT(img_height), 15, 16);
+	ovl->ovl_gcfg = set_bits32(ovl->ovl_gcfg, 0x1, 1, 0);
+	ovl->ovl_gcfg = set_bits32(ovl->ovl_gcfg, 0x1, 1, 16);
+	ovl->ovl_block_size =
+	    set_bits32(ovl->ovl_block_size, block_size, 15, 16);
+
+	return 0;
+}
+
+int hisi_dss_ovl_layer_config(struct hisi_fb_data_type *hisifd,
+			      dss_overlay_t *pov_req, dss_layer_t *layer,
+			      dss_rect_t *wb_ov_block_rect, bool has_base)
+{
+	dss_ovl_t *ovl = NULL;
+	int ovl_idx = 0;
+	int layer_idx = 0;
+	int blend_mode = 0;
+	dss_rect_t wb_ov_rect;
+	dss_rect_t dst_rect;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(layer == NULL);
+
+	ovl_idx = hisifd->ov_req.ovl_idx;
+	layer_idx = layer->layer_idx;
+
+	if (layer->chn_idx == DSS_RCHN_V2) {
+		return 0;
+	}
+
+	BUG_ON((ovl_idx < DSS_OVL0) || (ovl_idx >= DSS_OVL_IDX_MAX));
+	ovl = &(hisifd->dss_module.ov[ovl_idx]);
+	hisifd->dss_module.ov_used[ovl_idx] = 1;
+
+	if (layer->need_cap & CAP_BASE) {
+		ovl->ovl_bg_color =
+		    set_bits32(ovl->ovl_bg_color, layer->color, 32, 0);
+		ovl->ovl_gcfg = set_bits32(ovl->ovl_gcfg, 0x1, 1, 16);
+		return 0;
+	}
+
+	if (layer->glb_alpha < 0) {
+		layer->glb_alpha = 0;
+		HISI_FB_ERR("layer's glb_alpha(0x%x) is out of range!",
+			    layer->glb_alpha);
+	} else if (layer->glb_alpha > 0xFF) {
+		layer->glb_alpha = 0xFF;
+		HISI_FB_ERR("layer's glb_alpha(0x%x) is out of range!",
+			    layer->glb_alpha);
+	}
+
+	blend_mode = get_ovl_blending_mode(pov_req, layer);
+	BUG_ON((blend_mode < 0) || (blend_mode >= DSS_BLEND_MAX));
+
+	if (has_base) {
+		layer_idx -= 1;
+		if (layer_idx < 0) {
+			HISI_FB_ERR("layer_idx(%d) is out of range!\n",
+				    layer_idx);
+			return -EINVAL;
+		}
+	}
+
+	ovl->ovl_layer_used[layer_idx] = 1;
+
+	if ((layer->chn_idx == DSS_RCHN_V0)
+	    && layer->block_info.arsr2p_left_clip) {
+		dst_rect.x =
+		    layer->dst_rect.x + layer->block_info.arsr2p_left_clip;
+		dst_rect.y = layer->dst_rect.y;
+		dst_rect.w =
+		    layer->dst_rect.w - layer->block_info.arsr2p_left_clip;
+		dst_rect.h = layer->dst_rect.h;
+	} else {
+		dst_rect = layer->dst_rect;
+	}
+
+	if (wb_ov_block_rect) {
+		wb_ov_rect.x = pov_req->wb_ov_rect.x + wb_ov_block_rect->x;
+		wb_ov_rect.y = pov_req->wb_ov_rect.y;
+
+		ovl->ovl_layer[layer_idx].layer_pos =
+		    set_bits32(ovl->ovl_layer[layer_idx].layer_pos,
+			       (dst_rect.x - wb_ov_rect.x), 15, 0);
+		ovl->ovl_layer[layer_idx].layer_pos =
+		    set_bits32(ovl->ovl_layer[layer_idx].layer_pos,
+			       (dst_rect.y - wb_ov_rect.y), 15, 16);
+
+		ovl->ovl_layer[layer_idx].layer_size =
+		    set_bits32(ovl->ovl_layer[layer_idx].layer_size,
+			       (dst_rect.x - wb_ov_rect.x +
+				DSS_WIDTH(dst_rect.w)), 15, 0);
+		ovl->ovl_layer[layer_idx].layer_size =
+		    set_bits32(ovl->ovl_layer[layer_idx].layer_size,
+			       (dst_rect.y - wb_ov_rect.y +
+				DSS_HEIGHT(dst_rect.h)), 15, 16);
+	} else {
+		ovl->ovl_layer[layer_idx].layer_pos =
+		    set_bits32(ovl->ovl_layer[layer_idx].layer_pos, dst_rect.x,
+			       15, 0);
+		ovl->ovl_layer[layer_idx].layer_pos =
+		    set_bits32(ovl->ovl_layer[layer_idx].layer_pos, dst_rect.y,
+			       15, 16);
+
+		ovl->ovl_layer[layer_idx].layer_size =
+		    set_bits32(ovl->ovl_layer[layer_idx].layer_size,
+			       DSS_WIDTH(dst_rect.x + dst_rect.w), 15, 0);
+		ovl->ovl_layer[layer_idx].layer_size =
+		    set_bits32(ovl->ovl_layer[layer_idx].layer_size,
+			       DSS_HEIGHT(dst_rect.y + dst_rect.h), 15, 16);
+	}
+
+	ovl->ovl_layer[layer_idx].layer_alpha =
+	    set_bits32(ovl->ovl_layer[layer_idx].layer_alpha,
+		       ((layer->glb_alpha << 0) |
+		        (g_ovl_alpha[blend_mode].fix_mode << 8) |
+				(g_ovl_alpha[blend_mode].dst_pmode << 9) |
+				(g_ovl_alpha[blend_mode].alpha_offdst << 10) |
+				(g_ovl_alpha[blend_mode].dst_gmode << 12) |
+				(g_ovl_alpha[blend_mode].dst_amode << 14) |
+				(layer->glb_alpha <<16) |
+				(g_ovl_alpha[blend_mode].alpha_smode << 24) |
+				(g_ovl_alpha[blend_mode].src_pmode << 25) |
+				(g_ovl_alpha[blend_mode].src_lmode << 26) |
+				(g_ovl_alpha[blend_mode].alpha_offdst << 27) |
+				(g_ovl_alpha[blend_mode].src_gmode << 28) |
+				(g_ovl_alpha[blend_mode].src_amode << 30)), 32, 0);
+
+	if (layer->need_cap & (CAP_DIM | CAP_PURE_COLOR)) {
+		ovl->ovl_layer[layer_idx].layer_pattern =
+		    set_bits32(ovl->ovl_layer[layer_idx].layer_pattern,
+			       layer->color, 32, 0);
+		ovl->ovl_layer[layer_idx].layer_cfg =
+		    set_bits32(ovl->ovl_layer[layer_idx].layer_cfg, 0x1, 1, 0);
+		ovl->ovl_layer[layer_idx].layer_cfg =
+		    set_bits32(ovl->ovl_layer[layer_idx].layer_cfg, 0x1, 1, 8);
+	} else {
+		ovl->ovl_layer[layer_idx].layer_pattern =
+		    set_bits32(ovl->ovl_layer[layer_idx].layer_pattern, 0x0, 32,
+			       0);
+		ovl->ovl_layer[layer_idx].layer_cfg =
+		    set_bits32(ovl->ovl_layer[layer_idx].layer_cfg, 0x1, 1, 0);
+		ovl->ovl_layer[layer_idx].layer_cfg =
+		    set_bits32(ovl->ovl_layer[layer_idx].layer_cfg, 0x0, 1, 8);
+	}
+
+	ovl->ovl_layer_pos[layer_idx].layer_pspos =
+	    set_bits32(ovl->ovl_layer_pos[layer_idx].layer_pspos, dst_rect.x,
+		       15, 0);
+	ovl->ovl_layer_pos[layer_idx].layer_pspos =
+	    set_bits32(ovl->ovl_layer_pos[layer_idx].layer_pspos, dst_rect.y,
+		       15, 16);
+	ovl->ovl_layer_pos[layer_idx].layer_pepos =
+	    set_bits32(ovl->ovl_layer_pos[layer_idx].layer_pepos,
+		       DSS_WIDTH(dst_rect.x + dst_rect.w), 15, 0);
+	ovl->ovl_layer_pos[layer_idx].layer_pepos =
+	    set_bits32(ovl->ovl_layer_pos[layer_idx].layer_pepos,
+		       DSS_HEIGHT(dst_rect.y + dst_rect.h), 15, 16);
+
+	return 0;
+}
+
+/*******************************************************************************
+ ** dirty_region_updt
+ */
+static void hisi_dss_dirty_region_dbuf_set_reg(struct hisi_fb_data_type *hisifd,
+					       char __iomem *dss_base,
+					       dirty_region_updt_t *
+					       s_dirty_region_updt)
+{
+	BUG_ON(hisifd == NULL);
+	BUG_ON(dss_base == NULL);
+	BUG_ON(s_dirty_region_updt == NULL);
+
+	hisifd->set_reg(hisifd, dss_base + DSS_DBUF0_OFFSET + DBUF_FRM_SIZE,
+			s_dirty_region_updt->dbuf_frm_size, 32, 0);
+	hisifd->set_reg(hisifd, dss_base + DSS_DBUF0_OFFSET + DBUF_FRM_HSIZE,
+			s_dirty_region_updt->dbuf_frm_hsize, 32, 0);
+	hisifd->set_reg(hisifd, dss_base + DSS_DPP_OFFSET + DPP_IMG_SIZE_BEF_SR,
+			((s_dirty_region_updt->dpp_img_vrt_bef_sr << 16) |
+			  s_dirty_region_updt->dpp_img_hrz_bef_sr), 32, 0);
+	hisifd->set_reg(hisifd, dss_base + DSS_DPP_OFFSET + DPP_IMG_SIZE_AFT_SR,
+			((s_dirty_region_updt->dpp_img_vrt_aft_sr << 16) |
+			  s_dirty_region_updt->dpp_img_hrz_aft_sr), 32, 0);
+}
+
+static void hisi_dss_dirty_region_updt_set_reg(struct hisi_fb_data_type *hisifd,
+					       char __iomem *dss_base,
+					       dirty_region_updt_t *
+					       s_dirty_region_updt)
+{
+	BUG_ON(hisifd == NULL);
+	BUG_ON(dss_base == NULL);
+	BUG_ON(s_dirty_region_updt == NULL);
+
+	set_reg(dss_base + DSS_MIPI_DSI0_OFFSET + MIPIDSI_EDPI_CMD_SIZE_OFFSET,
+		s_dirty_region_updt->edpi_cmd_size, 32, 0);
+	if (is_dual_mipi_panel(hisifd)) {
+		set_reg(dss_base + DSS_MIPI_DSI1_OFFSET +
+			MIPIDSI_EDPI_CMD_SIZE_OFFSET,
+			s_dirty_region_updt->edpi_cmd_size, 32, 0);
+	}
+
+	set_reg(dss_base + DSS_LDI0_OFFSET + LDI_DPI0_HRZ_CTRL0,
+		s_dirty_region_updt->ldi_dpi0_hrz_ctrl0, 29, 0);
+	set_reg(dss_base + DSS_LDI0_OFFSET + LDI_DPI0_HRZ_CTRL1,
+		s_dirty_region_updt->ldi_dpi0_hrz_ctrl1, 13, 0);
+	set_reg(dss_base + DSS_LDI0_OFFSET + LDI_DPI0_HRZ_CTRL2,
+		s_dirty_region_updt->ldi_dpi0_hrz_ctrl2, 13, 0);
+	set_reg(dss_base + DSS_LDI0_OFFSET + LDI_VRT_CTRL0,
+		s_dirty_region_updt->ldi_vrt_ctrl0, 29, 0);
+	set_reg(dss_base + DSS_LDI0_OFFSET + LDI_VRT_CTRL1,
+		s_dirty_region_updt->ldi_vrt_ctrl1, 13, 0);
+	set_reg(dss_base + DSS_LDI0_OFFSET + LDI_VRT_CTRL2,
+		s_dirty_region_updt->ldi_vrt_ctrl2, 13, 0);
+
+	if (is_dual_mipi_panel(hisifd)) {
+		set_reg(dss_base + DSS_LDI0_OFFSET + LDI_DPI1_HRZ_CTRL0,
+			s_dirty_region_updt->ldi_dpi1_hrz_ctrl0, 29, 0);
+		set_reg(dss_base + DSS_LDI0_OFFSET + LDI_DPI1_HRZ_CTRL1,
+			s_dirty_region_updt->ldi_dpi1_hrz_ctrl1, 13, 0);
+		set_reg(dss_base + DSS_LDI0_OFFSET + LDI_DPI1_HRZ_CTRL2,
+			s_dirty_region_updt->ldi_dpi1_hrz_ctrl2, 13, 0);
+	}
+
+	if (hisifd->panel_info.ifbc_type != IFBC_TYPE_NONE) {
+		if (!is_ifbc_vesa_panel(hisifd)) {
+			set_reg(dss_base + DSS_IFBC_OFFSET + IFBC_SIZE,
+				s_dirty_region_updt->ifbc_size, 32, 0);
+		} else {
+			set_reg(dss_base + DSS_DSC_OFFSET + DSC_PIC_SIZE,
+				s_dirty_region_updt->ifbc_size, 32, 0);
+		}
+	}
+}
+
+int hisi_dss_dirty_region_dbuf_config(struct hisi_fb_data_type *hisifd,
+				      dss_overlay_t *pov_req)
+{
+	struct hisi_panel_info *pinfo = NULL;
+	dirty_region_updt_t *dirty_region_updt = NULL;
+	struct dss_rect dirty = { 0 };
+
+	BUG_ON(hisifd == NULL);
+	pinfo = &(hisifd->panel_info);
+
+	if ((hisifd->index != PRIMARY_PANEL_IDX) ||
+	    !pinfo->dirty_region_updt_support)
+		return 0;
+
+	if ((!pov_req)
+	    || (pov_req->dirty_rect.x == 0 && pov_req->dirty_rect.y == 0
+		&& pov_req->dirty_rect.w == 0 && pov_req->dirty_rect.h == 0)) {
+		dirty.x = 0;
+		dirty.y = 0;
+		dirty.w = hisifd->panel_info.xres;
+		dirty.h = hisifd->panel_info.yres;
+	} else {
+		dirty = pov_req->dirty_rect;
+	}
+
+	if ((dirty.x == hisifd->dirty_region_updt.x)
+	    && (dirty.y == hisifd->dirty_region_updt.y)
+	    && (dirty.w == hisifd->dirty_region_updt.w)
+	    && (dirty.h == hisifd->dirty_region_updt.h)) {
+		return 0;
+	}
+
+	dirty_region_updt = &(hisifd->dss_module.dirty_region_updt);
+	hisifd->dss_module.dirty_region_updt_used = 1;
+	dirty_region_updt->dpp_img_hrz_bef_sr =
+	    set_bits32(dirty_region_updt->dpp_img_hrz_bef_sr,
+		       DSS_WIDTH(dirty.w), 13, 0);
+	dirty_region_updt->dpp_img_vrt_bef_sr =
+	    set_bits32(dirty_region_updt->dpp_img_vrt_bef_sr,
+		       DSS_WIDTH(dirty.h), 13, 0);
+	dirty_region_updt->dpp_img_hrz_aft_sr =
+	    set_bits32(dirty_region_updt->dpp_img_hrz_aft_sr,
+		       DSS_WIDTH(dirty.w), 13, 0);
+	dirty_region_updt->dpp_img_vrt_aft_sr =
+	    set_bits32(dirty_region_updt->dpp_img_vrt_aft_sr,
+		       DSS_WIDTH(dirty.h), 13, 0);
+
+	dirty_region_updt->dbuf_frm_size =
+	    set_bits32(dirty_region_updt->dbuf_frm_size, dirty.w * dirty.h, 27,
+		       0);
+	dirty_region_updt->dbuf_frm_hsize =
+	    set_bits32(dirty_region_updt->dbuf_frm_hsize, DSS_WIDTH(dirty.w),
+		       13, 0);
+
+	return 0;
+}
+
+void hisi_dss_dirty_region_updt_config(struct hisi_fb_data_type *hisifd,
+				       dss_overlay_t *pov_req)
+{
+	struct hisi_fb_panel_data *pdata = NULL;
+	struct hisi_panel_info *pinfo = NULL;
+	dirty_region_updt_t *dirty_region_updt = NULL;
+	struct dss_rect dirty = { 0 };
+	uint32_t h_porch_pading = 0;
+	uint32_t v_porch_pading = 0;
+	dss_rect_t rect = { 0 };
+	uint32_t max_latency = 0;
+	uint32_t bits_per_pixel = 0;
+	uint32_t h_front_porch_max = 0;
+	uint32_t h_front_porch = 0;
+	uint32_t h_back_porch = 0;
+
+	BUG_ON(hisifd == NULL);
+	pdata = dev_get_platdata(&hisifd->pdev->dev);
+	BUG_ON(pdata == NULL);
+	pinfo = &(hisifd->panel_info);
+
+	if ((hisifd->index != PRIMARY_PANEL_IDX) ||
+	    !pinfo->dirty_region_updt_support)
+		return;
+
+	if ((!pov_req) || (pov_req->dirty_rect.w == 0)
+	    || (pov_req->dirty_rect.h == 0)) {
+		dirty.x = 0;
+		dirty.y = 0;
+		dirty.w = hisifd->panel_info.xres;
+		dirty.h = hisifd->panel_info.yres;
+	} else {
+		dirty = pov_req->dirty_rect;
+	}
+
+	if (hisifd->panel_info.xres >= dirty.w) {
+		h_porch_pading = hisifd->panel_info.xres - dirty.w;
+	}
+
+	if (hisifd->panel_info.yres >= dirty.h) {
+		v_porch_pading = hisifd->panel_info.yres - dirty.h;
+	}
+
+	if ((dirty.x == hisifd->dirty_region_updt.x)
+	    && (dirty.y == hisifd->dirty_region_updt.y)
+	    && (dirty.w == hisifd->dirty_region_updt.w)
+	    && (dirty.h == hisifd->dirty_region_updt.h)) {
+		return;
+	}
+
+	rect.x = 0;
+	rect.y = 0;
+	rect.w = dirty.w;
+	rect.h = dirty.h;
+	mipi_ifbc_get_rect(hisifd, &rect);
+
+	h_front_porch = pinfo->ldi.h_front_porch;
+	h_back_porch = pinfo->ldi.h_back_porch;
+
+	h_porch_pading = h_porch_pading * rect.w / dirty.w;
+	v_porch_pading = v_porch_pading * rect.h / dirty.h;
+
+	if (pinfo->bpp == LCD_RGB888)
+		bits_per_pixel = 24;
+	else if (pinfo->bpp == LCD_RGB565)
+		bits_per_pixel = 16;
+	else
+		bits_per_pixel = 24;
+
+	if (pinfo->pxl_clk_rate_div == 0)
+		pinfo->pxl_clk_rate_div = 1;
+	max_latency =
+	    (rect.w * bits_per_pixel / 8 + 1 + 6) / (pinfo->mipi.lane_nums + 1);
+
+	h_front_porch_max =
+	    max_latency * (pinfo->pxl_clk_rate / pinfo->pxl_clk_rate_div) /
+	    pinfo->dsi_phy_ctrl.lane_byte_clk;
+	HISI_FB_DEBUG("bits_per_pixel = %d\n" "data_lane_lp2hs_time = %d\n"
+		      "max_latency = %d\n" "pxl_clk_rate = %lld\n"
+		      "pxl_clk_rate_div = %d\n"
+		      "dsi_phy_ctrl.lane_byte_clk = %lld\n"
+		      "h_front_porch_max = %d\n", bits_per_pixel,
+		      pinfo->dsi_phy_ctrl.data_lane_lp2hs_time, max_latency,
+		      pinfo->pxl_clk_rate, pinfo->pxl_clk_rate_div,
+		      pinfo->dsi_phy_ctrl.lane_byte_clk, h_front_porch_max);
+
+	if (h_front_porch > h_front_porch_max) {
+		h_back_porch += (h_front_porch - h_front_porch_max);
+		h_front_porch = h_front_porch_max;
+	}
+
+	dirty_region_updt = &(hisifd->dss_module.dirty_region_updt);
+
+	dirty_region_updt->ldi_dpi0_hrz_ctrl0 =
+	    set_bits32(dirty_region_updt->ldi_dpi0_hrz_ctrl0,
+		       (h_front_porch) | ((h_back_porch + h_porch_pading) <<
+					  16), 29, 0);
+	dirty_region_updt->ldi_dpi0_hrz_ctrl1 =
+	    set_bits32(dirty_region_updt->ldi_dpi0_hrz_ctrl1,
+		       DSS_WIDTH(pinfo->ldi.h_pulse_width), 13, 0);
+	dirty_region_updt->ldi_dpi0_hrz_ctrl2 =
+	    set_bits32(dirty_region_updt->ldi_dpi0_hrz_ctrl2, DSS_WIDTH(rect.w),
+		       13, 0);
+
+	if (is_dual_mipi_panel(hisifd)) {
+		dirty_region_updt->ldi_dpi1_hrz_ctrl0 =
+		    set_bits32(dirty_region_updt->ldi_dpi1_hrz_ctrl0,
+			       (h_back_porch + h_porch_pading) << 16, 29, 0);
+		dirty_region_updt->ldi_dpi1_hrz_ctrl1 =
+		    set_bits32(dirty_region_updt->ldi_dpi1_hrz_ctrl1,
+			       DSS_WIDTH(pinfo->ldi.h_pulse_width), 13, 0);
+		dirty_region_updt->ldi_dpi1_hrz_ctrl2 =
+		    set_bits32(dirty_region_updt->ldi_dpi1_hrz_ctrl2,
+			       DSS_WIDTH(rect.w), 13, 0);
+	}
+
+	dirty_region_updt->ldi_vrt_ctrl0 =
+	    set_bits32(dirty_region_updt->ldi_vrt_ctrl0,
+		       (pinfo->ldi.v_front_porch +
+			v_porch_pading) | ((pinfo->ldi.v_back_porch) << 16), 29,
+		       0);
+	dirty_region_updt->ldi_vrt_ctrl1 =
+	    set_bits32(dirty_region_updt->ldi_vrt_ctrl1,
+		       DSS_HEIGHT(pinfo->ldi.v_pulse_width), 13, 0);
+	dirty_region_updt->ldi_vrt_ctrl2 =
+	    set_bits32(dirty_region_updt->ldi_vrt_ctrl2, DSS_HEIGHT(rect.h), 13,
+		       0);
+
+	dirty_region_updt->edpi_cmd_size =
+	    set_bits32(dirty_region_updt->edpi_cmd_size, rect.w, 16, 0);
+
+	if (pinfo->ifbc_type != IFBC_TYPE_NONE) {
+		if ((pinfo->ifbc_type == IFBC_TYPE_VESA2X_DUAL) ||
+		    (pinfo->ifbc_type == IFBC_TYPE_VESA3X_DUAL)) {
+			dirty_region_updt->ifbc_size =
+			    set_bits32(dirty_region_updt->ifbc_size,
+				       ((DSS_WIDTH(dirty.w / 2) << 16) |
+					DSS_HEIGHT(dirty.h)), 32, 0);
+		} else {
+			dirty_region_updt->ifbc_size =
+			    set_bits32(dirty_region_updt->ifbc_size,
+				       ((DSS_WIDTH(dirty.w) << 16) |
+					DSS_HEIGHT(dirty.h)), 32, 0);
+		}
+	}
+
+	/*if (pdata && pdata->set_display_region) {
+	   pdata->set_display_region(hisifd->pdev, &dirty);
+	   } */
+
+	hisifd->dirty_region_updt = dirty;
+
+	hisi_dss_dirty_region_updt_set_reg(hisifd, hisifd->dss_base,
+					   &(hisifd->dss_module.
+					     dirty_region_updt));
+
+	if (g_debug_dirty_region_updt) {
+		HISI_FB_INFO
+		    ("dirty_region(%d,%d, %d,%d), h_porch_pading=%d, v_porch_pading=%d.\n",
+		     dirty.x, dirty.y, dirty.w, dirty.h, h_porch_pading,
+		     v_porch_pading);
+	}
+}
+
+/*******************************************************************************
+ ** WCHN
+ */
+static uint32_t hisi_calculate_display_addr_wb(bool mmu_enable,
+					       dss_wb_layer_t *wb_layer,
+					       dss_rect_t aligned_rect,
+					       dss_rect_t *ov_block_rect,
+					       int add_type)
+{
+	uint32_t addr = 0;
+	uint32_t dst_addr = 0;
+	uint32_t stride = 0;
+	uint32_t offset = 0;
+	int left = 0, top = 0;
+	int bpp = 0;
+
+	if (wb_layer->transform & HISI_FB_TRANSFORM_ROT_90) {
+		left = wb_layer->dst_rect.x;
+		top =
+		    ov_block_rect->x - wb_layer->dst_rect.x +
+		    wb_layer->dst_rect.y;
+	} else {
+		left = aligned_rect.x;
+		top = aligned_rect.y;
+	}
+
+	if (add_type == DSS_ADDR_PLANE0) {
+		stride = wb_layer->dst.stride;
+		dst_addr =
+		    mmu_enable ? wb_layer->dst.vir_addr : wb_layer->dst.
+		    phy_addr;
+	} else if (add_type == DSS_ADDR_PLANE1) {
+		stride = wb_layer->dst.stride_plane1;
+		offset = wb_layer->dst.offset_plane1;
+		dst_addr =
+		    mmu_enable ? (wb_layer->dst.vir_addr +
+				  offset) : (wb_layer->dst.phy_addr + offset);
+		top /= 2;
+	} else {
+		HISI_FB_ERR("NOT SUPPORT this add_type(%d).\n", add_type);
+		BUG_ON(1);
+	}
+
+	bpp = wb_layer->dst.bpp;
+	addr = dst_addr + left * bpp + top * stride;
+
+	return addr;
+}
+
+int hisi_dss_wdfc_config(struct hisi_fb_data_type *hisifd,
+			 dss_wb_layer_t *layer, dss_rect_t *aligned_rect,
+			 dss_rect_t *ov_block_rect)
+{
+	dss_dfc_t *dfc = NULL;
+	int chn_idx = 0;
+	dss_rect_t in_rect;
+	bool need_dither = false;
+
+	int size_hrz = 0;
+	int size_vrt = 0;
+	int dfc_fmt = 0;
+	int dfc_pix_in_num = 0;
+	int aligned_line = 0;
+	uint32_t dfc_w = 0;
+	int aligned_pixel = 0;
+
+	uint32_t left_pad = 0;
+	uint32_t right_pad = 0;
+	uint32_t top_pad = 0;
+	uint32_t bottom_pad = 0;
+
+	uint32_t addr = 0;
+	uint32_t dst_addr = 0;
+	uint32_t bpp = 0;
+	bool mmu_enable = false;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(layer == NULL);
+	BUG_ON(aligned_rect == NULL);
+
+	chn_idx = layer->chn_idx;
+
+	dfc = &(hisifd->dss_module.dfc[chn_idx]);
+	hisifd->dss_module.dfc_used[chn_idx] = 1;
+
+	dfc_fmt = hisi_pixel_format_hal2dfc(layer->dst.format);
+	if (dfc_fmt < 0) {
+		HISI_FB_ERR("layer format (%d) not support !\n",
+			    layer->dst.format);
+		return -EINVAL;
+	}
+
+	if (layer->need_cap & CAP_AFBCE) {
+		aligned_pixel = AFBC_BLOCK_ALIGN;
+	} else {
+		aligned_pixel = DMA_ALIGN_BYTES / layer->dst.bpp;
+	}
+
+	need_dither = isNeedDither(dfc_fmt);
+	if (ov_block_rect) {
+		memcpy(&in_rect, ov_block_rect, sizeof(dss_rect_t));
+	} else {
+		in_rect = layer->src_rect;
+	}
+
+	size_hrz = DSS_WIDTH(in_rect.w);
+	size_vrt = DSS_HEIGHT(in_rect.h);
+
+	if ((size_hrz + 1) % 2 == 1) {
+		size_hrz += 1;
+		dfc_w = 1;
+	}
+
+	dfc_pix_in_num = (layer->dst.bpp <= 2) ? 0x1 : 0x0;
+
+	if (layer->need_cap & CAP_AFBCE) {
+		aligned_rect->x = ALIGN_DOWN(in_rect.x, aligned_pixel);
+		aligned_rect->w =
+		    ALIGN_UP(in_rect.x - aligned_rect->x + in_rect.w + dfc_w,
+			     aligned_pixel);
+		aligned_rect->y = ALIGN_DOWN(in_rect.y, aligned_pixel);
+		aligned_rect->h =
+		    ALIGN_UP(in_rect.y - aligned_rect->y + in_rect.h,
+			     aligned_pixel);
+
+		left_pad = in_rect.x - aligned_rect->x;
+		right_pad =
+		    aligned_rect->w - (in_rect.x - aligned_rect->x + in_rect.w +
+				       dfc_w);
+		top_pad = in_rect.y - aligned_rect->y;
+		bottom_pad =
+		    aligned_rect->h - (in_rect.y - aligned_rect->y + in_rect.h);
+	} else if (layer->transform & HISI_FB_TRANSFORM_ROT_90) {
+		aligned_line = (layer->dst.bpp <= 2) ? 32 : 16;
+		mmu_enable = (layer->dst.mmu_enable == 1) ? true : false;
+		dst_addr =
+		    mmu_enable ? layer->dst.vir_addr : layer->dst.phy_addr;
+		bpp = layer->dst.bpp;
+		addr =
+		    dst_addr + layer->dst_rect.x * bpp +
+		    (in_rect.x - layer->dst_rect.x + layer->dst_rect.y) *
+		    	layer->dst.stride;
+
+		if (is_YUV_SP_420(layer->dst.format)) {
+			top_pad = (addr & 0x1F) / bpp;
+		} else {
+			top_pad = (addr & 0x3F) / bpp;
+		}
+
+		aligned_rect->x = in_rect.x;
+		aligned_rect->y = in_rect.y;
+		aligned_rect->w = size_hrz + 1;
+		aligned_rect->h = ALIGN_UP(in_rect.h + top_pad, aligned_line);
+
+		left_pad = 0;
+		right_pad = 0;
+		bottom_pad = aligned_rect->h - in_rect.h - top_pad;
+	} else {
+		aligned_rect->x = ALIGN_DOWN(in_rect.x, aligned_pixel);
+		aligned_rect->w =
+		    ALIGN_UP(in_rect.x - aligned_rect->x + in_rect.w + dfc_w,
+			     aligned_pixel);
+		aligned_rect->y = in_rect.y;
+
+		if (is_YUV_SP_420(layer->dst.format)) {
+			aligned_rect->h = ALIGN_UP(in_rect.h, 2);
+		} else {
+			aligned_rect->h = in_rect.h;
+		}
+
+		left_pad = in_rect.x - aligned_rect->x;
+		right_pad = aligned_rect->w - (left_pad + in_rect.w + dfc_w);
+		top_pad = 0;
+		bottom_pad = aligned_rect->h - in_rect.h;
+	}
+
+	dfc->disp_size =
+	    set_bits32(dfc->disp_size, (size_vrt | (size_hrz << 16)), 32, 0);
+	dfc->pix_in_num = set_bits32(dfc->pix_in_num, dfc_pix_in_num, 1, 0);
+	dfc->disp_fmt = set_bits32(dfc->disp_fmt, dfc_fmt, 5, 1);
+	dfc->clip_ctl_hrz = set_bits32(dfc->clip_ctl_hrz, 0x0, 12, 0);
+	dfc->clip_ctl_vrz = set_bits32(dfc->clip_ctl_vrz, 0x0, 12, 0);
+	dfc->ctl_clip_en = set_bits32(dfc->ctl_clip_en, 0x0, 1, 0);
+	dfc->icg_module = set_bits32(dfc->icg_module, 0x1, 1, 0);
+	if (need_dither) {
+		dfc->dither_enable = set_bits32(dfc->dither_enable, 0x1, 1, 0);
+	} else {
+		dfc->dither_enable = set_bits32(dfc->dither_enable, 0x0, 1, 0);
+	}
+
+	if (left_pad || right_pad || top_pad || bottom_pad) {
+		dfc->padding_ctl = set_bits32(dfc->padding_ctl, (left_pad |
+								 (right_pad << 8) | (top_pad << 16) |
+								 (bottom_pad << 24) | (0x1 << 31)), 32, 0);
+	} else {
+		dfc->padding_ctl = set_bits32(dfc->padding_ctl, 0x0, 32, 0);
+	}
+
+	return 0;
+}
+
+static void hisi_dss_wdma_init(char __iomem *wdma_base, dss_wdma_t *s_wdma)
+{
+	BUG_ON(wdma_base == NULL);
+	BUG_ON(s_wdma == NULL);
+
+	memset(s_wdma, 0, sizeof(dss_wdma_t));
+
+	s_wdma->oft_x0 = inp32(wdma_base + DMA_OFT_X0);
+	s_wdma->oft_y0 = inp32(wdma_base + DMA_OFT_Y0);
+	s_wdma->oft_x1 = inp32(wdma_base + DMA_OFT_X1);
+	s_wdma->oft_y1 = inp32(wdma_base + DMA_OFT_Y1);
+	s_wdma->mask0 = inp32(wdma_base + DMA_MASK0);
+	s_wdma->mask1 = inp32(wdma_base + DMA_MASK1);
+	s_wdma->stretch_size_vrt = inp32(wdma_base + DMA_STRETCH_SIZE_VRT);
+	s_wdma->ctrl = inp32(wdma_base + DMA_CTRL);
+	s_wdma->tile_scram = inp32(wdma_base + DMA_TILE_SCRAM);
+	s_wdma->sw_mask_en = inp32(wdma_base + WDMA_DMA_SW_MASK_EN);
+	s_wdma->start_mask0 = inp32(wdma_base + WDMA_DMA_START_MASK0);
+	s_wdma->end_mask0 = inp32(wdma_base + WDMA_DMA_END_MASK1);
+	s_wdma->start_mask1 = inp32(wdma_base + WDMA_DMA_START_MASK1);
+	s_wdma->end_mask1 = inp32(wdma_base + WDMA_DMA_END_MASK1);
+	s_wdma->data_addr = inp32(wdma_base + DMA_DATA_ADDR0);
+	s_wdma->stride0 = inp32(wdma_base + DMA_STRIDE0);
+	s_wdma->data1_addr = inp32(wdma_base + DMA_DATA_ADDR1);
+	s_wdma->stride1 = inp32(wdma_base + DMA_STRIDE1);
+	s_wdma->stretch_stride = inp32(wdma_base + DMA_STRETCH_STRIDE0);
+	s_wdma->data_num = inp32(wdma_base + DMA_DATA_NUM0);
+
+	s_wdma->ch_rd_shadow = inp32(wdma_base + CH_RD_SHADOW);
+	s_wdma->ch_ctl = inp32(wdma_base + CH_CTL);
+	s_wdma->ch_secu_en = inp32(wdma_base + CH_SECU_EN);
+	s_wdma->ch_sw_end_req = inp32(wdma_base + CH_SW_END_REQ);
+
+	s_wdma->afbce_hreg_pic_blks = inp32(wdma_base + AFBCE_HREG_PIC_BLKS);
+	s_wdma->afbce_hreg_format = inp32(wdma_base + AFBCE_HREG_FORMAT);
+	s_wdma->afbce_hreg_hdr_ptr_lo =
+	    inp32(wdma_base + AFBCE_HREG_HDR_PTR_LO);
+	s_wdma->afbce_hreg_pld_ptr_lo =
+	    inp32(wdma_base + AFBCE_HREG_PLD_PTR_LO);
+	s_wdma->afbce_picture_size = inp32(wdma_base + AFBCE_PICTURE_SIZE);
+	s_wdma->afbce_ctl = inp32(wdma_base + AFBCE_CTL);
+	s_wdma->afbce_header_srtide = inp32(wdma_base + AFBCE_HEADER_SRTIDE);
+	s_wdma->afbce_payload_stride = inp32(wdma_base + AFBCE_PAYLOAD_STRIDE);
+	s_wdma->afbce_enc_os_cfg = inp32(wdma_base + AFBCE_ENC_OS_CFG);
+	s_wdma->afbce_mem_ctrl = inp32(wdma_base + AFBCE_MEM_CTRL);
+}
+
+static void hisi_dss_wdma_set_reg(struct hisi_fb_data_type *hisifd,
+				  char __iomem *wdma_base, dss_wdma_t *s_wdma)
+{
+	BUG_ON(hisifd == NULL);
+	BUG_ON(wdma_base == NULL);
+	BUG_ON(s_wdma == NULL);
+
+	hisifd->set_reg(hisifd, wdma_base + CH_REG_DEFAULT, 0x1, 32, 0);
+	hisifd->set_reg(hisifd, wdma_base + CH_REG_DEFAULT, 0x0, 32, 0);
+
+	hisifd->set_reg(hisifd, wdma_base + DMA_OFT_X0, s_wdma->oft_x0, 32, 0);
+	hisifd->set_reg(hisifd, wdma_base + DMA_OFT_Y0, s_wdma->oft_y0, 32, 0);
+	hisifd->set_reg(hisifd, wdma_base + DMA_OFT_X1, s_wdma->oft_x1, 32, 0);
+	hisifd->set_reg(hisifd, wdma_base + DMA_OFT_Y1, s_wdma->oft_y1, 32, 0);
+	hisifd->set_reg(hisifd, wdma_base + DMA_CTRL, s_wdma->ctrl, 32, 0);
+	hisifd->set_reg(hisifd, wdma_base + DMA_TILE_SCRAM,
+			s_wdma->tile_scram, 32, 0);
+	hisifd->set_reg(hisifd, wdma_base + WDMA_DMA_SW_MASK_EN,
+			s_wdma->sw_mask_en, 32, 0);
+	hisifd->set_reg(hisifd, wdma_base + WDMA_DMA_START_MASK0,
+			s_wdma->start_mask0, 32, 0);
+	hisifd->set_reg(hisifd, wdma_base + WDMA_DMA_END_MASK0,
+			s_wdma->end_mask0, 32, 0);
+	hisifd->set_reg(hisifd, wdma_base + DMA_DATA_ADDR0,
+			s_wdma->data_addr, 32, 0);
+	hisifd->set_reg(hisifd, wdma_base + DMA_STRIDE0,
+			s_wdma->stride0, 32, 0);
+	hisifd->set_reg(hisifd, wdma_base + DMA_DATA_ADDR1,
+			s_wdma->data1_addr, 32, 0);
+	hisifd->set_reg(hisifd, wdma_base + DMA_STRIDE1,
+			s_wdma->stride1, 32, 0);
+
+	hisifd->set_reg(hisifd, wdma_base + CH_CTL, s_wdma->ch_ctl, 32, 0);
+	hisifd->set_reg(hisifd, wdma_base + ROT_SIZE, s_wdma->rot_size, 32, 0);
+	hisifd->set_reg(hisifd, wdma_base + DMA_BUF_SIZE,
+			s_wdma->dma_buf_size, 32, 0);
+
+	if (s_wdma->afbc_used == 1) {
+		hisifd->set_reg(hisifd, wdma_base + AFBCE_HREG_PIC_BLKS,
+				s_wdma->afbce_hreg_pic_blks, 32, 0);
+		hisifd->set_reg(hisifd, wdma_base + AFBCE_HREG_FORMAT,
+				s_wdma->afbce_hreg_format, 32, 0);
+		hisifd->set_reg(hisifd, wdma_base + AFBCE_HREG_HDR_PTR_LO,
+				s_wdma->afbce_hreg_hdr_ptr_lo, 32, 0);
+		hisifd->set_reg(hisifd, wdma_base + AFBCE_HREG_PLD_PTR_LO,
+				s_wdma->afbce_hreg_pld_ptr_lo, 32, 0);
+		hisifd->set_reg(hisifd, wdma_base + AFBCE_PICTURE_SIZE,
+				s_wdma->afbce_picture_size, 32, 0);
+		hisifd->set_reg(hisifd, wdma_base + AFBCE_HEADER_SRTIDE,
+				s_wdma->afbce_header_srtide, 32, 0);
+		hisifd->set_reg(hisifd, wdma_base + AFBCE_PAYLOAD_STRIDE,
+				s_wdma->afbce_payload_stride, 32, 0);
+		hisifd->set_reg(hisifd, wdma_base + AFBCE_ENC_OS_CFG,
+				s_wdma->afbce_enc_os_cfg, 32, 0);
+		hisifd->set_reg(hisifd, wdma_base + AFBCE_THRESHOLD,
+				s_wdma->afbce_threshold, 32, 0);
+		hisifd->set_reg(hisifd, wdma_base + AFBCE_SCRAMBLE_MODE,
+				s_wdma->afbce_scramble_mode, 32, 0);
+		hisifd->set_reg(hisifd, wdma_base + AFBCE_HEADER_POINTER_OFFSET,
+				s_wdma->afbce_header_pointer_offset, 32, 0);
+	}
+}
+
+int hisi_dss_wdma_config(struct hisi_fb_data_type *hisifd,
+			 dss_overlay_t *pov_req, dss_wb_layer_t *layer,
+			 dss_rect_t aligned_rect, dss_rect_t *ov_block_rect,
+			 bool last_block)
+{
+	dss_wdma_t *wdma = NULL;
+	int chn_idx = 0;
+	int wdma_format = 0;
+	int wdma_transform = 0;
+	uint32_t oft_x0 = 0;
+	uint32_t oft_x1 = 0;
+	uint32_t oft_y0 = 0;
+	uint32_t oft_y1 = 0;
+	uint32_t data_num = 0;
+	uint32_t wdma_addr = 0;
+	uint32_t wdma_stride = 0;
+
+	uint32_t wdma_buf_width = 0;
+	uint32_t wdma_buf_height = 0;
+
+	dss_rect_t in_rect;
+	int temp = 0;
+	int aligned_pixel = 0;
+	int l2t_interleave_n = 0;
+	bool mmu_enable = false;
+
+	dss_rect_ltrb_t afbc_header_rect = { 0 };
+	dss_rect_ltrb_t afbc_payload_rect = { 0 };
+	uint32_t afbce_hreg_pic_blks;
+	uint32_t afbc_header_addr = 0;
+	uint32_t afbc_header_stride = 0;
+	uint32_t afbc_payload_addr = 0;
+	uint32_t afbc_payload_stride = 0;
+	int32_t afbc_header_start_pos = 0;
+	uint32_t afbc_header_pointer_offset = 0;
+	uint32_t stride_align = 0;
+	uint32_t addr_align = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_req == NULL);
+	BUG_ON(layer == NULL);
+
+	chn_idx = layer->chn_idx;
+
+	wdma = &(hisifd->dss_module.wdma[chn_idx]);
+	hisifd->dss_module.dma_used[chn_idx] = 1;
+
+	wdma_format = hisi_pixel_format_hal2dma(layer->dst.format);
+	if (wdma_format < 0) {
+		HISI_FB_ERR("hisi_pixel_format_hal2dma failed!\n");
+		return -EINVAL;
+	}
+
+	in_rect = aligned_rect;
+	aligned_pixel = DMA_ALIGN_BYTES / layer->dst.bpp;
+
+	wdma_transform = hisi_transform_hal2dma(layer->transform, chn_idx);
+	if (wdma_transform < 0) {
+		HISI_FB_ERR("hisi_transform_hal2dma failed!\n");
+		return -EINVAL;
+	}
+
+	mmu_enable = (layer->dst.mmu_enable == 1) ? true : false;
+	wdma_addr = mmu_enable ? layer->dst.vir_addr : layer->dst.phy_addr;
+
+	if (layer->need_cap & CAP_AFBCE) {
+		wdma->afbc_used = 1;
+		if ((layer->dst.width & (AFBC_HEADER_ADDR_ALIGN - 1)) ||
+		    (layer->dst.height & (AFBC_BLOCK_ALIGN - 1))) {
+			HISI_FB_ERR
+			    ("wb_layer img width(%d) is not %d bytes aligned, or "
+			     "img heigh(%d) is not %d bytes aligned!\n",
+			     layer->dst.width, AFBC_HEADER_ADDR_ALIGN,
+			     layer->dst.height, AFBC_BLOCK_ALIGN);
+			return -EINVAL;
+		}
+
+		if ((in_rect.w < AFBC_PIC_WIDTH_MIN)
+		    || (in_rect.w > AFBCE_IN_WIDTH_MAX)
+		    || (in_rect.h < AFBC_PIC_HEIGHT_MIN)
+		    || (in_rect.h > AFBC_PIC_HEIGHT_MAX)
+		    || (in_rect.w & (AFBC_BLOCK_ALIGN - 1))
+		    || (in_rect.h & (AFBC_BLOCK_ALIGN - 1))) {
+			HISI_FB_ERR
+			    ("afbce in_rect(%d,%d, %d,%d) is out of range!",
+			     in_rect.x, in_rect.y, in_rect.w, in_rect.h);
+			return -EINVAL;
+		}
+
+		afbc_header_rect.right =
+		    ALIGN_UP(in_rect.x + in_rect.w, AFBC_HEADER_ADDR_ALIGN) - 1;
+		afbc_header_rect.bottom =
+		    ALIGN_UP(in_rect.y + in_rect.h, AFBC_BLOCK_ALIGN) - 1;
+		if (layer->transform & HISI_FB_TRANSFORM_ROT_90) {
+			afbc_header_rect.left =
+			    ALIGN_DOWN(layer->dst_rect.x,
+				       AFBC_HEADER_ADDR_ALIGN);
+			afbc_header_rect.top =
+			    ALIGN_DOWN(layer->dst_rect.y +
+				       (ov_block_rect->x - layer->dst_rect.x),
+				       AFBC_BLOCK_ALIGN);
+
+			afbc_payload_rect.left =
+			    ALIGN_DOWN(layer->dst_rect.x, AFBC_BLOCK_ALIGN);
+			afbc_payload_rect.top = afbc_header_rect.top;
+
+			afbc_header_start_pos =
+			    (layer->dst_rect.x -
+			     afbc_header_rect.left) / AFBC_BLOCK_ALIGN;
+		} else {
+			afbc_header_rect.left =
+			    ALIGN_DOWN(in_rect.x, AFBC_HEADER_ADDR_ALIGN);
+			afbc_header_rect.top =
+			    ALIGN_DOWN(in_rect.y, AFBC_BLOCK_ALIGN);
+
+			afbc_payload_rect.left =
+			    ALIGN_DOWN(in_rect.x, AFBC_BLOCK_ALIGN);
+			afbc_payload_rect.top = afbc_header_rect.top;
+
+			afbc_header_start_pos =
+			    (in_rect.x -
+			     afbc_header_rect.left) / AFBC_BLOCK_ALIGN;
+		}
+
+		if (afbc_header_start_pos < 0) {
+			HISI_FB_ERR("afbc_header_start_pos(%d) is invalid!\n",
+				    afbc_header_start_pos);
+			return -EINVAL;
+		}
+
+		afbce_hreg_pic_blks =
+		    (in_rect.w / AFBC_BLOCK_ALIGN) * (in_rect.h /
+						      AFBC_BLOCK_ALIGN) - 1;
+
+		afbc_header_stride =
+		    (layer->dst.width / AFBC_BLOCK_ALIGN) *
+		    AFBC_HEADER_STRIDE_BLOCK;
+
+		afbc_header_pointer_offset =
+		    (afbc_header_rect.top / AFBC_BLOCK_ALIGN) *
+		    afbc_header_stride +
+		    (afbc_header_rect.left / AFBC_BLOCK_ALIGN) *
+		    AFBC_HEADER_STRIDE_BLOCK;
+
+		afbc_header_addr =
+		    layer->dst.afbc_header_addr + afbc_header_pointer_offset;
+
+		if ((afbc_header_addr & (AFBC_HEADER_ADDR_ALIGN - 1)) ||
+		    (afbc_header_stride & (AFBC_HEADER_STRIDE_ALIGN - 1))) {
+			HISI_FB_ERR
+			    ("wb_layer afbc_header_addr(0x%x) is not %d bytes aligned, or "
+			     "afbc_header_stride(0x%x) is not %d bytes aligned!\n",
+			     afbc_header_addr, AFBC_HEADER_ADDR_ALIGN,
+			     afbc_header_stride, AFBC_HEADER_STRIDE_ALIGN);
+			return -EINVAL;
+		}
+
+		if (layer->dst.bpp == 4) {
+			stride_align = AFBC_PAYLOAD_STRIDE_ALIGN_32;
+			addr_align = AFBC_PAYLOAD_ADDR_ALIGN_32;
+		} else if (layer->dst.bpp == 2) {
+			stride_align = AFBC_PAYLOAD_STRIDE_ALIGN_16;
+			addr_align = AFBC_PAYLOAD_ADDR_ALIGN_16;
+		} else {
+			HISI_FB_ERR("bpp(%d) not supported!\n", layer->dst.bpp);
+			return -EINVAL;
+		}
+
+		afbc_payload_stride = layer->dst.afbc_payload_stride;
+		if (layer->dst.afbc_scramble_mode != DSS_AFBC_SCRAMBLE_MODE2) {
+			afbc_payload_stride =
+			    (layer->dst.width / AFBC_BLOCK_ALIGN) *
+			    stride_align;
+		}
+		afbc_payload_addr = layer->dst.afbc_payload_addr +
+		    (afbc_payload_rect.top / AFBC_BLOCK_ALIGN) *
+		    afbc_payload_stride +
+		    (afbc_payload_rect.left / AFBC_BLOCK_ALIGN) * stride_align;
+
+		if ((afbc_payload_addr & (addr_align - 1)) ||
+		    (afbc_payload_stride & (stride_align - 1))) {
+			HISI_FB_ERR
+			    ("afbc_payload_addr(0x%x) is not %d bytes aligned, or "
+			     "afbc_payload_stride(0x%x) is not %d bytes aligned!\n",
+			     afbc_payload_addr, addr_align, afbc_payload_stride,
+			     stride_align);
+			return -EINVAL;
+		}
+
+		if (g_debug_ovl_online_composer) {
+			HISI_FB_INFO
+			    ("aligned_rect(%d,%d,%d,%d), afbc_rect(%d,%d,%d,%d)!\n",
+			     in_rect.x, in_rect.y,
+			     DSS_WIDTH(in_rect.x + in_rect.w),
+			     DSS_WIDTH(in_rect.y + in_rect.h),
+			     afbc_payload_rect.left, afbc_payload_rect.top,
+			     afbc_payload_rect.right, afbc_payload_rect.bottom);
+		}
+
+		wdma->ctrl = set_bits32(wdma->ctrl, wdma_format, 5, 3);
+		wdma->ctrl =
+		    set_bits32(wdma->ctrl, (mmu_enable ? 0x1 : 0x0), 1, 8);
+		wdma->ctrl = set_bits32(wdma->ctrl, wdma_transform, 3, 9);
+		if (last_block) {
+			wdma->ch_ctl = set_bits32(wdma->ch_ctl, 0x1d, 5, 0);
+		} else {
+			wdma->ch_ctl = set_bits32(wdma->ch_ctl, 0xd, 5, 0);
+		}
+
+		wdma->rot_size = set_bits32(wdma->rot_size,
+					    (DSS_WIDTH(in_rect.w) |
+					     (DSS_HEIGHT(in_rect.h) << 16)), 32, 0);
+
+		wdma->afbce_hreg_pic_blks =
+		    set_bits32(wdma->afbce_hreg_pic_blks,
+		    		afbce_hreg_pic_blks, 24, 0);
+
+		wdma->afbce_hreg_format =
+		    set_bits32(wdma->afbce_hreg_format,
+			       (isYUVPackage(layer->dst.format) ? 0x0 : 0x1), 1, 21);
+
+		wdma->afbce_hreg_hdr_ptr_lo =
+		    set_bits32(wdma->afbce_hreg_hdr_ptr_lo,
+		    		afbc_header_addr, 32, 0);
+
+		wdma->afbce_hreg_pld_ptr_lo =
+		    set_bits32(wdma->afbce_hreg_pld_ptr_lo,
+		    		afbc_payload_addr, 32, 0);
+
+		wdma->afbce_picture_size =
+		    set_bits32(wdma->afbce_picture_size,
+			       ((DSS_WIDTH(in_rect.w) << 16) |
+			          DSS_HEIGHT(in_rect.h)), 32, 0);
+
+		wdma->afbce_header_srtide =
+		    set_bits32(wdma->afbce_header_srtide,
+			       ((afbc_header_start_pos << 14) |
+				afbc_header_stride), 16, 0);
+
+		wdma->afbce_payload_stride =
+		    set_bits32(wdma->afbce_payload_stride, afbc_payload_stride, 20, 0);
+
+		wdma->afbce_enc_os_cfg =
+		    set_bits32(wdma->afbce_enc_os_cfg,
+			       DSS_AFBCE_ENC_OS_CFG_DEFAULT_VAL, 3, 0);
+
+		wdma->afbce_mem_ctrl =
+		    set_bits32(wdma->afbce_mem_ctrl, 0x0, 12, 0);
+		wdma->afbce_threshold =
+		    set_bits32(wdma->afbce_threshold, 0x2, 32, 0);
+		wdma->afbce_header_pointer_offset =
+		    set_bits32(wdma->afbce_header_pointer_offset,
+			       afbc_header_pointer_offset, 32, 0);
+		wdma->afbce_scramble_mode =
+		    set_bits32(wdma->afbce_scramble_mode,
+			       layer->dst.afbc_scramble_mode, 2, 0);
+
+		return 0;
+	}
+
+	if (layer->need_cap & CAP_TILE) {
+		l2t_interleave_n =
+		    hisi_get_rdma_tile_interleave(layer->dst.stride);
+		if (l2t_interleave_n < MIN_INTERLEAVE) {
+			HISI_FB_ERR
+			    ("tile stride should be 256*2^n, error stride:%d!\n",
+			     layer->dst.stride);
+			return -EINVAL;
+		}
+
+		if (wdma_addr & (TILE_DMA_ADDR_ALIGN - 1)) {
+			HISI_FB_ERR
+			    ("tile wdma_addr(0x%x) is not %d bytes aligned.\n",
+			     wdma_addr, TILE_DMA_ADDR_ALIGN);
+			return -EINVAL;
+		}
+	}
+
+	if (layer->transform & HISI_FB_TRANSFORM_ROT_90) {
+		temp = in_rect.w;
+		in_rect.w = in_rect.h;
+		in_rect.h = temp;
+
+		oft_x0 = 0;
+		oft_x1 = DSS_WIDTH(in_rect.w) / aligned_pixel;
+		oft_y0 = 0;
+		oft_y1 = DSS_HEIGHT(ov_block_rect->w);
+	} else {
+		oft_x0 = in_rect.x / aligned_pixel;
+		oft_x1 = DSS_WIDTH(in_rect.x + in_rect.w) / aligned_pixel;
+		oft_y0 = in_rect.y;
+		oft_y1 = DSS_HEIGHT(in_rect.y + in_rect.h);
+	}
+
+	wdma_addr =
+	    hisi_calculate_display_addr_wb(mmu_enable, layer, in_rect,
+					   ov_block_rect, DSS_ADDR_PLANE0);
+	wdma_stride = layer->dst.stride / DMA_ALIGN_BYTES;
+
+	data_num = (oft_x1 - oft_x0 + 1) * (oft_y1 - oft_y0 + 1);
+	if (layer->transform & HISI_FB_TRANSFORM_ROT_90) {
+		wdma->rot_size = set_bits32(wdma->rot_size,
+					    (DSS_WIDTH(ov_block_rect->w) |
+					     (DSS_HEIGHT(aligned_rect.h) << 16)), 32, 0);
+
+		if (ov_block_rect) {
+			wdma_buf_width = DSS_HEIGHT(ov_block_rect->h);
+			wdma_buf_height = DSS_WIDTH(ov_block_rect->w);
+		} else {
+			wdma_buf_width = DSS_HEIGHT(layer->src_rect.h);
+			wdma_buf_height = DSS_WIDTH(layer->src_rect.w);
+		}
+	} else {
+		if (ov_block_rect) {
+			wdma_buf_width = DSS_WIDTH(ov_block_rect->w);
+			wdma_buf_height = DSS_HEIGHT(ov_block_rect->h);
+		} else {
+			wdma_buf_width = DSS_WIDTH(layer->src_rect.w);
+			wdma_buf_height = DSS_HEIGHT(layer->src_rect.h);
+		}
+	}
+
+	wdma->oft_x0 = set_bits32(wdma->oft_x0, oft_x0, 12, 0);
+	wdma->oft_y0 = set_bits32(wdma->oft_y0, oft_y0, 16, 0);
+	wdma->oft_x1 = set_bits32(wdma->oft_x1, oft_x1, 12, 0);
+	wdma->oft_y1 = set_bits32(wdma->oft_y1, oft_y1, 16, 0);
+
+	wdma->ctrl = set_bits32(wdma->ctrl, wdma_format, 5, 3);
+	wdma->ctrl = set_bits32(wdma->ctrl, wdma_transform, 3, 9);
+	wdma->ctrl = set_bits32(wdma->ctrl, (mmu_enable ? 0x1 : 0x0), 1, 8);
+	wdma->data_num = set_bits32(wdma->data_num, data_num, 30, 0);
+
+	wdma->ctrl =
+	    set_bits32(wdma->ctrl, ((layer->need_cap & CAP_TILE) ? 0x1 : 0x0),
+		       1, 1);
+	wdma->tile_scram =
+	    set_bits32(wdma->tile_scram,
+		       ((layer->need_cap & CAP_TILE) ? 0x1 : 0x0), 1, 0);
+
+	wdma->data_addr = set_bits32(wdma->data_addr, wdma_addr, 32, 0);
+	wdma->stride0 =
+	    set_bits32(wdma->stride0, wdma_stride | (l2t_interleave_n << 16),
+		       20, 0);
+
+	if (is_YUV_SP_420(layer->dst.format)) {
+		wdma_addr =
+		    hisi_calculate_display_addr_wb(mmu_enable, layer, in_rect,
+						   ov_block_rect, DSS_ADDR_PLANE1);
+
+		wdma_stride = layer->dst.stride_plane1 / DMA_ALIGN_BYTES;
+		wdma->data1_addr =
+		    set_bits32(wdma->data1_addr, wdma_addr, 32, 0);
+		wdma->stride1 = set_bits32(wdma->stride1, wdma_stride, 13, 0);
+	}
+
+	if (last_block) {
+		wdma->ch_ctl = set_bits32(wdma->ch_ctl, 1, 1, 4);
+	} else {
+		wdma->ch_ctl = set_bits32(wdma->ch_ctl, 0, 1, 4);
+	}
+	wdma->ch_ctl = set_bits32(wdma->ch_ctl, 1, 1, 3);
+	wdma->ch_ctl = set_bits32(wdma->ch_ctl, 1, 1, 0);
+
+	wdma->dma_buf_size = set_bits32(wdma->dma_buf_size,
+					wdma_buf_width | (wdma_buf_height << 16), 32, 0);
+
+	return 0;
+}
+
+/*******************************************************************************
+ ** DSS GLOBAL
+ */
+int hisi_dss_module_init(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+
+	memcpy(&(hisifd->dss_module), &(hisifd->dss_module_default),
+	       sizeof(dss_module_reg_t));
+
+	return 0;
+}
+
+int hisi_dss_module_default(struct hisi_fb_data_type *hisifd)
+{
+	dss_module_reg_t *dss_module = NULL;
+	uint32_t module_base = 0;
+	char __iomem *dss_base = NULL;
+	int i = 0;
+
+	BUG_ON(hisifd == NULL);
+	dss_base = hisifd->dss_base;
+	BUG_ON(dss_base == NULL);
+
+	dss_module = &(hisifd->dss_module_default);
+	memset(dss_module, 0, sizeof(dss_module_reg_t));
+
+	for (i = 0; i < DSS_MCTL_IDX_MAX; i++) {
+		module_base = g_dss_module_ovl_base[i][MODULE_MCTL_BASE];
+		if (module_base != 0) {
+			dss_module->mctl_base[i] = dss_base + module_base;
+			hisi_dss_mctl_init(dss_module->mctl_base[i],
+					   &(dss_module->mctl[i]));
+		}
+	}
+
+	for (i = 0; i < DSS_OVL_IDX_MAX; i++) {
+		module_base = g_dss_module_ovl_base[i][MODULE_OVL_BASE];
+		if (module_base != 0) {
+			dss_module->ov_base[i] = dss_base + module_base;
+			hisi_dss_ovl_init(dss_module->ov_base[i],
+					  &(dss_module->ov[i]), i);
+		}
+	}
+
+	for (i = 0; i < DSS_CHN_MAX_DEFINE; i++) {
+		module_base = g_dss_module_base[i][MODULE_AIF0_CHN];
+		if (module_base != 0) {
+			dss_module->aif_ch_base[i] = dss_base + module_base;
+			hisi_dss_aif_init(dss_module->aif_ch_base[i],
+					  &(dss_module->aif[i]));
+		}
+
+		module_base = g_dss_module_base[i][MODULE_AIF1_CHN];
+		if (module_base != 0) {
+			dss_module->aif1_ch_base[i] = dss_base + module_base;
+			hisi_dss_aif_init(dss_module->aif1_ch_base[i],
+					  &(dss_module->aif1[i]));
+		}
+
+		module_base = g_dss_module_base[i][MODULE_MIF_CHN];
+		if (module_base != 0) {
+			dss_module->mif_ch_base[i] = dss_base + module_base;
+			hisi_dss_mif_init(dss_module->mif_ch_base[i],
+					  &(dss_module->mif[i]), i);
+		}
+
+		module_base = g_dss_module_base[i][MODULE_MCTL_CHN_MUTEX];
+		if (module_base != 0) {
+			dss_module->mctl_ch_base[i].chn_mutex_base =
+			    dss_base + module_base;
+		}
+
+		module_base = g_dss_module_base[i][MODULE_MCTL_CHN_FLUSH_EN];
+		if (module_base != 0) {
+			dss_module->mctl_ch_base[i].chn_flush_en_base =
+			    dss_base + module_base;
+		}
+
+		module_base = g_dss_module_base[i][MODULE_MCTL_CHN_OV_OEN];
+		if (module_base != 0) {
+			dss_module->mctl_ch_base[i].chn_ov_en_base =
+			    dss_base + module_base;
+		}
+
+		module_base = g_dss_module_base[i][MODULE_MCTL_CHN_STARTY];
+		if (module_base != 0) {
+			dss_module->mctl_ch_base[i].chn_starty_base =
+			    dss_base + module_base;
+			hisi_dss_mctl_ch_starty_init(
+				dss_module->mctl_ch_base[i].chn_starty_base,
+				&(dss_module->mctl_ch[i]));
+		}
+
+		module_base = g_dss_module_base[i][MODULE_MCTL_CHN_MOD_DBG];
+		if (module_base != 0) {
+			dss_module->mctl_ch_base[i].chn_mod_dbg_base =
+			    dss_base + module_base;
+			hisi_dss_mctl_ch_mod_dbg_init(
+				dss_module->mctl_ch_base[i].chn_mod_dbg_base,
+				&(dss_module->mctl_ch[i]));
+		}
+
+		module_base = g_dss_module_base[i][MODULE_DMA];
+		if (module_base != 0) {
+			dss_module->dma_base[i] = dss_base + module_base;
+			if (i < DSS_WCHN_W0 || i == DSS_RCHN_V2) {
+				hisi_dss_rdma_init(dss_module->dma_base[i],
+						   &(dss_module->rdma[i]));
+			} else {
+				hisi_dss_wdma_init(dss_module->dma_base[i],
+						   &(dss_module->wdma[i]));
+			}
+
+			if ((i == DSS_RCHN_V0) || (i == DSS_RCHN_V1)
+			    || (i == DSS_RCHN_V2)) {
+				hisi_dss_rdma_u_init(dss_module->dma_base[i],
+						     &(dss_module->rdma[i]));
+				hisi_dss_rdma_v_init(dss_module->dma_base[i],
+						     &(dss_module->rdma[i]));
+			}
+		}
+
+		module_base = g_dss_module_base[i][MODULE_DFC];
+		if (module_base != 0) {
+			dss_module->dfc_base[i] = dss_base + module_base;
+			hisi_dss_dfc_init(dss_module->dfc_base[i],
+					  &(dss_module->dfc[i]));
+		}
+
+		module_base = g_dss_module_base[i][MODULE_SCL];
+		if (module_base != 0) {
+			dss_module->scl_base[i] = dss_base + module_base;
+			hisi_dss_scl_init(dss_module->scl_base[i],
+					  &(dss_module->scl[i]));
+		}
+
+		module_base = DSS_POST_SCF_OFFSET;
+		if (module_base != 0) {
+			dss_module->post_scf_base = dss_base + module_base;
+			hisi_dss_post_scf_init(dss_module->post_scf_base,
+					       &(dss_module->post_scf));
+		}
+		module_base = g_dss_module_base[i][MODULE_PCSC];
+		if (module_base != 0) {
+			dss_module->pcsc_base[i] = dss_base + module_base;
+			hisi_dss_csc_init(dss_module->pcsc_base[i],
+					  &(dss_module->pcsc[i]));
+		}
+
+		module_base = g_dss_module_base[i][MODULE_ARSR2P];
+		if (module_base != 0) {
+			dss_module->arsr2p_base[i] = dss_base + module_base;
+			hisi_dss_arsr2p_init(dss_module->arsr2p_base[i],
+					     &(dss_module->arsr2p[i]));
+		}
+		module_base = g_dss_module_base[i][MODULE_POST_CLIP];
+		if (module_base != 0) {
+			dss_module->post_clip_base[i] = dss_base + module_base;
+			hisi_dss_post_clip_init(dss_module->post_clip_base[i],
+						&(dss_module->post_clip[i]));
+		}
+
+		module_base = g_dss_module_base[i][MODULE_CSC];
+		if (module_base != 0) {
+			dss_module->csc_base[i] = dss_base + module_base;
+			hisi_dss_csc_init(dss_module->csc_base[i],
+					  &(dss_module->csc[i]));
+		}
+	}
+
+	module_base = DSS_MCTRL_SYS_OFFSET;
+	if (module_base != 0) {
+		dss_module->mctl_sys_base = dss_base + module_base;
+		hisi_dss_mctl_sys_init(dss_module->mctl_sys_base,
+				       &(dss_module->mctl_sys));
+	}
+
+	module_base = DSS_SMMU_OFFSET;
+	if (module_base != 0) {
+		dss_module->smmu_base = dss_base + module_base;
+		hisi_dss_smmu_init(dss_module->smmu_base, &(dss_module->smmu));
+	}
+
+	return 0;
+}
+
+int hisi_dss_ch_module_set_regs(struct hisi_fb_data_type *hisifd,
+				int32_t mctl_idx, int chn_idx, uint32_t wb_type,
+				bool enable_cmdlist)
+{
+	dss_module_reg_t *dss_module = NULL;
+	int i = 0;
+	int ret = 0;
+	uint32_t tmp = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON((chn_idx < 0) || (chn_idx >= DSS_CHN_MAX_DEFINE));
+
+	dss_module = &(hisifd->dss_module);
+	i = chn_idx;
+
+	if (enable_cmdlist) {
+		if (chn_idx == DSS_RCHN_V2) {
+			tmp = (0x1 << DSS_CMDLIST_V2);
+			hisifd->cmdlist_idx = DSS_CMDLIST_V2;
+		} else if (chn_idx == DSS_WCHN_W2) {
+			tmp = (0x1 << DSS_CMDLIST_W2);
+			hisifd->cmdlist_idx = DSS_CMDLIST_W2;
+		} else {
+			tmp = (0x1 << chn_idx);
+			hisifd->cmdlist_idx = chn_idx;
+		}
+
+		ret =
+		    hisi_cmdlist_add_new_node(hisifd, tmp, 0, 0, 0, 0, wb_type);
+		if (ret != 0) {
+			HISI_FB_ERR("fb%d, hisi_cmdlist_add_new_node err:%d \n",
+				    hisifd->index, ret);
+			goto err_return;
+		}
+	}
+
+	if (dss_module->mctl_ch_used[i] == 1) {
+		hisi_dss_mctl_ch_set_reg(hisifd,
+					 &(dss_module->mctl_ch_base[i]),
+					 &(dss_module->mctl_ch[i]), mctl_idx);
+	}
+
+	if (dss_module->smmu_used == 1) {
+		hisi_dss_smmu_ch_set_reg(hisifd, dss_module->smmu_base,
+					 &(dss_module->smmu), i);
+	}
+
+	if (dss_module->dma_used[i] == 1) {
+		if (i < DSS_WCHN_W0 || i == DSS_RCHN_V2) {
+			hisi_dss_rdma_set_reg(hisifd, dss_module->dma_base[i],
+					      &(dss_module->rdma[i]));
+		} else {
+			hisi_dss_wdma_set_reg(hisifd, dss_module->dma_base[i],
+					      &(dss_module->wdma[i]));
+		}
+
+		if ((i == DSS_RCHN_V0) || (i == DSS_RCHN_V1)
+		    || (i == DSS_RCHN_V2)) {
+			hisi_dss_rdma_u_set_reg(hisifd, dss_module->dma_base[i],
+						&(dss_module->rdma[i]));
+			hisi_dss_rdma_v_set_reg(hisifd, dss_module->dma_base[i],
+						&(dss_module->rdma[i]));
+		}
+	}
+
+	if (dss_module->aif_ch_used[i] == 1) {
+		hisi_dss_aif_ch_set_reg(hisifd, dss_module->aif_ch_base[i],
+					&(dss_module->aif[i]));
+	}
+
+	if (dss_module->aif1_ch_used[i] == 1) {
+		hisi_dss_aif_ch_set_reg(hisifd, dss_module->aif1_ch_base[i],
+					&(dss_module->aif1[i]));
+	}
+
+	if (dss_module->mif_used[i] == 1) {
+		hisi_dss_mif_set_reg(hisifd, dss_module->mif_ch_base[i],
+				     &(dss_module->mif[i]), i);
+	}
+
+	if (dss_module->dfc_used[i] == 1) {
+		hisi_dss_dfc_set_reg(hisifd, dss_module->dfc_base[i],
+				     &(dss_module->dfc[i]));
+	}
+
+	if (dss_module->scl_used[i] == 1) {
+		hisi_dss_chn_scl_load_filter_coef_set_reg(hisifd, false,
+							  chn_idx,
+							  dss_module->scl[i].fmt);
+		hisi_dss_scl_set_reg(hisifd, dss_module->scl_base[i],
+				     &(dss_module->scl[i]));
+	}
+	if (hisifd->dss_module.post_cilp_used[i]) {
+		hisi_dss_post_clip_set_reg(hisifd,
+					   dss_module->post_clip_base[i],
+					   &(dss_module->post_clip[i]));
+	}
+	if (dss_module->pcsc_used[i] == 1) {
+		hisi_dss_csc_set_reg(hisifd, dss_module->pcsc_base[i],
+				     &(dss_module->pcsc[i]));
+	}
+
+	if (dss_module->arsr2p_used[i] == 1) {
+		hisi_dss_arsr2p_set_reg(hisifd, dss_module->arsr2p_base[i],
+					&(dss_module->arsr2p[i]));
+	}
+
+	if (dss_module->csc_used[i] == 1) {
+		hisi_dss_csc_set_reg(hisifd, dss_module->csc_base[i],
+				     &(dss_module->csc[i]));
+	}
+
+	if (dss_module->mctl_ch_used[i] == 1) {
+		hisi_dss_mctl_sys_ch_set_reg(hisifd,
+					     &(dss_module->mctl_ch_base[i]),
+					     &(dss_module->mctl_ch[i]), i, true);
+	}
+
+	return 0;
+
+ err_return:
+	return ret;
+}
+
+int hisi_dss_ov_module_set_regs(struct hisi_fb_data_type *hisifd,
+				dss_overlay_t *pov_req, int ovl_idx,
+				bool enable_cmdlist, int task_end, int last,
+				bool is_first_ov_block)
+{
+	dss_module_reg_t *dss_module = NULL;
+	int i = 0;
+	int ret = 0;
+	uint32_t tmp = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	if (pov_req && pov_req->wb_layer_infos[0].chn_idx == DSS_WCHN_W2) {
+		return 0;
+	}
+
+	dss_module = &(hisifd->dss_module);
+	i = ovl_idx;
+
+	if (enable_cmdlist) {
+		tmp = (0x1 << (DSS_CMDLIST_OV0 + ovl_idx));
+		hisifd->cmdlist_idx = DSS_CMDLIST_OV0 + ovl_idx;
+
+		ret =
+		    hisi_cmdlist_add_new_node(hisifd, tmp, 0, task_end, 0, last,
+					      0);
+		if (ret != 0) {
+			HISI_FB_ERR("fb%d, hisi_cmdlist_add_new_node err:%d \n",
+				    hisifd->index, ret);
+			goto err_return;
+		}
+	}
+
+	if (dss_module->mctl_used[i] == 1) {
+		hisi_dss_mctl_ov_set_reg(hisifd, dss_module->mctl_base[i],
+					 &(dss_module->mctl[i]), ovl_idx,
+					 enable_cmdlist);
+	}
+
+	if (is_first_ov_block) {
+		if (dss_module->dirty_region_updt_used == 1)
+			hisi_dss_dirty_region_dbuf_set_reg(hisifd,
+							   hisifd->dss_base,
+							   &(dss_module->
+							     dirty_region_updt));
+	}
+
+	if (dss_module->ov_used[i] == 1) {
+		hisi_dss_ovl_set_reg(hisifd, dss_module->ov_base[i],
+				     &(dss_module->ov[i]), ovl_idx);
+	}
+
+	if (hisifd->dss_module.post_scf_used == 1) {
+		hisi_dss_post_scf_set_reg(hisifd,
+					  hisifd->dss_module.post_scf_base,
+					  &(hisifd->dss_module.post_scf));
+	}
+
+	if (dss_module->mctl_sys_used == 1) {
+		hisi_dss_mctl_sys_set_reg(hisifd, dss_module->mctl_sys_base,
+					  &(dss_module->mctl_sys), ovl_idx);
+	}
+
+	return 0;
+
+ err_return:
+	return ret;
+}
+
+int hisi_dss_prev_module_set_regs(struct hisi_fb_data_type *hisifd,
+				  dss_overlay_t *pov_req,
+				  uint32_t cmdlist_pre_idxs,
+				  bool enable_cmdlist, bool *use_comm_mmbuf)
+{
+	dss_module_reg_t *dss_module = NULL;
+	dss_layer_t *layer = NULL;
+	dss_wb_layer_t *wb_layer = NULL;
+	int32_t ovl_idx = 0;
+	int32_t layer_idx = 0;
+	int32_t mctl_idx = 0;
+	int chn_idx = 0;
+	int i = 0;
+	int j = 0;
+	int k = 0;
+	int m = 0;
+	bool has_base = false;
+	int ret = 0;
+	uint32_t tmp = 0;
+	uint32_t cmdlist_idxs_temp = 0;
+	dss_overlay_block_t *pov_h_block_infos = NULL;
+	dss_overlay_block_t *pov_h_block = NULL;
+	dss_mmbuf_t offline_mmbuf[DSS_CHN_MAX_DEFINE];
+	bool has_rot = false;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_req == NULL);
+
+	ovl_idx = pov_req->ovl_idx;
+	dss_module = &(hisifd->dss_module);
+
+	if (enable_cmdlist) {
+		if (pov_req->wb_enable) {
+			ret =
+			    hisi_cmdlist_add_new_node(hisifd, cmdlist_pre_idxs,
+						      0, 1, 1, 1, 0);
+		} else {
+			ret =
+			    hisi_cmdlist_add_new_node(hisifd, cmdlist_pre_idxs,
+						      0, 0, 0, 0, 0);
+		}
+		if (ret != 0) {
+			HISI_FB_ERR("fb%d, hisi_cmdlist_add_new_node err:%d \n",
+				    hisifd->index, ret);
+			goto err_return;
+		}
+	}
+
+	memset(offline_mmbuf, 0x0, sizeof(offline_mmbuf));
+	cmdlist_idxs_temp = cmdlist_pre_idxs;
+	pov_h_block_infos = (dss_overlay_block_t *) pov_req->ov_block_infos_ptr;
+	for (m = 0; m < pov_req->ov_block_nums; m++) {
+		pov_h_block = &(pov_h_block_infos[m]);
+
+		for (i = 0; i < pov_h_block->layer_nums; i++) {
+			layer = &(pov_h_block->layer_infos[i]);
+			chn_idx = layer->chn_idx;
+			layer_idx = layer->layer_idx;
+
+			if (chn_idx == DSS_RCHN_V2) {
+				mctl_idx = DSS_MCTL5;
+			} else {
+				mctl_idx = ovl_idx;
+			}
+
+			if (layer->need_cap & (CAP_BASE | CAP_DIM | CAP_PURE_COLOR)) {
+				if (layer->need_cap & CAP_BASE)
+					has_base = true;
+
+				continue;
+			}
+
+			if (ovl_idx == DSS_OVL0) {
+				if ((layer->need_cap & CAP_AFBCD)
+				    && (layer->dst_rect.y >=
+					pov_h_block->ov_block_rect.y)) {
+					if (j < DSS_CHN_MAX_DEFINE) {
+						g_pre_online_mmbuf[j].addr =
+						    layer->img.mmbuf_base;
+						g_pre_online_mmbuf[j].size =
+						    layer->img.mmbuf_size;
+						j++;
+					}
+				}
+			}
+
+			if (ovl_idx == DSS_OVL2) {
+				if (layer->need_cap & CAP_AFBCD) {
+					if (j < DSS_CHN_MAX_DEFINE) {
+						offline_mmbuf[j].addr =
+						    layer->img.mmbuf_base;
+						offline_mmbuf[j].size =
+						    layer->img.mmbuf_size;
+						j++;
+					}
+				}
+			}
+
+			if (chn_idx == DSS_RCHN_V2) {
+				tmp = (0x1 << DSS_CMDLIST_V2);
+				hisifd->cmdlist_idx = DSS_CMDLIST_V2;
+			} else {
+				tmp = (0x1 << chn_idx);
+				hisifd->cmdlist_idx = chn_idx;
+			}
+
+			if ((cmdlist_idxs_temp & tmp) != tmp) {
+				continue;
+			} else {
+				cmdlist_idxs_temp &= (~tmp);
+			}
+
+			hisi_dss_chn_set_reg_default_value(hisifd,
+							   dss_module->dma_base[chn_idx]);
+			hisi_dss_smmu_ch_set_reg(hisifd, dss_module->smmu_base,
+						 &(dss_module->smmu), chn_idx);
+			hisi_dss_mif_set_reg(hisifd,
+					     dss_module->mif_ch_base[chn_idx],
+					     &(dss_module->mif[chn_idx]), chn_idx);
+			hisi_dss_aif_ch_set_reg(hisifd,
+						dss_module->aif_ch_base[chn_idx],
+						&(dss_module->aif[chn_idx]));
+
+			dss_module->mctl_ch[chn_idx].chn_mutex =
+			    set_bits32(dss_module->mctl_ch[chn_idx].chn_mutex,
+				       0x1, 1, 0);
+			dss_module->mctl_ch[chn_idx].chn_flush_en =
+			    set_bits32(dss_module->mctl_ch[chn_idx].chn_flush_en,
+			    	   0x1, 1, 0);
+			dss_module->mctl_ch[chn_idx].chn_ov_oen =
+			    set_bits32(dss_module->mctl_ch[chn_idx].chn_ov_oen,
+				       0x0, 32, 0);
+			dss_module->mctl_ch_used[chn_idx] = 1;
+
+			hisi_dss_mctl_sys_ch_set_reg(hisifd,
+						     &(dss_module->mctl_ch_base[chn_idx]),
+						     &(dss_module->mctl_ch[chn_idx]),
+						     chn_idx, false);
+		}
+	}
+
+	if (g_debug_dump_mmbuf) {
+		if (ovl_idx == DSS_OVL0) {
+			for (i = 0; i < DSS_CHN_MAX_DEFINE; i++) {
+				HISI_FB_INFO
+				    ("g_pre_online_mmbuf[%d].addr=%d, size=%d, j=%d\n",
+				     i, g_pre_online_mmbuf[i].addr,
+				     g_pre_online_mmbuf[i].size, j);
+			}
+		}
+	}
+
+	if (pov_req->wb_enable
+	    && ((ovl_idx > DSS_OVL1) || (mctl_idx == DSS_MCTL5))) {
+		if (mctl_idx != DSS_MCTL5) {
+			hisifd->cmdlist_idx = DSS_CMDLIST_OV0 + ovl_idx;
+
+
+			hisi_dss_ov_set_reg_default_value(hisifd,
+							  dss_module->ov_base[ovl_idx],
+							  ovl_idx);
+		}
+
+		for (k = 0; k < pov_req->wb_layer_nums; k++) {
+			wb_layer = &(pov_req->wb_layer_infos[k]);
+			chn_idx = wb_layer->chn_idx;
+			if (wb_layer->transform & HISI_FB_TRANSFORM_ROT_90)
+				has_rot = true;
+
+			if (chn_idx == DSS_WCHN_W2) {
+				hisifd->cmdlist_idx = DSS_CMDLIST_W2;
+			} else {
+				hisifd->cmdlist_idx = chn_idx;
+			}
+
+			hisi_dss_chn_set_reg_default_value(hisifd,
+							   dss_module->dma_base[chn_idx]);
+			hisi_dss_mif_set_reg(hisifd,
+					     dss_module->mif_ch_base[chn_idx],
+					     &(dss_module->mif[chn_idx]), chn_idx);
+			hisi_dss_aif_ch_set_reg(hisifd,
+						dss_module->aif_ch_base[chn_idx],
+						&(dss_module->aif[chn_idx]));
+
+			dss_module->mctl_ch[chn_idx].chn_mutex =
+			    set_bits32(dss_module->mctl_ch[chn_idx].chn_mutex,
+				       0x1, 1, 0);
+			dss_module->mctl_ch[chn_idx].chn_flush_en =
+			    set_bits32(dss_module->mctl_ch[chn_idx].chn_flush_en,
+			    	   0x1, 1, 0);
+			dss_module->mctl_ch[chn_idx].chn_ov_oen =
+			    set_bits32(dss_module->mctl_ch[chn_idx].chn_ov_oen,
+				       0x0, 32, 0);
+			dss_module->mctl_ch_used[chn_idx] = 1;
+
+			hisi_dss_mctl_sys_ch_set_reg(hisifd,
+						     &(dss_module->mctl_ch_base[chn_idx]),
+						     &(dss_module->mctl_ch[chn_idx]),
+						     chn_idx, false);
+		}
+
+		if (mctl_idx != DSS_MCTL5) {
+			hisifd->cmdlist_idx = DSS_CMDLIST_OV0 + ovl_idx;
+
+			dss_module->mctl_sys.chn_ov_sel_used[ovl_idx] = 1;
+			dss_module->mctl_sys.wch_ov_sel_used[ovl_idx -
+							     DSS_OVL2] = 1;
+			dss_module->mctl_sys.ov_flush_en_used[ovl_idx] = 1;
+			dss_module->mctl_sys.ov_flush_en[ovl_idx] =
+			    set_bits32(dss_module->mctl_sys.ov_flush_en[ovl_idx],
+			    	   0x1, 1, 0);
+			hisi_dss_mctl_sys_set_reg(hisifd,
+						  dss_module->mctl_sys_base,
+						  &(dss_module->mctl_sys), ovl_idx);
+		}
+
+		for (i = 0; i < DSS_CHN_MAX_DEFINE; i++) {
+			for (k = 0; k < DSS_CHN_MAX_DEFINE; k++) {
+				if ((((offline_mmbuf[i].addr <
+					   g_pre_online_mmbuf[k].addr + g_pre_online_mmbuf[k].size)
+				      && (offline_mmbuf[i].addr >=
+				       g_pre_online_mmbuf[k].addr))
+				     ||
+				      ((g_pre_online_mmbuf[k].addr <
+				       offline_mmbuf[i].addr + offline_mmbuf[i].size)
+				      && (g_pre_online_mmbuf[k].addr >=
+					   offline_mmbuf[i].addr)))
+				    && offline_mmbuf[i].size) {
+					if (use_comm_mmbuf) {
+						*use_comm_mmbuf = true;
+						break;
+					}
+				}
+			}
+		}
+
+		if (g_debug_dump_mmbuf) {
+			for (i = 0; i < DSS_CHN_MAX_DEFINE; i++) {
+				HISI_FB_INFO
+				    ("offline_mmbuf[%d].addr=%d, size=%d, use_comm_mmbuf=%d, j=%d\n",
+				     i, offline_mmbuf[i].addr,
+				     offline_mmbuf[i].size, *use_comm_mmbuf, j);
+			}
+		}
+
+		if (!has_rot) {
+			memset(g_pre_online_mmbuf, 0x0,
+			       sizeof(g_pre_online_mmbuf));
+		}
+	}
+
+	return 0;
+
+ err_return:
+	return ret;
+}
+
+void hisi_dss_unflow_handler(struct hisi_fb_data_type *hisifd,
+			     dss_overlay_t *pov_req, bool unmask)
+{
+	uint32_t tmp = 0;
+
+	BUG_ON(hisifd == NULL);
+	if (pov_req->ovl_idx == DSS_OVL0) {
+		tmp =
+		    inp32(hisifd->dss_base + DSS_LDI0_OFFSET +
+			  LDI_CPU_ITF_INT_MSK);
+		if (unmask) {
+			tmp &= ~BIT_LDI_UNFLOW;
+		} else {
+			tmp |= BIT_LDI_UNFLOW;
+		}
+		outp32(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK,
+		       tmp);
+
+	} else if (pov_req->ovl_idx == DSS_OVL1) {
+		tmp =
+		    inp32(hisifd->dss_base + DSS_LDI1_OFFSET +
+			  LDI_CPU_ITF_INT_MSK);
+		if (unmask) {
+			tmp &= ~BIT_LDI_UNFLOW;
+		} else {
+			tmp |= BIT_LDI_UNFLOW;
+		}
+		outp32(hisifd->dss_base + DSS_LDI1_OFFSET + LDI_CPU_ITF_INT_MSK,
+		       tmp);
+	} else {
+		;
+	}
+}
+
+/*******************************************************************************
+ ** compose handler
+ */
+int hisi_ov_compose_handler(struct hisi_fb_data_type *hisifd,
+			    dss_overlay_t *pov_req,
+			    dss_overlay_block_t *pov_h_block,
+			    dss_layer_t *layer,
+			    dss_rect_t *wb_dst_rect,
+			    dss_rect_t *wb_ov_block_rect,
+			    dss_rect_ltrb_t *clip_rect,
+			    dss_rect_t *aligned_rect,
+			    bool *rdma_stretch_enable,
+			    bool *has_base,
+			    bool csc_needed, bool enable_cmdlist)
+{
+	int ret = 0;
+	int32_t mctl_idx = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_h_block == NULL);
+	BUG_ON(layer == NULL);
+	BUG_ON(clip_rect == NULL);
+	BUG_ON(aligned_rect == NULL);
+	BUG_ON(rdma_stretch_enable == NULL);
+
+	ret = hisi_dss_check_layer_par(hisifd, layer);
+	if (ret != 0) {
+		HISI_FB_ERR("hisi_dss_check_layer_par failed! ret = %d\n", ret);
+		goto err_return;
+	}
+
+	if (layer->need_cap & (CAP_BASE | CAP_DIM | CAP_PURE_COLOR)) {
+		if (layer->need_cap & CAP_BASE)
+			*has_base = true;
+
+		ret =
+		    hisi_dss_ovl_layer_config(hisifd, pov_req, layer,
+					      wb_ov_block_rect, *has_base);
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("hisi_dss_ovl_config failed! need_cap=0x%x, ret=%d\n",
+			     layer->need_cap, ret);
+			goto err_return;
+		}
+
+		ret =
+		    hisi_dss_mctl_ch_config(hisifd, pov_req, layer, NULL,
+					    pov_req->ovl_idx, wb_ov_block_rect,
+					    *has_base);
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("hisi_dss_mctl_ch_config failed! ret = %d\n", ret);
+			goto err_return;
+		}
+
+		return ret;
+	}
+
+	if (g_debug_ovl_block_composer) {
+		HISI_FB_INFO
+		    ("layer->dst_rect.y=%d, pov_h_block->ov_block_rect.y=%d,"
+		     "layer->chn_idx=%d, layer->layer_idx=%d\n",
+		     layer->dst_rect.y, pov_h_block->ov_block_rect.y,
+		     layer->chn_idx, layer->layer_idx);
+	}
+
+	if (layer->dst_rect.y < pov_h_block->ov_block_rect.y) {
+		if (g_debug_ovl_block_composer) {
+			HISI_FB_INFO
+			    ("layer->dst_rect.y=%d, pov_h_block->ov_block_rect.y=%d,"
+			     "layer->chn_idx=%d, layer->layer_idx=%d!!!!\n",
+			     layer->dst_rect.y, pov_h_block->ov_block_rect.y,
+			     layer->chn_idx, layer->layer_idx);
+		}
+
+		ret =
+		    hisi_dss_ovl_layer_config(hisifd, pov_req, layer,
+					      wb_ov_block_rect, *has_base);
+		if (ret != 0) {
+			HISI_FB_ERR("hisi_dss_ovl_config failed, ret = %d\n",
+				    ret);
+			goto err_return;
+		}
+
+		ret =
+		    hisi_dss_mctl_ch_config(hisifd, pov_req, layer, NULL,
+					    pov_req->ovl_idx, wb_ov_block_rect,
+					    *has_base);
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("hisi_dss_mctl_ch_config failed! ret = %d\n", ret);
+			goto err_return;
+		}
+
+		return ret;
+	}
+
+	ret = hisi_dss_smmu_ch_config(hisifd, layer, NULL);
+	if (ret != 0) {
+		HISI_FB_ERR("hisi_dss_smmu_ch_config failed! ret = %d\n", ret);
+		goto err_return;
+	}
+
+	if (g_debug_ovl_online_composer) {
+		HISI_FB_INFO
+		    ("fb%d, rdma input, src_rect(%d,%d,%d,%d), "
+		     "src_rect_mask(%d,%d,%d,%d), dst_rect(%d,%d,%d,%d).\n",
+		     hisifd->index, layer->src_rect.x, layer->src_rect.y,
+		     layer->src_rect.w, layer->src_rect.h,
+		     layer->src_rect_mask.x, layer->src_rect_mask.y,
+		     layer->src_rect_mask.w, layer->src_rect_mask.h,
+		     layer->dst_rect.x, layer->dst_rect.y, layer->dst_rect.w,
+		     layer->dst_rect.h);
+	}
+
+	ret = hisi_dss_rdma_config(hisifd, pov_req->ovl_idx, layer,
+				   clip_rect, aligned_rect,
+				   rdma_stretch_enable);
+	if (ret != 0) {
+		HISI_FB_ERR("hisi_dss_rdma_config failed! ret = %d\n", ret);
+		goto err_return;
+	}
+
+	if (g_debug_ovl_online_composer) {
+		HISI_FB_INFO
+		    ("fb%d, rdma output, clip_rect(%d,%d,%d,%d), "
+		     "aligned_rect(%d,%d,%d,%d), dst_rect(%d,%d,%d,%d).\n",
+		     hisifd->index, clip_rect->left, clip_rect->right,
+		     clip_rect->top, clip_rect->bottom, aligned_rect->x,
+		     aligned_rect->y, aligned_rect->w, aligned_rect->h,
+		     layer->dst_rect.x, layer->dst_rect.y, layer->dst_rect.w,
+		     layer->dst_rect.h);
+	}
+
+	ret =
+	    hisi_dss_aif_ch_config(hisifd, pov_req, layer, wb_dst_rect, NULL,
+				   pov_req->ovl_idx);
+	if (ret != 0) {
+		HISI_FB_ERR("hisi_dss_aif_ch_config failed! ret = %d\n", ret);
+		goto err_return;
+	}
+
+	ret =
+	    hisi_dss_aif1_ch_config(hisifd, pov_req, layer, NULL,
+				    pov_req->ovl_idx);
+	if (ret != 0) {
+		HISI_FB_ERR("hisi_dss_aif1_ch_config failed! ret = %d\n", ret);
+		goto err_return;
+	}
+
+	ret = hisi_dss_mif_config(hisifd, layer, NULL, *rdma_stretch_enable);
+	if (ret != 0) {
+		HISI_FB_ERR("hisi_dss_mif_config failed! ret = %d\n", ret);
+		goto err_return;
+	}
+
+	ret = hisi_dss_rdfc_config(hisifd, layer, aligned_rect, *clip_rect);
+	if (ret != 0) {
+		HISI_FB_ERR("hisi_dss_rdfc_config failed! ret = %d\n", ret);
+		goto err_return;
+	}
+
+	if (g_debug_ovl_online_composer) {
+		HISI_FB_INFO
+		    ("fb%d, rdfc output, clip_rect(%d,%d,%d,%d), "
+		     "aligned_rect(%d,%d,%d,%d), dst_rect(%d,%d,%d,%d).\n",
+		     hisifd->index, clip_rect->left, clip_rect->right,
+		     clip_rect->top, clip_rect->bottom, aligned_rect->x,
+		     aligned_rect->y, aligned_rect->w, aligned_rect->h,
+		     layer->dst_rect.x, layer->dst_rect.y, layer->dst_rect.w,
+		     layer->dst_rect.h);
+	}
+
+	ret =
+	    hisi_dss_scl_config(hisifd, layer, aligned_rect,
+				*rdma_stretch_enable);
+	if (ret != 0) {
+		HISI_FB_ERR("hisi_dss_scl_config failed! ret = %d\n", ret);
+		goto err_return;
+	}
+	ret =
+	    hisi_dss_arsr2p_config(hisifd, layer, aligned_rect,
+				   *rdma_stretch_enable);
+	if (ret != 0) {
+		HISI_FB_ERR("hisi_dss_arsr2p_config failed! ret = %d\n", ret);
+		goto err_return;
+	}
+
+	ret = hisi_dss_post_clip_config(hisifd, layer);
+	if (ret != 0) {
+		HISI_FB_ERR("hisi_dss_post_clip_config failed! ret = %d\n",
+			    ret);
+		goto err_return;
+	}
+
+	if (g_debug_ovl_online_composer) {
+		HISI_FB_INFO
+		    ("fb%d, scf output, clip_rect(%d,%d,%d,%d), "
+		     "aligned_rect(%d,%d,%d,%d), dst_rect(%d,%d,%d,%d).\n",
+		     hisifd->index, clip_rect->left, clip_rect->right,
+		     clip_rect->top, clip_rect->bottom, aligned_rect->x,
+		     aligned_rect->y, aligned_rect->w, aligned_rect->h,
+		     layer->dst_rect.x, layer->dst_rect.y, layer->dst_rect.w,
+		     layer->dst_rect.h);
+	}
+
+	if (csc_needed) {
+		ret = hisi_dss_csc_config(hisifd, layer, NULL);
+		if (ret != 0) {
+			HISI_FB_ERR("hisi_dss_csc_config failed! ret = %d\n",
+				    ret);
+			goto err_return;
+		}
+	}
+
+	ret =
+	    hisi_dss_ovl_layer_config(hisifd, pov_req, layer, wb_ov_block_rect,
+				      *has_base);
+	if (ret != 0) {
+		HISI_FB_ERR("hisi_dss_ovl_config failed, ret = %d\n", ret);
+		goto err_return;
+	}
+
+	ret =
+	    hisi_dss_mctl_ch_config(hisifd, pov_req, layer, NULL,
+				    pov_req->ovl_idx, wb_ov_block_rect,
+				    *has_base);
+	if (ret != 0) {
+		HISI_FB_ERR("hisi_dss_mctl_ch_config failed! ret = %d\n", ret);
+		goto err_return;
+	}
+
+	if (layer->chn_idx == DSS_RCHN_V2) {
+		mctl_idx = DSS_MCTL5;
+	} else {
+		mctl_idx = pov_req->ovl_idx;
+	}
+
+	ret =
+	    hisi_dss_ch_module_set_regs(hisifd, mctl_idx, layer->chn_idx, 0,
+					enable_cmdlist);
+	if (ret != 0) {
+		HISI_FB_ERR
+		    ("fb%d, hisi_dss_ch_module_set_regs failed! ret = %d\n",
+		     hisifd->index, ret);
+		goto err_return;
+	}
+
+	return 0;
+
+ err_return:
+	return ret;
+}
+
+/*******************************************************************************
+ **
+ */
+DEFINE_SEMAPHORE(hisi_dss_mmbuf_sem);
+static int mmbuf_refcount = 0;
+static int dss_sr_refcount = 0;
+
+struct hisifb_mmbuf {
+	struct list_head list_node;
+	uint32_t addr;
+	uint32_t size;
+};
+
+static struct list_head *g_mmbuf_list = NULL;
+
+static void hisifb_dss_on(struct hisi_fb_data_type *hisifd, int enable_cmdlist)
+{
+	int prev_refcount = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	down(&hisi_dss_mmbuf_sem);
+
+	prev_refcount = dss_sr_refcount++;
+	if (!prev_refcount) {
+		hisi_dss_qos_on(hisifd);
+		hisi_dss_mmbuf_on(hisifd);
+		hisi_dss_mif_on(hisifd);
+		hisi_dss_smmu_on(hisifd);
+		hisi_dss_scl_coef_on(hisifd, false, SCL_COEF_YUV_IDX);
+
+		if (enable_cmdlist) {
+			hisi_dss_cmdlist_qos_on(hisifd);
+		}
+	}
+
+	up(&hisi_dss_mmbuf_sem);
+
+	HISI_FB_DEBUG("fb%d, -, dss_sr_refcount=%d.\n", hisifd->index,
+		      dss_sr_refcount);
+}
+
+static void hisifb_dss_off(struct hisi_fb_data_type *hisifd, bool is_lp)
+{
+	struct hisifb_mmbuf *node, *_node_;
+	int new_refcount = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	down(&hisi_dss_mmbuf_sem);
+	new_refcount = --dss_sr_refcount;
+	WARN_ON(new_refcount < 0);
+
+	if (is_lp) {
+		if (!new_refcount) {
+			hisifd->ldi_data_gate_en = 0;
+
+			memset(&(hisifd->ov_block_infos_prev_prev), 0,
+			       HISI_DSS_OV_BLOCK_NUMS *
+			       sizeof(dss_overlay_block_t));
+			memset(&hisifd->ov_req_prev_prev, 0,
+			       sizeof(dss_overlay_t));
+			memset(&(hisifd->ov_block_infos_prev), 0,
+			       HISI_DSS_OV_BLOCK_NUMS *
+			       sizeof(dss_overlay_block_t));
+			memset(&hisifd->ov_req_prev, 0, sizeof(dss_overlay_t));
+			memset(&(hisifd->ov_block_infos), 0,
+			       HISI_DSS_OV_BLOCK_NUMS *
+			       sizeof(dss_overlay_block_t));
+			memset(&hisifd->ov_req, 0, sizeof(dss_overlay_t));
+		}
+	}
+
+	if (!g_mmbuf_list || is_lp) {
+		up(&hisi_dss_mmbuf_sem);
+		return;
+	}
+
+	if (!new_refcount) {
+		list_for_each_entry_safe(node, _node_, g_mmbuf_list, list_node) {
+			if ((node->addr > 0) && (node->size > 0)) {
+				gen_pool_free(hisifd->mmbuf_gen_pool,
+					      node->addr, node->size);
+				HISI_FB_DEBUG
+				    ("hisi_dss_mmbuf_free, addr=0x%x, size=%d.\n",
+				     node->addr, node->size);
+			}
+
+			list_del(&node->list_node);
+			kfree(node);
+		}
+	}
+	up(&hisi_dss_mmbuf_sem);
+
+	HISI_FB_DEBUG("fb%d, -, dss_sr_refcount=%d.\n", hisifd->index,
+		      dss_sr_refcount);
+}
+
+void *hisi_dss_mmbuf_init(struct hisi_fb_data_type *hisifd)
+{
+	struct gen_pool *pool = NULL;
+	int order = 3;
+	size_t size = MMBUF_SIZE_MAX;
+	uint32_t addr = MMBUF_BASE;
+	int prev_refcount = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	down(&hisi_dss_mmbuf_sem);
+
+	prev_refcount = mmbuf_refcount++;
+	if (!prev_refcount) {
+		pool = gen_pool_create(order, 0);
+		if (pool == NULL) {
+			HISI_FB_ERR("fb%d, gen_pool_create failed!",
+				    hisifd->index);
+			goto err_out;
+		}
+
+		if (gen_pool_add(pool, addr, size, 0) != 0) {
+			gen_pool_destroy(pool);
+			HISI_FB_ERR("fb%d, gen_pool_add failed!",
+				    hisifd->index);
+			goto err_out;
+		}
+
+		g_mmbuf_gen_pool = pool;
+
+		if (!g_mmbuf_list) {
+			g_mmbuf_list =
+			    kzalloc(sizeof(struct list_head), GFP_KERNEL);
+			BUG_ON(g_mmbuf_list == NULL);
+			INIT_LIST_HEAD(g_mmbuf_list);
+		}
+#ifdef CONFIG_SMMU_RWERRADDR_USED
+		if (!g_smmu_rwerraddr_virt) {
+			g_smmu_rwerraddr_virt =
+			    kmalloc(SMMU_RW_ERR_ADDR_SIZE,
+				    GFP_KERNEL | __GFP_DMA);
+			if (g_smmu_rwerraddr_virt) {
+				memset(g_smmu_rwerraddr_virt, 0,
+				       SMMU_RW_ERR_ADDR_SIZE);
+			} else {
+				HISI_FB_ERR
+				    ("kmalloc g_smmu_rwerraddr_virt fail.\n");
+			}
+		}
+#endif
+	}
+
+	hisifd->mmbuf_gen_pool = g_mmbuf_gen_pool;
+	hisifd->mmbuf_list = g_mmbuf_list;
+
+ err_out:
+	up(&hisi_dss_mmbuf_sem);
+
+	HISI_FB_DEBUG("fb%d, -, mmbuf_refcount=%d.\n", hisifd->index,
+		      mmbuf_refcount);
+
+	return pool;
+}
+
+void hisi_dss_mmbuf_deinit(struct hisi_fb_data_type *hisifd)
+{
+	int new_refcount = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);
+
+	hisifb_dss_off(hisifd, false);
+
+	down(&hisi_dss_mmbuf_sem);
+	new_refcount = --mmbuf_refcount;
+	WARN_ON(new_refcount < 0);
+
+	if (!new_refcount) {
+		if (g_mmbuf_gen_pool) {
+			gen_pool_destroy(g_mmbuf_gen_pool);
+			g_mmbuf_gen_pool = NULL;
+		}
+
+		if (g_mmbuf_list) {
+			kfree(g_mmbuf_list);
+			g_mmbuf_list = NULL;
+		}
+#ifdef CONFIG_SMMU_RWERRADDR_USED
+		if (g_smmu_rwerraddr_virt) {
+			kfree(g_smmu_rwerraddr_virt);
+			g_smmu_rwerraddr_virt = NULL;
+		}
+#endif
+	}
+
+	hisifd->mmbuf_gen_pool = NULL;
+	hisifd->mmbuf_list = NULL;
+	up(&hisi_dss_mmbuf_sem);
+
+	HISI_FB_DEBUG("fb%d, -, mmbuf_refcount=%d.\n", hisifd->index,
+		      mmbuf_refcount);
+}
+
+uint32_t hisi_dss_mmbuf_alloc(void *handle, uint32_t size)
+{
+	uint32_t addr = 0;
+	struct hisifb_mmbuf *node = NULL;
+	struct hisifb_mmbuf *mmbuf_node, *_node_;
+
+	if (NULL == handle) {
+		HISI_FB_ERR("handle is NULL!\n");
+		return addr;
+	}
+
+	if (NULL == g_mmbuf_list) {
+		HISI_FB_ERR("g_mmbuf_list is NULL!\n");
+		return addr;
+	}
+
+	if (size <= 0 || size > MMBUF_SIZE_MAX) {
+		HISI_FB_ERR("mmbuf size is invalid, size=%d!\n", size);
+		return addr;
+	}
+
+	down(&hisi_dss_mmbuf_sem);
+
+	addr = gen_pool_alloc(handle, size);
+	if (addr <= 0) {
+		HISI_FB_INFO("note: mmbuf not enough,addr=0x%x\n", addr);
+	} else {
+		node = kzalloc(sizeof(struct hisifb_mmbuf), GFP_KERNEL);
+		if (node) {
+			node->addr = addr;
+			node->size = size;
+			list_add_tail(&node->list_node, g_mmbuf_list);
+		} else {
+			HISI_FB_ERR("kzalloc struct hisifb_mmbuf fail!\n");
+		}
+
+		if ((addr & (MMBUF_ADDR_ALIGN - 1))
+		    || (size & (MMBUF_ADDR_ALIGN - 1))) {
+			HISI_FB_ERR
+			    ("addr(0x%x) is not %d bytes aligned, "
+			     "or size(0x%x) is not %d bytes"
+			     "aligned!\n", addr, MMBUF_ADDR_ALIGN, size,
+			     MMBUF_ADDR_ALIGN);
+
+			list_for_each_entry_safe(mmbuf_node, _node_,
+						 g_mmbuf_list, list_node) {
+				HISI_FB_ERR
+				    ("mmbuf_node_addr(0x%x), mmbuf_node_size(0x%x)!\n",
+				     mmbuf_node->addr, mmbuf_node->size);
+			}
+		}
+	}
+
+	up(&hisi_dss_mmbuf_sem);
+
+	HISI_FB_DEBUG("addr=0x%x, size=%d.\n", addr, size);
+
+	return addr;
+}
+
+void hisi_dss_mmbuf_free(void *handle, uint32_t addr, uint32_t size)
+{
+	struct hisifb_mmbuf *node, *_node_;
+
+	if (NULL == handle) {
+		HISI_FB_ERR("handle is NULL!\n");
+		return;
+	}
+
+	if (NULL == g_mmbuf_list) {
+		HISI_FB_ERR("g_mmbuf_list is NULL!\n");
+		return;
+	}
+
+	down(&hisi_dss_mmbuf_sem);
+
+	list_for_each_entry_safe(node, _node_, g_mmbuf_list, list_node) {
+		if ((node->addr == addr) && (node->size == size)) {
+			gen_pool_free(handle, addr, size);
+			list_del(&node->list_node);
+			kfree(node);
+		}
+	}
+
+	up(&hisi_dss_mmbuf_sem);
+
+	HISI_FB_DEBUG("addr=0x%x, size=%d.\n", addr, size);
+}
+
+void hisi_dss_mmbuf_info_clear(struct hisi_fb_data_type *hisifd, int idx)
+{
+	int i = 0;
+	dss_mmbuf_info_t *mmbuf_info = NULL;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON((idx < 0) || (idx >= HISI_DSS_CMDLIST_DATA_MAX));
+
+	mmbuf_info = &(hisifd->mmbuf_infos[idx]);
+	for (i = 0; i < DSS_CHN_MAX_DEFINE; i++) {
+		if (mmbuf_info->mm_used[i] == 1) {
+			hisi_dss_mmbuf_free(g_mmbuf_gen_pool,
+					    mmbuf_info->mm_base[i],
+					    mmbuf_info->mm_size[i]);
+
+			if (g_debug_ovl_online_composer) {
+				HISI_FB_INFO("fb%d, mm_base(0x%x, %d).\n",
+					     hisifd->index,
+					     mmbuf_info->mm_base[i],
+					     mmbuf_info->mm_size[i]);
+			}
+
+			mmbuf_info->mm_base[i] = 0;
+			mmbuf_info->mm_size[i] = 0;
+			mmbuf_info->mm_used[i] = 0;
+		}
+	}
+}
+
+void hisi_mmbuf_info_get_online(struct hisi_fb_data_type *hisifd)
+{
+	int tmp = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	tmp = (hisifd->frame_count + 1) % HISI_DSS_CMDLIST_DATA_MAX;
+	hisi_dss_mmbuf_info_clear(hisifd, tmp);
+
+	tmp = hisifd->frame_count % HISI_DSS_CMDLIST_DATA_MAX;
+	hisifd->mmbuf_info = &(hisifd->mmbuf_infos[tmp]);
+}
+
+/*******************************************************************************
+ **
+ */
+void hisi_dss_mmbuf_on(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+#if 0
+	outp32(hisifd->mmbuf_crg_base + SMC_LOCK, 0x5A5A5A5A);
+	outp32(hisifd->mmbuf_crg_base + SMC_MEM_LP, 0x00000712);
+#endif
+}
+
+static int hisi_overlay_fastboot(struct hisi_fb_data_type *hisifd)
+{
+	dss_overlay_t *pov_req_prev = NULL;
+	dss_overlay_block_t *pov_h_block_infos = NULL;
+	dss_overlay_block_t *pov_h_block = NULL;
+	dss_layer_t *layer = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +\n", hisifd->index);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		pov_req_prev = &(hisifd->ov_req_prev);
+		memset(pov_req_prev, 0, sizeof(dss_overlay_t));
+		pov_req_prev->ov_block_infos_ptr =
+		    (uint64_t) (&(hisifd->ov_block_infos_prev));
+		pov_req_prev->ov_block_nums = 1;
+		pov_req_prev->ovl_idx = DSS_OVL0;
+
+		pov_h_block_infos =
+		    (dss_overlay_block_t *) pov_req_prev->ov_block_infos_ptr;
+		pov_h_block = &(pov_h_block_infos[0]);
+		pov_h_block->layer_nums = 1;
+
+		layer = &(pov_h_block->layer_infos[0]);
+		layer->img.mmu_enable = 0;
+		layer->layer_idx = 0x0;
+		layer->chn_idx = DSS_RCHN_D0;
+		layer->need_cap = 0;
+
+		memcpy(&(hisifd->dss_module_default.rdma[DSS_RCHN_D0]),
+		       &(hisifd->dss_module_default.rdma[DSS_RCHN_D3]),
+		       sizeof(dss_rdma_t));
+		memcpy(&(hisifd->dss_module_default.dfc[DSS_RCHN_D0]),
+		       &(hisifd->dss_module_default.dfc[DSS_RCHN_D3]),
+		       sizeof(dss_dfc_t));
+		memcpy(&(hisifd->dss_module_default.ov[DSS_OVL0].ovl_layer[0]),
+		       &(hisifd->dss_module_default.ov[DSS_OVL0].ovl_layer[1]),
+		       sizeof(dss_ovl_layer_t));
+
+		memset(&(hisifd->dss_module_default.mctl_ch[DSS_RCHN_D0]), 0,
+		       sizeof(dss_mctl_ch_t));
+		memset(&(hisifd->dss_module_default.mctl[DSS_OVL0]), 0,
+		       sizeof(dss_mctl_t));
+
+		hisifd->dss_module_default.mctl_sys.chn_ov_sel[DSS_OVL0] =
+		    0xFFFFFFFF;
+		hisifd->dss_module_default.mctl_sys.ov_flush_en[DSS_OVL0] = 0x0;
+
+		if (is_mipi_cmd_panel(hisifd)) {
+			if (hisifd->vactive0_start_flag == 0) {
+				hisifd->vactive0_start_flag = 1;
+				hisifd->vactive0_end_flag = 1;
+			}
+		}
+	}
+
+	HISI_FB_DEBUG("fb%d, -\n", hisifd->index);
+
+	return 0;
+}
+
+int hisi_overlay_on(struct hisi_fb_data_type *hisifd, bool fastboot_enable)
+{
+	int ret = 0;
+	int ovl_idx = 0;
+	int mctl_idx = 0;
+	uint32_t cmdlist_idxs = 0;
+	int enable_cmdlist = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_DEBUG("fb%d, +\n", hisifd->index);
+
+	memset(&(hisifd->sbl), 0, sizeof(dss_sbl_t));
+	hisifd->sbl_enable = 0;
+	hisifd->sbl_lsensor_value = 0;
+	hisifd->sbl_level = 0;
+
+	hisifd->vactive0_start_flag = 0;
+	hisifd->vactive0_end_flag = 0;
+	hisifd->crc_flag = 0;
+
+	hisifd->dirty_region_updt.x = 0;
+	hisifd->dirty_region_updt.y = 0;
+	hisifd->dirty_region_updt.w = hisifd->panel_info.xres;
+	hisifd->dirty_region_updt.h = hisifd->panel_info.yres;
+
+	hisifd->resolution_rect.x = 0;
+	hisifd->resolution_rect.y = 0;
+	hisifd->resolution_rect.w = hisifd->panel_info.xres;
+	hisifd->resolution_rect.h = hisifd->panel_info.yres;
+
+	hisifd->res_updt_rect.x = 0;
+	hisifd->res_updt_rect.y = 0;
+	hisifd->res_updt_rect.w = hisifd->panel_info.xres;
+	hisifd->res_updt_rect.h = hisifd->panel_info.yres;
+
+	memset(&hisifd->ov_req, 0, sizeof(dss_overlay_t));
+	hisifd->ov_req.frame_no = 0xFFFFFFFF;
+
+	g_offline_cmdlist_idxs = 0;
+
+#if 0
+	if (g_dss_module_resource_initialized == 0) {
+		hisi_dss_module_default(hisifd);
+		g_dss_module_resource_initialized = 1;
+		hisifd->dss_module_resource_initialized = true;
+	}
+
+	if (!hisifd->dss_module_resource_initialized) {
+		if (hisifd->index != PRIMARY_PANEL_IDX) {
+			memcpy(&(hisifd->dss_module_default),
+			       &(hisifd_list[PRIMARY_PANEL_IDX]->
+				 dss_module_default), sizeof(dss_module_reg_t));
+		}
+		hisifd->dss_module_resource_initialized = true;
+	}
+#else
+	if ((hisifd->index == PRIMARY_PANEL_IDX) ||
+	    (hisifd->index == EXTERNAL_PANEL_IDX)) {
+		hisifb_activate_vsync(hisifd);
+	}
+
+	if (g_dss_module_resource_initialized == 0) {
+		hisi_dss_module_default(hisifd);
+		g_dss_module_resource_initialized = 1;
+		hisifd->dss_module_resource_initialized = true;
+	} else {
+		if (!hisifd->dss_module_resource_initialized) {
+			if (hisifd->index != PRIMARY_PANEL_IDX) {
+				if (hisifd_list[PRIMARY_PANEL_IDX]) {
+					memcpy(&(hisifd->dss_module_default),
+					       &(hisifd_list
+						 [PRIMARY_PANEL_IDX]->
+						 dss_module_default),
+					       sizeof(dss_module_reg_t));
+				}
+			}
+			hisifd->dss_module_resource_initialized = true;
+		}
+	}
+#endif
+
+	enable_cmdlist = g_enable_ovl_cmdlist_online;
+	hisifb_dss_on(hisifd, enable_cmdlist);
+
+	if ((hisifd->index == PRIMARY_PANEL_IDX) ||
+	    (hisifd->index == EXTERNAL_PANEL_IDX)) {
+		if (hisifd->index == PRIMARY_PANEL_IDX) {
+			ovl_idx = DSS_OVL0;
+			mctl_idx = DSS_MCTL0;
+		} else {
+			ovl_idx = DSS_OVL1;
+			mctl_idx = DSS_MCTL1;
+		}
+
+		if ((hisifd->index == EXTERNAL_PANEL_IDX)
+		    && hisifd->panel_info.fake_hdmi)
+			enable_cmdlist = 0;
+
+		ldi_data_gate(hisifd, true);
+
+		hisi_dss_mctl_on(hisifd, mctl_idx, enable_cmdlist,
+				 fastboot_enable);
+
+		if (fastboot_enable) {
+			hisi_overlay_fastboot(hisifd);
+		} else {
+			ret = hisi_dss_module_init(hisifd);
+			if (ret != 0) {
+				HISI_FB_ERR
+				    ("fb%d, failed to hisi_dss_module_init! ret = %d\n",
+				     hisifd->index, ret);
+				goto err_out;
+			}
+
+			if (enable_cmdlist) {
+				hisifd->set_reg = hisi_cmdlist_set_reg;
+
+				hisi_cmdlist_data_get_online(hisifd);
+
+				cmdlist_idxs =
+				    (0x1 << (ovl_idx + DSS_CMDLIST_OV0));
+				hisi_cmdlist_add_nop_node(hisifd, cmdlist_idxs,
+							  0, 0);
+			} else {
+				hisifd->set_reg = hisifb_set_reg;
+
+				hisi_dss_mctl_mutex_lock(hisifd, ovl_idx);
+			}
+
+			hisifd->ov_req_prev.ovl_idx = ovl_idx;
+
+			ret =
+			    hisi_dss_ovl_base_config(hisifd, NULL, NULL, NULL,
+						     ovl_idx, 0);
+			if (ret != 0) {
+				HISI_FB_ERR
+				    ("fb%d, faile to hisi_dss_ovl_base_config! ret=%d\n",
+				     hisifd->index, ret);
+				goto err_out;
+			}
+
+			ret =
+			    hisi_dss_mctl_ov_config(hisifd, NULL, ovl_idx,
+						    false, true);
+			if (ret != 0) {
+				HISI_FB_ERR
+				    ("fb%d, faile to hisi_dss_mctl_config! ret=%d\n",
+				     hisifd->index, ret);
+				goto err_out;
+			}
+
+			ret =
+			    hisi_dss_ov_module_set_regs(hisifd, NULL, ovl_idx,
+							enable_cmdlist, 1, 0,
+							true);
+			if (ret != 0) {
+				HISI_FB_ERR
+				    ("fb%d, failed to hisi_dss_module_config! ret = %d\n",
+				     hisifd->index, ret);
+				goto err_out;
+			}
+
+			if (enable_cmdlist) {
+				hisi_cmdlist_flush_cache(hisifd,
+							 hisifd->ion_client,
+							 cmdlist_idxs);
+				hisi_cmdlist_config_start(hisifd, mctl_idx,
+							  cmdlist_idxs, 0);
+			} else {
+				hisi_dss_mctl_mutex_unlock(hisifd, ovl_idx);
+			}
+
+			single_frame_update(hisifd);
+			enable_ldi(hisifd);
+			hisifb_frame_updated(hisifd);
+			hisifd->frame_count++;
+
+			if (g_debug_ovl_cmdlist) {
+				hisi_cmdlist_dump_all_node(hisifd, NULL,
+							   cmdlist_idxs);
+			}
+		}
+ err_out:
+		hisifb_deactivate_vsync(hisifd);
+	} else if (hisifd->index == AUXILIARY_PANEL_IDX) {
+		enable_cmdlist = g_enable_ovl_cmdlist_offline;
+
+		hisi_dss_mctl_on(hisifd, DSS_MCTL2, enable_cmdlist, 0);
+		hisi_dss_mctl_on(hisifd, DSS_MCTL3, enable_cmdlist, 0);
+		hisi_dss_mctl_on(hisifd, DSS_MCTL5, enable_cmdlist, 0);
+	} else {
+		HISI_FB_ERR("fb%d, not supported!", hisifd->index);
+	}
+
+	HISI_FB_DEBUG("fb%d, -\n", hisifd->index);
+
+	return 0;
+}
+
+int hisi_overlay_off(struct hisi_fb_data_type *hisifd)
+{
+	int ret = 0;
+	int ovl_idx = 0;
+	uint32_t cmdlist_pre_idxs = 0;
+	uint32_t cmdlist_idxs = 0;
+	int enable_cmdlist = 0;
+	dss_overlay_t *pov_req_prev = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	pov_req_prev = &(hisifd->ov_req_prev);
+
+	HISI_FB_DEBUG("fb%d, +\n", hisifd->index);
+
+	if ((hisifd->index == PRIMARY_PANEL_IDX) ||
+	    (hisifd->index == EXTERNAL_PANEL_IDX)) {
+		hisifb_activate_vsync(hisifd);
+
+		ret = hisi_vactive0_start_config(hisifd, pov_req_prev);
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("fb%d, hisi_vactive0_start_config failed! ret = %d\n",
+			     hisifd->index, ret);
+			goto err_out;
+		}
+
+		if (hisifd->aod_function == 1) {
+			HISI_FB_INFO("fb%d, aod mode\n", hisifd->index);
+			goto err_out;
+		}
+
+		if (hisifd->index == PRIMARY_PANEL_IDX) {
+			ovl_idx = DSS_OVL0;
+		} else {
+			ovl_idx = DSS_OVL1;
+		}
+
+		enable_cmdlist = g_enable_ovl_cmdlist_online;
+		if ((hisifd->index == EXTERNAL_PANEL_IDX)
+		    && hisifd->panel_info.fake_hdmi)
+			enable_cmdlist = 0;
+
+		ret = hisi_dss_module_init(hisifd);
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("fb%d, failed to hisi_dss_module_init! ret = %d\n",
+			     hisifd->index, ret);
+			goto err_out;
+		}
+
+		if (enable_cmdlist) {
+			hisifd->set_reg = hisi_cmdlist_set_reg;
+
+			hisi_cmdlist_data_get_online(hisifd);
+
+			ret =
+			    hisi_cmdlist_get_cmdlist_idxs(pov_req_prev,
+							  &cmdlist_pre_idxs,
+							  NULL);
+			if (ret != 0) {
+				HISI_FB_ERR
+				    ("fb%d, hisi_cmdlist_get_cmdlist_idxs "
+				     "pov_req_prev failed! ret = %d\n",
+				     hisifd->index, ret);
+				goto err_out;
+			}
+
+			cmdlist_idxs = (1 << (DSS_CMDLIST_OV0 + ovl_idx));
+			cmdlist_pre_idxs &= (~(cmdlist_idxs));
+
+			hisi_cmdlist_add_nop_node(hisifd, cmdlist_pre_idxs, 0,
+						  0);
+			hisi_cmdlist_add_nop_node(hisifd, cmdlist_idxs, 0, 0);
+		} else {
+			hisifd->set_reg = hisifb_set_reg;
+
+			hisi_dss_mctl_mutex_lock(hisifd, ovl_idx);
+			cmdlist_pre_idxs = ~0;
+		}
+
+		hisi_dss_prev_module_set_regs(hisifd, pov_req_prev,
+					      cmdlist_pre_idxs, enable_cmdlist,
+					      NULL);
+
+		ret =
+		    hisi_dss_ovl_base_config(hisifd, NULL, NULL, NULL, ovl_idx,
+					     0);
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("fb%d, faile to hisi_dss_ovl_base_config! ret=%d\n",
+			     hisifd->index, ret);
+			goto err_out;
+		}
+
+		ret =
+		    hisi_dss_mctl_ov_config(hisifd, NULL, ovl_idx, false, true);
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("fb%d, faile to hisi_dss_mctl_config! ret=%d\n",
+			     hisifd->index, ret);
+			goto err_out;
+		}
+
+		ret = hisi_dss_dirty_region_dbuf_config(hisifd, NULL);
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("fb%d, hisi_dss_dirty_region_dbuf_config failed! ret = %d\n",
+			     hisifd->index, ret);
+			goto err_out;
+		}
+
+		ret =
+		    hisi_dss_ov_module_set_regs(hisifd, NULL, ovl_idx,
+						enable_cmdlist, 1, 0, true);
+		if (ret != 0) {
+			HISI_FB_ERR
+			    ("fb%d, failed to hisi_dss_module_config! ret = %d\n",
+			     hisifd->index, ret);
+			goto err_out;
+		}
+
+		if (enable_cmdlist) {
+			hisi_cmdlist_config_stop(hisifd, cmdlist_pre_idxs);
+
+			cmdlist_idxs |= cmdlist_pre_idxs;
+			hisi_cmdlist_flush_cache(hisifd, hisifd->ion_client,
+						 cmdlist_idxs);
+
+			if (g_debug_ovl_cmdlist) {
+				hisi_cmdlist_dump_all_node(hisifd, NULL,
+							   cmdlist_idxs);
+			}
+
+			hisi_cmdlist_config_start(hisifd, ovl_idx, cmdlist_idxs, 0);
+		} else {
+			hisi_dss_mctl_mutex_unlock(hisifd, ovl_idx);
+		}
+
+		if (hisifd->panel_info.dirty_region_updt_support) {
+			hisi_dss_dirty_region_updt_config(hisifd, NULL);
+		}
+
+		ldi_data_gate(hisifd, true);
+
+		single_frame_update(hisifd);
+		hisifb_frame_updated(hisifd);
+
+		if (!hisi_dss_check_reg_reload_status(hisifd)) {
+			mdelay(20);
+		}
+
+		ldi_data_gate(hisifd, false);
+
+		if (is_mipi_cmd_panel(hisifd)) {
+			hisifd->ldi_data_gate_en = 1;
+		}
+
+		hisifd->frame_count++;
+ err_out:
+		hisifb_deactivate_vsync(hisifd);
+	} else if (hisifd->index == AUXILIARY_PANEL_IDX) {
+		;
+	} else {
+		HISI_FB_ERR("fb%d, not support !\n", hisifd->index);
+		BUG_ON(1);
+	}
+
+	if (hisifd->index == AUXILIARY_PANEL_IDX) {
+		hisifb_dss_off(hisifd, true);
+	} else {
+		hisifb_dss_off(hisifd, false);
+	}
+
+	hisifd->ldi_data_gate_en = 0;
+
+	memset(&(hisifd->ov_block_infos_prev_prev), 0,
+	       HISI_DSS_OV_BLOCK_NUMS * sizeof(dss_overlay_block_t));
+	memset(&hisifd->ov_req_prev_prev, 0, sizeof(dss_overlay_t));
+	memset(&(hisifd->ov_block_infos_prev), 0,
+	       HISI_DSS_OV_BLOCK_NUMS * sizeof(dss_overlay_block_t));
+	memset(&hisifd->ov_req_prev, 0, sizeof(dss_overlay_t));
+	memset(&(hisifd->ov_block_infos), 0,
+	       HISI_DSS_OV_BLOCK_NUMS * sizeof(dss_overlay_block_t));
+	memset(&hisifd->ov_req, 0, sizeof(dss_overlay_t));
+
+	HISI_FB_DEBUG("fb%d, -\n", hisifd->index);
+
+	return 0;
+}
+
+bool hisi_dss_check_reg_reload_status(struct hisi_fb_data_type *hisifd)
+{
+	mdelay(50);
+
+	return true;
+}
+
+bool hisi_dss_check_crg_sctrl_status(struct hisi_fb_data_type *hisifd)
+{
+	uint32_t crg_state_check = 0;
+	uint32_t sctrl_mmbuf_dss_check = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	crg_state_check = inp32(hisifd->peri_crg_base + PERCLKEN3);
+	if ((crg_state_check & 0x23000) != 0x23000) {
+		HISI_FB_ERR
+		    ("dss crg_clk_enable failed, crg_state_check = 0x%x\n",
+		     crg_state_check);
+		return false;
+	}
+
+	crg_state_check = inp32(hisifd->peri_crg_base + PERRSTSTAT3);
+	if ((crg_state_check | 0xfffff3ff) != 0xfffff3ff) {
+		HISI_FB_ERR("dss crg_reset failed, crg_state_check = 0x%x\n",
+			    crg_state_check);
+		return false;
+	}
+
+	crg_state_check = inp32(hisifd->peri_crg_base + ISOSTAT);
+	if ((crg_state_check | 0xffffffbf) != 0xffffffbf) {
+		HISI_FB_ERR("dss iso_disable failed, crg_state_check = 0x%x\n",
+			    crg_state_check);
+		return false;
+	}
+
+	crg_state_check = inp32(hisifd->peri_crg_base + PERPWRSTAT);
+	if ((crg_state_check & 0x20) != 0x20) {
+		HISI_FB_ERR
+		    ("dss subsys regulator_enabel failed, crg_state_check = 0x%x\n",
+		     crg_state_check);
+		return false;
+	}
+
+	sctrl_mmbuf_dss_check = inp32(hisifd->sctrl_base + SCPERCLKEN1);
+	if ((sctrl_mmbuf_dss_check & 0x1000000) != 0x1000000) {
+		HISI_FB_ERR
+		    ("dss subsys mmbuf_dss_clk_enable failed, sctrl_mmbuf_dss_check = 0x%x\n",
+		     sctrl_mmbuf_dss_check);
+		return false;
+	}
+
+	return true;
+}
+
+int hisi_overlay_ioctl_handler(struct hisi_fb_data_type *hisifd,
+			       uint32_t cmd, void __user *argp)
+{
+	int ret = 0;
+	uint32_t timediff = 0;
+	struct timeval tv0;
+	struct timeval tv1;
+	struct hisi_panel_info *pinfo = NULL;
+
+	if (NULL == hisifd) {
+		HISI_FB_ERR("NULL Pointer\n");
+		return -EINVAL;
+	}
+	pinfo = &(hisifd->panel_info);
+
+	switch (cmd) {
+	case HISIFB_OV_ONLINE_PLAY:
+		if (hisifd->ov_online_play) {
+			if (g_debug_ovl_online_composer_timediff & 0x1)
+				hisifb_get_timestamp(&tv0);
+
+			down(&hisifd->blank_sem);
+			ret = hisifd->ov_online_play(hisifd, argp);
+			if (ret != 0) {
+				HISI_FB_ERR("fb%d ov_online_play failed!\n",
+					    hisifd->index);
+			}
+			up(&hisifd->blank_sem);
+
+			if (g_debug_ovl_online_composer_timediff & 0x1) {
+				hisifb_get_timestamp(&tv1);
+				timediff = hisifb_timestamp_diff(&tv0, &tv1);
+				if (timediff >=
+				    g_debug_ovl_online_composer_time_threshold)
+					HISI_FB_ERR
+					    ("ONLING_IOCTL_TIMEDIFF is %u us!\n",
+					     timediff);
+			}
+
+			if (ret == 0) {
+				if (hisifd->bl_update) {
+					hisifd->bl_update(hisifd);
+				}
+			}
+		}
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+int hisi_overlay_init(struct hisi_fb_data_type *hisifd)
+{
+	char wq_name[128] = { 0 };
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(hisifd->dss_base == NULL);
+
+	hisifd->dss_module_resource_initialized = false;
+
+	hisifd->vactive0_start_flag = 0;
+	hisifd->vactive0_end_flag = 0;
+	init_waitqueue_head(&hisifd->vactive0_start_wq);
+	hisifd->ldi_data_gate_en = 0;
+
+	hisifd->crc_flag = 0;
+
+	hisifd->frame_update_flag = 0;
+
+	memset(&hisifd->ov_req, 0, sizeof(dss_overlay_t));
+	memset(&hisifd->dss_module, 0, sizeof(dss_module_reg_t));
+	memset(&hisifd->dss_module_default, 0, sizeof(dss_module_reg_t));
+
+	hisifd->dirty_region_updt.x = 0;
+	hisifd->dirty_region_updt.y = 0;
+	hisifd->dirty_region_updt.w = hisifd->panel_info.xres;
+	hisifd->dirty_region_updt.h = hisifd->panel_info.yres;
+
+	hisifd->resolution_rect.x = 0;
+	hisifd->resolution_rect.y = 0;
+	hisifd->resolution_rect.w = hisifd->panel_info.xres;
+	hisifd->resolution_rect.h = hisifd->panel_info.yres;
+
+	hisifd->res_updt_rect.x = 0;
+	hisifd->res_updt_rect.y = 0;
+	hisifd->res_updt_rect.w = hisifd->panel_info.xres;
+	hisifd->res_updt_rect.h = hisifd->panel_info.yres;
+
+	hisifd->pan_display_fnc = hisi_overlay_pan_display;
+	hisifd->ov_ioctl_handler = hisi_overlay_ioctl_handler;
+
+	hisifd->dss_debug_wq = NULL;
+	hisifd->ldi_underflow_wq = NULL;
+	hisifd->rch2_ce_end_wq = NULL;
+	hisifd->rch4_ce_end_wq = NULL;
+	hisifd->dpp_ce_end_wq = NULL;
+	hisifd->hiace_end_wq = NULL;
+
+	if ((hisifd->index == PRIMARY_PANEL_IDX) ||
+	    (hisifd->index == EXTERNAL_PANEL_IDX
+	     && !hisifd->panel_info.fake_hdmi)) {
+		snprintf(wq_name, 128, "fb%d_dss_debug", hisifd->index);
+		hisifd->dss_debug_wq = create_singlethread_workqueue(wq_name);
+		if (!hisifd->dss_debug_wq) {
+			HISI_FB_ERR
+			    ("fb%d, create dss debug workqueue failed!\n",
+			     hisifd->index);
+			return -EINVAL;
+		}
+		INIT_WORK(&hisifd->dss_debug_work, hisi_dss_debug_func);
+
+		snprintf(wq_name, 128, "fb%d_ldi_underflow", hisifd->index);
+		hisifd->ldi_underflow_wq =
+		    create_singlethread_workqueue(wq_name);
+		if (!hisifd->ldi_underflow_wq) {
+			HISI_FB_ERR
+			    ("fb%d, create ldi underflow workqueue failed!\n",
+			     hisifd->index);
+			return -EINVAL;
+		}
+		INIT_WORK(&hisifd->ldi_underflow_work,
+			  hisi_ldi_underflow_handle_func);
+	}
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		hisifd->set_reg = hisi_cmdlist_set_reg;
+		hisifd->ov_online_play = hisi_ov_online_play;
+		hisifd->ov_wb_isr_handler = NULL;
+		hisifd->ov_vactive0_start_isr_handler =
+		    hisi_vactive0_start_isr_handler;
+
+		hisifd->crc_isr_handler = NULL;
+
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		hisifd->set_reg = hisifb_set_reg;
+		hisifd->ov_online_play = hisi_ov_online_play;
+		hisifd->ov_wb_isr_handler = NULL;
+		hisifd->ov_vactive0_start_isr_handler =
+		    hisi_vactive0_start_isr_handler;
+
+		hisifd->crc_isr_handler = NULL;
+	} else if (hisifd->index == AUXILIARY_PANEL_IDX) {
+		hisifd->set_reg = hisi_cmdlist_set_reg;
+		hisifd->ov_online_play = NULL;
+		hisifd->ov_wb_isr_handler = NULL;
+		hisifd->ov_vactive0_start_isr_handler = NULL;
+
+		hisifd->crc_isr_handler = NULL;
+	} else {
+		HISI_FB_ERR("fb%d not support this device!\n", hisifd->index);
+		return -EINVAL;
+	}
+
+	hisi_cmdlist_init(hisifd);
+
+	hisi_dss_mmbuf_init(hisifd);
+
+	return 0;
+}
+
+int hisi_overlay_deinit(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+	}
+
+	if (hisifd->rch4_ce_end_wq) {
+		destroy_workqueue(hisifd->rch4_ce_end_wq);
+		hisifd->rch4_ce_end_wq = NULL;
+	}
+
+	if (hisifd->rch2_ce_end_wq) {
+		destroy_workqueue(hisifd->rch2_ce_end_wq);
+		hisifd->rch2_ce_end_wq = NULL;
+	}
+
+	if (hisifd->dpp_ce_end_wq) {
+		destroy_workqueue(hisifd->dpp_ce_end_wq);
+		hisifd->dpp_ce_end_wq = NULL;
+	}
+
+	if (hisifd->hiace_end_wq) {
+		destroy_workqueue(hisifd->hiace_end_wq);
+		hisifd->hiace_end_wq = NULL;
+	}
+
+	if (hisifd->dss_debug_wq) {
+		destroy_workqueue(hisifd->dss_debug_wq);
+		hisifd->dss_debug_wq = NULL;
+	}
+
+	if (hisifd->ldi_underflow_wq) {
+		destroy_workqueue(hisifd->ldi_underflow_wq);
+		hisifd->ldi_underflow_wq = NULL;
+	}
+
+	hisi_cmdlist_deinit(hisifd);
+
+	hisi_dss_mmbuf_deinit(hisifd);
+
+	return 0;
+}
+
+void hisi_vactive0_start_isr_handler(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+
+	if (is_mipi_cmd_panel(hisifd) && (hisifd->frame_update_flag == 0)) {
+		hisifd->vactive0_start_flag = 1;
+	} else {
+		hisifd->vactive0_start_flag++;
+	}
+
+	wake_up_interruptible_all(&hisifd->vactive0_start_wq);
+}
+
+int hisi_vactive0_start_config(struct hisi_fb_data_type *hisifd,
+			       dss_overlay_t *pov_req)
+{
+	int ret = 0;
+	int ret1 = 0;
+	int times = 0;
+	uint32_t prev_vactive0_start = 0;
+	uint32_t isr_s1 = 0;
+	uint32_t isr_s2 = 0;
+	uint32_t isr_s2_mask = 0;
+	char __iomem *ldi_base = NULL;
+	struct timeval tv0;
+	struct timeval tv1;
+	dss_overlay_t *pov_req_dump = NULL;
+	dss_overlay_t *pov_req_prev = NULL;
+	dss_overlay_t *pov_req_prev_prev = NULL;
+	uint32_t cmdlist_idxs = 0;
+	uint32_t cmdlist_idxs_prev = 0;
+	uint32_t cmdlist_idxs_prev_prev = 0;
+	uint32_t read_value[4] = { 0 };
+	uint32_t ldi_vstate = 0;
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_req == NULL);
+
+	pov_req_prev = &(hisifd->ov_req_prev);
+	pov_req_prev_prev = &(hisifd->ov_req_prev_prev);
+	if (is_mipi_cmd_panel(hisifd) && (hisifd->frame_update_flag == 0)) {
+		pov_req_dump = &(hisifd->ov_req_prev_prev);
+		if (hisifd->vactive0_start_flag == 1) {
+			hisifd->vactive0_start_flag = 0;
+			single_frame_update(hisifd);
+		}
+
+		if (hisifd->vactive0_start_flag == 0) {
+			hisifb_get_timestamp(&tv0);
+
+ REDO_0:
+			ret =
+			    wait_event_interruptible_timeout(hisifd->vactive0_start_wq,
+							     hisifd->vactive0_start_flag,
+							     msecs_to_jiffies
+							     (DSS_COMPOSER_TIMEOUT_THRESHOLD_ASIC));
+			if (ret == -ERESTARTSYS) {
+				if (times < 50) {
+					times++;
+					mdelay(10);
+					goto REDO_0;
+				}
+			}
+			times = 0;
+
+			if (ret <= 0) {
+				hisifb_get_timestamp(&tv1);
+
+				ret1 =
+				    hisi_cmdlist_get_cmdlist_idxs(pov_req_prev,
+								  &cmdlist_idxs_prev,
+								  NULL);
+				if (ret1 != 0) {
+					HISI_FB_INFO
+					    ("fb%d, hisi_cmdlist_get_cmdlist_idxs "
+					     "pov_req_prev failed! ret = %d\n",
+					     hisifd->index, ret1);
+				}
+
+				ret1 =
+				    hisi_cmdlist_get_cmdlist_idxs
+				    (pov_req_prev_prev, &cmdlist_idxs_prev_prev,
+				     NULL);
+				if (ret1 != 0) {
+					HISI_FB_INFO
+					    ("fb%d, hisi_cmdlist_get_cmdlist_idxs "
+					     "pov_req_prev_prev failed! ret = %d\n",
+					     hisifd->index, ret1);
+				}
+
+				cmdlist_idxs =
+				    cmdlist_idxs_prev | cmdlist_idxs_prev_prev;
+
+				HISI_FB_ERR
+				    ("fb%d, 1wait_for vactive0_start_flag timeout!ret=%d, "
+				     "vactive0_start_flag=%d, pre_pre_frame_no=%u, "
+				     "frame_no=%u, TIMESTAMP_DIFF is %u us, "
+				     "cmdlist_idxs_prev=0x%x, cmdlist_idxs_prev_prev=0x%x, "
+				     "cmdlist_idxs=0x%x, itf0_ints=0x%x\n",
+				     hisifd->index, ret,
+				     hisifd->vactive0_start_flag,
+				     pov_req_dump->frame_no, pov_req->frame_no,
+				     hisifb_timestamp_diff(&tv0, &tv1),
+				     cmdlist_idxs_prev, cmdlist_idxs_prev_prev,
+				     cmdlist_idxs,
+				     inp32(hisifd->dss_base + DSS_LDI0_OFFSET +
+					   LDI_CPU_ITF_INTS)
+				    );
+
+				if (g_debug_ovl_online_composer_hold) {
+					dumpDssOverlay(hisifd, pov_req_dump,
+						       (g_debug_need_save_file
+							== 1));
+					hisi_cmdlist_dump_all_node(hisifd, NULL,
+								   cmdlist_idxs);
+					mdelay(HISI_DSS_COMPOSER_HOLD_TIME);
+				}
+
+				if (g_debug_ldi_underflow_clear
+				    && g_ldi_data_gate_en) {
+#if 1
+					hisi_cmdlist_config_reset(hisifd,
+								  pov_req_dump,
+								  cmdlist_idxs);
+
+					ldi_data_gate(hisifd, false);
+					mdelay(10);
+#else
+					if (hisifd->ldi_underflow_wq) {
+						queue_work(hisifd->
+							   ldi_underflow_wq,
+							   &hisifd->
+							   ldi_underflow_work);
+					}
+#endif
+
+					mipi_panel_check_reg(hisifd,
+							     read_value);
+					ldi_vstate =
+					    inp32(hisifd->dss_base +
+						  DSS_LDI0_OFFSET + LDI_VSTATE);
+					HISI_FB_ERR("fb%d, "
+						    "Number of the Errors on DSI : 0x05 = 0x%x\n"
+						    "Display Power Mode : 0x0A = 0x%x\n"
+						    "Display Signal Mode : 0x0E = 0x%x\n"
+						    "Display Self-Diagnostic Result : 0x0F = 0x%x\n"
+						    "LDI vstate : 0x%x, LDI dpi0_hstate : 0x%x\n",
+						    hisifd->index,
+						    read_value[0],
+						    read_value[1],
+						    read_value[2],
+						    read_value[3], ldi_vstate,
+						    inp32(hisifd->dss_base +
+							  DSS_LDI0_OFFSET +
+							  LDI_DPI0_HSTATE));
+
+					memset(&(hisifd->ov_block_infos_prev), 0,
+					       HISI_DSS_OV_BLOCK_NUMS *
+					       sizeof(dss_overlay_block_t));
+
+					memset(&(hisifd->ov_req_prev), 0,
+					       sizeof(dss_overlay_t));
+
+					if (LDI_VSTATE_V_WAIT_TE0 == ldi_vstate) {
+						vactive_timeout_count++;
+						if ((vactive_timeout_count >= 3)
+						    && hisifd->panel_info.esd_enable) {
+							hisifd->esd_recover_state =
+								ESD_RECOVER_STATE_START;
+							if (hisifd->esd_ctrl.esd_check_wq) {
+								queue_work(hisifd->esd_ctrl.esd_check_wq,
+								     &(hisifd->esd_ctrl.esd_check_work));
+							}
+						}
+					}
+					return 0;
+				}
+
+				ldi_data_gate(hisifd, false);
+				mipi_panel_check_reg(hisifd, read_value);
+				ldi_vstate =
+				    inp32(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_VSTATE);
+				HISI_FB_ERR("fb%d, "
+					    "Number of the Errors on DSI : 0x05 = 0x%x\n"
+					    "Display Power Mode : 0x0A = 0x%x\n"
+					    "Display Signal Mode : 0x0E = 0x%x\n"
+					    "Display Self-Diagnostic Result : 0x0F = 0x%x\n"
+					    "LDI vstate : 0x%x, LDI dpi0_hstate : 0x%x \n",
+					    hisifd->index, read_value[0],
+					    read_value[1], read_value[2],
+					    read_value[3], ldi_vstate,
+					    inp32(hisifd->dss_base +
+						  DSS_LDI0_OFFSET +
+						  LDI_DPI0_HSTATE));
+
+ REDO_1:
+				ret =
+				    wait_event_interruptible_timeout(hisifd->vactive0_start_wq,
+								     hisifd->vactive0_start_flag,
+								     msecs_to_jiffies
+								     (DSS_COMPOSER_TIMEOUT_THRESHOLD_ASIC));
+				if (ret == -ERESTARTSYS) {
+					if (times < 50) {
+						times++;
+						mdelay(10);
+						goto REDO_1;
+					}
+				}
+				times = 0;
+
+				if (ret <= 0) {
+					HISI_FB_ERR
+					    ("fb%d, 2wait_for vactive0_start_flag timeout!ret=%d, "
+					     "vactive0_start_flag=%d, frame_no=%u.\n",
+					     hisifd->index, ret,
+					     hisifd->vactive0_start_flag,
+					     pov_req_dump->frame_no);
+
+					ldi_data_gate(hisifd, false);
+					ret = -ETIMEDOUT;
+					if (LDI_VSTATE_V_WAIT_TE0 == ldi_vstate) {
+						vactive_timeout_count++;
+						if ((vactive_timeout_count >= 1)
+						    && hisifd->panel_info.esd_enable) {
+							hisifd->esd_recover_state =
+							    ESD_RECOVER_STATE_START;
+							if (hisifd->esd_ctrl.esd_check_wq) {
+								queue_work(hisifd->esd_ctrl.esd_check_wq,
+								     &(hisifd->esd_ctrl.esd_check_work));
+							}
+							ret = 0;
+						}
+					}
+				} else {
+					ldi_data_gate(hisifd, true);
+					ret = 0;
+				}
+			} else {
+				ldi_data_gate(hisifd, true);
+				ret = 0;
+			}
+		}
+
+		ldi_data_gate(hisifd, true);
+		hisifd->vactive0_start_flag = 0;
+		hisifd->vactive0_end_flag = 0;
+		if (ret >= 0) {
+			vactive_timeout_count = 0;
+		}
+	} else {
+		pov_req_dump = &(hisifd->ov_req_prev);
+
+		hisifb_get_timestamp(&tv0);
+		ldi_data_gate(hisifd, false);
+		prev_vactive0_start = hisifd->vactive0_start_flag;
+
+ REDO_2:
+		ret =
+		    wait_event_interruptible_timeout(hisifd->vactive0_start_wq,
+						     (prev_vactive0_start !=
+						      hisifd->vactive0_start_flag),
+						     msecs_to_jiffies
+						     (DSS_COMPOSER_TIMEOUT_THRESHOLD_ASIC));
+		if (ret == -ERESTARTSYS) {
+			if (times < 50) {
+				times++;
+				mdelay(10);
+				goto REDO_2;
+			}
+		}
+
+		if (ret <= 0) {
+			hisifb_get_timestamp(&tv1);
+			ret =
+			    hisi_cmdlist_get_cmdlist_idxs(pov_req_dump,
+							  &cmdlist_idxs, NULL);
+			if (ret != 0) {
+				HISI_FB_INFO
+				    ("fb%d, hisi_cmdlist_get_cmdlist_idxs "
+				     "pov_req_prev failed! ret = %d\n",
+				     hisifd->index, ret);
+			}
+
+			HISI_FB_ERR
+			    ("fb%d, 1wait_for vactive0_start_flag timeout!ret=%d, "
+			     "vactive0_start_flag=%d, frame_no=%u, "
+			     "TIMESTAMP_DIFF is %u us, cmdlist_idxs=0x%x!\n",
+			     hisifd->index, ret,
+			     hisifd->vactive0_start_flag,
+			     pov_req_dump->frame_no,
+			     hisifb_timestamp_diff(&tv0, &tv1),
+			     cmdlist_idxs);
+
+			if (g_debug_ovl_online_composer_hold) {
+				dumpDssOverlay(hisifd, pov_req_dump,
+					       (g_debug_need_save_file == 1));
+				hisi_cmdlist_dump_all_node(hisifd, NULL,
+							   cmdlist_idxs);
+				mdelay(HISI_DSS_COMPOSER_HOLD_TIME);
+			}
+			mipi_dsi_reset(hisifd);
+
+			ret = -ETIMEDOUT;
+		} else {
+			ret = 0;
+		}
+	}
+
+	if (ret == -ETIMEDOUT) {
+		if (pov_req_dump && pov_req_dump->ovl_idx == DSS_OVL0) {
+			isr_s1 = inp32(hisifd->dss_base + GLB_CPU_PDP_INTS);
+			isr_s2_mask =
+			    inp32(hisifd->dss_base + DSS_LDI0_OFFSET +
+				  LDI_CPU_ITF_INT_MSK);
+			isr_s2 =
+			    inp32(hisifd->dss_base + DSS_LDI0_OFFSET +
+				  LDI_CPU_ITF_INTS);
+			ldi_base = hisifd->dss_base + DSS_LDI0_OFFSET;
+		} else if (pov_req_dump && pov_req_dump->ovl_idx == DSS_OVL1) {
+			isr_s1 = inp32(hisifd->dss_base + GLB_CPU_SDP_INTS);
+			isr_s2_mask =
+			    inp32(hisifd->dss_base + DSS_LDI1_OFFSET +
+				  LDI_CPU_ITF_INT_MSK);
+			isr_s2 =
+			    inp32(hisifd->dss_base + DSS_LDI1_OFFSET +
+				  LDI_CPU_ITF_INTS);
+			ldi_base = hisifd->dss_base + DSS_LDI1_OFFSET;
+		} else {
+			;
+		}
+
+		HISI_FB_ERR("fb%d, isr_s1=0x%x, isr_s2_mask=0x%x, isr_s2=0x%x, "
+			    "LDI_CTRL(0x%x), LDI_FRM_MSK(0x%x).\n",
+			    hisifd->index, isr_s1, isr_s2_mask, isr_s2,
+			    inp32(ldi_base + LDI_CTRL),
+			    inp32(ldi_base + LDI_FRM_MSK));
+	}
+
+	return ret;
+}
+
+int hisi_crc_enable(struct hisi_fb_data_type *hisifd, dss_overlay_t *pov_req)
+{
+	uint32_t tmp = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_req == NULL);
+
+	if (g_enable_crc_debug == 0)
+		return 0;
+
+	if (pov_req->crc_enable_status <= 0)
+		return 0;
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		tmp = inp32(hisifd->dss_base + DSS_DPP_OFFSET + DPP_INT_MSK);
+
+		if (pov_req->crc_enable_status == DSS_CRC_OV_EN) {
+			outp32(hisifd->dss_base + DSS_DBG_OFFSET +
+			       DBG_CRC_OV0_EN, 0x1);
+
+			tmp &= ~BIT_CRC_OV0_INT;
+		} else if (pov_req->crc_enable_status == DSS_CRC_LDI_EN) {
+
+			tmp &= ~BIT_CRC_ITF0_INT;
+		} else if (pov_req->crc_enable_status == DSS_CRC_SUM_EN) {
+			outp32(hisifd->dss_base + DSS_DBG_OFFSET +
+			       DBG_CRC_SUM_EN, 0x1);
+
+			tmp &= ~BIT_CRC_SUM_INT;
+		}
+		outp32(hisifd->dss_base + DSS_DPP_OFFSET + DPP_INT_MSK, tmp);
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		tmp = inp32(hisifd->dss_base + DSS_DPP_OFFSET + DPP_INT_MSK);
+
+		if (pov_req->crc_enable_status == DSS_CRC_OV_EN) {
+			outp32(hisifd->dss_base + DSS_DBG_OFFSET +
+			       DBG_CRC_OV1_EN, 0x1);
+
+			tmp &= ~BIT_CRC_OV1_INT;
+		} else if (pov_req->crc_enable_status == DSS_CRC_LDI_EN) {
+			outp32(hisifd->dss_base + GLB_CRC_LDI1_EN, 0x1);
+
+			tmp &= ~BIT_CRC_ITF1_INT;
+		} else if (pov_req->crc_enable_status == DSS_CRC_SUM_EN) {
+			outp32(hisifd->dss_base + DSS_DBG_OFFSET +
+			       DBG_CRC_SUM_EN, 0x1);
+
+			tmp &= ~BIT_CRC_SUM_INT;
+		}
+		outp32(hisifd->dss_base + DSS_DPP_OFFSET + DPP_INT_MSK, tmp);
+	} else {
+		HISI_FB_ERR("fb%d, not support!", hisifd->index);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int hisi_crc_disable(struct hisi_fb_data_type *hisifd)
+{
+	uint32_t tmp = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		outp32(hisifd->dss_base + DSS_DBG_OFFSET + DBG_CRC_OV0_EN, 0x0);
+
+		outp32(hisifd->dss_base + DSS_DBG_OFFSET + DBG_CRC_SUM_EN, 0x0);
+		tmp = inp32(hisifd->dss_base + DSS_DPP_OFFSET + DPP_INT_MSK);
+		tmp |= (BIT_CRC_OV0_INT | BIT_CRC_ITF0_INT | BIT_CRC_SUM_INT);
+		outp32(hisifd->dss_base + DSS_DPP_OFFSET + DPP_INT_MSK, tmp);
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		outp32(hisifd->dss_base + DSS_DBG_OFFSET + DBG_CRC_OV1_EN, 0x0);
+		outp32(hisifd->dss_base + GLB_CRC_LDI1_EN, 0x0);
+		outp32(hisifd->dss_base + DSS_DBG_OFFSET + DBG_CRC_SUM_EN, 0x0);
+		tmp = inp32(hisifd->dss_base + DSS_DPP_OFFSET + DPP_INT_MSK);
+		tmp |= (BIT_CRC_OV1_INT | BIT_CRC_ITF1_INT | BIT_CRC_SUM_INT);
+		outp32(hisifd->dss_base + DSS_DPP_OFFSET + DPP_INT_MSK, tmp);
+	} else {
+		HISI_FB_ERR("fb%d, not support!", hisifd->index);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int hisi_crc_get_result(struct hisi_fb_data_type *hisifd,
+			       dss_overlay_t *pov_req)
+{
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_req == NULL);
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		if (pov_req->crc_enable_status == DSS_CRC_OV_EN) {
+			pov_req->crc_info.crc_ov_result =
+			    inp32(hisifd->dss_base + DSS_DBG_OFFSET +
+				  DBG_CRC_DBG_OV0);
+			pov_req->crc_info.crc_ov_frm =
+			    inp32(hisifd->dss_base + DSS_DBG_OFFSET +
+				  DBG_CRC_OV0_FRM);
+		} else if (pov_req->crc_enable_status == DSS_CRC_LDI_EN) {
+			pov_req->crc_info.crc_ldi_result =
+			    inp32(hisifd->dss_base + GLB_CRC_DBG_LDI0);
+			pov_req->crc_info.crc_ldi_frm =
+			    inp32(hisifd->dss_base + GLB_CRC_LDI0_FRM);
+		} else if (pov_req->crc_enable_status == DSS_CRC_SUM_EN) {
+			pov_req->crc_info.crc_ldi_result =
+			    inp32(hisifd->dss_base + DSS_DBG_OFFSET +
+				  DBG_CRC_DBG_SUM);
+			pov_req->crc_info.crc_ldi_frm =
+			    inp32(hisifd->dss_base + DSS_DBG_OFFSET +
+				  DBG_CRC_SUM_FRM);
+		}
+	} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+		if (pov_req->crc_enable_status == DSS_CRC_OV_EN) {
+			pov_req->crc_info.crc_ov_result =
+			    inp32(hisifd->dss_base + DSS_DBG_OFFSET +
+				  DBG_CRC_DBG_OV1);
+			pov_req->crc_info.crc_ov_frm =
+			    inp32(hisifd->dss_base + DSS_DBG_OFFSET +
+				  DBG_CRC_OV1_FRM);
+		} else if (pov_req->crc_enable_status == DSS_CRC_LDI_EN) {
+			pov_req->crc_info.crc_ldi_result =
+			    inp32(hisifd->dss_base + GLB_CRC_DBG_LDI1);
+			pov_req->crc_info.crc_ldi_frm =
+			    inp32(hisifd->dss_base + GLB_CRC_LDI1_FRM);
+		} else if (pov_req->crc_enable_status == DSS_CRC_SUM_EN) {
+			pov_req->crc_info.crc_ldi_result =
+			    inp32(hisifd->dss_base + DSS_DBG_OFFSET +
+				  DBG_CRC_DBG_SUM);
+			pov_req->crc_info.crc_ldi_frm =
+			    inp32(hisifd->dss_base + DSS_DBG_OFFSET +
+				  DBG_CRC_SUM_FRM);
+		}
+	} else {
+		HISI_FB_ERR("fb%d, not support!", hisifd->index);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+void hisi_crc_isr_handler(struct hisi_fb_data_type *hisifd)
+{
+	BUG_ON(hisifd == NULL);
+
+	hisi_crc_disable(hisifd);
+
+	hisifd->crc_flag++;
+	wake_up_interruptible_all(&hisifd->crc_wq);
+}
+
+int hisi_crc_config(struct hisi_fb_data_type *hisifd, dss_overlay_t *pov_req)
+{
+	int ret = 0;
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_req == NULL);
+
+	if (g_enable_crc_debug == 0)
+		return 0;
+
+	if (pov_req->crc_enable_status <= 0)
+		return 0;
+
+#if 1
+	mdelay(100);
+	hisi_crc_get_result(hisifd, pov_req);
+	hisi_crc_disable(hisifd);
+#else
+	prev_crc_flag = hisifd->crc_flag;
+	ret = wait_event_interruptible_timeout(hisifd->crc_wq,
+					       (prev_crc_flag !=
+						hisifd->crc_flag), 1 * HZ);
+	if (ret == -ERESTARTSYS) {
+		HISI_FB_DEBUG
+		    ("fb%d, wait_for crc_flag, "
+		     "Returns -ERESTARTSYS if interrupted by a signal!\n",
+		     hisifd->index);
+		ret =
+		    wait_event_interruptible_timeout(hisifd->crc_wq,
+						     (prev_crc_flag !=
+						      hisifd->crc_flag), 1 * HZ);
+	}
+
+	if (ret <= 0) {
+		HISI_FB_ERR("fb%d, wait_for crc_flag timeout!ret=%d, "
+			    "prev_crc_flag=%d, crc_flag=%d\n",
+			    hisifd->index, ret, prev_crc_flag,
+			    hisifd->crc_flag);
+		ret = -ETIMEDOUT;
+	} else {
+		ret = 0;
+
+		hisi_crc_get_result(hisifd, pov_req);
+	}
+#endif
+
+	return ret;
+}
+
+void hisi_dss_debug_func(struct work_struct *work)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+
+	hisifd = container_of(work, struct hisi_fb_data_type, dss_debug_work);
+	BUG_ON(hisifd == NULL);
+
+	dumpDssOverlay(hisifd, &hisifd->ov_req, true);
+}
+
+void hisi_ldi_underflow_handle_func(struct work_struct *work)
+{
+	struct hisi_fb_data_type *hisifd = NULL;
+	dss_overlay_t *pov_req_prev = NULL;
+	dss_overlay_t *pov_req_prev_prev = NULL;
+	uint32_t cmdlist_idxs_prev = 0;
+	uint32_t cmdlist_idxs_prev_prev = 0;
+	int ret = 0;
+	uint32_t tmp = 0;
+	uint32_t isr_s1 = 0;
+	uint32_t isr_s2 = 0;
+
+	hisifd =
+	    container_of(work, struct hisi_fb_data_type, ldi_underflow_work);
+	BUG_ON(hisifd == NULL);
+
+	HISI_FB_INFO("fb%d, +.\n", hisifd->index);
+
+	down(&hisifd->blank_sem0);
+	if (!hisifd->panel_power_on) {
+		HISI_FB_INFO("fb%d, panel is power off!", hisifd->index);
+		up(&hisifd->blank_sem0);
+		return;
+	}
+	hisifb_activate_vsync(hisifd);
+
+	pov_req_prev = &(hisifd->ov_req_prev);
+	pov_req_prev_prev = &(hisifd->ov_req_prev_prev);
+
+	ret =
+	    hisi_cmdlist_get_cmdlist_idxs(pov_req_prev, &cmdlist_idxs_prev, NULL);
+	if (ret != 0) {
+		HISI_FB_ERR
+		    ("fb%d, hisi_cmdlist_get_cmdlist_idxs "
+		     "pov_req_prev failed! ret = %d\n",
+		     hisifd->index, ret);
+	}
+
+	ret =
+	    hisi_cmdlist_get_cmdlist_idxs(pov_req_prev_prev,
+					  &cmdlist_idxs_prev_prev, NULL);
+	if (ret != 0) {
+		HISI_FB_ERR
+		    ("fb%d, hisi_cmdlist_get_cmdlist_idxs "
+		     "pov_req_prev_prev failed! ret = %d\n",
+		     hisifd->index, ret);
+	}
+
+	hisi_cmdlist_config_reset(hisifd, pov_req_prev,
+				  cmdlist_idxs_prev | cmdlist_idxs_prev_prev);
+
+	enable_ldi(hisifd);
+	isr_s1 = inp32(hisifd->dss_base + GLB_CPU_PDP_INTS);
+	isr_s2 = inp32(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS);
+	outp32(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS, isr_s2);
+	outp32(hisifd->dss_base + GLB_CPU_PDP_INTS, isr_s1);
+
+	tmp = inp32(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK);
+	tmp &= ~BIT_LDI_UNFLOW;
+	outp32(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK, tmp);
+
+	hisifb_deactivate_vsync(hisifd);
+
+	up(&hisifd->blank_sem0);
+
+	HISI_FB_INFO
+	    ("fb%d, -. cmdlist_idxs_prev = 0x%x, cmdlist_idxs_prev_prev = 0x%x\n",
+	     hisifd->index, cmdlist_idxs_prev, cmdlist_idxs_prev_prev);
+}
+
+/*lint +e778 +e732*/
diff --git a/drivers/video/fbdev/hisi/dss/hisi_overlay_utils.h b/drivers/video/fbdev/hisi/dss/hisi_overlay_utils.h
new file mode 100755
index 000000000000..31088fbe2c73
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_overlay_utils.h
@@ -0,0 +1,269 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+#ifndef HISI_OVERLAY_UTILS_H
+#define HISI_OVERLAY_UTILS_H
+
+#include "hisi_fb.h"
+
+/*******************************************************************************
+ **
+ */
+extern uint32_t g_dss_module_base[DSS_CHN_MAX_DEFINE][MODULE_CHN_MAX];
+extern uint32_t g_dss_module_ovl_base[DSS_MCTL_IDX_MAX][MODULE_OVL_MAX];
+extern uint32_t g_dss_module_cap[DSS_CHN_MAX_DEFINE][MODULE_CAP_MAX];
+extern uint32_t g_dss_mif_sid_map[DSS_CHN_MAX_DEFINE];
+extern uint32_t g_dss_smmu_smrx_idx[DSS_CHN_MAX_DEFINE];
+extern int g_scf_lut_chn_coef_idx[DSS_CHN_MAX_DEFINE];
+extern unsigned int g_dss_smmu_outstanding;
+extern void *g_smmu_rwerraddr_virt;
+
+#define DSS_COMPOSER_TIMEOUT_THRESHOLD_FPGA	(10000)
+#define DSS_COMPOSER_TIMEOUT_THRESHOLD_ASIC	(300)
+
+enum ENUM_LDI_VSTATE {
+	LDI_VSTATE_IDLE = 0x1,
+	LDI_VSTATE_VSW = 0x2,
+	LDI_VSTATE_VBP = 0x4,
+	LDI_VSTATE_VACTIVE0 = 0x8,
+	LDI_VSTATE_VACTIVE_SPACE = 0x10,
+	LDI_VSTATE_VACTIVE1 = 0x20,
+	LDI_VSTATE_VFP = 0x40,
+	LDI_VSTATE_V_WAIT_TE0 = 0x80,
+	LDI_VSTATE_V_WAIT_TE1 = 0x100,
+	LDI_VSTATE_V_WAIT_TE_EN = 0x200,
+};
+
+void dumpDssOverlay(struct hisi_fb_data_type *hisifd, dss_overlay_t *pov_req,
+		    bool isNeedSaveFile);
+
+int hisi_get_hal_format(struct fb_info *info);
+int hisi_overlay_init(struct hisi_fb_data_type *hisifd);
+int hisi_overlay_deinit(struct hisi_fb_data_type *hisifd);
+int hisi_overlay_on(struct hisi_fb_data_type *hisifd, bool fastboot_enable);
+int hisi_overlay_off(struct hisi_fb_data_type *hisifd);
+bool hisi_dss_check_reg_reload_status(struct hisi_fb_data_type *hisifd);
+bool hisi_dss_check_crg_sctrl_status(struct hisi_fb_data_type *hisifd);
+
+void hisifb_adjust_block_rect(int block_num, dss_rect_t *ov_block_rects[],
+			      dss_wb_layer_t *wb_layer);
+void hisifb_disreset_dss(struct hisi_fb_data_type *hisifd);
+
+void hisi_vactive0_start_isr_handler(struct hisi_fb_data_type *hisifd);
+int hisi_vactive0_start_config(struct hisi_fb_data_type *hisifd,
+			       dss_overlay_t *pov_req);
+
+int hisi_dss_dirty_region_dbuf_config(struct hisi_fb_data_type *hisifd,
+				      dss_overlay_t *pov_req);
+void hisi_dss_dirty_region_updt_config(struct hisi_fb_data_type *hisifd,
+				       dss_overlay_t *pov_req);
+
+int hisi_dss_handle_cur_ovl_req(struct hisi_fb_data_type *hisifd,
+				dss_overlay_t *pov_req);
+
+int hisi_ov_compose_handler(struct hisi_fb_data_type *hisifd,
+			    dss_overlay_t *pov_req,
+			    dss_overlay_block_t *pov_h_block,
+			    dss_layer_t *layer,
+			    dss_rect_t *wb_dst_rect,
+			    dss_rect_t *wb_ov_block_rect,
+			    dss_rect_ltrb_t *clip_rect,
+			    dss_rect_t *aligned_rect,
+			    bool *rdma_stretch_enable,
+			    bool *has_base,
+			    bool csc_needed, bool enable_cmdlist);
+
+void hisi_dss_qos_on(struct hisi_fb_data_type *hisifd);
+void hisi_dss_mmbuf_on(struct hisi_fb_data_type *hisifd);
+void hisi_dss_mif_on(struct hisi_fb_data_type *hisifd);
+void hisi_dss_smmu_on(struct hisi_fb_data_type *hisifd);
+void hisi_dss_smmu_init(char __iomem *smmu_base, dss_smmu_t *s_smmu);
+void hisi_dss_smmu_ch_set_reg(struct hisi_fb_data_type *hisifd,
+			      char __iomem *smmu_base, dss_smmu_t *s_smmu,
+			      int chn_idx);
+void hisi_dss_smmu_ov_set_reg(struct hisi_fb_data_type *hisifd,
+			      char __iomem *smmu_base, dss_smmu_t *s_smmu);
+int hisi_dss_scl_coef_on(struct hisi_fb_data_type *hisifd, bool enable_cmdlist,
+			 int coef_lut_idx);
+
+int hisi_overlay_pan_display(struct hisi_fb_data_type *hisifd);
+int hisi_ov_online_play(struct hisi_fb_data_type *hisifd, void __user *argp);
+int hisi_overlay_ioctl_handler(struct hisi_fb_data_type *hisifd,
+			       uint32_t cmd, void __user *argp);
+
+void hisi_dss_unflow_handler(struct hisi_fb_data_type *hisifd,
+			     dss_overlay_t *pov_req, bool unmask);
+
+void hisi_dss_chn_set_reg_default_value(struct hisi_fb_data_type *hisifd,
+					char __iomem *dma_base);
+void hisi_dss_ov_set_reg_default_value(struct hisi_fb_data_type *hisifd,
+				       char __iomem *ovl_base, int ovl_idx);
+int hisi_dss_prev_module_set_regs(struct hisi_fb_data_type *hisifd,
+				  dss_overlay_t *pov_req,
+				  uint32_t cmdlist_pre_idxs,
+				  bool enable_cmdlist, bool *use_comm_mmbuf);
+
+int hisi_dss_check_pure_layer(struct hisi_fb_data_type *hisifd,
+			      dss_overlay_block_t *pov_h_block,
+			      void __user *argp);
+
+int hisi_dss_check_userdata(struct hisi_fb_data_type *hisifd,
+			    dss_overlay_t *pov_req,
+			    dss_overlay_block_t *pov_h_block_infos);
+int hisi_dss_check_layer_par(struct hisi_fb_data_type *hisifd,
+			     dss_layer_t *layer);
+
+int hisi_dss_aif_handler(struct hisi_fb_data_type *hisifd,
+			 dss_overlay_t *pov_req,
+			 dss_overlay_block_t *pov_h_block);
+void hisi_dss_aif_init(char __iomem *aif_ch_base, dss_aif_t *s_aif);
+void hisi_dss_aif_ch_set_reg(struct hisi_fb_data_type *hisifd,
+			     char __iomem *aif_ch_base, dss_aif_t *s_aif);
+int hisi_dss_aif_ch_config(struct hisi_fb_data_type *hisifd,
+			   dss_overlay_t *pov_req, dss_layer_t *layer,
+			   dss_rect_t *wb_dst_rect, dss_wb_layer_t *wb_layer,
+			   int ovl_idx);
+
+int hisi_dss_aif1_ch_config(struct hisi_fb_data_type *hisifd,
+			    dss_overlay_t *pov_req, dss_layer_t *layer,
+			    dss_wb_layer_t *wb_layer, int ovl_idx);
+
+int hisi_dss_mif_config(struct hisi_fb_data_type *hisifd,
+			dss_layer_t *layer, dss_wb_layer_t *wb_layer,
+			bool rdma_stretch_enable);
+
+int hisi_dss_smmu_ch_config(struct hisi_fb_data_type *hisifd,
+			    dss_layer_t *layer, dss_wb_layer_t *wb_layer);
+
+int hisi_dss_rdma_config(struct hisi_fb_data_type *hisifd, int ovl_idx,
+			 dss_layer_t *layer, dss_rect_ltrb_t *clip_rect,
+			 dss_rect_t *aligned_rect, bool *rdma_stretch_enable);
+int hisi_dss_wdma_config(struct hisi_fb_data_type *hisifd,
+			 dss_overlay_t *pov_req, dss_wb_layer_t *layer,
+			 dss_rect_t aligned_rect, dss_rect_t *ov_block_rect,
+			 bool last_block);
+int hisi_dss_rdfc_config(struct hisi_fb_data_type *hisifd, dss_layer_t *layer,
+			 dss_rect_t *aligned_rect, dss_rect_ltrb_t clip_rect);
+int hisi_dss_wdfc_config(struct hisi_fb_data_type *hisifd,
+			 dss_wb_layer_t *layer, dss_rect_t *aligned_rect,
+			 dss_rect_t *ov_block_rect);
+
+void hisi_dss_scl_set_reg(struct hisi_fb_data_type *hisifd,
+			  char __iomem *scl_base, dss_scl_t *s_scl);
+int hisi_dss_chn_scl_load_filter_coef_set_reg(struct hisi_fb_data_type *hisifd,
+					      bool enable_cmdlist, int chn_idx,
+					      uint32_t format);
+int hisi_dss_post_scl_load_filter_coef(struct hisi_fb_data_type *hisifd,
+				       bool enable_cmdlist,
+				       char __iomem *scl_lut_base,
+				       int coef_lut_idx);
+int hisi_dss_scl_config(struct hisi_fb_data_type *hisifd, dss_layer_t *layer,
+			dss_rect_t *aligned_rect, bool rdma_stretch_enable);
+
+int hisi_dss_post_scf_config(struct hisi_fb_data_type *hisifd,
+			     dss_overlay_t *pov_req);
+void hisi_dss_csc_init(char __iomem *csc_base, dss_csc_t *s_csc);
+void hisi_dss_csc_set_reg(struct hisi_fb_data_type *hisifd,
+			  char __iomem *csc_base, dss_csc_t *s_csc);
+int hisi_dss_csc_config(struct hisi_fb_data_type *hisifd, dss_layer_t *layer,
+			dss_wb_layer_t *wb_layer);
+
+int hisi_dss_ovl_base_config(struct hisi_fb_data_type *hisifd,
+			     dss_overlay_t *pov_req,
+			     dss_overlay_block_t *pov_h_block,
+			     dss_rect_t *wb_ov_block_rect, int ovl_idx,
+			     int ov_h_block_idx);
+int hisi_dss_ovl_layer_config(struct hisi_fb_data_type *hisifd,
+			      dss_overlay_t *pov_req, dss_layer_t *layer,
+			      dss_rect_t *wb_ov_block_rect, bool has_base);
+
+void hisi_dss_mctl_mutex_lock(struct hisi_fb_data_type *hisifd, int ovl_idx);
+void hisi_dss_mctl_mutex_unlock(struct hisi_fb_data_type *hisifd, int ovl_idx);
+void hisi_dss_mctl_on(struct hisi_fb_data_type *hisifd,
+		      int mctl_idx, bool enable_cmdlist, bool fastboot_enable);
+int hisi_dss_mctl_ch_config(struct hisi_fb_data_type *hisifd,
+			    dss_overlay_t *pov_req, dss_layer_t *layer,
+			    dss_wb_layer_t *wb_layer, int ovl_idx,
+			    dss_rect_t *wb_ov_block_rect, bool has_base);
+int hisi_dss_mctl_ov_config(struct hisi_fb_data_type *hisifd,
+			    dss_overlay_t *pov_req, int ovl_idx, bool has_base,
+			    bool is_first_ov_block);
+
+int hisi_dss_sharpness_config(struct hisi_fb_data_type *hisifd,
+			      dss_layer_t *layer);
+int hisi_dss_post_clip_config(struct hisi_fb_data_type *hisifd,
+			      dss_layer_t *layer);
+int hisi_dss_ce_config(struct hisi_fb_data_type *hisifd, dss_layer_t *layer);
+
+int hisi_dss_module_default(struct hisi_fb_data_type *hisifd);
+int hisi_dss_module_init(struct hisi_fb_data_type *hisifd);
+int hisi_dss_ch_module_set_regs(struct hisi_fb_data_type *hisifd,
+				int32_t mctl_idx, int chn_idx, uint32_t wb_type,
+				bool enable_cmdlist);
+int hisi_dss_ov_module_set_regs(struct hisi_fb_data_type *hisifd,
+				dss_overlay_t *pov_req, int ovl_idx,
+				bool enable_cmdlist, int task_end, int last,
+				bool is_first_ov_block);
+
+void hisi_dss_secure_layer_check_config(struct hisi_fb_data_type *hisifd,
+					dss_overlay_t *pov_req);
+void hisi_rch2_ce_end_handle_func(struct work_struct *work);
+void hisi_rch4_ce_end_handle_func(struct work_struct *work);
+void hisi_dss_dpp_acm_ce_end_handle_func(struct work_struct *work);
+
+void hisi_crc_isr_handler(struct hisi_fb_data_type *hisifd);
+int hisi_crc_enable(struct hisi_fb_data_type *hisifd, dss_overlay_t *pov_req);
+int hisi_crc_config(struct hisi_fb_data_type *hisifd, dss_overlay_t *pov_req);
+void hisi_dss_debug_func(struct work_struct *work);
+void hisi_ldi_underflow_handle_func(struct work_struct *work);
+
+void *hisi_dss_mmbuf_init(struct hisi_fb_data_type *hisifd);
+void hisi_dss_mmbuf_deinit(struct hisi_fb_data_type *hisifd);
+uint32_t hisi_dss_mmbuf_alloc(void *handle, uint32_t size);
+void hisi_dss_mmbuf_free(void *handle, uint32_t addr, uint32_t size);
+void hisi_dss_mmbuf_info_clear(struct hisi_fb_data_type *hisifd, int idx);
+void hisi_mmbuf_info_get_online(struct hisi_fb_data_type *hisifd);
+void hisi_dss_mctl_ov_set_ctl_dbg_reg(struct hisi_fb_data_type *hisifd,
+				      char __iomem *mctl_base,
+				      bool enable_cmdlist);
+uint32_t hisi_dss_mif_get_invalid_sel(dss_img_t *img, uint32_t transform,
+				      int v_scaling_factor, uint8_t is_tile,
+				      bool rdma_stretch_enable);
+
+bool isYUVPackage(uint32_t format);
+bool isYUVSemiPlanar(uint32_t format);
+bool isYUVPlanar(uint32_t format);
+bool isYUV(uint32_t format);
+
+bool is_YUV_SP_420(uint32_t format);
+bool is_YUV_SP_422(uint32_t format);
+bool is_YUV_P_420(uint32_t format);
+bool is_YUV_P_422(uint32_t format);
+bool is_RGBX(uint32_t format);
+
+int hisi_dss_arsr1p_write_coefs(struct hisi_fb_data_type *hisifd,
+				bool enable_cmdlist, char __iomem *addr,
+				const int **p, int row, int col);
+
+/*arsr2p interface*/
+void hisi_dss_arsr2p_init(char __iomem *arsr2p_base, dss_arsr2p_t *s_arsr2p);
+void hisi_dss_arsr2p_set_reg(struct hisi_fb_data_type *hisifd,
+			     char __iomem *arsr2p_base,
+			     dss_arsr2p_t *s_arsr2p);
+void hisi_dss_arsr2p_coef_on(struct hisi_fb_data_type *hisifd,
+			     bool enable_cmdlist);
+int hisi_dss_arsr2p_config(struct hisi_fb_data_type *hisifd,
+				dss_layer_t *layer, dss_rect_t *aligned_rect, bool rdma_stretch_enable);
+void hisi_remove_mctl_mutex(struct hisi_fb_data_type *hisifd, int mctl_idx,
+			    uint32_t cmdlist_idxs);
+
+#endif				/* HISI_OVERLAY_UTILS_H */
diff --git a/drivers/video/fbdev/hisi/dss/hisi_overlay_utils_hi3660.c b/drivers/video/fbdev/hisi/dss/hisi_overlay_utils_hi3660.c
new file mode 100755
index 000000000000..fb7628e0aa3e
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_overlay_utils_hi3660.c
@@ -0,0 +1,2741 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#include "hisi_overlay_utils.h"
+
+uint32_t g_dss_module_base[DSS_CHN_MAX_DEFINE][MODULE_CHN_MAX] = {
+	/* D0 */
+	{
+	 MIF_CH0_OFFSET,
+	 AIF0_CH0_OFFSET,
+	 AIF1_CH0_OFFSET,
+	 MCTL_CTL_MUTEX_RCH0,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH0_FLUSH_EN,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH0_OV_OEN,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH0_STARTY,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_MOD0_DBG,
+	 DSS_RCH_D0_DMA_OFFSET,
+	 DSS_RCH_D0_DFC_OFFSET,
+	 0,
+	 0,
+	 0,
+	 0,
+	 0,
+	 0,
+	 DSS_RCH_D0_CSC_OFFSET,
+	 }
+	,
+
+	/* D1 */
+	{
+	 MIF_CH1_OFFSET,
+	 AIF0_CH1_OFFSET,
+	 AIF1_CH1_OFFSET,
+	 MCTL_CTL_MUTEX_RCH1,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH1_FLUSH_EN,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH1_OV_OEN,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH1_STARTY,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_MOD1_DBG,
+	 DSS_RCH_D1_DMA_OFFSET,
+	 DSS_RCH_D1_DFC_OFFSET,
+	 0,
+	 0,
+	 0,
+	 0,
+	 0,
+	 0,
+	 DSS_RCH_D1_CSC_OFFSET,
+	 }
+	,
+
+	/* V0 */
+	{
+	 MIF_CH2_OFFSET,
+	 AIF0_CH2_OFFSET,
+	 AIF1_CH2_OFFSET,
+	 MCTL_CTL_MUTEX_RCH2,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH2_FLUSH_EN,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH2_OV_OEN,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH2_STARTY,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_MOD2_DBG,
+	 DSS_RCH_VG0_DMA_OFFSET,
+	 DSS_RCH_VG0_DFC_OFFSET,
+	 DSS_RCH_VG0_SCL_OFFSET,
+	 DSS_RCH_VG0_SCL_LUT_OFFSET,
+	 DSS_RCH_VG0_ARSR_OFFSET,
+	 DSS_RCH_VG0_ARSR_LUT_OFFSET,
+	 DSS_RCH_VG0_POST_CLIP_OFFSET,
+	 DSS_RCH_VG0_PCSC_OFFSET,
+	 DSS_RCH_VG0_CSC_OFFSET,
+	 }
+	,
+
+	/* G0 */
+	{
+	 MIF_CH3_OFFSET,
+	 AIF0_CH3_OFFSET,
+	 AIF1_CH3_OFFSET,
+	 MCTL_CTL_MUTEX_RCH3,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH3_FLUSH_EN,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH3_OV_OEN,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH3_STARTY,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_MOD3_DBG,
+	 DSS_RCH_G0_DMA_OFFSET,
+	 DSS_RCH_G0_DFC_OFFSET,
+	 DSS_RCH_G0_SCL_OFFSET,
+	 0,
+	 0,
+	 0,
+	 DSS_RCH_G0_POST_CLIP_OFFSET,
+	 0,
+	 DSS_RCH_G0_CSC_OFFSET,
+	 }
+	,
+
+	/* V1 */
+	{
+	 MIF_CH4_OFFSET,
+	 AIF0_CH4_OFFSET,
+	 AIF1_CH4_OFFSET,
+	 MCTL_CTL_MUTEX_RCH4,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH4_FLUSH_EN,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH4_OV_OEN,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH4_STARTY,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_MOD4_DBG,
+	 DSS_RCH_VG1_DMA_OFFSET,
+	 DSS_RCH_VG1_DFC_OFFSET,
+	 DSS_RCH_VG1_SCL_OFFSET,
+	 DSS_RCH_VG1_SCL_LUT_OFFSET,
+	 0,
+	 0,
+	 DSS_RCH_VG1_POST_CLIP_OFFSET,
+	 0,
+	 DSS_RCH_VG1_CSC_OFFSET,
+	 }
+	,
+
+	/* G1 */
+	{
+	 MIF_CH5_OFFSET,
+	 AIF0_CH5_OFFSET,
+	 AIF1_CH5_OFFSET,
+	 MCTL_CTL_MUTEX_RCH5,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH5_FLUSH_EN,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH5_OV_OEN,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH5_STARTY,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_MOD5_DBG,
+	 DSS_RCH_G1_DMA_OFFSET,
+	 DSS_RCH_G1_DFC_OFFSET,
+	 DSS_RCH_G1_SCL_OFFSET,
+	 0,
+	 0,
+	 0,
+	 DSS_RCH_G1_POST_CLIP_OFFSET,
+	 0,
+	 DSS_RCH_G1_CSC_OFFSET,
+	 }
+	,
+
+	/* D2 */
+	{
+	 MIF_CH6_OFFSET,
+	 AIF0_CH6_OFFSET,
+	 AIF1_CH6_OFFSET,
+	 MCTL_CTL_MUTEX_RCH6,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH6_FLUSH_EN,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH6_OV_OEN,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH6_STARTY,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_MOD6_DBG,
+	 DSS_RCH_D2_DMA_OFFSET,
+	 DSS_RCH_D2_DFC_OFFSET,
+	 0,
+	 0,
+	 0,
+	 0,
+	 0,
+	 0,
+	 DSS_RCH_D2_CSC_OFFSET,
+	 }
+	,
+
+	/* D3 */
+	{
+	 MIF_CH7_OFFSET,
+	 AIF0_CH7_OFFSET,
+	 AIF1_CH7_OFFSET,
+	 MCTL_CTL_MUTEX_RCH7,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH7_FLUSH_EN,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH7_OV_OEN,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH7_STARTY,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_MOD7_DBG,
+	 DSS_RCH_D3_DMA_OFFSET,
+	 DSS_RCH_D3_DFC_OFFSET,
+	 0,
+	 0,
+	 0,
+	 0,
+	 0,
+	 0,
+	 DSS_RCH_D3_CSC_OFFSET,
+	 }
+	,
+
+	/* W0 */
+	{
+	 MIF_CH8_OFFSET,
+	 AIF0_CH8_OFFSET,
+	 AIF1_CH8_OFFSET,
+	 MCTL_CTL_MUTEX_WCH0,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_WCH0_FLUSH_EN,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_WCH0_OV_IEN,
+	 0,
+	 0,
+	 DSS_WCH0_DMA_OFFSET,
+	 DSS_WCH0_DFC_OFFSET,
+	 0,
+	 0,
+	 0,
+	 0,
+	 0,
+	 0,
+	 DSS_WCH0_CSC_OFFSET,
+	 }
+	,
+
+	/* W1 */
+	{
+	 MIF_CH9_OFFSET,
+	 AIF0_CH9_OFFSET,
+	 AIF1_CH9_OFFSET,
+	 MCTL_CTL_MUTEX_WCH1,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_WCH1_FLUSH_EN,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_WCH1_OV_IEN,
+	 0,
+	 0,
+	 DSS_WCH1_DMA_OFFSET,
+	 DSS_WCH1_DFC_OFFSET,
+	 0,
+	 0,
+	 0,
+	 0,
+	 0,
+	 0,
+	 DSS_WCH1_CSC_OFFSET,
+	 }
+	,
+
+	/* V2 */
+	{
+	 MIF_CH10_OFFSET,
+	 AIF0_CH11_OFFSET,
+	 AIF1_CH11_OFFSET,
+	 MCTL_CTL_MUTEX_RCH8,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_RCH8_FLUSH_EN,
+	 0,
+	 0,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_MOD8_DBG,
+	 DSS_RCH_VG2_DMA_OFFSET,
+	 DSS_RCH_VG2_DFC_OFFSET,
+	 DSS_RCH_VG2_SCL_OFFSET,
+	 DSS_RCH_VG2_SCL_LUT_OFFSET,
+	 0,
+	 0,
+	 DSS_RCH_VG2_POST_CLIP_OFFSET,
+	 0,
+	 DSS_RCH_VG2_CSC_OFFSET,
+	 }
+	,
+	/* W2 */
+	{
+	 MIF_CH11_OFFSET,
+	 AIF0_CH12_OFFSET,
+	 AIF1_CH12_OFFSET,
+	 MCTL_CTL_MUTEX_WCH2,
+	 DSS_MCTRL_SYS_OFFSET + MCTL_WCH2_FLUSH_EN,
+	 0,
+	 0,
+	 0,
+	 DSS_WCH2_DMA_OFFSET,
+	 DSS_WCH2_DFC_OFFSET,
+	 0,
+	 0,
+	 0,
+	 0,
+	 0,
+	 0,
+	 DSS_WCH2_CSC_OFFSET,
+	 }
+	,
+};
+
+uint32_t g_dss_module_ovl_base[DSS_MCTL_IDX_MAX][MODULE_OVL_MAX] = {
+	{DSS_OVL0_OFFSET,
+	 DSS_MCTRL_CTL0_OFFSET}
+	,
+
+	{DSS_OVL1_OFFSET,
+	 DSS_MCTRL_CTL1_OFFSET}
+	,
+
+	{DSS_OVL2_OFFSET,
+	 DSS_MCTRL_CTL2_OFFSET}
+	,
+
+	{DSS_OVL3_OFFSET,
+	 DSS_MCTRL_CTL3_OFFSET}
+	,
+
+	{0,
+	 DSS_MCTRL_CTL4_OFFSET}
+	,
+
+	{0,
+	 DSS_MCTRL_CTL5_OFFSET}
+	,
+};
+
+int g_scf_lut_chn_coef_idx[DSS_CHN_MAX_DEFINE] = {
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+};
+
+uint32_t g_dss_module_cap[DSS_CHN_MAX_DEFINE][MODULE_CAP_MAX] = {
+	/* D2 */
+	{0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1},
+	/* D3 */
+	{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1},
+	/* V0 */
+	{0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1},
+	/* G0 */
+	{0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0},
+	/* V1 */
+	{0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1},
+	/* G1 */
+	{0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0},
+	/* D0 */
+	{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1},
+	/* D1 */
+	{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1},
+
+	/* W0 */
+	{1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1},
+	/* W1 */
+	{1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1},
+
+	/* V2 */
+	{0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1},
+	/* W2 */
+	{1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1},
+};
+
+/* number of smrx idx for each channel */
+uint32_t g_dss_chn_sid_num[DSS_CHN_MAX_DEFINE] = {
+	4, 1, 4, 4, 4, 4, 1, 1, 3, 3, 3, 2
+};
+
+/* start idx of each channel */
+/* smrx_idx = g_dss_smmu_smrx_idx[chn_idx] + (0 ~ g_dss_chn_sid_num[chn_idx]) */
+uint32_t g_dss_smmu_smrx_idx[DSS_CHN_MAX_DEFINE] = {
+	0, 4, 5, 9, 13, 17, 21, 22, 26, 29, 23, 32
+};
+
+void *g_smmu_rwerraddr_virt = NULL;
+static void aif_bw_sort(dss_aif_bw_t a[], int n)
+{
+	int i = 0;
+	int j = 0;
+	dss_aif_bw_t tmp;
+
+	for (; i < n; ++i) {
+		for (j = i; j < n - 1; ++j) {
+			if (a[j].bw > a[j + 1].bw) {
+				tmp = a[j];
+				a[j] = a[j + 1];
+				a[j + 1] = tmp;
+			}
+		}
+	}
+}
+
+int hisi_dss_aif_handler(struct hisi_fb_data_type *hisifd,
+		     dss_overlay_t *pov_req, dss_overlay_block_t *pov_h_block)
+{
+	int i = 0;
+	int k = 0;
+	dss_layer_t *layer = NULL;
+	dss_wb_layer_t *wb_layer = NULL;
+	int chn_idx = 0;
+	dss_aif_bw_t *aif_bw = NULL;
+	uint32_t tmp = 0;
+	uint32_t bw_sum = 0;
+
+	int rch_cnt = 0;
+	int axi0_cnt = 0;
+	int axi1_cnt = 0;
+	dss_aif_bw_t aif_bw_tmp[DSS_CHN_MAX_DEFINE];
+
+	dss_aif_bw_t *aif1_bw = NULL;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_req == NULL);
+	BUG_ON(pov_h_block == NULL);
+
+	memset(aif_bw_tmp, 0, sizeof(aif_bw_tmp));
+
+	if (pov_req->wb_enable) {
+		for (k = 0; k < pov_req->wb_layer_nums; k++) {
+			wb_layer = &(pov_req->wb_layer_infos[k]);
+			chn_idx = wb_layer->chn_idx;
+
+			aif_bw = &(hisifd->dss_module.aif_bw[chn_idx]);
+			aif_bw->bw = (uint64_t) wb_layer->dst.buf_size *
+			    (wb_layer->src_rect.w * wb_layer->src_rect.h) /
+			    (wb_layer->dst.width * wb_layer->dst.height);
+			aif_bw->chn_idx = chn_idx;
+			aif_bw->axi_sel = AXI_CHN1;
+			aif_bw->is_used = 1;
+		}
+
+		if (pov_req->wb_compose_type == DSS_WB_COMPOSE_COPYBIT) {
+			for (i = 0; i < pov_h_block->layer_nums; i++) {
+				layer = &pov_h_block->layer_infos[i];
+				chn_idx = layer->chn_idx;
+				aif_bw_tmp[i].chn_idx = chn_idx;
+				aif_bw_tmp[i].axi_sel = AXI_CHN0;
+				aif_bw_tmp[i].is_used = 1;
+				hisifd->dss_module.aif_bw[chn_idx] =
+				    aif_bw_tmp[i];
+			}
+			return 0;
+		}
+	}
+
+	rch_cnt = 0;
+	for (i = 0; i < pov_h_block->layer_nums; i++) {
+		layer = &pov_h_block->layer_infos[i];
+		chn_idx = layer->chn_idx;
+
+		if (layer->need_cap & (CAP_BASE | CAP_DIM | CAP_PURE_COLOR))
+			continue;
+
+		if (layer->need_cap & CAP_AFBCD) {
+			aif1_bw = &(hisifd->dss_module.aif1_bw[chn_idx]);
+			aif1_bw->is_used = 1;
+			aif1_bw->chn_idx = chn_idx;
+			if ((pov_req->ovl_idx == DSS_OVL0) ||
+			    (pov_req->ovl_idx == DSS_OVL1)) {
+				if ((i % 2) == 0) {
+					aif1_bw->axi_sel = AXI_CHN0;
+				} else {
+					aif1_bw->axi_sel = AXI_CHN1;
+				}
+			} else {
+				if ((i % 2) == 0) {
+					aif1_bw->axi_sel = AXI_CHN1;
+				} else {
+					aif1_bw->axi_sel = AXI_CHN0;
+				}
+			}
+
+			if (g_debug_ovl_online_composer) {
+				HISI_FB_INFO
+				    ("fb%d, aif1, chn_idx=%d, axi_sel=%d.\n",
+				     hisifd->index, chn_idx, aif1_bw->axi_sel);
+			}
+		}
+
+		aif_bw_tmp[i].bw = (uint64_t) layer->img.buf_size *
+		    (layer->src_rect.w * layer->src_rect.h) /
+		    (layer->img.width * layer->img.height);
+		aif_bw_tmp[i].chn_idx = chn_idx;
+		aif_bw_tmp[i].axi_sel = AXI_CHN0;
+		aif_bw_tmp[i].is_used = 1;
+
+		bw_sum += aif_bw_tmp[i].bw;
+		rch_cnt++;
+	}
+
+	aif_bw_sort(aif_bw_tmp, rch_cnt);
+
+	for (i = 0; i < DSS_CHN_MAX_DEFINE; i++) {
+		if (aif_bw_tmp[i].is_used != 1)
+			continue;
+
+		tmp += aif_bw_tmp[i].bw;
+
+		if ((pov_req->ovl_idx == DSS_OVL0)
+		    || (pov_req->ovl_idx == DSS_OVL1)) {
+			if (tmp <= (bw_sum / 2)) {
+				aif_bw_tmp[i].axi_sel = AXI_CHN0;
+				if (axi0_cnt >= AXI0_MAX_DSS_CHN_THRESHOLD) {
+					aif_bw_tmp[i -
+						   AXI0_MAX_DSS_CHN_THRESHOLD].axi_sel
+					    = AXI_CHN1;
+					axi1_cnt++;
+					axi0_cnt--;
+				}
+				axi0_cnt++;
+			} else {
+				aif_bw_tmp[i].axi_sel = AXI_CHN1;
+				axi1_cnt++;
+			}
+		} else {
+			if (tmp <= (bw_sum / 2)) {
+				aif_bw_tmp[i].axi_sel = AXI_CHN1;
+				if (axi1_cnt >= AXI1_MAX_DSS_CHN_THRESHOLD) {
+					aif_bw_tmp[i -
+						   AXI1_MAX_DSS_CHN_THRESHOLD].axi_sel
+					    = AXI_CHN0;
+					axi0_cnt++;
+					axi1_cnt--;
+				}
+				axi1_cnt++;
+			} else {
+				aif_bw_tmp[i].axi_sel = AXI_CHN0;
+				axi0_cnt++;
+			}
+		}
+
+		chn_idx = aif_bw_tmp[i].chn_idx;
+		hisifd->dss_module.aif_bw[chn_idx] = aif_bw_tmp[i];
+
+		if (g_debug_ovl_online_composer) {
+			HISI_FB_INFO
+			    ("fb%d, aif0, chn_idx=%d, axi_sel=%d, bw=%llu.\n",
+			     hisifd->index, chn_idx, aif_bw_tmp[i].axi_sel,
+			     aif_bw_tmp[i].bw);
+		}
+	}
+
+	return 0;
+}
+
+void hisi_dss_qos_on(struct hisi_fb_data_type *hisifd)
+{
+	outp32(hisifd->noc_dss_base + 0xc, 0x2);
+	outp32(hisifd->noc_dss_base + 0x8c, 0x2);
+	outp32(hisifd->noc_dss_base + 0x10c, 0x2);
+	outp32(hisifd->noc_dss_base + 0x18c, 0x2);
+}
+
+/*******************************************************************************
+ ** DSS AIF
+ */
+static int mid_array[DSS_CHN_MAX_DEFINE] = {
+	0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x2, 0x1, 0x3, 0x0
+};
+#define CREDIT_STEP_LOWER_ENABLE
+void hisi_dss_aif_init(char __iomem *aif_ch_base, dss_aif_t *s_aif)
+{
+	BUG_ON(aif_ch_base == NULL);
+	BUG_ON(s_aif == NULL);
+
+	memset(s_aif, 0, sizeof(dss_aif_t));
+
+	s_aif->aif_ch_ctl = inp32(aif_ch_base + AIF_CH_CTL);
+	s_aif->aif_ch_ctl_add = inp32(aif_ch_base + AIF_CH_CTL_ADD);
+}
+
+void hisi_dss_aif_ch_set_reg(struct hisi_fb_data_type *hisifd,
+			char __iomem *aif_ch_base, dss_aif_t *s_aif)
+{
+	BUG_ON(hisifd == NULL);
+	BUG_ON(aif_ch_base == NULL);
+	BUG_ON(s_aif == NULL);
+
+	hisifd->set_reg(hisifd, aif_ch_base + AIF_CH_CTL, s_aif->aif_ch_ctl, 32,
+			0);
+	hisifd->set_reg(hisifd, aif_ch_base + AIF_CH_CTL_ADD,
+			s_aif->aif_ch_ctl_add, 32, 0);
+}
+
+int hisi_dss_aif_ch_config(struct hisi_fb_data_type *hisifd,
+		       dss_overlay_t *pov_req, dss_layer_t *layer,
+		       dss_rect_t *wb_dst_rect,
+		       dss_wb_layer_t *wb_layer, int ovl_idx)
+{
+	dss_aif_t *aif = NULL;
+	dss_aif_bw_t *aif_bw = NULL;
+	int chn_idx = 0;
+	int mid = 0;
+	uint32_t credit_step = 0;
+	uint32_t credit_step_lower = 0;
+	uint64_t dss_core_rate = 0;
+	uint32_t scfd_h = 0;
+	uint32_t scfd_v = 0;
+	uint32_t online_offline_rate = 1;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_req == NULL);
+	BUG_ON((layer == NULL) && (wb_layer == NULL));
+	BUG_ON((ovl_idx < DSS_OVL0) || (ovl_idx >= DSS_OVL_IDX_MAX));
+
+	if (wb_layer) {
+		chn_idx = wb_layer->chn_idx;
+	} else {
+		chn_idx = layer->chn_idx;
+	}
+
+	aif = &(hisifd->dss_module.aif[chn_idx]);
+	hisifd->dss_module.aif_ch_used[chn_idx] = 1;
+
+	aif_bw = &(hisifd->dss_module.aif_bw[chn_idx]);
+	BUG_ON(aif_bw->is_used != 1);
+
+	mid = mid_array[chn_idx];
+	BUG_ON(mid < 0 || mid > 0xb);
+
+	aif->aif_ch_ctl = set_bits32(aif->aif_ch_ctl, aif_bw->axi_sel, 1, 0);
+	aif->aif_ch_ctl = set_bits32(aif->aif_ch_ctl, mid, 4, 4);
+
+	if ((ovl_idx == DSS_OVL2) || (ovl_idx == DSS_OVL3)
+	    || (layer->chn_idx == DSS_RCHN_V2)) {
+		if (layer && ((layer->need_cap & CAP_AFBCD) != CAP_AFBCD)) {
+			dss_core_rate = hisifd->dss_clk_rate.dss_pri_clk_rate;
+			if (dss_core_rate == 0) {
+				HISI_FB_ERR
+				    ("fb%d, dss_core_rate(%llu) is invalid!",
+				     hisifd->index, dss_core_rate);
+				dss_core_rate = DEFAULT_DSS_CORE_CLK_07V_RATE;
+			}
+
+			credit_step_lower =
+			    g_dss_min_bandwidth_inbusbusy * 1000000UL * 8 /
+			    dss_core_rate;
+
+			if ((layer->src_rect.w > layer->dst_rect.w) &&
+			    (layer->src_rect.w > get_panel_xres(hisifd))) {
+				scfd_h =
+				    layer->src_rect.w * 100 /
+				    get_panel_xres(hisifd);
+			} else {
+				scfd_h = 100;
+			}
+
+			if (layer->src_rect.h > layer->dst_rect.h) {
+				scfd_v =
+				    layer->src_rect.h * 100 / layer->dst_rect.h;
+			} else {
+				scfd_v = 100;
+			}
+
+			if (pov_req->wb_compose_type == DSS_WB_COMPOSE_COPYBIT) {
+				if (wb_dst_rect) {
+					online_offline_rate =
+					    wb_dst_rect->w * wb_dst_rect->h /
+					    (hisifd->panel_info.xres *
+					     hisifd->panel_info.yres);
+				}
+
+				if (online_offline_rate == 0)
+					online_offline_rate = 1;
+			}
+
+			credit_step =
+			    hisifd->panel_info.pxl_clk_rate *
+			    online_offline_rate * 32 * scfd_h * scfd_v /
+			    dss_core_rate / (100 * 100);
+
+			if (g_debug_ovl_online_composer
+			    || g_debug_ovl_credit_step) {
+				HISI_FB_INFO
+				    ("fb%d, layer_idx(%d), chn_idx(%d), src_rect(%d,%d,%d,%d),"
+				     "dst_rect(%d,%d,%d,%d), scfd_h=%d, "
+				     "scfd_v=%d, credit_step=%d.\n",
+				     hisifd->index, layer->layer_idx,
+				     layer->chn_idx, layer->src_rect.x,
+				     layer->src_rect.y, layer->src_rect.w,
+				     layer->src_rect.h, layer->dst_rect.x,
+				     layer->dst_rect.y, layer->dst_rect.w,
+				     layer->dst_rect.h, scfd_h, scfd_v,
+				     credit_step);
+			}
+
+			if (credit_step < 32) {
+				credit_step = 32;
+			}
+#ifndef CREDIT_STEP_LOWER_ENABLE
+			if (credit_step > 64) {
+				aif->aif_ch_ctl =
+				    set_bits32(aif->aif_ch_ctl, 0x0, 1, 11);
+			} else {
+				aif->aif_ch_ctl =
+				    set_bits32(aif->aif_ch_ctl, 0x1, 1, 11);
+				aif->aif_ch_ctl =
+				    set_bits32(aif->aif_ch_ctl, credit_step, 7,
+					       16);
+			}
+#else
+			/* credit en lower */
+			aif->aif_ch_ctl_add =
+			    set_bits32(aif->aif_ch_ctl_add, 1, 1, 11);
+			aif->aif_ch_ctl_add =
+			    set_bits32(aif->aif_ch_ctl_add, 2, 4, 12);
+			aif->aif_ch_ctl_add =
+			    set_bits32(aif->aif_ch_ctl_add, credit_step_lower,
+				       7, 16);
+			aif->aif_ch_ctl =
+			    set_bits32(aif->aif_ch_ctl, 0x2, 2, 8);
+			aif->aif_ch_ctl =
+			    set_bits32(aif->aif_ch_ctl, 0x0, 1, 11);
+#endif
+		}
+
+		if (wb_layer) {
+			dss_core_rate = hisifd->dss_clk_rate.dss_pri_clk_rate;
+			if (dss_core_rate == 0) {
+				HISI_FB_ERR
+				    ("fb%d, dss_core_rate(%llu) is invalid!",
+				     hisifd->index, dss_core_rate);
+				dss_core_rate = DEFAULT_DSS_CORE_CLK_07V_RATE;
+			}
+
+			credit_step_lower =
+			    g_dss_min_bandwidth_inbusbusy * 1000000UL * 8 /
+			    dss_core_rate;
+
+			scfd_h = 100;
+			scfd_v = 100;
+			online_offline_rate = 1;
+			credit_step =
+			    hisifd->panel_info.pxl_clk_rate *
+			    online_offline_rate * 32 * scfd_h * scfd_v /
+			    dss_core_rate / (100 * 100);
+
+			if (credit_step < 32) {
+				credit_step = 32;
+			}
+#ifndef CREDIT_STEP_LOWER_ENABLE
+			if (credit_step > 64) {
+				aif->aif_ch_ctl =
+				    set_bits32(aif->aif_ch_ctl, 0x0, 1, 11);
+			} else {
+				aif->aif_ch_ctl =
+				    set_bits32(aif->aif_ch_ctl, 0x1, 1, 11);
+				aif->aif_ch_ctl =
+				    set_bits32(aif->aif_ch_ctl, credit_step, 7,
+					       16);
+			}
+#else
+			/* credit en lower */
+			aif->aif_ch_ctl_add =
+			    set_bits32(aif->aif_ch_ctl_add, 1, 1, 11);
+			aif->aif_ch_ctl_add =
+			    set_bits32(aif->aif_ch_ctl_add, 2, 4, 12);
+			aif->aif_ch_ctl_add =
+			    set_bits32(aif->aif_ch_ctl_add, credit_step_lower,
+				       7, 16);
+			aif->aif_ch_ctl =
+			    set_bits32(aif->aif_ch_ctl, 0x2, 2, 8);
+			aif->aif_ch_ctl =
+			    set_bits32(aif->aif_ch_ctl, 0x0, 1, 11);
+#endif
+		}
+	}
+	return 0;
+}
+
+int hisi_dss_aif1_ch_config(struct hisi_fb_data_type *hisifd,
+			dss_overlay_t *pov_req, dss_layer_t *layer,
+			dss_wb_layer_t *wb_layer, int ovl_idx)
+{
+	dss_aif_t *aif1 = NULL;
+	dss_aif_bw_t *aif1_bw = NULL;
+	int chn_idx = 0;
+	uint32_t need_cap = 0;
+	int mid = 0;
+	uint32_t credit_step = 0;
+	uint32_t credit_step_lower = 0;
+	uint64_t dss_core_rate = 0;
+	uint32_t scfd_h = 0;
+	uint32_t scfd_v = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(pov_req == NULL);
+	BUG_ON((layer == NULL) && (wb_layer == NULL));
+	BUG_ON((ovl_idx < DSS_OVL0) || (ovl_idx >= DSS_OVL_IDX_MAX));
+
+	if (wb_layer) {
+		chn_idx = wb_layer->chn_idx;
+		need_cap = wb_layer->need_cap;
+	} else {
+		chn_idx = layer->chn_idx;
+		need_cap = layer->need_cap;
+	}
+
+	if (!(need_cap & CAP_AFBCD))
+		return 0;
+
+	aif1 = &(hisifd->dss_module.aif1[chn_idx]);
+	hisifd->dss_module.aif1_ch_used[chn_idx] = 1;
+
+	aif1_bw = &(hisifd->dss_module.aif1_bw[chn_idx]);
+	BUG_ON(aif1_bw->is_used != 1);
+
+	mid = mid_array[chn_idx];
+	BUG_ON(mid < 0 || mid > 0xb);
+
+	aif1->aif_ch_ctl = set_bits32(aif1->aif_ch_ctl, aif1_bw->axi_sel, 1, 0);
+	aif1->aif_ch_ctl = set_bits32(aif1->aif_ch_ctl, mid, 4, 4);
+
+	if ((ovl_idx == DSS_OVL0) || (ovl_idx == DSS_OVL1)) {
+		if (layer && (layer->need_cap & CAP_AFBCD)) {
+			dss_core_rate = hisifd->dss_clk_rate.dss_pri_clk_rate;
+			if (dss_core_rate == 0) {
+				HISI_FB_ERR
+				    ("fb%d, dss_core_rate(%llu) is invalid!",
+				     hisifd->index, dss_core_rate);
+				dss_core_rate = DEFAULT_DSS_CORE_CLK_07V_RATE;
+			}
+
+			if ((layer->src_rect.w > layer->dst_rect.w) &&
+			    (layer->src_rect.w > get_panel_xres(hisifd))) {
+				scfd_h =
+				    layer->src_rect.w * 100 /
+				    get_panel_xres(hisifd);
+			} else {
+				scfd_h = 100;
+			}
+
+			if (layer->src_rect.h > layer->dst_rect.h) {
+				scfd_v =
+				    layer->src_rect.h * 100 / layer->dst_rect.h;
+			} else {
+				scfd_v = 100;
+			}
+
+			credit_step =
+			    hisifd->panel_info.pxl_clk_rate * 32 * 150 *
+			    scfd_h * scfd_v / dss_core_rate / (100 * 100 * 100);
+
+			if (g_debug_ovl_online_composer
+			    || g_debug_ovl_credit_step) {
+				HISI_FB_INFO
+				    ("fb%d, layer_idx(%d), chn_idx(%d), src_rect(%d,%d,%d,%d),"
+				     "dst_rect(%d,%d,%d,%d), scfd_h=%d, "
+				     "scfd_v=%d, credit_step=%d.\n",
+				     hisifd->index, layer->layer_idx,
+				     layer->chn_idx, layer->src_rect.x,
+				     layer->src_rect.y, layer->src_rect.w,
+				     layer->src_rect.h, layer->dst_rect.x,
+				     layer->dst_rect.y, layer->dst_rect.w,
+				     layer->dst_rect.h, scfd_h, scfd_v,
+				     credit_step);
+			}
+
+			if (credit_step < 32) {
+				credit_step = 32;
+			}
+
+			if (credit_step > 64) {
+				aif1->aif_ch_ctl =
+				    set_bits32(aif1->aif_ch_ctl, 0x0, 1, 11);
+			} else {
+				aif1->aif_ch_ctl =
+				    set_bits32(aif1->aif_ch_ctl, 0x1, 1, 11);
+				aif1->aif_ch_ctl =
+				    set_bits32(aif1->aif_ch_ctl, credit_step, 7,
+					       16);
+			}
+
+		}
+	} else {
+		if (layer && (layer->need_cap & CAP_AFBCD)) {
+			dss_core_rate = hisifd->dss_clk_rate.dss_pri_clk_rate;
+			if (dss_core_rate == 0) {
+				HISI_FB_ERR
+				    ("fb%d, dss_core_rate(%llu is invalid!",
+				     hisifd->index, dss_core_rate);
+				dss_core_rate = DEFAULT_DSS_CORE_CLK_07V_RATE;
+			}
+
+			credit_step_lower =
+			    g_dss_min_bandwidth_inbusbusy * 1000000UL * 8 /
+			    dss_core_rate;
+
+			if ((layer->src_rect.w > layer->dst_rect.w) &&
+			    (layer->src_rect.w > get_panel_xres(hisifd))) {
+				scfd_h =
+				    layer->src_rect.w * 100 /
+				    get_panel_xres(hisifd);
+			} else {
+				scfd_h = 100;
+			}
+
+			if (layer->src_rect.h > layer->dst_rect.h) {
+				scfd_v =
+				    layer->src_rect.h * 100 / layer->dst_rect.h;
+			} else {
+				scfd_v = 100;
+			}
+
+			credit_step =
+			    hisifd->panel_info.pxl_clk_rate * 32 * scfd_h *
+			    scfd_v / dss_core_rate / (100 * 100);
+
+			if (g_debug_ovl_online_composer
+			    || g_debug_ovl_credit_step) {
+				HISI_FB_INFO
+				    ("fb%d, layer_idx(%d), chn_idx(%d), src_rect(%d,%d,%d,%d),"
+				     "dst_rect(%d,%d,%d,%d), scfd_h=%d, "
+				     "scfd_v=%d, credit_step=%d.\n",
+				     hisifd->index, layer->layer_idx,
+				     layer->chn_idx, layer->src_rect.x,
+				     layer->src_rect.y, layer->src_rect.w,
+				     layer->src_rect.h, layer->dst_rect.x,
+				     layer->dst_rect.y, layer->dst_rect.w,
+				     layer->dst_rect.h, scfd_h, scfd_v,
+				     credit_step);
+			}
+#ifndef CREDIT_STEP_LOWER_ENABLE
+			if (credit_step > 64) {
+				aif1->aif_ch_ctl =
+				    set_bits32(aif1->aif_ch_ctl, 0x0, 1, 11);
+			} else {
+				aif1->aif_ch_ctl =
+				    set_bits32(aif1->aif_ch_ctl, 0x1, 1, 11);
+				aif1->aif_ch_ctl =
+				    set_bits32(aif1->aif_ch_ctl, credit_step, 7,
+					       16);
+			}
+#else
+			/* credit en lower */
+			aif1->aif_ch_ctl_add =
+			    set_bits32(aif1->aif_ch_ctl_add, 1, 1, 11);
+			aif1->aif_ch_ctl_add =
+			    set_bits32(aif1->aif_ch_ctl_add, 2, 4, 12);
+			aif1->aif_ch_ctl_add =
+			    set_bits32(aif1->aif_ch_ctl_add, credit_step_lower,
+				       7, 16);
+			aif1->aif_ch_ctl =
+			    set_bits32(aif1->aif_ch_ctl, 0x2, 2, 8);
+			aif1->aif_ch_ctl =
+			    set_bits32(aif1->aif_ch_ctl, 0x0, 1, 11);
+#endif
+		}
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+ ** DSS SMMU
+ */
+void hisi_dss_smmu_on(struct hisi_fb_data_type *hisifd)
+{
+	char __iomem *smmu_base = NULL;
+	int idx0 = 0;
+	int idx1 = 0;
+	int idx2 = 0;
+	uint32_t phy_pgd_base = 0;
+	struct iommu_domain_data *domain_data = NULL;
+	uint64_t smmu_rwerraddr_phys = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	smmu_base = hisifd->dss_base + DSS_SMMU_OFFSET;
+
+	set_reg(smmu_base + SMMU_SCR, 0x0, 1, 0);
+	set_reg(smmu_base + SMMU_SCR, 0x1, 8, 20);
+	set_reg(smmu_base + SMMU_SCR, g_dss_smmu_outstanding - 1, 4, 16);
+	set_reg(smmu_base + SMMU_SCR, 0x7, 3, 3);
+	set_reg(smmu_base + SMMU_LP_CTRL, 0x1, 1, 0);
+
+	set_reg(smmu_base + SMMU_CB_TTBCR, 0x1, 1, 0);
+
+	if (g_smmu_rwerraddr_virt) {
+		smmu_rwerraddr_phys = virt_to_phys(g_smmu_rwerraddr_virt);
+		set_reg(smmu_base + SMMU_ERR_RDADDR,
+			(uint32_t) (smmu_rwerraddr_phys & 0xFFFFFFFF), 32, 0);
+		set_reg(smmu_base + SMMU_ERR_WRADDR,
+			(uint32_t) (smmu_rwerraddr_phys & 0xFFFFFFFF), 32, 0);
+	} else {
+		set_reg(smmu_base + SMMU_ERR_RDADDR, 0x7FF00000, 32, 0);
+		set_reg(smmu_base + SMMU_ERR_WRADDR, 0x7FFF0000, 32, 0);
+	}
+
+	set_reg(smmu_base + SMMU_RLD_EN0_NS, DSS_SMMU_RLD_EN0_DEFAULT_VAL, 32,
+		0);
+	set_reg(smmu_base + SMMU_RLD_EN1_NS, DSS_SMMU_RLD_EN1_DEFAULT_VAL, 32,
+		0);
+
+	idx0 = 36;
+	idx1 = 37;
+	idx2 = 38;
+
+	set_reg(smmu_base + SMMU_SMRx_NS + idx0 * 0x4, 0x1, 32, 0);
+	set_reg(smmu_base + SMMU_SMRx_NS + idx1 * 0x4, 0x1, 32, 0);
+	set_reg(smmu_base + SMMU_SMRx_NS + idx2 * 0x4, 0x1, 32, 0);
+
+	domain_data = (struct iommu_domain_data *)(hisifd->hisi_domain->priv);
+	phy_pgd_base = (uint32_t) (domain_data->phy_pgd_base);
+	set_reg(smmu_base + SMMU_CB_TTBR0, phy_pgd_base, 32, 0);
+}
+
+void hisi_dss_smmu_init(char __iomem *smmu_base, dss_smmu_t *s_smmu)
+{
+	BUG_ON(smmu_base == NULL);
+	BUG_ON(s_smmu == NULL);
+
+	memset(s_smmu, 0, sizeof(dss_smmu_t));
+}
+
+void
+hisi_dss_smmu_ch_set_reg(struct hisi_fb_data_type *hisifd,
+			 char __iomem *smmu_base, dss_smmu_t *s_smmu,
+			 int chn_idx)
+{
+	uint32_t idx = 0;
+	uint32_t i = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(smmu_base == NULL);
+	BUG_ON(s_smmu == NULL);
+
+	if (s_smmu->smmu_smrx_ns_used[chn_idx] == 0)
+		return;
+
+	for (i = 0; i < g_dss_chn_sid_num[chn_idx]; i++) {
+		idx = g_dss_smmu_smrx_idx[chn_idx] + i;
+		BUG_ON((idx < 0) || (idx >= SMMU_SID_NUM));
+
+		hisifd->set_reg(hisifd, smmu_base + SMMU_SMRx_NS + idx * 0x4,
+				s_smmu->smmu_smrx_ns[idx], 32, 0);
+	}
+}
+
+int
+hisi_dss_smmu_ch_config(struct hisi_fb_data_type *hisifd,
+			dss_layer_t *layer, dss_wb_layer_t *wb_layer)
+{
+	dss_smmu_t *smmu = NULL;
+	int chn_idx = 0;
+	dss_img_t *img = NULL;
+	uint32_t idx = 0;
+	uint32_t i = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON((layer == NULL) && (wb_layer == NULL));
+
+	if (wb_layer) {
+		img = &(wb_layer->dst);
+		chn_idx = wb_layer->chn_idx;
+	} else {
+		img = &(layer->img);
+		chn_idx = layer->chn_idx;
+	}
+
+	smmu = &(hisifd->dss_module.smmu);
+	hisifd->dss_module.smmu_used = 1;
+
+	smmu->smmu_smrx_ns_used[chn_idx] = 1;
+
+	for (i = 0; i < g_dss_chn_sid_num[chn_idx]; i++) {
+		idx = g_dss_smmu_smrx_idx[chn_idx] + i;
+		BUG_ON((idx < 0) || (idx >= SMMU_SID_NUM));
+
+		if (img->mmu_enable == 0) {
+			smmu->smmu_smrx_ns[idx] =
+			    set_bits32(smmu->smmu_smrx_ns[idx], 0x1, 1, 0);
+		} else {
+			/* stream config */
+			smmu->smmu_smrx_ns[idx] =
+			    set_bits32(smmu->smmu_smrx_ns[idx], 0x0, 1, 0);
+			smmu->smmu_smrx_ns[idx] =
+			    set_bits32(smmu->smmu_smrx_ns[idx], 0x1, 1, 4);
+			smmu->smmu_smrx_ns[idx] =
+			    set_bits32(smmu->smmu_smrx_ns[idx], 0x3, 7, 5);
+		}
+	}
+	return 0;
+}
+
+void
+hisifb_adjust_block_rect(int block_num, dss_rect_t *ov_block_rects[],
+			 dss_wb_layer_t *wb_layer)
+{
+	return;
+}
+
+/*******************************************************************************
+ ** DSS CSC
+ */
+#define CSC_ROW	(3)
+#define CSC_COL	(5)
+
+/* application: mode 2 is used in rgb2yuv, mode 0 is used in yuv2rgb */
+#define CSC_MPREC_MODE_0 (0)
+#define CSC_MPREC_MODE_1 (1)
+#define CSC_MPREC_MODE_2 (2)
+
+#define CSC_MPREC_MODE_RGB2YUV (CSC_MPREC_MODE_2)
+#define CSC_MPREC_MODE_YUV2RGB (CSC_MPREC_MODE_0)
+
+/*
+ ** Rec.601 for Computer
+ ** [ p00 p01 p02 cscidc2 cscodc2 ]
+ ** [ p10 p11 p12 cscidc1 cscodc1 ]
+ ** [ p20 p21 p22 cscidc0 cscodc0 ]
+ */
+static int CSC_COE_YUV2RGB601_NARROW_MPREC0[CSC_ROW][CSC_COL] = {
+	{0x4a8, 0x000, 0x662, 0x7f0, 0x000},
+	{0x4a8, 0x1e6f, 0x1cc0, 0x77f, 0x000},
+	{0x4a8, 0x812, 0x000, 0x77f, 0x000}
+};
+
+static int CSC_COE_RGB2YUV601_NARROW_MPREC2[CSC_ROW][CSC_COL] = {
+	{0x41C, 0x811, 0x191, 0x000, 0x010},
+	{0x1DA1, 0x1B58, 0x707, 0x000, 0x081},
+	{0x707, 0x1A1E, 0x1EDB, 0x000, 0x081}
+};
+
+static int CSC_COE_YUV2RGB709_NARROW_MPREC0[CSC_ROW][CSC_COL] = {
+	{0x4a8, 0x000, 0x72c, 0x7f0, 0x000},
+	{0x4a8, 0x1f26, 0x1dde, 0x77f, 0x000},
+	{0x4a8, 0x873, 0x000, 0x77f, 0x000}
+};
+
+static int CSC_COE_RGB2YUV709_NARROW_MPREC2[CSC_ROW][CSC_COL] = {
+	{0x2EC, 0x9D4, 0x0FE, 0x000, 0x010},
+	{0x1E64, 0x1A95, 0x707, 0x000, 0x081},
+	{0x707, 0x199E, 0x1F5B, 0x000, 0x081}
+};
+
+static int CSC_COE_YUV2RGB601_WIDE_MPREC0[CSC_ROW][CSC_COL] = {
+	{0x400, 0x000, 0x59c, 0x000, 0x000},
+	{0x400, 0x1ea0, 0x1d25, 0x77f, 0x000},
+	{0x400, 0x717, 0x000, 0x77f, 0x000}
+};
+
+static int CSC_COE_RGB2YUV601_WIDE_MPREC2[CSC_ROW][CSC_COL] = {
+	{0x4C9, 0x964, 0x1d3, 0x000, 0x000},
+	{0x1D4D, 0x1AB3, 0x800, 0x000, 0x081},
+	{0x800, 0x194D, 0x1EB3, 0x000, 0x081},
+};
+
+static int CSC_COE_YUV2RGB709_WIDE_MPREC0[CSC_ROW][CSC_COL] = {
+	{0x400, 0x000, 0x64d, 0x000, 0x000},
+	{0x400, 0x1f40, 0x1e21, 0x77f, 0x000},
+	{0x400, 0x76c, 0x000, 0x77f, 0x000}
+};
+
+static int CSC_COE_RGB2YUV709_WIDE_MPREC2[CSC_ROW][CSC_COL] = {
+	{0x367, 0xB71, 0x128, 0x000, 0x000},
+	{0x1E2B, 0x19D5, 0x800, 0x000, 0x081},
+	{0x800, 0x18BC, 0x1F44, 0x000, 0x081},
+};
+
+void hisi_dss_csc_init(char __iomem *csc_base, dss_csc_t *s_csc)
+{
+	BUG_ON(csc_base == NULL);
+	BUG_ON(s_csc == NULL);
+
+	memset(s_csc, 0, sizeof(dss_csc_t));
+
+	s_csc->idc0 = inp32(csc_base + CSC_IDC0);
+	s_csc->idc2 = inp32(csc_base + CSC_IDC2);
+	s_csc->odc0 = inp32(csc_base + CSC_ODC0);
+	s_csc->odc2 = inp32(csc_base + CSC_ODC2);
+	s_csc->p0 = inp32(csc_base + CSC_P0);
+	s_csc->p1 = inp32(csc_base + CSC_P1);
+	s_csc->p2 = inp32(csc_base + CSC_P2);
+	s_csc->p3 = inp32(csc_base + CSC_P3);
+	s_csc->p4 = inp32(csc_base + CSC_P4);
+	s_csc->icg_module = inp32(csc_base + CSC_ICG_MODULE);
+	s_csc->mprec = inp32(csc_base + CSC_MPREC);
+}
+
+void
+hisi_dss_csc_set_reg(struct hisi_fb_data_type *hisifd,
+		     char __iomem *csc_base, dss_csc_t *s_csc)
+{
+	BUG_ON(hisifd == NULL);
+	BUG_ON(csc_base == NULL);
+	BUG_ON(s_csc == NULL);
+
+	hisifd->set_reg(hisifd, csc_base + CSC_IDC0, s_csc->idc0, 32, 0);
+	hisifd->set_reg(hisifd, csc_base + CSC_IDC2, s_csc->idc2, 32, 0);
+	hisifd->set_reg(hisifd, csc_base + CSC_ODC0, s_csc->odc0, 32, 0);
+	hisifd->set_reg(hisifd, csc_base + CSC_ODC2, s_csc->odc2, 32, 0);
+	hisifd->set_reg(hisifd, csc_base + CSC_P0, s_csc->p0, 32, 0);
+	hisifd->set_reg(hisifd, csc_base + CSC_P1, s_csc->p1, 32, 0);
+	hisifd->set_reg(hisifd, csc_base + CSC_P2, s_csc->p2, 32, 0);
+	hisifd->set_reg(hisifd, csc_base + CSC_P3, s_csc->p3, 32, 0);
+	hisifd->set_reg(hisifd, csc_base + CSC_P4, s_csc->p4, 32, 0);
+	hisifd->set_reg(hisifd, csc_base + CSC_ICG_MODULE,
+			s_csc->icg_module, 32, 0);
+	hisifd->set_reg(hisifd, csc_base + CSC_MPREC, s_csc->mprec, 32, 0);
+}
+
+bool is_pcsc_needed(dss_layer_t *layer)
+{
+	if (layer->chn_idx != DSS_RCHN_V0)
+		return false;
+
+	if (layer->need_cap & CAP_2D_SHARPNESS)
+		return true;
+
+	/* horizental shrink is not supported by arsr2p */
+	if ((layer->dst_rect.h != layer->src_rect.h)
+	    || (layer->dst_rect.w > layer->src_rect.w))
+		return true;
+
+	return false;
+}
+
+int
+hisi_dss_csc_config(struct hisi_fb_data_type *hisifd,
+		    dss_layer_t *layer, dss_wb_layer_t *wb_layer)
+{
+	dss_csc_t *csc = NULL;
+	int chn_idx = 0;
+	uint32_t format = 0;
+	uint32_t csc_mode = 0;
+	int (*csc_coe_yuv2rgb)[CSC_COL];
+	int (*csc_coe_rgb2yuv)[CSC_COL];
+
+	BUG_ON(hisifd == NULL);
+
+	if (wb_layer) {
+		chn_idx = wb_layer->chn_idx;
+		format = wb_layer->dst.format;
+		csc_mode = wb_layer->dst.csc_mode;
+	} else {
+		chn_idx = layer->chn_idx;
+		format = layer->img.format;
+		csc_mode = layer->img.csc_mode;
+	}
+
+	if (chn_idx != DSS_RCHN_V0) {
+		if (!isYUV(format))
+			return 0;
+		hisifd->dss_module.csc_used[chn_idx] = 1;
+	} else if ((chn_idx == DSS_RCHN_V0) && (!isYUV(format))) {
+		if (!is_pcsc_needed(layer))
+			return 0;
+
+		hisifd->dss_module.csc_used[DSS_RCHN_V0] = 1;
+		hisifd->dss_module.pcsc_used[DSS_RCHN_V0] = 1;
+	} else {
+		hisifd->dss_module.csc_used[chn_idx] = 1;
+	}
+
+	if (csc_mode == DSS_CSC_601_WIDE) {
+		csc_coe_yuv2rgb = CSC_COE_YUV2RGB601_WIDE_MPREC0;
+		csc_coe_rgb2yuv = CSC_COE_RGB2YUV601_WIDE_MPREC2;
+	} else if (csc_mode == DSS_CSC_601_NARROW) {
+		csc_coe_yuv2rgb = CSC_COE_YUV2RGB601_NARROW_MPREC0;
+		csc_coe_rgb2yuv = CSC_COE_RGB2YUV601_NARROW_MPREC2;
+	} else if (csc_mode == DSS_CSC_709_WIDE) {
+		csc_coe_yuv2rgb = CSC_COE_YUV2RGB709_WIDE_MPREC0;
+		csc_coe_rgb2yuv = CSC_COE_RGB2YUV709_WIDE_MPREC2;
+	} else if (csc_mode == DSS_CSC_709_NARROW) {
+		csc_coe_yuv2rgb = CSC_COE_YUV2RGB709_NARROW_MPREC0;
+		csc_coe_rgb2yuv = CSC_COE_RGB2YUV709_NARROW_MPREC2;
+	} else {
+		/* TBD  add csc mprec mode 1 and mode 2 */
+		HISI_FB_ERR("not support this csc_mode(%d)!\n", csc_mode);
+		csc_coe_yuv2rgb = CSC_COE_YUV2RGB601_WIDE_MPREC0;
+		csc_coe_rgb2yuv = CSC_COE_RGB2YUV601_WIDE_MPREC2;
+	}
+
+	/* config rch csc */
+	if (layer && hisifd->dss_module.csc_used[chn_idx]) {
+		csc = &(hisifd->dss_module.csc[chn_idx]);
+		csc->mprec = CSC_MPREC_MODE_YUV2RGB;
+		csc->icg_module = set_bits32(csc->icg_module, 0x1, 1, 0);
+
+		csc->idc0 = set_bits32(csc->idc0,
+				       (csc_coe_yuv2rgb[2][3]) |
+				       (csc_coe_yuv2rgb[1][3] << 16), 27, 0);
+		csc->idc2 =
+		    set_bits32(csc->idc2, (csc_coe_yuv2rgb[0][3]), 11, 0);
+
+		csc->odc0 = set_bits32(csc->odc0,
+				       (csc_coe_yuv2rgb[2][4]) |
+				       (csc_coe_yuv2rgb[1][4] << 16), 27, 0);
+		csc->odc2 =
+		    set_bits32(csc->odc2, (csc_coe_yuv2rgb[0][4]), 11, 0);
+
+		csc->p0 = set_bits32(csc->p0, csc_coe_yuv2rgb[0][0], 13, 0);
+		csc->p0 = set_bits32(csc->p0, csc_coe_yuv2rgb[0][1], 13, 16);
+
+		csc->p1 = set_bits32(csc->p1, csc_coe_yuv2rgb[0][2], 13, 0);
+		csc->p1 = set_bits32(csc->p1, csc_coe_yuv2rgb[1][0], 13, 16);
+
+		csc->p2 = set_bits32(csc->p2, csc_coe_yuv2rgb[1][1], 13, 0);
+		csc->p2 = set_bits32(csc->p2, csc_coe_yuv2rgb[1][2], 13, 16);
+
+		csc->p3 = set_bits32(csc->p3, csc_coe_yuv2rgb[2][0], 13, 0);
+		csc->p3 = set_bits32(csc->p3, csc_coe_yuv2rgb[2][1], 13, 16);
+
+		csc->p4 = set_bits32(csc->p4, csc_coe_yuv2rgb[2][2], 13, 0);
+	}
+
+	/* config rch pcsc */
+	if (layer && hisifd->dss_module.pcsc_used[chn_idx]) {
+		csc = &(hisifd->dss_module.pcsc[chn_idx]);
+		csc->mprec = CSC_MPREC_MODE_RGB2YUV;
+		csc->icg_module = set_bits32(csc->icg_module, 0x1, 1, 0);
+
+		csc->idc0 = set_bits32(csc->idc0,
+				       (csc_coe_rgb2yuv[2][3]) |
+				       (csc_coe_rgb2yuv[1][3] << 16), 27, 0);
+		csc->idc2 =
+		    set_bits32(csc->idc2, (csc_coe_rgb2yuv[0][3]), 11, 0);
+
+		csc->odc0 = set_bits32(csc->odc0,
+				       (csc_coe_rgb2yuv[2][4]) |
+				       (csc_coe_rgb2yuv[1][4] << 16), 27, 0);
+		csc->odc2 =
+		    set_bits32(csc->odc2, (csc_coe_rgb2yuv[0][4]), 11, 0);
+
+		csc->p0 = set_bits32(csc->p0, csc_coe_rgb2yuv[0][0], 13, 0);
+		csc->p0 = set_bits32(csc->p0, csc_coe_rgb2yuv[0][1], 13, 16);
+
+		csc->p1 = set_bits32(csc->p1, csc_coe_rgb2yuv[0][2], 13, 0);
+		csc->p1 = set_bits32(csc->p1, csc_coe_rgb2yuv[1][0], 13, 16);
+
+		csc->p2 = set_bits32(csc->p2, csc_coe_rgb2yuv[1][1], 13, 0);
+		csc->p2 = set_bits32(csc->p2, csc_coe_rgb2yuv[1][2], 13, 16);
+
+		csc->p3 = set_bits32(csc->p3, csc_coe_rgb2yuv[2][0], 13, 0);
+		csc->p3 = set_bits32(csc->p3, csc_coe_rgb2yuv[2][1], 13, 16);
+
+		csc->p4 = set_bits32(csc->p4, csc_coe_rgb2yuv[2][2], 13, 0);
+	}
+
+	/* config wch csc */
+	if (wb_layer) {
+		csc = &(hisifd->dss_module.csc[chn_idx]);
+		csc->mprec = CSC_MPREC_MODE_RGB2YUV;
+		csc->icg_module = set_bits32(csc->icg_module, 0x1, 1, 0);
+
+		csc->idc0 = set_bits32(csc->idc0,
+				       (csc_coe_rgb2yuv[2][3]) |
+				       (csc_coe_rgb2yuv[1][3] << 16), 27, 0);
+		csc->idc2 =
+		    set_bits32(csc->idc2, (csc_coe_rgb2yuv[0][3]), 11, 0);
+
+		csc->odc0 = set_bits32(csc->odc0,
+				       (csc_coe_rgb2yuv[2][4]) |
+				       (csc_coe_rgb2yuv[1][4] << 16), 27, 0);
+		csc->odc2 =
+		    set_bits32(csc->odc2, (csc_coe_rgb2yuv[0][4]), 11, 0);
+
+		csc->p0 = set_bits32(csc->p0, csc_coe_rgb2yuv[0][0], 13, 0);
+		csc->p0 = set_bits32(csc->p0, csc_coe_rgb2yuv[0][1], 13, 16);
+
+		csc->p1 = set_bits32(csc->p1, csc_coe_rgb2yuv[0][2], 13, 0);
+		csc->p1 = set_bits32(csc->p1, csc_coe_rgb2yuv[1][0], 13, 16);
+
+		csc->p2 = set_bits32(csc->p2, csc_coe_rgb2yuv[1][1], 13, 0);
+		csc->p2 = set_bits32(csc->p2, csc_coe_rgb2yuv[1][2], 13, 16);
+
+		csc->p3 = set_bits32(csc->p3, csc_coe_rgb2yuv[2][0], 13, 0);
+		csc->p3 = set_bits32(csc->p3, csc_coe_rgb2yuv[2][1], 13, 16);
+
+		csc->p4 = set_bits32(csc->p4, csc_coe_rgb2yuv[2][2], 13, 0);
+	}
+
+	return 0;
+}
+
+uint32_t hisi_dss_mif_get_invalid_sel(dss_img_t *img, uint32_t transform,
+			     int v_scaling_factor, uint8_t is_tile,
+			     bool rdma_stretch_enable)
+{
+	uint32_t invalid_sel_val = 0;
+	uint32_t tlb_tag_org = 0;
+
+	if (img == NULL) {
+		HISI_FB_ERR("img is null");
+		return 0;
+	}
+
+	if ((transform == (HISI_FB_TRANSFORM_ROT_90 | HISI_FB_TRANSFORM_FLIP_H))
+	    || (transform ==
+		(HISI_FB_TRANSFORM_ROT_90 | HISI_FB_TRANSFORM_FLIP_V))) {
+		transform = HISI_FB_TRANSFORM_ROT_90;
+	}
+
+	tlb_tag_org = (transform & 0x7) |
+	    ((is_tile ? 1 : 0) << 3) | ((rdma_stretch_enable ? 1 : 0) << 4);
+
+	switch (tlb_tag_org) {
+	case MMU_TLB_TAG_ORG_0x0:
+		invalid_sel_val = 1;
+		break;
+	case MMU_TLB_TAG_ORG_0x1:
+		invalid_sel_val = 1;
+		break;
+	case MMU_TLB_TAG_ORG_0x2:
+		invalid_sel_val = 2;
+		break;
+	case MMU_TLB_TAG_ORG_0x3:
+		invalid_sel_val = 2;
+		break;
+	case MMU_TLB_TAG_ORG_0x4:
+		invalid_sel_val = 0;
+		break;
+	case MMU_TLB_TAG_ORG_0x7:
+		invalid_sel_val = 0;
+		break;
+
+	case MMU_TLB_TAG_ORG_0x8:
+		invalid_sel_val = 3;
+		break;
+	case MMU_TLB_TAG_ORG_0x9:
+		invalid_sel_val = 3;
+		break;
+	case MMU_TLB_TAG_ORG_0xA:
+		invalid_sel_val = 3;
+		break;
+	case MMU_TLB_TAG_ORG_0xB:
+		invalid_sel_val = 3;
+		break;
+	case MMU_TLB_TAG_ORG_0xC:
+		invalid_sel_val = 0;
+		break;
+	case MMU_TLB_TAG_ORG_0xF:
+		invalid_sel_val = 0;
+		break;
+
+	case MMU_TLB_TAG_ORG_0x10:
+		invalid_sel_val = 1;
+		break;
+	case MMU_TLB_TAG_ORG_0x11:
+		invalid_sel_val = 1;
+		break;
+	case MMU_TLB_TAG_ORG_0x12:
+		invalid_sel_val = 2;
+		break;
+	case MMU_TLB_TAG_ORG_0x13:
+		invalid_sel_val = 2;
+		break;
+	case MMU_TLB_TAG_ORG_0x14:
+		invalid_sel_val = 0;
+		break;
+	case MMU_TLB_TAG_ORG_0x17:
+		invalid_sel_val = 0;
+		break;
+
+	case MMU_TLB_TAG_ORG_0x18:
+		invalid_sel_val = 3;
+		break;
+	case MMU_TLB_TAG_ORG_0x19:
+		invalid_sel_val = 3;
+		break;
+	case MMU_TLB_TAG_ORG_0x1A:
+		invalid_sel_val = 3;
+		break;
+	case MMU_TLB_TAG_ORG_0x1B:
+		invalid_sel_val = 3;
+		break;
+	case MMU_TLB_TAG_ORG_0x1C:
+		invalid_sel_val = 0;
+		break;
+	case MMU_TLB_TAG_ORG_0x1F:
+		invalid_sel_val = 0;
+		break;
+
+	default:
+		invalid_sel_val = 0;
+		HISI_FB_ERR("not support this tlb_tag_org(0x%x)!\n",
+			    tlb_tag_org);
+		break;
+	}
+
+	return invalid_sel_val;
+}
+
+/*******************************************************************************
+ ** DSS ARSR2P
+ */
+#define ARSR2P_PHASE_NUM	(9)
+#define ARSR2P_TAP4	(4)
+#define ARSR2P_TAP6	(6)
+#define ARSR2P_MIN_INPUT (16)
+#define ARSR2P_MAX_WIDTH (2560)
+#define ARSR2P_MAX_HEIGHT (8192)
+#define ARSR2P_SCALE_MAX (60)
+
+#define ARSR2P_SCL_UP_OFFSET (0x48)
+#define ARSR2P_COEF_H0_OFFSET (0x100)
+#define ARSR2P_COEF_H1_OFFSET (0x200)
+
+static const int COEF_AUV_SCL_UP_TAP4[ARSR2P_PHASE_NUM][ARSR2P_TAP4] = {
+	{-3, 254, 6, -1},
+	{-9, 255, 13, -3},
+	{-18, 254, 27, -7},
+	{-23, 245, 44, -10},
+	{-27, 233, 64, -14},
+	{-29, 218, 85, -18},
+	{-29, 198, 108, -21},
+	{-29, 177, 132, -24},
+	{-27, 155, 155, -27}
+};
+
+static const int COEF_AUV_SCL_DOWN_TAP4[ARSR2P_PHASE_NUM][ARSR2P_TAP4] = {
+	{31, 194, 31, 0},
+	{23, 206, 44, -17},
+	{14, 203, 57, -18},
+	{6, 198, 70, -18},
+	{0, 190, 85, -19},
+	{-5, 180, 99, -18},
+	{-10, 170, 114, -18},
+	{-13, 157, 129, -17},
+	{-15, 143, 143, -15}
+};
+
+static const int COEF_Y_SCL_UP_TAP6[ARSR2P_PHASE_NUM][ARSR2P_TAP6] = {
+	{0, -3, 254, 6, -1, 0},
+	{4, -12, 252, 15, -5, 2},
+	{7, -22, 245, 31, -9, 4},
+	{10, -29, 234, 49, -14, 6},
+	{12, -34, 221, 68, -19, 8},
+	{13, -37, 206, 88, -24, 10},
+	{14, -38, 189, 108, -29, 12},
+	{14, -38, 170, 130, -33, 13},
+	{14, -36, 150, 150, -36, 14}
+};
+
+static const int COEF_Y_SCL_DOWN_TAP6[ARSR2P_PHASE_NUM][ARSR2P_TAP6] = {
+	{-22, 43, 214, 43, -22, 0},
+	{-18, 29, 205, 53, -23, 10},
+	{-16, 18, 203, 67, -25, 9},
+	{-13, 9, 198, 80, -26, 8},
+	{-10, 0, 191, 95, -27, 7},
+	{-7, -7, 182, 109, -27, 6},
+	{-5, -14, 174, 124, -27, 4},
+	{-2, -18, 162, 137, -25, 2},
+	{0, -22, 150, 150, -22, 0}
+};
+
+/*******************************************************************************
+ ** DSS ARSR2P
+ */
+int
+hisi_dss_arsr1p_write_coefs(struct hisi_fb_data_type *hisifd,
+			    bool enable_cmdlist, char __iomem *addr,
+			    const int **p, int row, int col)
+{
+	int coef_value = 0;
+	int coef_num = 0;
+	int i = 0;
+	int j = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(addr == NULL);
+
+	if ((row != ARSR2P_PHASE_NUM)
+	    || ((col != ARSR2P_TAP4) && (col != ARSR2P_TAP6))) {
+		HISI_FB_ERR
+		    ("arsr1p filter coefficients is err, arsr1p_phase_num = %d, arsr1p_tap_num = %d\n",
+		     row, col);
+		return -EINVAL;
+	}
+
+	coef_num = (col == ARSR2P_TAP4 ? 2 : 3);
+
+	for (j = 0; j < 2; j++) {
+		for (i = 0; i < row; i++) {
+			if (coef_num == 2) {
+				coef_value =
+				    (*((int *)p + i * col + j * coef_num) &
+				     0x1FF) |
+				    ((*((int *)p + i * col + j * coef_num + 1) &
+				      0x1FF) << 9);
+			} else {
+				coef_value =
+				    (*((int *)p + i * col + j * coef_num) &
+				     0x1FF) |
+				    ((*((int *)p + i * col + j * coef_num + 1) &
+				      0x1FF) << 9) | ((*((int *)p + i * col +
+							 j * coef_num +
+							 2) & 0x1FF) << 18);
+			}
+
+			if (enable_cmdlist) {
+				hisifd->set_reg(hisifd,
+						addr + 0x8 * i + j * 0x4,
+						coef_value, 32, 0);
+			} else {
+				set_reg(addr + 0x8 * i + j * 0x4, coef_value,
+					32, 0);
+			}
+		}
+	}
+
+	return 0;
+}
+
+int
+hisi_dss_post_scl_load_filter_coef(struct hisi_fb_data_type *hisifd,
+				   bool enable_cmdlist,
+				   char __iomem *scl_lut_base,
+				   int coef_lut_idx)
+{
+	int ret = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	ret =
+	    hisi_dss_arsr1p_write_coefs(hisifd, enable_cmdlist,
+					scl_lut_base + ARSR1P_COEFF_H_Y0,
+					(const int **)COEF_Y_SCL_UP_TAP6,
+					ARSR2P_PHASE_NUM, ARSR2P_TAP6);
+	if (ret < 0) {
+		HISI_FB_ERR("Error to write H_Y0_COEF coefficients.\n");
+	}
+
+	ret =
+	    hisi_dss_arsr1p_write_coefs(hisifd, enable_cmdlist,
+					scl_lut_base + ARSR1P_COEFF_V_Y0,
+					(const int **)COEF_Y_SCL_UP_TAP6,
+					ARSR2P_PHASE_NUM, ARSR2P_TAP6);
+	if (ret < 0) {
+		HISI_FB_ERR("Error to write V_Y0_COEF coefficients.\n");
+	}
+
+	ret =
+	    hisi_dss_arsr1p_write_coefs(hisifd, enable_cmdlist,
+					scl_lut_base + ARSR1P_COEFF_H_UV0,
+					(const int **)COEF_AUV_SCL_UP_TAP4,
+					ARSR2P_PHASE_NUM, ARSR2P_TAP4);
+	if (ret < 0) {
+		HISI_FB_ERR("Error to write H_UV0_COEF coefficients.\n");
+	}
+
+	ret =
+	    hisi_dss_arsr1p_write_coefs(hisifd, enable_cmdlist,
+					scl_lut_base + ARSR1P_COEFF_V_UV0,
+					(const int **)COEF_AUV_SCL_UP_TAP4,
+					ARSR2P_PHASE_NUM, ARSR2P_TAP4);
+	if (ret < 0) {
+		HISI_FB_ERR("Error to write V_UV0_COEF coefficients.\n");
+	}
+
+	return ret;
+}
+
+int
+hisi_dss_arsr2p_write_coefs(struct hisi_fb_data_type *hisifd,
+			    bool enable_cmdlist, char __iomem *addr,
+			    const int **p, int row, int col)
+{
+	int coef_value = 0;
+	int coef_num = 0;
+	int i = 0;
+	int j = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(addr == NULL);
+
+	if ((row != ARSR2P_PHASE_NUM)
+	    || ((col != ARSR2P_TAP4) && (col != ARSR2P_TAP6))) {
+		HISI_FB_ERR
+		    ("arsr2p filter coefficients is err, arsr2p_phase_num = %d, arsr2p_tap_num = %d\n",
+		     row, col);
+		return -EINVAL;
+	}
+
+	coef_num = (col == ARSR2P_TAP4 ? 2 : 3);
+	for (i = 0; i < row; i++) {
+		for (j = 0; j < 2; j++) {
+			if (coef_num == 2) {
+				coef_value =
+				    (*((int *)p + i * col + j * coef_num) &
+				     0x1FF) |
+				    ((*((int *)p + i * col + j * coef_num + 1) &
+				      0x1FF) << 9);
+			} else {
+				coef_value =
+				    (*((int *)p + i * col + j * coef_num) &
+				     0x1FF) |
+				    ((*((int *)p + i * col + j * coef_num + 1) &
+				      0x1FF) << 9) | ((*((int *)p + i * col +
+							 j * coef_num +
+							 2) & 0x1FF) << 18);
+			}
+
+			if (enable_cmdlist) {
+				hisifd->set_reg(hisifd,
+						addr + 0x8 * i + j * 0x4,
+						coef_value, 32, 0);
+			} else {
+				set_reg(addr + 0x8 * i + j * 0x4, coef_value,
+					32, 0);
+			}
+		}
+	}
+
+	return 0;
+}
+
+void
+hisi_dss_arsr2p_write_config_coefs(struct hisi_fb_data_type *hisifd,
+				   bool enable_cmdlist,
+				   char __iomem *addr,
+				   const int **scl_down,
+				   const int **scl_up, int row, int col)
+{
+	int ret = 0;
+
+	ret =
+	    hisi_dss_arsr2p_write_coefs(hisifd, enable_cmdlist, addr,
+					scl_down, row, col);
+	if (ret < 0) {
+		HISI_FB_ERR("Error to write COEF_SCL_DOWN coefficients.\n");
+		return;
+	}
+
+	ret =
+	    hisi_dss_arsr2p_write_coefs(hisifd, enable_cmdlist,
+					addr + ARSR2P_SCL_UP_OFFSET, scl_up,
+					row, col);
+	if (ret < 0) {
+		HISI_FB_ERR("Error to write COEF_SCL_UP coefficients.\n");
+		return;
+	}
+
+}
+
+void hisi_dss_arsr2p_init(char __iomem *arsr2p_base, dss_arsr2p_t *s_arsr2p)
+{
+	BUG_ON(arsr2p_base == NULL);
+	BUG_ON(s_arsr2p == NULL);
+
+	memset(s_arsr2p, 0, sizeof(dss_arsr2p_t));
+
+	s_arsr2p->arsr_input_width_height =
+	    inp32(arsr2p_base + ARSR2P_INPUT_WIDTH_HEIGHT);
+	s_arsr2p->arsr_output_width_height =
+	    inp32(arsr2p_base + ARSR2P_OUTPUT_WIDTH_HEIGHT);
+	s_arsr2p->ihleft = inp32(arsr2p_base + ARSR2P_IHLEFT);
+	s_arsr2p->ihright = inp32(arsr2p_base + ARSR2P_IHRIGHT);
+	s_arsr2p->ivtop = inp32(arsr2p_base + ARSR2P_IVTOP);
+	s_arsr2p->ivbottom = inp32(arsr2p_base + ARSR2P_IVBOTTOM);
+	s_arsr2p->ihinc = inp32(arsr2p_base + ARSR2P_IHINC);
+	s_arsr2p->ivinc = inp32(arsr2p_base + ARSR2P_IVINC);
+	s_arsr2p->offset = inp32(arsr2p_base + ARSR2P_UV_OFFSET);
+	s_arsr2p->mode = inp32(arsr2p_base + ARSR2P_MODE);
+	s_arsr2p->arsr2p_effect.skin_thres_y =
+	    inp32(arsr2p_base + ARSR2P_SKIN_THRES_Y);
+	s_arsr2p->arsr2p_effect.skin_thres_u =
+	    inp32(arsr2p_base + ARSR2P_SKIN_THRES_U);
+	s_arsr2p->arsr2p_effect.skin_thres_v =
+	    inp32(arsr2p_base + ARSR2P_SKIN_THRES_V);
+	s_arsr2p->arsr2p_effect.skin_cfg0 =
+	    inp32(arsr2p_base + ARSR2P_SKIN_CFG0);
+	s_arsr2p->arsr2p_effect.skin_cfg1 =
+	    inp32(arsr2p_base + ARSR2P_SKIN_CFG1);
+	s_arsr2p->arsr2p_effect.skin_cfg2 =
+	    inp32(arsr2p_base + ARSR2P_SKIN_CFG2);
+	s_arsr2p->arsr2p_effect.shoot_cfg1 =
+	    inp32(arsr2p_base + ARSR2P_SHOOT_CFG1);
+	s_arsr2p->arsr2p_effect.shoot_cfg2 =
+	    inp32(arsr2p_base + ARSR2P_SHOOT_CFG2);
+	s_arsr2p->arsr2p_effect.sharp_cfg1 =
+	    inp32(arsr2p_base + ARSR2P_SHARP_CFG1);
+	s_arsr2p->arsr2p_effect.sharp_cfg2 =
+	    inp32(arsr2p_base + ARSR2P_SHARP_CFG2);
+	s_arsr2p->arsr2p_effect.sharp_cfg3 =
+	    inp32(arsr2p_base + ARSR2P_SHARP_CFG3);
+	s_arsr2p->arsr2p_effect.sharp_cfg4 =
+	    inp32(arsr2p_base + ARSR2P_SHARP_CFG4);
+	s_arsr2p->arsr2p_effect.sharp_cfg5 =
+	    inp32(arsr2p_base + ARSR2P_SHARP_CFG5);
+	s_arsr2p->arsr2p_effect.sharp_cfg6 =
+	    inp32(arsr2p_base + ARSR2P_SHARP_CFG6);
+	s_arsr2p->arsr2p_effect.sharp_cfg7 =
+	    inp32(arsr2p_base + ARSR2P_SHARP_CFG7);
+	s_arsr2p->arsr2p_effect.sharp_cfg8 =
+	    inp32(arsr2p_base + ARSR2P_SHARP_CFG8);
+	s_arsr2p->arsr2p_effect.sharp_cfg9 =
+	    inp32(arsr2p_base + ARSR2P_SHARP_CFG9);
+	s_arsr2p->arsr2p_effect.texturw_analysts =
+	    inp32(arsr2p_base + ARSR2P_TEXTURW_ANALYSTS);
+	s_arsr2p->arsr2p_effect.intplshootctrl =
+	    inp32(arsr2p_base + ARSR2P_INTPLSHOOTCTRL);
+
+	s_arsr2p->ihleft1 = inp32(arsr2p_base + ARSR2P_IHLEFT1);
+	s_arsr2p->ihright1 = inp32(arsr2p_base + ARSR2P_IHRIGHT1);
+	s_arsr2p->ivbottom1 = inp32(arsr2p_base + ARSR2P_IVBOTTOM1);
+}
+
+void
+hisi_dss_arsr2p_set_reg(struct hisi_fb_data_type *hisifd,
+			char __iomem *arsr2p_base, dss_arsr2p_t *s_arsr2p)
+{
+	BUG_ON(arsr2p_base == NULL);
+	BUG_ON(s_arsr2p == NULL);
+
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_INPUT_WIDTH_HEIGHT,
+			s_arsr2p->arsr_input_width_height, 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_OUTPUT_WIDTH_HEIGHT,
+			s_arsr2p->arsr_output_width_height, 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_IHLEFT,
+			s_arsr2p->ihleft, 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_IHRIGHT,
+			s_arsr2p->ihright, 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_IVTOP,
+			s_arsr2p->ivtop, 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_IVBOTTOM,
+			s_arsr2p->ivbottom, 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_IHINC,
+			s_arsr2p->ihinc, 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_IVINC,
+			s_arsr2p->ivinc, 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_UV_OFFSET,
+			s_arsr2p->offset, 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_MODE,
+			s_arsr2p->mode, 32, 0);
+
+	if (hisifd->dss_module.arsr2p_effect_used[DSS_RCHN_V0]) {
+		hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SKIN_THRES_Y,
+				s_arsr2p->arsr2p_effect.skin_thres_y, 32, 0);
+		hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SKIN_THRES_U,
+				s_arsr2p->arsr2p_effect.skin_thres_u, 32, 0);
+		hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SKIN_THRES_V,
+				s_arsr2p->arsr2p_effect.skin_thres_v, 32, 0);
+		hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SKIN_CFG0,
+				s_arsr2p->arsr2p_effect.skin_cfg0, 32, 0);
+		hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SKIN_CFG1,
+				s_arsr2p->arsr2p_effect.skin_cfg1, 32, 0);
+		hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SKIN_CFG2,
+				s_arsr2p->arsr2p_effect.skin_cfg2, 32, 0);
+		hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHOOT_CFG1,
+				s_arsr2p->arsr2p_effect.shoot_cfg1, 32, 0);
+		hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHOOT_CFG2,
+				s_arsr2p->arsr2p_effect.shoot_cfg2, 32, 0);
+		hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHARP_CFG1,
+				s_arsr2p->arsr2p_effect.sharp_cfg1, 32, 0);
+		hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHARP_CFG2,
+				s_arsr2p->arsr2p_effect.sharp_cfg2, 32, 0);
+		hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHARP_CFG3,
+				s_arsr2p->arsr2p_effect.sharp_cfg3, 32, 0);
+		hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHARP_CFG4,
+				s_arsr2p->arsr2p_effect.sharp_cfg4, 32, 0);
+		hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHARP_CFG5,
+				s_arsr2p->arsr2p_effect.sharp_cfg5, 32, 0);
+		hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHARP_CFG6,
+				s_arsr2p->arsr2p_effect.sharp_cfg6, 32, 0);
+		hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHARP_CFG7,
+				s_arsr2p->arsr2p_effect.sharp_cfg7, 32, 0);
+		hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHARP_CFG8,
+				s_arsr2p->arsr2p_effect.sharp_cfg8, 32, 0);
+		hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHARP_CFG9,
+				s_arsr2p->arsr2p_effect.sharp_cfg9, 32, 0);
+		hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_TEXTURW_ANALYSTS,
+				s_arsr2p->arsr2p_effect.texturw_analysts, 32, 0);
+		hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_INTPLSHOOTCTRL,
+				s_arsr2p->arsr2p_effect.intplshootctrl, 32, 0);
+	}
+
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_IHLEFT1,
+			s_arsr2p->ihleft1, 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_IHRIGHT1,
+			s_arsr2p->ihright1, 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_IVBOTTOM1,
+			s_arsr2p->ivbottom1, 32, 0);
+}
+
+void
+hisi_dss_arsr2p_coef_on(struct hisi_fb_data_type *hisifd, bool enable_cmdlist)
+{
+	uint32_t module_base = 0;
+	char __iomem *arsr2p_base = 0;
+	char __iomem *coefy_v = NULL;
+	char __iomem *coefa_v = NULL;
+	char __iomem *coefuv_v = NULL;
+
+	BUG_ON(hisifd == NULL);
+
+	module_base = g_dss_module_base[DSS_RCHN_V0][MODULE_ARSR2P_LUT];
+	coefy_v = hisifd->dss_base + module_base + ARSR2P_LUT_COEFY_V_OFFSET;
+	coefa_v = hisifd->dss_base + module_base + ARSR2P_LUT_COEFA_V_OFFSET;
+	coefuv_v = hisifd->dss_base + module_base + ARSR2P_LUT_COEFUV_V_OFFSET;
+	arsr2p_base =
+	    hisifd->dss_base + g_dss_module_base[DSS_RCHN_V0][MODULE_ARSR2P];
+
+	/* COEFY_V COEFY_H */
+	hisi_dss_arsr2p_write_config_coefs(hisifd, enable_cmdlist, coefy_v,
+					   (const int **)
+					   COEF_Y_SCL_DOWN_TAP6,
+					   (const int **)COEF_Y_SCL_UP_TAP6,
+					   ARSR2P_PHASE_NUM, ARSR2P_TAP6);
+	hisi_dss_arsr2p_write_config_coefs(hisifd, enable_cmdlist,
+					   coefy_v + ARSR2P_COEF_H0_OFFSET,
+					   (const int **)
+					   COEF_Y_SCL_DOWN_TAP6,
+					   (const int **)COEF_Y_SCL_UP_TAP6,
+					   ARSR2P_PHASE_NUM, ARSR2P_TAP6);
+	hisi_dss_arsr2p_write_config_coefs(hisifd, enable_cmdlist,
+					   coefy_v + ARSR2P_COEF_H1_OFFSET,
+					   (const int **)
+					   COEF_Y_SCL_DOWN_TAP6,
+					   (const int **)COEF_Y_SCL_UP_TAP6,
+					   ARSR2P_PHASE_NUM, ARSR2P_TAP6);
+
+	/* COEFA_V COEFA_H */
+	hisi_dss_arsr2p_write_config_coefs(hisifd, enable_cmdlist, coefa_v,
+					   (const int **)
+					   COEF_AUV_SCL_DOWN_TAP4,
+					   (const int **)
+					   COEF_AUV_SCL_UP_TAP4,
+					   ARSR2P_PHASE_NUM, ARSR2P_TAP4);
+	hisi_dss_arsr2p_write_config_coefs(hisifd, enable_cmdlist,
+					   coefa_v + ARSR2P_COEF_H0_OFFSET,
+					   (const int **)
+					   COEF_AUV_SCL_DOWN_TAP4,
+					   (const int **)
+					   COEF_AUV_SCL_UP_TAP4,
+					   ARSR2P_PHASE_NUM, ARSR2P_TAP4);
+	hisi_dss_arsr2p_write_config_coefs(hisifd, enable_cmdlist,
+					   coefa_v + ARSR2P_COEF_H1_OFFSET,
+					   (const int **)
+					   COEF_AUV_SCL_DOWN_TAP4,
+					   (const int **)
+					   COEF_AUV_SCL_UP_TAP4,
+					   ARSR2P_PHASE_NUM, ARSR2P_TAP4);
+
+	/* COEFUV_V COEFUV_H */
+	hisi_dss_arsr2p_write_config_coefs(hisifd, enable_cmdlist, coefuv_v,
+					   (const int **)
+					   COEF_AUV_SCL_DOWN_TAP4,
+					   (const int **)
+					   COEF_AUV_SCL_UP_TAP4,
+					   ARSR2P_PHASE_NUM, ARSR2P_TAP4);
+	hisi_dss_arsr2p_write_config_coefs(hisifd, enable_cmdlist,
+					   coefuv_v + ARSR2P_COEF_H0_OFFSET,
+					   (const int **)
+					   COEF_AUV_SCL_DOWN_TAP4,
+					   (const int **)
+					   COEF_AUV_SCL_UP_TAP4,
+					   ARSR2P_PHASE_NUM, ARSR2P_TAP4);
+	hisi_dss_arsr2p_write_config_coefs(hisifd, enable_cmdlist,
+					   coefuv_v + ARSR2P_COEF_H1_OFFSET,
+					   (const int **)
+					   COEF_AUV_SCL_DOWN_TAP4,
+					   (const int **)
+					   COEF_AUV_SCL_UP_TAP4,
+					   ARSR2P_PHASE_NUM, ARSR2P_TAP4);
+
+	if (enable_cmdlist) {
+		hisifd->set_reg = hisi_cmdlist_set_reg;
+	} else {
+		hisifd->set_reg = hisifb_set_reg;
+	}
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SKIN_THRES_Y,
+			(75 | (83 << 8) | (145 << 16)), 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SKIN_THRES_U,
+			(5 | (10 << 8) | (113 << 16)), 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SKIN_THRES_V,
+			(6 | (12 << 8) | (152 << 16)), 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SKIN_CFG0,
+			(512 | (3 << 12)), 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SKIN_CFG1, (819), 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SKIN_CFG2, (682), 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHOOT_CFG1,
+			(512 | (20 << 16)), 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHOOT_CFG2,
+			(-16 | (0 << 16)), 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHARP_CFG1,
+			(2 | (6 << 8) | (48 << 16) | (64 << 24)), 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHARP_CFG2,
+			(8 | (24 << 8) | (24 << 16) | (40 << 24)), 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHARP_CFG3,
+			(1 | (1 << 8) | (2500 << 16)), 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHARP_CFG4,
+			(10 | (6 << 8) | (9 << 16) | (12 << 24)), 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHARP_CFG5,
+			(2 | (12 << 8)), 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHARP_CFG6,
+			(448 | (64 << 16)), 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHARP_CFG7,
+			(1 | (250 << 16)), 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHARP_CFG8,
+			(-48000), 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_SHARP_CFG9,
+			(-32000), 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_TEXTURW_ANALYSTS,
+			(15 | (20 << 16)), 32, 0);
+	hisifd->set_reg(hisifd, arsr2p_base + ARSR2P_INTPLSHOOTCTRL,
+			(4), 32, 0);
+
+}
+
+void hisi_dss_arsr2p_effect_config(dss_arsr2p_effect_t *arsr2p_effect)
+{
+	arsr2p_effect->skin_thres_y = 75 | (83 << 8) | (145 << 16);
+	arsr2p_effect->skin_thres_u = 5 | (10 << 8) | (113 << 16);
+	arsr2p_effect->skin_thres_v = 6 | (12 << 8) | (152 << 16);
+	arsr2p_effect->skin_cfg0 = 512 | (3 << 12);
+	arsr2p_effect->skin_cfg1 = 819;
+	arsr2p_effect->skin_cfg2 = 682;
+	arsr2p_effect->shoot_cfg1 = 512 | (20 << 16);
+	arsr2p_effect->shoot_cfg2 = -16 | (0 << 16);
+	arsr2p_effect->sharp_cfg1 = 2 | (6 << 8) | (48 << 16) | (64 << 24);
+	arsr2p_effect->sharp_cfg2 = 8 | (24 << 8) | (24 << 16) | (40 << 24);
+	arsr2p_effect->sharp_cfg3 = 1 | (1 << 8) | (2500 << 16);
+	arsr2p_effect->sharp_cfg4 = 10 | (6 << 8) | (9 << 16) | (12 << 24);
+	arsr2p_effect->sharp_cfg5 = 2 | (12 << 8);
+	arsr2p_effect->sharp_cfg6 = 448 | (64 << 16);
+	arsr2p_effect->sharp_cfg7 = 1 | (250 << 16);
+	arsr2p_effect->sharp_cfg8 = -48000;
+	arsr2p_effect->sharp_cfg9 = -32000;
+	arsr2p_effect->texturw_analysts = 15 | (20 << 16);
+	arsr2p_effect->intplshootctrl = 4;
+}
+
+int
+hisi_dss_arsr2p_config(struct hisi_fb_data_type *hisifd,
+		       dss_layer_t *layer, dss_rect_t *aligned_rect,
+		       bool rdma_stretch_enable)
+{
+	dss_arsr2p_t *arsr2p = NULL;
+	dss_rect_t src_rect;
+	dss_rect_t dst_rect;
+	uint32_t need_cap = 0;
+	int chn_idx = 0;
+	dss_block_info_t *pblock_info = NULL;
+	int extraw = 0, extraw_left = 0, extraw_right = 0;
+
+	bool en_hscl = false;
+	bool en_vscl = false;
+
+	/* arsr mode */
+	bool imageintpl_dis = false;
+	bool hscldown_enabled = false;
+	bool nearest_en = false;
+	bool diintpl_en = false;
+	bool textureanalyhsisen_en = false;
+	bool skinctrl_en = false;
+	bool shootdetect_en = false;
+	bool sharpen_en = false;
+	bool arsr2p_bypass = true;
+
+	bool hscldown_flag = false;
+
+	int ih_inc = 0;
+	int iv_inc = 0;
+	int ih_left = 0;
+	int ih_right = 0;
+	int iv_top = 0;
+	int iv_bottom = 0;
+	int uv_offset = 0;
+	int src_width = 0;
+	int dst_whole_width = 0;
+
+	int outph_left = 0;
+	int outph_right = 0;
+	int outpv_bottom = 0;
+
+	BUG_ON(hisifd == NULL);
+	BUG_ON(layer == NULL);
+
+	chn_idx = layer->chn_idx;
+	if (chn_idx != DSS_RCHN_V0) {
+		return 0;
+	}
+
+	need_cap = layer->need_cap;
+
+	src_rect = layer->src_rect;
+	dst_rect = layer->dst_rect;
+	pblock_info = &(layer->block_info);
+
+	if (pblock_info && pblock_info->h_ratio_arsr2p) {
+		src_rect = pblock_info->arsr2p_in_rect;
+	}
+
+	src_rect.h = aligned_rect->h;
+
+	/* horizental scaler compute */
+	do {
+		if (pblock_info && pblock_info->h_ratio_arsr2p) {
+			ih_inc = pblock_info->h_ratio_arsr2p;
+			src_width = src_rect.w;
+			dst_whole_width = pblock_info->arsr2p_dst_w;
+			src_rect.x = src_rect.x - pblock_info->arsr2p_src_x;
+			src_rect.y = src_rect.y - pblock_info->arsr2p_src_y;
+			dst_rect.x = dst_rect.x - pblock_info->arsr2p_dst_x;
+			dst_rect.y = dst_rect.y - pblock_info->arsr2p_dst_y;
+
+			if (pblock_info->both_vscfh_arsr2p_used) {
+				hscldown_flag = true;
+			}
+
+			if (rdma_stretch_enable) {
+				en_hscl = true;
+			}
+
+			if (ih_inc && ih_inc != ARSR2P_INC_FACTOR) {
+				en_hscl = true;
+			}
+		} else {
+			/* horizental scaling down is not supported by arsr2p, set src_rect.w = dst_rect.w */
+			if (src_rect.w > dst_rect.w) {
+				src_width = dst_rect.w;
+				hscldown_flag = true;
+			} else {
+				src_width = src_rect.w;
+			}
+			dst_whole_width = dst_rect.w;
+
+			src_rect.x = 0;
+			src_rect.y = 0;
+			dst_rect.x = 0;
+			dst_rect.y = 0;
+			if (src_width != dst_rect.w)
+				en_hscl = true;
+
+			ih_inc =
+			    (DSS_WIDTH(src_width) * ARSR2P_INC_FACTOR +
+			     ARSR2P_INC_FACTOR - ih_left) / dst_rect.w;
+		}
+
+		outph_left =
+		    dst_rect.x * ih_inc - (src_rect.x * ARSR2P_INC_FACTOR);
+		if (outph_left < 0)
+			outph_left = 0;
+
+		extraw = (8 * ARSR2P_INC_FACTOR) / ih_inc;
+		extraw_left = (extraw % 2) ? (extraw + 1) : (extraw);
+		ih_left = outph_left - extraw_left * ih_inc;
+		if (ih_left < 0)
+			ih_left = 0;
+
+		outph_right =
+		    (dst_rect.x + dst_rect.w - 1) * ih_inc -
+		    (src_rect.x * ARSR2P_INC_FACTOR);
+		if (dst_whole_width == dst_rect.w) {
+			extraw = (2 * ARSR2P_INC_FACTOR) / ih_inc;
+			extraw_right = (extraw % 2) ? (extraw + 1) : (extraw);
+			ih_right = outph_right + extraw_right * ih_inc;
+
+			/*if(ihright+(starti << 16)) >(width - 1)* ihinc);
+			   ihright = endo*ihinc-(starti<<16); */
+			extraw =
+			    (dst_whole_width - 1) * ih_inc -
+			    (src_rect.x * ARSR2P_INC_FACTOR);
+
+			if (ih_right > extraw) {
+				ih_right = extraw;
+			}
+		} else {
+			ih_right = src_width * ARSR2P_INC_FACTOR - 1;
+		}
+	} while(0);
+
+	/* vertical scaler compute */
+	do {
+		if (src_rect.h != dst_rect.h)
+			en_vscl = true;
+
+		if (src_rect.h > dst_rect.h) {
+			iv_inc =
+			    (DSS_HEIGHT(src_rect.h) * ARSR2P_INC_FACTOR +
+			     ARSR2P_INC_FACTOR / 2 -
+			     iv_top) / DSS_HEIGHT(dst_rect.h);
+		} else {
+			iv_inc =
+			    (DSS_HEIGHT(src_rect.h) * ARSR2P_INC_FACTOR +
+			     ARSR2P_INC_FACTOR - iv_top) / dst_rect.h;
+		}
+
+		iv_bottom = DSS_HEIGHT(dst_rect.h) * iv_inc + iv_top;
+		outpv_bottom = iv_bottom;
+	} while(0);
+
+	if (need_cap & CAP_2D_SHARPNESS) {
+		sharpen_en = true;
+	}
+
+	if ((!en_hscl) && (!en_vscl)) {
+		if (!sharpen_en) {
+			/*if both scaler up and sharpness are not needed, just return */
+			return 0;
+		} else if (!hscldown_flag) {
+			/*if only sharpness is needed, disable image interplo, enable textureanalyhsis */
+			imageintpl_dis = true;
+			textureanalyhsisen_en = true;
+		}
+	}
+
+	arsr2p = &(hisifd->dss_module.arsr2p[chn_idx]);
+	hisifd->dss_module.arsr2p_used[chn_idx] = 1;
+
+	/*check arsr2p input and output width */
+	if ((src_width < ARSR2P_MIN_INPUT) || (dst_rect.w < ARSR2P_MIN_INPUT)
+	    || (src_width > ARSR2P_MAX_WIDTH)
+	    || (dst_rect.w > ARSR2P_MAX_WIDTH)) {
+		HISI_FB_ERR
+		    ("src_rect.w(%d) or dst_rect.w(%d) is smaller than 16 "
+		     "or larger than 2560!\n",
+		     src_width, dst_rect.w);
+		return -EINVAL;
+	}
+
+	if ((dst_rect.w > (src_width * ARSR2P_SCALE_MAX))
+	    || (src_width > (dst_rect.w * ARSR2P_SCALE_MAX))) {
+		HISI_FB_ERR
+		    ("width out of range, original_src_rec(%d, %d, %d, %d) "
+		     "new_src_rect(%d, %d, %d, %d), dst_rect(%d, %d, %d, %d)\n",
+		     layer->src_rect.x, layer->src_rect.y, src_width,
+		     layer->src_rect.h, src_rect.x, src_rect.y, src_width,
+		     src_rect.h, dst_rect.x, dst_rect.y, dst_rect.w,
+		     dst_rect.h);
+
+		return -EINVAL;
+	}
+
+	/*check arsr2p input and output height */
+	if ((src_rect.h > ARSR2P_MAX_HEIGHT)
+	    || (dst_rect.h > ARSR2P_MAX_HEIGHT)) {
+		HISI_FB_ERR
+		    ("src_rect.h(%d) or dst_rect.h(%d) is smaller than 16 "
+		     "or larger than 8192!\n",
+		     src_rect.h, dst_rect.h);
+		return -EINVAL;
+	}
+
+	if ((dst_rect.h > (src_rect.h * ARSR2P_SCALE_MAX))
+	    || (src_rect.h > (dst_rect.h * ARSR2P_SCALE_MAX))) {
+		HISI_FB_ERR
+		    ("height out of range, original_src_rec(%d, %d, %d, %d) "
+		     "new_src_rect(%d, %d, %d, %d), dst_rect(%d, %d, %d, %d).\n",
+		     layer->src_rect.x, layer->src_rect.y, layer->src_rect.w,
+		     layer->src_rect.h, src_rect.x, src_rect.y, src_rect.w,
+		     src_rect.h, dst_rect.x, dst_rect.y, dst_rect.w,
+		     dst_rect.h);
+		return -EINVAL;
+	}
+
+	/*if arsr2p is enabled, hbp+hfp+hsw > 20 */
+	/*if (hisifd_primary && (hisifd_primary->panel_info.ldi.h_back_porch + hisifd_primary->panel_info.ldi.h_front_porch
+	   + hisifd_primary->panel_info.ldi.h_pulse_width) <= 20) {
+	   HISI_FB_ERR("ldi hbp+hfp+hsw is not larger than 20, return!\n");
+	   return -EINVAL;
+	   } */
+
+	/*config arsr2p mode , start */
+	arsr2p_bypass = false;
+	do {
+		if (hscldown_flag) {
+			hscldown_enabled = true;
+			break;
+		}
+
+		if (!en_hscl && (iv_inc >= 2 * ARSR2P_INC_FACTOR)
+		    && !pblock_info->h_ratio_arsr2p) {
+			nearest_en = true;
+			sharpen_en = false;
+			break;
+		}
+
+		if ((!en_hscl) && (!en_vscl)) {
+			break;
+		}
+
+		diintpl_en = true;
+		textureanalyhsisen_en = true;
+	} while(0);
+
+	if (sharpen_en) {
+		skinctrl_en = true;
+		shootdetect_en = true;
+	}
+	/*config arsr2p mode , end */
+
+	/*if sharpness 2d is needed, config the arsr2p effect */
+	hisi_dss_arsr2p_effect_config(&(arsr2p->arsr2p_effect));
+	hisifd->dss_module.arsr2p_effect_used[chn_idx] = 1;
+
+	arsr2p->arsr_input_width_height =
+	    set_bits32(arsr2p->arsr_input_width_height,
+		       DSS_HEIGHT(src_rect.h), 13, 0);
+	arsr2p->arsr_input_width_height =
+	    set_bits32(arsr2p->arsr_input_width_height, DSS_WIDTH(src_width),
+		       13, 16);
+	arsr2p->arsr_output_width_height =
+	    set_bits32(arsr2p->arsr_output_width_height,
+		       DSS_HEIGHT(dst_rect.h), 13, 0);
+	arsr2p->arsr_output_width_height =
+	    set_bits32(arsr2p->arsr_output_width_height,
+		       DSS_WIDTH(dst_rect.w), 13, 16);
+	arsr2p->ihleft = set_bits32(arsr2p->ihleft, ih_left, 29, 0);
+	arsr2p->ihright = set_bits32(arsr2p->ihright, ih_right, 29, 0);
+	arsr2p->ivtop = set_bits32(arsr2p->ivtop, iv_top, 29, 0);
+	arsr2p->ivbottom = set_bits32(arsr2p->ivbottom, iv_bottom, 29, 0);
+	arsr2p->ihinc = set_bits32(arsr2p->ihinc, ih_inc, 22, 0);
+	arsr2p->ivinc = set_bits32(arsr2p->ivinc, iv_inc, 22, 0);
+	arsr2p->offset = set_bits32(arsr2p->offset, uv_offset, 22, 0);
+	arsr2p->mode = set_bits32(arsr2p->mode, arsr2p_bypass, 1, 0);
+	arsr2p->mode = set_bits32(arsr2p->mode, sharpen_en, 1, 1);
+	arsr2p->mode = set_bits32(arsr2p->mode, shootdetect_en, 1, 2);
+	arsr2p->mode = set_bits32(arsr2p->mode, skinctrl_en, 1, 3);
+	arsr2p->mode = set_bits32(arsr2p->mode, textureanalyhsisen_en, 1, 4);
+	arsr2p->mode = set_bits32(arsr2p->mode, diintpl_en, 1, 5);
+	arsr2p->mode = set_bits32(arsr2p->mode, nearest_en, 1, 6);
+	arsr2p->mode = set_bits32(arsr2p->mode, hscldown_enabled, 1, 7);
+	arsr2p->mode = set_bits32(arsr2p->mode, imageintpl_dis, 1, 8);
+
+	arsr2p->ihleft1 = set_bits32(arsr2p->ihleft1, outph_left, 29, 0);
+	arsr2p->ihright1 = set_bits32(arsr2p->ihright1, outph_right, 29, 0);
+	arsr2p->ivbottom1 = set_bits32(arsr2p->ivbottom1, outpv_bottom, 29, 0);
+
+	return 0;
+}
+
+/*******************************************************************************
+ ** DSS remove mctl ch&ov mutex for offline
+ */
+void
+hisi_remove_mctl_mutex(struct hisi_fb_data_type *hisifd, int mctl_idx,
+		       uint32_t cmdlist_idxs)
+{
+	dss_module_reg_t *dss_module = NULL;
+	int i = 0;
+	char __iomem *chn_mutex_base = NULL;
+	char __iomem *cmdlist_base = NULL;
+	uint32_t offset = 0;
+	uint32_t cmdlist_idxs_temp = 0;
+
+	BUG_ON(hisifd == NULL);
+
+	dss_module = &(hisifd->dss_module);
+	cmdlist_base = hisifd->dss_base + DSS_CMDLIST_OFFSET;
+
+	for (i = 0; i < DSS_CHN_MAX_DEFINE; i++) {
+		if (dss_module->mctl_ch_used[i] == 1) {
+			chn_mutex_base =
+			    dss_module->mctl_ch_base[i].chn_mutex_base +
+			    g_dss_module_ovl_base[mctl_idx][MODULE_MCTL_BASE];
+			BUG_ON(chn_mutex_base == NULL);
+
+			set_reg(chn_mutex_base, 0, 32, 0);
+		}
+	}
+
+	set_reg(dss_module->mctl_base[mctl_idx] + MCTL_CTL_MUTEX_OV, 0, 32, 0);
+
+	offset = 0x40;
+	cmdlist_idxs_temp = cmdlist_idxs;
+
+	for (i = 0; i < HISI_DSS_CMDLIST_MAX; i++) {
+		if ((cmdlist_idxs_temp & 0x1) == 0x1) {
+			set_reg(cmdlist_base + CMDLIST_CH0_CTRL + i * offset,
+				0x6, 3, 2);
+		}
+		cmdlist_idxs_temp = cmdlist_idxs_temp >> 1;
+	}
+
+}
+
+void
+hisi_dss_mctl_ov_set_ctl_dbg_reg(struct hisi_fb_data_type *hisifd,
+				 char __iomem *mctl_base, bool enable_cmdlist)
+{
+	if (hisifd == NULL) {
+		HISI_FB_ERR("hisifd is null");
+		return;
+	}
+
+	if (enable_cmdlist) {
+		set_reg(mctl_base + MCTL_CTL_DBG, 0xB03A20, 32, 0);
+		set_reg(mctl_base + MCTL_CTL_TOP, 0x1, 32, 0);
+	} else {
+		set_reg(mctl_base + MCTL_CTL_DBG, 0xB13A00, 32, 0);
+		if (hisifd->index == PRIMARY_PANEL_IDX) {
+			set_reg(mctl_base + MCTL_CTL_TOP, 0x2, 32, 0);
+		} else if (hisifd->index == EXTERNAL_PANEL_IDX) {
+			set_reg(mctl_base + MCTL_CTL_TOP, 0x3, 32, 0);
+		} else {
+			;
+		}
+	}
+}
+
+int
+hisi_dss_check_userdata(struct hisi_fb_data_type *hisifd,
+			dss_overlay_t *pov_req,
+			dss_overlay_block_t *pov_h_block_infos)
+{
+	int i = 0;
+	dss_wb_layer_t *wb_layer = NULL;
+
+	if (hisifd == NULL) {
+		HISI_FB_ERR("invalid hisifd!");
+		return -EINVAL;
+	}
+
+	if (pov_req == NULL) {
+		HISI_FB_ERR("fb%d, invalid pov_req!", hisifd->index);
+		return -EINVAL;
+	}
+
+	if (pov_h_block_infos == NULL) {
+		HISI_FB_ERR("fb%d, invalid pov_h_block_infos!", hisifd->index);
+		return -EINVAL;
+	}
+
+	if ((pov_req->ov_block_nums <= 0) ||
+	    (pov_req->ov_block_nums > HISI_DSS_OV_BLOCK_NUMS)) {
+		HISI_FB_ERR("fb%d, invalid ov_block_nums=%d!",
+			    hisifd->index, pov_req->ov_block_nums);
+		return -EINVAL;
+	}
+
+	if ((pov_h_block_infos->layer_nums <= 0)
+	    || (pov_h_block_infos->layer_nums > MAX_DSS_SRC_NUM)) {
+		HISI_FB_ERR("fb%d, invalid layer_nums=%d!",
+			    hisifd->index, pov_h_block_infos->layer_nums);
+		return -EINVAL;
+	}
+
+	if ((pov_req->ovl_idx < 0) || pov_req->ovl_idx >= DSS_OVL_IDX_MAX) {
+		HISI_FB_ERR("fb%d, invalid ovl_idx=%d!",
+			    hisifd->index, pov_req->ovl_idx);
+		return -EINVAL;
+	}
+
+	if (hisifd->index == PRIMARY_PANEL_IDX) {
+		if (hisifd->panel_info.dirty_region_updt_support) {
+			if (pov_req->dirty_rect.x < 0
+			    || pov_req->dirty_rect.y < 0
+			    || pov_req->dirty_rect.w < 0
+			    || pov_req->dirty_rect.h < 0) {
+				HISI_FB_ERR
+				    ("dirty_rect(%d, %d, %d, %d) is out of range!\n",
+				     pov_req->dirty_rect.x,
+				     pov_req->dirty_rect.y,
+				     pov_req->dirty_rect.w,
+				     pov_req->dirty_rect.h);
+				return -EINVAL;
+			}
+		}
+	}
+
+	if (hisifd->index == AUXILIARY_PANEL_IDX) {
+		if (pov_req->wb_enable != 1) {
+			HISI_FB_ERR("pov_req->wb_enable=%u is invalid!\n",
+				    pov_req->wb_enable);
+			return -EINVAL;
+		}
+
+		if ((pov_req->wb_layer_nums <= 0) ||
+		    (pov_req->wb_layer_nums > MAX_DSS_DST_NUM)) {
+			HISI_FB_ERR("fb%d, invalid wb_layer_nums=%d!",
+				    hisifd->index, pov_req->wb_layer_nums);
+			return -EINVAL;
+		}
+
+		if (pov_req->wb_ov_rect.x < 0 || pov_req->wb_ov_rect.y < 0) {
+			HISI_FB_ERR("wb_ov_rect(%d, %d) is out of range!\n",
+				    pov_req->wb_ov_rect.x,
+				    pov_req->wb_ov_rect.y);
+			return -EINVAL;
+		}
+
+		if (pov_req->wb_compose_type >= DSS_WB_COMPOSE_TYPE_MAX) {
+			HISI_FB_ERR("wb_compose_type=%u is invalid!\n",
+				    pov_req->wb_compose_type);
+			return -EINVAL;
+		}
+
+		for (i = 0; i < pov_req->wb_layer_nums; i++) {
+			wb_layer = &(pov_req->wb_layer_infos[i]);
+
+			if (wb_layer->chn_idx != DSS_WCHN_W2) {
+				if (wb_layer->chn_idx < DSS_WCHN_W0
+				    || wb_layer->chn_idx > DSS_WCHN_W1) {
+					HISI_FB_ERR
+					    ("fb%d, wchn_idx=%d is invalid!",
+					     hisifd->index, wb_layer->chn_idx);
+					return -EINVAL;
+				}
+			}
+
+			if (wb_layer->dst.format >= HISI_FB_PIXEL_FORMAT_MAX) {
+				HISI_FB_ERR("fb%d, format=%d is invalid!",
+					    hisifd->index,
+					    wb_layer->dst.format);
+				return -EINVAL;
+			}
+
+			if ((wb_layer->dst.bpp == 0)
+			    || (wb_layer->dst.width == 0)
+			    || (wb_layer->dst.height == 0)
+			    || (wb_layer->dst.stride == 0)) {
+				HISI_FB_ERR
+				    ("fb%d, bpp=%d, width=%d, height=%d, stride=%d is invalid!",
+				     hisifd->index, wb_layer->dst.bpp,
+				     wb_layer->dst.width, wb_layer->dst.height,
+				     wb_layer->dst.stride);
+				return -EINVAL;
+			}
+#if 0
+			if (wb_layer->dst.mmu_enable) {
+				if (wb_layer->dst.buf_size == 0) {
+					HISI_FB_ERR
+					    ("fb%d, buf_size=%d is invalid!",
+					     hisifd->index,
+					     wb_layer->dst.buf_size);
+					return -EINVAL;
+				}
+			}
+
+			if (isYUVSemiPlanar(wb_layer->dst.format)
+			    || isYUVPlanar(wb_layer->dst.format)) {
+				if ((wb_layer->dst.stride_plane1 == 0)
+				    || (wb_layer->dst.offset_plane1 == 0)) {
+					HISI_FB_ERR
+					    ("fb%d, stride_plane1=%d, offset_plane1=%d is invalid!",
+					     hisifd->index,
+					     wb_layer->dst.stride_plane1,
+					     wb_layer->dst.offset_plane1);
+					return -EINVAL;
+				}
+			}
+
+			if (isYUVPlanar(wb_layer->dst.format)) {
+				if ((wb_layer->dst.stride_plane2 == 0)
+				    || (wb_layer->dst.offset_plane2 == 0)) {
+					HISI_FB_ERR
+					    ("fb%d, stride_plane2=%d, offset_plane2=%d is invalid!",
+					     hisifd->index,
+					     wb_layer->dst.stride_plane2,
+					     wb_layer->dst.offset_plane2);
+					return -EINVAL;
+				}
+			}
+#endif
+
+			if (wb_layer->need_cap & CAP_AFBCE) {
+				if ((wb_layer->dst.afbc_header_stride == 0)
+				    || (wb_layer->dst.afbc_payload_stride == 0)) {
+					HISI_FB_ERR
+					    ("fb%d, afbc_header_stride=%d, afbc_payload_stride=%d is invalid!",
+					     hisifd->index,
+					     wb_layer->dst.afbc_header_stride,
+					     wb_layer->dst.afbc_payload_stride);
+					return -EINVAL;
+				}
+			}
+
+			if (wb_layer->dst.csc_mode >= DSS_CSC_MOD_MAX) {
+				HISI_FB_ERR("fb%d, csc_mode=%d is invalid!",
+					    hisifd->index,
+					    wb_layer->dst.csc_mode);
+				return -EINVAL;
+			}
+
+			if (wb_layer->dst.afbc_scramble_mode >=
+			    DSS_AFBC_SCRAMBLE_MODE_MAX) {
+				HISI_FB_ERR
+				    ("fb%d, afbc_scramble_mode=%d is invalid!",
+				     hisifd->index,
+				     wb_layer->dst.afbc_scramble_mode);
+				return -EINVAL;
+			}
+
+			if (wb_layer->src_rect.x < 0 || wb_layer->src_rect.y < 0
+			    || wb_layer->src_rect.w <= 0
+			    || wb_layer->src_rect.h <= 0) {
+				HISI_FB_ERR
+				    ("src_rect(%d, %d, %d, %d) is out of range!\n",
+				     wb_layer->src_rect.x, wb_layer->src_rect.y,
+				     wb_layer->src_rect.w,
+				     wb_layer->src_rect.h);
+				return -EINVAL;
+			}
+
+			if (wb_layer->dst_rect.x < 0 || wb_layer->dst_rect.y < 0
+			    || wb_layer->dst_rect.w <= 0
+			    || wb_layer->dst_rect.h <= 0) {
+				HISI_FB_ERR
+				    ("dst_rect(%d, %d, %d, %d) is out of range!\n",
+				     wb_layer->dst_rect.x, wb_layer->dst_rect.y,
+				     wb_layer->dst_rect.w,
+				     wb_layer->dst_rect.h);
+				return -EINVAL;
+			}
+		}
+	} else {
+		;
+	}
+
+	return 0;
+}
+
+int
+hisi_dss_check_layer_par(struct hisi_fb_data_type *hisifd, dss_layer_t *layer)
+{
+	if (hisifd == NULL) {
+		HISI_FB_ERR("hisifd is NULL, return!");
+		return -EINVAL;
+	}
+
+	if (layer == NULL) {
+		HISI_FB_ERR("layer is NULL, return!");
+		return -EINVAL;
+	}
+
+	if (layer->layer_idx < 0 || layer->layer_idx >= MAX_DSS_SRC_NUM) {
+		HISI_FB_ERR("fb%d, layer_idx=%d is invalid!", hisifd->index,
+			    layer->layer_idx);
+		return -EINVAL;
+	}
+
+	if (layer->need_cap & (CAP_BASE | CAP_DIM | CAP_PURE_COLOR))
+		return 0;
+
+	if (hisifd->index == AUXILIARY_PANEL_IDX) {
+		if (layer->chn_idx != DSS_RCHN_V2) {
+			if (layer->chn_idx < 0 || layer->chn_idx >= DSS_WCHN_W0) {
+				HISI_FB_ERR("fb%d, rchn_idx=%d is invalid!",
+					    hisifd->index, layer->chn_idx);
+				return -EINVAL;
+			}
+		}
+
+		if (layer->chn_idx == DSS_RCHN_D2) {
+			HISI_FB_ERR
+			    ("fb%d, chn_idx[%d] does not used by offline play!",
+			     hisifd->index, layer->chn_idx);
+			return -EINVAL;
+		}
+	} else {
+		if (layer->chn_idx < 0 || layer->chn_idx >= DSS_WCHN_W0) {
+			HISI_FB_ERR("fb%d, rchn_idx=%d is invalid!",
+				    hisifd->index, layer->chn_idx);
+			return -EINVAL;
+		}
+	}
+
+	if (layer->blending < 0 || layer->blending >= HISI_FB_BLENDING_MAX) {
+		HISI_FB_ERR("fb%d, blending=%d is invalid!", hisifd->index,
+			    layer->blending);
+		return -EINVAL;
+	}
+
+	if (layer->img.format >= HISI_FB_PIXEL_FORMAT_MAX) {
+		HISI_FB_ERR("fb%d, format=%d is invalid!", hisifd->index,
+			    layer->img.format);
+		return -EINVAL;
+	}
+
+	if ((layer->img.bpp == 0) || (layer->img.width == 0)
+	    || (layer->img.height == 0) || (layer->img.stride == 0)) {
+		HISI_FB_ERR
+		    ("fb%d, bpp=%d, width=%d, height=%d, stride=%d is invalid!",
+		     hisifd->index, layer->img.bpp, layer->img.width,
+		     layer->img.height, layer->img.stride);
+		return -EINVAL;
+	}
+#if 0
+	if (layer->img.mmu_enable) {
+		if (layer->img.buf_size == 0) {
+			HISI_FB_ERR("fb%d, buf_size=%d is invalid!",
+				    hisifd->index, layer->img.buf_size);
+			return -EINVAL;
+		}
+	}
+
+	if (isYUVSemiPlanar(layer->img.format)
+	    || isYUVPlanar(layer->img.format)) {
+		if ((layer->img.stride_plane1 == 0)
+		    || (layer->img.offset_plane1 == 0)) {
+			HISI_FB_ERR
+			    ("fb%d, stride_plane1=%d, offset_plane1=%d is invalid!",
+			     hisifd->index, layer->img.stride_plane1,
+			     layer->img.offset_plane1);
+			return -EINVAL;
+		}
+	}
+
+	if (isYUVPlanar(layer->img.format)) {
+		if ((layer->img.stride_plane2 == 0)
+		    || (layer->img.offset_plane2 == 0)) {
+			HISI_FB_ERR
+			    ("fb%d, stride_plane2=%d, offset_plane2=%d is invalid!",
+			     hisifd->index, layer->img.stride_plane2,
+			     layer->img.offset_plane2);
+			return -EINVAL;
+		}
+	}
+#endif
+
+	if (layer->need_cap & CAP_AFBCD) {
+		if ((layer->img.afbc_header_stride == 0)
+		    || (layer->img.afbc_payload_stride == 0)
+		    || (layer->img.mmbuf_size == 0)) {
+			HISI_FB_ERR
+			    ("fb%d, afbc_header_stride=%d, afbc_payload_stride=%d, "
+			     "mmbuf_size=%d is invalid!",
+			     hisifd->index, layer->img.afbc_header_stride,
+			     layer->img.afbc_payload_stride,
+			     layer->img.mmbuf_size);
+			return -EINVAL;
+		}
+	}
+
+	if (layer->img.csc_mode >= DSS_CSC_MOD_MAX) {
+		HISI_FB_ERR("fb%d, csc_mode=%d is invalid!", hisifd->index,
+			    layer->img.csc_mode);
+		return -EINVAL;
+	}
+
+	if (layer->img.afbc_scramble_mode >= DSS_AFBC_SCRAMBLE_MODE_MAX) {
+		HISI_FB_ERR("fb%d, afbc_scramble_mode=%d is invalid!",
+			    hisifd->index, layer->img.afbc_scramble_mode);
+		return -EINVAL;
+	}
+
+	if ((layer->layer_idx != 0) && (layer->need_cap & CAP_BASE)) {
+		HISI_FB_ERR("fb%d, layer%d is not base!", hisifd->index,
+			    layer->layer_idx);
+		return -EINVAL;
+	}
+
+	if (layer->src_rect.x < 0 || layer->src_rect.y < 0 ||
+	    layer->src_rect.w <= 0 || layer->src_rect.h <= 0) {
+		HISI_FB_ERR("src_rect(%d, %d, %d, %d) is out of range!\n",
+			    layer->src_rect.x, layer->src_rect.y,
+			    layer->src_rect.w, layer->src_rect.h);
+		return -EINVAL;
+	}
+
+	if (layer->src_rect_mask.x < 0 || layer->src_rect_mask.y < 0 ||
+	    layer->src_rect_mask.w < 0 || layer->src_rect_mask.h < 0) {
+		HISI_FB_ERR("src_rect_mask(%d, %d, %d, %d) is out of range!\n",
+			    layer->src_rect_mask.x, layer->src_rect_mask.y,
+			    layer->src_rect_mask.w, layer->src_rect_mask.h);
+		return -EINVAL;
+	}
+
+	if (layer->dst_rect.x < 0 || layer->dst_rect.y < 0 ||
+	    layer->dst_rect.w <= 0 || layer->dst_rect.h <= 0) {
+		HISI_FB_ERR("dst_rect(%d, %d, %d, %d) is out of range!\n",
+			    layer->dst_rect.x, layer->dst_rect.y,
+			    layer->dst_rect.w, layer->dst_rect.h);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+void hisifb_disreset_dss(struct hisi_fb_data_type *hisifd)
+{
+}
diff --git a/drivers/video/fbdev/hisi/dss/hisi_overlay_utils_hi3660.h b/drivers/video/fbdev/hisi/dss/hisi_overlay_utils_hi3660.h
new file mode 100755
index 000000000000..1d5b1fc0cc92
--- /dev/null
+++ b/drivers/video/fbdev/hisi/dss/hisi_overlay_utils_hi3660.h
@@ -0,0 +1,73 @@
+/* Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+#ifndef _HISI_OVERLAY_UTILS_PLATFORM_H_
+#define _HISI_OVERLAY_UTILS_PLATFORM_H_
+
+#define HISI_DSS_VERSION_V400
+
+#define GPIO_LCD_POWER_1V2  (54)
+#define GPIO_LCD_STANDBY    (67)
+#define GPIO_LCD_RESETN     (65)
+#define GPIO_LCD_GATING     (60)
+#define GPIO_LCD_PCLK_GATING (58)
+#define GPIO_LCD_REFCLK_GATING (59)
+#define GPIO_LCD_SPICS         (168)
+#define GPIO_LCD_DRV_EN        (73)
+
+#define GPIO_PG_SEL_A (72)
+#define GPIO_TX_RX_A (74)
+#define GPIO_PG_SEL_B (76)
+#define GPIO_TX_RX_B (78)
+
+/*******************************************************************************
+ **
+ */
+#define CRGPERI_PLL0_CLK_RATE	(1600000000UL)
+#define CRGPERI_PLL2_CLK_RATE	(960000000UL)
+#define CRGPERI_PLL3_CLK_RATE	(1600000000UL)
+
+#define DEFAULT_DSS_CORE_CLK_08V_RATE	(535000000UL)
+#define DEFAULT_DSS_CORE_CLK_07V_RATE	(400000000UL)
+#define DEFAULT_PCLK_DSS_RATE	(114000000UL)
+#define DEFAULT_PCLK_PCTRL_RATE	(80000000UL)
+#define DSS_MAX_PXL0_CLK_288M (288000000UL)
+
+#define MMBUF_SIZE_MAX	(288 * 1024)
+#define HISI_DSS_CMDLIST_MAX	(16)
+#define HISI_DSS_CMDLIST_IDXS_MAX (0xFFFF)
+#define HISI_DSS_COPYBIT_CMDLIST_IDXS	 (0xC000)
+#define HISI_DSS_DPP_MAX_SUPPORT_BIT (0x7ff)
+#define HISIFB_DSS_PLATFORM_TYPE  (FB_ACCEL_HI366x | FB_ACCEL_PLATFORM_TYPE_ASIC)
+
+#define DSS_MIF_SMMU_SMRX_IDX_STEP (16)
+#define CRG_PERI_DIS3_DEFAULT_VAL     (0x0002F000)
+#define SCF_LINE_BUF	(2560)
+#define DSS_GLB_MODULE_CLK_SEL_DEFAULT_VAL  (0xF0000008)
+#define DSS_LDI_CLK_SEL_DEFAULT_VAL    (0x00000004)
+#define DSS_DBUF_MEM_CTRL_DEFAULT_VAL  (0x00000008)
+#define DSS_SMMU_RLD_EN0_DEFAULT_VAL    (0xffffffff)
+#define DSS_SMMU_RLD_EN1_DEFAULT_VAL    (0xffffff8f)
+#define DSS_SMMU_OUTSTANDING_VAL		(0xf)
+#define DSS_MIF_CTRL2_INVAL_SEL3_STRIDE_MASK		(0xc)
+#define DSS_AFBCE_ENC_OS_CFG_DEFAULT_VAL			(0x7)
+#define TUI_SEC_RCH			(DSS_RCHN_V0)
+#define DSS_CHN_MAX_DEFINE (DSS_COPYBIT_MAX)
+
+/* perf stat */
+#define DSS_DEVMEM_PERF_BASE						(0xFDF10000)
+#define CRG_PERIPH_APB_PERRSTSTAT0_REG 				(0x68)
+#define CRG_PERIPH_APB_IP_RST_PERF_STAT_BIT 		(18)
+#define PERF_SAMPSTOP_REG 							(0x10)
+#define DEVMEM_PERF_SIZE							(0x100)
+
+#endif
-- 
2.12.0-rc0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 8/8] fb: hisilicon: Add framebuffer driver for hi3660 SoC
  2017-02-07  2:35   ` cailiwei
@ 2017-02-07  2:35     ` cailiwei
  -1 siblings, 0 replies; 15+ messages in thread
From: cailiwei @ 2017-02-07  2:35 UTC (permalink / raw)
  To: linux-fbdev, linux-kernel, b.zolnierkie, guodong.xu
  Cc: suzhuangluan, dengqingshan, xuhongtao8, zhengwanchun,
	shizongxuan, cailiwei

From: Levy-Cai <cailiwei@hisilicon.com>

Add framebuffer driver for hi3660 SoC, this driver include lcd
driver & Hdmi adv7533/adv7535 driver, support lcd display at
1080p@60 and hdmi display at 1080p@60.

Signed-off-by: cailiwei <cailiwei@hisilicon.com>
---
 arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 48 +++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)
 mode change 100644 => 100755 arch/arm64/boot/dts/hisilicon/hi3660.dtsi

diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
old mode 100644
new mode 100755
index 5389799ff371..2ad11800dd67
--- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -132,6 +132,54 @@
 		clock-frequency = <1920000>;
 	};
 
+	/* display start */
+	framebuffer@E8600000 {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		compatible = "hisilicon,hisifb";
+		fastboot_enable_flag = <0>;
+		fake_lcd_flag = <0>;
+		dss_base_phy = <0xE8600000>;
+		// DSS, PERI_CRG, SCTRL, PCTRL, NOC_DSS_Service_Target, MMBUF_CFG
+		reg = <0 0xE8600000 0 0x80000>, <0 0xFFF35000 0 0x1000>, <0 0xFFF0A000 0 0x1000>, <0 0xE8A09000 0 0x1000>,
+				<0 0xE86C0000 0 0x10000>, <0 0xFFF02000 0 0x1000>, <0 0xFFF31000 0 0x1000>;
+		// dss-pdp, dss-sdp, dss-adp, dss-dsi0, dss-dsi1 irq
+		interrupts = <0 245 4>, <0 246 4>, <0 247 4>, <0 251 4>, <0 252 4>;
+		//regulator_dsssubsys-supply = <&dsssubsys>;
+		//regulator_mmbuf-supply = <&mmbuf>;
+		clocks = <&crg_ctrl HI3660_ACLK_GATE_DSS>, <&crg_ctrl HI3660_PCLK_GATE_DSS>, <&crg_ctrl HI3660_CLK_GATE_EDC0>,
+				<&crg_ctrl HI3660_CLK_GATE_LDI0>, <&crg_ctrl HI3660_CLK_GATE_LDI1>, <&sctrl HI3660_CLK_GATE_DSS_AXI_MM>,
+				<&sctrl HI3660_PCLK_GATE_MMBUF>, <&crg_ctrl HI3660_CLK_GATE_TXDPHY0_REF>, <&crg_ctrl HI3660_CLK_GATE_TXDPHY1_REF>,
+				<&crg_ctrl HI3660_CLK_GATE_TXDPHY0_CFG>, <&crg_ctrl HI3660_CLK_GATE_TXDPHY1_CFG>, <&crg_ctrl HI3660_PCLK_GATE_DSI0>,
+				<&crg_ctrl HI3660_PCLK_GATE_DSI1>;//, <&crg_ctrl HI3660_PCLK_GATE_PCTRL>;
+		clock-names = "aclk_dss", "pclk_dss", "clk_edc0", "clk_ldi0", "clk_ldi1",
+				"clk_dss_axi_mm", "pclk_mmbuf",
+				"clk_txdphy0_ref", "clk_txdphy1_ref", "clk_txdphy0_cfg", "clk_txdphy1_cfg",
+				"pclk_dsi0", "pclk_dsi1";//, "pclk_pctrl";
+		status = "ok";
+		fpga_flag = <0>;
+
+		/*iommu_info {
+			start-addr = <0x8000>;
+			size = <0xbfff8000>;
+		};*/
+	};
+
+	panel_lcd_hikey {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		compatible = "hisilicon,mipi_hikey";
+		lcd-bl-type = <0>;
+		lcd-display-type = <8>;
+		//vdd-supply = <&ldo3>;
+		lcd-ifbc-type = <0>;
+		gpios = <&gpio27 0 0>, <&gpio27 2 0>, <&gpio22 6 0>, <&gpio2 4 0>;
+		gpio_nums = <216 218 182 20>;
+		fpga_flag = <0>;
+		status = "disabled";
+	};
+	/* display end */
+
 	soc {
 		compatible = "simple-bus";
 		#address-cells = <2>;
-- 
2.12.0-rc0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 8/8] fb: hisilicon: Add framebuffer driver for hi3660 SoC
@ 2017-02-07  2:35     ` cailiwei
  0 siblings, 0 replies; 15+ messages in thread
From: cailiwei @ 2017-02-07  2:35 UTC (permalink / raw)
  To: linux-fbdev, linux-kernel, b.zolnierkie, guodong.xu
  Cc: suzhuangluan, dengqingshan, xuhongtao8, zhengwanchun,
	shizongxuan, cailiwei

From: Levy-Cai <cailiwei@hisilicon.com>

Add framebuffer driver for hi3660 SoC, this driver include lcd
driver & Hdmi adv7533/adv7535 driver, support lcd display at
1080p@60 and hdmi display at 1080p@60.

Signed-off-by: cailiwei <cailiwei@hisilicon.com>
---
 arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 48 +++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)
 mode change 100644 => 100755 arch/arm64/boot/dts/hisilicon/hi3660.dtsi

diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
old mode 100644
new mode 100755
index 5389799ff371..2ad11800dd67
--- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -132,6 +132,54 @@
 		clock-frequency = <1920000>;
 	};
 
+	/* display start */
+	framebuffer@E8600000 {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		compatible = "hisilicon,hisifb";
+		fastboot_enable_flag = <0>;
+		fake_lcd_flag = <0>;
+		dss_base_phy = <0xE8600000>;
+		// DSS, PERI_CRG, SCTRL, PCTRL, NOC_DSS_Service_Target, MMBUF_CFG
+		reg = <0 0xE8600000 0 0x80000>, <0 0xFFF35000 0 0x1000>, <0 0xFFF0A000 0 0x1000>, <0 0xE8A09000 0 0x1000>,
+				<0 0xE86C0000 0 0x10000>, <0 0xFFF02000 0 0x1000>, <0 0xFFF31000 0 0x1000>;
+		// dss-pdp, dss-sdp, dss-adp, dss-dsi0, dss-dsi1 irq
+		interrupts = <0 245 4>, <0 246 4>, <0 247 4>, <0 251 4>, <0 252 4>;
+		//regulator_dsssubsys-supply = <&dsssubsys>;
+		//regulator_mmbuf-supply = <&mmbuf>;
+		clocks = <&crg_ctrl HI3660_ACLK_GATE_DSS>, <&crg_ctrl HI3660_PCLK_GATE_DSS>, <&crg_ctrl HI3660_CLK_GATE_EDC0>,
+				<&crg_ctrl HI3660_CLK_GATE_LDI0>, <&crg_ctrl HI3660_CLK_GATE_LDI1>, <&sctrl HI3660_CLK_GATE_DSS_AXI_MM>,
+				<&sctrl HI3660_PCLK_GATE_MMBUF>, <&crg_ctrl HI3660_CLK_GATE_TXDPHY0_REF>, <&crg_ctrl HI3660_CLK_GATE_TXDPHY1_REF>,
+				<&crg_ctrl HI3660_CLK_GATE_TXDPHY0_CFG>, <&crg_ctrl HI3660_CLK_GATE_TXDPHY1_CFG>, <&crg_ctrl HI3660_PCLK_GATE_DSI0>,
+				<&crg_ctrl HI3660_PCLK_GATE_DSI1>;//, <&crg_ctrl HI3660_PCLK_GATE_PCTRL>;
+		clock-names = "aclk_dss", "pclk_dss", "clk_edc0", "clk_ldi0", "clk_ldi1",
+				"clk_dss_axi_mm", "pclk_mmbuf",
+				"clk_txdphy0_ref", "clk_txdphy1_ref", "clk_txdphy0_cfg", "clk_txdphy1_cfg",
+				"pclk_dsi0", "pclk_dsi1";//, "pclk_pctrl";
+		status = "ok";
+		fpga_flag = <0>;
+
+		/*iommu_info {
+			start-addr = <0x8000>;
+			size = <0xbfff8000>;
+		};*/
+	};
+
+	panel_lcd_hikey {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		compatible = "hisilicon,mipi_hikey";
+		lcd-bl-type = <0>;
+		lcd-display-type = <8>;
+		//vdd-supply = <&ldo3>;
+		lcd-ifbc-type = <0>;
+		gpios = <&gpio27 0 0>, <&gpio27 2 0>, <&gpio22 6 0>, <&gpio2 4 0>;
+		gpio_nums = <216 218 182 20>;
+		fpga_flag = <0>;
+		status = "disabled";
+	};
+	/* display end */
+
 	soc {
 		compatible = "simple-bus";
 		#address-cells = <2>;
-- 
2.12.0-rc0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/8] fb: hisilicon: Add framebuffer driver for hi3660 SoC
  2017-02-07  2:35   ` cailiwei
@ 2017-02-08 16:07     ` Bartlomiej Zolnierkiewicz
  -1 siblings, 0 replies; 15+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2017-02-08 16:07 UTC (permalink / raw)
  To: cailiwei
  Cc: linux-fbdev, linux-kernel, guodong.xu, suzhuangluan,
	dengqingshan, xuhongtao8, zhengwanchun, shizongxuan


Hi,

I cannot merge this upstream as it was collectively
decided that there should be no new fbdev drivers
(DRM subsystem should be used instead).

[ You may consider submitting this driver to staging
  subsystem to make hardware usable by kernel while
  proper DRM driver is being developed. ]

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

On Tuesday, February 07, 2017 10:35:52 AM cailiwei wrote:
> From: Levy-Cai <cailiwei@hisilicon.com>
> 
> Add framebuffer driver for hi3660 SoC, this driver include lcd
> driver & Hdmi adv7533/adv7535 driver, support lcd display at
> 1080p@60 and hdmi display at 1080p@60.
> 
> Signed-off-by: cailiwei <cailiwei@hisilicon.com>
> ---
>  drivers/video/fbdev/Kconfig           | 11 ++++++++++
>  drivers/video/fbdev/Makefile          |  1 +
>  drivers/video/fbdev/hisi/Kconfig      |  6 +++++
>  drivers/video/fbdev/hisi/dss/Makefile | 41 +++++++++++++++++++++++++++++++++++
>  4 files changed, 59 insertions(+)
>  mode change 100644 => 100755 drivers/video/fbdev/Kconfig
>  mode change 100644 => 100755 drivers/video/fbdev/Makefile
>  create mode 100755 drivers/video/fbdev/hisi/Kconfig
>  create mode 100755 drivers/video/fbdev/hisi/dss/Makefile
> 
> diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
> old mode 100644
> new mode 100755
> index 5d3b0db5ce0a..85c46cc75908
> --- a/drivers/video/fbdev/Kconfig
> +++ b/drivers/video/fbdev/Kconfig
> @@ -2429,6 +2429,16 @@ config FB_HYPERV
>  	help
>  	  This framebuffer driver supports Microsoft Hyper-V Synthetic Video.
>  
> +config FB_HISI
> +	tristate "Hisilicon Framebuffer support"
> +	depends on FB
> +	select FB_CFB_FILLRECT
> +	select FB_CFB_COPYAREA
> +	select FB_CFB_IMAGEBLIT
> +	select REGMAP
> +	help
> +	  This framebuffer driver supports Hisilicon FB.
> +
>  config FB_SIMPLE
>  	bool "Simple framebuffer support"
>  	depends on (FB = y)
> @@ -2448,6 +2458,7 @@ config FB_SIMPLE
>  source "drivers/video/fbdev/omap/Kconfig"
>  source "drivers/video/fbdev/omap2/Kconfig"
>  source "drivers/video/fbdev/mmp/Kconfig"
> +source "drivers/video/fbdev/hisi/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 ee8c81405a7f..a10d3d2793e3
> --- a/drivers/video/fbdev/Makefile
> +++ b/drivers/video/fbdev/Makefile
> @@ -23,6 +23,7 @@ obj-$(CONFIG_FB_I740)		  += i740fb.o
>  obj-$(CONFIG_FB_MATROX)		  += matrox/
>  obj-$(CONFIG_FB_RIVA)		  += riva/
>  obj-$(CONFIG_FB_NVIDIA)		  += nvidia/
> +obj-$(CONFIG_FB_HISI)             += hisi/dss/
>  obj-$(CONFIG_FB_ATY)		  += aty/ macmodes.o
>  obj-$(CONFIG_FB_ATY128)		  += aty/ macmodes.o
>  obj-$(CONFIG_FB_RADEON)		  += aty/
> diff --git a/drivers/video/fbdev/hisi/Kconfig b/drivers/video/fbdev/hisi/Kconfig
> new file mode 100755
> index 000000000000..c30747d52a38
> --- /dev/null
> +++ b/drivers/video/fbdev/hisi/Kconfig
> @@ -0,0 +1,6 @@
> +config HISI_FB_KIRIN960
> +	tristate "HISI FB KIRIN960 Framebuffer support"
> +	depends on FB_HISI
> +
> +	help
> +	  This framebuffer driver supports KIRIN960 FB.
> diff --git a/drivers/video/fbdev/hisi/dss/Makefile b/drivers/video/fbdev/hisi/dss/Makefile
> new file mode 100755
> index 000000000000..60004880dd80
> --- /dev/null
> +++ b/drivers/video/fbdev/hisi/dss/Makefile
> @@ -0,0 +1,41 @@
> +ifeq ($(CONFIG_HISI_FB_KIRIN960),y)
> +obj-$(CONFIG_HISI_FB_KIRIN960) := hisifb.o
> +endif
> +
> +hisifb-objs := \
> +	hisi_mipi_dsi_host.o \
> +	hisi_mipi_dsi.o \
> +	hisi_dpe.o \
> +	hisi_fb_panel.o \
> +	hisi_fb_isr.o \
> +	hisi_fb_vsync.o \
> +	hisi_fb_buf_sync.o \
> +	hisi_fb_bl.o \
> +	hisi_fb_utils.o \
> +	hisi_fb.o \
> +	hisi_overlay_utils.o \
> +	hisi_block_algorithm.o \
> +	hisi_overlay_online.o \
> +	hisi_overlay_cmdlist_utils.o
> +
> +ifeq ($(CONFIG_HISI_FB_KIRIN960),y)
> +hisifb-objs += \
> +	hisi_dpe_utils_hi3660.o \
> +	hisi_overlay_utils_hi3660.o \
> +	panel/mipi_hikey_nte300nts.o \
> +	hdmi/adv75xx.o \
> +	hdmi/mipi_adi_hdmi.o
> +endif
> +
> +EXTRA_CFLAGS += -Idrivers/video/hisi/dss \
> +		-Idrivers/video/hisi/panel \
> +		-Idrivers/video/hisi \
> +		-Iinclude \
> +		-Idrivers/staging/android
> +
> +ifeq ($(CONFIG_HISI_PERIDVFS),y)
> +EXTRA_CFLAGS += -Idrivers/clk/hisi/peri_dvfs
> +endif
> +
> +clean:
> +	rm *.o .*cmd

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/8] fb: hisilicon: Add framebuffer driver for hi3660 SoC
@ 2017-02-08 16:07     ` Bartlomiej Zolnierkiewicz
  0 siblings, 0 replies; 15+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2017-02-08 16:07 UTC (permalink / raw)
  To: cailiwei
  Cc: linux-fbdev, linux-kernel, guodong.xu, suzhuangluan,
	dengqingshan, xuhongtao8, zhengwanchun, shizongxuan


Hi,

I cannot merge this upstream as it was collectively
decided that there should be no new fbdev drivers
(DRM subsystem should be used instead).

[ You may consider submitting this driver to staging
  subsystem to make hardware usable by kernel while
  proper DRM driver is being developed. ]

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

On Tuesday, February 07, 2017 10:35:52 AM cailiwei wrote:
> From: Levy-Cai <cailiwei@hisilicon.com>
> 
> Add framebuffer driver for hi3660 SoC, this driver include lcd
> driver & Hdmi adv7533/adv7535 driver, support lcd display at
> 1080p@60 and hdmi display at 1080p@60.
> 
> Signed-off-by: cailiwei <cailiwei@hisilicon.com>
> ---
>  drivers/video/fbdev/Kconfig           | 11 ++++++++++
>  drivers/video/fbdev/Makefile          |  1 +
>  drivers/video/fbdev/hisi/Kconfig      |  6 +++++
>  drivers/video/fbdev/hisi/dss/Makefile | 41 +++++++++++++++++++++++++++++++++++
>  4 files changed, 59 insertions(+)
>  mode change 100644 => 100755 drivers/video/fbdev/Kconfig
>  mode change 100644 => 100755 drivers/video/fbdev/Makefile
>  create mode 100755 drivers/video/fbdev/hisi/Kconfig
>  create mode 100755 drivers/video/fbdev/hisi/dss/Makefile
> 
> diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
> old mode 100644
> new mode 100755
> index 5d3b0db5ce0a..85c46cc75908
> --- a/drivers/video/fbdev/Kconfig
> +++ b/drivers/video/fbdev/Kconfig
> @@ -2429,6 +2429,16 @@ config FB_HYPERV
>  	help
>  	  This framebuffer driver supports Microsoft Hyper-V Synthetic Video.
>  
> +config FB_HISI
> +	tristate "Hisilicon Framebuffer support"
> +	depends on FB
> +	select FB_CFB_FILLRECT
> +	select FB_CFB_COPYAREA
> +	select FB_CFB_IMAGEBLIT
> +	select REGMAP
> +	help
> +	  This framebuffer driver supports Hisilicon FB.
> +
>  config FB_SIMPLE
>  	bool "Simple framebuffer support"
>  	depends on (FB = y)
> @@ -2448,6 +2458,7 @@ config FB_SIMPLE
>  source "drivers/video/fbdev/omap/Kconfig"
>  source "drivers/video/fbdev/omap2/Kconfig"
>  source "drivers/video/fbdev/mmp/Kconfig"
> +source "drivers/video/fbdev/hisi/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 ee8c81405a7f..a10d3d2793e3
> --- a/drivers/video/fbdev/Makefile
> +++ b/drivers/video/fbdev/Makefile
> @@ -23,6 +23,7 @@ obj-$(CONFIG_FB_I740)		  += i740fb.o
>  obj-$(CONFIG_FB_MATROX)		  += matrox/
>  obj-$(CONFIG_FB_RIVA)		  += riva/
>  obj-$(CONFIG_FB_NVIDIA)		  += nvidia/
> +obj-$(CONFIG_FB_HISI)             += hisi/dss/
>  obj-$(CONFIG_FB_ATY)		  += aty/ macmodes.o
>  obj-$(CONFIG_FB_ATY128)		  += aty/ macmodes.o
>  obj-$(CONFIG_FB_RADEON)		  += aty/
> diff --git a/drivers/video/fbdev/hisi/Kconfig b/drivers/video/fbdev/hisi/Kconfig
> new file mode 100755
> index 000000000000..c30747d52a38
> --- /dev/null
> +++ b/drivers/video/fbdev/hisi/Kconfig
> @@ -0,0 +1,6 @@
> +config HISI_FB_KIRIN960
> +	tristate "HISI FB KIRIN960 Framebuffer support"
> +	depends on FB_HISI
> +
> +	help
> +	  This framebuffer driver supports KIRIN960 FB.
> diff --git a/drivers/video/fbdev/hisi/dss/Makefile b/drivers/video/fbdev/hisi/dss/Makefile
> new file mode 100755
> index 000000000000..60004880dd80
> --- /dev/null
> +++ b/drivers/video/fbdev/hisi/dss/Makefile
> @@ -0,0 +1,41 @@
> +ifeq ($(CONFIG_HISI_FB_KIRIN960),y)
> +obj-$(CONFIG_HISI_FB_KIRIN960) := hisifb.o
> +endif
> +
> +hisifb-objs := \
> +	hisi_mipi_dsi_host.o \
> +	hisi_mipi_dsi.o \
> +	hisi_dpe.o \
> +	hisi_fb_panel.o \
> +	hisi_fb_isr.o \
> +	hisi_fb_vsync.o \
> +	hisi_fb_buf_sync.o \
> +	hisi_fb_bl.o \
> +	hisi_fb_utils.o \
> +	hisi_fb.o \
> +	hisi_overlay_utils.o \
> +	hisi_block_algorithm.o \
> +	hisi_overlay_online.o \
> +	hisi_overlay_cmdlist_utils.o
> +
> +ifeq ($(CONFIG_HISI_FB_KIRIN960),y)
> +hisifb-objs += \
> +	hisi_dpe_utils_hi3660.o \
> +	hisi_overlay_utils_hi3660.o \
> +	panel/mipi_hikey_nte300nts.o \
> +	hdmi/adv75xx.o \
> +	hdmi/mipi_adi_hdmi.o
> +endif
> +
> +EXTRA_CFLAGS += -Idrivers/video/hisi/dss \
> +		-Idrivers/video/hisi/panel \
> +		-Idrivers/video/hisi \
> +		-Iinclude \
> +		-Idrivers/staging/android
> +
> +ifeq ($(CONFIG_HISI_PERIDVFS),y)
> +EXTRA_CFLAGS += -Idrivers/clk/hisi/peri_dvfs
> +endif
> +
> +clean:
> +	rm *.o .*cmd


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2017-02-08 16:41 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20170207024027epcas5p2528e797ee0c34cb60d97f0b659f4acbf@epcas5p2.samsung.com>
2017-02-07  2:35 ` [PATCH 1/8] fb: hisilicon: Add framebuffer driver for hi3660 SoC cailiwei
2017-02-07  2:35   ` cailiwei
2017-02-07  2:35   ` [PATCH 2/8] " cailiwei
2017-02-07  2:35     ` cailiwei
2017-02-07  2:35   ` [PATCH 3/8] " cailiwei
2017-02-07  2:35   ` [PATCH 4/8] " cailiwei
2017-02-07  2:35   ` [PATCH 5/8] " cailiwei
2017-02-07  2:35     ` cailiwei
2017-02-07  2:35   ` [PATCH 6/8] " cailiwei
2017-02-07  2:35     ` cailiwei
2017-02-07  2:35   ` [PATCH 7/8] " cailiwei
2017-02-07  2:35   ` [PATCH 8/8] " cailiwei
2017-02-07  2:35     ` cailiwei
2017-02-08 16:07   ` [PATCH 1/8] " Bartlomiej Zolnierkiewicz
2017-02-08 16:07     ` Bartlomiej Zolnierkiewicz

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.