* [PATCH v2 00/15] Add MediaTek SoC DRM support for MT8196
@ 2025-03-21 9:33 paul-pl.chen
2025-03-21 9:33 ` [PATCH v2 01/15] dt-bindings: arm: mediatek: mmsys: add compatible " paul-pl.chen
` (14 more replies)
0 siblings, 15 replies; 42+ messages in thread
From: paul-pl.chen @ 2025-03-21 9:33 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
linux-arm-kernel, Project_Global_Chrome_Upstream_Group
From: Paul-pl Chen <paul-pl.chen@mediatek.com>
This patch series adds support for the MediaTek MT8196 SoC's display
subsystem in the DRM driver.
Changes in v2:
- add support for MT8196's new hardware components (EXDMA, BLENDER,
OUTPROC) following the previous MTK OVL software architecture.
- reuse mtk_ovl drivers in MediaTek DRM display to support the new
MT8196 SoC.
- implement support for multiple mmsys instances within a single
mediatek-drm driver, improving flexibility and scalability.
- refactor existing components (mutex, OVL) to accommodate the new
architecture and improve code reusability.
- update component matching, binding logic, and data structures to
support the new multi-mmsys design.
Nancy Lin (10):
soc: mediatek: add mmsys support for MT8196
soc: mediatek: mutex: refactor SOF settings for output components
soc: mediatek: mutex: add mutex support for MT8196
drm/mediatek: Refine OVL format convert API and export to public
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 (5):
dt-bindings: arm: mediatek: mmsys: add compatible for MT8196
dt-bindings: soc: mediatek: add mutex yaml for MT8196
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
.../bindings/arm/mediatek/mediatek,mmsys.yaml | 5 +
.../display/mediatek/mediatek,blender.yaml | 48 ++
.../display/mediatek/mediatek,outproc.yaml | 54 ++
.../bindings/dma/mediatek,exdma.yaml | 70 ++
.../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 | 133 +--
drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 6 +
drivers/gpu/drm/mediatek/mtk_disp_blender.c | 276 ++++++
drivers/gpu/drm/mediatek/mtk_disp_blender.h | 18 +
drivers/gpu/drm/mediatek/mtk_disp_drv.h | 67 ++
drivers/gpu/drm/mediatek/mtk_disp_exdma.c | 372 ++++++++
drivers/gpu/drm/mediatek/mtk_disp_outproc.c | 242 ++++++
drivers/gpu/drm/mediatek/mtk_disp_outproc.h | 22 +
drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 158 ++--
drivers/gpu/drm/mediatek/mtk_disp_ovl.h | 16 +
.../drm/mediatek/mtk_disp_ovlsys_adaptor.c | 797 ++++++++++++++++++
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 281 +++++-
drivers/gpu/drm/mediatek/mtk_drm_drv.h | 28 +-
drivers/soc/mediatek/mt8196-mmsys.h | 451 ++++++++++
drivers/soc/mediatek/mtk-mmsys.c | 203 ++++-
drivers/soc/mediatek/mtk-mmsys.h | 18 +
drivers/soc/mediatek/mtk-mutex.c | 257 +++++-
include/linux/soc/mediatek/mtk-mmsys.h | 60 ++
include/linux/soc/mediatek/mtk-mutex.h | 4 +
27 files changed, 3675 insertions(+), 265 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] 42+ messages in thread
* [PATCH v2 01/15] dt-bindings: arm: mediatek: mmsys: add compatible for MT8196
2025-03-21 9:33 [PATCH v2 00/15] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
@ 2025-03-21 9:33 ` paul-pl.chen
2025-03-24 9:33 ` Krzysztof Kozlowski
2025-03-21 9:33 ` [PATCH v2 02/15] dt-bindings: soc: mediatek: add mutex yaml " paul-pl.chen
` (13 subsequent siblings)
14 siblings, 1 reply; 42+ messages in thread
From: paul-pl.chen @ 2025-03-21 9:33 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>
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: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
.../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] 42+ messages in thread
* [PATCH v2 02/15] dt-bindings: soc: mediatek: add mutex yaml for MT8196
2025-03-21 9:33 [PATCH v2 00/15] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
2025-03-21 9:33 ` [PATCH v2 01/15] dt-bindings: arm: mediatek: mmsys: add compatible " paul-pl.chen
@ 2025-03-21 9:33 ` paul-pl.chen
2025-03-24 9:34 ` Krzysztof Kozlowski
2025-03-21 9:33 ` [PATCH v2 03/15] dt-bindings: display: mediatek: add EXDMA " paul-pl.chen
` (12 subsequent siblings)
14 siblings, 1 reply; 42+ messages in thread
From: paul-pl.chen @ 2025-03-21 9:33 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 compatible string to support mutex for MT8196.
Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
.../devicetree/bindings/soc/mediatek/mediatek,mutex.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml b/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml
index a10326a9683d..1be4e139a8b5 100644
--- a/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml
+++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml
@@ -36,6 +36,7 @@ properties:
- mediatek,mt8188-vpp-mutex
- mediatek,mt8192-disp-mutex
- mediatek,mt8195-disp-mutex
+ - mediatek,mt8196-disp-mutex
- mediatek,mt8195-vpp-mutex
- mediatek,mt8365-disp-mutex
@@ -87,6 +88,7 @@ allOf:
- mediatek,mt8186-mdp3-mutex
- mediatek,mt8192-disp-mutex
- mediatek,mt8195-disp-mutex
+ - mediatek,mt8196-disp-mutex
then:
required:
- clocks
--
2.45.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH v2 03/15] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-03-21 9:33 [PATCH v2 00/15] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
2025-03-21 9:33 ` [PATCH v2 01/15] dt-bindings: arm: mediatek: mmsys: add compatible " paul-pl.chen
2025-03-21 9:33 ` [PATCH v2 02/15] dt-bindings: soc: mediatek: add mutex yaml " paul-pl.chen
@ 2025-03-21 9:33 ` paul-pl.chen
2025-03-24 2:45 ` CK Hu (胡俊光)
2025-03-21 9:33 ` [PATCH v2 04/15] dt-bindings: display: mediatek: add BLENDER " paul-pl.chen
` (11 subsequent siblings)
14 siblings, 1 reply; 42+ messages in thread
From: paul-pl.chen @ 2025-03-21 9:33 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 | 70 +++++++++++++++++++
1 file changed, 70 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..de7f8283bb48
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/mediatek,exdma.yaml
@@ -0,0 +1,70 @@
+# 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>;
+
+ disp_ovl0_exdma2: dma-controller@32850000 {
+ compatible = "mediatek,mt8196-exdma";
+ reg = <0 0x32850000 0 0x1000>;
+ clocks = <&ovlsys_config_clk 13>;
+ power-domains = <&hfrpsys 12>;
+ mediatek,larb = <&smi_larb0>;
+ iommus = <&mm_smmu 144>;
+ #dma-cells = <1>;
+ };
+ };
--
2.45.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH v2 04/15] dt-bindings: display: mediatek: add BLENDER yaml for MT8196
2025-03-21 9:33 [PATCH v2 00/15] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
` (2 preceding siblings ...)
2025-03-21 9:33 ` [PATCH v2 03/15] dt-bindings: display: mediatek: add EXDMA " paul-pl.chen
@ 2025-03-21 9:33 ` paul-pl.chen
2025-03-24 9:36 ` Krzysztof Kozlowski
2025-03-21 9:33 ` [PATCH v2 05/15] dt-bindings: display: mediatek: add OUTPROC " paul-pl.chen
` (10 subsequent siblings)
14 siblings, 1 reply; 42+ messages in thread
From: paul-pl.chen @ 2025-03-21 9:33 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,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>
---
.../display/mediatek/mediatek,blender.yaml | 48 +++++++++++++++++++
1 file changed, 48 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..23e274a49228
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,blender.yaml
@@ -0,0 +1,48 @@
+# 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>;
+
+ disp_ovl0_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] 42+ messages in thread
* [PATCH v2 05/15] dt-bindings: display: mediatek: add OUTPROC yaml for MT8196
2025-03-21 9:33 [PATCH v2 00/15] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
` (3 preceding siblings ...)
2025-03-21 9:33 ` [PATCH v2 04/15] dt-bindings: display: mediatek: add BLENDER " paul-pl.chen
@ 2025-03-21 9:33 ` paul-pl.chen
2025-03-24 16:02 ` Rob Herring
2025-03-21 9:33 ` [PATCH v2 06/15] soc: mediatek: add mmsys support " paul-pl.chen
` (9 subsequent siblings)
14 siblings, 1 reply; 42+ messages in thread
From: paul-pl.chen @ 2025-03-21 9:33 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..f42e9abc1436
--- /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>;
+
+ disp_ovl0_outproc0: outproc@32970000 {
+ compatible = "mediatek,mt8196-outproc";
+ reg = <0 0x32970000 0 0x1000>;
+ clocks = <&ovlsys_config_clk 49>;
+ interrupts = <GIC_SPI 450 IRQ_TYPE_LEVEL_HIGH 0>;
+ };
+ };
--
2.45.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH v2 06/15] soc: mediatek: add mmsys support for MT8196
2025-03-21 9:33 [PATCH v2 00/15] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
` (4 preceding siblings ...)
2025-03-21 9:33 ` [PATCH v2 05/15] dt-bindings: display: mediatek: add OUTPROC " paul-pl.chen
@ 2025-03-21 9:33 ` paul-pl.chen
2025-03-24 17:09 ` AngeloGioacchino Del Regno
2025-03-21 9:33 ` [PATCH v2 07/15] soc: mediatek: mutex: refactor SOF settings for output components paul-pl.chen
` (8 subsequent siblings)
14 siblings, 1 reply; 42+ messages in thread
From: paul-pl.chen @ 2025-03-21 9:33 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>
1. Defining driver data and adding compatible string
for different subsystems
(DISPSYS0, DISPSYS1, OVLSYS0, OVLSYS1, VDISP_AO)
2. Adding functions to control top clocks and ddp clocks.
3. Updating the probe function to initialize clocks and
enable runtime PM if its node has the power-domains property.
4. Adding functions to configure ddp components and
set default configurations.
5. Adding the routing table for each mmsys in MT8196.
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 | 451 +++++++++++++++++++++++++
drivers/soc/mediatek/mtk-mmsys.c | 203 ++++++++++-
drivers/soc/mediatek/mtk-mmsys.h | 18 +
include/linux/soc/mediatek/mtk-mmsys.h | 60 ++++
4 files changed, 731 insertions(+), 1 deletion(-)
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..ff841ae9939a
--- /dev/null
+++ b/drivers/soc/mediatek/mt8196-mmsys.h
@@ -0,0 +1,451 @@
+/* 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[] = {
+ {
+ DDP_COMPONENT_OVL0_EXDMA2, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL0_EXDMA2, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL0_EXDMA3, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL0_EXDMA4, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL0_EXDMA5, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL0_EXDMA6, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL0_EXDMA7, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL0_EXDMA8, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL0_EXDMA9, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL0_BLENDER4, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL0_BLENDER8, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL0_OUTPROC0, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL0_OUTPROC1, DDP_COMPONENT_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[] = {
+ {
+ DDP_COMPONENT_OVL1_EXDMA2, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL1_EXDMA2, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL1_EXDMA3, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL1_EXDMA4, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL1_EXDMA5, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL1_EXDMA6, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL1_EXDMA7, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL1_EXDMA8, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL1_EXDMA9, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL1_BLENDER4, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL1_BLENDER8, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL1_OUTPROC0, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_OVL1_OUTPROC1, DDP_COMPONENT_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[] = {
+ {
+ DDP_COMPONENT_DLI_ASYNC0, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_DLI_ASYNC0, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_DLI_ASYNC0, DDP_COMPONENT_DLO_ASYNC1,
+ MT8196_PANEL_COMP_OUT_CB1_MOUT_EN, MT8196_DISP_TO_DLO_RELAY1,
+ MT8196_DISP_TO_DLO_RELAY1
+ }, {
+ DDP_COMPONENT_DLI_ASYNC1, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_DLI_ASYNC1, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_DLI_ASYNC1, DDP_COMPONENT_DLO_ASYNC2,
+ MT8196_PANEL_COMP_OUT_CB2_MOUT_EN, MT8196_DISP_TO_DLO_RELAY2,
+ MT8196_DISP_TO_DLO_RELAY2
+ }, {
+ DDP_COMPONENT_DLI_ASYNC8, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_DLI_ASYNC8, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_DLI_ASYNC8, DDP_COMPONENT_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[] = {
+ {
+ DDP_COMPONENT_DLI_ASYNC21, DDP_COMPONENT_DVO0,
+ MT8196_SPLITTER_IN_CB1_MOUT_EN, MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB9,
+ MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB9
+ }, {
+ DDP_COMPONENT_DLI_ASYNC21, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_DLI_ASYNC21, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_DLI_ASYNC21, DDP_COMPONENT_DVO0,
+ MT8196_MERGE_OUT_CB0_MOUT_EN, MT8196_DISP_COMP_OUT_CB_TO_DVO0,
+ MT8196_DISP_COMP_OUT_CB_TO_DVO0
+ }, {
+ DDP_COMPONENT_DLI_ASYNC22, DDP_COMPONENT_DP_INTF0,
+ MT8196_SPLITTER_IN_CB2_MOUT_EN, MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB10,
+ MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB10
+ }, {
+ DDP_COMPONENT_DLI_ASYNC22, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_DLI_ASYNC22, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_DLI_ASYNC22, DDP_COMPONENT_DP_INTF0,
+ MT8196_MERGE_OUT_CB1_MOUT_EN, MT8196_DISP_COMP_OUT_CB_TO_DP_INTF0,
+ MT8196_DISP_COMP_OUT_CB_TO_DP_INTF0
+ }, {
+ DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_DVO0,
+ MT8196_SPLITTER_IN_CB3_MOUT_EN, MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB11,
+ MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB11
+ }, {
+ DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_DVO0,
+ MT8196_MERGE_OUT_CB2_MOUT_EN, MT8196_DISP_COMP_OUT_CB_TO_DVO0,
+ MT8196_DISP_COMP_OUT_CB_TO_DVO0
+ }, {
+ DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_DP_INTF1,
+ MT8196_SPLITTER_IN_CB3_MOUT_EN, MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB11,
+ MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB11
+ }, {
+ DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_DP_INTF1,
+ MT8196_MERGE_OUT_CB2_MOUT_EN, MT8196_DISP_COMP_OUT_CB_TO_DP_INTF1,
+ MT8196_DISP_COMP_OUT_CB_TO_DP_INTF1
+ }, {
+ DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_DSI0,
+ MT8196_SPLITTER_IN_CB3_MOUT_EN, MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB11,
+ MT8196_DISP_DLI_RELAY_TO_SPLITTER_OUT_CB11
+ }, {
+ DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_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
+ }, {
+ DDP_COMPONENT_DLI_ASYNC23, DDP_COMPONENT_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 bb4639ca0b8c..1d3ca4f9f237 100644
--- a/drivers/soc/mediatek/mtk-mmsys.c
+++ b/drivers/soc/mediatek/mtk-mmsys.c
@@ -4,12 +4,14 @@
* Author: James Liao <jamesjj.liao@mediatek.com>
*/
+#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>
@@ -21,6 +23,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
@@ -144,6 +147,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,
@@ -158,6 +209,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 +234,99 @@ 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;
+
+ 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;
+
+ mtk_mmsys_update_bits(mmsys, async[i].offset, async[i].mask,
+ height << 16 | width, 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 +537,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 +579,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 +633,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 +646,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[] = {
@@ -476,6 +672,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/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..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,
@@ -84,6 +136,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] 42+ messages in thread
* [PATCH v2 07/15] soc: mediatek: mutex: refactor SOF settings for output components
2025-03-21 9:33 [PATCH v2 00/15] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
` (5 preceding siblings ...)
2025-03-21 9:33 ` [PATCH v2 06/15] soc: mediatek: add mmsys support " paul-pl.chen
@ 2025-03-21 9:33 ` paul-pl.chen
2025-03-24 17:12 ` AngeloGioacchino Del Regno
2025-03-21 9:33 ` [PATCH v2 08/15] soc: mediatek: mutex: add mutex support for MT8196 paul-pl.chen
` (7 subsequent siblings)
14 siblings, 1 reply; 42+ messages in thread
From: paul-pl.chen @ 2025-03-21 9:33 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>
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().
- Added mtk_mutex_add_comp_sof() and mtk_mutex_remove_comp_sof()
for SOF settings.
- Reused the switch case for SOF IDs.
- Separated MOD and SOF logic.
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 | 121 +++++++++++++++----------
include/linux/soc/mediatek/mtk-mutex.h | 4 +
2 files changed, 79 insertions(+), 46 deletions(-)
diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
index aaa965d4b050..c026ac0e6969 100644
--- a/drivers/soc/mediatek/mtk-mutex.c
+++ b/drivers/soc/mediatek/mtk-mutex.c
@@ -853,43 +853,84 @@ void mtk_mutex_unprepare(struct mtk_mutex *mutex)
}
EXPORT_SYMBOL_GPL(mtk_mutex_unprepare);
-void mtk_mutex_add_comp(struct mtk_mutex *mutex,
- enum mtk_ddp_comp_id id)
+static int mtk_mutex_get_output_comp_sof(enum mtk_ddp_comp_id id)
{
- struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
- mutex[mutex->id]);
- unsigned int reg;
- unsigned int sof_id;
- unsigned int offset;
-
- WARN_ON(&mtx->mutex[mutex->id] != mutex);
-
switch (id) {
case DDP_COMPONENT_DSI0:
- sof_id = MUTEX_SOF_DSI0;
- break;
+ return MUTEX_SOF_DSI0;
case DDP_COMPONENT_DSI1:
- sof_id = MUTEX_SOF_DSI0;
- break;
+ return MUTEX_SOF_DSI1;
case DDP_COMPONENT_DSI2:
- sof_id = MUTEX_SOF_DSI2;
- break;
+ return MUTEX_SOF_DSI2;
case DDP_COMPONENT_DSI3:
- sof_id = MUTEX_SOF_DSI3;
- break;
+ return MUTEX_SOF_DSI3;
case DDP_COMPONENT_DPI0:
- sof_id = MUTEX_SOF_DPI0;
- break;
+ return MUTEX_SOF_DPI0;
case DDP_COMPONENT_DPI1:
- sof_id = MUTEX_SOF_DPI1;
- break;
+ return MUTEX_SOF_DPI1;
case DDP_COMPONENT_DP_INTF0:
- sof_id = MUTEX_SOF_DP_INTF0;
- break;
+ return MUTEX_SOF_DP_INTF0;
case DDP_COMPONENT_DP_INTF1:
- sof_id = MUTEX_SOF_DP_INTF1;
- break;
+ return MUTEX_SOF_DP_INTF1;
default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+void mtk_mutex_add_comp_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 offset;
+ bool is_output_comp = !!mtk_mutex_get_output_comp_sof(id);
+
+ WARN_ON(&mtx->mutex[mutex->id] != mutex);
+
+ if (!is_output_comp) {
if (mtx->data->mutex_mod[id] < 32) {
offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
mutex->id);
@@ -902,12 +943,10 @@ void mtk_mutex_add_comp(struct mtk_mutex *mutex,
reg |= 1 << (mtx->data->mutex_mod[id] - 32);
writel_relaxed(reg, mtx->regs + offset);
}
- return;
}
- writel_relaxed(mtx->data->mutex_sof[sof_id],
- mtx->regs +
- DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, mutex->id));
+ if (is_output_comp)
+ mtk_mutex_add_comp_sof(mutex, id);
}
EXPORT_SYMBOL_GPL(mtk_mutex_add_comp);
@@ -918,24 +957,11 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
mutex[mutex->id]);
unsigned int reg;
unsigned int offset;
+ bool is_output_comp = !!mtk_mutex_get_output_comp_sof(id);
WARN_ON(&mtx->mutex[mutex->id] != mutex);
- switch (id) {
- case DDP_COMPONENT_DSI0:
- case DDP_COMPONENT_DSI1:
- case DDP_COMPONENT_DSI2:
- case DDP_COMPONENT_DSI3:
- case DDP_COMPONENT_DPI0:
- case DDP_COMPONENT_DPI1:
- case DDP_COMPONENT_DP_INTF0:
- case DDP_COMPONENT_DP_INTF1:
- writel_relaxed(MUTEX_SOF_SINGLE_MODE,
- mtx->regs +
- DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg,
- mutex->id));
- break;
- default:
+ if (!is_output_comp) {
if (mtx->data->mutex_mod[id] < 32) {
offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
mutex->id);
@@ -948,8 +974,11 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
reg &= ~(1 << (mtx->data->mutex_mod[id] - 32));
writel_relaxed(reg, mtx->regs + offset);
}
- break;
}
+
+ if (is_output_comp)
+ mtk_mutex_remove_comp_sof(mutex, id);
+
}
EXPORT_SYMBOL_GPL(mtk_mutex_remove_comp);
diff --git a/include/linux/soc/mediatek/mtk-mutex.h b/include/linux/soc/mediatek/mtk-mutex.h
index 635218e3ac68..515e2d8bfc90 100644
--- a/include/linux/soc/mediatek/mtk-mutex.h
+++ b/include/linux/soc/mediatek/mtk-mutex.h
@@ -69,6 +69,10 @@ enum mtk_mutex_sof_index {
struct mtk_mutex *mtk_mutex_get(struct device *dev);
int mtk_mutex_prepare(struct mtk_mutex *mutex);
+void mtk_mutex_add_comp_sof(struct mtk_mutex *mutex,
+ enum mtk_ddp_comp_id id);
+void mtk_mutex_remove_comp_sof(struct mtk_mutex *mutex,
+ enum mtk_ddp_comp_id id);
void mtk_mutex_add_comp(struct mtk_mutex *mutex,
enum mtk_ddp_comp_id id);
void mtk_mutex_enable(struct mtk_mutex *mutex);
--
2.45.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH v2 08/15] soc: mediatek: mutex: add mutex support for MT8196
2025-03-21 9:33 [PATCH v2 00/15] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
` (6 preceding siblings ...)
2025-03-21 9:33 ` [PATCH v2 07/15] soc: mediatek: mutex: refactor SOF settings for output components paul-pl.chen
@ 2025-03-21 9:33 ` paul-pl.chen
2025-03-21 9:33 ` [PATCH v2 09/15] drm/mediatek: Refine OVL format convert API and export to public paul-pl.chen
` (6 subsequent siblings)
14 siblings, 0 replies; 42+ messages in thread
From: paul-pl.chen @ 2025-03-21 9:33 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
linux-arm-kernel, Project_Global_Chrome_Upstream_Group
From: Nancy Lin <nancy.lin@mediatek.com>
Add mutex support for the main and external displays in MT8196:
- Introduce a new DVO0 output component for the new mutex
settings of MT8196.
- Add a need_sof_mof flag to configure both SOF and MOD settings
for the output component.
Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
drivers/soc/mediatek/mtk-mutex.c | 140 ++++++++++++++++++++++++++++++-
1 file changed, 138 insertions(+), 2 deletions(-)
diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
index c026ac0e6969..f51d1cb5ad1e 100644
--- a/drivers/soc/mediatek/mtk-mutex.c
+++ b/drivers/soc/mediatek/mtk-mutex.c
@@ -19,6 +19,7 @@
#define MT2701_MUTEX0_SOF0 0x30
#define MT8183_MUTEX0_MOD0 0x30
#define MT8183_MUTEX0_SOF0 0x2c
+#define MT8196_MUTEX0_MOD0 0x34
#define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n))
#define DISP_REG_MUTEX(n) (0x24 + 0x20 * (n))
@@ -237,6 +238,47 @@
#define MT8195_MUTEX_MOD_MDP_WROT2 32
#define MT8195_MUTEX_MOD_MDP_WROT3 33
+/* OVLSYS */
+#define MT8196_MUTEX_MOD0_OVL_EXDMA2 2
+#define MT8196_MUTEX_MOD0_OVL_EXDMA3 3
+#define MT8196_MUTEX_MOD0_OVL_EXDMA4 4
+#define MT8196_MUTEX_MOD0_OVL_EXDMA5 5
+#define MT8196_MUTEX_MOD0_OVL_EXDMA6 6
+#define MT8196_MUTEX_MOD0_OVL_EXDMA7 7
+#define MT8196_MUTEX_MOD0_OVL_EXDMA8 8
+#define MT8196_MUTEX_MOD0_OVL_EXDMA9 9
+#define MT8196_MUTEX_MOD0_OVL_BLENDER1 11
+#define MT8196_MUTEX_MOD0_OVL_BLENDER2 12
+#define MT8196_MUTEX_MOD0_OVL_BLENDER3 13
+#define MT8196_MUTEX_MOD0_OVL_BLENDER4 14
+#define MT8196_MUTEX_MOD0_OVL_BLENDER5 15
+#define MT8196_MUTEX_MOD0_OVL_BLENDER6 16
+#define MT8196_MUTEX_MOD0_OVL_BLENDER7 17
+#define MT8196_MUTEX_MOD0_OVL_BLENDER8 18
+#define MT8196_MUTEX_MOD0_OVL_BLENDER9 19
+#define MT8196_MUTEX_MOD0_OVL_OUTPROC0 20
+#define MT8196_MUTEX_MOD0_OVL_OUTPROC1 21
+#define MT8196_MUTEX_MOD0_OVL_OUTPROC2 22
+#define MT8196_MUTEX_MOD1_OVL_DLO_ASYNC5 (32 + 16)
+#define MT8196_MUTEX_MOD1_OVL_DLO_ASYNC6 (32 + 17)
+
+/* DISP0 */
+#define MT8196_MUTEX_MOD0_DISP_DLI_ASYNC0 16
+#define MT8196_MUTEX_MOD0_DISP_DLI_ASYNC1 17
+#define MT8196_MUTEX_MOD0_DISP_DLI_ASYNC8 24
+#define MT8196_MUTEX_MOD1_DISP_DLO_ASYNC1 (32 + 1)
+#define MT8196_MUTEX_MOD1_DISP_DLO_ASYNC2 (32 + 2)
+#define MT8196_MUTEX_MOD1_DISP_DLO_ASYNC3 (32 + 3)
+
+/* DISP1 */
+#define MT8196_MUTEX_MOD0_DISP1_DLI_ASYNC21 1
+#define MT8196_MUTEX_MOD0_DISP1_DLI_ASYNC22 2
+#define MT8196_MUTEX_MOD0_DISP1_DLI_ASYNC23 3
+#define MT8196_MUTEX_MOD0_DISP1_DP_INTF0 13
+#define MT8196_MUTEX_MOD0_DISP1_DP_INTF1 14
+#define MT8196_MUTEX_MOD0_DISP1_DSI0 23
+#define MT8196_MUTEX_MOD0_DISP1_DVO 29
+
#define MT8365_MUTEX_MOD_DISP_OVL0 7
#define MT8365_MUTEX_MOD_DISP_OVL0_2L 8
#define MT8365_MUTEX_MOD_DISP_RDMA0 9
@@ -297,6 +339,12 @@
#define MT8195_MUTEX_SOF_DP_INTF1 4
#define MT8195_MUTEX_SOF_DPI0 6 /* for HDMI_TX */
#define MT8195_MUTEX_SOF_DPI1 5 /* for digital video out */
+#define MT8196_MUTEX_SOF_DSI0 1
+#define MT8196_MUTEX_SOF_DSI1 2
+#define MT8196_MUTEX_SOF_DSI2 4
+#define MT8196_MUTEX_SOF_DPI0 5
+#define MT8196_MUTEX_SOF_DPI1 6
+#define MT8196_MUTEX_SOF_DVO0 7
#define MT8183_MUTEX_EOF_DSI0 (MT8183_MUTEX_SOF_DSI0 << 6)
#define MT8183_MUTEX_EOF_DPI0 (MT8183_MUTEX_SOF_DPI0 << 6)
@@ -310,6 +358,12 @@
#define MT8195_MUTEX_EOF_DP_INTF1 (MT8195_MUTEX_SOF_DP_INTF1 << 7)
#define MT8195_MUTEX_EOF_DPI0 (MT8195_MUTEX_SOF_DPI0 << 7)
#define MT8195_MUTEX_EOF_DPI1 (MT8195_MUTEX_SOF_DPI1 << 7)
+#define MT8196_MUTEX_EOF_DSI0 (MT8196_MUTEX_SOF_DSI0 << 7)
+#define MT8196_MUTEX_EOF_DSI1 (MT8196_MUTEX_SOF_DSI1 << 7)
+#define MT8196_MUTEX_EOF_DSI2 (MT8196_MUTEX_SOF_DSI2 << 7)
+#define MT8196_MUTEX_EOF_DPI0 (MT8196_MUTEX_SOF_DPI0 << 7)
+#define MT8196_MUTEX_EOF_DPI1 (MT8196_MUTEX_SOF_DPI1 << 7)
+#define MT8196_MUTEX_EOF_DVO0 (MT8196_MUTEX_SOF_DVO0 << 7)
struct mtk_mutex {
u8 id;
@@ -326,6 +380,7 @@ enum mtk_mutex_sof_id {
MUTEX_SOF_DSI3,
MUTEX_SOF_DP_INTF0,
MUTEX_SOF_DP_INTF1,
+ MUTEX_SOF_DVO0,
DDP_MUTEX_SOF_MAX,
};
@@ -336,6 +391,7 @@ struct mtk_mutex_data {
const u16 mutex_mod_reg;
const u16 mutex_sof_reg;
const bool no_clk;
+ const bool need_sof_mod;
};
struct mtk_mutex_ctx {
@@ -625,6 +681,64 @@ static const u8 mt8195_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
[MUTEX_MOD_IDX_MDP_WROT3] = MT8195_MUTEX_MOD_MDP_WROT3,
};
+static const u8 mt8196_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+ [DDP_COMPONENT_OVL0_EXDMA2] = MT8196_MUTEX_MOD0_OVL_EXDMA2,
+ [DDP_COMPONENT_OVL0_EXDMA3] = MT8196_MUTEX_MOD0_OVL_EXDMA3,
+ [DDP_COMPONENT_OVL0_EXDMA4] = MT8196_MUTEX_MOD0_OVL_EXDMA4,
+ [DDP_COMPONENT_OVL0_EXDMA5] = MT8196_MUTEX_MOD0_OVL_EXDMA5,
+ [DDP_COMPONENT_OVL0_EXDMA6] = MT8196_MUTEX_MOD0_OVL_EXDMA6,
+ [DDP_COMPONENT_OVL0_EXDMA7] = MT8196_MUTEX_MOD0_OVL_EXDMA7,
+ [DDP_COMPONENT_OVL0_EXDMA8] = MT8196_MUTEX_MOD0_OVL_EXDMA8,
+ [DDP_COMPONENT_OVL0_EXDMA9] = MT8196_MUTEX_MOD0_OVL_EXDMA9,
+ [DDP_COMPONENT_OVL0_BLENDER1] = MT8196_MUTEX_MOD0_OVL_BLENDER1,
+ [DDP_COMPONENT_OVL0_BLENDER2] = MT8196_MUTEX_MOD0_OVL_BLENDER2,
+ [DDP_COMPONENT_OVL0_BLENDER3] = MT8196_MUTEX_MOD0_OVL_BLENDER3,
+ [DDP_COMPONENT_OVL0_BLENDER4] = MT8196_MUTEX_MOD0_OVL_BLENDER4,
+ [DDP_COMPONENT_OVL0_BLENDER5] = MT8196_MUTEX_MOD0_OVL_BLENDER5,
+ [DDP_COMPONENT_OVL0_BLENDER6] = MT8196_MUTEX_MOD0_OVL_BLENDER6,
+ [DDP_COMPONENT_OVL0_BLENDER7] = MT8196_MUTEX_MOD0_OVL_BLENDER7,
+ [DDP_COMPONENT_OVL0_BLENDER8] = MT8196_MUTEX_MOD0_OVL_BLENDER8,
+ [DDP_COMPONENT_OVL0_BLENDER9] = MT8196_MUTEX_MOD0_OVL_BLENDER9,
+ [DDP_COMPONENT_OVL0_OUTPROC0] = MT8196_MUTEX_MOD0_OVL_OUTPROC0,
+ [DDP_COMPONENT_OVL0_OUTPROC1] = MT8196_MUTEX_MOD0_OVL_OUTPROC1,
+ [DDP_COMPONENT_OVL0_DLO_ASYNC5] = MT8196_MUTEX_MOD1_OVL_DLO_ASYNC5,
+ [DDP_COMPONENT_OVL0_DLO_ASYNC6] = MT8196_MUTEX_MOD1_OVL_DLO_ASYNC6,
+ [DDP_COMPONENT_OVL1_EXDMA2] = MT8196_MUTEX_MOD0_OVL_EXDMA2,
+ [DDP_COMPONENT_OVL1_EXDMA3] = MT8196_MUTEX_MOD0_OVL_EXDMA3,
+ [DDP_COMPONENT_OVL1_EXDMA4] = MT8196_MUTEX_MOD0_OVL_EXDMA4,
+ [DDP_COMPONENT_OVL1_EXDMA5] = MT8196_MUTEX_MOD0_OVL_EXDMA5,
+ [DDP_COMPONENT_OVL1_EXDMA6] = MT8196_MUTEX_MOD0_OVL_EXDMA6,
+ [DDP_COMPONENT_OVL1_EXDMA7] = MT8196_MUTEX_MOD0_OVL_EXDMA7,
+ [DDP_COMPONENT_OVL1_EXDMA8] = MT8196_MUTEX_MOD0_OVL_EXDMA8,
+ [DDP_COMPONENT_OVL1_EXDMA9] = MT8196_MUTEX_MOD0_OVL_EXDMA9,
+ [DDP_COMPONENT_OVL1_BLENDER1] = MT8196_MUTEX_MOD0_OVL_BLENDER1,
+ [DDP_COMPONENT_OVL1_BLENDER2] = MT8196_MUTEX_MOD0_OVL_BLENDER2,
+ [DDP_COMPONENT_OVL1_BLENDER3] = MT8196_MUTEX_MOD0_OVL_BLENDER3,
+ [DDP_COMPONENT_OVL1_BLENDER4] = MT8196_MUTEX_MOD0_OVL_BLENDER4,
+ [DDP_COMPONENT_OVL1_BLENDER5] = MT8196_MUTEX_MOD0_OVL_BLENDER5,
+ [DDP_COMPONENT_OVL1_BLENDER6] = MT8196_MUTEX_MOD0_OVL_BLENDER6,
+ [DDP_COMPONENT_OVL1_BLENDER7] = MT8196_MUTEX_MOD0_OVL_BLENDER7,
+ [DDP_COMPONENT_OVL1_BLENDER8] = MT8196_MUTEX_MOD0_OVL_BLENDER8,
+ [DDP_COMPONENT_OVL1_BLENDER9] = MT8196_MUTEX_MOD0_OVL_BLENDER9,
+ [DDP_COMPONENT_OVL1_OUTPROC0] = MT8196_MUTEX_MOD0_OVL_OUTPROC0,
+ [DDP_COMPONENT_OVL1_OUTPROC1] = MT8196_MUTEX_MOD0_OVL_OUTPROC1,
+ [DDP_COMPONENT_OVL1_DLO_ASYNC5] = MT8196_MUTEX_MOD1_OVL_DLO_ASYNC5,
+ [DDP_COMPONENT_OVL1_DLO_ASYNC6] = MT8196_MUTEX_MOD1_OVL_DLO_ASYNC6,
+ [DDP_COMPONENT_DLI_ASYNC0] = MT8196_MUTEX_MOD0_DISP_DLI_ASYNC0,
+ [DDP_COMPONENT_DLI_ASYNC1] = MT8196_MUTEX_MOD0_DISP_DLI_ASYNC1,
+ [DDP_COMPONENT_DLI_ASYNC8] = MT8196_MUTEX_MOD0_DISP_DLI_ASYNC8,
+ [DDP_COMPONENT_DLO_ASYNC1] = MT8196_MUTEX_MOD1_DISP_DLO_ASYNC1,
+ [DDP_COMPONENT_DLO_ASYNC2] = MT8196_MUTEX_MOD1_DISP_DLO_ASYNC2,
+ [DDP_COMPONENT_DLO_ASYNC3] = MT8196_MUTEX_MOD1_DISP_DLO_ASYNC3,
+ [DDP_COMPONENT_DLI_ASYNC21] = MT8196_MUTEX_MOD0_DISP1_DLI_ASYNC21,
+ [DDP_COMPONENT_DLI_ASYNC22] = MT8196_MUTEX_MOD0_DISP1_DLI_ASYNC22,
+ [DDP_COMPONENT_DLI_ASYNC23] = MT8196_MUTEX_MOD0_DISP1_DLI_ASYNC23,
+ [DDP_COMPONENT_DVO0] = MT8196_MUTEX_MOD0_DISP1_DVO,
+ [DDP_COMPONENT_DP_INTF0] = MT8196_MUTEX_MOD0_DISP1_DP_INTF0,
+ [DDP_COMPONENT_DP_INTF1] = MT8196_MUTEX_MOD0_DISP1_DP_INTF1,
+ [DDP_COMPONENT_DSI0] = MT8196_MUTEX_MOD0_DISP1_DSI0,
+};
+
static const u8 mt8365_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL0] = MT8365_MUTEX_MOD_DISP_AAL,
[DDP_COMPONENT_CCORR] = MT8365_MUTEX_MOD_DISP_CCORR,
@@ -710,6 +824,17 @@ static const u16 mt8195_mutex_sof[DDP_MUTEX_SOF_MAX] = {
MT8195_MUTEX_SOF_DP_INTF1 | MT8195_MUTEX_EOF_DP_INTF1,
};
+static const u16 mt8196_mutex_sof[DDP_MUTEX_SOF_MAX] = {
+ [MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
+ [MUTEX_SOF_DSI0] = MT8196_MUTEX_SOF_DSI0 | MT8196_MUTEX_EOF_DSI0,
+ [MUTEX_SOF_DSI1] = MT8196_MUTEX_SOF_DSI1 | MT8196_MUTEX_EOF_DSI1,
+ [MUTEX_SOF_DP_INTF0] =
+ MT8196_MUTEX_SOF_DPI0 | MT8196_MUTEX_EOF_DPI0,
+ [MUTEX_SOF_DP_INTF1] =
+ MT8196_MUTEX_SOF_DPI1 | MT8196_MUTEX_EOF_DPI1,
+ [MUTEX_SOF_DVO0] = MT8196_MUTEX_SOF_DVO0 | MT8196_MUTEX_EOF_DVO0,
+};
+
static const struct mtk_mutex_data mt2701_mutex_driver_data = {
.mutex_mod = mt2701_mutex_mod,
.mutex_sof = mt2712_mutex_sof,
@@ -803,6 +928,14 @@ static const struct mtk_mutex_data mt8195_vpp_mutex_driver_data = {
.mutex_table_mod = mt8195_mutex_table_mod,
};
+static const struct mtk_mutex_data mt8196_mutex_driver_data = {
+ .mutex_mod = mt8196_mutex_mod,
+ .mutex_sof = mt8196_mutex_sof,
+ .mutex_mod_reg = MT8196_MUTEX0_MOD0,
+ .mutex_sof_reg = MT2701_MUTEX0_SOF0,
+ .need_sof_mod = true,
+};
+
static const struct mtk_mutex_data mt8365_mutex_driver_data = {
.mutex_mod = mt8365_mutex_mod,
.mutex_sof = mt8183_mutex_sof,
@@ -872,6 +1005,8 @@ static int mtk_mutex_get_output_comp_sof(enum mtk_ddp_comp_id id)
return MUTEX_SOF_DP_INTF0;
case DDP_COMPONENT_DP_INTF1:
return MUTEX_SOF_DP_INTF1;
+ case DDP_COMPONENT_DVO0:
+ return MUTEX_SOF_DVO0;
default:
break;
}
@@ -930,7 +1065,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);
@@ -961,7 +1096,7 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
WARN_ON(&mtx->mutex[mutex->id] != mutex);
- if (!is_output_comp) {
+ if (!is_output_comp || mtx->data->need_sof_mod) {
if (mtx->data->mutex_mod[id] < 32) {
offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
mutex->id);
@@ -1169,6 +1304,7 @@ static const struct of_device_id mutex_driver_dt_match[] = {
{ .compatible = "mediatek,mt8192-disp-mutex", .data = &mt8192_mutex_driver_data },
{ .compatible = "mediatek,mt8195-disp-mutex", .data = &mt8195_mutex_driver_data },
{ .compatible = "mediatek,mt8195-vpp-mutex", .data = &mt8195_vpp_mutex_driver_data },
+ { .compatible = "mediatek,mt8196-disp-mutex", .data = &mt8196_mutex_driver_data },
{ .compatible = "mediatek,mt8365-disp-mutex", .data = &mt8365_mutex_driver_data },
{ /* sentinel */ },
};
--
2.45.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH v2 09/15] drm/mediatek: Refine OVL format convert API and export to public
2025-03-21 9:33 [PATCH v2 00/15] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
` (7 preceding siblings ...)
2025-03-21 9:33 ` [PATCH v2 08/15] soc: mediatek: mutex: add mutex support for MT8196 paul-pl.chen
@ 2025-03-21 9:33 ` paul-pl.chen
2025-03-25 2:57 ` CK Hu (胡俊光)
2025-03-21 9:33 ` [PATCH v2 10/15] drm/mediatek: add EXDMA support for MT8196 paul-pl.chen
` (5 subsequent siblings)
14 siblings, 1 reply; 42+ messages in thread
From: paul-pl.chen @ 2025-03-21 9:33 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>
Refine OVL format convert API and export to public.
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 | 158 ++++++++++++++++--------
drivers/gpu/drm/mediatek/mtk_disp_ovl.h | 16 +++
2 files changed, 122 insertions(+), 52 deletions(-)
create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovl.h
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index d0581c4e3c99..e2b125a717c6 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -18,6 +18,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 +63,15 @@
/* OVL_CON_RGB_SWAP works only if OVL_CON_CLRFMT_MAN is enabled */
#define OVL_CON_RGB_SWAP BIT(25)
-#define OVL_CON_CLRFMT_RGB (1 << 12)
-#define OVL_CON_CLRFMT_ARGB8888 (2 << 12)
-#define OVL_CON_CLRFMT_RGBA8888 (3 << 12)
-#define OVL_CON_CLRFMT_ABGR8888 (OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP)
-#define OVL_CON_CLRFMT_BGRA8888 (OVL_CON_CLRFMT_RGBA8888 | OVL_CON_BYTE_SWAP)
-#define OVL_CON_CLRFMT_UYVY (4 << 12)
-#define OVL_CON_CLRFMT_YUYV (5 << 12)
-#define OVL_CON_MTX_YUV_TO_RGB (6 << 16)
-#define OVL_CON_CLRFMT_PARGB8888 ((3 << 12) | OVL_CON_CLRFMT_MAN)
-#define OVL_CON_CLRFMT_PABGR8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_RGB_SWAP)
-#define OVL_CON_CLRFMT_PBGRA8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_BYTE_SWAP)
-#define OVL_CON_CLRFMT_PRGBA8888 (OVL_CON_CLRFMT_PABGR8888 | OVL_CON_BYTE_SWAP)
-#define OVL_CON_CLRFMT_RGB565(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \
- 0 : OVL_CON_CLRFMT_RGB)
-#define OVL_CON_CLRFMT_RGB888(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \
- OVL_CON_CLRFMT_RGB : 0)
+#define OVL_CON_CLRFMT_RGB565(shift) (0 << (shift))
+#define OVL_CON_CLRFMT_RGB888(shift) (1 << (shift))
+#define OVL_CON_CLRFMT_ARGB8888(shift) (2 << (shift))
+#define OVL_CON_CLRFMT_RGBA8888(shift) (3 << (shift))
+#define OVL_CON_CLRFMT_UYVY(shift) (4 << (shift))
+#define OVL_CON_CLRFMT_YUYV(shift) (5 << (shift))
+#define OVL_CON_MTX_YUV_TO_RGB (6 << 16)
+#define OVL_CON_CLRFMT_PARGB8888(shift, man) ((3 << (shift)) | (man))
+
#define OVL_CON_AEN BIT(8)
#define OVL_CON_ALPHA 0xff
#define OVL_CON_VIRT_FLIP BIT(9)
@@ -85,7 +79,7 @@
#define OVL_COLOR_ALPHA GENMASK(31, 24)
-static inline bool is_10bit_rgb(u32 fmt)
+bool mtk_ovl_is_10bit_rgb(unsigned int fmt)
{
switch (fmt) {
case DRM_FORMAT_XRGB2101010:
@@ -295,7 +289,7 @@ static void mtk_ovl_set_bit_depth(struct device *dev, int idx, u32 format,
if (!ovl->data->supports_clrfmt_ext)
return;
- if (is_10bit_rgb(format))
+ if (mtk_ovl_is_10bit_rgb(format))
bit_depth = OVL_CON_CLRFMT_10_BIT;
mtk_ddp_write_mask(cmdq_pkt, OVL_CON_CLRFMT_BIT_DEPTH(bit_depth, idx),
@@ -394,10 +388,26 @@ 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)
+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;
+}
+
+unsigned int mtk_ovl_get_blend_mode(struct mtk_plane_state *state, unsigned int blend_modes)
{
- unsigned int fmt = state->pending.format;
unsigned int blend_mode = DRM_MODE_BLEND_COVERAGE;
/*
@@ -412,52 +422,102 @@ static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl,
* will get an error return from drm_plane_create_blend_mode_property() and
* state->base.pixel_blend_mode should not be used.
*/
- if (ovl->data->blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
+ if (blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
blend_mode = state->base.pixel_blend_mode;
+ return blend_mode;
+}
+
+unsigned int mtk_ovl_fmt_convert(unsigned int fmt, unsigned int blend_mode,
+ bool fmt_rgb565_is_0, bool color_convert,
+ u8 clrfmt_shift, u32 clrfmt_man, u32 byte_swap, u32 rgb_swap)
+{
+ unsigned int con = 0;
+ bool need_byte_swap = false, need_rgb_swap = false;
+
switch (fmt) {
default:
case DRM_FORMAT_RGB565:
- return OVL_CON_CLRFMT_RGB565(ovl);
+ con = fmt_rgb565_is_0 ?
+ OVL_CON_CLRFMT_RGB565(clrfmt_shift) : OVL_CON_CLRFMT_RGB888(clrfmt_shift);
+ break;
case DRM_FORMAT_BGR565:
- return OVL_CON_CLRFMT_RGB565(ovl) | OVL_CON_BYTE_SWAP;
+ con = fmt_rgb565_is_0 ?
+ OVL_CON_CLRFMT_RGB565(clrfmt_shift) : OVL_CON_CLRFMT_RGB888(clrfmt_shift);
+ need_byte_swap = true; /* RGB565 -> BGR565 */
+ break;
case DRM_FORMAT_RGB888:
- return OVL_CON_CLRFMT_RGB888(ovl);
+ con = fmt_rgb565_is_0 ?
+ OVL_CON_CLRFMT_RGB888(clrfmt_shift) : OVL_CON_CLRFMT_RGB565(clrfmt_shift);
+ break;
case DRM_FORMAT_BGR888:
- return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP;
+ con = fmt_rgb565_is_0 ?
+ OVL_CON_CLRFMT_RGB888(clrfmt_shift) : OVL_CON_CLRFMT_RGB565(clrfmt_shift);
+ need_byte_swap = true; /* RGB888 -> BGR888 */
+ break;
case DRM_FORMAT_RGBX8888:
case DRM_FORMAT_RGBA8888:
case DRM_FORMAT_RGBX1010102:
case DRM_FORMAT_RGBA1010102:
- return blend_mode == DRM_MODE_BLEND_COVERAGE ?
- OVL_CON_CLRFMT_RGBA8888 :
- OVL_CON_CLRFMT_PRGBA8888;
+ if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
+ con = OVL_CON_CLRFMT_RGBA8888(clrfmt_shift);
+ } else {
+ con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
+ need_byte_swap = true; /* PARGB8888 -> PBGRA8888 */
+ need_rgb_swap = true; /* PBGRA8888 -> PRGBA8888 */
+ }
+ break;
case DRM_FORMAT_BGRX8888:
case DRM_FORMAT_BGRA8888:
case DRM_FORMAT_BGRX1010102:
case DRM_FORMAT_BGRA1010102:
- return blend_mode == DRM_MODE_BLEND_COVERAGE ?
- OVL_CON_CLRFMT_BGRA8888 :
- OVL_CON_CLRFMT_PBGRA8888;
+ if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
+ con = OVL_CON_CLRFMT_RGBA8888(clrfmt_shift);
+ need_byte_swap = true; /* RGB8888 -> BGR8888 */
+ } else {
+ con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
+ need_byte_swap = true; /* PARGB8888 -> PBGRA8888 */
+ }
+ break;
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_ARGB2101010:
- return blend_mode == DRM_MODE_BLEND_COVERAGE ?
- OVL_CON_CLRFMT_ARGB8888 :
- OVL_CON_CLRFMT_PARGB8888;
+ if (blend_mode == DRM_MODE_BLEND_COVERAGE)
+ con = OVL_CON_CLRFMT_ARGB8888(clrfmt_shift);
+ else
+ con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
+ break;
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_ABGR8888:
case DRM_FORMAT_XBGR2101010:
case DRM_FORMAT_ABGR2101010:
- return blend_mode == DRM_MODE_BLEND_COVERAGE ?
- OVL_CON_CLRFMT_ABGR8888 :
- OVL_CON_CLRFMT_PABGR8888;
+ if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
+ con = OVL_CON_CLRFMT_ARGB8888(clrfmt_shift);
+ need_rgb_swap = true; /* ARGB8888 -> ABGR8888 */
+ } else {
+ con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
+ need_rgb_swap = true; /* PARGB8888 -> PABGR8888 */
+ }
+ break;
case DRM_FORMAT_UYVY:
- return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB;
+ con = OVL_CON_CLRFMT_UYVY(clrfmt_shift);
+ break;
case DRM_FORMAT_YUYV:
- return OVL_CON_CLRFMT_YUYV | OVL_CON_MTX_YUV_TO_RGB;
+ con = OVL_CON_CLRFMT_YUYV(clrfmt_shift);
+ break;
}
+
+ if (color_convert)
+ con |= OVL_CON_MTX_YUV_TO_RGB;
+
+ if (need_byte_swap)
+ con |= byte_swap;
+
+ if (need_rgb_swap)
+ con |= rgb_swap;
+
+ return con;
}
static void mtk_ovl_afbc_layer_config(struct mtk_disp_ovl *ovl,
@@ -495,7 +555,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;
@@ -504,7 +564,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
return;
}
- con = mtk_ovl_fmt_convert(ovl, state);
+ con = mtk_ovl_fmt_convert(fmt, blend_mode, ovl->data->fmt_rgb565_is_0, true,
+ 12, OVL_CON_CLRFMT_MAN, OVL_CON_BYTE_SWAP, OVL_CON_RGB_SWAP);
if (state->base.fb) {
con |= state->base.alpha & OVL_CON_ALPHA;
@@ -512,17 +573,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;
}
/*
@@ -548,6 +600,8 @@ 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));
+
+ ignore_pixel_alpha = mtk_ovl_is_ignore_pixel_alpha(state, blend_mode) ? OVL_CONST_BLEND : 0;
mtk_ddp_write_relaxed(cmdq_pkt, pitch_lsb | ignore_pixel_alpha,
&ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH(idx));
mtk_ddp_write_relaxed(cmdq_pkt, src_size, &ovl->cmdq_reg, ovl->regs,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.h b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
new file mode 100644
index 000000000000..9bd5dc62d626
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ */
+
+#ifndef __MTK_DISP_OVL_H__
+#define __MTK_DISP_OVL_H__
+
+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);
+
+#endif
--
2.45.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH v2 10/15] drm/mediatek: add EXDMA support for MT8196
2025-03-21 9:33 [PATCH v2 00/15] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
` (8 preceding siblings ...)
2025-03-21 9:33 ` [PATCH v2 09/15] drm/mediatek: Refine OVL format convert API and export to public paul-pl.chen
@ 2025-03-21 9:33 ` paul-pl.chen
2025-03-24 3:00 ` CK Hu (胡俊光)
2025-03-21 9:33 ` [PATCH v2 11/15] drm/mediatek: add BLENDER " paul-pl.chen
` (4 subsequent siblings)
14 siblings, 1 reply; 42+ messages in thread
From: paul-pl.chen @ 2025-03-21 9:33 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
linux-arm-kernel, Project_Global_Chrome_Upstream_Group
From: Nancy Lin <nancy.lin@mediatek.com>
EXDMA is a DMA engine for reading data from DRAM with
various DRAM footprints and data formats. For input
sources in certain color formats and color domains,
EXDMA also includes a color transfer function to
process pixels into a consistent color domain.
New Add: 6320385 Fix RG16 and refine RG24
Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
---
drivers/gpu/drm/mediatek/Makefile | 1 +
drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 1 +
drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 1 +
drivers/gpu/drm/mediatek/mtk_disp_drv.h | 9 +
drivers/gpu/drm/mediatek/mtk_disp_exdma.c | 372 ++++++++++++++++++++++
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 +
drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 +
7 files changed, 386 insertions(+)
create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_exdma.c
diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
index 32a2ed6c0cfe..db92f4fb353d 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -5,6 +5,7 @@ mediatek-drm-y := mtk_crtc.o \
mtk_disp_aal.o \
mtk_disp_ccorr.o \
mtk_disp_color.o \
+ mtk_disp_exdma.o \
mtk_disp_gamma.o \
mtk_disp_merge.o \
mtk_disp_ovl.o \
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index edc6417639e6..3e0739d8e6f1 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -445,6 +445,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
[MTK_DP_INTF] = "dp-intf",
[MTK_DPI] = "dpi",
[MTK_DSI] = "dsi",
+ [MTK_OVL_EXDMA] = "exdma",
};
struct mtk_ddp_comp_match {
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
index 39720b27f4e9..86dc0ee3924c 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
@@ -43,6 +43,7 @@ enum mtk_ddp_comp_type {
MTK_DPI,
MTK_DP_INTF,
MTK_DSI,
+ MTK_OVL_EXDMA,
MTK_DDP_COMP_TYPE_MAX,
};
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index 04217a36939c..4e3d2510bef5 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -39,6 +39,15 @@ void mtk_color_config(struct device *dev, unsigned int w,
unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
void mtk_color_start(struct device *dev);
+int mtk_disp_exdma_clk_enable(struct device *dev);
+void mtk_disp_exdma_clk_disable(struct device *dev);
+void mtk_disp_exdma_start(struct device *dev, struct cmdq_pkt *cmdq_pkt);
+void mtk_disp_exdma_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt);
+void mtk_disp_exdma_layer_config(struct device *dev, struct mtk_plane_state *state,
+ struct cmdq_pkt *cmdq_pkt);
+const u32 *mtk_disp_exdma_get_formats(struct device *dev);
+size_t mtk_disp_exdma_get_num_formats(struct device *dev);
+
void mtk_dither_set_common(void __iomem *regs, struct cmdq_client_reg *cmdq_reg,
unsigned int bpc, unsigned int cfg,
unsigned int dither_en, struct cmdq_pkt *cmdq_pkt);
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_exdma.c b/drivers/gpu/drm/mediatek/mtk_disp_exdma.c
new file mode 100644
index 000000000000..d4f7021f98d7
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_exdma.c
@@ -0,0 +1,372 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ */
+
+#include <drm/drm_fourcc.h>
+#include <drm/drm_blend.h>
+#include <drm/drm_framebuffer.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/soc/mediatek/mtk-cmdq.h>
+
+#include "mtk_disp_drv.h"
+#include "mtk_drm_drv.h"
+#include "mtk_disp_ovl.h"
+
+#define DISP_REG_OVL_EXDMA_EN_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_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 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)
+
+static const u32 formats[] = {
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_BGRX8888,
+ DRM_FORMAT_BGRA8888,
+ DRM_FORMAT_ABGR8888,
+ DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_RGBX8888,
+ DRM_FORMAT_RGBA8888,
+ DRM_FORMAT_RGB888,
+ DRM_FORMAT_BGR888,
+ DRM_FORMAT_RGB565,
+ DRM_FORMAT_BGR565,
+ DRM_FORMAT_UYVY,
+ DRM_FORMAT_YUYV,
+ DRM_FORMAT_XRGB2101010,
+ DRM_FORMAT_ARGB2101010,
+ DRM_FORMAT_RGBX1010102,
+ DRM_FORMAT_RGBA1010102,
+ DRM_FORMAT_XBGR2101010,
+ DRM_FORMAT_ABGR2101010,
+ DRM_FORMAT_BGRX1010102,
+ DRM_FORMAT_BGRA1010102,
+};
+
+struct mtk_disp_exdma {
+ void __iomem *regs;
+ struct clk *clk;
+ struct cmdq_client_reg cmdq_reg;
+ struct device *larb;
+};
+
+static unsigned int mtk_disp_exdma_color_convert(unsigned int color_encoding)
+{
+ switch (color_encoding) {
+ default:
+ case DRM_COLOR_YCBCR_BT709:
+ return OVL_EXDMA_CON_INT_MTX_BT709_TO_RGB;
+ case DRM_COLOR_YCBCR_BT601:
+ return OVL_EXDMA_CON_INT_MTX_BT601_TO_RGB;
+ }
+}
+
+void mtk_disp_exdma_start(struct device *dev, struct cmdq_pkt *cmdq_pkt)
+{
+ struct mtk_disp_exdma *priv = dev_get_drvdata(dev);
+ unsigned int value = 0, mask = 0;
+
+ value = OVL_EXDMA_RDMA_BURST_CON1_BURST16_EN | OVL_EXDMA_RDMA_BURST_CON1_DDR_ACK_EN;
+ mask = OVL_EXDMA_RDMA_BURST_CON1_BURST16_EN | OVL_EXDMA_RDMA_BURST_CON1_DDR_EN |
+ OVL_EXDMA_RDMA_BURST_CON1_DDR_ACK_EN;
+ mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_EXDMA_RDMA_BURST_CON1, mask);
+ /*
+ * The dummy register is used in the configuration of the EXDMA engine to
+ * write commands to DRAM, ensuring that data transfers occur normally.
+ */
+ value = OVL_EXDMA_EXT_DDR_EN_OPT | OVL_EXDMA_FORCE_EXT_DDR_EN;
+ mask = OVL_EXDMA_EXT_DDR_EN_OPT | OVL_EXDMA_FORCE_EXT_DDR_EN;
+ mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_EXDMA_DUMMY_REG, mask);
+
+ value = OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN |
+ OVL_EXDMA_DATAPATH_CON_HDR_GCLAST_EN |
+ OVL_EXDMA_DATAPATH_CON_GCLAST_EN;
+ mask = OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN |
+ OVL_EXDMA_DATAPATH_CON_HDR_GCLAST_EN |
+ OVL_EXDMA_DATAPATH_CON_GCLAST_EN;
+ mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_EXDMA_DATAPATH_CON, mask);
+
+ mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_MOUT_BGCLR_OUT, &priv->cmdq_reg,
+ priv->regs, DISP_REG_OVL_EXDMA_MOUT,
+ OVL_EXDMA_MOUT_BGCLR_OUT | OVL_EXDMA_MOUT_OUT_DATA);
+
+ mtk_ddp_write(cmdq_pkt, ~0, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_EXDMA_GDRDY_PRD);
+
+ mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_RDMA0_EN, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_EXDMA_RDMA0_CTRL, OVL_EXDMA_RDMA0_EN);
+ 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);
+
+ mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_EN, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_EXDMA_EN, OVL_EXDMA_EN);
+}
+
+void mtk_disp_exdma_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt)
+{
+ struct mtk_disp_exdma *priv = dev_get_drvdata(dev);
+
+ mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_EXDMA_EN, OVL_EXDMA_EN);
+ mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_EXDMA_RDMA0_CTRL, OVL_EXDMA_RDMA0_EN);
+ mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_EXDMA_DATAPATH_CON, OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN);
+ mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_EXDMA_L0_EN, OVL_EXDMA_L0_EN);
+ mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_RST, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_EXDMA_RST, OVL_EXDMA_RST);
+ mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_EXDMA_RST, OVL_EXDMA_RST);
+}
+
+void mtk_disp_exdma_layer_config(struct device *dev, struct mtk_plane_state *state,
+ struct cmdq_pkt *cmdq_pkt)
+{
+ struct mtk_disp_exdma *priv = dev_get_drvdata(dev);
+ struct mtk_plane_pending_state *pending = &state->pending;
+ const struct drm_format_info *fmt_info = drm_format_info(pending->format);
+ unsigned int align_width = 0;
+ bool csc_enable = (fmt_info) ? fmt_info->is_yuv : false;
+ unsigned int blend_mode = mtk_ovl_get_blend_mode(state,
+ BIT(DRM_MODE_BLEND_PREMULTI) |
+ BIT(DRM_MODE_BLEND_COVERAGE) |
+ BIT(DRM_MODE_BLEND_PIXEL_NONE));
+ unsigned int val = 0;
+ unsigned int clrfmt_mask = OVL_EXDMA_CON_RGB_SWAP |
+ OVL_EXDMA_CON_BYTE_SWAP |
+ OVL_EXDMA_CON_CLRFMT_MAN |
+ OVL_EXDMA_CON_FLD_CLRFMT |
+ OVL_EXDMA_CON_FLD_CLRFMT_NB;
+
+ if (!pending->enable) {
+ mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_EXDMA_RDMA0_CTRL, OVL_EXDMA_RDMA0_EN);
+ mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_EXDMA_L0_EN, OVL_EXDMA_L0_EN);
+ return;
+ }
+
+ /* OVLSYS is in 1T2P domain, width needs to be 2 pixels align */
+ align_width = ALIGN_DOWN(pending->width, 2);
+
+ mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
+ priv->regs, DISP_REG_OVL_EXDMA_ROI_SIZE);
+
+ mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
+ priv->regs, DISP_REG_OVL_EXDMA_SRC_SIZE);
+ mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
+ priv->regs, DISP_REG_OVL_EXDMA_SRC_SIZE);
+
+ mtk_ddp_write_mask(cmdq_pkt, pending->pitch, &priv->cmdq_reg,
+ priv->regs, DISP_REG_OVL_EXDMA_PITCH, OVL_EXDMA_L0_SRC_PITCH_MASK);
+ mtk_ddp_write_mask(cmdq_pkt, pending->pitch >> 16, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_EXDMA_PITCH_MSB, 0xf);
+
+ 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, clrfmt_mask);
+
+ val = OVL_EXDMA_HG_FOVL_EXDMA_CK_ON | OVL_EXDMA_HF_FOVL_EXDMA_CK_ON |
+ OVL_EXDMA_OP_8BIT_MODE;
+ mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_EXDMA_EN_CON, val);
+
+ val = OVL_EXDMA_RDMA0_L0_VCSEL | OVL_EXDMA_RDMA0_HDR_L0_VCSEL;
+ mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_EXDMA_L0_GUSER_EXT, val);
+
+ val = pending->pitch;
+ if (mtk_ovl_is_ignore_pixel_alpha(state, blend_mode))
+ val |= OVL_EXDMA_L0_CONST_BLD;
+ mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_EXDMA_PITCH,
+ OVL_EXDMA_L0_CONST_BLD | OVL_EXDMA_L0_SRC_PITCH);
+}
+
+const u32 *mtk_disp_exdma_get_formats(struct device *dev)
+{
+ return formats;
+}
+
+size_t mtk_disp_exdma_get_num_formats(struct device *dev)
+{
+ return ARRAY_SIZE(formats);
+}
+
+int mtk_disp_exdma_clk_enable(struct device *dev)
+{
+ struct mtk_disp_exdma *exdma = dev_get_drvdata(dev);
+
+ return clk_prepare_enable(exdma->clk);
+}
+
+void mtk_disp_exdma_clk_disable(struct device *dev)
+{
+ struct mtk_disp_exdma *exdma = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(exdma->clk);
+}
+
+static int mtk_disp_exdma_bind(struct device *dev, struct device *master,
+ void *data)
+{
+ return 0;
+}
+
+static void mtk_disp_exdma_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+}
+
+static const struct component_ops mtk_disp_exdma_component_ops = {
+ .bind = mtk_disp_exdma_bind,
+ .unbind = mtk_disp_exdma_unbind,
+};
+
+static int mtk_disp_exdma_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct platform_device *larb_pdev = NULL;
+ struct device_node *larb_node = NULL;
+ struct resource *res;
+ struct mtk_disp_exdma *priv;
+ int ret = 0;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->regs)) {
+ dev_err(dev, "failed to ioremap exdma\n");
+ return PTR_ERR(priv->regs);
+ }
+
+ priv->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(priv->clk)) {
+ dev_err(dev, "failed to get exdma clk\n");
+ return PTR_ERR(priv->clk);
+ }
+
+ larb_node = of_parse_phandle(dev->of_node, "mediatek,larb", 0);
+ if (larb_node) {
+ larb_pdev = of_find_device_by_node(larb_node);
+ if (larb_pdev)
+ priv->larb = &larb_pdev->dev;
+ of_node_put(larb_node);
+ }
+
+ if (!priv->larb) {
+ dev_dbg(dev, "not find larb dev");
+ return -EPROBE_DEFER;
+ }
+ device_link_add(dev, priv->larb, DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
+
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+ ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
+ if (ret)
+ dev_dbg(dev, "No mediatek,gce-client-reg\n");
+#endif
+ platform_set_drvdata(pdev, priv);
+
+ pm_runtime_enable(dev);
+
+ ret = component_add(dev, &mtk_disp_exdma_component_ops);
+ if (ret != 0) {
+ pm_runtime_disable(dev);
+ dev_err(dev, "Failed to add component: %d\n", ret);
+ }
+ return ret;
+}
+
+static void mtk_disp_exdma_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &mtk_disp_exdma_component_ops);
+ pm_runtime_disable(&pdev->dev);
+}
+
+static const struct of_device_id mtk_disp_exdma_driver_dt_match[] = {
+ { .compatible = "mediatek,mt8196-exdma", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mtk_disp_exdma_driver_dt_match);
+
+struct platform_driver mtk_disp_exdma_driver = {
+ .probe = mtk_disp_exdma_probe,
+ .remove = mtk_disp_exdma_remove,
+ .driver = {
+ .name = "mediatek-disp-exdma",
+ .owner = THIS_MODULE,
+ .of_match_table = mtk_disp_exdma_driver_dt_match,
+ },
+};
+
+MODULE_AUTHOR("Nancy Lin <nancy.lin@mediatek.com>");
+MODULE_DESCRIPTION("MediaTek Exdma Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 74158b9d6503..bb7306a942ff 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -1276,6 +1276,7 @@ static struct platform_driver * const mtk_drm_drivers[] = {
&mtk_disp_aal_driver,
&mtk_disp_ccorr_driver,
&mtk_disp_color_driver,
+ &mtk_disp_exdma_driver,
&mtk_disp_gamma_driver,
&mtk_disp_merge_driver,
&mtk_disp_ovl_adaptor_driver,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index 675cdc90a440..898a75898775 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -72,6 +72,7 @@ struct mtk_drm_private {
extern struct platform_driver mtk_disp_aal_driver;
extern struct platform_driver mtk_disp_ccorr_driver;
extern struct platform_driver mtk_disp_color_driver;
+extern struct platform_driver mtk_disp_exdma_driver;
extern struct platform_driver mtk_disp_gamma_driver;
extern struct platform_driver mtk_disp_merge_driver;
extern struct platform_driver mtk_disp_ovl_adaptor_driver;
--
2.45.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH v2 11/15] drm/mediatek: add BLENDER support for MT8196
2025-03-21 9:33 [PATCH v2 00/15] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
` (9 preceding siblings ...)
2025-03-21 9:33 ` [PATCH v2 10/15] drm/mediatek: add EXDMA support for MT8196 paul-pl.chen
@ 2025-03-21 9:33 ` paul-pl.chen
2025-03-24 8:33 ` CK Hu (胡俊光)
2025-03-21 9:33 ` [PATCH v2 12/15] drm/mediatek: add OUTPROC " paul-pl.chen
` (3 subsequent siblings)
14 siblings, 1 reply; 42+ messages in thread
From: paul-pl.chen @ 2025-03-21 9:33 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 | 276 ++++++++++++++++++++
drivers/gpu/drm/mediatek/mtk_disp_blender.h | 18 ++
drivers/gpu/drm/mediatek/mtk_disp_drv.h | 12 +
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 +
drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 +
8 files changed, 311 insertions(+)
create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_blender.c
create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_blender.h
diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
index db92f4fb353d..a7b9ebe27f68 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -3,6 +3,7 @@
mediatek-drm-y := mtk_crtc.o \
mtk_ddp_comp.o \
mtk_disp_aal.o \
+ mtk_disp_blender.o \
mtk_disp_ccorr.o \
mtk_disp_color.o \
mtk_disp_exdma.o \
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index 3e0739d8e6f1..e65c6df987f2 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -445,6 +445,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
[MTK_DP_INTF] = "dp-intf",
[MTK_DPI] = "dpi",
[MTK_DSI] = "dsi",
+ [MTK_OVL_BLENDER] = "blender",
[MTK_OVL_EXDMA] = "exdma",
};
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
index 86dc0ee3924c..075ba5683f93 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
@@ -43,6 +43,7 @@ enum mtk_ddp_comp_type {
MTK_DPI,
MTK_DP_INTF,
MTK_DSI,
+ MTK_OVL_BLENDER,
MTK_OVL_EXDMA,
MTK_DDP_COMP_TYPE_MAX,
};
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_blender.c b/drivers/gpu/drm/mediatek/mtk_disp_blender.c
new file mode 100644
index 000000000000..32c9e3d463a4
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_blender.c
@@ -0,0 +1,276 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ */
+
+#include <drm/drm_fourcc.h>
+#include <drm/drm_blend.h>
+#include <drm/drm_framebuffer.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/soc/mediatek/mtk-cmdq.h>
+#include <linux/soc/mediatek/mtk-mmsys.h>
+
+#include "mtk_crtc.h"
+#include "mtk_ddp_comp.h"
+#include "mtk_disp_drv.h"
+#include "mtk_drm_drv.h"
+#include "mtk_disp_blender.h"
+#include "mtk_disp_ovl.h"
+
+#define OVL_BLD_ALPHA 0xff
+#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_PITCH 0x208
+#define OVL_BLD_L0_CONST BIT(24)
+#define DISP_REG_OVL_BLD_L0_CLR 0x20c
+#define OVL_BLD_CON_CLRFMT_MAN BIT(4)
+#define OVL_BLD_L0_SRC_PITCH GENMASK(15, 0)
+#define DISP_REG_OVL_BLD_PITCH 0x2f4
+
+struct mtk_disp_blender {
+ void __iomem *regs;
+ struct clk *clk;
+ struct cmdq_client_reg cmdq_reg;
+};
+
+void mtk_disp_blender_layer_config(struct device *dev, struct mtk_plane_state *state,
+ struct cmdq_pkt *cmdq_pkt)
+{
+ struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+ struct mtk_plane_pending_state *pending = &state->pending;
+ unsigned int align_width = ALIGN_DOWN(pending->width, 2);
+ unsigned int alpha;
+ unsigned int clrfmt;
+ unsigned int blend_mode = mtk_ovl_get_blend_mode(state,
+ BIT(DRM_MODE_BLEND_PREMULTI) |
+ BIT(DRM_MODE_BLEND_COVERAGE) |
+ BIT(DRM_MODE_BLEND_PIXEL_NONE));
+ unsigned int ignore_pixel_alpha = 0;
+
+ if (!pending->enable) {
+ mtk_ddp_write(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_L_EN);
+ return;
+ }
+
+ mtk_ddp_write(cmdq_pkt, pending->y << 16 | pending->x, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_BLD_OFFSET);
+
+ mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_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);
+
+ alpha = (OVL_BLD_ALPHA & (state->base.alpha >> 8)) |
+ OVL_BLD_L_ALPHA_EN;
+
+ if (mtk_ovl_is_ignore_pixel_alpha(state, blend_mode))
+ ignore_pixel_alpha = OVL_BLD_L0_CONST;
+
+ mtk_ddp_write_mask(cmdq_pkt, pending->pitch | ignore_pixel_alpha,
+ &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_BLD_PITCH, OVL_BLD_L0_CONST | OVL_BLD_L0_SRC_PITCH);
+
+ mtk_ddp_write_mask(cmdq_pkt, alpha, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_BLD_L_CON2, OVL_BLD_L_ALPHA_EN | OVL_BLD_L_ALPHA);
+
+ mtk_ddp_write(cmdq_pkt, OVL_BLD_L_EN, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_L_EN);
+}
+
+void mtk_disp_blender_config(struct device *dev, unsigned int w,
+ unsigned int h, unsigned int vrefresh,
+ unsigned int bpc, bool most_top,
+ bool most_bottom, struct cmdq_pkt *cmdq_pkt)
+{
+ struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+ u32 datapath;
+
+ dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
+ mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_BLD_ROI_SIZE);
+ mtk_ddp_write(cmdq_pkt, DISP_REG_OVL_BLD_BGCLR_BALCK, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_BLD_BGCLR_CLR);
+ mtk_ddp_write(cmdq_pkt, DISP_REG_OVL_BLD_BGCLR_BALCK, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_BLD_L0_CLR);
+
+ if (most_top)
+ datapath = OVL_BLD_BGCLR_OUT_TO_PROC;
+ else
+ datapath = OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER;
+ /*
+ * The primary input is from EXDMA and the second input
+ * is optionally from another blender
+ */
+ if (!most_bottom)
+ datapath |= OVL_BLD_BGCLR_IN_SEL;
+
+ mtk_ddp_write_mask(cmdq_pkt, datapath,
+ &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_DATAPATH_CON,
+ OVL_BLD_BGCLR_OUT_TO_PROC | OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER |
+ OVL_BLD_BGCLR_IN_SEL);
+}
+
+void mtk_disp_blender_start(struct device *dev, struct cmdq_pkt *cmdq_pkt)
+{
+ struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+ unsigned int tmp;
+
+ tmp = readl(priv->regs + DISP_REG_OVL_BLD_SHADOW_CTRL);
+ tmp = tmp | OVL_BLD_BYPASS_SHADOW;
+ writel(tmp, priv->regs + DISP_REG_OVL_BLD_SHADOW_CTRL);
+ mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_EN, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_BLD_EN, OVL_BLD_EN);
+}
+
+void mtk_disp_blender_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt)
+{
+ struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+
+ mtk_ddp_write(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_L_EN);
+ mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_BLD_EN, OVL_BLD_EN);
+ mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_RST, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_BLD_RST, OVL_BLD_RST);
+ mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_BLD_RST, OVL_BLD_RST);
+}
+
+int mtk_disp_blender_clk_enable(struct device *dev)
+{
+ struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+
+ return clk_prepare_enable(priv->clk);
+}
+
+void mtk_disp_blender_clk_disable(struct device *dev)
+{
+ struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(priv->clk);
+}
+
+u32 mtk_disp_blender_get_blend_modes(struct device *dev)
+{
+ return BIT(DRM_MODE_BLEND_PREMULTI) |
+ BIT(DRM_MODE_BLEND_COVERAGE) |
+ BIT(DRM_MODE_BLEND_PIXEL_NONE);
+}
+
+static int mtk_disp_blender_bind(struct device *dev, struct device *master,
+ void *data)
+{
+ return 0;
+}
+
+static void mtk_disp_blender_unbind(struct device *dev, struct device *master, void *data)
+{
+}
+
+static const struct component_ops mtk_disp_blender_component_ops = {
+ .bind = mtk_disp_blender_bind,
+ .unbind = mtk_disp_blender_unbind,
+};
+
+static int mtk_disp_blender_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ struct mtk_disp_blender *priv;
+ int ret = 0;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->regs)) {
+ dev_err(dev, "failed to ioremap blender\n");
+ return PTR_ERR(priv->regs);
+ }
+
+ priv->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(priv->clk)) {
+ dev_err(dev, "failed to get blender clk\n");
+ return PTR_ERR(priv->clk);
+ }
+
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+ ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
+ if (ret)
+ dev_dbg(dev, "No mediatek,gce-client-reg\n");
+#endif
+ platform_set_drvdata(pdev, priv);
+
+ ret = component_add(dev, &mtk_disp_blender_component_ops);
+ if (ret)
+ dev_notice(dev, "Failed to add component: %d\n", ret);
+
+ return ret;
+}
+
+static void mtk_disp_blender_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &mtk_disp_blender_component_ops);
+}
+
+static const struct of_device_id mtk_disp_blender_driver_dt_match[] = {
+ { .compatible = "mediatek,mt8196-blender"},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, mtk_disp_blender_driver_dt_match);
+
+struct platform_driver mtk_disp_blender_driver = {
+ .probe = mtk_disp_blender_probe,
+ .remove = mtk_disp_blender_remove,
+ .driver = {
+ .name = "mediatek-disp-blender",
+ .owner = THIS_MODULE,
+ .of_match_table = mtk_disp_blender_driver_dt_match,
+ },
+};
+
+MODULE_AUTHOR("Nancy Lin <nancy.lin@mediatek.com>");
+MODULE_DESCRIPTION("MediaTek Blender Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_blender.h b/drivers/gpu/drm/mediatek/mtk_disp_blender.h
new file mode 100644
index 000000000000..be60a0f8de40
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_blender.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ */
+
+#ifndef __MTK_DISP_BLENDER_H__
+#define __MTK_DISP_BLENDER_H__
+
+enum mtk_disp_blender_layer {
+ FIRST_BLENDER,
+ LAST_BLENDER,
+ SINGLE_BLENDER,
+ OTHERS,
+ BLENDER_LAYER_MAX,
+};
+
+u32 mtk_disp_blender_get_blend_modes(struct device *dev);
+#endif // __MTK_DISP_BLENDER_H__
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index 4e3d2510bef5..39e3af1e2b16 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -9,6 +9,7 @@
#include <linux/soc/mediatek/mtk-cmdq.h>
#include <linux/soc/mediatek/mtk-mmsys.h>
#include <linux/soc/mediatek/mtk-mutex.h>
+#include "mtk_disp_blender.h"
#include "mtk_mdp_rdma.h"
#include "mtk_plane.h"
@@ -39,6 +40,17 @@ void mtk_color_config(struct device *dev, unsigned int w,
unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
void mtk_color_start(struct device *dev);
+void mtk_disp_blender_start(struct device *dev, struct cmdq_pkt *cmdq_pkt);
+void mtk_disp_blender_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt);
+int mtk_disp_blender_clk_enable(struct device *dev);
+void mtk_disp_blender_clk_disable(struct device *dev);
+void mtk_disp_blender_config(struct device *dev, unsigned int w,
+ unsigned int h, unsigned int vrefresh,
+ unsigned int bpc, bool most_top, bool most_bottom,
+ struct cmdq_pkt *cmdq_pkt);
+void mtk_disp_blender_layer_config(struct device *dev, struct mtk_plane_state *state,
+ struct cmdq_pkt *cmdq_pkt);
+
int mtk_disp_exdma_clk_enable(struct device *dev);
void mtk_disp_exdma_clk_disable(struct device *dev);
void mtk_disp_exdma_start(struct device *dev, struct cmdq_pkt *cmdq_pkt);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index bb7306a942ff..7a14f45d5f97 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -1274,6 +1274,7 @@ static struct platform_driver mtk_drm_platform_driver = {
static struct platform_driver * const mtk_drm_drivers[] = {
&mtk_disp_aal_driver,
+ &mtk_disp_blender_driver,
&mtk_disp_ccorr_driver,
&mtk_disp_color_driver,
&mtk_disp_exdma_driver,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index 898a75898775..89178de1478f 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -70,6 +70,7 @@ struct mtk_drm_private {
};
extern struct platform_driver mtk_disp_aal_driver;
+extern struct platform_driver mtk_disp_blender_driver;
extern struct platform_driver mtk_disp_ccorr_driver;
extern struct platform_driver mtk_disp_color_driver;
extern struct platform_driver mtk_disp_exdma_driver;
--
2.45.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH v2 12/15] drm/mediatek: add OUTPROC support for MT8196
2025-03-21 9:33 [PATCH v2 00/15] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
` (10 preceding siblings ...)
2025-03-21 9:33 ` [PATCH v2 11/15] drm/mediatek: add BLENDER " paul-pl.chen
@ 2025-03-21 9:33 ` paul-pl.chen
2025-03-24 9:00 ` CK Hu (胡俊光)
2025-03-21 9:33 ` [PATCH v2 13/15] drm/mediatek: add ovlsys_adaptor " paul-pl.chen
` (2 subsequent siblings)
14 siblings, 1 reply; 42+ messages in thread
From: paul-pl.chen @ 2025-03-21 9:33 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 | 242 ++++++++++++++++++++
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, 283 insertions(+)
create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_outproc.c
create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_outproc.h
diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
index a7b9ebe27f68..9546bc6b7b2e 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -10,6 +10,7 @@ mediatek-drm-y := mtk_crtc.o \
mtk_disp_gamma.o \
mtk_disp_merge.o \
mtk_disp_ovl.o \
+ mtk_disp_outproc.o \
mtk_disp_ovl_adaptor.o \
mtk_disp_rdma.o \
mtk_drm_drv.o \
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index e65c6df987f2..cc780744f060 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -447,6 +447,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
[MTK_DSI] = "dsi",
[MTK_OVL_BLENDER] = "blender",
[MTK_OVL_EXDMA] = "exdma",
+ [MTK_OVL_OUTPROC] = "outproc",
};
struct mtk_ddp_comp_match {
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
index 075ba5683f93..b33d3289b8b6 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
@@ -45,6 +45,7 @@ enum mtk_ddp_comp_type {
MTK_DSI,
MTK_OVL_BLENDER,
MTK_OVL_EXDMA,
+ MTK_OVL_OUTPROC,
MTK_DDP_COMP_TYPE_MAX,
};
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index 39e3af1e2b16..3c519a662074 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -64,6 +64,20 @@ void mtk_dither_set_common(void __iomem *regs, struct cmdq_client_reg *cmdq_reg,
unsigned int bpc, unsigned int cfg,
unsigned int dither_en, struct cmdq_pkt *cmdq_pkt);
+void mtk_disp_outproc_start(struct device *dev);
+void mtk_disp_outproc_stop(struct device *dev);
+int mtk_disp_outproc_clk_enable(struct device *dev);
+void mtk_disp_outproc_clk_disable(struct device *dev);
+void mtk_disp_outproc_config(struct device *dev, unsigned int w,
+ unsigned int h, unsigned int vrefresh,
+ unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
+void mtk_disp_outproc_register_vblank_cb(struct device *dev,
+ void (*vblank_cb)(void *),
+ void *vblank_cb_data);
+void mtk_disp_outproc_unregister_vblank_cb(struct device *dev);
+void mtk_disp_outproc_enable_vblank(struct device *dev);
+void mtk_disp_outproc_disable_vblank(struct device *dev);
+
void mtk_dpi_start(struct device *dev);
void mtk_dpi_stop(struct device *dev);
unsigned int mtk_dpi_encoder_index(struct device *dev);
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_outproc.c b/drivers/gpu/drm/mediatek/mtk_disp_outproc.c
new file mode 100644
index 000000000000..a7c6d1982bca
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_outproc.c
@@ -0,0 +1,242 @@
+// 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_drm_drv.h"
+#include "mtk_disp_outproc.h"
+
+#define DISP_REG_OVL_OUTPROC_INTEN 0x004
+#define OVL_OUTPROC_FME_CPL_INTEN BIT(1)
+#define DISP_REG_OVL_OUTPROC_INTSTA 0x008
+#define DISP_REG_OVL_OUTPROC_DATAPATH_CON 0x010
+#define OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP BIT(26)
+
+#define DISP_REG_OVL_OUTPROC_EN 0x020
+#define OVL_OUTPROC_OVL_EN BIT(0)
+#define DISP_REG_OVL_OUTPROC_RST 0x024
+#define OVL_OUTPROC_RST BIT(0)
+#define DISP_REG_OVL_OUTPROC_SHADOW_CTRL 0x028
+#define OVL_OUTPROC_BYPASS_SHADOW BIT(2)
+#define DISP_REG_OVL_OUTPROC_ROI_SIZE 0x030
+
+struct mtk_disp_outproc {
+ void __iomem *regs;
+ struct clk *clk;
+ void (*vblank_cb)(void *data);
+ void *vblank_cb_data;
+ int irq;
+ struct cmdq_client_reg cmdq_reg;
+};
+
+void mtk_disp_outproc_register_vblank_cb(struct device *dev,
+ void (*vblank_cb)(void *),
+ void *vblank_cb_data)
+{
+ struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+ priv->vblank_cb = vblank_cb;
+ priv->vblank_cb_data = vblank_cb_data;
+}
+
+void mtk_disp_outproc_unregister_vblank_cb(struct device *dev)
+{
+ struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+ priv->vblank_cb = NULL;
+ priv->vblank_cb_data = NULL;
+}
+
+void mtk_disp_outproc_enable_vblank(struct device *dev)
+{
+ struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+ writel(OVL_OUTPROC_FME_CPL_INTEN, priv->regs + DISP_REG_OVL_OUTPROC_INTEN);
+}
+
+void mtk_disp_outproc_disable_vblank(struct device *dev)
+{
+ struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+ writel(0x0, priv->regs + DISP_REG_OVL_OUTPROC_INTEN);
+}
+
+static irqreturn_t mtk_disp_outproc_irq_handler(int irq, void *dev_id)
+{
+ struct mtk_disp_outproc *priv = dev_id;
+ u32 val;
+
+ val = readl(priv->regs + DISP_REG_OVL_OUTPROC_INTSTA);
+ if (!val)
+ return IRQ_NONE;
+
+ writel(0x0, priv->regs + DISP_REG_OVL_OUTPROC_INTSTA);
+
+ if (priv->vblank_cb)
+ priv->vblank_cb(priv->vblank_cb_data);
+
+ return IRQ_HANDLED;
+}
+
+void mtk_disp_outproc_config(struct device *dev, unsigned int w,
+ unsigned int h, unsigned int vrefresh,
+ unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
+{
+ struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
+
+ //move mtk_ddp_write_mask to mtk_ddp_write
+ mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_OUTPROC_ROI_SIZE);
+ mtk_ddp_write_mask(cmdq_pkt, OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP,
+ &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_OUTPROC_DATAPATH_CON,
+ OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP);
+}
+
+void mtk_disp_outproc_start(struct device *dev)
+{
+ struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+ unsigned int tmp;
+
+ tmp = readl(priv->regs + DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
+ tmp = tmp | OVL_OUTPROC_BYPASS_SHADOW;
+ writel(tmp, priv->regs + DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
+
+ mtk_ddp_write(NULL, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_OUTPROC_INTSTA);
+ mtk_ddp_write_mask(NULL, OVL_OUTPROC_OVL_EN, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_OUTPROC_EN, OVL_OUTPROC_OVL_EN);
+}
+
+void mtk_disp_outproc_stop(struct device *dev)
+{
+ struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+ mtk_ddp_write_mask(NULL, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_OUTPROC_EN, OVL_OUTPROC_OVL_EN);
+ mtk_ddp_write_mask(NULL, OVL_OUTPROC_RST, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_OUTPROC_RST, OVL_OUTPROC_RST);
+ mtk_ddp_write_mask(NULL, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_OUTPROC_RST, OVL_OUTPROC_RST);
+}
+
+int mtk_disp_outproc_clk_enable(struct device *dev)
+{
+ struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+ return clk_prepare_enable(priv->clk);
+}
+
+void mtk_disp_outproc_clk_disable(struct device *dev)
+{
+ struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(priv->clk);
+}
+
+static int mtk_disp_outproc_bind(struct device *dev, struct device *master,
+ void *data)
+{
+ return 0;
+}
+
+static void mtk_disp_outproc_unbind(struct device *dev, struct device *master, void *data)
+{
+}
+
+static const struct component_ops mtk_disp_outproc_component_ops = {
+ .bind = mtk_disp_outproc_bind,
+ .unbind = mtk_disp_outproc_unbind,
+};
+
+static int mtk_disp_outproc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mtk_disp_outproc *priv;
+ int ret = 0;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(priv->regs))
+ return dev_err_probe(dev, PTR_ERR(priv->regs), "failed to ioremap outproc\n");
+
+ priv->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(priv->clk))
+ return dev_err_probe(dev, PTR_ERR(priv->clk), "failed to get outproc clk\n");
+
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+ ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
+ if (ret)
+ dev_dbg(dev, "No mediatek,gce-client-reg\n");
+#endif
+
+ if (of_property_read_u32_index(dev->of_node, "interrupts", 0, &ret)) {
+ dev_dbg(dev, "interrupts not defined\n");
+ } else {
+ priv->irq = platform_get_irq(pdev, 0);
+ if (priv->irq < 0)
+ priv->irq = 0;
+
+ if (priv->irq) {
+ ret = devm_request_irq(dev, priv->irq, mtk_disp_outproc_irq_handler,
+ IRQF_TRIGGER_NONE, dev_name(dev), priv);
+ if (ret < 0) {
+ dev_err(dev, "Failed to request irq %d: %d\n", priv->irq, ret);
+ return ret;
+ }
+ }
+ }
+
+ platform_set_drvdata(pdev, priv);
+
+ ret = component_add(dev, &mtk_disp_outproc_component_ops);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to add component\n");
+
+ return ret;
+}
+
+static void mtk_disp_outproc_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &mtk_disp_outproc_component_ops);
+}
+
+static const struct of_device_id mtk_disp_outproc_driver_dt_match[] = {
+ { .compatible = "mediatek,mt8196-outproc"},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, mtk_disp_outproc_driver_dt_match);
+
+struct platform_driver mtk_disp_outproc_driver = {
+ .probe = mtk_disp_outproc_probe,
+ .remove = mtk_disp_outproc_remove,
+ .driver = {
+ .name = "mediatek-disp-outproc",
+ .owner = THIS_MODULE,
+ .of_match_table = mtk_disp_outproc_driver_dt_match,
+ },
+};
+
+MODULE_AUTHOR("Nancy Lin <nancy.lin@mediatek.com>");
+MODULE_DESCRIPTION("MediaTek Output processing Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_outproc.h b/drivers/gpu/drm/mediatek/mtk_disp_outproc.h
new file mode 100644
index 000000000000..abb101979521
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_outproc.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ */
+
+#ifndef __MTK_DISP_OUTPROC_H__
+#define __MTK_DISP_OUTPROC_H__
+
+void mtk_disp_outproc_start(struct device *dev);
+void mtk_disp_outproc_stop(struct device *dev);
+int mtk_disp_outproc_clk_enable(struct device *dev);
+void mtk_disp_outproc_clk_disable(struct device *dev);
+void mtk_disp_outproc_config(struct device *dev, unsigned int w,
+ unsigned int h, unsigned int vrefresh,
+ unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
+void mtk_disp_outproc_register_vblank_cb(struct device *dev,
+ void (*vblank_cb)(void *),
+ void *vblank_cb_data);
+void mtk_disp_outproc_unregister_vblank_cb(struct device *dev);
+void mtk_disp_outproc_enable_vblank(struct device *dev);
+void mtk_disp_outproc_disable_vblank(struct device *dev);
+#endif
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 7a14f45d5f97..f7b9c7a982a7 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -1280,6 +1280,7 @@ static struct platform_driver * const mtk_drm_drivers[] = {
&mtk_disp_exdma_driver,
&mtk_disp_gamma_driver,
&mtk_disp_merge_driver,
+ &mtk_disp_outproc_driver,
&mtk_disp_ovl_adaptor_driver,
&mtk_disp_ovl_driver,
&mtk_disp_rdma_driver,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index 89178de1478f..c4717c37b0f1 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -76,6 +76,7 @@ extern struct platform_driver mtk_disp_color_driver;
extern struct platform_driver mtk_disp_exdma_driver;
extern struct platform_driver mtk_disp_gamma_driver;
extern struct platform_driver mtk_disp_merge_driver;
+extern struct platform_driver mtk_disp_outproc_driver;
extern struct platform_driver mtk_disp_ovl_adaptor_driver;
extern struct platform_driver mtk_disp_ovl_driver;
extern struct platform_driver mtk_disp_rdma_driver;
--
2.45.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH v2 13/15] drm/mediatek: add ovlsys_adaptor support for MT8196
2025-03-21 9:33 [PATCH v2 00/15] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
` (11 preceding siblings ...)
2025-03-21 9:33 ` [PATCH v2 12/15] drm/mediatek: add OUTPROC " paul-pl.chen
@ 2025-03-21 9:33 ` paul-pl.chen
2025-04-11 3:07 ` CK Hu (胡俊光)
2025-03-21 9:33 ` [PATCH v2 14/15] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver paul-pl.chen
2025-03-21 9:33 ` [PATCH v2 15/15] drm/mediatek: Add support for MT8196 multiple mmsys paul-pl.chen
14 siblings, 1 reply; 42+ messages in thread
From: paul-pl.chen @ 2025-03-21 9:33 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 | 797 ++++++++++++++++++
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 73 ++
drivers/gpu/drm/mediatek/mtk_drm_drv.h | 11 +-
7 files changed, 942 insertions(+), 1 deletion(-)
create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
index 9546bc6b7b2e..dedf50860d3f 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -9,6 +9,7 @@ mediatek-drm-y := mtk_crtc.o \
mtk_disp_exdma.o \
mtk_disp_gamma.o \
mtk_disp_merge.o \
+ mtk_disp_ovlsys_adaptor.o \
mtk_disp_ovl.o \
mtk_disp_outproc.o \
mtk_disp_ovl_adaptor.o \
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index cc780744f060..c96e027359ac 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -368,6 +368,31 @@ static const struct mtk_ddp_comp_funcs ddp_ovl = {
.get_num_formats = mtk_ovl_get_num_formats,
};
+static const struct mtk_ddp_comp_funcs ddp_ovlsys_adaptor = {
+ .power_on = mtk_ovlsys_adaptor_power_on,
+ .power_off = mtk_ovlsys_adaptor_power_off,
+ .clk_enable = mtk_ovlsys_adaptor_clk_enable,
+ .clk_disable = mtk_ovlsys_adaptor_clk_disable,
+ .config = mtk_ovlsys_adaptor_config,
+ .start = mtk_ovlsys_adaptor_start,
+ .stop = mtk_ovlsys_adaptor_stop,
+ .layer_check = mtk_ovlsys_adaptor_layer_check,
+ .layer_nr = mtk_ovlsys_adaptor_layer_nr,
+ .layer_config = mtk_ovlsys_adaptor_layer_config,
+ .register_vblank_cb = mtk_ovlsys_adaptor_register_vblank_cb,
+ .unregister_vblank_cb = mtk_ovlsys_adaptor_unregister_vblank_cb,
+ .enable_vblank = mtk_ovlsys_adaptor_enable_vblank,
+ .disable_vblank = mtk_ovlsys_adaptor_disable_vblank,
+ .dma_dev_get = mtk_ovlsys_adaptor_dma_dev_get,
+ .connect = mtk_ovlsys_adaptor_connect,
+ .disconnect = mtk_ovlsys_adaptor_disconnect,
+ .add = mtk_ovlsys_adaptor_add_comp,
+ .remove = mtk_ovlsys_adaptor_remove_comp,
+ .get_blend_modes = mtk_ovlsys_adaptor_get_blend_modes,
+ .get_formats = mtk_ovlsys_adaptor_get_formats,
+ .get_num_formats = mtk_ovlsys_adaptor_get_num_formats,
+};
+
static const struct mtk_ddp_comp_funcs ddp_postmask = {
.clk_enable = mtk_ddp_clk_enable,
.clk_disable = mtk_ddp_clk_disable,
@@ -437,6 +462,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
[MTK_DISP_OVL] = "ovl",
[MTK_DISP_OVL_2L] = "ovl-2l",
[MTK_DISP_OVL_ADAPTOR] = "ovl_adaptor",
+ [MTK_DISP_OVLSYS_ADAPTOR] = "ovlsys_adaptor",
[MTK_DISP_POSTMASK] = "postmask",
[MTK_DISP_PWM] = "pwm",
[MTK_DISP_RDMA] = "rdma",
@@ -469,6 +495,8 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
[DDP_COMPONENT_DPI0] = { MTK_DPI, 0, &ddp_dpi },
[DDP_COMPONENT_DPI1] = { MTK_DPI, 1, &ddp_dpi },
[DDP_COMPONENT_DRM_OVL_ADAPTOR] = { MTK_DISP_OVL_ADAPTOR, 0, &ddp_ovl_adaptor },
+ [DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0] = { MTK_DISP_OVLSYS_ADAPTOR, 0, &ddp_ovlsys_adaptor},
+ [DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1] = { MTK_DISP_OVLSYS_ADAPTOR, 1, &ddp_ovlsys_adaptor},
[DDP_COMPONENT_DSC0] = { MTK_DISP_DSC, 0, &ddp_dsc },
[DDP_COMPONENT_DSC1] = { MTK_DISP_DSC, 1, &ddp_dsc },
[DDP_COMPONENT_DSI0] = { MTK_DSI, 0, &ddp_dsi },
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
index b33d3289b8b6..ef64ce7a071f 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
@@ -33,6 +33,7 @@ enum mtk_ddp_comp_type {
MTK_DISP_MUTEX,
MTK_DISP_OD,
MTK_DISP_OVL,
+ MTK_DISP_OVLSYS_ADAPTOR,
MTK_DISP_OVL_2L,
MTK_DISP_OVL_ADAPTOR,
MTK_DISP_POSTMASK,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index 3c519a662074..1ff8c4593fc1 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -174,6 +174,38 @@ size_t mtk_ovl_adaptor_get_num_formats(struct device *dev);
enum drm_mode_status mtk_ovl_adaptor_mode_valid(struct device *dev,
const struct drm_display_mode *mode);
+int mtk_ovlsys_adaptor_power_on(struct device *dev);
+void mtk_ovlsys_adaptor_power_off(struct device *dev);
+void mtk_ovlsys_adaptor_add_comp(struct device *dev, struct mtk_mutex *mutex);
+void mtk_ovlsys_adaptor_remove_comp(struct device *dev, struct mtk_mutex *mutex);
+void mtk_ovlsys_adaptor_connect(struct device *dev, struct device *mmsys_dev,
+ unsigned int next);
+void mtk_ovlsys_adaptor_disconnect(struct device *dev, struct device *mmsys_dev,
+ unsigned int next);
+int mtk_ovlsys_adaptor_clk_enable(struct device *dev);
+void mtk_ovlsys_adaptor_clk_disable(struct device *dev);
+void mtk_ovlsys_adaptor_config(struct device *dev, unsigned int w,
+ unsigned int h, unsigned int vrefresh,
+ unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
+void mtk_ovlsys_adaptor_layer_config(struct device *dev, unsigned int idx,
+ struct mtk_plane_state *state,
+ struct cmdq_pkt *cmdq_pkt);
+int mtk_ovlsys_adaptor_layer_check(struct device *dev,
+ unsigned int idx,
+ struct mtk_plane_state *mtk_state);
+void mtk_ovlsys_adaptor_register_vblank_cb(struct device *dev, void (*vblank_cb)(void *),
+ void *vblank_cb_data);
+void mtk_ovlsys_adaptor_unregister_vblank_cb(struct device *dev);
+void mtk_ovlsys_adaptor_enable_vblank(struct device *dev);
+void mtk_ovlsys_adaptor_disable_vblank(struct device *dev);
+void mtk_ovlsys_adaptor_start(struct device *dev);
+void mtk_ovlsys_adaptor_stop(struct device *dev);
+unsigned int mtk_ovlsys_adaptor_layer_nr(struct device *dev);
+struct device *mtk_ovlsys_adaptor_dma_dev_get(struct device *dev);
+u32 mtk_ovlsys_adaptor_get_blend_modes(struct device *dev);
+const u32 *mtk_ovlsys_adaptor_get_formats(struct device *dev);
+size_t mtk_ovlsys_adaptor_get_num_formats(struct device *dev);
+
void mtk_rdma_bypass_shadow(struct device *dev);
int mtk_rdma_clk_enable(struct device *dev);
void mtk_rdma_clk_disable(struct device *dev);
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c b/drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
new file mode 100644
index 000000000000..04cb555bd77b
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
@@ -0,0 +1,797 @@
+// 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_disp_blender.h"
+#include "mtk_disp_drv.h"
+#include "mtk_crtc.h"
+#include "mtk_ddp_comp.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;
+ unsigned int max_size;
+};
+
+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_EXDMA0] = { OVLSYS_ADAPTOR_TYPE_EXDMA, 0, DDP_COMPONENT_ID_MAX},
+ [OVLSYS_ADAPTOR_EXDMA1] = { OVLSYS_ADAPTOR_TYPE_EXDMA, 1, DDP_COMPONENT_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;
+}
+
+static struct device *get_comp_by_type_idx(struct device *dev,
+ enum mtk_ovlsys_adaptor_comp_type type,
+ unsigned int idx)
+{
+ struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+ int i;
+ int count = 0;
+
+ for (i = 0; i < priv->path_size; i++) {
+ if (get_type(priv->path[i]) == type) {
+ if (count == idx)
+ return priv->ovl_adaptor_comp[priv->path[i]];
+ count++;
+ }
+ }
+ return NULL;
+}
+
+int mtk_ovlsys_adaptor_power_on(struct device *dev)
+{
+ struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+ struct device *comp;
+ int ret = 0;
+ int i;
+
+ for (i = 0; i < OVLSYS_ADAPTOR_ID_MAX; i++) {
+ comp = priv->ovl_adaptor_comp[i];
+
+ if (!comp)
+ continue;
+
+ if (get_type(i) != OVLSYS_ADAPTOR_TYPE_EXDMA)
+ continue;
+
+ ret = pm_runtime_get_sync(comp);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enable power domain %d, err %d\n", i, ret);
+ goto pwr_err;
+ }
+ }
+
+ return ret;
+pwr_err:
+ while (--i >= 0) {
+ comp = priv->ovl_adaptor_comp[i];
+ if (!comp)
+ continue;
+ if (get_type(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 < OVLSYS_ADAPTOR_ID_MAX; i++) {
+ comp = priv->ovl_adaptor_comp[i];
+
+ if (!comp)
+ continue;
+
+ if (get_type(i) == OVLSYS_ADAPTOR_TYPE_EXDMA)
+ 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 device *exdma;
+ struct device *blender;
+ unsigned int align_width = 0;
+ const struct drm_format_info *fmt_info = drm_format_info(pending->format);
+ struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+ 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 = get_comp_by_type_idx(dev, OVLSYS_ADAPTOR_TYPE_EXDMA, idx);
+ if (!exdma) {
+ dev_err(dev, "%s: exdma%d comp not found\n", __func__, idx);
+ return;
+ }
+ blender = get_comp_by_type_idx(dev, OVLSYS_ADAPTOR_TYPE_BLENDER, idx);
+ if (!blender) {
+ dev_err(dev, "%s: blender%d comp not found\n", __func__, idx);
+ return;
+ }
+
+ /* OVLSYS is in 1T2P domain, width needs to be 2 pixels align */
+ align_width = ALIGN_DOWN(pending->width, 2);
+
+ if (pending->height == 0 || align_width == 0 ||
+ pending->x > priv->max_size || pending->y > priv->max_size) {
+ pending->enable = false;
+ mtk_disp_exdma_layer_config(exdma, state, cmdq_pkt);
+ mtk_disp_blender_layer_config(blender, state, cmdq_pkt);
+ return;
+ }
+
+ mtk_disp_exdma_layer_config(exdma, state, cmdq_pkt);
+
+ mtk_disp_blender_layer_config(blender, state, cmdq_pkt);
+
+ mtk_disp_exdma_start(exdma, cmdq_pkt);
+ mtk_disp_blender_start(blender, cmdq_pkt);
+}
+
+void mtk_ovlsys_adaptor_config(struct device *dev, unsigned int w,
+ unsigned int h, unsigned int vrefresh,
+ unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
+{
+ struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+ int i;
+ int blender_idx = 0;
+ bool most_top;
+ bool most_bottom;
+
+ for (i = 0; i < priv->path_size; i++) {
+ if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER) {
+ blender_idx++;
+
+ if (priv->layer_nr == 1) {
+ most_top = true; /*SINGLE_BLENDER;*/
+ most_bottom = false; /*blender is LAST_BLENDER*/
+ } else if (blender_idx == 1) {
+ most_top = false; /* NON-SINGLE LAYER */
+ most_bottom = true; /* FIRST LAYER */
+ } else if (blender_idx == priv->layer_nr) {
+ most_top = true; /* NON-SINGLE LAYER */
+ most_bottom = false; /* LAST LAYER */
+ } else {
+ most_top = false; /* NON-SINGLE LAYER */
+ most_bottom = false; /* OTHER LAYER */
+ }
+
+ mtk_disp_blender_config(priv->ovl_adaptor_comp[priv->path[i]], w, h,
+ vrefresh, bpc, most_top, most_bottom, cmdq_pkt);
+ } else if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_OUTPROC) {
+ mtk_disp_outproc_config(priv->ovl_adaptor_comp[priv->path[i]], w, h,
+ vrefresh, bpc, cmdq_pkt);
+ }
+ }
+}
+
+int mtk_ovlsys_adaptor_layer_check(struct device *dev,
+ unsigned int idx,
+ struct mtk_plane_state *mtk_state)
+{
+ struct drm_plane_state *state = &mtk_state->base;
+
+ /* Check if any unsupported rotation is set */
+ if (state->rotation & ~DRM_MODE_ROTATE_0)
+ return -EINVAL;
+
+ return 0;
+}
+
+void mtk_ovlsys_adaptor_start(struct device *dev)
+{
+ struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+ int i;
+
+ for (i = 0; i < priv->path_size; i++) {
+ if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_EXDMA)
+ mtk_disp_exdma_start(priv->ovl_adaptor_comp[priv->path[i]], NULL);
+ else if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER)
+ mtk_disp_blender_start(priv->ovl_adaptor_comp[priv->path[i]], NULL);
+ else
+ 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; i++) {
+ if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_EXDMA)
+ mtk_disp_exdma_stop(priv->ovl_adaptor_comp[priv->path[i]], NULL);
+ else if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER)
+ mtk_disp_blender_stop(priv->ovl_adaptor_comp[priv->path[i]], NULL);
+ else
+ 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 = 0;
+ int i;
+
+ for (i = 0; i < OVLSYS_ADAPTOR_ID_MAX; i++) {
+ comp = priv->ovl_adaptor_comp[i];
+
+ if (!comp)
+ continue;
+
+ if (get_type(i) == OVLSYS_ADAPTOR_TYPE_EXDMA)
+ ret = mtk_disp_exdma_clk_enable(comp);
+ else if (get_type(i) == OVLSYS_ADAPTOR_TYPE_BLENDER)
+ ret = mtk_disp_blender_clk_enable(comp);
+ else
+ ret = mtk_disp_outproc_clk_enable(comp);
+
+ if (ret) {
+ dev_err(dev, "Failed to enable clock %d, err %d\n", i, ret);
+ goto clk_err;
+ }
+ }
+
+ return ret;
+
+clk_err:
+ while (--i >= 0) {
+ comp = priv->ovl_adaptor_comp[i];
+ if (!comp)
+ continue;
+ if (get_type(i) == OVLSYS_ADAPTOR_TYPE_EXDMA)
+ mtk_disp_exdma_clk_disable(comp);
+ else if (get_type(i) == OVLSYS_ADAPTOR_TYPE_BLENDER)
+ mtk_disp_blender_clk_disable(comp);
+ else
+ mtk_disp_outproc_clk_disable(comp);
+ }
+ i = OVLSYS_ADAPTOR_ID_MAX;
+
+ 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 < OVLSYS_ADAPTOR_ID_MAX; i++) {
+ comp = priv->ovl_adaptor_comp[i];
+
+ if (!comp)
+ continue;
+
+ if (get_type(i) == OVLSYS_ADAPTOR_TYPE_EXDMA)
+ mtk_disp_exdma_clk_disable(comp);
+ else if (get_type(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);
+ struct device *comp;
+ int i;
+
+ for (i = 0; i < priv->path_size; i++)
+ if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER) {
+ comp = priv->ovl_adaptor_comp[priv->path[i]];
+ return mtk_disp_blender_get_blend_modes(comp);
+ }
+
+ return 0;
+}
+
+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,
+ enum mtk_ddp_comp_id *comp_id)
+{
+ 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) {
+ *comp_id = comp_matches[i].comp_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 *node, *parent;
+ struct platform_device *comp_pdev;
+ int i;
+
+ parent = dev->parent->parent->of_node->parent;
+
+ for_each_child_of_node(parent, node) {
+ const struct of_device_id *of_id;
+ enum mtk_ovlsys_adaptor_comp_type type;
+ enum mtk_ddp_comp_id comp_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, &comp_id);
+ if (id < 0) {
+ dev_warn(dev, "Skipping unknown component %pOF\n",
+ node);
+ continue;
+ }
+
+ for (i = 0; i < priv->path_size; i++)
+ if (priv->path[i] == id)
+ found = true;
+
+ if (!found)
+ continue;
+
+ comp_pdev = of_find_device_by_node(node);
+ if (!comp_pdev)
+ return -EPROBE_DEFER;
+
+ priv->ovl_adaptor_comp[id] = &comp_pdev->dev;
+
+ drm_of_component_match_add(dev, match, component_compare_of, node);
+ dev_dbg(dev, "Adding component match for %pOF\n", node);
+ }
+
+ if (!*match) {
+ dev_err(dev, "No match device for ovlsys_adaptor\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int mtk_disp_ovlsys_adaptor_comp_bind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+ if (!priv->children_bound)
+ return -EPROBE_DEFER;
+
+ return 0;
+}
+
+static void mtk_disp_ovlsys_adaptor_comp_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+}
+
+static const struct component_ops mtk_disp_ovlsys_adaptor_comp_ops = {
+ .bind = mtk_disp_ovlsys_adaptor_comp_bind,
+ .unbind = mtk_disp_ovlsys_adaptor_comp_unbind,
+};
+
+static int mtk_disp_ovlsys_adaptor_master_bind(struct device *dev)
+{
+ struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+ int ret, i;
+ unsigned int layer_nr = 0;
+
+ 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;
+
+ for (i = 0; i < priv->path_size; i++)
+ if (comp_matches[priv->path[i]].type == OVLSYS_ADAPTOR_TYPE_BLENDER)
+ layer_nr++;
+ priv->layer_nr = layer_nr;
+
+ return 0;
+}
+
+static void mtk_disp_ovlsys_adaptor_master_unbind(struct device *dev)
+{
+ struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
+
+ priv->children_bound = false;
+}
+
+static const struct component_master_ops mtk_disp_ovlsys_adaptor_master_ops = {
+ .bind = mtk_disp_ovlsys_adaptor_master_bind,
+ .unbind = mtk_disp_ovlsys_adaptor_master_unbind,
+};
+
+static int mtk_disp_ovlsys_adaptor_probe(struct platform_device *pdev)
+{
+ struct mtk_disp_ovlsys_adaptor *priv;
+ struct device *dev = &pdev->dev;
+ struct component_match *match = NULL;
+ struct mtk_ovlsys_platform_data *ovlsys_priv; //mtk_drm_ovlsys_private
+ 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;
+ priv->max_size = OVLSYS_ADAPTOR_DRIVER_DATA_MAX_SIZE;
+
+ if (ovlsys_priv->use_path == CRTC_MAIN) {
+ priv->path = mt8196_mtk_ovl_main;
+ priv->path_size = ARRAY_SIZE(mt8196_mtk_ovl_main);
+ } else if (ovlsys_priv->use_path == CRTC_EXT) {
+ priv->path = mt8196_mtk_ovl_ext;
+ priv->path_size = ARRAY_SIZE(mt8196_mtk_ovl_ext);
+ } else if (ovlsys_priv->use_path == CRTC_THIRD) {
+ priv->path = mt8196_mtk_ovl_third;
+ priv->path_size = ARRAY_SIZE(mt8196_mtk_ovl_third);
+ }
+
+ ret = ovlsys_adaptor_comp_init(dev, &match);
+ if (ret < 0)
+ return ret;
+
+ component_master_add_with_match(dev, &mtk_disp_ovlsys_adaptor_master_ops, match);
+
+ pm_runtime_enable(dev);
+
+ ret = component_add(dev, &mtk_disp_ovlsys_adaptor_comp_ops);
+ if (ret != 0) {
+ pm_runtime_disable(dev);
+ dev_err(dev, "Failed to add component: %d\n", ret);
+ }
+
+ return ret;
+}
+
+static void mtk_disp_ovlsys_adaptor_remove(struct platform_device *pdev)
+{
+ component_master_del(&pdev->dev, &mtk_disp_ovlsys_adaptor_master_ops);
+ pm_runtime_disable(&pdev->dev);
+}
+
+struct platform_driver mtk_disp_ovlsys_adaptor_driver = {
+ .probe = mtk_disp_ovlsys_adaptor_probe,
+ .remove = mtk_disp_ovlsys_adaptor_remove,
+ .driver = {
+ .name = "mediatek-disp-ovlsys-adaptor",
+ .owner = THIS_MODULE,
+ },
+};
+
+MODULE_AUTHOR("Nancy Lin <nancy.lin@mediatek.com>");
+MODULE_DESCRIPTION("MediaTek Ovlsys Adaptor Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index f7b9c7a982a7..0639201e2e92 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -457,6 +457,27 @@ static bool mtk_drm_find_mmsys_comp(struct mtk_drm_private *private, int comp_id
return false;
}
+static int mtk_drm_mmsys_comp_in_path(struct mtk_drm_private *private, int comp_id)
+{
+ const struct mtk_mmsys_driver_data *drv_data = private->data;
+ int i;
+
+ if (drv_data->main_path)
+ for (i = 0; i < drv_data->main_len; i++)
+ if (drv_data->main_path[i] == comp_id)
+ return CRTC_MAIN;
+ if (drv_data->ext_path)
+ for (i = 0; i < drv_data->ext_len; i++)
+ if (drv_data->ext_path[i] == comp_id)
+ return CRTC_EXT;
+ if (drv_data->third_path)
+ for (i = 0; i < drv_data->third_len; i++)
+ if (drv_data->third_path[i] == comp_id)
+ return CRTC_THIRD;
+
+ return -EINVAL;
+}
+
static int mtk_drm_kms_init(struct drm_device *drm)
{
struct mtk_drm_private *private = drm->dev_private;
@@ -1122,6 +1143,57 @@ static int mtk_drm_probe(struct platform_device *pdev)
component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev);
}
+ if (mtk_drm_find_mmsys_comp(private, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0)) {
+ struct mtk_ovlsys_platform_data ovlsys_priv;
+
+ ovlsys_priv.mmsys_dev = private->mmsys_dev;
+ ovlsys_priv.use_path =
+ mtk_drm_mmsys_comp_in_path(private, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0);
+ ovl_adaptor =
+ platform_device_register_data(dev, "mediatek-disp-ovlsys-adaptor",
+ PLATFORM_DEVID_AUTO,
+ (void *)&ovlsys_priv,
+ sizeof(struct mtk_ovlsys_platform_data));
+ private->ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0].dev = &ovl_adaptor->dev;
+ mtk_ddp_comp_init(NULL, &private->ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0],
+ DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0);
+ component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev);
+ }
+
+ if (mtk_drm_find_mmsys_comp(private, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1)) {
+ struct mtk_ovlsys_platform_data ovlsys_priv; //mtk_drm_ovlsys_private
+
+ ovlsys_priv.mmsys_dev = private->mmsys_dev;
+ ovlsys_priv.use_path =
+ mtk_drm_mmsys_comp_in_path(private, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1);
+ ovl_adaptor =
+ platform_device_register_data(dev, "mediatek-disp-ovlsys-adaptor",
+ PLATFORM_DEVID_AUTO,
+ (void *)&ovlsys_priv,
+ sizeof(struct mtk_ovlsys_platform_data));
+ private->ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1].dev = &ovl_adaptor->dev;
+ mtk_ddp_comp_init(NULL, &private->ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1],
+ DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1);
+ component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev);
+ }
+
+ if (mtk_drm_find_mmsys_comp(private, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2)) {
+ struct mtk_ovlsys_platform_data ovlsys_priv;
+
+ ovlsys_priv.mmsys_dev = private->mmsys_dev;
+ ovlsys_priv.use_path =
+ mtk_drm_mmsys_comp_in_path(private, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2);
+ ovl_adaptor =
+ platform_device_register_data(dev, "mediatek-disp-ovlsys-adaptor",
+ PLATFORM_DEVID_AUTO,
+ (void *)&ovlsys_priv,
+ sizeof(struct mtk_ovlsys_platform_data));
+ private->ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2].dev = &ovl_adaptor->dev;
+ mtk_ddp_comp_init(NULL, &private->ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2],
+ DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2);
+ component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev);
+ }
+
/* Iterate over sibling DISP function blocks */
for_each_child_of_node(phandle->parent, node) {
enum mtk_ddp_comp_type comp_type;
@@ -1283,6 +1355,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..6e9ed9837c5b 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -11,7 +11,9 @@
#define MAX_CONNECTOR 2
#define DDP_COMPONENT_DRM_OVL_ADAPTOR (DDP_COMPONENT_ID_MAX + 1)
-#define DDP_COMPONENT_DRM_ID_MAX (DDP_COMPONENT_DRM_OVL_ADAPTOR + 1)
+#define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 (DDP_COMPONENT_DRM_OVL_ADAPTOR + 1)
+#define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 + 1)
+#define DDP_COMPONENT_DRM_ID_MAX (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 + 1)
enum mtk_crtc_path {
CRTC_MAIN,
@@ -69,6 +71,12 @@ struct mtk_drm_private {
struct mtk_drm_private **all_drm_private;
};
+struct mtk_ovlsys_platform_data {//mtk_drm_ovlsys_private
+ struct device *mmsys_dev;
+ struct device *mutex_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] 42+ messages in thread
* [PATCH v2 14/15] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver
2025-03-21 9:33 [PATCH v2 00/15] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
` (12 preceding siblings ...)
2025-03-21 9:33 ` [PATCH v2 13/15] drm/mediatek: add ovlsys_adaptor " paul-pl.chen
@ 2025-03-21 9:33 ` paul-pl.chen
2025-03-25 3:44 ` CK Hu (胡俊光)
2025-03-21 9:33 ` [PATCH v2 15/15] drm/mediatek: Add support for MT8196 multiple mmsys paul-pl.chen
14 siblings, 1 reply; 42+ messages in thread
From: paul-pl.chen @ 2025-03-21 9:33 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 | 102 +++----
drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 2 +
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 86 +++---
drivers/gpu/drm/mediatek/mtk_drm_drv.h | 16 +-
6 files changed, 392 insertions(+), 162 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c
index 8f6fba4217ec..4f91ffdd08ae 100644
--- a/drivers/gpu/drm/mediatek/mtk_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_crtc.c
@@ -58,13 +58,17 @@ struct mtk_crtc {
wait_queue_head_t cb_blocking_queue;
#endif
- struct device *mmsys_dev;
+ struct device *mmsys_dev[MAX_MMSYS];
struct device *dma_dev;
- struct mtk_mutex *mutex;
+ struct device *vdisp_ao_dev;
+ struct mtk_mutex *mutex[MAX_MMSYS];
unsigned int ddp_comp_nr;
struct mtk_ddp_comp **ddp_comp;
+ enum mtk_drm_mmsys *ddp_comp_sys;
+ bool exist[MAX_MMSYS];
unsigned int num_conn_routes;
const struct mtk_drm_route *conn_routes;
+ enum mtk_drm_mmsys conn_routes_sys;
/* lock for display hardware access */
struct mutex hw_lock;
@@ -82,6 +86,11 @@ struct mtk_crtc_state {
unsigned int pending_vrefresh;
};
+struct mtk_crtc_comp_info {
+ enum mtk_drm_mmsys sys;
+ unsigned int comp_id;
+};
+
static inline struct mtk_crtc *to_mtk_crtc(struct drm_crtc *c)
{
return container_of(c, struct mtk_crtc, base);
@@ -130,7 +139,10 @@ static void mtk_crtc_destroy(struct drm_crtc *crtc)
struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
int i;
- mtk_mutex_put(mtk_crtc->mutex);
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->mutex[i])
+ mtk_mutex_put(mtk_crtc->mutex[i]);
+
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
if (mtk_crtc->cmdq_client.chan) {
cmdq_pkt_destroy(&mtk_crtc->cmdq_client, &mtk_crtc->cmdq_handle);
@@ -228,7 +240,14 @@ static int mtk_crtc_ddp_clk_enable(struct mtk_crtc *mtk_crtc)
int i;
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
+ enum mtk_drm_mmsys mmsys;
+
ret = mtk_ddp_comp_clk_enable(mtk_crtc->ddp_comp[i]);
+ if (mtk_ddp_comp_get_type(mtk_crtc->ddp_comp[i]->id) == MTK_DISP_VIRTUAL) {
+ mmsys = mtk_crtc->ddp_comp_sys[i];
+ ret = mtk_mmsys_ddp_clk_enable(mtk_crtc->mmsys_dev[mmsys],
+ mtk_crtc->ddp_comp[i]->id);
+ }
if (ret) {
DRM_ERROR("Failed to enable clock %d: %d\n", i, ret);
goto err;
@@ -237,17 +256,28 @@ static int mtk_crtc_ddp_clk_enable(struct mtk_crtc *mtk_crtc)
return 0;
err:
- while (--i >= 0)
+ while (--i >= 0) {
mtk_ddp_comp_clk_disable(mtk_crtc->ddp_comp[i]);
+ if (mtk_ddp_comp_get_type(mtk_crtc->ddp_comp[i]->id) == MTK_DISP_VIRTUAL)
+ mtk_mmsys_ddp_clk_disable(mtk_crtc->mmsys_dev[mtk_crtc->ddp_comp_sys[i]],
+ mtk_crtc->ddp_comp[i]->id);
+ }
return ret;
}
static void mtk_crtc_ddp_clk_disable(struct mtk_crtc *mtk_crtc)
{
int i;
+ enum mtk_drm_mmsys mmsys;
- for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
+ for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
mtk_ddp_comp_clk_disable(mtk_crtc->ddp_comp[i]);
+ if (mtk_ddp_comp_get_type(mtk_crtc->ddp_comp[i]->id) == MTK_DISP_VIRTUAL) {
+ mmsys = mtk_crtc->ddp_comp_sys[i];
+ mtk_mmsys_ddp_clk_disable(mtk_crtc->mmsys_dev[mmsys],
+ mtk_crtc->ddp_comp[i]->id);
+ }
+ }
}
static
@@ -340,7 +370,8 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
struct drm_connector_list_iter conn_iter;
unsigned int width, height, vrefresh, bpc = MTK_MAX_BPC;
int ret;
- int i;
+ int i, j;
+ enum mtk_drm_mmsys mmsys;
if (WARN_ON(!crtc->state))
return -EINVAL;
@@ -370,10 +401,18 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
return ret;
}
- ret = mtk_mutex_prepare(mtk_crtc->mutex);
- if (ret < 0) {
- DRM_ERROR("Failed to enable mutex clock: %d\n", ret);
- goto err_pm_runtime_put;
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i])
+ mtk_mmsys_top_clk_enable(mtk_crtc->mmsys_dev[i]);
+
+ for (i = 0; i < MAX_MMSYS; i++) {
+ if (!mtk_crtc->mutex[i] || !mtk_crtc->exist[i])
+ continue;
+ ret = mtk_mutex_prepare(mtk_crtc->mutex[i]);
+ if (ret < 0) {
+ DRM_ERROR("Failed to enable mmsys%d mutex clock: %d\n", i, ret);
+ goto err_pm_runtime_put;
+ }
}
ret = mtk_crtc_ddp_clk_enable(mtk_crtc);
@@ -382,19 +421,36 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
goto err_mutex_unprepare;
}
+ if (mtk_crtc->vdisp_ao_dev)
+ mtk_mmsys_default_config(mtk_crtc->vdisp_ao_dev);
+
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i])
+ mtk_mmsys_default_config(mtk_crtc->mmsys_dev[i]);
+
for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
- if (!mtk_ddp_comp_connect(mtk_crtc->ddp_comp[i], mtk_crtc->mmsys_dev,
+ mmsys = mtk_crtc->ddp_comp_sys[i];
+ if (!mtk_ddp_comp_connect(mtk_crtc->ddp_comp[i], mtk_crtc->mmsys_dev[mmsys],
mtk_crtc->ddp_comp[i + 1]->id))
- mtk_mmsys_ddp_connect(mtk_crtc->mmsys_dev,
+ mtk_mmsys_ddp_connect(mtk_crtc->mmsys_dev[mmsys],
mtk_crtc->ddp_comp[i]->id,
mtk_crtc->ddp_comp[i + 1]->id);
- if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
- mtk_mutex_add_comp(mtk_crtc->mutex,
+ if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex[mmsys]))
+ mtk_mutex_add_comp(mtk_crtc->mutex[mmsys],
mtk_crtc->ddp_comp[i]->id);
}
- if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
- mtk_mutex_add_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
- mtk_mutex_enable(mtk_crtc->mutex);
+ mmsys = mtk_crtc->ddp_comp_sys[i];
+ if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex[mmsys]))
+ mtk_mutex_add_comp(mtk_crtc->mutex[mmsys], mtk_crtc->ddp_comp[i]->id);
+
+ /* Need to set sof source for all mmsys mutexes in this crtc */
+ for (j = 0; j < MAX_MMSYS; j++)
+ if (mtk_crtc->exist[j] && mtk_crtc->mutex[j])
+ mtk_mutex_add_comp_sof(mtk_crtc->mutex[j], mtk_crtc->ddp_comp[i]->id);
+
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+ mtk_mutex_enable(mtk_crtc->mutex[i]);
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[i];
@@ -402,7 +458,11 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
if (i == 1)
mtk_ddp_comp_bgclr_in_on(comp);
- mtk_ddp_comp_config(comp, width, height, vrefresh, bpc, NULL);
+ if (mtk_ddp_comp_get_type(comp->id) == MTK_DISP_VIRTUAL)
+ mtk_mmsys_ddp_config(mtk_crtc->mmsys_dev[mtk_crtc->ddp_comp_sys[i]],
+ comp->id, width, height, NULL);
+ else
+ mtk_ddp_comp_config(comp, width, height, vrefresh, bpc, NULL);
mtk_ddp_comp_start(comp);
}
@@ -426,7 +486,10 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
return 0;
err_mutex_unprepare:
- mtk_mutex_unprepare(mtk_crtc->mutex);
+ while (--i >= 0)
+ if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+ mtk_mutex_unprepare(mtk_crtc->mutex[i]);
+
err_pm_runtime_put:
pm_runtime_put(crtc->dev->dev);
return ret;
@@ -437,7 +500,8 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_crtc *mtk_crtc)
struct drm_device *drm = mtk_crtc->base.dev;
struct drm_crtc *crtc = &mtk_crtc->base;
unsigned long flags;
- int i;
+ int i, j;
+ enum mtk_drm_mmsys mmsys;
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
mtk_ddp_comp_stop(mtk_crtc->ddp_comp[i]);
@@ -445,27 +509,47 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_crtc *mtk_crtc)
mtk_ddp_comp_bgclr_in_off(mtk_crtc->ddp_comp[i]);
}
- for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
- if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
- mtk_mutex_remove_comp(mtk_crtc->mutex,
+ for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
+ mmsys = mtk_crtc->ddp_comp_sys[i];
+ if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex[mmsys]))
+ mtk_mutex_remove_comp(mtk_crtc->mutex[mtk_crtc->ddp_comp_sys[i]],
mtk_crtc->ddp_comp[i]->id);
- mtk_mutex_disable(mtk_crtc->mutex);
+ }
for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
- if (!mtk_ddp_comp_disconnect(mtk_crtc->ddp_comp[i], mtk_crtc->mmsys_dev,
- mtk_crtc->ddp_comp[i + 1]->id))
- mtk_mmsys_ddp_disconnect(mtk_crtc->mmsys_dev,
- mtk_crtc->ddp_comp[i]->id,
- mtk_crtc->ddp_comp[i + 1]->id);
- if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
- mtk_mutex_remove_comp(mtk_crtc->mutex,
+ struct mtk_ddp_comp *comp;
+ unsigned int curr, next;
+
+ comp = mtk_crtc->ddp_comp[i];
+ curr = mtk_crtc->ddp_comp[i]->id;
+ next = mtk_crtc->ddp_comp[i + 1]->id;
+ mmsys = mtk_crtc->ddp_comp_sys[i];
+ if (!mtk_ddp_comp_disconnect(comp, mtk_crtc->mmsys_dev[mmsys], next))
+ mtk_mmsys_ddp_disconnect(mtk_crtc->mmsys_dev[mmsys], curr, next);
+ if (!mtk_ddp_comp_remove(comp, mtk_crtc->mutex[mmsys]))
+ mtk_mutex_remove_comp(mtk_crtc->mutex[mtk_crtc->ddp_comp_sys[i]],
mtk_crtc->ddp_comp[i]->id);
+
}
- if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
- mtk_mutex_remove_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
+
+ mmsys = mtk_crtc->ddp_comp_sys[i];
+ if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex[mmsys]))
+ mtk_mutex_remove_comp(mtk_crtc->mutex[mmsys], mtk_crtc->ddp_comp[i]->id);
+
+ /* Need to remove sof source for all mmsys mutexes in this crtc */
+ for (j = 0; j < MAX_MMSYS; j++)
+ if (mtk_crtc->exist[j] && mtk_crtc->mutex[j])
+ mtk_mutex_remove_comp_sof(mtk_crtc->mutex[j], mtk_crtc->ddp_comp[i]->id);
+
mtk_crtc_ddp_clk_disable(mtk_crtc);
- mtk_mutex_unprepare(mtk_crtc->mutex);
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+ mtk_mutex_unprepare(mtk_crtc->mutex[i]);
- pm_runtime_put(drm->dev);
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i])
+ mtk_mmsys_top_clk_disable(mtk_crtc->mmsys_dev[i]);
+
+ pm_runtime_put_sync(drm->dev);
if (crtc->state->event && !crtc->state->active) {
spin_lock_irqsave(&crtc->dev->event_lock, flags);
@@ -589,9 +673,15 @@ static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank)
mtk_crtc->pending_async_planes = true;
if (priv->data->shadow_register) {
- mtk_mutex_acquire(mtk_crtc->mutex);
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+ mtk_mutex_acquire(mtk_crtc->mutex[i]);
+
mtk_crtc_ddp_config(crtc, NULL);
- mtk_mutex_release(mtk_crtc->mutex);
+
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+ mtk_mutex_release(mtk_crtc->mutex[i]);
}
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
if (mtk_crtc->cmdq_client.chan) {
@@ -675,6 +765,7 @@ static void mtk_crtc_update_output(struct drm_crtc *crtc,
{
int crtc_index = drm_crtc_index(crtc);
int i;
+ unsigned int mmsys;
struct device *dev;
struct drm_crtc_state *crtc_state = state->crtcs[crtc_index].new_state;
struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
@@ -687,7 +778,8 @@ static void mtk_crtc_update_output(struct drm_crtc *crtc,
if (!mtk_crtc->num_conn_routes)
return;
- priv = ((struct mtk_drm_private *)crtc->dev->dev_private)->all_drm_private[crtc_index];
+ mmsys = mtk_crtc->conn_routes_sys;
+ priv = ((struct mtk_drm_private *)crtc->dev->dev_private)->all_drm_private[mmsys];
dev = priv->dev;
dev_dbg(dev, "connector change:%d, encoder mask:0x%x for crtc:%d\n",
@@ -700,6 +792,8 @@ static void mtk_crtc_update_output(struct drm_crtc *crtc,
if (comp->encoder_index >= 0 &&
(encoder_mask & BIT(comp->encoder_index))) {
mtk_crtc->ddp_comp[mtk_crtc->ddp_comp_nr - 1] = comp;
+ mtk_crtc->ddp_comp_sys[mtk_crtc->ddp_comp_nr - 1] = mmsys;
+ mtk_crtc->exist[mmsys] = true;
dev_dbg(dev, "Add comp_id: %d at path index %d\n",
comp->id, mtk_crtc->ddp_comp_nr - 1);
break;
@@ -736,9 +830,31 @@ static void mtk_crtc_atomic_enable(struct drm_crtc *crtc,
struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
int ret;
+ int i, j;
+ int mmsys_cnt = 0;
DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i])
+ mmsys_cnt++;
+
+ if (mmsys_cnt > 1) {
+ for (i = 0; i < MAX_MMSYS; i++) {
+ if (!mtk_crtc->exist[i])
+ continue;
+ ret = pm_runtime_resume_and_get(mtk_crtc->mmsys_dev[i]);
+ if (ret < 0) {
+ DRM_DEV_ERROR(mtk_crtc->mmsys_dev[i],
+ "Failed to enable power domain: %d\n", ret);
+ for (j = i - 1; j >= 0; j--)
+ if (mtk_crtc->exist[i])
+ pm_runtime_put(mtk_crtc->mmsys_dev[j]);
+ return;
+ }
+ }
+ }
+
ret = mtk_ddp_comp_power_on(comp);
if (ret < 0) {
DRM_DEV_ERROR(comp->dev, "Failed to enable power domain: %d\n", ret);
@@ -762,7 +878,8 @@ static void mtk_crtc_atomic_disable(struct drm_crtc *crtc,
{
struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
- int i;
+ int i, ret;
+ int mmsys_cnt = 0;
DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
if (!mtk_crtc->enabled)
@@ -794,6 +911,22 @@ static void mtk_crtc_atomic_disable(struct drm_crtc *crtc,
mtk_crtc_ddp_hw_fini(mtk_crtc);
mtk_ddp_comp_power_off(comp);
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i])
+ mmsys_cnt++;
+
+ if (mmsys_cnt > 1) {
+ for (i = 0; i < MAX_MMSYS; i++) {
+ if (mtk_crtc->exist[i]) {
+ ret = pm_runtime_put(mtk_crtc->mmsys_dev[i]);
+ if (ret < 0)
+ DRM_DEV_ERROR(mtk_crtc->mmsys_dev[i],
+ "Failed to disable power domain: %d\n",
+ ret);
+ }
+ }
+ }
+
mtk_crtc->enabled = false;
}
@@ -953,49 +1086,108 @@ struct device *mtk_crtc_dma_dev_get(struct drm_crtc *crtc)
return mtk_crtc->dma_dev;
}
-int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
- unsigned int path_len, int priv_data_index,
- const struct mtk_drm_route *conn_routes,
- unsigned int num_conn_routes)
+int mtk_crtc_create(struct drm_device *drm_dev, enum mtk_crtc_path path_sel)
{
struct mtk_drm_private *priv = drm_dev->dev_private;
struct device *dev = drm_dev->dev;
struct mtk_crtc *mtk_crtc;
unsigned int num_comp_planes = 0;
int ret;
- int i;
+ int i, j, k;
bool has_ctm = false;
uint gamma_lut_size = 0;
struct drm_crtc *tmp;
int crtc_i = 0;
-
- if (!path)
- return 0;
-
- priv = priv->all_drm_private[priv_data_index];
+ struct mtk_drm_private *subsys_priv;
+ struct mtk_crtc_comp_info path[DDP_COMPONENT_ID_MAX];
+ unsigned int path_len = 0;
+ const struct mtk_drm_route *conn_routes = NULL;
+ unsigned int num_conn_routes = 0;
+ enum mtk_drm_mmsys conn_mmsys;
drm_for_each_crtc(tmp, drm_dev)
crtc_i++;
+ for (j = 0; j < priv->data->mmsys_dev_num; j++) {
+ for (k = 0; k < MAX_MMSYS; k++) {
+ const unsigned int *subsys_path;
+ unsigned int subsys_path_len = 0;
+ unsigned int order = 0;
+
+ subsys_priv = priv->all_drm_private[k];
+ if (!subsys_priv)
+ continue;
+
+ if (path_sel == CRTC_MAIN) {
+ subsys_path = subsys_priv->data->main_path;
+ subsys_path_len = subsys_priv->data->main_len;
+ order = subsys_priv->data->main_order;
+ } else if (path_sel == CRTC_EXT) {
+ subsys_path = subsys_priv->data->ext_path;
+ subsys_path_len = subsys_priv->data->ext_len;
+ order = subsys_priv->data->ext_order;
+ } else if (path_sel == CRTC_THIRD) {
+ subsys_path = subsys_priv->data->third_path;
+ subsys_path_len = subsys_priv->data->third_len;
+ order = subsys_priv->data->third_order;
+ }
+
+ if (subsys_priv->data->num_conn_routes) {
+ conn_routes = subsys_priv->data->conn_routes;
+ num_conn_routes = subsys_priv->data->num_conn_routes;
+ conn_mmsys = subsys_priv->data->mmsys_id;
+ }
+
+ if (j != order)
+ continue;
+ if (!subsys_path_len)
+ continue;
+
+ for (i = 0; i < subsys_path_len; i++) {
+ path[path_len].sys = subsys_priv->data->mmsys_id;
+ path[path_len].comp_id = subsys_path[i];
+ path_len++;
+ }
+ }
+ }
+
+ if (!path_len)
+ return 0;
+
+ if (num_conn_routes) {
+ for (i = 0; i < num_conn_routes; i++)
+ if (conn_routes->crtc_id == crtc_i)
+ break;
+ if (i == num_conn_routes) {
+ num_conn_routes = 0;
+ conn_routes = NULL;
+ }
+ }
+
for (i = 0; i < path_len; i++) {
- enum mtk_ddp_comp_id comp_id = path[i];
+ enum mtk_ddp_comp_id comp_id = path[i].comp_id;
struct device_node *node;
struct mtk_ddp_comp *comp;
+ priv = priv->all_drm_private[path[i].sys];
node = priv->comp_node[comp_id];
comp = &priv->ddp_comp[comp_id];
/* Not all drm components have a DTS device node, such as ovl_adaptor,
* which is the drm bring up sub driver
*/
- if (!node && comp_id != DDP_COMPONENT_DRM_OVL_ADAPTOR) {
+ if (!node && comp_id != DDP_COMPONENT_DRM_OVL_ADAPTOR &&
+ comp_id != DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 &&
+ comp_id != DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 &&
+ comp_id != DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2 &&
+ mtk_ddp_comp_get_type(comp_id) != MTK_DISP_VIRTUAL) {
dev_info(dev,
"Not creating crtc %d because component %d is disabled or missing\n",
crtc_i, comp_id);
return 0;
}
- if (!comp->dev) {
+ if (!comp->dev && mtk_ddp_comp_get_type(comp_id) != MTK_DISP_VIRTUAL) {
dev_err(dev, "Component %pOF not initialized\n", node);
return -ENODEV;
}
@@ -1005,7 +1197,9 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
if (!mtk_crtc)
return -ENOMEM;
- mtk_crtc->mmsys_dev = priv->mmsys_dev;
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (priv->all_drm_private[i])
+ mtk_crtc->mmsys_dev[i] = priv->all_drm_private[i]->mmsys_dev;
mtk_crtc->ddp_comp_nr = path_len;
mtk_crtc->ddp_comp = devm_kcalloc(dev,
mtk_crtc->ddp_comp_nr + (conn_routes ? 1 : 0),
@@ -1014,19 +1208,36 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
if (!mtk_crtc->ddp_comp)
return -ENOMEM;
- mtk_crtc->mutex = mtk_mutex_get(priv->mutex_dev);
- if (IS_ERR(mtk_crtc->mutex)) {
- ret = PTR_ERR(mtk_crtc->mutex);
- dev_err(dev, "Failed to get mutex: %d\n", ret);
- return ret;
+ mtk_crtc->ddp_comp_sys = devm_kmalloc_array(dev, mtk_crtc->ddp_comp_nr +
+ (conn_routes ? 1 : 0),
+ sizeof(*mtk_crtc->ddp_comp_sys), GFP_KERNEL);
+ if (!mtk_crtc->ddp_comp_sys)
+ return -ENOMEM;
+
+ for (i = 0; i < MAX_MMSYS; i++) {
+ if (!priv->all_drm_private[i])
+ continue;
+
+ priv = priv->all_drm_private[i];
+ mtk_crtc->mutex[i] = mtk_mutex_get(priv->mutex_dev);
+ if (IS_ERR(mtk_crtc->mutex[i])) {
+ ret = PTR_ERR(mtk_crtc->mutex[i]);
+ dev_err(dev, "Failed to get mutex: %d\n", ret);
+ return ret;
+ }
}
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
- unsigned int comp_id = path[i];
+ unsigned int comp_id = path[i].comp_id;
struct mtk_ddp_comp *comp;
+ priv = priv->all_drm_private[path[i].sys];
comp = &priv->ddp_comp[comp_id];
+ if (mtk_ddp_comp_get_type(comp_id) == MTK_DISP_VIRTUAL)
+ comp->id = comp_id;
mtk_crtc->ddp_comp[i] = comp;
+ mtk_crtc->ddp_comp_sys[i] = path[i].sys;
+ mtk_crtc->exist[path[i].sys] = true;
if (comp->funcs) {
if (comp->funcs->gamma_set && comp->funcs->gamma_get_lut_size) {
@@ -1063,8 +1274,10 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
* In the case of ovl_adaptor sub driver, it needs to use the
* dma_dev_get function to get representative dma dev.
*/
- mtk_crtc->dma_dev = mtk_ddp_comp_dma_dev_get(&priv->ddp_comp[path[0]]);
+ priv = priv->all_drm_private[path[0].sys];
+ mtk_crtc->dma_dev = mtk_ddp_comp_dma_dev_get(&priv->ddp_comp[path[0].comp_id]);
+ mtk_crtc->vdisp_ao_dev = priv->vdisp_ao_dev;
ret = mtk_crtc_init(drm_dev, mtk_crtc, crtc_i);
if (ret < 0)
return ret;
@@ -1077,7 +1290,7 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
i = priv->mbox_index++;
- mtk_crtc->cmdq_client.client.dev = mtk_crtc->mmsys_dev;
+ mtk_crtc->cmdq_client.client.dev = mtk_crtc->mmsys_dev[priv->data->mmsys_id];
mtk_crtc->cmdq_client.client.tx_block = false;
mtk_crtc->cmdq_client.client.knows_txdone = true;
mtk_crtc->cmdq_client.client.rx_callback = ddp_cmdq_cb;
@@ -1117,6 +1330,7 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
#endif
if (conn_routes) {
+ priv = priv->all_drm_private[conn_mmsys];
for (i = 0; i < num_conn_routes; i++) {
unsigned int comp_id = conn_routes[i].route_ddp;
struct device_node *node = priv->comp_node[comp_id];
@@ -1133,6 +1347,7 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
mtk_ddp_comp_encoder_index_set(&priv->ddp_comp[comp_id]);
}
+ mtk_crtc->conn_routes_sys = conn_mmsys;
mtk_crtc->num_conn_routes = num_conn_routes;
mtk_crtc->conn_routes = conn_routes;
@@ -1140,5 +1355,10 @@ int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
mtk_crtc->ddp_comp_nr++;
}
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i])
+ device_link_add(mtk_crtc->base.dev->dev,
+ priv->all_drm_private[i]->mutex_dev, 0);
+
return 0;
}
diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.h b/drivers/gpu/drm/mediatek/mtk_crtc.h
index 388e900b6f4d..255f2823d17a 100644
--- a/drivers/gpu/drm/mediatek/mtk_crtc.h
+++ b/drivers/gpu/drm/mediatek/mtk_crtc.h
@@ -15,10 +15,8 @@
#define MTK_MIN_BPC 3
void mtk_crtc_commit(struct drm_crtc *crtc);
-int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path,
- unsigned int path_len, int priv_data_index,
- const struct mtk_drm_route *conn_routes,
- unsigned int num_conn_routes);
+int mtk_crtc_create(struct drm_device *drm_dev,
+ enum mtk_crtc_path path_sel);
int mtk_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane,
struct mtk_plane_state *state);
void mtk_crtc_async_update(struct drm_crtc *crtc, struct drm_plane *plane,
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index c96e027359ac..6628f5cd732a 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -467,6 +467,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
[MTK_DISP_PWM] = "pwm",
[MTK_DISP_RDMA] = "rdma",
[MTK_DISP_UFOE] = "ufoe",
+ [MTK_DISP_VIRTUAL] = "virtual",
[MTK_DISP_WDMA] = "wdma",
[MTK_DP_INTF] = "dp-intf",
[MTK_DPI] = "dpi",
@@ -490,6 +491,15 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
[DDP_COMPONENT_COLOR0] = { MTK_DISP_COLOR, 0, &ddp_color },
[DDP_COMPONENT_COLOR1] = { MTK_DISP_COLOR, 1, &ddp_color },
[DDP_COMPONENT_DITHER0] = { MTK_DISP_DITHER, 0, &ddp_dither },
+ [DDP_COMPONENT_DLI_ASYNC0] = { MTK_DISP_VIRTUAL, -1, NULL },
+ [DDP_COMPONENT_DLI_ASYNC1] = { MTK_DISP_VIRTUAL, -1, NULL },
+ [DDP_COMPONENT_DLI_ASYNC8] = { MTK_DISP_VIRTUAL, -1, NULL },
+ [DDP_COMPONENT_DLI_ASYNC21] = { MTK_DISP_VIRTUAL, -1, NULL },
+ [DDP_COMPONENT_DLI_ASYNC22] = { MTK_DISP_VIRTUAL, -1, NULL },
+ [DDP_COMPONENT_DLI_ASYNC23] = { MTK_DISP_VIRTUAL, -1, NULL },
+ [DDP_COMPONENT_DLO_ASYNC1] = { MTK_DISP_VIRTUAL, -1, NULL },
+ [DDP_COMPONENT_DLO_ASYNC2] = { MTK_DISP_VIRTUAL, -1, NULL },
+ [DDP_COMPONENT_DLO_ASYNC3] = { MTK_DISP_VIRTUAL, -1, NULL },
[DDP_COMPONENT_DP_INTF0] = { MTK_DP_INTF, 0, &ddp_dpi },
[DDP_COMPONENT_DP_INTF1] = { MTK_DP_INTF, 1, &ddp_dpi },
[DDP_COMPONENT_DPI0] = { MTK_DPI, 0, &ddp_dpi },
@@ -497,6 +507,7 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
[DDP_COMPONENT_DRM_OVL_ADAPTOR] = { MTK_DISP_OVL_ADAPTOR, 0, &ddp_ovl_adaptor },
[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0] = { MTK_DISP_OVLSYS_ADAPTOR, 0, &ddp_ovlsys_adaptor},
[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1] = { MTK_DISP_OVLSYS_ADAPTOR, 1, &ddp_ovlsys_adaptor},
+ [DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2] = { MTK_DISP_OVLSYS_ADAPTOR, 2, &ddp_ovlsys_adaptor},
[DDP_COMPONENT_DSC0] = { MTK_DISP_DSC, 0, &ddp_dsc },
[DDP_COMPONENT_DSC1] = { MTK_DISP_DSC, 1, &ddp_dsc },
[DDP_COMPONENT_DSI0] = { MTK_DSI, 0, &ddp_dsi },
@@ -513,7 +524,10 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
[DDP_COMPONENT_OD0] = { MTK_DISP_OD, 0, &ddp_od },
[DDP_COMPONENT_OD1] = { MTK_DISP_OD, 1, &ddp_od },
[DDP_COMPONENT_OVL0] = { MTK_DISP_OVL, 0, &ddp_ovl },
+ [DDP_COMPONENT_OVL0_DLO_ASYNC5] = { MTK_DISP_VIRTUAL, -1, NULL },
+ [DDP_COMPONENT_OVL0_DLO_ASYNC6] = { MTK_DISP_VIRTUAL, -1, NULL },
[DDP_COMPONENT_OVL1] = { MTK_DISP_OVL, 1, &ddp_ovl },
+ [DDP_COMPONENT_OVL1_DLO_ASYNC5] = { MTK_DISP_VIRTUAL, -1, NULL },
[DDP_COMPONENT_OVL_2L0] = { MTK_DISP_OVL_2L, 0, &ddp_ovl },
[DDP_COMPONENT_OVL_2L1] = { MTK_DISP_OVL_2L, 1, &ddp_ovl },
[DDP_COMPONENT_OVL_2L2] = { MTK_DISP_OVL_2L, 2, &ddp_ovl },
@@ -564,27 +578,6 @@ static int mtk_ddp_comp_find_in_route(struct device *dev,
return -ENODEV;
}
-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)
- continue;
-
- if (!comp_node[path[i]])
- return false;
- }
-
- return true;
-}
-
int mtk_ddp_comp_get_id(struct device_node *node,
enum mtk_ddp_comp_type comp_type)
{
@@ -600,53 +593,36 @@ int mtk_ddp_comp_get_id(struct device_node *node,
return -EINVAL;
}
+enum mtk_ddp_comp_type mtk_ddp_comp_get_type(unsigned int comp_id)
+{
+ return mtk_ddp_matches[comp_id].type;
+}
+
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;
- 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++;
- }
- }
-
- ret = mtk_ddp_comp_find_in_route(dev,
- private->data->conn_routes,
- private->data->num_conn_routes,
- private->ddp_comp);
-
- if (ret < 0)
- DRM_INFO("Failed to find comp in ddp table, ret = %d\n", ret);
+ if (mtk_ddp_comp_find(dev,
+ private->data->main_path,
+ private->data->main_len,
+ private->ddp_comp))
+ ret = BIT(0);
+ else if (mtk_ddp_comp_find(dev,
+ private->data->ext_path,
+ private->data->ext_len,
+ private->ddp_comp))
+ ret = BIT(1);
+ else if (mtk_ddp_comp_find(dev,
+ private->data->third_path,
+ private->data->third_len,
+ private->ddp_comp))
+ ret = BIT(2);
+ else
+ ret = mtk_ddp_comp_find_in_route(dev,
+ private->data->conn_routes,
+ private->data->num_conn_routes,
+ private->ddp_comp);
return ret;
}
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
index ef64ce7a071f..badb42bd4f7c 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
@@ -40,6 +40,7 @@ enum mtk_ddp_comp_type {
MTK_DISP_PWM,
MTK_DISP_RDMA,
MTK_DISP_UFOE,
+ MTK_DISP_VIRTUAL,
MTK_DISP_WDMA,
MTK_DPI,
MTK_DP_INTF,
@@ -47,6 +48,7 @@ enum mtk_ddp_comp_type {
MTK_OVL_BLENDER,
MTK_OVL_EXDMA,
MTK_OVL_OUTPROC,
+ MTK_VDISP_AO,
MTK_DDP_COMP_TYPE_MAX,
};
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 0639201e2e92..b9c6a2a657ea 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -374,7 +374,7 @@ static int mtk_drm_match(struct device *dev, const void *data)
static bool mtk_drm_get_all_drm_priv(struct device *dev)
{
struct mtk_drm_private *drm_priv = dev_get_drvdata(dev);
- struct mtk_drm_private *all_drm_priv[MAX_CRTC];
+ struct mtk_drm_private *all_drm_priv[MAX_MMSYS] = {NULL};
struct mtk_drm_private *temp_drm_priv;
struct device_node *phandle = dev->parent->of_node;
const struct of_device_id *of_id;
@@ -402,26 +402,22 @@ static bool mtk_drm_get_all_drm_priv(struct device *dev)
if (!temp_drm_priv)
continue;
- if (temp_drm_priv->data->main_len)
- all_drm_priv[CRTC_MAIN] = temp_drm_priv;
- else if (temp_drm_priv->data->ext_len)
- all_drm_priv[CRTC_EXT] = temp_drm_priv;
- else if (temp_drm_priv->data->third_len)
- all_drm_priv[CRTC_THIRD] = temp_drm_priv;
+ all_drm_priv[temp_drm_priv->data->mmsys_id] = temp_drm_priv;
if (temp_drm_priv->mtk_drm_bound)
cnt++;
- if (cnt == MAX_CRTC) {
+ if (cnt == temp_drm_priv->data->mmsys_dev_num) {
of_node_put(node);
break;
}
}
if (drm_priv->data->mmsys_dev_num == cnt) {
- for (i = 0; i < cnt; i++)
- for (j = 0; j < cnt; j++)
- all_drm_priv[j]->all_drm_private[i] = all_drm_priv[i];
+ for (i = 0; i < MAX_MMSYS; i++)
+ for (j = 0; j < MAX_MMSYS; j++)
+ if (all_drm_priv[j])
+ all_drm_priv[j]->all_drm_private[i] = all_drm_priv[i];
return true;
}
@@ -506,7 +502,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)
@@ -529,8 +528,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;
@@ -542,28 +543,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;
}
}
}
@@ -582,8 +578,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
@@ -601,11 +598,13 @@ static int mtk_drm_kms_init(struct drm_device *drm)
return 0;
err_component_unbind:
- for (i = 0; i < private->data->mmsys_dev_num; i++)
- component_unbind_all(private->all_drm_private[i]->dev, drm);
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (private->all_drm_private[i])
+ component_unbind_all(private->all_drm_private[i]->dev, drm);
put_mutex_dev:
- for (i = 0; i < private->data->mmsys_dev_num; i++)
- put_device(private->all_drm_private[i]->mutex_dev);
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (private->all_drm_private[i])
+ put_device(private->all_drm_private[i]->mutex_dev);
return ret;
}
@@ -669,6 +668,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;
@@ -681,8 +693,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)
@@ -1125,7 +1138,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)
@@ -1220,6 +1233,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",
@@ -1295,6 +1314,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 6e9ed9837c5b..6a6d689345b1 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -13,7 +13,8 @@
#define DDP_COMPONENT_DRM_OVL_ADAPTOR (DDP_COMPONENT_ID_MAX + 1)
#define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 (DDP_COMPONENT_DRM_OVL_ADAPTOR + 1)
#define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 + 1)
-#define DDP_COMPONENT_DRM_ID_MAX (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 + 1)
+#define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2 (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 + 1)
+#define DDP_COMPONENT_DRM_ID_MAX (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2 + 1)
enum mtk_crtc_path {
CRTC_MAIN,
@@ -22,6 +23,14 @@ enum mtk_crtc_path {
MAX_CRTC,
};
+enum mtk_drm_mmsys {
+ DISPSYS0,
+ DISPSYS1,
+ OVLSYS0,
+ OVLSYS1,
+ MAX_MMSYS,
+};
+
struct device;
struct device_node;
struct drm_crtc;
@@ -38,10 +47,13 @@ struct mtk_drm_route {
struct mtk_mmsys_driver_data {
const unsigned int *main_path;
unsigned int main_len;
+ unsigned int main_order;
const unsigned int *ext_path;
unsigned int ext_len;
+ unsigned int ext_order;
const unsigned int *third_path;
unsigned int third_len;
+ unsigned int third_order;
const struct mtk_drm_route *conn_routes;
unsigned int num_conn_routes;
@@ -63,6 +75,8 @@ struct mtk_drm_private {
struct device_node *mutex_node;
struct device *mutex_dev;
struct device *mmsys_dev;
+ struct device_node *vdisp_ao_node;
+ struct device *vdisp_ao_dev;
struct device_node *comp_node[DDP_COMPONENT_DRM_ID_MAX];
struct mtk_ddp_comp ddp_comp[DDP_COMPONENT_DRM_ID_MAX];
struct mtk_mmsys_driver_data *data;
--
2.45.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [PATCH v2 15/15] drm/mediatek: Add support for MT8196 multiple mmsys
2025-03-21 9:33 [PATCH v2 00/15] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
` (13 preceding siblings ...)
2025-03-21 9:33 ` [PATCH v2 14/15] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver paul-pl.chen
@ 2025-03-21 9:33 ` paul-pl.chen
14 siblings, 0 replies; 42+ messages in thread
From: paul-pl.chen @ 2025-03-21 9:33 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 b9c6a2a657ea..70a7e6d06d4f 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -193,6 +193,10 @@ static const struct mtk_drm_route mt8188_mtk_ddp_main_routes[] = {
{0, DDP_COMPONENT_DSI0},
};
+static const struct mtk_drm_route mt8196_mtk_ddp_routes[] = {
+ {2, DDP_COMPONENT_DSI0},
+};
+
static const unsigned int mt8192_mtk_ddp_main[] = {
DDP_COMPONENT_OVL0,
DDP_COMPONENT_OVL_2L0,
@@ -231,6 +235,50 @@ static const unsigned int mt8195_mtk_ddp_ext[] = {
DDP_COMPONENT_DP_INTF1,
};
+static const unsigned int mt8196_mtk_ddp_ovl0_main[] = {
+ DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0,
+ DDP_COMPONENT_OVL0_DLO_ASYNC5,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp0_main[] = {
+ DDP_COMPONENT_DLI_ASYNC0,
+ DDP_COMPONENT_DLO_ASYNC1,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp1_main[] = {
+ DDP_COMPONENT_DLI_ASYNC21,
+ DDP_COMPONENT_DVO0,
+};
+
+static const unsigned int mt8196_mtk_ddp_ovl0_ext[] = {
+ DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1,
+ DDP_COMPONENT_OVL0_DLO_ASYNC6,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp0_ext[] = {
+ DDP_COMPONENT_DLI_ASYNC1,
+ DDP_COMPONENT_DLO_ASYNC2,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp1_ext[] = {
+ DDP_COMPONENT_DLI_ASYNC22,
+ DDP_COMPONENT_DP_INTF0,
+};
+
+static const unsigned int mt8196_mtk_ddp_ovl1_third[] = {
+ DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2,
+ DDP_COMPONENT_OVL1_DLO_ASYNC5,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp0_third[] = {
+ DDP_COMPONENT_DLI_ASYNC8,
+ DDP_COMPONENT_DLO_ASYNC3,
+};
+
+static const unsigned int mt8196_mtk_ddp_disp1_third[] = {
+ DDP_COMPONENT_DLI_ASYNC23,
+};
+
static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
.main_path = mt2701_mtk_ddp_main,
.main_len = ARRAY_SIZE(mt2701_mtk_ddp_main),
@@ -327,8 +375,65 @@ static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data = {
.min_height = 1,
};
-static const struct mtk_mmsys_driver_data mt8365_mmsys_driver_data = {
- .mmsys_dev_num = 1,
+static const struct mtk_mmsys_driver_data mt8196_dispsys0_driver_data = {
+ .main_path = mt8196_mtk_ddp_disp0_main,
+ .main_len = ARRAY_SIZE(mt8196_mtk_ddp_disp0_main),
+ .main_order = 1,
+ .ext_path = mt8196_mtk_ddp_disp0_ext,
+ .ext_len = ARRAY_SIZE(mt8196_mtk_ddp_disp0_ext),
+ .ext_order = 1,
+ .third_path = mt8196_mtk_ddp_disp0_third,
+ .third_len = ARRAY_SIZE(mt8196_mtk_ddp_disp0_third),
+ .third_order = 1,
+ .mmsys_id = DISPSYS0,
+ .mmsys_dev_num = 4,
+ .max_width = 8191,
+ .min_width = 2, /* 2-pixel align when ethdr is bypassed */
+ .min_height = 1,
+};
+
+static const struct mtk_mmsys_driver_data mt8196_dispsys1_driver_data = {
+ .main_path = mt8196_mtk_ddp_disp1_main,
+ .main_len = ARRAY_SIZE(mt8196_mtk_ddp_disp1_main),
+ .main_order = 2,
+ .ext_path = mt8196_mtk_ddp_disp1_ext,
+ .ext_len = ARRAY_SIZE(mt8196_mtk_ddp_disp1_ext),
+ .ext_order = 2,
+ .third_path = mt8196_mtk_ddp_disp1_third,
+ .third_len = ARRAY_SIZE(mt8196_mtk_ddp_disp1_third),
+ .conn_routes = mt8196_mtk_ddp_routes,
+ .num_conn_routes = ARRAY_SIZE(mt8196_mtk_ddp_routes),
+ .third_order = 2,
+ .mmsys_id = DISPSYS1,
+ .mmsys_dev_num = 4,
+ .max_width = 8191,
+ .min_width = 2, /* 2-pixel align when ethdr is bypassed */
+ .min_height = 1,
+};
+
+static const struct mtk_mmsys_driver_data mt8196_ovlsys0_driver_data = {
+ .main_path = mt8196_mtk_ddp_ovl0_main,
+ .main_len = ARRAY_SIZE(mt8196_mtk_ddp_ovl0_main),
+ .main_order = 0,
+ .ext_path = mt8196_mtk_ddp_ovl0_ext,
+ .ext_len = ARRAY_SIZE(mt8196_mtk_ddp_ovl0_ext),
+ .ext_order = 0,
+ .mmsys_id = OVLSYS0,
+ .mmsys_dev_num = 4,
+ .max_width = 8191,
+ .min_width = 2, /* 2-pixel align when ethdr is bypassed */
+ .min_height = 1,
+};
+
+static const struct mtk_mmsys_driver_data mt8196_ovlsys1_driver_data = {
+ .third_path = mt8196_mtk_ddp_ovl1_third,
+ .third_len = ARRAY_SIZE(mt8196_mtk_ddp_ovl1_third),
+ .third_order = 0,
+ .mmsys_id = OVLSYS1,
+ .mmsys_dev_num = 4,
+ .max_width = 8191,
+ .min_width = 2, /* 2-pixel align when ethdr is bypassed */
+ .min_height = 1,
};
static const struct of_device_id mtk_drm_of_ids[] = {
@@ -358,8 +463,14 @@ static const struct of_device_id mtk_drm_of_ids[] = {
.data = &mt8195_vdosys0_driver_data},
{ .compatible = "mediatek,mt8195-vdosys1",
.data = &mt8195_vdosys1_driver_data},
- { .compatible = "mediatek,mt8365-mmsys",
- .data = &mt8365_mmsys_driver_data},
+ { .compatible = "mediatek,mt8196-dispsys0",
+ .data = &mt8196_dispsys0_driver_data},
+ { .compatible = "mediatek,mt8196-dispsys1",
+ .data = &mt8196_dispsys1_driver_data},
+ { .compatible = "mediatek,mt8196-ovlsys0",
+ .data = &mt8196_ovlsys0_driver_data},
+ { .compatible = "mediatek,mt8196-ovlsys1",
+ .data = &mt8196_ovlsys1_driver_data},
{ }
};
MODULE_DEVICE_TABLE(of, mtk_drm_of_ids);
--
2.45.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* Re: [PATCH v2 03/15] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-03-21 9:33 ` [PATCH v2 03/15] dt-bindings: display: mediatek: add EXDMA " paul-pl.chen
@ 2025-03-24 2:45 ` CK Hu (胡俊光)
2025-05-14 16:25 ` Paul-pl Chen (陳柏霖)
0 siblings, 1 reply; 42+ messages in thread
From: CK Hu (胡俊光) @ 2025-03-24 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
[-- Attachment #1: Type: text/plain, Size: 3346 bytes --]
On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> From: Paul-pl Chen <paul-pl.chen@mediatek.com>
>
> Add mediatek,exdma.yaml to support EXDMA for MT8196.
> The MediaTek display overlap extended DMA engine, namely
> OVL_EXDMA or EXDMA, primarily functions as a DMA engine
> for reading data from DRAM with various DRAM footprints
> and data formats.
>
> Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> ---
> .../bindings/dma/mediatek,exdma.yaml | 70 +++++++++++++++++++
> 1 file changed, 70 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..de7f8283bb48
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/dma/mediatek,exdma.yaml
> @@ -0,0 +1,70 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: https://urldefense.com/v3/__http://devicetree.org/schemas/dma/mediatek,exdma.yaml*__;Iw!!CTRNKA9wMg0ARbw!jH_-2I8NkTUX90vbZGjduUAo4on8DsCGFTrVX5jUdxL_zpKt5PSPRGm31otPZ4wIDzI2h9HFGbF4DC5jPw1nejo$
> +$schema: https://urldefense.com/v3/__http://devicetree.org/meta-schemas/core.yaml*__;Iw!!CTRNKA9wMg0ARbw!jH_-2I8NkTUX90vbZGjduUAo4on8DsCGFTrVX5jUdxL_zpKt5PSPRGm31otPZ4wIDzI2h9HFGbF4DC5jr1jxJoQ$
> +
> +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>;
> +
> + disp_ovl0_exdma2: dma-controller@32850000 {
> + compatible = "mediatek,mt8196-exdma";
> + reg = <0 0x32850000 0 0x1000>;
> + clocks = <&ovlsys_config_clk 13>;
> + power-domains = <&hfrpsys 12>;
> + mediatek,larb = <&smi_larb0>;
larb is controlled by iommu, and exdma has already point to iommu.
OVL also not point to larb, so it's not necessary to point to larb here.
Regards,
CK
> + iommus = <&mm_smmu 144>;
> + #dma-cells = <1>;
> + };
> + };
[-- Attachment #2: Type: text/html, Size: 6802 bytes --]
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 10/15] drm/mediatek: add EXDMA support for MT8196
2025-03-21 9:33 ` [PATCH v2 10/15] drm/mediatek: add EXDMA support for MT8196 paul-pl.chen
@ 2025-03-24 3:00 ` CK Hu (胡俊光)
2025-05-14 10:00 ` Paul-pl Chen (陳柏霖)
0 siblings, 1 reply; 42+ messages in thread
From: CK Hu (胡俊光) @ 2025-03-24 3:00 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
[-- Attachment #1: Type: text/plain, Size: 20416 bytes --]
On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> From: Nancy Lin <nancy.lin@mediatek.com>
>
> EXDMA is a DMA engine for reading data from DRAM with
> various DRAM footprints and data formats. For input
> sources in certain color formats and color domains,
> EXDMA also includes a color transfer function to
> process pixels into a consistent color domain.
> New Add: 6320385 Fix RG16 and refine RG24
>
> Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
> Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> ---
> drivers/gpu/drm/mediatek/Makefile | 1 +
> drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 1 +
> drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 1 +
> drivers/gpu/drm/mediatek/mtk_disp_drv.h | 9 +
> drivers/gpu/drm/mediatek/mtk_disp_exdma.c | 372 ++++++++++++++++++++++
> drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 +
> drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 +
> 7 files changed, 386 insertions(+)
> create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_exdma.c
>
> diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
> index 32a2ed6c0cfe..db92f4fb353d 100644
> --- a/drivers/gpu/drm/mediatek/Makefile
> +++ b/drivers/gpu/drm/mediatek/Makefile
> @@ -5,6 +5,7 @@ mediatek-drm-y := mtk_crtc.o \
> mtk_disp_aal.o \
> mtk_disp_ccorr.o \
> mtk_disp_color.o \
> + mtk_disp_exdma.o \
> mtk_disp_gamma.o \
> mtk_disp_merge.o \
> mtk_disp_ovl.o \
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> index edc6417639e6..3e0739d8e6f1 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> @@ -445,6 +445,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
> [MTK_DP_INTF] = "dp-intf",
> [MTK_DPI] = "dpi",
> [MTK_DSI] = "dsi",
> + [MTK_OVL_EXDMA] = "exdma",
> };
>
> struct mtk_ddp_comp_match {
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> index 39720b27f4e9..86dc0ee3924c 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> @@ -43,6 +43,7 @@ enum mtk_ddp_comp_type {
> MTK_DPI,
> MTK_DP_INTF,
> MTK_DSI,
> + MTK_OVL_EXDMA,
> MTK_DDP_COMP_TYPE_MAX,
> };
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> index 04217a36939c..4e3d2510bef5 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> @@ -39,6 +39,15 @@ void mtk_color_config(struct device *dev, unsigned int w,
> unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
> void mtk_color_start(struct device *dev);
>
> +int mtk_disp_exdma_clk_enable(struct device *dev);
> +void mtk_disp_exdma_clk_disable(struct device *dev);
> +void mtk_disp_exdma_start(struct device *dev, struct cmdq_pkt *cmdq_pkt);
> +void mtk_disp_exdma_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt);
> +void mtk_disp_exdma_layer_config(struct device *dev, struct mtk_plane_state *state,
> + struct cmdq_pkt *cmdq_pkt);
> +const u32 *mtk_disp_exdma_get_formats(struct device *dev);
> +size_t mtk_disp_exdma_get_num_formats(struct device *dev);
> +
> void mtk_dither_set_common(void __iomem *regs, struct cmdq_client_reg *cmdq_reg,
> unsigned int bpc, unsigned int cfg,
> unsigned int dither_en, struct cmdq_pkt *cmdq_pkt);
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_exdma.c b/drivers/gpu/drm/mediatek/mtk_disp_exdma.c
> new file mode 100644
> index 000000000000..d4f7021f98d7
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_exdma.c
> @@ -0,0 +1,372 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2025 MediaTek Inc.
> + */
> +
> +#include <drm/drm_fourcc.h>
> +#include <drm/drm_blend.h>
> +#include <drm/drm_framebuffer.h>
> +#include <linux/clk.h>
> +#include <linux/component.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/soc/mediatek/mtk-cmdq.h>
> +
> +#include "mtk_disp_drv.h"
> +#include "mtk_drm_drv.h"
> +#include "mtk_disp_ovl.h"
> +
> +#define DISP_REG_OVL_EXDMA_EN_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_OFFSET 0x044
DISP_REG_OVL_EXDMA_OFFSET is useless, so drop it.
> +#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 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)
OVL_EXDMA_MOUT_OUT_DATA is useless, so drop it.
> +#define OVL_EXDMA_MOUT_BGCLR_OUT BIT(1)
> +
> +static const u32 formats[] = {
> + DRM_FORMAT_XRGB8888,
> + DRM_FORMAT_ARGB8888,
> + DRM_FORMAT_BGRX8888,
> + DRM_FORMAT_BGRA8888,
> + DRM_FORMAT_ABGR8888,
> + DRM_FORMAT_XBGR8888,
> + DRM_FORMAT_RGBX8888,
> + DRM_FORMAT_RGBA8888,
> + DRM_FORMAT_RGB888,
> + DRM_FORMAT_BGR888,
> + DRM_FORMAT_RGB565,
> + DRM_FORMAT_BGR565,
In this version, you add BGR565. If mt8195 also support BGR565, add BGR565 to mt8195_formats[] and merge these two array.
> + DRM_FORMAT_UYVY,
> + DRM_FORMAT_YUYV,
> + DRM_FORMAT_XRGB2101010,
> + DRM_FORMAT_ARGB2101010,
> + DRM_FORMAT_RGBX1010102,
> + DRM_FORMAT_RGBA1010102,
> + DRM_FORMAT_XBGR2101010,
> + DRM_FORMAT_ABGR2101010,
> + DRM_FORMAT_BGRX1010102,
> + DRM_FORMAT_BGRA1010102,
> +};
> +
> +struct mtk_disp_exdma {
> + void __iomem *regs;
> + struct clk *clk;
> + struct cmdq_client_reg cmdq_reg;
> + struct device *larb;
> +};
> +
> +static unsigned int mtk_disp_exdma_color_convert(unsigned int color_encoding)
> +{
> + switch (color_encoding) {
> + default:
> + case DRM_COLOR_YCBCR_BT709:
> + return OVL_EXDMA_CON_INT_MTX_BT709_TO_RGB;
> + case DRM_COLOR_YCBCR_BT601:
> + return OVL_EXDMA_CON_INT_MTX_BT601_TO_RGB;
> + }
> +}
> +
> +void mtk_disp_exdma_start(struct device *dev, struct cmdq_pkt *cmdq_pkt)
> +{
> + struct mtk_disp_exdma *priv = dev_get_drvdata(dev);
> + unsigned int value = 0, mask = 0;
It's not necessary to initialize these variable.
> +
> + value = OVL_EXDMA_RDMA_BURST_CON1_BURST16_EN | OVL_EXDMA_RDMA_BURST_CON1_DDR_ACK_EN;
> + mask = OVL_EXDMA_RDMA_BURST_CON1_BURST16_EN | OVL_EXDMA_RDMA_BURST_CON1_DDR_EN |
> + OVL_EXDMA_RDMA_BURST_CON1_DDR_ACK_EN;
It seems that you clear OVL_EXDMA_RDMA_BURST_CON1_DDR_EN. Describe why you clear it.
> + mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_RDMA_BURST_CON1, mask);
> + /*
> + * The dummy register is used in the configuration of the EXDMA engine to
> + * write commands to DRAM, ensuring that data transfers occur normally.
EXDMA would write data into DRAM? Describe more clear so I could understand this.
> + */
> + value = OVL_EXDMA_EXT_DDR_EN_OPT | OVL_EXDMA_FORCE_EXT_DDR_EN;
> + mask = OVL_EXDMA_EXT_DDR_EN_OPT | OVL_EXDMA_FORCE_EXT_DDR_EN;
mask is identical to value, so just use value.
> + mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_DUMMY_REG, mask);
> +
> + value = OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN |
> + OVL_EXDMA_DATAPATH_CON_HDR_GCLAST_EN |
> + OVL_EXDMA_DATAPATH_CON_GCLAST_EN;
> + mask = OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN |
> + OVL_EXDMA_DATAPATH_CON_HDR_GCLAST_EN |
> + OVL_EXDMA_DATAPATH_CON_GCLAST_EN;
> + mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_DATAPATH_CON, mask);
> +
> + mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_MOUT_BGCLR_OUT, &priv->cmdq_reg,
> + priv->regs, DISP_REG_OVL_EXDMA_MOUT,
> + OVL_EXDMA_MOUT_BGCLR_OUT | OVL_EXDMA_MOUT_OUT_DATA);
> +
> + mtk_ddp_write(cmdq_pkt, ~0, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_EXDMA_GDRDY_PRD);
> +
> + mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_RDMA0_EN, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_RDMA0_CTRL, OVL_EXDMA_RDMA0_EN);
EXDMA has layer config function, and RDMA would enable/disable by layer, so move OVL_EXDMA_RDMA0_EN config to layer config function.
> + mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_L0_EN, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_L0_EN, OVL_EXDMA_L0_EN);
EXDMA has layer config function, and L0 would enable/disable by layer, so move OVL_EXDMA_L0_EN config to layer config function.
> +
> + mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_EN, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_EN, OVL_EXDMA_EN);
> +}
> +
> +void mtk_disp_exdma_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt)
> +{
> + struct mtk_disp_exdma *priv = dev_get_drvdata(dev);
> +
> + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_EN, OVL_EXDMA_EN);
> + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_RDMA0_CTRL, OVL_EXDMA_RDMA0_EN);
> + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_DATAPATH_CON, OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN);
> + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_L0_EN, OVL_EXDMA_L0_EN);
> + mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_RST, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_RST, OVL_EXDMA_RST);
> + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_RST, OVL_EXDMA_RST);
> +}
> +
> +void mtk_disp_exdma_layer_config(struct device *dev, struct mtk_plane_state *state,
> + struct cmdq_pkt *cmdq_pkt)
> +{
> + struct mtk_disp_exdma *priv = dev_get_drvdata(dev);
> + struct mtk_plane_pending_state *pending = &state->pending;
> + const struct drm_format_info *fmt_info = drm_format_info(pending->format);
> + unsigned int align_width = 0;
> + bool csc_enable = (fmt_info) ? fmt_info->is_yuv : false;
> + unsigned int blend_mode = mtk_ovl_get_blend_mode(state,
> + BIT(DRM_MODE_BLEND_PREMULTI) |
> + BIT(DRM_MODE_BLEND_COVERAGE) |
> + BIT(DRM_MODE_BLEND_PIXEL_NONE));
> + unsigned int val = 0;
It's not necessary to initialize val.
> + unsigned int clrfmt_mask = OVL_EXDMA_CON_RGB_SWAP |
> + OVL_EXDMA_CON_BYTE_SWAP |
> + OVL_EXDMA_CON_CLRFMT_MAN |
> + OVL_EXDMA_CON_FLD_CLRFMT |
> + OVL_EXDMA_CON_FLD_CLRFMT_NB;
> +
> + if (!pending->enable) {
> + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_RDMA0_CTRL, OVL_EXDMA_RDMA0_EN);
> + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_L0_EN, OVL_EXDMA_L0_EN);
> + return;
> + }
> +
> + /* OVLSYS is in 1T2P domain, width needs to be 2 pixels align */
> + align_width = ALIGN_DOWN(pending->width, 2);
If width is 101, change width to 100 would get correct display output?
> +
> + mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
> + priv->regs, DISP_REG_OVL_EXDMA_ROI_SIZE);
> +
> + mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
> + priv->regs, DISP_REG_OVL_EXDMA_SRC_SIZE);
> + mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
> + priv->regs, DISP_REG_OVL_EXDMA_SRC_SIZE);
Why do you duplicate DISP_REG_OVL_EXDMA_SRC_SIZE register setting?
> +
> + mtk_ddp_write_mask(cmdq_pkt, pending->pitch, &priv->cmdq_reg,
> + priv->regs, DISP_REG_OVL_EXDMA_PITCH, OVL_EXDMA_L0_SRC_PITCH_MASK);
> + mtk_ddp_write_mask(cmdq_pkt, pending->pitch >> 16, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_PITCH_MSB, 0xf);
Symbolize 0xf.
> +
> + val = mtk_disp_exdma_color_convert(pending->color_encoding);
> + if (csc_enable)
> + val |= OVL_EXDMA_CON_INT_MTX_EN;
> + mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_EXDMA_CON,
> + OVL_EXDMA_CON_FLD_INT_MTX_SEL | OVL_EXDMA_CON_INT_MTX_EN);
You have no way to disable csc.
If first frame is YUV format, you enable csc.
And second frame is RGB, you does not disable csc, so RGB would do csc and display incorrect result.
> +
> + val = mtk_ovl_fmt_convert(pending->format, blend_mode, true, false, 0,
> + OVL_EXDMA_CON_CLRFMT_MAN, OVL_EXDMA_CON_BYTE_SWAP,
> + OVL_EXDMA_CON_RGB_SWAP);
> + if (mtk_ovl_is_10bit_rgb(pending->format))
> + val |= OVL_EXDMA_CON_CLRFMT_NB_10_BIT;
> + mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_L0_CLRFMT, clrfmt_mask);
> +
> + val = OVL_EXDMA_HG_FOVL_EXDMA_CK_ON | OVL_EXDMA_HF_FOVL_EXDMA_CK_ON |
Does CK_ON mean clock on? If so, where do you turn off the clock?
> + OVL_EXDMA_OP_8BIT_MODE;
> + mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_EN_CON, val);
> +
> + val = OVL_EXDMA_RDMA0_L0_VCSEL | OVL_EXDMA_RDMA0_HDR_L0_VCSEL;
> + mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EXDMA_L0_GUSER_EXT, val);
> +
> + val = pending->pitch;
> + if (mtk_ovl_is_ignore_pixel_alpha(state, blend_mode))
> + val |= OVL_EXDMA_L0_CONST_BLD;
> + mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_EXDMA_PITCH,
> + OVL_EXDMA_L0_CONST_BLD | OVL_EXDMA_L0_SRC_PITCH);
> +}
> +
> +const u32 *mtk_disp_exdma_get_formats(struct device *dev)
> +{
> + return formats;
> +}
> +
> +size_t mtk_disp_exdma_get_num_formats(struct device *dev)
> +{
> + return ARRAY_SIZE(formats);
> +}
> +
> +int mtk_disp_exdma_clk_enable(struct device *dev)
> +{
> + struct mtk_disp_exdma *exdma = dev_get_drvdata(dev);
> +
> + return clk_prepare_enable(exdma->clk);
> +}
> +
> +void mtk_disp_exdma_clk_disable(struct device *dev)
> +{
> + struct mtk_disp_exdma *exdma = dev_get_drvdata(dev);
> +
> + clk_disable_unprepare(exdma->clk);
> +}
> +
> +static int mtk_disp_exdma_bind(struct device *dev, struct device *master,
> + void *data)
> +{
> + return 0;
> +}
> +
> +static void mtk_disp_exdma_unbind(struct device *dev, struct device *master,
> + void *data)
> +{
> +}
> +
> +static const struct component_ops mtk_disp_exdma_component_ops = {
> + .bind = mtk_disp_exdma_bind,
> + .unbind = mtk_disp_exdma_unbind,
> +};
> +
> +static int mtk_disp_exdma_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct platform_device *larb_pdev = NULL;
> + struct device_node *larb_node = NULL;
> + struct resource *res;
> + struct mtk_disp_exdma *priv;
> + int ret = 0;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + priv->regs = devm_ioremap_resource(dev, res);
> + if (IS_ERR(priv->regs)) {
> + dev_err(dev, "failed to ioremap exdma\n");
> + return PTR_ERR(priv->regs);
> + }
> +
> + priv->clk = devm_clk_get(dev, NULL);
> + if (IS_ERR(priv->clk)) {
> + dev_err(dev, "failed to get exdma clk\n");
> + return PTR_ERR(priv->clk);
> + }
> +
> + larb_node = of_parse_phandle(dev->of_node, "mediatek,larb", 0);
> + if (larb_node) {
> + larb_pdev = of_find_device_by_node(larb_node);
> + if (larb_pdev)
> + priv->larb = &larb_pdev->dev;
> + of_node_put(larb_node);
> + }
> +
> + if (!priv->larb) {
> + dev_dbg(dev, "not find larb dev");
> + return -EPROBE_DEFER;
> + }
> + device_link_add(dev, priv->larb, DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
> +
> +#if IS_REACHABLE(CONFIG_MTK_CMDQ)
> + ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
You does not define cmdq client reg in binding document, so it seems this series depend on some cmdq series.
Add the dependency information in cover letter.
> + if (ret)
> + dev_dbg(dev, "No mediatek,gce-client-reg\n");
> +#endif
> + platform_set_drvdata(pdev, priv);
> +
> + pm_runtime_enable(dev);
> +
> + ret = component_add(dev, &mtk_disp_exdma_component_ops);
> + if (ret != 0) {
> + pm_runtime_disable(dev);
> + dev_err(dev, "Failed to add component: %d\n", ret);
> + }
> + return ret;
> +}
> +
> +static void mtk_disp_exdma_remove(struct platform_device *pdev)
> +{
> + component_del(&pdev->dev, &mtk_disp_exdma_component_ops);
> + pm_runtime_disable(&pdev->dev);
> +}
> +
> +static const struct of_device_id mtk_disp_exdma_driver_dt_match[] = {
> + { .compatible = "mediatek,mt8196-exdma", },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, mtk_disp_exdma_driver_dt_match);
> +
> +struct platform_driver mtk_disp_exdma_driver = {
> + .probe = mtk_disp_exdma_probe,
> + .remove = mtk_disp_exdma_remove,
> + .driver = {
> + .name = "mediatek-disp-exdma",
> + .owner = THIS_MODULE,
> + .of_match_table = mtk_disp_exdma_driver_dt_match,
> + },
> +};
> +
> +MODULE_AUTHOR("Nancy Lin <nancy.lin@mediatek.com>");
> +MODULE_DESCRIPTION("MediaTek Exdma Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index 74158b9d6503..bb7306a942ff 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -1276,6 +1276,7 @@ static struct platform_driver * const mtk_drm_drivers[] = {
> &mtk_disp_aal_driver,
> &mtk_disp_ccorr_driver,
> &mtk_disp_color_driver,
> + &mtk_disp_exdma_driver,
> &mtk_disp_gamma_driver,
> &mtk_disp_merge_driver,
> &mtk_disp_ovl_adaptor_driver,
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> index 675cdc90a440..898a75898775 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> @@ -72,6 +72,7 @@ struct mtk_drm_private {
> extern struct platform_driver mtk_disp_aal_driver;
> extern struct platform_driver mtk_disp_ccorr_driver;
> extern struct platform_driver mtk_disp_color_driver;
> +extern struct platform_driver mtk_disp_exdma_driver;
> extern struct platform_driver mtk_disp_gamma_driver;
> extern struct platform_driver mtk_disp_merge_driver;
> extern struct platform_driver mtk_disp_ovl_adaptor_driver;
[-- Attachment #2: Type: text/html, Size: 30264 bytes --]
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 11/15] drm/mediatek: add BLENDER support for MT8196
2025-03-21 9:33 ` [PATCH v2 11/15] drm/mediatek: add BLENDER " paul-pl.chen
@ 2025-03-24 8:33 ` CK Hu (胡俊光)
2025-05-13 17:12 ` Paul-pl Chen (陳柏霖)
0 siblings, 1 reply; 42+ messages in thread
From: CK Hu (胡俊光) @ 2025-03-24 8:33 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
[-- Attachment #1: Type: text/plain, Size: 10037 bytes --]
On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> 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 | 276 ++++++++++++++++++++
> drivers/gpu/drm/mediatek/mtk_disp_blender.h | 18 ++
> drivers/gpu/drm/mediatek/mtk_disp_drv.h | 12 +
> drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 +
> drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 +
> 8 files changed, 311 insertions(+)
> create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_blender.c
> create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_blender.h
>
> diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
> index db92f4fb353d..a7b9ebe27f68 100644
> --- a/drivers/gpu/drm/mediatek/Makefile
> +++ b/drivers/gpu/drm/mediatek/Makefile
> @@ -3,6 +3,7 @@
> mediatek-drm-y := mtk_crtc.o \
> mtk_ddp_comp.o \
> mtk_disp_aal.o \
> + mtk_disp_blender.o \
> mtk_disp_ccorr.o \
> mtk_disp_color.o \
> mtk_disp_exdma.o \
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> index 3e0739d8e6f1..e65c6df987f2 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> @@ -445,6 +445,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
> [MTK_DP_INTF] = "dp-intf",
> [MTK_DPI] = "dpi",
> [MTK_DSI] = "dsi",
> + [MTK_OVL_BLENDER] = "blender",
> [MTK_OVL_EXDMA] = "exdma",
> };
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> index 86dc0ee3924c..075ba5683f93 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> @@ -43,6 +43,7 @@ enum mtk_ddp_comp_type {
> MTK_DPI,
> MTK_DP_INTF,
> MTK_DSI,
> + MTK_OVL_BLENDER,
> MTK_OVL_EXDMA,
> MTK_DDP_COMP_TYPE_MAX,
> };
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_blender.c b/drivers/gpu/drm/mediatek/mtk_disp_blender.c
> new file mode 100644
> index 000000000000..32c9e3d463a4
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_blender.c
> @@ -0,0 +1,276 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2025 MediaTek Inc.
> + */
> +
> +#include <drm/drm_fourcc.h>
> +#include <drm/drm_blend.h>
> +#include <drm/drm_framebuffer.h>
> +#include <linux/clk.h>
> +#include <linux/component.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset.h>
> +#include <linux/soc/mediatek/mtk-cmdq.h>
> +#include <linux/soc/mediatek/mtk-mmsys.h>
> +
> +#include "mtk_crtc.h"
> +#include "mtk_ddp_comp.h"
> +#include "mtk_disp_drv.h"
> +#include "mtk_drm_drv.h"
> +#include "mtk_disp_blender.h"
> +#include "mtk_disp_ovl.h"
> +
> +#define OVL_BLD_ALPHA 0xff
> +#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_PITCH 0x208
DISP_REG_OVL_BLD_L0_PITCH is useless, so drop it.
> +#define OVL_BLD_L0_CONST BIT(24)
> +#define DISP_REG_OVL_BLD_L0_CLR 0x20c
> +#define OVL_BLD_CON_CLRFMT_MAN BIT(4)
> +#define OVL_BLD_L0_SRC_PITCH GENMASK(15, 0)
> +#define DISP_REG_OVL_BLD_PITCH 0x2f4
> +
> +struct mtk_disp_blender {
> + void __iomem *regs;
> + struct clk *clk;
> + struct cmdq_client_reg cmdq_reg;
> +};
> +
> +void mtk_disp_blender_layer_config(struct device *dev, struct mtk_plane_state *state,
> + struct cmdq_pkt *cmdq_pkt)
> +{
> + struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> + struct mtk_plane_pending_state *pending = &state->pending;
> + unsigned int align_width = ALIGN_DOWN(pending->width, 2);
If width is 101, changing width to 100 would get correct display output?
> + unsigned int alpha;
> + unsigned int clrfmt;
> + unsigned int blend_mode = mtk_ovl_get_blend_mode(state,
> + BIT(DRM_MODE_BLEND_PREMULTI) |
> + BIT(DRM_MODE_BLEND_COVERAGE) |
> + BIT(DRM_MODE_BLEND_PIXEL_NONE));
> + unsigned int ignore_pixel_alpha = 0;
> +
> + if (!pending->enable) {
> + mtk_ddp_write(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_L_EN);
> + return;
> + }
> +
> + mtk_ddp_write(cmdq_pkt, pending->y << 16 | pending->x, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_BLD_OFFSET);
> +
> + mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_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);
> +
> + alpha = (OVL_BLD_ALPHA & (state->base.alpha >> 8)) |
> + OVL_BLD_L_ALPHA_EN;
> +
> + if (mtk_ovl_is_ignore_pixel_alpha(state, blend_mode))
> + ignore_pixel_alpha = OVL_BLD_L0_CONST;
> +
> + mtk_ddp_write_mask(cmdq_pkt, pending->pitch | ignore_pixel_alpha,
> + &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_BLD_PITCH, OVL_BLD_L0_CONST | OVL_BLD_L0_SRC_PITCH);
EXDMA already has pitch function, why BLENDER also has pitch function?
What does BLENDER pitch do?
> +
> + mtk_ddp_write_mask(cmdq_pkt, alpha, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_BLD_L_CON2, OVL_BLD_L_ALPHA_EN | OVL_BLD_L_ALPHA);
> +
> + mtk_ddp_write(cmdq_pkt, OVL_BLD_L_EN, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_L_EN);
> +}
> +
> +void mtk_disp_blender_config(struct device *dev, unsigned int w,
> + unsigned int h, unsigned int vrefresh,
> + unsigned int bpc, bool most_top,
> + bool most_bottom, struct cmdq_pkt *cmdq_pkt)
> +{
> + struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> + u32 datapath;
> +
> + dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
> + mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_BLD_ROI_SIZE);
> + mtk_ddp_write(cmdq_pkt, DISP_REG_OVL_BLD_BGCLR_BALCK, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_BLD_BGCLR_CLR);
> + mtk_ddp_write(cmdq_pkt, DISP_REG_OVL_BLD_BGCLR_BALCK, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_BLD_L0_CLR);
I think I know what is BGLCR_CLR, but what is L0_CLR?
> +
> + if (most_top)
> + datapath = OVL_BLD_BGCLR_OUT_TO_PROC;
> + else
> + datapath = OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER;
> + /*
> + * The primary input is from EXDMA and the second input
> + * is optionally from another blender
> + */
> + if (!most_bottom)
> + datapath |= OVL_BLD_BGCLR_IN_SEL;
> +
> + mtk_ddp_write_mask(cmdq_pkt, datapath,
> + &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_DATAPATH_CON,
> + OVL_BLD_BGCLR_OUT_TO_PROC | OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER |
> + OVL_BLD_BGCLR_IN_SEL);
> +}
> +
> +void mtk_disp_blender_start(struct device *dev, struct cmdq_pkt *cmdq_pkt)
> +{
> + struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> + unsigned int tmp;
> +
> + tmp = readl(priv->regs + DISP_REG_OVL_BLD_SHADOW_CTRL);
> + tmp = tmp | OVL_BLD_BYPASS_SHADOW;
> + writel(tmp, priv->regs + DISP_REG_OVL_BLD_SHADOW_CTRL);
> + mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_EN, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_BLD_EN, OVL_BLD_EN);
> +}
> +
> +void mtk_disp_blender_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt)
> +{
> + struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> +
> + mtk_ddp_write(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_L_EN);
> + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_BLD_EN, OVL_BLD_EN);
You already control OVL_BLD_EN in layer config, so it's not necessary to control here.
Regards,
CK
> + mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_RST, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_BLD_RST, OVL_BLD_RST);
> + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_BLD_RST, OVL_BLD_RST);
> +}
> +
>
[-- Attachment #2: Type: text/html, Size: 15589 bytes --]
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 12/15] drm/mediatek: add OUTPROC support for MT8196
2025-03-21 9:33 ` [PATCH v2 12/15] drm/mediatek: add OUTPROC " paul-pl.chen
@ 2025-03-24 9:00 ` CK Hu (胡俊光)
2025-03-28 2:57 ` Paul-pl Chen (陳柏霖)
0 siblings, 1 reply; 42+ messages in thread
From: CK Hu (胡俊光) @ 2025-03-24 9:00 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
[-- Attachment #1: Type: text/plain, Size: 5359 bytes --]
On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> From: Nancy Lin <nancy.lin@mediatek.com>
>
> OUTPROC handles the post-stage of pixel processing in
> the overlapping procedure.OUTPROC manages pixels for
> gamma correction and ensures that pixel values are
> within the correct range.
>
> Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
> Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> ---
[snip]
> 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..a7c6d1982bca
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_outproc.c
> @@ -0,0 +1,242 @@
> +// 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_drm_drv.h"
Alphabetic order.
> +#include "mtk_disp_outproc.h"
> +
> +#define DISP_REG_OVL_OUTPROC_INTEN 0x004
> +#define OVL_OUTPROC_FME_CPL_INTEN BIT(1)
> +#define DISP_REG_OVL_OUTPROC_INTSTA 0x008
> +#define DISP_REG_OVL_OUTPROC_DATAPATH_CON 0x010
> +#define OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP BIT(26)
> +
> +#define DISP_REG_OVL_OUTPROC_EN 0x020
> +#define OVL_OUTPROC_OVL_EN BIT(0)
> +#define DISP_REG_OVL_OUTPROC_RST 0x024
> +#define OVL_OUTPROC_RST BIT(0)
> +#define DISP_REG_OVL_OUTPROC_SHADOW_CTRL 0x028
> +#define OVL_OUTPROC_BYPASS_SHADOW BIT(2)
> +#define DISP_REG_OVL_OUTPROC_ROI_SIZE 0x030
> +
> +struct mtk_disp_outproc {
> + void __iomem *regs;
> + struct clk *clk;
> + void (*vblank_cb)(void *data);
> + void *vblank_cb_data;
> + int irq;
> + struct cmdq_client_reg cmdq_reg;
> +};
> +
> +void mtk_disp_outproc_register_vblank_cb(struct device *dev,
> + void (*vblank_cb)(void *),
> + void *vblank_cb_data)
> +{
> + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> + priv->vblank_cb = vblank_cb;
> + priv->vblank_cb_data = vblank_cb_data;
> +}
> +
> +void mtk_disp_outproc_unregister_vblank_cb(struct device *dev)
> +{
> + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> + priv->vblank_cb = NULL;
> + priv->vblank_cb_data = NULL;
> +}
> +
> +void mtk_disp_outproc_enable_vblank(struct device *dev)
> +{
> + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> + writel(OVL_OUTPROC_FME_CPL_INTEN, priv->regs + DISP_REG_OVL_OUTPROC_INTEN);
> +}
> +
> +void mtk_disp_outproc_disable_vblank(struct device *dev)
> +{
> + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> + writel(0x0, priv->regs + DISP_REG_OVL_OUTPROC_INTEN);
> +}
> +
> +static irqreturn_t mtk_disp_outproc_irq_handler(int irq, void *dev_id)
> +{
> + struct mtk_disp_outproc *priv = dev_id;
> + u32 val;
> +
> + val = readl(priv->regs + DISP_REG_OVL_OUTPROC_INTSTA);
> + if (!val)
> + return IRQ_NONE;
> +
> + writel(0x0, priv->regs + DISP_REG_OVL_OUTPROC_INTSTA);
> +
> + if (priv->vblank_cb)
> + priv->vblank_cb(priv->vblank_cb_data);
> +
> + return IRQ_HANDLED;
> +}
> +
> +void mtk_disp_outproc_config(struct device *dev, unsigned int w,
> + unsigned int h, unsigned int vrefresh,
> + unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
> +{
> + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> + dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
> +
> + //move mtk_ddp_write_mask to mtk_ddp_write
I think this comment is redundant.
> + mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_ROI_SIZE);
> + mtk_ddp_write_mask(cmdq_pkt, OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP,
> + &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_DATAPATH_CON,
> + OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP);
> +}
> +
> +void mtk_disp_outproc_start(struct device *dev)
> +{
> + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> + unsigned int tmp;
> +
> + tmp = readl(priv->regs + DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
> + tmp = tmp | OVL_OUTPROC_BYPASS_SHADOW;
> + writel(tmp, priv->regs + DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
> +
> + mtk_ddp_write(NULL, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_INTSTA);
> + mtk_ddp_write_mask(NULL, OVL_OUTPROC_OVL_EN, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_EN, OVL_OUTPROC_OVL_EN);
Use readl() and writel().
> +}
> +
> +void mtk_disp_outproc_stop(struct device *dev)
> +{
> + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> + mtk_ddp_write_mask(NULL, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_EN, OVL_OUTPROC_OVL_EN);
> + mtk_ddp_write_mask(NULL, OVL_OUTPROC_RST, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_RST, OVL_OUTPROC_RST);
> + mtk_ddp_write_mask(NULL, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_RST, OVL_OUTPROC_RST);
Use readl() and writel().
> +}
> +
> +
[-- Attachment #2: Type: text/html, Size: 8697 bytes --]
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 01/15] dt-bindings: arm: mediatek: mmsys: add compatible for MT8196
2025-03-21 9:33 ` [PATCH v2 01/15] dt-bindings: arm: mediatek: mmsys: add compatible " paul-pl.chen
@ 2025-03-24 9:33 ` Krzysztof Kozlowski
0 siblings, 0 replies; 42+ messages in thread
From: Krzysztof Kozlowski @ 2025-03-24 9:33 UTC (permalink / raw)
To: paul-pl.chen
Cc: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno,
matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
xiandong.wang, sirius.wang, sunny.shen, fshao, treapking,
devicetree, linux-kernel, dri-devel, linux-mediatek,
linux-arm-kernel, Project_Global_Chrome_Upstream_Group
On Fri, Mar 21, 2025 at 05:33:30PM +0800, paul-pl.chen wrote:
> From: Paul-pl Chen <paul-pl.chen@mediatek.com>
>
> In previous SoCs, a single HW pipeline was an independent mmsys,
> which included the OVL module, PQ module, and display interface
> module.
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 02/15] dt-bindings: soc: mediatek: add mutex yaml for MT8196
2025-03-21 9:33 ` [PATCH v2 02/15] dt-bindings: soc: mediatek: add mutex yaml " paul-pl.chen
@ 2025-03-24 9:34 ` Krzysztof Kozlowski
0 siblings, 0 replies; 42+ messages in thread
From: Krzysztof Kozlowski @ 2025-03-24 9:34 UTC (permalink / raw)
To: paul-pl.chen
Cc: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno,
matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
xiandong.wang, sirius.wang, sunny.shen, fshao, treapking,
devicetree, linux-kernel, dri-devel, linux-mediatek,
linux-arm-kernel, Project_Global_Chrome_Upstream_Group
On Fri, Mar 21, 2025 at 05:33:31PM +0800, paul-pl.chen wrote:
> From: Paul-pl Chen <paul-pl.chen@mediatek.com>
>
> Add compatible string to support mutex for MT8196.
>
> Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> ---
> .../devicetree/bindings/soc/mediatek/mediatek,mutex.yaml | 2 ++
> 1 file changed, 2 insertions(+)
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 04/15] dt-bindings: display: mediatek: add BLENDER yaml for MT8196
2025-03-21 9:33 ` [PATCH v2 04/15] dt-bindings: display: mediatek: add BLENDER " paul-pl.chen
@ 2025-03-24 9:36 ` Krzysztof Kozlowski
2025-03-28 2:27 ` Paul-pl Chen (陳柏霖)
0 siblings, 1 reply; 42+ messages in thread
From: Krzysztof Kozlowski @ 2025-03-24 9:36 UTC (permalink / raw)
To: paul-pl.chen
Cc: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno,
matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
xiandong.wang, sirius.wang, sunny.shen, fshao, treapking,
devicetree, linux-kernel, dri-devel, linux-mediatek,
linux-arm-kernel, Project_Global_Chrome_Upstream_Group
On Fri, Mar 21, 2025 at 05:33:33PM +0800, paul-pl.chen wrote:
> +additionalProperties: false
> +
> +examples:
> + - |
> +
Why did you add here blank line? Random changes happening...
> + soc {
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + disp_ovl0_blender0: blender@328d0000 {
> + compatible = "mediatek,mt8196-blender";
> + reg = <0 0x328d0000 0 0x1000>;
> + clocks = <&ovlsys_config_clk 29>;
With fixed code:
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 05/15] dt-bindings: display: mediatek: add OUTPROC yaml for MT8196
2025-03-21 9:33 ` [PATCH v2 05/15] dt-bindings: display: mediatek: add OUTPROC " paul-pl.chen
@ 2025-03-24 16:02 ` Rob Herring
2025-04-01 15:44 ` Paul-pl Chen (陳柏霖)
0 siblings, 1 reply; 42+ messages in thread
From: Rob Herring @ 2025-03-24 16:02 UTC (permalink / raw)
To: paul-pl.chen
Cc: 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, Mar 21, 2025 at 05:33:34PM +0800, paul-pl.chen wrote:
> From: Paul-pl Chen <paul-pl.chen@mediatek.com>
>
> Add mediate,outproc.yaml to support OUTPROC for MT8196.
> MediaTek display overlap output processor, namely OVL_OUTPROC
> or OUTPROC,handles the post-stage of pixel processing in the
> overlapping procedure.
>
> Signed-off-by: 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..f42e9abc1436
> --- /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: |
Don't need '|' if no formatting to preserve.
> + 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>;
> +
> + disp_ovl0_outproc0: outproc@32970000 {
Drop unused labels.
> + 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 [flat|nested] 42+ messages in thread
* Re: [PATCH v2 06/15] soc: mediatek: add mmsys support for MT8196
2025-03-21 9:33 ` [PATCH v2 06/15] soc: mediatek: add mmsys support " paul-pl.chen
@ 2025-03-24 17:09 ` AngeloGioacchino Del Regno
2025-04-02 4:06 ` Paul-pl Chen (陳柏霖)
0 siblings, 1 reply; 42+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-03-24 17:09 UTC (permalink / raw)
To: paul-pl.chen, robh, krzk+dt, conor+dt, chunkuang.hu
Cc: 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
Il 21/03/25 10:33, paul-pl.chen ha scritto:
> From: Nancy Lin <nancy.lin@mediatek.com>
>
> 1. Defining driver data and adding compatible string
> for different subsystems
> (DISPSYS0, DISPSYS1, OVLSYS0, OVLSYS1, VDISP_AO)
> 2. Adding functions to control top clocks and ddp clocks.
> 3. Updating the probe function to initialize clocks and
> enable runtime PM if its node has the power-domains property.
> 4. Adding functions to configure ddp components and
> set default configurations.
> 5. Adding the routing table for each mmsys in MT8196.
You need at least two commits for all that you're doing here... and adding MT8196
tables should be the last one.
>
> 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 | 451 +++++++++++++++++++++++++
> drivers/soc/mediatek/mtk-mmsys.c | 203 ++++++++++-
> drivers/soc/mediatek/mtk-mmsys.h | 18 +
> include/linux/soc/mediatek/mtk-mmsys.h | 60 ++++
> 4 files changed, 731 insertions(+), 1 deletion(-)
> 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..ff841ae9939a
> --- /dev/null
> +++ b/drivers/soc/mediatek/mt8196-mmsys.h
> @@ -0,0 +1,451 @@
..snip..
> +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[] = {
> + {
> + DDP_COMPONENT_OVL0_EXDMA2, DDP_COMPONENT_OVL0_BLENDER1,
There's a new MMSYS_ROUTE macro that was introduced because tables contained
wrong values in multiple instances and in multiple SoCs: please use it here and
for all routing tables.
> + 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
..snip..
> +};
> +#endif /* __SOC_MEDIATEK_MT8196_MMSYS_H */
> diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c
> index bb4639ca0b8c..1d3ca4f9f237 100644
> --- a/drivers/soc/mediatek/mtk-mmsys.c
> +++ b/drivers/soc/mediatek/mtk-mmsys.c
> @@ -4,12 +4,14 @@
> * Author: James Liao <jamesjj.liao@mediatek.com>
> */
>
> +#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>
>
> @@ -21,6 +23,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
> @@ -144,6 +147,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,
> @@ -158,6 +209,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 +234,99 @@ 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]);
Why can't you add the clocks in the mediatek-drm nodes and handle enablement in the
drm driver?!
> + 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;
> +
> + 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;
> +
> + mtk_mmsys_update_bits(mmsys, async[i].offset, async[i].mask,
> + height << 16 | width, cmdq_pkt);
linux/bitfield.h provides macros that you should use for those register fields.
> +}
> +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 +537,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 +579,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");
No, you can't do that if there's no binding to support that.
> + 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;
> + }
> +
Also this looks like you have children providing only clocks?!
I really need to look at the bindings to decide, but this looks wrong.
Regards,
Angelo
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 07/15] soc: mediatek: mutex: refactor SOF settings for output components
2025-03-21 9:33 ` [PATCH v2 07/15] soc: mediatek: mutex: refactor SOF settings for output components paul-pl.chen
@ 2025-03-24 17:12 ` AngeloGioacchino Del Regno
2025-04-02 3:30 ` Paul-pl Chen (陳柏霖)
0 siblings, 1 reply; 42+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-03-24 17:12 UTC (permalink / raw)
To: paul-pl.chen, robh, krzk+dt, conor+dt, chunkuang.hu
Cc: 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
Il 21/03/25 10:33, paul-pl.chen ha scritto:
> From: Nancy Lin <nancy.lin@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().
>
> - Added mtk_mutex_add_comp_sof() and mtk_mutex_remove_comp_sof()
> for SOF settings.
> - Reused the switch case for SOF IDs.
> - Separated MOD and SOF logic.
>
This also needs more than one commit.
The cleanups go in a commit doing only cleanups.
> 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 | 121 +++++++++++++++----------
> include/linux/soc/mediatek/mtk-mutex.h | 4 +
> 2 files changed, 79 insertions(+), 46 deletions(-)
>
> diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
> index aaa965d4b050..c026ac0e6969 100644
> --- a/drivers/soc/mediatek/mtk-mutex.c
> +++ b/drivers/soc/mediatek/mtk-mutex.c
> @@ -853,43 +853,84 @@ void mtk_mutex_unprepare(struct mtk_mutex *mutex)
> }
> EXPORT_SYMBOL_GPL(mtk_mutex_unprepare);
>
> -void mtk_mutex_add_comp(struct mtk_mutex *mutex,
> - enum mtk_ddp_comp_id id)
> +static int mtk_mutex_get_output_comp_sof(enum mtk_ddp_comp_id id)
> {
> - struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
> - mutex[mutex->id]);
> - unsigned int reg;
> - unsigned int sof_id;
> - unsigned int offset;
> -
> - WARN_ON(&mtx->mutex[mutex->id] != mutex);
> -
> switch (id) {
> case DDP_COMPONENT_DSI0:
> - sof_id = MUTEX_SOF_DSI0;
> - break;
> + return MUTEX_SOF_DSI0;
> case DDP_COMPONENT_DSI1:
> - sof_id = MUTEX_SOF_DSI0;
> - break;
> + return MUTEX_SOF_DSI1;
> case DDP_COMPONENT_DSI2:
> - sof_id = MUTEX_SOF_DSI2;
> - break;
> + return MUTEX_SOF_DSI2;
> case DDP_COMPONENT_DSI3:
> - sof_id = MUTEX_SOF_DSI3;
> - break;
> + return MUTEX_SOF_DSI3;
> case DDP_COMPONENT_DPI0:
> - sof_id = MUTEX_SOF_DPI0;
> - break;
> + return MUTEX_SOF_DPI0;
> case DDP_COMPONENT_DPI1:
> - sof_id = MUTEX_SOF_DPI1;
> - break;
> + return MUTEX_SOF_DPI1;
> case DDP_COMPONENT_DP_INTF0:
> - sof_id = MUTEX_SOF_DP_INTF0;
> - break;
> + return MUTEX_SOF_DP_INTF0;
> case DDP_COMPONENT_DP_INTF1:
> - sof_id = MUTEX_SOF_DP_INTF1;
> - break;
> + return MUTEX_SOF_DP_INTF1;
> default:
> + break;
> + }
> +
> + return -EINVAL;
> +}
> +
> +void mtk_mutex_add_comp_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);
fits in one line
> +}
> +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 offset;
> + bool is_output_comp = !!mtk_mutex_get_output_comp_sof(id);
> +
> + WARN_ON(&mtx->mutex[mutex->id] != mutex);
> +
Looks like you can just do
if (is_output_comp) {
mtk_mutex_add_comp_sof(mutex, id);
return;
}
if (mtx->data->mutex_mod[id] < 32) { .....etc
> + if (!is_output_comp) {
> if (mtx->data->mutex_mod[id] < 32) {
> offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
> mutex->id);
> @@ -902,12 +943,10 @@ void mtk_mutex_add_comp(struct mtk_mutex *mutex,
> reg |= 1 << (mtx->data->mutex_mod[id] - 32);
> writel_relaxed(reg, mtx->regs + offset);
> }
> - return;
> }
>
> - writel_relaxed(mtx->data->mutex_sof[sof_id],
> - mtx->regs +
> - DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, mutex->id));
> + if (is_output_comp)
> + mtk_mutex_add_comp_sof(mutex, id);
> }
> EXPORT_SYMBOL_GPL(mtk_mutex_add_comp);
>
> @@ -918,24 +957,11 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
> mutex[mutex->id]);
> unsigned int reg;
> unsigned int offset;
> + bool is_output_comp = !!mtk_mutex_get_output_comp_sof(id);
>
> WARN_ON(&mtx->mutex[mutex->id] != mutex);
>
> - switch (id) {
> - case DDP_COMPONENT_DSI0:
> - case DDP_COMPONENT_DSI1:
> - case DDP_COMPONENT_DSI2:
> - case DDP_COMPONENT_DSI3:
> - case DDP_COMPONENT_DPI0:
> - case DDP_COMPONENT_DPI1:
> - case DDP_COMPONENT_DP_INTF0:
> - case DDP_COMPONENT_DP_INTF1:
> - writel_relaxed(MUTEX_SOF_SINGLE_MODE,
> - mtx->regs +
> - DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg,
> - mutex->id));
> - break;
> - default:
> + if (!is_output_comp) {
same comment as before.
> if (mtx->data->mutex_mod[id] < 32) {
> offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
> mutex->id);
> @@ -948,8 +974,11 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
> reg &= ~(1 << (mtx->data->mutex_mod[id] - 32));
> writel_relaxed(reg, mtx->regs + offset);
> }
> - break;
> }
> +
> + if (is_output_comp)
> + mtk_mutex_remove_comp_sof(mutex, id);
> +
Regards,
Angelo
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 09/15] drm/mediatek: Refine OVL format convert API and export to public
2025-03-21 9:33 ` [PATCH v2 09/15] drm/mediatek: Refine OVL format convert API and export to public paul-pl.chen
@ 2025-03-25 2:57 ` CK Hu (胡俊光)
2025-05-13 16:22 ` Paul-pl Chen (陳柏霖)
0 siblings, 1 reply; 42+ messages in thread
From: CK Hu (胡俊光) @ 2025-03-25 2:57 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
[-- Attachment #1: Type: text/plain, Size: 12232 bytes --]
On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> From: Nancy Lin <nancy.lin@mediatek.com>
>
> Refine OVL format convert API and export to public.
>
> 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 | 158 ++++++++++++++++--------
> drivers/gpu/drm/mediatek/mtk_disp_ovl.h | 16 +++
> 2 files changed, 122 insertions(+), 52 deletions(-)
> create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovl.h
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> index d0581c4e3c99..e2b125a717c6 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> @@ -18,6 +18,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 +63,15 @@
> /* OVL_CON_RGB_SWAP works only if OVL_CON_CLRFMT_MAN is enabled */
> #define OVL_CON_RGB_SWAP BIT(25)
>
> -#define OVL_CON_CLRFMT_RGB (1 << 12)
> -#define OVL_CON_CLRFMT_ARGB8888 (2 << 12)
> -#define OVL_CON_CLRFMT_RGBA8888 (3 << 12)
> -#define OVL_CON_CLRFMT_ABGR8888 (OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP)
> -#define OVL_CON_CLRFMT_BGRA8888 (OVL_CON_CLRFMT_RGBA8888 | OVL_CON_BYTE_SWAP)
> -#define OVL_CON_CLRFMT_UYVY (4 << 12)
> -#define OVL_CON_CLRFMT_YUYV (5 << 12)
> -#define OVL_CON_MTX_YUV_TO_RGB (6 << 16)
> -#define OVL_CON_CLRFMT_PARGB8888 ((3 << 12) | OVL_CON_CLRFMT_MAN)
> -#define OVL_CON_CLRFMT_PABGR8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_RGB_SWAP)
> -#define OVL_CON_CLRFMT_PBGRA8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_BYTE_SWAP)
> -#define OVL_CON_CLRFMT_PRGBA8888 (OVL_CON_CLRFMT_PABGR8888 | OVL_CON_BYTE_SWAP)
> -#define OVL_CON_CLRFMT_RGB565(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \
> - 0 : OVL_CON_CLRFMT_RGB)
> -#define OVL_CON_CLRFMT_RGB888(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \
> - OVL_CON_CLRFMT_RGB : 0)
> +#define OVL_CON_CLRFMT_RGB565(shift) (0 << (shift))
> +#define OVL_CON_CLRFMT_RGB888(shift) (1 << (shift))
> +#define OVL_CON_CLRFMT_ARGB8888(shift) (2 << (shift))
> +#define OVL_CON_CLRFMT_RGBA8888(shift) (3 << (shift))
> +#define OVL_CON_CLRFMT_UYVY(shift) (4 << (shift))
> +#define OVL_CON_CLRFMT_YUYV(shift) (5 << (shift))
> +#define OVL_CON_MTX_YUV_TO_RGB (6 << 16)
> +#define OVL_CON_CLRFMT_PARGB8888(shift, man) ((3 << (shift)) | (man))
> +
> #define OVL_CON_AEN BIT(8)
> #define OVL_CON_ALPHA 0xff
> #define OVL_CON_VIRT_FLIP BIT(9)
> @@ -85,7 +79,7 @@
>
> #define OVL_COLOR_ALPHA GENMASK(31, 24)
>
> -static inline bool is_10bit_rgb(u32 fmt)
> +bool mtk_ovl_is_10bit_rgb(unsigned int fmt)
> {
> switch (fmt) {
> case DRM_FORMAT_XRGB2101010:
> @@ -295,7 +289,7 @@ static void mtk_ovl_set_bit_depth(struct device *dev, int idx, u32 format,
> if (!ovl->data->supports_clrfmt_ext)
> return;
>
> - if (is_10bit_rgb(format))
> + if (mtk_ovl_is_10bit_rgb(format))
> bit_depth = OVL_CON_CLRFMT_10_BIT;
>
> mtk_ddp_write_mask(cmdq_pkt, OVL_CON_CLRFMT_BIT_DEPTH(bit_depth, idx),
> @@ -394,10 +388,26 @@ 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)
> +bool mtk_ovl_is_ignore_pixel_alpha(struct mtk_plane_state *state, unsigned int blend_mode)
> +{
This modification is not related to the title, so separate to another patch.
> + 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;
> +}
> +
> +unsigned int mtk_ovl_get_blend_mode(struct mtk_plane_state *state, unsigned int blend_modes)
> {
> - unsigned int fmt = state->pending.format;
> unsigned int blend_mode = DRM_MODE_BLEND_COVERAGE;
>
> /*
> @@ -412,52 +422,102 @@ static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl,
> * will get an error return from drm_plane_create_blend_mode_property() and
> * state->base.pixel_blend_mode should not be used.
> */
> - if (ovl->data->blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
> + if (blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
> blend_mode = state->base.pixel_blend_mode;
>
> + return blend_mode;
> +}
> +
> +unsigned int mtk_ovl_fmt_convert(unsigned int fmt, unsigned int blend_mode,
> + bool fmt_rgb565_is_0, bool color_convert,
> + u8 clrfmt_shift, u32 clrfmt_man, u32 byte_swap, u32 rgb_swap)
> +{
> + unsigned int con = 0;
> + bool need_byte_swap = false, need_rgb_swap = false;
> +
> switch (fmt) {
> default:
> case DRM_FORMAT_RGB565:
> - return OVL_CON_CLRFMT_RGB565(ovl);
> + con = fmt_rgb565_is_0 ?
> + OVL_CON_CLRFMT_RGB565(clrfmt_shift) : OVL_CON_CLRFMT_RGB888(clrfmt_shift);
> + break;
> case DRM_FORMAT_BGR565:
> - return OVL_CON_CLRFMT_RGB565(ovl) | OVL_CON_BYTE_SWAP;
> + con = fmt_rgb565_is_0 ?
> + OVL_CON_CLRFMT_RGB565(clrfmt_shift) : OVL_CON_CLRFMT_RGB888(clrfmt_shift);
> + need_byte_swap = true; /* RGB565 -> BGR565 */
> + break;
> case DRM_FORMAT_RGB888:
> - return OVL_CON_CLRFMT_RGB888(ovl);
> + con = fmt_rgb565_is_0 ?
> + OVL_CON_CLRFMT_RGB888(clrfmt_shift) : OVL_CON_CLRFMT_RGB565(clrfmt_shift);
> + break;
> case DRM_FORMAT_BGR888:
> - return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP;
> + con = fmt_rgb565_is_0 ?
> + OVL_CON_CLRFMT_RGB888(clrfmt_shift) : OVL_CON_CLRFMT_RGB565(clrfmt_shift);
> + need_byte_swap = true; /* RGB888 -> BGR888 */
> + break;
> case DRM_FORMAT_RGBX8888:
> case DRM_FORMAT_RGBA8888:
> case DRM_FORMAT_RGBX1010102:
> case DRM_FORMAT_RGBA1010102:
> - return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> - OVL_CON_CLRFMT_RGBA8888 :
> - OVL_CON_CLRFMT_PRGBA8888;
> + if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
> + con = OVL_CON_CLRFMT_RGBA8888(clrfmt_shift);
> + } else {
> + con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
> + need_byte_swap = true; /* PARGB8888 -> PBGRA8888 */
> + need_rgb_swap = true; /* PBGRA8888 -> PRGBA8888 */
> + }
> + break;
> case DRM_FORMAT_BGRX8888:
> case DRM_FORMAT_BGRA8888:
> case DRM_FORMAT_BGRX1010102:
> case DRM_FORMAT_BGRA1010102:
> - return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> - OVL_CON_CLRFMT_BGRA8888 :
> - OVL_CON_CLRFMT_PBGRA8888;
> + if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
> + con = OVL_CON_CLRFMT_RGBA8888(clrfmt_shift);
> + need_byte_swap = true; /* RGB8888 -> BGR8888 */
> + } else {
> + con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
> + need_byte_swap = true; /* PARGB8888 -> PBGRA8888 */
> + }
> + break;
> case DRM_FORMAT_XRGB8888:
> case DRM_FORMAT_ARGB8888:
> case DRM_FORMAT_XRGB2101010:
> case DRM_FORMAT_ARGB2101010:
> - return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> - OVL_CON_CLRFMT_ARGB8888 :
> - OVL_CON_CLRFMT_PARGB8888;
> + if (blend_mode == DRM_MODE_BLEND_COVERAGE)
> + con = OVL_CON_CLRFMT_ARGB8888(clrfmt_shift);
> + else
> + con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
> + break;
> case DRM_FORMAT_XBGR8888:
> case DRM_FORMAT_ABGR8888:
> case DRM_FORMAT_XBGR2101010:
> case DRM_FORMAT_ABGR2101010:
> - return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> - OVL_CON_CLRFMT_ABGR8888 :
> - OVL_CON_CLRFMT_PABGR8888;
> + if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
> + con = OVL_CON_CLRFMT_ARGB8888(clrfmt_shift);
> + need_rgb_swap = true; /* ARGB8888 -> ABGR8888 */
> + } else {
> + con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
> + need_rgb_swap = true; /* PARGB8888 -> PABGR8888 */
> + }
> + break;
> case DRM_FORMAT_UYVY:
> - return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB;
> + con = OVL_CON_CLRFMT_UYVY(clrfmt_shift);
> + break;
> case DRM_FORMAT_YUYV:
> - return OVL_CON_CLRFMT_YUYV | OVL_CON_MTX_YUV_TO_RGB;
> + con = OVL_CON_CLRFMT_YUYV(clrfmt_shift);
> + break;
> }
> +
> + if (color_convert)
> + con |= OVL_CON_MTX_YUV_TO_RGB;
Only YUV need this. RGB do not need this.
> +
> + 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,
> @@ -495,7 +555,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);
This modification is not related to the title, so separate to another patch.
> unsigned int ignore_pixel_alpha = 0;
> unsigned int con;
>
> @@ -504,7 +564,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
> return;
> }
>
> - con = mtk_ovl_fmt_convert(ovl, state);
> + con = mtk_ovl_fmt_convert(fmt, blend_mode, ovl->data->fmt_rgb565_is_0, true,
> + 12, OVL_CON_CLRFMT_MAN, OVL_CON_BYTE_SWAP, OVL_CON_RGB_SWAP);
> if (state->base.fb) {
> con |= state->base.alpha & OVL_CON_ALPHA;
>
> @@ -512,17 +573,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)
This modification is not related to the title, so separate to another patch.
> 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;
> }
>
> /*
> @@ -548,6 +600,8 @@ 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));
> +
> + ignore_pixel_alpha = mtk_ovl_is_ignore_pixel_alpha(state, blend_mode) ? OVL_CONST_BLEND : 0;
> mtk_ddp_write_relaxed(cmdq_pkt, pitch_lsb | ignore_pixel_alpha,
> &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH(idx));
> mtk_ddp_write_relaxed(cmdq_pkt, src_size, &ovl->cmdq_reg, ovl->regs,
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.h b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
> new file mode 100644
> index 000000000000..9bd5dc62d626
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
> @@ -0,0 +1,16 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2025 MediaTek Inc.
> + */
> +
> +#ifndef __MTK_DISP_OVL_H__
> +#define __MTK_DISP_OVL_H__
> +
> +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);
> +
> +#endif
[-- Attachment #2: Type: text/html, Size: 19297 bytes --]
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 14/15] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver
2025-03-21 9:33 ` [PATCH v2 14/15] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver paul-pl.chen
@ 2025-03-25 3:44 ` CK Hu (胡俊光)
2025-05-13 16:11 ` Paul-pl Chen (陳柏霖)
0 siblings, 1 reply; 42+ messages in thread
From: CK Hu (胡俊光) @ 2025-03-25 3:44 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
[-- Attachment #1: Type: text/plain, Size: 1100 bytes --]
On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> 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>
> ---
[snip]
>
> +enum mtk_drm_mmsys {
> + DISPSYS0,
> + DISPSYS1,
> + OVLSYS0,
> + OVLSYS1,
> + MAX_MMSYS,
> +};
Let ovlsys sub driver control OVLSYS0 and OVLSYS1, so mediatek drm driver would not see them and this patch is not necessary.
Regards,
CK
[-- Attachment #2: Type: text/html, Size: 2704 bytes --]
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 04/15] dt-bindings: display: mediatek: add BLENDER yaml for MT8196
2025-03-24 9:36 ` Krzysztof Kozlowski
@ 2025-03-28 2:27 ` Paul-pl Chen (陳柏霖)
0 siblings, 0 replies; 42+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-03-28 2:27 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
[-- Attachment #1: Type: text/plain, Size: 1016 bytes --]
On Mon, 2025-03-24 at 10:36 +0100, Krzysztof Kozlowski wrote:
>
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>
>
> On Fri, Mar 21, 2025 at 05:33:33PM +0800, paul-pl.chen wrote:
> > +additionalProperties: false
> > +
> > +examples:
> > + - |
> > +
>
> Why did you add here blank line? Random changes happening...
>
Sorry, we will fix it at the next version.
> > + soc {
> > + #address-cells = <2>;
> > + #size-cells = <2>;
> > +
> > + disp_ovl0_blender0: blender@328d0000 {
> > + compatible = "mediatek,mt8196-blender";
> > + reg = <0 0x328d0000 0 0x1000>;
> > + clocks = <&ovlsys_config_clk 29>;
>
> With fixed code:
>
Thanks, We will follow tthehe fixed.
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>
> Best regards,
> Krzysztof
>
> Best regards,
Paul
[-- Attachment #2: Type: text/html, Size: 2932 bytes --]
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 12/15] drm/mediatek: add OUTPROC support for MT8196
2025-03-24 9:00 ` CK Hu (胡俊光)
@ 2025-03-28 2:57 ` Paul-pl Chen (陳柏霖)
0 siblings, 0 replies; 42+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-03-28 2:57 UTC (permalink / raw)
To: CK Hu (胡俊光), robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org, chunkuang.hu@kernel.org,
AngeloGioacchino Del Regno
Cc: Sunny Shen (沈姍姍),
Sirius Wang (王皓昱),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
linux-kernel@vger.kernel.org,
Project_Global_Chrome_Upstream_Group,
dri-devel@lists.freedesktop.org,
linux-mediatek@lists.infradead.org,
Jason-JH Lin (林睿祥),
devicetree@vger.kernel.org, fshao@chromium.org,
p.zabel@pengutronix.de, Singo Chang (張興國),
linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
treapking@chromium.org
[-- Attachment #1: Type: text/plain, Size: 6211 bytes --]
On Mon, 2025-03-24 at 09:00 +0000, CK Hu (胡俊光) wrote:
> On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> > From: Nancy Lin <nancy.lin@mediatek.com>
> >
> > OUTPROC handles the post-stage of pixel processing in
> > the overlapping procedure.OUTPROC manages pixels for
> > gamma correction and ensures that pixel values are
> > within the correct range.
> >
> > Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
> > Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> > ---
>
> [snip]
>
> > 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..a7c6d1982bca
> > --- /dev/null
> > +++ b/drivers/gpu/drm/mediatek/mtk_disp_outproc.c
> > @@ -0,0 +1,242 @@
> > +// 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_drm_drv.h"
>
> Alphabetic order.
>
> OK, I will fix the Alphabetic order.
>
> > +#include "mtk_disp_outproc.h"
> > +
> > +#define
> > DISP_REG_OVL_OUTPROC_INTEN 0x004
> > +#define
> > OVL_OUTPROC_FME_CPL_INTEN BIT(1)
> > +#define
> > DISP_REG_OVL_OUTPROC_INTSTA 0x008
> > +#define
> > DISP_REG_OVL_OUTPROC_DATAPATH_CON 0x010
> > +#define
> > OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP BIT(26)
> > +
> > +#define
> > DISP_REG_OVL_OUTPROC_EN 0x020
> > +#define
> > OVL_OUTPROC_OVL_EN BIT(0)
> > +#define
> > DISP_REG_OVL_OUTPROC_RST 0x024
> > +#define
> > OVL_OUTPROC_RST BIT(0)
> > +#define
> > DISP_REG_OVL_OUTPROC_SHADOW_CTRL 0x028
> > +#define
> > OVL_OUTPROC_BYPASS_SHADOW BIT(2)
> > +#define
> > DISP_REG_OVL_OUTPROC_ROI_SIZE 0x030
> > +
> > +struct mtk_disp_outproc {
> > + void __iomem *regs;
> > + struct clk *clk;
> > + void (*vblank_cb)(void *data);
> > + void *vblank_cb_data;
> > + int irq;
> > + struct cmdq_client_reg cmdq_reg;
> > +};
> > +
> > +void mtk_disp_outproc_register_vblank_cb(struct device *dev,
> > + void (*vblank_cb)(void
> > *),
> > + void *vblank_cb_data)
> > +{
> > + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> > +
> > + priv->vblank_cb = vblank_cb;
> > + priv->vblank_cb_data = vblank_cb_data;
> > +}
> > +
> > +void mtk_disp_outproc_unregister_vblank_cb(struct device *dev)
> > +{
> > + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> > +
> > + priv->vblank_cb = NULL;
> > + priv->vblank_cb_data = NULL;
> > +}
> > +
> > +void mtk_disp_outproc_enable_vblank(struct device *dev)
> > +{
> > + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> > +
> > + writel(OVL_OUTPROC_FME_CPL_INTEN, priv->regs +
> > DISP_REG_OVL_OUTPROC_INTEN);
> > +}
> > +
> > +void mtk_disp_outproc_disable_vblank(struct device *dev)
> > +{
> > + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> > +
> > + writel(0x0, priv->regs + DISP_REG_OVL_OUTPROC_INTEN);
> > +}
> > +
> > +static irqreturn_t mtk_disp_outproc_irq_handler(int irq, void
> > *dev_id)
> > +{
> > + struct mtk_disp_outproc *priv = dev_id;
> > + u32 val;
> > +
> > + val = readl(priv->regs + DISP_REG_OVL_OUTPROC_INTSTA);
> > + if (!val)
> > + return IRQ_NONE;
> > +
> > + writel(0x0, priv->regs + DISP_REG_OVL_OUTPROC_INTSTA);
> > +
> > + if (priv->vblank_cb)
> > + priv->vblank_cb(priv->vblank_cb_data);
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +void mtk_disp_outproc_config(struct device *dev, unsigned int w,
> > + unsigned int h, unsigned int
> > vrefresh,
> > + unsigned int bpc, struct cmdq_pkt
> > *cmdq_pkt)
> > +{
> > + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> > +
> > + dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
> > +
> > + //move mtk_ddp_write_mask to mtk_ddp_write
>
> I think this comment is redundant.
Sure, this redundant comment will be removed at the next version.
>
> > + mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg,
> > priv->regs,
> > + DISP_REG_OVL_OUTPROC_ROI_SIZE);
> > + mtk_ddp_write_mask(cmdq_pkt,
> > OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP,
> > + &priv->cmdq_reg, priv->regs,
> > + DISP_REG_OVL_OUTPROC_DATAPATH_CON,
> > + OVL_OUTPROC_DATAPATH_CON_OUTPUT_CLAMP);
> > +}
> > +
> > +void mtk_disp_outproc_start(struct device *dev)
> > +{
> > + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> > + unsigned int tmp;
> > +
> > + tmp = readl(priv->regs +
> > DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
> > + tmp = tmp | OVL_OUTPROC_BYPASS_SHADOW;
> > + writel(tmp, priv->regs +
> > DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
> > +
> > + mtk_ddp_write(NULL, 0, &priv->cmdq_reg, priv->regs,
> > + DISP_REG_OVL_OUTPROC_INTSTA);
> > + mtk_ddp_write_mask(NULL, OVL_OUTPROC_OVL_EN, &priv-
> > >cmdq_reg, priv->regs,
> > + DISP_REG_OVL_OUTPROC_EN,
> > OVL_OUTPROC_OVL_EN);
>
> Use readl() and writel().
>
> Understood, I will use `writel` to replace the 'mtk_ddp_write'.
> > +}
> > +
> > +void mtk_disp_outproc_stop(struct device *dev)
> > +{
> > + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> > +
> > + mtk_ddp_write_mask(NULL, 0, &priv->cmdq_reg, priv->regs,
> > + DISP_REG_OVL_OUTPROC_EN,
> > OVL_OUTPROC_OVL_EN);
> > + mtk_ddp_write_mask(NULL, OVL_OUTPROC_RST, &priv->cmdq_reg,
> > priv->regs,
> > + DISP_REG_OVL_OUTPROC_RST,
> > OVL_OUTPROC_RST);
> > + mtk_ddp_write_mask(NULL, 0, &priv->cmdq_reg, priv->regs,
> > + DISP_REG_OVL_OUTPROC_RST,
> > OVL_OUTPROC_RST);
>
> Use readl() and writel().
Understood, I will use `writel` to replace the 'mtk_ddp_write'.
>
> > +}
> > +
> > +
>
>
>
Best regards,
Paul
[-- Attachment #2: Type: text/html, Size: 11287 bytes --]
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 05/15] dt-bindings: display: mediatek: add OUTPROC yaml for MT8196
2025-03-24 16:02 ` Rob Herring
@ 2025-04-01 15:44 ` Paul-pl Chen (陳柏霖)
0 siblings, 0 replies; 42+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-04-01 15:44 UTC (permalink / raw)
To: robh@kernel.org
Cc: Project_Global_Chrome_Upstream_Group,
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, krzk+dt@kernel.org,
fshao@chromium.org, Jason-JH Lin (林睿祥),
Singo Chang (張興國), p.zabel@pengutronix.de,
linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
treapking@chromium.org
[-- Attachment #1: Type: text/plain, Size: 3518 bytes --]
On Mon, 2025-03-24 at 11:02 -0500, Rob Herring wrote:
>
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>
>
> On Fri, Mar 21, 2025 at 05:33:34PM +0800, paul-pl.chen wrote:
> > From: Paul-pl Chen <paul-pl.chen@mediatek.com>
> >
> > Add mediate,outproc.yaml to support OUTPROC for MT8196.
> > MediaTek display overlap output processor, namely OVL_OUTPROC
> > or OUTPROC,handles the post-stage of pixel processing in the
> > overlapping procedure.
> >
> > Signed-off-by: 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,outpr
> > oc.yaml
> > b/Documentation/devicetree/bindings/display/mediatek/mediatek,outpr
> > oc.yaml
> > new file mode 100644
> > index 000000000000..f42e9abc1436
> > --- /dev/null
> > +++
> > b/Documentation/devicetree/bindings/display/mediatek/mediatek,outpr
> > oc.yaml
> > @@ -0,0 +1,54 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id:
> > https://urldefense.com/v3/__http://devicetree.org/schemas/display/mediatek/mediatek,outproc.yaml*__;Iw!!CTRNKA9wMg0ARbw!ghGkyCSu5Imt_Qeb1RI5QcLmLfa_Q1aEayGOzR2CJs_yks_d7KvxS3HLH_e6SVWf4bq8iEm8gKfVhyPozw$
> > +$schema:
> > https://urldefense.com/v3/__http://devicetree.org/meta-schemas/core.yaml*__;Iw!!CTRNKA9wMg0ARbw!ghGkyCSu5Imt_Qeb1RI5QcLmLfa_Q1aEayGOzR2CJs_yks_d7KvxS3HLH_e6SVWf4bq8iEm8gKfoJ-K_hA$
> > +
> > +title: MediaTek display overlap output processor
> > +
> > +maintainers:
> > + - Chun-Kuang Hu <chunkuang.hu@kernel.org>
> > + - Philipp Zabel <p.zabel@pengutronix.de>
> > +
> > +description: |
>
> Don't need '|' if no formatting to preserve.
Sure, I will remove this part.
>
> > + 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>;
> > +
> > + disp_ovl0_outproc0: outproc@32970000 {
>
> Drop unused labels.
Sure, we will remove the unused labels. "disp_ovl0_outproc0"
Best regards,
Paul
>
> > + 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
> >
[-- Attachment #2: Type: text/html, Size: 7244 bytes --]
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 07/15] soc: mediatek: mutex: refactor SOF settings for output components
2025-03-24 17:12 ` AngeloGioacchino Del Regno
@ 2025-04-02 3:30 ` Paul-pl Chen (陳柏霖)
0 siblings, 0 replies; 42+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-04-02 3:30 UTC (permalink / raw)
To: robh@kernel.org, krzk+dt@kernel.org, AngeloGioacchino Del Regno,
conor+dt@kernel.org, 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
[-- Attachment #1: Type: text/plain, Size: 10081 bytes --]
On Mon, 2025-03-24 at 18:12 +0100, AngeloGioacchino Del Regno wrote:
>
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>
>
> Il 21/03/25 10:33, paul-pl.chen ha scritto:
> > From: Nancy Lin <nancy.lin@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().
> >
> > - Added mtk_mutex_add_comp_sof() and mtk_mutex_remove_comp_sof()
> > for SOF settings.
> > - Reused the switch case for SOF IDs.
> > - Separated MOD and SOF logic.
> >
>
> This also needs more than one commit.
>
> The cleanups go in a commit doing only cleanups.
>
Hi AngeloGioacchino,
Based on your advice, I'm considering dividing the changes as follows:
Commit 1:refactor SOF settings for output components
- Added mtk_mutex_add_comp_sof() and mtk_mutex_remove_comp_sof()
for SOF settings.
- Separated MOD and SOF logic.
Commit 2:
- Reused the switch case for SOF IDs.
> > Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
> > Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> > ---
> > drivers/soc/mediatek/mtk-mutex.c | 121 +++++++++++++++-----
> > -----
> > include/linux/soc/mediatek/mtk-mutex.h | 4 +
> > 2 files changed, 79 insertions(+), 46 deletions(-)
> >
> > diff --git a/drivers/soc/mediatek/mtk-mutex.c
> > b/drivers/soc/mediatek/mtk-mutex.c
> > index aaa965d4b050..c026ac0e6969 100644
> > --- a/drivers/soc/mediatek/mtk-mutex.c
> > +++ b/drivers/soc/mediatek/mtk-mutex.c
> > @@ -853,43 +853,84 @@ void mtk_mutex_unprepare(struct mtk_mutex
> > *mutex)
> > }
> > EXPORT_SYMBOL_GPL(mtk_mutex_unprepare);
> >
> > -void mtk_mutex_add_comp(struct mtk_mutex *mutex,
> > - enum mtk_ddp_comp_id id)
> > +static int mtk_mutex_get_output_comp_sof(enum mtk_ddp_comp_id id)
> > {
> > - struct mtk_mutex_ctx *mtx = container_of(mutex, struct
> > mtk_mutex_ctx,
> > - mutex[mutex->id]);
> > - unsigned int reg;
> > - unsigned int sof_id;
> > - unsigned int offset;
> > -
> > - WARN_ON(&mtx->mutex[mutex->id] != mutex);
> > -
> > switch (id) {
> > case DDP_COMPONENT_DSI0:
> > - sof_id = MUTEX_SOF_DSI0;
> > - break;
> > + return MUTEX_SOF_DSI0;
> > case DDP_COMPONENT_DSI1:
> > - sof_id = MUTEX_SOF_DSI0;
> > - break;
> > + return MUTEX_SOF_DSI1;
> > case DDP_COMPONENT_DSI2:
> > - sof_id = MUTEX_SOF_DSI2;
> > - break;
> > + return MUTEX_SOF_DSI2;
> > case DDP_COMPONENT_DSI3:
> > - sof_id = MUTEX_SOF_DSI3;
> > - break;
> > + return MUTEX_SOF_DSI3;
> > case DDP_COMPONENT_DPI0:
> > - sof_id = MUTEX_SOF_DPI0;
> > - break;
> > + return MUTEX_SOF_DPI0;
> > case DDP_COMPONENT_DPI1:
> > - sof_id = MUTEX_SOF_DPI1;
> > - break;
> > + return MUTEX_SOF_DPI1;
> > case DDP_COMPONENT_DP_INTF0:
> > - sof_id = MUTEX_SOF_DP_INTF0;
> > - break;
> > + return MUTEX_SOF_DP_INTF0;
> > case DDP_COMPONENT_DP_INTF1:
> > - sof_id = MUTEX_SOF_DP_INTF1;
> > - break;
> > + return MUTEX_SOF_DP_INTF1;
> > default:
> > + break;
> > + }
> > +
> > + return -EINVAL;
> > +}
> > +
> > +void mtk_mutex_add_comp_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);
>
> fits in one line
>
> OK, I will fix it in one line.
> > +}
> > +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 offset;
> > + bool is_output_comp = !!mtk_mutex_get_output_comp_sof(id);
> > +
> > + WARN_ON(&mtx->mutex[mutex->id] != mutex);
> > +
>
> Looks like you can just do
>
> if (is_output_comp) {
> mtk_mutex_add_comp_sof(mutex, id);
> return;
> }
>
> if (mtx->data->mutex_mod[id] < 32) { .....etc
>
OK,
This is because the next patch [PATCH v2 08/15],
we have to consider using the condition of "mtx->data->need_sof_mod"
to set the register setting of DISP_REG_MUTEX_MOD.
> > + if (!is_output_comp) {
> > if (mtx->data->mutex_mod[id] < 32) {
> > offset = DISP_REG_MUTEX_MOD(mtx->data-
> > >mutex_mod_reg,
> > mutex->id);
> > @@ -902,12 +943,10 @@ void mtk_mutex_add_comp(struct mtk_mutex
> > *mutex,
> > reg |= 1 << (mtx->data->mutex_mod[id] - 32);
> > writel_relaxed(reg, mtx->regs + offset);
> > }
> > - return;
> > }
> >
> > - writel_relaxed(mtx->data->mutex_sof[sof_id],
> > - mtx->regs +
> > - DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg,
> > mutex->id));
> > + if (is_output_comp)
> > + mtk_mutex_add_comp_sof(mutex, id);
> > }
> > EXPORT_SYMBOL_GPL(mtk_mutex_add_comp);
> >
> > @@ -918,24 +957,11 @@ void mtk_mutex_remove_comp(struct mtk_mutex
> > *mutex,
> > mutex[mutex->id]);
> > unsigned int reg;
> > unsigned int offset;
> > + bool is_output_comp = !!mtk_mutex_get_output_comp_sof(id);
> >
> > WARN_ON(&mtx->mutex[mutex->id] != mutex);
> >
> > - switch (id) {
> > - case DDP_COMPONENT_DSI0:
> > - case DDP_COMPONENT_DSI1:
> > - case DDP_COMPONENT_DSI2:
> > - case DDP_COMPONENT_DSI3:
> > - case DDP_COMPONENT_DPI0:
> > - case DDP_COMPONENT_DPI1:
> > - case DDP_COMPONENT_DP_INTF0:
> > - case DDP_COMPONENT_DP_INTF1:
> > - writel_relaxed(MUTEX_SOF_SINGLE_MODE,
> > - mtx->regs +
> > - DISP_REG_MUTEX_SOF(mtx->data-
> > >mutex_sof_reg,
> > - mutex->id));
> > - break;
> > - default:
> > + if (!is_output_comp) {
>
> same comment as before.
>
OK,
This is because the next patch [PATCH v2 08/15],
we have to consider using the condition of "mtx->data->need_sof_mod"
to set the register setting of DISP_REG_MUTEX_MOD.
Best regards,
Paul
> > if (mtx->data->mutex_mod[id] < 32) {
> > offset = DISP_REG_MUTEX_MOD(mtx->data-
> > >mutex_mod_reg,
> > mutex->id);
> > @@ -948,8 +974,11 @@ void mtk_mutex_remove_comp(struct mtk_mutex
> > *mutex,
> > reg &= ~(1 << (mtx->data->mutex_mod[id] -
> > 32));
> > writel_relaxed(reg, mtx->regs + offset);
> > }
> > - break;
> > }
> > +
> > + if (is_output_comp)
> > + mtk_mutex_remove_comp_sof(mutex, id);
> > +
>
> Regards,
> Angelo
>
>
[-- Attachment #2: Type: text/html, Size: 22415 bytes --]
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 06/15] soc: mediatek: add mmsys support for MT8196
2025-03-24 17:09 ` AngeloGioacchino Del Regno
@ 2025-04-02 4:06 ` Paul-pl Chen (陳柏霖)
2025-04-02 9:33 ` AngeloGioacchino Del Regno
0 siblings, 1 reply; 42+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-04-02 4:06 UTC (permalink / raw)
To: robh@kernel.org, krzk+dt@kernel.org, AngeloGioacchino Del Regno,
conor+dt@kernel.org, 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
[-- Attachment #1: Type: text/plain, Size: 17864 bytes --]
On Mon, 2025-03-24 at 18:09 +0100, AngeloGioacchino Del Regno wrote:
>
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>
>
> Il 21/03/25 10:33, paul-pl.chen ha scritto:
> > From: Nancy Lin <nancy.lin@mediatek.com>
> >
> > 1. Defining driver data and adding compatible string
> > for different subsystems
> > (DISPSYS0, DISPSYS1, OVLSYS0, OVLSYS1, VDISP_AO)
> > 2. Adding functions to control top clocks and ddp clocks.
> > 3. Updating the probe function to initialize clocks and
> > enable runtime PM if its node has the power-domains property.
> > 4. Adding functions to configure ddp components and
> > set default configurations.
> > 5. Adding the routing table for each mmsys in MT8196.
>
> You need at least two commits for all that you're doing here... and
> adding MT8196
> tables should be the last one.
>
Hi AngeloGioacchino,
Thank you for your feedback. I appreciate your suggestion to split the
changes into at least two commits. Based on your advice, I'm
considering dividing the changes as follows:
Commit 1: Add mmsys support
This commit would include:
(1) Defining driver data and adding compatible strings for different
subsystems (DISPSYS0, DISPSYS1, OVLSYS0, OVLSYS1, VDISP_AO)
(2) Adding functions to control top clocks and ddp clocks
(3) Updating the probe function to initialize clocks and enable runtime
PM if its node has the power-domains property
(4) Adding functions to configure ddp components and set default
configurations
Commit 2: Add mmsys tables support for MT8196
This commit would focus on:
(5) Adding the routing table for each mmsys in MT8196
Does this division align with your expectations?
> >
> > 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 | 451
> > +++++++++++++++++++++++++
> > drivers/soc/mediatek/mtk-mmsys.c | 203 ++++++++++-
> > drivers/soc/mediatek/mtk-mmsys.h | 18 +
> > include/linux/soc/mediatek/mtk-mmsys.h | 60 ++++
> > 4 files changed, 731 insertions(+), 1 deletion(-)
> > 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..ff841ae9939a
> > --- /dev/null
> > +++ b/drivers/soc/mediatek/mt8196-mmsys.h
> > @@ -0,0 +1,451 @@
>
> ..snip..
>
> > +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[] = {
> > + {
> > + DDP_COMPONENT_OVL0_EXDMA2,
> > DDP_COMPONENT_OVL0_BLENDER1,
>
> There's a new MMSYS_ROUTE macro that was introduced because tables
> contained
> wrong values in multiple instances and in multiple SoCs: please use
> it here and
> for all routing tables.
>
Sure, I will use the new MMSYS_ROUTE macro " MMSYS_ROUTE " to replace
the old routing table.
> > + 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
>
> ..snip..
>
> > +};
> > +#endif /* __SOC_MEDIATEK_MT8196_MMSYS_H */
> > diff --git a/drivers/soc/mediatek/mtk-mmsys.c
> > b/drivers/soc/mediatek/mtk-mmsys.c
> > index bb4639ca0b8c..1d3ca4f9f237 100644
> > --- a/drivers/soc/mediatek/mtk-mmsys.c
> > +++ b/drivers/soc/mediatek/mtk-mmsys.c
> > @@ -4,12 +4,14 @@
> > * Author: James Liao <jamesjj.liao@mediatek.com>
> > */
> >
> > +#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>
> >
> > @@ -21,6 +23,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
> > @@ -144,6 +147,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,
> > @@ -158,6 +209,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 +234,99 @@ 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]);
>
> Why can't you add the clocks in the mediatek-drm nodes and handle
> enablement in the
> drm driver?!
>
The "async" is not like other components under mediate-drm that have
independent functions.It only controls which clocks need to be enabled
when the path MUX goes through certain routes.
That's why it's placed in mtk-mmsys. It's only activated when it needs
to be connected to the necessary path MUX.
Currently, the path order is represented through component IDs.
Therefore, to indicate its relative position on the DDP path, we
defined a component ID for it to use.
> > + 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;
> > +
> > + 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;
> > +
> > + mtk_mmsys_update_bits(mmsys, async[i].offset, async[i].mask,
> > + height << 16 | width, cmdq_pkt);
>
> linux/bitfield.h provides macros that you should use for those
> register fields.
>
We use "mtk_mmsys_update_bits" to check if a cmdq packet exists.
If the cmdq packet exists, the function will make settings through
cmdq.
If cmdq is NULL, it will directly make settings through the CPU.
Regarding your comment
"linux/bitfield.h provides macros that you should use for those
register fields", are they suggesting that:
[1] We should use the macros provided by linux/bitfield.h to replace
expressions like "height << 16"
or [2] We should rewrite mtk_mmsys_update_bits using kernel APIs
> > +}
> > +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 +537,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 +579,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");
>
> No, you can't do that if there's no binding to support that.
>
We will add the "async" component in the MMSYS YAML file.
"async" is a nessceary clock in the specific routing display
path MUX configuration
>
> > + 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;
> > + }
> > +
>
> Also this looks like you have children providing only clocks?!
> I really need to look at the bindings to decide, but this looks
> wrong.
>
We will add the "async" component in the MMSYS YAML file.
"async" is a nessceary clock in the specific routing display
path MUX configuration
> Regards,
> Angelo
>
>
> Best Regards,
Paul
[-- Attachment #2: Type: text/html, Size: 34322 bytes --]
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 06/15] soc: mediatek: add mmsys support for MT8196
2025-04-02 4:06 ` Paul-pl Chen (陳柏霖)
@ 2025-04-02 9:33 ` AngeloGioacchino Del Regno
2025-04-11 9:26 ` Paul-pl Chen (陳柏霖)
0 siblings, 1 reply; 42+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-04-02 9:33 UTC (permalink / raw)
To: Paul-pl Chen (陳柏霖), robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org, 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
Il 02/04/25 06:06, Paul-pl Chen (陳柏霖) ha scritto:
> On Mon, 2025-03-24 at 18:09 +0100, AngeloGioacchino Del Regno wrote:
>>
>> External email : Please do not click links or open attachments until
>> you have verified the sender or the content.
>>
>>
>> Il 21/03/25 10:33, paul-pl.chen ha scritto:
>>> From: Nancy Lin <nancy.lin@mediatek.com>
>>>
>>> 1. Defining driver data and adding compatible string
>>> for different subsystems
>>> (DISPSYS0, DISPSYS1, OVLSYS0, OVLSYS1, VDISP_AO)
>>> 2. Adding functions to control top clocks and ddp clocks.
>>> 3. Updating the probe function to initialize clocks and
>>> enable runtime PM if its node has the power-domains property.
>>> 4. Adding functions to configure ddp components and
>>> set default configurations.
>>> 5. Adding the routing table for each mmsys in MT8196.
>>
>> You need at least two commits for all that you're doing here... and
>> adding MT8196
>> tables should be the last one.
>>
> Hi AngeloGioacchino,
>
> Thank you for your feedback. I appreciate your suggestion to split the
> changes into at least two commits. Based on your advice, I'm
> considering dividing the changes as follows:
>
> Commit 1: Add mmsys support
> This commit would include:
> (1) Defining driver data and adding compatible strings for different
> subsystems (DISPSYS0, DISPSYS1, OVLSYS0, OVLSYS1, VDISP_AO)
> (2) Adding functions to control top clocks and ddp clocks
> (3) Updating the probe function to initialize clocks and enable runtime
> PM if its node has the power-domains property
> (4) Adding functions to configure ddp components and set default
> configurations
>
> Commit 2: Add mmsys tables support for MT8196
> This commit would focus on:
> (5) Adding the routing table for each mmsys in MT8196
>
> Does this division align with your expectations?
Yes, but if you want, you can even do more than two commits - just make it
readable; each commit needs a precise scope, only changes that *need to*
be together go in a single commit.
>>>
>>> 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 | 451
>>> +++++++++++++++++++++++++
>>> drivers/soc/mediatek/mtk-mmsys.c | 203 ++++++++++-
>>> drivers/soc/mediatek/mtk-mmsys.h | 18 +
>>> include/linux/soc/mediatek/mtk-mmsys.h | 60 ++++
>>> 4 files changed, 731 insertions(+), 1 deletion(-)
>>> 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..ff841ae9939a
>>> --- /dev/null
>>> +++ b/drivers/soc/mediatek/mt8196-mmsys.h
>>> @@ -0,0 +1,451 @@
>>
>> ..snip..
>>
>>> +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[] = {
>>> + {
>>> + DDP_COMPONENT_OVL0_EXDMA2,
>>> DDP_COMPONENT_OVL0_BLENDER1,
>>
>> There's a new MMSYS_ROUTE macro that was introduced because tables
>> contained
>> wrong values in multiple instances and in multiple SoCs: please use
>> it here and
>> for all routing tables.
>>
> Sure, I will use the new MMSYS_ROUTE macro " MMSYS_ROUTE " to replace
> the old routing table.
>>> + 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
>>
>> ..snip..
>>
>>> +};
>>> +#endif /* __SOC_MEDIATEK_MT8196_MMSYS_H */
>>> diff --git a/drivers/soc/mediatek/mtk-mmsys.c
>>> b/drivers/soc/mediatek/mtk-mmsys.c
>>> index bb4639ca0b8c..1d3ca4f9f237 100644
>>> --- a/drivers/soc/mediatek/mtk-mmsys.c
>>> +++ b/drivers/soc/mediatek/mtk-mmsys.c
>>> @@ -4,12 +4,14 @@
>>> * Author: James Liao <jamesjj.liao@mediatek.com>
>>> */
>>>
>>> +#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>
>>>
>>> @@ -21,6 +23,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
>>> @@ -144,6 +147,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,
>>> @@ -158,6 +209,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 +234,99 @@ 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]);
>>
>> Why can't you add the clocks in the mediatek-drm nodes and handle
>> enablement in the
>> drm driver?!
>>
> The "async" is not like other components under mediate-drm that have
> independent functions.It only controls which clocks need to be enabled
> when the path MUX goes through certain routes.
>
> That's why it's placed in mtk-mmsys. It's only activated when it needs
> to be connected to the necessary path MUX.
>
> Currently, the path order is represented through component IDs.
> Therefore, to indicate its relative position on the DDP path, we
> defined a component ID for it to use.
>
I'm still not convinced - this explanation still doesn't exclude the possibility
of doing that in mediatek-drm, really.
Having one big node containing clocks for multiple hardware IPs doesn't correctly
describe the hardware in the devicetree as well, and this is because those clocks
don't belong to the big VDO, but to the single hardware components that are
children of a VDO.
While this means that the clocks are still contained in a VDO macro-block, they
are relative to a sub-block and enable register access of a sub-block, not of
the VDO macro-block.
>>> + 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;
>>> +
>>> + 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;
>>> +
>>> + mtk_mmsys_update_bits(mmsys, async[i].offset, async[i].mask,
>>> + height << 16 | width, cmdq_pkt);
>>
>> linux/bitfield.h provides macros that you should use for those
>> register fields.
>>
>
> We use "mtk_mmsys_update_bits" to check if a cmdq packet exists.
> If the cmdq packet exists, the function will make settings through
> cmdq.
> If cmdq is NULL, it will directly make settings through the CPU.
>
> Regarding your comment
> "linux/bitfield.h provides macros that you should use for those
> register fields", are they suggesting that:
>
> [1] We should use the macros provided by linux/bitfield.h to replace
> expressions like "height << 16"
>
You have to use those macros to replace expressions like "height << 16".
val = FIELD_PREP(SOMETHING, height);
val |= FIELD_PREP(SOMETHING_ELSE, width);
mtk_mmsys_update_bits(mmsys, async[i].offset, async[i].mask, val, cmdq_pkt);
Regards,
Angelo
> or [2] We should rewrite mtk_mmsys_update_bits using kernel APIs
>>> +}
>>> +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 +537,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 +579,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");
>>
>> No, you can't do that if there's no binding to support that.
>>
> We will add the "async" component in the MMSYS YAML file.
> "async" is a nessceary clock in the specific routing display
> path MUX configuration
>>
>>> + 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;
>>> + }
>>> +
>>
>> Also this looks like you have children providing only clocks?!
>> I really need to look at the bindings to decide, but this looks
>> wrong.
>>
> We will add the "async" component in the MMSYS YAML file.
> "async" is a nessceary clock in the specific routing display
> path MUX configuration
>> Regards,
>> Angelo
>>
>>
>> Best Regards,
> Paul
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 13/15] drm/mediatek: add ovlsys_adaptor support for MT8196
2025-03-21 9:33 ` [PATCH v2 13/15] drm/mediatek: add ovlsys_adaptor " paul-pl.chen
@ 2025-04-11 3:07 ` CK Hu (胡俊光)
2025-05-14 16:18 ` Paul-pl Chen (陳柏霖)
0 siblings, 1 reply; 42+ messages in thread
From: CK Hu (胡俊光) @ 2025-04-11 3:07 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
[-- Attachment #1: Type: text/plain, Size: 42483 bytes --]
On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> From: Nancy Lin <nancy.lin@mediatek.com>
>
> Ovlsys_adaptor is an encapsulated module designed to
> simplify the DRM control flow. This module is composed
> of 20 EXDMAs, 20 BLENDERs, and 12 OUTPROCs.
> Two EXDMAs merge into one layer, allowing the module
> to support 20 layers for 3 display paths.
> Ovlsys_adaptor driver is integrated within the
> mtk_ddp_comp framework.
>
> Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
> Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> ---
> 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 | 797 ++++++++++++++++++
> drivers/gpu/drm/mediatek/mtk_drm_drv.c | 73 ++
> drivers/gpu/drm/mediatek/mtk_drm_drv.h | 11 +-
> 7 files changed, 942 insertions(+), 1 deletion(-)
> create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
>
> diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
> index 9546bc6b7b2e..dedf50860d3f 100644
> --- a/drivers/gpu/drm/mediatek/Makefile
> +++ b/drivers/gpu/drm/mediatek/Makefile
> @@ -9,6 +9,7 @@ mediatek-drm-y := mtk_crtc.o \
> mtk_disp_exdma.o \
> mtk_disp_gamma.o \
> mtk_disp_merge.o \
> + mtk_disp_ovlsys_adaptor.o \
> mtk_disp_ovl.o \
> mtk_disp_outproc.o \
> mtk_disp_ovl_adaptor.o \
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> index cc780744f060..c96e027359ac 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> @@ -368,6 +368,31 @@ static const struct mtk_ddp_comp_funcs ddp_ovl = {
> .get_num_formats = mtk_ovl_get_num_formats,
> };
>
> +static const struct mtk_ddp_comp_funcs ddp_ovlsys_adaptor = {
> + .power_on = mtk_ovlsys_adaptor_power_on,
> + .power_off = mtk_ovlsys_adaptor_power_off,
> + .clk_enable = mtk_ovlsys_adaptor_clk_enable,
> + .clk_disable = mtk_ovlsys_adaptor_clk_disable,
> + .config = mtk_ovlsys_adaptor_config,
> + .start = mtk_ovlsys_adaptor_start,
> + .stop = mtk_ovlsys_adaptor_stop,
> + .layer_check = mtk_ovlsys_adaptor_layer_check,
> + .layer_nr = mtk_ovlsys_adaptor_layer_nr,
> + .layer_config = mtk_ovlsys_adaptor_layer_config,
> + .register_vblank_cb = mtk_ovlsys_adaptor_register_vblank_cb,
> + .unregister_vblank_cb = mtk_ovlsys_adaptor_unregister_vblank_cb,
> + .enable_vblank = mtk_ovlsys_adaptor_enable_vblank,
> + .disable_vblank = mtk_ovlsys_adaptor_disable_vblank,
> + .dma_dev_get = mtk_ovlsys_adaptor_dma_dev_get,
> + .connect = mtk_ovlsys_adaptor_connect,
> + .disconnect = mtk_ovlsys_adaptor_disconnect,
> + .add = mtk_ovlsys_adaptor_add_comp,
> + .remove = mtk_ovlsys_adaptor_remove_comp,
> + .get_blend_modes = mtk_ovlsys_adaptor_get_blend_modes,
> + .get_formats = mtk_ovlsys_adaptor_get_formats,
> + .get_num_formats = mtk_ovlsys_adaptor_get_num_formats,
> +};
> +
> static const struct mtk_ddp_comp_funcs ddp_postmask = {
> .clk_enable = mtk_ddp_clk_enable,
> .clk_disable = mtk_ddp_clk_disable,
> @@ -437,6 +462,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
> [MTK_DISP_OVL] = "ovl",
> [MTK_DISP_OVL_2L] = "ovl-2l",
> [MTK_DISP_OVL_ADAPTOR] = "ovl_adaptor",
> + [MTK_DISP_OVLSYS_ADAPTOR] = "ovlsys_adaptor",
> [MTK_DISP_POSTMASK] = "postmask",
> [MTK_DISP_PWM] = "pwm",
> [MTK_DISP_RDMA] = "rdma",
> @@ -469,6 +495,8 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
> [DDP_COMPONENT_DPI0] = { MTK_DPI, 0, &ddp_dpi },
> [DDP_COMPONENT_DPI1] = { MTK_DPI, 1, &ddp_dpi },
> [DDP_COMPONENT_DRM_OVL_ADAPTOR] = { MTK_DISP_OVL_ADAPTOR, 0, &ddp_ovl_adaptor },
> + [DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0] = { MTK_DISP_OVLSYS_ADAPTOR, 0, &ddp_ovlsys_adaptor},
> + [DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1] = { MTK_DISP_OVLSYS_ADAPTOR, 1, &ddp_ovlsys_adaptor},
> [DDP_COMPONENT_DSC0] = { MTK_DISP_DSC, 0, &ddp_dsc },
> [DDP_COMPONENT_DSC1] = { MTK_DISP_DSC, 1, &ddp_dsc },
> [DDP_COMPONENT_DSI0] = { MTK_DSI, 0, &ddp_dsi },
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> index b33d3289b8b6..ef64ce7a071f 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> @@ -33,6 +33,7 @@ enum mtk_ddp_comp_type {
> MTK_DISP_MUTEX,
> MTK_DISP_OD,
> MTK_DISP_OVL,
> + MTK_DISP_OVLSYS_ADAPTOR,
> MTK_DISP_OVL_2L,
> MTK_DISP_OVL_ADAPTOR,
> MTK_DISP_POSTMASK,
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> index 3c519a662074..1ff8c4593fc1 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> @@ -174,6 +174,38 @@ size_t mtk_ovl_adaptor_get_num_formats(struct device *dev);
> enum drm_mode_status mtk_ovl_adaptor_mode_valid(struct device *dev,
> const struct drm_display_mode *mode);
>
> +int mtk_ovlsys_adaptor_power_on(struct device *dev);
> +void mtk_ovlsys_adaptor_power_off(struct device *dev);
> +void mtk_ovlsys_adaptor_add_comp(struct device *dev, struct mtk_mutex *mutex);
> +void mtk_ovlsys_adaptor_remove_comp(struct device *dev, struct mtk_mutex *mutex);
> +void mtk_ovlsys_adaptor_connect(struct device *dev, struct device *mmsys_dev,
> + unsigned int next);
> +void mtk_ovlsys_adaptor_disconnect(struct device *dev, struct device *mmsys_dev,
> + unsigned int next);
> +int mtk_ovlsys_adaptor_clk_enable(struct device *dev);
> +void mtk_ovlsys_adaptor_clk_disable(struct device *dev);
> +void mtk_ovlsys_adaptor_config(struct device *dev, unsigned int w,
> + unsigned int h, unsigned int vrefresh,
> + unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
> +void mtk_ovlsys_adaptor_layer_config(struct device *dev, unsigned int idx,
> + struct mtk_plane_state *state,
> + struct cmdq_pkt *cmdq_pkt);
> +int mtk_ovlsys_adaptor_layer_check(struct device *dev,
> + unsigned int idx,
> + struct mtk_plane_state *mtk_state);
> +void mtk_ovlsys_adaptor_register_vblank_cb(struct device *dev, void (*vblank_cb)(void *),
> + void *vblank_cb_data);
> +void mtk_ovlsys_adaptor_unregister_vblank_cb(struct device *dev);
> +void mtk_ovlsys_adaptor_enable_vblank(struct device *dev);
> +void mtk_ovlsys_adaptor_disable_vblank(struct device *dev);
> +void mtk_ovlsys_adaptor_start(struct device *dev);
> +void mtk_ovlsys_adaptor_stop(struct device *dev);
> +unsigned int mtk_ovlsys_adaptor_layer_nr(struct device *dev);
> +struct device *mtk_ovlsys_adaptor_dma_dev_get(struct device *dev);
> +u32 mtk_ovlsys_adaptor_get_blend_modes(struct device *dev);
> +const u32 *mtk_ovlsys_adaptor_get_formats(struct device *dev);
> +size_t mtk_ovlsys_adaptor_get_num_formats(struct device *dev);
> +
> void mtk_rdma_bypass_shadow(struct device *dev);
> int mtk_rdma_clk_enable(struct device *dev);
> void mtk_rdma_clk_disable(struct device *dev);
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c b/drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
> new file mode 100644
> index 000000000000..04cb555bd77b
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
> @@ -0,0 +1,797 @@
> +// 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_disp_blender.h"
> +#include "mtk_disp_drv.h"
> +#include "mtk_crtc.h"
Alphabetic order.
> +#include "mtk_ddp_comp.h"
Ditto.
> +#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;
> + unsigned int max_size;
It's not necessary to store max_size in private data.
Drop this and use OVLSYS_ADAPTOR_DRIVER_DATA_MAX_SIZE directly.
> +};
> +
> +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_EXDMA0] = { OVLSYS_ADAPTOR_TYPE_EXDMA, 0, DDP_COMPONENT_ID_MAX},
> + [OVLSYS_ADAPTOR_EXDMA1] = { OVLSYS_ADAPTOR_TYPE_EXDMA, 1, DDP_COMPONENT_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;
> +}
> +
> +static struct device *get_comp_by_type_idx(struct device *dev,
> + enum mtk_ovlsys_adaptor_comp_type type,
> + unsigned int idx)
> +{
> + struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
> + int i;
> + int count = 0;
> +
> + for (i = 0; i < priv->path_size; i++) {
> + if (get_type(priv->path[i]) == type) {
> + if (count == idx)
> + return priv->ovl_adaptor_comp[priv->path[i]];
> + count++;
> + }
> + }
> + return NULL;
> +}
> +
> +int mtk_ovlsys_adaptor_power_on(struct device *dev)
> +{
> + struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
> + struct device *comp;
> + int ret = 0;
> + int i;
> +
> + for (i = 0; i < OVLSYS_ADAPTOR_ID_MAX; i++) {
Why this for-loop is not as below example?
for (i = 0; i < priv->path_size; i++) {
> + comp = priv->ovl_adaptor_comp[i];
> +
> + if (!comp)
> + continue;
> +
> + if (get_type(i) != OVLSYS_ADAPTOR_TYPE_EXDMA)
Why only EXDMA need power on?
> + continue;
> +
> + ret = pm_runtime_get_sync(comp);
> + if (ret < 0) {
> + dev_err(dev, "Failed to enable power domain %d, err %d\n", i, ret);
> + goto pwr_err;
> + }
> + }
> +
> + return ret;
> +pwr_err:
> + while (--i >= 0) {
> + comp = priv->ovl_adaptor_comp[i];
> + if (!comp)
> + continue;
> + if (get_type(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 < OVLSYS_ADAPTOR_ID_MAX; i++) {
> + comp = priv->ovl_adaptor_comp[i];
> +
> + if (!comp)
> + continue;
> +
> + if (get_type(i) == OVLSYS_ADAPTOR_TYPE_EXDMA)
> + 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 device *exdma;
> + struct device *blender;
> + unsigned int align_width = 0;
> + const struct drm_format_info *fmt_info = drm_format_info(pending->format);
> + struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
> +
> + 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 = get_comp_by_type_idx(dev, OVLSYS_ADAPTOR_TYPE_EXDMA, idx);
exdma = priv->ovl_adaptor_comp[priv->path[idx * 2]];
> + if (!exdma) {
You just need to check idx < priv->layer_nr.
> + dev_err(dev, "%s: exdma%d comp not found\n", __func__, idx);
> + return;
> + }
> + blender = get_comp_by_type_idx(dev, OVLSYS_ADAPTOR_TYPE_BLENDER, idx);
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;
> + }
> +
> + /* OVLSYS is in 1T2P domain, width needs to be 2 pixels align */
> + align_width = ALIGN_DOWN(pending->width, 2);
> +
> + if (pending->height == 0 || align_width == 0 ||
> + pending->x > priv->max_size || pending->y > priv->max_size) {
> + pending->enable = false;
Why modify pending->enable?
> + mtk_disp_exdma_layer_config(exdma, state, cmdq_pkt);
> + mtk_disp_blender_layer_config(blender, state, cmdq_pkt);
> + return;
> + }
> +
> + mtk_disp_exdma_layer_config(exdma, state, cmdq_pkt);
> +
> + mtk_disp_blender_layer_config(blender, state, cmdq_pkt);
> +
> + mtk_disp_exdma_start(exdma, cmdq_pkt);
> + mtk_disp_blender_start(blender, cmdq_pkt);
The start function is done in ovlsys_start(), so remove these start function.
> +}
> +
> +void mtk_ovlsys_adaptor_config(struct device *dev, unsigned int w,
> + unsigned int h, unsigned int vrefresh,
> + unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
> +{
> + struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
> + int i;
> + int blender_idx = 0;
> + bool most_top;
> + bool most_bottom;
> +
> + for (i = 0; i < priv->path_size; i++) {
> + if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER) {
> + blender_idx++;
> +
> + if (priv->layer_nr == 1) {
> + most_top = true; /*SINGLE_BLENDER;*/
> + most_bottom = false; /*blender is LAST_BLENDER*/
Only one blender, so most_bottom = true;
> + } else if (blender_idx == 1) {
> + most_top = false; /* NON-SINGLE LAYER */
> + most_bottom = true; /* FIRST LAYER */
> + } else if (blender_idx == priv->layer_nr) {
> + most_top = true; /* NON-SINGLE LAYER */
> + most_bottom = false; /* LAST LAYER */
> + } else {
> + most_top = false; /* NON-SINGLE LAYER */
> + most_bottom = false; /* OTHER LAYER */
> + }
> +
> + mtk_disp_blender_config(priv->ovl_adaptor_comp[priv->path[i]], w, h,
> + vrefresh, bpc, most_top, most_bottom, cmdq_pkt);
You could remove the if-else checking, and
mtk_disp_blender_config(priv->ovl_adaptor_comp[priv->path[i]], w, h,
vrefresh, bpc, blender_idx == priv->layer_nr,
blender_idx == 1, cmdq_pkt);
> + } else if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_OUTPROC) {
> + mtk_disp_outproc_config(priv->ovl_adaptor_comp[priv->path[i]], w, h,
> + vrefresh, bpc, cmdq_pkt);
> + }
> + }
> +}
> +
> +int mtk_ovlsys_adaptor_layer_check(struct device *dev,
> + unsigned int idx,
> + struct mtk_plane_state *mtk_state)
> +{
> + struct drm_plane_state *state = &mtk_state->base;
> +
> + /* Check if any unsupported rotation is set */
> + if (state->rotation & ~DRM_MODE_ROTATE_0)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> +void mtk_ovlsys_adaptor_start(struct device *dev)
> +{
> + struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
> + int i;
> +
> + for (i = 0; i < priv->path_size; i++) {
> + if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_EXDMA)
> + mtk_disp_exdma_start(priv->ovl_adaptor_comp[priv->path[i]], NULL);
> + else if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER)
> + mtk_disp_blender_start(priv->ovl_adaptor_comp[priv->path[i]], NULL);
> + else
> + mtk_disp_outproc_start(priv->ovl_adaptor_comp[priv->path[i]]);
> + }
I think the order in path has some rule, so this for-loop could be simplified as
for (i = 0; i < (priv->path_size - 1); i += 2) {
mtk_disp_exdma_start(priv->ovl_adaptor_comp[priv->path[i]], NULL);
mtk_disp_blender_start(priv->ovl_adaptor_comp[priv->path[i + 1]], NULL);
}
mtk_disp_outproc_start(priv->ovl_adaptor_comp[priv->path[i]]);
> +}
> +
> +void mtk_ovlsys_adaptor_stop(struct device *dev)
> +{
> + struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
> + int i;
> +
> + for (i = 0; i < priv->path_size; i++) {
> + if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_EXDMA)
> + mtk_disp_exdma_stop(priv->ovl_adaptor_comp[priv->path[i]], NULL);
> + else if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER)
> + mtk_disp_blender_stop(priv->ovl_adaptor_comp[priv->path[i]], NULL);
> + else
> + 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 = 0;
> + int i;
> +
> + for (i = 0; i < OVLSYS_ADAPTOR_ID_MAX; i++) {
Why this for-loop is not as below?
for (i = 0; i < priv->path_size; i++) {
> + comp = priv->ovl_adaptor_comp[i];
> +
> + if (!comp)
> + continue;
> +
> + if (get_type(i) == OVLSYS_ADAPTOR_TYPE_EXDMA)
> + ret = mtk_disp_exdma_clk_enable(comp);
> + else if (get_type(i) == OVLSYS_ADAPTOR_TYPE_BLENDER)
> + ret = mtk_disp_blender_clk_enable(comp);
> + else
> + ret = mtk_disp_outproc_clk_enable(comp);
> +
> + if (ret) {
> + dev_err(dev, "Failed to enable clock %d, err %d\n", i, ret);
> + goto clk_err;
> + }
> + }
> +
> + return ret;
> +
> +clk_err:
> + while (--i >= 0) {
> + comp = priv->ovl_adaptor_comp[i];
> + if (!comp)
> + continue;
> + if (get_type(i) == OVLSYS_ADAPTOR_TYPE_EXDMA)
> + mtk_disp_exdma_clk_disable(comp);
> + else if (get_type(i) == OVLSYS_ADAPTOR_TYPE_BLENDER)
> + mtk_disp_blender_clk_disable(comp);
> + else
> + mtk_disp_outproc_clk_disable(comp);
> + }
> + i = OVLSYS_ADAPTOR_ID_MAX;
Why assign i here?
> +
> + 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 < OVLSYS_ADAPTOR_ID_MAX; i++) {
> + comp = priv->ovl_adaptor_comp[i];
> +
> + if (!comp)
> + continue;
> +
> + if (get_type(i) == OVLSYS_ADAPTOR_TYPE_EXDMA)
> + mtk_disp_exdma_clk_disable(comp);
> + else if (get_type(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);
> + struct device *comp;
> + int i;
> +
> + for (i = 0; i < priv->path_size; i++)
> + if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER) {
> + comp = priv->ovl_adaptor_comp[priv->path[i]];
> + return mtk_disp_blender_get_blend_modes(comp);
> + }
In mtk_ovlsys_adaptor_get_formats(), you have assume that priv->ovl_adaptor_comp[priv->path[0]] is exdma,
so you could assume that priv->ovl_adaptor_comp[priv->path[1]] is blender.
Then
return mtk_disp_blender_get_blend_modes(priv->ovl_adaptor_comp[priv->path[1]]);
> +
> + return 0;
> +}
> +
> +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,
> + enum mtk_ddp_comp_id *comp_id)
> +{
> + 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) {
> + *comp_id = comp_matches[i].comp_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 *node, *parent;
> + struct platform_device *comp_pdev;
> + int i;
> +
> + parent = dev->parent->parent->of_node->parent;
> +
> + for_each_child_of_node(parent, node) {
for_each_child_of_node_scoped()
> + const struct of_device_id *of_id;
> + enum mtk_ovlsys_adaptor_comp_type type;
> + enum mtk_ddp_comp_id comp_id;
comp_id is useless, drop it.
> + 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, &comp_id);
> + if (id < 0) {
> + dev_warn(dev, "Skipping unknown component %pOF\n",
> + node);
> + continue;
> + }
> +
> + for (i = 0; i < priv->path_size; i++)
> + if (priv->path[i] == id)
> + found = true;
> +
> + if (!found)
> + continue;
> +
> + comp_pdev = of_find_device_by_node(node);
> + if (!comp_pdev)
> + return -EPROBE_DEFER;
> +
> + priv->ovl_adaptor_comp[id] = &comp_pdev->dev;
> +
> + drm_of_component_match_add(dev, match, component_compare_of, node);
> + dev_dbg(dev, "Adding component match for %pOF\n", node);
> + }
> +
> + if (!*match) {
> + dev_err(dev, "No match device for ovlsys_adaptor\n");
> + return -ENODEV;
> + }
> +
> + return 0;
> +}
> +
> +static int mtk_disp_ovlsys_adaptor_comp_bind(struct device *dev, struct device *master,
> + void *data)
> +{
> + struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
> +
> + if (!priv->children_bound)
> + return -EPROBE_DEFER;
> +
> + return 0;
> +}
> +
> +static void mtk_disp_ovlsys_adaptor_comp_unbind(struct device *dev, struct device *master,
> + void *data)
> +{
> +}
> +
> +static const struct component_ops mtk_disp_ovlsys_adaptor_comp_ops = {
> + .bind = mtk_disp_ovlsys_adaptor_comp_bind,
> + .unbind = mtk_disp_ovlsys_adaptor_comp_unbind,
> +};
> +
> +static int mtk_disp_ovlsys_adaptor_master_bind(struct device *dev)
> +{
> + struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
> + int ret, i;
> + unsigned int layer_nr = 0;
> +
> + 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;
> +
> + for (i = 0; i < priv->path_size; i++)
> + if (comp_matches[priv->path[i]].type == OVLSYS_ADAPTOR_TYPE_BLENDER)
> + layer_nr++;
It seems you could drop layer_nr.
Assign priv->layer_nr to 0 first, and then priv->layer_nr++.
> + priv->layer_nr = layer_nr;
> +
> + return 0;
> +}
> +
> +static void mtk_disp_ovlsys_adaptor_master_unbind(struct device *dev)
> +{
> + struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
> +
> + priv->children_bound = false;
> +}
> +
> +static const struct component_master_ops mtk_disp_ovlsys_adaptor_master_ops = {
> + .bind = mtk_disp_ovlsys_adaptor_master_bind,
> + .unbind = mtk_disp_ovlsys_adaptor_master_unbind,
> +};
> +
> +static int mtk_disp_ovlsys_adaptor_probe(struct platform_device *pdev)
> +{
> + struct mtk_disp_ovlsys_adaptor *priv;
> + struct device *dev = &pdev->dev;
> + struct component_match *match = NULL;
> + struct mtk_ovlsys_platform_data *ovlsys_priv; //mtk_drm_ovlsys_private
Remove the comment.
> + 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;
> + priv->max_size = OVLSYS_ADAPTOR_DRIVER_DATA_MAX_SIZE;
> +
> + if (ovlsys_priv->use_path == CRTC_MAIN) {
> + priv->path = mt8196_mtk_ovl_main;
> + priv->path_size = ARRAY_SIZE(mt8196_mtk_ovl_main);
> + } else if (ovlsys_priv->use_path == CRTC_EXT) {
> + priv->path = mt8196_mtk_ovl_ext;
> + priv->path_size = ARRAY_SIZE(mt8196_mtk_ovl_ext);
> + } else if (ovlsys_priv->use_path == CRTC_THIRD) {
> + priv->path = mt8196_mtk_ovl_third;
> + priv->path_size = ARRAY_SIZE(mt8196_mtk_ovl_third);
> + }
> +
> + ret = ovlsys_adaptor_comp_init(dev, &match);
> + if (ret < 0)
> + return ret;
> +
> + component_master_add_with_match(dev, &mtk_disp_ovlsys_adaptor_master_ops, match);
> +
> + pm_runtime_enable(dev);
> +
> + ret = component_add(dev, &mtk_disp_ovlsys_adaptor_comp_ops);
> + if (ret != 0) {
> + pm_runtime_disable(dev);
> + dev_err(dev, "Failed to add component: %d\n", ret);
> + }
> +
> + return ret;
> +}
> +
> +static void mtk_disp_ovlsys_adaptor_remove(struct platform_device *pdev)
> +{
> + component_master_del(&pdev->dev, &mtk_disp_ovlsys_adaptor_master_ops);
> + pm_runtime_disable(&pdev->dev);
> +}
> +
> +struct platform_driver mtk_disp_ovlsys_adaptor_driver = {
> + .probe = mtk_disp_ovlsys_adaptor_probe,
> + .remove = mtk_disp_ovlsys_adaptor_remove,
> + .driver = {
> + .name = "mediatek-disp-ovlsys-adaptor",
> + .owner = THIS_MODULE,
> + },
> +};
> +
> +MODULE_AUTHOR("Nancy Lin <nancy.lin@mediatek.com>");
> +MODULE_DESCRIPTION("MediaTek Ovlsys Adaptor Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index f7b9c7a982a7..0639201e2e92 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -457,6 +457,27 @@ static bool mtk_drm_find_mmsys_comp(struct mtk_drm_private *private, int comp_id
> return false;
> }
>
> +static int mtk_drm_mmsys_comp_in_path(struct mtk_drm_private *private, int comp_id)
> +{
> + const struct mtk_mmsys_driver_data *drv_data = private->data;
> + int i;
> +
> + if (drv_data->main_path)
> + for (i = 0; i < drv_data->main_len; i++)
> + if (drv_data->main_path[i] == comp_id)
> + return CRTC_MAIN;
> + if (drv_data->ext_path)
> + for (i = 0; i < drv_data->ext_len; i++)
> + if (drv_data->ext_path[i] == comp_id)
> + return CRTC_EXT;
> + if (drv_data->third_path)
> + for (i = 0; i < drv_data->third_len; i++)
> + if (drv_data->third_path[i] == comp_id)
> + return CRTC_THIRD;
> +
This function is almost like mtk_drm_find_mmsys_comp(), try to merge them.
> + return -EINVAL;
> +}
> +
> static int mtk_drm_kms_init(struct drm_device *drm)
> {
> struct mtk_drm_private *private = drm->dev_private;
> @@ -1122,6 +1143,57 @@ static int mtk_drm_probe(struct platform_device *pdev)
> component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev);
> }
>
> + if (mtk_drm_find_mmsys_comp(private, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0)) {
> + struct mtk_ovlsys_platform_data ovlsys_priv;
> +
> + ovlsys_priv.mmsys_dev = private->mmsys_dev;
> + ovlsys_priv.use_path =
> + mtk_drm_mmsys_comp_in_path(private, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0);
> + ovl_adaptor =
> + platform_device_register_data(dev, "mediatek-disp-ovlsys-adaptor",
> + PLATFORM_DEVID_AUTO,
> + (void *)&ovlsys_priv,
> + sizeof(struct mtk_ovlsys_platform_data));
> + private->ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0].dev = &ovl_adaptor->dev;
> + mtk_ddp_comp_init(NULL, &private->ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0],
> + DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0);
> + component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev);
> + }
> +
> + if (mtk_drm_find_mmsys_comp(private, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1)) {
> + struct mtk_ovlsys_platform_data ovlsys_priv; //mtk_drm_ovlsys_private
> +
> + ovlsys_priv.mmsys_dev = private->mmsys_dev;
> + ovlsys_priv.use_path =
> + mtk_drm_mmsys_comp_in_path(private, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1);
> + ovl_adaptor =
> + platform_device_register_data(dev, "mediatek-disp-ovlsys-adaptor",
> + PLATFORM_DEVID_AUTO,
> + (void *)&ovlsys_priv,
> + sizeof(struct mtk_ovlsys_platform_data));
> + private->ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1].dev = &ovl_adaptor->dev;
> + mtk_ddp_comp_init(NULL, &private->ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1],
> + DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1);
> + component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev);
> + }
> +
> + if (mtk_drm_find_mmsys_comp(private, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2)) {
> + struct mtk_ovlsys_platform_data ovlsys_priv;
> +
> + ovlsys_priv.mmsys_dev = private->mmsys_dev;
> + ovlsys_priv.use_path =
> + mtk_drm_mmsys_comp_in_path(private, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2);
> + ovl_adaptor =
> + platform_device_register_data(dev, "mediatek-disp-ovlsys-adaptor",
> + PLATFORM_DEVID_AUTO,
> + (void *)&ovlsys_priv,
> + sizeof(struct mtk_ovlsys_platform_data));
> + private->ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2].dev = &ovl_adaptor->dev;
> + mtk_ddp_comp_init(NULL, &private->ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2],
> + DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2);
> + component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev);
> + }
The code about these three path are almost the same.
Try to merge them.
You could use one function with different parameter
(such as DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1, DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2).
> +
> /* Iterate over sibling DISP function blocks */
> for_each_child_of_node(phandle->parent, node) {
> enum mtk_ddp_comp_type comp_type;
> @@ -1283,6 +1355,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..6e9ed9837c5b 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> @@ -11,7 +11,9 @@
>
> #define MAX_CONNECTOR 2
> #define DDP_COMPONENT_DRM_OVL_ADAPTOR (DDP_COMPONENT_ID_MAX + 1)
> -#define DDP_COMPONENT_DRM_ID_MAX (DDP_COMPONENT_DRM_OVL_ADAPTOR + 1)
> +#define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 (DDP_COMPONENT_DRM_OVL_ADAPTOR + 1)
> +#define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 + 1)
> +#define DDP_COMPONENT_DRM_ID_MAX (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 + 1)
>
> enum mtk_crtc_path {
> CRTC_MAIN,
> @@ -69,6 +71,12 @@ struct mtk_drm_private {
> struct mtk_drm_private **all_drm_private;
> };
>
> +struct mtk_ovlsys_platform_data {//mtk_drm_ovlsys_private
Remove this comment
> + struct device *mmsys_dev;
> + struct device *mutex_dev;
mutex_dev is useless, drop it.
Regards,
CK
> + 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;
[-- Attachment #2: Type: text/html, Size: 61622 bytes --]
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 06/15] soc: mediatek: add mmsys support for MT8196
2025-04-02 9:33 ` AngeloGioacchino Del Regno
@ 2025-04-11 9:26 ` Paul-pl Chen (陳柏霖)
0 siblings, 0 replies; 42+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-04-11 9:26 UTC (permalink / raw)
To: robh@kernel.org, krzk+dt@kernel.org, AngeloGioacchino Del Regno,
conor+dt@kernel.org, chunkuang.hu@kernel.org
Cc: Sunny Shen (沈姍姍),
Sirius Wang (王皓昱),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
linux-kernel@vger.kernel.org,
Project_Global_Chrome_Upstream_Group,
dri-devel@lists.freedesktop.org,
linux-mediatek@lists.infradead.org,
Jason-JH Lin (林睿祥),
devicetree@vger.kernel.org, fshao@chromium.org,
p.zabel@pengutronix.de, Singo Chang (張興國),
linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
treapking@chromium.org
[-- Attachment #1: Type: text/plain, Size: 22990 bytes --]
On Wed, 2025-04-02 at 11:33 +0200, AngeloGioacchino Del Regno wrote:
>
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>
>
> Il 02/04/25 06:06, Paul-pl Chen (陳柏霖) ha scritto:
> > On Mon, 2025-03-24 at 18:09 +0100, AngeloGioacchino Del Regno
> > wrote:
> > >
> > > External email : Please do not click links or open attachments
> > > until
> > > you have verified the sender or the content.
> > >
> > >
> > > Il 21/03/25 10:33, paul-pl.chen ha scritto:
> > > > From: Nancy Lin <nancy.lin@mediatek.com>
> > > >
> > > > 1. Defining driver data and adding compatible string
> > > > for different subsystems
> > > > (DISPSYS0, DISPSYS1, OVLSYS0, OVLSYS1, VDISP_AO)
> > > > 2. Adding functions to control top clocks and ddp clocks.
> > > > 3. Updating the probe function to initialize clocks and
> > > > enable runtime PM if its node has the power-domains property.
> > > > 4. Adding functions to configure ddp components and
> > > > set default configurations.
> > > > 5. Adding the routing table for each mmsys in MT8196.
> > >
> > > You need at least two commits for all that you're doing here...
> > > and
> > > adding MT8196
> > > tables should be the last one.
> > >
> > Hi AngeloGioacchino,
> >
> > Thank you for your feedback. I appreciate your suggestion to split
> > the
> > changes into at least two commits. Based on your advice, I'm
> > considering dividing the changes as follows:
> >
> > Commit 1: Add mmsys support
> > This commit would include:
> > (1) Defining driver data and adding compatible strings for
> > different
> > subsystems (DISPSYS0, DISPSYS1, OVLSYS0, OVLSYS1, VDISP_AO)
> > (2) Adding functions to control top clocks and ddp clocks
> > (3) Updating the probe function to initialize clocks and enable
> > runtime
> > PM if its node has the power-domains property
> > (4) Adding functions to configure ddp components and set default
> > configurations
> >
> > Commit 2: Add mmsys tables support for MT8196
> > This commit would focus on:
> > (5) Adding the routing table for each mmsys in MT8196
> >
> > Does this division align with your expectations?
>
> Yes, but if you want, you can even do more than two commits - just
> make it
> readable; each commit needs a precise scope, only changes that *need
> to*
> be together go in a single commit.
>
Got it, thanks!
> > > >
> > > > 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 | 451
> > > > +++++++++++++++++++++++++
> > > > drivers/soc/mediatek/mtk-mmsys.c | 203 ++++++++++-
> > > > drivers/soc/mediatek/mtk-mmsys.h | 18 +
> > > > include/linux/soc/mediatek/mtk-mmsys.h | 60 ++++
> > > > 4 files changed, 731 insertions(+), 1 deletion(-)
> > > > 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..ff841ae9939a
> > > > --- /dev/null
> > > > +++ b/drivers/soc/mediatek/mt8196-mmsys.h
> > > > @@ -0,0 +1,451 @@
> > >
> > > ..snip..
> > >
> > > > +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[] = {
> > > > + {
> > > > + DDP_COMPONENT_OVL0_EXDMA2,
> > > > DDP_COMPONENT_OVL0_BLENDER1,
> > >
> > > There's a new MMSYS_ROUTE macro that was introduced because
> > > tables
> > > contained
> > > wrong values in multiple instances and in multiple SoCs: please
> > > use
> > > it here and
> > > for all routing tables.
> > >
> > Sure, I will use the new MMSYS_ROUTE macro " MMSYS_ROUTE " to
> > replace
> > the old routing table.
> > > > + 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
> > >
> > > ..snip..
> > >
> > > > +};
> > > > +#endif /* __SOC_MEDIATEK_MT8196_MMSYS_H */
> > > > diff --git a/drivers/soc/mediatek/mtk-mmsys.c
> > > > b/drivers/soc/mediatek/mtk-mmsys.c
> > > > index bb4639ca0b8c..1d3ca4f9f237 100644
> > > > --- a/drivers/soc/mediatek/mtk-mmsys.c
> > > > +++ b/drivers/soc/mediatek/mtk-mmsys.c
> > > > @@ -4,12 +4,14 @@
> > > > * Author: James Liao <jamesjj.liao@mediatek.com>
> > > > */
> > > >
> > > > +#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>
> > > >
> > > > @@ -21,6 +23,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
> > > > @@ -144,6 +147,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,
> > > > @@ -158,6 +209,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 +234,99 @@ 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]);
> > >
> > > Why can't you add the clocks in the mediatek-drm nodes and handle
> > > enablement in the
> > > drm driver?!
> > >
> > The "async" is not like other components under mediate-drm that
> > have
> > independent functions.It only controls which clocks need to be
> > enabled
> > when the path MUX goes through certain routes.
> >
> > That's why it's placed in mtk-mmsys. It's only activated when it
> > needs
> > to be connected to the necessary path MUX.
> >
> > Currently, the path order is represented through component IDs.
> > Therefore, to indicate its relative position on the DDP path, we
> > defined a component ID for it to use.
> >
> I'm still not convinced - this explanation still doesn't exclude the
> possibility
> of doing that in mediatek-drm, really.
>
> Having one big node containing clocks for multiple hardware IPs
> doesn't correctly
> describe the hardware in the devicetree as well, and this is because
> those clocks
> don't belong to the big VDO, but to the single hardware components
> that are
> children of a VDO.
>
> While this means that the clocks are still contained in a VDO macro-
> block, they
> are relative to a sub-block and enable register access of a sub-
> block, not of
> the VDO macro-block.
>
>
Below is the DTS node defined as "async" for MT8196, based on the DTS
node "ovlsys1_config_clk async."
ovlsys1_config_clk: syscon@32c00000 {
compatible = "mediatek,mt8196-ovlsys1",
"syscon";
reg = <0 0x32c00000 0 0x1000>;
mm-hw-ccf-regmap = <&mm_hwv>;
mboxes = <&gce0 2 CMDQ_THR_PRIO_4>, <&gce0 10
CMDQ_THR_PRIO_4>;
power-domains = <&hfrpsys
MT8196_POWER_DOMAIN_OVL1_DORMANT>;
#clock-cells = <1>;
async {
clocks = <&ovlsys1_config_clk
CLK_OVL_DLO5_DISP>,
<&ovlsys1_config_clk
CLK_OVL_DLO6_DISP>;
};
};
The clock configuration for this "async" will affect the connections in
the "mmsys_mt8196_ovl0_routing_table,"
specifically "MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY5" and
"MT8196_DISP_OVL_OUT_PROC_CB_TO_OVL_DLO_RELAY6."
Patch:
https://patchwork.kernel.org/project/linux-mediatek/patch/20250321093435.94835-7-paul-pl.chen@mediatek.com/
Driver Code:
static const struct mtk_mmsys_routes mmsys_mt8196_ovl0_routing_table[]
= {
//Snip
{
DDP_COMPONENT_OVL0_OUTPROC0,
DDP_COMPONENT_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
}, {
DDP_COMPONENT_OVL0_OUTPROC1,
DDP_COMPONENT_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
}
}
> > > > + 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;
> > > > +
> > > > + 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;
> > > > +
> > > > + mtk_mmsys_update_bits(mmsys, async[i].offset,
> > > > async[i].mask,
> > > > + height << 16 | width, cmdq_pkt);
> > >
> > > linux/bitfield.h provides macros that you should use for those
> > > register fields.
> > >
> >
> > We use "mtk_mmsys_update_bits" to check if a cmdq packet exists.
> > If the cmdq packet exists, the function will make settings through
> > cmdq.
> > If cmdq is NULL, it will directly make settings through the CPU.
> >
> > Regarding your comment
> > "linux/bitfield.h provides macros that you should use for those
> > register fields", are they suggesting that:
> >
> > [1] We should use the macros provided by linux/bitfield.h to
> > replace
> > expressions like "height << 16"
> >
>
> You have to use those macros to replace expressions like "height <<
> 16".
>
> val = FIELD_PREP(SOMETHING, height);
> val |= FIELD_PREP(SOMETHING_ELSE, width);
>
> mtk_mmsys_update_bits(mmsys, async[i].offset, async[i].mask, val,
> cmdq_pkt);
>
> Regards,
> Angelo
>
>
> Thanks for the feednack and example.
Best Regards,
Paul
>
>
> > or [2] We should rewrite mtk_mmsys_update_bits using kernel APIs
> > > > +}
> > > > +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 +537,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 +579,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");
> > >
> > > No, you can't do that if there's no binding to support that.
> > >
> > We will add the "async" component in the MMSYS YAML file.
> > "async" is a nessceary clock in the specific routing display
> > path MUX configuration
> > >
> > > > + 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;
> > > > + }
> > > > +
> > >
> > > Also this looks like you have children providing only clocks?!
> > > I really need to look at the bindings to decide, but this looks
> > > wrong.
> > >
> > We will add the "async" component in the MMSYS YAML file.
> > "async" is a nessceary clock in the specific routing display
> > path MUX configuration
> > > Regards,
> > > Angelo
> > >
> > >
> > > Best Regards,
> > Paul
>
>
[-- Attachment #2: Type: text/html, Size: 48233 bytes --]
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 14/15] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver
2025-03-25 3:44 ` CK Hu (胡俊光)
@ 2025-05-13 16:11 ` Paul-pl Chen (陳柏霖)
0 siblings, 0 replies; 42+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-05-13 16:11 UTC (permalink / raw)
To: CK Hu (胡俊光)
Cc: conor+dt@kernel.org, robh@kernel.org,
Sunny Shen (沈姍姍),
Sirius Wang (王皓昱),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
AngeloGioacchino Del Regno, linux-kernel@vger.kernel.org,
Project_Global_Chrome_Upstream_Group,
dri-devel@lists.freedesktop.org,
linux-mediatek@lists.infradead.org,
Jason-JH Lin (林睿祥),
devicetree@vger.kernel.org, fshao@chromium.org,
krzk+dt@kernel.org, p.zabel@pengutronix.de,
Singo Chang (張興國),
linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
treapking@chromium.org, chunkuang.hu@kernel.org
[-- Attachment #1: Type: text/plain, Size: 1625 bytes --]
On Tue, 2025-03-25 at 03:44 +0000, CK Hu (胡俊光) wrote:
> On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> > 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>
> > ---
>
> [snip]
>
> >
> > +enum mtk_drm_mmsys {
> > + DISPSYS0,
> > + DISPSYS1,
> > + OVLSYS0,
> > + OVLSYS1,
> > + MAX_MMSYS,
> > +};
>
> Let ovlsys sub driver control OVLSYS0 and OVLSYS1, so mediatek drm
> driver would not see them and this patch is not necessary.
>
> Regards,
> CK
>
>
Hi CK,
The DRM Driver needs the distinguish between ovlsys0,
ovlsys1, dispsys0, dispsys1 to connect the main, ext, third
CRTC Paths.
"ovlsys sub driver control OVLSYS0 and OVLSYS1, so mediatek drm
driver would not see them and this patch"
This is significant change, we will fix this modification at the
next version.
Best, Paul
>
>
>
>
[-- Attachment #2: Type: text/html, Size: 3785 bytes --]
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 09/15] drm/mediatek: Refine OVL format convert API and export to public
2025-03-25 2:57 ` CK Hu (胡俊光)
@ 2025-05-13 16:22 ` Paul-pl Chen (陳柏霖)
0 siblings, 0 replies; 42+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-05-13 16:22 UTC (permalink / raw)
To: CK Hu (胡俊光), robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org, chunkuang.hu@kernel.org,
AngeloGioacchino Del Regno
Cc: Sunny Shen (沈姍姍),
Sirius Wang (王皓昱),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
linux-kernel@vger.kernel.org,
Project_Global_Chrome_Upstream_Group,
dri-devel@lists.freedesktop.org,
linux-mediatek@lists.infradead.org,
Jason-JH Lin (林睿祥),
devicetree@vger.kernel.org, fshao@chromium.org,
p.zabel@pengutronix.de, Singo Chang (張興國),
linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
treapking@chromium.org
[-- Attachment #1: Type: text/plain, Size: 13626 bytes --]
On Tue, 2025-03-25 at 02:57 +0000, CK Hu (胡俊光) wrote:
> On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> > From: Nancy Lin <nancy.lin@mediatek.com>
> >
> > Refine OVL format convert API and export to public.
> >
> > 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 | 158 ++++++++++++++++----
> > ----
> > drivers/gpu/drm/mediatek/mtk_disp_ovl.h | 16 +++
> > 2 files changed, 122 insertions(+), 52 deletions(-)
> > create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovl.h
> >
> > diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> > b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> > index d0581c4e3c99..e2b125a717c6 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> > @@ -18,6 +18,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 +63,15 @@
> > /* OVL_CON_RGB_SWAP works only if OVL_CON_CLRFMT_MAN is enabled */
> > #define OVL_CON_RGB_SWAP BIT(25)
> >
> > -#define OVL_CON_CLRFMT_RGB (1 << 12)
> > -#define OVL_CON_CLRFMT_ARGB8888 (2 << 12)
> > -#define OVL_CON_CLRFMT_RGBA8888 (3 << 12)
> > -#define OVL_CON_CLRFMT_ABGR8888 (OVL_CON_CLRFMT_ARGB8888 |
> > OVL_CON_BYTE_SWAP)
> > -#define OVL_CON_CLRFMT_BGRA8888 (OVL_CON_CLRFMT_RGBA8888 |
> > OVL_CON_BYTE_SWAP)
> > -#define OVL_CON_CLRFMT_UYVY (4 << 12)
> > -#define OVL_CON_CLRFMT_YUYV (5 << 12)
> > -#define OVL_CON_MTX_YUV_TO_RGB (6 << 16)
> > -#define OVL_CON_CLRFMT_PARGB8888 ((3 << 12) | OVL_CON_CLRFMT_MAN)
> > -#define OVL_CON_CLRFMT_PABGR8888 (OVL_CON_CLRFMT_PARGB8888 |
> > OVL_CON_RGB_SWAP)
> > -#define OVL_CON_CLRFMT_PBGRA8888 (OVL_CON_CLRFMT_PARGB8888 |
> > OVL_CON_BYTE_SWAP)
> > -#define OVL_CON_CLRFMT_PRGBA8888 (OVL_CON_CLRFMT_PABGR8888 |
> > OVL_CON_BYTE_SWAP)
> > -#define OVL_CON_CLRFMT_RGB565(ovl) ((ovl)->data-
> > >fmt_rgb565_is_0 ? \
> > - 0 : OVL_CON_CLRFMT_RGB)
> > -#define OVL_CON_CLRFMT_RGB888(ovl) ((ovl)->data-
> > >fmt_rgb565_is_0 ? \
> > - OVL_CON_CLRFMT_RGB : 0)
> > +#define OVL_CON_CLRFMT_RGB565(shift) (0 << (shift))
> > +#define OVL_CON_CLRFMT_RGB888(shift) (1 << (shift))
> > +#define OVL_CON_CLRFMT_ARGB8888(shift) (2 << (shift))
> > +#define OVL_CON_CLRFMT_RGBA8888(shift) (3 << (shift))
> > +#define OVL_CON_CLRFMT_UYVY(shift) (4 << (shift))
> > +#define OVL_CON_CLRFMT_YUYV(shift) (5 << (shift))
> > +#define OVL_CON_MTX_YUV_TO_RGB (6 << 16)
> > +#define OVL_CON_CLRFMT_PARGB8888(shift, man) ((3 << (shift)) |
> > (man))
> > +
> > #define OVL_CON_AEN BIT(8)
> > #define OVL_CON_ALPHA 0xff
> > #define OVL_CON_VIRT_FLIP BIT(9)
> > @@ -85,7 +79,7 @@
> >
> > #define OVL_COLOR_ALPHA GENMASK(31, 24)
> >
> > -static inline bool is_10bit_rgb(u32 fmt)
> > +bool mtk_ovl_is_10bit_rgb(unsigned int fmt)
> > {
> > switch (fmt) {
> > case DRM_FORMAT_XRGB2101010:
> > @@ -295,7 +289,7 @@ static void mtk_ovl_set_bit_depth(struct device
> > *dev, int idx, u32 format,
> > if (!ovl->data->supports_clrfmt_ext)
> > return;
> >
> > - if (is_10bit_rgb(format))
> > + if (mtk_ovl_is_10bit_rgb(format))
> > bit_depth = OVL_CON_CLRFMT_10_BIT;
> >
> > mtk_ddp_write_mask(cmdq_pkt,
> > OVL_CON_CLRFMT_BIT_DEPTH(bit_depth, idx),
> > @@ -394,10 +388,26 @@ 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)
> > +bool mtk_ovl_is_ignore_pixel_alpha(struct mtk_plane_state *state,
> > unsigned int blend_mode)
> > +{
>
> This modification is not related to the title, so separate to another
> patch.
>
Sure, I will separate to another patch.
> > + 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;
> > +}
> > +
> > +unsigned int mtk_ovl_get_blend_mode(struct mtk_plane_state *state,
> > unsigned int blend_modes)
> > {
> > - unsigned int fmt = state->pending.format;
> > unsigned int blend_mode = DRM_MODE_BLEND_COVERAGE;
> >
> > /*
> > @@ -412,52 +422,102 @@ static unsigned int
> > mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl,
> > * will get an error return from
> > drm_plane_create_blend_mode_property() and
> > * state->base.pixel_blend_mode should not be used.
> > */
> > - if (ovl->data->blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
> > + if (blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
> > blend_mode = state->base.pixel_blend_mode;
> >
> > + return blend_mode;
> > +}
> > +
> > +unsigned int mtk_ovl_fmt_convert(unsigned int fmt, unsigned int
> > blend_mode,
> > + bool fmt_rgb565_is_0, bool
> > color_convert,
> > + u8 clrfmt_shift, u32 clrfmt_man,
> > u32 byte_swap, u32 rgb_swap)
> > +{
> > + unsigned int con = 0;
> > + bool need_byte_swap = false, need_rgb_swap = false;
> > +
> > switch (fmt) {
> > default:
> > case DRM_FORMAT_RGB565:
> > - return OVL_CON_CLRFMT_RGB565(ovl);
> > + con = fmt_rgb565_is_0 ?
> > + OVL_CON_CLRFMT_RGB565(clrfmt_shift) :
> > OVL_CON_CLRFMT_RGB888(clrfmt_shift);
> > + break;
> > case DRM_FORMAT_BGR565:
> > - return OVL_CON_CLRFMT_RGB565(ovl) |
> > OVL_CON_BYTE_SWAP;
> > + con = fmt_rgb565_is_0 ?
> > + OVL_CON_CLRFMT_RGB565(clrfmt_shift) :
> > OVL_CON_CLRFMT_RGB888(clrfmt_shift);
> > + need_byte_swap = true; /* RGB565 -> BGR565 */
> > + break;
> > case DRM_FORMAT_RGB888:
> > - return OVL_CON_CLRFMT_RGB888(ovl);
> > + con = fmt_rgb565_is_0 ?
> > + OVL_CON_CLRFMT_RGB888(clrfmt_shift) :
> > OVL_CON_CLRFMT_RGB565(clrfmt_shift);
> > + break;
> > case DRM_FORMAT_BGR888:
> > - return OVL_CON_CLRFMT_RGB888(ovl) |
> > OVL_CON_BYTE_SWAP;
> > + con = fmt_rgb565_is_0 ?
> > + OVL_CON_CLRFMT_RGB888(clrfmt_shift) :
> > OVL_CON_CLRFMT_RGB565(clrfmt_shift);
> > + need_byte_swap = true; /* RGB888 -> BGR888 */
> > + break;
> > case DRM_FORMAT_RGBX8888:
> > case DRM_FORMAT_RGBA8888:
> > case DRM_FORMAT_RGBX1010102:
> > case DRM_FORMAT_RGBA1010102:
> > - return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> > - OVL_CON_CLRFMT_RGBA8888 :
> > - OVL_CON_CLRFMT_PRGBA8888;
> > + if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
> > + con =
> > OVL_CON_CLRFMT_RGBA8888(clrfmt_shift);
> > + } else {
> > + con =
> > OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
> > + need_byte_swap = true; /* PARGB8888 ->
> > PBGRA8888 */
> > + need_rgb_swap = true; /* PBGRA8888 ->
> > PRGBA8888 */
> > + }
> > + break;
> > case DRM_FORMAT_BGRX8888:
> > case DRM_FORMAT_BGRA8888:
> > case DRM_FORMAT_BGRX1010102:
> > case DRM_FORMAT_BGRA1010102:
> > - return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> > - OVL_CON_CLRFMT_BGRA8888 :
> > - OVL_CON_CLRFMT_PBGRA8888;
> > + if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
> > + con =
> > OVL_CON_CLRFMT_RGBA8888(clrfmt_shift);
> > + need_byte_swap = true; /* RGB8888 ->
> > BGR8888 */
> > + } else {
> > + con =
> > OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
> > + need_byte_swap = true; /* PARGB8888 ->
> > PBGRA8888 */
> > + }
> > + break;
> > case DRM_FORMAT_XRGB8888:
> > case DRM_FORMAT_ARGB8888:
> > case DRM_FORMAT_XRGB2101010:
> > case DRM_FORMAT_ARGB2101010:
> > - return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> > - OVL_CON_CLRFMT_ARGB8888 :
> > - OVL_CON_CLRFMT_PARGB8888;
> > + if (blend_mode == DRM_MODE_BLEND_COVERAGE)
> > + con =
> > OVL_CON_CLRFMT_ARGB8888(clrfmt_shift);
> > + else
> > + con =
> > OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
> > + break;
> > case DRM_FORMAT_XBGR8888:
> > case DRM_FORMAT_ABGR8888:
> > case DRM_FORMAT_XBGR2101010:
> > case DRM_FORMAT_ABGR2101010:
> > - return blend_mode == DRM_MODE_BLEND_COVERAGE ?
> > - OVL_CON_CLRFMT_ABGR8888 :
> > - OVL_CON_CLRFMT_PABGR8888;
> > + if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
> > + con =
> > OVL_CON_CLRFMT_ARGB8888(clrfmt_shift);
> > + need_rgb_swap = true; /* ARGB8888 ->
> > ABGR8888 */
> > + } else {
> > + con =
> > OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
> > + need_rgb_swap = true; /* PARGB8888 ->
> > PABGR8888 */
> > + }
> > + break;
> > case DRM_FORMAT_UYVY:
> > - return OVL_CON_CLRFMT_UYVY |
> > OVL_CON_MTX_YUV_TO_RGB;
> > + con = OVL_CON_CLRFMT_UYVY(clrfmt_shift);
> > + break;
> > case DRM_FORMAT_YUYV:
> > - return OVL_CON_CLRFMT_YUYV |
> > OVL_CON_MTX_YUV_TO_RGB;
> > + con = OVL_CON_CLRFMT_YUYV(clrfmt_shift);
> > + break;
> > }
> > +
> > + if (color_convert)
> > + con |= OVL_CON_MTX_YUV_TO_RGB;
>
> Only YUV need this. RGB do not need this.
>
> OK I will fix this part.
> > +
> > + 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,
> > @@ -495,7 +555,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);
>
> This modification is not related to the title, so separate to another
> patch.
>
> Sure, I will separate to another patch.
> > unsigned int ignore_pixel_alpha = 0;
> > unsigned int con;
> >
> > @@ -504,7 +564,8 @@ void mtk_ovl_layer_config(struct device *dev,
> > unsigned int idx,
> > return;
> > }
> >
> > - con = mtk_ovl_fmt_convert(ovl, state);
> > + con = mtk_ovl_fmt_convert(fmt, blend_mode, ovl->data-
> > >fmt_rgb565_is_0, true,
> > + 12, OVL_CON_CLRFMT_MAN,
> > OVL_CON_BYTE_SWAP, OVL_CON_RGB_SWAP);
> > if (state->base.fb) {
> > con |= state->base.alpha & OVL_CON_ALPHA;
> >
> > @@ -512,17 +573,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)
>
> This modification is not related to the title, so separate to another
> patch.
>
> Sure, I will separate to another patch.
> > 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;
> > }
> >
> > /*
> > @@ -548,6 +600,8 @@ 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));
> > +
> > + ignore_pixel_alpha = mtk_ovl_is_ignore_pixel_alpha(state,
> > blend_mode) ? OVL_CONST_BLEND : 0;
> > mtk_ddp_write_relaxed(cmdq_pkt, pitch_lsb |
> > ignore_pixel_alpha,
> > &ovl->cmdq_reg, ovl->regs,
> > DISP_REG_OVL_PITCH(idx));
> > mtk_ddp_write_relaxed(cmdq_pkt, src_size, &ovl->cmdq_reg,
> > ovl->regs,
> > diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
> > b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
> > new file mode 100644
> > index 000000000000..9bd5dc62d626
> > --- /dev/null
> > +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
> > @@ -0,0 +1,16 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * Copyright (c) 2025 MediaTek Inc.
> > + */
> > +
> > +#ifndef __MTK_DISP_OVL_H__
> > +#define __MTK_DISP_OVL_H__
> > +
> > +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);
> > +
> > +#endif
>
[-- Attachment #2: Type: text/html, Size: 23819 bytes --]
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 11/15] drm/mediatek: add BLENDER support for MT8196
2025-03-24 8:33 ` CK Hu (胡俊光)
@ 2025-05-13 17:12 ` Paul-pl Chen (陳柏霖)
0 siblings, 0 replies; 42+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-05-13 17:12 UTC (permalink / raw)
To: CK Hu (胡俊光), robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org, chunkuang.hu@kernel.org,
AngeloGioacchino Del Regno
Cc: Sunny Shen (沈姍姍),
Sirius Wang (王皓昱),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
linux-kernel@vger.kernel.org,
Project_Global_Chrome_Upstream_Group,
dri-devel@lists.freedesktop.org,
linux-mediatek@lists.infradead.org,
Jason-JH Lin (林睿祥),
devicetree@vger.kernel.org, fshao@chromium.org,
p.zabel@pengutronix.de, Singo Chang (張興國),
linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
treapking@chromium.org
[-- Attachment #1: Type: text/plain, Size: 11819 bytes --]
On Mon, 2025-03-24 at 08:33 +0000, CK Hu (胡俊光) wrote:
> On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> > 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 | 276
> > ++++++++++++++++++++
> > drivers/gpu/drm/mediatek/mtk_disp_blender.h | 18 ++
> > drivers/gpu/drm/mediatek/mtk_disp_drv.h | 12 +
> > drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 +
> > drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 +
> > 8 files changed, 311 insertions(+)
> > create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_blender.c
> > create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_blender.h
> >
> > diff --git a/drivers/gpu/drm/mediatek/Makefile
> > b/drivers/gpu/drm/mediatek/Makefile
> > index db92f4fb353d..a7b9ebe27f68 100644
> > --- a/drivers/gpu/drm/mediatek/Makefile
> > +++ b/drivers/gpu/drm/mediatek/Makefile
> > @@ -3,6 +3,7 @@
> > mediatek-drm-y := mtk_crtc.o \
> > mtk_ddp_comp.o \
> > mtk_disp_aal.o \
> > + mtk_disp_blender.o \
> > mtk_disp_ccorr.o \
> > mtk_disp_color.o \
> > mtk_disp_exdma.o \
> > diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > index 3e0739d8e6f1..e65c6df987f2 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > @@ -445,6 +445,7 @@ static const char * const
> > mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
> > [MTK_DP_INTF] = "dp-intf",
> > [MTK_DPI] = "dpi",
> > [MTK_DSI] = "dsi",
> > + [MTK_OVL_BLENDER] = "blender",
> > [MTK_OVL_EXDMA] = "exdma",
> > };
> >
> > diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > index 86dc0ee3924c..075ba5683f93 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > @@ -43,6 +43,7 @@ enum mtk_ddp_comp_type {
> > MTK_DPI,
> > MTK_DP_INTF,
> > MTK_DSI,
> > + MTK_OVL_BLENDER,
> > MTK_OVL_EXDMA,
> > MTK_DDP_COMP_TYPE_MAX,
> > };
> > diff --git a/drivers/gpu/drm/mediatek/mtk_disp_blender.c
> > b/drivers/gpu/drm/mediatek/mtk_disp_blender.c
> > new file mode 100644
> > index 000000000000..32c9e3d463a4
> > --- /dev/null
> > +++ b/drivers/gpu/drm/mediatek/mtk_disp_blender.c
> > @@ -0,0 +1,276 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (c) 2025 MediaTek Inc.
> > + */
> > +
> > +#include <drm/drm_fourcc.h>
> > +#include <drm/drm_blend.h>
> > +#include <drm/drm_framebuffer.h>
> > +#include <linux/clk.h>
> > +#include <linux/component.h>
> > +#include <linux/of.h>
> > +#include <linux/of_device.h>
> > +#include <linux/of_address.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/reset.h>
> > +#include <linux/soc/mediatek/mtk-cmdq.h>
> > +#include <linux/soc/mediatek/mtk-mmsys.h>
> > +
> > +#include "mtk_crtc.h"
> > +#include "mtk_ddp_comp.h"
> > +#include "mtk_disp_drv.h"
> > +#include "mtk_drm_drv.h"
> > +#include "mtk_disp_blender.h"
> > +#include "mtk_disp_ovl.h"
> > +
> > +#define OVL_BLD_ALPHA 0xff
> > +#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_PITCH 0x208
>
> DISP_REG_OVL_BLD_L0_PITCH is useless, so drop it.
>
>
> This will be used in the mtk_disp_blender_config.
Sorry for the misleading, the naming would be
#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)
> > +#define
> > OVL_BLD_L0_SRC_PITCH GENMASK(15, 0)
> > +#define DISP_REG_OVL_BLD_PITCH 0x2f4
> > +
> > +struct mtk_disp_blender {
> > + void __iomem *regs;
> > + struct clk *clk;
> > + struct cmdq_client_reg cmdq_reg;
> > +};
> > +
> > +void mtk_disp_blender_layer_config(struct device *dev, struct
> > mtk_plane_state *state,
> > + struct cmdq_pkt *cmdq_pkt)
> > +{
> > + struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> > + struct mtk_plane_pending_state *pending = &state->pending;
> > + unsigned int align_width = ALIGN_DOWN(pending->width, 2);
>
> If width is 101, changing width to 100 would get correct display
> output?
>
>
Yes, according to our internal experiments, the ALIGN_DOWN code can
be removed simultaneously from the drives for "EXDMA, BLENDER,
OVLSYS_ADAPTOR". I will fix it.
>
> > + unsigned int alpha;
> > + unsigned int clrfmt;
> > + unsigned int blend_mode = mtk_ovl_get_blend_mode(state,
> > +
> > BIT(DRM_MODE_BLEND_PREMULTI) |
> > +
> > BIT(DRM_MODE_BLEND_COVERAGE) |
> > +
> > BIT(DRM_MODE_BLEND_PIXEL_NONE));
> > + unsigned int ignore_pixel_alpha = 0;
> > +
> > + if (!pending->enable) {
> > + mtk_ddp_write(cmdq_pkt, 0, &priv->cmdq_reg, priv-
> > >regs, DISP_REG_OVL_BLD_L_EN);
> > + return;
> > + }
> > +
> > + mtk_ddp_write(cmdq_pkt, pending->y << 16 | pending->x,
> > &priv->cmdq_reg, priv->regs,
> > + DISP_REG_OVL_BLD_OFFSET);
> > +
> > + mtk_ddp_write(cmdq_pkt, pending->height << 16 |
> > align_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);
> > +
> > + alpha = (OVL_BLD_ALPHA & (state->base.alpha >> 8)) |
> > + OVL_BLD_L_ALPHA_EN;
> > +
> > + if (mtk_ovl_is_ignore_pixel_alpha(state, blend_mode))
> > + ignore_pixel_alpha = OVL_BLD_L0_CONST;
> > +
> > + mtk_ddp_write_mask(cmdq_pkt, pending->pitch |
> > ignore_pixel_alpha,
> > + &priv->cmdq_reg, priv->regs,
> > + DISP_REG_OVL_BLD_PITCH,
> > OVL_BLD_L0_CONST | OVL_BLD_L0_SRC_PITCH);
>
> EXDMA already has pitch function, why BLENDER also has pitch
> function?
> What does BLENDER pitch do?
The input source of blender layer can be EXDMA layer output or
the blender constanat itself.
The color setting is configured for the blender constant layer.
>
> > +
> > + mtk_ddp_write_mask(cmdq_pkt, alpha, &priv->cmdq_reg, priv-
> > >regs,
> > + DISP_REG_OVL_BLD_L_CON2,
> > OVL_BLD_L_ALPHA_EN | OVL_BLD_L_ALPHA);
> > +
> > + mtk_ddp_write(cmdq_pkt, OVL_BLD_L_EN, &priv->cmdq_reg,
> > priv->regs, DISP_REG_OVL_BLD_L_EN);
> > +}
> > +
> > +void mtk_disp_blender_config(struct device *dev, unsigned int w,
> > + unsigned int h, unsigned int
> > vrefresh,
> > + unsigned int bpc, bool most_top,
> > + bool most_bottom, struct cmdq_pkt
> > *cmdq_pkt)
> > +{
> > + struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> > + u32 datapath;
> > +
> > + dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
> > + mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg,
> > priv->regs,
> > + DISP_REG_OVL_BLD_ROI_SIZE);
> > + mtk_ddp_write(cmdq_pkt, DISP_REG_OVL_BLD_BGCLR_BALCK,
> > &priv->cmdq_reg, priv->regs,
> > + DISP_REG_OVL_BLD_BGCLR_CLR);
> > + mtk_ddp_write(cmdq_pkt, DISP_REG_OVL_BLD_BGCLR_BALCK,
> > &priv->cmdq_reg, priv->regs,
> > + DISP_REG_OVL_BLD_L0_CLR);
>
> I think I know what is BGLCR_CLR, but what is L0_CLR?
>
>
DISP_REG_OVL_BLD_L0_CLR controls te constant color for each
individual layer,
while OVL_BLD_BGCLR_CLR controls the background color for
the entire display.
>
>
>
> > +
> > + if (most_top)
> > + datapath = OVL_BLD_BGCLR_OUT_TO_PROC;
> > + else
> > + datapath = OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER;
> > + /*
> > + * The primary input is from EXDMA and the second input
> > + * is optionally from another blender
> > + */
> > + if (!most_bottom)
> > + datapath |= OVL_BLD_BGCLR_IN_SEL;
> > +
> > + mtk_ddp_write_mask(cmdq_pkt, datapath,
> > + &priv->cmdq_reg, priv->regs,
> > DISP_REG_OVL_BLD_DATAPATH_CON,
> > + OVL_BLD_BGCLR_OUT_TO_PROC |
> > OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER |
> > + OVL_BLD_BGCLR_IN_SEL);
> > +}
> > +
> > +void mtk_disp_blender_start(struct device *dev, struct cmdq_pkt
> > *cmdq_pkt)
> > +{
> > + struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> > + unsigned int tmp;
> > +
> > + tmp = readl(priv->regs + DISP_REG_OVL_BLD_SHADOW_CTRL);
> > + tmp = tmp | OVL_BLD_BYPASS_SHADOW;
> > + writel(tmp, priv->regs + DISP_REG_OVL_BLD_SHADOW_CTRL);
> > + mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_EN, &priv->cmdq_reg,
> > priv->regs,
> > + DISP_REG_OVL_BLD_EN, OVL_BLD_EN);
> > +}
> > +
> > +void mtk_disp_blender_stop(struct device *dev, struct cmdq_pkt
> > *cmdq_pkt)
> > +{
> > + struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> > +
> > + mtk_ddp_write(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> > DISP_REG_OVL_BLD_L_EN);
> > + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv-
> > >regs,
> > + DISP_REG_OVL_BLD_EN, OVL_BLD_EN);
>
> You already control OVL_BLD_EN in layer config, so it's not necessary
> to control here.
>
> Regards,
> CK
>
> OK I will fix it.
>
> Best, Paul
>
> > + mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_RST, &priv->cmdq_reg,
> > priv->regs,
> > + DISP_REG_OVL_BLD_RST, OVL_BLD_RST);
> > + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv-
> > >regs,
> > + DISP_REG_OVL_BLD_RST, OVL_BLD_RST);
> > +}
> > +
> >
>
[-- Attachment #2: Type: text/html, Size: 20335 bytes --]
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 10/15] drm/mediatek: add EXDMA support for MT8196
2025-03-24 3:00 ` CK Hu (胡俊光)
@ 2025-05-14 10:00 ` Paul-pl Chen (陳柏霖)
0 siblings, 0 replies; 42+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-05-14 10:00 UTC (permalink / raw)
To: CK Hu (胡俊光), robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org, chunkuang.hu@kernel.org,
AngeloGioacchino Del Regno
Cc: Sunny Shen (沈姍姍),
Sirius Wang (王皓昱),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
linux-kernel@vger.kernel.org,
Project_Global_Chrome_Upstream_Group,
dri-devel@lists.freedesktop.org,
linux-mediatek@lists.infradead.org,
Jason-JH Lin (林睿祥),
devicetree@vger.kernel.org, fshao@chromium.org,
p.zabel@pengutronix.de, Singo Chang (張興國),
linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
treapking@chromium.org
[-- Attachment #1: Type: text/plain, Size: 23273 bytes --]
On Mon, 2025-03-24 at 03:00 +0000, CK Hu (胡俊光) wrote:
> On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> > From: Nancy Lin <nancy.lin@mediatek.com>
> >
> > EXDMA is a DMA engine for reading data from DRAM with
> > various DRAM footprints and data formats. For input
> > sources in certain color formats and color domains,
> > EXDMA also includes a color transfer function to
> > process pixels into a consistent color domain.
> > New Add: 6320385 Fix RG16 and refine RG24
> >
> > Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
> > Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> > ---
> > drivers/gpu/drm/mediatek/Makefile | 1 +
> > drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 1 +
> > drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 1 +
> > drivers/gpu/drm/mediatek/mtk_disp_drv.h | 9 +
> > drivers/gpu/drm/mediatek/mtk_disp_exdma.c | 372
> > ++++++++++++++++++++++
> > drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 +
> > drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 +
> > 7 files changed, 386 insertions(+)
> > create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_exdma.c
> >
> > diff --git a/drivers/gpu/drm/mediatek/Makefile
> > b/drivers/gpu/drm/mediatek/Makefile
> > index 32a2ed6c0cfe..db92f4fb353d 100644
> > --- a/drivers/gpu/drm/mediatek/Makefile
> > +++ b/drivers/gpu/drm/mediatek/Makefile
> > @@ -5,6 +5,7 @@ mediatek-drm-y := mtk_crtc.o \
> > mtk_disp_aal.o \
> > mtk_disp_ccorr.o \
> > mtk_disp_color.o \
> > + mtk_disp_exdma.o \
> > mtk_disp_gamma.o \
> > mtk_disp_merge.o \
> > mtk_disp_ovl.o \
> > diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > index edc6417639e6..3e0739d8e6f1 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > @@ -445,6 +445,7 @@ static const char * const
> > mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
> > [MTK_DP_INTF] = "dp-intf",
> > [MTK_DPI] = "dpi",
> > [MTK_DSI] = "dsi",
> > + [MTK_OVL_EXDMA] = "exdma",
> > };
> >
> > struct mtk_ddp_comp_match {
> > diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > index 39720b27f4e9..86dc0ee3924c 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > @@ -43,6 +43,7 @@ enum mtk_ddp_comp_type {
> > MTK_DPI,
> > MTK_DP_INTF,
> > MTK_DSI,
> > + MTK_OVL_EXDMA,
> > MTK_DDP_COMP_TYPE_MAX,
> > };
> >
> > diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> > b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> > index 04217a36939c..4e3d2510bef5 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> > +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> > @@ -39,6 +39,15 @@ void mtk_color_config(struct device *dev,
> > unsigned int w,
> > unsigned int bpc, struct cmdq_pkt
> > *cmdq_pkt);
> > void mtk_color_start(struct device *dev);
> >
> > +int mtk_disp_exdma_clk_enable(struct device *dev);
> > +void mtk_disp_exdma_clk_disable(struct device *dev);
> > +void mtk_disp_exdma_start(struct device *dev, struct cmdq_pkt
> > *cmdq_pkt);
> > +void mtk_disp_exdma_stop(struct device *dev, struct cmdq_pkt
> > *cmdq_pkt);
> > +void mtk_disp_exdma_layer_config(struct device *dev, struct
> > mtk_plane_state *state,
> > + struct cmdq_pkt *cmdq_pkt);
> > +const u32 *mtk_disp_exdma_get_formats(struct device *dev);
> > +size_t mtk_disp_exdma_get_num_formats(struct device *dev);
> > +
> > void mtk_dither_set_common(void __iomem *regs, struct
> > cmdq_client_reg *cmdq_reg,
> > unsigned int bpc, unsigned int cfg,
> > unsigned int dither_en, struct cmdq_pkt
> > *cmdq_pkt);
> > diff --git a/drivers/gpu/drm/mediatek/mtk_disp_exdma.c
> > b/drivers/gpu/drm/mediatek/mtk_disp_exdma.c
> > new file mode 100644
> > index 000000000000..d4f7021f98d7
> > --- /dev/null
> > +++ b/drivers/gpu/drm/mediatek/mtk_disp_exdma.c
> > @@ -0,0 +1,372 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (c) 2025 MediaTek Inc.
> > + */
> > +
> > +#include <drm/drm_fourcc.h>
> > +#include <drm/drm_blend.h>
> > +#include <drm/drm_framebuffer.h>
> > +#include <linux/clk.h>
> > +#include <linux/component.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of_device.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/pm_runtime.h>
> > +#include <linux/soc/mediatek/mtk-cmdq.h>
> > +
> > +#include "mtk_disp_drv.h"
> > +#include "mtk_drm_drv.h"
> > +#include "mtk_disp_ovl.h"
> > +
> > +#define DISP_REG_OVL_EXDMA_EN_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_OFFSET 0x044
>
> DISP_REG_OVL_EXDMA_OFFSET is useless, so drop it.
>
>
Sorry, this is misleading naming, I will change it to
DISP_REG_OVL_EXDMA_L0_OFFSET. It woulde use in the driver
>
>
> > +#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 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)
>
> OVL_EXDMA_MOUT_OUT_DATA is useless, so drop it.
It would used in the driver mtk_disp_exdma_start()
in the next version of the patch.
>
> > +#define OVL_EXDMA_MOUT_BGCLR_OUT BIT(1)
> > +
> > +static const u32 formats[] = {
> > + DRM_FORMAT_XRGB8888,
> > + DRM_FORMAT_ARGB8888,
> > + DRM_FORMAT_BGRX8888,
> > + DRM_FORMAT_BGRA8888,
> > + DRM_FORMAT_ABGR8888,
> > + DRM_FORMAT_XBGR8888,
> > + DRM_FORMAT_RGBX8888,
> > + DRM_FORMAT_RGBA8888,
> > + DRM_FORMAT_RGB888,
> > + DRM_FORMAT_BGR888,
> > + DRM_FORMAT_RGB565,
> > + DRM_FORMAT_BGR565,
>
> In this version, you add BGR565. If mt8195 also support BGR565, add
> BGR565 to mt8195_formats[] and merge these two array.
>
Sure, I will fix it.
>
> > + DRM_FORMAT_UYVY,
> > + DRM_FORMAT_YUYV,
> > + DRM_FORMAT_XRGB2101010,
> > + DRM_FORMAT_ARGB2101010,
> > + DRM_FORMAT_RGBX1010102,
> > + DRM_FORMAT_RGBA1010102,
> > + DRM_FORMAT_XBGR2101010,
> > + DRM_FORMAT_ABGR2101010,
> > + DRM_FORMAT_BGRX1010102,
> > + DRM_FORMAT_BGRA1010102,
> > +};
> > +
> > +struct mtk_disp_exdma {
> > + void __iomem *regs;
> > + struct clk *clk;
> > + struct cmdq_client_reg cmdq_reg;
> > + struct device *larb;
> > +};
> > +
> > +static unsigned int mtk_disp_exdma_color_convert(unsigned int
> > color_encoding)
> > +{
> > + switch (color_encoding) {
> > + default:
> > + case DRM_COLOR_YCBCR_BT709:
> > + return OVL_EXDMA_CON_INT_MTX_BT709_TO_RGB;
> > + case DRM_COLOR_YCBCR_BT601:
> > + return OVL_EXDMA_CON_INT_MTX_BT601_TO_RGB;
> > + }
> > +}
> > +
> > +void mtk_disp_exdma_start(struct device *dev, struct cmdq_pkt
> > *cmdq_pkt)
> > +{
> > + struct mtk_disp_exdma *priv = dev_get_drvdata(dev);
> > + unsigned int value = 0, mask = 0;
>
> It's not necessary to initialize these variable.
Sure, I will fix it.
>
> > +
> > + value = OVL_EXDMA_RDMA_BURST_CON1_BURST16_EN |
> > OVL_EXDMA_RDMA_BURST_CON1_DDR_ACK_EN;
> > + mask = OVL_EXDMA_RDMA_BURST_CON1_BURST16_EN |
> > OVL_EXDMA_RDMA_BURST_CON1_DDR_EN |
> > + OVL_EXDMA_RDMA_BURST_CON1_DDR_ACK_EN;
>
> It seems that you clear OVL_EXDMA_RDMA_BURST_CON1_DDR_EN. Describe
> why you clear it.
This configuration of clear OVL_EXDMA_RDMA_BURST_CON1_DDR_EN is to
enable dynamic power switching mechanism for EXDMA, which is "SRT" mode
The SRT mode will have better power efficiency.
>
> > + mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv-
> > >regs,
> > + DISP_REG_OVL_EXDMA_RDMA_BURST_CON1,
> > mask);
> > + /*
> > + * The dummy register is used in the configuration of the
> > EXDMA engine to
> > + * write commands to DRAM, ensuring that data transfers
> > occur normally.
>
> EXDMA would write data into DRAM? Describe more clear so I could
> understand this.
>
> > + */
> > + value = OVL_EXDMA_EXT_DDR_EN_OPT |
> > OVL_EXDMA_FORCE_EXT_DDR_EN;
> > + mask = OVL_EXDMA_EXT_DDR_EN_OPT |
> > OVL_EXDMA_FORCE_EXT_DDR_EN;
>
> mask is identical to value, so just use value.
OK I will make it clean to value.
>
> > + mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv-
> > >regs,
> > + DISP_REG_OVL_EXDMA_DUMMY_REG, mask);
> > +
> > + value = OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN |
> > + OVL_EXDMA_DATAPATH_CON_HDR_GCLAST_EN |
> > + OVL_EXDMA_DATAPATH_CON_GCLAST_EN;
> > + mask = OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN |
> > + OVL_EXDMA_DATAPATH_CON_HDR_GCLAST_EN |
> > + OVL_EXDMA_DATAPATH_CON_GCLAST_EN;
> > + mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv-
> > >regs,
> > + DISP_REG_OVL_EXDMA_DATAPATH_CON, mask);
> > +
> > + mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_MOUT_BGCLR_OUT,
> > &priv->cmdq_reg,
> > + priv->regs, DISP_REG_OVL_EXDMA_MOUT,
> > + OVL_EXDMA_MOUT_BGCLR_OUT |
> > OVL_EXDMA_MOUT_OUT_DATA);
> > +
> > + mtk_ddp_write(cmdq_pkt, ~0, &priv->cmdq_reg, priv->regs,
> > DISP_REG_OVL_EXDMA_GDRDY_PRD);
> > +
> > + mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_RDMA0_EN, &priv-
> > >cmdq_reg, priv->regs,
> > + DISP_REG_OVL_EXDMA_RDMA0_CTRL,
> > OVL_EXDMA_RDMA0_EN);
>
> EXDMA has layer config function, and RDMA would enable/disable by
> layer, so move OVL_EXDMA_RDMA0_EN config to layer config function.
>
> > + mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_L0_EN, &priv-
> > >cmdq_reg, priv->regs,
> > + DISP_REG_OVL_EXDMA_L0_EN,
> > OVL_EXDMA_L0_EN);
>
> EXDMA has layer config function, and L0 would enable/disable by
> layer, so move OVL_EXDMA_L0_EN config to layer config function.
OK I will fix move the config to the layer configuation function.
>
> > +
> > + mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_EN, &priv-
> > >cmdq_reg, priv->regs,
> > + DISP_REG_OVL_EXDMA_EN, OVL_EXDMA_EN);
> > +}
> > +
> > +void mtk_disp_exdma_stop(struct device *dev, struct cmdq_pkt
> > *cmdq_pkt)
> > +{
> > + struct mtk_disp_exdma *priv = dev_get_drvdata(dev);
> > +
> > + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv-
> > >regs,
> > + DISP_REG_OVL_EXDMA_EN, OVL_EXDMA_EN);
> > + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv-
> > >regs,
> > + DISP_REG_OVL_EXDMA_RDMA0_CTRL,
> > OVL_EXDMA_RDMA0_EN);
> > + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv-
> > >regs,
> > + DISP_REG_OVL_EXDMA_DATAPATH_CON,
> > OVL_EXDMA_DATAPATH_CON_LAYER_SMI_ID_EN);
> > + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv-
> > >regs,
> > + DISP_REG_OVL_EXDMA_L0_EN,
> > OVL_EXDMA_L0_EN);
> > + mtk_ddp_write_mask(cmdq_pkt, OVL_EXDMA_RST, &priv-
> > >cmdq_reg, priv->regs,
> > + DISP_REG_OVL_EXDMA_RST, OVL_EXDMA_RST);
> > + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv-
> > >regs,
> > + DISP_REG_OVL_EXDMA_RST, OVL_EXDMA_RST);
> > +}
> > +
> > +void mtk_disp_exdma_layer_config(struct device *dev, struct
> > mtk_plane_state *state,
> > + struct cmdq_pkt *cmdq_pkt)
> > +{
> > + struct mtk_disp_exdma *priv = dev_get_drvdata(dev);
> > + struct mtk_plane_pending_state *pending = &state->pending;
> > + const struct drm_format_info *fmt_info =
> > drm_format_info(pending->format);
> > + unsigned int align_width = 0;
> > + bool csc_enable = (fmt_info) ? fmt_info->is_yuv : false;
> > + unsigned int blend_mode = mtk_ovl_get_blend_mode(state,
> > +
> > BIT(DRM_MODE_BLEND_PREMULTI) |
> > +
> > BIT(DRM_MODE_BLEND_COVERAGE) |
> > +
> > BIT(DRM_MODE_BLEND_PIXEL_NONE));
> > + unsigned int val = 0;
>
> It's not necessary to initialize val.
>
OK I will fix it.
> > + unsigned int clrfmt_mask = OVL_EXDMA_CON_RGB_SWAP |
> > + OVL_EXDMA_CON_BYTE_SWAP |
> > + OVL_EXDMA_CON_CLRFMT_MAN |
> > + OVL_EXDMA_CON_FLD_CLRFMT |
> > + OVL_EXDMA_CON_FLD_CLRFMT_NB;
> > +
> > + if (!pending->enable) {
> > + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg,
> > priv->regs,
> > + DISP_REG_OVL_EXDMA_RDMA0_CTRL,
> > OVL_EXDMA_RDMA0_EN);
> > + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg,
> > priv->regs,
> > + DISP_REG_OVL_EXDMA_L0_EN,
> > OVL_EXDMA_L0_EN);
> > + return;
> > + }
> > +
> > + /* OVLSYS is in 1T2P domain, width needs to be 2 pixels
> > align */
> > + align_width = ALIGN_DOWN(pending->width, 2);
>
> If width is 101, change width to 100 would get correct display
> output?
>
yes, and i will remove this ALIGN_DOWN.
> > +
> > + mtk_ddp_write(cmdq_pkt, pending->height << 16 |
> > align_width, &priv->cmdq_reg,
> > + priv->regs, DISP_REG_OVL_EXDMA_ROI_SIZE);
> > +
> > + mtk_ddp_write(cmdq_pkt, pending->height << 16 |
> > align_width, &priv->cmdq_reg,
> > + priv->regs, DISP_REG_OVL_EXDMA_SRC_SIZE);
> > + mtk_ddp_write(cmdq_pkt, pending->height << 16 |
> > align_width, &priv->cmdq_reg,
> > + priv->regs, DISP_REG_OVL_EXDMA_SRC_SIZE);
>
> Why do you duplicate DISP_REG_OVL_EXDMA_SRC_SIZE register setting?
Yes this is the redundant code, I will fix it.
>
> > +
> > + mtk_ddp_write_mask(cmdq_pkt, pending->pitch, &priv-
> > >cmdq_reg,
> > + priv->regs, DISP_REG_OVL_EXDMA_PITCH,
> > OVL_EXDMA_L0_SRC_PITCH_MASK);
> > + mtk_ddp_write_mask(cmdq_pkt, pending->pitch >> 16, &priv-
> > >cmdq_reg, priv->regs,
> > + DISP_REG_OVL_EXDMA_PITCH_MSB, 0xf);
>
> Symbolize 0xf.
Sure, we will Symbolize the magic number.
>
> > +
> > + val = mtk_disp_exdma_color_convert(pending-
> > >color_encoding);
> > + if (csc_enable)
> > + val |= OVL_EXDMA_CON_INT_MTX_EN;
> > + mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv-
> > >regs, DISP_REG_OVL_EXDMA_CON,
> > + OVL_EXDMA_CON_FLD_INT_MTX_SEL |
> > OVL_EXDMA_CON_INT_MTX_EN);
>
> You have no way to disable csc.
> If first frame is YUV format, you enable csc.
> And second frame is RGB, you does not disable csc, so RGB would do
> csc and display incorrect result.
>
>
I have checked when the val is equal to zero, it will clear the bit
OVL_EXDMA_CON_INIT_MTX_EN. So we don't have to worry this problem.
> > +
> > + val = mtk_ovl_fmt_convert(pending->format, blend_mode,
> > true, false, 0,
> > + OVL_EXDMA_CON_CLRFMT_MAN,
> > OVL_EXDMA_CON_BYTE_SWAP,
> > + OVL_EXDMA_CON_RGB_SWAP);
> > + if (mtk_ovl_is_10bit_rgb(pending->format))
> > + val |= OVL_EXDMA_CON_CLRFMT_NB_10_BIT;
> > + mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv-
> > >regs,
> > + DISP_REG_OVL_EXDMA_L0_CLRFMT,
> > clrfmt_mask);
> > +
> > + val = OVL_EXDMA_HG_FOVL_EXDMA_CK_ON |
> > OVL_EXDMA_HF_FOVL_EXDMA_CK_ON |
>
> Does CK_ON mean clock on? If so, where do you turn off the clock?
>
OK, I will add the code to turn off it.
>
> > + OVL_EXDMA_OP_8BIT_MODE;
> > + mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv-
> > >regs,
> > + DISP_REG_OVL_EXDMA_EN_CON, val);
> > +
> > + val = OVL_EXDMA_RDMA0_L0_VCSEL |
> > OVL_EXDMA_RDMA0_HDR_L0_VCSEL;
> > + mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv-
> > >regs,
> > + DISP_REG_OVL_EXDMA_L0_GUSER_EXT, val);
> > +
> > + val = pending->pitch;
> > + if (mtk_ovl_is_ignore_pixel_alpha(state, blend_mode))
> > + val |= OVL_EXDMA_L0_CONST_BLD;
> > + mtk_ddp_write_mask(cmdq_pkt, val, &priv->cmdq_reg, priv-
> > >regs, DISP_REG_OVL_EXDMA_PITCH,
> > + OVL_EXDMA_L0_CONST_BLD |
> > OVL_EXDMA_L0_SRC_PITCH);
> > +}
> > +
> > +const u32 *mtk_disp_exdma_get_formats(struct device *dev)
> > +{
> > + return formats;
> > +}
> > +
> > +size_t mtk_disp_exdma_get_num_formats(struct device *dev)
> > +{
> > + return ARRAY_SIZE(formats);
> > +}
> > +
> > +int mtk_disp_exdma_clk_enable(struct device *dev)
> > +{
> > + struct mtk_disp_exdma *exdma = dev_get_drvdata(dev);
> > +
> > + return clk_prepare_enable(exdma->clk);
> > +}
> > +
> > +void mtk_disp_exdma_clk_disable(struct device *dev)
> > +{
> > + struct mtk_disp_exdma *exdma = dev_get_drvdata(dev);
> > +
> > + clk_disable_unprepare(exdma->clk);
> > +}
> > +
> > +static int mtk_disp_exdma_bind(struct device *dev, struct device
> > *master,
> > + void *data)
> > +{
> > + return 0;
> > +}
> > +
> > +static void mtk_disp_exdma_unbind(struct device *dev, struct
> > device *master,
> > + void *data)
> > +{
> > +}
> > +
> > +static const struct component_ops mtk_disp_exdma_component_ops = {
> > + .bind = mtk_disp_exdma_bind,
> > + .unbind = mtk_disp_exdma_unbind,
> > +};
> > +
> > +static int mtk_disp_exdma_probe(struct platform_device *pdev)
> > +{
> > + struct device *dev = &pdev->dev;
> > + struct platform_device *larb_pdev = NULL;
> > + struct device_node *larb_node = NULL;
> > + struct resource *res;
> > + struct mtk_disp_exdma *priv;
> > + int ret = 0;
> > +
> > + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> > + if (!priv)
> > + return -ENOMEM;
> > +
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > + priv->regs = devm_ioremap_resource(dev, res);
> > + if (IS_ERR(priv->regs)) {
> > + dev_err(dev, "failed to ioremap exdma\n");
> > + return PTR_ERR(priv->regs);
> > + }
> > +
> > + priv->clk = devm_clk_get(dev, NULL);
> > + if (IS_ERR(priv->clk)) {
> > + dev_err(dev, "failed to get exdma clk\n");
> > + return PTR_ERR(priv->clk);
> > + }
> > +
> > + larb_node = of_parse_phandle(dev->of_node,
> > "mediatek,larb", 0);
> > + if (larb_node) {
> > + larb_pdev = of_find_device_by_node(larb_node);
> > + if (larb_pdev)
> > + priv->larb = &larb_pdev->dev;
> > + of_node_put(larb_node);
> > + }
> > +
> > + if (!priv->larb) {
> > + dev_dbg(dev, "not find larb dev");
> > + return -EPROBE_DEFER;
> > + }
> > + device_link_add(dev, priv->larb, DL_FLAG_PM_RUNTIME |
> > DL_FLAG_STATELESS);
> > +
> > +#if IS_REACHABLE(CONFIG_MTK_CMDQ)
> > + ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
>
> You does not define cmdq client reg in binding document, so it seems
> this series depend on some cmdq series.
> Add the dependency information in cover letter.
>
MT8196 EXDMA doesn't support GCE subsys id, so we must use this
to get the EXDMA pa info to the cmdq_reg structure.
Best, Paul
> > + if (ret)
> > + dev_dbg(dev, "No mediatek,gce-client-reg\n");
> > +#endif
> > + platform_set_drvdata(pdev, priv);
> > +
> > + pm_runtime_enable(dev);
> > +
> > + ret = component_add(dev, &mtk_disp_exdma_component_ops);
> > + if (ret != 0) {
> > + pm_runtime_disable(dev);
> > + dev_err(dev, "Failed to add component: %d\n",
> > ret);
> > + }
> > + return ret;
> > +}
> > +
> > +static void mtk_disp_exdma_remove(struct platform_device *pdev)
> > +{
> > + component_del(&pdev->dev, &mtk_disp_exdma_component_ops);
> > + pm_runtime_disable(&pdev->dev);
> > +}
> > +
> > +static const struct of_device_id mtk_disp_exdma_driver_dt_match[]
> > = {
> > + { .compatible = "mediatek,mt8196-exdma", },
> > + {},
> > +};
> > +MODULE_DEVICE_TABLE(of, mtk_disp_exdma_driver_dt_match);
> > +
> > +struct platform_driver mtk_disp_exdma_driver = {
> > + .probe = mtk_disp_exdma_probe,
> > + .remove = mtk_disp_exdma_remove,
> > + .driver = {
> > + .name = "mediatek-disp-exdma",
> > + .owner = THIS_MODULE,
> > + .of_match_table = mtk_disp_exdma_driver_dt_match,
> > + },
> > +};
> > +
> > +MODULE_AUTHOR("Nancy Lin <nancy.lin@mediatek.com>");
> > +MODULE_DESCRIPTION("MediaTek Exdma Driver");
> > +MODULE_LICENSE("GPL");
> > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> > b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> > index 74158b9d6503..bb7306a942ff 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> > @@ -1276,6 +1276,7 @@ static struct platform_driver * const
> > mtk_drm_drivers[] = {
> > &mtk_disp_aal_driver,
> > &mtk_disp_ccorr_driver,
> > &mtk_disp_color_driver,
> > + &mtk_disp_exdma_driver,
> > &mtk_disp_gamma_driver,
> > &mtk_disp_merge_driver,
> > &mtk_disp_ovl_adaptor_driver,
> > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> > b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> > index 675cdc90a440..898a75898775 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> > +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> > @@ -72,6 +72,7 @@ struct mtk_drm_private {
> > extern struct platform_driver mtk_disp_aal_driver;
> > extern struct platform_driver mtk_disp_ccorr_driver;
> > extern struct platform_driver mtk_disp_color_driver;
> > +extern struct platform_driver mtk_disp_exdma_driver;
> > extern struct platform_driver mtk_disp_gamma_driver;
> > extern struct platform_driver mtk_disp_merge_driver;
> > extern struct platform_driver mtk_disp_ovl_adaptor_driver;
>
[-- Attachment #2: Type: text/html, Size: 38607 bytes --]
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 13/15] drm/mediatek: add ovlsys_adaptor support for MT8196
2025-04-11 3:07 ` CK Hu (胡俊光)
@ 2025-05-14 16:18 ` Paul-pl Chen (陳柏霖)
0 siblings, 0 replies; 42+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-05-14 16:18 UTC (permalink / raw)
To: CK Hu (胡俊光), robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org, chunkuang.hu@kernel.org,
AngeloGioacchino Del Regno
Cc: Sunny Shen (沈姍姍),
Sirius Wang (王皓昱),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
linux-kernel@vger.kernel.org,
Project_Global_Chrome_Upstream_Group,
dri-devel@lists.freedesktop.org,
linux-mediatek@lists.infradead.org,
Jason-JH Lin (林睿祥),
devicetree@vger.kernel.org, fshao@chromium.org,
p.zabel@pengutronix.de, Singo Chang (張興國),
linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
treapking@chromium.org
[-- Attachment #1: Type: text/plain, Size: 47509 bytes --]
On Fri, 2025-04-11 at 03:07 +0000, CK Hu (胡俊光) wrote:
> On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> > From: Nancy Lin <nancy.lin@mediatek.com>
> >
> > Ovlsys_adaptor is an encapsulated module designed to
> > simplify the DRM control flow. This module is composed
> > of 20 EXDMAs, 20 BLENDERs, and 12 OUTPROCs.
> > Two EXDMAs merge into one layer, allowing the module
> > to support 20 layers for 3 display paths.
> > Ovlsys_adaptor driver is integrated within the
> > mtk_ddp_comp framework.
> >
> > Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
> > Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> > ---
> > 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 | 797
> > ++++++++++++++++++
> > drivers/gpu/drm/mediatek/mtk_drm_drv.c | 73 ++
> > drivers/gpu/drm/mediatek/mtk_drm_drv.h | 11 +-
> > 7 files changed, 942 insertions(+), 1 deletion(-)
> > create mode 100644
> > drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
> >
> > diff --git a/drivers/gpu/drm/mediatek/Makefile
> > b/drivers/gpu/drm/mediatek/Makefile
> > index 9546bc6b7b2e..dedf50860d3f 100644
> > --- a/drivers/gpu/drm/mediatek/Makefile
> > +++ b/drivers/gpu/drm/mediatek/Makefile
> > @@ -9,6 +9,7 @@ mediatek-drm-y := mtk_crtc.o \
> > mtk_disp_exdma.o \
> > mtk_disp_gamma.o \
> > mtk_disp_merge.o \
> > + mtk_disp_ovlsys_adaptor.o \
> > mtk_disp_ovl.o \
> > mtk_disp_outproc.o \
> > mtk_disp_ovl_adaptor.o \
> > diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > index cc780744f060..c96e027359ac 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > @@ -368,6 +368,31 @@ static const struct mtk_ddp_comp_funcs ddp_ovl
> > = {
> > .get_num_formats = mtk_ovl_get_num_formats,
> > };
> >
> > +static const struct mtk_ddp_comp_funcs ddp_ovlsys_adaptor = {
> > + .power_on = mtk_ovlsys_adaptor_power_on,
> > + .power_off = mtk_ovlsys_adaptor_power_off,
> > + .clk_enable = mtk_ovlsys_adaptor_clk_enable,
> > + .clk_disable = mtk_ovlsys_adaptor_clk_disable,
> > + .config = mtk_ovlsys_adaptor_config,
> > + .start = mtk_ovlsys_adaptor_start,
> > + .stop = mtk_ovlsys_adaptor_stop,
> > + .layer_check = mtk_ovlsys_adaptor_layer_check,
> > + .layer_nr = mtk_ovlsys_adaptor_layer_nr,
> > + .layer_config = mtk_ovlsys_adaptor_layer_config,
> > + .register_vblank_cb =
> > mtk_ovlsys_adaptor_register_vblank_cb,
> > + .unregister_vblank_cb =
> > mtk_ovlsys_adaptor_unregister_vblank_cb,
> > + .enable_vblank = mtk_ovlsys_adaptor_enable_vblank,
> > + .disable_vblank = mtk_ovlsys_adaptor_disable_vblank,
> > + .dma_dev_get = mtk_ovlsys_adaptor_dma_dev_get,
> > + .connect = mtk_ovlsys_adaptor_connect,
> > + .disconnect = mtk_ovlsys_adaptor_disconnect,
> > + .add = mtk_ovlsys_adaptor_add_comp,
> > + .remove = mtk_ovlsys_adaptor_remove_comp,
> > + .get_blend_modes = mtk_ovlsys_adaptor_get_blend_modes,
> > + .get_formats = mtk_ovlsys_adaptor_get_formats,
> > + .get_num_formats = mtk_ovlsys_adaptor_get_num_formats,
> > +};
> > +
> > static const struct mtk_ddp_comp_funcs ddp_postmask = {
> > .clk_enable = mtk_ddp_clk_enable,
> > .clk_disable = mtk_ddp_clk_disable,
> > @@ -437,6 +462,7 @@ static const char * const
> > mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
> > [MTK_DISP_OVL] = "ovl",
> > [MTK_DISP_OVL_2L] = "ovl-2l",
> > [MTK_DISP_OVL_ADAPTOR] = "ovl_adaptor",
> > + [MTK_DISP_OVLSYS_ADAPTOR] = "ovlsys_adaptor",
> > [MTK_DISP_POSTMASK] = "postmask",
> > [MTK_DISP_PWM] = "pwm",
> > [MTK_DISP_RDMA] = "rdma",
> > @@ -469,6 +495,8 @@ static const struct mtk_ddp_comp_match
> > mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
> > [DDP_COMPONENT_DPI0] = {
> > MTK_DPI, 0, &ddp_dpi },
> > [DDP_COMPONENT_DPI1] = {
> > MTK_DPI, 1, &ddp_dpi },
> > [DDP_COMPONENT_DRM_OVL_ADAPTOR] = {
> > MTK_DISP_OVL_ADAPTOR, 0, &ddp_ovl_adaptor },
> > + [DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0] = {
> > MTK_DISP_OVLSYS_ADAPTOR, 0, &ddp_ovlsys_adaptor},
> > + [DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1] = {
> > MTK_DISP_OVLSYS_ADAPTOR, 1, &ddp_ovlsys_adaptor},
> > [DDP_COMPONENT_DSC0] = {
> > MTK_DISP_DSC, 0, &ddp_dsc },
> > [DDP_COMPONENT_DSC1] = {
> > MTK_DISP_DSC, 1, &ddp_dsc },
> > [DDP_COMPONENT_DSI0] = {
> > MTK_DSI, 0, &ddp_dsi },
> > diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > index b33d3289b8b6..ef64ce7a071f 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > @@ -33,6 +33,7 @@ enum mtk_ddp_comp_type {
> > MTK_DISP_MUTEX,
> > MTK_DISP_OD,
> > MTK_DISP_OVL,
> > + MTK_DISP_OVLSYS_ADAPTOR,
> > MTK_DISP_OVL_2L,
> > MTK_DISP_OVL_ADAPTOR,
> > MTK_DISP_POSTMASK,
> > diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> > b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> > index 3c519a662074..1ff8c4593fc1 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> > +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> > @@ -174,6 +174,38 @@ size_t mtk_ovl_adaptor_get_num_formats(struct
> > device *dev);
> > enum drm_mode_status mtk_ovl_adaptor_mode_valid(struct device
> > *dev,
> > const struct
> > drm_display_mode *mode);
> >
> > +int mtk_ovlsys_adaptor_power_on(struct device *dev);
> > +void mtk_ovlsys_adaptor_power_off(struct device *dev);
> > +void mtk_ovlsys_adaptor_add_comp(struct device *dev, struct
> > mtk_mutex *mutex);
> > +void mtk_ovlsys_adaptor_remove_comp(struct device *dev, struct
> > mtk_mutex *mutex);
> > +void mtk_ovlsys_adaptor_connect(struct device *dev, struct device
> > *mmsys_dev,
> > + unsigned int next);
> > +void mtk_ovlsys_adaptor_disconnect(struct device *dev, struct
> > device *mmsys_dev,
> > + unsigned int next);
> > +int mtk_ovlsys_adaptor_clk_enable(struct device *dev);
> > +void mtk_ovlsys_adaptor_clk_disable(struct device *dev);
> > +void mtk_ovlsys_adaptor_config(struct device *dev, unsigned int w,
> > + unsigned int h, unsigned int
> > vrefresh,
> > + unsigned int bpc, struct cmdq_pkt
> > *cmdq_pkt);
> > +void mtk_ovlsys_adaptor_layer_config(struct device *dev, unsigned
> > int idx,
> > + struct mtk_plane_state
> > *state,
> > + struct cmdq_pkt *cmdq_pkt);
> > +int mtk_ovlsys_adaptor_layer_check(struct device *dev,
> > + unsigned int idx,
> > + struct mtk_plane_state
> > *mtk_state);
> > +void mtk_ovlsys_adaptor_register_vblank_cb(struct device *dev,
> > void (*vblank_cb)(void *),
> > + void *vblank_cb_data);
> > +void mtk_ovlsys_adaptor_unregister_vblank_cb(struct device *dev);
> > +void mtk_ovlsys_adaptor_enable_vblank(struct device *dev);
> > +void mtk_ovlsys_adaptor_disable_vblank(struct device *dev);
> > +void mtk_ovlsys_adaptor_start(struct device *dev);
> > +void mtk_ovlsys_adaptor_stop(struct device *dev);
> > +unsigned int mtk_ovlsys_adaptor_layer_nr(struct device *dev);
> > +struct device *mtk_ovlsys_adaptor_dma_dev_get(struct device *dev);
> > +u32 mtk_ovlsys_adaptor_get_blend_modes(struct device *dev);
> > +const u32 *mtk_ovlsys_adaptor_get_formats(struct device *dev);
> > +size_t mtk_ovlsys_adaptor_get_num_formats(struct device *dev);
> > +
> > void mtk_rdma_bypass_shadow(struct device *dev);
> > int mtk_rdma_clk_enable(struct device *dev);
> > void mtk_rdma_clk_disable(struct device *dev);
> > diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
> > b/drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
> > new file mode 100644
> > index 000000000000..04cb555bd77b
> > --- /dev/null
> > +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
> > @@ -0,0 +1,797 @@
> > +// 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_disp_blender.h"
> > +#include "mtk_disp_drv.h"
> > +#include "mtk_crtc.h"
>
> Alphabetic order.
>
OK, I will fix it.
> > +#include "mtk_ddp_comp.h"
>
> Ditto.
OK, I will fix it.
>
> > +#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;
> > + unsigned int max_size;
>
> It's not necessary to store max_size in private data.
> Drop this and use OVLSYS_ADAPTOR_DRIVER_DATA_MAX_SIZE directly.
>
OK, I will fix it and use OVLSYS_ADAPTOR_DRIVER_DATA_MAX_SIZE
directly to replace the max_size.
> > +};
> > +
> > +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_EXDMA0] = { OVLSYS_ADAPTOR_TYPE_EXDMA,
> > 0, DDP_COMPONENT_ID_MAX},
> > + [OVLSYS_ADAPTOR_EXDMA1] = {
> > OVLSYS_ADAPTOR_TYPE_EXDMA, 1, DDP_COMPONENT_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;
> > +}
> > +
> > +static struct device *get_comp_by_type_idx(struct device *dev,
> > + enum
> > mtk_ovlsys_adaptor_comp_type type,
> > + unsigned int idx)
> > +{
> > + struct mtk_disp_ovlsys_adaptor *priv =
> > dev_get_drvdata(dev);
> > + int i;
> > + int count = 0;
> > +
> > + for (i = 0; i < priv->path_size; i++) {
> > + if (get_type(priv->path[i]) == type) {
> > + if (count == idx)
> > + return priv-
> > >ovl_adaptor_comp[priv->path[i]];
> > + count++;
> > + }
> > + }
> > + return NULL;
> > +}
> > +
> > +int mtk_ovlsys_adaptor_power_on(struct device *dev)
> > +{
> > + struct mtk_disp_ovlsys_adaptor *priv =
> > dev_get_drvdata(dev);
> > + struct device *comp;
> > + int ret = 0;
> > + int i;
> > +
> > + for (i = 0; i < OVLSYS_ADAPTOR_ID_MAX; i++) {
>
> Why this for-loop is not as below example?
>
> for (i = 0; i < priv->path_size; i++) {
>
OK, I will try to fix this in the way of using riv->path_size.
> > + comp = priv->ovl_adaptor_comp[i];
> > +
> > + if (!comp)
> > + continue;
> > +
> > + if (get_type(i) != OVLSYS_ADAPTOR_TYPE_EXDMA)
>
> Why only EXDMA need power on?
The whole ovlsys_adatopr has the EXDMA, BLENDER, OUT_PROC,
and the ovlsys_adator using the same power source.
>
> > + continue;
> > +
> > + ret = pm_runtime_get_sync(comp);
> > + if (ret < 0) {
> > + dev_err(dev, "Failed to enable power
> > domain %d, err %d\n", i, ret);
> > + goto pwr_err;
> > + }
> > + }
> > +
> > + return ret;
> > +pwr_err:
> > + while (--i >= 0) {
> > + comp = priv->ovl_adaptor_comp[i];
> > + if (!comp)
> > + continue;
> > + if (get_type(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 < OVLSYS_ADAPTOR_ID_MAX; i++) {
> > + comp = priv->ovl_adaptor_comp[i];
> > +
> > + if (!comp)
> > + continue;
> > +
> > + if (get_type(i) == OVLSYS_ADAPTOR_TYPE_EXDMA)
> > + 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 device *exdma;
> > + struct device *blender;
> > + unsigned int align_width = 0;
> > + const struct drm_format_info *fmt_info =
> > drm_format_info(pending->format);
> > + struct mtk_disp_ovlsys_adaptor *priv =
> > dev_get_drvdata(dev);
> > +
> > + 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 = get_comp_by_type_idx(dev,
> > OVLSYS_ADAPTOR_TYPE_EXDMA, idx);
>
> exdma = priv->ovl_adaptor_comp[priv->path[idx * 2]];
>
> > + if (!exdma) {
>
> You just need to check idx < priv->layer_nr.
>
>
OK I will try to fix it.
>
> > + dev_err(dev, "%s: exdma%d comp not found\n",
> > __func__, idx);
> > + return;
> > + }
> > + blender = get_comp_by_type_idx(dev,
> > OVLSYS_ADAPTOR_TYPE_BLENDER, idx);
>
> 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;
> > + }
> > +
> > + /* OVLSYS is in 1T2P domain, width needs to be 2 pixels
> > align */
> > + align_width = ALIGN_DOWN(pending->width, 2);
> > +
> > + if (pending->height == 0 || align_width == 0 ||
> > + pending->x > priv->max_size || pending->y > priv-
> > >max_size) {
> > + pending->enable = false;
>
> Why modify pending->enable?
>
>
The EXDMA and BLENDER's layer_config setting is all check the flag.
pending->enable
>
>
>
> > + mtk_disp_exdma_layer_config(exdma, state,
> > cmdq_pkt);
> > + mtk_disp_blender_layer_config(blender, state,
> > cmdq_pkt);
> > + return;
> > + }
> > +
> > + mtk_disp_exdma_layer_config(exdma, state, cmdq_pkt);
> > +
> > + mtk_disp_blender_layer_config(blender, state, cmdq_pkt);
> > +
> > + mtk_disp_exdma_start(exdma, cmdq_pkt);
> > + mtk_disp_blender_start(blender, cmdq_pkt);
>
> The start function is done in ovlsys_start(), so remove these start
> function.
>
OK I will fix it.
>
> > +}
> > +
> > +void mtk_ovlsys_adaptor_config(struct device *dev, unsigned int w,
> > + unsigned int h, unsigned int
> > vrefresh,
> > + unsigned int bpc, struct cmdq_pkt
> > *cmdq_pkt)
> > +{
> > + struct mtk_disp_ovlsys_adaptor *priv =
> > dev_get_drvdata(dev);
> > + int i;
> > + int blender_idx = 0;
> > + bool most_top;
> > + bool most_bottom;
> > +
> > + for (i = 0; i < priv->path_size; i++) {
> > + if (get_type(priv->path[i]) ==
> > OVLSYS_ADAPTOR_TYPE_BLENDER) {
> > + blender_idx++;
> > +
> > + if (priv->layer_nr == 1) {
> > + most_top =
> > true; /*SINGLE_BLENDER;*/
> > + most_bottom = false; /*blender
> > is LAST_BLENDER*/
>
> Only one blender, so most_bottom = true;
Ok, I will fix it.
>
> > + } else if (blender_idx == 1) {
> > + most_top = false; /* NON-
> > SINGLE LAYER */
> > + most_bottom = true; /* FIRST
> > LAYER */
> > + } else if (blender_idx == priv->layer_nr)
> > {
> > + most_top = true; /* NON-
> > SINGLE LAYER */
> > + most_bottom = false; /* LAST
> > LAYER */
> > + } else {
> > + most_top = false; /* NON-
> > SINGLE LAYER */
> > + most_bottom = false; /* OTHER
> > LAYER */
> > + }
> > +
> > + mtk_disp_blender_config(priv-
> > >ovl_adaptor_comp[priv->path[i]], w, h,
> > + vrefresh, bpc,
> > most_top, most_bottom, cmdq_pkt);
>
> You could remove the if-else checking, and
>
> mtk_disp_blender_config(priv->ovl_adaptor_comp[priv->path[i]], w, h,
> vrefresh, bpc, blender_idx == priv->layer_nr,
> blender_idx == 1, cmdq_pkt);
Ok, I will fix it.
>
> > + } else if (get_type(priv->path[i]) ==
> > OVLSYS_ADAPTOR_TYPE_OUTPROC) {
> > + mtk_disp_outproc_config(priv-
> > >ovl_adaptor_comp[priv->path[i]], w, h,
> > + vrefresh, bpc,
> > cmdq_pkt);
> > + }
> > + }
> > +}
> > +
> > +int mtk_ovlsys_adaptor_layer_check(struct device *dev,
> > + unsigned int idx,
> > + struct mtk_plane_state
> > *mtk_state)
> > +{
> > + struct drm_plane_state *state = &mtk_state->base;
> > +
> > + /* Check if any unsupported rotation is set */
> > + if (state->rotation & ~DRM_MODE_ROTATE_0)
> > + return -EINVAL;
> > +
> > + return 0;
> > +}
> > +
> > +void mtk_ovlsys_adaptor_start(struct device *dev)
> > +{
> > + struct mtk_disp_ovlsys_adaptor *priv =
> > dev_get_drvdata(dev);
> > + int i;
> > +
> > + for (i = 0; i < priv->path_size; i++) {
> > + if (get_type(priv->path[i]) ==
> > OVLSYS_ADAPTOR_TYPE_EXDMA)
> > + mtk_disp_exdma_start(priv-
> > >ovl_adaptor_comp[priv->path[i]], NULL);
> > + else if (get_type(priv->path[i]) ==
> > OVLSYS_ADAPTOR_TYPE_BLENDER)
> > + mtk_disp_blender_start(priv-
> > >ovl_adaptor_comp[priv->path[i]], NULL);
> > + else
> > + mtk_disp_outproc_start(priv-
> > >ovl_adaptor_comp[priv->path[i]]);
> > + }
>
> I think the order in path has some rule, so this for-loop could be
> simplified as
>
> for (i = 0; i < (priv->path_size - 1); i += 2) {
> mtk_disp_exdma_start(priv->ovl_adaptor_comp[priv->path[i]],
> NULL);
> mtk_disp_blender_start(priv->ovl_adaptor_comp[priv->path[i +
> 1]], NULL);
> }
>
Ok, I will fix it.
> 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; i++) {
> > + if (get_type(priv->path[i]) ==
> > OVLSYS_ADAPTOR_TYPE_EXDMA)
> > + mtk_disp_exdma_stop(priv-
> > >ovl_adaptor_comp[priv->path[i]], NULL);
> > + else if (get_type(priv->path[i]) ==
> > OVLSYS_ADAPTOR_TYPE_BLENDER)
> > + mtk_disp_blender_stop(priv-
> > >ovl_adaptor_comp[priv->path[i]], NULL);
> > + else
> > + 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 = 0;
> > + int i;
> > +
> > + for (i = 0; i < OVLSYS_ADAPTOR_ID_MAX; i++) {
>
> Why this for-loop is not as below?
>
Ok, I will fix it.
> for (i = 0; i < priv->path_size; i++) {
>
> > + comp = priv->ovl_adaptor_comp[i];
> > +
> > + if (!comp)
> > + continue;
> > +
> > + if (get_type(i) == OVLSYS_ADAPTOR_TYPE_EXDMA)
> > + ret = mtk_disp_exdma_clk_enable(comp);
> > + else if (get_type(i) ==
> > OVLSYS_ADAPTOR_TYPE_BLENDER)
> > + ret = mtk_disp_blender_clk_enable(comp);
> > + else
> > + ret = mtk_disp_outproc_clk_enable(comp);
> > +
> > + if (ret) {
> > + dev_err(dev, "Failed to enable clock %d,
> > err %d\n", i, ret);
> > + goto clk_err;
> > + }
> > + }
> > +
> > + return ret;
> > +
> > +clk_err:
> > + while (--i >= 0) {
> > + comp = priv->ovl_adaptor_comp[i];
> > + if (!comp)
> > + continue;
> > + if (get_type(i) == OVLSYS_ADAPTOR_TYPE_EXDMA)
> > + mtk_disp_exdma_clk_disable(comp);
> > + else if (get_type(i) ==
> > OVLSYS_ADAPTOR_TYPE_BLENDER)
> > + mtk_disp_blender_clk_disable(comp);
> > + else
> > + mtk_disp_outproc_clk_disable(comp);
> > + }
> > + i = OVLSYS_ADAPTOR_ID_MAX;
>
> Why assign i here?
>
It's the redundant. I will fix it.
>
> > +
> > + 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 < OVLSYS_ADAPTOR_ID_MAX; i++) {
> > + comp = priv->ovl_adaptor_comp[i];
> > +
> > + if (!comp)
> > + continue;
> > +
> > + if (get_type(i) == OVLSYS_ADAPTOR_TYPE_EXDMA)
> > + mtk_disp_exdma_clk_disable(comp);
> > + else if (get_type(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);
> > + struct device *comp;
> > + int i;
> > +
> > + for (i = 0; i < priv->path_size; i++)
> > + if (get_type(priv->path[i]) ==
> > OVLSYS_ADAPTOR_TYPE_BLENDER) {
> > + comp = priv->ovl_adaptor_comp[priv-
> > >path[i]];
> > + return
> > mtk_disp_blender_get_blend_modes(comp);
> > + }
>
> In mtk_ovlsys_adaptor_get_formats(), you have assume that priv-
> >ovl_adaptor_comp[priv->path[0]] is exdma,
> so you could assume that priv->ovl_adaptor_comp[priv->path[1]] is
> blender.
> Then
>
> return mtk_disp_blender_get_blend_modes(priv->ovl_adaptor_comp[priv-
> >path[1]]);
>
Ok, I will try to fix it.
> > +
> > + return 0;
> > +}
> > +
> > +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,
> > + enum mtk_ddp_comp_id
> > *comp_id)
> > +{
> > + 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) {
> > + *comp_id = comp_matches[i].comp_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 *node, *parent;
> > + struct platform_device *comp_pdev;
> > + int i;
> > +
> > + parent = dev->parent->parent->of_node->parent;
> > +
> > + for_each_child_of_node(parent, node) {
>
> for_each_child_of_node_scoped()
>
Ok, I will fix it.
> > + const struct of_device_id *of_id;
> > + enum mtk_ovlsys_adaptor_comp_type type;
> > + enum mtk_ddp_comp_id comp_id;
>
> comp_id is useless, drop it.
Ok, I will fix it.
>
> > + 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,
> > &comp_id);
> > + if (id < 0) {
> > + dev_warn(dev, "Skipping unknown component
> > %pOF\n",
> > + node);
> > + continue;
> > + }
> > +
> > + for (i = 0; i < priv->path_size; i++)
> > + if (priv->path[i] == id)
> > + found = true;
> > +
> > + if (!found)
> > + continue;
> > +
> > + comp_pdev = of_find_device_by_node(node);
> > + if (!comp_pdev)
> > + return -EPROBE_DEFER;
> > +
> > + priv->ovl_adaptor_comp[id] = &comp_pdev->dev;
> > +
> > + drm_of_component_match_add(dev, match,
> > component_compare_of, node);
> > + dev_dbg(dev, "Adding component match for %pOF\n",
> > node);
> > + }
> > +
> > + if (!*match) {
> > + dev_err(dev, "No match device for
> > ovlsys_adaptor\n");
> > + return -ENODEV;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int mtk_disp_ovlsys_adaptor_comp_bind(struct device *dev,
> > struct device *master,
> > + void *data)
> > +{
> > + struct mtk_disp_ovlsys_adaptor *priv =
> > dev_get_drvdata(dev);
> > +
> > + if (!priv->children_bound)
> > + return -EPROBE_DEFER;
> > +
> > + return 0;
> > +}
> > +
> > +static void mtk_disp_ovlsys_adaptor_comp_unbind(struct device
> > *dev, struct device *master,
> > + void *data)
> > +{
> > +}
> > +
> > +static const struct component_ops mtk_disp_ovlsys_adaptor_comp_ops
> > = {
> > + .bind = mtk_disp_ovlsys_adaptor_comp_bind,
> > + .unbind = mtk_disp_ovlsys_adaptor_comp_unbind,
> > +};
> > +
> > +static int mtk_disp_ovlsys_adaptor_master_bind(struct device *dev)
> > +{
> > + struct mtk_disp_ovlsys_adaptor *priv =
> > dev_get_drvdata(dev);
> > + int ret, i;
> > + unsigned int layer_nr = 0;
> > +
> > + 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;
> > +
> > + for (i = 0; i < priv->path_size; i++)
> > + if (comp_matches[priv->path[i]].type ==
> > OVLSYS_ADAPTOR_TYPE_BLENDER)
> > + layer_nr++;
>
> It seems you could drop layer_nr.
> Assign priv->layer_nr to 0 first, and then priv->layer_nr++.
Ok, I will fix it.
>
> > + priv->layer_nr = layer_nr;
> > +
> > + return 0;
> > +}
> > +
> > +static void mtk_disp_ovlsys_adaptor_master_unbind(struct device
> > *dev)
> > +{
> > + struct mtk_disp_ovlsys_adaptor *priv =
> > dev_get_drvdata(dev);
> > +
> > + priv->children_bound = false;
> > +}
> > +
> > +static const struct component_master_ops
> > mtk_disp_ovlsys_adaptor_master_ops = {
> > + .bind = mtk_disp_ovlsys_adaptor_master_bind,
> > + .unbind =
> > mtk_disp_ovlsys_adaptor_master_unbind,
> > +};
> > +
> > +static int mtk_disp_ovlsys_adaptor_probe(struct platform_device
> > *pdev)
> > +{
> > + struct mtk_disp_ovlsys_adaptor *priv;
> > + struct device *dev = &pdev->dev;
> > + struct component_match *match = NULL;
> > + struct mtk_ovlsys_platform_data *ovlsys_priv;
> > //mtk_drm_ovlsys_private
>
> Remove the comment.
Ok, I will fix it.
>
> > + 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;
> > + priv->max_size = OVLSYS_ADAPTOR_DRIVER_DATA_MAX_SIZE;
> > +
> > + if (ovlsys_priv->use_path == CRTC_MAIN) {
> > + priv->path = mt8196_mtk_ovl_main;
> > + priv->path_size = ARRAY_SIZE(mt8196_mtk_ovl_main);
> > + } else if (ovlsys_priv->use_path == CRTC_EXT) {
> > + priv->path = mt8196_mtk_ovl_ext;
> > + priv->path_size = ARRAY_SIZE(mt8196_mtk_ovl_ext);
> > + } else if (ovlsys_priv->use_path == CRTC_THIRD) {
> > + priv->path = mt8196_mtk_ovl_third;
> > + priv->path_size =
> > ARRAY_SIZE(mt8196_mtk_ovl_third);
> > + }
> > +
> > + ret = ovlsys_adaptor_comp_init(dev, &match);
> > + if (ret < 0)
> > + return ret;
> > +
> > + component_master_add_with_match(dev,
> > &mtk_disp_ovlsys_adaptor_master_ops, match);
> > +
> > + pm_runtime_enable(dev);
> > +
> > + ret = component_add(dev,
> > &mtk_disp_ovlsys_adaptor_comp_ops);
> > + if (ret != 0) {
> > + pm_runtime_disable(dev);
> > + dev_err(dev, "Failed to add component: %d\n",
> > ret);
> > + }
> > +
> > + return ret;
> > +}
> > +
> > +static void mtk_disp_ovlsys_adaptor_remove(struct platform_device
> > *pdev)
> > +{
> > + component_master_del(&pdev->dev,
> > &mtk_disp_ovlsys_adaptor_master_ops);
> > + pm_runtime_disable(&pdev->dev);
> > +}
> > +
> > +struct platform_driver mtk_disp_ovlsys_adaptor_driver = {
> > + .probe = mtk_disp_ovlsys_adaptor_probe,
> > + .remove = mtk_disp_ovlsys_adaptor_remove,
> > + .driver = {
> > + .name = "mediatek-disp-ovlsys-adaptor",
> > + .owner = THIS_MODULE,
> > + },
> > +};
> > +
> > +MODULE_AUTHOR("Nancy Lin <nancy.lin@mediatek.com>");
> > +MODULE_DESCRIPTION("MediaTek Ovlsys Adaptor Driver");
> > +MODULE_LICENSE("GPL");
> > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> > b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> > index f7b9c7a982a7..0639201e2e92 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> > @@ -457,6 +457,27 @@ static bool mtk_drm_find_mmsys_comp(struct
> > mtk_drm_private *private, int comp_id
> > return false;
> > }
> >
> > +static int mtk_drm_mmsys_comp_in_path(struct mtk_drm_private
> > *private, int comp_id)
> > +{
> > + const struct mtk_mmsys_driver_data *drv_data = private-
> > >data;
> > + int i;
> > +
> > + if (drv_data->main_path)
> > + for (i = 0; i < drv_data->main_len; i++)
> > + if (drv_data->main_path[i] == comp_id)
> > + return CRTC_MAIN;
> > + if (drv_data->ext_path)
> > + for (i = 0; i < drv_data->ext_len; i++)
> > + if (drv_data->ext_path[i] == comp_id)
> > + return CRTC_EXT;
> > + if (drv_data->third_path)
> > + for (i = 0; i < drv_data->third_len; i++)
> > + if (drv_data->third_path[i] == comp_id)
> > + return CRTC_THIRD;
> > +
>
> This function is almost like mtk_drm_find_mmsys_comp(), try to merge
> them.
>
Ok, I will try to merge the mtk_drm_find_mmsys_comp() and
mtk_drm_mmsys_comp_in_path.
> > + return -EINVAL;
> > +}
> > +
> > static int mtk_drm_kms_init(struct drm_device *drm)
> > {
> > struct mtk_drm_private *private = drm->dev_private;
> > @@ -1122,6 +1143,57 @@ static int mtk_drm_probe(struct
> > platform_device *pdev)
> > component_match_add(dev, &match, compare_dev,
> > &ovl_adaptor->dev);
> > }
> >
> > + if (mtk_drm_find_mmsys_comp(private,
> > DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0)) {
> > + struct mtk_ovlsys_platform_data ovlsys_priv;
> > +
> > + ovlsys_priv.mmsys_dev = private->mmsys_dev;
> > + ovlsys_priv.use_path =
> > + mtk_drm_mmsys_comp_in_path(private,
> > DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0);
> > + ovl_adaptor =
> > + platform_device_register_data(dev,
> > "mediatek-disp-ovlsys-adaptor",
> > +
> > PLATFORM_DEVID_AUTO,
> > + (void
> > *)&ovlsys_priv,
> > +
> > sizeof(struct mtk_ovlsys_platform_data));
> > + private-
> > >ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0].dev = &ovl_adaptor-
> > >dev;
> > + mtk_ddp_comp_init(NULL, &private-
> > >ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0],
> > +
> > DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0);
> > + component_match_add(dev, &match, compare_dev,
> > &ovl_adaptor->dev);
> > + }
> > +
> > + if (mtk_drm_find_mmsys_comp(private,
> > DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1)) {
> > + struct mtk_ovlsys_platform_data ovlsys_priv;
> > //mtk_drm_ovlsys_private
> > +
> > + ovlsys_priv.mmsys_dev = private->mmsys_dev;
> > + ovlsys_priv.use_path =
> > + mtk_drm_mmsys_comp_in_path(private,
> > DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1);
> > + ovl_adaptor =
> > + platform_device_register_data(dev,
> > "mediatek-disp-ovlsys-adaptor",
> > +
> > PLATFORM_DEVID_AUTO,
> > + (void
> > *)&ovlsys_priv,
> > +
> > sizeof(struct mtk_ovlsys_platform_data));
> > + private-
> > >ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1].dev = &ovl_adaptor-
> > >dev;
> > + mtk_ddp_comp_init(NULL, &private-
> > >ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1],
> > +
> > DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1);
> > + component_match_add(dev, &match, compare_dev,
> > &ovl_adaptor->dev);
> > + }
> > +
> > + if (mtk_drm_find_mmsys_comp(private,
> > DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2)) {
> > + struct mtk_ovlsys_platform_data ovlsys_priv;
> > +
> > + ovlsys_priv.mmsys_dev = private->mmsys_dev;
> > + ovlsys_priv.use_path =
> > + mtk_drm_mmsys_comp_in_path(private,
> > DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2);
> > + ovl_adaptor =
> > + platform_device_register_data(dev,
> > "mediatek-disp-ovlsys-adaptor",
> > +
> > PLATFORM_DEVID_AUTO,
> > + (void
> > *)&ovlsys_priv,
> > +
> > sizeof(struct mtk_ovlsys_platform_data));
> > + private-
> > >ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2].dev = &ovl_adaptor-
> > >dev;
> > + mtk_ddp_comp_init(NULL, &private-
> > >ddp_comp[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2],
> > +
> > DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2);
> > + component_match_add(dev, &match, compare_dev,
> > &ovl_adaptor->dev);
> > + }
>
> The code about these three path are almost the same.
> Try to merge them.
> You could use one function with different parameter
> (such as DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0,
> DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1,
> DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2).
>
OK I will try to merge them.
> > +
> > /* Iterate over sibling DISP function blocks */
> > for_each_child_of_node(phandle->parent, node) {
> > enum mtk_ddp_comp_type comp_type;
> > @@ -1283,6 +1355,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..6e9ed9837c5b 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> > +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> > @@ -11,7 +11,9 @@
> >
> > #define MAX_CONNECTOR 2
> > #define DDP_COMPONENT_DRM_OVL_ADAPTOR (DDP_COMPONENT_ID_MAX + 1)
> > -#define DDP_COMPONENT_DRM_ID_MAX (DDP_COMPONENT_DRM_OVL_ADAPTOR +
> > 1)
> > +#define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0
> > (DDP_COMPONENT_DRM_OVL_ADAPTOR + 1)
> > +#define DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1
> > (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 + 1)
> > +#define DDP_COMPONENT_DRM_ID_MAX
> > (DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 + 1)
> >
> > enum mtk_crtc_path {
> > CRTC_MAIN,
> > @@ -69,6 +71,12 @@ struct mtk_drm_private {
> > struct mtk_drm_private **all_drm_private;
> > };
> >
> > +struct mtk_ovlsys_platform_data {//mtk_drm_ovlsys_private
>
> Remove this comment
>
Ok, I will fix it.
>
> > + struct device *mmsys_dev;
> > + struct device *mutex_dev;
>
> mutex_dev is useless, drop it.
>
> Regards,
> CK
>
Ok, I will fix it. Thanks for all the comment and review.
Best, Paul
> > + 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;
>
[-- Attachment #2: Type: text/html, Size: 78327 bytes --]
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2 03/15] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-03-24 2:45 ` CK Hu (胡俊光)
@ 2025-05-14 16:25 ` Paul-pl Chen (陳柏霖)
0 siblings, 0 replies; 42+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-05-14 16:25 UTC (permalink / raw)
To: CK Hu (胡俊光), robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org, chunkuang.hu@kernel.org,
AngeloGioacchino Del Regno
Cc: Sunny Shen (沈姍姍),
Sirius Wang (王皓昱),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
linux-kernel@vger.kernel.org,
Project_Global_Chrome_Upstream_Group,
dri-devel@lists.freedesktop.org,
linux-mediatek@lists.infradead.org,
Jason-JH Lin (林睿祥),
devicetree@vger.kernel.org, fshao@chromium.org,
p.zabel@pengutronix.de, Singo Chang (張興國),
linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
treapking@chromium.org
[-- Attachment #1: Type: text/plain, Size: 3907 bytes --]
On Mon, 2025-03-24 at 02:45 +0000, CK Hu (胡俊光) wrote:
> On Fri, 2025-03-21 at 17:33 +0800, paul-pl.chen wrote:
> > From: Paul-pl Chen <paul-pl.chen@mediatek.com>
> >
> > Add mediatek,exdma.yaml to support EXDMA for MT8196.
> > The MediaTek display overlap extended DMA engine, namely
> > OVL_EXDMA or EXDMA, primarily functions as a DMA engine
> > for reading data from DRAM with various DRAM footprints
> > and data formats.
> >
> > Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
> > ---
> > .../bindings/dma/mediatek,exdma.yaml | 70
> > +++++++++++++++++++
> > 1 file changed, 70 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..de7f8283bb48
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/dma/mediatek,exdma.yaml
> > @@ -0,0 +1,70 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id:
> > https://urldefense.com/v3/__http://devicetree.org/schemas/dma/mediatek,exdma.yaml*__;Iw!!CTRNKA9wMg0ARbw!jH_-2I8NkTUX90vbZGjduUAo4on8DsCGFTrVX5jUdxL_zpKt5PSPRGm31otPZ4wIDzI2h9HFGbF4DC5jPw1nejo$
> >
> > +$schema:
> > https://urldefense.com/v3/__http://devicetree.org/meta-schemas/core.yaml*__;Iw!!CTRNKA9wMg0ARbw!jH_-2I8NkTUX90vbZGjduUAo4on8DsCGFTrVX5jUdxL_zpKt5PSPRGm31otPZ4wIDzI2h9HFGbF4DC5jr1jxJoQ$
> >
> > +
> > +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>;
> > +
> > + disp_ovl0_exdma2: dma-controller@32850000 {
> > + compatible = "mediatek,mt8196-exdma";
> > + reg = <0 0x32850000 0 0x1000>;
> > + clocks = <&ovlsys_config_clk 13>;
> > + power-domains = <&hfrpsys 12>;
> > + mediatek,larb = <&smi_larb0>;
>
> larb is controlled by iommu, and exdma has already point to iommu.
> OVL also not point to larb, so it's not necessary to point to larb
> here.
>
> Regards,
> CK
>
>
>
This is for the device-link.
Best, Paul
>
> > + iommus = <&mm_smmu 144>;
> > + #dma-cells = <1>;
> > + };
> > + };
>
[-- Attachment #2: Type: text/html, Size: 8279 bytes --]
^ permalink raw reply [flat|nested] 42+ messages in thread
end of thread, other threads:[~2025-05-14 16:25 UTC | newest]
Thread overview: 42+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-21 9:33 [PATCH v2 00/15] Add MediaTek SoC DRM support for MT8196 paul-pl.chen
2025-03-21 9:33 ` [PATCH v2 01/15] dt-bindings: arm: mediatek: mmsys: add compatible " paul-pl.chen
2025-03-24 9:33 ` Krzysztof Kozlowski
2025-03-21 9:33 ` [PATCH v2 02/15] dt-bindings: soc: mediatek: add mutex yaml " paul-pl.chen
2025-03-24 9:34 ` Krzysztof Kozlowski
2025-03-21 9:33 ` [PATCH v2 03/15] dt-bindings: display: mediatek: add EXDMA " paul-pl.chen
2025-03-24 2:45 ` CK Hu (胡俊光)
2025-05-14 16:25 ` Paul-pl Chen (陳柏霖)
2025-03-21 9:33 ` [PATCH v2 04/15] dt-bindings: display: mediatek: add BLENDER " paul-pl.chen
2025-03-24 9:36 ` Krzysztof Kozlowski
2025-03-28 2:27 ` Paul-pl Chen (陳柏霖)
2025-03-21 9:33 ` [PATCH v2 05/15] dt-bindings: display: mediatek: add OUTPROC " paul-pl.chen
2025-03-24 16:02 ` Rob Herring
2025-04-01 15:44 ` Paul-pl Chen (陳柏霖)
2025-03-21 9:33 ` [PATCH v2 06/15] soc: mediatek: add mmsys support " paul-pl.chen
2025-03-24 17:09 ` AngeloGioacchino Del Regno
2025-04-02 4:06 ` Paul-pl Chen (陳柏霖)
2025-04-02 9:33 ` AngeloGioacchino Del Regno
2025-04-11 9:26 ` Paul-pl Chen (陳柏霖)
2025-03-21 9:33 ` [PATCH v2 07/15] soc: mediatek: mutex: refactor SOF settings for output components paul-pl.chen
2025-03-24 17:12 ` AngeloGioacchino Del Regno
2025-04-02 3:30 ` Paul-pl Chen (陳柏霖)
2025-03-21 9:33 ` [PATCH v2 08/15] soc: mediatek: mutex: add mutex support for MT8196 paul-pl.chen
2025-03-21 9:33 ` [PATCH v2 09/15] drm/mediatek: Refine OVL format convert API and export to public paul-pl.chen
2025-03-25 2:57 ` CK Hu (胡俊光)
2025-05-13 16:22 ` Paul-pl Chen (陳柏霖)
2025-03-21 9:33 ` [PATCH v2 10/15] drm/mediatek: add EXDMA support for MT8196 paul-pl.chen
2025-03-24 3:00 ` CK Hu (胡俊光)
2025-05-14 10:00 ` Paul-pl Chen (陳柏霖)
2025-03-21 9:33 ` [PATCH v2 11/15] drm/mediatek: add BLENDER " paul-pl.chen
2025-03-24 8:33 ` CK Hu (胡俊光)
2025-05-13 17:12 ` Paul-pl Chen (陳柏霖)
2025-03-21 9:33 ` [PATCH v2 12/15] drm/mediatek: add OUTPROC " paul-pl.chen
2025-03-24 9:00 ` CK Hu (胡俊光)
2025-03-28 2:57 ` Paul-pl Chen (陳柏霖)
2025-03-21 9:33 ` [PATCH v2 13/15] drm/mediatek: add ovlsys_adaptor " paul-pl.chen
2025-04-11 3:07 ` CK Hu (胡俊光)
2025-05-14 16:18 ` Paul-pl Chen (陳柏霖)
2025-03-21 9:33 ` [PATCH v2 14/15] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver paul-pl.chen
2025-03-25 3:44 ` CK Hu (胡俊光)
2025-05-13 16:11 ` Paul-pl Chen (陳柏霖)
2025-03-21 9:33 ` [PATCH v2 15/15] drm/mediatek: Add support for MT8196 multiple mmsys paul-pl.chen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).