All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel
@ 2019-08-20  1:16 Laurent Pinchart
  2019-08-20  1:16 ` [PATCH v2 01/50] video: hdmi: Change return type of hdmi_avi_infoframe_init() to void Laurent Pinchart
                   ` (50 more replies)
  0 siblings, 51 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Hello,

This patch series (nearly, see [1]) completes the rework of the omapdrm
driver to move to drm_bridge and drm_panel.

Let's start with some context (copied from v1) to understand the
problem. omapdrm contains custom drivers for external encoders, panels
and connectors (collectively referred to as display drivers). It
combines them to create output pipelines abstracted by a drm_encoder and
a drm_connector, with the ability to delegate the encoder and connector
operations to the component in the pipeline that implements them. For
instance, for an HDMI output pipeline, the hot plug detection and the
EDID read can be implemented by two different components, when they are
handled by two different devices at the hardware level.

DRM/KMS uses drm_bridge and drm_panel to abstract external encoders and
panels. The model is however simpler than what omapdrm provides, as
bridges were designed to be simple add-ons at the output of a
drm_encoder. The ability to chain bridges exists, but a bridge driver
hardcodes in its design its position in the pipeline : bridges that
expect to terminate the pipeline create a drm_connector, while bridges
that expect to be an intermediate component in the pipeline do not
create a connector. In addition to not supporting bridges that can be
either internal or a termination point in the pipeline depending on the
hardware design, implementing the drm_connector inside a bridge driver
makes it impossible to support hardware where bridge operations are
handled by different hardware components, as explained above.

The omapdrm driver has received support for drm_bridge and drm_panel,
but these issues prevented completely moving away from the omapdrm
custom display drivers. This patch series thus first reworks the
drm_bridge infrastructure to support the omapdrm use cases, and then
transitions the omapdrm driver.

The series starts with a small drive-by cleanup (01/50), followed by a
new helper (02/50) that leverages data from drm_connector.c to convert a
connector type to a string. Patch 03/50 then adds a new flag to the
drm_display_info structure to identify HDMI sinks. This is a feature
needed by the OMAP4 and OMAP5 HDMI encoders, and I believe it can be
useful to other HDMI encoders as well.

The next two patches address the drm_bridge issues explained above.
Patch 04/50 adds connector-related operations to drm_bridge, and patch
05/50 makes it possible to attach to a bridge without having the bridge
create a connector. The connector is expected to be created by the
display controller driver.

The approach taken here is slightly intrusive as path 05/50 adds a
parameter to the bridge .attach() operation, and thus touches all bridge
drivers, even if the changes are very simple (as a consequence I haven't
CC'ed all the individual bridge maintainers as the CC list was too
large). Other options may be possible, what matters most to me is the
feature, not so much its implementation. Please note that compared to v1
this version uses a flag bitmask instead of a boolean on Andrzej's
request, as he expects the parameter to be useful for other purposes.

The first sizeable change follows with the rename of the dumb-vga-dac
driver to simple-bridge (06/50 and 07/50) and support for non-VGA
bridges (08/50). This doesn't change the spirit of the driver that still
focusses on transparent bridges, but prepares it to support an analog
video amplifier. Patches 09/50 then add support for an enable GPIO, and
10/50 support for the OPA362 video amplifier itself.

The next six patches make use of these new features: patches 11/50 and
12/50 add new bridge drivers for display connectors and for the TI
TPD12S015 HDMI level shifter respectively, patch 13/50 supports the new
API in the panel bridge driver, and patches 15/50 to 16/50 do the same
in the ti-tfp410 driver.

Patch 17/50 is possibly the most remarkable one in the series, with the
drm_bridge operations extension, as it provides a helper for display
controller drivers to construct a drm_connector entirerly backed by a
chain of bridges. This offsets the complexity of the additional bridge
operations by handling it all in a single place. An example usage for
omapdrm can be found in patch 34/50. Don't let its diffstat mislead you,
usage of the helper would remove lots of code if it wasn't for the fact
that the legacy implementation still has to be kept for the DSI panel
(see [1]). Down the road this helper and the new operation paradigm
should remove code from both display controller and bridge drivers.

The rest of the series is omapdrm-focussed, slowly preparing the driver
for the switch to drm_bridge drivers using the new helper (34/50), the
removal of the omapdrm-specific display drivers (35/50), and lots of
simplification and code removal in the other patches.

Compared to v1, many review comments have been taken into account, please
see individual patches for details. Please note that some issues are
still being discussed and have thus not been addressed yet. This
includes HPD handling and removal of the drm_connector argument from the
drm_bridge .get_edid() operation.

The patches can be found at

	git://linuxtv.org/pinchartl/media.git omapdrm/bridge/devel

[1] The only notable exception is the omapdrm-specific DSI panel driver
that implements a large number of custom operations. This should be
addressed separately.

Laurent Pinchart (50):
  video: hdmi: Change return type of hdmi_avi_infoframe_init() to void
  drm/connector: Add helper to get a connector type name
  drm/edid: Add flag to drm_display_info to identify HDMI sinks
  drm/bridge: Add connector-related bridge operations and data
  drm/bridge: Extend bridge API to disable connector creation
  drm/bridge: dumb-vga-dac: Rename internal symbols to simple-bridge
  drm/bridge: dumb-vga-dac: Rename driver to simple-bridge
  drm/bridge: simple-bridge: Add support for non-VGA bridges
  drm/bridge: simple-bridge: Add support for enable GPIO
  drm/bridge: simple-bridge: Add support for the TI OP362
  drm/bridge: Add bridge driver for display connectors
  drm/bridge: Add driver for the TI TPD12S015 HDMI level shifter
  drm/bridge: panel: Implement bridge connector operations
  drm/bridge: tfp410: Don't include drmP.h
  drm/bridge: tfp410: Replace manual connector handling with bridge
  drm/bridge: tfp410: Allow operation without drm_connector
  drm: Add helper to create a connector for a chain of bridges
  drm/omap: Simplify HDMI mode and infoframe configuration
  drm/omap: Factor out display type to connector type conversion
  drm/omap: Use the drm_panel_bridge API
  drm/omap: dss: Fix output next device lookup in DT
  drm/omap: Add infrastructure to support drm_bridge local to DSS
    outputs
  drm/omap: dss: Make omap_dss_device_ops optional
  drm/omap: hdmi: Allocate EDID in the .read_edid() operation
  drm/omap: hdmi4: Rework EDID read to isolate data read
  drm/omap: hdmi5: Rework EDID read to isolate data read
  drm/omap: hdmi4: Register a drm_bridge for EDID read
  drm/omap: hdmi5: Register a drm_bridge for EDID read
  drm/omap: hdmi4: Move mode set, enable and disable operations to
    bridge
  drm/omap: hdmi5: Move mode set, enable and disable operations to
    bridge
  drm/omap: hdmi4: Implement drm_bridge .hpd_notify() operation
  drm/omap: dss: Remove .set_hdmi_mode() and .set_infoframe() operations
  drm/omap: venc: Register a drm_bridge
  drm/omap: Create connector for bridges
  drm/omap: Switch the HDMI and VENC outputs to drm_bridge
  drm/omap: Remove HPD, detect and EDID omapdss operations
  drm/omap: hdmi: Remove omap_dss_device operations
  drm/omap: venc: Remove omap_dss_device operations
  drm/omap: hdmi4: Simplify EDID read
  drm/omap: hdmi5: Simplify EDID read
  drm/omap: dpi: Sort includes alphabetically
  drm/omap: dpi: Reorder functions in sections
  drm/omap: dpi: Simplify clock setting API
  drm/omap: dpi: Register a drm_bridge
  drm/omap: sdi: Sort includes alphabetically
  drm/omap: sdi: Register a drm_bridge
  drm/omap: Simplify connector implementation
  drm/omap: dss: Remove unused omap_dss_device operations
  drm/omap: dss: Inline the omapdss_display_get() function
  drm/omap: dss: Remove unused omapdss_of_find_connected_device()
    function

 Documentation/gpu/todo.rst                    |  12 +
 arch/arm/configs/davinci_all_defconfig        |   2 +-
 arch/arm/configs/integrator_defconfig         |   2 +-
 arch/arm/configs/multi_v7_defconfig           |   2 +-
 arch/arm/configs/shmobile_defconfig           |   2 +-
 arch/arm/configs/sunxi_defconfig              |   2 +-
 arch/arm/configs/versatile_defconfig          |   2 +-
 drivers/gpu/drm/Makefile                      |   3 +-
 drivers/gpu/drm/arc/arcpgu_hdmi.c             |   2 +-
 .../gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c  |   2 +-
 drivers/gpu/drm/bridge/Kconfig                |  29 +-
 drivers/gpu/drm/bridge/Makefile               |   4 +-
 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c  |   6 +-
 drivers/gpu/drm/bridge/analogix-anx78xx.c     |   6 +-
 .../drm/bridge/analogix/analogix_dp_core.c    |   8 +-
 drivers/gpu/drm/bridge/cdns-dsi.c             |   6 +-
 drivers/gpu/drm/bridge/display-connector.c    | 292 ++++++++++++++
 drivers/gpu/drm/bridge/dumb-vga-dac.c         | 299 --------------
 drivers/gpu/drm/bridge/lvds-encoder.c         |   5 +-
 .../bridge/megachips-stdpxxxx-ge-b850v3-fw.c  |   6 +-
 drivers/gpu/drm/bridge/nxp-ptn3460.c          |   6 +-
 drivers/gpu/drm/bridge/panel.c                |  22 +-
 drivers/gpu/drm/bridge/parade-ps8622.c        |   6 +-
 drivers/gpu/drm/bridge/sii902x.c              |   6 +-
 drivers/gpu/drm/bridge/sil-sii8620.c          |   3 +-
 drivers/gpu/drm/bridge/simple-bridge.c        | 339 ++++++++++++++++
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c     |   8 +-
 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c |   8 +-
 drivers/gpu/drm/bridge/tc358764.c             |   6 +-
 drivers/gpu/drm/bridge/tc358767.c             |   6 +-
 drivers/gpu/drm/bridge/thc63lvd1024.c         |   5 +-
 drivers/gpu/drm/bridge/ti-sn65dsi86.c         |   6 +-
 drivers/gpu/drm/bridge/ti-tfp410.c            | 205 ++++------
 drivers/gpu/drm/bridge/ti-tpd12s015.c         | 195 +++++++++
 drivers/gpu/drm/drm_bridge.c                  | 100 ++++-
 drivers/gpu/drm/drm_bridge_connector.c        | 372 ++++++++++++++++++
 drivers/gpu/drm/drm_connector.c               |  15 +
 drivers/gpu/drm/drm_edid.c                    |  11 +-
 drivers/gpu/drm/drm_simple_kms_helper.c       |   2 +-
 drivers/gpu/drm/exynos/exynos_dp.c            |   3 +-
 drivers/gpu/drm/exynos/exynos_drm_dsi.c       |   4 +-
 drivers/gpu/drm/exynos/exynos_hdmi.c          |   2 +-
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c     |   2 +-
 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c  |   2 +-
 drivers/gpu/drm/i2c/tda998x_drv.c             |   8 +-
 drivers/gpu/drm/imx/imx-ldb.c                 |   2 +-
 drivers/gpu/drm/imx/parallel-display.c        |   2 +-
 drivers/gpu/drm/ingenic/ingenic-drm.c         |   2 +-
 drivers/gpu/drm/mcde/mcde_dsi.c               |   8 +-
 drivers/gpu/drm/mediatek/mtk_dpi.c            |   2 +-
 drivers/gpu/drm/mediatek/mtk_dsi.c            |   2 +-
 drivers/gpu/drm/mediatek/mtk_hdmi.c           |   8 +-
 drivers/gpu/drm/msm/dsi/dsi_manager.c         |   4 +-
 drivers/gpu/drm/msm/edp/edp_bridge.c          |   2 +-
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c        |   2 +-
 drivers/gpu/drm/omapdrm/displays/Kconfig      |  22 --
 drivers/gpu/drm/omapdrm/displays/Makefile     |   4 -
 .../omapdrm/displays/connector-analog-tv.c    |  97 -----
 .../gpu/drm/omapdrm/displays/connector-hdmi.c | 183 ---------
 .../gpu/drm/omapdrm/displays/encoder-opa362.c | 137 -------
 .../drm/omapdrm/displays/encoder-tpd12s015.c  | 217 ----------
 .../gpu/drm/omapdrm/displays/panel-dsi-cm.c   |   2 +-
 drivers/gpu/drm/omapdrm/dss/Makefile          |   2 +-
 drivers/gpu/drm/omapdrm/dss/base.c            |  71 ++--
 drivers/gpu/drm/omapdrm/dss/display.c         |   9 -
 drivers/gpu/drm/omapdrm/dss/dpi.c             | 337 +++++++++-------
 drivers/gpu/drm/omapdrm/dss/dsi.c             |   4 +-
 drivers/gpu/drm/omapdrm/dss/dss-of.c          |  28 --
 drivers/gpu/drm/omapdrm/dss/dss.c             |   3 +-
 drivers/gpu/drm/omapdrm/dss/hdmi.h            |   4 +-
 drivers/gpu/drm/omapdrm/dss/hdmi4.c           | 324 ++++++++-------
 drivers/gpu/drm/omapdrm/dss/hdmi4_core.c      |  59 +--
 drivers/gpu/drm/omapdrm/dss/hdmi4_core.h      |   4 +-
 drivers/gpu/drm/omapdrm/dss/hdmi5.c           | 304 +++++++-------
 drivers/gpu/drm/omapdrm/dss/hdmi5_core.c      |  48 +--
 drivers/gpu/drm/omapdrm/dss/hdmi5_core.h      |   5 +-
 .../gpu/drm/omapdrm/dss/omapdss-boot-init.c   |   5 -
 drivers/gpu/drm/omapdrm/dss/omapdss.h         |  47 +--
 drivers/gpu/drm/omapdrm/dss/output.c          |  55 ++-
 drivers/gpu/drm/omapdrm/dss/sdi.c             | 188 +++++----
 drivers/gpu/drm/omapdrm/dss/venc.c            | 270 +++++++------
 drivers/gpu/drm/omapdrm/omap_connector.c      | 246 +-----------
 drivers/gpu/drm/omapdrm/omap_connector.h      |   3 -
 drivers/gpu/drm/omapdrm/omap_drv.c            |  96 +++--
 drivers/gpu/drm/omapdrm/omap_encoder.c        |  83 +---
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c     |   2 +-
 drivers/gpu/drm/rcar-du/rcar_lvds.c           |   8 +-
 drivers/gpu/drm/rockchip/rockchip_lvds.c      |   2 +-
 drivers/gpu/drm/rockchip/rockchip_rgb.c       |   2 +-
 drivers/gpu/drm/sti/sti_dvo.c                 |   2 +-
 drivers/gpu/drm/sti/sti_hda.c                 |   2 +-
 drivers/gpu/drm/sti/sti_hdmi.c                |   2 +-
 drivers/gpu/drm/stm/ltdc.c                    |   2 +-
 drivers/gpu/drm/sun4i/sun4i_lvds.c            |   2 +-
 drivers/gpu/drm/sun4i/sun4i_rgb.c             |   2 +-
 drivers/gpu/drm/tilcdc/tilcdc_external.c      |   2 +-
 drivers/gpu/drm/vc4/vc4_dpi.c                 |   2 +-
 drivers/gpu/drm/vc4/vc4_dsi.c                 |   2 +-
 drivers/video/hdmi.c                          |  11 +-
 include/drm/drm_bridge.h                      | 197 +++++++++-
 include/drm/drm_bridge_connector.h            |  18 +
 include/drm/drm_connector.h                   |   9 +
 include/linux/hdmi.h                          |   2 +-
 103 files changed, 2819 insertions(+), 2375 deletions(-)
 create mode 100644 drivers/gpu/drm/bridge/display-connector.c
 delete mode 100644 drivers/gpu/drm/bridge/dumb-vga-dac.c
 create mode 100644 drivers/gpu/drm/bridge/simple-bridge.c
 create mode 100644 drivers/gpu/drm/bridge/ti-tpd12s015.c
 create mode 100644 drivers/gpu/drm/drm_bridge_connector.c
 delete mode 100644 drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
 delete mode 100644 drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
 delete mode 100644 drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
 delete mode 100644 drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
 delete mode 100644 drivers/gpu/drm/omapdrm/dss/dss-of.c
 create mode 100644 include/drm/drm_bridge_connector.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] 106+ messages in thread

* [PATCH v2 01/50] video: hdmi: Change return type of hdmi_avi_infoframe_init() to void
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-20 11:18   ` Bartlomiej Zolnierkiewicz
  2019-08-22  9:12   ` Boris Brezillon
  2019-08-20  1:16 ` [PATCH v2 02/50] drm/connector: Add helper to get a connector type name Laurent Pinchart
                   ` (49 subsequent siblings)
  50 siblings, 2 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel,
	Bartlomiej Zolnierkiewicz

The hdmi_avi_infoframe_init() never needs to return an error, change its
return type to void.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
---
Changes since v1:

- Removed documentation of the return value

Cc: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
---
 drivers/gpu/drm/drm_edid.c |  5 +----
 drivers/video/hdmi.c       | 11 ++---------
 include/linux/hdmi.h       |  2 +-
 3 files changed, 4 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 82a4ceed3fcf..86ddb67c1e8a 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -5083,14 +5083,11 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
 					 const struct drm_display_mode *mode)
 {
 	enum hdmi_picture_aspect picture_aspect;
-	int err;
 
 	if (!frame || !mode)
 		return -EINVAL;
 
-	err = hdmi_avi_infoframe_init(frame);
-	if (err < 0)
-		return err;
+	hdmi_avi_infoframe_init(frame);
 
 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
 		frame->pixel_repeat = 1;
diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
index b939bc28d886..ff4d09592602 100644
--- a/drivers/video/hdmi.c
+++ b/drivers/video/hdmi.c
@@ -53,18 +53,14 @@ static void hdmi_infoframe_set_checksum(void *buffer, size_t size)
 /**
  * hdmi_avi_infoframe_init() - initialize an HDMI AVI infoframe
  * @frame: HDMI AVI infoframe
- *
- * Returns 0 on success or a negative error code on failure.
  */
-int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
+void hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
 {
 	memset(frame, 0, sizeof(*frame));
 
 	frame->type = HDMI_INFOFRAME_TYPE_AVI;
 	frame->version = 2;
 	frame->length = HDMI_AVI_INFOFRAME_SIZE;
-
-	return 0;
 }
 EXPORT_SYMBOL(hdmi_avi_infoframe_init);
 
@@ -1553,7 +1549,6 @@ static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame,
 				     const void *buffer, size_t size)
 {
 	const u8 *ptr = buffer;
-	int ret;
 
 	if (size < HDMI_INFOFRAME_SIZE(AVI))
 		return -EINVAL;
@@ -1566,9 +1561,7 @@ static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame,
 	if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AVI)) != 0)
 		return -EINVAL;
 
-	ret = hdmi_avi_infoframe_init(frame);
-	if (ret)
-		return ret;
+	hdmi_avi_infoframe_init(frame);
 
 	ptr += HDMI_INFOFRAME_HEADER_SIZE;
 
diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h
index 9918a6c910c5..9613d796cfb1 100644
--- a/include/linux/hdmi.h
+++ b/include/linux/hdmi.h
@@ -207,7 +207,7 @@ struct hdmi_drm_infoframe {
 	u16 max_fall;
 };
 
-int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame);
+void hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame);
 ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
 				size_t size);
 ssize_t hdmi_avi_infoframe_pack_only(const struct hdmi_avi_infoframe *frame,
-- 
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] 106+ messages in thread

* [PATCH v2 02/50] drm/connector: Add helper to get a connector type name
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
  2019-08-20  1:16 ` [PATCH v2 01/50] video: hdmi: Change return type of hdmi_avi_infoframe_init() to void Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-22  9:13   ` Boris Brezillon
  2019-08-20  1:16 ` [PATCH v2 03/50] drm/edid: Add flag to drm_display_info to identify HDMI sinks Laurent Pinchart
                   ` (48 subsequent siblings)
  50 siblings, 1 reply; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

drm_connector.c contains a map of connector types (DRM_MODE_CONNECTOR_*)
to name strings, but doesn't expose it. This leads to drivers having to
store a similar map.

Add a new drm_get_connector_type_name() helper function that return a
name string for a connector type.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/drm_connector.c | 15 +++++++++++++++
 include/drm/drm_connector.h     |  1 +
 2 files changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 4c766624b20d..3f93633a9ff2 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -111,6 +111,21 @@ void drm_connector_ida_destroy(void)
 		ida_destroy(&drm_connector_enum_list[i].ida);
 }
 
+/**
+ * drm_get_connector_type_name - return a string for connector type
+ * @type: The connector type (DRM_MODE_CONNECTOR_*)
+ *
+ * Returns: the name of the connector type, or NULL if the type is not valid.
+ */
+const char *drm_get_connector_type_name(unsigned int type)
+{
+	if (type < ARRAY_SIZE(drm_connector_enum_list))
+		return drm_connector_enum_list[type].name;
+
+	return NULL;
+}
+EXPORT_SYMBOL(drm_get_connector_type_name);
+
 /**
  * drm_connector_get_cmdline_mode - reads the user's cmdline mode
  * @connector: connector to quwery
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 681cb590f952..b91e369cfb11 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1500,6 +1500,7 @@ drm_connector_is_unregistered(struct drm_connector *connector)
 		DRM_CONNECTOR_UNREGISTERED;
 }
 
+const char *drm_get_connector_type_name(unsigned int connector_type);
 const char *drm_get_connector_status_name(enum drm_connector_status status);
 const char *drm_get_subpixel_order_name(enum subpixel_order order);
 const char *drm_get_dpms_name(int val);
-- 
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] 106+ messages in thread

* [PATCH v2 03/50] drm/edid: Add flag to drm_display_info to identify HDMI sinks
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
  2019-08-20  1:16 ` [PATCH v2 01/50] video: hdmi: Change return type of hdmi_avi_infoframe_init() to void Laurent Pinchart
  2019-08-20  1:16 ` [PATCH v2 02/50] drm/connector: Add helper to get a connector type name Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-22  9:15   ` Boris Brezillon
  2019-08-20  1:16 ` [PATCH v2 04/50] drm/bridge: Add connector-related bridge operations and data Laurent Pinchart
                   ` (47 subsequent siblings)
  50 siblings, 1 reply; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

The drm_display_info structure contains many fields related to HDMI
sinks, but none that identifies if a sink compliant with CEA-861 (EDID)
shall be treated as an HDMI sink or a DVI sink. Add such a flag, and
populate it according to section 8.3.3 ("DVI/HDMI Device
Discrimination") of the HDMI v1.3 specification.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
Changes since v1:

- Link the is_hdmi field doc with drm_detect_hdmi_monitor()
- Add a conversion task in todo.rst
---
 Documentation/gpu/todo.rst  | 12 ++++++++++++
 drivers/gpu/drm/drm_edid.c  |  6 ++++++
 include/drm/drm_connector.h |  8 ++++++++
 3 files changed, 26 insertions(+)

diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index 32787acff0a8..199751149e23 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -284,6 +284,18 @@ drm_fb_helper tasks
   removed: drm_fb_helper_single_add_all_connectors(),
   drm_fb_helper_add_one_connector() and drm_fb_helper_remove_one_connector().
 
+Replace drm_detect_hdmi_monitor() with drm_display_info.is_hdmi
+---------------------------------------------------------------
+
+Once EDID is parsed, the monitor HDMI support information is available through
+drm_display_info.is_hdmi. Many drivers still call drm_detect_hdmi_monitor() to
+retrieve the same information, which is less efficient.
+
+Audit each individual driver calling drm_detect_hdmi_monitor() and switch to
+drm_display_info.is_hdmi if applicable.
+
+Contact: Laurent Pinchart, respective driver maintainers
+
 Core refactorings
 =================
 
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 86ddb67c1e8a..8be00dda945b 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -4325,6 +4325,9 @@ EXPORT_SYMBOL(drm_av_sync_delay);
  *
  * Parse the CEA extension according to CEA-861-B.
  *
+ * Drivers that have added the modes parsed from EDID to drm_display_info
+ * should use &drm_display_info.is_hdmi instead of calling this function.
+ *
  * Return: True if the monitor is HDMI, false if not or unknown.
  */
 bool drm_detect_hdmi_monitor(struct edid *edid)
@@ -4559,6 +4562,8 @@ drm_parse_hdmi_vsdb_video(struct drm_connector *connector, const u8 *db)
 	struct drm_display_info *info = &connector->display_info;
 	u8 len = cea_db_payload_len(db);
 
+	info->is_hdmi = true;
+
 	if (len >= 6)
 		info->dvi_dual = db[6] & 1;
 	if (len >= 7)
@@ -4627,6 +4632,7 @@ drm_reset_display_info(struct drm_connector *connector)
 	info->cea_rev = 0;
 	info->max_tmds_clock = 0;
 	info->dvi_dual = false;
+	info->is_hdmi = false;
 	info->has_hdmi_infoframe = false;
 	info->rgb_quant_range_selectable = false;
 	memset(&info->hdmi, 0, sizeof(info->hdmi));
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index b91e369cfb11..9b6f69c5092b 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -430,6 +430,14 @@ struct drm_display_info {
 	 */
 	bool dvi_dual;
 
+	/**
+	 * @is_hdmi: True if the sink is an HDMI device.
+	 *
+	 * This field shall be used instead of calling
+	 * drm_detect_hdmi_monitor() when possible.
+	 */
+	bool is_hdmi;
+
 	/**
 	 * @has_hdmi_infoframe: Does the sink support the HDMI infoframe?
 	 */
-- 
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] 106+ messages in thread

* [PATCH v2 04/50] drm/bridge: Add connector-related bridge operations and data
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (2 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 03/50] drm/edid: Add flag to drm_display_info to identify HDMI sinks Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-22 15:24   ` Boris Brezillon
  2019-08-22 16:41   ` Boris Brezillon
  2019-08-20  1:16 ` [PATCH v2 05/50] drm/bridge: Extend bridge API to disable connector creation Laurent Pinchart
                   ` (46 subsequent siblings)
  50 siblings, 2 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

To support implementation of DRM connectors on top of DRM bridges
instead of by bridges, the drm_bridge needs to expose new operations and
data:

- Output detection, hot-plug notification, mode retrieval and EDID
  retrieval operations
- Bitmask of supported operations
- Bridge output type
- I2C adapter for DDC access

Add and document these.

Three new bridge helper functions are also added to handle hot plug
notification in a way that is as transparent as possible for the
bridges.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v1:

- Make .hpd_enable() and .hpd_disable() optional
- Rename .lost_hotplug() to .hpd_notify()
- Add ddc field to drm_bridge
---
 drivers/gpu/drm/drm_bridge.c |  94 +++++++++++++++++++
 include/drm/drm_bridge.h     | 177 ++++++++++++++++++++++++++++++++++-
 2 files changed, 270 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index cba537c99e43..cf1fbed88410 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -70,6 +70,8 @@ static LIST_HEAD(bridge_list);
  */
 void drm_bridge_add(struct drm_bridge *bridge)
 {
+	mutex_init(&bridge->hpd_mutex);
+
 	mutex_lock(&bridge_lock);
 	list_add_tail(&bridge->list, &bridge_list);
 	mutex_unlock(&bridge_lock);
@@ -86,6 +88,8 @@ void drm_bridge_remove(struct drm_bridge *bridge)
 	mutex_lock(&bridge_lock);
 	list_del_init(&bridge->list);
 	mutex_unlock(&bridge_lock);
+
+	mutex_destroy(&bridge->hpd_mutex);
 }
 EXPORT_SYMBOL(drm_bridge_remove);
 
@@ -462,6 +466,96 @@ void drm_atomic_bridge_enable(struct drm_bridge *bridge,
 }
 EXPORT_SYMBOL(drm_atomic_bridge_enable);
 
+/**
+ * drm_bridge_hpd_enable - enable hot plug detection for the bridge
+ * @bridge: bridge control structure
+ * @cb: hot-plug detection callback
+ * @data: data to be passed to the hot-plug detection callback
+ *
+ * Call &drm_bridge_funcs.hpd_enable if implemented and register the given @cb
+ * and @data as hot plug notification callback. From now on the @cb will be
+ * called with @data when an output status change is detected by the bridge,
+ * until hot plug notification gets disabled with drm_bridge_hpd_disable().
+ *
+ * Hot plug detection is supported only if the DRM_BRIDGE_OP_HPD flag is set in
+ * bridge->ops. This function shall not be called when the flag is not set.
+ *
+ * Only one hot plug detection callback can be registered at a time, it is an
+ * error to call this function when hot plug detection is already enabled for
+ * the bridge.
+ */
+void drm_bridge_hpd_enable(struct drm_bridge *bridge,
+			   void (*cb)(void *data,
+				      enum drm_connector_status status),
+			   void *data)
+{
+	if (!bridge || !(bridge->ops & DRM_BRIDGE_OP_HPD))
+		return;
+
+	mutex_lock(&bridge->hpd_mutex);
+
+	if (WARN(bridge->hpd_cb, "Hot plug detection already enabled\n"))
+		goto unlock;
+
+	bridge->hpd_cb = cb;
+	bridge->hpd_data = data;
+
+	if (bridge->funcs->hpd_enable)
+		bridge->funcs->hpd_enable(bridge);
+
+unlock:
+	mutex_unlock(&bridge->hpd_mutex);
+}
+EXPORT_SYMBOL_GPL(drm_bridge_hpd_enable);
+
+/**
+ * drm_bridge_hpd_disable - disable hot plug detection for the bridge
+ * @bridge: bridge control structure
+ *
+ * Call &drm_bridge_funcs.hpd_disable if implemented and unregister the hot
+ * plug detection callback previously registered with drm_bridge_hpd_enable().
+ * Once this function returns the callback will not be called by the bridge
+ * when an output status change occurs.
+ *
+ * Hot plug detection is supported only if the DRM_BRIDGE_OP_HPD flag is set in
+ * bridge->ops. This function shall not be called when the flag is not set.
+ */
+void drm_bridge_hpd_disable(struct drm_bridge *bridge)
+{
+	if (!bridge || !(bridge->ops & DRM_BRIDGE_OP_HPD))
+		return;
+
+	mutex_lock(&bridge->hpd_mutex);
+	if (bridge->funcs->hpd_disable)
+		bridge->funcs->hpd_disable(bridge);
+
+	bridge->hpd_cb = NULL;
+	bridge->hpd_data = NULL;
+	mutex_unlock(&bridge->hpd_mutex);
+}
+EXPORT_SYMBOL_GPL(drm_bridge_hpd_disable);
+
+/**
+ * drm_bridge_hpd_notify - notify hot plug detection events
+ * @bridge: bridge control structure
+ * @status: output connection status
+ *
+ * Bridge drivers shall call this function to report hot plug events when they
+ * detect a change in the output status, when hot plug detection has been
+ * enabled by drm_bridge_hpd_enable().
+ *
+ * This function shall be called in a context that can sleep.
+ */
+void drm_bridge_hpd_notify(struct drm_bridge *bridge,
+			   enum drm_connector_status status)
+{
+	mutex_lock(&bridge->hpd_mutex);
+	if (bridge->hpd_cb)
+		bridge->hpd_cb(bridge->hpd_data, status);
+	mutex_unlock(&bridge->hpd_mutex);
+}
+EXPORT_SYMBOL_GPL(drm_bridge_hpd_notify);
+
 #ifdef CONFIG_OF
 /**
  * of_drm_find_bridge - find the bridge corresponding to the device node in
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 7616f6562fe4..7db6ca0fd75d 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -23,14 +23,16 @@
 #ifndef __DRM_BRIDGE_H__
 #define __DRM_BRIDGE_H__
 
-#include <linux/list.h>
 #include <linux/ctype.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
 #include <drm/drm_mode_object.h>
 #include <drm/drm_modes.h>
 
 struct drm_bridge;
 struct drm_bridge_timings;
 struct drm_panel;
+struct i2c_adapter;
 
 /**
  * struct drm_bridge_funcs - drm_bridge control functions
@@ -334,6 +336,111 @@ struct drm_bridge_funcs {
 	 */
 	void (*atomic_post_disable)(struct drm_bridge *bridge,
 				    struct drm_atomic_state *state);
+
+	/**
+	 * @detect:
+	 *
+	 * Check if anything is attached to the bridge output.
+	 *
+	 * This callback is optional, if not implemented the bridge will be
+	 * considered as always having a component attached to its output.
+	 * Bridges that implement this callback shall set the
+	 * DRM_BRIDGE_OP_DETECT flag in their &drm_bridge->ops.
+	 *
+	 * RETURNS:
+	 *
+	 * drm_connector_status indicating the bridge output status.
+	 */
+	enum drm_connector_status (*detect)(struct drm_bridge *bridge);
+
+	/**
+	 * @get_modes:
+	 *
+	 * Fill all modes currently valid for the sink into the &drm_connector
+	 * with drm_mode_probed_add().
+	 *
+	 * The @get_modes callback is mostly intended to support non-probable
+	 * displays such as many fixed panels. Bridges that support reading
+	 * EDID shall leave @get_modes unimplemented and implement the
+	 * &drm_bridge_funcs->get_edid callback instead.
+	 *
+	 * This callback is optional. Bridges that implement it shall set the
+	 * DRM_BRIDGE_OP_MODES flag in their &drm_bridge->ops.
+	 *
+	 * RETURNS:
+	 *
+	 * The number of modes added by calling drm_mode_probed_add().
+	 */
+	int (*get_modes)(struct drm_bridge *bridge,
+			 struct drm_connector *connector);
+
+	/**
+	 * @get_edid:
+	 *
+	 * Read and parse the EDID data of the connected display.
+	 *
+	 * The @get_edid callback is the preferred way of reporting mode
+	 * information for a display connected to the bridge output. Bridges
+	 * that support readind EDID shall implement this callback and leave
+	 * the @get_modes callback unimplemented.
+	 *
+	 * The caller of this operation shall first verify the output
+	 * connection status and refrain from reading EDID from a disconnected
+	 * output.
+	 *
+	 * This callback is optional. Bridges that implement it shall set the
+	 * DRM_BRIDGE_OP_EDID flag in their &drm_bridge->ops.
+	 *
+	 * RETURNS:
+	 *
+	 * An edid structure newly allocated with kmalloc() (or similar) on
+	 * success, or NULL otherwise. The caller is responsible for freeing
+	 * the returned edid structure with kfree().
+	 */
+	struct edid *(*get_edid)(struct drm_bridge *bridge,
+				 struct drm_connector *connector);
+
+	/**
+	 * @hpd_notify:
+	 *
+	 * Notify the bridge of hot plug detection.
+	 *
+	 * This callback is optional, it may be implemented by bridges that
+	 * need to be notified of display connection or disconnection for
+	 * internal reasons. One use case is to reset the internal state of CEC
+	 * controllers for HDMI bridges.
+	 */
+	void (*hpd_notify)(struct drm_bridge *bridge,
+			   enum drm_connector_status status);
+
+	/**
+	 * @hpd_enable:
+	 *
+	 * Enable hot plug detection. From now on the bridge shall call
+	 * drm_bridge_hpd_notify() each time a change is detected in the output
+	 * connection status, until hot plug detection gets disabled with
+	 * @hpd_disable.
+	 *
+	 * This callback is optional and shall only be implemented by bridges
+	 * that support hot-plug notification without polling. Bridges that
+	 * implement it shall also implement the @hpd_disable callback and set
+	 * the DRM_BRIDGE_OP_HPD flag in their &drm_bridge->ops.
+	 */
+	void (*hpd_enable)(struct drm_bridge *bridge);
+
+	/**
+	 * @hpd_disable:
+	 *
+	 * Disable hot plug detection. Once this function returns the bridge
+	 * shall not call drm_bridge_hpd_notify() when a change in the output
+	 * connection status occurs.
+	 *
+	 * This callback is optional and shall only be implemented by bridges
+	 * that support hot-plug notification without polling. Bridges that
+	 * implement it shall also implement the @hpd_enable callback and set
+	 * the DRM_BRIDGE_OP_HPD flag in their &drm_bridge->ops.
+	 */
+	void (*hpd_disable)(struct drm_bridge *bridge);
 };
 
 /**
@@ -372,6 +479,39 @@ struct drm_bridge_timings {
 	bool dual_link;
 };
 
+/**
+ * enum drm_bridge_ops - Bitmask of operations supported by the bridge
+ */
+enum drm_bridge_ops {
+	/**
+	 * @DRM_BRIDGE_OP_DETECT: The bridge can detect displays connected to
+	 * its output. Bridges that set this flag shall implement the
+	 * &drm_bridge_funcs->detect callback.
+	 */
+	DRM_BRIDGE_OP_DETECT = BIT(0),
+	/**
+	 * @DRM_BRIDGE_OP_EDID: The bridge can retrieve the EDID of the display
+	 * connected to its output. Bridges that set this flag shall implement
+	 * the &drm_bridge_funcs->get_edid callback.
+	 */
+	DRM_BRIDGE_OP_EDID = BIT(1),
+	/**
+	 * @DRM_BRIDGE_OP_HPD: The bridge can detect hot-plug and hot-unplug
+	 * without requiring polling. Bridges that set this flag shall
+	 * implement the &drm_bridge_funcs->hpd_enable and
+	 * &drm_bridge_funcs->hpd_disable callbacks if they support enabling
+	 * and disabling hot-plug detection dynamically.
+	 */
+	DRM_BRIDGE_OP_HPD = BIT(2),
+	/**
+	 * @DRM_BRIDGE_OP_MODES: The bridge can retrieving the modes supported
+	 * by the display at its output. This does not include readind EDID
+	 * which is separately covered by @DRM_BRIDGE_OP_EDID. Bridges that set
+	 * this flag shall implement the &drm_bridge_funcs->get_modes callback.
+	 */
+	DRM_BRIDGE_OP_MODES = BIT(3),
+};
+
 /**
  * struct drm_bridge - central DRM bridge control structure
  */
@@ -398,6 +538,33 @@ struct drm_bridge {
 	const struct drm_bridge_funcs *funcs;
 	/** @driver_private: pointer to the bridge driver's internal context */
 	void *driver_private;
+	/** @ops: bitmask of operations supported by the bridge */
+	enum drm_bridge_ops ops;
+	/**
+	 * @type: Type of the connection at the bridge output
+	 * (DRM_MODE_CONNECTOR_*). For bridges at the end of this chain this
+	 * identifies the type of connected display.
+	 */
+	int type;
+	/**
+	 * @ddc: Associated I2C adapter for DDC access, if any.
+	 */
+	struct i2c_adapter *ddc;
+	/** private: */
+	/**
+	 * @hpd_mutex: Protects the @hpd_cb and @hpd_data fields.
+	 */
+	struct mutex hpd_mutex;
+	/**
+	 * @hpd_cb: Hot plug detection callback, registered with
+	 * drm_bridge_hpd_enable().
+	 */
+	void (*hpd_cb)(void *data, enum drm_connector_status status);
+	/**
+	 * @hpd_data: Private data passed to the Hot plug detection callback
+	 * @hpd_cb.
+	 */
+	void *hpd_data;
 };
 
 void drm_bridge_add(struct drm_bridge *bridge);
@@ -428,6 +595,14 @@ void drm_atomic_bridge_pre_enable(struct drm_bridge *bridge,
 void drm_atomic_bridge_enable(struct drm_bridge *bridge,
 			      struct drm_atomic_state *state);
 
+void drm_bridge_hpd_enable(struct drm_bridge *bridge,
+			   void (*cb)(void *data,
+				      enum drm_connector_status status),
+			   void *data);
+void drm_bridge_hpd_disable(struct drm_bridge *bridge);
+void drm_bridge_hpd_notify(struct drm_bridge *bridge,
+			   enum drm_connector_status status);
+
 #ifdef CONFIG_DRM_PANEL_BRIDGE
 struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
 					u32 connector_type);
-- 
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] 106+ messages in thread

* [PATCH v2 05/50] drm/bridge: Extend bridge API to disable connector creation
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (3 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 04/50] drm/bridge: Add connector-related bridge operations and data Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-22 15:34   ` Boris Brezillon
  2019-10-01  7:04   ` Tomi Valkeinen
  2019-08-20  1:16 ` [PATCH v2 06/50] drm/bridge: dumb-vga-dac: Rename internal symbols to simple-bridge Laurent Pinchart
                   ` (45 subsequent siblings)
  50 siblings, 2 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Most bridge drivers create a DRM connector to model the connector at the
output of the bridge. This model is historical and has worked pretty
well so far, but causes several issues:

- It prevents supporting more complex display pipelines where DRM
connector operations are split over multiple components. For instance a
pipeline with a bridge connected to the DDC signals to read EDID data,
and another one connected to the HPD signal to detect connection and
disconnection, will not be possible to support through this model.

- It requires every bridge driver to implement similar connector
handling code, resulting in code duplication.

- It assumes that a bridge will either be wired to a connector or to
another bridge, but doesn't support bridges that can be used in both
positions very well (although there is some ad-hoc support for this in
the analogix_dp bridge driver).

In order to solve these issues, ownership of the connector should be
moved to the display controller driver (where it can be implemented
using helpers provided by the core).

Extend the bridge API to allow disabling connector creation in bridge
drivers as a first step towards the new model. The new create_connector
argument to the bridge .attach() operation tells the bridge driver
whether to create a connector. Set the argument to true unconditionally,
and modify all existing bridge drivers to return an error when connector
creation is not requested as they don't support this feature yet.

The change is based on the following semantic patch, with manual review
and edits.

@ rule1 @
identifier funcs;
identifier fn;
@@
 struct drm_bridge_funcs funcs = {
 	...,
 	.attach = fn
 };

@ depends on rule1 @
identifier rule1.fn;
identifier bridge;
statement S, S1;
@@
 int fn(
 	struct drm_bridge *bridge
+	, enum drm_bridge_attach_flags flags
 )
 {
 	... when != S
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+		return -EINVAL;
+
 	S1
 	...
 }

@@
expression E1, E2, E3;
@@
 drm_bridge_attach(E1, E2, E3
+	, 0
 )

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v1:

- Replace the create_connector boolean with a flags bitmask
- Update ingenic driver
- Add semantic patch to commit message
---
 drivers/gpu/drm/arc/arcpgu_hdmi.c             |  2 +-
 .../gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c  |  2 +-
 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c  |  6 +++++-
 drivers/gpu/drm/bridge/analogix-anx78xx.c     |  6 +++++-
 .../drm/bridge/analogix/analogix_dp_core.c    |  8 ++++++--
 drivers/gpu/drm/bridge/cdns-dsi.c             |  6 ++++--
 drivers/gpu/drm/bridge/dumb-vga-dac.c         |  6 +++++-
 drivers/gpu/drm/bridge/lvds-encoder.c         |  5 +++--
 .../bridge/megachips-stdpxxxx-ge-b850v3-fw.c  |  6 +++++-
 drivers/gpu/drm/bridge/nxp-ptn3460.c          |  6 +++++-
 drivers/gpu/drm/bridge/panel.c                |  6 +++++-
 drivers/gpu/drm/bridge/parade-ps8622.c        |  6 +++++-
 drivers/gpu/drm/bridge/sii902x.c              |  6 +++++-
 drivers/gpu/drm/bridge/sil-sii8620.c          |  3 ++-
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c     |  8 ++++++--
 drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c |  8 +++++---
 drivers/gpu/drm/bridge/tc358764.c             |  6 +++++-
 drivers/gpu/drm/bridge/tc358767.c             |  6 +++++-
 drivers/gpu/drm/bridge/thc63lvd1024.c         |  5 +++--
 drivers/gpu/drm/bridge/ti-sn65dsi86.c         |  6 +++++-
 drivers/gpu/drm/bridge/ti-tfp410.c            |  6 +++++-
 drivers/gpu/drm/drm_bridge.c                  |  6 ++++--
 drivers/gpu/drm/drm_simple_kms_helper.c       |  2 +-
 drivers/gpu/drm/exynos/exynos_dp.c            |  3 ++-
 drivers/gpu/drm/exynos/exynos_drm_dsi.c       |  4 ++--
 drivers/gpu/drm/exynos/exynos_hdmi.c          |  2 +-
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c     |  2 +-
 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c  |  2 +-
 drivers/gpu/drm/i2c/tda998x_drv.c             |  8 ++++++--
 drivers/gpu/drm/imx/imx-ldb.c                 |  2 +-
 drivers/gpu/drm/imx/parallel-display.c        |  2 +-
 drivers/gpu/drm/ingenic/ingenic-drm.c         |  2 +-
 drivers/gpu/drm/mcde/mcde_dsi.c               |  8 ++++++--
 drivers/gpu/drm/mediatek/mtk_dpi.c            |  2 +-
 drivers/gpu/drm/mediatek/mtk_dsi.c            |  2 +-
 drivers/gpu/drm/mediatek/mtk_hdmi.c           |  8 ++++++--
 drivers/gpu/drm/msm/dsi/dsi_manager.c         |  4 ++--
 drivers/gpu/drm/msm/edp/edp_bridge.c          |  2 +-
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c        |  2 +-
 drivers/gpu/drm/omapdrm/omap_drv.c            |  2 +-
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c     |  2 +-
 drivers/gpu/drm/rcar-du/rcar_lvds.c           |  8 ++++++--
 drivers/gpu/drm/rockchip/rockchip_lvds.c      |  2 +-
 drivers/gpu/drm/rockchip/rockchip_rgb.c       |  2 +-
 drivers/gpu/drm/sti/sti_dvo.c                 |  2 +-
 drivers/gpu/drm/sti/sti_hda.c                 |  2 +-
 drivers/gpu/drm/sti/sti_hdmi.c                |  2 +-
 drivers/gpu/drm/stm/ltdc.c                    |  2 +-
 drivers/gpu/drm/sun4i/sun4i_lvds.c            |  2 +-
 drivers/gpu/drm/sun4i/sun4i_rgb.c             |  2 +-
 drivers/gpu/drm/tilcdc/tilcdc_external.c      |  2 +-
 drivers/gpu/drm/vc4/vc4_dpi.c                 |  2 +-
 drivers/gpu/drm/vc4/vc4_dsi.c                 |  2 +-
 include/drm/drm_bridge.h                      | 20 ++++++++++++++++---
 54 files changed, 166 insertions(+), 70 deletions(-)

diff --git a/drivers/gpu/drm/arc/arcpgu_hdmi.c b/drivers/gpu/drm/arc/arcpgu_hdmi.c
index 98aac743cc26..ab023e070529 100644
--- a/drivers/gpu/drm/arc/arcpgu_hdmi.c
+++ b/drivers/gpu/drm/arc/arcpgu_hdmi.c
@@ -39,7 +39,7 @@ int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np)
 		return ret;
 
 	/* Link drm_bridge to encoder */
-	ret = drm_bridge_attach(encoder, bridge, NULL);
+	ret = drm_bridge_attach(encoder, bridge, NULL, 0);
 	if (ret)
 		drm_encoder_cleanup(encoder);
 
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
index 375fa84c548b..c388497366ca 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
@@ -113,7 +113,7 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, int endpoint)
 	}
 
 	if (bridge) {
-		ret = drm_bridge_attach(&output->encoder, bridge, NULL);
+		ret = drm_bridge_attach(&output->encoder, bridge, NULL, 0);
 		if (!ret)
 			return 0;
 
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index 98bccace8c1c..6e42d5e05d07 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -847,11 +847,15 @@ static void adv7511_bridge_mode_set(struct drm_bridge *bridge,
 	adv7511_mode_set(adv, mode, adj_mode);
 }
 
-static int adv7511_bridge_attach(struct drm_bridge *bridge)
+static int adv7511_bridge_attach(struct drm_bridge *bridge,
+				 enum drm_bridge_attach_flags flags)
 {
 	struct adv7511 *adv = bridge_to_adv7511(bridge);
 	int ret;
 
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+		return -EINVAL;
+
 	if (!bridge->encoder) {
 		DRM_ERROR("Parent encoder object not found");
 		return -ENODEV;
diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix-anx78xx.c
index 3c7cc5af735c..995a54547fbe 100644
--- a/drivers/gpu/drm/bridge/analogix-anx78xx.c
+++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c
@@ -998,11 +998,15 @@ static const struct drm_connector_funcs anx78xx_connector_funcs = {
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
-static int anx78xx_bridge_attach(struct drm_bridge *bridge)
+static int anx78xx_bridge_attach(struct drm_bridge *bridge,
+				 enum drm_bridge_attach_flags flags)
 {
 	struct anx78xx *anx78xx = bridge_to_anx78xx(bridge);
 	int err;
 
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+		return -EINVAL;
+
 	if (!bridge->encoder) {
 		DRM_ERROR("Parent encoder object not found");
 		return -ENODEV;
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 22885dceaa17..d903eed368e3 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1215,13 +1215,17 @@ static const struct drm_connector_funcs analogix_dp_connector_funcs = {
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
-static int analogix_dp_bridge_attach(struct drm_bridge *bridge)
+static int analogix_dp_bridge_attach(struct drm_bridge *bridge,
+				     enum drm_bridge_attach_flags flags)
 {
 	struct analogix_dp_device *dp = bridge->driver_private;
 	struct drm_encoder *encoder = dp->encoder;
 	struct drm_connector *connector = NULL;
 	int ret = 0;
 
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+		return -EINVAL;
+
 	if (!bridge->encoder) {
 		DRM_ERROR("Parent encoder object not found");
 		return -ENODEV;
@@ -1587,7 +1591,7 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev,
 	bridge->driver_private = dp;
 	bridge->funcs = &analogix_dp_bridge_funcs;
 
-	ret = drm_bridge_attach(dp->encoder, bridge, NULL);
+	ret = drm_bridge_attach(dp->encoder, bridge, NULL, 0);
 	if (ret) {
 		DRM_ERROR("failed to attach drm bridge\n");
 		return -EINVAL;
diff --git a/drivers/gpu/drm/bridge/cdns-dsi.c b/drivers/gpu/drm/bridge/cdns-dsi.c
index 6166dca6be81..2af7f25c7413 100644
--- a/drivers/gpu/drm/bridge/cdns-dsi.c
+++ b/drivers/gpu/drm/bridge/cdns-dsi.c
@@ -645,7 +645,8 @@ static int cdns_dsi_check_conf(struct cdns_dsi *dsi,
 	return 0;
 }
 
-static int cdns_dsi_bridge_attach(struct drm_bridge *bridge)
+static int cdns_dsi_bridge_attach(struct drm_bridge *bridge,
+				  enum drm_bridge_attach_flags flags)
 {
 	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
 	struct cdns_dsi *dsi = input_to_dsi(input);
@@ -657,7 +658,8 @@ static int cdns_dsi_bridge_attach(struct drm_bridge *bridge)
 		return -ENOTSUPP;
 	}
 
-	return drm_bridge_attach(bridge->encoder, output->bridge, bridge);
+	return drm_bridge_attach(bridge->encoder, output->bridge, bridge,
+				 flags);
 }
 
 static enum drm_mode_status
diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
index 7aa789c35882..74ebca58eb1f 100644
--- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
+++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
@@ -99,11 +99,15 @@ static const struct drm_connector_funcs dumb_vga_con_funcs = {
 	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
 };
 
-static int dumb_vga_attach(struct drm_bridge *bridge)
+static int dumb_vga_attach(struct drm_bridge *bridge,
+			   enum drm_bridge_attach_flags flags)
 {
 	struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
 	int ret;
 
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+		return -EINVAL;
+
 	if (!bridge->encoder) {
 		DRM_ERROR("Missing encoder\n");
 		return -ENODEV;
diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c b/drivers/gpu/drm/bridge/lvds-encoder.c
index 2ab2c234f26c..9ebc750449cf 100644
--- a/drivers/gpu/drm/bridge/lvds-encoder.c
+++ b/drivers/gpu/drm/bridge/lvds-encoder.c
@@ -18,14 +18,15 @@ struct lvds_encoder {
 	struct gpio_desc *powerdown_gpio;
 };
 
-static int lvds_encoder_attach(struct drm_bridge *bridge)
+static int lvds_encoder_attach(struct drm_bridge *bridge,
+			       enum drm_bridge_attach_flags flags)
 {
 	struct lvds_encoder *lvds_encoder = container_of(bridge,
 							 struct lvds_encoder,
 							 bridge);
 
 	return drm_bridge_attach(bridge->encoder, lvds_encoder->panel_bridge,
-				 bridge);
+				 bridge, flags);
 }
 
 static void lvds_encoder_enable(struct drm_bridge *bridge)
diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
index 6e81e5db57f2..1380291f6672 100644
--- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
+++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
@@ -205,13 +205,17 @@ static irqreturn_t ge_b850v3_lvds_irq_handler(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int ge_b850v3_lvds_attach(struct drm_bridge *bridge)
+static int ge_b850v3_lvds_attach(struct drm_bridge *bridge,
+				 enum drm_bridge_attach_flags flags)
 {
 	struct drm_connector *connector = &ge_b850v3_lvds_ptr->connector;
 	struct i2c_client *stdp4028_i2c
 			= ge_b850v3_lvds_ptr->stdp4028_i2c;
 	int ret;
 
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+		return -EINVAL;
+
 	if (!bridge->encoder) {
 		DRM_ERROR("Parent encoder object not found");
 		return -ENODEV;
diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c
index d4a1cc5052c3..42c69e9d0d70 100644
--- a/drivers/gpu/drm/bridge/nxp-ptn3460.c
+++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c
@@ -235,11 +235,15 @@ static const struct drm_connector_funcs ptn3460_connector_funcs = {
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
-static int ptn3460_bridge_attach(struct drm_bridge *bridge)
+static int ptn3460_bridge_attach(struct drm_bridge *bridge,
+				 enum drm_bridge_attach_flags flags)
 {
 	struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge);
 	int ret;
 
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+		return -EINVAL;
+
 	if (!bridge->encoder) {
 		DRM_ERROR("Parent encoder object not found");
 		return -ENODEV;
diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index b12ae3a4c5f1..f5b8e55301ac 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -52,12 +52,16 @@ static const struct drm_connector_funcs panel_bridge_connector_funcs = {
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
-static int panel_bridge_attach(struct drm_bridge *bridge)
+static int panel_bridge_attach(struct drm_bridge *bridge,
+			       enum drm_bridge_attach_flags flags)
 {
 	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
 	struct drm_connector *connector = &panel_bridge->connector;
 	int ret;
 
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+		return -EINVAL;
+
 	if (!bridge->encoder) {
 		DRM_ERROR("Missing encoder\n");
 		return -ENODEV;
diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c
index 93c68e2e9484..816482df27a8 100644
--- a/drivers/gpu/drm/bridge/parade-ps8622.c
+++ b/drivers/gpu/drm/bridge/parade-ps8622.c
@@ -475,11 +475,15 @@ static const struct drm_connector_funcs ps8622_connector_funcs = {
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
-static int ps8622_attach(struct drm_bridge *bridge)
+static int ps8622_attach(struct drm_bridge *bridge,
+			 enum drm_bridge_attach_flags flags)
 {
 	struct ps8622_bridge *ps8622 = bridge_to_ps8622(bridge);
 	int ret;
 
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+		return -EINVAL;
+
 	if (!bridge->encoder) {
 		DRM_ERROR("Parent encoder object not found");
 		return -ENODEV;
diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
index 38f75ac580df..51f5d7e8e360 100644
--- a/drivers/gpu/drm/bridge/sii902x.c
+++ b/drivers/gpu/drm/bridge/sii902x.c
@@ -398,12 +398,16 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
 	mutex_unlock(&sii902x->mutex);
 }
 
-static int sii902x_bridge_attach(struct drm_bridge *bridge)
+static int sii902x_bridge_attach(struct drm_bridge *bridge,
+				 enum drm_bridge_attach_flags flags)
 {
 	struct sii902x *sii902x = bridge_to_sii902x(bridge);
 	struct drm_device *drm = bridge->dev;
 	int ret;
 
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+		return -EINVAL;
+
 	drm_connector_helper_add(&sii902x->connector,
 				 &sii902x_connector_helper_funcs);
 
diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
index bd3165ee5354..461bdeb32568 100644
--- a/drivers/gpu/drm/bridge/sil-sii8620.c
+++ b/drivers/gpu/drm/bridge/sil-sii8620.c
@@ -2200,7 +2200,8 @@ static inline struct sii8620 *bridge_to_sii8620(struct drm_bridge *bridge)
 	return container_of(bridge, struct sii8620, bridge);
 }
 
-static int sii8620_attach(struct drm_bridge *bridge)
+static int sii8620_attach(struct drm_bridge *bridge,
+			  enum drm_bridge_attach_flags flags)
 {
 	struct sii8620 *ctx = bridge_to_sii8620(bridge);
 
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 4044071090c4..cb86c4705ce8 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2225,12 +2225,16 @@ static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs =
 	.get_modes = dw_hdmi_connector_get_modes,
 };
 
-static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
+static int dw_hdmi_bridge_attach(struct drm_bridge *bridge,
+				 enum drm_bridge_attach_flags flags)
 {
 	struct dw_hdmi *hdmi = bridge->driver_private;
 	struct drm_encoder *encoder = bridge->encoder;
 	struct drm_connector *connector = &hdmi->connector;
 
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+		return -EINVAL;
+
 	connector->interlace_allowed = 1;
 	connector->polled = DRM_CONNECTOR_POLL_HPD;
 
@@ -2911,7 +2915,7 @@ struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev,
 	if (IS_ERR(hdmi))
 		return hdmi;
 
-	ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL);
+	ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL, 0);
 	if (ret) {
 		dw_hdmi_remove(hdmi);
 		DRM_ERROR("Failed to initialize bridge with drm\n");
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index 675442bfc1bd..9245dde314a8 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -923,7 +923,8 @@ dw_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge,
 	return mode_status;
 }
 
-static int dw_mipi_dsi_bridge_attach(struct drm_bridge *bridge)
+static int dw_mipi_dsi_bridge_attach(struct drm_bridge *bridge,
+				     enum drm_bridge_attach_flags flags)
 {
 	struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
 
@@ -936,7 +937,8 @@ static int dw_mipi_dsi_bridge_attach(struct drm_bridge *bridge)
 	bridge->encoder->encoder_type = DRM_MODE_ENCODER_DSI;
 
 	/* Attach the panel-bridge to the dsi bridge */
-	return drm_bridge_attach(bridge->encoder, dsi->panel_bridge, bridge);
+	return drm_bridge_attach(bridge->encoder, dsi->panel_bridge, bridge,
+				 flags);
 }
 
 static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = {
@@ -1111,7 +1113,7 @@ int dw_mipi_dsi_bind(struct dw_mipi_dsi *dsi, struct drm_encoder *encoder)
 {
 	int ret;
 
-	ret = drm_bridge_attach(encoder, &dsi->bridge, NULL);
+	ret = drm_bridge_attach(encoder, &dsi->bridge, NULL, true);
 	if (ret) {
 		DRM_ERROR("Failed to initialize bridge with drm\n");
 		return ret;
diff --git a/drivers/gpu/drm/bridge/tc358764.c b/drivers/gpu/drm/bridge/tc358764.c
index 170f162ffa55..ea768d2b80bb 100644
--- a/drivers/gpu/drm/bridge/tc358764.c
+++ b/drivers/gpu/drm/bridge/tc358764.c
@@ -348,12 +348,16 @@ static void tc358764_enable(struct drm_bridge *bridge)
 		dev_err(ctx->dev, "error enabling panel (%d)\n", ret);
 }
 
-static int tc358764_attach(struct drm_bridge *bridge)
+static int tc358764_attach(struct drm_bridge *bridge,
+			   enum drm_bridge_attach_flags flags)
 {
 	struct tc358764 *ctx = bridge_to_tc358764(bridge);
 	struct drm_device *drm = bridge->dev;
 	int ret;
 
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+		return -EINVAL;
+
 	ctx->connector.polled = DRM_CONNECTOR_POLL_HPD;
 	ret = drm_connector_init(drm, &ctx->connector,
 				 &tc358764_connector_funcs,
diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
index cebc8e620820..f90d72a85164 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -1378,13 +1378,17 @@ static const struct drm_connector_funcs tc_connector_funcs = {
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
-static int tc_bridge_attach(struct drm_bridge *bridge)
+static int tc_bridge_attach(struct drm_bridge *bridge,
+			    enum drm_bridge_attach_flags flags)
 {
 	u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
 	struct tc_data *tc = bridge_to_tc(bridge);
 	struct drm_device *drm = bridge->dev;
 	int ret;
 
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+		return -EINVAL;
+
 	/* Create DP/eDP connector */
 	drm_connector_helper_add(&tc->connector, &tc_connector_helper_funcs);
 	ret = drm_connector_init(drm, &tc->connector, &tc_connector_funcs,
diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c b/drivers/gpu/drm/bridge/thc63lvd1024.c
index 3d74129b2995..97d8129760e9 100644
--- a/drivers/gpu/drm/bridge/thc63lvd1024.c
+++ b/drivers/gpu/drm/bridge/thc63lvd1024.c
@@ -42,11 +42,12 @@ static inline struct thc63_dev *to_thc63(struct drm_bridge *bridge)
 	return container_of(bridge, struct thc63_dev, bridge);
 }
 
-static int thc63_attach(struct drm_bridge *bridge)
+static int thc63_attach(struct drm_bridge *bridge,
+			enum drm_bridge_attach_flags flags)
 {
 	struct thc63_dev *thc63 = to_thc63(bridge);
 
-	return drm_bridge_attach(bridge->encoder, thc63->next, bridge);
+	return drm_bridge_attach(bridge->encoder, thc63->next, bridge, flags);
 }
 
 static enum drm_mode_status thc63_mode_valid(struct drm_bridge *bridge,
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
index 0a580957c8cf..e970d3fbc20b 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -263,7 +263,8 @@ static int ti_sn_bridge_parse_regulators(struct ti_sn_bridge *pdata)
 				       pdata->supplies);
 }
 
-static int ti_sn_bridge_attach(struct drm_bridge *bridge)
+static int ti_sn_bridge_attach(struct drm_bridge *bridge,
+			       enum drm_bridge_attach_flags flags)
 {
 	int ret, val;
 	struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge);
@@ -274,6 +275,9 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge)
 						   .node = NULL,
 						 };
 
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+		return -EINVAL;
+
 	ret = drm_connector_init(bridge->dev, &pdata->connector,
 				 &ti_sn_bridge_connector_funcs,
 				 DRM_MODE_CONNECTOR_eDP);
diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
index 61cc2354ef1b..a9359038f7dc 100644
--- a/drivers/gpu/drm/bridge/ti-tfp410.c
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -117,11 +117,15 @@ static const struct drm_connector_funcs tfp410_con_funcs = {
 	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
 };
 
-static int tfp410_attach(struct drm_bridge *bridge)
+static int tfp410_attach(struct drm_bridge *bridge,
+			 enum drm_bridge_attach_flags flags)
 {
 	struct tfp410 *dvi = drm_bridge_to_tfp410(bridge);
 	int ret;
 
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+		return -EINVAL;
+
 	if (!bridge->encoder) {
 		dev_err(dvi->dev, "Missing encoder\n");
 		return -ENODEV;
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index cf1fbed88410..814027a98fcb 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -99,6 +99,7 @@ EXPORT_SYMBOL(drm_bridge_remove);
  * @encoder: DRM encoder
  * @bridge: bridge to attach
  * @previous: previous bridge in the chain (optional)
+ * @flags: DRM_BRIDGE_ATTACH_* flags
  *
  * Called by a kms driver to link the bridge to an encoder's chain. The previous
  * argument specifies the previous bridge in the chain. If NULL, the bridge is
@@ -116,7 +117,8 @@ EXPORT_SYMBOL(drm_bridge_remove);
  * Zero on success, error code on failure
  */
 int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
-		      struct drm_bridge *previous)
+		      struct drm_bridge *previous,
+		      enum drm_bridge_attach_flags flags)
 {
 	int ret;
 
@@ -133,7 +135,7 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
 	bridge->encoder = encoder;
 
 	if (bridge->funcs->attach) {
-		ret = bridge->funcs->attach(bridge);
+		ret = bridge->funcs->attach(bridge, flags);
 		if (ret < 0) {
 			bridge->dev = NULL;
 			bridge->encoder = NULL;
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
index b11910f14c46..ea105d137066 100644
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
@@ -228,7 +228,7 @@ static const struct drm_plane_funcs drm_simple_kms_plane_funcs = {
 int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe,
 					  struct drm_bridge *bridge)
 {
-	return drm_bridge_attach(&pipe->encoder, bridge, NULL);
+	return drm_bridge_attach(&pipe->encoder, bridge, NULL, 0);
 }
 EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
 
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
index 3a0f0ba8c63a..3f79c8151aad 100644
--- a/drivers/gpu/drm/exynos/exynos_dp.c
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
@@ -105,7 +105,8 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
 
 	/* Pre-empt DP connector creation if there's a bridge */
 	if (dp->ptn_bridge) {
-		ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge);
+		ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge,
+					0);
 		if (ret) {
 			DRM_DEV_ERROR(dp->dev,
 				      "Failed to attach bridge to drm\n");
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 6926cee91b36..a84a1979e327 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1519,7 +1519,7 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
 
 	out_bridge  = of_drm_find_bridge(device->dev.of_node);
 	if (out_bridge) {
-		drm_bridge_attach(encoder, out_bridge, NULL);
+		drm_bridge_attach(encoder, out_bridge, NULL, 0);
 		dsi->out_bridge = out_bridge;
 		encoder->bridge = NULL;
 	} else {
@@ -1695,7 +1695,7 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
 	if (dsi->in_bridge_node) {
 		in_bridge = of_drm_find_bridge(dsi->in_bridge_node);
 		if (in_bridge)
-			drm_bridge_attach(encoder, in_bridge, NULL);
+			drm_bridge_attach(encoder, in_bridge, NULL, 0);
 	}
 
 	return mipi_dsi_host_register(&dsi->dsi_host);
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index bc1565f1822a..9978743ee058 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -952,7 +952,7 @@ static int hdmi_create_connector(struct drm_encoder *encoder)
 	drm_connector_attach_encoder(connector, encoder);
 
 	if (hdata->bridge) {
-		ret = drm_bridge_attach(encoder, hdata->bridge, NULL);
+		ret = drm_bridge_attach(encoder, hdata->bridge, NULL, 0);
 		if (ret)
 			DRM_DEV_ERROR(hdata->dev, "Failed to attach bridge\n");
 	}
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
index a92fd6c70b09..900a33e1d2fb 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
@@ -150,5 +150,5 @@ int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
 		return fsl_dcu_attach_panel(fsl_dev, panel);
 	}
 
-	return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
+	return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL, 0);
 }
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
index 5bf8138941de..43543a0877a9 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
@@ -776,7 +776,7 @@ static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi)
 	int ret;
 
 	/* associate the bridge to dsi encoder */
-	ret = drm_bridge_attach(encoder, bridge, NULL);
+	ret = drm_bridge_attach(encoder, bridge, NULL, 0);
 	if (ret) {
 		DRM_ERROR("failed to attach external bridge\n");
 		return ret;
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 84c6d4c91c65..3f9a3d5dbdeb 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -1355,10 +1355,14 @@ static int tda998x_connector_init(struct tda998x_priv *priv,
 
 /* DRM bridge functions */
 
-static int tda998x_bridge_attach(struct drm_bridge *bridge)
+static int tda998x_bridge_attach(struct drm_bridge *bridge,
+				 enum drm_bridge_attach_flags flags)
 {
 	struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
 
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+		return -EINVAL;
+
 	return tda998x_connector_init(priv, bridge->dev);
 }
 
@@ -2022,7 +2026,7 @@ static int tda998x_encoder_init(struct device *dev, struct drm_device *drm)
 	if (ret)
 		goto err_encoder;
 
-	ret = drm_bridge_attach(&priv->encoder, &priv->bridge, NULL);
+	ret = drm_bridge_attach(&priv->encoder, &priv->bridge, NULL, 0);
 	if (ret)
 		goto err_bridge;
 
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index 695f307f36b2..6358e9733398 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -445,7 +445,7 @@ static int imx_ldb_register(struct drm_device *drm,
 
 	if (imx_ldb_ch->bridge) {
 		ret = drm_bridge_attach(&imx_ldb_ch->encoder,
-					imx_ldb_ch->bridge, NULL);
+					imx_ldb_ch->bridge, NULL, 0);
 		if (ret) {
 			DRM_ERROR("Failed to initialize bridge with drm\n");
 			return ret;
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
index e7ce17503ae1..e385ce5deb90 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -181,7 +181,7 @@ static int imx_pd_register(struct drm_device *drm,
 		drm_panel_attach(imxpd->panel, &imxpd->connector);
 
 	if (imxpd->bridge) {
-		ret = drm_bridge_attach(encoder, imxpd->bridge, NULL);
+		ret = drm_bridge_attach(encoder, imxpd->bridge, NULL, 0);
 		if (ret < 0) {
 			dev_err(imxpd->dev, "failed to attach bridge: %d\n",
 				ret);
diff --git a/drivers/gpu/drm/ingenic/ingenic-drm.c b/drivers/gpu/drm/ingenic/ingenic-drm.c
index ce1fae3a78a9..65eb10179ea9 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm.c
@@ -726,7 +726,7 @@ static int ingenic_drm_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = drm_bridge_attach(&priv->encoder, bridge, NULL);
+	ret = drm_bridge_attach(&priv->encoder, bridge, NULL, 0);
 	if (ret) {
 		dev_err(dev, "Unable to attach bridge");
 		return ret;
diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c
index 07f7090d08b3..8feaa1b81473 100644
--- a/drivers/gpu/drm/mcde/mcde_dsi.c
+++ b/drivers/gpu/drm/mcde/mcde_dsi.c
@@ -817,12 +817,16 @@ mcde_dsi_connector_helper_funcs = {
 	.get_modes = mcde_dsi_get_modes,
 };
 
-static int mcde_dsi_bridge_attach(struct drm_bridge *bridge)
+static int mcde_dsi_bridge_attach(struct drm_bridge *bridge,
+				  enum drm_bridge_attach_flags flags)
 {
 	struct mcde_dsi *d = bridge_to_mcde_dsi(bridge);
 	struct drm_device *drm = bridge->dev;
 	int ret;
 
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+		return -EINVAL;
+
 	drm_connector_helper_add(&d->connector,
 				 &mcde_dsi_connector_helper_funcs);
 
@@ -842,7 +846,7 @@ static int mcde_dsi_bridge_attach(struct drm_bridge *bridge)
 	/* The encoder in the bridge attached to the DSI bridge */
 	drm_connector_attach_encoder(&d->connector, bridge->encoder);
 	/* Then we attach the DSI bridge to the output (panel etc) bridge */
-	ret = drm_bridge_attach(bridge->encoder, d->bridge_out, bridge);
+	ret = drm_bridge_attach(bridge->encoder, d->bridge_out, bridge, flags);
 	if (ret) {
 		dev_err(d->dev, "failed to attach the DSI bridge\n");
 		return ret;
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
index be6d95c5ff25..cfb47b054d20 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -606,7 +606,7 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)
 	/* Currently DPI0 is fixed to be driven by OVL1 */
 	dpi->encoder.possible_crtcs = BIT(1);
 
-	ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL);
+	ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL, 0);
 	if (ret) {
 		dev_err(dev, "Failed to attach bridge: %d\n", ret);
 		goto err_cleanup;
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 224afb666881..d1129d4077a9 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -821,7 +821,7 @@ static int mtk_dsi_create_conn_enc(struct drm_device *drm, struct mtk_dsi *dsi)
 
 	/* If there's a bridge, attach to it and let it create the connector */
 	if (dsi->bridge) {
-		ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL);
+		ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL, 0);
 		if (ret) {
 			DRM_ERROR("Failed to attach bridge to drm\n");
 			goto err_encoder_cleanup;
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index ce91b61364eb..f0e55f219772 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -1294,11 +1294,15 @@ static void mtk_hdmi_hpd_event(bool hpd, struct device *dev)
  * Bridge callbacks
  */
 
-static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge)
+static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge,
+				  enum drm_bridge_attach_flags flags)
 {
 	struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
 	int ret;
 
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+		return -EINVAL;
+
 	ret = drm_connector_init(bridge->encoder->dev, &hdmi->conn,
 				 &mtk_hdmi_connector_funcs,
 				 DRM_MODE_CONNECTOR_HDMIA);
@@ -1322,7 +1326,7 @@ static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge)
 
 	if (hdmi->next_bridge) {
 		ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge,
-					bridge);
+					bridge, flags);
 		if (ret) {
 			dev_err(hdmi->dev,
 				"Failed to attach external bridge: %d\n", ret);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 271aa7bbca92..50b9bddf92b3 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -664,7 +664,7 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
 	bridge = &dsi_bridge->base;
 	bridge->funcs = &dsi_mgr_bridge_funcs;
 
-	ret = drm_bridge_attach(encoder, bridge, NULL);
+	ret = drm_bridge_attach(encoder, bridge, NULL, 0);
 	if (ret)
 		goto fail;
 
@@ -693,7 +693,7 @@ struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id)
 	encoder = msm_dsi->encoder;
 
 	/* link the internal dsi bridge to the external bridge */
-	drm_bridge_attach(encoder, ext_bridge, int_bridge);
+	drm_bridge_attach(encoder, ext_bridge, int_bridge, 0);
 
 	/*
 	 * we need the drm_connector created by the external bridge
diff --git a/drivers/gpu/drm/msm/edp/edp_bridge.c b/drivers/gpu/drm/msm/edp/edp_bridge.c
index 2950bba4aca9..b59451d9712c 100644
--- a/drivers/gpu/drm/msm/edp/edp_bridge.c
+++ b/drivers/gpu/drm/msm/edp/edp_bridge.c
@@ -91,7 +91,7 @@ struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp)
 	bridge = &edp_bridge->base;
 	bridge->funcs = &edp_bridge_funcs;
 
-	ret = drm_bridge_attach(edp->encoder, bridge, NULL);
+	ret = drm_bridge_attach(edp->encoder, bridge, NULL, 0);
 	if (ret)
 		goto fail;
 
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index c8dbd82854c2..7a685f0edd88 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -285,7 +285,7 @@ struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
 	bridge = &hdmi_bridge->base;
 	bridge->funcs = &msm_hdmi_bridge_funcs;
 
-	ret = drm_bridge_attach(hdmi->encoder, bridge, NULL);
+	ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, 0);
 	if (ret)
 		goto fail;
 
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 9f652d2e7af1..2988af9ae743 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -296,7 +296,7 @@ static int omap_modeset_init(struct drm_device *dev)
 
 		if (pipe->output->bridge) {
 			ret = drm_bridge_attach(pipe->encoder,
-						pipe->output->bridge, NULL);
+						pipe->output->bridge, NULL, 0);
 			if (ret < 0)
 				return ret;
 		}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index 0f00bdfe2366..26603843c318 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -120,7 +120,7 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
 	 * Attach the bridge to the encoder. The bridge will create the
 	 * connector.
 	 */
-	ret = drm_bridge_attach(encoder, bridge, NULL);
+	ret = drm_bridge_attach(encoder, bridge, NULL, 0);
 	if (ret) {
 		drm_encoder_cleanup(encoder);
 		return ret;
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c
index 1c62578590f4..7e976723c9b1 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
@@ -605,7 +605,8 @@ static void rcar_lvds_mode_set(struct drm_bridge *bridge,
 	rcar_lvds_get_lvds_mode(lvds);
 }
 
-static int rcar_lvds_attach(struct drm_bridge *bridge)
+static int rcar_lvds_attach(struct drm_bridge *bridge,
+			    enum drm_bridge_attach_flags flags)
 {
 	struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
 	struct drm_connector *connector = &lvds->connector;
@@ -615,7 +616,10 @@ static int rcar_lvds_attach(struct drm_bridge *bridge)
 	/* If we have a next bridge just attach it. */
 	if (lvds->next_bridge)
 		return drm_bridge_attach(bridge->encoder, lvds->next_bridge,
-					 bridge);
+					 bridge, flags);
+
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+		return -EINVAL;
 
 	/* Otherwise if we have a panel, create a connector. */
 	if (!lvds->panel)
diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c
index 64aefa856896..addf56209f46 100644
--- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
+++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
@@ -440,7 +440,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
 			goto err_free_connector;
 		}
 	} else {
-		ret = drm_bridge_attach(encoder, lvds->bridge, NULL);
+		ret = drm_bridge_attach(encoder, lvds->bridge, NULL, 0);
 		if (ret) {
 			DRM_DEV_ERROR(drm_dev->dev,
 				      "failed to attach bridge: %d\n", ret);
diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.c b/drivers/gpu/drm/rockchip/rockchip_rgb.c
index 89e0bb0fe0ab..f586e06f3df2 100644
--- a/drivers/gpu/drm/rockchip/rockchip_rgb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_rgb.c
@@ -142,7 +142,7 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev,
 
 	rgb->bridge = bridge;
 
-	ret = drm_bridge_attach(encoder, rgb->bridge, NULL);
+	ret = drm_bridge_attach(encoder, rgb->bridge, NULL, 0);
 	if (ret) {
 		DRM_DEV_ERROR(drm_dev->dev,
 			      "failed to attach bridge: %d\n", ret);
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
index e55870190bf5..0baca6368c36 100644
--- a/drivers/gpu/drm/sti/sti_dvo.c
+++ b/drivers/gpu/drm/sti/sti_dvo.c
@@ -466,7 +466,7 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
 	bridge->of_node = dvo->dev.of_node;
 	drm_bridge_add(bridge);
 
-	err = drm_bridge_attach(encoder, bridge, NULL);
+	err = drm_bridge_attach(encoder, bridge, NULL, 0);
 	if (err) {
 		DRM_ERROR("Failed to attach bridge\n");
 		return err;
diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
index 94e404f13234..6a3d8b800950 100644
--- a/drivers/gpu/drm/sti/sti_hda.c
+++ b/drivers/gpu/drm/sti/sti_hda.c
@@ -700,7 +700,7 @@ static int sti_hda_bind(struct device *dev, struct device *master, void *data)
 
 	bridge->driver_private = hda;
 	bridge->funcs = &sti_hda_bridge_funcs;
-	drm_bridge_attach(encoder, bridge, NULL);
+	drm_bridge_attach(encoder, bridge, NULL, 0);
 
 	connector->encoder = encoder;
 
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index 9862c322f0c4..2d080a6040d9 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -1279,7 +1279,7 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
 
 	bridge->driver_private = hdmi;
 	bridge->funcs = &sti_hdmi_bridge_funcs;
-	drm_bridge_attach(encoder, bridge, NULL);
+	drm_bridge_attach(encoder, bridge, NULL, 0);
 
 	connector->encoder = encoder;
 
diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
index 3ab4fbf8eb0d..18561d977d84 100644
--- a/drivers/gpu/drm/stm/ltdc.c
+++ b/drivers/gpu/drm/stm/ltdc.c
@@ -1055,7 +1055,7 @@ static int ltdc_encoder_init(struct drm_device *ddev, struct drm_bridge *bridge)
 	drm_encoder_init(ddev, encoder, &ltdc_encoder_funcs,
 			 DRM_MODE_ENCODER_DPI, NULL);
 
-	ret = drm_bridge_attach(encoder, bridge, NULL);
+	ret = drm_bridge_attach(encoder, bridge, NULL, 0);
 	if (ret) {
 		drm_encoder_cleanup(encoder);
 		return -EINVAL;
diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c
index 7fbf425acb55..693163c70eee 100644
--- a/drivers/gpu/drm/sun4i/sun4i_lvds.c
+++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c
@@ -155,7 +155,7 @@ int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon)
 	}
 
 	if (bridge) {
-		ret = drm_bridge_attach(encoder, bridge, NULL);
+		ret = drm_bridge_attach(encoder, bridge, NULL, 0);
 		if (ret) {
 			dev_err(drm->dev, "Couldn't attach our bridge\n");
 			goto err_cleanup_connector;
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index aac56983f208..22463f5302c4 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -252,7 +252,7 @@ int sun4i_rgb_init(struct drm_device *drm, struct sun4i_tcon *tcon)
 	}
 
 	if (rgb->bridge) {
-		ret = drm_bridge_attach(encoder, rgb->bridge, NULL);
+		ret = drm_bridge_attach(encoder, rgb->bridge, NULL, 0);
 		if (ret) {
 			dev_err(drm->dev, "Couldn't attach our bridge\n");
 			goto err_cleanup_connector;
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_external.c b/drivers/gpu/drm/tilcdc/tilcdc_external.c
index 43d756b7810e..1ed765ce9349 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_external.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c
@@ -94,7 +94,7 @@ int tilcdc_attach_bridge(struct drm_device *ddev, struct drm_bridge *bridge)
 
 	priv->external_encoder->possible_crtcs = BIT(0);
 
-	ret = drm_bridge_attach(priv->external_encoder, bridge, NULL);
+	ret = drm_bridge_attach(priv->external_encoder, bridge, NULL, 0);
 	if (ret) {
 		dev_err(ddev->dev, "drm_bridge_attach() failed %d\n", ret);
 		return ret;
diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c
index 8a27a6acee61..59662d735432 100644
--- a/drivers/gpu/drm/vc4/vc4_dpi.c
+++ b/drivers/gpu/drm/vc4/vc4_dpi.c
@@ -251,7 +251,7 @@ static int vc4_dpi_init_bridge(struct vc4_dpi *dpi)
 	if (panel)
 		bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_DPI);
 
-	return drm_bridge_attach(dpi->encoder, bridge, NULL);
+	return drm_bridge_attach(dpi->encoder, bridge, NULL, 0);
 }
 
 static int vc4_dpi_bind(struct device *dev, struct device *master, void *data)
diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
index c78fa8144776..f5d5b6837831 100644
--- a/drivers/gpu/drm/vc4/vc4_dsi.c
+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
@@ -1599,7 +1599,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
 			 DRM_MODE_ENCODER_DSI, NULL);
 	drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs);
 
-	ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL);
+	ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL, 0);
 	if (ret) {
 		dev_err(dev, "bridge attach failed: %d\n", ret);
 		return ret;
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 7db6ca0fd75d..928d046ad99d 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -34,6 +34,17 @@ struct drm_bridge_timings;
 struct drm_panel;
 struct i2c_adapter;
 
+/**
+ * enum drm_bridge_attach_flags - Flags for &drm_bridge_funcs.attach
+ */
+enum drm_bridge_attach_flags {
+	/**
+	 * @DRM_BRIDGE_ATTACH_NO_CONNECTOR: When this flag is set the bridge
+	 * shall not create a drm_connector.
+	 */
+	DRM_BRIDGE_ATTACH_NO_CONNECTOR = BIT(0),
+};
+
 /**
  * struct drm_bridge_funcs - drm_bridge control functions
  */
@@ -42,7 +53,8 @@ struct drm_bridge_funcs {
 	 * @attach:
 	 *
 	 * This callback is invoked whenever our bridge is being attached to a
-	 * &drm_encoder.
+	 * &drm_encoder. The flags argument tunes the behaviour of the attach
+	 * operation (see DRM_BRIDGE_ATTACH_*).
 	 *
 	 * The attach callback is optional.
 	 *
@@ -50,7 +62,8 @@ struct drm_bridge_funcs {
 	 *
 	 * Zero on success, error code on failure.
 	 */
-	int (*attach)(struct drm_bridge *bridge);
+	int (*attach)(struct drm_bridge *bridge,
+		      enum drm_bridge_attach_flags flags);
 
 	/**
 	 * @detach:
@@ -571,7 +584,8 @@ void drm_bridge_add(struct drm_bridge *bridge);
 void drm_bridge_remove(struct drm_bridge *bridge);
 struct drm_bridge *of_drm_find_bridge(struct device_node *np);
 int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
-		      struct drm_bridge *previous);
+		      struct drm_bridge *previous,
+		      enum drm_bridge_attach_flags flags);
 
 bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
 			   const struct drm_display_mode *mode,
-- 
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] 106+ messages in thread

* [PATCH v2 06/50] drm/bridge: dumb-vga-dac: Rename internal symbols to simple-bridge
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (4 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 05/50] drm/bridge: Extend bridge API to disable connector creation Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-22 15:39   ` Boris Brezillon
  2019-08-26 11:25   ` Maxime Ripard
  2019-08-20  1:16 ` [PATCH v2 07/50] drm/bridge: dumb-vga-dac: Rename driver " Laurent Pinchart
                   ` (44 subsequent siblings)
  50 siblings, 2 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

The dumb-vga-dac driver is a simple DRM bridge driver for simple VGA
DACs that don't require configuration. Other non-VGA bridges fall in a
similar category, and would benefit from a common driver. Prepare for
this by renaming the internal symbols from dumb-vga-dac to
simple-bridge.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
---
 drivers/gpu/drm/bridge/dumb-vga-dac.c | 154 +++++++++++++-------------
 1 file changed, 77 insertions(+), 77 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
index 74ebca58eb1f..03ceb0cd8b9e 100644
--- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
+++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
@@ -16,7 +16,7 @@
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
 
-struct dumb_vga {
+struct simple_bridge {
 	struct drm_bridge	bridge;
 	struct drm_connector	connector;
 
@@ -24,28 +24,28 @@ struct dumb_vga {
 	struct regulator	*vdd;
 };
 
-static inline struct dumb_vga *
-drm_bridge_to_dumb_vga(struct drm_bridge *bridge)
+static inline struct simple_bridge *
+drm_bridge_to_simple_bridge(struct drm_bridge *bridge)
 {
-	return container_of(bridge, struct dumb_vga, bridge);
+	return container_of(bridge, struct simple_bridge, bridge);
 }
 
-static inline struct dumb_vga *
-drm_connector_to_dumb_vga(struct drm_connector *connector)
+static inline struct simple_bridge *
+drm_connector_to_simple_bridge(struct drm_connector *connector)
 {
-	return container_of(connector, struct dumb_vga, connector);
+	return container_of(connector, struct simple_bridge, connector);
 }
 
-static int dumb_vga_get_modes(struct drm_connector *connector)
+static int simple_bridge_get_modes(struct drm_connector *connector)
 {
-	struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
+	struct simple_bridge *sbridge = drm_connector_to_simple_bridge(connector);
 	struct edid *edid;
 	int ret;
 
-	if (!vga->ddc)
+	if (!sbridge->ddc)
 		goto fallback;
 
-	edid = drm_get_edid(connector, vga->ddc);
+	edid = drm_get_edid(connector, sbridge->ddc);
 	if (!edid) {
 		DRM_INFO("EDID readout failed, falling back to standard modes\n");
 		goto fallback;
@@ -69,14 +69,14 @@ static int dumb_vga_get_modes(struct drm_connector *connector)
 	return ret;
 }
 
-static const struct drm_connector_helper_funcs dumb_vga_con_helper_funcs = {
-	.get_modes	= dumb_vga_get_modes,
+static const struct drm_connector_helper_funcs simple_bridge_con_helper_funcs = {
+	.get_modes	= simple_bridge_get_modes,
 };
 
 static enum drm_connector_status
-dumb_vga_connector_detect(struct drm_connector *connector, bool force)
+simple_bridge_connector_detect(struct drm_connector *connector, bool force)
 {
-	struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
+	struct simple_bridge *sbridge = drm_connector_to_simple_bridge(connector);
 
 	/*
 	 * Even if we have an I2C bus, we can't assume that the cable
@@ -84,14 +84,14 @@ dumb_vga_connector_detect(struct drm_connector *connector, bool force)
 	 * wire the DDC pins, or the I2C bus might not be working at
 	 * all.
 	 */
-	if (vga->ddc && drm_probe_ddc(vga->ddc))
+	if (sbridge->ddc && drm_probe_ddc(sbridge->ddc))
 		return connector_status_connected;
 
 	return connector_status_unknown;
 }
 
-static const struct drm_connector_funcs dumb_vga_con_funcs = {
-	.detect			= dumb_vga_connector_detect,
+static const struct drm_connector_funcs simple_bridge_con_funcs = {
+	.detect			= simple_bridge_connector_detect,
 	.fill_modes		= drm_helper_probe_single_connector_modes,
 	.destroy		= drm_connector_cleanup,
 	.reset			= drm_atomic_helper_connector_reset,
@@ -99,10 +99,10 @@ static const struct drm_connector_funcs dumb_vga_con_funcs = {
 	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
 };
 
-static int dumb_vga_attach(struct drm_bridge *bridge,
-			   enum drm_bridge_attach_flags flags)
+static int simple_bridge_attach(struct drm_bridge *bridge,
+				enum drm_bridge_attach_flags flags)
 {
-	struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
+	struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
 	int ret;
 
 	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
@@ -113,50 +113,50 @@ static int dumb_vga_attach(struct drm_bridge *bridge,
 		return -ENODEV;
 	}
 
-	drm_connector_helper_add(&vga->connector,
-				 &dumb_vga_con_helper_funcs);
-	ret = drm_connector_init_with_ddc(bridge->dev, &vga->connector,
-					  &dumb_vga_con_funcs,
+	drm_connector_helper_add(&sbridge->connector,
+				 &simple_bridge_con_helper_funcs);
+	ret = drm_connector_init_with_ddc(bridge->dev, &sbridge->connector,
+					  &simple_bridge_con_funcs,
 					  DRM_MODE_CONNECTOR_VGA,
-					  vga->ddc);
+					  sbridge->ddc);
 	if (ret) {
 		DRM_ERROR("Failed to initialize connector\n");
 		return ret;
 	}
 
-	drm_connector_attach_encoder(&vga->connector,
+	drm_connector_attach_encoder(&sbridge->connector,
 					  bridge->encoder);
 
 	return 0;
 }
 
-static void dumb_vga_enable(struct drm_bridge *bridge)
+static void simple_bridge_enable(struct drm_bridge *bridge)
 {
-	struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
+	struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
 	int ret = 0;
 
-	if (vga->vdd)
-		ret = regulator_enable(vga->vdd);
+	if (sbridge->vdd)
+		ret = regulator_enable(sbridge->vdd);
 
 	if (ret)
 		DRM_ERROR("Failed to enable vdd regulator: %d\n", ret);
 }
 
-static void dumb_vga_disable(struct drm_bridge *bridge)
+static void simple_bridge_disable(struct drm_bridge *bridge)
 {
-	struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
+	struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
 
-	if (vga->vdd)
-		regulator_disable(vga->vdd);
+	if (sbridge->vdd)
+		regulator_disable(sbridge->vdd);
 }
 
-static const struct drm_bridge_funcs dumb_vga_bridge_funcs = {
-	.attach		= dumb_vga_attach,
-	.enable		= dumb_vga_enable,
-	.disable	= dumb_vga_disable,
+static const struct drm_bridge_funcs simple_bridge_bridge_funcs = {
+	.attach		= simple_bridge_attach,
+	.enable		= simple_bridge_enable,
+	.disable	= simple_bridge_disable,
 };
 
-static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
+static struct i2c_adapter *simple_bridge_retrieve_ddc(struct device *dev)
 {
 	struct device_node *phandle, *remote;
 	struct i2c_adapter *ddc;
@@ -178,53 +178,53 @@ static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
 	return ddc;
 }
 
-static int dumb_vga_probe(struct platform_device *pdev)
+static int simple_bridge_probe(struct platform_device *pdev)
 {
-	struct dumb_vga *vga;
+	struct simple_bridge *sbridge;
 
-	vga = devm_kzalloc(&pdev->dev, sizeof(*vga), GFP_KERNEL);
-	if (!vga)
+	sbridge = devm_kzalloc(&pdev->dev, sizeof(*sbridge), GFP_KERNEL);
+	if (!sbridge)
 		return -ENOMEM;
-	platform_set_drvdata(pdev, vga);
+	platform_set_drvdata(pdev, sbridge);
 
-	vga->vdd = devm_regulator_get_optional(&pdev->dev, "vdd");
-	if (IS_ERR(vga->vdd)) {
-		int ret = PTR_ERR(vga->vdd);
+	sbridge->vdd = devm_regulator_get_optional(&pdev->dev, "vdd");
+	if (IS_ERR(sbridge->vdd)) {
+		int ret = PTR_ERR(sbridge->vdd);
 		if (ret == -EPROBE_DEFER)
 			return -EPROBE_DEFER;
-		vga->vdd = NULL;
+		sbridge->vdd = NULL;
 		dev_dbg(&pdev->dev, "No vdd regulator found: %d\n", ret);
 	}
 
-	vga->ddc = dumb_vga_retrieve_ddc(&pdev->dev);
-	if (IS_ERR(vga->ddc)) {
-		if (PTR_ERR(vga->ddc) == -ENODEV) {
+	sbridge->ddc = simple_bridge_retrieve_ddc(&pdev->dev);
+	if (IS_ERR(sbridge->ddc)) {
+		if (PTR_ERR(sbridge->ddc) == -ENODEV) {
 			dev_dbg(&pdev->dev,
 				"No i2c bus specified. Disabling EDID readout\n");
-			vga->ddc = NULL;
+			sbridge->ddc = NULL;
 		} else {
 			dev_err(&pdev->dev, "Couldn't retrieve i2c bus\n");
-			return PTR_ERR(vga->ddc);
+			return PTR_ERR(sbridge->ddc);
 		}
 	}
 
-	vga->bridge.funcs = &dumb_vga_bridge_funcs;
-	vga->bridge.of_node = pdev->dev.of_node;
-	vga->bridge.timings = of_device_get_match_data(&pdev->dev);
+	sbridge->bridge.funcs = &simple_bridge_bridge_funcs;
+	sbridge->bridge.of_node = pdev->dev.of_node;
+	sbridge->bridge.timings = of_device_get_match_data(&pdev->dev);
 
-	drm_bridge_add(&vga->bridge);
+	drm_bridge_add(&sbridge->bridge);
 
 	return 0;
 }
 
-static int dumb_vga_remove(struct platform_device *pdev)
+static int simple_bridge_remove(struct platform_device *pdev)
 {
-	struct dumb_vga *vga = platform_get_drvdata(pdev);
+	struct simple_bridge *sbridge = platform_get_drvdata(pdev);
 
-	drm_bridge_remove(&vga->bridge);
+	drm_bridge_remove(&sbridge->bridge);
 
-	if (vga->ddc)
-		i2c_put_adapter(vga->ddc);
+	if (sbridge->ddc)
+		i2c_put_adapter(sbridge->ddc);
 
 	return 0;
 }
@@ -235,7 +235,7 @@ static int dumb_vga_remove(struct platform_device *pdev)
  * NOTE: the ADV7123EP seems to have other timings and need a new timings
  * set if used.
  */
-static const struct drm_bridge_timings default_dac_timings = {
+static const struct drm_bridge_timings default_bridge_timings = {
 	/* Timing specifications, datasheet page 7 */
 	.input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE,
 	.setup_time_ps = 500,
@@ -246,7 +246,7 @@ static const struct drm_bridge_timings default_dac_timings = {
  * Information taken from the THS8134, THS8134A, THS8134B datasheet named
  * "SLVS205D", dated May 1990, revised March 2000.
  */
-static const struct drm_bridge_timings ti_ths8134_dac_timings = {
+static const struct drm_bridge_timings ti_ths8134_bridge_timings = {
 	/* From timing diagram, datasheet page 9 */
 	.input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE,
 	/* From datasheet, page 12 */
@@ -259,7 +259,7 @@ static const struct drm_bridge_timings ti_ths8134_dac_timings = {
  * Information taken from the THS8135 datasheet named "SLAS343B", dated
  * May 2001, revised April 2013.
  */
-static const struct drm_bridge_timings ti_ths8135_dac_timings = {
+static const struct drm_bridge_timings ti_ths8135_bridge_timings = {
 	/* From timing diagram, datasheet page 14 */
 	.input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE,
 	/* From datasheet, page 16 */
@@ -267,37 +267,37 @@ static const struct drm_bridge_timings ti_ths8135_dac_timings = {
 	.hold_time_ps = 500,
 };
 
-static const struct of_device_id dumb_vga_match[] = {
+static const struct of_device_id simple_bridge_match[] = {
 	{
 		.compatible = "dumb-vga-dac",
 		.data = NULL,
 	},
 	{
 		.compatible = "adi,adv7123",
-		.data = &default_dac_timings,
+		.data = &default_bridge_timings,
 	},
 	{
 		.compatible = "ti,ths8135",
-		.data = &ti_ths8135_dac_timings,
+		.data = &ti_ths8135_bridge_timings,
 	},
 	{
 		.compatible = "ti,ths8134",
-		.data = &ti_ths8134_dac_timings,
+		.data = &ti_ths8134_bridge_timings,
 	},
 	{},
 };
-MODULE_DEVICE_TABLE(of, dumb_vga_match);
+MODULE_DEVICE_TABLE(of, simple_bridge_match);
 
-static struct platform_driver dumb_vga_driver = {
-	.probe	= dumb_vga_probe,
-	.remove	= dumb_vga_remove,
+static struct platform_driver simple_bridge_driver = {
+	.probe	= simple_bridge_probe,
+	.remove	= simple_bridge_remove,
 	.driver		= {
 		.name		= "dumb-vga-dac",
-		.of_match_table	= dumb_vga_match,
+		.of_match_table	= simple_bridge_match,
 	},
 };
-module_platform_driver(dumb_vga_driver);
+module_platform_driver(simple_bridge_driver);
 
 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
-MODULE_DESCRIPTION("Dumb VGA DAC bridge driver");
+MODULE_DESCRIPTION("Simple DRM bridge driver");
 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 related	[flat|nested] 106+ messages in thread

* [PATCH v2 07/50] drm/bridge: dumb-vga-dac: Rename driver to simple-bridge
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (5 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 06/50] drm/bridge: dumb-vga-dac: Rename internal symbols to simple-bridge Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-22 15:42   ` Boris Brezillon
  2019-08-26 11:26   ` Maxime Ripard
  2019-08-20  1:16 ` [PATCH v2 08/50] drm/bridge: simple-bridge: Add support for non-VGA bridges Laurent Pinchart
                   ` (43 subsequent siblings)
  50 siblings, 2 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel
  Cc: Simon Horman, Maxime Ripard, Sebastian Reichel, Russell King,
	Chen-Yu Tsai, Tomi Valkeinen, Sean Paul

The dumb-vga-dac driver can support simple DRM bridges without being
limited to VGA DACs. Rename it to simple-bridge.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
---
 arch/arm/configs/davinci_all_defconfig           |  2 +-
 arch/arm/configs/integrator_defconfig            |  2 +-
 arch/arm/configs/multi_v7_defconfig              |  2 +-
 arch/arm/configs/shmobile_defconfig              |  2 +-
 arch/arm/configs/sunxi_defconfig                 |  2 +-
 arch/arm/configs/versatile_defconfig             |  2 +-
 drivers/gpu/drm/bridge/Kconfig                   | 16 ++++++++--------
 drivers/gpu/drm/bridge/Makefile                  |  2 +-
 .../bridge/{dumb-vga-dac.c => simple-bridge.c}   |  2 +-
 9 files changed, 16 insertions(+), 16 deletions(-)
 rename drivers/gpu/drm/bridge/{dumb-vga-dac.c => simple-bridge.c} (99%)

diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig
index 9a32a8c0f873..4b8cf51b2abd 100644
--- a/arch/arm/configs/davinci_all_defconfig
+++ b/arch/arm/configs/davinci_all_defconfig
@@ -155,7 +155,7 @@ CONFIG_VIDEO_TVP514X=m
 CONFIG_VIDEO_ADV7343=m
 CONFIG_DRM=m
 CONFIG_DRM_TILCDC=m
-CONFIG_DRM_DUMB_VGA_DAC=m
+CONFIG_DRM_SIMPLE_BRIDGE=m
 CONFIG_DRM_TINYDRM=m
 CONFIG_TINYDRM_ST7586=m
 CONFIG_FB=y
diff --git a/arch/arm/configs/integrator_defconfig b/arch/arm/configs/integrator_defconfig
index 2f0a762dc3a0..a9755c501bec 100644
--- a/arch/arm/configs/integrator_defconfig
+++ b/arch/arm/configs/integrator_defconfig
@@ -55,7 +55,7 @@ CONFIG_SMC91X=y
 # CONFIG_KEYBOARD_ATKBD is not set
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_DRM=y
-CONFIG_DRM_DUMB_VGA_DAC=y
+CONFIG_DRM_SIMPLE_BRIDGE=y
 CONFIG_DRM_PL111=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_MATROX=y
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 6a40bc2ef271..9eefc0cc29bc 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -644,11 +644,11 @@ CONFIG_DRM_PANEL_ORISETECH_OTM8009A=m
 CONFIG_DRM_PANEL_RAYDIUM_RM68200=m
 CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03=m
 CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0=m
-CONFIG_DRM_DUMB_VGA_DAC=m
 CONFIG_DRM_NXP_PTN3460=m
 CONFIG_DRM_PARADE_PS8622=m
 CONFIG_DRM_SII902X=m
 CONFIG_DRM_SII9234=m
+CONFIG_DRM_SIMPLE_BRIDGE=m
 CONFIG_DRM_TOSHIBA_TC358764=m
 CONFIG_DRM_I2C_ADV7511=m
 CONFIG_DRM_I2C_ADV7511_AUDIO=y
diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig
index c6c70355141c..a8e7827a7214 100644
--- a/arch/arm/configs/shmobile_defconfig
+++ b/arch/arm/configs/shmobile_defconfig
@@ -125,8 +125,8 @@ CONFIG_VIDEO_ADV7604=y
 CONFIG_VIDEO_ML86V7667=y
 CONFIG_DRM=y
 CONFIG_DRM_RCAR_DU=y
-CONFIG_DRM_DUMB_VGA_DAC=y
 CONFIG_DRM_SII902X=y
+CONFIG_DRM_SIMPLE_BRIDGE=y
 CONFIG_DRM_I2C_ADV7511=y
 CONFIG_DRM_I2C_ADV7511_AUDIO=y
 CONFIG_FB_SH_MOBILE_LCDC=y
diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig
index df433abfcb02..19cccae84a19 100644
--- a/arch/arm/configs/sunxi_defconfig
+++ b/arch/arm/configs/sunxi_defconfig
@@ -99,7 +99,7 @@ CONFIG_RC_DEVICES=y
 CONFIG_IR_SUNXI=y
 CONFIG_DRM=y
 CONFIG_DRM_SUN4I=y
-CONFIG_DRM_DUMB_VGA_DAC=y
+CONFIG_DRM_SIMPLE_BRIDGE=y
 CONFIG_FB_SIMPLE=y
 CONFIG_SOUND=y
 CONFIG_SND=y
diff --git a/arch/arm/configs/versatile_defconfig b/arch/arm/configs/versatile_defconfig
index fe4d4b596585..767935337413 100644
--- a/arch/arm/configs/versatile_defconfig
+++ b/arch/arm/configs/versatile_defconfig
@@ -59,7 +59,7 @@ CONFIG_GPIO_PL061=y
 CONFIG_DRM=y
 CONFIG_DRM_PANEL_ARM_VERSATILE=y
 CONFIG_DRM_PANEL_SIMPLE=y
-CONFIG_DRM_DUMB_VGA_DAC=y
+CONFIG_DRM_SIMPLE_BRIDGE=y
 CONFIG_DRM_PL111=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 1cc9f502c1f2..d0146438b0f5 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -37,14 +37,6 @@ config DRM_CDNS_DSI
 	  Support Cadence DPI to DSI bridge. This is an internal
 	  bridge and is meant to be directly embedded in a SoC.
 
-config DRM_DUMB_VGA_DAC
-	tristate "Dumb VGA DAC Bridge support"
-	depends on OF
-	select DRM_KMS_HELPER
-	help
-	  Support for non-programmable RGB to VGA DAC bridges, such as ADI
-	  ADV7123, TI THS8134 and THS8135 or passive resistor ladder DACs.
-
 config DRM_LVDS_ENCODER
 	tristate "Transparent parallel to LVDS encoder support"
 	depends on OF
@@ -109,6 +101,14 @@ config DRM_SII9234
 	  It is an I2C driver, that detects connection of MHL bridge
 	  and starts encapsulation of HDMI signal.
 
+config DRM_SIMPLE_BRIDGE
+	tristate "Simple DRM bridge support"
+	depends on OF
+	select DRM_KMS_HELPER
+	help
+	  Support for non-programmable DRM bridges, such as ADI ADV7123, TI
+	  THS8134 and THS8135 or passive resistor ladder DACs.
+
 config DRM_THINE_THC63LVD1024
 	tristate "Thine THC63LVD1024 LVDS decoder bridge"
 	depends on OF
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 4934fcf5a6f8..6ff7f2adbb0e 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -1,7 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
 obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o
-obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
 obj-$(CONFIG_DRM_LVDS_ENCODER) += lvds-encoder.o
 obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o
 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
@@ -9,6 +8,7 @@ obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
 obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o
 obj-$(CONFIG_DRM_SII902X) += sii902x.o
 obj-$(CONFIG_DRM_SII9234) += sii9234.o
+obj-$(CONFIG_DRM_SIMPLE_BRIDGE) += simple-bridge.o
 obj-$(CONFIG_DRM_THINE_THC63LVD1024) += thc63lvd1024.o
 obj-$(CONFIG_DRM_TOSHIBA_TC358764) += tc358764.o
 obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o
diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/simple-bridge.c
similarity index 99%
rename from drivers/gpu/drm/bridge/dumb-vga-dac.c
rename to drivers/gpu/drm/bridge/simple-bridge.c
index 03ceb0cd8b9e..7551a361f22e 100644
--- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
+++ b/drivers/gpu/drm/bridge/simple-bridge.c
@@ -292,7 +292,7 @@ static struct platform_driver simple_bridge_driver = {
 	.probe	= simple_bridge_probe,
 	.remove	= simple_bridge_remove,
 	.driver		= {
-		.name		= "dumb-vga-dac",
+		.name		= "simple-bridge",
 		.of_match_table	= simple_bridge_match,
 	},
 };
-- 
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] 106+ messages in thread

* [PATCH v2 08/50] drm/bridge: simple-bridge: Add support for non-VGA bridges
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (6 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 07/50] drm/bridge: dumb-vga-dac: Rename driver " Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-22 15:43   ` Boris Brezillon
  2019-08-26 11:27   ` Maxime Ripard
  2019-08-20  1:16 ` [PATCH v2 09/50] drm/bridge: simple-bridge: Add support for enable GPIO Laurent Pinchart
                   ` (42 subsequent siblings)
  50 siblings, 2 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Create a new simple_bridge_info structure that stores information about
the bridge model, and store the bridge timings in there, along with the
connector type. Use that new structure for of_device_id data. This
enables support for non-VGA bridges.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
Reviewed-by: Stefan Agner <stefan@agner.ch>
---
Changes since v1:

- Renamed simple_bridge_info.type field to connector_type
---
 drivers/gpu/drm/bridge/simple-bridge.c | 41 ++++++++++++++++++--------
 1 file changed, 29 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/bridge/simple-bridge.c b/drivers/gpu/drm/bridge/simple-bridge.c
index 7551a361f22e..85aa852eafb4 100644
--- a/drivers/gpu/drm/bridge/simple-bridge.c
+++ b/drivers/gpu/drm/bridge/simple-bridge.c
@@ -16,10 +16,17 @@
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
 
+struct simple_bridge_info {
+	const struct drm_bridge_timings *timings;
+	unsigned int connector_type;
+};
+
 struct simple_bridge {
 	struct drm_bridge	bridge;
 	struct drm_connector	connector;
 
+	const struct simple_bridge_info *info;
+
 	struct i2c_adapter	*ddc;
 	struct regulator	*vdd;
 };
@@ -117,7 +124,7 @@ static int simple_bridge_attach(struct drm_bridge *bridge,
 				 &simple_bridge_con_helper_funcs);
 	ret = drm_connector_init_with_ddc(bridge->dev, &sbridge->connector,
 					  &simple_bridge_con_funcs,
-					  DRM_MODE_CONNECTOR_VGA,
+					  sbridge->info->connector_type,
 					  sbridge->ddc);
 	if (ret) {
 		DRM_ERROR("Failed to initialize connector\n");
@@ -187,6 +194,8 @@ static int simple_bridge_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	platform_set_drvdata(pdev, sbridge);
 
+	sbridge->info = of_device_get_match_data(&pdev->dev);
+
 	sbridge->vdd = devm_regulator_get_optional(&pdev->dev, "vdd");
 	if (IS_ERR(sbridge->vdd)) {
 		int ret = PTR_ERR(sbridge->vdd);
@@ -210,7 +219,7 @@ static int simple_bridge_probe(struct platform_device *pdev)
 
 	sbridge->bridge.funcs = &simple_bridge_bridge_funcs;
 	sbridge->bridge.of_node = pdev->dev.of_node;
-	sbridge->bridge.timings = of_device_get_match_data(&pdev->dev);
+	sbridge->bridge.timings = sbridge->info->timings;
 
 	drm_bridge_add(&sbridge->bridge);
 
@@ -270,19 +279,27 @@ static const struct drm_bridge_timings ti_ths8135_bridge_timings = {
 static const struct of_device_id simple_bridge_match[] = {
 	{
 		.compatible = "dumb-vga-dac",
-		.data = NULL,
-	},
-	{
+		.data = &(const struct simple_bridge_info) {
+			.connector_type = DRM_MODE_CONNECTOR_VGA,
+		},
+	}, {
 		.compatible = "adi,adv7123",
-		.data = &default_bridge_timings,
-	},
-	{
+		.data = &(const struct simple_bridge_info) {
+			.timings = &default_bridge_timings,
+			.connector_type = DRM_MODE_CONNECTOR_VGA,
+		},
+	}, {
 		.compatible = "ti,ths8135",
-		.data = &ti_ths8135_bridge_timings,
-	},
-	{
+		.data = &(const struct simple_bridge_info) {
+			.timings = &ti_ths8135_bridge_timings,
+			.connector_type = DRM_MODE_CONNECTOR_VGA,
+		},
+	}, {
 		.compatible = "ti,ths8134",
-		.data = &ti_ths8134_bridge_timings,
+		.data = &(const struct simple_bridge_info) {
+			.timings = &ti_ths8134_bridge_timings,
+			.connector_type = DRM_MODE_CONNECTOR_VGA,
+		},
 	},
 	{},
 };
-- 
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] 106+ messages in thread

* [PATCH v2 09/50] drm/bridge: simple-bridge: Add support for enable GPIO
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (7 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 08/50] drm/bridge: simple-bridge: Add support for non-VGA bridges Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-22 15:45   ` Boris Brezillon
  2019-08-26 11:33   ` Maxime Ripard
  2019-08-20  1:16 ` [PATCH v2 10/50] drm/bridge: simple-bridge: Add support for the TI OP362 Laurent Pinchart
                   ` (41 subsequent siblings)
  50 siblings, 2 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

If an enable GPIO is declared in the firmware, assert it when enabling
the bridge and deassert it when disabling it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
Reviewed-by: Stefan Agner <stefan@agner.ch>
---
 drivers/gpu/drm/bridge/simple-bridge.c | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/simple-bridge.c b/drivers/gpu/drm/bridge/simple-bridge.c
index 85aa852eafb4..3e5031833368 100644
--- a/drivers/gpu/drm/bridge/simple-bridge.c
+++ b/drivers/gpu/drm/bridge/simple-bridge.c
@@ -6,6 +6,7 @@
  * Maxime Ripard <maxime.ripard@free-electrons.com>
  */
 
+#include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/of_graph.h>
@@ -29,6 +30,7 @@ struct simple_bridge {
 
 	struct i2c_adapter	*ddc;
 	struct regulator	*vdd;
+	struct gpio_desc	*enable;
 };
 
 static inline struct simple_bridge *
@@ -140,19 +142,23 @@ static int simple_bridge_attach(struct drm_bridge *bridge,
 static void simple_bridge_enable(struct drm_bridge *bridge)
 {
 	struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
-	int ret = 0;
+	int ret;
 
-	if (sbridge->vdd)
+	if (sbridge->vdd) {
 		ret = regulator_enable(sbridge->vdd);
+		if (ret)
+			DRM_ERROR("Failed to enable vdd regulator: %d\n", ret);
+	}
 
-	if (ret)
-		DRM_ERROR("Failed to enable vdd regulator: %d\n", ret);
+	gpiod_set_value_cansleep(sbridge->enable, 1);
 }
 
 static void simple_bridge_disable(struct drm_bridge *bridge)
 {
 	struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
 
+	gpiod_set_value_cansleep(sbridge->enable, 0);
+
 	if (sbridge->vdd)
 		regulator_disable(sbridge->vdd);
 }
@@ -205,6 +211,14 @@ static int simple_bridge_probe(struct platform_device *pdev)
 		dev_dbg(&pdev->dev, "No vdd regulator found: %d\n", ret);
 	}
 
+	sbridge->enable = devm_gpiod_get_optional(&pdev->dev, "enable",
+						  GPIOD_OUT_LOW);
+	if (IS_ERR(sbridge->enable)) {
+		if (PTR_ERR(sbridge->enable) != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Unable to retrieve enable GPIO\n");
+		return PTR_ERR(sbridge->enable);
+	}
+
 	sbridge->ddc = simple_bridge_retrieve_ddc(&pdev->dev);
 	if (IS_ERR(sbridge->ddc)) {
 		if (PTR_ERR(sbridge->ddc) == -ENODEV) {
-- 
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] 106+ messages in thread

* [PATCH v2 10/50] drm/bridge: simple-bridge: Add support for the TI OP362
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (8 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 09/50] drm/bridge: simple-bridge: Add support for enable GPIO Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-22 15:45   ` Boris Brezillon
  2019-08-26 11:34   ` Maxime Ripard
  2019-08-20  1:16 ` [PATCH v2 11/50] drm/bridge: Add bridge driver for display connectors Laurent Pinchart
                   ` (40 subsequent siblings)
  50 siblings, 2 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

The TI OP362 is an analog video amplifier controlled through a GPIO. Add
support for it to the simple-bridge driver.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
---
 drivers/gpu/drm/bridge/simple-bridge.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/bridge/simple-bridge.c b/drivers/gpu/drm/bridge/simple-bridge.c
index 3e5031833368..52626e2de90e 100644
--- a/drivers/gpu/drm/bridge/simple-bridge.c
+++ b/drivers/gpu/drm/bridge/simple-bridge.c
@@ -302,6 +302,11 @@ static const struct of_device_id simple_bridge_match[] = {
 			.timings = &default_bridge_timings,
 			.connector_type = DRM_MODE_CONNECTOR_VGA,
 		},
+	}, {
+		.compatible = "ti,opa362",
+		.data = &(const struct simple_bridge_info) {
+			.connector_type = DRM_MODE_CONNECTOR_Composite,
+		},
 	}, {
 		.compatible = "ti,ths8135",
 		.data = &(const struct simple_bridge_info) {
-- 
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] 106+ messages in thread

* [PATCH v2 11/50] drm/bridge: Add bridge driver for display connectors
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (9 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 10/50] drm/bridge: simple-bridge: Add support for the TI OP362 Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-22 16:05   ` Boris Brezillon
  2019-08-26 11:36   ` Maxime Ripard
  2019-08-20  1:16 ` [PATCH v2 12/50] drm/bridge: Add driver for the TI TPD12S015 HDMI level shifter Laurent Pinchart
                   ` (39 subsequent siblings)
  50 siblings, 2 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Display connectors are modelled in DT as a device node, but have so far
been handled manually in several bridge drivers. This resulted in
duplicate code in several bridge drivers, with slightly different (and
thus confusing) logics.

In order to fix this, implement a bridge driver for display connectors.
The driver centralises logic for the DVI, HDMI, VGAn composite and
S-video connectors and exposes corresponding bridge operations.

This driver in itself doesn't solve the issue completely, changes in
bridge and display controller drivers are needed to make use of the new
connector driver.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v1:

- Use drm_get_connector_type_name() instead of open-coding
  display_connector_type_name()
- Remove empty .hpd_enable() and .hpd_disable() operations
- Set bridge.ddc
---
 drivers/gpu/drm/bridge/Kconfig             |  11 +
 drivers/gpu/drm/bridge/Makefile            |   1 +
 drivers/gpu/drm/bridge/display-connector.c | 292 +++++++++++++++++++++
 3 files changed, 304 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/display-connector.c

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index d0146438b0f5..f776d522c5aa 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -37,6 +37,17 @@ config DRM_CDNS_DSI
 	  Support Cadence DPI to DSI bridge. This is an internal
 	  bridge and is meant to be directly embedded in a SoC.
 
+config DRM_DISPLAY_CONNECTOR
+	tristate "Display connector support"
+	depends on OF
+	help
+	  Driver for display connectors with support for DDC and hot-plug
+	  detection. Most display controller handle display connectors
+	  internally and don't need this driver, but the DRM subsystem is
+	  moving towards separating connector handling from display controllers
+	  on ARM-based platforms. Saying Y here when this driver is not needed
+	  will not cause any issue.
+
 config DRM_LVDS_ENCODER
 	tristate "Transparent parallel to LVDS encoder support"
 	depends on OF
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 6ff7f2adbb0e..e5987b3aaf62 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
 obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o
+obj-$(CONFIG_DRM_DISPLAY_CONNECTOR) += display-connector.o
 obj-$(CONFIG_DRM_LVDS_ENCODER) += lvds-encoder.o
 obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o
 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
diff --git a/drivers/gpu/drm/bridge/display-connector.c b/drivers/gpu/drm/bridge/display-connector.c
new file mode 100644
index 000000000000..988626b91036
--- /dev/null
+++ b/drivers/gpu/drm/bridge/display-connector.c
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ */
+
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include <drm/drm_bridge.h>
+#include <drm/drm_edid.h>
+
+struct display_connector {
+	struct drm_bridge	bridge;
+
+	const char		*label;
+	struct gpio_desc	*hpd_gpio;
+	int			hpd_irq;
+};
+
+static inline struct display_connector *
+to_display_connector(struct drm_bridge *bridge)
+{
+	return container_of(bridge, struct display_connector, bridge);
+}
+
+static int display_connector_attach(struct drm_bridge *bridge,
+				    enum drm_bridge_attach_flags flags)
+{
+	return flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR ? 0 : -EINVAL;
+}
+
+static enum drm_connector_status
+display_connector_detect(struct drm_bridge *bridge)
+{
+	struct display_connector *conn = to_display_connector(bridge);
+
+	if (conn->hpd_gpio) {
+		if (gpiod_get_value_cansleep(conn->hpd_gpio))
+			return connector_status_connected;
+		else
+			return connector_status_disconnected;
+	}
+
+	if (conn->bridge.ddc && drm_probe_ddc(conn->bridge.ddc))
+		return connector_status_connected;
+
+	switch (conn->bridge.type) {
+	case DRM_MODE_CONNECTOR_DVIA:
+	case DRM_MODE_CONNECTOR_DVID:
+	case DRM_MODE_CONNECTOR_DVII:
+	case DRM_MODE_CONNECTOR_HDMIA:
+	case DRM_MODE_CONNECTOR_HDMIB:
+		/*
+		 * For DVI and HDMI connectors a DDC probe failure indicates
+		 * that no cable is connected.
+		 */
+		return connector_status_disconnected;
+
+	case DRM_MODE_CONNECTOR_Composite:
+	case DRM_MODE_CONNECTOR_SVIDEO:
+	case DRM_MODE_CONNECTOR_VGA:
+	default:
+		/*
+		 * Composite and S-Video connectors have no other detection
+		 * mean than the HPD GPIO. For VGA connectors, even if we have
+		 * an I2C bus, we can't assume that the cable is disconnected
+		 * if drm_probe_ddc fails, as some cables don't wire the DDC
+		 * pins.
+		 */
+		return connector_status_unknown;
+	}
+}
+
+static struct edid *display_connector_get_edid(struct drm_bridge *bridge,
+					       struct drm_connector *connector)
+{
+	struct display_connector *conn = to_display_connector(bridge);
+
+	return drm_get_edid(connector, conn->bridge.ddc);
+}
+
+static const struct drm_bridge_funcs display_connector_bridge_funcs = {
+	.attach = display_connector_attach,
+	.detect = display_connector_detect,
+	.get_edid = display_connector_get_edid,
+};
+
+static irqreturn_t display_connector_hpd_irq(int irq, void *arg)
+{
+	struct display_connector *conn = arg;
+	struct drm_bridge *bridge = &conn->bridge;
+
+	drm_bridge_hpd_notify(bridge, display_connector_detect(bridge));
+
+	return IRQ_HANDLED;
+}
+
+static int display_connector_probe(struct platform_device *pdev)
+{
+	struct display_connector *conn;
+	unsigned int type;
+	int ret;
+
+	conn = devm_kzalloc(&pdev->dev, sizeof(*conn), GFP_KERNEL);
+	if (!conn)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, conn);
+
+	type = (uintptr_t)of_device_get_match_data(&pdev->dev);
+
+	/* Get the exact connector type. */
+	switch (type) {
+	case DRM_MODE_CONNECTOR_DVII: {
+		bool analog, digital;
+
+		analog = of_property_read_bool(pdev->dev.of_node, "analog");
+		digital = of_property_read_bool(pdev->dev.of_node, "digital");
+		if (analog && !digital) {
+			conn->bridge.type = DRM_MODE_CONNECTOR_DVIA;
+		} else if (!analog && digital) {
+			conn->bridge.type = DRM_MODE_CONNECTOR_DVID;
+		} else if (analog && digital) {
+			conn->bridge.type = DRM_MODE_CONNECTOR_DVII;
+		} else {
+			dev_err(&pdev->dev, "DVI connector with no type\n");
+			return -EINVAL;
+		}
+		break;
+	}
+
+	case DRM_MODE_CONNECTOR_HDMIA: {
+		const char *hdmi_type;
+
+		ret = of_property_read_string(pdev->dev.of_node, "type",
+					      &hdmi_type);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "HDMI connector with no type\n");
+			return -EINVAL;
+		}
+
+		if (!strcmp(hdmi_type, "a") || !strcmp(hdmi_type, "c") ||
+		    !strcmp(hdmi_type, "d") || !strcmp(hdmi_type, "e")) {
+			conn->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
+		} else if (!strcmp(hdmi_type, "b")) {
+			conn->bridge.type = DRM_MODE_CONNECTOR_HDMIB;
+		} else {
+			dev_err(&pdev->dev,
+				"Unsupported HDMI connector type '%s'\n",
+				hdmi_type);
+			return -EINVAL;
+		}
+
+		break;
+	}
+
+	default:
+		conn->bridge.type = type;
+		break;
+	}
+
+	/* Get the optional connector label. */
+	of_property_read_string(pdev->dev.of_node, "label", &conn->label);
+
+	/*
+	 * Get the HPD GPIO for DVI and HDMI connectors. If the GPIO can provide
+	 * interrupts, register an interrupt handler.
+	 */
+	if (type == DRM_MODE_CONNECTOR_DVII ||
+	    type == DRM_MODE_CONNECTOR_HDMIA) {
+		conn->hpd_gpio = devm_gpiod_get_optional(&pdev->dev, "hpd",
+							 GPIOD_IN);
+		if (IS_ERR(conn->hpd_gpio)) {
+			if (PTR_ERR(conn->hpd_gpio) != -EPROBE_DEFER)
+				dev_err(&pdev->dev,
+					"Unable to retrieve HPD GPIO\n");
+			return PTR_ERR(conn->hpd_gpio);
+		}
+
+		conn->hpd_irq = gpiod_to_irq(conn->hpd_gpio);
+	} else {
+		conn->hpd_irq = -EINVAL;
+	}
+
+	if (conn->hpd_irq >= 0) {
+		ret = devm_request_threaded_irq(&pdev->dev, conn->hpd_irq,
+						NULL, display_connector_hpd_irq,
+						IRQF_TRIGGER_RISING |
+						IRQF_TRIGGER_FALLING |
+						IRQF_ONESHOT,
+						"HPD", conn);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Failed to request HPD interrupt\n");
+			return ret;
+		}
+	}
+
+	/* Retrieve the DDC I2C adapter for DVI, HDMI and VGA connectors. */
+	if (type == DRM_MODE_CONNECTOR_DVII ||
+	    type == DRM_MODE_CONNECTOR_HDMIA ||
+	    type == DRM_MODE_CONNECTOR_VGA) {
+		struct device_node *phandle;
+
+		phandle = of_parse_phandle(pdev->dev.of_node, "ddc-i2c-bus", 0);
+		if (phandle) {
+			conn->bridge.ddc = of_get_i2c_adapter_by_node(phandle);
+			of_node_put(phandle);
+			if (!conn->bridge.ddc)
+				return -EPROBE_DEFER;
+		} else {
+			dev_dbg(&pdev->dev,
+				"No I2C bus specified, disabling EDID readout\n");
+		}
+	}
+
+	conn->bridge.funcs = &display_connector_bridge_funcs;
+	conn->bridge.of_node = pdev->dev.of_node;
+
+	if (conn->bridge.ddc)
+		conn->bridge.ops |= DRM_BRIDGE_OP_EDID
+				 |  DRM_BRIDGE_OP_DETECT;
+	if (conn->hpd_gpio)
+		conn->bridge.ops |= DRM_BRIDGE_OP_DETECT;
+	if (conn->hpd_irq >= 0)
+		conn->bridge.ops |= DRM_BRIDGE_OP_HPD;
+
+	dev_info(&pdev->dev,
+		 "Found %s display connector '%s' %s DDC bus and %s HPD GPIO (ops 0x%x)\n",
+		 drm_get_connector_type_name(conn->bridge.type),
+		 conn->label ? conn->label : "<unlabelled>",
+		 conn->bridge.ddc ? "with" : "without",
+		 conn->hpd_gpio ? "with" : "without",
+		 conn->bridge.ops);
+
+	drm_bridge_add(&conn->bridge);
+
+	return 0;
+}
+
+static int display_connector_remove(struct platform_device *pdev)
+{
+	struct display_connector *conn = platform_get_drvdata(pdev);
+
+	drm_bridge_remove(&conn->bridge);
+
+	if (!IS_ERR(conn->bridge.ddc))
+		i2c_put_adapter(conn->bridge.ddc);
+
+	return 0;
+}
+
+static const struct of_device_id display_connector_match[] = {
+	{
+		.compatible = "composite-video-connector",
+		.data = (void *)DRM_MODE_CONNECTOR_Composite,
+	}, {
+		.compatible = "dvi-connector",
+		.data = (void *)DRM_MODE_CONNECTOR_DVII,
+	}, {
+		.compatible = "hdmi-connector",
+		.data = (void *)DRM_MODE_CONNECTOR_HDMIA,
+	}, {
+		.compatible = "svideo-connector",
+		.data = (void *)DRM_MODE_CONNECTOR_SVIDEO,
+	}, {
+		.compatible = "vga-connector",
+		.data = (void *)DRM_MODE_CONNECTOR_VGA,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, display_connector_match);
+
+static struct platform_driver display_connector_driver = {
+	.probe	= display_connector_probe,
+	.remove	= display_connector_remove,
+	.driver		= {
+		.name		= "display-connector",
+		.of_match_table	= display_connector_match,
+	},
+};
+module_platform_driver(display_connector_driver);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("Display connector driver");
+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 related	[flat|nested] 106+ messages in thread

* [PATCH v2 12/50] drm/bridge: Add driver for the TI TPD12S015 HDMI level shifter
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (10 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 11/50] drm/bridge: Add bridge driver for display connectors Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-20  1:16 ` [PATCH v2 13/50] drm/bridge: panel: Implement bridge connector operations Laurent Pinchart
                   ` (38 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

The TI TPD12S015 is an HDMI level shifter and ESD protector controlled
through GPIOs. Add a DRM bridge driver for the device.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v1:

- Remove empty .hpd_enable() and .hpd_disable() operations
---
 drivers/gpu/drm/bridge/Kconfig        |   8 ++
 drivers/gpu/drm/bridge/Makefile       |   1 +
 drivers/gpu/drm/bridge/ti-tpd12s015.c | 195 ++++++++++++++++++++++++++
 3 files changed, 204 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/ti-tpd12s015.c

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index f776d522c5aa..c8a28df5ffc1 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -161,6 +161,14 @@ config DRM_TI_SN65DSI86
 	help
 	  Texas Instruments SN65DSI86 DSI to eDP Bridge driver
 
+config DRM_TI_TPD12S015
+	tristate "TI TPD12S015 HDMI level shifter and ESD protection"
+	depends on OF
+	select DRM_KMS_HELPER
+	help
+	  Texas Instruments TPD12S015 HDMI level shifter and ESD protection
+	  driver.
+
 source "drivers/gpu/drm/bridge/analogix/Kconfig"
 
 source "drivers/gpu/drm/bridge/adv7511/Kconfig"
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index e5987b3aaf62..ce635651e31b 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -17,4 +17,5 @@ obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
 obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
 obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o
 obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
+obj-$(CONFIG_DRM_TI_TPD12S015) += ti-tpd12s015.o
 obj-y += synopsys/
diff --git a/drivers/gpu/drm/bridge/ti-tpd12s015.c b/drivers/gpu/drm/bridge/ti-tpd12s015.c
new file mode 100644
index 000000000000..dc7c5578d258
--- /dev/null
+++ b/drivers/gpu/drm/bridge/ti-tpd12s015.c
@@ -0,0 +1,195 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TPD12S015 HDMI ESD protection & level shifter chip driver
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+
+#include <drm/drm_bridge.h>
+
+struct tpd12s015_device {
+	struct drm_bridge bridge;
+
+	struct gpio_desc *ct_cp_hpd_gpio;
+	struct gpio_desc *ls_oe_gpio;
+	struct gpio_desc *hpd_gpio;
+	int hpd_irq;
+
+	struct drm_bridge *next_bridge;
+};
+
+static inline struct tpd12s015_device *to_tpd12s015(struct drm_bridge *bridge)
+{
+	return container_of(bridge, struct tpd12s015_device, bridge);
+}
+
+static int tpd12s015_attach(struct drm_bridge *bridge,
+			    enum drm_bridge_attach_flags flags)
+{
+	struct tpd12s015_device *tpd = to_tpd12s015(bridge);
+	int ret;
+
+	if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
+		return -EINVAL;
+
+	ret = drm_bridge_attach(bridge->encoder, tpd->next_bridge,
+				bridge, flags);
+	if (ret < 0)
+		return ret;
+
+	gpiod_set_value_cansleep(tpd->ct_cp_hpd_gpio, 1);
+	gpiod_set_value_cansleep(tpd->ls_oe_gpio, 1);
+
+	/* DC-DC converter needs at max 300us to get to 90% of 5V. */
+	usleep_range(300, 1000);
+
+	return 0;
+}
+
+static void tpd12s015_detach(struct drm_bridge *bridge)
+{
+	struct tpd12s015_device *tpd = to_tpd12s015(bridge);
+
+	gpiod_set_value_cansleep(tpd->ct_cp_hpd_gpio, 0);
+	gpiod_set_value_cansleep(tpd->ls_oe_gpio, 0);
+}
+
+static enum drm_connector_status tpd12s015_detect(struct drm_bridge *bridge)
+{
+	struct tpd12s015_device *tpd = to_tpd12s015(bridge);
+
+	if (gpiod_get_value_cansleep(tpd->hpd_gpio))
+		return connector_status_connected;
+	else
+		return connector_status_disconnected;
+}
+
+static const struct drm_bridge_funcs tpd12s015_bridge_funcs = {
+	.attach			= tpd12s015_attach,
+	.detach			= tpd12s015_detach,
+	.detect			= tpd12s015_detect,
+};
+
+static irqreturn_t tpd12s015_hpd_isr(int irq, void *data)
+{
+	struct tpd12s015_device *tpd = data;
+	struct drm_bridge *bridge = &tpd->bridge;
+
+	drm_bridge_hpd_notify(bridge, tpd12s015_detect(bridge));
+
+	return IRQ_HANDLED;
+}
+
+static int tpd12s015_probe(struct platform_device *pdev)
+{
+	struct tpd12s015_device *tpd;
+	struct device_node *node;
+	struct gpio_desc *gpio;
+	int ret;
+
+	tpd = devm_kzalloc(&pdev->dev, sizeof(*tpd), GFP_KERNEL);
+	if (!tpd)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, tpd);
+
+	tpd->bridge.funcs = &tpd12s015_bridge_funcs;
+	tpd->bridge.of_node = pdev->dev.of_node;
+	tpd->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
+	tpd->bridge.ops = DRM_BRIDGE_OP_DETECT;
+
+	/* Get the next bridge, connected to port@1. */
+	node = of_graph_get_remote_node(pdev->dev.of_node, 1, -1);
+	if (!node)
+		return -ENODEV;
+
+	tpd->next_bridge = of_drm_find_bridge(node);
+	of_node_put(node);
+
+	if (!tpd->next_bridge)
+		return -EPROBE_DEFER;
+
+	/* Get the control and HPD GPIOs. */
+	gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 0,
+					     GPIOD_OUT_LOW);
+	if (IS_ERR(gpio))
+		return PTR_ERR(gpio);
+
+	tpd->ct_cp_hpd_gpio = gpio;
+
+	gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 1,
+					     GPIOD_OUT_LOW);
+	if (IS_ERR(gpio))
+		return PTR_ERR(gpio);
+
+	tpd->ls_oe_gpio = gpio;
+
+	gpio = devm_gpiod_get_index(&pdev->dev, NULL, 2, GPIOD_IN);
+	if (IS_ERR(gpio))
+		return PTR_ERR(gpio);
+
+	tpd->hpd_gpio = gpio;
+
+	/* Register the IRQ if the HPD GPIO is IRQ-capable. */
+	if (tpd->hpd_gpio)
+		tpd->hpd_irq = gpiod_to_irq(tpd->hpd_gpio);
+
+	if (tpd->hpd_irq) {
+		ret = devm_request_threaded_irq(&pdev->dev, tpd->hpd_irq, NULL,
+						tpd12s015_hpd_isr,
+						IRQF_TRIGGER_RISING |
+						IRQF_TRIGGER_FALLING |
+						IRQF_ONESHOT,
+						"tpd12s015 hpd", tpd);
+		if (ret)
+			return ret;
+
+		tpd->bridge.ops |= DRM_BRIDGE_OP_HPD;
+	}
+
+	/* Register the DRM bridge. */
+	drm_bridge_add(&tpd->bridge);
+
+	return 0;
+}
+
+static int __exit tpd12s015_remove(struct platform_device *pdev)
+{
+	struct tpd12s015_device *tpd = platform_get_drvdata(pdev);
+
+	drm_bridge_remove(&tpd->bridge);
+
+	return 0;
+}
+
+static const struct of_device_id tpd12s015_of_match[] = {
+	{ .compatible = "ti,tpd12s015", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, tpd12s015_of_match);
+
+static struct platform_driver tpd12s015_driver = {
+	.probe	= tpd12s015_probe,
+	.remove	= __exit_p(tpd12s015_remove),
+	.driver	= {
+		.name	= "tpd12s015",
+		.of_match_table = tpd12s015_of_match,
+	},
+};
+
+module_platform_driver(tpd12s015_driver);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
+MODULE_DESCRIPTION("TPD12S015 HDMI level shifter and ESD protection driver");
+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 related	[flat|nested] 106+ messages in thread

* [PATCH v2 13/50] drm/bridge: panel: Implement bridge connector operations
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (11 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 12/50] drm/bridge: Add driver for the TI TPD12S015 HDMI level shifter Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-20 10:37   ` Sam Ravnborg
  2019-08-22 16:29   ` Boris Brezillon
  2019-08-20  1:16 ` [PATCH v2 14/50] drm/bridge: tfp410: Don't include drmP.h Laurent Pinchart
                   ` (37 subsequent siblings)
  50 siblings, 2 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Implement the newly added bridge connector operations, allowing the
usage of drm_bridge_panel with drm_bridge_connector.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/bridge/panel.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index f5b8e55301ac..1c7f5b648f05 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -60,7 +60,7 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
 	int ret;
 
 	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
-		return -EINVAL;
+		return 0;
 
 	if (!bridge->encoder) {
 		DRM_ERROR("Missing encoder\n");
@@ -123,6 +123,18 @@ static void panel_bridge_post_disable(struct drm_bridge *bridge)
 	drm_panel_unprepare(panel_bridge->panel);
 }
 
+static int panel_bridge_get_modes(struct drm_bridge *bridge,
+				  struct drm_connector *connector)
+{
+	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
+
+	/*
+	 * FIXME: drm_panel_get_modes() should take the connector as an
+	 * argument.
+	 */
+	return drm_panel_get_modes(panel_bridge->panel);
+}
+
 static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
 	.attach = panel_bridge_attach,
 	.detach = panel_bridge_detach,
@@ -130,6 +142,7 @@ static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
 	.enable = panel_bridge_enable,
 	.disable = panel_bridge_disable,
 	.post_disable = panel_bridge_post_disable,
+	.get_modes = panel_bridge_get_modes,
 };
 
 /**
@@ -175,6 +188,9 @@ struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
 #ifdef CONFIG_OF
 	panel_bridge->bridge.of_node = panel->dev->of_node;
 #endif
+	panel_bridge->bridge.ops = DRM_BRIDGE_OP_MODES;
+	/* FIXME: The panel should report its type. */
+	panel_bridge->bridge.type = DRM_MODE_CONNECTOR_DPI;
 
 	drm_bridge_add(&panel_bridge->bridge);
 
-- 
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] 106+ messages in thread

* [PATCH v2 14/50] drm/bridge: tfp410: Don't include drmP.h
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (12 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 13/50] drm/bridge: panel: Implement bridge connector operations Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-22 16:11   ` Boris Brezillon
  2019-08-20  1:16 ` [PATCH v2 15/50] drm/bridge: tfp410: Replace manual connector handling with bridge Laurent Pinchart
                   ` (36 subsequent siblings)
  50 siblings, 1 reply; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

The drmP.h header is deprecated, replace it with the headers
specifically needed by the tfp410 driver. While at it, replace the DRM
print macros with dev_info() and dev_err() instead of including
drm_print.h

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/bridge/ti-tfp410.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
index a9359038f7dc..4a468f44ef69 100644
--- a/drivers/gpu/drm/bridge/ti-tfp410.c
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -14,6 +14,7 @@
 #include <linux/platform_device.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
@@ -60,7 +61,8 @@ static int tfp410_get_modes(struct drm_connector *connector)
 
 	edid = drm_get_edid(connector, dvi->ddc);
 	if (!edid) {
-		DRM_INFO("EDID read failed. Fallback to standard modes\n");
+		dev_info(dvi->dev,
+			 "EDID read failed. Fallback to standard modes\n");
 		goto fallback;
 	}
 
@@ -364,7 +366,7 @@ static int tfp410_init(struct device *dev, bool i2c)
 			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 			"hdmi-hpd", dvi);
 		if (ret) {
-			DRM_ERROR("failed to register hpd interrupt\n");
+			dev_err(dev, "failed to register hpd interrupt\n");
 			goto fail;
 		}
 	}
-- 
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] 106+ messages in thread

* [PATCH v2 15/50] drm/bridge: tfp410: Replace manual connector handling with bridge
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (13 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 14/50] drm/bridge: tfp410: Don't include drmP.h Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-22 16:36   ` Boris Brezillon
  2019-08-27  7:43   ` Tomi Valkeinen
  2019-08-20  1:16 ` [PATCH v2 16/50] drm/bridge: tfp410: Allow operation without drm_connector Laurent Pinchart
                   ` (35 subsequent siblings)
  50 siblings, 2 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Now that a driver is available for display connectors, replace the
manual connector handling code with usage of the DRM bridge API. The
tfp410 driver doesn't deal with the display connector directly anymore,
but still delegates drm_connector operations to the next bridge. This
brings us one step closer to having the tfp410 driver handling the
TFP410 only.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/bridge/ti-tfp410.c | 195 ++++++++++-------------------
 1 file changed, 68 insertions(+), 127 deletions(-)

diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
index 4a468f44ef69..65651ae6c553 100644
--- a/drivers/gpu/drm/bridge/ti-tfp410.c
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -4,14 +4,12 @@
  * Author: Jyri Sarha <jsarha@ti.com>
  */
 
-#include <linux/delay.h>
-#include <linux/fwnode.h>
 #include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
-#include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/of_graph.h>
 #include <linux/platform_device.h>
+#include <linux/workqueue.h>
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_bridge.h>
@@ -24,16 +22,13 @@
 struct tfp410 {
 	struct drm_bridge	bridge;
 	struct drm_connector	connector;
-	unsigned int		connector_type;
 
 	u32			bus_format;
-	struct i2c_adapter	*ddc;
-	struct gpio_desc	*hpd;
-	int			hpd_irq;
 	struct delayed_work	hpd_work;
 	struct gpio_desc	*powerdown;
 
 	struct drm_bridge_timings timings;
+	struct drm_bridge	*next_bridge;
 
 	struct device *dev;
 };
@@ -56,10 +51,10 @@ static int tfp410_get_modes(struct drm_connector *connector)
 	struct edid *edid;
 	int ret;
 
-	if (!dvi->ddc)
+	if (!(dvi->next_bridge->ops & DRM_BRIDGE_OP_EDID))
 		goto fallback;
 
-	edid = drm_get_edid(connector, dvi->ddc);
+	edid = dvi->next_bridge->funcs->get_edid(dvi->next_bridge, connector);
 	if (!edid) {
 		dev_info(dvi->dev,
 			 "EDID read failed. Fallback to standard modes\n");
@@ -93,21 +88,10 @@ tfp410_connector_detect(struct drm_connector *connector, bool force)
 {
 	struct tfp410 *dvi = drm_connector_to_tfp410(connector);
 
-	if (dvi->hpd) {
-		if (gpiod_get_value_cansleep(dvi->hpd))
-			return connector_status_connected;
-		else
-			return connector_status_disconnected;
-	}
+	if (!(dvi->next_bridge->ops & DRM_BRIDGE_OP_DETECT))
+		return connector_status_unknown;
 
-	if (dvi->ddc) {
-		if (drm_probe_ddc(dvi->ddc))
-			return connector_status_connected;
-		else
-			return connector_status_disconnected;
-	}
-
-	return connector_status_unknown;
+	return dvi->next_bridge->funcs->detect(dvi->next_bridge);
 }
 
 static const struct drm_connector_funcs tfp410_con_funcs = {
@@ -119,12 +103,35 @@ static const struct drm_connector_funcs tfp410_con_funcs = {
 	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
 };
 
+static void tfp410_hpd_work_func(struct work_struct *work)
+{
+	struct tfp410 *dvi;
+
+	dvi = container_of(work, struct tfp410, hpd_work.work);
+
+	if (dvi->bridge.dev)
+		drm_helper_hpd_irq_event(dvi->bridge.dev);
+}
+
+static void tfp410_hpd_callback(void *arg, enum drm_connector_status status)
+{
+	struct tfp410 *dvi = arg;
+
+	mod_delayed_work(system_wq, &dvi->hpd_work,
+			 msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
+}
+
 static int tfp410_attach(struct drm_bridge *bridge,
 			 enum drm_bridge_attach_flags flags)
 {
 	struct tfp410 *dvi = drm_bridge_to_tfp410(bridge);
 	int ret;
 
+	ret = drm_bridge_attach(bridge->encoder, dvi->next_bridge, bridge,
+				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+	if (ret < 0)
+		return ret;
+
 	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
 		return -EINVAL;
 
@@ -133,17 +140,23 @@ static int tfp410_attach(struct drm_bridge *bridge,
 		return -ENODEV;
 	}
 
-	if (dvi->hpd_irq >= 0)
+	if (dvi->next_bridge->ops & DRM_BRIDGE_OP_DETECT)
 		dvi->connector.polled = DRM_CONNECTOR_POLL_HPD;
 	else
 		dvi->connector.polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
 
+	if (dvi->next_bridge->ops & DRM_BRIDGE_OP_HPD) {
+		INIT_DELAYED_WORK(&dvi->hpd_work, tfp410_hpd_work_func);
+		drm_bridge_hpd_enable(dvi->next_bridge, tfp410_hpd_callback,
+				      dvi);
+	}
+
 	drm_connector_helper_add(&dvi->connector,
 				 &tfp410_con_helper_funcs);
 	ret = drm_connector_init_with_ddc(bridge->dev, &dvi->connector,
 					  &tfp410_con_funcs,
-					  dvi->connector_type,
-					  dvi->ddc);
+					  dvi->next_bridge->type,
+					  dvi->next_bridge->ddc);
 	if (ret) {
 		dev_err(dvi->dev, "drm_connector_init() failed: %d\n", ret);
 		return ret;
@@ -152,12 +165,21 @@ static int tfp410_attach(struct drm_bridge *bridge,
 	drm_display_info_set_bus_formats(&dvi->connector.display_info,
 					 &dvi->bus_format, 1);
 
-	drm_connector_attach_encoder(&dvi->connector,
-					  bridge->encoder);
+	drm_connector_attach_encoder(&dvi->connector, bridge->encoder);
 
 	return 0;
 }
 
+static void tfp410_detach(struct drm_bridge *bridge)
+{
+	struct tfp410 *dvi = drm_bridge_to_tfp410(bridge);
+
+	if (dvi->connector.dev && dvi->next_bridge->ops & DRM_BRIDGE_OP_HPD) {
+		drm_bridge_hpd_disable(dvi->next_bridge);
+		cancel_delayed_work_sync(&dvi->hpd_work);
+	}
+}
+
 static void tfp410_enable(struct drm_bridge *bridge)
 {
 	struct tfp410 *dvi = drm_bridge_to_tfp410(bridge);
@@ -174,30 +196,11 @@ static void tfp410_disable(struct drm_bridge *bridge)
 
 static const struct drm_bridge_funcs tfp410_bridge_funcs = {
 	.attach		= tfp410_attach,
+	.detach		= tfp410_detach,
 	.enable		= tfp410_enable,
 	.disable	= tfp410_disable,
 };
 
-static void tfp410_hpd_work_func(struct work_struct *work)
-{
-	struct tfp410 *dvi;
-
-	dvi = container_of(work, struct tfp410, hpd_work.work);
-
-	if (dvi->bridge.dev)
-		drm_helper_hpd_irq_event(dvi->bridge.dev);
-}
-
-static irqreturn_t tfp410_hpd_irq_thread(int irq, void *arg)
-{
-	struct tfp410 *dvi = arg;
-
-	mod_delayed_work(system_wq, &dvi->hpd_work,
-			msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
-
-	return IRQ_HANDLED;
-}
-
 static const struct drm_bridge_timings tfp410_default_timings = {
 	.input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE
 			 | DRM_BUS_FLAG_DE_HIGH,
@@ -275,51 +278,9 @@ static int tfp410_parse_timings(struct tfp410 *dvi, bool i2c)
 	return 0;
 }
 
-static int tfp410_get_connector_properties(struct tfp410 *dvi)
-{
-	struct device_node *connector_node, *ddc_phandle;
-	int ret = 0;
-
-	/* port@1 is the connector node */
-	connector_node = of_graph_get_remote_node(dvi->dev->of_node, 1, -1);
-	if (!connector_node)
-		return -ENODEV;
-
-	if (of_device_is_compatible(connector_node, "hdmi-connector"))
-		dvi->connector_type = DRM_MODE_CONNECTOR_HDMIA;
-	else
-		dvi->connector_type = DRM_MODE_CONNECTOR_DVID;
-
-	dvi->hpd = fwnode_get_named_gpiod(&connector_node->fwnode,
-					"hpd-gpios", 0, GPIOD_IN, "hpd");
-	if (IS_ERR(dvi->hpd)) {
-		ret = PTR_ERR(dvi->hpd);
-		dvi->hpd = NULL;
-		if (ret == -ENOENT)
-			ret = 0;
-		else
-			goto fail;
-	}
-
-	ddc_phandle = of_parse_phandle(connector_node, "ddc-i2c-bus", 0);
-	if (!ddc_phandle)
-		goto fail;
-
-	dvi->ddc = of_get_i2c_adapter_by_node(ddc_phandle);
-	if (dvi->ddc)
-		dev_info(dvi->dev, "Connector's ddc i2c bus found\n");
-	else
-		ret = -EPROBE_DEFER;
-
-	of_node_put(ddc_phandle);
-
-fail:
-	of_node_put(connector_node);
-	return ret;
-}
-
 static int tfp410_init(struct device *dev, bool i2c)
 {
+	struct device_node *node;
 	struct tfp410 *dvi;
 	int ret;
 
@@ -331,21 +292,31 @@ static int tfp410_init(struct device *dev, bool i2c)
 	dvi = devm_kzalloc(dev, sizeof(*dvi), GFP_KERNEL);
 	if (!dvi)
 		return -ENOMEM;
+
+	dvi->dev = dev;
 	dev_set_drvdata(dev, dvi);
 
 	dvi->bridge.funcs = &tfp410_bridge_funcs;
 	dvi->bridge.of_node = dev->of_node;
 	dvi->bridge.timings = &dvi->timings;
-	dvi->dev = dev;
+	dvi->bridge.type = DRM_MODE_CONNECTOR_DVID;
 
 	ret = tfp410_parse_timings(dvi, i2c);
 	if (ret)
-		goto fail;
+		return ret;
 
-	ret = tfp410_get_connector_properties(dvi);
-	if (ret)
-		goto fail;
+	/* Get the next bridge, connected to port@1. */
+	node = of_graph_get_remote_node(dev->of_node, 1, -1);
+	if (!node)
+		return -ENODEV;
 
+	dvi->next_bridge = of_drm_find_bridge(node);
+	of_node_put(node);
+
+	if (!dvi->next_bridge)
+		return -EPROBE_DEFER;
+
+	/* Get the powerdown GPIO. */
 	dvi->powerdown = devm_gpiod_get_optional(dev, "powerdown",
 						 GPIOD_OUT_HIGH);
 	if (IS_ERR(dvi->powerdown)) {
@@ -353,48 +324,18 @@ static int tfp410_init(struct device *dev, bool i2c)
 		return PTR_ERR(dvi->powerdown);
 	}
 
-	if (dvi->hpd)
-		dvi->hpd_irq = gpiod_to_irq(dvi->hpd);
-	else
-		dvi->hpd_irq = -ENXIO;
-
-	if (dvi->hpd_irq >= 0) {
-		INIT_DELAYED_WORK(&dvi->hpd_work, tfp410_hpd_work_func);
-
-		ret = devm_request_threaded_irq(dev, dvi->hpd_irq,
-			NULL, tfp410_hpd_irq_thread, IRQF_TRIGGER_RISING |
-			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-			"hdmi-hpd", dvi);
-		if (ret) {
-			dev_err(dev, "failed to register hpd interrupt\n");
-			goto fail;
-		}
-	}
-
+	/*  Register the DRM bridge. */
 	drm_bridge_add(&dvi->bridge);
 
 	return 0;
-fail:
-	i2c_put_adapter(dvi->ddc);
-	if (dvi->hpd)
-		gpiod_put(dvi->hpd);
-	return ret;
 }
 
 static int tfp410_fini(struct device *dev)
 {
 	struct tfp410 *dvi = dev_get_drvdata(dev);
 
-	if (dvi->hpd_irq >= 0)
-		cancel_delayed_work_sync(&dvi->hpd_work);
-
 	drm_bridge_remove(&dvi->bridge);
 
-	if (dvi->ddc)
-		i2c_put_adapter(dvi->ddc);
-	if (dvi->hpd)
-		gpiod_put(dvi->hpd);
-
 	return 0;
 }
 
-- 
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] 106+ messages in thread

* [PATCH v2 16/50] drm/bridge: tfp410: Allow operation without drm_connector
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (14 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 15/50] drm/bridge: tfp410: Replace manual connector handling with bridge Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-22 18:17   ` Boris Brezillon
  2019-08-20  1:16 ` [PATCH v2 17/50] drm: Add helper to create a connector for a chain of bridges Laurent Pinchart
                   ` (34 subsequent siblings)
  50 siblings, 1 reply; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

The tfp410 driver can operate as part of a pipeline where the
drm_connector is created by the display controller. Enable this mode of
operation by skipping creation of a drm_connector internally.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/bridge/ti-tfp410.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
index 65651ae6c553..16cc8abe3262 100644
--- a/drivers/gpu/drm/bridge/ti-tfp410.c
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -133,7 +133,7 @@ static int tfp410_attach(struct drm_bridge *bridge,
 		return ret;
 
 	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
-		return -EINVAL;
+		return 0;
 
 	if (!bridge->encoder) {
 		dev_err(dvi->dev, "Missing encoder\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] 106+ messages in thread

* [PATCH v2 17/50] drm: Add helper to create a connector for a chain of bridges
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (15 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 16/50] drm/bridge: tfp410: Allow operation without drm_connector Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-22 18:31   ` Boris Brezillon
  2019-08-20  1:16 ` [PATCH v2 18/50] drm/omap: Simplify HDMI mode and infoframe configuration Laurent Pinchart
                   ` (33 subsequent siblings)
  50 siblings, 1 reply; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Most bridge drivers create a DRM connector to model the connector at the
output of the bridge. This model is historical and has worked pretty
well so far, but causes several issues:

- It prevents supporting more complex display pipelines where DRM
connector operations are split over multiple components. For instance a
pipeline with a bridge connected to the DDC signals to read EDID data,
and another one connected to the HPD signal to detect connection and
disconnection, will not be possible to support through this model.

- It requires every bridge driver to implement similar connector
handling code, resulting in code duplication.

- It assumes that a bridge will either be wired to a connector or to
another bridge, but doesn't support bridges that can be used in both
positions very well (although there is some ad-hoc support for this in
the analogix_dp bridge driver).

In order to solve these issues, ownership of the connector needs to be
moved to the display controller driver.

To avoid code duplication in display controller drivers, add a new
helper to create and manage a DRM connector backed by a chain of
bridges. All connector operations are delegating to the appropriate
bridge in the chain.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v1:

- Removed the unused MAX_EDID macro
- Removed the unused drm_bridge_connector.hdmi_mode field
- Use drm_connector_init_with_ddc()
---
 drivers/gpu/drm/Makefile               |   3 +-
 drivers/gpu/drm/drm_bridge_connector.c | 372 +++++++++++++++++++++++++
 include/drm/drm_bridge_connector.h     |  18 ++
 3 files changed, 392 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/drm_bridge_connector.c
 create mode 100644 include/drm/drm_bridge_connector.h

diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 10f8329a8b71..acc984d2ab4f 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -37,7 +37,8 @@ drm_vram_helper-y := drm_gem_vram_helper.o \
 		     drm_vram_mm_helper.o
 obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
 
-drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_dsc.o drm_probe_helper.o \
+drm_kms_helper-y := drm_bridge_connector.o drm_crtc_helper.o drm_dp_helper.o \
+		drm_dsc.o drm_probe_helper.o \
 		drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
 		drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
 		drm_simple_kms_helper.o drm_modeset_helper.o \
diff --git a/drivers/gpu/drm/drm_bridge_connector.c b/drivers/gpu/drm/drm_bridge_connector.c
new file mode 100644
index 000000000000..a968570245e7
--- /dev/null
+++ b/drivers/gpu/drm/drm_bridge_connector.c
@@ -0,0 +1,372 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <drm/drm_atomic_state_helper.h>
+#include <drm/drm_bridge.h>
+#include <drm/drm_bridge_connector.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_device.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_probe_helper.h>
+
+/**
+ * DOC: overview
+ *
+ * The DRM bridge connector helper object provides a DRM connector
+ * implementation that wraps a chain of &struct drm_bridge. The connector
+ * operations are fully implemented based on the operations of the bridges in
+ * the chain, and don't require any intervention from the display controller
+ * driver at runtime.
+ *
+ * To use the helper, display controller drivers create a bridge connector with
+ * a call to drm_bridge_connector_init(). This associates the newly created
+ * connector with the chain of bridges passed to the function and registers it
+ * with the DRM device. At that point the connector becomes fully usable, no
+ * further operation is needed.
+ *
+ * The DRM bridge connector operations are implemented based on the operations
+ * provided by the bridges in the chain. Each connector operation is delegated
+ * to the bridge closest to the connector (at the end of the chain) that
+ * provides the relevant functionality.
+ *
+ * To make use of this helper, all bridges in the chain shall report bridge
+ * operation flags (&drm_bridge->ops) and bridge output type
+ * (&drm_bridge->type), and none of them may create a DRM connector directly.
+ */
+
+/**
+ * struct drm_bridge_connector - A connector backed by a chain of bridges
+ */
+struct drm_bridge_connector {
+	/**
+	 * @base: The base DRM connector
+	 */
+	struct drm_connector base;
+	/**
+	 * @bridge:
+	 *
+	 * The first bridge in the chain (connected to the output of the CRTC).
+	 */
+	struct drm_bridge *bridge;
+	/**
+	 * @bridge_edid:
+	 *
+	 * The last bridge in the chain (closest to the connector) that provides
+	 * EDID read support, if any (see &DRM_BRIDGE_OP_EDID).
+	 */
+	struct drm_bridge *bridge_edid;
+	/**
+	 * @bridge_hpd:
+	 *
+	 * The last bridge in the chain (closest to the connector) that provides
+	 * hot-plug detection notification, if any (see &DRM_BRIDGE_OP_HPD).
+	 */
+	struct drm_bridge *bridge_hpd;
+	/**
+	 * @bridge_detect:
+	 *
+	 * The last bridge in the chain (closest to the connector) that provides
+	 * connector detection, if any (see &DRM_BRIDGE_OP_DETECT).
+	 */
+	struct drm_bridge *bridge_detect;
+	/**
+	 * @bridge_detect:
+	 *
+	 * The last bridge in the chain (closest to the connector) that provides
+	 * connector modes detection, if any (see &DRM_BRIDGE_OP_MODES).
+	 */
+	struct drm_bridge *bridge_modes;
+};
+
+#define to_drm_bridge_connector(x) \
+	container_of(x, struct drm_bridge_connector, base)
+
+/* -----------------------------------------------------------------------------
+ * Bridge Connector Hot-Plug Handling
+ */
+
+static void drm_bridge_connector_hpd_notify(struct drm_connector *connector,
+					    enum drm_connector_status status)
+{
+	struct drm_bridge_connector *bridge_connector =
+		to_drm_bridge_connector(connector);
+	struct drm_bridge *bridge;
+
+	/* Notify all bridges in the pipeline of hotplug events. */
+	for (bridge = bridge_connector->bridge; bridge; bridge = bridge->next) {
+		if (bridge->funcs->hpd_notify)
+			bridge->funcs->hpd_notify(bridge, status);
+	}
+}
+
+static void drm_bridge_connector_hpd_cb(void *cb_data,
+					enum drm_connector_status status)
+{
+	struct drm_bridge_connector *drm_bridge_connector = cb_data;
+	struct drm_connector *connector = &drm_bridge_connector->base;
+	struct drm_device *dev = connector->dev;
+	enum drm_connector_status old_status;
+
+	mutex_lock(&dev->mode_config.mutex);
+	old_status = connector->status;
+	connector->status = status;
+	mutex_unlock(&dev->mode_config.mutex);
+
+	if (old_status == status)
+		return;
+
+	drm_bridge_connector_hpd_notify(connector, status);
+
+	drm_kms_helper_hotplug_event(dev);
+}
+
+/**
+ * drm_bridge_connector_enable_hpd - Enable hot-plug detection for the connector
+ * @connector: The DRM bridge connector
+ *
+ * This function enables hot-plug detection for the given bridge connector.
+ * This is typically used by display drivers in their resume handler.
+ */
+void drm_bridge_connector_enable_hpd(struct drm_connector *connector)
+{
+	struct drm_bridge_connector *bridge_connector =
+		to_drm_bridge_connector(connector);
+	struct drm_bridge *hpd = bridge_connector->bridge_hpd;
+
+	if (hpd)
+		drm_bridge_hpd_enable(hpd, drm_bridge_connector_hpd_cb,
+				      bridge_connector);
+}
+EXPORT_SYMBOL_GPL(drm_bridge_connector_enable_hpd);
+
+/**
+ * drm_bridge_connector_disable_hpd - Disable hot-plug detection for the
+ * connector
+ * @connector: The DRM bridge connector
+ *
+ * This function disables hot-plug detection for the given bridge connector.
+ * This is typically used by display drivers in their suspend handler.
+ */
+void drm_bridge_connector_disable_hpd(struct drm_connector *connector)
+{
+	struct drm_bridge_connector *bridge_connector =
+		to_drm_bridge_connector(connector);
+	struct drm_bridge *hpd = bridge_connector->bridge_hpd;
+
+	if (hpd)
+		drm_bridge_hpd_disable(hpd);
+}
+EXPORT_SYMBOL_GPL(drm_bridge_connector_disable_hpd);
+
+/* -----------------------------------------------------------------------------
+ * Bridge Connector Functions
+ */
+
+static enum drm_connector_status
+drm_bridge_connector_detect(struct drm_connector *connector, bool force)
+{
+	struct drm_bridge_connector *bridge_connector =
+		to_drm_bridge_connector(connector);
+	struct drm_bridge *detect = bridge_connector->bridge_detect;
+	enum drm_connector_status status;
+
+	if (detect) {
+		status = detect->funcs->detect(detect);
+
+		drm_bridge_connector_hpd_notify(connector, status);
+	} else {
+		switch (connector->connector_type) {
+		case DRM_MODE_CONNECTOR_DPI:
+		case DRM_MODE_CONNECTOR_LVDS:
+		case DRM_MODE_CONNECTOR_DSI:
+			status = connector_status_connected;
+			break;
+		default:
+			status = connector_status_unknown;
+			break;
+		}
+	}
+
+	return status;
+}
+
+static void drm_bridge_connector_destroy(struct drm_connector *connector)
+{
+	struct drm_bridge_connector *bridge_connector =
+		to_drm_bridge_connector(connector);
+
+	if (bridge_connector->bridge_hpd) {
+		struct drm_bridge *hpd = bridge_connector->bridge_hpd;
+
+		drm_bridge_hpd_disable(hpd);
+	}
+
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+
+	kfree(bridge_connector);
+}
+
+static const struct drm_connector_funcs drm_bridge_connector_funcs = {
+	.reset = drm_atomic_helper_connector_reset,
+	.detect = drm_bridge_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = drm_bridge_connector_destroy,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+/* -----------------------------------------------------------------------------
+ * Bridge Connector Helper Functions
+ */
+
+static int drm_bridge_connector_get_modes_edid(struct drm_connector *connector,
+					       struct drm_bridge *bridge)
+{
+	enum drm_connector_status status;
+	struct edid *edid;
+	int n;
+
+	status = drm_bridge_connector_detect(connector, false);
+	if (status != connector_status_connected)
+		goto no_edid;
+
+	edid = bridge->funcs->get_edid(bridge, connector);
+	if (!edid || !drm_edid_is_valid(edid)) {
+		kfree(edid);
+		goto no_edid;
+	}
+
+	drm_connector_update_edid_property(connector, edid);
+	n = drm_add_edid_modes(connector, edid);
+
+	kfree(edid);
+	return n;
+
+no_edid:
+	drm_connector_update_edid_property(connector, NULL);
+	return 0;
+}
+
+static int drm_bridge_connector_get_modes(struct drm_connector *connector)
+{
+	struct drm_bridge_connector *bridge_connector =
+		to_drm_bridge_connector(connector);
+	struct drm_bridge *bridge;
+
+	/*
+	 * If display exposes EDID, then we parse that in the normal way to
+	 * build table of supported modes.
+	 */
+	bridge = bridge_connector->bridge_edid;
+	if (bridge)
+		return drm_bridge_connector_get_modes_edid(connector, bridge);
+
+	/*
+	 * Otherwise if the display pipeline reports modes (e.g. with a fixed
+	 * resolution panel or an analog TV output), query it.
+	 */
+	bridge = bridge_connector->bridge_modes;
+	if (bridge)
+		return bridge->funcs->get_modes(bridge, connector);
+
+	/*
+	 * We can't retrieve modes, which can happen for instance for a DVI or
+	 * VGA output with the DDC bus unconnected. The KMS core will add the
+	 * default modes.
+	 */
+	return 0;
+}
+
+static const struct drm_connector_helper_funcs drm_bridge_connector_helper_funcs = {
+	.get_modes = drm_bridge_connector_get_modes,
+	/* No need for .mode_valid(), the bridges are checked by the core. */
+};
+
+/* -----------------------------------------------------------------------------
+ * Bridge Connector Initialisation
+ */
+
+/**
+ * drm_bridge_connector_init - Initialise a connector for a chain of bridges
+ * @drm: the DRM device
+ * @bridge: the bridge closest to the CRTC output
+ *
+ * Allocate, initialise and register a &drm_bridge_connector with the @drm
+ * device. The connector is associated with a chain of bridges that starts at
+ * the CRTC output with @bridge. All bridges in the chain shall report bridge
+ * operation flags (&drm_bridge->ops) and bridge output type
+ * (&drm_bridge->type), and none of them may create a DRM connector directly.
+ *
+ * Returns a pointer to the new connector on success, or a negative error
+ * pointer otherwise.
+ */
+struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
+						struct drm_bridge *bridge)
+{
+	struct drm_bridge_connector *bridge_connector;
+	struct drm_connector *connector;
+	struct i2c_adapter *ddc = NULL;
+	int connector_type;
+
+	bridge_connector = kzalloc(sizeof(*bridge_connector), GFP_KERNEL);
+	if (!bridge_connector)
+		return ERR_PTR(-ENOMEM);
+
+	bridge_connector->bridge = bridge;
+
+	/*
+	 * Initialise connector status handling. First locate the furthest
+	 * bridges in the pipeline that support HPD and output detection. Then
+	 * initialise the connector polling mode, using HPD if available and
+	 * falling back to polling if supported. If neither HPD nor output
+	 * detection are available, we don't support hotplug detection at all.
+	 */
+	connector_type = DRM_MODE_CONNECTOR_Unknown;
+	for ( ; bridge; bridge = bridge->next) {
+		if (bridge->ops & DRM_BRIDGE_OP_EDID)
+			bridge_connector->bridge_edid = bridge;
+		if (bridge->ops & DRM_BRIDGE_OP_HPD)
+			bridge_connector->bridge_hpd = bridge;
+		if (bridge->ops & DRM_BRIDGE_OP_DETECT)
+			bridge_connector->bridge_detect = bridge;
+		if (bridge->ops & DRM_BRIDGE_OP_MODES)
+			bridge_connector->bridge_modes = bridge;
+
+		if (!bridge->next)
+			connector_type = bridge->type;
+
+		if (bridge->ddc)
+			ddc = bridge->ddc;
+	}
+
+	if (connector_type == DRM_MODE_CONNECTOR_Unknown) {
+		kfree(bridge_connector);
+		return ERR_PTR(-EINVAL);
+	}
+
+	/*
+	 * TODO: Handle interlace_allowed, doublescan_allowed, stereo_allowed
+	 * and ycbcr_420_allowed.
+	 */
+	connector = &bridge_connector->base;
+	drm_connector_init_with_ddc(drm, connector, &drm_bridge_connector_funcs,
+				    connector_type, ddc);
+	drm_connector_helper_add(connector, &drm_bridge_connector_helper_funcs);
+
+	if (bridge_connector->bridge_hpd)
+		connector->polled = DRM_CONNECTOR_POLL_HPD;
+	else if (bridge_connector->bridge_detect)
+		connector->polled = DRM_CONNECTOR_POLL_CONNECT
+				  | DRM_CONNECTOR_POLL_DISCONNECT;
+
+	return connector;
+}
+EXPORT_SYMBOL_GPL(drm_bridge_connector_init);
diff --git a/include/drm/drm_bridge_connector.h b/include/drm/drm_bridge_connector.h
new file mode 100644
index 000000000000..ec33b44954b8
--- /dev/null
+++ b/include/drm/drm_bridge_connector.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ */
+
+#ifndef __DRM_BRIDGE_CONNECTOR_H__
+#define __DRM_BRIDGE_CONNECTOR_H__
+
+struct drm_bridge;
+struct drm_connector;
+struct drm_device;
+
+void drm_bridge_connector_enable_hpd(struct drm_connector *connector);
+void drm_bridge_connector_disable_hpd(struct drm_connector *connector);
+struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
+						struct drm_bridge *bridge);
+
+#endif /* __DRM_BRIDGE_CONNECTOR_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] 106+ messages in thread

* [PATCH v2 18/50] drm/omap: Simplify HDMI mode and infoframe configuration
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (16 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 17/50] drm: Add helper to create a connector for a chain of bridges Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-20  1:16 ` [PATCH v2 19/50] drm/omap: Factor out display type to connector type conversion Laurent Pinchart
                   ` (32 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Remove the omap_connector_get_hdmi_mode() function as the HDMI mode can
be accessed directly from the connector's display info.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/gpu/drm/omapdrm/omap_connector.c | 11 -----------
 drivers/gpu/drm/omapdrm/omap_connector.h |  1 -
 drivers/gpu/drm/omapdrm/omap_encoder.c   |  4 +---
 3 files changed, 1 insertion(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
index 5b8799c69f68..f2dd8e1fc48b 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -21,7 +21,6 @@ struct omap_connector {
 	struct drm_connector base;
 	struct omap_dss_device *output;
 	struct omap_dss_device *hpd;
-	bool hdmi_mode;
 };
 
 static void omap_connector_hpd_notify(struct drm_connector *connector,
@@ -84,13 +83,6 @@ void omap_connector_disable_hpd(struct drm_connector *connector)
 		hpd->ops->unregister_hpd_cb(hpd);
 }
 
-bool omap_connector_get_hdmi_mode(struct drm_connector *connector)
-{
-	struct omap_connector *omap_connector = to_omap_connector(connector);
-
-	return omap_connector->hdmi_mode;
-}
-
 static struct omap_dss_device *
 omap_connector_find_device(struct drm_connector *connector,
 			   enum omap_dss_device_ops_flag op)
@@ -167,7 +159,6 @@ static void omap_connector_destroy(struct drm_connector *connector)
 static int omap_connector_get_modes_edid(struct drm_connector *connector,
 					 struct omap_dss_device *dssdev)
 {
-	struct omap_connector *omap_connector = to_omap_connector(connector);
 	enum drm_connector_status status;
 	void *edid;
 	int n;
@@ -189,8 +180,6 @@ static int omap_connector_get_modes_edid(struct drm_connector *connector,
 	drm_connector_update_edid_property(connector, edid);
 	n = drm_add_edid_modes(connector, edid);
 
-	omap_connector->hdmi_mode = drm_detect_hdmi_monitor(edid);
-
 	kfree(edid);
 	return n;
 
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.h b/drivers/gpu/drm/omapdrm/omap_connector.h
index 13607bda33d8..4aa5608f4bbe 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.h
+++ b/drivers/gpu/drm/omapdrm/omap_connector.h
@@ -21,7 +21,6 @@ struct omap_dss_device;
 struct drm_connector *omap_connector_init(struct drm_device *dev,
 					  struct omap_dss_device *output,
 					  struct drm_encoder *encoder);
-bool omap_connector_get_hdmi_mode(struct drm_connector *connector);
 void omap_connector_enable_hpd(struct drm_connector *connector);
 void omap_connector_disable_hpd(struct drm_connector *connector);
 enum drm_mode_status omap_connector_mode_fixup(struct omap_dss_device *dssdev,
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
index 6fe14111cd95..415d0eac1c0c 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -75,9 +75,7 @@ static void omap_encoder_hdmi_mode_set(struct drm_connector *connector,
 {
 	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
 	struct omap_dss_device *dssdev = omap_encoder->output;
-	bool hdmi_mode;
-
-	hdmi_mode = omap_connector_get_hdmi_mode(connector);
+	bool hdmi_mode = connector->display_info.is_hdmi;
 
 	if (dssdev->ops->hdmi.set_hdmi_mode)
 		dssdev->ops->hdmi.set_hdmi_mode(dssdev, hdmi_mode);
-- 
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] 106+ messages in thread

* [PATCH v2 19/50] drm/omap: Factor out display type to connector type conversion
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (17 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 18/50] drm/omap: Simplify HDMI mode and infoframe configuration Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-20  1:16 ` [PATCH v2 20/50] drm/omap: Use the drm_panel_bridge API Laurent Pinchart
                   ` (31 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Move the code that computes the DRM connector type for the
omapdss_device display type to a new omapdss_device_connector_type()
function for later reuse.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/gpu/drm/omapdrm/dss/base.c       | 23 +++++++++++++++++++++++
 drivers/gpu/drm/omapdrm/dss/omapdss.h    |  1 +
 drivers/gpu/drm/omapdrm/omap_connector.c | 19 +------------------
 3 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/base.c b/drivers/gpu/drm/omapdrm/dss/base.c
index a1970b9db6ab..cae5687822e2 100644
--- a/drivers/gpu/drm/omapdrm/dss/base.c
+++ b/drivers/gpu/drm/omapdrm/dss/base.c
@@ -285,6 +285,29 @@ void omapdss_device_post_disable(struct omap_dss_device *dssdev)
 }
 EXPORT_SYMBOL_GPL(omapdss_device_post_disable);
 
+unsigned int omapdss_device_connector_type(enum omap_display_type type)
+{
+	switch (type) {
+	case OMAP_DISPLAY_TYPE_HDMI:
+		return DRM_MODE_CONNECTOR_HDMIA;
+	case OMAP_DISPLAY_TYPE_DVI:
+		return DRM_MODE_CONNECTOR_DVID;
+	case OMAP_DISPLAY_TYPE_DSI:
+		return DRM_MODE_CONNECTOR_DSI;
+	case OMAP_DISPLAY_TYPE_DPI:
+	case OMAP_DISPLAY_TYPE_DBI:
+		return DRM_MODE_CONNECTOR_DPI;
+	case OMAP_DISPLAY_TYPE_VENC:
+		/* TODO: This could also be composite */
+		return DRM_MODE_CONNECTOR_SVIDEO;
+	case OMAP_DISPLAY_TYPE_SDI:
+		return DRM_MODE_CONNECTOR_LVDS;
+	default:
+		return DRM_MODE_CONNECTOR_Unknown;
+	}
+}
+EXPORT_SYMBOL_GPL(omapdss_device_connector_type);
+
 /* -----------------------------------------------------------------------------
  * Components Handling
  */
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 79f6b195c7cf..c5672e5174c5 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -479,6 +479,7 @@ void omapdss_device_pre_enable(struct omap_dss_device *dssdev);
 void omapdss_device_enable(struct omap_dss_device *dssdev);
 void omapdss_device_disable(struct omap_dss_device *dssdev);
 void omapdss_device_post_disable(struct omap_dss_device *dssdev);
+unsigned int omapdss_device_connector_type(enum omap_display_type type);
 
 int omap_dss_get_num_overlay_managers(void);
 
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
index f2dd8e1fc48b..8dc613afb1c5 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -295,24 +295,7 @@ static int omap_connector_get_type(struct omap_dss_device *output)
 	type = display->type;
 	omapdss_device_put(display);
 
-	switch (type) {
-	case OMAP_DISPLAY_TYPE_HDMI:
-		return DRM_MODE_CONNECTOR_HDMIA;
-	case OMAP_DISPLAY_TYPE_DVI:
-		return DRM_MODE_CONNECTOR_DVID;
-	case OMAP_DISPLAY_TYPE_DSI:
-		return DRM_MODE_CONNECTOR_DSI;
-	case OMAP_DISPLAY_TYPE_DPI:
-	case OMAP_DISPLAY_TYPE_DBI:
-		return DRM_MODE_CONNECTOR_DPI;
-	case OMAP_DISPLAY_TYPE_VENC:
-		/* TODO: This could also be composite */
-		return DRM_MODE_CONNECTOR_SVIDEO;
-	case OMAP_DISPLAY_TYPE_SDI:
-		return DRM_MODE_CONNECTOR_LVDS;
-	default:
-		return DRM_MODE_CONNECTOR_Unknown;
-	}
+	return omapdss_device_connector_type(type);
 }
 
 /* initialize connector */
-- 
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] 106+ messages in thread

* [PATCH v2 20/50] drm/omap: Use the drm_panel_bridge API
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (18 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 19/50] drm/omap: Factor out display type to connector type conversion Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-20  1:16 ` [PATCH v2 21/50] drm/omap: dss: Fix output next device lookup in DT Laurent Pinchart
                   ` (30 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Replace the manual panel handling code by a drm_panel_bridge. This
simplifies the driver and allows all components in the display pipeline
to be treated as bridges, paving the way to generic connector handling.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
Changes since v1:

- Keep #include <drm/drm_panel.h>
---
 drivers/gpu/drm/omapdrm/dss/base.c       | 12 ++++-----
 drivers/gpu/drm/omapdrm/dss/output.c     | 33 +++++++++++++++++++++---
 drivers/gpu/drm/omapdrm/omap_connector.c |  9 -------
 drivers/gpu/drm/omapdrm/omap_drv.c       | 13 ----------
 drivers/gpu/drm/omapdrm/omap_encoder.c   | 13 ----------
 5 files changed, 34 insertions(+), 46 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/base.c b/drivers/gpu/drm/omapdrm/dss/base.c
index cae5687822e2..80d48936d177 100644
--- a/drivers/gpu/drm/omapdrm/dss/base.c
+++ b/drivers/gpu/drm/omapdrm/dss/base.c
@@ -149,8 +149,7 @@ struct omap_dss_device *omapdss_device_next_output(struct omap_dss_device *from)
 			goto done;
 		}
 
-		if (dssdev->id &&
-		    (dssdev->next || dssdev->bridge || dssdev->panel))
+		if (dssdev->id && (dssdev->next || dssdev->bridge))
 			goto done;
 	}
 
@@ -185,11 +184,10 @@ int omapdss_device_connect(struct dss_device *dss,
 	if (!dst) {
 		/*
 		 * The destination is NULL when the source is connected to a
-		 * bridge or panel instead of a DSS device. Stop here, we will
-		 * attach the bridge or panel later when we will have a DRM
-		 * encoder.
+		 * bridge instead of a DSS device. Stop here, we will attach
+		 * the bridge later when we will have a DRM encoder.
 		 */
-		return src && (src->bridge || src->panel) ? 0 : -EINVAL;
+		return src && src->bridge ? 0 : -EINVAL;
 	}
 
 	if (omapdss_device_is_connected(dst))
@@ -217,7 +215,7 @@ void omapdss_device_disconnect(struct omap_dss_device *src,
 		dst ? dev_name(dst->dev) : "NULL");
 
 	if (!dst) {
-		WARN_ON(!src->bridge && !src->panel);
+		WARN_ON(!src->bridge);
 		return;
 	}
 
diff --git a/drivers/gpu/drm/omapdrm/dss/output.c b/drivers/gpu/drm/omapdrm/dss/output.c
index de0f882f0f7b..ca02728acc15 100644
--- a/drivers/gpu/drm/omapdrm/dss/output.c
+++ b/drivers/gpu/drm/omapdrm/dss/output.c
@@ -19,6 +19,7 @@
 int omapdss_device_init_output(struct omap_dss_device *out)
 {
 	struct device_node *remote_node;
+	int ret;
 
 	remote_node = of_graph_get_remote_node(out->dev->of_node, 0, 0);
 	if (!remote_node) {
@@ -36,17 +37,41 @@ int omapdss_device_init_output(struct omap_dss_device *out)
 
 	if (out->next && out->type != out->next->type) {
 		dev_err(out->dev, "output type and display type don't match\n");
-		omapdss_device_put(out->next);
-		out->next = NULL;
-		return -EINVAL;
+		ret = -EINVAL;
+		goto error;
 	}
 
-	return out->next || out->bridge || out->panel ? 0 : -EPROBE_DEFER;
+	if (out->panel) {
+		unsigned int connector_type;
+		struct drm_bridge *bridge;
+
+		connector_type = omapdss_device_connector_type(out->type);
+		bridge = drm_panel_bridge_add(out->panel, connector_type);
+		if (IS_ERR(bridge)) {
+			dev_err(out->dev,
+				"unable to create panel bridge (%ld)\n",
+				PTR_ERR(bridge));
+			ret = PTR_ERR(bridge);
+			goto error;
+		}
+
+		out->bridge = bridge;
+	}
+
+	return out->next || out->bridge ? 0 : -EPROBE_DEFER;
+
+error:
+	omapdss_device_put(out->next);
+	out->next = NULL;
+	return ret;
 }
 EXPORT_SYMBOL(omapdss_device_init_output);
 
 void omapdss_device_cleanup_output(struct omap_dss_device *out)
 {
+	if (out->bridge && out->panel)
+		drm_panel_bridge_remove(out->bridge);
+
 	if (out->next)
 		omapdss_device_put(out->next);
 }
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
index 8dc613afb1c5..b0cb2ecb30ab 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -6,7 +6,6 @@
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
-#include <drm/drm_panel.h>
 #include <drm/drm_probe_helper.h>
 
 #include "omap_drv.h"
@@ -190,7 +189,6 @@ static int omap_connector_get_modes_edid(struct drm_connector *connector,
 
 static int omap_connector_get_modes(struct drm_connector *connector)
 {
-	struct omap_connector *omap_connector = to_omap_connector(connector);
 	struct omap_dss_device *dssdev;
 
 	DBG("%s", connector->name);
@@ -213,13 +211,6 @@ static int omap_connector_get_modes(struct drm_connector *connector)
 	if (dssdev)
 		return dssdev->ops->get_modes(dssdev, connector);
 
-	/*
-	 * Otherwise if the display pipeline uses a drm_panel, we delegate the
-	 * operation to the panel API.
-	 */
-	if (omap_connector->output->panel)
-		return drm_panel_get_modes(omap_connector->output->panel);
-
 	/*
 	 * We can't retrieve modes, which can happen for instance for a DVI or
 	 * VGA output with the DDC bus unconnected. The KMS core will add the
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 2988af9ae743..72872dfdb73e 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -15,7 +15,6 @@
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_file.h>
 #include <drm/drm_ioctl.h>
-#include <drm/drm_panel.h>
 #include <drm/drm_prime.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
@@ -133,9 +132,6 @@ static void omap_disconnect_pipelines(struct drm_device *ddev)
 	for (i = 0; i < priv->num_pipes; i++) {
 		struct omap_drm_pipeline *pipe = &priv->pipes[i];
 
-		if (pipe->output->panel)
-			drm_panel_detach(pipe->output->panel);
-
 		omapdss_device_disconnect(NULL, pipe->output);
 
 		omapdss_device_put(pipe->output);
@@ -220,8 +216,6 @@ static int omap_display_id(struct omap_dss_device *output)
 			bridge = bridge->next;
 
 		node = bridge->of_node;
-	} else if (output->panel) {
-		node = output->panel->dev->of_node;
 	}
 
 	return node ? of_alias_get_id(node, "display") : -ENODEV;
@@ -336,13 +330,6 @@ static int omap_modeset_init(struct drm_device *dev)
 				return -ENOMEM;
 
 			drm_connector_attach_encoder(pipe->connector, encoder);
-
-			if (pipe->output->panel) {
-				ret = drm_panel_attach(pipe->output->panel,
-						       pipe->connector);
-				if (ret < 0)
-					return ret;
-			}
 		}
 
 		crtc = omap_crtc_init(dev, pipe, priv->planes[i]);
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
index 415d0eac1c0c..7f3f5844c62a 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -9,7 +9,6 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_modeset_helper_vtables.h>
 #include <drm/drm_edid.h>
-#include <drm/drm_panel.h>
 
 #include "omap_drv.h"
 
@@ -155,12 +154,6 @@ static void omap_encoder_disable(struct drm_encoder *encoder)
 
 	dev_dbg(dev->dev, "disable(%s)\n", dssdev->name);
 
-	/* Disable the panel if present. */
-	if (dssdev->panel) {
-		drm_panel_disable(dssdev->panel);
-		drm_panel_unprepare(dssdev->panel);
-	}
-
 	/*
 	 * Disable the chain of external devices, starting at the one at the
 	 * internal encoder's output.
@@ -210,12 +203,6 @@ static void omap_encoder_enable(struct drm_encoder *encoder)
 	 * internal encoder's output.
 	 */
 	omapdss_device_enable(dssdev->next);
-
-	/* Enable the panel if present. */
-	if (dssdev->panel) {
-		drm_panel_prepare(dssdev->panel);
-		drm_panel_enable(dssdev->panel);
-	}
 }
 
 static int omap_encoder_atomic_check(struct drm_encoder *encoder,
-- 
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] 106+ messages in thread

* [PATCH v2 21/50] drm/omap: dss: Fix output next device lookup in DT
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (19 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 20/50] drm/omap: Use the drm_panel_bridge API Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-20  1:16 ` [PATCH v2 22/50] drm/omap: Add infrastructure to support drm_bridge local to DSS outputs Laurent Pinchart
                   ` (29 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

The DSS core looks up the next device connected to an output by
traversing the OF graph. It currently hardcodes the local port number to
0, which breaks any output with a different port number (SDI on OMAP3
and any DPI output but the first one). Fix this by repurposing the
currently unused of_ports bitmask in omap_dss_device with an of_port
output port number, and use it to traverse the OF graph.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c | 2 +-
 drivers/gpu/drm/omapdrm/displays/connector-hdmi.c      | 2 +-
 drivers/gpu/drm/omapdrm/displays/encoder-opa362.c      | 2 +-
 drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c   | 2 +-
 drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c        | 2 +-
 drivers/gpu/drm/omapdrm/dss/dpi.c                      | 2 +-
 drivers/gpu/drm/omapdrm/dss/dsi.c                      | 2 +-
 drivers/gpu/drm/omapdrm/dss/hdmi4.c                    | 2 +-
 drivers/gpu/drm/omapdrm/dss/hdmi5.c                    | 2 +-
 drivers/gpu/drm/omapdrm/dss/omapdss.h                  | 4 ++--
 drivers/gpu/drm/omapdrm/dss/output.c                   | 3 ++-
 drivers/gpu/drm/omapdrm/dss/sdi.c                      | 2 +-
 drivers/gpu/drm/omapdrm/dss/venc.c                     | 2 +-
 13 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
index 0d20fab605d7..f36aa1885d39 100644
--- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
+++ b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
@@ -55,7 +55,7 @@ static int tvc_probe(struct platform_device *pdev)
 	dssdev->type = OMAP_DISPLAY_TYPE_VENC;
 	dssdev->display = true;
 	dssdev->owner = THIS_MODULE;
-	dssdev->of_ports = BIT(0);
+	dssdev->of_port = 0;
 
 	omapdss_display_init(dssdev);
 	omapdss_device_register(dssdev);
diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
index f5d69d810bb8..37c212491cd3 100644
--- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
+++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
@@ -139,7 +139,7 @@ static int hdmic_probe(struct platform_device *pdev)
 	dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
 	dssdev->display = true;
 	dssdev->owner = THIS_MODULE;
-	dssdev->of_ports = BIT(0);
+	dssdev->of_port = 0;
 	dssdev->ops_flags = ddata->hpd_gpio
 			  ? OMAP_DSS_DEVICE_OP_DETECT | OMAP_DSS_DEVICE_OP_HPD
 			  : 0;
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c b/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
index b992387ed674..252705222ef1 100644
--- a/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
+++ b/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
@@ -86,7 +86,7 @@ static int opa362_probe(struct platform_device *pdev)
 	dssdev->dev = &pdev->dev;
 	dssdev->type = OMAP_DISPLAY_TYPE_VENC;
 	dssdev->owner = THIS_MODULE;
-	dssdev->of_ports = BIT(1) | BIT(0);
+	dssdev->of_port = 1;
 
 	dssdev->next = omapdss_of_find_connected_device(pdev->dev.of_node, 1);
 	if (IS_ERR(dssdev->next)) {
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
index 089105c5aa0a..857ae84cd7d1 100644
--- a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
+++ b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
@@ -165,7 +165,7 @@ static int tpd_probe(struct platform_device *pdev)
 	dssdev->dev = &pdev->dev;
 	dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
 	dssdev->owner = THIS_MODULE;
-	dssdev->of_ports = BIT(1) | BIT(0);
+	dssdev->of_port = 1;
 	dssdev->ops_flags = OMAP_DSS_DEVICE_OP_DETECT
 			  | OMAP_DSS_DEVICE_OP_HPD;
 
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
index 564e3e1a1891..939ea0578f6a 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
@@ -1265,7 +1265,7 @@ static int dsicm_probe(struct platform_device *pdev)
 	dssdev->type = OMAP_DISPLAY_TYPE_DSI;
 	dssdev->display = true;
 	dssdev->owner = THIS_MODULE;
-	dssdev->of_ports = BIT(0);
+	dssdev->of_port = 0;
 	dssdev->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
 
 	dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c
index 95147437b990..462ed6f3118a 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -625,7 +625,7 @@ static int dpi_init_output_port(struct dpi_data *dpi, struct device_node *port)
 	out->id = OMAP_DSS_OUTPUT_DPI;
 	out->type = OMAP_DISPLAY_TYPE_DPI;
 	out->dispc_channel = dpi_get_channel(dpi);
-	out->of_ports = BIT(port_num);
+	out->of_port = port_num;
 	out->ops = &dpi_ops;
 	out->owner = THIS_MODULE;
 
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c
index b30fcaa2d0f5..0b04a10b8996 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -5117,7 +5117,7 @@ static int dsi_init_output(struct dsi_data *dsi)
 	out->dispc_channel = dsi_get_channel(dsi);
 	out->ops = &dsi_ops;
 	out->owner = THIS_MODULE;
-	out->of_ports = BIT(0);
+	out->of_port = 0;
 	out->bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE
 		       | DRM_BUS_FLAG_DE_HIGH
 		       | DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE;
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 0f557fad4513..44075718407b 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -673,7 +673,7 @@ static int hdmi4_init_output(struct omap_hdmi *hdmi)
 	out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
 	out->ops = &hdmi_ops;
 	out->owner = THIS_MODULE;
-	out->of_ports = BIT(0);
+	out->of_port = 0;
 	out->ops_flags = OMAP_DSS_DEVICE_OP_EDID;
 
 	r = omapdss_device_init_output(out);
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index d9463b332554..1b5bd44ee09d 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -657,7 +657,7 @@ static int hdmi5_init_output(struct omap_hdmi *hdmi)
 	out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
 	out->ops = &hdmi_ops;
 	out->owner = THIS_MODULE;
-	out->of_ports = BIT(0);
+	out->of_port = 0;
 	out->ops_flags = OMAP_DSS_DEVICE_OP_EDID;
 
 	r = omapdss_device_init_output(out);
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index c5672e5174c5..b48a51d11310 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -436,8 +436,8 @@ struct omap_dss_device {
 	/* output instance */
 	enum omap_dss_output_id id;
 
-	/* bitmask of port numbers in DT */
-	unsigned int of_ports;
+	/* port number in DT */
+	unsigned int of_port;
 };
 
 struct omap_dss_driver {
diff --git a/drivers/gpu/drm/omapdrm/dss/output.c b/drivers/gpu/drm/omapdrm/dss/output.c
index ca02728acc15..745afd7d80de 100644
--- a/drivers/gpu/drm/omapdrm/dss/output.c
+++ b/drivers/gpu/drm/omapdrm/dss/output.c
@@ -21,7 +21,8 @@ int omapdss_device_init_output(struct omap_dss_device *out)
 	struct device_node *remote_node;
 	int ret;
 
-	remote_node = of_graph_get_remote_node(out->dev->of_node, 0, 0);
+	remote_node = of_graph_get_remote_node(out->dev->of_node,
+					       out->of_port, 0);
 	if (!remote_node) {
 		dev_dbg(out->dev, "failed to find video sink\n");
 		return 0;
diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c
index 3b447c01fa2a..9092ed3d0ef1 100644
--- a/drivers/gpu/drm/omapdrm/dss/sdi.c
+++ b/drivers/gpu/drm/omapdrm/dss/sdi.c
@@ -265,7 +265,7 @@ static int sdi_init_output(struct sdi_device *sdi)
 	out->name = "sdi.0";
 	out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
 	/* We have SDI only on OMAP3, where it's on port 1 */
-	out->of_ports = BIT(1);
+	out->of_port = 1;
 	out->ops = &sdi_ops;
 	out->owner = THIS_MODULE;
 	out->bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE	/* 15.5.9.1.2 */
diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c
index 596a297d5813..e2f480f689b8 100644
--- a/drivers/gpu/drm/omapdrm/dss/venc.c
+++ b/drivers/gpu/drm/omapdrm/dss/venc.c
@@ -754,7 +754,7 @@ static int venc_init_output(struct venc_device *venc)
 	out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
 	out->ops = &venc_ops;
 	out->owner = THIS_MODULE;
-	out->of_ports = BIT(0);
+	out->of_port = 0;
 	out->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
 
 	r = omapdss_device_init_output(out);
-- 
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] 106+ messages in thread

* [PATCH v2 22/50] drm/omap: Add infrastructure to support drm_bridge local to DSS outputs
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (20 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 21/50] drm/omap: dss: Fix output next device lookup in DT Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-20  1:16 ` [PATCH v2 23/50] drm/omap: dss: Make omap_dss_device_ops optional Laurent Pinchart
                   ` (28 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

In order to support drm_bridge-based pipeline, the internal HDMI
encoders will need to expose the EDID read operation through the
drm_bridge API, and thus to expose a drm_bridge instance corresponding
to the encoder. The HDMI encoders are however handled as omap_dss_device
instances, which conflicts with this requirement.

In order to move forward with the drm_bridge transition, add support for
creating drm_bridge instances local to DSS outputs. If a local bridge is
passed to the omapdss_device_init_output() function, it is used as the
first bridge in the chain, and the omap_dss_device.next_bridge field is
set to the next bridge for the use of the internal encoders' bridges.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/gpu/drm/omapdrm/dss/dpi.c     |  2 +-
 drivers/gpu/drm/omapdrm/dss/dsi.c     |  2 +-
 drivers/gpu/drm/omapdrm/dss/hdmi4.c   |  2 +-
 drivers/gpu/drm/omapdrm/dss/hdmi5.c   |  2 +-
 drivers/gpu/drm/omapdrm/dss/omapdss.h |  4 +++-
 drivers/gpu/drm/omapdrm/dss/output.c  | 20 ++++++++++++++++----
 drivers/gpu/drm/omapdrm/dss/sdi.c     |  2 +-
 drivers/gpu/drm/omapdrm/dss/venc.c    |  2 +-
 drivers/gpu/drm/omapdrm/omap_drv.c    |  2 +-
 9 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c
index 462ed6f3118a..2d0eb5fcbb5b 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -629,7 +629,7 @@ static int dpi_init_output_port(struct dpi_data *dpi, struct device_node *port)
 	out->ops = &dpi_ops;
 	out->owner = THIS_MODULE;
 
-	r = omapdss_device_init_output(out);
+	r = omapdss_device_init_output(out, NULL);
 	if (r < 0)
 		return r;
 
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 0b04a10b8996..989d0d14ed5a 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -5122,7 +5122,7 @@ static int dsi_init_output(struct dsi_data *dsi)
 		       | DRM_BUS_FLAG_DE_HIGH
 		       | DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE;
 
-	r = omapdss_device_init_output(out);
+	r = omapdss_device_init_output(out, NULL);
 	if (r < 0)
 		return r;
 
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 44075718407b..dd4a14fe7e59 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -676,7 +676,7 @@ static int hdmi4_init_output(struct omap_hdmi *hdmi)
 	out->of_port = 0;
 	out->ops_flags = OMAP_DSS_DEVICE_OP_EDID;
 
-	r = omapdss_device_init_output(out);
+	r = omapdss_device_init_output(out, NULL);
 	if (r < 0)
 		return r;
 
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 1b5bd44ee09d..8e3790dd8b98 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -660,7 +660,7 @@ static int hdmi5_init_output(struct omap_hdmi *hdmi)
 	out->of_port = 0;
 	out->ops_flags = OMAP_DSS_DEVICE_OP_EDID;
 
-	r = omapdss_device_init_output(out);
+	r = omapdss_device_init_output(out, NULL);
 	if (r < 0)
 		return r;
 
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index b48a51d11310..82e9bfa5530a 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -400,6 +400,7 @@ struct omap_dss_device {
 	struct dss_device *dss;
 	struct omap_dss_device *next;
 	struct drm_bridge *bridge;
+	struct drm_bridge *next_bridge;
 	struct drm_panel *panel;
 
 	struct list_head list;
@@ -488,7 +489,8 @@ int omap_dss_get_num_overlays(void);
 #define for_each_dss_output(d) \
 	while ((d = omapdss_device_next_output(d)) != NULL)
 struct omap_dss_device *omapdss_device_next_output(struct omap_dss_device *from);
-int omapdss_device_init_output(struct omap_dss_device *out);
+int omapdss_device_init_output(struct omap_dss_device *out,
+			       struct drm_bridge *local_bridge);
 void omapdss_device_cleanup_output(struct omap_dss_device *out);
 
 typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
diff --git a/drivers/gpu/drm/omapdrm/dss/output.c b/drivers/gpu/drm/omapdrm/dss/output.c
index 745afd7d80de..b27739afb335 100644
--- a/drivers/gpu/drm/omapdrm/dss/output.c
+++ b/drivers/gpu/drm/omapdrm/dss/output.c
@@ -16,7 +16,8 @@
 #include "dss.h"
 #include "omapdss.h"
 
-int omapdss_device_init_output(struct omap_dss_device *out)
+int omapdss_device_init_output(struct omap_dss_device *out,
+			       struct drm_bridge *local_bridge)
 {
 	struct device_node *remote_node;
 	int ret;
@@ -59,10 +60,20 @@ int omapdss_device_init_output(struct omap_dss_device *out)
 		out->bridge = bridge;
 	}
 
-	return out->next || out->bridge ? 0 : -EPROBE_DEFER;
+	if (local_bridge) {
+		out->next_bridge = out->bridge;
+		out->bridge = local_bridge;
+	}
+
+	if (!out->next && !out->bridge) {
+		ret = -EPROBE_DEFER;
+		goto error;
+	}
+
+	return 0;
 
 error:
-	omapdss_device_put(out->next);
+	omapdss_device_cleanup_output(out);
 	out->next = NULL;
 	return ret;
 }
@@ -71,7 +82,8 @@ EXPORT_SYMBOL(omapdss_device_init_output);
 void omapdss_device_cleanup_output(struct omap_dss_device *out)
 {
 	if (out->bridge && out->panel)
-		drm_panel_bridge_remove(out->bridge);
+		drm_panel_bridge_remove(out->next_bridge ?
+					out->next_bridge : out->bridge);
 
 	if (out->next)
 		omapdss_device_put(out->next);
diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c
index 9092ed3d0ef1..11aa2f712ff4 100644
--- a/drivers/gpu/drm/omapdrm/dss/sdi.c
+++ b/drivers/gpu/drm/omapdrm/dss/sdi.c
@@ -271,7 +271,7 @@ static int sdi_init_output(struct sdi_device *sdi)
 	out->bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE	/* 15.5.9.1.2 */
 		       | DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE;
 
-	r = omapdss_device_init_output(out);
+	r = omapdss_device_init_output(out, NULL);
 	if (r < 0)
 		return r;
 
diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c
index e2f480f689b8..977d8d525b43 100644
--- a/drivers/gpu/drm/omapdrm/dss/venc.c
+++ b/drivers/gpu/drm/omapdrm/dss/venc.c
@@ -757,7 +757,7 @@ static int venc_init_output(struct venc_device *venc)
 	out->of_port = 0;
 	out->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
 
-	r = omapdss_device_init_output(out);
+	r = omapdss_device_init_output(out, NULL);
 	if (r < 0)
 		return r;
 
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 72872dfdb73e..de373fd50729 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -323,7 +323,7 @@ static int omap_modeset_init(struct drm_device *dev)
 		struct drm_encoder *encoder = pipe->encoder;
 		struct drm_crtc *crtc;
 
-		if (!pipe->output->bridge) {
+		if (pipe->output->next) {
 			pipe->connector = omap_connector_init(dev, pipe->output,
 							      encoder);
 			if (!pipe->connector)
-- 
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] 106+ messages in thread

* [PATCH v2 23/50] drm/omap: dss: Make omap_dss_device_ops optional
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (21 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 22/50] drm/omap: Add infrastructure to support drm_bridge local to DSS outputs Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-20  1:16 ` [PATCH v2 24/50] drm/omap: hdmi: Allocate EDID in the .read_edid() operation Laurent Pinchart
                   ` (27 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

As part of the move to drm_bridge ops, the dssdev ops will become empty
for some of the internal encoders. Make them optional in the driver to
allow them to be removed completely, easing the transition.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/gpu/drm/omapdrm/dss/base.c       | 21 ++++++++++++---------
 drivers/gpu/drm/omapdrm/dss/dss.c        |  3 ++-
 drivers/gpu/drm/omapdrm/omap_connector.c |  2 +-
 drivers/gpu/drm/omapdrm/omap_encoder.c   | 12 +++++++-----
 4 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/base.c b/drivers/gpu/drm/omapdrm/dss/base.c
index 80d48936d177..2db3bd2f19db 100644
--- a/drivers/gpu/drm/omapdrm/dss/base.c
+++ b/drivers/gpu/drm/omapdrm/dss/base.c
@@ -195,10 +195,12 @@ int omapdss_device_connect(struct dss_device *dss,
 
 	dst->dss = dss;
 
-	ret = dst->ops->connect(src, dst);
-	if (ret < 0) {
-		dst->dss = NULL;
-		return ret;
+	if (dst->ops && dst->ops->connect) {
+		ret = dst->ops->connect(src, dst);
+		if (ret < 0) {
+			dst->dss = NULL;
+			return ret;
+		}
 	}
 
 	return 0;
@@ -226,7 +228,8 @@ void omapdss_device_disconnect(struct omap_dss_device *src,
 
 	WARN_ON(dst->state != OMAP_DSS_DISPLAY_DISABLED);
 
-	dst->ops->disconnect(src, dst);
+	if (dst->ops && dst->ops->disconnect)
+		dst->ops->disconnect(src, dst);
 	dst->dss = NULL;
 }
 EXPORT_SYMBOL_GPL(omapdss_device_disconnect);
@@ -238,7 +241,7 @@ void omapdss_device_pre_enable(struct omap_dss_device *dssdev)
 
 	omapdss_device_pre_enable(dssdev->next);
 
-	if (dssdev->ops->pre_enable)
+	if (dssdev->ops && dssdev->ops->pre_enable)
 		dssdev->ops->pre_enable(dssdev);
 }
 EXPORT_SYMBOL_GPL(omapdss_device_pre_enable);
@@ -248,7 +251,7 @@ void omapdss_device_enable(struct omap_dss_device *dssdev)
 	if (!dssdev)
 		return;
 
-	if (dssdev->ops->enable)
+	if (dssdev->ops && dssdev->ops->enable)
 		dssdev->ops->enable(dssdev);
 
 	omapdss_device_enable(dssdev->next);
@@ -264,7 +267,7 @@ void omapdss_device_disable(struct omap_dss_device *dssdev)
 
 	omapdss_device_disable(dssdev->next);
 
-	if (dssdev->ops->disable)
+	if (dssdev->ops && dssdev->ops->disable)
 		dssdev->ops->disable(dssdev);
 }
 EXPORT_SYMBOL_GPL(omapdss_device_disable);
@@ -274,7 +277,7 @@ void omapdss_device_post_disable(struct omap_dss_device *dssdev)
 	if (!dssdev)
 		return;
 
-	if (dssdev->ops->post_disable)
+	if (dssdev->ops && dssdev->ops->post_disable)
 		dssdev->ops->post_disable(dssdev);
 
 	omapdss_device_post_disable(dssdev->next);
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c
index 5711b7a720e6..9001e1bd3055 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss.c
@@ -1550,7 +1550,8 @@ static void dss_shutdown(struct platform_device *pdev)
 	DSSDBG("shutdown\n");
 
 	for_each_dss_output(dssdev) {
-		if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+		if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE &&
+		    dssdev->ops && dssdev->ops->disable)
 			dssdev->ops->disable(dssdev);
 	}
 }
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
index b0cb2ecb30ab..a24cec4b0bb9 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -228,7 +228,7 @@ enum drm_mode_status omap_connector_mode_fixup(struct omap_dss_device *dssdev,
 	drm_mode_copy(adjusted_mode, mode);
 
 	for (; dssdev; dssdev = dssdev->next) {
-		if (!dssdev->ops->check_timings)
+		if (!dssdev->ops || !dssdev->ops->check_timings)
 			continue;
 
 		ret = dssdev->ops->check_timings(dssdev, adjusted_mode);
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
index 7f3f5844c62a..bd87c28f9046 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -76,10 +76,10 @@ static void omap_encoder_hdmi_mode_set(struct drm_connector *connector,
 	struct omap_dss_device *dssdev = omap_encoder->output;
 	bool hdmi_mode = connector->display_info.is_hdmi;
 
-	if (dssdev->ops->hdmi.set_hdmi_mode)
+	if (dssdev->ops && dssdev->ops->hdmi.set_hdmi_mode)
 		dssdev->ops->hdmi.set_hdmi_mode(dssdev, hdmi_mode);
 
-	if (hdmi_mode && dssdev->ops->hdmi.set_infoframe) {
+	if (hdmi_mode && dssdev->ops && dssdev->ops->hdmi.set_infoframe) {
 		struct hdmi_avi_infoframe avi;
 		int r;
 
@@ -137,7 +137,7 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
 	dss_mgr_set_timings(output, &vm);
 
 	for (dssdev = output; dssdev; dssdev = dssdev->next) {
-		if (dssdev->ops->set_timings)
+		if (dssdev->ops && dssdev->ops->set_timings)
 			dssdev->ops->set_timings(dssdev, adjusted_mode);
 	}
 
@@ -166,7 +166,8 @@ static void omap_encoder_disable(struct drm_encoder *encoder)
 	 * flow where the pipeline output controls the encoder.
 	 */
 	if (dssdev->type != OMAP_DISPLAY_TYPE_DSI) {
-		dssdev->ops->disable(dssdev);
+		if (dssdev->ops && dssdev->ops->disable)
+			dssdev->ops->disable(dssdev);
 		dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 	}
 
@@ -194,7 +195,8 @@ static void omap_encoder_enable(struct drm_encoder *encoder)
 	 * flow where the pipeline output controls the encoder.
 	 */
 	if (dssdev->type != OMAP_DISPLAY_TYPE_DSI) {
-		dssdev->ops->enable(dssdev);
+		if (dssdev->ops && dssdev->ops->enable)
+			dssdev->ops->enable(dssdev);
 		dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
 	}
 
-- 
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] 106+ messages in thread

* [PATCH v2 24/50] drm/omap: hdmi: Allocate EDID in the .read_edid() operation
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (22 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 23/50] drm/omap: dss: Make omap_dss_device_ops optional Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-20  1:16 ` [PATCH v2 25/50] drm/omap: hdmi4: Rework EDID read to isolate data read Laurent Pinchart
                   ` (26 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Bring the omapdss-specific .read_edid() operation in sync with the
drm_bridge .get_edid() operation to ease code reuse.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
Changes since v1:

- Keep MAX_EDID macro
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c      | 36 ++++++++++++++++--------
 drivers/gpu/drm/omapdrm/dss/hdmi5.c      | 24 ++++++++++++----
 drivers/gpu/drm/omapdrm/dss/omapdss.h    |  2 +-
 drivers/gpu/drm/omapdrm/omap_connector.c | 12 ++------
 4 files changed, 47 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index dd4a14fe7e59..e15fa3862922 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -405,31 +405,45 @@ static void hdmi_disconnect(struct omap_dss_device *src,
 	omapdss_device_disconnect(dst, dst->next);
 }
 
-static int hdmi_read_edid(struct omap_dss_device *dssdev,
-		u8 *edid, int len)
+#define MAX_EDID	512
+
+static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
 {
 	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
 	bool need_enable;
+	u8 *edid;
 	int r;
 
+	edid = kzalloc(MAX_EDID, GFP_KERNEL);
+	if (!edid)
+		return NULL;
+
 	need_enable = hdmi->core_enabled == false;
 
 	if (need_enable) {
 		r = hdmi4_core_enable(&hdmi->core);
-		if (r)
-			return r;
+		if (r) {
+			kfree(edid);
+			return NULL;
+		}
+	}
+
+	r = read_edid(hdmi, edid, MAX_EDID);
+	if (r < 0) {
+		kfree(edid);
+		edid = NULL;
+	} else {
+		unsigned int cec_addr;
+
+		cec_addr = r >= 256 ? cec_get_edid_phys_addr(edid, r, NULL)
+			 : CEC_PHYS_ADDR_INVALID;
+		hdmi4_cec_set_phys_addr(&hdmi->core, cec_addr);
 	}
 
-	r = read_edid(hdmi, edid, len);
-	if (r >= 256)
-		hdmi4_cec_set_phys_addr(&hdmi->core,
-					cec_get_edid_phys_addr(edid, r, NULL));
-	else
-		hdmi4_cec_set_phys_addr(&hdmi->core, CEC_PHYS_ADDR_INVALID);
 	if (need_enable)
 		hdmi4_core_disable(&hdmi->core);
 
-	return r;
+	return (struct edid *)edid;
 }
 
 static void hdmi_lost_hotplug(struct omap_dss_device *dssdev)
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 8e3790dd8b98..99720dfc5769 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -410,27 +410,39 @@ static void hdmi_disconnect(struct omap_dss_device *src,
 	omapdss_device_disconnect(dst, dst->next);
 }
 
-static int hdmi_read_edid(struct omap_dss_device *dssdev,
-		u8 *edid, int len)
+#define MAX_EDID	512
+
+static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
 {
 	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
 	bool need_enable;
+	u8 *edid;
 	int r;
 
+	edid = kzalloc(MAX_EDID, GFP_KERNEL);
+	if (!edid)
+		return NULL;
+
 	need_enable = hdmi->core_enabled == false;
 
 	if (need_enable) {
 		r = hdmi_core_enable(hdmi);
-		if (r)
-			return r;
+		if (r) {
+			kfree(edid);
+			return NULL;
+		}
 	}
 
-	r = read_edid(hdmi, edid, len);
+	r = read_edid(hdmi, edid, MAX_EDID);
+	if (r < 0) {
+		kfree(edid);
+		edid = NULL;
+	}
 
 	if (need_enable)
 		hdmi_core_disable(hdmi);
 
-	return r;
+	return (struct edid *)edid;
 }
 
 static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 82e9bfa5530a..269e143d57be 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -367,7 +367,7 @@ struct omap_dss_device_ops {
 				void *cb_data);
 	void (*unregister_hpd_cb)(struct omap_dss_device *dssdev);
 
-	int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
+	struct edid *(*read_edid)(struct omap_dss_device *dssdev);
 
 	int (*get_modes)(struct omap_dss_device *dssdev,
 			 struct drm_connector *connector);
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
index a24cec4b0bb9..c636ae228130 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -153,25 +153,19 @@ static void omap_connector_destroy(struct drm_connector *connector)
 	kfree(omap_connector);
 }
 
-#define MAX_EDID  512
-
 static int omap_connector_get_modes_edid(struct drm_connector *connector,
 					 struct omap_dss_device *dssdev)
 {
 	enum drm_connector_status status;
-	void *edid;
+	struct edid *edid;
 	int n;
 
 	status = omap_connector_detect(connector, false);
 	if (status != connector_status_connected)
 		goto no_edid;
 
-	edid = kzalloc(MAX_EDID, GFP_KERNEL);
-	if (!edid)
-		goto no_edid;
-
-	if (dssdev->ops->read_edid(dssdev, edid, MAX_EDID) <= 0 ||
-	    !drm_edid_is_valid(edid)) {
+	edid = dssdev->ops->read_edid(dssdev);
+	if (!edid || !drm_edid_is_valid(edid)) {
 		kfree(edid);
 		goto no_edid;
 	}
-- 
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] 106+ messages in thread

* [PATCH v2 25/50] drm/omap: hdmi4: Rework EDID read to isolate data read
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (23 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 24/50] drm/omap: hdmi: Allocate EDID in the .read_edid() operation Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-26 11:39   ` Tomi Valkeinen
  2019-08-20  1:16 ` [PATCH v2 26/50] drm/omap: hdmi5: " Laurent Pinchart
                   ` (25 subsequent siblings)
  50 siblings, 1 reply; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

In preparation of adding DRM bridge support to the hdmi4 encoder code,
rework the EDID read to isolate data read.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c      | 94 +++++++++++++++---------
 drivers/gpu/drm/omapdrm/dss/hdmi4_core.c | 59 +++------------
 drivers/gpu/drm/omapdrm/dss/hdmi4_core.h |  4 +-
 3 files changed, 73 insertions(+), 84 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index e15fa3862922..37536b9f3114 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -272,23 +272,6 @@ static int hdmi_dump_regs(struct seq_file *s, void *p)
 	return 0;
 }
 
-static int read_edid(struct omap_hdmi *hdmi, u8 *buf, int len)
-{
-	int r;
-
-	mutex_lock(&hdmi->lock);
-
-	r = hdmi_runtime_get(hdmi);
-	BUG_ON(r);
-
-	r = hdmi4_read_edid(&hdmi->core,  buf, len);
-
-	hdmi_runtime_put(hdmi);
-	mutex_unlock(&hdmi->lock);
-
-	return r;
-}
-
 static void hdmi_start_audio_stream(struct omap_hdmi *hd)
 {
 	hdmi_wp_audio_enable(&hd->wp, true);
@@ -407,10 +390,8 @@ static void hdmi_disconnect(struct omap_dss_device *src,
 
 #define MAX_EDID	512
 
-static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi)
 {
-	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-	bool need_enable;
 	u8 *edid;
 	int r;
 
@@ -418,32 +399,79 @@ static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
 	if (!edid)
 		return NULL;
 
+	r = hdmi4_core_ddc_read(&hdmi->core, edid, 0, EDID_LENGTH);
+	if (r)
+		goto error;
+
+	if (edid[0x7e] > 0) {
+		char checksum = 0;
+		unsigned int i;
+
+		r = hdmi4_core_ddc_read(&hdmi->core, edid + EDID_LENGTH, 1,
+					EDID_LENGTH);
+		if (r)
+			goto error;
+
+		for (i = 0; i < EDID_LENGTH; ++i)
+			checksum += edid[EDID_LENGTH + i];
+
+		if (checksum != 0) {
+			DSSERR("E-EDID checksum failed!!\n");
+			goto error;
+		}
+	}
+
+	return (struct edid *)edid;
+
+error:
+	kfree(edid);
+	return NULL;
+}
+
+static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+{
+	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
+	struct edid *edid = NULL;
+	unsigned int cec_addr;
+	bool need_enable;
+	int r;
+
 	need_enable = hdmi->core_enabled == false;
 
 	if (need_enable) {
 		r = hdmi4_core_enable(&hdmi->core);
-		if (r) {
-			kfree(edid);
+		if (r)
 			return NULL;
-		}
 	}
 
-	r = read_edid(hdmi, edid, MAX_EDID);
-	if (r < 0) {
-		kfree(edid);
-		edid = NULL;
+	mutex_lock(&hdmi->lock);
+	r = hdmi_runtime_get(hdmi);
+	BUG_ON(r);
+
+	r = hdmi4_core_ddc_init(&hdmi->core);
+	if (r)
+		goto done;
+
+	edid = hdmi_read_edid_data(hdmi);
+
+done:
+	hdmi_runtime_put(hdmi);
+	mutex_unlock(&hdmi->lock);
+
+	if (edid && edid->extensions) {
+		unsigned int len = (edid->extensions + 1) * EDID_LENGTH;
+
+		cec_addr = cec_get_edid_phys_addr((u8 *)edid, len, NULL);
 	} else {
-		unsigned int cec_addr;
-
-		cec_addr = r >= 256 ? cec_get_edid_phys_addr(edid, r, NULL)
-			 : CEC_PHYS_ADDR_INVALID;
-		hdmi4_cec_set_phys_addr(&hdmi->core, cec_addr);
+		cec_addr = CEC_PHYS_ADDR_INVALID;
 	}
 
+	hdmi4_cec_set_phys_addr(&hdmi->core, cec_addr);
+
 	if (need_enable)
 		hdmi4_core_disable(&hdmi->core);
 
-	return (struct edid *)edid;
+	return edid;
 }
 
 static void hdmi_lost_hotplug(struct omap_dss_device *dssdev)
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c
index 5d5d5588ebc1..62175e85f0ef 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c
@@ -32,7 +32,7 @@ static inline void __iomem *hdmi_av_base(struct hdmi_core_data *core)
 	return core->base + HDMI_CORE_AV;
 }
 
-static int hdmi_core_ddc_init(struct hdmi_core_data *core)
+int hdmi4_core_ddc_init(struct hdmi_core_data *core)
 {
 	void __iomem *base = core->base;
 
@@ -74,13 +74,11 @@ static int hdmi_core_ddc_init(struct hdmi_core_data *core)
 	return 0;
 }
 
-static int hdmi_core_ddc_edid(struct hdmi_core_data *core,
-		u8 *pedid, int ext)
+int hdmi4_core_ddc_read(void *data, u8 *buf, unsigned int block, size_t len)
 {
+	struct hdmi_core_data *core = data;
 	void __iomem *base = core->base;
 	u32 i;
-	char checksum;
-	u32 offset = 0;
 
 	/* HDMI_CORE_DDC_STATUS_IN_PROG */
 	if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
@@ -89,24 +87,21 @@ static int hdmi_core_ddc_edid(struct hdmi_core_data *core,
 		return -ETIMEDOUT;
 	}
 
-	if (ext % 2 != 0)
-		offset = 0x80;
-
 	/* Load Segment Address Register */
-	REG_FLD_MOD(base, HDMI_CORE_DDC_SEGM, ext / 2, 7, 0);
+	REG_FLD_MOD(base, HDMI_CORE_DDC_SEGM, block / 2, 7, 0);
 
 	/* Load Slave Address Register */
 	REG_FLD_MOD(base, HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1);
 
 	/* Load Offset Address Register */
-	REG_FLD_MOD(base, HDMI_CORE_DDC_OFFSET, offset, 7, 0);
+	REG_FLD_MOD(base, HDMI_CORE_DDC_OFFSET, block % 2 ? 0x80 : 0, 7, 0);
 
 	/* Load Byte Count */
-	REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT1, 0x80, 7, 0);
+	REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT1, len, 7, 0);
 	REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT2, 0x0, 1, 0);
 
 	/* Set DDC_CMD */
-	if (ext)
+	if (block)
 		REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x4, 3, 0);
 	else
 		REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x2, 3, 0);
@@ -122,7 +117,7 @@ static int hdmi_core_ddc_edid(struct hdmi_core_data *core,
 		return -EIO;
 	}
 
-	for (i = 0; i < 0x80; ++i) {
+	for (i = 0; i < len; ++i) {
 		int t;
 
 		/* IN_PROG */
@@ -141,48 +136,12 @@ static int hdmi_core_ddc_edid(struct hdmi_core_data *core,
 			udelay(1);
 		}
 
-		pedid[i] = REG_GET(base, HDMI_CORE_DDC_DATA, 7, 0);
-	}
-
-	checksum = 0;
-	for (i = 0; i < 0x80; ++i)
-		checksum += pedid[i];
-
-	if (checksum != 0) {
-		DSSERR("E-EDID checksum failed!!\n");
-		return -EIO;
+		buf[i] = REG_GET(base, HDMI_CORE_DDC_DATA, 7, 0);
 	}
 
 	return 0;
 }
 
-int hdmi4_read_edid(struct hdmi_core_data *core, u8 *edid, int len)
-{
-	int r, l;
-
-	if (len < 128)
-		return -EINVAL;
-
-	r = hdmi_core_ddc_init(core);
-	if (r)
-		return r;
-
-	r = hdmi_core_ddc_edid(core, edid, 0);
-	if (r)
-		return r;
-
-	l = 128;
-
-	if (len >= 128 * 2 && edid[0x7e] > 0) {
-		r = hdmi_core_ddc_edid(core, edid + 0x80, 1);
-		if (r)
-			return r;
-		l += 128;
-	}
-
-	return l;
-}
-
 static void hdmi_core_init(struct hdmi_core_video_config *video_cfg)
 {
 	DSSDBG("Enter hdmi_core_init\n");
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.h b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.h
index 11c4b7ba1eee..dc64ae2aa300 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.h
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.h
@@ -249,7 +249,9 @@ struct hdmi_core_packet_enable_repeat {
 	u32	generic_pkt_repeat;
 };
 
-int hdmi4_read_edid(struct hdmi_core_data *core, u8 *edid, int len);
+int hdmi4_core_ddc_init(struct hdmi_core_data *core);
+int hdmi4_core_ddc_read(void *data, u8 *buf, unsigned int block, size_t len);
+
 void hdmi4_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
 		struct hdmi_config *cfg);
 void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s);
-- 
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] 106+ messages in thread

* [PATCH v2 26/50] drm/omap: hdmi5: Rework EDID read to isolate data read
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (24 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 25/50] drm/omap: hdmi4: Rework EDID read to isolate data read Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-20  1:16 ` [PATCH v2 27/50] drm/omap: hdmi4: Register a drm_bridge for EDID read Laurent Pinchart
                   ` (24 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

In preparation of adding DRM bridge support to the hdmi5 encoder code,
rework the EDID read to isolate data read.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/hdmi5.c      | 89 ++++++++++++++----------
 drivers/gpu/drm/omapdrm/dss/hdmi5_core.c | 48 +++----------
 drivers/gpu/drm/omapdrm/dss/hdmi5_core.h |  5 +-
 3 files changed, 65 insertions(+), 77 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 99720dfc5769..2b02b0a11696 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -271,30 +271,6 @@ static int hdmi_dump_regs(struct seq_file *s, void *p)
 	return 0;
 }
 
-static int read_edid(struct omap_hdmi *hdmi, u8 *buf, int len)
-{
-	int r;
-	int idlemode;
-
-	mutex_lock(&hdmi->lock);
-
-	r = hdmi_runtime_get(hdmi);
-	BUG_ON(r);
-
-	idlemode = REG_GET(hdmi->wp.base, HDMI_WP_SYSCONFIG, 3, 2);
-	/* No-idle mode */
-	REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
-
-	r = hdmi5_read_edid(&hdmi->core,  buf, len);
-
-	REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, idlemode, 3, 2);
-
-	hdmi_runtime_put(hdmi);
-	mutex_unlock(&hdmi->lock);
-
-	return r;
-}
-
 static void hdmi_start_audio_stream(struct omap_hdmi *hd)
 {
 	REG_FLD_MOD(hd->wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
@@ -412,32 +388,73 @@ static void hdmi_disconnect(struct omap_dss_device *src,
 
 #define MAX_EDID	512
 
-static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+static struct edid *hdmi_read_edid_data(struct hdmi_core_data *core)
 {
-	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-	bool need_enable;
+	int max_ext_blocks = 3;
+	int r, n, i;
 	u8 *edid;
-	int r;
 
 	edid = kzalloc(MAX_EDID, GFP_KERNEL);
 	if (!edid)
 		return NULL;
 
+	r = hdmi5_core_ddc_read(core, edid, 0, EDID_LENGTH);
+	if (r)
+		goto error;
+
+	n = edid[0x7e];
+
+	if (n > max_ext_blocks)
+		n = max_ext_blocks;
+
+	for (i = 1; i <= n; i++) {
+		r = hdmi5_core_ddc_read(core, edid + i * EDID_LENGTH, i,
+					EDID_LENGTH);
+		if (r)
+			goto error;
+	}
+
+	return (struct edid *)edid;
+
+error:
+	kfree(edid);
+	return NULL;
+}
+
+static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+{
+	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
+	struct edid *edid;
+	bool need_enable;
+	int idlemode;
+	int r;
+
 	need_enable = hdmi->core_enabled == false;
 
 	if (need_enable) {
 		r = hdmi_core_enable(hdmi);
-		if (r) {
-			kfree(edid);
+		if (r)
 			return NULL;
-		}
 	}
 
-	r = read_edid(hdmi, edid, MAX_EDID);
-	if (r < 0) {
-		kfree(edid);
-		edid = NULL;
-	}
+	mutex_lock(&hdmi->lock);
+	r = hdmi_runtime_get(hdmi);
+	BUG_ON(r);
+
+	idlemode = REG_GET(hdmi->wp.base, HDMI_WP_SYSCONFIG, 3, 2);
+	/* No-idle mode */
+	REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
+
+	hdmi5_core_ddc_init(&hdmi->core);
+
+	edid = hdmi_read_edid_data(&hdmi->core);
+
+	hdmi5_core_ddc_uninit(&hdmi->core);
+
+	REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, idlemode, 3, 2);
+
+	hdmi_runtime_put(hdmi);
+	mutex_unlock(&hdmi->lock);
 
 	if (need_enable)
 		hdmi_core_disable(hdmi);
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
index 7400fb99d453..95c02892d268 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
@@ -35,7 +35,7 @@ static const struct csc_table csc_table_deepcolor[] = {
 	[3] = { 8192, 0, 0, 0, 0, 8192, 0, 0, 0, 0, 8192, 0, },
 };
 
-static void hdmi_core_ddc_init(struct hdmi_core_data *core)
+void hdmi5_core_ddc_init(struct hdmi_core_data *core)
 {
 	void __iomem *base = core->base;
 	const unsigned long long iclk = 266000000;	/* DSS L3 ICLK */
@@ -114,7 +114,7 @@ static void hdmi_core_ddc_init(struct hdmi_core_data *core)
 	REG_FLD_MOD(base, HDMI_CORE_I2CM_INT, 0x0, 2, 2);
 }
 
-static void hdmi_core_ddc_uninit(struct hdmi_core_data *core)
+void hdmi5_core_ddc_uninit(struct hdmi_core_data *core)
 {
 	void __iomem *base = core->base;
 
@@ -124,14 +124,14 @@ static void hdmi_core_ddc_uninit(struct hdmi_core_data *core)
 	REG_FLD_MOD(base, HDMI_CORE_I2CM_INT, 0x1, 2, 2);
 }
 
-static int hdmi_core_ddc_edid(struct hdmi_core_data *core, u8 *pedid, u8 ext)
+int hdmi5_core_ddc_read(void *data, u8 *buf, unsigned int block, size_t len)
 {
+	struct hdmi_core_data *core = data;
 	void __iomem *base = core->base;
 	u8 cur_addr;
-	char checksum = 0;
 	const int retries = 1000;
-	u8 seg_ptr = ext / 2;
-	u8 edidbase = ((ext % 2) * 0x80);
+	u8 seg_ptr = block / 2;
+	u8 edidbase = ((block % 2) * EDID_LENGTH);
 
 	REG_FLD_MOD(base, HDMI_CORE_I2CM_SEGPTR, seg_ptr, 7, 0);
 
@@ -139,7 +139,7 @@ static int hdmi_core_ddc_edid(struct hdmi_core_data *core, u8 *pedid, u8 ext)
 	 * TODO: We use polling here, although we probably should use proper
 	 * interrupts.
 	 */
-	for (cur_addr = 0; cur_addr < 128; ++cur_addr) {
+	for (cur_addr = 0; cur_addr < len; ++cur_addr) {
 		int i;
 
 		/* clear ERROR and DONE */
@@ -176,45 +176,13 @@ static int hdmi_core_ddc_edid(struct hdmi_core_data *core, u8 *pedid, u8 ext)
 			return -EIO;
 		}
 
-		pedid[cur_addr] = REG_GET(base, HDMI_CORE_I2CM_DATAI, 7, 0);
-		checksum += pedid[cur_addr];
+		buf[cur_addr] = REG_GET(base, HDMI_CORE_I2CM_DATAI, 7, 0);
 	}
 
 	return 0;
 
 }
 
-int hdmi5_read_edid(struct hdmi_core_data *core, u8 *edid, int len)
-{
-	int r, n, i;
-	int max_ext_blocks = (len / 128) - 1;
-
-	if (len < 128)
-		return -EINVAL;
-
-	hdmi_core_ddc_init(core);
-
-	r = hdmi_core_ddc_edid(core, edid, 0);
-	if (r)
-		goto out;
-
-	n = edid[0x7e];
-
-	if (n > max_ext_blocks)
-		n = max_ext_blocks;
-
-	for (i = 1; i <= n; i++) {
-		r = hdmi_core_ddc_edid(core, edid + i * EDID_LENGTH, i);
-		if (r)
-			goto out;
-	}
-
-out:
-	hdmi_core_ddc_uninit(core);
-
-	return r ? r : len;
-}
-
 void hdmi5_core_dump(struct hdmi_core_data *core, struct seq_file *s)
 {
 
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.h b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.h
index f10b8a283011..65eadefdb3f9 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5_core.h
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5_core.h
@@ -281,7 +281,10 @@ struct csc_table {
 	u16 c1, c2, c3, c4;
 };
 
-int hdmi5_read_edid(struct hdmi_core_data *core, u8 *edid, int len);
+void hdmi5_core_ddc_init(struct hdmi_core_data *core);
+int hdmi5_core_ddc_read(void *data, u8 *buf, unsigned int block, size_t len);
+void hdmi5_core_ddc_uninit(struct hdmi_core_data *core);
+
 void hdmi5_core_dump(struct hdmi_core_data *core, struct seq_file *s);
 int hdmi5_core_handle_irqs(struct hdmi_core_data *core);
 void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
-- 
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] 106+ messages in thread

* [PATCH v2 27/50] drm/omap: hdmi4: Register a drm_bridge for EDID read
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (25 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 26/50] drm/omap: hdmi5: " Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-20  1:16 ` [PATCH v2 28/50] drm/omap: hdmi5: " Laurent Pinchart
                   ` (23 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

In order to integrate with a chain of drm_bridge, the internal HDMI4
encoder has to expose the EDID read operation through the drm_bridge
API. Register a bridge at initialisation time to do so.

For the time being make the next bridge in the chain optional as the
HDMI output is still based on omap_dss_device. The create_connector
argument to the bridge attach function is also ignored for the same
reason. This will be changed later when removing the related
omapdrm-specific display drivers.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/hdmi.h  |  3 ++
 drivers/gpu/drm/omapdrm/dss/hdmi4.c | 74 +++++++++++++++++++++++++++--
 2 files changed, 72 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi.h b/drivers/gpu/drm/omapdrm/dss/hdmi.h
index c867552c925c..bd43f6abf27b 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi.h
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi.h
@@ -14,6 +14,7 @@
 #include <linux/hdmi.h>
 #include <sound/omap-hdmi-audio.h>
 #include <media/cec.h>
+#include <drm/drm_bridge.h>
 
 #include "omapdss.h"
 #include "dss.h"
@@ -364,6 +365,7 @@ struct omap_hdmi {
 	bool core_enabled;
 
 	struct omap_dss_device output;
+	struct drm_bridge bridge;
 
 	struct platform_device *audio_pdev;
 	void (*audio_abort_cb)(struct device *dev);
@@ -379,5 +381,6 @@ struct omap_hdmi {
 };
 
 #define dssdev_to_hdmi(dssdev) container_of(dssdev, struct omap_hdmi, output)
+#define drm_bridge_to_hdmi(b) container_of(b, struct omap_hdmi, bridge)
 
 #endif
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 37536b9f3114..8b6fcd724d66 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -390,7 +390,8 @@ static void hdmi_disconnect(struct omap_dss_device *src,
 
 #define MAX_EDID	512
 
-static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi)
+static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi,
+					struct drm_connector *connector)
 {
 	u8 *edid;
 	int r;
@@ -428,9 +429,12 @@ static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi)
 	return NULL;
 }
 
-static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+static struct edid *
+hdmi_do_read_edid(struct omap_hdmi *hdmi,
+		  struct edid *(*read)(struct omap_hdmi *hdmi,
+				       struct drm_connector *connector),
+		  struct drm_connector *connector)
 {
-	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
 	struct edid *edid = NULL;
 	unsigned int cec_addr;
 	bool need_enable;
@@ -452,7 +456,7 @@ static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
 	if (r)
 		goto done;
 
-	edid = hdmi_read_edid_data(hdmi);
+	edid = read(hdmi, connector);
 
 done:
 	hdmi_runtime_put(hdmi);
@@ -474,6 +478,12 @@ static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
 	return edid;
 }
 
+static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+{
+	return hdmi_do_read_edid(dssdev_to_hdmi(dssdev), hdmi_read_edid_data,
+				 NULL);
+}
+
 static void hdmi_lost_hotplug(struct omap_dss_device *dssdev)
 {
 	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
@@ -517,6 +527,56 @@ static const struct omap_dss_device_ops hdmi_ops = {
 	},
 };
 
+/* -----------------------------------------------------------------------------
+ * DRM Bridge Operations
+ */
+
+static int hdmi4_bridge_attach(struct drm_bridge *bridge,
+			       enum drm_bridge_attach_flags flags)
+{
+	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+	if (!hdmi->output.next_bridge)
+		return 0;
+
+	return drm_bridge_attach(bridge->encoder, hdmi->output.next_bridge,
+				 bridge, flags);
+}
+
+static struct edid *hdmi4_bridge_read_edid(struct omap_hdmi *hdmi,
+					   struct drm_connector *connector)
+{
+	return drm_do_get_edid(connector, hdmi4_core_ddc_read, &hdmi->core);
+}
+
+static struct edid *hdmi4_bridge_get_edid(struct drm_bridge *bridge,
+					  struct drm_connector *connector)
+{
+	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+	return hdmi_do_read_edid(hdmi, hdmi4_bridge_read_edid, connector);
+}
+
+static const struct drm_bridge_funcs hdmi4_bridge_funcs = {
+	.attach = hdmi4_bridge_attach,
+	.get_edid = hdmi4_bridge_get_edid,
+};
+
+static void hdmi4_bridge_init(struct omap_hdmi *hdmi)
+{
+	hdmi->bridge.funcs = &hdmi4_bridge_funcs;
+	hdmi->bridge.of_node = hdmi->pdev->dev.of_node;
+	hdmi->bridge.ops = DRM_BRIDGE_OP_EDID;
+	hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
+
+	drm_bridge_add(&hdmi->bridge);
+}
+
+static void hdmi4_bridge_cleanup(struct omap_hdmi *hdmi)
+{
+	drm_bridge_remove(&hdmi->bridge);
+}
+
 /* -----------------------------------------------------------------------------
  * Audio Callbacks
  */
@@ -708,6 +768,8 @@ static int hdmi4_init_output(struct omap_hdmi *hdmi)
 	struct omap_dss_device *out = &hdmi->output;
 	int r;
 
+	hdmi4_bridge_init(hdmi);
+
 	out->dev = &hdmi->pdev->dev;
 	out->id = OMAP_DSS_OUTPUT_HDMI;
 	out->type = OMAP_DISPLAY_TYPE_HDMI;
@@ -718,7 +780,7 @@ static int hdmi4_init_output(struct omap_hdmi *hdmi)
 	out->of_port = 0;
 	out->ops_flags = OMAP_DSS_DEVICE_OP_EDID;
 
-	r = omapdss_device_init_output(out, NULL);
+	r = omapdss_device_init_output(out, &hdmi->bridge);
 	if (r < 0)
 		return r;
 
@@ -733,6 +795,8 @@ static void hdmi4_uninit_output(struct omap_hdmi *hdmi)
 
 	omapdss_device_unregister(out);
 	omapdss_device_cleanup_output(out);
+
+	hdmi4_bridge_cleanup(hdmi);
 }
 
 static int hdmi4_probe_of(struct omap_hdmi *hdmi)
-- 
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] 106+ messages in thread

* [PATCH v2 28/50] drm/omap: hdmi5: Register a drm_bridge for EDID read
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (26 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 27/50] drm/omap: hdmi4: Register a drm_bridge for EDID read Laurent Pinchart
@ 2019-08-20  1:16 ` Laurent Pinchart
  2019-08-20  1:17 ` [PATCH v2 29/50] drm/omap: hdmi4: Move mode set, enable and disable operations to bridge Laurent Pinchart
                   ` (22 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:16 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

In order to integrate with a chain of drm_bridge, the internal HDMI5
encoder has to expose the EDID read operation through the drm_bridge
API. Register a bridge at initialisation time to do so.

For the time being make the next bridge in the chain optional as the
HDMI output is still based on omap_dss_device. The create_connector
argument to the bridge attach function is also ignored for the same
reason. This will be changed later when removing the related
omapdrm-specific display drivers.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/hdmi5.c | 75 +++++++++++++++++++++++++++--
 1 file changed, 70 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 2b02b0a11696..a895ed159981 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -388,8 +388,10 @@ static void hdmi_disconnect(struct omap_dss_device *src,
 
 #define MAX_EDID	512
 
-static struct edid *hdmi_read_edid_data(struct hdmi_core_data *core)
+static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi,
+					struct drm_connector *connector)
 {
+	struct hdmi_core_data *core = &hdmi->core;
 	int max_ext_blocks = 3;
 	int r, n, i;
 	u8 *edid;
@@ -421,9 +423,12 @@ static struct edid *hdmi_read_edid_data(struct hdmi_core_data *core)
 	return NULL;
 }
 
-static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+static struct edid *
+hdmi_do_read_edid(struct omap_hdmi *hdmi,
+		  struct edid *(*read)(struct omap_hdmi *hdmi,
+				       struct drm_connector *connector),
+		  struct drm_connector *connector)
 {
-	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
 	struct edid *edid;
 	bool need_enable;
 	int idlemode;
@@ -447,7 +452,7 @@ static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
 
 	hdmi5_core_ddc_init(&hdmi->core);
 
-	edid = hdmi_read_edid_data(&hdmi->core);
+	edid = read(hdmi, connector);
 
 	hdmi5_core_ddc_uninit(&hdmi->core);
 
@@ -462,6 +467,12 @@ static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
 	return (struct edid *)edid;
 }
 
+static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
+{
+	return hdmi_do_read_edid(dssdev_to_hdmi(dssdev), hdmi_read_edid_data,
+				 NULL);
+}
+
 static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
 		const struct hdmi_avi_infoframe *avi)
 {
@@ -497,6 +508,56 @@ static const struct omap_dss_device_ops hdmi_ops = {
 	},
 };
 
+/* -----------------------------------------------------------------------------
+ * DRM Bridge Operations
+ */
+
+static int hdmi5_bridge_attach(struct drm_bridge *bridge,
+			       enum drm_bridge_attach_flags flags)
+{
+	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+	if (!hdmi->output.next_bridge)
+		return 0;
+
+	return drm_bridge_attach(bridge->encoder, hdmi->output.next_bridge,
+				 bridge, flags);
+}
+
+static struct edid *hdmi5_bridge_read_edid(struct omap_hdmi *hdmi,
+					   struct drm_connector *connector)
+{
+	return drm_do_get_edid(connector, hdmi5_core_ddc_read, &hdmi->core);
+}
+
+static struct edid *hdmi5_bridge_get_edid(struct drm_bridge *bridge,
+					  struct drm_connector *connector)
+{
+	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+	return hdmi_do_read_edid(hdmi, hdmi5_bridge_read_edid, connector);
+}
+
+static const struct drm_bridge_funcs hdmi5_bridge_funcs = {
+	.attach = hdmi5_bridge_attach,
+	.get_edid = hdmi5_bridge_get_edid,
+};
+
+static void hdmi5_bridge_init(struct omap_hdmi *hdmi)
+{
+	hdmi->bridge.funcs = &hdmi5_bridge_funcs;
+	hdmi->bridge.of_node = hdmi->pdev->dev.of_node;
+	hdmi->bridge.ops = DRM_BRIDGE_OP_EDID;
+	hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
+
+	drm_bridge_add(&hdmi->bridge);
+}
+
+static void hdmi5_bridge_cleanup(struct omap_hdmi *hdmi)
+{
+	drm_bridge_remove(&hdmi->bridge);
+}
+
 /* -----------------------------------------------------------------------------
  * Audio Callbacks
  */
@@ -679,6 +740,8 @@ static int hdmi5_init_output(struct omap_hdmi *hdmi)
 	struct omap_dss_device *out = &hdmi->output;
 	int r;
 
+	hdmi5_bridge_init(hdmi);
+
 	out->dev = &hdmi->pdev->dev;
 	out->id = OMAP_DSS_OUTPUT_HDMI;
 	out->type = OMAP_DISPLAY_TYPE_HDMI;
@@ -689,7 +752,7 @@ static int hdmi5_init_output(struct omap_hdmi *hdmi)
 	out->of_port = 0;
 	out->ops_flags = OMAP_DSS_DEVICE_OP_EDID;
 
-	r = omapdss_device_init_output(out, NULL);
+	r = omapdss_device_init_output(out, &hdmi->bridge);
 	if (r < 0)
 		return r;
 
@@ -704,6 +767,8 @@ static void hdmi5_uninit_output(struct omap_hdmi *hdmi)
 
 	omapdss_device_unregister(out);
 	omapdss_device_cleanup_output(out);
+
+	hdmi5_bridge_cleanup(hdmi);
 }
 
 static int hdmi5_probe_of(struct omap_hdmi *hdmi)
-- 
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] 106+ messages in thread

* [PATCH v2 29/50] drm/omap: hdmi4: Move mode set, enable and disable operations to bridge
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (27 preceding siblings ...)
  2019-08-20  1:16 ` [PATCH v2 28/50] drm/omap: hdmi5: " Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-26 11:50   ` Tomi Valkeinen
  2019-08-20  1:17 ` [PATCH v2 30/50] drm/omap: hdmi5: " Laurent Pinchart
                   ` (21 subsequent siblings)
  50 siblings, 1 reply; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Move the omap_dss_device .set_timings(), .enable() and .disable()
operations to the drm_bridge functions. As the drm_bridge for the HDMI
encoder is unconditionally registered and attached, those operations
will be called at the appropriate time.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c | 201 +++++++++++++++-------------
 1 file changed, 106 insertions(+), 95 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 8b6fcd724d66..2211a7a3dad3 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -28,6 +28,8 @@
 #include <sound/omap-hdmi-audio.h>
 #include <media/cec.h>
 
+#include <drm/drm_atomic.h>
+
 #include "omapdss.h"
 #include "hdmi4_core.h"
 #include "hdmi4_cec.h"
@@ -237,20 +239,6 @@ static void hdmi_power_off_full(struct omap_hdmi *hdmi)
 	hdmi_power_off_core(hdmi);
 }
 
-static void hdmi_display_set_timings(struct omap_dss_device *dssdev,
-				     const struct drm_display_mode *mode)
-{
-	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-	mutex_lock(&hdmi->lock);
-
-	drm_display_mode_to_videomode(mode, &hdmi->cfg.vm);
-
-	dispc_set_tv_pclk(hdmi->dss->dispc, mode->clock * 1000);
-
-	mutex_unlock(&hdmi->lock);
-}
-
 static int hdmi_dump_regs(struct seq_file *s, void *p)
 {
 	struct omap_hdmi *hdmi = s->private;
@@ -284,62 +272,6 @@ static void hdmi_stop_audio_stream(struct omap_hdmi *hd)
 	hdmi_wp_audio_enable(&hd->wp, false);
 }
 
-static void hdmi_display_enable(struct omap_dss_device *dssdev)
-{
-	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-	unsigned long flags;
-	int r;
-
-	DSSDBG("ENTER hdmi_display_enable\n");
-
-	mutex_lock(&hdmi->lock);
-
-	r = hdmi_power_on_full(hdmi);
-	if (r) {
-		DSSERR("failed to power on device\n");
-		goto done;
-	}
-
-	if (hdmi->audio_configured) {
-		r = hdmi4_audio_config(&hdmi->core, &hdmi->wp,
-				       &hdmi->audio_config,
-				       hdmi->cfg.vm.pixelclock);
-		if (r) {
-			DSSERR("Error restoring audio configuration: %d", r);
-			hdmi->audio_abort_cb(&hdmi->pdev->dev);
-			hdmi->audio_configured = false;
-		}
-	}
-
-	spin_lock_irqsave(&hdmi->audio_playing_lock, flags);
-	if (hdmi->audio_configured && hdmi->audio_playing)
-		hdmi_start_audio_stream(hdmi);
-	hdmi->display_enabled = true;
-	spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags);
-
-done:
-	mutex_unlock(&hdmi->lock);
-}
-
-static void hdmi_display_disable(struct omap_dss_device *dssdev)
-{
-	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-	unsigned long flags;
-
-	DSSDBG("Enter hdmi_display_disable\n");
-
-	mutex_lock(&hdmi->lock);
-
-	spin_lock_irqsave(&hdmi->audio_playing_lock, flags);
-	hdmi_stop_audio_stream(hdmi);
-	hdmi->display_enabled = false;
-	spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags);
-
-	hdmi_power_off_full(hdmi);
-
-	mutex_unlock(&hdmi->lock);
-}
-
 int hdmi4_core_enable(struct hdmi_core_data *core)
 {
 	struct omap_hdmi *hdmi = container_of(core, struct omap_hdmi, core);
@@ -491,39 +423,14 @@ static void hdmi_lost_hotplug(struct omap_dss_device *dssdev)
 	hdmi4_cec_set_phys_addr(&hdmi->core, CEC_PHYS_ADDR_INVALID);
 }
 
-static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
-		const struct hdmi_avi_infoframe *avi)
-{
-	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-	hdmi->cfg.infoframe = *avi;
-	return 0;
-}
-
-static int hdmi_set_hdmi_mode(struct omap_dss_device *dssdev,
-		bool hdmi_mode)
-{
-	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-	hdmi->cfg.hdmi_dvi_mode = hdmi_mode ? HDMI_HDMI : HDMI_DVI;
-	return 0;
-}
-
 static const struct omap_dss_device_ops hdmi_ops = {
 	.connect		= hdmi_connect,
 	.disconnect		= hdmi_disconnect,
 
-	.enable			= hdmi_display_enable,
-	.disable		= hdmi_display_disable,
-
-	.set_timings		= hdmi_display_set_timings,
-
 	.read_edid		= hdmi_read_edid,
 
 	.hdmi = {
 		.lost_hotplug		= hdmi_lost_hotplug,
-		.set_infoframe		= hdmi_set_infoframe,
-		.set_hdmi_mode		= hdmi_set_hdmi_mode,
 	},
 };
 
@@ -543,6 +450,107 @@ static int hdmi4_bridge_attach(struct drm_bridge *bridge,
 				 bridge, flags);
 }
 
+static void hdmi4_bridge_mode_set(struct drm_bridge *bridge,
+				  const struct drm_display_mode *mode,
+				  const struct drm_display_mode *adjusted_mode)
+{
+	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+	mutex_lock(&hdmi->lock);
+
+	drm_display_mode_to_videomode(adjusted_mode, &hdmi->cfg.vm);
+
+	dispc_set_tv_pclk(hdmi->dss->dispc, adjusted_mode->clock * 1000);
+
+	mutex_unlock(&hdmi->lock);
+}
+
+static void hdmi4_bridge_enable(struct drm_bridge *bridge,
+				struct drm_atomic_state *state)
+{
+	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+	struct drm_connector_state *conn_state;
+	struct drm_connector *connector;
+	struct drm_crtc_state *crtc_state;
+	unsigned long flags;
+	int ret;
+
+	/*
+	 * None of these should fail, as the bridge can't be enabled without a
+	 * valid CRTC to connector path with fully populated new states.
+	 */
+	connector = drm_atomic_get_new_connector_for_encoder(state,
+							     bridge->encoder);
+	if (WARN_ON(!connector))
+		return;
+	conn_state = drm_atomic_get_new_connector_state(state, connector);
+	if (WARN_ON(!conn_state))
+		return;
+	crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
+	if (WARN_ON(!crtc_state))
+		return;
+
+	hdmi->cfg.hdmi_dvi_mode = connector->display_info.is_hdmi
+				? HDMI_HDMI : HDMI_DVI;
+
+	if (connector->display_info.is_hdmi) {
+		const struct drm_display_mode *mode;
+		struct hdmi_avi_infoframe avi;
+
+		mode = &crtc_state->adjusted_mode;
+		ret = drm_hdmi_avi_infoframe_from_display_mode(&avi, connector,
+							       mode);
+		if (ret == 0)
+			hdmi->cfg.infoframe = avi;
+	}
+
+	mutex_lock(&hdmi->lock);
+
+	ret = hdmi_power_on_full(hdmi);
+	if (ret) {
+		DSSERR("failed to power on device\n");
+		goto done;
+	}
+
+	if (hdmi->audio_configured) {
+		ret = hdmi4_audio_config(&hdmi->core, &hdmi->wp,
+					 &hdmi->audio_config,
+					 hdmi->cfg.vm.pixelclock);
+		if (ret) {
+			DSSERR("Error restoring audio configuration: %d", ret);
+			hdmi->audio_abort_cb(&hdmi->pdev->dev);
+			hdmi->audio_configured = false;
+		}
+	}
+
+	spin_lock_irqsave(&hdmi->audio_playing_lock, flags);
+	if (hdmi->audio_configured && hdmi->audio_playing)
+		hdmi_start_audio_stream(hdmi);
+	hdmi->display_enabled = true;
+	spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags);
+
+done:
+	mutex_unlock(&hdmi->lock);
+}
+
+static void hdmi4_bridge_disable(struct drm_bridge *bridge,
+				 struct drm_atomic_state *state)
+{
+	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+	unsigned long flags;
+
+	mutex_lock(&hdmi->lock);
+
+	spin_lock_irqsave(&hdmi->audio_playing_lock, flags);
+	hdmi_stop_audio_stream(hdmi);
+	hdmi->display_enabled = false;
+	spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags);
+
+	hdmi_power_off_full(hdmi);
+
+	mutex_unlock(&hdmi->lock);
+}
+
 static struct edid *hdmi4_bridge_read_edid(struct omap_hdmi *hdmi,
 					   struct drm_connector *connector)
 {
@@ -559,6 +567,9 @@ static struct edid *hdmi4_bridge_get_edid(struct drm_bridge *bridge,
 
 static const struct drm_bridge_funcs hdmi4_bridge_funcs = {
 	.attach = hdmi4_bridge_attach,
+	.mode_set = hdmi4_bridge_mode_set,
+	.atomic_enable = hdmi4_bridge_enable,
+	.atomic_disable = hdmi4_bridge_disable,
 	.get_edid = hdmi4_bridge_get_edid,
 };
 
-- 
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] 106+ messages in thread

* [PATCH v2 30/50] drm/omap: hdmi5: Move mode set, enable and disable operations to bridge
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (28 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 29/50] drm/omap: hdmi4: Move mode set, enable and disable operations to bridge Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-20  1:17 ` [PATCH v2 31/50] drm/omap: hdmi4: Implement drm_bridge .hpd_notify() operation Laurent Pinchart
                   ` (20 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Move the omap_dss_device .set_timings(), .enable() and .disable()
operations to the drm_bridge functions. As the drm_bridge for the HDMI
encoder is unconditionally registered and attached, those operations
will be called at the appropriate time.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/hdmi5.c | 204 +++++++++++++++-------------
 1 file changed, 106 insertions(+), 98 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index a895ed159981..09be3f0dec81 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -31,6 +31,8 @@
 #include <linux/of_graph.h>
 #include <sound/omap-hdmi-audio.h>
 
+#include <drm/drm_atomic.h>
+
 #include "omapdss.h"
 #include "hdmi5_core.h"
 #include "dss.h"
@@ -236,20 +238,6 @@ static void hdmi_power_off_full(struct omap_hdmi *hdmi)
 	hdmi_power_off_core(hdmi);
 }
 
-static void hdmi_display_set_timings(struct omap_dss_device *dssdev,
-				     const struct drm_display_mode *mode)
-{
-	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-	mutex_lock(&hdmi->lock);
-
-	drm_display_mode_to_videomode(mode, &hdmi->cfg.vm);
-
-	dispc_set_tv_pclk(hdmi->dss->dispc, mode->clock * 1000);
-
-	mutex_unlock(&hdmi->lock);
-}
-
 static int hdmi_dump_regs(struct seq_file *s, void *p)
 {
 	struct omap_hdmi *hdmi = s->private;
@@ -285,62 +273,6 @@ static void hdmi_stop_audio_stream(struct omap_hdmi *hd)
 	REG_FLD_MOD(hd->wp.base, HDMI_WP_SYSCONFIG, hd->wp_idlemode, 3, 2);
 }
 
-static void hdmi_display_enable(struct omap_dss_device *dssdev)
-{
-	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-	unsigned long flags;
-	int r;
-
-	DSSDBG("ENTER hdmi_display_enable\n");
-
-	mutex_lock(&hdmi->lock);
-
-	r = hdmi_power_on_full(hdmi);
-	if (r) {
-		DSSERR("failed to power on device\n");
-		goto done;
-	}
-
-	if (hdmi->audio_configured) {
-		r = hdmi5_audio_config(&hdmi->core, &hdmi->wp,
-				       &hdmi->audio_config,
-				       hdmi->cfg.vm.pixelclock);
-		if (r) {
-			DSSERR("Error restoring audio configuration: %d", r);
-			hdmi->audio_abort_cb(&hdmi->pdev->dev);
-			hdmi->audio_configured = false;
-		}
-	}
-
-	spin_lock_irqsave(&hdmi->audio_playing_lock, flags);
-	if (hdmi->audio_configured && hdmi->audio_playing)
-		hdmi_start_audio_stream(hdmi);
-	hdmi->display_enabled = true;
-	spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags);
-
-done:
-	mutex_unlock(&hdmi->lock);
-}
-
-static void hdmi_display_disable(struct omap_dss_device *dssdev)
-{
-	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-	unsigned long flags;
-
-	DSSDBG("Enter hdmi_display_disable\n");
-
-	mutex_lock(&hdmi->lock);
-
-	spin_lock_irqsave(&hdmi->audio_playing_lock, flags);
-	hdmi_stop_audio_stream(hdmi);
-	hdmi->display_enabled = false;
-	spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags);
-
-	hdmi_power_off_full(hdmi);
-
-	mutex_unlock(&hdmi->lock);
-}
-
 static int hdmi_core_enable(struct omap_hdmi *hdmi)
 {
 	int r = 0;
@@ -473,39 +405,11 @@ static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
 				 NULL);
 }
 
-static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
-		const struct hdmi_avi_infoframe *avi)
-{
-	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-	hdmi->cfg.infoframe = *avi;
-	return 0;
-}
-
-static int hdmi_set_hdmi_mode(struct omap_dss_device *dssdev,
-		bool hdmi_mode)
-{
-	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-	hdmi->cfg.hdmi_dvi_mode = hdmi_mode ? HDMI_HDMI : HDMI_DVI;
-	return 0;
-}
-
 static const struct omap_dss_device_ops hdmi_ops = {
 	.connect		= hdmi_connect,
 	.disconnect		= hdmi_disconnect,
 
-	.enable			= hdmi_display_enable,
-	.disable		= hdmi_display_disable,
-
-	.set_timings		= hdmi_display_set_timings,
-
 	.read_edid		= hdmi_read_edid,
-
-	.hdmi = {
-		.set_infoframe		= hdmi_set_infoframe,
-		.set_hdmi_mode		= hdmi_set_hdmi_mode,
-	},
 };
 
 /* -----------------------------------------------------------------------------
@@ -524,6 +428,107 @@ static int hdmi5_bridge_attach(struct drm_bridge *bridge,
 				 bridge, flags);
 }
 
+static void hdmi5_bridge_mode_set(struct drm_bridge *bridge,
+				  const struct drm_display_mode *mode,
+				  const struct drm_display_mode *adjusted_mode)
+{
+	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+	mutex_lock(&hdmi->lock);
+
+	drm_display_mode_to_videomode(adjusted_mode, &hdmi->cfg.vm);
+
+	dispc_set_tv_pclk(hdmi->dss->dispc, adjusted_mode->clock * 1000);
+
+	mutex_unlock(&hdmi->lock);
+}
+
+static void hdmi5_bridge_enable(struct drm_bridge *bridge,
+				struct drm_atomic_state *state)
+{
+	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+	struct drm_connector_state *conn_state;
+	struct drm_connector *connector;
+	struct drm_crtc_state *crtc_state;
+	unsigned long flags;
+	int ret;
+
+	/*
+	 * None of these should fail, as the bridge can't be enabled without a
+	 * valid CRTC to connector path with fully populated new states.
+	 */
+	connector = drm_atomic_get_new_connector_for_encoder(state,
+							     bridge->encoder);
+	if (WARN_ON(!connector))
+		return;
+	conn_state = drm_atomic_get_new_connector_state(state, connector);
+	if (WARN_ON(!conn_state))
+		return;
+	crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
+	if (WARN_ON(!crtc_state))
+		return;
+
+	hdmi->cfg.hdmi_dvi_mode = connector->display_info.is_hdmi
+				? HDMI_HDMI : HDMI_DVI;
+
+	if (connector->display_info.is_hdmi) {
+		const struct drm_display_mode *mode;
+		struct hdmi_avi_infoframe avi;
+
+		mode = &crtc_state->adjusted_mode;
+		ret = drm_hdmi_avi_infoframe_from_display_mode(&avi, connector,
+							       mode);
+		if (ret == 0)
+			hdmi->cfg.infoframe = avi;
+	}
+
+	mutex_lock(&hdmi->lock);
+
+	ret = hdmi_power_on_full(hdmi);
+	if (ret) {
+		DSSERR("failed to power on device\n");
+		goto done;
+	}
+
+	if (hdmi->audio_configured) {
+		ret = hdmi5_audio_config(&hdmi->core, &hdmi->wp,
+					 &hdmi->audio_config,
+					 hdmi->cfg.vm.pixelclock);
+		if (ret) {
+			DSSERR("Error restoring audio configuration: %d", ret);
+			hdmi->audio_abort_cb(&hdmi->pdev->dev);
+			hdmi->audio_configured = false;
+		}
+	}
+
+	spin_lock_irqsave(&hdmi->audio_playing_lock, flags);
+	if (hdmi->audio_configured && hdmi->audio_playing)
+		hdmi_start_audio_stream(hdmi);
+	hdmi->display_enabled = true;
+	spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags);
+
+done:
+	mutex_unlock(&hdmi->lock);
+}
+
+static void hdmi5_bridge_disable(struct drm_bridge *bridge,
+				 struct drm_atomic_state *state)
+{
+	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+	unsigned long flags;
+
+	mutex_lock(&hdmi->lock);
+
+	spin_lock_irqsave(&hdmi->audio_playing_lock, flags);
+	hdmi_stop_audio_stream(hdmi);
+	hdmi->display_enabled = false;
+	spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags);
+
+	hdmi_power_off_full(hdmi);
+
+	mutex_unlock(&hdmi->lock);
+}
+
 static struct edid *hdmi5_bridge_read_edid(struct omap_hdmi *hdmi,
 					   struct drm_connector *connector)
 {
@@ -540,6 +545,9 @@ static struct edid *hdmi5_bridge_get_edid(struct drm_bridge *bridge,
 
 static const struct drm_bridge_funcs hdmi5_bridge_funcs = {
 	.attach = hdmi5_bridge_attach,
+	.mode_set = hdmi5_bridge_mode_set,
+	.atomic_enable = hdmi5_bridge_enable,
+	.atomic_disable = hdmi5_bridge_disable,
 	.get_edid = hdmi5_bridge_get_edid,
 };
 
-- 
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] 106+ messages in thread

* [PATCH v2 31/50] drm/omap: hdmi4: Implement drm_bridge .hpd_notify() operation
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (29 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 30/50] drm/omap: hdmi5: " Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-20  1:17 ` [PATCH v2 32/50] drm/omap: dss: Remove .set_hdmi_mode() and .set_infoframe() operations Laurent Pinchart
                   ` (19 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

The HDMI4 encoder is transitioning to the drm_bridge API, implement the
last missing operation.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 2211a7a3dad3..349b1081b98f 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -551,6 +551,15 @@ static void hdmi4_bridge_disable(struct drm_bridge *bridge,
 	mutex_unlock(&hdmi->lock);
 }
 
+static void hdmi4_bridge_hpd_notify(struct drm_bridge *bridge,
+				    enum drm_connector_status status)
+{
+	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+
+	if (status == connector_status_disconnected)
+		hdmi4_cec_set_phys_addr(&hdmi->core, CEC_PHYS_ADDR_INVALID);
+}
+
 static struct edid *hdmi4_bridge_read_edid(struct omap_hdmi *hdmi,
 					   struct drm_connector *connector)
 {
@@ -570,6 +579,7 @@ static const struct drm_bridge_funcs hdmi4_bridge_funcs = {
 	.mode_set = hdmi4_bridge_mode_set,
 	.atomic_enable = hdmi4_bridge_enable,
 	.atomic_disable = hdmi4_bridge_disable,
+	.hpd_notify = hdmi4_bridge_hpd_notify,
 	.get_edid = hdmi4_bridge_get_edid,
 };
 
-- 
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] 106+ messages in thread

* [PATCH v2 32/50] drm/omap: dss: Remove .set_hdmi_mode() and .set_infoframe() operations
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (30 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 31/50] drm/omap: hdmi4: Implement drm_bridge .hpd_notify() operation Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-20  1:17 ` [PATCH v2 33/50] drm/omap: venc: Register a drm_bridge Laurent Pinchart
                   ` (18 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

The omapdss_hdmi_ops .set_hdmi_mode() and .set_infoframe() operations
operations are not used anymore, remove them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/omapdss.h  |  3 ---
 drivers/gpu/drm/omapdrm/omap_encoder.c | 26 --------------------------
 2 files changed, 29 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 269e143d57be..30a12cf91cbb 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -287,9 +287,6 @@ struct omap_dss_writeback_info {
 
 struct omapdss_hdmi_ops {
 	void (*lost_hotplug)(struct omap_dss_device *dssdev);
-	int (*set_hdmi_mode)(struct omap_dss_device *dssdev, bool hdmi_mode);
-	int (*set_infoframe)(struct omap_dss_device *dssdev,
-		const struct hdmi_avi_infoframe *avi);
 };
 
 struct omapdss_dsi_ops {
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
index bd87c28f9046..1545d30f26e0 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -68,28 +68,6 @@ static void omap_encoder_update_videomode_flags(struct videomode *vm,
 	}
 }
 
-static void omap_encoder_hdmi_mode_set(struct drm_connector *connector,
-				       struct drm_encoder *encoder,
-				       struct drm_display_mode *adjusted_mode)
-{
-	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-	struct omap_dss_device *dssdev = omap_encoder->output;
-	bool hdmi_mode = connector->display_info.is_hdmi;
-
-	if (dssdev->ops && dssdev->ops->hdmi.set_hdmi_mode)
-		dssdev->ops->hdmi.set_hdmi_mode(dssdev, hdmi_mode);
-
-	if (hdmi_mode && dssdev->ops && dssdev->ops->hdmi.set_infoframe) {
-		struct hdmi_avi_infoframe avi;
-		int r;
-
-		r = drm_hdmi_avi_infoframe_from_display_mode(&avi, connector,
-							     adjusted_mode);
-		if (r == 0)
-			dssdev->ops->hdmi.set_infoframe(dssdev, &avi);
-	}
-}
-
 static void omap_encoder_mode_set(struct drm_encoder *encoder,
 				  struct drm_display_mode *mode,
 				  struct drm_display_mode *adjusted_mode)
@@ -140,10 +118,6 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
 		if (dssdev->ops && dssdev->ops->set_timings)
 			dssdev->ops->set_timings(dssdev, adjusted_mode);
 	}
-
-	/* Set the HDMI mode and HDMI infoframe if applicable. */
-	if (output->type == OMAP_DISPLAY_TYPE_HDMI)
-		omap_encoder_hdmi_mode_set(connector, encoder, adjusted_mode);
 }
 
 static void omap_encoder_disable(struct drm_encoder *encoder)
-- 
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] 106+ messages in thread

* [PATCH v2 33/50] drm/omap: venc: Register a drm_bridge
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (31 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 32/50] drm/omap: dss: Remove .set_hdmi_mode() and .set_infoframe() operations Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-20  1:17 ` [PATCH v2 34/50] drm/omap: Create connector for bridges Laurent Pinchart
                   ` (17 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

In order to integrate with a chain of drm_bridge, the internal VENC
encoder has to expose the mode valid, fixup and set, the enable and
disable and the get modes operations through the drm_bridge API.
Register a bridge at initialisation time to do so.

Most of those operations are removed from the omap_dss_device as they
are now called through the drm_bridge API by the DRM atomic helpers. The
only exception is the .get_modes() operation that is still invoked
through the omap_dss_device-based pipeline.

For the time being make the next bridge in the chain optional as the
VENC output is still based on omap_dss_device. The create_connector
argument to the bridge attach function is also ignored for the same
reason. This will be changed later when removing the related
omapdrm-specific display drivers.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/venc.c | 245 +++++++++++++++++++----------
 1 file changed, 161 insertions(+), 84 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c
index 977d8d525b43..46e333442d5a 100644
--- a/drivers/gpu/drm/omapdrm/dss/venc.c
+++ b/drivers/gpu/drm/omapdrm/dss/venc.c
@@ -26,6 +26,8 @@
 #include <linux/component.h>
 #include <linux/sys_soc.h>
 
+#include <drm/drm_bridge.h>
+
 #include "omapdss.h"
 #include "dss.h"
 
@@ -303,9 +305,11 @@ struct venc_device {
 	bool requires_tv_dac_clk;
 
 	struct omap_dss_device output;
+	struct drm_bridge bridge;
 };
 
 #define dssdev_to_venc(dssdev) container_of(dssdev, struct venc_device, output)
+#define drm_bridge_to_venc(b) container_of(b, struct venc_device, bridge)
 
 static inline void venc_write_reg(struct venc_device *venc, int idx, u32 val)
 {
@@ -477,32 +481,6 @@ static void venc_power_off(struct venc_device *venc)
 	venc_runtime_put(venc);
 }
 
-static void venc_display_enable(struct omap_dss_device *dssdev)
-{
-	struct venc_device *venc = dssdev_to_venc(dssdev);
-
-	DSSDBG("venc_display_enable\n");
-
-	mutex_lock(&venc->venc_lock);
-
-	venc_power_on(venc);
-
-	mutex_unlock(&venc->venc_lock);
-}
-
-static void venc_display_disable(struct omap_dss_device *dssdev)
-{
-	struct venc_device *venc = dssdev_to_venc(dssdev);
-
-	DSSDBG("venc_display_disable\n");
-
-	mutex_lock(&venc->venc_lock);
-
-	venc_power_off(venc);
-
-	mutex_unlock(&venc->venc_lock);
-}
-
 static int venc_get_modes(struct omap_dss_device *dssdev,
 			  struct drm_connector *connector)
 {
@@ -545,57 +523,6 @@ static enum venc_videomode venc_get_videomode(const struct drm_display_mode *mod
 	return VENC_MODE_UNKNOWN;
 }
 
-static void venc_set_timings(struct omap_dss_device *dssdev,
-			     const struct drm_display_mode *mode)
-{
-	struct venc_device *venc = dssdev_to_venc(dssdev);
-	enum venc_videomode venc_mode = venc_get_videomode(mode);
-
-	DSSDBG("venc_set_timings\n");
-
-	mutex_lock(&venc->venc_lock);
-
-	switch (venc_mode) {
-	default:
-		WARN_ON_ONCE(1);
-		/* Fall-through */
-	case VENC_MODE_PAL:
-		venc->config = &venc_config_pal_trm;
-		break;
-
-	case VENC_MODE_NTSC:
-		venc->config = &venc_config_ntsc_trm;
-		break;
-	}
-
-	dispc_set_tv_pclk(venc->dss->dispc, 13500000);
-
-	mutex_unlock(&venc->venc_lock);
-}
-
-static int venc_check_timings(struct omap_dss_device *dssdev,
-			      struct drm_display_mode *mode)
-{
-	DSSDBG("venc_check_timings\n");
-
-	switch (venc_get_videomode(mode)) {
-	case VENC_MODE_PAL:
-		drm_mode_copy(mode, &omap_dss_pal_mode);
-		break;
-
-	case VENC_MODE_NTSC:
-		drm_mode_copy(mode, &omap_dss_ntsc_mode);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
-	drm_mode_set_name(mode);
-	return 0;
-}
-
 static int venc_dump_regs(struct seq_file *s, void *p)
 {
 	struct venc_device *venc = s->private;
@@ -689,15 +616,161 @@ static const struct omap_dss_device_ops venc_ops = {
 	.connect = venc_connect,
 	.disconnect = venc_disconnect,
 
-	.enable = venc_display_enable,
-	.disable = venc_display_disable,
-
-	.check_timings = venc_check_timings,
-	.set_timings = venc_set_timings,
-
 	.get_modes = venc_get_modes,
 };
 
+/* -----------------------------------------------------------------------------
+ * DRM Bridge Operations
+ */
+
+static int venc_bridge_attach(struct drm_bridge *bridge,
+			      enum drm_bridge_attach_flags flags)
+{
+	struct venc_device *venc = drm_bridge_to_venc(bridge);
+
+	if (venc->output.next_bridge)
+		return 0;
+
+	return drm_bridge_attach(bridge->encoder, venc->output.next_bridge,
+				 bridge, flags);
+}
+
+static enum drm_mode_status
+venc_bridge_mode_valid(struct drm_bridge *bridge,
+		       const struct drm_display_mode *mode)
+{
+	switch (venc_get_videomode(mode)) {
+	case VENC_MODE_PAL:
+	case VENC_MODE_NTSC:
+		return MODE_OK;
+
+	default:
+		return MODE_BAD;
+	}
+}
+
+static bool venc_bridge_mode_fixup(struct drm_bridge *bridge,
+				   const struct drm_display_mode *mode,
+				   struct drm_display_mode *adjusted_mode)
+{
+	const struct drm_display_mode *venc_mode;
+
+	switch (venc_get_videomode(adjusted_mode)) {
+	case VENC_MODE_PAL:
+		venc_mode = &omap_dss_pal_mode;
+		break;
+
+	case VENC_MODE_NTSC:
+		venc_mode = &omap_dss_ntsc_mode;
+		break;
+
+	default:
+		return false;
+	}
+
+	drm_mode_copy(adjusted_mode, venc_mode);
+	drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
+	drm_mode_set_name(adjusted_mode);
+
+	return true;
+}
+
+static void venc_bridge_mode_set(struct drm_bridge *bridge,
+				 const struct drm_display_mode *mode,
+				 const struct drm_display_mode *adjusted_mode)
+{
+	struct venc_device *venc = drm_bridge_to_venc(bridge);
+	enum venc_videomode venc_mode = venc_get_videomode(adjusted_mode);
+
+	mutex_lock(&venc->venc_lock);
+
+	switch (venc_mode) {
+	default:
+		WARN_ON_ONCE(1);
+		/* Fall-through */
+	case VENC_MODE_PAL:
+		venc->config = &venc_config_pal_trm;
+		break;
+
+	case VENC_MODE_NTSC:
+		venc->config = &venc_config_ntsc_trm;
+		break;
+	}
+
+	dispc_set_tv_pclk(venc->dss->dispc, 13500000);
+
+	mutex_unlock(&venc->venc_lock);
+}
+
+static void venc_bridge_enable(struct drm_bridge *bridge,
+			       struct drm_atomic_state *state)
+{
+	struct venc_device *venc = drm_bridge_to_venc(bridge);
+
+	mutex_lock(&venc->venc_lock);
+	venc_power_on(venc);
+	mutex_unlock(&venc->venc_lock);
+}
+
+static void venc_bridge_disable(struct drm_bridge *bridge,
+				struct drm_atomic_state *state)
+{
+	struct venc_device *venc = drm_bridge_to_venc(bridge);
+
+	mutex_lock(&venc->venc_lock);
+	venc_power_off(venc);
+	mutex_unlock(&venc->venc_lock);
+}
+
+static int venc_bridge_get_modes(struct drm_bridge *bridge,
+				 struct drm_connector *connector)
+{
+	static const struct drm_display_mode *modes[] = {
+		&omap_dss_pal_mode,
+		&omap_dss_ntsc_mode,
+	};
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(modes); ++i) {
+		struct drm_display_mode *mode;
+
+		mode = drm_mode_duplicate(connector->dev, modes[i]);
+		if (!mode)
+			return i;
+
+		mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+		drm_mode_set_name(mode);
+		drm_mode_probed_add(connector, mode);
+	}
+
+	return ARRAY_SIZE(modes);
+}
+
+static const struct drm_bridge_funcs venc_bridge_funcs = {
+	.attach = venc_bridge_attach,
+	.mode_valid = venc_bridge_mode_valid,
+	.mode_fixup = venc_bridge_mode_fixup,
+	.mode_set = venc_bridge_mode_set,
+	.atomic_enable = venc_bridge_enable,
+	.atomic_disable = venc_bridge_disable,
+	.get_modes = venc_bridge_get_modes,
+};
+
+static void venc_bridge_init(struct venc_device *venc)
+{
+	venc->bridge.funcs = &venc_bridge_funcs;
+	venc->bridge.of_node = venc->pdev->dev.of_node;
+	venc->bridge.ops = DRM_BRIDGE_OP_MODES;
+	venc->bridge.type = DRM_MODE_CONNECTOR_SVIDEO;
+
+	drm_bridge_add(&venc->bridge);
+}
+
+static void venc_bridge_cleanup(struct venc_device *venc)
+{
+	drm_bridge_remove(&venc->bridge);
+}
+
 /* -----------------------------------------------------------------------------
  * Component Bind & Unbind
  */
@@ -747,6 +820,8 @@ static int venc_init_output(struct venc_device *venc)
 	struct omap_dss_device *out = &venc->output;
 	int r;
 
+	venc_bridge_init(venc);
+
 	out->dev = &venc->pdev->dev;
 	out->id = OMAP_DSS_OUTPUT_VENC;
 	out->type = OMAP_DISPLAY_TYPE_VENC;
@@ -757,7 +832,7 @@ static int venc_init_output(struct venc_device *venc)
 	out->of_port = 0;
 	out->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
 
-	r = omapdss_device_init_output(out, NULL);
+	r = omapdss_device_init_output(out, &venc->bridge);
 	if (r < 0)
 		return r;
 
@@ -770,6 +845,8 @@ static void venc_uninit_output(struct venc_device *venc)
 {
 	omapdss_device_unregister(&venc->output);
 	omapdss_device_cleanup_output(&venc->output);
+
+	venc_bridge_cleanup(venc);
 }
 
 static int venc_probe_of(struct venc_device *venc)
-- 
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] 106+ messages in thread

* [PATCH v2 34/50] drm/omap: Create connector for bridges
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (32 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 33/50] drm/omap: venc: Register a drm_bridge Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-22 17:00   ` Boris Brezillon
  2019-08-20  1:17 ` [PATCH v2 35/50] drm/omap: Switch the HDMI and VENC outputs to drm_bridge Laurent Pinchart
                   ` (16 subsequent siblings)
  50 siblings, 1 reply; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Use the drm_bridge_connector helper to create a connector for pipelines
that use drm_bridge. This allows splitting connector operations across
multiple bridges when necessary, instead of having the last bridge in
the chain creating the connector and handling all connector operations
internally.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v1:

- Squash with patch "drm/omap: Detach from panels at remove time"
---
 drivers/gpu/drm/omapdrm/omap_drv.c | 82 +++++++++++++++++++++++++-----
 1 file changed, 70 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index de373fd50729..f38d95cb31ba 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -11,10 +11,12 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge_connector.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_file.h>
 #include <drm/drm_ioctl.h>
+#include <drm/drm_panel.h>
 #include <drm/drm_prime.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
@@ -290,9 +292,14 @@ static int omap_modeset_init(struct drm_device *dev)
 
 		if (pipe->output->bridge) {
 			ret = drm_bridge_attach(pipe->encoder,
-						pipe->output->bridge, NULL, 0);
-			if (ret < 0)
+						pipe->output->bridge, NULL,
+						DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+			if (ret < 0) {
+				dev_err(priv->dev,
+					"unable to attach bridge %pOF\n",
+					pipe->output->bridge->of_node);
 				return ret;
+			}
 		}
 
 		id = omap_display_id(pipe->output);
@@ -328,8 +335,31 @@ static int omap_modeset_init(struct drm_device *dev)
 							      encoder);
 			if (!pipe->connector)
 				return -ENOMEM;
+		} else {
+			struct drm_bridge *bridge = pipe->output->bridge;
 
-			drm_connector_attach_encoder(pipe->connector, encoder);
+			pipe->connector = drm_bridge_connector_init(dev,
+								    bridge);
+			if (IS_ERR(pipe->connector)) {
+				dev_err(priv->dev,
+					"unable to create bridge connector for %pOF\n",
+					bridge->of_node);
+				return PTR_ERR(pipe->connector);
+			}
+		}
+
+		drm_connector_attach_encoder(pipe->connector, encoder);
+
+		/*
+		 * FIXME: drm_panel should not store the drm_connector pointer
+		 * internally but should receive it in its .get_modes()
+		 * operation.
+		 */
+		if (pipe->output->panel) {
+			ret = drm_panel_attach(pipe->output->panel,
+					       pipe->connector);
+			if (ret < 0)
+				return ret;
 		}
 
 		crtc = omap_crtc_init(dev, pipe, priv->planes[i]);
@@ -368,6 +398,23 @@ static int omap_modeset_init(struct drm_device *dev)
 	return 0;
 }
 
+static void omap_modeset_fini(struct drm_device *ddev)
+{
+	struct omap_drm_private *priv = ddev->dev_private;
+	unsigned int i;
+
+	omap_drm_irq_uninstall(ddev);
+
+	for (i = 0; i < priv->num_pipes; i++) {
+		struct omap_drm_pipeline *pipe = &priv->pipes[i];
+
+		if (pipe->output->panel)
+			drm_panel_detach(pipe->output->panel);
+	}
+
+	drm_mode_config_cleanup(ddev);
+}
+
 /*
  * Enable the HPD in external components if supported
  */
@@ -377,8 +424,15 @@ static void omap_modeset_enable_external_hpd(struct drm_device *ddev)
 	unsigned int i;
 
 	for (i = 0; i < priv->num_pipes; i++) {
-		if (priv->pipes[i].connector)
-			omap_connector_enable_hpd(priv->pipes[i].connector);
+		struct drm_connector *connector = priv->pipes[i].connector;
+
+		if (!connector)
+			continue;
+
+		if (priv->pipes[i].output->next)
+			omap_connector_enable_hpd(connector);
+		else
+			drm_bridge_connector_enable_hpd(connector);
 	}
 }
 
@@ -391,8 +445,15 @@ static void omap_modeset_disable_external_hpd(struct drm_device *ddev)
 	unsigned int i;
 
 	for (i = 0; i < priv->num_pipes; i++) {
-		if (priv->pipes[i].connector)
-			omap_connector_disable_hpd(priv->pipes[i].connector);
+		struct drm_connector *connector = priv->pipes[i].connector;
+
+		if (!connector)
+			continue;
+
+		if (priv->pipes[i].output->next)
+			omap_connector_disable_hpd(connector);
+		else
+			drm_bridge_connector_disable_hpd(connector);
 	}
 }
 
@@ -615,8 +676,7 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev)
 
 	omap_fbdev_fini(ddev);
 err_cleanup_modeset:
-	drm_mode_config_cleanup(ddev);
-	omap_drm_irq_uninstall(ddev);
+	omap_modeset_fini(ddev);
 err_gem_deinit:
 	omap_gem_deinit(ddev);
 	destroy_workqueue(priv->wq);
@@ -641,9 +701,7 @@ static void omapdrm_cleanup(struct omap_drm_private *priv)
 
 	drm_atomic_helper_shutdown(ddev);
 
-	drm_mode_config_cleanup(ddev);
-
-	omap_drm_irq_uninstall(ddev);
+	omap_modeset_fini(ddev);
 	omap_gem_deinit(ddev);
 
 	destroy_workqueue(priv->wq);
-- 
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] 106+ messages in thread

* [PATCH v2 35/50] drm/omap: Switch the HDMI and VENC outputs to drm_bridge
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (33 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 34/50] drm/omap: Create connector for bridges Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-20  1:17 ` [PATCH v2 36/50] drm/omap: Remove HPD, detect and EDID omapdss operations Laurent Pinchart
                   ` (15 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

The TPD12S015, OPA362 and analog and HDMI connectors are now supported
by DRM bridge drivers, and the omapdrm HDMI and VENC outputs can be
handled through the drm_bridge API. Switch the outputs to drm_bridge by
making the next bridge mandatory and removing the related
omapdrm-specific display drivers.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/displays/Kconfig      |  22 --
 drivers/gpu/drm/omapdrm/displays/Makefile     |   4 -
 .../omapdrm/displays/connector-analog-tv.c    |  97 --------
 .../gpu/drm/omapdrm/displays/connector-hdmi.c | 183 ---------------
 .../gpu/drm/omapdrm/displays/encoder-opa362.c | 137 -----------
 .../drm/omapdrm/displays/encoder-tpd12s015.c  | 217 ------------------
 drivers/gpu/drm/omapdrm/dss/hdmi4.c           |   4 +-
 drivers/gpu/drm/omapdrm/dss/hdmi5.c           |   4 +-
 .../gpu/drm/omapdrm/dss/omapdss-boot-init.c   |   5 -
 drivers/gpu/drm/omapdrm/dss/output.c          |   5 +
 drivers/gpu/drm/omapdrm/dss/venc.c            |   4 +-
 11 files changed, 11 insertions(+), 671 deletions(-)
 delete mode 100644 drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
 delete mode 100644 drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
 delete mode 100644 drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
 delete mode 100644 drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c

diff --git a/drivers/gpu/drm/omapdrm/displays/Kconfig b/drivers/gpu/drm/omapdrm/displays/Kconfig
index 240dda102845..f2be594c7eff 100644
--- a/drivers/gpu/drm/omapdrm/displays/Kconfig
+++ b/drivers/gpu/drm/omapdrm/displays/Kconfig
@@ -1,28 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 menu "OMAPDRM External Display Device Drivers"
 
-config DRM_OMAP_ENCODER_OPA362
-	tristate "OPA362 external analog amplifier"
-	help
-	  Driver for OPA362 external analog TV amplifier controlled
-	  through a GPIO.
-
-config DRM_OMAP_ENCODER_TPD12S015
-        tristate "TPD12S015 HDMI ESD protection and level shifter"
-	help
-	  Driver for TPD12S015, which offers HDMI ESD protection and level
-	  shifting.
-
-config DRM_OMAP_CONNECTOR_HDMI
-        tristate "HDMI Connector"
-	help
-	  Driver for a generic HDMI connector.
-
-config DRM_OMAP_CONNECTOR_ANALOG_TV
-        tristate "Analog TV Connector"
-	help
-	  Driver for a generic analog TV connector.
-
 config DRM_OMAP_PANEL_DSI_CM
 	tristate "Generic DSI Command Mode Panel"
 	depends on BACKLIGHT_CLASS_DEVICE
diff --git a/drivers/gpu/drm/omapdrm/displays/Makefile b/drivers/gpu/drm/omapdrm/displays/Makefile
index cb76859dc574..488ddf153613 100644
--- a/drivers/gpu/drm/omapdrm/displays/Makefile
+++ b/drivers/gpu/drm/omapdrm/displays/Makefile
@@ -1,6 +1,2 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_DRM_OMAP_ENCODER_OPA362) += encoder-opa362.o
-obj-$(CONFIG_DRM_OMAP_ENCODER_TPD12S015) += encoder-tpd12s015.o
-obj-$(CONFIG_DRM_OMAP_CONNECTOR_HDMI) += connector-hdmi.o
-obj-$(CONFIG_DRM_OMAP_CONNECTOR_ANALOG_TV) += connector-analog-tv.o
 obj-$(CONFIG_DRM_OMAP_PANEL_DSI_CM) += panel-dsi-cm.o
diff --git a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c b/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
deleted file mode 100644
index f36aa1885d39..000000000000
--- a/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
+++ /dev/null
@@ -1,97 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Analog TV Connector driver
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- */
-
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-
-#include "../dss/omapdss.h"
-
-struct panel_drv_data {
-	struct omap_dss_device dssdev;
-
-	struct device *dev;
-};
-
-#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
-
-static int tvc_connect(struct omap_dss_device *src,
-		       struct omap_dss_device *dst)
-{
-	return 0;
-}
-
-static void tvc_disconnect(struct omap_dss_device *src,
-			   struct omap_dss_device *dst)
-{
-}
-
-static const struct omap_dss_device_ops tvc_ops = {
-	.connect		= tvc_connect,
-	.disconnect		= tvc_disconnect,
-};
-
-static int tvc_probe(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata;
-	struct omap_dss_device *dssdev;
-
-	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
-	if (!ddata)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, ddata);
-	ddata->dev = &pdev->dev;
-
-	dssdev = &ddata->dssdev;
-	dssdev->ops = &tvc_ops;
-	dssdev->dev = &pdev->dev;
-	dssdev->type = OMAP_DISPLAY_TYPE_VENC;
-	dssdev->display = true;
-	dssdev->owner = THIS_MODULE;
-	dssdev->of_port = 0;
-
-	omapdss_display_init(dssdev);
-	omapdss_device_register(dssdev);
-
-	return 0;
-}
-
-static int __exit tvc_remove(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-
-	omapdss_device_unregister(&ddata->dssdev);
-
-	return 0;
-}
-
-static const struct of_device_id tvc_of_match[] = {
-	{ .compatible = "omapdss,svideo-connector", },
-	{ .compatible = "omapdss,composite-video-connector", },
-	{},
-};
-
-MODULE_DEVICE_TABLE(of, tvc_of_match);
-
-static struct platform_driver tvc_connector_driver = {
-	.probe	= tvc_probe,
-	.remove	= __exit_p(tvc_remove),
-	.driver	= {
-		.name	= "connector-analog-tv",
-		.of_match_table = tvc_of_match,
-		.suppress_bind_attrs = true,
-	},
-};
-
-module_platform_driver(tvc_connector_driver);
-
-MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
-MODULE_DESCRIPTION("Analog TV Connector driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
deleted file mode 100644
index 37c212491cd3..000000000000
--- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
+++ /dev/null
@@ -1,183 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * HDMI Connector driver
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- */
-
-#include <linux/gpio/consumer.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include "../dss/omapdss.h"
-
-struct panel_drv_data {
-	struct omap_dss_device dssdev;
-	void (*hpd_cb)(void *cb_data, enum drm_connector_status status);
-	void *hpd_cb_data;
-	struct mutex hpd_lock;
-
-	struct device *dev;
-
-	struct gpio_desc *hpd_gpio;
-};
-
-#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
-
-static int hdmic_connect(struct omap_dss_device *src,
-			 struct omap_dss_device *dst)
-{
-	return 0;
-}
-
-static void hdmic_disconnect(struct omap_dss_device *src,
-			     struct omap_dss_device *dst)
-{
-}
-
-static bool hdmic_detect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	return gpiod_get_value_cansleep(ddata->hpd_gpio);
-}
-
-static void hdmic_register_hpd_cb(struct omap_dss_device *dssdev,
-				  void (*cb)(void *cb_data,
-					    enum drm_connector_status status),
-				  void *cb_data)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	mutex_lock(&ddata->hpd_lock);
-	ddata->hpd_cb = cb;
-	ddata->hpd_cb_data = cb_data;
-	mutex_unlock(&ddata->hpd_lock);
-}
-
-static void hdmic_unregister_hpd_cb(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	mutex_lock(&ddata->hpd_lock);
-	ddata->hpd_cb = NULL;
-	ddata->hpd_cb_data = NULL;
-	mutex_unlock(&ddata->hpd_lock);
-}
-
-static const struct omap_dss_device_ops hdmic_ops = {
-	.connect		= hdmic_connect,
-	.disconnect		= hdmic_disconnect,
-
-	.detect			= hdmic_detect,
-	.register_hpd_cb	= hdmic_register_hpd_cb,
-	.unregister_hpd_cb	= hdmic_unregister_hpd_cb,
-};
-
-static irqreturn_t hdmic_hpd_isr(int irq, void *data)
-{
-	struct panel_drv_data *ddata = data;
-
-	mutex_lock(&ddata->hpd_lock);
-	if (ddata->hpd_cb) {
-		enum drm_connector_status status;
-
-		if (hdmic_detect(&ddata->dssdev))
-			status = connector_status_connected;
-		else
-			status = connector_status_disconnected;
-
-		ddata->hpd_cb(ddata->hpd_cb_data, status);
-	}
-	mutex_unlock(&ddata->hpd_lock);
-
-	return IRQ_HANDLED;
-}
-
-static int hdmic_probe(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata;
-	struct omap_dss_device *dssdev;
-	struct gpio_desc *gpio;
-	int r;
-
-	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
-	if (!ddata)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, ddata);
-	ddata->dev = &pdev->dev;
-
-	mutex_init(&ddata->hpd_lock);
-
-	/* HPD GPIO */
-	gpio = devm_gpiod_get_optional(&pdev->dev, "hpd", GPIOD_IN);
-	if (IS_ERR(gpio)) {
-		dev_err(&pdev->dev, "failed to parse HPD gpio\n");
-		return PTR_ERR(gpio);
-	}
-
-	ddata->hpd_gpio = gpio;
-
-	if (ddata->hpd_gpio) {
-		r = devm_request_threaded_irq(&pdev->dev,
-				gpiod_to_irq(ddata->hpd_gpio),
-				NULL, hdmic_hpd_isr,
-				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
-				IRQF_ONESHOT,
-				"hdmic hpd", ddata);
-		if (r)
-			return r;
-	}
-
-	dssdev = &ddata->dssdev;
-	dssdev->ops = &hdmic_ops;
-	dssdev->dev = &pdev->dev;
-	dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
-	dssdev->display = true;
-	dssdev->owner = THIS_MODULE;
-	dssdev->of_port = 0;
-	dssdev->ops_flags = ddata->hpd_gpio
-			  ? OMAP_DSS_DEVICE_OP_DETECT | OMAP_DSS_DEVICE_OP_HPD
-			  : 0;
-
-	omapdss_display_init(dssdev);
-	omapdss_device_register(dssdev);
-
-	return 0;
-}
-
-static int __exit hdmic_remove(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-
-	omapdss_device_unregister(&ddata->dssdev);
-
-	return 0;
-}
-
-static const struct of_device_id hdmic_of_match[] = {
-	{ .compatible = "omapdss,hdmi-connector", },
-	{},
-};
-
-MODULE_DEVICE_TABLE(of, hdmic_of_match);
-
-static struct platform_driver hdmi_connector_driver = {
-	.probe	= hdmic_probe,
-	.remove	= __exit_p(hdmic_remove),
-	.driver	= {
-		.name	= "connector-hdmi",
-		.of_match_table = hdmic_of_match,
-		.suppress_bind_attrs = true,
-	},
-};
-
-module_platform_driver(hdmi_connector_driver);
-
-MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
-MODULE_DESCRIPTION("HDMI Connector driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c b/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
deleted file mode 100644
index 252705222ef1..000000000000
--- a/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
+++ /dev/null
@@ -1,137 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * OPA362 analog video amplifier with output/power control
- *
- * Copyright (C) 2014 Golden Delicious Computers
- * Author: H. Nikolaus Schaller <hns@goldelico.com>
- *
- * based on encoder-tfp410
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- */
-
-#include <linux/gpio/consumer.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include "../dss/omapdss.h"
-
-struct panel_drv_data {
-	struct omap_dss_device dssdev;
-
-	struct gpio_desc *enable_gpio;
-};
-
-#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
-
-static int opa362_connect(struct omap_dss_device *src,
-			  struct omap_dss_device *dst)
-{
-	return omapdss_device_connect(dst->dss, dst, dst->next);
-}
-
-static void opa362_disconnect(struct omap_dss_device *src,
-			      struct omap_dss_device *dst)
-{
-	omapdss_device_disconnect(dst, dst->next);
-}
-
-static void opa362_enable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	if (ddata->enable_gpio)
-		gpiod_set_value_cansleep(ddata->enable_gpio, 1);
-}
-
-static void opa362_disable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	if (ddata->enable_gpio)
-		gpiod_set_value_cansleep(ddata->enable_gpio, 0);
-}
-
-static const struct omap_dss_device_ops opa362_ops = {
-	.connect	= opa362_connect,
-	.disconnect	= opa362_disconnect,
-	.enable		= opa362_enable,
-	.disable	= opa362_disable,
-};
-
-static int opa362_probe(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata;
-	struct omap_dss_device *dssdev;
-	struct gpio_desc *gpio;
-
-	dev_dbg(&pdev->dev, "probe\n");
-
-	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
-	if (!ddata)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, ddata);
-
-	gpio = devm_gpiod_get_optional(&pdev->dev, "enable", GPIOD_OUT_LOW);
-	if (IS_ERR(gpio))
-		return PTR_ERR(gpio);
-
-	ddata->enable_gpio = gpio;
-
-	dssdev = &ddata->dssdev;
-	dssdev->ops = &opa362_ops;
-	dssdev->dev = &pdev->dev;
-	dssdev->type = OMAP_DISPLAY_TYPE_VENC;
-	dssdev->owner = THIS_MODULE;
-	dssdev->of_port = 1;
-
-	dssdev->next = omapdss_of_find_connected_device(pdev->dev.of_node, 1);
-	if (IS_ERR(dssdev->next)) {
-		if (PTR_ERR(dssdev->next) != -EPROBE_DEFER)
-			dev_err(&pdev->dev, "failed to find video sink\n");
-		return PTR_ERR(dssdev->next);
-	}
-
-	omapdss_device_register(dssdev);
-
-	return 0;
-}
-
-static int __exit opa362_remove(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct omap_dss_device *dssdev = &ddata->dssdev;
-
-	if (dssdev->next)
-		omapdss_device_put(dssdev->next);
-	omapdss_device_unregister(&ddata->dssdev);
-
-	opa362_disable(dssdev);
-
-	return 0;
-}
-
-static const struct of_device_id opa362_of_match[] = {
-	{ .compatible = "omapdss,ti,opa362", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, opa362_of_match);
-
-static struct platform_driver opa362_driver = {
-	.probe	= opa362_probe,
-	.remove	= __exit_p(opa362_remove),
-	.driver	= {
-		.name	= "amplifier-opa362",
-		.of_match_table = opa362_of_match,
-		.suppress_bind_attrs = true,
-	},
-};
-
-module_platform_driver(opa362_driver);
-
-MODULE_AUTHOR("H. Nikolaus Schaller <hns@goldelico.com>");
-MODULE_DESCRIPTION("OPA362 analog video amplifier with output/power control");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
deleted file mode 100644
index 857ae84cd7d1..000000000000
--- a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
+++ /dev/null
@@ -1,217 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * TPD12S015 HDMI ESD protection & level shifter chip driver
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- */
-
-#include <linux/completion.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/gpio/consumer.h>
-#include <linux/mutex.h>
-
-#include "../dss/omapdss.h"
-
-struct panel_drv_data {
-	struct omap_dss_device dssdev;
-	void (*hpd_cb)(void *cb_data, enum drm_connector_status status);
-	void *hpd_cb_data;
-	struct mutex hpd_lock;
-
-	struct gpio_desc *ct_cp_hpd_gpio;
-	struct gpio_desc *ls_oe_gpio;
-	struct gpio_desc *hpd_gpio;
-};
-
-#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
-
-static int tpd_connect(struct omap_dss_device *src,
-		       struct omap_dss_device *dst)
-{
-	struct panel_drv_data *ddata = to_panel_data(dst);
-	int r;
-
-	r = omapdss_device_connect(dst->dss, dst, dst->next);
-	if (r)
-		return r;
-
-	gpiod_set_value_cansleep(ddata->ct_cp_hpd_gpio, 1);
-	gpiod_set_value_cansleep(ddata->ls_oe_gpio, 1);
-
-	/* DC-DC converter needs at max 300us to get to 90% of 5V */
-	udelay(300);
-
-	return 0;
-}
-
-static void tpd_disconnect(struct omap_dss_device *src,
-			   struct omap_dss_device *dst)
-{
-	struct panel_drv_data *ddata = to_panel_data(dst);
-
-	gpiod_set_value_cansleep(ddata->ct_cp_hpd_gpio, 0);
-	gpiod_set_value_cansleep(ddata->ls_oe_gpio, 0);
-
-	omapdss_device_disconnect(dst, dst->next);
-}
-
-static bool tpd_detect(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	return gpiod_get_value_cansleep(ddata->hpd_gpio);
-}
-
-static void tpd_register_hpd_cb(struct omap_dss_device *dssdev,
-				void (*cb)(void *cb_data,
-					  enum drm_connector_status status),
-				void *cb_data)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	mutex_lock(&ddata->hpd_lock);
-	ddata->hpd_cb = cb;
-	ddata->hpd_cb_data = cb_data;
-	mutex_unlock(&ddata->hpd_lock);
-}
-
-static void tpd_unregister_hpd_cb(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	mutex_lock(&ddata->hpd_lock);
-	ddata->hpd_cb = NULL;
-	ddata->hpd_cb_data = NULL;
-	mutex_unlock(&ddata->hpd_lock);
-}
-
-static const struct omap_dss_device_ops tpd_ops = {
-	.connect		= tpd_connect,
-	.disconnect		= tpd_disconnect,
-	.detect			= tpd_detect,
-	.register_hpd_cb	= tpd_register_hpd_cb,
-	.unregister_hpd_cb	= tpd_unregister_hpd_cb,
-};
-
-static irqreturn_t tpd_hpd_isr(int irq, void *data)
-{
-	struct panel_drv_data *ddata = data;
-
-	mutex_lock(&ddata->hpd_lock);
-	if (ddata->hpd_cb) {
-		enum drm_connector_status status;
-
-		if (tpd_detect(&ddata->dssdev))
-			status = connector_status_connected;
-		else
-			status = connector_status_disconnected;
-
-		ddata->hpd_cb(ddata->hpd_cb_data, status);
-	}
-	mutex_unlock(&ddata->hpd_lock);
-
-	return IRQ_HANDLED;
-}
-
-static int tpd_probe(struct platform_device *pdev)
-{
-	struct omap_dss_device *dssdev;
-	struct panel_drv_data *ddata;
-	int r;
-	struct gpio_desc *gpio;
-
-	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
-	if (!ddata)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, ddata);
-
-	gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 0,
-		 GPIOD_OUT_LOW);
-	if (IS_ERR(gpio))
-		return PTR_ERR(gpio);
-
-	ddata->ct_cp_hpd_gpio = gpio;
-
-	gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 1,
-		 GPIOD_OUT_LOW);
-	if (IS_ERR(gpio))
-		return PTR_ERR(gpio);
-
-	ddata->ls_oe_gpio = gpio;
-
-	gpio = devm_gpiod_get_index(&pdev->dev, NULL, 2,
-		GPIOD_IN);
-	if (IS_ERR(gpio))
-		return PTR_ERR(gpio);
-
-	ddata->hpd_gpio = gpio;
-
-	mutex_init(&ddata->hpd_lock);
-
-	r = devm_request_threaded_irq(&pdev->dev, gpiod_to_irq(ddata->hpd_gpio),
-		NULL, tpd_hpd_isr,
-		IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-		"tpd12s015 hpd", ddata);
-	if (r)
-		return r;
-
-	dssdev = &ddata->dssdev;
-	dssdev->ops = &tpd_ops;
-	dssdev->dev = &pdev->dev;
-	dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
-	dssdev->owner = THIS_MODULE;
-	dssdev->of_port = 1;
-	dssdev->ops_flags = OMAP_DSS_DEVICE_OP_DETECT
-			  | OMAP_DSS_DEVICE_OP_HPD;
-
-	dssdev->next = omapdss_of_find_connected_device(pdev->dev.of_node, 1);
-	if (IS_ERR(dssdev->next)) {
-		if (PTR_ERR(dssdev->next) != -EPROBE_DEFER)
-			dev_err(&pdev->dev, "failed to find video sink\n");
-		return PTR_ERR(dssdev->next);
-	}
-
-	omapdss_device_register(dssdev);
-
-	return 0;
-}
-
-static int __exit tpd_remove(struct platform_device *pdev)
-{
-	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-	struct omap_dss_device *dssdev = &ddata->dssdev;
-
-	if (dssdev->next)
-		omapdss_device_put(dssdev->next);
-	omapdss_device_unregister(&ddata->dssdev);
-
-	return 0;
-}
-
-static const struct of_device_id tpd_of_match[] = {
-	{ .compatible = "omapdss,ti,tpd12s015", },
-	{},
-};
-
-MODULE_DEVICE_TABLE(of, tpd_of_match);
-
-static struct platform_driver tpd_driver = {
-	.probe	= tpd_probe,
-	.remove	= __exit_p(tpd_remove),
-	.driver	= {
-		.name	= "tpd12s015",
-		.of_match_table = tpd_of_match,
-		.suppress_bind_attrs = true,
-	},
-};
-
-module_platform_driver(tpd_driver);
-
-MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
-MODULE_DESCRIPTION("TPD12S015 driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 349b1081b98f..5d6adbb1d547 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -443,8 +443,8 @@ static int hdmi4_bridge_attach(struct drm_bridge *bridge,
 {
 	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
 
-	if (!hdmi->output.next_bridge)
-		return 0;
+	if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
+		return -EINVAL;
 
 	return drm_bridge_attach(bridge->encoder, hdmi->output.next_bridge,
 				 bridge, flags);
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 09be3f0dec81..74300fea86cc 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -421,8 +421,8 @@ static int hdmi5_bridge_attach(struct drm_bridge *bridge,
 {
 	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
 
-	if (!hdmi->output.next_bridge)
-		return 0;
+	if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
+		return -EINVAL;
 
 	return drm_bridge_attach(bridge->encoder, hdmi->output.next_bridge,
 				 bridge, flags);
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c b/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
index 31502857f013..ae356f8c83e8 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
@@ -174,12 +174,7 @@ static const struct of_device_id omapdss_of_match[] __initconst = {
 };
 
 static const struct of_device_id omapdss_of_fixups_whitelist[] __initconst = {
-	{ .compatible = "composite-video-connector" },
-	{ .compatible = "hdmi-connector" },
 	{ .compatible = "panel-dsi-cm" },
-	{ .compatible = "svideo-connector" },
-	{ .compatible = "ti,opa362" },
-	{ .compatible = "ti,tpd12s015" },
 	{},
 };
 
diff --git a/drivers/gpu/drm/omapdrm/dss/output.c b/drivers/gpu/drm/omapdrm/dss/output.c
index b27739afb335..8aa9ee5a2b01 100644
--- a/drivers/gpu/drm/omapdrm/dss/output.c
+++ b/drivers/gpu/drm/omapdrm/dss/output.c
@@ -61,6 +61,11 @@ int omapdss_device_init_output(struct omap_dss_device *out,
 	}
 
 	if (local_bridge) {
+		if (!out->bridge) {
+			ret = -EPROBE_DEFER;
+			goto error;
+		}
+
 		out->next_bridge = out->bridge;
 		out->bridge = local_bridge;
 	}
diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c
index 46e333442d5a..cc775e8b9978 100644
--- a/drivers/gpu/drm/omapdrm/dss/venc.c
+++ b/drivers/gpu/drm/omapdrm/dss/venc.c
@@ -628,8 +628,8 @@ static int venc_bridge_attach(struct drm_bridge *bridge,
 {
 	struct venc_device *venc = drm_bridge_to_venc(bridge);
 
-	if (venc->output.next_bridge)
-		return 0;
+	if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
+		return -EINVAL;
 
 	return drm_bridge_attach(bridge->encoder, venc->output.next_bridge,
 				 bridge, flags);
-- 
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] 106+ messages in thread

* [PATCH v2 36/50] drm/omap: Remove HPD, detect and EDID omapdss operations
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (34 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 35/50] drm/omap: Switch the HDMI and VENC outputs to drm_bridge Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-20  1:17 ` [PATCH v2 37/50] drm/omap: hdmi: Remove omap_dss_device operations Laurent Pinchart
                   ` (14 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Due to the removal of several omapdrm display drivers, the omapdss HPD,
detected and EDID operations are not used anymore. Remove them and all
related code.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c      |  61 --------
 drivers/gpu/drm/omapdrm/dss/hdmi5.c      |  46 ------
 drivers/gpu/drm/omapdrm/dss/omapdss.h    |  25 +--
 drivers/gpu/drm/omapdrm/omap_connector.c | 190 +++--------------------
 drivers/gpu/drm/omapdrm/omap_connector.h |   2 -
 drivers/gpu/drm/omapdrm/omap_drv.c       |   8 +-
 6 files changed, 22 insertions(+), 310 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 5d6adbb1d547..6e0b5384746b 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -320,47 +320,6 @@ static void hdmi_disconnect(struct omap_dss_device *src,
 	omapdss_device_disconnect(dst, dst->next);
 }
 
-#define MAX_EDID	512
-
-static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi,
-					struct drm_connector *connector)
-{
-	u8 *edid;
-	int r;
-
-	edid = kzalloc(MAX_EDID, GFP_KERNEL);
-	if (!edid)
-		return NULL;
-
-	r = hdmi4_core_ddc_read(&hdmi->core, edid, 0, EDID_LENGTH);
-	if (r)
-		goto error;
-
-	if (edid[0x7e] > 0) {
-		char checksum = 0;
-		unsigned int i;
-
-		r = hdmi4_core_ddc_read(&hdmi->core, edid + EDID_LENGTH, 1,
-					EDID_LENGTH);
-		if (r)
-			goto error;
-
-		for (i = 0; i < EDID_LENGTH; ++i)
-			checksum += edid[EDID_LENGTH + i];
-
-		if (checksum != 0) {
-			DSSERR("E-EDID checksum failed!!\n");
-			goto error;
-		}
-	}
-
-	return (struct edid *)edid;
-
-error:
-	kfree(edid);
-	return NULL;
-}
-
 static struct edid *
 hdmi_do_read_edid(struct omap_hdmi *hdmi,
 		  struct edid *(*read)(struct omap_hdmi *hdmi,
@@ -410,28 +369,9 @@ hdmi_do_read_edid(struct omap_hdmi *hdmi,
 	return edid;
 }
 
-static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
-{
-	return hdmi_do_read_edid(dssdev_to_hdmi(dssdev), hdmi_read_edid_data,
-				 NULL);
-}
-
-static void hdmi_lost_hotplug(struct omap_dss_device *dssdev)
-{
-	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
-
-	hdmi4_cec_set_phys_addr(&hdmi->core, CEC_PHYS_ADDR_INVALID);
-}
-
 static const struct omap_dss_device_ops hdmi_ops = {
 	.connect		= hdmi_connect,
 	.disconnect		= hdmi_disconnect,
-
-	.read_edid		= hdmi_read_edid,
-
-	.hdmi = {
-		.lost_hotplug		= hdmi_lost_hotplug,
-	},
 };
 
 /* -----------------------------------------------------------------------------
@@ -799,7 +739,6 @@ static int hdmi4_init_output(struct omap_hdmi *hdmi)
 	out->ops = &hdmi_ops;
 	out->owner = THIS_MODULE;
 	out->of_port = 0;
-	out->ops_flags = OMAP_DSS_DEVICE_OP_EDID;
 
 	r = omapdss_device_init_output(out, &hdmi->bridge);
 	if (r < 0)
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 74300fea86cc..7c150d641458 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -318,43 +318,6 @@ static void hdmi_disconnect(struct omap_dss_device *src,
 	omapdss_device_disconnect(dst, dst->next);
 }
 
-#define MAX_EDID	512
-
-static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi,
-					struct drm_connector *connector)
-{
-	struct hdmi_core_data *core = &hdmi->core;
-	int max_ext_blocks = 3;
-	int r, n, i;
-	u8 *edid;
-
-	edid = kzalloc(MAX_EDID, GFP_KERNEL);
-	if (!edid)
-		return NULL;
-
-	r = hdmi5_core_ddc_read(core, edid, 0, EDID_LENGTH);
-	if (r)
-		goto error;
-
-	n = edid[0x7e];
-
-	if (n > max_ext_blocks)
-		n = max_ext_blocks;
-
-	for (i = 1; i <= n; i++) {
-		r = hdmi5_core_ddc_read(core, edid + i * EDID_LENGTH, i,
-					EDID_LENGTH);
-		if (r)
-			goto error;
-	}
-
-	return (struct edid *)edid;
-
-error:
-	kfree(edid);
-	return NULL;
-}
-
 static struct edid *
 hdmi_do_read_edid(struct omap_hdmi *hdmi,
 		  struct edid *(*read)(struct omap_hdmi *hdmi,
@@ -399,17 +362,9 @@ hdmi_do_read_edid(struct omap_hdmi *hdmi,
 	return (struct edid *)edid;
 }
 
-static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
-{
-	return hdmi_do_read_edid(dssdev_to_hdmi(dssdev), hdmi_read_edid_data,
-				 NULL);
-}
-
 static const struct omap_dss_device_ops hdmi_ops = {
 	.connect		= hdmi_connect,
 	.disconnect		= hdmi_disconnect,
-
-	.read_edid		= hdmi_read_edid,
 };
 
 /* -----------------------------------------------------------------------------
@@ -758,7 +713,6 @@ static int hdmi5_init_output(struct omap_hdmi *hdmi)
 	out->ops = &hdmi_ops;
 	out->owner = THIS_MODULE;
 	out->of_port = 0;
-	out->ops_flags = OMAP_DSS_DEVICE_OP_EDID;
 
 	r = omapdss_device_init_output(out, &hdmi->bridge);
 	if (r < 0)
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 30a12cf91cbb..cb79e05c902d 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -285,10 +285,6 @@ struct omap_dss_writeback_info {
 	u8 pre_mult_alpha;
 };
 
-struct omapdss_hdmi_ops {
-	void (*lost_hotplug)(struct omap_dss_device *dssdev);
-};
-
 struct omapdss_dsi_ops {
 	void (*disable)(struct omap_dss_device *dssdev, bool disconnect_lanes,
 			bool enter_ulps);
@@ -356,36 +352,17 @@ struct omap_dss_device_ops {
 	void (*set_timings)(struct omap_dss_device *dssdev,
 			    const struct drm_display_mode *mode);
 
-	bool (*detect)(struct omap_dss_device *dssdev);
-
-	void (*register_hpd_cb)(struct omap_dss_device *dssdev,
-				void (*cb)(void *cb_data,
-					  enum drm_connector_status status),
-				void *cb_data);
-	void (*unregister_hpd_cb)(struct omap_dss_device *dssdev);
-
-	struct edid *(*read_edid)(struct omap_dss_device *dssdev);
-
 	int (*get_modes)(struct omap_dss_device *dssdev,
 			 struct drm_connector *connector);
 
-	union {
-		const struct omapdss_hdmi_ops hdmi;
-		const struct omapdss_dsi_ops dsi;
-	};
+	const struct omapdss_dsi_ops dsi;
 };
 
 /**
  * enum omap_dss_device_ops_flag - Indicates which device ops are supported
- * @OMAP_DSS_DEVICE_OP_DETECT: The device supports output connection detection
- * @OMAP_DSS_DEVICE_OP_HPD: The device supports all hot-plug-related operations
- * @OMAP_DSS_DEVICE_OP_EDID: The device supports reading EDID
  * @OMAP_DSS_DEVICE_OP_MODES: The device supports reading modes
  */
 enum omap_dss_device_ops_flag {
-	OMAP_DSS_DEVICE_OP_DETECT = BIT(0),
-	OMAP_DSS_DEVICE_OP_HPD = BIT(1),
-	OMAP_DSS_DEVICE_OP_EDID = BIT(2),
 	OMAP_DSS_DEVICE_OP_MODES = BIT(3),
 };
 
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
index c636ae228130..baa31ed1f993 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -19,111 +19,22 @@
 struct omap_connector {
 	struct drm_connector base;
 	struct omap_dss_device *output;
-	struct omap_dss_device *hpd;
 };
 
-static void omap_connector_hpd_notify(struct drm_connector *connector,
-				      enum drm_connector_status status)
-{
-	struct omap_connector *omap_connector = to_omap_connector(connector);
-	struct omap_dss_device *dssdev;
-
-	if (status != connector_status_disconnected)
-		return;
-
-	/*
-	 * Notify all devics in the pipeline of disconnection. This is required
-	 * to let the HDMI encoders reset their internal state related to
-	 * connection status, such as the CEC address.
-	 */
-	for (dssdev = omap_connector->output; dssdev; dssdev = dssdev->next) {
-		if (dssdev->ops && dssdev->ops->hdmi.lost_hotplug)
-			dssdev->ops->hdmi.lost_hotplug(dssdev);
-	}
-}
-
-static void omap_connector_hpd_cb(void *cb_data,
-				  enum drm_connector_status status)
-{
-	struct omap_connector *omap_connector = cb_data;
-	struct drm_connector *connector = &omap_connector->base;
-	struct drm_device *dev = connector->dev;
-	enum drm_connector_status old_status;
-
-	mutex_lock(&dev->mode_config.mutex);
-	old_status = connector->status;
-	connector->status = status;
-	mutex_unlock(&dev->mode_config.mutex);
-
-	if (old_status == status)
-		return;
-
-	omap_connector_hpd_notify(connector, status);
-
-	drm_kms_helper_hotplug_event(dev);
-}
-
-void omap_connector_enable_hpd(struct drm_connector *connector)
-{
-	struct omap_connector *omap_connector = to_omap_connector(connector);
-	struct omap_dss_device *hpd = omap_connector->hpd;
-
-	if (hpd)
-		hpd->ops->register_hpd_cb(hpd, omap_connector_hpd_cb,
-					  omap_connector);
-}
-
-void omap_connector_disable_hpd(struct drm_connector *connector)
-{
-	struct omap_connector *omap_connector = to_omap_connector(connector);
-	struct omap_dss_device *hpd = omap_connector->hpd;
-
-	if (hpd)
-		hpd->ops->unregister_hpd_cb(hpd);
-}
-
-static struct omap_dss_device *
-omap_connector_find_device(struct drm_connector *connector,
-			   enum omap_dss_device_ops_flag op)
-{
-	struct omap_connector *omap_connector = to_omap_connector(connector);
-	struct omap_dss_device *dssdev = NULL;
-	struct omap_dss_device *d;
-
-	for (d = omap_connector->output; d; d = d->next) {
-		if (d->ops_flags & op)
-			dssdev = d;
-	}
-
-	return dssdev;
-}
-
 static enum drm_connector_status omap_connector_detect(
 		struct drm_connector *connector, bool force)
 {
-	struct omap_dss_device *dssdev;
 	enum drm_connector_status status;
 
-	dssdev = omap_connector_find_device(connector,
-					    OMAP_DSS_DEVICE_OP_DETECT);
-
-	if (dssdev) {
-		status = dssdev->ops->detect(dssdev)
-		       ? connector_status_connected
-		       : connector_status_disconnected;
-
-		omap_connector_hpd_notify(connector, status);
-	} else {
-		switch (connector->connector_type) {
-		case DRM_MODE_CONNECTOR_DPI:
-		case DRM_MODE_CONNECTOR_LVDS:
-		case DRM_MODE_CONNECTOR_DSI:
-			status = connector_status_connected;
-			break;
-		default:
-			status = connector_status_unknown;
-			break;
-		}
+	switch (connector->connector_type) {
+	case DRM_MODE_CONNECTOR_DPI:
+	case DRM_MODE_CONNECTOR_LVDS:
+	case DRM_MODE_CONNECTOR_DSI:
+		status = connector_status_connected;
+		break;
+	default:
+		status = connector_status_unknown;
+		break;
 	}
 
 	VERB("%s: %d (force=%d)", connector->name, status, force);
@@ -137,14 +48,6 @@ static void omap_connector_destroy(struct drm_connector *connector)
 
 	DBG("%s", connector->name);
 
-	if (omap_connector->hpd) {
-		struct omap_dss_device *hpd = omap_connector->hpd;
-
-		hpd->ops->unregister_hpd_cb(hpd);
-		omapdss_device_put(hpd);
-		omap_connector->hpd = NULL;
-	}
-
 	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 
@@ -153,63 +56,27 @@ static void omap_connector_destroy(struct drm_connector *connector)
 	kfree(omap_connector);
 }
 
-static int omap_connector_get_modes_edid(struct drm_connector *connector,
-					 struct omap_dss_device *dssdev)
-{
-	enum drm_connector_status status;
-	struct edid *edid;
-	int n;
-
-	status = omap_connector_detect(connector, false);
-	if (status != connector_status_connected)
-		goto no_edid;
-
-	edid = dssdev->ops->read_edid(dssdev);
-	if (!edid || !drm_edid_is_valid(edid)) {
-		kfree(edid);
-		goto no_edid;
-	}
-
-	drm_connector_update_edid_property(connector, edid);
-	n = drm_add_edid_modes(connector, edid);
-
-	kfree(edid);
-	return n;
-
-no_edid:
-	drm_connector_update_edid_property(connector, NULL);
-	return 0;
-}
-
 static int omap_connector_get_modes(struct drm_connector *connector)
 {
-	struct omap_dss_device *dssdev;
+	struct omap_connector *omap_connector = to_omap_connector(connector);
+	struct omap_dss_device *dssdev = NULL;
+	struct omap_dss_device *d;
 
 	DBG("%s", connector->name);
 
 	/*
-	 * If display exposes EDID, then we parse that in the normal way to
-	 * build table of supported modes.
+	 * If the display pipeline reports modes (e.g. with a fixed resolution
+	 * panel or an analog TV output), query it.
 	 */
-	dssdev = omap_connector_find_device(connector,
-					    OMAP_DSS_DEVICE_OP_EDID);
-	if (dssdev)
-		return omap_connector_get_modes_edid(connector, dssdev);
+	for (d = omap_connector->output; d; d = d->next) {
+		if (d->ops_flags & OMAP_DSS_DEVICE_OP_MODES)
+			dssdev = d;
+	}
 
-	/*
-	 * Otherwise if the display pipeline reports modes (e.g. with a fixed
-	 * resolution panel or an analog TV output), query it.
-	 */
-	dssdev = omap_connector_find_device(connector,
-					    OMAP_DSS_DEVICE_OP_MODES);
 	if (dssdev)
 		return dssdev->ops->get_modes(dssdev, connector);
 
-	/*
-	 * We can't retrieve modes, which can happen for instance for a DVI or
-	 * VGA output with the DDC bus unconnected. The KMS core will add the
-	 * default modes.
-	 */
+	/* We can't retrieve modes. The KMS core will add the default modes. */
 	return 0;
 }
 
@@ -290,7 +157,6 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
 {
 	struct drm_connector *connector = NULL;
 	struct omap_connector *omap_connector;
-	struct omap_dss_device *dssdev;
 
 	DBG("%s", output->name);
 
@@ -308,24 +174,6 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
 			   omap_connector_get_type(output));
 	drm_connector_helper_add(connector, &omap_connector_helper_funcs);
 
-	/*
-	 * Initialize connector status handling. First try to find a device that
-	 * supports hot-plug reporting. If it fails, fall back to a device that
-	 * support polling. If that fails too, we don't support hot-plug
-	 * detection at all.
-	 */
-	dssdev = omap_connector_find_device(connector, OMAP_DSS_DEVICE_OP_HPD);
-	if (dssdev) {
-		omap_connector->hpd = omapdss_device_get(dssdev);
-		connector->polled = DRM_CONNECTOR_POLL_HPD;
-	} else {
-		dssdev = omap_connector_find_device(connector,
-						    OMAP_DSS_DEVICE_OP_DETECT);
-		if (dssdev)
-			connector->polled = DRM_CONNECTOR_POLL_CONNECT |
-					    DRM_CONNECTOR_POLL_DISCONNECT;
-	}
-
 	return connector;
 
 fail:
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.h b/drivers/gpu/drm/omapdrm/omap_connector.h
index 4aa5608f4bbe..0ecd4f1655b7 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.h
+++ b/drivers/gpu/drm/omapdrm/omap_connector.h
@@ -21,8 +21,6 @@ struct omap_dss_device;
 struct drm_connector *omap_connector_init(struct drm_device *dev,
 					  struct omap_dss_device *output,
 					  struct drm_encoder *encoder);
-void omap_connector_enable_hpd(struct drm_connector *connector);
-void omap_connector_disable_hpd(struct drm_connector *connector);
 enum drm_mode_status omap_connector_mode_fixup(struct omap_dss_device *dssdev,
 					const struct drm_display_mode *mode,
 					struct drm_display_mode *adjusted_mode);
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index f38d95cb31ba..f4a7572e4737 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -429,9 +429,7 @@ static void omap_modeset_enable_external_hpd(struct drm_device *ddev)
 		if (!connector)
 			continue;
 
-		if (priv->pipes[i].output->next)
-			omap_connector_enable_hpd(connector);
-		else
+		if (priv->pipes[i].output->bridge)
 			drm_bridge_connector_enable_hpd(connector);
 	}
 }
@@ -450,9 +448,7 @@ static void omap_modeset_disable_external_hpd(struct drm_device *ddev)
 		if (!connector)
 			continue;
 
-		if (priv->pipes[i].output->next)
-			omap_connector_disable_hpd(connector);
-		else
+		if (priv->pipes[i].output->bridge)
 			drm_bridge_connector_disable_hpd(connector);
 	}
 }
-- 
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] 106+ messages in thread

* [PATCH v2 37/50] drm/omap: hdmi: Remove omap_dss_device operations
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (35 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 36/50] drm/omap: Remove HPD, detect and EDID omapdss operations Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-20  1:17 ` [PATCH v2 38/50] drm/omap: venc: " Laurent Pinchart
                   ` (13 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Now that the HDMI outputs are driven fully through the drm_bridge API
their omap_dss_device operations are not used anymore. Remove them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/hdmi.h  |  1 -
 drivers/gpu/drm/omapdrm/dss/hdmi4.c | 18 ------------------
 drivers/gpu/drm/omapdrm/dss/hdmi5.c | 18 ------------------
 3 files changed, 37 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi.h b/drivers/gpu/drm/omapdrm/dss/hdmi.h
index bd43f6abf27b..3a40833d3368 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi.h
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi.h
@@ -380,7 +380,6 @@ struct omap_hdmi {
 	bool display_enabled;
 };
 
-#define dssdev_to_hdmi(dssdev) container_of(dssdev, struct omap_hdmi, output)
 #define drm_bridge_to_hdmi(b) container_of(b, struct omap_hdmi, bridge)
 
 #endif
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 6e0b5384746b..bfe32eb3f282 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -308,18 +308,6 @@ void hdmi4_core_disable(struct hdmi_core_data *core)
 	mutex_unlock(&hdmi->lock);
 }
 
-static int hdmi_connect(struct omap_dss_device *src,
-			struct omap_dss_device *dst)
-{
-	return omapdss_device_connect(dst->dss, dst, dst->next);
-}
-
-static void hdmi_disconnect(struct omap_dss_device *src,
-			    struct omap_dss_device *dst)
-{
-	omapdss_device_disconnect(dst, dst->next);
-}
-
 static struct edid *
 hdmi_do_read_edid(struct omap_hdmi *hdmi,
 		  struct edid *(*read)(struct omap_hdmi *hdmi,
@@ -369,11 +357,6 @@ hdmi_do_read_edid(struct omap_hdmi *hdmi,
 	return edid;
 }
 
-static const struct omap_dss_device_ops hdmi_ops = {
-	.connect		= hdmi_connect,
-	.disconnect		= hdmi_disconnect,
-};
-
 /* -----------------------------------------------------------------------------
  * DRM Bridge Operations
  */
@@ -736,7 +719,6 @@ static int hdmi4_init_output(struct omap_hdmi *hdmi)
 	out->type = OMAP_DISPLAY_TYPE_HDMI;
 	out->name = "hdmi.0";
 	out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
-	out->ops = &hdmi_ops;
 	out->owner = THIS_MODULE;
 	out->of_port = 0;
 
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 7c150d641458..68e5a74e0772 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -306,18 +306,6 @@ static void hdmi_core_disable(struct omap_hdmi *hdmi)
 	mutex_unlock(&hdmi->lock);
 }
 
-static int hdmi_connect(struct omap_dss_device *src,
-			struct omap_dss_device *dst)
-{
-	return omapdss_device_connect(dst->dss, dst, dst->next);
-}
-
-static void hdmi_disconnect(struct omap_dss_device *src,
-			    struct omap_dss_device *dst)
-{
-	omapdss_device_disconnect(dst, dst->next);
-}
-
 static struct edid *
 hdmi_do_read_edid(struct omap_hdmi *hdmi,
 		  struct edid *(*read)(struct omap_hdmi *hdmi,
@@ -362,11 +350,6 @@ hdmi_do_read_edid(struct omap_hdmi *hdmi,
 	return (struct edid *)edid;
 }
 
-static const struct omap_dss_device_ops hdmi_ops = {
-	.connect		= hdmi_connect,
-	.disconnect		= hdmi_disconnect,
-};
-
 /* -----------------------------------------------------------------------------
  * DRM Bridge Operations
  */
@@ -710,7 +693,6 @@ static int hdmi5_init_output(struct omap_hdmi *hdmi)
 	out->type = OMAP_DISPLAY_TYPE_HDMI;
 	out->name = "hdmi.0";
 	out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
-	out->ops = &hdmi_ops;
 	out->owner = THIS_MODULE;
 	out->of_port = 0;
 
-- 
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] 106+ messages in thread

* [PATCH v2 38/50] drm/omap: venc: Remove omap_dss_device operations
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (36 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 37/50] drm/omap: hdmi: Remove omap_dss_device operations Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-20  1:17 ` [PATCH v2 39/50] drm/omap: hdmi4: Simplify EDID read Laurent Pinchart
                   ` (12 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Now that the VENC output is driven fully through the drm_bridge API its
omap_dss_device operations are not used anymore. Remove them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/venc.c | 45 ------------------------------
 1 file changed, 45 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c
index cc775e8b9978..fe0a0b159d44 100644
--- a/drivers/gpu/drm/omapdrm/dss/venc.c
+++ b/drivers/gpu/drm/omapdrm/dss/venc.c
@@ -308,7 +308,6 @@ struct venc_device {
 	struct drm_bridge bridge;
 };
 
-#define dssdev_to_venc(dssdev) container_of(dssdev, struct venc_device, output)
 #define drm_bridge_to_venc(b) container_of(b, struct venc_device, bridge)
 
 static inline void venc_write_reg(struct venc_device *venc, int idx, u32 val)
@@ -481,30 +480,6 @@ static void venc_power_off(struct venc_device *venc)
 	venc_runtime_put(venc);
 }
 
-static int venc_get_modes(struct omap_dss_device *dssdev,
-			  struct drm_connector *connector)
-{
-	static const struct drm_display_mode *modes[] = {
-		&omap_dss_pal_mode,
-		&omap_dss_ntsc_mode,
-	};
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(modes); ++i) {
-		struct drm_display_mode *mode;
-
-		mode = drm_mode_duplicate(connector->dev, modes[i]);
-		if (!mode)
-			return i;
-
-		mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
-		drm_mode_set_name(mode);
-		drm_mode_probed_add(connector, mode);
-	}
-
-	return ARRAY_SIZE(modes);
-}
-
 static enum venc_videomode venc_get_videomode(const struct drm_display_mode *mode)
 {
 	if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
@@ -600,25 +575,6 @@ static int venc_get_clocks(struct venc_device *venc)
 	return 0;
 }
 
-static int venc_connect(struct omap_dss_device *src,
-			struct omap_dss_device *dst)
-{
-	return omapdss_device_connect(dst->dss, dst, dst->next);
-}
-
-static void venc_disconnect(struct omap_dss_device *src,
-			    struct omap_dss_device *dst)
-{
-	omapdss_device_disconnect(dst, dst->next);
-}
-
-static const struct omap_dss_device_ops venc_ops = {
-	.connect = venc_connect,
-	.disconnect = venc_disconnect,
-
-	.get_modes = venc_get_modes,
-};
-
 /* -----------------------------------------------------------------------------
  * DRM Bridge Operations
  */
@@ -827,7 +783,6 @@ static int venc_init_output(struct venc_device *venc)
 	out->type = OMAP_DISPLAY_TYPE_VENC;
 	out->name = "venc.0";
 	out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
-	out->ops = &venc_ops;
 	out->owner = THIS_MODULE;
 	out->of_port = 0;
 	out->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
-- 
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] 106+ messages in thread

* [PATCH v2 39/50] drm/omap: hdmi4: Simplify EDID read
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (37 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 38/50] drm/omap: venc: " Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-20  1:17 ` [PATCH v2 40/50] drm/omap: hdmi5: " Laurent Pinchart
                   ` (11 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Now that the omap_dss_device EDID read operation has been removed,
simplify the bridge-based EDID access by merging multiple functions
together.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c | 96 ++++++++++++-----------------
 1 file changed, 40 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index bfe32eb3f282..38e5af61d8a5 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -308,55 +308,6 @@ void hdmi4_core_disable(struct hdmi_core_data *core)
 	mutex_unlock(&hdmi->lock);
 }
 
-static struct edid *
-hdmi_do_read_edid(struct omap_hdmi *hdmi,
-		  struct edid *(*read)(struct omap_hdmi *hdmi,
-				       struct drm_connector *connector),
-		  struct drm_connector *connector)
-{
-	struct edid *edid = NULL;
-	unsigned int cec_addr;
-	bool need_enable;
-	int r;
-
-	need_enable = hdmi->core_enabled == false;
-
-	if (need_enable) {
-		r = hdmi4_core_enable(&hdmi->core);
-		if (r)
-			return NULL;
-	}
-
-	mutex_lock(&hdmi->lock);
-	r = hdmi_runtime_get(hdmi);
-	BUG_ON(r);
-
-	r = hdmi4_core_ddc_init(&hdmi->core);
-	if (r)
-		goto done;
-
-	edid = read(hdmi, connector);
-
-done:
-	hdmi_runtime_put(hdmi);
-	mutex_unlock(&hdmi->lock);
-
-	if (edid && edid->extensions) {
-		unsigned int len = (edid->extensions + 1) * EDID_LENGTH;
-
-		cec_addr = cec_get_edid_phys_addr((u8 *)edid, len, NULL);
-	} else {
-		cec_addr = CEC_PHYS_ADDR_INVALID;
-	}
-
-	hdmi4_cec_set_phys_addr(&hdmi->core, cec_addr);
-
-	if (need_enable)
-		hdmi4_core_disable(&hdmi->core);
-
-	return edid;
-}
-
 /* -----------------------------------------------------------------------------
  * DRM Bridge Operations
  */
@@ -483,18 +434,51 @@ static void hdmi4_bridge_hpd_notify(struct drm_bridge *bridge,
 		hdmi4_cec_set_phys_addr(&hdmi->core, CEC_PHYS_ADDR_INVALID);
 }
 
-static struct edid *hdmi4_bridge_read_edid(struct omap_hdmi *hdmi,
-					   struct drm_connector *connector)
-{
-	return drm_do_get_edid(connector, hdmi4_core_ddc_read, &hdmi->core);
-}
-
 static struct edid *hdmi4_bridge_get_edid(struct drm_bridge *bridge,
 					  struct drm_connector *connector)
 {
 	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+	struct edid *edid = NULL;
+	unsigned int cec_addr;
+	bool need_enable;
+	int r;
 
-	return hdmi_do_read_edid(hdmi, hdmi4_bridge_read_edid, connector);
+	need_enable = hdmi->core_enabled == false;
+
+	if (need_enable) {
+		r = hdmi4_core_enable(&hdmi->core);
+		if (r)
+			return NULL;
+	}
+
+	mutex_lock(&hdmi->lock);
+	r = hdmi_runtime_get(hdmi);
+	BUG_ON(r);
+
+	r = hdmi4_core_ddc_init(&hdmi->core);
+	if (r)
+		goto done;
+
+	edid = drm_do_get_edid(connector, hdmi4_core_ddc_read, &hdmi->core);
+
+done:
+	hdmi_runtime_put(hdmi);
+	mutex_unlock(&hdmi->lock);
+
+	if (edid && edid->extensions) {
+		unsigned int len = (edid->extensions + 1) * EDID_LENGTH;
+
+		cec_addr = cec_get_edid_phys_addr((u8 *)edid, len, NULL);
+	} else {
+		cec_addr = CEC_PHYS_ADDR_INVALID;
+	}
+
+	hdmi4_cec_set_phys_addr(&hdmi->core, cec_addr);
+
+	if (need_enable)
+		hdmi4_core_disable(&hdmi->core);
+
+	return edid;
 }
 
 static const struct drm_bridge_funcs hdmi4_bridge_funcs = {
-- 
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] 106+ messages in thread

* [PATCH v2 40/50] drm/omap: hdmi5: Simplify EDID read
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (38 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 39/50] drm/omap: hdmi4: Simplify EDID read Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-20  1:17 ` [PATCH v2 41/50] drm/omap: dpi: Sort includes alphabetically Laurent Pinchart
                   ` (10 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Now that the omap_dss_device EDID read operation has been removed,
simplify the bridge-based EDID access by merging multiple functions
together.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/hdmi5.c | 86 ++++++++++++-----------------
 1 file changed, 35 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index 68e5a74e0772..5d4dbd32722b 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -306,50 +306,6 @@ static void hdmi_core_disable(struct omap_hdmi *hdmi)
 	mutex_unlock(&hdmi->lock);
 }
 
-static struct edid *
-hdmi_do_read_edid(struct omap_hdmi *hdmi,
-		  struct edid *(*read)(struct omap_hdmi *hdmi,
-				       struct drm_connector *connector),
-		  struct drm_connector *connector)
-{
-	struct edid *edid;
-	bool need_enable;
-	int idlemode;
-	int r;
-
-	need_enable = hdmi->core_enabled == false;
-
-	if (need_enable) {
-		r = hdmi_core_enable(hdmi);
-		if (r)
-			return NULL;
-	}
-
-	mutex_lock(&hdmi->lock);
-	r = hdmi_runtime_get(hdmi);
-	BUG_ON(r);
-
-	idlemode = REG_GET(hdmi->wp.base, HDMI_WP_SYSCONFIG, 3, 2);
-	/* No-idle mode */
-	REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
-
-	hdmi5_core_ddc_init(&hdmi->core);
-
-	edid = read(hdmi, connector);
-
-	hdmi5_core_ddc_uninit(&hdmi->core);
-
-	REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, idlemode, 3, 2);
-
-	hdmi_runtime_put(hdmi);
-	mutex_unlock(&hdmi->lock);
-
-	if (need_enable)
-		hdmi_core_disable(hdmi);
-
-	return (struct edid *)edid;
-}
-
 /* -----------------------------------------------------------------------------
  * DRM Bridge Operations
  */
@@ -467,18 +423,46 @@ static void hdmi5_bridge_disable(struct drm_bridge *bridge,
 	mutex_unlock(&hdmi->lock);
 }
 
-static struct edid *hdmi5_bridge_read_edid(struct omap_hdmi *hdmi,
-					   struct drm_connector *connector)
-{
-	return drm_do_get_edid(connector, hdmi5_core_ddc_read, &hdmi->core);
-}
-
 static struct edid *hdmi5_bridge_get_edid(struct drm_bridge *bridge,
 					  struct drm_connector *connector)
 {
 	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
+	struct edid *edid;
+	bool need_enable;
+	int idlemode;
+	int r;
 
-	return hdmi_do_read_edid(hdmi, hdmi5_bridge_read_edid, connector);
+	need_enable = hdmi->core_enabled == false;
+
+	if (need_enable) {
+		r = hdmi_core_enable(hdmi);
+		if (r)
+			return NULL;
+	}
+
+	mutex_lock(&hdmi->lock);
+	r = hdmi_runtime_get(hdmi);
+	BUG_ON(r);
+
+	idlemode = REG_GET(hdmi->wp.base, HDMI_WP_SYSCONFIG, 3, 2);
+	/* No-idle mode */
+	REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
+
+	hdmi5_core_ddc_init(&hdmi->core);
+
+	edid = drm_do_get_edid(connector, hdmi5_core_ddc_read, &hdmi->core);
+
+	hdmi5_core_ddc_uninit(&hdmi->core);
+
+	REG_FLD_MOD(hdmi->wp.base, HDMI_WP_SYSCONFIG, idlemode, 3, 2);
+
+	hdmi_runtime_put(hdmi);
+	mutex_unlock(&hdmi->lock);
+
+	if (need_enable)
+		hdmi_core_disable(hdmi);
+
+	return (struct edid *)edid;
 }
 
 static const struct drm_bridge_funcs hdmi5_bridge_funcs = {
-- 
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] 106+ messages in thread

* [PATCH v2 41/50] drm/omap: dpi: Sort includes alphabetically
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (39 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 40/50] drm/omap: hdmi5: " Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-20  1:17 ` [PATCH v2 42/50] drm/omap: dpi: Reorder functions in sections Laurent Pinchart
                   ` (9 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

This makes it easier to quickly locate duplicate includes.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/dpi.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c
index 2d0eb5fcbb5b..f8354271ce6f 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -9,20 +9,20 @@
 
 #define DSS_SUBSYS_NAME "DPI"
 
-#include <linux/kernel.h>
+#include <linux/clk.h>
 #include <linux/delay.h>
-#include <linux/export.h>
 #include <linux/err.h>
 #include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/string.h>
-#include <linux/of.h>
-#include <linux/clk.h>
 #include <linux/sys_soc.h>
 
-#include "omapdss.h"
 #include "dss.h"
+#include "omapdss.h"
 
 struct dpi_data {
 	struct platform_device *pdev;
-- 
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] 106+ messages in thread

* [PATCH v2 42/50] drm/omap: dpi: Reorder functions in sections
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (40 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 41/50] drm/omap: dpi: Sort includes alphabetically Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-20  1:17 ` [PATCH v2 43/50] drm/omap: dpi: Simplify clock setting API Laurent Pinchart
                   ` (8 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Group functions based on their purpose and split them in sections to
make the source code easier to navigate.

No functional change is included.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/dpi.c | 146 ++++++++++++++++--------------
 1 file changed, 79 insertions(+), 67 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c
index f8354271ce6f..dccf81e4ce64 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -48,6 +48,10 @@ static struct dpi_data *dpi_get_data_from_dssdev(struct omap_dss_device *dssdev)
 	return container_of(dssdev, struct dpi_data, output);
 }
 
+/* -----------------------------------------------------------------------------
+ * Clock Handling and PLL
+ */
+
 static enum dss_clk_source dpi_get_clk_src_dra7xx(struct dpi_data *dpi,
 						  enum omap_channel channel)
 {
@@ -366,6 +370,62 @@ static void dpi_config_lcd_manager(struct dpi_data *dpi)
 	dss_mgr_set_lcd_config(&dpi->output, &dpi->mgr_config);
 }
 
+static int dpi_verify_pll(struct dss_pll *pll)
+{
+	int r;
+
+	/* do initial setup with the PLL to see if it is operational */
+
+	r = dss_pll_enable(pll);
+	if (r)
+		return r;
+
+	dss_pll_disable(pll);
+
+	return 0;
+}
+
+static void dpi_init_pll(struct dpi_data *dpi)
+{
+	struct dss_pll *pll;
+
+	if (dpi->pll)
+		return;
+
+	dpi->clk_src = dpi_get_clk_src(dpi);
+
+	pll = dss_pll_find_by_src(dpi->dss, dpi->clk_src);
+	if (!pll)
+		return;
+
+	if (dpi_verify_pll(pll)) {
+		DSSWARN("PLL not operational\n");
+		return;
+	}
+
+	dpi->pll = pll;
+}
+
+/* -----------------------------------------------------------------------------
+ * omap_dss_device Operations
+ */
+
+static int dpi_connect(struct omap_dss_device *src,
+		       struct omap_dss_device *dst)
+{
+	struct dpi_data *dpi = dpi_get_data_from_dssdev(dst);
+
+	dpi_init_pll(dpi);
+
+	return omapdss_device_connect(dst->dss, dst, dst->next);
+}
+
+static void dpi_disconnect(struct omap_dss_device *src,
+			   struct omap_dss_device *dst)
+{
+	omapdss_device_disconnect(dst, dst->next);
+}
+
 static void dpi_display_enable(struct omap_dss_device *dssdev)
 {
 	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
@@ -446,20 +506,6 @@ static void dpi_display_disable(struct omap_dss_device *dssdev)
 	mutex_unlock(&dpi->lock);
 }
 
-static void dpi_set_timings(struct omap_dss_device *dssdev,
-			    const struct drm_display_mode *mode)
-{
-	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
-
-	DSSDBG("dpi_set_timings\n");
-
-	mutex_lock(&dpi->lock);
-
-	dpi->pixelclock = mode->clock * 1000;
-
-	mutex_unlock(&dpi->lock);
-}
-
 static int dpi_check_timings(struct omap_dss_device *dssdev,
 			     struct drm_display_mode *mode)
 {
@@ -500,41 +546,30 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
 	return 0;
 }
 
-static int dpi_verify_pll(struct dss_pll *pll)
+static void dpi_set_timings(struct omap_dss_device *dssdev,
+			    const struct drm_display_mode *mode)
 {
-	int r;
+	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
 
-	/* do initial setup with the PLL to see if it is operational */
+	DSSDBG("dpi_set_timings\n");
 
-	r = dss_pll_enable(pll);
-	if (r)
-		return r;
+	mutex_lock(&dpi->lock);
 
-	dss_pll_disable(pll);
+	dpi->pixelclock = mode->clock * 1000;
 
-	return 0;
+	mutex_unlock(&dpi->lock);
 }
 
-static void dpi_init_pll(struct dpi_data *dpi)
-{
-	struct dss_pll *pll;
-
-	if (dpi->pll)
-		return;
-
-	dpi->clk_src = dpi_get_clk_src(dpi);
+static const struct omap_dss_device_ops dpi_ops = {
+	.connect = dpi_connect,
+	.disconnect = dpi_disconnect,
 
-	pll = dss_pll_find_by_src(dpi->dss, dpi->clk_src);
-	if (!pll)
-		return;
+	.enable = dpi_display_enable,
+	.disable = dpi_display_disable,
 
-	if (dpi_verify_pll(pll)) {
-		DSSWARN("PLL not operational\n");
-		return;
-	}
-
-	dpi->pll = pll;
-}
+	.check_timings = dpi_check_timings,
+	.set_timings = dpi_set_timings,
+};
 
 /*
  * Return a hardcoded channel for the DPI output. This should work for
@@ -572,33 +607,6 @@ static enum omap_channel dpi_get_channel(struct dpi_data *dpi)
 	}
 }
 
-static int dpi_connect(struct omap_dss_device *src,
-		       struct omap_dss_device *dst)
-{
-	struct dpi_data *dpi = dpi_get_data_from_dssdev(dst);
-
-	dpi_init_pll(dpi);
-
-	return omapdss_device_connect(dst->dss, dst, dst->next);
-}
-
-static void dpi_disconnect(struct omap_dss_device *src,
-			   struct omap_dss_device *dst)
-{
-	omapdss_device_disconnect(dst, dst->next);
-}
-
-static const struct omap_dss_device_ops dpi_ops = {
-	.connect = dpi_connect,
-	.disconnect = dpi_disconnect,
-
-	.enable = dpi_display_enable,
-	.disable = dpi_display_disable,
-
-	.check_timings = dpi_check_timings,
-	.set_timings = dpi_set_timings,
-};
-
 static int dpi_init_output_port(struct dpi_data *dpi, struct device_node *port)
 {
 	struct omap_dss_device *out = &dpi->output;
@@ -647,6 +655,10 @@ static void dpi_uninit_output_port(struct device_node *port)
 	omapdss_device_cleanup_output(out);
 }
 
+/* -----------------------------------------------------------------------------
+ * Initialisation and Cleanup
+ */
+
 static const struct soc_device_attribute dpi_soc_devices[] = {
 	{ .machine = "OMAP3[456]*" },
 	{ .machine = "[AD]M37*" },
-- 
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] 106+ messages in thread

* [PATCH v2 43/50] drm/omap: dpi: Simplify clock setting API
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (41 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 42/50] drm/omap: dpi: Reorder functions in sections Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-20  1:17 ` [PATCH v2 44/50] drm/omap: dpi: Register a drm_bridge Laurent Pinchart
                   ` (7 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

The dpi_set_pll_clk() and dpi_set_dispc_clk() return various information
through pointer arguments that are never used by the callers. Remove
them to simplify the clock setting API.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/dpi.c | 32 ++++++++-----------------------
 1 file changed, 8 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c
index dccf81e4ce64..c167bd1116ec 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -287,9 +287,7 @@ static bool dpi_dss_clk_calc(struct dpi_data *dpi, unsigned long pck,
 
 
 
-static int dpi_set_pll_clk(struct dpi_data *dpi, enum omap_channel channel,
-		unsigned long pck_req, unsigned long *fck, int *lck_div,
-		int *pck_div)
+static int dpi_set_pll_clk(struct dpi_data *dpi, unsigned long pck_req)
 {
 	struct dpi_clk_calc_ctx ctx;
 	int r;
@@ -303,19 +301,15 @@ static int dpi_set_pll_clk(struct dpi_data *dpi, enum omap_channel channel,
 	if (r)
 		return r;
 
-	dss_select_lcd_clk_source(dpi->dss, channel, dpi->clk_src);
+	dss_select_lcd_clk_source(dpi->dss, dpi->output.dispc_channel,
+				  dpi->clk_src);
 
 	dpi->mgr_config.clock_info = ctx.dispc_cinfo;
 
-	*fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
-	*lck_div = ctx.dispc_cinfo.lck_div;
-	*pck_div = ctx.dispc_cinfo.pck_div;
-
 	return 0;
 }
 
-static int dpi_set_dispc_clk(struct dpi_data *dpi, unsigned long pck_req,
-		unsigned long *fck, int *lck_div, int *pck_div)
+static int dpi_set_dispc_clk(struct dpi_data *dpi, unsigned long pck_req)
 {
 	struct dpi_clk_calc_ctx ctx;
 	int r;
@@ -331,29 +325,19 @@ static int dpi_set_dispc_clk(struct dpi_data *dpi, unsigned long pck_req,
 
 	dpi->mgr_config.clock_info = ctx.dispc_cinfo;
 
-	*fck = ctx.fck;
-	*lck_div = ctx.dispc_cinfo.lck_div;
-	*pck_div = ctx.dispc_cinfo.pck_div;
-
 	return 0;
 }
 
 static int dpi_set_mode(struct dpi_data *dpi)
 {
-	int lck_div = 0, pck_div = 0;
-	unsigned long fck = 0;
-	int r = 0;
+	int r;
 
 	if (dpi->pll)
-		r = dpi_set_pll_clk(dpi, dpi->output.dispc_channel,
-				    dpi->pixelclock, &fck, &lck_div, &pck_div);
+		r = dpi_set_pll_clk(dpi, dpi->pixelclock);
 	else
-		r = dpi_set_dispc_clk(dpi, dpi->pixelclock, &fck,
-				&lck_div, &pck_div);
-	if (r)
-		return r;
+		r = dpi_set_dispc_clk(dpi, dpi->pixelclock);
 
-	return 0;
+	return r;
 }
 
 static void dpi_config_lcd_manager(struct dpi_data *dpi)
-- 
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] 106+ messages in thread

* [PATCH v2 44/50] drm/omap: dpi: Register a drm_bridge
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (42 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 43/50] drm/omap: dpi: Simplify clock setting API Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-27  9:07   ` Hans Verkuil
  2019-08-20  1:17 ` [PATCH v2 45/50] drm/omap: sdi: Sort includes alphabetically Laurent Pinchart
                   ` (6 subsequent siblings)
  50 siblings, 1 reply; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

In order to integrate with a chain of drm_bridge, the internal DPI
output has to expose its operations through the drm_bridge API.
Register a bridge at initialisation time to do so and remove the
omap_dss_device operations that are now unused.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/dpi.c | 205 ++++++++++++++++++------------
 1 file changed, 122 insertions(+), 83 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c
index c167bd1116ec..3874e6b6ec49 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -21,6 +21,8 @@
 #include <linux/string.h>
 #include <linux/sys_soc.h>
 
+#include <drm/drm_bridge.h>
+
 #include "dss.h"
 #include "omapdss.h"
 
@@ -41,12 +43,10 @@ struct dpi_data {
 	int data_lines;
 
 	struct omap_dss_device output;
+	struct drm_bridge bridge;
 };
 
-static struct dpi_data *dpi_get_data_from_dssdev(struct omap_dss_device *dssdev)
-{
-	return container_of(dssdev, struct dpi_data, output);
-}
+#define drm_bridge_to_dpi(bridge) container_of(bridge, struct dpi_data, bridge)
 
 /* -----------------------------------------------------------------------------
  * Clock Handling and PLL
@@ -354,6 +354,32 @@ static void dpi_config_lcd_manager(struct dpi_data *dpi)
 	dss_mgr_set_lcd_config(&dpi->output, &dpi->mgr_config);
 }
 
+static int dpi_clock_update(struct dpi_data *dpi, unsigned long *clock)
+{
+	int lck_div, pck_div;
+	unsigned long fck;
+	struct dpi_clk_calc_ctx ctx;
+
+	if (dpi->pll) {
+		if (!dpi_pll_clk_calc(dpi, *clock, &ctx))
+			return -EINVAL;
+
+		fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
+	} else {
+		if (!dpi_dss_clk_calc(dpi, *clock, &ctx))
+			return -EINVAL;
+
+		fck = ctx.fck;
+	}
+
+	lck_div = ctx.dispc_cinfo.lck_div;
+	pck_div = ctx.dispc_cinfo.pck_div;
+
+	*clock = fck / lck_div / pck_div;
+
+	return 0;
+}
+
 static int dpi_verify_pll(struct dss_pll *pll)
 {
 	int r;
@@ -391,29 +417,76 @@ static void dpi_init_pll(struct dpi_data *dpi)
 }
 
 /* -----------------------------------------------------------------------------
- * omap_dss_device Operations
+ * DRM Bridge Operations
  */
 
-static int dpi_connect(struct omap_dss_device *src,
-		       struct omap_dss_device *dst)
+static int dpi_bridge_attach(struct drm_bridge *bridge,
+			     enum drm_bridge_attach_flags flags)
 {
-	struct dpi_data *dpi = dpi_get_data_from_dssdev(dst);
+	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
+
+	if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
+		return -EINVAL;
 
 	dpi_init_pll(dpi);
 
-	return omapdss_device_connect(dst->dss, dst, dst->next);
+	return drm_bridge_attach(bridge->encoder, dpi->output.next_bridge,
+				 bridge, flags);
 }
 
-static void dpi_disconnect(struct omap_dss_device *src,
-			   struct omap_dss_device *dst)
+static enum drm_mode_status
+dpi_bridge_mode_valid(struct drm_bridge *bridge,
+		       const struct drm_display_mode *mode)
 {
-	omapdss_device_disconnect(dst, dst->next);
+	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
+	unsigned long clock = mode->clock * 1000;
+	int ret;
+
+	if (mode->hdisplay % 8 != 0)
+		return MODE_BAD_WIDTH;
+
+	if (mode->clock == 0)
+		return MODE_NOCLOCK;
+
+	ret = dpi_clock_update(dpi, &clock);
+	if (ret < 0)
+		return MODE_CLOCK_RANGE;
+
+	return MODE_OK;
+}
+
+static bool dpi_bridge_mode_fixup(struct drm_bridge *bridge,
+				   const struct drm_display_mode *mode,
+				   struct drm_display_mode *adjusted_mode)
+{
+	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
+	unsigned long clock = mode->clock * 1000;
+	int ret;
+
+	ret = dpi_clock_update(dpi, &clock);
+	if (ret < 0)
+		return false;
+
+	adjusted_mode->clock = clock / 1000;
+
+	return true;
+}
+
+static void dpi_bridge_mode_set(struct drm_bridge *bridge,
+				 const struct drm_display_mode *mode,
+				 const struct drm_display_mode *adjusted_mode)
+{
+	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
+
+	mutex_lock(&dpi->lock);
+	dpi->pixelclock = adjusted_mode->clock * 1000;
+	mutex_unlock(&dpi->lock);
 }
 
-static void dpi_display_enable(struct omap_dss_device *dssdev)
+static void dpi_bridge_enable(struct drm_bridge *bridge,
+			       struct drm_atomic_state *state)
 {
-	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
-	struct omap_dss_device *out = &dpi->output;
+	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
 	int r;
 
 	mutex_lock(&dpi->lock);
@@ -428,7 +501,7 @@ static void dpi_display_enable(struct omap_dss_device *dssdev)
 	if (r)
 		goto err_get_dispc;
 
-	r = dss_dpi_select_source(dpi->dss, dpi->id, out->dispc_channel);
+	r = dss_dpi_select_source(dpi->dss, dpi->id, dpi->output.dispc_channel);
 	if (r)
 		goto err_src_sel;
 
@@ -468,9 +541,10 @@ static void dpi_display_enable(struct omap_dss_device *dssdev)
 	mutex_unlock(&dpi->lock);
 }
 
-static void dpi_display_disable(struct omap_dss_device *dssdev)
+static void dpi_bridge_disable(struct drm_bridge *bridge,
+				struct drm_atomic_state *state)
 {
-	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
+	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
 
 	mutex_lock(&dpi->lock);
 
@@ -490,71 +564,33 @@ static void dpi_display_disable(struct omap_dss_device *dssdev)
 	mutex_unlock(&dpi->lock);
 }
 
-static int dpi_check_timings(struct omap_dss_device *dssdev,
-			     struct drm_display_mode *mode)
-{
-	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
-	int lck_div, pck_div;
-	unsigned long fck;
-	unsigned long pck;
-	struct dpi_clk_calc_ctx ctx;
-	bool ok;
-
-	if (mode->hdisplay % 8 != 0)
-		return -EINVAL;
-
-	if (mode->clock == 0)
-		return -EINVAL;
-
-	if (dpi->pll) {
-		ok = dpi_pll_clk_calc(dpi, mode->clock * 1000, &ctx);
-		if (!ok)
-			return -EINVAL;
-
-		fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
-	} else {
-		ok = dpi_dss_clk_calc(dpi, mode->clock * 1000, &ctx);
-		if (!ok)
-			return -EINVAL;
-
-		fck = ctx.fck;
-	}
-
-	lck_div = ctx.dispc_cinfo.lck_div;
-	pck_div = ctx.dispc_cinfo.pck_div;
-
-	pck = fck / lck_div / pck_div;
-
-	mode->clock = pck / 1000;
-
-	return 0;
-}
-
-static void dpi_set_timings(struct omap_dss_device *dssdev,
-			    const struct drm_display_mode *mode)
-{
-	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
-
-	DSSDBG("dpi_set_timings\n");
-
-	mutex_lock(&dpi->lock);
-
-	dpi->pixelclock = mode->clock * 1000;
-
-	mutex_unlock(&dpi->lock);
-}
-
-static const struct omap_dss_device_ops dpi_ops = {
-	.connect = dpi_connect,
-	.disconnect = dpi_disconnect,
-
-	.enable = dpi_display_enable,
-	.disable = dpi_display_disable,
-
-	.check_timings = dpi_check_timings,
-	.set_timings = dpi_set_timings,
+static const struct drm_bridge_funcs dpi_bridge_funcs = {
+	.attach = dpi_bridge_attach,
+	.mode_valid = dpi_bridge_mode_valid,
+	.mode_fixup = dpi_bridge_mode_fixup,
+	.mode_set = dpi_bridge_mode_set,
+	.atomic_enable = dpi_bridge_enable,
+	.atomic_disable = dpi_bridge_disable,
 };
 
+static void dpi_bridge_init(struct dpi_data *dpi)
+{
+	dpi->bridge.funcs = &dpi_bridge_funcs;
+	dpi->bridge.of_node = dpi->pdev->dev.of_node;
+	dpi->bridge.type = DRM_MODE_CONNECTOR_DPI;
+
+	drm_bridge_add(&dpi->bridge);
+}
+
+static void dpi_bridge_cleanup(struct dpi_data *dpi)
+{
+	drm_bridge_remove(&dpi->bridge);
+}
+
+/* -----------------------------------------------------------------------------
+ * Initialisation and Cleanup
+ */
+
 /*
  * Return a hardcoded channel for the DPI output. This should work for
  * current use cases, but this can be later expanded to either resolve
@@ -597,6 +633,8 @@ static int dpi_init_output_port(struct dpi_data *dpi, struct device_node *port)
 	u32 port_num = 0;
 	int r;
 
+	dpi_bridge_init(dpi);
+
 	of_property_read_u32(port, "reg", &port_num);
 	dpi->id = port_num <= 2 ? port_num : 0;
 
@@ -618,10 +656,9 @@ static int dpi_init_output_port(struct dpi_data *dpi, struct device_node *port)
 	out->type = OMAP_DISPLAY_TYPE_DPI;
 	out->dispc_channel = dpi_get_channel(dpi);
 	out->of_port = port_num;
-	out->ops = &dpi_ops;
 	out->owner = THIS_MODULE;
 
-	r = omapdss_device_init_output(out, NULL);
+	r = omapdss_device_init_output(out, &dpi->bridge);
 	if (r < 0)
 		return r;
 
@@ -637,6 +674,8 @@ static void dpi_uninit_output_port(struct device_node *port)
 
 	omapdss_device_unregister(out);
 	omapdss_device_cleanup_output(out);
+
+	dpi_bridge_cleanup(dpi);
 }
 
 /* -----------------------------------------------------------------------------
-- 
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] 106+ messages in thread

* [PATCH v2 45/50] drm/omap: sdi: Sort includes alphabetically
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (43 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 44/50] drm/omap: dpi: Register a drm_bridge Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-20  1:17 ` [PATCH v2 46/50] drm/omap: sdi: Register a drm_bridge Laurent Pinchart
                   ` (5 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

This makes it easier to quickly locate duplicate includes.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/sdi.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c
index 11aa2f712ff4..7dedfcc86922 100644
--- a/drivers/gpu/drm/omapdrm/dss/sdi.c
+++ b/drivers/gpu/drm/omapdrm/dss/sdi.c
@@ -6,17 +6,17 @@
 
 #define DSS_SUBSYS_NAME "SDI"
 
-#include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/err.h>
-#include <linux/regulator/consumer.h>
 #include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
 #include <linux/string.h>
-#include <linux/of.h>
 
-#include "omapdss.h"
 #include "dss.h"
+#include "omapdss.h"
 
 struct sdi_device {
 	struct platform_device *pdev;
-- 
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] 106+ messages in thread

* [PATCH v2 46/50] drm/omap: sdi: Register a drm_bridge
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (44 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 45/50] drm/omap: sdi: Sort includes alphabetically Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-20  1:17 ` [PATCH v2 47/50] drm/omap: Simplify connector implementation Laurent Pinchart
                   ` (4 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

In order to integrate with a chain of drm_bridge, the internal SDI
output has to expose its operations through the drm_bridge API.
Register a bridge at initialisation time to do so and remove the
omap_dss_device operations that are now unused.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/sdi.c | 178 +++++++++++++++++++-----------
 1 file changed, 113 insertions(+), 65 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c
index 7dedfcc86922..6927b67a9a4b 100644
--- a/drivers/gpu/drm/omapdrm/dss/sdi.c
+++ b/drivers/gpu/drm/omapdrm/dss/sdi.c
@@ -15,6 +15,8 @@
 #include <linux/regulator/consumer.h>
 #include <linux/string.h>
 
+#include <drm/drm_bridge.h>
+
 #include "dss.h"
 #include "omapdss.h"
 
@@ -30,9 +32,11 @@ struct sdi_device {
 	int datapairs;
 
 	struct omap_dss_device output;
+	struct drm_bridge bridge;
 };
 
-#define dssdev_to_sdi(dssdev) container_of(dssdev, struct sdi_device, output)
+#define drm_bridge_to_sdi(bridge) \
+	container_of(bridge, struct sdi_device, bridge)
 
 struct sdi_clk_calc_ctx {
 	struct sdi_device *sdi;
@@ -118,9 +122,82 @@ static void sdi_config_lcd_manager(struct sdi_device *sdi)
 	dss_mgr_set_lcd_config(&sdi->output, &sdi->mgr_config);
 }
 
-static void sdi_display_enable(struct omap_dss_device *dssdev)
+/* -----------------------------------------------------------------------------
+ * DRM Bridge Operations
+ */
+
+static int sdi_bridge_attach(struct drm_bridge *bridge,
+			     enum drm_bridge_attach_flags flags)
 {
-	struct sdi_device *sdi = dssdev_to_sdi(dssdev);
+	struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
+
+	if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
+		return -EINVAL;
+
+	return drm_bridge_attach(bridge->encoder, sdi->output.next_bridge,
+				 bridge, flags);
+}
+
+static enum drm_mode_status
+sdi_bridge_mode_valid(struct drm_bridge *bridge,
+		      const struct drm_display_mode *mode)
+{
+	struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
+	unsigned long pixelclock = mode->clock * 1000;
+	struct dispc_clock_info dispc_cinfo;
+	unsigned long fck;
+	int ret;
+
+	if (pixelclock == 0)
+		return MODE_NOCLOCK;
+
+	ret = sdi_calc_clock_div(sdi, pixelclock, &fck, &dispc_cinfo);
+	if (ret < 0)
+		return MODE_CLOCK_RANGE;
+
+	return MODE_OK;
+}
+
+static bool sdi_bridge_mode_fixup(struct drm_bridge *bridge,
+				  const struct drm_display_mode *mode,
+				  struct drm_display_mode *adjusted_mode)
+{
+	struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
+	unsigned long pixelclock = mode->clock * 1000;
+	struct dispc_clock_info dispc_cinfo;
+	unsigned long fck;
+	unsigned long pck;
+	int ret;
+
+	ret = sdi_calc_clock_div(sdi, pixelclock, &fck, &dispc_cinfo);
+	if (ret < 0)
+		return false;
+
+	pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div;
+
+	if (pck != pixelclock)
+		dev_dbg(&sdi->pdev->dev,
+			"pixel clock adjusted from %lu Hz to %lu Hz\n",
+			pixelclock, pck);
+
+	adjusted_mode->clock = pck / 1000;
+
+	return true;
+}
+
+static void sdi_bridge_mode_set(struct drm_bridge *bridge,
+				const struct drm_display_mode *mode,
+				const struct drm_display_mode *adjusted_mode)
+{
+	struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
+
+	sdi->pixelclock = adjusted_mode->clock * 1000;
+}
+
+static void sdi_bridge_enable(struct drm_bridge *bridge,
+			      struct drm_atomic_state *state)
+{
+	struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
 	struct dispc_clock_info dispc_cinfo;
 	unsigned long fck;
 	int r;
@@ -181,9 +258,10 @@ static void sdi_display_enable(struct omap_dss_device *dssdev)
 	regulator_disable(sdi->vdds_sdi_reg);
 }
 
-static void sdi_display_disable(struct omap_dss_device *dssdev)
+static void sdi_bridge_disable(struct drm_bridge *bridge,
+			       struct drm_atomic_state *state)
 {
-	struct sdi_device *sdi = dssdev_to_sdi(dssdev);
+	struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
 
 	dss_mgr_disable(&sdi->output);
 
@@ -194,71 +272,40 @@ static void sdi_display_disable(struct omap_dss_device *dssdev)
 	regulator_disable(sdi->vdds_sdi_reg);
 }
 
-static void sdi_set_timings(struct omap_dss_device *dssdev,
-			    const struct drm_display_mode *mode)
-{
-	struct sdi_device *sdi = dssdev_to_sdi(dssdev);
-
-	sdi->pixelclock = mode->clock * 1000;
-}
-
-static int sdi_check_timings(struct omap_dss_device *dssdev,
-			     struct drm_display_mode *mode)
-{
-	struct sdi_device *sdi = dssdev_to_sdi(dssdev);
-	struct dispc_clock_info dispc_cinfo;
-	unsigned long pixelclock = mode->clock * 1000;
-	unsigned long fck;
-	unsigned long pck;
-	int r;
-
-	if (pixelclock == 0)
-		return -EINVAL;
-
-	r = sdi_calc_clock_div(sdi, pixelclock, &fck, &dispc_cinfo);
-	if (r)
-		return r;
-
-	pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div;
-
-	if (pck != pixelclock) {
-		DSSWARN("Pixel clock adjusted from %lu Hz to %lu Hz\n",
-			pixelclock, pck);
-
-		mode->clock = pck / 1000;
-	}
-
-	return 0;
-}
-
-static int sdi_connect(struct omap_dss_device *src,
-		       struct omap_dss_device *dst)
-{
-	return omapdss_device_connect(dst->dss, dst, dst->next);
-}
-
-static void sdi_disconnect(struct omap_dss_device *src,
-			   struct omap_dss_device *dst)
-{
-	omapdss_device_disconnect(dst, dst->next);
-}
-
-static const struct omap_dss_device_ops sdi_ops = {
-	.connect = sdi_connect,
-	.disconnect = sdi_disconnect,
-
-	.enable = sdi_display_enable,
-	.disable = sdi_display_disable,
-
-	.check_timings = sdi_check_timings,
-	.set_timings = sdi_set_timings,
+static const struct drm_bridge_funcs sdi_bridge_funcs = {
+	.attach = sdi_bridge_attach,
+	.mode_valid = sdi_bridge_mode_valid,
+	.mode_fixup = sdi_bridge_mode_fixup,
+	.mode_set = sdi_bridge_mode_set,
+	.atomic_enable = sdi_bridge_enable,
+	.atomic_disable = sdi_bridge_disable,
 };
 
+static void sdi_bridge_init(struct sdi_device *sdi)
+{
+	sdi->bridge.funcs = &sdi_bridge_funcs;
+	sdi->bridge.of_node = sdi->pdev->dev.of_node;
+	sdi->bridge.type = DRM_MODE_CONNECTOR_LVDS;
+
+	drm_bridge_add(&sdi->bridge);
+}
+
+static void sdi_bridge_cleanup(struct sdi_device *sdi)
+{
+	drm_bridge_remove(&sdi->bridge);
+}
+
+/* -----------------------------------------------------------------------------
+ * Initialisation and Cleanup
+ */
+
 static int sdi_init_output(struct sdi_device *sdi)
 {
 	struct omap_dss_device *out = &sdi->output;
 	int r;
 
+	sdi_bridge_init(sdi);
+
 	out->dev = &sdi->pdev->dev;
 	out->id = OMAP_DSS_OUTPUT_SDI;
 	out->type = OMAP_DISPLAY_TYPE_SDI;
@@ -266,12 +313,11 @@ static int sdi_init_output(struct sdi_device *sdi)
 	out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
 	/* We have SDI only on OMAP3, where it's on port 1 */
 	out->of_port = 1;
-	out->ops = &sdi_ops;
 	out->owner = THIS_MODULE;
 	out->bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE	/* 15.5.9.1.2 */
 		       | DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE;
 
-	r = omapdss_device_init_output(out, NULL);
+	r = omapdss_device_init_output(out, &sdi->bridge);
 	if (r < 0)
 		return r;
 
@@ -284,6 +330,8 @@ static void sdi_uninit_output(struct sdi_device *sdi)
 {
 	omapdss_device_unregister(&sdi->output);
 	omapdss_device_cleanup_output(&sdi->output);
+
+	sdi_bridge_cleanup(sdi);
 }
 
 int sdi_init_port(struct dss_device *dss, struct platform_device *pdev,
-- 
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] 106+ messages in thread

* [PATCH v2 47/50] drm/omap: Simplify connector implementation
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (45 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 46/50] drm/omap: sdi: Register a drm_bridge Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-20  1:17 ` [PATCH v2 48/50] drm/omap: dss: Remove unused omap_dss_device operations Laurent Pinchart
                   ` (3 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Now that the omap_connector is used for DSI only we can simplify its
implementation.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v1:

- Remove export of omapdss_device_connector_type()
---
 drivers/gpu/drm/omapdrm/dss/base.c       |  1 -
 drivers/gpu/drm/omapdrm/omap_connector.c | 31 ++----------------------
 2 files changed, 2 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/base.c b/drivers/gpu/drm/omapdrm/dss/base.c
index 2db3bd2f19db..389e2c1b4909 100644
--- a/drivers/gpu/drm/omapdrm/dss/base.c
+++ b/drivers/gpu/drm/omapdrm/dss/base.c
@@ -307,7 +307,6 @@ unsigned int omapdss_device_connector_type(enum omap_display_type type)
 		return DRM_MODE_CONNECTOR_Unknown;
 	}
 }
-EXPORT_SYMBOL_GPL(omapdss_device_connector_type);
 
 /* -----------------------------------------------------------------------------
  * Components Handling
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
index baa31ed1f993..528764566b17 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -24,22 +24,7 @@ struct omap_connector {
 static enum drm_connector_status omap_connector_detect(
 		struct drm_connector *connector, bool force)
 {
-	enum drm_connector_status status;
-
-	switch (connector->connector_type) {
-	case DRM_MODE_CONNECTOR_DPI:
-	case DRM_MODE_CONNECTOR_LVDS:
-	case DRM_MODE_CONNECTOR_DSI:
-		status = connector_status_connected;
-		break;
-	default:
-		status = connector_status_unknown;
-		break;
-	}
-
-	VERB("%s: %d (force=%d)", connector->name, status, force);
-
-	return status;
+	return connector_status_connected;
 }
 
 static void omap_connector_destroy(struct drm_connector *connector)
@@ -138,18 +123,6 @@ static const struct drm_connector_helper_funcs omap_connector_helper_funcs = {
 	.mode_valid = omap_connector_mode_valid,
 };
 
-static int omap_connector_get_type(struct omap_dss_device *output)
-{
-	struct omap_dss_device *display;
-	enum omap_display_type type;
-
-	display = omapdss_display_get(output);
-	type = display->type;
-	omapdss_device_put(display);
-
-	return omapdss_device_connector_type(type);
-}
-
 /* initialize connector */
 struct drm_connector *omap_connector_init(struct drm_device *dev,
 					  struct omap_dss_device *output,
@@ -171,7 +144,7 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
 	connector->doublescan_allowed = 0;
 
 	drm_connector_init(dev, connector, &omap_connector_funcs,
-			   omap_connector_get_type(output));
+			   DRM_MODE_CONNECTOR_DSI);
 	drm_connector_helper_add(connector, &omap_connector_helper_funcs);
 
 	return connector;
-- 
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] 106+ messages in thread

* [PATCH v2 48/50] drm/omap: dss: Remove unused omap_dss_device operations
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (46 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 47/50] drm/omap: Simplify connector implementation Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-20  1:17 ` [PATCH v2 49/50] drm/omap: dss: Inline the omapdss_display_get() function Laurent Pinchart
                   ` (2 subsequent siblings)
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

The omap_dss_device .pre_enable(), .post_disable() and .set_timings()
are not used anymore. Remove them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/base.c     | 26 ---------------
 drivers/gpu/drm/omapdrm/dss/omapdss.h  |  6 ----
 drivers/gpu/drm/omapdrm/omap_encoder.c | 44 +++-----------------------
 3 files changed, 5 insertions(+), 71 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/base.c b/drivers/gpu/drm/omapdrm/dss/base.c
index 389e2c1b4909..92a9473bd9b2 100644
--- a/drivers/gpu/drm/omapdrm/dss/base.c
+++ b/drivers/gpu/drm/omapdrm/dss/base.c
@@ -234,18 +234,6 @@ void omapdss_device_disconnect(struct omap_dss_device *src,
 }
 EXPORT_SYMBOL_GPL(omapdss_device_disconnect);
 
-void omapdss_device_pre_enable(struct omap_dss_device *dssdev)
-{
-	if (!dssdev)
-		return;
-
-	omapdss_device_pre_enable(dssdev->next);
-
-	if (dssdev->ops && dssdev->ops->pre_enable)
-		dssdev->ops->pre_enable(dssdev);
-}
-EXPORT_SYMBOL_GPL(omapdss_device_pre_enable);
-
 void omapdss_device_enable(struct omap_dss_device *dssdev)
 {
 	if (!dssdev)
@@ -272,20 +260,6 @@ void omapdss_device_disable(struct omap_dss_device *dssdev)
 }
 EXPORT_SYMBOL_GPL(omapdss_device_disable);
 
-void omapdss_device_post_disable(struct omap_dss_device *dssdev)
-{
-	if (!dssdev)
-		return;
-
-	if (dssdev->ops && dssdev->ops->post_disable)
-		dssdev->ops->post_disable(dssdev);
-
-	omapdss_device_post_disable(dssdev->next);
-
-	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-EXPORT_SYMBOL_GPL(omapdss_device_post_disable);
-
 unsigned int omapdss_device_connector_type(enum omap_display_type type)
 {
 	switch (type) {
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index cb79e05c902d..e7418a74f722 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -342,15 +342,11 @@ struct omap_dss_device_ops {
 	void (*disconnect)(struct omap_dss_device *dssdev,
 			struct omap_dss_device *dst);
 
-	void (*pre_enable)(struct omap_dss_device *dssdev);
 	void (*enable)(struct omap_dss_device *dssdev);
 	void (*disable)(struct omap_dss_device *dssdev);
-	void (*post_disable)(struct omap_dss_device *dssdev);
 
 	int (*check_timings)(struct omap_dss_device *dssdev,
 			     struct drm_display_mode *mode);
-	void (*set_timings)(struct omap_dss_device *dssdev,
-			    const struct drm_display_mode *mode);
 
 	int (*get_modes)(struct omap_dss_device *dssdev,
 			 struct drm_connector *connector);
@@ -450,10 +446,8 @@ int omapdss_device_connect(struct dss_device *dss,
 			   struct omap_dss_device *dst);
 void omapdss_device_disconnect(struct omap_dss_device *src,
 			       struct omap_dss_device *dst);
-void omapdss_device_pre_enable(struct omap_dss_device *dssdev);
 void omapdss_device_enable(struct omap_dss_device *dssdev);
 void omapdss_device_disable(struct omap_dss_device *dssdev);
-void omapdss_device_post_disable(struct omap_dss_device *dssdev);
 unsigned int omapdss_device_connector_type(enum omap_display_type type);
 
 int omap_dss_get_num_overlay_managers(void);
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
index 1545d30f26e0..83ab5bb897c4 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -111,13 +111,8 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
 	bus_flags = connector->display_info.bus_flags;
 	omap_encoder_update_videomode_flags(&vm, bus_flags);
 
-	/* Set timings for all devices in the display pipeline. */
+	/* Set timings for the dss manager. */
 	dss_mgr_set_timings(output, &vm);
-
-	for (dssdev = output; dssdev; dssdev = dssdev->next) {
-		if (dssdev->ops && dssdev->ops->set_timings)
-			dssdev->ops->set_timings(dssdev, adjusted_mode);
-	}
 }
 
 static void omap_encoder_disable(struct drm_encoder *encoder)
@@ -130,26 +125,10 @@ static void omap_encoder_disable(struct drm_encoder *encoder)
 
 	/*
 	 * Disable the chain of external devices, starting at the one at the
-	 * internal encoder's output.
+	 * internal encoder's output. This is used for DSI outputs only, as
+	 * dssdev->next is NULL for all other outputs.
 	 */
 	omapdss_device_disable(dssdev->next);
-
-	/*
-	 * Disable the internal encoder. This will disable the DSS output. The
-	 * DSI is treated as an exception as DSI pipelines still use the legacy
-	 * flow where the pipeline output controls the encoder.
-	 */
-	if (dssdev->type != OMAP_DISPLAY_TYPE_DSI) {
-		if (dssdev->ops && dssdev->ops->disable)
-			dssdev->ops->disable(dssdev);
-		dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-	}
-
-	/*
-	 * Perform the post-disable operations on the chain of external devices
-	 * to complete the display pipeline disable.
-	 */
-	omapdss_device_post_disable(dssdev->next);
 }
 
 static void omap_encoder_enable(struct drm_encoder *encoder)
@@ -160,23 +139,10 @@ static void omap_encoder_enable(struct drm_encoder *encoder)
 
 	dev_dbg(dev->dev, "enable(%s)\n", dssdev->name);
 
-	/* Prepare the chain of external devices for pipeline enable. */
-	omapdss_device_pre_enable(dssdev->next);
-
-	/*
-	 * Enable the internal encoder. This will enable the DSS output. The
-	 * DSI is treated as an exception as DSI pipelines still use the legacy
-	 * flow where the pipeline output controls the encoder.
-	 */
-	if (dssdev->type != OMAP_DISPLAY_TYPE_DSI) {
-		if (dssdev->ops && dssdev->ops->enable)
-			dssdev->ops->enable(dssdev);
-		dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-	}
-
 	/*
 	 * Enable the chain of external devices, starting at the one at the
-	 * internal encoder's output.
+	 * internal encoder's output. This is used for DSI outputs only, as
+	 * dssdev->next is NULL for all other outputs.
 	 */
 	omapdss_device_enable(dssdev->next);
 }
-- 
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] 106+ messages in thread

* [PATCH v2 49/50] drm/omap: dss: Inline the omapdss_display_get() function
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (47 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 48/50] drm/omap: dss: Remove unused omap_dss_device operations Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-20  1:17 ` [PATCH v2 50/50] drm/omap: dss: Remove unused omapdss_of_find_connected_device() function Laurent Pinchart
  2019-08-26 12:15 ` [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Tomi Valkeinen
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Inline the omapdss_display_get() in its only caller to simplify the
code.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/display.c | 9 ---------
 drivers/gpu/drm/omapdrm/dss/omapdss.h | 1 -
 drivers/gpu/drm/omapdrm/omap_drv.c    | 7 ++++---
 3 files changed, 4 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c
index 8a3f61f5825f..3b82158b1bfd 100644
--- a/drivers/gpu/drm/omapdrm/dss/display.c
+++ b/drivers/gpu/drm/omapdrm/dss/display.c
@@ -40,15 +40,6 @@ void omapdss_display_init(struct omap_dss_device *dssdev)
 }
 EXPORT_SYMBOL_GPL(omapdss_display_init);
 
-struct omap_dss_device *omapdss_display_get(struct omap_dss_device *output)
-{
-	while (output->next)
-		output = output->next;
-
-	return omapdss_device_get(output);
-}
-EXPORT_SYMBOL_GPL(omapdss_display_get);
-
 int omapdss_display_get_modes(struct drm_connector *connector,
 			      const struct videomode *vm)
 {
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index e7418a74f722..a8d9fc715515 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -432,7 +432,6 @@ static inline bool omapdss_is_initialized(void)
 }
 
 void omapdss_display_init(struct omap_dss_device *dssdev);
-struct omap_dss_device *omapdss_display_get(struct omap_dss_device *output);
 int omapdss_display_get_modes(struct drm_connector *connector,
 			      const struct videomode *vm);
 
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index f4a7572e4737..ff82faf594a3 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -206,11 +206,12 @@ static int omap_display_id(struct omap_dss_device *output)
 	struct device_node *node = NULL;
 
 	if (output->next) {
-		struct omap_dss_device *display;
+		struct omap_dss_device *display = output;
+
+		while (display->next)
+			display = display->next;
 
-		display = omapdss_display_get(output);
 		node = display->dev->of_node;
-		omapdss_device_put(display);
 	} else if (output->bridge) {
 		struct drm_bridge *bridge = output->bridge;
 
-- 
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] 106+ messages in thread

* [PATCH v2 50/50] drm/omap: dss: Remove unused omapdss_of_find_connected_device() function
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (48 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 49/50] drm/omap: dss: Inline the omapdss_display_get() function Laurent Pinchart
@ 2019-08-20  1:17 ` Laurent Pinchart
  2019-08-26 12:15 ` [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Tomi Valkeinen
  50 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20  1:17 UTC (permalink / raw)
  To: dri-devel; +Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

The omapdss_of_find_connected_device() function isn't used anymore,
remove it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/Makefile  |  2 +-
 drivers/gpu/drm/omapdrm/dss/dss-of.c  | 28 ---------------------------
 drivers/gpu/drm/omapdrm/dss/omapdss.h |  3 ---
 3 files changed, 1 insertion(+), 32 deletions(-)
 delete mode 100644 drivers/gpu/drm/omapdrm/dss/dss-of.c

diff --git a/drivers/gpu/drm/omapdrm/dss/Makefile b/drivers/gpu/drm/omapdrm/dss/Makefile
index 904101c5e79d..39e83d6fcb08 100644
--- a/drivers/gpu/drm/omapdrm/dss/Makefile
+++ b/drivers/gpu/drm/omapdrm/dss/Makefile
@@ -2,7 +2,7 @@
 obj-$(CONFIG_OMAP2_DSS_INIT) += omapdss-boot-init.o
 
 obj-$(CONFIG_OMAP_DSS_BASE) += omapdss-base.o
-omapdss-base-y := base.o display.o dss-of.o output.o
+omapdss-base-y := base.o display.o output.o
 
 obj-$(CONFIG_OMAP2_DSS) += omapdss.o
 # Core DSS files
diff --git a/drivers/gpu/drm/omapdrm/dss/dss-of.c b/drivers/gpu/drm/omapdrm/dss/dss-of.c
deleted file mode 100644
index b7981f3b80ad..000000000000
--- a/drivers/gpu/drm/omapdrm/dss/dss-of.c
+++ /dev/null
@@ -1,28 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- */
-
-#include <linux/err.h>
-#include <linux/of.h>
-#include <linux/of_graph.h>
-
-#include "omapdss.h"
-
-struct omap_dss_device *
-omapdss_of_find_connected_device(struct device_node *node, unsigned int port)
-{
-	struct device_node *remote_node;
-	struct omap_dss_device *dssdev;
-
-	remote_node = of_graph_get_remote_node(node, port, 0);
-	if (!remote_node)
-		return NULL;
-
-	dssdev = omapdss_find_device_by_node(remote_node);
-	of_node_put(remote_node);
-
-	return dssdev ? dssdev : ERR_PTR(-EPROBE_DEFER);
-}
-EXPORT_SYMBOL_GPL(omapdss_of_find_connected_device);
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index a8d9fc715515..757ad2a52e1c 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -472,9 +472,6 @@ static inline bool omapdss_device_is_enabled(struct omap_dss_device *dssdev)
 	return dssdev->state == OMAP_DSS_DISPLAY_ACTIVE;
 }
 
-struct omap_dss_device *
-omapdss_of_find_connected_device(struct device_node *node, unsigned int port);
-
 enum dss_writeback_channel {
 	DSS_WB_LCD1_MGR =	0,
 	DSS_WB_LCD2_MGR =	1,
-- 
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] 106+ messages in thread

* Re: [PATCH v2 13/50] drm/bridge: panel: Implement bridge connector operations
  2019-08-20  1:16 ` [PATCH v2 13/50] drm/bridge: panel: Implement bridge connector operations Laurent Pinchart
@ 2019-08-20 10:37   ` Sam Ravnborg
  2019-08-20 16:08     ` Laurent Pinchart
  2019-10-03  5:56     ` Tomi Valkeinen
  2019-08-22 16:29   ` Boris Brezillon
  1 sibling, 2 replies; 106+ messages in thread
From: Sam Ravnborg @ 2019-08-20 10:37 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

Hi Laurent.

On Tue, Aug 20, 2019 at 04:16:44AM +0300, Laurent Pinchart wrote:
> Implement the newly added bridge connector operations, allowing the
> usage of drm_bridge_panel with drm_bridge_connector.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/gpu/drm/bridge/panel.c | 18 +++++++++++++++++-
>  1 file changed, 17 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
> index f5b8e55301ac..1c7f5b648f05 100644
> --- a/drivers/gpu/drm/bridge/panel.c
> +++ b/drivers/gpu/drm/bridge/panel.c
> @@ -60,7 +60,7 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
>  	int ret;
>  
>  	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> -		return -EINVAL;
> +		return 0;
>  
>  	if (!bridge->encoder) {
>  		DRM_ERROR("Missing encoder\n");
> @@ -123,6 +123,18 @@ static void panel_bridge_post_disable(struct drm_bridge *bridge)
>  	drm_panel_unprepare(panel_bridge->panel);
>  }
>  
> +static int panel_bridge_get_modes(struct drm_bridge *bridge,
> +				  struct drm_connector *connector)
> +{
> +	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
> +
> +	/*
> +	 * FIXME: drm_panel_get_modes() should take the connector as an
> +	 * argument.
> +	 */
Noted, I have patches to fix this. Needs a little testing/polishing
before I post them.

> +	return drm_panel_get_modes(panel_bridge->panel);
> +}
> +
>  static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
>  	.attach = panel_bridge_attach,
>  	.detach = panel_bridge_detach,
> @@ -130,6 +142,7 @@ static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
>  	.enable = panel_bridge_enable,
>  	.disable = panel_bridge_disable,
>  	.post_disable = panel_bridge_post_disable,
> +	.get_modes = panel_bridge_get_modes,
>  };
>  
>  /**
> @@ -175,6 +188,9 @@ struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
>  #ifdef CONFIG_OF
>  	panel_bridge->bridge.of_node = panel->dev->of_node;
>  #endif
> +	panel_bridge->bridge.ops = DRM_BRIDGE_OP_MODES;
> +	/* FIXME: The panel should report its type. */
> +	panel_bridge->bridge.type = DRM_MODE_CONNECTOR_DPI;
Confused.
We move the connector to the display controller.
So the panel does not know the type.

In others words - please put a few more words on this FIXME.

	Sam

>  
>  	drm_bridge_add(&panel_bridge->bridge);
>  
> -- 
> Regards,
> 
> Laurent Pinchart
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 01/50] video: hdmi: Change return type of hdmi_avi_infoframe_init() to void
  2019-08-20  1:16 ` [PATCH v2 01/50] video: hdmi: Change return type of hdmi_avi_infoframe_init() to void Laurent Pinchart
@ 2019-08-20 11:18   ` Bartlomiej Zolnierkiewicz
  2019-08-22  9:12   ` Boris Brezillon
  1 sibling, 0 replies; 106+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2019-08-20 11:18 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel


On 8/20/19 3:16 AM, Laurent Pinchart wrote:
> The hdmi_avi_infoframe_init() never needs to return an error, change its
> return type to void.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>

Acked-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

> ---
> Changes since v1:
> 
> - Removed documentation of the return value
> 
> Cc: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> ---
>  drivers/gpu/drm/drm_edid.c |  5 +----
>  drivers/video/hdmi.c       | 11 ++---------
>  include/linux/hdmi.h       |  2 +-
>  3 files changed, 4 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 82a4ceed3fcf..86ddb67c1e8a 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -5083,14 +5083,11 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
>  					 const struct drm_display_mode *mode)
>  {
>  	enum hdmi_picture_aspect picture_aspect;
> -	int err;
>  
>  	if (!frame || !mode)
>  		return -EINVAL;
>  
> -	err = hdmi_avi_infoframe_init(frame);
> -	if (err < 0)
> -		return err;
> +	hdmi_avi_infoframe_init(frame);
>  
>  	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
>  		frame->pixel_repeat = 1;
> diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
> index b939bc28d886..ff4d09592602 100644
> --- a/drivers/video/hdmi.c
> +++ b/drivers/video/hdmi.c
> @@ -53,18 +53,14 @@ static void hdmi_infoframe_set_checksum(void *buffer, size_t size)
>  /**
>   * hdmi_avi_infoframe_init() - initialize an HDMI AVI infoframe
>   * @frame: HDMI AVI infoframe
> - *
> - * Returns 0 on success or a negative error code on failure.
>   */
> -int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
> +void hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
>  {
>  	memset(frame, 0, sizeof(*frame));
>  
>  	frame->type = HDMI_INFOFRAME_TYPE_AVI;
>  	frame->version = 2;
>  	frame->length = HDMI_AVI_INFOFRAME_SIZE;
> -
> -	return 0;
>  }
>  EXPORT_SYMBOL(hdmi_avi_infoframe_init);
>  
> @@ -1553,7 +1549,6 @@ static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame,
>  				     const void *buffer, size_t size)
>  {
>  	const u8 *ptr = buffer;
> -	int ret;
>  
>  	if (size < HDMI_INFOFRAME_SIZE(AVI))
>  		return -EINVAL;
> @@ -1566,9 +1561,7 @@ static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame,
>  	if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AVI)) != 0)
>  		return -EINVAL;
>  
> -	ret = hdmi_avi_infoframe_init(frame);
> -	if (ret)
> -		return ret;
> +	hdmi_avi_infoframe_init(frame);
>  
>  	ptr += HDMI_INFOFRAME_HEADER_SIZE;
>  
> diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h
> index 9918a6c910c5..9613d796cfb1 100644
> --- a/include/linux/hdmi.h
> +++ b/include/linux/hdmi.h
> @@ -207,7 +207,7 @@ struct hdmi_drm_infoframe {
>  	u16 max_fall;
>  };
>  
> -int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame);
> +void hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame);
>  ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
>  				size_t size);
>  ssize_t hdmi_avi_infoframe_pack_only(const struct hdmi_avi_infoframe *frame,
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 13/50] drm/bridge: panel: Implement bridge connector operations
  2019-08-20 10:37   ` Sam Ravnborg
@ 2019-08-20 16:08     ` Laurent Pinchart
  2019-10-03  5:56     ` Tomi Valkeinen
  1 sibling, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-20 16:08 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

Hi Sam,

On Tue, Aug 20, 2019 at 12:37:06PM +0200, Sam Ravnborg wrote:
> On Tue, Aug 20, 2019 at 04:16:44AM +0300, Laurent Pinchart wrote:
> > Implement the newly added bridge connector operations, allowing the
> > usage of drm_bridge_panel with drm_bridge_connector.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/gpu/drm/bridge/panel.c | 18 +++++++++++++++++-
> >  1 file changed, 17 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
> > index f5b8e55301ac..1c7f5b648f05 100644
> > --- a/drivers/gpu/drm/bridge/panel.c
> > +++ b/drivers/gpu/drm/bridge/panel.c
> > @@ -60,7 +60,7 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
> >  	int ret;
> >  
> >  	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> > -		return -EINVAL;
> > +		return 0;
> >  
> >  	if (!bridge->encoder) {
> >  		DRM_ERROR("Missing encoder\n");
> > @@ -123,6 +123,18 @@ static void panel_bridge_post_disable(struct drm_bridge *bridge)
> >  	drm_panel_unprepare(panel_bridge->panel);
> >  }
> >  
> > +static int panel_bridge_get_modes(struct drm_bridge *bridge,
> > +				  struct drm_connector *connector)
> > +{
> > +	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
> > +
> > +	/*
> > +	 * FIXME: drm_panel_get_modes() should take the connector as an
> > +	 * argument.
> > +	 */
>
> Noted, I have patches to fix this. Needs a little testing/polishing
> before I post them.

Take your time. Thank you for addressing this issue :-)

> > +	return drm_panel_get_modes(panel_bridge->panel);
> > +}
> > +
> >  static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
> >  	.attach = panel_bridge_attach,
> >  	.detach = panel_bridge_detach,
> > @@ -130,6 +142,7 @@ static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
> >  	.enable = panel_bridge_enable,
> >  	.disable = panel_bridge_disable,
> >  	.post_disable = panel_bridge_post_disable,
> > +	.get_modes = panel_bridge_get_modes,
> >  };
> >  
> >  /**
> > @@ -175,6 +188,9 @@ struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
> >  #ifdef CONFIG_OF
> >  	panel_bridge->bridge.of_node = panel->dev->of_node;
> >  #endif
> > +	panel_bridge->bridge.ops = DRM_BRIDGE_OP_MODES;
> > +	/* FIXME: The panel should report its type. */
> > +	panel_bridge->bridge.type = DRM_MODE_CONNECTOR_DPI;
>
> Confused.
> We move the connector to the display controller.
> So the panel does not know the type.
> 
> In others words - please put a few more words on this FIXME.

I mean the panel should report if it's a DPI, LVDS, or other type of
panel, so that the display controller will know what to initialise the
connector type to. I think the drm_panel structure should get a type
field, similar to the bridge type field. Does that make sense to you ?

> >  
> >  	drm_bridge_add(&panel_bridge->bridge);
> >  

-- 
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] 106+ messages in thread

* Re: [PATCH v2 01/50] video: hdmi: Change return type of hdmi_avi_infoframe_init() to void
  2019-08-20  1:16 ` [PATCH v2 01/50] video: hdmi: Change return type of hdmi_avi_infoframe_init() to void Laurent Pinchart
  2019-08-20 11:18   ` Bartlomiej Zolnierkiewicz
@ 2019-08-22  9:12   ` Boris Brezillon
  1 sibling, 0 replies; 106+ messages in thread
From: Boris Brezillon @ 2019-08-22  9:12 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Bartlomiej Zolnierkiewicz, Maxime Ripard, Sebastian Reichel,
	dri-devel, Tomi Valkeinen, Sean Paul

On Tue, 20 Aug 2019 04:16:32 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

> The hdmi_avi_infoframe_init() never needs to return an error, change its
> return type to void.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>

> ---
> Changes since v1:
> 
> - Removed documentation of the return value
> 
> Cc: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> ---
>  drivers/gpu/drm/drm_edid.c |  5 +----
>  drivers/video/hdmi.c       | 11 ++---------
>  include/linux/hdmi.h       |  2 +-
>  3 files changed, 4 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 82a4ceed3fcf..86ddb67c1e8a 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -5083,14 +5083,11 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
>  					 const struct drm_display_mode *mode)
>  {
>  	enum hdmi_picture_aspect picture_aspect;
> -	int err;
>  
>  	if (!frame || !mode)
>  		return -EINVAL;
>  
> -	err = hdmi_avi_infoframe_init(frame);
> -	if (err < 0)
> -		return err;
> +	hdmi_avi_infoframe_init(frame);
>  
>  	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
>  		frame->pixel_repeat = 1;
> diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
> index b939bc28d886..ff4d09592602 100644
> --- a/drivers/video/hdmi.c
> +++ b/drivers/video/hdmi.c
> @@ -53,18 +53,14 @@ static void hdmi_infoframe_set_checksum(void *buffer, size_t size)
>  /**
>   * hdmi_avi_infoframe_init() - initialize an HDMI AVI infoframe
>   * @frame: HDMI AVI infoframe
> - *
> - * Returns 0 on success or a negative error code on failure.
>   */
> -int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
> +void hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
>  {
>  	memset(frame, 0, sizeof(*frame));
>  
>  	frame->type = HDMI_INFOFRAME_TYPE_AVI;
>  	frame->version = 2;
>  	frame->length = HDMI_AVI_INFOFRAME_SIZE;
> -
> -	return 0;
>  }
>  EXPORT_SYMBOL(hdmi_avi_infoframe_init);
>  
> @@ -1553,7 +1549,6 @@ static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame,
>  				     const void *buffer, size_t size)
>  {
>  	const u8 *ptr = buffer;
> -	int ret;
>  
>  	if (size < HDMI_INFOFRAME_SIZE(AVI))
>  		return -EINVAL;
> @@ -1566,9 +1561,7 @@ static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame,
>  	if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AVI)) != 0)
>  		return -EINVAL;
>  
> -	ret = hdmi_avi_infoframe_init(frame);
> -	if (ret)
> -		return ret;
> +	hdmi_avi_infoframe_init(frame);
>  
>  	ptr += HDMI_INFOFRAME_HEADER_SIZE;
>  
> diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h
> index 9918a6c910c5..9613d796cfb1 100644
> --- a/include/linux/hdmi.h
> +++ b/include/linux/hdmi.h
> @@ -207,7 +207,7 @@ struct hdmi_drm_infoframe {
>  	u16 max_fall;
>  };
>  
> -int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame);
> +void hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame);
>  ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
>  				size_t size);
>  ssize_t hdmi_avi_infoframe_pack_only(const struct hdmi_avi_infoframe *frame,

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

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

* Re: [PATCH v2 02/50] drm/connector: Add helper to get a connector type name
  2019-08-20  1:16 ` [PATCH v2 02/50] drm/connector: Add helper to get a connector type name Laurent Pinchart
@ 2019-08-22  9:13   ` Boris Brezillon
  0 siblings, 0 replies; 106+ messages in thread
From: Boris Brezillon @ 2019-08-22  9:13 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

On Tue, 20 Aug 2019 04:16:33 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

> drm_connector.c contains a map of connector types (DRM_MODE_CONNECTOR_*)
> to name strings, but doesn't expose it. This leads to drivers having to
> store a similar map.
> 
> Add a new drm_get_connector_type_name() helper function that return a
> name string for a connector type.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>

> ---
>  drivers/gpu/drm/drm_connector.c | 15 +++++++++++++++
>  include/drm/drm_connector.h     |  1 +
>  2 files changed, 16 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 4c766624b20d..3f93633a9ff2 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -111,6 +111,21 @@ void drm_connector_ida_destroy(void)
>  		ida_destroy(&drm_connector_enum_list[i].ida);
>  }
>  
> +/**
> + * drm_get_connector_type_name - return a string for connector type
> + * @type: The connector type (DRM_MODE_CONNECTOR_*)
> + *
> + * Returns: the name of the connector type, or NULL if the type is not valid.
> + */
> +const char *drm_get_connector_type_name(unsigned int type)
> +{
> +	if (type < ARRAY_SIZE(drm_connector_enum_list))
> +		return drm_connector_enum_list[type].name;
> +
> +	return NULL;
> +}
> +EXPORT_SYMBOL(drm_get_connector_type_name);
> +
>  /**
>   * drm_connector_get_cmdline_mode - reads the user's cmdline mode
>   * @connector: connector to quwery
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index 681cb590f952..b91e369cfb11 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -1500,6 +1500,7 @@ drm_connector_is_unregistered(struct drm_connector *connector)
>  		DRM_CONNECTOR_UNREGISTERED;
>  }
>  
> +const char *drm_get_connector_type_name(unsigned int connector_type);
>  const char *drm_get_connector_status_name(enum drm_connector_status status);
>  const char *drm_get_subpixel_order_name(enum subpixel_order order);
>  const char *drm_get_dpms_name(int val);

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

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

* Re: [PATCH v2 03/50] drm/edid: Add flag to drm_display_info to identify HDMI sinks
  2019-08-20  1:16 ` [PATCH v2 03/50] drm/edid: Add flag to drm_display_info to identify HDMI sinks Laurent Pinchart
@ 2019-08-22  9:15   ` Boris Brezillon
  0 siblings, 0 replies; 106+ messages in thread
From: Boris Brezillon @ 2019-08-22  9:15 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

On Tue, 20 Aug 2019 04:16:34 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

> The drm_display_info structure contains many fields related to HDMI
> sinks, but none that identifies if a sink compliant with CEA-861 (EDID)
> shall be treated as an HDMI sink or a DVI sink. Add such a flag, and
> populate it according to section 8.3.3 ("DVI/HDMI Device
> Discrimination") of the HDMI v1.3 specification.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>

> ---
> Changes since v1:
> 
> - Link the is_hdmi field doc with drm_detect_hdmi_monitor()
> - Add a conversion task in todo.rst
> ---
>  Documentation/gpu/todo.rst  | 12 ++++++++++++
>  drivers/gpu/drm/drm_edid.c  |  6 ++++++
>  include/drm/drm_connector.h |  8 ++++++++
>  3 files changed, 26 insertions(+)
> 
> diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
> index 32787acff0a8..199751149e23 100644
> --- a/Documentation/gpu/todo.rst
> +++ b/Documentation/gpu/todo.rst
> @@ -284,6 +284,18 @@ drm_fb_helper tasks
>    removed: drm_fb_helper_single_add_all_connectors(),
>    drm_fb_helper_add_one_connector() and drm_fb_helper_remove_one_connector().
>  
> +Replace drm_detect_hdmi_monitor() with drm_display_info.is_hdmi
> +---------------------------------------------------------------
> +
> +Once EDID is parsed, the monitor HDMI support information is available through
> +drm_display_info.is_hdmi. Many drivers still call drm_detect_hdmi_monitor() to
> +retrieve the same information, which is less efficient.
> +
> +Audit each individual driver calling drm_detect_hdmi_monitor() and switch to
> +drm_display_info.is_hdmi if applicable.
> +
> +Contact: Laurent Pinchart, respective driver maintainers
> +
>  Core refactorings
>  =================
>  
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 86ddb67c1e8a..8be00dda945b 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -4325,6 +4325,9 @@ EXPORT_SYMBOL(drm_av_sync_delay);
>   *
>   * Parse the CEA extension according to CEA-861-B.
>   *
> + * Drivers that have added the modes parsed from EDID to drm_display_info
> + * should use &drm_display_info.is_hdmi instead of calling this function.
> + *
>   * Return: True if the monitor is HDMI, false if not or unknown.
>   */
>  bool drm_detect_hdmi_monitor(struct edid *edid)
> @@ -4559,6 +4562,8 @@ drm_parse_hdmi_vsdb_video(struct drm_connector *connector, const u8 *db)
>  	struct drm_display_info *info = &connector->display_info;
>  	u8 len = cea_db_payload_len(db);
>  
> +	info->is_hdmi = true;
> +
>  	if (len >= 6)
>  		info->dvi_dual = db[6] & 1;
>  	if (len >= 7)
> @@ -4627,6 +4632,7 @@ drm_reset_display_info(struct drm_connector *connector)
>  	info->cea_rev = 0;
>  	info->max_tmds_clock = 0;
>  	info->dvi_dual = false;
> +	info->is_hdmi = false;
>  	info->has_hdmi_infoframe = false;
>  	info->rgb_quant_range_selectable = false;
>  	memset(&info->hdmi, 0, sizeof(info->hdmi));
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index b91e369cfb11..9b6f69c5092b 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -430,6 +430,14 @@ struct drm_display_info {
>  	 */
>  	bool dvi_dual;
>  
> +	/**
> +	 * @is_hdmi: True if the sink is an HDMI device.
> +	 *
> +	 * This field shall be used instead of calling
> +	 * drm_detect_hdmi_monitor() when possible.
> +	 */
> +	bool is_hdmi;
> +
>  	/**
>  	 * @has_hdmi_infoframe: Does the sink support the HDMI infoframe?
>  	 */

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

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

* Re: [PATCH v2 04/50] drm/bridge: Add connector-related bridge operations and data
  2019-08-20  1:16 ` [PATCH v2 04/50] drm/bridge: Add connector-related bridge operations and data Laurent Pinchart
@ 2019-08-22 15:24   ` Boris Brezillon
  2019-08-22 16:41   ` Boris Brezillon
  1 sibling, 0 replies; 106+ messages in thread
From: Boris Brezillon @ 2019-08-22 15:24 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

On Tue, 20 Aug 2019 04:16:35 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

> To support implementation of DRM connectors on top of DRM bridges
> instead of by bridges, the drm_bridge needs to expose new operations and
> data:
> 
> - Output detection, hot-plug notification, mode retrieval and EDID
>   retrieval operations
> - Bitmask of supported operations
> - Bridge output type
> - I2C adapter for DDC access
> 
> Add and document these.
> 
> Three new bridge helper functions are also added to handle hot plug
> notification in a way that is as transparent as possible for the
> bridges.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>

> ---
> Changes since v1:
> 
> - Make .hpd_enable() and .hpd_disable() optional
> - Rename .lost_hotplug() to .hpd_notify()
> - Add ddc field to drm_bridge
> ---
>  drivers/gpu/drm/drm_bridge.c |  94 +++++++++++++++++++
>  include/drm/drm_bridge.h     | 177 ++++++++++++++++++++++++++++++++++-
>  2 files changed, 270 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index cba537c99e43..cf1fbed88410 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -70,6 +70,8 @@ static LIST_HEAD(bridge_list);
>   */
>  void drm_bridge_add(struct drm_bridge *bridge)
>  {
> +	mutex_init(&bridge->hpd_mutex);
> +
>  	mutex_lock(&bridge_lock);
>  	list_add_tail(&bridge->list, &bridge_list);
>  	mutex_unlock(&bridge_lock);
> @@ -86,6 +88,8 @@ void drm_bridge_remove(struct drm_bridge *bridge)
>  	mutex_lock(&bridge_lock);
>  	list_del_init(&bridge->list);
>  	mutex_unlock(&bridge_lock);
> +
> +	mutex_destroy(&bridge->hpd_mutex);
>  }
>  EXPORT_SYMBOL(drm_bridge_remove);
>  
> @@ -462,6 +466,96 @@ void drm_atomic_bridge_enable(struct drm_bridge *bridge,
>  }
>  EXPORT_SYMBOL(drm_atomic_bridge_enable);
>  
> +/**
> + * drm_bridge_hpd_enable - enable hot plug detection for the bridge
> + * @bridge: bridge control structure
> + * @cb: hot-plug detection callback
> + * @data: data to be passed to the hot-plug detection callback
> + *
> + * Call &drm_bridge_funcs.hpd_enable if implemented and register the given @cb
> + * and @data as hot plug notification callback. From now on the @cb will be
> + * called with @data when an output status change is detected by the bridge,
> + * until hot plug notification gets disabled with drm_bridge_hpd_disable().
> + *
> + * Hot plug detection is supported only if the DRM_BRIDGE_OP_HPD flag is set in
> + * bridge->ops. This function shall not be called when the flag is not set.
> + *
> + * Only one hot plug detection callback can be registered at a time, it is an
> + * error to call this function when hot plug detection is already enabled for
> + * the bridge.
> + */
> +void drm_bridge_hpd_enable(struct drm_bridge *bridge,
> +			   void (*cb)(void *data,
> +				      enum drm_connector_status status),
> +			   void *data)
> +{
> +	if (!bridge || !(bridge->ops & DRM_BRIDGE_OP_HPD))
> +		return;
> +
> +	mutex_lock(&bridge->hpd_mutex);
> +
> +	if (WARN(bridge->hpd_cb, "Hot plug detection already enabled\n"))
> +		goto unlock;
> +
> +	bridge->hpd_cb = cb;
> +	bridge->hpd_data = data;
> +
> +	if (bridge->funcs->hpd_enable)
> +		bridge->funcs->hpd_enable(bridge);
> +
> +unlock:
> +	mutex_unlock(&bridge->hpd_mutex);
> +}
> +EXPORT_SYMBOL_GPL(drm_bridge_hpd_enable);
> +
> +/**
> + * drm_bridge_hpd_disable - disable hot plug detection for the bridge
> + * @bridge: bridge control structure
> + *
> + * Call &drm_bridge_funcs.hpd_disable if implemented and unregister the hot
> + * plug detection callback previously registered with drm_bridge_hpd_enable().
> + * Once this function returns the callback will not be called by the bridge
> + * when an output status change occurs.
> + *
> + * Hot plug detection is supported only if the DRM_BRIDGE_OP_HPD flag is set in
> + * bridge->ops. This function shall not be called when the flag is not set.
> + */
> +void drm_bridge_hpd_disable(struct drm_bridge *bridge)
> +{
> +	if (!bridge || !(bridge->ops & DRM_BRIDGE_OP_HPD))
> +		return;
> +
> +	mutex_lock(&bridge->hpd_mutex);
> +	if (bridge->funcs->hpd_disable)
> +		bridge->funcs->hpd_disable(bridge);
> +
> +	bridge->hpd_cb = NULL;
> +	bridge->hpd_data = NULL;
> +	mutex_unlock(&bridge->hpd_mutex);
> +}
> +EXPORT_SYMBOL_GPL(drm_bridge_hpd_disable);
> +
> +/**
> + * drm_bridge_hpd_notify - notify hot plug detection events
> + * @bridge: bridge control structure
> + * @status: output connection status
> + *
> + * Bridge drivers shall call this function to report hot plug events when they
> + * detect a change in the output status, when hot plug detection has been
> + * enabled by drm_bridge_hpd_enable().
> + *
> + * This function shall be called in a context that can sleep.
> + */
> +void drm_bridge_hpd_notify(struct drm_bridge *bridge,
> +			   enum drm_connector_status status)
> +{
> +	mutex_lock(&bridge->hpd_mutex);
> +	if (bridge->hpd_cb)
> +		bridge->hpd_cb(bridge->hpd_data, status);
> +	mutex_unlock(&bridge->hpd_mutex);
> +}
> +EXPORT_SYMBOL_GPL(drm_bridge_hpd_notify);
> +
>  #ifdef CONFIG_OF
>  /**
>   * of_drm_find_bridge - find the bridge corresponding to the device node in
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 7616f6562fe4..7db6ca0fd75d 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -23,14 +23,16 @@
>  #ifndef __DRM_BRIDGE_H__
>  #define __DRM_BRIDGE_H__
>  
> -#include <linux/list.h>
>  #include <linux/ctype.h>
> +#include <linux/list.h>
> +#include <linux/mutex.h>
>  #include <drm/drm_mode_object.h>
>  #include <drm/drm_modes.h>
>  
>  struct drm_bridge;
>  struct drm_bridge_timings;
>  struct drm_panel;
> +struct i2c_adapter;
>  
>  /**
>   * struct drm_bridge_funcs - drm_bridge control functions
> @@ -334,6 +336,111 @@ struct drm_bridge_funcs {
>  	 */
>  	void (*atomic_post_disable)(struct drm_bridge *bridge,
>  				    struct drm_atomic_state *state);
> +
> +	/**
> +	 * @detect:
> +	 *
> +	 * Check if anything is attached to the bridge output.
> +	 *
> +	 * This callback is optional, if not implemented the bridge will be
> +	 * considered as always having a component attached to its output.
> +	 * Bridges that implement this callback shall set the
> +	 * DRM_BRIDGE_OP_DETECT flag in their &drm_bridge->ops.
> +	 *
> +	 * RETURNS:
> +	 *
> +	 * drm_connector_status indicating the bridge output status.
> +	 */
> +	enum drm_connector_status (*detect)(struct drm_bridge *bridge);
> +
> +	/**
> +	 * @get_modes:
> +	 *
> +	 * Fill all modes currently valid for the sink into the &drm_connector
> +	 * with drm_mode_probed_add().
> +	 *
> +	 * The @get_modes callback is mostly intended to support non-probable
> +	 * displays such as many fixed panels. Bridges that support reading
> +	 * EDID shall leave @get_modes unimplemented and implement the
> +	 * &drm_bridge_funcs->get_edid callback instead.
> +	 *
> +	 * This callback is optional. Bridges that implement it shall set the
> +	 * DRM_BRIDGE_OP_MODES flag in their &drm_bridge->ops.
> +	 *
> +	 * RETURNS:
> +	 *
> +	 * The number of modes added by calling drm_mode_probed_add().
> +	 */
> +	int (*get_modes)(struct drm_bridge *bridge,
> +			 struct drm_connector *connector);
> +
> +	/**
> +	 * @get_edid:
> +	 *
> +	 * Read and parse the EDID data of the connected display.
> +	 *
> +	 * The @get_edid callback is the preferred way of reporting mode
> +	 * information for a display connected to the bridge output. Bridges
> +	 * that support readind EDID shall implement this callback and leave
> +	 * the @get_modes callback unimplemented.
> +	 *
> +	 * The caller of this operation shall first verify the output
> +	 * connection status and refrain from reading EDID from a disconnected
> +	 * output.
> +	 *
> +	 * This callback is optional. Bridges that implement it shall set the
> +	 * DRM_BRIDGE_OP_EDID flag in their &drm_bridge->ops.
> +	 *
> +	 * RETURNS:
> +	 *
> +	 * An edid structure newly allocated with kmalloc() (or similar) on
> +	 * success, or NULL otherwise. The caller is responsible for freeing
> +	 * the returned edid structure with kfree().
> +	 */
> +	struct edid *(*get_edid)(struct drm_bridge *bridge,
> +				 struct drm_connector *connector);
> +
> +	/**
> +	 * @hpd_notify:
> +	 *
> +	 * Notify the bridge of hot plug detection.
> +	 *
> +	 * This callback is optional, it may be implemented by bridges that
> +	 * need to be notified of display connection or disconnection for
> +	 * internal reasons. One use case is to reset the internal state of CEC
> +	 * controllers for HDMI bridges.
> +	 */
> +	void (*hpd_notify)(struct drm_bridge *bridge,
> +			   enum drm_connector_status status);
> +
> +	/**
> +	 * @hpd_enable:
> +	 *
> +	 * Enable hot plug detection. From now on the bridge shall call
> +	 * drm_bridge_hpd_notify() each time a change is detected in the output
> +	 * connection status, until hot plug detection gets disabled with
> +	 * @hpd_disable.
> +	 *
> +	 * This callback is optional and shall only be implemented by bridges
> +	 * that support hot-plug notification without polling. Bridges that
> +	 * implement it shall also implement the @hpd_disable callback and set
> +	 * the DRM_BRIDGE_OP_HPD flag in their &drm_bridge->ops.
> +	 */
> +	void (*hpd_enable)(struct drm_bridge *bridge);
> +
> +	/**
> +	 * @hpd_disable:
> +	 *
> +	 * Disable hot plug detection. Once this function returns the bridge
> +	 * shall not call drm_bridge_hpd_notify() when a change in the output
> +	 * connection status occurs.
> +	 *
> +	 * This callback is optional and shall only be implemented by bridges
> +	 * that support hot-plug notification without polling. Bridges that
> +	 * implement it shall also implement the @hpd_enable callback and set
> +	 * the DRM_BRIDGE_OP_HPD flag in their &drm_bridge->ops.
> +	 */
> +	void (*hpd_disable)(struct drm_bridge *bridge);
>  };
>  
>  /**
> @@ -372,6 +479,39 @@ struct drm_bridge_timings {
>  	bool dual_link;
>  };
>  
> +/**
> + * enum drm_bridge_ops - Bitmask of operations supported by the bridge
> + */
> +enum drm_bridge_ops {
> +	/**
> +	 * @DRM_BRIDGE_OP_DETECT: The bridge can detect displays connected to
> +	 * its output. Bridges that set this flag shall implement the
> +	 * &drm_bridge_funcs->detect callback.
> +	 */
> +	DRM_BRIDGE_OP_DETECT = BIT(0),
> +	/**
> +	 * @DRM_BRIDGE_OP_EDID: The bridge can retrieve the EDID of the display
> +	 * connected to its output. Bridges that set this flag shall implement
> +	 * the &drm_bridge_funcs->get_edid callback.
> +	 */
> +	DRM_BRIDGE_OP_EDID = BIT(1),
> +	/**
> +	 * @DRM_BRIDGE_OP_HPD: The bridge can detect hot-plug and hot-unplug
> +	 * without requiring polling. Bridges that set this flag shall
> +	 * implement the &drm_bridge_funcs->hpd_enable and
> +	 * &drm_bridge_funcs->hpd_disable callbacks if they support enabling
> +	 * and disabling hot-plug detection dynamically.
> +	 */
> +	DRM_BRIDGE_OP_HPD = BIT(2),
> +	/**
> +	 * @DRM_BRIDGE_OP_MODES: The bridge can retrieving the modes supported
> +	 * by the display at its output. This does not include readind EDID
> +	 * which is separately covered by @DRM_BRIDGE_OP_EDID. Bridges that set
> +	 * this flag shall implement the &drm_bridge_funcs->get_modes callback.
> +	 */
> +	DRM_BRIDGE_OP_MODES = BIT(3),
> +};
> +
>  /**
>   * struct drm_bridge - central DRM bridge control structure
>   */
> @@ -398,6 +538,33 @@ struct drm_bridge {
>  	const struct drm_bridge_funcs *funcs;
>  	/** @driver_private: pointer to the bridge driver's internal context */
>  	void *driver_private;
> +	/** @ops: bitmask of operations supported by the bridge */
> +	enum drm_bridge_ops ops;
> +	/**
> +	 * @type: Type of the connection at the bridge output
> +	 * (DRM_MODE_CONNECTOR_*). For bridges at the end of this chain this
> +	 * identifies the type of connected display.
> +	 */
> +	int type;
> +	/**
> +	 * @ddc: Associated I2C adapter for DDC access, if any.
> +	 */
> +	struct i2c_adapter *ddc;
> +	/** private: */
> +	/**
> +	 * @hpd_mutex: Protects the @hpd_cb and @hpd_data fields.
> +	 */
> +	struct mutex hpd_mutex;
> +	/**
> +	 * @hpd_cb: Hot plug detection callback, registered with
> +	 * drm_bridge_hpd_enable().
> +	 */
> +	void (*hpd_cb)(void *data, enum drm_connector_status status);
> +	/**
> +	 * @hpd_data: Private data passed to the Hot plug detection callback
> +	 * @hpd_cb.
> +	 */
> +	void *hpd_data;
>  };
>  
>  void drm_bridge_add(struct drm_bridge *bridge);
> @@ -428,6 +595,14 @@ void drm_atomic_bridge_pre_enable(struct drm_bridge *bridge,
>  void drm_atomic_bridge_enable(struct drm_bridge *bridge,
>  			      struct drm_atomic_state *state);
>  
> +void drm_bridge_hpd_enable(struct drm_bridge *bridge,
> +			   void (*cb)(void *data,
> +				      enum drm_connector_status status),
> +			   void *data);
> +void drm_bridge_hpd_disable(struct drm_bridge *bridge);
> +void drm_bridge_hpd_notify(struct drm_bridge *bridge,
> +			   enum drm_connector_status status);
> +
>  #ifdef CONFIG_DRM_PANEL_BRIDGE
>  struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
>  					u32 connector_type);

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

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

* Re: [PATCH v2 05/50] drm/bridge: Extend bridge API to disable connector creation
  2019-08-20  1:16 ` [PATCH v2 05/50] drm/bridge: Extend bridge API to disable connector creation Laurent Pinchart
@ 2019-08-22 15:34   ` Boris Brezillon
  2019-10-01  7:04   ` Tomi Valkeinen
  1 sibling, 0 replies; 106+ messages in thread
From: Boris Brezillon @ 2019-08-22 15:34 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

On Tue, 20 Aug 2019 04:16:36 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

> Most bridge drivers create a DRM connector to model the connector at the
> output of the bridge. This model is historical and has worked pretty
> well so far, but causes several issues:
> 
> - It prevents supporting more complex display pipelines where DRM
> connector operations are split over multiple components. For instance a
> pipeline with a bridge connected to the DDC signals to read EDID data,
> and another one connected to the HPD signal to detect connection and
> disconnection, will not be possible to support through this model.
> 
> - It requires every bridge driver to implement similar connector
> handling code, resulting in code duplication.
> 
> - It assumes that a bridge will either be wired to a connector or to
> another bridge, but doesn't support bridges that can be used in both
> positions very well (although there is some ad-hoc support for this in
> the analogix_dp bridge driver).
> 
> In order to solve these issues, ownership of the connector should be
> moved to the display controller driver (where it can be implemented
> using helpers provided by the core).
> 
> Extend the bridge API to allow disabling connector creation in bridge
> drivers as a first step towards the new model. The new create_connector
> argument to the bridge .attach() operation tells the bridge driver
> whether to create a connector. Set the argument to true unconditionally,

You're talking about the extra arg passed to drm_bridge_attach(), right?
I guess this commit message reflects the old implementation where
the extra arg was a boolean.

> and modify all existing bridge drivers to return an error when connector
> creation is not requested as they don't support this feature yet.
> 
> The change is based on the following semantic patch, with manual review
> and edits.
> 
> @ rule1 @
> identifier funcs;
> identifier fn;
> @@
>  struct drm_bridge_funcs funcs = {
>  	...,
>  	.attach = fn
>  };
> 
> @ depends on rule1 @
> identifier rule1.fn;
> identifier bridge;
> statement S, S1;
> @@
>  int fn(
>  	struct drm_bridge *bridge
> +	, enum drm_bridge_attach_flags flags
>  )
>  {
>  	... when != S
> +	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> +		return -EINVAL;
> +
>  	S1
>  	...
>  }
> 
> @@
> expression E1, E2, E3;
> @@
>  drm_bridge_attach(E1, E2, E3
> +	, 0
>  )
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Haven't gone through the diff but the semantic patch looks good, and
I'm pretty sure you compiled all drivers implementing the attach hook
and/or calling drm_bridge_attach().

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>

> ---
> Changes since v1:
> 
> - Replace the create_connector boolean with a flags bitmask
> - Update ingenic driver
> - Add semantic patch to commit message
> ---
>  drivers/gpu/drm/arc/arcpgu_hdmi.c             |  2 +-
>  .../gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c  |  2 +-
>  drivers/gpu/drm/bridge/adv7511/adv7511_drv.c  |  6 +++++-
>  drivers/gpu/drm/bridge/analogix-anx78xx.c     |  6 +++++-
>  .../drm/bridge/analogix/analogix_dp_core.c    |  8 ++++++--
>  drivers/gpu/drm/bridge/cdns-dsi.c             |  6 ++++--
>  drivers/gpu/drm/bridge/dumb-vga-dac.c         |  6 +++++-
>  drivers/gpu/drm/bridge/lvds-encoder.c         |  5 +++--
>  .../bridge/megachips-stdpxxxx-ge-b850v3-fw.c  |  6 +++++-
>  drivers/gpu/drm/bridge/nxp-ptn3460.c          |  6 +++++-
>  drivers/gpu/drm/bridge/panel.c                |  6 +++++-
>  drivers/gpu/drm/bridge/parade-ps8622.c        |  6 +++++-
>  drivers/gpu/drm/bridge/sii902x.c              |  6 +++++-
>  drivers/gpu/drm/bridge/sil-sii8620.c          |  3 ++-
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c     |  8 ++++++--
>  drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c |  8 +++++---
>  drivers/gpu/drm/bridge/tc358764.c             |  6 +++++-
>  drivers/gpu/drm/bridge/tc358767.c             |  6 +++++-
>  drivers/gpu/drm/bridge/thc63lvd1024.c         |  5 +++--
>  drivers/gpu/drm/bridge/ti-sn65dsi86.c         |  6 +++++-
>  drivers/gpu/drm/bridge/ti-tfp410.c            |  6 +++++-
>  drivers/gpu/drm/drm_bridge.c                  |  6 ++++--
>  drivers/gpu/drm/drm_simple_kms_helper.c       |  2 +-
>  drivers/gpu/drm/exynos/exynos_dp.c            |  3 ++-
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c       |  4 ++--
>  drivers/gpu/drm/exynos/exynos_hdmi.c          |  2 +-
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c     |  2 +-
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c  |  2 +-
>  drivers/gpu/drm/i2c/tda998x_drv.c             |  8 ++++++--
>  drivers/gpu/drm/imx/imx-ldb.c                 |  2 +-
>  drivers/gpu/drm/imx/parallel-display.c        |  2 +-
>  drivers/gpu/drm/ingenic/ingenic-drm.c         |  2 +-
>  drivers/gpu/drm/mcde/mcde_dsi.c               |  8 ++++++--
>  drivers/gpu/drm/mediatek/mtk_dpi.c            |  2 +-
>  drivers/gpu/drm/mediatek/mtk_dsi.c            |  2 +-
>  drivers/gpu/drm/mediatek/mtk_hdmi.c           |  8 ++++++--
>  drivers/gpu/drm/msm/dsi/dsi_manager.c         |  4 ++--
>  drivers/gpu/drm/msm/edp/edp_bridge.c          |  2 +-
>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c        |  2 +-
>  drivers/gpu/drm/omapdrm/omap_drv.c            |  2 +-
>  drivers/gpu/drm/rcar-du/rcar_du_encoder.c     |  2 +-
>  drivers/gpu/drm/rcar-du/rcar_lvds.c           |  8 ++++++--
>  drivers/gpu/drm/rockchip/rockchip_lvds.c      |  2 +-
>  drivers/gpu/drm/rockchip/rockchip_rgb.c       |  2 +-
>  drivers/gpu/drm/sti/sti_dvo.c                 |  2 +-
>  drivers/gpu/drm/sti/sti_hda.c                 |  2 +-
>  drivers/gpu/drm/sti/sti_hdmi.c                |  2 +-
>  drivers/gpu/drm/stm/ltdc.c                    |  2 +-
>  drivers/gpu/drm/sun4i/sun4i_lvds.c            |  2 +-
>  drivers/gpu/drm/sun4i/sun4i_rgb.c             |  2 +-
>  drivers/gpu/drm/tilcdc/tilcdc_external.c      |  2 +-
>  drivers/gpu/drm/vc4/vc4_dpi.c                 |  2 +-
>  drivers/gpu/drm/vc4/vc4_dsi.c                 |  2 +-
>  include/drm/drm_bridge.h                      | 20 ++++++++++++++++---
>  54 files changed, 166 insertions(+), 70 deletions(-)
> 
> diff --git a/drivers/gpu/drm/arc/arcpgu_hdmi.c b/drivers/gpu/drm/arc/arcpgu_hdmi.c
> index 98aac743cc26..ab023e070529 100644
> --- a/drivers/gpu/drm/arc/arcpgu_hdmi.c
> +++ b/drivers/gpu/drm/arc/arcpgu_hdmi.c
> @@ -39,7 +39,7 @@ int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np)
>  		return ret;
>  
>  	/* Link drm_bridge to encoder */
> -	ret = drm_bridge_attach(encoder, bridge, NULL);
> +	ret = drm_bridge_attach(encoder, bridge, NULL, 0);
>  	if (ret)
>  		drm_encoder_cleanup(encoder);
>  
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> index 375fa84c548b..c388497366ca 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> @@ -113,7 +113,7 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, int endpoint)
>  	}
>  
>  	if (bridge) {
> -		ret = drm_bridge_attach(&output->encoder, bridge, NULL);
> +		ret = drm_bridge_attach(&output->encoder, bridge, NULL, 0);
>  		if (!ret)
>  			return 0;
>  
> diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
> index 98bccace8c1c..6e42d5e05d07 100644
> --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
> +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
> @@ -847,11 +847,15 @@ static void adv7511_bridge_mode_set(struct drm_bridge *bridge,
>  	adv7511_mode_set(adv, mode, adj_mode);
>  }
>  
> -static int adv7511_bridge_attach(struct drm_bridge *bridge)
> +static int adv7511_bridge_attach(struct drm_bridge *bridge,
> +				 enum drm_bridge_attach_flags flags)
>  {
>  	struct adv7511 *adv = bridge_to_adv7511(bridge);
>  	int ret;
>  
> +	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> +		return -EINVAL;
> +
>  	if (!bridge->encoder) {
>  		DRM_ERROR("Parent encoder object not found");
>  		return -ENODEV;
> diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix-anx78xx.c
> index 3c7cc5af735c..995a54547fbe 100644
> --- a/drivers/gpu/drm/bridge/analogix-anx78xx.c
> +++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c
> @@ -998,11 +998,15 @@ static const struct drm_connector_funcs anx78xx_connector_funcs = {
>  	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
>  };
>  
> -static int anx78xx_bridge_attach(struct drm_bridge *bridge)
> +static int anx78xx_bridge_attach(struct drm_bridge *bridge,
> +				 enum drm_bridge_attach_flags flags)
>  {
>  	struct anx78xx *anx78xx = bridge_to_anx78xx(bridge);
>  	int err;
>  
> +	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> +		return -EINVAL;
> +
>  	if (!bridge->encoder) {
>  		DRM_ERROR("Parent encoder object not found");
>  		return -ENODEV;
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 22885dceaa17..d903eed368e3 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -1215,13 +1215,17 @@ static const struct drm_connector_funcs analogix_dp_connector_funcs = {
>  	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
>  };
>  
> -static int analogix_dp_bridge_attach(struct drm_bridge *bridge)
> +static int analogix_dp_bridge_attach(struct drm_bridge *bridge,
> +				     enum drm_bridge_attach_flags flags)
>  {
>  	struct analogix_dp_device *dp = bridge->driver_private;
>  	struct drm_encoder *encoder = dp->encoder;
>  	struct drm_connector *connector = NULL;
>  	int ret = 0;
>  
> +	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> +		return -EINVAL;
> +
>  	if (!bridge->encoder) {
>  		DRM_ERROR("Parent encoder object not found");
>  		return -ENODEV;
> @@ -1587,7 +1591,7 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev,
>  	bridge->driver_private = dp;
>  	bridge->funcs = &analogix_dp_bridge_funcs;
>  
> -	ret = drm_bridge_attach(dp->encoder, bridge, NULL);
> +	ret = drm_bridge_attach(dp->encoder, bridge, NULL, 0);
>  	if (ret) {
>  		DRM_ERROR("failed to attach drm bridge\n");
>  		return -EINVAL;
> diff --git a/drivers/gpu/drm/bridge/cdns-dsi.c b/drivers/gpu/drm/bridge/cdns-dsi.c
> index 6166dca6be81..2af7f25c7413 100644
> --- a/drivers/gpu/drm/bridge/cdns-dsi.c
> +++ b/drivers/gpu/drm/bridge/cdns-dsi.c
> @@ -645,7 +645,8 @@ static int cdns_dsi_check_conf(struct cdns_dsi *dsi,
>  	return 0;
>  }
>  
> -static int cdns_dsi_bridge_attach(struct drm_bridge *bridge)
> +static int cdns_dsi_bridge_attach(struct drm_bridge *bridge,
> +				  enum drm_bridge_attach_flags flags)
>  {
>  	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
>  	struct cdns_dsi *dsi = input_to_dsi(input);
> @@ -657,7 +658,8 @@ static int cdns_dsi_bridge_attach(struct drm_bridge *bridge)
>  		return -ENOTSUPP;
>  	}
>  
> -	return drm_bridge_attach(bridge->encoder, output->bridge, bridge);
> +	return drm_bridge_attach(bridge->encoder, output->bridge, bridge,
> +				 flags);
>  }
>  
>  static enum drm_mode_status
> diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
> index 7aa789c35882..74ebca58eb1f 100644
> --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
> +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
> @@ -99,11 +99,15 @@ static const struct drm_connector_funcs dumb_vga_con_funcs = {
>  	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
>  };
>  
> -static int dumb_vga_attach(struct drm_bridge *bridge)
> +static int dumb_vga_attach(struct drm_bridge *bridge,
> +			   enum drm_bridge_attach_flags flags)
>  {
>  	struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
>  	int ret;
>  
> +	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> +		return -EINVAL;
> +
>  	if (!bridge->encoder) {
>  		DRM_ERROR("Missing encoder\n");
>  		return -ENODEV;
> diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c b/drivers/gpu/drm/bridge/lvds-encoder.c
> index 2ab2c234f26c..9ebc750449cf 100644
> --- a/drivers/gpu/drm/bridge/lvds-encoder.c
> +++ b/drivers/gpu/drm/bridge/lvds-encoder.c
> @@ -18,14 +18,15 @@ struct lvds_encoder {
>  	struct gpio_desc *powerdown_gpio;
>  };
>  
> -static int lvds_encoder_attach(struct drm_bridge *bridge)
> +static int lvds_encoder_attach(struct drm_bridge *bridge,
> +			       enum drm_bridge_attach_flags flags)
>  {
>  	struct lvds_encoder *lvds_encoder = container_of(bridge,
>  							 struct lvds_encoder,
>  							 bridge);
>  
>  	return drm_bridge_attach(bridge->encoder, lvds_encoder->panel_bridge,
> -				 bridge);
> +				 bridge, flags);
>  }
>  
>  static void lvds_encoder_enable(struct drm_bridge *bridge)
> diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
> index 6e81e5db57f2..1380291f6672 100644
> --- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
> +++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
> @@ -205,13 +205,17 @@ static irqreturn_t ge_b850v3_lvds_irq_handler(int irq, void *dev_id)
>  	return IRQ_HANDLED;
>  }
>  
> -static int ge_b850v3_lvds_attach(struct drm_bridge *bridge)
> +static int ge_b850v3_lvds_attach(struct drm_bridge *bridge,
> +				 enum drm_bridge_attach_flags flags)
>  {
>  	struct drm_connector *connector = &ge_b850v3_lvds_ptr->connector;
>  	struct i2c_client *stdp4028_i2c
>  			= ge_b850v3_lvds_ptr->stdp4028_i2c;
>  	int ret;
>  
> +	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> +		return -EINVAL;
> +
>  	if (!bridge->encoder) {
>  		DRM_ERROR("Parent encoder object not found");
>  		return -ENODEV;
> diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c
> index d4a1cc5052c3..42c69e9d0d70 100644
> --- a/drivers/gpu/drm/bridge/nxp-ptn3460.c
> +++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c
> @@ -235,11 +235,15 @@ static const struct drm_connector_funcs ptn3460_connector_funcs = {
>  	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
>  };
>  
> -static int ptn3460_bridge_attach(struct drm_bridge *bridge)
> +static int ptn3460_bridge_attach(struct drm_bridge *bridge,
> +				 enum drm_bridge_attach_flags flags)
>  {
>  	struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge);
>  	int ret;
>  
> +	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> +		return -EINVAL;
> +
>  	if (!bridge->encoder) {
>  		DRM_ERROR("Parent encoder object not found");
>  		return -ENODEV;
> diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
> index b12ae3a4c5f1..f5b8e55301ac 100644
> --- a/drivers/gpu/drm/bridge/panel.c
> +++ b/drivers/gpu/drm/bridge/panel.c
> @@ -52,12 +52,16 @@ static const struct drm_connector_funcs panel_bridge_connector_funcs = {
>  	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
>  };
>  
> -static int panel_bridge_attach(struct drm_bridge *bridge)
> +static int panel_bridge_attach(struct drm_bridge *bridge,
> +			       enum drm_bridge_attach_flags flags)
>  {
>  	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
>  	struct drm_connector *connector = &panel_bridge->connector;
>  	int ret;
>  
> +	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> +		return -EINVAL;
> +
>  	if (!bridge->encoder) {
>  		DRM_ERROR("Missing encoder\n");
>  		return -ENODEV;
> diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c
> index 93c68e2e9484..816482df27a8 100644
> --- a/drivers/gpu/drm/bridge/parade-ps8622.c
> +++ b/drivers/gpu/drm/bridge/parade-ps8622.c
> @@ -475,11 +475,15 @@ static const struct drm_connector_funcs ps8622_connector_funcs = {
>  	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
>  };
>  
> -static int ps8622_attach(struct drm_bridge *bridge)
> +static int ps8622_attach(struct drm_bridge *bridge,
> +			 enum drm_bridge_attach_flags flags)
>  {
>  	struct ps8622_bridge *ps8622 = bridge_to_ps8622(bridge);
>  	int ret;
>  
> +	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> +		return -EINVAL;
> +
>  	if (!bridge->encoder) {
>  		DRM_ERROR("Parent encoder object not found");
>  		return -ENODEV;
> diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
> index 38f75ac580df..51f5d7e8e360 100644
> --- a/drivers/gpu/drm/bridge/sii902x.c
> +++ b/drivers/gpu/drm/bridge/sii902x.c
> @@ -398,12 +398,16 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
>  	mutex_unlock(&sii902x->mutex);
>  }
>  
> -static int sii902x_bridge_attach(struct drm_bridge *bridge)
> +static int sii902x_bridge_attach(struct drm_bridge *bridge,
> +				 enum drm_bridge_attach_flags flags)
>  {
>  	struct sii902x *sii902x = bridge_to_sii902x(bridge);
>  	struct drm_device *drm = bridge->dev;
>  	int ret;
>  
> +	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> +		return -EINVAL;
> +
>  	drm_connector_helper_add(&sii902x->connector,
>  				 &sii902x_connector_helper_funcs);
>  
> diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
> index bd3165ee5354..461bdeb32568 100644
> --- a/drivers/gpu/drm/bridge/sil-sii8620.c
> +++ b/drivers/gpu/drm/bridge/sil-sii8620.c
> @@ -2200,7 +2200,8 @@ static inline struct sii8620 *bridge_to_sii8620(struct drm_bridge *bridge)
>  	return container_of(bridge, struct sii8620, bridge);
>  }
>  
> -static int sii8620_attach(struct drm_bridge *bridge)
> +static int sii8620_attach(struct drm_bridge *bridge,
> +			  enum drm_bridge_attach_flags flags)
>  {
>  	struct sii8620 *ctx = bridge_to_sii8620(bridge);
>  
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index 4044071090c4..cb86c4705ce8 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -2225,12 +2225,16 @@ static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs =
>  	.get_modes = dw_hdmi_connector_get_modes,
>  };
>  
> -static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
> +static int dw_hdmi_bridge_attach(struct drm_bridge *bridge,
> +				 enum drm_bridge_attach_flags flags)
>  {
>  	struct dw_hdmi *hdmi = bridge->driver_private;
>  	struct drm_encoder *encoder = bridge->encoder;
>  	struct drm_connector *connector = &hdmi->connector;
>  
> +	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> +		return -EINVAL;
> +
>  	connector->interlace_allowed = 1;
>  	connector->polled = DRM_CONNECTOR_POLL_HPD;
>  
> @@ -2911,7 +2915,7 @@ struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev,
>  	if (IS_ERR(hdmi))
>  		return hdmi;
>  
> -	ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL);
> +	ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL, 0);
>  	if (ret) {
>  		dw_hdmi_remove(hdmi);
>  		DRM_ERROR("Failed to initialize bridge with drm\n");
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
> index 675442bfc1bd..9245dde314a8 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
> @@ -923,7 +923,8 @@ dw_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge,
>  	return mode_status;
>  }
>  
> -static int dw_mipi_dsi_bridge_attach(struct drm_bridge *bridge)
> +static int dw_mipi_dsi_bridge_attach(struct drm_bridge *bridge,
> +				     enum drm_bridge_attach_flags flags)
>  {
>  	struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
>  
> @@ -936,7 +937,8 @@ static int dw_mipi_dsi_bridge_attach(struct drm_bridge *bridge)
>  	bridge->encoder->encoder_type = DRM_MODE_ENCODER_DSI;
>  
>  	/* Attach the panel-bridge to the dsi bridge */
> -	return drm_bridge_attach(bridge->encoder, dsi->panel_bridge, bridge);
> +	return drm_bridge_attach(bridge->encoder, dsi->panel_bridge, bridge,
> +				 flags);
>  }
>  
>  static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = {
> @@ -1111,7 +1113,7 @@ int dw_mipi_dsi_bind(struct dw_mipi_dsi *dsi, struct drm_encoder *encoder)
>  {
>  	int ret;
>  
> -	ret = drm_bridge_attach(encoder, &dsi->bridge, NULL);
> +	ret = drm_bridge_attach(encoder, &dsi->bridge, NULL, true);
>  	if (ret) {
>  		DRM_ERROR("Failed to initialize bridge with drm\n");
>  		return ret;
> diff --git a/drivers/gpu/drm/bridge/tc358764.c b/drivers/gpu/drm/bridge/tc358764.c
> index 170f162ffa55..ea768d2b80bb 100644
> --- a/drivers/gpu/drm/bridge/tc358764.c
> +++ b/drivers/gpu/drm/bridge/tc358764.c
> @@ -348,12 +348,16 @@ static void tc358764_enable(struct drm_bridge *bridge)
>  		dev_err(ctx->dev, "error enabling panel (%d)\n", ret);
>  }
>  
> -static int tc358764_attach(struct drm_bridge *bridge)
> +static int tc358764_attach(struct drm_bridge *bridge,
> +			   enum drm_bridge_attach_flags flags)
>  {
>  	struct tc358764 *ctx = bridge_to_tc358764(bridge);
>  	struct drm_device *drm = bridge->dev;
>  	int ret;
>  
> +	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> +		return -EINVAL;
> +
>  	ctx->connector.polled = DRM_CONNECTOR_POLL_HPD;
>  	ret = drm_connector_init(drm, &ctx->connector,
>  				 &tc358764_connector_funcs,
> diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
> index cebc8e620820..f90d72a85164 100644
> --- a/drivers/gpu/drm/bridge/tc358767.c
> +++ b/drivers/gpu/drm/bridge/tc358767.c
> @@ -1378,13 +1378,17 @@ static const struct drm_connector_funcs tc_connector_funcs = {
>  	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
>  };
>  
> -static int tc_bridge_attach(struct drm_bridge *bridge)
> +static int tc_bridge_attach(struct drm_bridge *bridge,
> +			    enum drm_bridge_attach_flags flags)
>  {
>  	u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
>  	struct tc_data *tc = bridge_to_tc(bridge);
>  	struct drm_device *drm = bridge->dev;
>  	int ret;
>  
> +	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> +		return -EINVAL;
> +
>  	/* Create DP/eDP connector */
>  	drm_connector_helper_add(&tc->connector, &tc_connector_helper_funcs);
>  	ret = drm_connector_init(drm, &tc->connector, &tc_connector_funcs,
> diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c b/drivers/gpu/drm/bridge/thc63lvd1024.c
> index 3d74129b2995..97d8129760e9 100644
> --- a/drivers/gpu/drm/bridge/thc63lvd1024.c
> +++ b/drivers/gpu/drm/bridge/thc63lvd1024.c
> @@ -42,11 +42,12 @@ static inline struct thc63_dev *to_thc63(struct drm_bridge *bridge)
>  	return container_of(bridge, struct thc63_dev, bridge);
>  }
>  
> -static int thc63_attach(struct drm_bridge *bridge)
> +static int thc63_attach(struct drm_bridge *bridge,
> +			enum drm_bridge_attach_flags flags)
>  {
>  	struct thc63_dev *thc63 = to_thc63(bridge);
>  
> -	return drm_bridge_attach(bridge->encoder, thc63->next, bridge);
> +	return drm_bridge_attach(bridge->encoder, thc63->next, bridge, flags);
>  }
>  
>  static enum drm_mode_status thc63_mode_valid(struct drm_bridge *bridge,
> diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> index 0a580957c8cf..e970d3fbc20b 100644
> --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> @@ -263,7 +263,8 @@ static int ti_sn_bridge_parse_regulators(struct ti_sn_bridge *pdata)
>  				       pdata->supplies);
>  }
>  
> -static int ti_sn_bridge_attach(struct drm_bridge *bridge)
> +static int ti_sn_bridge_attach(struct drm_bridge *bridge,
> +			       enum drm_bridge_attach_flags flags)
>  {
>  	int ret, val;
>  	struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge);
> @@ -274,6 +275,9 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge)
>  						   .node = NULL,
>  						 };
>  
> +	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> +		return -EINVAL;
> +
>  	ret = drm_connector_init(bridge->dev, &pdata->connector,
>  				 &ti_sn_bridge_connector_funcs,
>  				 DRM_MODE_CONNECTOR_eDP);
> diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
> index 61cc2354ef1b..a9359038f7dc 100644
> --- a/drivers/gpu/drm/bridge/ti-tfp410.c
> +++ b/drivers/gpu/drm/bridge/ti-tfp410.c
> @@ -117,11 +117,15 @@ static const struct drm_connector_funcs tfp410_con_funcs = {
>  	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
>  };
>  
> -static int tfp410_attach(struct drm_bridge *bridge)
> +static int tfp410_attach(struct drm_bridge *bridge,
> +			 enum drm_bridge_attach_flags flags)
>  {
>  	struct tfp410 *dvi = drm_bridge_to_tfp410(bridge);
>  	int ret;
>  
> +	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> +		return -EINVAL;
> +
>  	if (!bridge->encoder) {
>  		dev_err(dvi->dev, "Missing encoder\n");
>  		return -ENODEV;
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index cf1fbed88410..814027a98fcb 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -99,6 +99,7 @@ EXPORT_SYMBOL(drm_bridge_remove);
>   * @encoder: DRM encoder
>   * @bridge: bridge to attach
>   * @previous: previous bridge in the chain (optional)
> + * @flags: DRM_BRIDGE_ATTACH_* flags
>   *
>   * Called by a kms driver to link the bridge to an encoder's chain. The previous
>   * argument specifies the previous bridge in the chain. If NULL, the bridge is
> @@ -116,7 +117,8 @@ EXPORT_SYMBOL(drm_bridge_remove);
>   * Zero on success, error code on failure
>   */
>  int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
> -		      struct drm_bridge *previous)
> +		      struct drm_bridge *previous,
> +		      enum drm_bridge_attach_flags flags)
>  {
>  	int ret;
>  
> @@ -133,7 +135,7 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
>  	bridge->encoder = encoder;
>  
>  	if (bridge->funcs->attach) {
> -		ret = bridge->funcs->attach(bridge);
> +		ret = bridge->funcs->attach(bridge, flags);
>  		if (ret < 0) {
>  			bridge->dev = NULL;
>  			bridge->encoder = NULL;
> diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
> index b11910f14c46..ea105d137066 100644
> --- a/drivers/gpu/drm/drm_simple_kms_helper.c
> +++ b/drivers/gpu/drm/drm_simple_kms_helper.c
> @@ -228,7 +228,7 @@ static const struct drm_plane_funcs drm_simple_kms_plane_funcs = {
>  int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe,
>  					  struct drm_bridge *bridge)
>  {
> -	return drm_bridge_attach(&pipe->encoder, bridge, NULL);
> +	return drm_bridge_attach(&pipe->encoder, bridge, NULL, 0);
>  }
>  EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
>  
> diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
> index 3a0f0ba8c63a..3f79c8151aad 100644
> --- a/drivers/gpu/drm/exynos/exynos_dp.c
> +++ b/drivers/gpu/drm/exynos/exynos_dp.c
> @@ -105,7 +105,8 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
>  
>  	/* Pre-empt DP connector creation if there's a bridge */
>  	if (dp->ptn_bridge) {
> -		ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge);
> +		ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge,
> +					0);
>  		if (ret) {
>  			DRM_DEV_ERROR(dp->dev,
>  				      "Failed to attach bridge to drm\n");
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index 6926cee91b36..a84a1979e327 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -1519,7 +1519,7 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
>  
>  	out_bridge  = of_drm_find_bridge(device->dev.of_node);
>  	if (out_bridge) {
> -		drm_bridge_attach(encoder, out_bridge, NULL);
> +		drm_bridge_attach(encoder, out_bridge, NULL, 0);
>  		dsi->out_bridge = out_bridge;
>  		encoder->bridge = NULL;
>  	} else {
> @@ -1695,7 +1695,7 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
>  	if (dsi->in_bridge_node) {
>  		in_bridge = of_drm_find_bridge(dsi->in_bridge_node);
>  		if (in_bridge)
> -			drm_bridge_attach(encoder, in_bridge, NULL);
> +			drm_bridge_attach(encoder, in_bridge, NULL, 0);
>  	}
>  
>  	return mipi_dsi_host_register(&dsi->dsi_host);
> diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
> index bc1565f1822a..9978743ee058 100644
> --- a/drivers/gpu/drm/exynos/exynos_hdmi.c
> +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
> @@ -952,7 +952,7 @@ static int hdmi_create_connector(struct drm_encoder *encoder)
>  	drm_connector_attach_encoder(connector, encoder);
>  
>  	if (hdata->bridge) {
> -		ret = drm_bridge_attach(encoder, hdata->bridge, NULL);
> +		ret = drm_bridge_attach(encoder, hdata->bridge, NULL, 0);
>  		if (ret)
>  			DRM_DEV_ERROR(hdata->dev, "Failed to attach bridge\n");
>  	}
> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> index a92fd6c70b09..900a33e1d2fb 100644
> --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> @@ -150,5 +150,5 @@ int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
>  		return fsl_dcu_attach_panel(fsl_dev, panel);
>  	}
>  
> -	return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
> +	return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL, 0);
>  }
> diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> index 5bf8138941de..43543a0877a9 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> @@ -776,7 +776,7 @@ static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi)
>  	int ret;
>  
>  	/* associate the bridge to dsi encoder */
> -	ret = drm_bridge_attach(encoder, bridge, NULL);
> +	ret = drm_bridge_attach(encoder, bridge, NULL, 0);
>  	if (ret) {
>  		DRM_ERROR("failed to attach external bridge\n");
>  		return ret;
> diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
> index 84c6d4c91c65..3f9a3d5dbdeb 100644
> --- a/drivers/gpu/drm/i2c/tda998x_drv.c
> +++ b/drivers/gpu/drm/i2c/tda998x_drv.c
> @@ -1355,10 +1355,14 @@ static int tda998x_connector_init(struct tda998x_priv *priv,
>  
>  /* DRM bridge functions */
>  
> -static int tda998x_bridge_attach(struct drm_bridge *bridge)
> +static int tda998x_bridge_attach(struct drm_bridge *bridge,
> +				 enum drm_bridge_attach_flags flags)
>  {
>  	struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
>  
> +	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> +		return -EINVAL;
> +
>  	return tda998x_connector_init(priv, bridge->dev);
>  }
>  
> @@ -2022,7 +2026,7 @@ static int tda998x_encoder_init(struct device *dev, struct drm_device *drm)
>  	if (ret)
>  		goto err_encoder;
>  
> -	ret = drm_bridge_attach(&priv->encoder, &priv->bridge, NULL);
> +	ret = drm_bridge_attach(&priv->encoder, &priv->bridge, NULL, 0);
>  	if (ret)
>  		goto err_bridge;
>  
> diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
> index 695f307f36b2..6358e9733398 100644
> --- a/drivers/gpu/drm/imx/imx-ldb.c
> +++ b/drivers/gpu/drm/imx/imx-ldb.c
> @@ -445,7 +445,7 @@ static int imx_ldb_register(struct drm_device *drm,
>  
>  	if (imx_ldb_ch->bridge) {
>  		ret = drm_bridge_attach(&imx_ldb_ch->encoder,
> -					imx_ldb_ch->bridge, NULL);
> +					imx_ldb_ch->bridge, NULL, 0);
>  		if (ret) {
>  			DRM_ERROR("Failed to initialize bridge with drm\n");
>  			return ret;
> diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
> index e7ce17503ae1..e385ce5deb90 100644
> --- a/drivers/gpu/drm/imx/parallel-display.c
> +++ b/drivers/gpu/drm/imx/parallel-display.c
> @@ -181,7 +181,7 @@ static int imx_pd_register(struct drm_device *drm,
>  		drm_panel_attach(imxpd->panel, &imxpd->connector);
>  
>  	if (imxpd->bridge) {
> -		ret = drm_bridge_attach(encoder, imxpd->bridge, NULL);
> +		ret = drm_bridge_attach(encoder, imxpd->bridge, NULL, 0);
>  		if (ret < 0) {
>  			dev_err(imxpd->dev, "failed to attach bridge: %d\n",
>  				ret);
> diff --git a/drivers/gpu/drm/ingenic/ingenic-drm.c b/drivers/gpu/drm/ingenic/ingenic-drm.c
> index ce1fae3a78a9..65eb10179ea9 100644
> --- a/drivers/gpu/drm/ingenic/ingenic-drm.c
> +++ b/drivers/gpu/drm/ingenic/ingenic-drm.c
> @@ -726,7 +726,7 @@ static int ingenic_drm_probe(struct platform_device *pdev)
>  		return ret;
>  	}
>  
> -	ret = drm_bridge_attach(&priv->encoder, bridge, NULL);
> +	ret = drm_bridge_attach(&priv->encoder, bridge, NULL, 0);
>  	if (ret) {
>  		dev_err(dev, "Unable to attach bridge");
>  		return ret;
> diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c
> index 07f7090d08b3..8feaa1b81473 100644
> --- a/drivers/gpu/drm/mcde/mcde_dsi.c
> +++ b/drivers/gpu/drm/mcde/mcde_dsi.c
> @@ -817,12 +817,16 @@ mcde_dsi_connector_helper_funcs = {
>  	.get_modes = mcde_dsi_get_modes,
>  };
>  
> -static int mcde_dsi_bridge_attach(struct drm_bridge *bridge)
> +static int mcde_dsi_bridge_attach(struct drm_bridge *bridge,
> +				  enum drm_bridge_attach_flags flags)
>  {
>  	struct mcde_dsi *d = bridge_to_mcde_dsi(bridge);
>  	struct drm_device *drm = bridge->dev;
>  	int ret;
>  
> +	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> +		return -EINVAL;
> +
>  	drm_connector_helper_add(&d->connector,
>  				 &mcde_dsi_connector_helper_funcs);
>  
> @@ -842,7 +846,7 @@ static int mcde_dsi_bridge_attach(struct drm_bridge *bridge)
>  	/* The encoder in the bridge attached to the DSI bridge */
>  	drm_connector_attach_encoder(&d->connector, bridge->encoder);
>  	/* Then we attach the DSI bridge to the output (panel etc) bridge */
> -	ret = drm_bridge_attach(bridge->encoder, d->bridge_out, bridge);
> +	ret = drm_bridge_attach(bridge->encoder, d->bridge_out, bridge, flags);
>  	if (ret) {
>  		dev_err(d->dev, "failed to attach the DSI bridge\n");
>  		return ret;
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index be6d95c5ff25..cfb47b054d20 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -606,7 +606,7 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)
>  	/* Currently DPI0 is fixed to be driven by OVL1 */
>  	dpi->encoder.possible_crtcs = BIT(1);
>  
> -	ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL);
> +	ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL, 0);
>  	if (ret) {
>  		dev_err(dev, "Failed to attach bridge: %d\n", ret);
>  		goto err_cleanup;
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 224afb666881..d1129d4077a9 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -821,7 +821,7 @@ static int mtk_dsi_create_conn_enc(struct drm_device *drm, struct mtk_dsi *dsi)
>  
>  	/* If there's a bridge, attach to it and let it create the connector */
>  	if (dsi->bridge) {
> -		ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL);
> +		ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL, 0);
>  		if (ret) {
>  			DRM_ERROR("Failed to attach bridge to drm\n");
>  			goto err_encoder_cleanup;
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index ce91b61364eb..f0e55f219772 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -1294,11 +1294,15 @@ static void mtk_hdmi_hpd_event(bool hpd, struct device *dev)
>   * Bridge callbacks
>   */
>  
> -static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge)
> +static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge,
> +				  enum drm_bridge_attach_flags flags)
>  {
>  	struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
>  	int ret;
>  
> +	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> +		return -EINVAL;
> +
>  	ret = drm_connector_init(bridge->encoder->dev, &hdmi->conn,
>  				 &mtk_hdmi_connector_funcs,
>  				 DRM_MODE_CONNECTOR_HDMIA);
> @@ -1322,7 +1326,7 @@ static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge)
>  
>  	if (hdmi->next_bridge) {
>  		ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge,
> -					bridge);
> +					bridge, flags);
>  		if (ret) {
>  			dev_err(hdmi->dev,
>  				"Failed to attach external bridge: %d\n", ret);
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> index 271aa7bbca92..50b9bddf92b3 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> @@ -664,7 +664,7 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
>  	bridge = &dsi_bridge->base;
>  	bridge->funcs = &dsi_mgr_bridge_funcs;
>  
> -	ret = drm_bridge_attach(encoder, bridge, NULL);
> +	ret = drm_bridge_attach(encoder, bridge, NULL, 0);
>  	if (ret)
>  		goto fail;
>  
> @@ -693,7 +693,7 @@ struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id)
>  	encoder = msm_dsi->encoder;
>  
>  	/* link the internal dsi bridge to the external bridge */
> -	drm_bridge_attach(encoder, ext_bridge, int_bridge);
> +	drm_bridge_attach(encoder, ext_bridge, int_bridge, 0);
>  
>  	/*
>  	 * we need the drm_connector created by the external bridge
> diff --git a/drivers/gpu/drm/msm/edp/edp_bridge.c b/drivers/gpu/drm/msm/edp/edp_bridge.c
> index 2950bba4aca9..b59451d9712c 100644
> --- a/drivers/gpu/drm/msm/edp/edp_bridge.c
> +++ b/drivers/gpu/drm/msm/edp/edp_bridge.c
> @@ -91,7 +91,7 @@ struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp)
>  	bridge = &edp_bridge->base;
>  	bridge->funcs = &edp_bridge_funcs;
>  
> -	ret = drm_bridge_attach(edp->encoder, bridge, NULL);
> +	ret = drm_bridge_attach(edp->encoder, bridge, NULL, 0);
>  	if (ret)
>  		goto fail;
>  
> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> index c8dbd82854c2..7a685f0edd88 100644
> --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> @@ -285,7 +285,7 @@ struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
>  	bridge = &hdmi_bridge->base;
>  	bridge->funcs = &msm_hdmi_bridge_funcs;
>  
> -	ret = drm_bridge_attach(hdmi->encoder, bridge, NULL);
> +	ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, 0);
>  	if (ret)
>  		goto fail;
>  
> diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
> index 9f652d2e7af1..2988af9ae743 100644
> --- a/drivers/gpu/drm/omapdrm/omap_drv.c
> +++ b/drivers/gpu/drm/omapdrm/omap_drv.c
> @@ -296,7 +296,7 @@ static int omap_modeset_init(struct drm_device *dev)
>  
>  		if (pipe->output->bridge) {
>  			ret = drm_bridge_attach(pipe->encoder,
> -						pipe->output->bridge, NULL);
> +						pipe->output->bridge, NULL, 0);
>  			if (ret < 0)
>  				return ret;
>  		}
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
> index 0f00bdfe2366..26603843c318 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
> @@ -120,7 +120,7 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
>  	 * Attach the bridge to the encoder. The bridge will create the
>  	 * connector.
>  	 */
> -	ret = drm_bridge_attach(encoder, bridge, NULL);
> +	ret = drm_bridge_attach(encoder, bridge, NULL, 0);
>  	if (ret) {
>  		drm_encoder_cleanup(encoder);
>  		return ret;
> diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> index 1c62578590f4..7e976723c9b1 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> @@ -605,7 +605,8 @@ static void rcar_lvds_mode_set(struct drm_bridge *bridge,
>  	rcar_lvds_get_lvds_mode(lvds);
>  }
>  
> -static int rcar_lvds_attach(struct drm_bridge *bridge)
> +static int rcar_lvds_attach(struct drm_bridge *bridge,
> +			    enum drm_bridge_attach_flags flags)
>  {
>  	struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
>  	struct drm_connector *connector = &lvds->connector;
> @@ -615,7 +616,10 @@ static int rcar_lvds_attach(struct drm_bridge *bridge)
>  	/* If we have a next bridge just attach it. */
>  	if (lvds->next_bridge)
>  		return drm_bridge_attach(bridge->encoder, lvds->next_bridge,
> -					 bridge);
> +					 bridge, flags);
> +
> +	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> +		return -EINVAL;
>  
>  	/* Otherwise if we have a panel, create a connector. */
>  	if (!lvds->panel)
> diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c
> index 64aefa856896..addf56209f46 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
> @@ -440,7 +440,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
>  			goto err_free_connector;
>  		}
>  	} else {
> -		ret = drm_bridge_attach(encoder, lvds->bridge, NULL);
> +		ret = drm_bridge_attach(encoder, lvds->bridge, NULL, 0);
>  		if (ret) {
>  			DRM_DEV_ERROR(drm_dev->dev,
>  				      "failed to attach bridge: %d\n", ret);
> diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.c b/drivers/gpu/drm/rockchip/rockchip_rgb.c
> index 89e0bb0fe0ab..f586e06f3df2 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_rgb.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_rgb.c
> @@ -142,7 +142,7 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev,
>  
>  	rgb->bridge = bridge;
>  
> -	ret = drm_bridge_attach(encoder, rgb->bridge, NULL);
> +	ret = drm_bridge_attach(encoder, rgb->bridge, NULL, 0);
>  	if (ret) {
>  		DRM_DEV_ERROR(drm_dev->dev,
>  			      "failed to attach bridge: %d\n", ret);
> diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
> index e55870190bf5..0baca6368c36 100644
> --- a/drivers/gpu/drm/sti/sti_dvo.c
> +++ b/drivers/gpu/drm/sti/sti_dvo.c
> @@ -466,7 +466,7 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
>  	bridge->of_node = dvo->dev.of_node;
>  	drm_bridge_add(bridge);
>  
> -	err = drm_bridge_attach(encoder, bridge, NULL);
> +	err = drm_bridge_attach(encoder, bridge, NULL, 0);
>  	if (err) {
>  		DRM_ERROR("Failed to attach bridge\n");
>  		return err;
> diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
> index 94e404f13234..6a3d8b800950 100644
> --- a/drivers/gpu/drm/sti/sti_hda.c
> +++ b/drivers/gpu/drm/sti/sti_hda.c
> @@ -700,7 +700,7 @@ static int sti_hda_bind(struct device *dev, struct device *master, void *data)
>  
>  	bridge->driver_private = hda;
>  	bridge->funcs = &sti_hda_bridge_funcs;
> -	drm_bridge_attach(encoder, bridge, NULL);
> +	drm_bridge_attach(encoder, bridge, NULL, 0);
>  
>  	connector->encoder = encoder;
>  
> diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
> index 9862c322f0c4..2d080a6040d9 100644
> --- a/drivers/gpu/drm/sti/sti_hdmi.c
> +++ b/drivers/gpu/drm/sti/sti_hdmi.c
> @@ -1279,7 +1279,7 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
>  
>  	bridge->driver_private = hdmi;
>  	bridge->funcs = &sti_hdmi_bridge_funcs;
> -	drm_bridge_attach(encoder, bridge, NULL);
> +	drm_bridge_attach(encoder, bridge, NULL, 0);
>  
>  	connector->encoder = encoder;
>  
> diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
> index 3ab4fbf8eb0d..18561d977d84 100644
> --- a/drivers/gpu/drm/stm/ltdc.c
> +++ b/drivers/gpu/drm/stm/ltdc.c
> @@ -1055,7 +1055,7 @@ static int ltdc_encoder_init(struct drm_device *ddev, struct drm_bridge *bridge)
>  	drm_encoder_init(ddev, encoder, &ltdc_encoder_funcs,
>  			 DRM_MODE_ENCODER_DPI, NULL);
>  
> -	ret = drm_bridge_attach(encoder, bridge, NULL);
> +	ret = drm_bridge_attach(encoder, bridge, NULL, 0);
>  	if (ret) {
>  		drm_encoder_cleanup(encoder);
>  		return -EINVAL;
> diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c
> index 7fbf425acb55..693163c70eee 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_lvds.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c
> @@ -155,7 +155,7 @@ int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon)
>  	}
>  
>  	if (bridge) {
> -		ret = drm_bridge_attach(encoder, bridge, NULL);
> +		ret = drm_bridge_attach(encoder, bridge, NULL, 0);
>  		if (ret) {
>  			dev_err(drm->dev, "Couldn't attach our bridge\n");
>  			goto err_cleanup_connector;
> diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> index aac56983f208..22463f5302c4 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> @@ -252,7 +252,7 @@ int sun4i_rgb_init(struct drm_device *drm, struct sun4i_tcon *tcon)
>  	}
>  
>  	if (rgb->bridge) {
> -		ret = drm_bridge_attach(encoder, rgb->bridge, NULL);
> +		ret = drm_bridge_attach(encoder, rgb->bridge, NULL, 0);
>  		if (ret) {
>  			dev_err(drm->dev, "Couldn't attach our bridge\n");
>  			goto err_cleanup_connector;
> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_external.c b/drivers/gpu/drm/tilcdc/tilcdc_external.c
> index 43d756b7810e..1ed765ce9349 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_external.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c
> @@ -94,7 +94,7 @@ int tilcdc_attach_bridge(struct drm_device *ddev, struct drm_bridge *bridge)
>  
>  	priv->external_encoder->possible_crtcs = BIT(0);
>  
> -	ret = drm_bridge_attach(priv->external_encoder, bridge, NULL);
> +	ret = drm_bridge_attach(priv->external_encoder, bridge, NULL, 0);
>  	if (ret) {
>  		dev_err(ddev->dev, "drm_bridge_attach() failed %d\n", ret);
>  		return ret;
> diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c
> index 8a27a6acee61..59662d735432 100644
> --- a/drivers/gpu/drm/vc4/vc4_dpi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dpi.c
> @@ -251,7 +251,7 @@ static int vc4_dpi_init_bridge(struct vc4_dpi *dpi)
>  	if (panel)
>  		bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_DPI);
>  
> -	return drm_bridge_attach(dpi->encoder, bridge, NULL);
> +	return drm_bridge_attach(dpi->encoder, bridge, NULL, 0);
>  }
>  
>  static int vc4_dpi_bind(struct device *dev, struct device *master, void *data)
> diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
> index c78fa8144776..f5d5b6837831 100644
> --- a/drivers/gpu/drm/vc4/vc4_dsi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dsi.c
> @@ -1599,7 +1599,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
>  			 DRM_MODE_ENCODER_DSI, NULL);
>  	drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs);
>  
> -	ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL);
> +	ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL, 0);
>  	if (ret) {
>  		dev_err(dev, "bridge attach failed: %d\n", ret);
>  		return ret;
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 7db6ca0fd75d..928d046ad99d 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -34,6 +34,17 @@ struct drm_bridge_timings;
>  struct drm_panel;
>  struct i2c_adapter;
>  
> +/**
> + * enum drm_bridge_attach_flags - Flags for &drm_bridge_funcs.attach
> + */
> +enum drm_bridge_attach_flags {
> +	/**
> +	 * @DRM_BRIDGE_ATTACH_NO_CONNECTOR: When this flag is set the bridge
> +	 * shall not create a drm_connector.
> +	 */
> +	DRM_BRIDGE_ATTACH_NO_CONNECTOR = BIT(0),
> +};
> +
>  /**
>   * struct drm_bridge_funcs - drm_bridge control functions
>   */
> @@ -42,7 +53,8 @@ struct drm_bridge_funcs {
>  	 * @attach:
>  	 *
>  	 * This callback is invoked whenever our bridge is being attached to a
> -	 * &drm_encoder.
> +	 * &drm_encoder. The flags argument tunes the behaviour of the attach
> +	 * operation (see DRM_BRIDGE_ATTACH_*).
>  	 *
>  	 * The attach callback is optional.
>  	 *
> @@ -50,7 +62,8 @@ struct drm_bridge_funcs {
>  	 *
>  	 * Zero on success, error code on failure.
>  	 */
> -	int (*attach)(struct drm_bridge *bridge);
> +	int (*attach)(struct drm_bridge *bridge,
> +		      enum drm_bridge_attach_flags flags);
>  
>  	/**
>  	 * @detach:
> @@ -571,7 +584,8 @@ void drm_bridge_add(struct drm_bridge *bridge);
>  void drm_bridge_remove(struct drm_bridge *bridge);
>  struct drm_bridge *of_drm_find_bridge(struct device_node *np);
>  int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
> -		      struct drm_bridge *previous);
> +		      struct drm_bridge *previous,
> +		      enum drm_bridge_attach_flags flags);
>  
>  bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
>  			   const struct drm_display_mode *mode,

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

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

* Re: [PATCH v2 06/50] drm/bridge: dumb-vga-dac: Rename internal symbols to simple-bridge
  2019-08-20  1:16 ` [PATCH v2 06/50] drm/bridge: dumb-vga-dac: Rename internal symbols to simple-bridge Laurent Pinchart
@ 2019-08-22 15:39   ` Boris Brezillon
  2019-08-26 11:25   ` Maxime Ripard
  1 sibling, 0 replies; 106+ messages in thread
From: Boris Brezillon @ 2019-08-22 15:39 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

On Tue, 20 Aug 2019 04:16:37 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

> The dumb-vga-dac driver is a simple DRM bridge driver for simple VGA
> DACs that don't require configuration. Other non-VGA bridges fall in a
> similar category, and would benefit from a common driver. Prepare for
> this by renaming the internal symbols from dumb-vga-dac to
> simple-bridge.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>

> ---
>  drivers/gpu/drm/bridge/dumb-vga-dac.c | 154 +++++++++++++-------------
>  1 file changed, 77 insertions(+), 77 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
> index 74ebca58eb1f..03ceb0cd8b9e 100644
> --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
> +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
> @@ -16,7 +16,7 @@
>  #include <drm/drm_print.h>
>  #include <drm/drm_probe_helper.h>
>  
> -struct dumb_vga {
> +struct simple_bridge {
>  	struct drm_bridge	bridge;
>  	struct drm_connector	connector;
>  
> @@ -24,28 +24,28 @@ struct dumb_vga {
>  	struct regulator	*vdd;
>  };
>  
> -static inline struct dumb_vga *
> -drm_bridge_to_dumb_vga(struct drm_bridge *bridge)
> +static inline struct simple_bridge *
> +drm_bridge_to_simple_bridge(struct drm_bridge *bridge)
>  {
> -	return container_of(bridge, struct dumb_vga, bridge);
> +	return container_of(bridge, struct simple_bridge, bridge);
>  }
>  
> -static inline struct dumb_vga *
> -drm_connector_to_dumb_vga(struct drm_connector *connector)
> +static inline struct simple_bridge *
> +drm_connector_to_simple_bridge(struct drm_connector *connector)
>  {
> -	return container_of(connector, struct dumb_vga, connector);
> +	return container_of(connector, struct simple_bridge, connector);
>  }
>  
> -static int dumb_vga_get_modes(struct drm_connector *connector)
> +static int simple_bridge_get_modes(struct drm_connector *connector)
>  {
> -	struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
> +	struct simple_bridge *sbridge = drm_connector_to_simple_bridge(connector);
>  	struct edid *edid;
>  	int ret;
>  
> -	if (!vga->ddc)
> +	if (!sbridge->ddc)
>  		goto fallback;
>  
> -	edid = drm_get_edid(connector, vga->ddc);
> +	edid = drm_get_edid(connector, sbridge->ddc);
>  	if (!edid) {
>  		DRM_INFO("EDID readout failed, falling back to standard modes\n");
>  		goto fallback;
> @@ -69,14 +69,14 @@ static int dumb_vga_get_modes(struct drm_connector *connector)
>  	return ret;
>  }
>  
> -static const struct drm_connector_helper_funcs dumb_vga_con_helper_funcs = {
> -	.get_modes	= dumb_vga_get_modes,
> +static const struct drm_connector_helper_funcs simple_bridge_con_helper_funcs = {
> +	.get_modes	= simple_bridge_get_modes,
>  };
>  
>  static enum drm_connector_status
> -dumb_vga_connector_detect(struct drm_connector *connector, bool force)
> +simple_bridge_connector_detect(struct drm_connector *connector, bool force)
>  {
> -	struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
> +	struct simple_bridge *sbridge = drm_connector_to_simple_bridge(connector);
>  
>  	/*
>  	 * Even if we have an I2C bus, we can't assume that the cable
> @@ -84,14 +84,14 @@ dumb_vga_connector_detect(struct drm_connector *connector, bool force)
>  	 * wire the DDC pins, or the I2C bus might not be working at
>  	 * all.
>  	 */
> -	if (vga->ddc && drm_probe_ddc(vga->ddc))
> +	if (sbridge->ddc && drm_probe_ddc(sbridge->ddc))
>  		return connector_status_connected;
>  
>  	return connector_status_unknown;
>  }
>  
> -static const struct drm_connector_funcs dumb_vga_con_funcs = {
> -	.detect			= dumb_vga_connector_detect,
> +static const struct drm_connector_funcs simple_bridge_con_funcs = {
> +	.detect			= simple_bridge_connector_detect,
>  	.fill_modes		= drm_helper_probe_single_connector_modes,
>  	.destroy		= drm_connector_cleanup,
>  	.reset			= drm_atomic_helper_connector_reset,
> @@ -99,10 +99,10 @@ static const struct drm_connector_funcs dumb_vga_con_funcs = {
>  	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
>  };
>  
> -static int dumb_vga_attach(struct drm_bridge *bridge,
> -			   enum drm_bridge_attach_flags flags)
> +static int simple_bridge_attach(struct drm_bridge *bridge,
> +				enum drm_bridge_attach_flags flags)
>  {
> -	struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
> +	struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
>  	int ret;
>  
>  	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> @@ -113,50 +113,50 @@ static int dumb_vga_attach(struct drm_bridge *bridge,
>  		return -ENODEV;
>  	}
>  
> -	drm_connector_helper_add(&vga->connector,
> -				 &dumb_vga_con_helper_funcs);
> -	ret = drm_connector_init_with_ddc(bridge->dev, &vga->connector,
> -					  &dumb_vga_con_funcs,
> +	drm_connector_helper_add(&sbridge->connector,
> +				 &simple_bridge_con_helper_funcs);
> +	ret = drm_connector_init_with_ddc(bridge->dev, &sbridge->connector,
> +					  &simple_bridge_con_funcs,
>  					  DRM_MODE_CONNECTOR_VGA,
> -					  vga->ddc);
> +					  sbridge->ddc);
>  	if (ret) {
>  		DRM_ERROR("Failed to initialize connector\n");
>  		return ret;
>  	}
>  
> -	drm_connector_attach_encoder(&vga->connector,
> +	drm_connector_attach_encoder(&sbridge->connector,
>  					  bridge->encoder);
>  
>  	return 0;
>  }
>  
> -static void dumb_vga_enable(struct drm_bridge *bridge)
> +static void simple_bridge_enable(struct drm_bridge *bridge)
>  {
> -	struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
> +	struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
>  	int ret = 0;
>  
> -	if (vga->vdd)
> -		ret = regulator_enable(vga->vdd);
> +	if (sbridge->vdd)
> +		ret = regulator_enable(sbridge->vdd);
>  
>  	if (ret)
>  		DRM_ERROR("Failed to enable vdd regulator: %d\n", ret);
>  }
>  
> -static void dumb_vga_disable(struct drm_bridge *bridge)
> +static void simple_bridge_disable(struct drm_bridge *bridge)
>  {
> -	struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
> +	struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
>  
> -	if (vga->vdd)
> -		regulator_disable(vga->vdd);
> +	if (sbridge->vdd)
> +		regulator_disable(sbridge->vdd);
>  }
>  
> -static const struct drm_bridge_funcs dumb_vga_bridge_funcs = {
> -	.attach		= dumb_vga_attach,
> -	.enable		= dumb_vga_enable,
> -	.disable	= dumb_vga_disable,
> +static const struct drm_bridge_funcs simple_bridge_bridge_funcs = {
> +	.attach		= simple_bridge_attach,
> +	.enable		= simple_bridge_enable,
> +	.disable	= simple_bridge_disable,
>  };
>  
> -static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
> +static struct i2c_adapter *simple_bridge_retrieve_ddc(struct device *dev)
>  {
>  	struct device_node *phandle, *remote;
>  	struct i2c_adapter *ddc;
> @@ -178,53 +178,53 @@ static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
>  	return ddc;
>  }
>  
> -static int dumb_vga_probe(struct platform_device *pdev)
> +static int simple_bridge_probe(struct platform_device *pdev)
>  {
> -	struct dumb_vga *vga;
> +	struct simple_bridge *sbridge;
>  
> -	vga = devm_kzalloc(&pdev->dev, sizeof(*vga), GFP_KERNEL);
> -	if (!vga)
> +	sbridge = devm_kzalloc(&pdev->dev, sizeof(*sbridge), GFP_KERNEL);
> +	if (!sbridge)
>  		return -ENOMEM;
> -	platform_set_drvdata(pdev, vga);
> +	platform_set_drvdata(pdev, sbridge);
>  
> -	vga->vdd = devm_regulator_get_optional(&pdev->dev, "vdd");
> -	if (IS_ERR(vga->vdd)) {
> -		int ret = PTR_ERR(vga->vdd);
> +	sbridge->vdd = devm_regulator_get_optional(&pdev->dev, "vdd");
> +	if (IS_ERR(sbridge->vdd)) {
> +		int ret = PTR_ERR(sbridge->vdd);
>  		if (ret == -EPROBE_DEFER)
>  			return -EPROBE_DEFER;
> -		vga->vdd = NULL;
> +		sbridge->vdd = NULL;
>  		dev_dbg(&pdev->dev, "No vdd regulator found: %d\n", ret);
>  	}
>  
> -	vga->ddc = dumb_vga_retrieve_ddc(&pdev->dev);
> -	if (IS_ERR(vga->ddc)) {
> -		if (PTR_ERR(vga->ddc) == -ENODEV) {
> +	sbridge->ddc = simple_bridge_retrieve_ddc(&pdev->dev);
> +	if (IS_ERR(sbridge->ddc)) {
> +		if (PTR_ERR(sbridge->ddc) == -ENODEV) {
>  			dev_dbg(&pdev->dev,
>  				"No i2c bus specified. Disabling EDID readout\n");
> -			vga->ddc = NULL;
> +			sbridge->ddc = NULL;
>  		} else {
>  			dev_err(&pdev->dev, "Couldn't retrieve i2c bus\n");
> -			return PTR_ERR(vga->ddc);
> +			return PTR_ERR(sbridge->ddc);
>  		}
>  	}
>  
> -	vga->bridge.funcs = &dumb_vga_bridge_funcs;
> -	vga->bridge.of_node = pdev->dev.of_node;
> -	vga->bridge.timings = of_device_get_match_data(&pdev->dev);
> +	sbridge->bridge.funcs = &simple_bridge_bridge_funcs;
> +	sbridge->bridge.of_node = pdev->dev.of_node;
> +	sbridge->bridge.timings = of_device_get_match_data(&pdev->dev);
>  
> -	drm_bridge_add(&vga->bridge);
> +	drm_bridge_add(&sbridge->bridge);
>  
>  	return 0;
>  }
>  
> -static int dumb_vga_remove(struct platform_device *pdev)
> +static int simple_bridge_remove(struct platform_device *pdev)
>  {
> -	struct dumb_vga *vga = platform_get_drvdata(pdev);
> +	struct simple_bridge *sbridge = platform_get_drvdata(pdev);
>  
> -	drm_bridge_remove(&vga->bridge);
> +	drm_bridge_remove(&sbridge->bridge);
>  
> -	if (vga->ddc)
> -		i2c_put_adapter(vga->ddc);
> +	if (sbridge->ddc)
> +		i2c_put_adapter(sbridge->ddc);
>  
>  	return 0;
>  }
> @@ -235,7 +235,7 @@ static int dumb_vga_remove(struct platform_device *pdev)
>   * NOTE: the ADV7123EP seems to have other timings and need a new timings
>   * set if used.
>   */
> -static const struct drm_bridge_timings default_dac_timings = {
> +static const struct drm_bridge_timings default_bridge_timings = {
>  	/* Timing specifications, datasheet page 7 */
>  	.input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE,
>  	.setup_time_ps = 500,
> @@ -246,7 +246,7 @@ static const struct drm_bridge_timings default_dac_timings = {
>   * Information taken from the THS8134, THS8134A, THS8134B datasheet named
>   * "SLVS205D", dated May 1990, revised March 2000.
>   */
> -static const struct drm_bridge_timings ti_ths8134_dac_timings = {
> +static const struct drm_bridge_timings ti_ths8134_bridge_timings = {
>  	/* From timing diagram, datasheet page 9 */
>  	.input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE,
>  	/* From datasheet, page 12 */
> @@ -259,7 +259,7 @@ static const struct drm_bridge_timings ti_ths8134_dac_timings = {
>   * Information taken from the THS8135 datasheet named "SLAS343B", dated
>   * May 2001, revised April 2013.
>   */
> -static const struct drm_bridge_timings ti_ths8135_dac_timings = {
> +static const struct drm_bridge_timings ti_ths8135_bridge_timings = {
>  	/* From timing diagram, datasheet page 14 */
>  	.input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE,
>  	/* From datasheet, page 16 */
> @@ -267,37 +267,37 @@ static const struct drm_bridge_timings ti_ths8135_dac_timings = {
>  	.hold_time_ps = 500,
>  };
>  
> -static const struct of_device_id dumb_vga_match[] = {
> +static const struct of_device_id simple_bridge_match[] = {
>  	{
>  		.compatible = "dumb-vga-dac",
>  		.data = NULL,
>  	},
>  	{
>  		.compatible = "adi,adv7123",
> -		.data = &default_dac_timings,
> +		.data = &default_bridge_timings,
>  	},
>  	{
>  		.compatible = "ti,ths8135",
> -		.data = &ti_ths8135_dac_timings,
> +		.data = &ti_ths8135_bridge_timings,
>  	},
>  	{
>  		.compatible = "ti,ths8134",
> -		.data = &ti_ths8134_dac_timings,
> +		.data = &ti_ths8134_bridge_timings,
>  	},
>  	{},
>  };
> -MODULE_DEVICE_TABLE(of, dumb_vga_match);
> +MODULE_DEVICE_TABLE(of, simple_bridge_match);
>  
> -static struct platform_driver dumb_vga_driver = {
> -	.probe	= dumb_vga_probe,
> -	.remove	= dumb_vga_remove,
> +static struct platform_driver simple_bridge_driver = {
> +	.probe	= simple_bridge_probe,
> +	.remove	= simple_bridge_remove,
>  	.driver		= {
>  		.name		= "dumb-vga-dac",
> -		.of_match_table	= dumb_vga_match,
> +		.of_match_table	= simple_bridge_match,
>  	},
>  };
> -module_platform_driver(dumb_vga_driver);
> +module_platform_driver(simple_bridge_driver);
>  
>  MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
> -MODULE_DESCRIPTION("Dumb VGA DAC bridge driver");
> +MODULE_DESCRIPTION("Simple DRM bridge driver");
>  MODULE_LICENSE("GPL");

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

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

* Re: [PATCH v2 07/50] drm/bridge: dumb-vga-dac: Rename driver to simple-bridge
  2019-08-20  1:16 ` [PATCH v2 07/50] drm/bridge: dumb-vga-dac: Rename driver " Laurent Pinchart
@ 2019-08-22 15:42   ` Boris Brezillon
  2019-08-26 11:26   ` Maxime Ripard
  1 sibling, 0 replies; 106+ messages in thread
From: Boris Brezillon @ 2019-08-22 15:42 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sebastian Reichel, dri-devel,
	Russell King, Chen-Yu Tsai, Simon Horman, Sean Paul

On Tue, 20 Aug 2019 04:16:38 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

> The dumb-vga-dac driver can support simple DRM bridges without being
> limited to VGA DACs. Rename it to simple-bridge.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>

> ---
>  arch/arm/configs/davinci_all_defconfig           |  2 +-
>  arch/arm/configs/integrator_defconfig            |  2 +-
>  arch/arm/configs/multi_v7_defconfig              |  2 +-
>  arch/arm/configs/shmobile_defconfig              |  2 +-
>  arch/arm/configs/sunxi_defconfig                 |  2 +-
>  arch/arm/configs/versatile_defconfig             |  2 +-
>  drivers/gpu/drm/bridge/Kconfig                   | 16 ++++++++--------
>  drivers/gpu/drm/bridge/Makefile                  |  2 +-
>  .../bridge/{dumb-vga-dac.c => simple-bridge.c}   |  2 +-
>  9 files changed, 16 insertions(+), 16 deletions(-)
>  rename drivers/gpu/drm/bridge/{dumb-vga-dac.c => simple-bridge.c} (99%)
> 
> diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig
> index 9a32a8c0f873..4b8cf51b2abd 100644
> --- a/arch/arm/configs/davinci_all_defconfig
> +++ b/arch/arm/configs/davinci_all_defconfig
> @@ -155,7 +155,7 @@ CONFIG_VIDEO_TVP514X=m
>  CONFIG_VIDEO_ADV7343=m
>  CONFIG_DRM=m
>  CONFIG_DRM_TILCDC=m
> -CONFIG_DRM_DUMB_VGA_DAC=m
> +CONFIG_DRM_SIMPLE_BRIDGE=m
>  CONFIG_DRM_TINYDRM=m
>  CONFIG_TINYDRM_ST7586=m
>  CONFIG_FB=y
> diff --git a/arch/arm/configs/integrator_defconfig b/arch/arm/configs/integrator_defconfig
> index 2f0a762dc3a0..a9755c501bec 100644
> --- a/arch/arm/configs/integrator_defconfig
> +++ b/arch/arm/configs/integrator_defconfig
> @@ -55,7 +55,7 @@ CONFIG_SMC91X=y
>  # CONFIG_KEYBOARD_ATKBD is not set
>  # CONFIG_SERIO_SERPORT is not set
>  CONFIG_DRM=y
> -CONFIG_DRM_DUMB_VGA_DAC=y
> +CONFIG_DRM_SIMPLE_BRIDGE=y
>  CONFIG_DRM_PL111=y
>  CONFIG_FB_MODE_HELPERS=y
>  CONFIG_FB_MATROX=y
> diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
> index 6a40bc2ef271..9eefc0cc29bc 100644
> --- a/arch/arm/configs/multi_v7_defconfig
> +++ b/arch/arm/configs/multi_v7_defconfig
> @@ -644,11 +644,11 @@ CONFIG_DRM_PANEL_ORISETECH_OTM8009A=m
>  CONFIG_DRM_PANEL_RAYDIUM_RM68200=m
>  CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03=m
>  CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0=m
> -CONFIG_DRM_DUMB_VGA_DAC=m
>  CONFIG_DRM_NXP_PTN3460=m
>  CONFIG_DRM_PARADE_PS8622=m
>  CONFIG_DRM_SII902X=m
>  CONFIG_DRM_SII9234=m
> +CONFIG_DRM_SIMPLE_BRIDGE=m
>  CONFIG_DRM_TOSHIBA_TC358764=m
>  CONFIG_DRM_I2C_ADV7511=m
>  CONFIG_DRM_I2C_ADV7511_AUDIO=y
> diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig
> index c6c70355141c..a8e7827a7214 100644
> --- a/arch/arm/configs/shmobile_defconfig
> +++ b/arch/arm/configs/shmobile_defconfig
> @@ -125,8 +125,8 @@ CONFIG_VIDEO_ADV7604=y
>  CONFIG_VIDEO_ML86V7667=y
>  CONFIG_DRM=y
>  CONFIG_DRM_RCAR_DU=y
> -CONFIG_DRM_DUMB_VGA_DAC=y
>  CONFIG_DRM_SII902X=y
> +CONFIG_DRM_SIMPLE_BRIDGE=y
>  CONFIG_DRM_I2C_ADV7511=y
>  CONFIG_DRM_I2C_ADV7511_AUDIO=y
>  CONFIG_FB_SH_MOBILE_LCDC=y
> diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig
> index df433abfcb02..19cccae84a19 100644
> --- a/arch/arm/configs/sunxi_defconfig
> +++ b/arch/arm/configs/sunxi_defconfig
> @@ -99,7 +99,7 @@ CONFIG_RC_DEVICES=y
>  CONFIG_IR_SUNXI=y
>  CONFIG_DRM=y
>  CONFIG_DRM_SUN4I=y
> -CONFIG_DRM_DUMB_VGA_DAC=y
> +CONFIG_DRM_SIMPLE_BRIDGE=y
>  CONFIG_FB_SIMPLE=y
>  CONFIG_SOUND=y
>  CONFIG_SND=y
> diff --git a/arch/arm/configs/versatile_defconfig b/arch/arm/configs/versatile_defconfig
> index fe4d4b596585..767935337413 100644
> --- a/arch/arm/configs/versatile_defconfig
> +++ b/arch/arm/configs/versatile_defconfig
> @@ -59,7 +59,7 @@ CONFIG_GPIO_PL061=y
>  CONFIG_DRM=y
>  CONFIG_DRM_PANEL_ARM_VERSATILE=y
>  CONFIG_DRM_PANEL_SIMPLE=y
> -CONFIG_DRM_DUMB_VGA_DAC=y
> +CONFIG_DRM_SIMPLE_BRIDGE=y
>  CONFIG_DRM_PL111=y
>  CONFIG_FB_MODE_HELPERS=y
>  CONFIG_BACKLIGHT_CLASS_DEVICE=y
> diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
> index 1cc9f502c1f2..d0146438b0f5 100644
> --- a/drivers/gpu/drm/bridge/Kconfig
> +++ b/drivers/gpu/drm/bridge/Kconfig
> @@ -37,14 +37,6 @@ config DRM_CDNS_DSI
>  	  Support Cadence DPI to DSI bridge. This is an internal
>  	  bridge and is meant to be directly embedded in a SoC.
>  
> -config DRM_DUMB_VGA_DAC
> -	tristate "Dumb VGA DAC Bridge support"
> -	depends on OF
> -	select DRM_KMS_HELPER
> -	help
> -	  Support for non-programmable RGB to VGA DAC bridges, such as ADI
> -	  ADV7123, TI THS8134 and THS8135 or passive resistor ladder DACs.
> -
>  config DRM_LVDS_ENCODER
>  	tristate "Transparent parallel to LVDS encoder support"
>  	depends on OF
> @@ -109,6 +101,14 @@ config DRM_SII9234
>  	  It is an I2C driver, that detects connection of MHL bridge
>  	  and starts encapsulation of HDMI signal.
>  
> +config DRM_SIMPLE_BRIDGE
> +	tristate "Simple DRM bridge support"
> +	depends on OF
> +	select DRM_KMS_HELPER
> +	help
> +	  Support for non-programmable DRM bridges, such as ADI ADV7123, TI
> +	  THS8134 and THS8135 or passive resistor ladder DACs.
> +
>  config DRM_THINE_THC63LVD1024
>  	tristate "Thine THC63LVD1024 LVDS decoder bridge"
>  	depends on OF
> diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
> index 4934fcf5a6f8..6ff7f2adbb0e 100644
> --- a/drivers/gpu/drm/bridge/Makefile
> +++ b/drivers/gpu/drm/bridge/Makefile
> @@ -1,7 +1,6 @@
>  # SPDX-License-Identifier: GPL-2.0
>  obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
>  obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o
> -obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
>  obj-$(CONFIG_DRM_LVDS_ENCODER) += lvds-encoder.o
>  obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o
>  obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
> @@ -9,6 +8,7 @@ obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
>  obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o
>  obj-$(CONFIG_DRM_SII902X) += sii902x.o
>  obj-$(CONFIG_DRM_SII9234) += sii9234.o
> +obj-$(CONFIG_DRM_SIMPLE_BRIDGE) += simple-bridge.o
>  obj-$(CONFIG_DRM_THINE_THC63LVD1024) += thc63lvd1024.o
>  obj-$(CONFIG_DRM_TOSHIBA_TC358764) += tc358764.o
>  obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o
> diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/simple-bridge.c
> similarity index 99%
> rename from drivers/gpu/drm/bridge/dumb-vga-dac.c
> rename to drivers/gpu/drm/bridge/simple-bridge.c
> index 03ceb0cd8b9e..7551a361f22e 100644
> --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
> +++ b/drivers/gpu/drm/bridge/simple-bridge.c
> @@ -292,7 +292,7 @@ static struct platform_driver simple_bridge_driver = {
>  	.probe	= simple_bridge_probe,
>  	.remove	= simple_bridge_remove,
>  	.driver		= {
> -		.name		= "dumb-vga-dac",
> +		.name		= "simple-bridge",
>  		.of_match_table	= simple_bridge_match,
>  	},
>  };

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

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

* Re: [PATCH v2 08/50] drm/bridge: simple-bridge: Add support for non-VGA bridges
  2019-08-20  1:16 ` [PATCH v2 08/50] drm/bridge: simple-bridge: Add support for non-VGA bridges Laurent Pinchart
@ 2019-08-22 15:43   ` Boris Brezillon
  2019-08-26 11:27   ` Maxime Ripard
  1 sibling, 0 replies; 106+ messages in thread
From: Boris Brezillon @ 2019-08-22 15:43 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

On Tue, 20 Aug 2019 04:16:39 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

> Create a new simple_bridge_info structure that stores information about
> the bridge model, and store the bridge timings in there, along with the
> connector type. Use that new structure for of_device_id data. This
> enables support for non-VGA bridges.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
> Reviewed-by: Stefan Agner <stefan@agner.ch>

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>

> ---
> Changes since v1:
> 
> - Renamed simple_bridge_info.type field to connector_type
> ---
>  drivers/gpu/drm/bridge/simple-bridge.c | 41 ++++++++++++++++++--------
>  1 file changed, 29 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/simple-bridge.c b/drivers/gpu/drm/bridge/simple-bridge.c
> index 7551a361f22e..85aa852eafb4 100644
> --- a/drivers/gpu/drm/bridge/simple-bridge.c
> +++ b/drivers/gpu/drm/bridge/simple-bridge.c
> @@ -16,10 +16,17 @@
>  #include <drm/drm_print.h>
>  #include <drm/drm_probe_helper.h>
>  
> +struct simple_bridge_info {
> +	const struct drm_bridge_timings *timings;
> +	unsigned int connector_type;
> +};
> +
>  struct simple_bridge {
>  	struct drm_bridge	bridge;
>  	struct drm_connector	connector;
>  
> +	const struct simple_bridge_info *info;
> +
>  	struct i2c_adapter	*ddc;
>  	struct regulator	*vdd;
>  };
> @@ -117,7 +124,7 @@ static int simple_bridge_attach(struct drm_bridge *bridge,
>  				 &simple_bridge_con_helper_funcs);
>  	ret = drm_connector_init_with_ddc(bridge->dev, &sbridge->connector,
>  					  &simple_bridge_con_funcs,
> -					  DRM_MODE_CONNECTOR_VGA,
> +					  sbridge->info->connector_type,
>  					  sbridge->ddc);
>  	if (ret) {
>  		DRM_ERROR("Failed to initialize connector\n");
> @@ -187,6 +194,8 @@ static int simple_bridge_probe(struct platform_device *pdev)
>  		return -ENOMEM;
>  	platform_set_drvdata(pdev, sbridge);
>  
> +	sbridge->info = of_device_get_match_data(&pdev->dev);
> +
>  	sbridge->vdd = devm_regulator_get_optional(&pdev->dev, "vdd");
>  	if (IS_ERR(sbridge->vdd)) {
>  		int ret = PTR_ERR(sbridge->vdd);
> @@ -210,7 +219,7 @@ static int simple_bridge_probe(struct platform_device *pdev)
>  
>  	sbridge->bridge.funcs = &simple_bridge_bridge_funcs;
>  	sbridge->bridge.of_node = pdev->dev.of_node;
> -	sbridge->bridge.timings = of_device_get_match_data(&pdev->dev);
> +	sbridge->bridge.timings = sbridge->info->timings;
>  
>  	drm_bridge_add(&sbridge->bridge);
>  
> @@ -270,19 +279,27 @@ static const struct drm_bridge_timings ti_ths8135_bridge_timings = {
>  static const struct of_device_id simple_bridge_match[] = {
>  	{
>  		.compatible = "dumb-vga-dac",
> -		.data = NULL,
> -	},
> -	{
> +		.data = &(const struct simple_bridge_info) {
> +			.connector_type = DRM_MODE_CONNECTOR_VGA,
> +		},
> +	}, {
>  		.compatible = "adi,adv7123",
> -		.data = &default_bridge_timings,
> -	},
> -	{
> +		.data = &(const struct simple_bridge_info) {
> +			.timings = &default_bridge_timings,
> +			.connector_type = DRM_MODE_CONNECTOR_VGA,
> +		},
> +	}, {
>  		.compatible = "ti,ths8135",
> -		.data = &ti_ths8135_bridge_timings,
> -	},
> -	{
> +		.data = &(const struct simple_bridge_info) {
> +			.timings = &ti_ths8135_bridge_timings,
> +			.connector_type = DRM_MODE_CONNECTOR_VGA,
> +		},
> +	}, {
>  		.compatible = "ti,ths8134",
> -		.data = &ti_ths8134_bridge_timings,
> +		.data = &(const struct simple_bridge_info) {
> +			.timings = &ti_ths8134_bridge_timings,
> +			.connector_type = DRM_MODE_CONNECTOR_VGA,
> +		},
>  	},
>  	{},
>  };

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

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

* Re: [PATCH v2 09/50] drm/bridge: simple-bridge: Add support for enable GPIO
  2019-08-20  1:16 ` [PATCH v2 09/50] drm/bridge: simple-bridge: Add support for enable GPIO Laurent Pinchart
@ 2019-08-22 15:45   ` Boris Brezillon
  2019-08-26 11:33   ` Maxime Ripard
  1 sibling, 0 replies; 106+ messages in thread
From: Boris Brezillon @ 2019-08-22 15:45 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

On Tue, 20 Aug 2019 04:16:40 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

> If an enable GPIO is declared in the firmware, assert it when enabling
> the bridge and deassert it when disabling it.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
> Reviewed-by: Stefan Agner <stefan@agner.ch>

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>

> ---
>  drivers/gpu/drm/bridge/simple-bridge.c | 22 ++++++++++++++++++----
>  1 file changed, 18 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/simple-bridge.c b/drivers/gpu/drm/bridge/simple-bridge.c
> index 85aa852eafb4..3e5031833368 100644
> --- a/drivers/gpu/drm/bridge/simple-bridge.c
> +++ b/drivers/gpu/drm/bridge/simple-bridge.c
> @@ -6,6 +6,7 @@
>   * Maxime Ripard <maxime.ripard@free-electrons.com>
>   */
>  
> +#include <linux/gpio/consumer.h>
>  #include <linux/module.h>
>  #include <linux/of_device.h>
>  #include <linux/of_graph.h>
> @@ -29,6 +30,7 @@ struct simple_bridge {
>  
>  	struct i2c_adapter	*ddc;
>  	struct regulator	*vdd;
> +	struct gpio_desc	*enable;
>  };
>  
>  static inline struct simple_bridge *
> @@ -140,19 +142,23 @@ static int simple_bridge_attach(struct drm_bridge *bridge,
>  static void simple_bridge_enable(struct drm_bridge *bridge)
>  {
>  	struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
> -	int ret = 0;
> +	int ret;
>  
> -	if (sbridge->vdd)
> +	if (sbridge->vdd) {
>  		ret = regulator_enable(sbridge->vdd);
> +		if (ret)
> +			DRM_ERROR("Failed to enable vdd regulator: %d\n", ret);
> +	}
>  
> -	if (ret)
> -		DRM_ERROR("Failed to enable vdd regulator: %d\n", ret);
> +	gpiod_set_value_cansleep(sbridge->enable, 1);
>  }
>  
>  static void simple_bridge_disable(struct drm_bridge *bridge)
>  {
>  	struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
>  
> +	gpiod_set_value_cansleep(sbridge->enable, 0);
> +
>  	if (sbridge->vdd)
>  		regulator_disable(sbridge->vdd);
>  }
> @@ -205,6 +211,14 @@ static int simple_bridge_probe(struct platform_device *pdev)
>  		dev_dbg(&pdev->dev, "No vdd regulator found: %d\n", ret);
>  	}
>  
> +	sbridge->enable = devm_gpiod_get_optional(&pdev->dev, "enable",
> +						  GPIOD_OUT_LOW);
> +	if (IS_ERR(sbridge->enable)) {
> +		if (PTR_ERR(sbridge->enable) != -EPROBE_DEFER)
> +			dev_err(&pdev->dev, "Unable to retrieve enable GPIO\n");
> +		return PTR_ERR(sbridge->enable);
> +	}
> +
>  	sbridge->ddc = simple_bridge_retrieve_ddc(&pdev->dev);
>  	if (IS_ERR(sbridge->ddc)) {
>  		if (PTR_ERR(sbridge->ddc) == -ENODEV) {

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

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

* Re: [PATCH v2 10/50] drm/bridge: simple-bridge: Add support for the TI OP362
  2019-08-20  1:16 ` [PATCH v2 10/50] drm/bridge: simple-bridge: Add support for the TI OP362 Laurent Pinchart
@ 2019-08-22 15:45   ` Boris Brezillon
  2019-08-26 11:34   ` Maxime Ripard
  1 sibling, 0 replies; 106+ messages in thread
From: Boris Brezillon @ 2019-08-22 15:45 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

On Tue, 20 Aug 2019 04:16:41 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

> The TI OP362 is an analog video amplifier controlled through a GPIO. Add
> support for it to the simple-bridge driver.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>

> ---
>  drivers/gpu/drm/bridge/simple-bridge.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/gpu/drm/bridge/simple-bridge.c b/drivers/gpu/drm/bridge/simple-bridge.c
> index 3e5031833368..52626e2de90e 100644
> --- a/drivers/gpu/drm/bridge/simple-bridge.c
> +++ b/drivers/gpu/drm/bridge/simple-bridge.c
> @@ -302,6 +302,11 @@ static const struct of_device_id simple_bridge_match[] = {
>  			.timings = &default_bridge_timings,
>  			.connector_type = DRM_MODE_CONNECTOR_VGA,
>  		},
> +	}, {
> +		.compatible = "ti,opa362",
> +		.data = &(const struct simple_bridge_info) {
> +			.connector_type = DRM_MODE_CONNECTOR_Composite,
> +		},
>  	}, {
>  		.compatible = "ti,ths8135",
>  		.data = &(const struct simple_bridge_info) {

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

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

* Re: [PATCH v2 11/50] drm/bridge: Add bridge driver for display connectors
  2019-08-20  1:16 ` [PATCH v2 11/50] drm/bridge: Add bridge driver for display connectors Laurent Pinchart
@ 2019-08-22 16:05   ` Boris Brezillon
  2019-08-22 16:39     ` Laurent Pinchart
  2019-08-26 11:36   ` Maxime Ripard
  1 sibling, 1 reply; 106+ messages in thread
From: Boris Brezillon @ 2019-08-22 16:05 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

On Tue, 20 Aug 2019 04:16:42 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

> +	/*
> +	 * Get the HPD GPIO for DVI and HDMI connectors. If the GPIO can provide
> +	 * interrupts, register an interrupt handler.
> +	 */
> +	if (type == DRM_MODE_CONNECTOR_DVII ||
> +	    type == DRM_MODE_CONNECTOR_HDMIA) {
> +		conn->hpd_gpio = devm_gpiod_get_optional(&pdev->dev, "hpd",
> +							 GPIOD_IN);
> +		if (IS_ERR(conn->hpd_gpio)) {
> +			if (PTR_ERR(conn->hpd_gpio) != -EPROBE_DEFER)
> +				dev_err(&pdev->dev,
> +					"Unable to retrieve HPD GPIO\n");
> +			return PTR_ERR(conn->hpd_gpio);
> +		}
> +
> +		conn->hpd_irq = gpiod_to_irq(conn->hpd_gpio);
> +	} else {
> +		conn->hpd_irq = -EINVAL;
> +	}
> +
> +	if (conn->hpd_irq >= 0) {
> +		ret = devm_request_threaded_irq(&pdev->dev, conn->hpd_irq,
> +						NULL, display_connector_hpd_irq,
> +						IRQF_TRIGGER_RISING |
> +						IRQF_TRIGGER_FALLING |
> +						IRQF_ONESHOT,
> +						"HPD", conn);
> +		if (ret) {
> +			dev_err(&pdev->dev,
> +				"Failed to request HPD interrupt\n");
> +			return ret;

Is there anything that mandates support of edge events on GPIO chips?
I know it's quite common, but maybe we should fallback to polling
mode when devm_request_threaded_irq() fails.

> +		}
> +	}
> +
> +	/* Retrieve the DDC I2C adapter for DVI, HDMI and VGA connectors. */
> +	if (type == DRM_MODE_CONNECTOR_DVII ||
> +	    type == DRM_MODE_CONNECTOR_HDMIA ||
> +	    type == DRM_MODE_CONNECTOR_VGA) {
> +		struct device_node *phandle;
> +
> +		phandle = of_parse_phandle(pdev->dev.of_node, "ddc-i2c-bus", 0);
> +		if (phandle) {
> +			conn->bridge.ddc = of_get_i2c_adapter_by_node(phandle);
> +			of_node_put(phandle);
> +			if (!conn->bridge.ddc)
> +				return -EPROBE_DEFER;
> +		} else {
> +			dev_dbg(&pdev->dev,
> +				"No I2C bus specified, disabling EDID readout\n");
> +		}
> +	}
> +
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 14/50] drm/bridge: tfp410: Don't include drmP.h
  2019-08-20  1:16 ` [PATCH v2 14/50] drm/bridge: tfp410: Don't include drmP.h Laurent Pinchart
@ 2019-08-22 16:11   ` Boris Brezillon
  0 siblings, 0 replies; 106+ messages in thread
From: Boris Brezillon @ 2019-08-22 16:11 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

On Tue, 20 Aug 2019 04:16:45 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

> The drmP.h header is deprecated, replace it with the headers
> specifically needed by the tfp410 driver. While at it, replace the DRM
> print macros with dev_info() and dev_err() instead of including
> drm_print.h

Looks like drm_print.h is still included.

> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/gpu/drm/bridge/ti-tfp410.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
> index a9359038f7dc..4a468f44ef69 100644
> --- a/drivers/gpu/drm/bridge/ti-tfp410.c
> +++ b/drivers/gpu/drm/bridge/ti-tfp410.c
> @@ -14,6 +14,7 @@
>  #include <linux/platform_device.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_print.h>
>  #include <drm/drm_probe_helper.h>
> @@ -60,7 +61,8 @@ static int tfp410_get_modes(struct drm_connector *connector)
>  
>  	edid = drm_get_edid(connector, dvi->ddc);
>  	if (!edid) {
> -		DRM_INFO("EDID read failed. Fallback to standard modes\n");
> +		dev_info(dvi->dev,
> +			 "EDID read failed. Fallback to standard modes\n");
>  		goto fallback;
>  	}
>  
> @@ -364,7 +366,7 @@ static int tfp410_init(struct device *dev, bool i2c)
>  			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
>  			"hdmi-hpd", dvi);
>  		if (ret) {
> -			DRM_ERROR("failed to register hpd interrupt\n");
> +			dev_err(dev, "failed to register hpd interrupt\n");
>  			goto fail;
>  		}
>  	}

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

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

* Re: [PATCH v2 13/50] drm/bridge: panel: Implement bridge connector operations
  2019-08-20  1:16 ` [PATCH v2 13/50] drm/bridge: panel: Implement bridge connector operations Laurent Pinchart
  2019-08-20 10:37   ` Sam Ravnborg
@ 2019-08-22 16:29   ` Boris Brezillon
  2019-08-22 16:35     ` Laurent Pinchart
  1 sibling, 1 reply; 106+ messages in thread
From: Boris Brezillon @ 2019-08-22 16:29 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

On Tue, 20 Aug 2019 04:16:44 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

> Implement the newly added bridge connector operations, allowing the
> usage of drm_bridge_panel with drm_bridge_connector.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/gpu/drm/bridge/panel.c | 18 +++++++++++++++++-
>  1 file changed, 17 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
> index f5b8e55301ac..1c7f5b648f05 100644
> --- a/drivers/gpu/drm/bridge/panel.c
> +++ b/drivers/gpu/drm/bridge/panel.c
> @@ -60,7 +60,7 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
>  	int ret;
>  
>  	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> -		return -EINVAL;
> +		return 0;
>  
>  	if (!bridge->encoder) {
>  		DRM_ERROR("Missing encoder\n");
> @@ -123,6 +123,18 @@ static void panel_bridge_post_disable(struct drm_bridge *bridge)
>  	drm_panel_unprepare(panel_bridge->panel);
>  }
>  
> +static int panel_bridge_get_modes(struct drm_bridge *bridge,
> +				  struct drm_connector *connector)
> +{
> +	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
> +
> +	/*
> +	 * FIXME: drm_panel_get_modes() should take the connector as an
> +	 * argument.
> +	 */
> +	return drm_panel_get_modes(panel_bridge->panel);
> +}
> +
>  static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
>  	.attach = panel_bridge_attach,
>  	.detach = panel_bridge_detach,
> @@ -130,6 +142,7 @@ static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
>  	.enable = panel_bridge_enable,
>  	.disable = panel_bridge_disable,
>  	.post_disable = panel_bridge_post_disable,
> +	.get_modes = panel_bridge_get_modes,
>  };
>  
>  /**
> @@ -175,6 +188,9 @@ struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
>  #ifdef CONFIG_OF
>  	panel_bridge->bridge.of_node = panel->dev->of_node;
>  #endif
> +	panel_bridge->bridge.ops = DRM_BRIDGE_OP_MODES;
> +	/* FIXME: The panel should report its type. */
> +	panel_bridge->bridge.type = DRM_MODE_CONNECTOR_DPI;

Shouldn't we patch all panel drivers to expose this type before doing
this change? I mean, the connector type is exposed to userspace, and I
wouldn't be surprised if some userspace apps/libs decided to base their
output selection logic on this field.

>  
>  	drm_bridge_add(&panel_bridge->bridge);
>  

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

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

* Re: [PATCH v2 13/50] drm/bridge: panel: Implement bridge connector operations
  2019-08-22 16:29   ` Boris Brezillon
@ 2019-08-22 16:35     ` Laurent Pinchart
  2019-08-22 18:02       ` Boris Brezillon
  0 siblings, 1 reply; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-22 16:35 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

Hi Boris,

On Thu, Aug 22, 2019 at 06:29:09PM +0200, Boris Brezillon wrote:
> On Tue, 20 Aug 2019 04:16:44 +0300 Laurent Pinchart wrote:
> 
> > Implement the newly added bridge connector operations, allowing the
> > usage of drm_bridge_panel with drm_bridge_connector.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/gpu/drm/bridge/panel.c | 18 +++++++++++++++++-
> >  1 file changed, 17 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
> > index f5b8e55301ac..1c7f5b648f05 100644
> > --- a/drivers/gpu/drm/bridge/panel.c
> > +++ b/drivers/gpu/drm/bridge/panel.c
> > @@ -60,7 +60,7 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
> >  	int ret;
> >  
> >  	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> > -		return -EINVAL;
> > +		return 0;
> >  
> >  	if (!bridge->encoder) {
> >  		DRM_ERROR("Missing encoder\n");
> > @@ -123,6 +123,18 @@ static void panel_bridge_post_disable(struct drm_bridge *bridge)
> >  	drm_panel_unprepare(panel_bridge->panel);
> >  }
> >  
> > +static int panel_bridge_get_modes(struct drm_bridge *bridge,
> > +				  struct drm_connector *connector)
> > +{
> > +	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
> > +
> > +	/*
> > +	 * FIXME: drm_panel_get_modes() should take the connector as an
> > +	 * argument.
> > +	 */
> > +	return drm_panel_get_modes(panel_bridge->panel);
> > +}
> > +
> >  static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
> >  	.attach = panel_bridge_attach,
> >  	.detach = panel_bridge_detach,
> > @@ -130,6 +142,7 @@ static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
> >  	.enable = panel_bridge_enable,
> >  	.disable = panel_bridge_disable,
> >  	.post_disable = panel_bridge_post_disable,
> > +	.get_modes = panel_bridge_get_modes,
> >  };
> >  
> >  /**
> > @@ -175,6 +188,9 @@ struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
> >  #ifdef CONFIG_OF
> >  	panel_bridge->bridge.of_node = panel->dev->of_node;
> >  #endif
> > +	panel_bridge->bridge.ops = DRM_BRIDGE_OP_MODES;
> > +	/* FIXME: The panel should report its type. */
> > +	panel_bridge->bridge.type = DRM_MODE_CONNECTOR_DPI;
> 
> Shouldn't we patch all panel drivers to expose this type before doing
> this change? I mean, the connector type is exposed to userspace, and I
> wouldn't be surprised if some userspace apps/libs decided to base their
> output selection logic on this field.

Note that this type will only make it to userspace for drivers that use
the bridge->type field, likely through the drm bridge connector helper.
I do agree that panel drivers should be updated, but given the number of
panels in panel-simple and the fact that the information would need to
be researched for most of them, this will be significant work. Can't
this be done when converting display controller drivers on a need basis
?

Or maybe we could, as an interim measure, derive the type from the bus
formats reported by the panel if the panel type is not set ? If the
panel reports MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,
MEDIA_BUS_FMT_RGB666_1X7X4_SPWG or MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA then
we can set the type to LVDS, otherwise we set it to DPI. I can submit a
patch to add a type field to the panel structure and implement this
logic.

> >  	drm_bridge_add(&panel_bridge->bridge);

-- 
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] 106+ messages in thread

* Re: [PATCH v2 15/50] drm/bridge: tfp410: Replace manual connector handling with bridge
  2019-08-20  1:16 ` [PATCH v2 15/50] drm/bridge: tfp410: Replace manual connector handling with bridge Laurent Pinchart
@ 2019-08-22 16:36   ` Boris Brezillon
  2019-08-22 16:54     ` Laurent Pinchart
  2019-08-27  7:43   ` Tomi Valkeinen
  1 sibling, 1 reply; 106+ messages in thread
From: Boris Brezillon @ 2019-08-22 16:36 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

On Tue, 20 Aug 2019 04:16:46 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

> Now that a driver is available for display connectors, replace the
> manual connector handling code with usage of the DRM bridge API. The
> tfp410 driver doesn't deal with the display connector directly anymore,
> but still delegates drm_connector operations to the next bridge. This
> brings us one step closer to having the tfp410 driver handling the
> TFP410 only.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/gpu/drm/bridge/ti-tfp410.c | 195 ++++++++++-------------------
>  1 file changed, 68 insertions(+), 127 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
> index 4a468f44ef69..65651ae6c553 100644
> --- a/drivers/gpu/drm/bridge/ti-tfp410.c
> +++ b/drivers/gpu/drm/bridge/ti-tfp410.c
> @@ -4,14 +4,12 @@
>   * Author: Jyri Sarha <jsarha@ti.com>
>   */
>  
> -#include <linux/delay.h>
> -#include <linux/fwnode.h>
>  #include <linux/gpio/consumer.h>
>  #include <linux/i2c.h>
> -#include <linux/irq.h>
>  #include <linux/module.h>
>  #include <linux/of_graph.h>
>  #include <linux/platform_device.h>
> +#include <linux/workqueue.h>
>  
>  #include <drm/drm_atomic_helper.h>
>  #include <drm/drm_bridge.h>
> @@ -24,16 +22,13 @@
>  struct tfp410 {
>  	struct drm_bridge	bridge;
>  	struct drm_connector	connector;
> -	unsigned int		connector_type;
>  
>  	u32			bus_format;
> -	struct i2c_adapter	*ddc;
> -	struct gpio_desc	*hpd;
> -	int			hpd_irq;
>  	struct delayed_work	hpd_work;
>  	struct gpio_desc	*powerdown;
>  
>  	struct drm_bridge_timings timings;
> +	struct drm_bridge	*next_bridge;
>  
>  	struct device *dev;
>  };
> @@ -56,10 +51,10 @@ static int tfp410_get_modes(struct drm_connector *connector)
>  	struct edid *edid;
>  	int ret;
>  
> -	if (!dvi->ddc)
> +	if (!(dvi->next_bridge->ops & DRM_BRIDGE_OP_EDID))
>  		goto fallback;
>  
> -	edid = drm_get_edid(connector, dvi->ddc);
> +	edid = dvi->next_bridge->funcs->get_edid(dvi->next_bridge, connector);

Can we create a drm_bridge_get_edid() wrapper for that?
Something like:

int drm_bridge_get_edid(struct drm_bridge *bridge,
			struct drm_connector *conn)
{
	if (!(dvi->next_bridge->ops & DRM_BRIDGE_OP_EDID))
		return -ENOTSUPP;

	return bridge->funcs->get_edid(bridge, connector);
}

>  	if (!edid) {
>  		dev_info(dvi->dev,
>  			 "EDID read failed. Fallback to standard modes\n");
> @@ -93,21 +88,10 @@ tfp410_connector_detect(struct drm_connector *connector, bool force)
>  {
>  	struct tfp410 *dvi = drm_connector_to_tfp410(connector);
>  
> -	if (dvi->hpd) {
> -		if (gpiod_get_value_cansleep(dvi->hpd))
> -			return connector_status_connected;
> -		else
> -			return connector_status_disconnected;
> -	}
> +	if (!(dvi->next_bridge->ops & DRM_BRIDGE_OP_DETECT))
> +		return connector_status_unknown;
>  
> -	if (dvi->ddc) {
> -		if (drm_probe_ddc(dvi->ddc))
> -			return connector_status_connected;
> -		else
> -			return connector_status_disconnected;
> -	}
> -
> -	return connector_status_unknown;
> +	return dvi->next_bridge->funcs->detect(dvi->next_bridge);

Same here for the detect hook.

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

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

* Re: [PATCH v2 11/50] drm/bridge: Add bridge driver for display connectors
  2019-08-22 16:05   ` Boris Brezillon
@ 2019-08-22 16:39     ` Laurent Pinchart
  0 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-22 16:39 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

Hi Boris,

On Thu, Aug 22, 2019 at 06:05:20PM +0200, Boris Brezillon wrote:
> On Tue, 20 Aug 2019 04:16:42 +0300 Laurent Pinchart wrote:
> 
> > +	/*
> > +	 * Get the HPD GPIO for DVI and HDMI connectors. If the GPIO can provide
> > +	 * interrupts, register an interrupt handler.
> > +	 */
> > +	if (type == DRM_MODE_CONNECTOR_DVII ||
> > +	    type == DRM_MODE_CONNECTOR_HDMIA) {
> > +		conn->hpd_gpio = devm_gpiod_get_optional(&pdev->dev, "hpd",
> > +							 GPIOD_IN);
> > +		if (IS_ERR(conn->hpd_gpio)) {
> > +			if (PTR_ERR(conn->hpd_gpio) != -EPROBE_DEFER)
> > +				dev_err(&pdev->dev,
> > +					"Unable to retrieve HPD GPIO\n");
> > +			return PTR_ERR(conn->hpd_gpio);
> > +		}
> > +
> > +		conn->hpd_irq = gpiod_to_irq(conn->hpd_gpio);
> > +	} else {
> > +		conn->hpd_irq = -EINVAL;
> > +	}
> > +
> > +	if (conn->hpd_irq >= 0) {
> > +		ret = devm_request_threaded_irq(&pdev->dev, conn->hpd_irq,
> > +						NULL, display_connector_hpd_irq,
> > +						IRQF_TRIGGER_RISING |
> > +						IRQF_TRIGGER_FALLING |
> > +						IRQF_ONESHOT,
> > +						"HPD", conn);
> > +		if (ret) {
> > +			dev_err(&pdev->dev,
> > +				"Failed to request HPD interrupt\n");
> > +			return ret;
> 
> Is there anything that mandates support of edge events on GPIO chips?
> I know it's quite common, but maybe we should fallback to polling
> mode when devm_request_threaded_irq() fails.

That's a good point, I'll change this.

> > +		}
> > +	}
> > +
> > +	/* Retrieve the DDC I2C adapter for DVI, HDMI and VGA connectors. */
> > +	if (type == DRM_MODE_CONNECTOR_DVII ||
> > +	    type == DRM_MODE_CONNECTOR_HDMIA ||
> > +	    type == DRM_MODE_CONNECTOR_VGA) {
> > +		struct device_node *phandle;
> > +
> > +		phandle = of_parse_phandle(pdev->dev.of_node, "ddc-i2c-bus", 0);
> > +		if (phandle) {
> > +			conn->bridge.ddc = of_get_i2c_adapter_by_node(phandle);
> > +			of_node_put(phandle);
> > +			if (!conn->bridge.ddc)
> > +				return -EPROBE_DEFER;
> > +		} else {
> > +			dev_dbg(&pdev->dev,
> > +				"No I2C bus specified, disabling EDID readout\n");
> > +		}
> > +	}
> > +

-- 
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] 106+ messages in thread

* Re: [PATCH v2 04/50] drm/bridge: Add connector-related bridge operations and data
  2019-08-20  1:16 ` [PATCH v2 04/50] drm/bridge: Add connector-related bridge operations and data Laurent Pinchart
  2019-08-22 15:24   ` Boris Brezillon
@ 2019-08-22 16:41   ` Boris Brezillon
  2019-08-23  0:34     ` Laurent Pinchart
  1 sibling, 1 reply; 106+ messages in thread
From: Boris Brezillon @ 2019-08-22 16:41 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

On Tue, 20 Aug 2019 04:16:35 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

>  
> +/**
> + * enum drm_bridge_ops - Bitmask of operations supported by the bridge
> + */
> +enum drm_bridge_ops {
> +	/**
> +	 * @DRM_BRIDGE_OP_DETECT: The bridge can detect displays connected to
> +	 * its output. Bridges that set this flag shall implement the
> +	 * &drm_bridge_funcs->detect callback.
> +	 */
> +	DRM_BRIDGE_OP_DETECT = BIT(0),
> +	/**
> +	 * @DRM_BRIDGE_OP_EDID: The bridge can retrieve the EDID of the display
> +	 * connected to its output. Bridges that set this flag shall implement
> +	 * the &drm_bridge_funcs->get_edid callback.
> +	 */
> +	DRM_BRIDGE_OP_EDID = BIT(1),
> +	/**
> +	 * @DRM_BRIDGE_OP_HPD: The bridge can detect hot-plug and hot-unplug
> +	 * without requiring polling. Bridges that set this flag shall
> +	 * implement the &drm_bridge_funcs->hpd_enable and
> +	 * &drm_bridge_funcs->hpd_disable callbacks if they support enabling
> +	 * and disabling hot-plug detection dynamically.
> +	 */
> +	DRM_BRIDGE_OP_HPD = BIT(2),
> +	/**
> +	 * @DRM_BRIDGE_OP_MODES: The bridge can retrieving the modes supported
> +	 * by the display at its output. This does not include readind EDID
> +	 * which is separately covered by @DRM_BRIDGE_OP_EDID. Bridges that set
> +	 * this flag shall implement the &drm_bridge_funcs->get_modes callback.
> +	 */
> +	DRM_BRIDGE_OP_MODES = BIT(3),
> +};
> +
>  /**
>   * struct drm_bridge - central DRM bridge control structure
>   */
> @@ -398,6 +538,33 @@ struct drm_bridge {
>  	const struct drm_bridge_funcs *funcs;
>  	/** @driver_private: pointer to the bridge driver's internal context */
>  	void *driver_private;
> +	/** @ops: bitmask of operations supported by the bridge */
> +	enum drm_bridge_ops ops;

Just realized that you're not checking ->ops and ->funcs consistency at
attach() time (you're only checking ->ops in the tfp410 driver before
calling ->funcs->detect() and ->funcs->get_modes() and they might be
NULL).

> +	/**
> +	 * @type: Type of the connection at the bridge output
> +	 * (DRM_MODE_CONNECTOR_*). For bridges at the end of this chain this
> +	 * identifies the type of connected display.
> +	 */
> +	int type;
> +	/**
> +	 * @ddc: Associated I2C adapter for DDC access, if any.
> +	 */
> +	struct i2c_adapter *ddc;
> +	/** private: */
> +	/**
> +	 * @hpd_mutex: Protects the @hpd_cb and @hpd_data fields.
> +	 */
> +	struct mutex hpd_mutex;
> +	/**
> +	 * @hpd_cb: Hot plug detection callback, registered with
> +	 * drm_bridge_hpd_enable().
> +	 */
> +	void (*hpd_cb)(void *data, enum drm_connector_status status);
> +	/**
> +	 * @hpd_data: Private data passed to the Hot plug detection callback
> +	 * @hpd_cb.
> +	 */
> +	void *hpd_data;
>  };
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 15/50] drm/bridge: tfp410: Replace manual connector handling with bridge
  2019-08-22 16:36   ` Boris Brezillon
@ 2019-08-22 16:54     ` Laurent Pinchart
  2019-08-22 17:15       ` Boris Brezillon
  0 siblings, 1 reply; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-22 16:54 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

Hi Boris,

On Thu, Aug 22, 2019 at 06:36:45PM +0200, Boris Brezillon wrote:
> On Tue, 20 Aug 2019 04:16:46 +0300 Laurent Pinchart wrote:
> 
> > Now that a driver is available for display connectors, replace the
> > manual connector handling code with usage of the DRM bridge API. The
> > tfp410 driver doesn't deal with the display connector directly anymore,
> > but still delegates drm_connector operations to the next bridge. This
> > brings us one step closer to having the tfp410 driver handling the
> > TFP410 only.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/gpu/drm/bridge/ti-tfp410.c | 195 ++++++++++-------------------
> >  1 file changed, 68 insertions(+), 127 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
> > index 4a468f44ef69..65651ae6c553 100644
> > --- a/drivers/gpu/drm/bridge/ti-tfp410.c
> > +++ b/drivers/gpu/drm/bridge/ti-tfp410.c
> > @@ -4,14 +4,12 @@
> >   * Author: Jyri Sarha <jsarha@ti.com>
> >   */
> >  
> > -#include <linux/delay.h>
> > -#include <linux/fwnode.h>
> >  #include <linux/gpio/consumer.h>
> >  #include <linux/i2c.h>
> > -#include <linux/irq.h>
> >  #include <linux/module.h>
> >  #include <linux/of_graph.h>
> >  #include <linux/platform_device.h>
> > +#include <linux/workqueue.h>
> >  
> >  #include <drm/drm_atomic_helper.h>
> >  #include <drm/drm_bridge.h>
> > @@ -24,16 +22,13 @@
> >  struct tfp410 {
> >  	struct drm_bridge	bridge;
> >  	struct drm_connector	connector;
> > -	unsigned int		connector_type;
> >  
> >  	u32			bus_format;
> > -	struct i2c_adapter	*ddc;
> > -	struct gpio_desc	*hpd;
> > -	int			hpd_irq;
> >  	struct delayed_work	hpd_work;
> >  	struct gpio_desc	*powerdown;
> >  
> >  	struct drm_bridge_timings timings;
> > +	struct drm_bridge	*next_bridge;
> >  
> >  	struct device *dev;
> >  };
> > @@ -56,10 +51,10 @@ static int tfp410_get_modes(struct drm_connector *connector)
> >  	struct edid *edid;
> >  	int ret;
> >  
> > -	if (!dvi->ddc)
> > +	if (!(dvi->next_bridge->ops & DRM_BRIDGE_OP_EDID))
> >  		goto fallback;
> >  
> > -	edid = drm_get_edid(connector, dvi->ddc);
> > +	edid = dvi->next_bridge->funcs->get_edid(dvi->next_bridge, connector);
> 
> Can we create a drm_bridge_get_edid() wrapper for that?
> Something like:
> 
> int drm_bridge_get_edid(struct drm_bridge *bridge,
> 			struct drm_connector *conn)
> {
> 	if (!(dvi->next_bridge->ops & DRM_BRIDGE_OP_EDID))
> 		return -ENOTSUPP;

I assume you mean ERR_PTR(-ENOTSUPP) with the return type changed to
struct drm_edid *.

> 
> 	return bridge->funcs->get_edid(bridge, connector);
> }

I've thought about it, but I'm not sure it's worth it. These operations
are not meant to be called manually by bridges like in here. This is an
interim solution until support for drm_connector can be dropped from the
tfp410 driver, once its users will be converted. Do you think I should
still create a wrapper (which I would make static inline then) ?

> >  	if (!edid) {
> >  		dev_info(dvi->dev,
> >  			 "EDID read failed. Fallback to standard modes\n");
> > @@ -93,21 +88,10 @@ tfp410_connector_detect(struct drm_connector *connector, bool force)
> >  {
> >  	struct tfp410 *dvi = drm_connector_to_tfp410(connector);
> >  
> > -	if (dvi->hpd) {
> > -		if (gpiod_get_value_cansleep(dvi->hpd))
> > -			return connector_status_connected;
> > -		else
> > -			return connector_status_disconnected;
> > -	}
> > +	if (!(dvi->next_bridge->ops & DRM_BRIDGE_OP_DETECT))
> > +		return connector_status_unknown;
> >  
> > -	if (dvi->ddc) {
> > -		if (drm_probe_ddc(dvi->ddc))
> > -			return connector_status_connected;
> > -		else
> > -			return connector_status_disconnected;
> > -	}
> > -
> > -	return connector_status_unknown;
> > +	return dvi->next_bridge->funcs->detect(dvi->next_bridge);
> 
> Same here for the detect hook.
> 

-- 
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] 106+ messages in thread

* Re: [PATCH v2 34/50] drm/omap: Create connector for bridges
  2019-08-20  1:17 ` [PATCH v2 34/50] drm/omap: Create connector for bridges Laurent Pinchart
@ 2019-08-22 17:00   ` Boris Brezillon
  2019-08-22 23:41     ` Laurent Pinchart
  0 siblings, 1 reply; 106+ messages in thread
From: Boris Brezillon @ 2019-08-22 17:00 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

On Tue, 20 Aug 2019 04:17:05 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

> Use the drm_bridge_connector helper to create a connector for pipelines
> that use drm_bridge. This allows splitting connector operations across
> multiple bridges when necessary, instead of having the last bridge in
> the chain creating the connector and handling all connector operations
> internally.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> Changes since v1:
> 
> - Squash with patch "drm/omap: Detach from panels at remove time"
> ---
>  drivers/gpu/drm/omapdrm/omap_drv.c | 82 +++++++++++++++++++++++++-----
>  1 file changed, 70 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
> index de373fd50729..f38d95cb31ba 100644
> --- a/drivers/gpu/drm/omapdrm/omap_drv.c
> +++ b/drivers/gpu/drm/omapdrm/omap_drv.c
> @@ -11,10 +11,12 @@
>  
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge_connector.h>
>  #include <drm/drm_drv.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/drm_file.h>
>  #include <drm/drm_ioctl.h>
> +#include <drm/drm_panel.h>
>  #include <drm/drm_prime.h>
>  #include <drm/drm_probe_helper.h>
>  #include <drm/drm_vblank.h>
> @@ -290,9 +292,14 @@ static int omap_modeset_init(struct drm_device *dev)
>  
>  		if (pipe->output->bridge) {
>  			ret = drm_bridge_attach(pipe->encoder,
> -						pipe->output->bridge, NULL, 0);
> -			if (ret < 0)
> +						pipe->output->bridge, NULL,
> +						DRM_BRIDGE_ATTACH_NO_CONNECTOR);

I guess the only external bridge connected to an omap display
controller in upstream DTs is the TFP410. I was wondering if falling
back to !DRM_BRIDGE_ATTACH_NO_CONNECTOR would be acceptable in case one
wants to convert a display controller driver which is known to be
used in conjunction with various external bridges.

> +			if (ret < 0) {
> +				dev_err(priv->dev,
> +					"unable to attach bridge %pOF\n",
> +					pipe->output->bridge->of_node);
>  				return ret;
> +			}
>  		}
>  
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 15/50] drm/bridge: tfp410: Replace manual connector handling with bridge
  2019-08-22 16:54     ` Laurent Pinchart
@ 2019-08-22 17:15       ` Boris Brezillon
  0 siblings, 0 replies; 106+ messages in thread
From: Boris Brezillon @ 2019-08-22 17:15 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

On Thu, 22 Aug 2019 19:54:56 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

> Hi Boris,
> 
> On Thu, Aug 22, 2019 at 06:36:45PM +0200, Boris Brezillon wrote:
> > On Tue, 20 Aug 2019 04:16:46 +0300 Laurent Pinchart wrote:
> >   
> > > Now that a driver is available for display connectors, replace the
> > > manual connector handling code with usage of the DRM bridge API. The
> > > tfp410 driver doesn't deal with the display connector directly anymore,
> > > but still delegates drm_connector operations to the next bridge. This
> > > brings us one step closer to having the tfp410 driver handling the
> > > TFP410 only.
> > > 
> > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > ---
> > >  drivers/gpu/drm/bridge/ti-tfp410.c | 195 ++++++++++-------------------
> > >  1 file changed, 68 insertions(+), 127 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
> > > index 4a468f44ef69..65651ae6c553 100644
> > > --- a/drivers/gpu/drm/bridge/ti-tfp410.c
> > > +++ b/drivers/gpu/drm/bridge/ti-tfp410.c
> > > @@ -4,14 +4,12 @@
> > >   * Author: Jyri Sarha <jsarha@ti.com>
> > >   */
> > >  
> > > -#include <linux/delay.h>
> > > -#include <linux/fwnode.h>
> > >  #include <linux/gpio/consumer.h>
> > >  #include <linux/i2c.h>
> > > -#include <linux/irq.h>
> > >  #include <linux/module.h>
> > >  #include <linux/of_graph.h>
> > >  #include <linux/platform_device.h>
> > > +#include <linux/workqueue.h>
> > >  
> > >  #include <drm/drm_atomic_helper.h>
> > >  #include <drm/drm_bridge.h>
> > > @@ -24,16 +22,13 @@
> > >  struct tfp410 {
> > >  	struct drm_bridge	bridge;
> > >  	struct drm_connector	connector;
> > > -	unsigned int		connector_type;
> > >  
> > >  	u32			bus_format;
> > > -	struct i2c_adapter	*ddc;
> > > -	struct gpio_desc	*hpd;
> > > -	int			hpd_irq;
> > >  	struct delayed_work	hpd_work;
> > >  	struct gpio_desc	*powerdown;
> > >  
> > >  	struct drm_bridge_timings timings;
> > > +	struct drm_bridge	*next_bridge;
> > >  
> > >  	struct device *dev;
> > >  };
> > > @@ -56,10 +51,10 @@ static int tfp410_get_modes(struct drm_connector *connector)
> > >  	struct edid *edid;
> > >  	int ret;
> > >  
> > > -	if (!dvi->ddc)
> > > +	if (!(dvi->next_bridge->ops & DRM_BRIDGE_OP_EDID))
> > >  		goto fallback;
> > >  
> > > -	edid = drm_get_edid(connector, dvi->ddc);
> > > +	edid = dvi->next_bridge->funcs->get_edid(dvi->next_bridge, connector);  
> > 
> > Can we create a drm_bridge_get_edid() wrapper for that?
> > Something like:
> > 
> > int drm_bridge_get_edid(struct drm_bridge *bridge,
> > 			struct drm_connector *conn)
> > {
> > 	if (!(dvi->next_bridge->ops & DRM_BRIDGE_OP_EDID))
> > 		return -ENOTSUPP;  
> 
> I assume you mean ERR_PTR(-ENOTSUPP) with the return type changed to
> struct drm_edid *.
> 
> > 
> > 	return bridge->funcs->get_edid(bridge, connector);
> > }  
> 
> I've thought about it, but I'm not sure it's worth it. These operations
> are not meant to be called manually by bridges like in here. This is an
> interim solution until support for drm_connector can be dropped from the
> tfp410 driver, once its users will be converted. Do you think I should
> still create a wrapper (which I would make static inline then) ?

Well, this conversion is likely to take time, not to mention that other
drivers will go through the same process. And every time a bridge
driver is converted, it requires patching all display controller drivers
that are known to be connected to it before you can get rid of this
temporary solution. So yes, I still think it's worth adding those
helpers, maybe with a comment explaining that they should only be used
during the conversion phase (IOW, until the driver starts rejecting
the !DRM_BRIDGE_ATTACH_NO_CONNECTOR case).

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

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

* Re: [PATCH v2 13/50] drm/bridge: panel: Implement bridge connector operations
  2019-08-22 16:35     ` Laurent Pinchart
@ 2019-08-22 18:02       ` Boris Brezillon
  2019-08-23  0:39         ` Laurent Pinchart
  0 siblings, 1 reply; 106+ messages in thread
From: Boris Brezillon @ 2019-08-22 18:02 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

On Thu, 22 Aug 2019 19:35:24 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

> Hi Boris,
> 
> On Thu, Aug 22, 2019 at 06:29:09PM +0200, Boris Brezillon wrote:
> > On Tue, 20 Aug 2019 04:16:44 +0300 Laurent Pinchart wrote:
> >   
> > > Implement the newly added bridge connector operations, allowing the
> > > usage of drm_bridge_panel with drm_bridge_connector.
> > > 
> > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > ---
> > >  drivers/gpu/drm/bridge/panel.c | 18 +++++++++++++++++-
> > >  1 file changed, 17 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
> > > index f5b8e55301ac..1c7f5b648f05 100644
> > > --- a/drivers/gpu/drm/bridge/panel.c
> > > +++ b/drivers/gpu/drm/bridge/panel.c
> > > @@ -60,7 +60,7 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
> > >  	int ret;
> > >  
> > >  	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> > > -		return -EINVAL;
> > > +		return 0;
> > >  
> > >  	if (!bridge->encoder) {
> > >  		DRM_ERROR("Missing encoder\n");
> > > @@ -123,6 +123,18 @@ static void panel_bridge_post_disable(struct drm_bridge *bridge)
> > >  	drm_panel_unprepare(panel_bridge->panel);
> > >  }
> > >  
> > > +static int panel_bridge_get_modes(struct drm_bridge *bridge,
> > > +				  struct drm_connector *connector)
> > > +{
> > > +	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
> > > +
> > > +	/*
> > > +	 * FIXME: drm_panel_get_modes() should take the connector as an
> > > +	 * argument.
> > > +	 */
> > > +	return drm_panel_get_modes(panel_bridge->panel);
> > > +}
> > > +
> > >  static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
> > >  	.attach = panel_bridge_attach,
> > >  	.detach = panel_bridge_detach,
> > > @@ -130,6 +142,7 @@ static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
> > >  	.enable = panel_bridge_enable,
> > >  	.disable = panel_bridge_disable,
> > >  	.post_disable = panel_bridge_post_disable,
> > > +	.get_modes = panel_bridge_get_modes,
> > >  };
> > >  
> > >  /**
> > > @@ -175,6 +188,9 @@ struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
> > >  #ifdef CONFIG_OF
> > >  	panel_bridge->bridge.of_node = panel->dev->of_node;
> > >  #endif
> > > +	panel_bridge->bridge.ops = DRM_BRIDGE_OP_MODES;
> > > +	/* FIXME: The panel should report its type. */
> > > +	panel_bridge->bridge.type = DRM_MODE_CONNECTOR_DPI;  
> > 
> > Shouldn't we patch all panel drivers to expose this type before doing
> > this change? I mean, the connector type is exposed to userspace, and I
> > wouldn't be surprised if some userspace apps/libs decided to base their
> > output selection logic on this field.  
> 
> Note that this type will only make it to userspace for drivers that use
> the bridge->type field, likely through the drm bridge connector helper.
> I do agree that panel drivers should be updated, but given the number of
> panels in panel-simple and the fact that the information would need to
> be researched for most of them, this will be significant work. Can't
> this be done when converting display controller drivers on a need basis
> ?

I think setting a default value and fixing things on a need basis is
okay, but that doesn't prevent you from adding the necessary
infrastructure to let panel drivers pass this type (we can fallback to a
default type in panel drivers instead of here). I'm also not sure why
'DPI' is chosen as the default, shouldn't we use 'Unknown' instead?

> 
> Or maybe we could, as an interim measure, derive the type from the bus
> formats reported by the panel if the panel type is not set ? If the
> panel reports MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,
> MEDIA_BUS_FMT_RGB666_1X7X4_SPWG or MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA then
> we can set the type to LVDS, otherwise we set it to DPI.

Hm, aren't we better off patching panel descs exposing these bus formats
to also explicitly set desc->type to LVDS, leaving others to Unknown
(Unknown is 0, so you don't have to patch all panel_desc definitions)?

> I can submit a
> patch to add a type field to the panel structure and implement this
> logic.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 16/50] drm/bridge: tfp410: Allow operation without drm_connector
  2019-08-20  1:16 ` [PATCH v2 16/50] drm/bridge: tfp410: Allow operation without drm_connector Laurent Pinchart
@ 2019-08-22 18:17   ` Boris Brezillon
  0 siblings, 0 replies; 106+ messages in thread
From: Boris Brezillon @ 2019-08-22 18:17 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

On Tue, 20 Aug 2019 04:16:47 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

> The tfp410 driver can operate as part of a pipeline where the
> drm_connector is created by the display controller. Enable this mode of
> operation by skipping creation of a drm_connector internally.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>

> ---
>  drivers/gpu/drm/bridge/ti-tfp410.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
> index 65651ae6c553..16cc8abe3262 100644
> --- a/drivers/gpu/drm/bridge/ti-tfp410.c
> +++ b/drivers/gpu/drm/bridge/ti-tfp410.c
> @@ -133,7 +133,7 @@ static int tfp410_attach(struct drm_bridge *bridge,
>  		return ret;
>  
>  	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> -		return -EINVAL;
> +		return 0;
>  
>  	if (!bridge->encoder) {
>  		dev_err(dvi->dev, "Missing encoder\n");

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

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

* Re: [PATCH v2 17/50] drm: Add helper to create a connector for a chain of bridges
  2019-08-20  1:16 ` [PATCH v2 17/50] drm: Add helper to create a connector for a chain of bridges Laurent Pinchart
@ 2019-08-22 18:31   ` Boris Brezillon
  0 siblings, 0 replies; 106+ messages in thread
From: Boris Brezillon @ 2019-08-22 18:31 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

On Tue, 20 Aug 2019 04:16:48 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:


> +	/**
> +	 * @bridge_detect:

	    ^ @bridge_modes

> +	 *
> +	 * The last bridge in the chain (closest to the connector) that provides
> +	 * connector modes detection, if any (see &DRM_BRIDGE_OP_MODES).
> +	 */
> +	struct drm_bridge *bridge_modes;
> +};
> +

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

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

* Re: [PATCH v2 34/50] drm/omap: Create connector for bridges
  2019-08-22 17:00   ` Boris Brezillon
@ 2019-08-22 23:41     ` Laurent Pinchart
  0 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-22 23:41 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

Hi Boris,

On Thu, Aug 22, 2019 at 07:00:11PM +0200, Boris Brezillon wrote:
> On Tue, 20 Aug 2019 04:17:05 +0300 Laurent Pinchart wrote:
> > Use the drm_bridge_connector helper to create a connector for pipelines
> > that use drm_bridge. This allows splitting connector operations across
> > multiple bridges when necessary, instead of having the last bridge in
> > the chain creating the connector and handling all connector operations
> > internally.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > Changes since v1:
> > 
> > - Squash with patch "drm/omap: Detach from panels at remove time"
> > ---
> >  drivers/gpu/drm/omapdrm/omap_drv.c | 82 +++++++++++++++++++++++++-----
> >  1 file changed, 70 insertions(+), 12 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
> > index de373fd50729..f38d95cb31ba 100644
> > --- a/drivers/gpu/drm/omapdrm/omap_drv.c
> > +++ b/drivers/gpu/drm/omapdrm/omap_drv.c
> > @@ -11,10 +11,12 @@
> >  
> >  #include <drm/drm_atomic.h>
> >  #include <drm/drm_atomic_helper.h>
> > +#include <drm/drm_bridge_connector.h>
> >  #include <drm/drm_drv.h>
> >  #include <drm/drm_fb_helper.h>
> >  #include <drm/drm_file.h>
> >  #include <drm/drm_ioctl.h>
> > +#include <drm/drm_panel.h>
> >  #include <drm/drm_prime.h>
> >  #include <drm/drm_probe_helper.h>
> >  #include <drm/drm_vblank.h>
> > @@ -290,9 +292,14 @@ static int omap_modeset_init(struct drm_device *dev)
> >  
> >  		if (pipe->output->bridge) {
> >  			ret = drm_bridge_attach(pipe->encoder,
> > -						pipe->output->bridge, NULL, 0);
> > -			if (ret < 0)
> > +						pipe->output->bridge, NULL,
> > +						DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> 
> I guess the only external bridge connected to an omap display
> controller in upstream DTs is the TFP410.

No, there's also the TI OP362 (analog amplier) and TI TPD12S015 (HDMI
ESD protection and level shifter). Those are not really encoders, but
they're bridges.

> I was wondering if falling back to !DRM_BRIDGE_ATTACH_NO_CONNECTOR
> would be acceptable in case one wants to convert a display controller
> driver which is known to be used in conjunction with various external
> bridges.

Yes, a display controller can support both options. I would however
recommend addressing bridges first in a conversion, and once all bridges
used by a display controller support DRM_BRIDGE_ATTACH_NO_CONNECTOR (and
implement the connector bridge ops), switch the display controller to
DRM_BRIDGE_ATTACH_NO_CONNECTOR unconditionally.

> > +			if (ret < 0) {
> > +				dev_err(priv->dev,
> > +					"unable to attach bridge %pOF\n",
> > +					pipe->output->bridge->of_node);
> >  				return ret;
> > +			}
> >  		}
> >  

-- 
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] 106+ messages in thread

* Re: [PATCH v2 04/50] drm/bridge: Add connector-related bridge operations and data
  2019-08-22 16:41   ` Boris Brezillon
@ 2019-08-23  0:34     ` Laurent Pinchart
  2019-08-23  6:15       ` Boris Brezillon
  0 siblings, 1 reply; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-23  0:34 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

Hi Boris,

On Thu, Aug 22, 2019 at 06:41:25PM +0200, Boris Brezillon wrote:
> On Tue, 20 Aug 2019 04:16:35 +0300 Laurent Pinchart wrote:
> 
> > +/**
> > + * enum drm_bridge_ops - Bitmask of operations supported by the bridge
> > + */
> > +enum drm_bridge_ops {
> > +	/**
> > +	 * @DRM_BRIDGE_OP_DETECT: The bridge can detect displays connected to
> > +	 * its output. Bridges that set this flag shall implement the
> > +	 * &drm_bridge_funcs->detect callback.
> > +	 */
> > +	DRM_BRIDGE_OP_DETECT = BIT(0),
> > +	/**
> > +	 * @DRM_BRIDGE_OP_EDID: The bridge can retrieve the EDID of the display
> > +	 * connected to its output. Bridges that set this flag shall implement
> > +	 * the &drm_bridge_funcs->get_edid callback.
> > +	 */
> > +	DRM_BRIDGE_OP_EDID = BIT(1),
> > +	/**
> > +	 * @DRM_BRIDGE_OP_HPD: The bridge can detect hot-plug and hot-unplug
> > +	 * without requiring polling. Bridges that set this flag shall
> > +	 * implement the &drm_bridge_funcs->hpd_enable and
> > +	 * &drm_bridge_funcs->hpd_disable callbacks if they support enabling
> > +	 * and disabling hot-plug detection dynamically.
> > +	 */
> > +	DRM_BRIDGE_OP_HPD = BIT(2),
> > +	/**
> > +	 * @DRM_BRIDGE_OP_MODES: The bridge can retrieving the modes supported
> > +	 * by the display at its output. This does not include readind EDID
> > +	 * which is separately covered by @DRM_BRIDGE_OP_EDID. Bridges that set
> > +	 * this flag shall implement the &drm_bridge_funcs->get_modes callback.
> > +	 */
> > +	DRM_BRIDGE_OP_MODES = BIT(3),
> > +};
> > +
> >  /**
> >   * struct drm_bridge - central DRM bridge control structure
> >   */
> > @@ -398,6 +538,33 @@ struct drm_bridge {
> >  	const struct drm_bridge_funcs *funcs;
> >  	/** @driver_private: pointer to the bridge driver's internal context */
> >  	void *driver_private;
> > +	/** @ops: bitmask of operations supported by the bridge */
> > +	enum drm_bridge_ops ops;
> 
> Just realized that you're not checking ->ops and ->funcs consistency at
> attach() time (you're only checking ->ops in the tfp410 driver before
> calling ->funcs->detect() and ->funcs->get_modes() and they might be
> NULL).

Do you think that's an issue ? I would then expect the driver to crash
right away during development and the issue to be fixed.

> > +	/**
> > +	 * @type: Type of the connection at the bridge output
> > +	 * (DRM_MODE_CONNECTOR_*). For bridges at the end of this chain this
> > +	 * identifies the type of connected display.
> > +	 */
> > +	int type;
> > +	/**
> > +	 * @ddc: Associated I2C adapter for DDC access, if any.
> > +	 */
> > +	struct i2c_adapter *ddc;
> > +	/** private: */
> > +	/**
> > +	 * @hpd_mutex: Protects the @hpd_cb and @hpd_data fields.
> > +	 */
> > +	struct mutex hpd_mutex;
> > +	/**
> > +	 * @hpd_cb: Hot plug detection callback, registered with
> > +	 * drm_bridge_hpd_enable().
> > +	 */
> > +	void (*hpd_cb)(void *data, enum drm_connector_status status);
> > +	/**
> > +	 * @hpd_data: Private data passed to the Hot plug detection callback
> > +	 * @hpd_cb.
> > +	 */
> > +	void *hpd_data;
> >  };

-- 
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] 106+ messages in thread

* Re: [PATCH v2 13/50] drm/bridge: panel: Implement bridge connector operations
  2019-08-22 18:02       ` Boris Brezillon
@ 2019-08-23  0:39         ` Laurent Pinchart
  0 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-23  0:39 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

Hi Boris,

On Thu, Aug 22, 2019 at 08:02:47PM +0200, Boris Brezillon wrote:
> On Thu, 22 Aug 2019 19:35:24 +0300 Laurent Pinchart wrote:
> > On Thu, Aug 22, 2019 at 06:29:09PM +0200, Boris Brezillon wrote:
> >> On Tue, 20 Aug 2019 04:16:44 +0300 Laurent Pinchart wrote:
> >>   
> >>> Implement the newly added bridge connector operations, allowing the
> >>> usage of drm_bridge_panel with drm_bridge_connector.
> >>> 
> >>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >>> ---
> >>>  drivers/gpu/drm/bridge/panel.c | 18 +++++++++++++++++-
> >>>  1 file changed, 17 insertions(+), 1 deletion(-)
> >>> 
> >>> diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
> >>> index f5b8e55301ac..1c7f5b648f05 100644
> >>> --- a/drivers/gpu/drm/bridge/panel.c
> >>> +++ b/drivers/gpu/drm/bridge/panel.c
> >>> @@ -60,7 +60,7 @@ static int panel_bridge_attach(struct drm_bridge *bridge,
> >>>  	int ret;
> >>>  
> >>>  	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> >>> -		return -EINVAL;
> >>> +		return 0;
> >>>  
> >>>  	if (!bridge->encoder) {
> >>>  		DRM_ERROR("Missing encoder\n");
> >>> @@ -123,6 +123,18 @@ static void panel_bridge_post_disable(struct drm_bridge *bridge)
> >>>  	drm_panel_unprepare(panel_bridge->panel);
> >>>  }
> >>>  
> >>> +static int panel_bridge_get_modes(struct drm_bridge *bridge,
> >>> +				  struct drm_connector *connector)
> >>> +{
> >>> +	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
> >>> +
> >>> +	/*
> >>> +	 * FIXME: drm_panel_get_modes() should take the connector as an
> >>> +	 * argument.
> >>> +	 */
> >>> +	return drm_panel_get_modes(panel_bridge->panel);
> >>> +}
> >>> +
> >>>  static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
> >>>  	.attach = panel_bridge_attach,
> >>>  	.detach = panel_bridge_detach,
> >>> @@ -130,6 +142,7 @@ static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
> >>>  	.enable = panel_bridge_enable,
> >>>  	.disable = panel_bridge_disable,
> >>>  	.post_disable = panel_bridge_post_disable,
> >>> +	.get_modes = panel_bridge_get_modes,
> >>>  };
> >>>  
> >>>  /**
> >>> @@ -175,6 +188,9 @@ struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
> >>>  #ifdef CONFIG_OF
> >>>  	panel_bridge->bridge.of_node = panel->dev->of_node;
> >>>  #endif
> >>> +	panel_bridge->bridge.ops = DRM_BRIDGE_OP_MODES;
> >>> +	/* FIXME: The panel should report its type. */
> >>> +	panel_bridge->bridge.type = DRM_MODE_CONNECTOR_DPI;  
> >> 
> >> Shouldn't we patch all panel drivers to expose this type before doing
> >> this change? I mean, the connector type is exposed to userspace, and I
> >> wouldn't be surprised if some userspace apps/libs decided to base their
> >> output selection logic on this field.  
> > 
> > Note that this type will only make it to userspace for drivers that use
> > the bridge->type field, likely through the drm bridge connector helper.
> > I do agree that panel drivers should be updated, but given the number of
> > panels in panel-simple and the fact that the information would need to
> > be researched for most of them, this will be significant work. Can't
> > this be done when converting display controller drivers on a need basis
> > ?
> 
> I think setting a default value and fixing things on a need basis is
> okay, but that doesn't prevent you from adding the necessary
> infrastructure to let panel drivers pass this type (we can fallback to a
> default type in panel drivers instead of here).

I'll add the infrastructure/

> I'm also not sure why 'DPI' is chosen as the default, shouldn't we use
> 'Unknown' instead?

Mostly to avoid breaking userspace, as most panels supported by
drm_panel use DPI.

> > Or maybe we could, as an interim measure, derive the type from the bus
> > formats reported by the panel if the panel type is not set ? If the
> > panel reports MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,
> > MEDIA_BUS_FMT_RGB666_1X7X4_SPWG or MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA then
> > we can set the type to LVDS, otherwise we set it to DPI.
> 
> Hm, aren't we better off patching panel descs exposing these bus formats
> to also explicitly set desc->type to LVDS, leaving others to Unknown
> (Unknown is 0, so you don't have to patch all panel_desc definitions)?

I was thinking about adding this logic to
drivers/gpu/drm/bridge/panel.c, which would avoid patching lots of panel
drivers as a prerequisite. With such a logic there, plus a default to
DPI, I thought we would be good enough for an initial version. It would
leave DSI unhandled, so maybe not the best :-S

> > I can submit a
> > patch to add a type field to the panel structure and implement this
> > logic.

-- 
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] 106+ messages in thread

* Re: [PATCH v2 04/50] drm/bridge: Add connector-related bridge operations and data
  2019-08-23  0:34     ` Laurent Pinchart
@ 2019-08-23  6:15       ` Boris Brezillon
  0 siblings, 0 replies; 106+ messages in thread
From: Boris Brezillon @ 2019-08-23  6:15 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

On Fri, 23 Aug 2019 03:34:06 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

> Hi Boris,
> 
> On Thu, Aug 22, 2019 at 06:41:25PM +0200, Boris Brezillon wrote:
> > On Tue, 20 Aug 2019 04:16:35 +0300 Laurent Pinchart wrote:
> >   
> > > +/**
> > > + * enum drm_bridge_ops - Bitmask of operations supported by the bridge
> > > + */
> > > +enum drm_bridge_ops {
> > > +	/**
> > > +	 * @DRM_BRIDGE_OP_DETECT: The bridge can detect displays connected to
> > > +	 * its output. Bridges that set this flag shall implement the
> > > +	 * &drm_bridge_funcs->detect callback.
> > > +	 */
> > > +	DRM_BRIDGE_OP_DETECT = BIT(0),
> > > +	/**
> > > +	 * @DRM_BRIDGE_OP_EDID: The bridge can retrieve the EDID of the display
> > > +	 * connected to its output. Bridges that set this flag shall implement
> > > +	 * the &drm_bridge_funcs->get_edid callback.
> > > +	 */
> > > +	DRM_BRIDGE_OP_EDID = BIT(1),
> > > +	/**
> > > +	 * @DRM_BRIDGE_OP_HPD: The bridge can detect hot-plug and hot-unplug
> > > +	 * without requiring polling. Bridges that set this flag shall
> > > +	 * implement the &drm_bridge_funcs->hpd_enable and
> > > +	 * &drm_bridge_funcs->hpd_disable callbacks if they support enabling
> > > +	 * and disabling hot-plug detection dynamically.
> > > +	 */
> > > +	DRM_BRIDGE_OP_HPD = BIT(2),
> > > +	/**
> > > +	 * @DRM_BRIDGE_OP_MODES: The bridge can retrieving the modes supported
> > > +	 * by the display at its output. This does not include readind EDID
> > > +	 * which is separately covered by @DRM_BRIDGE_OP_EDID. Bridges that set
> > > +	 * this flag shall implement the &drm_bridge_funcs->get_modes callback.
> > > +	 */
> > > +	DRM_BRIDGE_OP_MODES = BIT(3),
> > > +};
> > > +
> > >  /**
> > >   * struct drm_bridge - central DRM bridge control structure
> > >   */
> > > @@ -398,6 +538,33 @@ struct drm_bridge {
> > >  	const struct drm_bridge_funcs *funcs;
> > >  	/** @driver_private: pointer to the bridge driver's internal context */
> > >  	void *driver_private;
> > > +	/** @ops: bitmask of operations supported by the bridge */
> > > +	enum drm_bridge_ops ops;  
> > 
> > Just realized that you're not checking ->ops and ->funcs consistency at
> > attach() time (you're only checking ->ops in the tfp410 driver before
> > calling ->funcs->detect() and ->funcs->get_modes() and they might be
> > NULL).  
> 
> Do you think that's an issue ? I would then expect the driver to crash
> right away during development and the issue to be fixed.

I tend to add those checks to avoid random NULL pointer exceptions, but
if others are fine with this solution, I'm fine too.

> 
> > > +	/**
> > > +	 * @type: Type of the connection at the bridge output
> > > +	 * (DRM_MODE_CONNECTOR_*). For bridges at the end of this chain this
> > > +	 * identifies the type of connected display.
> > > +	 */
> > > +	int type;
> > > +	/**
> > > +	 * @ddc: Associated I2C adapter for DDC access, if any.
> > > +	 */
> > > +	struct i2c_adapter *ddc;
> > > +	/** private: */
> > > +	/**
> > > +	 * @hpd_mutex: Protects the @hpd_cb and @hpd_data fields.
> > > +	 */
> > > +	struct mutex hpd_mutex;
> > > +	/**
> > > +	 * @hpd_cb: Hot plug detection callback, registered with
> > > +	 * drm_bridge_hpd_enable().
> > > +	 */
> > > +	void (*hpd_cb)(void *data, enum drm_connector_status status);
> > > +	/**
> > > +	 * @hpd_data: Private data passed to the Hot plug detection callback
> > > +	 * @hpd_cb.
> > > +	 */
> > > +	void *hpd_data;
> > >  };  
> 

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

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

* Re: [PATCH v2 06/50] drm/bridge: dumb-vga-dac: Rename internal symbols to simple-bridge
  2019-08-20  1:16 ` [PATCH v2 06/50] drm/bridge: dumb-vga-dac: Rename internal symbols to simple-bridge Laurent Pinchart
  2019-08-22 15:39   ` Boris Brezillon
@ 2019-08-26 11:25   ` Maxime Ripard
  1 sibling, 0 replies; 106+ messages in thread
From: Maxime Ripard @ 2019-08-26 11:25 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 637 bytes --]

Hi,

On Tue, Aug 20, 2019 at 04:16:37AM +0300, Laurent Pinchart wrote:
> The dumb-vga-dac driver is a simple DRM bridge driver for simple VGA
> DACs that don't require configuration. Other non-VGA bridges fall in a
> similar category, and would benefit from a common driver. Prepare for
> this by renaming the internal symbols from dumb-vga-dac to
> simple-bridge.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>

Reviewed-by: Maxime Ripard <maxime.ripard@bootlin.com>

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

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

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

* Re: [PATCH v2 07/50] drm/bridge: dumb-vga-dac: Rename driver to simple-bridge
  2019-08-20  1:16 ` [PATCH v2 07/50] drm/bridge: dumb-vga-dac: Rename driver " Laurent Pinchart
  2019-08-22 15:42   ` Boris Brezillon
@ 2019-08-26 11:26   ` Maxime Ripard
  1 sibling, 0 replies; 106+ messages in thread
From: Maxime Ripard @ 2019-08-26 11:26 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Simon Horman, Sebastian Reichel, dri-devel, Russell King,
	Chen-Yu Tsai, Tomi Valkeinen, Sean Paul


[-- Attachment #1.1: Type: text/plain, Size: 457 bytes --]

On Tue, Aug 20, 2019 at 04:16:38AM +0300, Laurent Pinchart wrote:
> The dumb-vga-dac driver can support simple DRM bridges without being
> limited to VGA DACs. Rename it to simple-bridge.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>

Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

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

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

* Re: [PATCH v2 08/50] drm/bridge: simple-bridge: Add support for non-VGA bridges
  2019-08-20  1:16 ` [PATCH v2 08/50] drm/bridge: simple-bridge: Add support for non-VGA bridges Laurent Pinchart
  2019-08-22 15:43   ` Boris Brezillon
@ 2019-08-26 11:27   ` Maxime Ripard
  1 sibling, 0 replies; 106+ messages in thread
From: Maxime Ripard @ 2019-08-26 11:27 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 640 bytes --]

On Tue, Aug 20, 2019 at 04:16:39AM +0300, Laurent Pinchart wrote:
> Create a new simple_bridge_info structure that stores information about
> the bridge model, and store the bridge timings in there, along with the
> connector type. Use that new structure for of_device_id data. This
> enables support for non-VGA bridges.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
> Reviewed-by: Stefan Agner <stefan@agner.ch>

Reviewed-by: Maxime Ripard <maxime.ripard@bootlin.com>

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

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

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

* Re: [PATCH v2 09/50] drm/bridge: simple-bridge: Add support for enable GPIO
  2019-08-20  1:16 ` [PATCH v2 09/50] drm/bridge: simple-bridge: Add support for enable GPIO Laurent Pinchart
  2019-08-22 15:45   ` Boris Brezillon
@ 2019-08-26 11:33   ` Maxime Ripard
  1 sibling, 0 replies; 106+ messages in thread
From: Maxime Ripard @ 2019-08-26 11:33 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 498 bytes --]

On Tue, Aug 20, 2019 at 04:16:40AM +0300, Laurent Pinchart wrote:
> If an enable GPIO is declared in the firmware, assert it when enabling
> the bridge and deassert it when disabling it.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
> Reviewed-by: Stefan Agner <stefan@agner.ch>

Reviewed-by: Maxime Ripard <mripard@kernel.org>

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

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

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

* Re: [PATCH v2 10/50] drm/bridge: simple-bridge: Add support for the TI OP362
  2019-08-20  1:16 ` [PATCH v2 10/50] drm/bridge: simple-bridge: Add support for the TI OP362 Laurent Pinchart
  2019-08-22 15:45   ` Boris Brezillon
@ 2019-08-26 11:34   ` Maxime Ripard
  1 sibling, 0 replies; 106+ messages in thread
From: Maxime Ripard @ 2019-08-26 11:34 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 452 bytes --]

On Tue, Aug 20, 2019 at 04:16:41AM +0300, Laurent Pinchart wrote:
> The TI OP362 is an analog video amplifier controlled through a GPIO. Add
> support for it to the simple-bridge driver.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>

Reviewed-by: Maxime Ripard <mripard@kernel.org>

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

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

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

* Re: [PATCH v2 11/50] drm/bridge: Add bridge driver for display connectors
  2019-08-20  1:16 ` [PATCH v2 11/50] drm/bridge: Add bridge driver for display connectors Laurent Pinchart
  2019-08-22 16:05   ` Boris Brezillon
@ 2019-08-26 11:36   ` Maxime Ripard
  1 sibling, 0 replies; 106+ messages in thread
From: Maxime Ripard @ 2019-08-26 11:36 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 899 bytes --]

On Tue, Aug 20, 2019 at 04:16:42AM +0300, Laurent Pinchart wrote:
> Display connectors are modelled in DT as a device node, but have so far
> been handled manually in several bridge drivers. This resulted in
> duplicate code in several bridge drivers, with slightly different (and
> thus confusing) logics.
>
> In order to fix this, implement a bridge driver for display connectors.
> The driver centralises logic for the DVI, HDMI, VGAn composite and
> S-video connectors and exposes corresponding bridge operations.
>
> This driver in itself doesn't solve the issue completely, changes in
> bridge and display controller drivers are needed to make use of the new
> connector driver.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Maxime Ripard <mripard@kernel.org>

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

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

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

* Re: [PATCH v2 25/50] drm/omap: hdmi4: Rework EDID read to isolate data read
  2019-08-20  1:16 ` [PATCH v2 25/50] drm/omap: hdmi4: Rework EDID read to isolate data read Laurent Pinchart
@ 2019-08-26 11:39   ` Tomi Valkeinen
  2019-08-26 13:06     ` Laurent Pinchart
  0 siblings, 1 reply; 106+ messages in thread
From: Tomi Valkeinen @ 2019-08-26 11:39 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel; +Cc: Maxime Ripard, Sean Paul, Sebastian Reichel

Hi,

On 20/08/2019 04:16, Laurent Pinchart wrote:
> In preparation of adding DRM bridge support to the hdmi4 encoder code,
> rework the EDID read to isolate data read.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>   drivers/gpu/drm/omapdrm/dss/hdmi4.c      | 94 +++++++++++++++---------
>   drivers/gpu/drm/omapdrm/dss/hdmi4_core.c | 59 +++------------
>   drivers/gpu/drm/omapdrm/dss/hdmi4_core.h |  4 +-
>   3 files changed, 73 insertions(+), 84 deletions(-)

I find this (and the next) patch a bit difficult to review. Can you 
explain a bit more what the purpose and the change is?

  Tomi

-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 29/50] drm/omap: hdmi4: Move mode set, enable and disable operations to bridge
  2019-08-20  1:17 ` [PATCH v2 29/50] drm/omap: hdmi4: Move mode set, enable and disable operations to bridge Laurent Pinchart
@ 2019-08-26 11:50   ` Tomi Valkeinen
  0 siblings, 0 replies; 106+ messages in thread
From: Tomi Valkeinen @ 2019-08-26 11:50 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel; +Cc: Maxime Ripard, Sean Paul, Sebastian Reichel

On 20/08/2019 04:17, Laurent Pinchart wrote:
> Move the omap_dss_device .set_timings(), .enable() and .disable()
> operations to the drm_bridge functions. As the drm_bridge for the HDMI
> encoder is unconditionally registered and attached, those operations
> will be called at the appropriate time.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>   drivers/gpu/drm/omapdrm/dss/hdmi4.c | 201 +++++++++++++++-------------
>   1 file changed, 106 insertions(+), 95 deletions(-)

set_hdmi_mode and set_infoframe seem to get merged into bridge_enable. I 
think that's worth mentioning in the desc. (for the next patch too)

  Tomi

-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel
  2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
                   ` (49 preceding siblings ...)
  2019-08-20  1:17 ` [PATCH v2 50/50] drm/omap: dss: Remove unused omapdss_of_find_connected_device() function Laurent Pinchart
@ 2019-08-26 12:15 ` Tomi Valkeinen
  2019-08-26 13:51   ` Laurent Pinchart
  50 siblings, 1 reply; 106+ messages in thread
From: Tomi Valkeinen @ 2019-08-26 12:15 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel; +Cc: Maxime Ripard, Sean Paul, Sebastian Reichel

Hi Laurent,

On 20/08/2019 04:16, Laurent Pinchart wrote:

> The patches can be found at
> 
> 	git://linuxtv.org/pinchartl/media.git omapdrm/bridge/devel

I took your branch, booted AM5 EVM (I see you had the hack dts patch in your branch), and:

insmod nfs/work/linux/drivers/media/cec/cec.ko
insmod nfs/work/linux/drivers/video/fbdev/core/cfbcopyarea.ko
insmod nfs/work/linux/drivers/video/fbdev/core/cfbimgblt.ko
insmod nfs/work/linux/drivers/video/fbdev/core/cfbfillrect.ko
insmod nfs/work/linux/drivers/gpu/drm/drm_panel_orientation_quirks.ko
insmod nfs/work/linux/drivers/gpu/drm/drm.ko
insmod nfs/work/linux/drivers/gpu/drm/drm_kms_helper.ko
insmod nfs/work/linux/drivers/gpu/drm/bridge/ti-tfp410.ko
insmod nfs/work/linux/drivers/gpu/drm/bridge/sii902x.ko
insmod nfs/work/linux/drivers/gpu/drm/bridge/tc358767.ko
insmod nfs/work/linux/drivers/gpu/drm/panel/panel-simple.ko
[   25.487002] panel-simple display: display supply power not found, using dummy regulator
[   25.495241] ------------[ cut here ]------------
[   25.499900] WARNING: CPU: 0 PID: 303 at drivers/gpu/drm/panel/panel-simple.c:378 panel_simple_probe+0x34c/0x3b4 [panel_simple]
[   25.511691] Modules linked in: panel_simple(+) tc358767 sii902x ti_tfp410 drm_kms_helper drm drm_panel_orientation_quirks cfbfillrect cfbimgblt cfbcopyarea cec
[   25.526341] CPU: 0 PID: 303 Comm: insmod Tainted: G        W         5.3.0-rc3-01400-g27515343445e #1
[   25.535602] Hardware name: Generic DRA74X (Flattened Device Tree)
[   25.541740] [<c01139b4>] (unwind_backtrace) from [<c010da68>] (show_stack+0x10/0x14)
[   25.549526] [<c010da68>] (show_stack) from [<c0941138>] (dump_stack+0xa8/0xc4)
[   25.556789] [<c0941138>] (dump_stack) from [<c013a57c>] (__warn.part.3+0xa8/0xd4)
[   25.564309] [<c013a57c>] (__warn.part.3) from [<c013a700>] (warn_slowpath_null+0x40/0x4c)
[   25.572540] [<c013a700>] (warn_slowpath_null) from [<bf0b86f0>] (panel_simple_probe+0x34c/0x3b4 [panel_simple])
[   25.582699] [<bf0b86f0>] (panel_simple_probe [panel_simple]) from [<c05f845c>] (platform_drv_probe+0x48/0x98)
[   25.592664] [<c05f845c>] (platform_drv_probe) from [<c05f5f4c>] (really_probe+0x100/0x410)
[   25.600969] [<c05f5f4c>] (really_probe) from [<c05f6428>] (driver_probe_device+0x6c/0x1b4)
[   25.609273] [<c05f6428>] (driver_probe_device) from [<c05f67c0>] (device_driver_attach+0x58/0x60)
[   25.618188] [<c05f67c0>] (device_driver_attach) from [<c05f686c>] (__driver_attach+0xa4/0x148)
[   25.626843] [<c05f686c>] (__driver_attach) from [<c05f3f24>] (bus_for_each_dev+0x70/0xb4)
[   25.635060] [<c05f3f24>] (bus_for_each_dev) from [<c05f5268>] (bus_add_driver+0x1a8/0x200)
[   25.643365] [<c05f5268>] (bus_add_driver) from [<c05f7414>] (driver_register+0x74/0x108)
[   25.651506] [<c05f7414>] (driver_register) from [<bf0aa010>] (panel_simple_init+0x10/0x1000 [panel_simple])
[   25.661634] ---[ end trace 1bb774fc77a9c1a2 ]---
[   25.666414] panel-simple display: Reject override mode: panel has a fixed mode
insmod nfs/work/linux/drivers/gpu/drm/omapdrm/dss/omapdss-base.ko
insmod nfs/work/linux/drivers/gpu/drm/omapdrm/dss/omapdss.ko
[   25.846736] DSS: OMAP DSS rev 6.1
insmod nfs/work/linux/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.ko
insmod nfs/work/linux/drivers/gpu/drm/omapdrm/omapdrm.ko
[   26.274382] dmm 4e000000.dmm: workaround for errata i878 in use
[   26.281981] dmm 4e000000.dmm: initialized all PAT entries
[   26.289408] ------------[ cut here ]------------
[   26.294298] WARNING: CPU: 1 PID: 64 at lib/list_debug.c:28 __list_add_valid+0x74/0xb0
[   26.302166] list_add corruption. prev->next should be next (bf0692bc), but was 6b6b6b6b. (prev=eadcd384).
[   26.314711] Modules linked in: omapdrm panel_dsi_cm omapdss omapdss_base panel_simple tc358767 sii902x ti_tfp410 drm_kms_helper drm drm_panel_orientation_quirks cfbf
illrect cfbimgblt cfbcopyarea cec
# [   26.332661] CPU: 1 PID: 64 Comm: kworker/1:1 Tainted: G        W         5.3.0-rc3-01400-g27515343445e #1
[   26.342354] Hardware name: Generic DRA74X (Flattened Device Tree)
[   26.348483] Workqueue: events deferred_probe_work_func
[   26.353658] [<c01139b4>] (unwind_backtrace) from [<c010da68>] (show_stack+0x10/0x14)
[   26.361445] [<c010da68>] (show_stack) from [<c0941138>] (dump_stack+0xa8/0xc4)
[   26.368707] [<c0941138>] (dump_stack) from [<c013a57c>] (__warn.part.3+0xa8/0xd4)
[   26.376229] [<c013a57c>] (__warn.part.3) from [<c013a604>] (warn_slowpath_fmt+0x5c/0x88)
[   26.384360] [<c013a604>] (warn_slowpath_fmt) from [<c04e5ef4>] (__list_add_valid+0x74/0xb0)
[   26.392806] [<c04e5ef4>] (__list_add_valid) from [<bf037c34>] (drm_bridge_add+0x40/0x6c [drm])
[   26.401545] [<bf037c34>] (drm_bridge_add [drm]) from [<bf0e2a0c>] (hdmi5_probe+0x17c/0x264 [omapdss])
[   26.410845] [<bf0e2a0c>] (hdmi5_probe [omapdss]) from [<c05f845c>] (platform_drv_probe+0x48/0x98)
[   26.419762] [<c05f845c>] (platform_drv_probe) from [<c05f5f4c>] (really_probe+0x100/0x410)
[   26.428068] [<c05f5f4c>] (really_probe) from [<c05f6428>] (driver_probe_device+0x6c/0x1b4)
[   26.436373] [<c05f6428>] (driver_probe_device) from [<c05f3ff8>] (bus_for_each_drv+0x7c/0xc4)
[   26.444938] [<c05f3ff8>] (bus_for_each_drv) from [<c05f5da4>] (__device_attach+0xc8/0x168)
[   26.453243] [<c05f5da4>] (__device_attach) from [<c05f4f80>] (bus_probe_device+0x84/0x8c)
[   26.461458] [<c05f4f80>] (bus_probe_device) from [<c05f54cc>] (deferred_probe_work_func+0x84/0xcc)
[   26.470463] [<c05f54cc>] (deferred_probe_work_func) from [<c0155c98>] (process_one_work+0x184/0x504)
[   26.479641] [<c0155c98>] (process_one_work) from [<c015691c>] (worker_thread+0x2c/0x51c)
[   26.487773] [<c015691c>] (worker_thread) from [<c015bd04>] (kthread+0x140/0x158)
[   26.495205] [<c015bd04>] (kthread) from [<c01010e8>] (ret_from_fork+0x14/0x2c)
[   26.502461] Exception stack(0xeaba3fb0 to 0xeaba3ff8)
[   26.507536] 3fa0:                                     00000000 00000000 00000000 00000000
[   26.515750] 3fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[   26.523964] 3fe0: 00000000 00000000 00000000 00000000 00000013 00000000
[   26.531766] ---[ end trace 1bb774fc77a9c1a3 ]---
[   26.536482] 8<--- cut here ---
[   26.539550] Unable to handle kernel paging request at virtual address 6b6b6b67
[   26.546845] pgd = e9e66080
[   26.549651] [6b6b6b67] *pgd=00000000
[   26.553249] Internal error: Oops: 5 [#1] PREEMPT SMP ARM
[   26.558584] Modules linked in: omapdrm panel_dsi_cm omapdss omapdss_base panel_simple tc358767 sii902x ti_tfp410 drm_kms_helper drm drm_panel_orientation_quirks cfbf
illrect cfbimgblt cfbcopyarea cec
[   26.576327] CPU: 1 PID: 64 Comm: kworker/1:1 Tainted: G        W         5.3.0-rc3-01400-g27515343445e #1
[   26.585933] Hardware name: Generic DRA74X (Flattened Device Tree)
[   26.592057] Workqueue: events deferred_probe_work_func
[   26.597270] PC is at of_drm_find_bridge+0x38/0x7c [drm]
[   26.602519] LR is at 0x0
[   26.605063] pc : [<bf037bb0>]    lr : [<00000000>]    psr: 900b0013
[   26.611356] sp : eaba3de0  ip : eaba2000  fp : 00000013
[   26.616604] r10: c0ebcc98  r9 : bf0e83c8  r8 : eaf69120
[   26.621852] r7 : eaf69174  r6 : eaf69174  r5 : efde6760  r4 : 6b6b6b5b
[   26.628406] r3 : 6b6b6b6b  r2 : 00000000  r1 : 00000000  r0 : bf0692bc
[   26.634964] Flags: NzcV  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
[   26.642132] Control: 10c5387d  Table: aafa806a  DAC: 00000051
[   26.647904] Process kworker/1:1 (pid: 64, stack limit = 0xef0d19b6)
[   26.654195] Stack: (0xeaba3de0 to 0xeaba4000)
[   26.658575] 3de0: eaf69120 efde6760 eaf69174 bf0aab64 eaf69000 ea0e8810 00000000 bf0e2a54
[   26.666790] 3e00: 00002000 bf0f02fc eaf69000 ea0e8810 c0f13054 ea0e8810 00000000 bf0f2220
[   26.675005] 3e20: 00000000 00000000 bf0f2220 c05f845c ea0e8810 c0f13054 c0f13058 00000000
[   26.683219] 3e40: 00000000 c05f5f4c c05f666c ea0e8810 c0b95478 ea0e8810 bf0f2220 c05f666c
[   26.691432] 3e60: c0e05148 00000001 c0ebcc98 c0ebcc98 c0b95478 c05f6428 00000001 c05f6638
[   26.699647] 3e80: bf0f2220 00000000 eaba3ecc c05f666c c0e05148 00000001 c0ebcc98 c05f3ff8
[   26.707862] 3ea0: c0b95478 eb8e0b6c eafda3b8 db20362b ea0e8810 ea0e8810 ea0e8854 c0e05148
[   26.716076] 3ec0: c0e88e78 c05f5da4 ea0e8810 ea0e8810 00000001 db20362b eafda2d4 ea0e8810
[   26.724291] 3ee0: c0e89100 c0e88e78 c0e88e8c c05f4f80 eafda2d4 ea0e8810 c0e88e78 c05f54cc
[   26.732505] 3f00: c05f5448 c0e88ea0 ea884780 efd8ef80 efd92300 00000000 c0eb30b0 00000000
[   26.740719] 3f20: ffffe000 c0155c98 ea869800 efd8ef80 00000008 ea884780 ea884794 efd8ef80
[   26.748934] 3f40: 00000008 efd8ef98 c0e03d00 efd8ef80 ffffe000 c015691c eaaeca9c c095f020
[   26.757150] 3f60: eaaeca9c 00000000 eaaeca80 eaaecac0 eaba2000 ea884780 c01568f0 eb91feb4
[   26.765365] 3f80: eaaeca9c c015bd04 00000000 eaaecac0 c015bbc4 00000000 00000000 00000000
[   26.773580] 3fa0: 00000000 00000000 00000000 c01010e8 00000000 00000000 00000000 00000000
[   26.781794] 3fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[   26.790009] 3fe0: 00000000 00000000 00000000 00000000 00000013 00000000 00000000 00000000
[   26.798278] [<bf037bb0>] (of_drm_find_bridge [drm]) from [<bf0aab64>] (omapdss_device_init_output+0x38/0x4d4 [omapdss_base])
[   26.809583] [<bf0aab64>] (omapdss_device_init_output [omapdss_base]) from [<bf0e2a54>] (hdmi5_probe+0x1c4/0x264 [omapdss])
[   26.820709] [<bf0e2a54>] (hdmi5_probe [omapdss]) from [<c05f845c>] (platform_drv_probe+0x48/0x98)
[   26.829627] [<c05f845c>] (platform_drv_probe) from [<c05f5f4c>] (really_probe+0x100/0x410)
[   26.837932] [<c05f5f4c>] (really_probe) from [<c05f6428>] (driver_probe_device+0x6c/0x1b4)
[   26.846236] [<c05f6428>] (driver_probe_device) from [<c05f3ff8>] (bus_for_each_drv+0x7c/0xc4)
[   26.854802] [<c05f3ff8>] (bus_for_each_drv) from [<c05f5da4>] (__device_attach+0xc8/0x168)
[   26.863106] [<c05f5da4>] (__device_attach) from [<c05f4f80>] (bus_probe_device+0x84/0x8c)
[   26.871323] [<c05f4f80>] (bus_probe_device) from [<c05f54cc>] (deferred_probe_work_func+0x84/0xcc)
[   26.880326] [<c05f54cc>] (deferred_probe_work_func) from [<c0155c98>] (process_one_work+0x184/0x504)
[   26.889503] [<c0155c98>] (process_one_work) from [<c015691c>] (worker_thread+0x2c/0x51c)
[   26.897634] [<c015691c>] (worker_thread) from [<c015bd04>] (kthread+0x140/0x158)
[   26.905065] [<c015bd04>] (kthread) from [<c01010e8>] (ret_from_fork+0x14/0x2c)
[   26.912318] Exception stack(0xeaba3fb0 to 0xeaba3ff8)
[   26.917393] 3fa0:                                     00000000 00000000 00000000 00000000
[   26.925607] 3fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[   26.933821] 3fe0: 00000000 00000000 00000000 00000000 00000013 00000000
[   26.940469] Code: e5133004 e1550003 1a000003 ea00000b (e5133004) 
[   26.946649] ---[ end trace 1bb774fc77a9c1a4 ]---



-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 25/50] drm/omap: hdmi4: Rework EDID read to isolate data read
  2019-08-26 11:39   ` Tomi Valkeinen
@ 2019-08-26 13:06     ` Laurent Pinchart
  0 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-26 13:06 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: Maxime Ripard, Sean Paul, Sebastian Reichel, dri-devel

Hi Tomi,

On Mon, Aug 26, 2019 at 02:39:25PM +0300, Tomi Valkeinen wrote:
> On 20/08/2019 04:16, Laurent Pinchart wrote:
> > In preparation of adding DRM bridge support to the hdmi4 encoder code,
> > rework the EDID read to isolate data read.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >   drivers/gpu/drm/omapdrm/dss/hdmi4.c      | 94 +++++++++++++++---------
> >   drivers/gpu/drm/omapdrm/dss/hdmi4_core.c | 59 +++------------
> >   drivers/gpu/drm/omapdrm/dss/hdmi4_core.h |  4 +-
> >   3 files changed, 73 insertions(+), 84 deletions(-)
> 
> I find this (and the next) patch a bit difficult to review. Can you 
> explain a bit more what the purpose and the change is?

The commit message in v3 will read

drm/omap: hdmi5: Rework EDID read to isolate data read

In preparation of adding DRM bridge support to the hdmi5 encoder code,
rework the EDID read to isolate data read.

The hdmi_read_edid() function is the main entry point. It performs all
initialisation steps required prior to reading the EDID (such as
ensuring the device is powered on), as well as corresponding cleanup
steps afterwards. EDID read itself is handled by hdmi_read_edid_data()
that calls the hdmi5_core_ddc_read() function to read individual blocks.

This new code architecture will allow reusing hdmi_read_edid() and
hdmi5_core_ddc_read() for the drm_bridge EDID read implementation, while
swapping out hdmi_read_edid_data() for the DRM drm_do_get_edid()
function.

-- 
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] 106+ messages in thread

* Re: [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel
  2019-08-26 12:15 ` [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Tomi Valkeinen
@ 2019-08-26 13:51   ` Laurent Pinchart
  2019-08-27  7:34     ` Tomi Valkeinen
  0 siblings, 1 reply; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-26 13:51 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: Maxime Ripard, Sean Paul, Sebastian Reichel, dri-devel

Hi Tomi,

On Mon, Aug 26, 2019 at 03:15:23PM +0300, Tomi Valkeinen wrote:
> On 20/08/2019 04:16, Laurent Pinchart wrote:
> 
> > The patches can be found at
> > 
> > 	git://linuxtv.org/pinchartl/media.git omapdrm/bridge/devel
> 
> I took your branch, booted AM5 EVM (I see you had the hack dts patch in your branch), and:
> 
> insmod nfs/work/linux/drivers/media/cec/cec.ko
> insmod nfs/work/linux/drivers/video/fbdev/core/cfbcopyarea.ko
> insmod nfs/work/linux/drivers/video/fbdev/core/cfbimgblt.ko
> insmod nfs/work/linux/drivers/video/fbdev/core/cfbfillrect.ko
> insmod nfs/work/linux/drivers/gpu/drm/drm_panel_orientation_quirks.ko
> insmod nfs/work/linux/drivers/gpu/drm/drm.ko
> insmod nfs/work/linux/drivers/gpu/drm/drm_kms_helper.ko
> insmod nfs/work/linux/drivers/gpu/drm/bridge/ti-tfp410.ko
> insmod nfs/work/linux/drivers/gpu/drm/bridge/sii902x.ko
> insmod nfs/work/linux/drivers/gpu/drm/bridge/tc358767.ko
> insmod nfs/work/linux/drivers/gpu/drm/panel/panel-simple.ko
> [   25.487002] panel-simple display: display supply power not found, using dummy regulator
> [   25.495241] ------------[ cut here ]------------
> [   25.499900] WARNING: CPU: 0 PID: 303 at drivers/gpu/drm/panel/panel-simple.c:378 panel_simple_probe+0x34c/0x3b4 [panel_simple]

How am I expected to sneak patches in if you test them ? :-)

This has been introduced by a recent rebase, and I've only tested the
series on the pandaboard since then. It looks like the problem comes
from

commit b8a2948fa2b3a5a6da67fd57aa01c7318d795125
Author: Sean Paul <seanpaul@chromium.org>
Date:   Thu Jul 11 13:34:53 2019 -0700

    drm/panel: simple: Add ability to override typical timing

which breaks our out-of-tree DT. As a short term fix I can simply drop
the panel timings from DT, but I think this issue can affect more
boards, and should thus probably be addressed on the kernel side.

One option is to patch osddisplays_osd070t1718_19ts to specify timings
instead of a fixed mode, but I don't have access to the panel's
datasheet. I'm also concerned this wouldn't scale.

Another option is to avoid the WARN_ON() if the timings parsed from DT
are identifical to the timings in the panel-simple driver. Sean, what's
your opinion ?

> [   25.511691] Modules linked in: panel_simple(+) tc358767 sii902x ti_tfp410 drm_kms_helper drm drm_panel_orientation_quirks cfbfillrect cfbimgblt cfbcopyarea cec
> [   25.526341] CPU: 0 PID: 303 Comm: insmod Tainted: G        W         5.3.0-rc3-01400-g27515343445e #1
> [   25.535602] Hardware name: Generic DRA74X (Flattened Device Tree)
> [   25.541740] [<c01139b4>] (unwind_backtrace) from [<c010da68>] (show_stack+0x10/0x14)
> [   25.549526] [<c010da68>] (show_stack) from [<c0941138>] (dump_stack+0xa8/0xc4)
> [   25.556789] [<c0941138>] (dump_stack) from [<c013a57c>] (__warn.part.3+0xa8/0xd4)
> [   25.564309] [<c013a57c>] (__warn.part.3) from [<c013a700>] (warn_slowpath_null+0x40/0x4c)
> [   25.572540] [<c013a700>] (warn_slowpath_null) from [<bf0b86f0>] (panel_simple_probe+0x34c/0x3b4 [panel_simple])
> [   25.582699] [<bf0b86f0>] (panel_simple_probe [panel_simple]) from [<c05f845c>] (platform_drv_probe+0x48/0x98)
> [   25.592664] [<c05f845c>] (platform_drv_probe) from [<c05f5f4c>] (really_probe+0x100/0x410)
> [   25.600969] [<c05f5f4c>] (really_probe) from [<c05f6428>] (driver_probe_device+0x6c/0x1b4)
> [   25.609273] [<c05f6428>] (driver_probe_device) from [<c05f67c0>] (device_driver_attach+0x58/0x60)
> [   25.618188] [<c05f67c0>] (device_driver_attach) from [<c05f686c>] (__driver_attach+0xa4/0x148)
> [   25.626843] [<c05f686c>] (__driver_attach) from [<c05f3f24>] (bus_for_each_dev+0x70/0xb4)
> [   25.635060] [<c05f3f24>] (bus_for_each_dev) from [<c05f5268>] (bus_add_driver+0x1a8/0x200)
> [   25.643365] [<c05f5268>] (bus_add_driver) from [<c05f7414>] (driver_register+0x74/0x108)
> [   25.651506] [<c05f7414>] (driver_register) from [<bf0aa010>] (panel_simple_init+0x10/0x1000 [panel_simple])
> [   25.661634] ---[ end trace 1bb774fc77a9c1a2 ]---
> [   25.666414] panel-simple display: Reject override mode: panel has a fixed mode
> insmod nfs/work/linux/drivers/gpu/drm/omapdrm/dss/omapdss-base.ko
> insmod nfs/work/linux/drivers/gpu/drm/omapdrm/dss/omapdss.ko
> [   25.846736] DSS: OMAP DSS rev 6.1
> insmod nfs/work/linux/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.ko
> insmod nfs/work/linux/drivers/gpu/drm/omapdrm/omapdrm.ko
> [   26.274382] dmm 4e000000.dmm: workaround for errata i878 in use
> [   26.281981] dmm 4e000000.dmm: initialized all PAT entries
> [   26.289408] ------------[ cut here ]------------
> [   26.294298] WARNING: CPU: 1 PID: 64 at lib/list_debug.c:28 __list_add_valid+0x74/0xb0
> [   26.302166] list_add corruption. prev->next should be next (bf0692bc), but was 6b6b6b6b. (prev=eadcd384).
> [   26.314711] Modules linked in: omapdrm panel_dsi_cm omapdss omapdss_base panel_simple tc358767 sii902x ti_tfp410 drm_kms_helper drm drm_panel_orientation_quirks cfbf
> illrect cfbimgblt cfbcopyarea cec
> # [   26.332661] CPU: 1 PID: 64 Comm: kworker/1:1 Tainted: G        W         5.3.0-rc3-01400-g27515343445e #1
> [   26.342354] Hardware name: Generic DRA74X (Flattened Device Tree)
> [   26.348483] Workqueue: events deferred_probe_work_func
> [   26.353658] [<c01139b4>] (unwind_backtrace) from [<c010da68>] (show_stack+0x10/0x14)
> [   26.361445] [<c010da68>] (show_stack) from [<c0941138>] (dump_stack+0xa8/0xc4)
> [   26.368707] [<c0941138>] (dump_stack) from [<c013a57c>] (__warn.part.3+0xa8/0xd4)
> [   26.376229] [<c013a57c>] (__warn.part.3) from [<c013a604>] (warn_slowpath_fmt+0x5c/0x88)
> [   26.384360] [<c013a604>] (warn_slowpath_fmt) from [<c04e5ef4>] (__list_add_valid+0x74/0xb0)
> [   26.392806] [<c04e5ef4>] (__list_add_valid) from [<bf037c34>] (drm_bridge_add+0x40/0x6c [drm])
> [   26.401545] [<bf037c34>] (drm_bridge_add [drm]) from [<bf0e2a0c>] (hdmi5_probe+0x17c/0x264 [omapdss])
> [   26.410845] [<bf0e2a0c>] (hdmi5_probe [omapdss]) from [<c05f845c>] (platform_drv_probe+0x48/0x98)
> [   26.419762] [<c05f845c>] (platform_drv_probe) from [<c05f5f4c>] (really_probe+0x100/0x410)
> [   26.428068] [<c05f5f4c>] (really_probe) from [<c05f6428>] (driver_probe_device+0x6c/0x1b4)
> [   26.436373] [<c05f6428>] (driver_probe_device) from [<c05f3ff8>] (bus_for_each_drv+0x7c/0xc4)
> [   26.444938] [<c05f3ff8>] (bus_for_each_drv) from [<c05f5da4>] (__device_attach+0xc8/0x168)
> [   26.453243] [<c05f5da4>] (__device_attach) from [<c05f4f80>] (bus_probe_device+0x84/0x8c)
> [   26.461458] [<c05f4f80>] (bus_probe_device) from [<c05f54cc>] (deferred_probe_work_func+0x84/0xcc)
> [   26.470463] [<c05f54cc>] (deferred_probe_work_func) from [<c0155c98>] (process_one_work+0x184/0x504)
> [   26.479641] [<c0155c98>] (process_one_work) from [<c015691c>] (worker_thread+0x2c/0x51c)
> [   26.487773] [<c015691c>] (worker_thread) from [<c015bd04>] (kthread+0x140/0x158)
> [   26.495205] [<c015bd04>] (kthread) from [<c01010e8>] (ret_from_fork+0x14/0x2c)
> [   26.502461] Exception stack(0xeaba3fb0 to 0xeaba3ff8)
> [   26.507536] 3fa0:                                     00000000 00000000 00000000 00000000
> [   26.515750] 3fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> [   26.523964] 3fe0: 00000000 00000000 00000000 00000000 00000013 00000000
> [   26.531766] ---[ end trace 1bb774fc77a9c1a3 ]---
> [   26.536482] 8<--- cut here ---
> [   26.539550] Unable to handle kernel paging request at virtual address 6b6b6b67
> [   26.546845] pgd = e9e66080
> [   26.549651] [6b6b6b67] *pgd=00000000
> [   26.553249] Internal error: Oops: 5 [#1] PREEMPT SMP ARM
> [   26.558584] Modules linked in: omapdrm panel_dsi_cm omapdss omapdss_base panel_simple tc358767 sii902x ti_tfp410 drm_kms_helper drm drm_panel_orientation_quirks cfbf
> illrect cfbimgblt cfbcopyarea cec
> [   26.576327] CPU: 1 PID: 64 Comm: kworker/1:1 Tainted: G        W         5.3.0-rc3-01400-g27515343445e #1
> [   26.585933] Hardware name: Generic DRA74X (Flattened Device Tree)
> [   26.592057] Workqueue: events deferred_probe_work_func
> [   26.597270] PC is at of_drm_find_bridge+0x38/0x7c [drm]
> [   26.602519] LR is at 0x0
> [   26.605063] pc : [<bf037bb0>]    lr : [<00000000>]    psr: 900b0013
> [   26.611356] sp : eaba3de0  ip : eaba2000  fp : 00000013
> [   26.616604] r10: c0ebcc98  r9 : bf0e83c8  r8 : eaf69120
> [   26.621852] r7 : eaf69174  r6 : eaf69174  r5 : efde6760  r4 : 6b6b6b5b
> [   26.628406] r3 : 6b6b6b6b  r2 : 00000000  r1 : 00000000  r0 : bf0692bc
> [   26.634964] Flags: NzcV  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
> [   26.642132] Control: 10c5387d  Table: aafa806a  DAC: 00000051
> [   26.647904] Process kworker/1:1 (pid: 64, stack limit = 0xef0d19b6)
> [   26.654195] Stack: (0xeaba3de0 to 0xeaba4000)
> [   26.658575] 3de0: eaf69120 efde6760 eaf69174 bf0aab64 eaf69000 ea0e8810 00000000 bf0e2a54
> [   26.666790] 3e00: 00002000 bf0f02fc eaf69000 ea0e8810 c0f13054 ea0e8810 00000000 bf0f2220
> [   26.675005] 3e20: 00000000 00000000 bf0f2220 c05f845c ea0e8810 c0f13054 c0f13058 00000000
> [   26.683219] 3e40: 00000000 c05f5f4c c05f666c ea0e8810 c0b95478 ea0e8810 bf0f2220 c05f666c
> [   26.691432] 3e60: c0e05148 00000001 c0ebcc98 c0ebcc98 c0b95478 c05f6428 00000001 c05f6638
> [   26.699647] 3e80: bf0f2220 00000000 eaba3ecc c05f666c c0e05148 00000001 c0ebcc98 c05f3ff8
> [   26.707862] 3ea0: c0b95478 eb8e0b6c eafda3b8 db20362b ea0e8810 ea0e8810 ea0e8854 c0e05148
> [   26.716076] 3ec0: c0e88e78 c05f5da4 ea0e8810 ea0e8810 00000001 db20362b eafda2d4 ea0e8810
> [   26.724291] 3ee0: c0e89100 c0e88e78 c0e88e8c c05f4f80 eafda2d4 ea0e8810 c0e88e78 c05f54cc
> [   26.732505] 3f00: c05f5448 c0e88ea0 ea884780 efd8ef80 efd92300 00000000 c0eb30b0 00000000
> [   26.740719] 3f20: ffffe000 c0155c98 ea869800 efd8ef80 00000008 ea884780 ea884794 efd8ef80
> [   26.748934] 3f40: 00000008 efd8ef98 c0e03d00 efd8ef80 ffffe000 c015691c eaaeca9c c095f020
> [   26.757150] 3f60: eaaeca9c 00000000 eaaeca80 eaaecac0 eaba2000 ea884780 c01568f0 eb91feb4
> [   26.765365] 3f80: eaaeca9c c015bd04 00000000 eaaecac0 c015bbc4 00000000 00000000 00000000
> [   26.773580] 3fa0: 00000000 00000000 00000000 c01010e8 00000000 00000000 00000000 00000000
> [   26.781794] 3fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> [   26.790009] 3fe0: 00000000 00000000 00000000 00000000 00000013 00000000 00000000 00000000
> [   26.798278] [<bf037bb0>] (of_drm_find_bridge [drm]) from [<bf0aab64>] (omapdss_device_init_output+0x38/0x4d4 [omapdss_base])
> [   26.809583] [<bf0aab64>] (omapdss_device_init_output [omapdss_base]) from [<bf0e2a54>] (hdmi5_probe+0x1c4/0x264 [omapdss])
> [   26.820709] [<bf0e2a54>] (hdmi5_probe [omapdss]) from [<c05f845c>] (platform_drv_probe+0x48/0x98)
> [   26.829627] [<c05f845c>] (platform_drv_probe) from [<c05f5f4c>] (really_probe+0x100/0x410)
> [   26.837932] [<c05f5f4c>] (really_probe) from [<c05f6428>] (driver_probe_device+0x6c/0x1b4)
> [   26.846236] [<c05f6428>] (driver_probe_device) from [<c05f3ff8>] (bus_for_each_drv+0x7c/0xc4)
> [   26.854802] [<c05f3ff8>] (bus_for_each_drv) from [<c05f5da4>] (__device_attach+0xc8/0x168)
> [   26.863106] [<c05f5da4>] (__device_attach) from [<c05f4f80>] (bus_probe_device+0x84/0x8c)
> [   26.871323] [<c05f4f80>] (bus_probe_device) from [<c05f54cc>] (deferred_probe_work_func+0x84/0xcc)
> [   26.880326] [<c05f54cc>] (deferred_probe_work_func) from [<c0155c98>] (process_one_work+0x184/0x504)
> [   26.889503] [<c0155c98>] (process_one_work) from [<c015691c>] (worker_thread+0x2c/0x51c)
> [   26.897634] [<c015691c>] (worker_thread) from [<c015bd04>] (kthread+0x140/0x158)
> [   26.905065] [<c015bd04>] (kthread) from [<c01010e8>] (ret_from_fork+0x14/0x2c)
> [   26.912318] Exception stack(0xeaba3fb0 to 0xeaba3ff8)
> [   26.917393] 3fa0:                                     00000000 00000000 00000000 00000000
> [   26.925607] 3fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> [   26.933821] 3fe0: 00000000 00000000 00000000 00000000 00000013 00000000
> [   26.940469] Code: e5133004 e1550003 1a000003 ea00000b (e5133004) 
> [   26.946649] ---[ end trace 1bb774fc77a9c1a4 ]---

-- 
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] 106+ messages in thread

* Re: [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel
  2019-08-26 13:51   ` Laurent Pinchart
@ 2019-08-27  7:34     ` Tomi Valkeinen
  2019-08-27  9:29       ` Laurent Pinchart
  0 siblings, 1 reply; 106+ messages in thread
From: Tomi Valkeinen @ 2019-08-27  7:34 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Maxime Ripard, Sean Paul, Sebastian Reichel, dri-devel

On 26/08/2019 16:51, Laurent Pinchart wrote:
> Hi Tomi,
> 
> On Mon, Aug 26, 2019 at 03:15:23PM +0300, Tomi Valkeinen wrote:
>> On 20/08/2019 04:16, Laurent Pinchart wrote:
>>
>>> The patches can be found at
>>>
>>> 	git://linuxtv.org/pinchartl/media.git omapdrm/bridge/devel
>>
>> I took your branch, booted AM5 EVM (I see you had the hack dts patch in your branch), and:
>>
>> insmod nfs/work/linux/drivers/media/cec/cec.ko
>> insmod nfs/work/linux/drivers/video/fbdev/core/cfbcopyarea.ko
>> insmod nfs/work/linux/drivers/video/fbdev/core/cfbimgblt.ko
>> insmod nfs/work/linux/drivers/video/fbdev/core/cfbfillrect.ko
>> insmod nfs/work/linux/drivers/gpu/drm/drm_panel_orientation_quirks.ko
>> insmod nfs/work/linux/drivers/gpu/drm/drm.ko
>> insmod nfs/work/linux/drivers/gpu/drm/drm_kms_helper.ko
>> insmod nfs/work/linux/drivers/gpu/drm/bridge/ti-tfp410.ko
>> insmod nfs/work/linux/drivers/gpu/drm/bridge/sii902x.ko
>> insmod nfs/work/linux/drivers/gpu/drm/bridge/tc358767.ko
>> insmod nfs/work/linux/drivers/gpu/drm/panel/panel-simple.ko
>> [   25.487002] panel-simple display: display supply power not found, using dummy regulator
>> [   25.495241] ------------[ cut here ]------------
>> [   25.499900] WARNING: CPU: 0 PID: 303 at drivers/gpu/drm/panel/panel-simple.c:378 panel_simple_probe+0x34c/0x3b4 [panel_simple]
> 
> How am I expected to sneak patches in if you test them ? :-)
> 
> This has been introduced by a recent rebase, and I've only tested the
> series on the pandaboard since then. It looks like the problem comes
> from
> 
> commit b8a2948fa2b3a5a6da67fd57aa01c7318d795125
> Author: Sean Paul <seanpaul@chromium.org>
> Date:   Thu Jul 11 13:34:53 2019 -0700
> 
>      drm/panel: simple: Add ability to override typical timing
> 
> which breaks our out-of-tree DT. As a short term fix I can simply drop
> the panel timings from DT, but I think this issue can affect more

So just removing the timings from the panel's node should be enough? 
Still crashing for me, although the panel warning goes away.

  Tomi

-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 15/50] drm/bridge: tfp410: Replace manual connector handling with bridge
  2019-08-20  1:16 ` [PATCH v2 15/50] drm/bridge: tfp410: Replace manual connector handling with bridge Laurent Pinchart
  2019-08-22 16:36   ` Boris Brezillon
@ 2019-08-27  7:43   ` Tomi Valkeinen
  2019-08-27  8:00     ` Laurent Pinchart
  1 sibling, 1 reply; 106+ messages in thread
From: Tomi Valkeinen @ 2019-08-27  7:43 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel; +Cc: Maxime Ripard, Sean Paul, Sebastian Reichel

On 20/08/2019 04:16, Laurent Pinchart wrote:
> Now that a driver is available for display connectors, replace the
> manual connector handling code with usage of the DRM bridge API. The
> tfp410 driver doesn't deal with the display connector directly anymore,
> but still delegates drm_connector operations to the next bridge. This
> brings us one step closer to having the tfp410 driver handling the
> TFP410 only.

The next step will drop those hpd related delayed works? They look 
pretty ugly =).

> +	dvi->bridge.type = DRM_MODE_CONNECTOR_DVID;

This is not the connector type seen by userspace, is it? I have never 
seen a board use TFP410 with a DVI connector...

  Tomi

-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 15/50] drm/bridge: tfp410: Replace manual connector handling with bridge
  2019-08-27  7:43   ` Tomi Valkeinen
@ 2019-08-27  8:00     ` Laurent Pinchart
  0 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-27  8:00 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: Maxime Ripard, Sean Paul, Sebastian Reichel, dri-devel

Hi Tomi,

On Tue, Aug 27, 2019 at 10:43:15AM +0300, Tomi Valkeinen wrote:
> On 20/08/2019 04:16, Laurent Pinchart wrote:
> > Now that a driver is available for display connectors, replace the
> > manual connector handling code with usage of the DRM bridge API. The
> > tfp410 driver doesn't deal with the display connector directly anymore,
> > but still delegates drm_connector operations to the next bridge. This
> > brings us one step closer to having the tfp410 driver handling the
> > TFP410 only.
> 
> The next step will drop those hpd related delayed works? They look 
> pretty ugly =).

Yesn all the connector-related code will disappear once users of the
TFP410 will switch to the new model.

> > +	dvi->bridge.type = DRM_MODE_CONNECTOR_DVID;
> 
> This is not the connector type seen by userspace, is it? I have never 
> seen a board use TFP410 with a DVI connector...

The connector type reported to userspace comes from the HDMI connector
DT node, so dvi->bridge.type isn't very relevant there. I've set it to
DVID to match the hardware.

-- 
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] 106+ messages in thread

* Re: [PATCH v2 44/50] drm/omap: dpi: Register a drm_bridge
  2019-08-20  1:17 ` [PATCH v2 44/50] drm/omap: dpi: Register a drm_bridge Laurent Pinchart
@ 2019-08-27  9:07   ` Hans Verkuil
  2019-08-27  9:51     ` Laurent Pinchart
  0 siblings, 1 reply; 106+ messages in thread
From: Hans Verkuil @ 2019-08-27  9:07 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel

Hi Laurent,

I tried this series with my Pandaboard, but it broke my Pandaboard. After
doing a git bisect it ended up with this patch as the culprit.

If I boot my Pandaboard I get this:

[    3.271881] omapdss_dss 58000000.dss: 58000000.dss supply vdda_video not found, using dummy regulator
[    3.285369] omapdss_dss 58000000.dss: 58000000.dss supply vdda_video not found, using dummy regulator
[   24.286773] rcu: INFO: rcu_sched self-detected stall on CPU
[   24.292388] rcu:     0-...!: (1306 ticks this GP) idle=6b6/1/0x40000002 softirq=85/85 fqs=19
[   24.300689]  (t=2100 jiffies g=-1063 q=10)
[   24.304809] rcu: rcu_sched kthread starved for 2058 jiffies! g-1063 f0x0 RCU_GP_WAIT_FQS(5) ->state=0x402 ->cpu=1
[   24.315124] rcu: RCU grace-period kthread stack dump:
[   24.315124] rcu_sched       I    0    10      2 0x00000000
[   24.325805] [<c09b7130>] (__schedule) from [<c09b73a8>] (schedule+0x40/0xc0)
[   24.332885] [<c09b73a8>] (schedule) from [<c09ba9d0>] (schedule_timeout+0x174/0x2a8)
[   24.340698] [<c09ba9d0>] (schedule_timeout) from [<c01943a4>] (rcu_gp_kthread+0x49c/0x9f4)
[   24.349121] [<c01943a4>] (rcu_gp_kthread) from [<c01559f8>] (kthread+0x13c/0x148)
[   24.356658] [<c01559f8>] (kthread) from [<c01010e8>] (ret_from_fork+0x14/0x2c)
[   24.363922] Exception stack(0xe70a1fb0 to 0xe70a1ff8)
[   24.363922] 1fa0:                                     00000000 00000000 00000000 00000000
[   24.363922] 1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[   24.385437] 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000
[   24.392089] NMI backtrace for cpu 0
[   24.392120] CPU: 0 PID: 105 Comm: kworker/0:2 Not tainted 5.3.0-rc3-arm #152
[   24.392120] Hardware name: Generic OMAP4 (Flattened Device Tree)
[   24.408721] Workqueue: events deferred_probe_work_func
[   24.408721] [<c010fd70>] (unwind_backtrace) from [<c010b7e8>] (show_stack+0x10/0x14)
[   24.421783] [<c010b7e8>] (show_stack) from [<c09a054c>] (dump_stack+0x84/0x9c)
[   24.429077] [<c09a054c>] (dump_stack) from [<c09a6ecc>] (nmi_cpu_backtrace+0x8c/0xc0)
[   24.436950] [<c09a6ecc>] (nmi_cpu_backtrace) from [<c09a7014>] (nmi_trigger_cpumask_backtrace+0x114/0x12c)
[   24.446655] [<c09a7014>] (nmi_trigger_cpumask_backtrace) from [<c01961e0>] (rcu_dump_cpu_stacks+0xa4/0xcc)
[   24.456359] [<c01961e0>] (rcu_dump_cpu_stacks) from [<c01952bc>] (rcu_sched_clock_irq+0x608/0x7f8)
[   24.465362] [<c01952bc>] (rcu_sched_clock_irq) from [<c019b21c>] (update_process_times+0x34/0x6c)
[   24.465362] [<c019b21c>] (update_process_times) from [<c01acfcc>] (tick_sched_timer+0x4c/0xa8)
[   24.483001] [<c01acfcc>] (tick_sched_timer) from [<c019c470>] (__hrtimer_run_queues+0x154/0x1fc)
[   24.491851] [<c019c470>] (__hrtimer_run_queues) from [<c019c84c>] (hrtimer_interrupt+0x11c/0x2ac)
[   24.500762] [<c019c84c>] (hrtimer_interrupt) from [<c010f3ac>] (twd_handler+0x30/0x38)
[   24.500762] [<c010f3ac>] (twd_handler) from [<c018959c>] (handle_percpu_devid_irq+0x78/0x138)
[   24.517333] [<c018959c>] (handle_percpu_devid_irq) from [<c0183a60>] (generic_handle_irq+0x24/0x34)
[   24.526458] [<c0183a60>] (generic_handle_irq) from [<c0184028>] (__handle_domain_irq+0x5c/0xb4)
[   24.526458] [<c0184028>] (__handle_domain_irq) from [<c03bbf2c>] (gic_handle_irq+0x58/0x9c)
[   24.526458] [<c03bbf2c>] (gic_handle_irq) from [<c0101a8c>] (__irq_svc+0x6c/0x90)
[   24.526458] Exception stack(0xe6439d68 to 0xe6439db0)
[   24.551177] 9d60:                   c0f783e8 00000000 00000000 efdb49d0 e647f2e8 efdb7f74
[   24.551177] 9d80: e647f2e8 00000000 e647f294 e647f2e8 00000000 efdb5a98 00000000 e6439db8
[   24.551177] 9da0: c04e9830 c04e9858 20000153 ffffffff
[   24.577789] [<c0101a8c>] (__irq_svc) from [<c04e9858>] (of_drm_find_bridge+0x40/0x84)
[   24.577789] [<c04e9858>] (of_drm_find_bridge) from [<c0526608>] (omapdss_device_init_output+0x38/0x140)
[   24.595153] [<c0526608>] (omapdss_device_init_output) from [<c0530294>] (dpi_init_port+0x208/0x294)
[   24.604248] [<c0530294>] (dpi_init_port) from [<c05278c4>] (dss_probe+0x2b4/0x550)
[   24.604248] [<c05278c4>] (dss_probe) from [<c0576c1c>] (platform_drv_probe+0x48/0x98)
[   24.604248] [<c0576c1c>] (platform_drv_probe) from [<c0574eb0>] (really_probe+0xf0/0x2c4)
[   24.627990] [<c0574eb0>] (really_probe) from [<c057520c>] (driver_probe_device+0x60/0x168)
[   24.627990] [<c057520c>] (driver_probe_device) from [<c0573410>] (bus_for_each_drv+0x84/0xc8)
[   24.644866] [<c0573410>] (bus_for_each_drv) from [<c0574d4c>] (__device_attach+0xd4/0x140)
[   24.644866] [<c0574d4c>] (__device_attach) from [<c05740f8>] (bus_probe_device+0x84/0x8c)
[   24.661376] [<c05740f8>] (bus_probe_device) from [<c057456c>] (deferred_probe_work_func+0x64/0x90)
[   24.670379] [<c057456c>] (deferred_probe_work_func) from [<c014f960>] (process_one_work+0x204/0x41c)
[   24.670410] [<c014f960>] (process_one_work) from [<c01510d4>] (worker_thread+0x2a8/0x5bc)
[   24.687805] [<c01510d4>] (worker_thread) from [<c01559f8>] (kthread+0x13c/0x148)
[   24.687805] [<c01559f8>] (kthread) from [<c01010e8>] (ret_from_fork+0x14/0x2c)
[   24.702484] Exception stack(0xe6439fb0 to 0xe6439ff8)
[   24.702484] 9fa0:                                     00000000 00000000 00000000 00000000
[   24.702484] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[   24.723999] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000

I can send my .config upon request if needed.

CONFIG_OMAP2_DSS_DPI is 'y', but there is nothing connected to the DPI port.

Regards,

	Hans

On 8/20/19 3:17 AM, Laurent Pinchart wrote:
> In order to integrate with a chain of drm_bridge, the internal DPI
> output has to expose its operations through the drm_bridge API.
> Register a bridge at initialisation time to do so and remove the
> omap_dss_device operations that are now unused.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/gpu/drm/omapdrm/dss/dpi.c | 205 ++++++++++++++++++------------
>  1 file changed, 122 insertions(+), 83 deletions(-)
> 
> diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c
> index c167bd1116ec..3874e6b6ec49 100644
> --- a/drivers/gpu/drm/omapdrm/dss/dpi.c
> +++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
> @@ -21,6 +21,8 @@
>  #include <linux/string.h>
>  #include <linux/sys_soc.h>
>  
> +#include <drm/drm_bridge.h>
> +
>  #include "dss.h"
>  #include "omapdss.h"
>  
> @@ -41,12 +43,10 @@ struct dpi_data {
>  	int data_lines;
>  
>  	struct omap_dss_device output;
> +	struct drm_bridge bridge;
>  };
>  
> -static struct dpi_data *dpi_get_data_from_dssdev(struct omap_dss_device *dssdev)
> -{
> -	return container_of(dssdev, struct dpi_data, output);
> -}
> +#define drm_bridge_to_dpi(bridge) container_of(bridge, struct dpi_data, bridge)
>  
>  /* -----------------------------------------------------------------------------
>   * Clock Handling and PLL
> @@ -354,6 +354,32 @@ static void dpi_config_lcd_manager(struct dpi_data *dpi)
>  	dss_mgr_set_lcd_config(&dpi->output, &dpi->mgr_config);
>  }
>  
> +static int dpi_clock_update(struct dpi_data *dpi, unsigned long *clock)
> +{
> +	int lck_div, pck_div;
> +	unsigned long fck;
> +	struct dpi_clk_calc_ctx ctx;
> +
> +	if (dpi->pll) {
> +		if (!dpi_pll_clk_calc(dpi, *clock, &ctx))
> +			return -EINVAL;
> +
> +		fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
> +	} else {
> +		if (!dpi_dss_clk_calc(dpi, *clock, &ctx))
> +			return -EINVAL;
> +
> +		fck = ctx.fck;
> +	}
> +
> +	lck_div = ctx.dispc_cinfo.lck_div;
> +	pck_div = ctx.dispc_cinfo.pck_div;
> +
> +	*clock = fck / lck_div / pck_div;
> +
> +	return 0;
> +}
> +
>  static int dpi_verify_pll(struct dss_pll *pll)
>  {
>  	int r;
> @@ -391,29 +417,76 @@ static void dpi_init_pll(struct dpi_data *dpi)
>  }
>  
>  /* -----------------------------------------------------------------------------
> - * omap_dss_device Operations
> + * DRM Bridge Operations
>   */
>  
> -static int dpi_connect(struct omap_dss_device *src,
> -		       struct omap_dss_device *dst)
> +static int dpi_bridge_attach(struct drm_bridge *bridge,
> +			     enum drm_bridge_attach_flags flags)
>  {
> -	struct dpi_data *dpi = dpi_get_data_from_dssdev(dst);
> +	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
> +
> +	if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
> +		return -EINVAL;
>  
>  	dpi_init_pll(dpi);
>  
> -	return omapdss_device_connect(dst->dss, dst, dst->next);
> +	return drm_bridge_attach(bridge->encoder, dpi->output.next_bridge,
> +				 bridge, flags);
>  }
>  
> -static void dpi_disconnect(struct omap_dss_device *src,
> -			   struct omap_dss_device *dst)
> +static enum drm_mode_status
> +dpi_bridge_mode_valid(struct drm_bridge *bridge,
> +		       const struct drm_display_mode *mode)
>  {
> -	omapdss_device_disconnect(dst, dst->next);
> +	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
> +	unsigned long clock = mode->clock * 1000;
> +	int ret;
> +
> +	if (mode->hdisplay % 8 != 0)
> +		return MODE_BAD_WIDTH;
> +
> +	if (mode->clock == 0)
> +		return MODE_NOCLOCK;
> +
> +	ret = dpi_clock_update(dpi, &clock);
> +	if (ret < 0)
> +		return MODE_CLOCK_RANGE;
> +
> +	return MODE_OK;
> +}
> +
> +static bool dpi_bridge_mode_fixup(struct drm_bridge *bridge,
> +				   const struct drm_display_mode *mode,
> +				   struct drm_display_mode *adjusted_mode)
> +{
> +	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
> +	unsigned long clock = mode->clock * 1000;
> +	int ret;
> +
> +	ret = dpi_clock_update(dpi, &clock);
> +	if (ret < 0)
> +		return false;
> +
> +	adjusted_mode->clock = clock / 1000;
> +
> +	return true;
> +}
> +
> +static void dpi_bridge_mode_set(struct drm_bridge *bridge,
> +				 const struct drm_display_mode *mode,
> +				 const struct drm_display_mode *adjusted_mode)
> +{
> +	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
> +
> +	mutex_lock(&dpi->lock);
> +	dpi->pixelclock = adjusted_mode->clock * 1000;
> +	mutex_unlock(&dpi->lock);
>  }
>  
> -static void dpi_display_enable(struct omap_dss_device *dssdev)
> +static void dpi_bridge_enable(struct drm_bridge *bridge,
> +			       struct drm_atomic_state *state)
>  {
> -	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
> -	struct omap_dss_device *out = &dpi->output;
> +	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
>  	int r;
>  
>  	mutex_lock(&dpi->lock);
> @@ -428,7 +501,7 @@ static void dpi_display_enable(struct omap_dss_device *dssdev)
>  	if (r)
>  		goto err_get_dispc;
>  
> -	r = dss_dpi_select_source(dpi->dss, dpi->id, out->dispc_channel);
> +	r = dss_dpi_select_source(dpi->dss, dpi->id, dpi->output.dispc_channel);
>  	if (r)
>  		goto err_src_sel;
>  
> @@ -468,9 +541,10 @@ static void dpi_display_enable(struct omap_dss_device *dssdev)
>  	mutex_unlock(&dpi->lock);
>  }
>  
> -static void dpi_display_disable(struct omap_dss_device *dssdev)
> +static void dpi_bridge_disable(struct drm_bridge *bridge,
> +				struct drm_atomic_state *state)
>  {
> -	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
> +	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
>  
>  	mutex_lock(&dpi->lock);
>  
> @@ -490,71 +564,33 @@ static void dpi_display_disable(struct omap_dss_device *dssdev)
>  	mutex_unlock(&dpi->lock);
>  }
>  
> -static int dpi_check_timings(struct omap_dss_device *dssdev,
> -			     struct drm_display_mode *mode)
> -{
> -	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
> -	int lck_div, pck_div;
> -	unsigned long fck;
> -	unsigned long pck;
> -	struct dpi_clk_calc_ctx ctx;
> -	bool ok;
> -
> -	if (mode->hdisplay % 8 != 0)
> -		return -EINVAL;
> -
> -	if (mode->clock == 0)
> -		return -EINVAL;
> -
> -	if (dpi->pll) {
> -		ok = dpi_pll_clk_calc(dpi, mode->clock * 1000, &ctx);
> -		if (!ok)
> -			return -EINVAL;
> -
> -		fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
> -	} else {
> -		ok = dpi_dss_clk_calc(dpi, mode->clock * 1000, &ctx);
> -		if (!ok)
> -			return -EINVAL;
> -
> -		fck = ctx.fck;
> -	}
> -
> -	lck_div = ctx.dispc_cinfo.lck_div;
> -	pck_div = ctx.dispc_cinfo.pck_div;
> -
> -	pck = fck / lck_div / pck_div;
> -
> -	mode->clock = pck / 1000;
> -
> -	return 0;
> -}
> -
> -static void dpi_set_timings(struct omap_dss_device *dssdev,
> -			    const struct drm_display_mode *mode)
> -{
> -	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
> -
> -	DSSDBG("dpi_set_timings\n");
> -
> -	mutex_lock(&dpi->lock);
> -
> -	dpi->pixelclock = mode->clock * 1000;
> -
> -	mutex_unlock(&dpi->lock);
> -}
> -
> -static const struct omap_dss_device_ops dpi_ops = {
> -	.connect = dpi_connect,
> -	.disconnect = dpi_disconnect,
> -
> -	.enable = dpi_display_enable,
> -	.disable = dpi_display_disable,
> -
> -	.check_timings = dpi_check_timings,
> -	.set_timings = dpi_set_timings,
> +static const struct drm_bridge_funcs dpi_bridge_funcs = {
> +	.attach = dpi_bridge_attach,
> +	.mode_valid = dpi_bridge_mode_valid,
> +	.mode_fixup = dpi_bridge_mode_fixup,
> +	.mode_set = dpi_bridge_mode_set,
> +	.atomic_enable = dpi_bridge_enable,
> +	.atomic_disable = dpi_bridge_disable,
>  };
>  
> +static void dpi_bridge_init(struct dpi_data *dpi)
> +{
> +	dpi->bridge.funcs = &dpi_bridge_funcs;
> +	dpi->bridge.of_node = dpi->pdev->dev.of_node;
> +	dpi->bridge.type = DRM_MODE_CONNECTOR_DPI;
> +
> +	drm_bridge_add(&dpi->bridge);
> +}
> +
> +static void dpi_bridge_cleanup(struct dpi_data *dpi)
> +{
> +	drm_bridge_remove(&dpi->bridge);
> +}
> +
> +/* -----------------------------------------------------------------------------
> + * Initialisation and Cleanup
> + */
> +
>  /*
>   * Return a hardcoded channel for the DPI output. This should work for
>   * current use cases, but this can be later expanded to either resolve
> @@ -597,6 +633,8 @@ static int dpi_init_output_port(struct dpi_data *dpi, struct device_node *port)
>  	u32 port_num = 0;
>  	int r;
>  
> +	dpi_bridge_init(dpi);
> +
>  	of_property_read_u32(port, "reg", &port_num);
>  	dpi->id = port_num <= 2 ? port_num : 0;
>  
> @@ -618,10 +656,9 @@ static int dpi_init_output_port(struct dpi_data *dpi, struct device_node *port)
>  	out->type = OMAP_DISPLAY_TYPE_DPI;
>  	out->dispc_channel = dpi_get_channel(dpi);
>  	out->of_port = port_num;
> -	out->ops = &dpi_ops;
>  	out->owner = THIS_MODULE;
>  
> -	r = omapdss_device_init_output(out, NULL);
> +	r = omapdss_device_init_output(out, &dpi->bridge);
>  	if (r < 0)
>  		return r;
>  
> @@ -637,6 +674,8 @@ static void dpi_uninit_output_port(struct device_node *port)
>  
>  	omapdss_device_unregister(out);
>  	omapdss_device_cleanup_output(out);
> +
> +	dpi_bridge_cleanup(dpi);
>  }
>  
>  /* -----------------------------------------------------------------------------
> 

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

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

* Re: [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel
  2019-08-27  7:34     ` Tomi Valkeinen
@ 2019-08-27  9:29       ` Laurent Pinchart
  2019-08-27  9:32         ` Tomi Valkeinen
  0 siblings, 1 reply; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-27  9:29 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: Maxime Ripard, Sean Paul, Sebastian Reichel, dri-devel

Hi Tomi,

On Tue, Aug 27, 2019 at 10:34:59AM +0300, Tomi Valkeinen wrote:
> On 26/08/2019 16:51, Laurent Pinchart wrote:
> > On Mon, Aug 26, 2019 at 03:15:23PM +0300, Tomi Valkeinen wrote:
> >> On 20/08/2019 04:16, Laurent Pinchart wrote:
> >>
> >>> The patches can be found at
> >>>
> >>> 	git://linuxtv.org/pinchartl/media.git omapdrm/bridge/devel
> >>
> >> I took your branch, booted AM5 EVM (I see you had the hack dts patch in your branch), and:
> >>
> >> insmod nfs/work/linux/drivers/media/cec/cec.ko
> >> insmod nfs/work/linux/drivers/video/fbdev/core/cfbcopyarea.ko
> >> insmod nfs/work/linux/drivers/video/fbdev/core/cfbimgblt.ko
> >> insmod nfs/work/linux/drivers/video/fbdev/core/cfbfillrect.ko
> >> insmod nfs/work/linux/drivers/gpu/drm/drm_panel_orientation_quirks.ko
> >> insmod nfs/work/linux/drivers/gpu/drm/drm.ko
> >> insmod nfs/work/linux/drivers/gpu/drm/drm_kms_helper.ko
> >> insmod nfs/work/linux/drivers/gpu/drm/bridge/ti-tfp410.ko
> >> insmod nfs/work/linux/drivers/gpu/drm/bridge/sii902x.ko
> >> insmod nfs/work/linux/drivers/gpu/drm/bridge/tc358767.ko
> >> insmod nfs/work/linux/drivers/gpu/drm/panel/panel-simple.ko
> >> [   25.487002] panel-simple display: display supply power not found, using dummy regulator
> >> [   25.495241] ------------[ cut here ]------------
> >> [   25.499900] WARNING: CPU: 0 PID: 303 at drivers/gpu/drm/panel/panel-simple.c:378 panel_simple_probe+0x34c/0x3b4 [panel_simple]
> > 
> > How am I expected to sneak patches in if you test them ? :-)
> > 
> > This has been introduced by a recent rebase, and I've only tested the
> > series on the pandaboard since then. It looks like the problem comes
> > from
> > 
> > commit b8a2948fa2b3a5a6da67fd57aa01c7318d795125
> > Author: Sean Paul <seanpaul@chromium.org>
> > Date:   Thu Jul 11 13:34:53 2019 -0700
> > 
> >      drm/panel: simple: Add ability to override typical timing
> > 
> > which breaks our out-of-tree DT. As a short term fix I can simply drop
> > the panel timings from DT, but I think this issue can affect more
> 
> So just removing the timings from the panel's node should be enough? 
> Still crashing for me, although the panel warning goes away.

My bad, you also need the following patch that I will include in v3.

From 9bbec803e9abbc650ca4884004b914f50e87cda0 Mon Sep 17 00:00:00 2001
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date: Tue, 27 Aug 2019 12:18:24 +0300
Subject: [PATCH] drm/panel: panel-simple: Set OSD070T1718 panel type

The OSD070T1718 is a DPI panel, set its type accordingly.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/panel/panel-simple.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 4b92b27eba86..5d487686d25c 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -2398,6 +2398,7 @@ static const struct panel_desc osddisplays_osd070t1718_19ts = {
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
 	.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
+	.connector_type = DRM_MODE_CONNECTOR_DPI,
 };

 static const struct drm_display_mode pda_91_00156_a0_mode = {

-- 
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] 106+ messages in thread

* Re: [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel
  2019-08-27  9:29       ` Laurent Pinchart
@ 2019-08-27  9:32         ` Tomi Valkeinen
  2019-08-27  9:40           ` Laurent Pinchart
  0 siblings, 1 reply; 106+ messages in thread
From: Tomi Valkeinen @ 2019-08-27  9:32 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Maxime Ripard, Sean Paul, Sebastian Reichel, dri-devel

On 27/08/2019 12:29, Laurent Pinchart wrote:
> Hi Tomi,
> 
> On Tue, Aug 27, 2019 at 10:34:59AM +0300, Tomi Valkeinen wrote:
>> On 26/08/2019 16:51, Laurent Pinchart wrote:
>>> On Mon, Aug 26, 2019 at 03:15:23PM +0300, Tomi Valkeinen wrote:
>>>> On 20/08/2019 04:16, Laurent Pinchart wrote:
>>>>
>>>>> The patches can be found at
>>>>>
>>>>> 	git://linuxtv.org/pinchartl/media.git omapdrm/bridge/devel
>>>>
>>>> I took your branch, booted AM5 EVM (I see you had the hack dts patch in your branch), and:
>>>>
>>>> insmod nfs/work/linux/drivers/media/cec/cec.ko
>>>> insmod nfs/work/linux/drivers/video/fbdev/core/cfbcopyarea.ko
>>>> insmod nfs/work/linux/drivers/video/fbdev/core/cfbimgblt.ko
>>>> insmod nfs/work/linux/drivers/video/fbdev/core/cfbfillrect.ko
>>>> insmod nfs/work/linux/drivers/gpu/drm/drm_panel_orientation_quirks.ko
>>>> insmod nfs/work/linux/drivers/gpu/drm/drm.ko
>>>> insmod nfs/work/linux/drivers/gpu/drm/drm_kms_helper.ko
>>>> insmod nfs/work/linux/drivers/gpu/drm/bridge/ti-tfp410.ko
>>>> insmod nfs/work/linux/drivers/gpu/drm/bridge/sii902x.ko
>>>> insmod nfs/work/linux/drivers/gpu/drm/bridge/tc358767.ko
>>>> insmod nfs/work/linux/drivers/gpu/drm/panel/panel-simple.ko
>>>> [   25.487002] panel-simple display: display supply power not found, using dummy regulator
>>>> [   25.495241] ------------[ cut here ]------------
>>>> [   25.499900] WARNING: CPU: 0 PID: 303 at drivers/gpu/drm/panel/panel-simple.c:378 panel_simple_probe+0x34c/0x3b4 [panel_simple]
>>>
>>> How am I expected to sneak patches in if you test them ? :-)
>>>
>>> This has been introduced by a recent rebase, and I've only tested the
>>> series on the pandaboard since then. It looks like the problem comes
>>> from
>>>
>>> commit b8a2948fa2b3a5a6da67fd57aa01c7318d795125
>>> Author: Sean Paul <seanpaul@chromium.org>
>>> Date:   Thu Jul 11 13:34:53 2019 -0700
>>>
>>>       drm/panel: simple: Add ability to override typical timing
>>>
>>> which breaks our out-of-tree DT. As a short term fix I can simply drop
>>> the panel timings from DT, but I think this issue can affect more
>>
>> So just removing the timings from the panel's node should be enough?
>> Still crashing for me, although the panel warning goes away.
> 
> My bad, you also need the following patch that I will include in v3.

Thanks, but I guess I need something more:

drivers/gpu/drm/panel/panel-simple.c:2384:3: error: ‘const struct 
panel_desc’ has no member named ‘connector_type’
   .connector_type = DRM_MODE_CONNECTOR_DPI,

  Tomi

-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel
  2019-08-27  9:32         ` Tomi Valkeinen
@ 2019-08-27  9:40           ` Laurent Pinchart
  0 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-27  9:40 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: Maxime Ripard, Sean Paul, Sebastian Reichel, dri-devel

Hi Tomi,

On Tue, Aug 27, 2019 at 12:32:46PM +0300, Tomi Valkeinen wrote:
> On 27/08/2019 12:29, Laurent Pinchart wrote:
> > On Tue, Aug 27, 2019 at 10:34:59AM +0300, Tomi Valkeinen wrote:
> >> On 26/08/2019 16:51, Laurent Pinchart wrote:
> >>> On Mon, Aug 26, 2019 at 03:15:23PM +0300, Tomi Valkeinen wrote:
> >>>> On 20/08/2019 04:16, Laurent Pinchart wrote:
> >>>>
> >>>>> The patches can be found at
> >>>>>
> >>>>> 	git://linuxtv.org/pinchartl/media.git omapdrm/bridge/devel
> >>>>
> >>>> I took your branch, booted AM5 EVM (I see you had the hack dts patch in your branch), and:
> >>>>
> >>>> insmod nfs/work/linux/drivers/media/cec/cec.ko
> >>>> insmod nfs/work/linux/drivers/video/fbdev/core/cfbcopyarea.ko
> >>>> insmod nfs/work/linux/drivers/video/fbdev/core/cfbimgblt.ko
> >>>> insmod nfs/work/linux/drivers/video/fbdev/core/cfbfillrect.ko
> >>>> insmod nfs/work/linux/drivers/gpu/drm/drm_panel_orientation_quirks.ko
> >>>> insmod nfs/work/linux/drivers/gpu/drm/drm.ko
> >>>> insmod nfs/work/linux/drivers/gpu/drm/drm_kms_helper.ko
> >>>> insmod nfs/work/linux/drivers/gpu/drm/bridge/ti-tfp410.ko
> >>>> insmod nfs/work/linux/drivers/gpu/drm/bridge/sii902x.ko
> >>>> insmod nfs/work/linux/drivers/gpu/drm/bridge/tc358767.ko
> >>>> insmod nfs/work/linux/drivers/gpu/drm/panel/panel-simple.ko
> >>>> [   25.487002] panel-simple display: display supply power not found, using dummy regulator
> >>>> [   25.495241] ------------[ cut here ]------------
> >>>> [   25.499900] WARNING: CPU: 0 PID: 303 at drivers/gpu/drm/panel/panel-simple.c:378 panel_simple_probe+0x34c/0x3b4 [panel_simple]
> >>>
> >>> How am I expected to sneak patches in if you test them ? :-)
> >>>
> >>> This has been introduced by a recent rebase, and I've only tested the
> >>> series on the pandaboard since then. It looks like the problem comes
> >>> from
> >>>
> >>> commit b8a2948fa2b3a5a6da67fd57aa01c7318d795125
> >>> Author: Sean Paul <seanpaul@chromium.org>
> >>> Date:   Thu Jul 11 13:34:53 2019 -0700
> >>>
> >>>       drm/panel: simple: Add ability to override typical timing
> >>>
> >>> which breaks our out-of-tree DT. As a short term fix I can simply drop
> >>> the panel timings from DT, but I think this issue can affect more
> >>
> >> So just removing the timings from the panel's node should be enough?
> >> Still crashing for me, although the panel warning goes away.
> > 
> > My bad, you also need the following patch that I will include in v3.
> 
> Thanks, but I guess I need something more:
> 
> drivers/gpu/drm/panel/panel-simple.c:2384:3: error: ‘const struct 
> panel_desc’ has no member named ‘connector_type’
>    .connector_type = DRM_MODE_CONNECTOR_DPI,

Yes, you also need to apply this on top of v3 which I haven't posted yet
:-) You can just fetch my omapdrm/bridge/devel branch, I've pushed the
latest version there.

-- 
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] 106+ messages in thread

* Re: [PATCH v2 44/50] drm/omap: dpi: Register a drm_bridge
  2019-08-27  9:07   ` Hans Verkuil
@ 2019-08-27  9:51     ` Laurent Pinchart
  2019-08-27 10:48       ` Laurent Pinchart
  0 siblings, 1 reply; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-27  9:51 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

Hi Hans,

On Tue, Aug 27, 2019 at 11:07:56AM +0200, Hans Verkuil wrote:
> Hi Laurent,
> 
> I tried this series with my Pandaboard, but it broke my Pandaboard. After
> doing a git bisect it ended up with this patch as the culprit.
> 
> If I boot my Pandaboard I get this:
> 
> [    3.271881] omapdss_dss 58000000.dss: 58000000.dss supply vdda_video not found, using dummy regulator
> [    3.285369] omapdss_dss 58000000.dss: 58000000.dss supply vdda_video not found, using dummy regulator
> [   24.286773] rcu: INFO: rcu_sched self-detected stall on CPU
> [   24.292388] rcu:     0-...!: (1306 ticks this GP) idle=6b6/1/0x40000002 softirq=85/85 fqs=19
> [   24.300689]  (t=2100 jiffies g=-1063 q=10)
> [   24.304809] rcu: rcu_sched kthread starved for 2058 jiffies! g-1063 f0x0 RCU_GP_WAIT_FQS(5) ->state=0x402 ->cpu=1
> [   24.315124] rcu: RCU grace-period kthread stack dump:
> [   24.315124] rcu_sched       I    0    10      2 0x00000000
> [   24.325805] [<c09b7130>] (__schedule) from [<c09b73a8>] (schedule+0x40/0xc0)
> [   24.332885] [<c09b73a8>] (schedule) from [<c09ba9d0>] (schedule_timeout+0x174/0x2a8)
> [   24.340698] [<c09ba9d0>] (schedule_timeout) from [<c01943a4>] (rcu_gp_kthread+0x49c/0x9f4)
> [   24.349121] [<c01943a4>] (rcu_gp_kthread) from [<c01559f8>] (kthread+0x13c/0x148)
> [   24.356658] [<c01559f8>] (kthread) from [<c01010e8>] (ret_from_fork+0x14/0x2c)
> [   24.363922] Exception stack(0xe70a1fb0 to 0xe70a1ff8)
> [   24.363922] 1fa0:                                     00000000 00000000 00000000 00000000
> [   24.363922] 1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> [   24.385437] 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000
> [   24.392089] NMI backtrace for cpu 0
> [   24.392120] CPU: 0 PID: 105 Comm: kworker/0:2 Not tainted 5.3.0-rc3-arm #152
> [   24.392120] Hardware name: Generic OMAP4 (Flattened Device Tree)
> [   24.408721] Workqueue: events deferred_probe_work_func
> [   24.408721] [<c010fd70>] (unwind_backtrace) from [<c010b7e8>] (show_stack+0x10/0x14)
> [   24.421783] [<c010b7e8>] (show_stack) from [<c09a054c>] (dump_stack+0x84/0x9c)
> [   24.429077] [<c09a054c>] (dump_stack) from [<c09a6ecc>] (nmi_cpu_backtrace+0x8c/0xc0)
> [   24.436950] [<c09a6ecc>] (nmi_cpu_backtrace) from [<c09a7014>] (nmi_trigger_cpumask_backtrace+0x114/0x12c)
> [   24.446655] [<c09a7014>] (nmi_trigger_cpumask_backtrace) from [<c01961e0>] (rcu_dump_cpu_stacks+0xa4/0xcc)
> [   24.456359] [<c01961e0>] (rcu_dump_cpu_stacks) from [<c01952bc>] (rcu_sched_clock_irq+0x608/0x7f8)
> [   24.465362] [<c01952bc>] (rcu_sched_clock_irq) from [<c019b21c>] (update_process_times+0x34/0x6c)
> [   24.465362] [<c019b21c>] (update_process_times) from [<c01acfcc>] (tick_sched_timer+0x4c/0xa8)
> [   24.483001] [<c01acfcc>] (tick_sched_timer) from [<c019c470>] (__hrtimer_run_queues+0x154/0x1fc)
> [   24.491851] [<c019c470>] (__hrtimer_run_queues) from [<c019c84c>] (hrtimer_interrupt+0x11c/0x2ac)
> [   24.500762] [<c019c84c>] (hrtimer_interrupt) from [<c010f3ac>] (twd_handler+0x30/0x38)
> [   24.500762] [<c010f3ac>] (twd_handler) from [<c018959c>] (handle_percpu_devid_irq+0x78/0x138)
> [   24.517333] [<c018959c>] (handle_percpu_devid_irq) from [<c0183a60>] (generic_handle_irq+0x24/0x34)
> [   24.526458] [<c0183a60>] (generic_handle_irq) from [<c0184028>] (__handle_domain_irq+0x5c/0xb4)
> [   24.526458] [<c0184028>] (__handle_domain_irq) from [<c03bbf2c>] (gic_handle_irq+0x58/0x9c)
> [   24.526458] [<c03bbf2c>] (gic_handle_irq) from [<c0101a8c>] (__irq_svc+0x6c/0x90)
> [   24.526458] Exception stack(0xe6439d68 to 0xe6439db0)
> [   24.551177] 9d60:                   c0f783e8 00000000 00000000 efdb49d0 e647f2e8 efdb7f74
> [   24.551177] 9d80: e647f2e8 00000000 e647f294 e647f2e8 00000000 efdb5a98 00000000 e6439db8
> [   24.551177] 9da0: c04e9830 c04e9858 20000153 ffffffff
> [   24.577789] [<c0101a8c>] (__irq_svc) from [<c04e9858>] (of_drm_find_bridge+0x40/0x84)
> [   24.577789] [<c04e9858>] (of_drm_find_bridge) from [<c0526608>] (omapdss_device_init_output+0x38/0x140)
> [   24.595153] [<c0526608>] (omapdss_device_init_output) from [<c0530294>] (dpi_init_port+0x208/0x294)
> [   24.604248] [<c0530294>] (dpi_init_port) from [<c05278c4>] (dss_probe+0x2b4/0x550)
> [   24.604248] [<c05278c4>] (dss_probe) from [<c0576c1c>] (platform_drv_probe+0x48/0x98)
> [   24.604248] [<c0576c1c>] (platform_drv_probe) from [<c0574eb0>] (really_probe+0xf0/0x2c4)
> [   24.627990] [<c0574eb0>] (really_probe) from [<c057520c>] (driver_probe_device+0x60/0x168)
> [   24.627990] [<c057520c>] (driver_probe_device) from [<c0573410>] (bus_for_each_drv+0x84/0xc8)
> [   24.644866] [<c0573410>] (bus_for_each_drv) from [<c0574d4c>] (__device_attach+0xd4/0x140)
> [   24.644866] [<c0574d4c>] (__device_attach) from [<c05740f8>] (bus_probe_device+0x84/0x8c)
> [   24.661376] [<c05740f8>] (bus_probe_device) from [<c057456c>] (deferred_probe_work_func+0x64/0x90)
> [   24.670379] [<c057456c>] (deferred_probe_work_func) from [<c014f960>] (process_one_work+0x204/0x41c)
> [   24.670410] [<c014f960>] (process_one_work) from [<c01510d4>] (worker_thread+0x2a8/0x5bc)
> [   24.687805] [<c01510d4>] (worker_thread) from [<c01559f8>] (kthread+0x13c/0x148)
> [   24.687805] [<c01559f8>] (kthread) from [<c01010e8>] (ret_from_fork+0x14/0x2c)
> [   24.702484] Exception stack(0xe6439fb0 to 0xe6439ff8)
> [   24.702484] 9fa0:                                     00000000 00000000 00000000 00000000
> [   24.702484] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> [   24.723999] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000
> 
> I can send my .config upon request if needed.
> 
> CONFIG_OMAP2_DSS_DPI is 'y', but there is nothing connected to the DPI port.

I've retested this on my pandaboard and couldn't reproduce the issue. As
I suspected a problem related to the kernel configuration, I tried
building the drivers in the kernel image instead of using modules, and I
then got a similar looking crash. I'm investigating it now.

> On 8/20/19 3:17 AM, Laurent Pinchart wrote:
> > In order to integrate with a chain of drm_bridge, the internal DPI
> > output has to expose its operations through the drm_bridge API.
> > Register a bridge at initialisation time to do so and remove the
> > omap_dss_device operations that are now unused.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> >  drivers/gpu/drm/omapdrm/dss/dpi.c | 205 ++++++++++++++++++------------
> >  1 file changed, 122 insertions(+), 83 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c
> > index c167bd1116ec..3874e6b6ec49 100644
> > --- a/drivers/gpu/drm/omapdrm/dss/dpi.c
> > +++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
> > @@ -21,6 +21,8 @@
> >  #include <linux/string.h>
> >  #include <linux/sys_soc.h>
> >  
> > +#include <drm/drm_bridge.h>
> > +
> >  #include "dss.h"
> >  #include "omapdss.h"
> >  
> > @@ -41,12 +43,10 @@ struct dpi_data {
> >  	int data_lines;
> >  
> >  	struct omap_dss_device output;
> > +	struct drm_bridge bridge;
> >  };
> >  
> > -static struct dpi_data *dpi_get_data_from_dssdev(struct omap_dss_device *dssdev)
> > -{
> > -	return container_of(dssdev, struct dpi_data, output);
> > -}
> > +#define drm_bridge_to_dpi(bridge) container_of(bridge, struct dpi_data, bridge)
> >  
> >  /* -----------------------------------------------------------------------------
> >   * Clock Handling and PLL
> > @@ -354,6 +354,32 @@ static void dpi_config_lcd_manager(struct dpi_data *dpi)
> >  	dss_mgr_set_lcd_config(&dpi->output, &dpi->mgr_config);
> >  }
> >  
> > +static int dpi_clock_update(struct dpi_data *dpi, unsigned long *clock)
> > +{
> > +	int lck_div, pck_div;
> > +	unsigned long fck;
> > +	struct dpi_clk_calc_ctx ctx;
> > +
> > +	if (dpi->pll) {
> > +		if (!dpi_pll_clk_calc(dpi, *clock, &ctx))
> > +			return -EINVAL;
> > +
> > +		fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
> > +	} else {
> > +		if (!dpi_dss_clk_calc(dpi, *clock, &ctx))
> > +			return -EINVAL;
> > +
> > +		fck = ctx.fck;
> > +	}
> > +
> > +	lck_div = ctx.dispc_cinfo.lck_div;
> > +	pck_div = ctx.dispc_cinfo.pck_div;
> > +
> > +	*clock = fck / lck_div / pck_div;
> > +
> > +	return 0;
> > +}
> > +
> >  static int dpi_verify_pll(struct dss_pll *pll)
> >  {
> >  	int r;
> > @@ -391,29 +417,76 @@ static void dpi_init_pll(struct dpi_data *dpi)
> >  }
> >  
> >  /* -----------------------------------------------------------------------------
> > - * omap_dss_device Operations
> > + * DRM Bridge Operations
> >   */
> >  
> > -static int dpi_connect(struct omap_dss_device *src,
> > -		       struct omap_dss_device *dst)
> > +static int dpi_bridge_attach(struct drm_bridge *bridge,
> > +			     enum drm_bridge_attach_flags flags)
> >  {
> > -	struct dpi_data *dpi = dpi_get_data_from_dssdev(dst);
> > +	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
> > +
> > +	if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
> > +		return -EINVAL;
> >  
> >  	dpi_init_pll(dpi);
> >  
> > -	return omapdss_device_connect(dst->dss, dst, dst->next);
> > +	return drm_bridge_attach(bridge->encoder, dpi->output.next_bridge,
> > +				 bridge, flags);
> >  }
> >  
> > -static void dpi_disconnect(struct omap_dss_device *src,
> > -			   struct omap_dss_device *dst)
> > +static enum drm_mode_status
> > +dpi_bridge_mode_valid(struct drm_bridge *bridge,
> > +		       const struct drm_display_mode *mode)
> >  {
> > -	omapdss_device_disconnect(dst, dst->next);
> > +	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
> > +	unsigned long clock = mode->clock * 1000;
> > +	int ret;
> > +
> > +	if (mode->hdisplay % 8 != 0)
> > +		return MODE_BAD_WIDTH;
> > +
> > +	if (mode->clock == 0)
> > +		return MODE_NOCLOCK;
> > +
> > +	ret = dpi_clock_update(dpi, &clock);
> > +	if (ret < 0)
> > +		return MODE_CLOCK_RANGE;
> > +
> > +	return MODE_OK;
> > +}
> > +
> > +static bool dpi_bridge_mode_fixup(struct drm_bridge *bridge,
> > +				   const struct drm_display_mode *mode,
> > +				   struct drm_display_mode *adjusted_mode)
> > +{
> > +	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
> > +	unsigned long clock = mode->clock * 1000;
> > +	int ret;
> > +
> > +	ret = dpi_clock_update(dpi, &clock);
> > +	if (ret < 0)
> > +		return false;
> > +
> > +	adjusted_mode->clock = clock / 1000;
> > +
> > +	return true;
> > +}
> > +
> > +static void dpi_bridge_mode_set(struct drm_bridge *bridge,
> > +				 const struct drm_display_mode *mode,
> > +				 const struct drm_display_mode *adjusted_mode)
> > +{
> > +	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
> > +
> > +	mutex_lock(&dpi->lock);
> > +	dpi->pixelclock = adjusted_mode->clock * 1000;
> > +	mutex_unlock(&dpi->lock);
> >  }
> >  
> > -static void dpi_display_enable(struct omap_dss_device *dssdev)
> > +static void dpi_bridge_enable(struct drm_bridge *bridge,
> > +			       struct drm_atomic_state *state)
> >  {
> > -	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
> > -	struct omap_dss_device *out = &dpi->output;
> > +	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
> >  	int r;
> >  
> >  	mutex_lock(&dpi->lock);
> > @@ -428,7 +501,7 @@ static void dpi_display_enable(struct omap_dss_device *dssdev)
> >  	if (r)
> >  		goto err_get_dispc;
> >  
> > -	r = dss_dpi_select_source(dpi->dss, dpi->id, out->dispc_channel);
> > +	r = dss_dpi_select_source(dpi->dss, dpi->id, dpi->output.dispc_channel);
> >  	if (r)
> >  		goto err_src_sel;
> >  
> > @@ -468,9 +541,10 @@ static void dpi_display_enable(struct omap_dss_device *dssdev)
> >  	mutex_unlock(&dpi->lock);
> >  }
> >  
> > -static void dpi_display_disable(struct omap_dss_device *dssdev)
> > +static void dpi_bridge_disable(struct drm_bridge *bridge,
> > +				struct drm_atomic_state *state)
> >  {
> > -	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
> > +	struct dpi_data *dpi = drm_bridge_to_dpi(bridge);
> >  
> >  	mutex_lock(&dpi->lock);
> >  
> > @@ -490,71 +564,33 @@ static void dpi_display_disable(struct omap_dss_device *dssdev)
> >  	mutex_unlock(&dpi->lock);
> >  }
> >  
> > -static int dpi_check_timings(struct omap_dss_device *dssdev,
> > -			     struct drm_display_mode *mode)
> > -{
> > -	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
> > -	int lck_div, pck_div;
> > -	unsigned long fck;
> > -	unsigned long pck;
> > -	struct dpi_clk_calc_ctx ctx;
> > -	bool ok;
> > -
> > -	if (mode->hdisplay % 8 != 0)
> > -		return -EINVAL;
> > -
> > -	if (mode->clock == 0)
> > -		return -EINVAL;
> > -
> > -	if (dpi->pll) {
> > -		ok = dpi_pll_clk_calc(dpi, mode->clock * 1000, &ctx);
> > -		if (!ok)
> > -			return -EINVAL;
> > -
> > -		fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
> > -	} else {
> > -		ok = dpi_dss_clk_calc(dpi, mode->clock * 1000, &ctx);
> > -		if (!ok)
> > -			return -EINVAL;
> > -
> > -		fck = ctx.fck;
> > -	}
> > -
> > -	lck_div = ctx.dispc_cinfo.lck_div;
> > -	pck_div = ctx.dispc_cinfo.pck_div;
> > -
> > -	pck = fck / lck_div / pck_div;
> > -
> > -	mode->clock = pck / 1000;
> > -
> > -	return 0;
> > -}
> > -
> > -static void dpi_set_timings(struct omap_dss_device *dssdev,
> > -			    const struct drm_display_mode *mode)
> > -{
> > -	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
> > -
> > -	DSSDBG("dpi_set_timings\n");
> > -
> > -	mutex_lock(&dpi->lock);
> > -
> > -	dpi->pixelclock = mode->clock * 1000;
> > -
> > -	mutex_unlock(&dpi->lock);
> > -}
> > -
> > -static const struct omap_dss_device_ops dpi_ops = {
> > -	.connect = dpi_connect,
> > -	.disconnect = dpi_disconnect,
> > -
> > -	.enable = dpi_display_enable,
> > -	.disable = dpi_display_disable,
> > -
> > -	.check_timings = dpi_check_timings,
> > -	.set_timings = dpi_set_timings,
> > +static const struct drm_bridge_funcs dpi_bridge_funcs = {
> > +	.attach = dpi_bridge_attach,
> > +	.mode_valid = dpi_bridge_mode_valid,
> > +	.mode_fixup = dpi_bridge_mode_fixup,
> > +	.mode_set = dpi_bridge_mode_set,
> > +	.atomic_enable = dpi_bridge_enable,
> > +	.atomic_disable = dpi_bridge_disable,
> >  };
> >  
> > +static void dpi_bridge_init(struct dpi_data *dpi)
> > +{
> > +	dpi->bridge.funcs = &dpi_bridge_funcs;
> > +	dpi->bridge.of_node = dpi->pdev->dev.of_node;
> > +	dpi->bridge.type = DRM_MODE_CONNECTOR_DPI;
> > +
> > +	drm_bridge_add(&dpi->bridge);
> > +}
> > +
> > +static void dpi_bridge_cleanup(struct dpi_data *dpi)
> > +{
> > +	drm_bridge_remove(&dpi->bridge);
> > +}
> > +
> > +/* -----------------------------------------------------------------------------
> > + * Initialisation and Cleanup
> > + */
> > +
> >  /*
> >   * Return a hardcoded channel for the DPI output. This should work for
> >   * current use cases, but this can be later expanded to either resolve
> > @@ -597,6 +633,8 @@ static int dpi_init_output_port(struct dpi_data *dpi, struct device_node *port)
> >  	u32 port_num = 0;
> >  	int r;
> >  
> > +	dpi_bridge_init(dpi);
> > +
> >  	of_property_read_u32(port, "reg", &port_num);
> >  	dpi->id = port_num <= 2 ? port_num : 0;
> >  
> > @@ -618,10 +656,9 @@ static int dpi_init_output_port(struct dpi_data *dpi, struct device_node *port)
> >  	out->type = OMAP_DISPLAY_TYPE_DPI;
> >  	out->dispc_channel = dpi_get_channel(dpi);
> >  	out->of_port = port_num;
> > -	out->ops = &dpi_ops;
> >  	out->owner = THIS_MODULE;
> >  
> > -	r = omapdss_device_init_output(out, NULL);
> > +	r = omapdss_device_init_output(out, &dpi->bridge);
> >  	if (r < 0)
> >  		return r;
> >  
> > @@ -637,6 +674,8 @@ static void dpi_uninit_output_port(struct device_node *port)
> >  
> >  	omapdss_device_unregister(out);
> >  	omapdss_device_cleanup_output(out);
> > +
> > +	dpi_bridge_cleanup(dpi);
> >  }
> >  
> >  /* -----------------------------------------------------------------------------
> > 
> 

-- 
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] 106+ messages in thread

* Re: [PATCH v2 44/50] drm/omap: dpi: Register a drm_bridge
  2019-08-27  9:51     ` Laurent Pinchart
@ 2019-08-27 10:48       ` Laurent Pinchart
  0 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-08-27 10:48 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: Maxime Ripard, Tomi Valkeinen, Sean Paul, Sebastian Reichel, dri-devel

Hi Hans,

On Tue, Aug 27, 2019 at 12:51:08PM +0300, Laurent Pinchart wrote:
> On Tue, Aug 27, 2019 at 11:07:56AM +0200, Hans Verkuil wrote:
> > Hi Laurent,
> > 
> > I tried this series with my Pandaboard, but it broke my Pandaboard. After
> > doing a git bisect it ended up with this patch as the culprit.
> > 
> > If I boot my Pandaboard I get this:
> > 
> > [    3.271881] omapdss_dss 58000000.dss: 58000000.dss supply vdda_video not found, using dummy regulator
> > [    3.285369] omapdss_dss 58000000.dss: 58000000.dss supply vdda_video not found, using dummy regulator
> > [   24.286773] rcu: INFO: rcu_sched self-detected stall on CPU
> > [   24.292388] rcu:     0-...!: (1306 ticks this GP) idle=6b6/1/0x40000002 softirq=85/85 fqs=19
> > [   24.300689]  (t=2100 jiffies g=-1063 q=10)
> > [   24.304809] rcu: rcu_sched kthread starved for 2058 jiffies! g-1063 f0x0 RCU_GP_WAIT_FQS(5) ->state=0x402 ->cpu=1
> > [   24.315124] rcu: RCU grace-period kthread stack dump:
> > [   24.315124] rcu_sched       I    0    10      2 0x00000000
> > [   24.325805] [<c09b7130>] (__schedule) from [<c09b73a8>] (schedule+0x40/0xc0)
> > [   24.332885] [<c09b73a8>] (schedule) from [<c09ba9d0>] (schedule_timeout+0x174/0x2a8)
> > [   24.340698] [<c09ba9d0>] (schedule_timeout) from [<c01943a4>] (rcu_gp_kthread+0x49c/0x9f4)
> > [   24.349121] [<c01943a4>] (rcu_gp_kthread) from [<c01559f8>] (kthread+0x13c/0x148)
> > [   24.356658] [<c01559f8>] (kthread) from [<c01010e8>] (ret_from_fork+0x14/0x2c)
> > [   24.363922] Exception stack(0xe70a1fb0 to 0xe70a1ff8)
> > [   24.363922] 1fa0:                                     00000000 00000000 00000000 00000000
> > [   24.363922] 1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> > [   24.385437] 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000
> > [   24.392089] NMI backtrace for cpu 0
> > [   24.392120] CPU: 0 PID: 105 Comm: kworker/0:2 Not tainted 5.3.0-rc3-arm #152
> > [   24.392120] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > [   24.408721] Workqueue: events deferred_probe_work_func
> > [   24.408721] [<c010fd70>] (unwind_backtrace) from [<c010b7e8>] (show_stack+0x10/0x14)
> > [   24.421783] [<c010b7e8>] (show_stack) from [<c09a054c>] (dump_stack+0x84/0x9c)
> > [   24.429077] [<c09a054c>] (dump_stack) from [<c09a6ecc>] (nmi_cpu_backtrace+0x8c/0xc0)
> > [   24.436950] [<c09a6ecc>] (nmi_cpu_backtrace) from [<c09a7014>] (nmi_trigger_cpumask_backtrace+0x114/0x12c)
> > [   24.446655] [<c09a7014>] (nmi_trigger_cpumask_backtrace) from [<c01961e0>] (rcu_dump_cpu_stacks+0xa4/0xcc)
> > [   24.456359] [<c01961e0>] (rcu_dump_cpu_stacks) from [<c01952bc>] (rcu_sched_clock_irq+0x608/0x7f8)
> > [   24.465362] [<c01952bc>] (rcu_sched_clock_irq) from [<c019b21c>] (update_process_times+0x34/0x6c)
> > [   24.465362] [<c019b21c>] (update_process_times) from [<c01acfcc>] (tick_sched_timer+0x4c/0xa8)
> > [   24.483001] [<c01acfcc>] (tick_sched_timer) from [<c019c470>] (__hrtimer_run_queues+0x154/0x1fc)
> > [   24.491851] [<c019c470>] (__hrtimer_run_queues) from [<c019c84c>] (hrtimer_interrupt+0x11c/0x2ac)
> > [   24.500762] [<c019c84c>] (hrtimer_interrupt) from [<c010f3ac>] (twd_handler+0x30/0x38)
> > [   24.500762] [<c010f3ac>] (twd_handler) from [<c018959c>] (handle_percpu_devid_irq+0x78/0x138)
> > [   24.517333] [<c018959c>] (handle_percpu_devid_irq) from [<c0183a60>] (generic_handle_irq+0x24/0x34)
> > [   24.526458] [<c0183a60>] (generic_handle_irq) from [<c0184028>] (__handle_domain_irq+0x5c/0xb4)
> > [   24.526458] [<c0184028>] (__handle_domain_irq) from [<c03bbf2c>] (gic_handle_irq+0x58/0x9c)
> > [   24.526458] [<c03bbf2c>] (gic_handle_irq) from [<c0101a8c>] (__irq_svc+0x6c/0x90)
> > [   24.526458] Exception stack(0xe6439d68 to 0xe6439db0)
> > [   24.551177] 9d60:                   c0f783e8 00000000 00000000 efdb49d0 e647f2e8 efdb7f74
> > [   24.551177] 9d80: e647f2e8 00000000 e647f294 e647f2e8 00000000 efdb5a98 00000000 e6439db8
> > [   24.551177] 9da0: c04e9830 c04e9858 20000153 ffffffff
> > [   24.577789] [<c0101a8c>] (__irq_svc) from [<c04e9858>] (of_drm_find_bridge+0x40/0x84)
> > [   24.577789] [<c04e9858>] (of_drm_find_bridge) from [<c0526608>] (omapdss_device_init_output+0x38/0x140)
> > [   24.595153] [<c0526608>] (omapdss_device_init_output) from [<c0530294>] (dpi_init_port+0x208/0x294)
> > [   24.604248] [<c0530294>] (dpi_init_port) from [<c05278c4>] (dss_probe+0x2b4/0x550)
> > [   24.604248] [<c05278c4>] (dss_probe) from [<c0576c1c>] (platform_drv_probe+0x48/0x98)
> > [   24.604248] [<c0576c1c>] (platform_drv_probe) from [<c0574eb0>] (really_probe+0xf0/0x2c4)
> > [   24.627990] [<c0574eb0>] (really_probe) from [<c057520c>] (driver_probe_device+0x60/0x168)
> > [   24.627990] [<c057520c>] (driver_probe_device) from [<c0573410>] (bus_for_each_drv+0x84/0xc8)
> > [   24.644866] [<c0573410>] (bus_for_each_drv) from [<c0574d4c>] (__device_attach+0xd4/0x140)
> > [   24.644866] [<c0574d4c>] (__device_attach) from [<c05740f8>] (bus_probe_device+0x84/0x8c)
> > [   24.661376] [<c05740f8>] (bus_probe_device) from [<c057456c>] (deferred_probe_work_func+0x64/0x90)
> > [   24.670379] [<c057456c>] (deferred_probe_work_func) from [<c014f960>] (process_one_work+0x204/0x41c)
> > [   24.670410] [<c014f960>] (process_one_work) from [<c01510d4>] (worker_thread+0x2a8/0x5bc)
> > [   24.687805] [<c01510d4>] (worker_thread) from [<c01559f8>] (kthread+0x13c/0x148)
> > [   24.687805] [<c01559f8>] (kthread) from [<c01010e8>] (ret_from_fork+0x14/0x2c)
> > [   24.702484] Exception stack(0xe6439fb0 to 0xe6439ff8)
> > [   24.702484] 9fa0:                                     00000000 00000000 00000000 00000000
> > [   24.702484] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> > [   24.723999] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000
> > 
> > I can send my .config upon request if needed.
> > 
> > CONFIG_OMAP2_DSS_DPI is 'y', but there is nothing connected to the DPI port.
> 
> I've retested this on my pandaboard and couldn't reproduce the issue. As
> I suspected a problem related to the kernel configuration, I tried
> building the drivers in the kernel image instead of using modules, and I
> then got a similar looking crash. I'm investigating it now.

Fix pushed to

	git://linuxtv.org/pinchartl/media.git omapdrm/bridge/devel

The issue was caused by incorrect cleanup on probe deferral, fixed by a
combination of "drm/omap: dss: Cleanup DSS ports on initialisation
failure" (new patch) and changes to "drm/omap: dpi: Register a
drm_bridge" and "drm/omap: spi: Register a drm_bridge".

-- 
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] 106+ messages in thread

* Re: [PATCH v2 05/50] drm/bridge: Extend bridge API to disable connector creation
  2019-08-20  1:16 ` [PATCH v2 05/50] drm/bridge: Extend bridge API to disable connector creation Laurent Pinchart
  2019-08-22 15:34   ` Boris Brezillon
@ 2019-10-01  7:04   ` Tomi Valkeinen
  2019-10-01 19:58     ` Laurent Pinchart
  1 sibling, 1 reply; 106+ messages in thread
From: Tomi Valkeinen @ 2019-10-01  7:04 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel; +Cc: Maxime Ripard, Sean Paul, Sebastian Reichel

On 20/08/2019 04:16, Laurent Pinchart wrote:

> @@ -1111,7 +1113,7 @@ int dw_mipi_dsi_bind(struct dw_mipi_dsi *dsi, struct drm_encoder *encoder)
>   {
>   	int ret;
>   
> -	ret = drm_bridge_attach(encoder, &dsi->bridge, NULL);
> +	ret = drm_bridge_attach(encoder, &dsi->bridge, NULL, true);

This doesn't look correct. Where does the "true" come from?

  Tomi

-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 05/50] drm/bridge: Extend bridge API to disable connector creation
  2019-10-01  7:04   ` Tomi Valkeinen
@ 2019-10-01 19:58     ` Laurent Pinchart
  0 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-10-01 19:58 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: Maxime Ripard, Sean Paul, Sebastian Reichel, dri-devel

Hi Tomi,

On Tue, Oct 01, 2019 at 10:04:11AM +0300, Tomi Valkeinen wrote:
> On 20/08/2019 04:16, Laurent Pinchart wrote:
> 
> > @@ -1111,7 +1113,7 @@ int dw_mipi_dsi_bind(struct dw_mipi_dsi *dsi, struct drm_encoder *encoder)
> >   {
> >   	int ret;
> >   
> > -	ret = drm_bridge_attach(encoder, &dsi->bridge, NULL);
> > +	ret = drm_bridge_attach(encoder, &dsi->bridge, NULL, true);
> 
> This doesn't look correct. Where does the "true" come from?

It should be 0. I think it comes from the previous version of this
patch, which I've rebased instead of regenerating it completely with
Coccinelle. I'll fix that.

-- 
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] 106+ messages in thread

* Re: [PATCH v2 13/50] drm/bridge: panel: Implement bridge connector operations
  2019-08-20 10:37   ` Sam Ravnborg
  2019-08-20 16:08     ` Laurent Pinchart
@ 2019-10-03  5:56     ` Tomi Valkeinen
  2019-10-09 19:24       ` Sam Ravnborg
  1 sibling, 1 reply; 106+ messages in thread
From: Tomi Valkeinen @ 2019-10-03  5:56 UTC (permalink / raw)
  To: Sam Ravnborg, Laurent Pinchart
  Cc: Maxime Ripard, Sean Paul, Sebastian Reichel, dri-devel

Hi Sam,

On 20/08/2019 13:37, Sam Ravnborg wrote:

>> @@ -123,6 +123,18 @@ static void panel_bridge_post_disable(struct drm_bridge *bridge)
>>   	drm_panel_unprepare(panel_bridge->panel);
>>   }
>>   
>> +static int panel_bridge_get_modes(struct drm_bridge *bridge,
>> +				  struct drm_connector *connector)
>> +{
>> +	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
>> +
>> +	/*
>> +	 * FIXME: drm_panel_get_modes() should take the connector as an
>> +	 * argument.
>> +	 */
> Noted, I have patches to fix this. Needs a little testing/polishing
> before I post them.

Do you have any testable patches for this?

I was testing this series with a Toshiba DPI-2-DSI bridge and a DSI 
panel, and was hitting a crash as simple-panel couldn't get the connector.

Laurent commented:

> panel_bridge_attach() should be modified to call drm_panel_attach() even
> when flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR, with the connctor parameter
> set to NULL. That's easy, and drm_panel_attach() won't complain and
> happily set panel->connector to NULL. The trouble is that the panel
> drivers rely on panel->connector in their get_modes() implementation.
> That function needs to be modified to take the connector pointer instead
> of retrieving it from panel->connector (which can then be removed).

  Tomi

-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 13/50] drm/bridge: panel: Implement bridge connector operations
  2019-10-03  5:56     ` Tomi Valkeinen
@ 2019-10-09 19:24       ` Sam Ravnborg
  2019-12-02 15:24         ` Laurent Pinchart
  0 siblings, 1 reply; 106+ messages in thread
From: Sam Ravnborg @ 2019-10-09 19:24 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Maxime Ripard, Sean Paul, Laurent Pinchart, dri-devel, Sebastian Reichel

Hi Tomi

On Thu, Oct 03, 2019 at 08:56:15AM +0300, Tomi Valkeinen wrote:
> Hi Sam,
> 
> On 20/08/2019 13:37, Sam Ravnborg wrote:
> 
> > > @@ -123,6 +123,18 @@ static void panel_bridge_post_disable(struct drm_bridge *bridge)
> > >   	drm_panel_unprepare(panel_bridge->panel);
> > >   }
> > > +static int panel_bridge_get_modes(struct drm_bridge *bridge,
> > > +				  struct drm_connector *connector)
> > > +{
> > > +	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
> > > +
> > > +	/*
> > > +	 * FIXME: drm_panel_get_modes() should take the connector as an
> > > +	 * argument.
> > > +	 */
> > Noted, I have patches to fix this. Needs a little testing/polishing
> > before I post them.
> 
> Do you have any testable patches for this?
> 
> I was testing this series with a Toshiba DPI-2-DSI bridge and a DSI panel,
> and was hitting a crash as simple-panel couldn't get the connector.


If time permits I will refresh the patches this weekend and send them
out.
But right now cannot promise much as I am awful behind.

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

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

* Re: [PATCH v2 13/50] drm/bridge: panel: Implement bridge connector operations
  2019-10-09 19:24       ` Sam Ravnborg
@ 2019-12-02 15:24         ` Laurent Pinchart
  0 siblings, 0 replies; 106+ messages in thread
From: Laurent Pinchart @ 2019-12-02 15:24 UTC (permalink / raw)
  To: Sam Ravnborg; +Cc: Tomi Valkeinen, Sean Paul, dri-devel, Sebastian Reichel

Hi Sam,

On Wed, Oct 09, 2019 at 09:24:47PM +0200, Sam Ravnborg wrote:
> On Thu, Oct 03, 2019 at 08:56:15AM +0300, Tomi Valkeinen wrote:
> > On 20/08/2019 13:37, Sam Ravnborg wrote:
> > 
> > > > @@ -123,6 +123,18 @@ static void panel_bridge_post_disable(struct drm_bridge *bridge)
> > > >   	drm_panel_unprepare(panel_bridge->panel);
> > > >   }
> > > > +static int panel_bridge_get_modes(struct drm_bridge *bridge,
> > > > +				  struct drm_connector *connector)
> > > > +{
> > > > +	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
> > > > +
> > > > +	/*
> > > > +	 * FIXME: drm_panel_get_modes() should take the connector as an
> > > > +	 * argument.
> > > > +	 */
> > > Noted, I have patches to fix this. Needs a little testing/polishing
> > > before I post them.
> > 
> > Do you have any testable patches for this?
> > 
> > I was testing this series with a Toshiba DPI-2-DSI bridge and a DSI panel,
> > and was hitting a crash as simple-panel couldn't get the connector.
> 
> If time permits I will refresh the patches this weekend and send them
> out.
> But right now cannot promise much as I am awful behind.

No worries at all. Is there any way I can help you, maybe continuing
in-progress work ?

-- 
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] 106+ messages in thread

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

Thread overview: 106+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-20  1:16 [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Laurent Pinchart
2019-08-20  1:16 ` [PATCH v2 01/50] video: hdmi: Change return type of hdmi_avi_infoframe_init() to void Laurent Pinchart
2019-08-20 11:18   ` Bartlomiej Zolnierkiewicz
2019-08-22  9:12   ` Boris Brezillon
2019-08-20  1:16 ` [PATCH v2 02/50] drm/connector: Add helper to get a connector type name Laurent Pinchart
2019-08-22  9:13   ` Boris Brezillon
2019-08-20  1:16 ` [PATCH v2 03/50] drm/edid: Add flag to drm_display_info to identify HDMI sinks Laurent Pinchart
2019-08-22  9:15   ` Boris Brezillon
2019-08-20  1:16 ` [PATCH v2 04/50] drm/bridge: Add connector-related bridge operations and data Laurent Pinchart
2019-08-22 15:24   ` Boris Brezillon
2019-08-22 16:41   ` Boris Brezillon
2019-08-23  0:34     ` Laurent Pinchart
2019-08-23  6:15       ` Boris Brezillon
2019-08-20  1:16 ` [PATCH v2 05/50] drm/bridge: Extend bridge API to disable connector creation Laurent Pinchart
2019-08-22 15:34   ` Boris Brezillon
2019-10-01  7:04   ` Tomi Valkeinen
2019-10-01 19:58     ` Laurent Pinchart
2019-08-20  1:16 ` [PATCH v2 06/50] drm/bridge: dumb-vga-dac: Rename internal symbols to simple-bridge Laurent Pinchart
2019-08-22 15:39   ` Boris Brezillon
2019-08-26 11:25   ` Maxime Ripard
2019-08-20  1:16 ` [PATCH v2 07/50] drm/bridge: dumb-vga-dac: Rename driver " Laurent Pinchart
2019-08-22 15:42   ` Boris Brezillon
2019-08-26 11:26   ` Maxime Ripard
2019-08-20  1:16 ` [PATCH v2 08/50] drm/bridge: simple-bridge: Add support for non-VGA bridges Laurent Pinchart
2019-08-22 15:43   ` Boris Brezillon
2019-08-26 11:27   ` Maxime Ripard
2019-08-20  1:16 ` [PATCH v2 09/50] drm/bridge: simple-bridge: Add support for enable GPIO Laurent Pinchart
2019-08-22 15:45   ` Boris Brezillon
2019-08-26 11:33   ` Maxime Ripard
2019-08-20  1:16 ` [PATCH v2 10/50] drm/bridge: simple-bridge: Add support for the TI OP362 Laurent Pinchart
2019-08-22 15:45   ` Boris Brezillon
2019-08-26 11:34   ` Maxime Ripard
2019-08-20  1:16 ` [PATCH v2 11/50] drm/bridge: Add bridge driver for display connectors Laurent Pinchart
2019-08-22 16:05   ` Boris Brezillon
2019-08-22 16:39     ` Laurent Pinchart
2019-08-26 11:36   ` Maxime Ripard
2019-08-20  1:16 ` [PATCH v2 12/50] drm/bridge: Add driver for the TI TPD12S015 HDMI level shifter Laurent Pinchart
2019-08-20  1:16 ` [PATCH v2 13/50] drm/bridge: panel: Implement bridge connector operations Laurent Pinchart
2019-08-20 10:37   ` Sam Ravnborg
2019-08-20 16:08     ` Laurent Pinchart
2019-10-03  5:56     ` Tomi Valkeinen
2019-10-09 19:24       ` Sam Ravnborg
2019-12-02 15:24         ` Laurent Pinchart
2019-08-22 16:29   ` Boris Brezillon
2019-08-22 16:35     ` Laurent Pinchart
2019-08-22 18:02       ` Boris Brezillon
2019-08-23  0:39         ` Laurent Pinchart
2019-08-20  1:16 ` [PATCH v2 14/50] drm/bridge: tfp410: Don't include drmP.h Laurent Pinchart
2019-08-22 16:11   ` Boris Brezillon
2019-08-20  1:16 ` [PATCH v2 15/50] drm/bridge: tfp410: Replace manual connector handling with bridge Laurent Pinchart
2019-08-22 16:36   ` Boris Brezillon
2019-08-22 16:54     ` Laurent Pinchart
2019-08-22 17:15       ` Boris Brezillon
2019-08-27  7:43   ` Tomi Valkeinen
2019-08-27  8:00     ` Laurent Pinchart
2019-08-20  1:16 ` [PATCH v2 16/50] drm/bridge: tfp410: Allow operation without drm_connector Laurent Pinchart
2019-08-22 18:17   ` Boris Brezillon
2019-08-20  1:16 ` [PATCH v2 17/50] drm: Add helper to create a connector for a chain of bridges Laurent Pinchart
2019-08-22 18:31   ` Boris Brezillon
2019-08-20  1:16 ` [PATCH v2 18/50] drm/omap: Simplify HDMI mode and infoframe configuration Laurent Pinchart
2019-08-20  1:16 ` [PATCH v2 19/50] drm/omap: Factor out display type to connector type conversion Laurent Pinchart
2019-08-20  1:16 ` [PATCH v2 20/50] drm/omap: Use the drm_panel_bridge API Laurent Pinchart
2019-08-20  1:16 ` [PATCH v2 21/50] drm/omap: dss: Fix output next device lookup in DT Laurent Pinchart
2019-08-20  1:16 ` [PATCH v2 22/50] drm/omap: Add infrastructure to support drm_bridge local to DSS outputs Laurent Pinchart
2019-08-20  1:16 ` [PATCH v2 23/50] drm/omap: dss: Make omap_dss_device_ops optional Laurent Pinchart
2019-08-20  1:16 ` [PATCH v2 24/50] drm/omap: hdmi: Allocate EDID in the .read_edid() operation Laurent Pinchart
2019-08-20  1:16 ` [PATCH v2 25/50] drm/omap: hdmi4: Rework EDID read to isolate data read Laurent Pinchart
2019-08-26 11:39   ` Tomi Valkeinen
2019-08-26 13:06     ` Laurent Pinchart
2019-08-20  1:16 ` [PATCH v2 26/50] drm/omap: hdmi5: " Laurent Pinchart
2019-08-20  1:16 ` [PATCH v2 27/50] drm/omap: hdmi4: Register a drm_bridge for EDID read Laurent Pinchart
2019-08-20  1:16 ` [PATCH v2 28/50] drm/omap: hdmi5: " Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 29/50] drm/omap: hdmi4: Move mode set, enable and disable operations to bridge Laurent Pinchart
2019-08-26 11:50   ` Tomi Valkeinen
2019-08-20  1:17 ` [PATCH v2 30/50] drm/omap: hdmi5: " Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 31/50] drm/omap: hdmi4: Implement drm_bridge .hpd_notify() operation Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 32/50] drm/omap: dss: Remove .set_hdmi_mode() and .set_infoframe() operations Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 33/50] drm/omap: venc: Register a drm_bridge Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 34/50] drm/omap: Create connector for bridges Laurent Pinchart
2019-08-22 17:00   ` Boris Brezillon
2019-08-22 23:41     ` Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 35/50] drm/omap: Switch the HDMI and VENC outputs to drm_bridge Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 36/50] drm/omap: Remove HPD, detect and EDID omapdss operations Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 37/50] drm/omap: hdmi: Remove omap_dss_device operations Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 38/50] drm/omap: venc: " Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 39/50] drm/omap: hdmi4: Simplify EDID read Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 40/50] drm/omap: hdmi5: " Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 41/50] drm/omap: dpi: Sort includes alphabetically Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 42/50] drm/omap: dpi: Reorder functions in sections Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 43/50] drm/omap: dpi: Simplify clock setting API Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 44/50] drm/omap: dpi: Register a drm_bridge Laurent Pinchart
2019-08-27  9:07   ` Hans Verkuil
2019-08-27  9:51     ` Laurent Pinchart
2019-08-27 10:48       ` Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 45/50] drm/omap: sdi: Sort includes alphabetically Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 46/50] drm/omap: sdi: Register a drm_bridge Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 47/50] drm/omap: Simplify connector implementation Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 48/50] drm/omap: dss: Remove unused omap_dss_device operations Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 49/50] drm/omap: dss: Inline the omapdss_display_get() function Laurent Pinchart
2019-08-20  1:17 ` [PATCH v2 50/50] drm/omap: dss: Remove unused omapdss_of_find_connected_device() function Laurent Pinchart
2019-08-26 12:15 ` [PATCH v2 00/50] drm/omap: Replace custom display drivers with drm_bridge and drm_panel Tomi Valkeinen
2019-08-26 13:51   ` Laurent Pinchart
2019-08-27  7:34     ` Tomi Valkeinen
2019-08-27  9:29       ` Laurent Pinchart
2019-08-27  9:32         ` Tomi Valkeinen
2019-08-27  9:40           ` 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.