<html><body><p>
<pre>
On Tue, 2025-06-17 at 09:17 +0000, CK Hu (胡俊光) wrote:
> On Thu, 2025-05-15 at 17:34 +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
>
> Drop this line.
>
> >
> > 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 | 349
> > ++++++++++++++++++++++
> >  drivers/gpu/drm/mediatek/mtk_drm_drv.c    |   1 +
> >  drivers/gpu/drm/mediatek/mtk_drm_drv.h    |   1 +
> >  7 files changed, 363 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..21a60e8f99c4
> > --- /dev/null
> > +++ b/drivers/gpu/drm/mediatek/mtk_disp_exdma.c
> > @@ -0,0 +1,349 @@
> > +// 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_L0_OFFSET0x044
> > +#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
> > OVL_EXDMA_L0_SRC_PITCH_MSB_MASKGENMASK(3, 0)
> > +#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)
> > +#define OVL_EXDMA_MOUT_BGCLR_OUTBIT(1)
> > +
> > +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)
> > +{
>
> Remove parameter cmdq_pkt.
>
> >
Sure, I will remove the unused cmdq_pkt and refactor function:
mtk_disp_exdma_start()
> > +struct mtk_disp_exdma *priv = dev_get_drvdata(dev);
> > +unsigned int value = 0, mask = 0;
> > +
> > +/*
> > + * This configuration enables dynamic power switching
> > mechanism for EXDMA,
> > + * also known as "SRT mode".
> > + * Such configuration allows the system to achieve better
> > power efficiency.
> > + */
> > +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;
> > +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
> > + * signal ddren_request, and get ddren_ack before
> > accessing the DRAM to
> > + * ensure data transfers occur normally.
> > + * primarily functions as a DMA engine for reading data
> > from DRAM with
> > + * various DRAM footprints and data formats.
> > + */
> > +value = OVL_EXDMA_EXT_DDR_EN_OPT |
> > OVL_EXDMA_FORCE_EXT_DDR_EN;
> > +
> > +mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv-
> > >regs,
> > +   DISP_REG_OVL_EXDMA_DUMMY_REG, value);
> > +
> > +value = 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,
> > value);
> > +
> > +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);
> > +
> > +value = OVL_EXDMA_HG_FOVL_EXDMA_CK_ON |
> > OVL_EXDMA_HF_FOVL_EXDMA_CK_ON |
> > +OVL_EXDMA_OP_8BIT_MODE;
> > +mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv-
> > >regs,
> > +   DISP_REG_OVL_EXDMA_EN_CON, value);
> > +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)
> > +{
>
> Remove parameter cmdq_pkt.
>
Sure, I will remove the unused NULL ptr and refactor function:
mtk_disp_exdma_stop()
>
>
> > +struct mtk_disp_exdma *priv = dev_get_drvdata(dev);
> > +unsigned int mask;
> > +
> > +mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv-
> > >regs,
> > +   DISP_REG_OVL_EXDMA_EN, OVL_EXDMA_EN);
> > +mask = OVL_EXDMA_HG_FOVL_EXDMA_CK_ON |
> > OVL_EXDMA_HF_FOVL_EXDMA_CK_ON |
> > +OVL_EXDMA_OP_8BIT_MODE;
> > +mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv-
> > >regs,
> > +   DISP_REG_OVL_EXDMA_EN_CON, mask);
> > +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, 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);
> > +bool csc_enable = (fmt_info) ? fmt_info->is_yuv : false;
> > +u32 blend_mode = mtk_ovl_get_blend_mode(state,
> > MTK_OVL_SUPPORT_BLEND_MODES);
> > +u32 val;
> > +
> > +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;
> > +}
> > +
> > +mtk_ddp_write(cmdq_pkt, pending->height << 16 | pending-
> > >width, &priv->cmdq_reg,
> > +      priv->regs, DISP_REG_OVL_EXDMA_ROI_SIZE);
> > +
> > +mtk_ddp_write(cmdq_pkt, pending->height << 16 | pending-
> > >width, &priv->cmdq_reg,
> > +      priv->regs, DISP_REG_OVL_EXDMA_SRC_SIZE);
> > +
> > +mtk_ddp_write(cmdq_pkt, pending->y << 16 | pending->x,
> > &priv->cmdq_reg, priv->regs,
> > +      DISP_REG_OVL_EXDMA_L0_OFFSET);
> > +mtk_ddp_write(cmdq_pkt, pending->addr, &priv->cmdq_reg,
> > +      priv->regs, DISP_REG_OVL_EXDMA_ADDR);
> > +
> > +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,
> > OVL_EXDMA_L0_SRC_PITCH_MSB_MASK);
> > +
> > +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);
> > +
> > +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,
> > +   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);
> > +
> > +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);
>
> You've set pitch in previous statement.
> So do not repeat setting pitch here.

> Regards,
> CK
>
Thanks for the review, I will refactor this part.

Best,
Paul

> > +
> > +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);
> > +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);
> > +}
> > +
>


</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><!--}-->