[PATCH v5 4/9] drm/vs: Add Hardware Functions for VS DC8200

keith zhao posted 9 patches 3 days, 5 hours ago
[PATCH v5 4/9] drm/vs: Add Hardware Functions for VS DC8200
Posted by keith zhao 3 days, 5 hours ago
This commit introduces hardware-based APIs for
the VS DRM related to the DC8200

Signed-off-by: keith zhao <keith.zhao@starfivetech.com>
---
 MAINTAINERS                            |    1 +
 drivers/gpu/drm/Kconfig                |    2 +
 drivers/gpu/drm/Makefile               |    1 +
 drivers/gpu/drm/verisilicon/Kconfig    |   13 +
 drivers/gpu/drm/verisilicon/Makefile   |    5 +
 drivers/gpu/drm/verisilicon/vs_dc_hw.c | 1104 ++++++++++++++++++++++++
 drivers/gpu/drm/verisilicon/vs_dc_hw.h |  492 +++++++++++
 drivers/gpu/drm/verisilicon/vs_type.h  |   54 ++
 8 files changed, 1672 insertions(+)
 create mode 100644 drivers/gpu/drm/verisilicon/Kconfig
 create mode 100644 drivers/gpu/drm/verisilicon/Makefile
 create mode 100644 drivers/gpu/drm/verisilicon/vs_dc_hw.c
 create mode 100644 drivers/gpu/drm/verisilicon/vs_dc_hw.h
 create mode 100644 drivers/gpu/drm/verisilicon/vs_type.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 7766ee0bdd74..55d6bccdd036 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7440,6 +7440,7 @@ T:	git https://gitlab.freedesktop.org/drm/misc/kernel.git
 F:	Documentation/devicetree/bindings/display/bridge/innosilicon,inno-hdmi.yaml
 F:	Documentation/devicetree/bindings/display/starfive/
 F:	drivers/gpu/drm/bridge/innosilicon/
+F:	drivers/gpu/drm/verisilicon
 F:	include/drm/bridge/inno_hdmi.h
 
 DRM DRIVER FOR SYNAPTICS R63353 PANELS
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 1df4e627e3d3..0abd0ecbe1e5 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -481,6 +481,8 @@ source "drivers/gpu/drm/sprd/Kconfig"
 
 source "drivers/gpu/drm/imagination/Kconfig"
 
+source "drivers/gpu/drm/verisilicon/Kconfig"
+
 config DRM_HYPERV
 	tristate "DRM Support for Hyper-V synthetic video device"
 	depends on DRM && PCI && MMU && HYPERV
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 3894f43f6d47..9450b90d5df1 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -223,3 +223,4 @@ obj-y			+= solomon/
 obj-$(CONFIG_DRM_SPRD) += sprd/
 obj-$(CONFIG_DRM_LOONGSON) += loongson/
 obj-$(CONFIG_DRM_POWERVR) += imagination/
+obj-$(CONFIG_DRM_VERISILICON_DC8200) += verisilicon/
diff --git a/drivers/gpu/drm/verisilicon/Kconfig b/drivers/gpu/drm/verisilicon/Kconfig
new file mode 100644
index 000000000000..874e8bcde5d5
--- /dev/null
+++ b/drivers/gpu/drm/verisilicon/Kconfig
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0
+config DRM_VERISILICON_DC8200
+	tristate "DRM Support for VeriSilicon DC8200"
+	depends on DRM
+	select DRM_KMS_HELPER
+	select DRM_GEM_DMA_HELPER
+	select DMA_CMA if HAVE_DMA_CONTIGUOUS
+	select CMA if HAVE_DMA_CONTIGUOUS
+	help
+	  Choose this option if you have a VeriSilicon DC8200 chipset.
+	  This driver provides VeriSilicon kernel mode
+	  setting and buffer management. It does not
+	  provide 2D or 3D acceleration.
diff --git a/drivers/gpu/drm/verisilicon/Makefile b/drivers/gpu/drm/verisilicon/Makefile
new file mode 100644
index 000000000000..7da54b259940
--- /dev/null
+++ b/drivers/gpu/drm/verisilicon/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
+vs_drm-objs := vs_dc_hw.o
+
+obj-$(CONFIG_DRM_VERISILICON_DC8200) += vs_drm.o
diff --git a/drivers/gpu/drm/verisilicon/vs_dc_hw.c b/drivers/gpu/drm/verisilicon/vs_dc_hw.c
new file mode 100644
index 000000000000..44c216fdf78d
--- /dev/null
+++ b/drivers/gpu/drm/verisilicon/vs_dc_hw.c
@@ -0,0 +1,1104 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) VeriSilicon Holdings Co., Ltd.
+ */
+
+#include <linux/bits.h>
+#include <linux/io.h>
+#include <linux/media-bus-format.h>
+#include <drm/drm_blend.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_framebuffer.h>
+
+#include "vs_dc_hw.h"
+
+static const u32 horkernel[] = {
+	0x00000000, 0x20000000, 0x00002000, 0x00000000,
+	0x00000000, 0x00000000, 0x23fd1c03, 0x00000000,
+	0x00000000, 0x00000000, 0x181f0000, 0x000027e1,
+	0x00000000, 0x00000000, 0x00000000, 0x2b981468,
+	0x00000000, 0x00000000, 0x00000000, 0x10f00000,
+	0x00002f10, 0x00000000, 0x00000000, 0x00000000,
+	0x32390dc7, 0x00000000, 0x00000000, 0x00000000,
+	0x0af50000, 0x0000350b, 0x00000000, 0x00000000,
+	0x00000000, 0x3781087f, 0x00000000, 0x00000000,
+	0x00000000, 0x06660000, 0x0000399a, 0x00000000,
+	0x00000000, 0x00000000, 0x3b5904a7, 0x00000000,
+	0x00000000, 0x00000000, 0x033c0000, 0x00003cc4,
+	0x00000000, 0x00000000, 0x00000000, 0x3de1021f,
+	0x00000000, 0x00000000, 0x00000000, 0x01470000,
+	0x00003eb9, 0x00000000, 0x00000000, 0x00000000,
+	0x3f5300ad, 0x00000000, 0x00000000, 0x00000000,
+	0x00480000, 0x00003fb8, 0x00000000, 0x00000000,
+	0x00000000, 0x3fef0011, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00004000, 0x00000000,
+	0x00000000, 0x00000000, 0x20002000, 0x00000000,
+	0x00000000, 0x00000000, 0x1c030000, 0x000023fd,
+	0x00000000, 0x00000000, 0x00000000, 0x27e1181f,
+	0x00000000, 0x00000000, 0x00000000, 0x14680000,
+	0x00002b98, 0x00000000, 0x00000000, 0x00000000,
+	0x2f1010f0, 0x00000000, 0x00000000, 0x00000000,
+	0x0dc70000, 0x00003239, 0x00000000, 0x00000000,
+	0x00000000, 0x350b0af5, 0x00000000, 0x00000000,
+	0x00000000, 0x087f0000, 0x00003781, 0x00000000,
+	0x00000000, 0x00000000, 0x399a0666, 0x00000000,
+	0x00000000, 0x00000000, 0x04a70000, 0x00003b59,
+	0x00000000, 0x00000000, 0x00000000, 0x3cc4033c,
+	0x00000000, 0x00000000, 0x00000000, 0x021f0000,
+};
+
+#define H_COEF_SIZE ARRAY_SIZE(horkernel)
+
+static const u32 verkernel[] = {
+	0x00000000, 0x20000000, 0x00002000, 0x00000000,
+	0x00000000, 0x00000000, 0x23fd1c03, 0x00000000,
+	0x00000000, 0x00000000, 0x181f0000, 0x000027e1,
+	0x00000000, 0x00000000, 0x00000000, 0x2b981468,
+	0x00000000, 0x00000000, 0x00000000, 0x10f00000,
+	0x00002f10, 0x00000000, 0x00000000, 0x00000000,
+	0x32390dc7, 0x00000000, 0x00000000, 0x00000000,
+	0x0af50000, 0x0000350b, 0x00000000, 0x00000000,
+	0x00000000, 0x3781087f, 0x00000000, 0x00000000,
+	0x00000000, 0x06660000, 0x0000399a, 0x00000000,
+	0x00000000, 0x00000000, 0x3b5904a7, 0x00000000,
+	0x00000000, 0x00000000, 0x033c0000, 0x00003cc4,
+	0x00000000, 0x00000000, 0x00000000, 0x3de1021f,
+	0x00000000, 0x00000000, 0x00000000, 0x01470000,
+	0x00003eb9, 0x00000000, 0x00000000, 0x00000000,
+	0x3f5300ad, 0x00000000, 0x00000000, 0x00000000,
+	0x00480000, 0x00003fb8, 0x00000000, 0x00000000,
+	0x00000000, 0x3fef0011, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00004000, 0x00000000,
+	0xcdcd0000, 0xfdfdfdfd, 0xabababab, 0xabababab,
+	0x00000000, 0x00000000, 0x5ff5f456, 0x000f5f58,
+	0x02cc6c78, 0x02cc0c28, 0xfeeefeee, 0xfeeefeee,
+	0xfeeefeee, 0xfeeefeee, 0xfeeefeee, 0xfeeefeee,
+	0xfeeefeee, 0xfeeefeee, 0xfeeefeee, 0xfeeefeee,
+	0xfeeefeee, 0xfeeefeee, 0xfeeefeee, 0xfeeefeee,
+	0xfeeefeee, 0xfeeefeee, 0xfeeefeee, 0xfeeefeee,
+	0xfeeefeee, 0xfeeefeee, 0xfeeefeee, 0xfeeefeee,
+	0xfeeefeee, 0xfeeefeee, 0xfeeefeee, 0xfeeefeee,
+	0xfeeefeee, 0xfeeefeee, 0xfeeefeee, 0xfeeefeee,
+	0xfeeefeee, 0xfeeefeee, 0xfeeefeee, 0xfeeefeee,
+	0xfeeefeee, 0xfeeefeee, 0xfeeefeee, 0xfeeefeee,
+	0xfeeefeee, 0xfeeefeee, 0xfeeefeee, 0xfeeefeee,
+};
+
+#define V_COEF_SIZE ARRAY_SIZE(verkernel)
+
+/*
+ * RGB 709->2020 conversion parameters
+ */
+static const u16 RGB2RGB[RGB_TO_RGB_TABLE_SIZE] = {
+	10279, 5395, 709,
+	1132, 15065, 187,
+	269, 1442, 14674
+};
+
+/*
+ * YUV601 to RGB conversion parameters
+ * YUV2RGB[0]  - [8] : C0 - C8;
+ * YUV2RGB[9]  - [11]: D0 - D2;
+ * YUV2RGB[12] - [13]: Y clamp min & max calue;
+ * YUV2RGB[14] - [15]: UV clamp min & max calue;
+ */
+static const s32 YUV601_2RGB[YUV_TO_RGB_TABLE_SIZE] = {
+	1196, 0, 1640, 1196,
+	-404, -836, 1196, 2076,
+	0, -916224, 558336, -1202944,
+	64, 940, 64, 960
+};
+
+/*
+ * YUV709 to RGB conversion parameters
+ * YUV2RGB[0]  - [8] : C0 - C8;
+ * YUV2RGB[9]  - [11]: D0 - D2;
+ * YUV2RGB[12] - [13]: Y clamp min & max calue;
+ * YUV2RGB[14] - [15]: UV clamp min & max calue;
+ */
+static s32 YUV709_2RGB[YUV_TO_RGB_TABLE_SIZE] = {
+	1196, 0, 1844, 1196,
+	-220, -548, 1196, 2172,
+	0, -1020672, 316672, -1188608,
+	64, 940, 64, 960
+};
+
+/*
+ * YUV2020 to RGB conversion parameters
+ * YUV2RGB[0]  - [8] : C0 - C8;
+ * YUV2RGB[9]  - [11]: D0 - D2;
+ * YUV2RGB[12] - [13]: Y clamp min & max calue;
+ * YUV2RGB[14] - [15]: UV clamp min & max calue;
+ */
+static s32 YUV2020_2RGB[YUV_TO_RGB_TABLE_SIZE] = {
+	1196, 0, 1724, 1196,
+	-192, -668, 1196, 2200,
+	0, -959232, 363776, -1202944,
+	64, 940, 64, 960
+};
+
+/*
+ * RGB to YUV2020 conversion parameters
+ * RGB2YUV[0] - [8] : C0 - C8;
+ * RGB2YUV[9] - [11]: D0 - D2;
+ */
+static s16 RGB2YUV[RGB_TO_YUV_TABLE_SIZE] = {
+	230, 594, 52,
+	-125, -323, 448,
+	448, -412, -36,
+	64, 512, 512
+};
+
+/* one is for primary plane and the other is for all overlay planes */
+static const struct dc_hw_plane_reg dc_plane_reg[] = {
+	{
+		.y_address		= DC_FRAMEBUFFER_ADDRESS,
+		.u_address		= DC_FRAMEBUFFER_U_ADDRESS,
+		.v_address		= DC_FRAMEBUFFER_V_ADDRESS,
+		.y_stride		= DC_FRAMEBUFFER_STRIDE,
+		.u_stride		= DC_FRAMEBUFFER_U_STRIDE,
+		.v_stride		= DC_FRAMEBUFFER_V_STRIDE,
+		.size			= DC_FRAMEBUFFER_SIZE,
+		.top_left		= DC_FRAMEBUFFER_TOP_LEFT,
+		.bottom_right	= DC_FRAMEBUFFER_BOTTOM_RIGHT,
+		.scale_factor_x			= DC_FRAMEBUFFER_SCALE_FACTOR_X,
+		.scale_factor_y			= DC_FRAMEBUFFER_SCALE_FACTOR_Y,
+		.h_filter_coef_index	= DC_FRAMEBUFFER_H_FILTER_COEF_INDEX,
+		.h_filter_coef_data		= DC_FRAMEBUFFER_H_FILTER_COEF_DATA,
+		.v_filter_coef_index	= DC_FRAMEBUFFER_V_FILTER_COEF_INDEX,
+		.v_filter_coef_data		= DC_FRAMEBUFFER_V_FILTER_COEF_DATA,
+		.init_offset			= DC_FRAMEBUFFER_INIT_OFFSET,
+		.color_key				= DC_FRAMEBUFFER_COLOR_KEY,
+		.color_key_high			= DC_FRAMEBUFFER_COLOR_KEY_HIGH,
+		.clear_value			= DC_FRAMEBUFFER_CLEAR_VALUE,
+		.color_table_index		= DC_FRAMEBUFFER_COLOR_TABLE_INDEX,
+		.color_table_data		= DC_FRAMEBUFFER_COLOR_TABLE_DATA,
+		.scale_config			= DC_FRAMEBUFFER_SCALE_CONFIG,
+		.water_mark				= DC_FRAMEBUFFER_WATER_MARK,
+		.degamma_index			= DC_FRAMEBUFFER_DEGAMMA_INDEX,
+		.degamma_data			= DC_FRAMEBUFFER_DEGAMMA_DATA,
+		.degamma_ex_data		= DC_FRAMEBUFFER_DEGAMMA_EX_DATA,
+		.src_global_color		= DC_FRAMEBUFFER_SRC_GLOBAL_COLOR,
+		.dst_global_color		= DC_FRAMEBUFFER_DST_GLOBAL_COLOR,
+		.blend_config			= DC_FRAMEBUFFER_BLEND_CONFIG,
+		.roi_origin				= DC_FRAMEBUFFER_ROI_ORIGIN,
+		.roi_size				= DC_FRAMEBUFFER_ROI_SIZE,
+		.yuv_to_rgb_coef0			= DC_FRAMEBUFFER_YUVTORGB_COEF0,
+		.yuv_to_rgb_coef1			= DC_FRAMEBUFFER_YUVTORGB_COEF1,
+		.yuv_to_rgb_coef2			= DC_FRAMEBUFFER_YUVTORGB_COEF2,
+		.yuv_to_rgb_coef3			= DC_FRAMEBUFFER_YUVTORGB_COEF3,
+		.yuv_to_rgb_coef4			= DC_FRAMEBUFFER_YUVTORGB_COEF4,
+		.yuv_to_rgb_coefd0			= DC_FRAMEBUFFER_YUVTORGB_COEFD0,
+		.yuv_to_rgb_coefd1			= DC_FRAMEBUFFER_YUVTORGB_COEFD1,
+		.yuv_to_rgb_coefd2			= DC_FRAMEBUFFER_YUVTORGB_COEFD2,
+		.y_clamp_bound				= DC_FRAMEBUFFER_Y_CLAMP_BOUND,
+		.uv_clamp_bound				= DC_FRAMEBUFFER_UV_CLAMP_BOUND,
+		.rgb_to_rgb_coef0			= DC_FRAMEBUFFER_RGBTORGB_COEF0,
+		.rgb_to_rgb_coef1			= DC_FRAMEBUFFER_RGBTORGB_COEF1,
+		.rgb_to_rgb_coef2			= DC_FRAMEBUFFER_RGBTORGB_COEF2,
+		.rgb_to_rgb_coef3			= DC_FRAMEBUFFER_RGBTORGB_COEF3,
+		.rgb_to_rgb_coef4			= DC_FRAMEBUFFER_RGBTORGB_COEF4,
+	},
+	{
+		.y_address		= DC_OVERLAY_ADDRESS,
+		.u_address		= DC_OVERLAY_U_ADDRESS,
+		.v_address		= DC_OVERLAY_V_ADDRESS,
+		.y_stride		= DC_OVERLAY_STRIDE,
+		.u_stride		= DC_OVERLAY_U_STRIDE,
+		.v_stride		= DC_OVERLAY_V_STRIDE,
+		.size			= DC_OVERLAY_SIZE,
+		.top_left		= DC_OVERLAY_TOP_LEFT,
+		.bottom_right	= DC_OVERLAY_BOTTOM_RIGHT,
+		.scale_factor_x	= DC_OVERLAY_SCALE_FACTOR_X,
+		.scale_factor_y	= DC_OVERLAY_SCALE_FACTOR_Y,
+		.h_filter_coef_index = DC_OVERLAY_H_FILTER_COEF_INDEX,
+		.h_filter_coef_data  = DC_OVERLAY_H_FILTER_COEF_DATA,
+		.v_filter_coef_index = DC_OVERLAY_V_FILTER_COEF_INDEX,
+		.v_filter_coef_data  = DC_OVERLAY_V_FILTER_COEF_DATA,
+		.init_offset		 = DC_OVERLAY_INIT_OFFSET,
+		.color_key			 = DC_OVERLAY_COLOR_KEY,
+		.color_key_high			= DC_OVERLAY_COLOR_KEY_HIGH,
+		.clear_value		 = DC_OVERLAY_CLEAR_VALUE,
+		.color_table_index	 = DC_OVERLAY_COLOR_TABLE_INDEX,
+		.color_table_data	 = DC_OVERLAY_COLOR_TABLE_DATA,
+		.scale_config		 = DC_OVERLAY_SCALE_CONFIG,
+		.water_mark				= DC_OVERLAY_WATER_MARK,
+		.degamma_index		 = DC_OVERLAY_DEGAMMA_INDEX,
+		.degamma_data		 = DC_OVERLAY_DEGAMMA_DATA,
+		.degamma_ex_data	 = DC_OVERLAY_DEGAMMA_EX_DATA,
+		.src_global_color	 = DC_OVERLAY_SRC_GLOBAL_COLOR,
+		.dst_global_color	 = DC_OVERLAY_DST_GLOBAL_COLOR,
+		.blend_config		 = DC_OVERLAY_BLEND_CONFIG,
+		.roi_origin				= DC_OVERLAY_ROI_ORIGIN,
+		.roi_size				= DC_OVERLAY_ROI_SIZE,
+		.yuv_to_rgb_coef0		 = DC_OVERLAY_YUVTORGB_COEF0,
+		.yuv_to_rgb_coef1		 = DC_OVERLAY_YUVTORGB_COEF1,
+		.yuv_to_rgb_coef2		 = DC_OVERLAY_YUVTORGB_COEF2,
+		.yuv_to_rgb_coef3		 = DC_OVERLAY_YUVTORGB_COEF3,
+		.yuv_to_rgb_coef4			= DC_OVERLAY_YUVTORGB_COEF4,
+		.yuv_to_rgb_coefd0			= DC_OVERLAY_YUVTORGB_COEFD0,
+		.yuv_to_rgb_coefd1			= DC_OVERLAY_YUVTORGB_COEFD1,
+		.yuv_to_rgb_coefd2			= DC_OVERLAY_YUVTORGB_COEFD2,
+		.y_clamp_bound		 = DC_OVERLAY_Y_CLAMP_BOUND,
+		.uv_clamp_bound		 = DC_OVERLAY_UV_CLAMP_BOUND,
+		.rgb_to_rgb_coef0		 = DC_OVERLAY_RGBTORGB_COEF0,
+		.rgb_to_rgb_coef1		 = DC_OVERLAY_RGBTORGB_COEF1,
+		.rgb_to_rgb_coef2		 = DC_OVERLAY_RGBTORGB_COEF2,
+		.rgb_to_rgb_coef3		 = DC_OVERLAY_RGBTORGB_COEF3,
+		.rgb_to_rgb_coef4		 = DC_OVERLAY_RGBTORGB_COEF4,
+	},
+};
+
+static inline u32 hi_read(struct dc_hw *hw, u32 reg)
+{
+	return readl(hw->hi_base + reg);
+}
+
+static inline void hi_write(struct dc_hw *hw, u32 reg, u32 value)
+{
+	writel(value, hw->hi_base + reg);
+}
+
+static inline void dc_write(struct dc_hw *hw, u32 reg, u32 value)
+{
+	writel(value, hw->reg_base + reg - DC_REG_BASE);
+}
+
+static inline u32 dc_read(struct dc_hw *hw, u32 reg)
+{
+	return readl(hw->reg_base + reg - DC_REG_BASE);
+}
+
+static inline void dc_write_mask(struct dc_hw *hw, u32 reg,
+				 u32 val, u32 mask)
+{
+	dc_write(hw, reg, (dc_read(hw, reg) & ~mask) | (val & mask));
+}
+
+static inline void dc_set_bit(struct dc_hw *hw, u32 reg, u32 mask)
+{
+	dc_write(hw, reg, dc_read(hw, reg) | mask);
+}
+
+static inline void dc_clear_bit(struct dc_hw *hw, u32 reg, u32 mask)
+{
+	dc_write(hw, reg, dc_read(hw, reg) & ~mask);
+}
+
+static void dc_load_plane_default_filter(struct dc_hw *hw,
+				   const struct dc_hw_plane_reg *reg, u32 offset)
+{
+	u8 i;
+
+	dc_write(hw, reg->scale_config + offset, 0x33);
+	dc_write(hw, reg->init_offset + offset, 0x80008000);
+	dc_write(hw, reg->h_filter_coef_index + offset, 0x00);
+	for (i = 0; i < H_COEF_SIZE; i++)
+		dc_write(hw, reg->h_filter_coef_data + offset, horkernel[i]);
+
+	dc_write(hw, reg->v_filter_coef_index + offset, 0x00);
+	for (i = 0; i < V_COEF_SIZE; i++)
+		dc_write(hw, reg->v_filter_coef_data + offset, verkernel[i]);
+}
+
+static void dc_load_csc_common(struct dc_hw *hw, const u32 *coef_reg,
+				 u32 *regval, u32 offset, u16 len)
+{
+	unsigned int i;
+
+	for (i = 0; i < len; i++)
+		dc_write(hw, coef_reg[i] + offset, regval[i]);
+}
+
+/**
+ *dc_load_plane_rgb_csc- Load RGB to RGB conversion coefficient
+ *
+ *This function loads the RGB to RGB conversion coefficients into hardware registers.
+ *
+ *@hw: Hardware Context
+ *@reg: register address structure
+ *@offset: offset
+ *@table: contains an array of conversion coefficients
+ */
+static void dc_load_plane_rgb_csc(struct dc_hw *hw, const struct dc_hw_plane_reg *reg,
+				     u32 offset, const u16 *table)
+{
+	u32 coef_reg[] = {
+		reg->rgb_to_rgb_coef0, reg->rgb_to_rgb_coef1,
+		reg->rgb_to_rgb_coef2, reg->rgb_to_rgb_coef3,
+		reg->rgb_to_rgb_coef4,
+	};
+	u32 regval[ARRAY_SIZE(coef_reg)] = {
+		table[0] | (table[1] << 16),
+		table[2] | (table[3] << 16),
+		table[4] | (table[5] << 16),
+		table[6] | (table[7] << 16),
+		table[8],
+	};
+
+	dc_load_csc_common(hw, coef_reg, regval, offset, ARRAY_SIZE(coef_reg));
+}
+
+/**
+ * dc_load_plane_yuv_to_rgb_csc - Load YUV to RGB conversion coefficients into hardware registers
+ * @hw: Pointer to the hardware structure
+ * @reg: Pointer to the hardware plane register structure
+ * @offset: Offset value for the coefficients
+ * @table: Pointer to the table containing the coefficients
+ *
+ * This function loads the YUV to RGB conversion coefficients and clamping bounds
+ * from the provided table into the hardware registers. The coefficients are used
+ * for color space conversion during video processing.
+ */
+static void dc_load_plane_yuv_to_rgb_csc(struct dc_hw *hw, const struct dc_hw_plane_reg *reg,
+					    u32 offset, const s32 *table)
+{
+	u32 coef_reg[] = {
+		reg->yuv_to_rgb_coef0, reg->yuv_to_rgb_coef1,
+		reg->yuv_to_rgb_coef2, reg->yuv_to_rgb_coef3,
+		reg->yuv_to_rgb_coef4, reg->yuv_to_rgb_coefd0,
+		reg->yuv_to_rgb_coefd1, reg->yuv_to_rgb_coefd2,
+		reg->y_clamp_bound, reg->uv_clamp_bound,
+	};
+
+	u32 regval[ARRAY_SIZE(coef_reg)] = {
+		(0xFFFF & table[0]) | (table[1] << 16),//Lower 16 of tab[0] and upper 16 of tab[1]
+		(0xFFFF & table[2]) | (table[3] << 16),//Lower 16 of tab[2] and upper 16 of tab[3]
+		(0xFFFF & table[4]) | (table[5] << 16),//Lower 16 of tab[4] and upper 16 of tab[5]
+		(0xFFFF & table[6]) | (table[7] << 16),//Lower 16 of tab[6] and upper 16 of tab[7]
+		table[8],			       //Direct value from tab[8]
+		table[9],			       //Direct value from tab[9]
+		table[10],			       //Direct value from tab[10]
+		table[11],			       //Direct value from tab[11]
+		table[12] | (table[13] << 16),         //Lower 16 of tab[12] and upper 16 of tab[13]
+		table[14] | (table[15] << 16),	       //Lower 16 of tab[14] and upper 16 of tab[15]
+	};
+
+	// Load the coefficients into the hardware registers
+	dc_load_csc_common(hw, coef_reg, regval, offset, ARRAY_SIZE(coef_reg));
+}
+
+/**
+ * dc_load_crtc_rgb_to_yuv_csc - Crtc load RGB to YUV csc into hardware registers
+ * @hw: Pointer to the hardware structure
+ * @offset: Offset value for the coefficients
+ * @table: Pointer to the table containing the coefficients
+ *
+ * This function loads the RGB to YUV conversion coefficients from the provided table
+ * into the hardware registers. The coefficients are used for crtc color space
+ * conversion during video processing.
+ */
+static void dc_load_crtc_rgb_to_yuv_csc(struct dc_hw *hw, u32 offset, s16 *table)
+{
+	u32 coef_reg[] = {
+		DC_DISPLAY_RGBTOYUV_COEF0, DC_DISPLAY_RGBTOYUV_COEF1,
+		DC_DISPLAY_RGBTOYUV_COEF2, DC_DISPLAY_RGBTOYUV_COEF3,
+		DC_DISPLAY_RGBTOYUV_COEF4, DC_DISPLAY_RGBTOYUV_COEFD0,
+		DC_DISPLAY_RGBTOYUV_COEFD1, DC_DISPLAY_RGBTOYUV_COEFD2,
+	};
+
+	u32 regval[ARRAY_SIZE(coef_reg)] = {
+		table[0] | (table[1] << 16),// Lower 16 of table[0] and upper 16 of table[1]
+		table[2] | (table[3] << 16),// Lower 16 of table[2] and upper 16 of table[3]
+		table[4] | (table[5] << 16),// Lower 16 of table[4] and upper 16 of table[5]
+		table[6] | (table[7] << 16),// Lower 16 of table[6] and upper 16 of table[7]
+		table[8],		    // Direct value from table[8]
+		table[9],		    // Direct value from table[9]
+		table[10],		    // Direct value from table[10]
+		table[11],		    // Direct value from table[11]
+	};
+
+	// Load the coefficients into the hardware registers
+	dc_load_csc_common(hw, coef_reg, regval, offset, ARRAY_SIZE(coef_reg));
+}
+
+static int dc_update_vs_format(u32 drm_format)
+{
+	switch (drm_format) {
+	case DRM_FORMAT_XRGB4444:
+	case DRM_FORMAT_RGBX4444:
+	case DRM_FORMAT_XBGR4444:
+	case DRM_FORMAT_BGRX4444:
+		return FORMAT_X4R4G4B4;
+
+	case DRM_FORMAT_ARGB4444:
+	case DRM_FORMAT_RGBA4444:
+	case DRM_FORMAT_ABGR4444:
+	case DRM_FORMAT_BGRA4444:
+		return FORMAT_A4R4G4B4;
+
+	case DRM_FORMAT_XRGB1555:
+	case DRM_FORMAT_RGBX5551:
+	case DRM_FORMAT_XBGR1555:
+	case DRM_FORMAT_BGRX5551:
+		return FORMAT_X1R5G5B5;
+
+	case DRM_FORMAT_ARGB1555:
+	case DRM_FORMAT_RGBA5551:
+	case DRM_FORMAT_ABGR1555:
+	case DRM_FORMAT_BGRA5551:
+		return FORMAT_A1R5G5B5;
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_BGR565:
+		return FORMAT_R5G6B5;
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_RGBX8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_BGRX8888:
+		return FORMAT_X8R8G8B8;
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_RGBA8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_BGRA8888:
+		return FORMAT_A8R8G8B8;
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
+		return FORMAT_YUY2;
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_VYUY:
+		return FORMAT_UYVY;
+	case DRM_FORMAT_YUV420:
+	case DRM_FORMAT_YVU420:
+		return FORMAT_YV12;
+	case DRM_FORMAT_NV21:
+		return FORMAT_NV12;
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV61:
+		return FORMAT_NV16;
+	case DRM_FORMAT_P010:
+		return FORMAT_P010;
+	case DRM_FORMAT_ARGB2101010:
+	case DRM_FORMAT_RGBA1010102:
+	case DRM_FORMAT_ABGR2101010:
+	case DRM_FORMAT_BGRA1010102:
+		return FORMAT_A2R10G10B10;
+	case DRM_FORMAT_NV12:
+		return FORMAT_NV12;
+	case DRM_FORMAT_YUV444:
+		return FORMAT_YUV444;
+	default:
+		return FORMAT_A8R8G8B8;
+	}
+}
+
+int dc_hw_init(struct vs_dc *dc)
+{
+	u8 i, id, panel_num, layer_num;
+	struct dc_hw *hw = &dc->hw;
+	u32 offset;
+
+	layer_num = hw->info->layer_num;
+	for (i = 0; i < layer_num; i++) {
+		id = dc->planes[i].id;
+		if (id == PRIMARY_PLANE_0 || id == PRIMARY_PLANE_1)
+			hw->reg[i] = dc_plane_reg[0];
+		else
+			hw->reg[i] = dc_plane_reg[1];
+
+		dc_load_plane_default_filter(hw, &hw->reg[i], dc->planes[i].offset);
+		dc_load_plane_rgb_csc(hw, &hw->reg[i], dc->planes[i].offset, RGB2RGB);
+	}
+
+	panel_num = hw->info->panel_num;
+	for (i = 0; i < panel_num; i++) {
+		offset = i << 2;
+
+		dc_load_crtc_rgb_to_yuv_csc(hw, offset, RGB2YUV);
+		dc_write(hw, DC_DISPLAY_PANEL_CONFIG + offset, PANEL_DE_EN |
+			 PANEL_DATA_EN | PANEL_CLOCK_EN);
+
+		offset = i ? DC_CURSOR_OFFSET : 0;
+		dc_write(hw, DC_CURSOR_BACKGROUND + offset, 0x00FFFFFF);
+		dc_write(hw, DC_CURSOR_FOREGROUND + offset, 0x00AAAAAA);
+	}
+
+	return 0;
+}
+
+void dc_hw_disable_plane(struct vs_dc *dc, u8 id)
+{
+	struct dc_hw *hw = &dc->hw;
+
+	if (id == PRIMARY_PLANE_0 || id == PRIMARY_PLANE_1)
+		dc_write_mask(hw, DC_FRAMEBUFFER_CONFIG_EX + dc->planes[id].offset,
+			      PRIMARY_EN(false), PRIMARY_EN_MASK);
+	else
+		dc_write_mask(hw, DC_OVERLAY_CONFIG + dc->planes[id].offset,
+			      OVERLAY_FB_EN(false), OVERLAY_FB_EN_MASK);
+}
+
+static int dc_get_cursor_size(uint32_t crtc_w)
+{
+	switch (crtc_w) {
+	case 32:
+		return CURSOR_SIZE_32X32;
+
+	case 64:
+		return CURSOR_SIZE_64X64;
+
+	default:
+		return CURSOR_SIZE_32X32;
+	}
+}
+
+void dc_hw_update_cursor(struct dc_hw *hw, u8 id, dma_addr_t dma_addr,
+			 u32 crtc_w, u32 crtc_x, u32 crtc_y,
+			 s32 hotspot_x, s32 hotspot_y)
+{
+	u32 offset, size;
+
+	offset = id ? DC_CURSOR_OFFSET : 0;
+	size = dc_get_cursor_size(crtc_w);
+
+	dc_write(hw, DC_CURSOR_ADDRESS + offset, dma_addr);
+	dc_write(hw, DC_CURSOR_LOCATION + offset, X_LCOTION(crtc_x) | Y_LCOTION(crtc_y));
+	dc_write_mask(hw, DC_CURSOR_CONFIG + offset,
+		      CURSOR_HOT_X(hotspot_x) |
+		      CURSOR_HOT_y(hotspot_y) |
+		      CURSOR_SIZE(size) |
+		      CURSOR_VALID(1) |
+		      CURSOR_TRIG_FETCH(1) |
+		      CURSOR_FORMAT(CURSOR_FORMAT_A8R8G8B8),
+		      CURSOR_HOT_X_MASK |
+		      CURSOR_HOT_y_MASK |
+		      CURSOR_SIZE_MASK |
+		      CURSOR_VALID_MASK |
+		      CURSOR_TRIG_FETCH_MASK |
+		      CURSOR_FORMAT_MASK);
+}
+
+void dc_hw_disable_cursor(struct dc_hw *hw, u8 id)
+{
+	u32 offset = 0;
+
+	offset = id ? DC_CURSOR_OFFSET : 0;
+	dc_clear_bit(hw, DC_CURSOR_CONFIG + offset, CURSOR_FORMAT_MASK);
+	dc_set_bit(hw, DC_CURSOR_CONFIG + offset, CURSOR_VALID(1));
+}
+
+void dc_hw_update_gamma(struct dc_hw *hw, u8 id, u16 index,
+			u16 r, u16 g, u16 b)
+{
+	if (index >= hw->info->gamma_size)
+		return;
+
+	hw->gamma[id].gamma[index][0] = r;
+	hw->gamma[id].gamma[index][1] = g;
+	hw->gamma[id].gamma[index][2] = b;
+}
+
+void dc_hw_enable_gamma(struct dc_hw *hw, u8 id, bool enable)
+{
+	u32 value;
+
+	if (enable) {
+		dc_write(hw, DC_DISPLAY_GAMMA_EX_INDEX + (id << 2), 0x00);
+		for (int i = 0; i < GAMMA_EX_SIZE; i++) {
+			value = hw->gamma[id].gamma[i][2] |
+				(hw->gamma[id].gamma[i][1] << 12);
+			dc_write(hw, DC_DISPLAY_GAMMA_EX_DATA + (id << 2), value);
+			dc_write(hw, DC_DISPLAY_GAMMA_EX_ONE_DATA + (id << 2),
+				 hw->gamma[id].gamma[i][0]);
+		}
+		dc_set_bit(hw, DC_DISPLAY_PANEL_CONFIG + (id << 2), PANEL_GAMMA_EN);
+	} else {
+		dc_clear_bit(hw, DC_DISPLAY_PANEL_CONFIG + (id << 2), PANEL_GAMMA_EN);
+	}
+}
+
+void dc_hw_enable(struct dc_hw *hw, int id, struct drm_display_mode *mode,
+		  u8 encoder_type, u32 output_fmt)
+{
+	u32 dp_cfg, dpi_cfg, offset = id << 2;
+	bool is_yuv = false;
+
+	if (encoder_type != DRM_MODE_ENCODER_DSI) {
+		switch (output_fmt) {
+		case MEDIA_BUS_FMT_RGB565_1X16:
+			dp_cfg = 0;
+			break;
+		case MEDIA_BUS_FMT_RGB666_1X18:
+			dp_cfg = 1;
+			break;
+		case MEDIA_BUS_FMT_RGB888_1X24:
+			dp_cfg = 2;
+			break;
+		case MEDIA_BUS_FMT_RGB101010_1X30:
+			dp_cfg = 3;
+			break;
+		case MEDIA_BUS_FMT_UYVY8_1X16:
+			dp_cfg = 2 << 4;
+			is_yuv = true;
+			break;
+		case MEDIA_BUS_FMT_YUV8_1X24:
+			dp_cfg = 4 << 4;
+			is_yuv = true;
+			break;
+		case MEDIA_BUS_FMT_UYVY10_1X20:
+			dp_cfg = 8 << 4;
+			is_yuv = true;
+			break;
+		case MEDIA_BUS_FMT_YUV10_1X30:
+			dp_cfg = 10 << 4;
+			is_yuv = true;
+			break;
+		case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
+			dp_cfg = 12 << 4;
+			is_yuv = true;
+			break;
+		case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
+			dp_cfg = 13 << 4;
+			is_yuv = true;
+			break;
+		default:
+			dp_cfg = 2;
+			break;
+		}
+		if (is_yuv)
+			dc_set_bit(hw, DC_DISPLAY_PANEL_CONFIG + offset, PANEL_RGB2YUV_EN);
+		else
+			dc_clear_bit(hw, DC_DISPLAY_PANEL_CONFIG + offset, PANEL_RGB2YUV_EN);
+		dc_write(hw, DC_DISPLAY_DP_CONFIG + offset, dp_cfg | DP_SELECT);
+	}
+
+	if (hw->out[id] == OUT_DPI)
+		dc_clear_bit(hw, DC_DISPLAY_DP_CONFIG + offset, DP_SELECT);
+
+	switch (output_fmt) {
+	case MEDIA_BUS_FMT_RGB565_1X16:
+		dpi_cfg = 0;
+		break;
+	case MEDIA_BUS_FMT_RGB666_1X18:
+		dpi_cfg = 3;
+		break;
+	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
+		dpi_cfg = 4;
+		break;
+	case MEDIA_BUS_FMT_RGB888_1X24:
+		dpi_cfg = 5;
+		break;
+	case MEDIA_BUS_FMT_RGB101010_1X30:
+		dpi_cfg = 6;
+		break;
+	default:
+		dpi_cfg = 5;
+		break;
+	}
+	dc_write(hw, DC_DISPLAY_DPI_CONFIG + offset, dpi_cfg);
+
+	if (id == 0)
+		dc_clear_bit(hw, DC_DISPLAY_PANEL_START, PANEL0_EN | TWO_PANEL_EN);
+	else
+		dc_clear_bit(hw, DC_DISPLAY_PANEL_START, PANEL1_EN | TWO_PANEL_EN);
+
+	dc_write(hw, DC_DISPLAY_H + offset,
+		 H_ACTIVE_LEN(mode->hdisplay) |
+		 H_TOTAL_LEN(mode->htotal));
+
+	dc_write(hw, DC_DISPLAY_H_SYNC + offset,
+		 H_SYNC_START_LEN(mode->hsync_start) |
+		 H_SYNC_END_LEN(mode->hsync_end) |
+		 H_POLARITY_LEN(mode->flags & DRM_MODE_FLAG_PHSYNC ? 0 : 1) |
+		 H_PLUS_LEN(1));
+
+	dc_write(hw, DC_DISPLAY_V + offset,
+		 V_ACTIVE_LEN(mode->vdisplay) |
+		 V_TOTAL_LEN(mode->vtotal));
+
+	dc_write(hw, DC_DISPLAY_V_SYNC + offset,
+		 V_SYNC_START_LEN(mode->vsync_start) |
+		 V_SYNC_END_LEN(mode->vsync_end) |
+		 V_POLARITY_LEN(mode->flags & DRM_MODE_FLAG_PVSYNC ? 0 : 1) |
+		 V_PLUS_LEN(1));
+
+	dc_set_bit(hw, DC_DISPLAY_PANEL_CONFIG + offset, PANEL_OUTPUT_EN);
+	dc_clear_bit(hw, DC_DISPLAY_PANEL_START, SYNC_EN);
+	dc_set_bit(hw, DC_DISPLAY_PANEL_START, BIT(id));
+}
+
+void dc_hw_disable(struct dc_hw *hw, int id)
+{
+	u32 offset = id << 2;
+
+	if (hw->out[id] == OUT_DPI)
+		dc_clear_bit(hw, DC_DISPLAY_DP_CONFIG + offset, DP_SELECT);
+	dc_clear_bit(hw, DC_DISPLAY_PANEL_CONFIG + offset, PANEL_OUTPUT_EN);
+	dc_clear_bit(hw, DC_DISPLAY_PANEL_START, BIT(id) | TWO_PANEL_EN);
+}
+
+void dc_hw_enable_interrupt(struct dc_hw *hw)
+{
+	hi_write(hw, AQ_INTR_ENBL, 0xFFFFFFFF);
+}
+
+void dc_hw_disable_interrupt(struct dc_hw *hw)
+{
+	hi_write(hw, AQ_INTR_ENBL, 0);
+}
+
+void dc_hw_get_interrupt(struct dc_hw *hw, u8 *status)
+{
+	u32 intr_status = hi_read(hw, AQ_INTR_ACKNOWLEDGE);
+
+	if (intr_status & BIT(0))
+		*status |= BIT(0); /* panel 0 frame done intr */
+
+	if (intr_status & BIT(1))
+		*status |= BIT(1); /* panel 1 frame done intr */
+}
+
+void dc_hw_enable_shadow_register(struct vs_dc *dc, bool enable)
+{
+	u32 i, offset;
+	struct dc_hw *hw = &dc->hw;
+	u8 id, layer_num = hw->info->layer_num;
+	u8 panel_num = hw->info->panel_num;
+
+	for (i = 0; i < layer_num; i++) {
+		id = dc->planes[i].id;
+		offset = dc->planes[i].offset;
+		if (enable) {
+			if (id == PRIMARY_PLANE_0 || id == PRIMARY_PLANE_1)
+				dc_set_bit(hw, DC_FRAMEBUFFER_CONFIG_EX + offset,
+					   PRIMARY_SHADOW_EN);
+			else
+				dc_set_bit(hw, DC_OVERLAY_CONFIG + offset,
+					   OVERLAY_SHADOW_EN);
+		} else {
+			if (id == PRIMARY_PLANE_0 || id == PRIMARY_PLANE_1)
+				dc_clear_bit(hw, DC_FRAMEBUFFER_CONFIG_EX + offset,
+					     PRIMARY_SHADOW_EN);
+			else
+				dc_clear_bit(hw, DC_OVERLAY_CONFIG + offset,
+					     OVERLAY_SHADOW_EN);
+		}
+	}
+
+	for (i = 0; i < panel_num; i++) {
+		offset = i << 2;
+		if (enable)
+			dc_clear_bit(hw, DC_DISPLAY_PANEL_CONFIG_EX + offset, PANEL_SHADOW_INVALID);
+		else
+			dc_set_bit(hw, DC_DISPLAY_PANEL_CONFIG_EX + offset, PANEL_SHADOW_INVALID);
+	}
+}
+
+void dc_hw_set_out(struct dc_hw *hw, enum dc_hw_out out, u8 id)
+{
+	if (out < OUT_MAX)
+		hw->out[id] = out;
+}
+
+static inline u8 dc_to_vs_yuv_color_space(u32 color_space)
+{
+	switch (color_space) {
+	case DRM_COLOR_YCBCR_BT601:
+		return COLOR_SPACE_601;
+	case DRM_COLOR_YCBCR_BT709:
+		return COLOR_SPACE_709;
+	case DRM_COLOR_YCBCR_BT2020:
+		return COLOR_SPACE_2020;
+	default:
+		return COLOR_SPACE_601;
+	}
+}
+
+static inline u8 dc_update_uv_swizzle(u32 format)
+{
+	switch (format) {
+	case DRM_FORMAT_YVYU:
+	case DRM_FORMAT_VYUY:
+	case DRM_FORMAT_NV21:
+	case DRM_FORMAT_NV61:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static inline u8 dc_update_swizzle(u32 format)
+{
+	switch (format) {
+	case DRM_FORMAT_RGBX4444:
+	case DRM_FORMAT_RGBA4444:
+	case DRM_FORMAT_RGBX5551:
+	case DRM_FORMAT_RGBA5551:
+	case DRM_FORMAT_RGBX8888:
+	case DRM_FORMAT_RGBA8888:
+	case DRM_FORMAT_RGBA1010102:
+		return SWIZZLE_RGBA;
+	case DRM_FORMAT_XBGR4444:
+	case DRM_FORMAT_ABGR4444:
+	case DRM_FORMAT_XBGR1555:
+	case DRM_FORMAT_ABGR1555:
+	case DRM_FORMAT_BGR565:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_ABGR2101010:
+		return SWIZZLE_ABGR;
+	case DRM_FORMAT_BGRX4444:
+	case DRM_FORMAT_BGRA4444:
+	case DRM_FORMAT_BGRX5551:
+	case DRM_FORMAT_BGRA5551:
+	case DRM_FORMAT_BGRX8888:
+	case DRM_FORMAT_BGRA8888:
+	case DRM_FORMAT_BGRA1010102:
+		return SWIZZLE_BGRA;
+	default:
+		return SWIZZLE_ARGB;
+	}
+}
+
+static inline u8 dc_to_vs_rotation(unsigned int rotation)
+{
+	switch (rotation & DRM_MODE_REFLECT_MASK) {
+	case DRM_MODE_REFLECT_X:
+		return FLIP_X;
+	case DRM_MODE_REFLECT_Y:
+		return FLIP_Y;
+	case DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y:
+		return FLIP_XY;
+	default:
+		return ROT_0;
+	}
+
+	switch (rotation & DRM_MODE_ROTATE_MASK) {
+	case DRM_MODE_ROTATE_0:
+		return ROT_0;
+	case DRM_MODE_ROTATE_90:
+		return ROT_90;
+	case DRM_MODE_ROTATE_180:
+		return ROT_180;
+	case DRM_MODE_ROTATE_270:
+		return ROT_270;
+	default:
+		return ROT_0;
+	}
+
+	return ROT_0;
+}
+
+void dc_plane_hw_update_format_colorspace(struct vs_dc *dc, u32 format,
+					  enum drm_color_encoding encoding,
+					  u8 id,
+					  bool is_yuv)
+{
+	u32 offset = dc->planes[id].offset;
+	struct dc_hw *hw = &dc->hw;
+
+	if (is_yuv) {
+		if (id == PRIMARY_PLANE_0 || id == PRIMARY_PLANE_1) {
+			dc_clear_bit(hw, DC_FRAMEBUFFER_CONFIG_EX + offset, PRIMARY_RGB2RGB_EN);
+			dc_set_bit(hw, DC_FRAMEBUFFER_CONFIG_EX + offset, PRIMARY_YUVCLAMP_EN);
+		} else {
+			dc_clear_bit(hw, DC_OVERLAY_CONFIG + offset, OVERLAY_RGB2RGB_EN);
+			dc_set_bit(hw, DC_OVERLAY_CONFIG + offset, OVERLAY_CLAMP_EN);
+		}
+		switch (dc_to_vs_yuv_color_space(encoding)) {
+		case COLOR_SPACE_601:
+			dc_load_plane_yuv_to_rgb_csc(hw, &hw->reg[id], offset, YUV601_2RGB);
+			break;
+		case COLOR_SPACE_709:
+			dc_load_plane_yuv_to_rgb_csc(hw, &hw->reg[id], offset, YUV709_2RGB);
+			break;
+		case COLOR_SPACE_2020:
+			dc_load_plane_yuv_to_rgb_csc(hw, &hw->reg[id], offset, YUV2020_2RGB);
+			break;
+		default:
+			break;
+		}
+	} else {
+		if (id == PRIMARY_PLANE_0 || id == PRIMARY_PLANE_1) {
+			dc_clear_bit(hw, DC_FRAMEBUFFER_CONFIG_EX + offset, PRIMARY_YUVCLAMP_EN);
+			dc_set_bit(hw, DC_FRAMEBUFFER_CONFIG_EX + offset, PRIMARY_RGB2RGB_EN);
+		} else {
+			dc_clear_bit(hw, DC_OVERLAY_CONFIG + offset,
+				     OVERLAY_CLAMP_EN);
+			dc_set_bit(hw, DC_OVERLAY_CONFIG + offset,
+				   OVERLAY_RGB2RGB_EN);
+		}
+	}
+}
+
+void dc_plane_hw_update_address(struct vs_dc *dc, u8 id, u32 format, dma_addr_t *dma_addr,
+				struct drm_framebuffer *drm_fb, struct drm_rect *src)
+{
+	u32 offset = dc->planes[id].offset;
+	struct dc_hw *hw = &dc->hw;
+
+	dc_write(hw, hw->reg[id].y_address + offset, dma_addr[0]);
+	dc_write(hw, hw->reg[id].u_address + offset,
+		 format == DRM_FORMAT_YVU420 ?
+		 dma_addr[2] : dma_addr[1]);
+	dc_write(hw, hw->reg[id].v_address + offset,
+		 format == DRM_FORMAT_YVU420 ?
+		 dma_addr[1] : dma_addr[2]);
+	dc_write(hw, hw->reg[id].y_stride + offset, drm_fb->pitches[0]);
+	dc_write(hw, hw->reg[id].u_stride + offset,
+		 format == DRM_FORMAT_YVU420 ?
+		 drm_fb->pitches[2] : drm_fb->pitches[1]);
+	dc_write(hw, hw->reg[id].v_stride + offset,
+		 format == DRM_FORMAT_YVU420 ?
+		 drm_fb->pitches[1] : drm_fb->pitches[2]);
+	dc_write(hw, hw->reg[id].size + offset,
+		 FB_SIZE(drm_rect_width(src) >> 16, drm_rect_height(src) >> 16));
+}
+
+void dc_plane_hw_update_format(struct vs_dc *dc, u32 format, enum drm_color_encoding encoding,
+			       unsigned int rotation, bool visible, unsigned int zpos,
+			       u8 id, u8 display_id)
+{
+	u32 offset = dc->planes[id].offset;
+	struct dc_hw *hw = &dc->hw;
+
+	if (id == PRIMARY_PLANE_0 || id == PRIMARY_PLANE_1) {
+		dc_write_mask(hw, DC_FRAMEBUFFER_CONFIG + offset,
+			      PRIMARY_FORMAT(dc_update_vs_format(format)) |
+			      PRIMARY_UV_SWIZ(dc_update_uv_swizzle(format)) |
+			      PRIMARY_SWIZ(dc_update_swizzle(format)) |
+			      PRIMARY_TILE(DRM_FORMAT_MOD_LINEAR) |
+			      PRIMARY_YUV_COLOR(dc_to_vs_yuv_color_space(encoding)) |
+			      PRIMARY_ROTATION(dc_to_vs_rotation(rotation)),
+			      PRIMARY_FORMAT_MASK |
+			      PRIMARY_UV_SWIZ_MASK |
+			      PRIMARY_SWIZ_MASK |
+			      PRIMARY_TILE_MASK |
+			      PRIMARY_YUV_COLOR_MASK |
+			      PRIMARY_ROTATION_MASK |
+			      PRIMARY_CLEAR_EN_MASK);
+		dc_write_mask(hw, DC_FRAMEBUFFER_CONFIG_EX + offset,
+			      PRIMARY_DECODER_EN(false) |
+			      PRIMARY_EN(visible) |
+			      PRIMARY_ZPOS(zpos) |
+			      PRIMARY_CHANNEL(display_id),
+			      PRIMARY_DECODER_EN_EN_MASK |
+			      PRIMARY_EN_MASK |
+			      PRIMARY_ZPOS_MASK |
+			      PRIMARY_CHANNEL_MASK);
+	} else {
+		dc_write_mask(hw, DC_OVERLAY_CONFIG + offset,
+			      OVERLAY_FB_EN(visible) |
+			      OVERLAY_FORMAT(dc_update_vs_format(format)) |
+			      OVERLAY_UV_SWIZ(dc_update_uv_swizzle(format)) |
+			      OVERLAY_SWIZ(dc_update_swizzle(format)) |
+			      OVERLAY_TILE(DRM_FORMAT_MOD_LINEAR) |
+			      OVERLAY_YUV_COLOR(dc_to_vs_yuv_color_space(encoding)) |
+			      OVERLAY_ROTATION(dc_to_vs_rotation(rotation)),
+			      OVERLAY_DEC_EN_MASK |
+			      OVERLAY_CLEAR_EN_MASK |
+			      OVERLAY_FB_EN_MASK |
+			      OVERLAY_FORMAT_MASK |
+			      OVERLAY_UV_SWIZ_MASK |
+			      OVERLAY_SWIZ_MASK |
+			      OVERLAY_TILE_MASK |
+			      OVERLAY_YUV_COLOR_MASK |
+			      OVERLAY_ROTATION_MASK);
+
+	 dc_write_mask(hw, DC_OVERLAY_CONFIG_EX + offset,
+		       OVERLAY_LAYER_SEL(zpos) | OVERLAY_PANEL_SEL(display_id),
+		       OVERLAY_LAYER_SEL_MASK | OVERLAY_PANEL_SEL_MASK);
+	}
+}
+
+/**
+ * calc_factor - Calculate the scaling factor for converting
+ *				 source dimensions to destination dimensions.
+ *
+ * @src: The source dimension (width or height).
+ * @dest: The destination dimension (width or height).
+ *
+ * This function computes a scaling factor for converting
+ * a given source size to a destination size. The factor is
+ * represented as a 16.16 fixed-point number. If either the
+ * source or destination dimension is less than or equal to 1,
+ * it will return a factor of 1 << 16 (which corresponds to
+ * a scaling factor of 1.0). The function ensures that scaling
+ * logic is only applied when both dimensions are greater than 1,
+ * avoiding potential division by zero or erroneous scaling.
+ *
+ * Returns: The computed scaling factor as a 32-bit unsigned integer.
+ */
+static u32 calc_factor(u32 src, u32 dest)
+{
+	u32 factor = 1 << 16;
+
+	if (src > 1 && dest > 1)
+		factor = ((src - 1) << 16) / (dest - 1);
+
+	return factor;
+}
+
+void dc_plane_hw_update_scale(struct vs_dc *dc, struct drm_rect *src, struct drm_rect *dst,
+			      u8 id, u8 display_id, unsigned int rotation)
+{
+	u32 offset = dc->planes[id].offset;
+	struct dc_hw *hw = &dc->hw;
+
+	int dst_w = drm_rect_width(dst);
+	int dst_h = drm_rect_height(dst);
+	int src_w, src_h, temp;
+	u32 scale_factor_x;
+	u32 scale_factor_y;
+	bool enable_scale = false;
+
+	src_w = drm_rect_width(src) >> 16;
+	src_h = drm_rect_height(src) >> 16;
+
+	if (drm_rotation_90_or_270(rotation)) {
+		temp = src_w;
+		src_w = src_h;
+		src_h = temp;
+	}
+
+	if (src_w != dst_w) {
+		scale_factor_x = calc_factor(src_w, dst_w);
+		enable_scale = true;
+	} else {
+		scale_factor_x = 1 << 16;
+	}
+	if (src_h != dst_h) {
+		scale_factor_y = calc_factor(src_h, dst_h);
+		enable_scale = true;
+	} else {
+		scale_factor_y = 1 << 16;
+	}
+	if (enable_scale) {
+		dc_write(hw, hw->reg[id].scale_factor_x + offset, scale_factor_x);
+		dc_write(hw, hw->reg[id].scale_factor_y + offset, scale_factor_y);
+		if (id == PRIMARY_PLANE_0 || id == PRIMARY_PLANE_1)
+			dc_set_bit(hw, DC_FRAMEBUFFER_CONFIG + offset, PRIMARY_SCALE_EN);
+		else
+			dc_set_bit(hw, DC_OVERLAY_SCALE_CONFIG + offset, OVERLAY_SCALE_EN);
+	} else {
+		if (id == PRIMARY_PLANE_0 || id == PRIMARY_PLANE_1)
+			dc_clear_bit(hw, DC_FRAMEBUFFER_CONFIG + offset, PRIMARY_SCALE_EN);
+		else
+			dc_clear_bit(hw, DC_OVERLAY_SCALE_CONFIG + offset, OVERLAY_SCALE_EN);
+	}
+
+	dc_write(hw, hw->reg[id].top_left + offset, X_POS(dst->x1) | Y_POS(dst->y1));
+	dc_write(hw, hw->reg[id].bottom_right + offset, X_POS(dst->x2) | Y_POS(dst->y2));
+}
+
+void dc_plane_hw_update_blend(struct vs_dc *dc, u16 alpha,
+			      u16 pixel_blend_mode, u8 id, u8 display_id)
+{
+	u32 offset = dc->planes[id].offset;
+	struct dc_hw *hw = &dc->hw;
+
+	dc_write(hw, hw->reg[id].src_global_color + offset, PRIMARY_ALPHA_LEN(alpha >> 8));
+	dc_write(hw, hw->reg[id].dst_global_color + offset, PRIMARY_ALPHA_LEN(alpha >> 8));
+	switch (pixel_blend_mode) {
+	case DRM_MODE_BLEND_PREMULTI:
+		dc_write(hw, hw->reg[id].blend_config + offset, BLEND_PREMULTI);
+		break;
+	case DRM_MODE_BLEND_COVERAGE:
+		dc_write(hw, hw->reg[id].blend_config + offset, BLEND_COVERAGE);
+		break;
+	case DRM_MODE_BLEND_PIXEL_NONE:
+		dc_write(hw, hw->reg[id].blend_config + offset, BLEND_PIXEL_NONE);
+		break;
+	default:
+		break;
+	}
+}
diff --git a/drivers/gpu/drm/verisilicon/vs_dc_hw.h b/drivers/gpu/drm/verisilicon/vs_dc_hw.h
new file mode 100644
index 000000000000..faf5b4c325f8
--- /dev/null
+++ b/drivers/gpu/drm/verisilicon/vs_dc_hw.h
@@ -0,0 +1,492 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) VeriSilicon Holdings Co., Ltd.
+ */
+
+#ifndef __VS_DC_HW_H__
+#define __VS_DC_HW_H__
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <drm/drm_atomic.h>
+
+#include "vs_type.h"
+
+#define UPDATE(x, h, l)				FIELD_PREP(GENMASK(h, l), x)
+
+#define AQ_INTR_ACKNOWLEDGE			0x0010
+#define AQ_INTR_ENBL				0x0014
+#define DC_HW_REVISION				0x0024
+#define DC_HW_CHIP_CID				0x0030
+
+#define DC_REG_BASE				0x0800
+#define DC_REG_RANGE				0x2000
+#define DC_SEC_REG_OFFSET			0x100000
+
+#define DC_FRAMEBUFFER_CONFIG			0x1518
+# define PRIMARY_FORMAT(x)			((x) << 26)
+# define PRIMARY_FORMAT_MASK			GENMASK(31, 26)
+# define PRIMARY_UV_SWIZ(x)			((x) << 25)
+# define PRIMARY_UV_SWIZ_MASK			GENMASK(25, 25)
+# define PRIMARY_SWIZ(x)			((x) << 23)
+# define PRIMARY_SWIZ_MASK			GENMASK(24, 23)
+# define PRIMARY_SCALE_EN			BIT(12)
+# define PRIMARY_TILE(x)			((x) << 17)
+# define PRIMARY_TILE_MASK			GENMASK(21, 17)
+# define PRIMARY_YUV_COLOR(x)			((x) << 14)
+# define PRIMARY_YUV_COLOR_MASK			GENMASK(16, 14)
+# define PRIMARY_ROTATION(x)			((x) << 11)
+# define PRIMARY_ROTATION_MASK			GENMASK(13, 11)
+# define PRIMARY_CLEAR_EN(x)			((x) << 8)
+# define PRIMARY_CLEAR_EN_MASK			GENMASK(8, 8)
+
+#define DC_FRAMEBUFFER_CONFIG_EX		0x1CC0
+# define PRIMARY_CHANNEL(x)			((x) << 19)
+# define PRIMARY_CHANNEL_MASK			GENMASK(19, 19)
+# define PRIMARY_ZPOS(x)			((x) << 16)
+# define PRIMARY_ZPOS_MASK			GENMASK(18, 16)
+# define PRIMARY_EN(x)				((x) << 13)
+# define PRIMARY_EN_MASK			GENMASK(13, 13)
+# define PRIMARY_SHADOW_EN			BIT(12)
+# define PRIMARY_YUVCLAMP_EN			BIT(8)
+# define PRIMARY_RGB2RGB_EN			BIT(6)
+# define PRIMARY_SYNC1_EN			BIT(4)
+# define PRIMARY_SYNC0_EN			BIT(3)
+# define PRIMARY_DECODER_EN(x)			((x) << 1)
+# define PRIMARY_DECODER_EN_EN_MASK		GENMASK(1, 1)
+
+#define DC_FRAMEBUFFER_SCALE_CONFIG		0x1520
+#define DC_FRAMEBUFFER_TOP_LEFT			0x24D8
+#define X_POS(x)				(x)
+#define Y_POS(x)				((x) << 15)
+
+#define DC_FRAMEBUFFER_BOTTOM_RIGHT		0x24E0
+#define DC_FRAMEBUFFER_ADDRESS			0x1400
+#define DC_FRAMEBUFFER_U_ADDRESS		0x1530
+#define DC_FRAMEBUFFER_V_ADDRESS		0x1538
+#define DC_FRAMEBUFFER_STRIDE			0x1408
+#define DC_FRAMEBUFFER_U_STRIDE			0x1800
+#define DC_FRAMEBUFFER_V_STRIDE			0x1808
+#define DC_FRAMEBUFFER_SIZE			0x1810
+#define FB_SIZE(w, h)				((w) | ((h) << 15))
+
+#define DC_FRAMEBUFFER_SCALE_FACTOR_X		0x1828
+#define DC_FRAMEBUFFER_SCALE_FACTOR_Y		0x1830
+#define DC_FRAMEBUFFER_H_FILTER_COEF_INDEX	0x1838
+#define DC_FRAMEBUFFER_H_FILTER_COEF_DATA	0x1A00
+#define DC_FRAMEBUFFER_V_FILTER_COEF_INDEX	0x1A08
+#define DC_FRAMEBUFFER_V_FILTER_COEF_DATA	0x1A10
+#define DC_FRAMEBUFFER_INIT_OFFSET		0x1A20
+#define DC_FRAMEBUFFER_COLOR_KEY		0x1508
+#define DC_FRAMEBUFFER_COLOR_KEY_HIGH		0x1510
+#define DC_FRAMEBUFFER_CLEAR_VALUE		0x1A18
+#define DC_FRAMEBUFFER_COLOR_TABLE_INDEX	0x1818
+#define DC_FRAMEBUFFER_COLOR_TABLE_DATA		0x1820
+#define DC_FRAMEBUFFER_BG_COLOR			0x1528
+#define DC_FRAMEBUFFER_ROI_ORIGIN		0x1CB0
+#define DC_FRAMEBUFFER_ROI_SIZE			0x1CB8
+#define DC_FRAMEBUFFER_WATER_MARK		0x1CE8
+#define DC_FRAMEBUFFER_DEGAMMA_INDEX		0x1D88
+#define DC_FRAMEBUFFER_DEGAMMA_DATA		0x1D90
+#define DC_FRAMEBUFFER_DEGAMMA_EX_DATA		0x1D98
+#define DC_FRAMEBUFFER_YUVTORGB_COEF0		0x1DA0
+#define DC_FRAMEBUFFER_YUVTORGB_COEF1		0x1DA8
+#define DC_FRAMEBUFFER_YUVTORGB_COEF2		0x1DB0
+#define DC_FRAMEBUFFER_YUVTORGB_COEF3		0x1DB8
+#define DC_FRAMEBUFFER_YUVTORGB_COEF4		0x1E00
+#define DC_FRAMEBUFFER_YUVTORGB_COEFD0		0x1E08
+#define DC_FRAMEBUFFER_YUVTORGB_COEFD1		0x1E10
+#define DC_FRAMEBUFFER_YUVTORGB_COEFD2		0x1E18
+#define DC_FRAMEBUFFER_Y_CLAMP_BOUND		0x1E88
+#define DC_FRAMEBUFFER_UV_CLAMP_BOUND		0x1E90
+#define DC_FRAMEBUFFER_RGBTORGB_COEF0		0x1E20
+#define DC_FRAMEBUFFER_RGBTORGB_COEF1		0x1E28
+#define DC_FRAMEBUFFER_RGBTORGB_COEF2		0x1E30
+#define DC_FRAMEBUFFER_RGBTORGB_COEF3		0x1E38
+#define DC_FRAMEBUFFER_RGBTORGB_COEF4		0x1E40
+#define DC_FRAMEBUFFER_BLEND_CONFIG		0x2510
+# define BLEND_PREMULTI				0x3450
+# define BLEND_COVERAGE				0x3950
+# define BLEND_PIXEL_NONE			0x3548
+
+#define DC_FRAMEBUFFER_SRC_GLOBAL_COLOR		0x2500
+# define PRIMARY_ALPHA_LEN(x)			((x) << 24)
+
+#define DC_FRAMEBUFFER_DST_GLOBAL_COLOR		0x2508
+
+#define DC_OVERLAY_CONFIG			0x1540
+# define OVERLAY_SHADOW_EN			BIT(31)
+# define OVERLAY_CLAMP_EN			BIT(30)
+# define OVERLAY_RGB2RGB_EN			BIT(29)
+# define OVERLAY_DEC_EN(x)			((x) << 27)
+# define OVERLAY_DEC_EN_MASK			GENMASK(27, 27)
+# define OVERLAY_CLEAR_EN(x)			((x) << 25)
+# define OVERLAY_CLEAR_EN_MASK			GENMASK(25, 25)
+# define OVERLAY_FB_EN(x)			((x) << 24)
+# define OVERLAY_FB_EN_MASK			GENMASK(24, 24)
+# define OVERLAY_FORMAT(x)			((x) << 16)
+# define OVERLAY_FORMAT_MASK			GENMASK(21, 16)
+# define OVERLAY_UV_SWIZ(x)			((x) << 15)
+# define OVERLAY_UV_SWIZ_MASK			GENMASK(15, 15)
+# define OVERLAY_SWIZ(x)			((x) << 13)
+# define OVERLAY_SWIZ_MASK			GENMASK(14, 13)
+# define OVERLAY_TILE(x)			((x) << 8)
+# define OVERLAY_TILE_MASK			GENMASK(12, 8)
+# define OVERLAY_YUV_COLOR(x)			((x) << 5)
+# define OVERLAY_YUV_COLOR_MASK			GENMASK(7, 5)
+# define OVERLAY_ROTATION(x)			((x) << 2)
+# define OVERLAY_ROTATION_MASK			GENMASK(4, 2)
+
+#define DC_OVERLAY_CONFIG_EX			0x2540
+# define OVERLAY_LAYER_SEL(x)			((x) << 0)
+# define OVERLAY_LAYER_SEL_MASK			GENMASK(2, 0)
+# define OVERLAY_PANEL_SEL(x)			((x) << 3)
+# define OVERLAY_PANEL_SEL_MASK			GENMASK(3, 3)
+
+#define DC_OVERLAY_SCALE_CONFIG			0x1C00
+# define OVERLAY_SCALE_EN			BIT(8)
+
+#define DC_OVERLAY_BLEND_CONFIG			0x1580
+#define DC_OVERLAY_TOP_LEFT			0x1640
+#define DC_OVERLAY_BOTTOM_RIGHT			0x1680
+#define DC_OVERLAY_ADDRESS			0x15C0
+#define DC_OVERLAY_U_ADDRESS			0x1840
+#define DC_OVERLAY_V_ADDRESS			0x1880
+#define DC_OVERLAY_STRIDE			0x1600
+#define DC_OVERLAY_U_STRIDE			0x18C0
+#define DC_OVERLAY_V_STRIDE			0x1900
+#define DC_OVERLAY_SIZE				0x17C0
+#define DC_OVERLAY_SCALE_FACTOR_X		0x1A40
+#define DC_OVERLAY_SCALE_FACTOR_Y		0x1A80
+#define DC_OVERLAY_H_FILTER_COEF_INDEX		0x1AC0
+#define DC_OVERLAY_H_FILTER_COEF_DATA		0x1B00
+#define DC_OVERLAY_V_FILTER_COEF_INDEX		0x1B40
+#define DC_OVERLAY_V_FILTER_COEF_DATA		0x1B80
+#define DC_OVERLAY_INIT_OFFSET			0x1BC0
+#define DC_OVERLAY_COLOR_KEY			0x1740
+#define DC_OVERLAY_COLOR_KEY_HIGH		0x1780
+#define DC_OVERLAY_CLEAR_VALUE			0x1940
+#define DC_OVERLAY_COLOR_TABLE_INDEX		0x1980
+#define DC_OVERLAY_COLOR_TABLE_DATA		0x19C0
+#define DC_OVERLAY_SRC_GLOBAL_COLOR		0x16C0
+# define OVERLAY_ALPHA_LEN(x)			((x) << 24)
+
+#define DC_OVERLAY_DST_GLOBAL_COLOR		0x1700
+#define DC_OVERLAY_ROI_ORIGIN			0x1D00
+#define DC_OVERLAY_ROI_SIZE			0x1D40
+#define DC_OVERLAY_WATER_MARK			0x1DC0
+#define DC_OVERLAY_DEGAMMA_INDEX		0x2200
+#define DC_OVERLAY_DEGAMMA_DATA			0x2240
+#define DC_OVERLAY_DEGAMMA_EX_DATA		0x2280
+#define DC_OVERLAY_YUVTORGB_COEF0		0x1EC0
+#define DC_OVERLAY_YUVTORGB_COEF1		0x1F00
+#define DC_OVERLAY_YUVTORGB_COEF2		0x1F40
+#define DC_OVERLAY_YUVTORGB_COEF3		0x1F80
+#define DC_OVERLAY_YUVTORGB_COEF4		0x1FC0
+#define DC_OVERLAY_YUVTORGB_COEFD0		0x2000
+#define DC_OVERLAY_YUVTORGB_COEFD1		0x2040
+#define DC_OVERLAY_YUVTORGB_COEFD2		0x2080
+#define DC_OVERLAY_Y_CLAMP_BOUND		0x22C0
+#define DC_OVERLAY_UV_CLAMP_BOUND		0x2300
+#define DC_OVERLAY_RGBTORGB_COEF0		0x20C0
+#define DC_OVERLAY_RGBTORGB_COEF1		0x2100
+#define DC_OVERLAY_RGBTORGB_COEF2		0x2140
+#define DC_OVERLAY_RGBTORGB_COEF3		0x2180
+#define DC_OVERLAY_RGBTORGB_COEF4		0x21C0
+
+#define DC_CURSOR_CONFIG			0x1468
+# define CURSOR_HOT_X(x)			((x) << 16)
+# define CURSOR_HOT_X_MASK			GENMASK(23, 16)
+# define CURSOR_HOT_y(x)			((x) << 8)
+# define CURSOR_HOT_y_MASK			GENMASK(15, 8)
+# define CURSOR_SIZE(x)				((x) << 5)
+# define CURSOR_SIZE_MASK			GENMASK(7, 5)
+# define CURSOR_VALID(x)			((x) << 3)
+# define CURSOR_VALID_MASK			GENMASK(3, 3)
+# define CURSOR_TRIG_FETCH(x)			((x) << 2)
+# define CURSOR_TRIG_FETCH_MASK			GENMASK(2, 2)
+# define CURSOR_FORMAT(x)			((x) << 0)
+# define CURSOR_FORMAT_MASK			GENMASK(1, 0)
+# define CURSOR_FORMAT_DISABLE			0
+# define CURSOR_FORMAT_MARK			1
+# define CURSOR_FORMAT_A8R8G8B8			2
+
+#define DC_CURSOR_ADDRESS			0x146C
+#define DC_CURSOR_LOCATION			0x1470
+# define X_LCOTION(x)				(x)
+# define Y_LCOTION(x)				((x) << 16)
+
+#define DC_CURSOR_BACKGROUND			0x1474
+#define DC_CURSOR_FOREGROUND			0x1478
+#define DC_CURSOR_CLK_GATING			0x1484
+#define DC_CURSOR_CONFIG_EX			0x24E8
+#define DC_CURSOR_OFFSET			0x1080
+
+#define DC_DISPLAY_DITHER_CONFIG		0x1410
+#define DC_DISPLAY_PANEL_CONFIG			0x1418
+# define PANEL_RGB2YUV_EN			BIT(16)
+# define PANEL_GAMMA_EN				BIT(13)
+# define PANEL_OUTPUT_EN			BIT(12)
+# define PANEL_CLOCK_EN				BIT(8)
+# define PANEL_DATA_EN				BIT(4)
+# define PANEL_DE_EN				BIT(0)
+
+#define DC_DISPLAY_PANEL_CONFIG_EX		0x2518
+# define PANEL_SHADOW_INVALID			BIT(0)
+
+#define DC_DISPLAY_DITHER_TABLE_LOW		0x1420
+#define DC_DISPLAY_DITHER_TABLE_HIGH		0x1428
+#define DC_DISPLAY_H				0x1430
+# define H_ACTIVE_LEN(x)			(x)
+# define H_TOTAL_LEN(x)				((x) << 16)
+
+#define DC_DISPLAY_H_SYNC			0x1438
+# define H_SYNC_START_LEN(x)			(x)
+# define H_SYNC_END_LEN(x)			((x) << 15)
+# define H_PLUS_LEN(x)				((x) << 30)
+# define H_POLARITY_LEN(x)			((x) << 31)
+
+#define DC_DISPLAY_V				0x1440
+# define V_ACTIVE_LEN(x)			(x)
+# define V_TOTAL_LEN(x)				((x) << 16)
+
+#define DC_DISPLAY_V_SYNC			0x1448
+# define V_SYNC_START_LEN(x)			(x)
+# define V_SYNC_END_LEN(x)			((x) << 15)
+# define V_PLUS_LEN(x)				((x) << 30)
+# define V_POLARITY_LEN(x)			((x) << 31)
+
+#define DC_DISPLAY_CURRENT_LOCATION		0x1450
+#define DC_DISPLAY_GAMMA_INDEX			0x1458
+#define DC_DISPLAY_GAMMA_DATA			0x1460
+#define DC_DISPLAY_INT				0x147C
+#define DC_DISPLAY_INT_ENABLE			0x1480
+#define DC_DISPLAY_DBI_CONFIG			0x1488
+#define DC_DISPLAY_GENERAL_CONFIG		0x14B0
+#define DC_DISPLAY_DPI_CONFIG			0x14B8
+#define DC_DISPLAY_PANEL_START			0x1CCC
+# define PANEL0_EN				BIT(0)
+# define PANEL1_EN				BIT(1)
+# define TWO_PANEL_EN				BIT(2)
+# define SYNC_EN				BIT(3)
+
+#define DC_DISPLAY_DEBUG_COUNTER_SELECT		0x14D0
+#define DC_DISPLAY_DEBUG_COUNTER_VALUE		0x14D8
+#define DC_DISPLAY_DP_CONFIG			0x1CD0
+# define DP_SELECT				BIT(3)
+
+#define DC_DISPLAY_GAMMA_EX_INDEX		0x1CF0
+#define DC_DISPLAY_GAMMA_EX_DATA		0x1CF8
+#define DC_DISPLAY_GAMMA_EX_ONE_DATA		0x1D80
+#define DC_DISPLAY_RGBTOYUV_COEF0		0x1E48
+#define DC_DISPLAY_RGBTOYUV_COEF1		0x1E50
+#define DC_DISPLAY_RGBTOYUV_COEF2		0x1E58
+#define DC_DISPLAY_RGBTOYUV_COEF3		0x1E60
+#define DC_DISPLAY_RGBTOYUV_COEF4		0x1E68
+#define DC_DISPLAY_RGBTOYUV_COEFD0		0x1E70
+#define DC_DISPLAY_RGBTOYUV_COEFD1		0x1E78
+#define DC_DISPLAY_RGBTOYUV_COEFD2		0x1E80
+
+#define DC_CLK_GATTING				0x1A28
+#define DC_QOS_CONFIG				0x1A38
+
+#define DC_TRANSPARENCY_OPAQUE			0x00
+#define DC_TRANSPARENCY_KEY			0x02
+#define DC_DISPLAY_DITHERTABLE_LOW		0x7B48F3C0
+#define DC_DISPLAY_DITHERTABLE_HIGH		0x596AD1E2
+
+#define DC_TILE_MODE4X4	0x15
+
+#define GAMMA_SIZE				256
+#define GAMMA_EX_SIZE				300
+#define DEGAMMA_SIZE				260
+
+#define RGB_TO_RGB_TABLE_SIZE			9
+#define YUV_TO_RGB_TABLE_SIZE			16
+#define RGB_TO_YUV_TABLE_SIZE			12
+
+#define DC_LAYER_NUM	6
+#define DC_DISPLAY_NUM	2
+#define DC_CURSOR_NUM	2
+
+enum dc_hw_plane_id {
+	PRIMARY_PLANE_0,
+	OVERLAY_PLANE_0,
+	OVERLAY_PLANE_1,
+	PRIMARY_PLANE_1,
+	OVERLAY_PLANE_2,
+	OVERLAY_PLANE_3,
+	CURSOR_PLANE_0,
+	CURSOR_PLANE_1,
+	PLANE_NUM
+};
+
+enum dc_hw_color_format {
+	FORMAT_X4R4G4B4,
+	FORMAT_A4R4G4B4,
+	FORMAT_X1R5G5B5,
+	FORMAT_A1R5G5B5,
+	FORMAT_R5G6B5,
+	FORMAT_X8R8G8B8,
+	FORMAT_A8R8G8B8,
+	FORMAT_YUY2,
+	FORMAT_UYVY,
+	FORMAT_INDEX8,
+	FORMAT_MONOCHROME,
+	FORMAT_YV12 = 0xf,
+	FORMAT_A8,
+	FORMAT_NV12,
+	FORMAT_NV16,
+	FORMAT_RG16,
+	FORMAT_R8,
+	FORMAT_NV12_10BIT,
+	FORMAT_A2R10G10B10,
+	FORMAT_NV16_10BIT,
+	FORMAT_INDEX1,
+	FORMAT_INDEX2,
+	FORMAT_INDEX4,
+	FORMAT_P010,
+	FORMAT_YUV444,
+	FORMAT_YUV444_10BIT,
+};
+
+enum dc_hw_yuv_color_space {
+	COLOR_SPACE_601 = 0,
+	COLOR_SPACE_709 = 1,
+	COLOR_SPACE_2020 = 3,
+};
+
+enum dc_hw_rotation {
+	ROT_0 = 0,
+	ROT_90 = 4,
+	ROT_180 = 5,
+	ROT_270 = 6,
+	FLIP_X = 1,
+	FLIP_Y = 2,
+	FLIP_XY = 3,
+};
+
+enum dc_hw_swizzle {
+	SWIZZLE_ARGB = 0,
+	SWIZZLE_RGBA,
+	SWIZZLE_ABGR,
+	SWIZZLE_BGRA,
+};
+
+enum dc_hw_out {
+	OUT_DPI,
+	OUT_DP,
+	OUT_MAX,
+};
+
+enum dc_hw_cursor_size {
+	CURSOR_SIZE_32X32 = 0,
+	CURSOR_SIZE_64X64,
+};
+
+struct dc_hw_plane_reg {
+	u32 y_address;
+	u32 u_address;
+	u32 v_address;
+	u32 y_stride;
+	u32 u_stride;
+	u32 v_stride;
+	u32 size;
+	u32 top_left;
+	u32 bottom_right;
+	u32 scale_factor_x;
+	u32 scale_factor_y;
+	u32 h_filter_coef_index;
+	u32 h_filter_coef_data;
+	u32 v_filter_coef_index;
+	u32 v_filter_coef_data;
+	u32 init_offset;
+	u32 color_key;
+	u32 color_key_high;
+	u32 clear_value;
+	u32 color_table_index;
+	u32 color_table_data;
+	u32 scale_config;
+	u32 water_mark;
+	u32 degamma_index;
+	u32 degamma_data;
+	u32 degamma_ex_data;
+	u32 src_global_color;
+	u32 dst_global_color;
+	u32 blend_config;
+	u32 roi_origin;
+	u32 roi_size;
+	u32 yuv_to_rgb_coef0;
+	u32 yuv_to_rgb_coef1;
+	u32 yuv_to_rgb_coef2;
+	u32 yuv_to_rgb_coef3;
+	u32 yuv_to_rgb_coef4;
+	u32 yuv_to_rgb_coefd0;
+	u32 yuv_to_rgb_coefd1;
+	u32 yuv_to_rgb_coefd2;
+	u32 y_clamp_bound;
+	u32 uv_clamp_bound;
+	u32 rgb_to_rgb_coef0;
+	u32 rgb_to_rgb_coef1;
+	u32 rgb_to_rgb_coef2;
+	u32 rgb_to_rgb_coef3;
+	u32 rgb_to_rgb_coef4;
+};
+
+struct dc_hw_gamma {
+	u16 gamma[GAMMA_EX_SIZE][3];
+};
+
+struct dc_hw {
+	enum dc_hw_out		out[DC_DISPLAY_NUM];
+	void __iomem		*hi_base;
+	void __iomem		*reg_base;
+	struct dc_hw_plane_reg	reg[DC_LAYER_NUM];
+
+	struct dc_hw_gamma	gamma[DC_DISPLAY_NUM];
+	struct vs_dc_info	*info;
+};
+
+struct vs_dc_plane {
+	enum dc_hw_plane_id id;
+	u32 offset;
+};
+
+struct vs_dc {
+	struct vs_crtc		*crtc[DC_DISPLAY_NUM];
+	struct dc_hw		hw;
+
+	struct vs_dc_plane	planes[PLANE_NUM];
+};
+
+int dc_hw_init(struct vs_dc *dc);
+void dc_hw_disable_plane(struct vs_dc *dc, u8 id);
+void dc_hw_update_cursor(struct dc_hw *hw, u8 id, dma_addr_t dma_addr,
+			 u32 crtc_w, u32 crtc_x, u32 crtc_y,
+			 s32 hotspot_x, int32_t hotspot_y);
+void dc_hw_disable_cursor(struct dc_hw *hw, u8 id);
+void dc_hw_update_gamma(struct dc_hw *hw, u8 id, u16 index,
+			u16 r, u16 g, u16 b);
+void dc_hw_enable_gamma(struct dc_hw *hw, u8 id, bool enable);
+void dc_hw_enable(struct dc_hw *hw, int id, struct drm_display_mode *mode,
+		  u8 encoder_type, u32 output_fmt);
+void dc_hw_disable(struct dc_hw *hw, int id);
+void dc_hw_enable_interrupt(struct dc_hw *hw);
+void dc_hw_disable_interrupt(struct dc_hw *hw);
+void dc_hw_get_interrupt(struct dc_hw *hw, u8 *status);
+void dc_hw_enable_shadow_register(struct vs_dc *dc, bool enable);
+void dc_hw_set_out(struct dc_hw *hw, enum dc_hw_out out, u8 id);
+void dc_hw_commit(struct dc_hw *hw);
+void dc_plane_hw_update_format_colorspace(struct vs_dc *dc, u32 format,
+					  enum drm_color_encoding encoding, u8 id, bool is_yuv);
+void dc_plane_hw_update_address(struct vs_dc *dc, u8 id, u32 format, dma_addr_t *dma_addr,
+				struct drm_framebuffer *drm_fb, struct drm_rect *src);
+void dc_plane_hw_update_format(struct vs_dc *dc, u32 format, enum drm_color_encoding encoding,
+			       unsigned int rotation, bool visible, unsigned int zpos,
+			       u8 id, u8 display_id);
+void dc_plane_hw_update_scale(struct vs_dc *dc, struct drm_rect *src, struct drm_rect *dst,
+			      u8 id, u8 display_id, unsigned int rotation);
+void dc_plane_hw_update_blend(struct vs_dc *dc, u16 alpha, u16 pixel_blend_mode,
+			      u8 id, u8 display_id);
+
+#endif /* __VS_DC_HW_H__ */
diff --git a/drivers/gpu/drm/verisilicon/vs_type.h b/drivers/gpu/drm/verisilicon/vs_type.h
new file mode 100644
index 000000000000..e9c4ef3cacd6
--- /dev/null
+++ b/drivers/gpu/drm/verisilicon/vs_type.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) VeriSilicon Holdings Co., Ltd.
+ */
+
+#ifndef __VS_TYPE_H__
+#define __VS_TYPE_H__
+
+enum drm_plane_type;
+
+struct vs_plane_data {
+	unsigned int num_formats;
+	const u32 *formats;
+	u8 num_modifiers;
+	const u64 *modifiers;
+	unsigned int min_width;
+	unsigned int min_height;
+	unsigned int max_width;
+	unsigned int max_height;
+	unsigned int rotation;
+	unsigned int blend_mode;
+	unsigned int color_encoding;
+	int min_scale; /* 16.16 fixed point */
+	int max_scale; /* 16.16 fixed point */
+	u8   zpos;
+};
+
+struct vs_plane_info {
+	u32 id;
+	const struct vs_plane_data *data;
+	enum drm_plane_type type;
+};
+
+struct vs_dc_info {
+	const char *name;
+
+	u8 panel_num;
+
+	/* planes */
+	u8 plane_num;
+
+	u8 layer_num;
+	u8 primary_num;
+	u8 overlay_num;
+	u8 cursor_num;
+	const struct vs_plane_info *info;
+	/* 0 means no gamma LUT */
+	u16 gamma_size;
+	u8 gamma_bits;
+
+	u16 pitch_alignment;
+};
+
+#endif /* __VS_TYPE_H__ */
-- 
2.34.1
Re: [PATCH v5 4/9] drm/vs: Add Hardware Functions for VS DC8200
Posted by kernel test robot 1 day, 8 hours ago
Hi keith,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.12 next-20241121]
[cannot apply to drm-misc/drm-misc-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/keith-zhao/dt-bindings-display-bindings-for-starfive-JH7110-display-pipeline/20241121-145710
base:   linus/master
patch link:    https://lore.kernel.org/r/20241120061848.196754-5-keith.zhao%40starfivetech.com
patch subject: [PATCH v5 4/9] drm/vs: Add Hardware Functions for VS DC8200
config: xtensa-kismet-CONFIG_CMA-CONFIG_DRM_VERISILICON_DC8200-0-0 (https://download.01.org/0day-ci/archive/20241122/202411221030.71tSpXt2-lkp@intel.com/config)
reproduce: (https://download.01.org/0day-ci/archive/20241122/202411221030.71tSpXt2-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202411221030.71tSpXt2-lkp@intel.com/

kismet warnings: (new ones prefixed by >>)
>> kismet: WARNING: unmet direct dependencies detected for CMA when selected by DRM_VERISILICON_DC8200
   WARNING: unmet direct dependencies detected for CMA
     Depends on [n]: MMU [=n]
     Selected by [y]:
     - DRM_VERISILICON_DC8200 [=y] && HAS_IOMEM [=y] && DRM [=y] && HAVE_DMA_CONTIGUOUS [=y]

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v5 4/9] drm/vs: Add Hardware Functions for VS DC8200
Posted by Dmitry Baryshkov 1 day, 11 hours ago
On Wed, Nov 20, 2024 at 02:18:43PM +0800, keith zhao wrote:
> This commit introduces hardware-based APIs for
> the VS DRM related to the DC8200

This doesn't describe anything. I've asked to describe the hardware.
Also please don't use phrases as "This commit does this and this". See
Documentation/process/submitting-patches.rst

> 
> Signed-off-by: keith zhao <keith.zhao@starfivetech.com>
> ---
>  MAINTAINERS                            |    1 +
>  drivers/gpu/drm/Kconfig                |    2 +
>  drivers/gpu/drm/Makefile               |    1 +
>  drivers/gpu/drm/verisilicon/Kconfig    |   13 +
>  drivers/gpu/drm/verisilicon/Makefile   |    5 +
>  drivers/gpu/drm/verisilicon/vs_dc_hw.c | 1104 ++++++++++++++++++++++++
>  drivers/gpu/drm/verisilicon/vs_dc_hw.h |  492 +++++++++++
>  drivers/gpu/drm/verisilicon/vs_type.h  |   54 ++
>  8 files changed, 1672 insertions(+)
>  create mode 100644 drivers/gpu/drm/verisilicon/Kconfig
>  create mode 100644 drivers/gpu/drm/verisilicon/Makefile
>  create mode 100644 drivers/gpu/drm/verisilicon/vs_dc_hw.c
>  create mode 100644 drivers/gpu/drm/verisilicon/vs_dc_hw.h
>  create mode 100644 drivers/gpu/drm/verisilicon/vs_type.h
> 

[...]

> +
> +struct dc_hw {
> +	enum dc_hw_out		out[DC_DISPLAY_NUM];
> +	void __iomem		*hi_base;
> +	void __iomem		*reg_base;
> +	struct dc_hw_plane_reg	reg[DC_LAYER_NUM];
> +
> +	struct dc_hw_gamma	gamma[DC_DISPLAY_NUM];
> +	struct vs_dc_info	*info;
> +};
> +
> +struct vs_dc_plane {
> +	enum dc_hw_plane_id id;
> +	u32 offset;
> +};
> +
> +struct vs_dc {
> +	struct vs_crtc		*crtc[DC_DISPLAY_NUM];

"Not defined here. Please drop and add when it is actually defined.",
this was in v4.

> +	struct dc_hw		hw;
> +
> +	struct vs_dc_plane	planes[PLANE_NUM];
> +};
> +
> +int dc_hw_init(struct vs_dc *dc);
> +void dc_hw_disable_plane(struct vs_dc *dc, u8 id);
> +void dc_hw_update_cursor(struct dc_hw *hw, u8 id, dma_addr_t dma_addr,
> +			 u32 crtc_w, u32 crtc_x, u32 crtc_y,
> +			 s32 hotspot_x, int32_t hotspot_y);
> +void dc_hw_disable_cursor(struct dc_hw *hw, u8 id);
> +void dc_hw_update_gamma(struct dc_hw *hw, u8 id, u16 index,
> +			u16 r, u16 g, u16 b);
> +void dc_hw_enable_gamma(struct dc_hw *hw, u8 id, bool enable);
> +void dc_hw_enable(struct dc_hw *hw, int id, struct drm_display_mode *mode,
> +		  u8 encoder_type, u32 output_fmt);
> +void dc_hw_disable(struct dc_hw *hw, int id);
> +void dc_hw_enable_interrupt(struct dc_hw *hw);
> +void dc_hw_disable_interrupt(struct dc_hw *hw);
> +void dc_hw_get_interrupt(struct dc_hw *hw, u8 *status);
> +void dc_hw_enable_shadow_register(struct vs_dc *dc, bool enable);
> +void dc_hw_set_out(struct dc_hw *hw, enum dc_hw_out out, u8 id);
> +void dc_hw_commit(struct dc_hw *hw);
> +void dc_plane_hw_update_format_colorspace(struct vs_dc *dc, u32 format,
> +					  enum drm_color_encoding encoding, u8 id, bool is_yuv);
> +void dc_plane_hw_update_address(struct vs_dc *dc, u8 id, u32 format, dma_addr_t *dma_addr,
> +				struct drm_framebuffer *drm_fb, struct drm_rect *src);
> +void dc_plane_hw_update_format(struct vs_dc *dc, u32 format, enum drm_color_encoding encoding,
> +			       unsigned int rotation, bool visible, unsigned int zpos,
> +			       u8 id, u8 display_id);
> +void dc_plane_hw_update_scale(struct vs_dc *dc, struct drm_rect *src, struct drm_rect *dst,
> +			      u8 id, u8 display_id, unsigned int rotation);
> +void dc_plane_hw_update_blend(struct vs_dc *dc, u16 alpha, u16 pixel_blend_mode,
> +			      u8 id, u8 display_id);
> +
> +#endif /* __VS_DC_HW_H__ */
> diff --git a/drivers/gpu/drm/verisilicon/vs_type.h b/drivers/gpu/drm/verisilicon/vs_type.h
> new file mode 100644
> index 000000000000..e9c4ef3cacd6
> --- /dev/null
> +++ b/drivers/gpu/drm/verisilicon/vs_type.h
> @@ -0,0 +1,54 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) VeriSilicon Holdings Co., Ltd.
> + */
> +
> +#ifndef __VS_TYPE_H__
> +#define __VS_TYPE_H__
> +
> +enum drm_plane_type;
> +
> +struct vs_plane_data {
> +	unsigned int num_formats;
> +	const u32 *formats;
> +	u8 num_modifiers;
> +	const u64 *modifiers;
> +	unsigned int min_width;
> +	unsigned int min_height;
> +	unsigned int max_width;
> +	unsigned int max_height;
> +	unsigned int rotation;
> +	unsigned int blend_mode;
> +	unsigned int color_encoding;
> +	int min_scale; /* 16.16 fixed point */
> +	int max_scale; /* 16.16 fixed point */
> +	u8   zpos;
> +};

Doesn't seem to be used in this patch. I think in v4 I've already asked
to drop everything (data types, fields, defines) that are not used by
_this_ patch. Readd them later, as required.

> +
> +struct vs_plane_info {
> +	u32 id;
> +	const struct vs_plane_data *data;
> +	enum drm_plane_type type;
> +};
> +
> +struct vs_dc_info {
> +	const char *name;
> +
> +	u8 panel_num;
> +
> +	/* planes */
> +	u8 plane_num;
> +
> +	u8 layer_num;
> +	u8 primary_num;
> +	u8 overlay_num;
> +	u8 cursor_num;
> +	const struct vs_plane_info *info;
> +	/* 0 means no gamma LUT */
> +	u16 gamma_size;
> +	u8 gamma_bits;
> +
> +	u16 pitch_alignment;
> +};
> +
> +#endif /* __VS_TYPE_H__ */
> -- 
> 2.34.1
> 

-- 
With best wishes
Dmitry