linux-renesas-soc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/8] Add dual-LVDS panel support to EK874
@ 2019-08-28 18:36 Fabrizio Castro
  2019-08-28 18:36 ` [PATCH v3 1/8] dt-bindings: display: Add bindings for LVDS bus-timings Fabrizio Castro
                   ` (9 more replies)
  0 siblings, 10 replies; 32+ messages in thread
From: Fabrizio Castro @ 2019-08-28 18:36 UTC (permalink / raw)
  To: Laurent Pinchart, Geert Uytterhoeven, David Airlie,
	Daniel Vetter, Rob Herring, Mark Rutland, Thierry Reding,
	Maarten Lankhorst, Maxime Ripard, Sean Paul, Andrzej Hajda
  Cc: Fabrizio Castro, Sam Ravnborg, Simon Horman, Magnus Damm,
	Kieran Bingham, dri-devel, devicetree, linux-kernel,
	linux-renesas-soc, Chris Paterson, Biju Das, Laurent Pinchart,
	Jacopo Mondi, xu_shunji, ebiharaml

Dear All,

this series adds support for dual-LVDS panel IDK-2121WR
from Advantech:
https://buy.advantech.eu/Displays/Embedded-LCD-Kits-High-Brightness/model-IDK-2121WR-K2FHA2E.htm

V3 approaches the problem in a completely different way, we now
have two new properties to mark the ports in the DT as receiving
even pixels and odd pixels: dual-lvds-even-pixels and dual-lvds-odd-pixels,
which means device drivers should not use bridge specific or panel
specific dual_link flags. Also, in this case the DT describes the
connection fully.

In order for the solution to be generic, I have exported a new helper
(drm_of_lvds_get_dual_link_configuration) to walk the device tree,
and figure out if the connection is dual-LVDS. The same helper gives
information about the configuration of the connection. If Px is connected
to a port expecting even pixels and Py is connected to a port expecting
odd pixels, then the helper returns DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS
(like in the example below), otherwise it returns
DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS.


 --------            dual-lvds-even-pixels  --------
|        |----                         ----|        |
|        | Px |---------------------->| Pn |        |
|        |----                         ----|        |
| SOURCE |           dual-lvds-odd-pixels  |  SINK  |
|        |----                         ----|        |
|        | Py |---------------------->| Pm |        |
|        |----                         ----|        |
 --------                                   --------

The device driver for the encoder then will work out if with the current
wiring the pixels need swapping or not.

The same solution works for both panels and bridges.

Since the DT describes the connection fully, driver
drivers/gpu/drm/panel/panel-lvds.c works out-of-the-box, no changes
required, however, this implementation opens up a problem with the
dt-bindings.
Driver drivers/gpu/drm/panel/panel-lvds.c can still be pleased by
a port node, but also by a ports node.
I have created Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
with the idea of including it from panels and bridges dt-bindings
supporting dual-LVDS (and of course the dt-bindings for the specific
devices should say which port should be marked as what), but file
Documentation/devicetree/bindings/display/panel/lvds.yaml formally
requires property "port", while with this implementation it should require
OneOf "port" and "ports", and unfortunately I can't seem to find a neat way
aroud that, other than creating a new compatible string
(e.g. "panel-dual-lvds"), a new dt-binding document for it, and of course adding
support for the new compatible string to drivers/gpu/drm/panel/panel-lvds.c.
As a result, this series is missing (at least) a patch necessary to fully
document the new implementation within
Documentation/devicetree/bindings/display/panel/lvds.yaml

Rob, do you have any suggestions? Do you think this idea works ok from a
documentation point of view? By the way, I don't really know what I am doing
with the yaml dt-bindings, I hope you won't be horrified by this series :-P

I hope I was able to deliver the concept clearly, if not please just ask.

Comments are very much appreciated.

Thanks,
Fab

Fabrizio Castro (8):
  dt-bindings: display: Add bindings for LVDS bus-timings
  dt-bindings: display: Add idk-2121wr binding
  drm: Add bus timings helper
  drm: rcar-du: lvds: Add dual-LVDS panels support
  drm: bridge: thc63: Do not report input bus mode through bridge
    timings
  arm64: dts: renesas: Add EK874 board with idk-2121wr display support
  [HACK] arm64: dts: renesas: draak: Enable LVDS
  [HACK] arm64: dts: renesas: draak: Enable LVDS dual-link operation

 .../bindings/display/bus-timings/lvds.yaml         |  38 +++++++
 .../display/panel/advantech,idk-2121wr.yaml        |  90 ++++++++++++++++
 arch/arm64/boot/dts/renesas/Makefile               |   3 +-
 .../boot/dts/renesas/r8a774c0-ek874-idk-2121wr.dts | 116 +++++++++++++++++++++
 arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts     |  21 +++-
 arch/arm64/boot/dts/renesas/r8a77995-draak.dts     |  26 +++--
 drivers/gpu/drm/Makefile                           |   3 +-
 drivers/gpu/drm/bridge/thc63lvd1024.c              |   9 +-
 drivers/gpu/drm/drm_bus_timings.c                  |  97 +++++++++++++++++
 drivers/gpu/drm/rcar-du/rcar_lvds.c                | 110 +++++++++++--------
 include/drm/drm_bridge.h                           |   8 --
 include/drm/drm_bus_timings.h                      |  21 ++++
 12 files changed, 473 insertions(+), 69 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
 create mode 100644 Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml
 create mode 100644 arch/arm64/boot/dts/renesas/r8a774c0-ek874-idk-2121wr.dts
 create mode 100644 drivers/gpu/drm/drm_bus_timings.c
 create mode 100644 include/drm/drm_bus_timings.h

-- 
2.7.4


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v3 1/8] dt-bindings: display: Add bindings for LVDS bus-timings
  2019-08-28 18:36 [PATCH v3 0/8] Add dual-LVDS panel support to EK874 Fabrizio Castro
@ 2019-08-28 18:36 ` Fabrizio Castro
  2019-08-29  7:57   ` Geert Uytterhoeven
  2019-08-29 14:03   ` Rob Herring
  2019-08-28 18:36 ` [PATCH v3 2/8] dt-bindings: display: Add idk-2121wr binding Fabrizio Castro
                   ` (8 subsequent siblings)
  9 siblings, 2 replies; 32+ messages in thread
From: Fabrizio Castro @ 2019-08-28 18:36 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, Rob Herring, Mark Rutland
  Cc: Fabrizio Castro, dri-devel, devicetree, linux-kernel,
	Simon Horman, Geert Uytterhoeven, Chris Paterson, Biju Das,
	linux-renesas-soc, Laurent Pinchart, Kieran Bingham,
	Jacopo Mondi, sam

Dual-LVDS connections need markers in the DT, this patch adds
some common documentation to be referenced by both panels and
bridges.

Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>

---
v2->v3:
* new patch
---
 .../bindings/display/bus-timings/lvds.yaml         | 38 ++++++++++++++++++++++
 1 file changed, 38 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/bus-timings/lvds.yaml

diff --git a/Documentation/devicetree/bindings/display/bus-timings/lvds.yaml b/Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
new file mode 100644
index 0000000..f35b55a
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bus-timings/lvds.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Common Properties for bus timings of LVDS interfaces
+
+maintainers:
+  - Thierry Reding <thierry.reding@gmail.com>
+  - Fabrizio Castro <fabrizio.castro@bp.renesas.com>
+
+description: |
+  This document defines device tree properties common to LVDS and dual-LVDS
+  interfaces, where a dual-LVDS interface is a dual-link connection with even
+  pixels traveling on one connection, and with odd pixels traveling on the other
+  connection.
+  This document doesn't constitue a device tree binding specification by itself
+  but is meant to be referenced by device tree bindings.
+  When referenced from panel or bridge device tree bindings, the properties
+  defined in this document are defined as follows. The panel and bridge device
+  tree bindings are responsible for defining whether each property is required
+  or optional.
+
+properties:
+  dual-lvds-even-pixels:
+    type: boolean
+    description:
+      This property is specific to an input port of a sink device. When
+      specified, it marks the port as recipient of even-pixels.
+
+  dual-lvds-odd-pixels:
+    type: boolean
+    description:
+      This property is specific to an input port of a sink device. When
+      specified, it marks the port as recipient of odd-pixels.
+
+...
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v3 2/8] dt-bindings: display: Add idk-2121wr binding
  2019-08-28 18:36 [PATCH v3 0/8] Add dual-LVDS panel support to EK874 Fabrizio Castro
  2019-08-28 18:36 ` [PATCH v3 1/8] dt-bindings: display: Add bindings for LVDS bus-timings Fabrizio Castro
@ 2019-08-28 18:36 ` Fabrizio Castro
  2019-11-07 18:12   ` Laurent Pinchart
  2019-08-28 18:36 ` [PATCH v3 3/8] drm: Add bus timings helper Fabrizio Castro
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 32+ messages in thread
From: Fabrizio Castro @ 2019-08-28 18:36 UTC (permalink / raw)
  To: Thierry Reding, David Airlie, Daniel Vetter, Rob Herring, Mark Rutland
  Cc: Fabrizio Castro, Sam Ravnborg, dri-devel, devicetree,
	linux-kernel, Simon Horman, Geert Uytterhoeven, Chris Paterson,
	Biju Das, linux-renesas-soc, Laurent Pinchart, Kieran Bingham,
	Jacopo Mondi

Add binding for the idk-2121wr LVDS panel from Advantech.

Some panel-specific documentation can be found here:
https://buy.advantech.eu/Displays/Embedded-LCD-Kits-High-Brightness/model-IDK-2121WR-K2FHA2E.htm

Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>

---
v2->v3:
* new patch
---
 .../display/panel/advantech,idk-2121wr.yaml        | 90 ++++++++++++++++++++++
 1 file changed, 90 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml

diff --git a/Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml b/Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml
new file mode 100644
index 0000000..b2ccdc8
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml
@@ -0,0 +1,90 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/advantech,idk-2121wr.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Advantech IDK-2121WR 21.5" Full-HD dual-LVDS panel
+
+maintainers:
+  - Fabrizio Castro <fabrizio.castro@bp.renesas.com>
+  - Thierry Reding <thierry.reding@gmail.com>
+
+description: |
+  The IDK-2121WR from Advantech is a Full-HD dual-LVDS panel.
+
+  The panels expects odd pixels from the first port, and even pixels from
+  the second port, therefore the ports must be marked accordingly.
+
+allOf:
+  - $ref: lvds.yaml#
+  - $ref: ../bus-timings/lvds.yaml#
+
+properties:
+  compatible:
+    items:
+      - const: advantech,idk-2121wr
+      - {} # panel-lvds, but not listed here to avoid false select
+
+  data-mapping:
+    const: vesa-24
+
+  width-mm:
+    const: 476
+
+  height-mm:
+    const: 268
+
+  panel-timing: true
+  ports: true
+
+additionalProperties: false
+
+required:
+  - compatible
+
+examples:
+  - |+
+    panel-lvds {
+      compatible = "advantech,idk-2121wr", "panel-lvds";
+
+      width-mm = <476>;
+      height-mm = <268>;
+
+      data-mapping = "vesa-24";
+
+      panel-timing {
+        clock-frequency = <148500000>;
+        hactive = <1920>;
+        vactive = <1080>;
+        hsync-len = <44>;
+        hfront-porch = <88>;
+        hback-porch = <148>;
+        vfront-porch = <4>;
+        vback-porch = <36>;
+        vsync-len = <5>;
+      };
+
+      ports {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        port@0 {
+          reg = <0>;
+          dual-lvds-odd-pixels;
+          panel_in0: endpoint {
+            remote-endpoint = <&lvds0_out>;
+          };
+        };
+
+        port@1 {
+          reg = <1>;
+          dual-lvds-even-pixels;
+          panel_in1: endpoint {
+            remote-endpoint = <&lvds1_out>;
+          };
+        };
+      };
+    };
+
+...
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v3 3/8] drm: Add bus timings helper
  2019-08-28 18:36 [PATCH v3 0/8] Add dual-LVDS panel support to EK874 Fabrizio Castro
  2019-08-28 18:36 ` [PATCH v3 1/8] dt-bindings: display: Add bindings for LVDS bus-timings Fabrizio Castro
  2019-08-28 18:36 ` [PATCH v3 2/8] dt-bindings: display: Add idk-2121wr binding Fabrizio Castro
@ 2019-08-28 18:36 ` Fabrizio Castro
  2019-11-07 19:26   ` Laurent Pinchart
  2019-08-28 18:36 ` [PATCH v3 4/8] drm: rcar-du: lvds: Add dual-LVDS panels support Fabrizio Castro
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 32+ messages in thread
From: Fabrizio Castro @ 2019-08-28 18:36 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Sean Paul, David Airlie, Daniel Vetter
  Cc: Fabrizio Castro, linux-kernel, dri-devel, Simon Horman,
	Geert Uytterhoeven, Chris Paterson, Biju Das, linux-renesas-soc,
	Laurent Pinchart, Kieran Bingham, Jacopo Mondi, sam

Helper to provide bus timing information.

Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>

---
v2->v3:
* new patch
---
 drivers/gpu/drm/Makefile          |  3 +-
 drivers/gpu/drm/drm_bus_timings.c | 97 +++++++++++++++++++++++++++++++++++++++
 include/drm/drm_bus_timings.h     | 21 +++++++++
 3 files changed, 120 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/drm_bus_timings.c
 create mode 100644 include/drm/drm_bus_timings.h

diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 9f0d2ee..a270063 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -17,7 +17,8 @@ drm-y       :=	drm_auth.o drm_cache.o \
 		drm_plane.o drm_color_mgmt.o drm_print.o \
 		drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
 		drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \
-		drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o
+		drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o \
+		drm_bus_timings.o
 
 drm-$(CONFIG_DRM_LEGACY) += drm_legacy_misc.o drm_bufs.o drm_context.o drm_dma.o drm_scatter.o drm_lock.o
 drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
diff --git a/drivers/gpu/drm/drm_bus_timings.c b/drivers/gpu/drm/drm_bus_timings.c
new file mode 100644
index 0000000..e2ecd22
--- /dev/null
+++ b/drivers/gpu/drm/drm_bus_timings.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <drm/drm_bus_timings.h>
+#include <linux/errno.h>
+#include <linux/of_graph.h>
+#include <linux/of.h>
+#include <linux/types.h>
+
+#define DRM_OF_LVDS_ODD		1
+#define DRM_OF_LVDS_EVEN	2
+
+static int drm_of_lvds_get_port_pixels_type(struct device_node *port_node)
+{
+	bool even_pixels, odd_pixels;
+
+	even_pixels = of_property_read_bool(port_node, "dual-lvds-even-pixels");
+	odd_pixels = of_property_read_bool(port_node, "dual-lvds-odd-pixels");
+	return  even_pixels * DRM_OF_LVDS_EVEN + odd_pixels * DRM_OF_LVDS_ODD;
+}
+
+/**
+ * drm_of_lvds_get_dual_link_configuration - get the dual-LVDS configuration
+ * @p1: device tree node corresponding to the first port of the source
+ * @p2: device tree node corresponding to the second port of the source
+ *
+ * An LVDS dual-link bus is made of two connections, even pixels transit on one
+ * connection, and odd pixels transit on the other connection.
+ * This function walks the DT (from the source ports to the sink ports) looking
+ * for a dual-LVDS bus. A dual-LVDS bus is identfied by markers found on the DT
+ * ports of the sink device(s). If such a bus is found, this function returns
+ * its configuration (either p1 connected to the even pixels port and p2
+ * connected to the odd pixels port, or p1 connected to the odd pixels port and
+ * p2 connected to the even pixels port).
+ *
+ * Return: A code describing the bus configuration when a valid dual-LVDS bus is
+ * found, or an error code when no valid dual-LVDS bus is found
+ *
+ * Possible codes for the bus configuration are:
+ *
+ * - DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS: when p1 is connected to the even pixels
+ *   port and p2 is connected to the odd pixels port
+ * - DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS: when p1 is connected to the odd pixels
+ *   port and p2 is connected to the even pixels port
+ *
+ */
+int drm_of_lvds_get_dual_link_configuration(const struct device_node *p1,
+					    const struct device_node *p2)
+{
+	struct device_node *remote_p1 = NULL, *remote_p2 = NULL;
+	struct device_node *parent_p1 = NULL, *parent_p2 = NULL;
+	struct device_node *ep1 = NULL, *ep2 = NULL;
+	u32 reg_p1, reg_p2;
+	int ret = -EINVAL, remote_p1_pt, remote_p2_pt;
+
+	if (!p1 || !p2)
+		return ret;
+	if (of_property_read_u32(p1, "reg", &reg_p1) ||
+	    of_property_read_u32(p2, "reg", &reg_p2))
+		return ret;
+	parent_p1 = of_get_parent(p1);
+	parent_p2 = of_get_parent(p2);
+	if (!parent_p1 || !parent_p2)
+		goto done;
+	ep1 = of_graph_get_endpoint_by_regs(parent_p1, reg_p1, 0);
+	ep2 = of_graph_get_endpoint_by_regs(parent_p2, reg_p2, 0);
+	if (!ep1 || !ep2)
+		goto done;
+	remote_p1 = of_graph_get_remote_port(ep1);
+	remote_p2 = of_graph_get_remote_port(ep2);
+	if (!remote_p1 || !remote_p2)
+		goto done;
+	remote_p1_pt = drm_of_lvds_get_port_pixels_type(remote_p1);
+	remote_p2_pt = drm_of_lvds_get_port_pixels_type(remote_p2);
+	/*
+	 * A valid dual-lVDS bus is found when one remote port is marked with
+	 * "dual-lvds-even-pixels", and the other remote port is marked with
+	 * "dual-lvds-odd-pixels", bail out if the markers are not right.
+	 */
+	if (!remote_p1_pt || !remote_p2_pt ||
+	    remote_p1_pt + remote_p2_pt != DRM_OF_LVDS_EVEN + DRM_OF_LVDS_ODD)
+		goto done;
+	if (remote_p1_pt == DRM_OF_LVDS_EVEN)
+		/* The sink expects even pixels through the first port */
+		ret = DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS;
+	else
+		/* The sink expects odd pixels through the first port */
+		ret = DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS;
+
+done:
+	of_node_put(ep1);
+	of_node_put(ep2);
+	of_node_put(parent_p1);
+	of_node_put(parent_p2);
+	of_node_put(remote_p1);
+	of_node_put(remote_p2);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(drm_of_lvds_get_dual_link_configuration);
diff --git a/include/drm/drm_bus_timings.h b/include/drm/drm_bus_timings.h
new file mode 100644
index 0000000..db8a385
--- /dev/null
+++ b/include/drm/drm_bus_timings.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DRM_BUS_TIMINGS__
+#define __DRM_BUS_TIMINGS__
+
+struct device_node;
+
+#define DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS	0
+#define DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS	1
+
+#ifdef CONFIG_OF
+int drm_of_lvds_get_dual_link_configuration(const struct device_node *p1,
+					    const struct device_node *p2);
+#else
+int drm_of_lvds_get_dual_link_configuration(const struct device_node *p1,
+					    const struct device_node *p2)
+{
+	return -EINVAL;
+}
+#endif
+
+#endif /* __DRM_BUS_TIMINGS__ */
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v3 4/8] drm: rcar-du: lvds: Add dual-LVDS panels support
  2019-08-28 18:36 [PATCH v3 0/8] Add dual-LVDS panel support to EK874 Fabrizio Castro
                   ` (2 preceding siblings ...)
  2019-08-28 18:36 ` [PATCH v3 3/8] drm: Add bus timings helper Fabrizio Castro
@ 2019-08-28 18:36 ` Fabrizio Castro
  2019-11-07 19:50   ` Laurent Pinchart
  2019-08-28 18:36 ` [PATCH v3 5/8] drm: bridge: thc63: Do not report input bus mode through bridge timings Fabrizio Castro
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 32+ messages in thread
From: Fabrizio Castro @ 2019-08-28 18:36 UTC (permalink / raw)
  To: Laurent Pinchart, David Airlie, Daniel Vetter
  Cc: Fabrizio Castro, Kieran Bingham, dri-devel, linux-renesas-soc,
	linux-kernel, Simon Horman, Geert Uytterhoeven, Chris Paterson,
	Biju Das, Jacopo Mondi, sam

The driver doesn't support dual-link LVDS displays, and the way
it identifies bridges won't allow for dual-LVDS displays to be
connected. Also, it's not possible to swap even and odd pixels
around in case the wiring isn't taking advantage of the default
hardware configuration. Further more, the "mode" of the companion
encoder should be same as the mode of the primary encoder.

Rework the driver to improve all of the above, so that it can
support dual-LVDS displays.

Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>

---
v2->v3:
* reworked to take advantange of the new dt-bindings
* squashed in the patche for fixing the companion's mode

Laurent,

unfortunately the best way to get the companion encoder to use
the same mode as the primary encoder is setting the mode directly
without calling into rcar_lvds_mode_set for the companion encoder,
as the below test fails for the companion encoder in
rcar_lvds_get_lvds_mode:
if (!info->num_bus_formats || !info->bus_formats)

Anyhow, setting the mode for the companion encoder doesn't seem
to be mandary according to the experiments I have been running,
but the HW User's Manual doesn't really say much about this,
therefore I think the safest option is still to set the mode for
the companion encoder.

Thanks,
Fab
---
 drivers/gpu/drm/rcar-du/rcar_lvds.c | 110 +++++++++++++++++++++---------------
 1 file changed, 65 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c
index 3fe0b86..dfec5e7 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
@@ -20,6 +20,8 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_bridge.h>
+#include <drm/drm_bus_timings.h>
+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_probe_helper.h>
 
@@ -69,6 +71,7 @@ struct rcar_lvds {
 
 	struct drm_bridge *companion;
 	bool dual_link;
+	bool stripe_swap_data;
 };
 
 #define bridge_to_rcar_lvds(b) \
@@ -439,12 +442,20 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
 	rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
 
 	if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) {
-		/*
-		 * Configure vertical stripe based on the mode of operation of
-		 * the connected device.
-		 */
-		rcar_lvds_write(lvds, LVDSTRIPE,
-				lvds->dual_link ? LVDSTRIPE_ST_ON : 0);
+		u32 lvdstripe = 0;
+
+		if (lvds->dual_link)
+			/*
+			 * Configure vertical stripe based on the mode of
+			 * operation of the connected device.
+			 *
+			 * ST_SWAP from LVD1STRIPE is reserved, do not set
+			 * in the companion LVDS
+			 */
+			lvdstripe = LVDSTRIPE_ST_ON |
+				(lvds->companion && lvds->stripe_swap_data ?
+				 LVDSTRIPE_ST_SWAP : 0);
+		rcar_lvds_write(lvds, LVDSTRIPE, lvdstripe);
 	}
 
 	/*
@@ -603,6 +614,11 @@ static void rcar_lvds_mode_set(struct drm_bridge *bridge,
 	lvds->display_mode = *adjusted_mode;
 
 	rcar_lvds_get_lvds_mode(lvds);
+	if (lvds->companion) {
+		struct rcar_lvds *companion_lvds = bridge_to_rcar_lvds(
+							lvds->companion);
+		companion_lvds->mode = lvds->mode;
+	}
 }
 
 static int rcar_lvds_attach(struct drm_bridge *bridge)
@@ -667,9 +683,10 @@ EXPORT_SYMBOL_GPL(rcar_lvds_dual_link);
 static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds)
 {
 	const struct of_device_id *match;
-	struct device_node *companion;
+	struct device_node *companion, *p0 = NULL, *p1 = NULL;
 	struct device *dev = lvds->dev;
-	int ret = 0;
+	struct rcar_lvds *companion_lvds;
+	int ret = 0, dual_link;
 
 	/* Locate the companion LVDS encoder for dual-link operation, if any. */
 	companion = of_parse_phandle(dev->of_node, "renesas,companion", 0);
@@ -687,16 +704,50 @@ static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds)
 		goto done;
 	}
 
+	/*
+	 * We need to work out if the sink is expecting us to function in
+	 * dual-link mode. We do this by looking at the DT port nodes we are
+	 * connected to, if they are marked as expecting even pixels and
+	 * odd pixels than we need to enable vertical stripe output
+	 */
+	p0 = of_graph_get_port_by_id(dev->of_node, 1);
+	p1 = of_graph_get_port_by_id(companion, 1);
+	dual_link = drm_of_lvds_get_dual_link_configuration(p0, p1);
+	if (dual_link >= DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS) {
+		dev_dbg(dev, "Dual-link configuration detected\n");
+		lvds->dual_link = true;
+	} else {
+		/* dual-link mode is not required */
+		dev_dbg(dev, "Single-link configuration detected\n");
+		goto done;
+	}
+	/*
+	 * We may need to swap even and odd pixels around in case the wiring
+	 * doesn't match the default configuration.
+	 * By default we generate even pixels from this encoder and odd pixels
+	 * from the companion encoder, but if p0 is connected to the port
+	 * expecting ood pixels, and p1 is connected to the port expecting even
+	 * pixels, then we need to swap even and odd pixels around
+	 */
+	if (dual_link == DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS) {
+		dev_dbg(dev, "Data swapping required\n");
+		lvds->stripe_swap_data = true;
+	}
+
 	lvds->companion = of_drm_find_bridge(companion);
 	if (!lvds->companion) {
 		ret = -EPROBE_DEFER;
 		goto done;
 	}
+	companion_lvds = bridge_to_rcar_lvds(lvds->companion);
+	companion_lvds->dual_link = lvds->dual_link;
 
 	dev_dbg(dev, "Found companion encoder %pOF\n", companion);
 
 done:
 	of_node_put(companion);
+	of_node_put(p0);
+	of_node_put(p1);
 
 	return ret;
 }
@@ -704,10 +755,7 @@ static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds)
 static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
 {
 	struct device_node *local_output = NULL;
-	struct device_node *remote_input = NULL;
 	struct device_node *remote = NULL;
-	struct device_node *node;
-	bool is_bridge = false;
 	int ret = 0;
 
 	local_output = of_graph_get_endpoint_by_regs(lvds->dev->of_node, 1, 0);
@@ -735,45 +783,17 @@ static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
 		goto done;
 	}
 
-	remote_input = of_graph_get_remote_endpoint(local_output);
-
-	for_each_endpoint_of_node(remote, node) {
-		if (node != remote_input) {
-			/*
-			 * We've found one endpoint other than the input, this
-			 * must be a bridge.
-			 */
-			is_bridge = true;
-			of_node_put(node);
-			break;
-		}
-	}
-
-	if (is_bridge) {
-		lvds->next_bridge = of_drm_find_bridge(remote);
-		if (!lvds->next_bridge) {
-			ret = -EPROBE_DEFER;
-			goto done;
-		}
-
-		if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK)
-			lvds->dual_link = lvds->next_bridge->timings
-					? lvds->next_bridge->timings->dual_link
-					: false;
-	} else {
-		lvds->panel = of_drm_find_panel(remote);
-		if (IS_ERR(lvds->panel)) {
-			ret = PTR_ERR(lvds->panel);
-			goto done;
-		}
+	ret = drm_of_find_panel_or_bridge(lvds->dev->of_node, 1, 0,
+					  &lvds->panel, &lvds->next_bridge);
+	if (ret) {
+		ret = -EPROBE_DEFER;
+		goto done;
 	}
-
-	if (lvds->dual_link)
+	if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK)
 		ret = rcar_lvds_parse_dt_companion(lvds);
 
 done:
 	of_node_put(local_output);
-	of_node_put(remote_input);
 	of_node_put(remote);
 
 	/*
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v3 5/8] drm: bridge: thc63: Do not report input bus mode through bridge timings
  2019-08-28 18:36 [PATCH v3 0/8] Add dual-LVDS panel support to EK874 Fabrizio Castro
                   ` (3 preceding siblings ...)
  2019-08-28 18:36 ` [PATCH v3 4/8] drm: rcar-du: lvds: Add dual-LVDS panels support Fabrizio Castro
@ 2019-08-28 18:36 ` Fabrizio Castro
  2019-11-07 19:52   ` Laurent Pinchart
  2019-08-28 18:36 ` [PATCH v3 6/8] arm64: dts: renesas: Add EK874 board with idk-2121wr display support Fabrizio Castro
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 32+ messages in thread
From: Fabrizio Castro @ 2019-08-28 18:36 UTC (permalink / raw)
  To: Laurent Pinchart, Andrzej Hajda, David Airlie, Daniel Vetter,
	Maarten Lankhorst, Maxime Ripard, Sean Paul
  Cc: Fabrizio Castro, dri-devel, linux-kernel, Simon Horman,
	Geert Uytterhoeven, Chris Paterson, Biju Das, linux-renesas-soc,
	Laurent Pinchart, Kieran Bingham, Jacopo Mondi, sam

No need to report the input bus mode through bridge timings
anymore, that's now done through the DT, as specified by the
dt-bindings.

Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>

---
v2->v3:
* new patch
---
 drivers/gpu/drm/bridge/thc63lvd1024.c | 9 ++++-----
 include/drm/drm_bridge.h              | 8 --------
 2 files changed, 4 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c b/drivers/gpu/drm/bridge/thc63lvd1024.c
index 3d74129b..730f682 100644
--- a/drivers/gpu/drm/bridge/thc63lvd1024.c
+++ b/drivers/gpu/drm/bridge/thc63lvd1024.c
@@ -34,7 +34,7 @@ struct thc63_dev {
 	struct drm_bridge bridge;
 	struct drm_bridge *next;
 
-	struct drm_bridge_timings timings;
+	bool dual_link;
 };
 
 static inline struct thc63_dev *to_thc63(struct drm_bridge *bridge)
@@ -62,7 +62,7 @@ static enum drm_mode_status thc63_mode_valid(struct drm_bridge *bridge,
 	 * isn't supported by the driver yet, simply derive the limits from the
 	 * input mode.
 	 */
-	if (thc63->timings.dual_link) {
+	if (thc63->dual_link) {
 		min_freq = 40000;
 		max_freq = 150000;
 	} else {
@@ -157,13 +157,13 @@ static int thc63_parse_dt(struct thc63_dev *thc63)
 
 		if (remote) {
 			if (of_device_is_available(remote))
-				thc63->timings.dual_link = true;
+				thc63->dual_link = true;
 			of_node_put(remote);
 		}
 	}
 
 	dev_dbg(thc63->dev, "operating in %s-link mode\n",
-		thc63->timings.dual_link ? "dual" : "single");
+		thc63->dual_link ? "dual" : "single");
 
 	return 0;
 }
@@ -221,7 +221,6 @@ static int thc63_probe(struct platform_device *pdev)
 	thc63->bridge.driver_private = thc63;
 	thc63->bridge.of_node = pdev->dev.of_node;
 	thc63->bridge.funcs = &thc63_bridge_func;
-	thc63->bridge.timings = &thc63->timings;
 
 	drm_bridge_add(&thc63->bridge);
 
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 7616f65..3228018 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -362,14 +362,6 @@ struct drm_bridge_timings {
 	 * input signal after the clock edge.
 	 */
 	u32 hold_time_ps;
-	/**
-	 * @dual_link:
-	 *
-	 * True if the bus operates in dual-link mode. The exact meaning is
-	 * dependent on the bus type. For LVDS buses, this indicates that even-
-	 * and odd-numbered pixels are received on separate links.
-	 */
-	bool dual_link;
 };
 
 /**
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v3 6/8] arm64: dts: renesas: Add EK874 board with idk-2121wr display support
  2019-08-28 18:36 [PATCH v3 0/8] Add dual-LVDS panel support to EK874 Fabrizio Castro
                   ` (4 preceding siblings ...)
  2019-08-28 18:36 ` [PATCH v3 5/8] drm: bridge: thc63: Do not report input bus mode through bridge timings Fabrizio Castro
@ 2019-08-28 18:36 ` Fabrizio Castro
  2019-11-07 19:55   ` Laurent Pinchart
  2019-08-28 18:36 ` [PATCH v3 7/8] [HACK] arm64: dts: renesas: draak: Enable LVDS Fabrizio Castro
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 32+ messages in thread
From: Fabrizio Castro @ 2019-08-28 18:36 UTC (permalink / raw)
  To: Rob Herring, Mark Rutland
  Cc: Fabrizio Castro, Simon Horman, Geert Uytterhoeven, Magnus Damm,
	linux-renesas-soc, devicetree, linux-kernel, Chris Paterson,
	Biju Das, Laurent Pinchart, Kieran Bingham, Jacopo Mondi, sam,
	xu_shunji, ebiharaml

The EK874 is advertised as compatible with panel IDK-2121WR from
Advantech, however the panel isn't sold alongside the board.
A new dts, adding everything that's required to get the panel to
to work with the EK874, is the most convenient way to support the
EK874 when it's connected to the IDK-2121WR.

Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>

---
v1->v2:
* Added comment for lvds-connector-en-gpio
* Renamed &lvds0_panel_in to panel_in0
* Renamed &lvds1_panel_in to panel_in1

v2->v3:
* removed renesas,swap-data property
* added dual-lvds-odd-pixels and dual-lvds-even-pixels properties

Geert,

no need to review this patch unless they like the idea behind this
series.

Thanks,
Fab

---
 arch/arm64/boot/dts/renesas/Makefile               |   3 +-
 .../boot/dts/renesas/r8a774c0-ek874-idk-2121wr.dts | 116 +++++++++++++++++++++
 2 files changed, 118 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/boot/dts/renesas/r8a774c0-ek874-idk-2121wr.dts

diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
index 42b74c2..ce48478 100644
--- a/arch/arm64/boot/dts/renesas/Makefile
+++ b/arch/arm64/boot/dts/renesas/Makefile
@@ -1,7 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0
 dtb-$(CONFIG_ARCH_R8A774A1) += r8a774a1-hihope-rzg2m.dtb
 dtb-$(CONFIG_ARCH_R8A774A1) += r8a774a1-hihope-rzg2m-ex.dtb
-dtb-$(CONFIG_ARCH_R8A774C0) += r8a774c0-cat874.dtb r8a774c0-ek874.dtb
+dtb-$(CONFIG_ARCH_R8A774C0) += r8a774c0-cat874.dtb r8a774c0-ek874.dtb \
+			       r8a774c0-ek874-idk-2121wr.dtb
 dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-x.dtb r8a7795-h3ulcb.dtb
 dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-kf.dtb
 dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-xs.dtb
diff --git a/arch/arm64/boot/dts/renesas/r8a774c0-ek874-idk-2121wr.dts b/arch/arm64/boot/dts/renesas/r8a774c0-ek874-idk-2121wr.dts
new file mode 100644
index 0000000..a7b27d0
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a774c0-ek874-idk-2121wr.dts
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the Silicon Linux RZ/G2E evaluation kit (EK874),
+ * connected to an Advantech IDK-2121WR 21.5" LVDS panel
+ *
+ * Copyright (C) 2019 Renesas Electronics Corp.
+ */
+
+#include "r8a774c0-ek874.dts"
+
+/ {
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm5 0 50000>;
+
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+
+		power-supply = <&reg_12p0v>;
+		enable-gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>;
+	};
+
+	panel-lvds {
+		compatible = "advantech,idk-2121wr", "panel-lvds";
+
+		width-mm = <476>;
+		height-mm = <268>;
+
+		data-mapping = "vesa-24";
+
+		panel-timing {
+			clock-frequency = <148500000>;
+			hactive = <1920>;
+			vactive = <1080>;
+			hsync-len = <44>;
+			hfront-porch = <88>;
+			hback-porch = <148>;
+			vfront-porch = <4>;
+			vback-porch = <36>;
+			vsync-len = <5>;
+		};
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				dual-lvds-odd-pixels;
+				panel_in0: endpoint {
+					remote-endpoint = <&lvds0_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+				dual-lvds-even-pixels;
+				panel_in1: endpoint {
+					remote-endpoint = <&lvds1_out>;
+				};
+			};
+		};
+	};
+};
+
+&gpio0 {
+	/*
+	 * When GP0_17 is low LVDS[01] are connected to the LVDS connector
+	 * When GP0_17 is high LVDS[01] are connected to the LT8918L
+	 */
+	lvds-connector-en-gpio{
+		gpio-hog;
+		gpios = <17 GPIO_ACTIVE_HIGH>;
+		output-low;
+		line-name = "lvds-connector-en-gpio";
+	};
+};
+
+&lvds0 {
+	ports {
+		port@1 {
+			lvds0_out: endpoint {
+				remote-endpoint = <&panel_in0>;
+			};
+		};
+	};
+};
+
+&lvds1 {
+	status = "okay";
+
+	clocks = <&cpg CPG_MOD 727>, <&x13_clk>, <&extal_clk>;
+	clock-names = "fck", "dclkin.0", "extal";
+
+	ports {
+		port@1 {
+			lvds1_out: endpoint {
+				remote-endpoint = <&panel_in1>;
+			};
+		};
+	};
+};
+
+&pfc {
+	pwm5_pins: pwm5 {
+		groups = "pwm5_a";
+		function = "pwm5";
+	};
+};
+
+&pwm5 {
+	pinctrl-0 = <&pwm5_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+};
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v3 7/8] [HACK] arm64: dts: renesas: draak: Enable LVDS
  2019-08-28 18:36 [PATCH v3 0/8] Add dual-LVDS panel support to EK874 Fabrizio Castro
                   ` (5 preceding siblings ...)
  2019-08-28 18:36 ` [PATCH v3 6/8] arm64: dts: renesas: Add EK874 board with idk-2121wr display support Fabrizio Castro
@ 2019-08-28 18:36 ` Fabrizio Castro
  2019-11-07 19:57   ` Laurent Pinchart
  2019-08-28 18:36 ` [PATCH v3 8/8] [HACK] arm64: dts: renesas: draak: Enable LVDS dual-link operation Fabrizio Castro
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 32+ messages in thread
From: Fabrizio Castro @ 2019-08-28 18:36 UTC (permalink / raw)
  To: Rob Herring, Mark Rutland
  Cc: Fabrizio Castro, Simon Horman, Geert Uytterhoeven, Magnus Damm,
	linux-renesas-soc, devicetree, linux-kernel, Chris Paterson,
	Biju Das, Laurent Pinchart, Kieran Bingham, Jacopo Mondi, sam

Enable and connect the second LVDS encoder to the second LVDS input of
the THC63LVD1024 for dual-link LVDS operation. This requires changing
the default settings of SW45 and SW47 to OFF and ON respectively.

This patch is based on Laurent's dual-LVDS work:
https://patchwork.kernel.org/patch/10965045/

Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
---
v2->v3:
* new patch

Geert,

no need to review this patch unless they like the idea behind this
series.

Thanks,
Fab

---
 arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
index b38f9d4..38b9c5a 100644
--- a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
@@ -87,11 +87,20 @@
 
 			port@0 {
 				reg = <0>;
-				thc63lvd1024_in: endpoint {
+				dual-lvds-even-pixels;
+				thc63lvd1024_in0: endpoint {
 					remote-endpoint = <&lvds0_out>;
 				};
 			};
 
+			port@1 {
+				reg = <1>;
+				dual-lvds-odd-pixels;
+				thc63lvd1024_in1: endpoint {
+					remote-endpoint = <&lvds1_out>;
+				};
+			};
+
 			port@2 {
 				reg = <2>;
 				thc63lvd1024_out: endpoint {
@@ -489,7 +498,7 @@
 	ports {
 		port@1 {
 			lvds0_out: endpoint {
-				remote-endpoint = <&thc63lvd1024_in>;
+				remote-endpoint = <&thc63lvd1024_in0>;
 			};
 		};
 	};
@@ -507,6 +516,14 @@
 		 <&x13_clk>,
 		 <&extal_clk>;
 	clock-names = "fck", "dclkin.0", "extal";
+
+	ports {
+		port@1 {
+			lvds1_out: endpoint {
+				remote-endpoint = <&thc63lvd1024_in1>;
+			};
+		};
+	};
 };
 
 &ohci0 {
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH v3 8/8] [HACK] arm64: dts: renesas: draak: Enable LVDS dual-link operation
  2019-08-28 18:36 [PATCH v3 0/8] Add dual-LVDS panel support to EK874 Fabrizio Castro
                   ` (6 preceding siblings ...)
  2019-08-28 18:36 ` [PATCH v3 7/8] [HACK] arm64: dts: renesas: draak: Enable LVDS Fabrizio Castro
@ 2019-08-28 18:36 ` Fabrizio Castro
  2019-08-29 15:26 ` [PATCH v3 0/8] Add dual-LVDS panel support to EK874 Rob Herring
  2019-10-22 16:30 ` Fabrizio Castro
  9 siblings, 0 replies; 32+ messages in thread
From: Fabrizio Castro @ 2019-08-28 18:36 UTC (permalink / raw)
  To: Rob Herring, Mark Rutland
  Cc: Fabrizio Castro, Simon Horman, Geert Uytterhoeven, Magnus Damm,
	linux-renesas-soc, devicetree, linux-kernel, Chris Paterson,
	Biju Das, Laurent Pinchart, Kieran Bingham, Jacopo Mondi, sam

Enable and connect the second LVDS encoder to the second LVDS input of
the THC63LVD1024 for dual-link LVDS operation. This requires changing
the default settings of SW45 and SW47 to OFF and ON respectively.

This patch is based on Laurent's dual-LVDS work:
https://patchwork.kernel.org/patch/10965045/

Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
---
v2->v3:
* new patch

Geert,

no need to review this patch unless they like the idea behind this
series.

Thanks,
Fab

---
 arch/arm64/boot/dts/renesas/r8a77995-draak.dts | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
index 67634cb..b4b8cde 100644
--- a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
@@ -77,11 +77,20 @@
 
 			port@0 {
 				reg = <0>;
-				thc63lvd1024_in: endpoint {
+				dual-lvds-even-pixels;
+				thc63lvd1024_in0: endpoint {
 					remote-endpoint = <&lvds0_out>;
 				};
 			};
 
+			port@1 {
+				reg = <1>;
+				dual-lvds-odd-pixels;
+				thc63lvd1024_in1: endpoint {
+					remote-endpoint = <&lvds1_out>;
+				};
+			};
+
 			port@2 {
 				reg = <2>;
 				thc63lvd1024_out: endpoint {
@@ -368,24 +377,27 @@
 	ports {
 		port@1 {
 			lvds0_out: endpoint {
-				remote-endpoint = <&thc63lvd1024_in>;
+				remote-endpoint = <&thc63lvd1024_in0>;
 			};
 		};
 	};
 };
 
 &lvds1 {
-	/*
-	 * Even though the LVDS1 output is not connected, the encoder must be
-	 * enabled to supply a pixel clock to the DU for the DPAD output when
-	 * LVDS0 is in use.
-	 */
 	status = "okay";
 
 	clocks = <&cpg CPG_MOD 727>,
 		 <&x12_clk>,
 		 <&extal_clk>;
 	clock-names = "fck", "dclkin.0", "extal";
+
+	ports {
+		port@1 {
+			lvds1_out: endpoint {
+				remote-endpoint = <&thc63lvd1024_in1>;
+			};
+		};
+	};
 };
 
 &ohci0 {
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 1/8] dt-bindings: display: Add bindings for LVDS bus-timings
  2019-08-28 18:36 ` [PATCH v3 1/8] dt-bindings: display: Add bindings for LVDS bus-timings Fabrizio Castro
@ 2019-08-29  7:57   ` Geert Uytterhoeven
  2019-08-29  9:14     ` Fabrizio Castro
  2019-08-29 14:03   ` Rob Herring
  1 sibling, 1 reply; 32+ messages in thread
From: Geert Uytterhoeven @ 2019-08-29  7:57 UTC (permalink / raw)
  To: Fabrizio Castro
  Cc: David Airlie, Daniel Vetter, Rob Herring, Mark Rutland,
	DRI Development,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux Kernel Mailing List, Simon Horman, Geert Uytterhoeven,
	Chris Paterson, Biju Das, Linux-Renesas, Laurent Pinchart,
	Kieran Bingham, Jacopo Mondi, Sam Ravnborg

Hi Fabrizio,

On Wed, Aug 28, 2019 at 8:36 PM Fabrizio Castro
<fabrizio.castro@bp.renesas.com> wrote:
> Dual-LVDS connections need markers in the DT, this patch adds
> some common documentation to be referenced by both panels and
> bridges.
>
> Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>

Thanks for your patch!

> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
> @@ -0,0 +1,38 @@
> +# SPDX-License-Identifier: GPL-2.0
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/bus-timings/lvds.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Common Properties for bus timings of LVDS interfaces
> +
> +maintainers:
> +  - Thierry Reding <thierry.reding@gmail.com>
> +  - Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> +
> +description: |
> +  This document defines device tree properties common to LVDS and dual-LVDS
> +  interfaces, where a dual-LVDS interface is a dual-link connection with even
> +  pixels traveling on one connection, and with odd pixels traveling on the other
> +  connection.
> +  This document doesn't constitue a device tree binding specification by itself
> +  but is meant to be referenced by device tree bindings.
> +  When referenced from panel or bridge device tree bindings, the properties
> +  defined in this document are defined as follows. The panel and bridge device
> +  tree bindings are responsible for defining whether each property is required
> +  or optional.
> +
> +properties:
> +  dual-lvds-even-pixels:
> +    type: boolean
> +    description:
> +      This property is specific to an input port of a sink device. When
> +      specified, it marks the port as recipient of even-pixels.
> +
> +  dual-lvds-odd-pixels:
> +    type: boolean
> +    description:
> +      This property is specific to an input port of a sink device. When
> +      specified, it marks the port as recipient of odd-pixels.

Do you need the "dual-" prefix? Isn't that implied by even/odd?
Or is it better to keep it, for readability?

I'm also thinking about a possible future extension to triple or quad LVDS.
As I'm not aware of English word equivalents of even/odd for triple/quad,
perhaps this should be specified using a numerical value instead?

If I go too far, please just say so ;-)

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH v3 1/8] dt-bindings: display: Add bindings for LVDS bus-timings
  2019-08-29  7:57   ` Geert Uytterhoeven
@ 2019-08-29  9:14     ` Fabrizio Castro
  0 siblings, 0 replies; 32+ messages in thread
From: Fabrizio Castro @ 2019-08-29  9:14 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: David Airlie, Daniel Vetter, Rob Herring, Mark Rutland,
	DRI Development,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux Kernel Mailing List, Simon Horman, Geert Uytterhoeven,
	Chris Paterson, Biju Das, Linux-Renesas, Laurent Pinchart,
	Kieran Bingham, Jacopo Mondi, Sam Ravnborg

Hi Geert,

Thank you for your feedback!

> From: linux-kernel-owner@vger.kernel.org <linux-kernel-owner@vger.kernel.org> On Behalf Of Geert Uytterhoeven
> Sent: 29 August 2019 08:58
> Subject: Re: [PATCH v3 1/8] dt-bindings: display: Add bindings for LVDS bus-timings
> 
> Hi Fabrizio,
> 
> On Wed, Aug 28, 2019 at 8:36 PM Fabrizio Castro
> <fabrizio.castro@bp.renesas.com> wrote:
> > Dual-LVDS connections need markers in the DT, this patch adds
> > some common documentation to be referenced by both panels and
> > bridges.
> >
> > Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> 
> Thanks for your patch!
> 
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
> > @@ -0,0 +1,38 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/display/bus-timings/lvds.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Common Properties for bus timings of LVDS interfaces
> > +
> > +maintainers:
> > +  - Thierry Reding <thierry.reding@gmail.com>
> > +  - Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> > +
> > +description: |
> > +  This document defines device tree properties common to LVDS and dual-LVDS
> > +  interfaces, where a dual-LVDS interface is a dual-link connection with even
> > +  pixels traveling on one connection, and with odd pixels traveling on the other
> > +  connection.
> > +  This document doesn't constitue a device tree binding specification by itself
> > +  but is meant to be referenced by device tree bindings.
> > +  When referenced from panel or bridge device tree bindings, the properties
> > +  defined in this document are defined as follows. The panel and bridge device
> > +  tree bindings are responsible for defining whether each property is required
> > +  or optional.
> > +
> > +properties:
> > +  dual-lvds-even-pixels:
> > +    type: boolean
> > +    description:
> > +      This property is specific to an input port of a sink device. When
> > +      specified, it marks the port as recipient of even-pixels.
> > +
> > +  dual-lvds-odd-pixels:
> > +    type: boolean
> > +    description:
> > +      This property is specific to an input port of a sink device. When
> > +      specified, it marks the port as recipient of odd-pixels.
> 
> Do you need the "dual-" prefix? Isn't that implied by even/odd?
> Or is it better to keep it, for readability?

I decided to go with "dual-lvds-even-pixels" and "dual-lvds-odd-pixels"
because the "dual-lvds" prefix uniquely identifies the type of bus, and I
decided to go with the "pixels" suffix because "dual-lvds-odd" just doesn't
sound right. I guess "dual-lvds-even-pixels" and "dual-lvds-odd-pixels"
are the most readable and future proof labels I could think of, but maybe
there is something better we can do? Laurent?

> 
> I'm also thinking about a possible future extension to triple or quad LVDS.
> As I'm not aware of English word equivalents of even/odd for triple/quad,
> perhaps this should be specified using a numerical value instead?

I would have to see a use case for other LVDS configurations for providing
a proper answer to this question, but perhaps we could accept that other
configurations for LVDS connections may come with labels that are tailored
to help uniquely identifying the ports while being readable? Perhaps numerical
values would work better in other cases? Laurent?

> 
> If I go too far, please just say so ;-)

Definitely worth discussing!

Thanks,
Fab

> 
> Gr{oetje,eeting}s,
> 
>                         Geert
> 
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
> 
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like that.
>                                 -- Linus Torvalds

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 1/8] dt-bindings: display: Add bindings for LVDS bus-timings
  2019-08-28 18:36 ` [PATCH v3 1/8] dt-bindings: display: Add bindings for LVDS bus-timings Fabrizio Castro
  2019-08-29  7:57   ` Geert Uytterhoeven
@ 2019-08-29 14:03   ` Rob Herring
  2019-08-29 14:38     ` Fabrizio Castro
  2019-12-06 15:10     ` Fabrizio Castro
  1 sibling, 2 replies; 32+ messages in thread
From: Rob Herring @ 2019-08-29 14:03 UTC (permalink / raw)
  To: Fabrizio Castro
  Cc: David Airlie, Daniel Vetter, Mark Rutland, dri-devel, devicetree,
	linux-kernel, Simon Horman, Geert Uytterhoeven, Chris Paterson,
	Biju Das, open list:MEDIA DRIVERS FOR RENESAS - FCP,
	Laurent Pinchart, Kieran Bingham, Jacopo Mondi, Sam Ravnborg

On Wed, Aug 28, 2019 at 1:36 PM Fabrizio Castro
<fabrizio.castro@bp.renesas.com> wrote:
>
> Dual-LVDS connections need markers in the DT, this patch adds
> some common documentation to be referenced by both panels and
> bridges.
>
> Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
>
> ---
> v2->v3:
> * new patch
> ---
>  .../bindings/display/bus-timings/lvds.yaml         | 38 ++++++++++++++++++++++
>  1 file changed, 38 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
>
> diff --git a/Documentation/devicetree/bindings/display/bus-timings/lvds.yaml b/Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
> new file mode 100644
> index 0000000..f35b55a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
> @@ -0,0 +1,38 @@
> +# SPDX-License-Identifier: GPL-2.0

(GPL-2.0-only OR BSD-2-Clause) is preferred for new bindings.

> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/bus-timings/lvds.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Common Properties for bus timings of LVDS interfaces
> +
> +maintainers:
> +  - Thierry Reding <thierry.reding@gmail.com>
> +  - Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> +
> +description: |
> +  This document defines device tree properties common to LVDS and dual-LVDS
> +  interfaces, where a dual-LVDS interface is a dual-link connection with even
> +  pixels traveling on one connection, and with odd pixels traveling on the other
> +  connection.
> +  This document doesn't constitue a device tree binding specification by itself

typo: constitute

> +  but is meant to be referenced by device tree bindings.
> +  When referenced from panel or bridge device tree bindings, the properties
> +  defined in this document are defined as follows. The panel and bridge device
> +  tree bindings are responsible for defining whether each property is required
> +  or optional.
> +
> +properties:
> +  dual-lvds-even-pixels:
> +    type: boolean
> +    description:
> +      This property is specific to an input port of a sink device. When

The schema should define what nodes these go in. The description seems
to indicate in 'port' nodes (or endpoint?), but your use in the panel
binding puts them in the parent.

> +      specified, it marks the port as recipient of even-pixels.
> +
> +  dual-lvds-odd-pixels:
> +    type: boolean
> +    description:
> +      This property is specific to an input port of a sink device. When
> +      specified, it marks the port as recipient of odd-pixels.

However, I don't think you even need these. A panel's port numbers are
fixed can imply even or odd. For example port@0 can be even and port@1
can be odd. The port numbering is typically panel specific, but we may
be able to define the numbering generically if we don't already have
panels with multiple ports.

Also, aren't there dual link DSI panels?

Rob

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH v3 1/8] dt-bindings: display: Add bindings for LVDS bus-timings
  2019-08-29 14:03   ` Rob Herring
@ 2019-08-29 14:38     ` Fabrizio Castro
  2019-11-07 18:00       ` Laurent Pinchart
  2019-12-06 15:10     ` Fabrizio Castro
  1 sibling, 1 reply; 32+ messages in thread
From: Fabrizio Castro @ 2019-08-29 14:38 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Mark Rutland, dri-devel, devicetree,
	linux-kernel, Simon Horman, Geert Uytterhoeven, Chris Paterson,
	Biju Das, open list:MEDIA DRIVERS FOR RENESAS - FCP,
	Laurent Pinchart, Kieran Bingham, Jacopo Mondi, Sam Ravnborg

Hi Rob,

Thank you for your feedback!

> From: Rob Herring <robh+dt@kernel.org>
> Sent: 29 August 2019 15:03
> Subject: Re: [PATCH v3 1/8] dt-bindings: display: Add bindings for LVDS bus-timings
> 
> On Wed, Aug 28, 2019 at 1:36 PM Fabrizio Castro
> <fabrizio.castro@bp.renesas.com> wrote:
> >
> > Dual-LVDS connections need markers in the DT, this patch adds
> > some common documentation to be referenced by both panels and
> > bridges.
> >
> > Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> >
> > ---
> > v2->v3:
> > * new patch
> > ---
> >  .../bindings/display/bus-timings/lvds.yaml         | 38 ++++++++++++++++++++++
> >  1 file changed, 38 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/display/bus-timings/lvds.yaml b/Documentation/devicetree/bindings/display/bus-
> timings/lvds.yaml
> > new file mode 100644
> > index 0000000..f35b55a
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
> > @@ -0,0 +1,38 @@
> > +# SPDX-License-Identifier: GPL-2.0
> 
> (GPL-2.0-only OR BSD-2-Clause) is preferred for new bindings.
> 
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/display/bus-timings/lvds.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Common Properties for bus timings of LVDS interfaces
> > +
> > +maintainers:
> > +  - Thierry Reding <thierry.reding@gmail.com>
> > +  - Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> > +
> > +description: |
> > +  This document defines device tree properties common to LVDS and dual-LVDS
> > +  interfaces, where a dual-LVDS interface is a dual-link connection with even
> > +  pixels traveling on one connection, and with odd pixels traveling on the other
> > +  connection.
> > +  This document doesn't constitue a device tree binding specification by itself
> 
> typo: constitute

Well spotted!

> 
> > +  but is meant to be referenced by device tree bindings.
> > +  When referenced from panel or bridge device tree bindings, the properties
> > +  defined in this document are defined as follows. The panel and bridge device
> > +  tree bindings are responsible for defining whether each property is required
> > +  or optional.
> > +
> > +properties:
> > +  dual-lvds-even-pixels:
> > +    type: boolean
> > +    description:
> > +      This property is specific to an input port of a sink device. When
> 
> The schema should define what nodes these go in. The description seems
> to indicate in 'port' nodes (or endpoint?), but your use in the panel
> binding puts them in the parent.

Did you manage to read this?
https://patchwork.kernel.org/cover/11119607/

Could you please advice on how to do this properly?

> 
> > +      specified, it marks the port as recipient of even-pixels.
> > +
> > +  dual-lvds-odd-pixels:
> > +    type: boolean
> > +    description:
> > +      This property is specific to an input port of a sink device. When
> > +      specified, it marks the port as recipient of odd-pixels.
> 
> However, I don't think you even need these. A panel's port numbers are
> fixed can imply even or odd. For example port@0 can be even and port@1
> can be odd. The port numbering is typically panel specific, but we may
> be able to define the numbering generically if we don't already have
> panels with multiple ports.
> 
> Also, aren't there dual link DSI panels?

This is the result of a discussion on here:
https://patchwork.kernel.org/patch/11095547/

Have you come across it?

Thanks!
Fab

> 
> Rob

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 0/8] Add dual-LVDS panel support to EK874
  2019-08-28 18:36 [PATCH v3 0/8] Add dual-LVDS panel support to EK874 Fabrizio Castro
                   ` (7 preceding siblings ...)
  2019-08-28 18:36 ` [PATCH v3 8/8] [HACK] arm64: dts: renesas: draak: Enable LVDS dual-link operation Fabrizio Castro
@ 2019-08-29 15:26 ` Rob Herring
  2019-09-02 10:01   ` Fabrizio Castro
  2019-10-22 16:30 ` Fabrizio Castro
  9 siblings, 1 reply; 32+ messages in thread
From: Rob Herring @ 2019-08-29 15:26 UTC (permalink / raw)
  To: Fabrizio Castro
  Cc: Laurent Pinchart, Geert Uytterhoeven, David Airlie,
	Daniel Vetter, Mark Rutland, Thierry Reding, Maarten Lankhorst,
	Maxime Ripard, Sean Paul, Andrzej Hajda, Sam Ravnborg,
	Simon Horman, Magnus Damm, Kieran Bingham, dri-devel, devicetree,
	linux-kernel, open list:MEDIA DRIVERS FOR RENESAS - FCP,
	Chris Paterson, Biju Das, Jacopo Mondi, xu_shunji, ebiharaml

On Wed, Aug 28, 2019 at 1:36 PM Fabrizio Castro
<fabrizio.castro@bp.renesas.com> wrote:
>
> Dear All,
>
> this series adds support for dual-LVDS panel IDK-2121WR
> from Advantech:
> https://buy.advantech.eu/Displays/Embedded-LCD-Kits-High-Brightness/model-IDK-2121WR-K2FHA2E.htm
>
> V3 approaches the problem in a completely different way, we now
> have two new properties to mark the ports in the DT as receiving
> even pixels and odd pixels: dual-lvds-even-pixels and dual-lvds-odd-pixels,
> which means device drivers should not use bridge specific or panel
> specific dual_link flags. Also, in this case the DT describes the
> connection fully.
>
> In order for the solution to be generic, I have exported a new helper
> (drm_of_lvds_get_dual_link_configuration) to walk the device tree,
> and figure out if the connection is dual-LVDS. The same helper gives
> information about the configuration of the connection. If Px is connected
> to a port expecting even pixels and Py is connected to a port expecting
> odd pixels, then the helper returns DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS
> (like in the example below), otherwise it returns
> DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS.
>
>
>  --------            dual-lvds-even-pixels  --------
> |        |----                         ----|        |
> |        | Px |---------------------->| Pn |        |
> |        |----                         ----|        |
> | SOURCE |           dual-lvds-odd-pixels  |  SINK  |
> |        |----                         ----|        |
> |        | Py |---------------------->| Pm |        |
> |        |----                         ----|        |
>  --------                                   --------
>
> The device driver for the encoder then will work out if with the current
> wiring the pixels need swapping or not.
>
> The same solution works for both panels and bridges.
>
> Since the DT describes the connection fully, driver
> drivers/gpu/drm/panel/panel-lvds.c works out-of-the-box, no changes
> required, however, this implementation opens up a problem with the
> dt-bindings.
> Driver drivers/gpu/drm/panel/panel-lvds.c can still be pleased by
> a port node, but also by a ports node.
> I have created Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
> with the idea of including it from panels and bridges dt-bindings
> supporting dual-LVDS (and of course the dt-bindings for the specific
> devices should say which port should be marked as what), but file
> Documentation/devicetree/bindings/display/panel/lvds.yaml formally
> requires property "port", while with this implementation it should require
> OneOf "port" and "ports", and unfortunately I can't seem to find a neat way
> aroud that, other than creating a new compatible string

Just add 'ports' and drop 'port' from being required in the common
binding. Then it is up to the panel specific bindings to define which
one is required. Or we just leave it to allow either form which the
graph code can handle.

We could have this in the common binding:

oneOf:
 - required: [ports]
 - required: [port]

Rob

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH v3 0/8] Add dual-LVDS panel support to EK874
  2019-08-29 15:26 ` [PATCH v3 0/8] Add dual-LVDS panel support to EK874 Rob Herring
@ 2019-09-02 10:01   ` Fabrizio Castro
  0 siblings, 0 replies; 32+ messages in thread
From: Fabrizio Castro @ 2019-09-02 10:01 UTC (permalink / raw)
  To: Rob Herring, Laurent Pinchart
  Cc: Geert Uytterhoeven, David Airlie, Daniel Vetter, Mark Rutland,
	Thierry Reding, Maarten Lankhorst, Maxime Ripard, Sean Paul,
	Andrzej Hajda, Sam Ravnborg, Simon Horman, Magnus Damm,
	Kieran Bingham, dri-devel, devicetree, linux-kernel,
	open list:MEDIA DRIVERS FOR RENESAS - FCP, Chris Paterson,
	Biju Das, Jacopo Mondi, xu_shunji, ebiharaml

Hi Rob,

Thank you for your feedback!

> From: Rob Herring <robh+dt@kernel.org>
> Sent: 29 August 2019 16:27
> To: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> Subject: Re: [PATCH v3 0/8] Add dual-LVDS panel support to EK874
> 
> On Wed, Aug 28, 2019 at 1:36 PM Fabrizio Castro
> <fabrizio.castro@bp.renesas.com> wrote:
> >
> > Dear All,
> >
> > this series adds support for dual-LVDS panel IDK-2121WR
> > from Advantech:
> > https://buy.advantech.eu/Displays/Embedded-LCD-Kits-High-Brightness/model-IDK-2121WR-K2FHA2E.htm
> >
> > V3 approaches the problem in a completely different way, we now
> > have two new properties to mark the ports in the DT as receiving
> > even pixels and odd pixels: dual-lvds-even-pixels and dual-lvds-odd-pixels,
> > which means device drivers should not use bridge specific or panel
> > specific dual_link flags. Also, in this case the DT describes the
> > connection fully.
> >
> > In order for the solution to be generic, I have exported a new helper
> > (drm_of_lvds_get_dual_link_configuration) to walk the device tree,
> > and figure out if the connection is dual-LVDS. The same helper gives
> > information about the configuration of the connection. If Px is connected
> > to a port expecting even pixels and Py is connected to a port expecting
> > odd pixels, then the helper returns DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS
> > (like in the example below), otherwise it returns
> > DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS.
> >
> >
> >  --------            dual-lvds-even-pixels  --------
> > |        |----                         ----|        |
> > |        | Px |---------------------->| Pn |        |
> > |        |----                         ----|        |
> > | SOURCE |           dual-lvds-odd-pixels  |  SINK  |
> > |        |----                         ----|        |
> > |        | Py |---------------------->| Pm |        |
> > |        |----                         ----|        |
> >  --------                                   --------
> >
> > The device driver for the encoder then will work out if with the current
> > wiring the pixels need swapping or not.
> >
> > The same solution works for both panels and bridges.
> >
> > Since the DT describes the connection fully, driver
> > drivers/gpu/drm/panel/panel-lvds.c works out-of-the-box, no changes
> > required, however, this implementation opens up a problem with the
> > dt-bindings.
> > Driver drivers/gpu/drm/panel/panel-lvds.c can still be pleased by
> > a port node, but also by a ports node.
> > I have created Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
> > with the idea of including it from panels and bridges dt-bindings
> > supporting dual-LVDS (and of course the dt-bindings for the specific
> > devices should say which port should be marked as what), but file
> > Documentation/devicetree/bindings/display/panel/lvds.yaml formally
> > requires property "port", while with this implementation it should require
> > OneOf "port" and "ports", and unfortunately I can't seem to find a neat way
> > aroud that, other than creating a new compatible string
> 
> Just add 'ports' and drop 'port' from being required in the common
> binding. Then it is up to the panel specific bindings to define which
> one is required. Or we just leave it to allow either form which the
> graph code can handle.
> 
> We could have this in the common binding:
> 
> oneOf:
>  - required: [ports]
>  - required: [port]


Thank you for Rob for looking into this. I will wait for a feedback from Laurent
on the code before sending out v4.

Thanks,
Fab

> 
> Rob

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH v3 0/8] Add dual-LVDS panel support to EK874
  2019-08-28 18:36 [PATCH v3 0/8] Add dual-LVDS panel support to EK874 Fabrizio Castro
                   ` (8 preceding siblings ...)
  2019-08-29 15:26 ` [PATCH v3 0/8] Add dual-LVDS panel support to EK874 Rob Herring
@ 2019-10-22 16:30 ` Fabrizio Castro
  9 siblings, 0 replies; 32+ messages in thread
From: Fabrizio Castro @ 2019-10-22 16:30 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Sam Ravnborg, Simon Horman, Magnus Damm, Kieran Bingham,
	dri-devel, devicetree, linux-kernel, linux-renesas-soc,
	Chris Paterson, Biju Das, Laurent Pinchart, Jacopo Mondi,
	ebiharaml, Fabrizio Castro, Geert Uytterhoeven, David Airlie,
	Daniel Vetter, Rob Herring, Mark Rutland, Thierry Reding,
	Maxime Ripard, Maarten Lankhorst, Sean Paul, Andrzej Hajda

Hi Laurent,

Did you have any time to look into this series?

Thanks,
Fab

> From: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> Sent: 28 August 2019 19:37
> Subject: [PATCH v3 0/8] Add dual-LVDS panel support to EK874
> 
> Dear All,
> 
> this series adds support for dual-LVDS panel IDK-2121WR
> from Advantech:
> https://buy.advantech.eu/Displays/Embedded-LCD-Kits-High-Brightness/model-IDK-2121WR-K2FHA2E.htm
> 
> V3 approaches the problem in a completely different way, we now
> have two new properties to mark the ports in the DT as receiving
> even pixels and odd pixels: dual-lvds-even-pixels and dual-lvds-odd-pixels,
> which means device drivers should not use bridge specific or panel
> specific dual_link flags. Also, in this case the DT describes the
> connection fully.
> 
> In order for the solution to be generic, I have exported a new helper
> (drm_of_lvds_get_dual_link_configuration) to walk the device tree,
> and figure out if the connection is dual-LVDS. The same helper gives
> information about the configuration of the connection. If Px is connected
> to a port expecting even pixels and Py is connected to a port expecting
> odd pixels, then the helper returns DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS
> (like in the example below), otherwise it returns
> DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS.
> 
> 
>  --------            dual-lvds-even-pixels  --------
> |        |----                         ----|        |
> |        | Px |---------------------->| Pn |        |
> |        |----                         ----|        |
> | SOURCE |           dual-lvds-odd-pixels  |  SINK  |
> |        |----                         ----|        |
> |        | Py |---------------------->| Pm |        |
> |        |----                         ----|        |
>  --------                                   --------
> 
> The device driver for the encoder then will work out if with the current
> wiring the pixels need swapping or not.
> 
> The same solution works for both panels and bridges.
> 
> Since the DT describes the connection fully, driver
> drivers/gpu/drm/panel/panel-lvds.c works out-of-the-box, no changes
> required, however, this implementation opens up a problem with the
> dt-bindings.
> Driver drivers/gpu/drm/panel/panel-lvds.c can still be pleased by
> a port node, but also by a ports node.
> I have created Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
> with the idea of including it from panels and bridges dt-bindings
> supporting dual-LVDS (and of course the dt-bindings for the specific
> devices should say which port should be marked as what), but file
> Documentation/devicetree/bindings/display/panel/lvds.yaml formally
> requires property "port", while with this implementation it should require
> OneOf "port" and "ports", and unfortunately I can't seem to find a neat way
> aroud that, other than creating a new compatible string
> (e.g. "panel-dual-lvds"), a new dt-binding document for it, and of course adding
> support for the new compatible string to drivers/gpu/drm/panel/panel-lvds.c.
> As a result, this series is missing (at least) a patch necessary to fully
> document the new implementation within
> Documentation/devicetree/bindings/display/panel/lvds.yaml
> 
> Rob, do you have any suggestions? Do you think this idea works ok from a
> documentation point of view? By the way, I don't really know what I am doing
> with the yaml dt-bindings, I hope you won't be horrified by this series :-P
> 
> I hope I was able to deliver the concept clearly, if not please just ask.
> 
> Comments are very much appreciated.
> 
> Thanks,
> Fab
> 
> Fabrizio Castro (8):
>   dt-bindings: display: Add bindings for LVDS bus-timings
>   dt-bindings: display: Add idk-2121wr binding
>   drm: Add bus timings helper
>   drm: rcar-du: lvds: Add dual-LVDS panels support
>   drm: bridge: thc63: Do not report input bus mode through bridge
>     timings
>   arm64: dts: renesas: Add EK874 board with idk-2121wr display support
>   [HACK] arm64: dts: renesas: draak: Enable LVDS
>   [HACK] arm64: dts: renesas: draak: Enable LVDS dual-link operation
> 
>  .../bindings/display/bus-timings/lvds.yaml         |  38 +++++++
>  .../display/panel/advantech,idk-2121wr.yaml        |  90 ++++++++++++++++
>  arch/arm64/boot/dts/renesas/Makefile               |   3 +-
>  .../boot/dts/renesas/r8a774c0-ek874-idk-2121wr.dts | 116 +++++++++++++++++++++
>  arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts     |  21 +++-
>  arch/arm64/boot/dts/renesas/r8a77995-draak.dts     |  26 +++--
>  drivers/gpu/drm/Makefile                           |   3 +-
>  drivers/gpu/drm/bridge/thc63lvd1024.c              |   9 +-
>  drivers/gpu/drm/drm_bus_timings.c                  |  97 +++++++++++++++++
>  drivers/gpu/drm/rcar-du/rcar_lvds.c                | 110 +++++++++++--------
>  include/drm/drm_bridge.h                           |   8 --
>  include/drm/drm_bus_timings.h                      |  21 ++++
>  12 files changed, 473 insertions(+), 69 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
>  create mode 100644 Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml
>  create mode 100644 arch/arm64/boot/dts/renesas/r8a774c0-ek874-idk-2121wr.dts
>  create mode 100644 drivers/gpu/drm/drm_bus_timings.c
>  create mode 100644 include/drm/drm_bus_timings.h
> 
> --
> 2.7.4


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 1/8] dt-bindings: display: Add bindings for LVDS bus-timings
  2019-08-29 14:38     ` Fabrizio Castro
@ 2019-11-07 18:00       ` Laurent Pinchart
  2019-12-06 15:11         ` Fabrizio Castro
  0 siblings, 1 reply; 32+ messages in thread
From: Laurent Pinchart @ 2019-11-07 18:00 UTC (permalink / raw)
  To: Fabrizio Castro
  Cc: Rob Herring, David Airlie, Daniel Vetter, Mark Rutland,
	dri-devel, devicetree, linux-kernel, Simon Horman,
	Geert Uytterhoeven, Chris Paterson, Biju Das,
	open list:MEDIA DRIVERS FOR RENESAS - FCP, Kieran Bingham,
	Jacopo Mondi, Sam Ravnborg

Hello Fabrizio,

On Thu, Aug 29, 2019 at 02:38:06PM +0000, Fabrizio Castro wrote:
> On 29 August 2019 15:03 Rob Herring wrote:
> > On Wed, Aug 28, 2019 at 1:36 PM Fabrizio Castro wrote:
> >>
> >> Dual-LVDS connections need markers in the DT, this patch adds
> >> some common documentation to be referenced by both panels and
> >> bridges.
> >>
> >> Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> >>
> >> ---
> >> v2->v3:
> >> * new patch
> >> ---
> >>  .../bindings/display/bus-timings/lvds.yaml         | 38 ++++++++++++++++++++++
> >>  1 file changed, 38 insertions(+)
> >>  create mode 100644 Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
> >>
> >> diff --git a/Documentation/devicetree/bindings/display/bus-timings/lvds.yaml b/Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
> >> new file mode 100644
> >> index 0000000..f35b55a
> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
> >> @@ -0,0 +1,38 @@
> >> +# SPDX-License-Identifier: GPL-2.0
> > 
> > (GPL-2.0-only OR BSD-2-Clause) is preferred for new bindings.
> > 
> >> +%YAML 1.2
> >> +---
> >> +$id: http://devicetree.org/schemas/display/bus-timings/lvds.yaml#
> >> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> >> +
> >> +title: Common Properties for bus timings of LVDS interfaces
> >> +
> >> +maintainers:
> >> +  - Thierry Reding <thierry.reding@gmail.com>
> >> +  - Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> >> +
> >> +description: |
> >> +  This document defines device tree properties common to LVDS and dual-LVDS
> >> +  interfaces, where a dual-LVDS interface is a dual-link connection with even
> >> +  pixels traveling on one connection, and with odd pixels traveling on the other
> >> +  connection.

As you define a dual-LVDS interface as "a dual-link connection", should
this be "even pixels traveling on one link, and with odd pixels
traveling on the other link" ?

> >> +  This document doesn't constitue a device tree binding specification by itself
> > 
> > typo: constitute
> 
> Well spotted!
> 
> >> +  but is meant to be referenced by device tree bindings.
> >> +  When referenced from panel or bridge device tree bindings, the properties
> >> +  defined in this document are defined as follows. The panel and bridge device
> >> +  tree bindings are responsible for defining whether each property is required
> >> +  or optional.
> >> +
> >> +properties:
> >> +  dual-lvds-even-pixels:
> >> +    type: boolean
> >> +    description:
> >> +      This property is specific to an input port of a sink device. When
> > 
> > The schema should define what nodes these go in. The description seems
> > to indicate in 'port' nodes (or endpoint?), but your use in the panel
> > binding puts them in the parent.
> 
> Did you manage to read this?
> https://patchwork.kernel.org/cover/11119607/
> 
> Could you please advice on how to do this properly?
> 
> >> +      specified, it marks the port as recipient of even-pixels.
> >> +
> >> +  dual-lvds-odd-pixels:
> >> +    type: boolean
> >> +    description:
> >> +      This property is specific to an input port of a sink device. When
> >> +      specified, it marks the port as recipient of odd-pixels.
> > 
> > However, I don't think you even need these. A panel's port numbers are
> > fixed can imply even or odd. For example port@0 can be even and port@1
> > can be odd. The port numbering is typically panel specific, but we may
> > be able to define the numbering generically if we don't already have
> > panels with multiple ports.
> > 
> > Also, aren't there dual link DSI panels?
> 
> This is the result of a discussion on here:
> https://patchwork.kernel.org/patch/11095547/
> 
> Have you come across it?

Let me repeat my comments from that thread for Rob in order to
centralize the discussion here.

> Taking one step back to look at the big picture, what we need is for the
> source to know what pixel (odd or even) to send on each LVDS output. For
> that it needs to know what pixel is expected by the sink the the inputs
> connected to the source's outputs. From each source output we can easily
> locate the DT nodes corresponding to the connected sink's input ports,
> but that doesn't give us enough information. From there, we could
> 
> - Infer the odd/even pixel expected by the source based on the port
>   numbers. This would require common DT bindings for all dual-link LVDS
>   sinks that specify the port ordering (for instance the bindings could
>   mandate that lowest numbered port correspond to even pixels).
> 
> - Read the odd/even pixel expected by the source from an explicit DT
>   property, as proposed above. This would also require common DT
>   bindings for all dual-link LVDS sinks that define these new
>   properties. This would I think be better than implicitly infering it
>   from DT port numbers.
> 
> - Retrieve the information from the sink drm_bridge at runtime. This
>   would require a way to query the bridge for the mapping from port
>   number to odd/even pixel. The DRM_LINK_DUAL_LVDS_ODD_EVEN flag could
>   be used for that, and would then be defined as "the lowest numbered
>   port corresponds to odd pixels and the highest numbered port
>   corresponds to even pixels".
> 
> The second and third options would both work I think. The third one is
> roughly what you've implemented, except that I think the flag
> description should be clarified.

Rob, what's your opinion ? We could certainly, in the context of a
panel, decide of a fixed mapping of port numbers to odd/even pixels, but
the issue is that sources need to know which pixels to send on which
link (assuming of course that this can be configured on the source
side). We thus need a way for the source to answer, at runtime, the
question "which of ports A and B of the sink correspond to even and odd
pixels ?". This can't be inferred by the source from the sink port
numbers, as the mapping between port number and odd/even pixels is
specific to each sink. We thus need to either store that property in the
DT node of the sink (option 2) or query it at runtime from the sink
(option 3).

I like option 2 as it's more explicit, but option 3 minimizes the
required properties in DT, which is always good. Patch 3/8 introduces a
helper that abstracts this from a sink point of view (which I think is a
very good idea), so once we decide which option to use, only 3/8 may
need to be adapted, the other patches should hopefully not require
rework.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 2/8] dt-bindings: display: Add idk-2121wr binding
  2019-08-28 18:36 ` [PATCH v3 2/8] dt-bindings: display: Add idk-2121wr binding Fabrizio Castro
@ 2019-11-07 18:12   ` Laurent Pinchart
  2019-12-06 15:17     ` Fabrizio Castro
  0 siblings, 1 reply; 32+ messages in thread
From: Laurent Pinchart @ 2019-11-07 18:12 UTC (permalink / raw)
  To: Fabrizio Castro
  Cc: Thierry Reding, David Airlie, Daniel Vetter, Rob Herring,
	Mark Rutland, Sam Ravnborg, dri-devel, devicetree, linux-kernel,
	Simon Horman, Geert Uytterhoeven, Chris Paterson, Biju Das,
	linux-renesas-soc, Kieran Bingham, Jacopo Mondi

Hi Fabrizio,

Thank you for the patch.

On Wed, Aug 28, 2019 at 07:36:36PM +0100, Fabrizio Castro wrote:
> Add binding for the idk-2121wr LVDS panel from Advantech.
> 
> Some panel-specific documentation can be found here:
> https://buy.advantech.eu/Displays/Embedded-LCD-Kits-High-Brightness/model-IDK-2121WR-K2FHA2E.htm
> 
> Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> 
> ---
> v2->v3:
> * new patch
> ---
>  .../display/panel/advantech,idk-2121wr.yaml        | 90 ++++++++++++++++++++++
>  1 file changed, 90 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml
> 
> diff --git a/Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml b/Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml
> new file mode 100644
> index 0000000..b2ccdc8
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml
> @@ -0,0 +1,90 @@
> +# SPDX-License-Identifier: GPL-2.0
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/panel/advantech,idk-2121wr.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Advantech IDK-2121WR 21.5" Full-HD dual-LVDS panel
> +
> +maintainers:
> +  - Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> +  - Thierry Reding <thierry.reding@gmail.com>
> +
> +description: |
> +  The IDK-2121WR from Advantech is a Full-HD dual-LVDS panel.
> +
> +  The panels expects odd pixels from the first port, and even pixels from

s/panels/panel/
Maybe s/from the/on the/g ?

> +  the second port, therefore the ports must be marked accordingly.
> +
> +allOf:
> +  - $ref: lvds.yaml#
> +  - $ref: ../bus-timings/lvds.yaml#
> +
> +properties:
> +  compatible:
> +    items:
> +      - const: advantech,idk-2121wr
> +      - {} # panel-lvds, but not listed here to avoid false select
> +
> +  data-mapping:
> +    const: vesa-24
> +
> +  width-mm:
> +    const: 476
> +
> +  height-mm:
> +    const: 268
> +
> +  panel-timing: true
> +  ports: true
> +
> +additionalProperties: false
> +
> +required:
> +  - compatible

Shouldn't data-mapping, width-mm, height-mm and ports be required too ?

As you mentioned in the cover letter, validating ports, port and the new
dual-lvds-*-pixels properties would be nice. I'm not YAML schema
specialist, so I'm fine with a best effort approach here, but as far as
I understand Rob proposed a way forward, could you try it ?

Apart from that, the bindings look sne to me, so

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

once the above issues get addressed.

> +
> +examples:
> +  - |+
> +    panel-lvds {
> +      compatible = "advantech,idk-2121wr", "panel-lvds";
> +
> +      width-mm = <476>;
> +      height-mm = <268>;
> +
> +      data-mapping = "vesa-24";
> +
> +      panel-timing {
> +        clock-frequency = <148500000>;
> +        hactive = <1920>;
> +        vactive = <1080>;
> +        hsync-len = <44>;
> +        hfront-porch = <88>;
> +        hback-porch = <148>;
> +        vfront-porch = <4>;
> +        vback-porch = <36>;
> +        vsync-len = <5>;
> +      };
> +
> +      ports {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        port@0 {
> +          reg = <0>;
> +          dual-lvds-odd-pixels;
> +          panel_in0: endpoint {
> +            remote-endpoint = <&lvds0_out>;
> +          };
> +        };
> +
> +        port@1 {
> +          reg = <1>;
> +          dual-lvds-even-pixels;
> +          panel_in1: endpoint {
> +            remote-endpoint = <&lvds1_out>;
> +          };
> +        };
> +      };
> +    };
> +
> +...

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 3/8] drm: Add bus timings helper
  2019-08-28 18:36 ` [PATCH v3 3/8] drm: Add bus timings helper Fabrizio Castro
@ 2019-11-07 19:26   ` Laurent Pinchart
  2019-11-07 19:30     ` Daniel Vetter
  2019-12-06 15:24     ` Fabrizio Castro
  0 siblings, 2 replies; 32+ messages in thread
From: Laurent Pinchart @ 2019-11-07 19:26 UTC (permalink / raw)
  To: Fabrizio Castro
  Cc: Maarten Lankhorst, Maxime Ripard, Sean Paul, David Airlie,
	Daniel Vetter, linux-kernel, dri-devel, Simon Horman,
	Geert Uytterhoeven, Chris Paterson, Biju Das, linux-renesas-soc,
	Kieran Bingham, Jacopo Mondi, sam

Hi Fabrizio,

Thank you for the patch.

On Wed, Aug 28, 2019 at 07:36:37PM +0100, Fabrizio Castro wrote:
> Helper to provide bus timing information.

You may want to expand this a bit. And actually fix it too, as the
helper you introduce isn't related to timings (same for the subject
line).

> Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> 
> ---
> v2->v3:
> * new patch
> ---
>  drivers/gpu/drm/Makefile          |  3 +-
>  drivers/gpu/drm/drm_bus_timings.c | 97 +++++++++++++++++++++++++++++++++++++++
>  include/drm/drm_bus_timings.h     | 21 +++++++++
>  3 files changed, 120 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/drm_bus_timings.c
>  create mode 100644 include/drm/drm_bus_timings.h
> 
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index 9f0d2ee..a270063 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -17,7 +17,8 @@ drm-y       :=	drm_auth.o drm_cache.o \
>  		drm_plane.o drm_color_mgmt.o drm_print.o \
>  		drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
>  		drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \
> -		drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o
> +		drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o \
> +		drm_bus_timings.o
>  
>  drm-$(CONFIG_DRM_LEGACY) += drm_legacy_misc.o drm_bufs.o drm_context.o drm_dma.o drm_scatter.o drm_lock.o
>  drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
> diff --git a/drivers/gpu/drm/drm_bus_timings.c b/drivers/gpu/drm/drm_bus_timings.c
> new file mode 100644
> index 0000000..e2ecd22
> --- /dev/null
> +++ b/drivers/gpu/drm/drm_bus_timings.c
> @@ -0,0 +1,97 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <drm/drm_bus_timings.h>
> +#include <linux/errno.h>
> +#include <linux/of_graph.h>
> +#include <linux/of.h>
> +#include <linux/types.h>
> +
> +#define DRM_OF_LVDS_ODD		1
> +#define DRM_OF_LVDS_EVEN	2
> +
> +static int drm_of_lvds_get_port_pixels_type(struct device_node *port_node)
> +{
> +	bool even_pixels, odd_pixels;
> +
> +	even_pixels = of_property_read_bool(port_node, "dual-lvds-even-pixels");
> +	odd_pixels = of_property_read_bool(port_node, "dual-lvds-odd-pixels");
> +	return  even_pixels * DRM_OF_LVDS_EVEN + odd_pixels * DRM_OF_LVDS_ODD;

s/  / /

But I would make these bitflags.

enum drm_of_lvds_pixels {
	DRM_OF_LVDS_EVEN = BIT(0),
	DRM_OF_LVDS_ODD = BIT(1),
};

static int drm_of_lvds_get_port_pixels_type(struct device_node *port)
{
	bool even_pixels = of_property_read_bool(port, "dual-lvds-even-pixels");
	bool odd_pixels = of_property_read_bool(port, "dual-lvds-odd-pixels");

	return (even_pixels ? DRM_OF_LVDS_EVEN : 0) |
	       (odd_pixels ? DRM_OF_LVDS_ODD : 0);
}

> +}
> +
> +/**
> + * drm_of_lvds_get_dual_link_configuration - get the dual-LVDS configuration

Should we name this drm_of_lvds_get_dual_link_pixel_order to better
reflect its purpose ?

> + * @p1: device tree node corresponding to the first port of the source
> + * @p2: device tree node corresponding to the second port of the source

Maybe port1 and port2 to make this more explicit ?

> + *
> + * An LVDS dual-link bus is made of two connections, even pixels transit on one
> + * connection, and odd pixels transit on the other connection.

To match the DT bindings documentation, I would recommand

"An LVDS dual-link connection is made of two links, with even pixels
transitting on one link, and odd pixels on the other link."

> + * This function walks the DT (from the source ports to the sink ports) looking
> + * for a dual-LVDS bus. A dual-LVDS bus is identfied by markers found on the DT
> + * ports of the sink device(s). If such a bus is found, this function returns
> + * its configuration (either p1 connected to the even pixels port and p2
> + * connected to the odd pixels port, or p1 connected to the odd pixels port and
> + * p2 connected to the even pixels port).

"walking the DT" sounds like the function goes through the whole graph.
How about the following ?

/**
 * drm_of_lvds_get_dual_link_pixel_order - Get LVDS dual-link pixel order
 * @port1: First DT port node of the Dual-link LVDS source
 * @port2: Second DT port node of the Dual-link LVDS source
 *
 * An LVDS dual-link connection is made of two links, with even pixels
 * transitting on one link, and odd pixels on the other link. This function
 * returns, for two ports of an LVDS dual-link source, which port shall transmit
 * the even and off pixels, based on the requirements of the connected sink.
 *
 * The pixel order is determined from the dual-lvds-even-pixels and
 * dual-lvds-odd-pixels properties in the sink's DT port nodes. If those
 * properties are not present, or if their usage is not valid, this function
 * returns -EINVAL.
 *
 * @port1 and @port2 are typically DT sibling nodes, but may have different
 * parents when, for instance, two separate LVDS encoders carry the even and odd
 * pixels.
 *
 * Return:
 * * DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS - @port1 carries even pixels and @port2
 *   carries odd pixels
 * * DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS - @port1 carries odd pixels and @port1
 *   carries even pixels
 * * -EINVAL - @port1 and @port2 are not connected to a dual-link LVDS sink, or
 *   the sink configuration is invalid
 */

We could also add -EPIPE as a return code for the case where port1 or
port2 are not connected.

> + *
> + * Return: A code describing the bus configuration when a valid dual-LVDS bus is
> + * found, or an error code when no valid dual-LVDS bus is found
> + *
> + * Possible codes for the bus configuration are:
> + *
> + * - DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS: when p1 is connected to the even pixels
> + *   port and p2 is connected to the odd pixels port
> + * - DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS: when p1 is connected to the odd pixels
> + *   port and p2 is connected to the even pixels port
> + *
> + */
> +int drm_of_lvds_get_dual_link_configuration(const struct device_node *p1,
> +					    const struct device_node *p2)
> +{
> +	struct device_node *remote_p1 = NULL, *remote_p2 = NULL;
> +	struct device_node *parent_p1 = NULL, *parent_p2 = NULL;

There's no need to initialize those two variables.

> +	struct device_node *ep1 = NULL, *ep2 = NULL;
> +	u32 reg_p1, reg_p2;
> +	int ret = -EINVAL, remote_p1_pt, remote_p2_pt;

Please split this last line, as it otherwise hides the initialization of
ret in the middle.

> +
> +	if (!p1 || !p2)
> +		return ret;

You can return -EINVAL directly.


> +	if (of_property_read_u32(p1, "reg", &reg_p1) ||
> +	    of_property_read_u32(p2, "reg", &reg_p2))
> +		return ret;

Same here.

> +	parent_p1 = of_get_parent(p1);
> +	parent_p2 = of_get_parent(p2);
> +	if (!parent_p1 || !parent_p2)
> +		goto done;
> +	ep1 = of_graph_get_endpoint_by_regs(parent_p1, reg_p1, 0);
> +	ep2 = of_graph_get_endpoint_by_regs(parent_p2, reg_p2, 0);
> +	if (!ep1 || !ep2)
> +		goto done;

If you only support the first endpoint, this should be mentioned in the
documentation. Alternatively you could pass the endpoint nodes instead
of the port nodes, or you could pass the endpoint number.

It's also a bit inefficient to use of_graph_get_endpoint_by_regs() when
you already have the port nodes. How about adding the following helper
function ?

struct device_node *of_graph_get_port_endpoint(struct device_node *port, int reg)
{
	struct device_node *endpoint = NULL;

	for_each_child_of_node(port, endpoint) {
		u32 id;

		if (!of_node_name_eq(endpoint, "endpoint") ||
			continue;

		if (reg == -1)
			return endpoint;

		if (of_property_read_u32(node, "reg", &id) < 0)
			continue;

		if (reg == id)
			return endpoint;
	}

	return NULL;
}

If you're concerned that adding a core helper would delay this patch
series, you could add it as a local helper, and move it to of_graph.h in
a second step.

> +	remote_p1 = of_graph_get_remote_port(ep1);
> +	remote_p2 = of_graph_get_remote_port(ep2);
> +	if (!remote_p1 || !remote_p2)
> +		goto done;
> +	remote_p1_pt = drm_of_lvds_get_port_pixels_type(remote_p1);
> +	remote_p2_pt = drm_of_lvds_get_port_pixels_type(remote_p2);
> +	/*
> +	 * A valid dual-lVDS bus is found when one remote port is marked with
> +	 * "dual-lvds-even-pixels", and the other remote port is marked with
> +	 * "dual-lvds-odd-pixels", bail out if the markers are not right.
> +	 */
> +	if (!remote_p1_pt || !remote_p2_pt ||
> +	    remote_p1_pt + remote_p2_pt != DRM_OF_LVDS_EVEN + DRM_OF_LVDS_ODD)
> +		goto done;
> +	if (remote_p1_pt == DRM_OF_LVDS_EVEN)
> +		/* The sink expects even pixels through the first port */
> +		ret = DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS;
> +	else
> +		/* The sink expects odd pixels through the first port */
> +		ret = DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS;
> +
> +done:
> +	of_node_put(ep1);
> +	of_node_put(ep2);
> +	of_node_put(parent_p1);
> +	of_node_put(parent_p2);
> +	of_node_put(remote_p1);
> +	of_node_put(remote_p2);
> +	return ret;

This is heavy, I would add blank lines to make the code easier to read.

> +}
> +EXPORT_SYMBOL_GPL(drm_of_lvds_get_dual_link_configuration);
> diff --git a/include/drm/drm_bus_timings.h b/include/drm/drm_bus_timings.h
> new file mode 100644
> index 0000000..db8a385
> --- /dev/null
> +++ b/include/drm/drm_bus_timings.h
> @@ -0,0 +1,21 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __DRM_BUS_TIMINGS__
> +#define __DRM_BUS_TIMINGS__
> +
> +struct device_node;
> +
> +#define DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS	0
> +#define DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS	1

These should be documented with kerneldoc. How about also turning them
into an enum ?

> +
> +#ifdef CONFIG_OF
> +int drm_of_lvds_get_dual_link_configuration(const struct device_node *p1,
> +					    const struct device_node *p2);
> +#else
> +int drm_of_lvds_get_dual_link_configuration(const struct device_node *p1,
> +					    const struct device_node *p2)
> +{
> +	return -EINVAL;
> +}
> +#endif
> +
> +#endif /* __DRM_BUS_TIMINGS__ */

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 3/8] drm: Add bus timings helper
  2019-11-07 19:26   ` Laurent Pinchart
@ 2019-11-07 19:30     ` Daniel Vetter
  2019-12-06 15:25       ` Fabrizio Castro
  2019-12-06 15:24     ` Fabrizio Castro
  1 sibling, 1 reply; 32+ messages in thread
From: Daniel Vetter @ 2019-11-07 19:30 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Fabrizio Castro, Maarten Lankhorst, Maxime Ripard, Sean Paul,
	David Airlie, Daniel Vetter, linux-kernel, dri-devel,
	Simon Horman, Geert Uytterhoeven, Chris Paterson, Biju Das,
	linux-renesas-soc, Kieran Bingham, Jacopo Mondi, sam

On Thu, Nov 07, 2019 at 09:26:21PM +0200, Laurent Pinchart wrote:
> Hi Fabrizio,
> 
> Thank you for the patch.
> 
> On Wed, Aug 28, 2019 at 07:36:37PM +0100, Fabrizio Castro wrote:
> > Helper to provide bus timing information.
> 
> You may want to expand this a bit. And actually fix it too, as the
> helper you introduce isn't related to timings (same for the subject
> line).

Also the kerneldoc needs to be pulled into the templates under
Documentation/gpu. And since it's just one function, why not put this into
drm_of.c? Gets rid of a pile of overhead.

> 
> > Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> > 
> > ---
> > v2->v3:
> > * new patch
> > ---
> >  drivers/gpu/drm/Makefile          |  3 +-
> >  drivers/gpu/drm/drm_bus_timings.c | 97 +++++++++++++++++++++++++++++++++++++++
> >  include/drm/drm_bus_timings.h     | 21 +++++++++
> >  3 files changed, 120 insertions(+), 1 deletion(-)
> >  create mode 100644 drivers/gpu/drm/drm_bus_timings.c
> >  create mode 100644 include/drm/drm_bus_timings.h
> > 
> > diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> > index 9f0d2ee..a270063 100644
> > --- a/drivers/gpu/drm/Makefile
> > +++ b/drivers/gpu/drm/Makefile
> > @@ -17,7 +17,8 @@ drm-y       :=	drm_auth.o drm_cache.o \
> >  		drm_plane.o drm_color_mgmt.o drm_print.o \
> >  		drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
> >  		drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \
> > -		drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o
> > +		drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o \
> > +		drm_bus_timings.o
> >  
> >  drm-$(CONFIG_DRM_LEGACY) += drm_legacy_misc.o drm_bufs.o drm_context.o drm_dma.o drm_scatter.o drm_lock.o
> >  drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
> > diff --git a/drivers/gpu/drm/drm_bus_timings.c b/drivers/gpu/drm/drm_bus_timings.c
> > new file mode 100644
> > index 0000000..e2ecd22
> > --- /dev/null
> > +++ b/drivers/gpu/drm/drm_bus_timings.c
> > @@ -0,0 +1,97 @@
> > +// SPDX-License-Identifier: GPL-2.0

DRM core is supposed to be MIT.
-Daniel

> > +#include <drm/drm_bus_timings.h>
> > +#include <linux/errno.h>
> > +#include <linux/of_graph.h>
> > +#include <linux/of.h>
> > +#include <linux/types.h>
> > +
> > +#define DRM_OF_LVDS_ODD		1
> > +#define DRM_OF_LVDS_EVEN	2
> > +
> > +static int drm_of_lvds_get_port_pixels_type(struct device_node *port_node)
> > +{
> > +	bool even_pixels, odd_pixels;
> > +
> > +	even_pixels = of_property_read_bool(port_node, "dual-lvds-even-pixels");
> > +	odd_pixels = of_property_read_bool(port_node, "dual-lvds-odd-pixels");
> > +	return  even_pixels * DRM_OF_LVDS_EVEN + odd_pixels * DRM_OF_LVDS_ODD;
> 
> s/  / /
> 
> But I would make these bitflags.
> 
> enum drm_of_lvds_pixels {
> 	DRM_OF_LVDS_EVEN = BIT(0),
> 	DRM_OF_LVDS_ODD = BIT(1),
> };
> 
> static int drm_of_lvds_get_port_pixels_type(struct device_node *port)
> {
> 	bool even_pixels = of_property_read_bool(port, "dual-lvds-even-pixels");
> 	bool odd_pixels = of_property_read_bool(port, "dual-lvds-odd-pixels");
> 
> 	return (even_pixels ? DRM_OF_LVDS_EVEN : 0) |
> 	       (odd_pixels ? DRM_OF_LVDS_ODD : 0);
> }
> 
> > +}
> > +
> > +/**
> > + * drm_of_lvds_get_dual_link_configuration - get the dual-LVDS configuration
> 
> Should we name this drm_of_lvds_get_dual_link_pixel_order to better
> reflect its purpose ?
> 
> > + * @p1: device tree node corresponding to the first port of the source
> > + * @p2: device tree node corresponding to the second port of the source
> 
> Maybe port1 and port2 to make this more explicit ?
> 
> > + *
> > + * An LVDS dual-link bus is made of two connections, even pixels transit on one
> > + * connection, and odd pixels transit on the other connection.
> 
> To match the DT bindings documentation, I would recommand
> 
> "An LVDS dual-link connection is made of two links, with even pixels
> transitting on one link, and odd pixels on the other link."
> 
> > + * This function walks the DT (from the source ports to the sink ports) looking
> > + * for a dual-LVDS bus. A dual-LVDS bus is identfied by markers found on the DT
> > + * ports of the sink device(s). If such a bus is found, this function returns
> > + * its configuration (either p1 connected to the even pixels port and p2
> > + * connected to the odd pixels port, or p1 connected to the odd pixels port and
> > + * p2 connected to the even pixels port).
> 
> "walking the DT" sounds like the function goes through the whole graph.
> How about the following ?
> 
> /**
>  * drm_of_lvds_get_dual_link_pixel_order - Get LVDS dual-link pixel order
>  * @port1: First DT port node of the Dual-link LVDS source
>  * @port2: Second DT port node of the Dual-link LVDS source
>  *
>  * An LVDS dual-link connection is made of two links, with even pixels
>  * transitting on one link, and odd pixels on the other link. This function
>  * returns, for two ports of an LVDS dual-link source, which port shall transmit
>  * the even and off pixels, based on the requirements of the connected sink.
>  *
>  * The pixel order is determined from the dual-lvds-even-pixels and
>  * dual-lvds-odd-pixels properties in the sink's DT port nodes. If those
>  * properties are not present, or if their usage is not valid, this function
>  * returns -EINVAL.
>  *
>  * @port1 and @port2 are typically DT sibling nodes, but may have different
>  * parents when, for instance, two separate LVDS encoders carry the even and odd
>  * pixels.
>  *
>  * Return:
>  * * DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS - @port1 carries even pixels and @port2
>  *   carries odd pixels
>  * * DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS - @port1 carries odd pixels and @port1
>  *   carries even pixels
>  * * -EINVAL - @port1 and @port2 are not connected to a dual-link LVDS sink, or
>  *   the sink configuration is invalid
>  */
> 
> We could also add -EPIPE as a return code for the case where port1 or
> port2 are not connected.
> 
> > + *
> > + * Return: A code describing the bus configuration when a valid dual-LVDS bus is
> > + * found, or an error code when no valid dual-LVDS bus is found
> > + *
> > + * Possible codes for the bus configuration are:
> > + *
> > + * - DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS: when p1 is connected to the even pixels
> > + *   port and p2 is connected to the odd pixels port
> > + * - DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS: when p1 is connected to the odd pixels
> > + *   port and p2 is connected to the even pixels port
> > + *
> > + */
> > +int drm_of_lvds_get_dual_link_configuration(const struct device_node *p1,
> > +					    const struct device_node *p2)
> > +{
> > +	struct device_node *remote_p1 = NULL, *remote_p2 = NULL;
> > +	struct device_node *parent_p1 = NULL, *parent_p2 = NULL;
> 
> There's no need to initialize those two variables.
> 
> > +	struct device_node *ep1 = NULL, *ep2 = NULL;
> > +	u32 reg_p1, reg_p2;
> > +	int ret = -EINVAL, remote_p1_pt, remote_p2_pt;
> 
> Please split this last line, as it otherwise hides the initialization of
> ret in the middle.
> 
> > +
> > +	if (!p1 || !p2)
> > +		return ret;
> 
> You can return -EINVAL directly.
> 
> 
> > +	if (of_property_read_u32(p1, "reg", &reg_p1) ||
> > +	    of_property_read_u32(p2, "reg", &reg_p2))
> > +		return ret;
> 
> Same here.
> 
> > +	parent_p1 = of_get_parent(p1);
> > +	parent_p2 = of_get_parent(p2);
> > +	if (!parent_p1 || !parent_p2)
> > +		goto done;
> > +	ep1 = of_graph_get_endpoint_by_regs(parent_p1, reg_p1, 0);
> > +	ep2 = of_graph_get_endpoint_by_regs(parent_p2, reg_p2, 0);
> > +	if (!ep1 || !ep2)
> > +		goto done;
> 
> If you only support the first endpoint, this should be mentioned in the
> documentation. Alternatively you could pass the endpoint nodes instead
> of the port nodes, or you could pass the endpoint number.
> 
> It's also a bit inefficient to use of_graph_get_endpoint_by_regs() when
> you already have the port nodes. How about adding the following helper
> function ?
> 
> struct device_node *of_graph_get_port_endpoint(struct device_node *port, int reg)
> {
> 	struct device_node *endpoint = NULL;
> 
> 	for_each_child_of_node(port, endpoint) {
> 		u32 id;
> 
> 		if (!of_node_name_eq(endpoint, "endpoint") ||
> 			continue;
> 
> 		if (reg == -1)
> 			return endpoint;
> 
> 		if (of_property_read_u32(node, "reg", &id) < 0)
> 			continue;
> 
> 		if (reg == id)
> 			return endpoint;
> 	}
> 
> 	return NULL;
> }
> 
> If you're concerned that adding a core helper would delay this patch
> series, you could add it as a local helper, and move it to of_graph.h in
> a second step.
> 
> > +	remote_p1 = of_graph_get_remote_port(ep1);
> > +	remote_p2 = of_graph_get_remote_port(ep2);
> > +	if (!remote_p1 || !remote_p2)
> > +		goto done;
> > +	remote_p1_pt = drm_of_lvds_get_port_pixels_type(remote_p1);
> > +	remote_p2_pt = drm_of_lvds_get_port_pixels_type(remote_p2);
> > +	/*
> > +	 * A valid dual-lVDS bus is found when one remote port is marked with
> > +	 * "dual-lvds-even-pixels", and the other remote port is marked with
> > +	 * "dual-lvds-odd-pixels", bail out if the markers are not right.
> > +	 */
> > +	if (!remote_p1_pt || !remote_p2_pt ||
> > +	    remote_p1_pt + remote_p2_pt != DRM_OF_LVDS_EVEN + DRM_OF_LVDS_ODD)
> > +		goto done;
> > +	if (remote_p1_pt == DRM_OF_LVDS_EVEN)
> > +		/* The sink expects even pixels through the first port */
> > +		ret = DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS;
> > +	else
> > +		/* The sink expects odd pixels through the first port */
> > +		ret = DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS;
> > +
> > +done:
> > +	of_node_put(ep1);
> > +	of_node_put(ep2);
> > +	of_node_put(parent_p1);
> > +	of_node_put(parent_p2);
> > +	of_node_put(remote_p1);
> > +	of_node_put(remote_p2);
> > +	return ret;
> 
> This is heavy, I would add blank lines to make the code easier to read.
> 
> > +}
> > +EXPORT_SYMBOL_GPL(drm_of_lvds_get_dual_link_configuration);
> > diff --git a/include/drm/drm_bus_timings.h b/include/drm/drm_bus_timings.h
> > new file mode 100644
> > index 0000000..db8a385
> > --- /dev/null
> > +++ b/include/drm/drm_bus_timings.h
> > @@ -0,0 +1,21 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +#ifndef __DRM_BUS_TIMINGS__
> > +#define __DRM_BUS_TIMINGS__
> > +
> > +struct device_node;
> > +
> > +#define DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS	0
> > +#define DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS	1
> 
> These should be documented with kerneldoc. How about also turning them
> into an enum ?
> 
> > +
> > +#ifdef CONFIG_OF
> > +int drm_of_lvds_get_dual_link_configuration(const struct device_node *p1,
> > +					    const struct device_node *p2);
> > +#else
> > +int drm_of_lvds_get_dual_link_configuration(const struct device_node *p1,
> > +					    const struct device_node *p2)
> > +{
> > +	return -EINVAL;
> > +}
> > +#endif
> > +
> > +#endif /* __DRM_BUS_TIMINGS__ */
> 
> -- 
> Regards,
> 
> Laurent Pinchart

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 4/8] drm: rcar-du: lvds: Add dual-LVDS panels support
  2019-08-28 18:36 ` [PATCH v3 4/8] drm: rcar-du: lvds: Add dual-LVDS panels support Fabrizio Castro
@ 2019-11-07 19:50   ` Laurent Pinchart
  2019-12-06 15:35     ` Fabrizio Castro
  0 siblings, 1 reply; 32+ messages in thread
From: Laurent Pinchart @ 2019-11-07 19:50 UTC (permalink / raw)
  To: Fabrizio Castro
  Cc: David Airlie, Daniel Vetter, Kieran Bingham, dri-devel,
	linux-renesas-soc, linux-kernel, Simon Horman,
	Geert Uytterhoeven, Chris Paterson, Biju Das, Jacopo Mondi, sam

Hi Fabrizio,

Thank you for the patch.

On Wed, Aug 28, 2019 at 07:36:38PM +0100, Fabrizio Castro wrote:
> The driver doesn't support dual-link LVDS displays, and the way
> it identifies bridges won't allow for dual-LVDS displays to be
> connected. Also, it's not possible to swap even and odd pixels
> around in case the wiring isn't taking advantage of the default
> hardware configuration. Further more, the "mode" of the companion
> encoder should be same as the mode of the primary encoder.
> 
> Rework the driver to improve all of the above, so that it can
> support dual-LVDS displays.

That's lots of changes in one patch, could it be split to ease review ?
Also, should the commit message be reworded to explain what the patch
does, instead of enumerating issues ? When there's a single issue being
addressed in a patch it's usually fine, but there the change is larger,
without an explanation of how you intend to fix the issues I can't tell
if the code really matches your intent.

> Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> 
> ---
> v2->v3:
> * reworked to take advantange of the new dt-bindings
> * squashed in the patche for fixing the companion's mode
> 
> Laurent,
> 
> unfortunately the best way to get the companion encoder to use
> the same mode as the primary encoder is setting the mode directly
> without calling into rcar_lvds_mode_set for the companion encoder,
> as the below test fails for the companion encoder in
> rcar_lvds_get_lvds_mode:
> if (!info->num_bus_formats || !info->bus_formats)

Would "[PATCH] drm: rcar-du: lvds: Get mode from state" help here ?
Maybe you could review that patch, I could then include it in my -next
branch, your work would be simplified, and everybody would be happy ?
:-)

> Anyhow, setting the mode for the companion encoder doesn't seem
> to be mandary according to the experiments I have been running,
> but the HW User's Manual doesn't really say much about this,
> therefore I think the safest option is still to set the mode for
> the companion encoder.

I agree it should be done.

> ---
>  drivers/gpu/drm/rcar-du/rcar_lvds.c | 110 +++++++++++++++++++++---------------
>  1 file changed, 65 insertions(+), 45 deletions(-)
> 
> diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> index 3fe0b86..dfec5e7 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> @@ -20,6 +20,8 @@
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
>  #include <drm/drm_bridge.h>
> +#include <drm/drm_bus_timings.h>
> +#include <drm/drm_of.h>
>  #include <drm/drm_panel.h>
>  #include <drm/drm_probe_helper.h>
>  
> @@ -69,6 +71,7 @@ struct rcar_lvds {
>  
>  	struct drm_bridge *companion;
>  	bool dual_link;
> +	bool stripe_swap_data;
>  };
>  
>  #define bridge_to_rcar_lvds(b) \
> @@ -439,12 +442,20 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
>  	rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
>  
>  	if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) {
> -		/*
> -		 * Configure vertical stripe based on the mode of operation of
> -		 * the connected device.
> -		 */
> -		rcar_lvds_write(lvds, LVDSTRIPE,
> -				lvds->dual_link ? LVDSTRIPE_ST_ON : 0);
> +		u32 lvdstripe = 0;
> +
> +		if (lvds->dual_link)
> +			/*
> +			 * Configure vertical stripe based on the mode of
> +			 * operation of the connected device.
> +			 *
> +			 * ST_SWAP from LVD1STRIPE is reserved, do not set
> +			 * in the companion LVDS
> +			 */
> +			lvdstripe = LVDSTRIPE_ST_ON |
> +				(lvds->companion && lvds->stripe_swap_data ?
> +				 LVDSTRIPE_ST_SWAP : 0);
> +		rcar_lvds_write(lvds, LVDSTRIPE, lvdstripe);
>  	}
>  
>  	/*
> @@ -603,6 +614,11 @@ static void rcar_lvds_mode_set(struct drm_bridge *bridge,
>  	lvds->display_mode = *adjusted_mode;
>  
>  	rcar_lvds_get_lvds_mode(lvds);
> +	if (lvds->companion) {
> +		struct rcar_lvds *companion_lvds = bridge_to_rcar_lvds(
> +							lvds->companion);
> +		companion_lvds->mode = lvds->mode;
> +	}
>  }
>  
>  static int rcar_lvds_attach(struct drm_bridge *bridge)
> @@ -667,9 +683,10 @@ EXPORT_SYMBOL_GPL(rcar_lvds_dual_link);
>  static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds)
>  {
>  	const struct of_device_id *match;
> -	struct device_node *companion;
> +	struct device_node *companion, *p0 = NULL, *p1 = NULL;
>  	struct device *dev = lvds->dev;
> -	int ret = 0;
> +	struct rcar_lvds *companion_lvds;
> +	int ret = 0, dual_link;
>  
>  	/* Locate the companion LVDS encoder for dual-link operation, if any. */
>  	companion = of_parse_phandle(dev->of_node, "renesas,companion", 0);
> @@ -687,16 +704,50 @@ static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds)
>  		goto done;
>  	}
>  
> +	/*
> +	 * We need to work out if the sink is expecting us to function in
> +	 * dual-link mode. We do this by looking at the DT port nodes we are
> +	 * connected to, if they are marked as expecting even pixels and
> +	 * odd pixels than we need to enable vertical stripe output
> +	 */
> +	p0 = of_graph_get_port_by_id(dev->of_node, 1);
> +	p1 = of_graph_get_port_by_id(companion, 1);
> +	dual_link = drm_of_lvds_get_dual_link_configuration(p0, p1);

You can call of_node_put(p0) and of_node_put(p1) here instead of adding
them at the end of the function.

> +	if (dual_link >= DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS) {
> +		dev_dbg(dev, "Dual-link configuration detected\n");
> +		lvds->dual_link = true;
> +	} else {
> +		/* dual-link mode is not required */
> +		dev_dbg(dev, "Single-link configuration detected\n");
> +		goto done;
> +	}

Missing blank line here.

> +	/*
> +	 * We may need to swap even and odd pixels around in case the wiring
> +	 * doesn't match the default configuration.
> +	 * By default we generate even pixels from this encoder and odd pixels
> +	 * from the companion encoder, but if p0 is connected to the port
> +	 * expecting ood pixels, and p1 is connected to the port expecting even
> +	 * pixels, then we need to swap even and odd pixels around
> +	 */
> +	if (dual_link == DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS) {
> +		dev_dbg(dev, "Data swapping required\n");
> +		lvds->stripe_swap_data = true;
> +	}
> +
>  	lvds->companion = of_drm_find_bridge(companion);
>  	if (!lvds->companion) {
>  		ret = -EPROBE_DEFER;
>  		goto done;
>  	}
> +	companion_lvds = bridge_to_rcar_lvds(lvds->companion);
> +	companion_lvds->dual_link = lvds->dual_link;

I don't like poking directly in the companion like this :-( Can't we let
the companion detect dual link mode itself ?

>  
>  	dev_dbg(dev, "Found companion encoder %pOF\n", companion);
>  
>  done:
>  	of_node_put(companion);
> +	of_node_put(p0);
> +	of_node_put(p1);
>  
>  	return ret;
>  }
> @@ -704,10 +755,7 @@ static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds)
>  static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
>  {
>  	struct device_node *local_output = NULL;
> -	struct device_node *remote_input = NULL;
>  	struct device_node *remote = NULL;
> -	struct device_node *node;
> -	bool is_bridge = false;
>  	int ret = 0;
>  
>  	local_output = of_graph_get_endpoint_by_regs(lvds->dev->of_node, 1, 0);
> @@ -735,45 +783,17 @@ static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
>  		goto done;
>  	}
>  

I think you can also drop all the code above.

> -	remote_input = of_graph_get_remote_endpoint(local_output);
> -
> -	for_each_endpoint_of_node(remote, node) {
> -		if (node != remote_input) {
> -			/*
> -			 * We've found one endpoint other than the input, this
> -			 * must be a bridge.
> -			 */
> -			is_bridge = true;
> -			of_node_put(node);
> -			break;
> -		}
> -	}
> -
> -	if (is_bridge) {
> -		lvds->next_bridge = of_drm_find_bridge(remote);
> -		if (!lvds->next_bridge) {
> -			ret = -EPROBE_DEFER;
> -			goto done;
> -		}
> -
> -		if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK)
> -			lvds->dual_link = lvds->next_bridge->timings
> -					? lvds->next_bridge->timings->dual_link
> -					: false;

Aren't you breaking backward compatibility with this change ? Unless I'm
mistaken you're now requiring the new DT properties, and the existing DT
that include a thc63lvd1024 won't have them.

> -	} else {
> -		lvds->panel = of_drm_find_panel(remote);
> -		if (IS_ERR(lvds->panel)) {
> -			ret = PTR_ERR(lvds->panel);
> -			goto done;
> -		}
> +	ret = drm_of_find_panel_or_bridge(lvds->dev->of_node, 1, 0,
> +					  &lvds->panel, &lvds->next_bridge);
> +	if (ret) {
> +		ret = -EPROBE_DEFER;

Shouldn't you return ret instead of overriding it ?

> +		goto done;
>  	}
> -
> -	if (lvds->dual_link)
> +	if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK)
>  		ret = rcar_lvds_parse_dt_companion(lvds);
>  
>  done:
>  	of_node_put(local_output);
> -	of_node_put(remote_input);
>  	of_node_put(remote);
>  
>  	/*

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 5/8] drm: bridge: thc63: Do not report input bus mode through bridge timings
  2019-08-28 18:36 ` [PATCH v3 5/8] drm: bridge: thc63: Do not report input bus mode through bridge timings Fabrizio Castro
@ 2019-11-07 19:52   ` Laurent Pinchart
  2019-12-06 15:38     ` Fabrizio Castro
  0 siblings, 1 reply; 32+ messages in thread
From: Laurent Pinchart @ 2019-11-07 19:52 UTC (permalink / raw)
  To: Fabrizio Castro
  Cc: Andrzej Hajda, David Airlie, Daniel Vetter, Maarten Lankhorst,
	Maxime Ripard, Sean Paul, dri-devel, linux-kernel, Simon Horman,
	Geert Uytterhoeven, Chris Paterson, Biju Das, linux-renesas-soc,
	Kieran Bingham, Jacopo Mondi, sam

Hi Fabrizio,

Thank you for the patch.

On Wed, Aug 28, 2019 at 07:36:39PM +0100, Fabrizio Castro wrote:
> No need to report the input bus mode through bridge timings
> anymore, that's now done through the DT, as specified by the
> dt-bindings.

Doesn't this break backward compatibility with older DT, as mentioned in
the review of 4/8 ?

> Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> 
> ---
> v2->v3:
> * new patch
> ---
>  drivers/gpu/drm/bridge/thc63lvd1024.c | 9 ++++-----
>  include/drm/drm_bridge.h              | 8 --------
>  2 files changed, 4 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c b/drivers/gpu/drm/bridge/thc63lvd1024.c
> index 3d74129b..730f682 100644
> --- a/drivers/gpu/drm/bridge/thc63lvd1024.c
> +++ b/drivers/gpu/drm/bridge/thc63lvd1024.c
> @@ -34,7 +34,7 @@ struct thc63_dev {
>  	struct drm_bridge bridge;
>  	struct drm_bridge *next;
>  
> -	struct drm_bridge_timings timings;
> +	bool dual_link;
>  };
>  
>  static inline struct thc63_dev *to_thc63(struct drm_bridge *bridge)
> @@ -62,7 +62,7 @@ static enum drm_mode_status thc63_mode_valid(struct drm_bridge *bridge,
>  	 * isn't supported by the driver yet, simply derive the limits from the
>  	 * input mode.
>  	 */
> -	if (thc63->timings.dual_link) {
> +	if (thc63->dual_link) {
>  		min_freq = 40000;
>  		max_freq = 150000;
>  	} else {
> @@ -157,13 +157,13 @@ static int thc63_parse_dt(struct thc63_dev *thc63)
>  
>  		if (remote) {
>  			if (of_device_is_available(remote))
> -				thc63->timings.dual_link = true;
> +				thc63->dual_link = true;
>  			of_node_put(remote);
>  		}
>  	}
>  
>  	dev_dbg(thc63->dev, "operating in %s-link mode\n",
> -		thc63->timings.dual_link ? "dual" : "single");
> +		thc63->dual_link ? "dual" : "single");
>  
>  	return 0;
>  }
> @@ -221,7 +221,6 @@ static int thc63_probe(struct platform_device *pdev)
>  	thc63->bridge.driver_private = thc63;
>  	thc63->bridge.of_node = pdev->dev.of_node;
>  	thc63->bridge.funcs = &thc63_bridge_func;
> -	thc63->bridge.timings = &thc63->timings;
>  
>  	drm_bridge_add(&thc63->bridge);
>  
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 7616f65..3228018 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -362,14 +362,6 @@ struct drm_bridge_timings {
>  	 * input signal after the clock edge.
>  	 */
>  	u32 hold_time_ps;
> -	/**
> -	 * @dual_link:
> -	 *
> -	 * True if the bus operates in dual-link mode. The exact meaning is
> -	 * dependent on the bus type. For LVDS buses, this indicates that even-
> -	 * and odd-numbered pixels are received on separate links.
> -	 */
> -	bool dual_link;
>  };
>  
>  /**

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 6/8] arm64: dts: renesas: Add EK874 board with idk-2121wr display support
  2019-08-28 18:36 ` [PATCH v3 6/8] arm64: dts: renesas: Add EK874 board with idk-2121wr display support Fabrizio Castro
@ 2019-11-07 19:55   ` Laurent Pinchart
  0 siblings, 0 replies; 32+ messages in thread
From: Laurent Pinchart @ 2019-11-07 19:55 UTC (permalink / raw)
  To: Fabrizio Castro
  Cc: Rob Herring, Mark Rutland, Simon Horman, Geert Uytterhoeven,
	Magnus Damm, linux-renesas-soc, devicetree, linux-kernel,
	Chris Paterson, Biju Das, Kieran Bingham, Jacopo Mondi, sam,
	xu_shunji, ebiharaml

Hi Fabrizio,

Thank you for the patch.

On Wed, Aug 28, 2019 at 07:36:40PM +0100, Fabrizio Castro wrote:
> The EK874 is advertised as compatible with panel IDK-2121WR from
> Advantech, however the panel isn't sold alongside the board.
> A new dts, adding everything that's required to get the panel to
> to work with the EK874, is the most convenient way to support the
> EK874 when it's connected to the IDK-2121WR.
> 
> Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> 
> ---
> v1->v2:
> * Added comment for lvds-connector-en-gpio
> * Renamed &lvds0_panel_in to panel_in0
> * Renamed &lvds1_panel_in to panel_in1
> 
> v2->v3:
> * removed renesas,swap-data property
> * added dual-lvds-odd-pixels and dual-lvds-even-pixels properties
> 
> Geert,
> 
> no need to review this patch unless they like the idea behind this
> series.

I like the idea :-) We still have a few issues to solve, but it should
make it in.

The patch looks sane to me, but I haven't checked if it matches the
hardware, so

Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

(even if this really calls for DT overlays)

> ---
>  arch/arm64/boot/dts/renesas/Makefile               |   3 +-
>  .../boot/dts/renesas/r8a774c0-ek874-idk-2121wr.dts | 116 +++++++++++++++++++++
>  2 files changed, 118 insertions(+), 1 deletion(-)
>  create mode 100644 arch/arm64/boot/dts/renesas/r8a774c0-ek874-idk-2121wr.dts
> 
> diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
> index 42b74c2..ce48478 100644
> --- a/arch/arm64/boot/dts/renesas/Makefile
> +++ b/arch/arm64/boot/dts/renesas/Makefile
> @@ -1,7 +1,8 @@
>  # SPDX-License-Identifier: GPL-2.0
>  dtb-$(CONFIG_ARCH_R8A774A1) += r8a774a1-hihope-rzg2m.dtb
>  dtb-$(CONFIG_ARCH_R8A774A1) += r8a774a1-hihope-rzg2m-ex.dtb
> -dtb-$(CONFIG_ARCH_R8A774C0) += r8a774c0-cat874.dtb r8a774c0-ek874.dtb
> +dtb-$(CONFIG_ARCH_R8A774C0) += r8a774c0-cat874.dtb r8a774c0-ek874.dtb \
> +			       r8a774c0-ek874-idk-2121wr.dtb
>  dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-x.dtb r8a7795-h3ulcb.dtb
>  dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-kf.dtb
>  dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-xs.dtb
> diff --git a/arch/arm64/boot/dts/renesas/r8a774c0-ek874-idk-2121wr.dts b/arch/arm64/boot/dts/renesas/r8a774c0-ek874-idk-2121wr.dts
> new file mode 100644
> index 0000000..a7b27d0
> --- /dev/null
> +++ b/arch/arm64/boot/dts/renesas/r8a774c0-ek874-idk-2121wr.dts
> @@ -0,0 +1,116 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Device Tree Source for the Silicon Linux RZ/G2E evaluation kit (EK874),
> + * connected to an Advantech IDK-2121WR 21.5" LVDS panel
> + *
> + * Copyright (C) 2019 Renesas Electronics Corp.
> + */
> +
> +#include "r8a774c0-ek874.dts"
> +
> +/ {
> +	backlight: backlight {
> +		compatible = "pwm-backlight";
> +		pwms = <&pwm5 0 50000>;
> +
> +		brightness-levels = <0 4 8 16 32 64 128 255>;
> +		default-brightness-level = <6>;
> +
> +		power-supply = <&reg_12p0v>;
> +		enable-gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>;
> +	};
> +
> +	panel-lvds {
> +		compatible = "advantech,idk-2121wr", "panel-lvds";
> +
> +		width-mm = <476>;
> +		height-mm = <268>;
> +
> +		data-mapping = "vesa-24";
> +
> +		panel-timing {
> +			clock-frequency = <148500000>;
> +			hactive = <1920>;
> +			vactive = <1080>;
> +			hsync-len = <44>;
> +			hfront-porch = <88>;
> +			hback-porch = <148>;
> +			vfront-porch = <4>;
> +			vback-porch = <36>;
> +			vsync-len = <5>;
> +		};
> +
> +		ports {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			port@0 {
> +				reg = <0>;
> +				dual-lvds-odd-pixels;
> +				panel_in0: endpoint {
> +					remote-endpoint = <&lvds0_out>;
> +				};
> +			};
> +
> +			port@1 {
> +				reg = <1>;
> +				dual-lvds-even-pixels;
> +				panel_in1: endpoint {
> +					remote-endpoint = <&lvds1_out>;
> +				};
> +			};
> +		};
> +	};
> +};
> +
> +&gpio0 {
> +	/*
> +	 * When GP0_17 is low LVDS[01] are connected to the LVDS connector
> +	 * When GP0_17 is high LVDS[01] are connected to the LT8918L
> +	 */
> +	lvds-connector-en-gpio{
> +		gpio-hog;
> +		gpios = <17 GPIO_ACTIVE_HIGH>;
> +		output-low;
> +		line-name = "lvds-connector-en-gpio";
> +	};
> +};
> +
> +&lvds0 {
> +	ports {
> +		port@1 {
> +			lvds0_out: endpoint {
> +				remote-endpoint = <&panel_in0>;
> +			};
> +		};
> +	};
> +};
> +
> +&lvds1 {
> +	status = "okay";
> +
> +	clocks = <&cpg CPG_MOD 727>, <&x13_clk>, <&extal_clk>;
> +	clock-names = "fck", "dclkin.0", "extal";
> +
> +	ports {
> +		port@1 {
> +			lvds1_out: endpoint {
> +				remote-endpoint = <&panel_in1>;
> +			};
> +		};
> +	};
> +};
> +
> +&pfc {
> +	pwm5_pins: pwm5 {
> +		groups = "pwm5_a";
> +		function = "pwm5";
> +	};
> +};
> +
> +&pwm5 {
> +	pinctrl-0 = <&pwm5_pins>;
> +	pinctrl-names = "default";
> +
> +	status = "okay";
> +};

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 7/8] [HACK] arm64: dts: renesas: draak: Enable LVDS
  2019-08-28 18:36 ` [PATCH v3 7/8] [HACK] arm64: dts: renesas: draak: Enable LVDS Fabrizio Castro
@ 2019-11-07 19:57   ` Laurent Pinchart
  2019-12-06 15:40     ` Fabrizio Castro
  0 siblings, 1 reply; 32+ messages in thread
From: Laurent Pinchart @ 2019-11-07 19:57 UTC (permalink / raw)
  To: Fabrizio Castro
  Cc: Rob Herring, Mark Rutland, Simon Horman, Geert Uytterhoeven,
	Magnus Damm, linux-renesas-soc, devicetree, linux-kernel,
	Chris Paterson, Biju Das, Kieran Bingham, Jacopo Mondi, sam

Hi Fabrizio,

Thank you for the patch.

The subject is wrong, it should be

[HACK] arm64: dts: renesas: ebisu: Enable LVDS dual-link operation

On Wed, Aug 28, 2019 at 07:36:41PM +0100, Fabrizio Castro wrote:
> Enable and connect the second LVDS encoder to the second LVDS input of
> the THC63LVD1024 for dual-link LVDS operation. This requires changing
> the default settings of SW45 and SW47 to OFF and ON respectively.
> 
> This patch is based on Laurent's dual-LVDS work:
> https://patchwork.kernel.org/patch/10965045/
> 
> Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> ---
> v2->v3:
> * new patch
> 
> Geert,
> 
> no need to review this patch unless they like the idea behind this
> series.
> 
> Thanks,
> Fab
> 
> ---
>  arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts | 21 +++++++++++++++++++--
>  1 file changed, 19 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
> index b38f9d4..38b9c5a 100644
> --- a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
> +++ b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
> @@ -87,11 +87,20 @@
>  
>  			port@0 {
>  				reg = <0>;
> -				thc63lvd1024_in: endpoint {
> +				dual-lvds-even-pixels;
> +				thc63lvd1024_in0: endpoint {
>  					remote-endpoint = <&lvds0_out>;
>  				};
>  			};
>  
> +			port@1 {
> +				reg = <1>;
> +				dual-lvds-odd-pixels;
> +				thc63lvd1024_in1: endpoint {
> +					remote-endpoint = <&lvds1_out>;
> +				};
> +			};
> +
>  			port@2 {
>  				reg = <2>;
>  				thc63lvd1024_out: endpoint {
> @@ -489,7 +498,7 @@
>  	ports {
>  		port@1 {
>  			lvds0_out: endpoint {
> -				remote-endpoint = <&thc63lvd1024_in>;
> +				remote-endpoint = <&thc63lvd1024_in0>;
>  			};
>  		};
>  	};
> @@ -507,6 +516,14 @@
>  		 <&x13_clk>,
>  		 <&extal_clk>;
>  	clock-names = "fck", "dclkin.0", "extal";
> +
> +	ports {
> +		port@1 {
> +			lvds1_out: endpoint {
> +				remote-endpoint = <&thc63lvd1024_in1>;
> +			};
> +		};
> +	};
>  };
>  
>  &ohci0 {
> -- 
> 2.7.4
> 

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH v3 1/8] dt-bindings: display: Add bindings for LVDS bus-timings
  2019-08-29 14:03   ` Rob Herring
  2019-08-29 14:38     ` Fabrizio Castro
@ 2019-12-06 15:10     ` Fabrizio Castro
  1 sibling, 0 replies; 32+ messages in thread
From: Fabrizio Castro @ 2019-12-06 15:10 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Airlie, Daniel Vetter, Mark Rutland, dri-devel, devicetree,
	linux-kernel, Simon Horman, Geert Uytterhoeven, Chris Paterson,
	Biju Das, open list:MEDIA DRIVERS FOR RENESAS - FCP,
	Laurent Pinchart, Kieran Bingham, Jacopo Mondi, Sam Ravnborg

Hi Rob,

> From: Rob Herring <robh+dt@kernel.org>
> Sent: 29 August 2019 15:03
> Subject: Re: [PATCH v3 1/8] dt-bindings: display: Add bindings for LVDS bus-timings
> 
> On Wed, Aug 28, 2019 at 1:36 PM Fabrizio Castro
> <fabrizio.castro@bp.renesas.com> wrote:
> >
> > Dual-LVDS connections need markers in the DT, this patch adds
> > some common documentation to be referenced by both panels and
> > bridges.
> >
> > Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> >
> > ---
> > v2->v3:
> > * new patch
> > ---
> >  .../bindings/display/bus-timings/lvds.yaml         | 38 ++++++++++++++++++++++
> >  1 file changed, 38 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/display/bus-timings/lvds.yaml b/Documentation/devicetree/bindings/display/bus-
> timings/lvds.yaml
> > new file mode 100644
> > index 0000000..f35b55a
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
> > @@ -0,0 +1,38 @@
> > +# SPDX-License-Identifier: GPL-2.0
> 
> (GPL-2.0-only OR BSD-2-Clause) is preferred for new bindings.
> 
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/display/bus-timings/lvds.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Common Properties for bus timings of LVDS interfaces
> > +
> > +maintainers:
> > +  - Thierry Reding <thierry.reding@gmail.com>
> > +  - Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> > +
> > +description: |
> > +  This document defines device tree properties common to LVDS and dual-LVDS
> > +  interfaces, where a dual-LVDS interface is a dual-link connection with even
> > +  pixels traveling on one connection, and with odd pixels traveling on the other
> > +  connection.
> > +  This document doesn't constitue a device tree binding specification by itself
> 
> typo: constitute
> 
> > +  but is meant to be referenced by device tree bindings.
> > +  When referenced from panel or bridge device tree bindings, the properties
> > +  defined in this document are defined as follows. The panel and bridge device
> > +  tree bindings are responsible for defining whether each property is required
> > +  or optional.
> > +
> > +properties:
> > +  dual-lvds-even-pixels:
> > +    type: boolean
> > +    description:
> > +      This property is specific to an input port of a sink device. When
> 
> The schema should define what nodes these go in. The description seems
> to indicate in 'port' nodes (or endpoint?), but your use in the panel
> binding puts them in the parent.
> 
> > +      specified, it marks the port as recipient of even-pixels.
> > +
> > +  dual-lvds-odd-pixels:
> > +    type: boolean
> > +    description:
> > +      This property is specific to an input port of a sink device. When
> > +      specified, it marks the port as recipient of odd-pixels.
> 
> However, I don't think you even need these. A panel's port numbers are
> fixed can imply even or odd. For example port@0 can be even and port@1
> can be odd. The port numbering is typically panel specific, but we may
> be able to define the numbering generically if we don't already have
> panels with multiple ports.

The ports on the receiving end of the link can be identified by any number,
not necessarily 0 and 1. Since at this point in time we only have 1 use case
for this I'll merge the generic and panel specific dt-schemas together, for
simplicity.
Perhaps we can split them back once we have a second use case?
I'll send a new patch shortly.

Thank you very much for your help and your patience!

Fab

> 
> Also, aren't there dual link DSI panels?
> 
> Rob

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH v3 1/8] dt-bindings: display: Add bindings for LVDS bus-timings
  2019-11-07 18:00       ` Laurent Pinchart
@ 2019-12-06 15:11         ` Fabrizio Castro
  0 siblings, 0 replies; 32+ messages in thread
From: Fabrizio Castro @ 2019-12-06 15:11 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Rob Herring, David Airlie, Daniel Vetter, Mark Rutland,
	dri-devel, devicetree, linux-kernel, Simon Horman,
	Geert Uytterhoeven, Chris Paterson, Biju Das,
	open list:MEDIA DRIVERS FOR RENESAS - FCP, Kieran Bingham,
	Jacopo Mondi, Sam Ravnborg

Hi Laurent,

Thank you for your feedback!

> From: devicetree-owner@vger.kernel.org <devicetree-owner@vger.kernel.org> On Behalf Of Laurent Pinchart
> Sent: 07 November 2019 18:01
> Subject: Re: [PATCH v3 1/8] dt-bindings: display: Add bindings for LVDS bus-timings
> 
> Hello Fabrizio,
> 
> On Thu, Aug 29, 2019 at 02:38:06PM +0000, Fabrizio Castro wrote:
> > On 29 August 2019 15:03 Rob Herring wrote:
> > > On Wed, Aug 28, 2019 at 1:36 PM Fabrizio Castro wrote:
> > >>
> > >> Dual-LVDS connections need markers in the DT, this patch adds
> > >> some common documentation to be referenced by both panels and
> > >> bridges.
> > >>
> > >> Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> > >>
> > >> ---
> > >> v2->v3:
> > >> * new patch
> > >> ---
> > >>  .../bindings/display/bus-timings/lvds.yaml         | 38 ++++++++++++++++++++++
> > >>  1 file changed, 38 insertions(+)
> > >>  create mode 100644 Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
> > >>
> > >> diff --git a/Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
> b/Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
> > >> new file mode 100644
> > >> index 0000000..f35b55a
> > >> --- /dev/null
> > >> +++ b/Documentation/devicetree/bindings/display/bus-timings/lvds.yaml
> > >> @@ -0,0 +1,38 @@
> > >> +# SPDX-License-Identifier: GPL-2.0
> > >
> > > (GPL-2.0-only OR BSD-2-Clause) is preferred for new bindings.
> > >
> > >> +%YAML 1.2
> > >> +---
> > >> +$id: http://devicetree.org/schemas/display/bus-timings/lvds.yaml#
> > >> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > >> +
> > >> +title: Common Properties for bus timings of LVDS interfaces
> > >> +
> > >> +maintainers:
> > >> +  - Thierry Reding <thierry.reding@gmail.com>
> > >> +  - Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> > >> +
> > >> +description: |
> > >> +  This document defines device tree properties common to LVDS and dual-LVDS
> > >> +  interfaces, where a dual-LVDS interface is a dual-link connection with even
> > >> +  pixels traveling on one connection, and with odd pixels traveling on the other
> > >> +  connection.
> 
> As you define a dual-LVDS interface as "a dual-link connection", should
> this be "even pixels traveling on one link, and with odd pixels
> traveling on the other link" ?

Will change.

Thanks,
Fab

> 
> > >> +  This document doesn't constitue a device tree binding specification by itself
> > >
> > > typo: constitute
> >
> > Well spotted!
> >
> > >> +  but is meant to be referenced by device tree bindings.
> > >> +  When referenced from panel or bridge device tree bindings, the properties
> > >> +  defined in this document are defined as follows. The panel and bridge device
> > >> +  tree bindings are responsible for defining whether each property is required
> > >> +  or optional.
> > >> +
> > >> +properties:
> > >> +  dual-lvds-even-pixels:
> > >> +    type: boolean
> > >> +    description:
> > >> +      This property is specific to an input port of a sink device. When
> > >
> > > The schema should define what nodes these go in. The description seems
> > > to indicate in 'port' nodes (or endpoint?), but your use in the panel
> > > binding puts them in the parent.
> >
> > Did you manage to read this?
> > https://patchwork.kernel.org/cover/11119607/
> >
> > Could you please advice on how to do this properly?
> >
> > >> +      specified, it marks the port as recipient of even-pixels.
> > >> +
> > >> +  dual-lvds-odd-pixels:
> > >> +    type: boolean
> > >> +    description:
> > >> +      This property is specific to an input port of a sink device. When
> > >> +      specified, it marks the port as recipient of odd-pixels.
> > >
> > > However, I don't think you even need these. A panel's port numbers are
> > > fixed can imply even or odd. For example port@0 can be even and port@1
> > > can be odd. The port numbering is typically panel specific, but we may
> > > be able to define the numbering generically if we don't already have
> > > panels with multiple ports.
> > >
> > > Also, aren't there dual link DSI panels?
> >
> > This is the result of a discussion on here:
> > https://patchwork.kernel.org/patch/11095547/
> >
> > Have you come across it?
> 
> Let me repeat my comments from that thread for Rob in order to
> centralize the discussion here.
> 
> > Taking one step back to look at the big picture, what we need is for the
> > source to know what pixel (odd or even) to send on each LVDS output. For
> > that it needs to know what pixel is expected by the sink the the inputs
> > connected to the source's outputs. From each source output we can easily
> > locate the DT nodes corresponding to the connected sink's input ports,
> > but that doesn't give us enough information. From there, we could
> >
> > - Infer the odd/even pixel expected by the source based on the port
> >   numbers. This would require common DT bindings for all dual-link LVDS
> >   sinks that specify the port ordering (for instance the bindings could
> >   mandate that lowest numbered port correspond to even pixels).
> >
> > - Read the odd/even pixel expected by the source from an explicit DT
> >   property, as proposed above. This would also require common DT
> >   bindings for all dual-link LVDS sinks that define these new
> >   properties. This would I think be better than implicitly infering it
> >   from DT port numbers.
> >
> > - Retrieve the information from the sink drm_bridge at runtime. This
> >   would require a way to query the bridge for the mapping from port
> >   number to odd/even pixel. The DRM_LINK_DUAL_LVDS_ODD_EVEN flag could
> >   be used for that, and would then be defined as "the lowest numbered
> >   port corresponds to odd pixels and the highest numbered port
> >   corresponds to even pixels".
> >
> > The second and third options would both work I think. The third one is
> > roughly what you've implemented, except that I think the flag
> > description should be clarified.
> 
> Rob, what's your opinion ? We could certainly, in the context of a
> panel, decide of a fixed mapping of port numbers to odd/even pixels, but
> the issue is that sources need to know which pixels to send on which
> link (assuming of course that this can be configured on the source
> side). We thus need a way for the source to answer, at runtime, the
> question "which of ports A and B of the sink correspond to even and odd
> pixels ?". This can't be inferred by the source from the sink port
> numbers, as the mapping between port number and odd/even pixels is
> specific to each sink. We thus need to either store that property in the
> DT node of the sink (option 2) or query it at runtime from the sink
> (option 3).
> 
> I like option 2 as it's more explicit, but option 3 minimizes the
> required properties in DT, which is always good. Patch 3/8 introduces a
> helper that abstracts this from a sink point of view (which I think is a
> very good idea), so once we decide which option to use, only 3/8 may
> need to be adapted, the other patches should hopefully not require
> rework.
> 
> --
> Regards,
> 
> Laurent Pinchart

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH v3 2/8] dt-bindings: display: Add idk-2121wr binding
  2019-11-07 18:12   ` Laurent Pinchart
@ 2019-12-06 15:17     ` Fabrizio Castro
  0 siblings, 0 replies; 32+ messages in thread
From: Fabrizio Castro @ 2019-12-06 15:17 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Thierry Reding, David Airlie, Daniel Vetter, Rob Herring,
	Mark Rutland, Sam Ravnborg, dri-devel, devicetree, linux-kernel,
	Simon Horman, Geert Uytterhoeven, Chris Paterson, Biju Das,
	linux-renesas-soc, Kieran Bingham, Jacopo Mondi

Hi Laurent,

Thank you for your feedback!

> From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Sent: 07 November 2019 18:12
> Subject: Re: [PATCH v3 2/8] dt-bindings: display: Add idk-2121wr binding
> 
> Hi Fabrizio,
> 
> Thank you for the patch.
> 
> On Wed, Aug 28, 2019 at 07:36:36PM +0100, Fabrizio Castro wrote:
> > Add binding for the idk-2121wr LVDS panel from Advantech.
> >
> > Some panel-specific documentation can be found here:
> > https://buy.advantech.eu/Displays/Embedded-LCD-Kits-High-Brightness/model-IDK-2121WR-K2FHA2E.htm
> >
> > Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> >
> > ---
> > v2->v3:
> > * new patch
> > ---
> >  .../display/panel/advantech,idk-2121wr.yaml        | 90 ++++++++++++++++++++++
> >  1 file changed, 90 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml
> b/Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml
> > new file mode 100644
> > index 0000000..b2ccdc8
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml
> > @@ -0,0 +1,90 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/display/panel/advantech,idk-2121wr.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Advantech IDK-2121WR 21.5" Full-HD dual-LVDS panel
> > +
> > +maintainers:
> > +  - Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> > +  - Thierry Reding <thierry.reding@gmail.com>
> > +
> > +description: |
> > +  The IDK-2121WR from Advantech is a Full-HD dual-LVDS panel.
> > +
> > +  The panels expects odd pixels from the first port, and even pixels from
> 
> s/panels/panel/
> Maybe s/from the/on the/g ?

Will fix

> 
> > +  the second port, therefore the ports must be marked accordingly.
> > +
> > +allOf:
> > +  - $ref: lvds.yaml#
> > +  - $ref: ../bus-timings/lvds.yaml#
> > +
> > +properties:
> > +  compatible:
> > +    items:
> > +      - const: advantech,idk-2121wr
> > +      - {} # panel-lvds, but not listed here to avoid false select
> > +
> > +  data-mapping:
> > +    const: vesa-24
> > +
> > +  width-mm:
> > +    const: 476
> > +
> > +  height-mm:
> > +    const: 268
> > +
> > +  panel-timing: true
> > +  ports: true
> > +
> > +additionalProperties: false
> > +
> > +required:
> > +  - compatible
> 
> Shouldn't data-mapping, width-mm, height-mm and ports be required too ?

Those are required by lvds.yaml, and this file has a reference to it.
Anyhow, I think the best course of action is to merge this with the
generic bus-timings/lvds.yaml for the time being, and maybe split
them back later on once we have another use case.

Thanks,
Fab

> 
> As you mentioned in the cover letter, validating ports, port and the new
> dual-lvds-*-pixels properties would be nice. I'm not YAML schema
> specialist, so I'm fine with a best effort approach here, but as far as
> I understand Rob proposed a way forward, could you try it ?
> 
> Apart from that, the bindings look sne to me, so
> 
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> 
> once the above issues get addressed.
> 
> > +
> > +examples:
> > +  - |+
> > +    panel-lvds {
> > +      compatible = "advantech,idk-2121wr", "panel-lvds";
> > +
> > +      width-mm = <476>;
> > +      height-mm = <268>;
> > +
> > +      data-mapping = "vesa-24";
> > +
> > +      panel-timing {
> > +        clock-frequency = <148500000>;
> > +        hactive = <1920>;
> > +        vactive = <1080>;
> > +        hsync-len = <44>;
> > +        hfront-porch = <88>;
> > +        hback-porch = <148>;
> > +        vfront-porch = <4>;
> > +        vback-porch = <36>;
> > +        vsync-len = <5>;
> > +      };
> > +
> > +      ports {
> > +        #address-cells = <1>;
> > +        #size-cells = <0>;
> > +
> > +        port@0 {
> > +          reg = <0>;
> > +          dual-lvds-odd-pixels;
> > +          panel_in0: endpoint {
> > +            remote-endpoint = <&lvds0_out>;
> > +          };
> > +        };
> > +
> > +        port@1 {
> > +          reg = <1>;
> > +          dual-lvds-even-pixels;
> > +          panel_in1: endpoint {
> > +            remote-endpoint = <&lvds1_out>;
> > +          };
> > +        };
> > +      };
> > +    };
> > +
> > +...
> 
> --
> Regards,
> 
> Laurent Pinchart

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH v3 3/8] drm: Add bus timings helper
  2019-11-07 19:26   ` Laurent Pinchart
  2019-11-07 19:30     ` Daniel Vetter
@ 2019-12-06 15:24     ` Fabrizio Castro
  1 sibling, 0 replies; 32+ messages in thread
From: Fabrizio Castro @ 2019-12-06 15:24 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maarten Lankhorst, Maxime Ripard, Sean Paul, David Airlie,
	Daniel Vetter, linux-kernel, dri-devel, Simon Horman,
	Geert Uytterhoeven, Chris Paterson, Biju Das, linux-renesas-soc,
	Kieran Bingham, Jacopo Mondi, sam

Hi Laurent,

Thank you for your feedback!

> From: linux-kernel-owner@vger.kernel.org <linux-kernel-owner@vger.kernel.org> On Behalf Of Laurent Pinchart
> Sent: 07 November 2019 19:26
> Subject: Re: [PATCH v3 3/8] drm: Add bus timings helper
> 
> Hi Fabrizio,
> 
> Thank you for the patch.
> 
> On Wed, Aug 28, 2019 at 07:36:37PM +0100, Fabrizio Castro wrote:
> > Helper to provide bus timing information.
> 
> You may want to expand this a bit. And actually fix it too, as the
> helper you introduce isn't related to timings (same for the subject
> line).

I'll rework this completely

> 
> > Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> >
> > ---
> > v2->v3:
> > * new patch
> > ---
> >  drivers/gpu/drm/Makefile          |  3 +-
> >  drivers/gpu/drm/drm_bus_timings.c | 97 +++++++++++++++++++++++++++++++++++++++
> >  include/drm/drm_bus_timings.h     | 21 +++++++++
> >  3 files changed, 120 insertions(+), 1 deletion(-)
> >  create mode 100644 drivers/gpu/drm/drm_bus_timings.c
> >  create mode 100644 include/drm/drm_bus_timings.h
> >
> > diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> > index 9f0d2ee..a270063 100644
> > --- a/drivers/gpu/drm/Makefile
> > +++ b/drivers/gpu/drm/Makefile
> > @@ -17,7 +17,8 @@ drm-y       :=	drm_auth.o drm_cache.o \
> >  		drm_plane.o drm_color_mgmt.o drm_print.o \
> >  		drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
> >  		drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \
> > -		drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o
> > +		drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o \
> > +		drm_bus_timings.o
> >
> >  drm-$(CONFIG_DRM_LEGACY) += drm_legacy_misc.o drm_bufs.o drm_context.o drm_dma.o drm_scatter.o drm_lock.o
> >  drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
> > diff --git a/drivers/gpu/drm/drm_bus_timings.c b/drivers/gpu/drm/drm_bus_timings.c
> > new file mode 100644
> > index 0000000..e2ecd22
> > --- /dev/null
> > +++ b/drivers/gpu/drm/drm_bus_timings.c
> > @@ -0,0 +1,97 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +#include <drm/drm_bus_timings.h>
> > +#include <linux/errno.h>
> > +#include <linux/of_graph.h>
> > +#include <linux/of.h>
> > +#include <linux/types.h>
> > +
> > +#define DRM_OF_LVDS_ODD		1
> > +#define DRM_OF_LVDS_EVEN	2
> > +
> > +static int drm_of_lvds_get_port_pixels_type(struct device_node *port_node)
> > +{
> > +	bool even_pixels, odd_pixels;
> > +
> > +	even_pixels = of_property_read_bool(port_node, "dual-lvds-even-pixels");
> > +	odd_pixels = of_property_read_bool(port_node, "dual-lvds-odd-pixels");
> > +	return  even_pixels * DRM_OF_LVDS_EVEN + odd_pixels * DRM_OF_LVDS_ODD;
> 
> s/  / /
> 
> But I would make these bitflags.
> 
> enum drm_of_lvds_pixels {
> 	DRM_OF_LVDS_EVEN = BIT(0),
> 	DRM_OF_LVDS_ODD = BIT(1),
> };
> 
> static int drm_of_lvds_get_port_pixels_type(struct device_node *port)
> {
> 	bool even_pixels = of_property_read_bool(port, "dual-lvds-even-pixels");
> 	bool odd_pixels = of_property_read_bool(port, "dual-lvds-odd-pixels");
> 
> 	return (even_pixels ? DRM_OF_LVDS_EVEN : 0) |
> 	       (odd_pixels ? DRM_OF_LVDS_ODD : 0);
> }

Will do

> 
> > +}
> > +
> > +/**
> > + * drm_of_lvds_get_dual_link_configuration - get the dual-LVDS configuration
> 
> Should we name this drm_of_lvds_get_dual_link_pixel_order to better
> reflect its purpose ?
> 
> > + * @p1: device tree node corresponding to the first port of the source
> > + * @p2: device tree node corresponding to the second port of the source
> 
> Maybe port1 and port2 to make this more explicit ?

yeah

> 
> > + *
> > + * An LVDS dual-link bus is made of two connections, even pixels transit on one
> > + * connection, and odd pixels transit on the other connection.
> 
> To match the DT bindings documentation, I would recommand
> 
> "An LVDS dual-link connection is made of two links, with even pixels
> transitting on one link, and odd pixels on the other link."
> 
> > + * This function walks the DT (from the source ports to the sink ports) looking
> > + * for a dual-LVDS bus. A dual-LVDS bus is identfied by markers found on the DT
> > + * ports of the sink device(s). If such a bus is found, this function returns
> > + * its configuration (either p1 connected to the even pixels port and p2
> > + * connected to the odd pixels port, or p1 connected to the odd pixels port and
> > + * p2 connected to the even pixels port).
> 
> "walking the DT" sounds like the function goes through the whole graph.
> How about the following ?
> 
> /**
>  * drm_of_lvds_get_dual_link_pixel_order - Get LVDS dual-link pixel order
>  * @port1: First DT port node of the Dual-link LVDS source
>  * @port2: Second DT port node of the Dual-link LVDS source
>  *
>  * An LVDS dual-link connection is made of two links, with even pixels
>  * transitting on one link, and odd pixels on the other link. This function
>  * returns, for two ports of an LVDS dual-link source, which port shall transmit
>  * the even and off pixels, based on the requirements of the connected sink.
>  *
>  * The pixel order is determined from the dual-lvds-even-pixels and
>  * dual-lvds-odd-pixels properties in the sink's DT port nodes. If those
>  * properties are not present, or if their usage is not valid, this function
>  * returns -EINVAL.
>  *
>  * @port1 and @port2 are typically DT sibling nodes, but may have different
>  * parents when, for instance, two separate LVDS encoders carry the even and odd
>  * pixels.
>  *
>  * Return:
>  * * DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS - @port1 carries even pixels and @port2
>  *   carries odd pixels
>  * * DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS - @port1 carries odd pixels and @port1
>  *   carries even pixels
>  * * -EINVAL - @port1 and @port2 are not connected to a dual-link LVDS sink, or
>  *   the sink configuration is invalid
>  */

Can do

> 
> We could also add -EPIPE as a return code for the case where port1 or
> port2 are not connected.

Good idea, will add

> 
> > + *
> > + * Return: A code describing the bus configuration when a valid dual-LVDS bus is
> > + * found, or an error code when no valid dual-LVDS bus is found
> > + *
> > + * Possible codes for the bus configuration are:
> > + *
> > + * - DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS: when p1 is connected to the even pixels
> > + *   port and p2 is connected to the odd pixels port
> > + * - DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS: when p1 is connected to the odd pixels
> > + *   port and p2 is connected to the even pixels port
> > + *
> > + */
> > +int drm_of_lvds_get_dual_link_configuration(const struct device_node *p1,
> > +					    const struct device_node *p2)
> > +{
> > +	struct device_node *remote_p1 = NULL, *remote_p2 = NULL;
> > +	struct device_node *parent_p1 = NULL, *parent_p2 = NULL;
> 
> There's no need to initialize those two variables.

Will change

> 
> > +	struct device_node *ep1 = NULL, *ep2 = NULL;
> > +	u32 reg_p1, reg_p2;
> > +	int ret = -EINVAL, remote_p1_pt, remote_p2_pt;
> 
> Please split this last line, as it otherwise hides the initialization of
> ret in the middle.

Will change

> 
> > +
> > +	if (!p1 || !p2)
> > +		return ret;
> 
> You can return -EINVAL directly.

ok

> 
> 
> > +	if (of_property_read_u32(p1, "reg", &reg_p1) ||
> > +	    of_property_read_u32(p2, "reg", &reg_p2))
> > +		return ret;
> 
> Same here.

ok

> 
> > +	parent_p1 = of_get_parent(p1);
> > +	parent_p2 = of_get_parent(p2);
> > +	if (!parent_p1 || !parent_p2)
> > +		goto done;
> > +	ep1 = of_graph_get_endpoint_by_regs(parent_p1, reg_p1, 0);
> > +	ep2 = of_graph_get_endpoint_by_regs(parent_p2, reg_p2, 0);
> > +	if (!ep1 || !ep2)
> > +		goto done;
> 
> If you only support the first endpoint, this should be mentioned in the
> documentation. Alternatively you could pass the endpoint nodes instead
> of the port nodes, or you could pass the endpoint number.

Or alternatively I could inspect all of the remote endpoints

> 
> It's also a bit inefficient to use of_graph_get_endpoint_by_regs() when
> you already have the port nodes. How about adding the following helper
> function ?

I'll implement something to walk through all of the endpoints we are connected to.
Will send something shortly for you to have a look at.

> 
> struct device_node *of_graph_get_port_endpoint(struct device_node *port, int reg)
> {
> 	struct device_node *endpoint = NULL;
> 
> 	for_each_child_of_node(port, endpoint) {
> 		u32 id;
> 
> 		if (!of_node_name_eq(endpoint, "endpoint") ||
> 			continue;
> 
> 		if (reg == -1)
> 			return endpoint;
> 
> 		if (of_property_read_u32(node, "reg", &id) < 0)
> 			continue;
> 
> 		if (reg == id)
> 			return endpoint;
> 	}
> 
> 	return NULL;
> }
> 
> If you're concerned that adding a core helper would delay this patch
> series, you could add it as a local helper, and move it to of_graph.h in
> a second step.
> 
> > +	remote_p1 = of_graph_get_remote_port(ep1);
> > +	remote_p2 = of_graph_get_remote_port(ep2);
> > +	if (!remote_p1 || !remote_p2)
> > +		goto done;
> > +	remote_p1_pt = drm_of_lvds_get_port_pixels_type(remote_p1);
> > +	remote_p2_pt = drm_of_lvds_get_port_pixels_type(remote_p2);
> > +	/*
> > +	 * A valid dual-lVDS bus is found when one remote port is marked with
> > +	 * "dual-lvds-even-pixels", and the other remote port is marked with
> > +	 * "dual-lvds-odd-pixels", bail out if the markers are not right.
> > +	 */
> > +	if (!remote_p1_pt || !remote_p2_pt ||
> > +	    remote_p1_pt + remote_p2_pt != DRM_OF_LVDS_EVEN + DRM_OF_LVDS_ODD)
> > +		goto done;
> > +	if (remote_p1_pt == DRM_OF_LVDS_EVEN)
> > +		/* The sink expects even pixels through the first port */
> > +		ret = DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS;
> > +	else
> > +		/* The sink expects odd pixels through the first port */
> > +		ret = DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS;
> > +
> > +done:
> > +	of_node_put(ep1);
> > +	of_node_put(ep2);
> > +	of_node_put(parent_p1);
> > +	of_node_put(parent_p2);
> > +	of_node_put(remote_p1);
> > +	of_node_put(remote_p2);
> > +	return ret;
> 
> This is heavy, I would add blank lines to make the code easier to read.

Most of this will disappear in v4

> 
> > +}
> > +EXPORT_SYMBOL_GPL(drm_of_lvds_get_dual_link_configuration);
> > diff --git a/include/drm/drm_bus_timings.h b/include/drm/drm_bus_timings.h
> > new file mode 100644
> > index 0000000..db8a385
> > --- /dev/null
> > +++ b/include/drm/drm_bus_timings.h
> > @@ -0,0 +1,21 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +#ifndef __DRM_BUS_TIMINGS__
> > +#define __DRM_BUS_TIMINGS__
> > +
> > +struct device_node;
> > +
> > +#define DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS	0
> > +#define DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS	1
> 
> These should be documented with kerneldoc. How about also turning them
> into an enum ?

Will change

Thanks,
Fab

> 
> > +
> > +#ifdef CONFIG_OF
> > +int drm_of_lvds_get_dual_link_configuration(const struct device_node *p1,
> > +					    const struct device_node *p2);
> > +#else
> > +int drm_of_lvds_get_dual_link_configuration(const struct device_node *p1,
> > +					    const struct device_node *p2)
> > +{
> > +	return -EINVAL;
> > +}
> > +#endif
> > +
> > +#endif /* __DRM_BUS_TIMINGS__ */
> 
> --
> Regards,
> 
> Laurent Pinchart

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH v3 3/8] drm: Add bus timings helper
  2019-11-07 19:30     ` Daniel Vetter
@ 2019-12-06 15:25       ` Fabrizio Castro
  0 siblings, 0 replies; 32+ messages in thread
From: Fabrizio Castro @ 2019-12-06 15:25 UTC (permalink / raw)
  To: Daniel Vetter, Laurent Pinchart
  Cc: Maarten Lankhorst, Maxime Ripard, Sean Paul, David Airlie,
	linux-kernel, dri-devel, Simon Horman, Geert Uytterhoeven,
	Chris Paterson, Biju Das, linux-renesas-soc, Kieran Bingham,
	Jacopo Mondi, sam

Hi Daniel,

Thank you for your feedback!

> From: Daniel Vetter <daniel.vetter@ffwll.ch> On Behalf Of Daniel Vetter
> Sent: 07 November 2019 19:30
> Subject: Re: [PATCH v3 3/8] drm: Add bus timings helper
> 
> On Thu, Nov 07, 2019 at 09:26:21PM +0200, Laurent Pinchart wrote:
> > Hi Fabrizio,
> >
> > Thank you for the patch.
> >
> > On Wed, Aug 28, 2019 at 07:36:37PM +0100, Fabrizio Castro wrote:
> > > Helper to provide bus timing information.
> >
> > You may want to expand this a bit. And actually fix it too, as the
> > helper you introduce isn't related to timings (same for the subject
> > line).
> 
> Also the kerneldoc needs to be pulled into the templates under
> Documentation/gpu. And since it's just one function, why not put this into
> drm_of.c? Gets rid of a pile of overhead.

Yeah, you are right, will try and pull this into drm_of.c in v4.

Thanks!

Fab

> 
> >
> > > Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> > >
> > > ---
> > > v2->v3:
> > > * new patch
> > > ---
> > >  drivers/gpu/drm/Makefile          |  3 +-
> > >  drivers/gpu/drm/drm_bus_timings.c | 97 +++++++++++++++++++++++++++++++++++++++
> > >  include/drm/drm_bus_timings.h     | 21 +++++++++
> > >  3 files changed, 120 insertions(+), 1 deletion(-)
> > >  create mode 100644 drivers/gpu/drm/drm_bus_timings.c
> > >  create mode 100644 include/drm/drm_bus_timings.h
> > >
> > > diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> > > index 9f0d2ee..a270063 100644
> > > --- a/drivers/gpu/drm/Makefile
> > > +++ b/drivers/gpu/drm/Makefile
> > > @@ -17,7 +17,8 @@ drm-y       :=	drm_auth.o drm_cache.o \
> > >  		drm_plane.o drm_color_mgmt.o drm_print.o \
> > >  		drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
> > >  		drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \
> > > -		drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o
> > > +		drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o \
> > > +		drm_bus_timings.o
> > >
> > >  drm-$(CONFIG_DRM_LEGACY) += drm_legacy_misc.o drm_bufs.o drm_context.o drm_dma.o drm_scatter.o drm_lock.o
> > >  drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
> > > diff --git a/drivers/gpu/drm/drm_bus_timings.c b/drivers/gpu/drm/drm_bus_timings.c
> > > new file mode 100644
> > > index 0000000..e2ecd22
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/drm_bus_timings.c
> > > @@ -0,0 +1,97 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> 
> DRM core is supposed to be MIT.
> -Daniel
> 
> > > +#include <drm/drm_bus_timings.h>
> > > +#include <linux/errno.h>
> > > +#include <linux/of_graph.h>
> > > +#include <linux/of.h>
> > > +#include <linux/types.h>
> > > +
> > > +#define DRM_OF_LVDS_ODD		1
> > > +#define DRM_OF_LVDS_EVEN	2
> > > +
> > > +static int drm_of_lvds_get_port_pixels_type(struct device_node *port_node)
> > > +{
> > > +	bool even_pixels, odd_pixels;
> > > +
> > > +	even_pixels = of_property_read_bool(port_node, "dual-lvds-even-pixels");
> > > +	odd_pixels = of_property_read_bool(port_node, "dual-lvds-odd-pixels");
> > > +	return  even_pixels * DRM_OF_LVDS_EVEN + odd_pixels * DRM_OF_LVDS_ODD;
> >
> > s/  / /
> >
> > But I would make these bitflags.
> >
> > enum drm_of_lvds_pixels {
> > 	DRM_OF_LVDS_EVEN = BIT(0),
> > 	DRM_OF_LVDS_ODD = BIT(1),
> > };
> >
> > static int drm_of_lvds_get_port_pixels_type(struct device_node *port)
> > {
> > 	bool even_pixels = of_property_read_bool(port, "dual-lvds-even-pixels");
> > 	bool odd_pixels = of_property_read_bool(port, "dual-lvds-odd-pixels");
> >
> > 	return (even_pixels ? DRM_OF_LVDS_EVEN : 0) |
> > 	       (odd_pixels ? DRM_OF_LVDS_ODD : 0);
> > }
> >
> > > +}
> > > +
> > > +/**
> > > + * drm_of_lvds_get_dual_link_configuration - get the dual-LVDS configuration
> >
> > Should we name this drm_of_lvds_get_dual_link_pixel_order to better
> > reflect its purpose ?
> >
> > > + * @p1: device tree node corresponding to the first port of the source
> > > + * @p2: device tree node corresponding to the second port of the source
> >
> > Maybe port1 and port2 to make this more explicit ?
> >
> > > + *
> > > + * An LVDS dual-link bus is made of two connections, even pixels transit on one
> > > + * connection, and odd pixels transit on the other connection.
> >
> > To match the DT bindings documentation, I would recommand
> >
> > "An LVDS dual-link connection is made of two links, with even pixels
> > transitting on one link, and odd pixels on the other link."
> >
> > > + * This function walks the DT (from the source ports to the sink ports) looking
> > > + * for a dual-LVDS bus. A dual-LVDS bus is identfied by markers found on the DT
> > > + * ports of the sink device(s). If such a bus is found, this function returns
> > > + * its configuration (either p1 connected to the even pixels port and p2
> > > + * connected to the odd pixels port, or p1 connected to the odd pixels port and
> > > + * p2 connected to the even pixels port).
> >
> > "walking the DT" sounds like the function goes through the whole graph.
> > How about the following ?
> >
> > /**
> >  * drm_of_lvds_get_dual_link_pixel_order - Get LVDS dual-link pixel order
> >  * @port1: First DT port node of the Dual-link LVDS source
> >  * @port2: Second DT port node of the Dual-link LVDS source
> >  *
> >  * An LVDS dual-link connection is made of two links, with even pixels
> >  * transitting on one link, and odd pixels on the other link. This function
> >  * returns, for two ports of an LVDS dual-link source, which port shall transmit
> >  * the even and off pixels, based on the requirements of the connected sink.
> >  *
> >  * The pixel order is determined from the dual-lvds-even-pixels and
> >  * dual-lvds-odd-pixels properties in the sink's DT port nodes. If those
> >  * properties are not present, or if their usage is not valid, this function
> >  * returns -EINVAL.
> >  *
> >  * @port1 and @port2 are typically DT sibling nodes, but may have different
> >  * parents when, for instance, two separate LVDS encoders carry the even and odd
> >  * pixels.
> >  *
> >  * Return:
> >  * * DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS - @port1 carries even pixels and @port2
> >  *   carries odd pixels
> >  * * DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS - @port1 carries odd pixels and @port1
> >  *   carries even pixels
> >  * * -EINVAL - @port1 and @port2 are not connected to a dual-link LVDS sink, or
> >  *   the sink configuration is invalid
> >  */
> >
> > We could also add -EPIPE as a return code for the case where port1 or
> > port2 are not connected.
> >
> > > + *
> > > + * Return: A code describing the bus configuration when a valid dual-LVDS bus is
> > > + * found, or an error code when no valid dual-LVDS bus is found
> > > + *
> > > + * Possible codes for the bus configuration are:
> > > + *
> > > + * - DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS: when p1 is connected to the even pixels
> > > + *   port and p2 is connected to the odd pixels port
> > > + * - DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS: when p1 is connected to the odd pixels
> > > + *   port and p2 is connected to the even pixels port
> > > + *
> > > + */
> > > +int drm_of_lvds_get_dual_link_configuration(const struct device_node *p1,
> > > +					    const struct device_node *p2)
> > > +{
> > > +	struct device_node *remote_p1 = NULL, *remote_p2 = NULL;
> > > +	struct device_node *parent_p1 = NULL, *parent_p2 = NULL;
> >
> > There's no need to initialize those two variables.
> >
> > > +	struct device_node *ep1 = NULL, *ep2 = NULL;
> > > +	u32 reg_p1, reg_p2;
> > > +	int ret = -EINVAL, remote_p1_pt, remote_p2_pt;
> >
> > Please split this last line, as it otherwise hides the initialization of
> > ret in the middle.
> >
> > > +
> > > +	if (!p1 || !p2)
> > > +		return ret;
> >
> > You can return -EINVAL directly.
> >
> >
> > > +	if (of_property_read_u32(p1, "reg", &reg_p1) ||
> > > +	    of_property_read_u32(p2, "reg", &reg_p2))
> > > +		return ret;
> >
> > Same here.
> >
> > > +	parent_p1 = of_get_parent(p1);
> > > +	parent_p2 = of_get_parent(p2);
> > > +	if (!parent_p1 || !parent_p2)
> > > +		goto done;
> > > +	ep1 = of_graph_get_endpoint_by_regs(parent_p1, reg_p1, 0);
> > > +	ep2 = of_graph_get_endpoint_by_regs(parent_p2, reg_p2, 0);
> > > +	if (!ep1 || !ep2)
> > > +		goto done;
> >
> > If you only support the first endpoint, this should be mentioned in the
> > documentation. Alternatively you could pass the endpoint nodes instead
> > of the port nodes, or you could pass the endpoint number.
> >
> > It's also a bit inefficient to use of_graph_get_endpoint_by_regs() when
> > you already have the port nodes. How about adding the following helper
> > function ?
> >
> > struct device_node *of_graph_get_port_endpoint(struct device_node *port, int reg)
> > {
> > 	struct device_node *endpoint = NULL;
> >
> > 	for_each_child_of_node(port, endpoint) {
> > 		u32 id;
> >
> > 		if (!of_node_name_eq(endpoint, "endpoint") ||
> > 			continue;
> >
> > 		if (reg == -1)
> > 			return endpoint;
> >
> > 		if (of_property_read_u32(node, "reg", &id) < 0)
> > 			continue;
> >
> > 		if (reg == id)
> > 			return endpoint;
> > 	}
> >
> > 	return NULL;
> > }
> >
> > If you're concerned that adding a core helper would delay this patch
> > series, you could add it as a local helper, and move it to of_graph.h in
> > a second step.
> >
> > > +	remote_p1 = of_graph_get_remote_port(ep1);
> > > +	remote_p2 = of_graph_get_remote_port(ep2);
> > > +	if (!remote_p1 || !remote_p2)
> > > +		goto done;
> > > +	remote_p1_pt = drm_of_lvds_get_port_pixels_type(remote_p1);
> > > +	remote_p2_pt = drm_of_lvds_get_port_pixels_type(remote_p2);
> > > +	/*
> > > +	 * A valid dual-lVDS bus is found when one remote port is marked with
> > > +	 * "dual-lvds-even-pixels", and the other remote port is marked with
> > > +	 * "dual-lvds-odd-pixels", bail out if the markers are not right.
> > > +	 */
> > > +	if (!remote_p1_pt || !remote_p2_pt ||
> > > +	    remote_p1_pt + remote_p2_pt != DRM_OF_LVDS_EVEN + DRM_OF_LVDS_ODD)
> > > +		goto done;
> > > +	if (remote_p1_pt == DRM_OF_LVDS_EVEN)
> > > +		/* The sink expects even pixels through the first port */
> > > +		ret = DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS;
> > > +	else
> > > +		/* The sink expects odd pixels through the first port */
> > > +		ret = DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS;
> > > +
> > > +done:
> > > +	of_node_put(ep1);
> > > +	of_node_put(ep2);
> > > +	of_node_put(parent_p1);
> > > +	of_node_put(parent_p2);
> > > +	of_node_put(remote_p1);
> > > +	of_node_put(remote_p2);
> > > +	return ret;
> >
> > This is heavy, I would add blank lines to make the code easier to read.
> >
> > > +}
> > > +EXPORT_SYMBOL_GPL(drm_of_lvds_get_dual_link_configuration);
> > > diff --git a/include/drm/drm_bus_timings.h b/include/drm/drm_bus_timings.h
> > > new file mode 100644
> > > index 0000000..db8a385
> > > --- /dev/null
> > > +++ b/include/drm/drm_bus_timings.h
> > > @@ -0,0 +1,21 @@
> > > +/* SPDX-License-Identifier: GPL-2.0 */
> > > +#ifndef __DRM_BUS_TIMINGS__
> > > +#define __DRM_BUS_TIMINGS__
> > > +
> > > +struct device_node;
> > > +
> > > +#define DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS	0
> > > +#define DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS	1
> >
> > These should be documented with kerneldoc. How about also turning them
> > into an enum ?
> >
> > > +
> > > +#ifdef CONFIG_OF
> > > +int drm_of_lvds_get_dual_link_configuration(const struct device_node *p1,
> > > +					    const struct device_node *p2);
> > > +#else
> > > +int drm_of_lvds_get_dual_link_configuration(const struct device_node *p1,
> > > +					    const struct device_node *p2)
> > > +{
> > > +	return -EINVAL;
> > > +}
> > > +#endif
> > > +
> > > +#endif /* __DRM_BUS_TIMINGS__ */
> >
> > --
> > Regards,
> >
> > Laurent Pinchart
> 
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH v3 4/8] drm: rcar-du: lvds: Add dual-LVDS panels support
  2019-11-07 19:50   ` Laurent Pinchart
@ 2019-12-06 15:35     ` Fabrizio Castro
  0 siblings, 0 replies; 32+ messages in thread
From: Fabrizio Castro @ 2019-12-06 15:35 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: David Airlie, Daniel Vetter, Kieran Bingham, dri-devel,
	linux-renesas-soc, linux-kernel, Simon Horman,
	Geert Uytterhoeven, Chris Paterson, Biju Das, Jacopo Mondi, sam

Hi Laurent,

> From: linux-renesas-soc-owner@vger.kernel.org <linux-renesas-soc-owner@vger.kernel.org> On Behalf Of Laurent Pinchart
> Sent: 07 November 2019 19:51
> Subject: Re: [PATCH v3 4/8] drm: rcar-du: lvds: Add dual-LVDS panels support
> 
> Hi Fabrizio,
> 
> Thank you for the patch.
> 
> On Wed, Aug 28, 2019 at 07:36:38PM +0100, Fabrizio Castro wrote:
> > The driver doesn't support dual-link LVDS displays, and the way
> > it identifies bridges won't allow for dual-LVDS displays to be
> > connected. Also, it's not possible to swap even and odd pixels
> > around in case the wiring isn't taking advantage of the default
> > hardware configuration. Further more, the "mode" of the companion
> > encoder should be same as the mode of the primary encoder.
> >
> > Rework the driver to improve all of the above, so that it can
> > support dual-LVDS displays.
> 
> That's lots of changes in one patch, could it be split to ease review ?
> Also, should the commit message be reworded to explain what the patch
> does, instead of enumerating issues ? When there's a single issue being
> addressed in a patch it's usually fine, but there the change is larger,
> without an explanation of how you intend to fix the issues I can't tell
> if the code really matches your intent.

Sorry for the pain, I'll split this patch into smaller patches.

> 
> > Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> >
> > ---
> > v2->v3:
> > * reworked to take advantange of the new dt-bindings
> > * squashed in the patche for fixing the companion's mode
> >
> > Laurent,
> >
> > unfortunately the best way to get the companion encoder to use
> > the same mode as the primary encoder is setting the mode directly
> > without calling into rcar_lvds_mode_set for the companion encoder,
> > as the below test fails for the companion encoder in
> > rcar_lvds_get_lvds_mode:
> > if (!info->num_bus_formats || !info->bus_formats)
> 
> Would "[PATCH] drm: rcar-du: lvds: Get mode from state" help here ?
> Maybe you could review that patch, I could then include it in my -next
> branch, your work would be simplified, and everybody would be happy ?
> :-)

I gave that a try, it doesn't work for me, even after fixing the NULL
pointer. Perhaps we could finalize this series first and then we could figure
that patch out next?

> 
> > Anyhow, setting the mode for the companion encoder doesn't seem
> > to be mandary according to the experiments I have been running,
> > but the HW User's Manual doesn't really say much about this,
> > therefore I think the safest option is still to set the mode for
> > the companion encoder.
> 
> I agree it should be done.
> 
> > ---
> >  drivers/gpu/drm/rcar-du/rcar_lvds.c | 110 +++++++++++++++++++++---------------
> >  1 file changed, 65 insertions(+), 45 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> > index 3fe0b86..dfec5e7 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> > @@ -20,6 +20,8 @@
> >  #include <drm/drm_atomic.h>
> >  #include <drm/drm_atomic_helper.h>
> >  #include <drm/drm_bridge.h>
> > +#include <drm/drm_bus_timings.h>
> > +#include <drm/drm_of.h>
> >  #include <drm/drm_panel.h>
> >  #include <drm/drm_probe_helper.h>
> >
> > @@ -69,6 +71,7 @@ struct rcar_lvds {
> >
> >  	struct drm_bridge *companion;
> >  	bool dual_link;
> > +	bool stripe_swap_data;
> >  };
> >
> >  #define bridge_to_rcar_lvds(b) \
> > @@ -439,12 +442,20 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
> >  	rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
> >
> >  	if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) {
> > -		/*
> > -		 * Configure vertical stripe based on the mode of operation of
> > -		 * the connected device.
> > -		 */
> > -		rcar_lvds_write(lvds, LVDSTRIPE,
> > -				lvds->dual_link ? LVDSTRIPE_ST_ON : 0);
> > +		u32 lvdstripe = 0;
> > +
> > +		if (lvds->dual_link)
> > +			/*
> > +			 * Configure vertical stripe based on the mode of
> > +			 * operation of the connected device.
> > +			 *
> > +			 * ST_SWAP from LVD1STRIPE is reserved, do not set
> > +			 * in the companion LVDS
> > +			 */
> > +			lvdstripe = LVDSTRIPE_ST_ON |
> > +				(lvds->companion && lvds->stripe_swap_data ?
> > +				 LVDSTRIPE_ST_SWAP : 0);
> > +		rcar_lvds_write(lvds, LVDSTRIPE, lvdstripe);
> >  	}
> >
> >  	/*
> > @@ -603,6 +614,11 @@ static void rcar_lvds_mode_set(struct drm_bridge *bridge,
> >  	lvds->display_mode = *adjusted_mode;
> >
> >  	rcar_lvds_get_lvds_mode(lvds);
> > +	if (lvds->companion) {
> > +		struct rcar_lvds *companion_lvds = bridge_to_rcar_lvds(
> > +							lvds->companion);
> > +		companion_lvds->mode = lvds->mode;
> > +	}
> >  }
> >
> >  static int rcar_lvds_attach(struct drm_bridge *bridge)
> > @@ -667,9 +683,10 @@ EXPORT_SYMBOL_GPL(rcar_lvds_dual_link);
> >  static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds)
> >  {
> >  	const struct of_device_id *match;
> > -	struct device_node *companion;
> > +	struct device_node *companion, *p0 = NULL, *p1 = NULL;
> >  	struct device *dev = lvds->dev;
> > -	int ret = 0;
> > +	struct rcar_lvds *companion_lvds;
> > +	int ret = 0, dual_link;
> >
> >  	/* Locate the companion LVDS encoder for dual-link operation, if any. */
> >  	companion = of_parse_phandle(dev->of_node, "renesas,companion", 0);
> > @@ -687,16 +704,50 @@ static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds)
> >  		goto done;
> >  	}
> >
> > +	/*
> > +	 * We need to work out if the sink is expecting us to function in
> > +	 * dual-link mode. We do this by looking at the DT port nodes we are
> > +	 * connected to, if they are marked as expecting even pixels and
> > +	 * odd pixels than we need to enable vertical stripe output
> > +	 */
> > +	p0 = of_graph_get_port_by_id(dev->of_node, 1);
> > +	p1 = of_graph_get_port_by_id(companion, 1);
> > +	dual_link = drm_of_lvds_get_dual_link_configuration(p0, p1);
> 
> You can call of_node_put(p0) and of_node_put(p1) here instead of adding
> them at the end of the function.

I'll be restructuring this code a little, and I'll move the put up here, as you suggested

> 
> > +	if (dual_link >= DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS) {
> > +		dev_dbg(dev, "Dual-link configuration detected\n");
> > +		lvds->dual_link = true;
> > +	} else {
> > +		/* dual-link mode is not required */
> > +		dev_dbg(dev, "Single-link configuration detected\n");
> > +		goto done;
> > +	}
> 
> Missing blank line here.

Thanks

> 
> > +	/*
> > +	 * We may need to swap even and odd pixels around in case the wiring
> > +	 * doesn't match the default configuration.
> > +	 * By default we generate even pixels from this encoder and odd pixels
> > +	 * from the companion encoder, but if p0 is connected to the port
> > +	 * expecting ood pixels, and p1 is connected to the port expecting even
> > +	 * pixels, then we need to swap even and odd pixels around
> > +	 */
> > +	if (dual_link == DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS) {
> > +		dev_dbg(dev, "Data swapping required\n");
> > +		lvds->stripe_swap_data = true;
> > +	}
> > +
> >  	lvds->companion = of_drm_find_bridge(companion);
> >  	if (!lvds->companion) {
> >  		ret = -EPROBE_DEFER;
> >  		goto done;
> >  	}
> > +	companion_lvds = bridge_to_rcar_lvds(lvds->companion);
> > +	companion_lvds->dual_link = lvds->dual_link;
> 
> I don't like poking directly in the companion like this :-( Can't we let
> the companion detect dual link mode itself ?

I don't like it either, but the companion encoder doesn't hold a reference to the
Primary encoder right now, so we would need to change strategy for this.
I think perhaps we could add this solution to the driver, and then we fix it
properly later on?

> 
> >
> >  	dev_dbg(dev, "Found companion encoder %pOF\n", companion);
> >
> >  done:
> >  	of_node_put(companion);
> > +	of_node_put(p0);
> > +	of_node_put(p1);
> >
> >  	return ret;
> >  }
> > @@ -704,10 +755,7 @@ static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds)
> >  static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
> >  {
> >  	struct device_node *local_output = NULL;
> > -	struct device_node *remote_input = NULL;
> >  	struct device_node *remote = NULL;
> > -	struct device_node *node;
> > -	bool is_bridge = false;
> >  	int ret = 0;
> >
> >  	local_output = of_graph_get_endpoint_by_regs(lvds->dev->of_node, 1, 0);
> > @@ -735,45 +783,17 @@ static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
> >  		goto done;
> >  	}
> >
> 
> I think you can also drop all the code above.
> 
> > -	remote_input = of_graph_get_remote_endpoint(local_output);
> > -
> > -	for_each_endpoint_of_node(remote, node) {
> > -		if (node != remote_input) {
> > -			/*
> > -			 * We've found one endpoint other than the input, this
> > -			 * must be a bridge.
> > -			 */
> > -			is_bridge = true;
> > -			of_node_put(node);
> > -			break;
> > -		}
> > -	}
> > -
> > -	if (is_bridge) {
> > -		lvds->next_bridge = of_drm_find_bridge(remote);
> > -		if (!lvds->next_bridge) {
> > -			ret = -EPROBE_DEFER;
> > -			goto done;
> > -		}
> > -
> > -		if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK)
> > -			lvds->dual_link = lvds->next_bridge->timings
> > -					? lvds->next_bridge->timings->dual_link
> > -					: false;
> 
> Aren't you breaking backward compatibility with this change ? Unless I'm
> mistaken you're now requiring the new DT properties, and the existing DT
> that include a thc63lvd1024 won't have them.

Unfortunately I am breaking backward compatibility here. Will be more careful
in v4, sorry!

> 
> > -	} else {
> > -		lvds->panel = of_drm_find_panel(remote);
> > -		if (IS_ERR(lvds->panel)) {
> > -			ret = PTR_ERR(lvds->panel);
> > -			goto done;
> > -		}
> > +	ret = drm_of_find_panel_or_bridge(lvds->dev->of_node, 1, 0,
> > +					  &lvds->panel, &lvds->next_bridge);
> > +	if (ret) {
> > +		ret = -EPROBE_DEFER;
> 
> Shouldn't you return ret instead of overriding it ?

Can do


Thanks,
Fab

> 
> > +		goto done;
> >  	}
> > -
> > -	if (lvds->dual_link)
> > +	if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK)
> >  		ret = rcar_lvds_parse_dt_companion(lvds);
> >
> >  done:
> >  	of_node_put(local_output);
> > -	of_node_put(remote_input);
> >  	of_node_put(remote);
> >
> >  	/*
> 
> --
> Regards,
> 
> Laurent Pinchart

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH v3 5/8] drm: bridge: thc63: Do not report input bus mode through bridge timings
  2019-11-07 19:52   ` Laurent Pinchart
@ 2019-12-06 15:38     ` Fabrizio Castro
  0 siblings, 0 replies; 32+ messages in thread
From: Fabrizio Castro @ 2019-12-06 15:38 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Andrzej Hajda, David Airlie, Daniel Vetter, Maarten Lankhorst,
	Maxime Ripard, Sean Paul, dri-devel, linux-kernel, Simon Horman,
	Geert Uytterhoeven, Chris Paterson, Biju Das, linux-renesas-soc,
	Kieran Bingham, Jacopo Mondi, sam

Hi Laurent,

Thank you for your feedback!

> From: linux-kernel-owner@vger.kernel.org <linux-kernel-owner@vger.kernel.org> On Behalf Of Laurent Pinchart
> Sent: 07 November 2019 19:52
> Subject: Re: [PATCH v3 5/8] drm: bridge: thc63: Do not report input bus mode through bridge timings
> 
> Hi Fabrizio,
> 
> Thank you for the patch.
> 
> On Wed, Aug 28, 2019 at 07:36:39PM +0100, Fabrizio Castro wrote:
> > No need to report the input bus mode through bridge timings
> > anymore, that's now done through the DT, as specified by the
> > dt-bindings.
> 
> Doesn't this break backward compatibility with older DT, as mentioned in
> the review of 4/8 ?
> 

I'll drop this patch in v4

Thanks,
Fab

> > Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> >
> > ---
> > v2->v3:
> > * new patch
> > ---
> >  drivers/gpu/drm/bridge/thc63lvd1024.c | 9 ++++-----
> >  include/drm/drm_bridge.h              | 8 --------
> >  2 files changed, 4 insertions(+), 13 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c b/drivers/gpu/drm/bridge/thc63lvd1024.c
> > index 3d74129b..730f682 100644
> > --- a/drivers/gpu/drm/bridge/thc63lvd1024.c
> > +++ b/drivers/gpu/drm/bridge/thc63lvd1024.c
> > @@ -34,7 +34,7 @@ struct thc63_dev {
> >  	struct drm_bridge bridge;
> >  	struct drm_bridge *next;
> >
> > -	struct drm_bridge_timings timings;
> > +	bool dual_link;
> >  };
> >
> >  static inline struct thc63_dev *to_thc63(struct drm_bridge *bridge)
> > @@ -62,7 +62,7 @@ static enum drm_mode_status thc63_mode_valid(struct drm_bridge *bridge,
> >  	 * isn't supported by the driver yet, simply derive the limits from the
> >  	 * input mode.
> >  	 */
> > -	if (thc63->timings.dual_link) {
> > +	if (thc63->dual_link) {
> >  		min_freq = 40000;
> >  		max_freq = 150000;
> >  	} else {
> > @@ -157,13 +157,13 @@ static int thc63_parse_dt(struct thc63_dev *thc63)
> >
> >  		if (remote) {
> >  			if (of_device_is_available(remote))
> > -				thc63->timings.dual_link = true;
> > +				thc63->dual_link = true;
> >  			of_node_put(remote);
> >  		}
> >  	}
> >
> >  	dev_dbg(thc63->dev, "operating in %s-link mode\n",
> > -		thc63->timings.dual_link ? "dual" : "single");
> > +		thc63->dual_link ? "dual" : "single");
> >
> >  	return 0;
> >  }
> > @@ -221,7 +221,6 @@ static int thc63_probe(struct platform_device *pdev)
> >  	thc63->bridge.driver_private = thc63;
> >  	thc63->bridge.of_node = pdev->dev.of_node;
> >  	thc63->bridge.funcs = &thc63_bridge_func;
> > -	thc63->bridge.timings = &thc63->timings;
> >
> >  	drm_bridge_add(&thc63->bridge);
> >
> > diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> > index 7616f65..3228018 100644
> > --- a/include/drm/drm_bridge.h
> > +++ b/include/drm/drm_bridge.h
> > @@ -362,14 +362,6 @@ struct drm_bridge_timings {
> >  	 * input signal after the clock edge.
> >  	 */
> >  	u32 hold_time_ps;
> > -	/**
> > -	 * @dual_link:
> > -	 *
> > -	 * True if the bus operates in dual-link mode. The exact meaning is
> > -	 * dependent on the bus type. For LVDS buses, this indicates that even-
> > -	 * and odd-numbered pixels are received on separate links.
> > -	 */
> > -	bool dual_link;
> >  };
> >
> >  /**
> 
> --
> Regards,
> 
> Laurent Pinchart

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH v3 7/8] [HACK] arm64: dts: renesas: draak: Enable LVDS
  2019-11-07 19:57   ` Laurent Pinchart
@ 2019-12-06 15:40     ` Fabrizio Castro
  0 siblings, 0 replies; 32+ messages in thread
From: Fabrizio Castro @ 2019-12-06 15:40 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Rob Herring, Mark Rutland, Simon Horman, Geert Uytterhoeven,
	Magnus Damm, linux-renesas-soc, devicetree, linux-kernel,
	Chris Paterson, Biju Das, Kieran Bingham, Jacopo Mondi, sam

Hello Laurent,

Thank you for the feedback!

> From: linux-renesas-soc-owner@vger.kernel.org <linux-renesas-soc-owner@vger.kernel.org> On Behalf Of Laurent Pinchart
> Sent: 07 November 2019 19:58
> Subject: Re: [PATCH v3 7/8] [HACK] arm64: dts: renesas: draak: Enable LVDS
> 
> Hi Fabrizio,
> 
> Thank you for the patch.
> 
> The subject is wrong, it should be
> 
> [HACK] arm64: dts: renesas: ebisu: Enable LVDS dual-link operation

This sounds like a copy and paste gone really wrong!
Sorry about that. I'll be dropping this patch in v4.

Thanks,
Fab

> 
> On Wed, Aug 28, 2019 at 07:36:41PM +0100, Fabrizio Castro wrote:
> > Enable and connect the second LVDS encoder to the second LVDS input of
> > the THC63LVD1024 for dual-link LVDS operation. This requires changing
> > the default settings of SW45 and SW47 to OFF and ON respectively.
> >
> > This patch is based on Laurent's dual-LVDS work:
> > https://patchwork.kernel.org/patch/10965045/
> >
> > Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> > ---
> > v2->v3:
> > * new patch
> >
> > Geert,
> >
> > no need to review this patch unless they like the idea behind this
> > series.
> >
> > Thanks,
> > Fab
> >
> > ---
> >  arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts | 21 +++++++++++++++++++--
> >  1 file changed, 19 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
> > index b38f9d4..38b9c5a 100644
> > --- a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
> > +++ b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
> > @@ -87,11 +87,20 @@
> >
> >  			port@0 {
> >  				reg = <0>;
> > -				thc63lvd1024_in: endpoint {
> > +				dual-lvds-even-pixels;
> > +				thc63lvd1024_in0: endpoint {
> >  					remote-endpoint = <&lvds0_out>;
> >  				};
> >  			};
> >
> > +			port@1 {
> > +				reg = <1>;
> > +				dual-lvds-odd-pixels;
> > +				thc63lvd1024_in1: endpoint {
> > +					remote-endpoint = <&lvds1_out>;
> > +				};
> > +			};
> > +
> >  			port@2 {
> >  				reg = <2>;
> >  				thc63lvd1024_out: endpoint {
> > @@ -489,7 +498,7 @@
> >  	ports {
> >  		port@1 {
> >  			lvds0_out: endpoint {
> > -				remote-endpoint = <&thc63lvd1024_in>;
> > +				remote-endpoint = <&thc63lvd1024_in0>;
> >  			};
> >  		};
> >  	};
> > @@ -507,6 +516,14 @@
> >  		 <&x13_clk>,
> >  		 <&extal_clk>;
> >  	clock-names = "fck", "dclkin.0", "extal";
> > +
> > +	ports {
> > +		port@1 {
> > +			lvds1_out: endpoint {
> > +				remote-endpoint = <&thc63lvd1024_in1>;
> > +			};
> > +		};
> > +	};
> >  };
> >
> >  &ohci0 {
> > --
> > 2.7.4
> >
> 
> --
> Regards,
> 
> Laurent Pinchart

^ permalink raw reply	[flat|nested] 32+ messages in thread

end of thread, other threads:[~2019-12-06 15:40 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-28 18:36 [PATCH v3 0/8] Add dual-LVDS panel support to EK874 Fabrizio Castro
2019-08-28 18:36 ` [PATCH v3 1/8] dt-bindings: display: Add bindings for LVDS bus-timings Fabrizio Castro
2019-08-29  7:57   ` Geert Uytterhoeven
2019-08-29  9:14     ` Fabrizio Castro
2019-08-29 14:03   ` Rob Herring
2019-08-29 14:38     ` Fabrizio Castro
2019-11-07 18:00       ` Laurent Pinchart
2019-12-06 15:11         ` Fabrizio Castro
2019-12-06 15:10     ` Fabrizio Castro
2019-08-28 18:36 ` [PATCH v3 2/8] dt-bindings: display: Add idk-2121wr binding Fabrizio Castro
2019-11-07 18:12   ` Laurent Pinchart
2019-12-06 15:17     ` Fabrizio Castro
2019-08-28 18:36 ` [PATCH v3 3/8] drm: Add bus timings helper Fabrizio Castro
2019-11-07 19:26   ` Laurent Pinchart
2019-11-07 19:30     ` Daniel Vetter
2019-12-06 15:25       ` Fabrizio Castro
2019-12-06 15:24     ` Fabrizio Castro
2019-08-28 18:36 ` [PATCH v3 4/8] drm: rcar-du: lvds: Add dual-LVDS panels support Fabrizio Castro
2019-11-07 19:50   ` Laurent Pinchart
2019-12-06 15:35     ` Fabrizio Castro
2019-08-28 18:36 ` [PATCH v3 5/8] drm: bridge: thc63: Do not report input bus mode through bridge timings Fabrizio Castro
2019-11-07 19:52   ` Laurent Pinchart
2019-12-06 15:38     ` Fabrizio Castro
2019-08-28 18:36 ` [PATCH v3 6/8] arm64: dts: renesas: Add EK874 board with idk-2121wr display support Fabrizio Castro
2019-11-07 19:55   ` Laurent Pinchart
2019-08-28 18:36 ` [PATCH v3 7/8] [HACK] arm64: dts: renesas: draak: Enable LVDS Fabrizio Castro
2019-11-07 19:57   ` Laurent Pinchart
2019-12-06 15:40     ` Fabrizio Castro
2019-08-28 18:36 ` [PATCH v3 8/8] [HACK] arm64: dts: renesas: draak: Enable LVDS dual-link operation Fabrizio Castro
2019-08-29 15:26 ` [PATCH v3 0/8] Add dual-LVDS panel support to EK874 Rob Herring
2019-09-02 10:01   ` Fabrizio Castro
2019-10-22 16:30 ` Fabrizio Castro

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).