linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 00/17] Add MediaTek SoC DRM support for MT8196
@ 2025-05-15  9:34 paul-pl.chen
  2025-05-15  9:34 ` [PATCH v3 01/17] dt-bindings: soc: mediatek: add mutex yaml " paul-pl.chen
                   ` (16 more replies)
  0 siblings, 17 replies; 35+ messages in thread
From: paul-pl.chen @ 2025-05-15  9:34 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
  Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
	xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
	treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group

From: Paul-pl Chen <paul-pl.chen@mediatek.com>

This patch series adds support for the MediaTek MT8196 SoC's display
subsystem in the DRM driver.

Changes in v3:

- [PATCH v3 06/17] 
  Refine runtime PM, top clocks and async controls for MMSYS 
- [PATCH v3 08/17]
  Refactor SOF settings by adding mtk_mutex_get_output_comp_sof() and
  extracting SOF logic from mtk_mutex_add_comp() 
  and mtk_mutex_remove_comp()
- [PATCH v3 10/17]
  Export OVL format definitions and format 
  conversion API
- [PATCH v3 11/17]
  Export OVL ignore pixel alpha logic
- [PATCH v3 12/17] 
  Refactor exdma_config setup to reduce complexity 
  and consolidate duplicate settings in exdma_layer_config()
- [PATCH v3 13/17]
  Refine blender's layer_config driver for improved efficiency
- [PATCH v3 14/17] Refine outproc driver: use readl() and writel() to 
  replace mtk_ddp_write_mask() for normal mode settings
- [PATCH v3 15/17]
  Refine ovlsys_adaptor driver:Use path instead of ovl_adaptor_comp for 
  searching component type. Improve efficiency of config, start, stop, 
  and layer_config functions
- [PATCH v3 16/17] 
  Refine mtk_find_possible_crtcs() function

Changes in v2:
- add support for MT8196's new hardware components (EXDMA, BLENDER, 
  OUTPROC) following the previous MTK OVL software architecture.
- reuse mtk_ovl drivers in MediaTek DRM display to support the new 
  MT8196 SoC.
- implement support for multiple mmsys instances within a single 
  mediatek-drm driver, improving flexibility and scalability.
- refactor existing components (mutex, OVL) to accommodate the new 
  architecture and improve code reusability.
- update component matching, binding logic, and data structures to 
  support the new multi-mmsys design.
Nancy Lin (10):
  dt-bindings: soc: mediatek: add mutex yaml for MT8196
  soc: mediatek: Add runtime PM and top clocks and async controls for
    MMSYS
  soc: mediatek: add mmsys support for MT8196
  soc: mediatek: mutex: add mutex support for MT8196
  drm/mediatek: Export OVL formats definitions and format conversion API
  drm/mediatek: drm/mediatek: Export OVL ignore pixel alpha function
  drm/mediatek: add EXDMA support for MT8196
  drm/mediatek: add OUTPROC support for MT8196
  drm/mediatek: add ovlsys_adaptor support for MT8196
  drm/mediatek: Add support for MT8196 multiple mmsys

Paul-pl Chen (7):
  dt-bindings: display: mediatek: add EXDMA yaml for MT8196
  dt-bindings: display: mediatek: add BLENDER yaml for MT8196
  dt-bindings: display: mediatek: add OUTPROC yaml for MT8196
  soc: mediatek: mutex: Reused the switch case for SOF ID
  soc: mediatek: mutex: refactor SOF settings for output components
  drm/mediatek: add BLENDER support for MT8196
  drm/mediatek: Add support for multiple mmsys in the one mediatek-drm
    driver

 .../display/mediatek/mediatek,blender.yaml    |  47 ++
 .../display/mediatek/mediatek,outproc.yaml    |  54 ++
 .../bindings/dma/mediatek,exdma.yaml          |  68 ++
 .../bindings/soc/mediatek/mediatek,mutex.yaml |   2 +
 drivers/gpu/drm/mediatek/Makefile             |   4 +
 drivers/gpu/drm/mediatek/mtk_crtc.c           | 342 ++++++--
 drivers/gpu/drm/mediatek/mtk_crtc.h           |   6 +-
 drivers/gpu/drm/mediatek/mtk_ddp_comp.c       | 136 +++-
 drivers/gpu/drm/mediatek/mtk_ddp_comp.h       |   6 +
 drivers/gpu/drm/mediatek/mtk_disp_blender.c   | 264 +++++++
 drivers/gpu/drm/mediatek/mtk_disp_blender.h   |  10 +
 drivers/gpu/drm/mediatek/mtk_disp_drv.h       |  67 ++
 drivers/gpu/drm/mediatek/mtk_disp_exdma.c     | 349 +++++++++
 drivers/gpu/drm/mediatek/mtk_disp_outproc.c   | 240 ++++++
 drivers/gpu/drm/mediatek/mtk_disp_outproc.h   |  22 +
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c       | 238 +++---
 drivers/gpu/drm/mediatek/mtk_disp_ovl.h       |  29 +
 .../drm/mediatek/mtk_disp_ovlsys_adaptor.c    | 729 ++++++++++++++++++
 drivers/gpu/drm/mediatek/mtk_drm_drv.c        | 277 +++++--
 drivers/gpu/drm/mediatek/mtk_drm_drv.h        |  27 +-
 drivers/soc/mediatek/mt8196-mmsys.h           | 396 ++++++++++
 drivers/soc/mediatek/mtk-mmsys.c              | 206 ++++-
 drivers/soc/mediatek/mtk-mmsys.h              |  18 +
 drivers/soc/mediatek/mtk-mutex.c              | 257 ++++--
 include/linux/soc/mediatek/mtk-mmsys.h        |  60 ++
 include/linux/soc/mediatek/mtk-mutex.h        |   4 +
 26 files changed, 3555 insertions(+), 303 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,blender.yaml
 create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,outproc.yaml
 create mode 100644 Documentation/devicetree/bindings/dma/mediatek,exdma.yaml
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_blender.c
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_blender.h
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_exdma.c
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_outproc.c
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_outproc.h
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovl.h
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
 create mode 100644 drivers/soc/mediatek/mt8196-mmsys.h

-- 
2.45.2


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v3 01/17] dt-bindings: soc: mediatek: add mutex yaml for MT8196
  2025-05-15  9:34 [PATCH v3 00/17] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
@ 2025-05-15  9:34 ` paul-pl.chen
  2025-05-15  9:34 ` [PATCH v3 02/17] dt-bindings: display: mediatek: add EXDMA " paul-pl.chen
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 35+ messages in thread
From: paul-pl.chen @ 2025-05-15  9:34 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
  Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
	xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
	treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group,
	Krzysztof Kozlowski

From: Nancy Lin <nancy.lin@mediatek.com>

Add compatible string to support mutex for MT8196.

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
 .../devicetree/bindings/soc/mediatek/mediatek,mutex.yaml        | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml b/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml
index a10326a9683d..1be4e139a8b5 100644
--- a/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml
+++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml
@@ -36,6 +36,7 @@ properties:
       - mediatek,mt8188-vpp-mutex
       - mediatek,mt8192-disp-mutex
       - mediatek,mt8195-disp-mutex
+      - mediatek,mt8196-disp-mutex
       - mediatek,mt8195-vpp-mutex
       - mediatek,mt8365-disp-mutex
 
@@ -87,6 +88,7 @@ allOf:
               - mediatek,mt8186-mdp3-mutex
               - mediatek,mt8192-disp-mutex
               - mediatek,mt8195-disp-mutex
+              - mediatek,mt8196-disp-mutex
     then:
       required:
         - clocks
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v3 02/17] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
  2025-05-15  9:34 [PATCH v3 00/17] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
  2025-05-15  9:34 ` [PATCH v3 01/17] dt-bindings: soc: mediatek: add mutex yaml " paul-pl.chen
@ 2025-05-15  9:34 ` paul-pl.chen
  2025-05-15 10:48   ` Rob Herring (Arm)
  2025-06-26  9:10   ` CK Hu (胡俊光)
  2025-05-15  9:34 ` [PATCH v3 03/17] dt-bindings: display: mediatek: add BLENDER " paul-pl.chen
                   ` (14 subsequent siblings)
  16 siblings, 2 replies; 35+ messages in thread
From: paul-pl.chen @ 2025-05-15  9:34 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
  Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
	xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
	treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group

From: Paul-pl Chen <paul-pl.chen@mediatek.com>

Add mediatek,exdma.yaml to support EXDMA for MT8196.
The MediaTek display overlap extended DMA engine, namely
OVL_EXDMA or EXDMA, primarily functions as a DMA engine
for reading data from DRAM with various DRAM footprints
and data formats.

Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
 .../bindings/dma/mediatek,exdma.yaml          | 68 +++++++++++++++++++
 1 file changed, 68 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dma/mediatek,exdma.yaml

diff --git a/Documentation/devicetree/bindings/dma/mediatek,exdma.yaml b/Documentation/devicetree/bindings/dma/mediatek,exdma.yaml
new file mode 100644
index 000000000000..eabf0cfc839e
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/mediatek,exdma.yaml
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/dma/mediatek,exdma.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek display overlap extended DMA engine
+
+maintainers:
+  - Chun-Kuang Hu <chunkuang.hu@kernel.org>
+  - Philipp Zabel <p.zabel@pengutronix.de>
+
+description:
+  The MediaTek display overlap extended DMA engine, namely OVL_EXDMA or EXDMA,
+  primarily functions as 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, OVL_EXDMA also includes a color transfer function
+  to process pixels into a consistent color domain.
+
+properties:
+  compatible:
+    const: mediatek,mt8196-exdma
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+  mediatek,larb:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: |
+      A phandle to the local arbiters node in the current SoCs.
+      Refer to bindings/memory-controllers/mediatek,smi-larb.yaml.
+
+  iommus:
+    maxItems: 1
+
+  '#dma-cells':
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - power-domains
+  - mediatek,larb
+
+additionalProperties: false
+
+examples:
+  - |
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        exdma: dma-controller@32850000 {
+            compatible = "mediatek,mt8196-exdma";
+            reg = <0 0x32850000 0 0x1000>;
+            clocks = <&ovlsys_config_clk 13>;
+            power-domains = <&hfrpsys 12>;
+            iommus = <&mm_smmu 144>;
+            #dma-cells = <1>;
+        };
+    };
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v3 03/17] dt-bindings: display: mediatek: add BLENDER yaml for MT8196
  2025-05-15  9:34 [PATCH v3 00/17] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
  2025-05-15  9:34 ` [PATCH v3 01/17] dt-bindings: soc: mediatek: add mutex yaml " paul-pl.chen
  2025-05-15  9:34 ` [PATCH v3 02/17] dt-bindings: display: mediatek: add EXDMA " paul-pl.chen
@ 2025-05-15  9:34 ` paul-pl.chen
  2025-05-19  6:41   ` Krzysztof Kozlowski
  2025-05-15  9:34 ` [PATCH v3 04/17] dt-bindings: display: mediatek: add OUTPROC " paul-pl.chen
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 35+ messages in thread
From: paul-pl.chen @ 2025-05-15  9:34 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
  Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
	xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
	treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group,
	Krzysztof Kozlowski

From: Paul-pl Chen <paul-pl.chen@mediatek.com>

Add mediatek,blender.yaml to support BLENDER for MT8196.
MediaTek display overlap blender, namely OVL_BLENDER or BLENDER,
executes the alpha blending function for overlapping layers
from different sources.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
 .../display/mediatek/mediatek,blender.yaml    | 47 +++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,blender.yaml

diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,blender.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,blender.yaml
new file mode 100644
index 000000000000..4b85f6ac40a2
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,blender.yaml
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/mediatek/mediatek,blender.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek Display Overlap Blender
+
+maintainers:
+  - Chun-Kuang Hu <chunkuang.hu@kernel.org>
+  - Philipp Zabel <p.zabel@pengutronix.de>
+
+description:
+  MediaTek display overlap blender, namely OVL_BLENDER or BLENDER,
+  executes the alpha blending function for overlapping layers
+  from different sources. This is the primary function of the
+  overlapping system.
+
+properties:
+  compatible:
+    const: mediatek,mt8196-blender
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+
+additionalProperties: false
+
+examples:
+  - |
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        blender0: blender@328d0000 {
+            compatible = "mediatek,mt8196-blender";
+            reg = <0 0x328d0000 0 0x1000>;
+            clocks = <&ovlsys_config_clk 29>;
+        };
+    };
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v3 04/17] dt-bindings: display: mediatek: add OUTPROC yaml for MT8196
  2025-05-15  9:34 [PATCH v3 00/17] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
                   ` (2 preceding siblings ...)
  2025-05-15  9:34 ` [PATCH v3 03/17] dt-bindings: display: mediatek: add BLENDER " paul-pl.chen
@ 2025-05-15  9:34 ` paul-pl.chen
  2025-05-19  6:43   ` Krzysztof Kozlowski
  2025-05-15  9:34 ` [PATCH v3 05/17] soc: mediatek: Add runtime PM and top clocks and async controls for MMSYS paul-pl.chen
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 35+ messages in thread
From: paul-pl.chen @ 2025-05-15  9:34 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
  Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
	xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
	treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group

From: Paul-pl Chen <paul-pl.chen@mediatek.com>

Add mediate,outproc.yaml to support OUTPROC for MT8196.
MediaTek display overlap output processor, namely OVL_OUTPROC
or OUTPROC,handles the post-stage of pixel processing in the
overlapping procedure.

Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
 .../display/mediatek/mediatek,outproc.yaml    | 54 +++++++++++++++++++
 1 file changed, 54 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,outproc.yaml

diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,outproc.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,outproc.yaml
new file mode 100644
index 000000000000..1292e394faaa
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,outproc.yaml
@@ -0,0 +1,54 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/mediatek/mediatek,outproc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek display overlap output processor
+
+maintainers:
+  - Chun-Kuang Hu <chunkuang.hu@kernel.org>
+  - Philipp Zabel <p.zabel@pengutronix.de>
+
+description:
+  MediaTek display overlap output processor, namely OVL_OUTPROC or OUTPROC,
+  handles the post-stage of pixel processing in the overlapping procedure.
+  OVL_OUTPROC manages pixels for gamma correction and ensures that pixel
+  values are within the correct range.
+
+properties:
+  compatible:
+    const: mediatek,mt8196-outproc
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        outproc0: outproc@32970000 {
+            compatible = "mediatek,mt8196-outproc";
+            reg = <0 0x32970000 0 0x1000>;
+            clocks = <&ovlsys_config_clk 49>;
+            interrupts = <GIC_SPI 450 IRQ_TYPE_LEVEL_HIGH 0>;
+        };
+    };
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v3 05/17] soc: mediatek: Add runtime PM and top clocks and async controls for MMSYS
  2025-05-15  9:34 [PATCH v3 00/17] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
                   ` (3 preceding siblings ...)
  2025-05-15  9:34 ` [PATCH v3 04/17] dt-bindings: display: mediatek: add OUTPROC " paul-pl.chen
@ 2025-05-15  9:34 ` paul-pl.chen
  2025-05-15  9:34 ` [PATCH v3 06/17] soc: mediatek: add mmsys support for MT8196 paul-pl.chen
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 35+ messages in thread
From: paul-pl.chen @ 2025-05-15  9:34 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
  Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
	xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
	treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group

From: Nancy Lin <nancy.lin@mediatek.com>

- Add initialization of top clocks and async clocks for each MMSYS.
- Add PM runtime control and new functions to manage these clocks.
- Add functions to set these clocks according to the default
  configuration of the corresponding MMSYS.

Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
 drivers/soc/mediatek/mtk-mmsys.c       | 152 ++++++++++++++++++++++++-
 drivers/soc/mediatek/mtk-mmsys.h       |  18 +++
 include/linux/soc/mediatek/mtk-mmsys.h |   8 ++
 3 files changed, 177 insertions(+), 1 deletion(-)

diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c
index bb4639ca0b8c..f448cc09ce19 100644
--- a/drivers/soc/mediatek/mtk-mmsys.c
+++ b/drivers/soc/mediatek/mtk-mmsys.c
@@ -4,12 +4,15 @@
  * Author: James Liao <jamesjj.liao@mediatek.com>
  */
 
+#include <linux/bitfield.h>
+#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/reset-controller.h>
 #include <linux/soc/mediatek/mtk-mmsys.h>
 
@@ -158,6 +161,9 @@ struct mtk_mmsys {
 	spinlock_t lock; /* protects mmsys_sw_rst_b reg */
 	struct reset_controller_dev rcdev;
 	struct cmdq_client_reg cmdq_base;
+	struct clk **async_clk;
+	int num_async_clk;
+	struct clk **top_clk;
 };
 
 static void mtk_mmsys_update_bits(struct mtk_mmsys *mmsys, u32 offset, u32 mask, u32 val,
@@ -180,6 +186,101 @@ static void mtk_mmsys_update_bits(struct mtk_mmsys *mmsys, u32 offset, u32 mask,
 	writel_relaxed(tmp, mmsys->regs + offset);
 }
 
+int mtk_mmsys_top_clk_enable(struct device *dev)
+{
+	struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
+	int ret, i;
+
+	if (!mmsys->data->num_top_clk)
+		return 0;
+
+	for (i = 0; i < mmsys->data->num_top_clk; i++)
+		ret = clk_prepare_enable(mmsys->top_clk[i]);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(mtk_mmsys_top_clk_enable);
+
+void mtk_mmsys_top_clk_disable(struct device *dev)
+{
+	struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
+	int i;
+
+	for (i = 0; i < mmsys->data->num_top_clk; i++)
+		clk_disable_unprepare(mmsys->top_clk[i]);
+}
+EXPORT_SYMBOL_GPL(mtk_mmsys_top_clk_disable);
+
+int mtk_mmsys_ddp_clk_enable(struct device *dev, enum mtk_ddp_comp_id comp_id)
+{
+	struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
+	const struct mtk_mmsys_async_info *async = mmsys->data->async_info;
+
+	int i;
+
+	if (!mmsys->data->num_async_info)
+		return 0;
+
+	for (i = 0; i < mmsys->data->num_async_info; i++)
+		if (comp_id == async[i].comp_id)
+			return clk_prepare_enable(mmsys->async_clk[async[i].index]);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_clk_enable);
+
+void mtk_mmsys_ddp_clk_disable(struct device *dev, enum mtk_ddp_comp_id comp_id)
+{
+	struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
+	const struct mtk_mmsys_async_info *async = mmsys->data->async_info;
+	int i;
+
+	if (!mmsys->data->num_async_info)
+		return;
+
+	for (i = 0; i < mmsys->data->num_async_info; i++)
+		if (comp_id == async[i].comp_id)
+			clk_disable_unprepare(mmsys->async_clk[async[i].index]);
+}
+EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_clk_disable);
+
+void mtk_mmsys_ddp_config(struct device *dev, enum mtk_ddp_comp_id comp_id,
+			  int width, int height, struct cmdq_pkt *cmdq_pkt)
+{
+	struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
+	const struct mtk_mmsys_async_info *async = mmsys->data->async_info;
+	int i;
+	u32 val;
+
+	if (!mmsys->data->num_async_info)
+		return;
+
+	for (i = 0; i < mmsys->data->num_async_info; i++)
+		if (comp_id == async[i].comp_id)
+			break;
+
+	if (i == mmsys->data->num_async_info)
+		return;
+
+	val = FIELD_PREP(GENMASK(31, 16), height);
+	val |= FIELD_PREP(GENMASK(15, 0), width);
+	mtk_mmsys_update_bits(mmsys, async[i].offset, async[i].mask, val, cmdq_pkt);
+}
+EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_config);
+
+void mtk_mmsys_default_config(struct device *dev)
+{
+	struct mtk_mmsys *mmsys = dev_get_drvdata(dev);
+	const struct mtk_mmsys_default *def_config = mmsys->data->def_config;
+	int i;
+
+	if (!mmsys->data->num_def_config)
+		return;
+
+	for (i = 0; i < mmsys->data->num_def_config; i++)
+		mtk_mmsys_update_bits(mmsys, def_config[i].offset, def_config[i].mask,
+				      def_config[i].val, NULL);
+}
+EXPORT_SYMBOL_GPL(mtk_mmsys_default_config);
+
 void mtk_mmsys_ddp_connect(struct device *dev,
 			   enum mtk_ddp_comp_id cur,
 			   enum mtk_ddp_comp_id next)
@@ -390,7 +491,7 @@ static int mtk_mmsys_probe(struct platform_device *pdev)
 	struct platform_device *clks;
 	struct platform_device *drm;
 	struct mtk_mmsys *mmsys;
-	int ret;
+	int ret, i;
 
 	mmsys = devm_kzalloc(dev, sizeof(*mmsys), GFP_KERNEL);
 	if (!mmsys)
@@ -432,6 +533,49 @@ static int mtk_mmsys_probe(struct platform_device *pdev)
 		return PTR_ERR(clks);
 	mmsys->clks_pdev = clks;
 
+	if (mmsys->data->num_top_clk) {
+		struct device_node *node;
+
+		node = of_get_child_by_name(dev->of_node, "top");
+		if (!node) {
+			dev_err(&pdev->dev, "Couldn't find top node\n");
+			return -EINVAL;
+		}
+
+		mmsys->top_clk = devm_kmalloc_array(dev, mmsys->data->num_top_clk,
+						    sizeof(*mmsys->top_clk), GFP_KERNEL);
+		if (!mmsys->top_clk)
+			return -ENOMEM;
+
+		for (i = 0; i < mmsys->data->num_top_clk; i++) {
+			mmsys->top_clk[i] = of_clk_get(node, i);
+			if (IS_ERR(mmsys->top_clk[i]))
+				return PTR_ERR(mmsys->top_clk[i]);
+		}
+	}
+
+	if (mmsys->data->num_async_info) {
+		struct device_node *node;
+
+		node = of_get_child_by_name(dev->of_node, "async");
+		if (!node) {
+			dev_err(&pdev->dev, "Couldn't find async node\n");
+			return -EINVAL;
+		}
+
+		mmsys->async_clk = devm_kmalloc_array(dev, mmsys->data->num_async_info,
+						      sizeof(*mmsys->async_clk), GFP_KERNEL);
+		if (!mmsys->async_clk)
+			return -ENOMEM;
+		mmsys->num_async_clk = mmsys->data->num_async_info;
+
+		for (i = 0; i < mmsys->num_async_clk; i++) {
+			mmsys->async_clk[i] = of_clk_get(node, i);
+			if (IS_ERR(mmsys->async_clk[i]))
+				return PTR_ERR(mmsys->async_clk[i]);
+		}
+	}
+
 	if (mmsys->data->is_vppsys)
 		goto out_probe_done;
 
@@ -443,6 +587,9 @@ static int mtk_mmsys_probe(struct platform_device *pdev)
 	}
 	mmsys->drm_pdev = drm;
 
+	if (of_property_present(dev->of_node, "power-domains"))
+		pm_runtime_enable(dev);
+
 out_probe_done:
 	return 0;
 }
@@ -453,6 +600,9 @@ static void mtk_mmsys_remove(struct platform_device *pdev)
 
 	platform_device_unregister(mmsys->drm_pdev);
 	platform_device_unregister(mmsys->clks_pdev);
+
+	if (of_property_present(pdev->dev.of_node, "power-domains"))
+		pm_runtime_disable(&pdev->dev);
 }
 
 static const struct of_device_id of_match_mtk_mmsys[] = {
diff --git a/drivers/soc/mediatek/mtk-mmsys.h b/drivers/soc/mediatek/mtk-mmsys.h
index fe628d5f5198..bbc03ef5b025 100644
--- a/drivers/soc/mediatek/mtk-mmsys.h
+++ b/drivers/soc/mediatek/mtk-mmsys.h
@@ -102,6 +102,19 @@ struct mtk_mmsys_routes {
 	u32 val;
 };
 
+struct mtk_mmsys_async_info {
+	u32 comp_id;
+	u32 index;
+	u32 offset;
+	u32 mask;
+};
+
+struct mtk_mmsys_default {
+	u32 offset;
+	u32 val;
+	u32 mask;
+};
+
 /**
  * struct mtk_mmsys_driver_data - Settings of the mmsys
  * @clk_driver: Clock driver name that the mmsys is using
@@ -139,6 +152,11 @@ struct mtk_mmsys_driver_data {
 	const u32 num_resets;
 	const bool is_vppsys;
 	const u8 vsync_len;
+	const struct mtk_mmsys_async_info *async_info;
+	const unsigned int num_async_info;
+	const struct mtk_mmsys_default *def_config;
+	const unsigned int num_def_config;
+	const unsigned int num_top_clk;
 };
 
 /*
diff --git a/include/linux/soc/mediatek/mtk-mmsys.h b/include/linux/soc/mediatek/mtk-mmsys.h
index 4885b065b849..f50f626e1840 100644
--- a/include/linux/soc/mediatek/mtk-mmsys.h
+++ b/include/linux/soc/mediatek/mtk-mmsys.h
@@ -84,6 +84,14 @@ enum mtk_ddp_comp_id {
 	DDP_COMPONENT_ID_MAX,
 };
 
+int mtk_mmsys_top_clk_enable(struct device *dev);
+void mtk_mmsys_top_clk_disable(struct device *dev);
+int mtk_mmsys_ddp_clk_enable(struct device *dev, enum mtk_ddp_comp_id comp_id);
+void mtk_mmsys_ddp_clk_disable(struct device *dev, enum mtk_ddp_comp_id comp_id);
+void mtk_mmsys_ddp_config(struct device *dev, enum mtk_ddp_comp_id comp_id,
+			  int width, int height, struct cmdq_pkt *cmdq_pkt);
+void mtk_mmsys_default_config(struct device *dev);
+
 void mtk_mmsys_ddp_connect(struct device *dev,
 			   enum mtk_ddp_comp_id cur,
 			   enum mtk_ddp_comp_id next);
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v3 06/17] soc: mediatek: add mmsys support for MT8196
  2025-05-15  9:34 [PATCH v3 00/17] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
                   ` (4 preceding siblings ...)
  2025-05-15  9:34 ` [PATCH v3 05/17] soc: mediatek: Add runtime PM and top clocks and async controls for MMSYS paul-pl.chen
@ 2025-05-15  9:34 ` paul-pl.chen
  2025-05-15  9:34 ` [PATCH v3 07/17] soc: mediatek: mutex: Reused the switch case for SOF ID paul-pl.chen
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 35+ messages in thread
From: paul-pl.chen @ 2025-05-15  9:34 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
  Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
	xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
	treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group

From: Nancy Lin <nancy.lin@mediatek.com>

Add driver data for MT8196 and add the routing table for each mmsys.

Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
 drivers/soc/mediatek/mt8196-mmsys.h    | 396 +++++++++++++++++++++++++
 drivers/soc/mediatek/mtk-mmsys.c       |  54 ++++
 include/linux/soc/mediatek/mtk-mmsys.h |  52 ++++
 3 files changed, 502 insertions(+)
 create mode 100644 drivers/soc/mediatek/mt8196-mmsys.h

diff --git a/drivers/soc/mediatek/mt8196-mmsys.h b/drivers/soc/mediatek/mt8196-mmsys.h
new file mode 100644
index 000000000000..63b14b446d08
--- /dev/null
+++ b/drivers/soc/mediatek/mt8196-mmsys.h
@@ -0,0 +1,396 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Nancy Lin <nancy.lin@mediatek.com>
+ */
+
+#ifndef __SOC_MEDIATEK_MT8196_MMSYS_H
+#define __SOC_MEDIATEK_MT8196_MMSYS_H
+
+/* DISPSYS1 */
+#define MT8196_COMP_OUT_CB6_MOUT_EN			0xd30
+#define MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB0		BIT(0)
+#define MT8196_COMP_OUT_CB7_MOUT_EN			0xd38
+#define MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB1		BIT(1)
+#define MT8196_COMP_OUT_CB8_MOUT_EN			0xd40
+#define MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB2		BIT(2)
+#define MT8196_MERGE_OUT_CB0_MOUT_EN			0xdcc
+#define MT8196_DISP_COMP_OUT_CB_TO_DVO0				BIT(9)
+#define MT8196_MERGE_OUT_CB1_MOUT_EN			0xdd4
+#define MT8196_MERGE_OUT_CB2_MOUT_EN			0xddc
+#define MT8196_DISP_COMP_OUT_CB_TO_DSI0				BIT(0)
+#define MT8196_DISP_COMP_OUT_CB_TO_DP_INTF0			BIT(10)
+#define MT8196_DISP_COMP_OUT_CB_TO_DP_INTF1			BIT(11)
+#define MT8196_SPLITTER_IN_CB1_MOUT_EN			0xeac
+#define MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB9		BIT(5)
+#define MT8196_SPLITTER_IN_CB2_MOUT_EN			0xeb4
+#define MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB10		BIT(6)
+#define MT8196_SPLITTER_IN_CB3_MOUT_EN			0xebc
+#define MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB11		BIT(7)
+#define MT8196_SPLITTER_OUT_CB9_MOUT_EN			0xf64
+#define MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB6		BIT(10)
+#define MT8196_SPLITTER_OUT_CB10_MOUT_EN		0xf6c
+#define MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB7		BIT(11)
+#define MT8196_SPLITTER_OUT_CB11_MOUT_EN		0xf74
+#define MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB8		BIT(12)
+#define MT8196_OVL_RSZ_IN_CB2_MOUT_EN			0xf70
+#define MT8196_DISP_OVL_EXDMA2_1_TO_OVL_EXDMA_OUT_CB3		BIT(1)
+
+/* OVLSYS */
+#define MT8196_OVL_BLENDER_OUT_CB4_MOUT_EN		0xe10
+#define MT8196_OVL_BLENDER_OUT_CB8_MOUT_EN		0xe20
+#define MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC0		BIT(0)
+#define MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC1		BIT(1)
+#define MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC2		BIT(2)
+#define MT8196_OVL_EXDMA_OUT_CB2_MOUT_EN		0xe60
+#define MT8196_OVL_EXDMA_OUT_CB3_MOUT_EN		0xe68
+#define MT8196_OVL_EXDMA_OUT_CB4_MOUT_EN		0xe70
+#define MT8196_OVL_EXDMA_OUT_CB5_MOUT_EN		0xe78
+#define MT8196_OVL_EXDMA_OUT_CB6_MOUT_EN		0xe80
+#define MT8196_OVL_EXDMA_OUT_CB7_MOUT_EN		0xe88
+#define MT8196_OVL_EXDMA_OUT_CB8_MOUT_EN		0xe90
+#define MT8196_OVL_EXDMA_OUT_CB9_MOUT_EN		0xe98
+#define MT8196_OVL_EXDMA_OUT_CB10_MOUT_EN		0xea0
+#define MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER1		BIT(2)
+#define MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER2		BIT(3)
+#define MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER3		BIT(4)
+#define MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER4		BIT(5)
+#define MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER5		BIT(6)
+#define MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER6		BIT(7)
+#define MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER7		BIT(8)
+#define MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER8		BIT(9)
+#define MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER9		BIT(10)
+#define MT8196_OVL_OUTPROC_OUT_CB0_MOUT_EN		0xf10
+#define MT8196_OVL_OUTPROC_OUT_CB1_MOUT_EN		0xf14
+#define MT8196_OVL_OUTPROC_OUT_CB2_MOUT_EN		0xf18
+#define MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY5		BIT(0)
+#define MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY6		BIT(1)
+#define MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY7		BIT(2)
+
+/* DISPSYS0 */
+#define MT8196_PANEL_COMP_OUT_CB1_MOUT_EN		0xd84
+#define MT8196_DISP_TO_DLO_RELAY1				BIT(1)
+#define MT8196_PANEL_COMP_OUT_CB2_MOUT_EN		0xd88
+#define MT8196_DISP_TO_DLO_RELAY2				BIT(2)
+#define MT8196_PANEL_COMP_OUT_CB3_MOUT_EN		0xd8c
+#define MT8196_DISP_TO_DLO_RELAY3				BIT(3)
+#define MT8196_PQ_IN_CB0_MOUT_EN			0xdd0
+#define MT8196_PQ_IN_CB0_TO_PQ_OUT_CB_6				BIT(2)
+
+#define MT8196_PQ_IN_CB1_MOUT_EN			0xdd4
+#define MT8196_PQ_IN_CB1_TO_PQ_OUT_CB_7				BIT(3)
+#define MT8196_PQ_IN_CB8_MOUT_EN			0xdf0
+#define MT8196_PQ_IN_CB8_TO_PQ_OUT_CB_8				BIT(4)
+#define MT8196_PQ_OUT_CB6_MOUT_EN			0xe54
+#define MT8196_PQ_OUT_CB6_TO_PANEL0_COMP_OUT_CB1		BIT(1)
+#define MT8196_PQ_OUT_CB7_MOUT_EN			0xe58
+#define MT8196_PQ_OUT_CB7_TO_PANEL0_COMP_OUT_CB2		BIT(2)
+#define MT8196_PQ_OUT_CB8_MOUT_EN			0xe5c
+#define MT8196_PQ_OUT_CB8_TO_PANEL0_COMP_OUT_CB3		BIT(3)
+
+/* OVLSYS config */
+#define MT8196_OVL_INT_MERGE				0x008
+#define MT8196_OVL_DL_OUT_RELAY5_SIZE			0x29c
+#define MT8196_OVL_DL_OUT_RELAY6_SIZE			0x2a0
+#define MT8196_OVLSYS_GCE_EVENT_SEL			0x408
+#define MT8196_OVLSYS_BYPASS_MUX_SHADOW			0xca0
+#define MT8196_OVLSYS_CB_CON				0xcac
+#define MT8196_CB_BYPASS_MUX_SHADOW				(0xff << 16)
+#define MT8196_EVENT_GCE_EN					(BIT(0) | BIT(1))
+
+/* DISPSYS config */
+#define MT8196_DISP0_DLI_RELAY0				0x200
+#define MT8196_DISP0_DLI_RELAY1				0x204
+#define MT8196_DISP0_DLI_RELAY8				0x220
+#define MT8196_DISP0_DLO_RELAY1				0x268
+#define MT8196_DISP0_DLO_RELAY2				0x26c
+#define MT8196_DISP0_DLO_RELAY3				0x270
+#define MT8196_DLI_RELAY_1T2P					BIT(30)
+#define MT8196_DISP0_BYPASS_MUX_SHADOW			0xc30
+#define MT8196_BYPASS_MUX_SHADOW				BIT(0)
+#define MT8196_OVLSYS_CB_BYPASS_MUX_SHADOW			(0xff << 16)
+
+/* DISPSYS1 config */
+#define MT8196_DISP1_INT_MERGE				0x008
+#define MT8196_DISP1_DLI_RELAY21			0x204
+#define MT8196_DISP1_DLI_RELAY22			0x208
+#define MT8196_DISP1_DLI_RELAY23			0x20c
+#define MT8196_DISP1_GCE_FRAME_DONE_SEL0		0xa10
+#define MT8196_DISP1_GCE_FRAME_DONE_SEL1		0xa14
+#define MT8196_FRAME_DONE_DVO					25
+#define MT8196_FRAME_DONE_DP_INTF0				41
+#define MT8196_DISP1_BYPASS_MUX_SHADOW			0xcf8
+
+/* VDISP_AO config */
+#define MT8196_VDISP_AO_REG_INTEN			0x000
+#define MT8196_CPU_INTEN					BIT(0)
+#define MT8196_CPU_INT_MERGE					BIT(4)
+#define MT8196_VDISP_AO_REG_INT_SEL_G0			0x020
+#define MT8196_VDISP_AO_REG_INT_SEL_G1			0x024
+#define MT8196_VDISP_AO_REG_INT_SEL_G2			0x028
+#define MT8196_VDISP_AO_REG_INT_SEL_G3			0x02c
+#define MT8196_VDISP_AO_REG_INT_SEL_G4			0x030
+#define MT8196_VDISP_AO_REG_INT_SEL_G5			0x034
+#define MT8196_VDISP_AO_REG_INT_SEL_G6			0x038
+#define MT8196_IRQ_TABLE_OVL0_OUTPROC0				(0xa6) /* GIC 450 */
+#define MT8196_IRQ_TABLE_OVL0_OUTPROC1				(0xa7) /* GIC 451 */
+#define MT8196_IRQ_TABLE_OVL1_OUTPROC0				(0xd6) /* GIC 452 */
+#define MT8196_IRQ_TABLE_DSI0					(0x35) /* GIC 453 */
+
+static const struct mtk_mmsys_async_info mmsys_mt8196_ovl0_async_comp_table[] = {
+	{DDP_COMPONENT_OVL0_DLO_ASYNC5, 0, MT8196_OVL_DL_OUT_RELAY5_SIZE, GENMASK(29, 0)},
+	{DDP_COMPONENT_OVL0_DLO_ASYNC6, 1, MT8196_OVL_DL_OUT_RELAY6_SIZE, GENMASK(29, 0)},
+};
+
+static const struct mtk_mmsys_async_info mmsys_mt8196_ovl1_async_comp_table[] = {
+	{DDP_COMPONENT_OVL1_DLO_ASYNC5, 0, MT8196_OVL_DL_OUT_RELAY5_SIZE, GENMASK(29, 0)},
+	{DDP_COMPONENT_OVL1_DLO_ASYNC6, 1, MT8196_OVL_DL_OUT_RELAY6_SIZE, GENMASK(29, 0)},
+};
+
+static const struct mtk_mmsys_async_info mmsys_mt8196_disp0_async_comp_table[] = {
+	{DDP_COMPONENT_DLI_ASYNC0, 0, MT8196_DISP0_DLI_RELAY0, GENMASK(29, 0)},
+	{DDP_COMPONENT_DLI_ASYNC1, 1, MT8196_DISP0_DLI_RELAY1, GENMASK(29, 0)},
+	{DDP_COMPONENT_DLI_ASYNC8, 2, MT8196_DISP0_DLI_RELAY8, GENMASK(29, 0)},
+	{DDP_COMPONENT_DLO_ASYNC1, 3, MT8196_DISP0_DLO_RELAY1, GENMASK(29, 0)},
+	{DDP_COMPONENT_DLO_ASYNC2, 4, MT8196_DISP0_DLO_RELAY2, GENMASK(29, 0)},
+	{DDP_COMPONENT_DLO_ASYNC3, 5, MT8196_DISP0_DLO_RELAY3, GENMASK(29, 0)},
+};
+
+static const struct mtk_mmsys_async_info mmsys_mt8196_disp1_async_comp_table[] = {
+	{DDP_COMPONENT_DLI_ASYNC21, 0, MT8196_DISP1_DLI_RELAY21, GENMASK(29, 0)},
+	{DDP_COMPONENT_DLI_ASYNC22, 1, MT8196_DISP1_DLI_RELAY22, GENMASK(29, 0)},
+	{DDP_COMPONENT_DLI_ASYNC23, 2, MT8196_DISP1_DLI_RELAY23, GENMASK(29, 0)},
+};
+
+static const struct mtk_mmsys_default mmsys_mt8196_vdisp_ao_default_table[] = {
+	{MT8196_VDISP_AO_REG_INTEN, MT8196_CPU_INTEN, MT8196_CPU_INT_MERGE | MT8196_CPU_INTEN},
+	{MT8196_VDISP_AO_REG_INT_SEL_G0, MT8196_IRQ_TABLE_OVL0_OUTPROC0, GENMASK(7, 0)},
+	{MT8196_VDISP_AO_REG_INT_SEL_G0, MT8196_IRQ_TABLE_OVL0_OUTPROC1 << 8, GENMASK(15, 8)},
+	{MT8196_VDISP_AO_REG_INT_SEL_G0, MT8196_IRQ_TABLE_OVL1_OUTPROC0 << 16, GENMASK(23, 16)},
+	{MT8196_VDISP_AO_REG_INT_SEL_G0, MT8196_IRQ_TABLE_DSI0 << 24, GENMASK(31, 24)}
+};
+
+static const struct mtk_mmsys_default mmsys_mt8196_ovl0_default_table[] = {
+	{MT8196_OVLSYS_GCE_EVENT_SEL, MT8196_EVENT_GCE_EN, GENMASK(1, 0)},
+	{MT8196_OVL_INT_MERGE, 0, BIT(0)},
+	{MT8196_OVLSYS_BYPASS_MUX_SHADOW,
+	 MT8196_BYPASS_MUX_SHADOW, MT8196_BYPASS_MUX_SHADOW},
+	{MT8196_OVLSYS_CB_CON, MT8196_OVLSYS_CB_BYPASS_MUX_SHADOW,
+	 MT8196_OVLSYS_CB_BYPASS_MUX_SHADOW},
+};
+
+static const struct mtk_mmsys_default mmsys_mt8196_disp0_default_table[] = {
+	{MT8196_OVLSYS_GCE_EVENT_SEL, MT8196_EVENT_GCE_EN, GENMASK(1, 0)},
+	{MT8196_DISP0_BYPASS_MUX_SHADOW,
+	 MT8196_CB_BYPASS_MUX_SHADOW | MT8196_BYPASS_MUX_SHADOW,
+	 MT8196_CB_BYPASS_MUX_SHADOW | MT8196_BYPASS_MUX_SHADOW},
+	{MT8196_DISP0_DLI_RELAY0, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
+	{MT8196_DISP0_DLI_RELAY1, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
+	{MT8196_DISP0_DLI_RELAY8, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
+	{MT8196_DISP0_DLO_RELAY1, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
+	{MT8196_DISP0_DLO_RELAY2, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
+	{MT8196_DISP0_DLO_RELAY3, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
+};
+
+static const struct mtk_mmsys_default mmsys_mt8196_disp1_default_table[] = {
+	{MT8196_OVLSYS_GCE_EVENT_SEL, MT8196_EVENT_GCE_EN, GENMASK(1, 0)},
+	{MT8196_DISP1_INT_MERGE, 0, BIT(0)},
+	{MT8196_DISP1_BYPASS_MUX_SHADOW,
+	 MT8196_CB_BYPASS_MUX_SHADOW | MT8196_BYPASS_MUX_SHADOW,
+	 MT8196_CB_BYPASS_MUX_SHADOW | MT8196_BYPASS_MUX_SHADOW},
+	{MT8196_DISP1_DLI_RELAY21, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
+	{MT8196_DISP1_DLI_RELAY22, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
+	{MT8196_DISP1_DLI_RELAY23, MT8196_DLI_RELAY_1T2P, GENMASK(31, 30)},
+	{MT8196_DISP1_GCE_FRAME_DONE_SEL0, MT8196_FRAME_DONE_DVO, GENMASK(5, 0)},
+	{MT8196_DISP1_GCE_FRAME_DONE_SEL1, MT8196_FRAME_DONE_DP_INTF0, GENMASK(5, 0)},
+};
+
+static const struct mtk_mmsys_routes mmsys_mt8196_ovl0_routing_table[] = {
+	MMSYS_ROUTE(OVL0_EXDMA2, OVL0_BLENDER1,
+		    MT8196_OVL_RSZ_IN_CB2_MOUT_EN, MT8196_DISP_OVL_EXDMA2_1_TO_OVL_EXDMA_OUT_CB3,
+		    MT8196_DISP_OVL_EXDMA2_1_TO_OVL_EXDMA_OUT_CB3),
+	MMSYS_ROUTE(OVL0_EXDMA2, OVL0_BLENDER1,
+		    MT8196_OVL_EXDMA_OUT_CB3_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER1,
+		    MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER1),
+	MMSYS_ROUTE(OVL0_EXDMA3, OVL0_BLENDER2,
+		    MT8196_OVL_EXDMA_OUT_CB4_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER2,
+		    MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER2),
+	MMSYS_ROUTE(OVL0_EXDMA4, OVL0_BLENDER3,
+		    MT8196_OVL_EXDMA_OUT_CB5_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER3,
+		    MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER3),
+	MMSYS_ROUTE(OVL0_EXDMA5, OVL0_BLENDER4,
+		    MT8196_OVL_EXDMA_OUT_CB6_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER4,
+		    MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER4),
+	MMSYS_ROUTE(OVL0_EXDMA6, OVL0_BLENDER5,
+		    MT8196_OVL_EXDMA_OUT_CB7_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER5,
+		    MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER5),
+	MMSYS_ROUTE(OVL0_EXDMA7, OVL0_BLENDER6,
+		    MT8196_OVL_EXDMA_OUT_CB8_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER6,
+		    MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER6),
+	MMSYS_ROUTE(OVL0_EXDMA8, OVL0_BLENDER7,
+		    MT8196_OVL_EXDMA_OUT_CB9_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER7,
+		    MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER7),
+	MMSYS_ROUTE(OVL0_EXDMA9, OVL0_BLENDER8,
+		    MT8196_OVL_EXDMA_OUT_CB10_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER8,
+		    MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER8),
+	MMSYS_ROUTE(OVL0_BLENDER4, OVL0_OUTPROC0,
+		    MT8196_OVL_BLENDER_OUT_CB4_MOUT_EN, MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC0,
+		    MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC0),
+	MMSYS_ROUTE(OVL0_BLENDER8, OVL0_OUTPROC1,
+		    MT8196_OVL_BLENDER_OUT_CB8_MOUT_EN, MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC1,
+		    MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC1),
+	MMSYS_ROUTE(OVL0_OUTPROC0, OVL0_DLO_ASYNC5,
+		    MT8196_OVL_OUTPROC_OUT_CB0_MOUT_EN,
+		    MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY5,
+		    MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY5),
+	MMSYS_ROUTE(OVL0_OUTPROC1, OVL0_DLO_ASYNC6,
+		    MT8196_OVL_OUTPROC_OUT_CB1_MOUT_EN,
+		    MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY6,
+		    MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY6)
+};
+
+static const struct mtk_mmsys_routes mmsys_mt8196_ovl1_routing_table[] = {
+	MMSYS_ROUTE(OVL1_EXDMA2, OVL1_BLENDER1,
+		    MT8196_OVL_RSZ_IN_CB2_MOUT_EN, MT8196_DISP_OVL_EXDMA2_1_TO_OVL_EXDMA_OUT_CB3,
+		    MT8196_DISP_OVL_EXDMA2_1_TO_OVL_EXDMA_OUT_CB3),
+	MMSYS_ROUTE(OVL1_EXDMA2, OVL1_BLENDER1,
+		    MT8196_OVL_EXDMA_OUT_CB3_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER1,
+		    MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER1),
+	MMSYS_ROUTE(OVL1_EXDMA3, OVL1_BLENDER2,
+		    MT8196_OVL_EXDMA_OUT_CB4_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER2,
+		    MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER2),
+	MMSYS_ROUTE(OVL1_EXDMA4, OVL1_BLENDER3,
+		    MT8196_OVL_EXDMA_OUT_CB5_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER3,
+		    MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER3),
+	MMSYS_ROUTE(OVL1_EXDMA5, OVL1_BLENDER4,
+		    MT8196_OVL_EXDMA_OUT_CB6_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER4,
+		    MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER4),
+	MMSYS_ROUTE(OVL1_EXDMA6, OVL1_BLENDER5,
+		    MT8196_OVL_EXDMA_OUT_CB7_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER5,
+		    MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER5),
+	MMSYS_ROUTE(OVL1_EXDMA7, OVL1_BLENDER6,
+		    MT8196_OVL_EXDMA_OUT_CB8_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER6,
+		    MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER6),
+	MMSYS_ROUTE(OVL1_EXDMA8, OVL1_BLENDER7,
+		    MT8196_OVL_EXDMA_OUT_CB9_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER7,
+		    MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER7),
+	MMSYS_ROUTE(OVL1_EXDMA9, OVL1_BLENDER8,
+		    MT8196_OVL_EXDMA_OUT_CB10_MOUT_EN, MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER8,
+		    MT8196_DISP_OVL_EXDMA_OUT_CB_TO_OVL_BLENDER8),
+	MMSYS_ROUTE(OVL1_BLENDER4, OVL1_OUTPROC0,
+		    MT8196_OVL_BLENDER_OUT_CB4_MOUT_EN, MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC0,
+		    MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC0),
+	MMSYS_ROUTE(OVL1_BLENDER8, OVL1_OUTPROC1,
+		    MT8196_OVL_BLENDER_OUT_CB8_MOUT_EN, MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC1,
+		    MT8196_DISP_OUT_BLENDER_CB_TO_OVL_OUTPROC1),
+	MMSYS_ROUTE(OVL1_OUTPROC0, OVL1_DLO_ASYNC5,
+		    MT8196_OVL_OUTPROC_OUT_CB0_MOUT_EN,
+		    MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY5,
+		    MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY5),
+	MMSYS_ROUTE(OVL1_OUTPROC1, OVL1_DLO_ASYNC6,
+		    MT8196_OVL_OUTPROC_OUT_CB1_MOUT_EN,
+		    MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY6,
+		    MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY6)
+};
+
+/*
+ * main: DLI_ASYNC0-> PQ_IN_CB0 -> PQ_OUT_CB6 -> PANEL_COMP_OUT_CB1 -> DLO_ASYNC1
+ * ext:  DLI_ASYNC1-> PQ_IN_CB1 -> PQ_OUT_CB7 -> PANEL_COMP_OUT_CB2 -> DLO_ASYNC2
+ */
+static const struct mtk_mmsys_routes mmsys_mt8196_disp0_routing_table[] = {
+	MMSYS_ROUTE(DLI_ASYNC0, DLO_ASYNC1,
+		    MT8196_PQ_IN_CB0_MOUT_EN, MT8196_PQ_IN_CB0_TO_PQ_OUT_CB_6,
+		    MT8196_PQ_IN_CB0_TO_PQ_OUT_CB_6),
+	MMSYS_ROUTE(DLI_ASYNC0, DLO_ASYNC1,
+		    MT8196_PQ_OUT_CB6_MOUT_EN, MT8196_PQ_OUT_CB6_TO_PANEL0_COMP_OUT_CB1,
+		    MT8196_PQ_OUT_CB6_TO_PANEL0_COMP_OUT_CB1),
+	MMSYS_ROUTE(DLI_ASYNC0, DLO_ASYNC1,
+		    MT8196_PANEL_COMP_OUT_CB1_MOUT_EN, MT8196_DISP_TO_DLO_RELAY1,
+		    MT8196_DISP_TO_DLO_RELAY1),
+	MMSYS_ROUTE(DLI_ASYNC1, DLO_ASYNC2,
+		    MT8196_PQ_IN_CB1_MOUT_EN, MT8196_PQ_IN_CB1_TO_PQ_OUT_CB_7,
+		    MT8196_PQ_IN_CB1_TO_PQ_OUT_CB_7),
+	MMSYS_ROUTE(DLI_ASYNC1, DLO_ASYNC2,
+		    MT8196_PQ_OUT_CB7_MOUT_EN, MT8196_PQ_OUT_CB7_TO_PANEL0_COMP_OUT_CB2,
+		    MT8196_PQ_OUT_CB7_TO_PANEL0_COMP_OUT_CB2),
+	MMSYS_ROUTE(DLI_ASYNC1, DLO_ASYNC2,
+		    MT8196_PANEL_COMP_OUT_CB2_MOUT_EN, MT8196_DISP_TO_DLO_RELAY2,
+		    MT8196_DISP_TO_DLO_RELAY2),
+	MMSYS_ROUTE(DLI_ASYNC8, DLO_ASYNC3,
+		    MT8196_PQ_IN_CB8_MOUT_EN, MT8196_PQ_IN_CB8_TO_PQ_OUT_CB_8,
+		    MT8196_PQ_IN_CB8_TO_PQ_OUT_CB_8),
+	MMSYS_ROUTE(DLI_ASYNC8, DLO_ASYNC3,
+		    MT8196_PQ_OUT_CB8_MOUT_EN, MT8196_PQ_OUT_CB8_TO_PANEL0_COMP_OUT_CB3,
+		    MT8196_PQ_OUT_CB8_TO_PANEL0_COMP_OUT_CB3),
+	MMSYS_ROUTE(DLI_ASYNC8, DLO_ASYNC3,
+		    MT8196_PANEL_COMP_OUT_CB3_MOUT_EN, MT8196_DISP_TO_DLO_RELAY3,
+		    MT8196_DISP_TO_DLO_RELAY3)
+};
+
+/*
+ * main: DLI_ASYNC21-> SPLITTER_IN_CB1-> SPLITTER_OUT_CB9-> COMP_OUT_CB6-> MERGE_OUT_CB0 -> DVO
+ * ext: DLI_ASYNC22-> SPLITTER_IN_CB2-> SPLITTER_OUT_CB10-> COMP_OUT_CB7-> MERGE_OUT_CB1 -> DP_INTF0
+ */
+static const struct mtk_mmsys_routes mmsys_mt8196_disp1_routing_table[] = {
+	MMSYS_ROUTE(DLI_ASYNC21, DVO0,
+		    MT8196_SPLITTER_IN_CB1_MOUT_EN, MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB9,
+		    MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB9),
+	MMSYS_ROUTE(DLI_ASYNC21, DVO0,
+		    MT8196_SPLITTER_OUT_CB9_MOUT_EN, MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB6,
+		    MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB6),
+	MMSYS_ROUTE(DLI_ASYNC21, DVO0,
+		    MT8196_COMP_OUT_CB6_MOUT_EN, MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB0,
+		    MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB0),
+	MMSYS_ROUTE(DLI_ASYNC21, DVO0,
+		    MT8196_MERGE_OUT_CB0_MOUT_EN, MT8196_DISP_COMP_OUT_CB_TO_DVO0,
+		    MT8196_DISP_COMP_OUT_CB_TO_DVO0),
+	MMSYS_ROUTE(DLI_ASYNC22, DP_INTF0,
+		    MT8196_SPLITTER_IN_CB2_MOUT_EN, MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB10,
+		    MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB10),
+	MMSYS_ROUTE(DLI_ASYNC22, DP_INTF0,
+		    MT8196_SPLITTER_OUT_CB10_MOUT_EN, MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB7,
+		    MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB7),
+	MMSYS_ROUTE(DLI_ASYNC22, DP_INTF0,
+		    MT8196_COMP_OUT_CB7_MOUT_EN, MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB1,
+		    MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB1),
+	MMSYS_ROUTE(DLI_ASYNC22, DP_INTF0,
+		    MT8196_MERGE_OUT_CB1_MOUT_EN, MT8196_DISP_COMP_OUT_CB_TO_DP_INTF0,
+		    MT8196_DISP_COMP_OUT_CB_TO_DP_INTF0),
+	MMSYS_ROUTE(DLI_ASYNC23, DVO0,
+		    MT8196_SPLITTER_IN_CB3_MOUT_EN, MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB11,
+		    MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB11),
+	MMSYS_ROUTE(DLI_ASYNC23, DVO0,
+		    MT8196_SPLITTER_OUT_CB11_MOUT_EN, MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB8,
+		    MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB8),
+	MMSYS_ROUTE(DLI_ASYNC23, DVO0,
+		    MT8196_COMP_OUT_CB8_MOUT_EN, MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB2,
+		    MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB2),
+	MMSYS_ROUTE(DLI_ASYNC23, DVO0,
+		    MT8196_MERGE_OUT_CB2_MOUT_EN, MT8196_DISP_COMP_OUT_CB_TO_DVO0,
+		    MT8196_DISP_COMP_OUT_CB_TO_DVO0),
+	MMSYS_ROUTE(DLI_ASYNC23, DP_INTF1,
+		    MT8196_SPLITTER_IN_CB3_MOUT_EN, MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB11,
+		    MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB11),
+	MMSYS_ROUTE(DLI_ASYNC23, DP_INTF1,
+		    MT8196_SPLITTER_OUT_CB11_MOUT_EN, MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB8,
+		    MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB8),
+	MMSYS_ROUTE(DLI_ASYNC23, DP_INTF1,
+		    MT8196_COMP_OUT_CB8_MOUT_EN, MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB2,
+		    MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB2),
+	MMSYS_ROUTE(DLI_ASYNC23, DP_INTF1,
+		    MT8196_MERGE_OUT_CB2_MOUT_EN, MT8196_DISP_COMP_OUT_CB_TO_DP_INTF1,
+		    MT8196_DISP_COMP_OUT_CB_TO_DP_INTF1),
+	MMSYS_ROUTE(DLI_ASYNC23, DSI0,
+		    MT8196_SPLITTER_IN_CB3_MOUT_EN, MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB11,
+		    MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB11),
+	MMSYS_ROUTE(DLI_ASYNC23, DSI0,
+		    MT8196_SPLITTER_OUT_CB11_MOUT_EN, MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB8,
+		    MT8196_DISP_SPLITTER_IN_CB_TO_COMP_OUT_CB8),
+	MMSYS_ROUTE(DLI_ASYNC23, DSI0,
+		    MT8196_COMP_OUT_CB8_MOUT_EN, MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB2,
+		    MT8196_DISP_SPLITTER_OUT_CB_TO_MERGE_OUT_CB2),
+	MMSYS_ROUTE(DLI_ASYNC23, DSI0,
+		    MT8196_MERGE_OUT_CB2_MOUT_EN, MT8196_DISP_COMP_OUT_CB_TO_DSI0,
+		    MT8196_DISP_COMP_OUT_CB_TO_DSI0)
+};
+#endif /* __SOC_MEDIATEK_MT8196_MMSYS_H */
diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c
index f448cc09ce19..3b490b993549 100644
--- a/drivers/soc/mediatek/mtk-mmsys.c
+++ b/drivers/soc/mediatek/mtk-mmsys.c
@@ -24,6 +24,7 @@
 #include "mt8188-mmsys.h"
 #include "mt8192-mmsys.h"
 #include "mt8195-mmsys.h"
+#include "mt8196-mmsys.h"
 #include "mt8365-mmsys.h"
 
 #define MMSYS_SW_RESET_PER_REG 32
@@ -147,6 +148,54 @@ static const struct mtk_mmsys_driver_data mt8195_vppsys1_driver_data = {
 	.is_vppsys = true,
 };
 
+static const struct mtk_mmsys_driver_data mt8196_dispsys0_driver_data = {
+	.clk_driver = "clk-mt8196-disp0",
+	.routes = mmsys_mt8196_disp0_routing_table,
+	.num_routes = ARRAY_SIZE(mmsys_mt8196_disp0_routing_table),
+	.async_info = mmsys_mt8196_disp0_async_comp_table,
+	.num_async_info = ARRAY_SIZE(mmsys_mt8196_disp0_async_comp_table),
+	.def_config = mmsys_mt8196_disp0_default_table,
+	.num_def_config = ARRAY_SIZE(mmsys_mt8196_disp0_default_table),
+	.num_top_clk = 1,
+};
+
+static const struct mtk_mmsys_driver_data mt8196_dispsys1_driver_data = {
+	.clk_driver = "clk-mt8196-disp1",
+	.routes = mmsys_mt8196_disp1_routing_table,
+	.num_routes = ARRAY_SIZE(mmsys_mt8196_disp1_routing_table),
+	.async_info = mmsys_mt8196_disp1_async_comp_table,
+	.num_async_info = ARRAY_SIZE(mmsys_mt8196_disp1_async_comp_table),
+	.def_config = mmsys_mt8196_disp1_default_table,
+	.num_def_config = ARRAY_SIZE(mmsys_mt8196_disp1_default_table),
+	.num_top_clk = 1,
+};
+
+static const struct mtk_mmsys_driver_data mt8196_ovlsys0_driver_data = {
+	.clk_driver = "clk-mt8196-ovl0",
+	.routes = mmsys_mt8196_ovl0_routing_table,
+	.num_routes = ARRAY_SIZE(mmsys_mt8196_ovl0_routing_table),
+	.async_info = mmsys_mt8196_ovl0_async_comp_table,
+	.num_async_info = ARRAY_SIZE(mmsys_mt8196_ovl0_async_comp_table),
+	.def_config = mmsys_mt8196_ovl0_default_table,
+	.num_def_config = ARRAY_SIZE(mmsys_mt8196_ovl0_default_table),
+};
+
+static const struct mtk_mmsys_driver_data mt8196_ovlsys1_driver_data = {
+	.clk_driver = "clk-mt8196-ovl1",
+	.routes = mmsys_mt8196_ovl1_routing_table,
+	.num_routes = ARRAY_SIZE(mmsys_mt8196_ovl1_routing_table),
+	.async_info = mmsys_mt8196_ovl1_async_comp_table,
+	.num_async_info = ARRAY_SIZE(mmsys_mt8196_ovl1_async_comp_table),
+	.def_config = mmsys_mt8196_ovl0_default_table,
+	.num_def_config = ARRAY_SIZE(mmsys_mt8196_ovl0_default_table),
+};
+
+static const struct mtk_mmsys_driver_data mt8196_vdisp_ao_driver_data = {
+	.clk_driver = "clk-mt8196-vdisp_ao",
+	.def_config = mmsys_mt8196_vdisp_ao_default_table,
+	.num_def_config = ARRAY_SIZE(mmsys_mt8196_vdisp_ao_default_table),
+};
+
 static const struct mtk_mmsys_driver_data mt8365_mmsys_driver_data = {
 	.clk_driver = "clk-mt8365-mm",
 	.routes = mt8365_mmsys_routing_table,
@@ -626,6 +675,11 @@ static const struct of_device_id of_match_mtk_mmsys[] = {
 	{ .compatible = "mediatek,mt8195-vdosys1", .data = &mt8195_vdosys1_driver_data },
 	{ .compatible = "mediatek,mt8195-vppsys0", .data = &mt8195_vppsys0_driver_data },
 	{ .compatible = "mediatek,mt8195-vppsys1", .data = &mt8195_vppsys1_driver_data },
+	{ .compatible = "mediatek,mt8196-dispsys0", .data = &mt8196_dispsys0_driver_data },
+	{ .compatible = "mediatek,mt8196-dispsys1", .data = &mt8196_dispsys1_driver_data },
+	{ .compatible = "mediatek,mt8196-ovlsys0", .data = &mt8196_ovlsys0_driver_data },
+	{ .compatible = "mediatek,mt8196-ovlsys1", .data = &mt8196_ovlsys1_driver_data },
+	{ .compatible = "mediatek,mt8196-vdisp-ao", .data = &mt8196_vdisp_ao_driver_data },
 	{ .compatible = "mediatek,mt8365-mmsys", .data = &mt8365_mmsys_driver_data },
 	{ /* sentinel */ }
 };
diff --git a/include/linux/soc/mediatek/mtk-mmsys.h b/include/linux/soc/mediatek/mtk-mmsys.h
index f50f626e1840..4a0b10567581 100644
--- a/include/linux/soc/mediatek/mtk-mmsys.h
+++ b/include/linux/soc/mediatek/mtk-mmsys.h
@@ -29,6 +29,15 @@ enum mtk_ddp_comp_id {
 	DDP_COMPONENT_COLOR1,
 	DDP_COMPONENT_DITHER0,
 	DDP_COMPONENT_DITHER1,
+	DDP_COMPONENT_DLI_ASYNC0,
+	DDP_COMPONENT_DLI_ASYNC1,
+	DDP_COMPONENT_DLI_ASYNC8,
+	DDP_COMPONENT_DLI_ASYNC21,
+	DDP_COMPONENT_DLI_ASYNC22,
+	DDP_COMPONENT_DLI_ASYNC23,
+	DDP_COMPONENT_DLO_ASYNC1,
+	DDP_COMPONENT_DLO_ASYNC2,
+	DDP_COMPONENT_DLO_ASYNC3,
 	DDP_COMPONENT_DP_INTF0,
 	DDP_COMPONENT_DP_INTF1,
 	DDP_COMPONENT_DPI0,
@@ -39,6 +48,7 @@ enum mtk_ddp_comp_id {
 	DDP_COMPONENT_DSI1,
 	DDP_COMPONENT_DSI2,
 	DDP_COMPONENT_DSI3,
+	DDP_COMPONENT_DVO0,
 	DDP_COMPONENT_ETHDR_MIXER,
 	DDP_COMPONENT_GAMMA,
 	DDP_COMPONENT_MDP_RDMA0,
@@ -58,10 +68,52 @@ enum mtk_ddp_comp_id {
 	DDP_COMPONENT_OD0,
 	DDP_COMPONENT_OD1,
 	DDP_COMPONENT_OVL0,
+	DDP_COMPONENT_OVL0_BLENDER1,
+	DDP_COMPONENT_OVL0_BLENDER2,
+	DDP_COMPONENT_OVL0_BLENDER3,
+	DDP_COMPONENT_OVL0_BLENDER4,
+	DDP_COMPONENT_OVL0_BLENDER5,
+	DDP_COMPONENT_OVL0_BLENDER6,
+	DDP_COMPONENT_OVL0_BLENDER7,
+	DDP_COMPONENT_OVL0_BLENDER8,
+	DDP_COMPONENT_OVL0_BLENDER9,
+	DDP_COMPONENT_OVL0_DLO_ASYNC5,
+	DDP_COMPONENT_OVL0_DLO_ASYNC6,
+	DDP_COMPONENT_OVL0_EXDMA2,
+	DDP_COMPONENT_OVL0_EXDMA3,
+	DDP_COMPONENT_OVL0_EXDMA4,
+	DDP_COMPONENT_OVL0_EXDMA5,
+	DDP_COMPONENT_OVL0_EXDMA6,
+	DDP_COMPONENT_OVL0_EXDMA7,
+	DDP_COMPONENT_OVL0_EXDMA8,
+	DDP_COMPONENT_OVL0_EXDMA9,
+	DDP_COMPONENT_OVL0_OUTPROC0,
+	DDP_COMPONENT_OVL0_OUTPROC1,
 	DDP_COMPONENT_OVL_2L0,
 	DDP_COMPONENT_OVL_2L1,
 	DDP_COMPONENT_OVL_2L2,
 	DDP_COMPONENT_OVL1,
+	DDP_COMPONENT_OVL1_BLENDER1,
+	DDP_COMPONENT_OVL1_BLENDER2,
+	DDP_COMPONENT_OVL1_BLENDER3,
+	DDP_COMPONENT_OVL1_BLENDER4,
+	DDP_COMPONENT_OVL1_BLENDER5,
+	DDP_COMPONENT_OVL1_BLENDER6,
+	DDP_COMPONENT_OVL1_BLENDER7,
+	DDP_COMPONENT_OVL1_BLENDER8,
+	DDP_COMPONENT_OVL1_BLENDER9,
+	DDP_COMPONENT_OVL1_DLO_ASYNC5,
+	DDP_COMPONENT_OVL1_DLO_ASYNC6,
+	DDP_COMPONENT_OVL1_EXDMA2,
+	DDP_COMPONENT_OVL1_EXDMA3,
+	DDP_COMPONENT_OVL1_EXDMA4,
+	DDP_COMPONENT_OVL1_EXDMA5,
+	DDP_COMPONENT_OVL1_EXDMA6,
+	DDP_COMPONENT_OVL1_EXDMA7,
+	DDP_COMPONENT_OVL1_EXDMA8,
+	DDP_COMPONENT_OVL1_EXDMA9,
+	DDP_COMPONENT_OVL1_OUTPROC0,
+	DDP_COMPONENT_OVL1_OUTPROC1,
 	DDP_COMPONENT_PADDING0,
 	DDP_COMPONENT_PADDING1,
 	DDP_COMPONENT_PADDING2,
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v3 07/17] soc: mediatek: mutex: Reused the switch case for SOF ID
  2025-05-15  9:34 [PATCH v3 00/17] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
                   ` (5 preceding siblings ...)
  2025-05-15  9:34 ` [PATCH v3 06/17] soc: mediatek: add mmsys support for MT8196 paul-pl.chen
@ 2025-05-15  9:34 ` paul-pl.chen
  2025-05-15  9:34 ` [PATCH v3 08/17] soc: mediatek: mutex: refactor SOF settings for output components paul-pl.chen
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 35+ messages in thread
From: paul-pl.chen @ 2025-05-15  9:34 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
  Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
	xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
	treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group

From: Paul-pl Chen <paul-pl.chen@mediatek.com>

Reused the switch case for SOF IDs.

Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
 drivers/soc/mediatek/mtk-mutex.c | 81 ++++++++++++++------------------
 1 file changed, 36 insertions(+), 45 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
index aaa965d4b050..47f4d9ae4bfc 100644
--- a/drivers/soc/mediatek/mtk-mutex.c
+++ b/drivers/soc/mediatek/mtk-mutex.c
@@ -853,43 +853,45 @@ void mtk_mutex_unprepare(struct mtk_mutex *mutex)
 }
 EXPORT_SYMBOL_GPL(mtk_mutex_unprepare);
 
-void mtk_mutex_add_comp(struct mtk_mutex *mutex,
-			enum mtk_ddp_comp_id id)
+static int mtk_mutex_get_output_comp_sof(enum mtk_ddp_comp_id id)
 {
-	struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
-						 mutex[mutex->id]);
-	unsigned int reg;
-	unsigned int sof_id;
-	unsigned int offset;
-
-	WARN_ON(&mtx->mutex[mutex->id] != mutex);
-
 	switch (id) {
 	case DDP_COMPONENT_DSI0:
-		sof_id = MUTEX_SOF_DSI0;
-		break;
+		return MUTEX_SOF_DSI0;
 	case DDP_COMPONENT_DSI1:
-		sof_id = MUTEX_SOF_DSI0;
-		break;
+		return MUTEX_SOF_DSI1;
 	case DDP_COMPONENT_DSI2:
-		sof_id = MUTEX_SOF_DSI2;
-		break;
+		return MUTEX_SOF_DSI2;
 	case DDP_COMPONENT_DSI3:
-		sof_id = MUTEX_SOF_DSI3;
-		break;
+		return MUTEX_SOF_DSI3;
 	case DDP_COMPONENT_DPI0:
-		sof_id = MUTEX_SOF_DPI0;
-		break;
+		return MUTEX_SOF_DPI0;
 	case DDP_COMPONENT_DPI1:
-		sof_id = MUTEX_SOF_DPI1;
-		break;
+		return MUTEX_SOF_DPI1;
 	case DDP_COMPONENT_DP_INTF0:
-		sof_id = MUTEX_SOF_DP_INTF0;
-		break;
+		return MUTEX_SOF_DP_INTF0;
 	case DDP_COMPONENT_DP_INTF1:
-		sof_id = MUTEX_SOF_DP_INTF1;
-		break;
+		return MUTEX_SOF_DP_INTF1;
 	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+void mtk_mutex_add_comp(struct mtk_mutex *mutex,
+			enum mtk_ddp_comp_id id)
+{
+	struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
+						 mutex[mutex->id]);
+	unsigned int reg;
+	unsigned int sof_id;
+	unsigned int offset;
+	int sof_id = mtk_mutex_get_output_comp_sof(id);
+
+	WARN_ON(&mtx->mutex[mutex->id] != mutex);
+
+	if (sof_id < 0) {
 		if (mtx->data->mutex_mod[id] < 32) {
 			offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
 						    mutex->id);
@@ -905,8 +907,7 @@ void mtk_mutex_add_comp(struct mtk_mutex *mutex,
 		return;
 	}
 
-	writel_relaxed(mtx->data->mutex_sof[sof_id],
-		       mtx->regs +
+	writel_relaxed(mtx->data->mutex_sof[sof_id], mtx->regs +
 		       DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, mutex->id));
 }
 EXPORT_SYMBOL_GPL(mtk_mutex_add_comp);
@@ -918,24 +919,10 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
 						 mutex[mutex->id]);
 	unsigned int reg;
 	unsigned int offset;
-
+	int sof_id = mtk_mutex_get_output_comp_sof(id);
 	WARN_ON(&mtx->mutex[mutex->id] != mutex);
 
-	switch (id) {
-	case DDP_COMPONENT_DSI0:
-	case DDP_COMPONENT_DSI1:
-	case DDP_COMPONENT_DSI2:
-	case DDP_COMPONENT_DSI3:
-	case DDP_COMPONENT_DPI0:
-	case DDP_COMPONENT_DPI1:
-	case DDP_COMPONENT_DP_INTF0:
-	case DDP_COMPONENT_DP_INTF1:
-		writel_relaxed(MUTEX_SOF_SINGLE_MODE,
-			       mtx->regs +
-			       DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg,
-						  mutex->id));
-		break;
-	default:
+	if (sof_id < 0) {
 		if (mtx->data->mutex_mod[id] < 32) {
 			offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
 						    mutex->id);
@@ -948,8 +935,12 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
 			reg &= ~(1 << (mtx->data->mutex_mod[id] - 32));
 			writel_relaxed(reg, mtx->regs + offset);
 		}
-		break;
+		return;
 	}
+
+	writel_relaxed(MUTEX_SOF_SINGLE_MODE,
+		       mtx->regs + DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg,
+		       mutex->id));
 }
 EXPORT_SYMBOL_GPL(mtk_mutex_remove_comp);
 
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v3 08/17] soc: mediatek: mutex: refactor SOF settings for output components
  2025-05-15  9:34 [PATCH v3 00/17] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
                   ` (6 preceding siblings ...)
  2025-05-15  9:34 ` [PATCH v3 07/17] soc: mediatek: mutex: Reused the switch case for SOF ID paul-pl.chen
@ 2025-05-15  9:34 ` paul-pl.chen
  2025-05-15  9:34 ` [PATCH v3 09/17] soc: mediatek: mutex: add mutex support for MT8196 paul-pl.chen
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 35+ messages in thread
From: paul-pl.chen @ 2025-05-15  9:34 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
  Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
	xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
	treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group

From: Paul-pl Chen <paul-pl.chen@mediatek.com>

Refactor SOF settings by adding mtk_mutex_get_output_comp_sof()
and extracting SOF logic from mtk_mutex_add_comp()
and mtk_mutex_remove_comp().

Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
 drivers/soc/mediatek/mtk-mutex.c       | 60 +++++++++++++++++++++-----
 include/linux/soc/mediatek/mtk-mutex.h |  4 ++
 2 files changed, 53 insertions(+), 11 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
index 47f4d9ae4bfc..b2a9992fb232 100644
--- a/drivers/soc/mediatek/mtk-mutex.c
+++ b/drivers/soc/mediatek/mtk-mutex.c
@@ -879,19 +879,57 @@ static int mtk_mutex_get_output_comp_sof(enum mtk_ddp_comp_id id)
 	return -EINVAL;
 }
 
+void mtk_mutex_add_comp_sof(struct mtk_mutex *mutex, enum mtk_ddp_comp_id id)
+{
+	struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
+						 mutex[mutex->id]);
+	int sof_id = mtk_mutex_get_output_comp_sof(id);
+	unsigned int offset;
+
+	if (sof_id < 0 || sof_id >= DDP_MUTEX_SOF_MAX)
+		return;
+
+	WARN_ON(&mtx->mutex[mutex->id] != mutex);
+
+	offset = DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, mutex->id);
+
+	writel_relaxed(mtx->data->mutex_sof[sof_id], mtx->regs + offset);
+}
+EXPORT_SYMBOL_GPL(mtk_mutex_add_comp_sof);
+
+void mtk_mutex_remove_comp_sof(struct mtk_mutex *mutex, enum mtk_ddp_comp_id id)
+{
+	struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
+						 mutex[mutex->id]);
+	unsigned int reg;
+	int sof_id = mtk_mutex_get_output_comp_sof(id);
+	unsigned int offset;
+
+	if (sof_id < 0 || sof_id >= DDP_MUTEX_SOF_MAX)
+		return;
+
+	WARN_ON(&mtx->mutex[mutex->id] != mutex);
+
+	offset = DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, mutex->id);
+	reg = readl_relaxed(mtx->regs + offset);
+	reg &= ~(1 << mtx->data->mutex_sof[id]);
+
+	writel_relaxed(reg, mtx->regs + offset);
+}
+EXPORT_SYMBOL_GPL(mtk_mutex_remove_comp_sof);
+
 void mtk_mutex_add_comp(struct mtk_mutex *mutex,
 			enum mtk_ddp_comp_id id)
 {
 	struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
 						 mutex[mutex->id]);
 	unsigned int reg;
-	unsigned int sof_id;
 	unsigned int offset;
-	int sof_id = mtk_mutex_get_output_comp_sof(id);
+	bool is_output_comp = (mtk_mutex_get_output_comp_sof(id) > 0);
 
 	WARN_ON(&mtx->mutex[mutex->id] != mutex);
 
-	if (sof_id < 0) {
+	if (!is_output_comp) {
 		if (mtx->data->mutex_mod[id] < 32) {
 			offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
 						    mutex->id);
@@ -904,11 +942,10 @@ void mtk_mutex_add_comp(struct mtk_mutex *mutex,
 			reg |= 1 << (mtx->data->mutex_mod[id] - 32);
 			writel_relaxed(reg, mtx->regs + offset);
 		}
-		return;
 	}
 
-	writel_relaxed(mtx->data->mutex_sof[sof_id], mtx->regs +
-		       DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, mutex->id));
+	if (is_output_comp)
+		mtk_mutex_add_comp_sof(mutex, id);
 }
 EXPORT_SYMBOL_GPL(mtk_mutex_add_comp);
 
@@ -919,10 +956,11 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
 						 mutex[mutex->id]);
 	unsigned int reg;
 	unsigned int offset;
-	int sof_id = mtk_mutex_get_output_comp_sof(id);
+	bool is_output_comp = (mtk_mutex_get_output_comp_sof(id) > 0);
+
 	WARN_ON(&mtx->mutex[mutex->id] != mutex);
 
-	if (sof_id < 0) {
+	if (!is_output_comp) {
 		if (mtx->data->mutex_mod[id] < 32) {
 			offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
 						    mutex->id);
@@ -938,9 +976,9 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
 		return;
 	}
 
-	writel_relaxed(MUTEX_SOF_SINGLE_MODE,
-		       mtx->regs + DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg,
-		       mutex->id));
+	if (is_output_comp)
+		mtk_mutex_remove_comp_sof(mutex, id);
+
 }
 EXPORT_SYMBOL_GPL(mtk_mutex_remove_comp);
 
diff --git a/include/linux/soc/mediatek/mtk-mutex.h b/include/linux/soc/mediatek/mtk-mutex.h
index 635218e3ac68..515e2d8bfc90 100644
--- a/include/linux/soc/mediatek/mtk-mutex.h
+++ b/include/linux/soc/mediatek/mtk-mutex.h
@@ -69,6 +69,10 @@ enum mtk_mutex_sof_index {
 
 struct mtk_mutex *mtk_mutex_get(struct device *dev);
 int mtk_mutex_prepare(struct mtk_mutex *mutex);
+void mtk_mutex_add_comp_sof(struct mtk_mutex *mutex,
+			    enum mtk_ddp_comp_id id);
+void mtk_mutex_remove_comp_sof(struct mtk_mutex *mutex,
+			       enum mtk_ddp_comp_id id);
 void mtk_mutex_add_comp(struct mtk_mutex *mutex,
 			enum mtk_ddp_comp_id id);
 void mtk_mutex_enable(struct mtk_mutex *mutex);
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v3 09/17] soc: mediatek: mutex: add mutex support for MT8196
  2025-05-15  9:34 [PATCH v3 00/17] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
                   ` (7 preceding siblings ...)
  2025-05-15  9:34 ` [PATCH v3 08/17] soc: mediatek: mutex: refactor SOF settings for output components paul-pl.chen
@ 2025-05-15  9:34 ` paul-pl.chen
  2025-05-15  9:34 ` [PATCH v3 10/17] drm/mediatek: Export OVL formats definitions and format conversion API paul-pl.chen
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 35+ messages in thread
From: paul-pl.chen @ 2025-05-15  9:34 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
  Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
	xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
	treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group

From: Nancy Lin <nancy.lin@mediatek.com>

Add mutex support for the main and external displays in MT8196:
- Introduce a new DVO0 output component for the new mutex
  settings of MT8196.
- Add a need_sof_mof flag to configure both SOF and MOD settings
  for the output component.

Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
 drivers/soc/mediatek/mtk-mutex.c | 140 ++++++++++++++++++++++++++++++-
 1 file changed, 138 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
index b2a9992fb232..183f3abcd7dd 100644
--- a/drivers/soc/mediatek/mtk-mutex.c
+++ b/drivers/soc/mediatek/mtk-mutex.c
@@ -19,6 +19,7 @@
 #define MT2701_MUTEX0_SOF0			0x30
 #define MT8183_MUTEX0_MOD0			0x30
 #define MT8183_MUTEX0_SOF0			0x2c
+#define MT8196_MUTEX0_MOD0			0x34
 
 #define DISP_REG_MUTEX_EN(n)			(0x20 + 0x20 * (n))
 #define DISP_REG_MUTEX(n)			(0x24 + 0x20 * (n))
@@ -237,6 +238,47 @@
 #define MT8195_MUTEX_MOD_MDP_WROT2             32
 #define MT8195_MUTEX_MOD_MDP_WROT3             33
 
+/* OVLSYS */
+#define MT8196_MUTEX_MOD0_OVL_EXDMA2		2
+#define MT8196_MUTEX_MOD0_OVL_EXDMA3		3
+#define MT8196_MUTEX_MOD0_OVL_EXDMA4		4
+#define MT8196_MUTEX_MOD0_OVL_EXDMA5		5
+#define MT8196_MUTEX_MOD0_OVL_EXDMA6		6
+#define MT8196_MUTEX_MOD0_OVL_EXDMA7		7
+#define MT8196_MUTEX_MOD0_OVL_EXDMA8		8
+#define MT8196_MUTEX_MOD0_OVL_EXDMA9		9
+#define MT8196_MUTEX_MOD0_OVL_BLENDER1		11
+#define MT8196_MUTEX_MOD0_OVL_BLENDER2		12
+#define MT8196_MUTEX_MOD0_OVL_BLENDER3		13
+#define MT8196_MUTEX_MOD0_OVL_BLENDER4		14
+#define MT8196_MUTEX_MOD0_OVL_BLENDER5		15
+#define MT8196_MUTEX_MOD0_OVL_BLENDER6		16
+#define MT8196_MUTEX_MOD0_OVL_BLENDER7		17
+#define MT8196_MUTEX_MOD0_OVL_BLENDER8		18
+#define MT8196_MUTEX_MOD0_OVL_BLENDER9		19
+#define MT8196_MUTEX_MOD0_OVL_OUTPROC0		20
+#define MT8196_MUTEX_MOD0_OVL_OUTPROC1		21
+#define MT8196_MUTEX_MOD0_OVL_OUTPROC2		22
+#define MT8196_MUTEX_MOD1_OVL_DLO_ASYNC5	(32 + 16)
+#define MT8196_MUTEX_MOD1_OVL_DLO_ASYNC6	(32 + 17)
+
+/* DISP0 */
+#define MT8196_MUTEX_MOD0_DISP_DLI_ASYNC0	16
+#define MT8196_MUTEX_MOD0_DISP_DLI_ASYNC1	17
+#define MT8196_MUTEX_MOD0_DISP_DLI_ASYNC8	24
+#define MT8196_MUTEX_MOD1_DISP_DLO_ASYNC1	(32 + 1)
+#define MT8196_MUTEX_MOD1_DISP_DLO_ASYNC2	(32 + 2)
+#define MT8196_MUTEX_MOD1_DISP_DLO_ASYNC3	(32 + 3)
+
+/* DISP1 */
+#define MT8196_MUTEX_MOD0_DISP1_DLI_ASYNC21	1
+#define MT8196_MUTEX_MOD0_DISP1_DLI_ASYNC22	2
+#define MT8196_MUTEX_MOD0_DISP1_DLI_ASYNC23	3
+#define MT8196_MUTEX_MOD0_DISP1_DP_INTF0	13
+#define MT8196_MUTEX_MOD0_DISP1_DP_INTF1	14
+#define MT8196_MUTEX_MOD0_DISP1_DSI0		23
+#define MT8196_MUTEX_MOD0_DISP1_DVO		29
+
 #define MT8365_MUTEX_MOD_DISP_OVL0		7
 #define MT8365_MUTEX_MOD_DISP_OVL0_2L		8
 #define MT8365_MUTEX_MOD_DISP_RDMA0		9
@@ -297,6 +339,12 @@
 #define MT8195_MUTEX_SOF_DP_INTF1		4
 #define MT8195_MUTEX_SOF_DPI0			6 /* for HDMI_TX */
 #define MT8195_MUTEX_SOF_DPI1			5 /* for digital video out */
+#define MT8196_MUTEX_SOF_DSI0			1
+#define MT8196_MUTEX_SOF_DSI1			2
+#define MT8196_MUTEX_SOF_DSI2			4
+#define MT8196_MUTEX_SOF_DPI0			5
+#define MT8196_MUTEX_SOF_DPI1			6
+#define MT8196_MUTEX_SOF_DVO0			7
 
 #define MT8183_MUTEX_EOF_DSI0			(MT8183_MUTEX_SOF_DSI0 << 6)
 #define MT8183_MUTEX_EOF_DPI0			(MT8183_MUTEX_SOF_DPI0 << 6)
@@ -310,6 +358,12 @@
 #define MT8195_MUTEX_EOF_DP_INTF1		(MT8195_MUTEX_SOF_DP_INTF1 << 7)
 #define MT8195_MUTEX_EOF_DPI0			(MT8195_MUTEX_SOF_DPI0 << 7)
 #define MT8195_MUTEX_EOF_DPI1			(MT8195_MUTEX_SOF_DPI1 << 7)
+#define MT8196_MUTEX_EOF_DSI0			(MT8196_MUTEX_SOF_DSI0 << 7)
+#define MT8196_MUTEX_EOF_DSI1			(MT8196_MUTEX_SOF_DSI1 << 7)
+#define MT8196_MUTEX_EOF_DSI2			(MT8196_MUTEX_SOF_DSI2 << 7)
+#define MT8196_MUTEX_EOF_DPI0			(MT8196_MUTEX_SOF_DPI0 << 7)
+#define MT8196_MUTEX_EOF_DPI1			(MT8196_MUTEX_SOF_DPI1 << 7)
+#define MT8196_MUTEX_EOF_DVO0			(MT8196_MUTEX_SOF_DVO0 << 7)
 
 struct mtk_mutex {
 	u8 id;
@@ -326,6 +380,7 @@ enum mtk_mutex_sof_id {
 	MUTEX_SOF_DSI3,
 	MUTEX_SOF_DP_INTF0,
 	MUTEX_SOF_DP_INTF1,
+	MUTEX_SOF_DVO0,
 	DDP_MUTEX_SOF_MAX,
 };
 
@@ -336,6 +391,7 @@ struct mtk_mutex_data {
 	const u16 mutex_mod_reg;
 	const u16 mutex_sof_reg;
 	const bool no_clk;
+	const bool need_sof_mod;
 };
 
 struct mtk_mutex_ctx {
@@ -625,6 +681,64 @@ static const u8 mt8195_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
 	[MUTEX_MOD_IDX_MDP_WROT3] = MT8195_MUTEX_MOD_MDP_WROT3,
 };
 
+static const u8 mt8196_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+	[DDP_COMPONENT_OVL0_EXDMA2] = MT8196_MUTEX_MOD0_OVL_EXDMA2,
+	[DDP_COMPONENT_OVL0_EXDMA3] = MT8196_MUTEX_MOD0_OVL_EXDMA3,
+	[DDP_COMPONENT_OVL0_EXDMA4] = MT8196_MUTEX_MOD0_OVL_EXDMA4,
+	[DDP_COMPONENT_OVL0_EXDMA5] = MT8196_MUTEX_MOD0_OVL_EXDMA5,
+	[DDP_COMPONENT_OVL0_EXDMA6] = MT8196_MUTEX_MOD0_OVL_EXDMA6,
+	[DDP_COMPONENT_OVL0_EXDMA7] = MT8196_MUTEX_MOD0_OVL_EXDMA7,
+	[DDP_COMPONENT_OVL0_EXDMA8] = MT8196_MUTEX_MOD0_OVL_EXDMA8,
+	[DDP_COMPONENT_OVL0_EXDMA9] = MT8196_MUTEX_MOD0_OVL_EXDMA9,
+	[DDP_COMPONENT_OVL0_BLENDER1] = MT8196_MUTEX_MOD0_OVL_BLENDER1,
+	[DDP_COMPONENT_OVL0_BLENDER2] = MT8196_MUTEX_MOD0_OVL_BLENDER2,
+	[DDP_COMPONENT_OVL0_BLENDER3] = MT8196_MUTEX_MOD0_OVL_BLENDER3,
+	[DDP_COMPONENT_OVL0_BLENDER4] = MT8196_MUTEX_MOD0_OVL_BLENDER4,
+	[DDP_COMPONENT_OVL0_BLENDER5] = MT8196_MUTEX_MOD0_OVL_BLENDER5,
+	[DDP_COMPONENT_OVL0_BLENDER6] = MT8196_MUTEX_MOD0_OVL_BLENDER6,
+	[DDP_COMPONENT_OVL0_BLENDER7] = MT8196_MUTEX_MOD0_OVL_BLENDER7,
+	[DDP_COMPONENT_OVL0_BLENDER8] = MT8196_MUTEX_MOD0_OVL_BLENDER8,
+	[DDP_COMPONENT_OVL0_BLENDER9] = MT8196_MUTEX_MOD0_OVL_BLENDER9,
+	[DDP_COMPONENT_OVL0_OUTPROC0] = MT8196_MUTEX_MOD0_OVL_OUTPROC0,
+	[DDP_COMPONENT_OVL0_OUTPROC1] = MT8196_MUTEX_MOD0_OVL_OUTPROC1,
+	[DDP_COMPONENT_OVL0_DLO_ASYNC5] = MT8196_MUTEX_MOD1_OVL_DLO_ASYNC5,
+	[DDP_COMPONENT_OVL0_DLO_ASYNC6] = MT8196_MUTEX_MOD1_OVL_DLO_ASYNC6,
+	[DDP_COMPONENT_OVL1_EXDMA2] = MT8196_MUTEX_MOD0_OVL_EXDMA2,
+	[DDP_COMPONENT_OVL1_EXDMA3] = MT8196_MUTEX_MOD0_OVL_EXDMA3,
+	[DDP_COMPONENT_OVL1_EXDMA4] = MT8196_MUTEX_MOD0_OVL_EXDMA4,
+	[DDP_COMPONENT_OVL1_EXDMA5] = MT8196_MUTEX_MOD0_OVL_EXDMA5,
+	[DDP_COMPONENT_OVL1_EXDMA6] = MT8196_MUTEX_MOD0_OVL_EXDMA6,
+	[DDP_COMPONENT_OVL1_EXDMA7] = MT8196_MUTEX_MOD0_OVL_EXDMA7,
+	[DDP_COMPONENT_OVL1_EXDMA8] = MT8196_MUTEX_MOD0_OVL_EXDMA8,
+	[DDP_COMPONENT_OVL1_EXDMA9] = MT8196_MUTEX_MOD0_OVL_EXDMA9,
+	[DDP_COMPONENT_OVL1_BLENDER1] = MT8196_MUTEX_MOD0_OVL_BLENDER1,
+	[DDP_COMPONENT_OVL1_BLENDER2] = MT8196_MUTEX_MOD0_OVL_BLENDER2,
+	[DDP_COMPONENT_OVL1_BLENDER3] = MT8196_MUTEX_MOD0_OVL_BLENDER3,
+	[DDP_COMPONENT_OVL1_BLENDER4] = MT8196_MUTEX_MOD0_OVL_BLENDER4,
+	[DDP_COMPONENT_OVL1_BLENDER5] = MT8196_MUTEX_MOD0_OVL_BLENDER5,
+	[DDP_COMPONENT_OVL1_BLENDER6] = MT8196_MUTEX_MOD0_OVL_BLENDER6,
+	[DDP_COMPONENT_OVL1_BLENDER7] = MT8196_MUTEX_MOD0_OVL_BLENDER7,
+	[DDP_COMPONENT_OVL1_BLENDER8] = MT8196_MUTEX_MOD0_OVL_BLENDER8,
+	[DDP_COMPONENT_OVL1_BLENDER9] = MT8196_MUTEX_MOD0_OVL_BLENDER9,
+	[DDP_COMPONENT_OVL1_OUTPROC0] = MT8196_MUTEX_MOD0_OVL_OUTPROC0,
+	[DDP_COMPONENT_OVL1_OUTPROC1] = MT8196_MUTEX_MOD0_OVL_OUTPROC1,
+	[DDP_COMPONENT_OVL1_DLO_ASYNC5] = MT8196_MUTEX_MOD1_OVL_DLO_ASYNC5,
+	[DDP_COMPONENT_OVL1_DLO_ASYNC6] = MT8196_MUTEX_MOD1_OVL_DLO_ASYNC6,
+	[DDP_COMPONENT_DLI_ASYNC0] = MT8196_MUTEX_MOD0_DISP_DLI_ASYNC0,
+	[DDP_COMPONENT_DLI_ASYNC1] = MT8196_MUTEX_MOD0_DISP_DLI_ASYNC1,
+	[DDP_COMPONENT_DLI_ASYNC8] = MT8196_MUTEX_MOD0_DISP_DLI_ASYNC8,
+	[DDP_COMPONENT_DLO_ASYNC1] = MT8196_MUTEX_MOD1_DISP_DLO_ASYNC1,
+	[DDP_COMPONENT_DLO_ASYNC2] = MT8196_MUTEX_MOD1_DISP_DLO_ASYNC2,
+	[DDP_COMPONENT_DLO_ASYNC3] = MT8196_MUTEX_MOD1_DISP_DLO_ASYNC3,
+	[DDP_COMPONENT_DLI_ASYNC21] = MT8196_MUTEX_MOD0_DISP1_DLI_ASYNC21,
+	[DDP_COMPONENT_DLI_ASYNC22] = MT8196_MUTEX_MOD0_DISP1_DLI_ASYNC22,
+	[DDP_COMPONENT_DLI_ASYNC23] = MT8196_MUTEX_MOD0_DISP1_DLI_ASYNC23,
+	[DDP_COMPONENT_DVO0] = MT8196_MUTEX_MOD0_DISP1_DVO,
+	[DDP_COMPONENT_DP_INTF0] = MT8196_MUTEX_MOD0_DISP1_DP_INTF0,
+	[DDP_COMPONENT_DP_INTF1] = MT8196_MUTEX_MOD0_DISP1_DP_INTF1,
+	[DDP_COMPONENT_DSI0] = MT8196_MUTEX_MOD0_DISP1_DSI0,
+};
+
 static const u8 mt8365_mutex_mod[DDP_COMPONENT_ID_MAX] = {
 	[DDP_COMPONENT_AAL0] = MT8365_MUTEX_MOD_DISP_AAL,
 	[DDP_COMPONENT_CCORR] = MT8365_MUTEX_MOD_DISP_CCORR,
@@ -710,6 +824,17 @@ static const u16 mt8195_mutex_sof[DDP_MUTEX_SOF_MAX] = {
 		MT8195_MUTEX_SOF_DP_INTF1 | MT8195_MUTEX_EOF_DP_INTF1,
 };
 
+static const u16 mt8196_mutex_sof[DDP_MUTEX_SOF_MAX] = {
+	[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
+	[MUTEX_SOF_DSI0] = MT8196_MUTEX_SOF_DSI0 | MT8196_MUTEX_EOF_DSI0,
+	[MUTEX_SOF_DSI1] = MT8196_MUTEX_SOF_DSI1 | MT8196_MUTEX_EOF_DSI1,
+	[MUTEX_SOF_DP_INTF0] =
+		MT8196_MUTEX_SOF_DPI0 | MT8196_MUTEX_EOF_DPI0,
+	[MUTEX_SOF_DP_INTF1] =
+		MT8196_MUTEX_SOF_DPI1 | MT8196_MUTEX_EOF_DPI1,
+	[MUTEX_SOF_DVO0] = MT8196_MUTEX_SOF_DVO0 | MT8196_MUTEX_EOF_DVO0,
+};
+
 static const struct mtk_mutex_data mt2701_mutex_driver_data = {
 	.mutex_mod = mt2701_mutex_mod,
 	.mutex_sof = mt2712_mutex_sof,
@@ -803,6 +928,14 @@ static const struct mtk_mutex_data mt8195_vpp_mutex_driver_data = {
 	.mutex_table_mod = mt8195_mutex_table_mod,
 };
 
+static const struct mtk_mutex_data mt8196_mutex_driver_data = {
+	.mutex_mod = mt8196_mutex_mod,
+	.mutex_sof = mt8196_mutex_sof,
+	.mutex_mod_reg = MT8196_MUTEX0_MOD0,
+	.mutex_sof_reg = MT2701_MUTEX0_SOF0,
+	.need_sof_mod = true,
+};
+
 static const struct mtk_mutex_data mt8365_mutex_driver_data = {
 	.mutex_mod = mt8365_mutex_mod,
 	.mutex_sof = mt8183_mutex_sof,
@@ -872,6 +1005,8 @@ static int mtk_mutex_get_output_comp_sof(enum mtk_ddp_comp_id id)
 		return MUTEX_SOF_DP_INTF0;
 	case DDP_COMPONENT_DP_INTF1:
 		return MUTEX_SOF_DP_INTF1;
+	case DDP_COMPONENT_DVO0:
+		return MUTEX_SOF_DVO0;
 	default:
 		break;
 	}
@@ -929,7 +1064,7 @@ void mtk_mutex_add_comp(struct mtk_mutex *mutex,
 
 	WARN_ON(&mtx->mutex[mutex->id] != mutex);
 
-	if (!is_output_comp) {
+	if (!is_output_comp || mtx->data->need_sof_mod) {
 		if (mtx->data->mutex_mod[id] < 32) {
 			offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
 						    mutex->id);
@@ -960,7 +1095,7 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
 
 	WARN_ON(&mtx->mutex[mutex->id] != mutex);
 
-	if (!is_output_comp) {
+	if (!is_output_comp || mtx->data->need_sof_mod) {
 		if (mtx->data->mutex_mod[id] < 32) {
 			offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
 						    mutex->id);
@@ -1169,6 +1304,7 @@ static const struct of_device_id mutex_driver_dt_match[] = {
 	{ .compatible = "mediatek,mt8192-disp-mutex", .data = &mt8192_mutex_driver_data },
 	{ .compatible = "mediatek,mt8195-disp-mutex", .data = &mt8195_mutex_driver_data },
 	{ .compatible = "mediatek,mt8195-vpp-mutex",  .data = &mt8195_vpp_mutex_driver_data },
+	{ .compatible = "mediatek,mt8196-disp-mutex", .data = &mt8196_mutex_driver_data },
 	{ .compatible = "mediatek,mt8365-disp-mutex", .data = &mt8365_mutex_driver_data },
 	{ /* sentinel */ },
 };
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v3 10/17] drm/mediatek: Export OVL formats definitions and format conversion API
  2025-05-15  9:34 [PATCH v3 00/17] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
                   ` (8 preceding siblings ...)
  2025-05-15  9:34 ` [PATCH v3 09/17] soc: mediatek: mutex: add mutex support for MT8196 paul-pl.chen
@ 2025-05-15  9:34 ` paul-pl.chen
  2025-06-17  5:43   ` CK Hu (胡俊光)
  2025-05-15  9:34 ` [PATCH v3 11/17] drm/mediatek: drm/mediatek: Export OVL ignore pixel alpha function paul-pl.chen
                   ` (6 subsequent siblings)
  16 siblings, 1 reply; 35+ messages in thread
From: paul-pl.chen @ 2025-05-15  9:34 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
  Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
	xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
	treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group

From: Nancy Lin <nancy.lin@mediatek.com>

In upcoming SoCs, the OVL component will be divided into multiple
smaller hardware units to enhance flexibility. To facilitate this
transition, the OVL format definitions and format conversion API
should be exported for reuse across these units.

Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 214 ++++++++++++++----------
 drivers/gpu/drm/mediatek/mtk_disp_ovl.h |  28 ++++
 2 files changed, 150 insertions(+), 92 deletions(-)
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovl.h

diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index d0581c4e3c99..a516b7c82b5a 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -3,8 +3,6 @@
  * Copyright (c) 2015 MediaTek Inc.
  */
 
-#include <drm/drm_blend.h>
-#include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 
 #include <linux/clk.h>
@@ -18,6 +16,7 @@
 #include "mtk_crtc.h"
 #include "mtk_ddp_comp.h"
 #include "mtk_disp_drv.h"
+#include "mtk_disp_ovl.h"
 #include "mtk_drm_drv.h"
 
 #define DISP_REG_OVL_INTEN			0x0004
@@ -62,22 +61,15 @@
 /* OVL_CON_RGB_SWAP works only if OVL_CON_CLRFMT_MAN is enabled */
 #define OVL_CON_RGB_SWAP	BIT(25)
 
-#define OVL_CON_CLRFMT_RGB	(1 << 12)
-#define OVL_CON_CLRFMT_ARGB8888	(2 << 12)
-#define OVL_CON_CLRFMT_RGBA8888	(3 << 12)
-#define OVL_CON_CLRFMT_ABGR8888	(OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP)
-#define OVL_CON_CLRFMT_BGRA8888	(OVL_CON_CLRFMT_RGBA8888 | OVL_CON_BYTE_SWAP)
-#define OVL_CON_CLRFMT_UYVY	(4 << 12)
-#define OVL_CON_CLRFMT_YUYV	(5 << 12)
-#define OVL_CON_MTX_YUV_TO_RGB	(6 << 16)
-#define OVL_CON_CLRFMT_PARGB8888 ((3 << 12) | OVL_CON_CLRFMT_MAN)
-#define OVL_CON_CLRFMT_PABGR8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_RGB_SWAP)
-#define OVL_CON_CLRFMT_PBGRA8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_BYTE_SWAP)
-#define OVL_CON_CLRFMT_PRGBA8888 (OVL_CON_CLRFMT_PABGR8888 | OVL_CON_BYTE_SWAP)
-#define OVL_CON_CLRFMT_RGB565(ovl)	((ovl)->data->fmt_rgb565_is_0 ? \
-					0 : OVL_CON_CLRFMT_RGB)
-#define OVL_CON_CLRFMT_RGB888(ovl)	((ovl)->data->fmt_rgb565_is_0 ? \
-					OVL_CON_CLRFMT_RGB : 0)
+#define OVL_CON_CLRFMT_RGB565(shift)	(0 << (shift))
+#define OVL_CON_CLRFMT_RGB888(shift)	(1 << (shift))
+#define OVL_CON_CLRFMT_ARGB8888(shift)	(2 << (shift))
+#define OVL_CON_CLRFMT_RGBA8888(shift)	(3 << (shift))
+#define OVL_CON_CLRFMT_UYVY(shift)	(4 << (shift))
+#define OVL_CON_CLRFMT_YUYV(shift)	(5 << (shift))
+#define OVL_CON_MTX_YUV_TO_RGB		(6 << 16)
+#define OVL_CON_CLRFMT_PARGB8888(shift, man) ((3 << (shift)) | (man))
+
 #define	OVL_CON_AEN		BIT(8)
 #define	OVL_CON_ALPHA		0xff
 #define	OVL_CON_VIRT_FLIP	BIT(9)
@@ -85,23 +77,7 @@
 
 #define OVL_COLOR_ALPHA		GENMASK(31, 24)
 
-static inline bool is_10bit_rgb(u32 fmt)
-{
-	switch (fmt) {
-	case DRM_FORMAT_XRGB2101010:
-	case DRM_FORMAT_ARGB2101010:
-	case DRM_FORMAT_RGBX1010102:
-	case DRM_FORMAT_RGBA1010102:
-	case DRM_FORMAT_XBGR2101010:
-	case DRM_FORMAT_ABGR2101010:
-	case DRM_FORMAT_BGRX1010102:
-	case DRM_FORMAT_BGRA1010102:
-		return true;
-	}
-	return false;
-}
-
-static const u32 mt8173_formats[] = {
+const u32 mt8173_ovl_formats[] = {
 	DRM_FORMAT_XRGB8888,
 	DRM_FORMAT_ARGB8888,
 	DRM_FORMAT_BGRX8888,
@@ -115,7 +91,9 @@ static const u32 mt8173_formats[] = {
 	DRM_FORMAT_YUYV,
 };
 
-static const u32 mt8195_formats[] = {
+const size_t mt8173_ovl_formats_len = ARRAY_SIZE(mt8173_ovl_formats);
+
+const u32 mt8195_ovl_formats[] = {
 	DRM_FORMAT_XRGB8888,
 	DRM_FORMAT_ARGB8888,
 	DRM_FORMAT_XRGB2101010,
@@ -139,6 +117,8 @@ static const u32 mt8195_formats[] = {
 	DRM_FORMAT_YUYV,
 };
 
+const size_t mt8195_ovl_formats_len = ARRAY_SIZE(mt8195_ovl_formats);
+
 struct mtk_disp_ovl_data {
 	unsigned int addr;
 	unsigned int gmc_bits;
@@ -167,6 +147,22 @@ struct mtk_disp_ovl {
 	void				*vblank_cb_data;
 };
 
+bool mtk_ovl_is_10bit_rgb(unsigned int fmt)
+{
+	switch (fmt) {
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_ARGB2101010:
+	case DRM_FORMAT_RGBX1010102:
+	case DRM_FORMAT_RGBA1010102:
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_ABGR2101010:
+	case DRM_FORMAT_BGRX1010102:
+	case DRM_FORMAT_BGRA1010102:
+		return true;
+	}
+	return false;
+}
+
 static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id)
 {
 	struct mtk_disp_ovl *priv = dev_id;
@@ -295,7 +291,7 @@ static void mtk_ovl_set_bit_depth(struct device *dev, int idx, u32 format,
 	if (!ovl->data->supports_clrfmt_ext)
 		return;
 
-	if (is_10bit_rgb(format))
+	if (mtk_ovl_is_10bit_rgb(format))
 		bit_depth = OVL_CON_CLRFMT_10_BIT;
 
 	mtk_ddp_write_mask(cmdq_pkt, OVL_CON_CLRFMT_BIT_DEPTH(bit_depth, idx),
@@ -394,10 +390,8 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx,
 		      DISP_REG_OVL_RDMA_CTRL(idx));
 }
 
-static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl,
-					struct mtk_plane_state *state)
+unsigned int mtk_ovl_get_blend_mode(struct mtk_plane_state *state, unsigned int blend_modes)
 {
-	unsigned int fmt = state->pending.format;
 	unsigned int blend_mode = DRM_MODE_BLEND_COVERAGE;
 
 	/*
@@ -412,52 +406,102 @@ static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl,
 	 * will get an error return from drm_plane_create_blend_mode_property() and
 	 * state->base.pixel_blend_mode should not be used.
 	 */
-	if (ovl->data->blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
+	if (blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
 		blend_mode = state->base.pixel_blend_mode;
 
+	return blend_mode;
+}
+
+unsigned int mtk_ovl_fmt_convert(unsigned int fmt, unsigned int blend_mode,
+				 bool fmt_rgb565_is_0, bool color_convert,
+				 u8 clrfmt_shift, u32 clrfmt_man, u32 byte_swap, u32 rgb_swap)
+{
+	unsigned int con = 0;
+	bool need_byte_swap = false, need_rgb_swap = false;
+
 	switch (fmt) {
 	default:
 	case DRM_FORMAT_RGB565:
-		return OVL_CON_CLRFMT_RGB565(ovl);
+		con = fmt_rgb565_is_0 ?
+			OVL_CON_CLRFMT_RGB565(clrfmt_shift) : OVL_CON_CLRFMT_RGB888(clrfmt_shift);
+	break;
 	case DRM_FORMAT_BGR565:
-		return OVL_CON_CLRFMT_RGB565(ovl) | OVL_CON_BYTE_SWAP;
+		con = fmt_rgb565_is_0 ?
+			OVL_CON_CLRFMT_RGB565(clrfmt_shift) : OVL_CON_CLRFMT_RGB888(clrfmt_shift);
+		need_byte_swap = true;	/* RGB565 -> BGR565 */
+	break;
 	case DRM_FORMAT_RGB888:
-		return OVL_CON_CLRFMT_RGB888(ovl);
+		con = fmt_rgb565_is_0 ?
+			OVL_CON_CLRFMT_RGB888(clrfmt_shift) : OVL_CON_CLRFMT_RGB565(clrfmt_shift);
+	break;
 	case DRM_FORMAT_BGR888:
-		return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP;
+		con = fmt_rgb565_is_0 ?
+			OVL_CON_CLRFMT_RGB888(clrfmt_shift) : OVL_CON_CLRFMT_RGB565(clrfmt_shift);
+		need_byte_swap = true;	/* RGB888 -> BGR888 */
+	break;
 	case DRM_FORMAT_RGBX8888:
 	case DRM_FORMAT_RGBA8888:
 	case DRM_FORMAT_RGBX1010102:
 	case DRM_FORMAT_RGBA1010102:
-		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
-		       OVL_CON_CLRFMT_RGBA8888 :
-		       OVL_CON_CLRFMT_PRGBA8888;
+		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
+			con = OVL_CON_CLRFMT_RGBA8888(clrfmt_shift);
+		} else {
+			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
+			need_byte_swap = true;	/* PARGB8888 -> PBGRA8888 */
+			need_rgb_swap = true;	/* PBGRA8888 -> PRGBA8888 */
+		}
+	break;
 	case DRM_FORMAT_BGRX8888:
 	case DRM_FORMAT_BGRA8888:
 	case DRM_FORMAT_BGRX1010102:
 	case DRM_FORMAT_BGRA1010102:
-		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
-		       OVL_CON_CLRFMT_BGRA8888 :
-		       OVL_CON_CLRFMT_PBGRA8888;
+		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
+			con = OVL_CON_CLRFMT_RGBA8888(clrfmt_shift);
+			need_byte_swap = true;	/* RGB8888 -> BGR8888 */
+		} else {
+			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
+			need_byte_swap = true;	/* PARGB8888 -> PBGRA8888 */
+		}
+	break;
 	case DRM_FORMAT_XRGB8888:
 	case DRM_FORMAT_ARGB8888:
 	case DRM_FORMAT_XRGB2101010:
 	case DRM_FORMAT_ARGB2101010:
-		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
-		       OVL_CON_CLRFMT_ARGB8888 :
-		       OVL_CON_CLRFMT_PARGB8888;
+		if (blend_mode == DRM_MODE_BLEND_COVERAGE)
+			con = OVL_CON_CLRFMT_ARGB8888(clrfmt_shift);
+		else
+			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
+	break;
 	case DRM_FORMAT_XBGR8888:
 	case DRM_FORMAT_ABGR8888:
 	case DRM_FORMAT_XBGR2101010:
 	case DRM_FORMAT_ABGR2101010:
-		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
-		       OVL_CON_CLRFMT_ABGR8888 :
-		       OVL_CON_CLRFMT_PABGR8888;
+		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
+			con = OVL_CON_CLRFMT_ARGB8888(clrfmt_shift);
+			need_rgb_swap = true;	/* ARGB8888 -> ABGR8888 */
+		} else {
+			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
+			need_rgb_swap = true;	/* PARGB8888 -> PABGR8888 */
+		}
+	break;
 	case DRM_FORMAT_UYVY:
-		return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB;
+		con = OVL_CON_CLRFMT_UYVY(clrfmt_shift);
+	break;
 	case DRM_FORMAT_YUYV:
-		return OVL_CON_CLRFMT_YUYV | OVL_CON_MTX_YUV_TO_RGB;
+		con = OVL_CON_CLRFMT_YUYV(clrfmt_shift);
+	break;
 	}
+
+	if (color_convert)
+		con |= OVL_CON_MTX_YUV_TO_RGB;
+
+	if (need_byte_swap)
+		con |= byte_swap;
+
+	if (need_rgb_swap)
+		con |= rgb_swap;
+
+	return con;
 }
 
 static void mtk_ovl_afbc_layer_config(struct mtk_disp_ovl *ovl,
@@ -504,7 +548,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
 		return;
 	}
 
-	con = mtk_ovl_fmt_convert(ovl, state);
+	con = mtk_ovl_fmt_convert(fmt, blend_mode, ovl->data->fmt_rgb565_is_0, true,
+				  12, OVL_CON_CLRFMT_MAN, OVL_CON_BYTE_SWAP, OVL_CON_RGB_SWAP);
 	if (state->base.fb) {
 		con |= state->base.alpha & OVL_CON_ALPHA;
 
@@ -514,15 +559,6 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
 		 */
 		if (blend_mode || state->base.fb->format->has_alpha)
 			con |= OVL_CON_AEN;
-
-		/*
-		 * Although the alpha channel can be ignored, CONST_BLD must be enabled
-		 * for XRGB format, otherwise OVL will still read the value from memory.
-		 * For RGB888 related formats, whether CONST_BLD is enabled or not won't
-		 * affect the result. Therefore we use !has_alpha as the condition.
-		 */
-		if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE || !state->base.fb->format->has_alpha)
-			ignore_pixel_alpha = OVL_CONST_BLEND;
 	}
 
 	/*
@@ -660,8 +696,8 @@ static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = {
 	.gmc_bits = 8,
 	.layer_nr = 4,
 	.fmt_rgb565_is_0 = false,
-	.formats = mt8173_formats,
-	.num_formats = ARRAY_SIZE(mt8173_formats),
+	.formats = mt8173_ovl_formats,
+	.num_formats = mt8173_ovl_formats_len,
 };
 
 static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = {
@@ -669,8 +705,8 @@ static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = {
 	.gmc_bits = 8,
 	.layer_nr = 4,
 	.fmt_rgb565_is_0 = true,
-	.formats = mt8173_formats,
-	.num_formats = ARRAY_SIZE(mt8173_formats),
+	.formats = mt8173_ovl_formats,
+	.num_formats = mt8173_ovl_formats_len,
 };
 
 static const struct mtk_disp_ovl_data mt8183_ovl_driver_data = {
@@ -678,8 +714,8 @@ static const struct mtk_disp_ovl_data mt8183_ovl_driver_data = {
 	.gmc_bits = 10,
 	.layer_nr = 4,
 	.fmt_rgb565_is_0 = true,
-	.formats = mt8173_formats,
-	.num_formats = ARRAY_SIZE(mt8173_formats),
+	.formats = mt8173_ovl_formats,
+	.num_formats = mt8173_ovl_formats_len,
 };
 
 static const struct mtk_disp_ovl_data mt8183_ovl_2l_driver_data = {
@@ -687,8 +723,8 @@ static const struct mtk_disp_ovl_data mt8183_ovl_2l_driver_data = {
 	.gmc_bits = 10,
 	.layer_nr = 2,
 	.fmt_rgb565_is_0 = true,
-	.formats = mt8173_formats,
-	.num_formats = ARRAY_SIZE(mt8173_formats),
+	.formats = mt8173_ovl_formats,
+	.num_formats = mt8173_ovl_formats_len,
 };
 
 static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = {
@@ -697,11 +733,9 @@ static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = {
 	.layer_nr = 4,
 	.fmt_rgb565_is_0 = true,
 	.smi_id_en = true,
-	.blend_modes = BIT(DRM_MODE_BLEND_PREMULTI) |
-		       BIT(DRM_MODE_BLEND_COVERAGE) |
-		       BIT(DRM_MODE_BLEND_PIXEL_NONE),
-	.formats = mt8173_formats,
-	.num_formats = ARRAY_SIZE(mt8173_formats),
+	.blend_modes = MTK_OVL_SUPPORT_BLEND_MODES,
+	.formats = mt8173_ovl_formats,
+	.num_formats = mt8173_ovl_formats_len,
 };
 
 static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = {
@@ -710,11 +744,9 @@ static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = {
 	.layer_nr = 2,
 	.fmt_rgb565_is_0 = true,
 	.smi_id_en = true,
-	.blend_modes = BIT(DRM_MODE_BLEND_PREMULTI) |
-		       BIT(DRM_MODE_BLEND_COVERAGE) |
-		       BIT(DRM_MODE_BLEND_PIXEL_NONE),
-	.formats = mt8173_formats,
-	.num_formats = ARRAY_SIZE(mt8173_formats),
+	.blend_modes = MTK_OVL_SUPPORT_BLEND_MODES,
+	.formats = mt8173_ovl_formats,
+	.num_formats = mt8173_ovl_formats_len,
 };
 
 static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = {
@@ -724,11 +756,9 @@ static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = {
 	.fmt_rgb565_is_0 = true,
 	.smi_id_en = true,
 	.supports_afbc = true,
-	.blend_modes = BIT(DRM_MODE_BLEND_PREMULTI) |
-		       BIT(DRM_MODE_BLEND_COVERAGE) |
-		       BIT(DRM_MODE_BLEND_PIXEL_NONE),
-	.formats = mt8195_formats,
-	.num_formats = ARRAY_SIZE(mt8195_formats),
+	.blend_modes = MTK_OVL_SUPPORT_BLEND_MODES,
+	.formats = mt8195_ovl_formats,
+	.num_formats = mt8195_ovl_formats_len,
 	.supports_clrfmt_ext = true,
 };
 
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.h b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
new file mode 100644
index 000000000000..3f7d7d54479d
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ */
+
+#ifndef __MTK_DISP_OVL_H__
+#define __MTK_DISP_OVL_H__
+
+#include <drm/drm_blend.h>
+#include <drm/drm_fourcc.h>
+
+#define MTK_OVL_SUPPORT_BLEND_MODES \
+	(BIT(DRM_MODE_BLEND_PREMULTI) | \
+	 BIT(DRM_MODE_BLEND_COVERAGE) | \
+	 BIT(DRM_MODE_BLEND_PIXEL_NONE))
+
+extern const u32 mt8173_ovl_formats[];
+extern const size_t mt8173_ovl_formats_len;
+extern const u32 mt8195_ovl_formats[];
+extern const size_t mt8195_ovl_formats_len;
+
+bool mtk_ovl_is_10bit_rgb(unsigned int fmt);
+unsigned int mtk_ovl_get_blend_mode(struct mtk_plane_state *state, unsigned int blend_modes);
+unsigned int mtk_ovl_fmt_convert(unsigned int fmt, unsigned int blend_mode,
+				 bool fmt_rgb565_is_0, bool color_convert,
+				 u8 clrfmt_shift, u32 clrfmt_man, u32 byte_swap, u32 rgb_swap);
+
+#endif
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v3 11/17] drm/mediatek: drm/mediatek: Export OVL ignore pixel alpha function
  2025-05-15  9:34 [PATCH v3 00/17] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
                   ` (9 preceding siblings ...)
  2025-05-15  9:34 ` [PATCH v3 10/17] drm/mediatek: Export OVL formats definitions and format conversion API paul-pl.chen
@ 2025-05-15  9:34 ` paul-pl.chen
  2025-06-17  6:06   ` CK Hu (胡俊光)
  2025-05-15  9:34 ` [PATCH v3 12/17] drm/mediatek: add EXDMA support for MT8196 paul-pl.chen
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 35+ messages in thread
From: paul-pl.chen @ 2025-05-15  9:34 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
  Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
	xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
	treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group

From: Nancy Lin <nancy.lin@mediatek.com>

For the new BLENDER component, the OVL ignore pixel alpha logic
should be exported as a function and reused it.

Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 24 ++++++++++++++++++++++--
 drivers/gpu/drm/mediatek/mtk_disp_ovl.h |  1 +
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index a516b7c82b5a..747898a574da 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -211,6 +211,23 @@ void mtk_ovl_disable_vblank(struct device *dev)
 	writel_relaxed(0x0, ovl->regs + DISP_REG_OVL_INTEN);
 }
 
+bool mtk_ovl_is_ignore_pixel_alpha(struct mtk_plane_state *state, unsigned int blend_mode)
+{
+	if (!state->base.fb)
+		return false;
+	/*
+	 * Although the alpha channel can be ignored, CONST_BLD must be enabled
+	 * for XRGB format, otherwise OVL will still read the value from memory.
+	 * For RGB888 related formats, whether CONST_BLD is enabled or not won't
+	 * affect the result. Therefore we use !has_alpha as the condition.
+	 */
+
+	if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE || !state->base.fb->format->has_alpha)
+		return true;
+
+	return false;
+}
+
 u32 mtk_ovl_get_blend_modes(struct device *dev)
 {
 	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
@@ -539,7 +556,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
 	unsigned int rotation = pending->rotation;
 	unsigned int offset = (pending->y << 16) | pending->x;
 	unsigned int src_size = (pending->height << 16) | pending->width;
-	unsigned int blend_mode = state->base.pixel_blend_mode;
+	unsigned int blend_mode = mtk_ovl_get_blend_mode(state, ovl->data->blend_modes);
 	unsigned int ignore_pixel_alpha = 0;
 	unsigned int con;
 
@@ -557,7 +574,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
 		 * For blend_modes supported SoCs, always enable alpha blending.
 		 * For blend_modes unsupported SoCs, enable alpha blending when has_alpha is set.
 		 */
-		if (blend_mode || state->base.fb->format->has_alpha)
+		if (state->base.pixel_blend_mode || state->base.fb->format->has_alpha)
 			con |= OVL_CON_AEN;
 	}
 
@@ -584,6 +601,9 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
 
 	mtk_ddp_write_relaxed(cmdq_pkt, con, &ovl->cmdq_reg, ovl->regs,
 			      DISP_REG_OVL_CON(idx));
+
+	if (mtk_ovl_is_ignore_pixel_alpha(state, blend_mode))
+		ignore_pixel_alpha = OVL_CONST_BLEND;
 	mtk_ddp_write_relaxed(cmdq_pkt, pitch_lsb | ignore_pixel_alpha,
 			      &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH(idx));
 	mtk_ddp_write_relaxed(cmdq_pkt, src_size, &ovl->cmdq_reg, ovl->regs,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.h b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
index 3f7d7d54479d..431567538eb5 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
@@ -20,6 +20,7 @@ extern const u32 mt8195_ovl_formats[];
 extern const size_t mt8195_ovl_formats_len;
 
 bool mtk_ovl_is_10bit_rgb(unsigned int fmt);
+bool mtk_ovl_is_ignore_pixel_alpha(struct mtk_plane_state *state, unsigned int blend_mode);
 unsigned int mtk_ovl_get_blend_mode(struct mtk_plane_state *state, unsigned int blend_modes);
 unsigned int mtk_ovl_fmt_convert(unsigned int fmt, unsigned int blend_mode,
 				 bool fmt_rgb565_is_0, bool color_convert,
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v3 12/17] drm/mediatek: add EXDMA support for MT8196
  2025-05-15  9:34 [PATCH v3 00/17] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
                   ` (10 preceding siblings ...)
  2025-05-15  9:34 ` [PATCH v3 11/17] drm/mediatek: drm/mediatek: Export OVL ignore pixel alpha function paul-pl.chen
@ 2025-05-15  9:34 ` paul-pl.chen
  2025-06-17  9:17   ` CK Hu (胡俊光)
  2025-05-15  9:34 ` [PATCH v3 13/17] drm/mediatek: add BLENDER " paul-pl.chen
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 35+ messages in thread
From: paul-pl.chen @ 2025-05-15  9:34 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
  Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
	xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
	treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group

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 | 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_CON		0xc
+#define OVL_EXDMA_OP_8BIT_MODE				BIT(4)
+#define OVL_EXDMA_HG_FOVL_EXDMA_CK_ON			BIT(8)
+#define OVL_EXDMA_HF_FOVL_EXDMA_CK_ON			BIT(10)
+#define DISP_REG_OVL_EXDMA_DATAPATH_CON		0x014
+#define OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN		BIT(0)
+#define OVL_EXDMA_DATAPATH_CON_GCLAST_EN		BIT(24)
+#define OVL_EXDMA_DATAPATH_CON_HDR_GCLAST_EN		BIT(25)
+#define DISP_REG_OVL_EXDMA_EN			0x020
+#define OVL_EXDMA_EN					BIT(0)
+#define DISP_REG_OVL_EXDMA_RST			0x024
+#define OVL_EXDMA_RST					BIT(0)
+#define DISP_REG_OVL_EXDMA_ROI_SIZE		0x030
+#define DISP_REG_OVL_EXDMA_L0_EN		0x040
+#define OVL_EXDMA_L0_EN					BIT(0)
+#define DISP_REG_OVL_EXDMA_L0_OFFSET		0x044
+#define DISP_REG_OVL_EXDMA_SRC_SIZE		0x048
+#define DISP_REG_OVL_EXDMA_L0_CLRFMT		0x050
+#define OVL_EXDMA_CON_FLD_CLRFMT			GENMASK(3, 0)
+#define OVL_EXDMA_CON_CLRFMT_MAN			BIT(4)
+#define OVL_EXDMA_CON_FLD_CLRFMT_NB			GENMASK(9, 8)
+#define OVL_EXDMA_CON_CLRFMT_NB_10_BIT			BIT(8)
+#define OVL_EXDMA_CON_BYTE_SWAP				BIT(16)
+#define OVL_EXDMA_CON_RGB_SWAP				BIT(17)
+#define DISP_REG_OVL_EXDMA_RDMA0_CTRL		0x100
+#define OVL_EXDMA_RDMA0_EN				BIT(0)
+#define DISP_REG_OVL_EXDMA_RDMA_BURST_CON1	0x1f4
+#define OVL_EXDMA_RDMA_BURST_CON1_BURST16_EN		BIT(28)
+#define OVL_EXDMA_RDMA_BURST_CON1_DDR_EN		BIT(30)
+#define OVL_EXDMA_RDMA_BURST_CON1_DDR_ACK_EN		BIT(31)
+#define DISP_REG_OVL_EXDMA_DUMMY_REG		0x200
+#define OVL_EXDMA_EXT_DDR_EN_OPT			BIT(2)
+#define OVL_EXDMA_FORCE_EXT_DDR_EN			BIT(3)
+#define DISP_REG_OVL_EXDMA_GDRDY_PRD		0x208
+#define DISP_REG_OVL_EXDMA_PITCH_MSB		0x2f0
+#define OVL_EXDMA_L0_SRC_PITCH_MSB_MASK			GENMASK(3, 0)
+#define DISP_REG_OVL_EXDMA_PITCH		0x2f4
+#define OVL_EXDMA_L0_SRC_PITCH				GENMASK(15, 0)
+#define OVL_EXDMA_L0_CONST_BLD				BIT(28)
+#define OVL_EXDMA_L0_SRC_PITCH_MASK			GENMASK(15, 0)
+#define DISP_REG_OVL_EXDMA_L0_GUSER_EXT		0x2fc
+#define OVL_EXDMA_RDMA0_L0_VCSEL			BIT(5)
+#define OVL_EXDMA_RDMA0_HDR_L0_VCSEL			BIT(21)
+#define DISP_REG_OVL_EXDMA_CON			0x300
+#define OVL_EXDMA_CON_FLD_INT_MTX_SEL			GENMASK(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_EN			BIT(27)
+#define DISP_REG_OVL_EXDMA_ADDR			0xf40
+#define DISP_REG_OVL_EXDMA_MOUT			0xff0
+#define OVL_EXDMA_MOUT_OUT_DATA				BIT(0)
+#define OVL_EXDMA_MOUT_BGCLR_OUT			BIT(1)
+
+struct mtk_disp_exdma {
+	void __iomem		*regs;
+	struct clk		*clk;
+	struct cmdq_client_reg	cmdq_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;
+
+	/*
+	 * 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)
+{
+	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);
+
+	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);
+}
+
+const u32 *mtk_disp_exdma_get_formats(struct device *dev)
+{
+	return mt8195_ovl_formats;
+}
+
+size_t mtk_disp_exdma_get_num_formats(struct device *dev)
+{
+	return mt8195_ovl_formats_len;
+}
+
+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);
+	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;
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v3 13/17] drm/mediatek: add BLENDER support for MT8196
  2025-05-15  9:34 [PATCH v3 00/17] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
                   ` (11 preceding siblings ...)
  2025-05-15  9:34 ` [PATCH v3 12/17] drm/mediatek: add EXDMA support for MT8196 paul-pl.chen
@ 2025-05-15  9:34 ` paul-pl.chen
  2025-06-18  6:40   ` CK Hu (胡俊光)
  2025-05-15  9:34 ` [PATCH v3 14/17] drm/mediatek: add OUTPROC " paul-pl.chen
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 35+ messages in thread
From: paul-pl.chen @ 2025-05-15  9:34 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
  Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
	xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
	treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group

From: Paul-pl Chen <paul-pl.chen@mediatek.com>

BLENDER executes the alpha blending function for overlapping
layers from different sources, which is the primary function
of the overlapping system.

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_blender.c | 264 ++++++++++++++++++++
 drivers/gpu/drm/mediatek/mtk_disp_blender.h |  10 +
 drivers/gpu/drm/mediatek/mtk_disp_drv.h     |  12 +
 drivers/gpu/drm/mediatek/mtk_drm_drv.c      |   1 +
 drivers/gpu/drm/mediatek/mtk_drm_drv.h      |   1 +
 8 files changed, 291 insertions(+)
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_blender.c
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_blender.h

diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
index db92f4fb353d..a7b9ebe27f68 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -3,6 +3,7 @@
 mediatek-drm-y := mtk_crtc.o \
 		  mtk_ddp_comp.o \
 		  mtk_disp_aal.o \
+		  mtk_disp_blender.o \
 		  mtk_disp_ccorr.o \
 		  mtk_disp_color.o \
 		  mtk_disp_exdma.o \
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index 3e0739d8e6f1..e65c6df987f2 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_BLENDER] = "blender",
 	[MTK_OVL_EXDMA] = "exdma",
 };
 
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
index 86dc0ee3924c..075ba5683f93 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_BLENDER,
 	MTK_OVL_EXDMA,
 	MTK_DDP_COMP_TYPE_MAX,
 };
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_blender.c b/drivers/gpu/drm/mediatek/mtk_disp_blender.c
new file mode 100644
index 000000000000..7c73bce99592
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_blender.c
@@ -0,0 +1,264 @@
+// 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.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 "mtk_disp_drv.h"
+#include "mtk_drm_drv.h"
+#include "mtk_disp_blender.h"
+#include "mtk_disp_ovl.h"
+
+#define DISP_REG_OVL_BLD_DATAPATH_CON			0x010
+#define OVL_BLD_BGCLR_IN_SEL					BIT(0)
+#define OVL_BLD_BGCLR_OUT_TO_PROC				BIT(4)
+#define OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER				BIT(5)
+#define DISP_REG_OVL_BLD_EN				0x020
+#define OVL_BLD_EN						BIT(0)
+#define OVL_BLD_FORCE_RELAY_MODE				BIT(4)
+#define OVL_BLD_RELAY_MODE					BIT(5)
+#define DISP_REG_OVL_BLD_RST				0x024
+#define OVL_BLD_RST						BIT(0)
+#define DISP_REG_OVL_BLD_SHADOW_CTRL			0x028
+#define OVL_BLD_BYPASS_SHADOW					BIT(2)
+#define DISP_REG_OVL_BLD_BGCLR_BALCK			0xff000000
+#define DISP_REG_OVL_BLD_ROI_SIZE			0x030
+#define DISP_REG_OVL_BLD_L_EN				0x040
+#define OVL_BLD_L_EN						BIT(0)
+#define DISP_REG_OVL_BLD_OFFSET				0x044
+#define DISP_REG_OVL_BLD_SRC_SIZE			0x048
+#define DISP_REG_OVL_BLD_L0_CLRFMT			0x050
+#define OVL_BLD_CON_FLD_CLRFMT					GENMASK(3, 0)
+#define OVL_BLD_CON_CLRFMT_MAN					BIT(4)
+#define OVL_BLD_CON_FLD_CLRFMT_NB				GENMASK(9, 8)
+#define OVL_BLD_CON_CLRFMT_NB_10_BIT				BIT(8)
+#define OVL_BLD_CON_BYTE_SWAP					BIT(16)
+#define OVL_BLD_CON_RGB_SWAP					BIT(17)
+#define DISP_REG_OVL_BLD_BGCLR_CLR			0x104
+#define DISP_REG_OVL_BLD_L_CON2				0x200
+#define OVL_BLD_L_ALPHA						GENMASK(7, 0)
+#define OVL_BLD_L_ALPHA_EN					BIT(12)
+#define DISP_REG_OVL_BLD_L0_ALPHA_SEL			0x208
+#define OVL_BLD_L0_CONST					BIT(24)
+#define DISP_REG_OVL_BLD_L0_CLR				0x20c
+#define OVL_BLD_CON_CLRFMT_MAN					BIT(4)
+
+struct mtk_disp_blender {
+	void __iomem		*regs;
+	struct clk		*clk;
+	struct cmdq_client_reg	cmdq_reg;
+};
+
+void mtk_disp_blender_layer_config(struct device *dev, struct mtk_plane_state *state,
+				   struct cmdq_pkt *cmdq_pkt)
+{
+	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+	struct mtk_plane_pending_state *pending = &state->pending;
+	u32 alpha, clrfmt, ignore_pixel_alpha = 0;
+	u32 blend_mode = mtk_ovl_get_blend_mode(state, MTK_OVL_SUPPORT_BLEND_MODES);
+
+	if (!pending->enable) {
+		mtk_ddp_write(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_L_EN);
+		return;
+	}
+
+	mtk_ddp_write(cmdq_pkt, pending->y << 16 | pending->x, &priv->cmdq_reg, priv->regs,
+		      DISP_REG_OVL_BLD_OFFSET);
+
+	mtk_ddp_write(cmdq_pkt, pending->height << 16 | pending->width, &priv->cmdq_reg,
+		      priv->regs, DISP_REG_OVL_BLD_SRC_SIZE);
+
+	clrfmt = mtk_ovl_fmt_convert(pending->format, blend_mode, true, false, 0,
+				     OVL_BLD_CON_CLRFMT_MAN, OVL_BLD_CON_BYTE_SWAP,
+				     OVL_BLD_CON_RGB_SWAP);
+	clrfmt |= mtk_ovl_is_10bit_rgb(pending->format) ? OVL_BLD_CON_CLRFMT_NB_10_BIT : 0;
+	mtk_ddp_write_mask(cmdq_pkt, clrfmt, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_BLD_L0_CLRFMT, OVL_BLD_CON_CLRFMT_MAN |
+			   OVL_BLD_CON_RGB_SWAP |  OVL_BLD_CON_BYTE_SWAP |
+			   OVL_BLD_CON_FLD_CLRFMT | OVL_BLD_CON_FLD_CLRFMT_NB);
+
+	if (mtk_ovl_is_ignore_pixel_alpha(state, blend_mode))
+		ignore_pixel_alpha = OVL_BLD_L0_CONST;
+	mtk_ddp_write_mask(cmdq_pkt, ignore_pixel_alpha, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_BLD_L0_ALPHA_SEL, OVL_BLD_L0_CONST);
+
+	alpha = (OVL_BLD_L_ALPHA & (state->base.alpha >> 8)) | OVL_BLD_L_ALPHA_EN;
+	mtk_ddp_write_mask(cmdq_pkt, alpha, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_BLD_L_CON2, OVL_BLD_L_ALPHA_EN | OVL_BLD_L_ALPHA);
+
+	mtk_ddp_write(cmdq_pkt, OVL_BLD_L_EN, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_L_EN);
+}
+
+void mtk_disp_blender_config(struct device *dev, unsigned int w,
+			     unsigned int h, unsigned int vrefresh,
+			     unsigned int bpc, bool most_top,
+			     bool most_bottom, struct cmdq_pkt *cmdq_pkt)
+{
+	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+	u32 datapath;
+
+	dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
+	mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs,
+		      DISP_REG_OVL_BLD_ROI_SIZE);
+	mtk_ddp_write(cmdq_pkt, DISP_REG_OVL_BLD_BGCLR_BALCK, &priv->cmdq_reg, priv->regs,
+		      DISP_REG_OVL_BLD_BGCLR_CLR);
+
+	/*
+	 * The input source of blender layer can be EXDMA layer output or
+	 * the blender constant layer itself.
+	 * This color setting is configured for the blender constant layer.
+	 */
+	mtk_ddp_write(cmdq_pkt, DISP_REG_OVL_BLD_BGCLR_BALCK, &priv->cmdq_reg, priv->regs,
+		      DISP_REG_OVL_BLD_L0_CLR);
+
+	if (most_top)
+		datapath = OVL_BLD_BGCLR_OUT_TO_PROC;
+	else
+		datapath = OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER;
+	/*
+	 * The primary input is from EXDMA and the second input
+	 * is optionally from another blender
+	 */
+	if (!most_bottom)
+		datapath |= OVL_BLD_BGCLR_IN_SEL;
+
+	mtk_ddp_write_mask(cmdq_pkt, datapath,
+			   &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_DATAPATH_CON,
+			   OVL_BLD_BGCLR_OUT_TO_PROC | OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER |
+			   OVL_BLD_BGCLR_IN_SEL);
+}
+
+void mtk_disp_blender_start(struct device *dev, struct cmdq_pkt *cmdq_pkt)
+{
+	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+
+	mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_BYPASS_SHADOW, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_BLD_SHADOW_CTRL, OVL_BLD_BYPASS_SHADOW);
+	mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_EN, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_BLD_EN, OVL_BLD_EN);
+}
+
+void mtk_disp_blender_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt)
+{
+	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+
+	mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_BLD_EN, OVL_BLD_EN);
+
+	mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_RST, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_BLD_RST, OVL_BLD_RST);
+	mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_BLD_RST, OVL_BLD_RST);
+}
+
+int mtk_disp_blender_clk_enable(struct device *dev)
+{
+	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+
+	return clk_prepare_enable(priv->clk);
+}
+
+void mtk_disp_blender_clk_disable(struct device *dev)
+{
+	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(priv->clk);
+}
+
+u32 mtk_disp_blender_get_blend_modes(struct device *dev)
+{
+	return MTK_OVL_SUPPORT_BLEND_MODES;
+}
+
+static int mtk_disp_blender_bind(struct device *dev, struct device *master,
+				 void *data)
+{
+	return 0;
+}
+
+static void mtk_disp_blender_unbind(struct device *dev, struct device *master, void *data)
+{
+}
+
+static const struct component_ops mtk_disp_blender_component_ops = {
+	.bind	= mtk_disp_blender_bind,
+	.unbind = mtk_disp_blender_unbind,
+};
+
+static int mtk_disp_blender_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct mtk_disp_blender *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 blender\n");
+		return PTR_ERR(priv->regs);
+	}
+
+	priv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(dev, "failed to get blender 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
+	platform_set_drvdata(pdev, priv);
+
+	ret = component_add(dev, &mtk_disp_blender_component_ops);
+	if (ret)
+		dev_notice(dev, "Failed to add component: %d\n", ret);
+
+	return ret;
+}
+
+static void mtk_disp_blender_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &mtk_disp_blender_component_ops);
+}
+
+static const struct of_device_id mtk_disp_blender_driver_dt_match[] = {
+	{ .compatible = "mediatek,mt8196-blender"},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, mtk_disp_blender_driver_dt_match);
+
+struct platform_driver mtk_disp_blender_driver = {
+	.probe		= mtk_disp_blender_probe,
+	.remove		= mtk_disp_blender_remove,
+	.driver		= {
+		.name	= "mediatek-disp-blender",
+		.owner	= THIS_MODULE,
+		.of_match_table = mtk_disp_blender_driver_dt_match,
+	},
+};
+
+MODULE_AUTHOR("Nancy Lin <nancy.lin@mediatek.com>");
+MODULE_DESCRIPTION("MediaTek Blender Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_blender.h b/drivers/gpu/drm/mediatek/mtk_disp_blender.h
new file mode 100644
index 000000000000..a47ab128649d
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_blender.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ */
+
+#ifndef __MTK_DISP_BLENDER_H__
+#define __MTK_DISP_BLENDER_H__
+
+u32 mtk_disp_blender_get_blend_modes(struct device *dev);
+#endif // __MTK_DISP_BLENDER_H__
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index 4e3d2510bef5..39e3af1e2b16 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -9,6 +9,7 @@
 #include <linux/soc/mediatek/mtk-cmdq.h>
 #include <linux/soc/mediatek/mtk-mmsys.h>
 #include <linux/soc/mediatek/mtk-mutex.h>
+#include "mtk_disp_blender.h"
 #include "mtk_mdp_rdma.h"
 #include "mtk_plane.h"
 
@@ -39,6 +40,17 @@ 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);
 
+void mtk_disp_blender_start(struct device *dev, struct cmdq_pkt *cmdq_pkt);
+void mtk_disp_blender_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt);
+int mtk_disp_blender_clk_enable(struct device *dev);
+void mtk_disp_blender_clk_disable(struct device *dev);
+void mtk_disp_blender_config(struct device *dev, unsigned int w,
+			     unsigned int h, unsigned int vrefresh,
+			     unsigned int bpc, bool most_top, bool most_bottom,
+			     struct cmdq_pkt *cmdq_pkt);
+void mtk_disp_blender_layer_config(struct device *dev, struct mtk_plane_state *state,
+				   struct cmdq_pkt *cmdq_pkt);
+
 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);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index bb7306a942ff..7a14f45d5f97 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -1274,6 +1274,7 @@ static struct platform_driver mtk_drm_platform_driver = {
 
 static struct platform_driver * const mtk_drm_drivers[] = {
 	&mtk_disp_aal_driver,
+	&mtk_disp_blender_driver,
 	&mtk_disp_ccorr_driver,
 	&mtk_disp_color_driver,
 	&mtk_disp_exdma_driver,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index 898a75898775..89178de1478f 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -70,6 +70,7 @@ struct mtk_drm_private {
 };
 
 extern struct platform_driver mtk_disp_aal_driver;
+extern struct platform_driver mtk_disp_blender_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;
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v3 14/17] drm/mediatek: add OUTPROC support for MT8196
  2025-05-15  9:34 [PATCH v3 00/17] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
                   ` (12 preceding siblings ...)
  2025-05-15  9:34 ` [PATCH v3 13/17] drm/mediatek: add BLENDER " paul-pl.chen
@ 2025-05-15  9:34 ` paul-pl.chen
  2025-06-18  8:23   ` CK Hu (胡俊光)
  2025-05-15  9:34 ` [PATCH v3 15/17] drm/mediatek: add ovlsys_adaptor " paul-pl.chen
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 35+ messages in thread
From: paul-pl.chen @ 2025-05-15  9:34 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
  Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
	xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
	treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group

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 | 240 ++++++++++++++++++++
 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, 281 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 39e3af1e2b16..3c519a662074 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..bc0b2388e9d6
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_outproc.c
@@ -0,0 +1,240 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ */
+
+#include <drm/drm_fourcc.h>
+#include <drm/drm_framebuffer.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of.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 "mtk_disp_outproc.h"
+#include "mtk_drm_drv.h"
+
+#define DISP_REG_OVL_OUTPROC_INTEN				0x004
+#define OVL_OUTPROC_FME_CPL_INTEN					BIT(1)
+#define DISP_REG_OVL_OUTPROC_INTSTA				0x008
+#define DISP_REG_OVL_OUTPROC_DATAPATH_CON			0x010
+#define OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP				BIT(26)
+
+#define DISP_REG_OVL_OUTPROC_EN					0x020
+#define OVL_OUTPROC_OVL_EN						BIT(0)
+#define DISP_REG_OVL_OUTPROC_RST				0x024
+#define OVL_OUTPROC_RST							BIT(0)
+#define DISP_REG_OVL_OUTPROC_SHADOW_CTRL			0x028
+#define OVL_OUTPROC_BYPASS_SHADOW					BIT(2)
+#define DISP_REG_OVL_OUTPROC_ROI_SIZE				0x030
+
+struct mtk_disp_outproc {
+	void __iomem		*regs;
+	struct clk		*clk;
+	void			(*vblank_cb)(void *data);
+	void			*vblank_cb_data;
+	int			irq;
+	struct cmdq_client_reg	cmdq_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;
+	u32 val;
+
+	val = readl(priv->regs + DISP_REG_OVL_OUTPROC_INTSTA);
+	if (!val)
+		return IRQ_NONE;
+
+	writel(0x0, priv->regs + DISP_REG_OVL_OUTPROC_INTSTA);
+
+	if (priv->vblank_cb)
+		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);
+	u32 tmp;
+
+	dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
+
+	writel((h << 16) | w, priv->regs + DISP_REG_OVL_OUTPROC_ROI_SIZE);
+
+	tmp = readl(priv->regs + DISP_REG_OVL_OUTPROC_DATAPATH_CON);
+	tmp = (tmp & ~OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP) |
+		  (OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP & OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP);
+	writel(tmp, priv->regs + DISP_REG_OVL_OUTPROC_DATAPATH_CON);
+}
+
+void mtk_disp_outproc_start(struct device *dev)
+{
+	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+	unsigned int tmp;
+
+	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);
+
+	writel(0, priv->regs + DISP_REG_OVL_OUTPROC_INTSTA);
+
+	tmp = readl(priv->regs + DISP_REG_OVL_OUTPROC_EN);
+	tmp = (tmp & ~OVL_OUTPROC_OVL_EN) | (OVL_OUTPROC_OVL_EN & OVL_OUTPROC_OVL_EN);
+	writel(tmp, priv->regs + DISP_REG_OVL_OUTPROC_EN);
+}
+
+void mtk_disp_outproc_stop(struct device *dev)
+{
+	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+	writel(0, priv->regs + DISP_REG_OVL_OUTPROC_EN);
+	writel(OVL_OUTPROC_RST, priv->regs + DISP_REG_OVL_OUTPROC_RST);
+	writel(0, priv->regs + DISP_REG_OVL_OUTPROC_RST);
+}
+
+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 mtk_disp_outproc *priv;
+	int ret = 0;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(priv->regs))
+		return dev_err_probe(dev, PTR_ERR(priv->regs), "failed to ioremap outproc\n");
+
+	priv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(priv->clk))
+		return dev_err_probe(dev, PTR_ERR(priv->clk), "failed to get outproc clk\n");
+
+#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");
+	} else {
+		priv->irq = platform_get_irq(pdev, 0);
+		if (priv->irq < 0)
+			priv->irq = 0;
+
+		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)
+		return dev_err_probe(dev, ret, "Failed to add component\n");
+
+	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..abb101979521
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_outproc.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025 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 7a14f45d5f97..f7b9c7a982a7 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -1280,6 +1280,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;
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v3 15/17] drm/mediatek: add ovlsys_adaptor support for MT8196
  2025-05-15  9:34 [PATCH v3 00/17] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
                   ` (13 preceding siblings ...)
  2025-05-15  9:34 ` [PATCH v3 14/17] drm/mediatek: add OUTPROC " paul-pl.chen
@ 2025-05-15  9:34 ` paul-pl.chen
  2025-05-16  6:34   ` kernel test robot
  2025-06-24  5:46   ` CK Hu (胡俊光)
  2025-05-15  9:34 ` [PATCH v3 16/17] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver paul-pl.chen
  2025-05-15  9:34 ` [PATCH v3 17/17] drm/mediatek: Add support for MT8196 multiple mmsys paul-pl.chen
  16 siblings, 2 replies; 35+ messages in thread
From: paul-pl.chen @ 2025-05-15  9:34 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
  Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
	xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
	treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group

From: Nancy Lin <nancy.lin@mediatek.com>

Ovlsys_adaptor is an encapsulated module designed to
simplify the DRM control flow. This module is composed
of 20 EXDMAs, 20 BLENDERs, and 12 OUTPROCs.
Two EXDMAs merge into one layer, allowing the module
to support 20 layers for 3 display paths.
Ovlsys_adaptor driver is integrated within the
mtk_ddp_comp framework.

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       |  28 +
 drivers/gpu/drm/mediatek/mtk_ddp_comp.h       |   1 +
 drivers/gpu/drm/mediatek/mtk_disp_drv.h       |  32 +
 .../drm/mediatek/mtk_disp_ovlsys_adaptor.c    | 729 ++++++++++++++++++
 drivers/gpu/drm/mediatek/mtk_drm_drv.c        |  69 +-
 drivers/gpu/drm/mediatek/mtk_drm_drv.h        |  10 +-
 7 files changed, 846 insertions(+), 24 deletions(-)
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c

diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
index 9546bc6b7b2e..dedf50860d3f 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -9,6 +9,7 @@ mediatek-drm-y := mtk_crtc.o \
 		  mtk_disp_exdma.o \
 		  mtk_disp_gamma.o \
 		  mtk_disp_merge.o \
+		  mtk_disp_ovlsys_adaptor.o \
 		  mtk_disp_ovl.o \
 		  mtk_disp_outproc.o \
 		  mtk_disp_ovl_adaptor.o \
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index cc780744f060..c96e027359ac 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -368,6 +368,31 @@ static const struct mtk_ddp_comp_funcs ddp_ovl = {
 	.get_num_formats = mtk_ovl_get_num_formats,
 };
 
+static const struct mtk_ddp_comp_funcs ddp_ovlsys_adaptor = {
+	.power_on = mtk_ovlsys_adaptor_power_on,
+	.power_off = mtk_ovlsys_adaptor_power_off,
+	.clk_enable = mtk_ovlsys_adaptor_clk_enable,
+	.clk_disable = mtk_ovlsys_adaptor_clk_disable,
+	.config = mtk_ovlsys_adaptor_config,
+	.start = mtk_ovlsys_adaptor_start,
+	.stop = mtk_ovlsys_adaptor_stop,
+	.layer_check = mtk_ovlsys_adaptor_layer_check,
+	.layer_nr = mtk_ovlsys_adaptor_layer_nr,
+	.layer_config = mtk_ovlsys_adaptor_layer_config,
+	.register_vblank_cb = mtk_ovlsys_adaptor_register_vblank_cb,
+	.unregister_vblank_cb = mtk_ovlsys_adaptor_unregister_vblank_cb,
+	.enable_vblank = mtk_ovlsys_adaptor_enable_vblank,
+	.disable_vblank = mtk_ovlsys_adaptor_disable_vblank,
+	.dma_dev_get = mtk_ovlsys_adaptor_dma_dev_get,
+	.connect = mtk_ovlsys_adaptor_connect,
+	.disconnect = mtk_ovlsys_adaptor_disconnect,
+	.add = mtk_ovlsys_adaptor_add_comp,
+	.remove = mtk_ovlsys_adaptor_remove_comp,
+	.get_blend_modes = mtk_ovlsys_adaptor_get_blend_modes,
+	.get_formats = mtk_ovlsys_adaptor_get_formats,
+	.get_num_formats = mtk_ovlsys_adaptor_get_num_formats,
+};
+
 static const struct mtk_ddp_comp_funcs ddp_postmask = {
 	.clk_enable = mtk_ddp_clk_enable,
 	.clk_disable = mtk_ddp_clk_disable,
@@ -437,6 +462,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
 	[MTK_DISP_OVL] = "ovl",
 	[MTK_DISP_OVL_2L] = "ovl-2l",
 	[MTK_DISP_OVL_ADAPTOR] = "ovl_adaptor",
+	[MTK_DISP_OVLSYS_ADAPTOR] = "ovlsys_adaptor",
 	[MTK_DISP_POSTMASK] = "postmask",
 	[MTK_DISP_PWM] = "pwm",
 	[MTK_DISP_RDMA] = "rdma",
@@ -469,6 +495,8 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
 	[DDP_COMPONENT_DPI0]		= { MTK_DPI,			0, &ddp_dpi },
 	[DDP_COMPONENT_DPI1]		= { MTK_DPI,			1, &ddp_dpi },
 	[DDP_COMPONENT_DRM_OVL_ADAPTOR]	= { MTK_DISP_OVL_ADAPTOR,	0, &ddp_ovl_adaptor },
+	[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0] = { MTK_DISP_OVLSYS_ADAPTOR, 0, &ddp_ovlsys_adaptor},
+	[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1] = { MTK_DISP_OVLSYS_ADAPTOR, 1, &ddp_ovlsys_adaptor},
 	[DDP_COMPONENT_DSC0]		= { MTK_DISP_DSC,		0, &ddp_dsc },
 	[DDP_COMPONENT_DSC1]		= { MTK_DISP_DSC,		1, &ddp_dsc },
 	[DDP_COMPONENT_DSI0]		= { MTK_DSI,			0, &ddp_dsi },
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
index b33d3289b8b6..ef64ce7a071f 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
@@ -33,6 +33,7 @@ enum mtk_ddp_comp_type {
 	MTK_DISP_MUTEX,
 	MTK_DISP_OD,
 	MTK_DISP_OVL,
+	MTK_DISP_OVLSYS_ADAPTOR,
 	MTK_DISP_OVL_2L,
 	MTK_DISP_OVL_ADAPTOR,
 	MTK_DISP_POSTMASK,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index 3c519a662074..1ff8c4593fc1 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -174,6 +174,38 @@ size_t mtk_ovl_adaptor_get_num_formats(struct device *dev);
 enum drm_mode_status mtk_ovl_adaptor_mode_valid(struct device *dev,
 						const struct drm_display_mode *mode);
 
+int mtk_ovlsys_adaptor_power_on(struct device *dev);
+void mtk_ovlsys_adaptor_power_off(struct device *dev);
+void mtk_ovlsys_adaptor_add_comp(struct device *dev, struct mtk_mutex *mutex);
+void mtk_ovlsys_adaptor_remove_comp(struct device *dev, struct mtk_mutex *mutex);
+void mtk_ovlsys_adaptor_connect(struct device *dev, struct device *mmsys_dev,
+				unsigned int next);
+void mtk_ovlsys_adaptor_disconnect(struct device *dev, struct device *mmsys_dev,
+				   unsigned int next);
+int mtk_ovlsys_adaptor_clk_enable(struct device *dev);
+void mtk_ovlsys_adaptor_clk_disable(struct device *dev);
+void mtk_ovlsys_adaptor_config(struct device *dev, unsigned int w,
+			       unsigned int h, unsigned int vrefresh,
+			       unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
+void mtk_ovlsys_adaptor_layer_config(struct device *dev, unsigned int idx,
+				     struct mtk_plane_state *state,
+				     struct cmdq_pkt *cmdq_pkt);
+int mtk_ovlsys_adaptor_layer_check(struct device *dev,
+				   unsigned int idx,
+				   struct mtk_plane_state *mtk_state);
+void mtk_ovlsys_adaptor_register_vblank_cb(struct device *dev, void (*vblank_cb)(void *),
+					   void *vblank_cb_data);
+void mtk_ovlsys_adaptor_unregister_vblank_cb(struct device *dev);
+void mtk_ovlsys_adaptor_enable_vblank(struct device *dev);
+void mtk_ovlsys_adaptor_disable_vblank(struct device *dev);
+void mtk_ovlsys_adaptor_start(struct device *dev);
+void mtk_ovlsys_adaptor_stop(struct device *dev);
+unsigned int mtk_ovlsys_adaptor_layer_nr(struct device *dev);
+struct device *mtk_ovlsys_adaptor_dma_dev_get(struct device *dev);
+u32 mtk_ovlsys_adaptor_get_blend_modes(struct device *dev);
+const u32 *mtk_ovlsys_adaptor_get_formats(struct device *dev);
+size_t mtk_ovlsys_adaptor_get_num_formats(struct device *dev);
+
 void mtk_rdma_bypass_shadow(struct device *dev);
 int mtk_rdma_clk_enable(struct device *dev);
 void mtk_rdma_clk_disable(struct device *dev);
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c b/drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
new file mode 100644
index 000000000000..465184190bc2
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
@@ -0,0 +1,729 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ */
+
+#include <drm/drm_fourcc.h>
+#include <drm/drm_of.h>
+#include <drm/drm_print.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/soc/mediatek/mtk-cmdq.h>
+#include <linux/soc/mediatek/mtk-mmsys.h>
+#include <linux/soc/mediatek/mtk-mutex.h>
+
+#include "mtk_crtc.h"
+#include "mtk_ddp_comp.h"
+#include "mtk_disp_blender.h"
+#include "mtk_disp_drv.h"
+#include "mtk_disp_outproc.h"
+#include "mtk_drm_drv.h"
+
+#define OVLSYS_ADAPTOR_DRIVER_DATA_MAX_SIZE 8191
+
+enum mtk_ovlsys_adaptor_comp_type {
+	OVLSYS_ADAPTOR_TYPE_EXDMA = 0,
+	OVLSYS_ADAPTOR_TYPE_BLENDER,
+	OVLSYS_ADAPTOR_TYPE_OUTPROC,
+	OVLSYS_ADAPTOR_TYPE_NUM,
+};
+
+enum mtk_ovlsys_adaptor_comp_id {
+	OVLSYS_ADAPTOR_EXDMA0,
+	OVLSYS_ADAPTOR_EXDMA1,
+	OVLSYS_ADAPTOR_EXDMA2,
+	OVLSYS_ADAPTOR_EXDMA3,
+	OVLSYS_ADAPTOR_EXDMA4,
+	OVLSYS_ADAPTOR_EXDMA5,
+	OVLSYS_ADAPTOR_EXDMA6,
+	OVLSYS_ADAPTOR_EXDMA7,
+	OVLSYS_ADAPTOR_EXDMA8,
+	OVLSYS_ADAPTOR_EXDMA9,
+	OVLSYS_ADAPTOR_EXDMA10,
+	OVLSYS_ADAPTOR_EXDMA11,
+	OVLSYS_ADAPTOR_EXDMA12,
+	OVLSYS_ADAPTOR_EXDMA13,
+	OVLSYS_ADAPTOR_EXDMA14,
+	OVLSYS_ADAPTOR_EXDMA15,
+	OVLSYS_ADAPTOR_EXDMA16,
+	OVLSYS_ADAPTOR_EXDMA17,
+	OVLSYS_ADAPTOR_EXDMA18,
+	OVLSYS_ADAPTOR_EXDMA19,
+	OVLSYS_ADAPTOR_BLENDER0,
+	OVLSYS_ADAPTOR_BLENDER1,
+	OVLSYS_ADAPTOR_BLENDER2,
+	OVLSYS_ADAPTOR_BLENDER3,
+	OVLSYS_ADAPTOR_BLENDER4,
+	OVLSYS_ADAPTOR_BLENDER5,
+	OVLSYS_ADAPTOR_BLENDER6,
+	OVLSYS_ADAPTOR_BLENDER7,
+	OVLSYS_ADAPTOR_BLENDER8,
+	OVLSYS_ADAPTOR_BLENDER9,
+	OVLSYS_ADAPTOR_BLENDER10,
+	OVLSYS_ADAPTOR_BLENDER11,
+	OVLSYS_ADAPTOR_BLENDER12,
+	OVLSYS_ADAPTOR_BLENDER13,
+	OVLSYS_ADAPTOR_BLENDER14,
+	OVLSYS_ADAPTOR_BLENDER15,
+	OVLSYS_ADAPTOR_BLENDER16,
+	OVLSYS_ADAPTOR_BLENDER17,
+	OVLSYS_ADAPTOR_BLENDER18,
+	OVLSYS_ADAPTOR_BLENDER19,
+	OVLSYS_ADAPTOR_OUTPROC0,
+	OVLSYS_ADAPTOR_OUTPROC1,
+	OVLSYS_ADAPTOR_OUTPROC2,
+	OVLSYS_ADAPTOR_OUTPROC3,
+	OVLSYS_ADAPTOR_OUTPROC4,
+	OVLSYS_ADAPTOR_OUTPROC5,
+	OVLSYS_ADAPTOR_OUTPROC6,
+	OVLSYS_ADAPTOR_OUTPROC7,
+	OVLSYS_ADAPTOR_OUTPROC8,
+	OVLSYS_ADAPTOR_OUTPROC9,
+	OVLSYS_ADAPTOR_OUTPROC10,
+	OVLSYS_ADAPTOR_OUTPROC11,
+	OVLSYS_ADAPTOR_ID_MAX
+};
+
+struct ovlsys_adaptor_comp_match {
+	enum mtk_ovlsys_adaptor_comp_type type;
+	int alias_id;
+	enum mtk_ddp_comp_id comp_id;
+};
+
+struct mtk_disp_ovlsys_adaptor {
+	struct device *ovl_adaptor_comp[OVLSYS_ADAPTOR_ID_MAX];
+	struct device *mmsys_dev;
+	const unsigned int *path;
+	unsigned int path_size;
+	unsigned int layer_nr;
+	bool children_bound;
+};
+
+static const char * const private_comp_stem[OVLSYS_ADAPTOR_TYPE_NUM] = {
+	[OVLSYS_ADAPTOR_TYPE_EXDMA]	= "exdma",
+	[OVLSYS_ADAPTOR_TYPE_BLENDER]	= "blender",
+	[OVLSYS_ADAPTOR_TYPE_OUTPROC]	= "outproc",
+};
+
+static const struct ovlsys_adaptor_comp_match comp_matches[OVLSYS_ADAPTOR_ID_MAX] = {
+	[OVLSYS_ADAPTOR_EXDMA2]	  = { OVLSYS_ADAPTOR_TYPE_EXDMA, 2, DDP_COMPONENT_OVL0_EXDMA2},
+	[OVLSYS_ADAPTOR_EXDMA3]	  = { OVLSYS_ADAPTOR_TYPE_EXDMA, 3, DDP_COMPONENT_OVL0_EXDMA3},
+	[OVLSYS_ADAPTOR_EXDMA4]	  = { OVLSYS_ADAPTOR_TYPE_EXDMA, 4, DDP_COMPONENT_OVL0_EXDMA4},
+	[OVLSYS_ADAPTOR_EXDMA5]	  = { OVLSYS_ADAPTOR_TYPE_EXDMA, 5, DDP_COMPONENT_OVL0_EXDMA5},
+	[OVLSYS_ADAPTOR_EXDMA6]	  = { OVLSYS_ADAPTOR_TYPE_EXDMA, 6, DDP_COMPONENT_OVL0_EXDMA6},
+	[OVLSYS_ADAPTOR_EXDMA7]	  = { OVLSYS_ADAPTOR_TYPE_EXDMA, 7, DDP_COMPONENT_OVL0_EXDMA7},
+	[OVLSYS_ADAPTOR_EXDMA8]	  = { OVLSYS_ADAPTOR_TYPE_EXDMA, 8, DDP_COMPONENT_OVL0_EXDMA8},
+	[OVLSYS_ADAPTOR_EXDMA9]	  = { OVLSYS_ADAPTOR_TYPE_EXDMA, 9, DDP_COMPONENT_OVL0_EXDMA9},
+	[OVLSYS_ADAPTOR_EXDMA12]   = { OVLSYS_ADAPTOR_TYPE_EXDMA, 12, DDP_COMPONENT_OVL1_EXDMA2},
+	[OVLSYS_ADAPTOR_EXDMA13]   = { OVLSYS_ADAPTOR_TYPE_EXDMA, 13, DDP_COMPONENT_OVL1_EXDMA3},
+	[OVLSYS_ADAPTOR_EXDMA14]   = { OVLSYS_ADAPTOR_TYPE_EXDMA, 14, DDP_COMPONENT_OVL1_EXDMA4},
+	[OVLSYS_ADAPTOR_EXDMA15]   = { OVLSYS_ADAPTOR_TYPE_EXDMA, 15, DDP_COMPONENT_OVL1_EXDMA5},
+	[OVLSYS_ADAPTOR_EXDMA16]   = { OVLSYS_ADAPTOR_TYPE_EXDMA, 16, DDP_COMPONENT_OVL1_EXDMA6},
+	[OVLSYS_ADAPTOR_EXDMA17]   = { OVLSYS_ADAPTOR_TYPE_EXDMA, 17, DDP_COMPONENT_OVL1_EXDMA7},
+	[OVLSYS_ADAPTOR_EXDMA18]   = { OVLSYS_ADAPTOR_TYPE_EXDMA, 18, DDP_COMPONENT_OVL1_EXDMA8},
+	[OVLSYS_ADAPTOR_EXDMA19]   = { OVLSYS_ADAPTOR_TYPE_EXDMA, 19, DDP_COMPONENT_OVL1_EXDMA9},
+	[OVLSYS_ADAPTOR_BLENDER1] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 1, DDP_COMPONENT_OVL0_BLENDER1},
+	[OVLSYS_ADAPTOR_BLENDER2] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 2, DDP_COMPONENT_OVL0_BLENDER2},
+	[OVLSYS_ADAPTOR_BLENDER3] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 3, DDP_COMPONENT_OVL0_BLENDER3},
+	[OVLSYS_ADAPTOR_BLENDER4] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 4, DDP_COMPONENT_OVL0_BLENDER4},
+	[OVLSYS_ADAPTOR_BLENDER5] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 5, DDP_COMPONENT_OVL0_BLENDER5},
+	[OVLSYS_ADAPTOR_BLENDER6] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 6, DDP_COMPONENT_OVL0_BLENDER6},
+	[OVLSYS_ADAPTOR_BLENDER7] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 7, DDP_COMPONENT_OVL0_BLENDER7},
+	[OVLSYS_ADAPTOR_BLENDER8] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 8, DDP_COMPONENT_OVL0_BLENDER8},
+	[OVLSYS_ADAPTOR_BLENDER9] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 9, DDP_COMPONENT_OVL0_BLENDER9},
+	[OVLSYS_ADAPTOR_BLENDER11] = {
+		OVLSYS_ADAPTOR_TYPE_BLENDER, 11, DDP_COMPONENT_OVL1_BLENDER1},
+	[OVLSYS_ADAPTOR_BLENDER12] = {
+		OVLSYS_ADAPTOR_TYPE_BLENDER, 12, DDP_COMPONENT_OVL1_BLENDER2},
+	[OVLSYS_ADAPTOR_BLENDER13] = {
+		OVLSYS_ADAPTOR_TYPE_BLENDER, 13, DDP_COMPONENT_OVL1_BLENDER3},
+	[OVLSYS_ADAPTOR_BLENDER14] = {
+		OVLSYS_ADAPTOR_TYPE_BLENDER, 14, DDP_COMPONENT_OVL1_BLENDER4},
+	[OVLSYS_ADAPTOR_BLENDER15] = {
+		OVLSYS_ADAPTOR_TYPE_BLENDER, 15, DDP_COMPONENT_OVL1_BLENDER5},
+	[OVLSYS_ADAPTOR_BLENDER16] = {
+		OVLSYS_ADAPTOR_TYPE_BLENDER, 16, DDP_COMPONENT_OVL1_BLENDER6},
+	[OVLSYS_ADAPTOR_BLENDER17] = {
+		OVLSYS_ADAPTOR_TYPE_BLENDER, 17, DDP_COMPONENT_OVL1_BLENDER7},
+	[OVLSYS_ADAPTOR_BLENDER18] = {
+		OVLSYS_ADAPTOR_TYPE_BLENDER, 18, DDP_COMPONENT_OVL1_BLENDER8},
+	[OVLSYS_ADAPTOR_BLENDER19] = {
+		OVLSYS_ADAPTOR_TYPE_BLENDER, 19, DDP_COMPONENT_OVL1_BLENDER9},
+	[OVLSYS_ADAPTOR_OUTPROC0] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 0, DDP_COMPONENT_OVL0_OUTPROC0},
+	[OVLSYS_ADAPTOR_OUTPROC1] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 1, DDP_COMPONENT_OVL0_OUTPROC1},
+	[OVLSYS_ADAPTOR_OUTPROC6] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 6, DDP_COMPONENT_OVL1_OUTPROC0},
+};
+
+static const unsigned int mt8196_mtk_ovl_main[] = {
+	OVLSYS_ADAPTOR_EXDMA2,
+	OVLSYS_ADAPTOR_BLENDER1,
+	OVLSYS_ADAPTOR_EXDMA3,
+	OVLSYS_ADAPTOR_BLENDER2,
+	OVLSYS_ADAPTOR_EXDMA4,
+	OVLSYS_ADAPTOR_BLENDER3,
+	OVLSYS_ADAPTOR_EXDMA5,
+	OVLSYS_ADAPTOR_BLENDER4,
+	OVLSYS_ADAPTOR_OUTPROC0,
+};
+
+static const unsigned int mt8196_mtk_ovl_ext[] = {
+	OVLSYS_ADAPTOR_EXDMA6,
+	OVLSYS_ADAPTOR_BLENDER5,
+	OVLSYS_ADAPTOR_EXDMA7,
+	OVLSYS_ADAPTOR_BLENDER6,
+	OVLSYS_ADAPTOR_EXDMA8,
+	OVLSYS_ADAPTOR_BLENDER7,
+	OVLSYS_ADAPTOR_EXDMA9,
+	OVLSYS_ADAPTOR_BLENDER8,
+	OVLSYS_ADAPTOR_OUTPROC1,
+};
+
+static const unsigned int mt8196_mtk_ovl_third[] = {
+	OVLSYS_ADAPTOR_EXDMA12,
+	OVLSYS_ADAPTOR_BLENDER11,
+	OVLSYS_ADAPTOR_EXDMA13,
+	OVLSYS_ADAPTOR_BLENDER12,
+	OVLSYS_ADAPTOR_EXDMA14,
+	OVLSYS_ADAPTOR_BLENDER13,
+	OVLSYS_ADAPTOR_EXDMA15,
+	OVLSYS_ADAPTOR_BLENDER14,
+	OVLSYS_ADAPTOR_OUTPROC6,
+};
+
+static enum mtk_ovlsys_adaptor_comp_type get_type(enum mtk_ovlsys_adaptor_comp_id id)
+{
+	return comp_matches[id].type;
+}
+
+static enum mtk_ddp_comp_id get_ddp_comp_id(enum mtk_ovlsys_adaptor_comp_id id)
+{
+	return comp_matches[id].comp_id;
+}
+
+int mtk_ovlsys_adaptor_power_on(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	struct device *comp;
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < priv->path_size; i++) {
+		comp = priv->ovl_adaptor_comp[priv->path[i]];
+		if (!comp || get_type(priv->path[i]) != OVLSYS_ADAPTOR_TYPE_EXDMA)
+			continue;
+
+		ret = pm_runtime_get_sync(comp);
+		if (ret < 0) {
+			dev_err(dev, "Failed to enable power domain %d, err %d\n", i, ret);
+			goto pwr_err;
+		}
+	}
+
+	return ret;
+
+pwr_err:
+	while (--i >= 0) {
+		comp = priv->ovl_adaptor_comp[i];
+		if (!comp || get_type(priv->path[i]) != OVLSYS_ADAPTOR_TYPE_EXDMA)
+			continue;
+
+		pm_runtime_put(priv->ovl_adaptor_comp[i]);
+	}
+
+	return ret;
+}
+
+void mtk_ovlsys_adaptor_power_off(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	struct device *comp;
+	int i;
+
+	for (i = 0; i < priv->path_size; i++) {
+		comp = priv->ovl_adaptor_comp[priv->path[i]];
+		if (!comp || get_type(priv->path[i]) != OVLSYS_ADAPTOR_TYPE_EXDMA)
+			continue;
+
+		pm_runtime_put(comp);
+	}
+}
+
+void mtk_ovlsys_adaptor_layer_config(struct device *dev, unsigned int idx,
+				     struct mtk_plane_state *state,
+				     struct cmdq_pkt *cmdq_pkt)
+{
+	struct mtk_plane_pending_state *pending = &state->pending;
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	struct device *exdma;
+	struct device *blender;
+	const struct drm_format_info *fmt_info = drm_format_info(pending->format);
+
+	DRM_DEV_DEBUG_DRIVER(dev, "idx:%d enable:%d fmt:0x%x addr:0x%pad fb_w:%d {%d,%d,%d,%d}\n",
+			     idx, pending->enable, pending->format,
+			     &pending->addr, (pending->pitch / fmt_info->cpp[0]),
+			     pending->x, pending->y, pending->width, pending->height);
+
+	exdma = priv->ovl_adaptor_comp[priv->path[idx * 2]];
+	if (!exdma) {
+		dev_err(dev, "%s: exdma%d comp not found\n", __func__, idx);
+		return;
+	}
+
+	blender = priv->ovl_adaptor_comp[priv->path[idx * 2 + 1]];
+	if (!blender) {
+		dev_err(dev, "%s: blender%d comp not found\n", __func__, idx);
+		return;
+	}
+
+	if (pending->height == 0 || pending->width == 0 ||
+	    pending->x > OVLSYS_ADAPTOR_DRIVER_DATA_MAX_SIZE ||
+	    pending->y > OVLSYS_ADAPTOR_DRIVER_DATA_MAX_SIZE)
+		pending->enable = false;
+
+	mtk_disp_exdma_layer_config(exdma, state, cmdq_pkt);
+	mtk_disp_blender_layer_config(blender, state, cmdq_pkt);
+}
+
+void mtk_ovlsys_adaptor_config(struct device *dev, unsigned int w,
+			       unsigned int h, unsigned int vrefresh,
+			       unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	int i;
+	int blender_idx = 0;
+
+	for (i = 0; i < priv->path_size; i++) {
+		if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER) {
+			blender_idx++;
+
+			mtk_disp_blender_config(priv->ovl_adaptor_comp[priv->path[i]], w, h,
+						vrefresh, bpc, blender_idx == priv->layer_nr,
+						blender_idx == 1, cmdq_pkt);
+		} else if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_OUTPROC) {
+			mtk_disp_outproc_config(priv->ovl_adaptor_comp[priv->path[i]], w, h,
+						vrefresh, bpc, cmdq_pkt);
+		}
+	}
+}
+
+int mtk_ovlsys_adaptor_layer_check(struct device *dev,
+				   unsigned int idx,
+				   struct mtk_plane_state *mtk_state)
+{
+	struct drm_plane_state *state = &mtk_state->base;
+
+	/* Check if any unsupported rotation is set */
+	if (state->rotation & ~DRM_MODE_ROTATE_0)
+		return -EINVAL;
+
+	return 0;
+}
+
+void mtk_ovlsys_adaptor_start(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	int i;
+
+	for (i = 0; i < (priv->path_size - 1); i += 2) {
+		mtk_disp_exdma_start(priv->ovl_adaptor_comp[priv->path[i]], NULL);
+		mtk_disp_blender_start(priv->ovl_adaptor_comp[priv->path[i + 1]], NULL);
+	}
+
+	mtk_disp_outproc_start(priv->ovl_adaptor_comp[priv->path[i]]);
+}
+
+void mtk_ovlsys_adaptor_stop(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	int i;
+
+	for (i = 0; i < (priv->path_size - 1); i += 2) {
+		mtk_disp_exdma_start(priv->ovl_adaptor_comp[priv->path[i]], NULL);
+		mtk_disp_blender_start(priv->ovl_adaptor_comp[priv->path[i + 1]], NULL);
+	}
+
+	mtk_disp_outproc_start(priv->ovl_adaptor_comp[priv->path[i]]);
+}
+
+int mtk_ovlsys_adaptor_clk_enable(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	struct device *comp;
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < priv->path_size; i++) {
+		comp = priv->ovl_adaptor_comp[priv->path[i]];
+		if (!comp)
+			continue;
+
+		if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_EXDMA)
+			ret = mtk_disp_exdma_clk_enable(comp);
+		else if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER)
+			ret = mtk_disp_blender_clk_enable(comp);
+		else
+			ret = mtk_disp_outproc_clk_enable(comp);
+
+		if (ret) {
+			dev_err(dev, "Failed to enable clock %d, err %d\n", i, ret);
+			goto clk_err;
+		}
+	}
+
+	return ret;
+
+clk_err:
+	while (--i >= 0) {
+		comp = priv->ovl_adaptor_comp[priv->path[i]];
+		if (!comp)
+			continue;
+
+		if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_EXDMA)
+			mtk_disp_exdma_clk_disable(comp);
+		else if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER)
+			mtk_disp_blender_clk_disable(comp);
+		else
+			mtk_disp_outproc_clk_disable(comp);
+	}
+
+	return ret;
+}
+
+void mtk_ovlsys_adaptor_clk_disable(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	struct device *comp;
+	int i;
+
+	for (i = 0; i < priv->path_size; i++) {
+		comp = priv->ovl_adaptor_comp[priv->path[i]];
+		if (!comp)
+			continue;
+
+		if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_EXDMA)
+			mtk_disp_exdma_clk_disable(comp);
+		else if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER)
+			mtk_disp_blender_clk_disable(comp);
+		else
+			mtk_disp_outproc_clk_disable(comp);
+	}
+}
+
+unsigned int mtk_ovlsys_adaptor_layer_nr(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+	return priv->layer_nr;
+}
+
+struct device *mtk_ovlsys_adaptor_dma_dev_get(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+	return priv->ovl_adaptor_comp[priv->path[0]];
+}
+
+void mtk_ovlsys_adaptor_register_vblank_cb(struct device *dev, void (*vblank_cb)(void *),
+					   void *vblank_cb_data)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+	mtk_disp_outproc_register_vblank_cb(priv->ovl_adaptor_comp[priv->path[priv->path_size - 1]],
+					    vblank_cb, vblank_cb_data);
+}
+
+void mtk_ovlsys_adaptor_unregister_vblank_cb(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	struct device *comp = priv->ovl_adaptor_comp[priv->path[priv->path_size - 1]];
+
+	mtk_disp_outproc_unregister_vblank_cb(comp);
+}
+
+void mtk_ovlsys_adaptor_enable_vblank(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+	mtk_disp_outproc_enable_vblank(priv->ovl_adaptor_comp[priv->path[priv->path_size - 1]]);
+}
+
+void mtk_ovlsys_adaptor_disable_vblank(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+	mtk_disp_outproc_disable_vblank(priv->ovl_adaptor_comp[priv->path[priv->path_size - 1]]);
+}
+
+u32 mtk_ovlsys_adaptor_get_blend_modes(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+	return mtk_disp_blender_get_blend_modes(priv->ovl_adaptor_comp[priv->path[1]]);
+}
+
+const u32 *mtk_ovlsys_adaptor_get_formats(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+	return mtk_disp_exdma_get_formats(priv->ovl_adaptor_comp[priv->path[0]]);
+}
+
+size_t mtk_ovlsys_adaptor_get_num_formats(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+	return mtk_disp_exdma_get_num_formats(priv->ovl_adaptor_comp[priv->path[0]]);
+}
+
+void mtk_ovlsys_adaptor_add_comp(struct device *dev, struct mtk_mutex *mutex)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	int i;
+
+	for (i = 0; i < priv->path_size; i++)
+		mtk_mutex_add_comp(mutex, get_ddp_comp_id(priv->path[i]));
+}
+
+void mtk_ovlsys_adaptor_remove_comp(struct device *dev, struct mtk_mutex *mutex)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	int i;
+
+	for (i = 0; i < priv->path_size; i++)
+		mtk_mutex_remove_comp(mutex, get_ddp_comp_id(priv->path[i]));
+}
+
+void mtk_ovlsys_adaptor_connect(struct device *dev, struct device *mmsys_dev, unsigned int next)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	int i;
+
+	for (i = 0; i < priv->path_size - 1; i++)
+		mtk_mmsys_ddp_connect(mmsys_dev, get_ddp_comp_id(priv->path[i]),
+				      get_ddp_comp_id(priv->path[i + 1]));
+
+	mtk_mmsys_ddp_connect(mmsys_dev, get_ddp_comp_id(priv->path[i]), next);
+}
+
+void mtk_ovlsys_adaptor_disconnect(struct device *dev, struct device *mmsys_dev, unsigned int next)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	int i;
+
+	for (i = 0; i < priv->path_size - 1; i++)
+		mtk_mmsys_ddp_disconnect(mmsys_dev, get_ddp_comp_id(priv->path[i]),
+					 get_ddp_comp_id(priv->path[i + 1]));
+
+	mtk_mmsys_ddp_disconnect(mmsys_dev, get_ddp_comp_id(priv->path[i]), next);
+}
+
+static int ovlsys_adaptor_comp_get_id(struct device *dev, struct device_node *node,
+				      enum mtk_ovlsys_adaptor_comp_type type)
+{
+	int alias_id = of_alias_get_id(node, private_comp_stem[type]);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(comp_matches); i++)
+		if (comp_matches[i].type == type &&
+		    comp_matches[i].alias_id == alias_id)
+			return i;
+
+	dev_warn(dev, "Failed to get id. type: %d, alias: %d\n", type, alias_id);
+	return -EINVAL;
+}
+
+static const struct of_device_id mtk_ovlsys_adaptor_comp_dt_ids[] = {
+	{
+		.compatible = "mediatek,mt8196-exdma",
+		.data = (void *)OVLSYS_ADAPTOR_TYPE_EXDMA,
+	}, {
+		.compatible = "mediatek,mt8196-blender",
+		.data = (void *)OVLSYS_ADAPTOR_TYPE_BLENDER,
+	}, {
+		.compatible = "mediatek,mt8196-outproc",
+		.data = (void *)OVLSYS_ADAPTOR_TYPE_OUTPROC,
+	},
+	{},
+};
+
+static int ovlsys_adaptor_comp_init(struct device *dev, struct component_match **match)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	struct device_node *parent;
+	struct platform_device *comp_pdev;
+	int i;
+
+	parent = dev->parent->parent->of_node->parent;
+
+	for_each_child_of_node_scoped(parent, node) {
+		enum mtk_ovlsys_adaptor_comp_type type;
+		const struct of_device_id *of_id;
+		int id;
+		bool found = false;
+
+		of_id = of_match_node(mtk_ovlsys_adaptor_comp_dt_ids, node);
+		if (!of_id)
+			continue;
+
+		if (!of_device_is_available(node)) {
+			dev_dbg(dev, "Skipping disabled component %pOF\n",
+				node);
+			continue;
+		}
+
+		type = (enum mtk_ovlsys_adaptor_comp_type)(uintptr_t)of_id->data;
+
+		id = ovlsys_adaptor_comp_get_id(dev, node, type);
+		if (id < 0) {
+			dev_warn(dev, "Skipping unknown component %pOF\n",
+				 node);
+			continue;
+		}
+
+		for (i = 0; i < priv->path_size; i++)
+			if (priv->path[i] == id)
+				found = true;
+
+		if (!found)
+			continue;
+
+		comp_pdev = of_find_device_by_node(node);
+		if (!comp_pdev)
+			return -EPROBE_DEFER;
+
+		priv->ovl_adaptor_comp[id] = &comp_pdev->dev;
+
+		drm_of_component_match_add(dev, match, component_compare_of, node);
+		dev_dbg(dev, "Adding component match for %pOF\n", node);
+	}
+
+	if (!*match) {
+		dev_err(dev, "No match device for ovlsys_adaptor\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int mtk_disp_ovlsys_adaptor_comp_bind(struct device *dev, struct device *master,
+					     void *data)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+	if (!priv->children_bound)
+		return -EPROBE_DEFER;
+
+	return 0;
+}
+
+static void mtk_disp_ovlsys_adaptor_comp_unbind(struct device *dev, struct device *master,
+						void *data)
+{
+}
+
+static const struct component_ops mtk_disp_ovlsys_adaptor_comp_ops = {
+	.bind	= mtk_disp_ovlsys_adaptor_comp_bind,
+	.unbind = mtk_disp_ovlsys_adaptor_comp_unbind,
+};
+
+static int mtk_disp_ovlsys_adaptor_master_bind(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+	int ret, i;
+
+	ret = component_bind_all(dev, priv->mmsys_dev);
+
+	if (ret)
+		return dev_err_probe(dev, ret, "component_bind_all failed!\n");
+
+	priv->children_bound = true;
+	priv->layer_nr = 0;
+
+	for (i = 0; i < priv->path_size; i++)
+		if (comp_matches[priv->path[i]].type == OVLSYS_ADAPTOR_TYPE_BLENDER)
+			priv->layer_nr++;
+
+	return 0;
+}
+
+static void mtk_disp_ovlsys_adaptor_master_unbind(struct device *dev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+	priv->children_bound = false;
+}
+
+static const struct component_master_ops mtk_disp_ovlsys_adaptor_master_ops = {
+	.bind		= mtk_disp_ovlsys_adaptor_master_bind,
+	.unbind		= mtk_disp_ovlsys_adaptor_master_unbind,
+};
+
+static int mtk_disp_ovlsys_adaptor_probe(struct platform_device *pdev)
+{
+	struct mtk_disp_ovlsys_adaptor *priv;
+	struct device *dev = &pdev->dev;
+	struct component_match *match = NULL;
+	struct mtk_ovlsys_platform_data *ovlsys_priv;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, priv);
+
+	ovlsys_priv = pdev->dev.platform_data;
+	priv->mmsys_dev = ovlsys_priv->mmsys_dev;
+
+	if (ovlsys_priv->use_path == CRTC_MAIN) {
+		priv->path = mt8196_mtk_ovl_main;
+		priv->path_size = ARRAY_SIZE(mt8196_mtk_ovl_main);
+	} else if (ovlsys_priv->use_path == CRTC_EXT) {
+		priv->path = mt8196_mtk_ovl_ext;
+		priv->path_size = ARRAY_SIZE(mt8196_mtk_ovl_ext);
+	} else if (ovlsys_priv->use_path == CRTC_THIRD) {
+		priv->path = mt8196_mtk_ovl_third;
+		priv->path_size = ARRAY_SIZE(mt8196_mtk_ovl_third);
+	}
+
+	ret = ovlsys_adaptor_comp_init(dev, &match);
+	if (ret < 0)
+		return ret;
+
+	component_master_add_with_match(dev, &mtk_disp_ovlsys_adaptor_master_ops, match);
+
+	pm_runtime_enable(dev);
+
+	ret = component_add(dev, &mtk_disp_ovlsys_adaptor_comp_ops);
+	if (ret != 0) {
+		pm_runtime_disable(dev);
+		dev_err(dev, "Failed to add component: %d\n", ret);
+	}
+
+	return ret;
+}
+
+static void mtk_disp_ovlsys_adaptor_remove(struct platform_device *pdev)
+{
+	component_master_del(&pdev->dev, &mtk_disp_ovlsys_adaptor_master_ops);
+	pm_runtime_disable(&pdev->dev);
+}
+
+struct platform_driver mtk_disp_ovlsys_adaptor_driver = {
+	.probe		= mtk_disp_ovlsys_adaptor_probe,
+	.remove		= mtk_disp_ovlsys_adaptor_remove,
+	.driver		= {
+		.name	= "mediatek-disp-ovlsys-adaptor",
+		.owner	= THIS_MODULE,
+	},
+};
+
+MODULE_AUTHOR("Nancy Lin <nancy.lin@mediatek.com>");
+MODULE_DESCRIPTION("MediaTek Ovlsys Adaptor 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 f7b9c7a982a7..4cf48fe7f0f1 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -429,32 +429,41 @@ static bool mtk_drm_get_all_drm_priv(struct device *dev)
 	return false;
 }
 
-static bool mtk_drm_find_mmsys_comp(struct mtk_drm_private *private, int comp_id)
+static bool mtk_drm_find_mmsys_comp(struct mtk_drm_private *private, int comp_id, int *use_path)
 {
 	const struct mtk_mmsys_driver_data *drv_data = private->data;
-	int i;
+	int i, path = MAX_CRTC;
 
 	if (drv_data->main_path)
 		for (i = 0; i < drv_data->main_len; i++)
-			if (drv_data->main_path[i] == comp_id)
-				return true;
+			if (drv_data->main_path[i] == comp_id) {
+				path = CRTC_MAIN;
+				goto found;
+			}
 
 	if (drv_data->ext_path)
 		for (i = 0; i < drv_data->ext_len; i++)
-			if (drv_data->ext_path[i] == comp_id)
-				return true;
-
+			if (drv_data->ext_path[i] == comp_id) {
+				path = CRTC_EXT;
+				goto found;
+			}
 	if (drv_data->third_path)
 		for (i = 0; i < drv_data->third_len; i++)
-			if (drv_data->third_path[i] == comp_id)
-				return true;
+			if (drv_data->third_path[i] == comp_id) {
+				path = CRTC_THIRD;
+				goto found;
+			}
 
 	if (drv_data->num_conn_routes)
 		for (i = 0; i < drv_data->num_conn_routes; i++)
 			if (drv_data->conn_routes[i].route_ddp == comp_id)
-				return true;
+				goto found;
 
 	return false;
+found:
+	if (use_path)
+		*use_path = path;
+	return true;
 }
 
 static int mtk_drm_kms_init(struct drm_device *drm)
@@ -1055,6 +1064,26 @@ static int mtk_drm_of_ddp_path_build(struct device *dev, struct device_node *nod
 	return 0;
 }
 
+static void mtk_drm_ovl_adaptor_probe(struct device *dev, struct mtk_drm_private *private,
+				      struct component_match **match, enum mtk_ddp_comp_id id)
+{
+	struct platform_device *ovl_adaptor;
+	struct mtk_drm_ovlsys_private ovlsys_priv;
+	bool is_ovlsys = (id != DDP_COMPONENT_DRM_OVL_ADAPTOR);
+	char *dev_name = is_ovlsys ? "mediatek-disp-ovlsys-adaptor" : "mediatek-disp-ovl-adaptor";
+	void *drv_data = is_ovlsys ? (void *)&ovlsys_priv : (void *)private->mmsys_dev;
+	size_t data_size = is_ovlsys ? sizeof(ovlsys_priv) : sizeof(*private->mmsys_dev);
+
+	if (mtk_drm_find_mmsys_comp(private, id, &ovlsys_priv.use_path)) {
+		ovlsys_priv.mmsys_dev = private->mmsys_dev;
+		ovl_adaptor = platform_device_register_data(dev, dev_name, PLATFORM_DEVID_AUTO,
+							    drv_data, data_size);
+		private->ddp_comp[id].dev = &ovl_adaptor->dev;
+		mtk_ddp_comp_init(NULL, &private->ddp_comp[id], id);
+		component_match_add(dev, match, compare_dev, &ovl_adaptor->dev);
+	}
+}
+
 static int mtk_drm_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -1064,7 +1093,6 @@ static int mtk_drm_probe(struct platform_device *pdev)
 	struct mtk_mmsys_driver_data *mtk_drm_data;
 	struct device_node *node;
 	struct component_match *match = NULL;
-	struct platform_device *ovl_adaptor;
 	int ret;
 	int i;
 
@@ -1110,17 +1138,11 @@ static int mtk_drm_probe(struct platform_device *pdev)
 	if (!private->all_drm_private)
 		return -ENOMEM;
 
-	/* Bringup ovl_adaptor */
-	if (mtk_drm_find_mmsys_comp(private, DDP_COMPONENT_DRM_OVL_ADAPTOR)) {
-		ovl_adaptor = platform_device_register_data(dev, "mediatek-disp-ovl-adaptor",
-							    PLATFORM_DEVID_AUTO,
-							    (void *)private->mmsys_dev,
-							    sizeof(*private->mmsys_dev));
-		private->ddp_comp[DDP_COMPONENT_DRM_OVL_ADAPTOR].dev = &ovl_adaptor->dev;
-		mtk_ddp_comp_init(NULL, &private->ddp_comp[DDP_COMPONENT_DRM_OVL_ADAPTOR],
-				  DDP_COMPONENT_DRM_OVL_ADAPTOR);
-		component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev);
-	}
+	/* Bringup ovl_adaptor and ovlsys_adaptor*/
+	mtk_drm_ovl_adaptor_probe(dev, private, &match, DDP_COMPONENT_DRM_OVL_ADAPTOR);
+	mtk_drm_ovl_adaptor_probe(dev, private, &match, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0);
+	mtk_drm_ovl_adaptor_probe(dev, private, &match, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1);
+	mtk_drm_ovl_adaptor_probe(dev, private, &match, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2);
 
 	/* Iterate over sibling DISP function blocks */
 	for_each_child_of_node(phandle->parent, node) {
@@ -1155,7 +1177,7 @@ static int mtk_drm_probe(struct platform_device *pdev)
 			continue;
 		}
 
-		if (!mtk_drm_find_mmsys_comp(private, comp_id))
+		if (!mtk_drm_find_mmsys_comp(private, comp_id, NULL))
 			continue;
 
 		private->comp_node[comp_id] = of_node_get(node);
@@ -1283,6 +1305,7 @@ static struct platform_driver * const mtk_drm_drivers[] = {
 	&mtk_disp_outproc_driver,
 	&mtk_disp_ovl_adaptor_driver,
 	&mtk_disp_ovl_driver,
+	&mtk_disp_ovlsys_adaptor_driver,
 	&mtk_disp_rdma_driver,
 	&mtk_dpi_driver,
 	&mtk_drm_platform_driver,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index c4717c37b0f1..54f320244511 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -11,7 +11,9 @@
 
 #define MAX_CONNECTOR	2
 #define DDP_COMPONENT_DRM_OVL_ADAPTOR (DDP_COMPONENT_ID_MAX + 1)
-#define DDP_COMPONENT_DRM_ID_MAX (DDP_COMPONENT_DRM_OVL_ADAPTOR + 1)
+#define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 (DDP_COMPONENT_DRM_OVL_ADAPTOR + 1)
+#define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 + 1)
+#define DDP_COMPONENT_DRM_ID_MAX (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 + 1)
 
 enum mtk_crtc_path {
 	CRTC_MAIN,
@@ -69,6 +71,11 @@ struct mtk_drm_private {
 	struct mtk_drm_private **all_drm_private;
 };
 
+struct mtk_ovlsys_platform_data {
+	struct device *mmsys_dev;
+	unsigned int use_path;
+};
+
 extern struct platform_driver mtk_disp_aal_driver;
 extern struct platform_driver mtk_disp_blender_driver;
 extern struct platform_driver mtk_disp_ccorr_driver;
@@ -79,6 +86,7 @@ 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_ovlsys_adaptor_driver;
 extern struct platform_driver mtk_disp_rdma_driver;
 extern struct platform_driver mtk_dpi_driver;
 extern struct platform_driver mtk_dsi_driver;
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v3 16/17] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver
  2025-05-15  9:34 [PATCH v3 00/17] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
                   ` (14 preceding siblings ...)
  2025-05-15  9:34 ` [PATCH v3 15/17] drm/mediatek: add ovlsys_adaptor " paul-pl.chen
@ 2025-05-15  9:34 ` paul-pl.chen
  2025-05-16  7:36   ` kernel test robot
  2025-06-24  5:49   ` CK Hu (胡俊光)
  2025-05-15  9:34 ` [PATCH v3 17/17] drm/mediatek: Add support for MT8196 multiple mmsys paul-pl.chen
  16 siblings, 2 replies; 35+ messages in thread
From: paul-pl.chen @ 2025-05-15  9:34 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
  Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
	xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
	treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group

From: Paul-pl Chen <paul-pl.chen@mediatek.com>

To support multiple mmsys instances in the one mediatek-drm instance,
providing improved flexibility and scalability by the following changes:

1. Add DDP_COMPONENT_DRM_OVLSYS_ADAPTOR* to probe the
  ovlsys_adaptor drivers and support different mmsys composition.
2. Added new component types MTK_DISP_VIRTUAL to support the
  routing to virtual display components.
3. Added and adjusted the existed structure or interface to extend
  the support of multiple mmsys instances.
4. Modified the component matching and binding logic to support
  multiple mmsys instances.

Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_crtc.c     | 342 +++++++++++++++++++-----
 drivers/gpu/drm/mediatek/mtk_crtc.h     |   6 +-
 drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 105 +++++---
 drivers/gpu/drm/mediatek/mtk_ddp_comp.h |   2 +
 drivers/gpu/drm/mediatek/mtk_drm_drv.c  |  86 +++---
 drivers/gpu/drm/mediatek/mtk_drm_drv.h  |  16 +-
 6 files changed, 422 insertions(+), 135 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c
index 8f6fba4217ec..4f91ffdd08ae 100644
--- a/drivers/gpu/drm/mediatek/mtk_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_crtc.c
@@ -58,13 +58,17 @@ struct mtk_crtc {
 	wait_queue_head_t		cb_blocking_queue;
 #endif
 
-	struct device			*mmsys_dev;
+	struct device			*mmsys_dev[MAX_MMSYS];
 	struct device			*dma_dev;
-	struct mtk_mutex		*mutex;
+	struct device			*vdisp_ao_dev;
+	struct mtk_mutex		*mutex[MAX_MMSYS];
 	unsigned int			ddp_comp_nr;
 	struct mtk_ddp_comp		**ddp_comp;
+	enum mtk_drm_mmsys		*ddp_comp_sys;
+	bool				exist[MAX_MMSYS];
 	unsigned int			num_conn_routes;
 	const struct mtk_drm_route	*conn_routes;
+	enum mtk_drm_mmsys		conn_routes_sys;
 
 	/* lock for display hardware access */
 	struct mutex			hw_lock;
@@ -82,6 +86,11 @@ struct mtk_crtc_state {
 	unsigned int			pending_vrefresh;
 };
 
+struct mtk_crtc_comp_info {
+	enum mtk_drm_mmsys sys;
+	unsigned int comp_id;
+};
+
 static inline struct mtk_crtc *to_mtk_crtc(struct drm_crtc *c)
 {
 	return container_of(c, struct mtk_crtc, base);
@@ -130,7 +139,10 @@ static void mtk_crtc_destroy(struct drm_crtc *crtc)
 	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
 	int i;
 
-	mtk_mutex_put(mtk_crtc->mutex);
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (mtk_crtc->mutex[i])
+			mtk_mutex_put(mtk_crtc->mutex[i]);
+
 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
 	if (mtk_crtc->cmdq_client.chan) {
 		cmdq_pkt_destroy(&mtk_crtc->cmdq_client, &mtk_crtc->cmdq_handle);
@@ -228,7 +240,14 @@ static int mtk_crtc_ddp_clk_enable(struct mtk_crtc *mtk_crtc)
 	int i;
 
 	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
+		enum mtk_drm_mmsys mmsys;
+
 		ret = mtk_ddp_comp_clk_enable(mtk_crtc->ddp_comp[i]);
+		if (mtk_ddp_comp_get_type(mtk_crtc->ddp_comp[i]->id) == MTK_DISP_VIRTUAL) {
+			mmsys = mtk_crtc->ddp_comp_sys[i];
+			ret = mtk_mmsys_ddp_clk_enable(mtk_crtc->mmsys_dev[mmsys],
+						       mtk_crtc->ddp_comp[i]->id);
+		}
 		if (ret) {
 			DRM_ERROR("Failed to enable clock %d: %d\n", i, ret);
 			goto err;
@@ -237,17 +256,28 @@ static int mtk_crtc_ddp_clk_enable(struct mtk_crtc *mtk_crtc)
 
 	return 0;
 err:
-	while (--i >= 0)
+	while (--i >= 0) {
 		mtk_ddp_comp_clk_disable(mtk_crtc->ddp_comp[i]);
+		if (mtk_ddp_comp_get_type(mtk_crtc->ddp_comp[i]->id) == MTK_DISP_VIRTUAL)
+			mtk_mmsys_ddp_clk_disable(mtk_crtc->mmsys_dev[mtk_crtc->ddp_comp_sys[i]],
+						  mtk_crtc->ddp_comp[i]->id);
+	}
 	return ret;
 }
 
 static void mtk_crtc_ddp_clk_disable(struct mtk_crtc *mtk_crtc)
 {
 	int i;
+	enum mtk_drm_mmsys mmsys;
 
-	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
+	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
 		mtk_ddp_comp_clk_disable(mtk_crtc->ddp_comp[i]);
+		if (mtk_ddp_comp_get_type(mtk_crtc->ddp_comp[i]->id) == MTK_DISP_VIRTUAL) {
+			mmsys = mtk_crtc->ddp_comp_sys[i];
+			mtk_mmsys_ddp_clk_disable(mtk_crtc->mmsys_dev[mmsys],
+						  mtk_crtc->ddp_comp[i]->id);
+		}
+	}
 }
 
 static
@@ -340,7 +370,8 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
 	struct drm_connector_list_iter conn_iter;
 	unsigned int width, height, vrefresh, bpc = MTK_MAX_BPC;
 	int ret;
-	int i;
+	int i, j;
+	enum mtk_drm_mmsys mmsys;
 
 	if (WARN_ON(!crtc->state))
 		return -EINVAL;
@@ -370,10 +401,18 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
 		return ret;
 	}
 
-	ret = mtk_mutex_prepare(mtk_crtc->mutex);
-	if (ret < 0) {
-		DRM_ERROR("Failed to enable mutex clock: %d\n", ret);
-		goto err_pm_runtime_put;
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (mtk_crtc->exist[i])
+			mtk_mmsys_top_clk_enable(mtk_crtc->mmsys_dev[i]);
+
+	for (i = 0; i < MAX_MMSYS; i++) {
+		if (!mtk_crtc->mutex[i] || !mtk_crtc->exist[i])
+			continue;
+		ret = mtk_mutex_prepare(mtk_crtc->mutex[i]);
+		if (ret < 0) {
+			DRM_ERROR("Failed to enable mmsys%d mutex clock: %d\n", i, ret);
+			goto err_pm_runtime_put;
+		}
 	}
 
 	ret = mtk_crtc_ddp_clk_enable(mtk_crtc);
@@ -382,19 +421,36 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
 		goto err_mutex_unprepare;
 	}
 
+	if (mtk_crtc->vdisp_ao_dev)
+		mtk_mmsys_default_config(mtk_crtc->vdisp_ao_dev);
+
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (mtk_crtc->exist[i])
+			mtk_mmsys_default_config(mtk_crtc->mmsys_dev[i]);
+
 	for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
-		if (!mtk_ddp_comp_connect(mtk_crtc->ddp_comp[i], mtk_crtc->mmsys_dev,
+		mmsys = mtk_crtc->ddp_comp_sys[i];
+		if (!mtk_ddp_comp_connect(mtk_crtc->ddp_comp[i], mtk_crtc->mmsys_dev[mmsys],
 					  mtk_crtc->ddp_comp[i + 1]->id))
-			mtk_mmsys_ddp_connect(mtk_crtc->mmsys_dev,
+			mtk_mmsys_ddp_connect(mtk_crtc->mmsys_dev[mmsys],
 					      mtk_crtc->ddp_comp[i]->id,
 					      mtk_crtc->ddp_comp[i + 1]->id);
-		if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
-			mtk_mutex_add_comp(mtk_crtc->mutex,
+		if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex[mmsys]))
+			mtk_mutex_add_comp(mtk_crtc->mutex[mmsys],
 					   mtk_crtc->ddp_comp[i]->id);
 	}
-	if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
-		mtk_mutex_add_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
-	mtk_mutex_enable(mtk_crtc->mutex);
+	mmsys = mtk_crtc->ddp_comp_sys[i];
+	if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex[mmsys]))
+		mtk_mutex_add_comp(mtk_crtc->mutex[mmsys], mtk_crtc->ddp_comp[i]->id);
+
+	/* Need to set sof source for all mmsys mutexes in this crtc */
+	for (j = 0; j < MAX_MMSYS; j++)
+		if (mtk_crtc->exist[j] && mtk_crtc->mutex[j])
+			mtk_mutex_add_comp_sof(mtk_crtc->mutex[j], mtk_crtc->ddp_comp[i]->id);
+
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+			mtk_mutex_enable(mtk_crtc->mutex[i]);
 
 	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
 		struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[i];
@@ -402,7 +458,11 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
 		if (i == 1)
 			mtk_ddp_comp_bgclr_in_on(comp);
 
-		mtk_ddp_comp_config(comp, width, height, vrefresh, bpc, NULL);
+		if (mtk_ddp_comp_get_type(comp->id) == MTK_DISP_VIRTUAL)
+			mtk_mmsys_ddp_config(mtk_crtc->mmsys_dev[mtk_crtc->ddp_comp_sys[i]],
+					     comp->id, width, height, NULL);
+		else
+			mtk_ddp_comp_config(comp, width, height, vrefresh, bpc, NULL);
 		mtk_ddp_comp_start(comp);
 	}
 
@@ -426,7 +486,10 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
 	return 0;
 
 err_mutex_unprepare:
-	mtk_mutex_unprepare(mtk_crtc->mutex);
+	while (--i >= 0)
+		if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+			mtk_mutex_unprepare(mtk_crtc->mutex[i]);
+
 err_pm_runtime_put:
 	pm_runtime_put(crtc->dev->dev);
 	return ret;
@@ -437,7 +500,8 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_crtc *mtk_crtc)
 	struct drm_device *drm = mtk_crtc->base.dev;
 	struct drm_crtc *crtc = &mtk_crtc->base;
 	unsigned long flags;
-	int i;
+	int i, j;
+	enum mtk_drm_mmsys mmsys;
 
 	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
 		mtk_ddp_comp_stop(mtk_crtc->ddp_comp[i]);
@@ -445,27 +509,47 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_crtc *mtk_crtc)
 			mtk_ddp_comp_bgclr_in_off(mtk_crtc->ddp_comp[i]);
 	}
 
-	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
-		if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
-			mtk_mutex_remove_comp(mtk_crtc->mutex,
+	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
+		mmsys = mtk_crtc->ddp_comp_sys[i];
+		if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex[mmsys]))
+			mtk_mutex_remove_comp(mtk_crtc->mutex[mtk_crtc->ddp_comp_sys[i]],
 					      mtk_crtc->ddp_comp[i]->id);
-	mtk_mutex_disable(mtk_crtc->mutex);
+	}
 	for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
-		if (!mtk_ddp_comp_disconnect(mtk_crtc->ddp_comp[i], mtk_crtc->mmsys_dev,
-					     mtk_crtc->ddp_comp[i + 1]->id))
-			mtk_mmsys_ddp_disconnect(mtk_crtc->mmsys_dev,
-						 mtk_crtc->ddp_comp[i]->id,
-						 mtk_crtc->ddp_comp[i + 1]->id);
-		if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
-			mtk_mutex_remove_comp(mtk_crtc->mutex,
+		struct mtk_ddp_comp *comp;
+		unsigned int curr, next;
+
+		comp = mtk_crtc->ddp_comp[i];
+		curr = mtk_crtc->ddp_comp[i]->id;
+		next = mtk_crtc->ddp_comp[i + 1]->id;
+		mmsys = mtk_crtc->ddp_comp_sys[i];
+		if (!mtk_ddp_comp_disconnect(comp, mtk_crtc->mmsys_dev[mmsys], next))
+			mtk_mmsys_ddp_disconnect(mtk_crtc->mmsys_dev[mmsys], curr, next);
+		if (!mtk_ddp_comp_remove(comp, mtk_crtc->mutex[mmsys]))
+			mtk_mutex_remove_comp(mtk_crtc->mutex[mtk_crtc->ddp_comp_sys[i]],
 					      mtk_crtc->ddp_comp[i]->id);
+
 	}
-	if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
-		mtk_mutex_remove_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
+
+	mmsys = mtk_crtc->ddp_comp_sys[i];
+	if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex[mmsys]))
+		mtk_mutex_remove_comp(mtk_crtc->mutex[mmsys], mtk_crtc->ddp_comp[i]->id);
+
+	/* Need to remove sof source for all mmsys mutexes in this crtc */
+	for (j = 0; j < MAX_MMSYS; j++)
+		if (mtk_crtc->exist[j] && mtk_crtc->mutex[j])
+			mtk_mutex_remove_comp_sof(mtk_crtc->mutex[j], mtk_crtc->ddp_comp[i]->id);
+
 	mtk_crtc_ddp_clk_disable(mtk_crtc);
-	mtk_mutex_unprepare(mtk_crtc->mutex);
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+			mtk_mutex_unprepare(mtk_crtc->mutex[i]);
 
-	pm_runtime_put(drm->dev);
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (mtk_crtc->exist[i])
+			mtk_mmsys_top_clk_disable(mtk_crtc->mmsys_dev[i]);
+
+	pm_runtime_put_sync(drm->dev);
 
 	if (crtc->state->event && !crtc->state->active) {
 		spin_lock_irqsave(&crtc->dev->event_lock, flags);
@@ -589,9 +673,15 @@ static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank)
 		mtk_crtc->pending_async_planes = true;
 
 	if (priv->data->shadow_register) {
-		mtk_mutex_acquire(mtk_crtc->mutex);
+		for (i = 0; i < MAX_MMSYS; i++)
+			if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+				mtk_mutex_acquire(mtk_crtc->mutex[i]);
+
 		mtk_crtc_ddp_config(crtc, NULL);
-		mtk_mutex_release(mtk_crtc->mutex);
+
+		for (i = 0; i < MAX_MMSYS; i++)
+			if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+				mtk_mutex_release(mtk_crtc->mutex[i]);
 	}
 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
 	if (mtk_crtc->cmdq_client.chan) {
@@ -675,6 +765,7 @@ static void mtk_crtc_update_output(struct drm_crtc *crtc,
 {
 	int crtc_index = drm_crtc_index(crtc);
 	int i;
+	unsigned int mmsys;
 	struct device *dev;
 	struct drm_crtc_state *crtc_state = state->crtcs[crtc_index].new_state;
 	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
@@ -687,7 +778,8 @@ static void mtk_crtc_update_output(struct drm_crtc *crtc,
 	if (!mtk_crtc->num_conn_routes)
 		return;
 
-	priv = ((struct mtk_drm_private *)crtc->dev->dev_private)->all_drm_private[crtc_index];
+	mmsys = mtk_crtc->conn_routes_sys;
+	priv = ((struct mtk_drm_private *)crtc->dev->dev_private)->all_drm_private[mmsys];
 	dev = priv->dev;
 
 	dev_dbg(dev, "connector change:%d, encoder mask:0x%x for crtc:%d\n",
@@ -700,6 +792,8 @@ static void mtk_crtc_update_output(struct drm_crtc *crtc,
 		if (comp->encoder_index >= 0 &&
 		    (encoder_mask & BIT(comp->encoder_index))) {
 			mtk_crtc->ddp_comp[mtk_crtc->ddp_comp_nr - 1] = comp;
+			mtk_crtc->ddp_comp_sys[mtk_crtc->ddp_comp_nr - 1] = mmsys;
+			mtk_crtc->exist[mmsys] = true;
 			dev_dbg(dev, "Add comp_id: %d at path index %d\n",
 				comp->id, mtk_crtc->ddp_comp_nr - 1);
 			break;
@@ -736,9 +830,31 @@ static void mtk_crtc_atomic_enable(struct drm_crtc *crtc,
 	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
 	struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
 	int ret;
+	int i, j;
+	int mmsys_cnt = 0;
 
 	DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
 
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (mtk_crtc->exist[i])
+			mmsys_cnt++;
+
+	if (mmsys_cnt > 1) {
+		for (i = 0; i < MAX_MMSYS; i++) {
+			if (!mtk_crtc->exist[i])
+				continue;
+			ret = pm_runtime_resume_and_get(mtk_crtc->mmsys_dev[i]);
+			if (ret < 0) {
+				DRM_DEV_ERROR(mtk_crtc->mmsys_dev[i],
+					      "Failed to enable power domain: %d\n", ret);
+				for (j = i - 1; j >= 0; j--)
+					if (mtk_crtc->exist[i])
+						pm_runtime_put(mtk_crtc->mmsys_dev[j]);
+				return;
+			}
+		}
+	}
+
 	ret = mtk_ddp_comp_power_on(comp);
 	if (ret < 0) {
 		DRM_DEV_ERROR(comp->dev, "Failed to enable power domain: %d\n", ret);
@@ -762,7 +878,8 @@ static void mtk_crtc_atomic_disable(struct drm_crtc *crtc,
 {
 	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
 	struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
-	int i;
+	int i, ret;
+	int mmsys_cnt = 0;
 
 	DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
 	if (!mtk_crtc->enabled)
@@ -794,6 +911,22 @@ static void mtk_crtc_atomic_disable(struct drm_crtc *crtc,
 	mtk_crtc_ddp_hw_fini(mtk_crtc);
 	mtk_ddp_comp_power_off(comp);
 
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (mtk_crtc->exist[i])
+			mmsys_cnt++;
+
+	if (mmsys_cnt > 1) {
+		for (i = 0; i < MAX_MMSYS; i++) {
+			if (mtk_crtc->exist[i]) {
+				ret = pm_runtime_put(mtk_crtc->mmsys_dev[i]);
+				if (ret < 0)
+					DRM_DEV_ERROR(mtk_crtc->mmsys_dev[i],
+						      "Failed to disable power domain: %d\n",
+						      ret);
+			}
+		}
+	}
+
 	mtk_crtc->enabled = false;
 }
 
@@ -953,49 +1086,108 @@ struct device *mtk_crtc_dma_dev_get(struct drm_crtc *crtc)
 	return mtk_crtc->dma_dev;
 }
 
-int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
-		    unsigned int path_len, int priv_data_index,
-		    const struct mtk_drm_route *conn_routes,
-		    unsigned int num_conn_routes)
+int mtk_crtc_create(struct drm_device *drm_dev, enum mtk_crtc_path path_sel)
 {
 	struct mtk_drm_private *priv = drm_dev->dev_private;
 	struct device *dev = drm_dev->dev;
 	struct mtk_crtc *mtk_crtc;
 	unsigned int num_comp_planes = 0;
 	int ret;
-	int i;
+	int i, j, k;
 	bool has_ctm = false;
 	uint gamma_lut_size = 0;
 	struct drm_crtc *tmp;
 	int crtc_i = 0;
-
-	if (!path)
-		return 0;
-
-	priv = priv->all_drm_private[priv_data_index];
+	struct mtk_drm_private *subsys_priv;
+	struct mtk_crtc_comp_info path[DDP_COMPONENT_ID_MAX];
+	unsigned int path_len = 0;
+	const struct mtk_drm_route *conn_routes = NULL;
+	unsigned int num_conn_routes = 0;
+	enum mtk_drm_mmsys conn_mmsys;
 
 	drm_for_each_crtc(tmp, drm_dev)
 		crtc_i++;
 
+	for (j = 0; j < priv->data->mmsys_dev_num; j++) {
+		for (k = 0; k < MAX_MMSYS; k++) {
+			const unsigned int *subsys_path;
+			unsigned int subsys_path_len = 0;
+			unsigned int order = 0;
+
+			subsys_priv = priv->all_drm_private[k];
+			if (!subsys_priv)
+				continue;
+
+			if (path_sel == CRTC_MAIN) {
+				subsys_path = subsys_priv->data->main_path;
+				subsys_path_len = subsys_priv->data->main_len;
+				order = subsys_priv->data->main_order;
+			} else if (path_sel == CRTC_EXT) {
+				subsys_path = subsys_priv->data->ext_path;
+				subsys_path_len = subsys_priv->data->ext_len;
+				order = subsys_priv->data->ext_order;
+			} else if (path_sel == CRTC_THIRD) {
+				subsys_path = subsys_priv->data->third_path;
+				subsys_path_len = subsys_priv->data->third_len;
+				order = subsys_priv->data->third_order;
+			}
+
+			if (subsys_priv->data->num_conn_routes) {
+				conn_routes = subsys_priv->data->conn_routes;
+				num_conn_routes = subsys_priv->data->num_conn_routes;
+				conn_mmsys = subsys_priv->data->mmsys_id;
+			}
+
+			if (j != order)
+				continue;
+			if (!subsys_path_len)
+				continue;
+
+			for (i = 0; i < subsys_path_len; i++) {
+				path[path_len].sys = subsys_priv->data->mmsys_id;
+				path[path_len].comp_id = subsys_path[i];
+				path_len++;
+			}
+		}
+	}
+
+	if (!path_len)
+		return 0;
+
+	if (num_conn_routes) {
+		for (i = 0; i < num_conn_routes; i++)
+			if (conn_routes->crtc_id == crtc_i)
+				break;
+		if (i == num_conn_routes) {
+			num_conn_routes = 0;
+			conn_routes = NULL;
+		}
+	}
+
 	for (i = 0; i < path_len; i++) {
-		enum mtk_ddp_comp_id comp_id = path[i];
+		enum mtk_ddp_comp_id comp_id = path[i].comp_id;
 		struct device_node *node;
 		struct mtk_ddp_comp *comp;
 
+		priv = priv->all_drm_private[path[i].sys];
 		node = priv->comp_node[comp_id];
 		comp = &priv->ddp_comp[comp_id];
 
 		/* Not all drm components have a DTS device node, such as ovl_adaptor,
 		 * which is the drm bring up sub driver
 		 */
-		if (!node && comp_id != DDP_COMPONENT_DRM_OVL_ADAPTOR) {
+		if (!node && comp_id != DDP_COMPONENT_DRM_OVL_ADAPTOR &&
+		    comp_id != DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 &&
+		    comp_id != DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 &&
+		    comp_id != DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2 &&
+		    mtk_ddp_comp_get_type(comp_id) != MTK_DISP_VIRTUAL) {
 			dev_info(dev,
 				"Not creating crtc %d because component %d is disabled or missing\n",
 				crtc_i, comp_id);
 			return 0;
 		}
 
-		if (!comp->dev) {
+		if (!comp->dev && mtk_ddp_comp_get_type(comp_id) != MTK_DISP_VIRTUAL) {
 			dev_err(dev, "Component %pOF not initialized\n", node);
 			return -ENODEV;
 		}
@@ -1005,7 +1197,9 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
 	if (!mtk_crtc)
 		return -ENOMEM;
 
-	mtk_crtc->mmsys_dev = priv->mmsys_dev;
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (priv->all_drm_private[i])
+			mtk_crtc->mmsys_dev[i] = priv->all_drm_private[i]->mmsys_dev;
 	mtk_crtc->ddp_comp_nr = path_len;
 	mtk_crtc->ddp_comp = devm_kcalloc(dev,
 					  mtk_crtc->ddp_comp_nr + (conn_routes ? 1 : 0),
@@ -1014,19 +1208,36 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
 	if (!mtk_crtc->ddp_comp)
 		return -ENOMEM;
 
-	mtk_crtc->mutex = mtk_mutex_get(priv->mutex_dev);
-	if (IS_ERR(mtk_crtc->mutex)) {
-		ret = PTR_ERR(mtk_crtc->mutex);
-		dev_err(dev, "Failed to get mutex: %d\n", ret);
-		return ret;
+	mtk_crtc->ddp_comp_sys = devm_kmalloc_array(dev, mtk_crtc->ddp_comp_nr +
+						    (conn_routes ? 1 : 0),
+						    sizeof(*mtk_crtc->ddp_comp_sys), GFP_KERNEL);
+	if (!mtk_crtc->ddp_comp_sys)
+		return -ENOMEM;
+
+	for (i = 0; i < MAX_MMSYS; i++) {
+		if (!priv->all_drm_private[i])
+			continue;
+
+		priv = priv->all_drm_private[i];
+		mtk_crtc->mutex[i] = mtk_mutex_get(priv->mutex_dev);
+		if (IS_ERR(mtk_crtc->mutex[i])) {
+			ret = PTR_ERR(mtk_crtc->mutex[i]);
+			dev_err(dev, "Failed to get mutex: %d\n", ret);
+			return ret;
+		}
 	}
 
 	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
-		unsigned int comp_id = path[i];
+		unsigned int comp_id = path[i].comp_id;
 		struct mtk_ddp_comp *comp;
 
+		priv = priv->all_drm_private[path[i].sys];
 		comp = &priv->ddp_comp[comp_id];
+		if (mtk_ddp_comp_get_type(comp_id) == MTK_DISP_VIRTUAL)
+			comp->id = comp_id;
 		mtk_crtc->ddp_comp[i] = comp;
+		mtk_crtc->ddp_comp_sys[i] = path[i].sys;
+		mtk_crtc->exist[path[i].sys] = true;
 
 		if (comp->funcs) {
 			if (comp->funcs->gamma_set && comp->funcs->gamma_get_lut_size) {
@@ -1063,8 +1274,10 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
 	 * In the case of ovl_adaptor sub driver, it needs to use the
 	 * dma_dev_get function to get representative dma dev.
 	 */
-	mtk_crtc->dma_dev = mtk_ddp_comp_dma_dev_get(&priv->ddp_comp[path[0]]);
+	priv = priv->all_drm_private[path[0].sys];
+	mtk_crtc->dma_dev = mtk_ddp_comp_dma_dev_get(&priv->ddp_comp[path[0].comp_id]);
 
+	mtk_crtc->vdisp_ao_dev = priv->vdisp_ao_dev;
 	ret = mtk_crtc_init(drm_dev, mtk_crtc, crtc_i);
 	if (ret < 0)
 		return ret;
@@ -1077,7 +1290,7 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
 
 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
 	i = priv->mbox_index++;
-	mtk_crtc->cmdq_client.client.dev = mtk_crtc->mmsys_dev;
+	mtk_crtc->cmdq_client.client.dev = mtk_crtc->mmsys_dev[priv->data->mmsys_id];
 	mtk_crtc->cmdq_client.client.tx_block = false;
 	mtk_crtc->cmdq_client.client.knows_txdone = true;
 	mtk_crtc->cmdq_client.client.rx_callback = ddp_cmdq_cb;
@@ -1117,6 +1330,7 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
 #endif
 
 	if (conn_routes) {
+		priv = priv->all_drm_private[conn_mmsys];
 		for (i = 0; i < num_conn_routes; i++) {
 			unsigned int comp_id = conn_routes[i].route_ddp;
 			struct device_node *node = priv->comp_node[comp_id];
@@ -1133,6 +1347,7 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
 			mtk_ddp_comp_encoder_index_set(&priv->ddp_comp[comp_id]);
 		}
 
+		mtk_crtc->conn_routes_sys = conn_mmsys;
 		mtk_crtc->num_conn_routes = num_conn_routes;
 		mtk_crtc->conn_routes = conn_routes;
 
@@ -1140,5 +1355,10 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
 		mtk_crtc->ddp_comp_nr++;
 	}
 
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (mtk_crtc->exist[i])
+			device_link_add(mtk_crtc->base.dev->dev,
+					priv->all_drm_private[i]->mutex_dev, 0);
+
 	return 0;
 }
diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.h b/drivers/gpu/drm/mediatek/mtk_crtc.h
index 388e900b6f4d..255f2823d17a 100644
--- a/drivers/gpu/drm/mediatek/mtk_crtc.h
+++ b/drivers/gpu/drm/mediatek/mtk_crtc.h
@@ -15,10 +15,8 @@
 #define MTK_MIN_BPC	3
 
 void mtk_crtc_commit(struct drm_crtc *crtc);
-int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
-		    unsigned int path_len, int priv_data_index,
-		    const struct mtk_drm_route *conn_routes,
-		    unsigned int num_conn_routes);
+int mtk_crtc_create(struct drm_device *drm_dev,
+		    enum mtk_crtc_path path_sel);
 int mtk_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane,
 			 struct mtk_plane_state *state);
 void mtk_crtc_async_update(struct drm_crtc *crtc, struct drm_plane *plane,
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index c96e027359ac..505edee09cb9 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -467,6 +467,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
 	[MTK_DISP_PWM] = "pwm",
 	[MTK_DISP_RDMA] = "rdma",
 	[MTK_DISP_UFOE] = "ufoe",
+	[MTK_DISP_VIRTUAL] = "virtual",
 	[MTK_DISP_WDMA] = "wdma",
 	[MTK_DP_INTF] = "dp-intf",
 	[MTK_DPI] = "dpi",
@@ -490,6 +491,15 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
 	[DDP_COMPONENT_COLOR0]		= { MTK_DISP_COLOR,		0, &ddp_color },
 	[DDP_COMPONENT_COLOR1]		= { MTK_DISP_COLOR,		1, &ddp_color },
 	[DDP_COMPONENT_DITHER0]		= { MTK_DISP_DITHER,		0, &ddp_dither },
+	[DDP_COMPONENT_DLI_ASYNC0]      = { MTK_DISP_VIRTUAL,           -1, NULL },
+	[DDP_COMPONENT_DLI_ASYNC1]      = { MTK_DISP_VIRTUAL,           -1, NULL },
+	[DDP_COMPONENT_DLI_ASYNC8]      = { MTK_DISP_VIRTUAL,           -1, NULL },
+	[DDP_COMPONENT_DLI_ASYNC21]     = { MTK_DISP_VIRTUAL,           -1, NULL },
+	[DDP_COMPONENT_DLI_ASYNC22]     = { MTK_DISP_VIRTUAL,           -1, NULL },
+	[DDP_COMPONENT_DLI_ASYNC23]     = { MTK_DISP_VIRTUAL,           -1, NULL },
+	[DDP_COMPONENT_DLO_ASYNC1]      = { MTK_DISP_VIRTUAL,           -1, NULL },
+	[DDP_COMPONENT_DLO_ASYNC2]      = { MTK_DISP_VIRTUAL,           -1, NULL },
+	[DDP_COMPONENT_DLO_ASYNC3]      = { MTK_DISP_VIRTUAL,           -1, NULL },
 	[DDP_COMPONENT_DP_INTF0]	= { MTK_DP_INTF,		0, &ddp_dpi },
 	[DDP_COMPONENT_DP_INTF1]	= { MTK_DP_INTF,		1, &ddp_dpi },
 	[DDP_COMPONENT_DPI0]		= { MTK_DPI,			0, &ddp_dpi },
@@ -497,6 +507,7 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
 	[DDP_COMPONENT_DRM_OVL_ADAPTOR]	= { MTK_DISP_OVL_ADAPTOR,	0, &ddp_ovl_adaptor },
 	[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0] = { MTK_DISP_OVLSYS_ADAPTOR, 0, &ddp_ovlsys_adaptor},
 	[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1] = { MTK_DISP_OVLSYS_ADAPTOR, 1, &ddp_ovlsys_adaptor},
+	[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2] = { MTK_DISP_OVLSYS_ADAPTOR, 2, &ddp_ovlsys_adaptor},
 	[DDP_COMPONENT_DSC0]		= { MTK_DISP_DSC,		0, &ddp_dsc },
 	[DDP_COMPONENT_DSC1]		= { MTK_DISP_DSC,		1, &ddp_dsc },
 	[DDP_COMPONENT_DSI0]		= { MTK_DSI,			0, &ddp_dsi },
@@ -513,7 +524,10 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
 	[DDP_COMPONENT_OD0]		= { MTK_DISP_OD,		0, &ddp_od },
 	[DDP_COMPONENT_OD1]		= { MTK_DISP_OD,		1, &ddp_od },
 	[DDP_COMPONENT_OVL0]		= { MTK_DISP_OVL,		0, &ddp_ovl },
+	[DDP_COMPONENT_OVL0_DLO_ASYNC5] = { MTK_DISP_VIRTUAL,           -1, NULL },
+	[DDP_COMPONENT_OVL0_DLO_ASYNC6] = { MTK_DISP_VIRTUAL,           -1, NULL },
 	[DDP_COMPONENT_OVL1]		= { MTK_DISP_OVL,		1, &ddp_ovl },
+	[DDP_COMPONENT_OVL1_DLO_ASYNC5] = { MTK_DISP_VIRTUAL,           -1, NULL },
 	[DDP_COMPONENT_OVL_2L0]		= { MTK_DISP_OVL_2L,		0, &ddp_ovl },
 	[DDP_COMPONENT_OVL_2L1]		= { MTK_DISP_OVL_2L,		1, &ddp_ovl },
 	[DDP_COMPONENT_OVL_2L2]		= { MTK_DISP_OVL_2L,		2, &ddp_ovl },
@@ -564,18 +578,24 @@ static int mtk_ddp_comp_find_in_route(struct device *dev,
 	return -ENODEV;
 }
 
+enum mtk_ddp_comp_type mtk_ddp_comp_get_type(unsigned int comp_id)
+{
+	return mtk_ddp_matches[comp_id].type;
+}
+
 static bool mtk_ddp_path_available(const unsigned int *path,
 				   unsigned int path_len,
 				   struct device_node **comp_node)
 {
 	unsigned int i;
 
-	if (!path || !path_len)
-		return false;
-
 	for (i = 0U; i < path_len; i++) {
 		/* OVL_ADAPTOR doesn't have a device node */
-		if (path[i] == DDP_COMPONENT_DRM_OVL_ADAPTOR)
+		if (path[i] == DDP_COMPONENT_DRM_OVL_ADAPTOR ||
+		    path[i] == DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 ||
+		    path[i] == DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 ||
+		    path[i] == DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2 ||
+		    mtk_ddp_comp_get_type(path[i]) == MTK_DISP_VIRTUAL)
 			continue;
 
 		if (!comp_node[path[i]])
@@ -605,39 +625,52 @@ int mtk_find_possible_crtcs(struct drm_device *drm, struct device *dev)
 	struct mtk_drm_private *private = drm->dev_private;
 	const struct mtk_mmsys_driver_data *data;
 	struct mtk_drm_private *priv_n;
-	int i = 0, j;
-	int ret;
+	int i, j, count = 0, ret;
+
+	/* search each path in private data */
+	for (i = 0; i < MAX_CRTC; i++) {
+		bool found = false;
+		int avail_mmsys_num = 0;
+
+		for (j = 0; j < private->data->mmsys_dev_num; j++) {
+			const unsigned int *path = NULL;
+			unsigned int path_len = 0;
+
+			priv_n = private->all_drm_private[j];
+			data = priv_n->data;
+
+			if (i == CRTC_MAIN) {
+				path = data->main_path;
+				path_len = data->main_len;
+			} else if (i == CRTC_EXT) {
+				path = data->ext_path;
+				path_len = data->ext_len;
+			} else if (i == CRTC_THIRD) {
+				path = data->third_path;
+				path_len = data->third_len;
+			}
+
+			/* skip if no path data in current mmsys */
+			if (path_len == 0 || !path) {
+				avail_mmsys_num++;
+				continue;
+			}
+
+			if (mtk_ddp_path_available(path, path_len, priv_n->comp_node))
+				avail_mmsys_num++;
+
+			if (mtk_ddp_comp_find(dev, path, path_len, priv_n->ddp_comp))
+				found = true;
+	}
+
+		/* skip invalid path */
+		if (avail_mmsys_num != private->data->mmsys_dev_num)
+			continue;
+
+		if (found)
+			return BIT(count);
 
-	for (j = 0; j < private->data->mmsys_dev_num; j++) {
-		priv_n = private->all_drm_private[j];
-		data = priv_n->data;
-
-		if (mtk_ddp_path_available(data->main_path, data->main_len,
-					   priv_n->comp_node)) {
-			if (mtk_ddp_comp_find(dev, data->main_path,
-					      data->main_len,
-					      priv_n->ddp_comp))
-				return BIT(i);
-			i++;
-		}
-
-		if (mtk_ddp_path_available(data->ext_path, data->ext_len,
-					   priv_n->comp_node)) {
-			if (mtk_ddp_comp_find(dev, data->ext_path,
-					      data->ext_len,
-					      priv_n->ddp_comp))
-				return BIT(i);
-			i++;
-		}
-
-		if (mtk_ddp_path_available(data->third_path, data->third_len,
-					   priv_n->comp_node)) {
-			if (mtk_ddp_comp_find(dev, data->third_path,
-					      data->third_len,
-					      priv_n->ddp_comp))
-				return BIT(i);
-			i++;
-		}
+			count++;
 	}
 
 	ret = mtk_ddp_comp_find_in_route(dev,
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
index ef64ce7a071f..badb42bd4f7c 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
@@ -40,6 +40,7 @@ enum mtk_ddp_comp_type {
 	MTK_DISP_PWM,
 	MTK_DISP_RDMA,
 	MTK_DISP_UFOE,
+	MTK_DISP_VIRTUAL,
 	MTK_DISP_WDMA,
 	MTK_DPI,
 	MTK_DP_INTF,
@@ -47,6 +48,7 @@ enum mtk_ddp_comp_type {
 	MTK_OVL_BLENDER,
 	MTK_OVL_EXDMA,
 	MTK_OVL_OUTPROC,
+	MTK_VDISP_AO,
 	MTK_DDP_COMP_TYPE_MAX,
 };
 
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 4cf48fe7f0f1..1e49ca3fef80 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -374,7 +374,7 @@ static int mtk_drm_match(struct device *dev, const void *data)
 static bool mtk_drm_get_all_drm_priv(struct device *dev)
 {
 	struct mtk_drm_private *drm_priv = dev_get_drvdata(dev);
-	struct mtk_drm_private *all_drm_priv[MAX_CRTC];
+	struct mtk_drm_private *all_drm_priv[MAX_MMSYS] = {NULL};
 	struct mtk_drm_private *temp_drm_priv;
 	struct device_node *phandle = dev->parent->of_node;
 	const struct of_device_id *of_id;
@@ -402,26 +402,22 @@ static bool mtk_drm_get_all_drm_priv(struct device *dev)
 		if (!temp_drm_priv)
 			continue;
 
-		if (temp_drm_priv->data->main_len)
-			all_drm_priv[CRTC_MAIN] = temp_drm_priv;
-		else if (temp_drm_priv->data->ext_len)
-			all_drm_priv[CRTC_EXT] = temp_drm_priv;
-		else if (temp_drm_priv->data->third_len)
-			all_drm_priv[CRTC_THIRD] = temp_drm_priv;
+		all_drm_priv[temp_drm_priv->data->mmsys_id] = temp_drm_priv;
 
 		if (temp_drm_priv->mtk_drm_bound)
 			cnt++;
 
-		if (cnt == MAX_CRTC) {
+		if (cnt == temp_drm_priv->data->mmsys_dev_num) {
 			of_node_put(node);
 			break;
 		}
 	}
 
 	if (drm_priv->data->mmsys_dev_num == cnt) {
-		for (i = 0; i < cnt; i++)
-			for (j = 0; j < cnt; j++)
-				all_drm_priv[j]->all_drm_private[i] = all_drm_priv[i];
+		for (i = 0; i < MAX_MMSYS; i++)
+			for (j = 0; j < MAX_MMSYS; j++)
+				if (all_drm_priv[j])
+					all_drm_priv[j]->all_drm_private[i] = all_drm_priv[i];
 
 		return true;
 	}
@@ -494,7 +490,10 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 	drm->mode_config.funcs = &mtk_drm_mode_config_funcs;
 	drm->mode_config.helper_private = &mtk_drm_mode_config_helpers;
 
-	for (i = 0; i < private->data->mmsys_dev_num; i++) {
+	for (i = 0; i < MAX_MMSYS; i++) {
+		if (!private->all_drm_private[i])
+			continue;
+
 		drm->dev_private = private->all_drm_private[i];
 		ret = component_bind_all(private->all_drm_private[i]->dev, drm);
 		if (ret)
@@ -517,8 +516,10 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 	 *    third path.
 	 */
 	for (i = 0; i < MAX_CRTC; i++) {
-		for (j = 0; j < private->data->mmsys_dev_num; j++) {
+		for (j = 0; j < MAX_MMSYS; j++) {
 			priv_n = private->all_drm_private[j];
+			if (!priv_n)
+				continue;
 
 			if (priv_n->data->max_width)
 				drm->mode_config.max_width = priv_n->data->max_width;
@@ -530,28 +531,23 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 				drm->mode_config.min_height = priv_n->data->min_height;
 
 			if (i == CRTC_MAIN && priv_n->data->main_len) {
-				ret = mtk_crtc_create(drm, priv_n->data->main_path,
-						      priv_n->data->main_len, j,
-						      priv_n->data->conn_routes,
-						      priv_n->data->num_conn_routes);
+				ret = mtk_crtc_create(drm, CRTC_MAIN);
 				if (ret)
 					goto err_component_unbind;
 
-				continue;
+				break;
 			} else if (i == CRTC_EXT && priv_n->data->ext_len) {
-				ret = mtk_crtc_create(drm, priv_n->data->ext_path,
-						      priv_n->data->ext_len, j, NULL, 0);
+				ret = mtk_crtc_create(drm, CRTC_EXT);
 				if (ret)
 					goto err_component_unbind;
 
-				continue;
+				break;
 			} else if (i == CRTC_THIRD && priv_n->data->third_len) {
-				ret = mtk_crtc_create(drm, priv_n->data->third_path,
-						      priv_n->data->third_len, j, NULL, 0);
+				ret = mtk_crtc_create(drm, CRTC_THIRD);
 				if (ret)
 					goto err_component_unbind;
 
-				continue;
+				break;
 			}
 		}
 	}
@@ -570,8 +566,9 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 		goto err_component_unbind;
 	}
 
-	for (i = 0; i < private->data->mmsys_dev_num; i++)
-		private->all_drm_private[i]->dma_dev = dma_dev;
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (private->all_drm_private[i])
+			private->all_drm_private[i]->dma_dev = dma_dev;
 
 	/*
 	 * Configure the DMA segment size to make sure we get contiguous IOVA
@@ -589,11 +586,13 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 	return 0;
 
 err_component_unbind:
-	for (i = 0; i < private->data->mmsys_dev_num; i++)
-		component_unbind_all(private->all_drm_private[i]->dev, drm);
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (private->all_drm_private[i])
+			component_unbind_all(private->all_drm_private[i]->dev, drm);
 put_mutex_dev:
-	for (i = 0; i < private->data->mmsys_dev_num; i++)
-		put_device(private->all_drm_private[i]->mutex_dev);
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (private->all_drm_private[i])
+			put_device(private->all_drm_private[i]->mutex_dev);
 
 	return ret;
 }
@@ -657,6 +656,19 @@ static int mtk_drm_bind(struct device *dev)
 	}
 
 	private->mutex_dev = &pdev->dev;
+
+	if (private->vdisp_ao_node) {
+		pdev = of_find_device_by_node(private->vdisp_ao_node);
+		if (!pdev) {
+			dev_err(dev, "Waiting for vdisp_ao device %pOF\n",
+				private->vdisp_ao_node);
+			of_node_put(private->mutex_node);
+			of_node_put(private->vdisp_ao_node);
+			return -EPROBE_DEFER;
+		}
+		private->vdisp_ao_dev = &pdev->dev;
+	}
+
 	private->mtk_drm_bound = true;
 	private->dev = dev;
 
@@ -669,8 +681,9 @@ static int mtk_drm_bind(struct device *dev)
 
 	private->drm_master = true;
 	drm->dev_private = private;
-	for (i = 0; i < private->data->mmsys_dev_num; i++)
-		private->all_drm_private[i]->drm = drm;
+	for (i = 0; i < MAX_MMSYS; i++)
+		if (private->all_drm_private[i])
+			private->all_drm_private[i]->drm = drm;
 
 	ret = mtk_drm_kms_init(drm);
 	if (ret < 0)
@@ -1132,7 +1145,7 @@ static int mtk_drm_probe(struct platform_device *pdev)
 		private->data = mtk_drm_data;
 	}
 
-	private->all_drm_private = devm_kmalloc_array(dev, private->data->mmsys_dev_num,
+	private->all_drm_private = devm_kmalloc_array(dev, MAX_MMSYS,
 						      sizeof(*private->all_drm_private),
 						      GFP_KERNEL);
 	if (!private->all_drm_private)
@@ -1170,6 +1183,12 @@ static int mtk_drm_probe(struct platform_device *pdev)
 			continue;
 		}
 
+		if (comp_type == MTK_VDISP_AO) {
+			private->vdisp_ao_node = of_node_get(node);
+			dev_dbg(dev, "get vdisp_ao node");
+			continue;
+		}
+
 		comp_id = mtk_ddp_comp_get_id(node, comp_type);
 		if (comp_id < 0) {
 			dev_warn(dev, "Skipping unknown component %pOF\n",
@@ -1245,6 +1264,7 @@ static void mtk_drm_remove(struct platform_device *pdev)
 	component_master_del(&pdev->dev, &mtk_drm_ops);
 	pm_runtime_disable(&pdev->dev);
 	of_node_put(private->mutex_node);
+	of_node_put(private->vdisp_ao_node);
 	for (i = 0; i < DDP_COMPONENT_DRM_ID_MAX; i++)
 		of_node_put(private->comp_node[i]);
 }
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index 54f320244511..bdd4dc5cefeb 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -13,7 +13,8 @@
 #define DDP_COMPONENT_DRM_OVL_ADAPTOR (DDP_COMPONENT_ID_MAX + 1)
 #define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 (DDP_COMPONENT_DRM_OVL_ADAPTOR + 1)
 #define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 + 1)
-#define DDP_COMPONENT_DRM_ID_MAX (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 + 1)
+#define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2 (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 + 1)
+#define DDP_COMPONENT_DRM_ID_MAX (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2 + 1)
 
 enum mtk_crtc_path {
 	CRTC_MAIN,
@@ -22,6 +23,14 @@ enum mtk_crtc_path {
 	MAX_CRTC,
 };
 
+enum mtk_drm_mmsys {
+	DISPSYS0,
+	DISPSYS1,
+	OVLSYS0,
+	OVLSYS1,
+	MAX_MMSYS,
+};
+
 struct device;
 struct device_node;
 struct drm_crtc;
@@ -38,10 +47,13 @@ struct mtk_drm_route {
 struct mtk_mmsys_driver_data {
 	const unsigned int *main_path;
 	unsigned int main_len;
+	unsigned int main_order;
 	const unsigned int *ext_path;
 	unsigned int ext_len;
+	unsigned int ext_order;
 	const unsigned int *third_path;
 	unsigned int third_len;
+	unsigned int third_order;
 	const struct mtk_drm_route *conn_routes;
 	unsigned int num_conn_routes;
 
@@ -63,6 +75,8 @@ struct mtk_drm_private {
 	struct device_node *mutex_node;
 	struct device *mutex_dev;
 	struct device *mmsys_dev;
+	struct device_node *vdisp_ao_node;
+	struct device *vdisp_ao_dev;
 	struct device_node *comp_node[DDP_COMPONENT_DRM_ID_MAX];
 	struct mtk_ddp_comp ddp_comp[DDP_COMPONENT_DRM_ID_MAX];
 	struct mtk_mmsys_driver_data *data;
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v3 17/17] drm/mediatek: Add support for MT8196 multiple mmsys
  2025-05-15  9:34 [PATCH v3 00/17] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
                   ` (15 preceding siblings ...)
  2025-05-15  9:34 ` [PATCH v3 16/17] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver paul-pl.chen
@ 2025-05-15  9:34 ` paul-pl.chen
  16 siblings, 0 replies; 35+ messages in thread
From: paul-pl.chen @ 2025-05-15  9:34 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
  Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
	xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
	treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group

From: Nancy Lin <nancy.lin@mediatek.com>

Add code to support MT8196 SOC Multi MMSYS Driver

Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_drm_drv.c | 119 ++++++++++++++++++++++++-
 1 file changed, 115 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 1e49ca3fef80..229f84a4e59c 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -193,6 +193,10 @@ static const struct mtk_drm_route mt8188_mtk_ddp_main_routes[] = {
 	{0, DDP_COMPONENT_DSI0},
 };
 
+static const struct mtk_drm_route mt8196_mtk_ddp_routes[] = {
+	{2, DDP_COMPONENT_DSI0},
+};
+
 static const unsigned int mt8192_mtk_ddp_main[] = {
 	DDP_COMPONENT_OVL0,
 	DDP_COMPONENT_OVL_2L0,
@@ -231,6 +235,50 @@ static const unsigned int mt8195_mtk_ddp_ext[] = {
 	DDP_COMPONENT_DP_INTF1,
 };
 
+static const unsigned int mt8196_mtk_ddp_ovl0_main[] = {
+	DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0,
+	DDP_COMPONENT_OVL0_DLO_ASYNC5,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp0_main[] = {
+	DDP_COMPONENT_DLI_ASYNC0,
+	DDP_COMPONENT_DLO_ASYNC1,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp1_main[] = {
+	DDP_COMPONENT_DLI_ASYNC21,
+	DDP_COMPONENT_DVO0,
+};
+
+static const unsigned int mt8196_mtk_ddp_ovl0_ext[] = {
+	DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1,
+	DDP_COMPONENT_OVL0_DLO_ASYNC6,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp0_ext[] = {
+	DDP_COMPONENT_DLI_ASYNC1,
+	DDP_COMPONENT_DLO_ASYNC2,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp1_ext[] = {
+	DDP_COMPONENT_DLI_ASYNC22,
+	DDP_COMPONENT_DP_INTF0,
+};
+
+static const unsigned int mt8196_mtk_ddp_ovl1_third[] = {
+	DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2,
+	DDP_COMPONENT_OVL1_DLO_ASYNC5,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp0_third[] = {
+	DDP_COMPONENT_DLI_ASYNC8,
+	DDP_COMPONENT_DLO_ASYNC3,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp1_third[] = {
+	DDP_COMPONENT_DLI_ASYNC23,
+};
+
 static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
 	.main_path = mt2701_mtk_ddp_main,
 	.main_len = ARRAY_SIZE(mt2701_mtk_ddp_main),
@@ -327,8 +375,65 @@ static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data = {
 	.min_height = 1,
 };
 
-static const struct mtk_mmsys_driver_data mt8365_mmsys_driver_data = {
-	.mmsys_dev_num = 1,
+static const struct mtk_mmsys_driver_data mt8196_dispsys0_driver_data = {
+	.main_path = mt8196_mtk_ddp_disp0_main,
+	.main_len = ARRAY_SIZE(mt8196_mtk_ddp_disp0_main),
+	.main_order = 1,
+	.ext_path = mt8196_mtk_ddp_disp0_ext,
+	.ext_len = ARRAY_SIZE(mt8196_mtk_ddp_disp0_ext),
+	.ext_order = 1,
+	.third_path = mt8196_mtk_ddp_disp0_third,
+	.third_len = ARRAY_SIZE(mt8196_mtk_ddp_disp0_third),
+	.third_order = 1,
+	.mmsys_id = DISPSYS0,
+	.mmsys_dev_num = 4,
+	.max_width = 8191,
+	.min_width = 2, /* 2-pixel align when ethdr is bypassed */
+	.min_height = 1,
+};
+
+static const struct mtk_mmsys_driver_data mt8196_dispsys1_driver_data = {
+	.main_path = mt8196_mtk_ddp_disp1_main,
+	.main_len = ARRAY_SIZE(mt8196_mtk_ddp_disp1_main),
+	.main_order = 2,
+	.ext_path = mt8196_mtk_ddp_disp1_ext,
+	.ext_len = ARRAY_SIZE(mt8196_mtk_ddp_disp1_ext),
+	.ext_order = 2,
+	.third_path = mt8196_mtk_ddp_disp1_third,
+	.third_len = ARRAY_SIZE(mt8196_mtk_ddp_disp1_third),
+	.conn_routes = mt8196_mtk_ddp_routes,
+	.num_conn_routes = ARRAY_SIZE(mt8196_mtk_ddp_routes),
+	.third_order = 2,
+	.mmsys_id = DISPSYS1,
+	.mmsys_dev_num = 4,
+	.max_width = 8191,
+	.min_width = 2, /* 2-pixel align when ethdr is bypassed */
+	.min_height = 1,
+};
+
+static const struct mtk_mmsys_driver_data mt8196_ovlsys0_driver_data = {
+	.main_path = mt8196_mtk_ddp_ovl0_main,
+	.main_len = ARRAY_SIZE(mt8196_mtk_ddp_ovl0_main),
+	.main_order = 0,
+	.ext_path = mt8196_mtk_ddp_ovl0_ext,
+	.ext_len = ARRAY_SIZE(mt8196_mtk_ddp_ovl0_ext),
+	.ext_order = 0,
+	.mmsys_id = OVLSYS0,
+	.mmsys_dev_num = 4,
+	.max_width = 8191,
+	.min_width = 2, /* 2-pixel align when ethdr is bypassed */
+	.min_height = 1,
+};
+
+static const struct mtk_mmsys_driver_data mt8196_ovlsys1_driver_data = {
+	.third_path = mt8196_mtk_ddp_ovl1_third,
+	.third_len = ARRAY_SIZE(mt8196_mtk_ddp_ovl1_third),
+	.third_order = 0,
+	.mmsys_id = OVLSYS1,
+	.mmsys_dev_num = 4,
+	.max_width = 8191,
+	.min_width = 2, /* 2-pixel align when ethdr is bypassed */
+	.min_height = 1,
 };
 
 static const struct of_device_id mtk_drm_of_ids[] = {
@@ -358,8 +463,14 @@ static const struct of_device_id mtk_drm_of_ids[] = {
 	  .data = &mt8195_vdosys0_driver_data},
 	{ .compatible = "mediatek,mt8195-vdosys1",
 	  .data = &mt8195_vdosys1_driver_data},
-	{ .compatible = "mediatek,mt8365-mmsys",
-	  .data = &mt8365_mmsys_driver_data},
+	{ .compatible = "mediatek,mt8196-dispsys0",
+	  .data = &mt8196_dispsys0_driver_data},
+	{ .compatible = "mediatek,mt8196-dispsys1",
+	  .data = &mt8196_dispsys1_driver_data},
+	{ .compatible = "mediatek,mt8196-ovlsys0",
+	  .data = &mt8196_ovlsys0_driver_data},
+	{ .compatible = "mediatek,mt8196-ovlsys1",
+	  .data = &mt8196_ovlsys1_driver_data},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, mtk_drm_of_ids);
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* Re: [PATCH v3 02/17] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
  2025-05-15  9:34 ` [PATCH v3 02/17] dt-bindings: display: mediatek: add EXDMA " paul-pl.chen
@ 2025-05-15 10:48   ` Rob Herring (Arm)
  2025-06-26  9:10   ` CK Hu (胡俊光)
  1 sibling, 0 replies; 35+ messages in thread
From: Rob Herring (Arm) @ 2025-05-15 10:48 UTC (permalink / raw)
  To: paul-pl.chen
  Cc: fshao, devicetree, Project_Global_Chrome_Upstream_Group,
	xiandong.wang, krzk+dt, dri-devel, nancy.lin, linux-mediatek,
	sirius.wang, singo.chang, linux-arm-kernel, p.zabel, treapking,
	jason-jh.lin, linux-kernel, matthias.bgg, conor+dt, chunkuang.hu,
	angelogioacchino.delregno, sunny.shen


On Thu, 15 May 2025 17:34:14 +0800, paul-pl.chen wrote:
> From: Paul-pl Chen <paul-pl.chen@mediatek.com>
> 
> Add mediatek,exdma.yaml to support EXDMA for MT8196.
> The MediaTek display overlap extended DMA engine, namely
> OVL_EXDMA or EXDMA, primarily functions as a DMA engine
> for reading data from DRAM with various DRAM footprints
> and data formats.
> 
> Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
> Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> ---
>  .../bindings/dma/mediatek,exdma.yaml          | 68 +++++++++++++++++++
>  1 file changed, 68 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/dma/mediatek,exdma.yaml
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/dma/mediatek,exdma.example.dtb: dma-controller@32850000 (mediatek,mt8196-exdma): 'mediatek,larb' is a required property
	from schema $id: http://devicetree.org/schemas/dma/mediatek,exdma.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250515093454.1729720-3-paul-pl.chen@mediatek.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v3 15/17] drm/mediatek: add ovlsys_adaptor support for MT8196
  2025-05-15  9:34 ` [PATCH v3 15/17] drm/mediatek: add ovlsys_adaptor " paul-pl.chen
@ 2025-05-16  6:34   ` kernel test robot
  2025-06-24  5:46   ` CK Hu (胡俊光)
  1 sibling, 0 replies; 35+ messages in thread
From: kernel test robot @ 2025-05-16  6:34 UTC (permalink / raw)
  To: paul-pl.chen, robh, krzk+dt, conor+dt, chunkuang.hu,
	angelogioacchino.delregno
  Cc: oe-kbuild-all, matthias.bgg, p.zabel, jason-jh.lin, nancy.lin,
	singo.chang, xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen,
	fshao, treapking, devicetree, linux-kernel, dri-devel,
	linux-mediatek, linux-arm-kernel,
	Project_Global_Chrome_Upstream_Group

Hi paul-pl.chen,

kernel test robot noticed the following build errors:

[auto build test ERROR on robh/for-next]
[also build test ERROR on linus/master v6.15-rc6 next-20250515]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/paul-pl-chen/dt-bindings-soc-mediatek-add-mutex-yaml-for-MT8196/20250515-173733
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link:    https://lore.kernel.org/r/20250515093454.1729720-16-paul-pl.chen%40mediatek.com
patch subject: [PATCH v3 15/17] drm/mediatek: add ovlsys_adaptor support for MT8196
config: arm64-randconfig-001-20250516 (https://download.01.org/0day-ci/archive/20250516/202505161422.JeAeW3Pd-lkp@intel.com/config)
compiler: aarch64-linux-gcc (GCC) 9.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250516/202505161422.JeAeW3Pd-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202505161422.JeAeW3Pd-lkp@intel.com/

All error/warnings (new ones prefixed by >>):

   drivers/gpu/drm/mediatek/mtk_drm_drv.c: In function 'mtk_drm_ovl_adaptor_probe':
>> drivers/gpu/drm/mediatek/mtk_drm_drv.c:1071:32: error: storage size of 'ovlsys_priv' isn't known
    1071 |  struct mtk_drm_ovlsys_private ovlsys_priv;
         |                                ^~~~~~~~~~~
>> drivers/gpu/drm/mediatek/mtk_drm_drv.c:1071:32: warning: unused variable 'ovlsys_priv' [-Wunused-variable]
   drivers/gpu/drm/mediatek/mtk_drm_drv.c: In function 'mtk_drm_probe':
   drivers/gpu/drm/mediatek/mtk_drm_drv.c:1145:50: error: 'DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2' undeclared (first use in this function); did you mean 'DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0'?
    1145 |  mtk_drm_ovl_adaptor_probe(dev, private, &match, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2);
         |                                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         |                                                  DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0
   drivers/gpu/drm/mediatek/mtk_drm_drv.c:1145:50: note: each undeclared identifier is reported only once for each function it appears in


vim +1071 drivers/gpu/drm/mediatek/mtk_drm_drv.c

  1066	
  1067	static void mtk_drm_ovl_adaptor_probe(struct device *dev, struct mtk_drm_private *private,
  1068					      struct component_match **match, enum mtk_ddp_comp_id id)
  1069	{
  1070		struct platform_device *ovl_adaptor;
> 1071		struct mtk_drm_ovlsys_private ovlsys_priv;
  1072		bool is_ovlsys = (id != DDP_COMPONENT_DRM_OVL_ADAPTOR);
  1073		char *dev_name = is_ovlsys ? "mediatek-disp-ovlsys-adaptor" : "mediatek-disp-ovl-adaptor";
  1074		void *drv_data = is_ovlsys ? (void *)&ovlsys_priv : (void *)private->mmsys_dev;
  1075		size_t data_size = is_ovlsys ? sizeof(ovlsys_priv) : sizeof(*private->mmsys_dev);
  1076	
  1077		if (mtk_drm_find_mmsys_comp(private, id, &ovlsys_priv.use_path)) {
  1078			ovlsys_priv.mmsys_dev = private->mmsys_dev;
  1079			ovl_adaptor = platform_device_register_data(dev, dev_name, PLATFORM_DEVID_AUTO,
  1080								    drv_data, data_size);
  1081			private->ddp_comp[id].dev = &ovl_adaptor->dev;
  1082			mtk_ddp_comp_init(NULL, &private->ddp_comp[id], id);
  1083			component_match_add(dev, match, compare_dev, &ovl_adaptor->dev);
  1084		}
  1085	}
  1086	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v3 16/17] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver
  2025-05-15  9:34 ` [PATCH v3 16/17] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver paul-pl.chen
@ 2025-05-16  7:36   ` kernel test robot
  2025-06-24  5:49   ` CK Hu (胡俊光)
  1 sibling, 0 replies; 35+ messages in thread
From: kernel test robot @ 2025-05-16  7:36 UTC (permalink / raw)
  To: paul-pl.chen, robh, krzk+dt, conor+dt, chunkuang.hu,
	angelogioacchino.delregno
  Cc: oe-kbuild-all, matthias.bgg, p.zabel, jason-jh.lin, nancy.lin,
	singo.chang, xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen,
	fshao, treapking, devicetree, linux-kernel, dri-devel,
	linux-mediatek, linux-arm-kernel,
	Project_Global_Chrome_Upstream_Group

Hi paul-pl.chen,

kernel test robot noticed the following build warnings:

[auto build test WARNING on robh/for-next]
[also build test WARNING on linus/master v6.15-rc6 next-20250515]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/paul-pl-chen/dt-bindings-soc-mediatek-add-mutex-yaml-for-MT8196/20250515-173733
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link:    https://lore.kernel.org/r/20250515093454.1729720-17-paul-pl.chen%40mediatek.com
patch subject: [PATCH v3 16/17] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver
config: arm64-randconfig-001-20250516 (https://download.01.org/0day-ci/archive/20250516/202505161512.PmRwb8Li-lkp@intel.com/config)
compiler: aarch64-linux-gcc (GCC) 9.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250516/202505161512.PmRwb8Li-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202505161512.PmRwb8Li-lkp@intel.com/

All warnings (new ones prefixed by >>):

   drivers/gpu/drm/mediatek/mtk_ddp_comp.c: In function 'mtk_find_possible_crtcs':
>> drivers/gpu/drm/mediatek/mtk_ddp_comp.c:670:3: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
     670 |   if (found)
         |   ^~
   drivers/gpu/drm/mediatek/mtk_ddp_comp.c:673:4: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
     673 |    count++;
         |    ^~~~~


vim +/if +670 drivers/gpu/drm/mediatek/mtk_ddp_comp.c

   622	
   623	int mtk_find_possible_crtcs(struct drm_device *drm, struct device *dev)
   624	{
   625		struct mtk_drm_private *private = drm->dev_private;
   626		const struct mtk_mmsys_driver_data *data;
   627		struct mtk_drm_private *priv_n;
   628		int i, j, count = 0, ret;
   629	
   630		/* search each path in private data */
   631		for (i = 0; i < MAX_CRTC; i++) {
   632			bool found = false;
   633			int avail_mmsys_num = 0;
   634	
   635			for (j = 0; j < private->data->mmsys_dev_num; j++) {
   636				const unsigned int *path = NULL;
   637				unsigned int path_len = 0;
   638	
   639				priv_n = private->all_drm_private[j];
   640				data = priv_n->data;
   641	
   642				if (i == CRTC_MAIN) {
   643					path = data->main_path;
   644					path_len = data->main_len;
   645				} else if (i == CRTC_EXT) {
   646					path = data->ext_path;
   647					path_len = data->ext_len;
   648				} else if (i == CRTC_THIRD) {
   649					path = data->third_path;
   650					path_len = data->third_len;
   651				}
   652	
   653				/* skip if no path data in current mmsys */
   654				if (path_len == 0 || !path) {
   655					avail_mmsys_num++;
   656					continue;
   657				}
   658	
   659				if (mtk_ddp_path_available(path, path_len, priv_n->comp_node))
   660					avail_mmsys_num++;
   661	
   662				if (mtk_ddp_comp_find(dev, path, path_len, priv_n->ddp_comp))
   663					found = true;
   664		}
   665	
   666			/* skip invalid path */
   667			if (avail_mmsys_num != private->data->mmsys_dev_num)
   668				continue;
   669	
 > 670			if (found)
   671				return BIT(count);
   672	
   673				count++;
   674		}
   675	
   676		ret = mtk_ddp_comp_find_in_route(dev,
   677						 private->data->conn_routes,
   678						 private->data->num_conn_routes,
   679						 private->ddp_comp);
   680	
   681		if (ret < 0)
   682			DRM_INFO("Failed to find comp in ddp table, ret = %d\n", ret);
   683	
   684		return ret;
   685	}
   686	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v3 03/17] dt-bindings: display: mediatek: add BLENDER yaml for MT8196
  2025-05-15  9:34 ` [PATCH v3 03/17] dt-bindings: display: mediatek: add BLENDER " paul-pl.chen
@ 2025-05-19  6:41   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 35+ messages in thread
From: Krzysztof Kozlowski @ 2025-05-19  6:41 UTC (permalink / raw)
  To: paul-pl.chen
  Cc: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno,
	matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
	xiandong.wang, sirius.wang, sunny.shen, fshao, treapking,
	devicetree, linux-kernel, dri-devel, linux-mediatek,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group

On Thu, May 15, 2025 at 05:34:15PM GMT, paul-pl.chen wrote:
> From: Paul-pl Chen <paul-pl.chen@mediatek.com>
> 
> Add mediatek,blender.yaml to support BLENDER for MT8196.
> MediaTek display overlap blender, namely OVL_BLENDER or BLENDER,
> executes the alpha blending function for overlapping layers
> from different sources.
> 
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> 

No blank line between tags, wrong order of tags.

> Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>

If you are the author, what does this SoB mean? When was this patch
written, by whom and when was the review given?

Can you start using b4?

You did not provide proper lore links to previous versions and tags are
not correctly added.

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v3 04/17] dt-bindings: display: mediatek: add OUTPROC yaml for MT8196
  2025-05-15  9:34 ` [PATCH v3 04/17] dt-bindings: display: mediatek: add OUTPROC " paul-pl.chen
@ 2025-05-19  6:43   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 35+ messages in thread
From: Krzysztof Kozlowski @ 2025-05-19  6:43 UTC (permalink / raw)
  To: paul-pl.chen
  Cc: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno,
	matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
	xiandong.wang, sirius.wang, sunny.shen, fshao, treapking,
	devicetree, linux-kernel, dri-devel, linux-mediatek,
	linux-arm-kernel, Project_Global_Chrome_Upstream_Group

On Thu, May 15, 2025 at 05:34:16PM GMT, paul-pl.chen wrote:
> From: Paul-pl Chen <paul-pl.chen@mediatek.com>
> 
> Add mediate,outproc.yaml to support OUTPROC for MT8196.
> MediaTek display overlap output processor, namely OVL_OUTPROC
> or OUTPROC,handles the post-stage of pixel processing in the
> overlapping procedure.
> 
> Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>

This was not here before. What is happening with this patchset? Why some
random SoBs were added?

Nothing like that was explained in commit msg.


> Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> ---
>  .../display/mediatek/mediatek,outproc.yaml    | 54 +++++++++++++++++++
>  1 file changed, 54 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,outproc.yaml
> 

...

> +examples:
> +  - |
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +
> +    soc {
> +        #address-cells = <2>;
> +        #size-cells = <2>;
> +
> +        outproc0: outproc@32970000 {

Drop unused label

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v3 10/17] drm/mediatek: Export OVL formats definitions and format conversion API
  2025-05-15  9:34 ` [PATCH v3 10/17] drm/mediatek: Export OVL formats definitions and format conversion API paul-pl.chen
@ 2025-06-17  5:43   ` CK Hu (胡俊光)
  2025-06-17  6:47     ` CK Hu (胡俊光)
  0 siblings, 1 reply; 35+ messages in thread
From: CK Hu (胡俊光) @ 2025-06-17  5:43 UTC (permalink / raw)
  To: robh@kernel.org, krzk+dt@kernel.org,
	Paul-pl Chen (陳柏霖), conor+dt@kernel.org,
	AngeloGioacchino Del Regno, chunkuang.hu@kernel.org
  Cc: Sunny Shen (沈姍姍),
	Sirius Wang (王皓昱),
	Nancy Lin (林欣螢),
	Xiandong Wang (王先冬),
	linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
	Project_Global_Chrome_Upstream_Group,
	linux-mediatek@lists.infradead.org,
	Jason-JH Lin (林睿祥),
	devicetree@vger.kernel.org, fshao@chromium.org,
	p.zabel@pengutronix.de, Singo Chang (張興國),
	linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
	treapking@chromium.org

On Thu, 2025-05-15 at 17:34 +0800, paul-pl.chen wrote:
> From: Nancy Lin <nancy.lin@mediatek.com>
> 
> In upcoming SoCs, the OVL component will be divided into multiple
> smaller hardware units to enhance flexibility. To facilitate this
> transition, the OVL format definitions and format conversion API
> should be exported for reuse across these units.
> 
> Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
> Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 214 ++++++++++++++----------
>  drivers/gpu/drm/mediatek/mtk_disp_ovl.h |  28 ++++
>  2 files changed, 150 insertions(+), 92 deletions(-)
>  create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovl.h
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> index d0581c4e3c99..a516b7c82b5a 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> @@ -3,8 +3,6 @@
>   * Copyright (c) 2015 MediaTek Inc.
>   */
>  
> -#include <drm/drm_blend.h>
> -#include <drm/drm_fourcc.h>
>  #include <drm/drm_framebuffer.h>
>  
>  #include <linux/clk.h>
> @@ -18,6 +16,7 @@
>  #include "mtk_crtc.h"
>  #include "mtk_ddp_comp.h"
>  #include "mtk_disp_drv.h"
> +#include "mtk_disp_ovl.h"
>  #include "mtk_drm_drv.h"
>  
>  #define DISP_REG_OVL_INTEN			0x0004
> @@ -62,22 +61,15 @@
>  /* OVL_CON_RGB_SWAP works only if OVL_CON_CLRFMT_MAN is enabled */
>  #define OVL_CON_RGB_SWAP	BIT(25)
>  
> -#define OVL_CON_CLRFMT_RGB	(1 << 12)
> -#define OVL_CON_CLRFMT_ARGB8888	(2 << 12)
> -#define OVL_CON_CLRFMT_RGBA8888	(3 << 12)
> -#define OVL_CON_CLRFMT_ABGR8888	(OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP)
> -#define OVL_CON_CLRFMT_BGRA8888	(OVL_CON_CLRFMT_RGBA8888 | OVL_CON_BYTE_SWAP)
> -#define OVL_CON_CLRFMT_UYVY	(4 << 12)
> -#define OVL_CON_CLRFMT_YUYV	(5 << 12)
> -#define OVL_CON_MTX_YUV_TO_RGB	(6 << 16)
> -#define OVL_CON_CLRFMT_PARGB8888 ((3 << 12) | OVL_CON_CLRFMT_MAN)
> -#define OVL_CON_CLRFMT_PABGR8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_RGB_SWAP)
> -#define OVL_CON_CLRFMT_PBGRA8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_BYTE_SWAP)
> -#define OVL_CON_CLRFMT_PRGBA8888 (OVL_CON_CLRFMT_PABGR8888 | OVL_CON_BYTE_SWAP)
> -#define OVL_CON_CLRFMT_RGB565(ovl)	((ovl)->data->fmt_rgb565_is_0 ? \
> -					0 : OVL_CON_CLRFMT_RGB)
> -#define OVL_CON_CLRFMT_RGB888(ovl)	((ovl)->data->fmt_rgb565_is_0 ? \
> -					OVL_CON_CLRFMT_RGB : 0)
> +#define OVL_CON_CLRFMT_RGB565(shift)	(0 << (shift))
> +#define OVL_CON_CLRFMT_RGB888(shift)	(1 << (shift))
> +#define OVL_CON_CLRFMT_ARGB8888(shift)	(2 << (shift))
> +#define OVL_CON_CLRFMT_RGBA8888(shift)	(3 << (shift))
> +#define OVL_CON_CLRFMT_UYVY(shift)	(4 << (shift))
> +#define OVL_CON_CLRFMT_YUYV(shift)	(5 << (shift))
> +#define OVL_CON_MTX_YUV_TO_RGB		(6 << 16)
> +#define OVL_CON_CLRFMT_PARGB8888(shift, man) ((3 << (shift)) | (man))
> +
>  #define	OVL_CON_AEN		BIT(8)
>  #define	OVL_CON_ALPHA		0xff
>  #define	OVL_CON_VIRT_FLIP	BIT(9)
> @@ -85,23 +77,7 @@
>  
>  #define OVL_COLOR_ALPHA		GENMASK(31, 24)
>  
> -static inline bool is_10bit_rgb(u32 fmt)
> -{
> -	switch (fmt) {
> -	case DRM_FORMAT_XRGB2101010:
> -	case DRM_FORMAT_ARGB2101010:
> -	case DRM_FORMAT_RGBX1010102:
> -	case DRM_FORMAT_RGBA1010102:
> -	case DRM_FORMAT_XBGR2101010:
> -	case DRM_FORMAT_ABGR2101010:
> -	case DRM_FORMAT_BGRX1010102:
> -	case DRM_FORMAT_BGRA1010102:
> -		return true;
> -	}
> -	return false;
> -}
> -
> -static const u32 mt8173_formats[] = {
> +const u32 mt8173_ovl_formats[] = {

It's not necessary to modify this.

>  	DRM_FORMAT_XRGB8888,
>  	DRM_FORMAT_ARGB8888,
>  	DRM_FORMAT_BGRX8888,
> @@ -115,7 +91,9 @@ static const u32 mt8173_formats[] = {
>  	DRM_FORMAT_YUYV,
>  };
>  
> -static const u32 mt8195_formats[] = {
> +const size_t mt8173_ovl_formats_len = ARRAY_SIZE(mt8173_ovl_formats);

It's not necessary to define this.

> +
> +const u32 mt8195_ovl_formats[] = {

It's not necessary to modify this.

>  	DRM_FORMAT_XRGB8888,
>  	DRM_FORMAT_ARGB8888,
>  	DRM_FORMAT_XRGB2101010,
> @@ -139,6 +117,8 @@ static const u32 mt8195_formats[] = {
>  	DRM_FORMAT_YUYV,
>  };
>  
> +const size_t mt8195_ovl_formats_len = ARRAY_SIZE(mt8195_ovl_formats);

It's not necessary to define this.

> +
>  struct mtk_disp_ovl_data {
>  	unsigned int addr;
>  	unsigned int gmc_bits;
> @@ -167,6 +147,22 @@ struct mtk_disp_ovl {
>  	void				*vblank_cb_data;
>  };
>  
> +bool mtk_ovl_is_10bit_rgb(unsigned int fmt)
> +{
> +	switch (fmt) {
> +	case DRM_FORMAT_XRGB2101010:
> +	case DRM_FORMAT_ARGB2101010:
> +	case DRM_FORMAT_RGBX1010102:
> +	case DRM_FORMAT_RGBA1010102:
> +	case DRM_FORMAT_XBGR2101010:
> +	case DRM_FORMAT_ABGR2101010:
> +	case DRM_FORMAT_BGRX1010102:
> +	case DRM_FORMAT_BGRA1010102:
> +		return true;
> +	}
> +	return false;
> +}
> +
>  static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id)
>  {
>  	struct mtk_disp_ovl *priv = dev_id;
> @@ -295,7 +291,7 @@ static void mtk_ovl_set_bit_depth(struct device *dev, int idx, u32 format,
>  	if (!ovl->data->supports_clrfmt_ext)
>  		return;
>  
> -	if (is_10bit_rgb(format))
> +	if (mtk_ovl_is_10bit_rgb(format))
>  		bit_depth = OVL_CON_CLRFMT_10_BIT;
>  
>  	mtk_ddp_write_mask(cmdq_pkt, OVL_CON_CLRFMT_BIT_DEPTH(bit_depth, idx),
> @@ -394,10 +390,8 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx,
>  		      DISP_REG_OVL_RDMA_CTRL(idx));
>  }
>  
> -static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl,
> -					struct mtk_plane_state *state)
> +unsigned int mtk_ovl_get_blend_mode(struct mtk_plane_state *state, unsigned int blend_modes)
>  {
> -	unsigned int fmt = state->pending.format;
>  	unsigned int blend_mode = DRM_MODE_BLEND_COVERAGE;
>  
>  	/*
> @@ -412,52 +406,102 @@ static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl,
>  	 * will get an error return from drm_plane_create_blend_mode_property() and
>  	 * state->base.pixel_blend_mode should not be used.
>  	 */
> -	if (ovl->data->blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
> +	if (blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
>  		blend_mode = state->base.pixel_blend_mode;

Originally, OVL would do this checking.
In this patch, it does not check this.
Let OVL keep this checking.

>  
> +	return blend_mode;
> +}
> +
> +unsigned int mtk_ovl_fmt_convert(unsigned int fmt, unsigned int blend_mode,
> +				 bool fmt_rgb565_is_0, bool color_convert,
> +				 u8 clrfmt_shift, u32 clrfmt_man, u32 byte_swap, u32 rgb_swap)
> +{
> +	unsigned int con = 0;
> +	bool need_byte_swap = false, need_rgb_swap = false;
> +
>  	switch (fmt) {
>  	default:
>  	case DRM_FORMAT_RGB565:
> -		return OVL_CON_CLRFMT_RGB565(ovl);
> +		con = fmt_rgb565_is_0 ?
> +			OVL_CON_CLRFMT_RGB565(clrfmt_shift) : OVL_CON_CLRFMT_RGB888(clrfmt_shift);
> +	break;
>  	case DRM_FORMAT_BGR565:
> -		return OVL_CON_CLRFMT_RGB565(ovl) | OVL_CON_BYTE_SWAP;
> +		con = fmt_rgb565_is_0 ?
> +			OVL_CON_CLRFMT_RGB565(clrfmt_shift) : OVL_CON_CLRFMT_RGB888(clrfmt_shift);
> +		need_byte_swap = true;	/* RGB565 -> BGR565 */
> +	break;
>  	case DRM_FORMAT_RGB888:
> -		return OVL_CON_CLRFMT_RGB888(ovl);
> +		con = fmt_rgb565_is_0 ?
> +			OVL_CON_CLRFMT_RGB888(clrfmt_shift) : OVL_CON_CLRFMT_RGB565(clrfmt_shift);
> +	break;
>  	case DRM_FORMAT_BGR888:
> -		return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP;
> +		con = fmt_rgb565_is_0 ?
> +			OVL_CON_CLRFMT_RGB888(clrfmt_shift) : OVL_CON_CLRFMT_RGB565(clrfmt_shift);
> +		need_byte_swap = true;	/* RGB888 -> BGR888 */
> +	break;
>  	case DRM_FORMAT_RGBX8888:
>  	case DRM_FORMAT_RGBA8888:
>  	case DRM_FORMAT_RGBX1010102:
>  	case DRM_FORMAT_RGBA1010102:
> -		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> -		       OVL_CON_CLRFMT_RGBA8888 :
> -		       OVL_CON_CLRFMT_PRGBA8888;
> +		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
> +			con = OVL_CON_CLRFMT_RGBA8888(clrfmt_shift);
> +		} else {
> +			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
> +			need_byte_swap = true;	/* PARGB8888 -> PBGRA8888 */
> +			need_rgb_swap = true;	/* PBGRA8888 -> PRGBA8888 */
> +		}
> +	break;
>  	case DRM_FORMAT_BGRX8888:
>  	case DRM_FORMAT_BGRA8888:
>  	case DRM_FORMAT_BGRX1010102:
>  	case DRM_FORMAT_BGRA1010102:
> -		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> -		       OVL_CON_CLRFMT_BGRA8888 :
> -		       OVL_CON_CLRFMT_PBGRA8888;
> +		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
> +			con = OVL_CON_CLRFMT_RGBA8888(clrfmt_shift);
> +			need_byte_swap = true;	/* RGB8888 -> BGR8888 */
> +		} else {
> +			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
> +			need_byte_swap = true;	/* PARGB8888 -> PBGRA8888 */
> +		}

More simple

con = blend_mode == DRM_MODE_BLEND_COVERAGE ?
	OVL_CON_CLRFMT_RGBA8888(clrfmt_shift) :
	OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);

/* RGBA8888 -> BGRA8888 or PARGB8888 -> PBGRA8888 */
need_byte_swap = true;

> +	break;
>  	case DRM_FORMAT_XRGB8888:
>  	case DRM_FORMAT_ARGB8888:
>  	case DRM_FORMAT_XRGB2101010:
>  	case DRM_FORMAT_ARGB2101010:
> -		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> -		       OVL_CON_CLRFMT_ARGB8888 :
> -		       OVL_CON_CLRFMT_PARGB8888;
> +		if (blend_mode == DRM_MODE_BLEND_COVERAGE)
> +			con = OVL_CON_CLRFMT_ARGB8888(clrfmt_shift);
> +		else
> +			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);

More simple

con = blend_mode == DRM_MODE_BLEND_COVERAGE ?
	OVL_CON_CLRFMT_ARGB8888(clrfmt_shift) :
	OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);

> +	break;
>  	case DRM_FORMAT_XBGR8888:
>  	case DRM_FORMAT_ABGR8888:
>  	case DRM_FORMAT_XBGR2101010:
>  	case DRM_FORMAT_ABGR2101010:
> -		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> -		       OVL_CON_CLRFMT_ABGR8888 :
> -		       OVL_CON_CLRFMT_PABGR8888;
> +		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
> +			con = OVL_CON_CLRFMT_ARGB8888(clrfmt_shift);
> +			need_rgb_swap = true;	/* ARGB8888 -> ABGR8888 */
> +		} else {
> +			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
> +			need_rgb_swap = true;	/* PARGB8888 -> PABGR8888 */
> +		}

More simple

con = blend_mode == DRM_MODE_BLEND_COVERAGE ?
	OVL_CON_CLRFMT_ARGB8888(clrfmt_shift) :
	OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);

/* RGB8888 -> ABGR8888 or PARGB8888 -> PABGR8888 */
need_rgb_swap = true;

> +	break;
>  	case DRM_FORMAT_UYVY:
> -		return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB;
> +		con = OVL_CON_CLRFMT_UYVY(clrfmt_shift);
> +	break;
>  	case DRM_FORMAT_YUYV:
> -		return OVL_CON_CLRFMT_YUYV | OVL_CON_MTX_YUV_TO_RGB;
> +		con = OVL_CON_CLRFMT_YUYV(clrfmt_shift);
> +	break;
>  	}
> +
> +	if (color_convert)
> +		con |= OVL_CON_MTX_YUV_TO_RGB;

For RGB format, you also do YUV_TO_RGB convert?

> +
> +	if (need_byte_swap)
> +		con |= byte_swap;
> +
> +	if (need_rgb_swap)
> +		con |= rgb_swap;
> +
> +	return con;
>  }
>  
>  static void mtk_ovl_afbc_layer_config(struct mtk_disp_ovl *ovl,
> @@ -504,7 +548,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
>  		return;
>  	}
>  
> -	con = mtk_ovl_fmt_convert(ovl, state);
> +	con = mtk_ovl_fmt_convert(fmt, blend_mode, ovl->data->fmt_rgb565_is_0, true,
> +				  12, OVL_CON_CLRFMT_MAN, OVL_CON_BYTE_SWAP, OVL_CON_RGB_SWAP);
>  	if (state->base.fb) {
>  		con |= state->base.alpha & OVL_CON_ALPHA;
>  
> @@ -514,15 +559,6 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
>  		 */
>  		if (blend_mode || state->base.fb->format->has_alpha)
>  			con |= OVL_CON_AEN;
> -
> -		/*
> -		 * Although the alpha channel can be ignored, CONST_BLD must be enabled
> -		 * for XRGB format, otherwise OVL will still read the value from memory.
> -		 * For RGB888 related formats, whether CONST_BLD is enabled or not won't
> -		 * affect the result. Therefore we use !has_alpha as the condition.
> -		 */
> -		if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE || !state->base.fb->format->has_alpha)
> -			ignore_pixel_alpha = OVL_CONST_BLEND;

Why do you modify this?
You change original OVL driver behavior.

>  	}
>  
>  	/*
> @@ -660,8 +696,8 @@ static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = {
>  	.gmc_bits = 8,
>  	.layer_nr = 4,
>  	.fmt_rgb565_is_0 = false,
> -	.formats = mt8173_formats,
> -	.num_formats = ARRAY_SIZE(mt8173_formats),
> +	.formats = mt8173_ovl_formats,
> +	.num_formats = mt8173_ovl_formats_len,

It's not necessary to modify this.

>  };
>  
>  static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = {
> @@ -669,8 +705,8 @@ static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = {
>  	.gmc_bits = 8,
>  	.layer_nr = 4,
>  	.fmt_rgb565_is_0 = true,
> -	.formats = mt8173_formats,
> -	.num_formats = ARRAY_SIZE(mt8173_formats),
> +	.formats = mt8173_ovl_formats,
> +	.num_formats = mt8173_ovl_formats_len,

It's not necessary to modify this.

>  };
>  
>  static const struct mtk_disp_ovl_data mt8183_ovl_driver_data = {
> @@ -678,8 +714,8 @@ static const struct mtk_disp_ovl_data mt8183_ovl_driver_data = {
>  	.gmc_bits = 10,
>  	.layer_nr = 4,
>  	.fmt_rgb565_is_0 = true,
> -	.formats = mt8173_formats,
> -	.num_formats = ARRAY_SIZE(mt8173_formats),
> +	.formats = mt8173_ovl_formats,
> +	.num_formats = mt8173_ovl_formats_len,

It's not necessary to modify this.

>  };
>  
>  static const struct mtk_disp_ovl_data mt8183_ovl_2l_driver_data = {
> @@ -687,8 +723,8 @@ static const struct mtk_disp_ovl_data mt8183_ovl_2l_driver_data = {
>  	.gmc_bits = 10,
>  	.layer_nr = 2,
>  	.fmt_rgb565_is_0 = true,
> -	.formats = mt8173_formats,
> -	.num_formats = ARRAY_SIZE(mt8173_formats),
> +	.formats = mt8173_ovl_formats,
> +	.num_formats = mt8173_ovl_formats_len,

It's not necessary to modify this.

>  };
>  
>  static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = {
> @@ -697,11 +733,9 @@ static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = {
>  	.layer_nr = 4,
>  	.fmt_rgb565_is_0 = true,
>  	.smi_id_en = true,
> -	.blend_modes = BIT(DRM_MODE_BLEND_PREMULTI) |
> -		       BIT(DRM_MODE_BLEND_COVERAGE) |
> -		       BIT(DRM_MODE_BLEND_PIXEL_NONE),
> -	.formats = mt8173_formats,
> -	.num_formats = ARRAY_SIZE(mt8173_formats),
> +	.blend_modes = MTK_OVL_SUPPORT_BLEND_MODES,
> +	.formats = mt8173_ovl_formats,
> +	.num_formats = mt8173_ovl_formats_len,
>  };
>  
>  static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = {
> @@ -710,11 +744,9 @@ static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = {
>  	.layer_nr = 2,
>  	.fmt_rgb565_is_0 = true,
>  	.smi_id_en = true,
> -	.blend_modes = BIT(DRM_MODE_BLEND_PREMULTI) |
> -		       BIT(DRM_MODE_BLEND_COVERAGE) |
> -		       BIT(DRM_MODE_BLEND_PIXEL_NONE),
> -	.formats = mt8173_formats,
> -	.num_formats = ARRAY_SIZE(mt8173_formats),
> +	.blend_modes = MTK_OVL_SUPPORT_BLEND_MODES,
> +	.formats = mt8173_ovl_formats,
> +	.num_formats = mt8173_ovl_formats_len,
>  };
>  
>  static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = {
> @@ -724,11 +756,9 @@ static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = {
>  	.fmt_rgb565_is_0 = true,
>  	.smi_id_en = true,
>  	.supports_afbc = true,
> -	.blend_modes = BIT(DRM_MODE_BLEND_PREMULTI) |
> -		       BIT(DRM_MODE_BLEND_COVERAGE) |
> -		       BIT(DRM_MODE_BLEND_PIXEL_NONE),
> -	.formats = mt8195_formats,
> -	.num_formats = ARRAY_SIZE(mt8195_formats),
> +	.blend_modes = MTK_OVL_SUPPORT_BLEND_MODES,
> +	.formats = mt8195_ovl_formats,
> +	.num_formats = mt8195_ovl_formats_len,
>  	.supports_clrfmt_ext = true,
>  };
>  
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.h b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
> new file mode 100644
> index 000000000000..3f7d7d54479d
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
> @@ -0,0 +1,28 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2025 MediaTek Inc.
> + */
> +
> +#ifndef __MTK_DISP_OVL_H__
> +#define __MTK_DISP_OVL_H__
> +
> +#include <drm/drm_blend.h>
> +#include <drm/drm_fourcc.h>
> +
> +#define MTK_OVL_SUPPORT_BLEND_MODES \
> +	(BIT(DRM_MODE_BLEND_PREMULTI) | \
> +	 BIT(DRM_MODE_BLEND_COVERAGE) | \
> +	 BIT(DRM_MODE_BLEND_PIXEL_NONE))

The title does not mention blend mode.
You may change the title or separate blend mode modification to another patch.

> +
> +extern const u32 mt8173_ovl_formats[];

It's not necessary to extern mt8173_ovl_formats[];

> +extern const size_t mt8173_ovl_formats_len;
> +extern const u32 mt8195_ovl_formats[];

Ditto.

Regards,
CK

> +extern const size_t mt8195_ovl_formats_len;
> +
> +bool mtk_ovl_is_10bit_rgb(unsigned int fmt);
> +unsigned int mtk_ovl_get_blend_mode(struct mtk_plane_state *state, unsigned int blend_modes);
> +unsigned int mtk_ovl_fmt_convert(unsigned int fmt, unsigned int blend_mode,
> +				 bool fmt_rgb565_is_0, bool color_convert,
> +				 u8 clrfmt_shift, u32 clrfmt_man, u32 byte_swap, u32 rgb_swap);
> +
> +#endif


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v3 11/17] drm/mediatek: drm/mediatek: Export OVL ignore pixel alpha function
  2025-05-15  9:34 ` [PATCH v3 11/17] drm/mediatek: drm/mediatek: Export OVL ignore pixel alpha function paul-pl.chen
@ 2025-06-17  6:06   ` CK Hu (胡俊光)
  0 siblings, 0 replies; 35+ messages in thread
From: CK Hu (胡俊光) @ 2025-06-17  6:06 UTC (permalink / raw)
  To: robh@kernel.org, krzk+dt@kernel.org,
	Paul-pl Chen (陳柏霖), conor+dt@kernel.org,
	AngeloGioacchino Del Regno, chunkuang.hu@kernel.org
  Cc: Sunny Shen (沈姍姍),
	Sirius Wang (王皓昱),
	Nancy Lin (林欣螢),
	Xiandong Wang (王先冬),
	linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
	Project_Global_Chrome_Upstream_Group,
	linux-mediatek@lists.infradead.org,
	Jason-JH Lin (林睿祥),
	devicetree@vger.kernel.org, fshao@chromium.org,
	p.zabel@pengutronix.de, Singo Chang (張興國),
	linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
	treapking@chromium.org

On Thu, 2025-05-15 at 17:34 +0800, paul-pl.chen wrote:
> From: Nancy Lin <nancy.lin@mediatek.com>
> 
> For the new BLENDER component, the OVL ignore pixel alpha logic
> should be exported as a function and reused it.
> 
> Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
> Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 24 ++++++++++++++++++++++--
>  drivers/gpu/drm/mediatek/mtk_disp_ovl.h |  1 +
>  2 files changed, 23 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> index a516b7c82b5a..747898a574da 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> @@ -211,6 +211,23 @@ void mtk_ovl_disable_vblank(struct device *dev)
>  	writel_relaxed(0x0, ovl->regs + DISP_REG_OVL_INTEN);
>  }
>  
> +bool mtk_ovl_is_ignore_pixel_alpha(struct mtk_plane_state *state, unsigned int blend_mode)
> +{
> +	if (!state->base.fb)
> +		return false;
> +	/*
> +	 * Although the alpha channel can be ignored, CONST_BLD must be enabled
> +	 * for XRGB format, otherwise OVL will still read the value from memory.
> +	 * For RGB888 related formats, whether CONST_BLD is enabled or not won't
> +	 * affect the result. Therefore we use !has_alpha as the condition.
> +	 */
> +
> +	if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE || !state->base.fb->format->has_alpha)
> +		return true;
> +
> +	return false;
> +}
> +
>  u32 mtk_ovl_get_blend_modes(struct device *dev)
>  {
>  	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
> @@ -539,7 +556,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
>  	unsigned int rotation = pending->rotation;
>  	unsigned int offset = (pending->y << 16) | pending->x;
>  	unsigned int src_size = (pending->height << 16) | pending->width;
> -	unsigned int blend_mode = state->base.pixel_blend_mode;
> +	unsigned int blend_mode = mtk_ovl_get_blend_mode(state, ovl->data->blend_modes);

I would like previous patch is about color format and this patch is about alpha blend.
You add mtk_ovl_get_blend_mode() in previous patch.
So remove mtk_ovl_get_blend_mode() in previous patch and add it in this patch.

In original design, blend_mode is only changed in mtk_ovl_format_convert(),
but this patch chagne blend_mode in mtk_ovl_layer_config().

In order to keep original behavior,
In below, where using blend_mode is chagned to use state->base.pixel_blend_mode,
so it's not necessary to have a variable blend_mode.

Regards,
CK

>  	unsigned int ignore_pixel_alpha = 0;
>  	unsigned int con;
>  
> @@ -557,7 +574,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
>  		 * For blend_modes supported SoCs, always enable alpha blending.
>  		 * For blend_modes unsupported SoCs, enable alpha blending when has_alpha is set.
>  		 */
> -		if (blend_mode || state->base.fb->format->has_alpha)
> +		if (state->base.pixel_blend_mode || state->base.fb->format->has_alpha)
>  			con |= OVL_CON_AEN;
>  	}
>  
> @@ -584,6 +601,9 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
>  
>  	mtk_ddp_write_relaxed(cmdq_pkt, con, &ovl->cmdq_reg, ovl->regs,
>  			      DISP_REG_OVL_CON(idx));
> +
> +	if (mtk_ovl_is_ignore_pixel_alpha(state, blend_mode))
> +		ignore_pixel_alpha = OVL_CONST_BLEND;
>  	mtk_ddp_write_relaxed(cmdq_pkt, pitch_lsb | ignore_pixel_alpha,
>  			      &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH(idx));
>  	mtk_ddp_write_relaxed(cmdq_pkt, src_size, &ovl->cmdq_reg, ovl->regs,
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.h b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
> index 3f7d7d54479d..431567538eb5 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
> @@ -20,6 +20,7 @@ extern const u32 mt8195_ovl_formats[];
>  extern const size_t mt8195_ovl_formats_len;
>  
>  bool mtk_ovl_is_10bit_rgb(unsigned int fmt);
> +bool mtk_ovl_is_ignore_pixel_alpha(struct mtk_plane_state *state, unsigned int blend_mode);
>  unsigned int mtk_ovl_get_blend_mode(struct mtk_plane_state *state, unsigned int blend_modes);
>  unsigned int mtk_ovl_fmt_convert(unsigned int fmt, unsigned int blend_mode,
>  				 bool fmt_rgb565_is_0, bool color_convert,


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v3 10/17] drm/mediatek: Export OVL formats definitions and format conversion API
  2025-06-17  5:43   ` CK Hu (胡俊光)
@ 2025-06-17  6:47     ` CK Hu (胡俊光)
  0 siblings, 0 replies; 35+ messages in thread
From: CK Hu (胡俊光) @ 2025-06-17  6:47 UTC (permalink / raw)
  To: robh@kernel.org, krzk+dt@kernel.org,
	Paul-pl Chen (陳柏霖), conor+dt@kernel.org,
	AngeloGioacchino Del Regno, chunkuang.hu@kernel.org
  Cc: Sunny Shen (沈姍姍),
	Sirius Wang (王皓昱),
	Nancy Lin (林欣螢),
	Xiandong Wang (王先冬),
	linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
	Project_Global_Chrome_Upstream_Group,
	linux-mediatek@lists.infradead.org,
	Jason-JH Lin (林睿祥),
	devicetree@vger.kernel.org, fshao@chromium.org,
	p.zabel@pengutronix.de, Singo Chang (張興國),
	linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
	treapking@chromium.org


> > +extern const u32 mt8195_ovl_formats[];
> 
> Ditto.

Sorry, it need to extern mt8195_ovl_formats for exdma driver.

Regards,
CK

> 
> Regards,
> CK
> 
> > +extern const size_t mt8195_ovl_formats_len;
> > +
> > +bool mtk_ovl_is_10bit_rgb(unsigned int fmt);
> > +unsigned int mtk_ovl_get_blend_mode(struct mtk_plane_state *state, unsigned int blend_modes);
> > +unsigned int mtk_ovl_fmt_convert(unsigned int fmt, unsigned int blend_mode,
> > +				 bool fmt_rgb565_is_0, bool color_convert,
> > +				 u8 clrfmt_shift, u32 clrfmt_man, u32 byte_swap, u32 rgb_swap);
> > +
> > +#endif
> 


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v3 12/17] drm/mediatek: add EXDMA support for MT8196
  2025-05-15  9:34 ` [PATCH v3 12/17] drm/mediatek: add EXDMA support for MT8196 paul-pl.chen
@ 2025-06-17  9:17   ` CK Hu (胡俊光)
  2025-07-04  6:26     ` Paul-pl Chen (陳柏霖)
  0 siblings, 1 reply; 35+ messages in thread
From: CK Hu (胡俊光) @ 2025-06-17  9:17 UTC (permalink / raw)
  To: robh@kernel.org, krzk+dt@kernel.org,
	Paul-pl Chen (陳柏霖), conor+dt@kernel.org,
	AngeloGioacchino Del Regno, chunkuang.hu@kernel.org
  Cc: Sunny Shen (沈姍姍),
	Sirius Wang (王皓昱),
	Nancy Lin (林欣螢),
	Xiandong Wang (王先冬),
	linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
	Project_Global_Chrome_Upstream_Group,
	linux-mediatek@lists.infradead.org,
	Jason-JH Lin (林睿祥),
	devicetree@vger.kernel.org, fshao@chromium.org,
	p.zabel@pengutronix.de, Singo Chang (張興國),
	linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
	treapking@chromium.org

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_CON		0xc
> +#define OVL_EXDMA_OP_8BIT_MODE				BIT(4)
> +#define OVL_EXDMA_HG_FOVL_EXDMA_CK_ON			BIT(8)
> +#define OVL_EXDMA_HF_FOVL_EXDMA_CK_ON			BIT(10)
> +#define DISP_REG_OVL_EXDMA_DATAPATH_CON		0x014
> +#define OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN		BIT(0)
> +#define OVL_EXDMA_DATAPATH_CON_GCLAST_EN		BIT(24)
> +#define OVL_EXDMA_DATAPATH_CON_HDR_GCLAST_EN		BIT(25)
> +#define DISP_REG_OVL_EXDMA_EN			0x020
> +#define OVL_EXDMA_EN					BIT(0)
> +#define DISP_REG_OVL_EXDMA_RST			0x024
> +#define OVL_EXDMA_RST					BIT(0)
> +#define DISP_REG_OVL_EXDMA_ROI_SIZE		0x030
> +#define DISP_REG_OVL_EXDMA_L0_EN		0x040
> +#define OVL_EXDMA_L0_EN					BIT(0)
> +#define DISP_REG_OVL_EXDMA_L0_OFFSET		0x044
> +#define DISP_REG_OVL_EXDMA_SRC_SIZE		0x048
> +#define DISP_REG_OVL_EXDMA_L0_CLRFMT		0x050
> +#define OVL_EXDMA_CON_FLD_CLRFMT			GENMASK(3, 0)
> +#define OVL_EXDMA_CON_CLRFMT_MAN			BIT(4)
> +#define OVL_EXDMA_CON_FLD_CLRFMT_NB			GENMASK(9, 8)
> +#define OVL_EXDMA_CON_CLRFMT_NB_10_BIT			BIT(8)
> +#define OVL_EXDMA_CON_BYTE_SWAP				BIT(16)
> +#define OVL_EXDMA_CON_RGB_SWAP				BIT(17)
> +#define DISP_REG_OVL_EXDMA_RDMA0_CTRL		0x100
> +#define OVL_EXDMA_RDMA0_EN				BIT(0)
> +#define DISP_REG_OVL_EXDMA_RDMA_BURST_CON1	0x1f4
> +#define OVL_EXDMA_RDMA_BURST_CON1_BURST16_EN		BIT(28)
> +#define OVL_EXDMA_RDMA_BURST_CON1_DDR_EN		BIT(30)
> +#define OVL_EXDMA_RDMA_BURST_CON1_DDR_ACK_EN		BIT(31)
> +#define DISP_REG_OVL_EXDMA_DUMMY_REG		0x200
> +#define OVL_EXDMA_EXT_DDR_EN_OPT			BIT(2)
> +#define OVL_EXDMA_FORCE_EXT_DDR_EN			BIT(3)
> +#define DISP_REG_OVL_EXDMA_GDRDY_PRD		0x208
> +#define DISP_REG_OVL_EXDMA_PITCH_MSB		0x2f0
> +#define OVL_EXDMA_L0_SRC_PITCH_MSB_MASK			GENMASK(3, 0)
> +#define DISP_REG_OVL_EXDMA_PITCH		0x2f4
> +#define OVL_EXDMA_L0_SRC_PITCH				GENMASK(15, 0)
> +#define OVL_EXDMA_L0_CONST_BLD				BIT(28)
> +#define OVL_EXDMA_L0_SRC_PITCH_MASK			GENMASK(15, 0)
> +#define DISP_REG_OVL_EXDMA_L0_GUSER_EXT		0x2fc
> +#define OVL_EXDMA_RDMA0_L0_VCSEL			BIT(5)
> +#define OVL_EXDMA_RDMA0_HDR_L0_VCSEL			BIT(21)
> +#define DISP_REG_OVL_EXDMA_CON			0x300
> +#define OVL_EXDMA_CON_FLD_INT_MTX_SEL			GENMASK(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_EN			BIT(27)
> +#define DISP_REG_OVL_EXDMA_ADDR			0xf40
> +#define DISP_REG_OVL_EXDMA_MOUT			0xff0
> +#define OVL_EXDMA_MOUT_OUT_DATA				BIT(0)
> +#define OVL_EXDMA_MOUT_BGCLR_OUT			BIT(1)
> +
> +struct mtk_disp_exdma {
> +	void __iomem		*regs;
> +	struct clk		*clk;
> +	struct cmdq_client_reg	cmdq_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.

> +	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.

> +	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

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


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v3 13/17] drm/mediatek: add BLENDER support for MT8196
  2025-05-15  9:34 ` [PATCH v3 13/17] drm/mediatek: add BLENDER " paul-pl.chen
@ 2025-06-18  6:40   ` CK Hu (胡俊光)
  2025-07-04  6:36     ` Paul-pl Chen (陳柏霖)
  0 siblings, 1 reply; 35+ messages in thread
From: CK Hu (胡俊光) @ 2025-06-18  6:40 UTC (permalink / raw)
  To: robh@kernel.org, krzk+dt@kernel.org,
	Paul-pl Chen (陳柏霖), conor+dt@kernel.org,
	AngeloGioacchino Del Regno, chunkuang.hu@kernel.org
  Cc: Sunny Shen (沈姍姍),
	Sirius Wang (王皓昱),
	Nancy Lin (林欣螢),
	Xiandong Wang (王先冬),
	linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
	Project_Global_Chrome_Upstream_Group,
	linux-mediatek@lists.infradead.org,
	Jason-JH Lin (林睿祥),
	devicetree@vger.kernel.org, fshao@chromium.org,
	p.zabel@pengutronix.de, Singo Chang (張興國),
	linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
	treapking@chromium.org

On Thu, 2025-05-15 at 17:34 +0800, paul-pl.chen wrote:
> From: Paul-pl Chen <paul-pl.chen@mediatek.com>
> 
> BLENDER executes the alpha blending function for overlapping
> layers from different sources, which is the primary function
> of the overlapping system.
> 
> Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
> Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> ---

[snip]

> +++ b/drivers/gpu/drm/mediatek/mtk_disp_blender.c
> @@ -0,0 +1,264 @@
> +// 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.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 "mtk_disp_drv.h"
> +#include "mtk_drm_drv.h"

alphabetic order.

> +#include "mtk_disp_blender.h"
> +#include "mtk_disp_ovl.h"
> +
> 

[snip]

> +
> +void mtk_disp_blender_config(struct device *dev, unsigned int w,
> +			     unsigned int h, unsigned int vrefresh,
> +			     unsigned int bpc, bool most_top,

vrefresh and bpc is useless, so drop them.

> +			     bool most_bottom, struct cmdq_pkt *cmdq_pkt)
> +{
> +	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> +	u32 datapath;
> +
> +	dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
> +	mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs,
> +		      DISP_REG_OVL_BLD_ROI_SIZE);
> +	mtk_ddp_write(cmdq_pkt, DISP_REG_OVL_BLD_BGCLR_BALCK, &priv->cmdq_reg, priv->regs,
> +		      DISP_REG_OVL_BLD_BGCLR_CLR);
> +
> +	/*
> +	 * The input source of blender layer can be EXDMA layer output or
> +	 * the blender constant layer itself.
> +	 * This color setting is configured for the blender constant layer.
> +	 */
> +	mtk_ddp_write(cmdq_pkt, DISP_REG_OVL_BLD_BGCLR_BALCK, &priv->cmdq_reg, priv->regs,
> +		      DISP_REG_OVL_BLD_L0_CLR);
> +
> +	if (most_top)
> +		datapath = OVL_BLD_BGCLR_OUT_TO_PROC;
> +	else
> +		datapath = OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER;
> +	/*
> +	 * The primary input is from EXDMA and the second input
> +	 * is optionally from another blender
> +	 */
> +	if (!most_bottom)
> +		datapath |= OVL_BLD_BGCLR_IN_SEL;
> +
> +	mtk_ddp_write_mask(cmdq_pkt, datapath,
> +			   &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_DATAPATH_CON,
> +			   OVL_BLD_BGCLR_OUT_TO_PROC | OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER |
> +			   OVL_BLD_BGCLR_IN_SEL);
> +}
> +
> +void mtk_disp_blender_start(struct device *dev, struct cmdq_pkt *cmdq_pkt)

Drop cmdq_pkt.

> +{
> +	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> +
> +	mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_BYPASS_SHADOW, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_BLD_SHADOW_CTRL, OVL_BLD_BYPASS_SHADOW);
> +	mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_EN, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_BLD_EN, OVL_BLD_EN);
> +}
> +
> +void mtk_disp_blender_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt)

Drop cmdq_pkt.

Regards,
CK

> +{
> +	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> +
> +	mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_BLD_EN, OVL_BLD_EN);
> +
> +	mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_RST, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_BLD_RST, OVL_BLD_RST);
> +	mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> +			   DISP_REG_OVL_BLD_RST, OVL_BLD_RST);
> +}
> +


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v3 14/17] drm/mediatek: add OUTPROC support for MT8196
  2025-05-15  9:34 ` [PATCH v3 14/17] drm/mediatek: add OUTPROC " paul-pl.chen
@ 2025-06-18  8:23   ` CK Hu (胡俊光)
  2025-07-04  7:24     ` Paul-pl Chen (陳柏霖)
  0 siblings, 1 reply; 35+ messages in thread
From: CK Hu (胡俊光) @ 2025-06-18  8:23 UTC (permalink / raw)
  To: robh@kernel.org, krzk+dt@kernel.org,
	Paul-pl Chen (陳柏霖), conor+dt@kernel.org,
	AngeloGioacchino Del Regno, chunkuang.hu@kernel.org
  Cc: Sunny Shen (沈姍姍),
	Sirius Wang (王皓昱),
	Nancy Lin (林欣螢),
	Xiandong Wang (王先冬),
	linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
	Project_Global_Chrome_Upstream_Group,
	linux-mediatek@lists.infradead.org,
	Jason-JH Lin (林睿祥),
	devicetree@vger.kernel.org, fshao@chromium.org,
	p.zabel@pengutronix.de, Singo Chang (張興國),
	linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
	treapking@chromium.org

On Thu, 2025-05-15 at 17: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>
> ---

[snip]

> +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);
> +	u32 tmp;
> +
> +	dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
> +
> +	writel((h << 16) | w, priv->regs + DISP_REG_OVL_OUTPROC_ROI_SIZE);
> +
> +	tmp = readl(priv->regs + DISP_REG_OVL_OUTPROC_DATAPATH_CON);
> +	tmp = (tmp & ~OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP) |
> +		  (OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP & OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP);

This would simplified as

tmp |= OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP;

> +	writel(tmp, priv->regs + DISP_REG_OVL_OUTPROC_DATAPATH_CON);
> +}
> +
> +void mtk_disp_outproc_start(struct device *dev)
> +{
> +	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +	unsigned int tmp;
> +
> +	tmp = readl(priv->regs + DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
> +	tmp = tmp | OVL_OUTPROC_BYPASS_SHADOW;

tmp |= OVL_OUTPROC_BYPASS_SHADOW;

> +	writel(tmp, priv->regs + DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
> +
> +	writel(0, priv->regs + DISP_REG_OVL_OUTPROC_INTSTA);

To align OVL driver, clear interrupt status in enable_vblank() function.

> +
> +	tmp = readl(priv->regs + DISP_REG_OVL_OUTPROC_EN);
> +	tmp = (tmp & ~OVL_OUTPROC_OVL_EN) | (OVL_OUTPROC_OVL_EN & OVL_OUTPROC_OVL_EN);

This would be simplified as

tmp |= OVL_OUTPROC_OVL_EN;

One question. In mtk_disp_outproc_stop(), you overwrite the whole register of  DISP_REG_OVL_OUTPROC_EN.
Why here not overwrite the whole register?

Regards,
CK

> +	writel(tmp, priv->regs + DISP_REG_OVL_OUTPROC_EN);
> +}
> +
> +void mtk_disp_outproc_stop(struct device *dev)
> +{
> +	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> +	writel(0, priv->regs + DISP_REG_OVL_OUTPROC_EN);
> +	writel(OVL_OUTPROC_RST, priv->regs + DISP_REG_OVL_OUTPROC_RST);
> +	writel(0, priv->regs + DISP_REG_OVL_OUTPROC_RST);
> +}
> +



^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v3 15/17] drm/mediatek: add ovlsys_adaptor support for MT8196
  2025-05-15  9:34 ` [PATCH v3 15/17] drm/mediatek: add ovlsys_adaptor " paul-pl.chen
  2025-05-16  6:34   ` kernel test robot
@ 2025-06-24  5:46   ` CK Hu (胡俊光)
  1 sibling, 0 replies; 35+ messages in thread
From: CK Hu (胡俊光) @ 2025-06-24  5:46 UTC (permalink / raw)
  To: robh@kernel.org, krzk+dt@kernel.org,
	Paul-pl Chen (陳柏霖), conor+dt@kernel.org,
	AngeloGioacchino Del Regno, chunkuang.hu@kernel.org
  Cc: Sunny Shen (沈姍姍),
	Sirius Wang (王皓昱),
	Nancy Lin (林欣螢),
	Xiandong Wang (王先冬),
	linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
	Project_Global_Chrome_Upstream_Group,
	linux-mediatek@lists.infradead.org,
	Jason-JH Lin (林睿祥),
	devicetree@vger.kernel.org, fshao@chromium.org,
	p.zabel@pengutronix.de, Singo Chang (張興國),
	linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
	treapking@chromium.org

On Thu, 2025-05-15 at 17:34 +0800, paul-pl.chen wrote:
> From: Nancy Lin <nancy.lin@mediatek.com>
> 
> Ovlsys_adaptor is an encapsulated module designed to
> simplify the DRM control flow. This module is composed
> of 20 EXDMAs, 20 BLENDERs, and 12 OUTPROCs.
> Two EXDMAs merge into one layer, allowing the module
> to support 20 layers for 3 display paths.
> Ovlsys_adaptor driver is integrated within the
> mtk_ddp_comp framework.
> 
> Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
> Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> ---

[snip]

> +
> +int mtk_ovlsys_adaptor_power_on(struct device *dev)
> +{
> +	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
> +	struct device *comp;
> +	int ret = 0;

int ret;

> +	int i;
> +
> +	for (i = 0; i < priv->path_size; i++) {
> +		comp = priv->ovl_adaptor_comp[priv->path[i]];
> +		if (!comp || get_type(priv->path[i]) != OVLSYS_ADAPTOR_TYPE_EXDMA)
> +			continue;
> +
> +		ret = pm_runtime_get_sync(comp);
> +		if (ret < 0) {
> +			dev_err(dev, "Failed to enable power domain %d, err %d\n", i, ret);
> +			goto pwr_err;
> +		}
> +	}
> +
> +	return ret;

return 0;

> +
> +pwr_err:
> +	while (--i >= 0) {
> +		comp = priv->ovl_adaptor_comp[i];
> +		if (!comp || get_type(priv->path[i]) != OVLSYS_ADAPTOR_TYPE_EXDMA)
> +			continue;
> +
> +		pm_runtime_put(priv->ovl_adaptor_comp[i]);
> +	}
> +
> +	return ret;
> +}
> +

[snip]

> +
> +void mtk_ovlsys_adaptor_layer_config(struct device *dev, unsigned int idx,
> +				     struct mtk_plane_state *state,
> +				     struct cmdq_pkt *cmdq_pkt)
> +{
> +	struct mtk_plane_pending_state *pending = &state->pending;
> +	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
> +	struct device *exdma;
> +	struct device *blender;
> +	const struct drm_format_info *fmt_info = drm_format_info(pending->format);
> +
> +	DRM_DEV_DEBUG_DRIVER(dev, "idx:%d enable:%d fmt:0x%x addr:0x%pad fb_w:%d {%d,%d,%d,%d}\n",
> +			     idx, pending->enable, pending->format,
> +			     &pending->addr, (pending->pitch / fmt_info->cpp[0]),
> +			     pending->x, pending->y, pending->width, pending->height);
> +
> +	exdma = priv->ovl_adaptor_comp[priv->path[idx * 2]];
> +	if (!exdma) {
> +		dev_err(dev, "%s: exdma%d comp not found\n", __func__, idx);
> +		return;
> +	}
> +
> +	blender = priv->ovl_adaptor_comp[priv->path[idx * 2 + 1]];
> +	if (!blender) {
> +		dev_err(dev, "%s: blender%d comp not found\n", __func__, idx);
> +		return;
> +	}
> +
> +	if (pending->height == 0 || pending->width == 0 ||
> +	    pending->x > OVLSYS_ADAPTOR_DRIVER_DATA_MAX_SIZE ||
> +	    pending->y > OVLSYS_ADAPTOR_DRIVER_DATA_MAX_SIZE)
> +		pending->enable = false;

In ovl_adaptor, it does not modify this.
And mtk_ethdr_layer_config() would check this again.
So align this behavior.

> +
> +	mtk_disp_exdma_layer_config(exdma, state, cmdq_pkt);
> +	mtk_disp_blender_layer_config(blender, state, cmdq_pkt);
> +}
> +
> +void mtk_ovlsys_adaptor_config(struct device *dev, unsigned int w,
> +			       unsigned int h, unsigned int vrefresh,
> +			       unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
> +{
> +	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
> +	int i;
> +	int blender_idx = 0;
> +
> +	for (i = 0; i < priv->path_size; i++) {
> +		if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER) {
> +			blender_idx++;
> +
> +			mtk_disp_blender_config(priv->ovl_adaptor_comp[priv->path[i]], w, h,
> +						vrefresh, bpc, blender_idx == priv->layer_nr,
> +						blender_idx == 1, cmdq_pkt);
> +		} else if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_OUTPROC) {
> +			mtk_disp_outproc_config(priv->ovl_adaptor_comp[priv->path[i]], w, h,
> +						vrefresh, bpc, cmdq_pkt);
> +		}
> +	}

for (i = 0; i < priv->layer_nr; i++)
	mtk_disp_blender_config(priv->ovl_adaptor_comp[priv->path[i * 2 + 1]], w, h,
				vrefresh, bpc, i == (priv->layer_nr - 1),
				i == 0, cmdq_pkt);

mtk_disp_outproc_config(priv->ovl_adaptor_comp[priv->path[i * 2]], w, h,
			vrefresh, bpc, cmdq_pkt);

> +}
> +
> +int mtk_ovlsys_adaptor_layer_check(struct device *dev,
> +				   unsigned int idx,
> +				   struct mtk_plane_state *mtk_state)
> +{
> +	struct drm_plane_state *state = &mtk_state->base;
> +
> +	/* Check if any unsupported rotation is set */
> +	if (state->rotation & ~DRM_MODE_ROTATE_0)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> 

[snip]

> +
> +void mtk_ovlsys_adaptor_stop(struct device *dev)
> +{
> +	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
> +	int i;
> +
> +	for (i = 0; i < (priv->path_size - 1); i += 2) {
> +		mtk_disp_exdma_start(priv->ovl_adaptor_comp[priv->path[i]], NULL);

mtk_disp_exdma_stop()

> +		mtk_disp_blender_start(priv->ovl_adaptor_comp[priv->path[i + 1]], NULL);

mtk_disp_blender_stop()

> +	}
> +
> +	mtk_disp_outproc_start(priv->ovl_adaptor_comp[priv->path[i]]);

mtk_disp_outproc_stop()

> +}
> +
> +int mtk_ovlsys_adaptor_clk_enable(struct device *dev)
> +{
> +	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
> +	struct device *comp;
> +	int ret = 0;

int ret;

> +	int i;
> +
> +	for (i = 0; i < priv->path_size; i++) {
> +		comp = priv->ovl_adaptor_comp[priv->path[i]];
> +		if (!comp)

I'm curious about why this happen?
If this would not happen, remove this.

> +			continue;
> +
> +		if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_EXDMA)
> +			ret = mtk_disp_exdma_clk_enable(comp);
> +		else if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER)
> +			ret = mtk_disp_blender_clk_enable(comp);
> +		else
> +			ret = mtk_disp_outproc_clk_enable(comp);
> +
> +		if (ret) {
> +			dev_err(dev, "Failed to enable clock %d, err %d\n", i, ret);
> +			goto clk_err;
> +		}
> +	}
> +
> +	return ret;

return 0;

> +
> +clk_err:
> +	while (--i >= 0) {
> +		comp = priv->ovl_adaptor_comp[priv->path[i]];
> +		if (!comp)
> +			continue;
> +
> +		if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_EXDMA)
> +			mtk_disp_exdma_clk_disable(comp);
> +		else if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER)
> +			mtk_disp_blender_clk_disable(comp);
> +		else
> +			mtk_disp_outproc_clk_disable(comp);
> +	}
> +
> +	return ret;
> +}
> +
> +void mtk_ovlsys_adaptor_clk_disable(struct device *dev)
> +{
> +	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
> +	struct device *comp;
> +	int i;
> +
> +	for (i = 0; i < priv->path_size; i++) {
> +		comp = priv->ovl_adaptor_comp[priv->path[i]];
> +		if (!comp)
> +			continue;
> +
> +		if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_EXDMA)
> +			mtk_disp_exdma_clk_disable(comp);
> +		else if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER)
> +			mtk_disp_blender_clk_disable(comp);
> +		else
> +			mtk_disp_outproc_clk_disable(comp);
> +	}
> +}
> +

[snip]

> +
> +static int mtk_disp_ovlsys_adaptor_master_bind(struct device *dev)
> +{
> +	struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
> +	int ret, i;
> +
> +	ret = component_bind_all(dev, priv->mmsys_dev);
> +
> +	if (ret)
> +		return dev_err_probe(dev, ret, "component_bind_all failed!\n");
> +
> +	priv->children_bound = true;
> +	priv->layer_nr = 0;

priv->layer_nr = priv->path_size / 2;

Regards,
CK

> +
> +	for (i = 0; i < priv->path_size; i++)
> +		if (comp_matches[priv->path[i]].type == OVLSYS_ADAPTOR_TYPE_BLENDER)
> +			priv->layer_nr++;
> +
> +	return 0;
> +}
> +


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v3 16/17] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver
  2025-05-15  9:34 ` [PATCH v3 16/17] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver paul-pl.chen
  2025-05-16  7:36   ` kernel test robot
@ 2025-06-24  5:49   ` CK Hu (胡俊光)
  1 sibling, 0 replies; 35+ messages in thread
From: CK Hu (胡俊光) @ 2025-06-24  5:49 UTC (permalink / raw)
  To: robh@kernel.org, krzk+dt@kernel.org,
	Paul-pl Chen (陳柏霖), conor+dt@kernel.org,
	AngeloGioacchino Del Regno, chunkuang.hu@kernel.org
  Cc: Sunny Shen (沈姍姍),
	Sirius Wang (王皓昱),
	Nancy Lin (林欣螢),
	Xiandong Wang (王先冬),
	linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
	Project_Global_Chrome_Upstream_Group,
	linux-mediatek@lists.infradead.org,
	Jason-JH Lin (林睿祥),
	devicetree@vger.kernel.org, fshao@chromium.org,
	p.zabel@pengutronix.de, Singo Chang (張興國),
	linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
	treapking@chromium.org

On Thu, 2025-05-15 at 17:34 +0800, paul-pl.chen wrote:
> From: Paul-pl Chen <paul-pl.chen@mediatek.com>
> 
> To support multiple mmsys instances in the one mediatek-drm instance,
> providing improved flexibility and scalability by the following changes:
> 
> 1. Add DDP_COMPONENT_DRM_OVLSYS_ADAPTOR* to probe the
>   ovlsys_adaptor drivers and support different mmsys composition.
> 2. Added new component types MTK_DISP_VIRTUAL to support the
>   routing to virtual display components.
> 3. Added and adjusted the existed structure or interface to extend
>   the support of multiple mmsys instances.
> 4. Modified the component matching and binding logic to support
>   multiple mmsys instances.

Letovlsys sub driver control OVLSYS0 and OVLSYS1, so mediatek drm driver would not see them and this patch is not necessary.

Regards,
CK

> 
> Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
> Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> ---


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v3 02/17] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
  2025-05-15  9:34 ` [PATCH v3 02/17] dt-bindings: display: mediatek: add EXDMA " paul-pl.chen
  2025-05-15 10:48   ` Rob Herring (Arm)
@ 2025-06-26  9:10   ` CK Hu (胡俊光)
  1 sibling, 0 replies; 35+ messages in thread
From: CK Hu (胡俊光) @ 2025-06-26  9:10 UTC (permalink / raw)
  To: robh@kernel.org, krzk+dt@kernel.org,
	Paul-pl Chen (陳柏霖), conor+dt@kernel.org,
	AngeloGioacchino Del Regno, chunkuang.hu@kernel.org
  Cc: Sunny Shen (沈姍姍),
	Sirius Wang (王皓昱),
	Nancy Lin (林欣螢),
	Xiandong Wang (王先冬),
	linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
	Project_Global_Chrome_Upstream_Group,
	linux-mediatek@lists.infradead.org,
	Jason-JH Lin (林睿祥),
	devicetree@vger.kernel.org, fshao@chromium.org,
	p.zabel@pengutronix.de, Singo Chang (張興國),
	linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
	treapking@chromium.org

Hi, Krzysztof:

On Thu, 2025-05-15 at 17:34 +0800, paul-pl.chen wrote:
> From: Paul-pl Chen <paul-pl.chen@mediatek.com>
> 
> Add mediatek,exdma.yaml to support EXDMA for MT8196.
> The MediaTek display overlap extended DMA engine, namely
> OVL_EXDMA or EXDMA, primarily functions as a DMA engine
> for reading data from DRAM with various DRAM footprints
> and data formats.
> 
> Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
> Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> ---
>  .../bindings/dma/mediatek,exdma.yaml          | 68 +++++++++++++++++++
>  1 file changed, 68 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/dma/mediatek,exdma.yaml
> 
> diff --git a/Documentation/devicetree/bindings/dma/mediatek,exdma.yaml b/Documentation/devicetree/bindings/dma/mediatek,exdma.yaml
> new file mode 100644
> index 000000000000..eabf0cfc839e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/dma/mediatek,exdma.yaml
> @@ -0,0 +1,68 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: https://urldefense.com/v3/__http://devicetree.org/schemas/dma/mediatek,exdma.yaml*__;Iw!!CTRNKA9wMg0ARbw!kyAk7kEiDjUCRgaUpAaRbjpX6B9M4Q7Sir5LSiDqKRw8uoTJRN1oCFUtZcst3vtG1Xc4hqcYEjBPd39E0QxRWv0$ 
> +$schema: https://urldefense.com/v3/__http://devicetree.org/meta-schemas/core.yaml*__;Iw!!CTRNKA9wMg0ARbw!kyAk7kEiDjUCRgaUpAaRbjpX6B9M4Q7Sir5LSiDqKRw8uoTJRN1oCFUtZcst3vtG1Xc4hqcYEjBPd39E8ZlPlfE$ 
> +
> +title: MediaTek display overlap extended DMA engine
> +
> +maintainers:
> +  - Chun-Kuang Hu <chunkuang.hu@kernel.org>
> +  - Philipp Zabel <p.zabel@pengutronix.de>
> +
> +description:
> +  The MediaTek display overlap extended DMA engine, namely OVL_EXDMA or EXDMA,
> +  primarily functions as 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, OVL_EXDMA also includes a color transfer function
> +  to process pixels into a consistent color domain.
> +
> +properties:
> +  compatible:
> +    const: mediatek,mt8196-exdma
> +
> +  reg:
> +    maxItems: 1
> +
> +  clocks:
> +    maxItems: 1
> +
> +  power-domains:
> +    maxItems: 1
> +
> +  mediatek,larb:
> +    $ref: /schemas/types.yaml#/definitions/phandle
> +    description: |
> +      A phandle to the local arbiters node in the current SoCs.
> +      Refer to bindings/memory-controllers/mediatek,smi-larb.yaml.

In MT8196, the data path that EXDMA access DRAM data is shown below.
 
EXDMA (dma device) <-> LARB <-> SMMU (mmu device) <-> DRAM
 
In MT8195, the data path that OVL access DRAM data is shown below.
 
OVL (dma device) <-> LARB <-> IOMMU_VPP (mmu device) <-> DRAM
 
These two are similar, and LARB works like a bus.
In MT8195 device tree [1] (upstream), OVL has an iommus property pointing to IOMMU_VPP,
and IOMMU_VPP has a larbs property pointing to LARB
 
                iommu_vpp: iommu@14018000 {
                         compatible = "mediatek,mt8195-iommu-vpp";
                         reg = <0 0x14018000 0 0x1000>;
                         mediatek,larbs = <&larb1 &larb3 &larb4 &larb6 &larb8
                                            &larb12 &larb14 &larb16 &larb18
                                            &larb20 &larb22 &larb23 &larb26
                                            &larb27>;
                         interrupts = <GIC_SPI 594 IRQ_TYPE_LEVEL_HIGH 0>;
                         clocks = <&vppsys0 CLK_VPP0_SMI_IOMMU>;
                         clock-names = "bclk";
                         #iommu-cells = <1>;
                         power-domains = <&spm MT8195_POWER_DOMAIN_VPPSYS0>;
                };
 
                display@14009000 {
                         compatible = "mediatek,mt8195-mdp3-ovl";
                         reg = <0 0x14009000 0 0x1000>;
                         interrupts = <GIC_SPI 586 IRQ_TYPE_LEVEL_HIGH 0>;
                         mediatek,gce-client-reg = <&gce1 SUBSYS_1400XXXX 0x9000 0x1000>;
                         clocks = <&vppsys0 CLK_VPP0_MDP_OVL>;
                         power-domains = <&spm MT8195_POWER_DOMAIN_VPPSYS0>;
                         iommus = <&iommu_vpp M4U_PORT_L4_MDP_OVL>;
                };
 
In MT8196 [2] (this patch), EXDMA has an iommus property pointing to SMMU and a larbs property pointing to LARB.
 
                 mm_smmu: iommu@30800000 {
                         compatible = "mediatek,mt8196-mm-smmu", "arm,smmu-v3";
                         reg = <0 0x30800000 0 0x1e0000>;
                         interrupts = <GIC_SPI 477 IRQ_TYPE_EDGE_RISING 0>;
                         interrupt-names = "combined";
                         #iommu-cells = <1>;
                 };
                 disp_ovl0_exdma2: dma-controller@32850000 {
                         compatible = "mediatek,mt8196-exdma";
                         reg = <0 0x32850000 0 0x1000>;
                         clocks = <&ovlsys_config_clk CLK_OVL_EXDMA2_DISP>;
                         power-domains = <&hfrpsys MT8196_POWER_DOMAIN_OVL0_DORMANT>;
                         mediatek,larb = <&smi_larb0>;
                         iommus = <&mm_smmu 144>;
                         #dma-cells = <1>;
                 };
 
Both hardware data path is similar, but LARB is pointed by IOMMU device in MT8195 and LARB is pointed by DMA device in MT8196.
Should LARB be pointed by the same device (DMA device or IOMMU device)?
Or another way to describe these three device?
 
 
[1] https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/arch/arm64/boot/dts/mediatek/mt8195.dtsi?h=next-20250626
[2] https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/6253459/2/arch/arm64/boot/dts/mediatek/mt8196.dtsi#3127

Regards,
CK

> +
> +  iommus:
> +    maxItems: 1
> +
> +  '#dma-cells':
> +    const: 1
> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - power-domains
> +  - mediatek,larb
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    soc {
> +        #address-cells = <2>;
> +        #size-cells = <2>;
> +
> +        exdma: dma-controller@32850000 {
> +            compatible = "mediatek,mt8196-exdma";
> +            reg = <0 0x32850000 0 0x1000>;
> +            clocks = <&ovlsys_config_clk 13>;
> +            power-domains = <&hfrpsys 12>;
> +            iommus = <&mm_smmu 144>;
> +            #dma-cells = <1>;
> +        };
> +    };


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v3 12/17] drm/mediatek: add EXDMA support for MT8196
  2025-06-17  9:17   ` CK Hu (胡俊光)
@ 2025-07-04  6:26     ` Paul-pl Chen (陳柏霖)
  0 siblings, 0 replies; 35+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-07-04  6:26 UTC (permalink / raw)
  To: CK Hu (胡俊光), robh@kernel.org,
	krzk+dt@kernel.org, conor+dt@kernel.org, chunkuang.hu@kernel.org,
	AngeloGioacchino Del Regno
  Cc: Sunny Shen (沈姍姍),
	Sirius Wang (王皓昱),
	Nancy Lin (林欣螢),
	Xiandong Wang (王先冬),
	linux-kernel@vger.kernel.org,
	Project_Global_Chrome_Upstream_Group,
	dri-devel@lists.freedesktop.org,
	linux-mediatek@lists.infradead.org,
	Jason-JH Lin (林睿祥),
	devicetree@vger.kernel.org, fshao@chromium.org,
	p.zabel@pengutronix.de, Singo Chang (張興國),
	linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
	treapking@chromium.org

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_CON		0xc
> > +#define OVL_EXDMA_OP_8BIT_MODE				BIT(4)
> > +#define OVL_EXDMA_HG_FOVL_EXDMA_CK_ON			BIT(8)
> > +#define OVL_EXDMA_HF_FOVL_EXDMA_CK_ON			BIT(10)
> > +#define DISP_REG_OVL_EXDMA_DATAPATH_CON		0x014
> > +#define OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN		BIT(0)
> > +#define OVL_EXDMA_DATAPATH_CON_GCLAST_EN		BIT(24)
> > +#define OVL_EXDMA_DATAPATH_CON_HDR_GCLAST_EN		BIT(25)
> > +#define DISP_REG_OVL_EXDMA_EN			0x020
> > +#define OVL_EXDMA_EN					BIT(0)
> > +#define DISP_REG_OVL_EXDMA_RST			0x024
> > +#define OVL_EXDMA_RST					BIT(0)
> > +#define DISP_REG_OVL_EXDMA_ROI_SIZE		0x030
> > +#define DISP_REG_OVL_EXDMA_L0_EN		0x040
> > +#define
> > OVL_EXDMA_L0_EN					BIT(0)
> > +#define DISP_REG_OVL_EXDMA_L0_OFFSET		0x044
> > +#define DISP_REG_OVL_EXDMA_SRC_SIZE		0x048
> > +#define DISP_REG_OVL_EXDMA_L0_CLRFMT		0x050
> > +#define OVL_EXDMA_CON_FLD_CLRFMT			GENMASK(3,
> > 0)
> > +#define OVL_EXDMA_CON_CLRFMT_MAN			BIT(4)
> > +#define OVL_EXDMA_CON_FLD_CLRFMT_NB			GENMASK(9,
> > 8)
> > +#define OVL_EXDMA_CON_CLRFMT_NB_10_BIT			BIT(8)
> > +#define
> > OVL_EXDMA_CON_BYTE_SWAP				BIT(16)
> > +#define OVL_EXDMA_CON_RGB_SWAP				BIT(17)
> > +#define DISP_REG_OVL_EXDMA_RDMA0_CTRL		0x100
> > +#define OVL_EXDMA_RDMA0_EN				BIT(0)
> > +#define DISP_REG_OVL_EXDMA_RDMA_BURST_CON1	0x1f4
> > +#define OVL_EXDMA_RDMA_BURST_CON1_BURST16_EN		BIT(28)
> > +#define OVL_EXDMA_RDMA_BURST_CON1_DDR_EN		BIT(30)
> > +#define OVL_EXDMA_RDMA_BURST_CON1_DDR_ACK_EN		BIT(31)
> > +#define DISP_REG_OVL_EXDMA_DUMMY_REG		0x200
> > +#define OVL_EXDMA_EXT_DDR_EN_OPT			BIT(2)
> > +#define OVL_EXDMA_FORCE_EXT_DDR_EN			BIT(3)
> > +#define DISP_REG_OVL_EXDMA_GDRDY_PRD		0x208
> > +#define DISP_REG_OVL_EXDMA_PITCH_MSB		0x2f0
> > +#define
> > OVL_EXDMA_L0_SRC_PITCH_MSB_MASK			GENMASK(3, 0)
> > +#define DISP_REG_OVL_EXDMA_PITCH		0x2f4
> > +#define
> > OVL_EXDMA_L0_SRC_PITCH				GENMASK(15, 0)
> > +#define OVL_EXDMA_L0_CONST_BLD				BIT(28)
> > +#define
> > OVL_EXDMA_L0_SRC_PITCH_MASK			GENMASK(15, 0)
> > +#define DISP_REG_OVL_EXDMA_L0_GUSER_EXT		0x2fc
> > +#define OVL_EXDMA_RDMA0_L0_VCSEL			BIT(5)
> > +#define OVL_EXDMA_RDMA0_HDR_L0_VCSEL			BIT(21)
> > +#define DISP_REG_OVL_EXDMA_CON			0x300
> > +#define
> > OVL_EXDMA_CON_FLD_INT_MTX_SEL			GENMASK(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_EN			BIT(27)
> > +#define DISP_REG_OVL_EXDMA_ADDR			0xf40
> > +#define DISP_REG_OVL_EXDMA_MOUT			0xff0
> > +#define
> > OVL_EXDMA_MOUT_OUT_DATA				BIT(0)
> > +#define OVL_EXDMA_MOUT_BGCLR_OUT			BIT(1)
> > +
> > +struct mtk_disp_exdma {
> > +	void __iomem		*regs;
> > +	struct clk		*clk;
> > +	struct cmdq_client_reg	cmdq_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);
> > +}
> > +
> 


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v3 13/17] drm/mediatek: add BLENDER support for MT8196
  2025-06-18  6:40   ` CK Hu (胡俊光)
@ 2025-07-04  6:36     ` Paul-pl Chen (陳柏霖)
  0 siblings, 0 replies; 35+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-07-04  6:36 UTC (permalink / raw)
  To: CK Hu (胡俊光), robh@kernel.org,
	krzk+dt@kernel.org, conor+dt@kernel.org, chunkuang.hu@kernel.org,
	AngeloGioacchino Del Regno
  Cc: Sunny Shen (沈姍姍),
	Sirius Wang (王皓昱),
	Nancy Lin (林欣螢),
	Xiandong Wang (王先冬),
	linux-kernel@vger.kernel.org,
	Project_Global_Chrome_Upstream_Group,
	dri-devel@lists.freedesktop.org,
	linux-mediatek@lists.infradead.org,
	Jason-JH Lin (林睿祥),
	devicetree@vger.kernel.org, fshao@chromium.org,
	p.zabel@pengutronix.de, Singo Chang (張興國),
	linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
	treapking@chromium.org

On Wed, 2025-06-18 at 06:40 +0000, CK Hu (胡俊光) wrote:
> On Thu, 2025-05-15 at 17:34 +0800, paul-pl.chen wrote:
> > From: Paul-pl Chen <paul-pl.chen@mediatek.com>
> > 
> > BLENDER executes the alpha blending function for overlapping
> > layers from different sources, which is the primary function
> > of the overlapping system.
> > 
> > Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
> > Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> > ---
> 
> [snip]
> 
> > +++ b/drivers/gpu/drm/mediatek/mtk_disp_blender.c
> > @@ -0,0 +1,264 @@
> > +// 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.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 "mtk_disp_drv.h"
> > +#include "mtk_drm_drv.h"
> 
> alphabetic order.
> 
Sure, I will remove the unused  cmdq_pkt and refactor function:
mtk_disp_exdma_start()
> > +#include "mtk_disp_blender.h"
> > +#include "mtk_disp_ovl.h"
> > +
> > 
> 
> [snip]
> 
> > +
> > +void mtk_disp_blender_config(struct device *dev, unsigned int w,
> > +			     unsigned int h, unsigned int
> > vrefresh,
> > +			     unsigned int bpc, bool most_top,
> 
> vrefresh and bpc is useless, so drop them.
> 

Understood, I will remove this unnecessary parameter.

> > +			     bool most_bottom, struct cmdq_pkt
> > *cmdq_pkt)
> > +{
> > +	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> > +	u32 datapath;
> > +
> > +	dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
> > +	mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg,
> > priv->regs,
> > +		      DISP_REG_OVL_BLD_ROI_SIZE);
> > +	mtk_ddp_write(cmdq_pkt, DISP_REG_OVL_BLD_BGCLR_BALCK,
> > &priv->cmdq_reg, priv->regs,
> > +		      DISP_REG_OVL_BLD_BGCLR_CLR);
> > +
> > +	/*
> > +	 * The input source of blender layer can be EXDMA layer
> > output or
> > +	 * the blender constant layer itself.
> > +	 * This color setting is configured for the blender
> > constant layer.
> > +	 */
> > +	mtk_ddp_write(cmdq_pkt, DISP_REG_OVL_BLD_BGCLR_BALCK,
> > &priv->cmdq_reg, priv->regs,
> > +		      DISP_REG_OVL_BLD_L0_CLR);
> > +
> > +	if (most_top)
> > +		datapath = OVL_BLD_BGCLR_OUT_TO_PROC;
> > +	else
> > +		datapath = OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER;
> > +	/*
> > +	 * The primary input is from EXDMA and the second input
> > +	 * is optionally from another blender
> > +	 */
> > +	if (!most_bottom)
> > +		datapath |= OVL_BLD_BGCLR_IN_SEL;
> > +
> > +	mtk_ddp_write_mask(cmdq_pkt, datapath,
> > +			   &priv->cmdq_reg, priv->regs,
> > DISP_REG_OVL_BLD_DATAPATH_CON,
> > +			   OVL_BLD_BGCLR_OUT_TO_PROC |
> > OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER |
> > +			   OVL_BLD_BGCLR_IN_SEL);
> > +}
> > +
> > +void mtk_disp_blender_start(struct device *dev, struct cmdq_pkt
> > *cmdq_pkt)
> 
> Drop cmdq_pkt.

OK, I will drop the cmd_pkt to refactor
function:mtk_disp_blender_start()
> 
> > +{
> > +	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> > +
> > +	mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_BYPASS_SHADOW, &priv-
> > >cmdq_reg, priv->regs,
> > +			   DISP_REG_OVL_BLD_SHADOW_CTRL,
> > OVL_BLD_BYPASS_SHADOW);
> > +	mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_EN, &priv->cmdq_reg,
> > priv->regs,
> > +			   DISP_REG_OVL_BLD_EN, OVL_BLD_EN);
> > +}
> > +
> > +void mtk_disp_blender_stop(struct device *dev, struct cmdq_pkt
> > *cmdq_pkt)
> 
> Drop cmdq_pkt.
> 
> Regards,
> CK
> 
OK, I will drop the cmd_pkt to refactor,
function:mtk_disp_blender_stop().

> > +{
> > +	struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> > +
> > +	mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv-
> > >regs,
> > +			   DISP_REG_OVL_BLD_EN, OVL_BLD_EN);
> > +
> > +	mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_RST, &priv->cmdq_reg,
> > priv->regs,
> > +			   DISP_REG_OVL_BLD_RST, OVL_BLD_RST);
> > +	mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv-
> > >regs,
> > +			   DISP_REG_OVL_BLD_RST, OVL_BLD_RST);
> > +}
> > +
> 


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH v3 14/17] drm/mediatek: add OUTPROC support for MT8196
  2025-06-18  8:23   ` CK Hu (胡俊光)
@ 2025-07-04  7:24     ` Paul-pl Chen (陳柏霖)
  0 siblings, 0 replies; 35+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-07-04  7:24 UTC (permalink / raw)
  To: CK Hu (胡俊光), robh@kernel.org,
	krzk+dt@kernel.org, conor+dt@kernel.org, chunkuang.hu@kernel.org,
	AngeloGioacchino Del Regno
  Cc: Sunny Shen (沈姍姍),
	Sirius Wang (王皓昱),
	Nancy Lin (林欣螢),
	Xiandong Wang (王先冬),
	linux-kernel@vger.kernel.org,
	Project_Global_Chrome_Upstream_Group,
	dri-devel@lists.freedesktop.org,
	linux-mediatek@lists.infradead.org,
	Jason-JH Lin (林睿祥),
	devicetree@vger.kernel.org, fshao@chromium.org,
	p.zabel@pengutronix.de, Singo Chang (張興國),
	linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
	treapking@chromium.org

On Wed, 2025-06-18 at 08:23 +0000, CK Hu (胡俊光) wrote:
> On Thu, 2025-05-15 at 17: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>
> > ---
> 
> [snip]
> 
> > +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);
> > +	u32 tmp;
> > +
> > +	dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
> > +
> > +	writel((h << 16) | w, priv->regs +
> > DISP_REG_OVL_OUTPROC_ROI_SIZE);
> > +
> > +	tmp = readl(priv->regs +
> > DISP_REG_OVL_OUTPROC_DATAPATH_CON);
> > +	tmp = (tmp & ~OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP) |
> > +		  (OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP &
> > OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP);
> 
> This would simplified as
> 
> tmp |= OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP;
> 

OK, I will refine the code to simplify this part.

> > +	writel(tmp, priv->regs +
> > DISP_REG_OVL_OUTPROC_DATAPATH_CON);
> > +}
> > +
> > +void mtk_disp_outproc_start(struct device *dev)
> > +{
> > +	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> > +	unsigned int tmp;
> > +
> > +	tmp = readl(priv->regs +
> > DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
> > +	tmp = tmp | OVL_OUTPROC_BYPASS_SHADOW;
> 
> tmp |= OVL_OUTPROC_BYPASS_SHADOW;

Understood, I will refine the code to simplify this part.
> 
> > +	writel(tmp, priv->regs +
> > DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
> > +
> > +	writel(0, priv->regs + DISP_REG_OVL_OUTPROC_INTSTA);
> 
> To align OVL driver, clear interrupt status in enable_vblank()
> function.
> 
> 

Understood, I will refine the code and move 
"the clear interrupt status" to function of enable_vblank().
> > +
> > +	tmp = readl(priv->regs + DISP_REG_OVL_OUTPROC_EN);
> > +	tmp = (tmp & ~OVL_OUTPROC_OVL_EN) | (OVL_OUTPROC_OVL_EN &
> > OVL_OUTPROC_OVL_EN);
> 
> This would be simplified as
> 
> tmp |= OVL_OUTPROC_OVL_EN;
> 

Understood, I will simplify the code. 

> One question. In mtk_disp_outproc_stop(), you overwrite the whole
> register of  DISP_REG_OVL_OUTPROC_EN.
> Why here not overwrite the whole register?
> 
> Regards,
> CK
> 
Hi Ck, I will perform an experiment to verify this part.

Best, Paul 
> > +	writel(tmp, priv->regs + DISP_REG_OVL_OUTPROC_EN);
> > +}
> > +
> > +void mtk_disp_outproc_stop(struct device *dev)
> > +{
> > +	struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> > +
> > +	writel(0, priv->regs + DISP_REG_OVL_OUTPROC_EN);
> > +	writel(OVL_OUTPROC_RST, priv->regs +
> > DISP_REG_OVL_OUTPROC_RST);
> > +	writel(0, priv->regs + DISP_REG_OVL_OUTPROC_RST);
> > +}
> > +
> 


^ permalink raw reply	[flat|nested] 35+ messages in thread

end of thread, other threads:[~2025-07-04  7:24 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-15  9:34 [PATCH v3 00/17] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
2025-05-15  9:34 ` [PATCH v3 01/17] dt-bindings: soc: mediatek: add mutex yaml " paul-pl.chen
2025-05-15  9:34 ` [PATCH v3 02/17] dt-bindings: display: mediatek: add EXDMA " paul-pl.chen
2025-05-15 10:48   ` Rob Herring (Arm)
2025-06-26  9:10   ` CK Hu (胡俊光)
2025-05-15  9:34 ` [PATCH v3 03/17] dt-bindings: display: mediatek: add BLENDER " paul-pl.chen
2025-05-19  6:41   ` Krzysztof Kozlowski
2025-05-15  9:34 ` [PATCH v3 04/17] dt-bindings: display: mediatek: add OUTPROC " paul-pl.chen
2025-05-19  6:43   ` Krzysztof Kozlowski
2025-05-15  9:34 ` [PATCH v3 05/17] soc: mediatek: Add runtime PM and top clocks and async controls for MMSYS paul-pl.chen
2025-05-15  9:34 ` [PATCH v3 06/17] soc: mediatek: add mmsys support for MT8196 paul-pl.chen
2025-05-15  9:34 ` [PATCH v3 07/17] soc: mediatek: mutex: Reused the switch case for SOF ID paul-pl.chen
2025-05-15  9:34 ` [PATCH v3 08/17] soc: mediatek: mutex: refactor SOF settings for output components paul-pl.chen
2025-05-15  9:34 ` [PATCH v3 09/17] soc: mediatek: mutex: add mutex support for MT8196 paul-pl.chen
2025-05-15  9:34 ` [PATCH v3 10/17] drm/mediatek: Export OVL formats definitions and format conversion API paul-pl.chen
2025-06-17  5:43   ` CK Hu (胡俊光)
2025-06-17  6:47     ` CK Hu (胡俊光)
2025-05-15  9:34 ` [PATCH v3 11/17] drm/mediatek: drm/mediatek: Export OVL ignore pixel alpha function paul-pl.chen
2025-06-17  6:06   ` CK Hu (胡俊光)
2025-05-15  9:34 ` [PATCH v3 12/17] drm/mediatek: add EXDMA support for MT8196 paul-pl.chen
2025-06-17  9:17   ` CK Hu (胡俊光)
2025-07-04  6:26     ` Paul-pl Chen (陳柏霖)
2025-05-15  9:34 ` [PATCH v3 13/17] drm/mediatek: add BLENDER " paul-pl.chen
2025-06-18  6:40   ` CK Hu (胡俊光)
2025-07-04  6:36     ` Paul-pl Chen (陳柏霖)
2025-05-15  9:34 ` [PATCH v3 14/17] drm/mediatek: add OUTPROC " paul-pl.chen
2025-06-18  8:23   ` CK Hu (胡俊光)
2025-07-04  7:24     ` Paul-pl Chen (陳柏霖)
2025-05-15  9:34 ` [PATCH v3 15/17] drm/mediatek: add ovlsys_adaptor " paul-pl.chen
2025-05-16  6:34   ` kernel test robot
2025-06-24  5:46   ` CK Hu (胡俊光)
2025-05-15  9:34 ` [PATCH v3 16/17] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver paul-pl.chen
2025-05-16  7:36   ` kernel test robot
2025-06-24  5:49   ` CK Hu (胡俊光)
2025-05-15  9:34 ` [PATCH v3 17/17] drm/mediatek: Add support for MT8196 multiple mmsys paul-pl.chen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).