linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196
@ 2025-08-28  8:06 Paul Chen
  2025-08-28  8:06 ` [PATCH v4 01/19] dt-bindings: arm: mediatek: mmsys: add compatible " Paul Chen
                   ` (19 more replies)
  0 siblings, 20 replies; 27+ messages in thread
From: Paul Chen @ 2025-08-28  8:06 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>

Changes in v4:
- [PATCH v4 11/19]
  Add New commit to refactor the naming of OVL Fornat.
- [PATCH v4 12/19]
  Refactor ovl_blend_mode fucntion
- [PATCH v4 13/19]
  Move mtk_ovl_get_blend_mode to this commit to align with driver.
- [PATCH v4 14/19]
  Remove the unused paramter cmdq
  Remove the reapet of pitch setting
- [PATCH v4 15/19]
  Remove the unused paramter cmdq
  Remove the useless parametrt of func():mtk_disp_blender_config
- [PATCH v4 16/19] 
  Simplified the driiver code to improve readability 
- [PATCH v4 17/19]
  Refine mtk_ovlsys_adaptor_layer_config's layer config checking. 
  Refine mtk_ovlsys_adaptor_config's logic
  Fix func()'s mtk_ovlsys_adaptor_stop settting
  Refine mtk_ovlsys_adaptor_clk_enbale to repaet NULL checking
- [PATCH v4 18/19]
  Fix the system report's syntext error

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 log

Nancy Lin (12):
  dt-bindings: arm: mediatek: mmsys: add compatible for MT8196
  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: add EXDMA support for MT8196
  drm/mediatek: add BLENDER support for MT8196
  drm/mediatek: add OUTPROC support for MT8196
  drm/mediatek: add ovlsys_adaptor support for MT8196
  drm/mediatek: Add support for multiple mmsys in the one mediatek-drm
    driver
  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: Rename OVL format naming
  drm/mediatek: Export OVL Blend function

 .../bindings/arm/mediatek/mediatek,mmsys.yaml |   5 +
 .../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   | 274 +++++++
 drivers/gpu/drm/mediatek/mtk_disp_blender.h   |  10 +
 drivers/gpu/drm/mediatek/mtk_disp_drv.h       |  66 ++
 drivers/gpu/drm/mediatek/mtk_disp_exdma.c     | 359 +++++++++
 drivers/gpu/drm/mediatek/mtk_disp_outproc.c   | 235 ++++++
 drivers/gpu/drm/mediatek/mtk_disp_outproc.h   |  22 +
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c       | 229 ++++--
 drivers/gpu/drm/mediatek/mtk_disp_ovl.h       |  29 +
 .../drm/mediatek/mtk_disp_ovlsys_adaptor.c    | 717 ++++++++++++++++++
 drivers/gpu/drm/mediatek/mtk_drm_drv.c        | 276 +++++--
 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              | 288 +++++--
 include/linux/soc/mediatek/mtk-mmsys.h        |  60 ++
 include/linux/soc/mediatek/mtk-mutex.h        |   4 +
 27 files changed, 3593 insertions(+), 293 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] 27+ messages in thread

* [PATCH v4 01/19] dt-bindings: arm: mediatek: mmsys: add compatible for MT8196
  2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
@ 2025-08-28  8:06 ` Paul Chen
  2025-08-28  8:06 ` [PATCH v4 02/19] dt-bindings: soc: mediatek: add mutex yaml " Paul Chen
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Paul Chen @ 2025-08-28  8:06 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>

In previous SoCs, a single HW pipeline was an independent mmsys,
which included the OVL module, PQ module, and display interface
module.

In the 8196, to increase the flexibility of pipeline connection
and control, the OVL module on a single HW pipeline was separated
into two mmsys, namely ovlsys0 and ovlsys1. The PQ module was also
separated into a dispsys0, and the display interface module was
separated into a dispsys1. Additionally, display power-related
settings are controlled through vdiso-ao.

For example:
The primary path and external path of the display both use
ovlsys0 -> dispsys0 -> dispsys1, forming a pipeline.

The third path of the display uses ovlsys1 -> dispsys0 -> dispsys1,
forming another pipeline.

Therefore, the 8196 needs to add 5 compatible string to support
mmsys for MT8196.

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

diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml
index 3f4262e93c78..5f244a8f6a47 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml
@@ -39,6 +39,11 @@ properties:
               - mediatek,mt8195-vdosys1
               - mediatek,mt8195-vppsys0
               - mediatek,mt8195-vppsys1
+              - mediatek,mt8196-dispsys0
+              - mediatek,mt8196-dispsys1
+              - mediatek,mt8196-ovlsys0
+              - mediatek,mt8196-ovlsys1
+              - mediatek,mt8196-vdisp-ao
               - mediatek,mt8365-mmsys
           - const: syscon
 
-- 
2.45.2



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

* [PATCH v4 02/19] dt-bindings: soc: mediatek: add mutex yaml for MT8196
  2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
  2025-08-28  8:06 ` [PATCH v4 01/19] dt-bindings: arm: mediatek: mmsys: add compatible " Paul Chen
@ 2025-08-28  8:06 ` Paul Chen
  2025-08-28  8:06 ` [PATCH v4 03/19] dt-bindings: display: mediatek: add EXDMA " Paul Chen
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Paul Chen @ 2025-08-28  8:06 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.

Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
 .../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] 27+ messages in thread

* [PATCH v4 03/19] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
  2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
  2025-08-28  8:06 ` [PATCH v4 01/19] dt-bindings: arm: mediatek: mmsys: add compatible " Paul Chen
  2025-08-28  8:06 ` [PATCH v4 02/19] dt-bindings: soc: mediatek: add mutex yaml " Paul Chen
@ 2025-08-28  8:06 ` Paul Chen
  2025-08-28 13:30   ` Rob Herring (Arm)
  2025-08-29  6:35   ` Krzysztof Kozlowski
  2025-08-28  8:06 ` [PATCH v4 04/19] dt-bindings: display: mediatek: add BLENDER " Paul Chen
                   ` (16 subsequent siblings)
  19 siblings, 2 replies; 27+ messages in thread
From: Paul Chen @ 2025-08-28  8:06 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: 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] 27+ messages in thread

* [PATCH v4 04/19] dt-bindings: display: mediatek: add BLENDER yaml for MT8196
  2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
                   ` (2 preceding siblings ...)
  2025-08-28  8:06 ` [PATCH v4 03/19] dt-bindings: display: mediatek: add EXDMA " Paul Chen
@ 2025-08-28  8:06 ` Paul Chen
  2025-08-28  8:07 ` [PATCH v4 05/19] dt-bindings: display: mediatek: add OUTPROC " Paul Chen
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Paul Chen @ 2025-08-28  8:06 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.

Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
 .../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] 27+ messages in thread

* [PATCH v4 05/19] dt-bindings: display: mediatek: add OUTPROC yaml for MT8196
  2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
                   ` (3 preceding siblings ...)
  2025-08-28  8:06 ` [PATCH v4 04/19] dt-bindings: display: mediatek: add BLENDER " Paul Chen
@ 2025-08-28  8:07 ` Paul Chen
  2025-08-29  6:49   ` Krzysztof Kozlowski
  2025-08-28  8:07 ` [PATCH v4 06/19] soc: mediatek: Add runtime PM and top clocks and async controls for MMSYS Paul Chen
                   ` (14 subsequent siblings)
  19 siblings, 1 reply; 27+ messages in thread
From: Paul Chen @ 2025-08-28  8:07 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: 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..7c884749dd7a
--- /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>;
+
+        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] 27+ messages in thread

* [PATCH v4 06/19] soc: mediatek: Add runtime PM and top clocks and async controls for MMSYS
  2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
                   ` (4 preceding siblings ...)
  2025-08-28  8:07 ` [PATCH v4 05/19] dt-bindings: display: mediatek: add OUTPROC " Paul Chen
@ 2025-08-28  8:07 ` Paul Chen
  2025-08-28  8:07 ` [PATCH v4 07/19] soc: mediatek: add mmsys support for MT8196 Paul Chen
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Paul Chen @ 2025-08-28  8:07 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] 27+ messages in thread

* [PATCH v4 07/19] soc: mediatek: add mmsys support for MT8196
  2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
                   ` (5 preceding siblings ...)
  2025-08-28  8:07 ` [PATCH v4 06/19] soc: mediatek: Add runtime PM and top clocks and async controls for MMSYS Paul Chen
@ 2025-08-28  8:07 ` Paul Chen
  2025-08-28  8:07 ` [PATCH v4 08/19] soc: mediatek: mutex: Reused the switch case for SOF ID Paul Chen
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Paul Chen @ 2025-08-28  8:07 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] 27+ messages in thread

* [PATCH v4 08/19] soc: mediatek: mutex: Reused the switch case for SOF ID
  2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
                   ` (6 preceding siblings ...)
  2025-08-28  8:07 ` [PATCH v4 07/19] soc: mediatek: add mmsys support for MT8196 Paul Chen
@ 2025-08-28  8:07 ` Paul Chen
  2025-08-28  8:07 ` [PATCH v4 09/19] soc: mediatek: mutex: refactor SOF settings for output components Paul Chen
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Paul Chen @ 2025-08-28  8:07 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: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
 drivers/soc/mediatek/mtk-mutex.c | 115 ++++++++++++++++---------------
 1 file changed, 60 insertions(+), 55 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
index 38179e8cd98f..1e5df5aa0bd5 100644
--- a/drivers/soc/mediatek/mtk-mutex.c
+++ b/drivers/soc/mediatek/mtk-mutex.c
@@ -887,53 +887,61 @@ 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, mod_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:
-		offset = DISP_REG_MUTEX_MOD(mtx, mtx->data->mutex_mod[id], mutex->id);
-		mod_id = mtx->data->mutex_mod[id] % 32;
-		reg = readl_relaxed(mtx->regs + offset);
-		reg |= BIT(mod_id);
-		writel_relaxed(reg, mtx->regs + offset);
+		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, mod_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);
+			reg = readl_relaxed(mtx->regs + offset);
+			reg |= 1 << mtx->data->mutex_mod[id];
+			writel_relaxed(reg, mtx->regs + offset);
+		} else {
+			offset = DISP_REG_MUTEX_MOD2(mutex->id);
+			reg = readl_relaxed(mtx->regs + offset);
+			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 +
+	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);
@@ -946,31 +954,28 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
 	unsigned int reg;
 	unsigned int mod_id;
 	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:
-		offset = DISP_REG_MUTEX_MOD(mtx, mtx->data->mutex_mod[id], mutex->id);
-		mod_id = mtx->data->mutex_mod[id] % 32;
-		reg = readl_relaxed(mtx->regs + offset);
-		reg &= ~BIT(mod_id);
-		writel_relaxed(reg, mtx->regs + offset);
-		break;
+	if (sof_id < 0) {
+		if (mtx->data->mutex_mod[id] < 32) {
+			offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
+						    mutex->id);
+			reg = readl_relaxed(mtx->regs + offset);
+			reg &= ~(1 << mtx->data->mutex_mod[id]);
+			writel_relaxed(reg, mtx->regs + offset);
+		} else {
+			offset = DISP_REG_MUTEX_MOD2(mutex->id);
+			reg = readl_relaxed(mtx->regs + offset);
+			reg &= ~(1 << (mtx->data->mutex_mod[id] - 32));
+			writel_relaxed(reg, mtx->regs + offset);
+		}
+		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] 27+ messages in thread

* [PATCH v4 09/19] soc: mediatek: mutex: refactor SOF settings for output components
  2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
                   ` (7 preceding siblings ...)
  2025-08-28  8:07 ` [PATCH v4 08/19] soc: mediatek: mutex: Reused the switch case for SOF ID Paul Chen
@ 2025-08-28  8:07 ` Paul Chen
  2025-08-28  8:07 ` [PATCH v4 10/19] soc: mediatek: mutex: add mutex support for MT8196 Paul Chen
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Paul Chen @ 2025-08-28  8:07 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: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
 drivers/soc/mediatek/mtk-mutex.c       | 57 +++++++++++++++++++++-----
 include/linux/soc/mediatek/mtk-mutex.h |  4 ++
 2 files changed, 51 insertions(+), 10 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
index 1e5df5aa0bd5..c48983d8a6cd 100644
--- a/drivers/soc/mediatek/mtk-mutex.c
+++ b/drivers/soc/mediatek/mtk-mutex.c
@@ -913,19 +913,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, mod_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);
@@ -941,8 +979,7 @@ void mtk_mutex_add_comp(struct mtk_mutex *mutex,
 		return;
 	}
 
-	writel_relaxed(mtx->data->mutex_sof[sof_id], mtx->regs +
-		       DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, mutex->id));
+	mtk_mutex_add_comp_sof(mutex, id);
 }
 EXPORT_SYMBOL_GPL(mtk_mutex_add_comp);
 
@@ -954,10 +991,11 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
 	unsigned int reg;
 	unsigned int mod_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);
@@ -973,9 +1011,8 @@ 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));
+	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] 27+ messages in thread

* [PATCH v4 10/19] soc: mediatek: mutex: add mutex support for MT8196
  2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
                   ` (8 preceding siblings ...)
  2025-08-28  8:07 ` [PATCH v4 09/19] soc: mediatek: mutex: refactor SOF settings for output components Paul Chen
@ 2025-08-28  8:07 ` Paul Chen
  2025-08-28  8:07 ` [PATCH v4 11/19] drm/mediatek: Rename OVL format naming Paul Chen
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Paul Chen @ 2025-08-28  8:07 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 | 148 +++++++++++++++++++++++++++++--
 1 file changed, 142 insertions(+), 6 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
index c48983d8a6cd..ebc938d065ce 100644
--- a/drivers/soc/mediatek/mtk-mutex.c
+++ b/drivers/soc/mediatek/mtk-mutex.c
@@ -22,6 +22,7 @@
 #define MT8183_MUTEX0_MOD0			0x30
 #define MT8183_MUTEX0_MOD1			0x34
 #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))
@@ -256,6 +257,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
@@ -316,6 +358,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)
@@ -329,6 +377,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;
@@ -345,6 +399,7 @@ enum mtk_mutex_sof_id {
 	MUTEX_SOF_DSI3,
 	MUTEX_SOF_DP_INTF0,
 	MUTEX_SOF_DP_INTF1,
+	MUTEX_SOF_DVO0,
 	DDP_MUTEX_SOF_MAX,
 };
 
@@ -356,6 +411,7 @@ struct mtk_mutex_data {
 	const u16 mutex_mod1_reg;
 	const u16 mutex_sof_reg;
 	const bool no_clk;
+	const bool need_sof_mod;
 };
 
 struct mtk_mutex_ctx {
@@ -645,6 +701,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,
@@ -730,6 +844,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,
@@ -836,6 +961,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,
@@ -906,6 +1039,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;
 	}
@@ -963,7 +1098,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);
@@ -976,10 +1111,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;
 	}
 
-	mtk_mutex_add_comp_sof(mutex, id);
+	if (is_output_comp)
+		mtk_mutex_add_comp_sof(mutex, id);
 }
 EXPORT_SYMBOL_GPL(mtk_mutex_add_comp);
 
@@ -995,7 +1130,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);
@@ -1008,10 +1143,10 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
 			reg &= ~(1 << (mtx->data->mutex_mod[id] - 32));
 			writel_relaxed(reg, mtx->regs + offset);
 		}
-		return;
 	}
 
-	mtk_mutex_remove_comp_sof(mutex, id);
+	if (is_output_comp)
+		mtk_mutex_remove_comp_sof(mutex, id);
 
 }
 EXPORT_SYMBOL_GPL(mtk_mutex_remove_comp);
@@ -1185,6 +1320,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] 27+ messages in thread

* [PATCH v4 11/19] drm/mediatek: Rename OVL format naming
  2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
                   ` (9 preceding siblings ...)
  2025-08-28  8:07 ` [PATCH v4 10/19] soc: mediatek: mutex: add mutex support for MT8196 Paul Chen
@ 2025-08-28  8:07 ` Paul Chen
  2025-09-01  2:45   ` CK Hu (胡俊光)
  2025-08-28  8:07 ` [PATCH v4 12/19] drm/mediatek: Export OVL formats definitions and format conversion API Paul Chen
                   ` (8 subsequent siblings)
  19 siblings, 1 reply; 27+ messages in thread
From: Paul Chen @ 2025-08-28  8:07 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>

Rename the OVL format naming

Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 32 ++++++++++++-------------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index e0236353d499..d4f096d37abc 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -101,7 +101,7 @@ static inline bool is_10bit_rgb(u32 fmt)
 	return false;
 }
 
-static const u32 mt8173_formats[] = {
+static const u32 mt8173_ovl_formats[] = {
 	DRM_FORMAT_XRGB8888,
 	DRM_FORMAT_ARGB8888,
 	DRM_FORMAT_BGRX8888,
@@ -115,7 +115,7 @@ static const u32 mt8173_formats[] = {
 	DRM_FORMAT_YUYV,
 };
 
-static const u32 mt8195_formats[] = {
+static const u32 mt8195_ovl_formats[] = {
 	DRM_FORMAT_XRGB8888,
 	DRM_FORMAT_ARGB8888,
 	DRM_FORMAT_XRGB2101010,
@@ -667,8 +667,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 = ARRAY_SIZE(mt8173_ovl_formats),
 };
 
 static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = {
@@ -676,8 +676,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 = ARRAY_SIZE(mt8173_ovl_formats),
 };
 
 static const struct mtk_disp_ovl_data mt8183_ovl_driver_data = {
@@ -685,8 +685,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 = ARRAY_SIZE(mt8173_ovl_formats),
 };
 
 static const struct mtk_disp_ovl_data mt8183_ovl_2l_driver_data = {
@@ -694,8 +694,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 = ARRAY_SIZE(mt8173_ovl_formats),
 };
 
 static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = {
@@ -707,8 +707,8 @@ static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = {
 	.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),
+	.formats = mt8173_ovl_formats,
+	.num_formats = ARRAY_SIZE(mt8173_ovl_formats),
 };
 
 static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = {
@@ -720,8 +720,8 @@ static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = {
 	.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),
+	.formats = mt8173_ovl_formats,
+	.num_formats = ARRAY_SIZE(mt8173_ovl_formats),
 };
 
 static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = {
@@ -734,8 +734,8 @@ static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = {
 	.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),
+	.formats = mt8195_ovl_formats,
+	.num_formats = ARRAY_SIZE(mt8195_ovl_formats),
 	.supports_clrfmt_ext = true,
 };
 
-- 
2.45.2



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

* [PATCH v4 12/19] drm/mediatek: Export OVL formats definitions and format conversion API
  2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
                   ` (10 preceding siblings ...)
  2025-08-28  8:07 ` [PATCH v4 11/19] drm/mediatek: Rename OVL format naming Paul Chen
@ 2025-08-28  8:07 ` Paul Chen
  2025-08-28  8:07 ` [PATCH v4 13/19] drm/mediatek: Export OVL Blend function Paul Chen
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Paul Chen @ 2025-08-28  8:07 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 | 177 +++++++++++++++---------
 drivers/gpu/drm/mediatek/mtk_disp_ovl.h |  21 +++
 2 files changed, 133 insertions(+), 65 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 d4f096d37abc..e3ee3f60f4ba 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -4,7 +4,6 @@
  */
 
 #include <drm/drm_blend.h>
-#include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 
 #include <linux/clk.h>
@@ -18,6 +17,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 +62,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)
@@ -101,7 +94,7 @@ static inline bool is_10bit_rgb(u32 fmt)
 	return false;
 }
 
-static const u32 mt8173_ovl_formats[] = {
+const u32 mt8173_ovl_formats[] = {
 	DRM_FORMAT_XRGB8888,
 	DRM_FORMAT_ARGB8888,
 	DRM_FORMAT_BGRX8888,
@@ -115,7 +108,9 @@ static const u32 mt8173_ovl_formats[] = {
 	DRM_FORMAT_YUYV,
 };
 
-static const u32 mt8195_ovl_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 +134,8 @@ static const u32 mt8195_ovl_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 +164,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;
@@ -302,7 +315,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),
@@ -401,70 +414,96 @@ 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_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 fmt = state->pending.format;
-	unsigned int blend_mode = DRM_MODE_BLEND_COVERAGE;
-
-	/*
-	 * For the platforms where OVL_CON_CLRFMT_MAN is defined in the hardware data sheet
-	 * and supports premultiplied color formats, such as OVL_CON_CLRFMT_PARGB8888.
-	 *
-	 * Check blend_modes in the driver data to see if premultiplied mode is supported.
-	 * If not, use coverage mode instead to set it to the supported color formats.
-	 *
-	 * Current DRM assumption is that alpha is default premultiplied, so the bitmask of
-	 * blend_modes must include BIT(DRM_MODE_BLEND_PREMULTI). Otherwise, mtk_plane_init()
-	 * 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))
-		blend_mode = state->base.pixel_blend_mode;
+	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,
@@ -511,7 +550,15 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
 		return;
 	}
 
-	con = mtk_ovl_fmt_convert(ovl, state);
+	if (ovl->data->blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
+		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);
+	else
+		con = mtk_ovl_fmt_convert(fmt, DRM_MODE_BLEND_COVERAGE,
+					  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;
 
@@ -668,7 +715,7 @@ static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = {
 	.layer_nr = 4,
 	.fmt_rgb565_is_0 = false,
 	.formats = mt8173_ovl_formats,
-	.num_formats = ARRAY_SIZE(mt8173_ovl_formats),
+	.num_formats = mt8173_ovl_formats_len,
 };
 
 static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = {
@@ -677,7 +724,7 @@ static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = {
 	.layer_nr = 4,
 	.fmt_rgb565_is_0 = true,
 	.formats = mt8173_ovl_formats,
-	.num_formats = ARRAY_SIZE(mt8173_ovl_formats),
+	.num_formats = mt8173_ovl_formats_len,
 };
 
 static const struct mtk_disp_ovl_data mt8183_ovl_driver_data = {
@@ -686,7 +733,7 @@ static const struct mtk_disp_ovl_data mt8183_ovl_driver_data = {
 	.layer_nr = 4,
 	.fmt_rgb565_is_0 = true,
 	.formats = mt8173_ovl_formats,
-	.num_formats = ARRAY_SIZE(mt8173_ovl_formats),
+	.num_formats = mt8173_ovl_formats_len,
 };
 
 static const struct mtk_disp_ovl_data mt8183_ovl_2l_driver_data = {
@@ -695,7 +742,7 @@ static const struct mtk_disp_ovl_data mt8183_ovl_2l_driver_data = {
 	.layer_nr = 2,
 	.fmt_rgb565_is_0 = true,
 	.formats = mt8173_ovl_formats,
-	.num_formats = ARRAY_SIZE(mt8173_ovl_formats),
+	.num_formats = mt8173_ovl_formats_len,
 };
 
 static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = {
@@ -708,7 +755,7 @@ static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = {
 		       BIT(DRM_MODE_BLEND_COVERAGE) |
 		       BIT(DRM_MODE_BLEND_PIXEL_NONE),
 	.formats = mt8173_ovl_formats,
-	.num_formats = ARRAY_SIZE(mt8173_ovl_formats),
+	.num_formats = mt8173_ovl_formats_len,
 };
 
 static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = {
@@ -721,7 +768,7 @@ static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = {
 		       BIT(DRM_MODE_BLEND_COVERAGE) |
 		       BIT(DRM_MODE_BLEND_PIXEL_NONE),
 	.formats = mt8173_ovl_formats,
-	.num_formats = ARRAY_SIZE(mt8173_ovl_formats),
+	.num_formats = mt8173_ovl_formats_len,
 };
 
 static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = {
@@ -735,7 +782,7 @@ static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = {
 		       BIT(DRM_MODE_BLEND_COVERAGE) |
 		       BIT(DRM_MODE_BLEND_PIXEL_NONE),
 	.formats = mt8195_ovl_formats,
-	.num_formats = ARRAY_SIZE(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..4f446d2e0712
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
@@ -0,0 +1,21 @@
+/* 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_fourcc.h>
+
+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_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] 27+ messages in thread

* [PATCH v4 13/19] drm/mediatek: Export OVL Blend function
  2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
                   ` (11 preceding siblings ...)
  2025-08-28  8:07 ` [PATCH v4 12/19] drm/mediatek: Export OVL formats definitions and format conversion API Paul Chen
@ 2025-08-28  8:07 ` Paul Chen
  2025-08-28  8:07 ` [PATCH v4 14/19] drm/mediatek: add EXDMA support for MT8196 Paul Chen
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Paul Chen @ 2025-08-28  8:07 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>

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 | 68 +++++++++++++++++--------
 drivers/gpu/drm/mediatek/mtk_disp_ovl.h |  8 +++
 2 files changed, 56 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index e3ee3f60f4ba..7cd3978beb98 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -228,6 +228,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);
@@ -414,6 +431,29 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx,
 		      DISP_REG_OVL_RDMA_CTRL(idx));
 }
 
+unsigned int mtk_ovl_get_blend_mode(struct mtk_plane_state *state, unsigned int blend_modes)
+{
+	unsigned int blend_mode = DRM_MODE_BLEND_COVERAGE;
+
+	/*
+	 * For the platforms where OVL_CON_CLRFMT_MAN is defined in the hardware data sheet
+	 * and supports premultiplied color formats, such as OVL_CON_CLRFMT_PARGB888
+	 * and supports premultiplied color formats, such as OVL_CON_CLRFMT_PARGB8888.
+	 *
+	 * Check blend_modes in the driver data to see if premultiplied mode is supported.
+	 * If not, use coverage mode instead to set it to the supported color formats.
+	 *
+	 * Current DRM assumption is that alpha is default premultiplied, so the bitmask of
+	 * blend_modes must include BIT(DRM_MODE_BLEND_PREMULTI). Otherwise, mtk_plane_init()
+	 * will get an error return from drm_plane_create_blend_mode_property() and
+	 * state->base.pixel_blend_mode should not be used.
+	 */
+	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)
@@ -541,7 +581,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;
 
@@ -566,17 +606,8 @@ 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;
-
-		/*
-		 * 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;
 	}
 
 	/*
@@ -602,6 +633,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,
@@ -751,9 +785,7 @@ 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),
+	.blend_modes = MTK_OVL_SUPPORT_BLEND_MODES,
 	.formats = mt8173_ovl_formats,
 	.num_formats = mt8173_ovl_formats_len,
 };
@@ -764,9 +796,7 @@ 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),
+	.blend_modes = MTK_OVL_SUPPORT_BLEND_MODES,
 	.formats = mt8173_ovl_formats,
 	.num_formats = mt8173_ovl_formats_len,
 };
@@ -778,9 +808,7 @@ 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),
+	.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
index 4f446d2e0712..431567538eb5 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
@@ -6,14 +6,22 @@
 #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);
+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,
 				 u8 clrfmt_shift, u32 clrfmt_man, u32 byte_swap, u32 rgb_swap);
-- 
2.45.2



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

* [PATCH v4 14/19] drm/mediatek: add EXDMA support for MT8196
  2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
                   ` (12 preceding siblings ...)
  2025-08-28  8:07 ` [PATCH v4 13/19] drm/mediatek: Export OVL Blend function Paul Chen
@ 2025-08-28  8:07 ` Paul Chen
  2025-08-28  8:07 ` [PATCH v4 15/19] drm/mediatek: add BLENDER " Paul Chen
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Paul Chen @ 2025-08-28  8:07 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.

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 | 359 ++++++++++++++++++++++
 drivers/gpu/drm/mediatek/mtk_drm_drv.c    |   1 +
 drivers/gpu/drm/mediatek/mtk_drm_drv.h    |   1 +
 7 files changed, 373 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 43afd0a26d14..92d2ce25ebc4 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 ac6620e10262..d9b771b03233 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -446,6 +446,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 7289b3dcf22f..5169a107e575 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 679d413bf10b..b9d8f17c4f31 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);
+void mtk_disp_exdma_stop(struct device *dev);
+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..9acb5da29712
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_exdma.c
@@ -0,0 +1,359 @@
+// 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_data {
+	unsigned int max_size;
+};
+
+struct mtk_disp_exdma {
+	void __iomem *regs;
+	struct clk *clk;
+	struct cmdq_client_reg cmdq_reg;
+	struct device *larb;
+	const struct mtk_disp_exdma_data *data;
+};
+
+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 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(NULL, 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(NULL, 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(NULL, value, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_DATAPATH_CON, value);
+
+	mtk_ddp_write_mask(NULL, 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(NULL, ~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(NULL, value, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_EN_CON, value);
+	mtk_ddp_write_mask(NULL, 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 mtk_disp_exdma *priv = dev_get_drvdata(dev);
+	unsigned int mask;
+
+	mtk_ddp_write_mask(NULL, 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(NULL, 0, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_EN_CON, mask);
+	mtk_ddp_write_mask(NULL, 0, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_DATAPATH_CON, OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN);
+	mtk_ddp_write_mask(NULL, OVL_EXDMA_RST, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_EXDMA_RST, OVL_EXDMA_RST);
+	mtk_ddp_write_mask(NULL, 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 || pending->height == 0 || pending->width == 0 ||
+	    pending->x > priv->data->max_size || pending->y > priv->data->max_size) {
+		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);
+
+	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, 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);
+
+	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
+	priv->data = of_device_get_match_data(dev);
+	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 mtk_disp_exdma_data mt8196_disp_exdma_driver_data = {
+	.max_size = 8191,
+};
+
+static const struct of_device_id mtk_disp_exdma_driver_dt_match[] = {
+	{ .compatible = "mediatek,mt8196-exdma",
+	  .data = &mt8196_disp_exdma_driver_data},
+	{},
+};
+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 d5e6bab36414..f9ae81cbd019 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -1290,6 +1290,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] 27+ messages in thread

* [PATCH v4 15/19] drm/mediatek: add BLENDER support for MT8196
  2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
                   ` (13 preceding siblings ...)
  2025-08-28  8:07 ` [PATCH v4 14/19] drm/mediatek: add EXDMA support for MT8196 Paul Chen
@ 2025-08-28  8:07 ` Paul Chen
  2025-08-28  8:07 ` [PATCH v4 16/19] drm/mediatek: add OUTPROC " Paul Chen
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Paul Chen @ 2025-08-28  8:07 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>

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 | 274 ++++++++++++++++++++
 drivers/gpu/drm/mediatek/mtk_disp_blender.h |  10 +
 drivers/gpu/drm/mediatek/mtk_disp_drv.h     |  11 +
 drivers/gpu/drm/mediatek/mtk_drm_drv.c      |   1 +
 drivers/gpu/drm/mediatek/mtk_drm_drv.h      |   1 +
 8 files changed, 300 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 92d2ce25ebc4..8d18d5583903 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 d9b771b03233..2e45580f25ea 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -446,6 +446,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 5169a107e575..290190d366af 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..9212d2e19ca7
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_blender.c
@@ -0,0 +1,274 @@
+// 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_blender.h"
+#include "mtk_disp_drv.h"
+#include "mtk_disp_ovl.h"
+#include "mtk_drm_drv.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_data {
+	unsigned int max_size;
+};
+
+struct mtk_disp_blender {
+	void __iomem *regs;
+	struct clk *clk;
+	struct cmdq_client_reg cmdq_reg;
+	const struct mtk_disp_blender_data *data;
+};
+
+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 || pending->height == 0 || pending->width == 0 ||
+	    pending->x > priv->data->max_size || pending->y > priv->data->max_size) {
+		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, 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 mtk_disp_blender *priv = dev_get_drvdata(dev);
+
+	mtk_ddp_write_mask(NULL, OVL_BLD_BYPASS_SHADOW, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_BLD_SHADOW_CTRL, OVL_BLD_BYPASS_SHADOW);
+	mtk_ddp_write_mask(NULL, 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 mtk_disp_blender *priv = dev_get_drvdata(dev);
+
+	mtk_ddp_write_mask(NULL, 0, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_BLD_EN, OVL_BLD_EN);
+
+	mtk_ddp_write_mask(NULL, OVL_BLD_RST, &priv->cmdq_reg, priv->regs,
+			   DISP_REG_OVL_BLD_RST, OVL_BLD_RST);
+	mtk_ddp_write_mask(NULL, 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);
+	priv->data = of_device_get_match_data(dev);
+	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 mtk_disp_blender_data mt8196_disp_blender_driver_data = {
+	.max_size = 8191,
+};
+
+static const struct of_device_id mtk_disp_blender_driver_dt_match[] = {
+	{ .compatible = "mediatek,mt8196-blender",
+	  .data = &mt8196_disp_blender_driver_data},
+	{},
+};
+
+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 b9d8f17c4f31..e0aeb87f0a5b 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,16 @@ 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);
+void mtk_disp_blender_stop(struct device *dev);
+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, 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);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index f9ae81cbd019..f28146164431 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -1288,6 +1288,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] 27+ messages in thread

* [PATCH v4 16/19] drm/mediatek: add OUTPROC support for MT8196
  2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
                   ` (14 preceding siblings ...)
  2025-08-28  8:07 ` [PATCH v4 15/19] drm/mediatek: add BLENDER " Paul Chen
@ 2025-08-28  8:07 ` Paul Chen
  2025-08-28  8:07 ` [PATCH v4 17/19] drm/mediatek: add ovlsys_adaptor " Paul Chen
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Paul Chen @ 2025-08-28  8:07 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 | 235 ++++++++++++++++++++
 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, 276 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 8d18d5583903..7bc02a7f178c 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 2e45580f25ea..f3e8645c35b6 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -448,6 +448,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 290190d366af..7f9facb5574b 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 e0aeb87f0a5b..cecee77a8590 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -63,6 +63,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..99f0d60c3574
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_outproc.c
@@ -0,0 +1,235 @@
+// 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(0x0, priv->regs + DISP_REG_OVL_OUTPROC_INTSTA);
+	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 = 0;
+
+	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 |= 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 = 0;
+
+	tmp = readl(priv->regs + DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
+	tmp |= OVL_OUTPROC_BYPASS_SHADOW;
+	writel(tmp, priv->regs + DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
+
+	writel(OVL_OUTPROC_OVL_EN, 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 f28146164431..cf5f9b8fc335 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -1294,6 +1294,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] 27+ messages in thread

* [PATCH v4 17/19] drm/mediatek: add ovlsys_adaptor support for MT8196
  2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
                   ` (15 preceding siblings ...)
  2025-08-28  8:07 ` [PATCH v4 16/19] drm/mediatek: add OUTPROC " Paul Chen
@ 2025-08-28  8:07 ` Paul Chen
  2025-08-28  8:07 ` [PATCH v4 18/19] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver Paul Chen
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Paul Chen @ 2025-08-28  8:07 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    | 717 ++++++++++++++++++
 drivers/gpu/drm/mediatek/mtk_drm_drv.c        |  69 +-
 drivers/gpu/drm/mediatek/mtk_drm_drv.h        |  11 +-
 7 files changed, 835 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 7bc02a7f178c..57a341fac48e 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 f3e8645c35b6..d52786bd51c5 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -369,6 +369,31 @@ static const struct mtk_ddp_comp_funcs ddp_ovl = {
 	.is_afbc_supported = mtk_ovl_is_afbc_supported,
 };
 
+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,
@@ -438,6 +463,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",
@@ -470,6 +496,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 7f9facb5574b..cba996f99dd7 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 cecee77a8590..3457c33ded57 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..c390a93d4a30
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
@@ -0,0 +1,717 @@
+// 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;
+	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 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;
+}
+
+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;
+	}
+
+	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;
+
+	for (i = 0; i < priv->layer_nr; i++)
+		mtk_disp_blender_config(priv->ovl_adaptor_comp[priv->path[i * 2 + 1]], w, h,
+					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;
+}
+
+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]]);
+		mtk_disp_blender_start(priv->ovl_adaptor_comp[priv->path[i + 1]]);
+	}
+
+	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_stop(priv->ovl_adaptor_comp[priv->path[i]]);
+		mtk_disp_blender_stop(priv->ovl_adaptor_comp[priv->path[i + 1]]);
+	}
+
+	mtk_disp_outproc_stop(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;
+	int i;
+
+	for (i = 0; i < priv->path_size; i++) {
+		comp = priv->ovl_adaptor_comp[priv->path[i]];
+
+		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 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);
+	}
+}
+
+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;
+
+	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;
+
+	/*
+	 * Based on the hardware design, both 3 Display Pipe blender layer
+	 * is half of the path size.
+	 */
+	priv->layer_nr = priv->path_size / 2;
+
+	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 cf5f9b8fc335..7972a0506616 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -428,32 +428,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)
@@ -1069,6 +1078,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_ovlsys_platform_data 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;
@@ -1078,7 +1107,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;
 
@@ -1124,17 +1152,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) {
@@ -1169,7 +1191,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);
@@ -1297,6 +1319,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..d04a7ed5d39f 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -11,7 +11,10 @@
 
 #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_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,
@@ -69,6 +72,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 +87,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] 27+ messages in thread

* [PATCH v4 18/19] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver
  2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
                   ` (16 preceding siblings ...)
  2025-08-28  8:07 ` [PATCH v4 17/19] drm/mediatek: add ovlsys_adaptor " Paul Chen
@ 2025-08-28  8:07 ` Paul Chen
  2025-08-28  8:07 ` [PATCH v4 19/19] drm/mediatek: Add support for MT8196 multiple mmsys Paul Chen
  2025-08-29  6:32 ` [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Krzysztof Kozlowski
  19 siblings, 0 replies; 27+ messages in thread
From: Paul Chen @ 2025-08-28  8:07 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>

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  |  85 +++---
 drivers/gpu/drm/mediatek/mtk_drm_drv.h  |  13 +
 6 files changed, 421 insertions(+), 132 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c
index bc7527542fdc..3e3a06e5811e 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;
@@ -769,9 +863,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);
@@ -795,7 +911,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)
@@ -827,6 +944,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;
 }
 
@@ -987,49 +1120,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;
 		}
@@ -1039,7 +1231,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),
@@ -1048,19 +1242,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) {
@@ -1097,8 +1308,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;
@@ -1111,7 +1324,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;
@@ -1151,6 +1364,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];
@@ -1167,6 +1381,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;
 
@@ -1174,5 +1389,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 828f109b83e7..a0ade3d6534b 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_plane_disable(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 d52786bd51c5..2222adb42131 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -468,6 +468,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",
@@ -491,6 +492,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 },
@@ -498,6 +508,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 },
@@ -514,7 +525,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 },
@@ -565,18 +579,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]])
@@ -606,39 +626,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 cba996f99dd7..37e3f4e7b28c 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 7972a0506616..13fceb0389cb 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -373,7 +373,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;
@@ -401,26 +401,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;
 	}
@@ -493,7 +489,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) {
@@ -519,8 +518,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;
@@ -532,28 +533,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;
 			}
 		}
 	}
@@ -572,8 +568,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
@@ -591,8 +588,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 < MAX_MMSYS; i++)
+		if (private->all_drm_private[i])
+			put_device(private->all_drm_private[i]->mutex_dev);
 
 	return ret;
 }
@@ -656,6 +658,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;
 
@@ -670,8 +685,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)
@@ -1146,7 +1162,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)
@@ -1184,6 +1200,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",
@@ -1259,6 +1281,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 d04a7ed5d39f..bdd4dc5cefeb 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -23,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;
@@ -39,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;
 
@@ -64,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] 27+ messages in thread

* [PATCH v4 19/19] drm/mediatek: Add support for MT8196 multiple mmsys
  2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
                   ` (17 preceding siblings ...)
  2025-08-28  8:07 ` [PATCH v4 18/19] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver Paul Chen
@ 2025-08-28  8:07 ` Paul Chen
  2025-08-29  6:32 ` [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Krzysztof Kozlowski
  19 siblings, 0 replies; 27+ messages in thread
From: Paul Chen @ 2025-08-28  8:07 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 13fceb0389cb..1cd37052e47c 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -192,6 +192,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,
@@ -230,6 +234,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),
@@ -326,8 +374,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[] = {
@@ -357,8 +462,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] 27+ messages in thread

* Re: [PATCH v4 03/19] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
  2025-08-28  8:06 ` [PATCH v4 03/19] dt-bindings: display: mediatek: add EXDMA " Paul Chen
@ 2025-08-28 13:30   ` Rob Herring (Arm)
  2025-08-29  6:35   ` Krzysztof Kozlowski
  1 sibling, 0 replies; 27+ messages in thread
From: Rob Herring (Arm) @ 2025-08-28 13:30 UTC (permalink / raw)
  To: Paul Chen
  Cc: xiandong.wang, angelogioacchino.delregno,
	Project_Global_Chrome_Upstream_Group, dri-devel, p.zabel,
	devicetree, krzk+dt, sunny.shen, linux-arm-kernel, singo.chang,
	linux-kernel, chunkuang.hu, conor+dt, linux-mediatek, sirius.wang,
	jason-jh.lin, matthias.bgg, nancy.lin, fshao, treapking


On Thu, 28 Aug 2025 16:06:58 +0800, Paul 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: 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/20250828080855.3502514-4-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] 27+ messages in thread

* Re: [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196
  2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
                   ` (18 preceding siblings ...)
  2025-08-28  8:07 ` [PATCH v4 19/19] drm/mediatek: Add support for MT8196 multiple mmsys Paul Chen
@ 2025-08-29  6:32 ` Krzysztof Kozlowski
  19 siblings, 0 replies; 27+ messages in thread
From: Krzysztof Kozlowski @ 2025-08-29  6:32 UTC (permalink / raw)
  To: Paul 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, Aug 28, 2025 at 04:06:55PM +0800, Paul Chen wrote:
> From: Paul-pl Chen <paul-pl.chen@mediatek.com>
> 
> Changes in v4:
> - [PATCH v4 11/19]
>   Add New commit to refactor the naming of OVL Fornat.
> - [PATCH v4 12/19]
>   Refactor ovl_blend_mode fucntion
> - [PATCH v4 13/19]
>   Move mtk_ovl_get_blend_mode to this commit to align with driver.
> - [PATCH v4 14/19]
>   Remove the unused paramter cmdq
>   Remove the reapet of pitch setting
> - [PATCH v4 15/19]
>   Remove the unused paramter cmdq
>   Remove the useless parametrt of func():mtk_disp_blender_config
> - [PATCH v4 16/19] 
>   Simplified the driiver code to improve readability 
> - [PATCH v4 17/19]
>   Refine mtk_ovlsys_adaptor_layer_config's layer config checking. 
>   Refine mtk_ovlsys_adaptor_config's logic
>   Fix func()'s mtk_ovlsys_adaptor_stop settting
>   Refine mtk_ovlsys_adaptor_clk_enbale to repaet NULL checking
> - [PATCH v4 18/19]
>   Fix the system report's syntext error


Where are lore links to previous versions?

Why aren't you using b4?

Best regards,
Krzysztof



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

* Re: [PATCH v4 03/19] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
  2025-08-28  8:06 ` [PATCH v4 03/19] dt-bindings: display: mediatek: add EXDMA " Paul Chen
  2025-08-28 13:30   ` Rob Herring (Arm)
@ 2025-08-29  6:35   ` Krzysztof Kozlowski
  2025-08-29  6:48     ` Krzysztof Kozlowski
  1 sibling, 1 reply; 27+ messages in thread
From: Krzysztof Kozlowski @ 2025-08-29  6:35 UTC (permalink / raw)
  To: Paul 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, Aug 28, 2025 at 04:06:58PM +0800, Paul 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: Paul-pl Chen <paul-pl.chen@mediatek.com>
> ---
>  .../bindings/dma/mediatek,exdma.yaml          | 68 +++++++++++++++++++


Your changelog says NOTHING changed here and this fails tests, so does it
mean you received that warnings before but you keep sending same broken
code?

Last two weeks of contributions from mediatek are absolutely terrible.
Very poor code, basic in-house reviews not done, basic testing not done.

I talked about this at OSSE 25 with some friends and got reasons why
your setup is broken. Well, it's on you.

I was already raising this with Mediatek, but we are now back to square
one.

NAK, because this patch WAS NEVER tested.

Best regards,
Krzysztof



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

* Re: [PATCH v4 03/19] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
  2025-08-29  6:35   ` Krzysztof Kozlowski
@ 2025-08-29  6:48     ` Krzysztof Kozlowski
  2025-08-29 11:10       ` Paul-pl Chen (陳柏霖)
  0 siblings, 1 reply; 27+ messages in thread
From: Krzysztof Kozlowski @ 2025-08-29  6:48 UTC (permalink / raw)
  To: Paul 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 Fri, Aug 29, 2025 at 08:35:23AM +0200, Krzysztof Kozlowski wrote:
> On Thu, Aug 28, 2025 at 04:06:58PM +0800, Paul 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: Paul-pl Chen <paul-pl.chen@mediatek.com>
> > ---
> >  .../bindings/dma/mediatek,exdma.yaml          | 68 +++++++++++++++++++
> 
> 
> Your changelog says NOTHING changed here and this fails tests, so does it
> mean you received that warnings before but you keep sending same broken
> code?
> 
> Last two weeks of contributions from mediatek are absolutely terrible.
> Very poor code, basic in-house reviews not done, basic testing not done.
> 
> I talked about this at OSSE 25 with some friends and got reasons why
> your setup is broken. Well, it's on you.
> 
> I was already raising this with Mediatek, but we are now back to square
> one.
> 
> NAK, because this patch WAS NEVER tested.


And now I found you got EXACTLY the same error at v3, so you just never
tested and ignored OUR test reports.

This is unfortunately an example how you waste reviewers' time.

Best regards,
Krzysztof



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

* Re: [PATCH v4 05/19] dt-bindings: display: mediatek: add OUTPROC yaml for MT8196
  2025-08-28  8:07 ` [PATCH v4 05/19] dt-bindings: display: mediatek: add OUTPROC " Paul Chen
@ 2025-08-29  6:49   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 27+ messages in thread
From: Krzysztof Kozlowski @ 2025-08-29  6:49 UTC (permalink / raw)
  To: Paul 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, Aug 28, 2025 at 04:07:00PM +0800, Paul 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: Paul-pl Chen <paul-pl.chen@mediatek.com>

NAK,

Never tested.

Best regards,
Krzysztof



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

* Re: [PATCH v4 03/19] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
  2025-08-29  6:48     ` Krzysztof Kozlowski
@ 2025-08-29 11:10       ` Paul-pl Chen (陳柏霖)
  0 siblings, 0 replies; 27+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-08-29 11:10 UTC (permalink / raw)
  To: krzk@kernel.org
  Cc: Project_Global_Chrome_Upstream_Group, robh@kernel.org,
	Sunny Shen (沈姍姍),
	Sirius Wang (王皓昱),
	Nancy Lin (林欣螢), AngeloGioacchino Del Regno,
	Xiandong Wang (王先冬),
	linux-kernel@vger.kernel.org, conor+dt@kernel.org,
	dri-devel@lists.freedesktop.org,
	linux-mediatek@lists.infradead.org, chunkuang.hu@kernel.org,
	devicetree@vger.kernel.org, fshao@chromium.org,
	krzk+dt@kernel.org, Jason-JH Lin (林睿祥),
	Singo Chang (張興國), p.zabel@pengutronix.de,
	linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
	treapking@chromium.org

On Fri, 2025-08-29 at 08:48 +0200, Krzysztof Kozlowski wrote:
> 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> On Fri, Aug 29, 2025 at 08:35:23AM +0200, Krzysztof Kozlowski wrote:
> > On Thu, Aug 28, 2025 at 04:06:58PM +0800, Paul 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: Paul-pl Chen <paul-pl.chen@mediatek.com>
> > > ---
> > >  .../bindings/dma/mediatek,exdma.yaml          | 68
> > > +++++++++++++++++++
> > 
> > 
> > Your changelog says NOTHING changed here and this fails tests, so
> > does it
> > mean you received that warnings before but you keep sending same
> > broken
> > code?
> > 
> > Last two weeks of contributions from mediatek are absolutely
> > terrible.
> > Very poor code, basic in-house reviews not done, basic testing not
> > done.
> > 
> > I talked about this at OSSE 25 with some friends and got reasons
> > why
> > your setup is broken. Well, it's on you.
> > 
> > I was already raising this with Mediatek, but we are now back to
> > square
> > one.
> > 
> > NAK, because this patch WAS NEVER tested.
> 
> 
> And now I found you got EXACTLY the same error at v3, so you just
> never
> tested and ignored OUR test reports.
> 
> This is unfortunately an example how you waste reviewers' time.
> 
> Best regards,
> Krzysztof
> 

Hi Krzysztof,
 
I apologize for resubmitting an insufficiently tested patch and wasting
reviewers’ time. The repeated failure and the inadequate changelog are
entirely my responsibility—no excuses. I’m withdrawing this revision
and will only resend after I’ve reproduced and fixed the failures,
validated with comprehensive tests, completed internal review, and
included a clear “Changes since vN.”
 
Thank you for the direct feedback—I will do better.
 
Best regards, Paul


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

* Re: [PATCH v4 11/19] drm/mediatek: Rename OVL format naming
  2025-08-28  8:07 ` [PATCH v4 11/19] drm/mediatek: Rename OVL format naming Paul Chen
@ 2025-09-01  2:45   ` CK Hu (胡俊光)
  0 siblings, 0 replies; 27+ messages in thread
From: CK Hu (胡俊光) @ 2025-09-01  2:45 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-08-28 at 16:07 +0800, Paul Chen wrote:
> From: Paul-pl Chen <paul-pl.chen@mediatek.com>
> 
> Rename the OVL format naming

This patch looks good to me, but commit message is not good to me.
You should include three important things in one patch.

WHAT does this patch do: describe what does this patch do in title.
WHY this patch: describe why need this patch. I need a reason to apply this patch.
HOW to do: commit body would show how to do. HOW should be related to WHAT.

You does not show WHY need this patch.
Describe the reason why I need this patch.

Regards,
CK

> 
> Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 32 ++++++++++++-------------
>  1 file changed, 16 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> index e0236353d499..d4f096d37abc 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> @@ -101,7 +101,7 @@ static inline bool is_10bit_rgb(u32 fmt)
>  	return false;
>  }
>  
> -static const u32 mt8173_formats[] = {
> +static const u32 mt8173_ovl_formats[] = {
>  	DRM_FORMAT_XRGB8888,
>  	DRM_FORMAT_ARGB8888,
>  	DRM_FORMAT_BGRX8888,
> @@ -115,7 +115,7 @@ static const u32 mt8173_formats[] = {
>  	DRM_FORMAT_YUYV,
>  };
>  
> -static const u32 mt8195_formats[] = {
> +static const u32 mt8195_ovl_formats[] = {
>  	DRM_FORMAT_XRGB8888,
>  	DRM_FORMAT_ARGB8888,
>  	DRM_FORMAT_XRGB2101010,
> @@ -667,8 +667,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 = ARRAY_SIZE(mt8173_ovl_formats),
>  };
>  
>  static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = {
> @@ -676,8 +676,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 = ARRAY_SIZE(mt8173_ovl_formats),
>  };
>  
>  static const struct mtk_disp_ovl_data mt8183_ovl_driver_data = {
> @@ -685,8 +685,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 = ARRAY_SIZE(mt8173_ovl_formats),
>  };
>  
>  static const struct mtk_disp_ovl_data mt8183_ovl_2l_driver_data = {
> @@ -694,8 +694,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 = ARRAY_SIZE(mt8173_ovl_formats),
>  };
>  
>  static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = {
> @@ -707,8 +707,8 @@ static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = {
>  	.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),
> +	.formats = mt8173_ovl_formats,
> +	.num_formats = ARRAY_SIZE(mt8173_ovl_formats),
>  };
>  
>  static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = {
> @@ -720,8 +720,8 @@ static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = {
>  	.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),
> +	.formats = mt8173_ovl_formats,
> +	.num_formats = ARRAY_SIZE(mt8173_ovl_formats),
>  };
>  
>  static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = {
> @@ -734,8 +734,8 @@ static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = {
>  	.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),
> +	.formats = mt8195_ovl_formats,
> +	.num_formats = ARRAY_SIZE(mt8195_ovl_formats),
>  	.supports_clrfmt_ext = true,
>  };
>  


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

end of thread, other threads:[~2025-09-01  2:51 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-28  8:06 [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Paul Chen
2025-08-28  8:06 ` [PATCH v4 01/19] dt-bindings: arm: mediatek: mmsys: add compatible " Paul Chen
2025-08-28  8:06 ` [PATCH v4 02/19] dt-bindings: soc: mediatek: add mutex yaml " Paul Chen
2025-08-28  8:06 ` [PATCH v4 03/19] dt-bindings: display: mediatek: add EXDMA " Paul Chen
2025-08-28 13:30   ` Rob Herring (Arm)
2025-08-29  6:35   ` Krzysztof Kozlowski
2025-08-29  6:48     ` Krzysztof Kozlowski
2025-08-29 11:10       ` Paul-pl Chen (陳柏霖)
2025-08-28  8:06 ` [PATCH v4 04/19] dt-bindings: display: mediatek: add BLENDER " Paul Chen
2025-08-28  8:07 ` [PATCH v4 05/19] dt-bindings: display: mediatek: add OUTPROC " Paul Chen
2025-08-29  6:49   ` Krzysztof Kozlowski
2025-08-28  8:07 ` [PATCH v4 06/19] soc: mediatek: Add runtime PM and top clocks and async controls for MMSYS Paul Chen
2025-08-28  8:07 ` [PATCH v4 07/19] soc: mediatek: add mmsys support for MT8196 Paul Chen
2025-08-28  8:07 ` [PATCH v4 08/19] soc: mediatek: mutex: Reused the switch case for SOF ID Paul Chen
2025-08-28  8:07 ` [PATCH v4 09/19] soc: mediatek: mutex: refactor SOF settings for output components Paul Chen
2025-08-28  8:07 ` [PATCH v4 10/19] soc: mediatek: mutex: add mutex support for MT8196 Paul Chen
2025-08-28  8:07 ` [PATCH v4 11/19] drm/mediatek: Rename OVL format naming Paul Chen
2025-09-01  2:45   ` CK Hu (胡俊光)
2025-08-28  8:07 ` [PATCH v4 12/19] drm/mediatek: Export OVL formats definitions and format conversion API Paul Chen
2025-08-28  8:07 ` [PATCH v4 13/19] drm/mediatek: Export OVL Blend function Paul Chen
2025-08-28  8:07 ` [PATCH v4 14/19] drm/mediatek: add EXDMA support for MT8196 Paul Chen
2025-08-28  8:07 ` [PATCH v4 15/19] drm/mediatek: add BLENDER " Paul Chen
2025-08-28  8:07 ` [PATCH v4 16/19] drm/mediatek: add OUTPROC " Paul Chen
2025-08-28  8:07 ` [PATCH v4 17/19] drm/mediatek: add ovlsys_adaptor " Paul Chen
2025-08-28  8:07 ` [PATCH v4 18/19] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver Paul Chen
2025-08-28  8:07 ` [PATCH v4 19/19] drm/mediatek: Add support for MT8196 multiple mmsys Paul Chen
2025-08-29  6:32 ` [PATCH v4 00/19] Add MediaTek SoC DRM support for MT8196 Krzysztof Kozlowski

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