<html><body><p>
<pre>
On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> From: Nancy Lin <nancy.lin@mediatek.com>
>
> EXDMA is a DMA engine for reading data from DRAM with
> various DRAM footprints and data formats. For input
> sources in certain color formats and color domains,
> EXDMA also includes a color transfer function to
> process pixels into a consistent color domain.
> New Add: 6320385 Fix RG16 and refine RG24
>
> Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
> Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> ---
> drivers/gpu/drm/mediatek/Makefile | 1 +
> drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 1 +
> drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 1 +
> drivers/gpu/drm/mediatek/mtk_disp_drv.h | 9 +
> drivers/gpu/drm/mediatek/mtk_disp_exdma.c | 372 ++++++++++++++++++++++
> drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 +
> drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 +
> 7 files changed, 386 insertions(+)
> create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_exdma.c
>
> diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
> index 32a2ed6c0cfe..db92f4fb353d 100644
> --- a/drivers/gpu/drm/mediatek/Makefile
> +++ b/drivers/gpu/drm/mediatek/Makefile
> @@ -5,6 +5,7 @@ mediatek-drm-y := mtk_crtc.o \
> mtk_disp_aal.o \
> mtk_disp_ccorr.o \
> mtk_disp_color.o \
> + mtk_disp_exdma.o \
> mtk_disp_gamma.o \
> mtk_disp_merge.o \
> mtk_disp_ovl.o \
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> index edc6417639e6..3e0739d8e6f1 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> @@ -445,6 +445,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
> [MTK_DP_INTF] = "dp-intf",
> [MTK_DPI] = "dpi",
> [MTK_DSI] = "dsi",
> +[MTK_OVL_EXDMA] = "exdma",
> };
>
> struct mtk_ddp_comp_match {
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> index 39720b27f4e9..86dc0ee3924c 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> @@ -43,6 +43,7 @@ enum mtk_ddp_comp_type {
> MTK_DPI,
> MTK_DP_INTF,
> MTK_DSI,
> +MTK_OVL_EXDMA,
> MTK_DDP_COMP_TYPE_MAX,
> };
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> index 04217a36939c..4e3d2510bef5 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> @@ -39,6 +39,15 @@ void mtk_color_config(struct device *dev, unsigned int w,
> unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
> void mtk_color_start(struct device *dev);
>
> +int mtk_disp_exdma_clk_enable(struct device *dev);
> +void mtk_disp_exdma_clk_disable(struct device *dev);
> +void mtk_disp_exdma_start(struct device *dev, struct cmdq_pkt *cmdq_pkt);
> +void mtk_disp_exdma_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt);
> +void mtk_disp_exdma_layer_config(struct device *dev, struct mtk_plane_state *state,
> + struct cmdq_pkt *cmdq_pkt);
> +const u32 *mtk_disp_exdma_get_formats(struct device *dev);
> +size_t mtk_disp_exdma_get_num_formats(struct device *dev);
> +
> void mtk_dither_set_common(void __iomem *regs, struct cmdq_client_reg *cmdq_reg,
> unsigned int bpc, unsigned int cfg,
> unsigned int dither_en, struct cmdq_pkt *cmdq_pkt);
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_exdma.c b/drivers/gpu/drm/mediatek/mtk_disp_exdma.c
> new file mode 100644
> index 000000000000..d4f7021f98d7
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_exdma.c
> @@ -0,0 +1,372 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2025 MediaTek Inc.
> + */
> +
> +#include <drm/drm_fourcc.h>
> +#include <drm/drm_blend.h>
> +#include <drm/drm_framebuffer.h>
> +#include <linux/clk.h>
> +#include <linux/component.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/soc/mediatek/mtk-cmdq.h>
> +
> +#include "mtk_disp_drv.h"
> +#include "mtk_drm_drv.h"
> +#include "mtk_disp_ovl.h"
> +
> +#define DISP_REG_OVL_EXDMA_EN_CON0xc
> +#define OVL_EXDMA_OP_8BIT_MODEBIT(4)
> +#define OVL_EXDMA_HG_FOVL_EXDMA_CK_ONBIT(8)
> +#define OVL_EXDMA_HF_FOVL_EXDMA_CK_ONBIT(10)
> +#define DISP_REG_OVL_EXDMA_DATAPATH_CON0x014
> +#define OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_ENBIT(0)
> +#define OVL_EXDMA_DATAPATH_CON_GCLAST_ENBIT(24)
> +#define OVL_EXDMA_DATAPATH_CON_HDR_GCLAST_ENBIT(25)
> +#define DISP_REG_OVL_EXDMA_EN0x020
> +#define OVL_EXDMA_ENBIT(0)
> +#define DISP_REG_OVL_EXDMA_RST0x024
> +#define OVL_EXDMA_RSTBIT(0)
> +#define DISP_REG_OVL_EXDMA_ROI_SIZE0x030
> +#define DISP_REG_OVL_EXDMA_L0_EN0x040
> +#define OVL_EXDMA_L0_ENBIT(0)
> +#define DISP_REG_OVL_EXDMA_OFFSET0x044
DISP_REG_OVL_EXDMA_OFFSET is useless, so drop it.
> +#define DISP_REG_OVL_EXDMA_SRC_SIZE0x048
> +#define DISP_REG_OVL_EXDMA_L0_CLRFMT0x050
> +#define OVL_EXDMA_CON_FLD_CLRFMTGENMASK(3, 0)
> +#define OVL_EXDMA_CON_CLRFMT_MANBIT(4)
> +#define OVL_EXDMA_CON_FLD_CLRFMT_NBGENMASK(9, 8)
> +#define OVL_EXDMA_CON_CLRFMT_NB_10_BITBIT(8)
> +#define OVL_EXDMA_CON_BYTE_SWAPBIT(16)
> +#define OVL_EXDMA_CON_RGB_SWAPBIT(17)
> +#define DISP_REG_OVL_EXDMA_RDMA0_CTRL0x100
> +#define OVL_EXDMA_RDMA0_ENBIT(0)
> +#define DISP_REG_OVL_EXDMA_RDMA_BURST_CON10x1f4
> +#define OVL_EXDMA_RDMA_BURST_CON1_BURST16_ENBIT(28)
> +#define OVL_EXDMA_RDMA_BURST_CON1_DDR_ENBIT(30)
> +#define OVL_EXDMA_RDMA_BURST_CON1_DDR_ACK_ENBIT(31)
> +#define DISP_REG_OVL_EXDMA_DUMMY_REG0x200
> +#define OVL_EXDMA_EXT_DDR_EN_OPTBIT(2)
> +#define OVL_EXDMA_FORCE_EXT_DDR_ENBIT(3)
> +#define DISP_REG_OVL_EXDMA_GDRDY_PRD0x208
> +#define DISP_REG_OVL_EXDMA_PITCH_MSB0x2f0
> +#define DISP_REG_OVL_EXDMA_PITCH0x2f4
> +#define OVL_EXDMA_L0_SRC_PITCHGENMASK(15, 0)
> +#define OVL_EXDMA_L0_CONST_BLDBIT(28)
> +#define OVL_EXDMA_L0_SRC_PITCH_MASKGENMASK(15, 0)
> +#define DISP_REG_OVL_EXDMA_L0_GUSER_EXT0x2fc
> +#define OVL_EXDMA_RDMA0_L0_VCSELBIT(5)
> +#define OVL_EXDMA_RDMA0_HDR_L0_VCSELBIT(21)
> +#define DISP_REG_OVL_EXDMA_CON0x300
> +#define OVL_EXDMA_CON_FLD_INT_MTX_SELGENMASK(19, 16)
> +#define OVL_EXDMA_CON_INT_MTX_BT601_TO_RGB(6 << 16)
> +#define OVL_EXDMA_CON_INT_MTX_BT709_TO_RGB(7 << 16)
> +#define OVL_EXDMA_CON_INT_MTX_ENBIT(27)
> +#define DISP_REG_OVL_EXDMA_ADDR0xf40
> +#define DISP_REG_OVL_EXDMA_MOUT0xff0
> +#define OVL_EXDMA_MOUT_OUT_DATABIT(0)
OVL_EXDMA_MOUT_OUT_DATA is useless, so drop it.
> +#define OVL_EXDMA_MOUT_BGCLR_OUTBIT(1)
> +
> +static const u32 formats[] = {
> +DRM_FORMAT_XRGB8888,
> +DRM_FORMAT_ARGB8888,
> +DRM_FORMAT_BGRX8888,
> +DRM_FORMAT_BGRA8888,
> +DRM_FORMAT_ABGR8888,
> +DRM_FORMAT_XBGR8888,
> +DRM_FORMAT_RGBX8888,
> +DRM_FORMAT_RGBA8888,
> +DRM_FORMAT_RGB888,
> +DRM_FORMAT_BGR888,
> +DRM_FORMAT_RGB565,
> +DRM_FORMAT_BGR565,
In this version, you add BGR565. If mt8195 also support BGR565, add BGR565 to mt8195_formats[] and merge these two array.
> +DRM_FORMAT_UYVY,
> +DRM_FORMAT_YUYV,
> +DRM_FORMAT_XRGB2101010,
> +DRM_FORMAT_ARGB2101010,
> +DRM_FORMAT_RGBX1010102,
> +DRM_FORMAT_RGBA1010102,
> +DRM_FORMAT_XBGR2101010,
> +DRM_FORMAT_ABGR2101010,
> +DRM_FORMAT_BGRX1010102,
> +DRM_FORMAT_BGRA1010102,
> +};
> +
> +struct mtk_disp_exdma {
> +void __iomem*regs;
> +struct clk*clk;
> +struct cmdq_client_regcmdq_reg;
> +struct device*larb;
> +};
> +
> +static unsigned int mtk_disp_exdma_color_convert(unsigned int color_encoding)
> +{
> +switch (color_encoding) {
> +default:
> +case DRM_COLOR_YCBCR_BT709:
> +return OVL_EXDMA_CON_INT_MTX_BT709_TO_RGB;
> +case DRM_COLOR_YCBCR_BT601:
> +return OVL_EXDMA_CON_INT_MTX_BT601_TO_RGB;
> +}
> +}
> +
> +void mtk_disp_exdma_start(struct device *dev, struct cmdq_pkt *cmdq_pkt)
> +{
> +struct mtk_disp_exdma *priv = dev_get_drvdata(dev);
> +unsigned int value = 0, mask = 0;
It's not necessary to initialize these variable.
> +
> +value = OVL_EXDMA_RDMA_BURST_CON1_BURST16_EN | OVL_EXDMA_RDMA_BURST_CON1_DDR_ACK_EN;
> +mask = OVL_EXDMA_RDMA_BURST_CON1_BURST16_EN | OVL_EXDMA_RDMA_BURST_CON1_DDR_EN |
> + OVL_EXDMA_RDMA_BURST_CON1_DDR_ACK_EN;
It seems that you clear OVL_EXDMA_RDMA_BURST_CON1_DDR_EN. Describe why you clear it.
> +mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_RDMA_BURST_CON1, mask);
> +/*
> + * The dummy register is used in the configuration of the EXDMA engine to
> + * write commands to DRAM, ensuring that data transfers occur normally.
EXDMA would write data into DRAM? Describe more clear so I could understand this.
> + */
> +value = OVL_EXDMA_EXT_DDR_EN_OPT | OVL_EXDMA_FORCE_EXT_DDR_EN;
> +mask = OVL_EXDMA_EXT_DDR_EN_OPT | OVL_EXDMA_FORCE_EXT_DDR_EN;
mask is identical to value, so just use value.
> +mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_DUMMY_REG, mask);
> +
> +value = OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN |
> +OVL_EXDMA_DATAPATH_CON_HDR_GCLAST_EN |
> +OVL_EXDMA_DATAPATH_CON_GCLAST_EN;
> +mask = OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN |
> + OVL_EXDMA_DATAPATH_CON_HDR_GCLAST_EN |
> + OVL_EXDMA_DATAPATH_CON_GCLAST_EN;
> +mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_DATAPATH_CON, mask);
> +
> +mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_MOUT_BGCLR_OUT, &priv->cmdq_reg,
> + priv->regs, DISP_REG_OVL_EXDMA_MOUT,
> + OVL_EXDMA_MOUT_BGCLR_OUT | OVL_EXDMA_MOUT_OUT_DATA);
> +
> +mtk_ddp_write(cmdq_pkt, ~0, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_EXDMA_GDRDY_PRD);
> +
> +mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_RDMA0_EN, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_RDMA0_CTRL, OVL_EXDMA_RDMA0_EN);
EXDMA has layer config function, and RDMA would enable/disable by layer, so move OVL_EXDMA_RDMA0_EN config to layer config function.
> +mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_L0_EN, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_L0_EN, OVL_EXDMA_L0_EN);
EXDMA has layer config function, and L0 would enable/disable by layer, so move OVL_EXDMA_L0_EN config to layer config function.
> +
> +mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_EN, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_EN, OVL_EXDMA_EN);
> +}
> +
> +void mtk_disp_exdma_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt)
> +{
> +struct mtk_disp_exdma *priv = dev_get_drvdata(dev);
> +
> +mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_EN, OVL_EXDMA_EN);
> +mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_RDMA0_CTRL, OVL_EXDMA_RDMA0_EN);
> +mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_DATAPATH_CON, OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN);
> +mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_L0_EN, OVL_EXDMA_L0_EN);
> +mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_RST, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_RST, OVL_EXDMA_RST);
> +mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_RST, OVL_EXDMA_RST);
> +}
> +
> +void mtk_disp_exdma_layer_config(struct device *dev, struct mtk_plane_state *state,
> + struct cmdq_pkt *cmdq_pkt)
> +{
> +struct mtk_disp_exdma *priv = dev_get_drvdata(dev);
> +struct mtk_plane_pending_state *pending = &state->pending;
> +const struct drm_format_info *fmt_info = drm_format_info(pending->format);
> +unsigned int align_width = 0;
> +bool csc_enable = (fmt_info) ? fmt_info->is_yuv : false;
> +unsigned int blend_mode = mtk_ovl_get_blend_mode(state,
> + BIT(DRM_MODE_BLEND_PREMULTI) |
> + BIT(DRM_MODE_BLEND_COVERAGE) |
> + BIT(DRM_MODE_BLEND_PIXEL_NONE));
> +unsigned int val = 0;
It's not necessary to initialize val.
> +unsigned int clrfmt_mask = OVL_EXDMA_CON_RGB_SWAP |
> + OVL_EXDMA_CON_BYTE_SWAP |
> + OVL_EXDMA_CON_CLRFMT_MAN |
> + OVL_EXDMA_CON_FLD_CLRFMT |
> + OVL_EXDMA_CON_FLD_CLRFMT_NB;
> +
> +if (!pending->enable) {
> +mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_RDMA0_CTRL, OVL_EXDMA_RDMA0_EN);
> +mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_L0_EN, OVL_EXDMA_L0_EN);
> +return;
> +}
> +
> +/* OVLSYS is in 1T2P domain, width needs to be 2 pixels align */
> +align_width = ALIGN_DOWN(pending->width, 2);
If width is 101, change width to 100 would get correct display output?
> +
> +mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
> + priv->regs, DISP_REG_OVL_EXDMA_ROI_SIZE);
> +
> +mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
> + priv->regs, DISP_REG_OVL_EXDMA_SRC_SIZE);
> +mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
> + priv->regs, DISP_REG_OVL_EXDMA_SRC_SIZE);
Why do you duplicate DISP_REG_OVL_EXDMA_SRC_SIZE register setting?
> +
> +mtk_ddp_write_mask(cmdq_pkt, pending->pitch, &priv->cmdq_reg,
> + priv->regs, DISP_REG_OVL_EXDMA_PITCH, OVL_EXDMA_L0_SRC_PITCH_MASK);
> +mtk_ddp_write_mask(cmdq_pkt, pending->pitch >> 16, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_PITCH_MSB, 0xf);
Symbolize 0xf.
> +
> +val = mtk_disp_exdma_color_convert(pending->color_encoding);
> +if (csc_enable)
> +val |= OVL_EXDMA_CON_INT_MTX_EN;
> +mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_EXDMA_CON,
> + OVL_EXDMA_CON_FLD_INT_MTX_SEL | OVL_EXDMA_CON_INT_MTX_EN);
You have no way to disable csc.
If first frame is YUV format, you enable csc.
And second frame is RGB, you does not disable csc, so RGB would do csc and display incorrect result.
> +
> +val = mtk_ovl_fmt_convert(pending->format, blend_mode, true, false, 0,
> + OVL_EXDMA_CON_CLRFMT_MAN, OVL_EXDMA_CON_BYTE_SWAP,
> + OVL_EXDMA_CON_RGB_SWAP);
> +if (mtk_ovl_is_10bit_rgb(pending->format))
> +val |= OVL_EXDMA_CON_CLRFMT_NB_10_BIT;
> +mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_L0_CLRFMT, clrfmt_mask);
> +
> +val = OVL_EXDMA_HG_FOVL_EXDMA_CK_ON | OVL_EXDMA_HF_FOVL_EXDMA_CK_ON |
Does CK_ON mean clock on? If so, where do you turn off the clock?
> +OVL_EXDMA_OP_8BIT_MODE;
> +mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_EN_CON, val);
> +
> +val = OVL_EXDMA_RDMA0_L0_VCSEL | OVL_EXDMA_RDMA0_HDR_L0_VCSEL;
> +mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_L0_GUSER_EXT, val);
> +
> +val = pending->pitch;
> +if (mtk_ovl_is_ignore_pixel_alpha(state, blend_mode))
> +val |= OVL_EXDMA_L0_CONST_BLD;
> +mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_EXDMA_PITCH,
> + OVL_EXDMA_L0_CONST_BLD | OVL_EXDMA_L0_SRC_PITCH);
> +}
> +
> +const u32 *mtk_disp_exdma_get_formats(struct device *dev)
> +{
> +return formats;
> +}
> +
> +size_t mtk_disp_exdma_get_num_formats(struct device *dev)
> +{
> +return ARRAY_SIZE(formats);
> +}
> +
> +int mtk_disp_exdma_clk_enable(struct device *dev)
> +{
> +struct mtk_disp_exdma *exdma = dev_get_drvdata(dev);
> +
> +return clk_prepare_enable(exdma->clk);
> +}
> +
> +void mtk_disp_exdma_clk_disable(struct device *dev)
> +{
> +struct mtk_disp_exdma *exdma = dev_get_drvdata(dev);
> +
> +clk_disable_unprepare(exdma->clk);
> +}
> +
> +static int mtk_disp_exdma_bind(struct device *dev, struct device *master,
> + void *data)
> +{
> +return 0;
> +}
> +
> +static void mtk_disp_exdma_unbind(struct device *dev, struct device *master,
> + void *data)
> +{
> +}
> +
> +static const struct component_ops mtk_disp_exdma_component_ops = {
> +.bind= mtk_disp_exdma_bind,
> +.unbind = mtk_disp_exdma_unbind,
> +};
> +
> +static int mtk_disp_exdma_probe(struct platform_device *pdev)
> +{
> +struct device *dev = &pdev->dev;
> +struct platform_device *larb_pdev = NULL;
> +struct device_node *larb_node = NULL;
> +struct resource *res;
> +struct mtk_disp_exdma *priv;
> +int ret = 0;
> +
> +priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +if (!priv)
> +return -ENOMEM;
> +
> +res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +priv->regs = devm_ioremap_resource(dev, res);
> +if (IS_ERR(priv->regs)) {
> +dev_err(dev, "failed to ioremap exdma\n");
> +return PTR_ERR(priv->regs);
> +}
> +
> +priv->clk = devm_clk_get(dev, NULL);
> +if (IS_ERR(priv->clk)) {
> +dev_err(dev, "failed to get exdma clk\n");
> +return PTR_ERR(priv->clk);
> +}
> +
> +larb_node = of_parse_phandle(dev->of_node, "mediatek,larb", 0);
> +if (larb_node) {
> +larb_pdev = of_find_device_by_node(larb_node);
> +if (larb_pdev)
> +priv->larb = &larb_pdev->dev;
> +of_node_put(larb_node);
> +}
> +
> +if (!priv->larb) {
> +dev_dbg(dev, "not find larb dev");
> +return -EPROBE_DEFER;
> +}
> +device_link_add(dev, priv->larb, DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
> +
> +#if IS_REACHABLE(CONFIG_MTK_CMDQ)
> +ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
You does not define cmdq client reg in binding document, so it seems this series depend on some cmdq series.
Add the dependency information in cover letter.
> +if (ret)
> +dev_dbg(dev, "No mediatek,gce-client-reg\n");
> +#endif
> +platform_set_drvdata(pdev, priv);
> +
> +pm_runtime_enable(dev);
> +
> +ret = component_add(dev, &mtk_disp_exdma_component_ops);
> +if (ret != 0) {
> +pm_runtime_disable(dev);
> +dev_err(dev, "Failed to add component: %d\n", ret);
> +}
> +return ret;
> +}
> +
> +static void mtk_disp_exdma_remove(struct platform_device *pdev)
> +{
> +component_del(&pdev->dev, &mtk_disp_exdma_component_ops);
> +pm_runtime_disable(&pdev->dev);
> +}
> +
> +static const struct of_device_id mtk_disp_exdma_driver_dt_match[] = {
> +{ .compatible = "mediatek,mt8196-exdma", },
> +{},
> +};
> +MODULE_DEVICE_TABLE(of, mtk_disp_exdma_driver_dt_match);
> +
> +struct platform_driver mtk_disp_exdma_driver = {
> +.probe = mtk_disp_exdma_probe,
> +.remove = mtk_disp_exdma_remove,
> +.driver = {
> +.name = "mediatek-disp-exdma",
> +.owner = THIS_MODULE,
> +.of_match_table = mtk_disp_exdma_driver_dt_match,
> +},
> +};
> +
> +MODULE_AUTHOR("Nancy Lin <nancy.lin@mediatek.com>");
> +MODULE_DESCRIPTION("MediaTek Exdma Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index 74158b9d6503..bb7306a942ff 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -1276,6 +1276,7 @@ static struct platform_driver * const mtk_drm_drivers[] = {
> &mtk_disp_aal_driver,
> &mtk_disp_ccorr_driver,
> &mtk_disp_color_driver,
> +&mtk_disp_exdma_driver,
> &mtk_disp_gamma_driver,
> &mtk_disp_merge_driver,
> &mtk_disp_ovl_adaptor_driver,
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> index 675cdc90a440..898a75898775 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> @@ -72,6 +72,7 @@ struct mtk_drm_private {
> extern struct platform_driver mtk_disp_aal_driver;
> extern struct platform_driver mtk_disp_ccorr_driver;
> extern struct platform_driver mtk_disp_color_driver;
> +extern struct platform_driver mtk_disp_exdma_driver;
> extern struct platform_driver mtk_disp_gamma_driver;
> extern struct platform_driver mtk_disp_merge_driver;
> extern struct platform_driver mtk_disp_ovl_adaptor_driver;
</pre>
</p></body></html><!--type:text--><!--{--><pre>************* MEDIATEK Confidentiality Notice ********************
The information contained in this e-mail message (including any
attachments) may be confidential, proprietary, privileged, or otherwise
exempt from disclosure under applicable laws. It is intended to be
conveyed only to the designated recipient(s). Any use, dissemination,
distribution, printing, retaining or copying of this e-mail (including its
attachments) by unintended recipient(s) is strictly prohibited and may
be unlawful. If you are not an intended recipient of this e-mail, or believe
that you have received this e-mail in error, please notify the sender
immediately (by replying to this e-mail), delete any and all copies of
this e-mail (including any attachments) from your system, and do not
disclose the content of this e-mail to any other person. Thank you!
</pre><!--}-->