* [PATCH 01/12] dt-bindings: arm: mediatek: mmsys: add compatible for MT8196
2025-01-10 12:33 [PATCH 00/12] Add Mediatek Soc DRM support for mt8196 paul-pl.chen
@ 2025-01-10 12:33 ` paul-pl.chen
2025-01-10 12:58 ` Krzysztof Kozlowski
2025-01-10 12:33 ` [PATCH 02/12] dt-bindings: soc: mediatek: add mutex yaml " paul-pl.chen
` (12 subsequent siblings)
13 siblings, 1 reply; 50+ messages in thread
From: paul-pl.chen @ 2025-01-10 12: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 for mmsys yaml of 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.34.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 01/12] dt-bindings: arm: mediatek: mmsys: add compatible for MT8196
2025-01-10 12:33 ` [PATCH 01/12] dt-bindings: arm: mediatek: mmsys: add compatible for MT8196 paul-pl.chen
@ 2025-01-10 12:58 ` Krzysztof Kozlowski
2025-01-13 11:25 ` Fei Shao
2025-01-15 9:18 ` Paul-pl Chen (陳柏霖)
0 siblings, 2 replies; 50+ messages in thread
From: Krzysztof Kozlowski @ 2025-01-10 12:58 UTC (permalink / raw)
To: paul-pl.chen, 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, sunny.shen, fshao, treapking,
devicetree, linux-kernel, dri-devel, linux-mediatek,
linux-arm-kernel, Project_Global_Chrome_Upstream_Group
On 10/01/2025 13:33, paul-pl.chen wrote:
> From: "Paul-pl.Chen" <paul-pl.chen@mediatek.com>
>
> Add compatible for mmsys yaml of MT8196
>
> Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
This is a wide pattern now in Mediatek: login name is used as family
name. Repeating the same comment to every Mediatek employee is a bit
tedious, so maybe you could fix it internally?
Create some guideline for your colleagues so you won't repeat the same
things over and over?
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 01/12] dt-bindings: arm: mediatek: mmsys: add compatible for MT8196
2025-01-10 12:58 ` Krzysztof Kozlowski
@ 2025-01-13 11:25 ` Fei Shao
2025-01-13 11:30 ` Krzysztof Kozlowski
2025-01-15 9:18 ` Paul-pl Chen (陳柏霖)
1 sibling, 1 reply; 50+ messages in thread
From: Fei Shao @ 2025-01-13 11:25 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: paul-pl.chen, 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,
treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
linux-arm-kernel, Project_Global_Chrome_Upstream_Group
On Fri, Jan 10, 2025 at 8:58 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On 10/01/2025 13:33, paul-pl.chen wrote:
> > From: "Paul-pl.Chen" <paul-pl.chen@mediatek.com>
> >
> > Add compatible for mmsys yaml of MT8196
> >
> > Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
>
>
> This is a wide pattern now in Mediatek: login name is used as family
> name. Repeating the same comment to every Mediatek employee is a bit
> tedious, so maybe you could fix it internally?
>
> Create some guideline for your colleagues so you won't repeat the same
> things over and over?
Not a guarantee that this will go away once and for all, but I can
ping some MediaTek folks via a separate channel, and hopefully they
can amplify this message internally.
Regards,
Fei
>
> Best regards,
> Krzysztof
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 01/12] dt-bindings: arm: mediatek: mmsys: add compatible for MT8196
2025-01-13 11:25 ` Fei Shao
@ 2025-01-13 11:30 ` Krzysztof Kozlowski
0 siblings, 0 replies; 50+ messages in thread
From: Krzysztof Kozlowski @ 2025-01-13 11:30 UTC (permalink / raw)
To: Fei Shao
Cc: paul-pl.chen, 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,
treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
linux-arm-kernel, Project_Global_Chrome_Upstream_Group
On 13/01/2025 12:25, Fei Shao wrote:
> On Fri, Jan 10, 2025 at 8:58 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>>
>> On 10/01/2025 13:33, paul-pl.chen wrote:
>>> From: "Paul-pl.Chen" <paul-pl.chen@mediatek.com>
>>>
>>> Add compatible for mmsys yaml of MT8196
>>>
>>> Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
>>
>>
>> This is a wide pattern now in Mediatek: login name is used as family
>> name. Repeating the same comment to every Mediatek employee is a bit
>> tedious, so maybe you could fix it internally?
>>
>> Create some guideline for your colleagues so you won't repeat the same
>> things over and over?
>
> Not a guarantee that this will go away once and for all, but I can
> ping some MediaTek folks via a separate channel, and hopefully they
> can amplify this message internally.
Thanks. I still expect from Mediatek employees, so Paul and dozen of
others who appear on the list, to actually care about their upstreaming
process thus incorporate such feedback into some sort of internal
guidelines or trainings, so they will not repeat the same mistake.
Big companies have responsibilities. Otherwise it is some sort of
exploit of community by big company.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 01/12] dt-bindings: arm: mediatek: mmsys: add compatible for MT8196
2025-01-10 12:58 ` Krzysztof Kozlowski
2025-01-13 11:25 ` Fei Shao
@ 2025-01-15 9:18 ` Paul-pl Chen (陳柏霖)
1 sibling, 0 replies; 50+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-01-15 9:18 UTC (permalink / raw)
To: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
chunkuang.hu@kernel.org, AngeloGioacchino Del Regno,
krzk@kernel.org
Cc: Sunny Shen (沈姍姍),
Sirius Wang (王皓昱),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
Project_Global_Chrome_Upstream_Group,
linux-mediatek@lists.infradead.org,
Jason-JH Lin (林睿祥),
devicetree@vger.kernel.org, fshao@chromium.org,
p.zabel@pengutronix.de, Singo Chang (張興國),
linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
treapking@chromium.org
On Fri, 2025-01-10 at 13:58 +0100, Krzysztof Kozlowski wrote:
>
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>
>
> On 10/01/2025 13:33, paul-pl.chen wrote:
> > From: "Paul-pl.Chen" <paul-pl.chen@mediatek.com>
> >
> > Add compatible for mmsys yaml of MT8196
> >
> > Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
>
>
> This is a wide pattern now in Mediatek: login name is used as family
> name. Repeating the same comment to every Mediatek employee is a bit
> tedious, so maybe you could fix it internally?
>
> Create some guideline for your colleagues so you won't repeat the
> same
> things over and over?
>
> Best regards,
> Krzysztof
Hi, Krzysztof
Thank you for bringing this to our attention. We have already addressed
this issue internally and have made the necessary corrections.
Mediatek has also conducted special internal awareness campaigns
regarding this matter.
We are going to establish guidelines to ensure that our colleagues do
not repeat the same mistakes.
Thank you for your understanding and cooperation.
Best regards,
Paul
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 02/12] dt-bindings: soc: mediatek: add mutex yaml for MT8196
2025-01-10 12:33 [PATCH 00/12] Add Mediatek Soc DRM support for mt8196 paul-pl.chen
2025-01-10 12:33 ` [PATCH 01/12] dt-bindings: arm: mediatek: mmsys: add compatible for MT8196 paul-pl.chen
@ 2025-01-10 12:33 ` paul-pl.chen
2025-01-10 12:33 ` [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA " paul-pl.chen
` (11 subsequent siblings)
13 siblings, 0 replies; 50+ messages in thread
From: paul-pl.chen @ 2025-01-10 12: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.34.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-01-10 12:33 [PATCH 00/12] Add Mediatek Soc DRM support for mt8196 paul-pl.chen
2025-01-10 12:33 ` [PATCH 01/12] dt-bindings: arm: mediatek: mmsys: add compatible for MT8196 paul-pl.chen
2025-01-10 12:33 ` [PATCH 02/12] dt-bindings: soc: mediatek: add mutex yaml " paul-pl.chen
@ 2025-01-10 12:33 ` paul-pl.chen
2025-01-10 13:01 ` Krzysztof Kozlowski
2025-01-10 12:33 ` paul-pl.chen
` (10 subsequent siblings)
13 siblings, 1 reply; 50+ messages in thread
From: paul-pl.chen @ 2025-01-10 12: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.
Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
---
The header used in examples:
#include <dt-bindings/clock/mt8196-clk.h>
#include <dt-bindings/power/mt8196-power.h>
are not upstreamed yet.
It will be sent by related owner soon.
---
.../display/mediatek/mediatek,exdma.yaml | 77 +++++++++++++++++++
1 file changed, 77 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.yaml
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.yaml
new file mode 100644
index 000000000000..385f5549dfaa
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.yaml
@@ -0,0 +1,77 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/mediatek/mediatek,exdma.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek EXDMA
+
+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:
+ items:
+ - description: EXDMA Clock
+
+ power-domains:
+ maxItems: 1
+
+ mediatek,larb:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ maxItems: 1
+ items:
+ maxItems: 1
+ 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
+ - iommus
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/mt8196-clk.h>
+ #include <dt-bindings/power/mt8196-power.h>
+
+ 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 CLK_OVL_EXDMA2_DISP>;
+ power-domains = <&hfrpsys MT8196_POWER_DOMAIN_OVL0_DORMANT>;
+ mediatek,larb = <&smi_larb0>;
+ iommus = <&mm_smmu 144>;
+ #dma-cells = <1>;
+ };
+ };
--
2.34.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-01-10 12:33 ` [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA " paul-pl.chen
@ 2025-01-10 13:01 ` Krzysztof Kozlowski
2025-01-17 10:36 ` Paul-pl Chen (陳柏霖)
0 siblings, 1 reply; 50+ messages in thread
From: Krzysztof Kozlowski @ 2025-01-10 13:01 UTC (permalink / raw)
To: paul-pl.chen, 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, sunny.shen, fshao, treapking,
devicetree, linux-kernel, dri-devel, linux-mediatek,
linux-arm-kernel, Project_Global_Chrome_Upstream_Group
On 10/01/2025 13:33, paul-pl.chen wrote:
> From: "Paul-pl.Chen" <paul-pl.chen@mediatek.com>
>
> Add mediatek,exdma.yaml to support EXDMA for MT8196.
>
> Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
> ---
> The header used in examples:
> #include <dt-bindings/clock/mt8196-clk.h>
> #include <dt-bindings/power/mt8196-power.h>
> are not upstreamed yet.
Which makes this untestable and unmergeable.
This cannot be accepted. Fix your dependencies or decouple from them.
> It will be sent by related owner soon.
Still this won't build and won't be possible to apply.
> ---
> .../display/mediatek/mediatek,exdma.yaml | 77 +++++++++++++++++++
> 1 file changed, 77 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.yaml
>
> diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.yaml
> new file mode 100644
> index 000000000000..385f5549dfaa
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.yaml
Filename matching compatible.
Why is this in display? DMA goes to dma.
> @@ -0,0 +1,77 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/mediatek/mediatek,exdma.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: MediaTek EXDMA
> +
> +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.
> +
Missing ref to dma schemas.
> +properties:
> + compatible:
> + const: mediatek,mt8196-exdma
> +
> + reg:
> + maxItems: 1
> +
> + clocks:
> + items:
> + - description: EXDMA Clock
> +
> + power-domains:
> + maxItems: 1
> +
> + mediatek,larb:
> + $ref: /schemas/types.yaml#/definitions/phandle-array
Why array? And isn't the property named mediatek,larbs?
> + maxItems: 1
> + items:
> + maxItems: 1
> + 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
> + - iommus
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-01-10 13:01 ` Krzysztof Kozlowski
@ 2025-01-17 10:36 ` Paul-pl Chen (陳柏霖)
2025-01-18 8:37 ` Krzysztof Kozlowski
0 siblings, 1 reply; 50+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-01-17 10:36 UTC (permalink / raw)
To: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
chunkuang.hu@kernel.org, AngeloGioacchino Del Regno,
krzk@kernel.org
Cc: Sunny Shen (沈姍姍),
Sirius Wang (王皓昱),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
Project_Global_Chrome_Upstream_Group,
linux-mediatek@lists.infradead.org,
Jason-JH Lin (林睿祥),
devicetree@vger.kernel.org, fshao@chromium.org,
p.zabel@pengutronix.de, Singo Chang (張興國),
linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
treapking@chromium.org
On Fri, 2025-01-10 at 14:01 +0100, Krzysztof Kozlowski wrote:
>
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>
>
> On 10/01/2025 13:33, paul-pl.chen wrote:
> > From: "Paul-pl.Chen" <paul-pl.chen@mediatek.com>
> >
> > Add mediatek,exdma.yaml to support EXDMA for MT8196.
> >
> > Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
> > ---
> > The header used in examples:
> > #include <dt-bindings/clock/mt8196-clk.h>
> > #include <dt-bindings/power/mt8196-power.h>
> > are not upstreamed yet.
>
> Which makes this untestable and unmergeable.
>
> This cannot be accepted. Fix your dependencies or decouple from them.
>
> > It will be sent by related owner soon.
>
> Still this won't build and won't be possible to apply.
>
> > ---
> > .../display/mediatek/mediatek,exdma.yaml | 77
> > +++++++++++++++++++
> > 1 file changed, 77 insertions(+)
> > create mode 100644
> > Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.y
> > aml
> >
> > diff --git
> > a/Documentation/devicetree/bindings/display/mediatek/mediatek,exdma
> > .yaml
> > b/Documentation/devicetree/bindings/display/mediatek/mediatek,exdma
> > .yaml
> > new file mode 100644
> > index 000000000000..385f5549dfaa
> > --- /dev/null
> > +++
> > b/Documentation/devicetree/bindings/display/mediatek/mediatek,exdma
> > .yaml
>
> Filename matching compatible.
>
> Why is this in display? DMA goes to dma.
Hi Krzysztof ,
Regarding the issue of the EXDMA driver, we have conducted an internal
survey of drivers under the DMA subsystem. We found that EXDMA operates
differently from typical DMA drivers, and therefore we believe that the
EXDMA driver may not be suitable to be placed under the
driver/mediatek/drm directory. The main reasons are as follows:
(1)No Memory Allocation within EXDMA Engine:
The EXDMA engine does not perform memory allocation operations itself.
Instead, it relies on GEM (Graphics Execution Manager) to allocate
memory.Traditional DMA drivers often handle their own memory
allocations, but in the case of EXDMA, memory management is delegated
to GEM.
(2)Primary Task of EXDMA:
The main function of EXDMA is to transfer buffers allocated by GEM to
the subsequent display pipeline.
EXDMA serves as a bridge between memory allocated by GEM and the
display components, rather than acting as a general-purpose DMA engine.
Based on the points above, we have decided to place the EXDMA driver
under the DRM display subsystem rather than under the DMA subsystem.
>
> > @@ -0,0 +1,77 @@
> > +# 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,exdma.yaml*__;Iw!!CTRNKA9wMg0ARbw!ldlqohpAoMyTt24UKnssKOk5Qvmc_wlvQPCdjneKDCeshDPwI5Uuuy4A2sI2RlfYLIFDKZx_-GGDOlX48Q$
> > +$schema:
> > https://urldefense.com/v3/__http://devicetree.org/meta-schemas/core.yaml*__;Iw!!CTRNKA9wMg0ARbw!ldlqohpAoMyTt24UKnssKOk5Qvmc_wlvQPCdjneKDCeshDPwI5Uuuy4A2sI2RlfYLIFDKZx_-GHpxO9DFQ$
> > +
> > +title: MediaTek EXDMA
> > +
> > +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.
> > +
>
> Missing ref to dma schemas.
allOf:
- $ref: dma-controller.yaml#
>
> > +properties:
> > + compatible:
> > + const: mediatek,mt8196-exdma
> > +
> > + reg:
> > + maxItems: 1
> > +
> > + clocks:
> > + items:
> > + - description: EXDMA Clock
> > +
> > + power-domains:
> > + maxItems: 1
> > +
> > + mediatek,larb:
> > + $ref: /schemas/types.yaml#/definitions/phandle-array
>
> Why array? And isn't the property named mediatek,larbs?
>
Using "mediatek,larb" here is correct because the EXDMA hardware IP
will only have one mediatek,larb. In the next version, we will change
the phandle-array definition to a single phandle.
Please refer to this link:
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/Documentation/devicetree/bindings?id=6d0990e6e844cfa045b1a7348f58964caceb4de4
Since MT8196 use SMMU, the SMMU can no longer internally determine the
connection relationship between smi-larb and the consumer's
pm_runtime_get(_sync). Therefore, we need to add this information back.
> >
> >
> > Best, Paul
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-01-17 10:36 ` Paul-pl Chen (陳柏霖)
@ 2025-01-18 8:37 ` Krzysztof Kozlowski
2025-01-21 17:07 ` Paul-pl Chen (陳柏霖)
2025-02-11 8:23 ` Paul-pl Chen (陳柏霖)
0 siblings, 2 replies; 50+ messages in thread
From: Krzysztof Kozlowski @ 2025-01-18 8:37 UTC (permalink / raw)
To: Paul-pl Chen (陳柏霖), 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, dri-devel@lists.freedesktop.org,
Project_Global_Chrome_Upstream_Group,
linux-mediatek@lists.infradead.org,
Jason-JH Lin (林睿祥),
devicetree@vger.kernel.org, fshao@chromium.org,
p.zabel@pengutronix.de, Singo Chang (張興國),
linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
treapking@chromium.org
On 17/01/2025 11:36, Paul-pl Chen (陳柏霖) wrote:
>>> b/Documentation/devicetree/bindings/display/mediatek/mediatek,exdma
>>> .yaml
>>
>> Filename matching compatible.
>>
>> Why is this in display? DMA goes to dma.
>
> Hi Krzysztof ,
>
> Regarding the issue of the EXDMA driver, we have conducted an internal
> survey of drivers under the DMA subsystem. We found that EXDMA operates
I did not talk about driver. I talked about this patch. Look at patch
title - it starts with dt-bindings. Is here anything about driver? No.
Why do we talk about driver?
> differently from typical DMA drivers, and therefore we believe that the
> EXDMA driver may not be suitable to be placed under the
> driver/mediatek/drm directory. The main reasons are as follows:
>
> (1)No Memory Allocation within EXDMA Engine:
> The EXDMA engine does not perform memory allocation operations itself.
> Instead, it relies on GEM (Graphics Execution Manager) to allocate
> memory.Traditional DMA drivers often handle their own memory
> allocations, but in the case of EXDMA, memory management is delegated
> to GEM.
>
> (2)Primary Task of EXDMA:
> The main function of EXDMA is to transfer buffers allocated by GEM to
> the subsequent display pipeline.
> EXDMA serves as a bridge between memory allocated by GEM and the
> display components, rather than acting as a general-purpose DMA engine.
> Based on the points above, we have decided to place the EXDMA driver
> under the DRM display subsystem rather than under the DMA subsystem.
I don't care if it uses GEM or kernel allocator or even 3rd party
allocator. The question is: what is this device? If it is performing
DMA, then it should be placed in "dma" directory. The rdma was placed
differently but as you can easily check: it was never acked/reviewed, so
don't use it as an example.
Of course if it does not perform DMA, then it should not be in dma, but
then I don't agree on using dma-cells here and anything like that in the
driver.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-01-18 8:37 ` Krzysztof Kozlowski
@ 2025-01-21 17:07 ` Paul-pl Chen (陳柏霖)
2025-02-11 8:23 ` Paul-pl Chen (陳柏霖)
1 sibling, 0 replies; 50+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-01-21 17:07 UTC (permalink / raw)
To: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
chunkuang.hu@kernel.org, AngeloGioacchino Del Regno,
krzk@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
On Sat, 2025-01-18 at 09:37 +0100, Krzysztof Kozlowski wrote:
> //snip
> I did not talk about driver. I talked about this patch. Look at patch
> title - it starts with dt-bindings. Is here anything about driver?
> No.
> Why do we talk about driver?
>
> > differently from typical DMA drivers, and therefore we believe that
> > the
> > EXDMA driver may not be suitable to be placed under the
> > driver/mediatek/drm directory. The main reasons are as follows:
> >
> > (1)No Memory Allocation within EXDMA Engine:
> > The EXDMA engine does not perform memory allocation operations
> > itself.
> > Instead, it relies on GEM (Graphics Execution Manager) to allocate
> > memory.Traditional DMA drivers often handle their own memory
> > allocations, but in the case of EXDMA, memory management is
> > delegated
> > to GEM.
> >
> > (2)Primary Task of EXDMA:
> > The main function of EXDMA is to transfer buffers allocated by GEM
> > to
> > the subsequent display pipeline.
> > EXDMA serves as a bridge between memory allocated by GEM and the
> > display components, rather than acting as a general-purpose DMA
> > engine.
> > Based on the points above, we have decided to place the EXDMA
> > driver
> > under the DRM display subsystem rather than under the DMA
> > subsystem.
>
>
> I don't care if it uses GEM or kernel allocator or even 3rd party
> allocator. The question is: what is this device? If it is performing
> DMA, then it should be placed in "dma" directory. The rdma was placed
> differently but as you can easily check: it was never acked/reviewed,
> so
> don't use it as an example.
>
> Of course if it does not perform DMA, then it should not be in dma,
> but
> then I don't agree on using dma-cells here and anything like that in
> the
> driver.
>
> Best regards,
> Krzysztof
>
Hi Krzysztof,
The current placement of EXDMA under the display subsystem in
Mediatek's architecture is primarily due to its functional role as a
sub-device within the display pipeline.
In MT8196 hardware design, the sub-devices in display pipeline follow a
sequence of: EXDMA -> BLENDER -> OUTPROC -> PQ -> DVO.
In MT8195 hardware design, the sub-devices in display pipeline follow a
sequence of: OVL -> PQ ->DSI.
As we see, OVL has been divided into three new hardware IPs in MT8196.
OVL and EXDMA both have the ability to fetch data directly from DRAM
and can be regarded as DMA controller.
I also have confirmed with the hardware designer that EXDMA is a kind
of DMA, but it is specially designed to handle the graphical layer, and
has better performance than ordinary DMA.
Therefore, I think that moving EXDMA and OVL from the display folder to
the DMA folder, or only kepping them in the display folder is decided
by the two different views of DMA ability or display sub-device.
We will follow your instructions to put EXDMA on the place you decided.
Best regards,
Paul Chen
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-01-18 8:37 ` Krzysztof Kozlowski
2025-01-21 17:07 ` Paul-pl Chen (陳柏霖)
@ 2025-02-11 8:23 ` Paul-pl Chen (陳柏霖)
2025-02-12 5:40 ` Krzysztof Kozlowski
1 sibling, 1 reply; 50+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-02-11 8:23 UTC (permalink / raw)
To: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
chunkuang.hu@kernel.org, AngeloGioacchino Del Regno,
krzk@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
On Sat, 2025-01-18 at 09:37 +0100, Krzysztof Kozlowski wrote:
>
> >
> > (2)Primary Task of EXDMA:
> > The main function of EXDMA is to transfer buffers allocated by GEM
> > to
> > the subsequent display pipeline.
> > EXDMA serves as a bridge between memory allocated by GEM and the
> > display components, rather than acting as a general-purpose DMA
> > engine.
> > Based on the points above, we have decided to place the EXDMA
> > driver
> > under the DRM display subsystem rather than under the DMA
> > subsystem.
>
>
> I don't care if it uses GEM or kernel allocator or even 3rd party
> allocator. The question is: what is this device? If it is performing
> DMA, then it should be placed in "dma" directory. The rdma was placed
> differently but as you can easily check: it was never acked/reviewed,
> so
> don't use it as an example.
>
> Of course if it does not perform DMA, then it should not be in dma,
> but
> then I don't agree on using dma-cells here and anything like that in
> the
> driver.
>
> Best regards,
> Krzysztof
>
>
>
Hi KK,
Sorry, I just found this email was not send.
This email is discuss about the EXDMA under the display subsystem
The current placement of EXDMA under the display subsystem in
Mediatek's architecture is primarily due to its functional role as a
sub-device within the display pipeline.
In MT8196 hardware design, the sub-devices in display pipeline follow a
sequence of: EXDMA -> BLENDER -> OUTPROC -> PQ -> DVO.
In MT8195 hardware design, the sub-devices in display pipeline follow a
sequence of: OVL -> PQ ->DSI.
As we see, OVL has been divided into three new hardware IPs in MT8196.
OVL and EXDMA both have the ability to fetch data directly from DRAM
and can be regarded as DMA controller.
I also have confirmed with the hardware designer that EXDMA is a kind
of DMA, but it is specially designed to handle the graphical layer, and
has better performance than ordinary DMA.
Therefore, I think that moving EXDMA and OVL from the display folder to
the DMA folder, or only kepping them in the display folder is decided
by the two different views of DMA ability or display sub-device.
We will follow your instructions to put EXDMA on the place you decided.
Best, Paul
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-02-11 8:23 ` Paul-pl Chen (陳柏霖)
@ 2025-02-12 5:40 ` Krzysztof Kozlowski
0 siblings, 0 replies; 50+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-12 5:40 UTC (permalink / raw)
To: Paul-pl Chen (陳柏霖), robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org, chunkuang.hu@kernel.org,
AngeloGioacchino Del Regno
Cc: Sunny Shen (沈姍姍),
Sirius Wang (王皓昱),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
linux-kernel@vger.kernel.org,
Project_Global_Chrome_Upstream_Group,
dri-devel@lists.freedesktop.org,
linux-mediatek@lists.infradead.org,
Jason-JH Lin (林睿祥),
devicetree@vger.kernel.org, fshao@chromium.org,
p.zabel@pengutronix.de, Singo Chang (張興國),
linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
treapking@chromium.org
On 11/02/2025 09:23, Paul-pl Chen (陳柏霖) wrote:
> On Sat, 2025-01-18 at 09:37 +0100, Krzysztof Kozlowski wrote:
>>
>>>
>>> (2)Primary Task of EXDMA:
>>> The main function of EXDMA is to transfer buffers allocated by GEM
>>> to
>>> the subsequent display pipeline.
>>> EXDMA serves as a bridge between memory allocated by GEM and the
>>> display components, rather than acting as a general-purpose DMA
>>> engine.
>>> Based on the points above, we have decided to place the EXDMA
>>> driver
>>> under the DRM display subsystem rather than under the DMA
>>> subsystem.
>>
>>
>> I don't care if it uses GEM or kernel allocator or even 3rd party
>> allocator. The question is: what is this device? If it is performing
>> DMA, then it should be placed in "dma" directory. The rdma was placed
>> differently but as you can easily check: it was never acked/reviewed,
>> so
>> don't use it as an example.
>>
>> Of course if it does not perform DMA, then it should not be in dma,
>> but
>> then I don't agree on using dma-cells here and anything like that in
>> the
>> driver.
>>
>> Best regards,
>> Krzysztof
>>
>>
>>
>
> Hi KK,
>
> Sorry, I just found this email was not send.
>
> This email is discuss about the EXDMA under the display subsystem
>
> The current placement of EXDMA under the display subsystem in
> Mediatek's architecture is primarily due to its functional role as a
> sub-device within the display pipeline.
>
> In MT8196 hardware design, the sub-devices in display pipeline follow a
> sequence of: EXDMA -> BLENDER -> OUTPROC -> PQ -> DVO.
>
> In MT8195 hardware design, the sub-devices in display pipeline follow a
> sequence of: OVL -> PQ ->DSI.
>
> As we see, OVL has been divided into three new hardware IPs in MT8196.
> OVL and EXDMA both have the ability to fetch data directly from DRAM
> and can be regarded as DMA controller.
>
> I also have confirmed with the hardware designer that EXDMA is a kind
> of DMA, but it is specially designed to handle the graphical layer, and
> has better performance than ordinary DMA.
To me the decisive factor is that you use dma-cells here, so it is a DMA
controller. DMA controllers should placed in a directory of their
maintainer, so they can review it.
>
> Therefore, I think that moving EXDMA and OVL from the display folder to
> the DMA folder, or only kepping them in the display folder is decided
> by the two different views of DMA ability or display sub-device.
>
> We will follow your instructions to put EXDMA on the place you decided.
>
>
> Best, Paul
>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-01-10 12:33 [PATCH 00/12] Add Mediatek Soc DRM support for mt8196 paul-pl.chen
` (2 preceding siblings ...)
2025-01-10 12:33 ` [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA " paul-pl.chen
@ 2025-01-10 12:33 ` paul-pl.chen
2025-01-10 13:54 ` Rob Herring (Arm)
2025-01-10 12:34 ` [PATCH 04/12] dt-bindings: display: mediatek: add BLENDER " paul-pl.chen
` (9 subsequent siblings)
13 siblings, 1 reply; 50+ messages in thread
From: paul-pl.chen @ 2025-01-10 12: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.
Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
---
The header used in examples:
#include <dt-bindings/clock/mt8196-clk.h>
#include <dt-bindings/power/mt8196-power.h>
are not upstreamed yet.
It will be sent by related owner soon.
---
.../display/mediatek/mediatek,exdma.yaml | 77 +++++++++++++++++++
1 file changed, 77 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.yaml
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.yaml
new file mode 100644
index 000000000000..385f5549dfaa
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.yaml
@@ -0,0 +1,77 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/mediatek/mediatek,exdma.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek EXDMA
+
+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:
+ items:
+ - description: EXDMA Clock
+
+ power-domains:
+ maxItems: 1
+
+ mediatek,larb:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ maxItems: 1
+ items:
+ maxItems: 1
+ 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
+ - iommus
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/mt8196-clk.h>
+ #include <dt-bindings/power/mt8196-power.h>
+
+ 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 CLK_OVL_EXDMA2_DISP>;
+ power-domains = <&hfrpsys MT8196_POWER_DOMAIN_OVL0_DORMANT>;
+ mediatek,larb = <&smi_larb0>;
+ iommus = <&mm_smmu 144>;
+ #dma-cells = <1>;
+ };
+ };
--
2.34.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-01-10 12:33 ` paul-pl.chen
@ 2025-01-10 13:54 ` Rob Herring (Arm)
2025-01-14 5:49 ` Paul-pl Chen (陳柏霖)
0 siblings, 1 reply; 50+ messages in thread
From: Rob Herring (Arm) @ 2025-01-10 13:54 UTC (permalink / raw)
To: paul-pl.chen
Cc: conor+dt, singo.chang, sunny.shen, chunkuang.hu,
Project_Global_Chrome_Upstream_Group, fshao, sirius.wang,
dri-devel, matthias.bgg, linux-kernel, devicetree, xiandong.wang,
treapking, nancy.lin, linux-mediatek, p.zabel, jason-jh.lin,
angelogioacchino.delregno, linux-arm-kernel, krzk+dt
On Fri, 10 Jan 2025 20:33:59 +0800, paul-pl.chen wrote:
> From: "Paul-pl.Chen" <paul-pl.chen@mediatek.com>
>
> Add mediatek,exdma.yaml to support EXDMA for MT8196.
>
> Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
> ---
> The header used in examples:
> #include <dt-bindings/clock/mt8196-clk.h>
> #include <dt-bindings/power/mt8196-power.h>
> are not upstreamed yet.
> It will be sent by related owner soon.
> ---
> .../display/mediatek/mediatek,exdma.yaml | 77 +++++++++++++++++++
> 1 file changed, 77 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.yaml
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
dtschema/dtc warnings/errors:
Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.example.dts:18:18: fatal error: dt-bindings/clock/mt8196-clk.h: No such file or directory
18 | #include <dt-bindings/clock/mt8196-clk.h>
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [scripts/Makefile.dtbs:131: Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.example.dtb] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [/builds/robherring/dt-review-ci/linux/Makefile:1506: dt_binding_check] Error 2
make: *** [Makefile:251: __sub-make] Error 2
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250110123835.2719824-5-paul-pl.chen@mediatek.com
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
^ permalink raw reply [flat|nested] 50+ messages in thread* RE: [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-01-10 13:54 ` Rob Herring (Arm)
@ 2025-01-14 5:49 ` Paul-pl Chen (陳柏霖)
2025-01-14 10:34 ` AngeloGioacchino Del Regno
2025-01-18 9:22 ` Krzysztof Kozlowski
0 siblings, 2 replies; 50+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-01-14 5:49 UTC (permalink / raw)
To: Rob Herring (Arm)
Cc: conor+dt@kernel.org, Singo Chang (張興國),
Sunny Shen (沈姍姍), chunkuang.hu@kernel.org,
Project_Global_Chrome_Upstream_Group, fshao@chromium.org,
Sirius Wang (王皓昱),
dri-devel@lists.freedesktop.org, matthias.bgg@gmail.com,
linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
Xiandong Wang (王先冬), treapking@chromium.org,
Nancy Lin (林欣螢),
linux-mediatek@lists.infradead.org, p.zabel@pengutronix.de,
Jason-JH Lin (林睿祥),
AngeloGioacchino Del Regno, linux-arm-kernel@lists.infradead.org,
krzk+dt@kernel.org
Hi Rob
Thanks for the advice.
The root cause of the erroneous log message is due to missing power/clock dependencies.
Once the MTK clock/power header file is upstreamed,
we will include a reference link in the next version of the upstream series submission.
Best, Paul-pl Chen
-----Original Message-----
From: Rob Herring (Arm) <robh@kernel.org>
Sent: Friday, January 10, 2025 9:54 PM
To: Paul-pl Chen (陳柏霖) <Paul-pl.Chen@mediatek.com>
Cc: conor+dt@kernel.org; Singo Chang (張興國) <Singo.Chang@mediatek.com>; Sunny Shen (沈姍姍) <Sunny.Shen@mediatek.com>; chunkuang.hu@kernel.org; Project_Global_Chrome_Upstream_Group <Project_Global_Chrome_Upstream_Group@mediatek.com>; fshao@chromium.org; Sirius Wang (王皓昱) <Sirius.Wang@mediatek.com>; dri-devel@lists.freedesktop.org; matthias.bgg@gmail.com; linux-kernel@vger.kernel.org; devicetree@vger.kernel.org; Xiandong Wang (王先冬) <Xiandong.Wang@mediatek.com>; treapking@chromium.org; Nancy Lin (林欣螢) <Nancy.Lin@mediatek.com>; linux-mediatek@lists.infradead.org; p.zabel@pengutronix.de; Jason-JH Lin (林睿祥) <Jason-JH.Lin@mediatek.com>; AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>; linux-arm-kernel@lists.infradead.org; krzk+dt@kernel.org
Subject: Re: [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
External email : Please do not click links or open attachments until you have verified the sender or the content.
On Fri, 10 Jan 2025 20:33:59 +0800, paul-pl.chen wrote:
> From: "Paul-pl.Chen" <paul-pl.chen@mediatek.com>
>
> Add mediatek,exdma.yaml to support EXDMA for MT8196.
>
> Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
> ---
> The header used in examples:
> #include <dt-bindings/clock/mt8196-clk.h> #include
> <dt-bindings/power/mt8196-power.h>
> are not upstreamed yet.
> It will be sent by related owner soon.
> ---
> .../display/mediatek/mediatek,exdma.yaml | 77 +++++++++++++++++++
> 1 file changed, 77 insertions(+)
> create mode 100644
> Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.yaml
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
dtschema/dtc warnings/errors:
Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.example.dts:18:18: fatal error: dt-bindings/clock/mt8196-clk.h: No such file or directory
18 | #include <dt-bindings/clock/mt8196-clk.h>
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [scripts/Makefile.dtbs:131: Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.example.dtb] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [/builds/robherring/dt-review-ci/linux/Makefile:1506: dt_binding_check] Error 2
make: *** [Makefile:251: __sub-make] Error 2
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250110123835.2719824-5-paul-pl.chen@mediatek.com
The base for the series is generally the latest rc1. A different dependency should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note that DT_SCHEMA_FILES can be set to your schema file to speed up checking your schema. However, it must be unset to test all examples with your schema.
^ permalink raw reply [flat|nested] 50+ messages in thread* Re: [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-01-14 5:49 ` Paul-pl Chen (陳柏霖)
@ 2025-01-14 10:34 ` AngeloGioacchino Del Regno
2025-01-15 12:13 ` Paul-pl Chen (陳柏霖)
2025-01-18 9:22 ` Krzysztof Kozlowski
1 sibling, 1 reply; 50+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-01-14 10:34 UTC (permalink / raw)
To: Paul-pl Chen (陳柏霖), Rob Herring (Arm)
Cc: conor+dt@kernel.org, Singo Chang (張興國),
Sunny Shen (沈姍姍), chunkuang.hu@kernel.org,
Project_Global_Chrome_Upstream_Group, fshao@chromium.org,
Sirius Wang (王皓昱),
dri-devel@lists.freedesktop.org, matthias.bgg@gmail.com,
linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
Xiandong Wang (王先冬), treapking@chromium.org,
Nancy Lin (林欣螢),
linux-mediatek@lists.infradead.org, p.zabel@pengutronix.de,
Jason-JH Lin (林睿祥),
linux-arm-kernel@lists.infradead.org, krzk+dt@kernel.org
Il 14/01/25 06:49, Paul-pl Chen (陳柏霖) ha scritto:
> Hi Rob
> Thanks for the advice.
> The root cause of the erroneous log message is due to missing power/clock dependencies.
> Once the MTK clock/power header file is upstreamed,
The mt8196-clk/power.h filenames are anyway wrong for upstream.... :-)
Cheers,
Angelo
> we will include a reference link in the next version of the upstream series submission.
>
> Best, Paul-pl Chen
>
> -----Original Message-----
> From: Rob Herring (Arm) <robh@kernel.org>
> Sent: Friday, January 10, 2025 9:54 PM
> To: Paul-pl Chen (陳柏霖) <Paul-pl.Chen@mediatek.com>
> Cc: conor+dt@kernel.org; Singo Chang (張興國) <Singo.Chang@mediatek.com>; Sunny Shen (沈姍姍) <Sunny.Shen@mediatek.com>; chunkuang.hu@kernel.org; Project_Global_Chrome_Upstream_Group <Project_Global_Chrome_Upstream_Group@mediatek.com>; fshao@chromium.org; Sirius Wang (王皓昱) <Sirius.Wang@mediatek.com>; dri-devel@lists.freedesktop.org; matthias.bgg@gmail.com; linux-kernel@vger.kernel.org; devicetree@vger.kernel.org; Xiandong Wang (王先冬) <Xiandong.Wang@mediatek.com>; treapking@chromium.org; Nancy Lin (林欣螢) <Nancy.Lin@mediatek.com>; linux-mediatek@lists.infradead.org; p.zabel@pengutronix.de; Jason-JH Lin (林睿祥) <Jason-JH.Lin@mediatek.com>; AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>; linux-arm-kernel@lists.infradead.org; krzk+dt@kernel.org
> Subject: Re: [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
>
>
> External email : Please do not click links or open attachments until you have verified the sender or the content.
>
>
> On Fri, 10 Jan 2025 20:33:59 +0800, paul-pl.chen wrote:
>> From: "Paul-pl.Chen" <paul-pl.chen@mediatek.com>
>>
>> Add mediatek,exdma.yaml to support EXDMA for MT8196.
>>
>> Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
>> ---
>> The header used in examples:
>> #include <dt-bindings/clock/mt8196-clk.h> #include
>> <dt-bindings/power/mt8196-power.h>
>> are not upstreamed yet.
>> It will be sent by related owner soon.
>> ---
>> .../display/mediatek/mediatek,exdma.yaml | 77 +++++++++++++++++++
>> 1 file changed, 77 insertions(+)
>> create mode 100644
>> Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.yaml
>>
>
> My bot found errors running 'make dt_binding_check' on your patch:
>
> yamllint warnings/errors:
>
> dtschema/dtc warnings/errors:
> Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.example.dts:18:18: fatal error: dt-bindings/clock/mt8196-clk.h: No such file or directory
> 18 | #include <dt-bindings/clock/mt8196-clk.h>
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> compilation terminated.
> make[2]: *** [scripts/Makefile.dtbs:131: Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.example.dtb] Error 1
> make[2]: *** Waiting for unfinished jobs....
> make[1]: *** [/builds/robherring/dt-review-ci/linux/Makefile:1506: dt_binding_check] Error 2
> make: *** [Makefile:251: __sub-make] Error 2
>
> doc reference errors (make refcheckdocs):
>
> See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250110123835.2719824-5-paul-pl.chen@mediatek.com
>
> The base for the series is generally the latest rc1. A different dependency should be noted in *this* patch.
>
> If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to
> date:
>
> pip3 install dtschema --upgrade
>
> Please check and re-submit after running the above command yourself. Note that DT_SCHEMA_FILES can be set to your schema file to speed up checking your schema. However, it must be unset to test all examples with your schema.
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-01-14 10:34 ` AngeloGioacchino Del Regno
@ 2025-01-15 12:13 ` Paul-pl Chen (陳柏霖)
0 siblings, 0 replies; 50+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-01-15 12:13 UTC (permalink / raw)
To: robh@kernel.org, AngeloGioacchino Del Regno
Cc: Sunny Shen (沈姍姍),
Sirius Wang (王皓昱),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
linux-mediatek@lists.infradead.org, conor+dt@kernel.org,
Project_Global_Chrome_Upstream_Group,
linux-kernel@vger.kernel.org, chunkuang.hu@kernel.org,
devicetree@vger.kernel.org, fshao@chromium.org,
krzk+dt@kernel.org, p.zabel@pengutronix.de,
Singo Chang (張興國),
Jason-JH Lin (林睿祥),
linux-arm-kernel@lists.infradead.org,
dri-devel@lists.freedesktop.org, matthias.bgg@gmail.com,
treapking@chromium.org
On Tue, 2025-01-14 at 11:34 +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 14/01/25 06:49, Paul-pl Chen (陳柏霖) ha scritto:
> > Hi Rob
> > Thanks for the advice.
> > The root cause of the erroneous log message is due to missing
> > power/clock dependencies.
> > Once the MTK clock/power header file is upstreamed,
>
> The mt8196-clk/power.h filenames are anyway wrong for upstream.... :-
> )
>
> Cheers,
> Angelo
>
Hi, Angelo
may I ask if you mean that the filenames "mt8196-clk/power.h "need to
be changed to the following?
"mediatek,mt8188-clk.h"
"mediatek,mt8188-power.h"
If so, we will ask the Mediatek clock/power owner to submit them
according to the correct upstream format.
>
Best,
Paul
//snip
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-01-14 5:49 ` Paul-pl Chen (陳柏霖)
2025-01-14 10:34 ` AngeloGioacchino Del Regno
@ 2025-01-18 9:22 ` Krzysztof Kozlowski
2025-01-21 17:14 ` Paul-pl Chen (陳柏霖)
2025-01-23 6:11 ` Paul-pl Chen (陳柏霖)
1 sibling, 2 replies; 50+ messages in thread
From: Krzysztof Kozlowski @ 2025-01-18 9:22 UTC (permalink / raw)
To: Paul-pl Chen (陳柏霖), Rob Herring (Arm)
Cc: conor+dt@kernel.org, Singo Chang (張興國),
Sunny Shen (沈姍姍), chunkuang.hu@kernel.org,
Project_Global_Chrome_Upstream_Group, fshao@chromium.org,
Sirius Wang (王皓昱),
dri-devel@lists.freedesktop.org, matthias.bgg@gmail.com,
linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
Xiandong Wang (王先冬), treapking@chromium.org,
Nancy Lin (林欣螢),
linux-mediatek@lists.infradead.org, p.zabel@pengutronix.de,
Jason-JH Lin (林睿祥),
AngeloGioacchino Del Regno, linux-arm-kernel@lists.infradead.org,
krzk+dt@kernel.org
On 14/01/2025 06:49, Paul-pl Chen (陳柏霖) wrote:
> Hi Rob
> Thanks for the advice.
> The root cause of the erroneous log message is due to missing power/clock dependencies.
> Once the MTK clock/power header file is upstreamed,
So this cannot be merged.
Decouple dependencies or wait with your submission till depenedncy is
applied to *LINUS* tree, not even maintainer. Otherwise this breaks
maintainer's tree. I really suggest decoupling.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-01-18 9:22 ` Krzysztof Kozlowski
@ 2025-01-21 17:14 ` Paul-pl Chen (陳柏霖)
2025-01-23 6:11 ` Paul-pl Chen (陳柏霖)
1 sibling, 0 replies; 50+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-01-21 17:14 UTC (permalink / raw)
To: robh@kernel.org, krzk@kernel.org
Cc: Sunny Shen (沈姍姍),
Sirius Wang (王皓昱),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
AngeloGioacchino Del Regno, linux-mediatek@lists.infradead.org,
conor+dt@kernel.org, Project_Global_Chrome_Upstream_Group,
linux-kernel@vger.kernel.org, chunkuang.hu@kernel.org,
devicetree@vger.kernel.org, fshao@chromium.org,
krzk+dt@kernel.org, p.zabel@pengutronix.de,
Singo Chang (張興國),
Jason-JH Lin (林睿祥),
linux-arm-kernel@lists.infradead.org,
dri-devel@lists.freedesktop.org, matthias.bgg@gmail.com,
treapking@chromium.org
On Sat, 2025-01-18 at 10:22 +0100, Krzysztof Kozlowski wrote:
> Decouple dependencies or wait with your submission till depenedncy is
> applied to *LINUS* tree, not even maintainer. Otherwise this breaks
> maintainer's tree. I really suggest decoupling.
>
> Best regards,
> Krzysztof
Thanks for the suggestion,
We will wait the dependency commit is applied to *LINUS* tree.
Best regards,
Paul
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-01-18 9:22 ` Krzysztof Kozlowski
2025-01-21 17:14 ` Paul-pl Chen (陳柏霖)
@ 2025-01-23 6:11 ` Paul-pl Chen (陳柏霖)
2025-01-23 6:25 ` Chen-Yu Tsai
2025-01-23 7:21 ` Krzysztof Kozlowski
1 sibling, 2 replies; 50+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-01-23 6:11 UTC (permalink / raw)
To: robh@kernel.org, krzk@kernel.org
Cc: Sunny Shen (沈姍姍),
Sirius Wang (王皓昱),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
AngeloGioacchino Del Regno, linux-mediatek@lists.infradead.org,
conor+dt@kernel.org, Project_Global_Chrome_Upstream_Group,
linux-kernel@vger.kernel.org, chunkuang.hu@kernel.org,
devicetree@vger.kernel.org, fshao@chromium.org,
krzk+dt@kernel.org, p.zabel@pengutronix.de,
Singo Chang (張興國),
Jason-JH Lin (林睿祥),
linux-arm-kernel@lists.infradead.org,
dri-devel@lists.freedesktop.org, matthias.bgg@gmail.com,
treapking@chromium.org
On Sat, 2025-01-18 at 10:22 +0100, Krzysztof Kozlowski wrote:
>
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>
>
> On 14/01/2025 06:49, Paul-pl Chen (陳柏霖) wrote:
> > Hi Rob
> > Thanks for the advice.
> > The root cause of the erroneous log message is due to missing
> > power/clock dependencies.
> > Once the MTK clock/power header file is upstreamed,
> So this cannot be merged.
>
> Decouple dependencies or wait with your submission till depenedncy is
> applied to *LINUS* tree, not even maintainer. Otherwise this breaks
> maintainer's tree. I really suggest decoupling.
>
> Best regards,
> Krzysztof
>
Hi Krzysztof
I hope this email finds you well. I have a couple of questions
regarding the EXDMA commit patch and decoupling:
1. Would removing the example from the EXDMA commit patch be sufficient
to achieve decoupling for EXDMA YAML and MTK clock/power header?
2. If removing the example from the EXDMA YAML is not allowed, what
alternative changes could we implement to achieve decoupling?
Thank you for your time and expertise. I appreciate any insights you
can provide.
Best regards,
Paul
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-01-23 6:11 ` Paul-pl Chen (陳柏霖)
@ 2025-01-23 6:25 ` Chen-Yu Tsai
2025-01-23 16:09 ` Paul-pl Chen (陳柏霖)
2025-01-23 7:21 ` Krzysztof Kozlowski
1 sibling, 1 reply; 50+ messages in thread
From: Chen-Yu Tsai @ 2025-01-23 6:25 UTC (permalink / raw)
To: Paul-pl Chen (陳柏霖)
Cc: robh@kernel.org, krzk@kernel.org,
Sunny Shen (沈姍姍),
Sirius Wang (王皓昱),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
AngeloGioacchino Del Regno, linux-mediatek@lists.infradead.org,
conor+dt@kernel.org, Project_Global_Chrome_Upstream_Group,
linux-kernel@vger.kernel.org, chunkuang.hu@kernel.org,
devicetree@vger.kernel.org, fshao@chromium.org,
krzk+dt@kernel.org, p.zabel@pengutronix.de,
Singo Chang (張興國),
Jason-JH Lin (林睿祥),
linux-arm-kernel@lists.infradead.org,
dri-devel@lists.freedesktop.org, matthias.bgg@gmail.com,
treapking@chromium.org
On Thu, Jan 23, 2025 at 2:11 PM Paul-pl Chen (陳柏霖)
<Paul-pl.Chen@mediatek.com> wrote:
>
> On Sat, 2025-01-18 at 10:22 +0100, Krzysztof Kozlowski wrote:
> >
> > External email : Please do not click links or open attachments until
> > you have verified the sender or the content.
> >
> >
> > On 14/01/2025 06:49, Paul-pl Chen (陳柏霖) wrote:
> > > Hi Rob
> > > Thanks for the advice.
> > > The root cause of the erroneous log message is due to missing
> > > power/clock dependencies.
> > > Once the MTK clock/power header file is upstreamed,
> > So this cannot be merged.
> >
> > Decouple dependencies or wait with your submission till depenedncy is
> > applied to *LINUS* tree, not even maintainer. Otherwise this breaks
> > maintainer's tree. I really suggest decoupling.
> >
> > Best regards,
> > Krzysztof
> >
>
> Hi Krzysztof
>
> I hope this email finds you well. I have a couple of questions
> regarding the EXDMA commit patch and decoupling:
>
> 1. Would removing the example from the EXDMA commit patch be sufficient
> to achieve decoupling for EXDMA YAML and MTK clock/power header?
>
> 2. If removing the example from the EXDMA YAML is not allowed, what
> alternative changes could we implement to achieve decoupling?
Just replace the macros in the example with the raw numbers, and
drop the inclusion of the header.
ChenYu
> Thank you for your time and expertise. I appreciate any insights you
> can provide.
>
> Best regards,
>
> Paul
>
> ************* MEDIATEK Confidentiality Notice ********************
> The information contained in this e-mail message (including any
> attachments) may be confidential, proprietary, privileged, or otherwise
> exempt from disclosure under applicable laws. It is intended to be
> conveyed only to the designated recipient(s). Any use, dissemination,
> distribution, printing, retaining or copying of this e-mail (including its
> attachments) by unintended recipient(s) is strictly prohibited and may
> be unlawful. If you are not an intended recipient of this e-mail, or believe
> that you have received this e-mail in error, please notify the sender
> immediately (by replying to this e-mail), delete any and all copies of
> this e-mail (including any attachments) from your system, and do not
> disclose the content of this e-mail to any other person. Thank you!
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-01-23 6:25 ` Chen-Yu Tsai
@ 2025-01-23 16:09 ` Paul-pl Chen (陳柏霖)
0 siblings, 0 replies; 50+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-01-23 16:09 UTC (permalink / raw)
To: wenst@chromium.org
Cc: robh@kernel.org, Sunny Shen (沈姍姍),
Sirius Wang (王皓昱),
Nancy Lin (林欣螢), AngeloGioacchino Del Regno,
Xiandong Wang (王先冬),
linux-kernel@vger.kernel.org,
Project_Global_Chrome_Upstream_Group, conor+dt@kernel.org,
linux-mediatek@lists.infradead.org, chunkuang.hu@kernel.org,
devicetree@vger.kernel.org, fshao@chromium.org,
krzk+dt@kernel.org, p.zabel@pengutronix.de,
Singo Chang (張興國), krzk@kernel.org,
Jason-JH Lin (林睿祥),
linux-arm-kernel@lists.infradead.org,
dri-devel@lists.freedesktop.org, matthias.bgg@gmail.com,
treapking@chromium.org
On Thu, 2025-01-23 at 14:25 +0800, Chen-Yu Tsai wrote:
>
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>
>
> On Thu, Jan 23, 2025 at 2:11 PM Paul-pl Chen (陳柏霖)
> <Paul-pl.Chen@mediatek.com> wrote:
> >
> > On Sat, 2025-01-18 at 10:22 +0100, Krzysztof Kozlowski wrote:
> > >
> > > External email : Please do not click links or open attachments
> > > until
> > > you have verified the sender or the content.
> > >
> > >
> > > On 14/01/2025 06:49, Paul-pl Chen (陳柏霖) wrote:
> > > > Hi Rob
> > > > Thanks for the advice.
> > > > The root cause of the erroneous log message is due to missing
> > > > power/clock dependencies.
> > > > Once the MTK clock/power header file is upstreamed,
> > > So this cannot be merged.
> > >
> > > Decouple dependencies or wait with your submission till
> > > depenedncy is
> > > applied to *LINUS* tree, not even maintainer. Otherwise this
> > > breaks
> > > maintainer's tree. I really suggest decoupling.
> > >
> > > Best regards,
> > > Krzysztof
> > >
> >
> > Hi Krzysztof
> >
> > I hope this email finds you well. I have a couple of questions
> > regarding the EXDMA commit patch and decoupling:
> >
> > 1. Would removing the example from the EXDMA commit patch be
> > sufficient
> > to achieve decoupling for EXDMA YAML and MTK clock/power header?
> >
> > 2. If removing the example from the EXDMA YAML is not allowed, what
> > alternative changes could we implement to achieve decoupling?
>
> Just replace the macros in the example with the raw numbers, and
> drop the inclusion of the header.
>
> ChenYu
>
>
Hi ChenYu
Thanks for the review and suggestion.
Best Regards,
Paul
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-01-23 6:11 ` Paul-pl Chen (陳柏霖)
2025-01-23 6:25 ` Chen-Yu Tsai
@ 2025-01-23 7:21 ` Krzysztof Kozlowski
2025-01-23 16:14 ` Paul-pl Chen (陳柏霖)
1 sibling, 1 reply; 50+ messages in thread
From: Krzysztof Kozlowski @ 2025-01-23 7:21 UTC (permalink / raw)
To: Paul-pl Chen (陳柏霖), robh@kernel.org
Cc: Sunny Shen (沈姍姍),
Sirius Wang (王皓昱),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
AngeloGioacchino Del Regno, linux-mediatek@lists.infradead.org,
conor+dt@kernel.org, Project_Global_Chrome_Upstream_Group,
linux-kernel@vger.kernel.org, chunkuang.hu@kernel.org,
devicetree@vger.kernel.org, fshao@chromium.org,
krzk+dt@kernel.org, p.zabel@pengutronix.de,
Singo Chang (張興國),
Jason-JH Lin (林睿祥),
linux-arm-kernel@lists.infradead.org,
dri-devel@lists.freedesktop.org, matthias.bgg@gmail.com,
treapking@chromium.org
On 23/01/2025 07:11, Paul-pl Chen (陳柏霖) wrote:
>
> Hi Krzysztof
>
> I hope this email finds you well. I have a couple of questions
> regarding the EXDMA commit patch and decoupling:
>
> 1. Would removing the example from the EXDMA commit patch be sufficient
> to achieve decoupling for EXDMA YAML and MTK clock/power header?
No
>
> 2. If removing the example from the EXDMA YAML is not allowed, what
> alternative changes could we implement to achieve decoupling?
Don't use the header constants but just some fake phandle.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-01-23 7:21 ` Krzysztof Kozlowski
@ 2025-01-23 16:14 ` Paul-pl Chen (陳柏霖)
2025-01-23 16:20 ` Chen-Yu Tsai
0 siblings, 1 reply; 50+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-01-23 16:14 UTC (permalink / raw)
To: robh@kernel.org, krzk@kernel.org
Cc: Sunny Shen (沈姍姍),
Sirius Wang (王皓昱),
Nancy Lin (林欣螢), AngeloGioacchino Del Regno,
Xiandong Wang (王先冬),
linux-mediatek@lists.infradead.org,
Project_Global_Chrome_Upstream_Group, conor+dt@kernel.org,
linux-kernel@vger.kernel.org, chunkuang.hu@kernel.org,
devicetree@vger.kernel.org, fshao@chromium.org,
krzk+dt@kernel.org, p.zabel@pengutronix.de,
Singo Chang (張興國),
Jason-JH Lin (林睿祥),
linux-arm-kernel@lists.infradead.org,
dri-devel@lists.freedesktop.org, matthias.bgg@gmail.com,
treapking@chromium.org
On Thu, 2025-01-23 at 08:21 +0100, Krzysztof Kozlowski wrote:
>
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>
>
> On 23/01/2025 07:11, Paul-pl Chen (陳柏霖) wrote:
> >
> > Hi Krzysztof
> >
> > I hope this email finds you well. I have a couple of questions
> > regarding the EXDMA commit patch and decoupling:
> >
> > 1. Would removing the example from the EXDMA commit patch be
> > sufficient
> > to achieve decoupling for EXDMA YAML and MTK clock/power header?
>
> No
>
> >
> > 2. If removing the example from the EXDMA YAML is not allowed, what
> > alternative changes could we implement to achieve decoupling?
>
> Don't use the header constants but just some fake phandle.
>
>
>
> Best regards,
> Krzysztof
Hi Krzysztof,
Once again, thanks for the review and reply.
SO If we apply Chenyu's suggestion:
+ example:
+ -|
+ soc {
+
+ disp_ovl0_exdma2: dma-controller@32850000 {
+ compatible = "mediatek,mt8196-exdma";
+ reg = <0 0x32850000 0 0x1000>;
+ clocks = <13>;
+ power-domains = <12>;
+ mediatek,larb = <88>;
+ iommus = <&mm_smmu 144>;
+ #dma-cells = <1>;
+ };
+ };
Does this work for decoupling?
Best Regards,
Paul
^ permalink raw reply [flat|nested] 50+ messages in thread* Re: [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA yaml for MT8196
2025-01-23 16:14 ` Paul-pl Chen (陳柏霖)
@ 2025-01-23 16:20 ` Chen-Yu Tsai
0 siblings, 0 replies; 50+ messages in thread
From: Chen-Yu Tsai @ 2025-01-23 16:20 UTC (permalink / raw)
To: Paul-pl Chen (陳柏霖)
Cc: robh@kernel.org, krzk@kernel.org,
Sunny Shen (沈姍姍),
Sirius Wang (王皓昱),
Nancy Lin (林欣螢), AngeloGioacchino Del Regno,
Xiandong Wang (王先冬),
linux-mediatek@lists.infradead.org,
Project_Global_Chrome_Upstream_Group, conor+dt@kernel.org,
linux-kernel@vger.kernel.org, chunkuang.hu@kernel.org,
devicetree@vger.kernel.org, fshao@chromium.org,
krzk+dt@kernel.org, p.zabel@pengutronix.de,
Singo Chang (張興國),
Jason-JH Lin (林睿祥),
linux-arm-kernel@lists.infradead.org,
dri-devel@lists.freedesktop.org, matthias.bgg@gmail.com,
treapking@chromium.org
On Fri, Jan 24, 2025 at 12:14 AM Paul-pl Chen (陳柏霖)
<Paul-pl.Chen@mediatek.com> wrote:
>
> On Thu, 2025-01-23 at 08:21 +0100, Krzysztof Kozlowski wrote:
> >
> > External email : Please do not click links or open attachments until
> > you have verified the sender or the content.
> >
> >
> > On 23/01/2025 07:11, Paul-pl Chen (陳柏霖) wrote:
> > >
> > > Hi Krzysztof
> > >
> > > I hope this email finds you well. I have a couple of questions
> > > regarding the EXDMA commit patch and decoupling:
> > >
> > > 1. Would removing the example from the EXDMA commit patch be
> > > sufficient
> > > to achieve decoupling for EXDMA YAML and MTK clock/power header?
> >
> > No
> >
> > >
> > > 2. If removing the example from the EXDMA YAML is not allowed, what
> > > alternative changes could we implement to achieve decoupling?
> >
> > Don't use the header constants but just some fake phandle.
> >
> >
> >
> > Best regards,
> > Krzysztof
>
> Hi Krzysztof,
>
> Once again, thanks for the review and reply.
>
> SO If we apply Chenyu's suggestion:
>
> + example:
> +-|
>
> +soc {
> +
> + disp_ovl0_exdma2: dma-controller@32850000 {
> +compatible = "mediatek,mt8196-exdma";
> +reg = <0 0x32850000 0 0x1000>;
> +clocks = <13>;
> +power-domains = <12>;
> +mediatek,larb = <88>;
> +iommus = <&mm_smmu 144>;
> +#dma-cells = <1>;
> + };
> + };
>
> Does this work for decoupling?
>
AFAIK it will since now it isn't including any headers.
ChenYu
> Best Regards,
>
> Paul
>
>
>
>
> ************* MEDIATEK Confidentiality Notice ********************
> The information contained in this e-mail message (including any
> attachments) may be confidential, proprietary, privileged, or otherwise
> exempt from disclosure under applicable laws. It is intended to be
> conveyed only to the designated recipient(s). Any use, dissemination,
> distribution, printing, retaining or copying of this e-mail (including its
> attachments) by unintended recipient(s) is strictly prohibited and may
> be unlawful. If you are not an intended recipient of this e-mail, or believe
> that you have received this e-mail in error, please notify the sender
> immediately (by replying to this e-mail), delete any and all copies of
> this e-mail (including any attachments) from your system, and do not
> disclose the content of this e-mail to any other person. Thank you!
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 04/12] dt-bindings: display: mediatek: add BLENDER yaml for MT8196
2025-01-10 12:33 [PATCH 00/12] Add Mediatek Soc DRM support for mt8196 paul-pl.chen
` (3 preceding siblings ...)
2025-01-10 12:33 ` paul-pl.chen
@ 2025-01-10 12:34 ` paul-pl.chen
2025-01-10 13:54 ` Rob Herring (Arm)
2025-01-10 12:34 ` [PATCH 05/12] dt-bindings: display: mediatek: add OUTPROC " paul-pl.chen
` (8 subsequent siblings)
13 siblings, 1 reply; 50+ messages in thread
From: paul-pl.chen @ 2025-01-10 12:34 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
linux-arm-kernel, Project_Global_Chrome_Upstream_Group
From: "Paul-pl.Chen" <paul-pl.chen@mediatek.com>
Add mediatek,blender.yaml to support BLENDER for MT8196.
Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
---
The header used in examples:
#include <dt-bindings/clock/mt8196-clk.h>
is not upstreamed yet.
It will be sent by related owner soon.
---
.../display/mediatek/mediatek,blender.yaml | 50 +++++++++++++++++++
1 file changed, 50 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..0bcc1a797f71
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,blender.yaml
@@ -0,0 +1,50 @@
+# 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:
+ items:
+ - description: Overlap Blender Clock
+
+required:
+ - compatible
+ - reg
+ - clocks
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/mt8196-clk.h>
+
+ 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 CLK_OVL_BLENDER0_DISP>;
+ };
+ };
--
2.34.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 04/12] dt-bindings: display: mediatek: add BLENDER yaml for MT8196
2025-01-10 12:34 ` [PATCH 04/12] dt-bindings: display: mediatek: add BLENDER " paul-pl.chen
@ 2025-01-10 13:54 ` Rob Herring (Arm)
0 siblings, 0 replies; 50+ messages in thread
From: Rob Herring (Arm) @ 2025-01-10 13:54 UTC (permalink / raw)
To: paul-pl.chen
Cc: p.zabel, Project_Global_Chrome_Upstream_Group, linux-arm-kernel,
xiandong.wang, linux-mediatek, singo.chang, chunkuang.hu,
sirius.wang, matthias.bgg, treapking, angelogioacchino.delregno,
linux-kernel, krzk+dt, sunny.shen, jason-jh.lin, nancy.lin,
dri-devel, fshao, conor+dt, devicetree
On Fri, 10 Jan 2025 20:34:00 +0800, paul-pl.chen wrote:
> From: "Paul-pl.Chen" <paul-pl.chen@mediatek.com>
>
> Add mediatek,blender.yaml to support BLENDER for MT8196.
>
> Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
> ---
> The header used in examples:
> #include <dt-bindings/clock/mt8196-clk.h>
> is not upstreamed yet.
> It will be sent by related owner soon.
> ---
> .../display/mediatek/mediatek,blender.yaml | 50 +++++++++++++++++++
> 1 file changed, 50 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,blender.yaml
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
dtschema/dtc warnings/errors:
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250110123835.2719824-6-paul-pl.chen@mediatek.com
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 05/12] dt-bindings: display: mediatek: add OUTPROC yaml for MT8196
2025-01-10 12:33 [PATCH 00/12] Add Mediatek Soc DRM support for mt8196 paul-pl.chen
` (4 preceding siblings ...)
2025-01-10 12:34 ` [PATCH 04/12] dt-bindings: display: mediatek: add BLENDER " paul-pl.chen
@ 2025-01-10 12:34 ` paul-pl.chen
2025-01-10 13:54 ` Rob Herring (Arm)
2025-01-10 12:34 ` [PATCH 06/12] soc: mediatek: add mmsys support " paul-pl.chen
` (7 subsequent siblings)
13 siblings, 1 reply; 50+ messages in thread
From: paul-pl.chen @ 2025-01-10 12:34 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
linux-arm-kernel, Project_Global_Chrome_Upstream_Group
From: "Paul-pl.Chen" <paul-pl.chen@mediatek.com>
Add mediate,outproc.yaml to support OUTPROC for MT8196.
Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
---
The header used in examples:
#include <dt-bindings/clock/mt8196-clk.h>
is not upstreamed yet.
It will be sent by related owner soon.
---
.../display/mediatek/mediatek,outproc.yaml | 57 +++++++++++++++++++
1 file changed, 57 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..b304ae41420f
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,outproc.yaml
@@ -0,0 +1,57 @@
+# 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:
+ items:
+ - description: Overlap Output Processor Clock
+
+ interrupts:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/mt8196-clk.h>
+ #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 CLK_OVL_OUTPROC0_DISP>;
+ interrupts = <GIC_SPI 450 IRQ_TYPE_LEVEL_HIGH 0>;
+ };
+ };
--
2.34.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 05/12] dt-bindings: display: mediatek: add OUTPROC yaml for MT8196
2025-01-10 12:34 ` [PATCH 05/12] dt-bindings: display: mediatek: add OUTPROC " paul-pl.chen
@ 2025-01-10 13:54 ` Rob Herring (Arm)
0 siblings, 0 replies; 50+ messages in thread
From: Rob Herring (Arm) @ 2025-01-10 13:54 UTC (permalink / raw)
To: paul-pl.chen
Cc: matthias.bgg, nancy.lin, devicetree, singo.chang, conor+dt,
sirius.wang, Project_Global_Chrome_Upstream_Group, krzk+dt,
sunny.shen, chunkuang.hu, linux-mediatek, fshao,
angelogioacchino.delregno, jason-jh.lin, xiandong.wang, dri-devel,
linux-kernel, treapking, p.zabel, linux-arm-kernel
On Fri, 10 Jan 2025 20:34:01 +0800, paul-pl.chen wrote:
> From: "Paul-pl.Chen" <paul-pl.chen@mediatek.com>
>
> Add mediate,outproc.yaml to support OUTPROC for MT8196.
>
> Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
> ---
> The header used in examples:
> #include <dt-bindings/clock/mt8196-clk.h>
> is not upstreamed yet.
>
> It will be sent by related owner soon.
> ---
> .../display/mediatek/mediatek,outproc.yaml | 57 +++++++++++++++++++
> 1 file changed, 57 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,outproc.yaml
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
dtschema/dtc warnings/errors:
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250110123835.2719824-7-paul-pl.chen@mediatek.com
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 06/12] soc: mediatek: add mmsys support for MT8196
2025-01-10 12:33 [PATCH 00/12] Add Mediatek Soc DRM support for mt8196 paul-pl.chen
` (5 preceding siblings ...)
2025-01-10 12:34 ` [PATCH 05/12] dt-bindings: display: mediatek: add OUTPROC " paul-pl.chen
@ 2025-01-10 12:34 ` paul-pl.chen
2025-01-10 12:34 ` [PATCH 07/12] soc: mediatek: mutex: add mutex " paul-pl.chen
` (6 subsequent siblings)
13 siblings, 0 replies; 50+ messages in thread
From: paul-pl.chen @ 2025-01-10 12:34 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
linux-arm-kernel, Project_Global_Chrome_Upstream_Group
From: "Nancy.Lin" <nancy.lin@mediatek.com>
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 | 447 +++++++++++++++++++++++++
drivers/soc/mediatek/mtk-mmsys.c | 204 ++++++++++-
drivers/soc/mediatek/mtk-mmsys.h | 18 +
include/linux/soc/mediatek/mtk-mmsys.h | 60 ++++
4 files changed, 728 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..03d1210d2b80
--- /dev/null
+++ b/drivers/soc/mediatek/mt8196-mmsys.h
@@ -0,0 +1,447 @@
+/* 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 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 DISP_DLI_RELAY_1T2P BIT(30)
+#define MT8196_DISP0_BYPASS_MUX_SHADOW 0xc30
+#define BYPASS_MUX_SHADOW BIT(0)
+#define 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 CPU_INTEN BIT(0)
+#define 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, CPU_INTEN, CPU_INT_MERGE | 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, BYPASS_MUX_SHADOW, BYPASS_MUX_SHADOW},
+ {MT8196_OVLSYS_CB_CON, OVLSYS_CB_BYPASS_MUX_SHADOW, 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, CB_BYPASS_MUX_SHADOW | BYPASS_MUX_SHADOW,
+ CB_BYPASS_MUX_SHADOW | BYPASS_MUX_SHADOW},
+ {MT8196_DISP0_DLI_RELAY0, DISP_DLI_RELAY_1T2P, GENMASK(31, 30)},
+ {MT8196_DISP0_DLI_RELAY1, DISP_DLI_RELAY_1T2P, GENMASK(31, 30)},
+ {MT8196_DISP0_DLI_RELAY8, DISP_DLI_RELAY_1T2P, GENMASK(31, 30)},
+ {MT8196_DISP0_DLO_RELAY1, DISP_DLI_RELAY_1T2P, GENMASK(31, 30)},
+ {MT8196_DISP0_DLO_RELAY2, DISP_DLI_RELAY_1T2P, GENMASK(31, 30)},
+ {MT8196_DISP0_DLO_RELAY3, DISP_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, CB_BYPASS_MUX_SHADOW | BYPASS_MUX_SHADOW,
+ CB_BYPASS_MUX_SHADOW | BYPASS_MUX_SHADOW},
+ {MT8196_DISP1_DLI_RELAY21, DISP_DLI_RELAY_1T2P, GENMASK(31, 30)},
+ {MT8196_DISP1_DLI_RELAY22, DISP_DLI_RELAY_1T2P, GENMASK(31, 30)},
+ {MT8196_DISP1_DLI_RELAY23, DISP_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..9916b23691a5 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_read_bool(dev->of_node, "power-domains"))
+ pm_runtime_enable(dev);
+
out_probe_done:
return 0;
}
@@ -453,6 +646,10 @@ static void mtk_mmsys_remove(struct platform_device *pdev)
platform_device_unregister(mmsys->drm_pdev);
platform_device_unregister(mmsys->clks_pdev);
+
+ if (of_property_read_bool(pdev->dev.of_node, "power-domains"))
+ pm_runtime_disable(&pdev->dev);
+
}
static const struct of_device_id of_match_mtk_mmsys[] = {
@@ -476,6 +673,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 d370192737ca..56f510af4f36 100644
--- a/drivers/soc/mediatek/mtk-mmsys.h
+++ b/drivers/soc/mediatek/mtk-mmsys.h
@@ -88,6 +88,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
@@ -125,6 +138,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.34.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 07/12] soc: mediatek: mutex: add mutex support for MT8196
2025-01-10 12:33 [PATCH 00/12] Add Mediatek Soc DRM support for mt8196 paul-pl.chen
` (6 preceding siblings ...)
2025-01-10 12:34 ` [PATCH 06/12] soc: mediatek: add mmsys support " paul-pl.chen
@ 2025-01-10 12:34 ` paul-pl.chen
2025-01-20 8:04 ` Chen-Yu Tsai
2025-01-10 12:34 ` [PATCH 08/12] drm/mediatek: add EXDMA " paul-pl.chen
` (5 subsequent siblings)
13 siblings, 1 reply; 50+ messages in thread
From: paul-pl.chen @ 2025-01-10 12:34 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
linux-arm-kernel, Project_Global_Chrome_Upstream_Group
From: "Nancy.Lin" <nancy.lin@mediatek.com>
Add mutex support the main and external display for MT8196.
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 | 233 +++++++++++++++++++++++--
include/linux/soc/mediatek/mtk-mutex.h | 2 +
2 files changed, 222 insertions(+), 13 deletions(-)
diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
index 5250c1d702eb..c08eb3cc71eb 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))
@@ -236,6 +237,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
@@ -295,6 +337,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)
@@ -307,6 +355,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;
@@ -323,6 +377,7 @@ enum mtk_mutex_sof_id {
MUTEX_SOF_DSI3,
MUTEX_SOF_DP_INTF0,
MUTEX_SOF_DP_INTF1,
+ MUTEX_SOF_DVO0,
DDP_MUTEX_SOF_MAX,
};
@@ -333,6 +388,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 {
@@ -621,6 +677,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,
@@ -704,6 +818,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,
@@ -797,6 +922,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,
@@ -847,6 +980,53 @@ void mtk_mutex_unprepare(struct mtk_mutex *mutex)
}
EXPORT_SYMBOL_GPL(mtk_mutex_unprepare);
+void mtk_mutex_write_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 sof_id = 0;
+
+ WARN_ON(&mtx->mutex[mutex->id] != mutex);
+
+ switch (id) {
+ case DDP_COMPONENT_DSI0:
+ sof_id = MUTEX_SOF_DSI0;
+ break;
+ case DDP_COMPONENT_DSI1:
+ sof_id = MUTEX_SOF_DSI0;
+ break;
+ case DDP_COMPONENT_DSI2:
+ sof_id = MUTEX_SOF_DSI2;
+ break;
+ case DDP_COMPONENT_DSI3:
+ sof_id = MUTEX_SOF_DSI3;
+ break;
+ case DDP_COMPONENT_DPI0:
+ sof_id = MUTEX_SOF_DPI0;
+ break;
+ case DDP_COMPONENT_DPI1:
+ sof_id = MUTEX_SOF_DPI1;
+ break;
+ case DDP_COMPONENT_DP_INTF0:
+ sof_id = MUTEX_SOF_DP_INTF0;
+ break;
+ case DDP_COMPONENT_DP_INTF1:
+ sof_id = MUTEX_SOF_DP_INTF1;
+ break;
+ case DDP_COMPONENT_DVO0:
+ sof_id = MUTEX_SOF_DVO0;
+ break;
+ default:
+ break;
+ }
+
+ writel_relaxed(mtx->data->mutex_sof[sof_id],
+ mtx->regs +
+ DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, mutex->id));
+}
+EXPORT_SYMBOL_GPL(mtk_mutex_write_comp_sof);
+
void mtk_mutex_add_comp(struct mtk_mutex *mutex,
enum mtk_ddp_comp_id id)
{
@@ -883,6 +1063,9 @@ void mtk_mutex_add_comp(struct mtk_mutex *mutex,
case DDP_COMPONENT_DP_INTF1:
sof_id = MUTEX_SOF_DP_INTF1;
break;
+ case DDP_COMPONENT_DVO0:
+ sof_id = MUTEX_SOF_DVO0;
+ break;
default:
if (mtx->data->mutex_mod[id] < 32) {
offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
@@ -891,7 +1074,8 @@ void mtk_mutex_add_comp(struct mtk_mutex *mutex,
reg |= 1 << mtx->data->mutex_mod[id];
writel_relaxed(reg, mtx->regs + offset);
} else {
- offset = DISP_REG_MUTEX_MOD2(mutex->id);
+ offset = DISP_REG_MUTEX_MOD1(mtx->data->mutex_mod_reg,
+ mutex->id);
reg = readl_relaxed(mtx->regs + offset);
reg |= 1 << (mtx->data->mutex_mod[id] - 32);
writel_relaxed(reg, mtx->regs + offset);
@@ -899,6 +1083,22 @@ void mtk_mutex_add_comp(struct mtk_mutex *mutex,
return;
}
+ if (mtx->data->need_sof_mod) {
+ if (mtx->data->mutex_mod[id] < 32) {
+ offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
+ mutex->id);
+ reg = readl_relaxed(mtx->regs + offset);
+ reg |= 1 << mtx->data->mutex_mod[id];
+ writel_relaxed(reg, mtx->regs + offset);
+ } else {
+ offset = DISP_REG_MUTEX_MOD1(mtx->data->mutex_mod_reg,
+ mutex->id);
+ reg = readl_relaxed(mtx->regs + offset);
+ reg |= 1 << (mtx->data->mutex_mod[id] - 32);
+ writel_relaxed(reg, mtx->regs + offset);
+ }
+ }
+
writel_relaxed(mtx->data->mutex_sof[sof_id],
mtx->regs +
DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, mutex->id));
@@ -924,26 +1124,32 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
case DDP_COMPONENT_DPI1:
case DDP_COMPONENT_DP_INTF0:
case DDP_COMPONENT_DP_INTF1:
+ case DDP_COMPONENT_DVO0:
writel_relaxed(MUTEX_SOF_SINGLE_MODE,
mtx->regs +
DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg,
mutex->id));
break;
default:
- if (mtx->data->mutex_mod[id] < 32) {
- offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
- mutex->id);
- reg = readl_relaxed(mtx->regs + offset);
- reg &= ~(1 << mtx->data->mutex_mod[id]);
- writel_relaxed(reg, mtx->regs + offset);
- } else {
- offset = DISP_REG_MUTEX_MOD2(mutex->id);
- reg = readl_relaxed(mtx->regs + offset);
- reg &= ~(1 << (mtx->data->mutex_mod[id] - 32));
- writel_relaxed(reg, mtx->regs + offset);
- }
break;
}
+
+ if (!mtx->data->need_sof_mod)
+ return;
+
+ if (mtx->data->mutex_mod[id] < 32) {
+ offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
+ mutex->id);
+ reg = readl_relaxed(mtx->regs + offset);
+ reg &= ~(1 << mtx->data->mutex_mod[id]);
+ writel_relaxed(reg, mtx->regs + offset);
+ } else {
+ offset = DISP_REG_MUTEX_MOD1(mtx->data->mutex_mod_reg,
+ mutex->id);
+ reg = readl_relaxed(mtx->regs + offset);
+ reg &= ~(1 << (mtx->data->mutex_mod[id] - 32));
+ writel_relaxed(reg, mtx->regs + offset);
+ }
}
EXPORT_SYMBOL_GPL(mtk_mutex_remove_comp);
@@ -1134,6 +1340,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 */ },
};
diff --git a/include/linux/soc/mediatek/mtk-mutex.h b/include/linux/soc/mediatek/mtk-mutex.h
index 635218e3ac68..c15b48f0e4bf 100644
--- a/include/linux/soc/mediatek/mtk-mutex.h
+++ b/include/linux/soc/mediatek/mtk-mutex.h
@@ -69,6 +69,8 @@ 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_write_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.34.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 07/12] soc: mediatek: mutex: add mutex support for MT8196
2025-01-10 12:34 ` [PATCH 07/12] soc: mediatek: mutex: add mutex " paul-pl.chen
@ 2025-01-20 8:04 ` Chen-Yu Tsai
0 siblings, 0 replies; 50+ messages in thread
From: Chen-Yu Tsai @ 2025-01-20 8:04 UTC (permalink / raw)
To: paul-pl.chen
Cc: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno,
devicetree, xiandong.wang, jason-jh.lin, singo.chang, treapking,
linux-kernel, dri-devel, Project_Global_Chrome_Upstream_Group,
nancy.lin, linux-mediatek, sunny.shen, p.zabel, sirius.wang,
matthias.bgg, linux-arm-kernel
On Fri, Jan 10, 2025 at 8:46 PM paul-pl.chen <paul-pl.chen@mediatek.com> wrote:
>
> From: "Nancy.Lin" <nancy.lin@mediatek.com>
>
> Add mutex support the main and external display for MT8196.
>
> 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 | 233 +++++++++++++++++++++++--
> include/linux/soc/mediatek/mtk-mutex.h | 2 +
> 2 files changed, 222 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
> index 5250c1d702eb..c08eb3cc71eb 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))
> @@ -236,6 +237,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
> @@ -295,6 +337,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)
> @@ -307,6 +355,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;
> @@ -323,6 +377,7 @@ enum mtk_mutex_sof_id {
> MUTEX_SOF_DSI3,
> MUTEX_SOF_DP_INTF0,
> MUTEX_SOF_DP_INTF1,
> + MUTEX_SOF_DVO0,
> DDP_MUTEX_SOF_MAX,
> };
>
> @@ -333,6 +388,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 {
> @@ -621,6 +677,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,
> @@ -704,6 +818,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,
> @@ -797,6 +922,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,
> @@ -847,6 +980,53 @@ void mtk_mutex_unprepare(struct mtk_mutex *mutex)
> }
> EXPORT_SYMBOL_GPL(mtk_mutex_unprepare);
>
> +void mtk_mutex_write_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 sof_id = 0;
> +
> + WARN_ON(&mtx->mutex[mutex->id] != mutex);
> +
> + switch (id) {
> + case DDP_COMPONENT_DSI0:
> + sof_id = MUTEX_SOF_DSI0;
> + break;
> + case DDP_COMPONENT_DSI1:
> + sof_id = MUTEX_SOF_DSI0;
> + break;
> + case DDP_COMPONENT_DSI2:
> + sof_id = MUTEX_SOF_DSI2;
> + break;
> + case DDP_COMPONENT_DSI3:
> + sof_id = MUTEX_SOF_DSI3;
> + break;
> + case DDP_COMPONENT_DPI0:
> + sof_id = MUTEX_SOF_DPI0;
> + break;
> + case DDP_COMPONENT_DPI1:
> + sof_id = MUTEX_SOF_DPI1;
> + break;
> + case DDP_COMPONENT_DP_INTF0:
> + sof_id = MUTEX_SOF_DP_INTF0;
> + break;
> + case DDP_COMPONENT_DP_INTF1:
> + sof_id = MUTEX_SOF_DP_INTF1;
> + break;
> + case DDP_COMPONENT_DVO0:
> + sof_id = MUTEX_SOF_DVO0;
> + break;
> + default:
> + break;
> + }
> +
> + writel_relaxed(mtx->data->mutex_sof[sof_id],
> + mtx->regs +
> + DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, mutex->id));
> +}
> +EXPORT_SYMBOL_GPL(mtk_mutex_write_comp_sof);
This duplicates the code in `mtk_mutex_add_comp()`. If the write to the
MUTEX_SOF register can be reordered to before the MUTEX_MOD* register,
I suggest replacing the existing code in `mtk_mutex_add_comp()` with
a call to this new function. In essence "move the existing SOF code
to a new helper function that is exported".
> void mtk_mutex_add_comp(struct mtk_mutex *mutex,
> enum mtk_ddp_comp_id id)
> {
> @@ -883,6 +1063,9 @@ void mtk_mutex_add_comp(struct mtk_mutex *mutex,
> case DDP_COMPONENT_DP_INTF1:
> sof_id = MUTEX_SOF_DP_INTF1;
> break;
> + case DDP_COMPONENT_DVO0:
> + sof_id = MUTEX_SOF_DVO0;
> + break;
> default:
> if (mtx->data->mutex_mod[id] < 32) {
> offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
> @@ -891,7 +1074,8 @@ void mtk_mutex_add_comp(struct mtk_mutex *mutex,
> reg |= 1 << mtx->data->mutex_mod[id];
> writel_relaxed(reg, mtx->regs + offset);
> } else {
> - offset = DISP_REG_MUTEX_MOD2(mutex->id);
> + offset = DISP_REG_MUTEX_MOD1(mtx->data->mutex_mod_reg,
> + mutex->id);
This needs to be a separate patch replacing MOD2 with MOD1, and
explain why this doesn't break existing platforms:
On existing platforms with mutex IDs larger than 32 (MT8188 and
MT8195), MOD2 == MOD + 0x4 == MOD1.
And the MOD2 macro should be removed in the same patch to avoid misuse
in the future.
> reg = readl_relaxed(mtx->regs + offset);
> reg |= 1 << (mtx->data->mutex_mod[id] - 32);
> writel_relaxed(reg, mtx->regs + offset);
> @@ -899,6 +1083,22 @@ void mtk_mutex_add_comp(struct mtk_mutex *mutex,
> return;
> }
>
> + if (mtx->data->need_sof_mod) {
> + if (mtx->data->mutex_mod[id] < 32) {
> + offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
> + mutex->id);
> + reg = readl_relaxed(mtx->regs + offset);
> + reg |= 1 << mtx->data->mutex_mod[id];
> + writel_relaxed(reg, mtx->regs + offset);
> + } else {
> + offset = DISP_REG_MUTEX_MOD1(mtx->data->mutex_mod_reg,
> + mutex->id);
> + reg = readl_relaxed(mtx->regs + offset);
> + reg |= 1 << (mtx->data->mutex_mod[id] - 32);
> + writel_relaxed(reg, mtx->regs + offset);
> + }
> + }
> +
This directly duplicates the block above. Something is wrong here.
> writel_relaxed(mtx->data->mutex_sof[sof_id],
> mtx->regs +
> DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, mutex->id));
> @@ -924,26 +1124,32 @@ void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
> case DDP_COMPONENT_DPI1:
> case DDP_COMPONENT_DP_INTF0:
> case DDP_COMPONENT_DP_INTF1:
> + case DDP_COMPONENT_DVO0:
> writel_relaxed(MUTEX_SOF_SINGLE_MODE,
> mtx->regs +
> DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg,
> mutex->id));
> break;
> default:
> - if (mtx->data->mutex_mod[id] < 32) {
> - offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
> - mutex->id);
> - reg = readl_relaxed(mtx->regs + offset);
> - reg &= ~(1 << mtx->data->mutex_mod[id]);
> - writel_relaxed(reg, mtx->regs + offset);
> - } else {
> - offset = DISP_REG_MUTEX_MOD2(mutex->id);
> - reg = readl_relaxed(mtx->regs + offset);
> - reg &= ~(1 << (mtx->data->mutex_mod[id] - 32));
> - writel_relaxed(reg, mtx->regs + offset);
> - }
> break;
> }
> +
> + if (!mtx->data->need_sof_mod)
> + return;
> +
> + if (mtx->data->mutex_mod[id] < 32) {
> + offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
> + mutex->id);
> + reg = readl_relaxed(mtx->regs + offset);
> + reg &= ~(1 << mtx->data->mutex_mod[id]);
> + writel_relaxed(reg, mtx->regs + offset);
> + } else {
> + offset = DISP_REG_MUTEX_MOD1(mtx->data->mutex_mod_reg,
> + mutex->id);
> + reg = readl_relaxed(mtx->regs + offset);
> + reg &= ~(1 << (mtx->data->mutex_mod[id] - 32));
> + writel_relaxed(reg, mtx->regs + offset);
> + }
Why is it OK to move this block, especially now that it has an early
return condition above? The add and remove paths not being the inverse
of each other seems suspect to me.
ChenYu
> }
> EXPORT_SYMBOL_GPL(mtk_mutex_remove_comp);
>
> @@ -1134,6 +1340,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 */ },
> };
> diff --git a/include/linux/soc/mediatek/mtk-mutex.h b/include/linux/soc/mediatek/mtk-mutex.h
> index 635218e3ac68..c15b48f0e4bf 100644
> --- a/include/linux/soc/mediatek/mtk-mutex.h
> +++ b/include/linux/soc/mediatek/mtk-mutex.h
> @@ -69,6 +69,8 @@ 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_write_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.34.1
>
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 08/12] drm/mediatek: add EXDMA support for MT8196
2025-01-10 12:33 [PATCH 00/12] Add Mediatek Soc DRM support for mt8196 paul-pl.chen
` (7 preceding siblings ...)
2025-01-10 12:34 ` [PATCH 07/12] soc: mediatek: mutex: add mutex " paul-pl.chen
@ 2025-01-10 12:34 ` paul-pl.chen
2025-01-16 1:45 ` CK Hu (胡俊光)
2025-01-20 9:54 ` Chen-Yu Tsai
2025-01-10 12:34 ` [PATCH 09/12] drm/mediatek: add BLENDER " paul-pl.chen
` (4 subsequent siblings)
13 siblings, 2 replies; 50+ messages in thread
From: paul-pl.chen @ 2025-01-10 12:34 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
linux-arm-kernel, Project_Global_Chrome_Upstream_Group
From: "Nancy.Lin" <nancy.lin@mediatek.com>
EXDMA is a DMA engine for reading data from DRAM with
various DRAM footprints and data formats. For input
sources in certain color formats and color domains,
EXDMA also includes a color transfer function to
process pixels into a consistent color domain.
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 | 447 ++++++++++++++++++++++
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 +
drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 +
7 files changed, 461 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..f8291651dc80 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_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..e1d7bda22972
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_exdma.c
@@ -0,0 +1,447 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021 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"
+
+#define DISP_REG_OVL_EN_CON 0xc
+#define OVL_OP_8BIT_MODE BIT(4)
+#define OVL_HG_FOVL_CK_ON BIT(8)
+#define OVL_HF_FOVL_CK_ON BIT(10)
+#define DISP_REG_OVL_DATAPATH_CON 0x014
+#define DATAPATH_CON_LAYER_SMI_ID_EN BIT(0)
+#define DATAPATH_CON_GCLAST_EN BIT(24)
+#define DATAPATH_CON_HDR_GCLAST_EN BIT(25)
+#define DISP_REG_OVL_EN 0x020
+#define DISP_OVL_EN BIT(0)
+#define DISP_REG_OVL_RST 0x024
+#define DISP_OVL_RST BIT(0)
+#define DISP_REG_OVL_ROI_SIZE 0x030
+#define DISP_REG_OVL_L0_EN 0x040
+#define DISP_OVL_L0_EN BIT(0)
+#define DISP_REG_OVL_OFFSET 0x044
+#define DISP_REG_OVL_SRC_SIZE 0x048
+#define DISP_REG_OVL_L0_CLRFMT 0x050
+#define OVL_CON_FLD_CLRFMT GENMASK(3, 0)
+#define OVL_CON_CLRFMT_MAN BIT(4)
+#define OVL_CON_FLD_CLRFMT_NB GENMASK(9, 8)
+#define OVL_CON_CLRFMT_NB_10_BIT BIT(8)
+#define OVL_CON_BYTE_SWAP BIT(16)
+#define OVL_CON_RGB_SWAP BIT(17)
+#define OVL_CON_CLRFMT_RGB565 0x000
+#define OVL_CON_CLRFMT_BGR888 0x001
+#define OVL_CON_CLRFMT_BGRA8888 0x002
+#define OVL_CON_CLRFMT_ABGRB8888 0x003
+#define OVL_CON_CLRFMT_UYVY 0x004
+#define OVL_CON_CLRFMT_YUYV 0x005
+#define OVL_CON_CLRFMT_BGR565 (0x000 | OVL_CON_BYTE_SWAP)
+#define OVL_CON_CLRFMT_RGB888 (0x001 | OVL_CON_BYTE_SWAP)
+#define OVL_CON_CLRFMT_RGBA8888 (0x002 | OVL_CON_BYTE_SWAP)
+#define OVL_CON_CLRFMT_ARGB8888 (0x003 | OVL_CON_BYTE_SWAP)
+#define OVL_CON_CLRFMT_VYUY (0x004 | OVL_CON_BYTE_SWAP)
+#define OVL_CON_CLRFMT_YVYU (0x005 | OVL_CON_BYTE_SWAP)
+#define OVL_CON_CLRFMT_PBGRA8888 (0x003 | OVL_CON_CLRFMT_MAN)
+#define OVL_CON_CLRFMT_PARGB8888 (OVL_CON_CLRFMT_PBGRA8888 | \
+ OVL_CON_BYTE_SWAP)
+#define OVL_CON_CLRFMT_PRGBA8888 (OVL_CON_CLRFMT_PBGRA8888 | \
+ OVL_CON_RGB_SWAP)
+#define OVL_CON_CLRFMT_PABGR8888 (OVL_CON_CLRFMT_PBGRA8888 | \
+ OVL_CON_RGB_SWAP | \
+ OVL_CON_BYTE_SWAP)
+#define DISP_REG_OVL_RDMA0_CTRL 0x100
+#define DISP_RDMA0_EN BIT(0)
+#define DISP_REG_OVL_RDMA_BURST_CON1 0x1f4
+#define DISP_RDMA_BURST_CON1_BURST16_EN BIT(28)
+#define DISP_RDMA_BURST_CON1_DDR_EN BIT(30)
+#define DISP_RDMA_BURST_CON1_DDR_ACK_EN BIT(31)
+#define DISP_REG_OVL_DUMMY_REG 0x200
+#define DISP_OVL_EXT_DDR_EN_OPT BIT(2)
+#define DISP_OVL_FORCE_EXT_DDR_EN BIT(3)
+#define DISP_REG_OVL_GDRDY_PRD 0x208
+#define DISP_REG_OVL_PITCH_MSB 0x2f0
+#define DISP_REG_OVL_PITCH 0x2f4
+#define OVL_L0_SRC_PITCH GENMASK(15, 0)
+#define OVL_L0_CONST_BLD BIT(28)
+#define OVL_L0_SRC_PITCH_MASK GENMASK(15, 0)
+#define DISP_REG_OVL_L0_GUSER_EXT 0x2fc
+#define OVL_RDMA0_L0_VCSEL BIT(5)
+#define OVL_RDMA0_HDR_L0_VCSEL BIT(21)
+#define DISP_REG_OVL_CON 0x300
+#define DISP_OVL_CON_FLD_INT_MTX_SEL GENMASK(19, 16)
+#define DISP_OVL_CON_INT_MTX_BT601_TO_RGB (6 << 16)
+#define DISP_OVL_CON_INT_MTX_BT709_TO_RGB (7 << 16)
+#define DISP_OVL_CON_INT_MTX_EN BIT(27)
+#define DISP_REG_OVL_ADDR 0xf40
+#define DISP_REG_OVL_MOUT 0xff0
+#define OVL_MOUT_OUT_DATA BIT(0)
+#define OVL_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_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 inline bool is_10bit_rgb(u32 fmt)
+{
+ switch (fmt) {
+ case DRM_FORMAT_XRGB2101010:
+ case DRM_FORMAT_ARGB2101010:
+ case DRM_FORMAT_RGBX1010102:
+ case DRM_FORMAT_RGBA1010102:
+ case DRM_FORMAT_XBGR2101010:
+ case DRM_FORMAT_ABGR2101010:
+ case DRM_FORMAT_BGRX1010102:
+ case DRM_FORMAT_BGRA1010102:
+ return true;
+ }
+ return false;
+}
+
+static unsigned int mtk_disp_exdma_fmt_convert(unsigned int fmt, unsigned int blend_mode)
+{
+ /*
+ * DRM_FORMAT: bit 32->0, OVL_FMT: bit 0->32,
+ * so DRM_FORMAT_RGB888 = OVL_CON_CLRFMT_BGR888
+ */
+ switch (fmt) {
+ default:
+ case DRM_FORMAT_BGR565:
+ return OVL_CON_CLRFMT_RGB565;
+ case DRM_FORMAT_RGB565:
+ return OVL_CON_CLRFMT_BGR565;
+ case DRM_FORMAT_RGB888:
+ return OVL_CON_CLRFMT_BGR888;
+ case DRM_FORMAT_BGR888:
+ return OVL_CON_CLRFMT_RGB888;
+ case DRM_FORMAT_RGBX8888:
+ case DRM_FORMAT_RGBA8888:
+ case DRM_FORMAT_RGBA1010102:
+ case DRM_FORMAT_RGBX1010102:
+ return ((blend_mode == DRM_MODE_BLEND_PREMULTI) ?
+ OVL_CON_CLRFMT_PABGR8888 : OVL_CON_CLRFMT_ABGRB8888) |
+ (is_10bit_rgb(fmt) ? OVL_CON_CLRFMT_NB_10_BIT : 0);
+ case DRM_FORMAT_BGRX8888:
+ case DRM_FORMAT_BGRA8888:
+ case DRM_FORMAT_BGRA1010102:
+ case DRM_FORMAT_BGRX1010102:
+ return ((blend_mode == DRM_MODE_BLEND_PREMULTI) ?
+ OVL_CON_CLRFMT_PARGB8888 : OVL_CON_CLRFMT_ARGB8888) |
+ (is_10bit_rgb(fmt) ? OVL_CON_CLRFMT_NB_10_BIT : 0);
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_ARGB2101010:
+ case DRM_FORMAT_XRGB2101010:
+ return ((blend_mode == DRM_MODE_BLEND_PREMULTI) ?
+ OVL_CON_CLRFMT_PBGRA8888 : OVL_CON_CLRFMT_BGRA8888) |
+ (is_10bit_rgb(fmt) ? OVL_CON_CLRFMT_NB_10_BIT : 0);
+ case DRM_FORMAT_XBGR8888:
+ case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_ABGR2101010:
+ case DRM_FORMAT_XBGR2101010:
+ return ((blend_mode == DRM_MODE_BLEND_PREMULTI) ?
+ OVL_CON_CLRFMT_PRGBA8888 : OVL_CON_CLRFMT_RGBA8888) |
+ (is_10bit_rgb(fmt) ? OVL_CON_CLRFMT_NB_10_BIT : 0);
+ case DRM_FORMAT_UYVY:
+ return OVL_CON_CLRFMT_UYVY;
+ case DRM_FORMAT_YUYV:
+ return OVL_CON_CLRFMT_YUYV;
+ }
+}
+
+static unsigned int exdma_color_convert(unsigned int color_encoding)
+{
+ switch (color_encoding) {
+ default:
+ case DRM_COLOR_YCBCR_BT709:
+ return DISP_OVL_CON_INT_MTX_BT709_TO_RGB;
+ case DRM_COLOR_YCBCR_BT601:
+ return DISP_OVL_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 = DISP_RDMA_BURST_CON1_BURST16_EN | DISP_RDMA_BURST_CON1_DDR_ACK_EN;
+ mask = DISP_RDMA_BURST_CON1_BURST16_EN | DISP_RDMA_BURST_CON1_DDR_EN |
+ DISP_RDMA_BURST_CON1_DDR_ACK_EN;
+ mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_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 = DISP_OVL_EXT_DDR_EN_OPT | DISP_OVL_FORCE_EXT_DDR_EN;
+ mask = DISP_OVL_EXT_DDR_EN_OPT | DISP_OVL_FORCE_EXT_DDR_EN;
+ mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_DUMMY_REG, mask);
+
+ value = DATAPATH_CON_LAYER_SMI_ID_EN | DATAPATH_CON_HDR_GCLAST_EN | DATAPATH_CON_GCLAST_EN;
+ mask = DATAPATH_CON_LAYER_SMI_ID_EN | DATAPATH_CON_HDR_GCLAST_EN | DATAPATH_CON_GCLAST_EN;
+ mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_DATAPATH_CON, mask);
+
+ mtk_ddp_write_mask(cmdq_pkt, OVL_MOUT_BGCLR_OUT, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_MOUT, OVL_MOUT_BGCLR_OUT | OVL_MOUT_OUT_DATA);
+
+ mtk_ddp_write(cmdq_pkt, ~0, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_GDRDY_PRD);
+
+ mtk_ddp_write_mask(cmdq_pkt, DISP_RDMA0_EN, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_RDMA0_CTRL, DISP_RDMA0_EN);
+ mtk_ddp_write_mask(cmdq_pkt, DISP_OVL_L0_EN, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_L0_EN, DISP_OVL_L0_EN);
+
+ mtk_ddp_write_mask(cmdq_pkt, DISP_OVL_EN, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_EN, DISP_OVL_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_EN, DISP_OVL_EN);
+ mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_RDMA0_CTRL, DISP_RDMA0_EN);
+ mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_DATAPATH_CON, DATAPATH_CON_LAYER_SMI_ID_EN);
+ mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_L0_EN, DISP_OVL_L0_EN);
+ mtk_ddp_write_mask(cmdq_pkt, DISP_OVL_RST, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_RST, DISP_OVL_RST);
+ mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_RST, DISP_OVL_RST);
+}
+
+void mtk_disp_exdma_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->is_yuv ? true : false;
+ unsigned int blend_mode = DRM_MODE_BLEND_PIXEL_NONE;
+ unsigned int clrfmt = 0;
+ unsigned int clrfmt_mask = OVL_CON_RGB_SWAP |
+ OVL_CON_BYTE_SWAP |
+ OVL_CON_CLRFMT_MAN |
+ OVL_CON_FLD_CLRFMT |
+ OVL_CON_FLD_CLRFMT_NB;
+
+ /* 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_ROI_SIZE);
+
+ mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
+ priv->regs, DISP_REG_OVL_SRC_SIZE);
+ mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
+ priv->regs, DISP_REG_OVL_SRC_SIZE);
+ mtk_ddp_write(cmdq_pkt, pending->addr, &priv->cmdq_reg,
+ priv->regs, DISP_REG_OVL_ADDR);
+ mtk_ddp_write_mask(cmdq_pkt, pending->pitch, &priv->cmdq_reg, priv->regs, OVL_L0_SRC_PITCH,
+ OVL_L0_SRC_PITCH_MASK);
+ mtk_ddp_write_mask(cmdq_pkt, pending->pitch >> 16, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_PITCH_MSB, 0xf);
+
+ if (csc_enable)
+ mtk_ddp_write_mask(cmdq_pkt, exdma_color_convert(pending->color_encoding) |
+ DISP_OVL_CON_INT_MTX_EN, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_CON, DISP_OVL_CON_FLD_INT_MTX_SEL |
+ DISP_OVL_CON_INT_MTX_EN);
+ else
+ mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_CON,
+ DISP_OVL_CON_INT_MTX_EN);
+
+ /* alpha blend setting */
+ if (state->base.fb && state->base.fb->format->has_alpha)
+ blend_mode = state->base.pixel_blend_mode;
+
+ clrfmt = mtk_disp_exdma_fmt_convert(pending->format, blend_mode);
+
+ mtk_ddp_write_mask(cmdq_pkt, clrfmt, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_L0_CLRFMT, clrfmt_mask);
+
+ mtk_ddp_write_mask(cmdq_pkt, OVL_OP_8BIT_MODE | OVL_HG_FOVL_CK_ON | OVL_HF_FOVL_CK_ON,
+ &priv->cmdq_reg, priv->regs, DISP_REG_OVL_EN_CON,
+ OVL_OP_8BIT_MODE | OVL_HG_FOVL_CK_ON | OVL_HF_FOVL_CK_ON);
+
+ mtk_ddp_write_mask(cmdq_pkt, OVL_RDMA0_L0_VCSEL | OVL_RDMA0_HDR_L0_VCSEL,
+ &priv->cmdq_reg, priv->regs, DISP_REG_OVL_L0_GUSER_EXT,
+ OVL_RDMA0_L0_VCSEL | OVL_RDMA0_HDR_L0_VCSEL);
+
+ if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE) {
+ mtk_ddp_write_mask(cmdq_pkt, OVL_L0_CONST_BLD | pending->pitch,
+ &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_PITCH, OVL_L0_CONST_BLD | OVL_L0_SRC_PITCH);
+ } else {
+ mtk_ddp_write_mask(cmdq_pkt, pending->pitch, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_PITCH, OVL_L0_CONST_BLD | OVL_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 8c8da188df09..ccbf46d0707a 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -1261,6 +1261,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.34.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 08/12] drm/mediatek: add EXDMA support for MT8196
2025-01-10 12:34 ` [PATCH 08/12] drm/mediatek: add EXDMA " paul-pl.chen
@ 2025-01-16 1:45 ` CK Hu (胡俊光)
2025-01-20 9:54 ` Chen-Yu Tsai
1 sibling, 0 replies; 50+ messages in thread
From: CK Hu (胡俊光) @ 2025-01-16 1: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: matthias.bgg@gmail.com, treapking@chromium.org,
Singo Chang (張興國),
Project_Global_Chrome_Upstream_Group,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
Jason-JH Lin (林睿祥),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
linux-mediatek@lists.infradead.org,
Sunny Shen (沈姍姍), p.zabel@pengutronix.de,
Sirius Wang (王皓昱),
linux-arm-kernel@lists.infradead.org
Hi, Paul:
On Fri, 2025-01-10 at 20:34 +0800,paul-pl.chen wrote:
>
> > From: "Nancy.Lin" <nancy.lin@mediatek.com>
>
> >
>
> > EXDMA is a DMA engine for reading data from DRAM with
>
> > various DRAM footprints and data formats. For input
>
> > sources in certain color formats and color domains,
>
> > EXDMA also includes a color transfer function to
>
> > process pixels into a consistent color domain.
>
> >
>
> > Signed-off-by: Nancy.Lin <nancy.lin@mediatek.com>
>
> > Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
>
> > ---
>
>
>
> [snip]
>
>
>
> > +#define DISP_REG_OVL_L0_CLRFMT 0x050
>
> > +#define OVL_CON_FLD_CLRFMT GENMASK(3, 0)
>
> > +#define OVL_CON_CLRFMT_MAN BIT(4)
>
> > +#define OVL_CON_FLD_CLRFMT_NB GENMASK(9, 8)
>
> > +#define OVL_CON_CLRFMT_NB_10_BIT BIT(8)
>
> > +#define OVL_CON_BYTE_SWAP BIT(16)
>
> > +#define OVL_CON_RGB_SWAP BIT(17)
>
> > +#define OVL_CON_CLRFMT_RGB565 0x000
>
> > +#define OVL_CON_CLRFMT_BGR888 0x001
>
> > +#define OVL_CON_CLRFMT_BGRA8888 0x002
>
> > +#define OVL_CON_CLRFMT_ABGRB8888 0x003
>
> > +#define OVL_CON_CLRFMT_UYVY 0x004
>
> > +#define OVL_CON_CLRFMT_YUYV 0x005
>
> > +#define OVL_CON_CLRFMT_BGR565 (0x000 | OVL_CON_BYTE_SWAP)
>
> > +#define OVL_CON_CLRFMT_RGB888 (0x001 | OVL_CON_BYTE_SWAP)
>
> > +#define OVL_CON_CLRFMT_RGBA8888 (0x002 | OVL_CON_BYTE_SWAP)
>
> > +#define OVL_CON_CLRFMT_ARGB8888 (0x003 | OVL_CON_BYTE_SWAP)
>
> > +#define OVL_CON_CLRFMT_VYUY (0x004 | OVL_CON_BYTE_SWAP)
>
> > +#define OVL_CON_CLRFMT_YVYU (0x005 | OVL_CON_BYTE_SWAP)
>
> > +#define OVL_CON_CLRFMT_PBGRA8888 (0x003 | OVL_CON_CLRFMT_MAN)
>
> > +#define OVL_CON_CLRFMT_PARGB8888 (OVL_CON_CLRFMT_PBGRA8888 | \
>
> > + OVL_CON_BYTE_SWAP)
>
> > +#define OVL_CON_CLRFMT_PRGBA8888 (OVL_CON_CLRFMT_PBGRA8888 | \
>
> > + OVL_CON_RGB_SWAP)
>
> > +#define OVL_CON_CLRFMT_PABGR8888 (OVL_CON_CLRFMT_PBGRA8888 | \
>
> > + OVL_CON_RGB_SWAP | \
>
> > + OVL_CON_BYTE_SWAP)
>
>
>
> The color format definition is identical with ovl driver. Try to merge them.
>
>
>
> > +#define DISP_REG_OVL_RDMA0_CTRL 0x100
>
> > +#define DISP_RDMA0_EN BIT(0)
>
> > +#define DISP_REG_OVL_RDMA_BURST_CON1 0x1f4
>
> > +#define DISP_RDMA_BURST_CON1_BURST16_EN BIT(28)
>
> > +#define DISP_RDMA_BURST_CON1_DDR_EN BIT(30)
>
> > +#define DISP_RDMA_BURST_CON1_DDR_ACK_EN BIT(31)
>
> > +#define DISP_REG_OVL_DUMMY_REG 0x200
>
> > +#define DISP_OVL_EXT_DDR_EN_OPT BIT(2)
>
> > +#define DISP_OVL_FORCE_EXT_DDR_EN BIT(3)
>
> > +#define DISP_REG_OVL_GDRDY_PRD 0x208
>
>
>
> [snip]
>
>
>
> > +
>
> > +static const u32 formats[] = {
>
>
>
> This array is identical with mt8195_formats[], try to merge them.
>
>
>
> > + 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_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,
>
> > +};
>
> > +
>
>
>
> [snip]
>
>
>
> > +
>
> > +static unsigned int mtk_disp_exdma_fmt_convert(unsigned int fmt, unsigned int blend_mode)
>
>
>
> This function is almost the same as mtk_ovl_fmt_convert(), try to merge them.
>
>
>
> Regards,
>
> CK
>
>
>
> > +{
>
> > + /*
>
> > + * DRM_FORMAT: bit 32->0, OVL_FMT: bit 0->32,
>
> > + * so DRM_FORMAT_RGB888 = OVL_CON_CLRFMT_BGR888
>
> > + */
>
> > + switch (fmt) {
>
> > + default:
>
> > + case DRM_FORMAT_BGR565:
>
> > + return OVL_CON_CLRFMT_RGB565;
>
> > + case DRM_FORMAT_RGB565:
>
> > + return OVL_CON_CLRFMT_BGR565;
>
> > + case DRM_FORMAT_RGB888:
>
> > + return OVL_CON_CLRFMT_BGR888;
>
> > + case DRM_FORMAT_BGR888:
>
> > + return OVL_CON_CLRFMT_RGB888;
>
> > + case DRM_FORMAT_RGBX8888:
>
> > + case DRM_FORMAT_RGBA8888:
>
> > + case DRM_FORMAT_RGBA1010102:
>
> > + case DRM_FORMAT_RGBX1010102:
>
> > + return ((blend_mode == DRM_MODE_BLEND_PREMULTI) ?
>
> > + OVL_CON_CLRFMT_PABGR8888 : OVL_CON_CLRFMT_ABGRB8888) |
>
> > + (is_10bit_rgb(fmt) ? OVL_CON_CLRFMT_NB_10_BIT : 0);
>
> > + case DRM_FORMAT_BGRX8888:
>
> > + case DRM_FORMAT_BGRA8888:
>
> > + case DRM_FORMAT_BGRA1010102:
>
> > + case DRM_FORMAT_BGRX1010102:
>
> > + return ((blend_mode == DRM_MODE_BLEND_PREMULTI) ?
>
> > + OVL_CON_CLRFMT_PARGB8888 : OVL_CON_CLRFMT_ARGB8888) |
>
> > + (is_10bit_rgb(fmt) ? OVL_CON_CLRFMT_NB_10_BIT : 0);
>
> > + case DRM_FORMAT_XRGB8888:
>
> > + case DRM_FORMAT_ARGB8888:
>
> > + case DRM_FORMAT_ARGB2101010:
>
> > + case DRM_FORMAT_XRGB2101010:
>
> > + return ((blend_mode == DRM_MODE_BLEND_PREMULTI) ?
>
> > + OVL_CON_CLRFMT_PBGRA8888 : OVL_CON_CLRFMT_BGRA8888) |
>
> > + (is_10bit_rgb(fmt) ? OVL_CON_CLRFMT_NB_10_BIT : 0);
>
> > + case DRM_FORMAT_XBGR8888:
>
> > + case DRM_FORMAT_ABGR8888:
>
> > + case DRM_FORMAT_ABGR2101010:
>
> > + case DRM_FORMAT_XBGR2101010:
>
> > + return ((blend_mode == DRM_MODE_BLEND_PREMULTI) ?
>
> > + OVL_CON_CLRFMT_PRGBA8888 : OVL_CON_CLRFMT_RGBA8888) |
>
> > + (is_10bit_rgb(fmt) ? OVL_CON_CLRFMT_NB_10_BIT : 0);
>
> > + case DRM_FORMAT_UYVY:
>
> > + return OVL_CON_CLRFMT_UYVY;
>
> > + case DRM_FORMAT_YUYV:
>
> > + return OVL_CON_CLRFMT_YUYV;
>
> > + }
>
> > +}
>
> > +
>
^ permalink raw reply [flat|nested] 50+ messages in thread* Re: [PATCH 08/12] drm/mediatek: add EXDMA support for MT8196
2025-01-10 12:34 ` [PATCH 08/12] drm/mediatek: add EXDMA " paul-pl.chen
2025-01-16 1:45 ` CK Hu (胡俊光)
@ 2025-01-20 9:54 ` Chen-Yu Tsai
1 sibling, 0 replies; 50+ messages in thread
From: Chen-Yu Tsai @ 2025-01-20 9:54 UTC (permalink / raw)
To: paul-pl.chen
Cc: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno,
devicetree, xiandong.wang, jason-jh.lin, singo.chang, treapking,
linux-kernel, dri-devel, Project_Global_Chrome_Upstream_Group,
nancy.lin, linux-mediatek, sunny.shen, p.zabel, sirius.wang,
matthias.bgg, linux-arm-kernel
On Fri, Jan 10, 2025 at 8:54 PM paul-pl.chen <paul-pl.chen@mediatek.com> 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.
>
> 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 | 447 ++++++++++++++++++++++
> drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 +
> drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 +
> 7 files changed, 461 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..f8291651dc80 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_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..e1d7bda22972
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_exdma.c
> @@ -0,0 +1,447 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2021 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"
> +
> +#define DISP_REG_OVL_EN_CON 0xc
> +#define OVL_OP_8BIT_MODE BIT(4)
> +#define OVL_HG_FOVL_CK_ON BIT(8)
> +#define OVL_HF_FOVL_CK_ON BIT(10)
> +#define DISP_REG_OVL_DATAPATH_CON 0x014
> +#define DATAPATH_CON_LAYER_SMI_ID_EN BIT(0)
> +#define DATAPATH_CON_GCLAST_EN BIT(24)
> +#define DATAPATH_CON_HDR_GCLAST_EN BIT(25)
> +#define DISP_REG_OVL_EN 0x020
> +#define DISP_OVL_EN BIT(0)
> +#define DISP_REG_OVL_RST 0x024
> +#define DISP_OVL_RST BIT(0)
> +#define DISP_REG_OVL_ROI_SIZE 0x030
> +#define DISP_REG_OVL_L0_EN 0x040
> +#define DISP_OVL_L0_EN BIT(0)
> +#define DISP_REG_OVL_OFFSET 0x044
> +#define DISP_REG_OVL_SRC_SIZE 0x048
> +#define DISP_REG_OVL_L0_CLRFMT 0x050
> +#define OVL_CON_FLD_CLRFMT GENMASK(3, 0)
> +#define OVL_CON_CLRFMT_MAN BIT(4)
> +#define OVL_CON_FLD_CLRFMT_NB GENMASK(9, 8)
> +#define OVL_CON_CLRFMT_NB_10_BIT BIT(8)
> +#define OVL_CON_BYTE_SWAP BIT(16)
> +#define OVL_CON_RGB_SWAP BIT(17)
> +#define OVL_CON_CLRFMT_RGB565 0x000
> +#define OVL_CON_CLRFMT_BGR888 0x001
> +#define OVL_CON_CLRFMT_BGRA8888 0x002
> +#define OVL_CON_CLRFMT_ABGRB8888 0x003
Typo? Should probably be OVL_CON_CLRFMT_ABGR8888.
> +#define OVL_CON_CLRFMT_UYVY 0x004
> +#define OVL_CON_CLRFMT_YUYV 0x005
> +#define OVL_CON_CLRFMT_BGR565 (0x000 | OVL_CON_BYTE_SWAP)
> +#define OVL_CON_CLRFMT_RGB888 (0x001 | OVL_CON_BYTE_SWAP)
> +#define OVL_CON_CLRFMT_RGBA8888 (0x002 | OVL_CON_BYTE_SWAP)
> +#define OVL_CON_CLRFMT_ARGB8888 (0x003 | OVL_CON_BYTE_SWAP)
> +#define OVL_CON_CLRFMT_VYUY (0x004 | OVL_CON_BYTE_SWAP)
> +#define OVL_CON_CLRFMT_YVYU (0x005 | OVL_CON_BYTE_SWAP)
Please use the OVL_CON_CLRFMT_* macros from above in place of the raw 0x???
values. This helps contrast what the byte swap is.
> +#define OVL_CON_CLRFMT_PBGRA8888 (0x003 | OVL_CON_CLRFMT_MAN)
> +#define OVL_CON_CLRFMT_PARGB8888 (OVL_CON_CLRFMT_PBGRA8888 | \
> + OVL_CON_BYTE_SWAP)
> +#define OVL_CON_CLRFMT_PRGBA8888 (OVL_CON_CLRFMT_PBGRA8888 | \
> + OVL_CON_RGB_SWAP)
> +#define OVL_CON_CLRFMT_PABGR8888 (OVL_CON_CLRFMT_PBGRA8888 | \
> + OVL_CON_RGB_SWAP | \
> + OVL_CON_BYTE_SWAP)
Can you stick to using one existing macro plus OR-ing just one flag?
Existing code in drivers/gpu/drm/mediatek/mtk_disp_ovl.c does that.
> +#define DISP_REG_OVL_RDMA0_CTRL 0x100
> +#define DISP_RDMA0_EN BIT(0)
> +#define DISP_REG_OVL_RDMA_BURST_CON1 0x1f4
> +#define DISP_RDMA_BURST_CON1_BURST16_EN BIT(28)
> +#define DISP_RDMA_BURST_CON1_DDR_EN BIT(30)
> +#define DISP_RDMA_BURST_CON1_DDR_ACK_EN BIT(31)
> +#define DISP_REG_OVL_DUMMY_REG 0x200
> +#define DISP_OVL_EXT_DDR_EN_OPT BIT(2)
> +#define DISP_OVL_FORCE_EXT_DDR_EN BIT(3)
> +#define DISP_REG_OVL_GDRDY_PRD 0x208
> +#define DISP_REG_OVL_PITCH_MSB 0x2f0
> +#define DISP_REG_OVL_PITCH 0x2f4
> +#define OVL_L0_SRC_PITCH GENMASK(15, 0)
> +#define OVL_L0_CONST_BLD BIT(28)
> +#define OVL_L0_SRC_PITCH_MASK GENMASK(15, 0)
> +#define DISP_REG_OVL_L0_GUSER_EXT 0x2fc
> +#define OVL_RDMA0_L0_VCSEL BIT(5)
> +#define OVL_RDMA0_HDR_L0_VCSEL BIT(21)
> +#define DISP_REG_OVL_CON 0x300
> +#define DISP_OVL_CON_FLD_INT_MTX_SEL GENMASK(19, 16)
> +#define DISP_OVL_CON_INT_MTX_BT601_TO_RGB (6 << 16)
> +#define DISP_OVL_CON_INT_MTX_BT709_TO_RGB (7 << 16)
> +#define DISP_OVL_CON_INT_MTX_EN BIT(27)
> +#define DISP_REG_OVL_ADDR 0xf40
> +#define DISP_REG_OVL_MOUT 0xff0
> +#define OVL_MOUT_OUT_DATA BIT(0)
> +#define OVL_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_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 inline bool is_10bit_rgb(u32 fmt)
> +{
> + switch (fmt) {
> + case DRM_FORMAT_XRGB2101010:
> + case DRM_FORMAT_ARGB2101010:
> + case DRM_FORMAT_RGBX1010102:
> + case DRM_FORMAT_RGBA1010102:
> + case DRM_FORMAT_XBGR2101010:
> + case DRM_FORMAT_ABGR2101010:
> + case DRM_FORMAT_BGRX1010102:
> + case DRM_FORMAT_BGRA1010102:
> + return true;
> + }
> + return false;
> +}
> +
> +static unsigned int mtk_disp_exdma_fmt_convert(unsigned int fmt, unsigned int blend_mode)
The function only differentiates pre-multiplied vs non-pre-multiplied
alpha. Maybe change the second parameter to "bool is_alpha_premultiplied"
to make it clear.
> +{
> + /*
> + * DRM_FORMAT: bit 32->0, OVL_FMT: bit 0->32,
> + * so DRM_FORMAT_RGB888 = OVL_CON_CLRFMT_BGR888
> + */
> + switch (fmt) {
> + default:
> + case DRM_FORMAT_BGR565:
> + return OVL_CON_CLRFMT_RGB565;
> + case DRM_FORMAT_RGB565:
> + return OVL_CON_CLRFMT_BGR565;
> + case DRM_FORMAT_RGB888:
> + return OVL_CON_CLRFMT_BGR888;
> + case DRM_FORMAT_BGR888:
> + return OVL_CON_CLRFMT_RGB888;
> + case DRM_FORMAT_RGBX8888:
> + case DRM_FORMAT_RGBA8888:
> + case DRM_FORMAT_RGBA1010102:
> + case DRM_FORMAT_RGBX1010102:
> + return ((blend_mode == DRM_MODE_BLEND_PREMULTI) ?
> + OVL_CON_CLRFMT_PABGR8888 : OVL_CON_CLRFMT_ABGRB8888) |
> + (is_10bit_rgb(fmt) ? OVL_CON_CLRFMT_NB_10_BIT : 0);
> + case DRM_FORMAT_BGRX8888:
> + case DRM_FORMAT_BGRA8888:
> + case DRM_FORMAT_BGRA1010102:
> + case DRM_FORMAT_BGRX1010102:
> + return ((blend_mode == DRM_MODE_BLEND_PREMULTI) ?
> + OVL_CON_CLRFMT_PARGB8888 : OVL_CON_CLRFMT_ARGB8888) |
> + (is_10bit_rgb(fmt) ? OVL_CON_CLRFMT_NB_10_BIT : 0);
> + case DRM_FORMAT_XRGB8888:
> + case DRM_FORMAT_ARGB8888:
> + case DRM_FORMAT_ARGB2101010:
> + case DRM_FORMAT_XRGB2101010:
> + return ((blend_mode == DRM_MODE_BLEND_PREMULTI) ?
> + OVL_CON_CLRFMT_PBGRA8888 : OVL_CON_CLRFMT_BGRA8888) |
> + (is_10bit_rgb(fmt) ? OVL_CON_CLRFMT_NB_10_BIT : 0);
> + case DRM_FORMAT_XBGR8888:
> + case DRM_FORMAT_ABGR8888:
> + case DRM_FORMAT_ABGR2101010:
> + case DRM_FORMAT_XBGR2101010:
> + return ((blend_mode == DRM_MODE_BLEND_PREMULTI) ?
> + OVL_CON_CLRFMT_PRGBA8888 : OVL_CON_CLRFMT_RGBA8888) |
> + (is_10bit_rgb(fmt) ? OVL_CON_CLRFMT_NB_10_BIT : 0);
> + case DRM_FORMAT_UYVY:
> + return OVL_CON_CLRFMT_UYVY;
> + case DRM_FORMAT_YUYV:
> + return OVL_CON_CLRFMT_YUYV;
> + }
> +}
> +
> +static unsigned int exdma_color_convert(unsigned int color_encoding)
> +{
> + switch (color_encoding) {
> + default:
> + case DRM_COLOR_YCBCR_BT709:
> + return DISP_OVL_CON_INT_MTX_BT709_TO_RGB;
> + case DRM_COLOR_YCBCR_BT601:
> + return DISP_OVL_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 = DISP_RDMA_BURST_CON1_BURST16_EN | DISP_RDMA_BURST_CON1_DDR_ACK_EN;
> + mask = DISP_RDMA_BURST_CON1_BURST16_EN | DISP_RDMA_BURST_CON1_DDR_EN |
> + DISP_RDMA_BURST_CON1_DDR_ACK_EN;
> + mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_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 = DISP_OVL_EXT_DDR_EN_OPT | DISP_OVL_FORCE_EXT_DDR_EN;
> + mask = DISP_OVL_EXT_DDR_EN_OPT | DISP_OVL_FORCE_EXT_DDR_EN;
> + mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_DUMMY_REG, mask);
> +
> + value = DATAPATH_CON_LAYER_SMI_ID_EN | DATAPATH_CON_HDR_GCLAST_EN | DATAPATH_CON_GCLAST_EN;
> + mask = DATAPATH_CON_LAYER_SMI_ID_EN | DATAPATH_CON_HDR_GCLAST_EN | DATAPATH_CON_GCLAST_EN;
> + mtk_ddp_write_mask(cmdq_pkt, value, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_DATAPATH_CON, mask);
> +
> + mtk_ddp_write_mask(cmdq_pkt, OVL_MOUT_BGCLR_OUT, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_MOUT, OVL_MOUT_BGCLR_OUT | OVL_MOUT_OUT_DATA);
> +
> + mtk_ddp_write(cmdq_pkt, ~0, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_GDRDY_PRD);
> +
> + mtk_ddp_write_mask(cmdq_pkt, DISP_RDMA0_EN, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_RDMA0_CTRL, DISP_RDMA0_EN);
> + mtk_ddp_write_mask(cmdq_pkt, DISP_OVL_L0_EN, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_L0_EN, DISP_OVL_L0_EN);
> +
> + mtk_ddp_write_mask(cmdq_pkt, DISP_OVL_EN, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_EN, DISP_OVL_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_EN, DISP_OVL_EN);
> + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_RDMA0_CTRL, DISP_RDMA0_EN);
> + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_DATAPATH_CON, DATAPATH_CON_LAYER_SMI_ID_EN);
> + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_L0_EN, DISP_OVL_L0_EN);
> + mtk_ddp_write_mask(cmdq_pkt, DISP_OVL_RST, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_RST, DISP_OVL_RST);
> + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_RST, DISP_OVL_RST);
> +}
> +
> +void mtk_disp_exdma_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->is_yuv ? true : false;
> + unsigned int blend_mode = DRM_MODE_BLEND_PIXEL_NONE;
> + unsigned int clrfmt = 0;
> + unsigned int clrfmt_mask = OVL_CON_RGB_SWAP |
> + OVL_CON_BYTE_SWAP |
> + OVL_CON_CLRFMT_MAN |
> + OVL_CON_FLD_CLRFMT |
> + OVL_CON_FLD_CLRFMT_NB;
> +
> + /* 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_ROI_SIZE);
> +
> + mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
> + priv->regs, DISP_REG_OVL_SRC_SIZE);
> + mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg,
> + priv->regs, DISP_REG_OVL_SRC_SIZE);
> + mtk_ddp_write(cmdq_pkt, pending->addr, &priv->cmdq_reg,
> + priv->regs, DISP_REG_OVL_ADDR);
> + mtk_ddp_write_mask(cmdq_pkt, pending->pitch, &priv->cmdq_reg, priv->regs, OVL_L0_SRC_PITCH,
> + OVL_L0_SRC_PITCH_MASK);
> + mtk_ddp_write_mask(cmdq_pkt, pending->pitch >> 16, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_PITCH_MSB, 0xf);
> +
> + if (csc_enable)
> + mtk_ddp_write_mask(cmdq_pkt, exdma_color_convert(pending->color_encoding) |
> + DISP_OVL_CON_INT_MTX_EN, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_CON, DISP_OVL_CON_FLD_INT_MTX_SEL |
> + DISP_OVL_CON_INT_MTX_EN);
> + else
> + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs, DISP_REG_OVL_CON,
> + DISP_OVL_CON_INT_MTX_EN);
> +
> + /* alpha blend setting */
> + if (state->base.fb && state->base.fb->format->has_alpha)
> + blend_mode = state->base.pixel_blend_mode;
> +
> + clrfmt = mtk_disp_exdma_fmt_convert(pending->format, blend_mode);
And here you would pass `blend_mode == DRM_MODE_BLEND_PREMULTI` in.
> +
> + mtk_ddp_write_mask(cmdq_pkt, clrfmt, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_L0_CLRFMT, clrfmt_mask);
> +
> + mtk_ddp_write_mask(cmdq_pkt, OVL_OP_8BIT_MODE | OVL_HG_FOVL_CK_ON | OVL_HF_FOVL_CK_ON,
> + &priv->cmdq_reg, priv->regs, DISP_REG_OVL_EN_CON,
> + OVL_OP_8BIT_MODE | OVL_HG_FOVL_CK_ON | OVL_HF_FOVL_CK_ON);
> +
> + mtk_ddp_write_mask(cmdq_pkt, OVL_RDMA0_L0_VCSEL | OVL_RDMA0_HDR_L0_VCSEL,
> + &priv->cmdq_reg, priv->regs, DISP_REG_OVL_L0_GUSER_EXT,
> + OVL_RDMA0_L0_VCSEL | OVL_RDMA0_HDR_L0_VCSEL);
> +
> + if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE) {
> + mtk_ddp_write_mask(cmdq_pkt, OVL_L0_CONST_BLD | pending->pitch,
> + &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_PITCH, OVL_L0_CONST_BLD | OVL_L0_SRC_PITCH);
> + } else {
> + mtk_ddp_write_mask(cmdq_pkt, pending->pitch, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_PITCH, OVL_L0_CONST_BLD | OVL_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);
priv->regs = devm_platform_ioremap_resource(pdev, 0);
> + 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 8c8da188df09..ccbf46d0707a 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -1261,6 +1261,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.34.1
>
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 09/12] drm/mediatek: add BLENDER support for MT8196
2025-01-10 12:33 [PATCH 00/12] Add Mediatek Soc DRM support for mt8196 paul-pl.chen
` (8 preceding siblings ...)
2025-01-10 12:34 ` [PATCH 08/12] drm/mediatek: add EXDMA " paul-pl.chen
@ 2025-01-10 12:34 ` paul-pl.chen
2025-02-12 3:45 ` CK Hu (胡俊光)
2025-01-10 12:34 ` [PATCH 10/12] drm/mediatek: add OUTPROC " paul-pl.chen
` (3 subsequent siblings)
13 siblings, 1 reply; 50+ messages in thread
From: paul-pl.chen @ 2025-01-10 12:34 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
linux-arm-kernel, Project_Global_Chrome_Upstream_Group
From: "Nancy.Lin" <nancy.lin@mediatek.com>
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 | 352 ++++++++++++++++++++
drivers/gpu/drm/mediatek/mtk_disp_blender.h | 17 +
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, 386 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..210906e017f6
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_blender.c
@@ -0,0 +1,352 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021 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"
+
+#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_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 DISP_OVL_BLD_BYPASS_SHADOW BIT(2)
+#define DISP_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_BLD_OVL_OFFSET 0x044
+#define DISP_REG_BLD_OVL_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 OVL_BLD_CON_CLRFMT_RGB565 0x000
+#define OVL_BLD_CON_CLRFMT_BGR888 0x001
+#define OVL_BLD_CON_CLRFMT_BGRA8888 0x002
+#define OVL_BLD_CON_CLRFMT_ABGRB8888 0x003
+#define OVL_BLD_CON_CLRFMT_UYVY 0x004
+#define OVL_BLD_CON_CLRFMT_YUYV 0x005
+#define OVL_BLD_CON_CLRFMT_BGR565 (0x000 | OVL_BLD_CON_BYTE_SWAP)
+#define OVL_BLD_CON_CLRFMT_RGB888 (0x001 | OVL_BLD_CON_BYTE_SWAP)
+#define OVL_BLD_CON_CLRFMT_RGBA8888 (0x002 | OVL_BLD_CON_BYTE_SWAP)
+#define OVL_BLD_CON_CLRFMT_ARGB8888 (0x003 | OVL_BLD_CON_BYTE_SWAP)
+#define OVL_BLD_CON_CLRFMT_VYUY (0x004 | OVL_BLD_CON_BYTE_SWAP)
+#define OVL_BLD_CON_CLRFMT_YVYU (0x005 | OVL_BLD_CON_BYTE_SWAP)
+#define OVL_BLD_CON_CLRFMT_PBGRA8888 (0x003 | OVL_BLD_CON_CLRFMT_MAN)
+#define OVL_BLD_CON_CLRFMT_PARGB8888 (OVL_BLD_CON_CLRFMT_PBGRA8888 | \
+ OVL_BLD_CON_BYTE_SWAP)
+#define OVL_BLD_CON_CLRFMT_PRGBA8888 (OVL_BLD_CON_CLRFMT_PBGRA8888 | \
+ OVL_BLD_CON_RGB_SWAP)
+#define OVL_BLD_CON_CLRFMT_PABGR8888 (OVL_BLD_CON_CLRFMT_PBGRA8888 | \
+ OVL_BLD_CON_RGB_SWAP | \
+ OVL_BLD_CON_BYTE_SWAP)
+#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_L0_CONST_BLD BIT(24)
+
+struct mtk_disp_blender {
+ void __iomem *regs;
+ struct clk *clk;
+ struct cmdq_client_reg cmdq_reg;
+};
+
+static inline bool is_10bit_rgb(u32 fmt)
+{
+ switch (fmt) {
+ case DRM_FORMAT_XRGB2101010:
+ case DRM_FORMAT_ARGB2101010:
+ case DRM_FORMAT_RGBX1010102:
+ case DRM_FORMAT_RGBA1010102:
+ case DRM_FORMAT_XBGR2101010:
+ case DRM_FORMAT_ABGR2101010:
+ case DRM_FORMAT_BGRX1010102:
+ case DRM_FORMAT_BGRA1010102:
+ return true;
+ }
+ return false;
+}
+
+static unsigned int mtk_disp_blender_fmt_convert(unsigned int fmt, unsigned int blend_mode)
+{
+ /*
+ * DRM_FORMAT: bit 32->0, BLD_FMT: bit 0->32,
+ * so DRM_FORMAT_RGB888 = OVL_BLD_CON_CLRFMT_BGR888
+ */
+ switch (fmt) {
+ default:
+ case DRM_FORMAT_BGR565:
+ return OVL_BLD_CON_CLRFMT_RGB565;
+ case DRM_FORMAT_RGB565:
+ return OVL_BLD_CON_CLRFMT_BGR565;
+ case DRM_FORMAT_RGB888:
+ return OVL_BLD_CON_CLRFMT_BGR888;
+ case DRM_FORMAT_BGR888:
+ return OVL_BLD_CON_CLRFMT_RGB888;
+ case DRM_FORMAT_RGBX8888:
+ case DRM_FORMAT_RGBA8888:
+ case DRM_FORMAT_RGBX1010102:
+ case DRM_FORMAT_RGBA1010102:
+ return ((blend_mode == DRM_MODE_BLEND_PREMULTI) ?
+ OVL_BLD_CON_CLRFMT_PABGR8888 : OVL_BLD_CON_CLRFMT_ABGRB8888) |
+ (is_10bit_rgb(fmt) ? OVL_BLD_CON_CLRFMT_NB_10_BIT : 0);
+ case DRM_FORMAT_BGRX8888:
+ case DRM_FORMAT_BGRA8888:
+ case DRM_FORMAT_BGRX1010102:
+ case DRM_FORMAT_BGRA1010102:
+ return ((blend_mode == DRM_MODE_BLEND_PREMULTI) ?
+ OVL_BLD_CON_CLRFMT_PARGB8888 : OVL_BLD_CON_CLRFMT_ARGB8888) |
+ (is_10bit_rgb(fmt) ? OVL_BLD_CON_CLRFMT_NB_10_BIT : 0);
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XRGB2101010:
+ case DRM_FORMAT_ARGB2101010:
+ return ((blend_mode == DRM_MODE_BLEND_PREMULTI) ?
+ OVL_BLD_CON_CLRFMT_PBGRA8888 : OVL_BLD_CON_CLRFMT_BGRA8888) |
+ (is_10bit_rgb(fmt) ? OVL_BLD_CON_CLRFMT_NB_10_BIT : 0);
+ case DRM_FORMAT_XBGR8888:
+ case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_XBGR2101010:
+ case DRM_FORMAT_ABGR2101010:
+ return ((blend_mode == DRM_MODE_BLEND_PREMULTI) ?
+ OVL_BLD_CON_CLRFMT_PRGBA8888 : OVL_BLD_CON_CLRFMT_RGBA8888) |
+ (is_10bit_rgb(fmt) ? OVL_BLD_CON_CLRFMT_NB_10_BIT : 0);
+ case DRM_FORMAT_UYVY:
+ return OVL_BLD_CON_CLRFMT_UYVY;
+ case DRM_FORMAT_YUYV:
+ return OVL_BLD_CON_CLRFMT_YUYV;
+ }
+}
+
+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 = DRM_MODE_BLEND_PIXEL_NONE;
+
+ if (!pending->enable) {
+ mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_BLD_L_EN, OVL_BLD_L_EN);
+ return;
+ }
+
+ mtk_ddp_write(cmdq_pkt, pending->y << 16 | pending->x, &priv->cmdq_reg, priv->regs,
+ DISP_REG_BLD_OVL_OFFSET);
+
+ mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg, priv->regs,
+ DISP_REG_BLD_OVL_SRC_SIZE);
+
+ if (state->base.fb && state->base.fb->format->has_alpha)
+ blend_mode = state->base.pixel_blend_mode;
+
+ clrfmt = mtk_disp_blender_fmt_convert(pending->format, blend_mode);
+
+ 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 = (0xFF & (state->base.alpha >> 8)) | OVL_BLD_L_ALPHA_EN;
+ mtk_ddp_write_mask(cmdq_pkt, alpha, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_BLD_L_CON2, OVL_BLD_L_ALPHA_EN | OVL_BLD_L_ALPHA);
+
+ mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_L_EN, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_BLD_L_EN, OVL_BLD_L_EN);
+
+ if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE)
+ mtk_ddp_write_mask(cmdq_pkt, OVL_L0_CONST_BLD, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_BLD_L0_PITCH, OVL_L0_CONST_BLD);
+ else
+ mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_BLD_L0_PITCH, OVL_L0_CONST_BLD);
+}
+
+void mtk_disp_blender_config(struct device *dev, unsigned int w,
+ unsigned int h, unsigned int vrefresh,
+ unsigned int bpc, enum mtk_disp_blender_layer blender,
+ struct cmdq_pkt *cmdq_pkt)
+{
+ struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+ unsigned int tmp;
+
+ dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
+
+ tmp = readl(priv->regs + DISP_REG_OVL_BLD_SHADOW_CTRL);
+ tmp = tmp | DISP_OVL_BLD_BYPASS_SHADOW;
+ writel(tmp, priv->regs + DISP_REG_OVL_BLD_SHADOW_CTRL);
+
+ 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_OVL_BLD_BGCLR_BALCK, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_BLD_BGCLR_CLR);
+
+ if (blender == FIRST_BLENDER)
+ mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER,
+ &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);
+ else if (blender == LAST_BLENDER)
+ mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_BGCLR_OUT_TO_PROC | OVL_BLD_BGCLR_IN_SEL,
+ &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);
+ else if (blender == SINGLE_BLENDER)
+ mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_BGCLR_OUT_TO_PROC,
+ &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);
+ else
+ mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER | OVL_BLD_BGCLR_IN_SEL,
+ &priv->cmdq_reg, priv->regs, DISP_REG_OVL_BLD_DATAPATH_CON,
+ OVL_BLD_BGCLR_OUT_TO_PROC | OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER |
+ OVL_BLD_BGCLR_IN_SEL);
+}
+
+void mtk_disp_blender_start(struct device *dev, struct cmdq_pkt *cmdq_pkt)
+{
+ struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+
+ mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_EN, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_BLD_EN, OVL_BLD_EN);
+}
+
+void mtk_disp_blender_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt)
+{
+ struct mtk_disp_blender *priv = dev_get_drvdata(dev);
+
+ mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_BLD_L_EN, 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);
+}
+
+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..3f0dfd422afd
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_blender.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021 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,
+};
+
+#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 f8291651dc80..719191f05b27 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, enum mtk_disp_blender_layer blender,
+ 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 ccbf46d0707a..e4a0d9fe4e2d 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -1259,6 +1259,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.34.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 09/12] drm/mediatek: add BLENDER support for MT8196
2025-01-10 12:34 ` [PATCH 09/12] drm/mediatek: add BLENDER " paul-pl.chen
@ 2025-02-12 3:45 ` CK Hu (胡俊光)
0 siblings, 0 replies; 50+ messages in thread
From: CK Hu (胡俊光) @ 2025-02-12 3: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: matthias.bgg@gmail.com, treapking@chromium.org,
Singo Chang (張興國),
Project_Global_Chrome_Upstream_Group,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
Jason-JH Lin (林睿祥),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
linux-mediatek@lists.infradead.org,
Sunny Shen (沈姍姍), p.zabel@pengutronix.de,
Sirius Wang (王皓昱),
linux-arm-kernel@lists.infradead.org
Hi, Paul:
On Fri, 2025-01-10 at 20:34 +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 | 352 ++++++++++++++++++++
> drivers/gpu/drm/mediatek/mtk_disp_blender.h | 17 +
> 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, 386 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..210906e017f6
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_blender.c
> @@ -0,0 +1,352 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2021 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"
> +
> +#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_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 DISP_OVL_BLD_BYPASS_SHADOW BIT(2)
> +#define DISP_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_BLD_OVL_OFFSET 0x044
> +#define DISP_REG_BLD_OVL_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 OVL_BLD_CON_CLRFMT_RGB565 0x000
> +#define OVL_BLD_CON_CLRFMT_BGR888 0x001
> +#define OVL_BLD_CON_CLRFMT_BGRA8888 0x002
> +#define OVL_BLD_CON_CLRFMT_ABGRB8888 0x003
> +#define OVL_BLD_CON_CLRFMT_UYVY 0x004
> +#define OVL_BLD_CON_CLRFMT_YUYV 0x005
> +#define OVL_BLD_CON_CLRFMT_BGR565 (0x000 | OVL_BLD_CON_BYTE_SWAP)
> +#define OVL_BLD_CON_CLRFMT_RGB888 (0x001 | OVL_BLD_CON_BYTE_SWAP)
> +#define OVL_BLD_CON_CLRFMT_RGBA8888 (0x002 | OVL_BLD_CON_BYTE_SWAP)
> +#define OVL_BLD_CON_CLRFMT_ARGB8888 (0x003 | OVL_BLD_CON_BYTE_SWAP)
> +#define OVL_BLD_CON_CLRFMT_VYUY (0x004 | OVL_BLD_CON_BYTE_SWAP)
> +#define OVL_BLD_CON_CLRFMT_YVYU (0x005 | OVL_BLD_CON_BYTE_SWAP)
> +#define OVL_BLD_CON_CLRFMT_PBGRA8888 (0x003 | OVL_BLD_CON_CLRFMT_MAN)
> +#define OVL_BLD_CON_CLRFMT_PARGB8888 (OVL_BLD_CON_CLRFMT_PBGRA8888 | \
> + OVL_BLD_CON_BYTE_SWAP)
> +#define OVL_BLD_CON_CLRFMT_PRGBA8888 (OVL_BLD_CON_CLRFMT_PBGRA8888 | \
> + OVL_BLD_CON_RGB_SWAP)
> +#define OVL_BLD_CON_CLRFMT_PABGR8888 (OVL_BLD_CON_CLRFMT_PBGRA8888 | \
> + OVL_BLD_CON_RGB_SWAP | \
> + OVL_BLD_CON_BYTE_SWAP)
> +#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_L0_CONST_BLD BIT(24)
> +
> +struct mtk_disp_blender {
> + void __iomem *regs;
> + struct clk *clk;
> + struct cmdq_client_reg cmdq_reg;
> +};
> +
> +static inline bool is_10bit_rgb(u32 fmt)
This function is the same as the one in OVL driver. Try to merge them.
> +{
> + switch (fmt) {
> + case DRM_FORMAT_XRGB2101010:
> + case DRM_FORMAT_ARGB2101010:
> + case DRM_FORMAT_RGBX1010102:
> + case DRM_FORMAT_RGBA1010102:
> + case DRM_FORMAT_XBGR2101010:
> + case DRM_FORMAT_ABGR2101010:
> + case DRM_FORMAT_BGRX1010102:
> + case DRM_FORMAT_BGRA1010102:
> + return true;
> + }
> + return false;
> +}
> +
> +static unsigned int mtk_disp_blender_fmt_convert(unsigned int fmt, unsigned int blend_mode)
This function is similar to mtk_ovl_fmt_convert(), try to merge them.
> +{
> + /*
> + * DRM_FORMAT: bit 32->0, BLD_FMT: bit 0->32,
> + * so DRM_FORMAT_RGB888 = OVL_BLD_CON_CLRFMT_BGR888
> + */
> + switch (fmt) {
> + default:
> + case DRM_FORMAT_BGR565:
> + return OVL_BLD_CON_CLRFMT_RGB565;
> + case DRM_FORMAT_RGB565:
> + return OVL_BLD_CON_CLRFMT_BGR565;
> + case DRM_FORMAT_RGB888:
> + return OVL_BLD_CON_CLRFMT_BGR888;
> + case DRM_FORMAT_BGR888:
> + return OVL_BLD_CON_CLRFMT_RGB888;
> + case DRM_FORMAT_RGBX8888:
> + case DRM_FORMAT_RGBA8888:
> + case DRM_FORMAT_RGBX1010102:
> + case DRM_FORMAT_RGBA1010102:
> + return ((blend_mode == DRM_MODE_BLEND_PREMULTI) ?
> + OVL_BLD_CON_CLRFMT_PABGR8888 : OVL_BLD_CON_CLRFMT_ABGRB8888) |
> + (is_10bit_rgb(fmt) ? OVL_BLD_CON_CLRFMT_NB_10_BIT : 0);
> + case DRM_FORMAT_BGRX8888:
> + case DRM_FORMAT_BGRA8888:
> + case DRM_FORMAT_BGRX1010102:
> + case DRM_FORMAT_BGRA1010102:
> + return ((blend_mode == DRM_MODE_BLEND_PREMULTI) ?
> + OVL_BLD_CON_CLRFMT_PARGB8888 : OVL_BLD_CON_CLRFMT_ARGB8888) |
> + (is_10bit_rgb(fmt) ? OVL_BLD_CON_CLRFMT_NB_10_BIT : 0);
> + case DRM_FORMAT_XRGB8888:
> + case DRM_FORMAT_ARGB8888:
> + case DRM_FORMAT_XRGB2101010:
> + case DRM_FORMAT_ARGB2101010:
> + return ((blend_mode == DRM_MODE_BLEND_PREMULTI) ?
> + OVL_BLD_CON_CLRFMT_PBGRA8888 : OVL_BLD_CON_CLRFMT_BGRA8888) |
> + (is_10bit_rgb(fmt) ? OVL_BLD_CON_CLRFMT_NB_10_BIT : 0);
> + case DRM_FORMAT_XBGR8888:
> + case DRM_FORMAT_ABGR8888:
> + case DRM_FORMAT_XBGR2101010:
> + case DRM_FORMAT_ABGR2101010:
> + return ((blend_mode == DRM_MODE_BLEND_PREMULTI) ?
> + OVL_BLD_CON_CLRFMT_PRGBA8888 : OVL_BLD_CON_CLRFMT_RGBA8888) |
> + (is_10bit_rgb(fmt) ? OVL_BLD_CON_CLRFMT_NB_10_BIT : 0);
> + case DRM_FORMAT_UYVY:
> + return OVL_BLD_CON_CLRFMT_UYVY;
> + case DRM_FORMAT_YUYV:
> + return OVL_BLD_CON_CLRFMT_YUYV;
> + }
> +}
> +
> +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);
Why do this alignment?
If width is 101, changing it to 102 would get correct display output?
I does not see pitch setting in this driver, so this hardware does not support pitch?
> + unsigned int alpha;
> + unsigned int clrfmt;
> + unsigned int blend_mode = DRM_MODE_BLEND_PIXEL_NONE;
> +
> + if (!pending->enable) {
> + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_BLD_L_EN, OVL_BLD_L_EN);
> + return;
> + }
> +
> + mtk_ddp_write(cmdq_pkt, pending->y << 16 | pending->x, &priv->cmdq_reg, priv->regs,
> + DISP_REG_BLD_OVL_OFFSET);
> +
> + mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &priv->cmdq_reg, priv->regs,
> + DISP_REG_BLD_OVL_SRC_SIZE);
> +
> + if (state->base.fb && state->base.fb->format->has_alpha)
> + blend_mode = state->base.pixel_blend_mode;
> +
> + clrfmt = mtk_disp_blender_fmt_convert(pending->format, blend_mode);
> +
> + 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 = (0xFF & (state->base.alpha >> 8)) | OVL_BLD_L_ALPHA_EN;
I think state->base.alpha is in the range of 0 ~ 255.
Do you test alpha blending with this patch?
If no, it's better to remove alpha related setting in this patch.
After you have test alpha, send alpha related patch.
I think this hardware has the same behavior with OVL hardware,
So I would like alpha related code is similar with the code in ovl driver.
> + 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_mask(cmdq_pkt, OVL_BLD_L_EN, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_BLD_L_EN, OVL_BLD_L_EN);
Move enable hardware to the bottom of this function.
> +
> + if (blend_mode == DRM_MODE_BLEND_PIXEL_NONE)
> + mtk_ddp_write_mask(cmdq_pkt, OVL_L0_CONST_BLD, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_BLD_L0_PITCH, OVL_L0_CONST_BLD);
> + else
> + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_BLD_L0_PITCH, OVL_L0_CONST_BLD);
> +}
> +
> +void mtk_disp_blender_config(struct device *dev, unsigned int w,
> + unsigned int h, unsigned int vrefresh,
> + unsigned int bpc, enum mtk_disp_blender_layer blender,
> + struct cmdq_pkt *cmdq_pkt)
> +{
> + struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> + unsigned int tmp;
> +
> + dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
> +
> + tmp = readl(priv->regs + DISP_REG_OVL_BLD_SHADOW_CTRL);
> + tmp = tmp | DISP_OVL_BLD_BYPASS_SHADOW;
> + writel(tmp, priv->regs + DISP_REG_OVL_BLD_SHADOW_CTRL);
Move bypass shadow to mtk_disp_blender_start().
> +
> + 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_OVL_BLD_BGCLR_BALCK, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_BLD_BGCLR_CLR);
> +
> + if (blender == FIRST_BLENDER)
> + mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER,
> + &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);
> + else if (blender == LAST_BLENDER)
> + mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_BGCLR_OUT_TO_PROC | OVL_BLD_BGCLR_IN_SEL,
> + &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);
> + else if (blender == SINGLE_BLENDER)
> + mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_BGCLR_OUT_TO_PROC,
> + &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);
> + else
> + mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER | OVL_BLD_BGCLR_IN_SEL,
> + &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);
I would like to drop blender, and
if (!first_blender)
bld_bgclr |= OVL_BLD_BGCLR_IN_SEL;
if (last_blender)
bld_bgclr |= OVL_BLD_BGCLR_OUT_TO_PROC;
else
bld_bgclr |= OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER;
mtk_ddp_write_mask(cmdq_pkt, bld_bgclr,
OVL_BLD_BGCLR_OUT_TO_PROC | OVL_BLD_BGCLR_OUT_TO_NEXT_LAYER |
OVL_BLD_BGCLR_IN_SEL);
The caller would call like this:
mtk_disp_blender_config(..., blender_idx == 1, blender_idx == layer_nr)
> +}
> +
> +void mtk_disp_blender_start(struct device *dev, struct cmdq_pkt *cmdq_pkt)
> +{
> + struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> +
> + mtk_ddp_write_mask(cmdq_pkt, OVL_BLD_EN, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_BLD_EN, OVL_BLD_EN);
> +}
> +
> +void mtk_disp_blender_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt)
> +{
> + struct mtk_disp_blender *priv = dev_get_drvdata(dev);
> +
> + mtk_ddp_write_mask(cmdq_pkt, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_BLD_L_EN, OVL_BLD_L_EN);
When OVL stop, it does not disable layer.
So align the behavior with OVL driver.
Regards,
CK
> + 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);
> +}
> +
> +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..3f0dfd422afd
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_blender.h
> @@ -0,0 +1,17 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2021 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,
> +};
> +
> +#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 f8291651dc80..719191f05b27 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, enum mtk_disp_blender_layer blender,
> + 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 ccbf46d0707a..e4a0d9fe4e2d 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -1259,6 +1259,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;
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 10/12] drm/mediatek: add OUTPROC support for MT8196
2025-01-10 12:33 [PATCH 00/12] Add Mediatek Soc DRM support for mt8196 paul-pl.chen
` (9 preceding siblings ...)
2025-01-10 12:34 ` [PATCH 09/12] drm/mediatek: add BLENDER " paul-pl.chen
@ 2025-01-10 12:34 ` paul-pl.chen
2025-02-12 4:08 ` CK Hu (胡俊光)
2025-01-10 12:34 ` [PATCH 11/12] drm/mediatek: add ovlsys_adaptor " paul-pl.chen
` (2 subsequent siblings)
13 siblings, 1 reply; 50+ messages in thread
From: paul-pl.chen @ 2025-01-10 12:34 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
linux-arm-kernel, Project_Global_Chrome_Upstream_Group
From: "Nancy.Lin" <nancy.lin@mediatek.com>
OUTPROC handles the post-stage of pixel processing in
the overlapping procedure.OUTPROC manages pixels for
gamma correction and ensures that pixel values are
within the correct range.
Signed-off-by: Nancy.Lin <nancy.lin@mediatek.com>
Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
---
drivers/gpu/drm/mediatek/Makefile | 1 +
drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 1 +
drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 1 +
drivers/gpu/drm/mediatek/mtk_disp_drv.h | 14 ++
drivers/gpu/drm/mediatek/mtk_disp_outproc.c | 244 ++++++++++++++++++++
drivers/gpu/drm/mediatek/mtk_disp_outproc.h | 22 ++
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 +
drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 +
8 files changed, 285 insertions(+)
create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_outproc.c
create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_outproc.h
diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
index a7b9ebe27f68..9546bc6b7b2e 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -10,6 +10,7 @@ mediatek-drm-y := mtk_crtc.o \
mtk_disp_gamma.o \
mtk_disp_merge.o \
mtk_disp_ovl.o \
+ mtk_disp_outproc.o \
mtk_disp_ovl_adaptor.o \
mtk_disp_rdma.o \
mtk_drm_drv.o \
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index e65c6df987f2..cc780744f060 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -447,6 +447,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
[MTK_DSI] = "dsi",
[MTK_OVL_BLENDER] = "blender",
[MTK_OVL_EXDMA] = "exdma",
+ [MTK_OVL_OUTPROC] = "outproc",
};
struct mtk_ddp_comp_match {
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
index 075ba5683f93..b33d3289b8b6 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
@@ -45,6 +45,7 @@ enum mtk_ddp_comp_type {
MTK_DSI,
MTK_OVL_BLENDER,
MTK_OVL_EXDMA,
+ MTK_OVL_OUTPROC,
MTK_DDP_COMP_TYPE_MAX,
};
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
index 719191f05b27..44d2cbe919dc 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -64,6 +64,20 @@ void mtk_dither_set_common(void __iomem *regs, struct cmdq_client_reg *cmdq_reg,
unsigned int bpc, unsigned int cfg,
unsigned int dither_en, struct cmdq_pkt *cmdq_pkt);
+void mtk_disp_outproc_start(struct device *dev);
+void mtk_disp_outproc_stop(struct device *dev);
+int mtk_disp_outproc_clk_enable(struct device *dev);
+void mtk_disp_outproc_clk_disable(struct device *dev);
+void mtk_disp_outproc_config(struct device *dev, unsigned int w,
+ unsigned int h, unsigned int vrefresh,
+ unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
+void mtk_disp_outproc_register_vblank_cb(struct device *dev,
+ void (*vblank_cb)(void *),
+ void *vblank_cb_data);
+void mtk_disp_outproc_unregister_vblank_cb(struct device *dev);
+void mtk_disp_outproc_enable_vblank(struct device *dev);
+void mtk_disp_outproc_disable_vblank(struct device *dev);
+
void mtk_dpi_start(struct device *dev);
void mtk_dpi_stop(struct device *dev);
unsigned int mtk_dpi_encoder_index(struct device *dev);
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_outproc.c b/drivers/gpu/drm/mediatek/mtk_disp_outproc.c
new file mode 100644
index 000000000000..af473eb2fb77
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_outproc.c
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ */
+
+#include <drm/drm_fourcc.h>
+#include <drm/drm_framebuffer.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/soc/mediatek/mtk-cmdq.h>
+#include <linux/soc/mediatek/mtk-mmsys.h>
+
+#include "mtk_crtc.h"
+#include "mtk_ddp_comp.h"
+#include <linux/of.h>
+#include "mtk_drm_drv.h"
+#include "mtk_disp_outproc.h"
+
+#define DISP_REG_OVL_OUTPROC_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 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;
+
+ writel(0x0, priv->regs + DISP_REG_OVL_OUTPROC_INTSTA);
+
+ if (!priv->vblank_cb)
+ return IRQ_NONE;
+
+ priv->vblank_cb(priv->vblank_cb_data);
+
+ return IRQ_HANDLED;
+}
+
+void mtk_disp_outproc_config(struct device *dev, unsigned int w,
+ unsigned int h, unsigned int vrefresh,
+ unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
+{
+ struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+ unsigned int tmp;
+
+ dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
+
+ tmp = readl(priv->regs + DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
+ tmp = tmp | OVL_OUTPROC_BYPASS_SHADOW;
+ writel(tmp, priv->regs + DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
+
+ mtk_ddp_write_mask(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_OUTPROC_ROI_SIZE, ~0);
+ mtk_ddp_write_mask(cmdq_pkt, DATAPATH_CON_OUTPUT_CLAMP, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_OUTPROC_DATAPATH_CON, DATAPATH_CON_OUTPUT_CLAMP);
+}
+
+void mtk_disp_outproc_start(struct device *dev)
+{
+ struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+ mtk_ddp_write_mask(NULL, OVL_OUTPROC_RST, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_OUTPROC_RST, OVL_OUTPROC_RST);
+ mtk_ddp_write_mask(NULL, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_OUTPROC_RST, OVL_OUTPROC_RST);
+ mtk_ddp_write(NULL, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_OUTPROC_INTSTA);
+ mtk_ddp_write_mask(NULL, OVL_OUTPROC_OVL_EN, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_OUTPROC_EN, OVL_OUTPROC_OVL_EN);
+}
+
+void mtk_disp_outproc_stop(struct device *dev)
+{
+ struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+ mtk_ddp_write(NULL, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_OUTPROC_INTEN);
+ mtk_ddp_write_mask(NULL, 0, &priv->cmdq_reg, priv->regs,
+ DISP_REG_OVL_OUTPROC_EN, OVL_OUTPROC_OVL_EN);
+}
+
+int mtk_disp_outproc_clk_enable(struct device *dev)
+{
+ struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+ return clk_prepare_enable(priv->clk);
+}
+
+void mtk_disp_outproc_clk_disable(struct device *dev)
+{
+ struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(priv->clk);
+}
+
+static int mtk_disp_outproc_bind(struct device *dev, struct device *master,
+ void *data)
+{
+ return 0;
+}
+
+static void mtk_disp_outproc_unbind(struct device *dev, struct device *master, void *data)
+{
+}
+
+static const struct component_ops mtk_disp_outproc_component_ops = {
+ .bind = mtk_disp_outproc_bind,
+ .unbind = mtk_disp_outproc_unbind,
+};
+
+static int mtk_disp_outproc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ struct mtk_disp_outproc *priv;
+ int ret = 0;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->regs)) {
+ dev_err(dev, "failed to ioremap outproc\n");
+ return PTR_ERR(priv->regs);
+ }
+
+ priv->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(priv->clk)) {
+ dev_err(dev, "failed to get outproc clk\n");
+ return PTR_ERR(priv->clk);
+ }
+
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+ ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
+ if (ret)
+ dev_dbg(dev, "No mediatek,gce-client-reg\n");
+#endif
+
+ if (of_property_read_u32_index(dev->of_node, "interrupts", 0, &ret)) {
+ dev_dbg(dev, "interrupts not defined\n");
+ } 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)
+ dev_notice(dev, "Failed to add component: %d\n", ret);
+
+ return ret;
+}
+
+static void mtk_disp_outproc_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &mtk_disp_outproc_component_ops);
+}
+
+static const struct of_device_id mtk_disp_outproc_driver_dt_match[] = {
+ { .compatible = "mediatek,mt8196-outproc"},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, mtk_disp_outproc_driver_dt_match);
+
+struct platform_driver mtk_disp_outproc_driver = {
+ .probe = mtk_disp_outproc_probe,
+ .remove = mtk_disp_outproc_remove,
+ .driver = {
+ .name = "mediatek-disp-outproc",
+ .owner = THIS_MODULE,
+ .of_match_table = mtk_disp_outproc_driver_dt_match,
+ },
+};
+
+MODULE_AUTHOR("Nancy Lin <nancy.lin@mediatek.com>");
+MODULE_DESCRIPTION("MediaTek Output processing Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_outproc.h b/drivers/gpu/drm/mediatek/mtk_disp_outproc.h
new file mode 100644
index 000000000000..22ee5d845eae
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_outproc.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ */
+
+#ifndef __MTK_DISP_OUTPROC_H__
+#define __MTK_DISP_OUTPROC_H__
+
+void mtk_disp_outproc_start(struct device *dev);
+void mtk_disp_outproc_stop(struct device *dev);
+int mtk_disp_outproc_clk_enable(struct device *dev);
+void mtk_disp_outproc_clk_disable(struct device *dev);
+void mtk_disp_outproc_config(struct device *dev, unsigned int w,
+ unsigned int h, unsigned int vrefresh,
+ unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
+void mtk_disp_outproc_register_vblank_cb(struct device *dev,
+ void (*vblank_cb)(void *),
+ void *vblank_cb_data);
+void mtk_disp_outproc_unregister_vblank_cb(struct device *dev);
+void mtk_disp_outproc_enable_vblank(struct device *dev);
+void mtk_disp_outproc_disable_vblank(struct device *dev);
+#endif
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index e4a0d9fe4e2d..27190057bd8e 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -1265,6 +1265,7 @@ static struct platform_driver * const mtk_drm_drivers[] = {
&mtk_disp_exdma_driver,
&mtk_disp_gamma_driver,
&mtk_disp_merge_driver,
+ &mtk_disp_outproc_driver,
&mtk_disp_ovl_adaptor_driver,
&mtk_disp_ovl_driver,
&mtk_disp_rdma_driver,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index 89178de1478f..c4717c37b0f1 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -76,6 +76,7 @@ extern struct platform_driver mtk_disp_color_driver;
extern struct platform_driver mtk_disp_exdma_driver;
extern struct platform_driver mtk_disp_gamma_driver;
extern struct platform_driver mtk_disp_merge_driver;
+extern struct platform_driver mtk_disp_outproc_driver;
extern struct platform_driver mtk_disp_ovl_adaptor_driver;
extern struct platform_driver mtk_disp_ovl_driver;
extern struct platform_driver mtk_disp_rdma_driver;
--
2.34.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 10/12] drm/mediatek: add OUTPROC support for MT8196
2025-01-10 12:34 ` [PATCH 10/12] drm/mediatek: add OUTPROC " paul-pl.chen
@ 2025-02-12 4:08 ` CK Hu (胡俊光)
2025-02-21 11:54 ` Paul-pl Chen (陳柏霖)
0 siblings, 1 reply; 50+ messages in thread
From: CK Hu (胡俊光) @ 2025-02-12 4:08 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: matthias.bgg@gmail.com, treapking@chromium.org,
Singo Chang (張興國),
Project_Global_Chrome_Upstream_Group,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
Jason-JH Lin (林睿祥),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
linux-mediatek@lists.infradead.org,
Sunny Shen (沈姍姍), p.zabel@pengutronix.de,
Sirius Wang (王皓昱),
linux-arm-kernel@lists.infradead.org
Hi, Paul:
On Fri, 2025-01-10 at 20:34 +0800, paul-pl.chen wrote:
> From: "Nancy.Lin" <nancy.lin@mediatek.com>
>
> OUTPROC handles the post-stage of pixel processing in
> the overlapping procedure.OUTPROC manages pixels for
> gamma correction and ensures that pixel values are
> within the correct range.
>
> Signed-off-by: Nancy.Lin <nancy.lin@mediatek.com>
> Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
> ---
> drivers/gpu/drm/mediatek/Makefile | 1 +
> drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 1 +
> drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 1 +
> drivers/gpu/drm/mediatek/mtk_disp_drv.h | 14 ++
> drivers/gpu/drm/mediatek/mtk_disp_outproc.c | 244 ++++++++++++++++++++
> drivers/gpu/drm/mediatek/mtk_disp_outproc.h | 22 ++
> drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 +
> drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 +
> 8 files changed, 285 insertions(+)
> create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_outproc.c
> create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_outproc.h
>
> diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
> index a7b9ebe27f68..9546bc6b7b2e 100644
> --- a/drivers/gpu/drm/mediatek/Makefile
> +++ b/drivers/gpu/drm/mediatek/Makefile
> @@ -10,6 +10,7 @@ mediatek-drm-y := mtk_crtc.o \
> mtk_disp_gamma.o \
> mtk_disp_merge.o \
> mtk_disp_ovl.o \
> + mtk_disp_outproc.o \
> mtk_disp_ovl_adaptor.o \
> mtk_disp_rdma.o \
> mtk_drm_drv.o \
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> index e65c6df987f2..cc780744f060 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> @@ -447,6 +447,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
> [MTK_DSI] = "dsi",
> [MTK_OVL_BLENDER] = "blender",
> [MTK_OVL_EXDMA] = "exdma",
> + [MTK_OVL_OUTPROC] = "outproc",
> };
>
> struct mtk_ddp_comp_match {
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> index 075ba5683f93..b33d3289b8b6 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> @@ -45,6 +45,7 @@ enum mtk_ddp_comp_type {
> MTK_DSI,
> MTK_OVL_BLENDER,
> MTK_OVL_EXDMA,
> + MTK_OVL_OUTPROC,
> MTK_DDP_COMP_TYPE_MAX,
> };
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> index 719191f05b27..44d2cbe919dc 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> @@ -64,6 +64,20 @@ void mtk_dither_set_common(void __iomem *regs, struct cmdq_client_reg *cmdq_reg,
> unsigned int bpc, unsigned int cfg,
> unsigned int dither_en, struct cmdq_pkt *cmdq_pkt);
>
> +void mtk_disp_outproc_start(struct device *dev);
> +void mtk_disp_outproc_stop(struct device *dev);
> +int mtk_disp_outproc_clk_enable(struct device *dev);
> +void mtk_disp_outproc_clk_disable(struct device *dev);
> +void mtk_disp_outproc_config(struct device *dev, unsigned int w,
> + unsigned int h, unsigned int vrefresh,
> + unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
> +void mtk_disp_outproc_register_vblank_cb(struct device *dev,
> + void (*vblank_cb)(void *),
> + void *vblank_cb_data);
> +void mtk_disp_outproc_unregister_vblank_cb(struct device *dev);
> +void mtk_disp_outproc_enable_vblank(struct device *dev);
> +void mtk_disp_outproc_disable_vblank(struct device *dev);
> +
> void mtk_dpi_start(struct device *dev);
> void mtk_dpi_stop(struct device *dev);
> unsigned int mtk_dpi_encoder_index(struct device *dev);
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_outproc.c b/drivers/gpu/drm/mediatek/mtk_disp_outproc.c
> new file mode 100644
> index 000000000000..af473eb2fb77
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_outproc.c
> @@ -0,0 +1,244 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2021 MediaTek Inc.
> + */
> +
> +#include <drm/drm_fourcc.h>
> +#include <drm/drm_framebuffer.h>
> +#include <linux/clk.h>
> +#include <linux/component.h>
> +#include <linux/of_device.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset.h>
> +#include <linux/soc/mediatek/mtk-cmdq.h>
> +#include <linux/soc/mediatek/mtk-mmsys.h>
> +
> +#include "mtk_crtc.h"
> +#include "mtk_ddp_comp.h"
> +#include <linux/of.h>
> +#include "mtk_drm_drv.h"
> +#include "mtk_disp_outproc.h"
> +
> +#define DISP_REG_OVL_OUTPROC_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 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;
> +
> + writel(0x0, priv->regs + DISP_REG_OVL_OUTPROC_INTSTA);
> +
> + if (!priv->vblank_cb)
> + return IRQ_NONE;
> +
> + priv->vblank_cb(priv->vblank_cb_data);
> +
> + return IRQ_HANDLED;
> +}
> +
> +void mtk_disp_outproc_config(struct device *dev, unsigned int w,
> + unsigned int h, unsigned int vrefresh,
> + unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
> +{
> + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> + unsigned int tmp;
> +
> + dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
> +
> + tmp = readl(priv->regs + DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
> + tmp = tmp | OVL_OUTPROC_BYPASS_SHADOW;
> + writel(tmp, priv->regs + DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
Move bypass shadow to mtk_disp_outproc_start().
> +
> + mtk_ddp_write_mask(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_ROI_SIZE, ~0);
mtk_ddp_write();
> + mtk_ddp_write_mask(cmdq_pkt, DATAPATH_CON_OUTPUT_CLAMP, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_DATAPATH_CON, DATAPATH_CON_OUTPUT_CLAMP);
> +}
> +
> +void mtk_disp_outproc_start(struct device *dev)
> +{
> + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> + mtk_ddp_write_mask(NULL, OVL_OUTPROC_RST, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_RST, OVL_OUTPROC_RST);
writel();
> + mtk_ddp_write_mask(NULL, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_RST, OVL_OUTPROC_RST);
Some hardware reset before start.
Some hardware reset after stop.
Could align this?
> + mtk_ddp_write(NULL, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_INTSTA);
> + mtk_ddp_write_mask(NULL, OVL_OUTPROC_OVL_EN, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_EN, OVL_OUTPROC_OVL_EN);
> +}
> +
> +void mtk_disp_outproc_stop(struct device *dev)
> +{
> + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> + mtk_ddp_write(NULL, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_INTEN);
OVL driver does not disable interrupt when stop.
Align this with OVL driver.
> + mtk_ddp_write_mask(NULL, 0, &priv->cmdq_reg, priv->regs,
> + DISP_REG_OVL_OUTPROC_EN, OVL_OUTPROC_OVL_EN);
> +}
> +
> +int mtk_disp_outproc_clk_enable(struct device *dev)
> +{
> + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> + return clk_prepare_enable(priv->clk);
> +}
> +
> +void mtk_disp_outproc_clk_disable(struct device *dev)
> +{
> + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> +
> + clk_disable_unprepare(priv->clk);
> +}
> +
> +static int mtk_disp_outproc_bind(struct device *dev, struct device *master,
> + void *data)
> +{
> + return 0;
> +}
> +
> +static void mtk_disp_outproc_unbind(struct device *dev, struct device *master, void *data)
> +{
> +}
> +
> +static const struct component_ops mtk_disp_outproc_component_ops = {
> + .bind = mtk_disp_outproc_bind,
> + .unbind = mtk_disp_outproc_unbind,
> +};
> +
> +static int mtk_disp_outproc_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct resource *res;
> + struct mtk_disp_outproc *priv;
> + int ret = 0;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + priv->regs = devm_ioremap_resource(dev, res);
> + if (IS_ERR(priv->regs)) {
> + dev_err(dev, "failed to ioremap outproc\n");
> + return PTR_ERR(priv->regs);
> + }
> +
> + priv->clk = devm_clk_get(dev, NULL);
> + if (IS_ERR(priv->clk)) {
> + dev_err(dev, "failed to get outproc clk\n");
> + return PTR_ERR(priv->clk);
> + }
> +
> +#if IS_REACHABLE(CONFIG_MTK_CMDQ)
> + ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
> + if (ret)
> + dev_dbg(dev, "No mediatek,gce-client-reg\n");
> +#endif
> +
> + if (of_property_read_u32_index(dev->of_node, "interrupts", 0, &ret)) {
> + dev_dbg(dev, "interrupts not defined\n");
In binding document, interrupt is required.
So return with error code.
> + } else {
> + priv->irq = platform_get_irq(pdev, 0);
> + if (priv->irq < 0)
> + priv->irq = 0;
In binding document, interrupt is required.
So return with error code.
Regards,
CK
> +
> + if (priv->irq) {
> + ret = devm_request_irq(dev, priv->irq, mtk_disp_outproc_irq_handler,
> + IRQF_TRIGGER_NONE, dev_name(dev), priv);
> + if (ret < 0) {
> + dev_err(dev, "Failed to request irq %d: %d\n", priv->irq, ret);
> + return ret;
> + }
> + }
> + }
> +
> + platform_set_drvdata(pdev, priv);
> +
> + ret = component_add(dev, &mtk_disp_outproc_component_ops);
> + if (ret)
> + dev_notice(dev, "Failed to add component: %d\n", ret);
> +
> + return ret;
> +}
> +
> +static void mtk_disp_outproc_remove(struct platform_device *pdev)
> +{
> + component_del(&pdev->dev, &mtk_disp_outproc_component_ops);
> +}
> +
> +static const struct of_device_id mtk_disp_outproc_driver_dt_match[] = {
> + { .compatible = "mediatek,mt8196-outproc"},
> + {},
> +};
> +
> +MODULE_DEVICE_TABLE(of, mtk_disp_outproc_driver_dt_match);
> +
> +struct platform_driver mtk_disp_outproc_driver = {
> + .probe = mtk_disp_outproc_probe,
> + .remove = mtk_disp_outproc_remove,
> + .driver = {
> + .name = "mediatek-disp-outproc",
> + .owner = THIS_MODULE,
> + .of_match_table = mtk_disp_outproc_driver_dt_match,
> + },
> +};
> +
> +MODULE_AUTHOR("Nancy Lin <nancy.lin@mediatek.com>");
> +MODULE_DESCRIPTION("MediaTek Output processing Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_outproc.h b/drivers/gpu/drm/mediatek/mtk_disp_outproc.h
> new file mode 100644
> index 000000000000..22ee5d845eae
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_outproc.h
> @@ -0,0 +1,22 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2021 MediaTek Inc.
> + */
> +
> +#ifndef __MTK_DISP_OUTPROC_H__
> +#define __MTK_DISP_OUTPROC_H__
> +
> +void mtk_disp_outproc_start(struct device *dev);
> +void mtk_disp_outproc_stop(struct device *dev);
> +int mtk_disp_outproc_clk_enable(struct device *dev);
> +void mtk_disp_outproc_clk_disable(struct device *dev);
> +void mtk_disp_outproc_config(struct device *dev, unsigned int w,
> + unsigned int h, unsigned int vrefresh,
> + unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
> +void mtk_disp_outproc_register_vblank_cb(struct device *dev,
> + void (*vblank_cb)(void *),
> + void *vblank_cb_data);
> +void mtk_disp_outproc_unregister_vblank_cb(struct device *dev);
> +void mtk_disp_outproc_enable_vblank(struct device *dev);
> +void mtk_disp_outproc_disable_vblank(struct device *dev);
> +#endif
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index e4a0d9fe4e2d..27190057bd8e 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -1265,6 +1265,7 @@ static struct platform_driver * const mtk_drm_drivers[] = {
> &mtk_disp_exdma_driver,
> &mtk_disp_gamma_driver,
> &mtk_disp_merge_driver,
> + &mtk_disp_outproc_driver,
> &mtk_disp_ovl_adaptor_driver,
> &mtk_disp_ovl_driver,
> &mtk_disp_rdma_driver,
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> index 89178de1478f..c4717c37b0f1 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> @@ -76,6 +76,7 @@ extern struct platform_driver mtk_disp_color_driver;
> extern struct platform_driver mtk_disp_exdma_driver;
> extern struct platform_driver mtk_disp_gamma_driver;
> extern struct platform_driver mtk_disp_merge_driver;
> +extern struct platform_driver mtk_disp_outproc_driver;
> extern struct platform_driver mtk_disp_ovl_adaptor_driver;
> extern struct platform_driver mtk_disp_ovl_driver;
> extern struct platform_driver mtk_disp_rdma_driver;
^ permalink raw reply [flat|nested] 50+ messages in thread* Re: [PATCH 10/12] drm/mediatek: add OUTPROC support for MT8196
2025-02-12 4:08 ` CK Hu (胡俊光)
@ 2025-02-21 11:54 ` Paul-pl Chen (陳柏霖)
0 siblings, 0 replies; 50+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-02-21 11:54 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 (沈姍姍),
Singo Chang (張興國), treapking@chromium.org,
Project_Global_Chrome_Upstream_Group,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
Jason-JH Lin (林睿祥),
linux-kernel@vger.kernel.org,
Nancy Lin (林欣螢),
Xiandong Wang (王先冬), matthias.bgg@gmail.com,
linux-mediatek@lists.infradead.org, p.zabel@pengutronix.de,
Sirius Wang (王皓昱),
linux-arm-kernel@lists.infradead.org
On Wed, 2025-02-12 at 04:08 +0000, CK Hu (胡俊光) wrote:
> Hi, Paul:
>
> On Fri, 2025-01-10 at 20:34 +0800, paul-pl.chen wrote:
> > From: "Nancy.Lin" <nancy.lin@mediatek.com>
> >
> > OUTPROC handles the post-stage of pixel processing in
> > the overlapping procedure.OUTPROC manages pixels for
> > gamma correction and ensures that pixel values are
> > within the correct range.
> >
> > Signed-off-by: Nancy.Lin <nancy.lin@mediatek.com>
> > Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
> > ---
> > drivers/gpu/drm/mediatek/Makefile | 1 +
> > drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 1 +
> > drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 1 +
> > drivers/gpu/drm/mediatek/mtk_disp_drv.h | 14 ++
> > drivers/gpu/drm/mediatek/mtk_disp_outproc.c | 244
> > ++++++++++++++++++++
> > drivers/gpu/drm/mediatek/mtk_disp_outproc.h | 22 ++
> > drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 +
> > drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 +
> > 8 files changed, 285 insertions(+)
> > create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_outproc.c
> > create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_outproc.h
> >
> >
//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..af473eb2fb77
> > --- /dev/null
> > +++ b/drivers/gpu/drm/mediatek/mtk_disp_outproc.c
> > @@ -0,0 +1,244 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (c) 2021 MediaTek Inc.
> > + */
> > +
> > +#include <drm/drm_fourcc.h>
> > +#include <drm/drm_framebuffer.h>
> > +#include <linux/clk.h>
> > +#include <linux/component.h>
> > +#include <linux/of_device.h>
> > +#include <linux/of_address.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/reset.h>
> > +#include <linux/soc/mediatek/mtk-cmdq.h>
> > +#include <linux/soc/mediatek/mtk-mmsys.h>
> > +
> > +#include "mtk_crtc.h"
> > +#include "mtk_ddp_comp.h"
> > +#include <linux/of.h>
> > +#include "mtk_drm_drv.h"
> > +#include "mtk_disp_outproc.h"
> > +
> > +#define
> > DISP_REG_OVL_OUTPROC_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
> > 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;
> > +
> > + writel(0x0, priv->regs + DISP_REG_OVL_OUTPROC_INTSTA);
> > +
> > + if (!priv->vblank_cb)
> > + return IRQ_NONE;
> > +
> > + priv->vblank_cb(priv->vblank_cb_data);
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +void mtk_disp_outproc_config(struct device *dev, unsigned int w,
> > + unsigned int h, unsigned int
> > vrefresh,
> > + unsigned int bpc, struct cmdq_pkt
> > *cmdq_pkt)
> > +{
> > + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> > + unsigned int tmp;
> > +
> > + dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
> > +
> > + tmp = readl(priv->regs +
> > DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
> > + tmp = tmp | OVL_OUTPROC_BYPASS_SHADOW;
> > + writel(tmp, priv->regs +
> > DISP_REG_OVL_OUTPROC_SHADOW_CTRL);
>
> Move bypass shadow to mtk_disp_outproc_start().
>
Sure, we will move the bypass shadow to mtk_disp_outproc_start().
> > +
> > + mtk_ddp_write_mask(cmdq_pkt, h << 16 | w, &priv->cmdq_reg,
> > priv->regs,
> > + DISP_REG_OVL_OUTPROC_ROI_SIZE, ~0);
>
> mtk_ddp_write();
>
> > + mtk_ddp_write_mask(cmdq_pkt, DATAPATH_CON_OUTPUT_CLAMP,
> > &priv->cmdq_reg, priv->regs,
> > + DISP_REG_OVL_OUTPROC_DATAPATH_CON,
> > DATAPATH_CON_OUTPUT_CLAMP);
> > +}
> > +
> > +void mtk_disp_outproc_start(struct device *dev)
> > +{
> > + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> > +
> > + mtk_ddp_write_mask(NULL, OVL_OUTPROC_RST, &priv->cmdq_reg,
> > priv->regs,
> > + DISP_REG_OVL_OUTPROC_RST,
> > OVL_OUTPROC_RST);
>
> writel();
>
Sure, I will use the writel() to replace the mtk_ddp_write_mask().
> > + mtk_ddp_write_mask(NULL, 0, &priv->cmdq_reg, priv->regs,
> > + DISP_REG_OVL_OUTPROC_RST,
> > OVL_OUTPROC_RST);
>
> Some hardware reset before start.
> Some hardware reset after stop.
>
> Could align this?
>
Sure, we will align this part.
> > + mtk_ddp_write(NULL, 0, &priv->cmdq_reg, priv->regs,
> > + DISP_REG_OVL_OUTPROC_INTSTA);
> > + mtk_ddp_write_mask(NULL, OVL_OUTPROC_OVL_EN, &priv-
> > >cmdq_reg, priv->regs,
> > + DISP_REG_OVL_OUTPROC_EN,
> > OVL_OUTPROC_OVL_EN);
> > +}
> > +
> > +void mtk_disp_outproc_stop(struct device *dev)
> > +{
> > + struct mtk_disp_outproc *priv = dev_get_drvdata(dev);
> > +
> > + mtk_ddp_write(NULL, 0, &priv->cmdq_reg, priv->regs,
> > + DISP_REG_OVL_OUTPROC_INTEN);
>
> OVL driver does not disable interrupt when stop.
> Align this with OVL driver.
>
Sure I will check the driver and align this part.
>
//snip
> > +#if IS_REACHABLE(CONFIG_MTK_CMDQ)
> > + ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
> > + if (ret)
> > + dev_dbg(dev, "No mediatek,gce-client-reg\n");
> > +#endif
> > +
> > + if (of_property_read_u32_index(dev->of_node, "interrupts",
> > 0, &ret)) {
> > + dev_dbg(dev, "interrupts not defined\n");
>
> In binding document, interrupt is required.
> So return with error code.
>
The interrupt is not required, I have rewrite the binding document.
> > + } else {
> > + priv->irq = platform_get_irq(pdev, 0);
> > + if (priv->irq < 0)
> > + priv->irq = 0;
>
> In binding document, interrupt is required.
> So return with error code.
>
> Regards,
> CK
>
The interrupt is not required, I have rewrite the binding document.
The next upstream version of patch would fix this problem
Best,
Paul
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 11/12] drm/mediatek: add ovlsys_adaptor support for MT8196
2025-01-10 12:33 [PATCH 00/12] Add Mediatek Soc DRM support for mt8196 paul-pl.chen
` (10 preceding siblings ...)
2025-01-10 12:34 ` [PATCH 10/12] drm/mediatek: add OUTPROC " paul-pl.chen
@ 2025-01-10 12:34 ` paul-pl.chen
2025-02-12 7:09 ` CK Hu (胡俊光)
2025-01-10 12:34 ` [PATCH 12/12] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver paul-pl.chen
2025-01-13 12:50 ` [PATCH 00/12] Add Mediatek Soc DRM support for mt8196 AngeloGioacchino Del Regno
13 siblings, 1 reply; 50+ messages in thread
From: paul-pl.chen @ 2025-01-10 12:34 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
linux-arm-kernel, Project_Global_Chrome_Upstream_Group
From: "Nancy.Lin" <nancy.lin@mediatek.com>
Ovlsys_adaptor is an encapsulated module designed to
simplify the DRM control flow. This module is composed
of 20 EXDMAs, 20 BLENDERs, and 12 OUTPROCs.
Two EXDMAs merge into one layer, allowing the module
to support 20 layers for 3 display paths.
Ovlsys_adaptor driver is integrated within the
mtk_ddp_comp framework.
Signed-off-by: Nancy.Lin <nancy.lin@mediatek.com>
Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
---
drivers/gpu/drm/mediatek/Makefile | 1 +
drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 25 +
drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 1 +
drivers/gpu/drm/mediatek/mtk_disp_drv.h | 31 +-
.../drm/mediatek/mtk_disp_ovlsys_adaptor.c | 758 ++++++++++++++++++
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 61 +-
drivers/gpu/drm/mediatek/mtk_drm_drv.h | 11 +-
7 files changed, 884 insertions(+), 4 deletions(-)
create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
index 9546bc6b7b2e..dedf50860d3f 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -9,6 +9,7 @@ mediatek-drm-y := mtk_crtc.o \
mtk_disp_exdma.o \
mtk_disp_gamma.o \
mtk_disp_merge.o \
+ mtk_disp_ovlsys_adaptor.o \
mtk_disp_ovl.o \
mtk_disp_outproc.o \
mtk_disp_ovl_adaptor.o \
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
index cc780744f060..492b8d965309 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -368,6 +368,28 @@ 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 = {
+ .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_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 +459,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 +492,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 44d2cbe919dc..67f6da59d0de 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
@@ -140,8 +140,8 @@ void mtk_ovl_enable_vblank(struct device *dev);
void mtk_ovl_disable_vblank(struct device *dev);
u32 mtk_ovl_get_blend_modes(struct device *dev);
const u32 *mtk_ovl_get_formats(struct device *dev);
-size_t mtk_ovl_get_num_formats(struct device *dev);
+size_t mtk_ovl_get_num_formats(struct device *dev);
void mtk_ovl_adaptor_add_comp(struct device *dev, struct mtk_mutex *mutex);
void mtk_ovl_adaptor_remove_comp(struct device *dev, struct mtk_mutex *mutex);
bool mtk_ovl_adaptor_is_comp_present(struct device_node *node);
@@ -174,6 +174,35 @@ 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);
+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);
+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..7bce2b7143cb
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
@@ -0,0 +1,758 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021 MediaTek Inc.
+ */
+
+#include <drm/drm_fourcc.h>
+#include <drm/drm_of.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"
+
+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_EXDMA10] = { OVLSYS_ADAPTOR_TYPE_EXDMA, 10, DDP_COMPONENT_ID_MAX},
+ [OVLSYS_ADAPTOR_EXDMA11] = { OVLSYS_ADAPTOR_TYPE_EXDMA, 11, DDP_COMPONENT_ID_MAX},
+ [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_BLENDER0] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 0, DDP_COMPONENT_ID_MAX},
+ [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_BLENDER10] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 10, DDP_COMPONENT_ID_MAX},
+ [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_OUTPROC2] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 2, DDP_COMPONENT_ID_MAX},
+ [OVLSYS_ADAPTOR_OUTPROC3] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 3, DDP_COMPONENT_ID_MAX},
+ [OVLSYS_ADAPTOR_OUTPROC4] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 4, DDP_COMPONENT_ID_MAX},
+ [OVLSYS_ADAPTOR_OUTPROC5] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 5, DDP_COMPONENT_ID_MAX},
+ [OVLSYS_ADAPTOR_OUTPROC6] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 6, DDP_COMPONENT_OVL1_OUTPROC0},
+ [OVLSYS_ADAPTOR_OUTPROC7] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 7, DDP_COMPONENT_ID_MAX},
+ [OVLSYS_ADAPTOR_OUTPROC8] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 8, DDP_COMPONENT_ID_MAX},
+ [OVLSYS_ADAPTOR_OUTPROC9] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 9, DDP_COMPONENT_ID_MAX},
+ [OVLSYS_ADAPTOR_OUTPROC10] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 10, DDP_COMPONENT_ID_MAX},
+ [OVLSYS_ADAPTOR_OUTPROC11] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 11, DDP_COMPONENT_ID_MAX},
+};
+
+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;
+}
+
+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);
+
+ dev_dbg(dev, "%s+ idx:%d, enable:%d, fmt:0x%x\n", __func__, idx,
+ pending->enable, pending->format);
+ dev_dbg(dev, "addr 0x%pad, fb w:%d, {%d,%d,%d,%d}\n",
+ &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);
+ blender = get_comp_by_type_idx(dev, OVLSYS_ADAPTOR_TYPE_BLENDER, idx);
+
+ /* OVLSYS is in 1T2P domain, width needs to be 2 pixels align */
+ align_width = ALIGN_DOWN(pending->width, 2);
+
+ if (!pending->enable || pending->height == 0 || align_width == 0 ||
+ pending->x > priv->max_size || pending->y > priv->max_size) {
+ pending->enable = false;
+ mtk_disp_exdma_stop(exdma, cmdq_pkt);
+ mtk_disp_blender_layer_config(blender, state, cmdq_pkt);
+ return;
+ }
+
+ mtk_disp_exdma_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;
+
+ for (i = 0; i < priv->path_size; i++) {
+ enum mtk_disp_blender_layer blender;
+
+ if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER) {
+ blender_idx++;
+ if (priv->layer_nr == 1)
+ blender = SINGLE_BLENDER;
+ else if (blender_idx == 1)
+ blender = FIRST_BLENDER;
+ else if (blender_idx == priv->layer_nr)
+ blender = LAST_BLENDER;
+ else
+ blender = OTHERS;
+
+ mtk_disp_blender_config(priv->ovl_adaptor_comp[priv->path[i]], w, h,
+ vrefresh, bpc, blender, 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;
+ 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;
+ }
+ }
+
+ 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_BLENDER0;
+
+pwr_err:
+ while (--i >= 0) {
+ comp = priv->ovl_adaptor_comp[i];
+ if (!comp)
+ continue;
+ pm_runtime_put(priv->ovl_adaptor_comp[i]);
+ }
+
+ 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);
+ pm_runtime_put(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]];
+
+ if (!priv->children_bound)
+ return;
+
+ 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]]);
+}
+
+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 const struct mtk_disp_ovlsys_adaptor mt8196_ovlsys_adaptor_driver_data = {
+ .max_size = 8191,
+};
+
+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_drm_ovlsys_private *ovlsys_priv;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, priv);
+
+ ovlsys_priv = pdev->dev.platform_data;
+ priv->mmsys_dev = ovlsys_priv->mmsys_dev;
+ priv->max_size = mt8196_ovlsys_adaptor_driver_data.max_size;
+
+ if (ovlsys_priv->use_path == 0) {
+ priv->path = mt8196_mtk_ovl_main;
+ priv->path_size = ARRAY_SIZE(mt8196_mtk_ovl_main);
+ } else if (ovlsys_priv->use_path == 1) {
+ priv->path = mt8196_mtk_ovl_ext;
+ priv->path_size = ARRAY_SIZE(mt8196_mtk_ovl_ext);
+ } else {
+ 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 27190057bd8e..7526bc38bcc7 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -448,6 +448,28 @@ 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 0;
+
+ if (drv_data->ext_path)
+ for (i = 0; i < drv_data->ext_len; i++)
+ if (drv_data->ext_path[i] == comp_id)
+ return 1;
+ if (drv_data->third_path)
+ for (i = 0; i < drv_data->third_len; i++)
+ if (drv_data->third_path[i] == comp_id)
+ return 2;
+
+ return -1;
+}
+
static int mtk_drm_kms_init(struct drm_device *drm)
{
struct mtk_drm_private *private = drm->dev_private;
@@ -463,8 +485,8 @@ static int mtk_drm_kms_init(struct drm_device *drm)
if (ret)
goto put_mutex_dev;
- drm->mode_config.min_width = 64;
- drm->mode_config.min_height = 64;
+ drm->mode_config.min_width = 1;
+ drm->mode_config.min_height = 1;
/*
* set max width and height as default value(4096x4096).
@@ -1107,6 +1129,40 @@ 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_drm_ovlsys_private 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_drm_ovlsys_private));
+ 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_drm_ovlsys_private ovlsys_priv;
+
+ 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_drm_ovlsys_private));
+ 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);
+ }
+
/* Iterate over sibling DISP function blocks */
for_each_child_of_node(phandle->parent, node) {
enum mtk_ddp_comp_type comp_type;
@@ -1268,6 +1324,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..aa17e743a1d0 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_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.34.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 11/12] drm/mediatek: add ovlsys_adaptor support for MT8196
2025-01-10 12:34 ` [PATCH 11/12] drm/mediatek: add ovlsys_adaptor " paul-pl.chen
@ 2025-02-12 7:09 ` CK Hu (胡俊光)
2025-02-21 12:34 ` Paul-pl Chen (陳柏霖)
0 siblings, 1 reply; 50+ messages in thread
From: CK Hu (胡俊光) @ 2025-02-12 7:09 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: matthias.bgg@gmail.com, treapking@chromium.org,
Singo Chang (張興國),
Project_Global_Chrome_Upstream_Group,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
Jason-JH Lin (林睿祥),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
linux-mediatek@lists.infradead.org,
Sunny Shen (沈姍姍), p.zabel@pengutronix.de,
Sirius Wang (王皓昱),
linux-arm-kernel@lists.infradead.org
Hi, Paul:
On Fri, 2025-01-10 at 20:34 +0800, paul-pl.chen wrote:
> From: "Nancy.Lin" <nancy.lin@mediatek.com>
>
> Ovlsys_adaptor is an encapsulated module designed to
> simplify the DRM control flow. This module is composed
> of 20 EXDMAs, 20 BLENDERs, and 12 OUTPROCs.
> Two EXDMAs merge into one layer, allowing the module
> to support 20 layers for 3 display paths.
> Ovlsys_adaptor driver is integrated within the
> mtk_ddp_comp framework.
>
> Signed-off-by: Nancy.Lin <nancy.lin@mediatek.com>
> Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
> ---
> drivers/gpu/drm/mediatek/Makefile | 1 +
> drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 25 +
> drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 1 +
> drivers/gpu/drm/mediatek/mtk_disp_drv.h | 31 +-
> .../drm/mediatek/mtk_disp_ovlsys_adaptor.c | 758 ++++++++++++++++++
> drivers/gpu/drm/mediatek/mtk_drm_drv.c | 61 +-
> drivers/gpu/drm/mediatek/mtk_drm_drv.h | 11 +-
> 7 files changed, 884 insertions(+), 4 deletions(-)
> create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
>
> diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
> index 9546bc6b7b2e..dedf50860d3f 100644
> --- a/drivers/gpu/drm/mediatek/Makefile
> +++ b/drivers/gpu/drm/mediatek/Makefile
> @@ -9,6 +9,7 @@ mediatek-drm-y := mtk_crtc.o \
> mtk_disp_exdma.o \
> mtk_disp_gamma.o \
> mtk_disp_merge.o \
> + mtk_disp_ovlsys_adaptor.o \
> mtk_disp_ovl.o \
> mtk_disp_outproc.o \
> mtk_disp_ovl_adaptor.o \
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> index cc780744f060..492b8d965309 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> @@ -368,6 +368,28 @@ 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 = {
> + .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_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 +459,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 +492,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 44d2cbe919dc..67f6da59d0de 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h
> @@ -140,8 +140,8 @@ void mtk_ovl_enable_vblank(struct device *dev);
> void mtk_ovl_disable_vblank(struct device *dev);
> u32 mtk_ovl_get_blend_modes(struct device *dev);
> const u32 *mtk_ovl_get_formats(struct device *dev);
> -size_t mtk_ovl_get_num_formats(struct device *dev);
>
> +size_t mtk_ovl_get_num_formats(struct device *dev);
> void mtk_ovl_adaptor_add_comp(struct device *dev, struct mtk_mutex *mutex);
> void mtk_ovl_adaptor_remove_comp(struct device *dev, struct mtk_mutex *mutex);
> bool mtk_ovl_adaptor_is_comp_present(struct device_node *node);
> @@ -174,6 +174,35 @@ 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);
>
> +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);
> +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..7bce2b7143cb
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
> @@ -0,0 +1,758 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2021 MediaTek Inc.
> + */
> +
> +#include <drm/drm_fourcc.h>
> +#include <drm/drm_of.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"
> +#include "mtk_drm_drv.h"
> +
> +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_EXDMA10] = { OVLSYS_ADAPTOR_TYPE_EXDMA, 10, DDP_COMPONENT_ID_MAX},
EXDMA10 has no component id, so just drop OVLSYS_ADAPTOR_EXDMA10.
> + [OVLSYS_ADAPTOR_EXDMA11] = { OVLSYS_ADAPTOR_TYPE_EXDMA, 11, DDP_COMPONENT_ID_MAX},
Ditto.
> + [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_BLENDER0] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 0, DDP_COMPONENT_ID_MAX},
Ditto.
> + [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_BLENDER10] = { OVLSYS_ADAPTOR_TYPE_BLENDER, 10, DDP_COMPONENT_ID_MAX},
Ditto.
> + [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_OUTPROC2] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 2, DDP_COMPONENT_ID_MAX},
> + [OVLSYS_ADAPTOR_OUTPROC3] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 3, DDP_COMPONENT_ID_MAX},
> + [OVLSYS_ADAPTOR_OUTPROC4] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 4, DDP_COMPONENT_ID_MAX},
> + [OVLSYS_ADAPTOR_OUTPROC5] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 5, DDP_COMPONENT_ID_MAX},
Ditto.
> + [OVLSYS_ADAPTOR_OUTPROC6] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 6, DDP_COMPONENT_OVL1_OUTPROC0},
> + [OVLSYS_ADAPTOR_OUTPROC7] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 7, DDP_COMPONENT_ID_MAX},
> + [OVLSYS_ADAPTOR_OUTPROC8] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 8, DDP_COMPONENT_ID_MAX},
> + [OVLSYS_ADAPTOR_OUTPROC9] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 9, DDP_COMPONENT_ID_MAX},
> + [OVLSYS_ADAPTOR_OUTPROC10] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 10, DDP_COMPONENT_ID_MAX},
> + [OVLSYS_ADAPTOR_OUTPROC11] = { OVLSYS_ADAPTOR_TYPE_OUTPROC, 11, DDP_COMPONENT_ID_MAX},
Ditto.
> +};
> +
> +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;
> +}
> +
> +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);
> +
> + dev_dbg(dev, "%s+ idx:%d, enable:%d, fmt:0x%x\n", __func__, idx,
> + pending->enable, pending->format);
> + dev_dbg(dev, "addr 0x%pad, fb w:%d, {%d,%d,%d,%d}\n",
> + &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);
> + blender = get_comp_by_type_idx(dev, OVLSYS_ADAPTOR_TYPE_BLENDER, idx);
> +
> + /* OVLSYS is in 1T2P domain, width needs to be 2 pixels align */
> + align_width = ALIGN_DOWN(pending->width, 2);
align_width is useless, so drop it.
> +
> + if (!pending->enable || pending->height == 0 || align_width == 0 ||
> + pending->x > priv->max_size || pending->y > priv->max_size) {
> + pending->enable = false;
> + mtk_disp_exdma_stop(exdma, cmdq_pkt);
> + mtk_disp_blender_layer_config(blender, state, cmdq_pkt);
> + return;
> + }
> +
> + mtk_disp_exdma_config(exdma, state, cmdq_pkt);
mtk_disp_exdma_config() does something like mtk_ovl_layer_config(), so I would like to rename it to mtk_disp_exdma_layer_config().
> +
> + mtk_disp_blender_layer_config(blender, state, cmdq_pkt);
> +
> + mtk_disp_exdma_start(exdma, cmdq_pkt);
Why call start in layer config?
start should be called in start.
> + mtk_disp_blender_start(blender, cmdq_pkt);
Ditto.
> +}
> +
> +void mtk_ovlsys_adaptor_config(struct device *dev, unsigned int w,
> + unsigned int h, unsigned int vrefresh,
> + unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
> +{
> + struct mtk_disp_ovlsys_adaptor *priv = dev_get_drvdata(dev);
> + int i;
> + int blender_idx = 0;
> +
> + for (i = 0; i < priv->path_size; i++) {
> + enum mtk_disp_blender_layer blender;
> +
> + if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER) {
> + blender_idx++;
> + if (priv->layer_nr == 1)
> + blender = SINGLE_BLENDER;
> + else if (blender_idx == 1)
> + blender = FIRST_BLENDER;
> + else if (blender_idx == priv->layer_nr)
> + blender = LAST_BLENDER;
> + else
> + blender = OTHERS;
> +
> + mtk_disp_blender_config(priv->ovl_adaptor_comp[priv->path[i]], w, h,
> + vrefresh, bpc, blender, cmdq_pkt);
mtk_disp_blender_config(priv->ovl_adaptor_comp[priv->path[i]], w, h,
vrefresh, bpc, blender_idx == 1, blender_idx == priv->layer_nr, 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);
The start never use cmdq, so remove the cmdq parameter.
> + else if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER)
> + mtk_disp_blender_start(priv->ovl_adaptor_comp[priv->path[i]], NULL);
Ditto.
> + 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);
Ditto.
> + else if (get_type(priv->path[i]) == OVLSYS_ADAPTOR_TYPE_BLENDER)
> + mtk_disp_blender_stop(priv->ovl_adaptor_comp[priv->path[i]], NULL);
Ditto.
> + 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;
> + 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);
Refer to mtk_ovl_adaptor_power_on().
This should be done in power_on() callback function.
> + if (ret < 0) {
> + dev_err(dev, "Failed to enable power domain %d, err %d\n", i, ret);
> + goto pwr_err;
> + }
> + }
> +
> + 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_BLENDER0;
> +
> +pwr_err:
> + while (--i >= 0) {
> + comp = priv->ovl_adaptor_comp[i];
> + if (!comp)
> + continue;
> + pm_runtime_put(priv->ovl_adaptor_comp[i]);
> + }
> +
> + 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);
> + pm_runtime_put(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]];
> +
> + if (!priv->children_bound)
In ovl adaptor, it does not check this. So remove this checking.
> + return;
> +
> + 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]]);
> +}
> +
> +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;
ovl adaptor does not check this, why ovlsys need this?
If this is removed, this function is similar to the one in ovl adaptor,
would you try to rewrite this function to be almost the same with the one in ovl adator?
Not merging it, just implement almost the same.
> +
> + 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 const struct mtk_disp_ovlsys_adaptor mt8196_ovlsys_adaptor_driver_data = {
> + .max_size = 8191,
This is the first SoC has ovlsys, so it's not necessary to has driver data.
After other SoC ovlsys is added, then consider to add driver data.
So,
#define OVLSYS_MAX_SIZE 8191
> +};
> +
> +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_drm_ovlsys_private *ovlsys_priv;
> + int ret;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + platform_set_drvdata(pdev, priv);
> +
> + ovlsys_priv = pdev->dev.platform_data;
> + priv->mmsys_dev = ovlsys_priv->mmsys_dev;
> + priv->max_size = mt8196_ovlsys_adaptor_driver_data.max_size;
> +
> + if (ovlsys_priv->use_path == 0) {
> + priv->path = mt8196_mtk_ovl_main;
> + priv->path_size = ARRAY_SIZE(mt8196_mtk_ovl_main);
> + } else if (ovlsys_priv->use_path == 1) {
> + priv->path = mt8196_mtk_ovl_ext;
> + priv->path_size = ARRAY_SIZE(mt8196_mtk_ovl_ext);
> + } else {
> + 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 27190057bd8e..7526bc38bcc7 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -448,6 +448,28 @@ 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 0;
> +
> + if (drv_data->ext_path)
> + for (i = 0; i < drv_data->ext_len; i++)
> + if (drv_data->ext_path[i] == comp_id)
> + return 1;
> + if (drv_data->third_path)
> + for (i = 0; i < drv_data->third_len; i++)
> + if (drv_data->third_path[i] == comp_id)
> + return 2;
> +
> + return -1;
> +}
> +
> static int mtk_drm_kms_init(struct drm_device *drm)
> {
> struct mtk_drm_private *private = drm->dev_private;
> @@ -463,8 +485,8 @@ static int mtk_drm_kms_init(struct drm_device *drm)
> if (ret)
> goto put_mutex_dev;
>
> - drm->mode_config.min_width = 64;
> - drm->mode_config.min_height = 64;
> + drm->mode_config.min_width = 1;
> + drm->mode_config.min_height = 1;
You change other SoC setting.
If 8196 has different setting, query min width/height from ddp component and separate this to another patch.
>
> /*
> * set max width and height as default value(4096x4096).
> @@ -1107,6 +1129,40 @@ 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_drm_ovlsys_private 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_drm_ovlsys_private));
> + 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_drm_ovlsys_private ovlsys_priv;
> +
> + 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_drm_ovlsys_private));
> + 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);
> + }
> +
> /* Iterate over sibling DISP function blocks */
> for_each_child_of_node(phandle->parent, node) {
> enum mtk_ddp_comp_type comp_type;
> @@ -1268,6 +1324,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..aa17e743a1d0 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_drm_ovlsys_private {
ovlsys has its own private data structure.
mtk_ovlsys_platform_data is better.
Regards,
CK
> + 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;
^ permalink raw reply [flat|nested] 50+ messages in thread* Re: [PATCH 11/12] drm/mediatek: add ovlsys_adaptor support for MT8196
2025-02-12 7:09 ` CK Hu (胡俊光)
@ 2025-02-21 12:34 ` Paul-pl Chen (陳柏霖)
0 siblings, 0 replies; 50+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-02-21 12:34 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 (沈姍姍),
Singo Chang (張興國), treapking@chromium.org,
Project_Global_Chrome_Upstream_Group,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
Jason-JH Lin (林睿祥),
linux-kernel@vger.kernel.org,
Nancy Lin (林欣螢),
Xiandong Wang (王先冬), matthias.bgg@gmail.com,
linux-mediatek@lists.infradead.org, p.zabel@pengutronix.de,
Sirius Wang (王皓昱),
linux-arm-kernel@lists.infradead.org
On Wed, 2025-02-12 at 07:09 +0000, CK Hu (胡俊光) wrote:
> Hi, Paul:
>
> On Fri, 2025-01-10 at 20:34 +0800, paul-pl.chen wrote:
> > From: "Nancy.Lin" <nancy.lin@mediatek.com>
> >
> > Ovlsys_adaptor is an encapsulated module designed to
> > simplify the DRM control flow. This module is composed
> > of 20 EXDMAs, 20 BLENDERs, and 12 OUTPROCs.
> > Two EXDMAs merge into one layer, allowing the module
> > to support 20 layers for 3 display paths.
> > Ovlsys_adaptor driver is integrated within the
> > mtk_ddp_comp framework.
> >
> > Signed-off-by: Nancy.Lin <nancy.lin@mediatek.com>
> > Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
> > ---
> > drivers/gpu/drm/mediatek/Makefile | 1 +
> > drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 25 +
> > drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 1 +
> > drivers/gpu/drm/mediatek/mtk_disp_drv.h | 31 +-
> > .../drm/mediatek/mtk_disp_ovlsys_adaptor.c | 758
> > ++++++++++++++++++
> > drivers/gpu/drm/mediatek/mtk_drm_drv.c | 61 +-
> > drivers/gpu/drm/mediatek/mtk_drm_drv.h | 11 +-
> > 7 files changed, 884 insertions(+), 4 deletions(-)
> > create mode 100644
> > drivers/gpu/drm/mediatek/mtk_disp_ovlsys_adaptor.c
> >
> > diff --git a/drivers/gpu/drm/mediatek/Makefile
> > b/drivers/gpu/drm/mediatek/Makefile
> >
//snip
> > +#include "mtk_disp_blender.h"
> > +#include "mtk_disp_drv.h"
> > +#include "mtk_crtc.h"
>
> Alphabetic order.
>
Ok, I will fix this part.
> > +#include "mtk_ddp_comp.h"
> > +#include "mtk_drm_drv.h"
> > +
> > +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_EXDMA10] = { OVLSYS_ADAPTOR_TYPE_EXDMA,
> > 10, DDP_COMPONENT_ID_MAX},
>
> EXDMA10 has no component id, so just drop OVLSYS_ADAPTOR_EXDMA10.
>
OK I will check this part.
> > + [OVLSYS_ADAPTOR_EXDMA11] = { OVLSYS_ADAPTOR_TYPE_EXDMA,
> > 11, DDP_COMPONENT_ID_MAX},
>
> Ditto.
>
OK I will check this part, too.
> > + [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_BLENDER0] = { OVLSYS_ADAPTOR_TYPE_BLENDER,
> > 0, DDP_COMPONENT_ID_MAX},
>
> Ditto.
>
OK I will check this part, too.
> > + [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_BLENDER10] = {
> > OVLSYS_ADAPTOR_TYPE_BLENDER, 10, DDP_COMPONENT_ID_MAX},
>
> Ditto.
>
OK I will check this part, too.
> > + [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_OUTPROC2] = { OVLSYS_ADAPTOR_TYPE_OUTPROC,
> > 2, DDP_COMPONENT_ID_MAX},
> > + [OVLSYS_ADAPTOR_OUTPROC3] = { OVLSYS_ADAPTOR_TYPE_OUTPROC,
> > 3, DDP_COMPONENT_ID_MAX},
> > + [OVLSYS_ADAPTOR_OUTPROC4] = { OVLSYS_ADAPTOR_TYPE_OUTPROC,
> > 4, DDP_COMPONENT_ID_MAX},
> > + [OVLSYS_ADAPTOR_OUTPROC5] = { OVLSYS_ADAPTOR_TYPE_OUTPROC,
> > 5, DDP_COMPONENT_ID_MAX},
>
> Ditto.
>
OK I will check this part, too.
> > + [OVLSYS_ADAPTOR_OUTPROC6] = { OVLSYS_ADAPTOR_TYPE_OUTPROC,
> > 6, DDP_COMPONENT_OVL1_OUTPROC0},
> > + [OVLSYS_ADAPTOR_OUTPROC7] = { OVLSYS_ADAPTOR_TYPE_OUTPROC,
> > 7, DDP_COMPONENT_ID_MAX},
> > + [OVLSYS_ADAPTOR_OUTPROC8] = { OVLSYS_ADAPTOR_TYPE_OUTPROC,
> > 8, DDP_COMPONENT_ID_MAX},
> > + [OVLSYS_ADAPTOR_OUTPROC9] = { OVLSYS_ADAPTOR_TYPE_OUTPROC,
> > 9, DDP_COMPONENT_ID_MAX},
> > + [OVLSYS_ADAPTOR_OUTPROC10] = {
> > OVLSYS_ADAPTOR_TYPE_OUTPROC, 10, DDP_COMPONENT_ID_MAX},
> > + [OVLSYS_ADAPTOR_OUTPROC11] = {
> > OVLSYS_ADAPTOR_TYPE_OUTPROC, 11, DDP_COMPONENT_ID_MAX},
>
> Ditto.
>
OK I will check this part, too.
> > +};
> > +
> > +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;
> > +}
> > +
> > +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);
> > +
> > + dev_dbg(dev, "%s+ idx:%d, enable:%d, fmt:0x%x\n",
> > __func__, idx,
> > + pending->enable, pending->format);
> > + dev_dbg(dev, "addr 0x%pad, fb w:%d, {%d,%d,%d,%d}\n",
> > + &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);
> > + blender = get_comp_by_type_idx(dev,
> > OVLSYS_ADAPTOR_TYPE_BLENDER, idx);
> > +
> > + /* OVLSYS is in 1T2P domain, width needs to be 2 pixels
> > align */
> > + align_width = ALIGN_DOWN(pending->width, 2);
>
> align_width is useless, so drop it.
>
> > +
> > + if (!pending->enable || pending->height == 0 ||
> > align_width == 0 ||
> > + pending->x > priv->max_size || pending->y > priv-
> > >max_size) {
> > + pending->enable = false;
> > + mtk_disp_exdma_stop(exdma, cmdq_pkt);
> > + mtk_disp_blender_layer_config(blender, state,
> > cmdq_pkt);
> > + return;
> > + }
> > +
> > + mtk_disp_exdma_config(exdma, state, cmdq_pkt);
>
> mtk_disp_exdma_config() does something like mtk_ovl_layer_config(),
> so I would like to rename it to mtk_disp_exdma_layer_config().
>
Sure, I will rename the function name.
> > +
> > + mtk_disp_blender_layer_config(blender, state, cmdq_pkt);
> > +
> > + mtk_disp_exdma_start(exdma, cmdq_pkt);
>
> Why call start in layer config?
> start should be called in start.
>
Sure, I will fix the order of setting.
> > + mtk_disp_blender_start(blender, cmdq_pkt);
>
> Ditto.
OK I will check this part, too.
>
> > +}
> > +
> > +void mtk_ovlsys_adaptor_config(struct device *dev, unsigned int w,
> > + unsigned int h, unsigned int
> > vrefresh,
> > + unsigned int bpc, struct cmdq_pkt
> > *cmdq_pkt)
> > +{
> > + struct mtk_disp_ovlsys_adaptor *priv =
> > dev_get_drvdata(dev);
> > + int i;
> > + int blender_idx = 0;
> > +
> > + for (i = 0; i < priv->path_size; i++) {
> > + enum mtk_disp_blender_layer blender;
> > +
> > + if (get_type(priv->path[i]) ==
> > OVLSYS_ADAPTOR_TYPE_BLENDER) {
> > + blender_idx++;
> > + if (priv->layer_nr == 1)
> > + blender = SINGLE_BLENDER;
> > + else if (blender_idx == 1)
> > + blender = FIRST_BLENDER;
> > + else if (blender_idx == priv->layer_nr)
> > + blender = LAST_BLENDER;
> > + else
> > + blender = OTHERS;
> > +
> > + mtk_disp_blender_config(priv-
> > >ovl_adaptor_comp[priv->path[i]], w, h,
> > + vrefresh, bpc,
> > blender, cmdq_pkt);
>
> mtk_disp_blender_config(priv->ovl_adaptor_comp[priv->path[i]], w, h,
> vrefresh, bpc, blender_idx == 1, blender_idx
> == priv->layer_nr, 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);
>
> The start never use cmdq, so remove the cmdq parameter.
Ok, I will fix this part.
>
> > + else if (get_type(priv->path[i]) ==
> > OVLSYS_ADAPTOR_TYPE_BLENDER)
> > + mtk_disp_blender_start(priv-
> > >ovl_adaptor_comp[priv->path[i]], NULL);
>
> Ditto.
>
Ok, I will fix this part.> > + 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);
>
> Ditto.
Ok, I will fix this part.th.
>
> > + else if (get_type(priv->path[i]) ==
> > OVLSYS_ADAPTOR_TYPE_BLENDER)
> > + mtk_disp_blender_stop(priv-
> > >ovl_adaptor_comp[priv->path[i]], NULL);
>
> Ditto.
Ok, I will fix this part.
>
> > + 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;
> > + 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);
>
> Refer to mtk_ovl_adaptor_power_on().
> This should be done in power_on() callback function.
Sure, I will align the power sequence with the function
mtk_ovl_adaptor_power_on().
>
> > + if (ret < 0) {
> > + dev_err(dev, "Failed to enable power
> > domain %d, err %d\n", i, ret);
> > + goto pwr_err;
> > + }
> > + }
> > +
> > + 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_BLENDER0;
> > +
> > +pwr_err:
> > + while (--i >= 0) {
> > + comp = priv->ovl_adaptor_comp[i];
> > + if (!comp)
> > + continue;
> > + pm_runtime_put(priv->ovl_adaptor_comp[i]);
> > + }
> > +
> > + 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);
> > + pm_runtime_put(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]];
> > +
> > + if (!priv->children_bound)
>
> In ovl adaptor, it does not check this. So remove this checking.
This is because of the mt8916's new hardwarew design.
ovlsys adaptor have to find the possible path.
>
> > + return;
> > +
> > + 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]]);
> > +}
> > +
> > +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;
>
> ovl adaptor does not check this, why ovlsys need this?
> If this is removed, this function is similar to the one in ovl
> adaptor,
> would you try to rewrite this function to be almost the same with the
> one in ovl adator?
> Not merging it, just implement almost the same.
This is because of the mt8916's new hardwarew design.
ovlsys adaptor have to find the possible path.
>
> > +
> > + 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 const struct mtk_disp_ovlsys_adaptor
> > mt8196_ovlsys_adaptor_driver_data = {
> > + .max_size = 8191,
>
> This is the first SoC has ovlsys, so it's not necessary to has driver
> data.
> After other SoC ovlsys is added, then consider to add driver data.
> So,
>
> #define OVLSYS_MAX_SIZE 8191
>
> > +};
> > +
> > +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_drm_ovlsys_private *ovlsys_priv;
> > + int ret;
> > +
> > + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> > + if (!priv)
> > + return -ENOMEM;
> > +
> > + platform_set_drvdata(pdev, priv);
> > +
> > + ovlsys_priv = pdev->dev.platform_data;
> > + priv->mmsys_dev = ovlsys_priv->mmsys_dev;
> > + priv->max_size =
> > mt8196_ovlsys_adaptor_driver_data.max_size;
> > +
> > + if (ovlsys_priv->use_path == 0) {
> > + priv->path = mt8196_mtk_ovl_main;
> > + priv->path_size = ARRAY_SIZE(mt8196_mtk_ovl_main);
> > + } else if (ovlsys_priv->use_path == 1) {
> > + priv->path = mt8196_mtk_ovl_ext;
> > + priv->path_size = ARRAY_SIZE(mt8196_mtk_ovl_ext);
> > + } else {
> > + 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 27190057bd8e..7526bc38bcc7 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> > @@ -448,6 +448,28 @@ 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 0;
> > +
> > + if (drv_data->ext_path)
> > + for (i = 0; i < drv_data->ext_len; i++)
> > + if (drv_data->ext_path[i] == comp_id)
> > + return 1;
> > + if (drv_data->third_path)
> > + for (i = 0; i < drv_data->third_len; i++)
> > + if (drv_data->third_path[i] == comp_id)
> > + return 2;
> > +
> > + return -1;
> > +}
> > +
> > static int mtk_drm_kms_init(struct drm_device *drm)
> > {
> > struct mtk_drm_private *private = drm->dev_private;
> > @@ -463,8 +485,8 @@ static int mtk_drm_kms_init(struct drm_device
> > *drm)
> > if (ret)
> > goto put_mutex_dev;
> >
> > - drm->mode_config.min_width = 64;
> > - drm->mode_config.min_height = 64;
> > + drm->mode_config.min_width = 1;
> > + drm->mode_config.min_height = 1;
>
> You change other SoC setting.
> If 8196 has different setting, query min width/height from ddp
> component and separate this to another patch.
>
Ok, I will separate this to another patch.
> >
> > /*
> > * set max width and height as default value(4096x4096).
> > @@ -1107,6 +1129,40 @@ 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_drm_ovlsys_private 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_drm_ovlsys_private));
> > + 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_drm_ovlsys_private ovlsys_priv;
> > +
> > + 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_drm_ovlsys_private));
> > + 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);
> > + }
> > +
> > /* Iterate over sibling DISP function blocks */
> > for_each_child_of_node(phandle->parent, node) {
> > enum mtk_ddp_comp_type comp_type;
> > @@ -1268,6 +1324,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..aa17e743a1d0 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_drm_ovlsys_private {
>
> ovlsys has its own private data structure.
> mtk_ovlsys_platform_data is better.
>
> Regards,
> CK
>
Ok, I will fix this problem.
Best, Paul
>
> > + 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;
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 12/12] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver
2025-01-10 12:33 [PATCH 00/12] Add Mediatek Soc DRM support for mt8196 paul-pl.chen
` (11 preceding siblings ...)
2025-01-10 12:34 ` [PATCH 11/12] drm/mediatek: add ovlsys_adaptor " paul-pl.chen
@ 2025-01-10 12:34 ` paul-pl.chen
2025-02-12 9:30 ` CK Hu (胡俊光)
2025-01-13 12:50 ` [PATCH 00/12] Add Mediatek Soc DRM support for mt8196 AngeloGioacchino Del Regno
13 siblings, 1 reply; 50+ messages in thread
From: paul-pl.chen @ 2025-01-10 12:34 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, chunkuang.hu, angelogioacchino.delregno
Cc: matthias.bgg, p.zabel, jason-jh.lin, nancy.lin, singo.chang,
xiandong.wang, sirius.wang, paul-pl.chen, sunny.shen, fshao,
treapking, devicetree, linux-kernel, dri-devel, linux-mediatek,
linux-arm-kernel, Project_Global_Chrome_Upstream_Group
From: "Nancy.Lin" <nancy.lin@mediatek.com>
To support multiple mmsys instances in the one mediatek-drm instance,
providing improved flexibility and scalability by the following changes:
1. Defined new DRM component IDs DDP_COMPONENT_DRM_OVLSYS_ADAPTOR*
to 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 | 350 +++++++++++++++++++-----
drivers/gpu/drm/mediatek/mtk_crtc.h | 6 +-
drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 106 +++++--
drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 2 +
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 223 ++++++++++++---
drivers/gpu/drm/mediatek/mtk_drm_drv.h | 16 +-
6 files changed, 578 insertions(+), 125 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c
index eb0e1233ad04..eca6941bfaa2 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);
@@ -125,7 +134,9 @@ 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);
@@ -223,7 +234,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;
@@ -232,17 +250,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
@@ -332,7 +361,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;
@@ -362,10 +392,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);
@@ -374,19 +412,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 mutexs in this crtc */
+ for (j = 0; j < MAX_MMSYS; j++)
+ if (mtk_crtc->exist[j] && mtk_crtc->mutex[j])
+ mtk_mutex_write_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];
@@ -394,7 +449,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);
}
@@ -418,7 +477,10 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
return 0;
err_mutex_unprepare:
- 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]);
+
err_pm_runtime_put:
pm_runtime_put(crtc->dev->dev);
return ret;
@@ -430,6 +492,7 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_crtc *mtk_crtc)
struct drm_crtc *crtc = &mtk_crtc->base;
unsigned long flags;
int i;
+ enum mtk_drm_mmsys mmsys;
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
mtk_ddp_comp_stop(mtk_crtc->ddp_comp[i]);
@@ -437,27 +500,46 @@ 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 < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+ mtk_mutex_disable(mtk_crtc->mutex[i]);
+
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);
+
mtk_crtc_ddp_clk_disable(mtk_crtc);
- mtk_mutex_unprepare(mtk_crtc->mutex);
- pm_runtime_put(drm->dev);
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
+ mtk_mutex_unprepare(mtk_crtc->mutex[i]);
+
+ 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);
@@ -581,9 +663,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) {
@@ -659,6 +747,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);
@@ -671,7 +760,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",
@@ -684,6 +774,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;
@@ -720,13 +812,35 @@ 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);
- ret = mtk_ddp_comp_power_on(comp);
- if (ret < 0) {
- DRM_DEV_ERROR(comp->dev, "Failed to enable power domain: %d\n", ret);
- return;
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i])
+ mmsys_cnt++;
+
+ if (mmsys_cnt == 1) {
+ ret = pm_runtime_resume_and_get(comp->dev);
+ if (ret < 0) {
+ DRM_DEV_ERROR(comp->dev, "Failed to enable power domain: %d\n", ret);
+ return;
+ }
+ } else {
+ 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(comp->dev);
+ return;
+ }
+ }
}
mtk_crtc_update_output(crtc, state);
@@ -746,12 +860,17 @@ 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)
return;
+ for (i = 0; i < MAX_MMSYS; i++)
+ if (mtk_crtc->exist[i])
+ mmsys_cnt++;
+
/* Set all pending plane state to disabled */
for (i = 0; i < mtk_crtc->layer_nr; i++) {
struct drm_plane *plane = &mtk_crtc->planes[i];
@@ -776,7 +895,21 @@ static void mtk_crtc_atomic_disable(struct drm_crtc *crtc,
drm_crtc_vblank_off(crtc);
mtk_crtc_ddp_hw_fini(mtk_crtc);
- mtk_ddp_comp_power_off(comp);
+
+ 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);
+ }
+ }
+ } else {
+ ret = pm_runtime_put(comp->dev);
+ if (ret < 0)
+ DRM_DEV_ERROR(comp->dev, "Failed to disable power domain: %d\n", ret);
+ }
mtk_crtc->enabled = false;
}
@@ -937,49 +1070,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;
+ 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;
}
@@ -989,7 +1181,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),
@@ -998,19 +1192,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) {
@@ -1047,8 +1258,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;
@@ -1061,7 +1274,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;
@@ -1101,6 +1314,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];
@@ -1117,6 +1331,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;
@@ -1124,5 +1339,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 492b8d965309..f841184d1e06 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
@@ -464,6 +464,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",
@@ -487,6 +488,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 },
@@ -494,6 +504,9 @@ 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_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 },
@@ -510,7 +523,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 },
@@ -567,12 +583,19 @@ static bool mtk_ddp_path_available(const unsigned int *path,
{
unsigned int i;
+ if (!path_len)
+ return true;
+
if (!path || !path_len)
return false;
for (i = 0U; i < path_len; i++) {
/* OVL_ADAPTOR doesn't have a device node */
- if (path[i] == DDP_COMPONENT_DRM_OVL_ADAPTOR)
+ if (path[i] == DDP_COMPONENT_DRM_OVL_ADAPTOR ||
+ path[i] == DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 ||
+ path[i] == DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 ||
+ path[i] == DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2 ||
+ mtk_ddp_comp_get_type(path[i]) == MTK_DISP_VIRTUAL)
continue;
if (!comp_node[path[i]])
@@ -597,44 +620,81 @@ 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;
+ int i = 0, j, count = 0;
+ bool found = false;
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++;
- }
+ priv_n->comp_node))
+ count++;
+
+ if (mtk_ddp_comp_find(dev, data->main_path, data->main_len,
+ priv_n->ddp_comp))
+ found = true;
+ }
+
+ if (count == private->data->mmsys_dev_num) {
+ if (found)
+ return BIT(i);
+ i++;
+ }
+
+ count = 0;
+ found = false;
+
+ 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->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++;
- }
+ priv_n->comp_node))
+ count++;
+
+ if (mtk_ddp_comp_find(dev, data->ext_path, data->ext_len,
+ priv_n->ddp_comp))
+ found = true;
+ }
+
+ if (count == private->data->mmsys_dev_num) {
+ if (found)
+ return BIT(i);
+ i++;
+ }
+
+ count = 0;
+ found = false;
+
+ 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->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++;
- }
+ priv_n->comp_node))
+ count++;
+
+ if (mtk_ddp_comp_find(dev, data->third_path, data->third_len,
+ priv_n->ddp_comp))
+ found = true;
+ }
+
+ if (count == private->data->mmsys_dev_num) {
+ if (found)
+ return BIT(i);
+ i++;
}
ret = mtk_ddp_comp_find_in_route(dev,
diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
index ef64ce7a071f..badb42bd4f7c 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
@@ -40,6 +40,7 @@ enum mtk_ddp_comp_type {
MTK_DISP_PWM,
MTK_DISP_RDMA,
MTK_DISP_UFOE,
+ MTK_DISP_VIRTUAL,
MTK_DISP_WDMA,
MTK_DPI,
MTK_DP_INTF,
@@ -47,6 +48,7 @@ enum mtk_ddp_comp_type {
MTK_OVL_BLENDER,
MTK_OVL_EXDMA,
MTK_OVL_OUTPROC,
+ MTK_VDISP_AO,
MTK_DDP_COMP_TYPE_MAX,
};
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 7526bc38bcc7..0665a6feb546 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,6 +375,67 @@ static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data = {
.min_height = 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[] = {
{ .compatible = "mediatek,mt2701-mmsys",
.data = &mt2701_mmsys_driver_data},
@@ -354,6 +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,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);
@@ -368,7 +485,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;
@@ -395,23 +512,18 @@ 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)
break;
}
if (drm_priv->data->mmsys_dev_num == cnt) {
- for (i = 0; i < cnt; i++)
- for (j = 0; j < cnt; j++)
+ for (i = 0; i < MAX_MMSYS; i++)
+ for (j = 0; j < MAX_MMSYS; j++)
all_drm_priv[j]->all_drm_private[i] = all_drm_priv[i];
return true;
@@ -498,7 +610,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)
@@ -521,8 +636,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;
@@ -534,28 +651,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;
}
}
}
@@ -574,8 +686,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
@@ -593,11 +706,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;
}
@@ -661,6 +776,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;
@@ -673,8 +801,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)
@@ -771,6 +900,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
.data = (void *)MTK_DISP_MUTEX },
{ .compatible = "mediatek,mt8195-disp-mutex",
.data = (void *)MTK_DISP_MUTEX },
+ { .compatible = "mediatek,mt8196-disp-mutex",
+ .data = (void *)MTK_DISP_MUTEX },
{ .compatible = "mediatek,mt8173-disp-od",
.data = (void *)MTK_DISP_OD },
{ .compatible = "mediatek,mt2701-disp-ovl",
@@ -837,6 +968,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
.data = (void *)MTK_DSI },
{ .compatible = "mediatek,mt8188-dsi",
.data = (void *)MTK_DSI },
+ { .compatible = "mediatek,mt8196-vdisp-ao",
+ .data = (void *)MTK_VDISP_AO },
{ }
};
@@ -1111,7 +1244,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)
@@ -1163,6 +1296,22 @@ 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_ADAPTOR2)) {
+ struct mtk_drm_ovlsys_private 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_drm_ovlsys_private));
+ 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;
@@ -1189,6 +1338,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",
@@ -1241,6 +1396,9 @@ static int mtk_drm_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, private);
+ if (!match)
+ drm_of_component_match_add(dev, &match, component_compare_of, NULL);
+
ret = component_master_add_with_match(dev, &mtk_drm_ops, match);
if (ret)
goto err_pm;
@@ -1264,6 +1422,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 aa17e743a1d0..36cfbfa30ff2 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.34.1
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 12/12] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver
2025-01-10 12:34 ` [PATCH 12/12] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver paul-pl.chen
@ 2025-02-12 9:30 ` CK Hu (胡俊光)
2025-02-21 12:39 ` Paul-pl Chen (陳柏霖)
0 siblings, 1 reply; 50+ messages in thread
From: CK Hu (胡俊光) @ 2025-02-12 9:30 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: matthias.bgg@gmail.com, treapking@chromium.org,
Singo Chang (張興國),
Project_Global_Chrome_Upstream_Group,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
Jason-JH Lin (林睿祥),
Nancy Lin (林欣螢),
Xiandong Wang (王先冬),
linux-mediatek@lists.infradead.org,
Sunny Shen (沈姍姍), p.zabel@pengutronix.de,
Sirius Wang (王皓昱),
linux-arm-kernel@lists.infradead.org
Hi, Paul:
On Fri, 2025-01-10 at 20:34 +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. Defined new DRM component IDs DDP_COMPONENT_DRM_OVLSYS_ADAPTOR*
> to 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.
I think the title would confuse me.
Original mediatek-drm driver already support multiple mmsys.
I try to understand MT8196 display.
Is one display pipeline separated into two mmsys?
The first is ovlsys and the second is dispsys?
If so, I would like mediatek-drm driver see only mmsys (dispsys),
and let ovlsys control is hidden in ovlsys sub driver, so mediatek-drm driver would not change so much.
>
> 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 | 350 +++++++++++++++++++-----
> drivers/gpu/drm/mediatek/mtk_crtc.h | 6 +-
> drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 106 +++++--
> drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 2 +
> drivers/gpu/drm/mediatek/mtk_drm_drv.c | 223 ++++++++++++---
> drivers/gpu/drm/mediatek/mtk_drm_drv.h | 16 +-
> 6 files changed, 578 insertions(+), 125 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c
> index eb0e1233ad04..eca6941bfaa2 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);
> @@ -125,7 +134,9 @@ 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);
> @@ -223,7 +234,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;
> @@ -232,17 +250,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
> @@ -332,7 +361,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;
> @@ -362,10 +392,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);
> @@ -374,19 +412,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 mutexs in this crtc */
> + for (j = 0; j < MAX_MMSYS; j++)
> + if (mtk_crtc->exist[j] && mtk_crtc->mutex[j])
> + mtk_mutex_write_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];
> @@ -394,7 +449,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);
> }
>
> @@ -418,7 +477,10 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc)
> return 0;
>
> err_mutex_unprepare:
> - 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]);
> +
> err_pm_runtime_put:
> pm_runtime_put(crtc->dev->dev);
> return ret;
> @@ -430,6 +492,7 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_crtc *mtk_crtc)
> struct drm_crtc *crtc = &mtk_crtc->base;
> unsigned long flags;
> int i;
> + enum mtk_drm_mmsys mmsys;
>
> for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
> mtk_ddp_comp_stop(mtk_crtc->ddp_comp[i]);
> @@ -437,27 +500,46 @@ 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 < MAX_MMSYS; i++)
> + if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
> + mtk_mutex_disable(mtk_crtc->mutex[i]);
> +
> 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);
> +
> mtk_crtc_ddp_clk_disable(mtk_crtc);
> - mtk_mutex_unprepare(mtk_crtc->mutex);
>
> - pm_runtime_put(drm->dev);
> + for (i = 0; i < MAX_MMSYS; i++)
> + if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
> + mtk_mutex_unprepare(mtk_crtc->mutex[i]);
> +
> + 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);
> @@ -581,9 +663,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) {
> @@ -659,6 +747,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);
> @@ -671,7 +760,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",
> @@ -684,6 +774,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;
> @@ -720,13 +812,35 @@ 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);
>
> - ret = mtk_ddp_comp_power_on(comp);
> - if (ret < 0) {
> - DRM_DEV_ERROR(comp->dev, "Failed to enable power domain: %d\n", ret);
> - return;
> + for (i = 0; i < MAX_MMSYS; i++)
> + if (mtk_crtc->exist[i])
> + mmsys_cnt++;
> +
> + if (mmsys_cnt == 1) {
> + ret = pm_runtime_resume_and_get(comp->dev);
> + if (ret < 0) {
> + DRM_DEV_ERROR(comp->dev, "Failed to enable power domain: %d\n", ret);
> + return;
> + }
> + } else {
> + 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(comp->dev);
> + return;
> + }
> + }
> }
>
> mtk_crtc_update_output(crtc, state);
> @@ -746,12 +860,17 @@ 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)
> return;
>
> + for (i = 0; i < MAX_MMSYS; i++)
> + if (mtk_crtc->exist[i])
> + mmsys_cnt++;
> +
> /* Set all pending plane state to disabled */
> for (i = 0; i < mtk_crtc->layer_nr; i++) {
> struct drm_plane *plane = &mtk_crtc->planes[i];
> @@ -776,7 +895,21 @@ static void mtk_crtc_atomic_disable(struct drm_crtc *crtc,
>
> drm_crtc_vblank_off(crtc);
> mtk_crtc_ddp_hw_fini(mtk_crtc);
> - mtk_ddp_comp_power_off(comp);
> +
> + 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);
> + }
> + }
> + } else {
> + ret = pm_runtime_put(comp->dev);
> + if (ret < 0)
> + DRM_DEV_ERROR(comp->dev, "Failed to disable power domain: %d\n", ret);
> + }
>
> mtk_crtc->enabled = false;
> }
> @@ -937,49 +1070,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;
> + 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;
> }
> @@ -989,7 +1181,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),
> @@ -998,19 +1192,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) {
> @@ -1047,8 +1258,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;
> @@ -1061,7 +1274,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;
> @@ -1101,6 +1314,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];
> @@ -1117,6 +1331,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;
>
> @@ -1124,5 +1339,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 492b8d965309..f841184d1e06 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> @@ -464,6 +464,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",
> @@ -487,6 +488,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 },
> @@ -494,6 +504,9 @@ 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_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 },
> @@ -510,7 +523,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 },
> @@ -567,12 +583,19 @@ static bool mtk_ddp_path_available(const unsigned int *path,
> {
> unsigned int i;
>
> + if (!path_len)
> + return true;
> +
> if (!path || !path_len)
> return false;
>
> for (i = 0U; i < path_len; i++) {
> /* OVL_ADAPTOR doesn't have a device node */
> - if (path[i] == DDP_COMPONENT_DRM_OVL_ADAPTOR)
> + if (path[i] == DDP_COMPONENT_DRM_OVL_ADAPTOR ||
> + path[i] == DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0 ||
> + path[i] == DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 ||
> + path[i] == DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2 ||
> + mtk_ddp_comp_get_type(path[i]) == MTK_DISP_VIRTUAL)
> continue;
>
> if (!comp_node[path[i]])
> @@ -597,44 +620,81 @@ 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;
> + int i = 0, j, count = 0;
> + bool found = false;
>
> 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++;
> - }
> + priv_n->comp_node))
> + count++;
> +
> + if (mtk_ddp_comp_find(dev, data->main_path, data->main_len,
> + priv_n->ddp_comp))
> + found = true;
> + }
> +
> + if (count == private->data->mmsys_dev_num) {
> + if (found)
> + return BIT(i);
> + i++;
> + }
> +
> + count = 0;
> + found = false;
> +
> + 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->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++;
> - }
> + priv_n->comp_node))
> + count++;
> +
> + if (mtk_ddp_comp_find(dev, data->ext_path, data->ext_len,
> + priv_n->ddp_comp))
> + found = true;
> + }
> +
> + if (count == private->data->mmsys_dev_num) {
> + if (found)
> + return BIT(i);
> + i++;
> + }
> +
> + count = 0;
> + found = false;
> +
> + 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->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++;
> - }
> + priv_n->comp_node))
> + count++;
> +
> + if (mtk_ddp_comp_find(dev, data->third_path, data->third_len,
> + priv_n->ddp_comp))
> + found = true;
> + }
> +
> + if (count == private->data->mmsys_dev_num) {
> + if (found)
> + return BIT(i);
> + i++;
> }
>
> ret = mtk_ddp_comp_find_in_route(dev,
> diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> index ef64ce7a071f..badb42bd4f7c 100644
> --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> @@ -40,6 +40,7 @@ enum mtk_ddp_comp_type {
> MTK_DISP_PWM,
> MTK_DISP_RDMA,
> MTK_DISP_UFOE,
> + MTK_DISP_VIRTUAL,
> MTK_DISP_WDMA,
> MTK_DPI,
> MTK_DP_INTF,
> @@ -47,6 +48,7 @@ enum mtk_ddp_comp_type {
> MTK_OVL_BLENDER,
> MTK_OVL_EXDMA,
> MTK_OVL_OUTPROC,
> + MTK_VDISP_AO,
> MTK_DDP_COMP_TYPE_MAX,
> };
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index 7526bc38bcc7..0665a6feb546 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,
> +};
Separate MT8196 part to another patch which add support MT8196.
Let this patch not related to specific SoC.
Regards,
CK
> +
> +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,6 +375,67 @@ static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data = {
> .min_height = 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[] = {
> { .compatible = "mediatek,mt2701-mmsys",
> .data = &mt2701_mmsys_driver_data},
> @@ -354,6 +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,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);
> @@ -368,7 +485,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;
> @@ -395,23 +512,18 @@ 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)
> break;
> }
>
> if (drm_priv->data->mmsys_dev_num == cnt) {
> - for (i = 0; i < cnt; i++)
> - for (j = 0; j < cnt; j++)
> + for (i = 0; i < MAX_MMSYS; i++)
> + for (j = 0; j < MAX_MMSYS; j++)
> all_drm_priv[j]->all_drm_private[i] = all_drm_priv[i];
>
> return true;
> @@ -498,7 +610,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)
> @@ -521,8 +636,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;
> @@ -534,28 +651,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;
> }
> }
> }
> @@ -574,8 +686,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
> @@ -593,11 +706,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;
> }
> @@ -661,6 +776,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;
>
> @@ -673,8 +801,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)
> @@ -771,6 +900,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
> .data = (void *)MTK_DISP_MUTEX },
> { .compatible = "mediatek,mt8195-disp-mutex",
> .data = (void *)MTK_DISP_MUTEX },
> + { .compatible = "mediatek,mt8196-disp-mutex",
> + .data = (void *)MTK_DISP_MUTEX },
> { .compatible = "mediatek,mt8173-disp-od",
> .data = (void *)MTK_DISP_OD },
> { .compatible = "mediatek,mt2701-disp-ovl",
> @@ -837,6 +968,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
> .data = (void *)MTK_DSI },
> { .compatible = "mediatek,mt8188-dsi",
> .data = (void *)MTK_DSI },
> + { .compatible = "mediatek,mt8196-vdisp-ao",
> + .data = (void *)MTK_VDISP_AO },
> { }
> };
>
> @@ -1111,7 +1244,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)
> @@ -1163,6 +1296,22 @@ 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_ADAPTOR2)) {
> + struct mtk_drm_ovlsys_private 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_drm_ovlsys_private));
> + 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;
> @@ -1189,6 +1338,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",
> @@ -1241,6 +1396,9 @@ static int mtk_drm_probe(struct platform_device *pdev)
>
> platform_set_drvdata(pdev, private);
>
> + if (!match)
> + drm_of_component_match_add(dev, &match, component_compare_of, NULL);
> +
> ret = component_master_add_with_match(dev, &mtk_drm_ops, match);
> if (ret)
> goto err_pm;
> @@ -1264,6 +1422,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 aa17e743a1d0..36cfbfa30ff2 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;
^ permalink raw reply [flat|nested] 50+ messages in thread* Re: [PATCH 12/12] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver
2025-02-12 9:30 ` CK Hu (胡俊光)
@ 2025-02-21 12:39 ` Paul-pl Chen (陳柏霖)
0 siblings, 0 replies; 50+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-02-21 12:39 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 (沈姍姍),
Singo Chang (張興國), treapking@chromium.org,
Project_Global_Chrome_Upstream_Group,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
Jason-JH Lin (林睿祥),
linux-kernel@vger.kernel.org,
Nancy Lin (林欣螢),
Xiandong Wang (王先冬), matthias.bgg@gmail.com,
linux-mediatek@lists.infradead.org, p.zabel@pengutronix.de,
Sirius Wang (王皓昱),
linux-arm-kernel@lists.infradead.org
On Wed, 2025-02-12 at 09:30 +0000, CK Hu (胡俊光) wrote:
> Hi, Paul:
>
> On Fri, 2025-01-10 at 20:34 +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. Defined new DRM component IDs DDP_COMPONENT_DRM_OVLSYS_ADAPTOR*
> > to 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.
>
> I think the title would confuse me.
> Original mediatek-drm driver already support multiple mmsys.
> I try to understand MT8196 display.
> Is one display pipeline separated into two mmsys?
> The first is ovlsys and the second is dispsys?
> If so, I would like mediatek-drm driver see only mmsys (dispsys),
> and let ovlsys control is hidden in ovlsys sub driver, so mediatek-
> drm driver would not change so much.
>
> >
> > 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 | 350 +++++++++++++++++++-
> > ----
> > drivers/gpu/drm/mediatek/mtk_crtc.h | 6 +-
> > drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 106 +++++--
> > drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 2 +
> > drivers/gpu/drm/mediatek/mtk_drm_drv.c | 223 ++++++++++++---
> > drivers/gpu/drm/mediatek/mtk_drm_drv.h | 16 +-
> > 6 files changed, 578 insertions(+), 125 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c
> > b/drivers/gpu/drm/mediatek/mtk_crtc.c
> > index eb0e1233ad04..eca6941bfaa2 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);
> > @@ -125,7 +134,9 @@ 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);
> > @@ -223,7 +234,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;
> > @@ -232,17 +250,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
> > @@ -332,7 +361,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;
> > @@ -362,10 +392,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);
> > @@ -374,19 +412,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 mutexs in this
> > crtc */
> > + for (j = 0; j < MAX_MMSYS; j++)
> > + if (mtk_crtc->exist[j] && mtk_crtc->mutex[j])
> > + mtk_mutex_write_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];
> > @@ -394,7 +449,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);
> > }
> >
> > @@ -418,7 +477,10 @@ static int mtk_crtc_ddp_hw_init(struct
> > mtk_crtc *mtk_crtc)
> > return 0;
> >
> > err_mutex_unprepare:
> > - 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]);
> > +
> > err_pm_runtime_put:
> > pm_runtime_put(crtc->dev->dev);
> > return ret;
> > @@ -430,6 +492,7 @@ static void mtk_crtc_ddp_hw_fini(struct
> > mtk_crtc *mtk_crtc)
> > struct drm_crtc *crtc = &mtk_crtc->base;
> > unsigned long flags;
> > int i;
> > + enum mtk_drm_mmsys mmsys;
> >
> > for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
> > mtk_ddp_comp_stop(mtk_crtc->ddp_comp[i]);
> > @@ -437,27 +500,46 @@ 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 < MAX_MMSYS; i++)
> > + if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
> > + mtk_mutex_disable(mtk_crtc->mutex[i]);
> > +
> > 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);
> > +
> > mtk_crtc_ddp_clk_disable(mtk_crtc);
> > - mtk_mutex_unprepare(mtk_crtc->mutex);
> >
> > - pm_runtime_put(drm->dev);
> > + for (i = 0; i < MAX_MMSYS; i++)
> > + if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
> > + mtk_mutex_unprepare(mtk_crtc->mutex[i]);
> > +
> > + 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);
> > @@ -581,9 +663,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) {
> > @@ -659,6 +747,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);
> > @@ -671,7 +760,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",
> > @@ -684,6 +774,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;
> > @@ -720,13 +812,35 @@ 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);
> >
> > - ret = mtk_ddp_comp_power_on(comp);
> > - if (ret < 0) {
> > - DRM_DEV_ERROR(comp->dev, "Failed to enable power
> > domain: %d\n", ret);
> > - return;
> > + for (i = 0; i < MAX_MMSYS; i++)
> > + if (mtk_crtc->exist[i])
> > + mmsys_cnt++;
> > +
> > + if (mmsys_cnt == 1) {
> > + ret = pm_runtime_resume_and_get(comp->dev);
> > + if (ret < 0) {
> > + DRM_DEV_ERROR(comp->dev, "Failed to enable
> > power domain: %d\n", ret);
> > + return;
> > + }
> > + } else {
> > + 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(com
> > p->dev);
> > + return;
> > + }
> > + }
> > }
> >
> > mtk_crtc_update_output(crtc, state);
> > @@ -746,12 +860,17 @@ 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)
> > return;
> >
> > + for (i = 0; i < MAX_MMSYS; i++)
> > + if (mtk_crtc->exist[i])
> > + mmsys_cnt++;
> > +
> > /* Set all pending plane state to disabled */
> > for (i = 0; i < mtk_crtc->layer_nr; i++) {
> > struct drm_plane *plane = &mtk_crtc->planes[i];
> > @@ -776,7 +895,21 @@ static void mtk_crtc_atomic_disable(struct
> > drm_crtc *crtc,
> >
> > drm_crtc_vblank_off(crtc);
> > mtk_crtc_ddp_hw_fini(mtk_crtc);
> > - mtk_ddp_comp_power_off(comp);
> > +
> > + 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);
> > + }
> > + }
> > + } else {
> > + ret = pm_runtime_put(comp->dev);
> > + if (ret < 0)
> > + DRM_DEV_ERROR(comp->dev, "Failed to
> > disable power domain: %d\n", ret);
> > + }
> >
> > mtk_crtc->enabled = false;
> > }
> > @@ -937,49 +1070,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;
> > + 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;
> > }
> > @@ -989,7 +1181,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),
> > @@ -998,19 +1192,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) {
> > @@ -1047,8 +1258,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;
> > @@ -1061,7 +1274,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;
> > @@ -1101,6 +1314,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];
> > @@ -1117,6 +1331,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;
> >
> > @@ -1124,5 +1339,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 492b8d965309..f841184d1e06 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > @@ -464,6 +464,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",
> > @@ -487,6 +488,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 },
> > @@ -494,6 +504,9 @@ 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_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 },
> > @@ -510,7 +523,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 },
> > @@ -567,12 +583,19 @@ static bool mtk_ddp_path_available(const
> > unsigned int *path,
> > {
> > unsigned int i;
> >
> > + if (!path_len)
> > + return true;
> > +
> > if (!path || !path_len)
> > return false;
> >
> > for (i = 0U; i < path_len; i++) {
> > /* OVL_ADAPTOR doesn't have a device node */
> > - if (path[i] == DDP_COMPONENT_DRM_OVL_ADAPTOR)
> > + if (path[i] == DDP_COMPONENT_DRM_OVL_ADAPTOR ||
> > + path[i] == DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0
> > ||
> > + path[i] ==
> > DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 ||
> > + path[i] ==
> > DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2 ||
> > + mtk_ddp_comp_get_type(path[i]) ==
> > MTK_DISP_VIRTUAL)
> > continue;
> >
> > if (!comp_node[path[i]])
> > @@ -597,44 +620,81 @@ 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;
> > + int i = 0, j, count = 0;
> > + bool found = false;
> >
> > 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++;
> > - }
> > + priv_n->comp_node))
> > + count++;
> > +
> > + if (mtk_ddp_comp_find(dev, data->main_path, data-
> > >main_len,
> > + priv_n->ddp_comp))
> > + found = true;
> > + }
> > +
> > + if (count == private->data->mmsys_dev_num) {
> > + if (found)
> > + return BIT(i);
> > + i++;
> > + }
> > +
> > + count = 0;
> > + found = false;
> > +
> > + 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->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++;
> > - }
> > + priv_n->comp_node))
> > + count++;
> > +
> > + if (mtk_ddp_comp_find(dev, data->ext_path, data-
> > >ext_len,
> > + priv_n->ddp_comp))
> > + found = true;
> > + }
> > +
> > + if (count == private->data->mmsys_dev_num) {
> > + if (found)
> > + return BIT(i);
> > + i++;
> > + }
> > +
> > + count = 0;
> > + found = false;
> > +
> > + 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->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++;
> > - }
> > + priv_n->comp_node))
> > + count++;
> > +
> > + if (mtk_ddp_comp_find(dev, data->third_path, data-
> > >third_len,
> > + priv_n->ddp_comp))
> > + found = true;
> > + }
> > +
> > + if (count == private->data->mmsys_dev_num) {
> > + if (found)
> > + return BIT(i);
> > + i++;
> > }
> >
> > ret = mtk_ddp_comp_find_in_route(dev,
> > diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > index ef64ce7a071f..badb42bd4f7c 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > @@ -40,6 +40,7 @@ enum mtk_ddp_comp_type {
> > MTK_DISP_PWM,
> > MTK_DISP_RDMA,
> > MTK_DISP_UFOE,
> > + MTK_DISP_VIRTUAL,
> > MTK_DISP_WDMA,
> > MTK_DPI,
> > MTK_DP_INTF,
> > @@ -47,6 +48,7 @@ enum mtk_ddp_comp_type {
> > MTK_OVL_BLENDER,
> > MTK_OVL_EXDMA,
> > MTK_OVL_OUTPROC,
> > + MTK_VDISP_AO,
> > MTK_DDP_COMP_TYPE_MAX,
> > };
> >
> > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> > b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> > index 7526bc38bcc7..0665a6feb546 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,
> > +};
>
> Separate MT8196 part to another patch which add support MT8196.
> Let this patch not related to specific SoC.
>
> Regards,
> CK
Sure, I will separate this patch to 2 part, first patch is to supprt
the multiple MMSYS for mediatek drm driver. Second patch is to support
MT8196 SOC.
Best,
Paul
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 00/12] Add Mediatek Soc DRM support for mt8196
2025-01-10 12:33 [PATCH 00/12] Add Mediatek Soc DRM support for mt8196 paul-pl.chen
` (12 preceding siblings ...)
2025-01-10 12:34 ` [PATCH 12/12] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver paul-pl.chen
@ 2025-01-13 12:50 ` AngeloGioacchino Del Regno
2025-01-15 8:05 ` Paul-pl Chen (陳柏霖)
13 siblings, 1 reply; 50+ messages in thread
From: AngeloGioacchino Del Regno @ 2025-01-13 12:50 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 10/01/25 13:33, paul-pl.chen ha scritto:
> From: "Paul-pl.Chen" <paul-pl.chen@mediatek.com>
>
> Add support multiple mmsys instances in the one mediatek-drm instance.
>
Hello Paul,
EXDMA, BLENDER and OUTPROC seem to have many things in common with the current
mtk_disp_ovl.c driver.
Please commonize code from mtk_disp_ovl to reuse in these three components that
you're adding, as there is a lot of code duplication.
Thanks,
Angelo
> Nancy.Lin (7):
> soc: mediatek: add mmsys support for MT8196
> soc: mediatek: mutex: add mutex support for MT8196
> 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
>
> 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 | 50 ++
> .../display/mediatek/mediatek,exdma.yaml | 77 ++
> .../display/mediatek/mediatek,outproc.yaml | 57 ++
> .../bindings/soc/mediatek/mediatek,mutex.yaml | 2 +
> drivers/gpu/drm/mediatek/Makefile | 4 +
> drivers/gpu/drm/mediatek/mtk_crtc.c | 350 ++++++--
> drivers/gpu/drm/mediatek/mtk_crtc.h | 6 +-
> drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 134 +++-
> drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 6 +
> drivers/gpu/drm/mediatek/mtk_disp_blender.c | 352 ++++++++
> drivers/gpu/drm/mediatek/mtk_disp_blender.h | 17 +
> drivers/gpu/drm/mediatek/mtk_disp_drv.h | 66 +-
> drivers/gpu/drm/mediatek/mtk_disp_exdma.c | 447 +++++++++++
> drivers/gpu/drm/mediatek/mtk_disp_outproc.c | 244 ++++++
> drivers/gpu/drm/mediatek/mtk_disp_outproc.h | 22 +
> .../drm/mediatek/mtk_disp_ovlsys_adaptor.c | 758 ++++++++++++++++++
> drivers/gpu/drm/mediatek/mtk_drm_drv.c | 287 ++++++-
> drivers/gpu/drm/mediatek/mtk_drm_drv.h | 28 +-
> drivers/soc/mediatek/mt8196-mmsys.h | 447 +++++++++++
> drivers/soc/mediatek/mtk-mmsys.c | 204 ++++-
> drivers/soc/mediatek/mtk-mmsys.h | 18 +
> drivers/soc/mediatek/mtk-mutex.c | 233 +++++-
> include/linux/soc/mediatek/mtk-mmsys.h | 60 ++
> include/linux/soc/mediatek/mtk-mutex.h | 2 +
> 25 files changed, 3734 insertions(+), 142 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,blender.yaml
> create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,exdma.yaml
> create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,outproc.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_ovlsys_adaptor.c
> create mode 100644 drivers/soc/mediatek/mt8196-mmsys.h
>
^ permalink raw reply [flat|nested] 50+ messages in thread* Re: [PATCH 00/12] Add Mediatek Soc DRM support for mt8196
2025-01-13 12:50 ` [PATCH 00/12] Add Mediatek Soc DRM support for mt8196 AngeloGioacchino Del Regno
@ 2025-01-15 8:05 ` Paul-pl Chen (陳柏霖)
0 siblings, 0 replies; 50+ messages in thread
From: Paul-pl Chen (陳柏霖) @ 2025-01-15 8:05 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
On Mon, 2025-01-13 at 13:50 +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 10/01/25 13:33, paul-pl.chen ha scritto:
> > From: "Paul-pl.Chen" <paul-pl.chen@mediatek.com>
> >
> > Add support multiple mmsys instances in the one mediatek-drm
> > instance.
> >
>
> Hello Paul,
>
> EXDMA, BLENDER and OUTPROC seem to have many things in common with
> the current
> mtk_disp_ovl.c driver.
>
> Please commonize code from mtk_disp_ovl to reuse in these three
> components that
> you're adding, as there is a lot of code duplication.
>
Hi Angelo,
Thanks for the review and feedback.
In this patch, we have separated the new EXDMA, BLENDER, and OUTPROC
from the original OVL hardware IP.
While EXDMA, BLENDER, OUTPROC, and OVL share similar functionalities,
they are fundamentally independent hardware components with distinct
register bases and offsets.
Merging them into a single driver would introduce unnecessary
complexity due to these differences,
making maintenance and future development more challenging. For
eample:
1. Register Differences:
Taking EXDMA and OVL as an example:
OVL:// OVL Reset Register #define DISP_REG_OVL_RST 0x0014
EXDMA:// EXDMA Reset Register #define DISP_REG_OVL_RST 0x0024
Although the macro names are similar, the register addresses differ.
This means that any operation involving these registers must account
for different base addresses and offsets.
2. Function Implementation Variations:
These register differences impact function implementations:
OVL Function:
mtk_ovl_config();
EXDMA Function:
mtk_disp_exdma_stop();
Integrating these functions would necessitate conditional logic to
handle the different registers and behaviors,
leading to less readable and maintainable code.
Best, Paul
> Thanks,
> Angelo
//snip
^ permalink raw reply [flat|nested] 50+ messages in thread