This commit introduces hardware-based APIs for the VS DRM related to the DC8200 Signed-off-by: keith zhao <keith.zhao@xxxxxxxxxxxxxxxx> --- 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