@@ -12,7 +12,8 @@ mediatek-drm-y := mtk_disp_ccorr.o \
mtk_drm_gem.o \
mtk_drm_plane.o \
mtk_dsi.o \
- mtk_dpi.o
+ mtk_dpi.o \
+ mtk_mdp_rdma.o
obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o
@@ -8,6 +8,7 @@
#include <linux/soc/mediatek/mtk-cmdq.h>
#include "mtk_drm_plane.h"
+#include "mtk_mdp_rdma.h"
void mtk_ccorr_ctm_set(struct device *dev, struct drm_crtc_state *state);
int mtk_ccorr_clk_enable(struct device *dev);
@@ -97,4 +98,15 @@ void mtk_rdma_enable_vblank(struct device *dev,
void *vblank_cb_data);
void mtk_rdma_disable_vblank(struct device *dev);
+void mtk_mdp_rdma_start(void __iomem *base,
+ struct cmdq_pkt *cmdq_pkt,
+ struct cmdq_client_reg *cmdq_base);
+void mtk_mdp_rdma_stop(void __iomem *base,
+ struct cmdq_pkt *cmdq_pkt,
+ struct cmdq_client_reg *cmdq_base);
+void mtk_mdp_rdma_config(void __iomem *base,
+ struct mtk_mdp_rdma_cfg *cfg,
+ struct cmdq_pkt *cmdq_pkt,
+ struct cmdq_client_reg *cmdq_base);
+
#endif
new file mode 100644
@@ -0,0 +1,275 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ */
+
+#include <drm/drm_fourcc.h>
+#include "mtk_drm_drv.h"
+#include "mtk_mdp_rdma.h"
+
+#define REG_FLD(width, shift) \
+ ((unsigned int)((((width) & 0xff) << 16) | ((shift) & 0xff)))
+
+#define REG_FLD_WIDTH(field) ((unsigned int)(((field) >> 16) & 0xff))
+
+#define REG_FLD_SHIFT(field) ((unsigned int)((field) & 0xff))
+
+#define REG_FLD_MASK(field) \
+ ((unsigned int)((1ULL << REG_FLD_WIDTH(field)) - 1) \
+ << REG_FLD_SHIFT(field))
+
+#define REG_FLD_VAL(field, val) \
+ (((val) << REG_FLD_SHIFT(field)) & REG_FLD_MASK(field))
+
+#define MDP_RDMA_EN 0x000
+#define FLD_ROT_ENABLE REG_FLD(1, 0)
+
+#define MDP_RDMA_RESET 0x008
+
+#define MDP_RDMA_CON 0x020
+#define FLD_OUTPUT_10B REG_FLD(1, 5)
+#define FLD_SIMPLE_MODE REG_FLD(1, 4)
+
+#define MDP_RDMA_GMCIF_CON 0x028
+#define FLD_EXT_ULTRA_EN REG_FLD(1, 18)
+#define FLD_PRE_ULTRA_EN REG_FLD(2, 16)
+#define FLD_ULTRA_EN REG_FLD(2, 12)
+#define FLD_RD_REQ_TYPE REG_FLD(4, 4)
+#define VAL_RD_REQ_TYPE_BURST_8_ACCESS 7
+#define FLD_EXT_PREULTRA_EN REG_FLD(1, 3)
+#define FLD_COMMAND_DIV REG_FLD(1, 0)
+
+#define MDP_RDMA_SRC_CON 0x030
+#define FLD_OUTPUT_ARGB REG_FLD(1, 25)
+#define FLD_BIT_NUMBER REG_FLD(2, 18)
+#define FLD_UNIFORM_CONFIG REG_FLD(1, 17)
+#define FLD_SWAP REG_FLD(1, 14)
+#define FLD_SRC_FORMAT REG_FLD(4, 0)
+
+#define MDP_RDMA_COMP_CON 0x038
+#define FLD_AFBC_EN REG_FLD(1, 22)
+#define FLD_AFBC_YUV_TRANSFORM REG_FLD(1, 21)
+#define FLD_UFBDC_EN REG_FLD(1, 12)
+
+#define MDP_RDMA_MF_BKGD_SIZE_IN_BYTE 0x060
+#define FLD_MF_BKGD_WB REG_FLD(23, 0)
+
+#define MDP_RDMA_MF_BKGD_SIZE_IN_PIXEL 0x068
+#define FLD_MF_BKGD_WP REG_FLD(23, 0)
+
+#define MDP_RDMA_MF_SRC_SIZE 0x070
+#define FLD_MF_SRC_H REG_FLD(15, 16)
+#define FLD_MF_SRC_W REG_FLD(15, 0)
+
+#define MDP_RDMA_MF_CLIP_SIZE 0x078
+#define FLD_MF_CLIP_H REG_FLD(15, 16)
+#define FLD_MF_CLIP_W REG_FLD(15, 0)
+
+#define MDP_RDMA_TARGET_LINE 0x0a0
+#define FLD_LINE_THRESHOLD REG_FLD(15, 17)
+#define FLD_TARGET_LINE_EN REG_FLD(1, 16)
+
+#define MDP_RDMA_SRC_OFFSET_0 0x118
+#define FLD_SRC_OFFSET_0 REG_FLD(32, 0)
+
+#define MDP_RDMA_TRANSFORM_0 0x200
+#define FLD_INT_MATRIX_SEL REG_FLD(5, 23)
+#define FLD_TRANS_EN REG_FLD(1, 16)
+
+#define MDP_RDMA_UTRA_H_CON_0 0x248
+#define FLD_PREUTRA_H_OFS_0 REG_FLD(10, 10)
+
+#define MDP_RDMA_UTRA_L_CON_0 0x250
+#define FLD_PREUTRA_L_OFS_0 REG_FLD(10, 10)
+
+#define MDP_RDMA_SRC_BASE_0 0xf00
+#define FLD_SRC_BASE_0 REG_FLD(32, 0)
+
+#define RDMA_INPUT_SWAP BIT(14)
+#define RDMA_INPUT_10BIT BIT(18)
+
+enum rdma_format {
+ RDMA_INPUT_FORMAT_RGB565 = 0,
+ RDMA_INPUT_FORMAT_RGB888 = 1,
+ RDMA_INPUT_FORMAT_RGBA8888 = 2,
+ RDMA_INPUT_FORMAT_ARGB8888 = 3,
+ RDMA_INPUT_FORMAT_UYVY = 4,
+ RDMA_INPUT_FORMAT_YUY2 = 5,
+ RDMA_INPUT_FORMAT_Y8 = 7,
+ RDMA_INPUT_FORMAT_YV12 = 8,
+ RDMA_INPUT_FORMAT_UYVY_3PL = 9,
+ RDMA_INPUT_FORMAT_NV12 = 12,
+ RDMA_INPUT_FORMAT_UYVY_2PL = 13,
+ RDMA_INPUT_FORMAT_Y410 = 14
+};
+
+static unsigned int rdma_fmt_convert(unsigned int fmt)
+{
+ switch (fmt) {
+ default:
+ case DRM_FORMAT_RGB565:
+ return RDMA_INPUT_FORMAT_RGB565;
+ case DRM_FORMAT_BGR565:
+ return RDMA_INPUT_FORMAT_RGB565 | RDMA_INPUT_SWAP;
+ case DRM_FORMAT_RGB888:
+ return RDMA_INPUT_FORMAT_RGB888;
+ case DRM_FORMAT_BGR888:
+ return RDMA_INPUT_FORMAT_RGB888 | RDMA_INPUT_SWAP;
+ case DRM_FORMAT_RGBX8888:
+ case DRM_FORMAT_RGBA8888:
+ return RDMA_INPUT_FORMAT_ARGB8888;
+ case DRM_FORMAT_BGRX8888:
+ case DRM_FORMAT_BGRA8888:
+ return RDMA_INPUT_FORMAT_ARGB8888 | RDMA_INPUT_SWAP;
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_ARGB8888:
+ return RDMA_INPUT_FORMAT_RGBA8888;
+ case DRM_FORMAT_XBGR8888:
+ case DRM_FORMAT_ABGR8888:
+ return RDMA_INPUT_FORMAT_RGBA8888 | RDMA_INPUT_SWAP;
+ case DRM_FORMAT_ABGR2101010:
+ return RDMA_INPUT_FORMAT_RGBA8888 | RDMA_INPUT_SWAP |
+ RDMA_INPUT_10BIT;
+ case DRM_FORMAT_ARGB2101010:
+ return RDMA_INPUT_FORMAT_RGBA8888 | RDMA_INPUT_10BIT;
+ case DRM_FORMAT_RGBA1010102:
+ return RDMA_INPUT_FORMAT_ARGB8888 | RDMA_INPUT_SWAP |
+ RDMA_INPUT_10BIT;
+ case DRM_FORMAT_BGRA1010102:
+ return RDMA_INPUT_FORMAT_ARGB8888 | RDMA_INPUT_10BIT;
+ case DRM_FORMAT_UYVY:
+ return RDMA_INPUT_FORMAT_UYVY;
+ case DRM_FORMAT_YUYV:
+ return RDMA_INPUT_FORMAT_YUY2;
+ }
+}
+
+static void mtk_mdp_rdma_fifo_config(void __iomem *base, struct cmdq_pkt *cmdq_pkt,
+ struct cmdq_client_reg *cmdq_base)
+{
+ unsigned int pre_ultra_h = 156;
+ unsigned int pre_ultra_l = 104;
+ unsigned int reg_mask;
+ unsigned int reg_val;
+ unsigned int reg;
+
+ reg = MDP_RDMA_GMCIF_CON;
+ reg_val = REG_FLD_VAL(FLD_RD_REQ_TYPE, VAL_RD_REQ_TYPE_BURST_8_ACCESS) |
+ REG_FLD_VAL(FLD_COMMAND_DIV, 1) |
+ REG_FLD_VAL(FLD_EXT_PREULTRA_EN, 1) |
+ REG_FLD_VAL(FLD_ULTRA_EN, 0) |
+ REG_FLD_VAL(FLD_PRE_ULTRA_EN, 1) |
+ REG_FLD_VAL(FLD_EXT_ULTRA_EN, 1);
+ reg_mask = REG_FLD_MASK(FLD_RD_REQ_TYPE) |
+ REG_FLD_MASK(FLD_COMMAND_DIV) |
+ REG_FLD_MASK(FLD_EXT_PREULTRA_EN) |
+ REG_FLD_MASK(FLD_ULTRA_EN) |
+ REG_FLD_MASK(FLD_PRE_ULTRA_EN) |
+ REG_FLD_MASK(FLD_EXT_ULTRA_EN);
+ mtk_ddp_write_mask(cmdq_pkt, reg_val, cmdq_base, base, reg, reg_mask);
+
+ reg = MDP_RDMA_UTRA_H_CON_0;
+ reg_val = REG_FLD_VAL(FLD_PREUTRA_H_OFS_0, pre_ultra_h);
+ reg_mask = REG_FLD_MASK(FLD_PREUTRA_H_OFS_0);
+ mtk_ddp_write_mask(cmdq_pkt, reg_val, cmdq_base, base, reg, reg_mask);
+
+ reg = MDP_RDMA_UTRA_L_CON_0;
+ reg_val = REG_FLD_VAL(FLD_PREUTRA_L_OFS_0, pre_ultra_l);
+ reg_mask = REG_FLD_MASK(FLD_PREUTRA_L_OFS_0);
+ mtk_ddp_write_mask(cmdq_pkt, reg_val, cmdq_base, base, reg, reg_mask);
+}
+
+void mtk_mdp_rdma_start(void __iomem *base, struct cmdq_pkt *cmdq_pkt,
+ struct cmdq_client_reg *cmdq_base)
+{
+ mtk_ddp_write_mask(cmdq_pkt, REG_FLD_VAL(FLD_ROT_ENABLE, 1), cmdq_base,
+ base, MDP_RDMA_EN, REG_FLD_MASK(FLD_ROT_ENABLE));
+}
+
+void mtk_mdp_rdma_stop(void __iomem *base, struct cmdq_pkt *cmdq_pkt,
+ struct cmdq_client_reg *cmdq_base)
+{
+ mtk_ddp_write_mask(cmdq_pkt, REG_FLD_VAL(FLD_ROT_ENABLE, 0), cmdq_base,
+ base, MDP_RDMA_EN, REG_FLD_MASK(FLD_ROT_ENABLE));
+ mtk_ddp_write(cmdq_pkt, 1, cmdq_base, base, MDP_RDMA_RESET);
+ mtk_ddp_write(cmdq_pkt, 0, cmdq_base, base, MDP_RDMA_RESET);
+}
+
+void mtk_mdp_rdma_config(void __iomem *base, struct mtk_mdp_rdma_cfg *cfg,
+ struct cmdq_pkt *cmdq_pkt,
+ struct cmdq_client_reg *cmdq_base)
+{
+ const struct drm_format_info *fmt_info = drm_format_info(cfg->fmt);
+ unsigned int src_pitch_y = cfg->pitch;
+ unsigned int bpp_y = fmt_info->cpp[0] * 8;
+ unsigned int offset_y = 0;
+
+ mtk_mdp_rdma_fifo_config(base, cmdq_pkt, cmdq_base);
+
+ mtk_ddp_write_mask(cmdq_pkt, REG_FLD_VAL(FLD_UNIFORM_CONFIG, 1),
+ cmdq_base, base, MDP_RDMA_SRC_CON,
+ REG_FLD_MASK(FLD_UNIFORM_CONFIG));
+ mtk_ddp_write_mask(cmdq_pkt, rdma_fmt_convert(cfg->fmt), cmdq_base,
+ base, MDP_RDMA_SRC_CON, REG_FLD_MASK(FLD_SWAP) |
+ REG_FLD_MASK(FLD_SRC_FORMAT) |
+ REG_FLD_MASK(FLD_BIT_NUMBER));
+
+ if (!cfg->csc_enable && fmt_info->has_alpha)
+ mtk_ddp_write_mask(cmdq_pkt, REG_FLD_VAL(FLD_OUTPUT_ARGB, 1),
+ cmdq_base, base, MDP_RDMA_SRC_CON,
+ REG_FLD_MASK(FLD_OUTPUT_ARGB));
+ else
+ mtk_ddp_write_mask(cmdq_pkt, REG_FLD_VAL(FLD_OUTPUT_ARGB, 0),
+ cmdq_base, base, MDP_RDMA_SRC_CON,
+ REG_FLD_MASK(FLD_OUTPUT_ARGB));
+
+ mtk_ddp_write_mask(cmdq_pkt, cfg->addr0, cmdq_base, base,
+ MDP_RDMA_SRC_BASE_0, REG_FLD_MASK(FLD_SRC_BASE_0));
+
+ mtk_ddp_write_mask(cmdq_pkt, src_pitch_y, cmdq_base, base,
+ MDP_RDMA_MF_BKGD_SIZE_IN_BYTE,
+ REG_FLD_MASK(FLD_MF_BKGD_WB));
+
+ mtk_ddp_write_mask(cmdq_pkt, REG_FLD_VAL(FLD_AFBC_YUV_TRANSFORM, 0),
+ cmdq_base, base, MDP_RDMA_COMP_CON,
+ REG_FLD_MASK(FLD_AFBC_YUV_TRANSFORM));
+ mtk_ddp_write_mask(cmdq_pkt, REG_FLD_VAL(FLD_UFBDC_EN, 0), cmdq_base,
+ base, MDP_RDMA_COMP_CON, REG_FLD_MASK(FLD_UFBDC_EN));
+ mtk_ddp_write_mask(cmdq_pkt, REG_FLD_VAL(FLD_AFBC_EN, 0), cmdq_base,
+ base, MDP_RDMA_COMP_CON, REG_FLD_MASK(FLD_AFBC_EN));
+
+ mtk_ddp_write_mask(cmdq_pkt, REG_FLD_VAL(FLD_OUTPUT_10B, 1), cmdq_base,
+ base, MDP_RDMA_CON, REG_FLD_MASK(FLD_OUTPUT_10B));
+ mtk_ddp_write_mask(cmdq_pkt, REG_FLD_VAL(FLD_SIMPLE_MODE, 1), cmdq_base,
+ base, MDP_RDMA_CON, REG_FLD_MASK(FLD_SIMPLE_MODE));
+ mtk_ddp_write_mask(cmdq_pkt, REG_FLD_VAL(FLD_TRANS_EN, cfg->csc_enable),
+ cmdq_base, base, MDP_RDMA_TRANSFORM_0,
+ REG_FLD_MASK(FLD_TRANS_EN));
+ mtk_ddp_write_mask(cmdq_pkt, REG_FLD_VAL(FLD_INT_MATRIX_SEL, cfg->profile),
+ cmdq_base, base, MDP_RDMA_TRANSFORM_0,
+ REG_FLD_MASK(FLD_INT_MATRIX_SEL));
+
+ offset_y = (cfg->x_left * bpp_y >> 3) + cfg->y_top * src_pitch_y;
+
+ mtk_ddp_write_mask(cmdq_pkt, REG_FLD_VAL(FLD_SRC_OFFSET_0, offset_y),
+ cmdq_base, base, MDP_RDMA_SRC_OFFSET_0,
+ REG_FLD_MASK(FLD_SRC_OFFSET_0));
+ mtk_ddp_write_mask(cmdq_pkt, REG_FLD_VAL(FLD_MF_SRC_W, cfg->width),
+ cmdq_base, base, MDP_RDMA_MF_SRC_SIZE,
+ REG_FLD_MASK(FLD_MF_SRC_W));
+ mtk_ddp_write_mask(cmdq_pkt, REG_FLD_VAL(FLD_MF_SRC_H, cfg->height),
+ cmdq_base, base, MDP_RDMA_MF_SRC_SIZE,
+ REG_FLD_MASK(FLD_MF_SRC_H));
+ mtk_ddp_write_mask(cmdq_pkt, REG_FLD_VAL(FLD_MF_CLIP_W, cfg->width),
+ cmdq_base, base, MDP_RDMA_MF_CLIP_SIZE,
+ REG_FLD_MASK(FLD_MF_CLIP_W));
+ mtk_ddp_write_mask(cmdq_pkt, REG_FLD_VAL(FLD_MF_CLIP_H, cfg->height),
+ cmdq_base, base, MDP_RDMA_MF_CLIP_SIZE,
+ REG_FLD_MASK(FLD_MF_CLIP_H));
+ mtk_ddp_write_mask(cmdq_pkt, REG_FLD_VAL(FLD_LINE_THRESHOLD, cfg->height),
+ cmdq_base, base, MDP_RDMA_TARGET_LINE,
+ REG_FLD_MASK(FLD_LINE_THRESHOLD));
+ mtk_ddp_write_mask(cmdq_pkt, REG_FLD_VAL(FLD_TARGET_LINE_EN, 1),
+ cmdq_base, base, MDP_RDMA_TARGET_LINE,
+ REG_FLD_MASK(FLD_TARGET_LINE_EN));
+}
new file mode 100644
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ */
+
+#ifndef __MTK_MDP_RDMA_H__
+#define __MTK_MDP_RDMA_H__
+
+enum mtk_mdp_rdma_profile {
+ RDMA_CSC_RGB_TO_JPEG = 0,
+ RDMA_CSC_RGB_TO_FULL709 = 1,
+ RDMA_CSC_RGB_TO_BT601 = 2,
+ RDMA_CSC_RGB_TO_BT709 = 3,
+ RDMA_CSC_JPEG_TO_RGB = 4,
+ RDMA_CSC_FULL709_TO_RGB = 5,
+ RDMA_CSC_BT601_TO_RGB = 6,
+ RDMA_CSC_BT709_TO_RGB = 7,
+ RDMA_CSC_JPEG_TO_BT601 = 8,
+ RDMA_CSC_JPEG_TO_BT709 = 9,
+ RDMA_CSC_BT601_TO_JPEG = 10,
+ RDMA_CSC_BT709_TO_BT601 = 11,
+ RDMA_CSC_BT601_TO_BT709 = 12
+};
+
+struct mtk_mdp_rdma_cfg {
+ enum mtk_mdp_rdma_profile profile;
+ unsigned int source_width;
+ unsigned int pitch;
+ unsigned int addr0;
+ unsigned int width;
+ unsigned int height;
+ unsigned int x_left;
+ unsigned int y_top;
+ bool csc_enable;
+ int fmt;
+};
+
+#endif // __MTK_MDP_RDMA_H__
+
Add MDP_RDMA driver for MT8195. MDP_RDMA is the DMA engine of the ovl_adaptor component. Signed-off-by: Nancy.Lin <nancy.lin@mediatek.com> --- drivers/gpu/drm/mediatek/Makefile | 3 +- drivers/gpu/drm/mediatek/mtk_disp_drv.h | 12 ++ drivers/gpu/drm/mediatek/mtk_mdp_rdma.c | 275 ++++++++++++++++++++++++ drivers/gpu/drm/mediatek/mtk_mdp_rdma.h | 39 ++++ 4 files changed, 328 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/mediatek/mtk_mdp_rdma.c create mode 100644 drivers/gpu/drm/mediatek/mtk_mdp_rdma.h