linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/49] DRM driver for Hikey 970
@ 2020-08-19 11:45 Mauro Carvalho Chehab
  2020-08-19 11:45 ` [PATCH 01/49] staging: hikey9xx: Add hisilicon DRM driver for hikey960/970 Mauro Carvalho Chehab
                   ` (4 more replies)
  0 siblings, 5 replies; 42+ messages in thread
From: Mauro Carvalho Chehab @ 2020-08-19 11:45 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linuxarm, mauro.chehab, Mauro Carvalho Chehab, John Stultz,
	Manivannan Sadhasivam, Daniel Vetter, dri-devel, Bogdan Togorean,
	Liwei Cai, linux-arm-kernel, Daniel Borkmann, Rob Herring,
	David S. Miller, Xinliang Liu, Neil Armstrong, Wanchun Zheng,
	devel, bpf, Xiubin Zhang, linux-media, Tomi Valkeinen,
	Jesper Dangaard Brouer, Laurent Pinchart, Xinwei Kong,
	Alexei Starovoitov, devicetree, Rob Clark, Laurentiu Palcu,
	Andrzej Hajda, John Fastabend, Liuyao An, linaro-mm-sig, Wei Xu,
	Rongrong Zou, Philipp Zabel, Sam Ravnborg, netdev, Sumit Semwal,
	linux-kernel, Jakub Kicinski, David Airlie, Chen Feng

This patch series port the out-of-tree driver for Hikey 970 (which
should also support Hikey 960) from the official 96boards tree:

   https://github.com/96boards-hikey/linux/tree/hikey970-v4.9

Based on his history, this driver seems to be originally written
for Kernel 4.4, and was later ported to Kernel 4.9. The original
driver used to depend on ION (from Kernel 4.4) and had its own
implementation for FB dev API.

As I need to preserve the original history (with has patches from
both HiSilicon and from Linaro),  I'm starting from the original
patch applied there. The remaining patches are incremental,
and port this driver to work with upstream Kernel.

This driver doesn't depend on any firmware or on any special
userspace code. It works as-is with both X11 and Wayland.

Yet, I'm submitting it via staging due to the following reasons:

- It depends on the LDO3 power supply, which is provided by
  a regulator driver that it is currently on staging;
- Due to legal reasons, I need to preserve the authorship of
  each one responsbile for each patch. So, I need to start from
  the original patch from Kernel 4.4;
- There are still some problems I need to figure out how to solve:
   - The adv7535 can't get EDID data. Maybe it is a timing issue,
     but it requires more research to be sure about how to solve it;
   - The driver only accept resolutions on a defined list, as there's
     a known bug that this driver may have troubles with random
     resolutions. Probably due to a bug at the pixel clock settings;
   - Sometimes (at least with 1080p), it generates LDI underflow
     errors, which in turn causes the DRM to stop working. That
     happens for example when using gdm on Wayland and
     gnome on X11;
   - Probably related to the previous issue, when the monitor
     suspends due to DPMS, it doesn't return back to life.

So, IMO, the best is to keep it on staging for a while, until those
remaining bugs gets solved.

I added this series, together with the regulator driver and
a few other patches (including a hack to fix a Kernel 5.8 
regression at WiFi ) at:

	https://gitlab.freedesktop.org/mchehab_kernel/hikey-970/-/commits/master


Chen Feng (1):
  staging: hikey9xx: Add hisilicon DRM driver for hikey960/970

John Stultz (1):
  staging: hikey9xx/gpu: port it to work with Kernel v4.9

Liwei Cai (2):
  staging: hikey9xx/gpu: solve tearing issue of display
  staging: hikey9xx/gpu: resolve the performance issue by interrupt
    mechanism

Mauro Carvalho Chehab (38):
  staging: hikey9xx/gpu: get rid of adv7535 fork
  staging: hikey9xx/gpu: rename the Kirin9xx namespace
  staging: hikey9xx/gpu: get rid of kirin9xx_fbdev.c
  staging: hikey9xx/gpu: get rid of some ifdefs
  staging: hikey9xx/gpu: rename the config option for Kirin970
  staging: hikey9xx/gpu: change the includes to reflect upstream
  staging: hikey9xx/gpu: port driver to upstream kAPIs
  staging: hikey9xx/gpu: add a copy of set_reg() function there
  staging: hikey9xx/gpu: get rid of ION headers
  staging: hikey9xx/gpu: add support for using a reserved CMA memory
  staging: hikey9xx/gpu: cleanup encoder attach logic
  staging: hikey9xx/gpu: Change the logic which sets the burst mode
  staging: hikey9xx/gpu: fix the DRM setting logic
  staging: hikey9xx/gpu: do some code cleanups
  staging: hikey9xx/gpu: use default GEM_CMA fops
  staging: hikey9xx/gpu: place vblank enable/disable at the right place
  staging: hikey9xx/gpu: remove an uneeded hack
  staging: hikey9xx/gpu: add a possible implementation for
    atomic_disable
  staging: hikey9xx/gpu: register connector
  staging: hikey9xx/gpu: fix driver name
  staging: hikey9xx/gpu: get rid of iommu_format
  staging: hikey9xx/gpu: re-work the mode validation code
  staging: hikey9xx/gpu: add support for enable/disable ldo3 regulator
  staging: hikey9xx/gpu: add SPMI headers
  staging: hikey9xx/gpu: solve most coding style issues
  staging: hikey9xx/gpu: don't use iommu code
  staging: hikey9xx/gpu: add kirin9xx driver to the building system
  staging: hikey9xx/gpu: get rid of typedefs
  staging: hikey9xx/gpu: get rid of input/output macros
  staging: hikey9xx/gpu: get rid of some unused data
  staging: hikey9xx/gpu: place common definitions at kirin9xx_dpe.h
  staging: hikey9xx/gpu: get rid of DRM_HISI_KIRIN970
  dts: hisilicon: hi3670.dtsi: add I2C settings
  dts: hikey970-pinctrl.dtsi: add missing pinctrl settings
  dt: hisilicon: add support for the PMIC found on Hikey 970
  dts: add support for Hikey 970 DRM
  staging: hikey9xx/gpu: drop kirin9xx_pwm
  dt: display: Add binds for the DPE and DSI controller for Kirin
    960/970

Xiubin Zhang (7):
  staging: hikey9xx/gpu: add support to hikey970 HDMI and panel
  staging: hikey9xx/gpu: Solve SR Cannot Display Problems.
  staging: hikey9xx/gpu: Solve HDMI compatibility Problem.
  staging: hikey9xx/gpu: Support MIPI DSI 3 lanes for hikey970.
  staging: hikey9xx/gpu: Solve SR test reset problem for hikey970.
  staging: hikey9xx/gpu: add debug prints for this driver
  staging: hikey9xx/gpu: Add support 10.1 inch special HDMI displays.

 .../display/hisilicon,hi3660-dpe.yaml         |   99 +
 .../display/hisilicon,hi3660-dsi.yaml         |  102 +
 .../boot/dts/hisilicon/hi3670-hikey970.dts    |   56 +-
 arch/arm64/boot/dts/hisilicon/hi3670.dtsi     |   77 +
 .../boot/dts/hisilicon/hikey970-drm.dtsi      |   93 +
 .../boot/dts/hisilicon/hikey970-pinctrl.dtsi  |  548 +++-
 .../boot/dts/hisilicon/hikey970-pmic.dtsi     |  197 ++
 drivers/staging/hikey9xx/Kconfig              |    3 +
 drivers/staging/hikey9xx/Makefile             |    1 +
 drivers/staging/hikey9xx/gpu/Kconfig          |   22 +
 drivers/staging/hikey9xx/gpu/Makefile         |    9 +
 drivers/staging/hikey9xx/gpu/kirin960_defs.c  |  378 +++
 .../staging/hikey9xx/gpu/kirin960_dpe_reg.h   |  233 ++
 drivers/staging/hikey9xx/gpu/kirin970_defs.c  |  381 +++
 .../staging/hikey9xx/gpu/kirin970_dpe_reg.h   | 1188 ++++++++
 drivers/staging/hikey9xx/gpu/kirin9xx_dpe.h   | 2437 +++++++++++++++++
 .../hikey9xx/gpu/kirin9xx_drm_dpe_utils.c     | 1178 ++++++++
 .../hikey9xx/gpu/kirin9xx_drm_dpe_utils.h     |  286 ++
 .../staging/hikey9xx/gpu/kirin9xx_drm_drv.c   |  368 +++
 .../staging/hikey9xx/gpu/kirin9xx_drm_drv.h   |   57 +
 .../staging/hikey9xx/gpu/kirin9xx_drm_dss.c   | 1063 +++++++
 .../hikey9xx/gpu/kirin9xx_drm_overlay_utils.c | 1005 +++++++
 .../hikey9xx/gpu/kirin9xx_dw_drm_dsi.c        | 2132 ++++++++++++++
 .../hikey9xx/gpu/kirin9xx_dw_dsi_reg.h        |  146 +
 .../staging/hikey9xx/gpu/kirin9xx_fb_panel.h  |  191 ++
 25 files changed, 12229 insertions(+), 21 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/hisilicon,hi3660-dpe.yaml
 create mode 100644 Documentation/devicetree/bindings/display/hisilicon,hi3660-dsi.yaml
 create mode 100644 arch/arm64/boot/dts/hisilicon/hikey970-drm.dtsi
 create mode 100644 arch/arm64/boot/dts/hisilicon/hikey970-pmic.dtsi
 create mode 100644 drivers/staging/hikey9xx/gpu/Kconfig
 create mode 100644 drivers/staging/hikey9xx/gpu/Makefile
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin960_defs.c
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin960_dpe_reg.h
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin970_defs.c
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin970_dpe_reg.h
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_dpe.h
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_drm_dpe_utils.c
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_drm_dpe_utils.h
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.c
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.h
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_drm_dss.c
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_dw_drm_dsi.c
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_dw_dsi_reg.h
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_fb_panel.h

-- 
2.26.2



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

* [PATCH 01/49] staging: hikey9xx: Add hisilicon DRM driver for hikey960/970
  2020-08-19 11:45 [PATCH 00/49] DRM driver for Hikey 970 Mauro Carvalho Chehab
@ 2020-08-19 11:45 ` Mauro Carvalho Chehab
  2020-08-19 11:46 ` [PATCH 40/49] staging: hikey9xx/gpu: get rid of input/output macros Mauro Carvalho Chehab
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 42+ messages in thread
From: Mauro Carvalho Chehab @ 2020-08-19 11:45 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linuxarm, mauro.chehab, Chen Feng, Mauro Carvalho Chehab,
	John Stultz, Manivannan Sadhasivam, Daniel Vetter, dri-devel,
	Philipp Zabel, Alexei Starovoitov, Daniel Borkmann,
	David S. Miller, Jakub Kicinski, Jesper Dangaard Brouer,
	John Fastabend, Sumit Semwal, Liwei Cai, Xiubin Zhang,
	Wanchun Zheng, linux-kernel, devel, netdev, bpf, linux-media,
	linaro-mm-sig

From: Chen Feng <puck.chen@hisilicon.com>

Add initial driver for hikey960 DRM driver, backported
from OOT tree. Later patches will be needed to make this
driver work.

[jstultz: Rework patchset to use upstream adv7511 and remove duplicated code]

[mchehab+huawei@kernel.org: port just a subset of the
 original patch and place it at staging]

Signed-off-by: Chen Feng <puck.chen@hisilicon.com>
Signed-off-by: Liwei Cai <cailiwei@hisilicon.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 drivers/staging/hikey9xx/gpu/Kconfig          |   52 +
 drivers/staging/hikey9xx/gpu/Makefile         |   12 +
 drivers/staging/hikey9xx/gpu/dw_drm_dsi.c     | 1650 +++++++++
 drivers/staging/hikey9xx/gpu/dw_dsi_reg.h     |  145 +
 drivers/staging/hikey9xx/gpu/kirin_dpe_reg.h  | 3114 +++++++++++++++++
 .../hikey9xx/gpu/kirin_drm_dpe_utils.c        |  731 ++++
 .../hikey9xx/gpu/kirin_drm_dpe_utils.h        |   58 +
 drivers/staging/hikey9xx/gpu/kirin_drm_drv.c  |  380 ++
 drivers/staging/hikey9xx/gpu/kirin_drm_drv.h  |   60 +
 drivers/staging/hikey9xx/gpu/kirin_drm_dss.c  |  701 ++++
 .../hikey9xx/gpu/kirin_drm_overlay_utils.c    | 1288 +++++++
 drivers/staging/hikey9xx/gpu/kirin_fb.c       |   94 +
 drivers/staging/hikey9xx/gpu/kirin_fbdev.c    |  470 +++
 13 files changed, 8755 insertions(+)
 create mode 100644 drivers/staging/hikey9xx/gpu/Kconfig
 create mode 100644 drivers/staging/hikey9xx/gpu/Makefile
 create mode 100644 drivers/staging/hikey9xx/gpu/dw_drm_dsi.c
 create mode 100644 drivers/staging/hikey9xx/gpu/dw_dsi_reg.h
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin_dpe_reg.h
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin_drm_dpe_utils.c
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin_drm_dpe_utils.h
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin_drm_drv.c
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin_drm_drv.h
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin_drm_dss.c
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin_drm_overlay_utils.c
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin_fb.c
 create mode 100644 drivers/staging/hikey9xx/gpu/kirin_fbdev.c

diff --git a/drivers/staging/hikey9xx/gpu/Kconfig b/drivers/staging/hikey9xx/gpu/Kconfig
new file mode 100644
index 000000000000..5533ee624f29
--- /dev/null
+++ b/drivers/staging/hikey9xx/gpu/Kconfig
@@ -0,0 +1,52 @@
+config DRM_HISI_KIRIN
+	tristate "DRM Support for Hisilicon Kirin series SoCs Platform"
+	depends on DRM && OF && ARM64
+	select DRM_KMS_HELPER
+	select DRM_GEM_CMA_HELPER
+	select DRM_KMS_CMA_HELPER
+	select HISI_KIRIN_DW_DSI
+	help
+	  Choose this option if you have a hisilicon Kirin chipsets(hi6220).
+	  If M is selected the module will be called kirin-drm.
+
+config DRM_KIRIN_960
+	tristate "DRM Support for Hisilicon Kirin960 series SoCs Platform"
+	depends on DRM && OF && ARM64
+	select DRM_KMS_HELPER
+	select DRM_GEM_CMA_HELPER
+	select DRM_KMS_CMA_HELPER
+	select HISI_KIRIN_DW_DSI
+	help
+	  Choose this option if you have a hisilicon Kirin chipsets(kirin960).
+	  If M is selected the module will be called kirin-drm.
+
+config HISI_KIRIN_DW_DSI
+	tristate "HiSilicon Kirin specific extensions for Synopsys DW MIPI DSI"
+	depends on DRM_HISI_KIRIN || DRM_KIRIN_960
+	select DRM_MIPI_DSI
+	select DRM_PANEL
+	help
+	 This selects support for HiSilicon Kirin SoC specific extensions for
+	 the Synopsys DesignWare DSI driver. If you want to enable MIPI DSI on
+	 hi6220 based SoC, you should selet this option.
+
+config DRM_PANEL_HIKEY960_NTE300NTS
+	tristate "Hikey960 NTE300NTS video mode panel"
+	depends on OF
+	depends on DRM_MIPI_DSI
+	help
+		Say Y here if you want to enable LCD panel driver for Hikey960 boadr.
+		Current support panel: NTE300NTS(1920X1200)
+
+config HISI_FB_970
+	tristate "DRM Support for Hisilicon Kirin970 series SoCs Platform"
+	depends on DRM && OF && ARM64
+	depends on DRM_MIPI_DSI
+	help
+	  Choose this option if you have a hisilicon Kirin chipsets(kirin970).
+	  If M is selected the module will be called kirin-drm.
+
+config HDMI_ADV7511_AUDIO
+	tristate "HDMI Support ADV7511 audio"
+	help
+	  Choose this option to support HDMI ADV7511 audio.
diff --git a/drivers/staging/hikey9xx/gpu/Makefile b/drivers/staging/hikey9xx/gpu/Makefile
new file mode 100644
index 000000000000..42d1ed179264
--- /dev/null
+++ b/drivers/staging/hikey9xx/gpu/Makefile
@@ -0,0 +1,12 @@
+EXTRA_CFLAGS += \
+		-Iinclude/drm
+
+kirin-drm-y := kirin_fbdev.o \
+		kirin_fb.o \
+		kirin_drm_drv.o \
+		kirin_drm_dss.o \
+		kirin_drm_dpe_utils.o \
+		kirin_drm_overlay_utils.o \
+
+obj-$(CONFIG_DRM_KIRIN_960) += kirin-drm.o
+obj-$(CONFIG_HISI_KIRIN_DW_DSI) += dw_drm_dsi.o
diff --git a/drivers/staging/hikey9xx/gpu/dw_drm_dsi.c b/drivers/staging/hikey9xx/gpu/dw_drm_dsi.c
new file mode 100644
index 000000000000..1d1d4f49609c
--- /dev/null
+++ b/drivers/staging/hikey9xx/gpu/dw_drm_dsi.c
@@ -0,0 +1,1650 @@
+/*
+ * DesignWare MIPI DSI Host Controller v1.02 driver
+ *
+ * Copyright (c) 2016 Linaro Limited.
+ * Copyright (c) 2014-2016 Hisilicon Limited.
+ *
+ * Author:
+ *	<shizongxuan@huawei.com>
+ *	<zhangxiubin@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of_graph.h>
+#include <linux/iopoll.h>
+#include <video/mipi_display.h>
+#include <linux/gpio/consumer.h>
+#include <linux/of_address.h>
+
+#include <drm/drm_of.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_encoder_slave.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_panel.h>
+
+#include "dw_dsi_reg.h"
+#include "kirin_dpe_reg.h"
+#include "kirin_drm_dpe_utils.h"
+
+#define DTS_COMP_DSI_NAME "hisilicon,hi3660-dsi"
+
+#define MAX_TX_ESC_CLK		10
+#define ROUND(x, y)		((x) / (y) + \
+				((x) % (y) * 10 / (y) >= 5 ? 1 : 0))
+#define ROUND1(x, y)	((x) / (y) + ((x) % (y)  ? 1 : 0))
+#define PHY_REF_CLK_RATE	19200000
+#define PHY_REF_CLK_PERIOD_PS	(1000000000 / (PHY_REF_CLK_RATE / 1000))
+
+#define encoder_to_dsi(encoder) \
+	container_of(encoder, struct dw_dsi, encoder)
+#define host_to_dsi(host) \
+	container_of(host, struct dw_dsi, host)
+#define connector_to_dsi(connector) \
+	container_of(connector, struct dw_dsi, connector)
+#define DSS_REDUCE(x)	((x) > 0 ? ((x) - 1) : (x))
+
+enum dsi_output_client {
+	OUT_HDMI = 0,
+	OUT_PANEL,
+	OUT_MAX
+};
+
+struct mipi_phy_params {
+	u64 lane_byte_clk;
+	u32 clk_division;
+
+	u32 clk_lane_lp2hs_time;
+	u32 clk_lane_hs2lp_time;
+	u32 data_lane_lp2hs_time;
+	u32 data_lane_hs2lp_time;
+	u32 clk2data_delay;
+	u32 data2clk_delay;
+
+	u32 clk_pre_delay;
+	u32 clk_post_delay;
+	u32 clk_t_lpx;
+	u32 clk_t_hs_prepare;
+	u32 clk_t_hs_zero;
+	u32 clk_t_hs_trial;
+	u32 clk_t_wakeup;
+	u32 data_pre_delay;
+	u32 data_post_delay;
+	u32 data_t_lpx;
+	u32 data_t_hs_prepare;
+	u32 data_t_hs_zero;
+	u32 data_t_hs_trial;
+	u32 data_t_ta_go;
+	u32 data_t_ta_get;
+	u32 data_t_wakeup;
+
+	u32 phy_stop_wait_time;
+
+	u32 rg_vrefsel_vcm;
+	u32 rg_hstx_ckg_sel;
+	u32 rg_pll_fbd_div5f;
+	u32 rg_pll_fbd_div1f;
+	u32 rg_pll_fbd_2p;
+	u32 rg_pll_enbwt;
+	u32 rg_pll_fbd_p;
+	u32 rg_pll_fbd_s;
+	u32 rg_pll_pre_div1p;
+	u32 rg_pll_pre_p;
+	u32 rg_pll_vco_750m;
+	u32 rg_pll_lpf_rs;
+	u32 rg_pll_lpf_cs;
+	u32 rg_pll_enswc;
+	u32 rg_pll_chp;
+
+	u32 pll_register_override;		/*0x1E[0]*/
+	u32 pll_power_down;			/*0x1E[1]*/
+	u32 rg_band_sel;				/*0x1E[2]*/
+	u32 rg_phase_gen_en;		/*0x1E[3]*/
+	u32 reload_sel;				/*0x1E[4]*/
+	u32 rg_pll_cp_p;				/*0x1E[7:5]*/
+	u32 rg_pll_refsel;				/*0x16[1:0]*/
+	u32 rg_pll_cp;				/*0x16[7:5]*/
+	u32 load_command;
+};
+
+struct dsi_hw_ctx {
+	void __iomem *base;
+	char __iomem *peri_crg_base;
+
+	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 dw_dsi_client {
+	u32 lanes;
+	u32 phy_clock; /* in kHz */
+	enum mipi_dsi_pixel_format format;
+	unsigned long mode_flags;
+};
+
+struct mipi_panel_info {
+	u8 dsi_version;
+	u8 vc;
+	u8 lane_nums;
+	u8 lane_nums_select_support;
+	u8 color_mode;
+	u32 dsi_bit_clk; /* clock lane(p/n) */
+	u32 burst_mode;
+	u32 max_tx_esc_clk;
+	u8 non_continue_en;
+
+	u32 dsi_bit_clk_val1;
+	u32 dsi_bit_clk_val2;
+	u32 dsi_bit_clk_val3;
+	u32 dsi_bit_clk_val4;
+	u32 dsi_bit_clk_val5;
+	u32 dsi_bit_clk_upt;
+	/*uint32_t dsi_pclk_rate;*/
+
+	u32 hs_wr_to_time;
+
+	/* dphy config parameter adjust*/
+	u32 clk_post_adjust;
+	u32 clk_pre_adjust;
+	u32 clk_pre_delay_adjust;
+	u32 clk_t_hs_exit_adjust;
+	u32 clk_t_hs_trial_adjust;
+	u32 clk_t_hs_prepare_adjust;
+	int clk_t_lpx_adjust;
+	u32 clk_t_hs_zero_adjust;
+	u32 data_post_delay_adjust;
+	int data_t_lpx_adjust;
+	u32 data_t_hs_prepare_adjust;
+	u32 data_t_hs_zero_adjust;
+	u32 data_t_hs_trial_adjust;
+	u32 rg_vrefsel_vcm_adjust;
+
+	/*only for Chicago<3660> use*/
+	u32 rg_vrefsel_vcm_clk_adjust;
+	u32 rg_vrefsel_vcm_data_adjust;
+};
+
+struct ldi_panel_info {
+	u32 h_back_porch;
+	u32 h_front_porch;
+	u32 h_pulse_width;
+
+	/*
+	** note: vbp > 8 if used overlay compose,
+	** also lcd vbp > 8 in lcd power on sequence
+	*/
+	u32 v_back_porch;
+	u32 v_front_porch;
+	u32 v_pulse_width;
+
+	u8 hsync_plr;
+	u8 vsync_plr;
+	u8 pixelclk_plr;
+	u8 data_en_plr;
+
+	/* for cabc */
+	u8 dpi0_overlap_size;
+	u8 dpi1_overlap_size;
+};
+
+struct dw_dsi {
+	struct drm_encoder encoder;
+	struct drm_bridge *bridge;
+	struct drm_panel *panel;
+	struct mipi_dsi_host host;
+	struct drm_connector connector; /* connector for panel */
+	struct drm_display_mode cur_mode;
+	struct dsi_hw_ctx *ctx;
+	struct mipi_phy_params phy;
+	struct mipi_panel_info mipi;
+	struct ldi_panel_info ldi;
+	u32 lanes;
+	enum mipi_dsi_pixel_format format;
+	unsigned long mode_flags;
+	struct gpio_desc *gpio_mux;
+	struct dw_dsi_client client[OUT_MAX];
+	enum dsi_output_client cur_client;
+	bool enable;
+};
+
+struct dsi_data {
+	struct dw_dsi dsi;
+	struct dsi_hw_ctx ctx;
+};
+
+struct dsi_phy_range {
+	u32 min_range_kHz;
+	u32 max_range_kHz;
+	u32 pll_vco_750M;
+	u32 hstx_ckg_sel;
+};
+
+static const struct dsi_phy_range dphy_range_info[] = {
+	{   46875,    62500,   1,    7 },
+	{   62500,    93750,   0,    7 },
+	{   93750,   125000,   1,    6 },
+	{  125000,   187500,   0,    6 },
+	{  187500,   250000,   1,    5 },
+	{  250000,   375000,   0,    5 },
+	{  375000,   500000,   1,    4 },
+	{  500000,   750000,   0,    4 },
+	{  750000,  1000000,   1,    0 },
+	{ 1000000,  1500000,   0,    0 }
+};
+
+void dsi_set_output_client(struct drm_device *dev)
+{
+	enum dsi_output_client client;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+	struct dw_dsi *dsi;
+
+	mutex_lock(&dev->mode_config.mutex);
+
+	/* find dsi encoder */
+	drm_for_each_encoder(encoder, dev)
+		if (encoder->encoder_type == DRM_MODE_ENCODER_DSI)
+			break;
+	dsi = encoder_to_dsi(encoder);
+
+	/* find HDMI connector */
+	drm_for_each_connector(connector, dev)
+		if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA)
+			break;
+
+	/*
+	 * set the proper dsi output client
+	 */
+	client = connector->status == connector_status_connected ?
+		OUT_HDMI : OUT_PANEL;
+	if (client != dsi->cur_client) {
+		/* associate bridge and dsi encoder */
+		if (client == OUT_HDMI)
+			encoder->bridge = dsi->bridge;
+		else
+			encoder->bridge = NULL;
+
+		gpiod_set_value_cansleep(dsi->gpio_mux, client);
+		dsi->cur_client = client;
+		/* let the userspace know panel connector status has changed */
+		drm_sysfs_hotplug_event(dev);
+		DRM_INFO("client change to %s\n", client == OUT_HDMI ?
+				 "HDMI" : "panel");
+	}
+
+	mutex_unlock(&dev->mode_config.mutex);
+}
+EXPORT_SYMBOL(dsi_set_output_client);
+
+static void get_dsi_phy_ctrl(struct dw_dsi *dsi,
+							struct mipi_phy_params *phy_ctrl)
+{
+	struct mipi_panel_info *mipi = NULL;
+	struct drm_display_mode *mode = NULL;
+	u32 dphy_req_kHz;
+	int bpp;
+	u32 id = 0;
+	u32 ui = 0;
+	u32 m_pll = 0;
+	u32 n_pll = 0;
+	u32 m_n_fract = 0;
+	u32 m_n_int = 0;
+	u64 lane_clock = 0;
+	u64 vco_div = 1;
+
+	u32 accuracy = 0;
+	u32 unit_tx_byte_clk_hs = 0;
+	u32 clk_post = 0;
+	u32 clk_pre = 0;
+	u32 clk_t_hs_exit = 0;
+	u32 clk_pre_delay = 0;
+	u32 clk_t_hs_prepare = 0;
+	u32 clk_t_lpx = 0;
+	u32 clk_t_hs_zero = 0;
+	u32 clk_t_hs_trial = 0;
+	u32 data_post_delay = 0;
+	u32 data_t_hs_prepare = 0;
+	u32 data_t_hs_zero = 0;
+	u32 data_t_hs_trial = 0;
+	u32 data_t_lpx = 0;
+	u32 clk_pre_delay_reality = 0;
+	u32 clk_t_hs_zero_reality = 0;
+	u32 clk_post_delay_reality = 0;
+	u32 data_t_hs_zero_reality = 0;
+	u32 data_post_delay_reality = 0;
+	u32 data_pre_delay_reality = 0;
+
+	WARN_ON(!phy_ctrl);
+	WARN_ON(!dsi);
+
+	id = dsi->cur_client;
+	mode = &dsi->cur_mode;
+	mipi = &dsi->mipi;
+
+	/*
+	 * count phy params
+	 */
+	bpp = mipi_dsi_pixel_format_to_bpp(dsi->client[id].format);
+	if (bpp < 0)
+		return;
+	if (mode->clock > 80000)
+	    dsi->client[id].lanes = 4;
+	else
+	    dsi->client[id].lanes = 3;
+	if (dsi->client[id].phy_clock)
+		dphy_req_kHz = dsi->client[id].phy_clock;
+	else
+		dphy_req_kHz = mode->clock * bpp / dsi->client[id].lanes;
+
+	lane_clock = dphy_req_kHz / 1000;
+	DRM_INFO("Expected : lane_clock = %llu M\n", lane_clock);
+
+	/************************  PLL parameters config  *********************/
+	/*chip spec :
+		If the output data rate is below 320 Mbps,
+		RG_BNAD_SEL should be set to 1.
+		At this mode a post divider of 1/4 will be applied to VCO.
+	*/
+	if ((320 <= lane_clock) && (lane_clock <= 2500)) {
+		phy_ctrl->rg_band_sel = 0;	/*0x1E[2]*/
+		vco_div = 1;
+	} else if ((80 <= lane_clock) && (lane_clock < 320)) {
+		phy_ctrl->rg_band_sel = 1;
+		vco_div = 4;
+	} else {
+		DRM_ERROR("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 set rg_pll_enswc=1, rg_pll_fbd_s can't be 0*/
+	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 {
+				DRM_ERROR("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 {
+		DRM_ERROR("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;
+	DRM_INFO("Config : lane_clock = %llu\n", lane_clock);
+
+	/*FIXME :*/
+	phy_ctrl->rg_pll_cp = 1;		/*0x16[7:5]*/
+	phy_ctrl->rg_pll_cp_p = 3;		/*0x1E[7:5]*/
+
+	/*test_code_0x14 other parameters config*/
+	phy_ctrl->rg_pll_enbwt = 0;	/*0x14[2]*/
+	phy_ctrl->rg_pll_chp = 0;		/*0x14[1:0]*/
+
+	/*test_code_0x16 other parameters config,  0x16[3:2] reserved*/
+	phy_ctrl->rg_pll_lpf_cs = 0;	/*0x16[4]*/
+	phy_ctrl->rg_pll_refsel = 1;		/*0x16[1:0]*/
+
+	/*test_code_0x1E other parameters config*/
+	phy_ctrl->reload_sel = 1;			/*0x1E[4]*/
+	phy_ctrl->rg_phase_gen_en = 1;	/*0x1E[3]*/
+	phy_ctrl->pll_power_down = 0;		/*0x1E[1]*/
+	phy_ctrl->pll_register_override = 1;	/*0x1E[0]*/
+
+	/*HSTX select VCM VREF*/
+	phy_ctrl->rg_vrefsel_vcm = 0x55;
+	if (mipi->rg_vrefsel_vcm_clk_adjust != 0)
+		phy_ctrl->rg_vrefsel_vcm = (phy_ctrl->rg_vrefsel_vcm & 0x0F) |
+			((mipi->rg_vrefsel_vcm_clk_adjust & 0x0F) << 4);
+
+	if (mipi->rg_vrefsel_vcm_data_adjust != 0)
+		phy_ctrl->rg_vrefsel_vcm = (phy_ctrl->rg_vrefsel_vcm & 0xF0) |
+			(mipi->rg_vrefsel_vcm_data_adjust & 0x0F);
+
+	/*if reload_sel = 1, need to set load_command*/
+	phy_ctrl->load_command = 0x5A;
+
+	/********************  clock/data lane parameters config  ******************/
+	accuracy = 10;
+	ui =  10 * 1000000000UL * accuracy / lane_clock;
+	/*unit of measurement*/
+	unit_tx_byte_clk_hs = 8 * ui;
+
+	/* D-PHY Specification : 60ns + 52*UI <= clk_post*/
+	clk_post = 600 * accuracy + 52 * ui + mipi->clk_post_adjust * ui;
+
+	/* D-PHY Specification : clk_pre >= 8*UI*/
+	clk_pre = 8 * ui + mipi->clk_pre_adjust * ui;
+
+	/* D-PHY Specification : clk_t_hs_exit >= 100ns*/
+	clk_t_hs_exit = 1000 * accuracy + mipi->clk_t_hs_exit_adjust * ui;
+
+	/* clocked by TXBYTECLKHS*/
+	clk_pre_delay = 0 + mipi->clk_pre_delay_adjust * ui;
+
+	/* D-PHY Specification : clk_t_hs_trial >= 60ns*/
+	/* clocked by TXBYTECLKHS*/
+	clk_t_hs_trial = 600 * accuracy + 3 * unit_tx_byte_clk_hs + mipi->clk_t_hs_trial_adjust * ui;
+
+	/* D-PHY Specification : 38ns <= clk_t_hs_prepare <= 95ns*/
+	/* clocked by TXBYTECLKHS*/
+	if (mipi->clk_t_hs_prepare_adjust == 0)
+		mipi->clk_t_hs_prepare_adjust = 43;
+
+	clk_t_hs_prepare = ((380 * accuracy + mipi->clk_t_hs_prepare_adjust * ui) <= (950 * accuracy - 8 * ui)) ?
+		(380 * accuracy + mipi->clk_t_hs_prepare_adjust * ui) : (950 * accuracy - 8 * ui);
+
+	/* clocked by TXBYTECLKHS*/
+	data_post_delay = 0 + mipi->data_post_delay_adjust * ui;
+
+	/* D-PHY Specification : data_t_hs_trial >= max( n*8*UI, 60ns + n*4*UI ), n = 1*/
+	/* clocked by TXBYTECLKHS*/
+	data_t_hs_trial = ((600 * accuracy + 4 * ui) >= (8 * ui) ? (600 * accuracy + 4 * ui) : (8 * ui)) + 8 * ui +
+		3 * unit_tx_byte_clk_hs + mipi->data_t_hs_trial_adjust * ui;
+
+	/* D-PHY Specification : 40ns + 4*UI <= data_t_hs_prepare <= 85ns + 6*UI*/
+	/* clocked by TXBYTECLKHS*/
+	if (mipi->data_t_hs_prepare_adjust == 0)
+		mipi->data_t_hs_prepare_adjust = 35;
+
+	data_t_hs_prepare = ((400  * accuracy + 4 * ui + mipi->data_t_hs_prepare_adjust * ui) <= (850 * accuracy + 6 * ui - 8 * ui)) ?
+		(400  * accuracy + 4 * ui + mipi->data_t_hs_prepare_adjust * ui) : (850 * accuracy + 6 * ui - 8 * ui);
+
+	/* D-PHY chip spec : clk_t_lpx + clk_t_hs_prepare > 200ns*/
+	/* D-PHY Specification : clk_t_lpx >= 50ns*/
+	/* clocked by TXBYTECLKHS*/
+	clk_t_lpx = (((2000 * accuracy - clk_t_hs_prepare) >= 500 * accuracy) ?
+		((2000 * accuracy - clk_t_hs_prepare)) : (500 * accuracy)) +
+		mipi->clk_t_lpx_adjust * ui;
+
+	/* D-PHY Specification : clk_t_hs_zero + clk_t_hs_prepare >= 300 ns*/
+	/* clocked by TXBYTECLKHS*/
+	clk_t_hs_zero = 3000 * accuracy - clk_t_hs_prepare + 3 * unit_tx_byte_clk_hs + mipi->clk_t_hs_zero_adjust * ui;
+
+	/* D-PHY chip spec : data_t_lpx + data_t_hs_prepare > 200ns*/
+	/* D-PHY Specification : data_t_lpx >= 50ns*/
+	/* clocked by TXBYTECLKHS*/
+	data_t_lpx = clk_t_lpx + mipi->data_t_lpx_adjust * ui; /*2000 * accuracy - data_t_hs_prepare;*/
+
+	/* D-PHY Specification : data_t_hs_zero + data_t_hs_prepare >= 145ns + 10*UI*/
+	/* clocked by TXBYTECLKHS*/
+	data_t_hs_zero = 1450 * accuracy + 10 * ui - data_t_hs_prepare +
+		3 * unit_tx_byte_clk_hs + 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) % mipi->max_tx_esc_clk) > 0) ?
+		(phy_ctrl->lane_byte_clk / 2 / mipi->max_tx_esc_clk + 1) :
+		(phy_ctrl->lane_byte_clk / 2 / mipi->max_tx_esc_clk);
+
+	DRM_INFO("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);
+	DRM_INFO("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 void dw_dsi_set_mode(struct dw_dsi *dsi, enum dsi_work_mode mode)
+{
+	struct dsi_hw_ctx *ctx = dsi->ctx;
+	void __iomem *base = ctx->base;
+
+	writel(RESET, base + PWR_UP);
+	writel(mode, base + MODE_CFG);
+	writel(POWERUP, base + PWR_UP);
+}
+
+static void dsi_set_burst_mode(void __iomem *base, unsigned long flags)
+{
+	u32 val;
+	u32 mode_mask = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+		MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
+	u32 non_burst_sync_pulse = MIPI_DSI_MODE_VIDEO |
+		MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
+	u32 non_burst_sync_event = MIPI_DSI_MODE_VIDEO;
+
+	/*
+	 * choose video mode type
+	 */
+	if ((flags & mode_mask) == non_burst_sync_pulse)
+		val = DSI_NON_BURST_SYNC_PULSES;
+	else if ((flags & mode_mask) == non_burst_sync_event)
+		val = DSI_NON_BURST_SYNC_EVENTS;
+	else
+		val = DSI_BURST_SYNC_PULSES_1;
+
+	set_reg(base + MIPIDSI_VID_MODE_CFG_OFFSET, val, 2, 0);
+}
+
+/*
+ * dsi phy reg write function
+ */
+static void dsi_phy_tst_set(void __iomem *base, u32 reg, u32 val)
+{
+	u32 reg_write = 0x10000 + reg;
+
+	/*
+	 * latch reg first
+	 */
+	writel(reg_write, base + MIPIDSI_PHY_TST_CTRL1_OFFSET);
+	writel(0x02, base + MIPIDSI_PHY_TST_CTRL0_OFFSET);
+	writel(0x00, base + MIPIDSI_PHY_TST_CTRL0_OFFSET);
+
+	/*
+	 * then latch value
+	 */
+	writel(val, base + MIPIDSI_PHY_TST_CTRL1_OFFSET);
+	writel(0x02, base + MIPIDSI_PHY_TST_CTRL0_OFFSET);
+	writel(0x00, base + MIPIDSI_PHY_TST_CTRL0_OFFSET);
+}
+
+static void dsi_mipi_init(struct dw_dsi *dsi, char __iomem *mipi_dsi_base)
+{
+	u32 hline_time = 0;
+	u32 hsa_time = 0;
+	u32 hbp_time = 0;
+	u64 pixel_clk = 0;
+	u32 i = 0;
+	u32 id = 0;
+	unsigned long dw_jiffies = 0;
+	u32 tmp = 0;
+	bool is_ready = false;
+	struct mipi_panel_info *mipi = NULL;
+	dss_rect_t rect;
+	u32 cmp_stopstate_val = 0;
+	u32 lanes;
+
+	WARN_ON(!dsi);
+	WARN_ON(!mipi_dsi_base);
+
+	id = dsi->cur_client;
+	mipi = &dsi->mipi;
+
+	if (mipi->max_tx_esc_clk == 0) {
+		DRM_INFO("max_tx_esc_clk is invalid!");
+		mipi->max_tx_esc_clk = DEFAULT_MAX_TX_ESC_CLK;
+	}
+
+	memset(&dsi->phy, 0, sizeof(struct mipi_phy_params));
+	get_dsi_phy_ctrl(dsi, &dsi->phy);
+
+	rect.x = 0;
+	rect.y = 0;
+	rect.w = dsi->cur_mode.hdisplay;
+	rect.h = dsi->cur_mode.vdisplay;
+	lanes = dsi->client[id].lanes - 1;
+	/***************Configure the DPHY start**************/
+
+	set_reg(mipi_dsi_base + MIPIDSI_PHY_IF_CFG_OFFSET, lanes, 2, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_CLKMGR_CFG_OFFSET, dsi->phy.clk_division, 8, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_CLKMGR_CFG_OFFSET, dsi->phy.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);
+
+	/* physical configuration PLL I*/
+	dsi_phy_tst_set(mipi_dsi_base, 0x14,
+		(dsi->phy.rg_pll_fbd_s << 4) + (dsi->phy.rg_pll_enswc << 3) +
+		(dsi->phy.rg_pll_enbwt << 2) + dsi->phy.rg_pll_chp);
+
+	/* physical configuration PLL II, M*/
+	dsi_phy_tst_set(mipi_dsi_base, 0x15, dsi->phy.rg_pll_fbd_p);
+
+	/* physical configuration PLL III*/
+	dsi_phy_tst_set(mipi_dsi_base, 0x16,
+		(dsi->phy.rg_pll_cp << 5) + (dsi->phy.rg_pll_lpf_cs << 4) +
+		dsi->phy.rg_pll_refsel);
+
+	/* physical configuration PLL IV, N*/
+	dsi_phy_tst_set(mipi_dsi_base, 0x17, dsi->phy.rg_pll_pre_p);
+
+	/* sets the analog characteristic of V reference in D-PHY TX*/
+	dsi_phy_tst_set(mipi_dsi_base, 0x1D, dsi->phy.rg_vrefsel_vcm);
+
+	/* MISC AFE Configuration*/
+	dsi_phy_tst_set(mipi_dsi_base, 0x1E,
+		(dsi->phy.rg_pll_cp_p << 5) + (dsi->phy.reload_sel << 4) +
+		(dsi->phy.rg_phase_gen_en << 3) + (dsi->phy.rg_band_sel << 2) +
+		(dsi->phy.pll_power_down << 1) + dsi->phy.pll_register_override);
+
+	/*reload_command*/
+	dsi_phy_tst_set(mipi_dsi_base, 0x1F, dsi->phy.load_command);
+
+	/* pre_delay of clock lane request setting*/
+	dsi_phy_tst_set(mipi_dsi_base, 0x20, DSS_REDUCE(dsi->phy.clk_pre_delay));
+
+	/* post_delay of clock lane request setting*/
+	dsi_phy_tst_set(mipi_dsi_base, 0x21, DSS_REDUCE(dsi->phy.clk_post_delay));
+
+	/* clock lane timing ctrl - t_lpx*/
+	dsi_phy_tst_set(mipi_dsi_base, 0x22, DSS_REDUCE(dsi->phy.clk_t_lpx));
+
+	/* clock lane timing ctrl - t_hs_prepare*/
+	dsi_phy_tst_set(mipi_dsi_base, 0x23, DSS_REDUCE(dsi->phy.clk_t_hs_prepare));
+
+	/* clock lane timing ctrl - t_hs_zero*/
+	dsi_phy_tst_set(mipi_dsi_base, 0x24, DSS_REDUCE(dsi->phy.clk_t_hs_zero));
+
+	/* clock lane timing ctrl - t_hs_trial*/
+	dsi_phy_tst_set(mipi_dsi_base, 0x25, dsi->phy.clk_t_hs_trial);
+
+	for (i = 0; i <= lanes; i++) {
+		/* data lane pre_delay*/
+		tmp = 0x30 + (i << 4);
+		dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_pre_delay));
+
+		/*data lane post_delay*/
+		tmp = 0x31 + (i << 4);
+		dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_post_delay));
+
+		/* data lane timing ctrl - t_lpx*/
+		dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_t_lpx));
+
+		/* data lane timing ctrl - t_hs_prepare*/
+		tmp = 0x33 + (i << 4);
+		dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_t_hs_prepare));
+
+		/* data lane timing ctrl - t_hs_zero*/
+		tmp = 0x34 + (i << 4);
+		dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_t_hs_zero));
+
+		/* data lane timing ctrl - t_hs_trial*/
+		tmp = 0x35 + (i << 4);
+		dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_t_hs_trial));
+
+		/* data lane timing ctrl - t_ta_go*/
+		tmp = 0x36 + (i << 4);
+		dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_t_ta_go));
+
+		/* data lane timing ctrl - t_ta_get*/
+		tmp = 0x37 + (i << 4);
+		dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_t_ta_get));
+	}
+
+	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) {
+		DRM_INFO("phylock is not ready!MIPIDSI_PHY_STATUS_OFFSET=0x%x.\n",
+			tmp);
+	}
+
+	if (lanes >= DSI_4_LANES)
+		cmp_stopstate_val = (BIT(4) | BIT(7) | BIT(9) | BIT(11));
+	else if (lanes >= DSI_3_LANES)
+		cmp_stopstate_val = (BIT(4) | BIT(7) | BIT(9));
+	else if (lanes >= 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) {
+		DRM_INFO("phystopstateclklane is not ready! MIPIDSI_PHY_STATUS_OFFSET=0x%x.\n",
+			tmp);
+	}
+
+	/*************************Configure the DPHY end*************************/
+
+	/* phy_stop_wait_time*/
+	set_reg(mipi_dsi_base + MIPIDSI_PHY_IF_CFG_OFFSET, dsi->phy.phy_stop_wait_time, 8, 8);
+
+	/*--------------configuring the DPI packet transmission----------------*/
+	/*
+	** 2. Configure the DPI Interface:
+	** This defines how the DPI interface interacts with the controller.
+	*/
+	set_reg(mipi_dsi_base + MIPIDSI_DPI_VCID_OFFSET, mipi->vc, 2, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_DPI_COLOR_CODING_OFFSET, mipi->color_mode, 4, 0);
+
+	set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET, dsi->ldi.data_en_plr, 1, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET, dsi->ldi.vsync_plr, 1, 1);
+	set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET, dsi->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.
+	*/
+	/* video mode: low power mode*/
+	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); */
+
+	/* TODO: fix blank display bug when set backlight*/
+	set_reg(mipi_dsi_base + MIPIDSI_DPI_LP_CMD_TIM_OFFSET, 0x4, 8, 16);
+	/* video mode: send read cmd by lp mode*/
+	set_reg(mipi_dsi_base + MIPIDSI_VID_MODE_CFG_OFFSET, 0x1, 1, 15);
+
+	set_reg(mipi_dsi_base + MIPIDSI_VID_PKT_SIZE_OFFSET, rect.w, 14, 0);
+
+	/* burst mode*/
+	dsi_set_burst_mode(mipi_dsi_base, dsi->client[id].mode_flags);
+	/* for dsi read, BTA enable*/
+	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 = dsi->cur_mode.clock * 1000;
+	/*htot = dsi->cur_mode.htotal;*/
+	/*vtot = dsi->cur_mode.vtotal;*/
+	dsi->ldi.h_front_porch = dsi->cur_mode.hsync_start - dsi->cur_mode.hdisplay;
+	dsi->ldi.h_back_porch = dsi->cur_mode.htotal - dsi->cur_mode.hsync_end;
+	dsi->ldi.h_pulse_width = dsi->cur_mode.hsync_end - dsi->cur_mode.hsync_start;
+	dsi->ldi.v_front_porch = dsi->cur_mode.vsync_start - dsi->cur_mode.vdisplay;
+	dsi->ldi.v_back_porch = dsi->cur_mode.vtotal - dsi->cur_mode.vsync_end;
+	dsi->ldi.v_pulse_width = dsi->cur_mode.vsync_end - dsi->cur_mode.vsync_start;
+	if (dsi->ldi.v_pulse_width > 15) {
+		DRM_DEBUG_DRIVER("vsw exceeded 15\n");
+		dsi->ldi.v_pulse_width = 15;
+	}
+	hsa_time = dsi->ldi.h_pulse_width * dsi->phy.lane_byte_clk / pixel_clk;
+	hbp_time = dsi->ldi.h_back_porch * dsi->phy.lane_byte_clk / pixel_clk;
+	hline_time = ROUND1((dsi->ldi.h_pulse_width + dsi->ldi.h_back_porch +
+		rect.w + dsi->ldi.h_front_porch) * dsi->phy.lane_byte_clk, pixel_clk);
+
+	DRM_INFO("hsa_time=%d, hbp_time=%d, hline_time=%d\n",
+	    hsa_time, hbp_time, hline_time);
+	DRM_INFO("lane_byte_clk=%llu, pixel_clk=%llu\n",
+	    dsi->phy.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);
+
+	/* Define the Vertical line configuration*/
+	set_reg(mipi_dsi_base + MIPIDSI_VID_VSA_LINES_OFFSET, dsi->ldi.v_pulse_width, 10, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_VID_VBP_LINES_OFFSET, dsi->ldi.v_back_porch, 10, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_VID_VFP_LINES_OFFSET, dsi->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);
+
+	/* Configure core's phy parameters*/
+	set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_LPCLK_CFG_OFFSET, dsi->phy.clk_lane_lp2hs_time, 10, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_LPCLK_CFG_OFFSET, dsi->phy.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, dsi->phy.data_lane_lp2hs_time, 10, 0);
+	set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_CFG_OFFSET, dsi->phy.data_lane_hs2lp_time, 10, 16);
+
+	/* Waking up Core*/
+	set_reg(mipi_dsi_base + MIPIDSI_PWR_UP_OFFSET, 0x1, 1, 0);
+}
+
+static void dsi_encoder_disable(struct drm_encoder *encoder)
+{
+	struct dw_dsi *dsi = encoder_to_dsi(encoder);
+	struct dsi_hw_ctx *ctx = dsi->ctx;
+	void __iomem *base = ctx->base;
+
+	if (!dsi->enable)
+		return;
+
+	dw_dsi_set_mode(dsi, DSI_COMMAND_MODE);
+	/* turn off panel's backlight */
+	if (dsi->panel && drm_panel_disable(dsi->panel))
+		DRM_ERROR("failed to disable panel\n");
+
+	/* turn off panel */
+	if (dsi->panel && drm_panel_unprepare(dsi->panel))
+		DRM_ERROR("failed to unprepare panel\n");
+
+	writel(0, base + PWR_UP);
+	writel(0, base + LPCLK_CTRL);
+	writel(0, base + PHY_RSTZ);
+	clk_disable_unprepare(ctx->dss_dphy0_ref_clk);
+	clk_disable_unprepare(ctx->dss_dphy0_cfg_clk);
+	clk_disable_unprepare(ctx->dss_pclk_dsi0_clk);
+
+	dsi->enable = false;
+}
+
+static int mipi_dsi_on_sub1(struct dw_dsi *dsi, char __iomem *mipi_dsi_base)
+{
+	WARN_ON(!mipi_dsi_base);
+
+	/* mipi init */
+	dsi_mipi_init(dsi, mipi_dsi_base);
+	DRM_INFO("dsi_mipi_init ok\n");
+	/* 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 dw_dsi *dsi, char __iomem *mipi_dsi_base)
+{
+	WARN_ON(!mipi_dsi_base);
+
+	/* switch to video mode */
+	set_reg(mipi_dsi_base + MIPIDSI_MODE_CFG_OFFSET, 0x0, 1, 0);
+
+	/* enable EOTP TX */
+	set_reg(mipi_dsi_base + MIPIDSI_PCKHDL_CFG_OFFSET, 0x1, 1, 0);
+
+	/* enable generate High Speed clock, continue clock */
+	set_reg(mipi_dsi_base + MIPIDSI_LPCLK_CTRL_OFFSET, 0x1, 2, 0);
+
+	return 0;
+}
+
+static void dsi_encoder_enable(struct drm_encoder *encoder)
+{
+	struct dw_dsi *dsi = encoder_to_dsi(encoder);
+	struct dsi_hw_ctx *ctx = dsi->ctx;
+	int ret;
+
+	if (dsi->enable)
+		return;
+
+	ret = clk_prepare_enable(ctx->dss_dphy0_ref_clk);
+	if (ret) {
+		DRM_ERROR("fail to enable dss_dphy0_ref_clk: %d\n", ret);
+		return;
+	}
+
+	ret = clk_prepare_enable(ctx->dss_dphy0_cfg_clk);
+	if (ret) {
+		DRM_ERROR("fail to enable dss_dphy0_cfg_clk: %d\n", ret);
+		return;
+	}
+
+	ret = clk_prepare_enable(ctx->dss_pclk_dsi0_clk);
+	if (ret) {
+		DRM_ERROR("fail to enable dss_pclk_dsi0_clk: %d\n", ret);
+		return;
+	}
+
+	mipi_dsi_on_sub1(dsi, ctx->base);
+
+	mipi_dsi_on_sub2(dsi, ctx->base);
+
+	/* turn on panel */
+	if (dsi->panel && drm_panel_prepare(dsi->panel))
+		DRM_ERROR("failed to prepare panel\n");
+
+	/*dw_dsi_set_mode(dsi, DSI_VIDEO_MODE);*/
+
+	/* turn on panel's back light */
+	if (dsi->panel && drm_panel_enable(dsi->panel))
+		DRM_ERROR("failed to enable panel\n");
+
+	dsi->enable = true;
+}
+
+static void dsi_encoder_mode_set(struct drm_encoder *encoder,
+				 struct drm_display_mode *mode,
+				 struct drm_display_mode *adj_mode)
+{
+	struct dw_dsi *dsi = encoder_to_dsi(encoder);
+
+	drm_mode_copy(&dsi->cur_mode, adj_mode);
+}
+
+static int dsi_encoder_atomic_check(struct drm_encoder *encoder,
+				    struct drm_crtc_state *crtc_state,
+				    struct drm_connector_state *conn_state)
+{
+	/* do nothing */
+	return 0;
+}
+
+static const struct drm_encoder_helper_funcs dw_encoder_helper_funcs = {
+	.atomic_check	= dsi_encoder_atomic_check,
+	.mode_set	= dsi_encoder_mode_set,
+	.enable		= dsi_encoder_enable,
+	.disable	= dsi_encoder_disable
+};
+
+static const struct drm_encoder_funcs dw_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+static int dw_drm_encoder_init(struct device *dev,
+			       struct drm_device *drm_dev,
+			       struct drm_encoder *encoder)
+{
+	int ret;
+	u32 crtc_mask = drm_of_find_possible_crtcs(drm_dev, dev->of_node);
+
+	if (!crtc_mask) {
+		DRM_ERROR("failed to find crtc mask\n");
+		return -EINVAL;
+	}
+
+	encoder->possible_crtcs = crtc_mask;
+	ret = drm_encoder_init(drm_dev, encoder, &dw_encoder_funcs,
+			       DRM_MODE_ENCODER_DSI);
+	if (ret) {
+		DRM_ERROR("failed to init dsi encoder\n");
+		return ret;
+	}
+
+	drm_encoder_helper_add(encoder, &dw_encoder_helper_funcs);
+
+	return 0;
+}
+
+static int dsi_host_attach(struct mipi_dsi_host *host,
+			   struct mipi_dsi_device *mdsi)
+{
+	struct dw_dsi *dsi = host_to_dsi(host);
+	u32 id = mdsi->channel >= 1 ? OUT_PANEL : OUT_HDMI;
+
+	if (mdsi->lanes < 1 || mdsi->lanes > 4) {
+		DRM_ERROR("dsi device params invalid\n");
+		return -EINVAL;
+	}
+
+	dsi->client[id].lanes = mdsi->lanes;
+	dsi->client[id].format = mdsi->format;
+	dsi->client[id].mode_flags = mdsi->mode_flags;
+	dsi->client[id].phy_clock = mdsi->phy_clock;
+
+	DRM_INFO("host attach, client name=[%s], id=%d\n", mdsi->name, id);
+
+	return 0;
+}
+
+static int dsi_host_detach(struct mipi_dsi_host *host,
+			   struct mipi_dsi_device *mdsi)
+{
+	/* do nothing */
+	return 0;
+}
+
+static int dsi_gen_pkt_hdr_write(void __iomem *base, u32 val)
+{
+	u32 status;
+	int ret;
+
+	ret = readx_poll_timeout(readl, base + CMD_PKT_STATUS, status,
+				 !(status & GEN_CMD_FULL), 1000,
+				 CMD_PKT_STATUS_TIMEOUT_US);
+	if (ret < 0) {
+		DRM_ERROR("failed to get available command FIFO\n");
+		return ret;
+	}
+
+	writel(val, base + GEN_HDR);
+
+	ret = readx_poll_timeout(readl, base + CMD_PKT_STATUS, status,
+				 status & (GEN_CMD_EMPTY | GEN_PLD_W_EMPTY),
+				 1000, CMD_PKT_STATUS_TIMEOUT_US);
+	if (ret < 0) {
+		DRM_ERROR("failed to write command FIFO\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int dsi_dcs_short_write(void __iomem *base,
+			       const struct mipi_dsi_msg *msg)
+{
+	const u16 *tx_buf = msg->tx_buf;
+	u32 val = GEN_HDATA(*tx_buf) | GEN_HTYPE(msg->type);
+
+	if (msg->tx_len > 2) {
+		DRM_ERROR("too long tx buf length %zu for short write\n",
+			  msg->tx_len);
+		return -EINVAL;
+	}
+
+	return dsi_gen_pkt_hdr_write(base, val);
+}
+
+static int dsi_dcs_long_write(void __iomem *base,
+			      const struct mipi_dsi_msg *msg)
+{
+	const u32 *tx_buf = msg->tx_buf;
+	int len = msg->tx_len, pld_data_bytes = sizeof(*tx_buf), ret;
+	u32 val = GEN_HDATA(msg->tx_len) | GEN_HTYPE(msg->type);
+	u32 remainder = 0;
+	u32 status;
+
+	if (msg->tx_len < 3) {
+		DRM_ERROR("wrong tx buf length %zu for long write\n",
+			  msg->tx_len);
+		return -EINVAL;
+	}
+
+	while (DIV_ROUND_UP(len, pld_data_bytes)) {
+		if (len < pld_data_bytes) {
+			memcpy(&remainder, tx_buf, len);
+			writel(remainder, base + GEN_PLD_DATA);
+			len = 0;
+		} else {
+			writel(*tx_buf, base + GEN_PLD_DATA);
+			tx_buf++;
+			len -= pld_data_bytes;
+		}
+
+		ret = readx_poll_timeout(readl, base + CMD_PKT_STATUS,
+					 status, !(status & GEN_PLD_W_FULL), 1000,
+					 CMD_PKT_STATUS_TIMEOUT_US);
+		if (ret < 0) {
+			DRM_ERROR("failed to get available write payload FIFO\n");
+			return ret;
+		}
+	}
+
+	return dsi_gen_pkt_hdr_write(base, val);
+}
+
+static ssize_t dsi_host_transfer(struct mipi_dsi_host *host,
+				    const struct mipi_dsi_msg *msg)
+{
+	struct dw_dsi *dsi = host_to_dsi(host);
+	struct dsi_hw_ctx *ctx = dsi->ctx;
+	void __iomem *base = ctx->base;
+	int ret;
+
+	switch (msg->type) {
+	case MIPI_DSI_DCS_SHORT_WRITE:
+	case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
+	case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE:
+		ret = dsi_dcs_short_write(base, msg);
+		break;
+	case MIPI_DSI_DCS_LONG_WRITE:
+		ret = dsi_dcs_long_write(base, msg);
+		break;
+	default:
+		DRM_ERROR("unsupported message type\n");
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static const struct mipi_dsi_host_ops dsi_host_ops = {
+	.attach = dsi_host_attach,
+	.detach = dsi_host_detach,
+	.transfer = dsi_host_transfer,
+};
+
+static int dsi_host_init(struct device *dev, struct dw_dsi *dsi)
+{
+	struct mipi_dsi_host *host = &dsi->host;
+	struct mipi_panel_info *mipi = &dsi->mipi;
+	int ret;
+
+	host->dev = dev;
+	host->ops = &dsi_host_ops;
+
+	mipi->max_tx_esc_clk = 10;
+	mipi->vc = 0;
+	mipi->color_mode = DSI_24BITS_1;
+	mipi->clk_post_adjust = 120;
+	mipi->clk_pre_adjust= 0;
+	mipi->clk_t_hs_prepare_adjust= 0;
+	mipi->clk_t_lpx_adjust= 0;
+	mipi->clk_t_hs_trial_adjust= 0;
+	mipi->clk_t_hs_exit_adjust= 0;
+	mipi->clk_t_hs_zero_adjust= 0;
+
+	dsi->ldi.data_en_plr = 0;
+	dsi->ldi.vsync_plr = 0;
+	dsi->ldi.hsync_plr = 0;
+
+	ret = mipi_dsi_host_register(host);
+	if (ret) {
+		DRM_ERROR("failed to register dsi host\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi)
+{
+	struct drm_encoder *encoder = &dsi->encoder;
+	struct drm_bridge *bridge = dsi->bridge;
+	int ret;
+
+	/* associate the bridge to dsi encoder */
+	bridge->encoder = encoder;
+
+	ret = drm_bridge_attach(dev, bridge);
+	if (ret) {
+		DRM_ERROR("failed to attach external bridge\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int dsi_connector_get_modes(struct drm_connector *connector)
+{
+	struct dw_dsi *dsi = connector_to_dsi(connector);
+
+	return drm_panel_get_modes(dsi->panel);
+}
+
+static enum drm_mode_status
+dsi_connector_mode_valid(struct drm_connector *connector,
+			 struct drm_display_mode *mode)
+{
+	enum drm_mode_status mode_status = MODE_OK;
+
+	return mode_status;
+}
+
+static struct drm_encoder *
+dsi_connector_best_encoder(struct drm_connector *connector)
+{
+	struct dw_dsi *dsi = connector_to_dsi(connector);
+
+	return &dsi->encoder;
+}
+
+static struct drm_connector_helper_funcs dsi_connector_helper_funcs = {
+	.get_modes = dsi_connector_get_modes,
+	.mode_valid = dsi_connector_mode_valid,
+	.best_encoder = dsi_connector_best_encoder,
+};
+
+static enum drm_connector_status
+dsi_connector_detect(struct drm_connector *connector, bool force)
+{
+	struct dw_dsi *dsi = connector_to_dsi(connector);
+	enum drm_connector_status status;
+
+	status = dsi->cur_client == OUT_PANEL ?	connector_status_connected :
+		connector_status_disconnected;
+
+	return status;
+}
+
+static void dsi_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+}
+
+static struct drm_connector_funcs dsi_atomic_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.detect = dsi_connector_detect,
+	.destroy = dsi_connector_destroy,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int dsi_connector_init(struct drm_device *dev, struct dw_dsi *dsi)
+{
+	struct drm_encoder *encoder = &dsi->encoder;
+	struct drm_connector *connector = &dsi->connector;
+	int ret;
+
+	connector->polled = DRM_CONNECTOR_POLL_HPD;
+	drm_connector_helper_add(connector,
+				 &dsi_connector_helper_funcs);
+
+	ret = drm_connector_init(dev, &dsi->connector,
+				 &dsi_atomic_connector_funcs,
+				 DRM_MODE_CONNECTOR_DSI);
+	if (ret)
+		return ret;
+
+	ret = drm_mode_connector_attach_encoder(connector, encoder);
+	if (ret)
+		return ret;
+
+	ret = drm_panel_attach(dsi->panel, connector);
+	if (ret)
+		return ret;
+
+	DRM_INFO("connector init\n");
+	return 0;
+}
+static int dsi_bind(struct device *dev, struct device *master, void *data)
+{
+	struct dsi_data *ddata = dev_get_drvdata(dev);
+	struct dw_dsi *dsi = &ddata->dsi;
+	struct drm_device *drm_dev = data;
+	int ret;
+
+	ret = dw_drm_encoder_init(dev, drm_dev, &dsi->encoder);
+	if (ret)
+		return ret;
+
+	if (dsi->bridge) {
+		ret = dsi_bridge_init(drm_dev, dsi);
+		if (ret)
+			return ret;
+	}
+
+	if (dsi->panel) {
+		ret = dsi_connector_init(drm_dev, dsi);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void dsi_unbind(struct device *dev, struct device *master, void *data)
+{
+	/* do nothing */
+}
+
+static const struct component_ops dsi_ops = {
+	.bind	= dsi_bind,
+	.unbind	= dsi_unbind,
+};
+
+static int dsi_parse_bridge_endpoint(struct dw_dsi *dsi,
+				     struct device_node *endpoint)
+{
+	struct device_node *bridge_node;
+	struct drm_bridge *bridge;
+
+	bridge_node = of_graph_get_remote_port_parent(endpoint);
+	if (!bridge_node) {
+		DRM_ERROR("no valid bridge node\n");
+		return -ENODEV;
+	}
+	of_node_put(bridge_node);
+
+	bridge = of_drm_find_bridge(bridge_node);
+	if (!bridge) {
+		DRM_INFO("wait for external HDMI bridge driver.\n");
+		return -EPROBE_DEFER;
+	}
+	dsi->bridge = bridge;
+
+	return 0;
+}
+
+static int dsi_parse_panel_endpoint(struct dw_dsi *dsi,
+				    struct device_node *endpoint)
+{
+	struct device_node *panel_node;
+	struct drm_panel *panel;
+
+	panel_node = of_graph_get_remote_port_parent(endpoint);
+	if (!panel_node) {
+		DRM_ERROR("no valid panel node\n");
+		return -ENODEV;
+	}
+	of_node_put(panel_node);
+
+	panel = of_drm_find_panel(panel_node);
+	if (!panel) {
+		DRM_DEBUG_DRIVER("skip this panel endpoint.\n");
+		return 0;
+	}
+	dsi->panel = panel;
+
+	return 0;
+}
+
+static int dsi_parse_endpoint(struct dw_dsi *dsi,
+			      struct device_node *np,
+			      enum dsi_output_client client)
+{
+	struct device_node *ep_node;
+	struct of_endpoint ep;
+	int ret = 0;
+
+	if (client == OUT_MAX)
+		return -EINVAL;
+
+	for_each_endpoint_of_node(np, ep_node) {
+		ret = of_graph_parse_endpoint(ep_node, &ep);
+		if (ret) {
+			of_node_put(ep_node);
+			return ret;
+		}
+
+		/* skip dsi input port, port == 0 is input port */
+		if (ep.port == 0)
+			continue;
+
+		/* parse bridge endpoint */
+		if (client == OUT_HDMI) {
+			if (ep.id == 0) {
+				ret = dsi_parse_bridge_endpoint(dsi, ep_node);
+				if (dsi->bridge)
+					break;
+			}
+		} else { /* parse panel endpoint */
+			if (ep.id > 0) {
+				ret = dsi_parse_panel_endpoint(dsi, ep_node);
+				if (dsi->panel)
+					break;
+			}
+		}
+
+		if (ret) {
+			of_node_put(ep_node);
+			return ret;
+		}
+	}
+
+	if (!dsi->bridge && !dsi->panel) {
+		DRM_ERROR("at least one bridge or panel node is required\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi)
+{
+	struct dsi_hw_ctx *ctx = dsi->ctx;
+	int ret = 0;
+	struct device_node *np = NULL;
+
+	np = of_find_compatible_node(NULL, NULL, DTS_COMP_DSI_NAME);
+	if (!np) {
+			DRM_ERROR("NOT FOUND device node %s!\n",
+				    DTS_COMP_DSI_NAME);
+			return -ENXIO;
+	}
+
+	ctx->base = of_iomap(np, 0);
+	if (!(ctx->base)) {
+			DRM_ERROR ("failed to get base resource.\n");
+			return -ENXIO;
+	}
+
+	ctx->peri_crg_base = of_iomap(np, 1);
+	if (!(ctx->peri_crg_base)) {
+			DRM_ERROR ("failed to get peri_crg_base resource.\n");
+			return -ENXIO;
+	}
+
+	dsi->gpio_mux = devm_gpiod_get(&pdev->dev, "mux", GPIOD_OUT_HIGH);
+	if (IS_ERR(dsi->gpio_mux))
+		return PTR_ERR(dsi->gpio_mux);
+	/* set dsi default output to panel */
+	dsi->cur_client = OUT_PANEL;
+
+	/*dis-reset*/
+	/*ip_reset_dis_dsi0, ip_reset_dis_dsi1*/
+	outp32(ctx->peri_crg_base + PERRSTDIS3, 0x30000000);
+
+	ctx->dss_dphy0_ref_clk = devm_clk_get(&pdev->dev, "clk_txdphy0_ref");
+	if (IS_ERR(ctx->dss_dphy0_ref_clk)) {
+		DRM_ERROR("failed to get dss_dphy0_ref_clk clock\n");
+		return PTR_ERR(ctx->dss_dphy0_ref_clk);
+	}
+
+	ret = clk_set_rate(ctx->dss_dphy0_ref_clk, DEFAULT_MIPI_CLK_RATE);
+	if (ret < 0) {
+		DRM_ERROR("dss_dphy0_ref_clk clk_set_rate(%lu) failed, error=%d!\n",
+			DEFAULT_MIPI_CLK_RATE, ret);
+		return -EINVAL;
+	}
+
+	DRM_DEBUG("dss_dphy0_ref_clk:[%lu]->[%lu].\n",
+		DEFAULT_MIPI_CLK_RATE, clk_get_rate(ctx->dss_dphy0_ref_clk));
+
+	ctx->dss_dphy0_cfg_clk = devm_clk_get(&pdev->dev, "clk_txdphy0_cfg");
+	if (IS_ERR(ctx->dss_dphy0_cfg_clk)) {
+		DRM_ERROR("failed to get dss_dphy0_cfg_clk clock\n");
+		return PTR_ERR(ctx->dss_dphy0_cfg_clk);
+	}
+
+	ret = clk_set_rate(ctx->dss_dphy0_cfg_clk, DEFAULT_MIPI_CLK_RATE);
+	if (ret < 0) {
+		DRM_ERROR("dss_dphy0_cfg_clk clk_set_rate(%lu) failed, error=%d!\n",
+			DEFAULT_MIPI_CLK_RATE, ret);
+		return -EINVAL;
+	}
+
+	DRM_DEBUG("dss_dphy0_cfg_clk:[%lu]->[%lu].\n",
+		DEFAULT_MIPI_CLK_RATE, clk_get_rate(ctx->dss_dphy0_cfg_clk));
+
+	ctx->dss_pclk_dsi0_clk = devm_clk_get(&pdev->dev, "pclk_dsi0");
+	if (IS_ERR(ctx->dss_pclk_dsi0_clk)) {
+		DRM_ERROR("failed to get dss_pclk_dsi0_clk clock\n");
+		return PTR_ERR(ctx->dss_pclk_dsi0_clk);
+	}
+
+	return 0;
+}
+
+static int dsi_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct device *dev = &pdev->dev;
+	struct dsi_data *data;
+	struct dw_dsi *dsi;
+	struct dsi_hw_ctx *ctx;
+	int ret;
+
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		DRM_ERROR("failed to allocate dsi data.\n");
+		return -ENOMEM;
+	}
+	dsi = &data->dsi;
+	ctx = &data->ctx;
+	dsi->ctx = ctx;
+
+	/* parse HDMI bridge endpoint */
+	ret = dsi_parse_endpoint(dsi, np, OUT_HDMI);
+	if (ret)
+		return ret;
+
+	ret = dsi_host_init(dev, dsi);
+	if (ret)
+		return ret;
+
+	/* parse panel endpoint */
+	ret = dsi_parse_endpoint(dsi, np, OUT_PANEL);
+	if (ret)
+		goto err_host_unregister;
+
+	ret = dsi_parse_dt(pdev, dsi);
+	if (ret)
+		goto err_host_unregister;
+
+	platform_set_drvdata(pdev, data);
+
+	ret = component_add(dev, &dsi_ops);
+	if (ret)
+		goto err_host_unregister;
+
+	return 0;
+
+err_host_unregister:
+	mipi_dsi_host_unregister(&dsi->host);
+	return ret;
+}
+
+static int dsi_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &dsi_ops);
+
+	return 0;
+}
+
+static const struct of_device_id dsi_of_match[] = {
+	{.compatible = "hisilicon,hi3660-dsi"},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, dsi_of_match);
+
+static struct platform_driver dsi_driver = {
+	.probe = dsi_probe,
+	.remove = dsi_remove,
+	.driver = {
+		.name = "dw-dsi",
+		.of_match_table = dsi_of_match,
+	},
+};
+
+module_platform_driver(dsi_driver);
+
+MODULE_DESCRIPTION("DesignWare MIPI DSI Host Controller v1.02 driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/hikey9xx/gpu/dw_dsi_reg.h b/drivers/staging/hikey9xx/gpu/dw_dsi_reg.h
new file mode 100644
index 000000000000..00fac1f35265
--- /dev/null
+++ b/drivers/staging/hikey9xx/gpu/dw_dsi_reg.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2016 Linaro Limited.
+ * Copyright (c) 2014-2016 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __DW_DSI_REG_H__
+#define __DW_DSI_REG_H__
+
+#define MASK(x)				(BIT(x) - 1)
+#define DEFAULT_MAX_TX_ESC_CLK	(10 * 1000000UL)
+/*
+ * regs
+ */
+#define PWR_UP                  0x04  /* Core power-up */
+#define RESET                   0
+#define POWERUP                 BIT(0)
+#define PHY_IF_CFG              0xA4  /* D-PHY interface configuration */
+#define CLKMGR_CFG              0x08  /* the internal clock dividers */
+#define PHY_RSTZ                0xA0  /* D-PHY reset control */
+#define PHY_ENABLECLK           BIT(2)
+#define PHY_UNRSTZ              BIT(1)
+#define PHY_UNSHUTDOWNZ         BIT(0)
+#define PHY_TST_CTRL0           0xB4  /* D-PHY test interface control 0 */
+#define PHY_TST_CTRL1           0xB8  /* D-PHY test interface control 1 */
+#define CLK_TLPX                0x10
+#define CLK_THS_PREPARE         0x11
+#define CLK_THS_ZERO            0x12
+#define CLK_THS_TRAIL           0x13
+#define CLK_TWAKEUP             0x14
+#define DATA_TLPX(x)            (0x20 + ((x) << 4))
+#define DATA_THS_PREPARE(x)     (0x21 + ((x) << 4))
+#define DATA_THS_ZERO(x)        (0x22 + ((x) << 4))
+#define DATA_THS_TRAIL(x)       (0x23 + ((x) << 4))
+#define DATA_TTA_GO(x)          (0x24 + ((x) << 4))
+#define DATA_TTA_GET(x)         (0x25 + ((x) << 4))
+#define DATA_TWAKEUP(x)         (0x26 + ((x) << 4))
+#define PHY_CFG_I               0x60
+#define PHY_CFG_PLL_I           0x63
+#define PHY_CFG_PLL_II          0x64
+#define PHY_CFG_PLL_III         0x65
+#define PHY_CFG_PLL_IV          0x66
+#define PHY_CFG_PLL_V           0x67
+#define DPI_COLOR_CODING        0x10  /* DPI color coding */
+#define DPI_CFG_POL             0x14  /* DPI polarity configuration */
+#define VID_HSA_TIME            0x48  /* Horizontal Sync Active time */
+#define VID_HBP_TIME            0x4C  /* Horizontal Back Porch time */
+#define VID_HLINE_TIME          0x50  /* Line time */
+#define VID_VSA_LINES           0x54  /* Vertical Sync Active period */
+#define VID_VBP_LINES           0x58  /* Vertical Back Porch period */
+#define VID_VFP_LINES           0x5C  /* Vertical Front Porch period */
+#define VID_VACTIVE_LINES       0x60  /* Vertical resolution */
+#define VID_PKT_SIZE            0x3C  /* Video packet size */
+#define VID_MODE_CFG            0x38  /* Video mode configuration */
+#define GEN_HDR			0x6c
+#define GEN_HDATA(data)		(((data) & 0xffff) << 8)
+#define GEN_HDATA_MASK		(0xffff << 8)
+#define GEN_HTYPE(type)		(((type) & 0xff) << 0)
+#define GEN_HTYPE_MASK		0xff
+#define GEN_PLD_DATA		0x70
+#define CMD_PKT_STATUS		0x74
+#define GEN_CMD_EMPTY		BIT(0)
+#define GEN_CMD_FULL		BIT(1)
+#define GEN_PLD_W_EMPTY		BIT(2)
+#define GEN_PLD_W_FULL		BIT(3)
+#define GEN_PLD_R_EMPTY		BIT(4)
+#define GEN_PLD_R_FULL		BIT(5)
+#define GEN_RD_CMD_BUSY		BIT(6)
+#define CMD_MODE_CFG		0x68
+#define MAX_RD_PKT_SIZE_LP	BIT(24)
+#define DCS_LW_TX_LP		BIT(19)
+#define DCS_SR_0P_TX_LP		BIT(18)
+#define DCS_SW_1P_TX_LP		BIT(17)
+#define DCS_SW_0P_TX_LP		BIT(16)
+#define GEN_LW_TX_LP		BIT(14)
+#define GEN_SR_2P_TX_LP		BIT(13)
+#define GEN_SR_1P_TX_LP		BIT(12)
+#define GEN_SR_0P_TX_LP		BIT(11)
+#define GEN_SW_2P_TX_LP		BIT(10)
+#define GEN_SW_1P_TX_LP		BIT(9)
+#define GEN_SW_0P_TX_LP		BIT(8)
+#define EN_ACK_RQST		BIT(1)
+#define EN_TEAR_FX		BIT(0)
+#define CMD_MODE_ALL_LP		(MAX_RD_PKT_SIZE_LP | \
+				 DCS_LW_TX_LP | \
+				 DCS_SR_0P_TX_LP | \
+				 DCS_SW_1P_TX_LP | \
+				 DCS_SW_0P_TX_LP | \
+				 GEN_LW_TX_LP | \
+				 GEN_SR_2P_TX_LP | \
+				 GEN_SR_1P_TX_LP | \
+				 GEN_SR_0P_TX_LP | \
+				 GEN_SW_2P_TX_LP | \
+				 GEN_SW_1P_TX_LP | \
+				 GEN_SW_0P_TX_LP)
+#define PHY_TMR_CFG             0x9C  /* Data lanes timing configuration */
+#define BTA_TO_CNT              0x8C  /* Response timeout definition */
+#define PHY_TMR_LPCLK_CFG       0x98  /* clock lane timing configuration */
+#define CLK_DATA_TMR_CFG        0xCC
+#define LPCLK_CTRL              0x94  /* Low-power in clock lane */
+#define PHY_TXREQUESTCLKHS      BIT(0)
+#define MODE_CFG                0x34  /* Video or Command mode selection */
+#define PHY_STATUS              0xB0  /* D-PHY PPI status interface */
+
+#define	PHY_STOP_WAIT_TIME      0x30
+#define CMD_PKT_STATUS_TIMEOUT_US	20000
+
+/*
+ * regs relevant enum
+ */
+enum dpi_color_coding {
+	DSI_24BITS_1 = 5,
+};
+
+enum dsi_video_mode_type {
+	DSI_NON_BURST_SYNC_PULSES = 0,
+	DSI_NON_BURST_SYNC_EVENTS,
+	DSI_BURST_SYNC_PULSES_1,
+	DSI_BURST_SYNC_PULSES_2
+};
+
+enum dsi_work_mode {
+	DSI_VIDEO_MODE = 0,
+	DSI_COMMAND_MODE
+};
+
+/*
+ * Register Write/Read Helper functions
+ */
+static inline void dw_update_bits(void __iomem *addr, u32 bit_start,
+				  u32 mask, u32 val)
+{
+	u32 tmp, orig;
+
+	orig = readl(addr);
+	tmp = orig & ~(mask << bit_start);
+	tmp |= (val & mask) << bit_start;
+	writel(tmp, addr);
+}
+
+#endif /* __DW_DRM_DSI_H__ */
diff --git a/drivers/staging/hikey9xx/gpu/kirin_dpe_reg.h b/drivers/staging/hikey9xx/gpu/kirin_dpe_reg.h
new file mode 100644
index 000000000000..61af8ef81878
--- /dev/null
+++ b/drivers/staging/hikey9xx/gpu/kirin_dpe_reg.h
@@ -0,0 +1,3114 @@
+/*
+ * Copyright (c) 2016 Linaro Limited.
+ * Copyright (c) 2014-2016 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __KIRIN_DPE_REG_H__
+#define __KIRIN_DPE_REG_H__
+
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/wait.h>
+#include <linux/bug.h>
+
+#include <linux/ion.h>
+#include <linux/hisi/hisi_ion.h>
+
+/*******************************************************************************
+**
+*/
+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,  /*for copybit, only supported in chicago*/
+	DSS_WCHN_W2,
+
+	DSS_COPYBIT_MAX,
+};
+
+enum dss_channel {
+	DSS_CH1 = 0,	/* channel 1 for primary plane */
+	DSS_CH_NUM
+};
+
+#define PRIMARY_CH	DSS_CH1 /* primary plane */
+
+typedef struct dss_rect {
+	s32 x;
+	s32 y;
+	s32 w;
+	s32 h;
+} dss_rect_t;
+
+typedef struct dss_rect_ltrb {
+	s32 left;
+	s32 top;
+	s32 right;
+	s32 bottom;
+} dss_rect_ltrb_t;
+
+enum {
+	DSI_1_LANES = 0,
+	DSI_2_LANES,
+	DSI_3_LANES,
+	DSI_4_LANES,
+};
+
+enum dss_ovl_idx {
+	DSS_OVL0 = 0,
+	DSS_OVL1,
+	DSS_OVL2,
+	DSS_OVL3,
+	DSS_OVL_IDX_MAX,
+};
+
+#define DSS_WCH_MAX  (2)
+
+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 drm_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;
+} drm_dss_layer_t;
+
+
+/*******************************************************************************
+**
+*/
+#define DEFAULT_MIPI_CLK_RATE	(192 * 100000L)
+#define DEFAULT_PCLK_DSI_RATE	(120 * 1000000L)
+
+#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 DSS_MAX_PXL0_CLK_144M (144000000UL)
+
+#define DSS_ADDR  0xE8600000
+#define DSS_DSI_ADDR	(DSS_ADDR + 0x01000)
+#define DSS_LDI_ADDR	(DSS_ADDR + 0x7d000)
+#define PMC_BASE	(0xFFF31000)
+#define PERI_CRG_BASE	(0xFFF35000)
+#define SCTRL_BASE	(0xFFF0A000)
+
+#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)
+
+/*
+ * DSS Registers
+*/
+
+/* 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 SCCLKDIV4	(0x260)
+
+#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 {
+	u32 aif_ch_ctl;
+	u32 aif_ch_ctl_add;
+} dss_aif_t;
+
+typedef struct dss_aif_bw {
+	u64 bw;
+	u8 chn_idx;
+	s8 axi_sel;
+	u8 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 {
+	u32 mif_ctrl1;
+	u32 mif_ctrl2;
+	u32 mif_ctrl3;
+	u32 mif_ctrl4;
+	u32 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 {
+	u32 smmu_scr;
+	u32 smmu_memctrl;
+	u32 smmu_lp_ctrl;
+	u32 smmu_press_remap;
+	u32 smmu_intmask_ns;
+	u32 smmu_intraw_ns;
+	u32 smmu_intstat_ns;
+	u32 smmu_intclr_ns;
+	u32 smmu_smrx_ns[SMMU_SID_NUM];
+	u32 smmu_rld_en0_ns;
+	u32 smmu_rld_en1_ns;
+	u32 smmu_rld_en2_ns;
+	u32 smmu_cb_sctrl;
+	u32 smmu_cb_ttbr0;
+	u32 smmu_cb_ttbr1;
+	u32 smmu_cb_ttbcr;
+	u32 smmu_offset_addr_ns;
+	u32 smmu_scachei_all;
+	u32 smmu_scachei_l1;
+	u32 smmu_scachei_l2l3;
+	u32 smmu_fama_ctrl0_ns;
+	u32 smmu_fama_ctrl1_ns;
+	u32 smmu_addr_msb;
+	u32 smmu_err_rdaddr;
+	u32 smmu_err_wraddr;
+	u32 smmu_fault_addr_tcu;
+	u32 smmu_fault_id_tcu;
+	u32 smmu_fault_addr_tbux;
+	u32 smmu_fault_id_tbux;
+	u32 smmu_fault_infox;
+	u32 smmu_dbgrptr_tlb;
+	u32 smmu_dbgrdata_tlb;
+	u32 smmu_dbgrptr_cache;
+	u32 smmu_dbgrdata0_cache;
+	u32 smmu_dbgrdata1_cache;
+	u32 smmu_dbgaxi_ctrl;
+	u32 smmu_ova_addr;
+	u32 smmu_opa_addr;
+	u32 smmu_ova_ctrl;
+	u32 smmu_opref_addr;
+	u32 smmu_opref_ctrl;
+	u32 smmu_opref_cnt;
+	u32 smmu_smrx_s[SMMU_SID_NUM];
+	u32 smmu_rld_en0_s;
+	u32 smmu_rld_en1_s;
+	u32 smmu_rld_en2_s;
+	u32 smmu_intmas_s;
+	u32 smmu_intraw_s;
+	u32 smmu_intstat_s;
+	u32 smmu_intclr_s;
+	u32 smmu_scr_s;
+	u32 smmu_scb_sctrl;
+	u32 smmu_scb_ttbr;
+	u32 smmu_scb_ttbcr;
+	u32 smmu_offset_addr_s;
+
+	u8 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 {
+	u32 disp_size;
+	u32 pix_in_num;
+	u32 disp_fmt;
+	u32 clip_ctl_hrz;
+	u32 clip_ctl_vrz;
+	u32 ctl_clip_en;
+	u32 icg_module;
+	u32 dither_enable;
+	u32 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 {
+	u32 en_hscl_str;
+	u32 en_vscl_str;
+	u32 h_v_order;
+	u32 input_width_height;
+	u32 output_width_height;
+	u32 en_hscl;
+	u32 en_vscl;
+	u32 acc_hscl;
+	u32 inc_hscl;
+	u32 inc_vscl;
+	u32 en_mmp;
+	u32 scf_ch_core_gt;
+	u32 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 {
+	u32 skin_thres_y;
+	u32 skin_thres_u;
+	u32 skin_thres_v;
+	u32 skin_cfg0;
+	u32 skin_cfg1;
+	u32 skin_cfg2;
+	u32 shoot_cfg1;
+	u32 shoot_cfg2;
+	u32 sharp_cfg1;
+	u32 sharp_cfg2;
+	u32 sharp_cfg3;
+	u32 sharp_cfg4;
+	u32 sharp_cfg5;
+	u32 sharp_cfg6;
+	u32 sharp_cfg7;
+	u32 sharp_cfg8;
+	u32 sharp_cfg9;
+	u32 texturw_analysts;
+	u32 intplshootctrl;
+} dss_arsr2p_effect_t;
+
+typedef struct dss_arsr2p {
+	u32 arsr_input_width_height;
+	u32 arsr_output_width_height;
+	u32 ihleft;
+	u32 ihright;
+	u32 ivtop;
+	u32 ivbottom;
+	u32 ihinc;
+	u32 ivinc;
+	u32 offset;
+	u32 mode;
+	dss_arsr2p_effect_t arsr2p_effect;
+	u32 ihleft1;
+	u32 ihright1;
+	u32 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 {
+	u32 disp_size;
+	u32 clip_ctl_hrz;
+	u32 clip_ctl_vrz;
+	u32 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 {
+	u32 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 {
+	u32 idc0;
+	u32 idc2;
+	u32 odc0;
+	u32 odc2;
+	u32 p0;
+	u32 p1;
+	u32 p2;
+	u32 p3;
+	u32 p4;
+	u32 icg_module;
+	u32 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 {
+	u32 oft_x0;
+	u32 oft_y0;
+	u32 oft_x1;
+	u32 oft_y1;
+	u32 mask0;
+	u32 mask1;
+	u32 stretch_size_vrt;
+	u32 ctrl;
+	u32 tile_scram;
+
+	u32 data_addr0;
+	u32 stride0;
+	u32 stretch_stride0;
+	u32 data_num0;
+
+	u32 data_addr1;
+	u32 stride1;
+	u32 stretch_stride1;
+	u32 data_num1;
+
+	u32 data_addr2;
+	u32 stride2;
+	u32 stretch_stride2;
+	u32 data_num2;
+
+	u32 ch_rd_shadow;
+	u32 ch_ctl;
+
+	u32 dma_buf_ctrl;
+
+	u32 vpp_ctrl;
+	u32 vpp_mem_ctrl;
+
+	u32 afbcd_hreg_hdr_ptr_lo;
+	u32 afbcd_hreg_pic_width;
+	u32 afbcd_hreg_pic_height;
+	u32 afbcd_hreg_format;
+	u32 afbcd_ctl;
+	u32 afbcd_str;
+	u32 afbcd_line_crop;
+	u32 afbcd_input_header_stride;
+	u32 afbcd_payload_stride;
+	u32 afbcd_mm_base_0;
+
+	u32 afbcd_afbcd_payload_pointer;
+	u32 afbcd_height_bf_str;
+	u32 afbcd_os_cfg;
+	u32 afbcd_mem_ctrl;
+	u32 afbcd_scramble_mode;
+	u32 afbcd_header_pointer_offset;
+
+	u8 vpp_used;
+	u8 afbc_used;
+} dss_rdma_t;
+
+typedef struct dss_wdma {
+	u32 oft_x0;
+	u32 oft_y0;
+	u32 oft_x1;
+	u32 oft_y1;
+
+	u32 mask0;
+	u32 mask1;
+	u32 stretch_size_vrt;
+	u32 ctrl;
+	u32 tile_scram;
+
+	u32 sw_mask_en;
+	u32 start_mask0;
+	u32 end_mask0;
+	u32 start_mask1;
+	u32 end_mask1;
+
+	u32 data_addr;
+	u32 stride0;
+	u32 data1_addr;
+	u32 stride1;
+
+	u32 stretch_stride;
+	u32 data_num;
+
+	u32 ch_rd_shadow;
+	u32 ch_ctl;
+	u32 ch_secu_en;
+	u32 ch_sw_end_req;
+
+	u32 dma_buf_ctrl;
+	u32 dma_buf_size;
+
+	u32 rot_size;
+
+	u32 afbce_hreg_pic_blks;
+	u32 afbce_hreg_format;
+	u32 afbce_hreg_hdr_ptr_lo;
+	u32 afbce_hreg_pld_ptr_lo;
+	u32 afbce_picture_size;
+	u32 afbce_ctl;
+	u32 afbce_header_srtide;
+	u32 afbce_payload_stride;
+	u32 afbce_enc_os_cfg;
+	u32 afbce_mem_ctrl;
+	u32 afbce_qos_cfg;
+	u32 afbce_threshold;
+	u32 afbce_scramble_mode;
+	u32 afbce_header_pointer_offset;
+
+	u8 afbc_used;
+	u8 rot_used;
+} dss_wdma_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 {
+	u32 ctl_mutex_itf;
+	u32 ctl_mutex_dbuf;
+	u32 ctl_mutex_scf;
+	u32 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 {
+	u32 chn_mutex;
+	u32 chn_flush_en;
+	u32 chn_ov_oen;
+	u32 chn_starty;
+	u32 chn_mod_dbg;
+} dss_mctl_ch_t;
+
+typedef struct dss_mctl_sys {
+	u32 ov_flush_en[DSS_OVL_IDX_MAX];
+	u32 chn_ov_sel[DSS_OVL_IDX_MAX];
+	u32 wchn_ov_sel[DSS_WCH_MAX];
+	u8 ov_flush_en_used[DSS_OVL_IDX_MAX];
+	u8 chn_ov_sel_used[DSS_OVL_IDX_MAX];
+	u8 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 {
+	u32 layer_pos;
+	u32 layer_size;
+	u32 layer_pattern;
+	u32 layer_alpha;
+	u32 layer_cfg;
+
+} dss_ovl_layer_t;
+
+typedef struct dss_ovl_layer_pos {
+	u32 layer_pspos;
+	u32 layer_pepos;
+
+} dss_ovl_layer_pos_t;
+
+typedef struct dss_ovl {
+	u32 ovl_size;
+	u32 ovl_bg_color;
+	u32 ovl_dst_startpos;
+	u32 ovl_dst_endpos;
+	u32 ovl_gcfg;
+	u32 ovl_block_size;
+	dss_ovl_layer_t ovl_layer[OVL_6LAYER_NUM];
+	dss_ovl_layer_pos_t ovl_layer_pos[OVL_6LAYER_NUM];
+	u8 ovl_layer_used[OVL_6LAYER_NUM];
+} dss_ovl_t;
+
+typedef struct dss_ovl_alpha {
+	u32 src_amode;
+	u32 src_gmode;
+	u32 alpha_offsrc;
+	u32 src_lmode;
+	u32 src_pmode;
+
+	u32 alpha_smode;
+
+	u32 dst_amode;
+	u32 dst_gmode;
+	u32 alpha_offdst;
+	u32 dst_pmode;
+
+	u32 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)
+
+/*******************************************************************************
+ ** 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 {
+	u32 ihleft;
+	u32 ihright;
+	u32 ihleft1;
+	u32 ihright1;
+	u32 ivtop;
+	u32 ivbottom;
+	u32 uv_offset;
+	u32 ihinc;
+	u32 ivinc;
+	u32 mode;
+	u32 format;
+
+	u32 skin_thres_y;
+	u32 skin_thres_u;
+	u32 skin_thres_v;
+	u32 skin_expected;
+	u32 skin_cfg;
+	u32 shoot_cfg1;
+	u32 shoot_cfg2;
+	u32 sharp_cfg1;
+	u32 sharp_cfg2;
+	u32 sharp_cfg3;
+	u32 sharp_cfg4;
+	u32 sharp_cfg5;
+	u32 sharp_cfg6;
+	u32 sharp_cfg7;
+	u32 sharp_cfg8;
+	u32 sharp_cfg9;
+	u32 sharp_cfg10;
+	u32 sharp_cfg11;
+	u32 diff_ctrl;
+	u32 lsc_cfg1;
+	u32 lsc_cfg2;
+	u32 lsc_cfg3;
+	u32 force_clk_on_cfg;
+
+	u32 dpp_img_hrz_bef_sr;
+	u32 dpp_img_vrt_bef_sr;
+	u32 dpp_img_hrz_aft_sr;
+	u32 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)
+
+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,
+
+	HISI_FB_PIXEL_FORMAT_UNSUPPORT = 800
+};
+
+struct dss_hw_ctx {
+	void __iomem *base;
+	struct regmap *noc_regmap;
+	struct reset_control *reset;
+
+	void __iomem *noc_dss_base;
+	void __iomem *peri_crg_base;
+	void __iomem *pmc_base;
+	void __iomem *sctrl_base;
+
+	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;
+
+	bool power_on;
+	int irq;
+
+	wait_queue_head_t vactive0_start_wq;
+	u32 vactive0_start_flag;
+	ktime_t vsync_timestamp;
+	ktime_t vsync_timestamp_prev;
+
+	struct iommu_domain *mmu_domain;
+	struct ion_client *ion_client;
+	struct ion_handle *ion_handle;
+	struct iommu_map_format iommu_format;
+	char __iomem *screen_base;
+	unsigned long smem_start;
+	unsigned long screen_size;
+};
+
+struct dss_crtc {
+	struct drm_crtc base;
+	struct dss_hw_ctx *ctx;
+	bool enable;
+	u32 out_format;
+	u32 bgr_fmt;
+};
+
+struct dss_plane {
+	struct drm_plane base;
+	/*void *ctx;*/
+	void *acrtc;
+	u8 ch; /* channel */
+};
+
+struct dss_data {
+	struct dss_crtc acrtc;
+	struct dss_plane aplane[DSS_CH_NUM];
+	struct dss_hw_ctx ctx;
+};
+
+/* ade-format info: */
+struct dss_format {
+	u32 pixel_format;
+	enum hisi_fb_pixel_format dss_format;
+};
+
+#define MIPI_DPHY_NUM	(2)
+
+/* IFBC compress mode */
+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_VESA3_75X_DUAL,
+
+	IFBC_TYPE_MAX
+};
+
+/* IFBC compress mode */
+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,
+};
+
+/* xres_div */
+enum XRES_DIV {
+	XRES_DIV_1 = 1,
+	XRES_DIV_2,
+	XRES_DIV_3,
+	XRES_DIV_4,
+	XRES_DIV_5,
+	XRES_DIV_6,
+};
+
+/* yres_div */
+enum YRES_DIV {
+	YRES_DIV_1 = 1,
+	YRES_DIV_2,
+	YRES_DIV_3,
+	YRES_DIV_4,
+	YRES_DIV_5,
+	YRES_DIV_6,
+};
+
+/* pxl0_divxcfg */
+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,
+};
+
+/* pxl0_div2_gt_en */
+enum PXL0_DIV2_GT_EN {
+	PXL0_DIV2_GT_EN_CLOSE = 0,
+	PXL0_DIV2_GT_EN_OPEN,
+};
+
+/* pxl0_div4_gt_en */
+enum PXL0_DIV4_GT_EN {
+	PXL0_DIV4_GT_EN_CLOSE = 0,
+	PXL0_DIV4_GT_EN_OPEN,
+};
+
+/* pxl0_dsi_gt_en */
+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,
+};
+
+typedef struct mipi_ifbc_division {
+	u32 xres_div;
+	u32 yres_div;
+	u32 comp_mode;
+	u32 pxl0_div2_gt_en;
+	u32 pxl0_div4_gt_en;
+	u32 pxl0_divxcfg;
+	u32 pxl0_dsi_gt_en;
+} mipi_ifbc_division_t;
+
+/*******************************************************************************
+**
+*/
+#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)
+
+#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
+
+#define to_dss_crtc(crtc) \
+	container_of(crtc, struct dss_crtc, base)
+
+#define to_dss_plane(plane) \
+	container_of(plane, struct dss_plane, base)
+
+#endif
diff --git a/drivers/staging/hikey9xx/gpu/kirin_drm_dpe_utils.c b/drivers/staging/hikey9xx/gpu/kirin_drm_dpe_utils.c
new file mode 100644
index 000000000000..2d6809b72b42
--- /dev/null
+++ b/drivers/staging/hikey9xx/gpu/kirin_drm_dpe_utils.c
@@ -0,0 +1,731 @@
+/* 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 <drm/drmP.h>
+
+#include "drm_mipi_dsi.h"
+#include "kirin_drm_dpe_utils.h"
+
+int g_debug_set_reg_val = 0;
+
+extern u32 g_dss_module_ovl_base[DSS_MCTL_IDX_MAX][MODULE_OVL_MAX];
+
+mipi_ifbc_division_t g_mipi_ifbc_division[MIPI_DPHY_NUM][IFBC_TYPE_MAX] = {
+	/*single mipi*/
+	{
+		/*none*/
+		{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},
+		/*orise2x*/
+		{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},
+		/*orise3x*/
+		{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},
+		/*himax2x*/
+		{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},
+		/*rsp2x*/
+		{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},
+		/*rsp3x  [NOTE]reality: xres_div = 1.5, yres_div = 2, amended in "mipi_ifbc_get_rect" function*/
+		{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},
+		/*vesa2x_1pipe*/
+		{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},
+		/*vesa3x_1pipe*/
+		{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},
+		/*vesa2x_2pipe*/
+		{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},
+		/*vesa3x_2pipe*/
+		{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}
+	},
+
+	/*dual mipi*/
+	{
+		/*none*/
+		{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},
+		/*orise2x*/
+		{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},
+		/*orise3x*/
+		{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},
+		/*himax2x*/
+		{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},
+		/*rsp2x*/
+		{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},
+		/*rsp3x*/
+		{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},
+		/*vesa2x_1pipe*/
+		{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},
+		/*vesa3x_1pipe*/
+		{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},
+		/*vesa2x_2pipe*/
+		{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},
+		/*vesa3x_2pipe*/
+		{XRES_DIV_6, YRES_DIV_1, IFBC_COMP_MODE_6, PXL0_DIV2_GT_EN_OPEN,
+			PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_5, 3} }
+};
+
+void set_reg(char __iomem *addr, uint32_t val, uint8_t bw, uint8_t bs)
+{
+	u32 mask = (1UL << bw) - 1UL;
+	u32 tmp = 0;
+
+	tmp = inp32(addr);
+	tmp &= ~(mask << bs);
+
+	outp32(addr, tmp | ((val & mask) << bs));
+
+	if (g_debug_set_reg_val) {
+		printk(KERN_INFO "writel: [%p] = 0x%x\n", addr,
+			     tmp | ((val & mask) << bs));
+	}
+}
+
+static int mipi_ifbc_get_rect(struct dss_rect *rect)
+{
+	u32 ifbc_type;
+	u32 mipi_idx;
+	u32 xres_div;
+	u32 yres_div;
+
+	ifbc_type = IFBC_TYPE_NONE;
+	mipi_idx = 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)
+		DRM_ERROR("xres(%d) is not division_h(%d) pixel aligned!\n", rect->w, xres_div);
+
+	if ((rect->h % yres_div) > 0)
+		DRM_ERROR("yres(%d) is not division_v(%d) pixel aligned!\n", rect->h, yres_div);
+
+	/*
+	** [NOTE] rsp3x && single_mipi CMD mode amended xres_div = 1.5, yres_div = 2 ,
+	** VIDEO mode amended xres_div = 3, yres_div = 1
+	*/
+	rect->w /= xres_div;
+	rect->h /= yres_div;
+
+	return 0;
+}
+
+static void init_ldi_pxl_div(struct dss_crtc *acrtc)
+{
+	struct dss_hw_ctx *ctx;
+	char __iomem *ldi_base;
+	struct drm_display_mode *mode;
+	struct drm_display_mode *adj_mode;
+
+	u32 ifbc_type = 0;
+	u32 mipi_idx = 0;
+	u32 pxl0_div2_gt_en = 0;
+	u32 pxl0_div4_gt_en = 0;
+	u32 pxl0_divxcfg = 0;
+	u32 pxl0_dsi_gt_en = 0;
+
+	ctx = acrtc->ctx;
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return;
+	}
+
+	mode = &acrtc->base.state->mode;
+	adj_mode = &acrtc->base.state->adjusted_mode;
+
+	ldi_base = ctx->base + DSS_LDI0_OFFSET;
+
+	ifbc_type = IFBC_TYPE_NONE;
+	mipi_idx = 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_other(struct dss_crtc *acrtc)
+{
+	struct dss_hw_ctx *ctx;
+	char __iomem *dss_base;
+
+	ctx = acrtc->ctx;
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return;
+	}
+
+	dss_base = ctx->base;
+
+	/**
+	 * VESA_CLK_SEL is set to 0 for initial,
+	 * 1 is needed only by vesa dual pipe compress
+	 */
+	set_reg(dss_base + DSS_LDI0_OFFSET + LDI_VESA_CLK_SEL, 0, 1, 0);
+}
+
+void init_ldi(struct dss_crtc *acrtc)
+{
+	struct dss_hw_ctx *ctx;
+	char __iomem *ldi_base;
+	struct drm_display_mode *mode;
+	struct drm_display_mode *adj_mode;
+
+	dss_rect_t rect = {0, 0, 0, 0};
+	u32 hfp, hbp, hsw, vfp, vbp, vsw;
+	u32 vsync_plr = 0;
+	u32 hsync_plr = 0;
+	u32 pixelclk_plr = 0;
+	u32 data_en_plr = 0;
+
+	ctx = acrtc->ctx;
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return ;
+	}
+
+	mode = &acrtc->base.state->mode;
+	adj_mode = &acrtc->base.state->adjusted_mode;
+
+	hfp = mode->hsync_start - mode->hdisplay;
+	hbp = mode->htotal - mode->hsync_end;
+	hsw = mode->hsync_end - mode->hsync_start;
+	vfp = mode->vsync_start - mode->vdisplay;
+	vbp = mode->vtotal - mode->vsync_end;
+	vsw = mode->vsync_end - mode->vsync_start;
+
+	ldi_base = ctx->base + DSS_LDI0_OFFSET;
+
+	rect.x = 0;
+	rect.y = 0;
+	rect.w = mode->hdisplay;
+	rect.h = mode->vdisplay;
+	mipi_ifbc_get_rect(&rect);
+
+	init_ldi_pxl_div(acrtc);
+
+	outp32(ldi_base + LDI_DPI0_HRZ_CTRL0,
+		hfp | ((hbp + DSS_WIDTH(hsw)) << 16));
+	outp32(ldi_base + LDI_DPI0_HRZ_CTRL1, 0);
+	outp32(ldi_base + LDI_DPI0_HRZ_CTRL2, DSS_WIDTH(rect.w));
+	outp32(ldi_base + LDI_VRT_CTRL0,
+		vfp | (vbp << 16));
+	outp32(ldi_base + LDI_VRT_CTRL1, DSS_HEIGHT(vsw));
+	outp32(ldi_base + LDI_VRT_CTRL2, DSS_HEIGHT(rect.h));
+
+	outp32(ldi_base + LDI_PLR_CTRL,
+		vsync_plr | (hsync_plr << 1) |
+		(pixelclk_plr << 2) | (data_en_plr << 3));
+
+	/* bpp*/
+	set_reg(ldi_base + LDI_CTRL, acrtc->out_format, 2, 3);
+	/* bgr*/
+	set_reg(ldi_base + LDI_CTRL, acrtc->bgr_fmt, 1, 13);
+
+	/* for ddr pmqos*/
+	outp32(ldi_base + LDI_VINACT_MSK_LEN, vfp);
+
+	/*cmd event sel*/
+	outp32(ldi_base + LDI_CMD_EVENT_SEL, 0x1);
+
+	/* for 1Hz LCD and mipi command LCD*/
+	set_reg(ldi_base + LDI_DSI_CMD_MOD_CTRL, 0x1, 1, 1);
+
+	/*ldi_data_gate(hisifd, true);*/
+
+#ifdef CONFIG_HISI_FB_LDI_COLORBAR_USED
+	/* colorbar width*/
+	set_reg(ldi_base + LDI_CTRL, DSS_WIDTH(0x3c), 7, 6);
+	/* colorbar ort*/
+	set_reg(ldi_base + LDI_WORK_MODE, 0x0, 1, 1);
+	/* colorbar enable*/
+	set_reg(ldi_base + LDI_WORK_MODE, 0x0, 1, 0);
+#else
+	/* normal*/
+	set_reg(ldi_base + LDI_WORK_MODE, 0x1, 1, 0);
+#endif
+
+	/* ldi disable*/
+	set_reg(ldi_base + LDI_CTRL, 0x0, 1, 0);
+}
+
+void init_dbuf(struct dss_crtc *acrtc)
+{
+	struct dss_hw_ctx *ctx;
+	struct drm_display_mode *mode;
+	struct drm_display_mode *adj_mode;
+	char __iomem *dbuf_base;
+
+	int sram_valid_num = 0;
+	int sram_max_mem_depth = 0;
+	int sram_min_support_depth = 0;
+
+	u32 thd_rqos_in = 0;
+	u32 thd_rqos_out = 0;
+	u32 thd_wqos_in = 0;
+	u32 thd_wqos_out = 0;
+	u32 thd_cg_in = 0;
+	u32 thd_cg_out = 0;
+	u32 thd_wr_wait = 0;
+	u32 thd_cg_hold = 0;
+	u32 thd_flux_req_befdfs_in = 0;
+	u32 thd_flux_req_befdfs_out = 0;
+	u32 thd_flux_req_aftdfs_in = 0;
+	u32 thd_flux_req_aftdfs_out = 0;
+	u32 thd_dfs_ok = 0;
+	u32 dfs_ok_mask = 0;
+	u32 thd_flux_req_sw_en = 1;
+	u32 hfp, hbp, hsw, vfp, vbp, vsw;
+
+	int dfs_time = 0;
+	int dfs_time_min = 0;
+	int depth = 0;
+
+	ctx = acrtc->ctx;
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return;
+	}
+
+	mode = &acrtc->base.state->mode;
+	adj_mode = &acrtc->base.state->adjusted_mode;
+
+	hfp = mode->hsync_start - mode->hdisplay;
+	hbp = mode->htotal - mode->hsync_end;
+	hsw = mode->hsync_end - mode->hsync_start;
+	vfp = mode->vsync_start - mode->vdisplay;
+	vbp = mode->vtotal - mode->vsync_end;
+	vsw = mode->vsync_end - mode->vsync_start;
+
+	dbuf_base = ctx->base + DSS_DBUF0_OFFSET;
+
+	if (mode->hdisplay * mode->vdisplay >= RES_4K_PHONE)
+		dfs_time_min = DFS_TIME_MIN_4K;
+	else
+		dfs_time_min = DFS_TIME_MIN;
+
+	dfs_time = DFS_TIME;
+	depth = DBUF0_DEPTH;
+
+	DRM_DEBUG("dfs_time=%d,\n"
+		"adj_mode->clock=%d\n"
+		"hsw=%d\n"
+		"hbp=%d\n"
+		"hfp=%d\n"
+		"mode->hdisplay=%d\n"
+		"mode->vdisplay=%d\n",
+		dfs_time,
+		adj_mode->clock,
+		hsw,
+		hbp,
+		hfp,
+		mode->hdisplay,
+		mode->vdisplay);
+
+	/*
+	** int K = 0;
+	** int Tp = 1000000  / adj_mode->clock;
+	** K = (hsw + hbp + mode->hdisplay +
+	**	hfp) / mode->hdisplay;
+	** thd_cg_out = dfs_time / (Tp * K * 6);
+	*/
+	thd_cg_out = (dfs_time * adj_mode->clock * 1000UL * mode->hdisplay) /
+		(((hsw + hbp + hfp) + mode->hdisplay) * 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 * mode->hdisplay / (1000000 / 60 / (mode->vdisplay +
+		vbp + vfp + vsw) * (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;
+
+	DRM_DEBUG("hdisplay=%d\n"
+		"vdisplay=%d\n"
+		"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",
+		mode->hdisplay,
+		mode->vdisplay,
+		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, mode->hdisplay * mode->vdisplay);
+	outp32(dbuf_base + DBUF_FRM_HSIZE, DSS_WIDTH(mode->hdisplay));
+	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);
+}
+
+void init_dpp(struct dss_crtc *acrtc)
+{
+	struct dss_hw_ctx *ctx;
+	struct drm_display_mode *mode;
+	struct drm_display_mode *adj_mode;
+	char __iomem *dpp_base;
+	char __iomem *mctl_sys_base;
+
+	ctx = acrtc->ctx;
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return;
+	}
+
+	mode = &acrtc->base.state->mode;
+	adj_mode = &acrtc->base.state->adjusted_mode;
+
+	dpp_base = ctx->base + DSS_DPP_OFFSET;
+	mctl_sys_base = ctx->base + DSS_MCTRL_SYS_OFFSET;
+
+	outp32(dpp_base + DPP_IMG_SIZE_BEF_SR,
+		(DSS_HEIGHT(mode->vdisplay) << 16) | DSS_WIDTH(mode->hdisplay));
+	outp32(dpp_base + DPP_IMG_SIZE_AFT_SR,
+		(DSS_HEIGHT(mode->vdisplay) << 16) | DSS_WIDTH(mode->hdisplay));
+
+#ifdef CONFIG_HISI_FB_DPP_COLORBAR_USED
+	void __iomem *mctl_base;
+	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);
+
+	mctl_base = ctx->base +
+		g_dss_module_ovl_base[DSS_OVL0][MODULE_MCTL_BASE];
+
+	set_reg(mctl_base + MCTL_CTL_MUTEX, 0x1, 1, 0);
+	set_reg(mctl_base + MCTL_CTL_EN, 0x1, 32, 0);
+	set_reg(mctl_base + MCTL_CTL_TOP, 0x2, 32, 0); /*auto mode*/
+	set_reg(mctl_base + MCTL_CTL_DBG, 0xB13A00, 32, 0);
+
+	set_reg(mctl_base + MCTL_CTL_MUTEX_ITF, 0x1, 2, 0);
+	set_reg(mctl_sys_base + MCTL_OV0_FLUSH_EN, 0x8, 4, 0);
+	set_reg(mctl_base + MCTL_CTL_MUTEX, 0x0, 1, 0);
+#endif
+}
+
+void enable_ldi(struct dss_crtc *acrtc)
+{
+	struct dss_hw_ctx *ctx;
+	char __iomem *ldi_base;
+
+	ctx = acrtc->ctx;
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return;
+	}
+
+	ldi_base = ctx->base + DSS_LDI0_OFFSET;
+
+	/* ldi enable */
+	set_reg(ldi_base + LDI_CTRL, 0x1, 1, 0);
+}
+
+void disable_ldi(struct dss_crtc *acrtc)
+{
+	struct dss_hw_ctx *ctx;
+	char __iomem *ldi_base;
+
+	ctx = acrtc->ctx;
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return;
+	}
+
+	ldi_base = ctx->base + DSS_LDI0_OFFSET;
+
+	/* ldi disable */
+	set_reg(ldi_base + LDI_CTRL, 0x0, 1, 0);
+}
+
+void dpe_interrupt_clear(struct dss_crtc *acrtc)
+{
+	struct dss_hw_ctx *ctx;
+	char __iomem *dss_base;
+	u32 clear;
+
+	ctx = acrtc->ctx;
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return;
+	}
+
+	dss_base = ctx->base;
+
+	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);
+}
+
+void dpe_interrupt_unmask(struct dss_crtc *acrtc)
+{
+	struct dss_hw_ctx *ctx;
+	char __iomem *dss_base;
+	u32 unmask;
+
+	ctx = acrtc->ctx;
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return;
+	}
+
+	dss_base = ctx->base;
+
+	unmask = ~0;
+	unmask &= ~(BIT_DPP_INTS | BIT_ITF0_INTS | BIT_MMU_IRPT_NS);
+	outp32(dss_base + GLB_CPU_PDP_INT_MSK, unmask);
+
+	unmask = ~0;
+	unmask &= ~(BIT_VSYNC | BIT_VACTIVE0_START
+		| BIT_VACTIVE0_END | BIT_FRM_END | BIT_LDI_UNFLOW);
+
+	outp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK, unmask);
+}
+
+void dpe_interrupt_mask(struct dss_crtc *acrtc)
+{
+	struct dss_hw_ctx *ctx;
+	char __iomem *dss_base;
+	u32 mask;
+
+	ctx = acrtc->ctx;
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return ;
+	}
+
+	dss_base = ctx->base;
+
+	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);
+}
+
+int dpe_init(struct dss_crtc *acrtc)
+{
+	struct drm_display_mode *mode;
+	struct drm_display_mode *adj_mode;
+
+	mode = &acrtc->base.state->mode;
+	adj_mode = &acrtc->base.state->adjusted_mode;
+
+	init_dbuf(acrtc);
+	init_dpp(acrtc);
+	init_other(acrtc);
+	init_ldi(acrtc);
+
+	hisifb_dss_on(acrtc->ctx);
+	hisi_dss_mctl_on(acrtc->ctx);
+
+	hisi_dss_mctl_mutex_lock(acrtc->ctx);
+
+	hisi_dss_ovl_base_config(acrtc->ctx, mode->hdisplay, mode->vdisplay);
+
+	hisi_dss_mctl_mutex_unlock(acrtc->ctx);
+
+	enable_ldi(acrtc);
+
+	mdelay(60);
+
+	return 0;
+}
+
+void dss_inner_clk_pdp_enable(struct dss_crtc *acrtc)
+{
+	struct dss_hw_ctx *ctx;
+	char __iomem *dss_base;
+
+	ctx = acrtc->ctx;
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return;
+	}
+	dss_base = ctx->base;
+
+	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_common_enable(struct dss_crtc *acrtc)
+{
+	struct dss_hw_ctx *ctx;
+	char __iomem *dss_base;
+
+	ctx = acrtc->ctx;
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return;
+	}
+	dss_base = ctx->base;
+
+	/*core/axi/mmbuf*/
+	outp32(dss_base + DSS_CMDLIST_OFFSET + CMD_MEM_CTRL, 0x00000008);  /*cmd mem*/
+
+	outp32(dss_base + DSS_RCH_VG0_SCL_OFFSET + SCF_COEF_MEM_CTRL, 0x00000088);/*rch_v0 ,scf mem*/
+	outp32(dss_base + DSS_RCH_VG0_SCL_OFFSET + SCF_LB_MEM_CTRL, 0x00000008);/*rch_v0 ,scf mem*/
+	outp32(dss_base + DSS_RCH_VG0_ARSR_OFFSET + ARSR2P_LB_MEM_CTRL, 0x00000008);/*rch_v0 ,arsr2p mem*/
+	outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + VPP_MEM_CTRL, 0x00000008);/*rch_v0 ,vpp mem*/
+	outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_v0 ,dma_buf mem*/
+	outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + AFBCD_MEM_CTRL, 0x00008888);/*rch_v0 ,afbcd mem*/
+
+	outp32(dss_base + DSS_RCH_VG1_SCL_OFFSET + SCF_COEF_MEM_CTRL, 0x00000088);/*rch_v1 ,scf mem*/
+	outp32(dss_base + DSS_RCH_VG1_SCL_OFFSET + SCF_LB_MEM_CTRL, 0x00000008);/*rch_v1 ,scf mem*/
+	outp32(dss_base + DSS_RCH_VG1_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_v1 ,dma_buf mem*/
+	outp32(dss_base + DSS_RCH_VG1_DMA_OFFSET + AFBCD_MEM_CTRL, 0x00008888);/*rch_v1 ,afbcd mem*/
+
+	outp32(dss_base + DSS_RCH_VG2_SCL_OFFSET + SCF_COEF_MEM_CTRL, 0x00000088);/*rch_v2 ,scf mem*/
+	outp32(dss_base + DSS_RCH_VG2_SCL_OFFSET + SCF_LB_MEM_CTRL, 0x00000008);/*rch_v2 ,scf mem*/
+	outp32(dss_base + DSS_RCH_VG2_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_v2 ,dma_buf mem*/
+
+	outp32(dss_base + DSS_RCH_G0_SCL_OFFSET + SCF_COEF_MEM_CTRL, 0x00000088);/*rch_g0 ,scf mem*/
+	outp32(dss_base + DSS_RCH_G0_SCL_OFFSET + SCF_LB_MEM_CTRL, 0x0000008);/*rch_g0 ,scf mem*/
+	outp32(dss_base + DSS_RCH_G0_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_g0 ,dma_buf mem*/
+	outp32(dss_base + DSS_RCH_G0_DMA_OFFSET + AFBCD_MEM_CTRL, 0x00008888);/*rch_g0 ,afbcd mem*/
+
+	outp32(dss_base + DSS_RCH_G1_SCL_OFFSET + SCF_COEF_MEM_CTRL, 0x00000088);/*rch_g1 ,scf mem*/
+	outp32(dss_base + DSS_RCH_G1_SCL_OFFSET + SCF_LB_MEM_CTRL, 0x0000008);/*rch_g1 ,scf mem*/
+	outp32(dss_base + DSS_RCH_G1_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_g1 ,dma_buf mem*/
+	outp32(dss_base + DSS_RCH_G1_DMA_OFFSET + AFBCD_MEM_CTRL, 0x00008888);/*rch_g1 ,afbcd mem*/
+
+	outp32(dss_base + DSS_RCH_D0_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_d0 ,dma_buf mem*/
+	outp32(dss_base + DSS_RCH_D0_DMA_OFFSET + AFBCD_MEM_CTRL, 0x00008888);/*rch_d0 ,afbcd mem*/
+	outp32(dss_base + DSS_RCH_D1_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_d1 ,dma_buf mem*/
+	outp32(dss_base + DSS_RCH_D2_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_d2 ,dma_buf mem*/
+	outp32(dss_base + DSS_RCH_D3_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_d3 ,dma_buf mem*/
+
+	outp32(dss_base + DSS_WCH0_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*wch0 DMA/AFBCE mem*/
+	outp32(dss_base + DSS_WCH0_DMA_OFFSET + AFBCE_MEM_CTRL, 0x00000888);/*wch0 DMA/AFBCE mem*/
+	outp32(dss_base + DSS_WCH0_DMA_OFFSET + ROT_MEM_CTRL, 0x00000008);/*wch0 rot mem*/
+	outp32(dss_base + DSS_WCH1_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*wch1 DMA/AFBCE mem*/
+	outp32(dss_base + DSS_WCH1_DMA_OFFSET + AFBCE_MEM_CTRL, 0x00000888);/*wch1 DMA/AFBCE mem*/
+	outp32(dss_base + DSS_WCH1_DMA_OFFSET + ROT_MEM_CTRL, 0x00000008);/*wch1 rot mem*/
+	outp32(dss_base + DSS_WCH2_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*wch2 DMA/AFBCE mem*/
+	outp32(dss_base + DSS_WCH2_DMA_OFFSET + ROT_MEM_CTRL, 0x00000008);/*wch2 rot mem*/
+}
+int dpe_irq_enable(struct dss_crtc *acrtc)
+{
+	struct dss_hw_ctx *ctx;
+
+	ctx = acrtc->ctx;
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return -1;
+	}
+
+	if (ctx->irq)
+		enable_irq(ctx->irq);
+
+	return 0;
+}
+
+int dpe_irq_disable(struct dss_crtc *acrtc)
+{
+	struct dss_hw_ctx *ctx;
+
+	ctx = acrtc->ctx;
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return -1;
+	}
+
+	if (ctx->irq)
+		disable_irq(ctx->irq);
+
+	/*disable_irq_nosync(ctx->irq);*/
+
+	return 0;
+}
diff --git a/drivers/staging/hikey9xx/gpu/kirin_drm_dpe_utils.h b/drivers/staging/hikey9xx/gpu/kirin_drm_dpe_utils.h
new file mode 100644
index 000000000000..7ee992273d72
--- /dev/null
+++ b/drivers/staging/hikey9xx/gpu/kirin_drm_dpe_utils.h
@@ -0,0 +1,58 @@
+/* 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 KIRIN_DRM_DPE_UTILS_H
+#define KIRIN_DRM_DPE_UTILS_H
+
+#include "kirin_dpe_reg.h"
+
+/*#define CONFIG_HISI_FB_OV_BASE_USED*/
+/*#define CONFIG_HISI_FB_DPP_COLORBAR_USED*/
+/*#define CONFIG_HISI_FB_LDI_COLORBAR_USED*/
+
+void set_reg(char __iomem *addr, uint32_t val, uint8_t bw, uint8_t bs);
+
+void init_dbuf(struct dss_crtc *acrtc);
+void init_dpp(struct dss_crtc *acrtc);
+void init_other(struct dss_crtc *acrtc);
+void init_ldi(struct dss_crtc *acrtc);
+
+void deinit_ldi(struct dss_crtc *acrtc);
+void enable_ldi(struct dss_crtc *acrtc);
+void disable_ldi(struct dss_crtc *acrtc);
+
+void dss_inner_clk_pdp_enable(struct dss_crtc *acrtc);
+void dss_inner_clk_common_enable(struct dss_crtc *acrtc);
+void dpe_interrupt_clear(struct dss_crtc *acrtc);
+void dpe_interrupt_unmask(struct dss_crtc *acrtc);
+void dpe_interrupt_mask(struct dss_crtc *acrtc);
+
+int dpe_irq_enable(struct dss_crtc *acrtc);
+int dpe_irq_disable(struct dss_crtc *acrtc);
+
+int dpe_init(struct dss_crtc *acrtc);
+
+void hisifb_dss_on(struct dss_hw_ctx *ctx);
+void hisi_dss_mctl_on(struct dss_hw_ctx *ctx);
+
+void hisi_dss_unflow_handler(struct dss_hw_ctx *ctx, bool unmask);
+int hisi_dss_mctl_mutex_lock(struct dss_hw_ctx *ctx);
+int hisi_dss_mctl_mutex_unlock(struct dss_hw_ctx *ctx);
+int hisi_dss_ovl_base_config(struct dss_hw_ctx *ctx, u32 xres, u32 yres);
+
+void hisi_fb_pan_display(struct drm_plane *plane);
+void hisi_dss_online_play(struct drm_plane *plane, drm_dss_layer_t *layer);
+
+u32 dss_get_format(u32 pixel_format);
+
+#endif
diff --git a/drivers/staging/hikey9xx/gpu/kirin_drm_drv.c b/drivers/staging/hikey9xx/gpu/kirin_drm_drv.c
new file mode 100644
index 000000000000..edb690062f64
--- /dev/null
+++ b/drivers/staging/hikey9xx/gpu/kirin_drm_drv.c
@@ -0,0 +1,380 @@
+/*
+ * Hisilicon Kirin SoCs drm master driver
+ *
+ * Copyright (c) 2016 Linaro Limited.
+ * Copyright (c) 2014-2016 Hisilicon Limited.
+ *
+ * Author:
+ *	<cailiwei@hisilicon.com>
+ *	<zhengwanchun@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/of_platform.h>
+#include <linux/component.h>
+#include <linux/of_graph.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "kirin_drm_drv.h"
+
+
+#ifdef CONFIG_DRM_FBDEV_EMULATION
+static bool fbdev = true;
+MODULE_PARM_DESC(fbdev, "Enable fbdev compat layer");
+module_param(fbdev, bool, 0600);
+#endif
+
+
+static struct kirin_dc_ops *dc_ops;
+
+static int kirin_drm_kms_cleanup(struct drm_device *dev)
+{
+	struct kirin_drm_private *priv = dev->dev_private;
+
+	if (priv->fbdev) {
+		kirin_drm_fbdev_fini(dev);
+		priv->fbdev = NULL;
+	}
+
+	drm_kms_helper_poll_fini(dev);
+	drm_vblank_cleanup(dev);
+	dc_ops->cleanup(dev);
+	drm_mode_config_cleanup(dev);
+	devm_kfree(dev->dev, priv);
+	dev->dev_private = NULL;
+
+	return 0;
+}
+
+static void kirin_fbdev_output_poll_changed(struct drm_device *dev)
+{
+	struct kirin_drm_private *priv = dev->dev_private;
+
+	dsi_set_output_client(dev);
+
+	if (priv->fbdev)
+		drm_fb_helper_hotplug_event(priv->fbdev);
+	else
+		priv->fbdev = kirin_drm_fbdev_init(dev);
+}
+
+static const struct drm_mode_config_funcs kirin_drm_mode_config_funcs = {
+	.fb_create = drm_fb_cma_create,
+	.output_poll_changed = kirin_fbdev_output_poll_changed,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
+};
+
+static void kirin_drm_mode_config_init(struct drm_device *dev)
+{
+	dev->mode_config.min_width = 0;
+	dev->mode_config.min_height = 0;
+
+	dev->mode_config.max_width = 2048;
+	dev->mode_config.max_height = 2048;
+
+	dev->mode_config.funcs = &kirin_drm_mode_config_funcs;
+}
+
+static int kirin_drm_kms_init(struct drm_device *dev)
+{
+	struct kirin_drm_private *priv;
+	int ret;
+
+	priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	dev->dev_private = priv;
+	dev_set_drvdata(dev->dev, dev);
+
+	/* dev->mode_config initialization */
+	drm_mode_config_init(dev);
+	kirin_drm_mode_config_init(dev);
+
+	/* display controller init */
+	ret = dc_ops->init(dev);
+	if (ret)
+		goto err_mode_config_cleanup;
+
+	/* bind and init sub drivers */
+	ret = component_bind_all(dev->dev, dev);
+	if (ret) {
+		DRM_ERROR("failed to bind all component.\n");
+		goto err_dc_cleanup;
+	}
+
+	/* vblank init */
+	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+	if (ret) {
+		DRM_ERROR("failed to initialize vblank.\n");
+		goto err_unbind_all;
+	}
+	/* with irq_enabled = true, we can use the vblank feature. */
+	dev->irq_enabled = true;
+
+	/* reset all the states of crtc/plane/encoder/connector */
+	drm_mode_config_reset(dev);
+
+	//if (fbdev)
+	//	priv->fbdev = kirin_drm_fbdev_init(dev);
+
+	/* init kms poll for handling hpd */
+	drm_kms_helper_poll_init(dev);
+
+	/* force detection after connectors init */
+	(void)drm_helper_hpd_irq_event(dev);
+
+	return 0;
+
+err_unbind_all:
+	component_unbind_all(dev->dev, dev);
+err_dc_cleanup:
+	dc_ops->cleanup(dev);
+err_mode_config_cleanup:
+	drm_mode_config_cleanup(dev);
+	devm_kfree(dev->dev, priv);
+	dev->dev_private = NULL;
+
+	return ret;
+}
+
+static const struct file_operations kirin_drm_fops = {
+	.owner		= THIS_MODULE,
+	.open		= drm_open,
+	.release	= drm_release,
+	.unlocked_ioctl	= drm_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= drm_compat_ioctl,
+#endif
+	.poll		= drm_poll,
+	.read		= drm_read,
+	.llseek		= no_llseek,
+	.mmap		= drm_gem_cma_mmap,
+};
+
+static int kirin_gem_cma_dumb_create(struct drm_file *file,
+				     struct drm_device *dev,
+				     struct drm_mode_create_dumb *args)
+{
+	return drm_gem_cma_dumb_create_internal(file, dev, args);
+}
+
+static int kirin_drm_connectors_register(struct drm_device *dev)
+{
+	struct drm_connector *connector;
+	struct drm_connector *failed_connector;
+	int ret;
+
+	mutex_lock(&dev->mode_config.mutex);
+	drm_for_each_connector(connector, dev) {
+		ret = drm_connector_register(connector);
+		if (ret) {
+			failed_connector = connector;
+			goto err;
+		}
+	}
+	mutex_unlock(&dev->mode_config.mutex);
+
+	return 0;
+
+err:
+	drm_for_each_connector(connector, dev) {
+		if (failed_connector == connector)
+			break;
+		drm_connector_unregister(connector);
+	}
+	mutex_unlock(&dev->mode_config.mutex);
+
+	return ret;
+}
+
+static struct drm_driver kirin_drm_driver = {
+	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
+				  DRIVER_ATOMIC | DRIVER_HAVE_IRQ | DRIVER_RENDER,
+	.fops				= &kirin_drm_fops,
+	.set_busid			= drm_platform_set_busid,
+
+	.gem_free_object	= drm_gem_cma_free_object,
+	.gem_vm_ops		= &drm_gem_cma_vm_ops,
+	.dumb_create		= kirin_gem_cma_dumb_create,
+	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
+	.dumb_destroy		= drm_gem_dumb_destroy,
+
+	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
+	.gem_prime_export	= drm_gem_prime_export,
+	.gem_prime_import	= drm_gem_prime_import,
+	.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
+	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
+	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
+	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
+
+	.name			= "kirin",
+	.desc			= "Hisilicon Kirin SoCs' DRM Driver",
+	.date			= "20170309",
+	.major			= 1,
+	.minor			= 0,
+};
+
+#ifdef CONFIG_OF
+/* NOTE: the CONFIG_OF case duplicates the same code as exynos or imx
+ * (or probably any other).. so probably some room for some helpers
+ */
+static int compare_of(struct device *dev, void *data)
+{
+	return dev->of_node == data;
+}
+#else
+static int compare_dev(struct device *dev, void *data)
+{
+	return dev == data;
+}
+#endif
+
+static int kirin_drm_bind(struct device *dev)
+{
+	struct drm_driver *driver = &kirin_drm_driver;
+	struct drm_device *drm_dev;
+	int ret;
+
+	//drm_platform_init(&kirin_drm_driver, to_platform_device(dev));
+
+	drm_dev = drm_dev_alloc(driver, dev);
+	if (!drm_dev)
+		return -ENOMEM;
+
+	drm_dev->platformdev = to_platform_device(dev);
+
+	ret = kirin_drm_kms_init(drm_dev);
+	if (ret)
+		goto err_drm_dev_unref;
+
+	ret = drm_dev_register(drm_dev, 0);
+	if (ret)
+		goto err_kms_cleanup;
+
+	/* connectors should be registered after drm device register */
+	ret = kirin_drm_connectors_register(drm_dev);
+	if (ret)
+		goto err_drm_dev_unregister;
+
+	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
+		 driver->name, driver->major, driver->minor, driver->patchlevel,
+		 driver->date, drm_dev->primary->index);
+
+	return 0;
+
+err_drm_dev_unregister:
+	drm_dev_unregister(drm_dev);
+err_kms_cleanup:
+	kirin_drm_kms_cleanup(drm_dev);
+err_drm_dev_unref:
+	drm_dev_unref(drm_dev);
+
+	return ret;
+}
+
+static void kirin_drm_unbind(struct device *dev)
+{
+	drm_put_dev(dev_get_drvdata(dev));
+}
+
+static const struct component_master_ops kirin_drm_ops = {
+	.bind = kirin_drm_bind,
+	.unbind = kirin_drm_unbind,
+};
+
+static struct device_node *kirin_get_remote_node(struct device_node *np)
+{
+	struct device_node *endpoint, *remote;
+
+	/* get the first endpoint, in our case only one remote node
+	 * is connected to display controller.
+	 */
+	endpoint = of_graph_get_next_endpoint(np, NULL);
+	if (!endpoint) {
+		DRM_ERROR("no valid endpoint node\n");
+		return ERR_PTR(-ENODEV);
+	}
+	of_node_put(endpoint);
+
+	remote = of_graph_get_remote_port_parent(endpoint);
+	if (!remote) {
+		DRM_ERROR("no valid remote node\n");
+		return ERR_PTR(-ENODEV);
+	}
+	of_node_put(remote);
+
+	if (!of_device_is_available(remote)) {
+		DRM_ERROR("not available for remote node\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	return remote;
+}
+
+static int kirin_drm_platform_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct component_match *match = NULL;
+	struct device_node *remote;
+
+	dc_ops = (struct kirin_dc_ops *)of_device_get_match_data(dev);
+	if (!dc_ops) {
+		DRM_ERROR("failed to get dt id data\n");
+		return -EINVAL;
+	}
+
+	remote = kirin_get_remote_node(np);
+	if (IS_ERR(remote))
+		return PTR_ERR(remote);
+
+	component_match_add(dev, &match, compare_of, remote);
+
+	return component_master_add_with_match(dev, &kirin_drm_ops, match);
+
+	return 0;
+}
+
+static int kirin_drm_platform_remove(struct platform_device *pdev)
+{
+	component_master_del(&pdev->dev, &kirin_drm_ops);
+	dc_ops = NULL;
+	return 0;
+}
+
+static const struct of_device_id kirin_drm_dt_ids[] = {
+	{ .compatible = "hisilicon,hi3660-dpe",
+	  .data = &dss_dc_ops,
+	},
+	{ /* end node */ },
+};
+MODULE_DEVICE_TABLE(of, kirin_drm_dt_ids);
+
+static struct platform_driver kirin_drm_platform_driver = {
+	.probe = kirin_drm_platform_probe,
+	.remove = kirin_drm_platform_remove,
+	.driver = {
+		.name = "kirin-drm",
+		.of_match_table = kirin_drm_dt_ids,
+	},
+};
+
+module_platform_driver(kirin_drm_platform_driver);
+
+MODULE_AUTHOR("cailiwei <cailiwei@hisilicon.com>");
+MODULE_AUTHOR("zhengwanchun <zhengwanchun@hisilicon.com>");
+MODULE_DESCRIPTION("hisilicon Kirin SoCs' DRM master driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/hikey9xx/gpu/kirin_drm_drv.h b/drivers/staging/hikey9xx/gpu/kirin_drm_drv.h
new file mode 100644
index 000000000000..b361f5f69932
--- /dev/null
+++ b/drivers/staging/hikey9xx/gpu/kirin_drm_drv.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016 Linaro Limited.
+ * Copyright (c) 2014-2016 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __KIRIN_DRM_DRV_H__
+#define __KIRIN_DRM_DRV_H__
+
+#include <drm/drmP.h>
+#include <linux/ion.h>
+#include <linux/hisi/hisi_ion.h>
+#include <linux/hisi/hisi-iommu.h>
+
+#include "drm_crtc.h"
+#include "drm_fb_helper.h"
+
+#define MAX_CRTC	2
+
+#define to_kirin_fbdev(x) container_of(x, struct kirin_fbdev, fb_helper)
+
+/* display controller init/cleanup ops */
+struct kirin_dc_ops {
+	int (*init)(struct drm_device *dev);
+	void (*cleanup)(struct drm_device *dev);
+};
+
+struct kirin_drm_private {
+	struct drm_fb_helper *fb_helper;
+	struct drm_fb_helper *fbdev;
+	struct drm_crtc *crtc[MAX_CRTC];
+};
+
+struct kirin_fbdev {
+	struct drm_fb_helper fb_helper;
+	struct drm_framebuffer *fb;
+
+	struct ion_client *ion_client;
+	struct ion_handle *ion_handle;
+	struct iommu_map_format iommu_format;
+	void *screen_base;
+	unsigned long smem_start;
+	unsigned long screen_size;
+	int shared_fd;
+};
+
+extern const struct kirin_dc_ops dss_dc_ops;
+extern void dsi_set_output_client(struct drm_device *dev);
+
+struct drm_framebuffer *kirin_framebuffer_init(struct drm_device *dev,
+		struct drm_mode_fb_cmd2 *mode_cmd);
+struct drm_fb_helper *kirin_drm_fbdev_init(struct drm_device *dev);
+void kirin_drm_fbdev_fini(struct drm_device *dev);
+
+
+#endif /* __KIRIN_DRM_DRV_H__ */
diff --git a/drivers/staging/hikey9xx/gpu/kirin_drm_dss.c b/drivers/staging/hikey9xx/gpu/kirin_drm_dss.c
new file mode 100644
index 000000000000..2a92372d0c81
--- /dev/null
+++ b/drivers/staging/hikey9xx/gpu/kirin_drm_dss.c
@@ -0,0 +1,701 @@
+/*
+ * Hisilicon Hi6220 SoC ADE(Advanced Display Engine)'s crtc&plane driver
+ *
+ * Copyright (c) 2016 Linaro Limited.
+ * Copyright (c) 2014-2016 Hisilicon Limited.
+ *
+ * Author:
+ *	Xinliang Liu <z.liuxinliang@hisilicon.com>
+ *	Xinliang Liu <xinliang.liu@linaro.org>
+ *	Xinwei Kong <kong.kongxinwei@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <video/display_timing.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/of_address.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+
+#include "kirin_drm_drv.h"
+
+#include "kirin_drm_dpe_utils.h"
+#include "kirin_dpe_reg.h"
+
+#define DTS_COMP_DSS_NAME "hisilicon,hi3660-dpe"
+
+#define DSS_DEBUG	0
+
+static const struct dss_format dss_formats[] = {
+	/* 16bpp RGB: */
+	{ DRM_FORMAT_RGB565, HISI_FB_PIXEL_FORMAT_RGB_565 },
+	{ DRM_FORMAT_BGR565, HISI_FB_PIXEL_FORMAT_BGR_565 },
+	/* 32bpp [A]RGB: */
+	{ DRM_FORMAT_XRGB8888, HISI_FB_PIXEL_FORMAT_RGBX_8888 },
+	{ DRM_FORMAT_XBGR8888, HISI_FB_PIXEL_FORMAT_BGRX_8888 },
+	{ DRM_FORMAT_RGBA8888, HISI_FB_PIXEL_FORMAT_RGBA_8888 },
+	{ DRM_FORMAT_BGRA8888, HISI_FB_PIXEL_FORMAT_BGRA_8888 },
+	/*{ DRM_FORMAT_ARGB8888,  },*/
+	/*{ DRM_FORMAT_ABGR8888,  },*/
+};
+
+static const u32 channel_formats1[] = {
+	DRM_FORMAT_RGB565, DRM_FORMAT_BGR565,
+	DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_RGBA8888, DRM_FORMAT_BGRA8888
+};
+
+u32 dss_get_channel_formats(u8 ch, const u32 **formats)
+{
+	switch (ch) {
+	case DSS_CH1:
+		*formats = channel_formats1;
+		return ARRAY_SIZE(channel_formats1);
+	default:
+		DRM_ERROR("no this channel %d\n", ch);
+		*formats = NULL;
+		return 0;
+	}
+}
+
+/* convert from fourcc format to dss format */
+u32 dss_get_format(u32 pixel_format)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dss_formats); i++)
+		if (dss_formats[i].pixel_format == pixel_format)
+			return dss_formats[i].dss_format;
+
+	/* not found */
+	DRM_ERROR("Not found pixel format!!fourcc_format= %d\n",
+		  pixel_format);
+	return HISI_FB_PIXEL_FORMAT_UNSUPPORT;
+}
+
+/*******************************************************************************
+ **
+ */
+static void dss_ldi_set_mode(struct dss_crtc *acrtc)
+{
+	int ret;
+	u32 clk_Hz;
+	struct dss_hw_ctx *ctx = acrtc->ctx;
+	struct drm_display_mode *mode = &acrtc->base.state->mode;
+	struct drm_display_mode *adj_mode = &acrtc->base.state->adjusted_mode;
+
+
+	DRM_INFO("mode->clock(org) = %u\n", mode->clock);
+	if(mode->clock == 148500){
+		clk_Hz = 144000 * 1000UL;
+	} else if(mode->clock == 83496){
+		clk_Hz = 80000 * 1000UL;
+	} else if(mode->clock == 74440){
+		clk_Hz = 72000 * 1000UL;
+	} else if(mode->clock == 74250){
+		clk_Hz = 72000 * 1000UL;
+	} else {
+		clk_Hz = mode->clock * 1000UL;;
+	}
+
+	/*
+	 * Success should be guaranteed in mode_valid call back,
+	 * so failure shouldn't happen here
+	 */
+	ret = clk_set_rate(ctx->dss_pxl0_clk, clk_Hz);
+	if (ret) {
+		DRM_ERROR("failed to set pixel clk %dHz (%d)\n", clk_Hz, ret);
+	}
+	adj_mode->clock = clk_get_rate(ctx->dss_pxl0_clk) / 1000;
+	DRM_INFO("dss_pxl0_clk = %u\n",  adj_mode->clock);
+
+	dpe_init(acrtc);
+}
+
+static int dss_power_up(struct dss_crtc *acrtc)
+{
+	int ret;
+	struct dss_hw_ctx *ctx = acrtc->ctx;
+
+	ret = clk_prepare_enable(ctx->dss_pxl0_clk);
+	if (ret) {
+		DRM_ERROR("failed to enable dss_pxl0_clk (%d)\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(ctx->dss_pri_clk);
+	if (ret) {
+		DRM_ERROR("failed to enable dss_pri_clk (%d)\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(ctx->dss_pclk_dss_clk);
+	if (ret) {
+		DRM_ERROR("failed to enable dss_pclk_dss_clk (%d)\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(ctx->dss_axi_clk);
+	if (ret) {
+		DRM_ERROR("failed to enable dss_axi_clk (%d)\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(ctx->dss_mmbuf_clk);
+	if (ret) {
+		DRM_ERROR("failed to enable dss_mmbuf_clk (%d)\n", ret);
+		return ret;
+	}
+	dss_inner_clk_pdp_enable(acrtc);
+	dss_inner_clk_common_enable(acrtc);
+	dpe_interrupt_mask(acrtc);
+	dpe_interrupt_clear(acrtc);
+	dpe_irq_enable(acrtc);
+	dpe_interrupt_unmask(acrtc);
+
+	ctx->power_on = true;
+	return 0;
+}
+
+#if 0
+static void dss_power_down(struct dss_crtc *acrtc)
+{
+	struct dss_hw_ctx *ctx = acrtc->ctx;
+
+	dpe_interrupt_mask(acrtc);
+	dpe_irq_disable(acrtc);
+
+	ctx->power_on = false;
+}
+#endif
+
+static int dss_enable_vblank(struct drm_device *dev, unsigned int pipe)
+{
+	struct kirin_drm_private *priv = dev->dev_private;
+	struct dss_crtc *acrtc = to_dss_crtc(priv->crtc[pipe]);
+	struct dss_hw_ctx *ctx = acrtc->ctx;
+
+	if (!ctx->power_on)
+		(void)dss_power_up(acrtc);
+
+	return 0;
+}
+
+static void dss_disable_vblank(struct drm_device *dev, unsigned int pipe)
+{
+	struct kirin_drm_private *priv = dev->dev_private;
+	struct dss_crtc *acrtc = to_dss_crtc(priv->crtc[pipe]);
+	struct dss_hw_ctx *ctx = acrtc->ctx;
+
+	if (!ctx->power_on) {
+		DRM_ERROR("power is down! vblank disable fail\n");
+		return;
+	}
+}
+
+static irqreturn_t dss_irq_handler(int irq, void *data)
+{
+	struct dss_crtc *acrtc = data;
+	struct dss_hw_ctx *ctx = acrtc->ctx;
+	void __iomem *dss_base = ctx->base;
+
+	u32 isr_s1 = 0;
+	u32 isr_s2 = 0;
+	u32 isr_s2_dpp = 0;
+	u32 isr_s2_smmu = 0;
+	u32 mask = 0;
+
+	isr_s1 = inp32(dss_base + GLB_CPU_PDP_INTS);
+	isr_s2 = inp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS);
+	isr_s2_dpp = inp32(dss_base + DSS_DPP_OFFSET + DPP_INTS);
+	isr_s2_smmu = inp32(dss_base + DSS_SMMU_OFFSET + SMMU_INTSTAT_NS);
+
+	outp32(dss_base + DSS_SMMU_OFFSET + SMMU_INTCLR_NS, isr_s2_smmu);
+	outp32(dss_base + DSS_DPP_OFFSET + DPP_INTS, isr_s2_dpp);
+	outp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS, isr_s2);
+	outp32(dss_base + GLB_CPU_PDP_INTS, isr_s1);
+
+	isr_s1 &= ~(inp32(dss_base + GLB_CPU_PDP_INT_MSK));
+	isr_s2 &= ~(inp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK));
+	isr_s2_dpp &= ~(inp32(dss_base + DSS_DPP_OFFSET + DPP_INT_MSK));
+
+	if (isr_s2 & BIT_VACTIVE0_START) {
+		ctx->vactive0_start_flag++;
+		wake_up_interruptible_all(&ctx->vactive0_start_wq);
+	}
+
+	if (isr_s2 & BIT_VSYNC)
+		ctx->vsync_timestamp = ktime_get();
+
+	if (isr_s2 & BIT_LDI_UNFLOW) {
+		mask = inp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK);
+		mask |= BIT_LDI_UNFLOW;
+		outp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK, mask);
+
+		DRM_ERROR("ldi underflow!\n");
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void dss_crtc_enable(struct drm_crtc *crtc)
+{
+	struct dss_crtc *acrtc = to_dss_crtc(crtc);
+	struct dss_hw_ctx *ctx = acrtc->ctx;
+	int ret;
+
+	if (acrtc->enable)
+		return;
+
+	if (!ctx->power_on) {
+		ret = dss_power_up(acrtc);
+		if (ret)
+			return;
+	}
+
+	acrtc->enable = true;
+}
+
+static void dss_crtc_disable(struct drm_crtc *crtc)
+{
+	struct dss_crtc *acrtc = to_dss_crtc(crtc);
+
+	if (!acrtc->enable)
+		return;
+
+	/*dss_power_down(acrtc);*/
+	acrtc->enable = false;
+}
+
+static int dss_crtc_atomic_check(struct drm_crtc *crtc,
+				 struct drm_crtc_state *state)
+{
+	/* do nothing */
+	return 0;
+}
+
+static void dss_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	struct dss_crtc *acrtc = to_dss_crtc(crtc);
+	struct dss_hw_ctx *ctx = acrtc->ctx;
+
+	if (!ctx->power_on)
+		(void)dss_power_up(acrtc);
+	dss_ldi_set_mode(acrtc);
+}
+
+static void dss_crtc_atomic_begin(struct drm_crtc *crtc,
+				  struct drm_crtc_state *old_state)
+{
+	struct dss_crtc *acrtc = to_dss_crtc(crtc);
+	struct dss_hw_ctx *ctx = acrtc->ctx;
+
+	if (!ctx->power_on)
+		(void)dss_power_up(acrtc);
+}
+
+static void dss_crtc_atomic_flush(struct drm_crtc *crtc,
+				  struct drm_crtc_state *old_state)
+
+{
+
+}
+
+static const struct drm_crtc_helper_funcs dss_crtc_helper_funcs = {
+	.enable		= dss_crtc_enable,
+	.disable	= dss_crtc_disable,
+	.atomic_check	= dss_crtc_atomic_check,
+	.mode_set_nofb	= dss_crtc_mode_set_nofb,
+	.atomic_begin	= dss_crtc_atomic_begin,
+	.atomic_flush	= dss_crtc_atomic_flush,
+};
+
+static const struct drm_crtc_funcs dss_crtc_funcs = {
+	.destroy	= drm_crtc_cleanup,
+	.set_config	= drm_atomic_helper_set_config,
+	.page_flip	= drm_atomic_helper_page_flip,
+	.reset		= drm_atomic_helper_crtc_reset,
+	.set_property = drm_atomic_helper_crtc_set_property,
+	.atomic_duplicate_state	= drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_crtc_destroy_state,
+};
+
+static int dss_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
+			 struct drm_plane *plane)
+{
+	struct kirin_drm_private *priv = dev->dev_private;
+	struct device_node *port;
+	int ret;
+
+	/* set crtc port so that
+	 * drm_of_find_possible_crtcs call works
+	 */
+	port = of_get_child_by_name(dev->dev->of_node, "port");
+	if (!port) {
+		DRM_ERROR("no port node found in %s\n",
+			  dev->dev->of_node->full_name);
+		return -EINVAL;
+	}
+	of_node_put(port);
+	crtc->port = port;
+
+	ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
+					&dss_crtc_funcs);
+	if (ret) {
+		DRM_ERROR("failed to init crtc.\n");
+		return ret;
+	}
+
+	drm_crtc_helper_add(crtc, &dss_crtc_helper_funcs);
+	priv->crtc[drm_crtc_index(crtc)] = crtc;
+
+	return 0;
+}
+
+static int dss_plane_prepare_fb(struct drm_plane *plane,
+				const struct drm_plane_state *new_state)
+{
+	/* do nothing */
+	return 0;
+}
+
+static void dss_plane_cleanup_fb(struct drm_plane *plane,
+				 const struct drm_plane_state *old_state)
+{
+	/* do nothing */
+}
+
+static int dss_plane_atomic_check(struct drm_plane *plane,
+				  struct drm_plane_state *state)
+{
+	struct drm_framebuffer *fb = state->fb;
+	struct drm_crtc *crtc = state->crtc;
+	struct drm_crtc_state *crtc_state;
+	u32 src_x = state->src_x >> 16;
+	u32 src_y = state->src_y >> 16;
+	u32 src_w = state->src_w >> 16;
+	u32 src_h = state->src_h >> 16;
+	int crtc_x = state->crtc_x;
+	int crtc_y = state->crtc_y;
+	u32 crtc_w = state->crtc_w;
+	u32 crtc_h = state->crtc_h;
+	u32 fmt;
+
+	if (!crtc || !fb)
+		return 0;
+
+	fmt = dss_get_format(fb->pixel_format);
+	if (fmt == HISI_FB_PIXEL_FORMAT_UNSUPPORT)
+		return -EINVAL;
+
+	crtc_state = drm_atomic_get_crtc_state(state->state, crtc);
+	if (IS_ERR(crtc_state))
+		return PTR_ERR(crtc_state);
+
+	if (src_w != crtc_w || src_h != crtc_h) {
+		DRM_ERROR("Scale not support!!!\n");
+		return -EINVAL;
+	}
+
+	if (src_x + src_w > fb->width ||
+	    src_y + src_h > fb->height)
+		return -EINVAL;
+
+	if (crtc_x < 0 || crtc_y < 0)
+		return -EINVAL;
+
+	if (crtc_x + crtc_w > crtc_state->adjusted_mode.hdisplay ||
+	    crtc_y + crtc_h > crtc_state->adjusted_mode.vdisplay)
+		return -EINVAL;
+
+	return 0;
+}
+
+static void dss_plane_atomic_update(struct drm_plane *plane,
+				    struct drm_plane_state *old_state)
+{
+	hisi_fb_pan_display(plane);
+}
+
+static void dss_plane_atomic_disable(struct drm_plane *plane,
+				     struct drm_plane_state *old_state)
+{
+	//struct dss_plane *aplane = to_dss_plane(plane);
+}
+
+static const struct drm_plane_helper_funcs dss_plane_helper_funcs = {
+	.prepare_fb = dss_plane_prepare_fb,
+	.cleanup_fb = dss_plane_cleanup_fb,
+	.atomic_check = dss_plane_atomic_check,
+	.atomic_update = dss_plane_atomic_update,
+	.atomic_disable = dss_plane_atomic_disable,
+};
+
+static struct drm_plane_funcs dss_plane_funcs = {
+	.update_plane	= drm_atomic_helper_update_plane,
+	.disable_plane	= drm_atomic_helper_disable_plane,
+	.set_property = drm_atomic_helper_plane_set_property,
+	.destroy = drm_plane_cleanup,
+	.reset = drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
+static int dss_plane_init(struct drm_device *dev, struct dss_plane *aplane,
+			  enum drm_plane_type type)
+{
+	const u32 *fmts;
+	u32 fmts_cnt;
+	int ret = 0;
+
+	/* get properties */
+	fmts_cnt = dss_get_channel_formats(aplane->ch, &fmts);
+	if (ret)
+		return ret;
+
+	ret = drm_universal_plane_init(dev, &aplane->base, 1, &dss_plane_funcs,
+				       fmts, fmts_cnt, type);
+	if (ret) {
+		DRM_ERROR("fail to init plane, ch=%d\n", aplane->ch);
+		return ret;
+	}
+
+	drm_plane_helper_add(&aplane->base, &dss_plane_helper_funcs);
+
+	return 0;
+}
+
+static int dss_enable_iommu(struct platform_device *pdev, struct dss_hw_ctx *ctx)
+{
+	struct device *dev = NULL;
+
+	dev = &pdev->dev;
+
+	/* create iommu domain */
+	ctx->mmu_domain = iommu_domain_alloc(dev->bus);
+	if (!ctx->mmu_domain) {
+		pr_err("iommu_domain_alloc failed!\n");
+		return -EINVAL;
+	}
+
+	iommu_attach_device(ctx->mmu_domain, dev);
+
+	return 0;
+}
+
+static int dss_dts_parse(struct platform_device *pdev, struct dss_hw_ctx *ctx)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = NULL;
+	int ret = 0;
+
+	np = of_find_compatible_node(NULL, NULL, DTS_COMP_DSS_NAME);
+	if (!np) {
+			DRM_ERROR("NOT FOUND device node %s!\n",
+				    DTS_COMP_DSS_NAME);
+			return -ENXIO;
+	}
+
+	ctx->base = of_iomap(np, 0);
+	if (!(ctx->base)) {
+			DRM_ERROR ("failed to get ade base resource.\n");
+			return -ENXIO;
+	}
+
+	ctx->peri_crg_base  = of_iomap(np, 1);
+	if (!(ctx->peri_crg_base)) {
+			DRM_ERROR ("failed to get ade peri_crg_base  resource.\n");
+			return -ENXIO;
+	}
+
+	ctx->sctrl_base  = of_iomap(np, 2);
+	if (!(ctx->sctrl_base)) {
+			DRM_ERROR ("failed to get ade sctrl_base  resource.\n");
+			return -ENXIO;
+	}
+
+	ctx->pmc_base = of_iomap(np, 3);
+	if (!(ctx->pmc_base)) {
+			DRM_ERROR ("failed to get ade pmc_base   resource.\n");
+			return -ENXIO;
+	}
+
+	ctx->noc_dss_base = of_iomap(np, 4);
+	if (!(ctx->noc_dss_base)) {
+			DRM_ERROR ("failed to get noc_dss_base  resource.\n");
+			return -ENXIO;
+	}
+
+	/* get irq no */
+	ctx->irq = irq_of_parse_and_map(np, 0);
+	if (ctx->irq <= 0) {
+		DRM_ERROR("failed to get irq_pdp resource.\n");
+		return -ENXIO;
+	}
+
+	DRM_INFO("dss irq = %d.", ctx->irq);
+
+	ctx->dss_mmbuf_clk = devm_clk_get(dev, "clk_dss_axi_mm");
+	if (!ctx->dss_mmbuf_clk) {
+		DRM_ERROR("failed to parse dss_mmbuf_clk\n");
+	    return -ENODEV;
+	}
+
+	ctx->dss_axi_clk = devm_clk_get(dev, "aclk_dss");
+	if (!ctx->dss_axi_clk) {
+		DRM_ERROR("failed to parse dss_axi_clk\n");
+		return -ENODEV;
+	}
+
+	ctx->dss_pclk_dss_clk = devm_clk_get(dev, "pclk_dss");
+	if (!ctx->dss_pclk_dss_clk) {
+		DRM_ERROR("failed to parse dss_pclk_dss_clk\n");
+	    return -ENODEV;
+	}
+
+	ctx->dss_pri_clk = devm_clk_get(dev, "clk_edc0");
+	if (!ctx->dss_pri_clk) {
+		DRM_ERROR("failed to parse dss_pri_clk\n");
+	    return -ENODEV;
+	}
+
+	ret = clk_set_rate(ctx->dss_pri_clk, DEFAULT_DSS_CORE_CLK_07V_RATE);
+	if (ret < 0) {
+		DRM_ERROR("dss_pri_clk clk_set_rate(%lu) failed, error=%d!\n",
+			DEFAULT_DSS_CORE_CLK_07V_RATE, ret);
+		return -EINVAL;
+	}
+
+	DRM_INFO("dss_pri_clk:[%lu]->[%llu].\n",
+		DEFAULT_DSS_CORE_CLK_07V_RATE, (uint64_t)clk_get_rate(ctx->dss_pri_clk));
+
+	ctx->dss_pxl0_clk = devm_clk_get(dev, "clk_ldi0");
+	if (!ctx->dss_pxl0_clk) {
+		DRM_ERROR("failed to parse dss_pxl0_clk\n");
+		return -ENODEV;
+	}
+
+	ret = clk_set_rate(ctx->dss_pxl0_clk, DSS_MAX_PXL0_CLK_144M);
+	if (ret < 0) {
+		DRM_ERROR("dss_pxl0_clk clk_set_rate(%lu) failed, error=%d!\n",
+			DSS_MAX_PXL0_CLK_144M, ret);
+		return -EINVAL;
+	}
+
+	DRM_INFO("dss_pxl0_clk:[%lu]->[%llu].\n",
+		DSS_MAX_PXL0_CLK_144M, (uint64_t)clk_get_rate(ctx->dss_pxl0_clk));
+
+	/* regulator enable */
+
+	dss_enable_iommu(pdev, ctx);
+
+	return 0;
+}
+
+static int dss_drm_init(struct drm_device *dev)
+{
+	struct platform_device *pdev = dev->platformdev;
+	struct dss_data *dss;
+	struct dss_hw_ctx *ctx;
+	struct dss_crtc *acrtc;
+	struct dss_plane *aplane;
+	enum drm_plane_type type;
+	int ret;
+	int i;
+
+	dss = devm_kzalloc(dev->dev, sizeof(*dss), GFP_KERNEL);
+	if (!dss) {
+		DRM_ERROR("failed to alloc dss_data\n");
+		return -ENOMEM;
+	}
+	platform_set_drvdata(pdev, dss);
+
+	ctx = &dss->ctx;
+	acrtc = &dss->acrtc;
+	acrtc->ctx = ctx;
+	acrtc->out_format = LCD_RGB888;
+	acrtc->bgr_fmt = LCD_RGB;
+
+	ret = dss_dts_parse(pdev, ctx);
+	if (ret)
+		return ret;
+
+	ctx->ion_client = NULL;
+	ctx->ion_handle = NULL;
+	ctx->screen_base = 0;
+	ctx->screen_size = 0;
+	ctx->smem_start = 0;
+
+	ctx->vactive0_start_flag = 0;
+	init_waitqueue_head(&ctx->vactive0_start_wq);
+
+	/*
+	 * plane init
+	 * TODO: Now only support primary plane, overlay planes
+	 * need to do.
+	 */
+	for (i = 0; i < DSS_CH_NUM; i++) {
+		aplane = &dss->aplane[i];
+		aplane->ch = i;
+		/*aplane->ctx = ctx;*/
+		aplane->acrtc = acrtc;
+		type = i == PRIMARY_CH ? DRM_PLANE_TYPE_PRIMARY :
+			DRM_PLANE_TYPE_OVERLAY;
+
+		ret = dss_plane_init(dev, aplane, type);
+		if (ret)
+			return ret;
+	}
+
+	/* crtc init */
+	ret = dss_crtc_init(dev, &acrtc->base, &dss->aplane[PRIMARY_CH].base);
+	if (ret)
+		return ret;
+
+	/* vblank irq init */
+	ret = devm_request_irq(dev->dev, ctx->irq, dss_irq_handler,
+			       IRQF_SHARED, dev->driver->name, acrtc);
+	if (ret) {
+	    DRM_ERROR("fail to  devm_request_irq, ret=%d!", ret);
+		return ret;
+	}
+
+	disable_irq(ctx->irq);
+
+	dev->driver->get_vblank_counter = drm_vblank_no_hw_counter;
+	dev->driver->enable_vblank = dss_enable_vblank;
+	dev->driver->disable_vblank = dss_disable_vblank;
+
+	return 0;
+}
+
+static void dss_drm_cleanup(struct drm_device *dev)
+{
+	struct platform_device *pdev = dev->platformdev;
+	struct dss_data *dss = platform_get_drvdata(pdev);
+	struct drm_crtc *crtc = &dss->acrtc.base;
+
+	drm_crtc_cleanup(crtc);
+}
+
+const struct kirin_dc_ops dss_dc_ops = {
+	.init = dss_drm_init,
+	.cleanup = dss_drm_cleanup
+};
diff --git a/drivers/staging/hikey9xx/gpu/kirin_drm_overlay_utils.c b/drivers/staging/hikey9xx/gpu/kirin_drm_overlay_utils.c
new file mode 100644
index 000000000000..98ab748b8d8e
--- /dev/null
+++ b/drivers/staging/hikey9xx/gpu/kirin_drm_overlay_utils.c
@@ -0,0 +1,1288 @@
+/* Copyright (c) 2008-2011, 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+
+#include "kirin_drm_dpe_utils.h"
+#include "kirin_drm_drv.h"
+
+
+#define DSS_CHN_MAX_DEFINE (DSS_COPYBIT_MAX)
+
+static int mid_array[DSS_CHN_MAX_DEFINE] = {0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x2, 0x1, 0x3, 0x0};
+
+/*
+** dss_chn_idx
+** 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_RCHN_V2,   DSS_WCHN_W2,
+*/
+/*lint -e785*/
+u32 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,
+	},
+};
+
+/*lint +e785*/
+u32 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},
+};
+
+/*SCF_LUT_CHN coef_idx*/
+int g_scf_lut_chn_coef_idx[DSS_CHN_MAX_DEFINE] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+
+u32 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 */
+u32 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]) */
+u32 g_dss_smmu_smrx_idx[DSS_CHN_MAX_DEFINE] = {
+	0, 4, 5, 9, 13, 17, 21, 22, 26, 29, 23, 32
+};
+u32 g_dss_mif_sid_map[DSS_CHN_MAX] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+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:
+		DRM_ERROR("not support format(%d)!\n", format);
+		ret = -1;
+		break;
+	}
+
+	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:
+		DRM_ERROR("not support format(%d)!\n", format);
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int hisi_dss_aif_ch_config(struct dss_hw_ctx *ctx, int chn_idx)
+{
+	void __iomem *aif0_ch_base;
+	int mid = 0;
+
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return -1;
+	}
+
+	mid = mid_array[chn_idx];
+	aif0_ch_base = ctx->base + g_dss_module_base[chn_idx][MODULE_AIF0_CHN];
+
+	set_reg(aif0_ch_base, 0x0, 1, 0);
+	set_reg(aif0_ch_base, (uint32_t)mid, 4, 4);
+
+	return 0;
+}
+
+static int hisi_dss_smmu_config(struct dss_hw_ctx *ctx, int chn_idx, bool mmu_enable)
+{
+	void __iomem *smmu_base;
+	u32 idx = 0, i = 0;
+
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return -1;
+	}
+
+	smmu_base = ctx->base + DSS_SMMU_OFFSET;
+
+	for (i = 0; i < g_dss_chn_sid_num[chn_idx]; i++) {
+		idx = g_dss_smmu_smrx_idx[chn_idx] + i;
+		if (!mmu_enable)
+			set_reg(smmu_base + SMMU_SMRx_NS + idx * 0x4, 1, 32, 0);
+		else
+			set_reg(smmu_base + SMMU_SMRx_NS + idx * 0x4, 0x70, 32, 0);
+	}
+
+	return 0;
+}
+
+static int hisi_dss_mif_config(struct dss_hw_ctx *ctx, int chn_idx, bool mmu_enable)
+{
+	void __iomem *mif_base;
+	void __iomem *mif_ch_base;
+
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return -1;
+	}
+
+	mif_base = ctx->base + DSS_MIF_OFFSET;
+	mif_ch_base = ctx->base +
+		g_dss_module_base[chn_idx][MODULE_MIF_CHN];
+
+	if (!mmu_enable) {
+		set_reg(mif_ch_base + MIF_CTRL1, 0x1, 1, 5);
+	} else  {
+		set_reg(mif_ch_base + MIF_CTRL1, 0x00080000, 32, 0);
+	}
+
+	return 0;
+}
+
+int hisi_dss_mctl_mutex_lock(struct dss_hw_ctx *ctx)
+{
+	void __iomem *mctl_base;
+
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return -1;
+	}
+
+	mctl_base = ctx->base +
+		g_dss_module_ovl_base[DSS_OVL0][MODULE_MCTL_BASE];
+
+	set_reg(mctl_base + MCTL_CTL_MUTEX, 0x1, 1, 0);
+
+	return 0;
+}
+
+int hisi_dss_mctl_mutex_unlock(struct dss_hw_ctx *ctx)
+{
+	void __iomem *mctl_base;
+
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return -1;
+	}
+
+	mctl_base = ctx->base +
+		g_dss_module_ovl_base[DSS_OVL0][MODULE_MCTL_BASE];
+
+	set_reg(mctl_base + MCTL_CTL_MUTEX, 0x0, 1, 0);
+
+	return 0;
+}
+
+static int hisi_dss_mctl_ov_config(struct dss_hw_ctx *ctx, int chn_idx)
+{
+	void __iomem *mctl_base;
+	u32 mctl_rch_offset = 0;
+
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return -1;
+	}
+
+	mctl_rch_offset = (uint32_t)(MCTL_CTL_MUTEX_RCH0 + chn_idx * 0x4);
+
+	mctl_base = ctx->base +
+		g_dss_module_ovl_base[DSS_OVL0][MODULE_MCTL_BASE];
+
+	set_reg(mctl_base + MCTL_CTL_EN, 0x1, 32, 0);
+	set_reg(mctl_base + MCTL_CTL_TOP, 0x2, 32, 0); /*auto mode*/
+	set_reg(mctl_base + MCTL_CTL_DBG, 0xB13A00, 32, 0);
+
+	set_reg(mctl_base + mctl_rch_offset, 0x1, 32, 0);
+	set_reg(mctl_base + MCTL_CTL_MUTEX_ITF, 0x1, 2, 0);
+	set_reg(mctl_base + MCTL_CTL_MUTEX_DBUF, 0x1, 2, 0);
+	set_reg(mctl_base + MCTL_CTL_MUTEX_OV, 1 << DSS_OVL0, 4, 0);
+
+	return 0;
+}
+
+static int hisi_dss_mctl_sys_config(struct dss_hw_ctx *ctx, int chn_idx)
+{
+	void __iomem *mctl_sys_base;
+
+	u32 layer_idx = 0;
+	u32 mctl_rch_ov_oen_offset = 0;
+	u32 mctl_rch_flush_en_offset = 0;
+
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return -1;
+	}
+
+	mctl_sys_base = ctx->base + DSS_MCTRL_SYS_OFFSET;
+	mctl_rch_ov_oen_offset = MCTL_RCH0_OV_OEN + chn_idx * 0x4;
+	mctl_rch_flush_en_offset = MCTL_RCH0_FLUSH_EN + chn_idx * 0x4;
+
+	set_reg(mctl_sys_base + mctl_rch_ov_oen_offset,
+		((1 << (layer_idx + 1)) | (0x100 << DSS_OVL0)), 32, 0);
+
+	set_reg(mctl_sys_base + MCTL_RCH_OV0_SEL, 0x8, 4, 0);
+
+	set_reg(mctl_sys_base + MCTL_RCH_OV0_SEL, chn_idx, 4, (layer_idx + 1) * 4);
+
+	set_reg(mctl_sys_base + MCTL_OV0_FLUSH_EN, 0xd, 4, 0);
+	set_reg(mctl_sys_base + mctl_rch_flush_en_offset, 0x1, 32, 0);
+
+	return 0;
+}
+
+static int hisi_dss_rdma_config(struct dss_hw_ctx *ctx,
+	const dss_rect_ltrb_t *rect, u32 display_addr, u32 hal_format,
+	u32 bpp, int chn_idx, bool afbcd, bool mmu_enable)
+{
+	void __iomem *rdma_base;
+
+	u32 aligned_pixel = 0;
+	u32 rdma_oft_x0 = 0;
+	u32 rdma_oft_y0 = 0;
+	u32 rdma_oft_x1 = 0;
+	u32 rdma_oft_y1 = 0;
+	u32 rdma_stride = 0;
+	u32 rdma_bpp = 0;
+	u32 rdma_format = 0;
+	u32 stretch_size_vrt = 0;
+
+	u32 stride_align = 0;
+	u32 mm_base_0 = 0;
+	u32 mm_base_1 = 0;
+
+	u32 afbcd_header_addr = 0;
+	u32 afbcd_header_stride = 0;
+	u32 afbcd_payload_addr = 0;
+	u32 afbcd_payload_stride = 0;
+
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return -1;
+	}
+
+	if (bpp == 4) {
+		rdma_bpp = 0x5;
+	} else if (bpp == 2) {
+		rdma_bpp = 0x0;
+	} else {
+		rdma_bpp = 0x0;
+	}
+
+	rdma_base = ctx->base +
+		g_dss_module_base[chn_idx][MODULE_DMA];
+
+	aligned_pixel = DMA_ALIGN_BYTES / bpp;
+	rdma_oft_x0 = rect->left / aligned_pixel;
+	rdma_oft_y0 = rect->top;
+	rdma_oft_x1 = rect->right / aligned_pixel;
+	rdma_oft_y1 = rect->bottom;
+
+	rdma_format = hisi_pixel_format_hal2dma(hal_format);
+	if (rdma_format < 0) {
+		DRM_ERROR("layer format(%d) not support !\n", hal_format);
+		return -EINVAL;
+	}
+
+	if (afbcd) {
+		mm_base_0 = 0;
+		mm_base_1 = mm_base_0 + rect->right * bpp * MMBUF_LINE_NUM;
+		mm_base_0 = ALIGN_UP(mm_base_0, MMBUF_ADDR_ALIGN);
+		mm_base_1 = ALIGN_UP(mm_base_1, MMBUF_ADDR_ALIGN);
+
+		if ((((rect->right - rect->left) + 1) & (AFBC_HEADER_ADDR_ALIGN - 1)) ||
+				(((rect->bottom - rect->top) + 1) & (AFBC_BLOCK_ALIGN - 1))) {
+			DRM_ERROR("img width(%d) is not %d bytes aligned, or "
+					"img heigh(%d) is not %d bytes aligned!\n",
+					((rect->right - rect->left) + 1), AFBC_HEADER_ADDR_ALIGN,
+					((rect->bottom - rect->top) + 1), AFBC_BLOCK_ALIGN);
+		}
+
+		if ((mm_base_0 & (MMBUF_ADDR_ALIGN - 1)) || (mm_base_1 & (MMBUF_ADDR_ALIGN - 1))) {
+			DRM_ERROR("mm_base_0(0x%x) is not %d bytes aligned, or "
+					"mm_base_1(0x%x) is not %d bytes aligned!\n",
+					mm_base_0, MMBUF_ADDR_ALIGN,
+					mm_base_1, MMBUF_ADDR_ALIGN);
+		}
+		/*header*/
+		afbcd_header_stride = (((rect->right - rect->left) + 1) / AFBC_BLOCK_ALIGN) * AFBC_HEADER_STRIDE_BLOCK;
+		afbcd_header_addr = (uint32_t)(unsigned long)display_addr;
+
+		/*payload*/
+		if (bpp == 4)
+			stride_align = AFBC_PAYLOAD_STRIDE_ALIGN_32;
+		else if (bpp == 2)
+			stride_align = AFBC_PAYLOAD_STRIDE_ALIGN_16;
+		else
+			DRM_ERROR("bpp(%d) not supported!\n", bpp);
+
+		afbcd_payload_stride = (((rect->right - rect->left) + 1) / AFBC_BLOCK_ALIGN) * stride_align;
+
+		afbcd_payload_addr = afbcd_header_addr + ALIGN_UP(16 * (((rect->right - rect->left) + 1) / 16) *
+				(((rect->bottom - rect->top) + 1) / 16), 1024);
+		afbcd_payload_addr = afbcd_payload_addr +
+			(rect->top / AFBC_BLOCK_ALIGN) * afbcd_payload_stride +
+			(rect->left / AFBC_BLOCK_ALIGN) * stride_align;
+
+		set_reg(rdma_base + CH_REG_DEFAULT, 0x1, 32, 0);
+		set_reg(rdma_base + CH_REG_DEFAULT, 0x0, 32, 0);
+		set_reg(rdma_base + DMA_OFT_X0, rdma_oft_x0, 12, 0);
+		set_reg(rdma_base + DMA_OFT_Y0, rdma_oft_y0, 16, 0);
+		set_reg(rdma_base + DMA_OFT_X1, rdma_oft_x1, 12, 0);
+		set_reg(rdma_base + DMA_OFT_Y1, rdma_oft_y1, 16, 0);
+		set_reg(rdma_base + DMA_STRETCH_SIZE_VRT, (rect->bottom - rect->top), 13, 0);
+		set_reg(rdma_base + DMA_CTRL, rdma_format, 5, 3);
+		set_reg(rdma_base + DMA_CTRL, (mmu_enable ? 0x1 : 0x0), 1, 8);
+
+		set_reg(rdma_base + AFBCD_HREG_PIC_WIDTH, (rect->right - rect->left), 16, 0);
+		set_reg(rdma_base + AFBCD_HREG_PIC_HEIGHT, (rect->bottom - rect->top), 16, 0);
+		set_reg(rdma_base + AFBCD_CTL, AFBC_HALF_BLOCK_UPPER_LOWER_ALL, 2, 6);
+		set_reg(rdma_base + AFBCD_HREG_HDR_PTR_LO, afbcd_header_addr, 32, 0);
+		set_reg(rdma_base + AFBCD_INPUT_HEADER_STRIDE, afbcd_header_stride, 14, 0);
+		set_reg(rdma_base + AFBCD_PAYLOAD_STRIDE, afbcd_payload_stride, 20, 0);
+		set_reg(rdma_base + AFBCD_MM_BASE_0, mm_base_0, 32, 0);
+		set_reg(rdma_base + AFBCD_HREG_FORMAT, 0x1, 1, 21);
+		set_reg(rdma_base + AFBCD_SCRAMBLE_MODE, 0x0, 32, 0);
+		set_reg(rdma_base + AFBCD_AFBCD_PAYLOAD_POINTER, afbcd_payload_addr, 32, 0);
+		set_reg(rdma_base + AFBCD_HEIGHT_BF_STR, (rect->bottom - rect->top), 16, 0);
+
+		set_reg(rdma_base + CH_CTL, 0xf005, 32, 0);
+	} else {
+		stretch_size_vrt = rdma_oft_y1 - rdma_oft_y0;
+		rdma_stride = ((rect->right - rect->left) + 1) * bpp / DMA_ALIGN_BYTES;
+
+		set_reg(rdma_base + CH_REG_DEFAULT, 0x1, 32, 0);
+		set_reg(rdma_base + CH_REG_DEFAULT, 0x0, 32, 0);
+
+		set_reg(rdma_base + DMA_OFT_X0, rdma_oft_x0, 12, 0);
+		set_reg(rdma_base + DMA_OFT_Y0, rdma_oft_y0, 16, 0);
+		set_reg(rdma_base + DMA_OFT_X1, rdma_oft_x1, 12, 0);
+		set_reg(rdma_base + DMA_OFT_Y1, rdma_oft_y1, 16, 0);
+		set_reg(rdma_base + DMA_CTRL, rdma_format, 5, 3);
+		set_reg(rdma_base + DMA_CTRL, (mmu_enable ? 0x1 : 0x0), 1, 8);
+		set_reg(rdma_base + DMA_STRETCH_SIZE_VRT, stretch_size_vrt, 32, 0);
+		set_reg(rdma_base + DMA_DATA_ADDR0, display_addr, 32, 0);
+		set_reg(rdma_base + DMA_STRIDE0, rdma_stride, 13, 0);
+
+		set_reg(rdma_base + CH_CTL, 0x1, 1, 0);
+	}
+
+	return 0;
+}
+
+static int hisi_dss_rdfc_config(struct dss_hw_ctx *ctx,
+	const dss_rect_ltrb_t *rect, u32 hal_format, u32 bpp, int chn_idx)
+{
+	void __iomem *rdfc_base;
+
+	u32 dfc_pix_in_num = 0;
+	u32 size_hrz = 0;
+	u32 size_vrt = 0;
+	u32 dfc_fmt = 0;
+
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return -1;
+	}
+
+	rdfc_base = ctx->base +
+		g_dss_module_base[chn_idx][MODULE_DFC];
+
+	dfc_pix_in_num = (bpp <= 2) ? 0x1 : 0x0;
+	size_hrz = rect->right - rect->left;
+	size_vrt = rect->bottom - rect->top;
+
+	dfc_fmt = hisi_pixel_format_hal2dfc(hal_format);
+	if (dfc_fmt < 0) {
+		DRM_ERROR("layer format (%d) not support !\n", hal_format);
+		return -EINVAL;
+	}
+
+	set_reg(rdfc_base + DFC_DISP_SIZE, (size_vrt | (size_hrz << 16)), 29, 0);
+	set_reg(rdfc_base + DFC_PIX_IN_NUM, dfc_pix_in_num, 1, 0);
+	//set_reg(rdfc_base + DFC_DISP_FMT, (bpp <= 2) ? 0x0 : 0x6, 5, 1);
+	set_reg(rdfc_base + DFC_DISP_FMT, dfc_fmt, 5, 1);
+	set_reg(rdfc_base + DFC_CTL_CLIP_EN, 0x1, 1, 0);
+	set_reg(rdfc_base + DFC_ICG_MODULE, 0x1, 1, 0);
+
+	return 0;
+}
+
+int hisi_dss_ovl_base_config(struct dss_hw_ctx *ctx, u32 xres, u32 yres)
+{
+	void __iomem *mctl_sys_base;
+	void __iomem *mctl_base;
+	void __iomem *ovl0_base;
+
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return -1;
+	}
+
+	mctl_sys_base = ctx->base + DSS_MCTRL_SYS_OFFSET;
+	mctl_base = ctx->base +
+		g_dss_module_ovl_base[DSS_OVL0][MODULE_MCTL_BASE];
+	ovl0_base = ctx->base +
+		g_dss_module_ovl_base[DSS_OVL0][MODULE_OVL_BASE];
+
+	set_reg(ovl0_base + OVL6_REG_DEFAULT, 0x1, 32, 0);
+	set_reg(ovl0_base + OVL6_REG_DEFAULT, 0x0, 32, 0);
+
+	set_reg(ovl0_base + OVL_SIZE, (xres - 1) | ((yres - 1) << 16), 32, 0);
+#ifdef CONFIG_HISI_FB_OV_BASE_USED
+	set_reg(ovl0_base + OVL_BG_COLOR, 0xFFFF0000, 32, 0);
+#else
+	set_reg(ovl0_base + OVL_BG_COLOR, 0xFF000000, 32, 0);
+#endif
+	set_reg(ovl0_base + OVL_DST_STARTPOS, 0x0, 32, 0);
+	set_reg(ovl0_base + OVL_DST_ENDPOS, (xres - 1) | ((yres - 1) << 16), 32, 0);
+	set_reg(ovl0_base + OVL_GCFG, 0x10001, 32, 0);
+
+	set_reg(mctl_base + MCTL_CTL_MUTEX_ITF, 0x1, 32, 0);
+	set_reg(mctl_base + MCTL_CTL_MUTEX_DBUF, 0x1, 2, 0);
+	set_reg(mctl_base + MCTL_CTL_MUTEX_OV, 1 << DSS_OVL0, 4, 0);
+
+	set_reg(mctl_sys_base + MCTL_RCH_OV0_SEL, 0x8, 4, 0);
+	set_reg(mctl_sys_base + MCTL_OV0_FLUSH_EN, 0xd, 4, 0);
+
+	return 0;
+}
+
+static int hisi_dss_ovl_config(struct dss_hw_ctx *ctx,
+	const dss_rect_ltrb_t *rect, u32 xres, u32 yres)
+{
+	void __iomem *ovl0_base;
+
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return -1;
+	}
+
+	ovl0_base = ctx->base +
+		g_dss_module_ovl_base[DSS_OVL0][MODULE_OVL_BASE];
+
+	set_reg(ovl0_base + OVL6_REG_DEFAULT, 0x1, 32, 0);
+	set_reg(ovl0_base + OVL6_REG_DEFAULT, 0x0, 32, 0);
+	set_reg(ovl0_base + OVL_SIZE, (xres - 1) |
+		((yres - 1) << 16), 32, 0);
+	set_reg(ovl0_base + OVL_BG_COLOR, 0xFF000000, 32, 0);
+	set_reg(ovl0_base + OVL_DST_STARTPOS, 0x0, 32, 0);
+	set_reg(ovl0_base + OVL_DST_ENDPOS, (xres - 1) |
+		((yres - 1) << 16), 32, 0);
+	set_reg(ovl0_base + OVL_GCFG, 0x10001, 32, 0);
+	set_reg(ovl0_base + OVL_LAYER0_POS, (rect->left) |
+		((rect->top) << 16), 32, 0);
+	set_reg(ovl0_base + OVL_LAYER0_SIZE, (rect->right) |
+		((rect->bottom) << 16), 32, 0);
+	set_reg(ovl0_base + OVL_LAYER0_ALPHA, 0x00ff40ff, 32, 0);
+	set_reg(ovl0_base + OVL_LAYER0_CFG, 0x1, 1, 0);
+
+	return 0;
+}
+
+static void hisi_dss_qos_on(struct dss_hw_ctx *ctx)
+{
+	char __iomem *noc_dss_base;
+
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return;
+	}
+
+	noc_dss_base = ctx->noc_dss_base;
+
+	outp32(noc_dss_base + 0xc, 0x2);
+	outp32(noc_dss_base + 0x8c, 0x2);
+	outp32(noc_dss_base + 0x10c, 0x2);
+	outp32(noc_dss_base + 0x18c, 0x2);
+}
+
+static void hisi_dss_mif_on(struct dss_hw_ctx *ctx)
+{
+	char __iomem *dss_base;
+	char __iomem *mif_base;
+
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return;
+	}
+
+	dss_base = ctx->base;
+	mif_base = ctx->base + DSS_MIF_OFFSET;
+
+	set_reg(mif_base + MIF_ENABLE, 0x1, 1, 0);
+	set_reg(dss_base + MIF_CH0_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+	set_reg(dss_base + MIF_CH1_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+	set_reg(dss_base + MIF_CH2_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+	set_reg(dss_base + MIF_CH3_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+	set_reg(dss_base + MIF_CH4_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+	set_reg(dss_base + MIF_CH5_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+	set_reg(dss_base + MIF_CH6_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+	set_reg(dss_base + MIF_CH7_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+	set_reg(dss_base + MIF_CH8_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+	set_reg(dss_base + MIF_CH9_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+
+	set_reg(dss_base + MIF_CH10_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+	set_reg(dss_base + MIF_CH11_OFFSET + MIF_CTRL0, 0x1, 1, 0);
+}
+
+void hisi_dss_smmu_on(struct dss_hw_ctx *ctx)
+{
+	void __iomem *smmu_base;
+	struct iommu_domain_data *domain_data = NULL;
+	uint32_t phy_pgd_base = 0;
+
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return;
+	}
+
+	smmu_base = ctx->base + DSS_SMMU_OFFSET;
+
+	set_reg(smmu_base + SMMU_SCR, 0x0, 1, 0);  /*global bypass cancel*/
+	set_reg(smmu_base + SMMU_SCR, 0x1, 8, 20); /*ptw_mid*/
+	set_reg(smmu_base + SMMU_SCR, 0xf, 4, 16); /*pwt_pf*/
+	set_reg(smmu_base + SMMU_SCR, 0x7, 3, 3);  /*interrupt cachel1 cach3l2 en*/
+	set_reg(smmu_base + SMMU_LP_CTRL, 0x1, 1, 0);  /*auto_clk_gt_en*/
+
+	/*Long Descriptor*/
+	set_reg(smmu_base + SMMU_CB_TTBCR, 0x1, 1, 0);
+
+	set_reg(smmu_base + SMMU_ERR_RDADDR, 0x7FF00000, 32, 0);
+	set_reg(smmu_base + SMMU_ERR_WRADDR, 0x7FFF0000, 32, 0);
+
+	/*disable cmdlist, dbg, reload*/
+	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);
+
+	/*cmdlist stream bypass*/
+	set_reg(smmu_base + SMMU_SMRx_NS + 36 * 0x4, 0x1, 32, 0); /*debug stream id*/
+	set_reg(smmu_base + SMMU_SMRx_NS + 37 * 0x4, 0x1, 32, 0); /*cmd unsec stream id*/
+	set_reg(smmu_base + SMMU_SMRx_NS + 38 * 0x4, 0x1, 32, 0); /*cmd sec stream id*/
+
+	/*TTBR0*/
+	domain_data = (struct iommu_domain_data *)(ctx->mmu_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 hisifb_dss_on(struct dss_hw_ctx *ctx)
+{
+	/* dss qos on*/
+	hisi_dss_qos_on(ctx);
+	/* mif on*/
+	hisi_dss_mif_on(ctx);
+	/* smmu on*/
+	hisi_dss_smmu_on(ctx);
+}
+
+void hisi_dss_mctl_on(struct dss_hw_ctx *ctx)
+{
+	char __iomem *mctl_base = NULL;
+	char __iomem *mctl_sys_base = NULL;
+
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return;
+	}
+	mctl_base = ctx->base +
+		g_dss_module_ovl_base[DSS_MCTL0][MODULE_MCTL_BASE];
+	mctl_sys_base = ctx->base + DSS_MCTRL_SYS_OFFSET;
+
+	set_reg(mctl_base + MCTL_CTL_EN, 0x1, 32, 0);
+	set_reg(mctl_base + MCTL_CTL_MUTEX_ITF, 0x1, 32, 0);
+	set_reg(mctl_base + MCTL_CTL_DBG, 0xB13A00, 32, 0);
+	set_reg(mctl_base + MCTL_CTL_TOP, 0x2, 32, 0);
+}
+
+void hisi_dss_unflow_handler(struct dss_hw_ctx *ctx, bool unmask)
+{
+	void __iomem *dss_base;
+	u32 tmp = 0;
+
+	if (!ctx) {
+		DRM_ERROR("ctx is NULL!\n");
+		return;
+	}
+
+	dss_base = ctx->base;
+
+	tmp = inp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK);
+	if (unmask)
+		tmp &= ~BIT_LDI_UNFLOW;
+	else
+		tmp |= BIT_LDI_UNFLOW;
+
+	outp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK, tmp);
+}
+
+static int hisi_vactive0_start_config(struct dss_hw_ctx *ctx)
+{
+	int ret = 0;
+	u32 times = 0;
+	u32 prev_vactive0_start = 0;
+
+	prev_vactive0_start = ctx->vactive0_start_flag;
+
+REDO:
+	ret = wait_event_interruptible_timeout(ctx->vactive0_start_wq,
+		(prev_vactive0_start != ctx->vactive0_start_flag),
+		msecs_to_jiffies(300));
+	if (ret == -ERESTARTSYS) {
+		if (times < 50) {
+			times++;
+			mdelay(10);
+			goto REDO;
+		}
+	}
+
+	if (ret <= 0) {
+		DRM_ERROR("wait_for vactive0_start_flag timeout! ret=%d.\n", ret);
+
+		ret = -ETIMEDOUT;
+	} else {
+		ret = 0;
+	}
+
+	return ret;
+}
+
+void hisi_fb_pan_display(struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = state->fb;
+	struct drm_display_mode *mode;
+	struct drm_display_mode *adj_mode;
+
+	struct dss_plane *aplane = to_dss_plane(plane);
+	struct dss_crtc *acrtc = aplane->acrtc;
+	struct dss_hw_ctx *ctx = acrtc->ctx;
+
+	struct kirin_drm_private *priv = plane->dev->dev_private;
+	struct kirin_fbdev *fbdev = to_kirin_fbdev(priv->fbdev);
+
+	ktime_t prepare_timestamp;
+	u64 vsync_timediff;
+
+	bool afbcd = false;
+	bool mmu_enable = true;
+	dss_rect_ltrb_t rect;
+	u32 bpp;
+	u32 stride;
+	u32 display_addr;
+	u32 hal_fmt;
+	int chn_idx = DSS_RCHN_D2;
+
+	int crtc_x = state->crtc_x;
+	int crtc_y = state->crtc_y;
+	unsigned int crtc_w = state->crtc_w;
+	unsigned int crtc_h = state->crtc_h;
+	u32 src_x = state->src_x >> 16;
+	u32 src_y = state->src_y >> 16;
+	u32 src_w = state->src_w >> 16;
+	u32 src_h = state->src_h >> 16;
+
+	u32 hfp, hbp, hsw, vfp, vbp, vsw;
+
+	mode = &acrtc->base.state->mode;
+	adj_mode = &acrtc->base.state->adjusted_mode;
+
+	bpp = fb->bits_per_pixel / 8;
+	stride = fb->pitches[0];
+
+	display_addr = (u32)fbdev->smem_start + src_y * stride;
+
+	rect.left = 0;
+	rect.right = src_w - 1;
+	rect.top = 0;
+	rect.bottom = src_h - 1;
+	hal_fmt = dss_get_format(fb->pixel_format);
+
+	DRM_DEBUG("channel%d: src:(%d,%d, %dx%d) crtc:(%d,%d, %dx%d), rect(%d,%d,%d,%d),"
+		"fb:%dx%d, pixel_format=%d, stride=%d, paddr=0x%x, bpp=%d, bits_per_pixel=%d.\n",
+		chn_idx, src_x, src_y, src_w, src_h,
+		crtc_x, crtc_y, crtc_w, crtc_h,
+		rect.left, rect.top, rect.right, rect.bottom,
+		fb->width, fb->height, hal_fmt,
+		stride, display_addr, bpp, fb->bits_per_pixel);
+
+	hfp = mode->hsync_start - mode->hdisplay;
+	hbp = mode->htotal - mode->hsync_end;
+	hsw = mode->hsync_end - mode->hsync_start;
+	vfp = mode->vsync_start - mode->vdisplay;
+	vbp = mode->vtotal - mode->vsync_end;
+	vsw = mode->vsync_end - mode->vsync_start;
+
+	vsync_timediff = (uint64_t)(mode->hdisplay + hbp + hfp + hsw) *
+		(mode->vdisplay + vbp + vfp + vsw) *
+		1000000000UL / (adj_mode->clock * 1000);
+
+	prepare_timestamp = ktime_get();
+
+	if ((ktime_to_ns(prepare_timestamp) > ktime_to_ns(ctx->vsync_timestamp)) &&
+		(ktime_to_ns(prepare_timestamp) - ktime_to_ns(ctx->vsync_timestamp) < (vsync_timediff - 2000000)) &&
+		(ktime_to_ns(ctx->vsync_timestamp_prev) != ktime_to_ns(ctx->vsync_timestamp))) {
+		DRM_DEBUG("vsync_timediff=%llu, timestamp_diff=%llu!\n",
+			vsync_timediff, ktime_to_ns(prepare_timestamp) - ktime_to_ns(ctx->vsync_timestamp));
+	} else {
+		DRM_DEBUG("vsync_timediff=%llu.\n", vsync_timediff);
+
+		if (hisi_vactive0_start_config(ctx) != 0) {
+			DRM_ERROR("hisi_vactive0_start_config failed!\n");
+			return;
+		}
+	}
+	ctx->vsync_timestamp_prev = ctx->vsync_timestamp;
+
+	hisi_dss_mctl_mutex_lock(ctx);
+	hisi_dss_aif_ch_config(ctx, chn_idx);
+	hisi_dss_mif_config(ctx, chn_idx, mmu_enable);
+	hisi_dss_smmu_config(ctx, chn_idx, mmu_enable);
+
+	hisi_dss_rdma_config(ctx, &rect, display_addr, hal_fmt, bpp, chn_idx, afbcd, mmu_enable);
+	hisi_dss_rdfc_config(ctx, &rect, hal_fmt, bpp, chn_idx);
+	hisi_dss_ovl_config(ctx, &rect, mode->hdisplay, mode->vdisplay);
+
+	hisi_dss_mctl_ov_config(ctx, chn_idx);
+	hisi_dss_mctl_sys_config(ctx, chn_idx);
+	hisi_dss_mctl_mutex_unlock(ctx);
+
+	hisi_dss_unflow_handler(ctx, true);
+
+	enable_ldi(acrtc);
+}
+
+void hisi_dss_online_play(struct drm_plane *plane, drm_dss_layer_t *layer)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_display_mode *mode;
+	struct drm_display_mode *adj_mode;
+
+	struct dss_plane *aplane = to_dss_plane(plane);
+	struct dss_crtc *acrtc = aplane->acrtc;
+	struct dss_hw_ctx *ctx = acrtc->ctx;
+
+	ktime_t prepare_timestamp;
+	u64 vsync_timediff;
+
+	bool afbcd = false;
+	bool mmu_enable = true;
+	dss_rect_ltrb_t rect;
+	u32 bpp;
+	u32 stride;
+	u32 display_addr;
+
+	int chn_idx = DSS_RCHN_D2;
+	u32 hal_fmt = 0;
+	u32 src_w = state->src_w >> 16;
+	u32 src_h = state->src_h >> 16;
+
+	u32 hfp, hbp, hsw, vfp, vbp, vsw;
+
+	mode = &acrtc->base.state->mode;
+	adj_mode = &acrtc->base.state->adjusted_mode;
+
+	bpp = layer->img.bpp;
+	stride = layer->img.stride;
+	display_addr = layer->img.vir_addr;
+	hal_fmt = layer->img.format;
+
+	rect.left = 0;
+	rect.right = src_w - 1;
+	rect.top = 0;
+	rect.bottom = src_h - 1;
+
+	hfp = mode->hsync_start - mode->hdisplay;
+	hbp = mode->htotal - mode->hsync_end;
+	hsw = mode->hsync_end - mode->hsync_start;
+	vfp = mode->vsync_start - mode->vdisplay;
+	vbp = mode->vtotal - mode->vsync_end;
+	vsw = mode->vsync_end - mode->vsync_start;
+
+	vsync_timediff = (uint64_t)(mode->hdisplay + hbp + hfp + hsw) *
+		(mode->vdisplay + vbp + vfp + vsw) *
+		1000000000UL / (adj_mode->clock * 1000);
+
+	prepare_timestamp = ktime_get();
+
+	if ((ktime_to_ns(prepare_timestamp) > ktime_to_ns(ctx->vsync_timestamp)) &&
+		(ktime_to_ns(prepare_timestamp) - ktime_to_ns(ctx->vsync_timestamp) < (vsync_timediff - 2000000)) &&
+		(ktime_to_ns(ctx->vsync_timestamp_prev) != ktime_to_ns(ctx->vsync_timestamp))) {
+		DRM_DEBUG("vsync_timediff=%llu, timestamp_diff=%llu!\n",
+			vsync_timediff, ktime_to_ns(prepare_timestamp) - ktime_to_ns(ctx->vsync_timestamp));
+	} else {
+		DRM_DEBUG("vsync_timediff=%llu.\n", vsync_timediff);
+
+		if (hisi_vactive0_start_config(ctx) != 0) {
+			DRM_ERROR("hisi_vactive0_start_config failed!\n");
+			return;
+		}
+	}
+
+	ctx->vsync_timestamp_prev = ctx->vsync_timestamp;
+
+	hisi_dss_mctl_mutex_lock(ctx);
+	hisi_dss_aif_ch_config(ctx, chn_idx);
+	hisi_dss_mif_config(ctx, chn_idx, mmu_enable);
+	hisi_dss_smmu_config(ctx, chn_idx, mmu_enable);
+
+	hisi_dss_rdma_config(ctx, &rect, display_addr, hal_fmt, bpp, chn_idx, afbcd, mmu_enable);
+	hisi_dss_rdfc_config(ctx, &rect, hal_fmt, bpp, chn_idx);
+	hisi_dss_ovl_config(ctx, &rect, mode->hdisplay, mode->vdisplay);
+
+	hisi_dss_mctl_ov_config(ctx, chn_idx);
+	hisi_dss_mctl_sys_config(ctx, chn_idx);
+	hisi_dss_mctl_mutex_unlock(ctx);
+
+	hisi_dss_unflow_handler(ctx, true);
+
+	enable_ldi(acrtc);
+}
diff --git a/drivers/staging/hikey9xx/gpu/kirin_fb.c b/drivers/staging/hikey9xx/gpu/kirin_fb.c
new file mode 100644
index 000000000000..834c9a381a4a
--- /dev/null
+++ b/drivers/staging/hikey9xx/gpu/kirin_fb.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <drm/drmP.h>
+
+#include "kirin_drm_drv.h"
+
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+
+struct kirin_framebuffer {
+	struct drm_framebuffer base;
+};
+#define to_kirin_framebuffer(x) container_of(x, struct kirin_framebuffer, base)
+
+
+static int kirin_framebuffer_create_handle(struct drm_framebuffer *fb,
+		struct drm_file *file_priv,
+		unsigned int *handle)
+{
+	//struct kirin_framebuffer *kirin_fb = to_kirin_framebuffer(fb);
+	return 0;
+}
+
+static void kirin_framebuffer_destroy(struct drm_framebuffer *fb)
+{
+	struct kirin_framebuffer *kirin_fb = to_kirin_framebuffer(fb);
+
+	DRM_DEBUG("destroy: FB ID: %d (%p)", fb->base.id, fb);
+
+	drm_framebuffer_cleanup(fb);
+
+	kfree(kirin_fb);
+}
+
+static int kirin_framebuffer_dirty(struct drm_framebuffer *fb,
+		struct drm_file *file_priv, unsigned flags, unsigned color,
+		struct drm_clip_rect *clips, unsigned num_clips)
+{
+	return 0;
+}
+
+static const struct drm_framebuffer_funcs kirin_framebuffer_funcs = {
+	.create_handle = kirin_framebuffer_create_handle,
+	.destroy = kirin_framebuffer_destroy,
+	.dirty = kirin_framebuffer_dirty,
+};
+
+struct drm_framebuffer *kirin_framebuffer_init(struct drm_device *dev,
+		struct drm_mode_fb_cmd2 *mode_cmd)
+{
+	struct kirin_framebuffer *kirin_fb = NULL;
+	struct drm_framebuffer *fb;
+	int ret;
+
+	kirin_fb = kzalloc(sizeof(*kirin_fb), GFP_KERNEL);
+	if (!kirin_fb) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	fb = &kirin_fb->base;
+
+	drm_helper_mode_fill_fb_struct(fb, mode_cmd);
+
+	ret = drm_framebuffer_init(dev, fb, &kirin_framebuffer_funcs);
+	if (ret) {
+		dev_err(dev->dev, "framebuffer init failed: %d\n", ret);
+		goto fail;
+	}
+
+	DRM_DEBUG("create: FB ID: %d (%p)", fb->base.id, fb);
+
+	return fb;
+
+fail:
+	kfree(kirin_fb);
+
+	return ERR_PTR(ret);
+}
diff --git a/drivers/staging/hikey9xx/gpu/kirin_fbdev.c b/drivers/staging/hikey9xx/gpu/kirin_fbdev.c
new file mode 100644
index 000000000000..424a4107db56
--- /dev/null
+++ b/drivers/staging/hikey9xx/gpu/kirin_fbdev.c
@@ -0,0 +1,470 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <drm/drmP.h>
+#include <drm_crtc_helper.h>
+
+#include <linux/ion.h>
+#include <linux/hisi/hisi_ion.h>
+
+#include "kirin_drm_drv.h"
+#include "kirin_dpe_reg.h"
+#include "kirin_drm_dpe_utils.h"
+
+#include "drm_crtc.h"
+#include "drm_fb_helper.h"
+
+//#define CONFIG_HISI_FB_HEAP_CARVEOUT_USED
+
+#define FBDEV_BUFFER_NUM 3
+struct fb_dmabuf_export
+{
+    __u32 fd;
+    __u32 flags;
+};
+#define FBIOGET_DMABUF  _IOR('F', 0x21, struct fb_dmabuf_export)
+
+#define HISIFB_IOCTL_MAGIC 'M'
+#define HISI_DRM_ONLINE_PLAY _IOW(HISIFB_IOCTL_MAGIC, 0x21, struct drm_dss_layer)
+
+/*
+ * fbdev funcs, to implement legacy fbdev interface on top of drm driver
+ */
+
+#define HISI_FB_ION_CLIENT_NAME	"hisi_fb_ion"
+
+unsigned long kirin_alloc_fb_buffer(struct kirin_fbdev *fbdev, int size)
+{
+	struct ion_client *client = NULL;
+	struct ion_handle *handle = NULL;
+	size_t buf_len = 0;
+	unsigned long buf_addr = 0;
+	int shared_fd = -1;
+
+	if (NULL == fbdev) {
+		DRM_ERROR("fbdev is NULL!\n");
+		return -EINVAL;
+	}
+
+	client = fbdev->ion_client;
+	handle = fbdev->ion_handle;
+
+	buf_len = size;
+
+	client = hisi_ion_client_create(HISI_FB_ION_CLIENT_NAME);
+	if (!client) {
+		DRM_ERROR("failed to create ion client!\n");
+		return -ENOMEM;
+	}
+	memset(&fbdev->iommu_format, 0, sizeof(struct iommu_map_format));
+
+#ifdef CONFIG_HISI_FB_HEAP_CARVEOUT_USED
+	handle = ion_alloc(client, buf_len, PAGE_SIZE, ION_HEAP(ION_GRALLOC_HEAP_ID), 0);
+#else
+	handle = ion_alloc(client, buf_len, PAGE_SIZE, ION_HEAP(ION_SYSTEM_HEAP_ID), 0);
+#endif
+	if (!handle) {
+		DRM_ERROR("failed to ion_alloc!\n");
+		goto err_return;
+	}
+
+	fbdev->screen_base = ion_map_kernel(client, handle);
+	if (!fbdev->screen_base) {
+		DRM_ERROR("failed to ion_map_kernel!\n");
+		goto err_ion_map;
+	}
+
+#ifdef CONFIG_HISI_FB_HEAP_CARVEOUT_USED
+	if (ion_phys(client, handle, &buf_addr, &buf_len) < 0) {
+		DRM_ERROR("failed to get ion phys!\n");
+		goto err_ion_get_addr;
+	}
+#else
+	if (ion_map_iommu(client, handle, &(fbdev->iommu_format))) {
+		DRM_ERROR("failed to ion_map_iommu!\n");
+		goto err_ion_get_addr;
+	}
+
+	buf_addr = fbdev->iommu_format.iova_start;
+#endif
+
+	fbdev->shared_fd = shared_fd;
+	fbdev->smem_start = buf_addr;
+	fbdev->screen_size = buf_len;
+	memset(fbdev->screen_base, 0x0, fbdev->screen_size);
+
+	fbdev->ion_client = client;
+	fbdev->ion_handle = handle;
+
+	return buf_addr;
+
+err_ion_get_addr:
+	ion_unmap_kernel(client, handle);
+err_ion_map:
+	ion_free(client, handle);
+err_return:
+	return 0;
+}
+
+static int kirin_fbdev_mmap(struct fb_info *info, struct vm_area_struct * vma)
+{
+	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;
+	unsigned long size = 0;
+	int i = 0;
+	int ret = 0;
+
+	struct drm_fb_helper *helper = (struct drm_fb_helper *)info->par;
+	struct kirin_fbdev *fbdev = to_kirin_fbdev(helper);
+
+	if (NULL == info) {
+		DRM_ERROR("info is NULL!\n");
+		return -EINVAL;
+	}
+
+	if (NULL == fbdev) {
+		DRM_ERROR("fbdev is NULL!\n");
+		return -EINVAL;
+	}
+
+	table = ion_sg_table(fbdev->ion_client, fbdev->ion_handle);
+	if ((table == NULL) || (vma == NULL)) {
+		DRM_ERROR("table or vma is NULL!\n");
+		return -EFAULT;
+	}
+
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+	addr = vma->vm_start;
+	offset = vma->vm_pgoff * PAGE_SIZE;
+	size = vma->vm_end - vma->vm_start;
+
+	if (size > info->fix.smem_len) {
+		DRM_ERROR("size=%lu is out of range(%u)!\n", size, info->fix.smem_len);
+		return -EFAULT;
+	}
+
+	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) {
+			DRM_ERROR("failed to remap_pfn_range! ret=%d\n", ret);
+		}
+
+		addr += len;
+		if (addr >= vma->vm_end)
+			return 0;
+	}
+
+	return 0;
+}
+
+static int kirin_dmabuf_export(struct fb_info *info, void __user *argp)
+{
+	int ret;
+	struct drm_fb_helper *helper;
+	struct kirin_fbdev *fbdev;
+	struct fb_dmabuf_export dmabuf_export;
+
+	helper = (struct drm_fb_helper *)info->par;
+	fbdev = to_kirin_fbdev(helper);
+
+	ret = copy_from_user(&dmabuf_export, argp, sizeof(struct fb_dmabuf_export));
+	if (ret) {
+		DRM_ERROR("copy for user failed!ret=%d.\n", ret);
+		ret = -EINVAL;
+	} else {
+		dmabuf_export.flags = 0;
+		dmabuf_export.fd = ion_share_dma_buf_fd(fbdev->ion_client, fbdev->ion_handle);
+		if (dmabuf_export.fd < 0) {
+			DRM_ERROR("failed to ion_share!\n");
+		}
+
+		ret = copy_to_user(argp, &dmabuf_export, sizeof(struct fb_dmabuf_export));
+		if (ret) {
+			DRM_ERROR("copy to user failed!ret=%d.", ret);
+			ret = -EFAULT;
+		}
+	}
+
+	return ret;
+}
+
+static int kirin_dss_online_compose(struct fb_info *info, void __user *argp)
+{
+	int ret;
+	struct drm_fb_helper *helper;
+	struct kirin_drm_private *priv;
+	struct drm_plane *plane;
+
+	struct drm_dss_layer layer;
+
+	helper = (struct drm_fb_helper *)info->par;
+	priv = helper->dev->dev_private;
+	plane =priv->crtc[0]->primary;
+
+	ret = copy_from_user(&layer, argp, sizeof(struct drm_dss_layer));
+	if (ret) {
+		DRM_ERROR("copy for user failed!ret=%d.\n", ret);
+		return -EINVAL;
+	}
+
+	hisi_dss_online_play(plane, &layer);
+
+	return ret;
+}
+
+static int kirin_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+{
+	int ret = -ENOSYS;
+	void __user *argp = (void __user *)arg;
+
+	if (NULL == info) {
+		DRM_ERROR("info is NULL!\n");
+		return -EINVAL;
+	}
+
+	switch (cmd) {
+	case FBIOGET_DMABUF:
+		ret = kirin_dmabuf_export(info, argp);
+		break;
+	case HISI_DRM_ONLINE_PLAY:
+		ret = kirin_dss_online_compose(info, argp);
+		break;
+	default:
+		break;
+	}
+
+	if (ret == -ENOSYS)
+		DRM_ERROR("unsupported ioctl (%x)\n", cmd);
+
+	return ret;
+}
+
+
+static struct fb_ops kirin_fb_ops = {
+	.owner = THIS_MODULE,
+
+	/* Note: to properly handle manual update displays, we wrap the
+	 * basic fbdev ops which write to the framebuffer
+	 */
+	.fb_read = drm_fb_helper_sys_read,
+	.fb_write = drm_fb_helper_sys_write,
+	.fb_fillrect = drm_fb_helper_sys_fillrect,
+	.fb_copyarea = drm_fb_helper_sys_copyarea,
+	.fb_imageblit = drm_fb_helper_sys_imageblit,
+	.fb_mmap = kirin_fbdev_mmap,
+
+	.fb_check_var = drm_fb_helper_check_var,
+	.fb_set_par = drm_fb_helper_set_par,
+	.fb_pan_display = drm_fb_helper_pan_display,
+	.fb_blank = drm_fb_helper_blank,
+	.fb_setcmap = drm_fb_helper_setcmap,
+
+	.fb_ioctl = kirin_fb_ioctl,
+	.fb_compat_ioctl = kirin_fb_ioctl,
+};
+
+static int kirin_fbdev_create(struct drm_fb_helper *helper,
+		struct drm_fb_helper_surface_size *sizes)
+{
+	struct kirin_fbdev *fbdev = to_kirin_fbdev(helper);
+	struct drm_device *dev = helper->dev;
+	struct drm_framebuffer *fb = NULL;
+	struct fb_info *fbi = NULL;
+	struct drm_mode_fb_cmd2 mode_cmd = {0};
+	int ret, size;
+	unsigned int bytes_per_pixel;
+
+	DRM_DEBUG("create fbdev: %dx%d@%d (%dx%d)\n", sizes->surface_width,
+			sizes->surface_height, sizes->surface_bpp,
+			sizes->fb_width, sizes->fb_height);
+
+	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+			sizes->surface_depth);
+
+	mode_cmd.width = sizes->surface_width;
+	mode_cmd.height = sizes->surface_height * FBDEV_BUFFER_NUM;
+
+	bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
+	mode_cmd.pitches[0] = sizes->surface_width * bytes_per_pixel;
+	//mode_cmd.pitches[0] = align_pitch(mode_cmd.width, sizes->surface_bpp);
+
+	/* allocate backing bo */
+	size = mode_cmd.pitches[0] * mode_cmd.height;
+	DRM_DEBUG("allocating %d bytes for fb %d", size, dev->primary->index);
+
+	fb = kirin_framebuffer_init(dev, &mode_cmd);
+	if (IS_ERR(fb)) {
+		dev_err(dev->dev, "failed to allocate fb\n");
+		/* note: if fb creation failed, we can't rely on fb destroy
+		 * to unref the bo:
+		 */
+		ret = PTR_ERR(fb);
+		goto fail;
+	}
+
+	mutex_lock(&dev->struct_mutex);
+
+	fbdev->ion_client = NULL;
+	fbdev->ion_handle = NULL;
+	fbdev->screen_base = NULL;
+	fbdev->smem_start = 0;
+	fbdev->screen_size = 0;
+	memset(&fbdev->iommu_format, 0, sizeof(struct iommu_map_format));
+
+	kirin_alloc_fb_buffer(fbdev, size);
+
+	fbi = drm_fb_helper_alloc_fbi(helper);
+	if (IS_ERR(fbi)) {
+		dev_err(dev->dev, "failed to allocate fb info\n");
+		ret = PTR_ERR(fbi);
+		goto fail_unlock;
+	}
+
+	DRM_DEBUG("fbi=%p, dev=%p", fbi, dev);
+
+	fbdev->fb = fb;
+	helper->fb = fb;
+
+	fbi->par = helper;
+	fbi->flags = FBINFO_DEFAULT;
+	fbi->fbops = &kirin_fb_ops;
+
+	strcpy(fbi->fix.id, "dss");
+
+	drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
+	drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
+
+	dev->mode_config.fb_base = fbdev->smem_start;
+	fbi->screen_base = fbdev->screen_base;
+	fbi->screen_size = fbdev->screen_size;
+	fbi->fix.smem_start = fbdev->smem_start;
+	fbi->fix.smem_len = fbdev->screen_size;
+
+	DRM_DEBUG("par=%p, %dx%d", fbi->par, fbi->var.xres, fbi->var.yres);
+	DRM_DEBUG("allocated %dx%d fb", fbdev->fb->width, fbdev->fb->height);
+
+	mutex_unlock(&dev->struct_mutex);
+
+	return 0;
+
+fail_unlock:
+	mutex_unlock(&dev->struct_mutex);
+fail:
+	if (ret) {
+		if (fb) {
+			drm_framebuffer_unregister_private(fb);
+			drm_framebuffer_remove(fb);
+		}
+	}
+	return ret;
+}
+
+static const struct drm_fb_helper_funcs kirin_fb_helper_funcs = {
+	.fb_probe = kirin_fbdev_create,
+};
+
+/* initialize fbdev helper */
+struct drm_fb_helper *kirin_drm_fbdev_init(struct drm_device *dev)
+{
+	struct kirin_drm_private *priv = dev->dev_private;
+	struct kirin_fbdev *fbdev = NULL;
+	struct drm_fb_helper *helper;
+	int ret;
+
+	fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
+	if (!fbdev)
+		goto fail;
+
+	priv->fb_helper = helper = &fbdev->fb_helper;
+
+	drm_fb_helper_prepare(dev, helper, &kirin_fb_helper_funcs);
+
+	DRM_INFO("num_crtc=%d, num_connector=%d.\n",
+		dev->mode_config.num_crtc, dev->mode_config.num_connector);
+
+	ret = drm_fb_helper_init(dev, helper,
+			dev->mode_config.num_crtc, dev->mode_config.num_connector);
+	if (ret) {
+		dev_err(dev->dev, "could not init fbdev: ret=%d\n", ret);
+		goto fail;
+	}
+
+	ret = drm_fb_helper_single_add_all_connectors(helper);
+	if (ret)
+		goto fini;
+
+	/* disable all the possible outputs/crtcs before entering KMS mode */
+	drm_helper_disable_unused_functions(dev);
+
+	ret = drm_fb_helper_initial_config(helper, 32);
+	if (ret)
+		goto fini;
+
+	priv->fbdev = helper;
+
+	return helper;
+
+fini:
+	drm_fb_helper_fini(helper);
+fail:
+	kfree(fbdev);
+	return NULL;
+}
+
+void kirin_drm_fbdev_fini(struct drm_device *dev)
+{
+	struct kirin_drm_private *priv = dev->dev_private;
+	struct drm_fb_helper *helper = priv->fbdev;
+	struct kirin_fbdev *fbdev;
+
+	drm_fb_helper_unregister_fbi(helper);
+	drm_fb_helper_release_fbi(helper);
+
+	drm_fb_helper_fini(helper);
+
+	fbdev = to_kirin_fbdev(priv->fbdev);
+
+	/* this will free the backing object */
+	if (fbdev->fb) {
+		drm_framebuffer_unregister_private(fbdev->fb);
+		drm_framebuffer_remove(fbdev->fb);
+	}
+
+	kfree(fbdev);
+
+	priv->fbdev = NULL;
+}
-- 
2.26.2


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

* [PATCH 40/49] staging: hikey9xx/gpu: get rid of input/output macros
  2020-08-19 11:45 [PATCH 00/49] DRM driver for Hikey 970 Mauro Carvalho Chehab
  2020-08-19 11:45 ` [PATCH 01/49] staging: hikey9xx: Add hisilicon DRM driver for hikey960/970 Mauro Carvalho Chehab
@ 2020-08-19 11:46 ` Mauro Carvalho Chehab
  2020-08-19 15:21 ` [PATCH 00/49] DRM driver for Hikey 970 Sam Ravnborg
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 42+ messages in thread
From: Mauro Carvalho Chehab @ 2020-08-19 11:46 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linuxarm, mauro.chehab, Mauro Carvalho Chehab, John Stultz,
	Manivannan Sadhasivam, Daniel Vetter, dri-devel, Sumit Semwal,
	Liwei Cai, Xiubin Zhang, Chen Feng, Liuyao An, Wanchun Zheng,
	devel, linux-kernel, linux-media, linaro-mm-sig

The DPE headers define several macros for I/O. Get rid of
them by replacing by the Linux ones.

In the specific case of outp32(), I used this small
coccinelle script to change them to writel():

	@ rule1 @
	expression addr, val;
	@@
	-outp32(addr, val)
	+writel(val, addr)

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 .../staging/hikey9xx/gpu/kirin960_dpe_reg.h   |  15 --
 .../staging/hikey9xx/gpu/kirin970_dpe_reg.h   |  15 --
 .../hikey9xx/gpu/kirin9xx_drm_dpe_utils.c     | 251 ++++++++++--------
 .../staging/hikey9xx/gpu/kirin9xx_drm_dss.c   |  24 +-
 .../hikey9xx/gpu/kirin9xx_drm_overlay_utils.c |  14 +-
 .../hikey9xx/gpu/kirin9xx_dw_drm_dsi.c        |  24 +-
 drivers/staging/hikey9xx/gpu/kirin9xx_pwm.c   |  20 +-
 7 files changed, 180 insertions(+), 183 deletions(-)

diff --git a/drivers/staging/hikey9xx/gpu/kirin960_dpe_reg.h b/drivers/staging/hikey9xx/gpu/kirin960_dpe_reg.h
index f34d5af189f7..cd248bf15503 100644
--- a/drivers/staging/hikey9xx/gpu/kirin960_dpe_reg.h
+++ b/drivers/staging/hikey9xx/gpu/kirin960_dpe_reg.h
@@ -3218,21 +3218,6 @@ struct mipi_ifbc_division {
 
 /*****************************************************************************/
 
-#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)
-
 #ifndef ALIGN_DOWN
 #define ALIGN_DOWN(val, al)  ((val) & ~((al) - 1))
 #endif
diff --git a/drivers/staging/hikey9xx/gpu/kirin970_dpe_reg.h b/drivers/staging/hikey9xx/gpu/kirin970_dpe_reg.h
index 4f24322ebc7f..aeae3720c889 100644
--- a/drivers/staging/hikey9xx/gpu/kirin970_dpe_reg.h
+++ b/drivers/staging/hikey9xx/gpu/kirin970_dpe_reg.h
@@ -4206,21 +4206,6 @@ struct mipi_ifbc_division {
 
 /*****************************************************************************/
 
-#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)
-
 #ifndef ALIGN_DOWN
 #define ALIGN_DOWN(val, al)  ((val) & ~((al) - 1))
 #endif
diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dpe_utils.c b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dpe_utils.c
index 0e3d192c3851..ac7924fd0fc9 100644
--- a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dpe_utils.c
+++ b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dpe_utils.c
@@ -123,10 +123,10 @@ void set_reg(char __iomem *addr, uint32_t val, uint8_t bw, uint8_t bs)
 	u32 mask = (1UL << bw) - 1UL;
 	u32 tmp = 0;
 
-	tmp = inp32(addr);
+	tmp = readl(addr);
 	tmp &= ~(mask << bs);
 
-	outp32(addr, tmp | ((val & mask) << bs));
+	writel(tmp | ((val & mask) << bs), addr);
 
 	if (g_debug_set_reg_val) {
 		printk(KERN_INFO "writel: [%p] = 0x%x\n", addr,
@@ -275,18 +275,16 @@ void init_ldi(struct dss_crtc *acrtc)
 
 	init_ldi_pxl_div(acrtc);
 
-	outp32(ldi_base + LDI_DPI0_HRZ_CTRL0,
-	       hfp | ((hbp + DSS_WIDTH(hsw)) << 16));
-	outp32(ldi_base + LDI_DPI0_HRZ_CTRL1, 0);
-	outp32(ldi_base + LDI_DPI0_HRZ_CTRL2, DSS_WIDTH(rect.w));
-	outp32(ldi_base + LDI_VRT_CTRL0,
-	       vfp | (vbp << 16));
-	outp32(ldi_base + LDI_VRT_CTRL1, DSS_HEIGHT(vsw));
-	outp32(ldi_base + LDI_VRT_CTRL2, DSS_HEIGHT(rect.h));
+	writel(hfp | ((hbp + DSS_WIDTH(hsw)) << 16),
+	       ldi_base + LDI_DPI0_HRZ_CTRL0);
+	writel(0, ldi_base + LDI_DPI0_HRZ_CTRL1);
+	writel(DSS_WIDTH(rect.w), ldi_base + LDI_DPI0_HRZ_CTRL2);
+	writel(vfp | (vbp << 16), ldi_base + LDI_VRT_CTRL0);
+	writel(DSS_HEIGHT(vsw), ldi_base + LDI_VRT_CTRL1);
+	writel(DSS_HEIGHT(rect.h), ldi_base + LDI_VRT_CTRL2);
 
-	outp32(ldi_base + LDI_PLR_CTRL,
-	       vsync_plr | (hsync_plr << 1) |
-		(pixelclk_plr << 2) | (data_en_plr << 3));
+	writel(vsync_plr | (hsync_plr << 1) | (pixelclk_plr << 2) | (data_en_plr << 3),
+	       ldi_base + LDI_PLR_CTRL);
 
 	/* bpp*/
 	set_reg(ldi_base + LDI_CTRL, acrtc->out_format, 2, 3);
@@ -294,10 +292,10 @@ void init_ldi(struct dss_crtc *acrtc)
 	set_reg(ldi_base + LDI_CTRL, acrtc->bgr_fmt, 1, 13);
 
 	/* for ddr pmqos*/
-	outp32(ldi_base + LDI_VINACT_MSK_LEN, vfp);
+	writel(vfp, ldi_base + LDI_VINACT_MSK_LEN);
 
 	/*cmd event sel*/
-	outp32(ldi_base + LDI_CMD_EVENT_SEL, 0x1);
+	writel(0x1, ldi_base + LDI_CMD_EVENT_SEL);
 
 	/* for 1Hz LCD and mipi command LCD*/
 	set_reg(ldi_base + LDI_DSI_CMD_MOD_CTRL, 0x1, 1, 1);
@@ -470,22 +468,25 @@ void init_dbuf(struct dss_crtc *acrtc)
 		thd_flux_req_aftdfs_out,
 		thd_dfs_ok);
 
-	outp32(dbuf_base + DBUF_FRM_SIZE, mode->hdisplay * mode->vdisplay);
-	outp32(dbuf_base + DBUF_FRM_HSIZE, DSS_WIDTH(mode->hdisplay));
-	outp32(dbuf_base + DBUF_SRAM_VALID_NUM, sram_valid_num);
+	writel(mode->hdisplay * mode->vdisplay, dbuf_base + DBUF_FRM_SIZE);
+	writel(DSS_WIDTH(mode->hdisplay), dbuf_base + DBUF_FRM_HSIZE);
+	writel(sram_valid_num, dbuf_base + DBUF_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);
+	writel((thd_rqos_out << 16) | thd_rqos_in, dbuf_base + DBUF_THD_RQOS);
+	writel((thd_wqos_out << 16) | thd_wqos_in, dbuf_base + DBUF_THD_WQOS);
+	writel((thd_cg_out << 16) | thd_cg_in, dbuf_base + DBUF_THD_CG);
+	writel((thd_cg_hold << 16) | thd_wr_wait, dbuf_base + DBUF_THD_OTHER);
+	writel((thd_flux_req_befdfs_out << 16) | thd_flux_req_befdfs_in,
+               dbuf_base + DBUF_THD_FLUX_REQ_BEF);
+	writel((thd_flux_req_aftdfs_out << 16) | thd_flux_req_aftdfs_in,
+               dbuf_base + DBUF_THD_FLUX_REQ_AFT);
+	writel(thd_dfs_ok, dbuf_base + DBUF_THD_DFS_OK);
+	writel((dfs_ok_mask << 1) | thd_flux_req_sw_en,
+               dbuf_base + DBUF_FLUX_REQ_CTRL);
 
-	outp32(dbuf_base + DBUF_DFS_LP_CTRL, 0x1);
+	writel(0x1, dbuf_base + DBUF_DFS_LP_CTRL);
 	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970)
-		outp32(dbuf_base + DBUF_DFS_RAM_MANAGE, dfs_ram);
+		writel(dfs_ram, dbuf_base + DBUF_DFS_RAM_MANAGE);
 }
 
 void init_dpp(struct dss_crtc *acrtc)
@@ -508,10 +509,10 @@ void init_dpp(struct dss_crtc *acrtc)
 	dpp_base = ctx->base + DSS_DPP_OFFSET;
 	mctl_sys_base = ctx->base + DSS_MCTRL_SYS_OFFSET;
 
-	outp32(dpp_base + DPP_IMG_SIZE_BEF_SR,
-	       (DSS_HEIGHT(mode->vdisplay) << 16) | DSS_WIDTH(mode->hdisplay));
-	outp32(dpp_base + DPP_IMG_SIZE_AFT_SR,
-	       (DSS_HEIGHT(mode->vdisplay) << 16) | DSS_WIDTH(mode->hdisplay));
+	writel((DSS_HEIGHT(mode->vdisplay) << 16) | DSS_WIDTH(mode->hdisplay),
+	       dpp_base + DPP_IMG_SIZE_BEF_SR);
+	writel((DSS_HEIGHT(mode->vdisplay) << 16) | DSS_WIDTH(mode->hdisplay),
+	       dpp_base + DPP_IMG_SIZE_AFT_SR);
 }
 
 void enable_ldi(struct dss_crtc *acrtc)
@@ -563,22 +564,22 @@ void dpe_interrupt_clear(struct dss_crtc *acrtc)
 	dss_base = ctx->base;
 
 	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);
+	writel(clear, dss_base + GLB_CPU_PDP_INTS);
+	writel(clear, dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS);
+	writel(clear, dss_base + DSS_DPP_OFFSET + DPP_INTS);
 
-	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);
+	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_MCTL_INTS);
+	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_WCH0_INTS);
+	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_WCH1_INTS);
+	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_RCH0_INTS);
+	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_RCH1_INTS);
+	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_RCH2_INTS);
+	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_RCH3_INTS);
+	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_RCH4_INTS);
+	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_RCH5_INTS);
+	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_RCH6_INTS);
+	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_RCH7_INTS);
+	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_DSS_GLB_INTS);
 }
 
 void dpe_interrupt_unmask(struct dss_crtc *acrtc)
@@ -597,12 +598,12 @@ void dpe_interrupt_unmask(struct dss_crtc *acrtc)
 
 	unmask = ~0;
 	unmask &= ~(BIT_ITF0_INTS | BIT_MMU_IRPT_NS);
-	outp32(dss_base + GLB_CPU_PDP_INT_MSK, unmask);
+	writel(unmask, dss_base + GLB_CPU_PDP_INT_MSK);
 
 	unmask = ~0;
 	unmask &= ~(BIT_VSYNC | BIT_VACTIVE0_END | BIT_LDI_UNFLOW);
 
-	outp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK, unmask);
+	writel(unmask, dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK);
 }
 
 void dpe_interrupt_mask(struct dss_crtc *acrtc)
@@ -620,21 +621,21 @@ void dpe_interrupt_mask(struct dss_crtc *acrtc)
 	dss_base = ctx->base;
 
 	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);
+	writel(mask, dss_base + GLB_CPU_PDP_INT_MSK);
+	writel(mask, dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK);
+	writel(mask, dss_base + DSS_DPP_OFFSET + DPP_INT_MSK);
+	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_DSS_GLB_INT_MSK);
+	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_MCTL_INT_MSK);
+	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_WCH0_INT_MSK);
+	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_WCH1_INT_MSK);
+	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_RCH0_INT_MSK);
+	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_RCH1_INT_MSK);
+	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_RCH2_INT_MSK);
+	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_RCH3_INT_MSK);
+	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_RCH4_INT_MSK);
+	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_RCH5_INT_MSK);
+	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_RCH6_INT_MSK);
+	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_RCH7_INT_MSK);
 }
 
 int dpe_init(struct dss_crtc *acrtc)
@@ -692,7 +693,7 @@ void dpe_check_itf_status(struct dss_crtc *acrtc)
 	mctl_sys_base =  ctx->base + DSS_MCTRL_SYS_OFFSET;
 
 	while (1) {
-		tmp = inp32(mctl_sys_base + MCTL_MOD17_STATUS + itf_idx * 0x4);
+		tmp = readl(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;
@@ -720,11 +721,11 @@ void dss_inner_clk_pdp_enable(struct dss_hw_ctx *ctx)
 	}
 	dss_base = ctx->base;
 
-	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);
+	writel(0x00000088, dss_base + DSS_IFBC_OFFSET + IFBC_MEM_CTRL);
+	writel(0x00000888, dss_base + DSS_DSC_OFFSET + DSC_MEM_CTRL);
+	writel(0x00000008, dss_base + DSS_LDI0_OFFSET + LDI_MEM_CTRL);
+	writel(0x00000008, dss_base + DSS_DBUF0_OFFSET + DBUF_MEM_CTRL);
+	writel(0x00000008, dss_base + DSS_DPP_DITHER_OFFSET + DITHER_MEM_CTRL);
 }
 
 void dss_inner_clk_common_enable(struct dss_hw_ctx *ctx)
@@ -739,61 +740,87 @@ void dss_inner_clk_common_enable(struct dss_hw_ctx *ctx)
 	dss_base = ctx->base;
 
 	/*core/axi/mmbuf*/
-	outp32(dss_base + DSS_CMDLIST_OFFSET + CMD_MEM_CTRL, 0x00000008);  /*cmd mem*/
+	writel(0x00000008, dss_base + DSS_CMDLIST_OFFSET + CMD_MEM_CTRL);  /*cmd mem*/
 
-	outp32(dss_base + DSS_RCH_VG0_SCL_OFFSET + SCF_COEF_MEM_CTRL, 0x00000088);/*rch_v0 ,scf mem*/
-	outp32(dss_base + DSS_RCH_VG0_SCL_OFFSET + SCF_LB_MEM_CTRL, 0x00000008);/*rch_v0 ,scf mem*/
-	outp32(dss_base + DSS_RCH_VG0_ARSR_OFFSET + ARSR2P_LB_MEM_CTRL, 0x00000008);/*rch_v0 ,arsr2p mem*/
-	outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + VPP_MEM_CTRL, 0x00000008);/*rch_v0 ,vpp mem*/
-	outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_v0 ,dma_buf mem*/
-	outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + AFBCD_MEM_CTRL, 0x00008888);/*rch_v0 ,afbcd mem*/
+	writel(0x00000088,
+	       dss_base + DSS_RCH_VG0_SCL_OFFSET + SCF_COEF_MEM_CTRL);/*rch_v0 ,scf mem*/
+	writel(0x00000008,
+	       dss_base + DSS_RCH_VG0_SCL_OFFSET + SCF_LB_MEM_CTRL);/*rch_v0 ,scf mem*/
+	writel(0x00000008,
+	       dss_base + DSS_RCH_VG0_ARSR_OFFSET + ARSR2P_LB_MEM_CTRL);/*rch_v0 ,arsr2p mem*/
+	writel(0x00000008, dss_base + DSS_RCH_VG0_DMA_OFFSET + VPP_MEM_CTRL);/*rch_v0 ,vpp mem*/
+	writel(0x00000008,
+	       dss_base + DSS_RCH_VG0_DMA_OFFSET + DMA_BUF_MEM_CTRL);/*rch_v0 ,dma_buf mem*/
+	writel(0x00008888, dss_base + DSS_RCH_VG0_DMA_OFFSET + AFBCD_MEM_CTRL);/*rch_v0 ,afbcd mem*/
 
-	outp32(dss_base + DSS_RCH_VG1_SCL_OFFSET + SCF_COEF_MEM_CTRL, 0x00000088);/*rch_v1 ,scf mem*/
-	outp32(dss_base + DSS_RCH_VG1_SCL_OFFSET + SCF_LB_MEM_CTRL, 0x00000008);/*rch_v1 ,scf mem*/
-	outp32(dss_base + DSS_RCH_VG1_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_v1 ,dma_buf mem*/
-	outp32(dss_base + DSS_RCH_VG1_DMA_OFFSET + AFBCD_MEM_CTRL, 0x00008888);/*rch_v1 ,afbcd mem*/
+	writel(0x00000088,
+	       dss_base + DSS_RCH_VG1_SCL_OFFSET + SCF_COEF_MEM_CTRL);/*rch_v1 ,scf mem*/
+	writel(0x00000008,
+	       dss_base + DSS_RCH_VG1_SCL_OFFSET + SCF_LB_MEM_CTRL);/*rch_v1 ,scf mem*/
+	writel(0x00000008,
+	       dss_base + DSS_RCH_VG1_DMA_OFFSET + DMA_BUF_MEM_CTRL);/*rch_v1 ,dma_buf mem*/
+	writel(0x00008888, dss_base + DSS_RCH_VG1_DMA_OFFSET + AFBCD_MEM_CTRL);/*rch_v1 ,afbcd mem*/
 
 	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
-		outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + HFBCD_MEM_CTRL, 0x88888888);
-		outp32(dss_base + DSS_RCH_VG0_DMA_OFFSET + HFBCD_MEM_CTRL_1, 0x00000888);
-		outp32(dss_base + DSS_RCH_VG1_DMA_OFFSET + HFBCD_MEM_CTRL, 0x88888888);
-		outp32(dss_base + DSS_RCH_VG1_DMA_OFFSET + HFBCD_MEM_CTRL_1, 0x00000888);
+		writel(0x88888888,
+		       dss_base + DSS_RCH_VG0_DMA_OFFSET + HFBCD_MEM_CTRL);
+		writel(0x00000888,
+		       dss_base + DSS_RCH_VG0_DMA_OFFSET + HFBCD_MEM_CTRL_1);
+		writel(0x88888888,
+		       dss_base + DSS_RCH_VG1_DMA_OFFSET + HFBCD_MEM_CTRL);
+		writel(0x00000888,
+		       dss_base + DSS_RCH_VG1_DMA_OFFSET + HFBCD_MEM_CTRL_1);
 	} else {
-		outp32(dss_base + DSS_RCH_VG2_SCL_OFFSET + SCF_COEF_MEM_CTRL, 0x00000088);/*rch_v2 ,scf mem*/
-		outp32(dss_base + DSS_RCH_VG2_SCL_OFFSET + SCF_LB_MEM_CTRL, 0x00000008);/*rch_v2 ,scf mem*/
+		writel(0x00000088,
+		       dss_base + DSS_RCH_VG2_SCL_OFFSET + SCF_COEF_MEM_CTRL);/*rch_v2 ,scf mem*/
+		writel(0x00000008,
+		       dss_base + DSS_RCH_VG2_SCL_OFFSET + SCF_LB_MEM_CTRL);/*rch_v2 ,scf mem*/
 	}
 
-	outp32(dss_base + DSS_RCH_VG2_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_v2 ,dma_buf mem*/
+	writel(0x00000008,
+	       dss_base + DSS_RCH_VG2_DMA_OFFSET + DMA_BUF_MEM_CTRL);/*rch_v2 ,dma_buf mem*/
 
-	outp32(dss_base + DSS_RCH_G0_SCL_OFFSET + SCF_COEF_MEM_CTRL, 0x00000088);/*rch_g0 ,scf mem*/
-	outp32(dss_base + DSS_RCH_G0_SCL_OFFSET + SCF_LB_MEM_CTRL, 0x0000008);/*rch_g0 ,scf mem*/
-	outp32(dss_base + DSS_RCH_G0_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_g0 ,dma_buf mem*/
-	outp32(dss_base + DSS_RCH_G0_DMA_OFFSET + AFBCD_MEM_CTRL, 0x00008888);/*rch_g0 ,afbcd mem*/
+	writel(0x00000088,
+	       dss_base + DSS_RCH_G0_SCL_OFFSET + SCF_COEF_MEM_CTRL);/*rch_g0 ,scf mem*/
+	writel(0x0000008, dss_base + DSS_RCH_G0_SCL_OFFSET + SCF_LB_MEM_CTRL);/*rch_g0 ,scf mem*/
+	writel(0x00000008,
+	       dss_base + DSS_RCH_G0_DMA_OFFSET + DMA_BUF_MEM_CTRL);/*rch_g0 ,dma_buf mem*/
+	writel(0x00008888, dss_base + DSS_RCH_G0_DMA_OFFSET + AFBCD_MEM_CTRL);/*rch_g0 ,afbcd mem*/
 
-	outp32(dss_base + DSS_RCH_G1_SCL_OFFSET + SCF_COEF_MEM_CTRL, 0x00000088);/*rch_g1 ,scf mem*/
-	outp32(dss_base + DSS_RCH_G1_SCL_OFFSET + SCF_LB_MEM_CTRL, 0x0000008);/*rch_g1 ,scf mem*/
-	outp32(dss_base + DSS_RCH_G1_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_g1 ,dma_buf mem*/
-	outp32(dss_base + DSS_RCH_G1_DMA_OFFSET + AFBCD_MEM_CTRL, 0x00008888);/*rch_g1 ,afbcd mem*/
+	writel(0x00000088,
+	       dss_base + DSS_RCH_G1_SCL_OFFSET + SCF_COEF_MEM_CTRL);/*rch_g1 ,scf mem*/
+	writel(0x0000008, dss_base + DSS_RCH_G1_SCL_OFFSET + SCF_LB_MEM_CTRL);/*rch_g1 ,scf mem*/
+	writel(0x00000008,
+	       dss_base + DSS_RCH_G1_DMA_OFFSET + DMA_BUF_MEM_CTRL);/*rch_g1 ,dma_buf mem*/
+	writel(0x00008888, dss_base + DSS_RCH_G1_DMA_OFFSET + AFBCD_MEM_CTRL);/*rch_g1 ,afbcd mem*/
 
-	outp32(dss_base + DSS_RCH_D0_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_d0 ,dma_buf mem*/
-	outp32(dss_base + DSS_RCH_D0_DMA_OFFSET + AFBCD_MEM_CTRL, 0x00008888);/*rch_d0 ,afbcd mem*/
-	outp32(dss_base + DSS_RCH_D1_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_d1 ,dma_buf mem*/
-	outp32(dss_base + DSS_RCH_D2_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_d2 ,dma_buf mem*/
-	outp32(dss_base + DSS_RCH_D3_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*rch_d3 ,dma_buf mem*/
+	writel(0x00000008,
+	       dss_base + DSS_RCH_D0_DMA_OFFSET + DMA_BUF_MEM_CTRL);/*rch_d0 ,dma_buf mem*/
+	writel(0x00008888, dss_base + DSS_RCH_D0_DMA_OFFSET + AFBCD_MEM_CTRL);/*rch_d0 ,afbcd mem*/
+	writel(0x00000008,
+	       dss_base + DSS_RCH_D1_DMA_OFFSET + DMA_BUF_MEM_CTRL);/*rch_d1 ,dma_buf mem*/
+	writel(0x00000008,
+	       dss_base + DSS_RCH_D2_DMA_OFFSET + DMA_BUF_MEM_CTRL);/*rch_d2 ,dma_buf mem*/
+	writel(0x00000008,
+	       dss_base + DSS_RCH_D3_DMA_OFFSET + DMA_BUF_MEM_CTRL);/*rch_d3 ,dma_buf mem*/
 
-	outp32(dss_base + DSS_WCH0_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*wch0 DMA/AFBCE mem*/
-	outp32(dss_base + DSS_WCH0_DMA_OFFSET + AFBCE_MEM_CTRL, 0x00000888);/*wch0 DMA/AFBCE mem*/
-	outp32(dss_base + DSS_WCH0_DMA_OFFSET + ROT_MEM_CTRL, 0x00000008);/*wch0 rot mem*/
-	outp32(dss_base + DSS_WCH1_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*wch1 DMA/AFBCE mem*/
-	outp32(dss_base + DSS_WCH1_DMA_OFFSET + AFBCE_MEM_CTRL, 0x00000888);/*wch1 DMA/AFBCE mem*/
-	outp32(dss_base + DSS_WCH1_DMA_OFFSET + ROT_MEM_CTRL, 0x00000008);/*wch1 rot mem*/
+	writel(0x00000008, dss_base + DSS_WCH0_DMA_OFFSET + DMA_BUF_MEM_CTRL);/*wch0 DMA/AFBCE mem*/
+	writel(0x00000888, dss_base + DSS_WCH0_DMA_OFFSET + AFBCE_MEM_CTRL);/*wch0 DMA/AFBCE mem*/
+	writel(0x00000008, dss_base + DSS_WCH0_DMA_OFFSET + ROT_MEM_CTRL);/*wch0 rot mem*/
+	writel(0x00000008, dss_base + DSS_WCH1_DMA_OFFSET + DMA_BUF_MEM_CTRL);/*wch1 DMA/AFBCE mem*/
+	writel(0x00000888, dss_base + DSS_WCH1_DMA_OFFSET + AFBCE_MEM_CTRL);/*wch1 DMA/AFBCE mem*/
+	writel(0x00000008, dss_base + DSS_WCH1_DMA_OFFSET + ROT_MEM_CTRL);/*wch1 rot mem*/
 	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
-		outp32(dss_base + DSS_WCH1_DMA_OFFSET + WCH_SCF_COEF_MEM_CTRL, 0x00000088);
-		outp32(dss_base + DSS_WCH1_DMA_OFFSET + WCH_SCF_LB_MEM_CTRL, 0x00000008);
-		outp32(dss_base + GLB_DSS_MEM_CTRL, 0x02605550);
+		writel(0x00000088,
+		       dss_base + DSS_WCH1_DMA_OFFSET + WCH_SCF_COEF_MEM_CTRL);
+		writel(0x00000008,
+		       dss_base + DSS_WCH1_DMA_OFFSET + WCH_SCF_LB_MEM_CTRL);
+		writel(0x02605550, dss_base + GLB_DSS_MEM_CTRL);
 	} else {
-		outp32(dss_base + DSS_WCH2_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);/*wch2 DMA/AFBCE mem*/
-		outp32(dss_base + DSS_WCH2_DMA_OFFSET + ROT_MEM_CTRL, 0x00000008);/*wch2 rot mem*/
+		writel(0x00000008,
+		       dss_base + DSS_WCH2_DMA_OFFSET + DMA_BUF_MEM_CTRL);/*wch2 DMA/AFBCE mem*/
+		writel(0x00000008,
+		       dss_base + DSS_WCH2_DMA_OFFSET + ROT_MEM_CTRL);/*wch2 rot mem*/
 		//outp32(dss_base + DSS_WCH2_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);
 		//outp32(dss_base + DSS_WCH2_DMA_OFFSET + DMA_BUF_MEM_CTRL, 0x00000008);
 	}
diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dss.c b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dss.c
index 546da775f2fb..292e14d2edf5 100644
--- a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dss.c
+++ b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dss.c
@@ -215,7 +215,7 @@ int hdmi_pxl_ppll7_init(struct dss_hw_ctx *ctx, u64 pixel_clock)
 	frac = (u64)(ceil_temp * vco_freq_output - sys_clock_fref / refdiv * fbdiv) * refdiv * frac_range;
 	frac = (u64)frac / sys_clock_fref;
 
-	ppll7ctrl0 = inp32(ctx->pmctrl_base + MIDIA_PPLL7_CTRL0);
+	ppll7ctrl0 = readl(ctx->pmctrl_base + MIDIA_PPLL7_CTRL0);
 	ppll7ctrl0 &= ~MIDIA_PPLL7_FREQ_DEVIDER_MASK;
 
 	ppll7ctrl0_val = 0x0;
@@ -223,9 +223,9 @@ int hdmi_pxl_ppll7_init(struct dss_hw_ctx *ctx, u64 pixel_clock)
 	ppll7ctrl0_val &= MIDIA_PPLL7_FREQ_DEVIDER_MASK;
 	ppll7ctrl0 |= ppll7ctrl0_val;
 
-	outp32(ctx->pmctrl_base + MIDIA_PPLL7_CTRL0, ppll7ctrl0);
+	writel(ppll7ctrl0, ctx->pmctrl_base + MIDIA_PPLL7_CTRL0);
 
-	ppll7ctrl1 = inp32(ctx->pmctrl_base + MIDIA_PPLL7_CTRL1);
+	ppll7ctrl1 = readl(ctx->pmctrl_base + MIDIA_PPLL7_CTRL1);
 	ppll7ctrl1 &= ~MIDIA_PPLL7_FRAC_MODE_MASK;
 
 	ppll7ctrl1_val = 0x0;
@@ -233,7 +233,7 @@ int hdmi_pxl_ppll7_init(struct dss_hw_ctx *ctx, u64 pixel_clock)
 	ppll7ctrl1_val &= MIDIA_PPLL7_FRAC_MODE_MASK;
 	ppll7ctrl1 |= ppll7ctrl1_val;
 
-	outp32(ctx->pmctrl_base + MIDIA_PPLL7_CTRL1, ppll7ctrl1);
+	writel(ppll7ctrl1, ctx->pmctrl_base + MIDIA_PPLL7_CTRL1);
 
 	DRM_INFO("PLL7 set to (0x%0x, 0x%0x)\n", ppll7ctrl0, ppll7ctrl1);
 
@@ -438,16 +438,16 @@ static irqreturn_t dss_irq_handler(int irq, void *data)
 	u32 isr_s2 = 0;
 	u32 mask = 0;
 
-	isr_s1 = inp32(dss_base + GLB_CPU_PDP_INTS);
-	isr_s2 = inp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS);
+	isr_s1 = readl(dss_base + GLB_CPU_PDP_INTS);
+	isr_s2 = readl(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS);
 	DRM_INFO_ONCE("isr_s1 = 0x%x!\n", isr_s1);
 	DRM_INFO_ONCE("isr_s2 = 0x%x!\n", isr_s2);
 
-	outp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS, isr_s2);
-	outp32(dss_base + GLB_CPU_PDP_INTS, isr_s1);
+	writel(isr_s2, dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS);
+	writel(isr_s1, dss_base + GLB_CPU_PDP_INTS);
 
-	isr_s1 &= ~(inp32(dss_base + GLB_CPU_PDP_INT_MSK));
-	isr_s2 &= ~(inp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK));
+	isr_s1 &= ~(readl(dss_base + GLB_CPU_PDP_INT_MSK));
+	isr_s2 &= ~(readl(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK));
 
 	if (isr_s2 & BIT_VACTIVE0_END) {
 		ctx->vactive0_end_flag++;
@@ -460,9 +460,9 @@ static irqreturn_t dss_irq_handler(int irq, void *data)
 	}
 
 	if (isr_s2 & BIT_LDI_UNFLOW) {
-		mask = inp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK);
+		mask = readl(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK);
 		mask |= BIT_LDI_UNFLOW;
-		outp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK, mask);
+		writel(mask, dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK);
 
 		DRM_ERROR("ldi underflow!\n");
 	}
diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c
index 58cbb1448306..60c43c153829 100644
--- a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c
+++ b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c
@@ -1298,10 +1298,10 @@ static void hisi_dss_qos_on(struct dss_hw_ctx *ctx)
 
 	noc_dss_base = ctx->noc_dss_base;
 
-	outp32(noc_dss_base + 0xc, 0x2);
-	outp32(noc_dss_base + 0x8c, 0x2);
-	outp32(noc_dss_base + 0x10c, 0x2);
-	outp32(noc_dss_base + 0x18c, 0x2);
+	writel(0x2, noc_dss_base + 0xc);
+	writel(0x2, noc_dss_base + 0x8c);
+	writel(0x2, noc_dss_base + 0x10c);
+	writel(0x2, noc_dss_base + 0x18c);
 }
 
 static void hisi_dss_mif_on(struct dss_hw_ctx *ctx)
@@ -1427,13 +1427,13 @@ void hisi_dss_unflow_handler(struct dss_hw_ctx *ctx, bool unmask)
 
 	dss_base = ctx->base;
 
-	tmp = inp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK);
+	tmp = readl(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK);
 	if (unmask)
 		tmp &= ~BIT_LDI_UNFLOW;
 	else
 		tmp |= BIT_LDI_UNFLOW;
 
-	outp32(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK, tmp);
+	writel(tmp, dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK);
 }
 
 void hisifb_mctl_sw_clr(struct dss_crtc *acrtc)
@@ -1457,7 +1457,7 @@ void hisifb_mctl_sw_clr(struct dss_crtc *acrtc)
 		set_reg(mctl_base + MCTL_CTL_CLEAR, 0x1, 1, 0);
 
 	while (1) {
-		mctl_status = inp32(mctl_base + MCTL_CTL_STATUS);
+		mctl_status = readl(mctl_base + MCTL_CTL_STATUS);
 		if (((mctl_status & 0x10) == 0) || (delay_count > 500)) {
 			is_timeout = (delay_count > 100) ? true : false;
 			delay_count = 0;
diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_dw_drm_dsi.c b/drivers/staging/hikey9xx/gpu/kirin9xx_dw_drm_dsi.c
index e7fb556befa1..5c6a9b78a1ec 100644
--- a/drivers/staging/hikey9xx/gpu/kirin9xx_dw_drm_dsi.c
+++ b/drivers/staging/hikey9xx/gpu/kirin9xx_dw_drm_dsi.c
@@ -279,10 +279,10 @@ static void set_reg(char __iomem *addr, uint32_t val, uint8_t bw,
 	u32 mask = (1UL << bw) - 1UL;
 	u32 tmp = 0;
 
-	tmp = inp32(addr);
+	tmp = readl(addr);
 	tmp &= ~(mask << bs);
 
-	outp32(addr, tmp | ((val & mask) << bs));
+	writel(tmp | ((val & mask) << bs), addr);
 }
 
 void dsi_set_output_client(struct drm_device *dev)
@@ -1078,11 +1078,11 @@ static void dsi_mipi_init(struct dw_dsi *dsi, char __iomem *mipi_dsi_base,
 	set_reg(mipi_dsi_base + MIPIDSI_CLKMGR_CFG_OFFSET, dsi->phy.clk_division, 8, 0);
 	set_reg(mipi_dsi_base + MIPIDSI_CLKMGR_CFG_OFFSET, dsi->phy.clk_division, 8, 8);
 
-	outp32(mipi_dsi_base + MIPIDSI_PHY_RSTZ_OFFSET, 0x00000000);
+	writel(0x00000000, mipi_dsi_base + MIPIDSI_PHY_RSTZ_OFFSET);
 
-	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);
+	writel(0x00000000, mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET);
+	writel(0x00000001, mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET);
+	writel(0x00000000, mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET);
 
 #if defined(CONFIG_DRM_HISI_KIRIN970)
 	dsi_phy_tst_set(mipi_dsi_base, 0x0042, 0x21);
@@ -1194,12 +1194,12 @@ static void dsi_mipi_init(struct dw_dsi *dsi, char __iomem *mipi_dsi_base,
 	}
 #endif
 
-	outp32(mipi_dsi_base + MIPIDSI_PHY_RSTZ_OFFSET, 0x00000007);
+	writel(0x00000007, mipi_dsi_base + MIPIDSI_PHY_RSTZ_OFFSET);
 
 	is_ready = false;
 	dw_jiffies = jiffies + HZ / 2;
 	do {
-		tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+		tmp = readl(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
 		if ((tmp & 0x00000001) == 0x00000001) {
 			is_ready = true;
 			break;
@@ -1223,7 +1223,7 @@ static void dsi_mipi_init(struct dw_dsi *dsi, char __iomem *mipi_dsi_base,
 	is_ready = false;
 	dw_jiffies = jiffies + HZ / 2;
 	do {
-		tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
+		tmp = readl(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
 		if ((tmp & cmp_stopstate_val) == cmp_stopstate_val) {
 			is_ready = true;
 			break;
@@ -1383,7 +1383,7 @@ static int mipi_dsi_on_sub1(struct dw_dsi *dsi, char __iomem *mipi_dsi_base,
 
 	/* dsi memory init */
 #if defined(CONFIG_DRM_HISI_KIRIN970)
-	outp32(mipi_dsi_base + DSI_MEM_CTRL, 0x02600008);
+	writel(0x02600008, mipi_dsi_base + DSI_MEM_CTRL);
 #endif
 
 	/* switch to cmd mode */
@@ -1422,7 +1422,7 @@ static int mipi_dsi_on_sub2(struct dw_dsi *dsi, char __iomem *mipi_dsi_base)
 	DRM_DEBUG("pctrl_dphytx_stopcnt = %llu\n", pctrl_dphytx_stopcnt);
 
 	//FIXME:
-	outp32(dsi->ctx->pctrl_base + PERI_CTRL29, (u32)pctrl_dphytx_stopcnt);
+	writel((u32)pctrl_dphytx_stopcnt, dsi->ctx->pctrl_base + PERI_CTRL29);
 #endif
 
 	return 0;
@@ -2015,7 +2015,7 @@ static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi)
 	DRM_INFO("dsi  cur_client is %d  <0->hdmi;1->panel>\n", dsi->cur_client);
 	/*dis-reset*/
 	/*ip_reset_dis_dsi0, ip_reset_dis_dsi1*/
-	outp32(ctx->peri_crg_base + PERRSTDIS3, 0x30000000);
+	writel(0x30000000, ctx->peri_crg_base + PERRSTDIS3);
 
 	ctx->dss_dphy0_ref_clk = devm_clk_get(&pdev->dev, "clk_txdphy0_ref");
 	if (IS_ERR(ctx->dss_dphy0_ref_clk)) {
diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_pwm.c b/drivers/staging/hikey9xx/gpu/kirin9xx_pwm.c
index 519e8f0232de..c920734e6332 100644
--- a/drivers/staging/hikey9xx/gpu/kirin9xx_pwm.c
+++ b/drivers/staging/hikey9xx/gpu/kirin9xx_pwm.c
@@ -177,14 +177,14 @@ int hisi_pwm_set_backlight(struct backlight_device *bl, uint32_t bl_level)
 
 	bl_level = (bl_level * PWM_OUT_PRECISION) / bl_max;
 
-	outp32(pwm_base + PWM_LOCK_OFFSET, 0x1acce551);
-	outp32(pwm_base + PWM_CTL_OFFSET, 0x0);
-	outp32(pwm_base + PWM_CFG_OFFSET, 0x2);
-	outp32(pwm_base + PWM_PR0_OFFSET, 0x1);
-	outp32(pwm_base + PWM_PR1_OFFSET, 0x2);
-	outp32(pwm_base + PWM_CTL_OFFSET, 0x1);
-	outp32(pwm_base + PWM_C0_MR_OFFSET, (PWM_OUT_PRECISION - 1));
-	outp32(pwm_base + PWM_C0_MR0_OFFSET, bl_level);
+	writel(0x1acce551, pwm_base + PWM_LOCK_OFFSET);
+	writel(0x0, pwm_base + PWM_CTL_OFFSET);
+	writel(0x2, pwm_base + PWM_CFG_OFFSET);
+	writel(0x1, pwm_base + PWM_PR0_OFFSET);
+	writel(0x2, pwm_base + PWM_PR1_OFFSET);
+	writel(0x1, pwm_base + PWM_CTL_OFFSET);
+	writel((PWM_OUT_PRECISION - 1), pwm_base + PWM_C0_MR_OFFSET);
+	writel(bl_level, pwm_base + PWM_C0_MR0_OFFSET);
 
 	return 0;
 }
@@ -214,7 +214,7 @@ int hisi_pwm_on(void)
 		return 0;
 
 	// dis-reset pwm
-	outp32(peri_crg_base + PERRSTDIS2, 0x1);
+	writel(0x1, peri_crg_base + PERRSTDIS2);
 
 	clk_tmp = g_pwm_clk;
 	if (clk_tmp) {
@@ -276,7 +276,7 @@ int hisi_pwm_off(void)
 	}
 
 	//reset pwm
-	outp32(peri_crg_base + PERRSTEN2, 0x1);
+	writel(0x1, peri_crg_base + PERRSTEN2);
 
 	g_pwm_on = 0;
 
-- 
2.26.2


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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-19 11:45 [PATCH 00/49] DRM driver for Hikey 970 Mauro Carvalho Chehab
  2020-08-19 11:45 ` [PATCH 01/49] staging: hikey9xx: Add hisilicon DRM driver for hikey960/970 Mauro Carvalho Chehab
  2020-08-19 11:46 ` [PATCH 40/49] staging: hikey9xx/gpu: get rid of input/output macros Mauro Carvalho Chehab
@ 2020-08-19 15:21 ` Sam Ravnborg
  2020-08-19 15:30   ` Laurent Pinchart
       [not found]   ` <20200819174027.70b39ee9@coco.lan>
  2020-08-19 21:13 ` John Stultz
  2020-08-19 21:36 ` John Stultz
  4 siblings, 2 replies; 42+ messages in thread
From: Sam Ravnborg @ 2020-08-19 15:21 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Greg Kroah-Hartman, Neil Armstrong, Xinliang Liu, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Laurent Pinchart, devel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	David Airlie, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Laurentiu Palcu, linux-media, devicetree, Liwei Cai,
	Jesper Dangaard Brouer, Manivannan Sadhasivam, Chen Feng,
	Alexei Starovoitov, linaro-mm-sig, Rob Herring, Jakub Kicinski,
	mauro.chehab, Rob Clark, linux-arm-kernel, netdev, linux-kernel,
	Liuyao An, Rongrong Zou, bpf, David S. Miller

Hi Mauro.

On Wed, Aug 19, 2020 at 01:45:28PM +0200, Mauro Carvalho Chehab wrote:
> This patch series port the out-of-tree driver for Hikey 970 (which
> should also support Hikey 960) from the official 96boards tree:
> 
>    https://github.com/96boards-hikey/linux/tree/hikey970-v4.9
> 
> Based on his history, this driver seems to be originally written
> for Kernel 4.4, and was later ported to Kernel 4.9. The original
> driver used to depend on ION (from Kernel 4.4) and had its own
> implementation for FB dev API.
> 
> As I need to preserve the original history (with has patches from
> both HiSilicon and from Linaro),  I'm starting from the original
> patch applied there. The remaining patches are incremental,
> and port this driver to work with upstream Kernel.
> 
> This driver doesn't depend on any firmware or on any special
> userspace code. It works as-is with both X11 and Wayland.
> 
> Yet, I'm submitting it via staging due to the following reasons:
> 
> - It depends on the LDO3 power supply, which is provided by
>   a regulator driver that it is currently on staging;
> - Due to legal reasons, I need to preserve the authorship of
>   each one responsbile for each patch. So, I need to start from
>   the original patch from Kernel 4.4;
> - There are still some problems I need to figure out how to solve:
>    - The adv7535 can't get EDID data. Maybe it is a timing issue,
>      but it requires more research to be sure about how to solve it;
>    - The driver only accept resolutions on a defined list, as there's
>      a known bug that this driver may have troubles with random
>      resolutions. Probably due to a bug at the pixel clock settings;
>    - Sometimes (at least with 1080p), it generates LDI underflow
>      errors, which in turn causes the DRM to stop working. That
>      happens for example when using gdm on Wayland and
>      gnome on X11;
>    - Probably related to the previous issue, when the monitor
>      suspends due to DPMS, it doesn't return back to life.
> 
> So, IMO, the best is to keep it on staging for a while, until those
> remaining bugs gets solved.
> 
> I added this series, together with the regulator driver and
> a few other patches (including a hack to fix a Kernel 5.8 
> regression at WiFi ) at:
> 
> 	https://gitlab.freedesktop.org/mchehab_kernel/hikey-970/-/commits/master
> 
> 
> Chen Feng (1):
>   staging: hikey9xx: Add hisilicon DRM driver for hikey960/970
> 
> John Stultz (1):
>   staging: hikey9xx/gpu: port it to work with Kernel v4.9
> 
> Liwei Cai (2):
>   staging: hikey9xx/gpu: solve tearing issue of display
>   staging: hikey9xx/gpu: resolve the performance issue by interrupt
>     mechanism
> 
> Mauro Carvalho Chehab (38):
>   staging: hikey9xx/gpu: get rid of adv7535 fork
Very good - I was in my mind starting a rant why we needed a fork of
this driver, but I see it gets deleted again.

I do acknowledge you need to preserve history and all -
but this patchset is not easy to review.

Could you follow-up with a review-able set of patches as a follow-up
for this?
I spotted some wrong bridge handling in one patch but I do not know if
this got changed in a later patch. And I lost the motivation to go
looking for it.


>   staging: hikey9xx/gpu: rename the Kirin9xx namespace
>   staging: hikey9xx/gpu: get rid of kirin9xx_fbdev.c
>   staging: hikey9xx/gpu: get rid of some ifdefs
>   staging: hikey9xx/gpu: rename the config option for Kirin970
>   staging: hikey9xx/gpu: change the includes to reflect upstream
>   staging: hikey9xx/gpu: port driver to upstream kAPIs
>   staging: hikey9xx/gpu: add a copy of set_reg() function there
>   staging: hikey9xx/gpu: get rid of ION headers
>   staging: hikey9xx/gpu: add support for using a reserved CMA memory
>   staging: hikey9xx/gpu: cleanup encoder attach logic
>   staging: hikey9xx/gpu: Change the logic which sets the burst mode
>   staging: hikey9xx/gpu: fix the DRM setting logic
>   staging: hikey9xx/gpu: do some code cleanups
>   staging: hikey9xx/gpu: use default GEM_CMA fops
>   staging: hikey9xx/gpu: place vblank enable/disable at the right place
>   staging: hikey9xx/gpu: remove an uneeded hack
>   staging: hikey9xx/gpu: add a possible implementation for
>     atomic_disable
>   staging: hikey9xx/gpu: register connector
>   staging: hikey9xx/gpu: fix driver name
>   staging: hikey9xx/gpu: get rid of iommu_format
>   staging: hikey9xx/gpu: re-work the mode validation code
>   staging: hikey9xx/gpu: add support for enable/disable ldo3 regulator
>   staging: hikey9xx/gpu: add SPMI headers
>   staging: hikey9xx/gpu: solve most coding style issues
>   staging: hikey9xx/gpu: don't use iommu code
>   staging: hikey9xx/gpu: add kirin9xx driver to the building system
>   staging: hikey9xx/gpu: get rid of typedefs
>   staging: hikey9xx/gpu: get rid of input/output macros
>   staging: hikey9xx/gpu: get rid of some unused data
>   staging: hikey9xx/gpu: place common definitions at kirin9xx_dpe.h
>   staging: hikey9xx/gpu: get rid of DRM_HISI_KIRIN970
>   dts: hisilicon: hi3670.dtsi: add I2C settings
>   dts: hikey970-pinctrl.dtsi: add missing pinctrl settings
>   dt: hisilicon: add support for the PMIC found on Hikey 970
>   dts: add support for Hikey 970 DRM
>   staging: hikey9xx/gpu: drop kirin9xx_pwm
>   dt: display: Add binds for the DPE and DSI controller for Kirin
>     960/970
> 
> Xiubin Zhang (7):
>   staging: hikey9xx/gpu: add support to hikey970 HDMI and panel
>   staging: hikey9xx/gpu: Solve SR Cannot Display Problems.
>   staging: hikey9xx/gpu: Solve HDMI compatibility Problem.
>   staging: hikey9xx/gpu: Support MIPI DSI 3 lanes for hikey970.
>   staging: hikey9xx/gpu: Solve SR test reset problem for hikey970.
>   staging: hikey9xx/gpu: add debug prints for this driver
>   staging: hikey9xx/gpu: Add support 10.1 inch special HDMI displays.
> 
>  .../display/hisilicon,hi3660-dpe.yaml         |   99 +
>  .../display/hisilicon,hi3660-dsi.yaml         |  102 +
>  .../boot/dts/hisilicon/hi3670-hikey970.dts    |   56 +-
>  arch/arm64/boot/dts/hisilicon/hi3670.dtsi     |   77 +
>  .../boot/dts/hisilicon/hikey970-drm.dtsi      |   93 +
>  .../boot/dts/hisilicon/hikey970-pinctrl.dtsi  |  548 +++-
>  .../boot/dts/hisilicon/hikey970-pmic.dtsi     |  197 ++
>  drivers/staging/hikey9xx/Kconfig              |    3 +
>  drivers/staging/hikey9xx/Makefile             |    1 +
>  drivers/staging/hikey9xx/gpu/Kconfig          |   22 +
>  drivers/staging/hikey9xx/gpu/Makefile         |    9 +
>  drivers/staging/hikey9xx/gpu/kirin960_defs.c  |  378 +++
>  .../staging/hikey9xx/gpu/kirin960_dpe_reg.h   |  233 ++
>  drivers/staging/hikey9xx/gpu/kirin970_defs.c  |  381 +++
>  .../staging/hikey9xx/gpu/kirin970_dpe_reg.h   | 1188 ++++++++
>  drivers/staging/hikey9xx/gpu/kirin9xx_dpe.h   | 2437 +++++++++++++++++
>  .../hikey9xx/gpu/kirin9xx_drm_dpe_utils.c     | 1178 ++++++++
>  .../hikey9xx/gpu/kirin9xx_drm_dpe_utils.h     |  286 ++
>  .../staging/hikey9xx/gpu/kirin9xx_drm_drv.c   |  368 +++
>  .../staging/hikey9xx/gpu/kirin9xx_drm_drv.h   |   57 +
>  .../staging/hikey9xx/gpu/kirin9xx_drm_dss.c   | 1063 +++++++
>  .../hikey9xx/gpu/kirin9xx_drm_overlay_utils.c | 1005 +++++++
>  .../hikey9xx/gpu/kirin9xx_dw_drm_dsi.c        | 2132 ++++++++++++++
>  .../hikey9xx/gpu/kirin9xx_dw_dsi_reg.h        |  146 +
>  .../staging/hikey9xx/gpu/kirin9xx_fb_panel.h  |  191 ++
>  25 files changed, 12229 insertions(+), 21 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/display/hisilicon,hi3660-dpe.yaml
>  create mode 100644 Documentation/devicetree/bindings/display/hisilicon,hi3660-dsi.yaml

Patch that intropduce new bindings must following the submitting patches
guidelines for bindings. For once the subject is "dt-bindings: bla bla".

	Sam

>  create mode 100644 arch/arm64/boot/dts/hisilicon/hikey970-drm.dtsi
>  create mode 100644 arch/arm64/boot/dts/hisilicon/hikey970-pmic.dtsi
>  create mode 100644 drivers/staging/hikey9xx/gpu/Kconfig
>  create mode 100644 drivers/staging/hikey9xx/gpu/Makefile
>  create mode 100644 drivers/staging/hikey9xx/gpu/kirin960_defs.c
>  create mode 100644 drivers/staging/hikey9xx/gpu/kirin960_dpe_reg.h
>  create mode 100644 drivers/staging/hikey9xx/gpu/kirin970_defs.c
>  create mode 100644 drivers/staging/hikey9xx/gpu/kirin970_dpe_reg.h
>  create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_dpe.h
>  create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_drm_dpe_utils.c
>  create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_drm_dpe_utils.h
>  create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.c
>  create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.h
>  create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_drm_dss.c
>  create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c
>  create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_dw_drm_dsi.c
>  create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_dw_dsi_reg.h
>  create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_fb_panel.h
> 
> -- 
> 2.26.2
> 
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-19 15:21 ` [PATCH 00/49] DRM driver for Hikey 970 Sam Ravnborg
@ 2020-08-19 15:30   ` Laurent Pinchart
  2020-08-19 19:52     ` John Stultz
       [not found]   ` <20200819174027.70b39ee9@coco.lan>
  1 sibling, 1 reply; 42+ messages in thread
From: Laurent Pinchart @ 2020-08-19 15:30 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: Mauro Carvalho Chehab, Greg Kroah-Hartman, Neil Armstrong,
	Xinliang Liu, Wanchun Zheng, linuxarm, dri-devel, Andrzej Hajda,
	devel, Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	David Airlie, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Laurentiu Palcu, linux-media, devicetree, Liwei Cai,
	Jesper Dangaard Brouer, Manivannan Sadhasivam, Chen Feng,
	Alexei Starovoitov, linaro-mm-sig, Rob Herring, Jakub Kicinski,
	mauro.chehab, Rob Clark, linux-arm-kernel, netdev, linux-kernel,
	Liuyao An, Rongrong Zou, bpf, David S. Miller

On Wed, Aug 19, 2020 at 05:21:20PM +0200, Sam Ravnborg wrote:
> Hi Mauro.
> 
> On Wed, Aug 19, 2020 at 01:45:28PM +0200, Mauro Carvalho Chehab wrote:
> > This patch series port the out-of-tree driver for Hikey 970 (which
> > should also support Hikey 960) from the official 96boards tree:
> > 
> >    https://github.com/96boards-hikey/linux/tree/hikey970-v4.9
> > 
> > Based on his history, this driver seems to be originally written
> > for Kernel 4.4, and was later ported to Kernel 4.9. The original
> > driver used to depend on ION (from Kernel 4.4) and had its own
> > implementation for FB dev API.
> > 
> > As I need to preserve the original history (with has patches from
> > both HiSilicon and from Linaro),  I'm starting from the original
> > patch applied there. The remaining patches are incremental,
> > and port this driver to work with upstream Kernel.
> > 
> > This driver doesn't depend on any firmware or on any special
> > userspace code. It works as-is with both X11 and Wayland.
> > 
> > Yet, I'm submitting it via staging due to the following reasons:
> > 
> > - It depends on the LDO3 power supply, which is provided by
> >   a regulator driver that it is currently on staging;
> > - Due to legal reasons, I need to preserve the authorship of
> >   each one responsbile for each patch. So, I need to start from
> >   the original patch from Kernel 4.4;
> > - There are still some problems I need to figure out how to solve:
> >    - The adv7535 can't get EDID data. Maybe it is a timing issue,
> >      but it requires more research to be sure about how to solve it;
> >    - The driver only accept resolutions on a defined list, as there's
> >      a known bug that this driver may have troubles with random
> >      resolutions. Probably due to a bug at the pixel clock settings;
> >    - Sometimes (at least with 1080p), it generates LDI underflow
> >      errors, which in turn causes the DRM to stop working. That
> >      happens for example when using gdm on Wayland and
> >      gnome on X11;
> >    - Probably related to the previous issue, when the monitor
> >      suspends due to DPMS, it doesn't return back to life.
> > 
> > So, IMO, the best is to keep it on staging for a while, until those
> > remaining bugs gets solved.
> > 
> > I added this series, together with the regulator driver and
> > a few other patches (including a hack to fix a Kernel 5.8 
> > regression at WiFi ) at:
> > 
> > 	https://gitlab.freedesktop.org/mchehab_kernel/hikey-970/-/commits/master
> > 
> > 
> > Chen Feng (1):
> >   staging: hikey9xx: Add hisilicon DRM driver for hikey960/970
> > 
> > John Stultz (1):
> >   staging: hikey9xx/gpu: port it to work with Kernel v4.9
> > 
> > Liwei Cai (2):
> >   staging: hikey9xx/gpu: solve tearing issue of display
> >   staging: hikey9xx/gpu: resolve the performance issue by interrupt
> >     mechanism
> > 
> > Mauro Carvalho Chehab (38):
> >   staging: hikey9xx/gpu: get rid of adv7535 fork
> Very good - I was in my mind starting a rant why we needed a fork of
> this driver, but I see it gets deleted again.
> 
> I do acknowledge you need to preserve history and all -
> but this patchset is not easy to review.

Why do we need to preserve history ? Adding relevant Signed-off-by and
Co-developed-by should be enough, shouldn't it ? Having a public branch
that contains the history is useful if anyone is interested, but I don't
think it's required in mainline.

> Could you follow-up with a review-able set of patches as a follow-up
> for this?
> I spotted some wrong bridge handling in one patch but I do not know if
> this got changed in a later patch. And I lost the motivation to go
> looking for it.
> 
> >   staging: hikey9xx/gpu: rename the Kirin9xx namespace
> >   staging: hikey9xx/gpu: get rid of kirin9xx_fbdev.c
> >   staging: hikey9xx/gpu: get rid of some ifdefs
> >   staging: hikey9xx/gpu: rename the config option for Kirin970
> >   staging: hikey9xx/gpu: change the includes to reflect upstream
> >   staging: hikey9xx/gpu: port driver to upstream kAPIs
> >   staging: hikey9xx/gpu: add a copy of set_reg() function there
> >   staging: hikey9xx/gpu: get rid of ION headers
> >   staging: hikey9xx/gpu: add support for using a reserved CMA memory
> >   staging: hikey9xx/gpu: cleanup encoder attach logic
> >   staging: hikey9xx/gpu: Change the logic which sets the burst mode
> >   staging: hikey9xx/gpu: fix the DRM setting logic
> >   staging: hikey9xx/gpu: do some code cleanups
> >   staging: hikey9xx/gpu: use default GEM_CMA fops
> >   staging: hikey9xx/gpu: place vblank enable/disable at the right place
> >   staging: hikey9xx/gpu: remove an uneeded hack
> >   staging: hikey9xx/gpu: add a possible implementation for
> >     atomic_disable
> >   staging: hikey9xx/gpu: register connector
> >   staging: hikey9xx/gpu: fix driver name
> >   staging: hikey9xx/gpu: get rid of iommu_format
> >   staging: hikey9xx/gpu: re-work the mode validation code
> >   staging: hikey9xx/gpu: add support for enable/disable ldo3 regulator
> >   staging: hikey9xx/gpu: add SPMI headers
> >   staging: hikey9xx/gpu: solve most coding style issues
> >   staging: hikey9xx/gpu: don't use iommu code
> >   staging: hikey9xx/gpu: add kirin9xx driver to the building system
> >   staging: hikey9xx/gpu: get rid of typedefs
> >   staging: hikey9xx/gpu: get rid of input/output macros
> >   staging: hikey9xx/gpu: get rid of some unused data
> >   staging: hikey9xx/gpu: place common definitions at kirin9xx_dpe.h
> >   staging: hikey9xx/gpu: get rid of DRM_HISI_KIRIN970
> >   dts: hisilicon: hi3670.dtsi: add I2C settings
> >   dts: hikey970-pinctrl.dtsi: add missing pinctrl settings
> >   dt: hisilicon: add support for the PMIC found on Hikey 970
> >   dts: add support for Hikey 970 DRM
> >   staging: hikey9xx/gpu: drop kirin9xx_pwm
> >   dt: display: Add binds for the DPE and DSI controller for Kirin
> >     960/970
> > 
> > Xiubin Zhang (7):
> >   staging: hikey9xx/gpu: add support to hikey970 HDMI and panel
> >   staging: hikey9xx/gpu: Solve SR Cannot Display Problems.
> >   staging: hikey9xx/gpu: Solve HDMI compatibility Problem.
> >   staging: hikey9xx/gpu: Support MIPI DSI 3 lanes for hikey970.
> >   staging: hikey9xx/gpu: Solve SR test reset problem for hikey970.
> >   staging: hikey9xx/gpu: add debug prints for this driver
> >   staging: hikey9xx/gpu: Add support 10.1 inch special HDMI displays.
> > 
> >  .../display/hisilicon,hi3660-dpe.yaml         |   99 +
> >  .../display/hisilicon,hi3660-dsi.yaml         |  102 +
> >  .../boot/dts/hisilicon/hi3670-hikey970.dts    |   56 +-
> >  arch/arm64/boot/dts/hisilicon/hi3670.dtsi     |   77 +
> >  .../boot/dts/hisilicon/hikey970-drm.dtsi      |   93 +
> >  .../boot/dts/hisilicon/hikey970-pinctrl.dtsi  |  548 +++-
> >  .../boot/dts/hisilicon/hikey970-pmic.dtsi     |  197 ++
> >  drivers/staging/hikey9xx/Kconfig              |    3 +
> >  drivers/staging/hikey9xx/Makefile             |    1 +
> >  drivers/staging/hikey9xx/gpu/Kconfig          |   22 +
> >  drivers/staging/hikey9xx/gpu/Makefile         |    9 +
> >  drivers/staging/hikey9xx/gpu/kirin960_defs.c  |  378 +++
> >  .../staging/hikey9xx/gpu/kirin960_dpe_reg.h   |  233 ++
> >  drivers/staging/hikey9xx/gpu/kirin970_defs.c  |  381 +++
> >  .../staging/hikey9xx/gpu/kirin970_dpe_reg.h   | 1188 ++++++++
> >  drivers/staging/hikey9xx/gpu/kirin9xx_dpe.h   | 2437 +++++++++++++++++
> >  .../hikey9xx/gpu/kirin9xx_drm_dpe_utils.c     | 1178 ++++++++
> >  .../hikey9xx/gpu/kirin9xx_drm_dpe_utils.h     |  286 ++
> >  .../staging/hikey9xx/gpu/kirin9xx_drm_drv.c   |  368 +++
> >  .../staging/hikey9xx/gpu/kirin9xx_drm_drv.h   |   57 +
> >  .../staging/hikey9xx/gpu/kirin9xx_drm_dss.c   | 1063 +++++++
> >  .../hikey9xx/gpu/kirin9xx_drm_overlay_utils.c | 1005 +++++++
> >  .../hikey9xx/gpu/kirin9xx_dw_drm_dsi.c        | 2132 ++++++++++++++
> >  .../hikey9xx/gpu/kirin9xx_dw_dsi_reg.h        |  146 +
> >  .../staging/hikey9xx/gpu/kirin9xx_fb_panel.h  |  191 ++
> >  25 files changed, 12229 insertions(+), 21 deletions(-)
> >  create mode 100644 Documentation/devicetree/bindings/display/hisilicon,hi3660-dpe.yaml
> >  create mode 100644 Documentation/devicetree/bindings/display/hisilicon,hi3660-dsi.yaml
> 
> Patch that intropduce new bindings must following the submitting patches
> guidelines for bindings. For once the subject is "dt-bindings: bla bla".
> 
> >  create mode 100644 arch/arm64/boot/dts/hisilicon/hikey970-drm.dtsi
> >  create mode 100644 arch/arm64/boot/dts/hisilicon/hikey970-pmic.dtsi
> >  create mode 100644 drivers/staging/hikey9xx/gpu/Kconfig
> >  create mode 100644 drivers/staging/hikey9xx/gpu/Makefile
> >  create mode 100644 drivers/staging/hikey9xx/gpu/kirin960_defs.c
> >  create mode 100644 drivers/staging/hikey9xx/gpu/kirin960_dpe_reg.h
> >  create mode 100644 drivers/staging/hikey9xx/gpu/kirin970_defs.c
> >  create mode 100644 drivers/staging/hikey9xx/gpu/kirin970_dpe_reg.h
> >  create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_dpe.h
> >  create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_drm_dpe_utils.c
> >  create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_drm_dpe_utils.h
> >  create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.c
> >  create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.h
> >  create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_drm_dss.c
> >  create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c
> >  create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_dw_drm_dsi.c
> >  create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_dw_dsi_reg.h
> >  create mode 100644 drivers/staging/hikey9xx/gpu/kirin9xx_fb_panel.h

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-19 15:30   ` Laurent Pinchart
@ 2020-08-19 19:52     ` John Stultz
  2020-08-20  7:03       ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 42+ messages in thread
From: John Stultz @ 2020-08-19 19:52 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Sam Ravnborg, Neil Armstrong, David Airlie, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, driverdevel, Daniel Borkmann,
	Mauro Carvalho Chehab, John Fastabend, Xiubin Zhang, Wei Xu,
	Xinliang Liu, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Jakub Kicinski, Laurentiu Palcu, linux-media,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Liwei Cai, Jesper Dangaard Brouer, Manivannan Sadhasivam,
	Chen Feng, Alexei Starovoitov,
	moderated list:DMA BUFFER SHARING FRAMEWORK, Rob Herring,
	mauro.chehab, Rob Clark, linux-arm-kernel, Greg Kroah-Hartman,
	lkml, Liuyao An, Network Development, Rongrong Zou,
	BPF Mailing List, David S. Miller

On Wed, Aug 19, 2020 at 8:31 AM Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> On Wed, Aug 19, 2020 at 05:21:20PM +0200, Sam Ravnborg wrote:
> > On Wed, Aug 19, 2020 at 01:45:28PM +0200, Mauro Carvalho Chehab wrote:
> > > This patch series port the out-of-tree driver for Hikey 970 (which
> > > should also support Hikey 960) from the official 96boards tree:
> > >
> > >    https://github.com/96boards-hikey/linux/tree/hikey970-v4.9
> > >
> > > Based on his history, this driver seems to be originally written
> > > for Kernel 4.4, and was later ported to Kernel 4.9. The original
> > > driver used to depend on ION (from Kernel 4.4) and had its own
> > > implementation for FB dev API.
> > >
> > > As I need to preserve the original history (with has patches from
> > > both HiSilicon and from Linaro),  I'm starting from the original
> > > patch applied there. The remaining patches are incremental,
> > > and port this driver to work with upstream Kernel.
> > >
...
> > > - Due to legal reasons, I need to preserve the authorship of
> > >   each one responsbile for each patch. So, I need to start from
> > >   the original patch from Kernel 4.4;
...
> > I do acknowledge you need to preserve history and all -
> > but this patchset is not easy to review.
>
> Why do we need to preserve history ? Adding relevant Signed-off-by and
> Co-developed-by should be enough, shouldn't it ? Having a public branch
> that contains the history is useful if anyone is interested, but I don't
> think it's required in mainline.

Yea. I concur with Laurent here. I'm not sure what legal reasoning you
have on this but preserving the "absolute" history here is actively
detrimental for review and understanding of the patch set.

Preserving Authorship, Signed-off-by lines and adding Co-developed-by
lines should be sufficient to provide both atribution credit and DCO
history.

thanks
-john

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-19 11:45 [PATCH 00/49] DRM driver for Hikey 970 Mauro Carvalho Chehab
                   ` (2 preceding siblings ...)
  2020-08-19 15:21 ` [PATCH 00/49] DRM driver for Hikey 970 Sam Ravnborg
@ 2020-08-19 21:13 ` John Stultz
  2020-08-19 21:25   ` Sam Ravnborg
  2020-08-20  6:34   ` Mauro Carvalho Chehab
  2020-08-19 21:36 ` John Stultz
  4 siblings, 2 replies; 42+ messages in thread
From: John Stultz @ 2020-08-19 21:13 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Greg Kroah-Hartman, linuxarm, mauro.chehab,
	Manivannan Sadhasivam, Daniel Vetter, dri-devel, Bogdan Togorean,
	Liwei Cai, linux-arm-kernel, Daniel Borkmann, Rob Herring,
	David S. Miller, Xinliang Liu, Neil Armstrong, Wanchun Zheng,
	driverdevel, BPF Mailing List, Xiubin Zhang, linux-media,
	Tomi Valkeinen, Jesper Dangaard Brouer, Laurent Pinchart,
	Xinwei Kong, Alexei Starovoitov,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Rob Clark, Laurentiu Palcu, Andrzej Hajda, John Fastabend,
	Liuyao An, moderated list:DMA BUFFER SHARING FRAMEWORK, Wei Xu,
	Rongrong Zou, Philipp Zabel, Sam Ravnborg, Network Development,
	Sumit Semwal, lkml, Jakub Kicinski, David Airlie, Chen Feng

On Wed, Aug 19, 2020 at 4:46 AM Mauro Carvalho Chehab
<mchehab+huawei@kernel.org> wrote:
> Yet, I'm submitting it via staging due to the following reasons:
>
> - It depends on the LDO3 power supply, which is provided by
>   a regulator driver that it is currently on staging;
> - Due to legal reasons, I need to preserve the authorship of
>   each one responsbile for each patch. So, I need to start from
>   the original patch from Kernel 4.4;
> - There are still some problems I need to figure out how to solve:
>    - The adv7535 can't get EDID data. Maybe it is a timing issue,
>      but it requires more research to be sure about how to solve it;

I've seen this on the HiKey960 as well. There is a patch to the
adv7533 driver I have to add a mdelay that seems to consistently
resolve the timing problem.  At some point I mentioned it to one of
the maintainers who seems open to having it added, but it seemed silly
to submit it until there was a upstream driver that needed such a
change.  So I think that patch can be submitted as a follow on to this
(hopefully cleaned up) series.

>    - The driver only accept resolutions on a defined list, as there's
>      a known bug that this driver may have troubles with random
>      resolutions. Probably due to a bug at the pixel clock settings;

So, yes, the SoC clks can't generate proper signals for HDMI
frequencies (apparently it's not an issue for panels). There is a
fixed set that we can get "close enough" that most monitors will work,
but its always a bit iffy (some monitors are strict in what they
take).

On the kirin driver, we were able to do a calculation to figure out if
the generated frequency would be close enough:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c#n615

I suspect we could do something similar for the hikey960/70, but I've
not really had time to dig in deeply there.

Personally, I don't see the allow-list as a problematic short term
solution, and again, not sure its worth pushing to staging for.

>    - Sometimes (at least with 1080p), it generates LDI underflow
>      errors, which in turn causes the DRM to stop working. That
>      happens for example when using gdm on Wayland and
>      gnome on X11;

Interestingly, I've not seen this on HiKey960 (at least with
Android/Surfaceflinger). The original HiKey board does have the
trouble where at 1080p the screen sometimes comes up horizontally
offset due to the LDI underflow, but the patches to address it have
been worse then the problem, so we reverted those.

>    - Probably related to the previous issue, when the monitor
>      suspends due to DPMS, it doesn't return back to life.
>

I don't believe I see this on HiKey960. But if it's the LDI issue on
the 970 that may explain it.


> So, IMO, the best is to keep it on staging for a while, until those
> remaining bugs gets solved.

I'm not sure I see all of these as compelling for pushing it in via
staging. And I suspect in the process of submitting the patches for
review folks may find the cause of some of the problems you list here.


> I added this series, together with the regulator driver and
> a few other patches (including a hack to fix a Kernel 5.8
> regression at WiFi ) at:
>
>         https://gitlab.freedesktop.org/mchehab_kernel/hikey-970/-/commits/master
>
>
> Chen Feng (1):
>   staging: hikey9xx: Add hisilicon DRM driver for hikey960/970
>
> John Stultz (1):
>   staging: hikey9xx/gpu: port it to work with Kernel v4.9

Nit: This is a display driver and has little to do with the GPU (other
then it will eventually live in drivers/gpu/drm/...), so I might
suggest using more conventional subject prefix,  "drm: hisilicon:"

thanks
-john

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-19 21:13 ` John Stultz
@ 2020-08-19 21:25   ` Sam Ravnborg
  2020-08-20  6:40     ` Mauro Carvalho Chehab
  2020-08-20  6:34   ` Mauro Carvalho Chehab
  1 sibling, 1 reply; 42+ messages in thread
From: Sam Ravnborg @ 2020-08-19 21:25 UTC (permalink / raw)
  To: John Stultz
  Cc: Mauro Carvalho Chehab, Greg Kroah-Hartman, linuxarm,
	mauro.chehab, Manivannan Sadhasivam, Daniel Vetter, dri-devel,
	Bogdan Togorean, Liwei Cai, linux-arm-kernel, Daniel Borkmann,
	Rob Herring, David S. Miller, Xinliang Liu, Neil Armstrong,
	Wanchun Zheng, driverdevel, BPF Mailing List, Xiubin Zhang,
	linux-media, Tomi Valkeinen, Jesper Dangaard Brouer,
	Laurent Pinchart, Xinwei Kong, Alexei Starovoitov,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Rob Clark, Laurentiu Palcu, Andrzej Hajda, John Fastabend,
	Liuyao An, moderated list:DMA BUFFER SHARING FRAMEWORK, Wei Xu,
	Rongrong Zou, Philipp Zabel, Network Development, Sumit Semwal,
	lkml, Jakub Kicinski, David Airlie, Chen Feng

Hi John.

> > So, IMO, the best is to keep it on staging for a while, until those
> > remaining bugs gets solved.
> 
> I'm not sure I see all of these as compelling for pushing it in via
> staging. And I suspect in the process of submitting the patches for
> review folks may find the cause of some of the problems you list here.

There is a tendency to forget drivers in staging, and with the almost
constant refactoring that happens in the drm drivers we would end up
fixing this driver when a bot trigger an error.
So IMO we need very good reasons to go in via staging.

	Sam

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-19 11:45 [PATCH 00/49] DRM driver for Hikey 970 Mauro Carvalho Chehab
                   ` (3 preceding siblings ...)
  2020-08-19 21:13 ` John Stultz
@ 2020-08-19 21:36 ` John Stultz
  2020-08-20  2:01   ` John Stultz
  2020-08-20  8:04   ` Mauro Carvalho Chehab
  4 siblings, 2 replies; 42+ messages in thread
From: John Stultz @ 2020-08-19 21:36 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Greg Kroah-Hartman, linuxarm, mauro.chehab,
	Manivannan Sadhasivam, Daniel Vetter, dri-devel, Bogdan Togorean,
	Liwei Cai, linux-arm-kernel, Daniel Borkmann, Rob Herring,
	David S. Miller, Xinliang Liu, Neil Armstrong, Wanchun Zheng,
	driverdevel, BPF Mailing List, Xiubin Zhang, linux-media,
	Tomi Valkeinen, Jesper Dangaard Brouer, Laurent Pinchart,
	Xinwei Kong, Alexei Starovoitov,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Rob Clark, Laurentiu Palcu, Andrzej Hajda, John Fastabend,
	Liuyao An, moderated list:DMA BUFFER SHARING FRAMEWORK, Wei Xu,
	Rongrong Zou, Philipp Zabel, Sam Ravnborg, Network Development,
	Sumit Semwal, lkml, Jakub Kicinski, David Airlie, Chen Feng

On Wed, Aug 19, 2020 at 4:46 AM Mauro Carvalho Chehab
<mchehab+huawei@kernel.org> wrote:
> So, IMO, the best is to keep it on staging for a while, until those
> remaining bugs gets solved.
>
> I added this series, together with the regulator driver and
> a few other patches (including a hack to fix a Kernel 5.8
> regression at WiFi ) at:
>
>         https://gitlab.freedesktop.org/mchehab_kernel/hikey-970/-/commits/master

Sorry, one more small request: Could you create a branch that only has
the DRM driver changes in it?

The reason I ask, is that since the HiKey960 isn't affected by the
majority of the problems you listed as motivation for going through
staging. So if we can validate that your tree works fine on HiKey960,
the series can be cleaned up and submitted properly upstream to enable
that SoC, and the outstanding 970 issues can be worked out afterwards
against mainline.

thanks
-john

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-19 21:36 ` John Stultz
@ 2020-08-20  2:01   ` John Stultz
  2020-08-20  3:28     ` John Stultz
  2020-08-20  8:04   ` Mauro Carvalho Chehab
  1 sibling, 1 reply; 42+ messages in thread
From: John Stultz @ 2020-08-20  2:01 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Greg Kroah-Hartman, linuxarm, mauro.chehab,
	Manivannan Sadhasivam, Daniel Vetter, dri-devel, Bogdan Togorean,
	Liwei Cai, linux-arm-kernel, Daniel Borkmann, Rob Herring,
	David S. Miller, Xinliang Liu, Neil Armstrong, Wanchun Zheng,
	driverdevel, BPF Mailing List, linux-media, Tomi Valkeinen,
	Jesper Dangaard Brouer, Laurent Pinchart, Xinwei Kong,
	Alexei Starovoitov,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Rob Clark, Laurentiu Palcu, Andrzej Hajda, John Fastabend,
	Liuyao An, moderated list:DMA BUFFER SHARING FRAMEWORK, Wei Xu,
	Rongrong Zou, Philipp Zabel, Sam Ravnborg, Network Development,
	Sumit Semwal, lkml, Jakub Kicinski, David Airlie, Chen Feng

On Wed, Aug 19, 2020 at 2:36 PM John Stultz <john.stultz@linaro.org> wrote:
>
> On Wed, Aug 19, 2020 at 4:46 AM Mauro Carvalho Chehab
> <mchehab+huawei@kernel.org> wrote:
> > So, IMO, the best is to keep it on staging for a while, until those
> > remaining bugs gets solved.
> >
> > I added this series, together with the regulator driver and
> > a few other patches (including a hack to fix a Kernel 5.8
> > regression at WiFi ) at:
> >
> >         https://gitlab.freedesktop.org/mchehab_kernel/hikey-970/-/commits/master
>
> Sorry, one more small request: Could you create a branch that only has
> the DRM driver changes in it?
>
> The reason I ask, is that since the HiKey960 isn't affected by the
> majority of the problems you listed as motivation for going through
> staging. So if we can validate that your tree works fine on HiKey960,
> the series can be cleaned up and submitted properly upstream to enable
> that SoC, and the outstanding 970 issues can be worked out afterwards
> against mainline.

Just as a heads up, I tried testing your tree with my HiKey960, and
after fixing the compat string inconsistency, the drivers seem to load
properly. However the drm_hwcomposer seems to have some trouble with
the driver:
01-01 00:12:41.456   345   345 E hwc-drm-display-compositor: Commit
test failed for display 0, FIXME
01-01 00:12:41.456   345   345 E hwc-drm-two: Failed to apply the
frame composition ret=-22
01-01 00:12:41.456   351   351 E HWComposer:
presentAndGetReleaseFences: present failed for display 0: BadParameter
(4)

I'll dig in a bit further as to why, but wanted to give you a heads up.

thanks
-john

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-20  2:01   ` John Stultz
@ 2020-08-20  3:28     ` John Stultz
  2020-08-20  7:48       ` Mauro Carvalho Chehab
  2020-08-24  6:49       ` Mauro Carvalho Chehab
  0 siblings, 2 replies; 42+ messages in thread
From: John Stultz @ 2020-08-20  3:28 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Greg Kroah-Hartman, linuxarm, mauro.chehab,
	Manivannan Sadhasivam, Daniel Vetter, dri-devel, Bogdan Togorean,
	Liwei Cai, linux-arm-kernel, Daniel Borkmann, Rob Herring,
	David S. Miller, Xinliang Liu, Neil Armstrong, Wanchun Zheng,
	driverdevel, BPF Mailing List, linux-media, Tomi Valkeinen,
	Jesper Dangaard Brouer, Laurent Pinchart, Xinwei Kong,
	Alexei Starovoitov,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Rob Clark, Laurentiu Palcu, Andrzej Hajda, John Fastabend,
	Liuyao An, moderated list:DMA BUFFER SHARING FRAMEWORK, Wei Xu,
	Rongrong Zou, Philipp Zabel, Sam Ravnborg, Network Development,
	Sumit Semwal, lkml, Jakub Kicinski, David Airlie, Chen Feng

On Wed, Aug 19, 2020 at 7:01 PM John Stultz <john.stultz@linaro.org> wrote:
>
> On Wed, Aug 19, 2020 at 2:36 PM John Stultz <john.stultz@linaro.org> wrote:
> >
> > On Wed, Aug 19, 2020 at 4:46 AM Mauro Carvalho Chehab
> > <mchehab+huawei@kernel.org> wrote:
> > > So, IMO, the best is to keep it on staging for a while, until those
> > > remaining bugs gets solved.
> > >
> > > I added this series, together with the regulator driver and
> > > a few other patches (including a hack to fix a Kernel 5.8
> > > regression at WiFi ) at:
> > >
> > >         https://gitlab.freedesktop.org/mchehab_kernel/hikey-970/-/commits/master
> >
> > Sorry, one more small request: Could you create a branch that only has
> > the DRM driver changes in it?
> >
> > The reason I ask, is that since the HiKey960 isn't affected by the
> > majority of the problems you listed as motivation for going through
> > staging. So if we can validate that your tree works fine on HiKey960,
> > the series can be cleaned up and submitted properly upstream to enable
> > that SoC, and the outstanding 970 issues can be worked out afterwards
> > against mainline.
>
> Just as a heads up, I tried testing your tree with my HiKey960, and
> after fixing the compat string inconsistency, the drivers seem to load
> properly. However the drm_hwcomposer seems to have some trouble with
> the driver:
> 01-01 00:12:41.456   345   345 E hwc-drm-display-compositor: Commit
> test failed for display 0, FIXME
> 01-01 00:12:41.456   345   345 E hwc-drm-two: Failed to apply the
> frame composition ret=-22
> 01-01 00:12:41.456   351   351 E HWComposer:
> presentAndGetReleaseFences: present failed for display 0: BadParameter
> (4)
>
> I'll dig in a bit further as to why, but wanted to give you a heads up.

Ok, I've mostly gotten it sorted out:
  - You're missing a few color formats.
  - And I re-discovered a crash that was already fixed in my tree.

I'll send those patches in a few here.

That said even with the patches I've got on top of your series, I
still see a few issues:
1) I'm seeing red-blue swap with your driver.  I need to dig a bit to
see what the difference is, I know gralloc has a config option for
this, and maybe the version of the driver I'm carrying has it wrong?
2) Performance is noticeably worse. Whereas with my tree, I see close
to 60fps (that clk issue we mentioned earlier is why it's not exactly
60) in most tests, but with yours it mostly hovers around 30some fps,
occasionally speeding up to 40 and then back down.

Obviously with some work I suspect we'll be able to sort these out,
but I also do feel that the set you're starting with for upstreaming
is pretty old. The driver I'm carrying was heavily refactored around
5.0 to share code with the existing kirin driver, in the hopes of
making usptreaming easier, and it seems a shame to throw that out and
focus your efforts on the older tree.

But to be fair, I've not had time to upstream the driver myself, and
it's obviously your choice on how you spend your time.  I am really
excited to see your efforts here, regardless of which driver you end
up pushing.

thanks
-john

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-19 21:13 ` John Stultz
  2020-08-19 21:25   ` Sam Ravnborg
@ 2020-08-20  6:34   ` Mauro Carvalho Chehab
  1 sibling, 0 replies; 42+ messages in thread
From: Mauro Carvalho Chehab @ 2020-08-20  6:34 UTC (permalink / raw)
  To: John Stultz
  Cc: Greg Kroah-Hartman, linuxarm, mauro.chehab,
	Manivannan Sadhasivam, Daniel Vetter, dri-devel, Bogdan Togorean,
	Liwei Cai, linux-arm-kernel, Daniel Borkmann, Rob Herring,
	David S. Miller, Xinliang Liu, Neil Armstrong, Wanchun Zheng,
	driverdevel, BPF Mailing List, Xiubin Zhang, linux-media,
	Tomi Valkeinen, Jesper Dangaard Brouer, Laurent Pinchart,
	Xinwei Kong, Alexei Starovoitov,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Rob Clark, Laurentiu Palcu, Andrzej Hajda, John Fastabend,
	Liuyao An, moderated list:DMA BUFFER SHARING FRAMEWORK, Wei Xu,
	Rongrong Zou, Philipp Zabel, Sam Ravnborg, Network Development,
	Sumit Semwal, lkml, Jakub Kicinski, David Airlie, Chen Feng

Em Wed, 19 Aug 2020 14:13:05 -0700
John Stultz <john.stultz@linaro.org> escreveu:

> On Wed, Aug 19, 2020 at 4:46 AM Mauro Carvalho Chehab
> <mchehab+huawei@kernel.org> wrote:
> > Yet, I'm submitting it via staging due to the following reasons:
> >
> > - It depends on the LDO3 power supply, which is provided by
> >   a regulator driver that it is currently on staging;
> > - Due to legal reasons, I need to preserve the authorship of
> >   each one responsbile for each patch. So, I need to start from
> >   the original patch from Kernel 4.4;
> > - There are still some problems I need to figure out how to solve:
> >    - The adv7535 can't get EDID data. Maybe it is a timing issue,
> >      but it requires more research to be sure about how to solve it;  
> 
> I've seen this on the HiKey960 as well. There is a patch to the
> adv7533 driver I have to add a mdelay that seems to consistently
> resolve the timing problem.  At some point I mentioned it to one of
> the maintainers who seems open to having it added, but it seemed silly
> to submit it until there was a upstream driver that needed such a
> change.  So I think that patch can be submitted as a follow on to this
> (hopefully cleaned up) series.

Yeah, I saw that mdelay() patch on your tree. While it should be cheap
to add a mdelay() or udelay_range() there, I'm not sure if this is just a 
timing issue or if something else is missing. The 4.9 driver does some 
extra setups on adv7535 (see the enclosed patch).

I'm wondering if something from that is missing. Btw, IMHO, one
interesting setting on the downstream code is support for colorbar test.
This was helpful when I was making this driver work upstream, as it
could be useful for someone trying to make some other DRM driver using it.

> 
> >    - The driver only accept resolutions on a defined list, as there's
> >      a known bug that this driver may have troubles with random
> >      resolutions. Probably due to a bug at the pixel clock settings;  
> 
> So, yes, the SoC clks can't generate proper signals for HDMI
> frequencies (apparently it's not an issue for panels). There is a
> fixed set that we can get "close enough" that most monitors will work,
> but its always a bit iffy (some monitors are strict in what they
> take).

There is an extra logic for Kirin 620 that seems to be validating
the frequencies that would be set to the clocks. If they're out of
the range, it would return MODE_BAD. I suspect that something similar
would be needed for Kirin 970 and 960. With that regards, 970 is
different from 960. I actually tried to write a patch for it, but
I guess there are still some things missing on my code, for 970.

This patch:

	https://gitlab.freedesktop.org/mchehab_kernel/hikey-970/-/commit/4614415770b33e27a9f15c7dde20895fb750592f

Splits the part of the code which calculates the clk_Hz from the
part which sets it. So, now, dss_calculate_clock() checks the
pixel clock frequency and adjusts it, if needed. 

I have another patch that were checking if the code modified the
clock_Hz at dss_crtc_mode_fixup(). With that, it would be easy to
return MODE_INVALID if something bad happens. However, such
patch didn't work as I would expect, so I ended dropping it.

> On the kirin driver, we were able to do a calculation to figure out if
> the generated frequency would be close enough:
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c#n615
> 
> I suspect we could do something similar for the hikey960/70, but I've
> not really had time to dig in deeply there.

Yeah, I tried something similar to that. Maybe it will work properly
for Hikey 960, but Hikey 970 has a much more complex code to setup
the pixel clock. On 960, just one clock is set:

	clk_set_rate(ctx->dss_pxl0_clk, clk_Hz);

While, on 970, pxl0 is always set to the same frequency (144 MHz),
at least for pixel clocks up to 255 MHz[1], but the code do some
complex calculus to setup PLL7 registers using the clock frequency. 

[1] pixel clocks above 255 MHz will be rejected anyway, as they'll
return MODE_BAD due to the checks if a mode is valid.

> 
> Personally, I don't see the allow-list as a problematic short term
> solution, and again, not sure its worth pushing to staging for.

Yeah, I guess we can live with that for a while.

> 
> >    - Sometimes (at least with 1080p), it generates LDI underflow
> >      errors, which in turn causes the DRM to stop working. That
> >      happens for example when using gdm on Wayland and
> >      gnome on X11;  
> 
> Interestingly, I've not seen this on HiKey960 (at least with
> Android/Surfaceflinger).

Here, it happens all the time when the monitor returns back from DPMS
suspend. It also happens on some specific cases (X11 x Wayland), 
console mode + startx, etc.

It sounds to me that it occurs when the driver tries to setup a new
resolution. Maybe something needs to be disabled before changing res
(and re-enabled afterwards).

> The original HiKey board does have the
> trouble where at 1080p the screen sometimes comes up horizontally
> offset due to the LDI underflow, but the patches to address it have
> been worse then the problem, so we reverted those.

The "visible" effect on my monitor is that the image disappears, 
and the monitor complains that there's an "Invalid Mode" at the HDMI
signal.

> 
> >    - Probably related to the previous issue, when the monitor
> >      suspends due to DPMS, it doesn't return back to life.
> >  
> 
> I don't believe I see this on HiKey960. But if it's the LDI issue on
> the 970 that may explain it.

Yes, when this happens, I get LDI underflow messages.

> > So, IMO, the best is to keep it on staging for a while, until those
> > remaining bugs gets solved.  
> 
> I'm not sure I see all of these as compelling for pushing it in via
> staging. And I suspect in the process of submitting the patches for
> review folks may find the cause of some of the problems you list here.

Yeah, I hope we can get rid of at least part of those during the
review process ;-)

Yet, I'd like to preserve the history. As the enclosed patch shows,
maybe there are some hidden gems at the previously existing code.

I may also have done something wrong when converting the driver.
So, preserving the history seems to be a good idea to me.

One of the advantages of using staging is that the full history
will be preserved at the incremental code at staging, while the
final patch moving the code out of staging will have all the changes
folded together into a single patch.

That makes easier for people to do a final review on it.

Also, some subsystem maintainers don't like the idea of merging the
entire history on their subsystems.

> Nit: This is a display driver and has little to do with the GPU (other
> then it will eventually live in drivers/gpu/drm/...), so I might
> suggest using more conventional subject prefix,  "drm: hisilicon:"

Ah, OK! I'll change the prefix at the next versions of this series.

Thanks,
Mauro

HACK: Some changes from downstream to adv7511 code

diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h
index a9bb734366ae..1440c08caf42 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511.h
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h
@@ -333,6 +333,7 @@ struct adv7511 {
 
 	struct regmap *regmap;
 	struct regmap *regmap_cec;
+	struct regmap *regmap_packet;
 	enum drm_connector_status status;
 	bool powered;
 
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index d59b37a2ae23..c9fbcb40f962 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -325,6 +325,153 @@ static void adv7511_set_link_config(struct adv7511 *adv7511,
 	adv7511->rgb = config->input_colorspace == HDMI_COLORSPACE_RGB;
 }
 
+static void adv7511_dsi_config_tgen(struct adv7511 *adv7511)
+{
+	struct drm_display_mode *mode = &adv7511->curr_mode;
+	unsigned int hsw, hfp, hbp, vsw, vfp, vbp;
+#ifndef TEST_COLORBAR_DISPLAY
+	u8 clock_div_by_lanes[] = { 6, 4, 3 }; /* 2, 3, 4 lanes */
+#endif
+
+	hsw = mode->hsync_end - mode->hsync_start;
+	hfp = mode->hsync_start - mode->hdisplay;
+	hbp = mode->htotal - mode->hsync_end;
+	vsw = mode->vsync_end - mode->vsync_start;
+	vfp = mode->vsync_start - mode->vdisplay;
+	vbp = mode->vtotal - mode->vsync_end;
+
+#ifdef TEST_COLORBAR_DISPLAY
+	/* set pixel clock auto mode */
+	regmap_write(adv7511->regmap_cec, 0x16,
+			0x00);
+#else
+	/* set pixel clock divider mode */
+	regmap_write(adv7511->regmap_cec, 0x16,
+			clock_div_by_lanes[adv7511->num_dsi_lanes - 2] << 3);
+#endif
+
+	/* horizontal porch params */
+	regmap_write(adv7511->regmap_cec, 0x28, mode->htotal >> 4);
+	regmap_write(adv7511->regmap_cec, 0x29, (mode->htotal << 4) & 0xff);
+	regmap_write(adv7511->regmap_cec, 0x2a, hsw >> 4);
+	regmap_write(adv7511->regmap_cec, 0x2b, (hsw << 4) & 0xff);
+	regmap_write(adv7511->regmap_cec, 0x2c, hfp >> 4);
+	regmap_write(adv7511->regmap_cec, 0x2d, (hfp << 4) & 0xff);
+	regmap_write(adv7511->regmap_cec, 0x2e, hbp >> 4);
+	regmap_write(adv7511->regmap_cec, 0x2f, (hbp << 4) & 0xff);
+
+	/* vertical porch params */
+	regmap_write(adv7511->regmap_cec, 0x30, mode->vtotal >> 4);
+	regmap_write(adv7511->regmap_cec, 0x31, (mode->vtotal << 4) & 0xff);
+	regmap_write(adv7511->regmap_cec, 0x32, vsw >> 4);
+	regmap_write(adv7511->regmap_cec, 0x33, (vsw << 4) & 0xff);
+	regmap_write(adv7511->regmap_cec, 0x34, vfp >> 4);
+	regmap_write(adv7511->regmap_cec, 0x35, (vfp << 4) & 0xff);
+	regmap_write(adv7511->regmap_cec, 0x36, vbp >> 4);
+	regmap_write(adv7511->regmap_cec, 0x37, (vbp << 4) & 0xff);
+}
+
+static void hikey970_hack_dpms(struct adv7511 *adv7511)
+{
+
+DRM_ERROR("Calling %s\n", __func__);
+
+	struct mipi_dsi_device *dsi = adv7511->dsi;
+
+	adv7511_dsi_config_tgen(adv7511);
+
+	/* set number of dsi lanes */
+	regmap_write(adv7511->regmap_cec, 0x1c, dsi->lanes << 4);
+
+#ifdef TEST_COLORBAR_DISPLAY
+	/* reset internal timing generator */
+	regmap_write(adv7511->regmap_cec, 0x27, 0xcb);
+	regmap_write(adv7511->regmap_cec, 0x27, 0x8b);
+	regmap_write(adv7511->regmap_cec, 0x27, 0xcb);
+#else
+	/* disable internal timing generator */
+	regmap_write(adv7511->regmap_cec, 0x27, 0x0b);
+#endif
+
+
+	/* enable hdmi */
+	regmap_write(adv7511->regmap_cec, 0x03, 0x89);
+#ifdef TEST_COLORBAR_DISPLAY
+	/*enable test mode */
+	regmap_write(adv7511->regmap_cec, 0x55, 0x80);//display colorbar
+#else
+	/* disable test mode */
+	regmap_write(adv7511->regmap_cec, 0x55, 0x00);
+#endif
+	/* disable test mode */
+	//regmap_write(adv7511->regmap_cec, 0x55, 0x00);
+	/* 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(adv7511->regmap_packet, n, spd_if[n]);
+
+		/* enable send SPD */
+		regmap_update_bits(adv7511->regmap, 0x40, BIT(6), BIT(6));
+	}
+
+	/* force audio */
+	/* hide Audio infoframe updates */
+	regmap_update_bits(adv7511->regmap, 0x4a, BIT(5), BIT(5));
+
+	/* i2s, internal mclk, mclk-256 */
+	regmap_update_bits(adv7511->regmap, 0x0a, 0x1f, 1);
+	regmap_update_bits(adv7511->regmap, 0x0b, 0xe0, 0);
+	/* enable i2s, use i2s format, sample rate from i2s */
+	regmap_update_bits(adv7511->regmap, 0x0c, 0xc7, BIT(2));
+	/* 16 bit audio */
+	regmap_update_bits(adv7511->regmap, 0x0d, 0xff, 16);
+	/* 16-bit audio */
+	regmap_update_bits(adv7511->regmap, 0x14, 0x0f, 2 << 4);
+	/* 48kHz */
+	regmap_update_bits(adv7511->regmap, 0x15, 0xf0, 2 << 4);
+	/* enable N/CTS, enable Audio sample packets */
+	regmap_update_bits(adv7511->regmap, 0x44, BIT(5), BIT(5));
+	/* N = 6144 */
+	regmap_write(adv7511->regmap, 1, (6144 >> 16) & 0xf);
+	regmap_write(adv7511->regmap, 2, (6144 >> 8) & 0xff);
+	regmap_write(adv7511->regmap, 3, (6144) & 0xff);
+	/* automatic cts */
+	regmap_update_bits(adv7511->regmap, 0x0a, BIT(7), 0);
+	/* enable N/CTS */
+	regmap_update_bits(adv7511->regmap, 0x44, BIT(6), BIT(6));
+	/* not copyrighted */
+	regmap_update_bits(adv7511->regmap, 0x12, BIT(5), BIT(5));
+
+	/* left source */
+	regmap_update_bits(adv7511->regmap, 0x0e, 7 << 3, 0);
+	/* right source */
+	regmap_update_bits(adv7511->regmap, 0x0e, 7 << 0, 1);
+	/* number of channels: sect 4.5.4: set to 0 */
+	regmap_update_bits(adv7511->regmap, 0x73, 7, 1);
+	/* number of channels: sect 4.5.4: set to 0 */
+	regmap_update_bits(adv7511->regmap, 0x73, 0xf0, 1 << 4);
+	/* sample rate: 48kHz */
+	regmap_update_bits(adv7511->regmap, 0x74, 7 << 2, 3 << 2);
+	/* channel allocation reg: sect 4.5.4: set to 0 */
+	regmap_update_bits(adv7511->regmap, 0x76, 0xff, 0);
+	/* enable audio infoframes */
+	regmap_update_bits(adv7511->regmap, 0x44, BIT(3), BIT(3));
+
+	/* AV mute disable */
+	regmap_update_bits(adv7511->regmap, 0x4b, BIT(7) | BIT(6), BIT(7));
+
+	/* use Audio infoframe updated info */
+	regmap_update_bits(adv7511->regmap, 0x4a, BIT(5), 0);
+}
+
 static void __adv7511_power_on(struct adv7511 *adv7511)
 {
 	adv7511->current_edid_segment = -1;
@@ -367,8 +514,10 @@ static void adv7511_power_on(struct adv7511 *adv7511)
 	 */
 	regcache_sync(adv7511->regmap);
 
-	if (adv7511->type == ADV7533 || adv7511->type == ADV7535)
+	if (adv7511->type == ADV7533 || adv7511->type == ADV7535) {
 		adv7533_dsi_power_on(adv7511);
+		hikey970_hack_dpms(adv7511);
+	}
 	adv7511->powered = true;
 }
 
@@ -981,8 +1130,10 @@ static int adv7511_init_regulators(struct adv7511 *adv)
 		adv->supplies[i].supply = supply_names[i];
 
 	ret = devm_regulator_bulk_get(dev, adv->num_supplies, adv->supplies);
-	if (ret)
+	if (ret) {
+		dev_err(dev, "Can't get all regulators\n");
 		return ret;
+	}
 
 	return regulator_bulk_enable(adv->num_supplies, adv->supplies);
 }
@@ -1022,6 +1173,14 @@ static const struct regmap_config adv7511_cec_regmap_config = {
 	.volatile_reg = adv7511_cec_register_volatile,
 };
 
+static const struct regmap_config adv7533_packet_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = 0xff,
+	.cache_type = REGCACHE_RBTREE,
+};
+
 static int adv7511_init_cec_regmap(struct adv7511 *adv)
 {
 	int ret;
@@ -1045,6 +1204,14 @@ static int adv7511_init_cec_regmap(struct adv7511 *adv)
 			goto err;
 	}
 
+	adv->regmap_packet = devm_regmap_init_i2c(adv->i2c_packet,
+						      &adv7533_packet_regmap_config);
+	if (IS_ERR(adv->regmap_packet)) {
+		ret = PTR_ERR(adv->regmap_packet);
+		goto err;
+	}
+
+
 	return 0;
 err:
 	i2c_unregister_device(adv->i2c_cec);
@@ -1168,8 +1335,8 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
 		return ret;
 
 	ret = adv7511_init_regulators(adv7511);
-	if (ret != -EPROBE_DEFER) {
-		dev_err(dev, "failed to init regulators\n");
+	if (ret && ret != -EPROBE_DEFER) {
+		dev_err(dev, "failed to init regulators: %d\n", ret);
 		return ret;
 	}
 



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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-19 21:25   ` Sam Ravnborg
@ 2020-08-20  6:40     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 42+ messages in thread
From: Mauro Carvalho Chehab @ 2020-08-20  6:40 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: John Stultz, Greg Kroah-Hartman, linuxarm, mauro.chehab,
	Manivannan Sadhasivam, Daniel Vetter, dri-devel, Bogdan Togorean,
	Liwei Cai, linux-arm-kernel, Daniel Borkmann, Rob Herring,
	David S. Miller, Xinliang Liu, Neil Armstrong, Wanchun Zheng,
	driverdevel, BPF Mailing List, Xiubin Zhang, linux-media,
	Tomi Valkeinen, Jesper Dangaard Brouer, Laurent Pinchart,
	Xinwei Kong, Alexei Starovoitov,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Rob Clark, Laurentiu Palcu, Andrzej Hajda, John Fastabend,
	Liuyao An, moderated list:DMA BUFFER SHARING FRAMEWORK, Wei Xu,
	Rongrong Zou, Philipp Zabel, Network Development, Sumit Semwal,
	lkml, Jakub Kicinski, David Airlie, Chen Feng

Em Wed, 19 Aug 2020 23:25:51 +0200
Sam Ravnborg <sam@ravnborg.org> escreveu:

> Hi John.
> 
> > > So, IMO, the best is to keep it on staging for a while, until those
> > > remaining bugs gets solved.  
> > 
> > I'm not sure I see all of these as compelling for pushing it in via
> > staging. And I suspect in the process of submitting the patches for
> > review folks may find the cause of some of the problems you list here.  
> 
> There is a tendency to forget drivers in staging, and with the almost
> constant refactoring that happens in the drm drivers we would end up
> fixing this driver when a bot trigger an error.
> So IMO we need very good reasons to go in via staging.

My plan is to have this driver upstream for 5.10, and getting it
out of staging by Kernel 5.11. So, I doubt that the DRM kAPIs would
change a lot during those 2 Kernel cycles.

In any case, I'm also fine to have a final patch at the end of this
series moving it out of staging. The only thing that, IMHO, prevents
it to be out of staging is the LDI underflow. Right now, if no input
events reach the driver, DPMS will put the monitor to suspend, and
it never returns back from life. I bet that, once we discover the
root cause, the fix would be just a couple of lines, but identifying
where the problem is can take a while.

Thanks,
Mauro

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-19 19:52     ` John Stultz
@ 2020-08-20  7:03       ` Mauro Carvalho Chehab
  2020-08-20 10:02         ` Laurent Pinchart
  0 siblings, 1 reply; 42+ messages in thread
From: Mauro Carvalho Chehab @ 2020-08-20  7:03 UTC (permalink / raw)
  To: John Stultz
  Cc: Laurent Pinchart, Sam Ravnborg, Neil Armstrong, David Airlie,
	Wanchun Zheng, linuxarm, dri-devel, Andrzej Hajda, driverdevel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	Xinliang Liu, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Jakub Kicinski, Laurentiu Palcu, linux-media,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Liwei Cai, Jesper Dangaard Brouer, Manivannan Sadhasivam,
	Chen Feng, Alexei Starovoitov,
	moderated list:DMA BUFFER SHARING FRAMEWORK, Rob Herring,
	mauro.chehab, Rob Clark, linux-arm-kernel, Greg Kroah-Hartman,
	lkml, Liuyao An, Network Development, Rongrong Zou,
	BPF Mailing List, David S. Miller

Em Wed, 19 Aug 2020 12:52:06 -0700
John Stultz <john.stultz@linaro.org> escreveu:

> On Wed, Aug 19, 2020 at 8:31 AM Laurent Pinchart
> <laurent.pinchart@ideasonboard.com> wrote:
> > On Wed, Aug 19, 2020 at 05:21:20PM +0200, Sam Ravnborg wrote:  
> > > On Wed, Aug 19, 2020 at 01:45:28PM +0200, Mauro Carvalho Chehab wrote:  
> > > > This patch series port the out-of-tree driver for Hikey 970 (which
> > > > should also support Hikey 960) from the official 96boards tree:
> > > >
> > > >    https://github.com/96boards-hikey/linux/tree/hikey970-v4.9
> > > >
> > > > Based on his history, this driver seems to be originally written
> > > > for Kernel 4.4, and was later ported to Kernel 4.9. The original
> > > > driver used to depend on ION (from Kernel 4.4) and had its own
> > > > implementation for FB dev API.
> > > >
> > > > As I need to preserve the original history (with has patches from
> > > > both HiSilicon and from Linaro),  I'm starting from the original
> > > > patch applied there. The remaining patches are incremental,
> > > > and port this driver to work with upstream Kernel.
> > > >  
> ...
> > > > - Due to legal reasons, I need to preserve the authorship of
> > > >   each one responsbile for each patch. So, I need to start from
> > > >   the original patch from Kernel 4.4;  
> ...
> > > I do acknowledge you need to preserve history and all -
> > > but this patchset is not easy to review.  
> >
> > Why do we need to preserve history ? Adding relevant Signed-off-by and
> > Co-developed-by should be enough, shouldn't it ? Having a public branch
> > that contains the history is useful if anyone is interested, but I don't
> > think it's required in mainline.  
> 
> Yea. I concur with Laurent here. I'm not sure what legal reasoning you
> have on this but preserving the "absolute" history here is actively
> detrimental for review and understanding of the patch set.
> 
> Preserving Authorship, Signed-off-by lines and adding Co-developed-by
> lines should be sufficient to provide both atribution credit and DCO
> history.

I'm not convinced that, from legal standpoint, folding things would
be enough. See, there are at least 3 legal systems involved here
among the different patch authors:

	- civil law;
	- common law;
	- customary law + common law.

Merging stuff altogether from different law systems can be problematic,
and trying to discuss this with experienced IP property lawyers will
for sure take a lot of time and efforts. I also bet that different
lawyers will have different opinions, because laws are subject to 
interpretation. With that matter I'm not aware of any court rules 
with regards to folded patches. So, it sounds to me that folding 
patches is something that has yet to be proofed in courts around
the globe.

At least for US legal system, it sounds that the Country of
origin of a patch is relevant, as they have a concept of
"national technology" that can be subject to export regulations.

From my side, I really prefer to play safe and stay out of any such
legal discussions.

Thanks,
Mauro

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
       [not found]     ` <20200819204800.GA110118@ravnborg.org>
@ 2020-08-20  7:21       ` Michel Dänzer
  2020-08-20  7:21       ` Mauro Carvalho Chehab
  2020-08-21 16:09       ` Joe Perches
  2 siblings, 0 replies; 42+ messages in thread
From: Michel Dänzer @ 2020-08-20  7:21 UTC (permalink / raw)
  To: Sam Ravnborg, Mauro Carvalho Chehab
  Cc: Neil Armstrong, Xinliang Liu, Wanchun Zheng, linuxarm, dri-devel,
	Andrzej Hajda, Laurent Pinchart, devel, Daniel Borkmann,
	John Fastabend, Xiubin Zhang, Wei Xu, David Airlie, Xinwei Kong,
	Tomi Valkeinen, Bogdan Togorean, Jakub Kicinski, Laurentiu Palcu,
	linux-media, devicetree, Liwei Cai, Jesper Dangaard Brouer,
	Manivannan Sadhasivam, Chen Feng, Alexei Starovoitov,
	linaro-mm-sig, Rob Herring, mauro.chehab, Rob Clark,
	linux-arm-kernel, Greg Kroah-Hartman, linux-kernel, Liuyao An,
	netdev, Rongrong Zou, bpf, David S. Miller

On 2020-08-19 10:48 p.m., Sam Ravnborg wrote:
> Hi Mauro.
> 
> It seems my review comments failed to reach dri-devel - likely due to
> the size of the mail.

Right, some e-mails in this thread went through the dri-devel moderation
queue due to their sizes. This mail of yours did as well, because you
didn't trim the quoted text (hint, hint).


-- 
Earthling Michel Dänzer               |               https://redhat.com
Libre software enthusiast             |             Mesa and X developer

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
       [not found]     ` <20200819204800.GA110118@ravnborg.org>
  2020-08-20  7:21       ` Michel Dänzer
@ 2020-08-20  7:21       ` Mauro Carvalho Chehab
  2020-08-21 16:09       ` Joe Perches
  2 siblings, 0 replies; 42+ messages in thread
From: Mauro Carvalho Chehab @ 2020-08-20  7:21 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: Greg Kroah-Hartman, Neil Armstrong, Xinliang Liu, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Laurent Pinchart, devel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	David Airlie, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Laurentiu Palcu, linux-media, devicetree, Liwei Cai,
	Jesper Dangaard Brouer, Manivannan Sadhasivam, Chen Feng,
	Alexei Starovoitov, linaro-mm-sig, Rob Herring, Jakub Kicinski,
	mauro.chehab, Rob Clark, linux-arm-kernel, netdev, linux-kernel,
	Liuyao An, Rongrong Zou, bpf, David S. Miller

Hi Sam,

Em Wed, 19 Aug 2020 22:48:00 +0200
Sam Ravnborg <sam@ravnborg.org> escreveu:

> Hi Mauro.
> 
> It seems my review comments failed to reach dri-devel - likely due to
> the size of the mail.

Probably. It reached here properly.

> Link:
> https://lore.kernel.org/linux-devicetree/20200819173558.GA3733@ravnborg.org/
> 
> I my review feedback I refer to checkpatch a few time.
> For drivers/gpu/ we have some nice tooling support.
> One thing our tooling does for us is running checkpatch every time
> we apply a patch.
> 
>     checkpatch -q --emacs --strict --show-types
> 
> So we expect patches to be more or less checkpatch --strict clean.
> 
> "more or less" - as common sense also plays a role.
> And sometimes checkpatch is just wrong.
> 
> Just in case you wondered why checkpatch --strict was requested.

We also use checkpatch --strict for media as a reference,
ignoring the things that would make things worse during review :-)

I'll run checkpatch here and ensure that the coding style
issues will be properly addressed.

Thanks,
Mauro

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-20  3:28     ` John Stultz
@ 2020-08-20  7:48       ` Mauro Carvalho Chehab
  2020-08-24  6:49       ` Mauro Carvalho Chehab
  1 sibling, 0 replies; 42+ messages in thread
From: Mauro Carvalho Chehab @ 2020-08-20  7:48 UTC (permalink / raw)
  To: John Stultz
  Cc: Greg Kroah-Hartman, linuxarm, mauro.chehab,
	Manivannan Sadhasivam, Daniel Vetter, dri-devel, Bogdan Togorean,
	Liwei Cai, linux-arm-kernel, Daniel Borkmann, Rob Herring,
	David S. Miller, Xinliang Liu, Neil Armstrong, Wanchun Zheng,
	driverdevel, BPF Mailing List, linux-media, Tomi Valkeinen,
	Jesper Dangaard Brouer, Laurent Pinchart, Xinwei Kong,
	Alexei Starovoitov,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Rob Clark, Laurentiu Palcu, Andrzej Hajda, John Fastabend,
	Liuyao An, moderated list:DMA BUFFER SHARING FRAMEWORK, Wei Xu,
	Rongrong Zou, Philipp Zabel, Sam Ravnborg, Network Development,
	Sumit Semwal, lkml, Jakub Kicinski, David Airlie, Chen Feng

Em Wed, 19 Aug 2020 20:28:44 -0700
John Stultz <john.stultz@linaro.org> escreveu:

> On Wed, Aug 19, 2020 at 7:01 PM John Stultz <john.stultz@linaro.org> wrote:
> >
> > On Wed, Aug 19, 2020 at 2:36 PM John Stultz <john.stultz@linaro.org> wrote:  
> > >
> > > On Wed, Aug 19, 2020 at 4:46 AM Mauro Carvalho Chehab
> > > <mchehab+huawei@kernel.org> wrote:  
> > > > So, IMO, the best is to keep it on staging for a while, until those
> > > > remaining bugs gets solved.
> > > >
> > > > I added this series, together with the regulator driver and
> > > > a few other patches (including a hack to fix a Kernel 5.8
> > > > regression at WiFi ) at:
> > > >
> > > >         https://gitlab.freedesktop.org/mchehab_kernel/hikey-970/-/commits/master  
> > >
> > > Sorry, one more small request: Could you create a branch that only has
> > > the DRM driver changes in it?
> > >
> > > The reason I ask, is that since the HiKey960 isn't affected by the
> > > majority of the problems you listed as motivation for going through
> > > staging. So if we can validate that your tree works fine on HiKey960,
> > > the series can be cleaned up and submitted properly upstream to enable
> > > that SoC, and the outstanding 970 issues can be worked out afterwards
> > > against mainline.  
> >
> > Just as a heads up, I tried testing your tree with my HiKey960, and
> > after fixing the compat string inconsistency, the drivers seem to load
> > properly. However the drm_hwcomposer seems to have some trouble with
> > the driver:
> > 01-01 00:12:41.456   345   345 E hwc-drm-display-compositor: Commit
> > test failed for display 0, FIXME
> > 01-01 00:12:41.456   345   345 E hwc-drm-two: Failed to apply the
> > frame composition ret=-22
> > 01-01 00:12:41.456   351   351 E HWComposer:
> > presentAndGetReleaseFences: present failed for display 0: BadParameter
> > (4)
> >
> > I'll dig in a bit further as to why, but wanted to give you a heads up.  
> 
> Ok, I've mostly gotten it sorted out:
>   - You're missing a few color formats.
>   - And I re-discovered a crash that was already fixed in my tree.
> 
> I'll send those patches in a few here.

Thank you for the patches! I'll test them with Hikey 970 in order to
be sure they're compatible also with such SoC.

> 
> That said even with the patches I've got on top of your series, I
> still see a few issues:

> 1) I'm seeing red-blue swap with your driver.  I need to dig a bit to
> see what the difference is, I know gralloc has a config option for
> this, and maybe the version of the driver I'm carrying has it wrong?

There are some settings at adv7535 with regards to the colormap.
The 4.9 fork of it has some different settings. Maybe it could
be somehow related to it.

I have here a Hikey 960, but didn't test it yet.

> 2) Performance is noticeably worse. Whereas with my tree, I see close
> to 60fps (that clk issue we mentioned earlier is why it's not exactly
> 60) in most tests, but with yours it mostly hovers around 30some fps,
> occasionally speeding up to 40 and then back down.

That's weird, but it could be due to some settings related to CMA, IOMMU
and/or AFBC.

> Obviously with some work I suspect we'll be able to sort these out,
> but I also do feel that the set you're starting with for upstreaming
> is pretty old. The driver I'm carrying was heavily refactored around
> 5.0 to share code with the existing kirin driver, in the hopes of
> making usptreaming easier, and it seems a shame to throw that out and
> focus your efforts on the older tree.
> 
> But to be fair, I've not had time to upstream the driver myself, and
> it's obviously your choice on how you spend your time.  I am really
> excited to see your efforts here, regardless of which driver you end
> up pushing.

On a quick look I've done, besides not having support for Hikey 970,
the code on your tree seems to have less settings than the original
one for Hikey 960. Yet, it should take some time to figure out what
those extra settings are doing.

Once I get this driver merged, and have USB support working fine[1],
my plan is to compare the version from your tree, and compare
with the one I have, in order to cleanup some stuff, check performance
and do some other optimizations.

-

[1] this is a little OOT here: USB has been a challenge. Depending
on the build, I'm getting an NMI interrupt error when the USB3
stack is loaded (usually at dwc3). The error is ESR_ELx_AET_UC.
Unfortunately, it doesn't point to where this error is generated,
making very hard to debug it.

Thanks,
Mauro

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-19 21:36 ` John Stultz
  2020-08-20  2:01   ` John Stultz
@ 2020-08-20  8:04   ` Mauro Carvalho Chehab
  1 sibling, 0 replies; 42+ messages in thread
From: Mauro Carvalho Chehab @ 2020-08-20  8:04 UTC (permalink / raw)
  To: John Stultz
  Cc: Greg Kroah-Hartman, linuxarm, mauro.chehab,
	Manivannan Sadhasivam, Daniel Vetter, dri-devel, Bogdan Togorean,
	Liwei Cai, linux-arm-kernel, Daniel Borkmann, Rob Herring,
	David S. Miller, Xinliang Liu, Neil Armstrong, Wanchun Zheng,
	driverdevel, BPF Mailing List, Xiubin Zhang, linux-media,
	Tomi Valkeinen, Jesper Dangaard Brouer, Laurent Pinchart,
	Xinwei Kong, Alexei Starovoitov,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Rob Clark, Laurentiu Palcu, Andrzej Hajda, John Fastabend,
	Liuyao An, moderated list:DMA BUFFER SHARING FRAMEWORK, Wei Xu,
	Rongrong Zou, Philipp Zabel, Sam Ravnborg, Network Development,
	Sumit Semwal, lkml, Jakub Kicinski, David Airlie, Chen Feng

Em Wed, 19 Aug 2020 14:36:52 -0700
John Stultz <john.stultz@linaro.org> escreveu:

> On Wed, Aug 19, 2020 at 4:46 AM Mauro Carvalho Chehab
> <mchehab+huawei@kernel.org> wrote:
> > So, IMO, the best is to keep it on staging for a while, until those
> > remaining bugs gets solved.
> >
> > I added this series, together with the regulator driver and
> > a few other patches (including a hack to fix a Kernel 5.8
> > regression at WiFi ) at:
> >
> >         https://gitlab.freedesktop.org/mchehab_kernel/hikey-970/-/commits/master  
> 
> Sorry, one more small request: Could you create a branch that only has
> the DRM driver changes in it?
> 
> The reason I ask, is that since the HiKey960 isn't affected by the
> majority of the problems you listed as motivation for going through
> staging. So if we can validate that your tree works fine on HiKey960,
> the series can be cleaned up and submitted properly upstream to enable
> that SoC, and the outstanding 970 issues can be worked out afterwards
> against mainline.

Well, if support for HiKey 960 is OK, I guess what we can do is to not 
push the patch with DT bindings for hikey970. We should probably fix
the color swap thing at the driver first.

From my side, provided that the history is preserved, I don't mind
if this is merged:

- via staging tree;
- at dri-devel tree;
- or having a the historic patchsets merged at /staging, with
  a follow up patch moving it from staging/ into /gpu/drm/.

Thanks,
Mauro

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-20  7:03       ` Mauro Carvalho Chehab
@ 2020-08-20 10:02         ` Laurent Pinchart
  2020-08-24 19:29           ` Dave Airlie
  0 siblings, 1 reply; 42+ messages in thread
From: Laurent Pinchart @ 2020-08-20 10:02 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: John Stultz, Sam Ravnborg, Neil Armstrong, David Airlie,
	Wanchun Zheng, linuxarm, dri-devel, Andrzej Hajda, driverdevel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	Xinliang Liu, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Jakub Kicinski, Laurentiu Palcu, linux-media,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Liwei Cai, Jesper Dangaard Brouer, Manivannan Sadhasivam,
	Chen Feng, Alexei Starovoitov,
	moderated list:DMA BUFFER SHARING FRAMEWORK, Rob Herring,
	mauro.chehab, Rob Clark, linux-arm-kernel, Greg Kroah-Hartman,
	lkml, Liuyao An, Network Development, Rongrong Zou,
	BPF Mailing List, David S. Miller

Hi Mauro,

On Thu, Aug 20, 2020 at 09:03:26AM +0200, Mauro Carvalho Chehab wrote:
> Em Wed, 19 Aug 2020 12:52:06 -0700 John Stultz escreveu:
> > On Wed, Aug 19, 2020 at 8:31 AM Laurent Pinchart wrote:
> > > On Wed, Aug 19, 2020 at 05:21:20PM +0200, Sam Ravnborg wrote:  
> > > > On Wed, Aug 19, 2020 at 01:45:28PM +0200, Mauro Carvalho Chehab wrote:  
> > > > > This patch series port the out-of-tree driver for Hikey 970 (which
> > > > > should also support Hikey 960) from the official 96boards tree:
> > > > >
> > > > >    https://github.com/96boards-hikey/linux/tree/hikey970-v4.9
> > > > >
> > > > > Based on his history, this driver seems to be originally written
> > > > > for Kernel 4.4, and was later ported to Kernel 4.9. The original
> > > > > driver used to depend on ION (from Kernel 4.4) and had its own
> > > > > implementation for FB dev API.
> > > > >
> > > > > As I need to preserve the original history (with has patches from
> > > > > both HiSilicon and from Linaro),  I'm starting from the original
> > > > > patch applied there. The remaining patches are incremental,
> > > > > and port this driver to work with upstream Kernel.
> > > > >  
> > ...
> > > > > - Due to legal reasons, I need to preserve the authorship of
> > > > >   each one responsbile for each patch. So, I need to start from
> > > > >   the original patch from Kernel 4.4;  
> > ...
> > > > I do acknowledge you need to preserve history and all -
> > > > but this patchset is not easy to review.  
> > >
> > > Why do we need to preserve history ? Adding relevant Signed-off-by and
> > > Co-developed-by should be enough, shouldn't it ? Having a public branch
> > > that contains the history is useful if anyone is interested, but I don't
> > > think it's required in mainline.  
> > 
> > Yea. I concur with Laurent here. I'm not sure what legal reasoning you
> > have on this but preserving the "absolute" history here is actively
> > detrimental for review and understanding of the patch set.
> > 
> > Preserving Authorship, Signed-off-by lines and adding Co-developed-by
> > lines should be sufficient to provide both atribution credit and DCO
> > history.
> 
> I'm not convinced that, from legal standpoint, folding things would
> be enough. See, there are at least 3 legal systems involved here
> among the different patch authors:
> 
> 	- civil law;
> 	- common law;
> 	- customary law + common law.
> 
> Merging stuff altogether from different law systems can be problematic,
> and trying to discuss this with experienced IP property lawyers will
> for sure take a lot of time and efforts. I also bet that different
> lawyers will have different opinions, because laws are subject to 
> interpretation. With that matter I'm not aware of any court rules 
> with regards to folded patches. So, it sounds to me that folding 
> patches is something that has yet to be proofed in courts around
> the globe.
> 
> At least for US legal system, it sounds that the Country of
> origin of a patch is relevant, as they have a concept of
> "national technology" that can be subject to export regulations.
> 
> From my side, I really prefer to play safe and stay out of any such
> legal discussions.

Let's be serious for a moment. If you think there are legal issues in
taking GPL-v2.0-only patches and squashing them while retaining
authorship information through tags, the Linux kernel if *full* of that.
You also routinely modify patches that you commit to the media subsystem
to fix "small issues".

The country of origin argument makes no sense either, the kernel code
base if full of code coming from pretty much all country on the planet.

Keeping the patches separate make this hard to review. Please squash
them.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
       [not found]     ` <20200819173558.GA3733@ravnborg.org>
@ 2020-08-20 14:06       ` Mauro Carvalho Chehab
  2020-08-20 14:48         ` Sam Ravnborg
  2020-08-21 13:37       ` Mauro Carvalho Chehab
                         ` (2 subsequent siblings)
  3 siblings, 1 reply; 42+ messages in thread
From: Mauro Carvalho Chehab @ 2020-08-20 14:06 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: Greg Kroah-Hartman, Neil Armstrong, Xinliang Liu, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Laurent Pinchart, devel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	David Airlie, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Laurentiu Palcu, linux-media, devicetree, Liwei Cai,
	Jesper Dangaard Brouer, Manivannan Sadhasivam, Chen Feng,
	Alexei Starovoitov, linaro-mm-sig, Rob Herring, Jakub Kicinski,
	mauro.chehab, Rob Clark, linux-arm-kernel, netdev, linux-kernel,
	Liuyao An, Rongrong Zou, bpf, David S. Miller

Em Wed, 19 Aug 2020 19:35:58 +0200
Sam Ravnborg <sam@ravnborg.org> escreveu:

I'm already handling the other comments from your review (I'll send a
more complete comment about them after finishing), but I have a doubt
what you meant about this:

> +static int kirin_drm_bind(struct device *dev)
> > +{
> > +	struct drm_driver *driver = &kirin_drm_driver;
> > +	struct drm_device *drm_dev;
> > +	struct kirin_drm_private *priv;
> > +	int ret;
> > +
> > +	drm_dev = drm_dev_alloc(driver, dev);
> > +	if (!drm_dev)
> > +		return -ENOMEM;
> > +
> > +	ret = kirin_drm_kms_init(drm_dev);
> > +	if (ret)
> > +		goto err_drm_dev_unref;
> > +
> > +	ret = drm_dev_register(drm_dev, 0);  
> There is better ways to do this. See drm_drv.c for the code example.

Not sure if I understood your comment here. The drm_drv.c example also calls 
drm_dev_register().

The only difference is that it calls it inside driver_probe(), while
on this driver, it uses:

	static const struct component_master_ops kirin_drm_ops = {
		.bind = kirin_drm_bind,
		.unbind = kirin_drm_unbind,
	};

	static int kirin_drm_platform_probe(struct platform_device *pdev)
	{
...
		drm_of_component_match_add(dev, &match, compare_of, remote);
...
	return component_master_add_with_match(dev, &kirin_drm_ops, match);
}

Are you meaning that I should get rid of this component API and call
kirin_drm_bind() from kirin_drm_platform_probe()?

Thanks,
Mauro

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-20 14:06       ` Mauro Carvalho Chehab
@ 2020-08-20 14:48         ` Sam Ravnborg
  2020-08-20 15:13           ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 42+ messages in thread
From: Sam Ravnborg @ 2020-08-20 14:48 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Greg Kroah-Hartman, Neil Armstrong, Xinliang Liu, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Laurent Pinchart, devel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	David Airlie, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Laurentiu Palcu, linux-media, devicetree, Liwei Cai,
	Jesper Dangaard Brouer, Manivannan Sadhasivam, Chen Feng,
	Alexei Starovoitov, linaro-mm-sig, Rob Herring, Jakub Kicinski,
	mauro.chehab, Rob Clark, linux-arm-kernel, netdev, linux-kernel,
	Liuyao An, Rongrong Zou, bpf, David S. Miller

Hi Mauro.

On Thu, Aug 20, 2020 at 04:06:49PM +0200, Mauro Carvalho Chehab wrote:
> Em Wed, 19 Aug 2020 19:35:58 +0200
> Sam Ravnborg <sam@ravnborg.org> escreveu:
> 
> I'm already handling the other comments from your review (I'll send a
> more complete comment about them after finishing),
If you get back only on things you do not understand or do not agree on
that would be fine. The rest should be visible in the changelog on the
updated patch - no need to do extra work here.

> but I have a doubt what you meant about this:
> 
> > +static int kirin_drm_bind(struct device *dev)
> > > +{
> > > +	struct drm_driver *driver = &kirin_drm_driver;
> > > +	struct drm_device *drm_dev;
> > > +	struct kirin_drm_private *priv;
> > > +	int ret;
> > > +
> > > +	drm_dev = drm_dev_alloc(driver, dev);
> > > +	if (!drm_dev)
> > > +		return -ENOMEM;
> > > +
> > > +	ret = kirin_drm_kms_init(drm_dev);
> > > +	if (ret)
> > > +		goto err_drm_dev_unref;
> > > +
> > > +	ret = drm_dev_register(drm_dev, 0);  
> > There is better ways to do this. See drm_drv.c for the code example.
> 
> Not sure if I understood your comment here. The drm_drv.c example also calls 
> drm_dev_register().

This is indeed not obvious from my comments but what I wnated to say is
that the driver should embed drm_device in some struct,
maybe in "struct kirin_drm_private".

This should also be part of the referenced example.

I hope this clarifies it.

	Sam

> 
> The only difference is that it calls it inside driver_probe(), while
> on this driver, it uses:
> 
> 	static const struct component_master_ops kirin_drm_ops = {
> 		.bind = kirin_drm_bind,
> 		.unbind = kirin_drm_unbind,
> 	};
> 
> 	static int kirin_drm_platform_probe(struct platform_device *pdev)
> 	{
> ...
> 		drm_of_component_match_add(dev, &match, compare_of, remote);
> ...
> 	return component_master_add_with_match(dev, &kirin_drm_ops, match);
> }
> 
> Are you meaning that I should get rid of this component API and call
> kirin_drm_bind() from kirin_drm_platform_probe()?
> 
> Thanks,
> Mauro

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-20 14:48         ` Sam Ravnborg
@ 2020-08-20 15:13           ` Mauro Carvalho Chehab
  2020-08-20 15:36             ` Sam Ravnborg
  0 siblings, 1 reply; 42+ messages in thread
From: Mauro Carvalho Chehab @ 2020-08-20 15:13 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: Greg Kroah-Hartman, Neil Armstrong, Xinliang Liu, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Laurent Pinchart, devel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	David Airlie, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Laurentiu Palcu, linux-media, devicetree, Liwei Cai,
	Jesper Dangaard Brouer, Manivannan Sadhasivam, Chen Feng,
	Alexei Starovoitov, linaro-mm-sig, Rob Herring, Jakub Kicinski,
	mauro.chehab, Rob Clark, linux-arm-kernel, netdev, linux-kernel,
	Liuyao An, Rongrong Zou, bpf, David S. Miller

Em Thu, 20 Aug 2020 16:48:08 +0200
Sam Ravnborg <sam@ravnborg.org> escreveu:

> Hi Mauro.
> 
> On Thu, Aug 20, 2020 at 04:06:49PM +0200, Mauro Carvalho Chehab wrote:
> > Em Wed, 19 Aug 2020 19:35:58 +0200
> > Sam Ravnborg <sam@ravnborg.org> escreveu:
> > 
> > I'm already handling the other comments from your review (I'll send a
> > more complete comment about them after finishing),  
> If you get back only on things you do not understand or do not agree on
> that would be fine. The rest should be visible in the changelog on the
> updated patch - no need to do extra work here.
> 
> > but I have a doubt what you meant about this:
> >   
> > > +static int kirin_drm_bind(struct device *dev)  
> > > > +{
> > > > +	struct drm_driver *driver = &kirin_drm_driver;
> > > > +	struct drm_device *drm_dev;
> > > > +	struct kirin_drm_private *priv;
> > > > +	int ret;
> > > > +
> > > > +	drm_dev = drm_dev_alloc(driver, dev);
> > > > +	if (!drm_dev)
> > > > +		return -ENOMEM;
> > > > +
> > > > +	ret = kirin_drm_kms_init(drm_dev);
> > > > +	if (ret)
> > > > +		goto err_drm_dev_unref;
> > > > +
> > > > +	ret = drm_dev_register(drm_dev, 0);    
> > > There is better ways to do this. See drm_drv.c for the code example.  
> > 
> > Not sure if I understood your comment here. The drm_drv.c example also calls 
> > drm_dev_register().  
> 
> This is indeed not obvious from my comments but what I wnated to say is
> that the driver should embed drm_device in some struct,
> maybe in "struct kirin_drm_private".
> 
> This should also be part of the referenced example.
> 
> I hope this clarifies it.

Yeah. I was already doing those changes ;-) 

Something like the enclosed patch, right?

Btw, I'm not sure if the error handling part is ok, as I didn't check
what the devm stuff does at the subsystem. 

-

On a separate question, I was unable to use the helper macros,
as it sounds that there's no macro with this:

	.dumb_create		= drm_gem_cma_dumb_create_internal,

The existing DRM_GEM_CMA_VMAP_DRIVER_OPS uses, instead
drm_gem_cma_dumb_create(). I'm not sure if this driver can use
such function instead.

Thanks,
Mauro

staging: hikey9xx/gpu: use drm_managed interface
    
Use a more modern design for the driver binding logic by
using drm_managed and getting rid of drm->dev_private.
    
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.c b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.c
index c7736f4d74b7..600c89605cc0 100644
--- a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.c
+++ b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.c
@@ -29,12 +29,13 @@
 #include <drm/drm_of.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
+#include <drm/drm_managed.h>
 
 #include "kirin9xx_drm_drv.h"
 
 static int kirin_drm_kms_cleanup(struct drm_device *dev)
 {
-	struct kirin_drm_private *priv = dev->dev_private;
+	struct kirin_drm_private *priv = to_drm_private(dev);
 	static struct kirin_dc_ops const *dc_ops;
 
 	if (priv->fbdev)
@@ -45,15 +46,13 @@ static int kirin_drm_kms_cleanup(struct drm_device *dev)
 	drm_kms_helper_poll_fini(dev);
 	dc_ops->cleanup(dev);
 	drm_mode_config_cleanup(dev);
-	devm_kfree(dev->dev, priv);
-	dev->dev_private = NULL;
 
 	return 0;
 }
 
 static void kirin_fbdev_output_poll_changed(struct drm_device *dev)
 {
-	struct kirin_drm_private *priv = dev->dev_private;
+	struct kirin_drm_private *priv = to_drm_private(dev);
 
 	dsi_set_output_client(dev);
 
@@ -69,18 +68,20 @@ static const struct drm_mode_config_funcs kirin_drm_mode_config_funcs = {
 
 static int kirin_drm_kms_init(struct drm_device *dev)
 {
-	struct kirin_drm_private *priv = dev->dev_private;
+	struct kirin_drm_private *priv = to_drm_private(dev);
 	static struct kirin_dc_ops const *dc_ops;
 	int ret;
 
-	priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL);
+	priv = drmm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
 	dev->dev_private = priv;
 	dev_set_drvdata(dev->dev, dev);
 
-	drm_mode_config_init(dev);
+	ret = drmm_mode_config_init(dev);
+	if (ret)
+		return ret;
 
 	dev->mode_config.min_width = 0;
 	dev->mode_config.min_height = 0;
@@ -94,20 +95,20 @@ static int kirin_drm_kms_init(struct drm_device *dev)
 	dc_ops = of_device_get_match_data(dev->dev);
 	ret = dc_ops->init(dev);
 	if (ret)
-		goto err_mode_config_cleanup;
+		return ret;
 
 	/* bind and init sub drivers */
 	ret = component_bind_all(dev->dev, dev);
 	if (ret) {
 		DRM_ERROR("failed to bind all component.\n");
-		goto err_dc_cleanup;
+		return ret;
 	}
 
 	/* vblank init */
 	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
 	if (ret) {
 		DRM_ERROR("failed to initialize vblank.\n");
-		goto err_unbind_all;
+		return ret;
 	}
 	/* with irq_enabled = true, we can use the vblank feature. */
 	dev->irq_enabled = true;
@@ -119,28 +120,10 @@ static int kirin_drm_kms_init(struct drm_device *dev)
 	drm_kms_helper_poll_init(dev);
 
 	return 0;
-
-err_unbind_all:
-	component_unbind_all(dev->dev, dev);
-err_dc_cleanup:
-	dc_ops->cleanup(dev);
-err_mode_config_cleanup:
-	drm_mode_config_cleanup(dev);
-	devm_kfree(dev->dev, priv);
-	dev->dev_private = NULL;
-
-	return ret;
 }
 
 DEFINE_DRM_GEM_CMA_FOPS(kirin_drm_fops);
 
-static int kirin_gem_cma_dumb_create(struct drm_file *file,
-				     struct drm_device *dev,
-				     struct drm_mode_create_dumb *args)
-{
-	return drm_gem_cma_dumb_create_internal(file, dev, args);
-}
-
 static int kirin_drm_connectors_register(struct drm_device *dev)
 {
 	struct drm_connector_list_iter conn_iter;
@@ -176,11 +159,11 @@ static int kirin_drm_connectors_register(struct drm_device *dev)
 static struct drm_driver kirin_drm_driver = {
 	.driver_features	= DRIVER_GEM | DRIVER_MODESET |
 				  DRIVER_ATOMIC | DRIVER_RENDER,
-	.fops				= &kirin_drm_fops,
+	.fops			= &kirin_drm_fops,
 
 	.gem_free_object	= drm_gem_cma_free_object,
 	.gem_vm_ops		= &drm_gem_cma_vm_ops,
-	.dumb_create		= kirin_gem_cma_dumb_create,
+	.dumb_create		= drm_gem_cma_dumb_create_internal,
 
 	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
 	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
@@ -207,42 +190,48 @@ static int compare_of(struct device *dev, void *data)
 static int kirin_drm_bind(struct device *dev)
 {
 	struct drm_driver *driver = &kirin_drm_driver;
-	struct drm_device *drm_dev;
 	struct kirin_drm_private *priv;
+	struct drm_device *drm;
 	int ret;
 
-	drm_dev = drm_dev_alloc(driver, dev);
-	if (!drm_dev)
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
 		return -ENOMEM;
 
-	ret = kirin_drm_kms_init(drm_dev);
+	drm = &priv->drm;
+
+	ret = devm_drm_dev_init(dev, drm, driver);
+	if (ret) {
+		kfree(priv);
+		return ret;
+	}
+	drmm_add_final_kfree(drm, priv);
+
+	ret = kirin_drm_kms_init(drm);
 	if (ret)
-		goto err_drm_dev_unref;
+		return ret;
 
-	ret = drm_dev_register(drm_dev, 0);
+	ret = drm_dev_register(drm, 0);
 	if (ret)
-		goto err_kms_cleanup;
+		return ret;
 
-	drm_fbdev_generic_setup(drm_dev, 0);
-	priv = drm_dev->dev_private;
+	drm_fbdev_generic_setup(drm, 0);
 
 	/* connectors should be registered after drm device register */
-	ret = kirin_drm_connectors_register(drm_dev);
+	ret = kirin_drm_connectors_register(drm);
 	if (ret)
 		goto err_drm_dev_unregister;
 
 	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
 		 driver->name, driver->major, driver->minor, driver->patchlevel,
-		 driver->date, drm_dev->primary->index);
+		 driver->date, drm->primary->index);
 
 	return 0;
 
 err_drm_dev_unregister:
-	drm_dev_unregister(drm_dev);
-err_kms_cleanup:
-	kirin_drm_kms_cleanup(drm_dev);
-err_drm_dev_unref:
-	drm_dev_put(drm_dev);
+	drm_dev_unregister(drm);
+	kirin_drm_kms_cleanup(drm);
+	drm_dev_put(drm);
 
 	return ret;
 }
@@ -252,6 +241,7 @@ static void kirin_drm_unbind(struct device *dev)
 	struct drm_device *drm_dev = dev_get_drvdata(dev);
 
 	drm_dev_unregister(drm_dev);
+	drm_atomic_helper_shutdown(drm_dev);
 	kirin_drm_kms_cleanup(drm_dev);
 	drm_dev_put(drm_dev);
 }
diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.h b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.h
index 58f6fc7be347..09255d136c54 100644
--- a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.h
+++ b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.h
@@ -31,6 +31,7 @@ struct kirin_dc_ops {
 };
 
 struct kirin_drm_private {
+	struct drm_device drm;
 	struct drm_fb_helper *fbdev;
 	struct drm_crtc *crtc[MAX_CRTC];
 };
@@ -44,4 +45,6 @@ extern const struct kirin_dc_ops kirin960_dss_dc_ops;
 extern const struct kirin_dc_ops kirin970_dss_dc_ops;
 void dsi_set_output_client(struct drm_device *dev);
 
+#define to_drm_private(d) container_of(d, struct kirin_drm_private, drm)
+
 #endif /* __KIRIN_DRM_DRV_H__ */

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-20 15:13           ` Mauro Carvalho Chehab
@ 2020-08-20 15:36             ` Sam Ravnborg
  0 siblings, 0 replies; 42+ messages in thread
From: Sam Ravnborg @ 2020-08-20 15:36 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Greg Kroah-Hartman, Neil Armstrong, Xinliang Liu, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Laurent Pinchart, devel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	David Airlie, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Laurentiu Palcu, linux-media, devicetree, Liwei Cai,
	Jesper Dangaard Brouer, Manivannan Sadhasivam, Chen Feng,
	Alexei Starovoitov, linaro-mm-sig, Rob Herring, Jakub Kicinski,
	mauro.chehab, Rob Clark, linux-arm-kernel, netdev, linux-kernel,
	Liuyao An, Rongrong Zou, bpf, David S. Miller

Hi Mauro.

Quick feedback below.

	Sam

On Thu, Aug 20, 2020 at 05:13:22PM +0200, Mauro Carvalho Chehab wrote:
> Em Thu, 20 Aug 2020 16:48:08 +0200
> Sam Ravnborg <sam@ravnborg.org> escreveu:
> 
> > Hi Mauro.
> > 
> > On Thu, Aug 20, 2020 at 04:06:49PM +0200, Mauro Carvalho Chehab wrote:
> > > Em Wed, 19 Aug 2020 19:35:58 +0200
> > > Sam Ravnborg <sam@ravnborg.org> escreveu:
> > > 
> > > I'm already handling the other comments from your review (I'll send a
> > > more complete comment about them after finishing),  
> > If you get back only on things you do not understand or do not agree on
> > that would be fine. The rest should be visible in the changelog on the
> > updated patch - no need to do extra work here.
> > 
> > > but I have a doubt what you meant about this:
> > >   
> > > > +static int kirin_drm_bind(struct device *dev)  
> > > > > +{
> > > > > +	struct drm_driver *driver = &kirin_drm_driver;
> > > > > +	struct drm_device *drm_dev;
> > > > > +	struct kirin_drm_private *priv;
> > > > > +	int ret;
> > > > > +
> > > > > +	drm_dev = drm_dev_alloc(driver, dev);
> > > > > +	if (!drm_dev)
> > > > > +		return -ENOMEM;
> > > > > +
> > > > > +	ret = kirin_drm_kms_init(drm_dev);
> > > > > +	if (ret)
> > > > > +		goto err_drm_dev_unref;
> > > > > +
> > > > > +	ret = drm_dev_register(drm_dev, 0);    
> > > > There is better ways to do this. See drm_drv.c for the code example.  
> > > 
> > > Not sure if I understood your comment here. The drm_drv.c example also calls 
> > > drm_dev_register().  
> > 
> > This is indeed not obvious from my comments but what I wnated to say is
> > that the driver should embed drm_device in some struct,
> > maybe in "struct kirin_drm_private".
> > 
> > This should also be part of the referenced example.
> > 
> > I hope this clarifies it.
> 
> Yeah. I was already doing those changes ;-) 
> 
> Something like the enclosed patch, right?
> 
> Btw, I'm not sure if the error handling part is ok, as I didn't check
> what the devm stuff does at the subsystem. 
> 
> -
> 
> On a separate question, I was unable to use the helper macros,
> as it sounds that there's no macro with this:
> 
> 	.dumb_create		= drm_gem_cma_dumb_create_internal,
> 
> The existing DRM_GEM_CMA_VMAP_DRIVER_OPS uses, instead
> drm_gem_cma_dumb_create(). I'm not sure if this driver can use
> such function instead.

From the documentation of drm_gem_cma_dumb_create_internal:
* It should not be used directly
* as their &drm_driver.dumb_create callback.

I would expect drm_gem_cma_dumb_create() to be the right choice.
So you can go ahead with DRM_GEM_CMA_VMAP_DRIVER_OPS

(I hope I am right, not the are	i know much about)


> staging: hikey9xx/gpu: use drm_managed interface
>     
> Use a more modern design for the driver binding logic by
> using drm_managed and getting rid of drm->dev_private.
>     
> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> 
> diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.c b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.c
> index c7736f4d74b7..600c89605cc0 100644
> --- a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.c
> +++ b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.c
> @@ -29,12 +29,13 @@
>  #include <drm/drm_of.h>
>  #include <drm/drm_probe_helper.h>
>  #include <drm/drm_vblank.h>
> +#include <drm/drm_managed.h>
>  
>  #include "kirin9xx_drm_drv.h"
>  
>  static int kirin_drm_kms_cleanup(struct drm_device *dev)
>  {
> -	struct kirin_drm_private *priv = dev->dev_private;
> +	struct kirin_drm_private *priv = to_drm_private(dev);
>  	static struct kirin_dc_ops const *dc_ops;
>  
>  	if (priv->fbdev)
> @@ -45,15 +46,13 @@ static int kirin_drm_kms_cleanup(struct drm_device *dev)
>  	drm_kms_helper_poll_fini(dev);
>  	dc_ops->cleanup(dev);

>  	drm_mode_config_cleanup(dev);
This should also be gone when you are using
drmm_mode_config_init()

> -	devm_kfree(dev->dev, priv);
> -	dev->dev_private = NULL;
>  
>  	return 0;
>  }
>  
>  static void kirin_fbdev_output_poll_changed(struct drm_device *dev)
>  {
> -	struct kirin_drm_private *priv = dev->dev_private;
> +	struct kirin_drm_private *priv = to_drm_private(dev);
>  
>  	dsi_set_output_client(dev);
>  
> @@ -69,18 +68,20 @@ static const struct drm_mode_config_funcs kirin_drm_mode_config_funcs = {
>  
>  static int kirin_drm_kms_init(struct drm_device *dev)
>  {
> -	struct kirin_drm_private *priv = dev->dev_private;
> +	struct kirin_drm_private *priv = to_drm_private(dev);
It is assigned a few lines later.

>  	static struct kirin_dc_ops const *dc_ops;
>  	int ret;
>  
> -	priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL);
> +	priv = drmm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>  	if (!priv)
>  		return -ENOMEM;

OK, I am confused here.
This code allocates a struct kirin_drm_private.
But the calling function does the same.
What am I missing here? Coffee?

>  
>  	dev->dev_private = priv;
>  	dev_set_drvdata(dev->dev, dev);
>  
> -	drm_mode_config_init(dev);
> +	ret = drmm_mode_config_init(dev);
> +	if (ret)
> +		return ret;
>  
>  	dev->mode_config.min_width = 0;
>  	dev->mode_config.min_height = 0;
> @@ -94,20 +95,20 @@ static int kirin_drm_kms_init(struct drm_device *dev)
>  	dc_ops = of_device_get_match_data(dev->dev);
>  	ret = dc_ops->init(dev);
>  	if (ret)
> -		goto err_mode_config_cleanup;
> +		return ret;
>  
>  	/* bind and init sub drivers */
>  	ret = component_bind_all(dev->dev, dev);
>  	if (ret) {
>  		DRM_ERROR("failed to bind all component.\n");
> -		goto err_dc_cleanup;
> +		return ret;
>  	}
>  
>  	/* vblank init */
>  	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
>  	if (ret) {
>  		DRM_ERROR("failed to initialize vblank.\n");
> -		goto err_unbind_all;
> +		return ret;
>  	}
>  	/* with irq_enabled = true, we can use the vblank feature. */
>  	dev->irq_enabled = true;
> @@ -119,28 +120,10 @@ static int kirin_drm_kms_init(struct drm_device *dev)
>  	drm_kms_helper_poll_init(dev);
>  
>  	return 0;
> -
> -err_unbind_all:
> -	component_unbind_all(dev->dev, dev);
> -err_dc_cleanup:
> -	dc_ops->cleanup(dev);
> -err_mode_config_cleanup:
> -	drm_mode_config_cleanup(dev);
> -	devm_kfree(dev->dev, priv);
> -	dev->dev_private = NULL;
> -
> -	return ret;
>  }
>  
>  DEFINE_DRM_GEM_CMA_FOPS(kirin_drm_fops);
>  
> -static int kirin_gem_cma_dumb_create(struct drm_file *file,
> -				     struct drm_device *dev,
> -				     struct drm_mode_create_dumb *args)
> -{
> -	return drm_gem_cma_dumb_create_internal(file, dev, args);
> -}
> -
>  static int kirin_drm_connectors_register(struct drm_device *dev)
>  {
>  	struct drm_connector_list_iter conn_iter;
> @@ -176,11 +159,11 @@ static int kirin_drm_connectors_register(struct drm_device *dev)
>  static struct drm_driver kirin_drm_driver = {
>  	.driver_features	= DRIVER_GEM | DRIVER_MODESET |
>  				  DRIVER_ATOMIC | DRIVER_RENDER,
> -	.fops				= &kirin_drm_fops,
> +	.fops			= &kirin_drm_fops,
>  
>  	.gem_free_object	= drm_gem_cma_free_object,
>  	.gem_vm_ops		= &drm_gem_cma_vm_ops,
> -	.dumb_create		= kirin_gem_cma_dumb_create,
> +	.dumb_create		= drm_gem_cma_dumb_create_internal,
>  
>  	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
>  	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
> @@ -207,42 +190,48 @@ static int compare_of(struct device *dev, void *data)
>  static int kirin_drm_bind(struct device *dev)
>  {
>  	struct drm_driver *driver = &kirin_drm_driver;
> -	struct drm_device *drm_dev;
>  	struct kirin_drm_private *priv;
> +	struct drm_device *drm;
>  	int ret;
>  
> -	drm_dev = drm_dev_alloc(driver, dev);
> -	if (!drm_dev)
> +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
>  		return -ENOMEM;
>  
> -	ret = kirin_drm_kms_init(drm_dev);
> +	drm = &priv->drm;
> +
> +	ret = devm_drm_dev_init(dev, drm, driver);
> +	if (ret) {
> +		kfree(priv);
> +		return ret;
> +	}
> +	drmm_add_final_kfree(drm, priv);
> +
> +	ret = kirin_drm_kms_init(drm);
>  	if (ret)
> -		goto err_drm_dev_unref;
> +		return ret;
>  
> -	ret = drm_dev_register(drm_dev, 0);
> +	ret = drm_dev_register(drm, 0);
>  	if (ret)
> -		goto err_kms_cleanup;
> +		return ret;
>  
> -	drm_fbdev_generic_setup(drm_dev, 0);
> -	priv = drm_dev->dev_private;
> +	drm_fbdev_generic_setup(drm, 0);
>  
>  	/* connectors should be registered after drm device register */
> -	ret = kirin_drm_connectors_register(drm_dev);
> +	ret = kirin_drm_connectors_register(drm);
>  	if (ret)
>  		goto err_drm_dev_unregister;
>  
>  	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
>  		 driver->name, driver->major, driver->minor, driver->patchlevel,
> -		 driver->date, drm_dev->primary->index);
> +		 driver->date, drm->primary->index);
>  
>  	return 0;
>  
>  err_drm_dev_unregister:
> -	drm_dev_unregister(drm_dev);
> -err_kms_cleanup:
> -	kirin_drm_kms_cleanup(drm_dev);
> -err_drm_dev_unref:
> -	drm_dev_put(drm_dev);
> +	drm_dev_unregister(drm);
> +	kirin_drm_kms_cleanup(drm);
> +	drm_dev_put(drm);
>  
>  	return ret;
>  }
> @@ -252,6 +241,7 @@ static void kirin_drm_unbind(struct device *dev)
>  	struct drm_device *drm_dev = dev_get_drvdata(dev);
>  
>  	drm_dev_unregister(drm_dev);
I think this is not needed. But the component framework confuses me.

> +	drm_atomic_helper_shutdown(drm_dev);
>  	kirin_drm_kms_cleanup(drm_dev);
>  	drm_dev_put(drm_dev);
This should likewise go I think.

>  }
> diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.h b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.h
> index 58f6fc7be347..09255d136c54 100644
> --- a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.h
> +++ b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.h
> @@ -31,6 +31,7 @@ struct kirin_dc_ops {
>  };
>  
>  struct kirin_drm_private {
> +	struct drm_device drm;
>  	struct drm_fb_helper *fbdev;
>  	struct drm_crtc *crtc[MAX_CRTC];
>  };
> @@ -44,4 +45,6 @@ extern const struct kirin_dc_ops kirin960_dss_dc_ops;
>  extern const struct kirin_dc_ops kirin970_dss_dc_ops;
>  void dsi_set_output_client(struct drm_device *dev);
>  
> +#define to_drm_private(d) container_of(d, struct kirin_drm_private, drm)
> +
>  #endif /* __KIRIN_DRM_DRV_H__ */

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
       [not found]     ` <20200819173558.GA3733@ravnborg.org>
  2020-08-20 14:06       ` Mauro Carvalho Chehab
@ 2020-08-21 13:37       ` Mauro Carvalho Chehab
  2020-08-21 13:58       ` Mauro Carvalho Chehab
  2020-08-21 14:41       ` Mauro Carvalho Chehab
  3 siblings, 0 replies; 42+ messages in thread
From: Mauro Carvalho Chehab @ 2020-08-21 13:37 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: Greg Kroah-Hartman, Neil Armstrong, Xinliang Liu, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Laurent Pinchart, devel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	David Airlie, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Laurentiu Palcu, linux-media, devicetree, Liwei Cai,
	Jesper Dangaard Brouer, Manivannan Sadhasivam, Chen Feng,
	Alexei Starovoitov, linaro-mm-sig, Rob Herring, Jakub Kicinski,
	mauro.chehab, Rob Clark, linux-arm-kernel, netdev, linux-kernel,
	Liuyao An, Rongrong Zou, bpf, David S. Miller

Hi Sam,

Em Wed, 19 Aug 2020 19:35:58 +0200
Sam Ravnborg <sam@ravnborg.org> escreveu:

> > +	ret = drm_bridge_attach(encoder, bridge, NULL, 0);  
> The bridge should be attached with the falg that tell the bridge NOT to
> create a connector.
> 
> The display driver shall created the connector.
> 
> Please see how other drivers do this (but most driver uses the old
> pattern so so look for drm_bridge_attach() with the flag argument.

Not sure if I got what should be done here.

From what I've seen at the DRM code, one of the differences between the 
display engine for the first Hikey board (Kirin 620 based) and 960/970
is with regards to bridges. The first Hikey device doesn't use any
external bridges: both panel and HDMI support are provided by the SoC.

The Hikey 960 and 970 boards may either use an external bridge
or not. They also have two output connectors:

- The first one doesn't use an external bridge. It is used
  only together with an external daughter display panel board. 
  It sounds that one such panels is this one:

	https://www.96boards.org/blog/linksprite-hikey-aosp/

  I don't have any such board. The OOT driver came with one
  panel display, I didn't port such driver. 

- The second one uses an external bridge (adv7535) which is connected
  to the HDMI board's connector.

As there's just one bridge, the driver uses this to find its
OF data:

	struct device_node *bridge_node;

	bridge_node = of_graph_get_remote_port_parent(endpoint);
	dsi->bridge = of_drm_find_bridge(bridge_node);

Basically, it doesn't call drm_bridge_add(), and doesn't
declare any struct drm_bridge_funcs fops, as there's just one
bridge that it is always there.

-

That's said, when I ported the code from Kernel 4.9, I fixed
some broken things at the hotplug logic, trying to use other
drivers with external bridges as examples. Yet, as you noticed,
I ended using some older bridge model.  

The only other driver I found that doesn't use drm_bridge_add()
and doesn't pass 0 as flags is this one:

	drivers/gpu/drm/omapdrm/omap_drv.c

Is it a good example?

What I see different there there is that it calls drm_bridge_attach()
with:

	ret = drm_bridge_attach(pipe->encoder,
				pipe->output->bridge, NULL,
				DRM_BRIDGE_ATTACH_NO_CONNECTOR);

Is adding this enough? Or should I do something else?


Thanks,
Mauro

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
       [not found]     ` <20200819173558.GA3733@ravnborg.org>
  2020-08-20 14:06       ` Mauro Carvalho Chehab
  2020-08-21 13:37       ` Mauro Carvalho Chehab
@ 2020-08-21 13:58       ` Mauro Carvalho Chehab
  2020-08-21 15:55         ` Sam Ravnborg
  2020-08-21 14:41       ` Mauro Carvalho Chehab
  3 siblings, 1 reply; 42+ messages in thread
From: Mauro Carvalho Chehab @ 2020-08-21 13:58 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: Greg Kroah-Hartman, Neil Armstrong, Xinliang Liu, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Laurent Pinchart, devel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	David Airlie, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Laurentiu Palcu, linux-media, devicetree, Liwei Cai,
	Jesper Dangaard Brouer, Manivannan Sadhasivam, Chen Feng,
	Alexei Starovoitov, linaro-mm-sig, Rob Herring, Jakub Kicinski,
	mauro.chehab, Rob Clark, linux-arm-kernel, netdev, linux-kernel,
	Liuyao An, Rongrong Zou, bpf, David S. Miller

Em Wed, 19 Aug 2020 19:35:58 +0200
Sam Ravnborg <sam@ravnborg.org> escreveu:

> Also a few high level comments:

Hi Sam,

Finally finished addressing the things you pointed, except by a few
ones:
	- bridge bindings;
	- use drm_foo() instead of DRM_foo() when possible.

A few answers to some of your comments.

> There is too much unused code present - please delete.
> I dod not think I spotted it all.

I'll took a look and dropped most of it. I kept just some
code there related to an optional IOMMU support. The code
there is commented out because they depend on a driver that,
after some upstream discussions, I'm opting to not sending
it. Basically, there are better ways to support the integrated
MMU for the GPU core.

I'added some FIXME and commented out the code, as I intend
to take another look on it in the future. Not top priority,
as the driver works without it, but it could affect driver's
performance.

> Some style issues - ask checkpatch --strict for help identifying
> these.

Ok. There aren't much reported by checkpatch, as I did lots of
checkpatch fixes already in this series. I ended keeping
some CamelCase for macros:

	CHECK:CAMELCASE: Avoid CamelCase: <SMMU_SMRx_P>
	#143: FILE: drivers/staging/hikey9xx/gpu/kirin970_dpe_reg.h:143:
	+#define SMMU_SMRx_P	(0x10000)

and a few other things that, IMHO, making checkpatch happier
would make things worse for humans ;-)

> Needs to be adapted to new bridge handling - see comments.

Ok.

> Move panel stuff to drm_panel (or maybe I got confsed so this was just
> bride stuff).

There used to have a separate panel driver. The DRM driver has
support for it, probably using some older binding model (although
I converted some things that don't work on upstream Kernels anymore).

The old panel driver is there at the history (patch 01/49), but
a later patch drops it. The main thing is that Hikey 970 board
doesn't come with any panel. Maybe are out there some daughter
boards providing a panel display, but I was unable to find it.

So, I ended dropping the panel driver, but keeping the main
driver's code to handle it, as someone could find it useful.

> Lots track a few times - so may have confused myself a few times.
> 
> Many small comments - but general impression is good.

Good!

> Happy hacking!

Thanks!

> 	Sam
> 
> 
> > diff --git a/drivers/staging/hikey9xx/gpu/Kconfig b/drivers/staging/hikey9xx/gpu/Kconfig
> > new file mode 100644
> > index 000000000000..957da13bcf81
> > --- /dev/null
> > +++ b/drivers/staging/hikey9xx/gpu/Kconfig
> > @@ -0,0 +1,22 @@
> > +config DRM_HISI_KIRIN9XX
> > +	tristate "DRM Support for Hisilicon Kirin9xx series SoCs Platform"
> > +	depends on DRM && OF && ARM64
> > +	select DRM_KMS_HELPER
> > +	select DRM_GEM_CMA_HELPER
> > +	select DRM_KMS_CMA_HELPER
> > +	select DRM_MIPI_DSI
> > +	help
> > +	  Choose this option if you have a HiSilicon Kirin960 or Kirin970.
> > +	  If M is selected the module will be called kirin9xx-drm.
> > +
> > +config DRM_HISI_KIRIN970
> > +	bool "Enable support for Hisilicon Kirin970"
> > +	depends on DRM_MIPI_DSI  
> Implied by DRM_HISI_KIRIN9XX, so not needed.
> > +	depends on DRM_HISI_KIRIN9XX
> > +	help
> > +	  Choose this option if you have a hisilicon Kirin chipsets(kirin970).
> > +
> > +config DRM_HISI_KIRIN9XX_DSI
> > +	tristate
> > +	depends on DRM_HISI_KIRIN9XX
> > +	default y  
> This is essential a copy of DRM_HISI_KIRIN9XX - so no need for this
> extra Kconfig variable.

The above are left-overs. I'm dropping everything, keeping just
DRM_HISI_KIRIN9XX. The driver now has support for both Kirin 960 and 970
at the same time, without needing an extra Kconfig.

> > +	// D0  
> Some people dislike the more readable c99 comments.
> I do not recall if coding style allows them
> Ask checkpatch --strict

It used to be forbidden. Linus changed his mind about c99 comments
some time ago. It is now allowed. More than that, using c99 comments is 
now mandatory for SPDX on c files.

In any case, changing to /* */ is as easy as running this script:

	for i in drivers/staging/hikey9xx/gpu/*.[ch]; do perl -ne 'if (! m,// SPDX,) { s,//\s*(.*),/* \1 */,; }; print $_' -i $i; done

As I also prefer not using c99 comments, I applied a cleanup patch.

> Some of the enums I checked are not used.

Yeah, based on the size of the header files, when compared with
the size of the code, I suspect that lots of things there won't be
used. Cleaning this could take some time and may end removing
some bits that we could need in the future in order to address
existing problems at the driver. 

So, I opted preserving them, at least on this initial
patchset. I intend to do a further cleanup when trying to
merge this driver with the one for Kirin 620. On a side node,
currently, I don't have a Kirin 620 board. So, I'm postponing
such task until I get one such boards, as I'm not willing
to take the risk of changing it without being able to test.

> If their members are used then consider to use the enum
> and not just an int.

Yeah, it makes sense to use enum for type consistency.

I would prefer to do such kind of cleanup later on, together
with the attempt of having a single driver for all Kirin
supported DRM, as this is something that I'll need to revisit
when trying to merge the code.

> > +	ctx->dss_pri_clk = devm_clk_get(dev, "clk_edc0");
> > +	if (!ctx->dss_pri_clk) {
> > +		DRM_ERROR("failed to parse dss_pri_clk\n");
> > +	return -ENODEV;
> > +	}
...

> I had expected some of these could fail with a PROBE_DEFER.
> Consider to use the newly introduced dev_probe_err()

Yeah, getting clock lines can fail. I was unable to find dev_probe_err(),
at least on Kernel 5.9-rc1. I saw this comment:

	https://lkml.org/lkml/2020/3/6/356

It sounds it didn't reach upstream. Anyway, I add error handling for the
the clk_get calls:

	ctx->dss_pri_clk = devm_clk_get(dev, "clk_edc0");
	ret = PTR_ERR_OR_ZERO(ctx->dss_pri_clk);
	if (ret == -EPROBE_DEFER) {
		return ret;
	} else if (ret) {
		DRM_ERROR("failed to parse dss_pri_clk: %d\n", ret);
		return ret;
	}

This should be able to detect deferred probe, plus to warn
about other errors.

PS.: I'll be changing DRM_foo() to drm_foo() on a separate
patchset, after finishing the remaining code changes.


> > +static int  dss_drm_suspend(struct platform_device *pdev, pm_message_t state)
> > +{
> > +	struct dss_data *dss = platform_get_drvdata(pdev);
> > +	struct drm_crtc *crtc = &dss->acrtc.base;
> > +
> > +	dss_crtc_disable(crtc, NULL);
> > +
> > +	return 0;
> > +}  
> There is a suspend (and resume) helper - can it be used?

That's a very good question. Hard to answer right, as last time
I checked, DPMS suspend/resume are currently broken. 

I need to re-test it, but it has been hard to work on that part,
because right now there's no USB driver (so, no keyboard/mouse).

I was using x2x to send evdev events to the remote machine, but
I did some changes at the test distro, and this stopped working.

I need to find some other solution to send evdev events to Hikey970
while I don't fix my USB driver port.

So, for now, I prefer keeping those. I'll revisit this before
moving the driver out of staging, as this is one of the current
bugs.

> > +
> > +#define ROUND(x, y)		((x) / (y) + \
> > +				((x) % (y) * 10 / (y) >= 5 ? 1 : 0))
> > +#define ROUND1(x, y)	((x) / (y) + ((x) % (y)  ? 1 : 0))  
> Use generic macros for this?

> > +#define encoder_to_dsi(encoder) \
> > +	container_of(encoder, struct dw_dsi, encoder)
> > +#define host_to_dsi(host) \
> > +	container_of(host, struct dw_dsi, host)
> > +#define connector_to_dsi(connector) \
> > +	container_of(connector, struct dw_dsi, connector)
> > +#define DSS_REDUCE(x)	((x) > 0 ? ((x) - 1) : (x))  
> Use generic macros for this?

> > +struct dw_dsi_client {
> > +	u32 lanes;
> > +	u32 phy_clock; /* in kHz */
> > +	enum mipi_dsi_pixel_format format;
> > +	unsigned long mode_flags;
> > +};
> > +  
> 
> Can the panel stuff be moved out and utilise drm_panel?

I saw the code at drm_panel. The real issue here is that I can't
test anything related to panel support, as I lack any hardware
for testing. So, there's a high chance I may end breaking
something while trying to do that.

> > +struct dw_dsi {
> > +	struct drm_encoder encoder;
> > +	struct drm_bridge *bridge;
> > +	struct drm_panel *panel;
> > +	struct mipi_dsi_host host;
> > +	struct drm_connector connector; /* connector for panel */
> > +	struct drm_display_mode cur_mode;
> > +	struct dsi_hw_ctx *ctx;
> > +	struct mipi_phy_params phy;
> > +	struct mipi_panel_info mipi;
> > +	struct ldi_panel_info ldi;
> > +	u32 lanes;
> > +	enum mipi_dsi_pixel_format format;
> > +	unsigned long mode_flags;
> > +	struct gpio_desc *gpio_mux;
> > +	struct dw_dsi_client client[OUT_MAX];
> > +	enum dsi_output_client cur_client, attached_client;
> > +	bool enable;
> > +};  
> This smells like a bridge driver.
> Bridge drivers shall use the bridge panel.
> And new bridge drivers shall not create conectors, thats the role of the
> display driver.

Actually, this device is "hybrid" with regards to bridges.
HDMI uses an external bridge (adv7535), while panel doesn't.

In any case, I would prefer not touching anything related to
the panel. As I mentioned on my other comment, currently
I lack any panels that might work on Hikey 970. So, this is
something I can't test.

> > +
> > +	/* Link drm_bridge to encoder */
> > +	if (!bridge) {
> > +		DRM_INFO("no dsi bridge to attach the encoder\n");
> > +		return 0;
> > +	}
> > +
> > +	crtc_mask = drm_of_find_possible_crtcs(drm_dev, dev->of_node);
> > +	if (!crtc_mask) {
> > +		DRM_ERROR("failed to find crtc mask\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	dev_info(dev, "Initializing CRTC encoder: %d\n",
> > +		 crtc_mask);
> > +
> > +	encoder->possible_crtcs = crtc_mask;
> > +	encoder->possible_clones = 0;
> > +	ret = drm_encoder_init(drm_dev, encoder, &dw_encoder_funcs,
> > +			       DRM_MODE_ENCODER_DSI, NULL);
> > +	if (ret) {
> > +		DRM_ERROR("failed to init dsi encoder\n");
> > +		return ret;
> > +	}
> > +
> > +	drm_encoder_helper_add(encoder, &dw_encoder_helper_funcs);
> > +
> > +	/* associate the bridge to dsi encoder */
> > +	ret = drm_bridge_attach(encoder, bridge, NULL, 0);  
> The bridge should be attached with the falg that tell the bridge NOT to
> create a connector.
> 
> The display driver shall created the connector.
> 
> Please see how other drivers do this (but most driver uses the old
> pattern so so look for drm_bridge_attach() with the flag argument.
> I cannot see any user of this pwm and backlight stuff.
> So the best would be to drop it all.
> > +
> > +int hisi_pwm_set_backlight(struct backlight_device *bl, uint32_t bl_level)
> > +{

Yeah, this was dropped in a patch on this series that it is after the DT
changes.

The PWM and backlight stuff is used by the display panel driver which
came together with the DRM drivers. I dropped it, together with the
parts of the driver which used to call them.


Thanks,
Mauro

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
       [not found]     ` <20200819173558.GA3733@ravnborg.org>
                         ` (2 preceding siblings ...)
  2020-08-21 13:58       ` Mauro Carvalho Chehab
@ 2020-08-21 14:41       ` Mauro Carvalho Chehab
  2020-08-21 15:56         ` Sam Ravnborg
  3 siblings, 1 reply; 42+ messages in thread
From: Mauro Carvalho Chehab @ 2020-08-21 14:41 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: Greg Kroah-Hartman, Neil Armstrong, Xinliang Liu, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Laurent Pinchart, devel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	David Airlie, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Laurentiu Palcu, linux-media, devicetree, Liwei Cai,
	Jesper Dangaard Brouer, Manivannan Sadhasivam, Chen Feng,
	Alexei Starovoitov, linaro-mm-sig, Rob Herring, Jakub Kicinski,
	mauro.chehab, Rob Clark, linux-arm-kernel, netdev, linux-kernel,
	Liuyao An, Rongrong Zou, bpf, David S. Miller

Another quick question:

Em Wed, 19 Aug 2020 19:35:58 +0200
Sam Ravnborg <sam@ravnborg.org> escreveu:

> > +#define DSS_REDUCE(x)	((x) > 0 ? ((x) - 1) : (x))  
> Use generic macros for this?

Do you know a generic macro similar to this? Or do you mean adding
it to include/kernel.h?

There are the atomic sub ones, but doesn't make sense here.

The closest one I found was min_not_zero(), but this would
take two args.

Btw, I agree that the name here is a bit odd... I would
have called such macro as 'dec_not_zero()'.

Thanks,
Mauro

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-21 13:58       ` Mauro Carvalho Chehab
@ 2020-08-21 15:55         ` Sam Ravnborg
       [not found]           ` <20200824180225.1a515b6a@coco.lan>
  0 siblings, 1 reply; 42+ messages in thread
From: Sam Ravnborg @ 2020-08-21 15:55 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Greg Kroah-Hartman, Neil Armstrong, Xinliang Liu, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Laurent Pinchart, devel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	David Airlie, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Laurentiu Palcu, linux-media, devicetree, Liwei Cai,
	Jesper Dangaard Brouer, Manivannan Sadhasivam, Chen Feng,
	Alexei Starovoitov, linaro-mm-sig, Rob Herring, Jakub Kicinski,
	mauro.chehab, Rob Clark, linux-arm-kernel, netdev, linux-kernel,
	Liuyao An, Rongrong Zou, bpf, David S. Miller

Hi Mauro.

Thanks for the detailed feedabck.
Two comments in the following.

	Sam

> 
> > > +	ctx->dss_pri_clk = devm_clk_get(dev, "clk_edc0");
> > > +	if (!ctx->dss_pri_clk) {
> > > +		DRM_ERROR("failed to parse dss_pri_clk\n");
> > > +	return -ENODEV;
> > > +	}
> ...
> 
> > I had expected some of these could fail with a PROBE_DEFER.
> > Consider to use the newly introduced dev_probe_err()
> 
> Yeah, getting clock lines can fail. I was unable to find dev_probe_err(),
> at least on Kernel 5.9-rc1. I saw this comment:
> 
> 	https://lkml.org/lkml/2020/3/6/356
> 
> It sounds it didn't reach upstream. Anyway, I add error handling for the
> the clk_get calls:
> 
> 	ctx->dss_pri_clk = devm_clk_get(dev, "clk_edc0");
> 	ret = PTR_ERR_OR_ZERO(ctx->dss_pri_clk);
> 	if (ret == -EPROBE_DEFER) {
> 		return ret;
> 	} else if (ret) {
> 		DRM_ERROR("failed to parse dss_pri_clk: %d\n", ret);
> 		return ret;
> 	}
> 
> This should be able to detect deferred probe, plus to warn
> about other errors.

I got the name wrong. It is named dev_err_probe(), and was introduced in -rc1.
 
> > Can the panel stuff be moved out and utilise drm_panel?
> 
> I saw the code at drm_panel. The real issue here is that I can't
> test anything related to panel support, as I lack any hardware
> for testing. So, there's a high chance I may end breaking
> something while trying to do that.

I will try to take a look again when you post next revision.
Maybe we should update it and risk that is not works, so whenever
someone try to fix it they do so on top of an up-to-date implmentation.
Lets se and decide later.


	Sam

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-21 14:41       ` Mauro Carvalho Chehab
@ 2020-08-21 15:56         ` Sam Ravnborg
  2020-08-24 16:06           ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 42+ messages in thread
From: Sam Ravnborg @ 2020-08-21 15:56 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Greg Kroah-Hartman, Neil Armstrong, Xinliang Liu, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Laurent Pinchart, devel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	David Airlie, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Laurentiu Palcu, linux-media, devicetree, Liwei Cai,
	Jesper Dangaard Brouer, Manivannan Sadhasivam, Chen Feng,
	Alexei Starovoitov, linaro-mm-sig, Rob Herring, Jakub Kicinski,
	mauro.chehab, Rob Clark, linux-arm-kernel, netdev, linux-kernel,
	Liuyao An, Rongrong Zou, bpf, David S. Miller

Hi Mauro.

On Fri, Aug 21, 2020 at 04:41:58PM +0200, Mauro Carvalho Chehab wrote:
> Another quick question:
> 
> Em Wed, 19 Aug 2020 19:35:58 +0200
> Sam Ravnborg <sam@ravnborg.org> escreveu:
> 
> > > +#define DSS_REDUCE(x)	((x) > 0 ? ((x) - 1) : (x))  
> > Use generic macros for this?
> 
> Do you know a generic macro similar to this? Or do you mean adding
> it to include/kernel.h?

It looked like something there should be a macro for.
But I do not know one.

And no, do not try to go the kernel.h route on this.
At least not until you see more than one user.

	Sam

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
       [not found]     ` <20200819204800.GA110118@ravnborg.org>
  2020-08-20  7:21       ` Michel Dänzer
  2020-08-20  7:21       ` Mauro Carvalho Chehab
@ 2020-08-21 16:09       ` Joe Perches
  2 siblings, 0 replies; 42+ messages in thread
From: Joe Perches @ 2020-08-21 16:09 UTC (permalink / raw)
  To: Sam Ravnborg, Mauro Carvalho Chehab
  Cc: Greg Kroah-Hartman, Neil Armstrong, Xinliang Liu, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Laurent Pinchart, devel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	David Airlie, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Laurentiu Palcu, linux-media, devicetree, Liwei Cai,
	Jesper Dangaard Brouer, Manivannan Sadhasivam, Chen Feng,
	Alexei Starovoitov, linaro-mm-sig, Rob Herring, Jakub Kicinski,
	mauro.chehab, Rob Clark, linux-arm-kernel, netdev, linux-kernel,
	Liuyao An, Rongrong Zou, bpf, David S. Miller

On Wed, 2020-08-19 at 22:48 +0200, Sam Ravnborg wrote:
> And sometimes checkpatch is just wrong.

I'm interested in examples for when checkpatch is "just wrong".



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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-20  3:28     ` John Stultz
  2020-08-20  7:48       ` Mauro Carvalho Chehab
@ 2020-08-24  6:49       ` Mauro Carvalho Chehab
  2020-08-24 13:18         ` Mauro Carvalho Chehab
  1 sibling, 1 reply; 42+ messages in thread
From: Mauro Carvalho Chehab @ 2020-08-24  6:49 UTC (permalink / raw)
  To: John Stultz
  Cc: Greg Kroah-Hartman, linuxarm, mauro.chehab,
	Manivannan Sadhasivam, Daniel Vetter, dri-devel, Bogdan Togorean,
	Liwei Cai, linux-arm-kernel, Daniel Borkmann, Rob Herring,
	David S. Miller, Xinliang Liu, Neil Armstrong, Wanchun Zheng,
	driverdevel, BPF Mailing List, linux-media, Tomi Valkeinen,
	Jesper Dangaard Brouer, Laurent Pinchart, Xinwei Kong,
	Alexei Starovoitov,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Rob Clark, Laurentiu Palcu, Andrzej Hajda, John Fastabend,
	Liuyao An, moderated list:DMA BUFFER SHARING FRAMEWORK, Wei Xu,
	Rongrong Zou, Philipp Zabel, Sam Ravnborg, Network Development,
	Sumit Semwal, lkml, Jakub Kicinski, David Airlie, Chen Feng

Hi John,

Em Wed, 19 Aug 2020 20:28:44 -0700
John Stultz <john.stultz@linaro.org> escreveu:


> That said even with the patches I've got on top of your series, I
> still see a few issues:
> 1) I'm seeing red-blue swap with your driver.  I need to dig a bit to
> see what the difference is, I know gralloc has a config option for
> this, and maybe the version of the driver I'm carrying has it wrong?

Maybe it is due to this:

	drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c:      hal_fmt = HISI_FB_PIXEL_FORMAT_BGRA_8888;/* dss_get_format(fb->pixel_format); */

It sounds to me that someone added a hack hardcoding BGRA_8888 over
there.

Btw, I removed the hack, with:


diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c
index a68db1a27bbf..ba64aae371e4 100644
--- a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c
+++ b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c
@@ -857,7 +857,7 @@ void hisi_fb_pan_display(struct drm_plane *plane)
        rect.right = src_w - 1;
        rect.top = 0;
        rect.bottom = src_h - 1;
-       hal_fmt = HISI_FB_PIXEL_FORMAT_BGRA_8888;/* dss_get_format(fb->pixel_format); */
+       hal_fmt = dss_get_format(fb->format->format);
 
        DRM_DEBUG_DRIVER("channel%d: src:(%d,%d, %dx%d) crtc:(%d,%d, %dx%d), rect(%d,%d,%d,%d),fb:%dx%d, pixel_format=%d, stride=%d, paddr=0x%x, bpp=%d.\n",
                         chn_idx, src_x, src_y, src_w, src_h,


And now red and blue are swapped on my HDMI screen too.

I'll compare this part with your version, but I guess the bug is
on this logic.


Thanks,
Mauro

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-24  6:49       ` Mauro Carvalho Chehab
@ 2020-08-24 13:18         ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 42+ messages in thread
From: Mauro Carvalho Chehab @ 2020-08-24 13:18 UTC (permalink / raw)
  To: John Stultz
  Cc: Greg Kroah-Hartman, linuxarm, mauro.chehab,
	Manivannan Sadhasivam, Daniel Vetter, dri-devel, Bogdan Togorean,
	Liwei Cai, linux-arm-kernel, Daniel Borkmann, Rob Herring,
	David S. Miller, Xinliang Liu, Neil Armstrong, Wanchun Zheng,
	driverdevel, BPF Mailing List, linux-media, Tomi Valkeinen,
	Jesper Dangaard Brouer, Laurent Pinchart, Xinwei Kong,
	Alexei Starovoitov,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Rob Clark, Laurentiu Palcu, Andrzej Hajda, John Fastabend,
	Liuyao An, moderated list:DMA BUFFER SHARING FRAMEWORK, Wei Xu,
	Rongrong Zou, Philipp Zabel, Sam Ravnborg, Network Development,
	Sumit Semwal, lkml, Jakub Kicinski, David Airlie, Chen Feng

Em Mon, 24 Aug 2020 08:49:30 +0200
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> escreveu:

> Hi John,
> 
> Em Wed, 19 Aug 2020 20:28:44 -0700
> John Stultz <john.stultz@linaro.org> escreveu:
> 
> 
> > That said even with the patches I've got on top of your series, I
> > still see a few issues:
> > 1) I'm seeing red-blue swap with your driver.  I need to dig a bit to
> > see what the difference is, I know gralloc has a config option for
> > this, and maybe the version of the driver I'm carrying has it wrong?  
> 
> Maybe it is due to this:
> 
> 	drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c:      hal_fmt = HISI_FB_PIXEL_FORMAT_BGRA_8888;/* dss_get_format(fb->pixel_format); */
> 
> It sounds to me that someone added a hack hardcoding BGRA_8888 over
> there.
> 
> Btw, I removed the hack, with:
> 
> 
> diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c
> index a68db1a27bbf..ba64aae371e4 100644
> --- a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c
> +++ b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c
> @@ -857,7 +857,7 @@ void hisi_fb_pan_display(struct drm_plane *plane)
>         rect.right = src_w - 1;
>         rect.top = 0;
>         rect.bottom = src_h - 1;
> -       hal_fmt = HISI_FB_PIXEL_FORMAT_BGRA_8888;/* dss_get_format(fb->pixel_format); */
> +       hal_fmt = dss_get_format(fb->format->format);
>  
>         DRM_DEBUG_DRIVER("channel%d: src:(%d,%d, %dx%d) crtc:(%d,%d, %dx%d), rect(%d,%d,%d,%d),fb:%dx%d, pixel_format=%d, stride=%d, paddr=0x%x, bpp=%d.\n",
>                          chn_idx, src_x, src_y, src_w, src_h,
> 
> 
> And now red and blue are swapped on my HDMI screen too.
> 
> I'll compare this part with your version, but I guess the bug is
> on this logic.

It sounds to me that the Hikey 960 version on your tree has some color 
inversion hack, just for ARGB 32 bpp. See:

	static const struct kirin_format dpe_formats[] = {
		{ DRM_FORMAT_RGB565, DPE_RGB_565 },
		{ DRM_FORMAT_BGR565, DPE_BGR_565 },
		{ DRM_FORMAT_XRGB8888, DPE_RGBX_8888 },
		{ DRM_FORMAT_XBGR8888, DPE_BGRX_8888 },
		{ DRM_FORMAT_RGBA8888, DPE_RGBA_8888 },
		{ DRM_FORMAT_BGRA8888, DPE_BGRA_8888 },
		{ DRM_FORMAT_ARGB8888, DPE_BGRA_8888 },
		{ DRM_FORMAT_ABGR8888, DPE_RGBA_8888 },
	};

The last two lines are weird, as they're reverting the byte order,
If there's some endiannes issue (which the change from ARGB->ABGR 
seems to imply), I would expect to have something similar for the 
other formats as well.

I did some tests here: both FB and X11 sets bpp to 24 bits.

Trying to use "startx -- -depth 32" don't work:

	"Default Screen Section" for depth/fbbpp 32/32
	[   129.250] (EE) modeset(0): Given depth (32) is not supported by the driver

Which sounds weird, as the driver announces 32 bit formats. 
I suspect that this could be related to the valid modes hack at 
the driver.

Btw, there are some color shift also with --depth 16, but replacing
BGR <=> RGB didn't work.

Did you test the different bpp resolutions with the driver on your
tree? The enclosed patch makes 24 bits bpp work here.

Thanks,
Mauro

-

[PATCH] staging: kirin9xx/gpu: rework the colorspace mode setting logic

There are some problems when setting the fourcc KMS:
The original code hardcodes BGRA_8888. The real issue here seems
to be that the byte order is different than the one for Kirin 620.

Instead of addressing it, the origincla code just used a fixed
mode. A port of the Hikey 960 DPE driver based on Kernel 5.0,
found at:

	https://git.linaro.org/people/john.stultz/android-dev.git/tree/drivers/gpu/drm/hisilicon/kirin/kirin_drm_dpe.c?h=dev/hikey960-mainline-WIP

contains a hack that swaps the byte order for 32-bits
ARGB/BRGR (see the last two lines):

		{ DRM_FORMAT_RGB565, DPE_RGB_565 },
		{ DRM_FORMAT_BGR565, DPE_BGR_565 },
		{ DRM_FORMAT_XRGB8888, DPE_RGBX_8888 },
		{ DRM_FORMAT_XBGR8888, DPE_BGRX_8888 },
		{ DRM_FORMAT_RGBA8888, DPE_RGBA_8888 },
		{ DRM_FORMAT_BGRA8888, DPE_BGRA_8888 },
		{ DRM_FORMAT_ARGB8888, DPE_BGRA_8888 },
		{ DRM_FORMAT_ABGR8888, DPE_RGBA_8888 },

But the same change was not applied to other modesets.

The Hikey 960 port was tested with AOSP, which seems to
be using ABGR format. Here, the chosen fourcc was
XBGR 32 bpp instead. I suspect that the original developer
also found a similar issue and decided to hardcode the
fourcc format.

That's said, currently the drivers uses some code instead of
tables in order to seek for the register settings. The version
from John Stultz tre for Kirin 960 that does a better approach
of using tables instead of code.

I opted to use the same code as the basis for the new logic,
as it makes easier to identify what the driver is actually doing.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_dpe.h b/drivers/staging/hikey9xx/gpu/kirin9xx_dpe.h
index e05522f85df8..26add227c389 100644
--- a/drivers/staging/hikey9xx/gpu/kirin9xx_dpe.h
+++ b/drivers/staging/hikey9xx/gpu/kirin9xx_dpe.h
@@ -144,6 +144,39 @@ enum dss_dma_format {
 	DMA_PIXEL_FORMAT_AYUV_4444,
 };
 
+enum dpe_fb_format {
+	DPE_RGB_565 = 0,
+	DPE_RGBX_4444,
+	DPE_RGBA_4444,
+	DPE_RGBX_5551,
+	DPE_RGBA_5551,
+	DPE_RGBX_8888,
+	DPE_RGBA_8888,
+	DPE_BGR_565,
+	DPE_BGRX_4444,
+	DPE_BGRA_4444,
+	DPE_BGRX_5551,
+	DPE_BGRA_5551,
+	DPE_BGRX_8888,
+	DPE_BGRA_8888,
+	DPE_YUV_422_I,
+	/* YUV Semi-planar */
+	DPE_YCbCr_422_SP,
+	DPE_YCrCb_422_SP,
+	DPE_YCbCr_420_SP,
+	DPE_YCrCb_420_SP,
+	/* YUV Planar */
+	DPE_YCbCr_422_P,
+	DPE_YCrCb_422_P,
+	DPE_YCbCr_420_P,
+	DPE_YCrCb_420_P,
+	/* YUV Package */
+	DPE_YUYV_422_Pkg,
+	DPE_UYVY_422_Pkg,
+	DPE_YVYU_422_Pkg,
+	DPE_VYUY_422_Pkg,
+};
+
 enum dss_buf_format {
 	DSS_BUF_LINEAR = 0,
 	DSS_BUF_TILE,
diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dpe_utils.h b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dpe_utils.h
index 8034c5134b25..a3071388a86c 100644
--- a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dpe_utils.h
+++ b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dpe_utils.h
@@ -22,46 +22,7 @@ enum dss_channel {
 
 #define PRIMARY_CH	DSS_CH1 /* primary plane */
 
-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,
-	HISI_FB_PIXEL_FORMAT_UYVY_422,
-	HISI_FB_PIXEL_FORMAT_YVYU_422,
-	HISI_FB_PIXEL_FORMAT_VYUY_422,
-	HISI_FB_PIXEL_FORMAT_MAX,
-
-	HISI_FB_PIXEL_FORMAT_UNSUPPORT = 800
-};
+#define HISI_FB_PIXEL_FORMAT_UNSUPPORT 800
 
 struct dss_hw_ctx {
 	struct drm_device *dev;
@@ -155,12 +116,6 @@ struct dss_data {
 	struct dss_hw_ctx ctx;
 };
 
-/* ade-format info: */
-struct dss_format {
-	u32 pixel_format;
-	enum hisi_fb_pixel_format dss_format;
-};
-
 struct dss_img {
 	u32 format;
 	u32 width;
@@ -266,8 +221,10 @@ int hisi_dss_mctl_mutex_lock(struct dss_hw_ctx *ctx);
 int hisi_dss_mctl_mutex_unlock(struct dss_hw_ctx *ctx);
 int hisi_dss_ovl_base_config(struct dss_hw_ctx *ctx, u32 xres, u32 yres);
 
+u32 hisi_dss_get_channel_formats(struct drm_device *dev, u8 ch, const u32 **formats);
+
 void hisi_fb_pan_display(struct drm_plane *plane);
 
-u32 dss_get_format(struct drm_device *dev, u32 pixel_format);
+u32 dpe_get_format(struct dss_hw_ctx *ctx, u32 pixel_format);
 
 #endif
diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dss.c b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dss.c
index 9bc114a33885..93eb9bf8b305 100644
--- a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dss.c
+++ b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dss.c
@@ -38,58 +38,6 @@
 #include "kirin9xx_drm_dpe_utils.h"
 #include "kirin9xx_dpe.h"
 
-static const struct dss_format dss_formats[] = {
-	/* 16bpp RGB: */
-	{ DRM_FORMAT_RGB565, HISI_FB_PIXEL_FORMAT_RGB_565 },
-	{ DRM_FORMAT_BGR565, HISI_FB_PIXEL_FORMAT_BGR_565 },
-	/* 32bpp [A]RGB: */
-	{ DRM_FORMAT_XRGB8888, HISI_FB_PIXEL_FORMAT_RGBX_8888 },
-	{ DRM_FORMAT_XBGR8888, HISI_FB_PIXEL_FORMAT_BGRX_8888 },
-	{ DRM_FORMAT_RGBA8888, HISI_FB_PIXEL_FORMAT_RGBA_8888 },
-	{ DRM_FORMAT_BGRA8888, HISI_FB_PIXEL_FORMAT_BGRA_8888 },
-	{ DRM_FORMAT_ARGB8888, HISI_FB_PIXEL_FORMAT_RGBA_8888 },
-	{ DRM_FORMAT_ABGR8888, HISI_FB_PIXEL_FORMAT_BGRA_8888 },
-};
-
-static const u32 channel_formats1[] = {
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_BGR565,
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_XBGR8888,
-	DRM_FORMAT_RGBA8888,
-	DRM_FORMAT_BGRA8888,
-	DRM_FORMAT_ARGB8888,
-	DRM_FORMAT_ABGR8888,
-};
-
-u32 dss_get_channel_formats(struct drm_device *dev, u8 ch, const u32 **formats)
-{
-	switch (ch) {
-	case DSS_CH1:
-		*formats = channel_formats1;
-		return ARRAY_SIZE(channel_formats1);
-	default:
-		drm_err(dev, "no formats for channel %d\n", ch);
-		*formats = NULL;
-		return 0;
-	}
-}
-
-/* convert from fourcc format to dss format */
-u32 dss_get_format(struct drm_device *dev, u32 pixel_format)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(dss_formats); i++)
-		if (dss_formats[i].pixel_format == pixel_format)
-			return dss_formats[i].dss_format;
-
-	/* not found */
-	drm_err(dev, "Not found pixel format!!fourcc_format= %d\n",
-		pixel_format);
-	return HISI_FB_PIXEL_FORMAT_UNSUPPORT;
-}
-
 /*****************************************************************************/
 
 int hdmi_pxl_ppll7_init(struct dss_hw_ctx *ctx, u64 pixel_clock)
@@ -616,6 +564,8 @@ static int dss_plane_atomic_check(struct drm_plane *plane,
 {
 	struct drm_framebuffer *fb = state->fb;
 	struct drm_crtc *crtc = state->crtc;
+	struct dss_crtc *acrtc = to_dss_crtc(crtc);
+	struct dss_hw_ctx *ctx = acrtc->ctx;
 	struct drm_crtc_state *crtc_state;
 	u32 src_x = state->src_x >> 16;
 	u32 src_y = state->src_y >> 16;
@@ -630,7 +580,7 @@ static int dss_plane_atomic_check(struct drm_plane *plane,
 	if (!crtc || !fb)
 		return 0;
 
-	fmt = dss_get_format(plane->dev, fb->format->format);
+	fmt = dpe_get_format(ctx, fb->format->format);
 	if (fmt == HISI_FB_PIXEL_FORMAT_UNSUPPORT)
 		return -EINVAL;
 
@@ -706,7 +656,7 @@ static int dss_plane_init(struct drm_device *dev, struct dss_plane *aplane,
 	int ret = 0;
 
 	/* get properties */
-	fmts_cnt = dss_get_channel_formats(dev, aplane->ch, &fmts);
+	fmts_cnt = hisi_dss_get_channel_formats(dev, aplane->ch, &fmts);
 	if (ret)
 		return ret;
 
diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c
index a68db1a27bbf..fb034337d689 100644
--- a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c
+++ b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c
@@ -22,168 +22,118 @@ static const int mid_array[DSS_CHN_MAX_DEFINE] = {
 	0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x2, 0x1, 0x3, 0x0
 };
 
-static int hisi_pixel_format_hal2dma(int format)
+struct dpe_format {
+	u32 pixel_format;
+	enum dpe_fb_format dpe_format;
+};
+
+static const struct dpe_format dpe_formats[] = {
+	{ DRM_FORMAT_RGB565, DPE_RGB_565 },
+	{ DRM_FORMAT_BGR565, DPE_BGR_565 },
+	{ DRM_FORMAT_XRGB8888, DPE_BGRX_8888 },
+	{ DRM_FORMAT_XBGR8888, DPE_RGBX_8888 },
+	{ DRM_FORMAT_RGBA8888, DPE_RGBA_8888 },
+	{ DRM_FORMAT_BGRA8888, DPE_BGRA_8888 },
+	{ DRM_FORMAT_ARGB8888, DPE_RGBA_8888 },
+	{ DRM_FORMAT_ABGR8888, DPE_BGRA_8888 },
+};
+
+static const u32 dpe_channel_formats[] = {
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR565,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_RGBA8888,
+	DRM_FORMAT_BGRA8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ABGR8888,
+};
+
+static u32 dpe_pixel_dma_format_map[] = {
+	DMA_PIXEL_FORMAT_RGB_565,
+	DMA_PIXEL_FORMAT_XRGB_4444,
+	DMA_PIXEL_FORMAT_ARGB_4444,
+	DMA_PIXEL_FORMAT_XRGB_5551,
+	DMA_PIXEL_FORMAT_ARGB_5551,
+	DMA_PIXEL_FORMAT_XRGB_8888,
+	DMA_PIXEL_FORMAT_ARGB_8888,
+	DMA_PIXEL_FORMAT_RGB_565,
+	DMA_PIXEL_FORMAT_XRGB_4444,
+	DMA_PIXEL_FORMAT_ARGB_4444,
+	DMA_PIXEL_FORMAT_XRGB_5551,
+	DMA_PIXEL_FORMAT_ARGB_5551,
+	DMA_PIXEL_FORMAT_XRGB_8888,
+	DMA_PIXEL_FORMAT_ARGB_8888,
+	DMA_PIXEL_FORMAT_YUYV_422,
+	DMA_PIXEL_FORMAT_YUV_422_SP_HP,
+	DMA_PIXEL_FORMAT_YUV_422_SP_HP,
+	DMA_PIXEL_FORMAT_YUV_420_SP_HP,
+	DMA_PIXEL_FORMAT_YUV_420_SP_HP,
+	DMA_PIXEL_FORMAT_YUV_422_P_HP,
+	DMA_PIXEL_FORMAT_YUV_422_P_HP,
+	DMA_PIXEL_FORMAT_YUV_420_P_HP,
+	DMA_PIXEL_FORMAT_YUV_420_P_HP,
+	DMA_PIXEL_FORMAT_YUYV_422,
+	DMA_PIXEL_FORMAT_YUYV_422,
+	DMA_PIXEL_FORMAT_YUYV_422,
+	DMA_PIXEL_FORMAT_YUYV_422,
+};
+
+static u32 dpe_pixel_dfc_format_map[] = {
+	DFC_PIXEL_FORMAT_RGB_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_BGR_565,
+	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_YUYV422,
+	DFC_PIXEL_FORMAT_YUYV422,
+	DFC_PIXEL_FORMAT_YVYU422,
+	DFC_PIXEL_FORMAT_YUYV422,
+	DFC_PIXEL_FORMAT_YVYU422,
+	DFC_PIXEL_FORMAT_YUYV422,
+	DFC_PIXEL_FORMAT_YVYU422,
+	DFC_PIXEL_FORMAT_YUYV422,
+	DFC_PIXEL_FORMAT_YVYU422,
+	DFC_PIXEL_FORMAT_YUYV422,
+	DFC_PIXEL_FORMAT_UYVY422,
+	DFC_PIXEL_FORMAT_YVYU422,
+	DFC_PIXEL_FORMAT_VYUY422,
+};
+
+u32 dpe_get_format(struct dss_hw_ctx *ctx, u32 pixel_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:
-	case HISI_FB_PIXEL_FORMAT_YVYU_422:
-	case HISI_FB_PIXEL_FORMAT_UYVY_422:
-	case HISI_FB_PIXEL_FORMAT_VYUY_422:
-		ret = DMA_PIXEL_FORMAT_YUYV_422;
-		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:
-		DRM_ERROR("not support format(%d)!\n", format);
-		ret = -1;
-		break;
+	int i;
+	const struct dpe_format *fmt = dpe_formats;
+	u32 size = ARRAY_SIZE(dpe_formats);
+
+
+	for (i = 0; i < size; i++) {
+		if (fmt[i].pixel_format == pixel_format) {
+			drm_info(ctx->dev, "requested fourcc %x, dpe format %d",
+				 pixel_format, fmt[i].dpe_format);
+			return fmt[i].dpe_format;
+		}
 	}
 
-	return ret;
+	drm_err(ctx->dev, "Not found pixel format! fourcc = %x\n",
+		pixel_format);
+
+	return HISI_FB_PIXEL_FORMAT_UNSUPPORT;
 }
 
-static int hisi_pixel_format_hal2dfc(int format)
+u32 hisi_dss_get_channel_formats(struct drm_device *dev, u8 ch, const u32 **formats)
 {
-	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:
-		ret = DFC_PIXEL_FORMAT_YUYV422;
-		break;
-	case HISI_FB_PIXEL_FORMAT_YVYU_422:
-		ret = DFC_PIXEL_FORMAT_YVYU422;
-		break;
-	case HISI_FB_PIXEL_FORMAT_UYVY_422:
-		ret = DFC_PIXEL_FORMAT_UYVY422;
-		break;
-	case HISI_FB_PIXEL_FORMAT_VYUY_422:
-		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:
-		DRM_ERROR("not support format(%d)!\n", format);
-		ret = -1;
-		break;
-	}
-
-	return ret;
+	*formats = dpe_channel_formats;
+	return ARRAY_SIZE(dpe_channel_formats);
 }
 
 static int hisi_dss_aif_ch_config(struct dss_hw_ctx *ctx, int chn_idx)
@@ -347,8 +297,10 @@ static int hisi_dss_mctl_sys_config(struct dss_hw_ctx *ctx, int chn_idx)
 }
 
 static int hisi_dss_rdma_config(struct dss_hw_ctx *ctx,
-				const struct dss_rect_ltrb *rect, u32 display_addr, u32 hal_format,
-	u32 bpp, int chn_idx, bool afbcd, bool mmu_enable)
+				const struct dss_rect_ltrb *rect,
+				u32 display_addr, u32 hal_format,
+				u32 bpp, int chn_idx, bool afbcd,
+				bool mmu_enable)
 {
 	void __iomem *rdma_base;
 
@@ -358,7 +310,6 @@ static int hisi_dss_rdma_config(struct dss_hw_ctx *ctx,
 	u32 rdma_oft_x1 = 0;
 	u32 rdma_oft_y1 = 0;
 	u32 rdma_stride = 0;
-	u32 rdma_bpp = 0;
 	u32 rdma_format = 0;
 	u32 stretch_size_vrt = 0;
 
@@ -371,18 +322,6 @@ static int hisi_dss_rdma_config(struct dss_hw_ctx *ctx,
 	u32 afbcd_payload_addr = 0;
 	u32 afbcd_payload_stride = 0;
 
-	if (!ctx) {
-		DRM_ERROR("ctx is NULL!\n");
-		return -1;
-	}
-
-	if (bpp == 4)
-		rdma_bpp = 0x5;
-	else if (bpp == 2)
-		rdma_bpp = 0x0;
-	else
-		rdma_bpp = 0x0;
-
 	rdma_base = ctx->base +
 		ctx->g_dss_module_base[chn_idx][MODULE_DMA];
 
@@ -392,11 +331,7 @@ static int hisi_dss_rdma_config(struct dss_hw_ctx *ctx,
 	rdma_oft_x1 = rect->right / aligned_pixel;
 	rdma_oft_y1 = rect->bottom;
 
-	rdma_format = hisi_pixel_format_hal2dma(hal_format);
-	if (rdma_format < 0) {
-		DRM_ERROR("layer format(%d) not support !\n", hal_format);
-		return -EINVAL;
-	}
+	rdma_format = dpe_pixel_dma_format_map[hal_format];
 
 	if (afbcd) {
 		mm_base_0 = 0;
@@ -470,10 +405,9 @@ static int hisi_dss_rdma_config(struct dss_hw_ctx *ctx,
 		set_reg(rdma_base + DMA_OFT_Y0, rdma_oft_y0, 16, 0);
 		set_reg(rdma_base + DMA_OFT_X1, rdma_oft_x1, 12, 0);
 		set_reg(rdma_base + DMA_OFT_Y1, rdma_oft_y1, 16, 0);
-		/* set_reg(rdma_base + DMA_CTRL, rdma_format, 5, 3); */
-		/* set_reg(rdma_base + DMA_CTRL, (mmu_enable ? 0x1 : 0x0), 1, 8); */
+		set_reg(rdma_base + DMA_CTRL, rdma_format, 5, 3);
+		set_reg(rdma_base + DMA_CTRL, (mmu_enable ? 0x1 : 0x0), 1, 8);
 		set_reg(rdma_base + DMA_CTRL, 0x130, 32, 0);
-		/* set_reg(rdma_base + DMA_CTRL, (mmu_enable ? 0x1 : 0x0), 1, 8); */
 		set_reg(rdma_base + DMA_STRETCH_SIZE_VRT, stretch_size_vrt, 32, 0);
 		set_reg(rdma_base + DMA_DATA_ADDR0, display_addr, 32, 0);
 		set_reg(rdma_base + DMA_STRIDE0, rdma_stride, 13, 0);
@@ -495,11 +429,6 @@ static int hisi_dss_rdfc_config(struct dss_hw_ctx *ctx,
 	u32 size_vrt = 0;
 	u32 dfc_fmt = 0;
 
-	if (!ctx) {
-		DRM_ERROR("ctx is NULL!\n");
-		return -1;
-	}
-
 	rdfc_base = ctx->base +
 		ctx->g_dss_module_base[chn_idx][MODULE_DFC];
 
@@ -507,15 +436,11 @@ static int hisi_dss_rdfc_config(struct dss_hw_ctx *ctx,
 	size_hrz = rect->right - rect->left;
 	size_vrt = rect->bottom - rect->top;
 
-	dfc_fmt = hisi_pixel_format_hal2dfc(hal_format);
-	if (dfc_fmt < 0) {
-		DRM_ERROR("layer format (%d) not support !\n", hal_format);
-		return -EINVAL;
-	}
+	dfc_fmt = dpe_pixel_dfc_format_map[hal_format];
 
-	set_reg(rdfc_base + DFC_DISP_SIZE, (size_vrt | (size_hrz << 16)), 29, 0);
+	set_reg(rdfc_base + DFC_DISP_SIZE, (size_vrt | (size_hrz << 16)),
+		29, 0);
 	set_reg(rdfc_base + DFC_PIX_IN_NUM, dfc_pix_in_num, 1, 0);
-	/* set_reg(rdfc_base + DFC_DISP_FMT, (bpp <= 2) ? 0x0 : 0x6, 5, 1); */
 	set_reg(rdfc_base + DFC_DISP_FMT, dfc_fmt, 5, 1);
 	set_reg(rdfc_base + DFC_CTL_CLIP_EN, 0x1, 1, 0);
 	set_reg(rdfc_base + DFC_ICG_MODULE, 0x1, 1, 0);
@@ -857,7 +782,7 @@ void hisi_fb_pan_display(struct drm_plane *plane)
 	rect.right = src_w - 1;
 	rect.top = 0;
 	rect.bottom = src_h - 1;
-	hal_fmt = HISI_FB_PIXEL_FORMAT_BGRA_8888;/* dss_get_format(fb->pixel_format); */
+	hal_fmt = dpe_get_format(ctx, fb->format->format);
 
 	DRM_DEBUG_DRIVER("channel%d: src:(%d,%d, %dx%d) crtc:(%d,%d, %dx%d), rect(%d,%d,%d,%d),fb:%dx%d, pixel_format=%d, stride=%d, paddr=0x%x, bpp=%d.\n",
 			 chn_idx, src_x, src_y, src_w, src_h,

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-21 15:56         ` Sam Ravnborg
@ 2020-08-24 16:06           ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 42+ messages in thread
From: Mauro Carvalho Chehab @ 2020-08-24 16:06 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: Greg Kroah-Hartman, Neil Armstrong, Xinliang Liu, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Laurent Pinchart, devel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	David Airlie, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Laurentiu Palcu, linux-media, devicetree, Liwei Cai,
	Jesper Dangaard Brouer, Manivannan Sadhasivam, Chen Feng,
	Alexei Starovoitov, linaro-mm-sig, Rob Herring, Jakub Kicinski,
	mauro.chehab, Rob Clark, linux-arm-kernel, netdev, linux-kernel,
	Liuyao An, Rongrong Zou, bpf, David S. Miller

Em Fri, 21 Aug 2020 17:56:50 +0200
Sam Ravnborg <sam@ravnborg.org> escreveu:

> Hi Mauro.
> 
> On Fri, Aug 21, 2020 at 04:41:58PM +0200, Mauro Carvalho Chehab wrote:
> > Another quick question:
> > 
> > Em Wed, 19 Aug 2020 19:35:58 +0200
> > Sam Ravnborg <sam@ravnborg.org> escreveu:
> >   
> > > > +#define DSS_REDUCE(x)	((x) > 0 ? ((x) - 1) : (x))    
> > > Use generic macros for this?  
> > 
> > Do you know a generic macro similar to this? Or do you mean adding
> > it to include/kernel.h?  
> 
> It looked like something there should be a macro for.
> But I do not know one.
> 
> And no, do not try to go the kernel.h route on this.
> At least not until you see more than one user.

Yeah, adding this to kernel.h just for a single usage is overkill. I would
be expecting that a non-underflow decrement logic is something that 
would be used on other places at the Kernel, but identifying this
pattern would require some time. Maybe Kernel janitors could write some
coccinelle script to replace similar patterns like that into some
macro in the future.

Thanks,
Mauro

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
       [not found]           ` <20200824180225.1a515b6a@coco.lan>
@ 2020-08-24 18:45             ` Sam Ravnborg
  2020-08-24 21:10             ` Sam Ravnborg
                               ` (3 subsequent siblings)
  4 siblings, 0 replies; 42+ messages in thread
From: Sam Ravnborg @ 2020-08-24 18:45 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Greg Kroah-Hartman, Neil Armstrong, Xinliang Liu, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Laurent Pinchart, devel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	David Airlie, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Laurentiu Palcu, linux-media, devicetree, Liwei Cai,
	Jesper Dangaard Brouer, Manivannan Sadhasivam, Chen Feng,
	Alexei Starovoitov, linaro-mm-sig, Rob Herring, Jakub Kicinski,
	mauro.chehab, Rob Clark, linux-arm-kernel, netdev, linux-kernel,
	Liuyao An, Rongrong Zou, bpf, David S. Miller

Hi Mauro.

> Before posting the big patch series again, let me send the new
> version folded into a single patch.

Review 1/N

Lots of small details I missed last time.
A good thing is that there is an opportunity to delete som more code.

	Sam

> diff --git a/drivers/staging/hikey9xx/gpu/Kconfig b/drivers/staging/hikey9xx/gpu/Kconfig
> new file mode 100644
> index 000000000000..8578ca953785
> --- /dev/null
> +++ b/drivers/staging/hikey9xx/gpu/Kconfig
> @@ -0,0 +1,10 @@
> +config DRM_HISI_KIRIN9XX
> +	tristate "DRM Support for Hisilicon Kirin9xx series SoCs Platform"
> +	depends on DRM && OF && ARM64
> +	select DRM_KMS_HELPER
> +	select DRM_GEM_CMA_HELPER
> +	select DRM_KMS_CMA_HELPER
> +	select DRM_MIPI_DSI
> +	help
> +	  Choose this option if you have a HiSilicon Kirin960 or Kirin970.
> +	  If M is selected the module will be called kirin9xx-drm.
> diff --git a/drivers/staging/hikey9xx/gpu/Makefile b/drivers/staging/hikey9xx/gpu/Makefile
> new file mode 100644
> index 000000000000..5f7974a95367
> --- /dev/null
> +++ b/drivers/staging/hikey9xx/gpu/Makefile
> @@ -0,0 +1,8 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +kirin9xx-drm-y := kirin9xx_drm_drv.o \
> +		  kirin9xx_drm_dss.o \
> +		  kirin9xx_drm_dpe_utils.o \
> +		  kirin970_defs.o kirin960_defs.o \
> +		  kirin9xx_drm_overlay_utils.o
> +
> +obj-$(CONFIG_DRM_HISI_KIRIN9XX) += kirin9xx-drm.o kirin9xx_dw_drm_dsi.o

General comment which is true for many many Makefile's
I have never understood the love of '\'.
Something like this works equally well:

kirin9xx-drm-y := kirin9xx_drm_drv.o kirin9xx_drm_dss.o
kirin9xx-drm-y += kirin9xx_drm_dpe_utils.o kirin970_defs.o
kirin9xx-drm-y += kirin960_defs.o kirin9xx_drm_overlay_utils.o

obj-$(CONFIG_DRM_HISI_KIRIN9XX) += kirin9xx-drm.o kirin9xx_dw_drm_dsi.o


> diff --git a/drivers/staging/hikey9xx/gpu/kirin960_defs.c b/drivers/staging/hikey9xx/gpu/kirin960_defs.c
> new file mode 100644
> index 000000000000..c5e1ec03c818
> --- /dev/null
> +++ b/drivers/staging/hikey9xx/gpu/kirin960_defs.c
> @@ -0,0 +1,346 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2008-2011, Hisilicon Tech. Co., Ltd. All rights reserved.
> + * Copyright (c) 2008-2020, Huawei Technologies Co., Ltd
> + */
> +
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_drv.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_fourcc.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_plane_helper.h>
> +
> +#include "kirin9xx_drm_dpe_utils.h"
> +#include "kirin9xx_drm_drv.h"
> +#include "kirin960_dpe_reg.h"
All includes blocks should be sorted.

The list of include files looks far too large for this simple file.
Reduce to the relevant include files.

> +
> +static const u32 kirin960_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,
> +	}, {
...
> +	},
> +};
> +
> +static const u32 kirin960_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,
> +	}
> +};
> +
> +/* SCF_LUT_CHN coef_idx */
> +static const int kirin960_g_scf_lut_chn_coef_idx[DSS_CHN_MAX_DEFINE] = {
> +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
> +};
> +
> +static const u32 kirin960_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 */
> +static const u32 kirin960_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]) */
> +static const u32 kirin960_g_dss_smmu_smrx_idx[DSS_CHN_MAX_DEFINE] = {
> +	0, 4, 5, 9, 13, 17, 21, 22, 26, 29, 23, 32
> +};
> +
> +static const u32 kirin960_g_dss_mif_sid_map[DSS_CHN_MAX] = {
> +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0
> +};
> +
> +void kirin960_dpe_defs(struct dss_hw_ctx *ctx)
> +{
> +	memcpy(&ctx->g_dss_module_base, &kirin960_g_dss_module_base,
> +	       sizeof(kirin960_g_dss_module_base));
> +	memcpy(&ctx->g_dss_module_ovl_base, &kirin960_g_dss_module_ovl_base,
> +	       sizeof(kirin960_g_dss_module_ovl_base));
> +	memcpy(&ctx->g_scf_lut_chn_coef_idx, &kirin960_g_scf_lut_chn_coef_idx,
> +	       sizeof(kirin960_g_scf_lut_chn_coef_idx));
> +	memcpy(&ctx->g_dss_module_cap, &kirin960_g_dss_module_cap,
> +	       sizeof(kirin960_g_dss_module_cap));
> +	memcpy(&ctx->g_dss_chn_sid_num, &kirin960_g_dss_chn_sid_num,
> +	       sizeof(kirin960_g_dss_chn_sid_num));
> +	memcpy(&ctx->g_dss_smmu_smrx_idx, &kirin960_g_dss_smmu_smrx_idx,
> +	       sizeof(kirin960_g_dss_smmu_smrx_idx));
> +
> +	ctx->smmu_offset = DSS_SMMU_OFFSET;
> +	ctx->afbc_header_addr_align = AFBC_HEADER_ADDR_ALIGN;
> +	ctx->dss_mmbuf_clk_rate_power_off = DEFAULT_DSS_MMBUF_CLK_RATE_POWER_OFF;
> +	ctx->rot_mem_ctrl = ROT_MEM_CTRL;
> +	ctx->dither_mem_ctrl = DITHER_MEM_CTRL;
> +	ctx->arsr2p_lb_mem_ctrl = ARSR2P_LB_MEM_CTRL;
> +	ctx->pxl0_clk_rate_power_off = DEFAULT_DSS_PXL0_CLK_RATE_POWER_OFF;
> +}
> diff --git a/drivers/staging/hikey9xx/gpu/kirin960_dpe_reg.h b/drivers/staging/hikey9xx/gpu/kirin960_dpe_reg.h
> new file mode 100644
> index 000000000000..3405fb9076c1
> --- /dev/null
> +++ b/drivers/staging/hikey9xx/gpu/kirin960_dpe_reg.h
> @@ -0,0 +1,229 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2016 Linaro Limited.
> + * Copyright (c) 2014-2016 Hisilicon Limited.
> + * Copyright (c) 2014-2020, Huawei Technologies Co., Ltd
> + */
> +
> +#ifndef __KIRIN960_DPE_REG_H__
> +#define __KIRIN960_DPE_REG_H__
> +
> +#include "kirin9xx_dpe.h"
It looks strange that a register definition header file needs a higher
level header file.
If the include file is needed there is likely some layering that needs to be fixed?

> +
> +#define CRGPERI_PLL0_CLK_RATE	(1600000000UL)
> +#define CRGPERI_PLL2_CLK_RATE	(960000000UL)
> +#define CRGPERI_PLL3_CLK_RATE	(1600000000UL)
> +
> +/* dss clk power off  */
> +#define DEFAULT_DSS_PXL0_CLK_RATE_POWER_OFF	(277000000UL)
> +#define DEFAULT_DSS_MMBUF_CLK_RATE_POWER_OFF	(238000000UL)
> +
> +/*****************************************************************************/
> +
> +#define SCPWREN	(0x0D0)
> +#define SCPEREN1 (0x040)
> +#define SCPERDIS1  (0x044)
> +#define SCPERRSTDIS1	(0x090)
> +#define SCISODIS	(0x0C4)
> +
> +/*****************************************************************************/
Why the above block of stars - looks random.


> +
> +/* MODULE BASE ADDRESS */
> +
> +#define DSS_SMMU_OFFSET	(0x8000)
> +
> +#define DSS_RCH_VG0_POST_CLIP_OFFSET	(0x203A0)
> +
> +#define DSS_RCH_VG1_POST_CLIP_OFFSET	(0x283A0)
> +
> +#define DSS_RCH_VG2_POST_CLIP_OFFSET	(0x303A0)
> +#define DSS_RCH_VG2_AFBCD_OFFSET	(0x30900)
> +
> +#define DSS_RCH_G0_POST_CLIP_OFFSET (0x383A0)
> +
> +#define DSS_RCH_G1_POST_CLIP_OFFSET (0x403A0)
> +
> +#define DSS_RCH_D2_AFBCD_OFFSET	(0x50900)
> +
> +#define DSS_RCH_D3_AFBCD_OFFSET	(0x51900)
> +
> +#define DSS_RCH_D1_AFBCD_OFFSET	(0x53900)
> +
> +#define DSS_WCH0_ROT_OFFSET	(0x5A500)
> +
> +#define DSS_WCH1_ROT_OFFSET	(0x5C500)
> +
> +#define DSS_DPP_DEGAMA_OFFSET	(0x70500)
> +#define DSS_DPP_LCP_OFFSET	(0x70900)
> +#define DSS_DPP_ARSR1P_OFFSET	(0x70A00)
> +#define DSS_DPP_BITEXT0_OFFSET	(0x70B00)
> +#define DSS_DPP_LCP_LUT_OFFSET	(0x73000)
> +#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
> +
> +/* AIF */
> +#define AIF0_CH0_ADD_OFFSET	(DSS_VBIF0_AIF + 0x04)
> +#define AIF0_CH1_ADD_OFFSET	(DSS_VBIF0_AIF + 0x24)
> +#define AIF0_CH2_ADD_OFFSET	(DSS_VBIF0_AIF + 0x44)
> +#define AIF0_CH3_ADD_OFFSET	(DSS_VBIF0_AIF + 0x64)
> +#define AIF0_CH4_ADD_OFFSET	(DSS_VBIF0_AIF + 0x84)
> +#define AIF0_CH5_ADD_OFFSET	(DSS_VBIF0_AIF + 0xa4)
> +#define AIF0_CH6_ADD_OFFSET	(DSS_VBIF0_AIF + 0xc4)
> +#define AIF0_CH7_ADD_OFFSET	(DSS_VBIF0_AIF + 0xe4)
> +#define AIF0_CH8_ADD_OFFSET	(DSS_VBIF0_AIF + 0x104)
> +#define AIF0_CH9_ADD_OFFSET	(DSS_VBIF0_AIF + 0x124)
> +#define AIF0_CH10_ADD_OFFSET	(DSS_VBIF0_AIF + 0x144)
> +#define AIF0_CH11_ADD_OFFSET	(DSS_VBIF0_AIF + 0x164)
> +#define AIF0_CH12_ADD_OFFSET	(DSS_VBIF0_AIF + 0x184)
> +
> +#define AIF1_CH0_ADD_OFFSET	(DSS_VBIF1_AIF + 0x04)
> +#define AIF1_CH1_ADD_OFFSET	(DSS_VBIF1_AIF + 0x24)
> +#define AIF1_CH2_ADD_OFFSET	(DSS_VBIF1_AIF + 0x44)
> +#define AIF1_CH3_ADD_OFFSET	(DSS_VBIF1_AIF + 0x64)
> +#define AIF1_CH4_ADD_OFFSET	(DSS_VBIF1_AIF + 0x84)
> +#define AIF1_CH5_ADD_OFFSET	(DSS_VBIF1_AIF + 0xa4)
> +#define AIF1_CH6_ADD_OFFSET	(DSS_VBIF1_AIF + 0xc4)
> +#define AIF1_CH7_ADD_OFFSET	(DSS_VBIF1_AIF + 0xe4)
> +#define AIF1_CH8_ADD_OFFSET	(DSS_VBIF1_AIF + 0x104)
> +#define AIF1_CH9_ADD_OFFSET	(DSS_VBIF1_AIF + 0x124)
> +#define AIF1_CH10_ADD_OFFSET	(DSS_VBIF1_AIF + 0x144)
> +#define AIF1_CH11_ADD_OFFSET	(DSS_VBIF1_AIF + 0x164)
> +#define AIF1_CH12_ADD_OFFSET	(DSS_VBIF1_AIF + 0x184)
> +
> +/* DFC */
> +#define DFC_GLB_ALPHA	(0x0008)
> +
> +/* ARSR2P v0 */
> +#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)
> +
> +/* POST_CLIP  v g */
> +#define POST_CLIP_CTL_HRZ	(0x0010)
> +#define POST_CLIP_CTL_VRZ	(0x0014)
> +#define POST_CLIP_EN	(0x0018)
> +
> +/* CSC */
> +
> +#define CSC_ICG_MODULE	(0x0024)
> +
> +/* DMA BUF */
> +
> +#define AFBCE_HREG_HDR_PTR_LO	(0x908)
> +#define AFBCE_HREG_PLD_PTR_LO	(0x90C)
> +
> +#define ROT_MEM_CTRL		(0x538)
> +#define ROT_SIZE	(0x53C)
> +
> +/* DMA aligned limited:  128bits aligned */
> +
> +#define AFBC_HEADER_ADDR_ALIGN	(64)
> +#define AFBC_HEADER_STRIDE_ALIGN	(64)
> +
> +/* DPP */
> +
> +#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 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)
> +
> +#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 LCP_U_GMP_COEF	(0x0000)
> +
> +#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)
> +
> +#endif
> diff --git a/drivers/staging/hikey9xx/gpu/kirin970_defs.c b/drivers/staging/hikey9xx/gpu/kirin970_defs.c
> new file mode 100644
> index 000000000000..d72d4d5712eb
> --- /dev/null
> +++ b/drivers/staging/hikey9xx/gpu/kirin970_defs.c
> @@ -0,0 +1,373 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2008-2011, Hisilicon Tech. Co., Ltd. All rights reserved.
> + * Copyright (c) 2008-2020, Huawei Technologies Co., Ltd
> + */
> +
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_drv.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_fourcc.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_plane_helper.h>
> +
> +#include "kirin9xx_drm_dpe_utils.h"
> +#include "kirin9xx_drm_drv.h"
> +#include "kirin970_dpe_reg.h"
Same as before. Sort and reduce to the necessary includes.

> +
> +static const u32 kirin970_g_dss_module_base[DSS_CHN_MAX_DEFINE][MODULE_CHN_MAX] = {
> +	/* D0 */
> +	{
> +	MIF_CH0_OFFSET,   /* MODULE_MIF_CHN */
> +	AIF0_CH0_OFFSET,  /* MODULE_AIF0_CHN */
> +	AIF1_CH0_OFFSET,  /* MODULE_AIF1_CHN */
> +	MCTL_CTL_MUTEX_RCH0,  /* MODULE_MCTL_CHN_MUTEX */
> +	DSS_MCTRL_SYS_OFFSET + MCTL_RCH0_FLUSH_EN,  /* MODULE_MCTL_CHN_FLUSH_EN */
> +	DSS_MCTRL_SYS_OFFSET + MCTL_RCH0_OV_OEN,  /* MODULE_MCTL_CHN_OV_OEN */
> +	DSS_MCTRL_SYS_OFFSET + MCTL_RCH0_STARTY,  /* MODULE_MCTL_CHN_STARTY */
> +	DSS_MCTRL_SYS_OFFSET + MCTL_MOD0_DBG,  /* MODULE_MCTL_CHN_MOD_DBG */
> +	DSS_RCH_D0_DMA_OFFSET,  /* MODULE_DMA */
> +	DSS_RCH_D0_DFC_OFFSET,  /* MODULE_DFC */
> +	0,  /* MODULE_SCL */
> +	0,  /* MODULE_SCL_LUT */
> +	0,  /* MODULE_ARSR2P */
> +	0,  /* MODULE_ARSR2P_LUT */
> +	0, /* MODULE_POST_CLIP_ES */
> +	0,  /* MODULE_POST_CLIP */
> +	0,  /* MODULE_PCSC */
> +	DSS_RCH_D0_CSC_OFFSET,  /* MODULE_CSC */
> +	},
...
> +	},
> +};
> +
> +static const u32 kirin970_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},
> +};
> +
> +/* SCF_LUT_CHN coef_idx */
> +static const int kirin970_g_scf_lut_chn_coef_idx[DSS_CHN_MAX_DEFINE] = {
> +	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
> +};
> +
> +static const u32 kirin970_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 */
> +static const u32 kirin970_g_dss_chn_sid_num[DSS_CHN_MAX_DEFINE] = {
> +	4, 1, 4, 4, 4, 4, 1, 1, 3, 4, 3, 3
> +};
> +
> +/* start idx of each channel */
> +/* smrx_idx = g_dss_smmu_smrx_idx[chn_idx] + (0 ~ g_dss_chn_sid_num[chn_idx]) */
> +static const u32 kirin970_g_dss_smmu_smrx_idx[DSS_CHN_MAX_DEFINE] = {
> +	0, 4, 5, 9, 13, 17, 21, 22, 26, 29, 23, 36
> +};
> +
> +void kirin970_dpe_defs(struct dss_hw_ctx *ctx)
> +{
> +	memcpy(&ctx->g_dss_module_base, &kirin970_g_dss_module_base,
> +	       sizeof(kirin970_g_dss_module_base));
> +	memcpy(&ctx->g_dss_module_ovl_base, &kirin970_g_dss_module_ovl_base,
> +	       sizeof(kirin970_g_dss_module_ovl_base));
> +	memcpy(&ctx->g_scf_lut_chn_coef_idx, &kirin970_g_scf_lut_chn_coef_idx,
> +	       sizeof(kirin970_g_scf_lut_chn_coef_idx));
> +	memcpy(&ctx->g_dss_module_cap, &kirin970_g_dss_module_cap,
> +	       sizeof(kirin970_g_dss_module_cap));
> +	memcpy(&ctx->g_dss_chn_sid_num, &kirin970_g_dss_chn_sid_num,
> +	       sizeof(kirin970_g_dss_chn_sid_num));
> +	memcpy(&ctx->g_dss_smmu_smrx_idx, &kirin970_g_dss_smmu_smrx_idx,
> +	       sizeof(kirin970_g_dss_smmu_smrx_idx));
> +
> +	ctx->smmu_offset = DSS_SMMU_OFFSET;
> +	ctx->afbc_header_addr_align = AFBC_HEADER_ADDR_ALIGN;
> +	ctx->dss_mmbuf_clk_rate_power_off = DEFAULT_DSS_MMBUF_CLK_RATE_POWER_OFF;
> +	ctx->rot_mem_ctrl = ROT_MEM_CTRL;
> +	ctx->dither_mem_ctrl = DITHER_MEM_CTRL;
> +	ctx->arsr2p_lb_mem_ctrl = ARSR2P_LB_MEM_CTRL;
> +	ctx->pxl0_clk_rate_power_off = DEFAULT_DSS_PXL0_CLK_RATE_POWER_OFF;
> +}
> diff --git a/drivers/staging/hikey9xx/gpu/kirin970_dpe_reg.h b/drivers/staging/hikey9xx/gpu/kirin970_dpe_reg.h
> new file mode 100644
> index 000000000000..6cd1d6f5e8d0
> --- /dev/null
> +++ b/drivers/staging/hikey9xx/gpu/kirin970_dpe_reg.h
> @@ -0,0 +1,1183 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2016 Linaro Limited.
> + * Copyright (c) 2014-2016 Hisilicon Limited.
> + * Copyright (c) 2014-2020, Huawei Technologies Co., Ltd
> + */
> +
> +#ifndef __KIRIN970_DPE_REG_H__
> +#define __KIRIN970_DPE_REG_H__
> +
> +#include "kirin9xx_dpe.h"
Same coment as before, looks like a layering issue if this header file
is needed.

> +
> +#define CRGPERI_PLL0_CLK_RATE	(1660000000UL)
> +#define CRGPERI_PLL2_CLK_RATE	(1920000000UL)
> +#define CRGPERI_PLL3_CLK_RATE	(1200000000UL)
> +#define CRGPERI_PLL7_CLK_RATE	(1782000000UL)
> +
> +/* core_clk: 0.65v-300M, 0.75-415M, 0.8-553.33M */
> +#define DEFAULT_DSS_CORE_CLK_RATE_L3	(554000000UL)
> +#define DEFAULT_DSS_CORE_CLK_RATE_L2	(415000000UL)
> +
> +#define DEFAULT_DSS_CORE_CLK_RATE_ES	(400000000UL)
> +
> +/* pix0_clk: 0.65v-300M, 0.75-415M, 0.8-645M */
> +#define DEFAULT_DSS_PXL0_CLK_RATE_L3	(645000000UL)
> +#define DEFAULT_DSS_PXL0_CLK_RATE_L2	(415000000UL)
> +#define DEFAULT_DSS_PXL0_CLK_RATE_L1	(300000000UL)
> +
> +/* mmbuf_clk: 0.65v-237.14M, 0.75-332M, 0.8-480M */
> +#define DEFAULT_DSS_MMBUF_CLK_RATE_L3	(480000000UL)
> +#define DEFAULT_DSS_MMBUF_CLK_RATE_L2	(332000000UL)
> +
> +/* pix1_clk: 0.65v-254.57M, 0.75-415M, 0.8-594M */
> +#define DEFAULT_DSS_PXL1_CLK_RATE_L3	(594000000UL)
> +#define DEFAULT_DSS_PXL1_CLK_RATE_L2	(415000000UL)
> +#define DEFAULT_DSS_PXL1_CLK_RATE_L1	(255000000UL)
> +
> +/* mdc_dvfs_clk: 0.65v-240M, 0.75-332M, 0.8-553.33M */
> +#define DEFAULT_MDC_CORE_CLK_RATE_L3	(554000000UL)
> +#define DEFAULT_MDC_CORE_CLK_RATE_L2	(332000000UL)
> +#define DEFAULT_MDC_CORE_CLK_RATE_L1	(240000000UL)
> +
> +/* dss clk power off  */
> +#define DEFAULT_DSS_PXL0_CLK_RATE_POWER_OFF	(238000000UL)
> +#define DEFAULT_DSS_MMBUF_CLK_RATE_POWER_OFF	(208000000UL)
> +
> +/*****************************************************************************/
> +
> +#define PEREN4	(0x040)
> +#define PERDIS4	(0x044)
> +#define PERRSTEN0	(0x060)
> +#define PERRSTDIS5	(0x0A0)
> +#define PEREN6	(0x410)
> +#define PERDIS6	(0x414)
> +
> +/* SYSCTRL */
> +#define SCISODIS	(0x044)
> +#define SCPWREN	(0x060)
> +#define SCPEREN1	(0x170)
> +#define SCPERDIS1	(0x174)
> +#define SCPEREN4	(0x1B0)
> +#define SCPERDIS4	(0x1B4)
> +#define SCPERRSTDIS1	(0x210)
> +
> +/* PCTRL */
> +#define PERI_CTRL33	(0x088)
> +
> +/*****************************************************************************/
> +
> +/* MODULE BASE ADDRESS */
> +
> +/* SMMU */
> +#define DSS_SMMU_OFFSET	(0x80000)
> +
> +/* RCH_V */
> +#define DSS_RCH_VG0_POST_CLIP_OFFSET_ES	(0x203A0)
> +#define DSS_RCH_VG0_POST_CLIP_OFFSET	(0x20480)
> +
> +#define DSS_RCH_VG1_POST_CLIP_OFFSET_ES	(0x283A0)
> +#define DSS_RCH_VG1_POST_CLIP_OFFSET	(0x28480)
> +
> +#define DSS_RCH_VG2_POST_CLIP_OFFSET_ES	(0x303A0)
> +#define DSS_RCH_VG2_POST_CLIP_OFFSET	(0x30480)
> +#define DSS_RCH_VG2_SCL_LUT_OFFSET		(0x31000)   /* ES */
> +
> +/* RCH_G */
> +#define DSS_RCH_G0_POST_CLIP_OFFSET_ES		(0x383A0)
> +#define DSS_RCH_G0_POST_CLIP_OFFSET		(0x38480)
> +
> +#define DSS_RCH_G1_POST_CLIP_OFFSET_ES	(0x403A0)
> +#define DSS_RCH_G1_POST_CLIP_OFFSET		(0x40480)
> +
> +/* RCH_D */
> +
> +/* WCH */
> +#define DSS_WCH0_BITEXT_OFFSET		(0x5A140)
> +#define DSS_WCH0_DITHER_OFFSET            (0x5A1D0)
> +#define DSS_WCH0_PCSC_OFFSET			(0x5A400)
> +#define DSS_WCH0_ROT_OFFSET			(0x5A530)
> +#define DSS_WCH0_FBCE_CREG_CTRL_GATE (0x5A964)
> +
> +#define DSS_WCH1_BITEXT_OFFSET		(0x5C140)
> +#define DSS_WCH1_DITHER_OFFSET            (0x5C1D0)
> +#define DSS_WCH1_SCL_OFFSET			(0x5C200)
> +#define DSS_WCH1_PCSC_OFFSET			(0x5C400)
> +#define DSS_WCH1_ROT_OFFSET			(0x5C530)
> +#define DSS_WCH1_FBCE_CREG_CTRL_GATE	(0x5C964)
> +
> +/* DPP */
> +#define DSS_DPP_CLIP_OFFSET	(0x70180)
> +#define DSS_DPP_XCC_OFFSET	(0x70900)
> +#define DSS_DPP_DEGAMMA_OFFSET	(0x70950)
> +#define DSS_DPP_GMP_OFFSET	(0x709A0)
> +#define DSS_DPP_ARSR_POST_OFFSET	(0x70A00)
> +#define DSS_DPP_GMP_LUT_OFFSET	(0x73000)
> +#define DSS_DPP_GAMA_PRE_LUT_OFFSET	(0x75000)
> +#define DSS_DPP_DEGAMMA_LUT_OFFSET	(0x78000)
> +#define DSS_DPP_ARSR_POST_LUT_OFFSET	(0x7B000)
> +
> +/* for boston es */
> +#define DSS_DPP_LCP_OFFSET_ES	(0x70900)
> +#define DSS_DPP_LCP_LUT_OFFSET_ES	(0x73000)
> +
> +/* POST SCF */
> +#define DSS_POST_SCF_OFFSET	DSS_DPP_ARSR_POST_OFFSET
> +#define DSS_POST_SCF_LUT_OFFSET	DSS_DPP_ARSR_POST_LUT_OFFSET
> +/* POST SCF for ES */
> +#define DSS_POST_SCF_LUT_OFFSET_ES	(0x7B000)
> +
> +/* AIF */
> +
> +/* (0x0004+0x20*n) */
> +#define AIF_CH_HS	(0x0004)
> +/* (0x0008+0x20*n) */
> +#define AIF_CH_LS	(0x0008)
> +
> +/* SMMU */
> +
> +#define SMMU_SMRx_P	(0x10000)
> +#define SMMU_RLD_EN0_P	(0x101F0)
> +#define SMMU_RLD_EN1_P	(0x101F4)
> +#define SMMU_RLD_EN2_P	(0x101F8)
> +#define SMMU_INTMAS_P	(0x10200)
> +#define SMMU_INTRAW_P	(0x10204)
> +#define SMMU_INTSTAT_P	(0x10208)
> +#define SMMU_INTCLR_P	(0x1020C)
> +#define SMMU_SCR_P		(0x10210)
> +#define SMMU_PCB_SCTRL	(0x10214)
> +#define SMMU_PCB_TTBR	(0x10218)
> +#define SMMU_PCB_TTBCR	(0x1021C)
> +#define SMMU_OFFSET_ADDR_P	(0x10220)
> +
> +/* DFC */
> +#define DFC_GLB_ALPHA01		(0x0008)
> +#define DFC_GLB_ALPHA23		(0x0028)
> +#define DFC_BITEXT_CTL		(0x0040)
> +#define DFC_DITHER_CTL1      (0x00D0)
> +
> +/* SCF */
> +
> +/* MACROS */
> +#define SCF_MIN_INPUT	(16) /* SCF min input pix 16x16 */
> +#define SCF_MIN_OUTPUT	(16) /* SCF min output pix 16x16 */
> +
> +#define SCF_INC_FACTOR	BIT(18) /* (262144) */
> +
> +/* ARSR2P ES  v0 */
> +#define ARSR2P_INPUT_WIDTH_HEIGHT_ES	(0x000)
> +#define ARSR2P_OUTPUT_WIDTH_HEIGHT_ES	(0x004)
> +#define ARSR2P_IHLEFT_ES	(0x008)
> +#define ARSR2P_IHRIGHT_ES	(0x00C)
> +#define ARSR2P_IVTOP_ES		(0x010)
> +#define ARSR2P_IVBOTTOM_ES	(0x014)
> +#define ARSR2P_IHINC_ES		(0x018)
> +#define ARSR2P_IVINC_ES		(0x01C)
> +#define ARSR2P_UV_OFFSET_ES	(0x020)
> +#define ARSR2P_MODE_ES		(0x024)
> +#define ARSR2P_SKIN_THRES_Y_ES	(0x028)
> +#define ARSR2P_SKIN_THRES_U_ES	(0x02C)
> +#define ARSR2P_SKIN_THRES_V_ES	(0x030)
> +#define ARSR2P_SKIN_CFG0_ES	(0x034)
> +#define ARSR2P_SKIN_CFG1_ES	(0x038)
> +#define ARSR2P_SKIN_CFG2_ES	(0x03C)
> +#define ARSR2P_SHOOT_CFG1_ES	(0x040)
> +#define ARSR2P_SHOOT_CFG2_ES	(0x044)
> +#define ARSR2P_SHARP_CFG1_ES	(0x048)
> +#define ARSR2P_SHARP_CFG2_ES	(0x04C)
> +#define ARSR2P_SHARP_CFG3_ES	(0x050)
> +#define ARSR2P_SHARP_CFG4_ES	(0x054)
> +#define ARSR2P_SHARP_CFG5_ES	(0x058)
> +#define ARSR2P_SHARP_CFG6_ES	(0x05C)
> +#define ARSR2P_SHARP_CFG7_ES	(0x060)
> +#define ARSR2P_SHARP_CFG8_ES	(0x064)
> +#define ARSR2P_SHARP_CFG9_ES	(0x068)
> +#define ARSR2P_TEXTURW_ANALYSTS_ES	(0x06C)
> +#define ARSR2P_INTPLSHOOTCTRL_ES	(0x070)
> +#define ARSR2P_DEBUG0_ES	(0x074)
> +#define ARSR2P_DEBUG1_ES	(0x078)
> +#define ARSR2P_DEBUG2_ES	(0x07C)
> +#define ARSR2P_DEBUG3_ES	(0x080)
> +#define ARSR2P_LB_MEM_CTRL_ES	(0x084)
> +#define ARSR2P_IHLEFT1_ES	(0x088)
> +#define ARSR2P_IHRIGHT1_ES	(0x090)
> +#define ARSR2P_IVBOTTOM1_ES	(0x094)
> +
> +#define ARSR2P_LUT_COEFY_V_OFFSET_ES	(0x0000)
> +#define ARSR2P_LUT_COEFY_H_OFFSET_ES	(0x0100)
> +#define ARSR2P_LUT_COEFA_V_OFFSET_ES	(0x0300)
> +#define ARSR2P_LUT_COEFA_H_OFFSET_ES	(0x0400)
> +#define ARSR2P_LUT_COEFUV_V_OFFSET_ES	(0x0600)
> +#define ARSR2P_LUT_COEFUV_H_OFFSET_ES	(0x0700)
> +
> +/* ARSR2P  v0 */
> +#define ARSR2P_IHLEFT1 (0x00C)
> +#define ARSR2P_IHRIGHT (0x010)
> +#define ARSR2P_IHRIGHT1 (0x014)
> +#define ARSR2P_IVTOP (0x018)
> +#define ARSR2P_IVBOTTOM (0x01C)
> +#define ARSR2P_IVBOTTOM1 (0x020)
> +#define ARSR2P_IHINC (0x024)
> +#define ARSR2P_IVINC (0x028)
> +#define ARSR2P_OFFSET (0x02C)
> +#define ARSR2P_MODE (0x030)
> +#define ARSR2P_SKIN_THRES_Y (0x034)
> +#define ARSR2P_SKIN_THRES_U (0x038)
> +#define ARSR2P_SKIN_THRES_V (0x03C)
> +#define ARSR2P_SKIN_CFG0 (0x040)
> +#define ARSR2P_SKIN_CFG1 (0x044)
> +#define ARSR2P_SKIN_CFG2 (0x048)
> +#define ARSR2P_SHOOT_CFG1 (0x04C)
> +#define ARSR2P_SHOOT_CFG2 (0x050)
> +#define ARSR2P_SHOOT_CFG3 (0x054)
> +#define ARSR2P_SHARP_CFG1 (0x080)
> +#define ARSR2P_SHARP_CFG2 (0x084)
> +#define ARSR2P_SHARP_CFG3 (0x088)
> +#define ARSR2P_SHARP_CFG4 (0x08C)
> +#define ARSR2P_SHARP_CFG5 (0x090)
> +#define ARSR2P_SHARP_CFG6 (0x094)
> +#define ARSR2P_SHARP_CFG7 (0x098)
> +#define ARSR2P_SHARP_CFG8 (0x09C)
> +#define ARSR2P_SHARP_CFG9 (0x0A0)
> +#define ARSR2P_SHARP_CFG10 (0x0A4)
> +#define ARSR2P_SHARP_CFG11 (0x0A8)
> +#define ARSR2P_SHARP_CFG12 (0x0AC)
> +#define ARSR2P_TEXTURW_ANALYSTS (0x0D0)
> +#define ARSR2P_INTPLSHOOTCTRL (0x0D4)
> +#define ARSR2P_DEBUG0 (0x0D8)
> +#define ARSR2P_DEBUG1 (0x0DC)
> +#define ARSR2P_DEBUG2 (0x0E0)
> +#define ARSR2P_DEBUG3 (0x0E4)
> +#define ARSR2P_LB_MEM_CTRL (0x0E8)
> +
> +/* POST_CLIP  v g */
> +#define POST_CLIP_CTL_HRZ			(0x0004)
> +#define POST_CLIP_CTL_VRZ			(0x0008)
> +#define POST_CLIP_EN				(0x000C)
> +
> +#define POST_CLIP_DISP_SIZE_ES		(0x0000)
> +#define POST_CLIP_CTL_HRZ_ES		(0x0010)
> +#define POST_CLIP_CTL_VRZ_ES		(0x0014)
> +#define POST_CLIP_EN_ES			(0x0018)
> +
> +/* CSC */
> +#define CSC_ICG_MODULE_ES	(0x0024)
> +#define CSC_P00				(0x0010)
> +#define CSC_P01				(0x0014)
> +#define CSC_P02				(0x0018)
> +#define CSC_P10				(0x001C)
> +#define CSC_P11				(0x0020)
> +#define CSC_P12				(0x0024)
> +#define CSC_P20				(0x0028)
> +#define CSC_P21				(0x002C)
> +#define CSC_P22				(0x0030)
> +#define CSC_ICG_MODULE		(0x0034)
> +
> +/* AFBCE */
> +#define AFBCE_HREG_HDR_PTR_L0		(0x908)
> +#define AFBCE_HREG_PLD_PTR_L0		(0x90C)
> +
> +/* ROT */
> +#define ROT_MEM_CTRL_ES		(0x538)
> +#define ROT_SIZE_ES			(0x53C)
> +
> +#define ROT_MEM_CTRL			(0x588)
> +#define ROT_SIZE				(0x58C)
> +#define ROT_422_MODE			(0x590)
> +
> +/* REG_DEFAULT */
> +
> +/* MACROS */
> +
> +/* DMA aligned limited:  128bits aligned */
> +
> +/* 16Bytes */
> +/* 32BPP:1024, 16BPP 512 */
> +
> +#define AFBC_HEADER_ADDR_ALIGN	(16)
> +#define AFBC_HEADER_STRIDE_ALIGN	(16)
> +
> +/* 16Pixels */
> +
> +#define MMBUF_BASE	(0x40) /* (0xea800000) */
> +#define MMBUF_BLOCK0_LINE_NUM	(8)
> +#define MMBUF_BLOCK0_ROT_LINE_NUM	(64)
> +#define MMBUF_BLOCK1_LINE_NUM	(16)
> +
> +#define HFBC_PIC_WIDTH_MIN	(64)
> +#define HFBC_PIC_WIDTH_ROT_MIN	(16)
> +#define HFBC_PIC_WIDTH_MAX	(512)
> +#define HFBC_PIC_WIDTH_ROT_MAX  (4096)
> +#define HFBC_PIC_HEIGHT_MIN	(8)
> +#define HFBC_PIC_HEIGHT_ROT_MIN	(32)
> +#define HFBC_PIC_HEIGHT_MAX	(8196)
> +#define HFBC_PIC_HEIGHT_ROT_MAX	(2160)
> +#define HFBC_BLOCK0_WIDTH_ALIGN	(64)
> +#define HFBC_BLOCK0_HEIGHT_ALIGN     (8)
> +#define HFBC_BLOCK1_WIDTH_ALIGN	 (32)
> +#define HFBC_BLOCK1_HEIGHT_ALIGN   (16)
> +#define HFBC_HEADER_ADDR_ALIGN	  (4)
> +#define HFBC_HEADER_STRIDE_ALIGN	  (32)
> +#define HFBC_HEADER_STRIDE_BLOCK	  (4)
> +#define HFBC_PAYLOAD0_ALIGN_8BIT       (512)
> +#define HFBC_PAYLOAD1_ALIGN_8BIT       (256)
> +#define HFBC_PAYLOAD_ALIGN_10BIT	(1024)
> +
> +#define HFBCD_BLOCK0_CROP_MAX	(7)
> +#define HFBCD_BLOCK0_ROT_CROP_MAX	(63)
> +#define HFBCD_BLOCK1_CROP_MAX	(15)
> +
> +/* MCTL  SYS */
> +/* SECU */
> +#define MCTL_RCH0_SECU_GATE		(0x0080)
> +#define MCTL_RCH1_SECU_GATE		(0x0084)
> +#define MCTL_RCH2_SECU_GATE		(0x0088)
> +#define MCTL_RCH3_SECU_GATE		(0x008C)
> +#define MCTL_RCH4_SECU_GATE		(0x0090)
> +#define MCTL_RCH5_SECU_GATE		(0x0094)
> +#define MCTL_RCH6_SECU_GATE		(0x0098)
> +#define MCTL_RCH7_SECU_GATE		(0x009C)
> +#define MCTL_RCH8_SECU_GATE		(0x00A0)
> +#define MCTL_OV2_SECU_GATE		(0x00B0)
> +#define MCTL_OV3_SECU_GATE		(0x00B4)
> +#define MCTL_DSI0_SECU_CFG			(0x00C0)
> +#define MCTL_DSI1_SECU_CFG			(0x00C4)
> +#define MCTL_DP_SECU_GATE			(0x00C8)
> +#define MCTL_DSI_MUX_SECU_GATE	(0x00CC)
> +/* FLUSH EN */
> +/* SW FOR RCH */
> +#define MCTL_RCH8_OV_OEN	(0x015C)
> +/* SW FOR OV */
> +#define MCTL_RCH_OV0_SEL1  (0x0190)
> +#define MCTL_RCH_OV1_SEL1  (0x0194)
> +#define MCTL_RCH_OV2_SEL1  (0x0198)
> +/* SW FOR WCH */
> +/* SW FOR OV2/3 OUTPUT */
> +/* SW */
> +/* RCH STARTY */
> +#define MCTL_RCH8_STARTY	(0x01E0)
> +/* LP */
> +
> +/* RCH */
> +#define MCTL_MOD_DBG_ADD_CH_NUM (2)  /* copybit */
> +
> +/* SBL */
> +/* SBL FOR ES */
> +#define SBL_REG_FRMT_MODE_ES                          (0x0000)
> +#define SBL_REG_FRMT_DBUF_CTRL_ES                     (0x0008)
> +#define SBL_REG_FRMT_FRAME_WIDTH_7_TO_0_ES            (0x0010)
> +#define SBL_REG_FRMT_FRAME_WIDTH_15_TO_8_ES           (0x0014)
> +#define SBL_REG_FRMT_FRAME_HEIGHT_7_TO_0_ES           (0x0018)
> +#define SBL_REG_FRMT_FRAME_HEIGHT_15_TO_8_ES          (0x001c)
> +#define SBL_REG_FRMT_ROI_HOR_START_7_TO_0_ES          (0x0080)
> +#define SBL_REG_FRMT_ROI_HOR_START_15_TO_8_ES         (0x0084)
> +#define SBL_REG_FRMT_ROI_HOR_END_7_TO_0_ES            (0x0088)
> +#define SBL_REG_FRMT_ROI_HOR_END_15_TO_8_ES           (0x008c)
> +#define SBL_REG_FRMT_ROI_VER_START_7_TO_0_ES          (0x0090)
> +#define SBL_REG_FRMT_ROI_VER_START_15_TO_8_ES         (0x0094)
> +#define SBL_REG_FRMT_ROI_VER_END_7_TO_0_ES            (0x0098)
> +#define SBL_REG_FRMT_ROI_VER_END_15_TO_8_ES           (0x009c)
> +#define SBL_REG_CALC_CONTROL_0_ES                     (0x0400)
> +#define SBL_REG_CALC_CONTROL_1_ES                     (0x0404)
> +#define SBL_REG_CALC_AMBIENT_LIGHT_7_TO_0_ES          (0x0408)
> +#define SBL_REG_CALC_AMBIENT_LIGHT_15_TO_8_ES         (0x040c)
> +#define SBL_REG_CALC_BACKLIGHT_7_TO_0_ES              (0x0410)
> +#define SBL_REG_CALC_BACKLIGHT_15_TO_8_ES             (0x0414)
> +#define SBL_REG_CALC_ASSERTIVENESS_ES                 (0x0418)
> +#define SBL_REG_CALC_TF_CONTROL_ES                    (0x041c)
> +#define SBL_REG_CALC_STRENGTH_MANUAL_7_TO_0_ES        (0x0420)
> +#define SBL_REG_CALC_STRENGTH_MANUAL_9_TO_8_ES        (0x0424)
> +#define SBL_REG_CALC_GAIN_AA_MANUAL_7_TO_0_ES         (0x0428)
> +#define SBL_REG_CALC_GAIN_AA_MANUAL_11_TO_8_ES        (0x042c)
> +#define SBL_REG_CALC_ROI_FACTOR_IN_7_TO_0_ES          (0x0430)
> +#define SBL_REG_CALC_ROI_FACTOR_IN_15_TO_8_ES         (0x0434)
> +#define SBL_REG_CALC_ROI_FACTOR_OUT_7_TO_0_ES         (0x0438)
> +#define SBL_REG_CALC_ROI_FACTOR_OUT_15_TO_8_ES        (0x043c)
> +#define SBL_REG_CALC_PSR_DELTA_CHANGE_7_TO_0_ES       (0x0448)
> +#define SBL_REG_CALC_PSR_DELTA_CHANGE_15_TO_8_ES      (0x044c)
> +#define SBL_REG_CALC_PSR_DELTA_SETTLE_7_TO_0_ES       (0x0450)
> +#define SBL_REG_CALC_PSR_DELTA_SETTLE_15_TO_8_ES      (0x0454)
> +#define SBL_REG_CALC_AL_SCALE_7_TO_0_ES               (0x0458)
> +#define SBL_REG_CALC_AL_SCALE_15_TO_8_ES              (0x045c)
> +#define SBL_REG_CALC_AL_TF_STEP_SAMPLE_ES             (0x0460)
> +#define SBL_REG_CALC_AL_TF_STEP_WAIT_7_TO_0_ES        (0x0468)
> +#define SBL_REG_CALC_AL_TF_STEP_WAIT_11_TO_8_ES       (0x046c)
> +#define SBL_REG_CALC_AL_TF_STEP_WAITUP_7_TO_0_ES      (0x0470)
> +#define SBL_REG_CALC_AL_TF_STEP_WAITUP_11_TO_8_ES     (0x0474)
> +#define SBL_REG_CALC_AL_TF_STEP_SIZE_7_TO_0_ES        (0x0478)
> +#define SBL_REG_CALC_AL_TF_STEP_SIZE_11_TO_8_ES       (0x047c)
> +#define SBL_REG_CALC_AL_TF_LIMIT_7_TO_0_ES            (0x0480)
> +#define SBL_REG_CALC_AL_TF_LIMIT_15_TO_8_ES           (0x0484)
> +#define SBL_REG_CALC_AL_TF_ALPHA_ES                   (0x0488)
> +#define SBL_REG_CALC_AL_TF_ALPHA_UP_ES                (0x048c)
> +#define SBL_REG_CALC_AL_TF_NOISE_7_TO_0_ES            (0x0490)
> +#define SBL_REG_CALC_AL_TF_NOISE_15_TO_8_ES           (0x0494)
> +#define SBL_REG_CALC_AL_TF_M_INC_7_TO_0_ES            (0x0498)
> +#define SBL_REG_CALC_AL_TF_M_INC_15_TO_8_ES           (0x049c)
> +#define SBL_REG_CALC_AL_TF_K_INC_7_TO_0_ES            (0x04a0)
> +#define SBL_REG_CALC_AL_TF_K_INC_15_TO_8_ES           (0x04a4)
> +#define SBL_REG_CALC_AL_TF_M_DEC_7_TO_0_ES            (0x04a8)
> +#define SBL_REG_CALC_AL_TF_M_DEC_15_TO_8_ES           (0x04ac)
> +#define SBL_REG_CALC_AL_TF_K_DEC_7_TO_0_ES            (0x04b0)
> +#define SBL_REG_CALC_AL_TF_K_DEC_15_TO_8_ES           (0x04b4)
> +#define SBL_REG_CALC_AL_TF_AGGRESSIVENESS_ES          (0x04b8)
> +#define SBL_REG_CALC_AL_RTF_FILTER_A_7_TO_0_ES        (0x04c0)
> +#define SBL_REG_CALC_AL_RTF_FILTER_A_15_TO_8_ES       (0x04c4)
> +#define SBL_REG_CALC_AL_RTF_FILTER_B_7_TO_0_ES        (0x04c8)
> +#define SBL_REG_CALC_AL_RTF_FILTER_B_15_TO_8_ES       (0x04cc)
> +#define SBL_REG_CALC_AL_RTF_FILTER_C_7_TO_0_ES        (0x04d0)
> +#define SBL_REG_CALC_AL_RTF_FILTER_C_15_TO_8_ES       (0x04d4)
> +#define SBL_REG_CALC_AB_AL_KNEE1_7_TO_0_ES            (0x04d8)
> +#define SBL_REG_CALC_AB_AL_KNEE1_15_TO_8_ES           (0x04dc)
> +#define SBL_REG_CALC_AB_AL_KNEE2_7_TO_0_ES            (0x04e0)
> +#define SBL_REG_CALC_AB_AL_KNEE2_15_TO_8_ES           (0x04e4)
> +#define SBL_REG_CALC_AB_BL_KNEE1_7_TO_0_ES            (0x04e8)
> +#define SBL_REG_CALC_AB_BL_KNEE1_15_TO_8_ES           (0x04ec)
> +#define SBL_REG_CALC_AB_BL_KNEE2_7_TO_0_ES            (0x04f0)
> +#define SBL_REG_CALC_AB_BL_KNEE2_15_TO_8_ES           (0x04f4)
> +#define SBL_REG_CALC_BL_PANEL_MAX_7_TO_0_ES           (0x04f8)
> +#define SBL_REG_CALC_BL_PANEL_MAX_15_TO_8_ES          (0x04fc)
> +#define SBL_REG_CALC_BL_OFFSET_7_TO_0_ES              (0x0500)
> +#define SBL_REG_CALC_BL_OFFSET_15_TO_8_ES             (0x0504)
> +#define SBL_REG_CALC_BL_MIN_7_TO_0_ES                 (0x0508)
> +#define SBL_REG_CALC_BL_MIN_15_TO_8_ES                (0x050c)
> +#define SBL_REG_CALC_BL_ATTEN_ALPHA_7_TO_0_ES         (0x0510)
> +#define SBL_REG_CALC_BL_ATTEN_ALPHA_9_TO_8_ES         (0x0514)
> +#define SBL_REG_CALC_SBC1_TF_DEPTH_7_TO_0_ES          (0x0518)
> +#define SBL_REG_CALC_SBC1_TF_DEPTH_15_TO_8_ES         (0x051c)
> +#define SBL_REG_CALC_SBC1_TF_STEP_7_TO_0_ES           (0x0520)
> +#define SBL_REG_CALC_SBC1_TF_STEP_15_TO_8_ES          (0x0524)
> +#define SBL_REG_CALC_SBC1_TF_ASYM_ES                  (0x0528)
> +#define SBL_REG_CALC_SBC1_TF_DEPTH_LOG_7_TO_0_ES      (0x0530)
> +#define SBL_REG_CALC_SBC1_TF_DEPTH_LOG_15_TO_8_ES     (0x0534)
> +#define SBL_REG_CALC_SBC1_TF_STEP_LOG_7_TO_0_ES       (0x0538)
> +#define SBL_REG_CALC_SBC1_TF_STEP_LOG_15_TO_8_ES      (0x053c)
> +#define SBL_REG_CALC_SBC1_TF_ASYM_LOG_ES              (0x0540)
> +#define SBL_REG_CALC_SBC2_TF_DEPTH_7_TO_0_ES          (0x0548)
> +#define SBL_REG_CALC_SBC2_TF_DEPTH_15_TO_8_ES         (0x054c)
> +#define SBL_REG_CALC_SBC2_TF_STEP_7_TO_0_ES           (0x0550)
> +#define SBL_REG_CALC_SBC2_TF_STEP_15_TO_8_ES          (0x0554)
> +#define SBL_REG_CALC_SBC2_TF_ASYM_ES                  (0x0558)
> +#define SBL_REG_CALC_SBC2_TF_DEPTH_LOG_7_TO_0_ES      (0x0560)
> +#define SBL_REG_CALC_SBC2_TF_DEPTH_LOG_15_TO_8_ES     (0x0564)
> +#define SBL_REG_CALC_SBC2_TF_STEP_LOG_7_TO_0_ES       (0x0568)
> +#define SBL_REG_CALC_SBC2_TF_STEP_LOG_15_TO_8_ES      (0x056c)
> +#define SBL_REG_CALC_SBC2_TF_ASYM_LOG_ES              (0x0570)
> +#define SBL_REG_CALC_CALIBRATION_A_7_TO_0_ES          (0x05b8)
> +#define SBL_REG_CALC_CALIBRATION_A_15_TO_8_ES         (0x05bc)
> +#define SBL_REG_CALC_CALIBRATION_B_7_TO_0_ES          (0x05c0)
> +#define SBL_REG_CALC_CALIBRATION_B_15_TO_8_ES         (0x05c4)
> +#define SBL_REG_CALC_CALIBRATION_C_7_TO_0_ES          (0x05c8)
> +#define SBL_REG_CALC_CALIBRATION_C_15_TO_8_ES         (0x05cc)
> +#define SBL_REG_CALC_CALIBRATION_D_7_TO_0_ES          (0x05d0)
> +#define SBL_REG_CALC_CALIBRATION_D_15_TO_8_ES         (0x05d4)
> +#define SBL_REG_CALC_CALIBRATION_E_7_TO_0_ES          (0x05d8)
> +#define SBL_REG_CALC_CALIBRATION_E_15_TO_8_ES         (0x05dc)
> +#define SBL_REG_CALC_BACKLIGHT_SCALE_7_TO_0_ES        (0x05e0)
> +#define SBL_REG_CALC_BACKLIGHT_SCALE_15_TO_8_ES       (0x05e4)
> +#define SBL_REG_CALC_GAIN_AA_TF_DEPTH_7_TO_0_ES       (0x05e8)
> +#define SBL_REG_CALC_GAIN_AA_TF_DEPTH_15_TO_8_ES      (0x05ec)
> +#define SBL_REG_CALC_GAIN_AA_TF_STEP_7_TO_0_ES        (0x05f0)
> +#define SBL_REG_CALC_GAIN_AA_TF_STEP_11_TO_8_ES       (0x05f4)
> +#define SBL_REG_CALC_GAIN_AA_TF_ASYM_ES               (0x05f8)
> +#define SBL_REG_CALC_STRENGTH_LIMIT_7_TO_0_ES         (0x0600)
> +#define SBL_REG_CALC_STRENGTH_LIMIT_9_TO_8_ES         (0x0604)
> +#define SBL_REG_CALC_ICUT_HIST_MIN_ES                 (0x0608)
> +#define SBL_REG_CALC_ICUT_BL_MIN_7_TO_0_ES            (0x0610)
> +#define SBL_REG_CALC_ICUT_BL_MIN_15_TO_8_ES           (0x0614)
> +#define SBL_REG_CALC_GAIN_CA_TF_DEPTH_7_TO_0_ES       (0x0618)
> +#define SBL_REG_CALC_GAIN_CA_TF_DEPTH_15_TO_8_ES      (0x061c)
> +#define SBL_REG_CALC_GAIN_CA_TF_STEP_7_TO_0_ES        (0x0620)
> +#define SBL_REG_CALC_GAIN_CA_TF_STEP_11_TO_8_ES       (0x0624)
> +#define SBL_REG_CALC_GAIN_CA_TF_ASYM_ES               (0x0628)
> +#define SBL_REG_CALC_GAIN_MAX_7_TO_0_ES               (0x0630)
> +#define SBL_REG_CALC_GAIN_MAX_11_TO_8_ES              (0x0634)
> +#define SBL_REG_CALC_GAIN_MIDDLE_7_TO_0_ES            (0x0638)
> +#define SBL_REG_CALC_GAIN_MIDDLE_11_TO_8_ES           (0x063c)
> +#define SBL_REG_CALC_BRIGHTPR_ES                      (0x0640)
> +#define SBL_REG_CALC_BPR_CORRECT_ES                   (0x0648)
> +#define SBL_CALC_BACKLIGHT_OUT_7_TO_0_ES              (0x0650)
> +#define SBL_CALC_BACKLIGHT_OUT_15_TO_8_ES             (0x0654)
> +#define SBL_CALC_STRENGTH_INROI_OUT_7_TO_0_ES         (0x0658)
> +#define SBL_CALC_STRENGTH_INROI_OUT_9_TO_8_ES         (0x065c)
> +#define SBL_CALC_STRENGTH_OUTROI_OUT_7_TO_0_ES        (0x0660)
> +#define SBL_CALC_STRENGTH_OUTROI_OUT_9_TO_8_ES        (0x0664)
> +#define SBL_CALC_DARKENH_OUT_7_TO_0_ES                (0x0668)
> +#define SBL_CALC_DARKENH_OUT_15_TO_8_ES               (0x066c)
> +#define SBL_CALC_BRIGHTPR_OUT_ES                      (0x0670)
> +#define SBL_CALC_STAT_OUT_7_TO_0_ES                   (0x0678)
> +#define SBL_CALC_STAT_OUT_15_TO_8_ES                  (0x067c)
> +#define SBL_REG_CALC_AL_DELTA_SETTLE_7_TO_0_ES        (0x0680)
> +#define SBL_REG_CALC_AL_DELTA_SETTLE_15_TO_8_ES       (0x0684)
> +#define SBL_REG_CALC_BL_DELTA_SETTLE_7_TO_0_ES        (0x0688)
> +#define SBL_REG_CALC_BL_DELTA_SETTLE_15_TO_8_ES       (0x068c)
> +#define SBL_CALC_AL_CALIB_LUT_ADDR_I_ES               (0x06c0)
> +#define SBL_CALC_AL_CALIB_LUT_DATA_W_7_TO_0_ES        (0x06d0)
> +#define SBL_CALC_AL_CALIB_LUT_DATA_W_15_TO_8_ES       (0x06d4)
> +#define SBL_CALC_BL_IN_LUT_ADDR_I_ES                  (0x0700)
> +#define SBL_CALC_BL_IN_LUT_DATA_W_7_TO_0_ES           (0x0710)
> +#define SBL_CALC_BL_IN_LUT_DATA_W_15_TO_8_ES          (0x0714)
> +#define SBL_CALC_BL_OUT_LUT_ADDR_I_ES                 (0x0740)
> +#define SBL_CALC_BL_OUT_LUT_DATA_W_7_TO_0_ES          (0x0750)
> +#define SBL_CALC_BL_OUT_LUT_DATA_W_15_TO_8_ES         (0x0754)
> +#define SBL_CALC_BL_ATTEN_LUT_ADDR_I_ES               (0x0780)
> +#define SBL_CALC_BL_ATTEN_LUT_DATA_W_7_TO_0_ES        (0x0790)
> +#define SBL_CALC_BL_ATTEN_LUT_DATA_W_15_TO_8_ES       (0x0794)
> +#define SBL_CALC_BL_AUTO_LUT_ADDR_I_ES                (0x07c0)
> +#define SBL_CALC_BL_AUTO_LUT_DATA_W_7_TO_0_ES         (0x07d0)
> +#define SBL_CALC_BL_AUTO_LUT_DATA_W_15_TO_8_ES        (0x07d4)
> +#define SBL_CALC_AL_CHANGE_LUT_ADDR_I_ES              (0x0800)
> +#define SBL_CALC_AL_CHANGE_LUT_DATA_W_7_TO_0_ES       (0x0810)
> +#define SBL_CALC_AL_CHANGE_LUT_DATA_W_15_TO_8_ES      (0x0814)
> +#define SBL_REG_CABC_INTENSITY_7_TO_0_ES              (0x0900)
> +#define SBL_REG_CABC_INTENSITY_11_TO_8_ES             (0x0904)
> +#define SBL_REG_CABC_ICUT_SELECT_ES                   (0x0908)
> +#define SBL_REG_CABC_ICUT_MANUAL_ES                   (0x090c)
> +#define SBL_CABC_ICUT_OUT_ES                          (0x0910)
> +#define SBL_REG_CORE1_VC_CONTROL_0_ES                 (0x0c00)
> +#define SBL_REG_CORE1_IRDX_CONTROL_0_ES               (0x0c40)
> +#define SBL_REG_CORE1_IRDX_CONTROL_1_ES               (0x0c44)
> +#define SBL_REG_CORE1_IRDX_VARIANCE_ES                (0x0c4c)
> +#define SBL_REG_CORE1_IRDX_SLOPE_MAX_ES               (0x0c50)
> +#define SBL_REG_CORE1_IRDX_SLOPE_MIN_ES               (0x0c54)
> +#define SBL_REG_CORE1_IRDX_BLACK_LEVEL_7_TO_0_ES      (0x0c58)
> +#define SBL_REG_CORE1_IRDX_BLACK_LEVEL_9_TO_8_ES      (0x0c5c)
> +#define SBL_REG_CORE1_IRDX_WHITE_LEVEL_7_TO_0_ES      (0x0c60)
> +#define SBL_REG_CORE1_IRDX_WHITE_LEVEL_9_TO_8_ES      (0x0c64)
> +#define SBL_REG_CORE1_IRDX_LIMIT_AMPL_ES              (0x0c68)
> +#define SBL_REG_CORE1_IRDX_DITHER_ES                  (0x0c6c)
> +#define SBL_REG_CORE1_IRDX_STRENGTH_INROI_7_TO_0_ES   (0x0c70)
> +#define SBL_REG_CORE1_IRDX_STRENGTH_INROI_9_TO_8_ES   (0x0c74)
> +#define SBL_REG_CORE1_IRDX_STRENGTH_OUTROI_7_TO_0_ES  (0x0c78)
> +#define SBL_REG_CORE1_IRDX_STRENGTH_OUTROI_9_TO_8_ES  (0x0c7c)
> +#define SBL_CORE1_IRDX_ASYMMETRY_LUT_ADDR_I_ES        (0x0c80)
> +#define SBL_CORE1_IRDX_ASYMMETRY_LUT_DATA_W_7_TO_0_ES (0x0c84)
> +#define SBL_CORE1_IRDX_ASYMMETRY_LUT_DATA_W_11_TO_8_ES (0x0c88)
> +#define SBL_CORE1_IRDX_COLOR_LUT_ADDR_I_ES            (0x0cc0)
> +#define SBL_CORE1_IRDX_COLOR_LUT_DATA_W_7_TO_0_ES     (0x0cc4)
> +#define SBL_CORE1_IRDX_COLOR_LUT_DATA_W_11_TO_8_ES    (0x0cc8)
> +#define SBL_REG_CORE1_IRDX_FILTER_CTRL_ES             (0x0d00)
> +#define SBL_REG_CORE1_IRDX_SVARIANCE_ES               (0x0d04)
> +#define SBL_REG_CORE1_IRDX_BRIGHTPR_ES                (0x0d08)
> +#define SBL_REG_CORE1_IRDX_CONTRAST_ES                (0x0d0c)
> +#define SBL_REG_CORE1_IRDX_DARKENH_7_TO_0_ES          (0x0d10)
> +#define SBL_REG_CORE1_IRDX_DARKENH_15_TO_8_ES         (0x0d14)
> +#define SBL_REG_CORE1_DTHR_CONTROL_ES                 (0x0dc0)
> +#define SBL_REG_CORE1_LOGO_TOP_ES                     (0x0dd0)
> +#define SBL_REG_CORE1_LOGO_LEFT_ES                    (0x0dd4)
> +#define SBL_REG_CORE1_CA_D_ARTITHRESH_7_TO_0_ES       (0x0e00)
> +#define SBL_REG_CORE1_CA_D_ARTITHRESH_9_TO_8_ES       (0x0e04)
> +#define SBL_CORE1_CA_STR_ATTEN_7_TO_0_ES              (0x0e10)
> +#define SBL_CORE1_CA_STR_ATTEN_15_TO_8_ES             (0x0e14)
> +#define SBL_CORE1_CA_STR_ATTEN_16_ES                  (0x0e18)
> +#define SBL_REG_CORE1_FRD_D_THRESH_7_TO_0_ES          (0x0e20)
> +#define SBL_REG_CORE1_FRD_D_THRESH_9_TO_8_ES          (0x0e24)
> +#define SBL_REG_CORE1_REG0_7_TO_0_ES                  (0x0e28)
> +#define SBL_REG_CORE1_REG0_15_TO_8_ES                 (0x0e2c)
> +#define SBL_REG_CORE1_REG1_7_TO_0_ES                  (0x0e30)
> +#define SBL_REG_CORE1_REG1_15_TO_8_ES                 (0x0e34)
> +#define SBL_REG_CORE1_REG2_7_TO_0_ES                  (0x0e38)
> +#define SBL_REG_CORE1_REG2_15_TO_8_ES                 (0x0e3c)
> +#define SBL_REG_CORE1_REG3_7_TO_0_ES                  (0x0e40)
> +#define SBL_REG_CORE1_REG3_15_TO_8_ES                 (0x0e44)
> +#define SBL_REG_CORE1_REG4_7_TO_0_ES                  (0x0e48)
> +#define SBL_REG_CORE1_REG4_15_TO_8_ES                 (0x0e4c)
> +#define SBL_REG_CORE1_REG5_7_TO_0_ES                  (0x0e50)
> +#define SBL_REG_CORE1_REG5_15_TO_8_ES                 (0x0e54)
> +#define SBL_CORE1_REG_OUT0_7_TO_0_ES                  (0x0e58)
> +#define SBL_CORE1_REG_OUT0_15_TO_8_ES                 (0x0e5c)
> +#define SBL_CORE1_REG_OUT1_7_TO_0_ES                  (0x0e60)
> +#define SBL_CORE1_REG_OUT1_15_TO_8_ES                 (0x0e64)
> +
> +/* SBL for 970 */
> +#define SBL_REG_FRMT_MODE                                  (0x0000)
> +#define SBL_REG_FRMT_FRAME_DIMEN                           (0x0004)
> +#define SBL_REG_FRMT_HW_VERSION                            (0x0014)
> +#define SBL_REG_FRMT_ROI_HOR                               (0x0020)
> +#define SBL_REG_FRMT_ROI_VER                               (0x0024)
> +#define SBL_REG_CALC_CONTROL                               (0x0100)
> +#define SBL_REG_AL_BL                                      (0x0104)
> +#define SBL_REG_FILTERS_CTRL                               (0x0108)
> +#define SBL_REG_MANUAL                                     (0x010c)
> +#define SBL_REG_CALC_ROI_FACTOR                            (0x0110)
> +#define SBL_REG_CALC_PSR_DELTA                             (0x0114)
> +#define SBL_REG_CALC_AL                                    (0x0118)
> +#define SBL_REG_CALC_AL_TF_STEP_WAIT                       (0x011c)
> +#define SBL_REG_CALC_AL_TF_STEP_SIZE_LIMIT                 (0x0120)
> +#define SBL_REG_CALC_AL_TF_ALPHA                           (0x0124)
> +#define SBL_REG_CALC_AL_TF_NOISE_M_INC                     (0x0128)
> +#define SBL_REG_CALC_AL_TF_K_INC_M_DEC                     (0x012c)
> +#define SBL_REG_CALC_AL_TF_K_DEC_AGGRESSIVENESS            (0x0130)
> +#define SBL_REG_CALC_AL_RTF_FILTER_A_7_TO_0                (0x0134)
> +#define SBL_REG_CALC_AL_RTF_FILTER_C_AB_AL_KNEE1           (0x0138)
> +#define SBL_REG_CALC_AB_AL_KNEE2_AB_BL_KNEE1               (0x013c)
> +#define SBL_REG_CALC_AB_BL_KNEE2_BL_PANEL_MAX              (0x0140)
> +#define SBL_REG_CALC_BL_OFFSET_BL_MIN                      (0x0144)
> +#define SBL_REG_CALC_BL_ATTEN_ALPHA_SBC1_TF_DEPTH          (0x0148)
> +#define SBL_REG_CALC_SBC1_TF_STEP_SBC1_TF_ASYM             (0x014c)
> +#define SBL_REG_CALC_SBC1_TF_DEPTH_LOG_SBC1_TF_STEP_LOG    (0x0150)
> +#define SBL_REG_CALC_SBC1_TF_ASYM_LOG_SBC2_TF_DEPTH        (0x0154)
> +#define SBL_REG_CALC_SBC2_TF_STEP_SBC2_TF_ASYM             (0x0158)
> +#define SBL_REG_CALC_SBC2_TF_DEPTH_LOG_SBC2_TF_STEP_LOG    (0x015c)
> +#define SBL_REG_CALC_SBC2_TF_ASYM_LOG                      (0x0160)
> +#define SBL_REG_CALC_CALIBRATION_A_B                       (0x0170)
> +#define SBL_REG_CALC_CALIBRATION_C_D                       (0x0174)
> +#define SBL_REG_CALC_CALIBRATION_E_BACKLIGHT_SCALE         (0x0178)
> +#define SBL_REG_CALC_GAIN_AA_TF_DEPTH_STEP                 (0x017c)
> +#define SBL_REG_CALC_GAIN_AA_TF_ASYM_STRENGTH_LIMIT        (0x0180)
> +#define SBL_REG_CALC_ICUT_HIST_MIN_ICUT_BL_MIN             (0x0184)
> +#define SBL_REG_CALC_GAIN_CA_TF_DEPTH_GAIN_CA_TF_STEP      (0x0188)
> +#define SBL_REG_CALC_GAIN_CA_TF_ASYM_GAIN_MAX              (0x018c)
> +#define SBL_REG_CALC_GAIN_MIDDLE_CALC_BRIGHTPR             (0x0190)
> +#define SBL_REG_CALC_BPR_CORRECT_CALC_BACKLIGHT_OUT        (0x0194)
> +#define SBL_CALC_STRENGTH_INROI_OUTROI_OUT                 (0x0198)
> +#define SBL_CALC_DARKENH_OUT_CALC_BRIGHTPR_OUT             (0x019c)
> +#define SBL_CALC_STAT_OUT                                  (0x01A0)
> +#define SBL_REG_CALC_BL_DELTA_SETTLE                       (0x01A4)
> +#define SBL_CALC_AL_CALIB_LUT_ADDR_I                       (0x01B0)
> +#define SBL_CALC_AL_CALIB_LUT_DATA_W                       (0x01B4)
> +#define SBL_CALC_BL_IN_LUT_ADDR_I                          (0x01C0)
> +#define SBL_CALC_BL_IN_LUT_DATA_W                          (0x01C4)
> +#define SBL_CALC_BL_OUT_LUT_ADDR_I                         (0x01D0)
> +#define SBL_CALC_BL_OUT_LUT_DATA_W                         (0x01D4)
> +#define SBL_CALC_BL_ATTEN_LUT_ADDR_I                       (0x01E0)
> +#define SBL_CALC_BL_ATTEN_LUT_DATA_W                       (0x01E4)
> +#define SBL_CALC_BL_AUTO_LUT_ADDR_I                        (0x01F0)
> +#define SBL_CALC_BL_AUTO_LUT_DATA_W                        (0x01F4)
> +#define SBL_CALC_AL_CHANGE_LUT_ADDR_I                      (0x0200)
> +#define SBL_CALC_AL_CHANGE_LUT_DATA_W                      (0x0204)
> +#define SBL_REG_CABC_INTENSITY_CABC_ICUT_SELECT            (0x0240)
> +#define SBL_REG_CABC_ICUT_MANUAL_CABC_ICUT_OUT             (0x0244)
> +#define SBL_REG_VC_VC_CONTROL_0                            (0x0300)
> +#define SBL_REG_VC_IRDX_CONTROL                            (0x0308)
> +#define SBL_REG_VC_IRDX_ALPHA_MANUAL_VC_IRDX_BETA_MANUA    (0x030c)
> +#define SBL_REG_VC_IRDX_VARIANCE                           (0x0310)
> +#define SBL_REG_VC_IRDX_SLOPE_MAX_MIN                      (0x0314)
> +#define SBL_REG_VC_IRDX_BLACK_WHITE_LEVEL_7_TO_0           (0x0318)
> +#define SBL_REG_VC_IRDX_LIMIT_AMPL_VC_IRDX_DITHER          (0x031c)
> +#define SBL_REG_VC_IRDX_STRENGTH_INROI_OUTROI              (0x0320)
> +#define SBL_CORE1_IRDX_ASYMMETRY_LUT_ADDR_I                (0x0324)
> +#define SBL_CORE1_IRDX_ASYMMETRY_LUT_DATA_W                (0x0328)
> +#define SBL_CORE1_IRDX_COLOR_LUT_ADDR_I                    (0x0334)
> +#define SBL_CORE1_IRDX_COLOR_LUT_DATA_W                    (0x0338)
> +#define SBL_REG_VC_IRDX_FILTER_CTRL                        (0x0344)
> +#define SBL_REG_VC_IRDX_BRIGHTPR                           (0x0348)
> +#define SBL_REG_VC_IRDX_CONTRAST                           (0x034c)
> +#define SBL_REG_VC_IRDX_DARKENH                            (0x0350)
> +#define SBL_REG_VC_DTHR_CONTROL                            (0x0370)
> +#define SBL_REG_VC_LOGO_TOP_LEFT                           (0x0374)
> +#define SBL_REG_VC_CA_D_ARTITHRESH                         (0x0380)
> +#define SBL_VC_CA_STR_ATTEN                                (0x0384)
> +#define SBL_REG_VC_REG1_REG2                               (0x038c)
> +#define SBL_REG_VC_REG3_REG4                               (0x0390)
> +#define SBL_REG_VC_REG5_REG_OUT0                           (0x0394)
> +#define SBL_VC_REG_OUT1                                    (0x0398)
> +#define SBL_VC_ANTI_FLCKR_CONTROL                          (0x039c)
> +#define SBL_VC_ANTI_FLCKR_RFD_FRD_THR                      (0x03a0)
> +#define SBL_VC_ANTI_FLCKR_SCD_THR_ANTI_FLCKR_FD3_SC_DLY    (0x03a4)
> +#define SBL_VC_ANTI_FLCKR_AL_ANTI_FLCKR_T_DURATION         (0x03a8)
> +#define SBL_VC_ANTI_FLCKR_ALPHA                            (0x03ac)
> +
> +/* DPP */
> +/* DPP TOP */
> +/* #define DPP_ARSR1P_MEM_CTRL	(0x01C) */
> +#define DPP_ARSR_POST_MEM_CTRL	(0x01C)
> +/* #define DPP_ARSR1P	(0x048) */
> +
> +/* DITHER */
> +#define DITHER_CTL1 (0x000)
> +#define DITHER_CTL0 (0x004)
> +#define DITHER_TRI_THD12_0 (0x008)
> +#define DITHER_TRI_THD12_1 (0x00C)
> +#define DITHER_TRI_THD10 (0x010)
> +#define DITHER_TRI_THD12_UNI_0 (0x014)
> +#define DITHER_TRI_THD12_UNI_1 (0x018)
> +#define DITHER_TRI_THD10_UNI (0x01C)
> +#define DITHER_BAYER_CTL (0x020)
> +#define DITHER_BAYER_ALPHA_THD (0x024)
> +#define DITHER_MATRIX_PART1 (0x028)
> +#define DITHER_MATRIX_PART0 (0x02C)
> +#define DITHER_HIFREQ_REG_INI_CFG_EN (0x030)
> +#define DITHER_HIFREQ_REG_INI0_0 (0x034)
> +#define DITHER_HIFREQ_REG_INI0_1 (0x038)
> +#define DITHER_HIFREQ_REG_INI0_2 (0x03C)
> +#define DITHER_HIFREQ_REG_INI0_3 (0x040)
> +#define DITHER_HIFREQ_REG_INI1_0 (0x044)
> +#define DITHER_HIFREQ_REG_INI1_1 (0x048)
> +#define DITHER_HIFREQ_REG_INI1_2 (0x04C)
> +#define DITHER_HIFREQ_REG_INI1_3 (0x050)
> +#define DITHER_HIFREQ_REG_INI2_0 (0x054)
> +#define DITHER_HIFREQ_REG_INI2_1 (0x058)
> +#define DITHER_HIFREQ_REG_INI2_2 (0x05C)
> +#define DITHER_HIFREQ_REG_INI2_3 (0x060)
> +#define DITHER_HIFREQ_POWER_CTRL (0x064)
> +#define DITHER_HIFREQ_FILT_0 (0x068)
> +#define DITHER_HIFREQ_FILT_1 (0x06C)
> +#define DITHER_HIFREQ_FILT_2 (0x070)
> +#define DITHER_HIFREQ_THD_R0 (0x074)
> +#define DITHER_HIFREQ_THD_R1 (0x078)
> +#define DITHER_HIFREQ_THD_G0 (0x07C)
> +#define DITHER_HIFREQ_THD_G1 (0x080)
> +#define DITHER_HIFREQ_THD_B0 (0x084)
> +#define DITHER_HIFREQ_THD_B1 (0x088)
> +#define DITHER_HIFREQ_DBG0 (0x08C)
> +#define DITHER_HIFREQ_DBG1 (0x090)
> +#define DITHER_HIFREQ_DBG2 (0x094)
> +#define DITHER_ERRDIFF_CTL (0x098)
> +#define DITHER_ERRDIFF_WEIGHT (0x09C)
> +#define DITHER_FRC_CTL (0x0A0)
> +#define DITHER_FRC_01_PART1 (0x0A4)
> +#define DITHER_FRC_01_PART0 (0x0A8)
> +#define DITHER_FRC_10_PART1 (0x0AC)
> +#define DITHER_FRC_10_PART0 (0x0B0)
> +#define DITHER_FRC_11_PART1 (0x0B4)
> +#define DITHER_FRC_11_PART0 (0x0B8)
> +#define DITHER_MEM_CTRL (0x0BC)
> +#define DITHER_DBG0 (0x0C0)
> +#define DITHER_DBG1 (0x0C4)
> +#define DITHER_DBG2 (0x0C8)
> +#define DITHER_CTRL2 (0x0CC)
> +
> +/* Dither for ES */
> +#define DITHER_PARA_ES (0x000)
> +#define DITHER_CTL_ES (0x004)
> +#define DITHER_MATRIX_PART1_ES (0x008)
> +#define DITHER_MATRIX_PART0_ES (0x00C)
> +#define DITHER_ERRDIFF_WEIGHT_ES (0x010)
> +#define DITHER_FRC_01_PART1_ES (0x014)
> +#define DITHER_FRC_01_PART0_ES (0x018)
> +#define DITHER_FRC_10_PART1_ES (0x01C)
> +#define DITHER_FRC_10_PART0_ES (0x020)
> +#define DITHER_FRC_11_PART1_ES (0x024)
> +#define DITHER_FRC_11_PART0_ES (0x028)
> +#define DITHER_MEM_CTRL_ES (0x02C)
> +#define DITHER_DBG0_ES (0x030)
> +#define DITHER_DBG1_ES (0x034)
> +#define DITHER_DBG2_ES (0x038)
> +
> +/* CSC_RGB2YUV_10bits  CSC_YUV2RGB_10bits */
> +
> +/* GAMA */
> +#define GAMA_LUT_SEL (0x008)
> +#define GAMA_DBG0 (0x00C)
> +#define GAMA_DBG1 (0x010)
> +
> +/* ACM for ES */
> +#define ACM_EN_ES            (0x000)
> +#define ACM_SATA_OFFSET_ES   (0x004)
> +#define ACM_HUESEL_ES        (0x008)
> +#define ACM_CSC_IDC0_ES      (0x00C)
> +#define ACM_CSC_IDC1_ES      (0x010)
> +#define ACM_CSC_IDC2_ES      (0x014)
> +#define ACM_CSC_P00_ES       (0x018)
> +#define ACM_CSC_P01_ES       (0x01C)
> +#define ACM_CSC_P02_ES       (0x020)
> +#define ACM_CSC_P10_ES       (0x024)
> +#define ACM_CSC_P11_ES       (0x028)
> +#define ACM_CSC_P12_ES       (0x02C)
> +#define ACM_CSC_P20_ES       (0x030)
> +#define ACM_CSC_P21_ES       (0x034)
> +#define ACM_CSC_P22_ES       (0x038)
> +#define ACM_CSC_MRREC_ES     (0x03C)
> +#define ACM_R0_H_ES          (0x040)
> +#define ACM_R1_H_ES          (0x044)
> +#define ACM_R2_H_ES          (0x048)
> +#define ACM_R3_H_ES          (0x04C)
> +#define ACM_R4_H_ES          (0x050)
> +#define ACM_R5_H_ES          (0x054)
> +#define ACM_R6_H_ES          (0x058)
> +#define ACM_LUT_DIS0_ES      (0x05C)
> +#define ACM_LUT_DIS1_ES      (0x060)
> +#define ACM_LUT_DIS2_ES      (0x064)
> +#define ACM_LUT_DIS3_ES      (0x068)
> +#define ACM_LUT_DIS4_ES      (0x06C)
> +#define ACM_LUT_DIS5_ES      (0x070)
> +#define ACM_LUT_DIS6_ES      (0x074)
> +#define ACM_LUT_DIS7_ES      (0x078)
> +#define ACM_LUT_PARAM0_ES    (0x07C)
> +#define ACM_LUT_PARAM1_ES    (0x080)
> +#define ACM_LUT_PARAM2_ES    (0x084)
> +#define ACM_LUT_PARAM3_ES    (0x088)
> +#define ACM_LUT_PARAM4_ES    (0x08C)
> +#define ACM_LUT_PARAM5_ES    (0x090)
> +#define ACM_LUT_PARAM6_ES    (0x094)
> +#define ACM_LUT_PARAM7_ES    (0x098)
> +#define ACM_LUT_SEL_ES       (0x09C)
> +#define ACM_MEM_CTRL_ES      (0x0A0)
> +#define ACM_DEBUG_TOP_ES     (0x0A4)
> +#define ACM_DEBUG_CFG_ES     (0x0A8)
> +#define ACM_DEBUG_W_ES       (0x0AC)
> +
> +/* ACM */
> +#define ACM_HUE_RLH01 (0x040)
> +#define ACM_HUE_RLH23 (0x044)
> +#define ACM_HUE_RLH45 (0x048)
> +#define ACM_HUE_RLH67 (0x04C)
> +#define ACM_HUE_PARAM01 (0x060)
> +#define ACM_HUE_PARAM23 (0x064)
> +#define ACM_HUE_PARAM45 (0x068)
> +#define ACM_HUE_PARAM67 (0x06C)
> +#define ACM_HUE_SMOOTH0 (0x070)
> +#define ACM_HUE_SMOOTH1 (0x074)
> +#define ACM_HUE_SMOOTH2 (0x078)
> +#define ACM_HUE_SMOOTH3 (0x07C)
> +#define ACM_HUE_SMOOTH4 (0x080)
> +#define ACM_HUE_SMOOTH5 (0x084)
> +#define ACM_HUE_SMOOTH6 (0x088)
> +#define ACM_HUE_SMOOTH7 (0x08C)
> +#define ACM_DBG_TOP (0x0A4)
> +#define ACM_DBG_CFG (0x0A8)
> +#define ACM_DBG_W (0x0AC)
> +#define ACM_COLOR_CHOOSE (0x0B0)
> +#define ACM_RGB2YUV_IDC0 (0x0C0)
> +#define ACM_RGB2YUV_IDC1 (0x0C4)
> +#define ACM_RGB2YUV_IDC2 (0x0C8)
> +#define ACM_RGB2YUV_P00 (0x0CC)
> +#define ACM_RGB2YUV_P01 (0x0D0)
> +#define ACM_RGB2YUV_P02 (0x0D4)
> +#define ACM_RGB2YUV_P10 (0x0D8)
> +#define ACM_RGB2YUV_P11 (0x0DC)
> +#define ACM_RGB2YUV_P12 (0x0E0)
> +#define ACM_RGB2YUV_P20 (0x0E4)
> +#define ACM_RGB2YUV_P21 (0x0E8)
> +#define ACM_RGB2YUV_P22 (0x0EC)
> +#define ACM_FACE_CRTL (0x100)
> +#define ACM_FACE_STARTXY (0x104)
> +#define ACM_FACE_SMOOTH_LEN01 (0x108)
> +#define ACM_FACE_SMOOTH_LEN23 (0x10C)
> +#define ACM_FACE_SMOOTH_PARAM0 (0x118)
> +#define ACM_FACE_SMOOTH_PARAM1 (0x11C)
> +#define ACM_FACE_SMOOTH_PARAM2 (0x120)
> +#define ACM_FACE_SMOOTH_PARAM3 (0x124)
> +#define ACM_FACE_SMOOTH_PARAM4 (0x128)
> +#define ACM_FACE_SMOOTH_PARAM5 (0x12C)
> +#define ACM_FACE_SMOOTH_PARAM6 (0x130)
> +#define ACM_FACE_SMOOTH_PARAM7 (0x134)
> +#define ACM_FACE_AREA_SEL (0x138)
> +#define ACM_FACE_SAT_LH (0x13C)
> +#define ACM_FACE_SAT_SMOOTH_LH (0x140)
> +#define ACM_FACE_SAT_SMO_PARAM_LH (0x148)
> +#define ACM_L_CONT_EN (0x160)
> +#define ACM_LC_PARAM01 (0x174)
> +#define ACM_LC_PARAM23 (0x178)
> +#define ACM_LC_PARAM45 (0x17C)
> +#define ACM_LC_PARAM67 (0x180)
> +#define ACM_L_ADJ_CTRL (0x1A0)
> +#define ACM_CAPTURE_CTRL (0x1B0)
> +#define ACM_CAPTURE_IN (0x1B4)
> +#define ACM_CAPTURE_OUT (0x1B8)
> +#define ACM_INK_CTRL (0x1C0)
> +#define ACM_INK_OUT (0x1C4)
> +
> +/* ACE FOR ES */
> +
> +/* LCP */
> +#define LCP_GMP_BYPASS_EN_ES	(0x030)
> +#define LCP_XCC_BYPASS_EN_ES	(0x034)
> +#define LCP_DEGAMA_EN_ES	(0x038)
> +#define LCP_DEGAMA_MEM_CTRL_ES	(0x03C)
> +#define LCP_GMP_MEM_CTRL_ES	(0x040)
> +
> +/* XCC */
> +#define XCC_COEF_00 (0x000)
> +#define XCC_COEF_01 (0x004)
> +#define XCC_COEF_02 (0x008)
> +#define XCC_COEF_03 (0x00C)
> +#define XCC_COEF_10 (0x010)
> +#define XCC_COEF_11 (0x014)
> +#define XCC_COEF_12 (0x018)
> +#define XCC_COEF_13 (0x01C)
> +#define XCC_COEF_20 (0x020)
> +#define XCC_COEF_21 (0x024)
> +#define XCC_COEF_22 (0x028)
> +#define XCC_COEF_23 (0x02C)
> +#define XCC_EN (0x034)
> +
> +/* DEGAMMA */
> +#define DEGAMA_EN (0x000)
> +#define DEGAMA_MEM_CTRL (0x004)
> +#define DEGAMA_LUT_SEL (0x008)
> +#define DEGAMA_DBG0 (0x00C)
> +#define DEGAMA_DBG1 (0x010)
> +
> +/* GMP */
> +#define GMP_EN (0x000)
> +#define GMP_MEM_CTRL (0x004)
> +#define GMP_LUT_SEL (0x008)
> +#define GMP_DBG_W0 (0x00C)
> +#define GMP_DBG_R0 (0x010)
> +#define GMP_DBG_R1 (0x014)
> +#define GMP_DBG_R2 (0x018)
> +
> +/* ARSR1P ES */
> +#define ARSR1P_IHLEFT_ES		(0x000)
> +#define ARSR1P_IHRIGHT_ES          (0x004)
> +#define ARSR1P_IHLEFT1_ES          (0x008)
> +#define ARSR1P_IHRIGHT1_ES         (0x00C)
> +#define ARSR1P_IVTOP_ES            (0x010)
> +#define ARSR1P_IVBOTTOM_ES         (0x014)
> +#define ARSR1P_UV_OFFSET_ES		(0x018)
> +#define ARSR1P_IHINC_ES            (0x01C)
> +#define ARSR1P_IVINC_ES            (0x020)
> +#define ARSR1P_MODE_ES		(0x024)
> +#define ARSR1P_FORMAT_ES           (0x028)
> +#define ARSR1P_SKIN_THRES_Y_ES	(0x02C)
> +#define ARSR1P_SKIN_THRES_U_ES	(0x030)
> +#define ARSR1P_SKIN_THRES_V_ES	(0x034)
> +#define ARSR1P_SKIN_EXPECTED_ES    (0x038)
> +#define ARSR1P_SKIN_CFG_ES		(0x03C)
> +#define ARSR1P_SHOOT_CFG1_ES		(0x040)
> +#define ARSR1P_SHOOT_CFG2_ES		(0x044)
> +#define ARSR1P_SHARP_CFG1_ES		(0x048)
> +#define ARSR1P_SHARP_CFG2_ES		(0x04C)
> +#define ARSR1P_SHARP_CFG3_ES		(0x050)
> +#define ARSR1P_SHARP_CFG4_ES		(0x054)
> +#define ARSR1P_SHARP_CFG5_ES		(0x058)
> +#define ARSR1P_SHARP_CFG6_ES		(0x05C)
> +#define ARSR1P_SHARP_CFG7_ES		(0x060)
> +#define ARSR1P_SHARP_CFG8_ES		(0x064)
> +#define ARSR1P_SHARP_CFG9_ES		(0x068)
> +#define ARSR1P_SHARP_CFG10_ES		(0x06C)
> +#define ARSR1P_SHARP_CFG11_ES		(0x070)
> +#define ARSR1P_DIFF_CTRL_ES		(0x074)
> +#define ARSR1P_LSC_CFG1_ES         (0x078)
> +#define ARSR1P_LSC_CFG2_ES         (0x07C)
> +#define ARSR1P_LSC_CFG3_ES         (0x080)
> +#define ARSR1P_FORCE_CLK_ON_CFG_ES	(0x084)
> +
> +/* ARSR1P */
> +
> +#define ARSR_POST_IHLEFT (0x000)
> +#define ARSR_POST_IHRIGHT (0x004)
> +#define ARSR_POST_IHLEFT1 (0x008)
> +#define ARSR_POST_IHRIGHT1 (0x00C)
> +#define ARSR_POST_IVTOP (0x010)
> +#define ARSR_POST_IVBOTTOM (0x014)
> +#define ARSR_POST_UV_OFFSET (0x018)
> +#define ARSR_POST_IHINC (0x01C)
> +#define ARSR_POST_IVINC (0x020)
> +#define ARSR_POST_MODE (0x024)
> +#define ARSR_POST_FORMAT (0x028)
> +#define ARSR_POST_SKIN_THRES_Y (0x02C)
> +#define ARSR_POST_SKIN_THRES_U (0x030)
> +#define ARSR_POST_SKIN_THRES_V (0x034)
> +#define ARSR_POST_SKIN_EXPECTED (0x038)
> +#define ARSR_POST_SKIN_CFG (0x03C)
> +#define ARSR_POST_SHOOT_CFG1 (0x040)
> +#define ARSR_POST_SHOOT_CFG2 (0x044)
> +#define ARSR_POST_SHOOT_CFG3 (0x048)
> +#define ARSR_POST_SHARP_CFG1_H (0x04C)
> +#define ARSR_POST_SHARP_CFG1_L (0x050)
> +#define ARSR_POST_SHARP_CFG2_H (0x054)
> +#define ARSR_POST_SHARP_CFG2_L (0x058)
> +#define ARSR_POST_SHARP_CFG3 (0x05C)
> +#define ARSR_POST_SHARP_CFG4 (0x060)
> +#define ARSR_POST_SHARP_CFG5 (0x064)
> +#define ARSR_POST_SHARP_CFG6 (0x068)
> +#define ARSR_POST_SHARP_CFG6_CUT (0x06C)
> +#define ARSR_POST_SHARP_CFG7 (0x070)
> +#define ARSR_POST_SHARP_CFG7_RATIO (0x074)
> +#define ARSR_POST_SHARP_CFG8 (0x078)
> +#define ARSR_POST_SHARP_CFG9 (0x07C)
> +#define ARSR_POST_SHARP_CFG10 (0x080)
> +#define ARSR_POST_SHARP_CFG11 (0x084)
> +#define ARSR_POST_DIFF_CTRL (0x088)
> +#define ARSR_POST_SKIN_SLOP_Y (0x08C)
> +#define ARSR_POST_SKIN_SLOP_U (0x090)
> +#define ARSR_POST_SKIN_SLOP_V (0x094)
> +#define ARSR_POST_FORCE_CLK_ON_CFG (0x098)
> +#define ARSR_POST_DEBUG_RW_0 (0x09C)
> +#define ARSR_POST_DEBUG_RW_1 (0x0A0)
> +#define ARSR_POST_DEBUG_RW_2 (0x0A4)
> +#define ARSR_POST_DEBUG_RO_0 (0x0A8)
> +#define ARSR_POST_DEBUG_RO_1 (0x0AC)
> +#define ARSR_POST_DEBUG_RO_2 (0x0B0)
> +
> +/* BIT EXT */
> +
> +/* GAMA PRE LUT */
> +#define U_GAMA_PRE_R_COEF	(0x000)
> +#define U_GAMA_PRE_G_COEF	(0x400)
> +#define U_GAMA_PRE_B_COEF	(0x800)
> +#define U_GAMA_PRE_R_LAST_COEF (0x200)
> +#define U_GAMA_PRE_G_LAST_COEF (0x600)
> +#define U_GAMA_PRE_B_LAST_COEF (0xA00)
> +
> +/* ACM LUT */
> +#define ACM_U_ACM_SATR_FACE_COEF (0x500)
> +#define ACM_U_ACM_LTA_COEF (0x580)
> +#define ACM_U_ACM_LTR0_COEF (0x600)
> +#define ACM_U_ACM_LTR1_COEF (0x640)
> +#define ACM_U_ACM_LTR2_COEF (0x680)
> +#define ACM_U_ACM_LTR3_COEF (0x6C0)
> +#define ACM_U_ACM_LTR4_COEF (0x700)
> +#define ACM_U_ACM_LTR5_COEF (0x740)
> +#define ACM_U_ACM_LTR6_COEF (0x780)
> +#define ACM_U_ACM_LTR7_COEF (0x7C0)
> +#define ACM_U_ACM_LH0_COFF (0x800)
> +#define ACM_U_ACM_LH1_COFF (0x880)
> +#define ACM_U_ACM_LH2_COFF (0x900)
> +#define ACM_U_ACM_LH3_COFF (0x980)
> +#define ACM_U_ACM_LH4_COFF (0xA00)
> +#define ACM_U_ACM_LH5_COFF (0xA80)
> +#define ACM_U_ACM_LH6_COFF (0xB00)
> +#define ACM_U_ACM_LH7_COFF (0xB80)
> +#define ACM_U_ACM_CH0_COFF (0xC00)
> +#define ACM_U_ACM_CH1_COFF (0xC80)
> +#define ACM_U_ACM_CH2_COFF (0xD00)
> +#define ACM_U_ACM_CH3_COFF (0xD80)
> +#define ACM_U_ACM_CH4_COFF (0xE00)
> +#define ACM_U_ACM_CH5_COFF (0xE80)
> +#define ACM_U_ACM_CH6_COFF (0xF00)
> +#define ACM_U_ACM_CH7_COFF (0xF80)
> +
> +/* LCP LUT */
> +#define GMP_U_GMP_COEF	(0x0000)
> +
> +#define U_DEGAMA_R_COEF	(0x0000)
> +#define U_DEGAMA_G_COEF	(0x0400)
> +#define U_DEGAMA_B_COEF	(0x0800)
> +#define U_DEGAMA_R_LAST_COEF (0x0200)
> +#define U_DEGAMA_G_LAST_COEF (0x0600)
> +#define U_DEGAMA_B_LAST_COEF (0x0A00)
> +
> +/* ARSR1P LUT for ES */
> +#define ARSR1P_LSC_GAIN_ES		(0x084)  /* 0xB07C+0x4*range27 */
> +#define ARSR1P_COEFF_H_Y0_ES	(0x0F0)  /* 0xB0E8+0x4*range9 */
> +#define ARSR1P_COEFF_H_Y1_ES	(0x114)  /* 0xB10C+0x4*range9 */
> +#define ARSR1P_COEFF_V_Y0_ES	(0x138)  /* 0xB130+0x4*range9 */
> +#define ARSR1P_COEFF_V_Y1_ES	(0x15C)  /* 0xB154+0x4*range9 */
> +#define ARSR1P_COEFF_H_UV0_ES	(0x180)  /* 0xB178+0x4*range9 */
> +#define ARSR1P_COEFF_H_UV1_ES	(0x1A4)  /* 0xB19C+0x4*range9 */
> +#define ARSR1P_COEFF_V_UV0_ES	(0x1C8)  /* 0xB1C0+0x4*range9 */
> +#define ARSR1P_COEFF_V_UV1_ES	(0x1EC)  /* 0xB1E4+0x4*range9 */
> +
> +/* ARSR1P LUT */
> +#define ARSR_POST_COEFF_H_Y0	(0x0F0)  /* 0xB0E8+0x4*range9 */
> +#define ARSR_POST_COEFF_H_Y1	(0x114)  /* 0xB10C+0x4*range9 */
> +#define ARSR_POST_COEFF_V_Y0	(0x138)  /* 0xB130+0x4*range9 */
> +#define ARSR_POST_COEFF_V_Y1	(0x15C)  /* 0xB154+0x4*range9 */
> +#define ARSR_POST_COEFF_H_UV0	(0x180)  /* 0xB178+0x4*range9 */
> +#define ARSR_POST_COEFF_H_UV1	(0x1A4)  /* 0xB19C+0x4*range9 */
> +#define ARSR_POST_COEFF_V_UV0	(0x1C8)  /* 0xB1C0+0x4*range9 */
> +#define ARSR_POST_COEFF_V_UV1	(0x1EC)  /* 0xB1E4+0x4*range9 */
> +
> +/* DPE */
> +#define DPE_INT_STAT (0x0000)
> +#define DPE_INT_UNMASK (0x0004)
> +#define DPE_BYPASS_ACE (0x0008)
> +#define DPE_BYPASS_ACE_STAT (0x000c)
> +#define DPE_UPDATE_LOCAL (0x0010)
> +#define DPE_LOCAL_VALID (0x0014)
> +#define DPE_GAMMA_AB_SHADOW (0x0018)
> +#define DPE_GAMMA_AB_WORK (0x001c)
> +#define DPE_GLOBAL_HIST_AB_SHADOW (0x0020)
> +#define DPE_GLOBAL_HIST_AB_WORK (0x0024)
> +#define DPE_IMAGE_INFO (0x0030)
> +#define DPE_HALF_BLOCK_INFO (0x0034)
> +#define DPE_XYWEIGHT (0x0038)
> +#define DPE_LHIST_SFT (0x003c)
> +#define DPE_ROI_START_POINT (0x0040)
> +#define DPE_ROI_WIDTH_HIGH (0x0044)
> +#define DPE_ROI_MODE_CTRL (0x0048)
> +#define DPE_ROI_HIST_STAT_MODE (0x004c)
> +#define DPE_HUE (0x0050)
> +#define DPE_SATURATION (0x0054)
> +#define DPE_VALUE (0x0058)
> +#define DPE_SKIN_GAIN (0x005c)
> +#define DPE_UP_LOW_TH (0x0060)
> +#define DPE_RGB_BLEND_WEIGHT (0x0064)
> +#define DPE_FNA_STATISTIC (0x0068)
> +#define DPE_UP_CNT (0x0070)
> +#define DPE_LOW_CNT (0x0074)
> +#define DPE_SUM_SATURATION (0x0078)
> +#define DPE_GLOBAL_HIST_LUT_ADDR (0x0080)
> +#define DPE_LHIST_EN (0x0100)
> +#define DPE_LOCAL_HIST_VxHy_2z_2z1 (0x0104)
> +#define DPE_GAMMA_EN (0x0108)
> +#define DPE_GAMMA_W (0x0108)
> +#define DPE_GAMMA_R (0x0110)
> +#define DPE_GAMMA_VxHy_3z2_3z1_3z_W (0x010c)
> +#define DPE_GAMMA_EN_HV_R (0x0110)
> +#define DPE_GAMMA_VxHy_3z2_3z1_3z_R (0x0114)
> +#define DPE_INIT_GAMMA (0x0120)
> +#define DPE_MANUAL_RELOAD (0x0124)
> +#define DPE_RAMCLK_FUNC (0x0128)
> +#define DPE_CLK_GATE (0x012c)
> +#define DPE_GAMMA_RAM_A_CFG_MEM_CTRL (0x0130)
> +#define DPE_GAMMA_RAM_B_CFG_MEM_CTRL (0x0134)
> +#define DPE_LHIST_RAM_CFG_MEM_CTRL (0x0138)
> +#define DPE_GAMMA_RAM_A_CFG_PM_CTRL (0x0140)
> +#define DPE_GAMMA_RAM_B_CFG_PM_CTRL (0x0144)
> +#define DPE_LHIST_RAM_CFG_PM_CTRL (0x0148)
> +#define DPE_SAT_GLOBAL_HIST_LUT_ADDR (0x0180)
> +#define DPE_FNA_EN (0x0200)
> +#define DPE_FNA_ADDR (0x0200)
> +#define DPE_FNA_DATA (0x0204)
> +#define DPE_FNA_VxHy (0x0204)
> +#define DPE_UPDATE_FNA (0x0208)
> +#define DPE_FNA_VALID (0x0210)
> +#define DPE_DB_PIPE_CFG (0x0220)
> +#define DPE_DB_PIPE_EXT_WIDTH (0x0224)
> +#define DPE_DB_PIPE_FULL_IMG_WIDTH (0x0228)
> +#define DPE_ACE_DBG0 (0x0300)
> +#define DPE_ACE_DBG1 (0x0304)
> +#define DPE_ACE_DBG2 (0x0308)
> +#define DPE_BYPASS_NR (0x0400)
> +#define DPE_S3_SOME_BRIGHTNESS01 (0x0410)
> +#define DPE_S3_SOME_BRIGHTNESS23 (0x0414)
> +#define DPE_S3_SOME_BRIGHTNESS4 (0x0418)
> +#define DPE_S3_MIN_MAX_SIGMA (0x0420)
> +#define DPE_S3_GREEN_SIGMA03 (0x0430)
> +#define DPE_S3_GREEN_SIGMA45 (0x0434)
> +#define DPE_S3_RED_SIGMA03 (0x0440)
> +#define DPE_S3_RED_SIGMA45 (0x0444)
> +#define DPE_S3_BLUE_SIGMA03 (0x0450)
> +#define DPE_S3_BLUE_SIGMA45 (0x0454)
> +#define DPE_S3_WHITE_SIGMA03 (0x0460)
> +#define DPE_S3_WHITE_SIGMA45 (0x0464)
> +#define DPE_S3_FILTER_LEVEL (0x0470)
> +#define DPE_S3_SIMILARITY_COEFF (0x0474)
> +#define DPE_S3_V_FILTER_WEIGHT_ADJ (0x0478)
> +#define DPE_S3_HUE (0x0480)
> +#define DPE_S3_SATURATION (0x0484)
> +#define DPE_S3_VALUE (0x0488)
> +#define DPE_S3_SKIN_GAIN (0x048c)
> +#define DPE_NR_RAMCLK_FUNC (0x0490)
> +#define DPE_NR_CLK_GATE (0x0494)
> +#define DPE_NR_RAM_A_CFG_MEM_CTRL (0x0498)
> +#define DPE_NR_RAM_A_CFG_PM_CTRL (0x049c)
> +
> +/* IFBC */
> +
> +/* LDI */
> +#define LDI_DP_DSI_SEL		(0x0080)
> +
> +/* MIPI DSI */
> +
> +#define AUTO_ULPS_MODE	(0x00E0)
> +#define AUTO_ULPS_ENTER_DELAY	(0x00E4)
> +#define AUTO_ULPS_WAKEUP_TIME	(0x00E8)
> +#define AUTO_ULPS_MIN_TIME  (0xF8)
> +#define DSI_MEM_CTRL  (0x0194)
> +#define DSI_PM_CTRL  (0x0198)
> +#define DSI_DEBUG  (0x019C)
> +
> +/* MMBUF */
> +
> +/* MEDIA_CRG */
> +#define MEDIA_PEREN0	(0x000)
> +#define MEDIA_PERDIS0	(0x004)
> +#define MEDIA_PERDIS1	(0x014)
> +#define MEDIA_PERDIS2	(0x024)
> +#define MEDIA_PERRSTEN0	(0x030)
> +#define MEDIA_PERRSTDIS0	(0x034)
> +#define MEDIA_PERRSTDIS1	(0x040)
> +#define MEDIA_CLKDIV8  (0x080)
> +#define MEDIA_CLKDIV9  (0x084)
> +#define MEDIA_PEREN1	(0x010)
> +#define MEDIA_PEREN2	(0x020)
> +#define PERRSTEN_GENERAL_SEC (0xA00)
> +#define PERRSTDIS_GENERAL_SEC (0xA04)
> +
> +#endif
> diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_dpe.h b/drivers/staging/hikey9xx/gpu/kirin9xx_dpe.h
> new file mode 100644
> index 000000000000..26add227c389
> --- /dev/null
> +++ b/drivers/staging/hikey9xx/gpu/kirin9xx_dpe.h
> @@ -0,0 +1,2457 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +/*
> + * Copyright (c) 2016 Linaro Limited.
> + * Copyright (c) 2014-2016 Hisilicon Limited.
> + * Copyright (c) 2014-2020, Huawei Technologies Co., Ltd
> + */
> +
> +#ifndef __KIRIN_DPE_H__
> +#define __KIRIN_DPE_H__
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/string.h>
> +#include <linux/platform_device.h>
> +#include <linux/device.h>
> +#include <linux/kernel.h>
> +#include <linux/wait.h>
> +#include <linux/bug.h>
> +#include <linux/iommu.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/regulator/driver.h>
> +#include <linux/regulator/machine.h>
> +
> +#include <drm/drm_plane.h>
> +#include <drm/drm_crtc.h>
Reduce headers to what is necessary.
This seems to be a common pattern.
Each header file shall include only what is required by that header
file. And .c file shall include the header file they need.

Note - for a poitner use forward and do not incldue the header.

> +
> +/* vcc name */
> +#define REGULATOR_PDP_NAME	"ldo3"

...

> +struct mipi_ifbc_division {
> +	u32 xres_div;
> +	u32 yres_div;
> +	u32 comp_mode;
> +	u32 pxl0_div2_gt_en;
> +	u32 pxl0_div4_gt_en;
> +	u32 pxl0_divxcfg;
> +	u32 pxl0_dsi_gt_en;
> +};

...

> +
> +/*****************************************************************************/
> +
> +#define to_dss_crtc(crtc) container_of(crtc, struct dss_crtc, base)
> +#define to_dss_plane(plane) container_of(plane, struct dss_plane, base)

These upcasts belongs to the header file that contains the struct that
they upcast too. So thay should be next to struct dss_crtc and struct
dss_plane.

> +
> +#endif
> diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dpe_utils.c b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dpe_utils.c
> new file mode 100644
> index 000000000000..5669914697a1
> --- /dev/null
> +++ b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dpe_utils.c
> @@ -0,0 +1,912 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
> + * Copyright (c) 2013-2020, Huawei Technologies Co., Ltd
> + */
> +#include <drm/drm_drv.h>
> +#include <drm/drm_mipi_dsi.h>
> +
> +#include "kirin9xx_drm_dpe_utils.h"
> +#include "kirin9xx_dpe.h"
> +
> +struct mipi_ifbc_division g_mipi_ifbc_division[MIPI_DPHY_NUM][IFBC_TYPE_MAX] = {
Only used in this file => static

> +	/* single mipi */
> +	{
> +			/* none */
> +		{
> +			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
> +		}, {
> +			/* orise2x */
> +			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
> +		}, {
> +			/* orise3x */
> +			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
> +		}, {
> +			/* himax2x */
> +			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
> +		}, {
> +			/* rsp2x */
> +			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
> +		}, {
> +			/*
> +			 * rsp3x
> +			 * NOTE: in reality: xres_div = 1.5, yres_div = 2,
> +			 * amended in "mipi_ifbc_get_rect" function
> +			 */
> +			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
> +		}, {
> +			/* vesa2x_1pipe */
> +			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
> +		}, {
> +			/* vesa3x_1pipe */
> +			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
> +		}, {
> +			/* vesa2x_2pipe */
> +			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
> +		}, {
> +			/* vesa3x_2pipe */
> +			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
> +		}
> +
> +	/* dual mipi */
> +	}, {
> +		{
> +			/* none */
> +			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
> +		}, {
> +			/* orise2x */
> +			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
> +		}, {
> +			/* orise3x */
> +			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
> +		}, {
> +			/* himax2x */
> +			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
> +		}, {
> +			/* rsp2x */
> +			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
> +		}, {
> +			/* rsp3x */
> +			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
> +		}, {
> +			/* vesa2x_1pipe */
> +			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
> +		}, {
> +			/* vesa3x_1pipe */
> +			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
> +		}, {
> +			/* vesa2x_2pipe */
> +			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
> +		}, {
> +			/* vesa3x_2pipe */
> +			XRES_DIV_6, YRES_DIV_1, IFBC_COMP_MODE_6, PXL0_DIV2_GT_EN_OPEN,
> +			PXL0_DIV4_GT_EN_CLOSE, PXL0_DIVCFG_5, 3
> +		}
> +	}
> +};
> +
> +u32 set_bits32(u32 old_val, uint32_t val, uint8_t bw, uint8_t bs)
Not used - can be deleted. Remember to delete prototype in header file.

> +{
> +	u32 mask = (1UL << bw) - 1UL;
> +	u32 tmp = 0;
> +
> +	tmp = old_val;
> +	tmp &= ~(mask << bs);
> +
> +	return (tmp | ((val & mask) << bs));
> +}
> +
> +static int mipi_ifbc_get_rect(struct dss_hw_ctx *ctx, struct dss_rect *rect)
> +{
> +	u32 ifbc_type;
> +	u32 mipi_idx;
> +	u32 xres_div;
> +	u32 yres_div;
> +
> +	ifbc_type = IFBC_TYPE_NONE;
> +	mipi_idx = 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)
> +		drm_err(ctx->dev,
> +			"xres(%d) is not division_h(%d) pixel aligned!\n",
> +			rect->w, xres_div);
> +
> +	if ((rect->h % yres_div) > 0)
> +		drm_err(ctx->dev,
> +			"yres(%d) is not division_v(%d) pixel aligned!\n",
> +			rect->h, yres_div);
> +
> +	/*
> +	 * NOTE: rsp3x && single_mipi CMD mode amended xres_div = 1.5,
> +	 *  yres_div = 2,
> +	 * VIDEO mode amended xres_div = 3, yres_div = 1
> +	 */
> +	rect->w /= xres_div;
> +	rect->h /= yres_div;
> +
> +	return 0;
> +}
> +
> +static void init_ldi_pxl_div(struct dss_crtc *acrtc)
> +{
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +	char __iomem *ldi_base;
> +	struct drm_display_mode *mode;
> +	struct drm_display_mode *adj_mode;
> +
> +	u32 ifbc_type = 0;
> +	u32 mipi_idx = 0;
> +	u32 pxl0_div2_gt_en = 0;
> +	u32 pxl0_div4_gt_en = 0;
> +	u32 pxl0_divxcfg = 0;
> +	u32 pxl0_dsi_gt_en = 0;
> +
> +	mode = &acrtc->base.state->mode;
> +	adj_mode = &acrtc->base.state->adjusted_mode;
> +
> +	ldi_base = ctx->base + DSS_LDI0_OFFSET;
> +
> +	ifbc_type = IFBC_TYPE_NONE;
> +	mipi_idx = 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_other(struct dss_crtc *acrtc)
Only used in this file => static
(And drop prototype in header file)

> +{
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +	char __iomem *dss_base = ctx->base;
> +
> +	/**
> +	 * VESA_CLK_SEL is set to 0 for initial,
> +	 * 1 is needed only by vesa dual pipe compress
> +	 */
> +	set_reg(dss_base + DSS_LDI0_OFFSET + LDI_VESA_CLK_SEL, 0, 1, 0);
> +}
> +
> +void init_ldi(struct dss_crtc *acrtc)
Only used in this file => static
(And drop prototype in header file)

> +{
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +	char __iomem *ldi_base;
> +	struct drm_display_mode *mode;
> +	struct drm_display_mode *adj_mode;
> +
> +	struct dss_rect rect = {0, 0, 0, 0};
> +	u32 hfp, hbp, hsw, vfp, vbp, vsw;
> +	u32 vsync_plr = 0;
> +	u32 hsync_plr = 0;
> +	u32 pixelclk_plr = 0;
> +	u32 data_en_plr = 0;
> +
> +	mode = &acrtc->base.state->mode;
> +	adj_mode = &acrtc->base.state->adjusted_mode;
> +
> +	hfp = mode->hsync_start - mode->hdisplay;
> +	hbp = mode->htotal - mode->hsync_end;
> +	hsw = mode->hsync_end - mode->hsync_start;
> +	vfp = mode->vsync_start - mode->vdisplay;
> +	vbp = mode->vtotal - mode->vsync_end;
> +	vsw = mode->vsync_end - mode->vsync_start;
> +
> +	ldi_base = ctx->base + DSS_LDI0_OFFSET;
> +
> +	rect.x = 0;
> +	rect.y = 0;
> +	rect.w = mode->hdisplay;
> +	rect.h = mode->vdisplay;
> +	mipi_ifbc_get_rect(ctx, &rect);
> +
> +	init_ldi_pxl_div(acrtc);
> +
> +	writel(hfp | ((hbp + DSS_WIDTH(hsw)) << 16),
> +	       ldi_base + LDI_DPI0_HRZ_CTRL0);
> +	writel(0, ldi_base + LDI_DPI0_HRZ_CTRL1);
> +	writel(DSS_WIDTH(rect.w), ldi_base + LDI_DPI0_HRZ_CTRL2);
> +	writel(vfp | (vbp << 16), ldi_base + LDI_VRT_CTRL0);
> +	writel(DSS_HEIGHT(vsw), ldi_base + LDI_VRT_CTRL1);
> +	writel(DSS_HEIGHT(rect.h), ldi_base + LDI_VRT_CTRL2);
> +
> +	writel(vsync_plr | (hsync_plr << 1) | (pixelclk_plr << 2) | (data_en_plr << 3),
> +	       ldi_base + LDI_PLR_CTRL);
> +
> +	/* bpp */
> +	set_reg(ldi_base + LDI_CTRL, acrtc->out_format, 2, 3);
> +	/* bgr */
> +	set_reg(ldi_base + LDI_CTRL, acrtc->bgr_fmt, 1, 13);
> +
> +	/* for ddr pmqos */
> +	writel(vfp, ldi_base + LDI_VINACT_MSK_LEN);
> +
> +	/* cmd event sel */
> +	writel(0x1, ldi_base + LDI_CMD_EVENT_SEL);
> +
> +	/* for 1Hz LCD and mipi command LCD */
> +	set_reg(ldi_base + LDI_DSI_CMD_MOD_CTRL, 0x1, 1, 1);
> +
> +	/* ldi_data_gate(ctx, true); */
> +
> +	/* normal */
> +	set_reg(ldi_base + LDI_WORK_MODE, 0x1, 1, 0);
> +
> +	/* ldi disable */
> +	set_reg(ldi_base + LDI_CTRL, 0x0, 1, 0);
> +}
> +
> +void deinit_ldi(struct dss_crtc *acrtc)
Only used in this file => static
(And drop prototype in header file)

> +{
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +	char __iomem *ldi_base;
> +
> +	ldi_base = ctx->base + DSS_LDI0_OFFSET;
> +
> +	/* ldi disable */
> +	set_reg(ldi_base + LDI_CTRL, 0, 1, 0);
> +}
> +
> +void init_dbuf(struct dss_crtc *acrtc)
Only used in this file => static
(And drop prototype in header file)

> +{
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +	struct drm_display_mode *mode;
> +	struct drm_display_mode *adj_mode;
> +	char __iomem *dbuf_base;
> +
> +	int sram_valid_num = 0;
> +	int sram_max_mem_depth = 0;
> +	int sram_min_support_depth = 0;
> +
> +	u32 thd_rqos_in = 0;
> +	u32 thd_rqos_out = 0;
> +	u32 thd_wqos_in = 0;
> +	u32 thd_wqos_out = 0;
> +	u32 thd_cg_in = 0;
> +	u32 thd_cg_out = 0;
> +	u32 thd_wr_wait = 0;
> +	u32 thd_cg_hold = 0;
> +	u32 thd_flux_req_befdfs_in = 0;
> +	u32 thd_flux_req_befdfs_out = 0;
> +	u32 thd_flux_req_aftdfs_in = 0;
> +	u32 thd_flux_req_aftdfs_out = 0;
> +	u32 thd_dfs_ok = 0;
> +	u32 dfs_ok_mask = 0;
> +	u32 thd_flux_req_sw_en = 1;
> +	u32 hfp, hbp, hsw, vfp, vbp, vsw;
> +
> +	int dfs_time = 0;
> +	int dfs_time_min = 0;
> +	int depth = 0;
> +	int dfs_ram = 0;
> +
> +	mode = &acrtc->base.state->mode;
> +	adj_mode = &acrtc->base.state->adjusted_mode;
> +
> +	hfp = mode->hsync_start - mode->hdisplay;
> +	hbp = mode->htotal - mode->hsync_end;
> +	hsw = mode->hsync_end - mode->hsync_start;
> +	vfp = mode->vsync_start - mode->vdisplay;
> +	vbp = mode->vtotal - mode->vsync_end;
> +	vsw = mode->vsync_end - mode->vsync_start;
> +
> +	dbuf_base = ctx->base + DSS_DBUF0_OFFSET;
> +
> +	if (mode->hdisplay * mode->vdisplay >= RES_4K_PHONE) {
> +		dfs_time_min = DFS_TIME_MIN_4K;
> +		dfs_ram = 0x0;
> +	} else {
> +		dfs_time_min = DFS_TIME_MIN;
> +		dfs_ram = 0xF00;
> +	}
> +
> +	dfs_time = DFS_TIME;
> +	depth = DBUF0_DEPTH;
> +
> +	/*
> +	 * int K = 0;
> +	 * int Tp = 1000000  / adj_mode->clock;
> +	 * K = (hsw + hbp + mode->hdisplay +
> +	 *	hfp) / mode->hdisplay;
> +	 * thd_cg_out = dfs_time / (Tp * K * 6);
> +	 */
> +	thd_cg_out = (dfs_time * adj_mode->clock * 1000UL * mode->hdisplay) /
> +		     (((hsw + hbp + hfp) + mode->hdisplay) * 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 * mode->hdisplay / (1000000 / 60 / (mode->vdisplay +
> +				 vbp + vfp + vsw) * (DBUF_WIDTH_BIT / 3 / BITS_PER_BYTE));
> +
> +	thd_flux_req_aftdfs_in = (sram_max_mem_depth - sram_min_support_depth) / 3;
> +	thd_flux_req_aftdfs_out = 2 * (sram_max_mem_depth - sram_min_support_depth) / 3;
> +
> +	thd_dfs_ok = thd_flux_req_befdfs_in;
> +
> +	writel(mode->hdisplay * mode->vdisplay, dbuf_base + DBUF_FRM_SIZE);
> +	writel(DSS_WIDTH(mode->hdisplay), dbuf_base + DBUF_FRM_HSIZE);
> +	writel(sram_valid_num, dbuf_base + DBUF_SRAM_VALID_NUM);
> +
> +	writel((thd_rqos_out << 16) | thd_rqos_in, dbuf_base + DBUF_THD_RQOS);
> +	writel((thd_wqos_out << 16) | thd_wqos_in, dbuf_base + DBUF_THD_WQOS);
> +	writel((thd_cg_out << 16) | thd_cg_in, dbuf_base + DBUF_THD_CG);
> +	writel((thd_cg_hold << 16) | thd_wr_wait, dbuf_base + DBUF_THD_OTHER);
> +	writel((thd_flux_req_befdfs_out << 16) | thd_flux_req_befdfs_in,
> +	       dbuf_base + DBUF_THD_FLUX_REQ_BEF);
> +	writel((thd_flux_req_aftdfs_out << 16) | thd_flux_req_aftdfs_in,
> +	       dbuf_base + DBUF_THD_FLUX_REQ_AFT);
> +	writel(thd_dfs_ok, dbuf_base + DBUF_THD_DFS_OK);
> +	writel((dfs_ok_mask << 1) | thd_flux_req_sw_en,
> +	       dbuf_base + DBUF_FLUX_REQ_CTRL);
> +
> +	writel(0x1, dbuf_base + DBUF_DFS_LP_CTRL);
> +	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970)
> +		writel(dfs_ram, dbuf_base + DBUF_DFS_RAM_MANAGE);
> +}
> +
> +void init_dpp(struct dss_crtc *acrtc)
Only used in this file => static
(And drop prototype in header file)

> +{
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +	struct drm_display_mode *mode;
> +	struct drm_display_mode *adj_mode;
> +	char __iomem *dpp_base;
> +	char __iomem *mctl_sys_base;
> +
> +	mode = &acrtc->base.state->mode;
> +	adj_mode = &acrtc->base.state->adjusted_mode;
> +
> +	dpp_base = ctx->base + DSS_DPP_OFFSET;
> +	mctl_sys_base = ctx->base + DSS_MCTRL_SYS_OFFSET;
> +
> +	writel((DSS_HEIGHT(mode->vdisplay) << 16) | DSS_WIDTH(mode->hdisplay),
> +	       dpp_base + DPP_IMG_SIZE_BEF_SR);
> +	writel((DSS_HEIGHT(mode->vdisplay) << 16) | DSS_WIDTH(mode->hdisplay),
> +	       dpp_base + DPP_IMG_SIZE_AFT_SR);
> +}
> +
> +void enable_ldi(struct dss_crtc *acrtc)
> +{
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +	char __iomem *ldi_base;
> +
> +	ldi_base = ctx->base + DSS_LDI0_OFFSET;
> +
> +	/* ldi enable */
> +	set_reg(ldi_base + LDI_CTRL, 0x1, 1, 0);
> +}
> +
> +void disable_ldi(struct dss_crtc *acrtc)
> +{
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +	char __iomem *ldi_base;
> +
> +	ldi_base = ctx->base + DSS_LDI0_OFFSET;
> +
> +	/* ldi disable */
> +	set_reg(ldi_base + LDI_CTRL, 0x0, 1, 0);
> +}
> +
> +void dpe_interrupt_clear(struct dss_crtc *acrtc)
> +{
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +	char __iomem *dss_base;
> +	u32 clear;
> +
> +	dss_base = ctx->base;
> +
> +	clear = ~0;
> +	writel(clear, dss_base + GLB_CPU_PDP_INTS);
> +	writel(clear, dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS);
> +	writel(clear, dss_base + DSS_DPP_OFFSET + DPP_INTS);
> +
> +	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_MCTL_INTS);
> +	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_WCH0_INTS);
> +	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_WCH1_INTS);
> +	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_RCH0_INTS);
> +	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_RCH1_INTS);
> +	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_RCH2_INTS);
> +	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_RCH3_INTS);
> +	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_RCH4_INTS);
> +	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_RCH5_INTS);
> +	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_RCH6_INTS);
> +	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_RCH7_INTS);
> +	writel(clear, dss_base + DSS_DBG_OFFSET + DBG_DSS_GLB_INTS);
> +}
> +
> +void dpe_interrupt_unmask(struct dss_crtc *acrtc)
> +{
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +	char __iomem *dss_base;
> +	u32 unmask;
> +
> +	dss_base = ctx->base;
> +
> +	unmask = ~0;
> +	unmask &= ~(BIT_ITF0_INTS | BIT_MMU_IRPT_NS);
> +	writel(unmask, dss_base + GLB_CPU_PDP_INT_MSK);
> +
> +	unmask = ~0;
> +	unmask &= ~(BIT_VSYNC | BIT_LDI_UNFLOW);
> +
> +	writel(unmask, dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK);
> +}
> +
> +void dpe_interrupt_mask(struct dss_crtc *acrtc)
> +{
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +	char __iomem *dss_base;
> +	u32 mask;
> +
> +	dss_base = ctx->base;
> +
> +	mask = ~0;
> +	writel(mask, dss_base + GLB_CPU_PDP_INT_MSK);
> +	writel(mask, dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK);
> +	writel(mask, dss_base + DSS_DPP_OFFSET + DPP_INT_MSK);
> +	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_DSS_GLB_INT_MSK);
> +	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_MCTL_INT_MSK);
> +	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_WCH0_INT_MSK);
> +	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_WCH1_INT_MSK);
> +	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_RCH0_INT_MSK);
> +	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_RCH1_INT_MSK);
> +	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_RCH2_INT_MSK);
> +	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_RCH3_INT_MSK);
> +	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_RCH4_INT_MSK);
> +	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_RCH5_INT_MSK);
> +	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_RCH6_INT_MSK);
> +	writel(mask, dss_base + DSS_DBG_OFFSET + DBG_RCH7_INT_MSK);
> +}
> +
> +int dpe_init(struct dss_crtc *acrtc)
> +{
> +	struct drm_display_mode *mode;
> +	struct drm_display_mode *adj_mode;
> +
> +	mode = &acrtc->base.state->mode;
> +	adj_mode = &acrtc->base.state->adjusted_mode;
> +
> +	init_dbuf(acrtc);
> +	init_dpp(acrtc);
> +	init_other(acrtc);
> +	init_ldi(acrtc);
> +
> +	hisifb_dss_on(acrtc->ctx);
> +	hisi_dss_mctl_on(acrtc->ctx);
> +
> +	hisi_dss_mctl_mutex_lock(acrtc->ctx);
> +
> +	hisi_dss_ovl_base_config(acrtc->ctx, mode->hdisplay, mode->vdisplay);
> +
> +	hisi_dss_mctl_mutex_unlock(acrtc->ctx);
> +
> +	enable_ldi(acrtc);
> +
> +	mdelay(60);
> +
> +	return 0;
> +}
> +
> +int dpe_deinit(struct dss_crtc *acrtc)
> +{
> +	deinit_ldi(acrtc);
> +
> +	return 0;
> +}
> +
> +void dpe_check_itf_status(struct dss_crtc *acrtc)
> +{
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +	char __iomem *mctl_sys_base = ctx->base + DSS_MCTRL_SYS_OFFSET;
> +	int tmp = 0;
> +	int delay_count = 0;
> +	bool is_timeout = true;
> +	int itf_idx = 0;
> +
> +	while (1) {
> +		tmp = readl(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;
> +		}
> +		mdelay(1);
> +		++delay_count;
> +	}
> +
> +	if (is_timeout)
> +		DRM_DEBUG_DRIVER("mctl_itf%d not in idle status,ints=0x%x !\n",
> +				 itf_idx, tmp);
drm_dbg(), same goes for other DRM_DEBUG_DRIVER() uses.
Find drmdevice via acrtc.

> +}
> +
> +void dss_inner_clk_pdp_disable(struct dss_hw_ctx *ctx)
> +{
> +}
> +
> +void dss_inner_clk_pdp_enable(struct dss_hw_ctx *ctx)
> +{
> +	char __iomem *dss_base;
> +
> +	dss_base = ctx->base;
> +
> +	writel(0x00000088, dss_base + DSS_IFBC_OFFSET + IFBC_MEM_CTRL);
> +	writel(0x00000888, dss_base + DSS_DSC_OFFSET + DSC_MEM_CTRL);
> +	writel(0x00000008, dss_base + DSS_LDI0_OFFSET + LDI_MEM_CTRL);
> +	writel(0x00000008, dss_base + DSS_DBUF0_OFFSET + DBUF_MEM_CTRL);
> +	writel(0x00000008, dss_base + DSS_DPP_DITHER_OFFSET + ctx->dither_mem_ctrl);
> +}
> +
> +void dss_inner_clk_common_enable(struct dss_hw_ctx *ctx)
> +{
> +	char __iomem *dss_base = ctx->base;
> +
> +	/* core/axi/mmbuf */
> +	writel(0x00000008, dss_base + DSS_CMDLIST_OFFSET + CMD_MEM_CTRL);  /* cmd mem */
> +
> +	writel(0x00000088,
> +	       dss_base + DSS_RCH_VG0_SCL_OFFSET + SCF_COEF_MEM_CTRL); /* rch_v0 ,scf mem */
> +	writel(0x00000008,
> +	       dss_base + DSS_RCH_VG0_SCL_OFFSET + SCF_LB_MEM_CTRL); /* rch_v0 ,scf mem */
> +	writel(0x00000008,
> +	       dss_base + DSS_RCH_VG0_ARSR_OFFSET + ctx->arsr2p_lb_mem_ctrl); /* rch_v0 ,arsr2p mem */
> +	writel(0x00000008, dss_base + DSS_RCH_VG0_DMA_OFFSET + VPP_MEM_CTRL); /* rch_v0 ,vpp mem */
> +	writel(0x00000008,
> +	       dss_base + DSS_RCH_VG0_DMA_OFFSET + DMA_BUF_MEM_CTRL); /* rch_v0 ,dma_buf mem */
> +	writel(0x00008888, dss_base + DSS_RCH_VG0_DMA_OFFSET + AFBCD_MEM_CTRL); /* rch_v0 ,afbcd mem */
> +
> +	writel(0x00000088,
> +	       dss_base + DSS_RCH_VG1_SCL_OFFSET + SCF_COEF_MEM_CTRL); /* rch_v1 ,scf mem */
> +	writel(0x00000008,
> +	       dss_base + DSS_RCH_VG1_SCL_OFFSET + SCF_LB_MEM_CTRL); /* rch_v1 ,scf mem */
> +	writel(0x00000008,
> +	       dss_base + DSS_RCH_VG1_DMA_OFFSET + DMA_BUF_MEM_CTRL); /* rch_v1 ,dma_buf mem */
> +	writel(0x00008888, dss_base + DSS_RCH_VG1_DMA_OFFSET + AFBCD_MEM_CTRL); /* rch_v1 ,afbcd mem */
> +
> +	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
> +		writel(0x88888888,
> +		       dss_base + DSS_RCH_VG0_DMA_OFFSET + HFBCD_MEM_CTRL);
> +		writel(0x00000888,
> +		       dss_base + DSS_RCH_VG0_DMA_OFFSET + HFBCD_MEM_CTRL_1);
> +		writel(0x88888888,
> +		       dss_base + DSS_RCH_VG1_DMA_OFFSET + HFBCD_MEM_CTRL);
> +		writel(0x00000888,
> +		       dss_base + DSS_RCH_VG1_DMA_OFFSET + HFBCD_MEM_CTRL_1);
> +	} else {
> +		writel(0x00000088,
> +		       dss_base + DSS_RCH_VG2_SCL_OFFSET + SCF_COEF_MEM_CTRL); /* rch_v2 ,scf mem */
> +		writel(0x00000008,
> +		       dss_base + DSS_RCH_VG2_SCL_OFFSET + SCF_LB_MEM_CTRL); /* rch_v2 ,scf mem */
> +	}
> +
> +	writel(0x00000008,
> +	       dss_base + DSS_RCH_VG2_DMA_OFFSET + DMA_BUF_MEM_CTRL); /* rch_v2 ,dma_buf mem */
> +
> +	writel(0x00000088,
> +	       dss_base + DSS_RCH_G0_SCL_OFFSET + SCF_COEF_MEM_CTRL); /* rch_g0 ,scf mem */
> +	writel(0x0000008, dss_base + DSS_RCH_G0_SCL_OFFSET + SCF_LB_MEM_CTRL); /* rch_g0 ,scf mem */
> +	writel(0x00000008,
> +	       dss_base + DSS_RCH_G0_DMA_OFFSET + DMA_BUF_MEM_CTRL); /* rch_g0 ,dma_buf mem */
> +	writel(0x00008888, dss_base + DSS_RCH_G0_DMA_OFFSET + AFBCD_MEM_CTRL); /* rch_g0 ,afbcd mem */
> +
> +	writel(0x00000088,
> +	       dss_base + DSS_RCH_G1_SCL_OFFSET + SCF_COEF_MEM_CTRL); /* rch_g1 ,scf mem */
> +	writel(0x0000008, dss_base + DSS_RCH_G1_SCL_OFFSET + SCF_LB_MEM_CTRL); /* rch_g1 ,scf mem */
> +	writel(0x00000008,
> +	       dss_base + DSS_RCH_G1_DMA_OFFSET + DMA_BUF_MEM_CTRL); /* rch_g1 ,dma_buf mem */
> +	writel(0x00008888, dss_base + DSS_RCH_G1_DMA_OFFSET + AFBCD_MEM_CTRL); /* rch_g1 ,afbcd mem */
> +
> +	writel(0x00000008,
> +	       dss_base + DSS_RCH_D0_DMA_OFFSET + DMA_BUF_MEM_CTRL); /* rch_d0 ,dma_buf mem */
> +	writel(0x00008888, dss_base + DSS_RCH_D0_DMA_OFFSET + AFBCD_MEM_CTRL); /* rch_d0 ,afbcd mem */
> +	writel(0x00000008,
> +	       dss_base + DSS_RCH_D1_DMA_OFFSET + DMA_BUF_MEM_CTRL); /* rch_d1 ,dma_buf mem */
> +	writel(0x00000008,
> +	       dss_base + DSS_RCH_D2_DMA_OFFSET + DMA_BUF_MEM_CTRL); /* rch_d2 ,dma_buf mem */
> +	writel(0x00000008,
> +	       dss_base + DSS_RCH_D3_DMA_OFFSET + DMA_BUF_MEM_CTRL); /* rch_d3 ,dma_buf mem */
> +
> +	writel(0x00000008, dss_base + DSS_WCH0_DMA_OFFSET + DMA_BUF_MEM_CTRL); /* wch0 DMA/AFBCE mem */
> +	writel(0x00000888, dss_base + DSS_WCH0_DMA_OFFSET + AFBCE_MEM_CTRL); /* wch0 DMA/AFBCE mem */
> +	writel(0x00000008, dss_base + DSS_WCH0_DMA_OFFSET + ctx->rot_mem_ctrl); /* wch0 rot mem */
> +	writel(0x00000008, dss_base + DSS_WCH1_DMA_OFFSET + DMA_BUF_MEM_CTRL); /* wch1 DMA/AFBCE mem */
> +	writel(0x00000888, dss_base + DSS_WCH1_DMA_OFFSET + AFBCE_MEM_CTRL); /* wch1 DMA/AFBCE mem */
> +	writel(0x00000008, dss_base + DSS_WCH1_DMA_OFFSET + ctx->rot_mem_ctrl); /* wch1 rot mem */
> +	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
> +		writel(0x00000088,
> +		       dss_base + DSS_WCH1_DMA_OFFSET + WCH_SCF_COEF_MEM_CTRL);
> +		writel(0x00000008,
> +		       dss_base + DSS_WCH1_DMA_OFFSET + WCH_SCF_LB_MEM_CTRL);
> +		writel(0x02605550, dss_base + GLB_DSS_MEM_CTRL);
> +	} else {
> +		writel(0x00000008,
> +		       dss_base + DSS_WCH2_DMA_OFFSET + DMA_BUF_MEM_CTRL); /* wch2 DMA/AFBCE mem */
> +		writel(0x00000008,
> +		       dss_base + DSS_WCH2_DMA_OFFSET + ctx->rot_mem_ctrl); /* wch2 rot mem */
> +	}
> +}
> +
> +int dpe_irq_enable(struct dss_crtc *acrtc)
> +{
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +
> +	if (ctx->irq)
> +		enable_irq(ctx->irq);
> +
> +	return 0;
> +}
> +
> +int dpe_irq_disable(struct dss_crtc *acrtc)
> +{
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +
> +	if (ctx->irq)
> +		disable_irq(ctx->irq);
> +
> +	return 0;
> +}
> +
> +int dpe_common_clk_enable(struct dss_hw_ctx *ctx)
> +{
> +	int ret = 0;
> +	struct clk *clk_tmp;
> +
> +	clk_tmp = ctx->dss_mmbuf_clk;
> +	if (clk_tmp) {
> +		ret = clk_prepare(clk_tmp);
> +		if (ret) {
> +			drm_err(ctx->dev,
> +				" dss_mmbuf_clk clk_prepare failed, error=%d!\n",
> +			        ret);
> +			return -EINVAL;
> +		}
> +
> +		ret = clk_enable(clk_tmp);
> +		if (ret) {
> +			drm_err(ctx->dev,
> +				" dss_mmbuf_clk clk_enable failed, error=%d!\n",
> +	   ret);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	clk_tmp = ctx->dss_axi_clk;
> +	if (clk_tmp) {
> +		ret = clk_prepare(clk_tmp);
> +		if (ret) {
> +			drm_err(ctx->dev,
> +				" dss_axi_clk clk_prepare failed, error=%d!\n",
> +				ret);
> +			return -EINVAL;
> +		}
> +
> +		ret = clk_enable(clk_tmp);
> +		if (ret) {
> +			drm_err(ctx->dev,
> +				" dss_axi_clk clk_enable failed, error=%d!\n",
> +				ret);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	clk_tmp = ctx->dss_pclk_dss_clk;
> +	if (clk_tmp) {
> +		ret = clk_prepare(clk_tmp);
> +		if (ret) {
> +			drm_err(ctx->dev,
> +				" dss_pclk_dss_clk clk_prepare failed, error=%d!\n",
> +				ret);
> +			return -EINVAL;
> +		}
> +
> +		ret = clk_enable(clk_tmp);
> +		if (ret) {
> +			drm_err(ctx->dev,
> +				" dss_pclk_dss_clk clk_enable failed, error=%d!\n",
> +				ret);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +int dpe_common_clk_disable(struct dss_hw_ctx *ctx)
> +{
> +	struct clk *clk_tmp;
> +
> +	clk_tmp = ctx->dss_pclk_dss_clk;
> +	if (clk_tmp) {
> +		clk_disable(clk_tmp);
> +		clk_unprepare(clk_tmp);
> +	}
> +
> +	clk_tmp = ctx->dss_axi_clk;
> +	if (clk_tmp) {
> +		clk_disable(clk_tmp);
> +		clk_unprepare(clk_tmp);
> +	}
> +
> +	clk_tmp = ctx->dss_mmbuf_clk;
> +	if (clk_tmp) {
> +		clk_disable(clk_tmp);
> +		clk_unprepare(clk_tmp);
> +	}
> +
> +	return 0;
> +}
> +
> +int dpe_inner_clk_enable(struct dss_hw_ctx *ctx)
> +{
> +	int ret = 0;
> +	struct clk *clk_tmp;
> +
> +	clk_tmp = ctx->dss_pri_clk;
> +	if (clk_tmp) {
> +		ret = clk_prepare(clk_tmp);
> +		if (ret) {
> +			drm_err(ctx->dev,
> +				" dss_pri_clk clk_prepare failed, error=%d!\n",
> +				ret);
> +			return -EINVAL;
> +		}
> +
> +		ret = clk_enable(clk_tmp);
> +		if (ret) {
> +			drm_err(ctx->dev,
> +				" dss_pri_clk clk_enable failed, error=%d!\n",
> +				ret);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	clk_tmp = ctx->dss_pxl0_clk;
> +	if (clk_tmp) {
> +		ret = clk_prepare(clk_tmp);
> +		if (ret) {
> +			drm_err(ctx->dev,
> +				" dss_pxl0_clk clk_prepare failed, error=%d!\n",
> +				ret);
> +			return -EINVAL;
> +		}
> +
> +		ret = clk_enable(clk_tmp);
> +		if (ret) {
> +			drm_err(ctx->dev, " dss_pxl0_clk clk_enable failed, error=%d!\n",
> +				ret);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +int dpe_inner_clk_disable(struct dss_hw_ctx *ctx)
> +{
> +	struct clk *clk_tmp;
> +
> +	clk_tmp = ctx->dss_pxl0_clk;
> +	if (clk_tmp) {
> +		clk_disable(clk_tmp);
> +		clk_unprepare(clk_tmp);
> +	}
> +
> +	clk_tmp = ctx->dss_pri_clk;
> +	if (clk_tmp) {
> +		clk_disable(clk_tmp);
> +		clk_unprepare(clk_tmp);
> +	}
> +
> +	return 0;
> +}
> +
> +int dpe_set_clk_rate(struct dss_hw_ctx *ctx)
> +{
> +	u64 clk_rate;
> +	int ret = 0;
> +
> +	clk_rate = DEFAULT_DSS_CORE_CLK_RATE_L1;
> +	ret = clk_set_rate(ctx->dss_pri_clk, DEFAULT_DSS_CORE_CLK_RATE_L1);
> +	if (ret < 0) {
> +		drm_err(ctx->dev,
> +			"dss_pri_clk clk_set_rate failed, error=%d!\n", ret);
> +		return -EINVAL;
> +	}
> +	drm_dbg(ctx->dev, "dss_pri_clk:[%llu]->[%llu].\n",
> +		clk_rate, (uint64_t)clk_get_rate(ctx->dss_pri_clk));
> +
> +	clk_rate = DEFAULT_DSS_MMBUF_CLK_RATE_L1;
> +	ret = clk_set_rate(ctx->dss_mmbuf_clk, DEFAULT_DSS_MMBUF_CLK_RATE_L1);
> +	if (ret < 0) {
> +		drm_err(ctx->dev,
> +			"dss_mmbuf clk_set_rate failed, error=%d!\n", ret);
> +		return -EINVAL;
> +	}
> +
> +	drm_dbg(ctx->dev, "dss_mmbuf_clk:[%llu]->[%llu].\n",
> +		clk_rate, (uint64_t)clk_get_rate(ctx->dss_mmbuf_clk));
> +
> +	return ret;
> +}
> +
> +int dpe_set_pixel_clk_rate_on_pll0(struct dss_hw_ctx *ctx)
Not used - delete

> +{
> +	int ret;
> +	u64 clk_rate;
> +
> +	clk_rate = ctx->pxl0_clk_rate_power_off;
> +	ret = clk_set_rate(ctx->dss_pxl0_clk, clk_rate);
> +	if (ret < 0) {
> +		drm_err(ctx->dev,
> +			"dss_pxl0_clk clk_set_rate(%llu) failed, error=%d!\n",
> +			  clk_rate, ret);
> +		return -EINVAL;
> +	}
> +	drm_dbg(ctx->dev, "dss_pxl0_clk:[%llu]->[%llu].\n",
> +		clk_rate, (uint64_t)clk_get_rate(ctx->dss_pxl0_clk));
> +
> +	return ret;
> +}
> +
> +int dpe_set_common_clk_rate_on_pll0(struct dss_hw_ctx *ctx)
Not used - delete
> +{
> +	int ret;
> +	u64 clk_rate;
> +
> +	clk_rate = ctx->dss_mmbuf_clk_rate_power_off;
> +	ret = clk_set_rate(ctx->dss_mmbuf_clk, clk_rate);
> +	if (ret < 0) {
> +		drm_err(ctx->dev,
> +			"dss_mmbuf clk_set_rate(%llu) failed, error=%d!\n",
> +			clk_rate, ret);
> +		return -EINVAL;
> +	}
> +	DRM_INFO("dss_mmbuf_clk:[%llu]->[%llu].\n",
> +		 clk_rate, (uint64_t)clk_get_rate(ctx->dss_mmbuf_clk));
> +
> +	clk_rate = DEFAULT_DSS_CORE_CLK_RATE_POWER_OFF;
> +	ret = clk_set_rate(ctx->dss_pri_clk, clk_rate);
> +	if (ret < 0) {
> +		drm_err(ctx->dev,
> +			"dss_pri_clk clk_set_rate(%llu) failed, error=%d!\n",
> +			clk_rate, ret);
> +		return -EINVAL;
> +	}
> +	drm_dbg(ctx->dev, "dss_pri_clk:[%llu]->[%llu].\n",
> +		clk_rate, (uint64_t)clk_get_rate(ctx->dss_pri_clk));
> +
> +	return ret;
> +}
> diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dpe_utils.h b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dpe_utils.h
> new file mode 100644
> index 000000000000..a3071388a86c
> --- /dev/null
> +++ b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dpe_utils.h
> @@ -0,0 +1,230 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2013-2014, Hisilicon Tech. Co., Ltd. All rights reserved.
> + * Copyright (c) 2013-2020, Huawei Technologies Co., Ltd
> + */
> +
> +#ifndef KIRIN_DRM_DPE_UTILS_H
> +#define KIRIN_DRM_DPE_UTILS_H
> +
> +#include <linux/kernel.h>
> +
> +#include <drm/drm_plane.h>
> +#include <drm/drm_crtc.h>
> +
> +#include "kirin9xx_drm_drv.h"
> +#include "kirin9xx_dpe.h"
> +
> +enum dss_channel {
> +	DSS_CH1 = 0,	/* channel 1 for primary plane */
> +	DSS_CH_NUM
> +};
> +
> +#define PRIMARY_CH	DSS_CH1 /* primary plane */
> +
> +#define HISI_FB_PIXEL_FORMAT_UNSUPPORT 800
> +
> +struct dss_hw_ctx {
> +	struct drm_device *dev;

drm_device is supposed to be embedded in struct dss_hw_ctx, and not a
pointer.

> +	void __iomem *base;
> +	struct regmap *noc_regmap;
> +	struct reset_control *reset;
> +	u32 g_dss_version_tag;
> +
> +	void __iomem *noc_dss_base;
> +	void __iomem *peri_crg_base;
> +	void __iomem *pmc_base;
> +	void __iomem *sctrl_base;
> +	void __iomem *media_crg_base;
> +	void __iomem *pctrl_base;
> +	void __iomem *mmbuf_crg_base;
Not used, delete

> +	void __iomem *pmctrl_base;
> +
> +	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;
Not used - delete.
> +
> +	struct dss_clk_rate *dss_clk;
Not used. Delete struct and this field.

> +
> +	struct regulator *dpe_regulator;
> +	struct regulator *mmbuf_regulator;
Not used - delete.

> +	struct regulator *mediacrg_regulator;
Not used - delete.

> +
> +	bool power_on;
> +	int irq;
> +
> +	wait_queue_head_t vactive0_end_wq;
> +	u32 vactive0_end_flag;
Seems not to be used - delete.

> +	ktime_t vsync_timestamp;
> +	ktime_t vsync_timestamp_prev;
vsync_timestamp is only assinged and vsync_timestamp_prev is not used.
Delete.

I gave up verifying the rest - there is some cleaning to be done here.

> +
> +	struct iommu_domain *mmu_domain;
> +	char __iomem *screen_base;
> +	unsigned long smem_start;
> +	unsigned long screen_size;
> +
> +	/* Version-specific data */
> +	u32 g_dss_module_base[DSS_CHN_MAX_DEFINE][MODULE_CHN_MAX];
> +	u32 g_dss_module_ovl_base[DSS_MCTL_IDX_MAX][MODULE_OVL_MAX];
> +	int g_scf_lut_chn_coef_idx[DSS_CHN_MAX_DEFINE];
> +	u32 g_dss_module_cap[DSS_CHN_MAX_DEFINE][MODULE_CAP_MAX];
> +	u32 g_dss_chn_sid_num[DSS_CHN_MAX_DEFINE];
> +	u32 g_dss_smmu_smrx_idx[DSS_CHN_MAX_DEFINE];
> +	u32 smmu_offset;
> +	u32 afbc_header_addr_align;
> +	u32 dss_mmbuf_clk_rate_power_off;
> +	u32 rot_mem_ctrl;
> +	u32 dither_mem_ctrl;
> +	u32 arsr2p_lb_mem_ctrl;
> +	u32 pxl0_clk_rate_power_off;
> +};
> +
> +void kirin960_dpe_defs(struct dss_hw_ctx *ctx);
> +void kirin970_dpe_defs(struct dss_hw_ctx *ctx);
> +
> +struct dss_clk_rate {
> +	u64 dss_pri_clk_rate;
> +	u64 dss_pclk_dss_rate;
> +	u64 dss_pclk_pctrl_rate;
> +	u64 dss_mmbuf_rate;
> +	u32 dss_voltage_value; /* 0:0.7v, 2:0.8v */
> +	u32 reserved;
> +};
> +
> +struct dss_crtc {
> +	struct drm_crtc base;
> +	struct dss_hw_ctx *ctx;
> +	bool enable;
> +	u32 out_format;
> +	u32 bgr_fmt;
> +};
> +
> +struct dss_plane {
> +	struct drm_plane base;
> +	/* void *ctx; */
> +	void *acrtc;
> +	u8 ch; /* channel */
> +};
> +
> +struct dss_data {
> +	struct dss_crtc acrtc;
> +	struct dss_plane aplane[DSS_CH_NUM];
> +	struct dss_hw_ctx ctx;
> +};
I looks like dss_data should be dropped and the above should be embedded
in struct dss_hw_ctx. This would simplyfy things and it would all be
allocated in one go.

> +
> +struct dss_img {
> +	u32 format;
> +	u32 width;
> +	u32 height;
> +	u32 bpp;		/* bytes per pixel */
> +	u32 buf_size;
> +	u32 stride;
> +	u32 stride_plane1;
> +	u32 stride_plane2;
> +	u64 phy_addr;
> +	u64 vir_addr;
> +	u32 offset_plane1;
> +	u32 offset_plane2;
> +
> +	u64 afbc_header_addr;
> +	u64 afbc_payload_addr;
> +	u32 afbc_header_stride;
> +	u32 afbc_payload_stride;
> +	u32 afbc_scramble_mode;
> +	u32 mmbuf_base;
> +	u32 mmbuf_size;
> +
> +	u32 mmu_enable;
> +	u32 csc_mode;
> +	u32 secure_mode;
> +	s32 shared_fd;
> +	u32 reserved0;
> +};
> +
> +struct dss_rect {
> +	s32 x;
> +	s32 y;
> +	s32 w;
> +	s32 h;
> +};
Hmm, use drm_rect?

> +
> +struct drm_dss_layer {
> +	struct dss_img img;
> +	struct dss_rect src_rect;
> +	struct dss_rect src_rect_mask;
> +	struct dss_rect dst_rect;
> +	u32 transform;
> +	s32 blending;
> +	u32 glb_alpha;
> +	u32 color;		/* background color or dim color */
> +	s32 layer_idx;
> +	s32 chn_idx;
> +	u32 need_cap;
> +	s32 acquire_fence;
> +};
There seems to be some relation between a dss layer and a drm panle
missing somewhere.

> +
> +static inline void set_reg(char __iomem *addr, uint32_t val, uint8_t bw,
> +			   uint8_t bs)
> +{
> +	u32 mask = (1UL << bw) - 1UL;
> +	u32 tmp = 0;
> +
> +	tmp = readl(addr);
> +	tmp &= ~(mask << bs);
> +
> +	writel(tmp | ((val & mask) << bs), addr);
> +}
> +
> +u32 set_bits32(u32 old_val, uint32_t val, uint8_t bw, uint8_t bs);
> +
> +void init_dbuf(struct dss_crtc *acrtc);
> +void init_dpp(struct dss_crtc *acrtc);
> +void init_other(struct dss_crtc *acrtc);
> +void init_ldi(struct dss_crtc *acrtc);
> +
> +void deinit_ldi(struct dss_crtc *acrtc);
> +void enable_ldi(struct dss_crtc *acrtc);
> +void disable_ldi(struct dss_crtc *acrtc);
> +
> +void dss_inner_clk_pdp_enable(struct dss_hw_ctx *ctx);
> +void dss_inner_clk_pdp_disable(struct dss_hw_ctx *ctx);
> +void dss_inner_clk_common_enable(struct dss_hw_ctx *ctx);
> +void dss_inner_clk_common_disable(struct dss_hw_ctx *ctx);
> +void dpe_interrupt_clear(struct dss_crtc *acrtc);
> +void dpe_interrupt_unmask(struct dss_crtc *acrtc);
> +void dpe_interrupt_mask(struct dss_crtc *acrtc);
> +int dpe_common_clk_enable(struct dss_hw_ctx *ctx);
> +int dpe_common_clk_disable(struct dss_hw_ctx *ctx);
> +int dpe_inner_clk_enable(struct dss_hw_ctx *ctx);
> +int dpe_inner_clk_disable(struct dss_hw_ctx *ctx);
> +int dpe_set_clk_rate(struct dss_hw_ctx *ctx);
> +
> +int dpe_irq_enable(struct dss_crtc *acrtc);
> +int dpe_irq_disable(struct dss_crtc *acrtc);
> +
> +int dpe_init(struct dss_crtc *acrtc);
> +int dpe_deinit(struct dss_crtc *acrtc);
> +void dpe_check_itf_status(struct dss_crtc *acrtc);
> +int dpe_set_clk_rate_on_pll0(struct dss_hw_ctx *ctx);
> +int dpe_set_common_clk_rate_on_pll0(struct dss_hw_ctx *ctx);
> +int dpe_set_pixel_clk_rate_on_pll0(struct dss_hw_ctx *ctx);
> +
> +void hisifb_dss_on(struct dss_hw_ctx *ctx);
> +void hisi_dss_mctl_on(struct dss_hw_ctx *ctx);
> +
> +void hisi_dss_unflow_handler(struct dss_hw_ctx *ctx, bool unmask);
> +int hisi_dss_mctl_mutex_lock(struct dss_hw_ctx *ctx);
> +int hisi_dss_mctl_mutex_unlock(struct dss_hw_ctx *ctx);
> +int hisi_dss_ovl_base_config(struct dss_hw_ctx *ctx, u32 xres, u32 yres);
> +
> +u32 hisi_dss_get_channel_formats(struct drm_device *dev, u8 ch, const u32 **formats);
> +
> +void hisi_fb_pan_display(struct drm_plane *plane);
> +
> +u32 dpe_get_format(struct dss_hw_ctx *ctx, u32 pixel_format);
> +
> +#endif

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-20 10:02         ` Laurent Pinchart
@ 2020-08-24 19:29           ` Dave Airlie
  2020-08-25 11:30             ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 42+ messages in thread
From: Dave Airlie @ 2020-08-24 19:29 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Mauro Carvalho Chehab, Neil Armstrong, David Airlie,
	Wanchun Zheng, linuxarm, dri-devel, Andrzej Hajda, Sam Ravnborg,
	driverdevel, Daniel Borkmann, John Fastabend, Xiubin Zhang,
	Wei Xu, Xinliang Liu, Xinwei Kong, Tomi Valkeinen,
	Bogdan Togorean, Jakub Kicinski, Laurentiu Palcu, linux-media,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Liwei Cai, Jesper Dangaard Brouer, Manivannan Sadhasivam,
	Chen Feng, Alexei Starovoitov,
	moderated list:DMA BUFFER SHARING FRAMEWORK, Rob Herring,
	mauro.chehab, Rob Clark, linux-arm-kernel, Greg Kroah-Hartman,
	lkml, Liuyao An, Network Development, Rongrong Zou,
	BPF Mailing List, David S. Miller

On Thu, 20 Aug 2020 at 20:02, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>
> Hi Mauro,
>
> On Thu, Aug 20, 2020 at 09:03:26AM +0200, Mauro Carvalho Chehab wrote:
> > Em Wed, 19 Aug 2020 12:52:06 -0700 John Stultz escreveu:
> > > On Wed, Aug 19, 2020 at 8:31 AM Laurent Pinchart wrote:
> > > > On Wed, Aug 19, 2020 at 05:21:20PM +0200, Sam Ravnborg wrote:
> > > > > On Wed, Aug 19, 2020 at 01:45:28PM +0200, Mauro Carvalho Chehab wrote:
> > > > > > This patch series port the out-of-tree driver for Hikey 970 (which
> > > > > > should also support Hikey 960) from the official 96boards tree:
> > > > > >
> > > > > >    https://github.com/96boards-hikey/linux/tree/hikey970-v4.9
> > > > > >
> > > > > > Based on his history, this driver seems to be originally written
> > > > > > for Kernel 4.4, and was later ported to Kernel 4.9. The original
> > > > > > driver used to depend on ION (from Kernel 4.4) and had its own
> > > > > > implementation for FB dev API.
> > > > > >
> > > > > > As I need to preserve the original history (with has patches from
> > > > > > both HiSilicon and from Linaro),  I'm starting from the original
> > > > > > patch applied there. The remaining patches are incremental,
> > > > > > and port this driver to work with upstream Kernel.
> > > > > >
> > > ...
> > > > > > - Due to legal reasons, I need to preserve the authorship of
> > > > > >   each one responsbile for each patch. So, I need to start from
> > > > > >   the original patch from Kernel 4.4;
> > > ...
> > > > > I do acknowledge you need to preserve history and all -
> > > > > but this patchset is not easy to review.
> > > >
> > > > Why do we need to preserve history ? Adding relevant Signed-off-by and
> > > > Co-developed-by should be enough, shouldn't it ? Having a public branch
> > > > that contains the history is useful if anyone is interested, but I don't
> > > > think it's required in mainline.
> > >
> > > Yea. I concur with Laurent here. I'm not sure what legal reasoning you
> > > have on this but preserving the "absolute" history here is actively
> > > detrimental for review and understanding of the patch set.
> > >
> > > Preserving Authorship, Signed-off-by lines and adding Co-developed-by
> > > lines should be sufficient to provide both atribution credit and DCO
> > > history.
> >
> > I'm not convinced that, from legal standpoint, folding things would
> > be enough. See, there are at least 3 legal systems involved here
> > among the different patch authors:
> >
> >       - civil law;
> >       - common law;
> >       - customary law + common law.
> >
> > Merging stuff altogether from different law systems can be problematic,
> > and trying to discuss this with experienced IP property lawyers will
> > for sure take a lot of time and efforts. I also bet that different
> > lawyers will have different opinions, because laws are subject to
> > interpretation. With that matter I'm not aware of any court rules
> > with regards to folded patches. So, it sounds to me that folding
> > patches is something that has yet to be proofed in courts around
> > the globe.
> >
> > At least for US legal system, it sounds that the Country of
> > origin of a patch is relevant, as they have a concept of
> > "national technology" that can be subject to export regulations.
> >
> > From my side, I really prefer to play safe and stay out of any such
> > legal discussions.
>
> Let's be serious for a moment. If you think there are legal issues in
> taking GPL-v2.0-only patches and squashing them while retaining
> authorship information through tags, the Linux kernel if *full* of that.
> You also routinely modify patches that you commit to the media subsystem
> to fix "small issues".
>
> The country of origin argument makes no sense either, the kernel code
> base if full of code coming from pretty much all country on the planet.
>
> Keeping the patches separate make this hard to review. Please squash
> them.

I'm inclined to agree with Laurent here.

Patches submitted as GPL-v2 with DCO lines and author names/companies
should be fine to be squashed and rearranged,
as long as the DCO and Authorship is kept somewhere in the new patch
that is applied.

Review is more important here.

Dave.

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
       [not found]           ` <20200824180225.1a515b6a@coco.lan>
  2020-08-24 18:45             ` Sam Ravnborg
@ 2020-08-24 21:10             ` Sam Ravnborg
  2020-08-24 21:24             ` Sam Ravnborg
                               ` (2 subsequent siblings)
  4 siblings, 0 replies; 42+ messages in thread
From: Sam Ravnborg @ 2020-08-24 21:10 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Greg Kroah-Hartman, Neil Armstrong, Xinliang Liu, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Laurent Pinchart, devel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	David Airlie, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Laurentiu Palcu, linux-media, devicetree, Liwei Cai,
	Jesper Dangaard Brouer, Manivannan Sadhasivam, Chen Feng,
	Alexei Starovoitov, linaro-mm-sig, Rob Herring, Jakub Kicinski,
	mauro.chehab, Rob Clark, linux-arm-kernel, netdev, linux-kernel,
	Liuyao An, Rongrong Zou, bpf, David S. Miller

Hi Mauro



> kirin9xx_fb_panel.h b/drivers/staging/hikey9xx/gpu/kirin9xx_fb_panel.h
> new file mode 100644
> index 000000000000..a69c20470f1d
> --- /dev/null
> +++ b/drivers/staging/hikey9xx/gpu/kirin9xx_fb_panel.h

This file is not referenced and should be deleted.

	Sam

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
       [not found]           ` <20200824180225.1a515b6a@coco.lan>
  2020-08-24 18:45             ` Sam Ravnborg
  2020-08-24 21:10             ` Sam Ravnborg
@ 2020-08-24 21:24             ` Sam Ravnborg
  2020-08-25 18:11             ` Sam Ravnborg
  2020-08-25 20:21             ` Sam Ravnborg
  4 siblings, 0 replies; 42+ messages in thread
From: Sam Ravnborg @ 2020-08-24 21:24 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Greg Kroah-Hartman, Neil Armstrong, Xinliang Liu, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Laurent Pinchart, devel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	David Airlie, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Laurentiu Palcu, linux-media, devicetree, Liwei Cai,
	Jesper Dangaard Brouer, Manivannan Sadhasivam, Chen Feng,
	Alexei Starovoitov, linaro-mm-sig, Rob Herring, Jakub Kicinski,
	mauro.chehab, Rob Clark, linux-arm-kernel, netdev, linux-kernel,
	Liuyao An, Rongrong Zou, bpf, David S. Miller

Hi Mauro

> Before posting the big patch series again, let me send the new
> version folded into a single patch.

Review 2/N

The way output_poll_changed is used to set gpio_mux to select between
the panel and the HDMI looks strange. But I do not know if there is a
more correct way to do it. Other DRM people would need to help
here if there is a better way to do it.

I looked briefly af suspend/resume.
I think this would benefit from using drm_mode_config_helper_suspend()
and drm_mode_config_helper_resume() but I did not finalize the anlyzis.

Other than this only some small details in the following.

	Sam

>  kirin9xx_drm_drv.c b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.c
> new file mode 100644
> index 000000000000..61b65f8b1ace
> --- /dev/null
> +++ b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.c
> @@ -0,0 +1,277 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Hisilicon Kirin SoCs drm master driver
> + *
> + * Copyright (c) 2016 Linaro Limited.
> + * Copyright (c) 2014-2016 Hisilicon Limited.
> + * Copyright (c) 2014-2020, Huawei Technologies Co., Ltd
> + * Author:
> + *	<cailiwei@hisilicon.com>
> + *	<zhengwanchun@hisilicon.com>
> + */
> +
> +#include <linux/of_platform.h>
> +#include <linux/component.h>
> +#include <linux/of_graph.h>
Sort includes

> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_drv.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_gem_framebuffer_helper.h>
> +#include <drm/drm_of.h>
> +#include <drm/drm_probe_helper.h>
> +#include <drm/drm_vblank.h>
> +#include <drm/drm_managed.h>
Sort includes

> +
> +#include "kirin9xx_dpe.h"
> +#include "kirin9xx_drm_drv.h"
> +
> +static int kirin_drm_kms_cleanup(struct drm_device *dev)
> +{
> +	struct kirin_drm_private *priv = to_drm_private(dev);
> +
> +	if (priv->fbdev)
> +		priv->fbdev = NULL;
> +
> +	drm_kms_helper_poll_fini(dev);
> +	kirin9xx_dss_drm_cleanup(dev);
> +
> +	return 0;
> +}
> +
> +static void kirin_fbdev_output_poll_changed(struct drm_device *dev)
> +{
> +	struct kirin_drm_private *priv = to_drm_private(dev);
> +
> +	dsi_set_output_client(dev);
> +
> +	drm_fb_helper_hotplug_event(priv->fbdev);
> +}
> +
> +static const struct drm_mode_config_funcs kirin_drm_mode_config_funcs = {
> +	.fb_create = drm_gem_fb_create,
> +	.output_poll_changed = kirin_fbdev_output_poll_changed,
> +	.atomic_check = drm_atomic_helper_check,
> +	.atomic_commit = drm_atomic_helper_commit,
> +};
> +
> +static int kirin_drm_kms_init(struct drm_device *dev)
> +{
> +	long kirin_type;
> +	int ret;
> +
> +	dev_set_drvdata(dev->dev, dev);
> +
> +	ret = drmm_mode_config_init(dev);
> +	if (ret)
> +		return ret;
> +
> +	dev->mode_config.min_width = 0;
> +	dev->mode_config.min_height = 0;
> +	dev->mode_config.max_width = 2048;
> +	dev->mode_config.max_height = 2048;
> +	dev->mode_config.preferred_depth = 32;
> +
> +	dev->mode_config.funcs = &kirin_drm_mode_config_funcs;
> +
> +	/* display controller init */
> +	kirin_type = (long)of_device_get_match_data(dev->dev);
> +	if (WARN_ON(!kirin_type))
> +		return -ENODEV;
> +
> +	ret = dss_drm_init(dev, kirin_type);
> +	if (ret)
> +		return ret;
> +
> +	/* bind and init sub drivers */
> +	ret = component_bind_all(dev->dev, dev);
> +	if (ret) {
> +		drm_err(dev, "failed to bind all component.\n");
> +		return ret;
> +	}
> +
> +	/* vblank init */
> +	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
> +	if (ret) {
> +		drm_err(dev, "failed to initialize vblank.\n");
> +		return ret;
> +	}
> +	/* with irq_enabled = true, we can use the vblank feature. */
> +	dev->irq_enabled = true;
> +
> +	/* reset all the states of crtc/plane/encoder/connector */
> +	drm_mode_config_reset(dev);
> +
> +	/* init kms poll for handling hpd */
> +	drm_kms_helper_poll_init(dev);
> +
> +	return 0;
> +}
> +
> +DEFINE_DRM_GEM_CMA_FOPS(kirin_drm_fops);
Move it to right above kirin_drm_driver where it is used

> +
> +static int kirin_drm_connectors_register(struct drm_device *dev)
> +{
> +	struct drm_connector_list_iter conn_iter;
> +	struct drm_connector *failed_connector;
> +	struct drm_connector *connector;
> +	int ret;
> +
> +	mutex_lock(&dev->mode_config.mutex);
> +	drm_connector_list_iter_begin(dev, &conn_iter);
> +	drm_for_each_connector_iter(connector, &conn_iter) {
> +		ret = drm_connector_register(connector);
> +		if (ret) {
> +			failed_connector = connector;
> +			goto err;
> +		}
> +	}
> +	mutex_unlock(&dev->mode_config.mutex);
> +
> +	return 0;
> +
> +err:
> +	drm_connector_list_iter_begin(dev, &conn_iter);
> +	drm_for_each_connector_iter(connector, &conn_iter) {
> +		if (failed_connector == connector)
> +			break;
> +		drm_connector_unregister(connector);
> +	}
> +	mutex_unlock(&dev->mode_config.mutex);
> +
> +	return ret;
> +}
> +
> +static struct drm_driver kirin_drm_driver = {
> +	.driver_features	= DRIVER_GEM | DRIVER_MODESET |
> +				  DRIVER_ATOMIC | DRIVER_RENDER,
> +
> +	.fops			= &kirin_drm_fops,
> +	.name			= "kirin9xx",
> +	.desc			= "Hisilicon Kirin9xx SoCs' DRM Driver",
> +	.date			= "20170309",
> +	.major			= 1,
> +	.minor			= 0,
> +
> +	DRM_GEM_CMA_VMAP_DRIVER_OPS
> +};
Looks good now.

> +
> +
> +static int compare_of(struct device *dev, void *data)
> +{
> +	return dev->of_node == data;
> +}
> +
> +static int kirin_drm_bind(struct device *dev)
> +{
> +	struct kirin_drm_private *priv;
> +	struct drm_device *drm;
> +	int ret;
> +
> +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	drm = &priv->drm;
> +
> +	ret = devm_drm_dev_init(dev, drm, &kirin_drm_driver);
> +	if (ret) {
> +		kfree(priv);
> +		return ret;
> +	}
> +	drmm_add_final_kfree(drm, priv);
> +
> +	ret = kirin_drm_kms_init(drm);
> +	if (ret)
> +		return ret;
> +
> +	ret = drm_dev_register(drm, 0);
> +	if (ret)
> +		return ret;
> +
> +	drm_fbdev_generic_setup(drm, 0);
Should be last - after connector register.

> +
> +	/* connectors should be registered after drm device register */
> +	ret = kirin_drm_connectors_register(drm);
> +	if (ret)
> +		goto err_drm_dev_unregister;
I am rather sure registering connectors are already taken care of by
drm_dev_register(). 
The driver set DRIVER_MODESET so drm_modeset_register_all() is called
which again registers all connectors.

> +
> +	return 0;
> +
> +err_drm_dev_unregister:
> +	drm_dev_unregister(drm);
> +	kirin_drm_kms_cleanup(drm);

> +	drm_dev_put(drm);
Not needed when using drmm_* and embedded drm_device
> +
> +	return ret;
> +}
> +
> +static void kirin_drm_unbind(struct device *dev)
> +{
> +	struct drm_device *drm_dev = dev_get_drvdata(dev);
> +
> +	drm_dev_unregister(drm_dev);
> +	drm_atomic_helper_shutdown(drm_dev);
> +	kirin_drm_kms_cleanup(drm_dev);

> +	drm_dev_put(drm_dev);
Not needed when using drmm_* and embedded drm_device

> +}
> +
> +static const struct component_master_ops kirin_drm_ops = {
> +	.bind = kirin_drm_bind,
> +	.unbind = kirin_drm_unbind,
> +};
> +
> +static int kirin_drm_platform_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct device_node *np = dev->of_node;
> +	struct component_match *match = NULL;
> +	struct device_node *remote;
> +
> +	remote = of_graph_get_remote_node(np, 0, 0);
> +	if (!remote)
> +		return -ENODEV;
> +
> +	drm_of_component_match_add(dev, &match, compare_of, remote);
> +	of_node_put(remote);
> +
> +	return component_master_add_with_match(dev, &kirin_drm_ops, match);
> +}
> +
> +static int kirin_drm_platform_remove(struct platform_device *pdev)
> +{
> +	component_master_del(&pdev->dev, &kirin_drm_ops);
> +	return 0;
> +}
> +
> +static const struct of_device_id kirin_drm_dt_ids[] = {
> +	{ .compatible = "hisilicon,hi3660-dpe",
> +	  .data = (void *)FB_ACCEL_HI366x,
> +	},
> +	{ .compatible = "hisilicon,kirin970-dpe",
> +	  .data = (void *)FB_ACCEL_KIRIN970,
> +	},
> +	{ /* end node */ },
> +};
> +MODULE_DEVICE_TABLE(of, kirin_drm_dt_ids);
> +
> +static struct platform_driver kirin_drm_platform_driver = {
> +	.probe = kirin_drm_platform_probe,
> +	.remove = kirin_drm_platform_remove,
> +	.suspend = kirin9xx_dss_drm_suspend,
> +	.resume = kirin9xx_dss_drm_resume,
> +	.driver = {
> +		.name = "kirin9xx-drm",
> +		.of_match_table = kirin_drm_dt_ids,
> +	},
> +};
> +
> +module_platform_driver(kirin_drm_platform_driver);
> +
> +MODULE_AUTHOR("cailiwei <cailiwei@hisilicon.com>");
> +MODULE_AUTHOR("zhengwanchun <zhengwanchun@hisilicon.com>");
> +MODULE_DESCRIPTION("hisilicon Kirin SoCs' DRM master driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.h b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.h
> new file mode 100644
> index 000000000000..9bfcb35d6fa5
> --- /dev/null
> +++ b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_drv.h
> @@ -0,0 +1,42 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2016 Linaro Limited.
> + * Copyright (c) 2014-2016 Hisilicon Limited.
> + * Copyright (c) 2014-2020, Huawei Technologies Co., Ltd
> + */
> +
> +#ifndef __KIRIN_DRM_DRV_H__
> +#define __KIRIN_DRM_DRV_H__
> +
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_drv.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_print.h>
> +
> +#include <linux/iommu.h>
> +
> +#define MAX_CRTC	2
> +
> +struct kirin_drm_private {
> +	struct drm_device drm;
Hmm, hare we have drm_device embedded - so some comments from previous
review can be ignored - ups.

> +	struct drm_fb_helper *fbdev;
Never assigned - can be deleted.
kirin_fbdev_output_poll_changed() needs to be re-visited as it assumes
fbdev is assigned.

> +	struct drm_crtc *crtc[MAX_CRTC];
> +};
> +
> +struct kirin_fbdev {
> +	struct drm_fb_helper fb_helper;
> +	struct drm_framebuffer *fb;
> +};
struct kirin_fbdev is unused - delete.

> +
> +/* provided by kirin9xx_drm_dss.c */
> +void kirin9xx_dss_drm_cleanup(struct drm_device *dev);
> +int kirin9xx_dss_drm_suspend(struct platform_device *pdev, pm_message_t state);
> +int kirin9xx_dss_drm_resume(struct platform_device *pdev);
> +int dss_drm_init(struct drm_device *dev, u32 g_dss_version_tag);
> +
> +void dsi_set_output_client(struct drm_device *dev);
> +
> +#define to_drm_private(d) container_of(d, struct kirin_drm_private, drm)
> +
> +#endif /* __KIRIN_DRM_DRV_H__ */
> diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dss.c b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dss.c
> new file mode 100644
> index 000000000000..ff93df229868
> --- /dev/null
> +++ b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_dss.c
> @@ -0,0 +1,979 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Hisilicon Hi6220 SoC ADE(Advanced Display Engine)'s crtc&plane driver
> + *
> + * Copyright (c) 2016 Linaro Limited.
> + * Copyright (c) 2014-2016 Hisilicon Limited.
> + * Copyright (c) 2014-2020, Huawei Technologies Co., Ltd
> + *
> + * Author:
> + *	Xinliang Liu <z.liuxinliang@hisilicon.com>
> + *	Xinliang Liu <xinliang.liu@linaro.org>
> + *	Xinwei Kong <kong.kongxinwei@hisilicon.com>
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/clk.h>
> +#include <video/display_timing.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +#include <linux/reset.h>
> +#include <linux/of_address.h>
> +#include <linux/of.h>
> +#include <linux/of_irq.h>
> +
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_drv.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_fourcc.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_plane_helper.h>
> +#include <drm/drm_vblank.h>
> +#include <drm/drm_modeset_helper_vtables.h>
> +
> +#include "kirin9xx_drm_drv.h"
> +#include "kirin9xx_drm_dpe_utils.h"
> +#include "kirin9xx_dpe.h"
> +
> +int hdmi_pxl_ppll7_init(struct dss_hw_ctx *ctx, u64 pixel_clock)
> +{
> +	u64 vco_min_freq_output = KIRIN970_VCO_MIN_FREQ_OUTPUT;
> +	u64 refdiv, fbdiv, frac, postdiv1 = 0, postdiv2 = 0;
> +	u64 dss_pxl0_clk = 7 * 144000000UL;
> +	u64 sys_clock_fref = KIRIN970_SYS_19M2;
> +	u64 ppll7_freq_divider;
> +	u64 vco_freq_output;
> +	u64 frac_range = 0x1000000; /* 2^24 */
> +	u64 pixel_clock_ori;
> +	u64 pixel_clock_cur;
> +	u32 ppll7ctrl0;
> +	u32 ppll7ctrl1;
> +	u32 ppll7ctrl0_val;
> +	u32 ppll7ctrl1_val;
> +	int ceil_temp;
> +	int i, ret;
> +	const int freq_divider_list[22] = {
> +		1,  2,  3,  4,  5,  6,  7,  8,
> +		9, 10, 12, 14, 15, 16, 20, 21,
> +		24, 25, 30, 36, 42, 49
> +	};
> +	const int postdiv1_list[22] = {
> +		1, 2, 3, 4, 5, 6, 7, 4, 3, 5,
> +		4, 7, 5, 4, 5, 7, 6, 5, 6, 6,
> +		7, 7
> +	};
> +	const int postdiv2_list[22] = {
> +		1, 1, 1, 1, 1, 1, 1, 2, 3, 2,
> +		3, 2, 3, 4, 4, 3, 4, 5, 5, 6,
> +		6, 7
> +	};
> +
> +	if (!pixel_clock) {
> +		drm_err(ctx->dev, "Pixel clock can't be zero!\n");
> +		return -EINVAL;
> +	}
> +
> +	pixel_clock_ori = pixel_clock;
> +	pixel_clock_cur = pixel_clock_ori;
> +
> +	if (pixel_clock_ori <= 255000000) {
> +		pixel_clock_cur *= 7;
> +		dss_pxl0_clk /= 7;
> +	} else if (pixel_clock_ori <= 415000000) {
> +		pixel_clock_cur *= 5;
> +		dss_pxl0_clk /= 5;
> +	} else if (pixel_clock_ori <= 594000000) {
> +		pixel_clock_cur *= 3;
> +		dss_pxl0_clk /= 3;
> +	} else {
> +		drm_err(ctx->dev, "Clock not supported!\n");
> +		return -EINVAL;
> +	}
> +
> +	pixel_clock_cur = pixel_clock_cur / 1000;
> +	if (!pixel_clock_cur) {
> +		drm_err(ctx->dev, "pixel_clock_cur can't be zero!\n");
> +		return -EINVAL;
> +	}
> +
> +	ceil_temp = DIV_ROUND_UP(vco_min_freq_output, pixel_clock_cur);
> +
> +	ppll7_freq_divider = (u64)ceil_temp;
> +
> +	for (i = 0; i < ARRAY_SIZE(freq_divider_list); i++) {
> +		if (freq_divider_list[i] >= ppll7_freq_divider) {
> +			ppll7_freq_divider = freq_divider_list[i];
> +			postdiv1 = postdiv1_list[i];
> +			postdiv2 = postdiv2_list[i];
> +			break;
> +		}
> +	}
> +
> +	if (i == ARRAY_SIZE(freq_divider_list)) {
> +		drm_err(ctx->dev, "Can't find a valid setting for PLL7!\n");
> +		return -EINVAL;
> +	}
> +
> +	vco_freq_output = ppll7_freq_divider * pixel_clock_cur;
> +	if (!vco_freq_output) {
> +		drm_err(ctx->dev, "Can't find a valid setting for VCO_FREQ!\n");
> +		return -EINVAL;
> +	}
> +
> +	ceil_temp = DIV_ROUND_UP(400000, vco_freq_output);
> +
> +	refdiv = ((vco_freq_output * ceil_temp) >= 494000) ? 1 : 2;
> +	fbdiv = (vco_freq_output * ceil_temp) * refdiv / sys_clock_fref;
> +
> +	frac = (u64)(ceil_temp * vco_freq_output - sys_clock_fref / refdiv * fbdiv) * refdiv * frac_range;
> +	frac = (u64)frac / sys_clock_fref;
> +
> +	ppll7ctrl0 = readl(ctx->pmctrl_base + MIDIA_PPLL7_CTRL0);
> +	ppll7ctrl0 &= ~MIDIA_PPLL7_FREQ_DEVIDER_MASK;
> +
> +	ppll7ctrl0_val = 0x0;
> +	ppll7ctrl0_val |= (u32)(postdiv2 << 23 | postdiv1 << 20 | fbdiv << 8 | refdiv << 2);
> +	ppll7ctrl0_val &= MIDIA_PPLL7_FREQ_DEVIDER_MASK;
> +	ppll7ctrl0 |= ppll7ctrl0_val;
> +
> +	writel(ppll7ctrl0, ctx->pmctrl_base + MIDIA_PPLL7_CTRL0);
> +
> +	ppll7ctrl1 = readl(ctx->pmctrl_base + MIDIA_PPLL7_CTRL1);
> +	ppll7ctrl1 &= ~MIDIA_PPLL7_FRAC_MODE_MASK;
> +
> +	ppll7ctrl1_val = 0x0;
> +	ppll7ctrl1_val |= (u32)(1 << 25 | 0 << 24 | frac);
> +	ppll7ctrl1_val &= MIDIA_PPLL7_FRAC_MODE_MASK;
> +	ppll7ctrl1 |= ppll7ctrl1_val;
> +
> +	writel(ppll7ctrl1, ctx->pmctrl_base + MIDIA_PPLL7_CTRL1);
> +
> +	drm_dbg(ctx->dev, "PLL7 set to (0x%0x, 0x%0x)\n",
> +		ppll7ctrl0, ppll7ctrl1);
> +
> +	ret = clk_set_rate(ctx->dss_pxl0_clk, dss_pxl0_clk);
> +	if (ret < 0)
> +		drm_err(ctx->dev, "%s: clk_set_rate(dss_pxl0_clk, %llu) failed: %d!\n",
> +			  __func__, dss_pxl0_clk, ret);
> +	else
> +		drm_dbg(ctx->dev, "dss_pxl0_clk:[%llu]->[%lu].\n",
> +			dss_pxl0_clk, clk_get_rate(ctx->dss_pxl0_clk));
> +
> +	return ret;
> +}
> +
> +static u64 dss_calculate_clock(struct dss_crtc *acrtc,
> +			       const struct drm_display_mode *mode)
> +{
> +	u64 clk_Hz;
> +
> +	if (acrtc->ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
> +		if (mode->clock == 148500)
> +			clk_Hz = 144000 * 1000UL;
> +		else if (mode->clock == 83496)
> +			clk_Hz = 84000 * 1000UL;
> +		else if (mode->clock == 74440)
> +			clk_Hz = 72000 * 1000UL;
> +		else if (mode->clock == 74250)
> +			clk_Hz = 72000 * 1000UL;
> +		else
> +			clk_Hz = mode->clock * 1000UL;
> +
> +		/* Adjust pixel clock for compatibility with 10.1 inch special displays. */
> +		if (mode->clock == 148500 && mode->width_mm == 532 && mode->height_mm == 299)
> +			clk_Hz = 152000 * 1000UL;
> +	} else {
> +		if (mode->clock == 148500)
> +			clk_Hz = 144000 * 1000UL;
> +		else if (mode->clock == 83496)
> +			clk_Hz = 80000 * 1000UL;
> +		else if (mode->clock == 74440)
> +			clk_Hz = 72000 * 1000UL;
> +		else if (mode->clock == 74250)
> +			clk_Hz = 72000 * 1000UL;
> +		else
> +			clk_Hz = mode->clock * 1000UL;
> +	}
> +
> +	return clk_Hz;
> +}
> +
> +static void dss_ldi_set_mode(struct dss_crtc *acrtc)
> +{
> +	struct drm_display_mode *adj_mode = &acrtc->base.state->adjusted_mode;
> +	struct drm_display_mode *mode = &acrtc->base.state->mode;
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +	u32 clock = mode->clock;
> +	u64 clk_Hz;
> +	int ret;
> +
> +	clk_Hz = dss_calculate_clock(acrtc, mode);
> +
> +	drm_dbg(ctx->dev, "Requested clock %u kHz, setting to %llu kHz\n",
> +		clock, clk_Hz / 1000);
> +
> +	if (acrtc->ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
> +		ret = hdmi_pxl_ppll7_init(ctx, clk_Hz);
> +	} else {
> +		ret = clk_set_rate(ctx->dss_pxl0_clk, clk_Hz);
> +		if (!ret) {
> +			clk_Hz = clk_get_rate(ctx->dss_pxl0_clk);
> +			drm_dbg(ctx->dev, "dss_pxl0_clk:[%llu]->[%lu].\n",
> +				clk_Hz, clk_get_rate(ctx->dss_pxl0_clk));
> +		}
> +	}
> +
> +	if (ret)
> +		drm_err(ctx->dev, "failed to set pixel clock\n");
> +	else
> +		adj_mode->clock = clk_Hz / 1000;
> +
> +	dpe_init(acrtc);
> +}
> +
> +static int dss_power_up(struct dss_crtc *acrtc)
> +{
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +	int ret = 0;
> +
> +	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
> +		dpe_common_clk_enable(ctx);
> +		dpe_inner_clk_enable(ctx);
> +		dpe_set_clk_rate(ctx);
> +	} else {
> +		ret = clk_prepare_enable(ctx->dss_pxl0_clk);
> +		if (ret) {
> +			drm_err(ctx->dev,
> +				"failed to enable dss_pxl0_clk (%d)\n", ret);
> +			return ret;
> +		}
> +
> +		ret = clk_prepare_enable(ctx->dss_pri_clk);
> +		if (ret) {
> +			drm_err(ctx->dev,
> +				"failed to enable dss_pri_clk (%d)\n", ret);
> +			return ret;
> +		}
> +
> +		ret = clk_prepare_enable(ctx->dss_pclk_dss_clk);
> +		if (ret) {
> +			drm_err(ctx->dev,
> +				"failed to enable dss_pclk_dss_clk (%d)\n", ret);
> +			return ret;
> +		}
> +
> +		ret = clk_prepare_enable(ctx->dss_axi_clk);
> +		if (ret) {
> +			drm_err(ctx->dev,
> +				"failed to enable dss_axi_clk (%d)\n", ret);
> +			return ret;
> +		}
> +
> +		ret = clk_prepare_enable(ctx->dss_mmbuf_clk);
> +		if (ret) {
> +			drm_err(ctx->dev,
> +				"failed to enable dss_mmbuf_clk (%d)\n", ret);
> +			return ret;
> +		}
> +	}
> +
> +	dss_inner_clk_common_enable(ctx);
> +	dss_inner_clk_pdp_enable(ctx);
> +
> +	dpe_interrupt_mask(acrtc);
> +	dpe_interrupt_clear(acrtc);
> +	dpe_irq_enable(acrtc);
> +	dpe_interrupt_unmask(acrtc);
> +
> +	ctx->power_on = true;
> +
> +	return ret;
> +}
> +
> +static void dss_power_down(struct dss_crtc *acrtc)
> +{
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +
> +	dpe_interrupt_mask(acrtc);
> +	dpe_irq_disable(acrtc);
> +	dpe_deinit(acrtc);
> +
> +	dpe_check_itf_status(acrtc);
> +	dss_inner_clk_pdp_disable(ctx);
> +
> +	dpe_inner_clk_disable(ctx);
> +	dpe_common_clk_disable(ctx);
> +
> +	ctx->power_on = false;
> +}
> +
> +static int dss_enable_vblank(struct drm_crtc *crtc)
> +{
> +	struct dss_crtc *acrtc = to_dss_crtc(crtc);
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +
> +	drm_dbg(ctx->dev, "%s\n", __func__);
> +	if (!ctx->power_on) {
> +		drm_dbg(ctx->dev, "Enabling vblank\n");
> +		(void)dss_power_up(acrtc);
> +	}
> +
> +	return 0;
> +}
enable_vblank is supposed to enable interrupts, not a general power up.
Power up should be done by another helper.

> +
> +static void dss_disable_vblank(struct drm_crtc *crtc)
> +{
> +	struct dss_crtc *acrtc = to_dss_crtc(crtc);
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +
> +	drm_dbg(ctx->dev, "%s\n", __func__);
> +	if (!ctx->power_on) {
> +		drm_err(ctx->dev, "power is down! vblank disable fail\n");
> +		return;
> +	}
> +}
Same here, just disable vblank

> +
> +static irqreturn_t dss_irq_handler(int irq, void *data)
> +{
> +	struct dss_crtc *acrtc = data;
> +	struct drm_crtc *crtc = &acrtc->base;
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +	void __iomem *dss_base = ctx->base;
> +
> +	u32 isr_s1 = 0;
> +	u32 isr_s2 = 0;
> +	u32 mask = 0;
> +
> +	isr_s1 = readl(dss_base + GLB_CPU_PDP_INTS);
> +	isr_s2 = readl(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS);
> +
> +	writel(isr_s2, dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INTS);
> +	writel(isr_s1, dss_base + GLB_CPU_PDP_INTS);
> +
> +	isr_s1 &= ~(readl(dss_base + GLB_CPU_PDP_INT_MSK));
> +	isr_s2 &= ~(readl(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK));
> +
> +	if (isr_s2 & BIT_VSYNC) {
> +		ctx->vsync_timestamp = ktime_get();
> +		drm_crtc_handle_vblank(crtc);
> +	}
> +
> +	if (isr_s2 & BIT_LDI_UNFLOW) {
> +		mask = readl(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK);
> +		mask |= BIT_LDI_UNFLOW;
> +		writel(mask, dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK);
> +
> +		drm_err(ctx->dev, "ldi underflow!\n");
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static bool dss_crtc_mode_fixup(struct drm_crtc *crtc,
> +				const struct drm_display_mode *mode,
> +				struct drm_display_mode *adj_mode)
> +{
> +	struct dss_crtc *acrtc = to_dss_crtc(crtc);
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +	u64 clk_Hz;
> +
> +	/* Check if clock is too high */
> +	if (mode->clock > 594000)
> +		return false;
> +	/*
> +	 * FIXME: the code should, instead, do some calculus instead of
> +	 * hardcoding the modes. Clearly, there's something missing at
> +	 * dss_calculate_clock()
> +	 */
> +
> +	/*
> +	 * HACK: reports at Hikey 970 mailing lists with the downstream
> +	 * Official Linaro 4.9 driver seem to indicate that some monitor
> +	 * modes aren't properly set. There, this hack was added.
> +	 *
> +	 * On my monitors, this wasn't needed, but better to keep this
> +	 * code here, together with this notice, just in case.
> +	 */
> +	if ((mode->hdisplay    == 1920 && mode->vdisplay == 1080 && mode->clock == 148500)
> +	    || (mode->hdisplay == 1920 && mode->vdisplay == 1080 && mode->clock == 148352)
> +	    || (mode->hdisplay == 1920 && mode->vdisplay == 1080 && mode->clock ==  80192)
> +	    || (mode->hdisplay == 1920 && mode->vdisplay == 1080 && mode->clock ==  74250)
> +	    || (mode->hdisplay == 1920 && mode->vdisplay == 1080 && mode->clock ==  61855)
> +	    || (mode->hdisplay == 1680 && mode->vdisplay == 1050 && mode->clock == 147116)
> +	    || (mode->hdisplay == 1680 && mode->vdisplay == 1050 && mode->clock == 146250)
> +	    || (mode->hdisplay == 1680 && mode->vdisplay == 1050 && mode->clock == 144589)
> +	    || (mode->hdisplay == 1600 && mode->vdisplay == 1200 && mode->clock == 160961)
> +	    || (mode->hdisplay == 1600 && mode->vdisplay == 900  && mode->clock == 118963)
> +	    || (mode->hdisplay == 1440 && mode->vdisplay == 900  && mode->clock == 126991)
> +	    || (mode->hdisplay == 1280 && mode->vdisplay == 1024 && mode->clock == 128946)
> +	    || (mode->hdisplay == 1280 && mode->vdisplay == 1024 && mode->clock ==  98619)
> +	    || (mode->hdisplay == 1280 && mode->vdisplay == 960  && mode->clock == 102081)
> +	    || (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 ==  78800)
> +	    || (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 ==  48907)
> +	    || (mode->hdisplay == 800  && mode->vdisplay == 600  && mode->clock ==  40000)
> +	    || (mode->hdisplay == 800  && mode->vdisplay == 480  && mode->clock ==  32000)
> +	   ) {
> +		clk_Hz = dss_calculate_clock(acrtc, mode);
> +
> +		/*
> +		 * On Kirin970, PXL0 clock is set to a const value,
> +		 * independently of the pixel clock.
> +		 */
> +		if (acrtc->ctx->g_dss_version_tag != FB_ACCEL_KIRIN970)
> +			clk_Hz = clk_round_rate(ctx->dss_pxl0_clk, mode->clock * 1000);
> +
> +		adj_mode->clock = clk_Hz / 1000;
> +
> +		return true;
> +	}
> +
> +	return false;
> +}
> +
> +static void dss_crtc_enable(struct drm_crtc *crtc,
> +			    struct drm_crtc_state *old_state)
> +{
> +	struct dss_crtc *acrtc = to_dss_crtc(crtc);
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +	int ret;
> +
> +	if (acrtc->enable)
> +		return;
> +
> +	if (!ctx->power_on) {
> +		ret = dss_power_up(acrtc);
> +		if (ret)
> +			return;
> +	}
> +
> +	acrtc->enable = true;
> +	drm_crtc_vblank_on(crtc);
> +}
> +
> +static void dss_crtc_disable(struct drm_crtc *crtc,
> +			     struct drm_crtc_state *old_state)
> +{
> +	struct dss_crtc *acrtc = to_dss_crtc(crtc);
> +
> +	if (!acrtc->enable)
> +		return;
> +
> +	dss_power_down(acrtc);
> +	acrtc->enable = false;
> +	drm_crtc_vblank_off(crtc);
> +}
> +
> +static void dss_crtc_mode_set_nofb(struct drm_crtc *crtc)
> +{
> +	struct dss_crtc *acrtc = to_dss_crtc(crtc);
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +
> +	if (!ctx->power_on)
> +		(void)dss_power_up(acrtc);
> +	dss_ldi_set_mode(acrtc);
> +}
> +
> +static void dss_crtc_atomic_begin(struct drm_crtc *crtc,
> +				  struct drm_crtc_state *old_state)
> +{
> +	struct dss_crtc *acrtc = to_dss_crtc(crtc);
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +
> +	if (!ctx->power_on)
> +		(void)dss_power_up(acrtc);
> +}
> +
> +static void dss_crtc_atomic_flush(struct drm_crtc *crtc,
> +				  struct drm_crtc_state *old_state)
> +
> +{
> +	struct drm_pending_vblank_event *event = crtc->state->event;
> +
> +	if (event) {
> +		crtc->state->event = NULL;
> +
> +		spin_lock_irq(&crtc->dev->event_lock);
> +		if (drm_crtc_vblank_get(crtc) == 0)
> +			drm_crtc_arm_vblank_event(crtc, event);
> +		else
> +			drm_crtc_send_vblank_event(crtc, event);
> +		spin_unlock_irq(&crtc->dev->event_lock);
> +	}
> +}
> +
> +static const struct drm_crtc_helper_funcs dss_crtc_helper_funcs = {
> +	.mode_fixup	= dss_crtc_mode_fixup,
> +	.atomic_enable	= dss_crtc_enable,
> +	.atomic_disable	= dss_crtc_disable,
> +	.mode_set_nofb	= dss_crtc_mode_set_nofb,
> +	.atomic_begin	= dss_crtc_atomic_begin,
> +	.atomic_flush	= dss_crtc_atomic_flush,
> +};
> +
> +static const struct drm_crtc_funcs dss_crtc_funcs = {
> +	.destroy	= drm_crtc_cleanup,
> +	.set_config	= drm_atomic_helper_set_config,
> +	.page_flip	= drm_atomic_helper_page_flip,
> +	.reset		= drm_atomic_helper_crtc_reset,
> +	.atomic_duplicate_state	= drm_atomic_helper_crtc_duplicate_state,
> +	.atomic_destroy_state	= drm_atomic_helper_crtc_destroy_state,
> +	.enable_vblank = dss_enable_vblank,
> +	.disable_vblank = dss_disable_vblank,
> +};
> +
> +static int dss_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
> +			 struct drm_plane *plane)
> +{
> +	struct kirin_drm_private *priv = to_drm_private(dev);
> +	struct device_node *port;
> +	int ret;
> +
> +	/* set crtc port so that
> +	 * drm_of_find_possible_crtcs call works
> +	 */
> +	port = of_get_child_by_name(dev->dev->of_node, "port");
> +	if (!port) {
> +		drm_err(dev, "no port node found in %s\n",
> +			dev->dev->of_node->full_name);
> +		return -EINVAL;
> +	}
> +	of_node_put(port);
> +	crtc->port = port;
> +
> +	ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
> +					&dss_crtc_funcs, NULL);
> +	if (ret) {
> +		drm_err(dev, "failed to init crtc.\n");
> +		return ret;
> +	}
> +
> +	drm_crtc_helper_add(crtc, &dss_crtc_helper_funcs);
> +	priv->crtc[drm_crtc_index(crtc)] = crtc;
> +
> +	return 0;
> +}
> +
> +static int dss_plane_atomic_check(struct drm_plane *plane,
> +				  struct drm_plane_state *state)
> +{
> +	struct drm_framebuffer *fb = state->fb;
> +	struct drm_crtc *crtc = state->crtc;
> +	struct dss_crtc *acrtc = to_dss_crtc(crtc);
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +	struct drm_crtc_state *crtc_state;
> +	u32 src_x = state->src_x >> 16;
> +	u32 src_y = state->src_y >> 16;
> +	u32 src_w = state->src_w >> 16;
> +	u32 src_h = state->src_h >> 16;
> +	int crtc_x = state->crtc_x;
> +	int crtc_y = state->crtc_y;
> +	u32 crtc_w = state->crtc_w;
> +	u32 crtc_h = state->crtc_h;
> +	u32 fmt;
> +
> +	if (!crtc || !fb)
> +		return 0;
> +
> +	fmt = dpe_get_format(ctx, fb->format->format);
> +	if (fmt == HISI_FB_PIXEL_FORMAT_UNSUPPORT)
> +		return -EINVAL;
> +
> +	crtc_state = drm_atomic_get_crtc_state(state->state, crtc);
> +	if (IS_ERR(crtc_state))
> +		return PTR_ERR(crtc_state);
> +
> +	if (src_w != crtc_w || src_h != crtc_h) {
> +		drm_err(ctx->dev, "Scale not support!!!\n");
> +		return -EINVAL;
> +	}
> +
> +	if (src_x + src_w > fb->width ||
> +	    src_y + src_h > fb->height)
> +		return -EINVAL;
> +
> +	if (crtc_x < 0 || crtc_y < 0)
> +		return -EINVAL;
> +
> +	if (crtc_x + crtc_w > crtc_state->adjusted_mode.hdisplay ||
> +	    crtc_y + crtc_h > crtc_state->adjusted_mode.vdisplay)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static void dss_plane_atomic_update(struct drm_plane *plane,
> +				    struct drm_plane_state *old_state)
> +{
> +	struct drm_plane_state *state = plane->state;
> +
> +	if (!state->fb) {
> +		state->visible = false;
> +		return;
> +	}
> +
> +	hisi_fb_pan_display(plane);
> +}
> +
> +static void dss_plane_atomic_disable(struct drm_plane *plane,
> +				     struct drm_plane_state *old_state)
> +{
> +	/* FIXME: Maybe this? */
> +#if 0
> +	struct dss_plane *aplane = to_dss_plane(plane);
> +	struct dss_crtc *acrtc = aplane->acrtc;
> +
> +	disable_ldi(acrtc);
> +	hisifb_mctl_sw_clr(acrtc);
> +#endif
> +}
> +
> +static const struct drm_plane_helper_funcs dss_plane_helper_funcs = {
> +	.atomic_check = dss_plane_atomic_check,
> +	.atomic_update = dss_plane_atomic_update,
> +	.atomic_disable = dss_plane_atomic_disable,
> +};
> +
> +static struct drm_plane_funcs dss_plane_funcs = {
> +	.update_plane	= drm_atomic_helper_update_plane,
> +	.disable_plane	= drm_atomic_helper_disable_plane,
> +	.destroy = drm_plane_cleanup,
> +	.reset = drm_atomic_helper_plane_reset,
> +	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
> +};
> +
> +static int dss_plane_init(struct drm_device *dev, struct dss_plane *aplane,
> +			  enum drm_plane_type type)
> +{
> +	const u32 *fmts;
> +	u32 fmts_cnt;
> +	int ret = 0;
> +
> +	/* get properties */
> +	fmts_cnt = hisi_dss_get_channel_formats(dev, aplane->ch, &fmts);
> +	if (ret)
> +		return ret;
> +
> +	ret = drm_universal_plane_init(dev, &aplane->base, 1, &dss_plane_funcs,
> +				       fmts, fmts_cnt, NULL,
> +				       type, NULL);
> +	if (ret) {
> +		drm_err(dev, "fail to init plane, ch=%d\n", aplane->ch);
> +		return ret;
> +	}
> +
> +	drm_plane_helper_add(&aplane->base, &dss_plane_helper_funcs);
> +
> +	return 0;
> +}
> +
> +static int dss_enable_iommu(struct platform_device *pdev, struct dss_hw_ctx *ctx)
> +{
> +#if 0
> +/*
> + * FIXME:
> + *
> + * Right now, the IOMMU support is actually disabled. See the caller of
> + * hisi_dss_smmu_config(). Yet, if we end enabling it, this should be
> + * ported to use io-pgtable directly.
> + */
> +	struct device *dev = NULL;
> +
> +	dev = &pdev->dev;
> +
> +	/* create iommu domain */
> +	ctx->mmu_domain = iommu_domain_alloc(dev->bus);
> +	if (!ctx->mmu_domain) {
> +		drm_err(ctx->dev, "iommu_domain_alloc failed!\n");
> +		return -EINVAL;
> +	}
> +
> +	iommu_attach_device(ctx->mmu_domain, dev);
> +#endif
> +	return 0;
> +}
> +
> +static int dss_dts_parse(struct platform_device *pdev, struct dss_hw_ctx *ctx)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct device_node *np = NULL;
> +	const char *compatible;
> +	int ret = 0;
> +
> +	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970)
> +		compatible = "hisilicon,kirin970-dpe";
> +	else
> +		compatible = "hisilicon,hi3660-dpe";
> +
> +	np = of_find_compatible_node(NULL, NULL, compatible);
> +	if (!np) {
> +		drm_err(ctx->dev, "NOT FOUND device node %s!\n", compatible);
> +		return -ENXIO;
> +	}
> +
> +	/* Initialize version-specific data */
> +	if (ctx->g_dss_version_tag == FB_ACCEL_HI366x)
> +		kirin960_dpe_defs(ctx);
> +	else
> +		kirin970_dpe_defs(ctx);
> +
> +	ctx->base = of_iomap(np, 0);
> +	if (!(ctx->base)) {
> +		drm_err(ctx->dev, "failed to get dss base resource.\n");
> +		return -ENXIO;
> +	}
> +
> +	ctx->peri_crg_base  = of_iomap(np, 1);
> +	if (!(ctx->peri_crg_base)) {
> +		drm_err(ctx->dev, "failed to get dss peri_crg_base resource.\n");
> +		return -ENXIO;
> +	}
> +
> +	ctx->sctrl_base  = of_iomap(np, 2);
> +	if (!(ctx->sctrl_base)) {
> +		drm_err(ctx->dev, "failed to get dss sctrl_base resource.\n");
> +		return -ENXIO;
> +	}
> +
> +	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
> +		ctx->pctrl_base = of_iomap(np, 3);
> +		if (!(ctx->pctrl_base)) {
> +			drm_err(ctx->dev,
> +				"failed to get dss pctrl_base resource.\n");
> +			return -ENXIO;
> +		}
> +	} else {
> +		ctx->pmc_base = of_iomap(np, 3);
> +		if (!(ctx->pmc_base)) {
> +			drm_err(ctx->dev,
> +				"failed to get dss pmc_base resource.\n");
> +			return -ENXIO;
> +		}
> +	}
> +
> +	ctx->noc_dss_base = of_iomap(np, 4);
> +	if (!(ctx->noc_dss_base)) {
> +		drm_err(ctx->dev, "failed to get noc_dss_base resource.\n");
> +		return -ENXIO;
> +	}
> +
> +	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
> +		ctx->pmctrl_base = of_iomap(np, 5);
> +		if (!(ctx->pmctrl_base)) {
> +			drm_err(ctx->dev,
> +				"failed to get dss pmctrl_base resource.\n");
> +			return -ENXIO;
> +		}
> +
> +		ctx->media_crg_base = of_iomap(np, 6);
> +		if (!(ctx->media_crg_base)) {
> +			drm_err(ctx->dev,
> +				"failed to get dss media_crg_base resource.\n");
> +			return -ENXIO;
> +		}
> +	}
> +
> +	/* get irq no */
> +	ctx->irq = irq_of_parse_and_map(np, 0);
> +	if (ctx->irq <= 0) {
> +		drm_err(ctx->dev, "failed to get irq_pdp resource.\n");
> +		return -ENXIO;
> +	}
> +
> +	drm_dbg(ctx->dev, "dss irq = %d.\n", ctx->irq);
> +
> +	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
> +		ctx->dpe_regulator = devm_regulator_get(dev, REGULATOR_PDP_NAME);
> +		if (!ctx->dpe_regulator) {
> +			drm_err(ctx->dev,
> +				"failed to get dpe_regulator resource! ret=%d.\n",
> +				ret);
> +			return -ENXIO;
> +		}
> +	}
> +
> +	ctx->dss_mmbuf_clk = devm_clk_get(dev, "clk_dss_axi_mm");
> +	ret = PTR_ERR_OR_ZERO(ctx->dss_mmbuf_clk);
> +	if (ret == -EPROBE_DEFER) {
> +		return ret;
> +	} else if (ret) {
> +		drm_err(ctx->dev, "failed to parse dss_mmbuf_clk: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ctx->dss_axi_clk = devm_clk_get(dev, "aclk_dss");
> +	ret = PTR_ERR_OR_ZERO(ctx->dss_axi_clk);
> +	if (ret == -EPROBE_DEFER) {
> +		return ret;
> +	} else if (ret) {
> +		drm_err(ctx->dev, "failed to parse dss_axi_clk: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ctx->dss_pclk_dss_clk = devm_clk_get(dev, "pclk_dss");
> +	ret = PTR_ERR_OR_ZERO(ctx->dss_pclk_dss_clk);
> +	if (ret == -EPROBE_DEFER) {
> +		return ret;
> +	} else if (ret) {
> +		drm_err(ctx->dev,
> +			"failed to parse dss_pclk_dss_clk: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ctx->dss_pri_clk = devm_clk_get(dev, "clk_edc0");
> +	ret = PTR_ERR_OR_ZERO(ctx->dss_pri_clk);
> +	if (ret == -EPROBE_DEFER) {
> +		return ret;
> +	} else if (ret) {
> +		drm_err(ctx->dev, "failed to parse dss_pri_clk: %d\n", ret);
> +		return ret;
> +	}
> +
> +	if (ctx->g_dss_version_tag != FB_ACCEL_KIRIN970) {
> +		ret = clk_set_rate(ctx->dss_pri_clk, DEFAULT_DSS_CORE_CLK_07V_RATE);
> +		if (ret < 0) {
> +			drm_err(ctx->dev, "dss_pri_clk clk_set_rate(%lu) failed, error=%d!\n",
> +				DEFAULT_DSS_CORE_CLK_07V_RATE, ret);
> +			return -EINVAL;
> +		}
> +
> +		drm_dbg(ctx->dev, "dss_pri_clk:[%lu]->[%llu].\n",
> +			DEFAULT_DSS_CORE_CLK_07V_RATE, (uint64_t)clk_get_rate(ctx->dss_pri_clk));
> +	}
> +
> +	ctx->dss_pxl0_clk = devm_clk_get(dev, "clk_ldi0");
> +	ret = PTR_ERR_OR_ZERO(ctx->dss_pri_clk);
> +	if (ret == -EPROBE_DEFER) {
> +		return ret;
> +	} else if (ret) {
> +		drm_err(ctx->dev, "failed to parse dss_pxl0_clk: %d\n", ret);
> +		return ret;
> +	}
> +
> +	if (ctx->g_dss_version_tag != FB_ACCEL_KIRIN970) {
> +		ret = clk_set_rate(ctx->dss_pxl0_clk, DSS_MAX_PXL0_CLK_144M);
> +		if (ret < 0) {
> +			drm_err(ctx->dev,
> +				"dss_pxl0_clk clk_set_rate(%lu) failed, error=%d!\n",
> +				DSS_MAX_PXL0_CLK_144M, ret);
> +			return -EINVAL;
> +		}
> +
> +		drm_dbg(ctx->dev, "dss_pxl0_clk:[%lu]->[%llu].\n",
> +			DSS_MAX_PXL0_CLK_144M,
> +			(uint64_t)clk_get_rate(ctx->dss_pxl0_clk));
> +	}
> +
> +	/* enable IOMMU */
> +	dss_enable_iommu(pdev, ctx);
> +
> +	return 0;
> +}
> +
> +int dss_drm_init(struct drm_device *dev, u32 g_dss_version_tag)
> +{
> +	struct platform_device *pdev = to_platform_device(dev->dev);
> +	struct dss_data *dss;
> +	struct dss_hw_ctx *ctx;
> +	struct dss_crtc *acrtc;
> +	struct dss_plane *aplane;
> +	enum drm_plane_type type;
> +	int ret;
> +	int i;
> +
> +	dss = devm_kzalloc(dev->dev, sizeof(*dss), GFP_KERNEL);
> +	if (!dss) {
> +		drm_err(dev, "failed to alloc dss_data\n");
> +		return -ENOMEM;
> +	}
> +	platform_set_drvdata(pdev, dss);
> +
> +	ctx = &dss->ctx;
> +	ctx->dev = dev;
> +	ctx->g_dss_version_tag = g_dss_version_tag;
> +
> +	acrtc = &dss->acrtc;
> +	acrtc->ctx = ctx;
> +	acrtc->out_format = LCD_RGB888;
> +	acrtc->bgr_fmt = LCD_RGB;
> +
> +	ret = dss_dts_parse(pdev, ctx);
> +	if (ret)
> +		return ret;
> +
> +	ctx->vactive0_end_flag = 0;
> +	init_waitqueue_head(&ctx->vactive0_end_wq);
> +
> +	/*
> +	 * plane init
> +	 * TODO: Now only support primary plane, overlay planes
> +	 * need to do.
TODO rather unclear..

> +	 */
> +	for (i = 0; i < DSS_CH_NUM; i++) {
> +		aplane = &dss->aplane[i];
> +		aplane->ch = i;
> +		/* aplane->ctx = ctx; */
> +		aplane->acrtc = acrtc;
> +		type = i == PRIMARY_CH ? DRM_PLANE_TYPE_PRIMARY :
> +			DRM_PLANE_TYPE_OVERLAY;
> +
> +		ret = dss_plane_init(dev, aplane, type);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	/* crtc init */
> +	ret = dss_crtc_init(dev, &acrtc->base, &dss->aplane[PRIMARY_CH].base);
> +	if (ret)
> +		return ret;
> +
> +	/* vblank irq init */
> +	ret = devm_request_irq(dev->dev, ctx->irq, dss_irq_handler,
> +			       IRQF_SHARED, dev->driver->name, acrtc);
> +	if (ret) {
> +		drm_err(dev, "fail to  devm_request_irq, ret=%d!", ret);
> +		return ret;
> +	}
> +
> +	disable_irq(ctx->irq);
> +
> +	return 0;
> +}
> +
> +void kirin9xx_dss_drm_cleanup(struct drm_device *dev)
> +{
> +	struct platform_device *pdev = to_platform_device(dev->dev);
> +	struct dss_data *dss = platform_get_drvdata(pdev);
> +	struct drm_crtc *crtc = &dss->acrtc.base;
> +
> +	drm_crtc_cleanup(crtc);
> +}
> +
> +int kirin9xx_dss_drm_suspend(struct platform_device *pdev, pm_message_t state)
> +{
> +	struct dss_data *dss = platform_get_drvdata(pdev);
> +	struct drm_crtc *crtc = &dss->acrtc.base;
> +
> +	dss_crtc_disable(crtc, NULL);
> +
> +	return 0;
> +}
> +
> +int kirin9xx_dss_drm_resume(struct platform_device *pdev)
> +{
> +	struct dss_data *dss = platform_get_drvdata(pdev);
> +	struct drm_crtc *crtc = &dss->acrtc.base;
> +
> +	dss_crtc_mode_set_nofb(crtc);
> +	dss_crtc_enable(crtc, NULL);
> +
> +	return 0;
> +}
> diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c
> new file mode 100644
> index 000000000000..c3e9fc95ad39
> --- /dev/null
> +++ b/drivers/staging/hikey9xx/gpu/kirin9xx_drm_overlay_utils.c
> @@ -0,0 +1,761 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2008-2011, Hisilicon Tech. Co., Ltd. All rights reserved.
> + * Copyright (c) 2008-2020, Huawei Technologies Co., Ltd
> + */
> +
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_drv.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_fourcc.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_plane_helper.h>
> +
> +#include "kirin9xx_drm_dpe_utils.h"
> +#include "kirin9xx_drm_drv.h"
> +#include "kirin9xx_dpe.h"
Excessive includes?

> +
> +static const int mid_array[DSS_CHN_MAX_DEFINE] = {
> +	0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x2, 0x1, 0x3, 0x0
> +};
> +
> +struct dpe_format {
> +	u32 pixel_format;
> +	enum dpe_fb_format dpe_format;
> +};
> +
> +/*
> + * FIXME: this driver was supposed to support 16 bpp with:
> + *
> + *       { DRM_FORMAT_RGB565, DPE_RGB_565 },
> + *       { DRM_FORMAT_BGR565, DPE_BGR_565 }
> + *
> + * However, those seem to be setting an YUYV mode.
> + * Using DRM_FORMAT_YUYV/DRM_FORMAT_UYVY doesn't currently work with X11,
> + * perhaps due to fb emulation. So, for now, let's just drop 16 bpp.
> + */
> +
> +static const struct dpe_format dpe_formats[] = {
> +	/* 24 bpp */
> +	{ DRM_FORMAT_XRGB8888, DPE_BGRX_8888 },
> +	{ DRM_FORMAT_XBGR8888, DPE_RGBX_8888 },
> +	/* 32 bpp */
> +	{ DRM_FORMAT_RGBA8888, DPE_RGBA_8888 },
> +	{ DRM_FORMAT_BGRA8888, DPE_BGRA_8888 },
> +	{ DRM_FORMAT_ARGB8888, DPE_RGBA_8888 },
> +	{ DRM_FORMAT_ABGR8888, DPE_BGRA_8888 },
> +};
> +
> +static const u32 dpe_channel_formats[] = {
> +	DRM_FORMAT_YUYV,
> +	DRM_FORMAT_UYVY,
> +	DRM_FORMAT_XRGB8888,
> +	DRM_FORMAT_XBGR8888,
> +	DRM_FORMAT_RGBA8888,
> +	DRM_FORMAT_BGRA8888,
> +	DRM_FORMAT_ARGB8888,
> +	DRM_FORMAT_ABGR8888,
> +};
> +
> +static u32 dpe_pixel_dma_format_map[] = {
> +	DMA_PIXEL_FORMAT_RGB_565,
> +	DMA_PIXEL_FORMAT_XRGB_4444,
> +	DMA_PIXEL_FORMAT_ARGB_4444,
> +	DMA_PIXEL_FORMAT_XRGB_5551,
> +	DMA_PIXEL_FORMAT_ARGB_5551,
> +	DMA_PIXEL_FORMAT_XRGB_8888,
> +	DMA_PIXEL_FORMAT_ARGB_8888,
> +	DMA_PIXEL_FORMAT_RGB_565,
> +	DMA_PIXEL_FORMAT_XRGB_4444,
> +	DMA_PIXEL_FORMAT_ARGB_4444,
> +	DMA_PIXEL_FORMAT_XRGB_5551,
> +	DMA_PIXEL_FORMAT_ARGB_5551,
> +	DMA_PIXEL_FORMAT_XRGB_8888,
> +	DMA_PIXEL_FORMAT_ARGB_8888,
> +	DMA_PIXEL_FORMAT_YUYV_422,
> +	DMA_PIXEL_FORMAT_YUV_422_SP_HP,
> +	DMA_PIXEL_FORMAT_YUV_422_SP_HP,
> +	DMA_PIXEL_FORMAT_YUV_420_SP_HP,
> +	DMA_PIXEL_FORMAT_YUV_420_SP_HP,
> +	DMA_PIXEL_FORMAT_YUV_422_P_HP,
> +	DMA_PIXEL_FORMAT_YUV_422_P_HP,
> +	DMA_PIXEL_FORMAT_YUV_420_P_HP,
> +	DMA_PIXEL_FORMAT_YUV_420_P_HP,
> +	DMA_PIXEL_FORMAT_YUYV_422,
> +	DMA_PIXEL_FORMAT_YUYV_422,
> +	DMA_PIXEL_FORMAT_YUYV_422,
> +	DMA_PIXEL_FORMAT_YUYV_422,
> +};
> +
> +static u32 dpe_pixel_dfc_format_map[] = {
> +	DFC_PIXEL_FORMAT_RGB_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_BGR_565,
> +	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_YUYV422,
> +	DFC_PIXEL_FORMAT_YUYV422,
> +	DFC_PIXEL_FORMAT_YVYU422,
> +	DFC_PIXEL_FORMAT_YUYV422,
> +	DFC_PIXEL_FORMAT_YVYU422,
> +	DFC_PIXEL_FORMAT_YUYV422,
> +	DFC_PIXEL_FORMAT_YVYU422,
> +	DFC_PIXEL_FORMAT_YUYV422,
> +	DFC_PIXEL_FORMAT_YVYU422,
> +	DFC_PIXEL_FORMAT_YUYV422,
> +	DFC_PIXEL_FORMAT_UYVY422,
> +	DFC_PIXEL_FORMAT_YVYU422,
> +	DFC_PIXEL_FORMAT_VYUY422,
> +};
> +
> +u32 dpe_get_format(struct dss_hw_ctx *ctx, u32 pixel_format)
> +{
> +	int i;
> +	const struct dpe_format *fmt = dpe_formats;
> +	u32 size = ARRAY_SIZE(dpe_formats);
> +
> +
> +	for (i = 0; i < size; i++) {
> +		if (fmt[i].pixel_format == pixel_format) {
> +			drm_info(ctx->dev, "requested fourcc %x, dpe format %d",
> +				 pixel_format, fmt[i].dpe_format);
> +			return fmt[i].dpe_format;
> +		}
> +	}
> +
> +	drm_err(ctx->dev, "Not found pixel format! fourcc = %x\n",
> +		pixel_format);
> +
> +	return HISI_FB_PIXEL_FORMAT_UNSUPPORT;
> +}
> +
> +u32 hisi_dss_get_channel_formats(struct drm_device *dev, u8 ch, const u32 **formats)
> +{
> +	*formats = dpe_channel_formats;
> +	return ARRAY_SIZE(dpe_channel_formats);
> +}
> +
> +static int hisi_dss_aif_ch_config(struct dss_hw_ctx *ctx, int chn_idx)
> +{
> +	void __iomem *aif0_ch_base;
> +	int mid = 0;
> +
> +	mid = mid_array[chn_idx];
> +	aif0_ch_base = ctx->base + ctx->g_dss_module_base[chn_idx][MODULE_AIF0_CHN];
> +
> +	set_reg(aif0_ch_base, 0x0, 1, 0);
> +	set_reg(aif0_ch_base, (uint32_t)mid, 4, 4);
> +
> +	return 0;
> +}
> +
> +static int hisi_dss_smmu_config(struct dss_hw_ctx *ctx, int chn_idx, bool mmu_enable)
> +{
> +	void __iomem *smmu_base;
> +	u32 idx = 0, i = 0;
> +
> +	smmu_base = ctx->base + ctx->smmu_offset;
> +
> +	for (i = 0; i < ctx->g_dss_chn_sid_num[chn_idx]; i++) {
> +		idx = ctx->g_dss_smmu_smrx_idx[chn_idx] + i;
> +		if (!mmu_enable) {
> +			set_reg(smmu_base + SMMU_SMRx_NS + idx * 0x4, 1, 32, 0);
> +		} else {
> +			/* set_reg(smmu_base + SMMU_SMRx_NS + idx * 0x4, 0x70, 32, 0); */
> +			set_reg(smmu_base + SMMU_SMRx_NS + idx * 0x4, 0x1C, 32, 0);
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int hisi_dss_mif_config(struct dss_hw_ctx *ctx, int chn_idx, bool mmu_enable)
> +{
> +	void __iomem *mif_base;
> +	void __iomem *mif_ch_base;
> +
> +	mif_base = ctx->base + DSS_MIF_OFFSET;
> +	mif_ch_base = ctx->base +
> +		ctx->g_dss_module_base[chn_idx][MODULE_MIF_CHN];
> +
> +	if (!mmu_enable)
> +		set_reg(mif_ch_base + MIF_CTRL1, 0x1, 1, 5);
> +	else
> +		set_reg(mif_ch_base + MIF_CTRL1, 0x00080000, 32, 0);
> +
> +	return 0;
> +}
> +
> +int hisi_dss_mctl_mutex_lock(struct dss_hw_ctx *ctx)
static?

> +{
> +	void __iomem *mctl_base;
> +
> +	mctl_base = ctx->base +
> +		ctx->g_dss_module_ovl_base[DSS_OVL0][MODULE_MCTL_BASE];
> +
> +	set_reg(mctl_base + MCTL_CTL_MUTEX, 0x1, 1, 0);
> +
> +	return 0;
> +}
> +
> +int hisi_dss_mctl_mutex_unlock(struct dss_hw_ctx *ctx)
static?

> +{
> +	void __iomem *mctl_base;
> +
> +
> +	mctl_base = ctx->base +
> +		ctx->g_dss_module_ovl_base[DSS_OVL0][MODULE_MCTL_BASE];
> +
> +	set_reg(mctl_base + MCTL_CTL_MUTEX, 0x0, 1, 0);
> +
> +	return 0;
> +}
> +
> +static int hisi_dss_mctl_ov_config(struct dss_hw_ctx *ctx, int chn_idx)
> +{
> +	void __iomem *mctl_base;
> +	u32 mctl_rch_offset = 0;
> +
> +	mctl_rch_offset = (uint32_t)(MCTL_CTL_MUTEX_RCH0 + chn_idx * 0x4);
> +
> +	mctl_base = ctx->base +
> +		ctx->g_dss_module_ovl_base[DSS_OVL0][MODULE_MCTL_BASE];
> +
> +	set_reg(mctl_base + MCTL_CTL_EN, 0x1, 32, 0);
> +	set_reg(mctl_base + MCTL_CTL_TOP, 0x2, 32, 0); /* auto mode */
> +	set_reg(mctl_base + MCTL_CTL_DBG, 0xB13A00, 32, 0);
> +
> +	set_reg(mctl_base + mctl_rch_offset, 0x1, 32, 0);
> +	set_reg(mctl_base + MCTL_CTL_MUTEX_ITF, 0x1, 2, 0);
> +	set_reg(mctl_base + MCTL_CTL_MUTEX_DBUF, 0x1, 2, 0);
> +	set_reg(mctl_base + MCTL_CTL_MUTEX_OV, 1 << DSS_OVL0, 4, 0);
> +
> +	return 0;
> +}
> +
> +static int hisi_dss_mctl_sys_config(struct dss_hw_ctx *ctx, int chn_idx)
> +{
> +	void __iomem *mctl_sys_base;
> +
> +	u32 layer_idx = 0;
> +	u32 mctl_rch_ov_oen_offset = 0;
> +	u32 mctl_rch_flush_en_offset = 0;
> +
> +
> +	mctl_sys_base = ctx->base + DSS_MCTRL_SYS_OFFSET;
> +	mctl_rch_ov_oen_offset = MCTL_RCH0_OV_OEN + chn_idx * 0x4;
> +	mctl_rch_flush_en_offset = MCTL_RCH0_FLUSH_EN + chn_idx * 0x4;
> +
> +	set_reg(mctl_sys_base + mctl_rch_ov_oen_offset,
> +		((1 << (layer_idx + 1)) | (0x100 << DSS_OVL0)), 32, 0);
> +
> +	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970)
> +		set_reg(mctl_sys_base + MCTL_RCH_OV0_SEL, 0xe, 4, 0);
> +	else
> +		set_reg(mctl_sys_base + MCTL_RCH_OV0_SEL, 0x8, 4, 0);
> +
> +	set_reg(mctl_sys_base + MCTL_RCH_OV0_SEL, chn_idx, 4, (layer_idx + 1) * 4);
> +
> +	set_reg(mctl_sys_base + MCTL_OV0_FLUSH_EN, 0xd, 4, 0);
> +	set_reg(mctl_sys_base + mctl_rch_flush_en_offset, 0x1, 32, 0);
> +
> +	return 0;
> +}
> +
> +static int hisi_dss_rdma_config(struct dss_hw_ctx *ctx,
> +				const struct dss_rect_ltrb *rect,
> +				u32 display_addr, u32 hal_format,
> +				u32 bpp, int chn_idx, bool afbcd,
> +				bool mmu_enable)
> +{
> +	void __iomem *rdma_base;
> +
> +	u32 aligned_pixel = 0;
> +	u32 rdma_oft_x0 = 0;
> +	u32 rdma_oft_y0 = 0;
> +	u32 rdma_oft_x1 = 0;
> +	u32 rdma_oft_y1 = 0;
> +	u32 rdma_stride = 0;
> +	u32 rdma_format = 0;
> +	u32 stretch_size_vrt = 0;
> +
> +	u32 stride_align = 0;
> +	u32 mm_base_0 = 0;
> +	u32 mm_base_1 = 0;
> +
> +	u32 afbcd_header_addr = 0;
> +	u32 afbcd_header_stride = 0;
> +	u32 afbcd_payload_addr = 0;
> +	u32 afbcd_payload_stride = 0;
> +
> +	rdma_base = ctx->base +
> +		ctx->g_dss_module_base[chn_idx][MODULE_DMA];
> +
> +	aligned_pixel = DMA_ALIGN_BYTES / bpp;
> +	rdma_oft_x0 = rect->left / aligned_pixel;
> +	rdma_oft_y0 = rect->top;
> +	rdma_oft_x1 = rect->right / aligned_pixel;
> +	rdma_oft_y1 = rect->bottom;
> +
> +	rdma_format = dpe_pixel_dma_format_map[hal_format];
> +
> +	if (afbcd) {
> +		mm_base_0 = 0;
> +		mm_base_1 = mm_base_0 + rect->right * bpp * MMBUF_LINE_NUM;
> +		mm_base_0 = ALIGN(mm_base_0, MMBUF_ADDR_ALIGN);
> +		mm_base_1 = ALIGN(mm_base_1, MMBUF_ADDR_ALIGN);
> +
> +		if ((((rect->right - rect->left) + 1) & (ctx->afbc_header_addr_align - 1)) ||
> +		    (((rect->bottom - rect->top) + 1) & (AFBC_BLOCK_ALIGN - 1))) {
> +			drm_err(ctx->dev,
> +				"img width(%d) is not %d bytes aligned, or img height (%d) is not %d bytes aligned!\n",
> +				((rect->right - rect->left) + 1),
> +				ctx->afbc_header_addr_align,
> +				((rect->bottom - rect->top) + 1),
> +				AFBC_BLOCK_ALIGN);
> +		}
> +
> +		if ((mm_base_0 & (MMBUF_ADDR_ALIGN - 1)) || (mm_base_1 & (MMBUF_ADDR_ALIGN - 1))) {
> +			drm_err(ctx->dev,
> +				"mm_base_0(0x%x) is not %d bytes aligned, or mm_base_1(0x%x) is not %d bytes aligned!\n",
> +				mm_base_0, MMBUF_ADDR_ALIGN,
> +				mm_base_1, MMBUF_ADDR_ALIGN);
> +		}
> +		/* header */
> +		afbcd_header_stride = (((rect->right - rect->left) + 1) / AFBC_BLOCK_ALIGN) * AFBC_HEADER_STRIDE_BLOCK;
> +		afbcd_header_addr = (uint32_t)(unsigned long)display_addr;
> +
> +		/* payload */
> +		if (bpp == 4)
> +			stride_align = AFBC_PAYLOAD_STRIDE_ALIGN_32;
> +		else if (bpp == 2)
> +			stride_align = AFBC_PAYLOAD_STRIDE_ALIGN_16;
> +		else
> +			drm_err(ctx->dev,"bpp(%d) not supported!\n", bpp);
> +
> +		afbcd_payload_stride = (((rect->right - rect->left) + 1) / AFBC_BLOCK_ALIGN) * stride_align;
> +
> +		afbcd_payload_addr = afbcd_header_addr + ALIGN(16 * (((rect->right - rect->left) + 1) / 16) *
> +				(((rect->bottom - rect->top) + 1) / 16), 1024);
> +		afbcd_payload_addr = afbcd_payload_addr +
> +			(rect->top / AFBC_BLOCK_ALIGN) * afbcd_payload_stride +
> +			(rect->left / AFBC_BLOCK_ALIGN) * stride_align;
> +
> +		set_reg(rdma_base + CH_REG_DEFAULT, 0x1, 32, 0);
> +		set_reg(rdma_base + CH_REG_DEFAULT, 0x0, 32, 0);
> +		set_reg(rdma_base + DMA_OFT_X0, rdma_oft_x0, 12, 0);
> +		set_reg(rdma_base + DMA_OFT_Y0, rdma_oft_y0, 16, 0);
> +		set_reg(rdma_base + DMA_OFT_X1, rdma_oft_x1, 12, 0);
> +		set_reg(rdma_base + DMA_OFT_Y1, rdma_oft_y1, 16, 0);
> +		set_reg(rdma_base + DMA_STRETCH_SIZE_VRT, (rect->bottom - rect->top), 13, 0);
> +		set_reg(rdma_base + DMA_CTRL, rdma_format, 5, 3);
> +		set_reg(rdma_base + DMA_CTRL, (mmu_enable ? 0x1 : 0x0), 1, 8);
> +
> +		set_reg(rdma_base + AFBCD_HREG_PIC_WIDTH, (rect->right - rect->left), 16, 0);
> +		set_reg(rdma_base + AFBCD_HREG_PIC_HEIGHT, (rect->bottom - rect->top), 16, 0);
> +		set_reg(rdma_base + AFBCD_CTL, AFBC_HALF_BLOCK_UPPER_LOWER_ALL, 2, 6);
> +		set_reg(rdma_base + AFBCD_HREG_HDR_PTR_LO, afbcd_header_addr, 32, 0);
> +		set_reg(rdma_base + AFBCD_INPUT_HEADER_STRIDE, afbcd_header_stride, 14, 0);
> +		set_reg(rdma_base + AFBCD_PAYLOAD_STRIDE, afbcd_payload_stride, 20, 0);
> +		set_reg(rdma_base + AFBCD_MM_BASE_0, mm_base_0, 32, 0);
> +		set_reg(rdma_base + AFBCD_HREG_FORMAT, 0x1, 1, 21);
> +		set_reg(rdma_base + AFBCD_SCRAMBLE_MODE, 0x0, 32, 0);
> +		set_reg(rdma_base + AFBCD_AFBCD_PAYLOAD_POINTER, afbcd_payload_addr, 32, 0);
> +		set_reg(rdma_base + AFBCD_HEIGHT_BF_STR, (rect->bottom - rect->top), 16, 0);
> +
> +		set_reg(rdma_base + CH_CTL, 0xf005, 32, 0);
> +	} else {
> +		stretch_size_vrt = rdma_oft_y1 - rdma_oft_y0;
> +		rdma_stride = ((rect->right - rect->left) + 1) * bpp / DMA_ALIGN_BYTES;
> +
> +		set_reg(rdma_base + CH_REG_DEFAULT, 0x1, 32, 0);
> +		set_reg(rdma_base + CH_REG_DEFAULT, 0x0, 32, 0);
> +
> +		set_reg(rdma_base + DMA_OFT_X0, rdma_oft_x0, 12, 0);
> +		set_reg(rdma_base + DMA_OFT_Y0, rdma_oft_y0, 16, 0);
> +		set_reg(rdma_base + DMA_OFT_X1, rdma_oft_x1, 12, 0);
> +		set_reg(rdma_base + DMA_OFT_Y1, rdma_oft_y1, 16, 0);
> +		set_reg(rdma_base + DMA_CTRL, rdma_format, 5, 3);
> +		set_reg(rdma_base + DMA_CTRL, (mmu_enable ? 0x1 : 0x0), 1, 8);
> +		set_reg(rdma_base + DMA_CTRL, 0x130, 32, 0);
> +		set_reg(rdma_base + DMA_STRETCH_SIZE_VRT, stretch_size_vrt, 32, 0);
> +		set_reg(rdma_base + DMA_DATA_ADDR0, display_addr, 32, 0);
> +		set_reg(rdma_base + DMA_STRIDE0, rdma_stride, 13, 0);
> +
> +		set_reg(rdma_base + CH_CTL, 0x1, 1, 0);
> +	}
> +
> +	return 0;
> +}
> +
> +static int hisi_dss_rdfc_config(struct dss_hw_ctx *ctx,
> +				const struct dss_rect_ltrb *rect,
> +				u32 hal_format, u32 bpp, int chn_idx)
> +{
> +	void __iomem *rdfc_base;
> +
> +	u32 dfc_pix_in_num = 0;
> +	u32 size_hrz = 0;
> +	u32 size_vrt = 0;
> +	u32 dfc_fmt = 0;
> +
> +	rdfc_base = ctx->base +
> +		ctx->g_dss_module_base[chn_idx][MODULE_DFC];
> +
> +	dfc_pix_in_num = (bpp <= 2) ? 0x1 : 0x0;
> +	size_hrz = rect->right - rect->left;
> +	size_vrt = rect->bottom - rect->top;
> +
> +	dfc_fmt = dpe_pixel_dfc_format_map[hal_format];
> +
> +	set_reg(rdfc_base + DFC_DISP_SIZE, (size_vrt | (size_hrz << 16)),
> +		29, 0);
> +	set_reg(rdfc_base + DFC_PIX_IN_NUM, dfc_pix_in_num, 1, 0);
> +	set_reg(rdfc_base + DFC_DISP_FMT, dfc_fmt, 5, 1);
> +	set_reg(rdfc_base + DFC_CTL_CLIP_EN, 0x1, 1, 0);
> +	set_reg(rdfc_base + DFC_ICG_MODULE, 0x1, 1, 0);
> +
> +	return 0;
> +}
> +
> +int hisi_dss_ovl_base_config(struct dss_hw_ctx *ctx, u32 xres, u32 yres)
> +{
> +	void __iomem *mctl_sys_base;
> +	void __iomem *mctl_base;
> +	void __iomem *ovl0_base;
> +
> +	mctl_sys_base = ctx->base + DSS_MCTRL_SYS_OFFSET;
> +	mctl_base = ctx->base +
> +		ctx->g_dss_module_ovl_base[DSS_OVL0][MODULE_MCTL_BASE];
> +	ovl0_base = ctx->base +
> +		ctx->g_dss_module_ovl_base[DSS_OVL0][MODULE_OVL_BASE];
> +
> +	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
> +		set_reg(ovl0_base + OV8_REG_DEFAULT, 0x1, 32, 0);
> +		set_reg(ovl0_base + OV8_REG_DEFAULT, 0x0, 32, 0);
> +		set_reg(ovl0_base + OVL_SIZE, (xres - 1) |
> +			((yres - 1) << 16), 32, 0);
> +
> +		set_reg(ovl0_base + OV_BG_COLOR_RGB, 0x00000000, 32, 0);
> +		set_reg(ovl0_base + OV_BG_COLOR_A, 0x00000000, 32, 0);
> +		set_reg(ovl0_base + OV_DST_STARTPOS, 0x0, 32, 0);
> +		set_reg(ovl0_base + OV_DST_ENDPOS, (xres - 1) |
> +			((yres - 1) << 16), 32, 0);
> +		set_reg(ovl0_base + OV_GCFG, 0x10001, 32, 0);
> +		set_reg(mctl_sys_base + MCTL_RCH_OV0_SEL, 0xE, 4, 0);
> +	} else {
> +		set_reg(ovl0_base + OVL6_REG_DEFAULT, 0x1, 32, 0);
> +		set_reg(ovl0_base + OVL6_REG_DEFAULT, 0x0, 32, 0);
> +		set_reg(ovl0_base + OVL_SIZE, (xres - 1) | ((yres - 1) << 16), 32, 0);
> +		set_reg(ovl0_base + OVL_BG_COLOR, 0xFF000000, 32, 0);
> +		set_reg(ovl0_base + OVL_DST_STARTPOS, 0x0, 32, 0);
> +		set_reg(ovl0_base + OVL_DST_ENDPOS, (xres - 1) | ((yres - 1) << 16), 32, 0);
> +		set_reg(ovl0_base + OVL_GCFG, 0x10001, 32, 0);
> +		set_reg(mctl_sys_base + MCTL_RCH_OV0_SEL, 0x8, 4, 0);
> +	}
> +
> +	set_reg(mctl_base + MCTL_CTL_MUTEX_ITF, 0x1, 32, 0);
> +	set_reg(mctl_base + MCTL_CTL_MUTEX_DBUF, 0x1, 2, 0);
> +	set_reg(mctl_base + MCTL_CTL_MUTEX_OV, 1 << DSS_OVL0, 4, 0);
> +	set_reg(mctl_sys_base + MCTL_OV0_FLUSH_EN, 0xd, 4, 0);
> +
> +	return 0;
> +}
> +
> +static int hisi_dss_ovl_config(struct dss_hw_ctx *ctx,
> +			       const struct dss_rect_ltrb *rect, u32 xres, u32 yres)
> +{
> +	void __iomem *ovl0_base;
> +
> +	ovl0_base = ctx->base +
> +		ctx->g_dss_module_ovl_base[DSS_OVL0][MODULE_OVL_BASE];
> +
> +	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
> +		set_reg(ovl0_base + OV8_REG_DEFAULT, 0x1, 32, 0);
> +		set_reg(ovl0_base + OV8_REG_DEFAULT, 0x0, 32, 0);
> +		set_reg(ovl0_base + OVL_SIZE, (xres - 1) |
> +			((yres - 1) << 16), 32, 0);
> +		set_reg(ovl0_base + OV_BG_COLOR_RGB, 0x3FF00000, 32, 0);
> +		set_reg(ovl0_base + OV_BG_COLOR_A, 0x3ff, 32, 0);
> +
> +		set_reg(ovl0_base + OV_DST_STARTPOS, 0x0, 32, 0);
> +		set_reg(ovl0_base + OV_DST_ENDPOS, (xres - 1) |
> +			((yres - 1) << 16), 32, 0);
> +		set_reg(ovl0_base + OV_GCFG, 0x10001, 32, 0);
> +		set_reg(ovl0_base + OV_LAYER0_POS, (rect->left) |
> +			((rect->top) << 16), 32, 0);
> +		set_reg(ovl0_base + OV_LAYER0_SIZE, (rect->right) |
> +			((rect->bottom) << 16), 32, 0);
> +		set_reg(ovl0_base + OV_LAYER0_ALPHA_MODE, 0x1004000, 32, 0); /* NEED CHECK? */
> +		set_reg(ovl0_base + OV_LAYER0_ALPHA_A, 0x3ff03ff, 32, 0);
> +		set_reg(ovl0_base + OV_LAYER0_CFG, 0x1, 1, 0);
> +	} else {
> +		set_reg(ovl0_base + OVL6_REG_DEFAULT, 0x1, 32, 0);
> +		set_reg(ovl0_base + OVL6_REG_DEFAULT, 0x0, 32, 0);
> +		set_reg(ovl0_base + OVL_SIZE, (xres - 1) |
> +			((yres - 1) << 16), 32, 0);
> +		set_reg(ovl0_base + OVL_BG_COLOR, 0xFFFF0000, 32, 0);
> +		set_reg(ovl0_base + OVL_DST_STARTPOS, 0x0, 32, 0);
> +		set_reg(ovl0_base + OVL_DST_ENDPOS, (xres - 1) |
> +			((yres - 1) << 16), 32, 0);
> +		set_reg(ovl0_base + OVL_GCFG, 0x10001, 32, 0);
> +		set_reg(ovl0_base + OVL_LAYER0_POS, (rect->left) |
> +			((rect->top) << 16), 32, 0);
> +		set_reg(ovl0_base + OVL_LAYER0_SIZE, (rect->right) |
> +			((rect->bottom) << 16), 32, 0);
> +		set_reg(ovl0_base + OVL_LAYER0_ALPHA, 0x00ff40ff, 32, 0);
> +		set_reg(ovl0_base + OVL_LAYER0_CFG, 0x1, 1, 0);
> +	}
> +
> +	return 0;
> +}
> +
> +static void hisi_dss_qos_on(struct dss_hw_ctx *ctx)
> +{
> +	char __iomem *noc_dss_base;
> +
> +	noc_dss_base = ctx->noc_dss_base;
> +
> +	writel(0x2, noc_dss_base + 0xc);
> +	writel(0x2, noc_dss_base + 0x8c);
> +	writel(0x2, noc_dss_base + 0x10c);
> +	writel(0x2, noc_dss_base + 0x18c);
> +}
> +
> +static void hisi_dss_mif_on(struct dss_hw_ctx *ctx)
> +{
> +	char __iomem *dss_base;
> +	char __iomem *mif_base;
> +
> +	dss_base = ctx->base;
> +	mif_base = ctx->base + DSS_MIF_OFFSET;
> +
> +	set_reg(mif_base + MIF_ENABLE, 0x1, 1, 0);
> +	set_reg(dss_base + MIF_CH0_OFFSET + MIF_CTRL0, 0x1, 1, 0);
> +	set_reg(dss_base + MIF_CH1_OFFSET + MIF_CTRL0, 0x1, 1, 0);
> +	set_reg(dss_base + MIF_CH2_OFFSET + MIF_CTRL0, 0x1, 1, 0);
> +	set_reg(dss_base + MIF_CH3_OFFSET + MIF_CTRL0, 0x1, 1, 0);
> +	set_reg(dss_base + MIF_CH4_OFFSET + MIF_CTRL0, 0x1, 1, 0);
> +	set_reg(dss_base + MIF_CH5_OFFSET + MIF_CTRL0, 0x1, 1, 0);
> +	set_reg(dss_base + MIF_CH6_OFFSET + MIF_CTRL0, 0x1, 1, 0);
> +	set_reg(dss_base + MIF_CH7_OFFSET + MIF_CTRL0, 0x1, 1, 0);
> +	set_reg(dss_base + MIF_CH8_OFFSET + MIF_CTRL0, 0x1, 1, 0);
> +	set_reg(dss_base + MIF_CH9_OFFSET + MIF_CTRL0, 0x1, 1, 0);
> +
> +	set_reg(dss_base + MIF_CH10_OFFSET + MIF_CTRL0, 0x1, 1, 0);
> +	set_reg(dss_base + MIF_CH11_OFFSET + MIF_CTRL0, 0x1, 1, 0);
> +}
> +
> +void hisi_dss_smmu_on(struct dss_hw_ctx *ctx)
static?

> +{
> +#if 0
> +/*
> + * FIXME:
> + *
> + * Right now, the IOMMU support is actually disabled. See the caller of
> + * hisi_dss_smmu_config(). Yet, if we end enabling it, this should be
> + * ported to use io-pgtable directly.
> + */
> +	void __iomem *smmu_base;
> +	struct iommu_domain_data *domain_data = NULL;
> +	u32 phy_pgd_base = 0;
> +	u64 fama_phy_pgd_base;
> +
> +	smmu_base = ctx->base + ctx->smmu_offset;
> +
> +	set_reg(smmu_base + SMMU_SCR, 0x0, 1, 0);  /* global bypass cancel */
> +	set_reg(smmu_base + SMMU_SCR, 0x1, 8, 20); /* ptw_mid */
> +	set_reg(smmu_base + SMMU_SCR, 0xf, 4, 16); /* pwt_pf */
> +	set_reg(smmu_base + SMMU_SCR, 0x7, 3, 3);  /* interrupt cachel1 cach3l2 en */
> +	set_reg(smmu_base + SMMU_LP_CTRL, 0x1, 1, 0);  /* auto_clk_gt_en */
> +
> +	/* Long Descriptor */
> +	set_reg(smmu_base + SMMU_CB_TTBCR, 0x1, 1, 0);
> +
> +	set_reg(smmu_base + SMMU_ERR_RDADDR, 0x7FF00000, 32, 0);
> +	set_reg(smmu_base + SMMU_ERR_WRADDR, 0x7FFF0000, 32, 0);
> +
> +	/* disable cmdlist, dbg, reload */
> +	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);
> +
> +	/* cmdlist stream bypass */
> +	set_reg(smmu_base + SMMU_SMRx_NS + 36 * 0x4, 0x1, 32, 0); /* debug stream id */
> +	set_reg(smmu_base + SMMU_SMRx_NS + 37 * 0x4, 0x1, 32, 0); /* cmd unsec stream id */
> +	set_reg(smmu_base + SMMU_SMRx_NS + 38 * 0x4, 0x1, 32, 0); /* cmd sec stream id */
> +
> +	/* TTBR0 */
> +	domain_data = (struct iommu_domain_data *)(ctx->mmu_domain->priv);
> +	fama_phy_pgd_base = domain_data->phy_pgd_base;
> +	phy_pgd_base = (uint32_t)(domain_data->phy_pgd_base);
> +	drm_dbg(ctx->dev,
> +		"fama_phy_pgd_base = %llu, phy_pgd_base =0x%x\n",
> +		fama_phy_pgd_base, phy_pgd_base);
> +	set_reg(smmu_base + SMMU_CB_TTBR0, phy_pgd_base, 32, 0);
> +#endif
> +}
> +
> +void hisifb_dss_on(struct dss_hw_ctx *ctx)
> +{
> +	/* dss qos on */
> +	hisi_dss_qos_on(ctx);
> +	/* mif on */
> +	hisi_dss_mif_on(ctx);
> +	/* smmu on */
> +	hisi_dss_smmu_on(ctx);
> +}
> +
> +void hisi_dss_mctl_on(struct dss_hw_ctx *ctx)
> +{
> +	char __iomem *mctl_base = NULL;
> +	char __iomem *mctl_sys_base = NULL;
> +
> +	mctl_base = ctx->base +
> +		ctx->g_dss_module_ovl_base[DSS_MCTL0][MODULE_MCTL_BASE];
> +	mctl_sys_base = ctx->base + DSS_MCTRL_SYS_OFFSET;
> +
> +	set_reg(mctl_base + MCTL_CTL_EN, 0x1, 32, 0);
> +	set_reg(mctl_base + MCTL_CTL_MUTEX_ITF, 0x1, 32, 0);
> +	set_reg(mctl_base + MCTL_CTL_DBG, 0xB13A00, 32, 0);
> +	set_reg(mctl_base + MCTL_CTL_TOP, 0x2, 32, 0);
> +}
> +
> +void hisi_dss_unflow_handler(struct dss_hw_ctx *ctx, bool unmask)
static?
> +{
> +	void __iomem *dss_base;
> +	u32 tmp = 0;
> +
> +	dss_base = ctx->base;
> +
> +	tmp = readl(dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK);
> +	if (unmask)
> +		tmp &= ~BIT_LDI_UNFLOW;
> +	else
> +		tmp |= BIT_LDI_UNFLOW;
> +
> +	writel(tmp, dss_base + DSS_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK);
> +}
> +
> +void hisifb_mctl_sw_clr(struct dss_crtc *acrtc)
> +{
> +	char __iomem *mctl_base = NULL;
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +	int mctl_status;
> +	int delay_count = 0;
> +	bool is_timeout;
> +
> +	mctl_base = ctx->base +
> +		    ctx->g_dss_module_ovl_base[DSS_MCTL0][MODULE_MCTL_BASE];
> +
> +	if (mctl_base)
> +		set_reg(mctl_base + MCTL_CTL_CLEAR, 0x1, 1, 0);
> +
> +	while (1) {
> +		mctl_status = readl(mctl_base + MCTL_CTL_STATUS);
> +		if (((mctl_status & 0x10) == 0) || (delay_count > 500)) {
> +			is_timeout = (delay_count > 100) ? true : false;
> +			delay_count = 0;
> +			break;
> +		}
> +
> +		udelay(1);
> +		++delay_count;
> +	}
> +
> +	if (is_timeout)
> +		drm_err(ctx->dev, "mctl_status =0x%x !\n", mctl_status);
> +
> +	enable_ldi(acrtc);
> +	DRM_INFO("-.\n");
> +}
> +
> +void hisi_fb_pan_display(struct drm_plane *plane)
> +{
> +	struct drm_plane_state *state = plane->state;
> +	struct drm_framebuffer *fb = state->fb;
> +	struct drm_display_mode *mode;
> +	struct drm_display_mode *adj_mode;
> +
> +	struct dss_plane *aplane = to_dss_plane(plane);
> +	struct dss_crtc *acrtc = aplane->acrtc;
> +	struct dss_hw_ctx *ctx = acrtc->ctx;
> +
> +	struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(state->fb, 0);
> +
> +	bool afbcd = false;
> +	bool mmu_enable = false;
> +	struct dss_rect_ltrb rect;
> +	u32 bpp;
> +	u32 stride;
> +	u32 display_addr = 0;
> +	u32 hal_fmt;
> +	int chn_idx = DSS_RCHN_D2;
> +
> +	int crtc_x = state->crtc_x;
> +	int crtc_y = state->crtc_y;
> +	unsigned int crtc_w = state->crtc_w;
> +	unsigned int crtc_h = state->crtc_h;
> +	u32 src_x = state->src_x >> 16;
> +	u32 src_y = state->src_y >> 16;
> +	u32 src_w = state->src_w >> 16;
> +	u32 src_h = state->src_h >> 16;
> +
> +	u32 hfp, hbp, hsw, vfp, vbp, vsw;
> +
> +	mode = &acrtc->base.state->mode;
> +	adj_mode = &acrtc->base.state->adjusted_mode;
> +
> +	bpp = fb->format->cpp[0];
> +	stride = fb->pitches[0];
> +
> +	display_addr = (u32)obj->paddr + src_y * stride;
> +
> +	rect.left = 0;
> +	rect.right = src_w - 1;
> +	rect.top = 0;
> +	rect.bottom = src_h - 1;
> +	hal_fmt = dpe_get_format(ctx, fb->format->format);
> +
> +	drm_dbg(ctx->dev,
> +		"channel%d: src:(%d,%d, %dx%d) crtc:(%d,%d, %dx%d), rect(%d,%d,%d,%d),fb:%dx%d, pixel_format=%d, stride=%d, paddr=0x%x, bpp=%d.\n",
> +			 chn_idx, src_x, src_y, src_w, src_h,
> +			 crtc_x, crtc_y, crtc_w, crtc_h,
> +			 rect.left, rect.top, rect.right, rect.bottom,
> +			 fb->width, fb->height, hal_fmt,
> +			 stride, display_addr, bpp);
> +
> +	hfp = mode->hsync_start - mode->hdisplay;
> +	hbp = mode->htotal - mode->hsync_end;
> +	hsw = mode->hsync_end - mode->hsync_start;
> +	vfp = mode->vsync_start - mode->vdisplay;
> +	vbp = mode->vtotal - mode->vsync_end;
> +	vsw = mode->vsync_end - mode->vsync_start;
The above varaibles are assinged but not used - delete them?

> +
> +	hisi_dss_mctl_mutex_lock(ctx);
> +	hisi_dss_aif_ch_config(ctx, chn_idx);
> +	hisi_dss_mif_config(ctx, chn_idx, mmu_enable);
> +	hisi_dss_smmu_config(ctx, chn_idx, mmu_enable);
> +
> +	hisi_dss_rdma_config(ctx, &rect, display_addr, hal_fmt, bpp, chn_idx, afbcd, mmu_enable);
> +	hisi_dss_rdfc_config(ctx, &rect, hal_fmt, bpp, chn_idx);
> +	hisi_dss_ovl_config(ctx, &rect, mode->hdisplay, mode->vdisplay);
> +
> +	hisi_dss_mctl_ov_config(ctx, chn_idx);
> +	hisi_dss_mctl_sys_config(ctx, chn_idx);
> +	hisi_dss_mctl_mutex_unlock(ctx);
> +	hisi_dss_unflow_handler(ctx, true);
> +
> +	enable_ldi(acrtc);
> +}

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-24 19:29           ` Dave Airlie
@ 2020-08-25 11:30             ` Mauro Carvalho Chehab
  2020-08-25 11:38               ` Laurent Pinchart
                                 ` (2 more replies)
  0 siblings, 3 replies; 42+ messages in thread
From: Mauro Carvalho Chehab @ 2020-08-25 11:30 UTC (permalink / raw)
  To: Dave Airlie
  Cc: Laurent Pinchart, Neil Armstrong, David Airlie, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Sam Ravnborg, driverdevel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	Xinliang Liu, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Jakub Kicinski, Laurentiu Palcu, linux-media,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Liwei Cai, Jesper Dangaard Brouer, Manivannan Sadhasivam,
	Chen Feng, Alexei Starovoitov,
	moderated list:DMA BUFFER SHARING FRAMEWORK, Rob Herring,
	mauro.chehab, Rob Clark, linux-arm-kernel, Greg Kroah-Hartman,
	lkml, Liuyao An, Network Development, Rongrong Zou,
	BPF Mailing List, David S. Miller

Em Tue, 25 Aug 2020 05:29:29 +1000
Dave Airlie <airlied@gmail.com> escreveu:

> On Thu, 20 Aug 2020 at 20:02, Laurent Pinchart
> <laurent.pinchart@ideasonboard.com> wrote:
> >
> > Hi Mauro,
> >
> > On Thu, Aug 20, 2020 at 09:03:26AM +0200, Mauro Carvalho Chehab wrote:  
> > > Em Wed, 19 Aug 2020 12:52:06 -0700 John Stultz escreveu:  
> > > > On Wed, Aug 19, 2020 at 8:31 AM Laurent Pinchart wrote:  
> > > > > On Wed, Aug 19, 2020 at 05:21:20PM +0200, Sam Ravnborg wrote:  
> > > > > > On Wed, Aug 19, 2020 at 01:45:28PM +0200, Mauro Carvalho Chehab wrote:  
> > > > > > > This patch series port the out-of-tree driver for Hikey 970 (which
> > > > > > > should also support Hikey 960) from the official 96boards tree:
> > > > > > >
> > > > > > >    https://github.com/96boards-hikey/linux/tree/hikey970-v4.9
> > > > > > >
> > > > > > > Based on his history, this driver seems to be originally written
> > > > > > > for Kernel 4.4, and was later ported to Kernel 4.9. The original
> > > > > > > driver used to depend on ION (from Kernel 4.4) and had its own
> > > > > > > implementation for FB dev API.
> > > > > > >
> > > > > > > As I need to preserve the original history (with has patches from
> > > > > > > both HiSilicon and from Linaro),  I'm starting from the original
> > > > > > > patch applied there. The remaining patches are incremental,
> > > > > > > and port this driver to work with upstream Kernel.
> > > > > > >  
> > > > ...  
> > > > > > > - Due to legal reasons, I need to preserve the authorship of
> > > > > > >   each one responsbile for each patch. So, I need to start from
> > > > > > >   the original patch from Kernel 4.4;  
> > > > ...  
> > > > > > I do acknowledge you need to preserve history and all -
> > > > > > but this patchset is not easy to review.  
> > > > >
> > > > > Why do we need to preserve history ? Adding relevant Signed-off-by and
> > > > > Co-developed-by should be enough, shouldn't it ? Having a public branch
> > > > > that contains the history is useful if anyone is interested, but I don't
> > > > > think it's required in mainline.  
> > > >
> > > > Yea. I concur with Laurent here. I'm not sure what legal reasoning you
> > > > have on this but preserving the "absolute" history here is actively
> > > > detrimental for review and understanding of the patch set.
> > > >
> > > > Preserving Authorship, Signed-off-by lines and adding Co-developed-by
> > > > lines should be sufficient to provide both atribution credit and DCO
> > > > history.  
> > >
> > > I'm not convinced that, from legal standpoint, folding things would
> > > be enough. See, there are at least 3 legal systems involved here
> > > among the different patch authors:
> > >
> > >       - civil law;
> > >       - common law;
> > >       - customary law + common law.
> > >
> > > Merging stuff altogether from different law systems can be problematic,
> > > and trying to discuss this with experienced IP property lawyers will
> > > for sure take a lot of time and efforts. I also bet that different
> > > lawyers will have different opinions, because laws are subject to
> > > interpretation. With that matter I'm not aware of any court rules
> > > with regards to folded patches. So, it sounds to me that folding
> > > patches is something that has yet to be proofed in courts around
> > > the globe.
> > >
> > > At least for US legal system, it sounds that the Country of
> > > origin of a patch is relevant, as they have a concept of
> > > "national technology" that can be subject to export regulations.
> > >
> > > From my side, I really prefer to play safe and stay out of any such
> > > legal discussions.  
> >
> > Let's be serious for a moment. If you think there are legal issues in
> > taking GPL-v2.0-only patches and squashing them while retaining
> > authorship information through tags, the Linux kernel if *full* of that.
> > You also routinely modify patches that you commit to the media subsystem
> > to fix "small issues".
> >
> > The country of origin argument makes no sense either, the kernel code
> > base if full of code coming from pretty much all country on the planet.
> >
> > Keeping the patches separate make this hard to review. Please squash
> > them.  
> 
> I'm inclined to agree with Laurent here.
> 
> Patches submitted as GPL-v2 with DCO lines and author names/companies
> should be fine to be squashed and rearranged,
> as long as the DCO and Authorship is kept somewhere in the new patch
> that is applied.
> 
> Review is more important here.

Sorry, but I can't agree that review is more important than to be able
to properly indicate copyrights in a valid way at the legal systems that
it would apply ;-)

In any case, there's an easy way to make the code easy to review:
I can write the patches against staging (where it is OK to submit
preserving the history) and then add a final patch moving it out
of staging.

You can then just review the last patch, as it will contain the
entire code on it.

Another alternative, as I'm already doing with Sam, is for me to
submit the folded code as a reply to 00/xx. You can then just 
review the final code, without concerning about how the code reached
there.

From review point of the view, this will be the same as reviewing
a folded patch, but, from legal standpoint, the entire copyright
chain will be preserved.

Thanks,
Mauro

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-25 11:30             ` Mauro Carvalho Chehab
@ 2020-08-25 11:38               ` Laurent Pinchart
  2020-08-25 12:31               ` Daniel Stone
  2020-08-26 14:44               ` Nicolas Dufresne
  2 siblings, 0 replies; 42+ messages in thread
From: Laurent Pinchart @ 2020-08-25 11:38 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Dave Airlie, Neil Armstrong, David Airlie, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Sam Ravnborg, driverdevel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	Xinliang Liu, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Jakub Kicinski, Laurentiu Palcu, linux-media,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Liwei Cai, Jesper Dangaard Brouer, Manivannan Sadhasivam,
	Chen Feng, Alexei Starovoitov,
	moderated list:DMA BUFFER SHARING FRAMEWORK, Rob Herring,
	mauro.chehab, Rob Clark, linux-arm-kernel, Greg Kroah-Hartman,
	lkml, Liuyao An, Network Development, Rongrong Zou,
	BPF Mailing List, David S. Miller

Hi Mauro,

On Tue, Aug 25, 2020 at 01:30:25PM +0200, Mauro Carvalho Chehab wrote:
> Em Tue, 25 Aug 2020 05:29:29 +1000
> Dave Airlie <airlied@gmail.com> escreveu:
> 
> > On Thu, 20 Aug 2020 at 20:02, Laurent Pinchart
> > <laurent.pinchart@ideasonboard.com> wrote:
> > >
> > > Hi Mauro,
> > >
> > > On Thu, Aug 20, 2020 at 09:03:26AM +0200, Mauro Carvalho Chehab wrote:  
> > > > Em Wed, 19 Aug 2020 12:52:06 -0700 John Stultz escreveu:  
> > > > > On Wed, Aug 19, 2020 at 8:31 AM Laurent Pinchart wrote:  
> > > > > > On Wed, Aug 19, 2020 at 05:21:20PM +0200, Sam Ravnborg wrote:  
> > > > > > > On Wed, Aug 19, 2020 at 01:45:28PM +0200, Mauro Carvalho Chehab wrote:  
> > > > > > > > This patch series port the out-of-tree driver for Hikey 970 (which
> > > > > > > > should also support Hikey 960) from the official 96boards tree:
> > > > > > > >
> > > > > > > >    https://github.com/96boards-hikey/linux/tree/hikey970-v4.9
> > > > > > > >
> > > > > > > > Based on his history, this driver seems to be originally written
> > > > > > > > for Kernel 4.4, and was later ported to Kernel 4.9. The original
> > > > > > > > driver used to depend on ION (from Kernel 4.4) and had its own
> > > > > > > > implementation for FB dev API.
> > > > > > > >
> > > > > > > > As I need to preserve the original history (with has patches from
> > > > > > > > both HiSilicon and from Linaro),  I'm starting from the original
> > > > > > > > patch applied there. The remaining patches are incremental,
> > > > > > > > and port this driver to work with upstream Kernel.
> > > > > > > >  
> > > > > ...  
> > > > > > > > - Due to legal reasons, I need to preserve the authorship of
> > > > > > > >   each one responsbile for each patch. So, I need to start from
> > > > > > > >   the original patch from Kernel 4.4;  
> > > > > ...  
> > > > > > > I do acknowledge you need to preserve history and all -
> > > > > > > but this patchset is not easy to review.  
> > > > > >
> > > > > > Why do we need to preserve history ? Adding relevant Signed-off-by and
> > > > > > Co-developed-by should be enough, shouldn't it ? Having a public branch
> > > > > > that contains the history is useful if anyone is interested, but I don't
> > > > > > think it's required in mainline.  
> > > > >
> > > > > Yea. I concur with Laurent here. I'm not sure what legal reasoning you
> > > > > have on this but preserving the "absolute" history here is actively
> > > > > detrimental for review and understanding of the patch set.
> > > > >
> > > > > Preserving Authorship, Signed-off-by lines and adding Co-developed-by
> > > > > lines should be sufficient to provide both atribution credit and DCO
> > > > > history.  
> > > >
> > > > I'm not convinced that, from legal standpoint, folding things would
> > > > be enough. See, there are at least 3 legal systems involved here
> > > > among the different patch authors:
> > > >
> > > >       - civil law;
> > > >       - common law;
> > > >       - customary law + common law.
> > > >
> > > > Merging stuff altogether from different law systems can be problematic,
> > > > and trying to discuss this with experienced IP property lawyers will
> > > > for sure take a lot of time and efforts. I also bet that different
> > > > lawyers will have different opinions, because laws are subject to
> > > > interpretation. With that matter I'm not aware of any court rules
> > > > with regards to folded patches. So, it sounds to me that folding
> > > > patches is something that has yet to be proofed in courts around
> > > > the globe.
> > > >
> > > > At least for US legal system, it sounds that the Country of
> > > > origin of a patch is relevant, as they have a concept of
> > > > "national technology" that can be subject to export regulations.
> > > >
> > > > From my side, I really prefer to play safe and stay out of any such
> > > > legal discussions.  
> > >
> > > Let's be serious for a moment. If you think there are legal issues in
> > > taking GPL-v2.0-only patches and squashing them while retaining
> > > authorship information through tags, the Linux kernel if *full* of that.
> > > You also routinely modify patches that you commit to the media subsystem
> > > to fix "small issues".
> > >
> > > The country of origin argument makes no sense either, the kernel code
> > > base if full of code coming from pretty much all country on the planet.
> > >
> > > Keeping the patches separate make this hard to review. Please squash
> > > them.  
> > 
> > I'm inclined to agree with Laurent here.
> > 
> > Patches submitted as GPL-v2 with DCO lines and author names/companies
> > should be fine to be squashed and rearranged,
> > as long as the DCO and Authorship is kept somewhere in the new patch
> > that is applied.
> > 
> > Review is more important here.
> 
> Sorry, but I can't agree that review is more important than to be able
> to properly indicate copyrights in a valid way at the legal systems that
> it would apply ;-)
> 
> In any case, there's an easy way to make the code easy to review:
> I can write the patches against staging (where it is OK to submit
> preserving the history) and then add a final patch moving it out
> of staging.
> 
> You can then just review the last patch, as it will contain the
> entire code on it.
> 
> Another alternative, as I'm already doing with Sam, is for me to
> submit the folded code as a reply to 00/xx. You can then just 
> review the final code, without concerning about how the code reached
> there.
> 
> From review point of the view, this will be the same as reviewing
> a folded patch, but, from legal standpoint, the entire copyright
> chain will be preserved.

Let's stop with the legal FUD please. Squashing patches is done
routinely in the kernel. If you have evidence this causes legal issues,
please bring it up with the TAB or the LF to make this practice stop.
Otherwise, please squash this series.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-25 11:30             ` Mauro Carvalho Chehab
  2020-08-25 11:38               ` Laurent Pinchart
@ 2020-08-25 12:31               ` Daniel Stone
  2020-08-26 14:44               ` Nicolas Dufresne
  2 siblings, 0 replies; 42+ messages in thread
From: Daniel Stone @ 2020-08-25 12:31 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Dave Airlie, Neil Armstrong, David Airlie, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Laurent Pinchart,
	Sam Ravnborg, driverdevel, Daniel Borkmann, John Fastabend,
	Xiubin Zhang, Wei Xu, Xinliang Liu, Xinwei Kong, Tomi Valkeinen,
	Bogdan Togorean, Jakub Kicinski, Laurentiu Palcu, linux-media,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Liwei Cai, Jesper Dangaard Brouer, Manivannan Sadhasivam,
	Chen Feng, Alexei Starovoitov,
	moderated list:DMA BUFFER SHARING FRAMEWORK, Rob Herring,
	mauro.chehab, Rob Clark, linux-arm-kernel, Greg Kroah-Hartman,
	lkml, Liuyao An, Network Development, Rongrong Zou,
	BPF Mailing List, David S. Miller

Hi Mauro,

On Tue, 25 Aug 2020 at 12:30, Mauro Carvalho Chehab
<mchehab+huawei@kernel.org> wrote:
> Sorry, but I can't agree that review is more important than to be able
> to properly indicate copyrights in a valid way at the legal systems that
> it would apply ;-)

The way to properly indicate copyright coverage is to insert a
copyright statement in the file. This has been the accepted way of
communicating copyright notices since approximately the dawn of time.
The value of the 'author' field within a chain of git commits does not
have privileged legal value.

If what you were saying is true, it would be impossible for any
project to copy code from any other project, unless they did git
filter-branch and made sure to follow renames too. As others have
noted, it would also be impossible for any patches to be developed
collaboratively by different copyright holders, or for maintainers to
apply changes.

This is accepted community practice and has passed signoffs from a
million different lawyers and copyright holders. If you wish to break
with this and do something different, the onus is on you to provide
the community with _specific_ legal advice; if this is accepted, the
development model would have to drastically change in the presence of
single pieces of code developed by multiple distinct copyright
holders.

Cheers,
Daniel

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
       [not found]           ` <20200824180225.1a515b6a@coco.lan>
                               ` (2 preceding siblings ...)
  2020-08-24 21:24             ` Sam Ravnborg
@ 2020-08-25 18:11             ` Sam Ravnborg
  2020-08-25 20:21             ` Sam Ravnborg
  4 siblings, 0 replies; 42+ messages in thread
From: Sam Ravnborg @ 2020-08-25 18:11 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Greg Kroah-Hartman, Neil Armstrong, Xinliang Liu, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Laurent Pinchart, devel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	David Airlie, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Laurentiu Palcu, linux-media, devicetree, Liwei Cai,
	Jesper Dangaard Brouer, Manivannan Sadhasivam, Chen Feng,
	Alexei Starovoitov, linaro-mm-sig, Rob Herring, Jakub Kicinski,
	mauro.chehab, Rob Clark, linux-arm-kernel, netdev, linux-kernel,
	Liuyao An, Rongrong Zou, bpf, David S. Miller

Hi Mauro

> Before posting the big patch series again, let me send the new
> version folded into a single patch.
> 
> If you'd like to see the entire thing, I'm placing it here:
> 
> 	https://gitlab.freedesktop.org/mchehab_kernel/hikey-970/-/commits/hikey970_v2/

Review 3/3

For next submission then to ease review it would be nice that the patch
is spilt up a little. Maybe something like:
- HW specific stuff in two patches (header fiels with register + setup
  code)
- Display driver files
- DSI driver files
- build stuff (Makefile, Kconfig fragments)
So all splits on file level - which should be easy to do.

This will make it easier for more people to give feedback. It is a bit
much to walk through 4k loc or what the full size is.
And then we can also provide a-b or r-b for fragments so the reviewed
parts can be ignored for later reviews.


For the DSI parts I may be hit by the old "when you have a hammer then
everything looks like a nail syndrome".
In my case the hammer is the bridge interface.

Suggestions:
- Move encoder to display driver
- Move connector creation to display driver (using
  drm_bridge_connector_init())
- Use drm_bridge interface for the DSI driver parts
- Maybe use the HDMI bridge driver as a chained driver - I did not look
  to close on this
- Use the standard bridge interface to find the bridge and drop use of
  the component framework

I hope that some other drm people chime in here.
Either to tell this is non-sense or confirm this is the way to go.

The above does not give any hint how to use the gpio_mux to shift
between the panel and HDMI. This logic needs to be in the display driver
as the bridge driver will only be used for HDMI - as I understand the
code. And I do not know how to do it.

Some details in the following that are not related to the above.

	Sam

> diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_dw_drm_dsi.c b/drivers/staging/hikey9xx/gpu/kirin9xx_dw_drm_dsi.c
> new file mode 100644
> index 000000000000..a2eed961b7d5
> --- /dev/null
> +++ b/drivers/staging/hikey9xx/gpu/kirin9xx_dw_drm_dsi.c
> @@ -0,0 +1,2126 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * DesignWare MIPI DSI Host Controller v1.02 driver
> + *
> + * Copyright (c) 2016 Linaro Limited.
> + * Copyright (c) 2014-2016 Hisilicon Limited.
> + * Copyright (c) 2014-2020, Huawei Technologies Co., Ltd
> + *
> + * Author:
> + *	<shizongxuan@huawei.com>
> + *	<zhangxiubin@huawei.com>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/component.h>
> +#include <linux/of_device.h>
> +#include <linux/of_graph.h>
> +#include <linux/iopoll.h>
> +#include <video/mipi_display.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/of_address.h>
Sort

> +
> +#include <drm/drm_of.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_mipi_dsi.h>
> +#include <drm/drm_encoder.h>
> +#include <drm/drm_device.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_panel.h>
> +#include <drm/drm_probe_helper.h>
Sort

> +
> +#include "kirin9xx_dw_dsi_reg.h"
> +#include "kirin9xx_dpe.h"
> +#include "kirin9xx_drm_drv.h"
> +#include "kirin9xx_drm_dpe_utils.h"
Sort

> +
> +#define PHY_REF_CLK_RATE	19200000
> +#define PHY_REF_CLK_PERIOD_PS	(1000000000 / (PHY_REF_CLK_RATE / 1000))
> +
> +#define encoder_to_dsi(encoder) \
> +	container_of(encoder, struct dw_dsi, encoder)
> +#define host_to_dsi(host) \
> +	container_of(host, struct dw_dsi, host)
> +#define connector_to_dsi(connector) \
> +	container_of(connector, struct dw_dsi, connector)
Move the upcast next to the struct definition.


> +#define DSS_REDUCE(x)	((x) > 0 ? ((x) - 1) : (x))
> +
> +enum dsi_output_client {
> +	OUT_HDMI = 0,
> +	OUT_PANEL,
> +	OUT_MAX
> +};
> +
> +struct mipi_phy_params {
I did not check all fiels but I managed to find at least one unused
field. Cheack and delete what is unused.
> +	u64 lane_byte_clk;
> +	u32 clk_division;
> +
> +	u32 clk_lane_lp2hs_time;
> +	u32 clk_lane_hs2lp_time;
> +	u32 data_lane_lp2hs_time;
> +	u32 data_lane_hs2lp_time;
> +	u32 clk2data_delay;
> +	u32 data2clk_delay;
> +
> +	u32 clk_pre_delay;
> +	u32 clk_post_delay;
> +	u32 clk_t_lpx;
> +	u32 clk_t_hs_prepare;
> +	u32 clk_t_hs_zero;
> +	u32 clk_t_hs_trial;
> +	u32 clk_t_wakeup;
> +	u32 data_pre_delay;
> +	u32 data_post_delay;
> +	u32 data_t_lpx;
> +	u32 data_t_hs_prepare;
> +	u32 data_t_hs_zero;
> +	u32 data_t_hs_trial;
> +	u32 data_t_ta_go;
> +	u32 data_t_ta_get;
> +	u32 data_t_wakeup;
> +
> +	u32 phy_stop_wait_time;
> +
> +	u32 rg_vrefsel_vcm;
> +	u32 rg_hstx_ckg_sel;
> +	u32 rg_pll_fbd_div5f;
> +	u32 rg_pll_fbd_div1f;
> +	u32 rg_pll_fbd_2p;
> +	u32 rg_pll_enbwt;
> +	u32 rg_pll_fbd_p;
> +	u32 rg_pll_fbd_s;
> +	u32 rg_pll_pre_div1p;
> +	u32 rg_pll_pre_p;
> +	u32 rg_pll_vco_750m;
> +	u32 rg_pll_lpf_rs;
> +	u32 rg_pll_lpf_cs;
> +	u32 rg_pll_enswc;
> +	u32 rg_pll_chp;
> +
Some indent gone wrong here?
> +	u32 pll_register_override;		/* 0x1E[0] */
> +	u32 pll_power_down;			/* 0x1E[1] */
> +	u32 rg_band_sel;				/* 0x1E[2] */
> +	u32 rg_phase_gen_en;		/* 0x1E[3] */
> +	u32 reload_sel;				/* 0x1E[4] */
> +	u32 rg_pll_cp_p;				/* 0x1E[7:5] */
> +	u32 rg_pll_refsel;				/* 0x16[1:0] */
> +	u32 rg_pll_cp;				/* 0x16[7:5] */
> +	u32 load_command;
> +
> +	/* for CDPHY */
> +	u32 rg_cphy_div;	/* Q */
> +	u32 rg_div;		/* M 0x4A[7:0] */
> +	u32 rg_pre_div;	/* N 0x49[0] */
> +	u32 rg_320m;		/* 0x48[2] */
> +	u32 rg_2p5g;		/* 0x48[1] */
> +	u32 rg_0p8v;		/* 0x48[0] */
> +	u32 rg_lpf_r;		/* 0x46[5:4] */
> +	u32 rg_cp;			/* 0x46[3:0] */
> +	u32 t_prepare;
> +	u32 t_lpx;
> +	u32 t_prebegin;
> +	u32 t_post;
> +};
> +
> +struct dsi_hw_ctx {
> +	void __iomem *base;
> +	char __iomem *peri_crg_base;
> +	void __iomem *pctrl_base;
> +
> +	u32 g_dss_version_tag;
> +
> +	struct clk *dss_dphy0_ref_clk;
> +	struct clk *dss_dphy1_ref_clk;
Not used, delete.
> +	struct clk *dss_dphy0_cfg_clk;
> +	struct clk *dss_dphy1_cfg_clk;
Not used, delete.

> +	struct clk *dss_pclk_dsi0_clk;
> +	struct clk *dss_pclk_dsi1_clk;
Not sued, delete.
> +};
> +
> +struct dw_dsi_client {
> +	u32 lanes;
> +	u32 phy_clock; /* in kHz */
> +	enum mipi_dsi_pixel_format format;
> +	unsigned long mode_flags;
> +};
> +
> +struct mipi_panel_info {
Some filed in the following are either not used or in some cases only
read. Clean it up.

Example: clk_t_hs_exit_adjust is assigned 0 and only read.
Looks like stuff to drop.

> +	u8 dsi_version;
> +	u8 vc;
> +	u8 lane_nums;
> +	u8 lane_nums_select_support;
> +	u8 color_mode;
> +	u32 dsi_bit_clk; /* clock lane(p/n) */
> +	u32 burst_mode;
> +	u32 max_tx_esc_clk;
> +	u8 non_continue_en;
> +
> +	u32 dsi_bit_clk_val1;
> +	u32 dsi_bit_clk_val2;
> +	u32 dsi_bit_clk_val3;
> +	u32 dsi_bit_clk_val4;
> +	u32 dsi_bit_clk_val5;
> +	u32 dsi_bit_clk_upt;
> +	/* uint32_t dsi_pclk_rate; */
> +
> +	u32 hs_wr_to_time;
> +
> +	/* dphy config parameter adjust */
> +	u32 clk_post_adjust;
> +	u32 clk_pre_adjust;
> +	u32 clk_pre_delay_adjust;
> +	u32 clk_t_hs_exit_adjust;
> +	u32 clk_t_hs_trial_adjust;
> +	u32 clk_t_hs_prepare_adjust;
> +	int clk_t_lpx_adjust;
> +	u32 clk_t_hs_zero_adjust;
> +	u32 data_post_delay_adjust;
> +	int data_t_lpx_adjust;
> +	u32 data_t_hs_prepare_adjust;
> +	u32 data_t_hs_zero_adjust;
> +	u32 data_t_hs_trial_adjust;
> +	u32 rg_vrefsel_vcm_adjust;
> +
> +	/* only for Chicago<3660> use */
> +	u32 rg_vrefsel_vcm_clk_adjust;
> +	u32 rg_vrefsel_vcm_data_adjust;
> +
> +	u32 phy_mode;  /* 0: DPHY, 1:CPHY */
> +	u32 lp11_flag;
> +};
> +
> +struct ldi_panel_info {
Fileds are only partially used.

> +	u32 h_back_porch;
> +	u32 h_front_porch;
> +	u32 h_pulse_width;
> +
> +	/*
> +	 * note: vbp > 8 if used overlay compose,
> +	 * also lcd vbp > 8 in lcd power on sequence
> +	 */
> +	u32 v_back_porch;
> +	u32 v_front_porch;
> +	u32 v_pulse_width;
> +
> +	u8 hsync_plr;
> +	u8 vsync_plr;
> +	u8 pixelclk_plr;
> +	u8 data_en_plr;
> +
> +	/* for cabc */
> +	u8 dpi0_overlap_size;
> +	u8 dpi1_overlap_size;
> +};
> +
> +struct dw_dsi {
> +	struct drm_encoder encoder;
> +	struct drm_bridge *bridge;
> +	struct drm_panel *panel;
> +	struct mipi_dsi_host host;
> +	struct drm_connector connector; /* connector for panel */
> +	struct drm_display_mode cur_mode;
> +	struct dsi_hw_ctx *ctx;
Would it be possible to embed dsi_hw_ctx?
So everything is allocated in one go.

> +	struct mipi_phy_params phy;
> +	struct mipi_panel_info mipi;
> +	struct ldi_panel_info ldi;
> +	u32 lanes;
> +	enum mipi_dsi_pixel_format format;
> +	unsigned long mode_flags;
> +	struct gpio_desc *gpio_mux;
> +	struct dw_dsi_client client[OUT_MAX];
> +	enum dsi_output_client cur_client, attached_client;
> +	bool enable;
> +};
> +
> +struct dsi_data {
> +	struct dw_dsi dsi;
> +	struct dsi_hw_ctx ctx;
> +};
If dsi_hw_ctx is embedded in dw_dsi then this struct can be dropped.
> +
> +struct dsi_phy_range {
> +	u32 min_range_kHz;
> +	u32 max_range_kHz;
> +	u32 pll_vco_750M;
> +	u32 hstx_ckg_sel;
> +};
Not used, delete.
> +
> +static const struct dsi_phy_range dphy_range_info[] = {
> +	{   46875,    62500,   1,    7 },
> +	{   62500,    93750,   0,    7 },
> +	{   93750,   125000,   1,    6 },
> +	{  125000,   187500,   0,    6 },
> +	{  187500,   250000,   1,    5 },
> +	{  250000,   375000,   0,    5 },
> +	{  375000,   500000,   1,    4 },
> +	{  500000,   750000,   0,    4 },
> +	{  750000,  1000000,   1,    0 },
> +	{ 1000000,  1500000,   0,    0 }
> +};
Not used, delete.

> +
> +/*
> + * Except for debug, this is identical to the one defined at
> + * kirin9xx_drm_dpe_utils.h.
> + */
> +
> +void dsi_set_output_client(struct drm_device *dev)
> +{
> +	struct drm_connector_list_iter conn_iter;
> +	struct drm_connector *connector;
> +	enum dsi_output_client client;
> +	struct drm_encoder *encoder;
> +	struct dw_dsi *dsi;
> +
> +	mutex_lock(&dev->mode_config.mutex);
> +
> +	/* find dsi encoder */
> +	drm_for_each_encoder(encoder, dev)
> +		if (encoder->encoder_type == DRM_MODE_ENCODER_DSI)
> +			break;
> +	dsi = encoder_to_dsi(encoder);
> +
> +	/* find HDMI connector */
> +	drm_connector_list_iter_begin(dev, &conn_iter);
> +	drm_for_each_connector_iter(connector, &conn_iter)
> +		if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA)
> +			break;
> +
> +	/*
> +	 * set the proper dsi output client
> +	 */
> +	client = connector->status == connector_status_connected ?
> +		OUT_HDMI : OUT_PANEL;
> +
> +	if (client != dsi->cur_client) {
> +		gpiod_set_value_cansleep(dsi->gpio_mux, client);
> +		dsi->cur_client = client;
> +
> +		msleep(20);
> +
> +		drm_info(dev, "client change to %s\n",
> +			 client == OUT_HDMI ? "HDMI" : "panel");
> +	}
> +
> +	mutex_unlock(&dev->mode_config.mutex);
> +}
> +EXPORT_SYMBOL(dsi_set_output_client);
> +
> +static void kirin970_get_dsi_dphy_ctrl(struct dw_dsi *dsi,
> +				       struct mipi_phy_params *phy_ctrl, u32 id)
> +{
> +	struct mipi_panel_info *mipi = NULL;
> +	struct drm_display_mode *mode = NULL;
> +	u32 dphy_req_kHz;
> +	int bpp;
> +	u32 ui = 0;
> +	u32 m_pll = 0;
> +	u32 n_pll = 0;
> +	u64 lane_clock = 0;
> +	u64 vco_div = 1;
> +	u32 m_n_fract = 0;
> +	u32 m_n_int = 0;
> +
> +	u32 accuracy = 0;
> +	u32 unit_tx_byte_clk_hs = 0;
> +	u32 clk_post = 0;
> +	u32 clk_pre = 0;
> +	u32 clk_t_hs_exit = 0;
> +	u32 clk_pre_delay = 0;
> +	u32 clk_t_hs_prepare = 0;
> +	u32 clk_t_lpx = 0;
> +	u32 clk_t_hs_zero = 0;
> +	u32 clk_t_hs_trial = 0;
> +	u32 data_post_delay = 0;
> +	u32 data_t_hs_prepare = 0;
> +	u32 data_t_hs_zero = 0;
> +	u32 data_t_hs_trial = 0;
> +	u32 data_t_lpx = 0;
> +
> +	WARN_ON(!phy_ctrl);
> +	WARN_ON(!dsi);
> +
> +	mode = &dsi->cur_mode;
> +	mipi = &dsi->mipi;
> +
> +	/*
> +	 * count phy params
> +	 */
> +	bpp = mipi_dsi_pixel_format_to_bpp(dsi->client[id].format);
> +	if (bpp < 0)
> +		return;
> +
> +	if (mode->clock > 80000)
> +		dsi->client[id].lanes = 4;
> +	else
> +		dsi->client[id].lanes = 3;
> +
> +	if (dsi->client[id].phy_clock)
> +		dphy_req_kHz = dsi->client[id].phy_clock;
> +	else
> +		dphy_req_kHz = mode->clock * bpp / dsi->client[id].lanes;
> +
> +	lane_clock = dphy_req_kHz / 1000;
> +	DRM_DEBUG("Expected : lane_clock = %llu M\n", lane_clock);
> +
> +	/************************  PLL parameters config  *********************/
> +	/* chip spec : */
> +	/* If the output data rate is below 320 Mbps, RG_BNAD_SEL should be set to 1. */
> +	/* At this mode a post divider of 1/4 will be applied to VCO. */
> +	if ((lane_clock >= 320) && (lane_clock <= 2500)) {
> +		phy_ctrl->rg_band_sel = 0;
> +		vco_div = 1;
> +	} else if ((lane_clock >= 80) && (lane_clock < 320)) {
> +		phy_ctrl->rg_band_sel = 1;
> +		vco_div = 4;
> +	} else {
> +		DRM_ERROR("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;
> +
> +	n_pll = 2;
> +
> +	m_pll = (u32)(lane_clock * vco_div * n_pll * 1000000UL / DEFAULT_MIPI_CLK_RATE);
> +
> +	lane_clock = m_pll * (DEFAULT_MIPI_CLK_RATE / n_pll) / vco_div;
> +	if (lane_clock > 750000000)
> +		phy_ctrl->rg_cp = 3;
> +	else if ((lane_clock >= 80000000) && (lane_clock <= 750000000))
> +		phy_ctrl->rg_cp = 1;
> +	else
> +		DRM_ERROR("80M <= lane_clock< = 2500M, not support lane_clock = %llu M.\n",
> +			  lane_clock);
> +
> +	/* chip spec : */
> +	phy_ctrl->rg_pre_div = n_pll - 1;
> +	phy_ctrl->rg_div = m_pll;
> +	phy_ctrl->rg_0p8v = 0;
> +	phy_ctrl->rg_2p5g = 1;
> +	phy_ctrl->rg_320m = 0;
> +	phy_ctrl->rg_lpf_r = 0;
> +
> +	/* TO DO HSTX select VCM VREF */
> +	phy_ctrl->rg_vrefsel_vcm = 0x5d;
> +
> +	/********************  clock/data lane parameters config  ******************/
> +	accuracy = 10;
> +	ui =  (u32)(10 * 1000000000UL * accuracy / lane_clock);
> +	/* unit of measurement */
> +	unit_tx_byte_clk_hs = 8 * ui;
> +
> +	/* D-PHY Specification : 60ns + 52*UI <= clk_post */
> +	clk_post = 600 * accuracy + 52 * ui + unit_tx_byte_clk_hs + mipi->clk_post_adjust * ui;
> +
> +	/* D-PHY Specification : clk_pre >= 8*UI */
> +	clk_pre = 8 * ui + unit_tx_byte_clk_hs + mipi->clk_pre_adjust * ui;
> +
> +	/* D-PHY Specification : clk_t_hs_exit >= 100ns */
> +	clk_t_hs_exit = 1000 * accuracy + 100 * accuracy + mipi->clk_t_hs_exit_adjust * ui;
> +
> +	/* clocked by TXBYTECLKHS */
> +	clk_pre_delay = 0 + mipi->clk_pre_delay_adjust * ui;
> +
> +	/* D-PHY Specification : clk_t_hs_trial >= 60ns */
> +	/* clocked by TXBYTECLKHS */
> +	clk_t_hs_trial = 600 * accuracy + 3 * unit_tx_byte_clk_hs + mipi->clk_t_hs_trial_adjust * ui;
> +
> +	/* D-PHY Specification : 38ns <= clk_t_hs_prepare <= 95ns */
> +	/* clocked by TXBYTECLKHS */
> +	clk_t_hs_prepare = 660 * accuracy;
> +
> +	/* clocked by TXBYTECLKHS */
> +	data_post_delay = 0 + mipi->data_post_delay_adjust * ui;
> +
> +	/* D-PHY Specification : data_t_hs_trial >= max( n*8*UI, 60ns + n*4*UI ), n = 1 */
> +	/* clocked by TXBYTECLKHS */
> +	data_t_hs_trial = ((600 * accuracy + 4 * ui) >= (8 * ui) ? (600 * accuracy + 4 * ui) : (8 * ui)) +
> +		2 * unit_tx_byte_clk_hs + mipi->data_t_hs_trial_adjust * ui;
> +
> +	/* D-PHY Specification : 40ns + 4*UI <= data_t_hs_prepare <= 85ns + 6*UI */
> +	/* clocked by TXBYTECLKHS */
> +	data_t_hs_prepare = 400 * accuracy + 4 * ui;
> +	/* D-PHY chip spec : clk_t_lpx + clk_t_hs_prepare > 200ns */
> +	/* D-PHY Specification : clk_t_lpx >= 50ns */
> +	/* clocked by TXBYTECLKHS */
> +	clk_t_lpx = (uint32_t)(2000 * accuracy + 10 * accuracy + mipi->clk_t_lpx_adjust * ui - clk_t_hs_prepare);
> +
> +	/* D-PHY Specification : clk_t_hs_zero + clk_t_hs_prepare >= 300 ns */
> +	/* clocked by TXBYTECLKHS */
> +	clk_t_hs_zero = (uint32_t)(3000 * accuracy + 3 * unit_tx_byte_clk_hs + mipi->clk_t_hs_zero_adjust * ui - clk_t_hs_prepare);
> +
> +	/* D-PHY chip spec : data_t_lpx + data_t_hs_prepare > 200ns */
> +	/* D-PHY Specification : data_t_lpx >= 50ns */
> +	/* clocked by TXBYTECLKHS */
> +	data_t_lpx = (uint32_t)(2000 * accuracy + 10 * accuracy + mipi->data_t_lpx_adjust * ui - data_t_hs_prepare);
> +
> +	/* D-PHY Specification : data_t_hs_zero + data_t_hs_prepare >= 145ns + 10*UI */
> +	/* clocked by TXBYTECLKHS */
> +	data_t_hs_zero = (uint32_t)(1450 * accuracy + 10 * ui +
> +		3 * unit_tx_byte_clk_hs + mipi->data_t_hs_zero_adjust * ui - data_t_hs_prepare);
> +
> +	phy_ctrl->clk_pre_delay = DIV_ROUND_UP(clk_pre_delay, unit_tx_byte_clk_hs);
> +	phy_ctrl->clk_t_hs_prepare = DIV_ROUND_UP(clk_t_hs_prepare, unit_tx_byte_clk_hs);
> +	phy_ctrl->clk_t_lpx = DIV_ROUND_UP(clk_t_lpx, unit_tx_byte_clk_hs);
> +	phy_ctrl->clk_t_hs_zero = DIV_ROUND_UP(clk_t_hs_zero, unit_tx_byte_clk_hs);
> +	phy_ctrl->clk_t_hs_trial = DIV_ROUND_UP(clk_t_hs_trial, unit_tx_byte_clk_hs);
> +
> +	phy_ctrl->data_post_delay = DIV_ROUND_UP(data_post_delay, unit_tx_byte_clk_hs);
> +	phy_ctrl->data_t_hs_prepare = DIV_ROUND_UP(data_t_hs_prepare, unit_tx_byte_clk_hs);
> +	phy_ctrl->data_t_lpx = DIV_ROUND_UP(data_t_lpx, unit_tx_byte_clk_hs);
> +	phy_ctrl->data_t_hs_zero = DIV_ROUND_UP(data_t_hs_zero, unit_tx_byte_clk_hs);
> +	phy_ctrl->data_t_hs_trial = DIV_ROUND_UP(data_t_hs_trial, unit_tx_byte_clk_hs);
> +
> +	phy_ctrl->clk_post_delay = phy_ctrl->data_t_hs_trial + DIV_ROUND_UP(clk_post, unit_tx_byte_clk_hs);
> +	phy_ctrl->data_pre_delay = phy_ctrl->clk_pre_delay + 2 + phy_ctrl->clk_t_lpx +
> +		phy_ctrl->clk_t_hs_prepare + phy_ctrl->clk_t_hs_zero + 8 + DIV_ROUND_UP(clk_pre, unit_tx_byte_clk_hs);
> +
> +	phy_ctrl->clk_lane_lp2hs_time = phy_ctrl->clk_pre_delay + phy_ctrl->clk_t_lpx + phy_ctrl->clk_t_hs_prepare +
> +		phy_ctrl->clk_t_hs_zero + 5 + 7;
> +	phy_ctrl->clk_lane_hs2lp_time = phy_ctrl->clk_t_hs_trial + phy_ctrl->clk_post_delay + 8 + 4;
> +	phy_ctrl->data_lane_lp2hs_time = phy_ctrl->data_pre_delay + phy_ctrl->data_t_lpx + phy_ctrl->data_t_hs_prepare +
> +		phy_ctrl->data_t_hs_zero + 5 + 7;
> +	phy_ctrl->data_lane_hs2lp_time = phy_ctrl->data_t_hs_trial + 8 + 5;
> +
> +	phy_ctrl->phy_stop_wait_time = phy_ctrl->clk_post_delay + 4 + phy_ctrl->clk_t_hs_trial +
> +		DIV_ROUND_UP(clk_t_hs_exit, unit_tx_byte_clk_hs) - (phy_ctrl->data_post_delay + 4 + 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) % mipi->max_tx_esc_clk) > 0) ?
> +		(uint32_t)(phy_ctrl->lane_byte_clk / 2 / mipi->max_tx_esc_clk + 1) :
> +		(uint32_t)(phy_ctrl->lane_byte_clk / 2 / mipi->max_tx_esc_clk);
> +
> +	DRM_DEBUG("DPHY clock_lane and data_lane config :\n"
> +		"lane_clock = %llu, n_pll=%d, m_pll=%d\n"
> +		"rg_cp=%d\n"
> +		"rg_band_sel=%d\n"
> +		"rg_vrefsel_vcm=%d\n"
> +		"clk_pre_delay=%d\n"
> +		"clk_post_delay=%d\n"
> +		"clk_t_hs_prepare=%d\n"
> +		"clk_t_lpx=%d\n"
> +		"clk_t_hs_zero=%d\n"
> +		"clk_t_hs_trial=%d\n"
> +		"data_pre_delay=%d\n"
> +		"data_post_delay=%d\n"
> +		"data_t_hs_prepare=%d\n"
> +		"data_t_lpx=%d\n"
> +		"data_t_hs_zero=%d\n"
> +		"data_t_hs_trial=%d\n"
> +		"clk_lane_lp2hs_time=%d\n"
> +		"clk_lane_hs2lp_time=%d\n"
> +		"data_lane_lp2hs_time=%d\n"
> +		"data_lane_hs2lp_time=%d\n"
> +		"phy_stop_wait_time=%d\n",
> +		lane_clock, n_pll, m_pll,
> +		phy_ctrl->rg_cp,
> +		phy_ctrl->rg_band_sel,
> +		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->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 void kirin960_get_dsi_phy_ctrl(struct dw_dsi *dsi,
> +				      struct mipi_phy_params *phy_ctrl, u32 id)
> +{
> +	struct mipi_panel_info *mipi = NULL;
> +	struct drm_display_mode *mode = NULL;
> +	u32 dphy_req_kHz;
> +	int bpp;
> +	u32 ui = 0;
> +	u32 m_pll = 0;
> +	u32 n_pll = 0;
> +	u32 m_n_fract = 0;
> +	u32 m_n_int = 0;
> +	u64 lane_clock = 0;
> +	u64 vco_div = 1;
> +
> +	u32 accuracy = 0;
> +	u32 unit_tx_byte_clk_hs = 0;
> +	u32 clk_post = 0;
> +	u32 clk_pre = 0;
> +	u32 clk_t_hs_exit = 0;
> +	u32 clk_pre_delay = 0;
> +	u32 clk_t_hs_prepare = 0;
> +	u32 clk_t_lpx = 0;
> +	u32 clk_t_hs_zero = 0;
> +	u32 clk_t_hs_trial = 0;
> +	u32 data_post_delay = 0;
> +	u32 data_t_hs_prepare = 0;
> +	u32 data_t_hs_zero = 0;
> +	u32 data_t_hs_trial = 0;
> +	u32 data_t_lpx = 0;
> +	u32 clk_pre_delay_reality = 0;
> +	u32 clk_t_hs_zero_reality = 0;
> +	u32 clk_post_delay_reality = 0;
> +	u32 data_t_hs_zero_reality = 0;
> +	u32 data_post_delay_reality = 0;
> +	u32 data_pre_delay_reality = 0;
> +
> +	WARN_ON(!phy_ctrl);
> +	WARN_ON(!dsi);
> +
> +	mode = &dsi->cur_mode;
> +	mipi = &dsi->mipi;
> +
> +	/*
> +	 * count phy params
> +	 */
> +	bpp = mipi_dsi_pixel_format_to_bpp(dsi->client[id].format);
> +	if (bpp < 0)
> +		return;
> +
> +	if (mode->clock > 80000)
> +		dsi->client[id].lanes = 4;
> +	else
> +		dsi->client[id].lanes = 3;
> +
> +	if (dsi->client[id].phy_clock)
> +		dphy_req_kHz = dsi->client[id].phy_clock;
> +	else
> +		dphy_req_kHz = mode->clock * bpp / dsi->client[id].lanes;
> +
> +	lane_clock = dphy_req_kHz / 1000;
> +	DRM_INFO("Expected : lane_clock = %llu M\n", lane_clock);
> +
> +	/************************  PLL parameters config  *********************/
> +
> +	/*
> +	 * chip spec :
> +	 *	If the output data rate is below 320 Mbps,
> +	 *	RG_BNAD_SEL should be set to 1.
> +	 *	At this mode a post divider of 1/4 will be applied to VCO.
> +	 */
> +	if ((lane_clock >= 320) && (lane_clock <= 2500)) {
> +		phy_ctrl->rg_band_sel = 0;	/* 0x1E[2] */
> +		vco_div = 1;
> +	} else if ((lane_clock >= 80) && (lane_clock < 320)) {
> +		phy_ctrl->rg_band_sel = 1;
> +		vco_div = 4;
> +	} else {
> +		DRM_ERROR("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 set rg_pll_enswc=1, rg_pll_fbd_s can't be 0 */
> +	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 {
> +				DRM_ERROR("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 {
> +		DRM_ERROR("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;
> +	DRM_INFO("Config : lane_clock = %llu\n", lane_clock);
> +
> +	/* FIXME : */
> +	phy_ctrl->rg_pll_cp = 1;		/* 0x16[7:5] */
> +	phy_ctrl->rg_pll_cp_p = 3;		/* 0x1E[7:5] */
> +
> +	/* test_code_0x14 other parameters config */
> +	phy_ctrl->rg_pll_enbwt = 0;	/* 0x14[2] */
> +	phy_ctrl->rg_pll_chp = 0;		/* 0x14[1:0] */
> +
> +	/* test_code_0x16 other parameters config,  0x16[3:2] reserved */
> +	phy_ctrl->rg_pll_lpf_cs = 0;	/* 0x16[4] */
> +	phy_ctrl->rg_pll_refsel = 1;		/* 0x16[1:0] */
> +
> +	/* test_code_0x1E other parameters config */
> +	phy_ctrl->reload_sel = 1;			/* 0x1E[4] */
> +	phy_ctrl->rg_phase_gen_en = 1;	/* 0x1E[3] */
> +	phy_ctrl->pll_power_down = 0;		/* 0x1E[1] */
> +	phy_ctrl->pll_register_override = 1;	/* 0x1E[0] */
> +
> +	/* HSTX select VCM VREF */
> +	phy_ctrl->rg_vrefsel_vcm = 0x55;
> +	if (mipi->rg_vrefsel_vcm_clk_adjust != 0)
> +		phy_ctrl->rg_vrefsel_vcm = (phy_ctrl->rg_vrefsel_vcm & 0x0F) |
> +			((mipi->rg_vrefsel_vcm_clk_adjust & 0x0F) << 4);
> +
> +	if (mipi->rg_vrefsel_vcm_data_adjust != 0)
> +		phy_ctrl->rg_vrefsel_vcm = (phy_ctrl->rg_vrefsel_vcm & 0xF0) |
> +			(mipi->rg_vrefsel_vcm_data_adjust & 0x0F);
> +
> +	/* if reload_sel = 1, need to set load_command */
> +	phy_ctrl->load_command = 0x5A;
> +
> +	/********************  clock/data lane parameters config  ******************/
> +	accuracy = 10;
> +	ui =  10 * 1000000000UL * accuracy / lane_clock;
> +	/* unit of measurement */
> +	unit_tx_byte_clk_hs = 8 * ui;
> +
> +	/* D-PHY Specification : 60ns + 52*UI <= clk_post */
> +	clk_post = 600 * accuracy + 52 * ui + mipi->clk_post_adjust * ui;
> +
> +	/* D-PHY Specification : clk_pre >= 8*UI */
> +	clk_pre = 8 * ui + mipi->clk_pre_adjust * ui;
> +
> +	/* D-PHY Specification : clk_t_hs_exit >= 100ns */
> +	clk_t_hs_exit = 1000 * accuracy + mipi->clk_t_hs_exit_adjust * ui;
> +
> +	/* clocked by TXBYTECLKHS */
> +	clk_pre_delay = 0 + mipi->clk_pre_delay_adjust * ui;
> +
> +	/* D-PHY Specification : clk_t_hs_trial >= 60ns */
> +	/* clocked by TXBYTECLKHS */
> +	clk_t_hs_trial = 600 * accuracy + 3 * unit_tx_byte_clk_hs + mipi->clk_t_hs_trial_adjust * ui;
> +
> +	/* D-PHY Specification : 38ns <= clk_t_hs_prepare <= 95ns */
> +	/* clocked by TXBYTECLKHS */
> +	if (mipi->clk_t_hs_prepare_adjust == 0)
> +		mipi->clk_t_hs_prepare_adjust = 43;
> +
> +	clk_t_hs_prepare = ((380 * accuracy + mipi->clk_t_hs_prepare_adjust * ui) <= (950 * accuracy - 8 * ui)) ?
> +		(380 * accuracy + mipi->clk_t_hs_prepare_adjust * ui) : (950 * accuracy - 8 * ui);
> +
> +	/* clocked by TXBYTECLKHS */
> +	data_post_delay = 0 + mipi->data_post_delay_adjust * ui;
> +
> +	/* D-PHY Specification : data_t_hs_trial >= max( n*8*UI, 60ns + n*4*UI ), n = 1 */
> +	/* clocked by TXBYTECLKHS */
> +	data_t_hs_trial = ((600 * accuracy + 4 * ui) >= (8 * ui) ? (600 * accuracy + 4 * ui) : (8 * ui)) + 8 * ui +
> +		3 * unit_tx_byte_clk_hs + mipi->data_t_hs_trial_adjust * ui;
> +
> +	/* D-PHY Specification : 40ns + 4*UI <= data_t_hs_prepare <= 85ns + 6*UI */
> +	/* clocked by TXBYTECLKHS */
> +	if (mipi->data_t_hs_prepare_adjust == 0)
> +		mipi->data_t_hs_prepare_adjust = 35;
> +
> +	data_t_hs_prepare = ((400  * accuracy + 4 * ui + mipi->data_t_hs_prepare_adjust * ui) <= (850 * accuracy + 6 * ui - 8 * ui)) ?
> +		(400  * accuracy + 4 * ui + mipi->data_t_hs_prepare_adjust * ui) : (850 * accuracy + 6 * ui - 8 * ui);
> +
> +	/* D-PHY chip spec : clk_t_lpx + clk_t_hs_prepare > 200ns */
> +	/* D-PHY Specification : clk_t_lpx >= 50ns */
> +	/* clocked by TXBYTECLKHS */
> +	clk_t_lpx = (((2000 * accuracy - clk_t_hs_prepare) >= 500 * accuracy) ?
> +		((2000 * accuracy - clk_t_hs_prepare)) : (500 * accuracy)) +
> +		mipi->clk_t_lpx_adjust * ui;
> +
> +	/* D-PHY Specification : clk_t_hs_zero + clk_t_hs_prepare >= 300 ns */
> +	/* clocked by TXBYTECLKHS */
> +	clk_t_hs_zero = 3000 * accuracy - clk_t_hs_prepare + 3 * unit_tx_byte_clk_hs + mipi->clk_t_hs_zero_adjust * ui;
> +
> +	/* D-PHY chip spec : data_t_lpx + data_t_hs_prepare > 200ns */
> +	/* D-PHY Specification : data_t_lpx >= 50ns */
> +	/* clocked by TXBYTECLKHS */
> +	data_t_lpx = clk_t_lpx + mipi->data_t_lpx_adjust * ui; /* 2000 * accuracy - data_t_hs_prepare; */
> +
> +	/* D-PHY Specification : data_t_hs_zero + data_t_hs_prepare >= 145ns + 10*UI */
> +	/* clocked by TXBYTECLKHS */
> +	data_t_hs_zero = 1450 * accuracy + 10 * ui - data_t_hs_prepare +
> +		3 * unit_tx_byte_clk_hs + mipi->data_t_hs_zero_adjust * ui;
> +
> +	phy_ctrl->clk_pre_delay = DIV_ROUND_UP(clk_pre_delay, unit_tx_byte_clk_hs);
> +	phy_ctrl->clk_t_hs_prepare = DIV_ROUND_UP(clk_t_hs_prepare, unit_tx_byte_clk_hs);
> +	phy_ctrl->clk_t_lpx = DIV_ROUND_UP(clk_t_lpx, unit_tx_byte_clk_hs);
> +	phy_ctrl->clk_t_hs_zero = DIV_ROUND_UP(clk_t_hs_zero, unit_tx_byte_clk_hs);
> +	phy_ctrl->clk_t_hs_trial = DIV_ROUND_UP(clk_t_hs_trial, unit_tx_byte_clk_hs);
> +
> +	phy_ctrl->data_post_delay = DIV_ROUND_UP(data_post_delay, unit_tx_byte_clk_hs);
> +	phy_ctrl->data_t_hs_prepare = DIV_ROUND_UP(data_t_hs_prepare, unit_tx_byte_clk_hs);
> +	phy_ctrl->data_t_lpx = DIV_ROUND_UP(data_t_lpx, unit_tx_byte_clk_hs);
> +	phy_ctrl->data_t_hs_zero = DIV_ROUND_UP(data_t_hs_zero, unit_tx_byte_clk_hs);
> +	phy_ctrl->data_t_hs_trial = DIV_ROUND_UP(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 + DIV_ROUND_UP(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 + DIV_ROUND_UP(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 + DIV_ROUND_UP(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) % mipi->max_tx_esc_clk) > 0) ?
> +		(phy_ctrl->lane_byte_clk / 2 / mipi->max_tx_esc_clk + 1) :
> +		(phy_ctrl->lane_byte_clk / 2 / mipi->max_tx_esc_clk);
> +
> +	DRM_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);
> +	DRM_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 void dw_dsi_set_mode(struct dw_dsi *dsi, enum dsi_work_mode mode)
> +{
> +	struct dsi_hw_ctx *ctx = dsi->ctx;
> +	void __iomem *base = ctx->base;
> +
> +	writel(RESET, base + PWR_UP);
> +	writel(mode, base + MODE_CFG);
> +	writel(POWERUP, base + PWR_UP);
> +}
> +
> +static void dsi_set_burst_mode(void __iomem *base, unsigned long burst_flags)
> +{
> +	unsigned long flags;
> +	u32 val;
> +
> +	flags = burst_flags;
> +	flags &= MIPI_DSI_MODE_VIDEO |
> +		 MIPI_DSI_MODE_VIDEO_BURST |
> +		 MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
> +
> +	if (!(flags & MIPI_DSI_MODE_VIDEO)) {
> +		DRM_WARN("MIPI_DSI_MODE_VIDEO was not set! Using DSI_NON_BURST_SYNC_PULSES");
> +		val = DSI_NON_BURST_SYNC_PULSES;
> +	} else if (flags & MIPI_DSI_MODE_VIDEO_BURST) {
> +		val = DSI_BURST_SYNC_PULSES_1;
> +	} else if (flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
> +		val = DSI_NON_BURST_SYNC_PULSES;
> +	} else {
> +		val = DSI_NON_BURST_SYNC_EVENTS;
> +	}
> +
> +	DRM_INFO("burst_mode = 0x%x (flags: 0x%04lx)", val, burst_flags);
> +	set_reg(base + MIPIDSI_VID_MODE_CFG_OFFSET, val, 2, 0);
> +}
> +
> +/*
> + * dsi phy reg write function
> + */
> +static void dsi_phy_tst_set(void __iomem *base, u32 reg, u32 val)
> +{
> +	u32 reg_write = 0x10000 + reg;
> +
> +	/*
> +	 * latch reg first
> +	 */
> +	writel(reg_write, base + MIPIDSI_PHY_TST_CTRL1_OFFSET);
> +	writel(0x02, base + MIPIDSI_PHY_TST_CTRL0_OFFSET);
> +	writel(0x00, base + MIPIDSI_PHY_TST_CTRL0_OFFSET);
> +
> +	/*
> +	 * then latch value
> +	 */
> +	writel(val, base + MIPIDSI_PHY_TST_CTRL1_OFFSET);
> +	writel(0x02, base + MIPIDSI_PHY_TST_CTRL0_OFFSET);
> +	writel(0x00, base + MIPIDSI_PHY_TST_CTRL0_OFFSET);
> +}
> +
> +static void mipi_config_dphy_spec1v2_parameter(struct dw_dsi *dsi,
> +					       char __iomem *mipi_dsi_base,
> +					       u32 id)
> +{
> +	u32 i;
> +	u32 addr = 0;
> +	u32 lanes;
> +
> +	lanes =  dsi->client[id].lanes - 1;
> +	for (i = 0; i <= (lanes + 1); i++) {
> +		/* Lane Transmission Property */
> +		addr = MIPIDSI_PHY_TST_LANE_TRANSMISSION_PROPERTY + (i << 5);
> +		dsi_phy_tst_set(mipi_dsi_base, addr, 0x43);
> +	}
> +
> +	/* pre_delay of clock lane request setting */
> +	dsi_phy_tst_set(mipi_dsi_base, MIPIDSI_PHY_TST_CLK_PRE_DELAY, DSS_REDUCE(dsi->phy.clk_pre_delay));
> +
> +	/* post_delay of clock lane request setting */
> +	dsi_phy_tst_set(mipi_dsi_base, MIPIDSI_PHY_TST_CLK_POST_DELAY, DSS_REDUCE(dsi->phy.clk_post_delay));
> +
> +	/* clock lane timing ctrl - t_lpx */
> +	dsi_phy_tst_set(mipi_dsi_base, MIPIDSI_PHY_TST_CLK_TLPX, DSS_REDUCE(dsi->phy.clk_t_lpx));
> +
> +	/* clock lane timing ctrl - t_hs_prepare */
> +	dsi_phy_tst_set(mipi_dsi_base, MIPIDSI_PHY_TST_CLK_PREPARE, DSS_REDUCE(dsi->phy.clk_t_hs_prepare));
> +
> +	/* clock lane timing ctrl - t_hs_zero */
> +	dsi_phy_tst_set(mipi_dsi_base, MIPIDSI_PHY_TST_CLK_ZERO, DSS_REDUCE(dsi->phy.clk_t_hs_zero));
> +
> +	/* clock lane timing ctrl - t_hs_trial */
> +	dsi_phy_tst_set(mipi_dsi_base, MIPIDSI_PHY_TST_CLK_TRAIL, DSS_REDUCE(dsi->phy.clk_t_hs_trial));
> +
> +	for (i = 0; i <= 4; i++) {
> +		if (lanes == 2 && i == 1) /* init mipi dsi 3 lanes should skip lane3 */
> +			i++;
> +
> +		if (i == 2) /* skip clock lane */
> +			i++;  /* addr: lane0:0x60; lane1:0x80; lane2:0xC0; lane3:0xE0 */
> +
> +		/* data lane pre_delay */
> +		addr = MIPIDSI_PHY_TST_DATA_PRE_DELAY + (i << 5);
> +		dsi_phy_tst_set(mipi_dsi_base, addr, DSS_REDUCE(dsi->phy.data_pre_delay));
> +
> +		/* data lane post_delay */
> +		addr = MIPIDSI_PHY_TST_DATA_POST_DELAY + (i << 5);
> +		dsi_phy_tst_set(mipi_dsi_base, addr, DSS_REDUCE(dsi->phy.data_post_delay));
> +
> +		/* data lane timing ctrl - t_lpx */
> +		addr = MIPIDSI_PHY_TST_DATA_TLPX + (i << 5);
> +		dsi_phy_tst_set(mipi_dsi_base, addr, DSS_REDUCE(dsi->phy.data_t_lpx));
> +
> +		/* data lane timing ctrl - t_hs_prepare */
> +		addr = MIPIDSI_PHY_TST_DATA_PREPARE + (i << 5);
> +		dsi_phy_tst_set(mipi_dsi_base, addr, DSS_REDUCE(dsi->phy.data_t_hs_prepare));
> +
> +		/* data lane timing ctrl - t_hs_zero */
> +		addr = MIPIDSI_PHY_TST_DATA_ZERO + (i << 5);
> +		dsi_phy_tst_set(mipi_dsi_base, addr, DSS_REDUCE(dsi->phy.data_t_hs_zero));
> +
> +		/* data lane timing ctrl - t_hs_trial */
> +		addr = MIPIDSI_PHY_TST_DATA_TRAIL + (i << 5);
> +		dsi_phy_tst_set(mipi_dsi_base, addr, DSS_REDUCE(dsi->phy.data_t_hs_trial));
> +
> +		DRM_DEBUG("DPHY spec1v2 config :\n"
> +			"addr=0x%x\n"
> +			"clk_pre_delay=%u\n"
> +			"clk_t_hs_trial=%u\n"
> +			"data_t_hs_zero=%u\n"
> +			"data_t_lpx=%u\n"
> +			"data_t_hs_prepare=%u\n",
> +			addr,
> +			dsi->phy.clk_pre_delay,
> +			dsi->phy.clk_t_hs_trial,
> +			dsi->phy.data_t_hs_zero,
> +			dsi->phy.data_t_lpx,
> +			dsi->phy.data_t_hs_prepare);
> +	}
> +}
> +
> +static void dsi_mipi_init(struct dw_dsi *dsi, char __iomem *mipi_dsi_base,
> +			  u32 id)
> +{
> +	struct dsi_hw_ctx *ctx = dsi->ctx;
> +	u32 hline_time = 0;
> +	u32 hsa_time = 0;
> +	u32 hbp_time = 0;
> +	u64 pixel_clk = 0;
> +	unsigned long dw_jiffies = 0;
> +	u32 tmp = 0;
> +	bool is_ready = false;
> +	struct mipi_panel_info *mipi = NULL;
> +	struct dss_rect rect;
> +	u32 cmp_stopstate_val = 0;
> +	u32 lanes;
> +
> +	WARN_ON(!dsi);
> +	WARN_ON(!mipi_dsi_base);
> +
> +	DRM_INFO("%s: id=%d\n", __func__, id);
> +
> +	mipi = &dsi->mipi;
> +
> +	if (mipi->max_tx_esc_clk == 0) {
> +		DRM_INFO("max_tx_esc_clk is invalid!");
> +		mipi->max_tx_esc_clk = DEFAULT_MAX_TX_ESC_CLK;
> +	}
> +
> +	memset(&dsi->phy, 0, sizeof(struct mipi_phy_params));
> +
> +	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970)
> +		kirin970_get_dsi_dphy_ctrl(dsi, &dsi->phy, id);
> +	else
> +		kirin960_get_dsi_phy_ctrl(dsi, &dsi->phy, id);
> +
> +	rect.x = 0;
> +	rect.y = 0;
> +	rect.w = dsi->cur_mode.hdisplay;
> +	rect.h = dsi->cur_mode.vdisplay;
> +	lanes = dsi->client[id].lanes - 1;
> +	/***************Configure the DPHY start**************/
> +
> +	set_reg(mipi_dsi_base + MIPIDSI_PHY_IF_CFG_OFFSET, lanes, 2, 0);
> +	set_reg(mipi_dsi_base + MIPIDSI_CLKMGR_CFG_OFFSET, dsi->phy.clk_division, 8, 0);
> +	set_reg(mipi_dsi_base + MIPIDSI_CLKMGR_CFG_OFFSET, dsi->phy.clk_division, 8, 8);
> +
> +	writel(0x00000000, mipi_dsi_base + MIPIDSI_PHY_RSTZ_OFFSET);
> +
> +	writel(0x00000000, mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET);
> +	writel(0x00000001, mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET);
> +	writel(0x00000000, mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET);
> +
> +	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
> +		dsi_phy_tst_set(mipi_dsi_base, 0x0042, 0x21);
> +		/* PLL configuration I */
> +		dsi_phy_tst_set(mipi_dsi_base, 0x0046,
> +				dsi->phy.rg_cp + (dsi->phy.rg_lpf_r << 4));
> +
> +		/* PLL configuration II */
> +		dsi_phy_tst_set(mipi_dsi_base, 0x0048,
> +				dsi->phy.rg_0p8v + (dsi->phy.rg_2p5g << 1) +
> +				(dsi->phy.rg_320m << 2) + (dsi->phy.rg_band_sel << 3));
> +
> +		/* PLL configuration III */
> +		dsi_phy_tst_set(mipi_dsi_base, 0x0049, dsi->phy.rg_pre_div);
> +
> +		/* PLL configuration IV */
> +		dsi_phy_tst_set(mipi_dsi_base, 0x004A, dsi->phy.rg_div);
> +
> +		dsi_phy_tst_set(mipi_dsi_base, 0x004F, 0xf0);
> +		dsi_phy_tst_set(mipi_dsi_base, 0x0050, 0xc0);
> +		dsi_phy_tst_set(mipi_dsi_base, 0x0051, 0x22);
> +
> +		dsi_phy_tst_set(mipi_dsi_base, 0x0053, dsi->phy.rg_vrefsel_vcm);
> +
> +		/* enable BTA */
> +		dsi_phy_tst_set(mipi_dsi_base, 0x0054, 0x03);
> +
> +		/* PLL update control */
> +		dsi_phy_tst_set(mipi_dsi_base, 0x004B, 0x1);
> +
> +		/* set dphy spec parameter */
> +		mipi_config_dphy_spec1v2_parameter(dsi, mipi_dsi_base, id);
> +	} else {
> +		int i = 0;
> +
> +		/* physical configuration PLL I */
> +		dsi_phy_tst_set(mipi_dsi_base, 0x14,
> +				(dsi->phy.rg_pll_fbd_s << 4) + (dsi->phy.rg_pll_enswc << 3) +
> +				(dsi->phy.rg_pll_enbwt << 2) + dsi->phy.rg_pll_chp);
> +
> +		/* physical configuration PLL II, M */
> +		dsi_phy_tst_set(mipi_dsi_base, 0x15, dsi->phy.rg_pll_fbd_p);
> +
> +		/* physical configuration PLL III */
> +		dsi_phy_tst_set(mipi_dsi_base, 0x16,
> +				(dsi->phy.rg_pll_cp << 5) + (dsi->phy.rg_pll_lpf_cs << 4) +
> +				dsi->phy.rg_pll_refsel);
> +
> +		/* physical configuration PLL IV, N */
> +		dsi_phy_tst_set(mipi_dsi_base, 0x17, dsi->phy.rg_pll_pre_p);
> +
> +		/* sets the analog characteristic of V reference in D-PHY TX */
> +		dsi_phy_tst_set(mipi_dsi_base, 0x1D, dsi->phy.rg_vrefsel_vcm);
> +
> +		/* MISC AFE Configuration */
> +		dsi_phy_tst_set(mipi_dsi_base, 0x1E,
> +				(dsi->phy.rg_pll_cp_p << 5) + (dsi->phy.reload_sel << 4) +
> +				(dsi->phy.rg_phase_gen_en << 3) + (dsi->phy.rg_band_sel << 2) +
> +				(dsi->phy.pll_power_down << 1) + dsi->phy.pll_register_override);
> +
> +		/* reload_command */
> +		dsi_phy_tst_set(mipi_dsi_base, 0x1F, dsi->phy.load_command);
> +
> +		/* pre_delay of clock lane request setting */
> +		dsi_phy_tst_set(mipi_dsi_base, 0x20, DSS_REDUCE(dsi->phy.clk_pre_delay));
> +
> +		/* post_delay of clock lane request setting */
> +		dsi_phy_tst_set(mipi_dsi_base, 0x21, DSS_REDUCE(dsi->phy.clk_post_delay));
> +
> +		/* clock lane timing ctrl - t_lpx */
> +		dsi_phy_tst_set(mipi_dsi_base, 0x22, DSS_REDUCE(dsi->phy.clk_t_lpx));
> +
> +		/* clock lane timing ctrl - t_hs_prepare */
> +		dsi_phy_tst_set(mipi_dsi_base, 0x23, DSS_REDUCE(dsi->phy.clk_t_hs_prepare));
> +
> +		/* clock lane timing ctrl - t_hs_zero */
> +		dsi_phy_tst_set(mipi_dsi_base, 0x24, DSS_REDUCE(dsi->phy.clk_t_hs_zero));
> +
> +		/* clock lane timing ctrl - t_hs_trial */
> +		dsi_phy_tst_set(mipi_dsi_base, 0x25, dsi->phy.clk_t_hs_trial);
> +
> +		for (i = 0; i <= lanes; i++) {
> +			/* data lane pre_delay */
> +			tmp = 0x30 + (i << 4);
> +			dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_pre_delay));
> +
> +			/* data lane post_delay */
> +			tmp = 0x31 + (i << 4);
> +			dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_post_delay));
> +
> +			/* data lane timing ctrl - t_lpx */
> +			dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_t_lpx));
> +
> +			/* data lane timing ctrl - t_hs_prepare */
> +			tmp = 0x33 + (i << 4);
> +			dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_t_hs_prepare));
> +
> +			/* data lane timing ctrl - t_hs_zero */
> +			tmp = 0x34 + (i << 4);
> +			dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_t_hs_zero));
> +
> +			/* data lane timing ctrl - t_hs_trial */
> +			tmp = 0x35 + (i << 4);
> +			dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_t_hs_trial));
> +
> +			/* data lane timing ctrl - t_ta_go */
> +			tmp = 0x36 + (i << 4);
> +			dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_t_ta_go));
> +
> +			/* data lane timing ctrl - t_ta_get */
> +			tmp = 0x37 + (i << 4);
> +			dsi_phy_tst_set(mipi_dsi_base, tmp, DSS_REDUCE(dsi->phy.data_t_ta_get));
> +		}
> +	}
> +
> +	writel(0x00000007, mipi_dsi_base + MIPIDSI_PHY_RSTZ_OFFSET);
> +
> +	is_ready = false;
> +	dw_jiffies = jiffies + HZ / 2;
> +	do {
> +		tmp = readl(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
> +		if ((tmp & 0x00000001) == 0x00000001) {
> +			is_ready = true;
> +			break;
> +		}
> +	} while (time_after(dw_jiffies, jiffies));
Use jiffies + msecs_to_jiffies(xxx) - and drop HZ /2.
Same goes for other similar HZ uses.

> +
> +	if (!is_ready) {
> +		DRM_INFO("phylock is not ready!MIPIDSI_PHY_STATUS_OFFSET=0x%x.\n",
> +			 tmp);
> +	}
> +
> +	if (lanes >= DSI_4_LANES)
> +		cmp_stopstate_val = (BIT(4) | BIT(7) | BIT(9) | BIT(11));
> +	else if (lanes >= DSI_3_LANES)
> +		cmp_stopstate_val = (BIT(4) | BIT(7) | BIT(9));
> +	else if (lanes >= 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 = readl(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) {
> +		DRM_INFO("phystopstateclklane is not ready! MIPIDSI_PHY_STATUS_OFFSET=0x%x.\n",
> +			 tmp);
> +	}
> +
> +	/*************************Configure the DPHY end*************************/
> +
> +	/* phy_stop_wait_time */
> +	set_reg(mipi_dsi_base + MIPIDSI_PHY_IF_CFG_OFFSET, dsi->phy.phy_stop_wait_time, 8, 8);
> +
> +	/*--------------configuring the DPI packet transmission---------------- */
> +
> +	/*
> +	 * 2. Configure the DPI Interface:
> +	 * This defines how the DPI interface interacts with the controller.
> +	 */
> +	set_reg(mipi_dsi_base + MIPIDSI_DPI_VCID_OFFSET, mipi->vc, 2, 0);
> +	set_reg(mipi_dsi_base + MIPIDSI_DPI_COLOR_CODING_OFFSET, mipi->color_mode, 4, 0);
> +
> +	set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET, dsi->ldi.data_en_plr, 1, 0);
> +	set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET, dsi->ldi.vsync_plr, 1, 1);
> +	set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET, dsi->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.
> +	 */
> +	/* video mode: low power mode */
> +	set_reg(mipi_dsi_base + MIPIDSI_VID_MODE_CFG_OFFSET, 0x3f, 6, 8);
> +
> +	/* TODO: fix blank display bug when set backlight */
> +	set_reg(mipi_dsi_base + MIPIDSI_DPI_LP_CMD_TIM_OFFSET, 0x4, 8, 16);
> +	/* video mode: send read cmd by lp mode */
> +	set_reg(mipi_dsi_base + MIPIDSI_VID_MODE_CFG_OFFSET, 0x1, 1, 15);
> +
> +	set_reg(mipi_dsi_base + MIPIDSI_VID_PKT_SIZE_OFFSET, rect.w, 14, 0);
> +
> +	/* burst mode */
> +	dsi_set_burst_mode(mipi_dsi_base, dsi->client[id].mode_flags);
> +	/* for dsi read, BTA enable */
> +	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 = dsi->cur_mode.clock * 1000;
> +	/* htot = dsi->cur_mode.htotal; */
> +	/* vtot = dsi->cur_mode.vtotal; */
> +	dsi->ldi.h_front_porch = dsi->cur_mode.hsync_start - dsi->cur_mode.hdisplay;
> +	dsi->ldi.h_back_porch = dsi->cur_mode.htotal - dsi->cur_mode.hsync_end;
> +	dsi->ldi.h_pulse_width = dsi->cur_mode.hsync_end - dsi->cur_mode.hsync_start;
> +	dsi->ldi.v_front_porch = dsi->cur_mode.vsync_start - dsi->cur_mode.vdisplay;
> +	dsi->ldi.v_back_porch = dsi->cur_mode.vtotal - dsi->cur_mode.vsync_end;
> +	dsi->ldi.v_pulse_width = dsi->cur_mode.vsync_end - dsi->cur_mode.vsync_start;
> +	if (dsi->ldi.v_pulse_width > 15) {
> +		DRM_DEBUG_DRIVER("vsw exceeded 15\n");
> +		dsi->ldi.v_pulse_width = 15;
> +	}
> +	hsa_time = dsi->ldi.h_pulse_width * dsi->phy.lane_byte_clk / pixel_clk;
> +	hbp_time = dsi->ldi.h_back_porch * dsi->phy.lane_byte_clk / pixel_clk;
> +	hline_time = DIV_ROUND_UP((dsi->ldi.h_pulse_width + dsi->ldi.h_back_porch +
> +		rect.w + dsi->ldi.h_front_porch) * dsi->phy.lane_byte_clk, pixel_clk);
> +
> +	DRM_INFO("hsa_time=%d, hbp_time=%d, hline_time=%d\n",
> +		 hsa_time, hbp_time, hline_time);
> +	DRM_INFO("lane_byte_clk=%llu, pixel_clk=%llu\n",
> +		 dsi->phy.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);
> +
> +	/* Define the Vertical line configuration */
> +	set_reg(mipi_dsi_base + MIPIDSI_VID_VSA_LINES_OFFSET,
> +		dsi->ldi.v_pulse_width, 10, 0);
> +	set_reg(mipi_dsi_base + MIPIDSI_VID_VBP_LINES_OFFSET,
> +		dsi->ldi.v_back_porch, 10, 0);
> +	set_reg(mipi_dsi_base + MIPIDSI_VID_VFP_LINES_OFFSET,
> +		dsi->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);
> +
> +	/* Configure core's phy parameters */
> +	set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_LPCLK_CFG_OFFSET,
> +		dsi->phy.clk_lane_lp2hs_time, 10, 0);
> +	set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_LPCLK_CFG_OFFSET,
> +		dsi->phy.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,
> +		dsi->phy.data_lane_lp2hs_time, 10, 0);
> +	set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_CFG_OFFSET,
> +		dsi->phy.data_lane_hs2lp_time, 10, 16);
> +
> +	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970)  {
> +		/* 16~19bit:pclk_en, pclk_sel, dpipclk_en, dpipclk_sel */
> +		set_reg(mipi_dsi_base + MIPIDSI_CLKMGR_CFG_OFFSET, 0x5, 4, 16);
> +		/* 0:dphy */
> +		set_reg(mipi_dsi_base + KIRIN970_PHY_MODE, 0x0, 1, 0);
> +	}
> +
> +	/* Waking up Core */
> +	set_reg(mipi_dsi_base + MIPIDSI_PWR_UP_OFFSET, 0x1, 1, 0);
> +}
> +
> +static void dsi_encoder_disable(struct drm_encoder *encoder)
> +{
> +	struct dw_dsi *dsi = encoder_to_dsi(encoder);
> +	struct dsi_hw_ctx *ctx = dsi->ctx;
> +	void __iomem *base = ctx->base;
> +
> +	if (!dsi->enable)
> +		return;
> +
> +	dw_dsi_set_mode(dsi, DSI_COMMAND_MODE);
> +	/* turn off panel's backlight */
> +	if (dsi->panel && drm_panel_disable(dsi->panel))
> +		DRM_ERROR("failed to disable panel\n");
> +
> +	/* turn off panel */
> +	if (dsi->panel && drm_panel_unprepare(dsi->panel))
> +		DRM_ERROR("failed to unprepare panel\n");
> +
> +	writel(0, base + PWR_UP);
> +	writel(0, base + LPCLK_CTRL);
> +	writel(0, base + PHY_RSTZ);
> +	clk_disable_unprepare(ctx->dss_dphy0_ref_clk);
> +	clk_disable_unprepare(ctx->dss_dphy0_cfg_clk);
> +	clk_disable_unprepare(ctx->dss_pclk_dsi0_clk);
> +
> +	dsi->enable = false;
> +}
> +
> +static int mipi_dsi_on_sub1(struct dw_dsi *dsi, char __iomem *mipi_dsi_base,
> +			    u32 id)
> +{
> +	struct dsi_hw_ctx *ctx = dsi->ctx;
> +
> +	WARN_ON(!mipi_dsi_base);
> +
> +	/* mipi init */
> +	dsi_mipi_init(dsi, mipi_dsi_base, id);
> +
> +	/* dsi memory init */
> +	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970)
> +		writel(0x02600008, mipi_dsi_base + KIRIN970_DSI_MEM_CTRL);
> +
> +	/* 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 dw_dsi *dsi, char __iomem *mipi_dsi_base)
> +{
> +	struct dsi_hw_ctx *ctx = dsi->ctx;
> +
> +	u64 pctrl_dphytx_stopcnt = 0;
> +
> +	WARN_ON(!mipi_dsi_base);
> +
> +	/* switch to video mode */
> +	set_reg(mipi_dsi_base + MIPIDSI_MODE_CFG_OFFSET, 0x0, 1, 0);
> +
> +	/* enable EOTP TX */
> +	set_reg(mipi_dsi_base + MIPIDSI_PCKHDL_CFG_OFFSET, 0x1, 1, 0);
> +
> +	/* enable generate High Speed clock, continue clock */
> +	set_reg(mipi_dsi_base + MIPIDSI_LPCLK_CTRL_OFFSET, 0x1, 2, 0);
> +
> +	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
> +		/* init: wait DPHY 4 data lane stopstate */
> +		pctrl_dphytx_stopcnt = (u64)(dsi->ldi.h_back_porch +
> +			dsi->ldi.h_front_porch + dsi->ldi.h_pulse_width + dsi->cur_mode.hdisplay + 5) *
> +			DEFAULT_PCLK_PCTRL_RATE / (dsi->cur_mode.clock * 1000);
> +		DRM_DEBUG("pctrl_dphytx_stopcnt = %llu\n", pctrl_dphytx_stopcnt);
> +
> +		/* FIXME: */
> +		writel((u32)pctrl_dphytx_stopcnt, dsi->ctx->pctrl_base + PERI_CTRL29);
> +	}
> +
> +	return 0;
> +}
> +
> +static void dsi_encoder_enable(struct drm_encoder *encoder)
> +{
> +	struct dw_dsi *dsi = encoder_to_dsi(encoder);
> +	struct dsi_hw_ctx *ctx = dsi->ctx;
> +	int ret;
> +
> +	if (dsi->enable)
> +		return;
> +
> +	ret = clk_prepare_enable(ctx->dss_dphy0_ref_clk);
> +	if (ret) {
> +		DRM_ERROR("fail to enable dss_dphy0_ref_clk: %d\n", ret);
> +		return;
> +	}
> +
> +	ret = clk_prepare_enable(ctx->dss_dphy0_cfg_clk);
> +	if (ret) {
> +		DRM_ERROR("fail to enable dss_dphy0_cfg_clk: %d\n", ret);
> +		return;
> +	}
> +
> +	ret = clk_prepare_enable(ctx->dss_pclk_dsi0_clk);
> +	if (ret) {
> +		DRM_ERROR("fail to enable dss_pclk_dsi0_clk: %d\n", ret);
> +		return;
> +	}
> +
> +	mipi_dsi_on_sub1(dsi, ctx->base, dsi->attached_client);
> +
> +	mipi_dsi_on_sub2(dsi, ctx->base);
> +
> +	/* turn on panel */
> +	if (dsi->panel && drm_panel_prepare(dsi->panel))
> +		DRM_ERROR("failed to prepare panel\n");
> +
> +	/* dw_dsi_set_mode(dsi, DSI_VIDEO_MODE); */
> +
> +	/* turn on panel's back light */
> +	if (dsi->panel && drm_panel_enable(dsi->panel))
> +		DRM_ERROR("failed to enable panel\n");
> +
> +	dsi->enable = true;
> +}
> +
> +static enum drm_mode_status dsi_encoder_mode_valid(struct drm_encoder *encoder,
> +						   const struct drm_display_mode *mode)
> +
> +{
> +	const struct drm_crtc_helper_funcs *crtc_funcs;
> +	struct drm_display_mode adj_mode;
> +	int clock = mode->clock;
> +	struct drm_crtc *crtc;
> +
> +	drm_for_each_crtc(crtc, encoder->dev) {
> +		drm_mode_copy(&adj_mode, mode);
> +
> +		crtc_funcs = crtc->helper_private;
> +		if (crtc_funcs && crtc_funcs->mode_fixup) {
> +			if (!crtc_funcs->mode_fixup(crtc, mode, &adj_mode)) {
> +				DRM_INFO("Discarded mode: %ix%i@%i, clock: %i (adjusted to %i)",
> +					 mode->hdisplay, mode->vdisplay,
> +					 drm_mode_vrefresh(mode),
> +					 mode->clock, clock);
> +
> +				return MODE_BAD;
> +			}
> +			clock = adj_mode.clock;
> +		}
> +	}
> +
> +	DRM_INFO("Valid mode: %ix%i@%i, clock %i (adjusted to %i)",
> +		 mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode),
> +		 mode->clock, clock);
> +
> +	return MODE_OK;
> +}
> +
> +static void dsi_encoder_mode_set(struct drm_encoder *encoder,
> +				 struct drm_display_mode *mode,
> +				 struct drm_display_mode *adj_mode)
> +{
> +	struct dw_dsi *dsi = encoder_to_dsi(encoder);
> +
> +	drm_mode_copy(&dsi->cur_mode, adj_mode);
> +}
> +
> +static int dsi_encoder_atomic_check(struct drm_encoder *encoder,
> +				    struct drm_crtc_state *crtc_state,
> +				    struct drm_connector_state *conn_state)
> +{
> +	/* do nothing */
> +	return 0;
> +}
> +
> +static const struct drm_encoder_helper_funcs dw_encoder_helper_funcs = {
> +	.atomic_check	= dsi_encoder_atomic_check,
> +	.mode_valid	= dsi_encoder_mode_valid,
> +	.mode_set	= dsi_encoder_mode_set,
> +	.enable		= dsi_encoder_enable,
> +	.disable	= dsi_encoder_disable
> +};
> +
> +static const struct drm_encoder_funcs dw_encoder_funcs = {
> +	.destroy = drm_encoder_cleanup,
> +};
> +
> +static int dw_drm_encoder_init(struct device *dev,
> +			       struct drm_device *drm_dev,
> +			       struct drm_encoder *encoder,
> +			       struct drm_bridge *bridge)
> +{
> +	int ret;
> +	u32 crtc_mask;
> +
> +	drm_info(drm_dev, "%s:\n", __func__);
> +
> +	/* Link drm_bridge to encoder */
> +	if (!bridge) {
> +		drm_info(drm_dev, "no dsi bridge to attach the encoder\n");
> +		return 0;
> +	}
> +
> +	crtc_mask = drm_of_find_possible_crtcs(drm_dev, dev->of_node);
> +	if (!crtc_mask) {
> +		DRM_ERROR("failed to find crtc mask\n");
> +		return -EINVAL;
> +	}
> +
> +	drm_info(drm_dev, "Initializing CRTC encoder: %d\n",
> +		 crtc_mask);
> +
> +	encoder->possible_crtcs = crtc_mask;
> +	encoder->possible_clones = 0;
> +	ret = drm_encoder_init(drm_dev, encoder, &dw_encoder_funcs,
> +			       DRM_MODE_ENCODER_DSI, NULL);
> +	if (ret) {
> +		drm_info(drm_dev, "failed to init dsi encoder\n");
> +		return ret;
> +	}
> +
> +	drm_encoder_helper_add(encoder, &dw_encoder_helper_funcs);
> +
> +	/* associate the bridge to dsi encoder */
> +	ret = drm_bridge_attach(encoder, bridge, NULL, 0);
> +	if (ret) {
> +		drm_info(drm_dev, "failed to attach external bridge\n");
> +		drm_encoder_cleanup(encoder);
> +	}
> +
> +	return ret;
> +}
All the encoder stuff can, I think, be repalced by the simple encoder.
See how other drivers uses drm_simple_encoder_init()

> +
> +static int dsi_host_attach(struct mipi_dsi_host *host,
> +			   struct mipi_dsi_device *mdsi)
> +{
> +	struct dw_dsi *dsi = host_to_dsi(host);
> +	u32 id = mdsi->channel >= 1 ? OUT_PANEL : OUT_HDMI;
> +
> +	if (mdsi->lanes < 1 || mdsi->lanes > 4) {
> +		DRM_ERROR("dsi device params invalid\n");
> +		return -EINVAL;
> +	}
> +
> +	dsi->client[id].lanes = mdsi->lanes;
> +	dsi->client[id].format = mdsi->format;
> +	dsi->client[id].mode_flags = mdsi->mode_flags;
> +	dsi->client[id].phy_clock = 0;
> +
> +	dsi->attached_client = id;
> +
> +	DRM_DEBUG("host attach, client name=[%s], id=%d\n", mdsi->name, id);
> +
> +	return 0;
> +}
> +
> +static int dsi_host_detach(struct mipi_dsi_host *host,
> +			   struct mipi_dsi_device *mdsi)
> +{
> +	/* do nothing */
> +	return 0;
> +}
> +
> +static int dsi_gen_pkt_hdr_write(void __iomem *base, u32 val)
> +{
> +	u32 status;
> +	int ret;
> +
> +	ret = readx_poll_timeout(readl, base + CMD_PKT_STATUS, status,
> +				 !(status & GEN_CMD_FULL), 1000,
> +				 CMD_PKT_STATUS_TIMEOUT_US);
> +	if (ret < 0) {
> +		DRM_ERROR("failed to get available command FIFO\n");
> +		return ret;
> +	}
> +
> +	writel(val, base + GEN_HDR);
> +
> +	ret = readx_poll_timeout(readl, base + CMD_PKT_STATUS, status,
> +				 status & (GEN_CMD_EMPTY | GEN_PLD_W_EMPTY),
> +				 1000, CMD_PKT_STATUS_TIMEOUT_US);
> +	if (ret < 0) {
> +		DRM_ERROR("failed to write command FIFO\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int dsi_dcs_short_write(void __iomem *base,
> +			       const struct mipi_dsi_msg *msg)
> +{
> +	const u16 *tx_buf = msg->tx_buf;
> +	u32 val = GEN_HDATA(*tx_buf) | GEN_HTYPE(msg->type);
> +
> +	if (msg->tx_len > 2) {
> +		DRM_ERROR("too long tx buf length %zu for short write\n",
> +			  msg->tx_len);
> +		return -EINVAL;
> +	}
> +
> +	return dsi_gen_pkt_hdr_write(base, val);
> +}
> +
> +static int dsi_dcs_long_write(void __iomem *base,
> +			      const struct mipi_dsi_msg *msg)
> +{
> +	const u32 *tx_buf = msg->tx_buf;
> +	int len = msg->tx_len, pld_data_bytes = sizeof(*tx_buf), ret;
> +	u32 val = GEN_HDATA(msg->tx_len) | GEN_HTYPE(msg->type);
> +	u32 remainder = 0;
> +	u32 status;
> +
> +	if (msg->tx_len < 3) {
> +		DRM_ERROR("wrong tx buf length %zu for long write\n",
> +			  msg->tx_len);
> +		return -EINVAL;
> +	}
> +
> +	while (DIV_ROUND_UP(len, pld_data_bytes)) {
> +		if (len < pld_data_bytes) {
> +			memcpy(&remainder, tx_buf, len);
> +			writel(remainder, base + GEN_PLD_DATA);
> +			len = 0;
> +		} else {
> +			writel(*tx_buf, base + GEN_PLD_DATA);
> +			tx_buf++;
> +			len -= pld_data_bytes;
> +		}
> +
> +		ret = readx_poll_timeout(readl, base + CMD_PKT_STATUS,
> +					 status, !(status & GEN_PLD_W_FULL), 1000,
> +					 CMD_PKT_STATUS_TIMEOUT_US);
> +		if (ret < 0) {
> +			DRM_ERROR("failed to get available write payload FIFO\n");
> +			return ret;
> +		}
> +	}
> +
> +	return dsi_gen_pkt_hdr_write(base, val);
> +}
> +
> +static ssize_t dsi_host_transfer(struct mipi_dsi_host *host,
> +				 const struct mipi_dsi_msg *msg)
> +{
> +	struct dw_dsi *dsi = host_to_dsi(host);
> +	struct dsi_hw_ctx *ctx = dsi->ctx;
> +	void __iomem *base = ctx->base;
> +	int ret;
> +
> +	switch (msg->type) {
> +	case MIPI_DSI_DCS_SHORT_WRITE:
> +	case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
> +	case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE:
> +		ret = dsi_dcs_short_write(base, msg);
> +		break;
> +	case MIPI_DSI_DCS_LONG_WRITE:
> +		ret = dsi_dcs_long_write(base, msg);
> +		break;
> +	default:
> +		DRM_ERROR("unsupported message type\n");
> +		ret = -EINVAL;
> +	}
> +
> +	return ret;
> +}
> +
> +static const struct mipi_dsi_host_ops dsi_host_ops = {
> +	.attach = dsi_host_attach,
> +	.detach = dsi_host_detach,
> +	.transfer = dsi_host_transfer,
> +};
> +
> +static int dsi_host_init(struct device *dev, struct dw_dsi *dsi)
> +{
> +	struct mipi_dsi_host *host = &dsi->host;
> +	struct mipi_panel_info *mipi = &dsi->mipi;
> +	int ret;
> +
> +	host->dev = dev;
> +	host->ops = &dsi_host_ops;
> +
> +	mipi->max_tx_esc_clk = 10 * 1000000UL;
> +	mipi->vc = 0;
> +	mipi->color_mode = DSI_24BITS_1;
> +	mipi->clk_post_adjust = 120;
> +	mipi->clk_pre_adjust = 0;
> +	mipi->clk_t_hs_prepare_adjust = 0;
> +	mipi->clk_t_lpx_adjust = 0;
> +	mipi->clk_t_hs_trial_adjust = 0;
> +	mipi->clk_t_hs_exit_adjust = 0;
> +	mipi->clk_t_hs_zero_adjust = 0;
> +
> +	dsi->ldi.data_en_plr = 0;
> +	dsi->ldi.vsync_plr = 0;
> +	dsi->ldi.hsync_plr = 0;
> +
> +	ret = mipi_dsi_host_register(host);
> +	if (ret) {
> +		dev_info(dev, "failed to register dsi host\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int dsi_connector_get_modes(struct drm_connector *connector)
> +{
> +	struct dw_dsi *dsi = connector_to_dsi(connector);
> +
> +	return drm_panel_get_modes(dsi->panel, connector);
> +}
> +
> +static enum drm_mode_status
> +dsi_connector_mode_valid(struct drm_connector *connector,
> +			 struct drm_display_mode *mode)
> +{
> +	enum drm_mode_status mode_status = MODE_OK;
> +
> +	return mode_status;
> +}
> +
> +static struct drm_encoder *
> +dsi_connector_best_encoder(struct drm_connector *connector)
> +{
> +	struct dw_dsi *dsi = connector_to_dsi(connector);
> +
> +	return &dsi->encoder;
> +}
> +
> +static const struct drm_connector_helper_funcs dsi_connector_helper_funcs = {
> +	.get_modes = dsi_connector_get_modes,
> +	.mode_valid = dsi_connector_mode_valid,
> +	.best_encoder = dsi_connector_best_encoder,
> +};
> +
> +static enum drm_connector_status
> +dsi_connector_detect(struct drm_connector *connector, bool force)
> +{
> +	struct dw_dsi *dsi = connector_to_dsi(connector);
> +	enum drm_connector_status status;
> +
> +	status = dsi->cur_client == OUT_PANEL ?	connector_status_connected :
> +		connector_status_disconnected;
> +
> +	return status;
> +}
> +
> +static void dsi_connector_destroy(struct drm_connector *connector)
> +{
> +	drm_connector_unregister(connector);
> +	drm_connector_cleanup(connector);
> +}
> +
> +static struct drm_connector_funcs dsi_atomic_connector_funcs = {
> +	.fill_modes = drm_helper_probe_single_connector_modes,
> +	.detect = dsi_connector_detect,
> +	.destroy = dsi_connector_destroy,
> +	.reset = drm_atomic_helper_connector_reset,
> +	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static int dsi_connector_init(struct drm_device *dev, struct dw_dsi *dsi)
> +{
> +	struct drm_encoder *encoder = &dsi->encoder;
> +	struct drm_connector *connector = &dsi->connector;
> +	int ret;
> +
> +	connector->polled = DRM_CONNECTOR_POLL_HPD;
> +	drm_connector_helper_add(connector,
> +				 &dsi_connector_helper_funcs);
> +
> +	ret = drm_connector_init(dev, &dsi->connector,
> +				 &dsi_atomic_connector_funcs,
> +				 DRM_MODE_CONNECTOR_DSI);
> +	if (ret)
> +		return ret;
> +
> +	drm_dbg(dev, "Attaching CRTC encoder\n");
> +	ret = drm_connector_attach_encoder(connector, encoder);
> +	if (ret)
> +		return ret;
> +
> +	ret = drm_panel_attach(dsi->panel, connector);
> +	if (ret)
> +		return ret;
> +
> +	drm_connector_register(&dsi->connector);
> +
> +	drm_dbg(dev, "connector init\n");
> +	return 0;
> +}
> +
> +static int dsi_bind(struct device *dev, struct device *master, void *data)
> +{
> +	struct dsi_data *ddata = dev_get_drvdata(dev);
> +	struct dw_dsi *dsi = &ddata->dsi;
> +	struct drm_device *drm_dev = data;
> +	int ret;
> +
> +	ret = dw_drm_encoder_init(dev, drm_dev, &dsi->encoder,
> +				  dsi->bridge);
> +	if (ret)
> +		return ret;
> +
> +	if (dsi->panel) {
> +		ret = dsi_connector_init(drm_dev, dsi);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static void dsi_unbind(struct device *dev, struct device *master, void *data)
> +{
> +	/* do nothing */
> +}
> +
> +static const struct component_ops dsi_ops = {
> +	.bind	= dsi_bind,
> +	.unbind	= dsi_unbind,
> +};
> +
> +static int dsi_parse_bridge_endpoint(struct dw_dsi *dsi,
> +				     struct device_node *endpoint)
> +{
> +	struct device_node *bridge_node;
> +	struct drm_bridge *bridge;
> +
> +	bridge_node = of_graph_get_remote_port_parent(endpoint);
> +	if (!bridge_node) {
> +		DRM_ERROR("no valid bridge node\n");
> +		return -ENODEV;
> +	}
> +	of_node_put(bridge_node);
> +
> +	bridge = of_drm_find_bridge(bridge_node);
> +	if (!bridge) {
> +		DRM_INFO("wait for external HDMI bridge driver.\n");
> +		return -EPROBE_DEFER;
> +	}
> +	dsi->bridge = bridge;
> +
> +	return 0;
> +}
> +
> +static int dsi_parse_panel_endpoint(struct dw_dsi *dsi,
> +				    struct device_node *endpoint)
> +{
> +	struct device_node *panel_node;
> +	struct drm_panel *panel;
> +
> +	panel_node = of_graph_get_remote_port_parent(endpoint);
> +	if (!panel_node) {
> +		DRM_ERROR("no valid panel node\n");
> +		return -ENODEV;
> +	}
> +	of_node_put(panel_node);
> +
> +	panel = of_drm_find_panel(panel_node);
> +	if (!panel) {
> +		DRM_DEBUG_DRIVER("skip this panel endpoint.\n");
> +		return 0;
> +	}
> +	dsi->panel = panel;
> +
> +	return 0;
> +}
> +
> +static int dsi_parse_endpoint(struct dw_dsi *dsi,
> +			      struct device_node *np,
> +			      enum dsi_output_client client)
> +{
> +	struct device_node *ep_node;
> +	struct of_endpoint ep;
> +	int ret = 0;
> +
> +	if (client == OUT_MAX)
> +		return -EINVAL;
> +
> +	for_each_endpoint_of_node(np, ep_node) {
> +		ret = of_graph_parse_endpoint(ep_node, &ep);
> +		if (ret) {
> +			of_node_put(ep_node);
> +			return ret;
> +		}
> +
> +		/* skip dsi input port, port == 0 is input port */
> +		if (ep.port == 0)
> +			continue;
> +
> +		/* parse bridge endpoint */
> +		if (client == OUT_HDMI) {
> +			if (ep.id == 0) {
> +				ret = dsi_parse_bridge_endpoint(dsi, ep_node);
> +				if (dsi->bridge)
> +					break;
> +			}
> +		} else { /* parse panel endpoint */
> +			if (ep.id > 0) {
> +				ret = dsi_parse_panel_endpoint(dsi, ep_node);
> +				if (dsi->panel)
> +					break;
> +			}
> +		}
> +
> +		if (ret) {
> +			of_node_put(ep_node);
> +			return ret;
> +		}
> +	}
> +
> +	if (!dsi->bridge && !dsi->panel) {
> +		DRM_ERROR("at least one bridge or panel node is required\n");
> +		return -ENODEV;
> +	}
> +
> +	return 0;
> +}
> +
> +static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi)
> +{
> +	struct dsi_hw_ctx *ctx = dsi->ctx;
> +	const char *compatible;
> +	int ret = 0;
> +	struct device_node *np = NULL;
> +
> +	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970)
> +		compatible = "hisilicon,kirin970-dsi";
> +	else
> +		compatible = "hisilicon,kirin960-dsi";
> +
> +	np = of_find_compatible_node(NULL, NULL, compatible);
> +	if (!np) {
> +		dev_err(&pdev->dev, "NOT FOUND device node %s!\n", compatible);
> +		return -ENXIO;
> +	}
> +
> +	ctx->base = of_iomap(np, 0);
> +	if (!(ctx->base)) {
> +		dev_err(&pdev->dev, "failed to get dsi base resource.\n");
> +		return -ENXIO;
> +	}
> +
> +	ctx->peri_crg_base = of_iomap(np, 1);
> +	if (!(ctx->peri_crg_base)) {
> +		dev_err(&pdev->dev, "failed to get peri_crg_base resource.\n");
> +		return -ENXIO;
> +	}
> +
> +	if (ctx->g_dss_version_tag == FB_ACCEL_KIRIN970) {
> +		ctx->pctrl_base = of_iomap(np, 2);
> +		if (!(ctx->pctrl_base)) {
> +			dev_err(&pdev->dev,
> +				"failed to get dss pctrl_base resource.\n");
> +			return -ENXIO;
> +		}
> +	}
> +
> +	dsi->gpio_mux = devm_gpiod_get(&pdev->dev, "mux", GPIOD_OUT_HIGH);
> +	if (IS_ERR(dsi->gpio_mux))
> +		return PTR_ERR(dsi->gpio_mux);
> +
> +	/* set dsi default output to panel */
> +	dsi->cur_client = OUT_PANEL;
> +	dsi->attached_client = dsi->cur_client;
> +
> +	DRM_INFO("dsi  cur_client is %d  <0->hdmi;1->panel>\n",
> +		 dsi->cur_client);
> +	/* dis-reset */
> +	/* ip_reset_dis_dsi0, ip_reset_dis_dsi1 */
> +	writel(0x30000000, ctx->peri_crg_base + PERRSTDIS3);
> +
> +	ctx->dss_dphy0_ref_clk = devm_clk_get(&pdev->dev, "clk_txdphy0_ref");
> +	if (IS_ERR(ctx->dss_dphy0_ref_clk)) {
> +		dev_err(&pdev->dev, "failed to get dss_dphy0_ref_clk clock\n");
> +		return PTR_ERR(ctx->dss_dphy0_ref_clk);
> +	}
> +
> +	ret = clk_set_rate(ctx->dss_dphy0_ref_clk, DEFAULT_MIPI_CLK_RATE);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "dss_dphy0_ref_clk clk_set_rate(%lu) failed, error=%d!\n",
> +			  DEFAULT_MIPI_CLK_RATE, ret);
> +		return -EINVAL;
> +	}
> +
> +	DRM_DEBUG("dss_dphy0_ref_clk:[%lu]->[%lu].\n",
> +		  DEFAULT_MIPI_CLK_RATE, clk_get_rate(ctx->dss_dphy0_ref_clk));
> +
> +	ctx->dss_dphy0_cfg_clk = devm_clk_get(&pdev->dev, "clk_txdphy0_cfg");
> +	if (IS_ERR(ctx->dss_dphy0_cfg_clk)) {
> +		dev_err(&pdev->dev, "failed to get dss_dphy0_cfg_clk clock\n");
> +		return PTR_ERR(ctx->dss_dphy0_cfg_clk);
> +	}
> +
> +	ret = clk_set_rate(ctx->dss_dphy0_cfg_clk, DEFAULT_MIPI_CLK_RATE);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "dss_dphy0_cfg_clk clk_set_rate(%lu) failed, error=%d!\n",
> +			  DEFAULT_MIPI_CLK_RATE, ret);
> +		return -EINVAL;
> +	}
> +
> +	DRM_DEBUG("dss_dphy0_cfg_clk:[%lu]->[%lu].\n",
> +		  DEFAULT_MIPI_CLK_RATE, clk_get_rate(ctx->dss_dphy0_cfg_clk));
> +
> +	ctx->dss_pclk_dsi0_clk = devm_clk_get(&pdev->dev, "pclk_dsi0");
> +	if (IS_ERR(ctx->dss_pclk_dsi0_clk)) {
> +		dev_err(&pdev->dev, "failed to get dss_pclk_dsi0_clk clock\n");
> +		return PTR_ERR(ctx->dss_pclk_dsi0_clk);
> +	}
> +
> +	return 0;
> +}
> +
> +static int dsi_probe(struct platform_device *pdev)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +	struct device *dev = &pdev->dev;
> +	struct dsi_data *data;
> +	struct dw_dsi *dsi;
> +	struct dsi_hw_ctx *ctx;
> +	int ret;
> +
> +	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> +	if (!data) {
> +		dev_err(&pdev->dev, "failed to allocate dsi data.\n");
> +		return -ENOMEM;
> +	}
> +	dsi = &data->dsi;
> +	ctx = &data->ctx;
> +	dsi->ctx = ctx;
> +
> +	ctx->g_dss_version_tag = (long)of_device_get_match_data(dev);
> +
> +	/* parse HDMI bridge endpoint */
> +	ret = dsi_parse_endpoint(dsi, np, OUT_HDMI);
> +	if (ret)
> +		return ret;
> +
> +	ret = dsi_host_init(dev, dsi);
> +	if (ret)
> +		return ret;
> +
> +	/* parse panel endpoint */
> +	ret = dsi_parse_endpoint(dsi, np, OUT_PANEL);
> +	if (ret)
> +		goto err_host_unregister;
> +
> +	ret = dsi_parse_dt(pdev, dsi);
> +	if (ret)
> +		goto err_host_unregister;
> +
> +	platform_set_drvdata(pdev, data);
> +
> +	ret = component_add(dev, &dsi_ops);
> +	if (ret)
> +		goto err_host_unregister;
> +
> +	return 0;
> +
> +err_host_unregister:
> +	mipi_dsi_host_unregister(&dsi->host);
> +	return ret;
> +}
> +
> +static int dsi_remove(struct platform_device *pdev)
> +{
> +	component_del(&pdev->dev, &dsi_ops);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id dsi_of_match[] = {
> +	{
> +		.compatible = "hisilicon,kirin960-dsi",
> +		.data = (void *)FB_ACCEL_HI366x
> +	}, {
> +		.compatible = "hisilicon,kirin970-dsi",
> +		.data = (void *)FB_ACCEL_KIRIN970
> +	},
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, dsi_of_match);
> +
> +static struct platform_driver dsi_driver = {
> +	.probe = dsi_probe,
> +	.remove = dsi_remove,
> +	.driver = {
> +		.name = "kirin9xx-dw-dsi",
> +		.of_match_table = dsi_of_match,
> +	},
> +};
> +
> +module_platform_driver(dsi_driver);
> +
> +MODULE_DESCRIPTION("DesignWare MIPI DSI Host Controller v1.02 driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/staging/hikey9xx/gpu/kirin9xx_dw_dsi_reg.h b/drivers/staging/hikey9xx/gpu/kirin9xx_dw_dsi_reg.h
> new file mode 100644
> index 000000000000..0e3971ca328c
> --- /dev/null
> +++ b/drivers/staging/hikey9xx/gpu/kirin9xx_dw_dsi_reg.h
> @@ -0,0 +1,142 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2016 Linaro Limited.
> + * Copyright (c) 2014-2016 Hisilicon Limited.
> + * Copyright (c) 2014-2020, Huawei Technologies Co., Ltd
> + */
> +
> +#ifndef __DW_DSI_REG_H__
> +#define __DW_DSI_REG_H__
> +
> +#define MASK(x)				(BIT(x) - 1)
Not used, delete.

> +#define DEFAULT_MAX_TX_ESC_CLK	(10 * 1000000UL)
> +/*
> + * regs
> + */
> +#define PWR_UP                  0x04  /* Core power-up */
> +#define RESET                   0
> +#define POWERUP                 BIT(0)
> +#define PHY_IF_CFG              0xA4  /* D-PHY interface configuration */
> +#define CLKMGR_CFG              0x08  /* the internal clock dividers */
> +#define PHY_RSTZ                0xA0  /* D-PHY reset control */
> +#define PHY_ENABLECLK           BIT(2)
> +#define PHY_UNRSTZ              BIT(1)
> +#define PHY_UNSHUTDOWNZ         BIT(0)
> +#define PHY_TST_CTRL0           0xB4  /* D-PHY test interface control 0 */
> +#define PHY_TST_CTRL1           0xB8  /* D-PHY test interface control 1 */
> +#define CLK_TLPX                0x10
> +#define CLK_THS_PREPARE         0x11
> +#define CLK_THS_ZERO            0x12
> +#define CLK_THS_TRAIL           0x13
> +#define CLK_TWAKEUP             0x14
> +#define DATA_TLPX(x)            (0x20 + ((x) << 4))
> +#define DATA_THS_PREPARE(x)     (0x21 + ((x) << 4))
> +#define DATA_THS_ZERO(x)        (0x22 + ((x) << 4))
> +#define DATA_THS_TRAIL(x)       (0x23 + ((x) << 4))
> +#define DATA_TTA_GO(x)          (0x24 + ((x) << 4))
> +#define DATA_TTA_GET(x)         (0x25 + ((x) << 4))
> +#define DATA_TWAKEUP(x)         (0x26 + ((x) << 4))
> +#define PHY_CFG_I               0x60
> +#define PHY_CFG_PLL_I           0x63
> +#define PHY_CFG_PLL_II          0x64
> +#define PHY_CFG_PLL_III         0x65
> +#define PHY_CFG_PLL_IV          0x66
> +#define PHY_CFG_PLL_V           0x67
> +#define DPI_COLOR_CODING        0x10  /* DPI color coding */
> +#define DPI_CFG_POL             0x14  /* DPI polarity configuration */
> +#define VID_HSA_TIME            0x48  /* Horizontal Sync Active time */
> +#define VID_HBP_TIME            0x4C  /* Horizontal Back Porch time */
> +#define VID_HLINE_TIME          0x50  /* Line time */
> +#define VID_VSA_LINES           0x54  /* Vertical Sync Active period */
> +#define VID_VBP_LINES           0x58  /* Vertical Back Porch period */
> +#define VID_VFP_LINES           0x5C  /* Vertical Front Porch period */
> +#define VID_VACTIVE_LINES       0x60  /* Vertical resolution */
> +#define VID_PKT_SIZE            0x3C  /* Video packet size */
> +#define VID_MODE_CFG            0x38  /* Video mode configuration */
> +#define GEN_HDR			0x6c
> +#define GEN_HDATA(data)		(((data) & 0xffff) << 8)
> +#define GEN_HDATA_MASK		(0xffff << 8)
> +#define GEN_HTYPE(type)		(((type) & 0xff) << 0)
> +#define GEN_HTYPE_MASK		0xff
> +#define GEN_PLD_DATA		0x70
> +#define CMD_PKT_STATUS		0x74
> +#define GEN_CMD_EMPTY		BIT(0)
> +#define GEN_CMD_FULL		BIT(1)
> +#define GEN_PLD_W_EMPTY		BIT(2)
> +#define GEN_PLD_W_FULL		BIT(3)
> +#define GEN_PLD_R_EMPTY		BIT(4)
> +#define GEN_PLD_R_FULL		BIT(5)
> +#define GEN_RD_CMD_BUSY		BIT(6)
> +#define CMD_MODE_CFG		0x68
> +#define MAX_RD_PKT_SIZE_LP	BIT(24)
> +#define DCS_LW_TX_LP		BIT(19)
> +#define DCS_SR_0P_TX_LP		BIT(18)
> +#define DCS_SW_1P_TX_LP		BIT(17)
> +#define DCS_SW_0P_TX_LP		BIT(16)
> +#define GEN_LW_TX_LP		BIT(14)
> +#define GEN_SR_2P_TX_LP		BIT(13)
> +#define GEN_SR_1P_TX_LP		BIT(12)
> +#define GEN_SR_0P_TX_LP		BIT(11)
> +#define GEN_SW_2P_TX_LP		BIT(10)
> +#define GEN_SW_1P_TX_LP		BIT(9)
> +#define GEN_SW_0P_TX_LP		BIT(8)
> +#define EN_ACK_RQST		BIT(1)
> +#define EN_TEAR_FX		BIT(0)
> +#define CMD_MODE_ALL_LP		(MAX_RD_PKT_SIZE_LP | \
> +				 DCS_LW_TX_LP | \
> +				 DCS_SR_0P_TX_LP | \
> +				 DCS_SW_1P_TX_LP | \
> +				 DCS_SW_0P_TX_LP | \
> +				 GEN_LW_TX_LP | \
> +				 GEN_SR_2P_TX_LP | \
> +				 GEN_SR_1P_TX_LP | \
> +				 GEN_SR_0P_TX_LP | \
> +				 GEN_SW_2P_TX_LP | \
> +				 GEN_SW_1P_TX_LP | \
> +				 GEN_SW_0P_TX_LP)
> +#define PHY_TMR_CFG             0x9C  /* Data lanes timing configuration */
> +#define BTA_TO_CNT              0x8C  /* Response timeout definition */
> +#define PHY_TMR_LPCLK_CFG       0x98  /* clock lane timing configuration */
> +#define CLK_DATA_TMR_CFG        0xCC
> +#define LPCLK_CTRL              0x94  /* Low-power in clock lane */
> +#define PHY_TXREQUESTCLKHS      BIT(0)
> +#define MODE_CFG                0x34  /* Video or Command mode selection */
> +#define PHY_STATUS              0xB0  /* D-PHY PPI status interface */
> +
> +#define	PHY_STOP_WAIT_TIME      0x30
> +#define CMD_PKT_STATUS_TIMEOUT_US	20000
> +
> +/*
> + * regs relevant enum
> + */
> +enum dpi_color_coding {
> +	DSI_24BITS_1 = 5,
> +};
> +
> +enum dsi_video_mode_type {
> +	DSI_NON_BURST_SYNC_PULSES = 0,
> +	DSI_NON_BURST_SYNC_EVENTS,
> +	DSI_BURST_SYNC_PULSES_1,
> +	DSI_BURST_SYNC_PULSES_2
> +};
> +
> +enum dsi_work_mode {
> +	DSI_VIDEO_MODE = 0,
> +	DSI_COMMAND_MODE
> +};
> +
> +/*
> + * Register Write/Read Helper functions
> + */
> +static inline void dw_update_bits(void __iomem *addr, u32 bit_start,
> +				  u32 mask, u32 val)

Not used I think, so delete if not.

> +{
> +	u32 tmp, orig;
> +
> +	orig = readl(addr);
> +	tmp = orig & ~(mask << bit_start);
> +	tmp |= (val & mask) << bit_start;
> +	writel(tmp, addr);
> +}
> +
> +#endif /* __DW_DRM_DSI_H__ */


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

* Re: [PATCH 00/49] DRM driver for Hikey 970
       [not found]           ` <20200824180225.1a515b6a@coco.lan>
                               ` (3 preceding siblings ...)
  2020-08-25 18:11             ` Sam Ravnborg
@ 2020-08-25 20:21             ` Sam Ravnborg
  4 siblings, 0 replies; 42+ messages in thread
From: Sam Ravnborg @ 2020-08-25 20:21 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Laurent Pinchart
  Cc: Greg Kroah-Hartman, Neil Armstrong, Xinliang Liu, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Laurent Pinchart, devel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	David Airlie, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Laurentiu Palcu, linux-media, devicetree, Liwei Cai,
	Jesper Dangaard Brouer, Manivannan Sadhasivam, Chen Feng,
	Alexei Starovoitov, linaro-mm-sig, Rob Herring, Jakub Kicinski,
	mauro.chehab, Rob Clark, linux-arm-kernel, netdev, linux-kernel,
	Liuyao An, Rongrong Zou, bpf, David S. Miller

Hi Mauro.

Laurent and I discussed this driver a little on irc.
Some highlights:

This parts could use register names:
+       writel(0x2, noc_dss_base + 0xc);
+       writel(0x2, noc_dss_base + 0x8c);
+       writel(0x2, noc_dss_base + 0x10c);
+       writel(0x2, noc_dss_base + 0x18c);

The two nodes in the DT for DPE and DSI uses overlapping range for reg
entries. It looks like a syscon node or some iommu thing is needed to do
this properly.

The chain will lok like this:

DPE -> DSI -> video mux -> {adv7533, panel}

But drm_bridge has not yet support for such non-linear setup.
The recommendation is to focus on the HDMI prat. Then we can later
come up with support for a video mux.

The video mux should have a dedicated node with one input node and two
output nodes. Which is also where the gpio should be.

The DSI node references two DPHY instances - should it be PHY driver(s)?

Does the DSI part contain one or two instances. Clocks looks duplicated.

Does the DPE and DSI share a lot of register blocks - or does it just
look like this from a first point of view?

You can read though the logs here:
https://people.freedesktop.org/~cbrill/dri-log/index.php

Could you please try to get back on some of the points above so we can
help you move forward in the right direction.

Thanks,
	Sam

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

* Re: [PATCH 00/49] DRM driver for Hikey 970
  2020-08-25 11:30             ` Mauro Carvalho Chehab
  2020-08-25 11:38               ` Laurent Pinchart
  2020-08-25 12:31               ` Daniel Stone
@ 2020-08-26 14:44               ` Nicolas Dufresne
  2 siblings, 0 replies; 42+ messages in thread
From: Nicolas Dufresne @ 2020-08-26 14:44 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Dave Airlie
  Cc: Laurent Pinchart, Neil Armstrong, David Airlie, Wanchun Zheng,
	linuxarm, dri-devel, Andrzej Hajda, Sam Ravnborg, driverdevel,
	Daniel Borkmann, John Fastabend, Xiubin Zhang, Wei Xu,
	Xinliang Liu, Xinwei Kong, Tomi Valkeinen, Bogdan Togorean,
	Jakub Kicinski, Laurentiu Palcu, linux-media,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Liwei Cai, Jesper Dangaard Brouer, Manivannan Sadhasivam,
	Chen Feng, Alexei Starovoitov,
	moderated list:DMA BUFFER SHARING FRAMEWORK, Rob Herring,
	mauro.chehab, Rob Clark, linux-arm-kernel, Greg Kroah-Hartman,
	lkml, Liuyao An, Network Development, Rongrong Zou,
	BPF Mailing List, David S. Miller

Le mardi 25 août 2020 à 13:30 +0200, Mauro Carvalho Chehab a écrit :
> Em Tue, 25 Aug 2020 05:29:29 +1000
> Dave Airlie <airlied@gmail.com> escreveu:
> 
> > On Thu, 20 Aug 2020 at 20:02, Laurent Pinchart
> > <laurent.pinchart@ideasonboard.com> wrote:
> > > Hi Mauro,
> > > 
> > > On Thu, Aug 20, 2020 at 09:03:26AM +0200, Mauro Carvalho Chehab wrote:  
> > > > Em Wed, 19 Aug 2020 12:52:06 -0700 John Stultz escreveu:  
> > > > > On Wed, Aug 19, 2020 at 8:31 AM Laurent Pinchart wrote:  
> > > > > > On Wed, Aug 19, 2020 at 05:21:20PM +0200, Sam Ravnborg wrote:  
> > > > > > > On Wed, Aug 19, 2020 at 01:45:28PM +0200, Mauro Carvalho Chehab wrote:  
> > > > > > > > This patch series port the out-of-tree driver for Hikey 970 (which
> > > > > > > > should also support Hikey 960) from the official 96boards tree:
> > > > > > > > 
> > > > > > > >    https://github.com/96boards-hikey/linux/tree/hikey970-v4.9
> > > > > > > > 
> > > > > > > > Based on his history, this driver seems to be originally written
> > > > > > > > for Kernel 4.4, and was later ported to Kernel 4.9. The original
> > > > > > > > driver used to depend on ION (from Kernel 4.4) and had its own
> > > > > > > > implementation for FB dev API.
> > > > > > > > 
> > > > > > > > As I need to preserve the original history (with has patches from
> > > > > > > > both HiSilicon and from Linaro),  I'm starting from the original
> > > > > > > > patch applied there. The remaining patches are incremental,
> > > > > > > > and port this driver to work with upstream Kernel.
> > > > > > > >  
> > > > > ...  
> > > > > > > > - Due to legal reasons, I need to preserve the authorship of
> > > > > > > >   each one responsbile for each patch. So, I need to start from
> > > > > > > >   the original patch from Kernel 4.4;  
> > > > > ...  
> > > > > > > I do acknowledge you need to preserve history and all -
> > > > > > > but this patchset is not easy to review.  
> > > > > > 
> > > > > > Why do we need to preserve history ? Adding relevant Signed-off-by and
> > > > > > Co-developed-by should be enough, shouldn't it ? Having a public branch
> > > > > > that contains the history is useful if anyone is interested, but I don't
> > > > > > think it's required in mainline.  
> > > > > 
> > > > > Yea. I concur with Laurent here. I'm not sure what legal reasoning you
> > > > > have on this but preserving the "absolute" history here is actively
> > > > > detrimental for review and understanding of the patch set.
> > > > > 
> > > > > Preserving Authorship, Signed-off-by lines and adding Co-developed-by
> > > > > lines should be sufficient to provide both atribution credit and DCO
> > > > > history.  
> > > > 
> > > > I'm not convinced that, from legal standpoint, folding things would
> > > > be enough. See, there are at least 3 legal systems involved here
> > > > among the different patch authors:
> > > > 
> > > >       - civil law;
> > > >       - common law;
> > > >       - customary law + common law.
> > > > 
> > > > Merging stuff altogether from different law systems can be problematic,
> > > > and trying to discuss this with experienced IP property lawyers will
> > > > for sure take a lot of time and efforts. I also bet that different
> > > > lawyers will have different opinions, because laws are subject to
> > > > interpretation. With that matter I'm not aware of any court rules
> > > > with regards to folded patches. So, it sounds to me that folding
> > > > patches is something that has yet to be proofed in courts around
> > > > the globe.
> > > > 
> > > > At least for US legal system, it sounds that the Country of
> > > > origin of a patch is relevant, as they have a concept of
> > > > "national technology" that can be subject to export regulations.
> > > > 
> > > > From my side, I really prefer to play safe and stay out of any such
> > > > legal discussions.  
> > > 
> > > Let's be serious for a moment. If you think there are legal issues in
> > > taking GPL-v2.0-only patches and squashing them while retaining
> > > authorship information through tags, the Linux kernel if *full* of that.
> > > You also routinely modify patches that you commit to the media subsystem
> > > to fix "small issues".
> > > 
> > > The country of origin argument makes no sense either, the kernel code
> > > base if full of code coming from pretty much all country on the planet.
> > > 
> > > Keeping the patches separate make this hard to review. Please squash
> > > them.  
> > 
> > I'm inclined to agree with Laurent here.
> > 
> > Patches submitted as GPL-v2 with DCO lines and author names/companies
> > should be fine to be squashed and rearranged,
> > as long as the DCO and Authorship is kept somewhere in the new patch
> > that is applied.
> > 
> > Review is more important here.
> 
> Sorry, but I can't agree that review is more important than to be able
> to properly indicate copyrights in a valid way at the legal systems that
> it would apply ;-)

Regardless of the "review-ability", our users distribute the Linux
Kernel as a whole, so who contributed which specific line of code is
already lost in a way. All we see in the distribution if a list of
copyright holder and licenses. In this context, the per patches
ownership have no legal implication. My two, non lawyer cents.

> 
> In any case, there's an easy way to make the code easy to review:
> I can write the patches against staging (where it is OK to submit
> preserving the history) and then add a final patch moving it out
> of staging.
> 
> You can then just review the last patch, as it will contain the
> entire code on it.
> 
> Another alternative, as I'm already doing with Sam, is for me to
> submit the folded code as a reply to 00/xx. You can then just 
> review the final code, without concerning about how the code reached
> there.
> 
> From review point of the view, this will be the same as reviewing
> a folded patch, but, from legal standpoint, the entire copyright
> chain will be preserved.
> 
> Thanks,
> Mauro


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

end of thread, other threads:[~2020-08-26 14:44 UTC | newest]

Thread overview: 42+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-19 11:45 [PATCH 00/49] DRM driver for Hikey 970 Mauro Carvalho Chehab
2020-08-19 11:45 ` [PATCH 01/49] staging: hikey9xx: Add hisilicon DRM driver for hikey960/970 Mauro Carvalho Chehab
2020-08-19 11:46 ` [PATCH 40/49] staging: hikey9xx/gpu: get rid of input/output macros Mauro Carvalho Chehab
2020-08-19 15:21 ` [PATCH 00/49] DRM driver for Hikey 970 Sam Ravnborg
2020-08-19 15:30   ` Laurent Pinchart
2020-08-19 19:52     ` John Stultz
2020-08-20  7:03       ` Mauro Carvalho Chehab
2020-08-20 10:02         ` Laurent Pinchart
2020-08-24 19:29           ` Dave Airlie
2020-08-25 11:30             ` Mauro Carvalho Chehab
2020-08-25 11:38               ` Laurent Pinchart
2020-08-25 12:31               ` Daniel Stone
2020-08-26 14:44               ` Nicolas Dufresne
     [not found]   ` <20200819174027.70b39ee9@coco.lan>
     [not found]     ` <20200819204800.GA110118@ravnborg.org>
2020-08-20  7:21       ` Michel Dänzer
2020-08-20  7:21       ` Mauro Carvalho Chehab
2020-08-21 16:09       ` Joe Perches
     [not found]     ` <20200819173558.GA3733@ravnborg.org>
2020-08-20 14:06       ` Mauro Carvalho Chehab
2020-08-20 14:48         ` Sam Ravnborg
2020-08-20 15:13           ` Mauro Carvalho Chehab
2020-08-20 15:36             ` Sam Ravnborg
2020-08-21 13:37       ` Mauro Carvalho Chehab
2020-08-21 13:58       ` Mauro Carvalho Chehab
2020-08-21 15:55         ` Sam Ravnborg
     [not found]           ` <20200824180225.1a515b6a@coco.lan>
2020-08-24 18:45             ` Sam Ravnborg
2020-08-24 21:10             ` Sam Ravnborg
2020-08-24 21:24             ` Sam Ravnborg
2020-08-25 18:11             ` Sam Ravnborg
2020-08-25 20:21             ` Sam Ravnborg
2020-08-21 14:41       ` Mauro Carvalho Chehab
2020-08-21 15:56         ` Sam Ravnborg
2020-08-24 16:06           ` Mauro Carvalho Chehab
2020-08-19 21:13 ` John Stultz
2020-08-19 21:25   ` Sam Ravnborg
2020-08-20  6:40     ` Mauro Carvalho Chehab
2020-08-20  6:34   ` Mauro Carvalho Chehab
2020-08-19 21:36 ` John Stultz
2020-08-20  2:01   ` John Stultz
2020-08-20  3:28     ` John Stultz
2020-08-20  7:48       ` Mauro Carvalho Chehab
2020-08-24  6:49       ` Mauro Carvalho Chehab
2020-08-24 13:18         ` Mauro Carvalho Chehab
2020-08-20  8:04   ` Mauro Carvalho Chehab

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).