drm/tidss: Add OLDI bridge support
Subsystems (5)
v9 cover drm/tidss: Add OLDI bridge support
Hello all,
This patch series adds support for the dual OLDI TXes supported in Texas Instruments' AM62x and AM62Px family of SoCs. The OLDI TX hardware supports single-lvds, lvds-clone, and dual-lvds modes. These TXes have now been represented through DRM bridges within TI-DSS.
* Some history and hardware description for this patch series *
This patch series is a complete re-vamp from the previously posted series[1] and hence, the version index has been reset to v1. The OLDI support from that series was dropped and only the base support for AM62x DSS was kept (and eventually merged)[2].
The OLDI display that the tidss driver today supports, could not be extended for the newer SoCs. The OLDI display in tidss is modelled after the DSS and OLDI hardware in the AM65x SoC. The DSS in AM65x SoC, has two video-ports. Both these video-ports (VP) output DPI video signals. One of the DPI output (from VP1) from the DSS connects to a singular OLDI TX present inside the SoC. There is no other way for the DPI from VP1 to be taken out of the SoC. The other DPI output however - the one from VP2 - is taken out of the SoC as is. Hence we have an OLDI bus output and a DPI bus output from the SoC. Since the VP1 and OLDI are tightly coupled, the tidss driver considers them as a single entity. That is why, any OLDI sink connects directly to the DSS ports in the OF graphs.
The newer SoCs have varying DSS and OLDI integrations.
The AM62x DSS also has 2 VPs. The 2nd VP, VP2, outputs DPI signals which are taken out of the SoC - similar to the AM65x above. For the VP1, there are 2 OLDI TXes. These OLDI TXes can only receive DPI signals from VP1, and don't connect to VP2 at all.
The AM62Px SoC has 2 OLDI TXes like AM62x SoC. However, the AM62Px SoC also has 2 separate DSSes. The 2 OLDI TXes can now be shared between the 2 VPs of the 2 DSSes.
The addition of the 2nd OLDI TX (and a 2nd DSS in AM62Px) creates a need for some major changes for a full feature experience.
1. The OF graph needs to be updated to accurately show the data flow.
2. The tidss and OLDI drivers now need to support the dual-link and the cloned single-link OLDI video signals.
3. The drivers also need to support the case where 2 OLDI TXes are connected to 2 different VPs - thereby creating 2 independent streams of single-link OLDI outputs.
Note that the OLDI does not have registers of its own. It is still dependent on the parent VP. The VP that provides the DPI video signals to the OLDI TXes, also gives the OLDI TXes all the config data. That is to say, the hardware doesn't sit on the bus directly - but does so through the DSS.
In light of all of these hardware variations, it was decided to have a separate OLDI driver (unlike AM65x) but not entirely separate so as to be a platform device. The OLDI TXes are now being represented as DRM bridges under the tidss.
* Regarding the Dependency Patches *
Since the OLDI TXes have a hardware dependency with the parent VP(s), the OLDI configuration needs to happen before that VP is enabled for streaming. VP stream enable takes place in tidss_crtc_atomic_enable hook. I have posted patches[0] allowing DRM bridges to get pre-enabled before the CRTC of that bridge is enabled. Without those patches, some warnings or glitches may be observed.
* Regarding the Drop of Clone Mode support *
Another key point to note is that the support for clone mode has been dropped from the tidss OLDI driver, from v5 onwards. If the DT is configured for a clone mode, the driver will report an error and exit. This has been done because the driver was not supporting a specific case of clone mode where 2 OLDI sink bridges connected to the 2 OLDI TXes require active programming (unlike the simple-panels which do not). The driver does not support creation of two encoder-bridge pipelines (along with the parent tidss driver) to allow program any subsequent bridges (OLDI sinks and bridges thereafter).
The code fragments that write the OLDI config to enable clone mode have been kept as they are, for future, but the driver will not continue to probe if it detects a clone mode configuration, for the time being.
This drop of clone mode support can be undone by applying this _soft-tested_ patch[6] on top of this series. This patch will revert the driver to previous revisions and will allow OLDI sinks that don't require active programming (for
example: simple-panels) to work with the driver. Note that this isn't the ideal way to run clone mode, but it just works for any bridge pipeline after OLDT TX that does not require additional configuration after the OLDI (for example: a couple of simple lvds panels connected directly to the OLDI TXes in clone mode).
These patches have been tested on AM625 based Beagleplay[3] platform with a Lincolntech LCD185 dual-lvds panel. The patches with complete support including the expected devicetree configuration of the OLDI TXes can be found in the "next_oldi-v9_1_tests" branch of my github fork[4]. This branch also has support for Microtips dual-lvds panel (SK-LCD1) which is compatible with the SK-AM625 EVM platform.
I'd appreciate it if somebody can test it, and report back if they observe any issues.
Thanks,
Aradhya
* Important note about the authorship of patches *
All the patches in the of this series were authored when I owned a "ti.com" based email id, i.e. <[email protected]>. This email id is not in use anymore, and all the work done later has been part of my personal work. Since the original patches were authored using TI's email id, I have maintained the original authorships as they are, as well as their sign offs.
I have further added another sign off that uses my current (and personal) email id, the one that is being used to send this revision, i.e. <[email protected]>.
---
Change Log:
V9:
- Fixes and improvements over V8, in patches 2/4 and 4/4.
* Reword the "ti,companion-oldi" property description. (Michael)
* Fix the missing "ti,companion-oldi" property in the dt-schema example. (Michael)
* Fix the get_oldi_mode() logic, for secondary-oldi in dual-link mode.
* Allow secondary-oldi to skip getting serial-clk and io-ctrl syscon regs.
* Rename enum "OLDI_MODE_CLONE_SECONDARY_SINGLE_LINK" to "OLDI_MODE_SECONDARY_CLONE_SINGLE_LINK".
- Rebase to latest drm-misc-next.
V8:
- V8 brings some additional changes that are required to properly set up Clone Mode in future:
* Allow for secondary OLDIs to have the "companion-oldi" devicetree property.
* Have separate Secondary OLDI enums for Dual-link and Clone Mode.
* Change get_oldi_mode() logic to distinguish between the 2 different types of secondary OLDIs (dual-link and clone-mode). This is required because the secondary OLDI of clone-mode needs to get registered as a drm_bridge device (when we have the full support in future). The secondary OLDI of dual-link mode does not need to be set up as a drm_bridge.
- Add "ti,am62l-dss" to the list of compatibles that cannot have the "oldi-transmitter" property or multiple endpoints on port@0.
- Fix some typos and the one wrong variable type in the tidss_oldi driver.
- Drop Tomi Valkeinen's R-b from patches 2/4 and 4/4 because the logic has fairly changed, and requires another pass at a review. Also drop Rob Herring's R-b tag from patch 2/4.
- Drop T-b tags from Alexander Sverdlin and Michael Walle, from patch 4/4.
V7:
- Use for_each_available_child_of_node() instead of for_each_child_of_node() to parse through the OLDI TX device nodes, as recommended by Alexander Sverdlin.
- Rebase to drm-misc-next.
As part of this, update the bridge attach part of the code, as encoders are now passed as a parameter in the drm_bridge_attach() call after Maxime Ripard's change in commit 98007a0d56b0
("drm/bridge: Add encoder parameter to drm_bridge_funcs.attach").
- Add Alexander Sverdlin's T-b tag in patch 4/4, and Tomi Valkeinen's R-b in
patch 3/4.
V6:
- Add patch 3/4: ("drm/tidss: Add 'AM65X_' prefix to OLDI identifiers"), to segregate the pre-existing OLDI code intended for AM65x, from the new-coming OLDI bridge driver related code.
- Cosmetic changes suggested by Tomi Valkeinen in patch 4.
- Rebase to latest linux-next (next-20250226).
- Add Rob Herring's R-b in patch-2, and Tomi Valkeinen's R-b tags in patches 2 and 4.
V5:
- Implement fixes suggested by Rob Herring in patch-2.
* Drop the example from OLDI schema.
* Fix the DSS schema conditions.
- Drop the OLDI clone mode support from the driver as it was incomplete and could not account for cases where OLDI TXes were connected to another pair of bridges that would require additional programming, instead of a pair of simple-panels which wouldn't.
V4:
- Implement fixes suggested by Krzysztof Kozlowski:
* Squash patches v3:2/4 and v3:3/4 to v4:2/3, and add more hardware details in commit description.
* Change the serial clock name for OLDI, from "s_clk" to "serial".
* Fix the required condition in the OLDI schema.
* Other minor fixes.
- Change "oldi-txes" OLDI DT node name to "oldi-transmitters".
- Update secondary-OLDI property requirements to be more relaxing for AM62P DSS configuration.
V3:
- Fix the dt_binding_check warning in patch 3/4[5] by adding "additionalProperties" constraint.
V2:
- Add all the R-b and A-b tags from Laurent Pinchart, Rob Herring, and Tomi Valkeinen.
- Reword the subject for patch 1/4.
- Reword the commit descriptions to add proper hardware detail.
- Drop the change in schema reference for port@0 in patch 3/4.
- Lots of improvements for patch 4/4.
* Refactor OLDI selection logic in tidss_oldi_tx_power().
* Add "companion_instance" support to identify the OLDI index in dual-link or cloned sinle-link modes.
* De-initialize tidss_oldi during tidss removal.
* Use dev_err_probe() instead of dev_err().
* Drop OLDI(n) macro.
* Move OLDI Config register bits to tidss_dispc_regs.h.
* Drop oldi bridge atomic_check().
* s/%d/%u for all print instances of "oldi_instance".
* Move OLDI init after DISPC init in tidss_probe.
* Use devm_drm_of_get_bridge() instead of drm_of_find_panel_or_bridge() to find the next bridge and drop all the drm_panel support from tidss_oldi.
Previous revisions:
V1: https://lore.kernel.org/all/[email protected]/
V2: https://lore.kernel.org/all/[email protected]/
V3: https://lore.kernel.org/all/[email protected]/
V4: https://lore.kernel.org/all/[email protected]/
V5: https://lore.kernel.org/all/[email protected]/
V6: https://lore.kernel.org/all/[email protected]/
V7: https://lore.kernel.org/all/[email protected]/
V8: https://lore.kernel.org/all/[email protected]/
[0]: Dependency Patches:
("drm/atomic-helper: Refactor crtc & encoder-bridge op loops into separate functions")
https://lore.kernel.org/all/[email protected]/
("drm/atomic-helper: Separate out bridge pre_enable/post_disable from enable/disable")
https://lore.kernel.org/all/[email protected]/
("drm/atomic-helper: Re-order bridge chain pre-enable and post-disable")
https://lore.kernel.org/all/[email protected]/
[1]: AM62 OLDI Series - v7
https://lore.kernel.org/all/[email protected]/
[2]: AM62 DSS Series - v9
https://lore.kernel.org/all/[email protected]/
[3]: TI AM625 SoC based Beagleplay platform
https://www.beagleboard.org/boards/beagleplay
[4]: GitHub Fork for OLDI tests
https://github.com/aradhya07/linux-ab/tree/next_oldi-v9_1_tests
[5]: ("ti,am65x-dss.yaml: oldi-txes: Missing additionalProperties/
unevaluatedProperties constraint")
https://lore.kernel.org/all/[email protected]/
[6]: Undo drop of OLDI clone mode support
https://gist.github.com/aradhya07/383b4679453025ba515d58858bd813ca
Aradhya Bhatia (4):
dt-bindings: display: ti,am65x-dss: Re-indent the example
dt-bindings: display: ti: Add schema for AM625 OLDI Transmitter drm/tidss: Mark AM65x OLDI code separately
drm/tidss: Add OLDI bridge support
.../bindings/display/ti/ti,am625-oldi.yaml | 79 +++ .../bindings/display/ti/ti,am65x-dss.yaml | 199 +++++- MAINTAINERS | 1 + drivers/gpu/drm/tidss/Makefile | 3 +- drivers/gpu/drm/tidss/tidss_dispc.c | 92 +-- drivers/gpu/drm/tidss/tidss_dispc.h | 7 +- drivers/gpu/drm/tidss/tidss_dispc_regs.h | 29 +- drivers/gpu/drm/tidss/tidss_drv.c | 9 + drivers/gpu/drm/tidss/tidss_drv.h | 5 + drivers/gpu/drm/tidss/tidss_kms.c | 2 +- drivers/gpu/drm/tidss/tidss_oldi.c | 598 ++++++++++++++++++ drivers/gpu/drm/tidss/tidss_oldi.h | 43 ++ 12 files changed, 1001 insertions(+), 66 deletions(-) create mode 100644 Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml create mode 100644 drivers/gpu/drm/tidss/tidss_oldi.c create mode 100644 drivers/gpu/drm/tidss/tidss_oldi.h
base-commit: 126bf397bf58485cdd631824190cdcfeb86f5d9b
Signature · 1 line
2.34.1
PATCH v9 1/4 dt-bindings: display: ti,am65x-dss: Re-indent the example
From: Aradhya Bhatia <[email protected]>
Reduce tab size from 8 spaces to 4 spaces to make the bindings consistent, and easy to expand.
--- .../bindings/display/ti/ti,am65x-dss.yaml | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-)
Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml +27 -27
@@ -161,32 +161,32 @@ examples: #include <dt-bindings/soc/ti,sci_pm_domain.h> dss: dss@4a00000 { - compatible = "ti,am65x-dss"; - reg = <0x04a00000 0x1000>, /* common */ - <0x04a02000 0x1000>, /* vidl1 */ - <0x04a06000 0x1000>, /* vid */ - <0x04a07000 0x1000>, /* ovr1 */ - <0x04a08000 0x1000>, /* ovr2 */ - <0x04a0a000 0x1000>, /* vp1 */ - <0x04a0b000 0x1000>, /* vp2 */ - <0x04a01000 0x1000>; /* common1 */ - reg-names = "common", "vidl1", "vid", - "ovr1", "ovr2", "vp1", "vp2", "common1"; - ti,am65x-oldi-io-ctrl = <&dss_oldi_io_ctrl>; - power-domains = <&k3_pds 67 TI_SCI_PD_EXCLUSIVE>; - clocks = <&k3_clks 67 1>, - <&k3_clks 216 1>, - <&k3_clks 67 2>; - clock-names = "fck", "vp1", "vp2"; - interrupts = <GIC_SPI 166 IRQ_TYPE_EDGE_RISING>; - ports { - #address-cells = <1>; - #size-cells = <0>; - port@0 { - reg = <0>; - oldi_out0: endpoint { - remote-endpoint = <&lcd_in0>; - }; - }; + compatible = "ti,am65x-dss"; + reg = <0x04a00000 0x1000>, /* common */ + <0x04a02000 0x1000>, /* vidl1 */ + <0x04a06000 0x1000>, /* vid */ + <0x04a07000 0x1000>, /* ovr1 */ + <0x04a08000 0x1000>, /* ovr2 */ + <0x04a0a000 0x1000>, /* vp1 */ + <0x04a0b000 0x1000>, /* vp2 */ + <0x04a01000 0x1000>; /* common1 */ + reg-names = "common", "vidl1", "vid", + "ovr1", "ovr2", "vp1", "vp2", "common1"; + ti,am65x-oldi-io-ctrl = <&dss_oldi_io_ctrl>; + power-domains = <&k3_pds 67 TI_SCI_PD_EXCLUSIVE>; + clocks = <&k3_clks 67 1>, + <&k3_clks 216 1>, + <&k3_clks 67 2>; + clock-names = "fck", "vp1", "vp2"; + interrupts = <GIC_SPI 166 IRQ_TYPE_EDGE_RISING>; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + oldi_out0: endpoint { + remote-endpoint = <&lcd_in0>; + }; }; + }; };
Signature · 1 line
2.34.1
PATCH v9 2/4 dt-bindings: display: ti: Add schema for AM625 OLDI Transmitter
In reply to Aradhya BhatiaFrom: Aradhya Bhatia <[email protected]>
The OLDI transmitters (TXes) do not have registers of their own, and are dependent on the source video-ports (VPs) from the DSS to provide configuration data. This hardware doesn't directly sit on the internal bus of the SoC, but does so via the DSS. Hence, the OLDI TXes are supposed to be child nodes under the DSS, and not independent devices.
Two of the OLDI TXes can function in tandem to output dual-link OLDI output, or cloned single-link outputs. In these cases, one OLDI will be the primary OLDI, and the other one, a companion. The following diagram represents such a configuration.
+-----+-----+ +-------+
| | | | |
| | VP1 +----+--->+ OLDI0 | (Primary - may need companion)
| | | | | |
| DSS +-----+ | +-------+
| | | |
| | VP2 | | +-------+
| | | | | |
+-----+-----+ +--->+ OLDI1 | (Companion OLDI)
| |
+-------+The DSS in AM625 SoC has a configuration like the one above. The AM625 DSS VP1 (port@0) can connect and control 2 OLDI TXes, to use them in dual-link or cloned single-link OLDI modes. It is only the VP1 that can connect to either OLDI TXes for the AM625 DSS, and not the VP2.
Alternatively, on some future TI SoCs, along with the above configuration, the OLDI TX can _also_ connect to separate video sources, making them work entirely independent of each other. In this case, neither of the OLDIs are "companion" or "secondary" OLDIs, and nor do they require one. They both are independent and primary OLDIs. The following diagram represents such a configuration.
+-----+-----+ +-------+ | | | | | | | VP1 +--+----------->+ OLDI0 | (Primary - may need companion) | | | | | | | +-----+ | +-------+ | | | | | | VP2 | | | | | | | DSS +-----+ | +---+ +-------+ | | | +-->+ M | | | | | VP3 +----->+ U +--->+ OLDI1 | (Companion or Primary) | | | | X | | | | +-----+ +---+ +-------+ | | | | | VP4 | | | | +-----+-----+
Note that depending on the mux configuration, the OLDIs can either be working together in tandem - sourced by VP1, OR, they could be working independently sourced by VP1 and VP3 respectively.
The idea is to support all the configurations with this OLDI TX schema.
The OLDI functionality is further supported by a system-control module, which contains a few registers to control OLDI IO power and other electrical characteristics of the IO lanes.
Add devicetree binding schema for the OLDI TXes to support various configurations, and extend their support to the AM625 DSS.
---
Changes Log:
V9:
- Reword the "ti,companion-oldi" property description.
- Fix the missing "ti,companion-oldi" property in the schema example.
- v8 of this patch: https://lore.kernel.org/all/[email protected]/
V8:
- Drop the condition that made the "secondary-oldi" and "companion-oldi" properties mutually exclusive.
- Add "ti,am62l-dss" compatible to the list of compatibles that cannot
use the multiple endpoints or have "oldi-transmitters", on port@0.
- Because of above, drop R-b tags from Tomi Valkeinen, and Rob Herring.
- v7 of this patch: https://lore.kernel.org/all/[email protected]/
--- .../bindings/display/ti/ti,am625-oldi.yaml | 79 +++++++++ .../bindings/display/ti/ti,am65x-dss.yaml | 157 ++++++++++++++++++ MAINTAINERS | 1 + 3 files changed, 237 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml
Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml new file +79 -0
@@ -0,0 +1,79 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/ti/ti,am625-oldi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments AM625 OLDI Transmitter + +maintainers: + - Tomi Valkeinen <[email protected]> + - Aradhya Bhatia <[email protected]> + +description: + The AM625 TI Keystone OpenLDI transmitter (OLDI TX) supports serialized RGB + pixel data transmission between host and flat panel display over LVDS (Low + Voltage Differential Sampling) interface. The OLDI TX consists of 7-to-1 data + serializers, and 4-data and 1-clock LVDS outputs. It supports the LVDS output + formats "jeida-18", "jeida-24" and "vesa-18", and can accept 24-bit RGB or + padded and un-padded 18-bit RGB bus formats as input. + +properties: + reg: + maxItems: 1 + + clocks: + maxItems: 1 + description: serial clock input for the OLDI transmitters + + clock-names: + const: serial + + ti,companion-oldi: + $ref: /schemas/types.yaml#/definitions/phandle + description: + phandle to companion OLDI transmitter. This property is required for both + the OLDI TXes if they are expected to work either in dual-lvds mode or in + clone mode. This property should point to the other OLDI TX's phandle. + + ti,secondary-oldi: + type: boolean + description: + Boolean property to mark the OLDI transmitter as the secondary one, when the + OLDI hardware is expected to run as a companion HW, in cases of dual-lvds + mode or clone mode. The primary OLDI hardware is responsible for all the + hardware configuration. + + ti,oldi-io-ctrl: + $ref: /schemas/types.yaml#/definitions/phandle + description: + phandle to syscon device node mapping OLDI IO_CTRL registers found in the + control MMR region. These registers are required to toggle the I/O lane + power, and control its electrical characteristics. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: Parallel RGB input port + + port@1: + $ref: /schemas/graph.yaml#/properties/port + description: LVDS output port + + required: + - port@0 + - port@1 + +required: + - reg + - clocks + - clock-names + - ti,oldi-io-ctrl + - ports + +additionalProperties: false + +...
Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml +157 -0
184 lines not on this page · raw message
MAINTAINERS +1 -0
@@ -8097,6 +8097,7 @@ M: Tomi Valkeinen <[email protected]> L: [email protected] 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,am65x-dss.yaml F: Documentation/devicetree/bindings/display/ti/ti,j721e-dss.yaml F: Documentation/devicetree/bindings/display/ti/ti,k2g-dss.yaml
Signature · 1 line
2.34.1
Re: [PATCH v9 2/4] dt-bindings: display: ti: Add schema for AM625 OLDI Transmitter
Quoted 84 lines · Aradhya Bhatia
From: Aradhya Bhatia <[email protected]>
The OLDI transmitters (TXes) do not have registers of their own, and are dependent on the source video-ports (VPs) from the DSS to provide configuration data. This hardware doesn't directly sit on the internal bus of the SoC, but does so via the DSS. Hence, the OLDI TXes are supposed to be child nodes under the DSS, and not independent devices.
Two of the OLDI TXes can function in tandem to output dual-link OLDI output, or cloned single-link outputs. In these cases, one OLDI will be the primary OLDI, and the other one, a companion. The following diagram represents such a configuration.
+-----+-----+ +-------+ | | | | | | | VP1 +----+--->+ OLDI0 | (Primary - may need companion) | | | | | | | DSS +-----+ | +-------+ | | | | | | VP2 | | +-------+ | | | | | | +-----+-----+ +--->+ OLDI1 | (Companion OLDI) | | +-------+The DSS in AM625 SoC has a configuration like the one above. The AM625 DSS VP1 (port@0) can connect and control 2 OLDI TXes, to use them in dual-link or cloned single-link OLDI modes. It is only the VP1 that can connect to either OLDI TXes for the AM625 DSS, and not the VP2.
Alternatively, on some future TI SoCs, along with the above configuration, the OLDI TX can _also_ connect to separate video sources, making them work entirely independent of each other. In this case, neither of the OLDIs are "companion" or "secondary" OLDIs, and nor do they require one. They both are independent and primary OLDIs. The following diagram represents such a configuration.
+-----+-----+ +-------+ | | | | | | | VP1 +--+----------->+ OLDI0 | (Primary - may need companion) | | | | | | | +-----+ | +-------+ | | | | | | VP2 | | | | | | | DSS +-----+ | +---+ +-------+ | | | +-->+ M | | | | | VP3 +----->+ U +--->+ OLDI1 | (Companion or Primary) | | | | X | | | | +-----+ +---+ +-------+ | | | | | VP4 | | | | +-----+-----+Note that depending on the mux configuration, the OLDIs can either be working together in tandem - sourced by VP1, OR, they could be working independently sourced by VP1 and VP3 respectively.
The idea is to support all the configurations with this OLDI TX schema.The OLDI functionality is further supported by a system-control module, which contains a few registers to control OLDI IO power and other electrical characteristics of the IO lanes.
Add devicetree binding schema for the OLDI TXes to support various configurations, and extend their support to the AM625 DSS.
Signed-off-by Aradhya Bhatia <[email protected]>Signed-off-by Aradhya Bhatia <[email protected]>---
Changes Log:
V9:
- Reword the "ti,companion-oldi" property description.
- Fix the missing "ti,companion-oldi" property in the schema example.
- v8 of this patch: https://lore.kernel.org/all/[email protected]/V8:
- Drop the condition that made the "secondary-oldi" and "companion-oldi" properties mutually exclusive.
- Add "ti,am62l-dss" compatible to the list of compatibles that cannot
use the multiple endpoints or have "oldi-transmitters", on port@0.
- Because of above, drop R-b tags from Tomi Valkeinen, and Rob Herring.
- v7 of this patch: https://lore.kernel.org/all/[email protected]/
Quoted 7 lines
--- .../bindings/display/ti/ti,am625-oldi.yaml | 79 +++++++++ .../bindings/display/ti/ti,am65x-dss.yaml | 157 ++++++++++++++++++ MAINTAINERS | 1 + 3 files changed, 237 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml
PATCH v9 3/4 drm/tidss: Mark AM65x OLDI code separately
In reply to Aradhya BhatiaThe dss dt schema and the tidss driver have kept the single-link OLDI in AM65x integrated with the parent video-port (VP) from DSS (as the OLDI configuration happens from the source VP only).
To help configure the dual-lvds modes that the OLDI has to offer in devices AM62x and later, a new OLDI bridge driver will be introduced.
Mark the existing OLDI code separately by renaming all the current OLDI identifiers with the 'AM65X_' prefix in tidss driver, to help distinguish from the upcoming OLDI bridge driver.
--- drivers/gpu/drm/tidss/tidss_dispc.c | 68 ++++++++++++------------ drivers/gpu/drm/tidss/tidss_dispc.h | 2 +- drivers/gpu/drm/tidss/tidss_dispc_regs.h | 15 +++--- drivers/gpu/drm/tidss/tidss_kms.c | 2 +- 4 files changed, 44 insertions(+), 43 deletions(-)
drivers/gpu/drm/tidss/tidss_dispc.c +33 -35
@@ -146,7 +146,7 @@ static const u16 tidss_am65x_common_regs[DISPC_COMMON_REG_TABLE_LEN] = {const struct dispc_features dispc_am65x_feats = { .max_pclk_khz = { [DISPC_VP_DPI ] =165000 , - [DISPC_VP_OLDI ] =165000 , + [DISPC_VP_OLDI_AM65X ] =165000 , }, .scaling = {
@@ -176,7 +176,7 @@ const struct dispc_features dispc_am65x_feats = { .vp_name = { "vp1", "vp2" }, .ovr_name = { "ovr1", "ovr2" }, .vpclk_name = { "vp1", "vp2" }, - .vp_bus_type = { DISPC_VP_OLDI, DISPC_VP_DPI }, + .vp_bus_type = { DISPC_VP_OLDI_AM65X, DISPC_VP_DPI }, .vp_feat = { .color = { .has_ctm = true,
@@ -491,7 +491,7 @@ struct dispc_device {void __iomem *base_ovr[TIDSS_MAX_PORTS ];void __iomem *base_vp[TIDSS_MAX_PORTS ]; -struct regmap *oldi_io_ctrl; +struct regmap *am65x_oldi_io_ctrl;struct clk *vp_clk[TIDSS_MAX_PORTS ];
@@ -1016,13 +1016,11 @@ void dispc_set_irqenable(struct dispc_device *dispc, dispc_irq_t mask) } } -enum dispc_oldi_mode_reg_val {SPWG_18 =0 ,JEIDA_24 =1 ,SPWG_24 =2 }; -struct dispc_bus_format {u32 bus_fmt;u32 data_width;bool is_oldi_fmt; -enum dispc_oldi_mode_reg_val oldi_mode_reg_val; +enum oldi_mode_reg_val am65x_oldi_mode_reg_val; };static const struct dispc_bus_format dispc_bus_formats[] = {
@@ -1066,7 +1064,7 @@ int dispc_vp_bus_check(struct dispc_device *dispc, u32 hw_videoport,return -EINVAL ; } -if (dispc->feat->vp_bus_type[hw_videoport] !=DISPC_VP_OLDI && +if (dispc->feat->vp_bus_type[hw_videoport] !=DISPC_VP_OLDI_AM65X && fmt->is_oldi_fmt) {dev_dbg (dispc->dev,"%s: %s is not OLDI-port\n" , __func__, dispc->feat->vp_name[hw_videoport]);
@@ -1076,23 +1074,23 @@ int dispc_vp_bus_check(struct dispc_device *dispc, u32 hw_videoport,return 0 ; } -static void dispc_oldi_tx_power (struct dispc_device *dispc,bool power) +static void dispc_am65x_oldi_tx_power (struct dispc_device *dispc,bool power) { -u32 val = power ?0 :OLDI_PWRDN_TX ; +u32 val = power ?0 :AM65X_OLDI_PWRDN_TX ; -if (WARN_ON (!dispc->oldi_io_ctrl)) +if (WARN_ON (!dispc->am65x_oldi_io_ctrl))return ; -regmap_update_bits (dispc->oldi_io_ctrl,OLDI_DAT0_IO_CTRL , -OLDI_PWRDN_TX , val); -regmap_update_bits (dispc->oldi_io_ctrl,OLDI_DAT1_IO_CTRL , -OLDI_PWRDN_TX , val); -regmap_update_bits (dispc->oldi_io_ctrl,OLDI_DAT2_IO_CTRL , -OLDI_PWRDN_TX , val); -regmap_update_bits (dispc->oldi_io_ctrl,OLDI_DAT3_IO_CTRL , -OLDI_PWRDN_TX , val); -regmap_update_bits (dispc->oldi_io_ctrl,OLDI_CLK_IO_CTRL , -OLDI_PWRDN_TX , val); +regmap_update_bits (dispc->am65x_oldi_io_ctrl,AM65X_OLDI_DAT0_IO_CTRL , +AM65X_OLDI_PWRDN_TX , val); +regmap_update_bits (dispc->am65x_oldi_io_ctrl,AM65X_OLDI_DAT1_IO_CTRL , +AM65X_OLDI_PWRDN_TX , val); +regmap_update_bits (dispc->am65x_oldi_io_ctrl,AM65X_OLDI_DAT2_IO_CTRL , +AM65X_OLDI_PWRDN_TX , val); +regmap_update_bits (dispc->am65x_oldi_io_ctrl,AM65X_OLDI_DAT3_IO_CTRL , +AM65X_OLDI_PWRDN_TX , val); +regmap_update_bits (dispc->am65x_oldi_io_ctrl,AM65X_OLDI_CLK_IO_CTRL , +AM65X_OLDI_PWRDN_TX , val); } static void dispc_set_num_datalines(struct dispc_device *dispc,
@@ -1121,8 +1119,8 @@ static void dispc_set_num_datalines(struct dispc_device *dispc,VP_REG_FLD_MOD (dispc, hw_videoport,DISPC_VP_CONTROL , v,10 ,8 ); } -static void dispc_enable_oldi (struct dispc_device *dispc,u32 hw_videoport, -const struct dispc_bus_format *fmt) +static void dispc_enable_am65x_oldi (struct dispc_device *dispc,u32 hw_videoport, +const struct dispc_bus_format *fmt) {u32 oldi_cfg =0 ;u32 oldi_reset_bit =BIT (5 + hw_videoport);
@@ -1141,7 +1139,7 @@ static void dispc_enable_oldi(struct dispc_device *dispc, u32 hw_videoport, oldi_cfg |=BIT (7 );/* DEPOL */ - oldi_cfg =FLD_MOD (oldi_cfg, fmt->oldi_mode_reg_val,3 ,1 ); + oldi_cfg =FLD_MOD (oldi_cfg, fmt->am65x_oldi_mode_reg_val,3 ,1 ); oldi_cfg |=BIT (12 );/* SOFTRST */
@@ -1170,10 +1168,10 @@ void dispc_vp_prepare(struct dispc_device *dispc, u32 hw_videoport,if (WARN_ON (!fmt))return ; -if (dispc->feat->vp_bus_type[hw_videoport] ==DISPC_VP_OLDI ) { -dispc_oldi_tx_power (dispc, true); +if (dispc->feat->vp_bus_type[hw_videoport] ==DISPC_VP_OLDI_AM65X ) { +dispc_am65x_oldi_tx_power (dispc, true); -dispc_enable_oldi (dispc, hw_videoport, fmt); +dispc_enable_am65x_oldi (dispc, hw_videoport, fmt); } }
@@ -1229,7 +1227,7 @@ void dispc_vp_enable(struct dispc_device *dispc, u32 hw_videoport, align = true;/* always use DE_HIGH for OLDI */ -if (dispc->feat->vp_bus_type[hw_videoport] ==DISPC_VP_OLDI ) +if (dispc->feat->vp_bus_type[hw_videoport] ==DISPC_VP_OLDI_AM65X ) ieo = false; dispc_vp_write(dispc, hw_videoport, DISPC_VP_POL_FREQ,
@@ -1255,10 +1253,10 @@ 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->vp_bus_type[hw_videoport] ==DISPC_VP_OLDI ) { +if (dispc->feat->vp_bus_type[hw_videoport] ==DISPC_VP_OLDI_AM65X ) {dispc_vp_write (dispc, hw_videoport,DISPC_VP_DSS_OLDI_CFG ,0 ); -dispc_oldi_tx_power (dispc, false); +dispc_am65x_oldi_tx_power (dispc, false); } }
@@ -2852,15 +2850,15 @@ static int dispc_iomap_resource(struct platform_device *pdev, const char *name,static int dispc_init_am65x_oldi_io_ctrl (struct device *dev,struct dispc_device *dispc) { - dispc->oldi_io_ctrl = + dispc->am65x_oldi_io_ctrl =syscon_regmap_lookup_by_phandle (dev->of_node,"ti,am65x-oldi-io-ctrl" ); -if (PTR_ERR (dispc->oldi_io_ctrl) == -ENODEV ) { - dispc->oldi_io_ctrl =NULL ; - }else if (IS_ERR (dispc->oldi_io_ctrl)) { +if (PTR_ERR (dispc->am65x_oldi_io_ctrl) == -ENODEV ) { + dispc->am65x_oldi_io_ctrl =NULL ; + }else if (IS_ERR (dispc->am65x_oldi_io_ctrl)) {dev_err (dev,"%s: syscon_regmap_lookup_by_phandle failed %ld\n" , - __func__,PTR_ERR (dispc->oldi_io_ctrl)); -return PTR_ERR (dispc->oldi_io_ctrl); + __func__,PTR_ERR (dispc->am65x_oldi_io_ctrl)); +return PTR_ERR (dispc->am65x_oldi_io_ctrl); }return 0 ; }
drivers/gpu/drm/tidss/tidss_dispc.h +1 -1
@@ -58,7 +58,7 @@ struct dispc_errata {enum dispc_vp_bus_type {DISPC_VP_DPI ,/* DPI output */ -DISPC_VP_OLDI ,/* OLDI (LVDS) output */ +DISPC_VP_OLDI_AM65X ,/* OLDI (LVDS) output for AM65x DSS */ DISPC_VP_INTERNAL ,/* SoC internal routing */ DISPC_VP_TIED_OFF ,/* Tied off / Unavailable */ DISPC_VP_MAX_BUS_TYPE ,
drivers/gpu/drm/tidss/tidss_dispc_regs.h +9 -6
@@ -226,18 +226,21 @@ enum dispc_common_regs {#define DISPC_VP_DSS_DMA_THREADSIZE 0x170/* J721E */ #define DISPC_VP_DSS_DMA_THREADSIZE_STATUS 0x174/* J721E */ +/* LVDS Format values for OLDI_MAP field in DISPC_VP_OLDI_CFG register */ +enum oldi_mode_reg_val {SPWG_18 =0 ,JEIDA_24 =1 ,SPWG_24 =2 }; +/* * OLDI IO_CTRL register offsets. On AM654 the registers are found * from CTRL_MMR0, there the syscon regmap should map 0x14 bytes from * CTRLMMR0P1_OLDI_DAT0_IO_CTRL to CTRLMMR0P1_OLDI_CLK_IO_CTRL * register range. */ -#define OLDI_DAT0_IO_CTRL 0x00 -#define OLDI_DAT1_IO_CTRL 0x04 -#define OLDI_DAT2_IO_CTRL 0x08 -#define OLDI_DAT3_IO_CTRL 0x0C -#define OLDI_CLK_IO_CTRL 0x10 +#define AM65X_OLDI_DAT0_IO_CTRL 0x00 +#define AM65X_OLDI_DAT1_IO_CTRL 0x04 +#define AM65X_OLDI_DAT2_IO_CTRL 0x08 +#define AM65X_OLDI_DAT3_IO_CTRL 0x0C +#define AM65X_OLDI_CLK_IO_CTRL 0x10 -#define OLDI_PWRDN_TX BIT(8) +#define AM65X_OLDI_PWRDN_TX BIT(8)#endif /* __TIDSS_DISPC_REGS_H */
drivers/gpu/drm/tidss/tidss_kms.c +1 -1
@@ -144,7 +144,7 @@ static int tidss_dispc_modeset_init(struct tidss_device *tidss)dev_dbg (dev,"Setting up panel for port %d\n" , i);switch (feat->vp_bus_type[i]) { -case DISPC_VP_OLDI : +case DISPC_VP_OLDI_AM65X : enc_type =DRM_MODE_ENCODER_LVDS ; conn_type =DRM_MODE_CONNECTOR_LVDS ;break ;
Signature · 1 line
2.34.1
PATCH v9 4/4 drm/tidss: Add OLDI bridge support
In reply to Aradhya BhatiaFrom: Aradhya Bhatia <[email protected]>
The AM62x and AM62Px SoCs feature 2 OLDI TXes each, which makes it possible to connect them in dual-link or cloned single-link OLDI display modes. The current OLDI support in tidss_dispc.c can only support for a single OLDI TX, connected to a VP and doesn't really support configuration of OLDIs in the other modes. The current OLDI support in tidss_dispc.c also works on the principle that the OLDI output can only be served by one, and only one, DSS video-port. This isn't the case in the AM62Px SoC, where there are 2 DSS controllers present that share the OLDI TXes.
Having their own devicetree and their own bridge entity will help support the various display modes and sharing possiblilities of the OLDI hardware.
For all these reasons, add support for the OLDI TXes as DRM bridges.
---
Change Log:
V9:
- Fix the get_oldi_mode() logic, for secondary-oldi in dual-link mode.
- Allow secondary-oldi to skip getting serial-clk and io-ctrl syscon regs.
- Rename enum "OLDI_MODE_CLONE_SECONDARY_SINGLE_LINK" to "OLDI_MODE_SECONDARY_CLONE_SINGLE_LINK".
- v8 of this patch: https://lore.kernel.org/all/[email protected]/
V8:
- Change get_oldi_mode() logic to distinguish between the 2 different types
of secondary OLDIs (dual-link and clone-mode). This is required because
the secondary OLDI of clone-mode needs to get registered as a drm_bridge
device (when we have the full support in future). The secondary OLDI of dual-link mode does not need to be set up as a drm_bridge.
- Fix some typos and the one wrong variable type in the tidss_oldi driver.
- Drop Tomi Valkeinen's R-b tag, and T-b tags by Alexander Sverdlin, and
Michael Walle.
- v7 of this patch: https://lore.kernel.org/all/[email protected]/
--- drivers/gpu/drm/tidss/Makefile | 3 +- drivers/gpu/drm/tidss/tidss_dispc.c | 24 +- drivers/gpu/drm/tidss/tidss_dispc.h | 5 + drivers/gpu/drm/tidss/tidss_dispc_regs.h | 14 + drivers/gpu/drm/tidss/tidss_drv.c | 9 + drivers/gpu/drm/tidss/tidss_drv.h | 5 + drivers/gpu/drm/tidss/tidss_oldi.c | 598 +++++++++++++++++++++++ drivers/gpu/drm/tidss/tidss_oldi.h | 43 ++ 8 files changed, 699 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/tidss/tidss_oldi.c create mode 100644 drivers/gpu/drm/tidss/tidss_oldi.h
drivers/gpu/drm/tidss/Makefile +2 -1
@@ -7,6 +7,7 @@ tidss-y := tidss_crtc.o \ tidss_irq.o \ tidss_plane.o \ tidss_scale_coefs.o \ - tidss_dispc.o + tidss_dispc.o \ + tidss_oldi.o obj-$(CONFIG_DRM_TIDSS) += tidss.o
drivers/gpu/drm/tidss/tidss_dispc.c +23 -1
@@ -566,6 +566,29 @@ static u32 dispc_vp_read(struct dispc_device *dispc, u32 hw_videoport, u16 reg)return ioread32 (base + reg); } +int tidss_configure_oldi (struct tidss_device *tidss,u32 hw_videoport, +u32 oldi_cfg) +{ +u32 count =0 ; +u32 oldi_reset_bit =BIT (5 + hw_videoport); + +dispc_vp_write (tidss->dispc, hw_videoport,DISPC_VP_DSS_OLDI_CFG , oldi_cfg); + +while (!(oldi_reset_bit &dispc_read (tidss->dispc,DSS_SYSSTATUS )) && + count <10000 ) + count++; + +if (!(oldi_reset_bit &dispc_read (tidss->dispc,DSS_SYSSTATUS ))) +return -ETIMEDOUT ; + +return 0 ; +} + +void tidss_disable_oldi (struct tidss_device *tidss,u32 hw_videoport) +{ +dispc_vp_write (tidss->dispc, hw_videoport,DISPC_VP_DSS_OLDI_CFG ,0 ); +} +/* * TRM gives bitfields as start:end, where start is the higher bit * number. For example 7:0
@@ -1418,7 +1441,6 @@ void dispc_vp_disable_clk(struct dispc_device *dispc, u32 hw_videoport)* Calculate the percentage difference between the requested pixel clock rate * and the effective rate resulting from calculating the clock divider value. */ -static unsigned int dispc_pclk_diff (unsigned long rate,unsigned long real_rate) {int r = rate /100 , rr = real_rate /100 ;
drivers/gpu/drm/tidss/tidss_dispc.h +5 -0
@@ -101,6 +101,11 @@ extern const struct dispc_features dispc_am62l_feats;extern const struct dispc_features dispc_am65x_feats;extern const struct dispc_features dispc_j721e_feats; +int tidss_configure_oldi (struct tidss_device *tidss,u32 hw_videoport, +u32 oldi_cfg); +void tidss_disable_oldi (struct tidss_device *tidss,u32 hw_videoport); +unsigned int dispc_pclk_diff (unsigned long rate,unsigned long real_rate); +void dispc_set_irqenable (struct dispc_device *dispc,dispc_irq_t mask);dispc_irq_t dispc_read_and_clear_irqstatus (struct dispc_device *dispc);
drivers/gpu/drm/tidss/tidss_dispc_regs.h +14 -0
@@ -226,6 +226,20 @@ enum dispc_common_regs {#define DISPC_VP_DSS_DMA_THREADSIZE 0x170/* J721E */ #define DISPC_VP_DSS_DMA_THREADSIZE_STATUS 0x174/* J721E */ +/* OLDI Config Bits (DISPC_VP_DSS_OLDI_CFG) */ +#define OLDI_ENABLE BIT(0) +#define OLDI_MAP (BIT(1) | BIT(2) | BIT(3)) +#define OLDI_SRC BIT(4) +#define OLDI_CLONE_MODE BIT(5) +#define OLDI_MASTERSLAVE BIT(6) +#define OLDI_DEPOL BIT(7) +#define OLDI_MSB BIT(8) +#define OLDI_LBEN BIT(9) +#define OLDI_LBDATA BIT(10) +#define OLDI_DUALMODESYNC BIT(11) +#define OLDI_SOFTRST BIT(12) +#define OLDI_TPATCFG BIT(13) +/* LVDS Format values for OLDI_MAP field in DISPC_VP_OLDI_CFG register */ enum oldi_mode_reg_val {SPWG_18 =0 ,JEIDA_24 =1 ,SPWG_24 =2 };
drivers/gpu/drm/tidss/tidss_drv.c +9 -0
@@ -24,6 +24,7 @@#include "tidss_drv.h" #include "tidss_kms.h" #include "tidss_irq.h" +#include "tidss_oldi.h" /* Power management */
@@ -147,6 +148,10 @@ static int tidss_probe(struct platform_device *pdev)return ret; } + ret =tidss_oldi_init (tidss); +if (ret) +return dev_err_probe (dev, ret,"failed to init OLDI\n" ); +pm_runtime_enable (dev);pm_runtime_set_autosuspend_delay (dev,1000 );
@@ -203,6 +208,8 @@ static int tidss_probe(struct platform_device *pdev)pm_runtime_dont_use_autosuspend (dev);pm_runtime_disable (dev); +tidss_oldi_deinit (tidss); +return ret; }
@@ -227,6 +234,8 @@ static void tidss_remove(struct platform_device *pdev)pm_runtime_dont_use_autosuspend (dev);pm_runtime_disable (dev); +tidss_oldi_deinit (tidss); +/* devm allocated dispc goes away with the dev so mark it NULL */ dispc_remove (tidss);
drivers/gpu/drm/tidss/tidss_drv.h +5 -0
@@ -11,8 +11,10 @@#define TIDSS_MAX_PORTS 4#define TIDSS_MAX_PLANES 4 +#define TIDSS_MAX_OLDI_TXES 2typedef u32 dispc_irq_t ; +struct tidss_oldi ;struct tidss_device {struct drm_device ddev;/* DRM device for DSS */
@@ -27,6 +29,9 @@ struct tidss_device {unsigned int num_planes;struct drm_plane *planes[TIDSS_MAX_PLANES ]; +unsigned int num_oldis; +struct tidss_oldi *oldis[TIDSS_MAX_OLDI_TXES ]; +unsigned int irq;/* protects the irq masks field and irqenable/irqstatus registers */
drivers/gpu/drm/tidss/tidss_oldi.c new file +598 -0
598 lines not on this page · raw message
drivers/gpu/drm/tidss/tidss_oldi.h new file +43 -0
43 lines not on this page · raw message
Signature · 1 line
2.34.1
Quoted 12 lines · Aradhya Bhatia
From: Aradhya Bhatia <[email protected]>
The AM62x and AM62Px SoCs feature 2 OLDI TXes each, which makes it possible to connect them in dual-link or cloned single-link OLDI display modes. The current OLDI support in
tidss_dispc.ccan only support for a single OLDI TX, connected to a VP and doesn't really support configuration of OLDIs in the other modes. The current OLDI support intidss_dispc.calso works on the principle that the OLDI output can only be served by one, and only one, DSS video-port. This isn't the case in the AM62Px SoC, where there are 2 DSS controllers present that share the OLDI TXes.
Quoted 8 lines
Having their own devicetree and their own bridge entity will help support the various display modes and sharing possiblilities of the OLDI hardware.
For all these reasons, add support for the OLDI TXes as DRM bridges.
Signed-off-by Aradhya Bhatia <[email protected]>Signed-off-by Aradhya Bhatia <[email protected]>
(with local patches from downstream for DSS support)
Thanks,
-michael
Hello Aradhya, Tomi,
Quoted 12 lines · Aradhya Bhatia
From: Aradhya Bhatia <[email protected]>
The AM62x and AM62Px SoCs feature 2 OLDI TXes each, which makes it possible to connect them in dual-link or cloned single-link OLDI display modes. The current OLDI support in
tidss_dispc.ccan only support for a single OLDI TX, connected to a VP and doesn't really support configuration of OLDIs in the other modes. The current OLDI support intidss_dispc.calso works on the principle that the OLDI output can only be served by one, and only one, DSS video-port. This isn't the case in the AM62Px SoC, where there are 2 DSS controllers present that share the OLDI TXes.
[...]
Quoted 92 lines
drivers/gpu/drm/tidss/tidss_oldi.c new file +92
-0+} + +int tidss_oldi_init (struct tidss_device *tidss) +{ +struct tidss_oldi *oldi; +struct device_node *child; +struct drm_bridge *bridge; +u32 parent_vp, oldi_instance; +int companion_instance =-1 ; +enum tidss_oldi_link_type link_type =OLDI_MODE_UNSUPPORTED ; +struct device_node *oldi_parent; +int ret =0 ; + + tidss->num_oldis =0 ; + + oldi_parent =of_get_child_by_name (tidss->dev->of_node,"oldi-transmitters" ); +if (!oldi_parent) +/* Return gracefully */ +return 0 ; + +for_each_available_child_of_node (oldi_parent, child) { + ret =get_parent_dss_vp (child, &parent_vp); +if (ret) { +if (ret == -ENODEV ) { +/* +* ENODEV means that this particular OLDI node +* is not connected with the DSS, which is not +* a harmful case. There could be another OLDI +* which may still be connected. +* Continue to search for that. +*/ + ret =0 ; +continue ; + } + goto err_put_node; + } + + ret =of_property_read_u32 (child,"reg" , &oldi_instance); +if (ret) + goto err_put_node; + +/* +* Now that it's confirmed that OLDI is connected with DSS, +* let's continue getting the OLDI sinks ahead and other OLDI +* properties. +*/ + bridge =devm_drm_of_get_bridge (tidss->dev, child, +OLDI_OUTPUT_PORT ,0 ); +if (IS_ERR (bridge)) { +/* +* Either there was no OLDI sink in the devicetree, or +* the OLDI sink has not been added yet. In any case, +* return. +* We don't want to have an OLDI node connected to DSS +* but not to any sink. +*/ + ret =dev_err_probe (tidss->dev,PTR_ERR (bridge), +"no panel/bridge for OLDI%u.\n" , + oldi_instance); + goto err_put_node; + } + + link_type =get_oldi_mode (child, &companion_instance); +if (link_type ==OLDI_MODE_UNSUPPORTED ) { + ret =dev_err_probe (tidss->dev, -EINVAL , +"OLDI%u: Unsupported OLDI connection.\n" , + oldi_instance); + goto err_put_node; + }else if ((link_type ==OLDI_MODE_SECONDARY_CLONE_SINGLE_LINK ) || + (link_type ==OLDI_MODE_CLONE_SINGLE_LINK )) { +/* +* The OLDI driver cannot support OLDI clone mode +* properly at present. +* The clone mode requires 2 working encoder-bridge +* pipelines, generating from the same crtc. The DRM +* framework does not support this at present. If +* there were to be, say, 2 OLDI sink bridges each +* connected to an OLDI TXes, they couldn't both be +* supported simultaneously. +* This driver still has some code pertaining to OLDI +* clone mode configuration in DSS hardware for future, +* when there is a better infrastructure in the DRM +* framework to support 2 encoder-bridge pipelines +* simultaneously. +* Till that time, this driver shall error out if it +* detects a clone mode configuration. +*/ + ret =dev_err_probe (tidss->dev, -EOPNOTSUPP , +"The OLDI driver does not support Clone Mode at present.\n" ); + goto err_put_node; + }else if (link_type ==OLDI_MODE_SECONDARY_DUAL_LINK ) { +/*
drivers/gpu/drm/tidss/tidss_oldi.c line 537
Quoted 10 lines
drivers/gpu/drm/tidss/tidss_oldi.c new file +10
-0+* This is the secondary OLDI node, which serves as a +* companion to the primary OLDI, when it is configured +* for the dual-link mode. Since the primary OLDI will +* be a part of bridge chain, no need to put this one +* too. Continue onto the next OLDI node. +*/ +continue ; + } + + oldi =devm_kzalloc (tidss->dev,sizeof (*oldi),GFP_KERNEL );
I think this needs to be changed to devm_drm_bridge_alloc() to get rid of the kernel warning. I am seeing WARNING in OLDI like:
[ 10.198109] WARNING: lib/refcount.c:25 at refcount_warn_saturate+0x120/0x144, CPU#0: kworker/u16:0/12 [ 10.198140] Modules linked in: snd_soc_simple_card mux_gpio snd_soc_simple_card_utils panel_simple cdns3_ti display_connector snd_soc_davinci_mcasp phy_can_transceiver k3_j72xx_bandgap tps6594_i2c tps6 [ 10.198310] CPU: 0 UID: 0 PID: 12 Comm: kworker/u16:0 Not tainted 6.16.0-rc3-next-20250627-00046-ga876218600d6 #197 PREEMPT [ 10.198321] Hardware name: Texas Instruments J722S EVM (DT) [ 10.198327] Workqueue: events_unbound deferred_probe_work_func [ 10.198344] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 10.198352] pc : refcount_warn_saturate+0x120/0x144 [ 10.198359] lr : refcount_warn_saturate+0x120/0x144 [ 10.198365] sp : ffff800082fa3a30 [ 10.198368] x29: ffff800082fa3a30 x28: 0000000000000000 x27: 0000000000000000 [ 10.198377] x26: 0000000000000004 x25: 0000000000000001 x24: ffff80007b1edf48 [ 10.198386] x23: ffff000806fa0000 x22: ffff00080c466800 x21: ffff00094701ec20 [ 10.198395] x20: ffff00080f9cec80 x19: ffff00080f9cec90 x18: fffffffffffe99f8 [ 10.198404] x17: ffff8008c4f5e000 x16: ffff800080000000 x15: 0000000000000002 [ 10.198414] x14: ffff0008001dc680 x13: 0000000000000021 x12: 0000000013cbce01 [ 10.198423] x11: 00000005cc209839 x10: ffff000946f68a40 x9 : ffff0008001dc680 [ 10.198433] x8 : 0000000000000000 x7 : ffff0008001dc680 x6 : 0000000000000002 [ 10.198441] x5 : 0000000000000400 x4 : 0000000000000400 x3 : 0000000013cbce01 [ 10.198450] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff0008001dc600 [ 10.198459] Call trace: [ 10.198464] refcount_warn_saturate+0x120/0x144 (P) [ 10.198473] drm_bridge_add+0xec/0xf0 [drm] [ 10.198733] tidss_oldi_init+0x2e0/0x434 [tidss] [ 10.198759] tidss_probe+0x1a4/0x2e0 [tidss] [ 10.198774] platform_probe+0x68/0xc4 [ 10.198786] really_probe+0xbc/0x29c [ 10.198798] __driver_probe_device+0x78/0x12c [ 10.198808] driver_probe_device+0xd8/0x15c [ 10.198817] __device_attach_driver+0xb8/0x134
oldi = devm_drm_bridge_alloc(tidss->dev, struct tidss_oldi, bridge,
&tidss_oldi_bridge_funcs);
I am posting a fix patch for this since now its merged to linux-next.
Thanks,
Jayesh
[...]
Tomi Valkeinen
maintainerHi,
Quoted 105 lines · Aradhya Bhatia
Hello all,
This patch series adds support for the dual OLDI TXes supported in Texas Instruments' AM62x and AM62Px family of SoCs. The OLDI TX hardware supports single-lvds, lvds-clone, and dual-lvds modes. These TXes have now been represented through DRM bridges within TI-DSS.
* Some history and hardware description for this patch series *
This patch series is a complete re-vamp from the previously posted series[1] and hence, the version index has been reset to v1. The OLDI support from that series was dropped and only the base support for AM62x DSS was kept (and eventually merged)[2].
The OLDI display that the tidss driver today supports, could not be extended for the newer SoCs. The OLDI display in tidss is modelled after the DSS and OLDI hardware in the AM65x SoC. The DSS in AM65x SoC, has two video-ports. Both these video-ports (VP) output DPI video signals. One of the DPI output (from VP1) from the DSS connects to a singular OLDI TX present inside the SoC. There is no other way for the DPI from VP1 to be taken out of the SoC. The other DPI output however - the one from VP2 - is taken out of the SoC as is. Hence we have an OLDI bus output and a DPI bus output from the SoC. Since the VP1 and OLDI are tightly coupled, the tidss driver considers them as a single entity. That is why, any OLDI sink connects directly to the DSS ports in the OF graphs.
The newer SoCs have varying DSS and OLDI integrations.
The AM62x DSS also has 2 VPs. The 2nd VP, VP2, outputs DPI signals which are taken out of the SoC - similar to the AM65x above. For the VP1, there are 2 OLDI TXes. These OLDI TXes can only receive DPI signals from VP1, and don't connect to VP2 at all.
The AM62Px SoC has 2 OLDI TXes like AM62x SoC. However, the AM62Px SoC also has 2 separate DSSes. The 2 OLDI TXes can now be shared between the 2 VPs of the 2 DSSes.
The addition of the 2nd OLDI TX (and a 2nd DSS in AM62Px) creates a need for some major changes for a full feature experience.
1. The OF graph needs to be updated to accurately show the data flow.
2. The tidss and OLDI drivers now need to support the dual-link and the cloned single-link OLDI video signals.
3. The drivers also need to support the case where 2 OLDI TXes are connected to 2 different VPs - thereby creating 2 independent streams of single-link OLDI outputs.Note that the OLDI does not have registers of its own. It is still dependent on the parent VP. The VP that provides the DPI video signals to the OLDI TXes, also gives the OLDI TXes all the config data. That is to say, the hardware doesn't sit on the bus directly - but does so through the DSS.
In light of all of these hardware variations, it was decided to have a separate OLDI driver (unlike AM65x) but not entirely separate so as to be a platform device. The OLDI TXes are now being represented as DRM bridges under the tidss.
* Regarding the Dependency Patches *
Since the OLDI TXes have a hardware dependency with the parent VP(s), the OLDI configuration needs to happen before that VP is enabled for streaming. VP stream enable takes place intidss_crtc_atomic_enablehook. I have posted patches[0] allowing DRM bridges to get pre-enabled before the CRTC of that bridge is enabled. Without those patches, some warnings or glitches may be observed.* Regarding the Drop of Clone Mode support *
Another key point to note is that the support for clone mode has been dropped from the tidss OLDI driver, from v5 onwards. If the DT is configured for a clone mode, the driver will report an error and exit. This has been done because the driver was not supporting a specific case of clone mode where 2 OLDI sink bridges connected to the 2 OLDI TXes require active programming (unlike the simple-panels which do not). The driver does not support creation of two encoder-bridge pipelines (along with the parent tidss driver) to allow program any subsequent bridges (OLDI sinks and bridges thereafter).
The code fragments that write the OLDI config to enable clone mode have been kept as they are, for future, but the driver will not continue to probe if it detects a clone mode configuration, for the time being.
This drop of clone mode support can be undone by applying this _soft-tested_ patch[6] on top of this series. This patch will revert the driver to previous revisions and will allow OLDI sinks that don't require active programming (for
example: simple-panels) to work with the driver. Note that this isn't the ideal way to run clone mode, but it just works for any bridge pipeline after OLDT TX that does not require additional configuration after the OLDI (for example: a couple of simple lvds panels connected directly to the OLDI TXes in clone mode).These patches have been tested on AM625 based Beagleplay[3] platform with a Lincolntech LCD185 dual-lvds panel. The patches with complete support including the expected devicetree configuration of the OLDI TXes can be found in the "next_oldi-v9_1_tests" branch of my github fork[4]. This branch also has support for Microtips dual-lvds panel (SK-LCD1) which is compatible with the SK-AM625 EVM platform.
I'd appreciate it if somebody can test it, and report back if they observe any issues.
Thanks,
Aradhya* Important note about the authorship of patches *
All the patches in the of this series were authored when I owned a "ti.com" based email id, i.e. <[email protected]>. This email id is not in use anymore, and all the work done later has been part of my personal work. Since the original patches were authored using TI's email id, I have maintained the original authorships as they are, as well as their sign offs.
Quoted 3 lines
I have further added another sign off that uses my current (and personal) email id, the one that is being used to send this revision, i.e. <[email protected]>.
Thanks! I will pick these up to drm-misc-next.
Tomi