* [PATCH v7 0/4] R-Car DU: Convert LVDS code to bridge driver
@ 2018-03-01 22:05 Laurent Pinchart
2018-03-01 22:05 ` [PATCH v7 1/4] dt-bindings: display: renesas: Add R-Car LVDS encoder DT bindings Laurent Pinchart
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Laurent Pinchart @ 2018-03-01 22:05 UTC (permalink / raw)
To: dri-devel; +Cc: linux-renesas-soc, Frank Rowand, devicetree
Hello,
This patch series addresses a design mistake that dates back from the initial
DU support. Support for the LVDS encoders, which are IP cores separate from
the DU, was bundled in the DU driver. Worse, both the DU and LVDS were
described through a single DT node.
To fix the, patches 1/4 and 2/4 define new DT bindings for the LVDS
encoders, and deprecate their description inside the DU bindings. To retain
backward compatibility with existing DT, patch 3/4 then patch the device tree
at runtime to convert the legacy bindings to the new ones.
With the DT side addressed, patch 4/4 converts the LVDS support code to a
separate bridge driver.
I decided to go for live DT patching in patch 3/4 because implementing
support for both the legacy and new bindings in the driver would have been
very intrusive, and prevented further cleanups. This version relies more
heavily on overlays to avoid touching the internals of the OF core compared to
v2, even if manual fixes to the device tree are still needed.
I plan to send a pull request by the end of the week if no new issue is
discovered.
Compared to v6, patch 3/4 now exists in two variants, to accommodate Frank's
"[PATCH v4 0/4] of: change overlay apply input data from unflattened" patch
series. If that series can't make it to v4.17, patch 3/4 variant 1 will be
used. Otherwise I will go with variant 2.
Compared to v5, I've dropped the OF changeset halpers series as Frank raised
concerns about hidding it in the middle of a driver patch series. I've thus
copied the implementation of of_changeset_add_property_copy() in the driver to
avoid blocking this series. The function arguments are identical, so when the
OF changeset helpers will land it will be very easy to drop the private copy
and use the of_changeset_add_property_copy() helper.
Compared to v4, the patch "of: changeset: Add of_changeset_node_move method"
has been dropped as it's not needed. The patches that update the DT sources to
the new DU and LVDS bindings have been dropped as well to avoid spamming the
lists as they depend on the driver changes going in first to avoid
regressions and haven't been changed.
Compared to v3, this series uses the OF changeset API to update properties
instead of accessing the internals of the property structure. This removes the
local implementation of functions to look up nodes by path and update
properties. In order to do this, I pulled in Pantelis' patch series titled
"[PATCH v2 0/5] of: dynamic: Changesets helpers & fixes" at Rob's request, and
rebased it while taking two small review comments into account.
Rob, I'd like this series to be merged in v4.17. As the changeset helpers are
now a dependency, I'd need you to merge them early (ideally on top of
v4.16-rc1) and provide a stable branch, or get your ack to merge them through
Dave's tree if they don't conflict with what you have and will queue for
v4.17.
This version also drops the small fix to the Porter board device tree that has
been queued for v4.17 already.
Compared to v2, the biggest change is in patch 3/4. Following Rob's and
Frank's reviews it was clear that modifying the unflattened DT structure of
the overlay before applying it wasn't popular. I have thus decided to use one
overlay source per SoC to move as much of the DT changes to the overlay as
possible, and only perform manual modifications (that are still needed as some
of the information is board-specific) on the system DT after applying the
overlay. As a result the overlay is parsed and applied without being modified.
Compared to v1, this series update the r8a7792 and r8a7794 device tree sources
and incorporate review feedback as described by the changelogs of individual
patches.
Laurent Pinchart (4):
dt-bindings: display: renesas: Add R-Car LVDS encoder DT bindings
dt-bindings: display: renesas: Deprecate LVDS support in the DU
bindings
drm: rcar-du: Fix legacy DT to create LVDS encoder nodes
drm: rcar-du: Convert LVDS encoder code to bridge driver
.../bindings/display/bridge/renesas,lvds.txt | 56 +++
.../devicetree/bindings/display/renesas,du.txt | 31 +-
MAINTAINERS | 1 +
drivers/gpu/drm/rcar-du/Kconfig | 6 +-
drivers/gpu/drm/rcar-du/Makefile | 10 +-
drivers/gpu/drm/rcar-du/rcar_du_drv.c | 21 +-
drivers/gpu/drm/rcar-du/rcar_du_drv.h | 5 -
drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 175 +------
drivers/gpu/drm/rcar-du/rcar_du_encoder.h | 12 -
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 14 +-
drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c | 93 ----
drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h | 24 -
drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 238 ----------
drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h | 64 ---
drivers/gpu/drm/rcar-du/rcar_du_of.c | 334 +++++++++++++
drivers/gpu/drm/rcar-du/rcar_du_of.h | 20 +
.../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts | 79 ++++
.../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts | 53 +++
.../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts | 53 +++
.../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts | 53 +++
.../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts | 53 +++
drivers/gpu/drm/rcar-du/rcar_lvds.c | 524 +++++++++++++++++++++
22 files changed, 1282 insertions(+), 637 deletions(-)
create mode 100644 Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h
delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of.c
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of.h
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts
create mode 100644 drivers/gpu/drm/rcar-du/rcar_lvds.c
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v7 1/4] dt-bindings: display: renesas: Add R-Car LVDS encoder DT bindings
2018-03-01 22:05 [PATCH v7 0/4] R-Car DU: Convert LVDS code to bridge driver Laurent Pinchart
@ 2018-03-01 22:05 ` Laurent Pinchart
2018-03-01 22:05 ` [PATCH v7 2/4] dt-bindings: display: renesas: Deprecate LVDS support in the DU bindings Laurent Pinchart
` (2 subsequent siblings)
3 siblings, 0 replies; 9+ messages in thread
From: Laurent Pinchart @ 2018-03-01 22:05 UTC (permalink / raw)
To: dri-devel; +Cc: linux-renesas-soc, devicetree
The Renesas R-Car Gen2 and Gen3 SoCs have internal LVDS encoders. Add
corresponding device tree bindings.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
Changes since v6:
- Fixed typo in SoC name
Changes since v1:
- Move the SoC name before the IP name in compatible strings
- Rename parallel input to parallel RGB input
- Fixed "renesas,r8a7743-lvds" description
- Document the resets property
- Fixed typo
---
.../bindings/display/bridge/renesas,lvds.txt | 56 ++++++++++++++++++++++
MAINTAINERS | 1 +
2 files changed, 57 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
new file mode 100644
index 000000000000..af45ba9d8f90
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
@@ -0,0 +1,56 @@
+Renesas R-Car LVDS Encoder
+==========================
+
+These DT bindings describe the LVDS encoder embedded in the Renesas R-Car
+Gen2, R-Car Gen3 and RZ/G SoCs.
+
+Required properties:
+
+- compatible : Shall contain one of
+ - "renesas,r8a7743-lvds" for R8A7743 (RZ/G1M) compatible LVDS encoders
+ - "renesas,r8a7790-lvds" for R8A7790 (R-Car H2) compatible LVDS encoders
+ - "renesas,r8a7791-lvds" for R8A7791 (R-Car M2-W) compatible LVDS encoders
+ - "renesas,r8a7793-lvds" for R8A7793 (R-Car M2-N) compatible LVDS encoders
+ - "renesas,r8a7795-lvds" for R8A7795 (R-Car H3) compatible LVDS encoders
+ - "renesas,r8a7796-lvds" for R8A7796 (R-Car M3-W) compatible LVDS encoders
+
+- reg: Base address and length for the memory-mapped registers
+- clocks: A phandle + clock-specifier pair for the functional clock
+- resets: A phandle + reset specifier for the module reset
+
+Required nodes:
+
+The LVDS encoder has two video ports. Their connections are modelled using the
+OF graph bindings specified in Documentation/devicetree/bindings/graph.txt.
+
+- Video port 0 corresponds to the parallel RGB input
+- Video port 1 corresponds to the LVDS output
+
+Each port shall have a single endpoint.
+
+
+Example:
+
+ lvds0: lvds@feb90000 {
+ compatible = "renesas,r8a7790-lvds";
+ reg = <0 0xfeb90000 0 0x1c>;
+ clocks = <&cpg CPG_MOD 726>;
+ resets = <&cpg 726>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ lvds0_in: endpoint {
+ remote-endpoint = <&du_out_lvds0>;
+ };
+ };
+ port@1 {
+ reg = <1>;
+ lvds0_out: endpoint {
+ };
+ };
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index 2afba909724c..13c8ec11135a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4744,6 +4744,7 @@ F: drivers/gpu/drm/rcar-du/
F: drivers/gpu/drm/shmobile/
F: include/linux/platform_data/shmob_drm.h
F: Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt
+F: Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
F: Documentation/devicetree/bindings/display/renesas,du.txt
DRM DRIVERS FOR ROCKCHIP
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v7 2/4] dt-bindings: display: renesas: Deprecate LVDS support in the DU bindings
2018-03-01 22:05 [PATCH v7 0/4] R-Car DU: Convert LVDS code to bridge driver Laurent Pinchart
2018-03-01 22:05 ` [PATCH v7 1/4] dt-bindings: display: renesas: Add R-Car LVDS encoder DT bindings Laurent Pinchart
@ 2018-03-01 22:05 ` Laurent Pinchart
2018-03-01 22:05 ` [PATCH v7 3/4 - variant 1] drm: rcar-du: Fix legacy DT to create LVDS encoder nodes Laurent Pinchart
2018-03-01 22:05 ` [PATCH v7 3/4 - variant 2] " Laurent Pinchart
3 siblings, 0 replies; 9+ messages in thread
From: Laurent Pinchart @ 2018-03-01 22:05 UTC (permalink / raw)
To: dri-devel; +Cc: linux-renesas-soc, devicetree
The internal LVDS encoders now have their own DT bindings, representing
them as part of the DU is deprecated.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
Changes since v1:
- Remove the LVDS reg range from the example
- Remove the reg-names property
---
.../devicetree/bindings/display/renesas,du.txt | 31 ++++++++--------------
1 file changed, 11 insertions(+), 20 deletions(-)
diff --git a/Documentation/devicetree/bindings/display/renesas,du.txt b/Documentation/devicetree/bindings/display/renesas,du.txt
index cd48aba3bc8c..e79cf9b0ad38 100644
--- a/Documentation/devicetree/bindings/display/renesas,du.txt
+++ b/Documentation/devicetree/bindings/display/renesas,du.txt
@@ -14,12 +14,7 @@ Required Properties:
- "renesas,du-r8a7795" for R8A7795 (R-Car H3) compatible DU
- "renesas,du-r8a7796" for R8A7796 (R-Car M3-W) compatible DU
- - reg: A list of base address and length of each memory resource, one for
- each entry in the reg-names property.
- - reg-names: Name of the memory resources. The DU requires one memory
- resource for the DU core (named "du") and one memory resource for each
- LVDS encoder (named "lvds.x" with "x" being the LVDS controller numerical
- index).
+ - reg: the memory-mapped I/O registers base address and length
- interrupt-parent: phandle of the parent interrupt controller.
- interrupts: Interrupt specifiers for the DU interrupts.
@@ -29,14 +24,13 @@ Required Properties:
- clock-names: Name of the clocks. This property is model-dependent.
- R8A7779 uses a single functional clock. The clock doesn't need to be
named.
- - All other DU instances use one functional clock per channel and one
- clock per LVDS encoder (if available). The functional clocks must be
- named "du.x" with "x" being the channel numerical index. The LVDS clocks
- must be named "lvds.x" with "x" being the LVDS encoder numerical index.
- - In addition to the functional and encoder clocks, all DU versions also
- support externally supplied pixel clocks. Those clocks are optional.
- When supplied they must be named "dclkin.x" with "x" being the input
- clock numerical index.
+ - All other DU instances use one functional clock per channel The
+ functional clocks must be named "du.x" with "x" being the channel
+ numerical index.
+ - In addition to the functional clocks, all DU versions also support
+ externally supplied pixel clocks. Those clocks are optional. When
+ supplied they must be named "dclkin.x" with "x" being the input clock
+ numerical index.
- vsps: A list of phandle and channel index tuples to the VSPs that handle
the memory interfaces for the DU channels. The phandle identifies the VSP
@@ -69,9 +63,7 @@ Example: R8A7795 (R-Car H3) ES2.0 DU
du: display@feb00000 {
compatible = "renesas,du-r8a7795";
- reg = <0 0xfeb00000 0 0x80000>,
- <0 0xfeb90000 0 0x14>;
- reg-names = "du", "lvds.0";
+ reg = <0 0xfeb00000 0 0x80000>;
interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 269 IRQ_TYPE_LEVEL_HIGH>,
@@ -79,9 +71,8 @@ Example: R8A7795 (R-Car H3) ES2.0 DU
clocks = <&cpg CPG_MOD 724>,
<&cpg CPG_MOD 723>,
<&cpg CPG_MOD 722>,
- <&cpg CPG_MOD 721>,
- <&cpg CPG_MOD 727>;
- clock-names = "du.0", "du.1", "du.2", "du.3", "lvds.0";
+ <&cpg CPG_MOD 721>;
+ clock-names = "du.0", "du.1", "du.2", "du.3";
vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, <&vspd0 1>;
ports {
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v7 3/4 - variant 1] drm: rcar-du: Fix legacy DT to create LVDS encoder nodes
2018-03-01 22:05 [PATCH v7 0/4] R-Car DU: Convert LVDS code to bridge driver Laurent Pinchart
2018-03-01 22:05 ` [PATCH v7 1/4] dt-bindings: display: renesas: Add R-Car LVDS encoder DT bindings Laurent Pinchart
2018-03-01 22:05 ` [PATCH v7 2/4] dt-bindings: display: renesas: Deprecate LVDS support in the DU bindings Laurent Pinchart
@ 2018-03-01 22:05 ` Laurent Pinchart
2018-03-02 0:42 ` Niklas Söderlund
2018-03-02 2:06 ` Frank Rowand
2018-03-01 22:05 ` [PATCH v7 3/4 - variant 2] " Laurent Pinchart
3 siblings, 2 replies; 9+ messages in thread
From: Laurent Pinchart @ 2018-03-01 22:05 UTC (permalink / raw)
To: dri-devel; +Cc: linux-renesas-soc, Frank Rowand, devicetree
The internal LVDS encoders now have their own DT bindings. Before
switching the driver infrastructure to those new bindings, implement
backward-compatibility through live DT patching.
Patching is disabled and will be enabled along with support for the new
DT bindings in the DU driver.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
Changes since v6:
- Don't free data used by the applied overlay
Changes since v5:
- Use a private copy of rcar_du_of_changeset_add_property()
Changes since v3:
- Use the OF changeset API
- Use of_graph_get_endpoint_by_regs()
- Replace hardcoded constants by sizeof()
Changes since v2:
- Update the SPDX headers to use C-style comments in header files
- Removed the manually created __local_fixups__ node
- Perform manual fixups on live DT instead of overlay
Changes since v1:
- Select OF_FLATTREE
- Compile LVDS DT bindings patch code when DRM_RCAR_LVDS is selected
- Update the SPDX headers to use GPL-2.0 instead of GPL-2.0-only
- Turn __dtb_rcar_du_of_lvds_(begin|end) from u8 to char
- Pass void begin and end pointers to rcar_du_of_get_overlay()
- Use of_get_parent() instead of accessing the parent pointer directly
- Find the LVDS endpoints nodes based on the LVDS node instead of the
root of the overlay
- Update to the <soc>-lvds compatible string format
---
drivers/gpu/drm/rcar-du/Kconfig | 2 +
drivers/gpu/drm/rcar-du/Makefile | 7 +-
drivers/gpu/drm/rcar-du/rcar_du_of.c | 334 +++++++++++++++++++++
drivers/gpu/drm/rcar-du/rcar_du_of.h | 20 ++
.../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts | 79 +++++
.../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts | 53 ++++
.../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts | 53 ++++
.../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts | 53 ++++
.../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts | 53 ++++
9 files changed, 653 insertions(+), 1 deletion(-)
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of.c
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of.h
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts
diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
index 5d0b4b7119af..3f83352a7313 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -22,6 +22,8 @@ config DRM_RCAR_LVDS
bool "R-Car DU LVDS Encoder Support"
depends on DRM_RCAR_DU
select DRM_PANEL
+ select OF_FLATTREE
+ select OF_OVERLAY
help
Enable support for the R-Car Display Unit embedded LVDS encoders.
diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
index 0cf5c11030e8..86b337b4be5d 100644
--- a/drivers/gpu/drm/rcar-du/Makefile
+++ b/drivers/gpu/drm/rcar-du/Makefile
@@ -8,7 +8,12 @@ rcar-du-drm-y := rcar_du_crtc.o \
rcar_du_plane.o
rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS) += rcar_du_lvdsenc.o
-
+rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS) += rcar_du_of.o \
+ rcar_du_of_lvds_r8a7790.dtb.o \
+ rcar_du_of_lvds_r8a7791.dtb.o \
+ rcar_du_of_lvds_r8a7793.dtb.o \
+ rcar_du_of_lvds_r8a7795.dtb.o \
+ rcar_du_of_lvds_r8a7796.dtb.o
rcar-du-drm-$(CONFIG_DRM_RCAR_VSP) += rcar_du_vsp.o
obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-drm.o
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of.c b/drivers/gpu/drm/rcar-du/rcar_du_of.c
new file mode 100644
index 000000000000..067278b91caa
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_of.c
@@ -0,0 +1,334 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * rcar_du_of.c - Legacy DT bindings compatibility
+ *
+ * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * Based on work from Jyri Sarha <jsarha@ti.com>
+ * Copyright (C) 2015 Texas Instruments
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
+#include <linux/of_graph.h>
+#include <linux/slab.h>
+
+#include "rcar_du_crtc.h"
+#include "rcar_du_drv.h"
+
+/* -----------------------------------------------------------------------------
+ * Generic Overlay Handling
+ */
+
+struct rcar_du_of_overlay {
+ const char *compatible;
+ void *begin;
+ void *end;
+};
+
+#define RCAR_DU_OF_DTB(type, soc) \
+ extern char __dtb_rcar_du_of_##type##_##soc##_begin[]; \
+ extern char __dtb_rcar_du_of_##type##_##soc##_end[]
+
+#define RCAR_DU_OF_OVERLAY(type, soc) \
+ { \
+ .compatible = "renesas,du-" #soc, \
+ .begin = __dtb_rcar_du_of_##type##_##soc##_begin, \
+ .end = __dtb_rcar_du_of_##type##_##soc##_end, \
+ }
+
+static int __init rcar_du_of_apply_overlay(const struct rcar_du_of_overlay *dtbs,
+ const char *compatible)
+{
+ const struct rcar_du_of_overlay *dtb = NULL;
+ struct device_node *node;
+ unsigned int i;
+ int ovcs_id;
+ void *data;
+ void *mem;
+
+ for (i = 0; dtbs[i].compatible; ++i) {
+ if (!strcmp(dtbs[i].compatible, compatible)) {
+ dtb = &dtbs[i];
+ break;
+ }
+ }
+
+ if (!dtb)
+ return -ENODEV;
+
+ data = kmemdup(dtb->begin, dtb->end - dtb->begin, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ mem = of_fdt_unflatten_tree(data, NULL, &node);
+ if (!mem) {
+ kfree(data);
+ return -ENOMEM;
+ }
+
+ ovcs_id = 0;
+ return of_overlay_apply(node, &ovcs_id);
+}
+
+static int __init rcar_du_of_add_property(struct of_changeset *ocs,
+ struct device_node *np,
+ const char *name, const void *value,
+ int length)
+{
+ struct property *prop;
+ int ret = -ENOMEM;
+
+ prop = kzalloc(sizeof(*prop), GFP_KERNEL);
+ if (!prop)
+ return -ENOMEM;
+
+ prop->name = kstrdup(name, GFP_KERNEL);
+ if (!prop->name)
+ goto out_err;
+
+ prop->value = kmemdup(value, length, GFP_KERNEL);
+ if (!prop->value)
+ goto out_err;
+
+ of_property_set_flag(prop, OF_DYNAMIC);
+
+ prop->length = length;
+
+ ret = of_changeset_add_property(ocs, np, prop);
+ if (!ret)
+ return 0;
+
+out_err:
+ kfree(prop->value);
+ kfree(prop->name);
+ kfree(prop);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * LVDS Overlays
+ */
+
+RCAR_DU_OF_DTB(lvds, r8a7790);
+RCAR_DU_OF_DTB(lvds, r8a7791);
+RCAR_DU_OF_DTB(lvds, r8a7793);
+RCAR_DU_OF_DTB(lvds, r8a7795);
+RCAR_DU_OF_DTB(lvds, r8a7796);
+
+static const struct rcar_du_of_overlay rcar_du_lvds_overlays[] __initconst = {
+ RCAR_DU_OF_OVERLAY(lvds, r8a7790),
+ RCAR_DU_OF_OVERLAY(lvds, r8a7791),
+ RCAR_DU_OF_OVERLAY(lvds, r8a7793),
+ RCAR_DU_OF_OVERLAY(lvds, r8a7795),
+ RCAR_DU_OF_OVERLAY(lvds, r8a7796),
+ { /* Sentinel */ },
+};
+
+static struct of_changeset rcar_du_lvds_changeset;
+
+static void __init rcar_du_of_lvds_patch_one(struct device_node *lvds,
+ const struct of_phandle_args *clk,
+ struct device_node *local,
+ struct device_node *remote)
+{
+ unsigned int psize;
+ unsigned int i;
+ __be32 value[4];
+ int ret;
+
+ /*
+ * Set the LVDS clocks property. This can't be performed by the overlay
+ * as the structure of the clock specifier has changed over time, and we
+ * don't know at compile time which binding version the system we will
+ * run on uses.
+ */
+ if (clk->args_count >= ARRAY_SIZE(value) - 1)
+ return;
+
+ of_changeset_init(&rcar_du_lvds_changeset);
+
+ value[0] = cpu_to_be32(clk->np->phandle);
+ for (i = 0; i < clk->args_count; ++i)
+ value[i + 1] = cpu_to_be32(clk->args[i]);
+
+ psize = (clk->args_count + 1) * 4;
+ ret = rcar_du_of_add_property(&rcar_du_lvds_changeset, lvds,
+ "clocks", value, psize);
+ if (ret < 0)
+ goto done;
+
+ /*
+ * Insert the node in the OF graph: patch the LVDS ports remote-endpoint
+ * properties to point to the endpoints of the sibling nodes in the
+ * graph. This can't be performed by the overlay: on the input side the
+ * overlay would contain a phandle for the DU LVDS output port that
+ * would clash with the system DT, and on the output side the connection
+ * is board-specific.
+ */
+ value[0] = cpu_to_be32(local->phandle);
+ value[1] = cpu_to_be32(remote->phandle);
+
+ for (i = 0; i < 2; ++i) {
+ struct device_node *endpoint;
+
+ endpoint = of_graph_get_endpoint_by_regs(lvds, i, 0);
+ if (!endpoint) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = rcar_du_of_add_property(&rcar_du_lvds_changeset,
+ endpoint, "remote-endpoint",
+ &value[i], sizeof(value[i]));
+ of_node_put(endpoint);
+ if (ret < 0)
+ goto done;
+ }
+
+ ret = of_changeset_apply(&rcar_du_lvds_changeset);
+
+done:
+ if (ret < 0)
+ of_changeset_destroy(&rcar_du_lvds_changeset);
+}
+
+struct lvds_of_data {
+ struct resource res;
+ struct of_phandle_args clkspec;
+ struct device_node *local;
+ struct device_node *remote;
+};
+
+static void __init rcar_du_of_lvds_patch(const struct of_device_id *of_ids)
+{
+ const struct rcar_du_device_info *info;
+ const struct of_device_id *match;
+ struct lvds_of_data lvds_data[2] = { };
+ struct device_node *lvds_node;
+ struct device_node *soc_node;
+ struct device_node *du_node;
+ char compatible[21];
+ const char *soc_name;
+ unsigned int i;
+ int ret;
+
+ /* Get the DU node and exit if not present or disabled. */
+ du_node = of_find_matching_node_and_match(NULL, of_ids, &match);
+ if (!du_node || !of_device_is_available(du_node)) {
+ of_node_put(du_node);
+ return;
+ }
+
+ info = match->data;
+ soc_node = of_get_parent(du_node);
+
+ if (WARN_ON(info->num_lvds > ARRAY_SIZE(lvds_data)))
+ goto done;
+
+ /*
+ * Skip if the LVDS nodes already exists.
+ *
+ * The nodes are searched based on the compatible string, which we
+ * construct from the SoC name found in the DU compatible string. As a
+ * match has been found we know the compatible string matches the
+ * expected format and can thus skip some of the string manipulation
+ * normal safety checks.
+ */
+ soc_name = strchr(match->compatible, '-') + 1;
+ sprintf(compatible, "renesas,%s-lvds", soc_name);
+ lvds_node = of_find_compatible_node(NULL, NULL, compatible);
+ if (lvds_node) {
+ of_node_put(lvds_node);
+ return;
+ }
+
+ /*
+ * Parse the DU node and store the register specifier, the clock
+ * specifier and the local and remote endpoint of the LVDS link for
+ * later use.
+ */
+ for (i = 0; i < info->num_lvds; ++i) {
+ struct lvds_of_data *lvds = &lvds_data[i];
+ unsigned int port;
+ char name[7];
+ int index;
+
+ sprintf(name, "lvds.%u", i);
+ index = of_property_match_string(du_node, "clock-names", name);
+ if (index < 0)
+ continue;
+
+ ret = of_parse_phandle_with_args(du_node, "clocks",
+ "#clock-cells", index,
+ &lvds->clkspec);
+ if (ret < 0)
+ continue;
+
+ port = info->routes[RCAR_DU_OUTPUT_LVDS0 + i].port;
+
+ lvds->local = of_graph_get_endpoint_by_regs(du_node, port, 0);
+ if (!lvds->local)
+ continue;
+
+ lvds->remote = of_graph_get_remote_endpoint(lvds->local);
+ if (!lvds->remote)
+ continue;
+
+ index = of_property_match_string(du_node, "reg-names", name);
+ if (index < 0)
+ continue;
+
+ of_address_to_resource(du_node, index, &lvds->res);
+ }
+
+ /* Parse and apply the overlay. This will resolve phandles. */
+ ret = rcar_du_of_apply_overlay(rcar_du_lvds_overlays,
+ match->compatible);
+ if (ret < 0)
+ goto done;
+
+ /* Patch the newly created LVDS encoder nodes. */
+ for_each_child_of_node(soc_node, lvds_node) {
+ struct resource res;
+
+ if (!of_device_is_compatible(lvds_node, compatible))
+ continue;
+
+ /* Locate the lvds_data entry based on the resource start. */
+ ret = of_address_to_resource(lvds_node, 0, &res);
+ if (ret < 0)
+ continue;
+
+ for (i = 0; i < ARRAY_SIZE(lvds_data); ++i) {
+ if (lvds_data[i].res.start == res.start)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(lvds_data))
+ continue;
+
+ /* Patch the LVDS encoder. */
+ rcar_du_of_lvds_patch_one(lvds_node, &lvds_data[i].clkspec,
+ lvds_data[i].local,
+ lvds_data[i].remote);
+ }
+
+done:
+ for (i = 0; i < info->num_lvds; ++i) {
+ of_node_put(lvds_data[i].clkspec.np);
+ of_node_put(lvds_data[i].local);
+ of_node_put(lvds_data[i].remote);
+ }
+
+ of_node_put(soc_node);
+ of_node_put(du_node);
+}
+
+void __init rcar_du_of_init(const struct of_device_id *of_ids)
+{
+ rcar_du_of_lvds_patch(of_ids);
+}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of.h b/drivers/gpu/drm/rcar-du/rcar_du_of.h
new file mode 100644
index 000000000000..c2e65a727e91
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_of.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * rcar_du_of.h - Legacy DT bindings compatibility
+ *
+ * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ */
+#ifndef __RCAR_DU_OF_H__
+#define __RCAR_DU_OF_H__
+
+#include <linux/init.h>
+
+struct of_device_id;
+
+#ifdef CONFIG_DRM_RCAR_LVDS
+void __init rcar_du_of_init(const struct of_device_id *of_ids);
+#else
+static inline void rcar_du_of_init(const struct of_device_id *of_ids) { }
+#endif /* CONFIG_DRM_RCAR_LVDS */
+
+#endif /* __RCAR_DU_OF_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts
new file mode 100644
index 000000000000..f118a6ae7782
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * rcar_du_of_lvds_r8a7790.dts - Legacy LVDS DT bindings conversion for R8A7790
+ *
+ * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * Based on work from Jyri Sarha <jsarha@ti.com>
+ * Copyright (C) 2015 Texas Instruments
+ */
+
+/dts-v1/;
+/plugin/;
+/ {
+ fragment@0 {
+ target-path = "/";
+ __overlay__ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ lvds@feb90000 {
+ compatible = "renesas,r8a7790-lvds";
+ reg = <0 0xfeb90000 0 0x1c>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ lvds0_input: endpoint {
+ };
+ };
+ port@1 {
+ reg = <1>;
+ lvds0_out: endpoint {
+ };
+ };
+ };
+ };
+
+ lvds@feb94000 {
+ compatible = "renesas,r8a7790-lvds";
+ reg = <0 0xfeb94000 0 0x1c>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ lvds1_input: endpoint {
+ };
+ };
+ port@1 {
+ reg = <1>;
+ lvds1_out: endpoint {
+ };
+ };
+ };
+ };
+ };
+ };
+
+ fragment@1 {
+ target-path = "/display@feb00000/ports";
+ __overlay__ {
+ port@1 {
+ endpoint {
+ remote-endpoint = <&lvds0_input>;
+ };
+ };
+ port@2 {
+ endpoint {
+ remote-endpoint = <&lvds1_input>;
+ };
+ };
+ };
+ };
+};
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts
new file mode 100644
index 000000000000..7d865727928c
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * rcar_du_of_lvds_r8a7791.dts - Legacy LVDS DT bindings conversion for R8A7791
+ *
+ * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * Based on work from Jyri Sarha <jsarha@ti.com>
+ * Copyright (C) 2015 Texas Instruments
+ */
+
+/dts-v1/;
+/plugin/;
+/ {
+ fragment@0 {
+ target-path = "/";
+ __overlay__ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ lvds@feb90000 {
+ compatible = "renesas,r8a7791-lvds";
+ reg = <0 0xfeb90000 0 0x1c>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ lvds0_input: endpoint {
+ };
+ };
+ port@1 {
+ reg = <1>;
+ lvds0_out: endpoint {
+ };
+ };
+ };
+ };
+ };
+ };
+
+ fragment@1 {
+ target-path = "/display@feb00000/ports";
+ __overlay__ {
+ port@1 {
+ endpoint {
+ remote-endpoint = <&lvds0_input>;
+ };
+ };
+ };
+ };
+};
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts
new file mode 100644
index 000000000000..bb263711834d
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * rcar_du_of_lvds_r8a7793.dts - Legacy LVDS DT bindings conversion for R8A7793
+ *
+ * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * Based on work from Jyri Sarha <jsarha@ti.com>
+ * Copyright (C) 2015 Texas Instruments
+ */
+
+/dts-v1/;
+/plugin/;
+/ {
+ fragment@0 {
+ target-path = "/";
+ __overlay__ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ lvds@feb90000 {
+ compatible = "renesas,r8a7793-lvds";
+ reg = <0 0xfeb90000 0 0x1c>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ lvds0_input: endpoint {
+ };
+ };
+ port@1 {
+ reg = <1>;
+ lvds0_out: endpoint {
+ };
+ };
+ };
+ };
+ };
+ };
+
+ fragment@1 {
+ target-path = "/display@feb00000/ports";
+ __overlay__ {
+ port@1 {
+ endpoint {
+ remote-endpoint = <&lvds0_input>;
+ };
+ };
+ };
+ };
+};
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts
new file mode 100644
index 000000000000..9bbf7c9e5ce4
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * rcar_du_of_lvds_r8a7795.dts - Legacy LVDS DT bindings conversion for R8A7795
+ *
+ * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * Based on work from Jyri Sarha <jsarha@ti.com>
+ * Copyright (C) 2015 Texas Instruments
+ */
+
+/dts-v1/;
+/plugin/;
+/ {
+ fragment@0 {
+ target-path = "/soc";
+ __overlay__ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ lvds@feb90000 {
+ compatible = "renesas,r8a7795-lvds";
+ reg = <0 0xfeb90000 0 0x14>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ lvds0_input: endpoint {
+ };
+ };
+ port@1 {
+ reg = <1>;
+ lvds0_out: endpoint {
+ };
+ };
+ };
+ };
+ };
+ };
+
+ fragment@1 {
+ target-path = "/soc/display@feb00000/ports";
+ __overlay__ {
+ port@3 {
+ endpoint {
+ remote-endpoint = <&lvds0_input>;
+ };
+ };
+ };
+ };
+};
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts
new file mode 100644
index 000000000000..d16f3e9e08ab
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * rcar_du_of_lvds_r8a7796.dts - Legacy LVDS DT bindings conversion for R8A7796
+ *
+ * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * Based on work from Jyri Sarha <jsarha@ti.com>
+ * Copyright (C) 2015 Texas Instruments
+ */
+
+/dts-v1/;
+/plugin/;
+/ {
+ fragment@0 {
+ target-path = "/soc";
+ __overlay__ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ lvds@feb90000 {
+ compatible = "renesas,r8a7796-lvds";
+ reg = <0 0xfeb90000 0 0x14>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ lvds0_input: endpoint {
+ };
+ };
+ port@1 {
+ reg = <1>;
+ lvds0_out: endpoint {
+ };
+ };
+ };
+ };
+ };
+ };
+
+ fragment@1 {
+ target-path = "/soc/display@feb00000/ports";
+ __overlay__ {
+ port@3 {
+ endpoint {
+ remote-endpoint = <&lvds0_input>;
+ };
+ };
+ };
+ };
+};
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v7 3/4 - variant 2] drm: rcar-du: Fix legacy DT to create LVDS encoder nodes
2018-03-01 22:05 [PATCH v7 0/4] R-Car DU: Convert LVDS code to bridge driver Laurent Pinchart
` (2 preceding siblings ...)
2018-03-01 22:05 ` [PATCH v7 3/4 - variant 1] drm: rcar-du: Fix legacy DT to create LVDS encoder nodes Laurent Pinchart
@ 2018-03-01 22:05 ` Laurent Pinchart
2018-03-02 2:17 ` Frank Rowand
3 siblings, 1 reply; 9+ messages in thread
From: Laurent Pinchart @ 2018-03-01 22:05 UTC (permalink / raw)
To: dri-devel; +Cc: linux-renesas-soc, Frank Rowand, devicetree
The internal LVDS encoders now have their own DT bindings. Before
switching the driver infrastructure to those new bindings, implement
backward-compatibility through live DT patching.
Patching is disabled and will be enabled along with support for the new
DT bindings in the DU driver.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
Changes since v6:
- Use of_overlay_fdt_apply()
Changes since v5:
- Use a private copy of rcar_du_of_changeset_add_property()
Changes since v3:
- Use the OF changeset API
- Use of_graph_get_endpoint_by_regs()
- Replace hardcoded constants by sizeof()
Changes since v2:
- Update the SPDX headers to use C-style comments in header files
- Removed the manually created __local_fixups__ node
- Perform manual fixups on live DT instead of overlay
Changes since v1:
- Select OF_FLATTREE
- Compile LVDS DT bindings patch code when DRM_RCAR_LVDS is selected
- Update the SPDX headers to use GPL-2.0 instead of GPL-2.0-only
- Turn __dtb_rcar_du_of_lvds_(begin|end) from u8 to char
- Pass void begin and end pointers to rcar_du_of_get_overlay()
- Use of_get_parent() instead of accessing the parent pointer directly
- Find the LVDS endpoints nodes based on the LVDS node instead of the
root of the overlay
- Update to the <soc>-lvds compatible string format
---
drivers/gpu/drm/rcar-du/Kconfig | 2 +
drivers/gpu/drm/rcar-du/Makefile | 7 +-
drivers/gpu/drm/rcar-du/rcar_du_of.c | 321 +++++++++++++++++++++
drivers/gpu/drm/rcar-du/rcar_du_of.h | 20 ++
.../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts | 79 +++++
.../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts | 53 ++++
.../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts | 53 ++++
.../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts | 53 ++++
.../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts | 53 ++++
9 files changed, 640 insertions(+), 1 deletion(-)
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of.c
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of.h
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts
create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts
diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
index 5d0b4b7119af..3f83352a7313 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -22,6 +22,8 @@ config DRM_RCAR_LVDS
bool "R-Car DU LVDS Encoder Support"
depends on DRM_RCAR_DU
select DRM_PANEL
+ select OF_FLATTREE
+ select OF_OVERLAY
help
Enable support for the R-Car Display Unit embedded LVDS encoders.
diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
index 0cf5c11030e8..86b337b4be5d 100644
--- a/drivers/gpu/drm/rcar-du/Makefile
+++ b/drivers/gpu/drm/rcar-du/Makefile
@@ -8,7 +8,12 @@ rcar-du-drm-y := rcar_du_crtc.o \
rcar_du_plane.o
rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS) += rcar_du_lvdsenc.o
-
+rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS) += rcar_du_of.o \
+ rcar_du_of_lvds_r8a7790.dtb.o \
+ rcar_du_of_lvds_r8a7791.dtb.o \
+ rcar_du_of_lvds_r8a7793.dtb.o \
+ rcar_du_of_lvds_r8a7795.dtb.o \
+ rcar_du_of_lvds_r8a7796.dtb.o
rcar-du-drm-$(CONFIG_DRM_RCAR_VSP) += rcar_du_vsp.o
obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-drm.o
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of.c b/drivers/gpu/drm/rcar-du/rcar_du_of.c
new file mode 100644
index 000000000000..4e3376c64dfd
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_of.c
@@ -0,0 +1,321 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * rcar_du_of.c - Legacy DT bindings compatibility
+ *
+ * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * Based on work from Jyri Sarha <jsarha@ti.com>
+ * Copyright (C) 2015 Texas Instruments
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
+#include <linux/of_graph.h>
+#include <linux/slab.h>
+
+#include "rcar_du_crtc.h"
+#include "rcar_du_drv.h"
+
+/* -----------------------------------------------------------------------------
+ * Generic Overlay Handling
+ */
+
+struct rcar_du_of_overlay {
+ const char *compatible;
+ void *begin;
+ void *end;
+};
+
+#define RCAR_DU_OF_DTB(type, soc) \
+ extern char __dtb_rcar_du_of_##type##_##soc##_begin[]; \
+ extern char __dtb_rcar_du_of_##type##_##soc##_end[]
+
+#define RCAR_DU_OF_OVERLAY(type, soc) \
+ { \
+ .compatible = "renesas,du-" #soc, \
+ .begin = __dtb_rcar_du_of_##type##_##soc##_begin, \
+ .end = __dtb_rcar_du_of_##type##_##soc##_end, \
+ }
+
+static int __init rcar_du_of_apply_overlay(const struct rcar_du_of_overlay *dtbs,
+ const char *compatible)
+{
+ const struct rcar_du_of_overlay *dtb = NULL;
+ unsigned int i;
+ int ovcs_id;
+
+ for (i = 0; dtbs[i].compatible; ++i) {
+ if (!strcmp(dtbs[i].compatible, compatible)) {
+ dtb = &dtbs[i];
+ break;
+ }
+ }
+
+ if (!dtb)
+ return -ENODEV;
+
+ ovcs_id = 0;
+ return of_overlay_fdt_apply(dtb->begin, &ovcs_id);
+}
+
+static int __init rcar_du_of_add_property(struct of_changeset *ocs,
+ struct device_node *np,
+ const char *name, const void *value,
+ int length)
+{
+ struct property *prop;
+ int ret = -ENOMEM;
+
+ prop = kzalloc(sizeof(*prop), GFP_KERNEL);
+ if (!prop)
+ return -ENOMEM;
+
+ prop->name = kstrdup(name, GFP_KERNEL);
+ if (!prop->name)
+ goto out_err;
+
+ prop->value = kmemdup(value, length, GFP_KERNEL);
+ if (!prop->value)
+ goto out_err;
+
+ of_property_set_flag(prop, OF_DYNAMIC);
+
+ prop->length = length;
+
+ ret = of_changeset_add_property(ocs, np, prop);
+ if (!ret)
+ return 0;
+
+out_err:
+ kfree(prop->value);
+ kfree(prop->name);
+ kfree(prop);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * LVDS Overlays
+ */
+
+RCAR_DU_OF_DTB(lvds, r8a7790);
+RCAR_DU_OF_DTB(lvds, r8a7791);
+RCAR_DU_OF_DTB(lvds, r8a7793);
+RCAR_DU_OF_DTB(lvds, r8a7795);
+RCAR_DU_OF_DTB(lvds, r8a7796);
+
+static const struct rcar_du_of_overlay rcar_du_lvds_overlays[] __initconst = {
+ RCAR_DU_OF_OVERLAY(lvds, r8a7790),
+ RCAR_DU_OF_OVERLAY(lvds, r8a7791),
+ RCAR_DU_OF_OVERLAY(lvds, r8a7793),
+ RCAR_DU_OF_OVERLAY(lvds, r8a7795),
+ RCAR_DU_OF_OVERLAY(lvds, r8a7796),
+ { /* Sentinel */ },
+};
+
+static struct of_changeset rcar_du_lvds_changeset;
+
+static void __init rcar_du_of_lvds_patch_one(struct device_node *lvds,
+ const struct of_phandle_args *clk,
+ struct device_node *local,
+ struct device_node *remote)
+{
+ unsigned int psize;
+ unsigned int i;
+ __be32 value[4];
+ int ret;
+
+ /*
+ * Set the LVDS clocks property. This can't be performed by the overlay
+ * as the structure of the clock specifier has changed over time, and we
+ * don't know at compile time which binding version the system we will
+ * run on uses.
+ */
+ if (clk->args_count >= ARRAY_SIZE(value) - 1)
+ return;
+
+ of_changeset_init(&rcar_du_lvds_changeset);
+
+ value[0] = cpu_to_be32(clk->np->phandle);
+ for (i = 0; i < clk->args_count; ++i)
+ value[i + 1] = cpu_to_be32(clk->args[i]);
+
+ psize = (clk->args_count + 1) * 4;
+ ret = rcar_du_of_add_property(&rcar_du_lvds_changeset, lvds,
+ "clocks", value, psize);
+ if (ret < 0)
+ goto done;
+
+ /*
+ * Insert the node in the OF graph: patch the LVDS ports remote-endpoint
+ * properties to point to the endpoints of the sibling nodes in the
+ * graph. This can't be performed by the overlay: on the input side the
+ * overlay would contain a phandle for the DU LVDS output port that
+ * would clash with the system DT, and on the output side the connection
+ * is board-specific.
+ */
+ value[0] = cpu_to_be32(local->phandle);
+ value[1] = cpu_to_be32(remote->phandle);
+
+ for (i = 0; i < 2; ++i) {
+ struct device_node *endpoint;
+
+ endpoint = of_graph_get_endpoint_by_regs(lvds, i, 0);
+ if (!endpoint) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = rcar_du_of_add_property(&rcar_du_lvds_changeset,
+ endpoint, "remote-endpoint",
+ &value[i], sizeof(value[i]));
+ of_node_put(endpoint);
+ if (ret < 0)
+ goto done;
+ }
+
+ ret = of_changeset_apply(&rcar_du_lvds_changeset);
+
+done:
+ if (ret < 0)
+ of_changeset_destroy(&rcar_du_lvds_changeset);
+}
+
+struct lvds_of_data {
+ struct resource res;
+ struct of_phandle_args clkspec;
+ struct device_node *local;
+ struct device_node *remote;
+};
+
+static void __init rcar_du_of_lvds_patch(const struct of_device_id *of_ids)
+{
+ const struct rcar_du_device_info *info;
+ const struct of_device_id *match;
+ struct lvds_of_data lvds_data[2] = { };
+ struct device_node *lvds_node;
+ struct device_node *soc_node;
+ struct device_node *du_node;
+ char compatible[21];
+ const char *soc_name;
+ unsigned int i;
+ int ret;
+
+ /* Get the DU node and exit if not present or disabled. */
+ du_node = of_find_matching_node_and_match(NULL, of_ids, &match);
+ if (!du_node || !of_device_is_available(du_node)) {
+ of_node_put(du_node);
+ return;
+ }
+
+ info = match->data;
+ soc_node = of_get_parent(du_node);
+
+ if (WARN_ON(info->num_lvds > ARRAY_SIZE(lvds_data)))
+ goto done;
+
+ /*
+ * Skip if the LVDS nodes already exists.
+ *
+ * The nodes are searched based on the compatible string, which we
+ * construct from the SoC name found in the DU compatible string. As a
+ * match has been found we know the compatible string matches the
+ * expected format and can thus skip some of the string manipulation
+ * normal safety checks.
+ */
+ soc_name = strchr(match->compatible, '-') + 1;
+ sprintf(compatible, "renesas,%s-lvds", soc_name);
+ lvds_node = of_find_compatible_node(NULL, NULL, compatible);
+ if (lvds_node) {
+ of_node_put(lvds_node);
+ return;
+ }
+
+ /*
+ * Parse the DU node and store the register specifier, the clock
+ * specifier and the local and remote endpoint of the LVDS link for
+ * later use.
+ */
+ for (i = 0; i < info->num_lvds; ++i) {
+ struct lvds_of_data *lvds = &lvds_data[i];
+ unsigned int port;
+ char name[7];
+ int index;
+
+ sprintf(name, "lvds.%u", i);
+ index = of_property_match_string(du_node, "clock-names", name);
+ if (index < 0)
+ continue;
+
+ ret = of_parse_phandle_with_args(du_node, "clocks",
+ "#clock-cells", index,
+ &lvds->clkspec);
+ if (ret < 0)
+ continue;
+
+ port = info->routes[RCAR_DU_OUTPUT_LVDS0 + i].port;
+
+ lvds->local = of_graph_get_endpoint_by_regs(du_node, port, 0);
+ if (!lvds->local)
+ continue;
+
+ lvds->remote = of_graph_get_remote_endpoint(lvds->local);
+ if (!lvds->remote)
+ continue;
+
+ index = of_property_match_string(du_node, "reg-names", name);
+ if (index < 0)
+ continue;
+
+ of_address_to_resource(du_node, index, &lvds->res);
+ }
+
+ /* Parse and apply the overlay. This will resolve phandles. */
+ ret = rcar_du_of_apply_overlay(rcar_du_lvds_overlays,
+ match->compatible);
+ if (ret < 0)
+ goto done;
+
+ /* Patch the newly created LVDS encoder nodes. */
+ for_each_child_of_node(soc_node, lvds_node) {
+ struct resource res;
+
+ if (!of_device_is_compatible(lvds_node, compatible))
+ continue;
+
+ /* Locate the lvds_data entry based on the resource start. */
+ ret = of_address_to_resource(lvds_node, 0, &res);
+ if (ret < 0)
+ continue;
+
+ for (i = 0; i < ARRAY_SIZE(lvds_data); ++i) {
+ if (lvds_data[i].res.start == res.start)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(lvds_data))
+ continue;
+
+ /* Patch the LVDS encoder. */
+ rcar_du_of_lvds_patch_one(lvds_node, &lvds_data[i].clkspec,
+ lvds_data[i].local,
+ lvds_data[i].remote);
+ }
+
+done:
+ for (i = 0; i < info->num_lvds; ++i) {
+ of_node_put(lvds_data[i].clkspec.np);
+ of_node_put(lvds_data[i].local);
+ of_node_put(lvds_data[i].remote);
+ }
+
+ of_node_put(soc_node);
+ of_node_put(du_node);
+}
+
+void __init rcar_du_of_init(const struct of_device_id *of_ids)
+{
+ rcar_du_of_lvds_patch(of_ids);
+}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of.h b/drivers/gpu/drm/rcar-du/rcar_du_of.h
new file mode 100644
index 000000000000..c2e65a727e91
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_of.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * rcar_du_of.h - Legacy DT bindings compatibility
+ *
+ * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ */
+#ifndef __RCAR_DU_OF_H__
+#define __RCAR_DU_OF_H__
+
+#include <linux/init.h>
+
+struct of_device_id;
+
+#ifdef CONFIG_DRM_RCAR_LVDS
+void __init rcar_du_of_init(const struct of_device_id *of_ids);
+#else
+static inline void rcar_du_of_init(const struct of_device_id *of_ids) { }
+#endif /* CONFIG_DRM_RCAR_LVDS */
+
+#endif /* __RCAR_DU_OF_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts
new file mode 100644
index 000000000000..f118a6ae7782
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * rcar_du_of_lvds_r8a7790.dts - Legacy LVDS DT bindings conversion for R8A7790
+ *
+ * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * Based on work from Jyri Sarha <jsarha@ti.com>
+ * Copyright (C) 2015 Texas Instruments
+ */
+
+/dts-v1/;
+/plugin/;
+/ {
+ fragment@0 {
+ target-path = "/";
+ __overlay__ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ lvds@feb90000 {
+ compatible = "renesas,r8a7790-lvds";
+ reg = <0 0xfeb90000 0 0x1c>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ lvds0_input: endpoint {
+ };
+ };
+ port@1 {
+ reg = <1>;
+ lvds0_out: endpoint {
+ };
+ };
+ };
+ };
+
+ lvds@feb94000 {
+ compatible = "renesas,r8a7790-lvds";
+ reg = <0 0xfeb94000 0 0x1c>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ lvds1_input: endpoint {
+ };
+ };
+ port@1 {
+ reg = <1>;
+ lvds1_out: endpoint {
+ };
+ };
+ };
+ };
+ };
+ };
+
+ fragment@1 {
+ target-path = "/display@feb00000/ports";
+ __overlay__ {
+ port@1 {
+ endpoint {
+ remote-endpoint = <&lvds0_input>;
+ };
+ };
+ port@2 {
+ endpoint {
+ remote-endpoint = <&lvds1_input>;
+ };
+ };
+ };
+ };
+};
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts
new file mode 100644
index 000000000000..7d865727928c
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * rcar_du_of_lvds_r8a7791.dts - Legacy LVDS DT bindings conversion for R8A7791
+ *
+ * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * Based on work from Jyri Sarha <jsarha@ti.com>
+ * Copyright (C) 2015 Texas Instruments
+ */
+
+/dts-v1/;
+/plugin/;
+/ {
+ fragment@0 {
+ target-path = "/";
+ __overlay__ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ lvds@feb90000 {
+ compatible = "renesas,r8a7791-lvds";
+ reg = <0 0xfeb90000 0 0x1c>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ lvds0_input: endpoint {
+ };
+ };
+ port@1 {
+ reg = <1>;
+ lvds0_out: endpoint {
+ };
+ };
+ };
+ };
+ };
+ };
+
+ fragment@1 {
+ target-path = "/display@feb00000/ports";
+ __overlay__ {
+ port@1 {
+ endpoint {
+ remote-endpoint = <&lvds0_input>;
+ };
+ };
+ };
+ };
+};
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts
new file mode 100644
index 000000000000..bb263711834d
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * rcar_du_of_lvds_r8a7793.dts - Legacy LVDS DT bindings conversion for R8A7793
+ *
+ * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * Based on work from Jyri Sarha <jsarha@ti.com>
+ * Copyright (C) 2015 Texas Instruments
+ */
+
+/dts-v1/;
+/plugin/;
+/ {
+ fragment@0 {
+ target-path = "/";
+ __overlay__ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ lvds@feb90000 {
+ compatible = "renesas,r8a7793-lvds";
+ reg = <0 0xfeb90000 0 0x1c>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ lvds0_input: endpoint {
+ };
+ };
+ port@1 {
+ reg = <1>;
+ lvds0_out: endpoint {
+ };
+ };
+ };
+ };
+ };
+ };
+
+ fragment@1 {
+ target-path = "/display@feb00000/ports";
+ __overlay__ {
+ port@1 {
+ endpoint {
+ remote-endpoint = <&lvds0_input>;
+ };
+ };
+ };
+ };
+};
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts
new file mode 100644
index 000000000000..9bbf7c9e5ce4
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * rcar_du_of_lvds_r8a7795.dts - Legacy LVDS DT bindings conversion for R8A7795
+ *
+ * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * Based on work from Jyri Sarha <jsarha@ti.com>
+ * Copyright (C) 2015 Texas Instruments
+ */
+
+/dts-v1/;
+/plugin/;
+/ {
+ fragment@0 {
+ target-path = "/soc";
+ __overlay__ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ lvds@feb90000 {
+ compatible = "renesas,r8a7795-lvds";
+ reg = <0 0xfeb90000 0 0x14>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ lvds0_input: endpoint {
+ };
+ };
+ port@1 {
+ reg = <1>;
+ lvds0_out: endpoint {
+ };
+ };
+ };
+ };
+ };
+ };
+
+ fragment@1 {
+ target-path = "/soc/display@feb00000/ports";
+ __overlay__ {
+ port@3 {
+ endpoint {
+ remote-endpoint = <&lvds0_input>;
+ };
+ };
+ };
+ };
+};
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts
new file mode 100644
index 000000000000..d16f3e9e08ab
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * rcar_du_of_lvds_r8a7796.dts - Legacy LVDS DT bindings conversion for R8A7796
+ *
+ * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * Based on work from Jyri Sarha <jsarha@ti.com>
+ * Copyright (C) 2015 Texas Instruments
+ */
+
+/dts-v1/;
+/plugin/;
+/ {
+ fragment@0 {
+ target-path = "/soc";
+ __overlay__ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ lvds@feb90000 {
+ compatible = "renesas,r8a7796-lvds";
+ reg = <0 0xfeb90000 0 0x14>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ lvds0_input: endpoint {
+ };
+ };
+ port@1 {
+ reg = <1>;
+ lvds0_out: endpoint {
+ };
+ };
+ };
+ };
+ };
+ };
+
+ fragment@1 {
+ target-path = "/soc/display@feb00000/ports";
+ __overlay__ {
+ port@3 {
+ endpoint {
+ remote-endpoint = <&lvds0_input>;
+ };
+ };
+ };
+ };
+};
--
Regards,
Laurent Pinchart
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v7 3/4 - variant 1] drm: rcar-du: Fix legacy DT to create LVDS encoder nodes
2018-03-01 22:05 ` [PATCH v7 3/4 - variant 1] drm: rcar-du: Fix legacy DT to create LVDS encoder nodes Laurent Pinchart
@ 2018-03-02 0:42 ` Niklas Söderlund
2018-03-02 13:02 ` Laurent Pinchart
2018-03-02 2:06 ` Frank Rowand
1 sibling, 1 reply; 9+ messages in thread
From: Niklas Söderlund @ 2018-03-02 0:42 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: dri-devel, linux-renesas-soc, Frank Rowand, devicetree
Hi Laurent,
Thanks for your patch,
All comments in this mail also applies to variant 2 of this patch as the
difference between them are so small.
First I got a question about your usage of __init thru out this driver.
What would happen if a system is booted without a DU node and then a
overlay is added using the old DU bindings will things work as expected,
the old style overlay load but DU/LVDS will be in a none functioning
state or will it explode? I don't feel this is a concern that you need
to address as it feels a bit extreme use-case but since this is such a
new approach (to me at least) to solve backward compatibility problems I
just had to ask :-)
I also trust you that all of the register values in the dts files are
correct.
On 2018-03-02 00:05:38 +0200, Laurent Pinchart wrote:
> The internal LVDS encoders now have their own DT bindings. Before
> switching the driver infrastructure to those new bindings, implement
> backward-compatibility through live DT patching.
>
> Patching is disabled and will be enabled along with support for the new
> DT bindings in the DU driver.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
> Changes since v6:
>
> - Don't free data used by the applied overlay
>
> Changes since v5:
>
> - Use a private copy of rcar_du_of_changeset_add_property()
>
> Changes since v3:
>
> - Use the OF changeset API
> - Use of_graph_get_endpoint_by_regs()
> - Replace hardcoded constants by sizeof()
>
> Changes since v2:
>
> - Update the SPDX headers to use C-style comments in header files
> - Removed the manually created __local_fixups__ node
> - Perform manual fixups on live DT instead of overlay
>
> Changes since v1:
>
> - Select OF_FLATTREE
> - Compile LVDS DT bindings patch code when DRM_RCAR_LVDS is selected
> - Update the SPDX headers to use GPL-2.0 instead of GPL-2.0-only
> - Turn __dtb_rcar_du_of_lvds_(begin|end) from u8 to char
> - Pass void begin and end pointers to rcar_du_of_get_overlay()
> - Use of_get_parent() instead of accessing the parent pointer directly
> - Find the LVDS endpoints nodes based on the LVDS node instead of the
> root of the overlay
> - Update to the <soc>-lvds compatible string format
> ---
> drivers/gpu/drm/rcar-du/Kconfig | 2 +
> drivers/gpu/drm/rcar-du/Makefile | 7 +-
> drivers/gpu/drm/rcar-du/rcar_du_of.c | 334 +++++++++++++++++++++
> drivers/gpu/drm/rcar-du/rcar_du_of.h | 20 ++
> .../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts | 79 +++++
> .../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts | 53 ++++
> .../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts | 53 ++++
> .../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts | 53 ++++
> .../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts | 53 ++++
> 9 files changed, 653 insertions(+), 1 deletion(-)
> create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of.c
> create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of.h
> create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts
> create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts
> create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts
> create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts
> create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts
>
> diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
> index 5d0b4b7119af..3f83352a7313 100644
> --- a/drivers/gpu/drm/rcar-du/Kconfig
> +++ b/drivers/gpu/drm/rcar-du/Kconfig
> @@ -22,6 +22,8 @@ config DRM_RCAR_LVDS
> bool "R-Car DU LVDS Encoder Support"
> depends on DRM_RCAR_DU
> select DRM_PANEL
> + select OF_FLATTREE
> + select OF_OVERLAY
> help
> Enable support for the R-Car Display Unit embedded LVDS encoders.
>
> diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
> index 0cf5c11030e8..86b337b4be5d 100644
> --- a/drivers/gpu/drm/rcar-du/Makefile
> +++ b/drivers/gpu/drm/rcar-du/Makefile
> @@ -8,7 +8,12 @@ rcar-du-drm-y := rcar_du_crtc.o \
> rcar_du_plane.o
>
> rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS) += rcar_du_lvdsenc.o
> -
> +rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS) += rcar_du_of.o \
> + rcar_du_of_lvds_r8a7790.dtb.o \
> + rcar_du_of_lvds_r8a7791.dtb.o \
> + rcar_du_of_lvds_r8a7793.dtb.o \
> + rcar_du_of_lvds_r8a7795.dtb.o \
> + rcar_du_of_lvds_r8a7796.dtb.o
> rcar-du-drm-$(CONFIG_DRM_RCAR_VSP) += rcar_du_vsp.o
>
> obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-drm.o
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of.c b/drivers/gpu/drm/rcar-du/rcar_du_of.c
> new file mode 100644
> index 000000000000..067278b91caa
> --- /dev/null
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_of.c
> @@ -0,0 +1,334 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * rcar_du_of.c - Legacy DT bindings compatibility
> + *
> + * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> + *
> + * Based on work from Jyri Sarha <jsarha@ti.com>
> + * Copyright (C) 2015 Texas Instruments
> + */
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_fdt.h>
> +#include <linux/of_graph.h>
> +#include <linux/slab.h>
> +
> +#include "rcar_du_crtc.h"
> +#include "rcar_du_drv.h"
> +
> +/* -----------------------------------------------------------------------------
> + * Generic Overlay Handling
> + */
> +
> +struct rcar_du_of_overlay {
> + const char *compatible;
> + void *begin;
> + void *end;
> +};
> +
> +#define RCAR_DU_OF_DTB(type, soc) \
> + extern char __dtb_rcar_du_of_##type##_##soc##_begin[]; \
> + extern char __dtb_rcar_du_of_##type##_##soc##_end[]
I think I understand this but just to be sure the names are derived from
the object files of the DTBs right? Would a comment on where these
external blobs come from make it easier to understand or is it just my
lack of experience that is showing?
> +
> +#define RCAR_DU_OF_OVERLAY(type, soc) \
> + { \
> + .compatible = "renesas,du-" #soc, \
> + .begin = __dtb_rcar_du_of_##type##_##soc##_begin, \
> + .end = __dtb_rcar_du_of_##type##_##soc##_end, \
> + }
> +
> +static int __init rcar_du_of_apply_overlay(const struct rcar_du_of_overlay *dtbs,
> + const char *compatible)
> +{
> + const struct rcar_du_of_overlay *dtb = NULL;
> + struct device_node *node;
> + unsigned int i;
> + int ovcs_id;
> + void *data;
> + void *mem;
> +
> + for (i = 0; dtbs[i].compatible; ++i) {
> + if (!strcmp(dtbs[i].compatible, compatible)) {
> + dtb = &dtbs[i];
> + break;
> + }
> + }
> +
> + if (!dtb)
> + return -ENODEV;
> +
> + data = kmemdup(dtb->begin, dtb->end - dtb->begin, GFP_KERNEL);
> + if (!data)
> + return -ENOMEM;
> +
> + mem = of_fdt_unflatten_tree(data, NULL, &node);
> + if (!mem) {
> + kfree(data);
> + return -ENOMEM;
> + }
> +
> + ovcs_id = 0;
> + return of_overlay_apply(node, &ovcs_id);
> +}
> +
> +static int __init rcar_du_of_add_property(struct of_changeset *ocs,
> + struct device_node *np,
> + const char *name, const void *value,
> + int length)
> +{
> + struct property *prop;
> + int ret = -ENOMEM;
> +
> + prop = kzalloc(sizeof(*prop), GFP_KERNEL);
> + if (!prop)
> + return -ENOMEM;
> +
> + prop->name = kstrdup(name, GFP_KERNEL);
> + if (!prop->name)
> + goto out_err;
> +
> + prop->value = kmemdup(value, length, GFP_KERNEL);
> + if (!prop->value)
> + goto out_err;
> +
> + of_property_set_flag(prop, OF_DYNAMIC);
> +
> + prop->length = length;
> +
> + ret = of_changeset_add_property(ocs, np, prop);
> + if (!ret)
> + return 0;
> +
> +out_err:
> + kfree(prop->value);
> + kfree(prop->name);
> + kfree(prop);
> + return ret;
> +}
> +
> +/* -----------------------------------------------------------------------------
> + * LVDS Overlays
> + */
> +
> +RCAR_DU_OF_DTB(lvds, r8a7790);
> +RCAR_DU_OF_DTB(lvds, r8a7791);
> +RCAR_DU_OF_DTB(lvds, r8a7793);
> +RCAR_DU_OF_DTB(lvds, r8a7795);
> +RCAR_DU_OF_DTB(lvds, r8a7796);
> +
> +static const struct rcar_du_of_overlay rcar_du_lvds_overlays[] __initconst = {
> + RCAR_DU_OF_OVERLAY(lvds, r8a7790),
> + RCAR_DU_OF_OVERLAY(lvds, r8a7791),
> + RCAR_DU_OF_OVERLAY(lvds, r8a7793),
> + RCAR_DU_OF_OVERLAY(lvds, r8a7795),
> + RCAR_DU_OF_OVERLAY(lvds, r8a7796),
> + { /* Sentinel */ },
> +};
> +
> +static struct of_changeset rcar_du_lvds_changeset;
> +
> +static void __init rcar_du_of_lvds_patch_one(struct device_node *lvds,
> + const struct of_phandle_args *clk,
> + struct device_node *local,
> + struct device_node *remote)
> +{
> + unsigned int psize;
> + unsigned int i;
> + __be32 value[4];
> + int ret;
> +
> + /*
> + * Set the LVDS clocks property. This can't be performed by the overlay
> + * as the structure of the clock specifier has changed over time, and we
> + * don't know at compile time which binding version the system we will
> + * run on uses.
> + */
> + if (clk->args_count >= ARRAY_SIZE(value) - 1)
> + return;
> +
> + of_changeset_init(&rcar_du_lvds_changeset);
> +
> + value[0] = cpu_to_be32(clk->np->phandle);
> + for (i = 0; i < clk->args_count; ++i)
> + value[i + 1] = cpu_to_be32(clk->args[i]);
> +
> + psize = (clk->args_count + 1) * 4;
> + ret = rcar_du_of_add_property(&rcar_du_lvds_changeset, lvds,
> + "clocks", value, psize);
> + if (ret < 0)
> + goto done;
> +
> + /*
> + * Insert the node in the OF graph: patch the LVDS ports remote-endpoint
> + * properties to point to the endpoints of the sibling nodes in the
> + * graph. This can't be performed by the overlay: on the input side the
> + * overlay would contain a phandle for the DU LVDS output port that
> + * would clash with the system DT, and on the output side the connection
> + * is board-specific.
> + */
> + value[0] = cpu_to_be32(local->phandle);
> + value[1] = cpu_to_be32(remote->phandle);
> +
> + for (i = 0; i < 2; ++i) {
> + struct device_node *endpoint;
> +
> + endpoint = of_graph_get_endpoint_by_regs(lvds, i, 0);
> + if (!endpoint) {
> + ret = -EINVAL;
> + goto done;
> + }
> +
> + ret = rcar_du_of_add_property(&rcar_du_lvds_changeset,
> + endpoint, "remote-endpoint",
> + &value[i], sizeof(value[i]));
> + of_node_put(endpoint);
> + if (ret < 0)
> + goto done;
> + }
> +
> + ret = of_changeset_apply(&rcar_du_lvds_changeset);
> +
> +done:
> + if (ret < 0)
> + of_changeset_destroy(&rcar_du_lvds_changeset);
> +}
> +
> +struct lvds_of_data {
> + struct resource res;
> + struct of_phandle_args clkspec;
> + struct device_node *local;
> + struct device_node *remote;
> +};
> +
> +static void __init rcar_du_of_lvds_patch(const struct of_device_id *of_ids)
> +{
> + const struct rcar_du_device_info *info;
> + const struct of_device_id *match;
> + struct lvds_of_data lvds_data[2] = { };
> + struct device_node *lvds_node;
> + struct device_node *soc_node;
> + struct device_node *du_node;
> + char compatible[21];
Do this need to be 22 bytes long to not create problems on boards where
the model name is one character longer then on the earlier boards in
Gen3? For example V3M would be "renesas,r8a77970-lvds\n".
Whit these small questions/issues addressed feel free to add to which
ever variant of this patch gets picked:
Reviewed-by: Niklas S�derlund <niklas.soderlund+renesas@ragnatech.se>
> + const char *soc_name;
> + unsigned int i;
> + int ret;
> +
> + /* Get the DU node and exit if not present or disabled. */
> + du_node = of_find_matching_node_and_match(NULL, of_ids, &match);
> + if (!du_node || !of_device_is_available(du_node)) {
> + of_node_put(du_node);
> + return;
> + }
> +
> + info = match->data;
> + soc_node = of_get_parent(du_node);
> +
> + if (WARN_ON(info->num_lvds > ARRAY_SIZE(lvds_data)))
> + goto done;
> +
> + /*
> + * Skip if the LVDS nodes already exists.
> + *
> + * The nodes are searched based on the compatible string, which we
> + * construct from the SoC name found in the DU compatible string. As a
> + * match has been found we know the compatible string matches the
> + * expected format and can thus skip some of the string manipulation
> + * normal safety checks.
> + */
> + soc_name = strchr(match->compatible, '-') + 1;
> + sprintf(compatible, "renesas,%s-lvds", soc_name);
> + lvds_node = of_find_compatible_node(NULL, NULL, compatible);
> + if (lvds_node) {
> + of_node_put(lvds_node);
> + return;
> + }
> +
> + /*
> + * Parse the DU node and store the register specifier, the clock
> + * specifier and the local and remote endpoint of the LVDS link for
> + * later use.
> + */
> + for (i = 0; i < info->num_lvds; ++i) {
> + struct lvds_of_data *lvds = &lvds_data[i];
> + unsigned int port;
> + char name[7];
> + int index;
> +
> + sprintf(name, "lvds.%u", i);
> + index = of_property_match_string(du_node, "clock-names", name);
> + if (index < 0)
> + continue;
> +
> + ret = of_parse_phandle_with_args(du_node, "clocks",
> + "#clock-cells", index,
> + &lvds->clkspec);
> + if (ret < 0)
> + continue;
> +
> + port = info->routes[RCAR_DU_OUTPUT_LVDS0 + i].port;
> +
> + lvds->local = of_graph_get_endpoint_by_regs(du_node, port, 0);
> + if (!lvds->local)
> + continue;
> +
> + lvds->remote = of_graph_get_remote_endpoint(lvds->local);
> + if (!lvds->remote)
> + continue;
> +
> + index = of_property_match_string(du_node, "reg-names", name);
> + if (index < 0)
> + continue;
> +
> + of_address_to_resource(du_node, index, &lvds->res);
> + }
> +
> + /* Parse and apply the overlay. This will resolve phandles. */
> + ret = rcar_du_of_apply_overlay(rcar_du_lvds_overlays,
> + match->compatible);
> + if (ret < 0)
> + goto done;
> +
> + /* Patch the newly created LVDS encoder nodes. */
> + for_each_child_of_node(soc_node, lvds_node) {
> + struct resource res;
> +
> + if (!of_device_is_compatible(lvds_node, compatible))
> + continue;
> +
> + /* Locate the lvds_data entry based on the resource start. */
> + ret = of_address_to_resource(lvds_node, 0, &res);
> + if (ret < 0)
> + continue;
> +
> + for (i = 0; i < ARRAY_SIZE(lvds_data); ++i) {
> + if (lvds_data[i].res.start == res.start)
> + break;
> + }
> +
> + if (i == ARRAY_SIZE(lvds_data))
> + continue;
> +
> + /* Patch the LVDS encoder. */
> + rcar_du_of_lvds_patch_one(lvds_node, &lvds_data[i].clkspec,
> + lvds_data[i].local,
> + lvds_data[i].remote);
> + }
> +
> +done:
> + for (i = 0; i < info->num_lvds; ++i) {
> + of_node_put(lvds_data[i].clkspec.np);
> + of_node_put(lvds_data[i].local);
> + of_node_put(lvds_data[i].remote);
> + }
> +
> + of_node_put(soc_node);
> + of_node_put(du_node);
> +}
> +
> +void __init rcar_du_of_init(const struct of_device_id *of_ids)
> +{
> + rcar_du_of_lvds_patch(of_ids);
> +}
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of.h b/drivers/gpu/drm/rcar-du/rcar_du_of.h
> new file mode 100644
> index 000000000000..c2e65a727e91
> --- /dev/null
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_of.h
> @@ -0,0 +1,20 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * rcar_du_of.h - Legacy DT bindings compatibility
> + *
> + * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> + */
> +#ifndef __RCAR_DU_OF_H__
> +#define __RCAR_DU_OF_H__
> +
> +#include <linux/init.h>
> +
> +struct of_device_id;
> +
> +#ifdef CONFIG_DRM_RCAR_LVDS
> +void __init rcar_du_of_init(const struct of_device_id *of_ids);
> +#else
> +static inline void rcar_du_of_init(const struct of_device_id *of_ids) { }
> +#endif /* CONFIG_DRM_RCAR_LVDS */
> +
> +#endif /* __RCAR_DU_OF_H__ */
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts
> new file mode 100644
> index 000000000000..f118a6ae7782
> --- /dev/null
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts
> @@ -0,0 +1,79 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * rcar_du_of_lvds_r8a7790.dts - Legacy LVDS DT bindings conversion for R8A7790
> + *
> + * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> + *
> + * Based on work from Jyri Sarha <jsarha@ti.com>
> + * Copyright (C) 2015 Texas Instruments
> + */
> +
> +/dts-v1/;
> +/plugin/;
> +/ {
> + fragment@0 {
> + target-path = "/";
> + __overlay__ {
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + lvds@feb90000 {
> + compatible = "renesas,r8a7790-lvds";
> + reg = <0 0xfeb90000 0 0x1c>;
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> + lvds0_input: endpoint {
> + };
> + };
> + port@1 {
> + reg = <1>;
> + lvds0_out: endpoint {
> + };
> + };
> + };
> + };
> +
> + lvds@feb94000 {
> + compatible = "renesas,r8a7790-lvds";
> + reg = <0 0xfeb94000 0 0x1c>;
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> + lvds1_input: endpoint {
> + };
> + };
> + port@1 {
> + reg = <1>;
> + lvds1_out: endpoint {
> + };
> + };
> + };
> + };
> + };
> + };
> +
> + fragment@1 {
> + target-path = "/display@feb00000/ports";
> + __overlay__ {
> + port@1 {
> + endpoint {
> + remote-endpoint = <&lvds0_input>;
> + };
> + };
> + port@2 {
> + endpoint {
> + remote-endpoint = <&lvds1_input>;
> + };
> + };
> + };
> + };
> +};
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts
> new file mode 100644
> index 000000000000..7d865727928c
> --- /dev/null
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts
> @@ -0,0 +1,53 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * rcar_du_of_lvds_r8a7791.dts - Legacy LVDS DT bindings conversion for R8A7791
> + *
> + * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> + *
> + * Based on work from Jyri Sarha <jsarha@ti.com>
> + * Copyright (C) 2015 Texas Instruments
> + */
> +
> +/dts-v1/;
> +/plugin/;
> +/ {
> + fragment@0 {
> + target-path = "/";
> + __overlay__ {
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + lvds@feb90000 {
> + compatible = "renesas,r8a7791-lvds";
> + reg = <0 0xfeb90000 0 0x1c>;
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> + lvds0_input: endpoint {
> + };
> + };
> + port@1 {
> + reg = <1>;
> + lvds0_out: endpoint {
> + };
> + };
> + };
> + };
> + };
> + };
> +
> + fragment@1 {
> + target-path = "/display@feb00000/ports";
> + __overlay__ {
> + port@1 {
> + endpoint {
> + remote-endpoint = <&lvds0_input>;
> + };
> + };
> + };
> + };
> +};
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts
> new file mode 100644
> index 000000000000..bb263711834d
> --- /dev/null
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts
> @@ -0,0 +1,53 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * rcar_du_of_lvds_r8a7793.dts - Legacy LVDS DT bindings conversion for R8A7793
> + *
> + * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> + *
> + * Based on work from Jyri Sarha <jsarha@ti.com>
> + * Copyright (C) 2015 Texas Instruments
> + */
> +
> +/dts-v1/;
> +/plugin/;
> +/ {
> + fragment@0 {
> + target-path = "/";
> + __overlay__ {
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + lvds@feb90000 {
> + compatible = "renesas,r8a7793-lvds";
> + reg = <0 0xfeb90000 0 0x1c>;
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> + lvds0_input: endpoint {
> + };
> + };
> + port@1 {
> + reg = <1>;
> + lvds0_out: endpoint {
> + };
> + };
> + };
> + };
> + };
> + };
> +
> + fragment@1 {
> + target-path = "/display@feb00000/ports";
> + __overlay__ {
> + port@1 {
> + endpoint {
> + remote-endpoint = <&lvds0_input>;
> + };
> + };
> + };
> + };
> +};
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts
> new file mode 100644
> index 000000000000..9bbf7c9e5ce4
> --- /dev/null
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts
> @@ -0,0 +1,53 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * rcar_du_of_lvds_r8a7795.dts - Legacy LVDS DT bindings conversion for R8A7795
> + *
> + * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> + *
> + * Based on work from Jyri Sarha <jsarha@ti.com>
> + * Copyright (C) 2015 Texas Instruments
> + */
> +
> +/dts-v1/;
> +/plugin/;
> +/ {
> + fragment@0 {
> + target-path = "/soc";
> + __overlay__ {
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + lvds@feb90000 {
> + compatible = "renesas,r8a7795-lvds";
> + reg = <0 0xfeb90000 0 0x14>;
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> + lvds0_input: endpoint {
> + };
> + };
> + port@1 {
> + reg = <1>;
> + lvds0_out: endpoint {
> + };
> + };
> + };
> + };
> + };
> + };
> +
> + fragment@1 {
> + target-path = "/soc/display@feb00000/ports";
> + __overlay__ {
> + port@3 {
> + endpoint {
> + remote-endpoint = <&lvds0_input>;
> + };
> + };
> + };
> + };
> +};
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts
> new file mode 100644
> index 000000000000..d16f3e9e08ab
> --- /dev/null
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts
> @@ -0,0 +1,53 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * rcar_du_of_lvds_r8a7796.dts - Legacy LVDS DT bindings conversion for R8A7796
> + *
> + * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> + *
> + * Based on work from Jyri Sarha <jsarha@ti.com>
> + * Copyright (C) 2015 Texas Instruments
> + */
> +
> +/dts-v1/;
> +/plugin/;
> +/ {
> + fragment@0 {
> + target-path = "/soc";
> + __overlay__ {
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + lvds@feb90000 {
> + compatible = "renesas,r8a7796-lvds";
> + reg = <0 0xfeb90000 0 0x14>;
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> + lvds0_input: endpoint {
> + };
> + };
> + port@1 {
> + reg = <1>;
> + lvds0_out: endpoint {
> + };
> + };
> + };
> + };
> + };
> + };
> +
> + fragment@1 {
> + target-path = "/soc/display@feb00000/ports";
> + __overlay__ {
> + port@3 {
> + endpoint {
> + remote-endpoint = <&lvds0_input>;
> + };
> + };
> + };
> + };
> +};
> --
> Regards,
>
> Laurent Pinchart
>
--
Regards,
Niklas S�derlund
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v7 3/4 - variant 1] drm: rcar-du: Fix legacy DT to create LVDS encoder nodes
2018-03-01 22:05 ` [PATCH v7 3/4 - variant 1] drm: rcar-du: Fix legacy DT to create LVDS encoder nodes Laurent Pinchart
2018-03-02 0:42 ` Niklas Söderlund
@ 2018-03-02 2:06 ` Frank Rowand
1 sibling, 0 replies; 9+ messages in thread
From: Frank Rowand @ 2018-03-02 2:06 UTC (permalink / raw)
To: Laurent Pinchart, dri-devel; +Cc: linux-renesas-soc, devicetree
On 03/01/18 14:05, Laurent Pinchart wrote:
> The internal LVDS encoders now have their own DT bindings. Before
> switching the driver infrastructure to those new bindings, implement
> backward-compatibility through live DT patching.
>
> Patching is disabled and will be enabled along with support for the new
> DT bindings in the DU driver.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
Reviewed-by: Frank Rowand <frank.rowand@sony.com>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v7 3/4 - variant 2] drm: rcar-du: Fix legacy DT to create LVDS encoder nodes
2018-03-01 22:05 ` [PATCH v7 3/4 - variant 2] " Laurent Pinchart
@ 2018-03-02 2:17 ` Frank Rowand
0 siblings, 0 replies; 9+ messages in thread
From: Frank Rowand @ 2018-03-02 2:17 UTC (permalink / raw)
To: Laurent Pinchart, dri-devel; +Cc: linux-renesas-soc, devicetree
On 03/01/18 14:05, Laurent Pinchart wrote:
> The internal LVDS encoders now have their own DT bindings. Before
> switching the driver infrastructure to those new bindings, implement
> backward-compatibility through live DT patching.
>
> Patching is disabled and will be enabled along with support for the new
> DT bindings in the DU driver.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
> Changes since v6:
>
> - Use of_overlay_fdt_apply()
>
> Changes since v5:
>
> - Use a private copy of rcar_du_of_changeset_add_property()
>
> Changes since v3:
>
> - Use the OF changeset API
> - Use of_graph_get_endpoint_by_regs()
> - Replace hardcoded constants by sizeof()
>
> Changes since v2:
>
> - Update the SPDX headers to use C-style comments in header files
> - Removed the manually created __local_fixups__ node
> - Perform manual fixups on live DT instead of overlay
>
> Changes since v1:
>
> - Select OF_FLATTREE
> - Compile LVDS DT bindings patch code when DRM_RCAR_LVDS is selected
> - Update the SPDX headers to use GPL-2.0 instead of GPL-2.0-only
> - Turn __dtb_rcar_du_of_lvds_(begin|end) from u8 to char
> - Pass void begin and end pointers to rcar_du_of_get_overlay()
> - Use of_get_parent() instead of accessing the parent pointer directly
> - Find the LVDS endpoints nodes based on the LVDS node instead of the
> root of the overlay
> - Update to the <soc>-lvds compatible string format
> ---
> drivers/gpu/drm/rcar-du/Kconfig | 2 +
> drivers/gpu/drm/rcar-du/Makefile | 7 +-
> drivers/gpu/drm/rcar-du/rcar_du_of.c | 321 +++++++++++++++++++++
> drivers/gpu/drm/rcar-du/rcar_du_of.h | 20 ++
> .../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts | 79 +++++
> .../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts | 53 ++++
> .../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts | 53 ++++
> .../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts | 53 ++++
> .../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts | 53 ++++
> 9 files changed, 640 insertions(+), 1 deletion(-)
> create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of.c
> create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of.h
> create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts
> create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts
> create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts
> create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts
> create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts
>
> diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
> index 5d0b4b7119af..3f83352a7313 100644
> --- a/drivers/gpu/drm/rcar-du/Kconfig
> +++ b/drivers/gpu/drm/rcar-du/Kconfig
> @@ -22,6 +22,8 @@ config DRM_RCAR_LVDS
> bool "R-Car DU LVDS Encoder Support"
> depends on DRM_RCAR_DU
> select DRM_PANEL
> + select OF_FLATTREE
> + select OF_OVERLAY
> help
> Enable support for the R-Car Display Unit embedded LVDS encoders.
>
> diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
> index 0cf5c11030e8..86b337b4be5d 100644
> --- a/drivers/gpu/drm/rcar-du/Makefile
> +++ b/drivers/gpu/drm/rcar-du/Makefile
> @@ -8,7 +8,12 @@ rcar-du-drm-y := rcar_du_crtc.o \
> rcar_du_plane.o
>
> rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS) += rcar_du_lvdsenc.o
> -
> +rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS) += rcar_du_of.o \
> + rcar_du_of_lvds_r8a7790.dtb.o \
> + rcar_du_of_lvds_r8a7791.dtb.o \
> + rcar_du_of_lvds_r8a7793.dtb.o \
> + rcar_du_of_lvds_r8a7795.dtb.o \
> + rcar_du_of_lvds_r8a7796.dtb.o
> rcar-du-drm-$(CONFIG_DRM_RCAR_VSP) += rcar_du_vsp.o
>
> obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-drm.o
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of.c b/drivers/gpu/drm/rcar-du/rcar_du_of.c
> new file mode 100644
> index 000000000000..4e3376c64dfd
> --- /dev/null
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_of.c
> @@ -0,0 +1,321 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * rcar_du_of.c - Legacy DT bindings compatibility
> + *
> + * Copyright (C) 2018 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> + *
> + * Based on work from Jyri Sarha <jsarha@ti.com>
> + * Copyright (C) 2015 Texas Instruments
> + */
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_fdt.h>
> +#include <linux/of_graph.h>
> +#include <linux/slab.h>
> +
> +#include "rcar_du_crtc.h"
> +#include "rcar_du_drv.h"
> +
> +/* -----------------------------------------------------------------------------
> + * Generic Overlay Handling
> + */
> +
> +struct rcar_du_of_overlay {
> + const char *compatible;
> + void *begin;
> + void *end;
> +};
> +
> +#define RCAR_DU_OF_DTB(type, soc) \
> + extern char __dtb_rcar_du_of_##type##_##soc##_begin[]; \
> + extern char __dtb_rcar_du_of_##type##_##soc##_end[]
> +
> +#define RCAR_DU_OF_OVERLAY(type, soc) \
> + { \
> + .compatible = "renesas,du-" #soc, \
> + .begin = __dtb_rcar_du_of_##type##_##soc##_begin, \
> + .end = __dtb_rcar_du_of_##type##_##soc##_end, \
> + }
> +
> +static int __init rcar_du_of_apply_overlay(const struct rcar_du_of_overlay *dtbs,
> + const char *compatible)
> +{
> + const struct rcar_du_of_overlay *dtb = NULL;
> + unsigned int i;
> + int ovcs_id;
> +
> + for (i = 0; dtbs[i].compatible; ++i) {
> + if (!strcmp(dtbs[i].compatible, compatible)) {
> + dtb = &dtbs[i];
> + break;
> + }
> + }
> +
> + if (!dtb)
> + return -ENODEV;
> +
> + ovcs_id = 0;
> + return of_overlay_fdt_apply(dtb->begin, &ovcs_id);
return of_overlay_fdt_apply(dtb->begin, dtb->end - dtb->begin, &ovcs_id);
For version 5 of my patch series I added an FDT size argument, as you
suggested.
Reviewed-by: Frank Rowand <frank.rowand@sony.com>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v7 3/4 - variant 1] drm: rcar-du: Fix legacy DT to create LVDS encoder nodes
2018-03-02 0:42 ` Niklas Söderlund
@ 2018-03-02 13:02 ` Laurent Pinchart
0 siblings, 0 replies; 9+ messages in thread
From: Laurent Pinchart @ 2018-03-02 13:02 UTC (permalink / raw)
To: Niklas Söderlund
Cc: Laurent Pinchart, dri-devel, linux-renesas-soc, Frank Rowand,
devicetree
Hi Niklas,
On Friday, 2 March 2018 02:42:18 EET Niklas Söderlund wrote:
> Hi Laurent,
>
> Thanks for your patch,
>
> All comments in this mail also applies to variant 2 of this patch as the
> difference between them are so small.
>
> First I got a question about your usage of __init thru out this driver.
> What would happen if a system is booted without a DU node and then a
> overlay is added using the old DU bindings will things work as expected,
> the old style overlay load but DU/LVDS will be in a none functioning
> state or will it explode? I don't feel this is a concern that you need
> to address as it feels a bit extreme use-case but since this is such a
> new approach (to me at least) to solve backward compatibility problems I
> just had to ask :-)
So, in a nutshell, you want to boot a system with a recent kernel (with this
series merged) with a device tree that doesn't describe the hardware fully,
add display support through an overlay using old-style bindings (which are
deprecated by this series) using an overlay API that currently doesn't exist
upstream (and thus require out-of-tree modules compiled for the new kernel),
and expect it to work ? :-)
> I also trust you that all of the register values in the dts files are
> correct.
>
> On 2018-03-02 00:05:38 +0200, Laurent Pinchart wrote:
> > The internal LVDS encoders now have their own DT bindings. Before
> > switching the driver infrastructure to those new bindings, implement
> > backward-compatibility through live DT patching.
> >
> > Patching is disabled and will be enabled along with support for the new
> > DT bindings in the DU driver.
> >
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > Changes since v6:
> >
> > - Don't free data used by the applied overlay
> >
> > Changes since v5:
> >
> > - Use a private copy of rcar_du_of_changeset_add_property()
> >
> > Changes since v3:
> >
> > - Use the OF changeset API
> > - Use of_graph_get_endpoint_by_regs()
> > - Replace hardcoded constants by sizeof()
> >
> > Changes since v2:
> >
> > - Update the SPDX headers to use C-style comments in header files
> > - Removed the manually created __local_fixups__ node
> > - Perform manual fixups on live DT instead of overlay
> >
> > Changes since v1:
> >
> > - Select OF_FLATTREE
> > - Compile LVDS DT bindings patch code when DRM_RCAR_LVDS is selected
> > - Update the SPDX headers to use GPL-2.0 instead of GPL-2.0-only
> > - Turn __dtb_rcar_du_of_lvds_(begin|end) from u8 to char
> > - Pass void begin and end pointers to rcar_du_of_get_overlay()
> > - Use of_get_parent() instead of accessing the parent pointer directly
> > - Find the LVDS endpoints nodes based on the LVDS node instead of the
> > root of the overlay
> > - Update to the <soc>-lvds compatible string format
> > ---
> >
> > drivers/gpu/drm/rcar-du/Kconfig | 2 +
> > drivers/gpu/drm/rcar-du/Makefile | 7 +-
> > drivers/gpu/drm/rcar-du/rcar_du_of.c | 334 ++++++++++++++++
> > drivers/gpu/drm/rcar-du/rcar_du_of.h | 20 ++
> > .../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts | 79 +++++
> > .../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts | 53 ++++
> > .../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts | 53 ++++
> > .../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts | 53 ++++
> > .../gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts | 53 ++++
> > 9 files changed, 653 insertions(+), 1 deletion(-)
> > create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of.c
> > create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of.h
> > create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7790.dts
> > create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7791.dts
> > create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7793.dts
> > create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7795.dts
> > create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_of_lvds_r8a7796.dts
[snip]
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_of.c
> > b/drivers/gpu/drm/rcar-du/rcar_du_of.c new file mode 100644
> > index 000000000000..067278b91caa
> > --- /dev/null
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_of.c
> > @@ -0,0 +1,334 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * rcar_du_of.c - Legacy DT bindings compatibility
> > + *
> > + * Copyright (C) 2018 Laurent Pinchart
> > <laurent.pinchart@ideasonboard.com>
> > + *
> > + * Based on work from Jyri Sarha <jsarha@ti.com>
> > + * Copyright (C) 2015 Texas Instruments
> > + */
> > +
> > +#include <linux/init.h>
> > +#include <linux/kernel.h>
> > +#include <linux/of.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of_fdt.h>
> > +#include <linux/of_graph.h>
> > +#include <linux/slab.h>
> > +
> > +#include "rcar_du_crtc.h"
> > +#include "rcar_du_drv.h"
> > +
> > +/* ----------------------------------------------------------------------
> > + * Generic Overlay Handling
> > + */
> > +
> > +struct rcar_du_of_overlay {
> > + const char *compatible;
> > + void *begin;
> > + void *end;
> > +};
> > +
> > +#define RCAR_DU_OF_DTB(type, soc) \
> > + extern char __dtb_rcar_du_of_##type##_##soc##_begin[]; \
> > + extern char __dtb_rcar_du_of_##type##_##soc##_end[]
>
> I think I understand this but just to be sure the names are derived from
> the object files of the DTBs right? Would a comment on where these
> external blobs come from make it easier to understand or is it just my
> lack of experience that is showing?
I didn't find this particularly unclear when I wrote the code so I didn't
think a comment was needed, but I can add one.
> > +
> > +#define RCAR_DU_OF_OVERLAY(type, soc) \
> > + { \
> > + .compatible = "renesas,du-" #soc, \
> > + .begin = __dtb_rcar_du_of_##type##_##soc##_begin, \
> > + .end = __dtb_rcar_du_of_##type##_##soc##_end, \
> > + }
> > +
> > +static int __init rcar_du_of_apply_overlay(const struct
> > rcar_du_of_overlay *dtbs, + const char *compatible)
> > +{
> > + const struct rcar_du_of_overlay *dtb = NULL;
> > + struct device_node *node;
> > + unsigned int i;
> > + int ovcs_id;
> > + void *data;
> > + void *mem;
> > +
> > + for (i = 0; dtbs[i].compatible; ++i) {
> > + if (!strcmp(dtbs[i].compatible, compatible)) {
> > + dtb = &dtbs[i];
> > + break;
> > + }
> > + }
> > +
> > + if (!dtb)
> > + return -ENODEV;
> > +
> > + data = kmemdup(dtb->begin, dtb->end - dtb->begin, GFP_KERNEL);
> > + if (!data)
> > + return -ENOMEM;
> > +
> > + mem = of_fdt_unflatten_tree(data, NULL, &node);
> > + if (!mem) {
> > + kfree(data);
> > + return -ENOMEM;
> > + }
> > +
> > + ovcs_id = 0;
> > + return of_overlay_apply(node, &ovcs_id);
> > +}
> > +
> > +static int __init rcar_du_of_add_property(struct of_changeset *ocs,
> > + struct device_node *np,
> > + const char *name, const void *value,
> > + int length)
> > +{
> > + struct property *prop;
> > + int ret = -ENOMEM;
> > +
> > + prop = kzalloc(sizeof(*prop), GFP_KERNEL);
> > + if (!prop)
> > + return -ENOMEM;
> > +
> > + prop->name = kstrdup(name, GFP_KERNEL);
> > + if (!prop->name)
> > + goto out_err;
> > +
> > + prop->value = kmemdup(value, length, GFP_KERNEL);
> > + if (!prop->value)
> > + goto out_err;
> > +
> > + of_property_set_flag(prop, OF_DYNAMIC);
> > +
> > + prop->length = length;
> > +
> > + ret = of_changeset_add_property(ocs, np, prop);
> > + if (!ret)
> > + return 0;
> > +
> > +out_err:
> > + kfree(prop->value);
> > + kfree(prop->name);
> > + kfree(prop);
> > + return ret;
> > +}
> > +
> > +/* ----------------------------------------------------------------------
> > + * LVDS Overlays
> > + */
> > +
> > +RCAR_DU_OF_DTB(lvds, r8a7790);
> > +RCAR_DU_OF_DTB(lvds, r8a7791);
> > +RCAR_DU_OF_DTB(lvds, r8a7793);
> > +RCAR_DU_OF_DTB(lvds, r8a7795);
> > +RCAR_DU_OF_DTB(lvds, r8a7796);
> > +
> > +static const struct rcar_du_of_overlay rcar_du_lvds_overlays[]
> > __initconst = {
> > + RCAR_DU_OF_OVERLAY(lvds, r8a7790),
> > + RCAR_DU_OF_OVERLAY(lvds, r8a7791),
> > + RCAR_DU_OF_OVERLAY(lvds, r8a7793),
> > + RCAR_DU_OF_OVERLAY(lvds, r8a7795),
> > + RCAR_DU_OF_OVERLAY(lvds, r8a7796),
> > + { /* Sentinel */ },
> > +};
> > +
> > +static struct of_changeset rcar_du_lvds_changeset;
> > +
> > +static void __init rcar_du_of_lvds_patch_one(struct device_node *lvds,
> > + const struct of_phandle_args *clk,
> > + struct device_node *local,
> > + struct device_node *remote)
> > +{
> > + unsigned int psize;
> > + unsigned int i;
> > + __be32 value[4];
> > + int ret;
> > +
> > + /*
> > + * Set the LVDS clocks property. This can't be performed by the overlay
> > + * as the structure of the clock specifier has changed over time, and
> > we
> > + * don't know at compile time which binding version the system we will
> > + * run on uses.
> > + */
> > + if (clk->args_count >= ARRAY_SIZE(value) - 1)
> > + return;
> > +
> > + of_changeset_init(&rcar_du_lvds_changeset);
> > +
> > + value[0] = cpu_to_be32(clk->np->phandle);
> > + for (i = 0; i < clk->args_count; ++i)
> > + value[i + 1] = cpu_to_be32(clk->args[i]);
> > +
> > + psize = (clk->args_count + 1) * 4;
> > + ret = rcar_du_of_add_property(&rcar_du_lvds_changeset, lvds,
> > + "clocks", value, psize);
> > + if (ret < 0)
> > + goto done;
> > +
> > + /*
> > + * Insert the node in the OF graph: patch the LVDS ports remote-
> > endpoint
> > + * properties to point to the endpoints of the sibling nodes in the
> > + * graph. This can't be performed by the overlay: on the input side the
> > + * overlay would contain a phandle for the DU LVDS output port that
> > + * would clash with the system DT, and on the output side the
> > connection
> > + * is board-specific.
> > + */
> > + value[0] = cpu_to_be32(local->phandle);
> > + value[1] = cpu_to_be32(remote->phandle);
> > +
> > + for (i = 0; i < 2; ++i) {
> > + struct device_node *endpoint;
> > +
> > + endpoint = of_graph_get_endpoint_by_regs(lvds, i, 0);
> > + if (!endpoint) {
> > + ret = -EINVAL;
> > + goto done;
> > + }
> > +
> > + ret = rcar_du_of_add_property(&rcar_du_lvds_changeset,
> > + endpoint, "remote-endpoint",
> > + &value[i], sizeof(value[i]));
> > + of_node_put(endpoint);
> > + if (ret < 0)
> > + goto done;
> > + }
> > +
> > + ret = of_changeset_apply(&rcar_du_lvds_changeset);
> > +
> > +done:
> > + if (ret < 0)
> > + of_changeset_destroy(&rcar_du_lvds_changeset);
> > +}
> > +
> > +struct lvds_of_data {
> > + struct resource res;
> > + struct of_phandle_args clkspec;
> > + struct device_node *local;
> > + struct device_node *remote;
> > +};
> > +
> > +static void __init rcar_du_of_lvds_patch(const struct of_device_id
> > *of_ids)
> > +{
> > + const struct rcar_du_device_info *info;
> > + const struct of_device_id *match;
> > + struct lvds_of_data lvds_data[2] = { };
> > + struct device_node *lvds_node;
> > + struct device_node *soc_node;
> > + struct device_node *du_node;
> > + char compatible[21];
>
> Do this need to be 22 bytes long to not create problems on boards where
> the model name is one character longer then on the earlier boards in
> Gen3? For example V3M would be "renesas,r8a77970-lvds\n".
V3M will only be supported using the new-style bindings, the compat code will
only run for older SoCs that use 4 digits. I'll however make the array 22
characters long just in case, as the compiler will pad it to 24 anyway.
> Whit these small questions/issues addressed feel free to add to which
> ever variant of this patch gets picked:
>
> Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Thank you.
> > + const char *soc_name;
> > + unsigned int i;
> > + int ret;
> > +
> > + /* Get the DU node and exit if not present or disabled. */
> > + du_node = of_find_matching_node_and_match(NULL, of_ids, &match);
> > + if (!du_node || !of_device_is_available(du_node)) {
> > + of_node_put(du_node);
> > + return;
> > + }
> > +
> > + info = match->data;
> > + soc_node = of_get_parent(du_node);
> > +
> > + if (WARN_ON(info->num_lvds > ARRAY_SIZE(lvds_data)))
> > + goto done;
> > +
> > + /*
> > + * Skip if the LVDS nodes already exists.
> > + *
> > + * The nodes are searched based on the compatible string, which we
> > + * construct from the SoC name found in the DU compatible string. As a
> > + * match has been found we know the compatible string matches the
> > + * expected format and can thus skip some of the string manipulation
> > + * normal safety checks.
> > + */
> > + soc_name = strchr(match->compatible, '-') + 1;
> > + sprintf(compatible, "renesas,%s-lvds", soc_name);
> > + lvds_node = of_find_compatible_node(NULL, NULL, compatible);
> > + if (lvds_node) {
> > + of_node_put(lvds_node);
> > + return;
> > + }
> > +
> > + /*
> > + * Parse the DU node and store the register specifier, the clock
> > + * specifier and the local and remote endpoint of the LVDS link for
> > + * later use.
> > + */
> > + for (i = 0; i < info->num_lvds; ++i) {
> > + struct lvds_of_data *lvds = &lvds_data[i];
> > + unsigned int port;
> > + char name[7];
> > + int index;
> > +
> > + sprintf(name, "lvds.%u", i);
> > + index = of_property_match_string(du_node, "clock-names", name);
> > + if (index < 0)
> > + continue;
> > +
> > + ret = of_parse_phandle_with_args(du_node, "clocks",
> > + "#clock-cells", index,
> > + &lvds->clkspec);
> > + if (ret < 0)
> > + continue;
> > +
> > + port = info->routes[RCAR_DU_OUTPUT_LVDS0 + i].port;
> > +
> > + lvds->local = of_graph_get_endpoint_by_regs(du_node, port, 0);
> > + if (!lvds->local)
> > + continue;
> > +
> > + lvds->remote = of_graph_get_remote_endpoint(lvds->local);
> > + if (!lvds->remote)
> > + continue;
> > +
> > + index = of_property_match_string(du_node, "reg-names", name);
> > + if (index < 0)
> > + continue;
> > +
> > + of_address_to_resource(du_node, index, &lvds->res);
> > + }
> > +
> > + /* Parse and apply the overlay. This will resolve phandles. */
> > + ret = rcar_du_of_apply_overlay(rcar_du_lvds_overlays,
> > + match->compatible);
> > + if (ret < 0)
> > + goto done;
> > +
> > + /* Patch the newly created LVDS encoder nodes. */
> > + for_each_child_of_node(soc_node, lvds_node) {
> > + struct resource res;
> > +
> > + if (!of_device_is_compatible(lvds_node, compatible))
> > + continue;
> > +
> > + /* Locate the lvds_data entry based on the resource start. */
> > + ret = of_address_to_resource(lvds_node, 0, &res);
> > + if (ret < 0)
> > + continue;
> > +
> > + for (i = 0; i < ARRAY_SIZE(lvds_data); ++i) {
> > + if (lvds_data[i].res.start == res.start)
> > + break;
> > + }
> > +
> > + if (i == ARRAY_SIZE(lvds_data))
> > + continue;
> > +
> > + /* Patch the LVDS encoder. */
> > + rcar_du_of_lvds_patch_one(lvds_node, &lvds_data[i].clkspec,
> > + lvds_data[i].local,
> > + lvds_data[i].remote);
> > + }
> > +
> > +done:
> > + for (i = 0; i < info->num_lvds; ++i) {
> > + of_node_put(lvds_data[i].clkspec.np);
> > + of_node_put(lvds_data[i].local);
> > + of_node_put(lvds_data[i].remote);
> > + }
> > +
> > + of_node_put(soc_node);
> > + of_node_put(du_node);
> > +}
> > +
> > +void __init rcar_du_of_init(const struct of_device_id *of_ids)
> > +{
> > + rcar_du_of_lvds_patch(of_ids);
> > +}
[snip]
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2018-03-02 13:01 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-03-01 22:05 [PATCH v7 0/4] R-Car DU: Convert LVDS code to bridge driver Laurent Pinchart
2018-03-01 22:05 ` [PATCH v7 1/4] dt-bindings: display: renesas: Add R-Car LVDS encoder DT bindings Laurent Pinchart
2018-03-01 22:05 ` [PATCH v7 2/4] dt-bindings: display: renesas: Deprecate LVDS support in the DU bindings Laurent Pinchart
2018-03-01 22:05 ` [PATCH v7 3/4 - variant 1] drm: rcar-du: Fix legacy DT to create LVDS encoder nodes Laurent Pinchart
2018-03-02 0:42 ` Niklas Söderlund
2018-03-02 13:02 ` Laurent Pinchart
2018-03-02 2:06 ` Frank Rowand
2018-03-01 22:05 ` [PATCH v7 3/4 - variant 2] " Laurent Pinchart
2018-03-02 2:17 ` Frank Rowand
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).