* [PATCH 01/10] dt-bindings: display: ti: Move ti,am62l-dss binding to a new binding file
2026-09-03 12:09 [PATCH 00/10] drm/tidss: Preparation for AM62P and BeagleY-AI display support Tomi Valkeinen
@ 2026-09-03 12:09 ` Tomi Valkeinen
2026-09-03 12:09 ` [PATCH 02/10] dt-bindings: display: ti,am65x-dss: Simplify binding Tomi Valkeinen
` (8 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Tomi Valkeinen @ 2026-09-03 12:09 UTC (permalink / raw)
To: Devarsh Thakkar, Swamil Jain, Jyri Sarha, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Tomi Valkeinen, dri-devel, devicetree, linux-kernel,
Tomi Valkeinen
We currently have two binding files for different TI K3 DSS versions:
ti,j721e-dss.yaml which contains bindings for the "full" DSS version,
with four planes and outputs, and ti,am65x-dss.yaml which used to
contain bindings for the "lite" DSS version, with two planes and
outputs.
ti,am62l-dss binding was added recently to the ti,am65x-dss.yaml file,
which only has a single plane and a single output. To keep with the
above "binding file per DSS model" style, and to simplify the
ti,am65x-dss.yaml file, let's move the ti,am62l-dss to a separate, new
file.
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
.../bindings/display/ti/ti,am62l-dss.yaml | 136 +++++++++++++++++++++
.../bindings/display/ti/ti,am65x-dss.yaml | 94 +++-----------
MAINTAINERS | 1 +
3 files changed, 156 insertions(+), 75 deletions(-)
diff --git a/Documentation/devicetree/bindings/display/ti/ti,am62l-dss.yaml b/Documentation/devicetree/bindings/display/ti/ti,am62l-dss.yaml
new file mode 100644
index 000000000000..ce6185dca18d
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/ti/ti,am62l-dss.yaml
@@ -0,0 +1,136 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2026 Texas Instruments Incorporated
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/ti/ti,am62l-dss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments AM62L Display Subsystem
+
+maintainers:
+ - Tomi Valkeinen <tomi.valkeinen@ti.com>
+
+description: |
+ The AM62L display subsystem is a cut-down version of the TI Keystone
+ Display SubSystem. It has a single output port which supports DPI
+ format and a single video "lite plane" which does not support scaling.
+ The output port is routed to the SoC boundary via the DPI interface,
+ and the same DPI signals are also routed internally to the DSI Tx
+ controller present within the SoC. Due to clocking limitations only
+ one of the interfaces (DSI or DPI) can be used at a time.
+
+properties:
+ compatible:
+ const: ti,am62l-dss
+
+ reg:
+ description:
+ Addresses to each DSS memory region described in the SoC's TRM.
+ items:
+ - description: common DSS register area
+ - description: VIDL1 light video plane
+ - description: OVR1 overlay manager for vp1
+ - description: VP1 video port 1
+ - description: common1 DSS register area
+
+ reg-names:
+ items:
+ - const: common
+ - const: vidl1
+ - const: ovr1
+ - const: vp1
+ - const: common1
+
+ clocks:
+ items:
+ - description: fck DSS functional clock
+ - description: vp1 Video Port 1 pixel clock
+
+ clock-names:
+ items:
+ - const: fck
+ - const: vp1
+
+ assigned-clocks:
+ minItems: 1
+ maxItems: 2
+
+ assigned-clock-parents:
+ minItems: 1
+ maxItems: 2
+
+ interrupts:
+ maxItems: 1
+
+ power-domains:
+ maxItems: 1
+ description: phandle to the associated power domain
+
+ dma-coherent: true
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ The DSS DPI output port node from video port 1, which may be
+ connected to the external DPI pins or to the internal DSI Tx
+ controller.
+
+ required:
+ - port@0
+
+ max-memory-bandwidth:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Input memory (from main memory to dispc) bandwidth limit in
+ bytes per second
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - clocks
+ - clock-names
+ - interrupts
+ - ports
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ bus {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ dss: dss@30200000 {
+ compatible = "ti,am62l-dss";
+ reg = <0x00 0x30200000 0x00 0x1000>, /* common */
+ <0x00 0x30202000 0x00 0x1000>, /* vidl1 */
+ <0x00 0x30207000 0x00 0x1000>, /* ovr1 */
+ <0x00 0x3020a000 0x00 0x1000>, /* vp1 */
+ <0x00 0x30201000 0x00 0x1000>; /* common1 */
+ reg-names = "common", "vidl1", "ovr1", "vp1", "common1";
+ power-domains = <&scmi_pds 39>;
+ clocks = <&scmi_clk 162>,
+ <&scmi_clk 161>;
+ clock-names = "fck", "vp1";
+ interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ dpi0_out: endpoint {
+ remote-endpoint = <&dsi_in>;
+ };
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
index d1e530e12604..4e9e441308cc 100644
--- a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
+++ b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
@@ -18,68 +18,45 @@ description: |
internally routed to 2 OLDI TXes. The second video port supports DPI
format. The first plane is full video plane with all features and the
second is a "lite plane" without scaling support.
- The AM62L display subsystem has a single output port which supports DPI
- format but it only supports single video "lite plane" which does not support
- scaling. The output port is routed to SoC boundary via DPI interface and same
- DPI signals are also routed internally to DSI Tx controller present within the
- SoC. Due to clocking limitations only one of the interface i.e. either DSI or
- DPI can be used at once.
properties:
compatible:
enum:
- ti,am625-dss
- ti,am62a7-dss
- - ti,am62l-dss
- ti,am65x-dss
reg:
description:
Addresses to each DSS memory region described in the SoC's TRM.
- oneOf:
- - items:
- - description: common DSS register area
- - description: VIDL1 light video plane
- - description: VID video plane
- - description: OVR1 overlay manager for vp1
- - description: OVR2 overlay manager for vp2
- - description: VP1 video port 1
- - description: VP2 video port 2
- - description: common1 DSS register area
- - items:
- - description: common DSS register area
- - description: VIDL1 light video plane
- - description: OVR1 overlay manager for vp1
- - description: VP1 video port 1
- - description: common1 DSS register area
+ items:
+ - description: common DSS register area
+ - description: VIDL1 light video plane
+ - description: VID video plane
+ - description: OVR1 overlay manager for vp1
+ - description: OVR2 overlay manager for vp2
+ - description: VP1 video port 1
+ - description: VP2 video port 2
+ - description: common1 DSS register area
reg-names:
- oneOf:
- - items:
- - const: common
- - const: vidl1
- - const: vid
- - const: ovr1
- - const: ovr2
- - const: vp1
- - const: vp2
- - const: common1
- - items:
- - const: common
- - const: vidl1
- - const: ovr1
- - const: vp1
- - const: common1
+ items:
+ - const: common
+ - const: vidl1
+ - const: vid
+ - const: ovr1
+ - const: ovr2
+ - const: vp1
+ - const: vp2
+ - const: common1
clocks:
- minItems: 2
items:
- description: fck DSS functional clock
- description: vp1 Video Port 1 pixel clock
- description: vp2 Video Port 2 pixel clock
clock-names:
- minItems: 2
items:
- const: fck
- const: vp1
@@ -113,8 +90,6 @@ properties:
For AM625 DSS, the internal DPI output port node from video
port 1.
For AM62A7 DSS, the port is tied off inside the SoC.
- For AM62L DSS, the DSS DPI output port node from video port 1
- or DSI Tx controller node connected to video port 1.
properties:
endpoint@0:
$ref: /schemas/graph.yaml#/properties/endpoint
@@ -189,38 +164,7 @@ allOf:
properties:
compatible:
contains:
- const: ti,am62l-dss
- then:
- properties:
- ports:
- properties:
- port@1: false
- reg:
- maxItems: 5
- reg-names:
- maxItems: 5
- clocks:
- maxItems: 2
- clock-names:
- maxItems: 2
- else:
- properties:
- reg:
- minItems: 8
- reg-names:
- minItems: 8
- clocks:
- minItems: 3
- clock-names:
- minItems: 3
-
- - if:
- properties:
- compatible:
- contains:
- enum:
- - ti,am62l-dss
- - ti,am65x-dss
+ const: ti,am65x-dss
then:
properties:
oldi-transmitters: false
diff --git a/MAINTAINERS b/MAINTAINERS
index 2e854d686da3..7e64f5270f4d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8971,6 +8971,7 @@ L: dri-devel@lists.freedesktop.org
S: Maintained
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
F: Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml
+F: Documentation/devicetree/bindings/display/ti/ti,am62l-dss.yaml
F: Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
F: Documentation/devicetree/bindings/display/ti/ti,j721e-dss.yaml
F: Documentation/devicetree/bindings/display/ti/ti,k2g-dss.yaml
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 02/10] dt-bindings: display: ti,am65x-dss: Simplify binding
2026-09-03 12:09 [PATCH 00/10] drm/tidss: Preparation for AM62P and BeagleY-AI display support Tomi Valkeinen
2026-09-03 12:09 ` [PATCH 01/10] dt-bindings: display: ti: Move ti,am62l-dss binding to a new binding file Tomi Valkeinen
@ 2026-09-03 12:09 ` Tomi Valkeinen
2026-09-03 12:09 ` [PATCH 03/10] dt-bindings: display: ti,am625-oldi: Add optional power-domain for OLDI Tomi Valkeinen
` (7 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Tomi Valkeinen @ 2026-09-03 12:09 UTC (permalink / raw)
To: Devarsh Thakkar, Swamil Jain, Jyri Sarha, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Tomi Valkeinen, dri-devel, devicetree, linux-kernel,
Tomi Valkeinen
In principle the DT binding for the DSS IP should mainly cover the DSS
IP. The current binding also covers the SoC integration topics outside
the DSS, mainly via the endpoint related rules and descriptions.
A more recent SoC, AM62P, has two instances of the DSS IP, and while
both DSS IPs are identical, they are integrated slightly differently
(e.g. which DSS output goes to an in-SoC DSI bridge, which goes to
DPI pins, etc.).
To make the bindings usable for both DSS instances, relax the binding
slightly: remove the explicit endpoint rules, and generalize the
descriptions.
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
.../bindings/display/ti/ti,am65x-dss.yaml | 55 ++++++++--------------
1 file changed, 20 insertions(+), 35 deletions(-)
diff --git a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
index 4e9e441308cc..db7d3d216b64 100644
--- a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
+++ b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
@@ -12,12 +12,21 @@ maintainers:
- Tomi Valkeinen <tomi.valkeinen@ti.com>
description: |
- The AM625 and AM65x TI Keystone Display SubSystem has two output
- ports and two video planes. In AM65x DSS, the first video port
- supports 1 OLDI TX and in AM625 DSS, the first video port output is
- internally routed to 2 OLDI TXes. The second video port supports DPI
- format. The first plane is full video plane with all features and the
- second is a "lite plane" without scaling support.
+ The Display Subsystem (DSS) used in e.g. AM65x and AM625 SoCs has two output
+ video ports (VP) and two video planes. The integration varies from SoC to SoC,
+ affecting the routing of the video ports.
+
+ The first plane is full video plane with all features and the second is a
+ "lite plane" without scaling support.
+
+ On AM65x, the first VP has an integrated OLDI TX, thus the first output port
+ is OLDI output. The second VP is routed to external MIPI DPI pins.
+
+ On AM625, the first VP is connected to two OLDI TX instances, and the second
+ VP is routed to external MIPI DPI pins.
+
+ On AM62A7, the first VP is tied off in the SoC, and the second VP is routed to
+ external MIPI DPI pins.
properties:
compatible:
@@ -85,34 +94,15 @@ properties:
properties:
port@0:
$ref: /schemas/graph.yaml#/properties/port
- description:
- For AM65x DSS, the OLDI output port node from video port 1.
- For AM625 DSS, the internal DPI output port node from video
- port 1.
- For AM62A7 DSS, the port is tied off inside the SoC.
- properties:
- endpoint@0:
- $ref: /schemas/graph.yaml#/properties/endpoint
- description:
- For AM625 DSS, VP Connection to OLDI0.
- For AM65X DSS, OLDI output from the SoC.
-
- endpoint@1:
- $ref: /schemas/graph.yaml#/properties/endpoint
- description:
- For AM625 DSS, VP Connection to OLDI1.
-
- anyOf:
- - required:
- - endpoint
- - required:
- - endpoint@0
- - endpoint@1
+ description: |
+ AM65x: OLDI output from video port 1
+ AM62A7: Not available, tied off inside the SoC
+ Other SoCs: Parallel video from video port 1
port@1:
$ref: /schemas/graph.yaml#/properties/port
description:
- The DSS DPI output port node from video port 2
+ Parallel video from video port 2
ti,am65x-oldi-io-ctrl:
$ref: /schemas/types.yaml#/definitions/phandle
@@ -168,11 +158,6 @@ allOf:
then:
properties:
oldi-transmitters: false
- ports:
- properties:
- port@0:
- properties:
- endpoint@1: false
required:
- compatible
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 03/10] dt-bindings: display: ti,am625-oldi: Add optional power-domain for OLDI
2026-09-03 12:09 [PATCH 00/10] drm/tidss: Preparation for AM62P and BeagleY-AI display support Tomi Valkeinen
2026-09-03 12:09 ` [PATCH 01/10] dt-bindings: display: ti: Move ti,am62l-dss binding to a new binding file Tomi Valkeinen
2026-09-03 12:09 ` [PATCH 02/10] dt-bindings: display: ti,am65x-dss: Simplify binding Tomi Valkeinen
@ 2026-09-03 12:09 ` Tomi Valkeinen
2026-09-03 12:09 ` [PATCH 04/10] drm/tidss: Remove extra pm_runtime_mark_last_busy Tomi Valkeinen
` (6 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Tomi Valkeinen @ 2026-09-03 12:09 UTC (permalink / raw)
To: Devarsh Thakkar, Swamil Jain, Jyri Sarha, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Tomi Valkeinen, dri-devel, devicetree, linux-kernel,
Tomi Valkeinen, Krzysztof Kozlowski
On some SoCs the OLDI blocks belong to the same power-domain as the main
DSS block, but on some more recent SoCs the OLDI blocks have a
controllable power-domain.
Add the power-domain to the DT binding.
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml b/Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml
index 8203ec5e5bb3..5dbf1f76dd3f 100644
--- a/Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml
+++ b/Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml
@@ -29,6 +29,9 @@ properties:
clock-names:
const: serial
+ power-domains:
+ maxItems: 1
+
ti,companion-oldi:
$ref: /schemas/types.yaml#/definitions/phandle
description:
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 04/10] drm/tidss: Remove extra pm_runtime_mark_last_busy
2026-09-03 12:09 [PATCH 00/10] drm/tidss: Preparation for AM62P and BeagleY-AI display support Tomi Valkeinen
` (2 preceding siblings ...)
2026-09-03 12:09 ` [PATCH 03/10] dt-bindings: display: ti,am625-oldi: Add optional power-domain for OLDI Tomi Valkeinen
@ 2026-09-03 12:09 ` Tomi Valkeinen
2026-09-03 12:09 ` [PATCH 05/10] drm/tidss: oldi: Remove define for unused register OLDI_LB_CTRL Tomi Valkeinen
` (5 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Tomi Valkeinen @ 2026-09-03 12:09 UTC (permalink / raw)
To: Devarsh Thakkar, Swamil Jain, Jyri Sarha, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Tomi Valkeinen, dri-devel, devicetree, linux-kernel,
Tomi Valkeinen
pm_runtime_put_autosuspend() calls pm_runtime_mark_last_busy(), so no
need to call pm_runtime_mark_last_busy() explicitly in the driver.
Tested-by: Swamil Jain <s-jain1@ti.com>
Reviewed-by: Swamil Jain <s-jain1@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/gpu/drm/tidss/tidss_drv.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/gpu/drm/tidss/tidss_drv.c b/drivers/gpu/drm/tidss/tidss_drv.c
index 1c8cc18bc53c..5cb3e746aeb3 100644
--- a/drivers/gpu/drm/tidss/tidss_drv.c
+++ b/drivers/gpu/drm/tidss/tidss_drv.c
@@ -42,8 +42,6 @@ void tidss_runtime_put(struct tidss_device *tidss)
{
int r;
- pm_runtime_mark_last_busy(tidss->dev);
-
r = pm_runtime_put_autosuspend(tidss->dev);
WARN_ON(r < 0);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 05/10] drm/tidss: oldi: Remove define for unused register OLDI_LB_CTRL
2026-09-03 12:09 [PATCH 00/10] drm/tidss: Preparation for AM62P and BeagleY-AI display support Tomi Valkeinen
` (3 preceding siblings ...)
2026-09-03 12:09 ` [PATCH 04/10] drm/tidss: Remove extra pm_runtime_mark_last_busy Tomi Valkeinen
@ 2026-09-03 12:09 ` Tomi Valkeinen
2026-09-03 12:09 ` [PATCH 06/10] drm/tidss: Add mechanism to detect DPI output Tomi Valkeinen
` (4 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Tomi Valkeinen @ 2026-09-03 12:09 UTC (permalink / raw)
To: Devarsh Thakkar, Swamil Jain, Jyri Sarha, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Tomi Valkeinen, dri-devel, devicetree, linux-kernel,
Tomi Valkeinen
OLDI_LB_CTRL define is not used, and doesn't seem to exist at least on
some SoCs. Let's remove the define.
Tested-by: Swamil Jain <s-jain1@ti.com>
Reviewed-by: Swamil Jain <s-jain1@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/gpu/drm/tidss/tidss_oldi.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/gpu/drm/tidss/tidss_oldi.h b/drivers/gpu/drm/tidss/tidss_oldi.h
index 8cd535c5ee65..a361e6dbfce3 100644
--- a/drivers/gpu/drm/tidss/tidss_oldi.h
+++ b/drivers/gpu/drm/tidss/tidss_oldi.h
@@ -20,7 +20,6 @@ struct tidss_oldi;
/* Register offsets */
#define OLDI_PD_CTRL 0x100
-#define OLDI_LB_CTRL 0x104
/* Power control bits */
#define OLDI_PWRDOWN_TX(n) BIT(n)
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 06/10] drm/tidss: Add mechanism to detect DPI output
2026-09-03 12:09 [PATCH 00/10] drm/tidss: Preparation for AM62P and BeagleY-AI display support Tomi Valkeinen
` (4 preceding siblings ...)
2026-09-03 12:09 ` [PATCH 05/10] drm/tidss: oldi: Remove define for unused register OLDI_LB_CTRL Tomi Valkeinen
@ 2026-09-03 12:09 ` Tomi Valkeinen
2026-09-03 12:09 ` [PATCH 07/10] drm/tidss: Add support for DPIENABLE bit Tomi Valkeinen
` (3 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Tomi Valkeinen @ 2026-09-03 12:09 UTC (permalink / raw)
To: Devarsh Thakkar, Swamil Jain, Jyri Sarha, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Tomi Valkeinen, dri-devel, devicetree, linux-kernel,
Tomi Valkeinen
There are situations where the driver needs to know if the output is
going to the DPI output or not. There is no trivial way to get this
information, as there is no "DPI bridge". We can only find this out in
reverse: check if the output is NOT DPI, and if that is negative, then
it must be DPI.
At the moment we have two non-DPI outputs: DSI and OLDI. DSI always has
"ti,j721e-dsi" DSI bridge connected to the DSI, so we can use that for
checking. OLDI doesn't have a compatible property, but we can check if
the DT node has "oldi-transmitters" node as a parent, and the dss node
itself as a grand-parent. There's also a special case for OLDI, the
AM62x OLDI, which uses an older design that requires a special case in
the detection.
If the output is not connected to either of the above, it must be DPI.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/gpu/drm/tidss/tidss_crtc.c | 10 ++++--
drivers/gpu/drm/tidss/tidss_crtc.h | 4 ++-
drivers/gpu/drm/tidss/tidss_dispc.c | 5 ++-
drivers/gpu/drm/tidss/tidss_dispc.h | 3 +-
drivers/gpu/drm/tidss/tidss_kms.c | 70 ++++++++++++++++++++++++++++++++++++-
5 files changed, 85 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/tidss/tidss_crtc.c b/drivers/gpu/drm/tidss/tidss_crtc.c
index 400329aa2200..ae9c66831b6c 100644
--- a/drivers/gpu/drm/tidss/tidss_crtc.c
+++ b/drivers/gpu/drm/tidss/tidss_crtc.c
@@ -192,7 +192,8 @@ static void tidss_crtc_atomic_flush(struct drm_crtc *crtc,
return;
/* Write vp properties to HW if needed. */
- dispc_vp_setup(tidss->dispc, tcrtc->hw_videoport, crtc->state, false);
+ dispc_vp_setup(tidss->dispc, tcrtc->hw_videoport, crtc->state, false,
+ tcrtc->dpi_output);
/* Update plane positions if needed. */
tidss_crtc_position_planes(tidss, crtc, old_crtc_state, false);
@@ -235,7 +236,8 @@ static void tidss_crtc_atomic_enable(struct drm_crtc *crtc,
if (r != 0)
return;
- dispc_vp_setup(tidss->dispc, tcrtc->hw_videoport, crtc->state, true);
+ dispc_vp_setup(tidss->dispc, tcrtc->hw_videoport, crtc->state, true,
+ tcrtc->dpi_output);
tidss_crtc_position_planes(tidss, crtc, old_state, true);
/* Turn vertical blanking interrupt reporting on. */
@@ -414,7 +416,8 @@ static const struct drm_crtc_funcs tidss_crtc_funcs = {
struct tidss_crtc *tidss_crtc_create(struct tidss_device *tidss,
u32 hw_videoport,
- struct drm_plane *primary)
+ struct drm_plane *primary,
+ bool dpi_output)
{
struct tidss_crtc *tcrtc;
struct drm_crtc *crtc;
@@ -427,6 +430,7 @@ struct tidss_crtc *tidss_crtc_create(struct tidss_device *tidss,
return ERR_PTR(-ENOMEM);
tcrtc->hw_videoport = hw_videoport;
+ tcrtc->dpi_output = dpi_output;
init_completion(&tcrtc->framedone_completion);
crtc = &tcrtc->crtc;
diff --git a/drivers/gpu/drm/tidss/tidss_crtc.h b/drivers/gpu/drm/tidss/tidss_crtc.h
index 040d1205496b..65df220698f6 100644
--- a/drivers/gpu/drm/tidss/tidss_crtc.h
+++ b/drivers/gpu/drm/tidss/tidss_crtc.h
@@ -20,6 +20,7 @@ struct tidss_crtc {
struct drm_crtc crtc;
u32 hw_videoport;
+ bool dpi_output;
struct drm_pending_vblank_event *event;
@@ -44,5 +45,6 @@ void tidss_crtc_error_irq(struct drm_crtc *crtc, u64 irqstatus);
struct tidss_crtc *tidss_crtc_create(struct tidss_device *tidss,
u32 hw_videoport,
- struct drm_plane *primary);
+ struct drm_plane *primary,
+ bool dpi_output);
#endif
diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c
index 58d5eb033bdb..c21ac3f51720 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc.c
+++ b/drivers/gpu/drm/tidss/tidss_dispc.c
@@ -448,6 +448,7 @@ static const u16 *dispc_common_regmap;
struct dss_vp_data {
u32 *gamma_table;
+ bool dpi_output;
};
struct dispc_device {
@@ -2770,8 +2771,10 @@ static void dispc_vp_set_color_mgmt(struct dispc_device *dispc,
}
void dispc_vp_setup(struct dispc_device *dispc, u32 hw_videoport,
- const struct drm_crtc_state *state, bool newmodeset)
+ const struct drm_crtc_state *state, bool newmodeset,
+ bool dpi_output)
{
+ dispc->vp_data[hw_videoport].dpi_output = dpi_output;
dispc_vp_set_default_color(dispc, hw_videoport, 0);
dispc_vp_set_color_mgmt(dispc, hw_videoport, state, newmodeset);
}
diff --git a/drivers/gpu/drm/tidss/tidss_dispc.h b/drivers/gpu/drm/tidss/tidss_dispc.h
index 739d211d0018..6f53d554259c 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc.h
+++ b/drivers/gpu/drm/tidss/tidss_dispc.h
@@ -131,7 +131,8 @@ void dispc_vp_disable_clk(struct dispc_device *dispc, u32 hw_videoport);
int dispc_vp_set_clk_rate(struct dispc_device *dispc, u32 hw_videoport,
unsigned long rate);
void dispc_vp_setup(struct dispc_device *dispc, u32 hw_videoport,
- const struct drm_crtc_state *state, bool newmodeset);
+ const struct drm_crtc_state *state, bool newmodeset,
+ bool dpi_output);
int dispc_runtime_suspend(struct dispc_device *dispc);
int dispc_runtime_resume(struct dispc_device *dispc);
diff --git a/drivers/gpu/drm/tidss/tidss_kms.c b/drivers/gpu/drm/tidss/tidss_kms.c
index 70c14c3be10d..eefe2221bdde 100644
--- a/drivers/gpu/drm/tidss/tidss_kms.c
+++ b/drivers/gpu/drm/tidss/tidss_kms.c
@@ -122,6 +122,68 @@ static const struct drm_mode_config_funcs mode_config_funcs = {
.atomic_commit = drm_atomic_helper_commit,
};
+static const char * const tidss_internal_bridge_compatibles[] = {
+ "ti,j721e-dsi",
+};
+
+/*
+ * Detect whether the bridge is internal to the SoC or not.
+ * We detect this via two means:
+ * - If the bridge's of_node has a compatible, compare to known internal values.
+ * - If the bridge is a grand-child of DSS, and has "oldi-transmitters" parent.
+ */
+static bool tidss_is_bridge_internal(struct tidss_device *tidss,
+ struct drm_bridge *bridge)
+{
+ struct device_node *parent, *grand_parent;
+ bool is_internal;
+
+ if (WARN_ON(!bridge->of_node))
+ return false;
+
+ for (unsigned int i = 0;
+ i < ARRAY_SIZE(tidss_internal_bridge_compatibles); ++i) {
+ if (of_device_is_compatible(bridge->of_node,
+ tidss_internal_bridge_compatibles[i]))
+ return true;
+ }
+
+ parent = of_get_parent(bridge->of_node);
+ grand_parent = of_get_parent(parent);
+
+ is_internal = parent && grand_parent &&
+ tidss->dev->of_node == grand_parent &&
+ of_node_name_eq(parent, "oldi-transmitters");
+
+ of_node_put(grand_parent);
+ of_node_put(parent);
+
+ return is_internal;
+}
+
+/*
+ * Detect whether the videoport's output goes to the DPI output or not. There is
+ * no "DPI bridge", so we have to find this out in reverse: check if the output
+ * is NOT DPI, and if that is negative, then it must be DPI.
+ */
+static bool tidss_is_dpi_output(struct tidss_device *tidss, u32 hw_videoport,
+ struct drm_bridge *bridge)
+{
+ /*
+ * On AM65x the OLDI TX is modeled as a part of the DSS itself, on VP0.
+ * On other SoCs OLDI TX is a separate bridge. As there is no DT node
+ * for the OLDI TX on AM65x, we cannot detect this from the DT data, and
+ * have to special-case it here.
+ */
+ if (tidss->feat->subrev == DISPC_AM65X && hw_videoport == 0)
+ return false;
+
+ if (!bridge)
+ return true;
+
+ return !tidss_is_bridge_internal(tidss, bridge);
+}
+
static int tidss_dispc_modeset_init(struct tidss_device *tidss)
{
struct device *dev = tidss->dev;
@@ -133,6 +195,7 @@ static int tidss_dispc_modeset_init(struct tidss_device *tidss)
u32 hw_videoport;
struct drm_bridge *bridge;
u32 enc_type;
+ bool dpi_output;
};
const struct dispc_features *feat = tidss->feat;
@@ -149,6 +212,7 @@ static int tidss_dispc_modeset_init(struct tidss_device *tidss)
struct drm_panel *panel;
struct drm_bridge *bridge;
u32 enc_type = DRM_MODE_ENCODER_NONE;
+ bool dpi_output;
int ret;
ret = drm_of_find_panel_or_bridge(dev->of_node, i, 0,
@@ -160,6 +224,8 @@ static int tidss_dispc_modeset_init(struct tidss_device *tidss)
return dev_err_probe(dev, ret, "port %d probe failed\n", i);
}
+ dpi_output = tidss_is_dpi_output(tidss, i, bridge);
+
if (panel) {
u32 conn_type;
int ret;
@@ -205,6 +271,7 @@ static int tidss_dispc_modeset_init(struct tidss_device *tidss)
pipes[num_pipes].hw_videoport = i;
pipes[num_pipes].bridge = bridge;
pipes[num_pipes].enc_type = enc_type;
+ pipes[num_pipes].dpi_output = dpi_output;
num_pipes++;
}
@@ -230,7 +297,8 @@ static int tidss_dispc_modeset_init(struct tidss_device *tidss)
tidss->planes[tidss->num_planes++] = &tplane->plane;
tcrtc = tidss_crtc_create(tidss, pipes[i].hw_videoport,
- &tplane->plane);
+ &tplane->plane,
+ pipes[i].dpi_output);
if (IS_ERR(tcrtc)) {
dev_err(tidss->dev, "crtc create failed\n");
return PTR_ERR(tcrtc);
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 07/10] drm/tidss: Add support for DPIENABLE bit
2026-09-03 12:09 [PATCH 00/10] drm/tidss: Preparation for AM62P and BeagleY-AI display support Tomi Valkeinen
` (5 preceding siblings ...)
2026-09-03 12:09 ` [PATCH 06/10] drm/tidss: Add mechanism to detect DPI output Tomi Valkeinen
@ 2026-09-03 12:09 ` Tomi Valkeinen
2026-09-03 12:09 ` [PATCH 08/10] drm/tidss: oldi: Fix OLDI signal polarities Tomi Valkeinen
` (2 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Tomi Valkeinen @ 2026-09-03 12:09 UTC (permalink / raw)
To: Devarsh Thakkar, Swamil Jain, Jyri Sarha, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Tomi Valkeinen, dri-devel, devicetree, linux-kernel,
Tomi Valkeinen
Many (or even all?) K3 SoCs have DSS VP_CONTROL.DPIENABLE bit described
in their documentation. This bit controls whether the DPI block is
enabled, and is set to 1 by default (i.e. DPI is enabled at HW reset).
However, in almost all SoCs the setting does not actually do anything,
and at the moment the bit is not managed by the driver.
The exception is AM62L, which does have DPIENABLE connected, and
disabling the DPI block when it is not in use provides power savings.
Let's add a new feature flag for this, 'has_vp_control_dpienable', and
implement the support. Disable DPIENABLE for all videoports at resume
time, so that it is 0 by default. Specifically enable and disable it in
dispc_vp_prepare() and dispc_vp_unprepare() for DPI output.
Tested-by: Swamil Jain <s-jain1@ti.com>
Reviewed-by: Devarsh Thakkar <devarsht@ti.com>
Reviewed-by: Swamil Jain <s-jain1@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/gpu/drm/tidss/tidss_dispc.c | 23 +++++++++++++++++++++--
drivers/gpu/drm/tidss/tidss_dispc.h | 2 ++
drivers/gpu/drm/tidss/tidss_dispc_regs.h | 1 +
3 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c
index c21ac3f51720..7efcdf7679ac 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc.c
+++ b/drivers/gpu/drm/tidss/tidss_dispc.c
@@ -442,6 +442,8 @@ const struct dispc_features dispc_am62l_feats = {
},
.vid_order = {0},
+
+ .has_vp_control_dpienable = true,
};
static const u16 *dispc_common_regmap;
@@ -1201,6 +1203,11 @@ void dispc_vp_prepare(struct dispc_device *dispc, u32 hw_videoport,
mode->crtc_hdisplay - 1) |
FIELD_PREP(DISPC_VP_SIZE_SCREEN_VDISPLAY_MASK,
mode->crtc_vdisplay - 1));
+
+ if (dispc->feat->has_vp_control_dpienable &&
+ dispc->vp_data[hw_videoport].dpi_output)
+ VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONTROL, 1,
+ DISPC_VP_CONTROL_DPIENABLE_MASK);
}
void dispc_vp_enable(struct dispc_device *dispc, u32 hw_videoport)
@@ -1217,6 +1224,11 @@ void dispc_vp_disable(struct dispc_device *dispc, u32 hw_videoport)
void dispc_vp_unprepare(struct dispc_device *dispc, u32 hw_videoport)
{
+ if (dispc->feat->has_vp_control_dpienable &&
+ dispc->vp_data[hw_videoport].dpi_output)
+ VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONTROL, 0,
+ DISPC_VP_CONTROL_DPIENABLE_MASK);
+
if (dispc->feat->vp_bus_type[hw_videoport] == DISPC_VP_OLDI_AM65X) {
dispc_vp_write(dispc, hw_videoport, DISPC_VP_DSS_OLDI_CFG, 0);
@@ -2436,10 +2448,17 @@ static void dispc_vp_init(struct dispc_device *dispc)
dev_dbg(dispc->dev, "%s()\n", __func__);
- /* Enable the gamma Shadow bit-field for all VPs*/
- for (i = 0; i < dispc->feat->num_vps; i++)
+ for (i = 0; i < dispc->feat->num_vps; i++) {
+ /* Enable the gamma Shadow bit-field for all VPs*/
VP_REG_FLD_MOD(dispc, i, DISPC_VP_CONFIG, 1,
DISPC_VP_CONFIG_GAMMAENABLE_MASK);
+
+ if (dispc->feat->has_vp_control_dpienable) {
+ /* Disable DPIENABLE for all VPs */
+ VP_REG_FLD_MOD(dispc, i, DISPC_VP_CONTROL, 0,
+ DISPC_VP_CONTROL_DPIENABLE_MASK);
+ }
+ }
}
static void dispc_initial_config(struct dispc_device *dispc)
diff --git a/drivers/gpu/drm/tidss/tidss_dispc.h b/drivers/gpu/drm/tidss/tidss_dispc.h
index 6f53d554259c..0fbfb86adfbf 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc.h
+++ b/drivers/gpu/drm/tidss/tidss_dispc.h
@@ -92,6 +92,8 @@ struct dispc_features {
u32 num_vids;
struct dispc_vid_info vid_info[TIDSS_MAX_PLANES];
u32 vid_order[TIDSS_MAX_PLANES];
+ /* The DSS has VP_CONTROL.DPIENABLE bit */
+ bool has_vp_control_dpienable;
};
extern const struct dispc_features dispc_k2g_feats;
diff --git a/drivers/gpu/drm/tidss/tidss_dispc_regs.h b/drivers/gpu/drm/tidss/tidss_dispc_regs.h
index 382027dddce8..13ff00696c2e 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc_regs.h
+++ b/drivers/gpu/drm/tidss/tidss_dispc_regs.h
@@ -230,6 +230,7 @@ enum dispc_common_regs {
#define DISPC_VP_CONTROL 0x4
#define DISPC_VP_CONTROL_DATALINES_MASK GENMASK(10, 8)
+#define DISPC_VP_CONTROL_DPIENABLE_MASK GENMASK(6, 6)
#define DISPC_VP_CONTROL_GOBIT_MASK GENMASK(5, 5)
#define DISPC_VP_CONTROL_ENABLE_MASK GENMASK(0, 0)
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 08/10] drm/tidss: oldi: Fix OLDI signal polarities
2026-09-03 12:09 [PATCH 00/10] drm/tidss: Preparation for AM62P and BeagleY-AI display support Tomi Valkeinen
` (6 preceding siblings ...)
2026-09-03 12:09 ` [PATCH 07/10] drm/tidss: Add support for DPIENABLE bit Tomi Valkeinen
@ 2026-09-03 12:09 ` Tomi Valkeinen
2026-09-03 12:21 ` sashiko-bot
2026-09-03 12:09 ` [PATCH 09/10] drm/tidss: Drop WARN_ON() from tidss_runtime_put() Tomi Valkeinen
2026-09-03 12:10 ` [PATCH 10/10] drm/tidss: oldi: Fix missing of_node_put()s in error paths Tomi Valkeinen
9 siblings, 1 reply; 13+ messages in thread
From: Tomi Valkeinen @ 2026-09-03 12:09 UTC (permalink / raw)
To: Devarsh Thakkar, Swamil Jain, Jyri Sarha, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Tomi Valkeinen, dri-devel, devicetree, linux-kernel,
Tomi Valkeinen
OLDI has a few issues with how it handles the signal polarities:
- It always sets OLDI_DEPOL, which means DE active low
- It sets DRM_BUS_FLAG_DE_HIGH in struct drm_bridge_timings, i.e.
reverse to the OLDI_DEPOL
- It sets DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE in struct drm_bridge_timings,
but the TRM says "The DSS interface is clocked on the rising edge of
OLDI_FWD_P_CLK pixel clock", which I read as "OLDI samples on rising
edge".
- But the defined drm_bridge_timings is not actually used anywhere, even
if it is set to bridge->timings, so the bus flags are just ignored.
However, based on my testing, OLDI_DEPOL bit or the edge on which data
and syncs are driven doesn't seem to affect the OLDI output. Possibly
it's not as robust, but I did not see any effect with an oscilloscope.
However, the code is still quite broken, so let's fix it:
- Remove drm_bridge_timings
- Set the correct input_bus_cfg.flags in tidss_oldi_atomic_check()
- Set OLDI_DEPOL based on the DE bus flag
Tested-by: Swamil Jain <s-jain1@ti.com>
Reviewed-by: Swamil Jain <s-jain1@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/gpu/drm/tidss/tidss_oldi.c | 38 ++++++++++++++++++++++++++++----------
1 file changed, 28 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/tidss/tidss_oldi.c b/drivers/gpu/drm/tidss/tidss_oldi.c
index 5eb749f495d5..624f1646fb07 100644
--- a/drivers/gpu/drm/tidss/tidss_oldi.c
+++ b/drivers/gpu/drm/tidss/tidss_oldi.c
@@ -164,7 +164,8 @@ static void tidss_oldi_tx_power(struct tidss_oldi *oldi, bool enable)
regmap_update_bits(oldi->io_ctrl, OLDI_PD_CTRL, mask, enable ? 0 : mask);
}
-static int tidss_oldi_config(struct tidss_oldi *oldi)
+static int tidss_oldi_config(struct tidss_oldi *oldi,
+ struct drm_bridge_state *bridge_state)
{
const struct oldi_bus_format *bus_fmt = NULL;
u32 oldi_cfg = 0;
@@ -183,7 +184,8 @@ static int tidss_oldi_config(struct tidss_oldi *oldi)
"OLDI%u: DSS port width %d not supported\n",
oldi->oldi_instance, bus_fmt->data_width);
- oldi_cfg |= OLDI_DEPOL;
+ if (bridge_state->input_bus_cfg.flags & DRM_BUS_FLAG_DE_LOW)
+ oldi_cfg |= OLDI_DEPOL; /* 1 = active low */
oldi_cfg = (oldi_cfg & (~OLDI_MAP)) | (bus_fmt->oldi_mode_reg_val << 1);
@@ -220,6 +222,22 @@ static int tidss_oldi_config(struct tidss_oldi *oldi)
return ret;
}
+static int tidss_oldi_atomic_check(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ bridge_state->input_bus_cfg.flags &=
+ ~(DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE |
+ DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE);
+
+ bridge_state->input_bus_cfg.flags |=
+ DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE |
+ DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE;
+
+ return 0;
+}
+
static void tidss_oldi_atomic_pre_enable(struct drm_bridge *bridge,
struct drm_atomic_commit *state)
{
@@ -228,6 +246,7 @@ static void tidss_oldi_atomic_pre_enable(struct drm_bridge *bridge,
struct drm_connector_state *conn_state;
struct drm_crtc_state *crtc_state;
struct drm_display_mode *mode;
+ struct drm_bridge_state *bridge_state;
if (oldi->link_type == OLDI_MODE_SECONDARY_CLONE_SINGLE_LINK)
return;
@@ -245,10 +264,14 @@ static void tidss_oldi_atomic_pre_enable(struct drm_bridge *bridge,
if (WARN_ON(!crtc_state))
return;
+ bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
+ if (WARN_ON(!bridge_state))
+ return;
+
mode = &crtc_state->adjusted_mode;
/* Configure the OLDI params*/
- tidss_oldi_config(oldi);
+ tidss_oldi_config(oldi, bridge_state);
/* Set the OLDI serial clock (7 times the pixel clock) */
tidss_oldi_set_serial_clk(oldi, mode->clock * 7 * 1000);
@@ -329,7 +352,8 @@ tidss_oldi_mode_valid(struct drm_bridge *bridge,
}
static const struct drm_bridge_funcs tidss_oldi_bridge_funcs = {
- .attach = tidss_oldi_bridge_attach,
+ .attach = tidss_oldi_bridge_attach,
+ .atomic_check = tidss_oldi_atomic_check,
.atomic_pre_enable = tidss_oldi_atomic_pre_enable,
.atomic_post_disable = tidss_oldi_atomic_post_disable,
.atomic_get_input_bus_fmts = tidss_oldi_atomic_get_input_bus_fmts,
@@ -440,11 +464,6 @@ static int get_parent_dss_vp(struct device_node *oldi_tx, u32 *parent_vp)
return -ENODEV;
}
-static const struct drm_bridge_timings default_tidss_oldi_timings = {
- .input_bus_flags = DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE
- | DRM_BUS_FLAG_DE_HIGH,
-};
-
void tidss_oldi_deinit(struct tidss_device *tidss)
{
for (int i = 0; i < tidss->num_oldis; i++) {
@@ -598,7 +617,6 @@ int tidss_oldi_init(struct tidss_device *tidss)
/* Register the bridge. */
oldi->bridge.of_node = child;
oldi->bridge.driver_private = oldi;
- oldi->bridge.timings = &default_tidss_oldi_timings;
tidss->oldis[tidss->num_oldis++] = oldi;
tidss->is_ext_vp_clk[oldi->parent_vp] = true;
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH 08/10] drm/tidss: oldi: Fix OLDI signal polarities
2026-09-03 12:09 ` [PATCH 08/10] drm/tidss: oldi: Fix OLDI signal polarities Tomi Valkeinen
@ 2026-09-03 12:21 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-09-03 12:21 UTC (permalink / raw)
To: Tomi Valkeinen; +Cc: dri-devel, conor+dt, robh, devicetree
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Modifying driver-private state in atomic check callback violates atomic modesetting semantics.
--
commit 3406ad4360f9e6a4eda4b2203c1f6400e5e7ab77
Author: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
drm/tidss: oldi: Fix OLDI signal polarities
This commit fixes OLDI signal polarities by removing drm_bridge_timings
and properly setting input_bus_cfg.flags in tidss_oldi_atomic_check(),
as well as setting OLDI_DEPOL based on the DE bus flag.
> diff --git a/drivers/gpu/drm/tidss/tidss_oldi.c b/drivers/gpu/drm/tidss/tidss_oldi.c
> index 5eb749f495d59..624f1646fb07a 100644
> --- a/drivers/gpu/drm/tidss/tidss_oldi.c
> +++ b/drivers/gpu/drm/tidss/tidss_oldi.c
[ ... ]
> @@ -329,7 +352,8 @@ tidss_oldi_mode_valid(struct drm_bridge *bridge,
> }
>
> static const struct drm_bridge_funcs tidss_oldi_bridge_funcs = {
> - .attach = tidss_oldi_bridge_attach,
> + .attach = tidss_oldi_bridge_attach,
> + .atomic_check = tidss_oldi_atomic_check,
> .atomic_pre_enable = tidss_oldi_atomic_pre_enable,
> .atomic_post_disable = tidss_oldi_atomic_post_disable,
> .atomic_get_input_bus_fmts = tidss_oldi_atomic_get_input_bus_fmts,
[Severity: High]
This isn't a bug introduced by this patch, but does the implementation of
tidss_oldi_atomic_get_input_bus_fmts() violate atomic modesetting
semantics by modifying driver-private state during the check phase?
In drivers/gpu/drm/tidss/tidss_oldi.c:tidss_oldi_atomic_get_input_bus_fmts():
input_fmts[0] = oldi_bus_formats[i].input_bus_fmt;
oldi->bus_format = &oldi_bus_formats[i];
A TEST_ONLY atomic commit or concurrent commits can alter the global
driver-private state (oldi->bus_format). This could cause a subsequent
real commit to program the hardware with an incorrect bus format, leading
to display corruption.
Should this configuration decision be stored in the drm_bridge_state object
instead of the driver-private tidss_oldi structure?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260903-tidss-pre-beagley-v1-0-93928baa8b12@ideasonboard.com?part=8
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 09/10] drm/tidss: Drop WARN_ON() from tidss_runtime_put()
2026-09-03 12:09 [PATCH 00/10] drm/tidss: Preparation for AM62P and BeagleY-AI display support Tomi Valkeinen
` (7 preceding siblings ...)
2026-09-03 12:09 ` [PATCH 08/10] drm/tidss: oldi: Fix OLDI signal polarities Tomi Valkeinen
@ 2026-09-03 12:09 ` Tomi Valkeinen
2026-09-03 12:23 ` sashiko-bot
2026-09-03 12:10 ` [PATCH 10/10] drm/tidss: oldi: Fix missing of_node_put()s in error paths Tomi Valkeinen
9 siblings, 1 reply; 13+ messages in thread
From: Tomi Valkeinen @ 2026-09-03 12:09 UTC (permalink / raw)
To: Devarsh Thakkar, Swamil Jain, Jyri Sarha, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Tomi Valkeinen, dri-devel, devicetree, linux-kernel,
Tomi Valkeinen
At the moment tidss driver has a WARN_ON(r < 0) for the
pm_runtime_put_autosuspend() return value, to catch unexpected
situations, and at the moment we never hit that warn. However, with the
upcoming change in tidss_oldi.c to change the OLDI to an auxiliary
device, we will get a child-parent relationship between tidss and OLDI.
The OLDI aux devices are children of the DSS device, so when an OLDI is
active, the DSS's child_count is non-zero, and
pm_runtime_put_autosuspend() on the DSS device returns -EBUSY. Which
then triggers the WARN_ON().
To avoid that, drop the WARN_ON. The -EBUSY is not an error, and it's a
normal situation with parent-child devices. Also, with a quick grep, it
looks like almost no driver in the kernel checks
pm_runtime_put_autosuspend()'s return value.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/gpu/drm/tidss/tidss_drv.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/tidss/tidss_drv.c b/drivers/gpu/drm/tidss/tidss_drv.c
index 5cb3e746aeb3..44b0b009c29a 100644
--- a/drivers/gpu/drm/tidss/tidss_drv.c
+++ b/drivers/gpu/drm/tidss/tidss_drv.c
@@ -40,10 +40,7 @@ int tidss_runtime_get(struct tidss_device *tidss)
void tidss_runtime_put(struct tidss_device *tidss)
{
- int r;
-
- r = pm_runtime_put_autosuspend(tidss->dev);
- WARN_ON(r < 0);
+ pm_runtime_put_autosuspend(tidss->dev);
}
static int __maybe_unused tidss_pm_runtime_suspend(struct device *dev)
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH 09/10] drm/tidss: Drop WARN_ON() from tidss_runtime_put()
2026-09-03 12:09 ` [PATCH 09/10] drm/tidss: Drop WARN_ON() from tidss_runtime_put() Tomi Valkeinen
@ 2026-09-03 12:23 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-09-03 12:23 UTC (permalink / raw)
To: Tomi Valkeinen; +Cc: robh, dri-devel, devicetree, conor+dt
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Callers of `tidss_runtime_get()` ignore its return value, proceeding to access hardware even if the device fails to resume.
- [High] Pending asynchronous suspend is cancelled by `pm_runtime_disable()` during device removal, leaving hardware powered on.
--
commit 1177f415f04c015bad856d54b014b7b1a387e7b9
Author: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
drm/tidss: Drop WARN_ON() from tidss_runtime_put()
This commit removes the WARN_ON() check for the return value of
pm_runtime_put_autosuspend() in tidss_runtime_put(). The change is made to
avoid spurious warnings when an OLDI auxiliary device is active, which
legitimately causes the autosuspend to return -EBUSY due to a non-zero
child count.
> diff --git a/drivers/gpu/drm/tidss/tidss_drv.c b/drivers/gpu/drm/tidss/tidss_drv.c
> index 5cb3e746aeb37..44b0b009c29a9 100644
> --- a/drivers/gpu/drm/tidss/tidss_drv.c
> +++ b/drivers/gpu/drm/tidss/tidss_drv.c
> @@ -40,10 +40,7 @@ int tidss_runtime_get(struct tidss_device *tidss)
>
> void tidss_runtime_put(struct tidss_device *tidss)
> {
[Severity: High]
This isn't a bug introduced by this patch, but since we are modifying the PM
handling here, is it safe for callers of tidss_runtime_get() to ignore its
return value?
If pm_runtime_resume_and_get() fails (e.g., due to power domain or clock
issues), the error is ignored, and the driver immediately accesses display
hardware registers which could cause a kernel panic (synchronous external
abort).
For example, in tidss_crtc_atomic_enable():
drivers/gpu/drm/tidss/tidss_crtc.c:tidss_crtc_atomic_enable() {
...
tidss_runtime_get(tidss);
r = dispc_vp_set_clk_rate(tidss->dispc, tcrtc->hw_videoport,
mode->crtc_clock * 1000);
...
}
The same happens in tidss_atomic_commit_tail() and tidss_crtc_enable_vblank().
Should these callers check the return value of tidss_runtime_get() before
proceeding to access hardware?
> - int r;
> -
> - r = pm_runtime_put_autosuspend(tidss->dev);
> - WARN_ON(r < 0);
> + pm_runtime_put_autosuspend(tidss->dev);
> }
[Severity: High]
This is a pre-existing issue, but does tidss_remove() safely handle the
asynchronous suspend scheduled here?
During module unload, tidss_remove() calls drm_atomic_helper_shutdown(),
which queues an async suspend via tidss_runtime_put(). Immediately after,
it calls pm_runtime_disable():
drivers/gpu/drm/tidss/tidss_drv.c:tidss_remove() {
...
drm_atomic_helper_shutdown(ddev);
...
pm_runtime_dont_use_autosuspend(dev);
pm_runtime_disable(dev);
...
}
Calling pm_runtime_disable() cancels the pending autosuspend timer. Does this
leave the hardware powered on after driver removal, causing a power leak and
leaving the PM core state machine in RPM_ACTIVE?
If the device is left in RPM_ACTIVE, could its parent power domain be pinned
active forever, preventing the entire SoC from entering deep sleep states?
Should this teardown sequence ensure the device is synchronously suspended
before disabling runtime PM?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260903-tidss-pre-beagley-v1-0-93928baa8b12@ideasonboard.com?part=9
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 10/10] drm/tidss: oldi: Fix missing of_node_put()s in error paths
2026-09-03 12:09 [PATCH 00/10] drm/tidss: Preparation for AM62P and BeagleY-AI display support Tomi Valkeinen
` (8 preceding siblings ...)
2026-09-03 12:09 ` [PATCH 09/10] drm/tidss: Drop WARN_ON() from tidss_runtime_put() Tomi Valkeinen
@ 2026-09-03 12:10 ` Tomi Valkeinen
9 siblings, 0 replies; 13+ messages in thread
From: Tomi Valkeinen @ 2026-09-03 12:10 UTC (permalink / raw)
To: Devarsh Thakkar, Swamil Jain, Jyri Sarha, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Tomi Valkeinen, dri-devel, devicetree, linux-kernel,
Tomi Valkeinen
If get_oldi_mode() errors early in the function, we don't put the
'companion' device_node. Add the of_node_put() calls.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Fixes: 7246e0929945 ("drm/tidss: Add OLDI bridge support")
---
drivers/gpu/drm/tidss/tidss_oldi.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/tidss/tidss_oldi.c b/drivers/gpu/drm/tidss/tidss_oldi.c
index 624f1646fb07..82b059f85244 100644
--- a/drivers/gpu/drm/tidss/tidss_oldi.c
+++ b/drivers/gpu/drm/tidss/tidss_oldi.c
@@ -383,12 +383,16 @@ static int get_oldi_mode(struct device_node *oldi_tx, int *companion_instance)
*/
return OLDI_MODE_SINGLE_LINK;
- if (of_property_read_u32(companion, "reg", &companion_reg))
+ if (of_property_read_u32(companion, "reg", &companion_reg)) {
+ of_node_put(companion);
return OLDI_MODE_UNSUPPORTED;
+ }
- if (companion_reg > (TIDSS_MAX_OLDI_TXES - 1))
+ if (companion_reg > (TIDSS_MAX_OLDI_TXES - 1)) {
/* Invalid companion OLDI reg value. */
+ of_node_put(companion);
return OLDI_MODE_UNSUPPORTED;
+ }
*companion_instance = (int)companion_reg;
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread