[PATCH v3 4/4] drm/tidss: Add OLDI bridge support

2024-07-16 Thread Aradhya Bhatia
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.

Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/tidss/Makefile   |   3 +-
 drivers/gpu/drm/tidss/tidss_dispc.c  |  20 +-
 drivers/gpu/drm/tidss/tidss_dispc.h  |   4 +
 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   | 537 +++
 drivers/gpu/drm/tidss/tidss_oldi.h   |  51 +++
 8 files changed, 641 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/drm/tidss/tidss_oldi.c
 create mode 100644 drivers/gpu/drm/tidss/tidss_oldi.h

diff --git a/drivers/gpu/drm/tidss/Makefile b/drivers/gpu/drm/tidss/Makefile
index 312645271014..b6d6becf1683 100644
--- a/drivers/gpu/drm/tidss/Makefile
+++ b/drivers/gpu/drm/tidss/Makefile
@@ -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
diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c 
b/drivers/gpu/drm/tidss/tidss_dispc.c
index 1ad711f8d2a8..8631a89e6155 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc.c
+++ b/drivers/gpu/drm/tidss/tidss_dispc.c
@@ -466,6 +466,25 @@ static u32 dispc_vp_read(struct dispc_device *dispc, u32 
hw_videoport, u16 reg)
return ioread32(base + reg);
 }
 
+void 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);
+
+   if (oldi_cfg != 0) {
+   while (!(oldi_reset_bit & dispc_read(tidss->dispc, 
DSS_SYSSTATUS)) &&
+  count < 1)
+   count++;
+
+   if (!(oldi_reset_bit & dispc_read(tidss->dispc, DSS_SYSSTATUS)))
+   dev_warn(tidss->dispc->dev, "%s: timeout waiting OLDI 
reset done\n",
+__func__);
+   }
+}
+
 /*
  * TRM gives bitfields as start:end, where start is the higher bit
  * number. For example 7:0
@@ -1310,7 +1329,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;
diff --git a/drivers/gpu/drm/tidss/tidss_dispc.h 
b/drivers/gpu/drm/tidss/tidss_dispc.h
index 086327d51a90..fab248f2055a 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc.h
+++ b/drivers/gpu/drm/tidss/tidss_dispc.h
@@ -94,6 +94,10 @@ extern const struct dispc_features dispc_am62a7_feats;
 extern const struct dispc_features dispc_am65x_feats;
 extern const struct dispc_features dispc_j721e_feats;
 
+void tidss_configure_oldi(struct tidss_device *tidss, u32 hw_videoport,
+ u32 oldi_cfg);
+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);
 
diff --git a/drivers/gpu/drm/tidss/tidss_dispc_regs.h 
b/drivers/gpu/drm/tidss/tidss_dispc_regs.h
index 13feedfe5d6d..03f7098029e6 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc_regs.h
+++ b/drivers/gpu/drm/tidss/tidss_dispc_regs.h
@@ -226,6 +226,20 @@ enum dispc_common_regs {
 #define DISPC_VP_DSS_DMA_THREADSIZE0x170 /* J721E */
 #define DISPC_VP_DSS_DMA_THREADSIZE_STATUS 0x174 /* J721E */
 
+/* OLDI Config Bits (DISPC_VP_DSS_OLDI_CFG) */
+#define OLDI_ENABLEBIT(0)
+#define OLDI_MAP   (BIT(1) | BIT(2) | BIT(3))
+#define OLDI_SRC   BIT(4)
+#define OLDI_CLONE_MODEBIT(5)
+#define OLDI_MASTERSLAVE   BIT(6)
+#define OLDI_DEPOL BIT(7)
+#define OLDI_MSB   BIT(8)
+#define OLDI_LBEN  BIT(9)
+#define OLDI_LBDATA   

[PATCH v3 2/4] dt-bindings: display: ti: Add schema for AM625 OLDI Transmitter

2024-07-16 Thread Aradhya Bhatia
The OLDI (transmitters) TXes do not have registers of their own, and are
dependent on the source video-ports 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 OLDI functionality is further supported by a system-control module,
which contains a few registers to control OLDI IO power and
characteristics.

Add devicetree binding schema for AM625 OLDI TXes.

Signed-off-by: Aradhya Bhatia 
---
 .../bindings/display/ti/ti,am625-oldi.yaml| 153 ++
 MAINTAINERS   |   1 +
 2 files changed, 154 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml

diff --git a/Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml 
b/Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml
new file mode 100644
index ..0a96e600bc0b
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml
@@ -0,0 +1,153 @@
+# 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 
+  - Aradhya Bhatia 
+
+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: s_clk
+
+  ti,companion-oldi:
+$ref: /schemas/types.yaml#/definitions/phandle
+description:
+  phandle to companion OLDI transmitter. This property is mandatory for the
+  primarty OLDI TX if the OLDI TXes are expected to work either in 
dual-lvds
+  mode or in clone mode. This property should point to the secondary OLDI
+  TX.
+
+  ti,secondary-oldi:
+type: boolean
+description: Boolean property to mark an OLDI TX as secondary node.
+
+  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. This property is needed for OLDI interface to work.
+
+  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
+
+allOf:
+  - if:
+  properties:
+ti,secondary-oldi: true
+then:
+  properties:
+ti,companion-oldi: false
+ti,oldi-io-ctrl: false
+clocks: false
+clock-names: false
+
+else:
+  required:
+- ti,oldi-io-ctrl
+- clocks
+- clock-names
+
+required:
+  - reg
+  - ports
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+
+oldi_txes {
+#address-cells = <1>;
+#size-cells = <0>;
+oldi: oldi@0 {
+reg = <0>;
+clocks = <_clks 186 0>;
+clock-names = "s_clk";
+ti,oldi-io-ctrl = <_oldi_io_ctrl>;
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+reg = <0>;
+oldi_in: endpoint {
+remote-endpoint = <_out>;
+};
+};
+};
+};
+};
+
+  - |
+#include 
+
+oldi_txes {
+#address-cells = <1>;
+#size-cells = <0>;
+oldi0: oldi@0 {
+reg = <0>;
+clocks = <_clks 186 0>;
+clock-names = "s_clk";
+ti,companion-oldi = <>;
+ti,oldi-io-ctrl = <_oldi_io_ctrl>;
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+reg = <0>;
+oldi0_in: endpoint {
+   

[PATCH v3 3/4] dt-bindings: display: ti, am65x-dss: Add OLDI properties for AM625 DSS

2024-07-16 Thread Aradhya Bhatia
The DSS in AM625 SoC has 2 OLDI TXes. Refer the OLDI schema to add the
support for the OLDI TXes.

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. Add support for an
additional endpoint under the port@0 to accurately depict the data flow
path.

Signed-off-by: Aradhya Bhatia 
---
 .../bindings/display/ti/ti,am65x-dss.yaml | 135 ++
 1 file changed, 135 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml 
b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
index 399d68986326..249597455d34 100644
--- a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
+++ b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
@@ -91,6 +91,24 @@ 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.
+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
 
   port@1:
 $ref: /schemas/graph.yaml#/properties/port
@@ -112,6 +130,23 @@ properties:
   Input memory (from main memory to dispc) bandwidth limit in
   bytes per second
 
+  oldi-txes:
+type: object
+additionalProperties: true
+properties:
+  "#address-cells":
+const: 1
+
+  "#size-cells":
+const: 0
+
+patternProperties:
+  '^oldi_tx@[0-1]$':
+type: object
+$ref: ti,am625-oldi.yaml#
+unevaluatedProperties: false
+description: OLDI transmitters connected to the DSS VPs
+
 allOf:
   - if:
   properties:
@@ -123,6 +158,19 @@ allOf:
 ports:
   properties:
 port@0: false
+oldi_txes: false
+
+  - if:
+  properties:
+compatible:
+  contains:
+const: ti,am65x-dss
+then:
+  properties:
+oldi_txes: false
+port@0:
+  properties:
+endpoint@1: false
 
 required:
   - compatible
@@ -171,3 +219,90 @@ examples:
 };
 };
 };
+
+  - |
+#include 
+#include 
+#include 
+
+bus {
+#address-cells = <2>;
+#size-cells = <2>;
+dss1: dss@3020 {
+compatible = "ti,am625-dss";
+reg = <0x00 0x3020 0x00 0x1000>, /* common */
+  <0x00 0x30202000 0x00 0x1000>, /* vidl1 */
+  <0x00 0x30206000 0x00 0x1000>, /* vid */
+  <0x00 0x30207000 0x00 0x1000>, /* ovr1 */
+  <0x00 0x30208000 0x00 0x1000>, /* ovr2 */
+  <0x00 0x3020a000 0x00 0x1000>, /* vp1 */
+  <0x00 0x3020b000 0x00 0x1000>, /* vp2 */
+  <0x00 0x30201000 0x00 0x1000>; /* common1 */
+reg-names = "common", "vidl1", "vid",
+"ovr1", "ovr2", "vp1", "vp2", "common1";
+power-domains = <_pds 186 TI_SCI_PD_EXCLUSIVE>;
+clocks =<_clks 186 6>,
+<_clock>,
+<_clks 186 2>;
+clock-names = "fck", "vp1", "vp2";
+interrupts = ;
+oldi-txes {
+#address-cells = <1>;
+#size-cells = <0>;
+oldi0: oldi@0 {
+reg = <0>;
+clocks = <_clks 186 0>;
+clock-names = "s_clk";
+ti,companion-oldi = <>;
+ti,oldi-io-ctrl = <_oldi_io_ctrl>;
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+reg = <0>;
+oldi0_in: endpoint {
+remote-endpoint = <_out0>;
+};
+};
+};
+};
+oldi1: oldi@1 {
+reg = <1>;
+ti,secondary-oldi;
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+ 

[PATCH v3 0/4] drm/tidss: Add OLDI bridge support

2024-07-16 Thread Aradhya Bhatia
and drop all
  the drm_panel support from tidss_oldi.

Previous revisions:
V2: https://lore.kernel.org/all/20240715200953.1213284-1-a-bhat...@ti.com/
V1: https://lore.kernel.org/all/20240511193055.1686149-1-a-bhat...@ti.com/

[0]: Dependency Patch: 
("drm/atomic-helper: Re-order bridge chain pre-enable and post-disable")
https://lore.kernel.org/all/20240622110929.3115714-11-a-bhat...@ti.com/

[1]: AM62 OLDI Series - v7
https://lore.kernel.org/all/20230125113529.13952-1-a-bhat...@ti.com/

[2]: AM62 DSS Series - v9
https://lore.kernel.org/all/20230616150900.6617-1-a-bhat...@ti.com/

[3]: GitHub Fork for OLDI tests
https://github.com/aradhya07/linux-ab/tree/next_oldi-v3-tests/

[4]: ("ti,am65x-dss.yaml: oldi-txes: Missing additionalProperties/
  unevaluatedProperties constraint")
https://lore.kernel.org/all/172107979988.1595945.9666141982402158422.r...@kernel.org/

Aradhya Bhatia (4):
  dt-bindings: display: ti,am65x-dss: Re-indent the example
  dt-bindings: display: ti: Add schema for AM625 OLDI Transmitter
  dt-bindings: display: ti,am65x-dss: Add OLDI properties for AM625 DSS
  drm/tidss: Add OLDI bridge support

 .../bindings/display/ti/ti,am625-oldi.yaml| 153 +
 .../bindings/display/ti/ti,am65x-dss.yaml | 177 +-
 MAINTAINERS   |   1 +
 drivers/gpu/drm/tidss/Makefile|   3 +-
 drivers/gpu/drm/tidss/tidss_dispc.c   |  20 +-
 drivers/gpu/drm/tidss/tidss_dispc.h   |   4 +
 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| 537 ++
 drivers/gpu/drm/tidss/tidss_oldi.h|  51 ++
 11 files changed, 951 insertions(+), 23 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: 3fe121b622825ff8cc995a1e6b026181c48188db
-- 
2.34.1



[PATCH v3 1/4] dt-bindings: display: ti, am65x-dss: Re-indent the example

2024-07-16 Thread Aradhya Bhatia
Reduce tab size from 8 spaces to 4 spaces to make the bindings
consistent, and easy to expand.

Acked-by: Rob Herring (Arm) 
Reviewed-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Signed-off-by: Aradhya Bhatia 
---
 .../bindings/display/ti/ti,am65x-dss.yaml | 54 +--
 1 file changed, 27 insertions(+), 27 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml 
b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
index 55e3e490d0e6..399d68986326 100644
--- a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
+++ b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
@@ -142,32 +142,32 @@ examples:
 #include 
 
 dss: dss@4a0 {
-compatible = "ti,am65x-dss";
-reg =   <0x04a0 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 = <_oldi_io_ctrl>;
-power-domains = <_pds 67 TI_SCI_PD_EXCLUSIVE>;
-clocks =<_clks 67 1>,
-<_clks 216 1>,
-<_clks 67 2>;
-clock-names = "fck", "vp1", "vp2";
-interrupts = ;
-ports {
-#address-cells = <1>;
-#size-cells = <0>;
-port@0 {
-reg = <0>;
-oldi_out0: endpoint {
-remote-endpoint = <_in0>;
-};
-};
+compatible = "ti,am65x-dss";
+reg = <0x04a0 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 = <_oldi_io_ctrl>;
+power-domains = <_pds 67 TI_SCI_PD_EXCLUSIVE>;
+clocks =<_clks 67 1>,
+<_clks 216 1>,
+<_clks 67 2>;
+clock-names = "fck", "vp1", "vp2";
+interrupts = ;
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+reg = <0>;
+oldi_out0: endpoint {
+remote-endpoint = <_in0>;
+};
 };
+};
 };
-- 
2.34.1



[PATCH v2 2/4] dt-bindings: display: ti: Add schema for AM625 OLDI Transmitter

2024-07-15 Thread Aradhya Bhatia
The OLDI (transmitters) TXes do not have registers of their own, and are
dependent on the source video-ports 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 OLDI functionality is further supported by a system-control module,
which contains a few registers to control OLDI IO power and
characteristics.

Add devicetree binding schema for AM625 OLDI TXes.

Signed-off-by: Aradhya Bhatia 
---
 .../bindings/display/ti/ti,am625-oldi.yaml| 153 ++
 MAINTAINERS   |   1 +
 2 files changed, 154 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml

diff --git a/Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml 
b/Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml
new file mode 100644
index ..0a96e600bc0b
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml
@@ -0,0 +1,153 @@
+# 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 
+  - Aradhya Bhatia 
+
+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: s_clk
+
+  ti,companion-oldi:
+$ref: /schemas/types.yaml#/definitions/phandle
+description:
+  phandle to companion OLDI transmitter. This property is mandatory for the
+  primarty OLDI TX if the OLDI TXes are expected to work either in 
dual-lvds
+  mode or in clone mode. This property should point to the secondary OLDI
+  TX.
+
+  ti,secondary-oldi:
+type: boolean
+description: Boolean property to mark an OLDI TX as secondary node.
+
+  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. This property is needed for OLDI interface to work.
+
+  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
+
+allOf:
+  - if:
+  properties:
+ti,secondary-oldi: true
+then:
+  properties:
+ti,companion-oldi: false
+ti,oldi-io-ctrl: false
+clocks: false
+clock-names: false
+
+else:
+  required:
+- ti,oldi-io-ctrl
+- clocks
+- clock-names
+
+required:
+  - reg
+  - ports
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+
+oldi_txes {
+#address-cells = <1>;
+#size-cells = <0>;
+oldi: oldi@0 {
+reg = <0>;
+clocks = <_clks 186 0>;
+clock-names = "s_clk";
+ti,oldi-io-ctrl = <_oldi_io_ctrl>;
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+reg = <0>;
+oldi_in: endpoint {
+remote-endpoint = <_out>;
+};
+};
+};
+};
+};
+
+  - |
+#include 
+
+oldi_txes {
+#address-cells = <1>;
+#size-cells = <0>;
+oldi0: oldi@0 {
+reg = <0>;
+clocks = <_clks 186 0>;
+clock-names = "s_clk";
+ti,companion-oldi = <>;
+ti,oldi-io-ctrl = <_oldi_io_ctrl>;
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+reg = <0>;
+oldi0_in: endpoint {
+   

[PATCH v2 4/4] drm/tidss: Add OLDI bridge support

2024-07-15 Thread Aradhya Bhatia
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.

Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/tidss/Makefile   |   3 +-
 drivers/gpu/drm/tidss/tidss_dispc.c  |  20 +-
 drivers/gpu/drm/tidss/tidss_dispc.h  |   4 +
 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   | 537 +++
 drivers/gpu/drm/tidss/tidss_oldi.h   |  51 +++
 8 files changed, 641 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/drm/tidss/tidss_oldi.c
 create mode 100644 drivers/gpu/drm/tidss/tidss_oldi.h

diff --git a/drivers/gpu/drm/tidss/Makefile b/drivers/gpu/drm/tidss/Makefile
index 312645271014..b6d6becf1683 100644
--- a/drivers/gpu/drm/tidss/Makefile
+++ b/drivers/gpu/drm/tidss/Makefile
@@ -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
diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c 
b/drivers/gpu/drm/tidss/tidss_dispc.c
index 1ad711f8d2a8..8631a89e6155 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc.c
+++ b/drivers/gpu/drm/tidss/tidss_dispc.c
@@ -466,6 +466,25 @@ static u32 dispc_vp_read(struct dispc_device *dispc, u32 
hw_videoport, u16 reg)
return ioread32(base + reg);
 }
 
+void 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);
+
+   if (oldi_cfg != 0) {
+   while (!(oldi_reset_bit & dispc_read(tidss->dispc, 
DSS_SYSSTATUS)) &&
+  count < 1)
+   count++;
+
+   if (!(oldi_reset_bit & dispc_read(tidss->dispc, DSS_SYSSTATUS)))
+   dev_warn(tidss->dispc->dev, "%s: timeout waiting OLDI 
reset done\n",
+__func__);
+   }
+}
+
 /*
  * TRM gives bitfields as start:end, where start is the higher bit
  * number. For example 7:0
@@ -1310,7 +1329,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;
diff --git a/drivers/gpu/drm/tidss/tidss_dispc.h 
b/drivers/gpu/drm/tidss/tidss_dispc.h
index 086327d51a90..fab248f2055a 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc.h
+++ b/drivers/gpu/drm/tidss/tidss_dispc.h
@@ -94,6 +94,10 @@ extern const struct dispc_features dispc_am62a7_feats;
 extern const struct dispc_features dispc_am65x_feats;
 extern const struct dispc_features dispc_j721e_feats;
 
+void tidss_configure_oldi(struct tidss_device *tidss, u32 hw_videoport,
+ u32 oldi_cfg);
+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);
 
diff --git a/drivers/gpu/drm/tidss/tidss_dispc_regs.h 
b/drivers/gpu/drm/tidss/tidss_dispc_regs.h
index 13feedfe5d6d..03f7098029e6 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc_regs.h
+++ b/drivers/gpu/drm/tidss/tidss_dispc_regs.h
@@ -226,6 +226,20 @@ enum dispc_common_regs {
 #define DISPC_VP_DSS_DMA_THREADSIZE0x170 /* J721E */
 #define DISPC_VP_DSS_DMA_THREADSIZE_STATUS 0x174 /* J721E */
 
+/* OLDI Config Bits (DISPC_VP_DSS_OLDI_CFG) */
+#define OLDI_ENABLEBIT(0)
+#define OLDI_MAP   (BIT(1) | BIT(2) | BIT(3))
+#define OLDI_SRC   BIT(4)
+#define OLDI_CLONE_MODEBIT(5)
+#define OLDI_MASTERSLAVE   BIT(6)
+#define OLDI_DEPOL BIT(7)
+#define OLDI_MSB   BIT(8)
+#define OLDI_LBEN  BIT(9)
+#define OLDI_LBDATA   

[PATCH v2 1/4] dt-bindings: display: ti, am65x-dss: Re-indent the example

2024-07-15 Thread Aradhya Bhatia
Reduce tab size from 8 spaces to 4 spaces to make the bindings
consistent, and easy to expand.

Acked-by: Rob Herring (Arm) 
Reviewed-by: Laurent Pinchart 
Reviewed-by: Tomi Valkeinen 
Signed-off-by: Aradhya Bhatia 
---
 .../bindings/display/ti/ti,am65x-dss.yaml | 54 +--
 1 file changed, 27 insertions(+), 27 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml 
b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
index 55e3e490d0e6..399d68986326 100644
--- a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
+++ b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
@@ -142,32 +142,32 @@ examples:
 #include 
 
 dss: dss@4a0 {
-compatible = "ti,am65x-dss";
-reg =   <0x04a0 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 = <_oldi_io_ctrl>;
-power-domains = <_pds 67 TI_SCI_PD_EXCLUSIVE>;
-clocks =<_clks 67 1>,
-<_clks 216 1>,
-<_clks 67 2>;
-clock-names = "fck", "vp1", "vp2";
-interrupts = ;
-ports {
-#address-cells = <1>;
-#size-cells = <0>;
-port@0 {
-reg = <0>;
-oldi_out0: endpoint {
-remote-endpoint = <_in0>;
-};
-};
+compatible = "ti,am65x-dss";
+reg = <0x04a0 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 = <_oldi_io_ctrl>;
+power-domains = <_pds 67 TI_SCI_PD_EXCLUSIVE>;
+clocks =<_clks 67 1>,
+<_clks 216 1>,
+<_clks 67 2>;
+clock-names = "fck", "vp1", "vp2";
+interrupts = ;
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+reg = <0>;
+oldi_out0: endpoint {
+remote-endpoint = <_in0>;
+};
 };
+};
 };
-- 
2.34.1



[PATCH v2 3/4] dt-bindings: display: ti, am65x-dss: Add OLDI properties for AM625 DSS

2024-07-15 Thread Aradhya Bhatia
The DSS in AM625 SoC has 2 OLDI TXes. Refer the OLDI schema to add the
support for the OLDI TXes.

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. Add support for an
additional endpoint under the port@0 to accurately depict the data flow
path.

Signed-off-by: Aradhya Bhatia 
---
 .../bindings/display/ti/ti,am65x-dss.yaml | 134 ++
 1 file changed, 134 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml 
b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
index 399d68986326..7fce2218c99e 100644
--- a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
+++ b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
@@ -91,6 +91,24 @@ 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.
+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
 
   port@1:
 $ref: /schemas/graph.yaml#/properties/port
@@ -112,6 +130,22 @@ properties:
   Input memory (from main memory to dispc) bandwidth limit in
   bytes per second
 
+  oldi-txes:
+type: object
+properties:
+  "#address-cells":
+const: 1
+
+  "#size-cells":
+const: 0
+
+patternProperties:
+  '^oldi_tx@[0-1]$':
+type: object
+$ref: ti,am625-oldi.yaml#
+unevaluatedProperties: false
+description: OLDI transmitters connected to the DSS VPs
+
 allOf:
   - if:
   properties:
@@ -123,6 +157,19 @@ allOf:
 ports:
   properties:
 port@0: false
+oldi_txes: false
+
+  - if:
+  properties:
+compatible:
+  contains:
+const: ti,am65x-dss
+then:
+  properties:
+oldi_txes: false
+port@0:
+  properties:
+endpoint@1: false
 
 required:
   - compatible
@@ -171,3 +218,90 @@ examples:
 };
 };
 };
+
+  - |
+#include 
+#include 
+#include 
+
+bus {
+#address-cells = <2>;
+#size-cells = <2>;
+dss1: dss@3020 {
+compatible = "ti,am625-dss";
+reg = <0x00 0x3020 0x00 0x1000>, /* common */
+  <0x00 0x30202000 0x00 0x1000>, /* vidl1 */
+  <0x00 0x30206000 0x00 0x1000>, /* vid */
+  <0x00 0x30207000 0x00 0x1000>, /* ovr1 */
+  <0x00 0x30208000 0x00 0x1000>, /* ovr2 */
+  <0x00 0x3020a000 0x00 0x1000>, /* vp1 */
+  <0x00 0x3020b000 0x00 0x1000>, /* vp2 */
+  <0x00 0x30201000 0x00 0x1000>; /* common1 */
+reg-names = "common", "vidl1", "vid",
+"ovr1", "ovr2", "vp1", "vp2", "common1";
+power-domains = <_pds 186 TI_SCI_PD_EXCLUSIVE>;
+clocks =<_clks 186 6>,
+<_clock>,
+<_clks 186 2>;
+clock-names = "fck", "vp1", "vp2";
+interrupts = ;
+oldi-txes {
+#address-cells = <1>;
+#size-cells = <0>;
+oldi0: oldi@0 {
+reg = <0>;
+clocks = <_clks 186 0>;
+clock-names = "s_clk";
+ti,companion-oldi = <>;
+ti,oldi-io-ctrl = <_oldi_io_ctrl>;
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+reg = <0>;
+oldi0_in: endpoint {
+remote-endpoint = <_out0>;
+};
+};
+};
+};
+oldi1: oldi@1 {
+reg = <1>;
+ti,secondary-oldi;
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+reg = <0

[PATCH v2 0/4] drm/tidss: Add OLDI bridge support

2024-07-15 Thread Aradhya Bhatia
e chain pre-enable and post-disable")
https://lore.kernel.org/all/20240622110929.3115714-11-a-bhat...@ti.com/

[1]: AM62 OLDI Series - v7
https://lore.kernel.org/all/20230125113529.13952-1-a-bhat...@ti.com/

[2]: AM62 DSS Series - v9
https://lore.kernel.org/all/20230616150900.6617-1-a-bhat...@ti.com/

[3]: GitHub Fork for OLDI tests
https://github.com/aradhya07/linux-ab/tree/next_oldi-v2-tests/

Aradhya Bhatia (4):
  dt-bindings: display: ti,am65x-dss: Re-indent the example
  dt-bindings: display: ti: Add schema for AM625 OLDI Transmitter
  dt-bindings: display: ti,am65x-dss: Add OLDI properties for AM625 DSS
  drm/tidss: Add OLDI bridge support

 .../bindings/display/ti/ti,am625-oldi.yaml| 153 +
 .../bindings/display/ti/ti,am65x-dss.yaml | 176 +-
 MAINTAINERS   |   1 +
 drivers/gpu/drm/tidss/Makefile|   3 +-
 drivers/gpu/drm/tidss/tidss_dispc.c   |  20 +-
 drivers/gpu/drm/tidss/tidss_dispc.h   |   4 +
 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| 537 ++
 drivers/gpu/drm/tidss/tidss_oldi.h|  51 ++
 11 files changed, 950 insertions(+), 23 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: 3fe121b622825ff8cc995a1e6b026181c48188db
-- 
2.34.1



Re: [PATCH 4/4] drm/tidss: Add OLDI bridge support

2024-07-15 Thread Aradhya Bhatia
Hi Tomi,

Thank you for reviewing the patches!

On 27/06/24 18:41, Tomi Valkeinen wrote:
> On 11/05/2024 22:30, Aradhya Bhatia wrote:
>> Up till now, the OLDI support in tidss was integrated within the tidss
>> dispc.
>> This was fine till the OLDI was one-to-mapped with the DSS video-port
>> (VP).
>> The AM62 and AM62P SoCs have 2 OLDI TXes that can support dual-lvds /
>> lvds-clone
>> modes.
>>
>> Add OLDI TXes as separate DRM bridge entities to better support the
>> new LVDS
>> configurations.
>>
>> Signed-off-by: Aradhya Bhatia 
>> ---
>> Note:
>>
>> The OLDI configuration should happen before the video-port
>> configuration takes
>> place in tidss_crtc_atomic_enable hook. I have posted a patch allowing
>> DRM
>> bridges to get enabled before the CRTC of that bridge is enabled[0].
>> This patch
>> uses the bridge hooks introduced in [0], and hence will not compile
>> without [0].
>>
>> [0]: Dependency Patch: Introduce early_enable / late_disable drm
>> bridge APIs
>> https://lore.kernel.org/all/20240511153051.1355825-7-a-bhat...@ti.com/
>>
>> ---
>>   drivers/gpu/drm/tidss/Makefile  |   3 +-
>>   drivers/gpu/drm/tidss/tidss_dispc.c |  11 +-
>>   drivers/gpu/drm/tidss/tidss_dispc.h |   4 +
>>   drivers/gpu/drm/tidss/tidss_drv.c   |  13 +-
>>   drivers/gpu/drm/tidss/tidss_drv.h   |   4 +
>>   drivers/gpu/drm/tidss/tidss_oldi.c  | 568 
>>   drivers/gpu/drm/tidss/tidss_oldi.h  |  73 
>>   7 files changed, 673 insertions(+), 3 deletions(-)
>>   create mode 100644 drivers/gpu/drm/tidss/tidss_oldi.c
>>   create mode 100644 drivers/gpu/drm/tidss/tidss_oldi.h
>>
>> diff --git a/drivers/gpu/drm/tidss/Makefile
>> b/drivers/gpu/drm/tidss/Makefile
>> index 312645271014..b6d6becf1683 100644
>> --- a/drivers/gpu/drm/tidss/Makefile
>> +++ b/drivers/gpu/drm/tidss/Makefile
>> @@ -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
>> diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c
>> b/drivers/gpu/drm/tidss/tidss_dispc.c
>> index 1ad711f8d2a8..4961da3989c0 100644
>> --- a/drivers/gpu/drm/tidss/tidss_dispc.c
>> +++ b/drivers/gpu/drm/tidss/tidss_dispc.c
>> @@ -466,6 +466,16 @@ static u32 dispc_vp_read(struct dispc_device
>> *dispc, u32 hw_videoport, u16 reg)
>>   return ioread32(base + reg);
>>   }
>>   +u32 tidss_get_status(struct tidss_device *tidss)
>> +{
>> +    return dispc_read(tidss->dispc, DSS_SYSSTATUS);
>> +}
>> +
>> +void tidss_configure_oldi(struct tidss_device *tidss, u32
>> hw_videoport, u32 val)
>> +{
>> +    return dispc_vp_write(tidss->dispc, hw_videoport,
>> DISPC_VP_DSS_OLDI_CFG, val);
>> +}
>> +
>>   /*
>>    * TRM gives bitfields as start:end, where start is the higher bit
>>    * number. For example 7:0
>> @@ -1310,7 +1320,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;
>> diff --git a/drivers/gpu/drm/tidss/tidss_dispc.h
>> b/drivers/gpu/drm/tidss/tidss_dispc.h
>> index 086327d51a90..800a73457aff 100644
>> --- a/drivers/gpu/drm/tidss/tidss_dispc.h
>> +++ b/drivers/gpu/drm/tidss/tidss_dispc.h
>> @@ -94,6 +94,10 @@ extern const struct dispc_features dispc_am62a7_feats;
>>   extern const struct dispc_features dispc_am65x_feats;
>>   extern const struct dispc_features dispc_j721e_feats;
>>   +u32 tidss_get_status(struct tidss_device *tidss);
>> +void tidss_configure_oldi(struct tidss_device *tidss, u32
>> hw_videoport, u32 val);
>> +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);
>>   diff --git a/drivers/gpu/drm/tidss/tidss_drv.c
>> b/drivers/gpu/drm/tidss/tidss_drv.c
>> index d15f836dca95..fd90e8498cc2 100644
>> --- a/drivers/gpu/drm/tidss/tidss_drv.c
>> +++ b/drivers/gpu/drm/tidss/t

Re: [PATCH v4 10/11] drm/atomic-helper: Re-order bridge chain pre-enable and post-disable

2024-07-11 Thread Aradhya Bhatia



On 26/06/24 18:37, Maxime Ripard wrote:
> On Wed, Jun 26, 2024 at 02:28:57PM GMT, Tomi Valkeinen wrote:
>> On 22/06/2024 14:09, Aradhya Bhatia wrote:
>>> Move the bridge pre_enable call before crtc enable, and the bridge
>>> post_disable call after the crtc disable.
>>>
>>> The sequence of enable after this patch will look like:
>>>
>>> bridge[n]_pre_enable
>>> ...
>>> bridge[1]_pre_enable
>>>
>>> crtc_enable
>>> encoder_enable
>>>
>>> bridge[1]_enable
>>> ...
>>> bridge[n]__enable
>>>
>>> and vice-versa for the bridge chain disable sequence.
>>>
>>> The definition of bridge pre_enable hook says that,
>>> "The display pipe (i.e. clocks and timing signals) feeding this bridge
>>> will not yet be running when this callback is called".
>>>
>>> Since CRTC is also a source feeding the bridge, it should not be enabled
>>> before the bridges in the pipeline are pre_enabled. Fix that by
>>> re-ordering the sequence of bridge pre_enable and bridge post_disable.
>>>
>>> Signed-off-by: Aradhya Bhatia 
>>> ---
>>>   drivers/gpu/drm/drm_atomic_helper.c | 165 ++--
>>>   include/drm/drm_atomic_helper.h |   7 ++
>>>   2 files changed, 114 insertions(+), 58 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
>>> b/drivers/gpu/drm/drm_atomic_helper.c
>>> index fb97b51b38f1..e8ad08634f58 100644
>>> --- a/drivers/gpu/drm/drm_atomic_helper.c
>>> +++ b/drivers/gpu/drm/drm_atomic_helper.c
>>> @@ -74,6 +74,7 @@
>>>* also shares the  drm_plane_helper_funcs function table with the 
>>> plane
>>>* helpers.
>>>*/
>>> +
>>
>> Extra change.
>>
>>>   static void
>>>   drm_atomic_helper_plane_changed(struct drm_atomic_state *state,
>>> struct drm_plane_state *old_plane_state,
>>> @@ -1122,11 +1123,11 @@ crtc_needs_disable(struct drm_crtc_state *old_state,
>>>   }
>>>   static void
>>> -disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
>>> +disable_encoder_brige_chain(struct drm_device *dev, struct 
>>> drm_atomic_state *old_state,
>>> +   enum bridge_chain_operation_type op_type)
>>>   {
>>> struct drm_connector *connector;
>>> struct drm_connector_state *old_conn_state, *new_conn_state;
>>> -   struct drm_crtc *crtc;
>>> struct drm_crtc_state *old_crtc_state, *new_crtc_state;
>>> int i;
>>> @@ -1163,32 +1164,55 @@ disable_outputs(struct drm_device *dev, struct 
>>> drm_atomic_state *old_state)
>>> if (WARN_ON(!encoder))
>>> continue;
>>> -   funcs = encoder->helper_private;
>>> -
>>> -   drm_dbg_atomic(dev, "disabling [ENCODER:%d:%s]\n",
>>> -  encoder->base.id, encoder->name);
>>> -
>>> /*
>>>  * Each encoder has at most one connector (since we always steal
>>>  * it away), so we won't call disable hooks twice.
>>>  */
>>> bridge = drm_bridge_chain_get_first_bridge(encoder);
>>> -   drm_atomic_bridge_chain_disable(bridge, old_state);
>>> -   /* Right function depends upon target state. */
>>> -   if (funcs) {
>>> -   if (funcs->atomic_disable)
>>> -   funcs->atomic_disable(encoder, old_state);
>>> -   else if (new_conn_state->crtc && funcs->prepare)
>>> -   funcs->prepare(encoder);
>>> -   else if (funcs->disable)
>>> -   funcs->disable(encoder);
>>> -   else if (funcs->dpms)
>>> -   funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
>>> -   }
>>> +   switch (op_type) {
>>> +   case DRM_ENCODER_BRIDGE_DISABLE:
>>> +   funcs = encoder->helper_private;
>>> +
>>> +   drm_dbg_atomic(dev, "disabling [ENCODER:%d:%s]\n",
>>> +  encoder->base.id, encoder->name);
>>> +
>>> +   drm_atomic_bridge_chain_disable(brid

Re: [PATCH v4 07/11] drm/bridge: cdns-dsi: Reset the DCS write FIFO

2024-07-11 Thread Aradhya Bhatia



On 26/06/24 16:33, Tomi Valkeinen wrote:
> On 22/06/2024 14:09, Aradhya Bhatia wrote:
>> If any normal DCS write command has already been transmitted prior to
>> transmitting any Zero-Parameter DCS command, then it is necessary to
>> clear the TX FIFO by resetting it. Otherwise, the FIFO points to another
>> location, and the DCS command transmits unnecessary data causing the
>> panel to not work[0].
>>
>> Allow the DCS Write FIFO in the cdns-dsi controller to reset as a rule,
>> before any DCS packet is transmitted to the DSI peripheral.
>>
>> [0]: Section 12.6.5.7.5.2: "Command Mode Settings" in TDA4VM Technical
>>   Reference Manual: https://www.ti.com/lit/zip/spruil1
> 
> Hmm so if I read the doc right, it says: if sending zero-parameter dcs
> command, clear the FIFO and write zero to direct_cmd_wrdat.

That's right.

> 
> Your patch seems to always clear the FIFO, not only for zero-parameter
> commands. Is that a problem (I don't think so, but...)?
> 

My patch does clear the FIFO every time.

While there is no documentation that says its harmless, I have tested
the patches with RPi Panel (which doesn't seem to have any
zero-parameter commands in the driver) - and so far it seems to have
worked fine.


> Also, is the direct_cmd_wrdat written at all when sending zero-parameter
> dcs command?
> 

At the moment, no.

Apparently there are 2 types of "Zero parameter" commands.

There is,

a) "MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM" - which has absolutely no
parameter that needs to be sent, and there is,

b) "MIPI_DSI_DCS_SHORT_WRITE" - which has a 1-byte command value that
needs to be transmitted.

(Macros referred from mipi_display.h)

In the J721E TRM[0], there is a table[1]  which classifies the
"MIPI_DSI_DCS_SHORT_WRITE" - the command with 1-byte command parameter -
as a "zero parameter" command.

For a "MIPI_DSI_DCS_SHORT_WRITE" command, we are still writing the
1-byte command data into the FIFO.

However, in the other section which talks about resetting the FIFO[2],
it is mentioned that, for "zero parameter" commands, the FIFO needs to
be reset and then 0x00 needs to be written to the FIFO.

The second step cannot be done for "MIPI_DSI_DCS_SHORT_WRITE" commands
because we want to write the 1 byte command parameter instead of 0x00
into the FIFO.

So, the only logical conclusion is that, the FIFO reset is only required
for _truly_ zero parameter commands, which is the
"MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM" command.

So, I am planning to change this patch to do 2 things, under the
condition that there are absolutely no data bytes that require
transmission.

a. Reset the FIFO.
b. Write 0x00 to the FIFO.


Regards
Aradhya

[0]: J721E TRM: https://www.ti.com/lit/zip/spruil1
[1]: Table: 12-1933: "DSI Main Settings Register Description".
[2]: Section 12.6.5.7.5.2: "Command Mode Settings"


> 
>>
>> Signed-off-by: Aradhya Bhatia 
>> ---
>>   drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 3 +++
>>   1 file changed, 3 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>> b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>> index 126e4bccd868..cad0c1478ef0 100644
>> --- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>> +++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>> @@ -1018,6 +1018,9 @@ static ssize_t cdns_dsi_transfer(struct
>> mipi_dsi_host *host,
>>     cdns_dsi_init_link(dsi);
>>   +    /* Reset the DCS Write FIFO */
>> +    writel(0x00, dsi->regs + DIRECT_CMD_FIFO_RST);
>> >>   ret = mipi_dsi_create_packet(, msg);
>>   if (ret)
>>   goto out;
> 
> 


Re: [PATCH v4 05/11] drm/bridge: cdns-dsi: Fix the clock variable for mode_valid()

2024-06-26 Thread Aradhya Bhatia



On 26/06/24 16:17, Tomi Valkeinen wrote:
> On 22/06/2024 14:09, Aradhya Bhatia wrote:
>> Allow the D-Phy config checks to use mode->clock instead of
>> mode->crtc_clock during mode_valid checks, like everywhere else in the
>> driver.
>>
>> Fixes: fced5a364dee ("drm/bridge: cdns: Convert to phy framework")
>> Signed-off-by: Aradhya Bhatia 
>> ---
>>   drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>> b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>> index 03a5af52ec0b..426f77092341 100644
>> --- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>> +++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>> @@ -574,7 +574,7 @@ static int cdns_dsi_check_conf(struct cdns_dsi *dsi,
>>   if (ret)
>>   return ret;
>>   -    phy_mipi_dphy_get_default_config(mode->crtc_clock * 1000,
>> +    phy_mipi_dphy_get_default_config((mode_valid_check ? mode->clock
>> : mode->crtc_clock) * 1000,
>>    mipi_dsi_pixel_format_to_bpp(output->dev->format),
>>    nlanes, phy_cfg);
>>   
> 
> I think this is fine as a fix.
> 
> Reviewed-by: Tomi Valkeinen 
> 
> However... The code looks a bit messy. Maybe the first one is something
> that could be addressed in this series.
> 
> - Return value of phy_mipi_dphy_get_default_config() is not checked

Sure, I can fix that.

> 
> - Using the non-crtc and crtc versions of the timings this way looks
> bad, but that's not a problem of the driver. It would be better to have
> a struct that contains the timings, and struct drm_display_mode would
> contain two instances of that struct. The driver code could then just
> pick the correct instance, instead of making the choice for each and
> every field. This would be an interesting coccinelle project ;)
> 
> - Calling cdns_dsi_check_conf() in cdns_dsi_bridge_enable() is odd.
> Everything should already have been checked. In fact, at the check phase
> the resulting config values could have been stored somewhere, so that
> they're ready for use by cdns_dsi_bridge_enable(). But this rises the
> question if the non-crtc and crtc timings can actually be different, and
> if they are... doesn't it break everything if at the check phase we use
> the non-crtc ones, but at enable phase we use crtc ones?

It'd appear that it does. I don't fully understand why the driver uses
non-crtc_* timing parameters during the check phase, only to use the
crtc_* timing parameters during _enable().

Since with tidss, both the sets are same, I haven't had to think too
much about this! =)

What is the ideal way that this should get addressed though? If we have
an agreeable resolution then maybe I can fix that as well.

> 
> Ah, I see, this is with non-atomic. Maybe after you switch to atomic
> callbacks, atomic_check could be used so that there's no need for the
> WARN_ON_ONCE() in enable callback.
> 

Yes, I think this would be better. We can use atomic_check() to verify
the crtc_* timing parameters, while the already existing mode_valid()
can continue checking the non-crtc_* ones.

I will add this change when I am adding other atomic_* APIs later in the
series.


Regards
Aradhya



Re: [PATCH v4 03/11] drm/bridge: cdns-dsi: Fix Phy _init() and _exit()

2024-06-26 Thread Aradhya Bhatia
Hi Tomi,

Thanks for reviewing the patches!

On 26/06/24 15:55, Tomi Valkeinen wrote:
> Hi,
> 
> On 22/06/2024 14:09, Aradhya Bhatia wrote:
>> Initialize the Phy during the cdns-dsi _resume(), and de-initialize it
>> during the _suspend().
>>
>> Also power-off the Phy from bridge_disable.
>>
>> Fixes: fced5a364dee ("drm/bridge: cdns: Convert to phy framework")
>> Signed-off-by: Aradhya Bhatia 
>> ---
>>   drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 10 --
>>   1 file changed, 8 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>> b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>> index 5159c3f0853e..d89c32bae2b9 100644
>> --- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>> +++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>> @@ -672,6 +672,10 @@ static void cdns_dsi_bridge_disable(struct
>> drm_bridge *bridge)
>>   if (dsi->platform_ops && dsi->platform_ops->disable)
>>   dsi->platform_ops->disable(dsi);
>>   +    phy_power_off(dsi->dphy);
>> +    dsi->link_initialized = false;
>> +    dsi->phy_initialized = false;
>> +
>>   pm_runtime_put(dsi->base.dev);
>>   }
>>   @@ -698,7 +702,6 @@ static void cdns_dsi_hs_init(struct cdns_dsi *dsi)
>>  DPHY_CMN_PDN | DPHY_PLL_PDN,
>>  dsi->regs + MCTL_DPHY_CFG0);
>>   -    phy_init(dsi->dphy);
>>   phy_set_mode(dsi->dphy, PHY_MODE_MIPI_DPHY);
>>   phy_configure(dsi->dphy, >phy_opts);
>>   phy_power_on(dsi->dphy);
>> @@ -1120,6 +1123,8 @@ static int __maybe_unused cdns_dsi_resume(struct
>> device *dev)
>>   clk_prepare_enable(dsi->dsi_p_clk);
>>   clk_prepare_enable(dsi->dsi_sys_clk);
>>   +    phy_init(dsi->dphy);
>> +
>>   return 0;
>>   }
>>   @@ -1127,10 +1132,11 @@ static int __maybe_unused
>> cdns_dsi_suspend(struct device *dev)
>>   {
>>   struct cdns_dsi *dsi = dev_get_drvdata(dev);
>>   +    phy_exit(dsi->dphy);
>> +
>>   clk_disable_unprepare(dsi->dsi_sys_clk);
>>   clk_disable_unprepare(dsi->dsi_p_clk);
>>   reset_control_assert(dsi->dsi_p_rst);
>> -    dsi->link_initialized = false;
>>   return 0;
>>   }
>>   
> 
> So with this patch, phy_init/exit will be called in the resume/suspend
> functions. That looks fine.
> 
> But the phy_power_on/phy_power_off looks odd to me. Here you add
> phy_power_off() to cdns_dsi_bridge_disable(), which sounds fine. But
> phy_power_on() is called in cdns_dsi_hs_init(), and that is called in
> cdns_dsi_bridge_enable() (which sounds fine), but also in
> cdns_dsi_bridge_pre_enable().
> 
> So doesn't that mean cdns_dsi_hs_init() call in cdns_dsi_bridge_enable()
> is extra, as it effectively does nothing (it exists right away if
> dsi->phy_initialized == true)?

That's right. When cdns_dsi_hs_init() is called from
cdns_dsi_bridge_enable(), it is simply expected to return since
phy_initialized is true.

I am not aware about the exact reasoning behind this, but this gets
addressed when I convert the _bridge_enable() to _bridge_pre_enable()
and drop the older _bridge_pre_enable() entirely.


Regards
Aradhya


Re: [PATCH] drm/bridge: display-connector: Fix atomic_get_input_bus_fmt hook

2024-06-26 Thread Aradhya Bhatia



On 25/06/24 19:46, Neil Armstrong wrote:
> On 25/06/2024 11:50, Aradhya Bhatia wrote:
>> The display-connector acts as a pass-through bridge. To truly reflect
>> that, this bridge should accept the same input format, as it expects to
>> output. That in turn should be the same as what the preceding bridge has
>> to output.
>>
>> While the get_output_fmt hook does exactly that by calling the same hook
>> of the previous bridge, the get_input_fmt hook should simply propagate
>> the expected output format as its required input format.
>>
>> Let's say bridge(n) converts YUV bus format to RGB before transmitting
>> the video signals. B is supposed to be RGB and A is YUV. The
>> get_input_fmt hook of bridge(n) should receive RGB as its expected
>> output format for it to select YUV as its required input format.
>>
>> Moreover, since the display-connector is a pass-through bridge, X and Y
>> should both be RGB as well.
>>
>>  +-+    +-+
>> A   | |   B    X   | |   Y
>> --->|  Bridge(n)  +--->    --->| Display +--->
>>  | |    | Connector   |
>>  | |    | |
>>  +-+    +-+
>>
>> But that's not what's happening at the moment.
>>
>> The core will call get_output_fmt hook of display-connector, which will
>> call the same hook of bridge(n). Y will get set to RGB because B is RGB.
>>
>> Now the core will call get_input_fmt hook of display-connector with Y =
>> RGB as its expected output format. This hook will in turn call the
>> get_input_fmt hook of bridge(n), with expected output as RGB. This hook
>> will then return YUV as its required input format, which will set X =
>> YUV.
>>
>> This is where things get off the track. The core will then call
>> bridge(n)'s get_input_fmt hook but this time the expected output will
>> have changed to X = YUV, instead of what ideally should have been X =
>> RGB. We don't know how bridge(n)'s input format requirement will change
>> now that its expected output format isn't RGB but YUV.
>>
>> Ideally, formats Y, X, B need to be the same and the get_input_fmt hook
>> for bridge(n) should be called with these as its expected output format.
>> Calling that hook twice can potentially change the expected output
>> format - which can then change the required input format again, or it
>> might just throw an -ENOTSUPP error.
>>
>> While many bridges don't utilize these APIs, or in a lot of cases A and
>> B are same anyway, it is not the biggest problem, but one that should be
>> fixed anyway.
>>
>> Fix this.
>>
>> Fixes: 7cd70656d128 ("drm/bridge: display-connector: implement bus
>> fmts callbacks")
>> Signed-off-by: Aradhya Bhatia 
>> ---
>>   drivers/gpu/drm/bridge/display-connector.c | 40 +-
>>   1 file changed, 1 insertion(+), 39 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/bridge/display-connector.c
>> b/drivers/gpu/drm/bridge/display-connector.c
>> index ab8e00baf3f1..eebf1fbcdd23 100644
>> --- a/drivers/gpu/drm/bridge/display-connector.c
>> +++ b/drivers/gpu/drm/bridge/display-connector.c
>> @@ -131,50 +131,12 @@ static u32
>> *display_connector_get_output_bus_fmts(struct drm_bridge *bridge,
>>     num_output_fmts);
>>   }
>>   -/*
>> - * Since this bridge is tied to the connector, it acts like a
>> passthrough,
>> - * so concerning the input bus formats, either pass the bus formats
>> from the
>> - * previous bridge or MEDIA_BUS_FMT_FIXED (like
>> select_bus_fmt_recursive())
>> - * when atomic_get_input_bus_fmts is not supported.
>> - * This supports negotiation if the bridge chain has all bits in place.
>> - */
>> -static u32 *display_connector_get_input_bus_fmts(struct drm_bridge
>> *bridge,
>> -    struct drm_bridge_state *bridge_state,
>> -    struct drm_crtc_state *crtc_state,
>> -    struct drm_connector_state *conn_state,
>> -    u32 output_fmt,
>> -    unsigned int *num_input_fmts)
>> -{
>> -    struct drm_bridge *prev_bridge = drm_bridge_get_prev_bridge(bridge);
>> -    struct drm_bridge_state *prev_bridge_state;
>> -
>> -    if (!prev_bridge ||
>> !prev_bridge->funcs->atomic_get_input_bus_fmts) {
>> -    u32 *in_bus_fmts;
>> -
>> -    *num_input_fmts = 1;
>> -    in_bus_fmts

[PATCH] drm/bridge: display-connector: Fix atomic_get_input_bus_fmt hook

2024-06-25 Thread Aradhya Bhatia
The display-connector acts as a pass-through bridge. To truly reflect
that, this bridge should accept the same input format, as it expects to
output. That in turn should be the same as what the preceding bridge has
to output.

While the get_output_fmt hook does exactly that by calling the same hook
of the previous bridge, the get_input_fmt hook should simply propagate
the expected output format as its required input format.

Let's say bridge(n) converts YUV bus format to RGB before transmitting
the video signals. B is supposed to be RGB and A is YUV. The
get_input_fmt hook of bridge(n) should receive RGB as its expected
output format for it to select YUV as its required input format.

Moreover, since the display-connector is a pass-through bridge, X and Y
should both be RGB as well.

+-++-+
A   | |   BX   | |   Y
--->|  Bridge(n)  +--->--->| Display +--->
| || Connector   |
| || |
+-++-+

But that's not what's happening at the moment.

The core will call get_output_fmt hook of display-connector, which will
call the same hook of bridge(n). Y will get set to RGB because B is RGB.

Now the core will call get_input_fmt hook of display-connector with Y =
RGB as its expected output format. This hook will in turn call the
get_input_fmt hook of bridge(n), with expected output as RGB. This hook
will then return YUV as its required input format, which will set X =
YUV.

This is where things get off the track. The core will then call
bridge(n)'s get_input_fmt hook but this time the expected output will
have changed to X = YUV, instead of what ideally should have been X =
RGB. We don't know how bridge(n)'s input format requirement will change
now that its expected output format isn't RGB but YUV.

Ideally, formats Y, X, B need to be the same and the get_input_fmt hook
for bridge(n) should be called with these as its expected output format.
Calling that hook twice can potentially change the expected output
format - which can then change the required input format again, or it
might just throw an -ENOTSUPP error.

While many bridges don't utilize these APIs, or in a lot of cases A and
B are same anyway, it is not the biggest problem, but one that should be
fixed anyway.

Fix this.

Fixes: 7cd70656d128 ("drm/bridge: display-connector: implement bus fmts 
callbacks")
Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/display-connector.c | 40 +-
 1 file changed, 1 insertion(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/bridge/display-connector.c 
b/drivers/gpu/drm/bridge/display-connector.c
index ab8e00baf3f1..eebf1fbcdd23 100644
--- a/drivers/gpu/drm/bridge/display-connector.c
+++ b/drivers/gpu/drm/bridge/display-connector.c
@@ -131,50 +131,12 @@ static u32 *display_connector_get_output_bus_fmts(struct 
drm_bridge *bridge,
  num_output_fmts);
 }
 
-/*
- * Since this bridge is tied to the connector, it acts like a passthrough,
- * so concerning the input bus formats, either pass the bus formats from the
- * previous bridge or MEDIA_BUS_FMT_FIXED (like select_bus_fmt_recursive())
- * when atomic_get_input_bus_fmts is not supported.
- * This supports negotiation if the bridge chain has all bits in place.
- */
-static u32 *display_connector_get_input_bus_fmts(struct drm_bridge *bridge,
-   struct drm_bridge_state *bridge_state,
-   struct drm_crtc_state *crtc_state,
-   struct drm_connector_state *conn_state,
-   u32 output_fmt,
-   unsigned int *num_input_fmts)
-{
-   struct drm_bridge *prev_bridge = drm_bridge_get_prev_bridge(bridge);
-   struct drm_bridge_state *prev_bridge_state;
-
-   if (!prev_bridge || !prev_bridge->funcs->atomic_get_input_bus_fmts) {
-   u32 *in_bus_fmts;
-
-   *num_input_fmts = 1;
-   in_bus_fmts = kmalloc(sizeof(*in_bus_fmts), GFP_KERNEL);
-   if (!in_bus_fmts)
-   return NULL;
-
-   in_bus_fmts[0] = MEDIA_BUS_FMT_FIXED;
-
-   return in_bus_fmts;
-   }
-
-   prev_bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state,
-   prev_bridge);
-
-   return prev_bridge->funcs->atomic_get_input_bus_fmts(prev_bridge, 
prev_bridge_state,
-crtc_state, 
conn_state, output_fmt,
-num_input_fmts);
-}
-
 static const struct drm_bridge_funcs display_connector_bridge_funcs = {
.attach = display_connector_attach,
 

Re: [PATCH v2 0/2] drm/bridge: tc358767: Fix DRM_BRIDGE_ATTACH_NO_CONNECTOR case

2024-06-24 Thread Aradhya Bhatia



On 22/06/24 17:49, Dmitry Baryshkov wrote:
> On Sat, Jun 22, 2024 at 05:16:58PM GMT, Aradhya Bhatia wrote:
>>
>>
>> On 17-Jun-24 13:41, Dmitry Baryshkov wrote:
>>> On Mon, Jun 17, 2024 at 07:40:32AM GMT, Jan Kiszka wrote:
>>>> On 16.02.24 15:57, Marek Vasut wrote:
>>>>> On 2/16/24 10:10, Tomi Valkeinen wrote:
>>>>>> Ok. Does anyone have a worry that these patches make the situation
>>>>>> worse for the DSI case than it was before? Afaics, if the DSI lanes
>>>>>> are not set up early enough by the DSI host, the driver would break
>>>>>> with and without these patches.
>>>>>>
>>>>>> These do fix the driver for DRM_BRIDGE_ATTACH_NO_CONNECTOR and DPI, so
>>>>>> I'd like to merge these unless these cause a regression with the DSI
>>>>>> case.
>>>>>
>>>>> 1/2 looks good to me, go ahead and apply .
>>
>> Isn't there any way for the second patch to move forward as well though?
>> The bridge device (under DPI to (e)DP mode) cannot really work without
>> it, and the patches have been pending idle for a long time. =)
>>
>>>>
>>>> My local patches still apply on top of 6.10-rc4, so I don't think this
>>>> ever happened. What's still holding up this long-pending fix (at least
>>>> for our devices)?
>>>
>>> Neither of the patches contains Fixes tags. If the first patch fixes an
>>> issue in previous kernels, please consider following the stable process.
>>>
>>> If we are unsure about the second patch, please send the first patch
>>> separately, adding proper tags.
>>>
>>
>> Thanks Dmitry! I can send the patches again with the required fixes
>> tags (or just patch-1 if we cannot do anything about patch-2).
> 
> The problem with the second patch is that it get mixed reviews. I can
> ack the first patch, but for the second one I'd need a confirmation from
> somebody else. I'll go on and apply the first patch later today.
> 

Thanks Dmitry!

However, would it be okay if I instead add another patch that makes 2
versions of the "tc_edp_bridge_funcs", say "tc_dpi_edp_bridge_funcs" and
"tc_dsi_edp_bridge_funcs", that have all the same function hooks except
for the .edid_read()?

The dsi edid_read() will remain the same, and Tomi's patch - patch 2/2 -
will only fix the dpi version of the edid_read()?

The bridge already has the capability to distinguish a DSI input from a
DPI input. This can be leveraged to decide which set of functions need
to be used without any major changes.


Regards
Aradhya


Re: [PATCH v2 0/2] drm/bridge: tc358767: Fix DRM_BRIDGE_ATTACH_NO_CONNECTOR case

2024-06-22 Thread Aradhya Bhatia



On 17-Jun-24 13:41, Dmitry Baryshkov wrote:
> On Mon, Jun 17, 2024 at 07:40:32AM GMT, Jan Kiszka wrote:
>> On 16.02.24 15:57, Marek Vasut wrote:
>>> On 2/16/24 10:10, Tomi Valkeinen wrote:
 Ok. Does anyone have a worry that these patches make the situation
 worse for the DSI case than it was before? Afaics, if the DSI lanes
 are not set up early enough by the DSI host, the driver would break
 with and without these patches.

 These do fix the driver for DRM_BRIDGE_ATTACH_NO_CONNECTOR and DPI, so
 I'd like to merge these unless these cause a regression with the DSI
 case.
>>>
>>> 1/2 looks good to me, go ahead and apply .

Isn't there any way for the second patch to move forward as well though?
The bridge device (under DPI to (e)DP mode) cannot really work without
it, and the patches have been pending idle for a long time. =)

>>
>> My local patches still apply on top of 6.10-rc4, so I don't think this
>> ever happened. What's still holding up this long-pending fix (at least
>> for our devices)?
> 
> Neither of the patches contains Fixes tags. If the first patch fixes an
> issue in previous kernels, please consider following the stable process.
> 
> If we are unsure about the second patch, please send the first patch
> separately, adding proper tags.
> 

Thanks Dmitry! I can send the patches again with the required fixes
tags (or just patch-1 if we cannot do anything about patch-2).


-- 
Regards
Aradhya


[PATCH v4 11/11] drm/bridge: cdns-dsi: Use pre_enable/post_disable to enable/disable

2024-06-22 Thread Aradhya Bhatia
The cdns-dsi controller requires that it be turned on completely before
the input DPI's source has begun streaming[0]. Not having that, allows
for a small window before cdns-dsi enable and after cdns-dsi disable
where the previous entity (in this case tidss's videoport) to continue
streaming DPI video signals. This small window where cdns-dsi is
disabled but is still receiving signals causes the input FIFO of
cdns-dsi to get corrupted. This causes the colors to shift on the output
display. The colors can either shift by one color component (R->G, G->B,
B->R), or by two color components (R->B, G->R, B->G).

Since tidss's videoport starts streaming via crtc enable hooks, we need
cdns-dsi to be up and running before that. Now that the bridges are
pre_enabled before crtc is enabled, and post_disabled after crtc is
disabled, use the pre_enable and post_disable hooks to get cdns-dsi
ready and running before the tidss videoport to get pass the color shift
issues.

[0]: See section 12.6.5.7.3 "Start-up Procedure" in J721E SoC TRM
 TRM Link: http://www.ti.com/lit/pdf/spruil1

Signed-off-by: Aradhya Bhatia 
---
 .../gpu/drm/bridge/cadence/cdns-dsi-core.c| 32 +++
 1 file changed, 4 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index c9697818308e..c352ea7db4ed 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -655,8 +655,8 @@ cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge,
return MODE_OK;
 }
 
-static void cdns_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
-  struct drm_bridge_state 
*old_bridge_state)
+static void cdns_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
+   struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -680,15 +680,6 @@ static void cdns_dsi_bridge_atomic_disable(struct 
drm_bridge *bridge,
pm_runtime_put(dsi->base.dev);
 }
 
-static void cdns_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
-   struct drm_bridge_state 
*old_bridge_state)
-{
-   struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
-   struct cdns_dsi *dsi = input_to_dsi(input);
-
-   pm_runtime_put(dsi->base.dev);
-}
-
 static void cdns_dsi_hs_init(struct cdns_dsi *dsi)
 {
struct cdns_dsi_output *output = >output;
@@ -757,8 +748,8 @@ static void cdns_dsi_init_link(struct cdns_dsi *dsi)
dsi->link_initialized = true;
 }
 
-static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
- struct drm_bridge_state 
*old_bridge_state)
+static void cdns_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -909,19 +900,6 @@ static void cdns_dsi_bridge_atomic_enable(struct 
drm_bridge *bridge,
writel(tmp, dsi->regs + MCTL_MAIN_EN);
 }
 
-static void cdns_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
- struct drm_bridge_state 
*old_bridge_state)
-{
-   struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
-   struct cdns_dsi *dsi = input_to_dsi(input);
-
-   if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
-   return;
-
-   cdns_dsi_init_link(dsi);
-   cdns_dsi_hs_init(dsi);
-}
-
 static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
   struct drm_bridge_state 
*bridge_state,
   struct drm_crtc_state 
*crtc_state,
@@ -952,9 +930,7 @@ static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct 
drm_bridge *bridge,
 static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
.attach = cdns_dsi_bridge_attach,
.mode_valid = cdns_dsi_bridge_mode_valid,
-   .atomic_disable = cdns_dsi_bridge_atomic_disable,
.atomic_pre_enable = cdns_dsi_bridge_atomic_pre_enable,
-   .atomic_enable = cdns_dsi_bridge_atomic_enable,
.atomic_post_disable = cdns_dsi_bridge_atomic_post_disable,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
-- 
2.34.1



[PATCH v4 05/11] drm/bridge: cdns-dsi: Fix the clock variable for mode_valid()

2024-06-22 Thread Aradhya Bhatia
Allow the D-Phy config checks to use mode->clock instead of
mode->crtc_clock during mode_valid checks, like everywhere else in the
driver.

Fixes: fced5a364dee ("drm/bridge: cdns: Convert to phy framework")
Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 03a5af52ec0b..426f77092341 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -574,7 +574,7 @@ static int cdns_dsi_check_conf(struct cdns_dsi *dsi,
if (ret)
return ret;
 
-   phy_mipi_dphy_get_default_config(mode->crtc_clock * 1000,
+   phy_mipi_dphy_get_default_config((mode_valid_check ? mode->clock : 
mode->crtc_clock) * 1000,
 
mipi_dsi_pixel_format_to_bpp(output->dev->format),
 nlanes, phy_cfg);
 
-- 
2.34.1



[PATCH v4 04/11] drm/bridge: cdns-dsi: Fix the link and phy init order

2024-06-22 Thread Aradhya Bhatia
The order of init of DSI link and DSI phy is wrong. The DSI link needs
to be configured before the DSI phy is getting configured. Otherwise,
the D-Phy is unable to lock in on the incoming PLL Reference clock[0].

Fix the order of inits.

[0]: See section 12.6.5.7.3 "Start-up Procedure" in J721E SoC TRM
 TRM Link: http://www.ti.com/lit/pdf/spruil1

Fixes: fced5a364dee ("drm/bridge: cdns: Convert to phy framework")
Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index d89c32bae2b9..03a5af52ec0b 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -778,8 +778,8 @@ static void cdns_dsi_bridge_enable(struct drm_bridge 
*bridge)
 
WARN_ON_ONCE(cdns_dsi_check_conf(dsi, mode, _cfg, false));
 
-   cdns_dsi_hs_init(dsi);
cdns_dsi_init_link(dsi);
+   cdns_dsi_hs_init(dsi);
 
writel(HBP_LEN(dsi_cfg.hbp) | HSA_LEN(dsi_cfg.hsa),
   dsi->regs + VID_HSIZE1);
-- 
2.34.1



[PATCH v4 02/11] drm/bridge: cdns-dsi: Move to devm_drm_of_get_bridge()

2024-06-22 Thread Aradhya Bhatia
Instead of manually finding the next bridge/panel, and maintaining the
panel-bridge (in-case the next entity is a panel), switch to using the
automatically managing devm_drm_of_get_bridge() API.

Drop the drm_panel support completely from the driver while at it.

Signed-off-by: Aradhya Bhatia 
---
 .../gpu/drm/bridge/cadence/cdns-dsi-core.c| 28 ++-
 .../gpu/drm/bridge/cadence/cdns-dsi-core.h|  2 --
 2 files changed, 3 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index b016f2ba06bb..5159c3f0853e 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -920,8 +920,6 @@ static int cdns_dsi_attach(struct mipi_dsi_host *host,
struct cdns_dsi_output *output = >output;
struct cdns_dsi_input *input = >input;
struct drm_bridge *bridge;
-   struct drm_panel *panel;
-   struct device_node *np;
int ret;
 
/*
@@ -939,26 +937,10 @@ static int cdns_dsi_attach(struct mipi_dsi_host *host,
/*
 * The host <-> device link might be described using an OF-graph
 * representation, in this case we extract the device of_node from
-* this representation, otherwise we use dsidev->dev.of_node which
-* should have been filled by the core.
+* this representation.
 */
-   np = of_graph_get_remote_node(dsi->base.dev->of_node, DSI_OUTPUT_PORT,
- dev->channel);
-   if (!np)
-   np = of_node_get(dev->dev.of_node);
-
-   panel = of_drm_find_panel(np);
-   if (!IS_ERR(panel)) {
-   bridge = drm_panel_bridge_add_typed(panel,
-   DRM_MODE_CONNECTOR_DSI);
-   } else {
-   bridge = of_drm_find_bridge(np);
-   if (!bridge)
-   bridge = ERR_PTR(-EINVAL);
-   }
-
-   of_node_put(np);
-
+   bridge = devm_drm_of_get_bridge(dsi->base.dev, dsi->base.dev->of_node,
+   DSI_OUTPUT_PORT, dev->channel);
if (IS_ERR(bridge)) {
ret = PTR_ERR(bridge);
dev_err(host->dev, "failed to add DSI device %s (err = %d)",
@@ -968,7 +950,6 @@ static int cdns_dsi_attach(struct mipi_dsi_host *host,
 
output->dev = dev;
output->bridge = bridge;
-   output->panel = panel;
 
/*
 * The DSI output has been properly configured, we can now safely
@@ -984,12 +965,9 @@ static int cdns_dsi_detach(struct mipi_dsi_host *host,
   struct mipi_dsi_device *dev)
 {
struct cdns_dsi *dsi = to_cdns_dsi(host);
-   struct cdns_dsi_output *output = >output;
struct cdns_dsi_input *input = >input;
 
drm_bridge_remove(>bridge);
-   if (output->panel)
-   drm_panel_bridge_remove(output->bridge);
 
return 0;
 }
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h
index ca7ea2da635c..5db5dbbbcaad 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h
@@ -10,7 +10,6 @@
 
 #include 
 #include 
-#include 
 
 #include 
 #include 
@@ -21,7 +20,6 @@ struct reset_control;
 
 struct cdns_dsi_output {
struct mipi_dsi_device *dev;
-   struct drm_panel *panel;
struct drm_bridge *bridge;
union phy_configure_opts phy_opts;
 };
-- 
2.34.1



[PATCH v4 07/11] drm/bridge: cdns-dsi: Reset the DCS write FIFO

2024-06-22 Thread Aradhya Bhatia
If any normal DCS write command has already been transmitted prior to
transmitting any Zero-Parameter DCS command, then it is necessary to
clear the TX FIFO by resetting it. Otherwise, the FIFO points to another
location, and the DCS command transmits unnecessary data causing the
panel to not work[0].

Allow the DCS Write FIFO in the cdns-dsi controller to reset as a rule,
before any DCS packet is transmitted to the DSI peripheral.

[0]: Section 12.6.5.7.5.2: "Command Mode Settings" in TDA4VM Technical
 Reference Manual: https://www.ti.com/lit/zip/spruil1

Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 126e4bccd868..cad0c1478ef0 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -1018,6 +1018,9 @@ static ssize_t cdns_dsi_transfer(struct mipi_dsi_host 
*host,
 
cdns_dsi_init_link(dsi);
 
+   /* Reset the DCS Write FIFO */
+   writel(0x00, dsi->regs + DIRECT_CMD_FIFO_RST);
+
ret = mipi_dsi_create_packet(, msg);
if (ret)
goto out;
-- 
2.34.1



[PATCH v4 10/11] drm/atomic-helper: Re-order bridge chain pre-enable and post-disable

2024-06-22 Thread Aradhya Bhatia
Move the bridge pre_enable call before crtc enable, and the bridge
post_disable call after the crtc disable.

The sequence of enable after this patch will look like:

bridge[n]_pre_enable
...
bridge[1]_pre_enable

crtc_enable
encoder_enable

bridge[1]_enable
...
bridge[n]__enable

and vice-versa for the bridge chain disable sequence.

The definition of bridge pre_enable hook says that,
"The display pipe (i.e. clocks and timing signals) feeding this bridge
will not yet be running when this callback is called".

Since CRTC is also a source feeding the bridge, it should not be enabled
before the bridges in the pipeline are pre_enabled. Fix that by
re-ordering the sequence of bridge pre_enable and bridge post_disable.

Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/drm_atomic_helper.c | 165 ++--
 include/drm/drm_atomic_helper.h |   7 ++
 2 files changed, 114 insertions(+), 58 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index fb97b51b38f1..e8ad08634f58 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -74,6 +74,7 @@
  * also shares the  drm_plane_helper_funcs function table with the plane
  * helpers.
  */
+
 static void
 drm_atomic_helper_plane_changed(struct drm_atomic_state *state,
struct drm_plane_state *old_plane_state,
@@ -1122,11 +1123,11 @@ crtc_needs_disable(struct drm_crtc_state *old_state,
 }
 
 static void
-disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
+disable_encoder_brige_chain(struct drm_device *dev, struct drm_atomic_state 
*old_state,
+   enum bridge_chain_operation_type op_type)
 {
struct drm_connector *connector;
struct drm_connector_state *old_conn_state, *new_conn_state;
-   struct drm_crtc *crtc;
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
int i;
 
@@ -1163,32 +1164,55 @@ disable_outputs(struct drm_device *dev, struct 
drm_atomic_state *old_state)
if (WARN_ON(!encoder))
continue;
 
-   funcs = encoder->helper_private;
-
-   drm_dbg_atomic(dev, "disabling [ENCODER:%d:%s]\n",
-  encoder->base.id, encoder->name);
-
/*
 * Each encoder has at most one connector (since we always steal
 * it away), so we won't call disable hooks twice.
 */
bridge = drm_bridge_chain_get_first_bridge(encoder);
-   drm_atomic_bridge_chain_disable(bridge, old_state);
 
-   /* Right function depends upon target state. */
-   if (funcs) {
-   if (funcs->atomic_disable)
-   funcs->atomic_disable(encoder, old_state);
-   else if (new_conn_state->crtc && funcs->prepare)
-   funcs->prepare(encoder);
-   else if (funcs->disable)
-   funcs->disable(encoder);
-   else if (funcs->dpms)
-   funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
-   }
+   switch (op_type) {
+   case DRM_ENCODER_BRIDGE_DISABLE:
+   funcs = encoder->helper_private;
+
+   drm_dbg_atomic(dev, "disabling [ENCODER:%d:%s]\n",
+  encoder->base.id, encoder->name);
+
+   drm_atomic_bridge_chain_disable(bridge, old_state);
+
+   /* Right function depends upon target state. */
+   if (funcs) {
+   if (funcs->atomic_disable)
+   funcs->atomic_disable(encoder, 
old_state);
+   else if (new_conn_state->crtc && funcs->prepare)
+   funcs->prepare(encoder);
+   else if (funcs->disable)
+   funcs->disable(encoder);
+   else if (funcs->dpms)
+   funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
+   }
+
+   break;
+
+   case DRM_BRIDGE_POST_DISABLE:
+   drm_atomic_bridge_chain_post_disable(bridge, old_state);
 
-   drm_atomic_bridge_chain_post_disable(bridge, old_state);
+   break;
+
+   default:
+   drm_err(dev, "Unrecognized Encoder/Bridge Operation 
(%d).\n", op_type);
+   break;
+   }
}
+}
+
+static void
+disable_outputs(struct drm_

[PATCH v4 09/11] drm/bridge: cdns-dsi: Support atomic bridge APIs

2024-06-22 Thread Aradhya Bhatia
Change the existing (and deprecated) bridge hooks, to the bridge
atomic APIs.

Add drm helpers for duplicate_state, destroy_state, and bridge_reset
bridge hooks.

Further add support for the input format negotiation hook.

Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Aradhya Bhatia 
---
 .../gpu/drm/bridge/cadence/cdns-dsi-core.c| 51 ---
 1 file changed, 43 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index cad0c1478ef0..c9697818308e 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -655,7 +655,8 @@ cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge,
return MODE_OK;
 }
 
-static void cdns_dsi_bridge_disable(struct drm_bridge *bridge)
+static void cdns_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
+  struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -679,7 +680,8 @@ static void cdns_dsi_bridge_disable(struct drm_bridge 
*bridge)
pm_runtime_put(dsi->base.dev);
 }
 
-static void cdns_dsi_bridge_post_disable(struct drm_bridge *bridge)
+static void cdns_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
+   struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -755,7 +757,8 @@ static void cdns_dsi_init_link(struct cdns_dsi *dsi)
dsi->link_initialized = true;
 }
 
-static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
+static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -906,7 +909,8 @@ static void cdns_dsi_bridge_enable(struct drm_bridge 
*bridge)
writel(tmp, dsi->regs + MCTL_MAIN_EN);
 }
 
-static void cdns_dsi_bridge_pre_enable(struct drm_bridge *bridge)
+static void cdns_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -918,13 +922,44 @@ static void cdns_dsi_bridge_pre_enable(struct drm_bridge 
*bridge)
cdns_dsi_hs_init(dsi);
 }
 
+static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
+  struct drm_bridge_state 
*bridge_state,
+  struct drm_crtc_state 
*crtc_state,
+  struct drm_connector_state 
*conn_state,
+  u32 output_fmt,
+  unsigned int *num_input_fmts)
+{
+   struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
+   struct cdns_dsi *dsi = input_to_dsi(input);
+   struct cdns_dsi_output *output = >output;
+   u32 *input_fmts;
+
+   *num_input_fmts = 0;
+
+   input_fmts = kzalloc(sizeof(*input_fmts), GFP_KERNEL);
+   if (!input_fmts)
+   return NULL;
+
+   input_fmts[0] = drm_mipi_dsi_get_input_bus_fmt(output->dev->format);
+   if (!input_fmts[0])
+   return NULL;
+
+   *num_input_fmts = 1;
+
+   return input_fmts;
+}
+
 static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
.attach = cdns_dsi_bridge_attach,
.mode_valid = cdns_dsi_bridge_mode_valid,
-   .disable = cdns_dsi_bridge_disable,
-   .pre_enable = cdns_dsi_bridge_pre_enable,
-   .enable = cdns_dsi_bridge_enable,
-   .post_disable = cdns_dsi_bridge_post_disable,
+   .atomic_disable = cdns_dsi_bridge_atomic_disable,
+   .atomic_pre_enable = cdns_dsi_bridge_atomic_pre_enable,
+   .atomic_enable = cdns_dsi_bridge_atomic_enable,
+   .atomic_post_disable = cdns_dsi_bridge_atomic_post_disable,
+   .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+   .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+   .atomic_reset = drm_atomic_helper_bridge_reset,
+   .atomic_get_input_bus_fmts = cdns_dsi_bridge_get_input_bus_fmts,
 };
 
 static int cdns_dsi_attach(struct mipi_dsi_host *host,
-- 
2.34.1



[PATCH v4 08/11] drm/mipi-dsi: Add helper to find input format

2024-06-22 Thread Aradhya Bhatia
Add a helper API that can be used by the DSI hosts to find the required
input bus format for the given output dsi pixel format.

Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/drm_mipi_dsi.c | 37 ++
 include/drm/drm_mipi_dsi.h |  1 +
 2 files changed, 38 insertions(+)

diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index a471c46f5ca6..937aa16dfcf6 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -36,6 +36,8 @@
 #include 
 #include 
 
+#include 
+
 #include 
 
 /**
@@ -866,6 +868,41 @@ ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, 
const void *params,
 }
 EXPORT_SYMBOL(mipi_dsi_generic_read);
 
+/**
+ * drm_mipi_dsi_get_input_bus_fmt() - Get the required MEDIA_BUS_FMT_* based
+ *   input pixel format for a given DSI output
+ *   pixel format
+ * @dsi_format: pixel format that a DSI host needs to output
+ *
+ * Various DSI hosts can use this function during their
+ * _bridge_funcs.atomic_get_input_bus_fmts operation to ascertain
+ * the MEDIA_BUS_FMT_* pixel format required as input.
+ *
+ * RETURNS:
+ * a 32-bit MEDIA_BUS_FMT_* value on success or 0 in case of failure.
+ */
+u32 drm_mipi_dsi_get_input_bus_fmt(enum mipi_dsi_pixel_format dsi_format)
+{
+   switch (dsi_format) {
+   case MIPI_DSI_FMT_RGB888:
+   return MEDIA_BUS_FMT_RGB888_1X24;
+
+   case MIPI_DSI_FMT_RGB666:
+   return MEDIA_BUS_FMT_RGB666_1X24_CPADHI;
+
+   case MIPI_DSI_FMT_RGB666_PACKED:
+   return MEDIA_BUS_FMT_RGB666_1X18;
+
+   case MIPI_DSI_FMT_RGB565:
+   return MEDIA_BUS_FMT_RGB565_1X16;
+
+   default:
+   /* Unsupported DSI Format */
+   return 0;
+   }
+}
+EXPORT_SYMBOL(drm_mipi_dsi_get_input_bus_fmt);
+
 /**
  * mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload
  * @dsi: DSI peripheral device
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 71d121aeef24..78a2c7d9eefb 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -290,6 +290,7 @@ void mipi_dsi_generic_write_multi(struct 
mipi_dsi_multi_context *ctx,
  const void *payload, size_t size);
 ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
  size_t num_params, void *data, size_t size);
+u32 drm_mipi_dsi_get_input_bus_fmt(enum mipi_dsi_pixel_format dsi_format);
 
 #define mipi_dsi_msleep(ctx, delay)\
do {\
-- 
2.34.1



[PATCH v4 00/11] drm/bridge: cdns-dsi: Fix the color-shift issue

2024-06-22 Thread Aradhya Bhatia
Hello all,

This series provides some crucial fixes and improvements for the Cadence's DSI
TX (cdns-dsi) controller found commonly in Texas Instruments' J7 family of SoCs
as well as in AM62P.

Along with that, this series aims to fix the color-shift issue that has been
going on with the DSI controller. This controller requires to be enabled before
the previous entity enables its stream[0]. It's a strict requirement which, if
not followed, causes the colors to "shift" on the display. The fix happens in
2 steps.

1. The bridge pre_enable calls have been shifted before the crtc_enable and
   the bridge post_disable calls have been shifted after the crtc_disable.
   This has been done as per the definition of bridge pre_enable.

   "The display pipe (i.e. clocks and timing signals) feeding this bridge
   will not yet be running when this callback is called".

   Since CRTC is also a source feeding the bridge, it should not be enabled
   before the bridges in the pipeline are pre_enabled.

   The sequence of enable after this patch will look like:

bridge[n]_pre_enable
...
bridge[1]_pre_enable

crtc_enable
encoder_enable

bridge[1]_enable
...
bridge[n]_enable

   and vice-versa for the bridge chain disable sequence.


2. The cdns-dsi enable / disable sequences have now been moved to pre_enable
   and post_disable sequences. This is the only way to have cdns-dsi drivers
   be up and ready before the previous entity is enables its streaming.

The DSI also spec requires the Clock and Data Lanes be ready before the DSI TX
enables its stream[0]. A patch has been added to make the code wait for that to
happen. Going ahead with further DSI (and DSS configuration), while the lanes
are not ready, has been found to be another reason for shift in colors.

These patches have been tested with J721E based BeagleboneAI64 along with a
RaspberryPi 7" DSI panel. The extra patches can be found in the
"next_dsi-v4-tests" branch of my github fork[1] for anyone who would like to
test them.

Thanks,
Aradhya


[0]: Section 12.6.5.7.3: "Start-up Procedure" [For DSI TX controller]
 in TDA4VM Technical Reference Manual https://www.ti.com/lit/zip/spruil1

[1]: https://github.com/aradhya07/linux-ab/tree/next_dsi-v4-tests

Change Log:

  - Changes in v4:
- Add new patch, "drm/bridge: cdns-dsi: Move to devm_drm_of_get_bridge()",
  to update to an auto-managed way of finding next bridge in the chain.
- Drop patch "drm/bridge: cdns-dsi: Fix the phy_initialized variable" and
  add "drm/bridge: cdns-dsi: Fix Phy _init() and _exit()" that properly
  de-initializes the Phy and maintains the initialization state.
- Reword patch "drm/bridge: cdns-dsi: Reset the DCS write FIFO" to explain
  the HW concerns better.
- Add R-b tag from Dmitry Baryshkov for patches 1/11 and 8/11.

  - Changes in v3:
- Reword the commit message for patch "drm/bridge: cdns-dsi: Fix OF node
  pointer".
- Add a new helper API to figure out DSI host input pixel format
  in patch "drm/mipi-dsi: Add helper to find input format".
- Use a common function for bridge pre-enable and enable, and bridge disable
  and post-disable, to avoid code duplication.
- Add T-b tag from Dominik Haller in patch 5/10. (Missed to add it in v2).
- Add R-b tag from Dmitry Baryshkov for patch 8/10.

  - Changes in v2:
- Drop patch "drm/tidss: Add CRTC mode_fixup"
- Split patch "drm/bridge: cdns-dsi: Fix minor bugs" into 4 separate ones
- Drop support for early_enable/late_disable APIs and instead re-order the
  pre_enable / post_disable APIs to be called before / after crtc_enable /
  crtc_disable.
- Drop support for early_enable/late_disable in cdns-dsi and use
  pre_enable/post_disable APIs instead to do bridge enable/disable.


Previous versions:

v1: https://lore.kernel.org/all/20240511153051.1355825-1-a-bhat...@ti.com/
v2: https://lore.kernel.org/all/20240530093621.1925863-1-a-bhat...@ti.com/
v3: https://lore.kernel.org/all/20240617105311.1587489-1-a-bhat...@ti.com/

Aradhya Bhatia (11):
  drm/bridge: cdns-dsi: Fix OF node pointer
  drm/bridge: cdns-dsi: Move to devm_drm_of_get_bridge()
  drm/bridge: cdns-dsi: Fix Phy _init() and _exit()
  drm/bridge: cdns-dsi: Fix the link and phy init order
  drm/bridge: cdns-dsi: Fix the clock variable for mode_valid()
  drm/bridge: cdns-dsi: Wait for Clk and Data Lanes to be ready
  drm/bridge: cdns-dsi: Reset the DCS write FIFO
  drm/mipi-dsi: Add helper to find input format
  drm/bridge: cdns-dsi: Support atomic bridge APIs
  drm/atomic-helper: Re-order bridge chain pre-enable and post-disable
  drm/bridge: cdns-dsi: Use pre_enable/post_disable to enable/disable

 ..

[PATCH v4 03/11] drm/bridge: cdns-dsi: Fix Phy _init() and _exit()

2024-06-22 Thread Aradhya Bhatia
Initialize the Phy during the cdns-dsi _resume(), and de-initialize it
during the _suspend().

Also power-off the Phy from bridge_disable.

Fixes: fced5a364dee ("drm/bridge: cdns: Convert to phy framework")
Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 5159c3f0853e..d89c32bae2b9 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -672,6 +672,10 @@ static void cdns_dsi_bridge_disable(struct drm_bridge 
*bridge)
if (dsi->platform_ops && dsi->platform_ops->disable)
dsi->platform_ops->disable(dsi);
 
+   phy_power_off(dsi->dphy);
+   dsi->link_initialized = false;
+   dsi->phy_initialized = false;
+
pm_runtime_put(dsi->base.dev);
 }
 
@@ -698,7 +702,6 @@ static void cdns_dsi_hs_init(struct cdns_dsi *dsi)
   DPHY_CMN_PDN | DPHY_PLL_PDN,
   dsi->regs + MCTL_DPHY_CFG0);
 
-   phy_init(dsi->dphy);
phy_set_mode(dsi->dphy, PHY_MODE_MIPI_DPHY);
phy_configure(dsi->dphy, >phy_opts);
phy_power_on(dsi->dphy);
@@ -1120,6 +1123,8 @@ static int __maybe_unused cdns_dsi_resume(struct device 
*dev)
clk_prepare_enable(dsi->dsi_p_clk);
clk_prepare_enable(dsi->dsi_sys_clk);
 
+   phy_init(dsi->dphy);
+
return 0;
 }
 
@@ -1127,10 +1132,11 @@ static int __maybe_unused cdns_dsi_suspend(struct 
device *dev)
 {
struct cdns_dsi *dsi = dev_get_drvdata(dev);
 
+   phy_exit(dsi->dphy);
+
clk_disable_unprepare(dsi->dsi_sys_clk);
clk_disable_unprepare(dsi->dsi_p_clk);
reset_control_assert(dsi->dsi_p_rst);
-   dsi->link_initialized = false;
return 0;
 }
 
-- 
2.34.1



[PATCH v4 06/11] drm/bridge: cdns-dsi: Wait for Clk and Data Lanes to be ready

2024-06-22 Thread Aradhya Bhatia
Once the DSI Link and DSI Phy are initialized, the code needs to wait
for Clk and Data Lanes to be ready, before continuing configuration.
This is in accordance with the DSI Start-up procedure, found in the
Technical Reference Manual of Texas Instrument's J721E SoC[0] which
houses this DSI TX controller.

If the previous bridge (or crtc/encoder) are configured pre-maturely,
the input signal FIFO gets corrupt. This introduces a color-shift on the
display.

Allow the driver to wait for the clk and data lanes to get ready during
DSI enable.

[0]: See section 12.6.5.7.3 "Start-up Procedure" in J721E SoC TRM
 TRM Link: http://www.ti.com/lit/pdf/spruil1

Fixes: e19233955d9e ("drm/bridge: Add Cadence DSI driver")
Tested-by: Dominik Haller 
Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 426f77092341..126e4bccd868 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -764,7 +764,7 @@ static void cdns_dsi_bridge_enable(struct drm_bridge 
*bridge)
struct phy_configure_opts_mipi_dphy *phy_cfg = 
>phy_opts.mipi_dphy;
unsigned long tx_byte_period;
struct cdns_dsi_cfg dsi_cfg;
-   u32 tmp, reg_wakeup, div;
+   u32 tmp, reg_wakeup, div, status;
int nlanes;
 
if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
@@ -781,6 +781,17 @@ static void cdns_dsi_bridge_enable(struct drm_bridge 
*bridge)
cdns_dsi_init_link(dsi);
cdns_dsi_hs_init(dsi);
 
+   /*
+* Now that the DSI Link and DSI Phy are initialized,
+* wait for the CLK and Data Lanes to be ready.
+*/
+   tmp = CLK_LANE_RDY;
+   for (int i = 0; i < nlanes; i++)
+   tmp |= DATA_LANE_RDY(i);
+
+   WARN_ON_ONCE(readl_poll_timeout(dsi->regs + MCTL_MAIN_STS, status,
+   status & tmp, 100, 0));
+
writel(HBP_LEN(dsi_cfg.hbp) | HSA_LEN(dsi_cfg.hsa),
   dsi->regs + VID_HSIZE1);
writel(HFP_LEN(dsi_cfg.hfp) | HACT_LEN(dsi_cfg.hact),
-- 
2.34.1



[PATCH v4 01/11] drm/bridge: cdns-dsi: Fix OF node pointer

2024-06-22 Thread Aradhya Bhatia
Fix the OF node pointer passed to the of_drm_find_bridge() call to find
the next bridge in the display chain.

To find the next bridge in the pipeline, we need to pass "np" - the OF
node pointer of the next entity in the devicetree chain. Passing
"of_node" to of_drm_find_bridge will make the function try to fetch the
bridge for the cdns-dsi which is not what's required.

Fix that.

Fixes: e19233955d9e ("drm/bridge: Add Cadence DSI driver")
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 7457d38622b0..b016f2ba06bb 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -952,7 +952,7 @@ static int cdns_dsi_attach(struct mipi_dsi_host *host,
bridge = drm_panel_bridge_add_typed(panel,
DRM_MODE_CONNECTOR_DSI);
} else {
-   bridge = of_drm_find_bridge(dev->dev.of_node);
+   bridge = of_drm_find_bridge(np);
if (!bridge)
bridge = ERR_PTR(-EINVAL);
}
-- 
2.34.1



Re: [PATCH v3 02/10] drm/bridge: cdns-dsi: Fix the phy_initialized variable

2024-06-19 Thread Aradhya Bhatia



On 18/06/24 01:04, Dmitry Baryshkov wrote:
> On Mon, 17 Jun 2024 at 17:16, Aradhya Bhatia  wrote:
>>
>> Hi Dmitry,
>>
>> Thanks for reviewing the patches!
>>
>> On 17/06/24 17:29, Dmitry Baryshkov wrote:
>>> On Mon, Jun 17, 2024 at 04:23:03PM GMT, Aradhya Bhatia wrote:
>>>> Update the Phy initialized state to "not initialized" when the driver
>>>> (and the hardware by extension) gets suspended. This will allow the Phy
>>>> to get initialized again after resume.
>>>>
>>>> Fixes: e19233955d9e ("drm/bridge: Add Cadence DSI driver")
>>>> Signed-off-by: Aradhya Bhatia 
>>>> ---
>>>>  drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 1 +
>>>>  1 file changed, 1 insertion(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
>>>> b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>>>> index b016f2ba06bb..42565e253b2d 100644
>>>> --- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>>>> +++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>>>> @@ -1153,6 +1153,7 @@ static int __maybe_unused cdns_dsi_suspend(struct 
>>>> device *dev)
>>>>  clk_disable_unprepare(dsi->dsi_p_clk);
>>>>  reset_control_assert(dsi->dsi_p_rst);
>>>>  dsi->link_initialized = false;
>>>
>>> Most likely you should also call phy_exit() here. And in _remove() too.
>>
>> I agree that phy_exit should be called here. But why in _remove()?
>> Wouldn't having phy_exit in 2 places mess up the internal ref count?
> 
> If suspend() is going to be called in the teardown path, then it's
> fine to have just one call here. Otherwise you might add one guarded
> with if (phy_initialized) to _remove() too.

Since the _suspend() and _resume() hooks are registered for both, system
sleep PM and runtime PM, the _suspend() hook does get called when I
remove the cdns_dsi module using modprobe. Tested that on my setup.

I believe having phy_exit() only in  _suspend() would suffice for now.

> 
>>
>>>
>>>> +dsi->phy_initialized = false;
>>>>  return 0;
>>>>  }
>>>>
>>>> --
>>>> 2.34.1
>>>>
>>>
>> --
>> Regards
>> Aradhya
> 
> 
> 

--
Regards
Aradhya


Re: [PATCH v3 02/10] drm/bridge: cdns-dsi: Fix the phy_initialized variable

2024-06-17 Thread Aradhya Bhatia
Hi Dmitry,

Thanks for reviewing the patches!

On 17/06/24 17:29, Dmitry Baryshkov wrote:
> On Mon, Jun 17, 2024 at 04:23:03PM GMT, Aradhya Bhatia wrote:
>> Update the Phy initialized state to "not initialized" when the driver
>> (and the hardware by extension) gets suspended. This will allow the Phy
>> to get initialized again after resume.
>>
>> Fixes: e19233955d9e ("drm/bridge: Add Cadence DSI driver")
>> Signed-off-by: Aradhya Bhatia 
>> ---
>>  drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
>> b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>> index b016f2ba06bb..42565e253b2d 100644
>> --- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>> +++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
>> @@ -1153,6 +1153,7 @@ static int __maybe_unused cdns_dsi_suspend(struct 
>> device *dev)
>>  clk_disable_unprepare(dsi->dsi_p_clk);
>>  reset_control_assert(dsi->dsi_p_rst);
>>  dsi->link_initialized = false;
> 
> Most likely you should also call phy_exit() here. And in _remove() too.

I agree that phy_exit should be called here. But why in _remove()?
Wouldn't having phy_exit in 2 places mess up the internal ref count?

> 
>> +dsi->phy_initialized = false;
>>  return 0;
>>  }
>>  
>> -- 
>> 2.34.1
>>
> 
--
Regards
Aradhya


Re: [PATCH] drm/tidss: Add drm_panic support

2024-06-17 Thread Aradhya Bhatia
Hi Javier,

I tested the patch, and it was good to see the panic screen on SK-AM62.
Thanks for adding this feature in tidss. =)

On 15/06/24 14:23, Javier Martinez Canillas wrote:
> Add support for the drm_panic module, which displays a pretty user
> friendly message on the screen when a Linux kernel panic occurs.
> 
> Signed-off-by: Javier Martinez Canillas 

Reviewed-by: Aradhya Bhatia 

> ---
> Tested on an AM625 BeaglePlay board by triggering a panic using the
> `echo c > /proc/sysrq-trigger` command.
> 
>  drivers/gpu/drm/tidss/tidss_plane.c | 14 +-
>  1 file changed, 13 insertions(+), 1 deletion(-)
> 

[...]

--
Regards
Aradhya


[PATCH v3 06/10] drm/bridge: cdns-dsi: Reset the DCS write FIFO

2024-06-17 Thread Aradhya Bhatia
Allow the DCS Write FIFO in the cdns-dsi controller to reset before any
DCS packet is transmitted to the DSI sink device.

The DCS FIFO reset is optional. Not all panels require it. But at
least one of the DSI based panel that uses Ilitek ILI9881C (DSI to DPI
bridge) doesn't work with without this reset.

Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 05d2f4cc50da..87fdd07ca0bc 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -1037,6 +1037,9 @@ static ssize_t cdns_dsi_transfer(struct mipi_dsi_host 
*host,
 
cdns_dsi_init_link(dsi);
 
+   /* Reset the DCS Write FIFO */
+   writel(0x00, dsi->regs + DIRECT_CMD_FIFO_RST);
+
ret = mipi_dsi_create_packet(, msg);
if (ret)
goto out;
-- 
2.34.1



[PATCH v3 10/10] drm/bridge: cdns-dsi: Use pre_enable/post_disable to enable/disable

2024-06-17 Thread Aradhya Bhatia
The cdns-dsi controller requires that it be turned on completely before
the input DPI's source has begun streaming[0]. Not having that, allows
for a small window before cdns-dsi enable and after cdns-dsi disable
where the previous entity (in this case tidss's videoport) to continue
streaming DPI video signals. This small window where cdns-dsi is
disabled but is still receiving signals causes the input FIFO of
cdns-dsi to get corrupted. This causes the colors to shift on the output
display. The colors can either shift by one color component (R->G, G->B,
B->R), or by two color components (R->B, G->R, B->G).

Since tidss's videoport starts streaming via crtc enable hooks, we need
cdns-dsi to be up and running before that. Now that the bridges are
pre_enabled before crtc is enabled, and post_disabled after crtc is
disabled, use the pre_enable and post_disable hooks to get cdns-dsi
ready and running before the tidss videoport to get pass the color shift
issues.

[0]: See section 12.6.5.7.3 "Start-up Procedure" in J721E SoC TRM
 TRM Link: http://www.ti.com/lit/pdf/spruil1

Signed-off-by: Aradhya Bhatia 
---
 .../gpu/drm/bridge/cadence/cdns-dsi-core.c| 32 +++
 1 file changed, 4 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index acbd4007b38c..a92814c3e0d6 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -655,8 +655,8 @@ cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge,
return MODE_OK;
 }
 
-static void cdns_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
-  struct drm_bridge_state 
*old_bridge_state)
+static void cdns_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
+   struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -676,15 +676,6 @@ static void cdns_dsi_bridge_atomic_disable(struct 
drm_bridge *bridge,
pm_runtime_put(dsi->base.dev);
 }
 
-static void cdns_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
-   struct drm_bridge_state 
*old_bridge_state)
-{
-   struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
-   struct cdns_dsi *dsi = input_to_dsi(input);
-
-   pm_runtime_put(dsi->base.dev);
-}
-
 static void cdns_dsi_hs_init(struct cdns_dsi *dsi)
 {
struct cdns_dsi_output *output = >output;
@@ -754,8 +745,8 @@ static void cdns_dsi_init_link(struct cdns_dsi *dsi)
dsi->link_initialized = true;
 }
 
-static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
- struct drm_bridge_state 
*old_bridge_state)
+static void cdns_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -906,19 +897,6 @@ static void cdns_dsi_bridge_atomic_enable(struct 
drm_bridge *bridge,
writel(tmp, dsi->regs + MCTL_MAIN_EN);
 }
 
-static void cdns_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
- struct drm_bridge_state 
*old_bridge_state)
-{
-   struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
-   struct cdns_dsi *dsi = input_to_dsi(input);
-
-   if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
-   return;
-
-   cdns_dsi_init_link(dsi);
-   cdns_dsi_hs_init(dsi);
-}
-
 static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
   struct drm_bridge_state 
*bridge_state,
   struct drm_crtc_state 
*crtc_state,
@@ -949,9 +927,7 @@ static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct 
drm_bridge *bridge,
 static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
.attach = cdns_dsi_bridge_attach,
.mode_valid = cdns_dsi_bridge_mode_valid,
-   .atomic_disable = cdns_dsi_bridge_atomic_disable,
.atomic_pre_enable = cdns_dsi_bridge_atomic_pre_enable,
-   .atomic_enable = cdns_dsi_bridge_atomic_enable,
.atomic_post_disable = cdns_dsi_bridge_atomic_post_disable,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
-- 
2.34.1



[PATCH v3 07/10] drm/mipi-dsi: Add helper to find input format

2024-06-17 Thread Aradhya Bhatia
Add a helper API that can be used by the DSI hosts to find the required
input bus format for the given output dsi pixel format.

Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/drm_mipi_dsi.c | 37 ++
 include/drm/drm_mipi_dsi.h |  1 +
 2 files changed, 38 insertions(+)

diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 795001bb7ff1..70ca6678fec2 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -36,6 +36,8 @@
 #include 
 #include 
 
+#include 
+
 #include 
 
 /**
@@ -810,6 +812,41 @@ ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, 
const void *params,
 }
 EXPORT_SYMBOL(mipi_dsi_generic_read);
 
+/**
+ * drm_mipi_dsi_get_input_bus_fmt() - Get the required MEDIA_BUS_FMT_* based
+ *   input pixel format for a given DSI output
+ *   pixel format
+ * @dsi_format: pixel format that a DSI host needs to output
+ *
+ * Various DSI hosts can use this function during their
+ * _bridge_funcs.atomic_get_input_bus_fmts operation to ascertain
+ * the MEDIA_BUS_FMT_* pixel format required as input.
+ *
+ * RETURNS:
+ * a 32-bit MEDIA_BUS_FMT_* value on success or 0 in case of failure.
+ */
+u32 drm_mipi_dsi_get_input_bus_fmt(enum mipi_dsi_pixel_format dsi_format)
+{
+   switch (dsi_format) {
+   case MIPI_DSI_FMT_RGB888:
+   return MEDIA_BUS_FMT_RGB888_1X24;
+
+   case MIPI_DSI_FMT_RGB666:
+   return MEDIA_BUS_FMT_RGB666_1X24_CPADHI;
+
+   case MIPI_DSI_FMT_RGB666_PACKED:
+   return MEDIA_BUS_FMT_RGB666_1X18;
+
+   case MIPI_DSI_FMT_RGB565:
+   return MEDIA_BUS_FMT_RGB565_1X16;
+
+   default:
+   /* Unsupported DSI Format */
+   return 0;
+   }
+}
+EXPORT_SYMBOL(drm_mipi_dsi_get_input_bus_fmt);
+
 /**
  * mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload
  * @dsi: DSI peripheral device
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 82b1cc434ea3..12ed7f51fe69 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -258,6 +258,7 @@ ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, 
const void *payload,
   size_t size);
 ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
  size_t num_params, void *data, size_t size);
+u32 drm_mipi_dsi_get_input_bus_fmt(enum mipi_dsi_pixel_format dsi_format);
 
 /**
  * enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode
-- 
2.34.1



[PATCH v3 08/10] drm/bridge: cdns-dsi: Support atomic bridge APIs

2024-06-17 Thread Aradhya Bhatia
Change the existing (and deprecated) bridge hooks, to the bridge
atomic APIs.

Add drm helpers for duplicate_state, destroy_state, and bridge_reset
bridge hooks.

Further add support for the input format negotiation hook.

Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Aradhya Bhatia 
---
 .../gpu/drm/bridge/cadence/cdns-dsi-core.c| 51 ---
 1 file changed, 43 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 87fdd07ca0bc..acbd4007b38c 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -655,7 +655,8 @@ cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge,
return MODE_OK;
 }
 
-static void cdns_dsi_bridge_disable(struct drm_bridge *bridge)
+static void cdns_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
+  struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -675,7 +676,8 @@ static void cdns_dsi_bridge_disable(struct drm_bridge 
*bridge)
pm_runtime_put(dsi->base.dev);
 }
 
-static void cdns_dsi_bridge_post_disable(struct drm_bridge *bridge)
+static void cdns_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
+   struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -752,7 +754,8 @@ static void cdns_dsi_init_link(struct cdns_dsi *dsi)
dsi->link_initialized = true;
 }
 
-static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
+static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -903,7 +906,8 @@ static void cdns_dsi_bridge_enable(struct drm_bridge 
*bridge)
writel(tmp, dsi->regs + MCTL_MAIN_EN);
 }
 
-static void cdns_dsi_bridge_pre_enable(struct drm_bridge *bridge)
+static void cdns_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -915,13 +919,44 @@ static void cdns_dsi_bridge_pre_enable(struct drm_bridge 
*bridge)
cdns_dsi_hs_init(dsi);
 }
 
+static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
+  struct drm_bridge_state 
*bridge_state,
+  struct drm_crtc_state 
*crtc_state,
+  struct drm_connector_state 
*conn_state,
+  u32 output_fmt,
+  unsigned int *num_input_fmts)
+{
+   struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
+   struct cdns_dsi *dsi = input_to_dsi(input);
+   struct cdns_dsi_output *output = >output;
+   u32 *input_fmts;
+
+   *num_input_fmts = 0;
+
+   input_fmts = kzalloc(sizeof(*input_fmts), GFP_KERNEL);
+   if (!input_fmts)
+   return NULL;
+
+   input_fmts[0] = drm_mipi_dsi_get_input_bus_fmt(output->dev->format);
+   if (!input_fmts[0])
+   return NULL;
+
+   *num_input_fmts = 1;
+
+   return input_fmts;
+}
+
 static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
.attach = cdns_dsi_bridge_attach,
.mode_valid = cdns_dsi_bridge_mode_valid,
-   .disable = cdns_dsi_bridge_disable,
-   .pre_enable = cdns_dsi_bridge_pre_enable,
-   .enable = cdns_dsi_bridge_enable,
-   .post_disable = cdns_dsi_bridge_post_disable,
+   .atomic_disable = cdns_dsi_bridge_atomic_disable,
+   .atomic_pre_enable = cdns_dsi_bridge_atomic_pre_enable,
+   .atomic_enable = cdns_dsi_bridge_atomic_enable,
+   .atomic_post_disable = cdns_dsi_bridge_atomic_post_disable,
+   .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+   .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+   .atomic_reset = drm_atomic_helper_bridge_reset,
+   .atomic_get_input_bus_fmts = cdns_dsi_bridge_get_input_bus_fmts,
 };
 
 static int cdns_dsi_attach(struct mipi_dsi_host *host,
-- 
2.34.1



[PATCH v3 09/10] drm/atomic-helper: Re-order bridge chain pre-enable and post-disable

2024-06-17 Thread Aradhya Bhatia
Move the bridge pre_enable call before crtc enable, and the bridge
post_disable call after the crtc disable.

The sequence of enable after this patch will look like:

bridge[n]_pre_enable
...
bridge[1]_pre_enable

crtc_enable
encoder_enable

bridge[1]_enable
...
bridge[n]__enable

and vice-versa for the bridge chain disable sequence.

The definition of bridge pre_enable hook says that,
"The display pipe (i.e. clocks and timing signals) feeding this bridge
will not yet be running when this callback is called".

Since CRTC is also a source feeding the bridge, it should not be enabled
before the bridges in the pipeline are pre_enabled. Fix that by
re-ordering the sequence of bridge pre_enable and bridge post_disable.

Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/drm_atomic_helper.c | 165 ++--
 include/drm/drm_atomic_helper.h |   7 ++
 2 files changed, 114 insertions(+), 58 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index fb97b51b38f1..e8ad08634f58 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -74,6 +74,7 @@
  * also shares the  drm_plane_helper_funcs function table with the plane
  * helpers.
  */
+
 static void
 drm_atomic_helper_plane_changed(struct drm_atomic_state *state,
struct drm_plane_state *old_plane_state,
@@ -1122,11 +1123,11 @@ crtc_needs_disable(struct drm_crtc_state *old_state,
 }
 
 static void
-disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
+disable_encoder_brige_chain(struct drm_device *dev, struct drm_atomic_state 
*old_state,
+   enum bridge_chain_operation_type op_type)
 {
struct drm_connector *connector;
struct drm_connector_state *old_conn_state, *new_conn_state;
-   struct drm_crtc *crtc;
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
int i;
 
@@ -1163,32 +1164,55 @@ disable_outputs(struct drm_device *dev, struct 
drm_atomic_state *old_state)
if (WARN_ON(!encoder))
continue;
 
-   funcs = encoder->helper_private;
-
-   drm_dbg_atomic(dev, "disabling [ENCODER:%d:%s]\n",
-  encoder->base.id, encoder->name);
-
/*
 * Each encoder has at most one connector (since we always steal
 * it away), so we won't call disable hooks twice.
 */
bridge = drm_bridge_chain_get_first_bridge(encoder);
-   drm_atomic_bridge_chain_disable(bridge, old_state);
 
-   /* Right function depends upon target state. */
-   if (funcs) {
-   if (funcs->atomic_disable)
-   funcs->atomic_disable(encoder, old_state);
-   else if (new_conn_state->crtc && funcs->prepare)
-   funcs->prepare(encoder);
-   else if (funcs->disable)
-   funcs->disable(encoder);
-   else if (funcs->dpms)
-   funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
-   }
+   switch (op_type) {
+   case DRM_ENCODER_BRIDGE_DISABLE:
+   funcs = encoder->helper_private;
+
+   drm_dbg_atomic(dev, "disabling [ENCODER:%d:%s]\n",
+  encoder->base.id, encoder->name);
+
+   drm_atomic_bridge_chain_disable(bridge, old_state);
+
+   /* Right function depends upon target state. */
+   if (funcs) {
+   if (funcs->atomic_disable)
+   funcs->atomic_disable(encoder, 
old_state);
+   else if (new_conn_state->crtc && funcs->prepare)
+   funcs->prepare(encoder);
+   else if (funcs->disable)
+   funcs->disable(encoder);
+   else if (funcs->dpms)
+   funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
+   }
+
+   break;
+
+   case DRM_BRIDGE_POST_DISABLE:
+   drm_atomic_bridge_chain_post_disable(bridge, old_state);
 
-   drm_atomic_bridge_chain_post_disable(bridge, old_state);
+   break;
+
+   default:
+   drm_err(dev, "Unrecognized Encoder/Bridge Operation 
(%d).\n", op_type);
+   break;
+   }
}
+}
+
+static void
+disable_outputs(struct drm_

[PATCH v3 04/10] drm/bridge: cdns-dsi: Fix the clock variable for mode_valid()

2024-06-17 Thread Aradhya Bhatia
Allow the D-Phy config checks to use mode->clock instead of
mode->crtc_clock during mode_valid checks, like everywhere else in the
driver.

Fixes: fced5a364dee ("drm/bridge: cdns: Convert to phy framework")
Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 371a3453970c..557b037bbc67 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -574,7 +574,7 @@ static int cdns_dsi_check_conf(struct cdns_dsi *dsi,
if (ret)
return ret;
 
-   phy_mipi_dphy_get_default_config(mode->crtc_clock * 1000,
+   phy_mipi_dphy_get_default_config((mode_valid_check ? mode->clock : 
mode->crtc_clock) * 1000,
 
mipi_dsi_pixel_format_to_bpp(output->dev->format),
 nlanes, phy_cfg);
 
-- 
2.34.1



[PATCH v3 02/10] drm/bridge: cdns-dsi: Fix the phy_initialized variable

2024-06-17 Thread Aradhya Bhatia
Update the Phy initialized state to "not initialized" when the driver
(and the hardware by extension) gets suspended. This will allow the Phy
to get initialized again after resume.

Fixes: e19233955d9e ("drm/bridge: Add Cadence DSI driver")
Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index b016f2ba06bb..42565e253b2d 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -1153,6 +1153,7 @@ static int __maybe_unused cdns_dsi_suspend(struct device 
*dev)
clk_disable_unprepare(dsi->dsi_p_clk);
reset_control_assert(dsi->dsi_p_rst);
dsi->link_initialized = false;
+   dsi->phy_initialized = false;
return 0;
 }
 
-- 
2.34.1



[PATCH v3 03/10] drm/bridge: cdns-dsi: Fix the link and phy init order

2024-06-17 Thread Aradhya Bhatia
The order of init of DSI link and DSI phy is wrong. The DSI link needs
to be configured before the DSI phy is getting configured. Otherwise,
the D-Phy is unable to lock in on the incoming PLL Reference clock[0].

Fix the order of inits.

[0]: See section 12.6.5.7.3 "Start-up Procedure" in J721E SoC TRM
 TRM Link: http://www.ti.com/lit/pdf/spruil1

Fixes: fced5a364dee ("drm/bridge: cdns: Convert to phy framework")
Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 42565e253b2d..371a3453970c 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -775,8 +775,8 @@ static void cdns_dsi_bridge_enable(struct drm_bridge 
*bridge)
 
WARN_ON_ONCE(cdns_dsi_check_conf(dsi, mode, _cfg, false));
 
-   cdns_dsi_hs_init(dsi);
cdns_dsi_init_link(dsi);
+   cdns_dsi_hs_init(dsi);
 
writel(HBP_LEN(dsi_cfg.hbp) | HSA_LEN(dsi_cfg.hsa),
   dsi->regs + VID_HSIZE1);
-- 
2.34.1



[PATCH v3 05/10] drm/bridge: cdns-dsi: Wait for Clk and Data Lanes to be ready

2024-06-17 Thread Aradhya Bhatia
Once the DSI Link and DSI Phy are initialized, the code needs to wait
for Clk and Data Lanes to be ready, before continuing configuration.
This is in accordance with the DSI Start-up procedure, found in the
Technical Reference Manual of Texas Instrument's J721E SoC[0] which
houses this DSI TX controller.

If the previous bridge (or crtc/encoder) are configured pre-maturely,
the input signal FIFO gets corrupt. This introduces a color-shift on the
display.

Allow the driver to wait for the clk and data lanes to get ready during
DSI enable.

[0]: See section 12.6.5.7.3 "Start-up Procedure" in J721E SoC TRM
 TRM Link: http://www.ti.com/lit/pdf/spruil1

Fixes: e19233955d9e ("drm/bridge: Add Cadence DSI driver")
Tested-by: Dominik Haller 
Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 557b037bbc67..05d2f4cc50da 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -761,7 +761,7 @@ static void cdns_dsi_bridge_enable(struct drm_bridge 
*bridge)
struct phy_configure_opts_mipi_dphy *phy_cfg = 
>phy_opts.mipi_dphy;
unsigned long tx_byte_period;
struct cdns_dsi_cfg dsi_cfg;
-   u32 tmp, reg_wakeup, div;
+   u32 tmp, reg_wakeup, div, status;
int nlanes;
 
if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
@@ -778,6 +778,17 @@ static void cdns_dsi_bridge_enable(struct drm_bridge 
*bridge)
cdns_dsi_init_link(dsi);
cdns_dsi_hs_init(dsi);
 
+   /*
+* Now that the DSI Link and DSI Phy are initialized,
+* wait for the CLK and Data Lanes to be ready.
+*/
+   tmp = CLK_LANE_RDY;
+   for (int i = 0; i < nlanes; i++)
+   tmp |= DATA_LANE_RDY(i);
+
+   WARN_ON_ONCE(readl_poll_timeout(dsi->regs + MCTL_MAIN_STS, status,
+   status & tmp, 100, 0));
+
writel(HBP_LEN(dsi_cfg.hbp) | HSA_LEN(dsi_cfg.hsa),
   dsi->regs + VID_HSIZE1);
writel(HFP_LEN(dsi_cfg.hfp) | HACT_LEN(dsi_cfg.hact),
-- 
2.34.1



[PATCH v3 00/10] drm/bridge: cdns-dsi: Fix the color-shift issue

2024-06-17 Thread Aradhya Bhatia
Hello all,

This series provides some crucial fixes and improvements for the Cadence's DSI
TX (cdns-dsi) controller found commonly in Texas Instruments' J7 family of SoCs
as well as in AM62P.

Along with that, this series aims to fix the color-shift issue that has been
going on with the DSI controller. This controller requires to be enabled before
the previous entity enables its stream[0]. It's a strict requirement which, if
not followed, causes the colors to "shift" on the display. The fix happens in
2 steps.

1. The bridge pre_enable calls have been shifted before the crtc_enable and
   the bridge post_disable calls have been shifted after the crtc_disable.
   This has been done as per the definition of bridge pre_enable.

   "The display pipe (i.e. clocks and timing signals) feeding this bridge
   will not yet be running when this callback is called".

   Since CRTC is also a source feeding the bridge, it should not be enabled
   before the bridges in the pipeline are pre_enabled.

   The sequence of enable after this patch will look like:

bridge[n]_pre_enable
...
bridge[1]_pre_enable

crtc_enable
encoder_enable

bridge[1]_enable
...
bridge[n]_enable

   and vice-versa for the bridge chain disable sequence.


2. The cdns-dsi enable / disable sequences have now been moved to pre_enable
   and post_disable sequences. This is the only way to have cdns-dsi drivers
   be up and ready before the previous entity is enables its streaming.

The DSI also spec requires the Clock and Data Lanes be ready before the DSI TX
enables its stream[0]. A patch has been added to make the code wait for that to
happen. Going ahead with further DSI (and DSS configuration), while the lanes
are not ready, has been found to be another reason for shift in colors.

All these patches have been tested on TI's vendor tree kernel with more devices,
but for the mainline, these patches have been tested with J721E based
BeagleboneAI64 along with a RaspberryPi 7" DSI panel. The extra patches can be
found in the "next_dsi-v2-tests" branch of my github fork[1] for anyone who
would like to test them.

Thanks,
Aradhya


[0]: Section 12.6.5.7.3: "Start-up Procedure" [For DSI TX controller]
 in TDA4VM Technical Reference Manual https://www.ti.com/lit/zip/spruil1

[1]: https://github.com/aradhya07/linux-ab/tree/next_dsi-v3-finals-test

Change Log:

  - Changes in v3:
- Reword the commit message for patch "drm/bridge: cdns-dsi: Fix OF node
  pointer".
- Add a new helper API to figure out DSI host input pixel format
  in patch "drm/mipi-dsi: Add helper to find input format".
- Use a common function for bridge pre-enable and enable, and bridge disable
  and post-disable, to avoid code duplication.
- Add T-b tag from Dominik Haller in patch 5/10. (Missed to add it in v2).
- Add R-b tag from Dmitry Baryshkov for patch 8/10.

  - Changes in v2:
- Drop patch "drm/tidss: Add CRTC mode_fixup"
- Split patch "drm/bridge: cdns-dsi: Fix minor bugs" into 4 separate ones
- Drop support for early_enable/late_disable APIs and instead re-order the
  pre_enable / post_disable APIs to be called before / after crtc_enable /
  crtc_disable.
- Drop support for early_enable/late_disable in cdns-dsi and use
  pre_enable/post_disable APIs instead to do bridge enable/disable.


Previous versions:

v1: https://lore.kernel.org/all/20240511153051.1355825-1-a-bhat...@ti.com/
v2: https://lore.kernel.org/all/20240530093621.1925863-1-a-bhat...@ti.com/

Aradhya Bhatia (10):
  drm/bridge: cdns-dsi: Fix OF node pointer
  drm/bridge: cdns-dsi: Fix the phy_initialized variable
  drm/bridge: cdns-dsi: Fix the link and phy init order
  drm/bridge: cdns-dsi: Fix the clock variable for mode_valid()
  drm/bridge: cdns-dsi: Wait for Clk and Data Lanes to be ready
  drm/bridge: cdns-dsi: Reset the DCS write FIFO
  drm/mipi-dsi: Add helper to find input format
  drm/bridge: cdns-dsi: Support atomic bridge APIs
  drm/atomic-helper: Re-order bridge chain pre-enable and post-disable
  drm/bridge: cdns-dsi: Use pre_enable/post_disable to enable/disable

 .../gpu/drm/bridge/cadence/cdns-dsi-core.c|  72 +---
 drivers/gpu/drm/drm_atomic_helper.c   | 165 --
 drivers/gpu/drm/drm_mipi_dsi.c|  37 
 include/drm/drm_atomic_helper.h   |   7 +
 include/drm/drm_mipi_dsi.h|   1 +
 5 files changed, 201 insertions(+), 81 deletions(-)


base-commit: 6906a84c482f098d31486df8dc98cead21cce2d0
-- 
2.34.1



[PATCH v3 01/10] drm/bridge: cdns-dsi: Fix OF node pointer

2024-06-17 Thread Aradhya Bhatia
Fix the OF node pointer passed to the of_drm_find_bridge() call to find
the next bridge in the display chain.

To find the next bridge in the pipeline, we need to pass "np" - the OF
node pointer of the next entity in the devicetree chain. Passing
"of_node" to of_drm_find_bridge will make the function try to fetch the
bridge for the cdns-dsi which is not what's required.

Fix that.

Fixes: e19233955d9e ("drm/bridge: Add Cadence DSI driver")
Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 7457d38622b0..b016f2ba06bb 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -952,7 +952,7 @@ static int cdns_dsi_attach(struct mipi_dsi_host *host,
bridge = drm_panel_bridge_add_typed(panel,
DRM_MODE_CONNECTOR_DSI);
} else {
-   bridge = of_drm_find_bridge(dev->dev.of_node);
+   bridge = of_drm_find_bridge(np);
if (!bridge)
bridge = ERR_PTR(-EINVAL);
}
-- 
2.34.1



Re: [PATCH v5 3/3] drm/bridge: sii902x: Add pixel clock check in atomic_check

2024-06-13 Thread Aradhya Bhatia



On 13-Jun-24 14:08, Jayesh Choudhary wrote:
> Check the pixel clock for the mode in atomic_check and ensure that
> it is within the range supported by the bridge.
> 
> Signed-off-by: Jayesh Choudhary 
> ---
>  drivers/gpu/drm/bridge/sii902x.c | 4 
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/gpu/drm/bridge/sii902x.c 
> b/drivers/gpu/drm/bridge/sii902x.c
> index 00a8c469f553..7f91b0db161e 100644
> --- a/drivers/gpu/drm/bridge/sii902x.c
> +++ b/drivers/gpu/drm/bridge/sii902x.c
> @@ -496,6 +496,10 @@ static int sii902x_bridge_atomic_check(struct drm_bridge 
> *bridge,
>  struct drm_crtc_state *crtc_state,
>  struct drm_connector_state *conn_state)
>  {
> + if (crtc_state->mode.clock < SII902X_MIN_PIXEL_CLOCK_KHZ ||
> + crtc_state->mode.clock > SII902X_MAX_PIXEL_CLOCK_KHZ)
> + return -EINVAL;
> +
>   /*
>* There might be flags negotiation supported in future but
>    * set the bus flags in atomic_check statically for now.

Reviewed-by: Aradhya Bhatia 

-- 
Regards
Aradhya


Re: [PATCH v5 1/3] drm/bridge: sii902x: Fix mode_valid hook

2024-06-13 Thread Aradhya Bhatia
Hi Jayesh,

Thanks for the patches!

On 13-Jun-24 14:08, Jayesh Choudhary wrote:
> Currently, mode_valid is defined only in drm_connector_helper_funcs.
> When the bridge is attached with the 'DRM_BRIDGE_ATTACH_NO_CONNECTOR'
> flag, the connector is not initialized, and so is the mode_valid
> hook under connector helper funcs.
> It also returns MODE_OK for all modes without actually checking the
> modes.
> So move the mode_valid hook to drm_bridge_funcs with proper clock
> checks for maximum and minimum pixel clock supported by the bridge.
> 
> Signed-off-by: Jayesh Choudhary 
> Reviewed-by: Dmitry Baryshkov 
> Acked-by: Sui Jingfeng 
> ---
>  drivers/gpu/drm/bridge/sii902x.c | 32 +++-
>  1 file changed, 23 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/sii902x.c 
> b/drivers/gpu/drm/bridge/sii902x.c
> index 2fbeda9025bf..6a6055a4ccf9 100644
> --- a/drivers/gpu/drm/bridge/sii902x.c
> +++ b/drivers/gpu/drm/bridge/sii902x.c
> @@ -163,6 +163,14 @@
>  
>  #define SII902X_AUDIO_PORT_INDEX 3
>  
> +/*
> + * The maximum resolution supported by the HDMI bridge is 1080p@60Hz
> + * and 1920x1200 requiring a pixel clock of 165MHz and the minimum
> + * resolution supported is 480p@60Hz requiring a pixel clock of 25MHz
> + */
> +#define SII902X_MIN_PIXEL_CLOCK_KHZ  25000
> +#define SII902X_MAX_PIXEL_CLOCK_KHZ  165000
> +
>  struct sii902x {
>   struct i2c_client *i2c;
>   struct regmap *regmap;
> @@ -310,17 +318,8 @@ static int sii902x_get_modes(struct drm_connector 
> *connector)
>   return num;
>  }
>  
> -static enum drm_mode_status sii902x_mode_valid(struct drm_connector 
> *connector,
> -struct drm_display_mode *mode)
> -{
> - /* TODO: check mode */
> -
> - return MODE_OK;
> -}
> -
>  static const struct drm_connector_helper_funcs 
> sii902x_connector_helper_funcs = {
>   .get_modes = sii902x_get_modes,
> - .mode_valid = sii902x_mode_valid,
>  };
>  
>  static void sii902x_bridge_disable(struct drm_bridge *bridge)
> @@ -504,6 +503,20 @@ static int sii902x_bridge_atomic_check(struct drm_bridge 
> *bridge,
>   return 0;
>  }
>  
> +static enum drm_mode_status
> +sii902x_bridge_mode_valid(struct drm_bridge *bridge,
> +   const struct drm_display_info *info,
> +   const struct drm_display_mode *mode)
> +{
> + if (mode->clock < SII902X_MIN_PIXEL_CLOCK_KHZ)
> + return MODE_CLOCK_LOW;
> +
> + if (mode->clock > SII902X_MAX_PIXEL_CLOCK_KHZ)
> + return MODE_CLOCK_HIGH;
> +
> + return MODE_OK;
> +}
> +
>  static const struct drm_bridge_funcs sii902x_bridge_funcs = {
>   .attach = sii902x_bridge_attach,
>   .mode_set = sii902x_bridge_mode_set,
> @@ -516,6 +529,7 @@ static const struct drm_bridge_funcs sii902x_bridge_funcs 
> = {
>   .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
>   .atomic_get_input_bus_fmts = sii902x_bridge_atomic_get_input_bus_fmts,
>   .atomic_check = sii902x_bridge_atomic_check,
> + .mode_valid = sii902x_bridge_mode_valid,
>  };
>  
>  static int sii902x_mute(struct sii902x *sii902x, bool mute)

Reviewed-by: Aradhya Bhatia 

-- 
Regards
Aradhya


Re: [PATCH v5 2/3] drm/bridge: sii902x: Support atomic bridge APIs

2024-06-13 Thread Aradhya Bhatia



On 13-Jun-24 14:08, Jayesh Choudhary wrote:
> Change exisitig enable() and disable() bridge hooks to their atomic
> counterparts as the former hooks are deprecated.
> 
> Signed-off-by: Jayesh Choudhary 
> ---
>  drivers/gpu/drm/bridge/sii902x.c | 10 ++
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/sii902x.c 
> b/drivers/gpu/drm/bridge/sii902x.c
> index 6a6055a4ccf9..00a8c469f553 100644
> --- a/drivers/gpu/drm/bridge/sii902x.c
> +++ b/drivers/gpu/drm/bridge/sii902x.c
> @@ -322,7 +322,8 @@ static const struct drm_connector_helper_funcs 
> sii902x_connector_helper_funcs =
>   .get_modes = sii902x_get_modes,
>  };
>  
> -static void sii902x_bridge_disable(struct drm_bridge *bridge)
> +static void sii902x_bridge_atomic_disable(struct drm_bridge *bridge,
> +   struct drm_bridge_state 
> *old_bridge_state)
>  {
>   struct sii902x *sii902x = bridge_to_sii902x(bridge);
>  
> @@ -335,7 +336,8 @@ static void sii902x_bridge_disable(struct drm_bridge 
> *bridge)
>   mutex_unlock(>mutex);
>  }
>  
> -static void sii902x_bridge_enable(struct drm_bridge *bridge)
> +static void sii902x_bridge_atomic_enable(struct drm_bridge *bridge,
> +  struct drm_bridge_state 
> *old_bridge_state)
>  {
>   struct sii902x *sii902x = bridge_to_sii902x(bridge);
>  
> @@ -520,8 +522,8 @@ sii902x_bridge_mode_valid(struct drm_bridge *bridge,
>  static const struct drm_bridge_funcs sii902x_bridge_funcs = {
>   .attach = sii902x_bridge_attach,
>   .mode_set = sii902x_bridge_mode_set,
> - .disable = sii902x_bridge_disable,
> - .enable = sii902x_bridge_enable,
> + .atomic_disable = sii902x_bridge_atomic_disable,
> + .atomic_enable = sii902x_bridge_atomic_enable,
>   .detect = sii902x_bridge_detect,
>   .edid_read = sii902x_bridge_edid_read,
>   .atomic_reset = drm_atomic_helper_bridge_reset,

Reviewed-by: Aradhya Bhatia 

-- 
Regards
Aradhya


Re: [PATCH v2 7/9] drm/bridge: cdns-dsi: Support atomic bridge APIs

2024-06-10 Thread Aradhya Bhatia
Hi Dmitry,

Thank you for reviewing the patches.

On 31/05/24 04:51, Dmitry Baryshkov wrote:
> On Thu, May 30, 2024 at 03:06:19PM +0530, Aradhya Bhatia wrote:
>> Change the existing (and deprecated) bridge hooks, to the bridge
>> atomic APIs.
>>
>> Add drm helpers for duplicate_state, destroy_state, and bridge_reset
>> bridge hooks.
>>
>> Further add support for the input format negotiation hook.
>>
>> Signed-off-by: Aradhya Bhatia 
>> ---
>>  .../gpu/drm/bridge/cadence/cdns-dsi-core.c| 70 ---
>>  1 file changed, 62 insertions(+), 8 deletions(-)
> 
> Reviewed-by: Dmitry Baryshkov 
> 
> Minor nit below.
> 
>>
>> @@ -915,13 +920,62 @@ static void cdns_dsi_bridge_pre_enable(struct 
>> drm_bridge *bridge)
>>  cdns_dsi_hs_init(dsi);
>>  }
>>  
>> +static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
>> +   struct drm_bridge_state 
>> *bridge_state,
>> +   struct drm_crtc_state 
>> *crtc_state,
>> +   struct drm_connector_state 
>> *conn_state,
>> +   u32 output_fmt,
>> +   unsigned int *num_input_fmts)
>> +{
> 
> This code below looks pretty generic. Would be logical to extract it to
> a helper and allow it to be used by other DSI host bridges?

I agree, it would indeed make sense.

I just tried to make a helper function that could directly be passed to
the drm_bridge_funcs list - like we do with
"drm_atomic_helper_bridge_propagate_bus_fmt". This would have been ideal
in my opinion.

But, that doesn't seem possible today. The parameter "output_fmt"
doesn't describe any of the DSI pixel formats from "enum
mipi_dsi_pixel_format", which is what's required to ascertain the input
bus format for dsi hosts. Neither do the drm_bridge{_state} help with
that.

For now, I am thinking to just add a common function that accepts the
dsi bus output format and returns the corresponding input bus format.
With this, every dsi host will still need to implement their own
get_input_fmt hook and call that function.

If you had something else in mind, do let me know! =)

Regards
Aradhya

> 
>> +struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
>> +struct cdns_dsi *dsi = input_to_dsi(input);
>> +struct cdns_dsi_output *output = >output;
>> +u32 *input_fmts;
>> +
>> +*num_input_fmts = 0;
>> +
>> +input_fmts = kzalloc(sizeof(*input_fmts), GFP_KERNEL);
>> +if (!input_fmts)
>> +return NULL;
>> +
>> +switch (output->dev->format) {
>> +case MIPI_DSI_FMT_RGB888:
>> +input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;
>> +break;
>> +
>> +case MIPI_DSI_FMT_RGB666:
>> +input_fmts[0] = MEDIA_BUS_FMT_RGB666_1X24_CPADHI;
>> +break;
>> +
>> +case MIPI_DSI_FMT_RGB666_PACKED:
>> +input_fmts[0] = MEDIA_BUS_FMT_RGB666_1X18;
>> +break;
>> +
>> +case MIPI_DSI_FMT_RGB565:
>> +input_fmts[0] = MEDIA_BUS_FMT_RGB565_1X16;
>> +break;
>> +
>> +default:
>> +/* Unsupported DSI Format */
>> +return NULL;
>> +}
>> +
>> +*num_input_fmts = 1;
>> +
>> +return input_fmts;
>> +}
>> +
> 


Re: [PATCH 6/7] drm/bridge: Introduce early_enable and late disable

2024-05-30 Thread Aradhya Bhatia
Hi Maxime,

On 28/05/24 17:13, Maxime Ripard wrote:
> On Fri, May 24, 2024 at 04:38:13PM GMT, Aradhya Bhatia wrote:
>> Hi Maxime,
>>
>> On 21/05/24 18:45, Maxime Ripard wrote:
>>> Hi,
>>>
>>> On Thu, May 16, 2024 at 03:10:15PM GMT, Aradhya Bhatia wrote:
>>>>>>  /**
>>>>>>   * @pre_enable:
>>>>>>   *
>>>>>> @@ -285,6 +319,26 @@ struct drm_bridge_funcs {
>>>>>>   */
>>>>>>  void (*enable)(struct drm_bridge *bridge);
>>>>>>  
>>>>>> +/**
>>>>>> + * @atomic_early_enable:
>>>>>> + *
>>>>>> + * This callback should enable the bridge. It is called right 
>>>>>> before
>>>>>> + * the preceding element in the display pipe is enabled. If the
>>>>>> + * preceding element is a bridge this means it's called before 
>>>>>> that
>>>>>> + * bridge's @atomic_early_enable. If the preceding element is a
>>>>>> + * _crtc it's called right before the crtc's
>>>>>> + * _crtc_helper_funcs.atomic_enable hook.
>>>>>> + *
>>>>>> + * The display pipe (i.e. clocks and timing signals) feeding 
>>>>>> this bridge
>>>>>> + * will not yet be running when this callback is called. The 
>>>>>> bridge can
>>>>>> + * enable the display link feeding the next bridge in the chain 
>>>>>> (if
>>>>>> + * there is one) when this callback is called.
>>>>>> + *
>>>>>> + * The @early_enable callback is optional.
>>>>>> + */
>>>>>> +void (*atomic_early_enable)(struct drm_bridge *bridge,
>>>>>> +struct drm_bridge_state 
>>>>>> *old_bridge_state);
>>>>>> +
>>>>>>  /**
>>>>>>   * @atomic_pre_enable:
>>>>>>   *
>>>>>> @@ -361,6 +415,21 @@ struct drm_bridge_funcs {
>>>>>>  void (*atomic_post_disable)(struct drm_bridge *bridge,
>>>>>>  struct drm_bridge_state 
>>>>>> *old_bridge_state);
>>>>>>  
>>>>>> +/**
>>>>>> + * @atomic_late_disable:
>>>>>> + *
>>>>>> + * This callback should disable the bridge. It is called right 
>>>>>> after the
>>>>>> + * preceding element in the display pipe is disabled. If the 
>>>>>> preceding
>>>>>> + * element is a bridge this means it's called after that 
>>>>>> bridge's
>>>>>> + * @atomic_late_disable. If the preceding element is a 
>>>>>> _crtc it's
>>>>>> + * called right after the crtc's 
>>>>>> _crtc_helper_funcs.atomic_disable
>>>>>> + * hook.
>>>>>> + *
>>>>>> + * The @atomic_late_disable callback is optional.
>>>>>> + */
>>>>>> +void (*atomic_late_disable)(struct drm_bridge *bridge,
>>>>>> +struct drm_bridge_state 
>>>>>> *old_bridge_state);
>>>>>> +
>>>>>
>>>>> But more importantly, I don't quite get the use case you're trying to
>>>>> solve here.
>>>>>
>>>>> If I got the rest of your series, the Cadence DSI bridge needs to be
>>>>> powered up before its source is started. You can't use atomic_enable or
>>>>> atomic_pre_enable because it would start the source before the DSI
>>>>> bridge. Is that correct?
>>>>>
>>>>
>>>> That's right. I cannot use bridge_atomic_pre_enable /
>>>> bridge_atomic_enable here. But that's because my source is CRTC, which
>>>> gets enabled via crtc_atomic_enable.
>>>>
>>>>
>>>>> If it is, then how is it different from what
>>>>> drm_atomic_bridge_chain_pre_enable is doing? The assumption there is
>>>>> that it starts enabling bridges last to first, to it should be enabled
&

Re: [PATCH 1/7] drm/tidss: Add CRTC mode_fixup

2024-05-30 Thread Aradhya Bhatia
Hi Maxime,

On 21/05/24 18:48, Maxime Ripard wrote:
> On Thu, May 16, 2024 at 04:33:40PM GMT, Aradhya Bhatia wrote:
>> Hi Maxime,
>>
>> Thank you for reviewing the patches.
>>
>> On 16/05/24 13:40, Maxime Ripard wrote:
>>> Hi,
>>>
>>> On Sat, May 11, 2024 at 09:00:45PM +0530, Aradhya Bhatia wrote:
>>>> Add support for mode_fixup for the tidss CRTC.
>>>>
>>>> Some bridges like the cdns-dsi consume the crtc_* timing parameters for
>>>> programming the blanking values. Allow for the normal timing parameters
>>>> to get copied to crtc_* timing params.
>>>>
>>>> Signed-off-by: Aradhya Bhatia 
>>>> ---
>>>>  drivers/gpu/drm/tidss/tidss_crtc.c | 11 +++
>>>>  1 file changed, 11 insertions(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/tidss/tidss_crtc.c 
>>>> b/drivers/gpu/drm/tidss/tidss_crtc.c
>>>> index 94f8e3178df5..797ef53d9ad2 100644
>>>> --- a/drivers/gpu/drm/tidss/tidss_crtc.c
>>>> +++ b/drivers/gpu/drm/tidss/tidss_crtc.c
>>>> @@ -309,12 +309,23 @@ enum drm_mode_status tidss_crtc_mode_valid(struct 
>>>> drm_crtc *crtc,
>>>>return dispc_vp_mode_valid(tidss->dispc, tcrtc->hw_videoport, mode);
>>>>  }
>>>>  
>>>> +static
>>>> +bool tidss_crtc_mode_fixup(struct drm_crtc *crtc,
>>>> + const struct drm_display_mode *mode,
>>>> + struct drm_display_mode *adjusted_mode)
>>>> +{
>>>> +  drm_mode_set_crtcinfo(adjusted_mode, 0);
>>>> +
>>>> +  return true;
>>>> +}
>>>> +
>>>>  static const struct drm_crtc_helper_funcs tidss_crtc_helper_funcs = {
>>>>.atomic_check = tidss_crtc_atomic_check,
>>>>.atomic_flush = tidss_crtc_atomic_flush,
>>>>.atomic_enable = tidss_crtc_atomic_enable,
>>>>.atomic_disable = tidss_crtc_atomic_disable,
>>>>  
>>>> +  .mode_fixup = tidss_crtc_mode_fixup,
>>>>.mode_valid = tidss_crtc_mode_valid,
>>>>  };
>>>
>>> mode_fixup is deprecated for atomic drivers, so the solution must be
>>> different there.
>>>
>>> It's also not clear to me how it could change anything there:
>>> drm_mode_set_crtcinfo with no flags will make crtc_* field exactly
>>> identical to their !crtc counterparts.
>>>
>>
>> I checked the flag options. There isn't any flag required. The only
>> reason to add this call is because cdns-dsi strictly requires the crtc_*
>> fields to be populated during the bridge enable.
>>
>> Secondly, if mode_fixup is deprecated, I think the crtc_atomic_check
>> would be the next best place to add this call.
> 
> That would be better, yes, but we shouldn't even have to do that in the
> first place. AFAIK all the path that create a drm_display_mode will call
> drm_mode_set_crtcinfo on it to fill those fields. So if they are missing
> somewhere, that's what the actual bug is, not something we should work
> around of at the driver level.
> 

You are right. This patch isn't required at all. The fix around the
mode->crtc_clock usage in one place in the cdns-dsi driver makes this
patch unnecessary. The DRM core does duplicate the timing parameters at
a later stage for the cdns-dsi bridge_enable to consume.

Dropped this patch in v2. Thanks!

Regards
Aradhya



[PATCH v2 6/9] drm/bridge: cdns-dsi: Reset the DCS write FIFO

2024-05-30 Thread Aradhya Bhatia
Allow the DCS Write FIFO in the cdns-dsi controller to reset before any
DCS packet is transmitted to the DSI sink device.

The DCS FIFO reset is optional. Not all panels require it. But at
least one of the DSI based panel that uses Ilitek ILI9881C (DSI to DPI
bridge) doesn't work with without this reset.

Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 05d2f4cc50da..87fdd07ca0bc 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -1037,6 +1037,9 @@ static ssize_t cdns_dsi_transfer(struct mipi_dsi_host 
*host,
 
cdns_dsi_init_link(dsi);
 
+   /* Reset the DCS Write FIFO */
+   writel(0x00, dsi->regs + DIRECT_CMD_FIFO_RST);
+
ret = mipi_dsi_create_packet(, msg);
if (ret)
goto out;
-- 
2.34.1



[PATCH v2 9/9] drm/bridge: cdns-dsi: Use pre_enable/post_disable to enable/disable

2024-05-30 Thread Aradhya Bhatia
The cdns-dsi controller requires that it be turned on completely before
the input DPI's source has begun streaming[0]. Not having that, allows
for a small window before cdns-dsi enable and after cdns-dsi disable
where the previous entity (in this case tidss's videoport) to continue
streaming DPI video signals. This small window where cdns-dsi is
disabled but is still receiving signals causes the input FIFO of
cdns-dsi to get corrupted. This causes the colors to shift on the output
display. The colors can either shift by one color component (R->G, G->B,
B->R), or by two color components (R->B, G->R, B->G).

Since tidss's videoport starts streaming via crtc enable hooks, we need
cdns-dsi to be up and running before that. Now that the bridges are
pre_enabled before crtc is enabled, and post_disabled after crtc is
disabled, use the pre_enable and post_disable hooks to get cdns-dsi
ready and running before the tidss videoport to get pass the color shift
issues.

[0]: See section 12.6.5.7.3 "Start-up Procedure" in J721E SoC TRM
 TRM Link: http://www.ti.com/lit/pdf/spruil1

Signed-off-by: Aradhya Bhatia 
---
 .../gpu/drm/bridge/cadence/cdns-dsi-core.c| 32 +++
 1 file changed, 4 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 6a2223ecff7d..1eedc7053ef8 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -656,8 +656,8 @@ cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge,
return MODE_OK;
 }
 
-static void cdns_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
-  struct drm_bridge_state 
*old_bridge_state)
+static void cdns_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
+   struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -677,15 +677,6 @@ static void cdns_dsi_bridge_atomic_disable(struct 
drm_bridge *bridge,
pm_runtime_put(dsi->base.dev);
 }
 
-static void cdns_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
-   struct drm_bridge_state 
*old_bridge_state)
-{
-   struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
-   struct cdns_dsi *dsi = input_to_dsi(input);
-
-   pm_runtime_put(dsi->base.dev);
-}
-
 static void cdns_dsi_hs_init(struct cdns_dsi *dsi)
 {
struct cdns_dsi_output *output = >output;
@@ -755,8 +746,8 @@ static void cdns_dsi_init_link(struct cdns_dsi *dsi)
dsi->link_initialized = true;
 }
 
-static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
- struct drm_bridge_state 
*old_bridge_state)
+static void cdns_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -907,19 +898,6 @@ static void cdns_dsi_bridge_atomic_enable(struct 
drm_bridge *bridge,
writel(tmp, dsi->regs + MCTL_MAIN_EN);
 }
 
-static void cdns_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
- struct drm_bridge_state 
*old_bridge_state)
-{
-   struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
-   struct cdns_dsi *dsi = input_to_dsi(input);
-
-   if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
-   return;
-
-   cdns_dsi_init_link(dsi);
-   cdns_dsi_hs_init(dsi);
-}
-
 static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
   struct drm_bridge_state 
*bridge_state,
   struct drm_crtc_state 
*crtc_state,
@@ -968,9 +946,7 @@ static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct 
drm_bridge *bridge,
 static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
.attach = cdns_dsi_bridge_attach,
.mode_valid = cdns_dsi_bridge_mode_valid,
-   .atomic_disable = cdns_dsi_bridge_atomic_disable,
.atomic_pre_enable = cdns_dsi_bridge_atomic_pre_enable,
-   .atomic_enable = cdns_dsi_bridge_atomic_enable,
.atomic_post_disable = cdns_dsi_bridge_atomic_post_disable,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
-- 
2.34.1



[PATCH v2 8/9] drm/atomic-helper: Re-order bridge chain pre-enable and post-disable

2024-05-30 Thread Aradhya Bhatia
Move the bridge pre_enable call before crtc enable, and the bridge
post_disable call after the crtc disable.

The sequence of enable after this patch will look like:

bridge[n]_pre_enable
...
bridge[1]_pre_enable

crtc_enable
encoder_enable

bridge[1]_enable
...
bridge[n]__enable

and vice-versa for the bridge chain disable sequence.

The definition of bridge pre_enable hook says that,
"The display pipe (i.e. clocks and timing signals) feeding this bridge
will not yet be running when this callback is called".

Since CRTC is also a source feeding the bridge, it should not be enabled
before the bridges in the pipeline are pre_enabled. Fix that by
re-ordering the sequence of bridge pre_enable and bridge post_disable.

Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/drm_atomic_helper.c | 70 +++--
 1 file changed, 67 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index fb97b51b38f1..02e093950218 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1186,8 +1186,6 @@ disable_outputs(struct drm_device *dev, struct 
drm_atomic_state *old_state)
else if (funcs->dpms)
funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
}
-
-   drm_atomic_bridge_chain_post_disable(bridge, old_state);
}
 
for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, 
new_crtc_state, i) {
@@ -1234,6 +1232,49 @@ disable_outputs(struct drm_device *dev, struct 
drm_atomic_state *old_state)
if (ret == 0)
drm_crtc_vblank_put(crtc);
}
+
+   for_each_oldnew_connector_in_state(old_state, connector, old_conn_state,
+  new_conn_state, i) {
+   struct drm_encoder *encoder;
+   struct drm_bridge *bridge;
+
+   /*
+* Shut down everything that's in the changeset and currently
+* still on. So need to check the old, saved state.
+*/
+   if (!old_conn_state->crtc)
+   continue;
+
+   old_crtc_state = drm_atomic_get_old_crtc_state(old_state, 
old_conn_state->crtc);
+
+   if (new_conn_state->crtc)
+   new_crtc_state = 
drm_atomic_get_new_crtc_state(old_state,
+  
new_conn_state->crtc);
+   else
+   new_crtc_state = NULL;
+
+   if (!crtc_needs_disable(old_crtc_state, new_crtc_state) ||
+   !drm_atomic_crtc_needs_modeset(old_conn_state->crtc->state))
+   continue;
+
+   encoder = old_conn_state->best_encoder;
+
+   /* We shouldn't get this far if we didn't previously have
+* an encoder.. but WARN_ON() rather than explode.
+*/
+   if (WARN_ON(!encoder))
+   continue;
+
+   drm_dbg_atomic(dev, "disabling [ENCODER:%d:%s]\n",
+  encoder->base.id, encoder->name);
+
+   /*
+* Each encoder has at most one connector (since we always steal
+* it away), so we won't call disable hooks twice.
+*/
+   bridge = drm_bridge_chain_get_first_bridge(encoder);
+   drm_atomic_bridge_chain_post_disable(bridge, old_state);
+   }
 }
 
 /**
@@ -1469,6 +1510,30 @@ void drm_atomic_helper_commit_modeset_enables(struct 
drm_device *dev,
struct drm_connector_state *new_conn_state;
int i;
 
+   for_each_new_connector_in_state(old_state, connector, new_conn_state, 
i) {
+   struct drm_encoder *encoder;
+   struct drm_bridge *bridge;
+
+   if (!new_conn_state->best_encoder)
+   continue;
+
+   if (!new_conn_state->crtc->state->active ||
+   !drm_atomic_crtc_needs_modeset(new_conn_state->crtc->state))
+   continue;
+
+   encoder = new_conn_state->best_encoder;
+
+   drm_dbg_atomic(dev, "enabling [ENCODER:%d:%s]\n",
+  encoder->base.id, encoder->name);
+
+   /*
+* Each encoder has at most one connector (since we always steal
+* it away), so we won't call enable hooks twice.
+*/
+   bridge = drm_bridge_chain_get_first_bridge(encoder);
+   drm_atomic_bridge_chain_pre_enable(bridge, old_state);
+   }
+
for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, 
new_crtc_state, i) {
const struct drm_crtc_helper_funcs *funcs

[PATCH v2 7/9] drm/bridge: cdns-dsi: Support atomic bridge APIs

2024-05-30 Thread Aradhya Bhatia
Change the existing (and deprecated) bridge hooks, to the bridge
atomic APIs.

Add drm helpers for duplicate_state, destroy_state, and bridge_reset
bridge hooks.

Further add support for the input format negotiation hook.

Signed-off-by: Aradhya Bhatia 
---
 .../gpu/drm/bridge/cadence/cdns-dsi-core.c| 70 ---
 1 file changed, 62 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 87fdd07ca0bc..6a2223ecff7d 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -655,7 +656,8 @@ cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge,
return MODE_OK;
 }
 
-static void cdns_dsi_bridge_disable(struct drm_bridge *bridge)
+static void cdns_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
+  struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -675,7 +677,8 @@ static void cdns_dsi_bridge_disable(struct drm_bridge 
*bridge)
pm_runtime_put(dsi->base.dev);
 }
 
-static void cdns_dsi_bridge_post_disable(struct drm_bridge *bridge)
+static void cdns_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
+   struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -752,7 +755,8 @@ static void cdns_dsi_init_link(struct cdns_dsi *dsi)
dsi->link_initialized = true;
 }
 
-static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
+static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -903,7 +907,8 @@ static void cdns_dsi_bridge_enable(struct drm_bridge 
*bridge)
writel(tmp, dsi->regs + MCTL_MAIN_EN);
 }
 
-static void cdns_dsi_bridge_pre_enable(struct drm_bridge *bridge)
+static void cdns_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -915,13 +920,62 @@ static void cdns_dsi_bridge_pre_enable(struct drm_bridge 
*bridge)
cdns_dsi_hs_init(dsi);
 }
 
+static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
+  struct drm_bridge_state 
*bridge_state,
+  struct drm_crtc_state 
*crtc_state,
+  struct drm_connector_state 
*conn_state,
+  u32 output_fmt,
+  unsigned int *num_input_fmts)
+{
+   struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
+   struct cdns_dsi *dsi = input_to_dsi(input);
+   struct cdns_dsi_output *output = >output;
+   u32 *input_fmts;
+
+   *num_input_fmts = 0;
+
+   input_fmts = kzalloc(sizeof(*input_fmts), GFP_KERNEL);
+   if (!input_fmts)
+   return NULL;
+
+   switch (output->dev->format) {
+   case MIPI_DSI_FMT_RGB888:
+   input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;
+   break;
+
+   case MIPI_DSI_FMT_RGB666:
+   input_fmts[0] = MEDIA_BUS_FMT_RGB666_1X24_CPADHI;
+   break;
+
+   case MIPI_DSI_FMT_RGB666_PACKED:
+   input_fmts[0] = MEDIA_BUS_FMT_RGB666_1X18;
+   break;
+
+   case MIPI_DSI_FMT_RGB565:
+   input_fmts[0] = MEDIA_BUS_FMT_RGB565_1X16;
+   break;
+
+   default:
+   /* Unsupported DSI Format */
+   return NULL;
+   }
+
+   *num_input_fmts = 1;
+
+   return input_fmts;
+}
+
 static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
.attach = cdns_dsi_bridge_attach,
.mode_valid = cdns_dsi_bridge_mode_valid,
-   .disable = cdns_dsi_bridge_disable,
-   .pre_enable = cdns_dsi_bridge_pre_enable,
-   .enable = cdns_dsi_bridge_enable,
-   .post_disable = cdns_dsi_bridge_post_disable,
+   .atomic_disable = cdns_dsi_bridge_atomic_disable,
+   .atomic_pre_enable = cdns_dsi_bridge_atomic_pre_enable,
+   .atomic_enable = cdns_dsi_bridge_atomic_enable,
+   .atomic_post_disable = cdns_dsi_bridge_atomic_post_disable,
+   .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+   .at

[PATCH v2 4/9] drm/bridge: cdns-dsi: Fix the clock variable for mode_valid()

2024-05-30 Thread Aradhya Bhatia
Allow the D-Phy config checks to use mode->clock instead of
mode->crtc_clock during mode_valid checks, like everywhere else in the
driver.

Fixes: fced5a364dee ("drm/bridge: cdns: Convert to phy framework")
Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 371a3453970c..557b037bbc67 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -574,7 +574,7 @@ static int cdns_dsi_check_conf(struct cdns_dsi *dsi,
if (ret)
return ret;
 
-   phy_mipi_dphy_get_default_config(mode->crtc_clock * 1000,
+   phy_mipi_dphy_get_default_config((mode_valid_check ? mode->clock : 
mode->crtc_clock) * 1000,
 
mipi_dsi_pixel_format_to_bpp(output->dev->format),
 nlanes, phy_cfg);
 
-- 
2.34.1



[PATCH v2 5/9] drm/bridge: cdns-dsi: Wait for Clk and Data Lanes to be ready

2024-05-30 Thread Aradhya Bhatia
Once the DSI Link and DSI Phy are initialized, the code needs to wait
for Clk and Data Lanes to be ready, before continuing configuration.
This is in accordance with the DSI Start-up procedure, found in the
Technical Reference Manual of Texas Instrument's J721E SoC[0] which
houses this DSI TX controller.

If the previous bridge (or crtc/encoder) are configured pre-maturely,
the input signal FIFO gets corrupt. This introduces a color-shift on the
display.

Allow the driver to wait for the clk and data lanes to get ready during
DSI enable.

[0]: See section 12.6.5.7.3 "Start-up Procedure" in J721E SoC TRM
 TRM Link: http://www.ti.com/lit/pdf/spruil1

Fixes: e19233955d9e ("drm/bridge: Add Cadence DSI driver")
Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 557b037bbc67..05d2f4cc50da 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -761,7 +761,7 @@ static void cdns_dsi_bridge_enable(struct drm_bridge 
*bridge)
struct phy_configure_opts_mipi_dphy *phy_cfg = 
>phy_opts.mipi_dphy;
unsigned long tx_byte_period;
struct cdns_dsi_cfg dsi_cfg;
-   u32 tmp, reg_wakeup, div;
+   u32 tmp, reg_wakeup, div, status;
int nlanes;
 
if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
@@ -778,6 +778,17 @@ static void cdns_dsi_bridge_enable(struct drm_bridge 
*bridge)
cdns_dsi_init_link(dsi);
cdns_dsi_hs_init(dsi);
 
+   /*
+* Now that the DSI Link and DSI Phy are initialized,
+* wait for the CLK and Data Lanes to be ready.
+*/
+   tmp = CLK_LANE_RDY;
+   for (int i = 0; i < nlanes; i++)
+   tmp |= DATA_LANE_RDY(i);
+
+   WARN_ON_ONCE(readl_poll_timeout(dsi->regs + MCTL_MAIN_STS, status,
+   status & tmp, 100, 0));
+
writel(HBP_LEN(dsi_cfg.hbp) | HSA_LEN(dsi_cfg.hsa),
   dsi->regs + VID_HSIZE1);
writel(HFP_LEN(dsi_cfg.hfp) | HACT_LEN(dsi_cfg.hact),
-- 
2.34.1



[PATCH v2 1/9] drm/bridge: cdns-dsi: Fix OF node pointer

2024-05-30 Thread Aradhya Bhatia
Fix the OF node pointer passed to the of_drm_find_bridge() call to find
the next bridge in the display chain.

Fixes: e19233955d9e ("drm/bridge: Add Cadence DSI driver")
Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 7457d38622b0..b016f2ba06bb 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -952,7 +952,7 @@ static int cdns_dsi_attach(struct mipi_dsi_host *host,
bridge = drm_panel_bridge_add_typed(panel,
DRM_MODE_CONNECTOR_DSI);
} else {
-   bridge = of_drm_find_bridge(dev->dev.of_node);
+   bridge = of_drm_find_bridge(np);
if (!bridge)
bridge = ERR_PTR(-EINVAL);
}
-- 
2.34.1



[PATCH v2 0/9] drm/bridge: cdns-dsi: Fix the color-shift issue

2024-05-30 Thread Aradhya Bhatia
Hello all,

This series provides some crucial fixes and improvements for the Cadence's DSI
TX (cdns-dsi) controller found commonly in Texas Instruments' J7 family of SoCs
as well as in AM62P.

Along with that, this series aims to fix the color-shift issue that has been
going on with the DSI controller. This controller requires to be enabled before
the previous entity enables its stream[0]. It's a strict requirement which, if
not followed, causes the colors to "shift" on the display. The fix happens in
2 steps.

1. The bridge pre_enable calls have been shifted before the crtc_enable and
   the bridge post_disable calls have been shifted after the crtc_disable.
   This has been done as per the definition of bridge pre_enable.

   "The display pipe (i.e. clocks and timing signals) feeding this bridge
   will not yet be running when this callback is called".

   Since CRTC is also a source feeding the bridge, it should not be enabled
   before the bridges in the pipeline are pre_enabled.

   The sequence of enable after this patch will look like:

bridge[n]_pre_enable
...
bridge[1]_pre_enable

crtc_enable
encoder_enable

bridge[1]_enable
...
bridge[n]_enable

   and vice-versa for the bridge chain disable sequence.


2. The cdns-dsi enable / disable sequences have now been moved to pre_enable
   and post_disable sequences. This is the only way to have cdns-dsi drivers
   be up and ready before the previous entity is enables its streaming.

The DSI also spec requires the Clock and Data Lanes be ready before the DSI TX
enables its stream[0]. A patch has been added to make the code wait for that to
happen. Going ahead with further DSI (and DSS configuration), while the lanes
are not ready, has been found to be another reason for shift in colors.

All these patches have been tested on TI's vendor tree kernel with more devices,
but for the mainline, these patches have been tested with J721E based
BeagleboneAI64 along with a RaspberryPi 7" DSI panel. The extra patches can be
found in the "next_dsi-v2-tests" branch of my github fork[1] for anyone who
would like to test them.

Thanks,
Aradhya


[0]: Section 12.6.5.7.3: "Start-up Procedure" [For DSI TX controller]
 in TDA4VM Technical Reference Manual https://www.ti.com/lit/zip/spruil1

[1]: https://github.com/aradhya07/linux-ab/tree/next_dsi-v2-tests

Change Log:

  - Changes in v2:
- Drop patch "drm/tidss: Add CRTC mode_fixup"
- Split patch "drm/bridge: cdns-dsi: Fix minor bugs" into 4 separate ones
- Drop support for early_enable/late_disable APIs and instead re-order the
  pre_enable / post_disable APIs to be called before / after crtc_enable /
  crtc_disable.
- Drop support for early_enable/late_disable in cdns-dsi and use
  pre_enable/post_disable APIs instead to do bridge enable/disable.


Previous versions:

v1: https://lore.kernel.org/all/20240511153051.1355825-1-a-bhat...@ti.com/

Aradhya Bhatia (9):
  drm/bridge: cdns-dsi: Fix OF node pointer
  drm/bridge: cdns-dsi: Fix the phy_initialized variable
  drm/bridge: cdns-dsi: Fix the link and phy init order
  drm/bridge: cdns-dsi: Fix the clock variable for mode_valid()
  drm/bridge: cdns-dsi: Wait for Clk and Data Lanes to be ready
  drm/bridge: cdns-dsi: Reset the DCS write FIFO
  drm/bridge: cdns-dsi: Support atomic bridge APIs
  drm/atomic-helper: Re-order bridge chain pre-enable and post-disable
  drm/bridge: cdns-dsi: Use pre_enable/post_disable to enable/disable

 .../gpu/drm/bridge/cadence/cdns-dsi-core.c| 91 ++-
 drivers/gpu/drm/drm_atomic_helper.c   | 70 +-
 2 files changed, 135 insertions(+), 26 deletions(-)


base-commit: 9d99040b1bc8dbf385a8aa535e9efcdf94466e19
-- 
2.34.1



[PATCH v2 3/9] drm/bridge: cdns-dsi: Fix the link and phy init order

2024-05-30 Thread Aradhya Bhatia
The order of init of DSI link and DSI phy is wrong. The DSI link needs
to be configured before the DSI phy is getting configured. Otherwise,
the D-Phy is unable to lock in on the incoming PLL Reference clock[0].

Fix the order of inits.

[0]: See section 12.6.5.7.3 "Start-up Procedure" in J721E SoC TRM
 TRM Link: http://www.ti.com/lit/pdf/spruil1

Fixes: fced5a364dee ("drm/bridge: cdns: Convert to phy framework")
Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 42565e253b2d..371a3453970c 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -775,8 +775,8 @@ static void cdns_dsi_bridge_enable(struct drm_bridge 
*bridge)
 
WARN_ON_ONCE(cdns_dsi_check_conf(dsi, mode, _cfg, false));
 
-   cdns_dsi_hs_init(dsi);
cdns_dsi_init_link(dsi);
+   cdns_dsi_hs_init(dsi);
 
writel(HBP_LEN(dsi_cfg.hbp) | HSA_LEN(dsi_cfg.hsa),
   dsi->regs + VID_HSIZE1);
-- 
2.34.1



[PATCH v2 2/9] drm/bridge: cdns-dsi: Fix the phy_initialized variable

2024-05-30 Thread Aradhya Bhatia
Update the Phy initialized state to "not initialized" when the driver
(and the hardware by extension) gets suspended. This will allow the Phy
to get initialized again after resume.

Fixes: e19233955d9e ("drm/bridge: Add Cadence DSI driver")
Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index b016f2ba06bb..42565e253b2d 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -1153,6 +1153,7 @@ static int __maybe_unused cdns_dsi_suspend(struct device 
*dev)
clk_disable_unprepare(dsi->dsi_p_clk);
reset_control_assert(dsi->dsi_p_rst);
dsi->link_initialized = false;
+   dsi->phy_initialized = false;
return 0;
 }
 
-- 
2.34.1



Re: [PATCH 6/7] drm/bridge: Introduce early_enable and late disable

2024-05-24 Thread Aradhya Bhatia
Hi Maxime,

On 21/05/24 18:45, Maxime Ripard wrote:
> Hi,
> 
> On Thu, May 16, 2024 at 03:10:15PM GMT, Aradhya Bhatia wrote:
>>>>/**
>>>> * @pre_enable:
>>>> *
>>>> @@ -285,6 +319,26 @@ struct drm_bridge_funcs {
>>>> */
>>>>void (*enable)(struct drm_bridge *bridge);
>>>>  
>>>> +  /**
>>>> +   * @atomic_early_enable:
>>>> +   *
>>>> +   * This callback should enable the bridge. It is called right before
>>>> +   * the preceding element in the display pipe is enabled. If the
>>>> +   * preceding element is a bridge this means it's called before that
>>>> +   * bridge's @atomic_early_enable. If the preceding element is a
>>>> +   * _crtc it's called right before the crtc's
>>>> +   * _crtc_helper_funcs.atomic_enable hook.
>>>> +   *
>>>> +   * The display pipe (i.e. clocks and timing signals) feeding this bridge
>>>> +   * will not yet be running when this callback is called. The bridge can
>>>> +   * enable the display link feeding the next bridge in the chain (if
>>>> +   * there is one) when this callback is called.
>>>> +   *
>>>> +   * The @early_enable callback is optional.
>>>> +   */
>>>> +  void (*atomic_early_enable)(struct drm_bridge *bridge,
>>>> +  struct drm_bridge_state *old_bridge_state);
>>>> +
>>>>/**
>>>> * @atomic_pre_enable:
>>>> *
>>>> @@ -361,6 +415,21 @@ struct drm_bridge_funcs {
>>>>void (*atomic_post_disable)(struct drm_bridge *bridge,
>>>>struct drm_bridge_state *old_bridge_state);
>>>>  
>>>> +  /**
>>>> +   * @atomic_late_disable:
>>>> +   *
>>>> +   * This callback should disable the bridge. It is called right after the
>>>> +   * preceding element in the display pipe is disabled. If the preceding
>>>> +   * element is a bridge this means it's called after that bridge's
>>>> +   * @atomic_late_disable. If the preceding element is a _crtc it's
>>>> +   * called right after the crtc's _crtc_helper_funcs.atomic_disable
>>>> +   * hook.
>>>> +   *
>>>> +   * The @atomic_late_disable callback is optional.
>>>> +   */
>>>> +  void (*atomic_late_disable)(struct drm_bridge *bridge,
>>>> +  struct drm_bridge_state *old_bridge_state);
>>>> +
>>>
>>> But more importantly, I don't quite get the use case you're trying to
>>> solve here.
>>>
>>> If I got the rest of your series, the Cadence DSI bridge needs to be
>>> powered up before its source is started. You can't use atomic_enable or
>>> atomic_pre_enable because it would start the source before the DSI
>>> bridge. Is that correct?
>>>
>>
>> That's right. I cannot use bridge_atomic_pre_enable /
>> bridge_atomic_enable here. But that's because my source is CRTC, which
>> gets enabled via crtc_atomic_enable.
>>
>>
>>> If it is, then how is it different from what
>>> drm_atomic_bridge_chain_pre_enable is doing? The assumption there is
>>> that it starts enabling bridges last to first, to it should be enabled
>>> before anything starts.
>>>
>>> The whole bridge enabling order code starts to be a bit of a mess, so it
>>> would be great if you could list all the order variations we have
>>> currently, and why none work for cdns-dsi.
>>>
>>
>> Of course! I can elaborate on the order.
>>
>> Without my patches (and given there isn't any bridge setting the
>> "pre_enable_prev_first" flag) the order of enable for any single display
>> chain, looks like this -
>>
>>  crtc_enable
>>  
>>  bridge[n]_pre_enable
>>  ---
>>  bridge[1]_pre_enable
>>
>>  encoder_enable
>>
>>  bridge[1]_enable
>>  ---
>>  bridge[n]_enable
>>
>> The tidss enables at the crtc_enable level, and hence is the first
>> entity with stream on. cdns-dsi doesn't stand a chance with
>> bridge_atmoic_pre_enable / bridge_atmoic_enable hooks. And there is no
>> bridge call happening before crtc currently.
> 
> Thanks for filling the blanks :)
> 
> I assume that since cdns-dsi is a bridge, and it only has a simple
> encoder implementation, for it to receive some video signal we need to
> 

Re: [PATCH v3 3/6] dt-bindings: display: simple: Add Microtips & Lincolntech Dual-LVDS Panels

2024-05-16 Thread Aradhya Bhatia
Hi Liu,

Thanks for reviewing the patch.

On 16/05/24 07:49, Liu Ying wrote:
> On 5/15/24 17:51, Aradhya Bhatia wrote:
>> Add the Microtips Technology USA's MF-101HIEBCAF0 10.1"[0] panel,
>> MF-103HIEB0GA0 10.25"[1] panel, and Lincoln Technology Solutions'
>> LCD185-101CT 10.1"[2] panel.
>>
>> Thes are all dual-lvds panels.
>>
>> Panel Links:
>> [0]: 
>> https://simplespec.microtipsusa.com/uploads/spec/datasheetFile/2588/13-101HIEBCAF0-S_V1.1_20221104.pdf
>> [1]: 
>> https://simplespec.microtipsusa.com/uploads/spec/datasheetFile/2660/13-103HIEB0GA0-S_V1.0_20211206.pdf
> 
> This one mentions some controls in '3. PIN DESCRIPTION' which
> don't comply with this binding, like RL, TB, STBYB and RESET.
> Note this binding only allows compatible, ports, backlight,
> enable-gpios and power-supply properties, nothing more.
>

Maybe the internal module _can_ support these control options but the
actual panel hardware does not expose any of these controls on its
connector pin-out, and hence has no possibility for additional SW
control. Even for the usage, the device-tree node for the panel only has
"compatible" and "ports" properties defined.

The panel is being used within the confines of a simple panel.

Regards
Aradhya

> 
>> [2]: 
>> https://lincolntechsolutions.com/wp-content/uploads/2023/04/LCD185-101CTL1ARNTT_DS_R1.3.pdf
>>
>> Signed-off-by: Aradhya Bhatia 
>> ---
>>  .../display/panel/panel-simple-lvds-dual-ports.yaml | 6 ++
>>  1 file changed, 6 insertions(+)
>>
>> diff --git 
>> a/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml
>>  
>> b/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml
>> index 716ece5f3978..e78160d1aa24 100644
>> --- 
>> a/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml
>> +++ 
>> b/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml
>> @@ -41,6 +41,12 @@ properties:
>>- auo,g190ean01
>>  # Kaohsiung Opto-Electronics Inc. 10.1" WUXGA (1920 x 1200) LVDS 
>> TFT LCD panel
>>- koe,tx26d202vm0bwa
>> +# Lincoln Technology Solutions, LCD185-101CT 10.1" TFT 1920x1200
>> +  - lincolntech,lcd185-101ct
>> +# Microtips Technology MF-101HIEBCAF0 10.1" WUXGA (1920x1200) TFT 
>> LCD panel
>> +  - microtips,mf-101hiebcaf0
>> +# Microtips Technology MF-103HIEB0GA0 10.25" 1920x720 TFT LCD panel
>> +  - microtips,mf-103hieb0ga0
>>  # NLT Technologies, Ltd. 15.6" FHD (1920x1080) LVDS TFT LCD panel
>>- nlt,nl192108ac18-02d
>>  
> 


Re: [PATCH 1/7] drm/tidss: Add CRTC mode_fixup

2024-05-16 Thread Aradhya Bhatia
Hi Maxime,

Thank you for reviewing the patches.

On 16/05/24 13:40, Maxime Ripard wrote:
> Hi,
> 
> On Sat, May 11, 2024 at 09:00:45PM +0530, Aradhya Bhatia wrote:
>> Add support for mode_fixup for the tidss CRTC.
>>
>> Some bridges like the cdns-dsi consume the crtc_* timing parameters for
>> programming the blanking values. Allow for the normal timing parameters
>> to get copied to crtc_* timing params.
>>
>> Signed-off-by: Aradhya Bhatia 
>> ---
>>  drivers/gpu/drm/tidss/tidss_crtc.c | 11 +++
>>  1 file changed, 11 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/tidss/tidss_crtc.c 
>> b/drivers/gpu/drm/tidss/tidss_crtc.c
>> index 94f8e3178df5..797ef53d9ad2 100644
>> --- a/drivers/gpu/drm/tidss/tidss_crtc.c
>> +++ b/drivers/gpu/drm/tidss/tidss_crtc.c
>> @@ -309,12 +309,23 @@ enum drm_mode_status tidss_crtc_mode_valid(struct 
>> drm_crtc *crtc,
>>  return dispc_vp_mode_valid(tidss->dispc, tcrtc->hw_videoport, mode);
>>  }
>>  
>> +static
>> +bool tidss_crtc_mode_fixup(struct drm_crtc *crtc,
>> +   const struct drm_display_mode *mode,
>> +   struct drm_display_mode *adjusted_mode)
>> +{
>> +drm_mode_set_crtcinfo(adjusted_mode, 0);
>> +
>> +return true;
>> +}
>> +
>>  static const struct drm_crtc_helper_funcs tidss_crtc_helper_funcs = {
>>  .atomic_check = tidss_crtc_atomic_check,
>>  .atomic_flush = tidss_crtc_atomic_flush,
>>  .atomic_enable = tidss_crtc_atomic_enable,
>>  .atomic_disable = tidss_crtc_atomic_disable,
>>  
>> +.mode_fixup = tidss_crtc_mode_fixup,
>>  .mode_valid = tidss_crtc_mode_valid,
>>  };
> 
> mode_fixup is deprecated for atomic drivers, so the solution must be
> different there.
> 
> It's also not clear to me how it could change anything there:
> drm_mode_set_crtcinfo with no flags will make crtc_* field exactly
> identical to their !crtc counterparts.
>

I checked the flag options. There isn't any flag required. The only
reason to add this call is because cdns-dsi strictly requires the crtc_*
fields to be populated during the bridge enable.

Secondly, if mode_fixup is deprecated, I think the crtc_atomic_check
would be the next best place to add this call.


Regards
Aradhya


Re: [PATCH 2/7] drm/bridge: cdns-dsi: Fix minor bugs

2024-05-16 Thread Aradhya Bhatia



On 16/05/24 13:41, Maxime Ripard wrote:
> On Sat, May 11, 2024 at 09:00:46PM +0530, Aradhya Bhatia wrote:
>> Update the Phy initialized state to "not initialized" when the driver
>> (and the hardware by extension) gets suspended. This will allow the Phy
>> to get initialized again after resume.
>>
>> Fix the OF node that gets passed to find the next available bridge in
>> the display pipeline.
>>
>> Fix the order of DSI Link and DSI Phy inits. The link init needs to
>> happen before the Phy is initialized, so the Phy can lock on the
>> incoming PLL reference clock. If this doesn't happen, the Phy cannot
>> lock (until DSI Link is init later on). This causes a warning dump
>> during the kernel boot.
>>
>> Allow the D-Phy config checks to use mode->clock instead of
>> mode->crtc_clock during mode_valid checks, like everywhere else in the
>> driver.
> 
> All these should be in separate patches.
> 

Alright! I will split them into different patches in v2.

Regards
Aradhya


Re: [PATCH 6/7] drm/bridge: Introduce early_enable and late disable

2024-05-16 Thread Aradhya Bhatia
Hi Maxime,

Thank you for reviewing the patches!

On 16/05/24 13:52, Maxime Ripard wrote:
> On Sat, May 11, 2024 at 09:00:50PM +0530, Aradhya Bhatia wrote:
>> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
>> index 4baca0d9107b..40f93230abb2 100644
>> --- a/include/drm/drm_bridge.h
>> +++ b/include/drm/drm_bridge.h
>> @@ -206,6 +206,20 @@ struct drm_bridge_funcs {
>>   */
>>  void (*post_disable)(struct drm_bridge *bridge);
>>  
>> +/**
>> + * @late_disable:
>> + *
>> + * This callback should disable the bridge. It is called right after the
>> + * preceding element in the display pipe is disabled. If the preceding
>> + * element is a bridge this means it's called after that bridge's
>> + * @atomic_post_disable. If the preceding element is a _crtc it's
>> + * called right after the crtc's _crtc_helper_funcs.atomic_disable
>> + * hook.
>> + *
>> + * The @late_disable callback is optional.
>> + */
>> +void (*late_disable)(struct drm_bridge *bridge);
>> +
>>  /**
>>   * @mode_set:
>>   *
>> @@ -235,6 +249,26 @@ struct drm_bridge_funcs {
>>  void (*mode_set)(struct drm_bridge *bridge,
>>   const struct drm_display_mode *mode,
>>   const struct drm_display_mode *adjusted_mode);
>> +
>> +/**
>> + * @early_enable:
>> + *
>> + * This callback should enable the bridge. It is called right before
>> + * the preceding element in the display pipe is enabled. If the
>> + * preceding element is a bridge this means it's called before that
>> + * bridge's @early_enable. If the preceding element is a _crtc it's
>> + * called right before the crtc's _crtc_helper_funcs.atomic_enable
>> + * hook.
>> + *
>> + * The display pipe (i.e. clocks and timing signals) feeding this bridge
>> + * will not yet be running when this callback is called. The bridge can
>> + * enable the display link feeding the next bridge in the chain (if
>> + * there is one) when this callback is called.
>> + *
>> + * The @early_enable callback is optional.
>> + */
>> +void (*early_enable)(struct drm_bridge *bridge);
>> +
> 
> You don't need the legacy option here, just go straight for the atomic one.

Got it! I can remove these in v2.

> 
>>  /**
>>   * @pre_enable:
>>   *
>> @@ -285,6 +319,26 @@ struct drm_bridge_funcs {
>>   */
>>  void (*enable)(struct drm_bridge *bridge);
>>  
>> +/**
>> + * @atomic_early_enable:
>> + *
>> + * This callback should enable the bridge. It is called right before
>> + * the preceding element in the display pipe is enabled. If the
>> + * preceding element is a bridge this means it's called before that
>> + * bridge's @atomic_early_enable. If the preceding element is a
>> + * _crtc it's called right before the crtc's
>> + * _crtc_helper_funcs.atomic_enable hook.
>> + *
>> + * The display pipe (i.e. clocks and timing signals) feeding this bridge
>> + * will not yet be running when this callback is called. The bridge can
>> + * enable the display link feeding the next bridge in the chain (if
>> + * there is one) when this callback is called.
>> + *
>> + * The @early_enable callback is optional.
>> + */
>> +void (*atomic_early_enable)(struct drm_bridge *bridge,
>> +struct drm_bridge_state *old_bridge_state);
>> +
>>  /**
>>   * @atomic_pre_enable:
>>   *
>> @@ -361,6 +415,21 @@ struct drm_bridge_funcs {
>>  void (*atomic_post_disable)(struct drm_bridge *bridge,
>>  struct drm_bridge_state *old_bridge_state);
>>  
>> +/**
>> + * @atomic_late_disable:
>> + *
>> + * This callback should disable the bridge. It is called right after the
>> + * preceding element in the display pipe is disabled. If the preceding
>> + * element is a bridge this means it's called after that bridge's
>> + * @atomic_late_disable. If the preceding element is a _crtc it's
>> + * called right after the crtc's _crtc_helper_funcs.atomic_disable
>> + * hook.
>> + *
>> + * The @atomic_late_disable callback is optional.
>> + */
>> +void (*atomic_late_disable)(struct drm_bridge *bridge,
>> +struct drm_bridge_state *old_bridge_sta

[PATCH v3 6/6] drm/panel: simple: Add Microtips Technology MF-103HIEB0GA0 panel

2024-05-15 Thread Aradhya Bhatia
Add support for Microtips Technology USA MF-103HIEB0GA0 10.25"[0],
1920x720, 8-bit TFT LCD with LVDS interface. Its a Dual-LVDS Panel and
does not support touch.

[0]: Panel Datasheet
https://simplespec.microtipsusa.com/uploads/spec/datasheetFile/2660/13-103HIEB0GA0-S_V1.0_20211206.pdf

Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/panel/panel-simple.c | 32 
 1 file changed, 32 insertions(+)

diff --git a/drivers/gpu/drm/panel/panel-simple.c 
b/drivers/gpu/drm/panel/panel-simple.c
index 3a0d8f0ff267..1b0a6b4e034c 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -3084,6 +3084,35 @@ static const struct panel_desc 
microtips_mf_101hiebcaf0_c = {
.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
+static const struct drm_display_mode microtips_mf_103hieb0ga0_mode = {
+   .clock = 93301,
+   .hdisplay = 1920,
+   .hsync_start = 1920 + 72,
+   .hsync_end = 1920 + 72 + 72,
+   .htotal = 1920 + 72 + 72 + 72,
+   .vdisplay = 720,
+   .vsync_start = 720 + 3,
+   .vsync_end = 720 + 3 + 3,
+   .vtotal = 720 + 3 + 3 + 2,
+};
+
+static const struct panel_desc microtips_mf_103hieb0ga0 = {
+   .modes = _mf_103hieb0ga0_mode,
+   .bpc = 8,
+   .num_modes = 1,
+   .size = {
+   .width = 244,
+   .height = 92,
+   },
+   .delay = {
+   .prepare = 50,
+   .disable = 50,
+   },
+   .bus_flags = DRM_BUS_FLAG_DE_HIGH,
+   .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+   .connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
 static const struct drm_display_mode mitsubishi_aa070mc01_mode = {
.clock = 30400,
.hdisplay = 800,
@@ -4726,6 +4755,9 @@ static const struct of_device_id platform_of_match[] = {
}, {
.compatible = "microtips,mf-101hiebcaf0",
.data = _mf_101hiebcaf0_c,
+   }, {
+   .compatible = "microtips,mf-103hieb0ga0",
+   .data = _mf_103hieb0ga0,
}, {
.compatible = "mitsubishi,aa070mc01-ca1",
.data = _aa070mc01,
-- 
2.34.1



[PATCH v3 4/6] drm/panel: simple: Add Lincoln Tech Sol LCD185-101CT panel

2024-05-15 Thread Aradhya Bhatia
Add support for Lincoln Technology Solutions LCD185-101CT, 10.1",
1920x1200, 8-bit TFT LCD with LVDS interface, LED backlight and PCAP
touch support (Goodix GT928).

[0]: Panel Datasheet
https://lincolntechsolutions.com/wp-content/uploads/2023/04/LCD185-101CTL1ARNTT_DS_R1.3.pdf

Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/panel/panel-simple.c | 32 
 1 file changed, 32 insertions(+)

diff --git a/drivers/gpu/drm/panel/panel-simple.c 
b/drivers/gpu/drm/panel/panel-simple.c
index dcb6d0b6ced0..10e974bffd28 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -2870,6 +2870,35 @@ static const struct panel_desc lg_lb070wv8 = {
.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
+static const struct drm_display_mode lincolntech_lcd185_101ct_mode = {
+   .clock = 155127,
+   .hdisplay = 1920,
+   .hsync_start = 1920 + 128,
+   .hsync_end = 1920 + 128 + 20,
+   .htotal = 1920 + 128 + 20 + 12,
+   .vdisplay = 1200,
+   .vsync_start = 1200 + 19,
+   .vsync_end = 1200 + 19 + 4,
+   .vtotal = 1200 + 19 + 4 + 20,
+};
+
+static const struct panel_desc lincolntech_lcd185_101ct = {
+   .modes = _lcd185_101ct_mode,
+   .bpc = 8,
+   .num_modes = 1,
+   .size = {
+   .width = 217,
+   .height = 136,
+   },
+   .delay = {
+   .prepare = 50,
+   .disable = 50,
+   },
+   .bus_flags = DRM_BUS_FLAG_DE_HIGH,
+   .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+   .connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
 static const struct display_timing logictechno_lt161010_2nh_timing = {
.pixelclock = { 2640, 3330, 4680 },
.hactive = { 800, 800, 800 },
@@ -4644,6 +4673,9 @@ static const struct of_device_id platform_of_match[] = {
}, {
.compatible = "lg,lb070wv8",
.data = _lb070wv8,
+   }, {
+   .compatible = "lincolntech,lcd185-101ct",
+   .data = _lcd185_101ct,
}, {
.compatible = "logicpd,type28",
.data = _type_28,
-- 
2.34.1



[PATCH v3 2/6] dt-bindings: vendor-prefixes: Add lincolntech

2024-05-15 Thread Aradhya Bhatia
Add document vendor prefix for Lincoln Technology Solutions
(lincolntech).

Signed-off-by: Aradhya Bhatia 
Acked-by: Krzysztof Kozlowski 
Reviewed-by: Laurent Pinchart 
---
 Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml 
b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index afebaf8e62bb..51ca841db26e 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -820,6 +820,8 @@ patternProperties:
 description: Lichee Pi
   "^linaro,.*":
 description: Linaro Limited
+  "^lincolntech,.*":
+description: Lincoln Technology Solutions
   "^lineartechnology,.*":
 description: Linear Technology
   "^linksprite,.*":
-- 
2.34.1



[PATCH v3 5/6] drm/panel: simple: Add Microtips Technology 13-101HIEBCAF0-C panel

2024-05-15 Thread Aradhya Bhatia
Add support for Microtips Technology USA 13-101HIECAF0-C 10.1",
1920x1200, 8-bit TFT LCD with LVDS interface, LED backlight and touch
support (ILITEK 2511).

[0]: Panel Datasheet
https://simplespec.microtipsusa.com/uploads/spec/datasheetFile/2588/13-101HIEBCAF0-S_V1.1_20221104.pdf

Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/panel/panel-simple.c | 32 
 1 file changed, 32 insertions(+)

diff --git a/drivers/gpu/drm/panel/panel-simple.c 
b/drivers/gpu/drm/panel/panel-simple.c
index 10e974bffd28..3a0d8f0ff267 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -3055,6 +3055,35 @@ static const struct panel_desc logicpd_type_28 = {
.connector_type = DRM_MODE_CONNECTOR_DPI,
 };
 
+static const struct drm_display_mode microtips_mf_101hiebcaf0_c_mode = {
+   .clock = 150275,
+   .hdisplay = 1920,
+   .hsync_start = 1920 + 32,
+   .hsync_end = 1920 + 32 + 52,
+   .htotal = 1920 + 32 + 52 + 24,
+   .vdisplay = 1200,
+   .vsync_start = 1200 + 24,
+   .vsync_end = 1200 + 24 + 8,
+   .vtotal = 1200 + 24 + 8 + 3,
+};
+
+static const struct panel_desc microtips_mf_101hiebcaf0_c = {
+   .modes = _mf_101hiebcaf0_c_mode,
+   .bpc = 8,
+   .num_modes = 1,
+   .size = {
+   .width = 217,
+   .height = 136,
+   },
+   .delay = {
+   .prepare = 50,
+   .disable = 50,
+   },
+   .bus_flags = DRM_BUS_FLAG_DE_HIGH,
+   .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+   .connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
 static const struct drm_display_mode mitsubishi_aa070mc01_mode = {
.clock = 30400,
.hdisplay = 800,
@@ -4694,6 +4723,9 @@ static const struct of_device_id platform_of_match[] = {
}, {
.compatible = "logictechno,lttd800480070-l6wh-rt",
.data = _lttd800480070_l6wh_rt,
+   }, {
+   .compatible = "microtips,mf-101hiebcaf0",
+   .data = _mf_101hiebcaf0_c,
}, {
.compatible = "mitsubishi,aa070mc01-ca1",
.data = _aa070mc01,
-- 
2.34.1



[PATCH v3 3/6] dt-bindings: display: simple: Add Microtips & Lincolntech Dual-LVDS Panels

2024-05-15 Thread Aradhya Bhatia
Add the Microtips Technology USA's MF-101HIEBCAF0 10.1"[0] panel,
MF-103HIEB0GA0 10.25"[1] panel, and Lincoln Technology Solutions'
LCD185-101CT 10.1"[2] panel.

Thes are all dual-lvds panels.

Panel Links:
[0]: 
https://simplespec.microtipsusa.com/uploads/spec/datasheetFile/2588/13-101HIEBCAF0-S_V1.1_20221104.pdf
[1]: 
https://simplespec.microtipsusa.com/uploads/spec/datasheetFile/2660/13-103HIEB0GA0-S_V1.0_20211206.pdf
[2]: 
https://lincolntechsolutions.com/wp-content/uploads/2023/04/LCD185-101CTL1ARNTT_DS_R1.3.pdf

Signed-off-by: Aradhya Bhatia 
---
 .../display/panel/panel-simple-lvds-dual-ports.yaml | 6 ++
 1 file changed, 6 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml
 
b/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml
index 716ece5f3978..e78160d1aa24 100644
--- 
a/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml
+++ 
b/Documentation/devicetree/bindings/display/panel/panel-simple-lvds-dual-ports.yaml
@@ -41,6 +41,12 @@ properties:
   - auo,g190ean01
 # Kaohsiung Opto-Electronics Inc. 10.1" WUXGA (1920 x 1200) LVDS TFT 
LCD panel
   - koe,tx26d202vm0bwa
+# Lincoln Technology Solutions, LCD185-101CT 10.1" TFT 1920x1200
+  - lincolntech,lcd185-101ct
+# Microtips Technology MF-101HIEBCAF0 10.1" WUXGA (1920x1200) TFT LCD 
panel
+  - microtips,mf-101hiebcaf0
+# Microtips Technology MF-103HIEB0GA0 10.25" 1920x720 TFT LCD panel
+  - microtips,mf-103hieb0ga0
 # NLT Technologies, Ltd. 15.6" FHD (1920x1080) LVDS TFT LCD panel
   - nlt,nl192108ac18-02d
 
-- 
2.34.1



[PATCH v3 1/6] dt-bindings: vendor-prefixes: Add microtips

2024-05-15 Thread Aradhya Bhatia
Add document vendor prefix for Microtips Technology USA (microtips).

Signed-off-by: Aradhya Bhatia 
Acked-by: Krzysztof Kozlowski 
Reviewed-by: Laurent Pinchart 
---
 Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml 
b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index fbf47f0bacf1..afebaf8e62bb 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -924,6 +924,8 @@ patternProperties:
 description: Microsoft Corporation
   "^microsys,.*":
 description: MicroSys Electronics GmbH
+  "^microtips,.*":
+description: Microtips Technology USA
   "^mikroe,.*":
 description: MikroElektronika d.o.o.
   "^mikrotik,.*":
-- 
2.34.1



[PATCH v3 0/6] drm/panel: simple: Add Panels and Panel Vendors

2024-05-15 Thread Aradhya Bhatia
Hi all,

Picking up this long-standing series which added support for Microtips'
and LincolnTech's dual-lvds panels.

Microtips Technology Solutions USA, and Lincoln Technology Solutions are
2 display panel vendors, and the patches 1/6 and 2/6 add their vendor
prefixes.

Patch 3/6 adds panel specific compatibles to the binding for simple
panels with 2 lvds ports.

Lastly, patches 4/6 through 6/6 add the timing parameters and the
compatibles in the panel-simple driver file.

This series has changed from v2 in that it is not trying to add a new
schema for panel-dual-lvds anymore. There is no requirement for that
today. So patches 3/4 and 4/4 from v2 have completely been dropped. And
in their place, have come new patches - 3/6 through 6/6.
Patches 1/4 and 2/4 from v2 are now 1/6 and 2/6 respectively, and I have
carried the tags provided by Laurent Pinchart and Krzysztof Kozlowski.

Regards
Aradhya

Changes in V3:
==
  - Drop the schema for "panel-dual-lvds".
  - Instead add the panels under schema for simple panels with dual
ports.
  - Add support for these panels in panel-simple driver.

Changes in V2:
==
  - Rebased to latest linux-next.
  - Made dt-binding syntax corrections in Patch 3/4, based on comments
by Krzysztof Kozlowski and Laurent Pinchart.

V2: https://lore.kernel.org/all/20230124101238.4542-1-a-bhat...@ti.com/
V1: https://lore.kernel.org/all/20230103064615.5311-1-a-bhat...@ti.com/


Aradhya Bhatia (6):
  dt-bindings: vendor-prefixes: Add microtips
  dt-bindings: vendor-prefixes: Add lincolntech
  dt-bindings: display: simple: Add Microtips & Lincolntech Dual-LVDS
Panels
  drm/panel: simple: Add Lincoln Tech Sol LCD185-101CT panel
  drm/panel: simple: Add Microtips Technology 13-101HIEBCAF0-C panel
  drm/panel: simple: Add Microtips Technology MF-103HIEB0GA0 panel

 .../panel/panel-simple-lvds-dual-ports.yaml   |  6 ++
 .../devicetree/bindings/vendor-prefixes.yaml  |  4 +
 drivers/gpu/drm/panel/panel-simple.c  | 96 +++
 3 files changed, 106 insertions(+)


base-commit: 82d92a9a1b9ea0ea52aff27cddd05009b4edad49
-- 
2.34.1



Re: [PATCH 1/4] dt-bindings: display: ti,am65x-dss: Minor Cleanup

2024-05-13 Thread Aradhya Bhatia



On 14/05/24 00:49, Rob Herring wrote:
> On Sun, May 12, 2024 at 01:00:52AM +0530, Aradhya Bhatia wrote:
>> Reduce tab size from 8 spaces to 4 spaces to make the bindings
>> consistent, and easy to expand.
> 
> "Re-indent the example" would be more specific than "minor cleanups" in 
> the subject.

That would be better. Will reword this in v2.
Thank you!

Regards
Aradhya

> 
> Otherwise,
> 
> Acked-by: Rob Herring (Arm) 
> 
>>
>> Signed-off-by: Aradhya Bhatia 
>> ---
>>  .../bindings/display/ti/ti,am65x-dss.yaml | 54 +--
>>  1 file changed, 27 insertions(+), 27 deletions(-)
> 


Re: [PATCH 3/4] dt-bindings: display: ti,am65x-dss: Add OLDI properties for AM625 DSS

2024-05-13 Thread Aradhya Bhatia



On 14/05/24 01:05, Rob Herring wrote:
> On Sun, May 12, 2024 at 01:00:54AM +0530, Aradhya Bhatia wrote:
>> The DSS in AM625 SoC has 2 OLDI TXes. Refer the OLDI schema to add the
>> properties.
>>
>> Signed-off-by: Aradhya Bhatia 
>> ---
>>  .../bindings/display/ti/ti,am65x-dss.yaml | 136 +-
>>  1 file changed, 135 insertions(+), 1 deletion(-)
>>
>> diff --git a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml 
>> b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
>> index 399d68986326..4aa2de59b32b 100644
>> --- a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
>> +++ b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
>> @@ -85,12 +85,30 @@ properties:
>>  
>>  properties:
>>port@0:
>> -$ref: /schemas/graph.yaml#/properties/port
>> +$ref: /schemas/graph.yaml#/$defs/port-base
> 
> You don't need this change. You aren't adding any extra properties.

Alright. I will make the change.

> 
>>  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
>>  
>>port@1:
>>  $ref: /schemas/graph.yaml#/properties/port
>> @@ -112,6 +130,22 @@ properties:
>>Input memory (from main memory to dispc) bandwidth limit in
>>bytes per second
>>  
>> +  oldi-txes:
>> +type: object
>> +properties:
>> +  "#address-cells":
>> +const: 1
>> +
>> +  "#size-cells":
>> +const: 0
>> +
>> +patternProperties:
>> +  '^oldi_tx@[0-1]$':
>> +type: object
>> +$ref: ti,am625-oldi.yaml#
>> +unevaluatedProperties: false
>> +description: OLDI transmitters connected to the DSS VPs
> 
> Connected to is not part of the DSS. I don't think these nodes belong 
> here as mentioned in the other patch.
> 

Replied to this in patch 2/4 to keep the discussion in one thread.


Regards
Aradhya



Re: [PATCH 2/4] dt-bindings: display: ti: Add schema for AM625 OLDI Transmitter

2024-05-13 Thread Aradhya Bhatia
Hi Rob,

Thank you for reviewing the patches!

On 14/05/24 01:00, Rob Herring wrote:
> On Mon, May 13, 2024 at 02:07:44PM +0530, Aradhya Bhatia wrote:
>> Hi Laurent,
>>
>> Thank you for reviewing the patches!
>>
>> On 13-May-24 01:04, Laurent Pinchart wrote:
>>> Hi Aradhya,
>>>
>>> Thank you for the patch.
>>>
>>> On Sun, May 12, 2024 at 01:00:53AM +0530, Aradhya Bhatia wrote:
>>>> Add devicetree binding schema for AM625 OLDI Transmitters.
>>>>
>>>> Signed-off-by: Aradhya Bhatia 
>>>> ---
>>>>  .../bindings/display/ti/ti,am625-oldi.yaml| 153 ++
>>>>  MAINTAINERS   |   1 +
>>>>  2 files changed, 154 insertions(+)
>>>>  create mode 100644 
>>>> Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml
>>>>
>>>> diff --git 
>>>> a/Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml 
>>>> b/Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml
>>>> new file mode 100644
>>>> index ..0a96e600bc0b
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml
>>>> @@ -0,0 +1,153 @@
>>>> +# 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 
>>>> +  - Aradhya Bhatia 
>>>> +
>>>> +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: s_clk
>>>> +
>>>> +  ti,companion-oldi:
>>>> +$ref: /schemas/types.yaml#/definitions/phandle
>>>> +description:
>>>> +  phandle to companion OLDI transmitter. This property is mandatory 
>>>> for the
>>>> +  primarty OLDI TX if the OLDI TXes are expected to work either in 
>>>> dual-lvds
>>>> +  mode or in clone mode. This property should point to the secondary 
>>>> OLDI
>>>> +  TX.
>>>> +
>>>> +  ti,secondary-oldi:
>>>> +type: boolean
>>>> +description: Boolean property to mark an OLDI TX as secondary node.
>>>> +
>>>> +  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. This property is needed for OLDI interface to 
>>>> work.
>>>> +
>>>> +  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
>>>> +
>>>> +allOf:
>>>> +  - if:
>>>> +  properties:
>>>> +ti,secondary-oldi: true
>>>> +then:
>>>> +  properties:
>>>> +ti,companion-oldi: false
>&g

Re: [PATCH 2/4] dt-bindings: display: ti: Add schema for AM625 OLDI Transmitter

2024-05-13 Thread Aradhya Bhatia
Hi Laurent,

Thank you for reviewing the patches!

On 13-May-24 01:04, Laurent Pinchart wrote:
> Hi Aradhya,
> 
> Thank you for the patch.
> 
> On Sun, May 12, 2024 at 01:00:53AM +0530, Aradhya Bhatia wrote:
>> Add devicetree binding schema for AM625 OLDI Transmitters.
>>
>> Signed-off-by: Aradhya Bhatia 
>> ---
>>  .../bindings/display/ti/ti,am625-oldi.yaml| 153 ++
>>  MAINTAINERS   |   1 +
>>  2 files changed, 154 insertions(+)
>>  create mode 100644 
>> Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml 
>> b/Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml
>> new file mode 100644
>> index ..0a96e600bc0b
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml
>> @@ -0,0 +1,153 @@
>> +# 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 
>> +  - Aradhya Bhatia 
>> +
>> +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: s_clk
>> +
>> +  ti,companion-oldi:
>> +$ref: /schemas/types.yaml#/definitions/phandle
>> +description:
>> +  phandle to companion OLDI transmitter. This property is mandatory for 
>> the
>> +  primarty OLDI TX if the OLDI TXes are expected to work either in 
>> dual-lvds
>> +  mode or in clone mode. This property should point to the secondary 
>> OLDI
>> +  TX.
>> +
>> +  ti,secondary-oldi:
>> +type: boolean
>> +description: Boolean property to mark an OLDI TX as secondary node.
>> +
>> +  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. This property is needed for OLDI interface to 
>> work.
>> +
>> +  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
>> +
>> +allOf:
>> +  - if:
>> +  properties:
>> +ti,secondary-oldi: true
>> +then:
>> +  properties:
>> +ti,companion-oldi: false
>> +ti,oldi-io-ctrl: false
>> +clocks: false
>> +clock-names: false
>> +
>> +else:
>> +  required:
>> +- ti,oldi-io-ctrl
>> +- clocks
>> +- clock-names
>> +
>> +required:
>> +  - reg
>> +  - ports
>> +
>> +additionalProperties: false
>> +
>> +examples:
>> +  - |
>> +#include 
>> +
>> +oldi_txes {
>> +#address-cells = <1>;
>> +#size-cells = <0>;
>> +oldi: oldi@0 {
>> +reg = <0>;
>> +clocks = <_clks 186 0>;
>> +clock-names = "s_clk";
>> +ti,oldi-io-ctrl = <_oldi_io_ctrl>;
> 
> What bus does this device live on ? Couldn't the I/O register space be
> referenced by the reg property ?.
> 

These registers are a part of the system-controller register space
(ctrl_mmr0). The whole register set is owned by the main_conf[0]
devicetree node, with sub-nodes pointing to specific regions. That's why
I cannot reference these registers directly.

The IO control node for OLDI will look like this though[1].

[0]:
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/arch/arm64/boot/dts/ti/k3-am62-main.dtsi#n45

[1]:
https://github.com/aradhya07/linux-ab/commit/7d7184fb36dc22c67cc2704fe708e885f300860c


>> +ports {
>> +#address-cells = <1>;
>> +#size-cells = <0>;
>> +port@0 {
>> +reg = <0>;
>> +oldi_in: endpoint {
>> +remote-endpoint = <_out>;
>> +};
>> +};
>> +};
>> +};
>> +};
>> +
> 

[ ... ]

-- 
Regards
Aradhya


Re: [PATCH 4/4] drm/tidss: Add OLDI bridge support

2024-05-12 Thread Aradhya Bhatia
Hi Francesco,

On 12/05/24 17:18, Francesco Dolcini wrote:
> Hello Aradhya, thanks for you patch, I should be able to test your patch on my
> hardware in the coming days.

That's appreciated. Thank you! =)

> 
> On Sun, May 12, 2024 at 01:00:55AM +0530, Aradhya Bhatia wrote:
>> Up till now, the OLDI support in tidss was integrated within the tidss dispc.
>> This was fine till the OLDI was one-to-mapped with the DSS video-port (VP).
>> The AM62 and AM62P SoCs have 2 OLDI TXes that can support dual-lvds / 
>> lvds-clone
>> modes.
>>
>> Add OLDI TXes as separate DRM bridge entities to better support the new LVDS
>> configurations.
>>
>> Signed-off-by: Aradhya Bhatia 
>> ---
>>  drivers/gpu/drm/tidss/Makefile  |   3 +-
>>  drivers/gpu/drm/tidss/tidss_dispc.c |  11 +-
>>  drivers/gpu/drm/tidss/tidss_dispc.h |   4 +
>>  drivers/gpu/drm/tidss/tidss_drv.c   |  13 +-
>>  drivers/gpu/drm/tidss/tidss_drv.h   |   4 +
>>  drivers/gpu/drm/tidss/tidss_oldi.c  | 568 
>>  drivers/gpu/drm/tidss/tidss_oldi.h  |  73 
>>  7 files changed, 673 insertions(+), 3 deletions(-)
>>  create mode 100644 drivers/gpu/drm/tidss/tidss_oldi.c
>>  create mode 100644 drivers/gpu/drm/tidss/tidss_oldi.h
>>
>> diff --git a/drivers/gpu/drm/tidss/tidss_drv.c 
>> b/drivers/gpu/drm/tidss/tidss_drv.c
>> index d15f836dca95..fd90e8498cc2 100644
>> --- a/drivers/gpu/drm/tidss/tidss_drv.c
>> +++ b/drivers/gpu/drm/tidss/tidss_drv.c
>> @@ -23,6 +23,7 @@
>>  #include "tidss_drv.h"
>>  #include "tidss_kms.h"
>>  #include "tidss_irq.h"
>> +#include "tidss_oldi.h"
>>  
>>  /* Power management */
>>  
>> @@ -140,10 +141,17 @@ static int tidss_probe(struct platform_device *pdev)
>>  
>>  spin_lock_init(>wait_lock);
>>  
>> +ret = tidss_oldi_init(tidss);
>> +if (ret) {
>> +if (ret != -EPROBE_DEFER)
>> +dev_err(dev, "failed to init OLDI (%d)\n", ret);
>> +return ret;
>> +}
> 
> return dev_err_probe()
> 
>> diff --git a/drivers/gpu/drm/tidss/tidss_oldi.c 
>> b/drivers/gpu/drm/tidss/tidss_oldi.c
>> new file mode 100644
>> index ..fd96ca815542
>> --- /dev/null
>> +++ b/drivers/gpu/drm/tidss/tidss_oldi.c
>> @@ -0,0 +1,568 @@
> 
> ...
> 
>> +ret = drm_of_find_panel_or_bridge(child, OLDI_OURPUT_PORT, -1,
>> +  , );
>> +if (ret) {
>> +/*
>> + * 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.
>> + */
>> +if (ret != -EPROBE_DEFER)
>> +dev_err(tidss->dev,
>> +"no panel/bridge for OLDI%d. Error 
>> %d\n",
>> +oldi_instance, ret);
> 
> just dev_err_probe
> 
>> +goto err_put_node;
>> +}
> 
> ...
> 
>> +if (IS_ERR(oldi->io_ctrl)) {
>> +dev_err(oldi->dev,
>> +"%s: oldi%d syscon_regmap_lookup_by_phandle 
>> failed %ld\n",
>> +   __func__, oldi_instance, PTR_ERR(oldi->io_ctrl));
>> +ret = PTR_ERR(oldi->io_ctrl);
> 
> dev_err_probe 
> 
>> +goto err_put_node;
>> +}
>> +
>> +oldi->s_clk = of_clk_get_by_name(child, "s_clk");
>> +if (IS_ERR(oldi->s_clk)) {
>> +dev_err(oldi->dev,
>> +"%s: oldi%d Failed to get s_clk: %ld\n",
>> +__func__, oldi_instance, PTR_ERR(oldi->s_clk));
>> +ret = PTR_ERR(oldi->s_clk);
> 
> dev_err_probe

Got it. Will update in all the 4 places.

> 
> In general, in this function, sometime you print an error and goto
> err_put_node, sometime you just goto err_put_node.  Not sure what's the
> rationale on this.

There hasn't been any real logic behind the prints, except that I have
added them whenever there was something (specifc) to be explained. Other
times, for example, if the error is -ENOM

[PATCH 1/4] dt-bindings: display: ti,am65x-dss: Minor Cleanup

2024-05-11 Thread Aradhya Bhatia
Reduce tab size from 8 spaces to 4 spaces to make the bindings
consistent, and easy to expand.

Signed-off-by: Aradhya Bhatia 
---
 .../bindings/display/ti/ti,am65x-dss.yaml | 54 +--
 1 file changed, 27 insertions(+), 27 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml 
b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
index 55e3e490d0e6..399d68986326 100644
--- a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
+++ b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
@@ -142,32 +142,32 @@ examples:
 #include 
 
 dss: dss@4a0 {
-compatible = "ti,am65x-dss";
-reg =   <0x04a0 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 = <_oldi_io_ctrl>;
-power-domains = <_pds 67 TI_SCI_PD_EXCLUSIVE>;
-clocks =<_clks 67 1>,
-<_clks 216 1>,
-<_clks 67 2>;
-clock-names = "fck", "vp1", "vp2";
-interrupts = ;
-ports {
-#address-cells = <1>;
-#size-cells = <0>;
-port@0 {
-reg = <0>;
-oldi_out0: endpoint {
-remote-endpoint = <_in0>;
-};
-};
+compatible = "ti,am65x-dss";
+reg = <0x04a0 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 = <_oldi_io_ctrl>;
+power-domains = <_pds 67 TI_SCI_PD_EXCLUSIVE>;
+clocks =<_clks 67 1>,
+<_clks 216 1>,
+<_clks 67 2>;
+clock-names = "fck", "vp1", "vp2";
+interrupts = ;
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+reg = <0>;
+oldi_out0: endpoint {
+remote-endpoint = <_in0>;
+};
 };
+};
 };
-- 
2.34.1



[PATCH 4/4] drm/tidss: Add OLDI bridge support

2024-05-11 Thread Aradhya Bhatia
Up till now, the OLDI support in tidss was integrated within the tidss dispc.
This was fine till the OLDI was one-to-mapped with the DSS video-port (VP).
The AM62 and AM62P SoCs have 2 OLDI TXes that can support dual-lvds / lvds-clone
modes.

Add OLDI TXes as separate DRM bridge entities to better support the new LVDS
configurations.

Signed-off-by: Aradhya Bhatia 
---
Note:

The OLDI configuration should happen before the video-port configuration takes
place in tidss_crtc_atomic_enable hook. I have posted a patch allowing DRM
bridges to get enabled before the CRTC of that bridge is enabled[0]. This patch
uses the bridge hooks introduced in [0], and hence will not compile without [0].

[0]: Dependency Patch: Introduce early_enable / late_disable drm bridge APIs
https://lore.kernel.org/all/20240511153051.1355825-7-a-bhat...@ti.com/

---
 drivers/gpu/drm/tidss/Makefile  |   3 +-
 drivers/gpu/drm/tidss/tidss_dispc.c |  11 +-
 drivers/gpu/drm/tidss/tidss_dispc.h |   4 +
 drivers/gpu/drm/tidss/tidss_drv.c   |  13 +-
 drivers/gpu/drm/tidss/tidss_drv.h   |   4 +
 drivers/gpu/drm/tidss/tidss_oldi.c  | 568 
 drivers/gpu/drm/tidss/tidss_oldi.h  |  73 
 7 files changed, 673 insertions(+), 3 deletions(-)
 create mode 100644 drivers/gpu/drm/tidss/tidss_oldi.c
 create mode 100644 drivers/gpu/drm/tidss/tidss_oldi.h

diff --git a/drivers/gpu/drm/tidss/Makefile b/drivers/gpu/drm/tidss/Makefile
index 312645271014..b6d6becf1683 100644
--- a/drivers/gpu/drm/tidss/Makefile
+++ b/drivers/gpu/drm/tidss/Makefile
@@ -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
diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c 
b/drivers/gpu/drm/tidss/tidss_dispc.c
index 1ad711f8d2a8..4961da3989c0 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc.c
+++ b/drivers/gpu/drm/tidss/tidss_dispc.c
@@ -466,6 +466,16 @@ static u32 dispc_vp_read(struct dispc_device *dispc, u32 
hw_videoport, u16 reg)
return ioread32(base + reg);
 }
 
+u32 tidss_get_status(struct tidss_device *tidss)
+{
+   return dispc_read(tidss->dispc, DSS_SYSSTATUS);
+}
+
+void tidss_configure_oldi(struct tidss_device *tidss, u32 hw_videoport, u32 
val)
+{
+   return dispc_vp_write(tidss->dispc, hw_videoport, 
DISPC_VP_DSS_OLDI_CFG, val);
+}
+
 /*
  * TRM gives bitfields as start:end, where start is the higher bit
  * number. For example 7:0
@@ -1310,7 +1320,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;
diff --git a/drivers/gpu/drm/tidss/tidss_dispc.h 
b/drivers/gpu/drm/tidss/tidss_dispc.h
index 086327d51a90..800a73457aff 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc.h
+++ b/drivers/gpu/drm/tidss/tidss_dispc.h
@@ -94,6 +94,10 @@ extern const struct dispc_features dispc_am62a7_feats;
 extern const struct dispc_features dispc_am65x_feats;
 extern const struct dispc_features dispc_j721e_feats;
 
+u32 tidss_get_status(struct tidss_device *tidss);
+void tidss_configure_oldi(struct tidss_device *tidss, u32 hw_videoport, u32 
val);
+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);
 
diff --git a/drivers/gpu/drm/tidss/tidss_drv.c 
b/drivers/gpu/drm/tidss/tidss_drv.c
index d15f836dca95..fd90e8498cc2 100644
--- a/drivers/gpu/drm/tidss/tidss_drv.c
+++ b/drivers/gpu/drm/tidss/tidss_drv.c
@@ -23,6 +23,7 @@
 #include "tidss_drv.h"
 #include "tidss_kms.h"
 #include "tidss_irq.h"
+#include "tidss_oldi.h"
 
 /* Power management */
 
@@ -140,10 +141,17 @@ static int tidss_probe(struct platform_device *pdev)
 
spin_lock_init(>wait_lock);
 
+   ret = tidss_oldi_init(tidss);
+   if (ret) {
+   if (ret != -EPROBE_DEFER)
+   dev_err(dev, "failed to init OLDI (%d)\n", ret);
+   return ret;
+   }
+
ret = dispc_init(tidss);
if (ret) {
dev_err(dev, "failed to initialize dispc: %d\n", ret);
-   return ret;
+   goto err_oldi_deinit;
}
 
pm_runtime_enable(dev);
@@ -202,6 +210,9 @@ static int tidss_probe(struct platform_device *pdev)
pm_runtime_dont_use_autosuspend(dev);
pm_runtime_disable(dev);
 
+err_oldi_deinit:
+   tidss_oldi_deinit(tidss);
+
return ret;
 }
 
diff --git a/drivers/gpu/drm/tidss/tidss_drv.h 
b/drivers/gpu/drm/tidss/tidss_drv.h
index d7f27b0b0315..4ccdc177

[PATCH 0/4] drm/tidss: Add OLDI bridge support

2024-05-11 Thread Aradhya Bhatia
Hello all,

This patch series add support for the dual OLDI TXes supported in Texas
Instruments' AM62x and AM62Px family of SoCs. The OLDI TXes support single-lvds,
lvds-clone, and dual-lvds modes. These have now been represented through DRM
bridges within TI-DSS.

The OLDI configuration should happen before the video-port configuration takes
place in tidss_crtc_atomic_enable hook. I have posted a patch allowing DRM
bridges to get enabled before the CRTC of that bridge is enabled[0]. The patch
4/4 of this series uses the bridge hooks introduced in [0], and hence will not
compile without [0].

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 AM625 DSS was kept (and eventually
merged)[2].

These patches have been tested on AM625 based platforms, SK-AM625 EVM with a
Microptis dual-lvds panel (SK-LCD1), and Beagleplay with a Lincolntech dual-lvds
panel (LCD-185T). The patches with complete support including the expected
devicetree configuration of the OLDI TXes can be found in the
"next_oldi_finals-v1-tests" branch of my github fork[3].

Thanks,
Aradhya

[0]: Dependency Patch: Introduce early_enable / late_disable drm bridge APIs
https://lore.kernel.org/all/20240511153051.1355825-7-a-bhat...@ti.com/

[1]: AM62 OLDI Series - v7
https://lore.kernel.org/all/20230125113529.13952-1-a-bhat...@ti.com/

[2]: AM62 DSS Series - v9
https://lore.kernel.org/all/20230616150900.6617-1-a-bhat...@ti.com/

[3]: GitHub Fork for OLDI tests
https://github.com/aradhya07/linux-ab/tree/next_oldi_finals-v1-tests


Aradhya Bhatia (4):
  dt-bindings: display: ti,am65x-dss: Minor Cleanup
  dt-bindings: display: ti: Add schema for AM625 OLDI Transmitter
  dt-bindings: display: ti,am65x-dss: Add OLDI properties for AM625 DSS
  drm/tidss: Add OLDI bridge support

 .../bindings/display/ti/ti,am625-oldi.yaml| 153 +
 .../bindings/display/ti/ti,am65x-dss.yaml | 178 +-
 MAINTAINERS   |   1 +
 drivers/gpu/drm/tidss/Makefile|   3 +-
 drivers/gpu/drm/tidss/tidss_dispc.c   |  11 +-
 drivers/gpu/drm/tidss/tidss_dispc.h   |   4 +
 drivers/gpu/drm/tidss/tidss_drv.c |  13 +-
 drivers/gpu/drm/tidss/tidss_drv.h |   4 +
 drivers/gpu/drm/tidss/tidss_oldi.c| 568 ++
 drivers/gpu/drm/tidss/tidss_oldi.h|  73 +++
 10 files changed, 983 insertions(+), 25 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: 75fa778d74b786a1608d55d655d42b480a6fa8bd
-- 
2.34.1



[PATCH 3/4] dt-bindings: display: ti, am65x-dss: Add OLDI properties for AM625 DSS

2024-05-11 Thread Aradhya Bhatia
The DSS in AM625 SoC has 2 OLDI TXes. Refer the OLDI schema to add the
properties.

Signed-off-by: Aradhya Bhatia 
---
 .../bindings/display/ti/ti,am65x-dss.yaml | 136 +-
 1 file changed, 135 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml 
b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
index 399d68986326..4aa2de59b32b 100644
--- a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
+++ b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
@@ -85,12 +85,30 @@ properties:
 
 properties:
   port@0:
-$ref: /schemas/graph.yaml#/properties/port
+$ref: /schemas/graph.yaml#/$defs/port-base
 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
 
   port@1:
 $ref: /schemas/graph.yaml#/properties/port
@@ -112,6 +130,22 @@ properties:
   Input memory (from main memory to dispc) bandwidth limit in
   bytes per second
 
+  oldi-txes:
+type: object
+properties:
+  "#address-cells":
+const: 1
+
+  "#size-cells":
+const: 0
+
+patternProperties:
+  '^oldi_tx@[0-1]$':
+type: object
+$ref: ti,am625-oldi.yaml#
+unevaluatedProperties: false
+description: OLDI transmitters connected to the DSS VPs
+
 allOf:
   - if:
   properties:
@@ -123,6 +157,19 @@ allOf:
 ports:
   properties:
 port@0: false
+oldi_txes: false
+
+  - if:
+  properties:
+compatible:
+  contains:
+const: ti,am65x-dss
+then:
+  properties:
+oldi_txes: false
+port@0:
+  properties:
+endpoint@1: false
 
 required:
   - compatible
@@ -171,3 +218,90 @@ examples:
 };
 };
 };
+
+  - |
+#include 
+#include 
+#include 
+
+bus {
+#address-cells = <2>;
+#size-cells = <2>;
+dss1: dss@3020 {
+compatible = "ti,am625-dss";
+reg = <0x00 0x3020 0x00 0x1000>, /* common */
+  <0x00 0x30202000 0x00 0x1000>, /* vidl1 */
+  <0x00 0x30206000 0x00 0x1000>, /* vid */
+  <0x00 0x30207000 0x00 0x1000>, /* ovr1 */
+  <0x00 0x30208000 0x00 0x1000>, /* ovr2 */
+  <0x00 0x3020a000 0x00 0x1000>, /* vp1 */
+  <0x00 0x3020b000 0x00 0x1000>, /* vp2 */
+  <0x00 0x30201000 0x00 0x1000>; /* common1 */
+reg-names = "common", "vidl1", "vid",
+"ovr1", "ovr2", "vp1", "vp2", "common1";
+power-domains = <_pds 186 TI_SCI_PD_EXCLUSIVE>;
+clocks =<_clks 186 6>,
+<_clock>,
+<_clks 186 2>;
+clock-names = "fck", "vp1", "vp2";
+interrupts = ;
+oldi-txes {
+#address-cells = <1>;
+#size-cells = <0>;
+oldi0: oldi@0 {
+reg = <0>;
+clocks = <_clks 186 0>;
+clock-names = "s_clk";
+ti,companion-oldi = <>;
+ti,oldi-io-ctrl = <_oldi_io_ctrl>;
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+reg = <0>;
+oldi0_in: endpoint {
+remote-endpoint = <_out0>;
+};
+};
+};
+};
+oldi1: oldi@1 {
+reg = <1>;
+ti,secondary-oldi;
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+  

[PATCH 2/4] dt-bindings: display: ti: Add schema for AM625 OLDI Transmitter

2024-05-11 Thread Aradhya Bhatia
Add devicetree binding schema for AM625 OLDI Transmitters.

Signed-off-by: Aradhya Bhatia 
---
 .../bindings/display/ti/ti,am625-oldi.yaml| 153 ++
 MAINTAINERS   |   1 +
 2 files changed, 154 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml

diff --git a/Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml 
b/Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml
new file mode 100644
index ..0a96e600bc0b
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/ti/ti,am625-oldi.yaml
@@ -0,0 +1,153 @@
+# 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 
+  - Aradhya Bhatia 
+
+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: s_clk
+
+  ti,companion-oldi:
+$ref: /schemas/types.yaml#/definitions/phandle
+description:
+  phandle to companion OLDI transmitter. This property is mandatory for the
+  primarty OLDI TX if the OLDI TXes are expected to work either in 
dual-lvds
+  mode or in clone mode. This property should point to the secondary OLDI
+  TX.
+
+  ti,secondary-oldi:
+type: boolean
+description: Boolean property to mark an OLDI TX as secondary node.
+
+  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. This property is needed for OLDI interface to work.
+
+  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
+
+allOf:
+  - if:
+  properties:
+ti,secondary-oldi: true
+then:
+  properties:
+ti,companion-oldi: false
+ti,oldi-io-ctrl: false
+clocks: false
+clock-names: false
+
+else:
+  required:
+- ti,oldi-io-ctrl
+- clocks
+- clock-names
+
+required:
+  - reg
+  - ports
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+
+oldi_txes {
+#address-cells = <1>;
+#size-cells = <0>;
+oldi: oldi@0 {
+reg = <0>;
+clocks = <_clks 186 0>;
+clock-names = "s_clk";
+ti,oldi-io-ctrl = <_oldi_io_ctrl>;
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+reg = <0>;
+oldi_in: endpoint {
+remote-endpoint = <_out>;
+};
+};
+};
+};
+};
+
+  - |
+#include 
+
+oldi_txes {
+#address-cells = <1>;
+#size-cells = <0>;
+oldi0: oldi@0 {
+reg = <0>;
+clocks = <_clks 186 0>;
+clock-names = "s_clk";
+ti,companion-oldi = <>;
+ti,oldi-io-ctrl = <_oldi_io_ctrl>;
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+reg = <0>;
+oldi0_in: endpoint {
+remote-endpoint = <_out0>;
+};
+};
+};
+};
+oldi1: oldi@1 {
+reg = <1>;
+ti,secondary-oldi;
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+reg = <0>;
+oldi1_in: endpoint {
+remote-endpoint = <_out1>;
+};
+};
+};
+};
+};
+
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index c675fc296b19..4426c4d41a7f 100644
--- a/MAINTAINERS
+++ b/MAINTAINE

[PATCH 7/7] drm/bridge: cdns-dsi: Implement early_enable and late_disable

2024-05-11 Thread Aradhya Bhatia
The cdsn-dsi controller requires that it be turned on completely before
the input DPI's source has begun streaming.

Since tidss's videoport starts streaming via crtc enable hooks, we need
cdns-dsi to be up and running before that. Hence, use the early_enable
and late_disable hooks to get pass the color issues.

Signed-off-by: Aradhya Bhatia 
---
 .../gpu/drm/bridge/cadence/cdns-dsi-core.c| 36 ---
 1 file changed, 6 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index c7519d18e94f..53fa20720089 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -656,8 +656,8 @@ cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge,
return MODE_OK;
 }
 
-static void cdns_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
-  struct drm_bridge_state 
*old_bridge_state)
+static void cdns_dsi_bridge_atomic_late_disable(struct drm_bridge *bridge,
+   struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -677,15 +677,6 @@ static void cdns_dsi_bridge_atomic_disable(struct 
drm_bridge *bridge,
pm_runtime_put(dsi->base.dev);
 }
 
-static void cdns_dsi_bridge_post_disable(struct drm_bridge *bridge,
-struct drm_bridge_state 
*old_bridge_state)
-{
-   struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
-   struct cdns_dsi *dsi = input_to_dsi(input);
-
-   pm_runtime_put(dsi->base.dev);
-}
-
 static void cdns_dsi_hs_init(struct cdns_dsi *dsi)
 {
struct cdns_dsi_output *output = >output;
@@ -755,8 +746,8 @@ static void cdns_dsi_init_link(struct cdns_dsi *dsi)
dsi->link_initialized = true;
 }
 
-static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
- struct drm_bridge_state 
*old_bridge_state)
+static void cdns_dsi_bridge_atomic_early_enable(struct drm_bridge *bridge,
+   struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -907,19 +898,6 @@ static void cdns_dsi_bridge_atomic_enable(struct 
drm_bridge *bridge,
writel(tmp, dsi->regs + MCTL_MAIN_EN);
 }
 
-static void cdns_dsi_bridge_pre_enable(struct drm_bridge *bridge,
-  struct drm_bridge_state 
*old_bridge_state)
-{
-   struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
-   struct cdns_dsi *dsi = input_to_dsi(input);
-
-   if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
-   return;
-
-   cdns_dsi_init_link(dsi);
-   cdns_dsi_hs_init(dsi);
-}
-
 static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
   struct drm_bridge_state 
*bridge_state,
   struct drm_crtc_state 
*crtc_state,
@@ -968,10 +946,8 @@ static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct 
drm_bridge *bridge,
 static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
.attach = cdns_dsi_bridge_attach,
.mode_valid = cdns_dsi_bridge_mode_valid,
-   .atomic_disable = cdns_dsi_bridge_atomic_disable,
-   .atomic_pre_enable = cdns_dsi_bridge_atomic_pre_enable,
-   .atomic_enable = cdns_dsi_bridge_atomic_enable,
-   .atomic_post_disable = cdns_dsi_bridge_atomic_post_disable,
+   .atomic_early_enable = cdns_dsi_bridge_atomic_early_enable,
+   .atomic_late_disable = cdns_dsi_bridge_atomic_late_disable,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
.atomic_reset = drm_atomic_helper_bridge_reset,
-- 
2.34.1



[PATCH 4/7] drm/bridge: cdns-dsi: Reset the DCS write FIFO

2024-05-11 Thread Aradhya Bhatia
Allow the DCS Write FIFO in the cdns-dsi controller to reset before any
DCS packet is transmitted to the DSI sink device.

Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 05d2f4cc50da..87fdd07ca0bc 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -1037,6 +1037,9 @@ static ssize_t cdns_dsi_transfer(struct mipi_dsi_host 
*host,
 
cdns_dsi_init_link(dsi);
 
+   /* Reset the DCS Write FIFO */
+   writel(0x00, dsi->regs + DIRECT_CMD_FIFO_RST);
+
ret = mipi_dsi_create_packet(, msg);
if (ret)
goto out;
-- 
2.34.1



[PATCH 5/7] drm/bridge: cdns-dsi: Support atomic bridge APIs

2024-05-11 Thread Aradhya Bhatia
Change the existing (and deparacated) bridge hooks, to the bridge
atomic APIs.

Add drm helpers for duplicate_state, destroy_state, and bridge_reset
bridge hooks.

Further add support for the input format negotiation hook.

Signed-off-by: Aradhya Bhatia 
---
 .../gpu/drm/bridge/cadence/cdns-dsi-core.c| 70 ---
 1 file changed, 62 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 87fdd07ca0bc..c7519d18e94f 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -655,7 +656,8 @@ cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge,
return MODE_OK;
 }
 
-static void cdns_dsi_bridge_disable(struct drm_bridge *bridge)
+static void cdns_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
+  struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -675,7 +677,8 @@ static void cdns_dsi_bridge_disable(struct drm_bridge 
*bridge)
pm_runtime_put(dsi->base.dev);
 }
 
-static void cdns_dsi_bridge_post_disable(struct drm_bridge *bridge)
+static void cdns_dsi_bridge_post_disable(struct drm_bridge *bridge,
+struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -752,7 +755,8 @@ static void cdns_dsi_init_link(struct cdns_dsi *dsi)
dsi->link_initialized = true;
 }
 
-static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
+static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -903,7 +907,8 @@ static void cdns_dsi_bridge_enable(struct drm_bridge 
*bridge)
writel(tmp, dsi->regs + MCTL_MAIN_EN);
 }
 
-static void cdns_dsi_bridge_pre_enable(struct drm_bridge *bridge)
+static void cdns_dsi_bridge_pre_enable(struct drm_bridge *bridge,
+  struct drm_bridge_state 
*old_bridge_state)
 {
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);
@@ -915,13 +920,62 @@ static void cdns_dsi_bridge_pre_enable(struct drm_bridge 
*bridge)
cdns_dsi_hs_init(dsi);
 }
 
+static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
+  struct drm_bridge_state 
*bridge_state,
+  struct drm_crtc_state 
*crtc_state,
+  struct drm_connector_state 
*conn_state,
+  u32 output_fmt,
+  unsigned int *num_input_fmts)
+{
+   struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
+   struct cdns_dsi *dsi = input_to_dsi(input);
+   struct cdns_dsi_output *output = >output;
+   u32 *input_fmts;
+
+   *num_input_fmts = 0;
+
+   input_fmts = kzalloc(sizeof(*input_fmts), GFP_KERNEL);
+   if (!input_fmts)
+   return NULL;
+
+   switch (output->dev->format) {
+   case MIPI_DSI_FMT_RGB888:
+   input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;
+   break;
+
+   case MIPI_DSI_FMT_RGB666:
+   input_fmts[0] = MEDIA_BUS_FMT_RGB666_1X24_CPADHI;
+   break;
+
+   case MIPI_DSI_FMT_RGB666_PACKED:
+   input_fmts[0] = MEDIA_BUS_FMT_RGB666_1X18;
+   break;
+
+   case MIPI_DSI_FMT_RGB565:
+   input_fmts[0] = MEDIA_BUS_FMT_RGB565_1X16;
+   break;
+
+   default:
+   /* Unsupported DSI Format */
+   return NULL;
+   }
+
+   *num_input_fmts = 1;
+
+   return input_fmts;
+}
+
 static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
.attach = cdns_dsi_bridge_attach,
.mode_valid = cdns_dsi_bridge_mode_valid,
-   .disable = cdns_dsi_bridge_disable,
-   .pre_enable = cdns_dsi_bridge_pre_enable,
-   .enable = cdns_dsi_bridge_enable,
-   .post_disable = cdns_dsi_bridge_post_disable,
+   .atomic_disable = cdns_dsi_bridge_atomic_disable,
+   .atomic_pre_enable = cdns_dsi_bridge_atomic_pre_enable,
+   .atomic_enable = cdns_dsi_bridge_atomic_enable,
+   .atomic_post_disable = cdns_dsi_bridge_atomic_post_disable,
+   .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+   .atomic_destroy_state = drm_atomic_helper_br

[PATCH 1/7] drm/tidss: Add CRTC mode_fixup

2024-05-11 Thread Aradhya Bhatia
Add support for mode_fixup for the tidss CRTC.

Some bridges like the cdns-dsi consume the crtc_* timing parameters for
programming the blanking values. Allow for the normal timing parameters
to get copied to crtc_* timing params.

Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/tidss/tidss_crtc.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/gpu/drm/tidss/tidss_crtc.c 
b/drivers/gpu/drm/tidss/tidss_crtc.c
index 94f8e3178df5..797ef53d9ad2 100644
--- a/drivers/gpu/drm/tidss/tidss_crtc.c
+++ b/drivers/gpu/drm/tidss/tidss_crtc.c
@@ -309,12 +309,23 @@ enum drm_mode_status tidss_crtc_mode_valid(struct 
drm_crtc *crtc,
return dispc_vp_mode_valid(tidss->dispc, tcrtc->hw_videoport, mode);
 }
 
+static
+bool tidss_crtc_mode_fixup(struct drm_crtc *crtc,
+  const struct drm_display_mode *mode,
+  struct drm_display_mode *adjusted_mode)
+{
+   drm_mode_set_crtcinfo(adjusted_mode, 0);
+
+   return true;
+}
+
 static const struct drm_crtc_helper_funcs tidss_crtc_helper_funcs = {
.atomic_check = tidss_crtc_atomic_check,
.atomic_flush = tidss_crtc_atomic_flush,
.atomic_enable = tidss_crtc_atomic_enable,
.atomic_disable = tidss_crtc_atomic_disable,
 
+   .mode_fixup = tidss_crtc_mode_fixup,
.mode_valid = tidss_crtc_mode_valid,
 };
 
-- 
2.34.1



[PATCH 2/7] drm/bridge: cdns-dsi: Fix minor bugs

2024-05-11 Thread Aradhya Bhatia
Update the Phy initialized state to "not initialized" when the driver
(and the hardware by extension) gets suspended. This will allow the Phy
to get initialized again after resume.

Fix the OF node that gets passed to find the next available bridge in
the display pipeline.

Fix the order of DSI Link and DSI Phy inits. The link init needs to
happen before the Phy is initialized, so the Phy can lock on the
incoming PLL reference clock. If this doesn't happen, the Phy cannot
lock (until DSI Link is init later on). This causes a warning dump
during the kernel boot.

Allow the D-Phy config checks to use mode->clock instead of
mode->crtc_clock during mode_valid checks, like everywhere else in the
driver.

Fixes: e19233955d9e ("drm/bridge: Add Cadence DSI driver")
Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 7457d38622b0..557b037bbc67 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -574,7 +574,7 @@ static int cdns_dsi_check_conf(struct cdns_dsi *dsi,
if (ret)
return ret;
 
-   phy_mipi_dphy_get_default_config(mode->crtc_clock * 1000,
+   phy_mipi_dphy_get_default_config((mode_valid_check ? mode->clock : 
mode->crtc_clock) * 1000,
 
mipi_dsi_pixel_format_to_bpp(output->dev->format),
 nlanes, phy_cfg);
 
@@ -775,8 +775,8 @@ static void cdns_dsi_bridge_enable(struct drm_bridge 
*bridge)
 
WARN_ON_ONCE(cdns_dsi_check_conf(dsi, mode, _cfg, false));
 
-   cdns_dsi_hs_init(dsi);
cdns_dsi_init_link(dsi);
+   cdns_dsi_hs_init(dsi);
 
writel(HBP_LEN(dsi_cfg.hbp) | HSA_LEN(dsi_cfg.hsa),
   dsi->regs + VID_HSIZE1);
@@ -952,7 +952,7 @@ static int cdns_dsi_attach(struct mipi_dsi_host *host,
bridge = drm_panel_bridge_add_typed(panel,
DRM_MODE_CONNECTOR_DSI);
} else {
-   bridge = of_drm_find_bridge(dev->dev.of_node);
+   bridge = of_drm_find_bridge(np);
if (!bridge)
bridge = ERR_PTR(-EINVAL);
}
@@ -1153,6 +1153,7 @@ static int __maybe_unused cdns_dsi_suspend(struct device 
*dev)
clk_disable_unprepare(dsi->dsi_p_clk);
reset_control_assert(dsi->dsi_p_rst);
dsi->link_initialized = false;
+   dsi->phy_initialized = false;
return 0;
 }
 
-- 
2.34.1



[PATCH 6/7] drm/bridge: Introduce early_enable and late disable

2024-05-11 Thread Aradhya Bhatia
With the existing pre_enable and enable function hooks, the order of
enable of display elements looks as follows,

crtc_enable -> bridge[n]_pre_enable -> ... -> bridge[1]_pre_enable ->
encoder_enable -> bridge[1]_enable -> ... -> bridge[n]_enable

and vice versa for the disable.

Some bridges need to be up and running before and after their source
gets enabled and has run. In some case, that source is a display unit,
controlled as part of _crtc.

For those bridges, add support for early_enable and late_disable
function hooks.

Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/drm_atomic_helper.c | 67 +++
 drivers/gpu/drm/drm_bridge.c| 84 +
 include/drm/drm_bridge.h| 73 +
 3 files changed, 224 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index fb97b51b38f1..396bb83e4296 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1234,6 +1234,49 @@ disable_outputs(struct drm_device *dev, struct 
drm_atomic_state *old_state)
if (ret == 0)
drm_crtc_vblank_put(crtc);
}
+
+   for_each_oldnew_connector_in_state(old_state, connector, old_conn_state,
+  new_conn_state, i) {
+   struct drm_encoder *encoder;
+   struct drm_bridge *bridge;
+
+   /*
+* Shut down everything that's in the changeset and currently
+* still on. So need to check the old, saved state.
+*/
+   if (!old_conn_state->crtc)
+   continue;
+
+   old_crtc_state = drm_atomic_get_old_crtc_state(old_state, 
old_conn_state->crtc);
+
+   if (new_conn_state->crtc)
+   new_crtc_state = 
drm_atomic_get_new_crtc_state(old_state,
+  
new_conn_state->crtc);
+   else
+   new_crtc_state = NULL;
+
+   if (!crtc_needs_disable(old_crtc_state, new_crtc_state) ||
+   !drm_atomic_crtc_needs_modeset(old_conn_state->crtc->state))
+   continue;
+
+   encoder = old_conn_state->best_encoder;
+
+   /* We shouldn't get this far if we didn't previously have
+* an encoder.. but WARN_ON() rather than explode.
+*/
+   if (WARN_ON(!encoder))
+   continue;
+
+   drm_dbg_atomic(dev, "disabling [ENCODER:%d:%s]\n",
+  encoder->base.id, encoder->name);
+
+   /*
+* Each encoder has at most one connector (since we always steal
+* it away), so we won't call disable hooks twice.
+*/
+   bridge = drm_bridge_chain_get_first_bridge(encoder);
+   drm_atomic_bridge_chain_late_disable(bridge, old_state);
+   }
 }
 
 /**
@@ -1469,6 +1512,30 @@ void drm_atomic_helper_commit_modeset_enables(struct 
drm_device *dev,
struct drm_connector_state *new_conn_state;
int i;
 
+   for_each_new_connector_in_state(old_state, connector, new_conn_state, 
i) {
+   struct drm_encoder *encoder;
+   struct drm_bridge *bridge;
+
+   if (!new_conn_state->best_encoder)
+   continue;
+
+   if (!new_conn_state->crtc->state->active ||
+   !drm_atomic_crtc_needs_modeset(new_conn_state->crtc->state))
+   continue;
+
+   encoder = new_conn_state->best_encoder;
+
+   drm_dbg_atomic(dev, "enabling [ENCODER:%d:%s]\n",
+  encoder->base.id, encoder->name);
+
+   /*
+* Each encoder has at most one connector (since we always steal
+* it away), so we won't call enable hooks twice.
+*/
+   bridge = drm_bridge_chain_get_first_bridge(encoder);
+   drm_atomic_bridge_chain_early_enable(bridge, old_state);
+   }
+
for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, 
new_crtc_state, i) {
const struct drm_crtc_helper_funcs *funcs;
 
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 28abe9aa99ca..b9070f6b3554 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -623,6 +623,50 @@ void drm_atomic_bridge_chain_disable(struct drm_bridge 
*bridge,
 }
 EXPORT_SYMBOL(drm_atomic_bridge_chain_disable);
 
+/**
+ * drm_atomic_bridge_chain_late_disable - disables all bridges in the encoder
+ *   chain after crtc is disabled.
+ * @bridge: bridge control structu

[PATCH 0/7] drm/bridge: cdns-dsi: Fix the color-shift issue

2024-05-11 Thread Aradhya Bhatia
Hello all,

This series provides some crucial fixes and improvements for the Cadence's DSI
TX (cdns-dsi) controller found commonly in Texas Instruments' J7 family of SoCs
as well as in AM62P.

The cdns-dsi bridge consumes the crtc_* timing parameters for programming the
timing parameters. A patch has been added in tidss to make sure the crtc_*
timings get populated.

It further adds support for "early_enable" and "late_disable" DRM bridge hooks.
These hooks are same as the existing "(pre_)enable" and "(post_)disable" hooks,
except that the early_enable hook gets called before the CRTC is even enabled in
the display pipeline and the late_disable hook gets called after the CRTC is
disabled.
The cdns-dsi controller requires to be enabled before the previous entity
enables its stream[0]. It's a strict requirement which, if not followed, causes
the colors to "shift" on the display. Since the previous entity is TIDSS in this
case, which gets enabled via the tidss_crtc hooks, early_enable/late_disable API
in the cdns-dsi bridge is the way to solve the issue.
The early_enable/late_disable APIs also help with the OLDI TXes available on the
AM62/AM62P SoCs, which will be a part of separate series.

This spec also requires the Clock and Data Lanes be ready before the DSI TX
enables its stream[0]. A patch has been added to make the code wait for that to
happen. Going ahead with further DSI (and DSS configuration), while the lanes
are not ready, has been found as another reason for shift in colors.

All these patches have been tested on TI's vendor tree kernel with more devices,
but for the mainline, these patches have been tested with J721E based
BeagleboneAI64 along with a RaspberryPi 7" DSI panel. The extra patches can be
found in the "next_dsi_finals-v1-test_rpi" branch of my github fork[1] for
anyone who would like to test them.

Thanks,
Aradhya


[0]: Section 12.6.5.7.3: Start-up Procesure [For DSI TX controller]
 in TDA4VM Technical Reference Manual https://www.ti.com/lit/zip/spruil1

[1]: https://github.com/aradhya07/linux-ab/tree/next_dsi_finals-v1-test_rpi


Aradhya Bhatia (7):
  drm/tidss: Add CRTC mode_fixup
  drm/bridge: cdns-dsi: Fix minor bugs
  drm/bridge: cdns-dsi: Wait for Clk and Data Lanes to be ready
  drm/bridge: cdns-dsi: Reset the DCS write FIFO
  drm/bridge: cdns-dsi: Support atomic bridge APIs
  drm/bridge: Introduce early_enable and late disable
  drm/bridge: cdns-dsi: Implement early_enable and late_disable

 .../gpu/drm/bridge/cadence/cdns-dsi-core.c| 91 ++-
 drivers/gpu/drm/drm_atomic_helper.c   | 67 ++
 drivers/gpu/drm/drm_bridge.c  | 84 +
 drivers/gpu/drm/tidss/tidss_crtc.c| 11 +++
 include/drm/drm_bridge.h  | 73 +++
 5 files changed, 303 insertions(+), 23 deletions(-)


base-commit: 75fa778d74b786a1608d55d655d42b480a6fa8bd
-- 
2.34.1


[PATCH 3/7] drm/bridge: cdns-dsi: Wait for Clk and Data Lanes to be ready

2024-05-11 Thread Aradhya Bhatia
Once the DSI Link and DSI Phy are initialized, the code needs to wait
for Clk and Data Lanes to be ready, before continuing configuration.
This is in accordance with the DSI Start-up procedure, found in the
Technical Reference Manual of Texas Instrument's J721E SoC[0] which
houses this DSI TX controller.

If the previous bridge (or crtc/encoder) are configured pre-maturely,
the input signal FIFO gets corrupt. This introduces a color-shift on the
display.

Allow the driver to wait for the clk and data lanes to get ready during
DSI enable.

Fixes: e19233955d9e ("drm/bridge: Add Cadence DSI driver")
Signed-off-by: Aradhya Bhatia 
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 557b037bbc67..05d2f4cc50da 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -761,7 +761,7 @@ static void cdns_dsi_bridge_enable(struct drm_bridge 
*bridge)
struct phy_configure_opts_mipi_dphy *phy_cfg = 
>phy_opts.mipi_dphy;
unsigned long tx_byte_period;
struct cdns_dsi_cfg dsi_cfg;
-   u32 tmp, reg_wakeup, div;
+   u32 tmp, reg_wakeup, div, status;
int nlanes;
 
if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
@@ -778,6 +778,17 @@ static void cdns_dsi_bridge_enable(struct drm_bridge 
*bridge)
cdns_dsi_init_link(dsi);
cdns_dsi_hs_init(dsi);
 
+   /*
+* Now that the DSI Link and DSI Phy are initialized,
+* wait for the CLK and Data Lanes to be ready.
+*/
+   tmp = CLK_LANE_RDY;
+   for (int i = 0; i < nlanes; i++)
+   tmp |= DATA_LANE_RDY(i);
+
+   WARN_ON_ONCE(readl_poll_timeout(dsi->regs + MCTL_MAIN_STS, status,
+   status & tmp, 100, 0));
+
writel(HBP_LEN(dsi_cfg.hbp) | HSA_LEN(dsi_cfg.hsa),
   dsi->regs + VID_HSIZE1);
writel(HFP_LEN(dsi_cfg.hfp) | HACT_LEN(dsi_cfg.hact),
-- 
2.34.1



Re: [PATCH v5 0/4] Add common1 region for AM62, AM62A & AM65x

2024-02-16 Thread Aradhya Bhatia



On 16-Feb-24 11:54, Devarsh Thakkar wrote:
> This adds DSS common1 region for respective SoCs supporting it.
> 
> Changelog:
> V2 : Remove do-not-merge tag and add am62a dss common1 reion
> V3 : Add Fixes tag to each commit
> V4 : Add Reviewed-by tag and AM62A SoC TRM Link
> V5 : Split dts patch to separate patches for each SoC
> 
> Devarsh Thakkar (4):
>   dt-bindings: display: ti,am65x-dss: Add support for common1 region
>   arm64: dts: ti: Add common1 register space for AM65x SoC
>   arm64: dts: ti: Add common1 register space for AM62x SoC
>   arm64: dts: ti: Add common1 register space for AM62A SoC

For the series,

Reviewed-by: Aradhya Bhatia 

Regards
Aradhya


> 
>  .../devicetree/bindings/display/ti/ti,am65x-dss.yaml   | 7 +--
>  arch/arm64/boot/dts/ti/k3-am62-main.dtsi   | 5 +++--
>  arch/arm64/boot/dts/ti/k3-am62a-main.dtsi  | 5 +++--
>  arch/arm64/boot/dts/ti/k3-am65-main.dtsi   | 5 +++--
>  4 files changed, 14 insertions(+), 8 deletions(-)
> 


Re: [PATCH v3 1/2] dt-bindings: display: ti,am65x-dss: Add support for common1 region

2024-02-15 Thread Aradhya Bhatia



On 15/02/24 14:02, Devarsh Thakkar wrote:
> TI keystone display subsystem present in AM65 and other SoCs such as AM62
> support two separate register spaces namely "common" and "common1" which
> can be used by two separate hosts to program the display controller as
> described in respective Technical Reference Manuals [1].
> 
> The common1 register space has similar set of configuration registers as
> supported in common register space except the global configuration
> registers which are exclusive to common region.
> 
> This adds binding for "common1" register region too as supported by the
> hardware.
> 
> [1]:
> AM62x TRM:
> https://www.ti.com/lit/pdf/spruiv7 (Section 14.8.9.1 DSS Registers)
> 
> AM65x TRM:
> https://www.ti.com/lit/pdf/spruid7 (Section 12.6.5 DSS Registers)

Can you add the TRM link for AM62A too?

With that sorted,

Reviewed-by: Aradhya Bhatia 

> 
> Fixes: 2d8730f1021f ("dt-bindings: display: ti,am65x-dss: Add dt-schema yaml 
> binding")
> Signed-off-by: Devarsh Thakkar 
> Acked-by: Conor Dooley > ---
> V2: Add Acked-by tag
> V3: Add Fixes tag
> ---
>  .../devicetree/bindings/display/ti/ti,am65x-dss.yaml   | 7 +--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml 
> b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
> index b6767ef0d24d..55e3e490d0e6 100644
> --- a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
> +++ b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
> @@ -37,6 +37,7 @@ properties:
>- description: OVR2 overlay manager for vp2
>- description: VP1 video port 1
>- description: VP2 video port 2
> +  - description: common1 DSS register area
>  
>reg-names:
>  items:
> @@ -47,6 +48,7 @@ properties:
>- const: ovr2
>- const: vp1
>- const: vp2
> +  - const: common1
>  
>clocks:
>  items:
> @@ -147,9 +149,10 @@ examples:
>  <0x04a07000 0x1000>, /* ovr1 */
>  <0x04a08000 0x1000>, /* ovr2 */
>  <0x04a0a000 0x1000>, /* vp1 */
> -<0x04a0b000 0x1000>; /* vp2 */
> +<0x04a0b000 0x1000>, /* vp2 */
> +<0x04a01000 0x1000>; /* common1 */
>  reg-names = "common", "vidl1", "vid",
> -"ovr1", "ovr2", "vp1", "vp2";
> +"ovr1", "ovr2", "vp1", "vp2", "common1";
>  ti,am65x-oldi-io-ctrl = <_oldi_io_ctrl>;
>  power-domains = <_pds 67 TI_SCI_PD_EXCLUSIVE>;
>  clocks =<_clks 67 1>,


Re: [PATCH 2/2] drm/tidss: Fix sync-lost issue with two displays

2024-02-15 Thread Aradhya Bhatia



On 13/02/24 13:46, Tomi Valkeinen wrote:
> A sync lost issue can be observed with two displays, when moving a plane
> from one disabled display to an another disabled display, and then
> enabling the display to which the plane was moved to. The exact
> requirements for this to trigger are not clear.
> 
> It looks like the issue is that the layers are left enabled in the first
> display's OVR registers. Even if the corresponding VP is disabled, it
> still causes an issue, as if the disabled VP and its OVR would still be
> in use, leading to the same VID being used by two OVRs. However, this is
> just speculation based on testing the DSS behavior.
> 
> Experimentation shows that as a workaround, we can disable all the
> layers in the OVR when disabling a VP. There should be no downside to
> this, as the OVR is anyway effectively disabled if its VP is disabled,
> and it seems to solve the sync lost issue.
> 
> However, there may be a bigger issue in play here, related to J721e
> erratum i2097 ("DSS: Disabling a Layer Connected to Overlay May Result
> in Synclost During the Next Frame"). Experimentation also shows that the
> OVR's CHANNELIN field has similar issue. So we may need to revisit this
> when we find out more about the core issue.
> 
> Signed-off-by: Tomi Valkeinen 
> Fixes: 32a1795f57ee ("drm/tidss: New driver for TI Keystone platform Display 
> SubSystem")

Reviewed-by: Aradhya Bhatia 

> ---
>  drivers/gpu/drm/tidss/tidss_crtc.c | 10 ++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/drivers/gpu/drm/tidss/tidss_crtc.c 
> b/drivers/gpu/drm/tidss/tidss_crtc.c
> index 5f838980c7a1..94f8e3178df5 100644
> --- a/drivers/gpu/drm/tidss/tidss_crtc.c
> +++ b/drivers/gpu/drm/tidss/tidss_crtc.c
> @@ -265,6 +265,16 @@ static void tidss_crtc_atomic_disable(struct drm_crtc 
> *crtc,
>  
>   reinit_completion(>framedone_completion);
>  
> + /*
> +  * If a layer is left enabled when the videoport is disabled, and the
> +  * vid pipeline that was used for the layer is taken into use on
> +  * another videoport, the DSS will report sync lost issues. Disable all
> +  * the layers here as a work-around.
> +  */
> + for (u32 layer = 0; layer < tidss->feat->num_planes; layer++)
> + dispc_ovr_enable_layer(tidss->dispc, tcrtc->hw_videoport, layer,
> +false);
> +
>   dispc_vp_disable(tidss->dispc, tcrtc->hw_videoport);
>  
>   if (!wait_for_completion_timeout(>framedone_completion,
> 


Re: [PATCH 1/2] drm/tidss: Fix initial plane zpos values

2024-02-15 Thread Aradhya Bhatia
Tomi, thank you for the fixes.

On 13/02/24 13:46, Tomi Valkeinen wrote:
> When the driver sets up the zpos property it sets the default zpos value
> to the HW id of the plane. That is fine as such, but as on many DSS
> versions the driver arranges the DRM planes in a different order than
> the HW planes (to keep the non-scalable planes first), this leads to odd
> initial zpos values. An example is J721e, where the initial zpos values
> for DRM planes are 1, 3, 0, 2.
> 
> In theory the userspace should configure the zpos values properly when
> using multiple planes, and in that sense the initial zpos values
> shouldn't matter, but there's really no reason not to fix this and help
> the userspace apps which don't handle zpos perfectly. In particular,
> Weston seems to have issues dealing with the planes with the current
> default zpos values.
> 
> So let's change the zpos values for the DRM planes to 0, 1, 2, 3.
> 
> Another option would be to configure the planes marked as primary planes
> to zpos 0. On a two display system this would give us plane zpos values
> of 0, 0, 1, 2. The end result and behavior would be very similar in this
> option, and I'm not aware that this would actually help us in any way.
> So, to keep the code simple, I opted for the 0, 1, 2, 3 values.
> 
> Signed-off-by: Tomi Valkeinen 
> Fixes: 32a1795f57ee ("drm/tidss: New driver for TI Keystone platform Display 
> SubSystem")

Reviewed-by: Aradhya Bhatia 

> ---
>  drivers/gpu/drm/tidss/tidss_plane.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/tidss/tidss_plane.c 
> b/drivers/gpu/drm/tidss/tidss_plane.c
> index e1c0ef0c3894..68fed531f6a7 100644
> --- a/drivers/gpu/drm/tidss/tidss_plane.c
> +++ b/drivers/gpu/drm/tidss/tidss_plane.c
> @@ -213,7 +213,7 @@ struct tidss_plane *tidss_plane_create(struct 
> tidss_device *tidss,
>  
>   drm_plane_helper_add(>plane, _plane_helper_funcs);
>  
> - drm_plane_create_zpos_property(>plane, hw_plane_id, 0,
> + drm_plane_create_zpos_property(>plane, tidss->num_planes, 0,
>  num_planes - 1);
>  
>   ret = drm_plane_create_color_properties(>plane,
> 


Re: [PATCH v3 2/2] arm64: dts: ti: Add common1 register space for AM62x, AM62A & AM65x SoCs

2024-02-15 Thread Aradhya Bhatia
Thanks for the fixes, Devarsh!

On 15/02/24 14:02, Devarsh Thakkar wrote:
> This adds common1 register space for AM62x, AM62A and AM65x SoC's which are
> using TI's Keystone display hardware and supporting it as described in
> Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
> 
> Fixes: 3618811657b3 ("arm64: dts: ti: k3-am62a-main: Add node for Display 
> SubSystem (DSS)")
> Fixes: 8ccc1073c7bb ("arm64: dts: ti: k3-am62-main: Add node for DSS")
> Fixes: fc539b90eda2 ("arm64: dts: ti: am654: Add DSS node")
> Signed-off-by: Devarsh Thakkar 

Reviewed-by: Aradhya Bhatia 

> ---
> V2: Add common1 region for AM62A SoC too
> V3: Add Fixes tag
> ---
>  arch/arm64/boot/dts/ti/k3-am62-main.dtsi  | 5 +++--
>  arch/arm64/boot/dts/ti/k3-am62a-main.dtsi | 5 +++--
>  arch/arm64/boot/dts/ti/k3-am65-main.dtsi  | 5 +++--
>  3 files changed, 9 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi 
> b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
> index fe0cc4a9a501..8cee4d94cdd3 100644
> --- a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
> +++ b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
> @@ -779,9 +779,10 @@ dss: dss@3020 {
> <0x00 0x30207000 0x00 0x1000>, /* ovr1 */
> <0x00 0x30208000 0x00 0x1000>, /* ovr2 */
> <0x00 0x3020a000 0x00 0x1000>, /* vp1: Used for OLDI */
> -   <0x00 0x3020b000 0x00 0x1000>; /* vp2: Used as DPI Out */
> +   <0x00 0x3020b000 0x00 0x1000>, /* vp2: Used as DPI Out */
> +   <0x00 0x30201000 0x00 0x1000>; /* common1 */
>   reg-names = "common", "vidl1", "vid",
> - "ovr1", "ovr2", "vp1", "vp2";
> + "ovr1", "ovr2", "vp1", "vp2", "common1";
>   power-domains = <_pds 186 TI_SCI_PD_EXCLUSIVE>;
>   clocks = <_clks 186 6>,
><_vp1_clk>,
> diff --git a/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi 
> b/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi
> index 972971159a62..f475daea548e 100644
> --- a/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi
> +++ b/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi
> @@ -994,9 +994,10 @@ dss: dss@3020 {
> <0x00 0x30207000 0x00 0x1000>, /* ovr1 */
> <0x00 0x30208000 0x00 0x1000>, /* ovr2 */
> <0x00 0x3020a000 0x00 0x1000>, /* vp1: Tied OFF in the 
> SoC */
> -   <0x00 0x3020b000 0x00 0x1000>; /* vp2: Used as DPI Out */
> +   <0x00 0x3020b000 0x00 0x1000>, /* vp2: Used as DPI Out */
> +   <0x00 0x30201000 0x00 0x1000>; /* common1 */
>   reg-names = "common", "vidl1", "vid",
> - "ovr1", "ovr2", "vp1", "vp2";
> + "ovr1", "ovr2", "vp1", "vp2", "common1";
>   power-domains = <_pds 186 TI_SCI_PD_EXCLUSIVE>;
>   clocks = <_clks 186 6>,
><_clks 186 0>,
> diff --git a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi 
> b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
> index 07010d31350e..ff857117d719 100644
> --- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
> +++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
> @@ -991,9 +991,10 @@ dss: dss@4a0 {
> <0x0 0x04a07000 0x0 0x1000>, /* ovr1 */
> <0x0 0x04a08000 0x0 0x1000>, /* ovr2 */
> <0x0 0x04a0a000 0x0 0x1000>, /* vp1 */
> -   <0x0 0x04a0b000 0x0 0x1000>; /* vp2 */
> +   <0x0 0x04a0b000 0x0 0x1000>, /* vp2 */
> +   <0x0 0x04a01000 0x0 0x1000>; /* common1 */
>   reg-names = "common", "vidl1", "vid",
> - "ovr1", "ovr2", "vp1", "vp2";
> + "ovr1", "ovr2", "vp1", "vp2", "common1";
>  
>   ti,am65x-oldi-io-ctrl = <_oldi_io_ctrl>;
>  


Re: [PATCH 0/2] drm/bridge: sii902x: Crash fixes

2024-01-16 Thread Aradhya Bhatia



On 03/01/24 19:01, Tomi Valkeinen wrote:
> Two small fixes to sii902x for crashes.
> 
> Signed-off-by: Tomi Valkeinen 
> ---
> Tomi Valkeinen (2):
>   drm/bridge: sii902x: Fix probing race issue
>   drm/bridge: sii902x: Fix audio codec unregistration

Stress-tested kernel boot on SK-AM62, SK-AM62-LP, SK-AM62A, and I
couldn't reproduce the issue. The kernel booted fine every time.

For the series,

Reviewed-by: Aradhya Bhatia 

> 
>  drivers/gpu/drm/bridge/sii902x.c | 42 
> +++-
>  1 file changed, 29 insertions(+), 13 deletions(-)
> ---
> base-commit: 0c75d52190b8bfa22cdb66e07148aea599c4535d
> change-id: 20240103-si902x-fixes-468d7153b8ee
> 
> Best regards,


Re: [PATCH v2 0/2] drm/bridge: tc358767: Fix DRM_BRIDGE_ATTACH_NO_CONNECTOR case

2023-12-11 Thread Aradhya Bhatia



On 06/12/23 17:41, Tomi Valkeinen wrote:
> Hi,
> 
> On 08/11/2023 14:45, Alexander Stein wrote:
>> Hi Tomi,
>>
>> Am Mittwoch, 8. November 2023, 12:27:21 CET schrieb Tomi Valkeinen:
>>> These two patches are needed to make tc358767 work in the
>>> DRM_BRIDGE_ATTACH_NO_CONNECTOR case, at least when using a DP connector.
>>>
>>> I have tested this with TI AM654 EVM with a tc358767 add-on card
>>> connected to a DP monitor.
>>
>> Just a question regarding the usage of this DSI-DP bridge.
>> What is the state of the DSI lanes after the DSI host has been
>> initialized,
>> but before calling atomic_pre_enable? AFAIK this bridge requires LP-11
>> on DSI
>> at any time for accessing the AUX channel.

+ Marek

Marek, Alexander,

A quick grep tells me that you have added devicetree for tc358767 in DSI
to (e)DP mode on other platforms. Could you please test these patches
and report if you find any issue?

Regards
Aradhya

> 
> We haven't received any test reports for the DSI-DP case... I was
> looking at the datasheet, and I wonder, why do you say the bridge
> requires DSI to be up for the AUX transactions?
> 
>  Tomi
> 
>> Best regards,
>> Alexander
>>
>>> Signed-off-by: Tomi Valkeinen 
>>> ---
>>> Changes in v2:
>>> - Update the format negotiation patch as discussed in
>>> https://lore.kernel.org/all/7ddf0edb-2925-4b7c-ad07-27c030dd0...@ti.com/ -
>>> Link to v1:
>>> https://lore.kernel.org/r/20231031-tc358767-v1-0-392081ad9f4b@ideasonboard.
>>> com
>>>
>>> ---
>>> Aradhya Bhatia (1):
>>>    drm/bridge: tc358767: Add format negotiation hooks for DPI/DSI to
>>> (e)DP
>>>
>>> Tomi Valkeinen (1):
>>>    drm/bridge: tc358767: Fix link properties discovery
>>>
>>>   drivers/gpu/drm/bridge/tc358767.c | 32
>>> 
>>>   1 file changed, 32 insertions(+)
>>> ---
>>> base-commit: 9d7c8c066916f231ca0ed4e4fce6c4b58ca3e451
>>> change-id: 20231031-tc358767-58e3ebdf95f0
>>>
>>> Best regards,
>>
>>
> 


Re: [PATCH] drm/panel: re-alphabetize the menu list

2023-12-08 Thread Aradhya Bhatia



On 07/12/23 22:28, Randy Dunlap wrote:
> 
> 
> On 12/7/23 01:52, Aradhya Bhatia wrote:
>> Hi Randy,
>>
>> Thanks for the patch!
>>
>> On 07/12/23 11:52, Randy Dunlap wrote:
>>> A few of the DRM_PANEL entries have become out of alphabetical order,
>>> so move them around a bit to restore alpha order.
>>>
>>> Signed-off-by: Randy Dunlap 
>>> Cc: Neil Armstrong 
>>> Cc: Jessica Zhang 
>>> Cc: Sam Ravnborg 
>>> Cc: Maarten Lankhorst 
>>> Cc: Maxime Ripard 
>>> Cc: Thomas Zimmermann 
>>> Cc: David Airlie 
>>> Cc: Daniel Vetter 
>>> Cc: dri-devel@lists.freedesktop.org
>>> ---
>>>  drivers/gpu/drm/panel/Kconfig |   90 
>>>  1 file changed, 45 insertions(+), 45 deletions(-)
>>>
>>> diff -- a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
>>> --- a/drivers/gpu/drm/panel/Kconfig
>>> +++ b/drivers/gpu/drm/panel/Kconfig
>>> @@ -95,34 +95,6 @@ config DRM_PANEL_LVDS
>>>   handling of power supplies or control signals. It implements automatic
>>>   backlight handling if the panel is attached to a backlight controller.
>>>  
>>> -config DRM_PANEL_SIMPLE
>>> -   tristate "support for simple panels (other than eDP ones)"
>>> -   depends on OF
>>> -   depends on BACKLIGHT_CLASS_DEVICE
>>> -   depends on PM
>>> -   select VIDEOMODE_HELPERS
>>> -   help
>>> - DRM panel driver for dumb non-eDP panels that need at most a regulator
>>> - and a GPIO to be powered up. Optionally a backlight can be attached so
>>> - that it can be automatically turned off when the panel goes into a
>>> - low power state.
>>> -
>>> -config DRM_PANEL_EDP
>>> -   tristate "support for simple Embedded DisplayPort panels"
>>> -   depends on OF
>>> -   depends on BACKLIGHT_CLASS_DEVICE
>>> -   depends on PM
>>> -   select VIDEOMODE_HELPERS
>>> -   select DRM_DISPLAY_DP_HELPER
>>> -   select DRM_DISPLAY_HELPER
>>> -   select DRM_DP_AUX_BUS
>>> -   select DRM_KMS_HELPER
>>> -   help
>>> - DRM panel driver for dumb eDP panels that need at most a regulator and
>>> - a GPIO to be powered up. Optionally a backlight can be attached so
>>> - that it can be automatically turned off when the panel goes into a
>>> - low power state.
>>> -
>>>  config DRM_PANEL_EBBG_FT8719
>>> tristate "EBBG FT8719 panel driver"
>>> depends on OF
>>> @@ -317,12 +289,6 @@ config DRM_PANEL_LEADTEK_LTK500HD1829
>>>   24 bit RGB per pixel. It provides a MIPI DSI interface to
>>>   the host and has a built-in LED backlight.
>>>  
>>> -config DRM_PANEL_SAMSUNG_LD9040
>>> -   tristate "Samsung LD9040 RGB/SPI panel"
>>> -   depends on OF && SPI
>>> -   depends on BACKLIGHT_CLASS_DEVICE
>>> -   select VIDEOMODE_HELPERS
>>> -
>>>  config DRM_PANEL_LG_LB035Q02
>>> tristate "LG LB035Q024573 RGB panel"
>>> depends on GPIOLIB && OF && SPI
>>> @@ -350,6 +316,17 @@ config DRM_PANEL_MAGNACHIP_D53E6EA8966
>>>   with the Magnachip D53E6EA8966 panel IC. This panel receives
>>>   video data via DSI but commands via 9-bit SPI using DBI.
>>>  
>>> +config DRM_PANEL_MANTIX_MLAF057WE51
>>> +   tristate "Mantix MLAF057WE51-X MIPI-DSI LCD panel"
>>> +   depends on OF
>>> +   depends on DRM_MIPI_DSI
>>> +   depends on BACKLIGHT_CLASS_DEVICE
>>> +   help
>>> + Say Y here if you want to enable support for the Mantix
>>> + MLAF057WE51-X MIPI DSI panel as e.g. used in the Librem 5. It
>>> + has a resolution of 720x1440 pixels, a built in backlight and touch
>>> + controller.
>>> +
>>>  config DRM_PANEL_NEC_NL8048HL11
>>> tristate "NEC NL8048HL11 RGB panel"
>>> depends on GPIOLIB && OF && SPI
>>> @@ -438,17 +415,6 @@ config DRM_PANEL_NOVATEK_NT39016
>>>   Say Y here if you want to enable support for the panels built
>>>   around the Novatek NT39016 display controller.
>>>  
>>> -config DRM_PANEL_MANTIX_MLAF057WE51
>>> -   tristate "Mantix MLAF057WE51-X MIPI-DSI LCD panel"
>>> -   depends on OF
>>> -   depends on DRM_MIPI_DSI
>>> -   depends on BACKLIGHT_

Re: [PATCH] drm/panel: re-alphabetize the menu list

2023-12-07 Thread Aradhya Bhatia
Hi Randy,

Thanks for the patch!

On 07/12/23 11:52, Randy Dunlap wrote:
> A few of the DRM_PANEL entries have become out of alphabetical order,
> so move them around a bit to restore alpha order.
> 
> Signed-off-by: Randy Dunlap 
> Cc: Neil Armstrong 
> Cc: Jessica Zhang 
> Cc: Sam Ravnborg 
> Cc: Maarten Lankhorst 
> Cc: Maxime Ripard 
> Cc: Thomas Zimmermann 
> Cc: David Airlie 
> Cc: Daniel Vetter 
> Cc: dri-devel@lists.freedesktop.org
> ---
>  drivers/gpu/drm/panel/Kconfig |   90 
>  1 file changed, 45 insertions(+), 45 deletions(-)
> 
> diff -- a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
> --- a/drivers/gpu/drm/panel/Kconfig
> +++ b/drivers/gpu/drm/panel/Kconfig
> @@ -95,34 +95,6 @@ config DRM_PANEL_LVDS
> handling of power supplies or control signals. It implements automatic
> backlight handling if the panel is attached to a backlight controller.
>  
> -config DRM_PANEL_SIMPLE
> - tristate "support for simple panels (other than eDP ones)"
> - depends on OF
> - depends on BACKLIGHT_CLASS_DEVICE
> - depends on PM
> - select VIDEOMODE_HELPERS
> - help
> -   DRM panel driver for dumb non-eDP panels that need at most a regulator
> -   and a GPIO to be powered up. Optionally a backlight can be attached so
> -   that it can be automatically turned off when the panel goes into a
> -   low power state.
> -
> -config DRM_PANEL_EDP
> - tristate "support for simple Embedded DisplayPort panels"
> - depends on OF
> - depends on BACKLIGHT_CLASS_DEVICE
> - depends on PM
> - select VIDEOMODE_HELPERS
> - select DRM_DISPLAY_DP_HELPER
> - select DRM_DISPLAY_HELPER
> - select DRM_DP_AUX_BUS
> - select DRM_KMS_HELPER
> - help
> -   DRM panel driver for dumb eDP panels that need at most a regulator and
> -   a GPIO to be powered up. Optionally a backlight can be attached so
> -   that it can be automatically turned off when the panel goes into a
> -   low power state.
> -
>  config DRM_PANEL_EBBG_FT8719
>   tristate "EBBG FT8719 panel driver"
>   depends on OF
> @@ -317,12 +289,6 @@ config DRM_PANEL_LEADTEK_LTK500HD1829
> 24 bit RGB per pixel. It provides a MIPI DSI interface to
> the host and has a built-in LED backlight.
>  
> -config DRM_PANEL_SAMSUNG_LD9040
> - tristate "Samsung LD9040 RGB/SPI panel"
> - depends on OF && SPI
> - depends on BACKLIGHT_CLASS_DEVICE
> - select VIDEOMODE_HELPERS
> -
>  config DRM_PANEL_LG_LB035Q02
>   tristate "LG LB035Q024573 RGB panel"
>   depends on GPIOLIB && OF && SPI
> @@ -350,6 +316,17 @@ config DRM_PANEL_MAGNACHIP_D53E6EA8966
> with the Magnachip D53E6EA8966 panel IC. This panel receives
> video data via DSI but commands via 9-bit SPI using DBI.
>  
> +config DRM_PANEL_MANTIX_MLAF057WE51
> + tristate "Mantix MLAF057WE51-X MIPI-DSI LCD panel"
> + depends on OF
> + depends on DRM_MIPI_DSI
> + depends on BACKLIGHT_CLASS_DEVICE
> + help
> +   Say Y here if you want to enable support for the Mantix
> +   MLAF057WE51-X MIPI DSI panel as e.g. used in the Librem 5. It
> +   has a resolution of 720x1440 pixels, a built in backlight and touch
> +   controller.
> +
>  config DRM_PANEL_NEC_NL8048HL11
>   tristate "NEC NL8048HL11 RGB panel"
>   depends on GPIOLIB && OF && SPI
> @@ -438,17 +415,6 @@ config DRM_PANEL_NOVATEK_NT39016
> Say Y here if you want to enable support for the panels built
> around the Novatek NT39016 display controller.
>  
> -config DRM_PANEL_MANTIX_MLAF057WE51
> - tristate "Mantix MLAF057WE51-X MIPI-DSI LCD panel"
> - depends on OF
> - depends on DRM_MIPI_DSI
> - depends on BACKLIGHT_CLASS_DEVICE
> - help
> -   Say Y here if you want to enable support for the Mantix
> -   MLAF057WE51-X MIPI DSI panel as e.g. used in the Librem 5. It
> -   has a resolution of 720x1440 pixels, a built in backlight and touch
> -   controller.
> -
>  config DRM_PANEL_OLIMEX_LCD_OLINUXINO
>   tristate "Olimex LCD-OLinuXino panel"
>   depends on OF
> @@ -566,6 +532,12 @@ config DRM_PANEL_SAMSUNG_DB7430
> DB7430 DPI display controller used in such devices as the
> LMS397KF04 480x800 DPI panel.
>  
> +config DRM_PANEL_SAMSUNG_LD9040
> + tristate "Samsung LD9040 RGB/SPI panel"
> + depends on OF && SPI
> + depends on BACKLIGHT_CLASS_DEVICE
> + select VIDEOMODE_HELPERS
> +
>  config DRM_PANEL_SAMSUNG_S6D16D0
>   tristate "Samsung S6D16D0 DSI video mode panel"
>   depends on OF
> @@ -774,6 +746,34 @@ config DRM_PANEL_STARTEK_KD070FHFID015
> with a resolution of 1024 x 600 pixels. It provides a MIPI DSI 
> interface to
> the host, a built-in LED backlight and touch controller.
>  
> +config DRM_PANEL_EDP
> + tristate "support for simple Embedded DisplayPort panels"
> + depends on OF
> + depends on 

  1   2   3   >