<html><body><p>
<pre>
Hi, Paul:
On Fri, 2025-01-10 at 20:34 +0800, paul-pl.chen wrote:
> From: "Nancy.Lin" <nancy.lin@mediatek.com>
>
> OUTPROC handles the post-stage of pixel processing in
> the overlapping procedure.OUTPROC manages pixels for
> gamma correction and ensures that pixel values are
> within the correct range.
>
> 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 | 14 ++
> drivers/gpu/drm/mediatek/mtk_disp_outproc.c | 244 ++++++++++++++++++++
> drivers/gpu/drm/mediatek/mtk_disp_outproc.h | 22 ++
> drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 +
> drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 +
> 8 files changed, 285 insertions(+)
> create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_outproc.c
> create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_outproc.h
>
> diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
> index a7b9ebe27f68..9546bc6b7b2e 100644
> --- a/drivers/gpu/drm/mediatek/Makefile
> +++ b/drivers/gpu/drm/mediatek/Makefile
> @@ -10,6 +10,7 @@ mediatek-drm-y := mtk_crtc.o \
> mtk_disp_gamma.o \
> mtk_disp_merge.o \
> mtk_disp_ovl.o \
> + mtk_disp_outproc.o \
> mtk_disp_ovl_adaptor.o \
> mtk_disp_rdma.o \
> mtk_drm_drv.o \
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> index e65c6df987f2..cc780744f060 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> @@ -447,6 +447,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
> [MTK_DSI] = "dsi",
> [MTK_OVL_BLENDER] = "blender",
> [MTK_OVL_EXDMA] = "exdma",
> +[MTK_OVL_OUTPROC] = "outproc",
> };
>
> 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 075ba5683f93..b33d3289b8b6 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> @@ -45,6 +45,7 @@ enum mtk_ddp_comp_type {
> MTK_DSI,
> MTK_OVL_BLENDER,
> MTK_OVL_EXDMA,
> +MTK_OVL_OUTPROC,
> 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 719191f05b27..44d2cbe919dc 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> @@ -64,6 +64,20 @@ 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);
>
> +void mtk_disp_outproc_start(struct device *dev);
> +void mtk_disp_outproc_stop(struct device *dev);
> +int mtk_disp_outproc_clk_enable(struct device *dev);
> +void mtk_disp_outproc_clk_disable(struct device *dev);
> +void mtk_disp_outproc_config(struct device *dev, unsigned int w,
> + unsigned int h, unsigned int vrefresh,
> + unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
> +void mtk_disp_outproc_register_vblank_cb(struct device *dev,
> + void (*vblank_cb)(void *),
> + void *vblank_cb_data);
> +void mtk_disp_outproc_unregister_vblank_cb(struct device *dev);
> +void mtk_disp_outproc_enable_vblank(struct device *dev);
> +void mtk_disp_outproc_disable_vblank(struct device *dev);
> +
> void mtk_dpi_start(struct device *dev);
> void mtk_dpi_stop(struct device *dev);
> unsigned int mtk_dpi_encoder_index(struct device *dev);
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_outproc.c b/drivers/gpu/drm/mediatek/mtk_disp_outproc.c
> new file mode 100644
> index 000000000000..af473eb2fb77
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_outproc.c
> @@ -0,0 +1,244 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2021 MediaTek Inc.
> + */
> +
> +#include <drm/drm_fourcc.h>
> +#include <drm/drm_framebuffer.h>
> +#include <linux/clk.h>
> +#include <linux/component.h>
> +#include <linux/of_device.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset.h>
> +#include <linux/soc/mediatek/mtk-cmdq.h>
> +#include <linux/soc/mediatek/mtk-mmsys.h>
> +
> +#include "mtk_crtc.h"
> +#include "mtk_ddp_comp.h"
> +#include <linux/of.h>
> +#include "mtk_drm_drv.h"
> +#include "mtk_disp_outproc.h"
> +
> +#define DISP_REG_OVL_OUTPROC_INTEN0x004
> +#define OVL_OUTPROC_FME_CPL_INTENBIT(1)
> +#define DISP_REG_OVL_OUTPROC_INTSTA0x008
> +#define DISP_REG_OVL_OUTPROC_DATAPATH_CON0x010
> +#define DATAPATH_CON_OUTPUT_CLAMPBIT(26)
> +
> +#define DISP_REG_OVL_OUTPROC_EN0x020
> +#define OVL_OUTPROC_OVL_ENBIT(0)
> +#define DISP_REG_OVL_OUTPROC_RST0x024
> +#define OVL_OUTPROC_RSTBIT(0)
> +#define DISP_REG_OVL_OUTPROC_SHADOW_CTRL0x028
> +#define OVL_OUTPROC_BYPASS_SHADOWBIT(2)
> +#define DISP_REG_OVL_OUTPROC_ROI_SIZE0x030
> +
> +struct mtk_disp_outproc {
> +void __iomem*regs;
> +struct clk*clk;
> +void(*vblank_cb)(void *data);
> +void*vblank_cb_data;
> +intirq;
> +struct cmdq_client_regcmdq_reg;
> +};
> +
> +void mtk_disp_outproc_register_vblank_cb(struct device *dev,
> + void (*vblank_cb)(void *),
> + void *vblank_cb_data)
> +{
> +struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> +priv->vblank_cb = vblank_cb;
> +priv->vblank_cb_data = vblank_cb_data;
> +}
> +
> +void mtk_disp_outproc_unregister_vblank_cb(struct device *dev)
> +{
> +struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> +priv->vblank_cb = NULL;
> +priv->vblank_cb_data = NULL;
> +}
> +
> +void mtk_disp_outproc_enable_vblank(struct device *dev)
> +{
> +struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> +writel(OVL_OUTPROC_FME_CPL_INTEN, priv->regs + DISP_REG_OVL_OUTPROC_INTEN);
> +}
> +
> +void mtk_disp_outproc_disable_vblank(struct device *dev)
> +{
> +struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> +writel(0x0, priv->regs + DISP_REG_OVL_OUTPROC_INTEN);
> +}
> +
> +static irqreturn_t mtk_disp_outproc_irq_handler(int irq, void *dev_id)
> +{
> +struct mtk_disp_outproc *priv = dev_id;
> +
> +writel(0x0, priv->regs + DISP_REG_OVL_OUTPROC_INTSTA);
> +
> +if (!priv->vblank_cb)
> +return IRQ_NONE;
> +
> +priv->vblank_cb(priv->vblank_cb_data);
> +
> +return IRQ_HANDLED;
> +}
> +
> +void mtk_disp_outproc_config(struct device *dev, unsigned int w,
> + unsigned int h, unsigned int vrefresh,
> + unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
> +{
> +struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +unsigned int tmp;
> +
> +dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
> +
> +tmp = readl(priv->regs + DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
> +tmp = tmp | OVL_OUTPROC_BYPASS_SHADOW;
> +writel(tmp, priv->regs + DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
Move bypass shadow to mtk_disp_outproc_start().
> +
> +mtk_ddp_write_mask(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_ROI_SIZE, ~0);
mtk_ddp_write();
> +mtk_ddp_write_mask(cmdq_pkt, DATAPATH_CON_OUTPUT_CLAMP, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_DATAPATH_CON, DATAPATH_CON_OUTPUT_CLAMP);
> +}
> +
> +void mtk_disp_outproc_start(struct device *dev)
> +{
> +struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> +mtk_ddp_write_mask(NULL, OVL_OUTPROC_RST, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_RST, OVL_OUTPROC_RST);
writel();
> +mtk_ddp_write_mask(NULL, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_RST, OVL_OUTPROC_RST);
Some hardware reset before start.
Some hardware reset after stop.
Could align this?
> +mtk_ddp_write(NULL, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_INTSTA);
> +mtk_ddp_write_mask(NULL, OVL_OUTPROC_OVL_EN, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_EN, OVL_OUTPROC_OVL_EN);
> +}
> +
> +void mtk_disp_outproc_stop(struct device *dev)
> +{
> +struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> +mtk_ddp_write(NULL, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_INTEN);
OVL driver does not disable interrupt when stop.
Align this with OVL driver.
> +mtk_ddp_write_mask(NULL, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_EN, OVL_OUTPROC_OVL_EN);
> +}
> +
> +int mtk_disp_outproc_clk_enable(struct device *dev)
> +{
> +struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> +return clk_prepare_enable(priv->clk);
> +}
> +
> +void mtk_disp_outproc_clk_disable(struct device *dev)
> +{
> +struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> +clk_disable_unprepare(priv->clk);
> +}
> +
> +static int mtk_disp_outproc_bind(struct device *dev, struct device *master,
> + void *data)
> +{
> +return 0;
> +}
> +
> +static void mtk_disp_outproc_unbind(struct device *dev, struct device *master, void *data)
> +{
> +}
> +
> +static const struct component_ops mtk_disp_outproc_component_ops = {
> +.bind= mtk_disp_outproc_bind,
> +.unbind = mtk_disp_outproc_unbind,
> +};
> +
> +static int mtk_disp_outproc_probe(struct platform_device *pdev)
> +{
> +struct device *dev = &pdev->dev;
> +struct resource *res;
> +struct mtk_disp_outproc *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 outproc\n");
> +return PTR_ERR(priv->regs);
> +}
> +
> +priv->clk = devm_clk_get(dev, NULL);
> +if (IS_ERR(priv->clk)) {
> +dev_err(dev, "failed to get outproc clk\n");
> +return PTR_ERR(priv->clk);
> +}
> +
> +#if IS_REACHABLE(CONFIG_MTK_CMDQ)
> +ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
> +if (ret)
> +dev_dbg(dev, "No mediatek,gce-client-reg\n");
> +#endif
> +
> +if (of_property_read_u32_index(dev->of_node, "interrupts", 0, &ret)) {
> +dev_dbg(dev, "interrupts not defined\n");
In binding document, interrupt is required.
So return with error code.
> +} else {
> +priv->irq = platform_get_irq(pdev, 0);
> +if (priv->irq < 0)
> +priv->irq = 0;
In binding document, interrupt is required.
So return with error code.
Regards,
CK
> +
> +if (priv->irq) {
> +ret = devm_request_irq(dev, priv->irq, mtk_disp_outproc_irq_handler,
> + IRQF_TRIGGER_NONE, dev_name(dev), priv);
> +if (ret < 0) {
> +dev_err(dev, "Failed to request irq %d: %d\n", priv->irq, ret);
> +return ret;
> +}
> +}
> +}
> +
> +platform_set_drvdata(pdev, priv);
> +
> +ret = component_add(dev, &mtk_disp_outproc_component_ops);
> +if (ret)
> +dev_notice(dev, "Failed to add component: %d\n", ret);
> +
> +return ret;
> +}
> +
> +static void mtk_disp_outproc_remove(struct platform_device *pdev)
> +{
> +component_del(&pdev->dev, &mtk_disp_outproc_component_ops);
> +}
> +
> +static const struct of_device_id mtk_disp_outproc_driver_dt_match[] = {
> +{ .compatible = "mediatek,mt8196-outproc"},
> +{},
> +};
> +
> +MODULE_DEVICE_TABLE(of, mtk_disp_outproc_driver_dt_match);
> +
> +struct platform_driver mtk_disp_outproc_driver = {
> +.probe= mtk_disp_outproc_probe,
> +.remove= mtk_disp_outproc_remove,
> +.driver= {
> +.name= "mediatek-disp-outproc",
> +.owner= THIS_MODULE,
> +.of_match_table = mtk_disp_outproc_driver_dt_match,
> +},
> +};
> +
> +MODULE_AUTHOR("Nancy Lin <nancy.lin@mediatek.com>");
> +MODULE_DESCRIPTION("MediaTek Output processing Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_outproc.h b/drivers/gpu/drm/mediatek/mtk_disp_outproc.h
> new file mode 100644
> index 000000000000..22ee5d845eae
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_outproc.h
> @@ -0,0 +1,22 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2021 MediaTek Inc.
> + */
> +
> +#ifndef __MTK_DISP_OUTPROC_H__
> +#define __MTK_DISP_OUTPROC_H__
> +
> +void mtk_disp_outproc_start(struct device *dev);
> +void mtk_disp_outproc_stop(struct device *dev);
> +int mtk_disp_outproc_clk_enable(struct device *dev);
> +void mtk_disp_outproc_clk_disable(struct device *dev);
> +void mtk_disp_outproc_config(struct device *dev, unsigned int w,
> + unsigned int h, unsigned int vrefresh,
> + unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
> +void mtk_disp_outproc_register_vblank_cb(struct device *dev,
> + void (*vblank_cb)(void *),
> + void *vblank_cb_data);
> +void mtk_disp_outproc_unregister_vblank_cb(struct device *dev);
> +void mtk_disp_outproc_enable_vblank(struct device *dev);
> +void mtk_disp_outproc_disable_vblank(struct device *dev);
> +#endif
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index e4a0d9fe4e2d..27190057bd8e 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -1265,6 +1265,7 @@ static struct platform_driver * const mtk_drm_drivers[] = {
> &mtk_disp_exdma_driver,
> &mtk_disp_gamma_driver,
> &mtk_disp_merge_driver,
> +&mtk_disp_outproc_driver,
> &mtk_disp_ovl_adaptor_driver,
> &mtk_disp_ovl_driver,
> &mtk_disp_rdma_driver,
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> index 89178de1478f..c4717c37b0f1 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> @@ -76,6 +76,7 @@ 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_outproc_driver;
> extern struct platform_driver mtk_disp_ovl_adaptor_driver;
> extern struct platform_driver mtk_disp_ovl_driver;
> extern struct platform_driver mtk_disp_rdma_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><!--}-->