All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] R-Car DU: Use drm bridge API
@ 2016-10-19 14:25 ` Laurent Pinchart
  0 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2016-10-19 14:25 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, devicetree

Hello,

(This time with the proper dri-devel mailing list address, sorry for the
noise)

This patch series replaces the custom external encoders support implementation
in the R-Car DU driver with code based on the DRM bridge API.

While the overall diffstat isn't impressive, the rcar-du-drm driver gets
notably thinner in the process:

        9 files changed, 38 insertions(+), 358 deletions(-)

This is offset by a reusable driver for LVDS encoders along with the
corresponding DT bindings (+ 277 lines).

Patch 1/8 adds the new LVDS encoder driver. It supports "dumb" LVDS encoders
only, similarly to the dumb-vga-dac driver. One notable difference, though, is
that LVDS encoders can't be purely passive, and thus require at least one
power supply (and usually multiple of them) and have a few control GPIOs (most
notably to control reset, power down, clock polarity and/or LVDS slew rate).
However, on many systems those encoders are integrated in such a way that the
control pins are pulled up or down appropriately and the power supplies are
either always on or shared with other display components that make them
operate as if they were always on. For that reason a common drivers for those
systems is useful, with simple DT bindings that don't try to cover any device-
specific control pin or power supply.

To ensure backward compatibility most LVDS encoders should *not* use the
common simple "lvds-encoder" compatible string, but should instead define a
device-specific compatible string that can then be added to the lvds-encoder
driver (patch 3/8). This way, when the need to control pins or supplies will
arise, a new driver can be developed matching on the device-specific
compatible string, which will then be removed from the simple driver. Existing
systems will migrate transparently without requiring a change to their device
tree.

A similar reasoning applies to VGA DACs, leading to the addition of the
"adi,adv7123" compatible string to the dumb-vga-dac driver's OF match table in
patch 2/8.

Patch 4/8 adds a new type field to the drm_bridge structure to inform bridge
users of the bridge type. This is useful for display driver to create a DRM
encoder of the appropriate type without having to resort to heuristics.
Patches 5/8 and 6/8 update all bridge drivers to initialize the new field to
the appropriate value.

Patches 7/8 and 8/8 finally migrate the rcar-du-drm driver to the DRM bridge
API, removing the custom VGA DAC implementation in patch 7/8 and the table of
bridge compatible strings used to find the encoder type in patch 8/8.

Cc: devicetree@vger.kernel.org

Laurent Pinchart (8):
  drm: bridge: Add LVDS encoder driver
  drm: bridge: vga-dac: Add adi,adv7123 compatible string
  drm: bridge: lvds-encoder: Add thine,thc63lvdm83d compatible string
  drm: Add encoder_type field to the drm_bridge structure
  drm: bridge: Set bridges' encoder type
  drm: Set on-chip bridges' encoder type
  drm: rcar-du: Replace manual VGA DAC implementation with DRM bridge
  drm: rcar-du: Initialize encoder's type based on the bridge's type

 .../bindings/display/bridge/lvds-transmitter.txt   |  64 +++++++
 drivers/gpu/drm/bridge/Kconfig                     |   8 +
 drivers/gpu/drm/bridge/Makefile                    |   1 +
 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c       |   1 +
 drivers/gpu/drm/bridge/analogix-anx78xx.c          |   1 +
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |   1 +
 drivers/gpu/drm/bridge/dumb-vga-dac.c              |   2 +
 drivers/gpu/drm/bridge/dw-hdmi.c                   |   2 +
 drivers/gpu/drm/bridge/lvds-encoder.c              | 204 +++++++++++++++++++++
 drivers/gpu/drm/bridge/nxp-ptn3460.c               |   2 +
 drivers/gpu/drm/bridge/parade-ps8622.c             |   2 +
 drivers/gpu/drm/bridge/sii902x.c                   |   2 +
 drivers/gpu/drm/bridge/tc358767.c                  |   2 +
 drivers/gpu/drm/exynos/exynos_drm_mic.c            |   2 +
 drivers/gpu/drm/mediatek/mtk_hdmi.c                |   2 +
 drivers/gpu/drm/rcar-du/Kconfig                    |   6 -
 drivers/gpu/drm/rcar-du/Makefile                   |   5 +-
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c          |  67 +++----
 drivers/gpu/drm/rcar-du/rcar_du_encoder.h          |   3 -
 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          | 137 --------------
 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h          |  35 ----
 drivers/gpu/drm/rcar-du/rcar_du_kms.c              |  38 +---
 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c           |  82 ---------
 drivers/gpu/drm/rcar-du/rcar_du_vgacon.h           |  23 ---
 drivers/gpu/drm/sti/sti_dvo.c                      |   2 +
 include/drm/drm_bridge.h                           |   8 +
 26 files changed, 344 insertions(+), 358 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
 create mode 100644 drivers/gpu/drm/bridge/lvds-encoder.c
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.h

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 0/8] R-Car DU: Use drm bridge API
@ 2016-10-19 14:25 ` Laurent Pinchart
  0 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2016-10-19 14:25 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, devicetree

Hello,

(This time with the proper dri-devel mailing list address, sorry for the
noise)

This patch series replaces the custom external encoders support implementation
in the R-Car DU driver with code based on the DRM bridge API.

While the overall diffstat isn't impressive, the rcar-du-drm driver gets
notably thinner in the process:

        9 files changed, 38 insertions(+), 358 deletions(-)

This is offset by a reusable driver for LVDS encoders along with the
corresponding DT bindings (+ 277 lines).

Patch 1/8 adds the new LVDS encoder driver. It supports "dumb" LVDS encoders
only, similarly to the dumb-vga-dac driver. One notable difference, though, is
that LVDS encoders can't be purely passive, and thus require at least one
power supply (and usually multiple of them) and have a few control GPIOs (most
notably to control reset, power down, clock polarity and/or LVDS slew rate).
However, on many systems those encoders are integrated in such a way that the
control pins are pulled up or down appropriately and the power supplies are
either always on or shared with other display components that make them
operate as if they were always on. For that reason a common drivers for those
systems is useful, with simple DT bindings that don't try to cover any device-
specific control pin or power supply.

To ensure backward compatibility most LVDS encoders should *not* use the
common simple "lvds-encoder" compatible string, but should instead define a
device-specific compatible string that can then be added to the lvds-encoder
driver (patch 3/8). This way, when the need to control pins or supplies will
arise, a new driver can be developed matching on the device-specific
compatible string, which will then be removed from the simple driver. Existing
systems will migrate transparently without requiring a change to their device
tree.

A similar reasoning applies to VGA DACs, leading to the addition of the
"adi,adv7123" compatible string to the dumb-vga-dac driver's OF match table in
patch 2/8.

Patch 4/8 adds a new type field to the drm_bridge structure to inform bridge
users of the bridge type. This is useful for display driver to create a DRM
encoder of the appropriate type without having to resort to heuristics.
Patches 5/8 and 6/8 update all bridge drivers to initialize the new field to
the appropriate value.

Patches 7/8 and 8/8 finally migrate the rcar-du-drm driver to the DRM bridge
API, removing the custom VGA DAC implementation in patch 7/8 and the table of
bridge compatible strings used to find the encoder type in patch 8/8.

Cc: devicetree@vger.kernel.org

Laurent Pinchart (8):
  drm: bridge: Add LVDS encoder driver
  drm: bridge: vga-dac: Add adi,adv7123 compatible string
  drm: bridge: lvds-encoder: Add thine,thc63lvdm83d compatible string
  drm: Add encoder_type field to the drm_bridge structure
  drm: bridge: Set bridges' encoder type
  drm: Set on-chip bridges' encoder type
  drm: rcar-du: Replace manual VGA DAC implementation with DRM bridge
  drm: rcar-du: Initialize encoder's type based on the bridge's type

 .../bindings/display/bridge/lvds-transmitter.txt   |  64 +++++++
 drivers/gpu/drm/bridge/Kconfig                     |   8 +
 drivers/gpu/drm/bridge/Makefile                    |   1 +
 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c       |   1 +
 drivers/gpu/drm/bridge/analogix-anx78xx.c          |   1 +
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |   1 +
 drivers/gpu/drm/bridge/dumb-vga-dac.c              |   2 +
 drivers/gpu/drm/bridge/dw-hdmi.c                   |   2 +
 drivers/gpu/drm/bridge/lvds-encoder.c              | 204 +++++++++++++++++++++
 drivers/gpu/drm/bridge/nxp-ptn3460.c               |   2 +
 drivers/gpu/drm/bridge/parade-ps8622.c             |   2 +
 drivers/gpu/drm/bridge/sii902x.c                   |   2 +
 drivers/gpu/drm/bridge/tc358767.c                  |   2 +
 drivers/gpu/drm/exynos/exynos_drm_mic.c            |   2 +
 drivers/gpu/drm/mediatek/mtk_hdmi.c                |   2 +
 drivers/gpu/drm/rcar-du/Kconfig                    |   6 -
 drivers/gpu/drm/rcar-du/Makefile                   |   5 +-
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c          |  67 +++----
 drivers/gpu/drm/rcar-du/rcar_du_encoder.h          |   3 -
 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          | 137 --------------
 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h          |  35 ----
 drivers/gpu/drm/rcar-du/rcar_du_kms.c              |  38 +---
 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c           |  82 ---------
 drivers/gpu/drm/rcar-du/rcar_du_vgacon.h           |  23 ---
 drivers/gpu/drm/sti/sti_dvo.c                      |   2 +
 include/drm/drm_bridge.h                           |   8 +
 26 files changed, 344 insertions(+), 358 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
 create mode 100644 drivers/gpu/drm/bridge/lvds-encoder.c
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.h

-- 
Regards,

Laurent Pinchart


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

* [PATCH 1/8] drm: bridge: Add LVDS encoder driver
  2016-10-19 14:25 ` Laurent Pinchart
  (?)
@ 2016-10-19 14:25 ` Laurent Pinchart
  2016-10-21  5:21   ` Archit Taneja
  2016-10-26 21:32     ` Rob Herring
  -1 siblings, 2 replies; 26+ messages in thread
From: Laurent Pinchart @ 2016-10-19 14:25 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, devicetree

The LVDS encoder driver is a DRM bridge driver that supports the
parallel to LVDS encoders that don't require any configuration. The
driver thus doesn't interact with the device, but creates an LVDS
connector for the panel and exposes its size and timing based on
information retrieved from DT.

Cc: devicetree@vger.kernel.org
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 .../bindings/display/bridge/lvds-transmitter.txt   |  64 +++++++
 drivers/gpu/drm/bridge/Kconfig                     |   8 +
 drivers/gpu/drm/bridge/Makefile                    |   1 +
 drivers/gpu/drm/bridge/lvds-encoder.c              | 203 +++++++++++++++++++++
 4 files changed, 276 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
 create mode 100644 drivers/gpu/drm/bridge/lvds-encoder.c

diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
new file mode 100644
index 000000000000..fd39ad34c383
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
@@ -0,0 +1,64 @@
+Parallel to LVDS Encoder
+------------------------
+
+This binding supports the parallel to LVDS encoders that don't require any
+configuration.
+
+LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A. Multiple
+incompatible data link layers have been used over time to transmit image data
+to LVDS panels. This binding targets devices compatible with the following
+specifications only.
+
+[JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999, February
+1999 (Version 1.0), Japan Electronic Industry Development Association (JEIDA)
+[LDI] "Open LVDS Display Interface", May 1999 (Version 0.95), National
+Semiconductor
+[VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video
+Electronics Standards Association (VESA)
+
+Those devices have been marketed under the FPD-Link and FlatLink brand names
+among others.
+
+
+Required properties:
+
+- compatible: Must be "lvds-encoder"
+
+Required nodes:
+
+This device has two video ports. Their connections are modeled using the OF
+graph bindings specified in Documentation/devicetree/bindings/graph.txt.
+
+- Video port 0 for parallel input
+- Video port 1 for LVDS output
+
+
+Example
+-------
+
+lvds-encoder {
+	compatible = "lvds-encoder";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+
+			lvds_enc_in: endpoint {
+				remote-endpoint = <&display_out_rgb>;
+			};
+		};
+
+		port@1 {
+			reg = <1>;
+
+			lvds_enc_out: endpoint {
+				remote-endpoint = <&lvds_panel_in>;
+			};
+		};
+	};
+};
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 10e12e74fc9f..5dafad7817ad 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -24,6 +24,14 @@ config DRM_DUMB_VGA_DAC
 	help
 	  Support for RGB to VGA DAC based bridges
 
+config DRM_LVDS_ENCODER
+	tristate "Transparent parallel to LVDS encoder support"
+	depends on OF
+	select DRM_KMS_HELPER
+	help
+	  Support for transparent parallel to LVDS encoders that don't require
+	  any configuration.
+
 config DRM_DW_HDMI
 	tristate
 	select DRM_KMS_HELPER
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index cdf3a3cf765d..bbaf583581ac 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -2,6 +2,7 @@ ccflags-y := -Iinclude/drm
 
 obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
 obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
+obj-$(CONFIG_DRM_LVDS_ENCODER) += lvds-encoder.o
 obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
 obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c b/drivers/gpu/drm/bridge/lvds-encoder.c
new file mode 100644
index 000000000000..33e8025c8a6d
--- /dev/null
+++ b/drivers/gpu/drm/bridge/lvds-encoder.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder.h>
+#include <drm/drm_modeset_helper_vtables.h>
+
+#include <linux/of_graph.h>
+
+#include <video/display_timing.h>
+#include <video/of_display_timing.h>
+#include <video/videomode.h>
+
+struct lvds_encoder {
+	struct device *dev;
+
+	struct drm_bridge bridge;
+	struct drm_connector connector;
+
+	struct {
+		unsigned int width_mm;
+		unsigned int height_mm;
+		struct videomode mode;
+	} panel;
+};
+
+static inline struct lvds_encoder *
+drm_bridge_to_lvds_encoder(struct drm_bridge *bridge)
+{
+	return container_of(bridge, struct lvds_encoder, bridge);
+}
+
+static inline struct lvds_encoder *
+drm_connector_to_lvds_encoder(struct drm_connector *connector)
+{
+	return container_of(connector, struct lvds_encoder, connector);
+}
+
+static int lvds_connector_get_modes(struct drm_connector *connector)
+{
+	struct lvds_encoder *lvds = drm_connector_to_lvds_encoder(connector);
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_create(connector->dev);
+	if (mode == NULL)
+		return 0;
+
+	mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
+
+	drm_display_mode_from_videomode(&lvds->panel.mode, mode);
+
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_connector_helper_funcs lvds_connector_helper_funcs = {
+	.get_modes = lvds_connector_get_modes,
+};
+
+static enum drm_connector_status
+lvds_connector_detect(struct drm_connector *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+static const struct drm_connector_funcs lvds_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.reset = drm_atomic_helper_connector_reset,
+	.detect = lvds_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = drm_connector_cleanup,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int lvds_encoder_attach(struct drm_bridge *bridge)
+{
+	struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge);
+	struct drm_connector *connector = &lvds->connector;
+	int ret;
+
+	if (!bridge->encoder) {
+		DRM_ERROR("Missing encoder\n");
+		return -ENODEV;
+	}
+
+	connector->display_info.width_mm = lvds->panel.width_mm;
+	connector->display_info.height_mm = lvds->panel.height_mm;
+
+	drm_connector_helper_add(connector, &lvds_connector_helper_funcs);
+
+	ret = drm_connector_init(bridge->dev, connector, &lvds_connector_funcs,
+				 DRM_MODE_CONNECTOR_LVDS);
+	if (ret) {
+		DRM_ERROR("Failed to initialize connector\n");
+		return ret;
+	}
+
+	drm_mode_connector_attach_encoder(&lvds->connector, bridge->encoder);
+
+	return 0;
+}
+
+static const struct drm_bridge_funcs lvds_encoder_bridge_funcs = {
+	.attach = lvds_encoder_attach,
+};
+
+static int lvds_encoder_probe(struct platform_device *pdev)
+{
+	struct lvds_encoder *lvds;
+	struct display_timing timing;
+	struct device_node *port;
+	struct device_node *endpoint;
+	struct device_node *panel;
+	int ret;
+
+	lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL);
+	if (!lvds)
+		return -ENOMEM;
+
+	lvds->dev = &pdev->dev;
+	platform_set_drvdata(pdev, lvds);
+
+	lvds->bridge.funcs = &lvds_encoder_bridge_funcs;
+	lvds->bridge.of_node = pdev->dev.of_node;
+	lvds->bridge.encoder_type = DRM_MODE_ENCODER_LVDS;
+
+	/* Locate the panel DT node. */
+	port = of_graph_get_port_by_id(pdev->dev.of_node, 1);
+	if (!port) {
+		dev_dbg(&pdev->dev, "port 1 not found\n");
+		return -ENXIO;
+	}
+
+	endpoint = of_get_child_by_name(port, "endpoint");
+	of_node_put(port);
+	if (!endpoint) {
+		dev_dbg(&pdev->dev, "no endpoint for port 1\n");
+		return -ENXIO;
+	}
+
+	panel = of_graph_get_remote_port_parent(endpoint);
+	of_node_put(endpoint);
+	if (!panel) {
+		dev_dbg(&pdev->dev, "no remote endpoint for port 1\n");
+		return -ENXIO;
+	}
+
+	/* Parse and store panel information. */
+	ret = of_get_display_timing(panel, "panel-timing", &timing);
+	of_node_put(panel);
+	if (ret < 0) {
+		dev_dbg(&pdev->dev, "unable to parse panel timings\n");
+		return ret;
+	}
+
+	videomode_from_timing(&timing, &lvds->panel.mode);
+
+	of_property_read_u32(panel, "width-mm", &lvds->panel.width_mm);
+	of_property_read_u32(panel, "height-mm", &lvds->panel.height_mm);
+
+	/* Register the bridge. */
+	return drm_bridge_add(&lvds->bridge);
+}
+
+static int lvds_encoder_remove(struct platform_device *pdev)
+{
+	struct lvds_encoder *encoder = platform_get_drvdata(pdev);
+
+	drm_bridge_remove(&encoder->bridge);
+
+	return 0;
+}
+
+static const struct of_device_id lvds_encoder_match[] = {
+	{ .compatible = "lvds-encoder" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, lvds_encoder_match);
+
+struct platform_driver lvds_encoder_driver = {
+	.probe	= lvds_encoder_probe,
+	.remove	= lvds_encoder_remove,
+	.driver		= {
+		.name		= "lvds-encoder",
+		.of_match_table	= lvds_encoder_match,
+	},
+};
+module_platform_driver(lvds_encoder_driver);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("Transparent parallel to LVDS encoder");
+MODULE_LICENSE("GPL");
-- 
Regards,

Laurent Pinchart

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

* [PATCH 2/8] drm: bridge: vga-dac: Add adi,adv7123 compatible string
  2016-10-19 14:25 ` Laurent Pinchart
  (?)
  (?)
@ 2016-10-19 14:25 ` Laurent Pinchart
  2016-10-21  5:13     ` Archit Taneja
  -1 siblings, 1 reply; 26+ messages in thread
From: Laurent Pinchart @ 2016-10-19 14:25 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, devicetree

The ADV7123 is a transparent VGA DAC. Unlike dumb VGA DACs it can be
controlled through a power save pin, and requires a power supply.
However, on most boards where the device is used neither the power save
signal nor the power supply are controllable.

To avoid developing a separate device-specific driver add an
"adi,adv7123" compatible entry to the dumb-vga-dac driver. This will
allow supporting most ADV7123-based boards easily, while allowing future
development of an adv7123 driver when needed without breaking backward
compatibility.

Cc: devicetree@vger.kernel.org
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/bridge/dumb-vga-dac.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
index afec232185a7..b33e3f829e4f 100644
--- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
+++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
@@ -204,6 +204,7 @@ static int dumb_vga_remove(struct platform_device *pdev)
 
 static const struct of_device_id dumb_vga_match[] = {
 	{ .compatible = "dumb-vga-dac" },
+	{ .compatible = "adi,adv7123" },
 	{},
 };
 MODULE_DEVICE_TABLE(of, dumb_vga_match);
-- 
Regards,

Laurent Pinchart

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

* [PATCH 3/8] drm: bridge: lvds-encoder: Add thine,thc63lvdm83d compatible string
  2016-10-19 14:25 ` Laurent Pinchart
                   ` (2 preceding siblings ...)
  (?)
@ 2016-10-19 14:25 ` Laurent Pinchart
  -1 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2016-10-19 14:25 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, devicetree

The THC63LVDM83D is a transparent LVDS encoder. Unlike dumb LVDS
encoders it can be controlled through a few pins (power down, LVDS
swing, clock edge selection) and requires power supplies. However, on
several boards where the device is used neither the control pins nor the
power supply are controllable.

To avoid developing a separate device-specific driver add a
"thine,thc63lvdm83d" compatible entry to the lvds-encoder driver. This
will allow supporting many THC63LVDM83D-based boards easily, while
allowing future development of an thc63lvdm83d driver when needed
without breaking backward compatibility.

Cc: devicetree@vger.kernel.org
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/bridge/lvds-encoder.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c b/drivers/gpu/drm/bridge/lvds-encoder.c
index 33e8025c8a6d..f3026ad82fe1 100644
--- a/drivers/gpu/drm/bridge/lvds-encoder.c
+++ b/drivers/gpu/drm/bridge/lvds-encoder.c
@@ -184,6 +184,7 @@ static int lvds_encoder_remove(struct platform_device *pdev)
 
 static const struct of_device_id lvds_encoder_match[] = {
 	{ .compatible = "lvds-encoder" },
+	{ .compatible = "thine,thc63lvdm83d" },
 	{},
 };
 MODULE_DEVICE_TABLE(of, lvds_encoder_match);
-- 
Regards,

Laurent Pinchart

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

* [PATCH 4/8] drm: Add encoder_type field to the drm_bridge structure
  2016-10-19 14:25 ` Laurent Pinchart
                   ` (3 preceding siblings ...)
  (?)
@ 2016-10-19 14:25 ` Laurent Pinchart
  2016-10-20 12:15     ` Archit Taneja
  -1 siblings, 1 reply; 26+ messages in thread
From: Laurent Pinchart @ 2016-10-19 14:25 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

The drm_bridge object models on- or off-chip hardware encoders and
provide an abstract control API to display drivers. In order to help
display drivers creating the right kind of drm_encoder object, expose
the type of the hardware encoder associated with each bridge.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 include/drm/drm_bridge.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 530a1d6e8cde..e93105bffc3c 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -194,6 +194,14 @@ struct drm_bridge {
 #endif
 	struct list_head list;
 
+	/**
+	 * @encoder_type:
+	 *
+	 * Type of the hardware encoder modeled by the bridge as one of the
+	 * DRM_MODE_ENCODER_* types. This will usually be identical to the
+	 * ->encoder.encoder_type for the last bridge in the chain only.
+	 */
+	int encoder_type;
 	const struct drm_bridge_funcs *funcs;
 	void *driver_private;
 };
-- 
Regards,

Laurent Pinchart

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

* [PATCH 5/8] drm: bridge: Set bridges' encoder type
  2016-10-19 14:25 ` Laurent Pinchart
                   ` (4 preceding siblings ...)
  (?)
@ 2016-10-19 14:25 ` Laurent Pinchart
  -1 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2016-10-19 14:25 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

Initialize the new drm_bridge::encoder_type field to the right value for
all external bridge drivers.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c       | 1 +
 drivers/gpu/drm/bridge/analogix-anx78xx.c          | 1 +
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 1 +
 drivers/gpu/drm/bridge/dumb-vga-dac.c              | 1 +
 drivers/gpu/drm/bridge/dw-hdmi.c                   | 2 ++
 drivers/gpu/drm/bridge/nxp-ptn3460.c               | 2 ++
 drivers/gpu/drm/bridge/parade-ps8622.c             | 2 ++
 drivers/gpu/drm/bridge/sii902x.c                   | 2 ++
 drivers/gpu/drm/bridge/tc358767.c                  | 2 ++
 9 files changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index 8ed3906dd411..66bbd2073529 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -1030,6 +1030,7 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
 
 	adv7511->bridge.funcs = &adv7511_bridge_funcs;
 	adv7511->bridge.of_node = dev->of_node;
+	adv7511->bridge.encoder_type = DRM_MODE_ENCODER_TMDS;
 
 	ret = drm_bridge_add(&adv7511->bridge);
 	if (ret) {
diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix-anx78xx.c
index a2a82366a771..62be93f7ffaa 100644
--- a/drivers/gpu/drm/bridge/analogix-anx78xx.c
+++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c
@@ -1437,6 +1437,7 @@ static int anx78xx_i2c_probe(struct i2c_client *client,
 	}
 
 	anx78xx->bridge.funcs = &anx78xx_bridge_funcs;
+	anx78xx->bridge.encoder_type = DRM_MODE_ENCODER_TMDS;
 
 	err = drm_bridge_add(&anx78xx->bridge);
 	if (err < 0) {
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 6e0447f329a2..d7eda99e5b8a 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1231,6 +1231,7 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev,
 	bridge->driver_private = dp;
 	bridge->encoder = dp->encoder;
 	bridge->funcs = &analogix_dp_bridge_funcs;
+	bridge->encoder_type = DRM_MODE_ENCODER_TMDS;
 
 	ret = drm_bridge_attach(drm_dev, bridge);
 	if (ret) {
diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
index b33e3f829e4f..036c54c849e6 100644
--- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
+++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
@@ -182,6 +182,7 @@ static int dumb_vga_probe(struct platform_device *pdev)
 
 	vga->bridge.funcs = &dumb_vga_bridge_funcs;
 	vga->bridge.of_node = pdev->dev.of_node;
+	vga->bridge.encoder_type = DRM_MODE_ENCODER_DAC;
 
 	ret = drm_bridge_add(&vga->bridge);
 	if (ret && !IS_ERR(vga->ddc))
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index ab7023e5dfde..f6485885c4ff 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -1609,6 +1609,8 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
 	hdmi->bridge = bridge;
 	bridge->driver_private = hdmi;
 	bridge->funcs = &dw_hdmi_bridge_funcs;
+	bridge->encoder_type = DRM_MODE_ENCODER_TMDS;
+
 	ret = drm_bridge_attach(drm, bridge);
 	if (ret) {
 		DRM_ERROR("Failed to initialize bridge with drm\n");
diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c
index f1a99938e924..8be117cc024f 100644
--- a/drivers/gpu/drm/bridge/nxp-ptn3460.c
+++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c
@@ -349,6 +349,8 @@ static int ptn3460_probe(struct i2c_client *client,
 
 	ptn_bridge->bridge.funcs = &ptn3460_bridge_funcs;
 	ptn_bridge->bridge.of_node = dev->of_node;
+	ptn_bridge->bridge.encoder_type = DRM_MODE_ENCODER_LVDS;
+
 	ret = drm_bridge_add(&ptn_bridge->bridge);
 	if (ret) {
 		DRM_ERROR("Failed to add bridge\n");
diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c
index 6f7c2f9860d2..37ac7211139a 100644
--- a/drivers/gpu/drm/bridge/parade-ps8622.c
+++ b/drivers/gpu/drm/bridge/parade-ps8622.c
@@ -615,6 +615,8 @@ static int ps8622_probe(struct i2c_client *client,
 
 	ps8622->bridge.funcs = &ps8622_bridge_funcs;
 	ps8622->bridge.of_node = dev->of_node;
+	ps8622->bridge.encoder_type = DRM_MODE_ENCODER_LVDS;
+
 	ret = drm_bridge_add(&ps8622->bridge);
 	if (ret) {
 		DRM_ERROR("Failed to add bridge\n");
diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
index 9126d0306ab5..ad4663dea333 100644
--- a/drivers/gpu/drm/bridge/sii902x.c
+++ b/drivers/gpu/drm/bridge/sii902x.c
@@ -418,6 +418,8 @@ static int sii902x_probe(struct i2c_client *client,
 
 	sii902x->bridge.funcs = &sii902x_bridge_funcs;
 	sii902x->bridge.of_node = dev->of_node;
+	sii902x->bridge.encoder_type = DRM_MODE_ENCODER_TMDS;
+
 	ret = drm_bridge_add(&sii902x->bridge);
 	if (ret) {
 		dev_err(dev, "Failed to add drm_bridge\n");
diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
index 44d476ea6d2e..934333cb647b 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -1353,6 +1353,8 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 	tc->bridge.funcs = &tc_bridge_funcs;
 	tc->bridge.of_node = dev->of_node;
+	tc->bridge.encoder_type = DRM_MODE_ENCODER_TMDS;
+
 	ret = drm_bridge_add(&tc->bridge);
 	if (ret) {
 		dev_err(dev, "Failed to add drm_bridge: %d\n", ret);
-- 
Regards,

Laurent Pinchart

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

* [PATCH 6/8] drm: Set on-chip bridges' encoder type
  2016-10-19 14:25 ` Laurent Pinchart
@ 2016-10-19 14:25   ` Laurent Pinchart
  -1 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2016-10-19 14:25 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

Initialize the new drm_bridge::encoder_type field to the right value for
all bridges that model on-SoC IP cores.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/exynos/exynos_drm_mic.c | 2 ++
 drivers/gpu/drm/mediatek/mtk_hdmi.c     | 2 ++
 drivers/gpu/drm/sti/sti_dvo.c           | 2 ++
 3 files changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c
index a0def0be6d65..7175ecda36e8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
@@ -390,6 +390,8 @@ static int exynos_mic_bind(struct device *dev, struct device *master,
 	mic->bridge.funcs = &mic_bridge_funcs;
 	mic->bridge.of_node = dev->of_node;
 	mic->bridge.driver_private = mic;
+	mic->bridge.encoder_type = DRM_MODE_ENCODER_DSI;
+
 	ret = drm_bridge_add(&mic->bridge);
 	if (ret)
 		DRM_ERROR("mic: Failed to add MIC to the global bridge list\n");
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index 71227deef21b..4fd2e6203266 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -1711,6 +1711,8 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev)
 
 	hdmi->bridge.funcs = &mtk_hdmi_bridge_funcs;
 	hdmi->bridge.of_node = pdev->dev.of_node;
+	hdmi->bridge.encoder_type = DRM_MODE_ENCODER_TMDS;
+
 	ret = drm_bridge_add(&hdmi->bridge);
 	if (ret) {
 		dev_err(dev, "failed to add bridge, ret = %d\n", ret);
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
index e8c1ed08a9f7..0c00d18028c5 100644
--- a/drivers/gpu/drm/sti/sti_dvo.c
+++ b/drivers/gpu/drm/sti/sti_dvo.c
@@ -472,6 +472,8 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
 	bridge->driver_private = dvo;
 	bridge->funcs = &sti_dvo_bridge_funcs;
 	bridge->of_node = dvo->dev.of_node;
+	bridge->encoder_type = DRM_MODE_ENCODER_LVDS;
+
 	err = drm_bridge_add(bridge);
 	if (err) {
 		DRM_ERROR("Failed to add bridge\n");
-- 
Regards,

Laurent Pinchart

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

* [PATCH 6/8] drm: Set on-chip bridges' encoder type
@ 2016-10-19 14:25   ` Laurent Pinchart
  0 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2016-10-19 14:25 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

Initialize the new drm_bridge::encoder_type field to the right value for
all bridges that model on-SoC IP cores.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/exynos/exynos_drm_mic.c | 2 ++
 drivers/gpu/drm/mediatek/mtk_hdmi.c     | 2 ++
 drivers/gpu/drm/sti/sti_dvo.c           | 2 ++
 3 files changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c
index a0def0be6d65..7175ecda36e8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
@@ -390,6 +390,8 @@ static int exynos_mic_bind(struct device *dev, struct device *master,
 	mic->bridge.funcs = &mic_bridge_funcs;
 	mic->bridge.of_node = dev->of_node;
 	mic->bridge.driver_private = mic;
+	mic->bridge.encoder_type = DRM_MODE_ENCODER_DSI;
+
 	ret = drm_bridge_add(&mic->bridge);
 	if (ret)
 		DRM_ERROR("mic: Failed to add MIC to the global bridge list\n");
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index 71227deef21b..4fd2e6203266 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -1711,6 +1711,8 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev)
 
 	hdmi->bridge.funcs = &mtk_hdmi_bridge_funcs;
 	hdmi->bridge.of_node = pdev->dev.of_node;
+	hdmi->bridge.encoder_type = DRM_MODE_ENCODER_TMDS;
+
 	ret = drm_bridge_add(&hdmi->bridge);
 	if (ret) {
 		dev_err(dev, "failed to add bridge, ret = %d\n", ret);
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
index e8c1ed08a9f7..0c00d18028c5 100644
--- a/drivers/gpu/drm/sti/sti_dvo.c
+++ b/drivers/gpu/drm/sti/sti_dvo.c
@@ -472,6 +472,8 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
 	bridge->driver_private = dvo;
 	bridge->funcs = &sti_dvo_bridge_funcs;
 	bridge->of_node = dvo->dev.of_node;
+	bridge->encoder_type = DRM_MODE_ENCODER_LVDS;
+
 	err = drm_bridge_add(bridge);
 	if (err) {
 		DRM_ERROR("Failed to add bridge\n");
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 7/8] drm: rcar-du: Replace manual VGA DAC implementation with DRM bridge
  2016-10-19 14:25 ` Laurent Pinchart
@ 2016-10-19 14:25   ` Laurent Pinchart
  -1 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2016-10-19 14:25 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/Kconfig           |   6 --
 drivers/gpu/drm/rcar-du/Makefile          |   5 +-
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c |  52 ++++++++----
 drivers/gpu/drm/rcar-du/rcar_du_encoder.h |   2 -
 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 137 ------------------------------
 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h |  35 --------
 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c  |  82 ------------------
 drivers/gpu/drm/rcar-du/rcar_du_vgacon.h  |  23 -----
 8 files changed, 35 insertions(+), 307 deletions(-)
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.h

diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
index 4c2fd056dd6d..c222dc157494 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -11,12 +11,6 @@ config DRM_RCAR_DU
 	  Choose this option if you have an R-Car chipset.
 	  If M is selected the module will be called rcar-du-drm.
 
-config DRM_RCAR_HDMI
-	bool "R-Car DU HDMI Encoder Support"
-	depends on DRM_RCAR_DU
-	help
-	  Enable support for external HDMI encoders.
-
 config DRM_RCAR_LVDS
 	bool "R-Car DU LVDS Encoder Support"
 	depends on DRM_RCAR_DU
diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
index d3b44651061a..a492e6858691 100644
--- a/drivers/gpu/drm/rcar-du/Makefile
+++ b/drivers/gpu/drm/rcar-du/Makefile
@@ -4,10 +4,7 @@ rcar-du-drm-y := rcar_du_crtc.o \
 		 rcar_du_group.o \
 		 rcar_du_kms.o \
 		 rcar_du_lvdscon.o \
-		 rcar_du_plane.o \
-		 rcar_du_vgacon.o
-
-rcar-du-drm-$(CONFIG_DRM_RCAR_HDMI)	+= rcar_du_hdmienc.o
+		 rcar_du_plane.o
 
 rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS)	+= rcar_du_lvdsenc.o
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index ab8645c57e2d..61aaf746b2d6 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -19,11 +19,9 @@
 
 #include "rcar_du_drv.h"
 #include "rcar_du_encoder.h"
-#include "rcar_du_hdmienc.h"
 #include "rcar_du_kms.h"
 #include "rcar_du_lvdscon.h"
 #include "rcar_du_lvdsenc.h"
-#include "rcar_du_vgacon.h"
 
 /* -----------------------------------------------------------------------------
  * Encoder
@@ -56,8 +54,12 @@ static int rcar_du_encoder_atomic_check(struct drm_encoder *encoder,
 	struct drm_connector *connector = conn_state->connector;
 	struct drm_device *dev = encoder->dev;
 
-	/* DAC encoders have currently no restriction on the mode. */
-	if (encoder->encoder_type == DRM_MODE_ENCODER_DAC)
+	/*
+	 * Only panel-related encoder types require validation here, everything
+	 * else is handled by the bridge drivers.
+	 */
+	if (encoder->encoder_type != DRM_MODE_ENCODER_NONE &&
+	    encoder->encoder_type != DRM_MODE_ENCODER_LVDS)
 		return 0;
 
 	if (list_empty(&connector->modes)) {
@@ -110,6 +112,7 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
 {
 	struct rcar_du_encoder *renc;
 	struct drm_encoder *encoder;
+	struct drm_bridge *bridge = NULL;
 	unsigned int encoder_type;
 	int ret;
 
@@ -133,6 +136,15 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
 		break;
 	}
 
+	if (enc_node) {
+		/* Locate the DRM bridge from the encoder DT node. */
+		bridge = of_drm_find_bridge(enc_node);
+		if (!bridge) {
+			ret = -EPROBE_DEFER;
+			goto done;
+		}
+	}
+
 	switch (type) {
 	case RCAR_DU_ENCODER_VGA:
 		encoder_type = DRM_MODE_ENCODER_DAC;
@@ -150,30 +162,34 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
 		break;
 	}
 
-	if (type == RCAR_DU_ENCODER_HDMI) {
-		ret = rcar_du_hdmienc_init(rcdu, renc, enc_node);
-		if (ret < 0)
-			goto done;
-	} else {
-		ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
-				       encoder_type, NULL);
-		if (ret < 0)
-			goto done;
+	ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
+			       encoder_type, NULL);
+	if (ret < 0)
+		goto done;
 
-		drm_encoder_helper_add(encoder, &encoder_helper_funcs);
+	drm_encoder_helper_add(encoder, &encoder_helper_funcs);
+
+	/* Link the bridge to the encoder. */
+	if (bridge) {
+		bridge->encoder = encoder;
+		encoder->bridge = bridge;
+
+		ret = drm_bridge_attach(rcdu->ddev, bridge);
+		if (ret) {
+			drm_encoder_cleanup(encoder);
+			return ret;
+		}
 	}
 
+	/* Create the connector. */
 	switch (encoder_type) {
 	case DRM_MODE_ENCODER_LVDS:
 		ret = rcar_du_lvds_connector_init(rcdu, renc, con_node);
 		break;
 
 	case DRM_MODE_ENCODER_DAC:
-		ret = rcar_du_vga_connector_init(rcdu, renc);
-		break;
-
 	case DRM_MODE_ENCODER_TMDS:
-		/* connector managed by the bridge driver */
+		/* Connector managed by the bridge driver. */
 		break;
 
 	default:
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
index 7fc10a9c34c3..5609a0b8d7e6 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
@@ -17,7 +17,6 @@
 #include <drm/drm_crtc.h>
 
 struct rcar_du_device;
-struct rcar_du_hdmienc;
 struct rcar_du_lvdsenc;
 
 enum rcar_du_encoder_type {
@@ -31,7 +30,6 @@ enum rcar_du_encoder_type {
 struct rcar_du_encoder {
 	struct drm_encoder base;
 	enum rcar_du_output output;
-	struct rcar_du_hdmienc *hdmi;
 	struct rcar_du_lvdsenc *lvds;
 };
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
deleted file mode 100644
index f9515f53cc5b..000000000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * R-Car Display Unit HDMI Encoder
- *
- * Copyright (C) 2014 Renesas Electronics Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/slab.h>
-
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-
-#include "rcar_du_drv.h"
-#include "rcar_du_encoder.h"
-#include "rcar_du_hdmienc.h"
-#include "rcar_du_lvdsenc.h"
-
-struct rcar_du_hdmienc {
-	struct rcar_du_encoder *renc;
-	bool enabled;
-};
-
-#define to_rcar_hdmienc(e)	(to_rcar_encoder(e)->hdmi)
-
-static void rcar_du_hdmienc_disable(struct drm_encoder *encoder)
-{
-	struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
-
-	if (hdmienc->renc->lvds)
-		rcar_du_lvdsenc_enable(hdmienc->renc->lvds, encoder->crtc,
-				       false);
-
-	hdmienc->enabled = false;
-}
-
-static void rcar_du_hdmienc_enable(struct drm_encoder *encoder)
-{
-	struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
-
-	if (hdmienc->renc->lvds)
-		rcar_du_lvdsenc_enable(hdmienc->renc->lvds, encoder->crtc,
-				       true);
-
-	hdmienc->enabled = true;
-}
-
-static int rcar_du_hdmienc_atomic_check(struct drm_encoder *encoder,
-					struct drm_crtc_state *crtc_state,
-					struct drm_connector_state *conn_state)
-{
-	struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
-	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
-
-	if (hdmienc->renc->lvds)
-		rcar_du_lvdsenc_atomic_check(hdmienc->renc->lvds,
-					     adjusted_mode);
-
-	return 0;
-}
-
-
-static void rcar_du_hdmienc_mode_set(struct drm_encoder *encoder,
-				     struct drm_display_mode *mode,
-				     struct drm_display_mode *adjusted_mode)
-{
-	struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
-
-	rcar_du_crtc_route_output(encoder->crtc, hdmienc->renc->output);
-}
-
-static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
-	.mode_set = rcar_du_hdmienc_mode_set,
-	.disable = rcar_du_hdmienc_disable,
-	.enable = rcar_du_hdmienc_enable,
-	.atomic_check = rcar_du_hdmienc_atomic_check,
-};
-
-static void rcar_du_hdmienc_cleanup(struct drm_encoder *encoder)
-{
-	struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
-
-	if (hdmienc->enabled)
-		rcar_du_hdmienc_disable(encoder);
-
-	drm_encoder_cleanup(encoder);
-}
-
-static const struct drm_encoder_funcs encoder_funcs = {
-	.destroy = rcar_du_hdmienc_cleanup,
-};
-
-int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
-			 struct rcar_du_encoder *renc, struct device_node *np)
-{
-	struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(renc);
-	struct drm_bridge *bridge;
-	struct rcar_du_hdmienc *hdmienc;
-	int ret;
-
-	hdmienc = devm_kzalloc(rcdu->dev, sizeof(*hdmienc), GFP_KERNEL);
-	if (hdmienc == NULL)
-		return -ENOMEM;
-
-	/* Locate the DRM bridge from the HDMI encoder DT node. */
-	bridge = of_drm_find_bridge(np);
-	if (!bridge)
-		return -EPROBE_DEFER;
-
-	ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
-			       DRM_MODE_ENCODER_TMDS, NULL);
-	if (ret < 0)
-		return ret;
-
-	drm_encoder_helper_add(encoder, &encoder_helper_funcs);
-
-	renc->hdmi = hdmienc;
-	hdmienc->renc = renc;
-
-	/* Link the bridge to the encoder. */
-	bridge->encoder = encoder;
-	encoder->bridge = bridge;
-
-	ret = drm_bridge_attach(rcdu->ddev, bridge);
-	if (ret) {
-		drm_encoder_cleanup(encoder);
-		return ret;
-	}
-
-	return 0;
-}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h
deleted file mode 100644
index 2ff0128ac8e1..000000000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * R-Car Display Unit HDMI Encoder
- *
- * Copyright (C) 2014 Renesas Electronics Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __RCAR_DU_HDMIENC_H__
-#define __RCAR_DU_HDMIENC_H__
-
-#include <linux/module.h>
-
-struct device_node;
-struct rcar_du_device;
-struct rcar_du_encoder;
-
-#if IS_ENABLED(CONFIG_DRM_RCAR_HDMI)
-int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
-			 struct rcar_du_encoder *renc, struct device_node *np);
-#else
-static inline int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
-				       struct rcar_du_encoder *renc,
-				       struct device_node *np)
-{
-	return -ENOSYS;
-}
-#endif
-
-#endif /* __RCAR_DU_HDMIENC_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
deleted file mode 100644
index 63d0df7f8487..000000000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * rcar_du_vgacon.c  --  R-Car Display Unit VGA Connector
- *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <drm/drmP.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-
-#include "rcar_du_drv.h"
-#include "rcar_du_encoder.h"
-#include "rcar_du_kms.h"
-#include "rcar_du_vgacon.h"
-
-static int rcar_du_vga_connector_get_modes(struct drm_connector *connector)
-{
-	return drm_add_modes_noedid(connector, 1280, 768);
-}
-
-static const struct drm_connector_helper_funcs connector_helper_funcs = {
-	.get_modes = rcar_du_vga_connector_get_modes,
-};
-
-static enum drm_connector_status
-rcar_du_vga_connector_detect(struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
-static const struct drm_connector_funcs connector_funcs = {
-	.dpms = drm_atomic_helper_connector_dpms,
-	.reset = drm_atomic_helper_connector_reset,
-	.detect = rcar_du_vga_connector_detect,
-	.fill_modes = drm_helper_probe_single_connector_modes,
-	.destroy = drm_connector_cleanup,
-	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
-int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
-			       struct rcar_du_encoder *renc)
-{
-	struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(renc);
-	struct rcar_du_connector *rcon;
-	struct drm_connector *connector;
-	int ret;
-
-	rcon = devm_kzalloc(rcdu->dev, sizeof(*rcon), GFP_KERNEL);
-	if (rcon == NULL)
-		return -ENOMEM;
-
-	connector = &rcon->connector;
-	connector->display_info.width_mm = 0;
-	connector->display_info.height_mm = 0;
-	connector->interlace_allowed = true;
-
-	ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
-				 DRM_MODE_CONNECTOR_VGA);
-	if (ret < 0)
-		return ret;
-
-	drm_connector_helper_add(connector, &connector_helper_funcs);
-
-	connector->dpms = DRM_MODE_DPMS_OFF;
-	drm_object_property_set_value(&connector->base,
-		rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
-
-	ret = drm_mode_connector_attach_encoder(connector, encoder);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.h b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.h
deleted file mode 100644
index 112f50316e01..000000000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * rcar_du_vgacon.h  --  R-Car Display Unit VGA Connector
- *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __RCAR_DU_VGACON_H__
-#define __RCAR_DU_VGACON_H__
-
-struct rcar_du_device;
-struct rcar_du_encoder;
-
-int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
-			       struct rcar_du_encoder *renc);
-
-#endif /* __RCAR_DU_VGACON_H__ */
-- 
Regards,

Laurent Pinchart

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

* [PATCH 7/8] drm: rcar-du: Replace manual VGA DAC implementation with DRM bridge
@ 2016-10-19 14:25   ` Laurent Pinchart
  0 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2016-10-19 14:25 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/Kconfig           |   6 --
 drivers/gpu/drm/rcar-du/Makefile          |   5 +-
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c |  52 ++++++++----
 drivers/gpu/drm/rcar-du/rcar_du_encoder.h |   2 -
 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 137 ------------------------------
 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h |  35 --------
 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c  |  82 ------------------
 drivers/gpu/drm/rcar-du/rcar_du_vgacon.h  |  23 -----
 8 files changed, 35 insertions(+), 307 deletions(-)
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.h

diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
index 4c2fd056dd6d..c222dc157494 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -11,12 +11,6 @@ config DRM_RCAR_DU
 	  Choose this option if you have an R-Car chipset.
 	  If M is selected the module will be called rcar-du-drm.
 
-config DRM_RCAR_HDMI
-	bool "R-Car DU HDMI Encoder Support"
-	depends on DRM_RCAR_DU
-	help
-	  Enable support for external HDMI encoders.
-
 config DRM_RCAR_LVDS
 	bool "R-Car DU LVDS Encoder Support"
 	depends on DRM_RCAR_DU
diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
index d3b44651061a..a492e6858691 100644
--- a/drivers/gpu/drm/rcar-du/Makefile
+++ b/drivers/gpu/drm/rcar-du/Makefile
@@ -4,10 +4,7 @@ rcar-du-drm-y := rcar_du_crtc.o \
 		 rcar_du_group.o \
 		 rcar_du_kms.o \
 		 rcar_du_lvdscon.o \
-		 rcar_du_plane.o \
-		 rcar_du_vgacon.o
-
-rcar-du-drm-$(CONFIG_DRM_RCAR_HDMI)	+= rcar_du_hdmienc.o
+		 rcar_du_plane.o
 
 rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS)	+= rcar_du_lvdsenc.o
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index ab8645c57e2d..61aaf746b2d6 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -19,11 +19,9 @@
 
 #include "rcar_du_drv.h"
 #include "rcar_du_encoder.h"
-#include "rcar_du_hdmienc.h"
 #include "rcar_du_kms.h"
 #include "rcar_du_lvdscon.h"
 #include "rcar_du_lvdsenc.h"
-#include "rcar_du_vgacon.h"
 
 /* -----------------------------------------------------------------------------
  * Encoder
@@ -56,8 +54,12 @@ static int rcar_du_encoder_atomic_check(struct drm_encoder *encoder,
 	struct drm_connector *connector = conn_state->connector;
 	struct drm_device *dev = encoder->dev;
 
-	/* DAC encoders have currently no restriction on the mode. */
-	if (encoder->encoder_type == DRM_MODE_ENCODER_DAC)
+	/*
+	 * Only panel-related encoder types require validation here, everything
+	 * else is handled by the bridge drivers.
+	 */
+	if (encoder->encoder_type != DRM_MODE_ENCODER_NONE &&
+	    encoder->encoder_type != DRM_MODE_ENCODER_LVDS)
 		return 0;
 
 	if (list_empty(&connector->modes)) {
@@ -110,6 +112,7 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
 {
 	struct rcar_du_encoder *renc;
 	struct drm_encoder *encoder;
+	struct drm_bridge *bridge = NULL;
 	unsigned int encoder_type;
 	int ret;
 
@@ -133,6 +136,15 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
 		break;
 	}
 
+	if (enc_node) {
+		/* Locate the DRM bridge from the encoder DT node. */
+		bridge = of_drm_find_bridge(enc_node);
+		if (!bridge) {
+			ret = -EPROBE_DEFER;
+			goto done;
+		}
+	}
+
 	switch (type) {
 	case RCAR_DU_ENCODER_VGA:
 		encoder_type = DRM_MODE_ENCODER_DAC;
@@ -150,30 +162,34 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
 		break;
 	}
 
-	if (type == RCAR_DU_ENCODER_HDMI) {
-		ret = rcar_du_hdmienc_init(rcdu, renc, enc_node);
-		if (ret < 0)
-			goto done;
-	} else {
-		ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
-				       encoder_type, NULL);
-		if (ret < 0)
-			goto done;
+	ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
+			       encoder_type, NULL);
+	if (ret < 0)
+		goto done;
 
-		drm_encoder_helper_add(encoder, &encoder_helper_funcs);
+	drm_encoder_helper_add(encoder, &encoder_helper_funcs);
+
+	/* Link the bridge to the encoder. */
+	if (bridge) {
+		bridge->encoder = encoder;
+		encoder->bridge = bridge;
+
+		ret = drm_bridge_attach(rcdu->ddev, bridge);
+		if (ret) {
+			drm_encoder_cleanup(encoder);
+			return ret;
+		}
 	}
 
+	/* Create the connector. */
 	switch (encoder_type) {
 	case DRM_MODE_ENCODER_LVDS:
 		ret = rcar_du_lvds_connector_init(rcdu, renc, con_node);
 		break;
 
 	case DRM_MODE_ENCODER_DAC:
-		ret = rcar_du_vga_connector_init(rcdu, renc);
-		break;
-
 	case DRM_MODE_ENCODER_TMDS:
-		/* connector managed by the bridge driver */
+		/* Connector managed by the bridge driver. */
 		break;
 
 	default:
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
index 7fc10a9c34c3..5609a0b8d7e6 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
@@ -17,7 +17,6 @@
 #include <drm/drm_crtc.h>
 
 struct rcar_du_device;
-struct rcar_du_hdmienc;
 struct rcar_du_lvdsenc;
 
 enum rcar_du_encoder_type {
@@ -31,7 +30,6 @@ enum rcar_du_encoder_type {
 struct rcar_du_encoder {
 	struct drm_encoder base;
 	enum rcar_du_output output;
-	struct rcar_du_hdmienc *hdmi;
 	struct rcar_du_lvdsenc *lvds;
 };
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
deleted file mode 100644
index f9515f53cc5b..000000000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * R-Car Display Unit HDMI Encoder
- *
- * Copyright (C) 2014 Renesas Electronics Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/slab.h>
-
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-
-#include "rcar_du_drv.h"
-#include "rcar_du_encoder.h"
-#include "rcar_du_hdmienc.h"
-#include "rcar_du_lvdsenc.h"
-
-struct rcar_du_hdmienc {
-	struct rcar_du_encoder *renc;
-	bool enabled;
-};
-
-#define to_rcar_hdmienc(e)	(to_rcar_encoder(e)->hdmi)
-
-static void rcar_du_hdmienc_disable(struct drm_encoder *encoder)
-{
-	struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
-
-	if (hdmienc->renc->lvds)
-		rcar_du_lvdsenc_enable(hdmienc->renc->lvds, encoder->crtc,
-				       false);
-
-	hdmienc->enabled = false;
-}
-
-static void rcar_du_hdmienc_enable(struct drm_encoder *encoder)
-{
-	struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
-
-	if (hdmienc->renc->lvds)
-		rcar_du_lvdsenc_enable(hdmienc->renc->lvds, encoder->crtc,
-				       true);
-
-	hdmienc->enabled = true;
-}
-
-static int rcar_du_hdmienc_atomic_check(struct drm_encoder *encoder,
-					struct drm_crtc_state *crtc_state,
-					struct drm_connector_state *conn_state)
-{
-	struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
-	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
-
-	if (hdmienc->renc->lvds)
-		rcar_du_lvdsenc_atomic_check(hdmienc->renc->lvds,
-					     adjusted_mode);
-
-	return 0;
-}
-
-
-static void rcar_du_hdmienc_mode_set(struct drm_encoder *encoder,
-				     struct drm_display_mode *mode,
-				     struct drm_display_mode *adjusted_mode)
-{
-	struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
-
-	rcar_du_crtc_route_output(encoder->crtc, hdmienc->renc->output);
-}
-
-static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
-	.mode_set = rcar_du_hdmienc_mode_set,
-	.disable = rcar_du_hdmienc_disable,
-	.enable = rcar_du_hdmienc_enable,
-	.atomic_check = rcar_du_hdmienc_atomic_check,
-};
-
-static void rcar_du_hdmienc_cleanup(struct drm_encoder *encoder)
-{
-	struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
-
-	if (hdmienc->enabled)
-		rcar_du_hdmienc_disable(encoder);
-
-	drm_encoder_cleanup(encoder);
-}
-
-static const struct drm_encoder_funcs encoder_funcs = {
-	.destroy = rcar_du_hdmienc_cleanup,
-};
-
-int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
-			 struct rcar_du_encoder *renc, struct device_node *np)
-{
-	struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(renc);
-	struct drm_bridge *bridge;
-	struct rcar_du_hdmienc *hdmienc;
-	int ret;
-
-	hdmienc = devm_kzalloc(rcdu->dev, sizeof(*hdmienc), GFP_KERNEL);
-	if (hdmienc == NULL)
-		return -ENOMEM;
-
-	/* Locate the DRM bridge from the HDMI encoder DT node. */
-	bridge = of_drm_find_bridge(np);
-	if (!bridge)
-		return -EPROBE_DEFER;
-
-	ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
-			       DRM_MODE_ENCODER_TMDS, NULL);
-	if (ret < 0)
-		return ret;
-
-	drm_encoder_helper_add(encoder, &encoder_helper_funcs);
-
-	renc->hdmi = hdmienc;
-	hdmienc->renc = renc;
-
-	/* Link the bridge to the encoder. */
-	bridge->encoder = encoder;
-	encoder->bridge = bridge;
-
-	ret = drm_bridge_attach(rcdu->ddev, bridge);
-	if (ret) {
-		drm_encoder_cleanup(encoder);
-		return ret;
-	}
-
-	return 0;
-}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h
deleted file mode 100644
index 2ff0128ac8e1..000000000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * R-Car Display Unit HDMI Encoder
- *
- * Copyright (C) 2014 Renesas Electronics Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __RCAR_DU_HDMIENC_H__
-#define __RCAR_DU_HDMIENC_H__
-
-#include <linux/module.h>
-
-struct device_node;
-struct rcar_du_device;
-struct rcar_du_encoder;
-
-#if IS_ENABLED(CONFIG_DRM_RCAR_HDMI)
-int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
-			 struct rcar_du_encoder *renc, struct device_node *np);
-#else
-static inline int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
-				       struct rcar_du_encoder *renc,
-				       struct device_node *np)
-{
-	return -ENOSYS;
-}
-#endif
-
-#endif /* __RCAR_DU_HDMIENC_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
deleted file mode 100644
index 63d0df7f8487..000000000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * rcar_du_vgacon.c  --  R-Car Display Unit VGA Connector
- *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <drm/drmP.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-
-#include "rcar_du_drv.h"
-#include "rcar_du_encoder.h"
-#include "rcar_du_kms.h"
-#include "rcar_du_vgacon.h"
-
-static int rcar_du_vga_connector_get_modes(struct drm_connector *connector)
-{
-	return drm_add_modes_noedid(connector, 1280, 768);
-}
-
-static const struct drm_connector_helper_funcs connector_helper_funcs = {
-	.get_modes = rcar_du_vga_connector_get_modes,
-};
-
-static enum drm_connector_status
-rcar_du_vga_connector_detect(struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
-static const struct drm_connector_funcs connector_funcs = {
-	.dpms = drm_atomic_helper_connector_dpms,
-	.reset = drm_atomic_helper_connector_reset,
-	.detect = rcar_du_vga_connector_detect,
-	.fill_modes = drm_helper_probe_single_connector_modes,
-	.destroy = drm_connector_cleanup,
-	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
-int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
-			       struct rcar_du_encoder *renc)
-{
-	struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(renc);
-	struct rcar_du_connector *rcon;
-	struct drm_connector *connector;
-	int ret;
-
-	rcon = devm_kzalloc(rcdu->dev, sizeof(*rcon), GFP_KERNEL);
-	if (rcon == NULL)
-		return -ENOMEM;
-
-	connector = &rcon->connector;
-	connector->display_info.width_mm = 0;
-	connector->display_info.height_mm = 0;
-	connector->interlace_allowed = true;
-
-	ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
-				 DRM_MODE_CONNECTOR_VGA);
-	if (ret < 0)
-		return ret;
-
-	drm_connector_helper_add(connector, &connector_helper_funcs);
-
-	connector->dpms = DRM_MODE_DPMS_OFF;
-	drm_object_property_set_value(&connector->base,
-		rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
-
-	ret = drm_mode_connector_attach_encoder(connector, encoder);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.h b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.h
deleted file mode 100644
index 112f50316e01..000000000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * rcar_du_vgacon.h  --  R-Car Display Unit VGA Connector
- *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __RCAR_DU_VGACON_H__
-#define __RCAR_DU_VGACON_H__
-
-struct rcar_du_device;
-struct rcar_du_encoder;
-
-int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
-			       struct rcar_du_encoder *renc);
-
-#endif /* __RCAR_DU_VGACON_H__ */
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 8/8] drm: rcar-du: Initialize encoder's type based on the bridge's type
  2016-10-19 14:25 ` Laurent Pinchart
@ 2016-10-19 14:25   ` Laurent Pinchart
  -1 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2016-10-19 14:25 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

Set the type of the DRM encoder that models the hardware encoders
(bridges) chain based on the type of the last bridge in the chain
instead of hardcoding encoder compatible strings in the display driver.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 17 ++------------
 drivers/gpu/drm/rcar-du/rcar_du_encoder.h |  1 -
 drivers/gpu/drm/rcar-du/rcar_du_kms.c     | 38 ++-----------------------------
 3 files changed, 4 insertions(+), 52 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index 61aaf746b2d6..f49be3765ed7 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -105,7 +105,6 @@ static const struct drm_encoder_funcs encoder_funcs = {
 };
 
 int rcar_du_encoder_init(struct rcar_du_device *rcdu,
-			 enum rcar_du_encoder_type type,
 			 enum rcar_du_output output,
 			 struct device_node *enc_node,
 			 struct device_node *con_node)
@@ -143,23 +142,11 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
 			ret = -EPROBE_DEFER;
 			goto done;
 		}
-	}
 
-	switch (type) {
-	case RCAR_DU_ENCODER_VGA:
-		encoder_type = DRM_MODE_ENCODER_DAC;
-		break;
-	case RCAR_DU_ENCODER_LVDS:
-		encoder_type = DRM_MODE_ENCODER_LVDS;
-		break;
-	case RCAR_DU_ENCODER_HDMI:
-		encoder_type = DRM_MODE_ENCODER_TMDS;
-		break;
-	case RCAR_DU_ENCODER_NONE:
-	default:
+		encoder_type = bridge->encoder_type;
+	} else {
 		/* No external encoder, use the internal encoder type. */
 		encoder_type = rcdu->info->routes[output].encoder_type;
-		break;
 	}
 
 	ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
index 5609a0b8d7e6..150de76088e1 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
@@ -47,7 +47,6 @@ struct rcar_du_connector {
 	container_of(c, struct rcar_du_connector, connector)
 
 int rcar_du_encoder_init(struct rcar_du_device *rcdu,
-			 enum rcar_du_encoder_type type,
 			 enum rcar_du_output output,
 			 struct device_node *enc_node,
 			 struct device_node *con_node);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index f03864033cbb..1f9f13a80f85 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -357,17 +357,6 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
 				     enum rcar_du_output output,
 				     struct of_endpoint *ep)
 {
-	static const struct {
-		const char *compatible;
-		enum rcar_du_encoder_type type;
-	} encoders[] = {
-		{ "adi,adv7123", RCAR_DU_ENCODER_VGA },
-		{ "adi,adv7511w", RCAR_DU_ENCODER_HDMI },
-		{ "adi,adv7513", RCAR_DU_ENCODER_HDMI },
-		{ "thine,thc63lvdm83d", RCAR_DU_ENCODER_LVDS },
-	};
-
-	enum rcar_du_encoder_type enc_type = RCAR_DU_ENCODER_NONE;
 	struct device_node *connector = NULL;
 	struct device_node *encoder = NULL;
 	struct device_node *ep_node = NULL;
@@ -414,30 +403,7 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
 
 	of_node_put(entity_ep_node);
 
-	if (encoder) {
-		/*
-		 * If an encoder has been found, get its type based on its
-		 * compatible string.
-		 */
-		unsigned int i;
-
-		for (i = 0; i < ARRAY_SIZE(encoders); ++i) {
-			if (of_device_is_compatible(encoder,
-						    encoders[i].compatible)) {
-				enc_type = encoders[i].type;
-				break;
-			}
-		}
-
-		if (i == ARRAY_SIZE(encoders)) {
-			dev_warn(rcdu->dev,
-				 "unknown encoder type for %s, skipping\n",
-				 encoder->full_name);
-			of_node_put(encoder);
-			of_node_put(connector);
-			return -EINVAL;
-		}
-	} else {
+	if (!encoder) {
 		/*
 		 * If no encoder has been found the entity must be the
 		 * connector.
@@ -445,7 +411,7 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
 		connector = entity;
 	}
 
-	ret = rcar_du_encoder_init(rcdu, enc_type, output, encoder, connector);
+	ret = rcar_du_encoder_init(rcdu, output, encoder, connector);
 	if (ret && ret != -EPROBE_DEFER)
 		dev_warn(rcdu->dev,
 			 "failed to initialize encoder %s on output %u (%d), skipping\n",
-- 
Regards,

Laurent Pinchart

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

* [PATCH 8/8] drm: rcar-du: Initialize encoder's type based on the bridge's type
@ 2016-10-19 14:25   ` Laurent Pinchart
  0 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2016-10-19 14:25 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

Set the type of the DRM encoder that models the hardware encoders
(bridges) chain based on the type of the last bridge in the chain
instead of hardcoding encoder compatible strings in the display driver.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 17 ++------------
 drivers/gpu/drm/rcar-du/rcar_du_encoder.h |  1 -
 drivers/gpu/drm/rcar-du/rcar_du_kms.c     | 38 ++-----------------------------
 3 files changed, 4 insertions(+), 52 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index 61aaf746b2d6..f49be3765ed7 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -105,7 +105,6 @@ static const struct drm_encoder_funcs encoder_funcs = {
 };
 
 int rcar_du_encoder_init(struct rcar_du_device *rcdu,
-			 enum rcar_du_encoder_type type,
 			 enum rcar_du_output output,
 			 struct device_node *enc_node,
 			 struct device_node *con_node)
@@ -143,23 +142,11 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
 			ret = -EPROBE_DEFER;
 			goto done;
 		}
-	}
 
-	switch (type) {
-	case RCAR_DU_ENCODER_VGA:
-		encoder_type = DRM_MODE_ENCODER_DAC;
-		break;
-	case RCAR_DU_ENCODER_LVDS:
-		encoder_type = DRM_MODE_ENCODER_LVDS;
-		break;
-	case RCAR_DU_ENCODER_HDMI:
-		encoder_type = DRM_MODE_ENCODER_TMDS;
-		break;
-	case RCAR_DU_ENCODER_NONE:
-	default:
+		encoder_type = bridge->encoder_type;
+	} else {
 		/* No external encoder, use the internal encoder type. */
 		encoder_type = rcdu->info->routes[output].encoder_type;
-		break;
 	}
 
 	ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
index 5609a0b8d7e6..150de76088e1 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
@@ -47,7 +47,6 @@ struct rcar_du_connector {
 	container_of(c, struct rcar_du_connector, connector)
 
 int rcar_du_encoder_init(struct rcar_du_device *rcdu,
-			 enum rcar_du_encoder_type type,
 			 enum rcar_du_output output,
 			 struct device_node *enc_node,
 			 struct device_node *con_node);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index f03864033cbb..1f9f13a80f85 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -357,17 +357,6 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
 				     enum rcar_du_output output,
 				     struct of_endpoint *ep)
 {
-	static const struct {
-		const char *compatible;
-		enum rcar_du_encoder_type type;
-	} encoders[] = {
-		{ "adi,adv7123", RCAR_DU_ENCODER_VGA },
-		{ "adi,adv7511w", RCAR_DU_ENCODER_HDMI },
-		{ "adi,adv7513", RCAR_DU_ENCODER_HDMI },
-		{ "thine,thc63lvdm83d", RCAR_DU_ENCODER_LVDS },
-	};
-
-	enum rcar_du_encoder_type enc_type = RCAR_DU_ENCODER_NONE;
 	struct device_node *connector = NULL;
 	struct device_node *encoder = NULL;
 	struct device_node *ep_node = NULL;
@@ -414,30 +403,7 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
 
 	of_node_put(entity_ep_node);
 
-	if (encoder) {
-		/*
-		 * If an encoder has been found, get its type based on its
-		 * compatible string.
-		 */
-		unsigned int i;
-
-		for (i = 0; i < ARRAY_SIZE(encoders); ++i) {
-			if (of_device_is_compatible(encoder,
-						    encoders[i].compatible)) {
-				enc_type = encoders[i].type;
-				break;
-			}
-		}
-
-		if (i == ARRAY_SIZE(encoders)) {
-			dev_warn(rcdu->dev,
-				 "unknown encoder type for %s, skipping\n",
-				 encoder->full_name);
-			of_node_put(encoder);
-			of_node_put(connector);
-			return -EINVAL;
-		}
-	} else {
+	if (!encoder) {
 		/*
 		 * If no encoder has been found the entity must be the
 		 * connector.
@@ -445,7 +411,7 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
 		connector = entity;
 	}
 
-	ret = rcar_du_encoder_init(rcdu, enc_type, output, encoder, connector);
+	ret = rcar_du_encoder_init(rcdu, output, encoder, connector);
 	if (ret && ret != -EPROBE_DEFER)
 		dev_warn(rcdu->dev,
 			 "failed to initialize encoder %s on output %u (%d), skipping\n",
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 4/8] drm: Add encoder_type field to the drm_bridge structure
  2016-10-19 14:25 ` [PATCH 4/8] drm: Add encoder_type field to the drm_bridge structure Laurent Pinchart
@ 2016-10-20 12:15     ` Archit Taneja
  0 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2016-10-20 12:15 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel; +Cc: linux-renesas-soc

Hi,

On 10/19/2016 07:55 PM, Laurent Pinchart wrote:
> The drm_bridge object models on- or off-chip hardware encoders and
> provide an abstract control API to display drivers. In order to help
> display drivers creating the right kind of drm_encoder object, expose
> the type of the hardware encoder associated with each bridge.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  include/drm/drm_bridge.h | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 530a1d6e8cde..e93105bffc3c 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -194,6 +194,14 @@ struct drm_bridge {
>  #endif
>  	struct list_head list;
>
> +	/**
> +	 * @encoder_type:
> +	 *
> +	 * Type of the hardware encoder modeled by the bridge as one of the
> +	 * DRM_MODE_ENCODER_* types. This will usually be identical to the
> +	 * ->encoder.encoder_type for the last bridge in the chain only.

It isn't entirely clear in the comment that we're mentioning
drm_encoder's encoder_type here. Maybe we can give a &drm_encoder
back reference?


> +	 */
> +	int encoder_type;
>  	const struct drm_bridge_funcs *funcs;
>  	void *driver_private;
>  };
>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH 4/8] drm: Add encoder_type field to the drm_bridge structure
@ 2016-10-20 12:15     ` Archit Taneja
  0 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2016-10-20 12:15 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel; +Cc: linux-renesas-soc

Hi,

On 10/19/2016 07:55 PM, Laurent Pinchart wrote:
> The drm_bridge object models on- or off-chip hardware encoders and
> provide an abstract control API to display drivers. In order to help
> display drivers creating the right kind of drm_encoder object, expose
> the type of the hardware encoder associated with each bridge.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  include/drm/drm_bridge.h | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 530a1d6e8cde..e93105bffc3c 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -194,6 +194,14 @@ struct drm_bridge {
>  #endif
>  	struct list_head list;
>
> +	/**
> +	 * @encoder_type:
> +	 *
> +	 * Type of the hardware encoder modeled by the bridge as one of the
> +	 * DRM_MODE_ENCODER_* types. This will usually be identical to the
> +	 * ->encoder.encoder_type for the last bridge in the chain only.

It isn't entirely clear in the comment that we're mentioning
drm_encoder's encoder_type here. Maybe we can give a &drm_encoder
back reference?


> +	 */
> +	int encoder_type;
>  	const struct drm_bridge_funcs *funcs;
>  	void *driver_private;
>  };
>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 2/8] drm: bridge: vga-dac: Add adi,adv7123 compatible string
  2016-10-19 14:25 ` [PATCH 2/8] drm: bridge: vga-dac: Add adi,adv7123 compatible string Laurent Pinchart
@ 2016-10-21  5:13     ` Archit Taneja
  0 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2016-10-21  5:13 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel; +Cc: linux-renesas-soc, devicetree



On 10/19/2016 07:55 PM, Laurent Pinchart wrote:
> The ADV7123 is a transparent VGA DAC. Unlike dumb VGA DACs it can be
> controlled through a power save pin, and requires a power supply.
> However, on most boards where the device is used neither the power save
> signal nor the power supply are controllable.
>
> To avoid developing a separate device-specific driver add an
> "adi,adv7123" compatible entry to the dumb-vga-dac driver. This will
> allow supporting most ADV7123-based boards easily, while allowing future
> development of an adv7123 driver when needed without breaking backward
> compatibility.

Shouldn't we have a DT binding doc for ADV7123, even if it's sharing
the dumb vga driver for now?

Same query for the Thine LVDS encoder.

Thanks,
Archit

>
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/bridge/dumb-vga-dac.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
> index afec232185a7..b33e3f829e4f 100644
> --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
> +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
> @@ -204,6 +204,7 @@ static int dumb_vga_remove(struct platform_device *pdev)
>
>  static const struct of_device_id dumb_vga_match[] = {
>  	{ .compatible = "dumb-vga-dac" },
> +	{ .compatible = "adi,adv7123" },
>  	{},
>  };
>  MODULE_DEVICE_TABLE(of, dumb_vga_match);
>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 2/8] drm: bridge: vga-dac: Add adi,adv7123 compatible string
@ 2016-10-21  5:13     ` Archit Taneja
  0 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2016-10-21  5:13 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel; +Cc: linux-renesas-soc, devicetree



On 10/19/2016 07:55 PM, Laurent Pinchart wrote:
> The ADV7123 is a transparent VGA DAC. Unlike dumb VGA DACs it can be
> controlled through a power save pin, and requires a power supply.
> However, on most boards where the device is used neither the power save
> signal nor the power supply are controllable.
>
> To avoid developing a separate device-specific driver add an
> "adi,adv7123" compatible entry to the dumb-vga-dac driver. This will
> allow supporting most ADV7123-based boards easily, while allowing future
> development of an adv7123 driver when needed without breaking backward
> compatibility.

Shouldn't we have a DT binding doc for ADV7123, even if it's sharing
the dumb vga driver for now?

Same query for the Thine LVDS encoder.

Thanks,
Archit

>
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/bridge/dumb-vga-dac.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
> index afec232185a7..b33e3f829e4f 100644
> --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
> +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
> @@ -204,6 +204,7 @@ static int dumb_vga_remove(struct platform_device *pdev)
>
>  static const struct of_device_id dumb_vga_match[] = {
>  	{ .compatible = "dumb-vga-dac" },
> +	{ .compatible = "adi,adv7123" },
>  	{},
>  };
>  MODULE_DEVICE_TABLE(of, dumb_vga_match);
>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH 1/8] drm: bridge: Add LVDS encoder driver
  2016-10-19 14:25 ` [PATCH 1/8] drm: bridge: Add LVDS encoder driver Laurent Pinchart
@ 2016-10-21  5:21   ` Archit Taneja
  2016-10-21 10:21       ` Laurent Pinchart
  2016-10-26 21:32     ` Rob Herring
  1 sibling, 1 reply; 26+ messages in thread
From: Archit Taneja @ 2016-10-21  5:21 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel; +Cc: linux-renesas-soc, devicetree



On 10/19/2016 07:55 PM, Laurent Pinchart wrote:
> The LVDS encoder driver is a DRM bridge driver that supports the
> parallel to LVDS encoders that don't require any configuration. The
> driver thus doesn't interact with the device, but creates an LVDS
> connector for the panel and exposes its size and timing based on
> information retrieved from DT.
>
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  .../bindings/display/bridge/lvds-transmitter.txt   |  64 +++++++
>  drivers/gpu/drm/bridge/Kconfig                     |   8 +
>  drivers/gpu/drm/bridge/Makefile                    |   1 +
>  drivers/gpu/drm/bridge/lvds-encoder.c              | 203 +++++++++++++++++++++
>  4 files changed, 276 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
>  create mode 100644 drivers/gpu/drm/bridge/lvds-encoder.c
>
> diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
> new file mode 100644
> index 000000000000..fd39ad34c383
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
> @@ -0,0 +1,64 @@
> +Parallel to LVDS Encoder
> +------------------------
> +
> +This binding supports the parallel to LVDS encoders that don't require any
> +configuration.
> +
> +LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A. Multiple
> +incompatible data link layers have been used over time to transmit image data
> +to LVDS panels. This binding targets devices compatible with the following
> +specifications only.
> +
> +[JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999, February
> +1999 (Version 1.0), Japan Electronic Industry Development Association (JEIDA)
> +[LDI] "Open LVDS Display Interface", May 1999 (Version 0.95), National
> +Semiconductor
> +[VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video
> +Electronics Standards Association (VESA)
> +
> +Those devices have been marketed under the FPD-Link and FlatLink brand names
> +among others.
> +
> +
> +Required properties:
> +
> +- compatible: Must be "lvds-encoder"
> +
> +Required nodes:
> +
> +This device has two video ports. Their connections are modeled using the OF
> +graph bindings specified in Documentation/devicetree/bindings/graph.txt.
> +
> +- Video port 0 for parallel input
> +- Video port 1 for LVDS output
> +
> +
> +Example
> +-------
> +
> +lvds-encoder {
> +	compatible = "lvds-encoder";
> +	#address-cells = <1>;
> +	#size-cells = <0>;
> +
> +	ports {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		port@0 {
> +			reg = <0>;
> +
> +			lvds_enc_in: endpoint {
> +				remote-endpoint = <&display_out_rgb>;
> +			};
> +		};
> +
> +		port@1 {
> +			reg = <1>;
> +
> +			lvds_enc_out: endpoint {
> +				remote-endpoint = <&lvds_panel_in>;
> +			};
> +		};
> +	};
> +};
> diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
> index 10e12e74fc9f..5dafad7817ad 100644
> --- a/drivers/gpu/drm/bridge/Kconfig
> +++ b/drivers/gpu/drm/bridge/Kconfig
> @@ -24,6 +24,14 @@ config DRM_DUMB_VGA_DAC
>  	help
>  	  Support for RGB to VGA DAC based bridges
>
> +config DRM_LVDS_ENCODER
> +	tristate "Transparent parallel to LVDS encoder support"
> +	depends on OF
> +	select DRM_KMS_HELPER
> +	help
> +	  Support for transparent parallel to LVDS encoders that don't require
> +	  any configuration.
> +
>  config DRM_DW_HDMI
>  	tristate
>  	select DRM_KMS_HELPER
> diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
> index cdf3a3cf765d..bbaf583581ac 100644
> --- a/drivers/gpu/drm/bridge/Makefile
> +++ b/drivers/gpu/drm/bridge/Makefile
> @@ -2,6 +2,7 @@ ccflags-y := -Iinclude/drm
>
>  obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
>  obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
> +obj-$(CONFIG_DRM_LVDS_ENCODER) += lvds-encoder.o
>  obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
>  obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
>  obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
> diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c b/drivers/gpu/drm/bridge/lvds-encoder.c
> new file mode 100644
> index 000000000000..33e8025c8a6d
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/lvds-encoder.c
> @@ -0,0 +1,203 @@
> +/*
> + * Copyright (C) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_connector.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
> +#include <drm/drm_modeset_helper_vtables.h>
> +
> +#include <linux/of_graph.h>
> +
> +#include <video/display_timing.h>
> +#include <video/of_display_timing.h>
> +#include <video/videomode.h>
> +
> +struct lvds_encoder {
> +	struct device *dev;
> +
> +	struct drm_bridge bridge;
> +	struct drm_connector connector;
> +
> +	struct {
> +		unsigned int width_mm;
> +		unsigned int height_mm;
> +		struct videomode mode;
> +	} panel;

I don't see why we need create our own panel instance
in the encoder driver. We should use the drm_panel
API here rather than managing panel specific stuff in
this driver.

The parade-ps8622 and nxp-ptn3460 bridge drivers already
do this.

Thanks,
Archit

> +};
> +
> +static inline struct lvds_encoder *
> +drm_bridge_to_lvds_encoder(struct drm_bridge *bridge)
> +{
> +	return container_of(bridge, struct lvds_encoder, bridge);
> +}
> +
> +static inline struct lvds_encoder *
> +drm_connector_to_lvds_encoder(struct drm_connector *connector)
> +{
> +	return container_of(connector, struct lvds_encoder, connector);
> +}
> +
> +static int lvds_connector_get_modes(struct drm_connector *connector)
> +{
> +	struct lvds_encoder *lvds = drm_connector_to_lvds_encoder(connector);
> +	struct drm_display_mode *mode;
> +
> +	mode = drm_mode_create(connector->dev);
> +	if (mode == NULL)
> +		return 0;
> +
> +	mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
> +
> +	drm_display_mode_from_videomode(&lvds->panel.mode, mode);
> +
> +	drm_mode_probed_add(connector, mode);
> +
> +	return 1;
> +}
> +
> +static const struct drm_connector_helper_funcs lvds_connector_helper_funcs = {
> +	.get_modes = lvds_connector_get_modes,
> +};
> +
> +static enum drm_connector_status
> +lvds_connector_detect(struct drm_connector *connector, bool force)
> +{
> +	return connector_status_connected;
> +}
> +
> +static const struct drm_connector_funcs lvds_connector_funcs = {
> +	.dpms = drm_atomic_helper_connector_dpms,
> +	.reset = drm_atomic_helper_connector_reset,
> +	.detect = lvds_connector_detect,
> +	.fill_modes = drm_helper_probe_single_connector_modes,
> +	.destroy = drm_connector_cleanup,
> +	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static int lvds_encoder_attach(struct drm_bridge *bridge)
> +{
> +	struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge);
> +	struct drm_connector *connector = &lvds->connector;
> +	int ret;
> +
> +	if (!bridge->encoder) {
> +		DRM_ERROR("Missing encoder\n");
> +		return -ENODEV;
> +	}
> +
> +	connector->display_info.width_mm = lvds->panel.width_mm;
> +	connector->display_info.height_mm = lvds->panel.height_mm;
> +
> +	drm_connector_helper_add(connector, &lvds_connector_helper_funcs);
> +
> +	ret = drm_connector_init(bridge->dev, connector, &lvds_connector_funcs,
> +				 DRM_MODE_CONNECTOR_LVDS);
> +	if (ret) {
> +		DRM_ERROR("Failed to initialize connector\n");
> +		return ret;
> +	}
> +
> +	drm_mode_connector_attach_encoder(&lvds->connector, bridge->encoder);
> +
> +	return 0;
> +}
> +
> +static const struct drm_bridge_funcs lvds_encoder_bridge_funcs = {
> +	.attach = lvds_encoder_attach,
> +};
> +
> +static int lvds_encoder_probe(struct platform_device *pdev)
> +{
> +	struct lvds_encoder *lvds;
> +	struct display_timing timing;
> +	struct device_node *port;
> +	struct device_node *endpoint;
> +	struct device_node *panel;
> +	int ret;
> +
> +	lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL);
> +	if (!lvds)
> +		return -ENOMEM;
> +
> +	lvds->dev = &pdev->dev;
> +	platform_set_drvdata(pdev, lvds);
> +
> +	lvds->bridge.funcs = &lvds_encoder_bridge_funcs;
> +	lvds->bridge.of_node = pdev->dev.of_node;
> +	lvds->bridge.encoder_type = DRM_MODE_ENCODER_LVDS;
> +
> +	/* Locate the panel DT node. */
> +	port = of_graph_get_port_by_id(pdev->dev.of_node, 1);
> +	if (!port) {
> +		dev_dbg(&pdev->dev, "port 1 not found\n");
> +		return -ENXIO;
> +	}
> +
> +	endpoint = of_get_child_by_name(port, "endpoint");
> +	of_node_put(port);
> +	if (!endpoint) {
> +		dev_dbg(&pdev->dev, "no endpoint for port 1\n");
> +		return -ENXIO;
> +	}
> +
> +	panel = of_graph_get_remote_port_parent(endpoint);
> +	of_node_put(endpoint);
> +	if (!panel) {
> +		dev_dbg(&pdev->dev, "no remote endpoint for port 1\n");
> +		return -ENXIO;
> +	}
> +
> +	/* Parse and store panel information. */
> +	ret = of_get_display_timing(panel, "panel-timing", &timing);
> +	of_node_put(panel);
> +	if (ret < 0) {
> +		dev_dbg(&pdev->dev, "unable to parse panel timings\n");
> +		return ret;
> +	}
> +
> +	videomode_from_timing(&timing, &lvds->panel.mode);
> +
> +	of_property_read_u32(panel, "width-mm", &lvds->panel.width_mm);
> +	of_property_read_u32(panel, "height-mm", &lvds->panel.height_mm);
> +
> +	/* Register the bridge. */
> +	return drm_bridge_add(&lvds->bridge);
> +}
> +
> +static int lvds_encoder_remove(struct platform_device *pdev)
> +{
> +	struct lvds_encoder *encoder = platform_get_drvdata(pdev);
> +
> +	drm_bridge_remove(&encoder->bridge);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id lvds_encoder_match[] = {
> +	{ .compatible = "lvds-encoder" },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, lvds_encoder_match);
> +
> +struct platform_driver lvds_encoder_driver = {
> +	.probe	= lvds_encoder_probe,
> +	.remove	= lvds_encoder_remove,
> +	.driver		= {
> +		.name		= "lvds-encoder",
> +		.of_match_table	= lvds_encoder_match,
> +	},
> +};
> +module_platform_driver(lvds_encoder_driver);
> +
> +MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
> +MODULE_DESCRIPTION("Transparent parallel to LVDS encoder");
> +MODULE_LICENSE("GPL");
>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH 1/8] drm: bridge: Add LVDS encoder driver
  2016-10-21  5:21   ` Archit Taneja
@ 2016-10-21 10:21       ` Laurent Pinchart
  0 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2016-10-21 10:21 UTC (permalink / raw)
  To: Archit Taneja; +Cc: linux-renesas-soc, devicetree, Laurent Pinchart, dri-devel

Hi Archit,

On Friday 21 Oct 2016 10:51:59 Archit Taneja wrote:
> On 10/19/2016 07:55 PM, Laurent Pinchart wrote:
> > The LVDS encoder driver is a DRM bridge driver that supports the
> > parallel to LVDS encoders that don't require any configuration. The
> > driver thus doesn't interact with the device, but creates an LVDS
> > connector for the panel and exposes its size and timing based on
> > information retrieved from DT.
> > 
> > Cc: devicetree@vger.kernel.org
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  .../bindings/display/bridge/lvds-transmitter.txt   |  64 +++++++
> >  drivers/gpu/drm/bridge/Kconfig                     |   8 +
> >  drivers/gpu/drm/bridge/Makefile                    |   1 +
> >  drivers/gpu/drm/bridge/lvds-encoder.c              | 203 ++++++++++++++++
> >  4 files changed, 276 insertions(+)
> >  create mode 100644
> >  Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
> >  create mode 100644 drivers/gpu/drm/bridge/lvds-encoder.c
> > 
> > diff --git
> > a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
> > b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
> > new file mode 100644
> > index 000000000000..fd39ad34c383
> > --- /dev/null
> > +++
> > b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
> > @@ -0,0 +1,64 @@
> > +Parallel to LVDS Encoder
> > +------------------------
> > +
> > +This binding supports the parallel to LVDS encoders that don't require
> > any
> > +configuration.
> > +
> > +LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A.
> > Multiple +incompatible data link layers have been used over time to
> > transmit image data +to LVDS panels. This binding targets devices
> > compatible with the following +specifications only.
> > +
> > +[JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999,
> > February
> > +1999 (Version 1.0), Japan Electronic Industry Development Association
> > (JEIDA) +[LDI] "Open LVDS Display Interface", May 1999 (Version 0.95),
> > National +Semiconductor
> > +[VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video
> > +Electronics Standards Association (VESA)
> > +
> > +Those devices have been marketed under the FPD-Link and FlatLink brand
> > names +among others.
> > +
> > +
> > +Required properties:
> > +
> > +- compatible: Must be "lvds-encoder"
> > +
> > +Required nodes:
> > +
> > +This device has two video ports. Their connections are modeled using the
> > OF +graph bindings specified in
> > Documentation/devicetree/bindings/graph.txt. +
> > +- Video port 0 for parallel input
> > +- Video port 1 for LVDS output
> > +
> > +
> > +Example
> > +-------
> > +
> > +lvds-encoder {
> > +	compatible = "lvds-encoder";
> > +	#address-cells = <1>;
> > +	#size-cells = <0>;
> > +
> > +	ports {
> > +		#address-cells = <1>;
> > +		#size-cells = <0>;
> > +
> > +		port@0 {
> > +			reg = <0>;
> > +
> > +			lvds_enc_in: endpoint {
> > +				remote-endpoint = <&display_out_rgb>;
> > +			};
> > +		};
> > +
> > +		port@1 {
> > +			reg = <1>;
> > +
> > +			lvds_enc_out: endpoint {
> > +				remote-endpoint = <&lvds_panel_in>;
> > +			};
> > +		};
> > +	};
> > +};
> > diff --git a/drivers/gpu/drm/bridge/Kconfig
> > b/drivers/gpu/drm/bridge/Kconfig index 10e12e74fc9f..5dafad7817ad 100644
> > --- a/drivers/gpu/drm/bridge/Kconfig
> > +++ b/drivers/gpu/drm/bridge/Kconfig
> > @@ -24,6 +24,14 @@ config DRM_DUMB_VGA_DAC
> > 
> >  	help
> >  	
> >  	  Support for RGB to VGA DAC based bridges
> > 
> > +config DRM_LVDS_ENCODER
> > +	tristate "Transparent parallel to LVDS encoder support"
> > +	depends on OF
> > +	select DRM_KMS_HELPER
> > +	help
> > +	  Support for transparent parallel to LVDS encoders that don't require
> > +	  any configuration.
> > +
> > 
> >  config DRM_DW_HDMI
> >  
> >  	tristate
> >  	select DRM_KMS_HELPER
> > 
> > diff --git a/drivers/gpu/drm/bridge/Makefile
> > b/drivers/gpu/drm/bridge/Makefile index cdf3a3cf765d..bbaf583581ac 100644
> > --- a/drivers/gpu/drm/bridge/Makefile
> > +++ b/drivers/gpu/drm/bridge/Makefile
> > @@ -2,6 +2,7 @@ ccflags-y := -Iinclude/drm
> > 
> >  obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
> >  obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
> > 
> > +obj-$(CONFIG_DRM_LVDS_ENCODER) += lvds-encoder.o
> > 
> >  obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
> >  obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
> >  obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
> > 
> > diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c
> > b/drivers/gpu/drm/bridge/lvds-encoder.c new file mode 100644
> > index 000000000000..33e8025c8a6d
> > --- /dev/null
> > +++ b/drivers/gpu/drm/bridge/lvds-encoder.c
> > @@ -0,0 +1,203 @@
> > +/*
> > + * Copyright (C) 2016 Laurent Pinchart
> > <laurent.pinchart@ideasonboard.com>
> > + *
> > + * This program is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU General Public License as
> > + * published by the Free Software Foundation; either version 2 of
> > + * the License, or (at your option) any later version.
> > + */
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_atomic_helper.h>
> > +#include <drm/drm_connector.h>
> > +#include <drm/drm_crtc_helper.h>
> > +#include <drm/drm_encoder.h>
> > +#include <drm/drm_modeset_helper_vtables.h>
> > +
> > +#include <linux/of_graph.h>
> > +
> > +#include <video/display_timing.h>
> > +#include <video/of_display_timing.h>
> > +#include <video/videomode.h>
> > +
> > +struct lvds_encoder {
> > +	struct device *dev;
> > +
> > +	struct drm_bridge bridge;
> > +	struct drm_connector connector;
> > +
> > +	struct {
> > +		unsigned int width_mm;
> > +		unsigned int height_mm;
> > +		struct videomode mode;
> > +	} panel;
> 
> I don't see why we need create our own panel instance
> in the encoder driver. We should use the drm_panel
> API here rather than managing panel specific stuff in
> this driver.

It's not a panel instance but a structure that holds information about the 
connected panel. This is temporary until the LVDS panel DT bindings I've 
submitted get accepted.

> The parade-ps8622 and nxp-ptn3460 bridge drivers already
> do this.
> 
> Thanks,
> Archit
> 
> > +};
> > +
> > +static inline struct lvds_encoder *
> > +drm_bridge_to_lvds_encoder(struct drm_bridge *bridge)
> > +{
> > +	return container_of(bridge, struct lvds_encoder, bridge);
> > +}
> > +
> > +static inline struct lvds_encoder *
> > +drm_connector_to_lvds_encoder(struct drm_connector *connector)
> > +{
> > +	return container_of(connector, struct lvds_encoder, connector);
> > +}
> > +
> > +static int lvds_connector_get_modes(struct drm_connector *connector)
> > +{
> > +	struct lvds_encoder *lvds = drm_connector_to_lvds_encoder(connector);
> > +	struct drm_display_mode *mode;
> > +
> > +	mode = drm_mode_create(connector->dev);
> > +	if (mode == NULL)
> > +		return 0;
> > +
> > +	mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
> > +
> > +	drm_display_mode_from_videomode(&lvds->panel.mode, mode);
> > +
> > +	drm_mode_probed_add(connector, mode);
> > +
> > +	return 1;
> > +}
> > +
> > +static const struct drm_connector_helper_funcs
> > lvds_connector_helper_funcs = { +	.get_modes = lvds_connector_get_modes,
> > +};
> > +
> > +static enum drm_connector_status
> > +lvds_connector_detect(struct drm_connector *connector, bool force)
> > +{
> > +	return connector_status_connected;
> > +}
> > +
> > +static const struct drm_connector_funcs lvds_connector_funcs = {
> > +	.dpms = drm_atomic_helper_connector_dpms,
> > +	.reset = drm_atomic_helper_connector_reset,
> > +	.detect = lvds_connector_detect,
> > +	.fill_modes = drm_helper_probe_single_connector_modes,
> > +	.destroy = drm_connector_cleanup,
> > +	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> > +	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> > +};
> > +
> > +static int lvds_encoder_attach(struct drm_bridge *bridge)
> > +{
> > +	struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge);
> > +	struct drm_connector *connector = &lvds->connector;
> > +	int ret;
> > +
> > +	if (!bridge->encoder) {
> > +		DRM_ERROR("Missing encoder\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	connector->display_info.width_mm = lvds->panel.width_mm;
> > +	connector->display_info.height_mm = lvds->panel.height_mm;
> > +
> > +	drm_connector_helper_add(connector, &lvds_connector_helper_funcs);
> > +
> > +	ret = drm_connector_init(bridge->dev, connector, 
&lvds_connector_funcs,
> > +				 DRM_MODE_CONNECTOR_LVDS);
> > +	if (ret) {
> > +		DRM_ERROR("Failed to initialize connector\n");
> > +		return ret;
> > +	}
> > +
> > +	drm_mode_connector_attach_encoder(&lvds->connector, bridge->encoder);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct drm_bridge_funcs lvds_encoder_bridge_funcs = {
> > +	.attach = lvds_encoder_attach,
> > +};
> > +
> > +static int lvds_encoder_probe(struct platform_device *pdev)
> > +{
> > +	struct lvds_encoder *lvds;
> > +	struct display_timing timing;
> > +	struct device_node *port;
> > +	struct device_node *endpoint;
> > +	struct device_node *panel;
> > +	int ret;
> > +
> > +	lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL);
> > +	if (!lvds)
> > +		return -ENOMEM;
> > +
> > +	lvds->dev = &pdev->dev;
> > +	platform_set_drvdata(pdev, lvds);
> > +
> > +	lvds->bridge.funcs = &lvds_encoder_bridge_funcs;
> > +	lvds->bridge.of_node = pdev->dev.of_node;
> > +	lvds->bridge.encoder_type = DRM_MODE_ENCODER_LVDS;
> > +
> > +	/* Locate the panel DT node. */
> > +	port = of_graph_get_port_by_id(pdev->dev.of_node, 1);
> > +	if (!port) {
> > +		dev_dbg(&pdev->dev, "port 1 not found\n");
> > +		return -ENXIO;
> > +	}
> > +
> > +	endpoint = of_get_child_by_name(port, "endpoint");
> > +	of_node_put(port);
> > +	if (!endpoint) {
> > +		dev_dbg(&pdev->dev, "no endpoint for port 1\n");
> > +		return -ENXIO;
> > +	}
> > +
> > +	panel = of_graph_get_remote_port_parent(endpoint);
> > +	of_node_put(endpoint);
> > +	if (!panel) {
> > +		dev_dbg(&pdev->dev, "no remote endpoint for port 1\n");
> > +		return -ENXIO;
> > +	}
> > +
> > +	/* Parse and store panel information. */
> > +	ret = of_get_display_timing(panel, "panel-timing", &timing);
> > +	of_node_put(panel);
> > +	if (ret < 0) {
> > +		dev_dbg(&pdev->dev, "unable to parse panel timings\n");
> > +		return ret;
> > +	}
> > +
> > +	videomode_from_timing(&timing, &lvds->panel.mode);
> > +
> > +	of_property_read_u32(panel, "width-mm", &lvds->panel.width_mm);
> > +	of_property_read_u32(panel, "height-mm", &lvds->panel.height_mm);
> > +
> > +	/* Register the bridge. */
> > +	return drm_bridge_add(&lvds->bridge);
> > +}
> > +
> > +static int lvds_encoder_remove(struct platform_device *pdev)
> > +{
> > +	struct lvds_encoder *encoder = platform_get_drvdata(pdev);
> > +
> > +	drm_bridge_remove(&encoder->bridge);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct of_device_id lvds_encoder_match[] = {
> > +	{ .compatible = "lvds-encoder" },
> > +	{},
> > +};
> > +MODULE_DEVICE_TABLE(of, lvds_encoder_match);
> > +
> > +struct platform_driver lvds_encoder_driver = {
> > +	.probe	= lvds_encoder_probe,
> > +	.remove	= lvds_encoder_remove,
> > +	.driver		= {
> > +		.name		= "lvds-encoder",
> > +		.of_match_table	= lvds_encoder_match,
> > +	},
> > +};
> > +module_platform_driver(lvds_encoder_driver);
> > +
> > +MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
> > +MODULE_DESCRIPTION("Transparent parallel to LVDS encoder");
> > +MODULE_LICENSE("GPL");

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 1/8] drm: bridge: Add LVDS encoder driver
@ 2016-10-21 10:21       ` Laurent Pinchart
  0 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2016-10-21 10:21 UTC (permalink / raw)
  To: Archit Taneja; +Cc: Laurent Pinchart, dri-devel, linux-renesas-soc, devicetree

Hi Archit,

On Friday 21 Oct 2016 10:51:59 Archit Taneja wrote:
> On 10/19/2016 07:55 PM, Laurent Pinchart wrote:
> > The LVDS encoder driver is a DRM bridge driver that supports the
> > parallel to LVDS encoders that don't require any configuration. The
> > driver thus doesn't interact with the device, but creates an LVDS
> > connector for the panel and exposes its size and timing based on
> > information retrieved from DT.
> > 
> > Cc: devicetree@vger.kernel.org
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  .../bindings/display/bridge/lvds-transmitter.txt   |  64 +++++++
> >  drivers/gpu/drm/bridge/Kconfig                     |   8 +
> >  drivers/gpu/drm/bridge/Makefile                    |   1 +
> >  drivers/gpu/drm/bridge/lvds-encoder.c              | 203 ++++++++++++++++
> >  4 files changed, 276 insertions(+)
> >  create mode 100644
> >  Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
> >  create mode 100644 drivers/gpu/drm/bridge/lvds-encoder.c
> > 
> > diff --git
> > a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
> > b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
> > new file mode 100644
> > index 000000000000..fd39ad34c383
> > --- /dev/null
> > +++
> > b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
> > @@ -0,0 +1,64 @@
> > +Parallel to LVDS Encoder
> > +------------------------
> > +
> > +This binding supports the parallel to LVDS encoders that don't require
> > any
> > +configuration.
> > +
> > +LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A.
> > Multiple +incompatible data link layers have been used over time to
> > transmit image data +to LVDS panels. This binding targets devices
> > compatible with the following +specifications only.
> > +
> > +[JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999,
> > February
> > +1999 (Version 1.0), Japan Electronic Industry Development Association
> > (JEIDA) +[LDI] "Open LVDS Display Interface", May 1999 (Version 0.95),
> > National +Semiconductor
> > +[VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video
> > +Electronics Standards Association (VESA)
> > +
> > +Those devices have been marketed under the FPD-Link and FlatLink brand
> > names +among others.
> > +
> > +
> > +Required properties:
> > +
> > +- compatible: Must be "lvds-encoder"
> > +
> > +Required nodes:
> > +
> > +This device has two video ports. Their connections are modeled using the
> > OF +graph bindings specified in
> > Documentation/devicetree/bindings/graph.txt. +
> > +- Video port 0 for parallel input
> > +- Video port 1 for LVDS output
> > +
> > +
> > +Example
> > +-------
> > +
> > +lvds-encoder {
> > +	compatible = "lvds-encoder";
> > +	#address-cells = <1>;
> > +	#size-cells = <0>;
> > +
> > +	ports {
> > +		#address-cells = <1>;
> > +		#size-cells = <0>;
> > +
> > +		port@0 {
> > +			reg = <0>;
> > +
> > +			lvds_enc_in: endpoint {
> > +				remote-endpoint = <&display_out_rgb>;
> > +			};
> > +		};
> > +
> > +		port@1 {
> > +			reg = <1>;
> > +
> > +			lvds_enc_out: endpoint {
> > +				remote-endpoint = <&lvds_panel_in>;
> > +			};
> > +		};
> > +	};
> > +};
> > diff --git a/drivers/gpu/drm/bridge/Kconfig
> > b/drivers/gpu/drm/bridge/Kconfig index 10e12e74fc9f..5dafad7817ad 100644
> > --- a/drivers/gpu/drm/bridge/Kconfig
> > +++ b/drivers/gpu/drm/bridge/Kconfig
> > @@ -24,6 +24,14 @@ config DRM_DUMB_VGA_DAC
> > 
> >  	help
> >  	
> >  	  Support for RGB to VGA DAC based bridges
> > 
> > +config DRM_LVDS_ENCODER
> > +	tristate "Transparent parallel to LVDS encoder support"
> > +	depends on OF
> > +	select DRM_KMS_HELPER
> > +	help
> > +	  Support for transparent parallel to LVDS encoders that don't require
> > +	  any configuration.
> > +
> > 
> >  config DRM_DW_HDMI
> >  
> >  	tristate
> >  	select DRM_KMS_HELPER
> > 
> > diff --git a/drivers/gpu/drm/bridge/Makefile
> > b/drivers/gpu/drm/bridge/Makefile index cdf3a3cf765d..bbaf583581ac 100644
> > --- a/drivers/gpu/drm/bridge/Makefile
> > +++ b/drivers/gpu/drm/bridge/Makefile
> > @@ -2,6 +2,7 @@ ccflags-y := -Iinclude/drm
> > 
> >  obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
> >  obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
> > 
> > +obj-$(CONFIG_DRM_LVDS_ENCODER) += lvds-encoder.o
> > 
> >  obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
> >  obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
> >  obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
> > 
> > diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c
> > b/drivers/gpu/drm/bridge/lvds-encoder.c new file mode 100644
> > index 000000000000..33e8025c8a6d
> > --- /dev/null
> > +++ b/drivers/gpu/drm/bridge/lvds-encoder.c
> > @@ -0,0 +1,203 @@
> > +/*
> > + * Copyright (C) 2016 Laurent Pinchart
> > <laurent.pinchart@ideasonboard.com>
> > + *
> > + * This program is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU General Public License as
> > + * published by the Free Software Foundation; either version 2 of
> > + * the License, or (at your option) any later version.
> > + */
> > +
> > +#include <drm/drmP.h>
> > +#include <drm/drm_atomic_helper.h>
> > +#include <drm/drm_connector.h>
> > +#include <drm/drm_crtc_helper.h>
> > +#include <drm/drm_encoder.h>
> > +#include <drm/drm_modeset_helper_vtables.h>
> > +
> > +#include <linux/of_graph.h>
> > +
> > +#include <video/display_timing.h>
> > +#include <video/of_display_timing.h>
> > +#include <video/videomode.h>
> > +
> > +struct lvds_encoder {
> > +	struct device *dev;
> > +
> > +	struct drm_bridge bridge;
> > +	struct drm_connector connector;
> > +
> > +	struct {
> > +		unsigned int width_mm;
> > +		unsigned int height_mm;
> > +		struct videomode mode;
> > +	} panel;
> 
> I don't see why we need create our own panel instance
> in the encoder driver. We should use the drm_panel
> API here rather than managing panel specific stuff in
> this driver.

It's not a panel instance but a structure that holds information about the 
connected panel. This is temporary until the LVDS panel DT bindings I've 
submitted get accepted.

> The parade-ps8622 and nxp-ptn3460 bridge drivers already
> do this.
> 
> Thanks,
> Archit
> 
> > +};
> > +
> > +static inline struct lvds_encoder *
> > +drm_bridge_to_lvds_encoder(struct drm_bridge *bridge)
> > +{
> > +	return container_of(bridge, struct lvds_encoder, bridge);
> > +}
> > +
> > +static inline struct lvds_encoder *
> > +drm_connector_to_lvds_encoder(struct drm_connector *connector)
> > +{
> > +	return container_of(connector, struct lvds_encoder, connector);
> > +}
> > +
> > +static int lvds_connector_get_modes(struct drm_connector *connector)
> > +{
> > +	struct lvds_encoder *lvds = drm_connector_to_lvds_encoder(connector);
> > +	struct drm_display_mode *mode;
> > +
> > +	mode = drm_mode_create(connector->dev);
> > +	if (mode == NULL)
> > +		return 0;
> > +
> > +	mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
> > +
> > +	drm_display_mode_from_videomode(&lvds->panel.mode, mode);
> > +
> > +	drm_mode_probed_add(connector, mode);
> > +
> > +	return 1;
> > +}
> > +
> > +static const struct drm_connector_helper_funcs
> > lvds_connector_helper_funcs = { +	.get_modes = lvds_connector_get_modes,
> > +};
> > +
> > +static enum drm_connector_status
> > +lvds_connector_detect(struct drm_connector *connector, bool force)
> > +{
> > +	return connector_status_connected;
> > +}
> > +
> > +static const struct drm_connector_funcs lvds_connector_funcs = {
> > +	.dpms = drm_atomic_helper_connector_dpms,
> > +	.reset = drm_atomic_helper_connector_reset,
> > +	.detect = lvds_connector_detect,
> > +	.fill_modes = drm_helper_probe_single_connector_modes,
> > +	.destroy = drm_connector_cleanup,
> > +	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> > +	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> > +};
> > +
> > +static int lvds_encoder_attach(struct drm_bridge *bridge)
> > +{
> > +	struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge);
> > +	struct drm_connector *connector = &lvds->connector;
> > +	int ret;
> > +
> > +	if (!bridge->encoder) {
> > +		DRM_ERROR("Missing encoder\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	connector->display_info.width_mm = lvds->panel.width_mm;
> > +	connector->display_info.height_mm = lvds->panel.height_mm;
> > +
> > +	drm_connector_helper_add(connector, &lvds_connector_helper_funcs);
> > +
> > +	ret = drm_connector_init(bridge->dev, connector, 
&lvds_connector_funcs,
> > +				 DRM_MODE_CONNECTOR_LVDS);
> > +	if (ret) {
> > +		DRM_ERROR("Failed to initialize connector\n");
> > +		return ret;
> > +	}
> > +
> > +	drm_mode_connector_attach_encoder(&lvds->connector, bridge->encoder);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct drm_bridge_funcs lvds_encoder_bridge_funcs = {
> > +	.attach = lvds_encoder_attach,
> > +};
> > +
> > +static int lvds_encoder_probe(struct platform_device *pdev)
> > +{
> > +	struct lvds_encoder *lvds;
> > +	struct display_timing timing;
> > +	struct device_node *port;
> > +	struct device_node *endpoint;
> > +	struct device_node *panel;
> > +	int ret;
> > +
> > +	lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL);
> > +	if (!lvds)
> > +		return -ENOMEM;
> > +
> > +	lvds->dev = &pdev->dev;
> > +	platform_set_drvdata(pdev, lvds);
> > +
> > +	lvds->bridge.funcs = &lvds_encoder_bridge_funcs;
> > +	lvds->bridge.of_node = pdev->dev.of_node;
> > +	lvds->bridge.encoder_type = DRM_MODE_ENCODER_LVDS;
> > +
> > +	/* Locate the panel DT node. */
> > +	port = of_graph_get_port_by_id(pdev->dev.of_node, 1);
> > +	if (!port) {
> > +		dev_dbg(&pdev->dev, "port 1 not found\n");
> > +		return -ENXIO;
> > +	}
> > +
> > +	endpoint = of_get_child_by_name(port, "endpoint");
> > +	of_node_put(port);
> > +	if (!endpoint) {
> > +		dev_dbg(&pdev->dev, "no endpoint for port 1\n");
> > +		return -ENXIO;
> > +	}
> > +
> > +	panel = of_graph_get_remote_port_parent(endpoint);
> > +	of_node_put(endpoint);
> > +	if (!panel) {
> > +		dev_dbg(&pdev->dev, "no remote endpoint for port 1\n");
> > +		return -ENXIO;
> > +	}
> > +
> > +	/* Parse and store panel information. */
> > +	ret = of_get_display_timing(panel, "panel-timing", &timing);
> > +	of_node_put(panel);
> > +	if (ret < 0) {
> > +		dev_dbg(&pdev->dev, "unable to parse panel timings\n");
> > +		return ret;
> > +	}
> > +
> > +	videomode_from_timing(&timing, &lvds->panel.mode);
> > +
> > +	of_property_read_u32(panel, "width-mm", &lvds->panel.width_mm);
> > +	of_property_read_u32(panel, "height-mm", &lvds->panel.height_mm);
> > +
> > +	/* Register the bridge. */
> > +	return drm_bridge_add(&lvds->bridge);
> > +}
> > +
> > +static int lvds_encoder_remove(struct platform_device *pdev)
> > +{
> > +	struct lvds_encoder *encoder = platform_get_drvdata(pdev);
> > +
> > +	drm_bridge_remove(&encoder->bridge);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct of_device_id lvds_encoder_match[] = {
> > +	{ .compatible = "lvds-encoder" },
> > +	{},
> > +};
> > +MODULE_DEVICE_TABLE(of, lvds_encoder_match);
> > +
> > +struct platform_driver lvds_encoder_driver = {
> > +	.probe	= lvds_encoder_probe,
> > +	.remove	= lvds_encoder_remove,
> > +	.driver		= {
> > +		.name		= "lvds-encoder",
> > +		.of_match_table	= lvds_encoder_match,
> > +	},
> > +};
> > +module_platform_driver(lvds_encoder_driver);
> > +
> > +MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
> > +MODULE_DESCRIPTION("Transparent parallel to LVDS encoder");
> > +MODULE_LICENSE("GPL");

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 2/8] drm: bridge: vga-dac: Add adi,adv7123 compatible string
  2016-10-21  5:13     ` Archit Taneja
  (?)
@ 2016-10-21 10:22     ` Laurent Pinchart
  2016-10-21 10:43         ` Archit Taneja
  -1 siblings, 1 reply; 26+ messages in thread
From: Laurent Pinchart @ 2016-10-21 10:22 UTC (permalink / raw)
  To: Archit Taneja; +Cc: Laurent Pinchart, dri-devel, linux-renesas-soc, devicetree

Hi Archit,

On Friday 21 Oct 2016 10:43:34 Archit Taneja wrote:
> On 10/19/2016 07:55 PM, Laurent Pinchart wrote:
> > The ADV7123 is a transparent VGA DAC. Unlike dumb VGA DACs it can be
> > controlled through a power save pin, and requires a power supply.
> > However, on most boards where the device is used neither the power save
> > signal nor the power supply are controllable.
> > 
> > To avoid developing a separate device-specific driver add an
> > "adi,adv7123" compatible entry to the dumb-vga-dac driver. This will
> > allow supporting most ADV7123-based boards easily, while allowing future
> > development of an adv7123 driver when needed without breaking backward
> > compatibility.
> 
> Shouldn't we have a DT binding doc for ADV7123, even if it's sharing
> the dumb vga driver for now?

Documentation/devicetree/bindings/display/bridge/adi,adv7123.txt

> Same query for the Thine LVDS encoder.

Documentation/devicetree/bindings/display/bridge/thine,thc63lvdm83d.txt

> > Cc: devicetree@vger.kernel.org
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/bridge/dumb-vga-dac.c | 1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c
> > b/drivers/gpu/drm/bridge/dumb-vga-dac.c index afec232185a7..b33e3f829e4f
> > 100644
> > --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
> > +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
> > @@ -204,6 +204,7 @@ static int dumb_vga_remove(struct platform_device
> > *pdev)> 
> >  static const struct of_device_id dumb_vga_match[] = {
> >  
> >  	{ .compatible = "dumb-vga-dac" },
> > +	{ .compatible = "adi,adv7123" },
> >  	{},
> >  };
> >  MODULE_DEVICE_TABLE(of, dumb_vga_match);

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 2/8] drm: bridge: vga-dac: Add adi,adv7123 compatible string
  2016-10-21 10:22     ` Laurent Pinchart
@ 2016-10-21 10:43         ` Archit Taneja
  0 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2016-10-21 10:43 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Laurent Pinchart, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA



On 10/21/2016 03:52 PM, Laurent Pinchart wrote:
> Hi Archit,
>
> On Friday 21 Oct 2016 10:43:34 Archit Taneja wrote:
>> On 10/19/2016 07:55 PM, Laurent Pinchart wrote:
>>> The ADV7123 is a transparent VGA DAC. Unlike dumb VGA DACs it can be
>>> controlled through a power save pin, and requires a power supply.
>>> However, on most boards where the device is used neither the power save
>>> signal nor the power supply are controllable.
>>>
>>> To avoid developing a separate device-specific driver add an
>>> "adi,adv7123" compatible entry to the dumb-vga-dac driver. This will
>>> allow supporting most ADV7123-based boards easily, while allowing future
>>> development of an adv7123 driver when needed without breaking backward
>>> compatibility.
>>
>> Shouldn't we have a DT binding doc for ADV7123, even if it's sharing
>> the dumb vga driver for now?
>
> Documentation/devicetree/bindings/display/bridge/adi,adv7123.txt
>
>> Same query for the Thine LVDS encoder.
>
> Documentation/devicetree/bindings/display/bridge/thine,thc63lvdm83d.txt

Cool, didn't know these already existed :)

Thanks,
Archit

>
>>> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>>> Signed-off-by: Laurent Pinchart
>>> <laurent.pinchart+renesas-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org>
>>> ---
>>>
>>>  drivers/gpu/drm/bridge/dumb-vga-dac.c | 1 +
>>>  1 file changed, 1 insertion(+)
>>>
>>> diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c
>>> b/drivers/gpu/drm/bridge/dumb-vga-dac.c index afec232185a7..b33e3f829e4f
>>> 100644
>>> --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
>>> +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
>>> @@ -204,6 +204,7 @@ static int dumb_vga_remove(struct platform_device
>>> *pdev)>
>>>  static const struct of_device_id dumb_vga_match[] = {
>>>
>>>  	{ .compatible = "dumb-vga-dac" },
>>> +	{ .compatible = "adi,adv7123" },
>>>  	{},
>>>  };
>>>  MODULE_DEVICE_TABLE(of, dumb_vga_match);
>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 2/8] drm: bridge: vga-dac: Add adi,adv7123 compatible string
@ 2016-10-21 10:43         ` Archit Taneja
  0 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2016-10-21 10:43 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Laurent Pinchart, dri-devel, linux-renesas-soc, devicetree



On 10/21/2016 03:52 PM, Laurent Pinchart wrote:
> Hi Archit,
>
> On Friday 21 Oct 2016 10:43:34 Archit Taneja wrote:
>> On 10/19/2016 07:55 PM, Laurent Pinchart wrote:
>>> The ADV7123 is a transparent VGA DAC. Unlike dumb VGA DACs it can be
>>> controlled through a power save pin, and requires a power supply.
>>> However, on most boards where the device is used neither the power save
>>> signal nor the power supply are controllable.
>>>
>>> To avoid developing a separate device-specific driver add an
>>> "adi,adv7123" compatible entry to the dumb-vga-dac driver. This will
>>> allow supporting most ADV7123-based boards easily, while allowing future
>>> development of an adv7123 driver when needed without breaking backward
>>> compatibility.
>>
>> Shouldn't we have a DT binding doc for ADV7123, even if it's sharing
>> the dumb vga driver for now?
>
> Documentation/devicetree/bindings/display/bridge/adi,adv7123.txt
>
>> Same query for the Thine LVDS encoder.
>
> Documentation/devicetree/bindings/display/bridge/thine,thc63lvdm83d.txt

Cool, didn't know these already existed :)

Thanks,
Archit

>
>>> Cc: devicetree@vger.kernel.org
>>> Signed-off-by: Laurent Pinchart
>>> <laurent.pinchart+renesas@ideasonboard.com>
>>> ---
>>>
>>>  drivers/gpu/drm/bridge/dumb-vga-dac.c | 1 +
>>>  1 file changed, 1 insertion(+)
>>>
>>> diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c
>>> b/drivers/gpu/drm/bridge/dumb-vga-dac.c index afec232185a7..b33e3f829e4f
>>> 100644
>>> --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
>>> +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
>>> @@ -204,6 +204,7 @@ static int dumb_vga_remove(struct platform_device
>>> *pdev)>
>>>  static const struct of_device_id dumb_vga_match[] = {
>>>
>>>  	{ .compatible = "dumb-vga-dac" },
>>> +	{ .compatible = "adi,adv7123" },
>>>  	{},
>>>  };
>>>  MODULE_DEVICE_TABLE(of, dumb_vga_match);
>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH 1/8] drm: bridge: Add LVDS encoder driver
  2016-10-19 14:25 ` [PATCH 1/8] drm: bridge: Add LVDS encoder driver Laurent Pinchart
@ 2016-10-26 21:32     ` Rob Herring
  2016-10-26 21:32     ` Rob Herring
  1 sibling, 0 replies; 26+ messages in thread
From: Rob Herring @ 2016-10-26 21:32 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-renesas-soc, devicetree, dri-devel

On Wed, Oct 19, 2016 at 05:25:36PM +0300, Laurent Pinchart wrote:
> The LVDS encoder driver is a DRM bridge driver that supports the
> parallel to LVDS encoders that don't require any configuration. The
> driver thus doesn't interact with the device, but creates an LVDS
> connector for the panel and exposes its size and timing based on
> information retrieved from DT.
> 
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  .../bindings/display/bridge/lvds-transmitter.txt   |  64 +++++++

It's preferred that bindings are separate patches. That makes the 
filtered DT only repo commits more sane.

Acked-by: Rob Herring <robh@kernel.org>

>  drivers/gpu/drm/bridge/Kconfig                     |   8 +
>  drivers/gpu/drm/bridge/Makefile                    |   1 +
>  drivers/gpu/drm/bridge/lvds-encoder.c              | 203 +++++++++++++++++++++
>  4 files changed, 276 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
>  create mode 100644 drivers/gpu/drm/bridge/lvds-encoder.c
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 1/8] drm: bridge: Add LVDS encoder driver
@ 2016-10-26 21:32     ` Rob Herring
  0 siblings, 0 replies; 26+ messages in thread
From: Rob Herring @ 2016-10-26 21:32 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel, linux-renesas-soc, devicetree

On Wed, Oct 19, 2016 at 05:25:36PM +0300, Laurent Pinchart wrote:
> The LVDS encoder driver is a DRM bridge driver that supports the
> parallel to LVDS encoders that don't require any configuration. The
> driver thus doesn't interact with the device, but creates an LVDS
> connector for the panel and exposes its size and timing based on
> information retrieved from DT.
> 
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  .../bindings/display/bridge/lvds-transmitter.txt   |  64 +++++++

It's preferred that bindings are separate patches. That makes the 
filtered DT only repo commits more sane.

Acked-by: Rob Herring <robh@kernel.org>

>  drivers/gpu/drm/bridge/Kconfig                     |   8 +
>  drivers/gpu/drm/bridge/Makefile                    |   1 +
>  drivers/gpu/drm/bridge/lvds-encoder.c              | 203 +++++++++++++++++++++
>  4 files changed, 276 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
>  create mode 100644 drivers/gpu/drm/bridge/lvds-encoder.c

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

* [PATCH 1/8] drm: bridge: Add LVDS encoder driver
  2016-10-19 14:07 [PATCH 0/8] R-Car DU: Use drm bridge API Laurent Pinchart
@ 2016-10-19 14:07 ` Laurent Pinchart
  0 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2016-10-19 14:07 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

The LVDS encoder driver is a DRM bridge driver that supports the
parallel to LVDS encoders that don't require any configuration. The
driver thus doesn't interact with the device, but creates an LVDS
connector for the panel and exposes its size and timing based on
information retrieved from DT.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 .../bindings/display/bridge/lvds-transmitter.txt   |  64 +++++++
 drivers/gpu/drm/bridge/Kconfig                     |   8 +
 drivers/gpu/drm/bridge/Makefile                    |   1 +
 drivers/gpu/drm/bridge/lvds-encoder.c              | 203 +++++++++++++++++++++
 4 files changed, 276 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
 create mode 100644 drivers/gpu/drm/bridge/lvds-encoder.c

diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
new file mode 100644
index 000000000000..fd39ad34c383
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
@@ -0,0 +1,64 @@
+Parallel to LVDS Encoder
+------------------------
+
+This binding supports the parallel to LVDS encoders that don't require any
+configuration.
+
+LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A. Multiple
+incompatible data link layers have been used over time to transmit image data
+to LVDS panels. This binding targets devices compatible with the following
+specifications only.
+
+[JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999, February
+1999 (Version 1.0), Japan Electronic Industry Development Association (JEIDA)
+[LDI] "Open LVDS Display Interface", May 1999 (Version 0.95), National
+Semiconductor
+[VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video
+Electronics Standards Association (VESA)
+
+Those devices have been marketed under the FPD-Link and FlatLink brand names
+among others.
+
+
+Required properties:
+
+- compatible: Must be "lvds-encoder"
+
+Required nodes:
+
+This device has two video ports. Their connections are modeled using the OF
+graph bindings specified in Documentation/devicetree/bindings/graph.txt.
+
+- Video port 0 for parallel input
+- Video port 1 for LVDS output
+
+
+Example
+-------
+
+lvds-encoder {
+	compatible = "lvds-encoder";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+
+			lvds_enc_in: endpoint {
+				remote-endpoint = <&display_out_rgb>;
+			};
+		};
+
+		port@1 {
+			reg = <1>;
+
+			lvds_enc_out: endpoint {
+				remote-endpoint = <&lvds_panel_in>;
+			};
+		};
+	};
+};
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 10e12e74fc9f..5dafad7817ad 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -24,6 +24,14 @@ config DRM_DUMB_VGA_DAC
 	help
 	  Support for RGB to VGA DAC based bridges
 
+config DRM_LVDS_ENCODER
+	tristate "Transparent parallel to LVDS encoder support"
+	depends on OF
+	select DRM_KMS_HELPER
+	help
+	  Support for transparent parallel to LVDS encoders that don't require
+	  any configuration.
+
 config DRM_DW_HDMI
 	tristate
 	select DRM_KMS_HELPER
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index cdf3a3cf765d..bbaf583581ac 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -2,6 +2,7 @@ ccflags-y := -Iinclude/drm
 
 obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
 obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
+obj-$(CONFIG_DRM_LVDS_ENCODER) += lvds-encoder.o
 obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
 obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c b/drivers/gpu/drm/bridge/lvds-encoder.c
new file mode 100644
index 000000000000..33e8025c8a6d
--- /dev/null
+++ b/drivers/gpu/drm/bridge/lvds-encoder.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder.h>
+#include <drm/drm_modeset_helper_vtables.h>
+
+#include <linux/of_graph.h>
+
+#include <video/display_timing.h>
+#include <video/of_display_timing.h>
+#include <video/videomode.h>
+
+struct lvds_encoder {
+	struct device *dev;
+
+	struct drm_bridge bridge;
+	struct drm_connector connector;
+
+	struct {
+		unsigned int width_mm;
+		unsigned int height_mm;
+		struct videomode mode;
+	} panel;
+};
+
+static inline struct lvds_encoder *
+drm_bridge_to_lvds_encoder(struct drm_bridge *bridge)
+{
+	return container_of(bridge, struct lvds_encoder, bridge);
+}
+
+static inline struct lvds_encoder *
+drm_connector_to_lvds_encoder(struct drm_connector *connector)
+{
+	return container_of(connector, struct lvds_encoder, connector);
+}
+
+static int lvds_connector_get_modes(struct drm_connector *connector)
+{
+	struct lvds_encoder *lvds = drm_connector_to_lvds_encoder(connector);
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_create(connector->dev);
+	if (mode == NULL)
+		return 0;
+
+	mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
+
+	drm_display_mode_from_videomode(&lvds->panel.mode, mode);
+
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_connector_helper_funcs lvds_connector_helper_funcs = {
+	.get_modes = lvds_connector_get_modes,
+};
+
+static enum drm_connector_status
+lvds_connector_detect(struct drm_connector *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+static const struct drm_connector_funcs lvds_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.reset = drm_atomic_helper_connector_reset,
+	.detect = lvds_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = drm_connector_cleanup,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int lvds_encoder_attach(struct drm_bridge *bridge)
+{
+	struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge);
+	struct drm_connector *connector = &lvds->connector;
+	int ret;
+
+	if (!bridge->encoder) {
+		DRM_ERROR("Missing encoder\n");
+		return -ENODEV;
+	}
+
+	connector->display_info.width_mm = lvds->panel.width_mm;
+	connector->display_info.height_mm = lvds->panel.height_mm;
+
+	drm_connector_helper_add(connector, &lvds_connector_helper_funcs);
+
+	ret = drm_connector_init(bridge->dev, connector, &lvds_connector_funcs,
+				 DRM_MODE_CONNECTOR_LVDS);
+	if (ret) {
+		DRM_ERROR("Failed to initialize connector\n");
+		return ret;
+	}
+
+	drm_mode_connector_attach_encoder(&lvds->connector, bridge->encoder);
+
+	return 0;
+}
+
+static const struct drm_bridge_funcs lvds_encoder_bridge_funcs = {
+	.attach = lvds_encoder_attach,
+};
+
+static int lvds_encoder_probe(struct platform_device *pdev)
+{
+	struct lvds_encoder *lvds;
+	struct display_timing timing;
+	struct device_node *port;
+	struct device_node *endpoint;
+	struct device_node *panel;
+	int ret;
+
+	lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL);
+	if (!lvds)
+		return -ENOMEM;
+
+	lvds->dev = &pdev->dev;
+	platform_set_drvdata(pdev, lvds);
+
+	lvds->bridge.funcs = &lvds_encoder_bridge_funcs;
+	lvds->bridge.of_node = pdev->dev.of_node;
+	lvds->bridge.encoder_type = DRM_MODE_ENCODER_LVDS;
+
+	/* Locate the panel DT node. */
+	port = of_graph_get_port_by_id(pdev->dev.of_node, 1);
+	if (!port) {
+		dev_dbg(&pdev->dev, "port 1 not found\n");
+		return -ENXIO;
+	}
+
+	endpoint = of_get_child_by_name(port, "endpoint");
+	of_node_put(port);
+	if (!endpoint) {
+		dev_dbg(&pdev->dev, "no endpoint for port 1\n");
+		return -ENXIO;
+	}
+
+	panel = of_graph_get_remote_port_parent(endpoint);
+	of_node_put(endpoint);
+	if (!panel) {
+		dev_dbg(&pdev->dev, "no remote endpoint for port 1\n");
+		return -ENXIO;
+	}
+
+	/* Parse and store panel information. */
+	ret = of_get_display_timing(panel, "panel-timing", &timing);
+	of_node_put(panel);
+	if (ret < 0) {
+		dev_dbg(&pdev->dev, "unable to parse panel timings\n");
+		return ret;
+	}
+
+	videomode_from_timing(&timing, &lvds->panel.mode);
+
+	of_property_read_u32(panel, "width-mm", &lvds->panel.width_mm);
+	of_property_read_u32(panel, "height-mm", &lvds->panel.height_mm);
+
+	/* Register the bridge. */
+	return drm_bridge_add(&lvds->bridge);
+}
+
+static int lvds_encoder_remove(struct platform_device *pdev)
+{
+	struct lvds_encoder *encoder = platform_get_drvdata(pdev);
+
+	drm_bridge_remove(&encoder->bridge);
+
+	return 0;
+}
+
+static const struct of_device_id lvds_encoder_match[] = {
+	{ .compatible = "lvds-encoder" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, lvds_encoder_match);
+
+struct platform_driver lvds_encoder_driver = {
+	.probe	= lvds_encoder_probe,
+	.remove	= lvds_encoder_remove,
+	.driver		= {
+		.name		= "lvds-encoder",
+		.of_match_table	= lvds_encoder_match,
+	},
+};
+module_platform_driver(lvds_encoder_driver);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("Transparent parallel to LVDS encoder");
+MODULE_LICENSE("GPL");
-- 
Regards,

Laurent Pinchart

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

end of thread, other threads:[~2016-10-26 21:32 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-19 14:25 [PATCH 0/8] R-Car DU: Use drm bridge API Laurent Pinchart
2016-10-19 14:25 ` Laurent Pinchart
2016-10-19 14:25 ` [PATCH 1/8] drm: bridge: Add LVDS encoder driver Laurent Pinchart
2016-10-21  5:21   ` Archit Taneja
2016-10-21 10:21     ` Laurent Pinchart
2016-10-21 10:21       ` Laurent Pinchart
2016-10-26 21:32   ` Rob Herring
2016-10-26 21:32     ` Rob Herring
2016-10-19 14:25 ` [PATCH 2/8] drm: bridge: vga-dac: Add adi,adv7123 compatible string Laurent Pinchart
2016-10-21  5:13   ` Archit Taneja
2016-10-21  5:13     ` Archit Taneja
2016-10-21 10:22     ` Laurent Pinchart
2016-10-21 10:43       ` Archit Taneja
2016-10-21 10:43         ` Archit Taneja
2016-10-19 14:25 ` [PATCH 3/8] drm: bridge: lvds-encoder: Add thine,thc63lvdm83d " Laurent Pinchart
2016-10-19 14:25 ` [PATCH 4/8] drm: Add encoder_type field to the drm_bridge structure Laurent Pinchart
2016-10-20 12:15   ` Archit Taneja
2016-10-20 12:15     ` Archit Taneja
2016-10-19 14:25 ` [PATCH 5/8] drm: bridge: Set bridges' encoder type Laurent Pinchart
2016-10-19 14:25 ` [PATCH 6/8] drm: Set on-chip " Laurent Pinchart
2016-10-19 14:25   ` Laurent Pinchart
2016-10-19 14:25 ` [PATCH 7/8] drm: rcar-du: Replace manual VGA DAC implementation with DRM bridge Laurent Pinchart
2016-10-19 14:25   ` Laurent Pinchart
2016-10-19 14:25 ` [PATCH 8/8] drm: rcar-du: Initialize encoder's type based on the bridge's type Laurent Pinchart
2016-10-19 14:25   ` Laurent Pinchart
  -- strict thread matches above, loose matches on Subject: below --
2016-10-19 14:07 [PATCH 0/8] R-Car DU: Use drm bridge API Laurent Pinchart
2016-10-19 14:07 ` [PATCH 1/8] drm: bridge: Add LVDS encoder driver Laurent Pinchart

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.