All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/21] drm: Add support for bus-format negotiation
@ 2019-08-26 15:26 Boris Brezillon
  2019-08-26 15:26 ` [PATCH v2 01/21] drm: Stop including drm_bridge.h from drm_crtc.h Boris Brezillon
                   ` (20 more replies)
  0 siblings, 21 replies; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

This patch series aims at adding support for runtime bus-format
negotiation between all elements of the
'encoder -> bridges -> connector/display' section of the pipeline.

In order to support that, we need drm bridges to fully take part in the
atomic state validation process, which requires adding a
drm_bridge_state and a new drm_bridge_funcs.atomic_check() hook.
Once those basic building blocks are in place, we can add new hooks to
allow bus format negotiation (those are called just before
->atomic_check()). The bus format selection is done at runtime by
testing all possible combinations across the whole bridge chain until
one is reported to work.

Major changes since the RFC:

* Add a dummy bridge to the drm_encoder object so that vc4 and exynos
  DSI drivers can implement the pre_enable/post_disable hooks instead
  of manually setting encoder->bridge to NULL to control the
  enable/disable sequence. This change is also a first step towards
  drm_bridge/drm_encoder unification. New encoder drivers should
  stop implementing drm_encoder_helper_funcs and switch to
  drm_bridge_funcs. Existing drivers can be converted progressively
  (already have a branch where I started converting some of them [1])
* rework the bus format negotiation to give more control to bridge
  drivers in the selection process (driver can select at runtime which
  input bus format they support for a specific output bus format based
  on any information available in the connector, crtc and bridge state.

A more detailed changelog is provided in each patch.

This patch series is also available here [2].

Thanks,

Boris

[1]https://github.com/bbrezillon/linux-0day/commits/drm-encoder-bridge
[2]https://github.com/bbrezillon/linux-0day/commits/drm-drm-bridge-busfmt-v2

Boris Brezillon (21):
  drm: Stop including drm_bridge.h from drm_crtc.h
  drm: Add a dummy bridge object to drm_encoder
  drm/vc4: Implement bridge_funcs instead of encoder_helper_funcs
  drm/exynos: Fix potential unbalanced calls to pm_runtime_put
  drm/exynos: Don't reset bridge->next
  drm/exynos: Implement bridge_funcs instead of encoder_helper_funcs
  drm/bridge: Rename bridge helpers targeting a bridge chain
  drm/msm: Use drm_attach_bridge() to attach a bridge to an encoder
  drm/bridge: Introduce drm_bridge_chain_get_next_bridge()
  drm/bridge: Make the bridge chain a double-linked list
  drm/bridge: Add the drm_for_each_bridge_in_chain() helper
  drm/bridge: Add a drm_bridge_state object
  drm/bridge: Patch atomic hooks to take a drm_bridge_state
  drm/bridge: Add an ->atomic_check() hook
  drm/bridge: Add the drm_bridge_chain_get_prev_bridge() helper
  drm/bridge: Add the necessary bits to support bus format negotiation
  drm/imx: pd: Use bus format/flags provided by the bridge when
    available
  drm/bridge: lvds-encoder: Implement basic bus format negotiation
  drm/bridge: panel: Propage bus format/flags
  drm/panel: simple: Add support for Toshiba LTA089AC29000 panel
  ARM: dts: imx: imx51-zii-rdu1: Fix the display pipeline definition

 .../display/bridge/lvds-transmitter.txt       |  12 +
 .../display/panel/toshiba,lt089ac29000.txt    |   5 +-
 arch/arm/boot/dts/imx51-zii-rdu1.dts          |  24 +-
 drivers/gpu/drm/arc/arcpgu_hdmi.c             |   1 +
 drivers/gpu/drm/bridge/analogix-anx78xx.c     |   1 +
 .../drm/bridge/analogix/analogix_dp_core.c    |  13 +-
 drivers/gpu/drm/bridge/dumb-vga-dac.c         |   1 +
 drivers/gpu/drm/bridge/lvds-encoder.c         | 105 +++
 .../bridge/megachips-stdpxxxx-ge-b850v3-fw.c  |   1 +
 drivers/gpu/drm/bridge/nxp-ptn3460.c          |   1 +
 drivers/gpu/drm/bridge/panel.c                |  31 +
 drivers/gpu/drm/bridge/parade-ps8622.c        |   1 +
 drivers/gpu/drm/bridge/sii902x.c              |   1 +
 drivers/gpu/drm/bridge/sii9234.c              |   1 +
 drivers/gpu/drm/bridge/sil-sii8620.c          |   1 +
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c     |   1 +
 drivers/gpu/drm/bridge/tc358764.c             |   1 +
 drivers/gpu/drm/bridge/tc358767.c             |   1 +
 drivers/gpu/drm/bridge/ti-sn65dsi86.c         |   1 +
 drivers/gpu/drm/bridge/ti-tfp410.c            |   1 +
 drivers/gpu/drm/drm_atomic.c                  |  39 +
 drivers/gpu/drm/drm_atomic_helper.c           |  46 +-
 drivers/gpu/drm/drm_bridge.c                  | 749 ++++++++++++++----
 drivers/gpu/drm/drm_crtc_helper.c             |  29 +-
 drivers/gpu/drm/drm_encoder.c                 |  26 +-
 drivers/gpu/drm/drm_probe_helper.c            |   3 +-
 drivers/gpu/drm/drm_simple_kms_helper.c       |   1 +
 drivers/gpu/drm/exynos/exynos_dp.c            |   2 +-
 drivers/gpu/drm/exynos/exynos_drm_dsi.c       |  70 +-
 drivers/gpu/drm/exynos/exynos_drm_mic.c       |   1 +
 drivers/gpu/drm/exynos/exynos_hdmi.c          |   1 +
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c     |   1 +
 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c  |   1 +
 drivers/gpu/drm/i2c/tda998x_drv.c             |   1 +
 drivers/gpu/drm/imx/imx-ldb.c                 |   1 +
 drivers/gpu/drm/imx/parallel-display.c        | 137 +++-
 drivers/gpu/drm/ingenic/ingenic-drm.c         |   1 +
 drivers/gpu/drm/mediatek/mtk_dpi.c            |   1 +
 drivers/gpu/drm/mediatek/mtk_dsi.c            |   1 +
 drivers/gpu/drm/mediatek/mtk_hdmi.c           |   9 +-
 drivers/gpu/drm/msm/dsi/dsi.h                 |   1 +
 drivers/gpu/drm/msm/edp/edp.c                 |   4 +-
 drivers/gpu/drm/msm/edp/edp.h                 |   1 +
 drivers/gpu/drm/msm/edp/edp_bridge.c          |  10 +-
 drivers/gpu/drm/msm/hdmi/hdmi.c               |   4 +-
 drivers/gpu/drm/msm/hdmi/hdmi.h               |   2 +
 drivers/gpu/drm/omapdrm/dss/output.c          |   1 +
 drivers/gpu/drm/omapdrm/omap_drv.c            |   5 +-
 drivers/gpu/drm/omapdrm/omap_encoder.c        |   4 +-
 drivers/gpu/drm/panel/panel-simple.c          |  36 +
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c        |  10 +-
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c     |   1 +
 drivers/gpu/drm/rockchip/rockchip_lvds.c      |   1 +
 drivers/gpu/drm/rockchip/rockchip_rgb.c       |   1 +
 drivers/gpu/drm/sti/sti_dvo.c                 |   1 +
 drivers/gpu/drm/sti/sti_hda.c                 |   1 +
 drivers/gpu/drm/sti/sti_hdmi.c                |   1 +
 drivers/gpu/drm/sun4i/sun4i_lvds.c            |   1 +
 drivers/gpu/drm/sun4i/sun4i_rgb.c             |   1 +
 drivers/gpu/drm/sun4i/sun4i_tcon.c            |   1 +
 drivers/gpu/drm/tilcdc/tilcdc_external.c      |   1 +
 drivers/gpu/drm/vc4/vc4_dsi.c                 |  73 +-
 include/drm/drm_atomic.h                      |   3 +
 include/drm/drm_bridge.h                      | 335 +++++++-
 include/drm/drm_crtc.h                        |   1 -
 include/drm/drm_encoder.h                     |  23 +-
 66 files changed, 1533 insertions(+), 314 deletions(-)

-- 
2.21.0

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

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

* [PATCH v2 01/21] drm: Stop including drm_bridge.h from drm_crtc.h
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  2019-08-28 20:27   ` Boris Brezillon
  2019-08-26 15:26 ` [PATCH v2 02/21] drm: Add a dummy bridge object to drm_encoder Boris Brezillon
                   ` (19 subsequent siblings)
  20 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

We are about to add a drm_bridge_state that inherits from
drm_private_state which is defined in drm_atomic.h. Problem is,
drm_atomic.h includes drm_crtc.h which in turn includes drm_bridge.h,
leading to "drm_private_state has incomplete type" error.

Let's force all users of the drm_bridge API to explicitly include
drm_bridge.h.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
---
Changes in v2:
* Fix inclusion order (Sam Ravnog)
* Add Sam's R-b
---
 drivers/gpu/drm/arc/arcpgu_hdmi.c                        | 1 +
 drivers/gpu/drm/bridge/analogix-anx78xx.c                | 1 +
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c       | 1 +
 drivers/gpu/drm/bridge/dumb-vga-dac.c                    | 1 +
 drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 1 +
 drivers/gpu/drm/bridge/nxp-ptn3460.c                     | 1 +
 drivers/gpu/drm/bridge/panel.c                           | 1 +
 drivers/gpu/drm/bridge/parade-ps8622.c                   | 1 +
 drivers/gpu/drm/bridge/sii902x.c                         | 1 +
 drivers/gpu/drm/bridge/sii9234.c                         | 1 +
 drivers/gpu/drm/bridge/sil-sii8620.c                     | 1 +
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c                | 1 +
 drivers/gpu/drm/bridge/tc358764.c                        | 1 +
 drivers/gpu/drm/bridge/tc358767.c                        | 1 +
 drivers/gpu/drm/bridge/ti-sn65dsi86.c                    | 1 +
 drivers/gpu/drm/bridge/ti-tfp410.c                       | 1 +
 drivers/gpu/drm/drm_atomic_helper.c                      | 1 +
 drivers/gpu/drm/drm_crtc_helper.c                        | 1 +
 drivers/gpu/drm/drm_encoder.c                            | 1 +
 drivers/gpu/drm/drm_probe_helper.c                       | 1 +
 drivers/gpu/drm/drm_simple_kms_helper.c                  | 1 +
 drivers/gpu/drm/exynos/exynos_dp.c                       | 1 +
 drivers/gpu/drm/exynos/exynos_drm_dsi.c                  | 1 +
 drivers/gpu/drm/exynos/exynos_drm_mic.c                  | 1 +
 drivers/gpu/drm/exynos/exynos_hdmi.c                     | 1 +
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c                | 1 +
 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c             | 1 +
 drivers/gpu/drm/i2c/tda998x_drv.c                        | 1 +
 drivers/gpu/drm/imx/imx-ldb.c                            | 1 +
 drivers/gpu/drm/imx/parallel-display.c                   | 1 +
 drivers/gpu/drm/ingenic/ingenic-drm.c                    | 1 +
 drivers/gpu/drm/mediatek/mtk_dpi.c                       | 1 +
 drivers/gpu/drm/mediatek/mtk_dsi.c                       | 1 +
 drivers/gpu/drm/mediatek/mtk_hdmi.c                      | 1 +
 drivers/gpu/drm/msm/dsi/dsi.h                            | 1 +
 drivers/gpu/drm/msm/edp/edp.h                            | 1 +
 drivers/gpu/drm/msm/hdmi/hdmi.h                          | 2 ++
 drivers/gpu/drm/omapdrm/dss/output.c                     | 1 +
 drivers/gpu/drm/omapdrm/omap_drv.c                       | 1 +
 drivers/gpu/drm/omapdrm/omap_encoder.c                   | 1 +
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c                | 1 +
 drivers/gpu/drm/rockchip/rockchip_lvds.c                 | 1 +
 drivers/gpu/drm/rockchip/rockchip_rgb.c                  | 1 +
 drivers/gpu/drm/sti/sti_dvo.c                            | 1 +
 drivers/gpu/drm/sti/sti_hda.c                            | 1 +
 drivers/gpu/drm/sti/sti_hdmi.c                           | 1 +
 drivers/gpu/drm/sun4i/sun4i_lvds.c                       | 1 +
 drivers/gpu/drm/sun4i/sun4i_rgb.c                        | 1 +
 drivers/gpu/drm/sun4i/sun4i_tcon.c                       | 1 +
 drivers/gpu/drm/tilcdc/tilcdc_external.c                 | 1 +
 drivers/gpu/drm/vc4/vc4_dsi.c                            | 1 +
 include/drm/drm_crtc.h                                   | 1 -
 52 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/arc/arcpgu_hdmi.c b/drivers/gpu/drm/arc/arcpgu_hdmi.c
index 98aac743cc26..8fd7094beece 100644
--- a/drivers/gpu/drm/arc/arcpgu_hdmi.c
+++ b/drivers/gpu/drm/arc/arcpgu_hdmi.c
@@ -5,6 +5,7 @@
  * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
  */
 
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_device.h>
diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix-anx78xx.c
index 3c7cc5af735c..e3f4fd2a5ad4 100644
--- a/drivers/gpu/drm/bridge/analogix-anx78xx.c
+++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c
@@ -19,6 +19,7 @@
 #include <linux/types.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_edid.h>
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 22885dceaa17..bb411fe52ae8 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -21,6 +21,7 @@
 #include <drm/bridge/analogix_dp.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_device.h>
 #include <drm/drm_panel.h>
diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
index 7aa789c35882..cc33dc411b9e 100644
--- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
+++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
@@ -12,6 +12,7 @@
 #include <linux/regulator/consumer.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>
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..e8a49f6146c6 100644
--- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
+++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
@@ -25,6 +25,7 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c
index d4a1cc5052c3..57ff01339559 100644
--- a/drivers/gpu/drm/bridge/nxp-ptn3460.c
+++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_of.h>
diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index b12ae3a4c5f1..6cffeb4a42f2 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -5,6 +5,7 @@
  */
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_connector.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_modeset_helper_vtables.h>
diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c
index 93c68e2e9484..b7a72dfdcac3 100644
--- a/drivers/gpu/drm/bridge/parade-ps8622.c
+++ b/drivers/gpu/drm/bridge/parade-ps8622.c
@@ -17,6 +17,7 @@
 #include <linux/regulator/consumer.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
index 38f75ac580df..b70e8c5cf2e1 100644
--- a/drivers/gpu/drm/bridge/sii902x.c
+++ b/drivers/gpu/drm/bridge/sii902x.c
@@ -20,6 +20,7 @@
 #include <linux/clk.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_print.h>
diff --git a/drivers/gpu/drm/bridge/sii9234.c b/drivers/gpu/drm/bridge/sii9234.c
index 25d4ad8c7ad6..ad00d841ed9e 100644
--- a/drivers/gpu/drm/bridge/sii9234.c
+++ b/drivers/gpu/drm/bridge/sii9234.c
@@ -13,6 +13,7 @@
  *    Dharam Kumar <dharam.kr@samsung.com>
  */
 #include <drm/bridge/mhl.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
 
diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
index bd3165ee5354..14643923a721 100644
--- a/drivers/gpu/drm/bridge/sil-sii8620.c
+++ b/drivers/gpu/drm/bridge/sil-sii8620.c
@@ -9,6 +9,7 @@
 #include <asm/unaligned.h>
 
 #include <drm/bridge/mhl.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_encoder.h>
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 355877f0ad7a..bd65d0479683 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -26,6 +26,7 @@
 
 #include <drm/bridge/dw_hdmi.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_encoder_slave.h>
 #include <drm/drm_of.h>
diff --git a/drivers/gpu/drm/bridge/tc358764.c b/drivers/gpu/drm/bridge/tc358764.c
index 170f162ffa55..db298f550a5a 100644
--- a/drivers/gpu/drm/bridge/tc358764.c
+++ b/drivers/gpu/drm/bridge/tc358764.c
@@ -16,6 +16,7 @@
 #include <video/mipi_display.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_mipi_dsi.h>
diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
index cebc8e620820..51664a2df731 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -26,6 +26,7 @@
 #include <linux/slab.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_of.h>
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
index 0a580957c8cf..43abf01ebd4c 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -17,6 +17,7 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_of.h>
diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
index 61cc2354ef1b..aa3198dc9903 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>
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index aa16ea17ff9b..4706439fb490 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -30,6 +30,7 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_atomic_uapi.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_device.h>
 #include <drm/drm_plane_helper.h>
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 6dd49a60deac..fa3694836c22 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -36,6 +36,7 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_atomic_uapi.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_drv.h>
diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
index 7fb47b7b8b44..80d88a55302e 100644
--- a/drivers/gpu/drm/drm_encoder.c
+++ b/drivers/gpu/drm/drm_encoder.c
@@ -22,6 +22,7 @@
 
 #include <linux/export.h>
 
+#include <drm/drm_bridge.h>
 #include <drm/drm_device.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_encoder.h>
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index ef2c468205a2..351cbc40f0f8 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -32,6 +32,7 @@
 #include <linux/export.h>
 #include <linux/moduleparam.h>
 
+#include <drm/drm_bridge.h>
 #include <drm/drm_client.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
index b11910f14c46..046055719245 100644
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
@@ -8,6 +8,7 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_simple_kms_helper.h>
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
index 3a0f0ba8c63a..1e6aa24bf45e 100644
--- a/drivers/gpu/drm/exynos/exynos_dp.c
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
@@ -19,6 +19,7 @@
 
 #include <drm/bridge/analogix_dp.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 6926cee91b36..72726f2c7a9f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -24,6 +24,7 @@
 #include <video/videomode.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_panel.h>
diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c
index b78e8c5ba553..f41d75923557 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
@@ -21,6 +21,7 @@
 #include <video/of_videomode.h>
 #include <video/videomode.h>
 
+#include <drm/drm_bridge.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_print.h>
 
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index bc1565f1822a..2e3795c2c794 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -34,6 +34,7 @@
 #include <media/cec-notifier.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
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..82c972e9c024 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
@@ -9,6 +9,7 @@
 #include <linux/of_graph.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_probe_helper.h>
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
index 5bf8138941de..bdcf9c6ae9e9 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_device.h>
 #include <drm/drm_encoder_slave.h>
 #include <drm/drm_mipi_dsi.h>
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 84c6d4c91c65..6c218bace2ce 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -14,6 +14,7 @@
 #include <sound/hdmi-codec.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_of.h>
 #include <drm/drm_print.h>
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index 695f307f36b2..208069faf183 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -20,6 +20,7 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
index e7ce17503ae1..35518e5de356 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -13,6 +13,7 @@
 #include <video/of_display_timing.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
diff --git a/drivers/gpu/drm/ingenic/ingenic-drm.c b/drivers/gpu/drm/ingenic/ingenic-drm.c
index ce1fae3a78a9..1daa1378fc36 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm.c
@@ -13,6 +13,7 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_drv.h>
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
index be6d95c5ff25..01fa8b8d763d 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -17,6 +17,7 @@
 #include <video/videomode.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_of.h>
 
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 224afb666881..a413f5ff442d 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -16,6 +16,7 @@
 #include <video/videomode.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index ce91b61364eb..c79b1f855d89 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -23,6 +23,7 @@
 #include <sound/hdmi-codec.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_print.h>
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 0da8a4e428ad..eff1a4c61258 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -9,6 +9,7 @@
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_panel.h>
diff --git a/drivers/gpu/drm/msm/edp/edp.h b/drivers/gpu/drm/msm/edp/edp.h
index f2c17858a703..eb34243dad53 100644
--- a/drivers/gpu/drm/msm/edp/edp.h
+++ b/drivers/gpu/drm/msm/edp/edp.h
@@ -10,6 +10,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_dp_helper.h>
 
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 982865866a29..4aba397a889b 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -13,6 +13,8 @@
 #include <linux/regulator/consumer.h>
 #include <linux/hdmi.h>
 
+#include <drm/drm_bridge.h>
+
 #include "msm_drv.h"
 #include "hdmi.xml.h"
 
diff --git a/drivers/gpu/drm/omapdrm/dss/output.c b/drivers/gpu/drm/omapdrm/dss/output.c
index de0f882f0f7b..de500bb05bdc 100644
--- a/drivers/gpu/drm/omapdrm/dss/output.c
+++ b/drivers/gpu/drm/omapdrm/dss/output.c
@@ -11,6 +11,7 @@
 #include <linux/of.h>
 #include <linux/of_graph.h>
 
+#include <drm/drm_bridge.h>
 #include <drm/drm_panel.h>
 
 #include "dss.h"
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 9f652d2e7af1..224ec6fdc800 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -11,6 +11,7 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_file.h>
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
index 6fe14111cd95..24bbe9f2a32e 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -6,6 +6,7 @@
 
 #include <linux/list.h>
 
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_modeset_helper_vtables.h>
 #include <drm/drm_edid.h>
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index 0f00bdfe2366..3a1139b725c0 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -9,6 +9,7 @@
 
 #include <linux/export.h>
 
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_modeset_helper_vtables.h>
 #include <drm/drm_panel.h>
diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c
index 64aefa856896..8a4c9af0ba73 100644
--- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
+++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
@@ -16,6 +16,7 @@
 #include <linux/regmap.h>
 #include <linux/reset.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_of.h>
diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.c b/drivers/gpu/drm/rockchip/rockchip_rgb.c
index 89e0bb0fe0ab..db1be1f3925c 100644
--- a/drivers/gpu/drm/rockchip/rockchip_rgb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_rgb.c
@@ -9,6 +9,7 @@
 #include <linux/of_graph.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
index e55870190bf5..0a4f00253f39 100644
--- a/drivers/gpu/drm/sti/sti_dvo.c
+++ b/drivers/gpu/drm/sti/sti_dvo.c
@@ -12,6 +12,7 @@
 #include <linux/platform_device.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_device.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_print.h>
diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
index 94e404f13234..9d3fd6370a29 100644
--- a/drivers/gpu/drm/sti/sti_hda.c
+++ b/drivers/gpu/drm/sti/sti_hda.c
@@ -12,6 +12,7 @@
 #include <linux/seq_file.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_debugfs.h>
 #include <drm/drm_device.h>
 #include <drm/drm_file.h>
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index 9862c322f0c4..84318d0832a0 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -14,6 +14,7 @@
 #include <linux/reset.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_debugfs.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_edid.h>
diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c
index 7fbf425acb55..25ab2ef6d545 100644
--- a/drivers/gpu/drm/sun4i/sun4i_lvds.c
+++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c
@@ -7,6 +7,7 @@
 #include <linux/clk.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_print.h>
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index aac56983f208..e74b9eddca01 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -9,6 +9,7 @@
 #include <linux/clk.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_print.h>
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 690aeb822704..eb187da56aba 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -16,6 +16,7 @@
 #include <linux/reset.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_connector.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_encoder.h>
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_external.c b/drivers/gpu/drm/tilcdc/tilcdc_external.c
index 43d756b7810e..4fc10838de80 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_external.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c
@@ -8,6 +8,7 @@
 #include <linux/of_graph.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_of.h>
 
 #include "tilcdc_drv.h"
diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
index c78fa8144776..3f63943e5472 100644
--- a/drivers/gpu/drm/vc4/vc4_dsi.c
+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
@@ -31,6 +31,7 @@
 #include <linux/pm_runtime.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_of.h>
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 7d14c11bdc0a..7e2963cad543 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -41,7 +41,6 @@
 #include <drm/drm_connector.h>
 #include <drm/drm_device.h>
 #include <drm/drm_property.h>
-#include <drm/drm_bridge.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_plane.h>
 #include <drm/drm_blend.h>
-- 
2.21.0

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

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

* [PATCH v2 02/21] drm: Add a dummy bridge object to drm_encoder
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
  2019-08-26 15:26 ` [PATCH v2 01/21] drm: Stop including drm_bridge.h from drm_crtc.h Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  2019-08-26 15:26 ` [PATCH v2 03/21] drm/vc4: Implement bridge_funcs instead of encoder_helper_funcs Boris Brezillon
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

This in one step in the right direction towards drm_encoder/drm_bridge
unification. By doing that we also allow encoder drivers to implement
the ->pre_enable() and ->post_disable() hooks without adding new
methods to drm_encoder_helper_funcs.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
Changes in v2:
* New patch
---
 drivers/gpu/drm/drm_atomic_helper.c     | 17 +++++++++--------
 drivers/gpu/drm/drm_bridge.c            |  4 ++--
 drivers/gpu/drm/drm_crtc_helper.c       | 20 ++++++++++----------
 drivers/gpu/drm/drm_encoder.c           | 23 ++++++++++++++---------
 drivers/gpu/drm/drm_probe_helper.c      |  2 +-
 drivers/gpu/drm/exynos/exynos_drm_dsi.c |  2 +-
 drivers/gpu/drm/msm/edp/edp.c           |  2 +-
 drivers/gpu/drm/msm/edp/edp_bridge.c    |  2 +-
 drivers/gpu/drm/msm/hdmi/hdmi.c         |  2 +-
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  4 ++--
 drivers/gpu/drm/vc4/vc4_dsi.c           |  2 +-
 include/drm/drm_encoder.h               | 16 ++++++++++++++--
 12 files changed, 57 insertions(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 4706439fb490..3fe60076da05 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -445,8 +445,9 @@ mode_fixup(struct drm_atomic_state *state)
 		encoder = new_conn_state->best_encoder;
 		funcs = encoder->helper_private;
 
-		ret = drm_bridge_mode_fixup(encoder->bridge, &new_crtc_state->mode,
-				&new_crtc_state->adjusted_mode);
+		ret = drm_bridge_mode_fixup(&encoder->bridge,
+					    &new_crtc_state->mode,
+					    &new_crtc_state->adjusted_mode);
 		if (!ret) {
 			DRM_DEBUG_ATOMIC("Bridge fixup failed\n");
 			return -EINVAL;
@@ -511,7 +512,7 @@ static enum drm_mode_status mode_valid_path(struct drm_connector *connector,
 		return ret;
 	}
 
-	ret = drm_bridge_mode_valid(encoder->bridge, mode);
+	ret = drm_bridge_mode_valid(&encoder->bridge, mode);
 	if (ret != MODE_OK) {
 		DRM_DEBUG_ATOMIC("[BRIDGE] mode_valid() failed\n");
 		return ret;
@@ -1030,7 +1031,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
 		 * Each encoder has at most one connector (since we always steal
 		 * it away), so we won't call disable hooks twice.
 		 */
-		drm_atomic_bridge_disable(encoder->bridge, old_state);
+		drm_atomic_bridge_disable(&encoder->bridge, old_state);
 
 		/* Right function depends upon target state. */
 		if (funcs) {
@@ -1044,7 +1045,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
 				funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
 		}
 
-		drm_atomic_bridge_post_disable(encoder->bridge, old_state);
+		drm_atomic_bridge_post_disable(&encoder->bridge, old_state);
 	}
 
 	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
@@ -1225,7 +1226,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
 			funcs->mode_set(encoder, mode, adjusted_mode);
 		}
 
-		drm_bridge_mode_set(encoder->bridge, mode, adjusted_mode);
+		drm_bridge_mode_set(&encoder->bridge, mode, adjusted_mode);
 	}
 }
 
@@ -1342,7 +1343,7 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
 		 * Each encoder has at most one connector (since we always steal
 		 * it away), so we won't call enable hooks twice.
 		 */
-		drm_atomic_bridge_pre_enable(encoder->bridge, old_state);
+		drm_atomic_bridge_pre_enable(&encoder->bridge, old_state);
 
 		if (funcs) {
 			if (funcs->atomic_enable)
@@ -1353,7 +1354,7 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
 				funcs->commit(encoder);
 		}
 
-		drm_atomic_bridge_enable(encoder->bridge, old_state);
+		drm_atomic_bridge_enable(&encoder->bridge, old_state);
 	}
 
 	drm_atomic_helper_commit_writebacks(dev, old_state);
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index cba537c99e43..c5d6b17f6790 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -139,8 +139,8 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
 
 	if (previous)
 		previous->next = bridge;
-	else
-		encoder->bridge = bridge;
+	else if (bridge != &encoder->bridge)
+		encoder->bridge.next = bridge;
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index fa3694836c22..c80e33a84605 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -160,14 +160,14 @@ drm_encoder_disable(struct drm_encoder *encoder)
 	if (!encoder_funcs)
 		return;
 
-	drm_bridge_disable(encoder->bridge);
+	drm_bridge_disable(&encoder->bridge);
 
 	if (encoder_funcs->disable)
 		(*encoder_funcs->disable)(encoder);
 	else if (encoder_funcs->dpms)
 		(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
 
-	drm_bridge_post_disable(encoder->bridge);
+	drm_bridge_post_disable(&encoder->bridge);
 }
 
 static void __drm_helper_disable_unused_functions(struct drm_device *dev)
@@ -327,8 +327,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 		if (!encoder_funcs)
 			continue;
 
-		ret = drm_bridge_mode_fixup(encoder->bridge,
-			mode, adjusted_mode);
+		ret = drm_bridge_mode_fixup(&encoder->bridge, mode,
+					    adjusted_mode);
 		if (!ret) {
 			DRM_DEBUG_KMS("Bridge fixup failed\n");
 			goto done;
@@ -365,13 +365,13 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 		if (!encoder_funcs)
 			continue;
 
-		drm_bridge_disable(encoder->bridge);
+		drm_bridge_disable(&encoder->bridge);
 
 		/* Disable the encoders as the first thing we do. */
 		if (encoder_funcs->prepare)
 			encoder_funcs->prepare(encoder);
 
-		drm_bridge_post_disable(encoder->bridge);
+		drm_bridge_post_disable(&encoder->bridge);
 	}
 
 	drm_crtc_prepare_encoders(dev);
@@ -399,7 +399,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 		if (encoder_funcs->mode_set)
 			encoder_funcs->mode_set(encoder, mode, adjusted_mode);
 
-		drm_bridge_mode_set(encoder->bridge, mode, adjusted_mode);
+		drm_bridge_mode_set(&encoder->bridge, mode, adjusted_mode);
 	}
 
 	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
@@ -414,12 +414,12 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 		if (!encoder_funcs)
 			continue;
 
-		drm_bridge_pre_enable(encoder->bridge);
+		drm_bridge_pre_enable(&encoder->bridge);
 
 		if (encoder_funcs->commit)
 			encoder_funcs->commit(encoder);
 
-		drm_bridge_enable(encoder->bridge);
+		drm_bridge_enable(&encoder->bridge);
 	}
 
 	/* Calculate and store various constants which
@@ -818,7 +818,7 @@ static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder)
 /* Helper which handles bridge ordering around encoder dpms */
 static void drm_helper_encoder_dpms(struct drm_encoder *encoder, int mode)
 {
-	struct drm_bridge *bridge = encoder->bridge;
+	struct drm_bridge *bridge = &encoder->bridge;
 	const struct drm_encoder_helper_funcs *encoder_funcs;
 
 	encoder_funcs = encoder->helper_private;
diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
index 80d88a55302e..686053bf41b9 100644
--- a/drivers/gpu/drm/drm_encoder.c
+++ b/drivers/gpu/drm/drm_encoder.c
@@ -91,6 +91,9 @@ void drm_encoder_unregister_all(struct drm_device *dev)
 	}
 }
 
+static const struct drm_bridge_funcs dummy_bridge_funcs = {
+};
+
 /**
  * drm_encoder_init - Init a preallocated encoder
  * @dev: drm device
@@ -140,6 +143,13 @@ int drm_encoder_init(struct drm_device *dev,
 		goto out_put;
 	}
 
+	if (!encoder->bridge.funcs)
+		encoder->bridge.funcs = &dummy_bridge_funcs;
+
+	ret = drm_bridge_attach(encoder, &encoder->bridge, NULL);
+	if (ret)
+		goto out_put;
+
 	list_add_tail(&encoder->head, &dev->mode_config.encoder_list);
 	encoder->index = dev->mode_config.num_encoder++;
 
@@ -160,21 +170,16 @@ EXPORT_SYMBOL(drm_encoder_init);
 void drm_encoder_cleanup(struct drm_encoder *encoder)
 {
 	struct drm_device *dev = encoder->dev;
+	struct drm_bridge *bridge, *next;
 
 	/* Note that the encoder_list is considered to be static; should we
 	 * remove the drm_encoder at runtime we would have to decrement all
 	 * the indices on the drm_encoder after us in the encoder_list.
 	 */
 
-	if (encoder->bridge) {
-		struct drm_bridge *bridge = encoder->bridge;
-		struct drm_bridge *next;
-
-		while (bridge) {
-			next = bridge->next;
-			drm_bridge_detach(bridge);
-			bridge = next;
-		}
+	for (bridge = &encoder->bridge; bridge; bridge = next) {
+		next = bridge->next;
+		drm_bridge_detach(bridge);
 	}
 
 	drm_mode_object_unregister(dev, &encoder->base);
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index 351cbc40f0f8..e4af2f9fa372 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -113,7 +113,7 @@ drm_mode_validate_pipeline(struct drm_display_mode *mode,
 			continue;
 		}
 
-		ret = drm_bridge_mode_valid(encoder->bridge, mode);
+		ret = drm_bridge_mode_valid(&encoder->bridge, mode);
 		if (ret != MODE_OK) {
 			/* There is also no point in continuing for crtc check
 			 * here. */
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 72726f2c7a9f..8e655ae1fb0c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1522,7 +1522,7 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
 	if (out_bridge) {
 		drm_bridge_attach(encoder, out_bridge, NULL);
 		dsi->out_bridge = out_bridge;
-		encoder->bridge = NULL;
+		encoder->bridge.next = NULL;
 	} else {
 		int ret = exynos_dsi_create_connector(encoder);
 
diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c
index 0f312ac5b624..b54559a79d36 100644
--- a/drivers/gpu/drm/msm/edp/edp.c
+++ b/drivers/gpu/drm/msm/edp/edp.c
@@ -178,7 +178,7 @@ int msm_edp_modeset_init(struct msm_edp *edp, struct drm_device *dev,
 		goto fail;
 	}
 
-	encoder->bridge = edp->bridge;
+	encoder->bridge.next = edp->bridge;
 
 	priv->bridges[priv->num_bridges++]       = edp->bridge;
 	priv->connectors[priv->num_connectors++] = edp->connector;
diff --git a/drivers/gpu/drm/msm/edp/edp_bridge.c b/drivers/gpu/drm/msm/edp/edp_bridge.c
index 2950bba4aca9..446acca110e9 100644
--- a/drivers/gpu/drm/msm/edp/edp_bridge.c
+++ b/drivers/gpu/drm/msm/edp/edp_bridge.c
@@ -56,7 +56,7 @@ static void edp_bridge_mode_set(struct drm_bridge *bridge,
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		if ((connector->encoder != NULL) &&
-			(connector->encoder->bridge == bridge)) {
+			(connector->encoder->bridge.next == bridge)) {
 			msm_edp_ctrl_timing_cfg(edp->ctrl,
 				adjusted_mode, &connector->display_info);
 			break;
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 0e4217be3f00..9d94a88dd8d6 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -327,7 +327,7 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
 		goto fail;
 	}
 
-	encoder->bridge = hdmi->bridge;
+	encoder->bridge.next = hdmi->bridge;
 
 	priv->bridges[priv->num_bridges++]       = hdmi->bridge;
 	priv->connectors[priv->num_connectors++] = hdmi->connector;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 2da46e3dc4ae..1bd748202946 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -681,7 +681,7 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
 		const struct drm_display_mode *mode =
 			&crtc->state->adjusted_mode;
 
-		rcar_lvds_clk_enable(encoder->base.bridge,
+		rcar_lvds_clk_enable(encoder->base.bridge.next,
 				     mode->clock * 1000);
 	}
 
@@ -707,7 +707,7 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
 		 * Disable the LVDS clock output, see
 		 * rcar_du_crtc_atomic_enable().
 		 */
-		rcar_lvds_clk_disable(encoder->base.bridge);
+		rcar_lvds_clk_disable(encoder->base.bridge.next);
 	}
 
 	spin_lock_irq(&crtc->dev->event_lock);
diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
index 3f63943e5472..e64b66b1efcd 100644
--- a/drivers/gpu/drm/vc4/vc4_dsi.c
+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
@@ -1610,7 +1610,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
 	 * from our driver, since we need to sequence them within the
 	 * encoder's enable/disable paths.
 	 */
-	dsi->encoder->bridge = NULL;
+	dsi->encoder->bridge.next = NULL;
 
 	if (dsi->port == 0)
 		vc4_debugfs_add_regset32(drm, "dsi0_regs", &dsi->regset);
diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
index 70cfca03d812..30d347c37402 100644
--- a/include/drm/drm_encoder.h
+++ b/include/drm/drm_encoder.h
@@ -25,6 +25,7 @@
 
 #include <linux/list.h>
 #include <linux/ctype.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_mode.h>
 #include <drm/drm_mode_object.h>
@@ -89,7 +90,6 @@ struct drm_encoder_funcs {
  * @head: list management
  * @base: base KMS object
  * @name: human readable name, can be overwritten by the driver
- * @bridge: bridge associated to the encoder
  * @funcs: control functions
  * @helper_private: mid-layer private data
  *
@@ -172,13 +172,25 @@ struct drm_encoder {
 	 * &drm_connector_state.crtc.
 	 */
 	struct drm_crtc *crtc;
-	struct drm_bridge *bridge;
+
+	/**
+	 * @bridge: Bridge representing our encoder. Other bridges might be
+	 * linked to this dummy bridge element to form an encoder chain.
+	 */
+	struct drm_bridge bridge;
+
 	const struct drm_encoder_funcs *funcs;
 	const struct drm_encoder_helper_funcs *helper_private;
 };
 
 #define obj_to_encoder(x) container_of(x, struct drm_encoder, base)
 
+static inline struct drm_encoder *
+bridge_to_encoder(struct drm_bridge *bridge)
+{
+	return container_of(bridge, struct drm_encoder, bridge);
+}
+
 __printf(5, 6)
 int drm_encoder_init(struct drm_device *dev,
 		     struct drm_encoder *encoder,
-- 
2.21.0

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

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

* [PATCH v2 03/21] drm/vc4: Implement bridge_funcs instead of encoder_helper_funcs
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
  2019-08-26 15:26 ` [PATCH v2 01/21] drm: Stop including drm_bridge.h from drm_crtc.h Boris Brezillon
  2019-08-26 15:26 ` [PATCH v2 02/21] drm: Add a dummy bridge object to drm_encoder Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  2019-08-26 15:26 ` [PATCH v2 04/21] drm/exynos: Fix potential unbalanced calls to pm_runtime_put Boris Brezillon
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

Those hooks are called exactly at the same time except the bridge
funcs have pre_enable()/post_disable() hooks which allows us to get
rid of the hack resetting encoder->bridge.next (was needed to control
the encoder/bridge enable/disable sequence).

We can also get of the dsi->bridge field since the bridge pointer is
available in encoder->bridge.next.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
Changes in v2:
* New patch (replaces "drm/vc4: Get rid of the dsi->bridge field")
---
 drivers/gpu/drm/vc4/vc4_dsi.c | 70 +++++++++++++++++++----------------
 1 file changed, 39 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
index e64b66b1efcd..4aa4c1a94f17 100644
--- a/drivers/gpu/drm/vc4/vc4_dsi.c
+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
@@ -498,7 +498,6 @@ struct vc4_dsi {
 
 	struct mipi_dsi_host dsi_host;
 	struct drm_encoder *encoder;
-	struct drm_bridge *bridge;
 
 	void __iomem *regs;
 
@@ -747,16 +746,13 @@ dsi_esc_timing(u32 ns)
 	return DIV_ROUND_UP(ns, ESC_TIME_NS);
 }
 
-static void vc4_dsi_encoder_disable(struct drm_encoder *encoder)
+static void vc4_dsi_bridge_post_disable(struct drm_bridge *bridge)
 {
+	struct drm_encoder *encoder = bridge_to_encoder(bridge);
 	struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
 	struct vc4_dsi *dsi = vc4_encoder->dsi;
 	struct device *dev = &dsi->pdev->dev;
 
-	drm_bridge_disable(dsi->bridge);
-	vc4_dsi_ulps(dsi, true);
-	drm_bridge_post_disable(dsi->bridge);
-
 	clk_disable_unprepare(dsi->pll_phy_clock);
 	clk_disable_unprepare(dsi->escape_clock);
 	clk_disable_unprepare(dsi->pixel_clock);
@@ -764,6 +760,15 @@ static void vc4_dsi_encoder_disable(struct drm_encoder *encoder)
 	pm_runtime_put(dev);
 }
 
+static void vc4_dsi_bridge_disable(struct drm_bridge *bridge)
+{
+	struct drm_encoder *encoder = bridge_to_encoder(bridge);
+	struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
+	struct vc4_dsi *dsi = vc4_encoder->dsi;
+
+	vc4_dsi_ulps(dsi, true);
+}
+
 /* Extends the mode's blank intervals to handle BCM2835's integer-only
  * DSI PLL divider.
  *
@@ -777,10 +782,11 @@ static void vc4_dsi_encoder_disable(struct drm_encoder *encoder)
  * higher-than-expected clock rate to the panel, but that's what the
  * firmware does too.
  */
-static bool vc4_dsi_encoder_mode_fixup(struct drm_encoder *encoder,
-				       const struct drm_display_mode *mode,
-				       struct drm_display_mode *adjusted_mode)
+static bool vc4_dsi_bridge_mode_fixup(struct drm_bridge *bridge,
+				      const struct drm_display_mode *mode,
+				      struct drm_display_mode *adjusted_mode)
 {
+	struct drm_encoder *encoder = bridge_to_encoder(bridge);
 	struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
 	struct vc4_dsi *dsi = vc4_encoder->dsi;
 	struct clk *phy_parent = clk_get_parent(dsi->pll_phy_clock);
@@ -816,8 +822,9 @@ static bool vc4_dsi_encoder_mode_fixup(struct drm_encoder *encoder,
 	return true;
 }
 
-static void vc4_dsi_encoder_enable(struct drm_encoder *encoder)
+static void vc4_dsi_bridge_pre_enable(struct drm_bridge *bridge)
 {
+	struct drm_encoder *encoder = bridge_to_encoder(bridge);
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
 	struct vc4_dsi *dsi = vc4_encoder->dsi;
@@ -1054,8 +1061,14 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder)
 	}
 
 	vc4_dsi_ulps(dsi, false);
+}
 
-	drm_bridge_pre_enable(dsi->bridge);
+static void vc4_dsi_bridge_enable(struct drm_bridge *bridge)
+{
+	struct drm_encoder *encoder = bridge_to_encoder(bridge);
+	struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
+	struct vc4_dsi *dsi = vc4_encoder->dsi;
+	bool debug_dump_regs = false;
 
 	if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
 		DSI_PORT_WRITE(DISP0_CTRL,
@@ -1072,8 +1085,6 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder)
 			       DSI_DISP0_ENABLE);
 	}
 
-	drm_bridge_enable(dsi->bridge);
-
 	if (debug_dump_regs) {
 		struct drm_printer p = drm_info_printer(&dsi->pdev->dev);
 		dev_info(&dsi->pdev->dev, "DSI regs after:\n");
@@ -1290,10 +1301,12 @@ static const struct mipi_dsi_host_ops vc4_dsi_host_ops = {
 	.transfer = vc4_dsi_host_transfer,
 };
 
-static const struct drm_encoder_helper_funcs vc4_dsi_encoder_helper_funcs = {
-	.disable = vc4_dsi_encoder_disable,
-	.enable = vc4_dsi_encoder_enable,
-	.mode_fixup = vc4_dsi_encoder_mode_fixup,
+static const struct drm_bridge_funcs vc4_dsi_bridge_funcs = {
+	.pre_enable = vc4_dsi_bridge_pre_enable,
+	.enable = vc4_dsi_bridge_enable,
+	.disable = vc4_dsi_bridge_disable,
+	.post_disable = vc4_dsi_bridge_post_disable,
+	.mode_fixup = vc4_dsi_bridge_mode_fixup,
 };
 
 static const struct of_device_id vc4_dsi_dt_match[] = {
@@ -1445,6 +1458,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	struct vc4_dsi *dsi = dev_get_drvdata(dev);
 	struct vc4_dsi_encoder *vc4_dsi_encoder;
+	struct drm_bridge *bridge;
 	struct drm_panel *panel;
 	const struct of_device_id *match;
 	dma_cap_mask_t dma_mask;
@@ -1561,7 +1575,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
 	}
 
 	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
-					  &panel, &dsi->bridge);
+					  &panel, &bridge);
 	if (ret) {
 		/* If the bridge or panel pointed by dev->of_node is not
 		 * enabled, just return 0 here so that we don't prevent the DRM
@@ -1576,10 +1590,10 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
 	}
 
 	if (panel) {
-		dsi->bridge = devm_drm_panel_bridge_add(dev, panel,
-							DRM_MODE_CONNECTOR_DSI);
-		if (IS_ERR(dsi->bridge))
-			return PTR_ERR(dsi->bridge);
+		bridge = devm_drm_panel_bridge_add(dev, panel,
+						   DRM_MODE_CONNECTOR_DSI);
+		if (IS_ERR(bridge))
+			return PTR_ERR(bridge);
 	}
 
 	/* The esc clock rate is supposed to always be 100Mhz. */
@@ -1596,21 +1610,15 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
 	if (dsi->port == 1)
 		vc4->dsi1 = dsi;
 
+	dsi->encoder->bridge.funcs = &vc4_dsi_bridge_funcs;
 	drm_encoder_init(drm, dsi->encoder, &vc4_dsi_encoder_funcs,
 			 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, bridge, NULL);
 	if (ret) {
 		dev_err(dev, "bridge attach failed: %d\n", ret);
 		return ret;
 	}
-	/* Disable the atomic helper calls into the bridge.  We
-	 * manually call the bridge pre_enable / enable / etc. calls
-	 * from our driver, since we need to sequence them within the
-	 * encoder's enable/disable paths.
-	 */
-	dsi->encoder->bridge.next = NULL;
 
 	if (dsi->port == 0)
 		vc4_debugfs_add_regset32(drm, "dsi0_regs", &dsi->regset);
@@ -1629,7 +1637,7 @@ static void vc4_dsi_unbind(struct device *dev, struct device *master,
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	struct vc4_dsi *dsi = dev_get_drvdata(dev);
 
-	if (dsi->bridge)
+	if (dsi->encoder->bridge.next)
 		pm_runtime_disable(dev);
 
 	vc4_dsi_encoder_destroy(dsi->encoder);
-- 
2.21.0

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

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

* [PATCH v2 04/21] drm/exynos: Fix potential unbalanced calls to pm_runtime_put
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
                   ` (2 preceding siblings ...)
  2019-08-26 15:26 ` [PATCH v2 03/21] drm/vc4: Implement bridge_funcs instead of encoder_helper_funcs Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  2019-10-11 13:31   ` Boris Brezillon
  2019-10-11 13:54   ` Andrzej Hajda
  2019-08-26 15:26 ` [PATCH v2 05/21] drm/exynos: Don't reset bridge->next Boris Brezillon
                   ` (16 subsequent siblings)
  20 siblings, 2 replies; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

The encoder->enable() can't report errors and is expected to always
succeed. If we call pm_runtime_put() in the exynos_dsi_enable() error
path (as currently done) we'll have unbalanced get/put calls when
encoder->disable() is called.

The situation is not ideal since drm_panel_{prepare,enable}() can
theoretically return an error (even if in practice I don't think any
panel driver does that). Putting a WARN_ON() is the best we can do,
unfortunately. Note that -ENOSYS is actually a valid case, it just
means the panel driver does not implement the hook.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
Changes in v2:
* New patch
---
 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 14 ++------------
 1 file changed, 2 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 8e655ae1fb0c..c555cecfe1f5 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1387,8 +1387,7 @@ static void exynos_dsi_enable(struct drm_encoder *encoder)
 
 	if (dsi->panel) {
 		ret = drm_panel_prepare(dsi->panel);
-		if (ret < 0)
-			goto err_put_sync;
+		WARN_ON(ret && ret != -ENOSYS);
 	} else {
 		drm_bridge_pre_enable(dsi->out_bridge);
 	}
@@ -1398,22 +1397,13 @@ static void exynos_dsi_enable(struct drm_encoder *encoder)
 
 	if (dsi->panel) {
 		ret = drm_panel_enable(dsi->panel);
-		if (ret < 0)
-			goto err_display_disable;
+		WARN_ON(ret && ret != -ENOSYS);
 	} else {
 		drm_bridge_enable(dsi->out_bridge);
 	}
 
 	dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
 	return;
-
-err_display_disable:
-	exynos_dsi_set_display_enable(dsi, false);
-	drm_panel_unprepare(dsi->panel);
-
-err_put_sync:
-	dsi->state &= ~DSIM_STATE_ENABLED;
-	pm_runtime_put(dsi->dev);
 }
 
 static void exynos_dsi_disable(struct drm_encoder *encoder)
-- 
2.21.0

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

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

* [PATCH v2 05/21] drm/exynos: Don't reset bridge->next
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
                   ` (3 preceding siblings ...)
  2019-08-26 15:26 ` [PATCH v2 04/21] drm/exynos: Fix potential unbalanced calls to pm_runtime_put Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  2019-08-26 15:26 ` [PATCH v2 06/21] drm/exynos: Implement bridge_funcs instead of encoder_helper_funcs Boris Brezillon
                   ` (15 subsequent siblings)
  20 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

bridge->next is only points to the new bridge if drm_bridge_attach()
succeeds. No need to reset it manually here.

Note that this change is part of the attempt to make the bridge chain
a double-linked list. In order to do that we must patch all drivers
manipulating the bridge->next field.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes in v2:
* Add Laurent's R-b (I'd like to have a R-b from the DRM exynos
  maintainers before applying that one)
---
 drivers/gpu/drm/exynos/exynos_dp.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
index 1e6aa24bf45e..4785885c0f4f 100644
--- a/drivers/gpu/drm/exynos/exynos_dp.c
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
@@ -110,7 +110,6 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
 		if (ret) {
 			DRM_DEV_ERROR(dp->dev,
 				      "Failed to attach bridge to drm\n");
-			bridge->next = NULL;
 			return ret;
 		}
 	}
-- 
2.21.0

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

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

* [PATCH v2 06/21] drm/exynos: Implement bridge_funcs instead of encoder_helper_funcs
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
                   ` (4 preceding siblings ...)
  2019-08-26 15:26 ` [PATCH v2 05/21] drm/exynos: Don't reset bridge->next Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  2019-08-26 15:26 ` [PATCH v2 07/21] drm/bridge: Rename bridge helpers targeting a bridge chain Boris Brezillon
                   ` (14 subsequent siblings)
  20 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

Those hooks are called exactly at the same time except the bridge
funcs have pre_enable()/post_disable() hooks which allows us to get
rid of the hack resetting encoder->bridge.next (was needed to control
the encoder/bridge enable/disable sequence).

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
Changes in v2:
* New patch (replacement for "drm/exynos: Get rid of exynos_dsi->out_bridge")
---
 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 55 ++++++++++++++++---------
 1 file changed, 36 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index c555cecfe1f5..4f713b0ac244 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1374,40 +1374,48 @@ static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi)
 	}
 }
 
-static void exynos_dsi_enable(struct drm_encoder *encoder)
+static void exynos_dsi_pre_enable(struct drm_bridge *bridge)
 {
+	struct drm_encoder *encoder = bridge_to_encoder(bridge);
 	struct exynos_dsi *dsi = encoder_to_dsi(encoder);
-	int ret;
 
 	if (dsi->state & DSIM_STATE_ENABLED)
 		return;
 
 	pm_runtime_get_sync(dsi->dev);
-	dsi->state |= DSIM_STATE_ENABLED;
 
 	if (dsi->panel) {
+		int ret;
+
 		ret = drm_panel_prepare(dsi->panel);
 		WARN_ON(ret && ret != -ENOSYS);
-	} else {
-		drm_bridge_pre_enable(dsi->out_bridge);
 	}
+}
+
+static void exynos_dsi_enable(struct drm_bridge *bridge)
+{
+	struct drm_encoder *encoder = bridge_to_encoder(bridge);
+	struct exynos_dsi *dsi = encoder_to_dsi(encoder);
+
+	if (dsi->state & DSIM_STATE_ENABLED)
+		return;
 
 	exynos_dsi_set_display_mode(dsi);
 	exynos_dsi_set_display_enable(dsi, true);
 
 	if (dsi->panel) {
+		int ret;
+
 		ret = drm_panel_enable(dsi->panel);
 		WARN_ON(ret && ret != -ENOSYS);
-	} else {
-		drm_bridge_enable(dsi->out_bridge);
 	}
 
-	dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
-	return;
+	dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE | DSIM_STATE_ENABLED;
 }
 
-static void exynos_dsi_disable(struct drm_encoder *encoder)
+static void exynos_dsi_disable(struct drm_bridge *bridge)
 {
+	struct drm_encoder *encoder = bridge_to_encoder(bridge);
 	struct exynos_dsi *dsi = encoder_to_dsi(encoder);
 
 	if (!(dsi->state & DSIM_STATE_ENABLED))
@@ -1415,11 +1423,18 @@ static void exynos_dsi_disable(struct drm_encoder *encoder)
 
 	dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
 
-	drm_panel_disable(dsi->panel);
-	drm_bridge_disable(dsi->out_bridge);
 	exynos_dsi_set_display_enable(dsi, false);
 	drm_panel_unprepare(dsi->panel);
-	drm_bridge_post_disable(dsi->out_bridge);
+}
+
+static void exynos_dsi_post_disable(struct drm_bridge *bridge)
+{
+	struct drm_encoder *encoder = bridge_to_encoder(bridge);
+	struct exynos_dsi *dsi = encoder_to_dsi(encoder);
+
+	if (!(dsi->state & DSIM_STATE_ENABLED))
+		return;
+
 	dsi->state &= ~DSIM_STATE_ENABLED;
 	pm_runtime_put_sync(dsi->dev);
 }
@@ -1489,9 +1504,11 @@ static int exynos_dsi_create_connector(struct drm_encoder *encoder)
 	return 0;
 }
 
-static const struct drm_encoder_helper_funcs exynos_dsi_encoder_helper_funcs = {
+static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = {
+	.pre_enable = exynos_dsi_pre_enable,
 	.enable = exynos_dsi_enable,
 	.disable = exynos_dsi_disable,
+	.post_disable = exynos_dsi_post_disable,
 };
 
 static const struct drm_encoder_funcs exynos_dsi_encoder_funcs = {
@@ -1512,7 +1529,6 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
 	if (out_bridge) {
 		drm_bridge_attach(encoder, out_bridge, NULL);
 		dsi->out_bridge = out_bridge;
-		encoder->bridge.next = NULL;
 	} else {
 		int ret = exynos_dsi_create_connector(encoder);
 
@@ -1569,7 +1585,8 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
 
 	if (dsi->panel) {
 		mutex_lock(&drm->mode_config.mutex);
-		exynos_dsi_disable(&dsi->encoder);
+		exynos_dsi_disable(&dsi->encoder.bridge);
+		exynos_dsi_post_disable(&dsi->encoder.bridge);
 		drm_panel_detach(dsi->panel);
 		dsi->panel = NULL;
 		dsi->connector.status = connector_status_disconnected;
@@ -1674,11 +1691,10 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
 	struct drm_bridge *in_bridge;
 	int ret;
 
+	encoder->bridge.funcs = &exynos_dsi_bridge_funcs;
 	drm_encoder_init(drm_dev, encoder, &exynos_dsi_encoder_funcs,
 			 DRM_MODE_ENCODER_TMDS, NULL);
 
-	drm_encoder_helper_add(encoder, &exynos_dsi_encoder_helper_funcs);
-
 	ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_LCD);
 	if (ret < 0)
 		return ret;
@@ -1698,7 +1714,8 @@ static void exynos_dsi_unbind(struct device *dev, struct device *master,
 	struct drm_encoder *encoder = dev_get_drvdata(dev);
 	struct exynos_dsi *dsi = encoder_to_dsi(encoder);
 
-	exynos_dsi_disable(encoder);
+	exynos_dsi_disable(&encoder->bridge);
+	exynos_dsi_post_disable(&encoder->bridge);
 
 	mipi_dsi_host_unregister(&dsi->dsi_host);
 }
-- 
2.21.0

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

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

* [PATCH v2 07/21] drm/bridge: Rename bridge helpers targeting a bridge chain
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
                   ` (5 preceding siblings ...)
  2019-08-26 15:26 ` [PATCH v2 06/21] drm/exynos: Implement bridge_funcs instead of encoder_helper_funcs Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  2019-08-26 15:26 ` [PATCH v2 08/21] drm/msm: Use drm_attach_bridge() to attach a bridge to an encoder Boris Brezillon
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

Change the prefix of bridge helpers targeting a bridge chain from
drm_bridge_ to drm_bridge_chain_ to better reflect the fact that
the operation will happen on all elements of chain, starting at the
bridge passed in argument.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
Changes in v2:
* Pass te bridge, not the encoder, so we can later act on a sub-chain
  instead of the whole chain
---
 drivers/gpu/drm/drm_atomic_helper.c |  20 +++--
 drivers/gpu/drm/drm_bridge.c        | 125 ++++++++++++++--------------
 drivers/gpu/drm/drm_crtc_helper.c   |  28 +++----
 drivers/gpu/drm/drm_probe_helper.c  |   2 +-
 drivers/gpu/drm/mediatek/mtk_hdmi.c |   4 +-
 include/drm/drm_bridge.h            |  64 +++++++-------
 6 files changed, 126 insertions(+), 117 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 3fe60076da05..cccd9e3531c1 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -445,9 +445,9 @@ mode_fixup(struct drm_atomic_state *state)
 		encoder = new_conn_state->best_encoder;
 		funcs = encoder->helper_private;
 
-		ret = drm_bridge_mode_fixup(&encoder->bridge,
-					    &new_crtc_state->mode,
-					    &new_crtc_state->adjusted_mode);
+		ret = drm_bridge_chain_mode_fixup(&encoder->bridge,
+					&new_crtc_state->mode,
+					&new_crtc_state->adjusted_mode);
 		if (!ret) {
 			DRM_DEBUG_ATOMIC("Bridge fixup failed\n");
 			return -EINVAL;
@@ -512,7 +512,7 @@ static enum drm_mode_status mode_valid_path(struct drm_connector *connector,
 		return ret;
 	}
 
-	ret = drm_bridge_mode_valid(&encoder->bridge, mode);
+	ret = drm_bridge_chain_mode_valid(&encoder->bridge, mode);
 	if (ret != MODE_OK) {
 		DRM_DEBUG_ATOMIC("[BRIDGE] mode_valid() failed\n");
 		return ret;
@@ -1031,7 +1031,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
 		 * Each encoder has at most one connector (since we always steal
 		 * it away), so we won't call disable hooks twice.
 		 */
-		drm_atomic_bridge_disable(&encoder->bridge, old_state);
+		drm_atomic_bridge_chain_disable(&encoder->bridge, old_state);
 
 		/* Right function depends upon target state. */
 		if (funcs) {
@@ -1045,7 +1045,8 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
 				funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
 		}
 
-		drm_atomic_bridge_post_disable(&encoder->bridge, old_state);
+		drm_atomic_bridge_chain_post_disable(&encoder->bridge,
+						     old_state);
 	}
 
 	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
@@ -1226,7 +1227,8 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
 			funcs->mode_set(encoder, mode, adjusted_mode);
 		}
 
-		drm_bridge_mode_set(&encoder->bridge, mode, adjusted_mode);
+		drm_bridge_chain_mode_set(&encoder->bridge, mode,
+					  adjusted_mode);
 	}
 }
 
@@ -1343,7 +1345,7 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
 		 * Each encoder has at most one connector (since we always steal
 		 * it away), so we won't call enable hooks twice.
 		 */
-		drm_atomic_bridge_pre_enable(&encoder->bridge, old_state);
+		drm_atomic_bridge_chain_pre_enable(&encoder->bridge, old_state);
 
 		if (funcs) {
 			if (funcs->atomic_enable)
@@ -1354,7 +1356,7 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
 				funcs->commit(encoder);
 		}
 
-		drm_atomic_bridge_enable(&encoder->bridge, old_state);
+		drm_atomic_bridge_chain_enable(&encoder->bridge, old_state);
 	}
 
 	drm_atomic_helper_commit_writebacks(dev, old_state);
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index c5d6b17f6790..52f1263530b7 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -172,8 +172,8 @@ void drm_bridge_detach(struct drm_bridge *bridge)
  */
 
 /**
- * drm_bridge_mode_fixup - fixup proposed mode for all bridges in the
- *			   encoder chain
+ * drm_bridge_chain_mode_fixup - fixup proposed mode for all bridges in the
+ *				 encoder chain
  * @bridge: bridge control structure
  * @mode: desired mode to be set for the bridge
  * @adjusted_mode: updated mode that works for this bridge
@@ -186,9 +186,9 @@ void drm_bridge_detach(struct drm_bridge *bridge)
  * RETURNS:
  * true on success, false on failure
  */
-bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
-			const struct drm_display_mode *mode,
-			struct drm_display_mode *adjusted_mode)
+bool drm_bridge_chain_mode_fixup(struct drm_bridge *bridge,
+				 const struct drm_display_mode *mode,
+				 struct drm_display_mode *adjusted_mode)
 {
 	bool ret = true;
 
@@ -198,15 +198,16 @@ bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
 	if (bridge->funcs->mode_fixup)
 		ret = bridge->funcs->mode_fixup(bridge, mode, adjusted_mode);
 
-	ret = ret && drm_bridge_mode_fixup(bridge->next, mode, adjusted_mode);
+	ret = ret && drm_bridge_chain_mode_fixup(bridge->next, mode,
+						 adjusted_mode);
 
 	return ret;
 }
-EXPORT_SYMBOL(drm_bridge_mode_fixup);
+EXPORT_SYMBOL(drm_bridge_chain_mode_fixup);
 
 /**
- * drm_bridge_mode_valid - validate the mode against all bridges in the
- * 			   encoder chain.
+ * drm_bridge_chain_mode_valid - validate the mode against all bridges in the
+ *				 encoder chain.
  * @bridge: bridge control structure
  * @mode: desired mode to be validated
  *
@@ -219,8 +220,9 @@ EXPORT_SYMBOL(drm_bridge_mode_fixup);
  * RETURNS:
  * MODE_OK on success, drm_mode_status Enum error code on failure
  */
-enum drm_mode_status drm_bridge_mode_valid(struct drm_bridge *bridge,
-					   const struct drm_display_mode *mode)
+enum drm_mode_status
+drm_bridge_chain_mode_valid(struct drm_bridge *bridge,
+			    const struct drm_display_mode *mode)
 {
 	enum drm_mode_status ret = MODE_OK;
 
@@ -233,12 +235,12 @@ enum drm_mode_status drm_bridge_mode_valid(struct drm_bridge *bridge,
 	if (ret != MODE_OK)
 		return ret;
 
-	return drm_bridge_mode_valid(bridge->next, mode);
+	return drm_bridge_chain_mode_valid(bridge->next, mode);
 }
-EXPORT_SYMBOL(drm_bridge_mode_valid);
+EXPORT_SYMBOL(drm_bridge_chain_mode_valid);
 
 /**
- * drm_bridge_disable - disables all bridges in the encoder chain
+ * drm_bridge_chain_disable - disables all bridges in the encoder chain
  * @bridge: bridge control structure
  *
  * Calls &drm_bridge_funcs.disable op for all the bridges in the encoder
@@ -247,20 +249,21 @@ EXPORT_SYMBOL(drm_bridge_mode_valid);
  *
  * Note: the bridge passed should be the one closest to the encoder
  */
-void drm_bridge_disable(struct drm_bridge *bridge)
+void drm_bridge_chain_disable(struct drm_bridge *bridge)
 {
 	if (!bridge)
 		return;
 
-	drm_bridge_disable(bridge->next);
+	drm_bridge_chain_disable(bridge->next);
 
 	if (bridge->funcs->disable)
 		bridge->funcs->disable(bridge);
 }
-EXPORT_SYMBOL(drm_bridge_disable);
+EXPORT_SYMBOL(drm_bridge_chain_disable);
 
 /**
- * drm_bridge_post_disable - cleans up after disabling all bridges in the encoder chain
+ * drm_bridge_chain_post_disable - cleans up after disabling all bridges in the
+ *				   encoder chain
  * @bridge: bridge control structure
  *
  * Calls &drm_bridge_funcs.post_disable op for all the bridges in the
@@ -269,7 +272,7 @@ EXPORT_SYMBOL(drm_bridge_disable);
  *
  * Note: the bridge passed should be the one closest to the encoder
  */
-void drm_bridge_post_disable(struct drm_bridge *bridge)
+void drm_bridge_chain_post_disable(struct drm_bridge *bridge)
 {
 	if (!bridge)
 		return;
@@ -277,25 +280,25 @@ void drm_bridge_post_disable(struct drm_bridge *bridge)
 	if (bridge->funcs->post_disable)
 		bridge->funcs->post_disable(bridge);
 
-	drm_bridge_post_disable(bridge->next);
+	drm_bridge_chain_post_disable(bridge->next);
 }
-EXPORT_SYMBOL(drm_bridge_post_disable);
+EXPORT_SYMBOL(drm_bridge_chain_post_disable);
 
 /**
- * drm_bridge_mode_set - set proposed mode for all bridges in the
- *			 encoder chain
+ * drm_bridge_chain_mode_set - set proposed mode for all bridges in the
+ *			       encoder chain
  * @bridge: bridge control structure
- * @mode: desired mode to be set for the bridge
- * @adjusted_mode: updated mode that works for this bridge
+ * @mode: desired mode to be set for the encoder chain
+ * @adjusted_mode: updated mode that works for this encoder chain
  *
  * Calls &drm_bridge_funcs.mode_set op for all the bridges in the
  * encoder chain, starting from the first bridge to the last.
  *
  * Note: the bridge passed should be the one closest to the encoder
  */
-void drm_bridge_mode_set(struct drm_bridge *bridge,
-			 const struct drm_display_mode *mode,
-			 const struct drm_display_mode *adjusted_mode)
+void drm_bridge_chain_mode_set(struct drm_bridge *bridge,
+			       const struct drm_display_mode *mode,
+			       const struct drm_display_mode *adjusted_mode)
 {
 	if (!bridge)
 		return;
@@ -303,13 +306,13 @@ void drm_bridge_mode_set(struct drm_bridge *bridge,
 	if (bridge->funcs->mode_set)
 		bridge->funcs->mode_set(bridge, mode, adjusted_mode);
 
-	drm_bridge_mode_set(bridge->next, mode, adjusted_mode);
+	drm_bridge_chain_mode_set(bridge->next, mode, adjusted_mode);
 }
-EXPORT_SYMBOL(drm_bridge_mode_set);
+EXPORT_SYMBOL(drm_bridge_chain_mode_set);
 
 /**
- * drm_bridge_pre_enable - prepares for enabling all
- *			   bridges in the encoder chain
+ * drm_bridge_chain_pre_enable - prepares for enabling all bridges in the
+ *				 encoder chain
  * @bridge: bridge control structure
  *
  * Calls &drm_bridge_funcs.pre_enable op for all the bridges in the encoder
@@ -318,20 +321,20 @@ EXPORT_SYMBOL(drm_bridge_mode_set);
  *
  * Note: the bridge passed should be the one closest to the encoder
  */
-void drm_bridge_pre_enable(struct drm_bridge *bridge)
+void drm_bridge_chain_pre_enable(struct drm_bridge *bridge)
 {
 	if (!bridge)
 		return;
 
-	drm_bridge_pre_enable(bridge->next);
+	drm_bridge_chain_pre_enable(bridge->next);
 
 	if (bridge->funcs->pre_enable)
 		bridge->funcs->pre_enable(bridge);
 }
-EXPORT_SYMBOL(drm_bridge_pre_enable);
+EXPORT_SYMBOL(drm_bridge_chain_pre_enable);
 
 /**
- * drm_bridge_enable - enables all bridges in the encoder chain
+ * drm_bridge_chain_enable - enables all bridges in the encoder chain
  * @bridge: bridge control structure
  *
  * Calls &drm_bridge_funcs.enable op for all the bridges in the encoder
@@ -340,7 +343,7 @@ EXPORT_SYMBOL(drm_bridge_pre_enable);
  *
  * Note that the bridge passed should be the one closest to the encoder
  */
-void drm_bridge_enable(struct drm_bridge *bridge)
+void drm_bridge_chain_enable(struct drm_bridge *bridge)
 {
 	if (!bridge)
 		return;
@@ -348,12 +351,12 @@ void drm_bridge_enable(struct drm_bridge *bridge)
 	if (bridge->funcs->enable)
 		bridge->funcs->enable(bridge);
 
-	drm_bridge_enable(bridge->next);
+	drm_bridge_chain_enable(bridge->next);
 }
-EXPORT_SYMBOL(drm_bridge_enable);
+EXPORT_SYMBOL(drm_bridge_chain_enable);
 
 /**
- * drm_atomic_bridge_disable - disables all bridges in the encoder chain
+ * drm_atomic_bridge_chain_disable - disables all bridges in the encoder chain
  * @bridge: bridge control structure
  * @state: atomic state being committed
  *
@@ -364,24 +367,24 @@ EXPORT_SYMBOL(drm_bridge_enable);
  *
  * Note: the bridge passed should be the one closest to the encoder
  */
-void drm_atomic_bridge_disable(struct drm_bridge *bridge,
-			       struct drm_atomic_state *state)
+void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge,
+				     struct drm_atomic_state *state)
 {
 	if (!bridge)
 		return;
 
-	drm_atomic_bridge_disable(bridge->next, state);
+	drm_atomic_bridge_chain_disable(bridge->next, state);
 
 	if (bridge->funcs->atomic_disable)
 		bridge->funcs->atomic_disable(bridge, state);
 	else if (bridge->funcs->disable)
 		bridge->funcs->disable(bridge);
 }
-EXPORT_SYMBOL(drm_atomic_bridge_disable);
+EXPORT_SYMBOL(drm_atomic_bridge_chain_disable);
 
 /**
- * drm_atomic_bridge_post_disable - cleans up after disabling all bridges in the
- *				    encoder chain
+ * drm_atomic_bridge_chain_post_disable - cleans up after disabling all bridges
+ *					  in the encoder chain
  * @bridge: bridge control structure
  * @state: atomic state being committed
  *
@@ -392,8 +395,8 @@ EXPORT_SYMBOL(drm_atomic_bridge_disable);
  *
  * Note: the bridge passed should be the one closest to the encoder
  */
-void drm_atomic_bridge_post_disable(struct drm_bridge *bridge,
-				    struct drm_atomic_state *state)
+void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
+					  struct drm_atomic_state *state)
 {
 	if (!bridge)
 		return;
@@ -403,13 +406,13 @@ void drm_atomic_bridge_post_disable(struct drm_bridge *bridge,
 	else if (bridge->funcs->post_disable)
 		bridge->funcs->post_disable(bridge);
 
-	drm_atomic_bridge_post_disable(bridge->next, state);
+	drm_atomic_bridge_chain_post_disable(bridge->next, state);
 }
-EXPORT_SYMBOL(drm_atomic_bridge_post_disable);
+EXPORT_SYMBOL(drm_atomic_bridge_chain_post_disable);
 
 /**
- * drm_atomic_bridge_pre_enable - prepares for enabling all bridges in the
- *				  encoder chain
+ * drm_atomic_bridge_chain_pre_enable - prepares for enabling all bridges in
+ *					the encoder chain
  * @bridge: bridge control structure
  * @state: atomic state being committed
  *
@@ -420,23 +423,23 @@ EXPORT_SYMBOL(drm_atomic_bridge_post_disable);
  *
  * Note: the bridge passed should be the one closest to the encoder
  */
-void drm_atomic_bridge_pre_enable(struct drm_bridge *bridge,
-				  struct drm_atomic_state *state)
+void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge,
+					struct drm_atomic_state *state)
 {
 	if (!bridge)
 		return;
 
-	drm_atomic_bridge_pre_enable(bridge->next, state);
+	drm_atomic_bridge_chain_pre_enable(bridge->next, state);
 
 	if (bridge->funcs->atomic_pre_enable)
 		bridge->funcs->atomic_pre_enable(bridge, state);
 	else if (bridge->funcs->pre_enable)
 		bridge->funcs->pre_enable(bridge);
 }
-EXPORT_SYMBOL(drm_atomic_bridge_pre_enable);
+EXPORT_SYMBOL(drm_atomic_bridge_chain_pre_enable);
 
 /**
- * drm_atomic_bridge_enable - enables all bridges in the encoder chain
+ * drm_atomic_bridge_chain_enable - enables all bridges in the encoder chain
  * @bridge: bridge control structure
  * @state: atomic state being committed
  *
@@ -447,8 +450,8 @@ EXPORT_SYMBOL(drm_atomic_bridge_pre_enable);
  *
  * Note: the bridge passed should be the one closest to the encoder
  */
-void drm_atomic_bridge_enable(struct drm_bridge *bridge,
-			      struct drm_atomic_state *state)
+void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge,
+				    struct drm_atomic_state *state)
 {
 	if (!bridge)
 		return;
@@ -458,9 +461,9 @@ void drm_atomic_bridge_enable(struct drm_bridge *bridge,
 	else if (bridge->funcs->enable)
 		bridge->funcs->enable(bridge);
 
-	drm_atomic_bridge_enable(bridge->next, state);
+	drm_atomic_bridge_chain_enable(bridge->next, state);
 }
-EXPORT_SYMBOL(drm_atomic_bridge_enable);
+EXPORT_SYMBOL(drm_atomic_bridge_chain_enable);
 
 #ifdef CONFIG_OF
 /**
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index c80e33a84605..18cdf9b8fdb0 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -160,14 +160,14 @@ drm_encoder_disable(struct drm_encoder *encoder)
 	if (!encoder_funcs)
 		return;
 
-	drm_bridge_disable(&encoder->bridge);
+	drm_bridge_chain_disable(&encoder->bridge);
 
 	if (encoder_funcs->disable)
 		(*encoder_funcs->disable)(encoder);
 	else if (encoder_funcs->dpms)
 		(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
 
-	drm_bridge_post_disable(&encoder->bridge);
+	drm_bridge_chain_post_disable(&encoder->bridge);
 }
 
 static void __drm_helper_disable_unused_functions(struct drm_device *dev)
@@ -327,8 +327,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 		if (!encoder_funcs)
 			continue;
 
-		ret = drm_bridge_mode_fixup(&encoder->bridge, mode,
-					    adjusted_mode);
+		ret = drm_bridge_chain_mode_fixup(&encoder->bridge, mode,
+						  adjusted_mode);
 		if (!ret) {
 			DRM_DEBUG_KMS("Bridge fixup failed\n");
 			goto done;
@@ -365,13 +365,13 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 		if (!encoder_funcs)
 			continue;
 
-		drm_bridge_disable(&encoder->bridge);
+		drm_bridge_chain_disable(&encoder->bridge);
 
 		/* Disable the encoders as the first thing we do. */
 		if (encoder_funcs->prepare)
 			encoder_funcs->prepare(encoder);
 
-		drm_bridge_post_disable(&encoder->bridge);
+		drm_bridge_chain_post_disable(&encoder->bridge);
 	}
 
 	drm_crtc_prepare_encoders(dev);
@@ -399,7 +399,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 		if (encoder_funcs->mode_set)
 			encoder_funcs->mode_set(encoder, mode, adjusted_mode);
 
-		drm_bridge_mode_set(&encoder->bridge, mode, adjusted_mode);
+		drm_bridge_chain_mode_set(&encoder->bridge, mode,
+					  adjusted_mode);
 	}
 
 	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
@@ -414,12 +415,12 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 		if (!encoder_funcs)
 			continue;
 
-		drm_bridge_pre_enable(&encoder->bridge);
+		drm_bridge_chain_pre_enable(&encoder->bridge);
 
 		if (encoder_funcs->commit)
 			encoder_funcs->commit(encoder);
 
-		drm_bridge_enable(&encoder->bridge);
+		drm_bridge_chain_enable(&encoder->bridge);
 	}
 
 	/* Calculate and store various constants which
@@ -818,7 +819,6 @@ static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder)
 /* Helper which handles bridge ordering around encoder dpms */
 static void drm_helper_encoder_dpms(struct drm_encoder *encoder, int mode)
 {
-	struct drm_bridge *bridge = &encoder->bridge;
 	const struct drm_encoder_helper_funcs *encoder_funcs;
 
 	encoder_funcs = encoder->helper_private;
@@ -826,17 +826,17 @@ static void drm_helper_encoder_dpms(struct drm_encoder *encoder, int mode)
 		return;
 
 	if (mode == DRM_MODE_DPMS_ON)
-		drm_bridge_pre_enable(bridge);
+		drm_bridge_chain_pre_enable(&encoder->bridge);
 	else
-		drm_bridge_disable(bridge);
+		drm_bridge_chain_disable(&encoder->bridge);
 
 	if (encoder_funcs->dpms)
 		encoder_funcs->dpms(encoder, mode);
 
 	if (mode == DRM_MODE_DPMS_ON)
-		drm_bridge_enable(bridge);
+		drm_bridge_chain_enable(&encoder->bridge);
 	else
-		drm_bridge_post_disable(bridge);
+		drm_bridge_chain_post_disable(&encoder->bridge);
 }
 
 static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index e4af2f9fa372..a5c49b1bef2d 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -113,7 +113,7 @@ drm_mode_validate_pipeline(struct drm_display_mode *mode,
 			continue;
 		}
 
-		ret = drm_bridge_mode_valid(&encoder->bridge, mode);
+		ret = drm_bridge_chain_mode_valid(&encoder->bridge, mode);
 		if (ret != MODE_OK) {
 			/* There is also no point in continuing for crtc check
 			 * here. */
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index c79b1f855d89..ea68b5adccbe 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -1247,8 +1247,8 @@ static int mtk_hdmi_conn_mode_valid(struct drm_connector *conn,
 		struct drm_display_mode adjusted_mode;
 
 		drm_mode_copy(&adjusted_mode, mode);
-		if (!drm_bridge_mode_fixup(hdmi->bridge.next, mode,
-					   &adjusted_mode))
+		if (!drm_bridge_chain_mode_fixup(hdmi->bridge.next, mode,
+						 &adjusted_mode))
 			return MODE_BAD;
 	}
 
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 7616f6562fe4..442a0654e1bf 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -254,9 +254,10 @@ struct drm_bridge_funcs {
 	 * there is one) when this callback is called.
 	 *
 	 * Note that this function will only be invoked in the context of an
-	 * atomic commit. It will not be invoked from &drm_bridge_pre_enable. It
-	 * would be prudent to also provide an implementation of @pre_enable if
-	 * you are expecting driver calls into &drm_bridge_pre_enable.
+	 * atomic commit. It will not be invoked from
+	 * &drm_bridge_chain_pre_enable. It would be prudent to also provide an
+	 * implementation of @pre_enable if you are expecting driver calls into
+	 * &drm_bridge_chain_pre_enable.
 	 *
 	 * The @atomic_pre_enable callback is optional.
 	 */
@@ -279,9 +280,9 @@ struct drm_bridge_funcs {
 	 * chain if there is one.
 	 *
 	 * Note that this function will only be invoked in the context of an
-	 * atomic commit. It will not be invoked from &drm_bridge_enable. It
-	 * would be prudent to also provide an implementation of @enable if
-	 * you are expecting driver calls into &drm_bridge_enable.
+	 * atomic commit. It will not be invoked from &drm_bridge_chain_enable.
+	 * It would be prudent to also provide an implementation of @enable if
+	 * you are expecting driver calls into &drm_bridge_chain_enable.
 	 *
 	 * The enable callback is optional.
 	 */
@@ -301,9 +302,10 @@ struct drm_bridge_funcs {
 	 * signals) feeding it is still running when this callback is called.
 	 *
 	 * Note that this function will only be invoked in the context of an
-	 * atomic commit. It will not be invoked from &drm_bridge_disable. It
-	 * would be prudent to also provide an implementation of @disable if
-	 * you are expecting driver calls into &drm_bridge_disable.
+	 * atomic commit. It will not be invoked from
+	 * &drm_bridge_chain_disable. It would be prudent to also provide an
+	 * implementation of @disable if you are expecting driver calls into
+	 * &drm_bridge_chain_disable.
 	 *
 	 * The disable callback is optional.
 	 */
@@ -325,10 +327,11 @@ struct drm_bridge_funcs {
 	 * called.
 	 *
 	 * Note that this function will only be invoked in the context of an
-	 * atomic commit. It will not be invoked from &drm_bridge_post_disable.
+	 * atomic commit. It will not be invoked from
+	 * &drm_bridge_chain_post_disable.
 	 * It would be prudent to also provide an implementation of
 	 * @post_disable if you are expecting driver calls into
-	 * &drm_bridge_post_disable.
+	 * &drm_bridge_chain_post_disable.
 	 *
 	 * The post_disable callback is optional.
 	 */
@@ -406,27 +409,28 @@ 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);
 
-bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
-			   const struct drm_display_mode *mode,
-			   struct drm_display_mode *adjusted_mode);
-enum drm_mode_status drm_bridge_mode_valid(struct drm_bridge *bridge,
-					   const struct drm_display_mode *mode);
-void drm_bridge_disable(struct drm_bridge *bridge);
-void drm_bridge_post_disable(struct drm_bridge *bridge);
-void drm_bridge_mode_set(struct drm_bridge *bridge,
-			 const struct drm_display_mode *mode,
-			 const struct drm_display_mode *adjusted_mode);
-void drm_bridge_pre_enable(struct drm_bridge *bridge);
-void drm_bridge_enable(struct drm_bridge *bridge);
+bool drm_bridge_chain_mode_fixup(struct drm_bridge *bridge,
+				 const struct drm_display_mode *mode,
+				 struct drm_display_mode *adjusted_mode);
+enum drm_mode_status
+drm_bridge_chain_mode_valid(struct drm_bridge *bridge,
+			    const struct drm_display_mode *mode);
+void drm_bridge_chain_disable(struct drm_bridge *bridge);
+void drm_bridge_chain_post_disable(struct drm_bridge *bridge);
+void drm_bridge_chain_mode_set(struct drm_bridge *bridge,
+			       const struct drm_display_mode *mode,
+			       const struct drm_display_mode *adjusted_mode);
+void drm_bridge_chain_pre_enable(struct drm_bridge *bridge);
+void drm_bridge_chain_enable(struct drm_bridge *bridge);
 
-void drm_atomic_bridge_disable(struct drm_bridge *bridge,
-			       struct drm_atomic_state *state);
-void drm_atomic_bridge_post_disable(struct drm_bridge *bridge,
+void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge,
+				     struct drm_atomic_state *state);
+void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
+					  struct drm_atomic_state *state);
+void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge,
+					struct drm_atomic_state *state);
+void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge,
 				    struct drm_atomic_state *state);
-void drm_atomic_bridge_pre_enable(struct drm_bridge *bridge,
-				  struct drm_atomic_state *state);
-void drm_atomic_bridge_enable(struct drm_bridge *bridge,
-			      struct drm_atomic_state *state);
 
 #ifdef CONFIG_DRM_PANEL_BRIDGE
 struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
-- 
2.21.0

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

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

* [PATCH v2 08/21] drm/msm: Use drm_attach_bridge() to attach a bridge to an encoder
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
                   ` (6 preceding siblings ...)
  2019-08-26 15:26 ` [PATCH v2 07/21] drm/bridge: Rename bridge helpers targeting a bridge chain Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  2019-08-28 15:22   ` Sean Paul
  2019-08-26 15:26 ` [PATCH v2 09/21] drm/bridge: Introduce drm_bridge_chain_get_next_bridge() Boris Brezillon
                   ` (12 subsequent siblings)
  20 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

This is part of our attempt to make the bridge chain a double-linked
list based on the generic list helpers. In order to do that, we must
patch all drivers manipulating the encoder->bridge field directly.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes in v2:
* Add Laurent and Sam R-b (waiting for a R-b from a drm/msm maintainer
  now)
---
 drivers/gpu/drm/msm/edp/edp.c   | 4 +++-
 drivers/gpu/drm/msm/hdmi/hdmi.c | 4 +++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c
index b54559a79d36..ad4e963ccd9b 100644
--- a/drivers/gpu/drm/msm/edp/edp.c
+++ b/drivers/gpu/drm/msm/edp/edp.c
@@ -178,7 +178,9 @@ int msm_edp_modeset_init(struct msm_edp *edp, struct drm_device *dev,
 		goto fail;
 	}
 
-	encoder->bridge.next = edp->bridge;
+	ret = drm_bridge_attach(encoder, edp->bridge, NULL);
+	if (ret)
+		goto fail;
 
 	priv->bridges[priv->num_bridges++]       = edp->bridge;
 	priv->connectors[priv->num_connectors++] = edp->connector;
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 9d94a88dd8d6..55b9a8c8312b 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -327,7 +327,9 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
 		goto fail;
 	}
 
-	encoder->bridge.next = hdmi->bridge;
+	ret = drm_bridge_attach(encoder, hdmi->bridge, NULL);
+	if (ret)
+		goto fail;
 
 	priv->bridges[priv->num_bridges++]       = hdmi->bridge;
 	priv->connectors[priv->num_connectors++] = hdmi->connector;
-- 
2.21.0

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

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

* [PATCH v2 09/21] drm/bridge: Introduce drm_bridge_chain_get_next_bridge()
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
                   ` (7 preceding siblings ...)
  2019-08-26 15:26 ` [PATCH v2 08/21] drm/msm: Use drm_attach_bridge() to attach a bridge to an encoder Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  2019-08-27  7:19   ` Neil Armstrong
  2019-08-26 15:26 ` [PATCH v2 10/21] drm/bridge: Make the bridge chain a double-linked list Boris Brezillon
                   ` (11 subsequent siblings)
  20 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

And use it in drivers accessing the bridge->next field directly.
This is part of our attempt to make the bridge chain a double-linked list
based on the generic list helpers.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
Changes in v2:
* Kill the last/first helpers (they're not really needed)
* Drop the !bridge || !bridge->encoder test
---
 drivers/gpu/drm/drm_bridge.c           | 14 ++++++++++++++
 drivers/gpu/drm/mediatek/mtk_hdmi.c    |  6 ++++--
 drivers/gpu/drm/msm/edp/edp_bridge.c   | 10 ++++++++--
 drivers/gpu/drm/omapdrm/omap_drv.c     |  4 ++--
 drivers/gpu/drm/omapdrm/omap_encoder.c |  3 ++-
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 10 +++++++---
 drivers/gpu/drm/vc4/vc4_dsi.c          |  4 +++-
 include/drm/drm_bridge.h               |  2 ++
 8 files changed, 42 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 52f1263530b7..3d9a6c6a7d4e 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -160,6 +160,20 @@ void drm_bridge_detach(struct drm_bridge *bridge)
 	bridge->dev = NULL;
 }
 
+/**
+ * drm_bridge_chain_get_next_bridge() - Get the next bridge in the chain
+ * @bridge: bridge object
+ *
+ * RETURNS:
+ * the next bridge in the chain, or NULL if @bridge is the last.
+ */
+struct drm_bridge *
+drm_bridge_chain_get_next_bridge(struct drm_bridge *bridge)
+{
+	return bridge->next;
+}
+EXPORT_SYMBOL(drm_bridge_chain_get_next_bridge);
+
 /**
  * DOC: bridge callbacks
  *
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index ea68b5adccbe..cfaa5aab8876 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -1238,16 +1238,18 @@ static int mtk_hdmi_conn_mode_valid(struct drm_connector *conn,
 				    struct drm_display_mode *mode)
 {
 	struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn);
+	struct drm_bridge *next_bridge;
 
 	dev_dbg(hdmi->dev, "xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
 		mode->hdisplay, mode->vdisplay, mode->vrefresh,
 		!!(mode->flags & DRM_MODE_FLAG_INTERLACE), mode->clock * 1000);
 
-	if (hdmi->bridge.next) {
+	next_bridge = drm_bridge_chain_get_next_bridge(&hdmi->bridge);
+	if (next_bridge) {
 		struct drm_display_mode adjusted_mode;
 
 		drm_mode_copy(&adjusted_mode, mode);
-		if (!drm_bridge_chain_mode_fixup(hdmi->bridge.next, mode,
+		if (!drm_bridge_chain_mode_fixup(next_bridge, mode,
 						 &adjusted_mode))
 			return MODE_BAD;
 	}
diff --git a/drivers/gpu/drm/msm/edp/edp_bridge.c b/drivers/gpu/drm/msm/edp/edp_bridge.c
index 446acca110e9..772408c94643 100644
--- a/drivers/gpu/drm/msm/edp/edp_bridge.c
+++ b/drivers/gpu/drm/msm/edp/edp_bridge.c
@@ -55,8 +55,14 @@ static void edp_bridge_mode_set(struct drm_bridge *bridge,
 	DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode));
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		if ((connector->encoder != NULL) &&
-			(connector->encoder->bridge.next == bridge)) {
+		struct drm_encoder *encoder = connector->encoder;
+		struct drm_bridge *first_bridge;
+
+		if (!encoder)
+			continue;
+
+		first_bridge = drm_bridge_chain_get_next_bridge(&encoder->bridge);
+		if (bridge == first_bridge) {
 			msm_edp_ctrl_timing_cfg(edp->ctrl,
 				adjusted_mode, &connector->display_info);
 			break;
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 224ec6fdc800..ba59881bcf3f 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -217,8 +217,8 @@ static int omap_display_id(struct omap_dss_device *output)
 	} else if (output->bridge) {
 		struct drm_bridge *bridge = output->bridge;
 
-		while (bridge->next)
-			bridge = bridge->next;
+		while (drm_bridge_chain_get_next_bridge(bridge))
+			bridge = drm_bridge_chain_get_next_bridge(bridge);
 
 		node = bridge->of_node;
 	} else if (output->panel) {
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
index 24bbe9f2a32e..8ca54081997e 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -126,7 +126,8 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
 	for (dssdev = output; dssdev; dssdev = dssdev->next)
 		omap_encoder_update_videomode_flags(&vm, dssdev->bus_flags);
 
-	for (bridge = output->bridge; bridge; bridge = bridge->next) {
+	for (bridge = output->bridge; bridge;
+	     bridge = drm_bridge_chain_get_next_bridge(bridge)) {
 		if (!bridge->timings)
 			continue;
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 1bd748202946..bcccdccd2878 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -14,6 +14,7 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_device.h>
 #include <drm/drm_fb_cma_helper.h>
@@ -680,9 +681,10 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
 			rcdu->encoders[RCAR_DU_OUTPUT_LVDS0 + rcrtc->index];
 		const struct drm_display_mode *mode =
 			&crtc->state->adjusted_mode;
+		struct drm_bridge *bridge;
 
-		rcar_lvds_clk_enable(encoder->base.bridge.next,
-				     mode->clock * 1000);
+		bridge = drm_bridge_chain_get_next_bridge(&encoder->base.bridge);
+		rcar_lvds_clk_enable(bridge, mode->clock * 1000);
 	}
 
 	rcar_du_crtc_start(rcrtc);
@@ -702,12 +704,14 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
 	    rstate->outputs == BIT(RCAR_DU_OUTPUT_DPAD0)) {
 		struct rcar_du_encoder *encoder =
 			rcdu->encoders[RCAR_DU_OUTPUT_LVDS0 + rcrtc->index];
+		struct drm_bridge *bridge;
 
 		/*
 		 * Disable the LVDS clock output, see
 		 * rcar_du_crtc_atomic_enable().
 		 */
-		rcar_lvds_clk_disable(encoder->base.bridge.next);
+		bridge = drm_bridge_chain_get_next_bridge(&encoder->base.bridge);
+		rcar_lvds_clk_disable(bridge);
 	}
 
 	spin_lock_irq(&crtc->dev->event_lock);
diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
index 4aa4c1a94f17..4ea352567cfb 100644
--- a/drivers/gpu/drm/vc4/vc4_dsi.c
+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
@@ -1636,8 +1636,10 @@ static void vc4_dsi_unbind(struct device *dev, struct device *master,
 	struct drm_device *drm = dev_get_drvdata(master);
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	struct vc4_dsi *dsi = dev_get_drvdata(dev);
+	struct drm_bridge *bridge;
 
-	if (dsi->encoder->bridge.next)
+	bridge = drm_bridge_chain_get_next_bridge(&dsi->encoder->bridge);
+	if (bridge)
 		pm_runtime_disable(dev);
 
 	vc4_dsi_encoder_destroy(dsi->encoder);
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 442a0654e1bf..7809fca99b2d 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -409,6 +409,8 @@ 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 *
+drm_bridge_chain_get_next_bridge(struct drm_bridge *bridge);
 bool drm_bridge_chain_mode_fixup(struct drm_bridge *bridge,
 				 const struct drm_display_mode *mode,
 				 struct drm_display_mode *adjusted_mode);
-- 
2.21.0

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

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

* [PATCH v2 10/21] drm/bridge: Make the bridge chain a double-linked list
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
                   ` (8 preceding siblings ...)
  2019-08-26 15:26 ` [PATCH v2 09/21] drm/bridge: Introduce drm_bridge_chain_get_next_bridge() Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  2019-08-26 15:26 ` [PATCH v2 11/21] drm/bridge: Add the drm_for_each_bridge_in_chain() helper Boris Brezillon
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

So that each element in the chain can easily access its predecessor.
This will be needed to support bus format negotiation between elements
of the bridge chain.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
Changes in v2:
* Adjust things to the "dummy encoder bridge" change (patch 2 in this
  series)
---
 drivers/gpu/drm/drm_bridge.c  | 177 ++++++++++++++++++----------------
 drivers/gpu/drm/drm_encoder.c |   6 +-
 include/drm/drm_bridge.h      |   4 +-
 include/drm/drm_encoder.h     |   7 ++
 4 files changed, 107 insertions(+), 87 deletions(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 3d9a6c6a7d4e..695ad67d33a5 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -55,7 +55,7 @@
  * just provide additional hooks to get the desired output at the end of the
  * encoder chain.
  *
- * Bridges can also be chained up using the &drm_bridge.next pointer.
+ * Bridges can also be chained up using the &drm_bridge.chain_node field.
  *
  * Both legacy CRTC helpers and the new atomic modeset helpers support bridges.
  */
@@ -114,6 +114,7 @@ EXPORT_SYMBOL(drm_bridge_remove);
 int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
 		      struct drm_bridge *previous)
 {
+	LIST_HEAD(tmp_list);
 	int ret;
 
 	if (!encoder || !bridge)
@@ -127,6 +128,7 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
 
 	bridge->dev = encoder->dev;
 	bridge->encoder = encoder;
+	list_add_tail(&bridge->chain_node, &tmp_list);
 
 	if (bridge->funcs->attach) {
 		ret = bridge->funcs->attach(bridge);
@@ -137,10 +139,12 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
 		}
 	}
 
-	if (previous)
-		previous->next = bridge;
-	else if (bridge != &encoder->bridge)
-		encoder->bridge.next = bridge;
+	if (bridge == &encoder->bridge)
+		list_splice(&tmp_list, &encoder->bridge_chain);
+	else if (!previous)
+		list_splice(&tmp_list, &encoder->bridge.chain_node);
+	else
+		list_splice(&tmp_list, &previous->chain_node);
 
 	return 0;
 }
@@ -157,6 +161,7 @@ void drm_bridge_detach(struct drm_bridge *bridge)
 	if (bridge->funcs->detach)
 		bridge->funcs->detach(bridge);
 
+	list_del(&bridge->chain_node);
 	bridge->dev = NULL;
 }
 
@@ -170,7 +175,10 @@ void drm_bridge_detach(struct drm_bridge *bridge)
 struct drm_bridge *
 drm_bridge_chain_get_next_bridge(struct drm_bridge *bridge)
 {
-	return bridge->next;
+	if (list_is_last(&bridge->chain_node, &bridge->encoder->bridge_chain))
+		return NULL;
+
+	return list_next_entry(bridge, chain_node);
 }
 EXPORT_SYMBOL(drm_bridge_chain_get_next_bridge);
 
@@ -204,18 +212,17 @@ bool drm_bridge_chain_mode_fixup(struct drm_bridge *bridge,
 				 const struct drm_display_mode *mode,
 				 struct drm_display_mode *adjusted_mode)
 {
-	bool ret = true;
+	struct drm_encoder *encoder = bridge->encoder;
 
-	if (!bridge)
-		return true;
+	list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
+		if (!bridge->funcs->mode_fixup)
+			continue;
 
-	if (bridge->funcs->mode_fixup)
-		ret = bridge->funcs->mode_fixup(bridge, mode, adjusted_mode);
+		if (!bridge->funcs->mode_fixup(bridge, mode, adjusted_mode))
+			return false;
+	}
 
-	ret = ret && drm_bridge_chain_mode_fixup(bridge->next, mode,
-						 adjusted_mode);
-
-	return ret;
+	return true;
 }
 EXPORT_SYMBOL(drm_bridge_chain_mode_fixup);
 
@@ -238,18 +245,20 @@ enum drm_mode_status
 drm_bridge_chain_mode_valid(struct drm_bridge *bridge,
 			    const struct drm_display_mode *mode)
 {
-	enum drm_mode_status ret = MODE_OK;
+	struct drm_encoder *encoder = bridge->encoder;
 
-	if (!bridge)
-		return ret;
+	list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
+		enum drm_mode_status ret;
+
+		if (!bridge->funcs->mode_valid)
+			continue;
 
-	if (bridge->funcs->mode_valid)
 		ret = bridge->funcs->mode_valid(bridge, mode);
+		if (ret != MODE_OK)
+			return ret;
+	}
 
-	if (ret != MODE_OK)
-		return ret;
-
-	return drm_bridge_chain_mode_valid(bridge->next, mode);
+	return MODE_OK;
 }
 EXPORT_SYMBOL(drm_bridge_chain_mode_valid);
 
@@ -265,13 +274,16 @@ EXPORT_SYMBOL(drm_bridge_chain_mode_valid);
  */
 void drm_bridge_chain_disable(struct drm_bridge *bridge)
 {
-	if (!bridge)
-		return;
+	struct drm_encoder *encoder = bridge->encoder;
+	struct drm_bridge *iter;
 
-	drm_bridge_chain_disable(bridge->next);
+	list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
+		if (iter->funcs->disable)
+			iter->funcs->disable(iter);
 
-	if (bridge->funcs->disable)
-		bridge->funcs->disable(bridge);
+		if (iter == bridge)
+			break;
+	}
 }
 EXPORT_SYMBOL(drm_bridge_chain_disable);
 
@@ -288,13 +300,12 @@ EXPORT_SYMBOL(drm_bridge_chain_disable);
  */
 void drm_bridge_chain_post_disable(struct drm_bridge *bridge)
 {
-	if (!bridge)
-		return;
+	struct drm_encoder *encoder = bridge->encoder;
 
-	if (bridge->funcs->post_disable)
-		bridge->funcs->post_disable(bridge);
-
-	drm_bridge_chain_post_disable(bridge->next);
+	list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
+		if (bridge->funcs->post_disable)
+			bridge->funcs->post_disable(bridge);
+	}
 }
 EXPORT_SYMBOL(drm_bridge_chain_post_disable);
 
@@ -314,13 +325,12 @@ void drm_bridge_chain_mode_set(struct drm_bridge *bridge,
 			       const struct drm_display_mode *mode,
 			       const struct drm_display_mode *adjusted_mode)
 {
-	if (!bridge)
-		return;
+	struct drm_encoder *encoder = bridge->encoder;
 
-	if (bridge->funcs->mode_set)
-		bridge->funcs->mode_set(bridge, mode, adjusted_mode);
-
-	drm_bridge_chain_mode_set(bridge->next, mode, adjusted_mode);
+	list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
+		if (bridge->funcs->mode_set)
+			bridge->funcs->mode_set(bridge, mode, adjusted_mode);
+	}
 }
 EXPORT_SYMBOL(drm_bridge_chain_mode_set);
 
@@ -337,13 +347,13 @@ EXPORT_SYMBOL(drm_bridge_chain_mode_set);
  */
 void drm_bridge_chain_pre_enable(struct drm_bridge *bridge)
 {
-	if (!bridge)
-		return;
+	struct drm_encoder *encoder = bridge->encoder;
+	struct drm_bridge *iter;
 
-	drm_bridge_chain_pre_enable(bridge->next);
-
-	if (bridge->funcs->pre_enable)
-		bridge->funcs->pre_enable(bridge);
+	list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
+		if (iter->funcs->pre_enable)
+			iter->funcs->pre_enable(iter);
+	}
 }
 EXPORT_SYMBOL(drm_bridge_chain_pre_enable);
 
@@ -359,13 +369,12 @@ EXPORT_SYMBOL(drm_bridge_chain_pre_enable);
  */
 void drm_bridge_chain_enable(struct drm_bridge *bridge)
 {
-	if (!bridge)
-		return;
+	struct drm_encoder *encoder = bridge->encoder;
 
-	if (bridge->funcs->enable)
-		bridge->funcs->enable(bridge);
-
-	drm_bridge_chain_enable(bridge->next);
+	list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
+		if (bridge->funcs->enable)
+			bridge->funcs->enable(bridge);
+	}
 }
 EXPORT_SYMBOL(drm_bridge_chain_enable);
 
@@ -384,15 +393,18 @@ EXPORT_SYMBOL(drm_bridge_chain_enable);
 void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge,
 				     struct drm_atomic_state *state)
 {
-	if (!bridge)
-		return;
+	struct drm_encoder *encoder = bridge->encoder;
+	struct drm_bridge *iter;
 
-	drm_atomic_bridge_chain_disable(bridge->next, state);
+	list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
+		if (iter->funcs->atomic_disable)
+			iter->funcs->atomic_disable(iter, state);
+		else if (iter->funcs->disable)
+			iter->funcs->disable(iter);
 
-	if (bridge->funcs->atomic_disable)
-		bridge->funcs->atomic_disable(bridge, state);
-	else if (bridge->funcs->disable)
-		bridge->funcs->disable(bridge);
+		if (iter == bridge)
+			break;
+	}
 }
 EXPORT_SYMBOL(drm_atomic_bridge_chain_disable);
 
@@ -412,15 +424,14 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_disable);
 void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
 					  struct drm_atomic_state *state)
 {
-	if (!bridge)
-		return;
+	struct drm_encoder *encoder = bridge->encoder;
 
-	if (bridge->funcs->atomic_post_disable)
-		bridge->funcs->atomic_post_disable(bridge, state);
-	else if (bridge->funcs->post_disable)
-		bridge->funcs->post_disable(bridge);
-
-	drm_atomic_bridge_chain_post_disable(bridge->next, state);
+	list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
+		if (bridge->funcs->atomic_post_disable)
+			bridge->funcs->atomic_post_disable(bridge, state);
+		else if (bridge->funcs->post_disable)
+			bridge->funcs->post_disable(bridge);
+	}
 }
 EXPORT_SYMBOL(drm_atomic_bridge_chain_post_disable);
 
@@ -440,15 +451,18 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_post_disable);
 void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge,
 					struct drm_atomic_state *state)
 {
-	if (!bridge)
-		return;
+	struct drm_encoder *encoder = bridge->encoder;
+	struct drm_bridge *iter;
 
-	drm_atomic_bridge_chain_pre_enable(bridge->next, state);
+	list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
+		if (iter->funcs->atomic_pre_enable)
+			iter->funcs->atomic_pre_enable(iter, state);
+		else if (iter->funcs->pre_enable)
+			iter->funcs->pre_enable(iter);
 
-	if (bridge->funcs->atomic_pre_enable)
-		bridge->funcs->atomic_pre_enable(bridge, state);
-	else if (bridge->funcs->pre_enable)
-		bridge->funcs->pre_enable(bridge);
+		if (iter == bridge)
+			break;
+	}
 }
 EXPORT_SYMBOL(drm_atomic_bridge_chain_pre_enable);
 
@@ -467,15 +481,14 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_pre_enable);
 void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge,
 				    struct drm_atomic_state *state)
 {
-	if (!bridge)
-		return;
+	struct drm_encoder *encoder = bridge->encoder;
 
-	if (bridge->funcs->atomic_enable)
-		bridge->funcs->atomic_enable(bridge, state);
-	else if (bridge->funcs->enable)
-		bridge->funcs->enable(bridge);
-
-	drm_atomic_bridge_chain_enable(bridge->next, state);
+	list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
+		if (bridge->funcs->atomic_enable)
+			bridge->funcs->atomic_enable(bridge, state);
+		else if (bridge->funcs->enable)
+			bridge->funcs->enable(bridge);
+	}
 }
 EXPORT_SYMBOL(drm_atomic_bridge_chain_enable);
 
diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
index 686053bf41b9..9bf642c09c55 100644
--- a/drivers/gpu/drm/drm_encoder.c
+++ b/drivers/gpu/drm/drm_encoder.c
@@ -143,6 +143,7 @@ int drm_encoder_init(struct drm_device *dev,
 		goto out_put;
 	}
 
+	INIT_LIST_HEAD(&encoder->bridge_chain);
 	if (!encoder->bridge.funcs)
 		encoder->bridge.funcs = &dummy_bridge_funcs;
 
@@ -177,10 +178,9 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
 	 * the indices on the drm_encoder after us in the encoder_list.
 	 */
 
-	for (bridge = &encoder->bridge; bridge; bridge = next) {
-		next = bridge->next;
+	list_for_each_entry_safe(bridge, next, &encoder->bridge_chain,
+				 chain_node)
 		drm_bridge_detach(bridge);
-	}
 
 	drm_mode_object_unregister(dev, &encoder->base);
 	kfree(encoder->name);
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 7809fca99b2d..8af92f0a9541 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -383,8 +383,8 @@ struct drm_bridge {
 	struct drm_device *dev;
 	/** @encoder: encoder to which this bridge is connected */
 	struct drm_encoder *encoder;
-	/** @next: the next bridge in the encoder chain */
-	struct drm_bridge *next;
+	/** @chain_node: used to form a bridge chain */
+	struct list_head chain_node;
 #ifdef CONFIG_OF
 	/** @of_node: device node pointer to the bridge */
 	struct device_node *of_node;
diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
index 30d347c37402..b3374d045801 100644
--- a/include/drm/drm_encoder.h
+++ b/include/drm/drm_encoder.h
@@ -173,6 +173,13 @@ struct drm_encoder {
 	 */
 	struct drm_crtc *crtc;
 
+	/**
+	 * @bridge_chain: Bridges attached to this encoder. The first entry of
+	 * this list is always &drm_encoder.bridge. It may be followed by other
+	 * bridge entities.
+	 */
+	struct list_head bridge_chain;
+
 	/**
 	 * @bridge: Bridge representing our encoder. Other bridges might be
 	 * linked to this dummy bridge element to form an encoder chain.
-- 
2.21.0

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

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

* [PATCH v2 11/21] drm/bridge: Add the drm_for_each_bridge_in_chain() helper
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
                   ` (9 preceding siblings ...)
  2019-08-26 15:26 ` [PATCH v2 10/21] drm/bridge: Make the bridge chain a double-linked list Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  2019-08-27  7:26   ` Neil Armstrong
  2019-08-26 15:26 ` [PATCH v2 12/21] drm/bridge: Add a drm_bridge_state object Boris Brezillon
                   ` (9 subsequent siblings)
  20 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

To iterate over all bridges attached to a specific encoder.

Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
Changes in v2:
* New patch
---
 include/drm/drm_bridge.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 8af92f0a9541..cf05b30f2967 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -409,6 +409,17 @@ 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);
 
+/**
+ * for_each_bridge_in_chain() - Iterate over all bridges present in a chain
+ * @encoder: the encoder to iterate bridges on
+ * @bridge: a bridge pointer updated to point to the current bridge at each
+ *	    iteration
+ *
+ * Iterate over all bridges present in the bridge chain attached to @encoder.
+ */
+#define drm_for_each_bridge_in_chain(encoder, bridge)			\
+	list_for_each_entry(bridge, &(encoder)->bridge_chain, chain_node)
+
 struct drm_bridge *
 drm_bridge_chain_get_next_bridge(struct drm_bridge *bridge);
 bool drm_bridge_chain_mode_fixup(struct drm_bridge *bridge,
-- 
2.21.0

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

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

* [PATCH v2 12/21] drm/bridge: Add a drm_bridge_state object
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
                   ` (10 preceding siblings ...)
  2019-08-26 15:26 ` [PATCH v2 11/21] drm/bridge: Add the drm_for_each_bridge_in_chain() helper Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  2019-08-26 15:26 ` [PATCH v2 13/21] drm/bridge: Patch atomic hooks to take a drm_bridge_state Boris Brezillon
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

One of the last remaining objects to not have its atomic state.

This is being motivated by our attempt to support runtime bus-format
negotiation between elements of the bridge chain.
This patch just paves the road for such a feature by adding a new
drm_bridge_state object inheriting from drm_private_obj so we can
re-use some of the existing state initialization/tracking logic.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
Changes in v2:
* Use drm_for_each_bridge_in_chain()
* Rename helpers to be more consistent with the rest of the DRM API
* Improve/fix the doc
---
 drivers/gpu/drm/drm_atomic.c        |  39 +++++++
 drivers/gpu/drm/drm_atomic_helper.c |  20 ++++
 drivers/gpu/drm/drm_bridge.c        | 168 +++++++++++++++++++++++++++-
 include/drm/drm_atomic.h            |   3 +
 include/drm/drm_bridge.h            | 118 +++++++++++++++++++
 5 files changed, 343 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 419381abbdd1..6c249ce39380 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -30,6 +30,7 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_uapi.h>
+#include <drm/drm_bridge.h>
 #include <drm/drm_debugfs.h>
 #include <drm/drm_device.h>
 #include <drm/drm_drv.h>
@@ -1010,6 +1011,44 @@ static void drm_atomic_connector_print_state(struct drm_printer *p,
 		connector->funcs->atomic_print_state(p, state);
 }
 
+/**
+ * drm_atomic_add_encoder_bridges - add bridges attached to an encoder
+ * @state: atomic state
+ * @encoder: DRM encoder
+ *
+ * This function adds all bridges attached to @encoder. This is needed to add
+ * bridge states to @state and make them available when
+ * &bridge_funcs.atomic_{check,pre_enable,enable,disable_post_disable}() are
+ * called
+ *
+ * Returns:
+ * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
+ * then the w/w mutex code has detected a deadlock and the entire atomic
+ * sequence must be restarted. All other errors are fatal.
+ */
+int
+drm_atomic_add_encoder_bridges(struct drm_atomic_state *state,
+			       struct drm_encoder *encoder)
+{
+	struct drm_bridge_state *bridge_state;
+	struct drm_bridge *bridge;
+
+	if (!encoder)
+		return 0;
+
+	DRM_DEBUG_ATOMIC("Adding all bridges for [encoder:%d:%s] to %p\n",
+			 encoder->base.id, encoder->name, state);
+
+	drm_for_each_bridge_in_chain(encoder, bridge) {
+		bridge_state = drm_atomic_get_bridge_state(state, bridge);
+		if (IS_ERR(bridge_state))
+			return PTR_ERR(bridge_state);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_atomic_add_encoder_bridges);
+
 /**
  * drm_atomic_add_affected_connectors - add connectors for crtc
  * @state: atomic state
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index cccd9e3531c1..b3f59e757b30 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -736,6 +736,26 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
 			return ret;
 	}
 
+	/*
+	 * Iterate over all connectors again, and add all affected bridges to
+	 * the state.
+	 */
+	for_each_oldnew_connector_in_state(state, connector,
+					   old_connector_state,
+					   new_connector_state, i) {
+		struct drm_encoder *encoder;
+
+		encoder = old_connector_state->best_encoder;
+		ret = drm_atomic_add_encoder_bridges(state, encoder);
+		if (ret)
+			return ret;
+
+		encoder = new_connector_state->best_encoder;
+		ret = drm_atomic_add_encoder_bridges(state, encoder);
+		if (ret)
+			return ret;
+	}
+
 	ret = mode_valid(state);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 695ad67d33a5..6c2d7691455b 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 
+#include <drm/drm_atomic_state_helper.h>
 #include <drm/drm_bridge.h>
 #include <drm/drm_encoder.h>
 
@@ -89,6 +90,38 @@ void drm_bridge_remove(struct drm_bridge *bridge)
 }
 EXPORT_SYMBOL(drm_bridge_remove);
 
+static struct drm_private_state *
+drm_bridge_atomic_duplicate_priv_state(struct drm_private_obj *obj)
+{
+	struct drm_bridge *bridge = drm_priv_to_bridge(obj);
+	struct drm_bridge_state *state;
+
+	if (bridge->funcs->atomic_duplicate_state)
+		state = bridge->funcs->atomic_duplicate_state(bridge);
+	else
+		state = drm_atomic_helper_bridge_duplicate_state(bridge);
+
+	return &state->base;
+}
+
+static void
+drm_bridge_atomic_destroy_priv_state(struct drm_private_obj *obj,
+				     struct drm_private_state *s)
+{
+	struct drm_bridge_state *state = drm_priv_to_bridge_state(s);
+	struct drm_bridge *bridge = drm_priv_to_bridge(obj);
+
+	if (bridge->funcs->atomic_destroy_state)
+		bridge->funcs->atomic_destroy_state(bridge, state);
+	else
+		drm_atomic_helper_bridge_destroy_state(bridge, state);
+}
+
+static const struct drm_private_state_funcs drm_bridge_priv_state_funcs = {
+	.atomic_duplicate_state = drm_bridge_atomic_duplicate_priv_state,
+	.atomic_destroy_state = drm_bridge_atomic_destroy_priv_state,
+};
+
 /**
  * drm_bridge_attach - attach the bridge to an encoder's chain
  *
@@ -114,6 +147,7 @@ EXPORT_SYMBOL(drm_bridge_remove);
 int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
 		      struct drm_bridge *previous)
 {
+	struct drm_bridge_state *state;
 	LIST_HEAD(tmp_list);
 	int ret;
 
@@ -132,13 +166,24 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
 
 	if (bridge->funcs->attach) {
 		ret = bridge->funcs->attach(bridge);
-		if (ret < 0) {
-			bridge->dev = NULL;
-			bridge->encoder = NULL;
-			return ret;
-		}
+		if (ret < 0)
+			goto err_reset_bridge;
 	}
 
+	if (bridge->funcs->atomic_reset)
+		state = bridge->funcs->atomic_reset(bridge);
+	else
+		state = drm_atomic_helper_bridge_reset(bridge);
+
+	if (IS_ERR(state)) {
+		ret = PTR_ERR(state);
+		goto err_detach_bridge;
+	}
+
+	drm_atomic_private_obj_init(bridge->dev, &bridge->base,
+				    &state->base,
+				    &drm_bridge_priv_state_funcs);
+
 	if (bridge == &encoder->bridge)
 		list_splice(&tmp_list, &encoder->bridge_chain);
 	else if (!previous)
@@ -147,6 +192,15 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
 		list_splice(&tmp_list, &previous->chain_node);
 
 	return 0;
+
+err_detach_bridge:
+	if (bridge->funcs->detach)
+		bridge->funcs->detach(bridge);
+
+err_reset_bridge:
+	bridge->dev = NULL;
+	bridge->encoder = NULL;
+	return ret;
 }
 EXPORT_SYMBOL(drm_bridge_attach);
 
@@ -158,6 +212,8 @@ void drm_bridge_detach(struct drm_bridge *bridge)
 	if (WARN_ON(!bridge->dev))
 		return;
 
+	drm_atomic_private_obj_fini(&bridge->base);
+
 	if (bridge->funcs->detach)
 		bridge->funcs->detach(bridge);
 
@@ -492,6 +548,108 @@ void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge,
 }
 EXPORT_SYMBOL(drm_atomic_bridge_chain_enable);
 
+/**
+ * drm_atomic_helper_bridge_destroy_state() - Default destroy state helper
+ * @bridge: the bridge this state refers to
+ * @state: state object to destroy
+ *
+ * Just a simple kfree() for now.
+ */
+void drm_atomic_helper_bridge_destroy_state(struct drm_bridge *bridge,
+					    struct drm_bridge_state *state)
+{
+	kfree(state);
+}
+EXPORT_SYMBOL(drm_atomic_helper_bridge_destroy_state);
+
+/**
+ * __drm_atomic_helper_bridge_reset() - Initialize a bridge state to its
+ *					default
+ * @bridge: the bridge this state is refers to
+ * @state: bridge state to initialize
+ *
+ * For now it's just a memset(0) plus a state->bridge assignment. Might
+ * be extended in the future.
+ */
+void __drm_atomic_helper_bridge_reset(struct drm_bridge *bridge,
+				      struct drm_bridge_state *state)
+{
+	memset(state, 0, sizeof(*state));
+	state->bridge = bridge;
+}
+EXPORT_SYMBOL(__drm_atomic_helper_bridge_reset);
+
+/**
+ * drm_atomic_helper_bridge_reset() - default &drm_plane_funcs.reset hook for
+ *				      bridges
+ * @bridge: the bridge to reset state on
+ *
+ * Resets the atomic state for @bridge by freeing the state pointer (which
+ * might be NULL, e.g. at driver load time) and allocating a new empty state
+ * object.
+ *
+ * RETURNS:
+ * A valid drm_bridge_state object in case of success, an ERR_PTR()
+ * giving the reaon of the failure otherwise.
+ */
+struct drm_bridge_state *
+drm_atomic_helper_bridge_reset(struct drm_bridge *bridge)
+{
+	struct drm_bridge_state *bridge_state;
+
+	bridge_state = kzalloc(sizeof(*bridge_state), GFP_KERNEL);
+	if (!bridge_state)
+		return ERR_PTR(-ENOMEM);
+
+	__drm_atomic_helper_bridge_reset(bridge, bridge_state);
+	return bridge_state;
+}
+EXPORT_SYMBOL(drm_atomic_helper_bridge_reset);
+
+/**
+ * __drm_atomic_helper_bridge_duplicate_state() - Copy the content of the
+ *						  current bridge state into a
+ *						  new one
+ * @bridge: bridge element the old and new states are referring to
+ * @new: new bridge state to copy to
+ *
+ * Should be used by custom &drm_bridge_funcs.atomic_duplicate() implementation
+ * to copy the previous state into the new object.
+ */
+void __drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge,
+						struct drm_bridge_state *new)
+{
+	__drm_atomic_helper_private_obj_duplicate_state(&bridge->base,
+							&new->base);
+	new->bridge = bridge;
+}
+EXPORT_SYMBOL(__drm_atomic_helper_bridge_duplicate_state);
+
+/**
+ * drm_atomic_helper_duplicate_bridge_state() - Default duplicate state helper
+ * @bridge: bridge containing the state to duplicate
+ *
+ * Default implementation of &drm_bridge_funcs.atomic_duplicate().
+ *
+ * RETURNS:
+ * a valid state object or NULL if the allocation fails.
+ */
+struct drm_bridge_state *
+drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge)
+{
+	struct drm_bridge_state *new;
+
+	if (WARN_ON(!bridge->base.state))
+		return NULL;
+
+	new = kzalloc(sizeof(*new), GFP_KERNEL);
+	if (new)
+		__drm_atomic_helper_bridge_duplicate_state(bridge, new);
+
+	return new;
+}
+EXPORT_SYMBOL(drm_atomic_helper_bridge_duplicate_state);
+
 #ifdef CONFIG_OF
 /**
  * of_drm_find_bridge - find the bridge corresponding to the device node in
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 927e1205d7aa..1c0a08217712 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -660,6 +660,9 @@ __drm_atomic_get_current_plane_state(struct drm_atomic_state *state,
 	return plane->state;
 }
 
+int __must_check
+drm_atomic_add_encoder_bridges(struct drm_atomic_state *state,
+			       struct drm_encoder *encoder);
 int __must_check
 drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
 				   struct drm_crtc *crtc);
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index cf05b30f2967..11b20e2a9fc6 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -25,6 +25,7 @@
 
 #include <linux/list.h>
 #include <linux/ctype.h>
+#include <drm/drm_atomic.h>
 #include <drm/drm_mode_object.h>
 #include <drm/drm_modes.h>
 
@@ -32,6 +33,23 @@ struct drm_bridge;
 struct drm_bridge_timings;
 struct drm_panel;
 
+/**
+ * struct drm_bridge_state - Atomic bridge state object
+ * @base: inherit from &drm_private_state
+ * @bridge: the bridge this state refers to
+ */
+struct drm_bridge_state {
+	struct drm_private_state base;
+
+	struct drm_bridge *bridge;
+};
+
+static inline struct drm_bridge_state *
+drm_priv_to_bridge_state(struct drm_private_state *priv)
+{
+	return container_of(priv, struct drm_bridge_state, base);
+}
+
 /**
  * struct drm_bridge_funcs - drm_bridge control functions
  */
@@ -337,6 +355,48 @@ struct drm_bridge_funcs {
 	 */
 	void (*atomic_post_disable)(struct drm_bridge *bridge,
 				    struct drm_atomic_state *state);
+
+	/**
+	 * @atomic_duplicate_state:
+	 *
+	 * Duplicate the current bridge state object (which is guaranteed to be
+	 * non-NULL).
+	 *
+	 * The atomic_duplicate_state() is optional, the core falls back on
+	 * &drm_atomic_helper_bridge_duplicate_state() when not implemented.
+	 *
+	 * RETURNS:
+	 * A valid drm_bridge_state object or NULL if the allocation fails.
+	 */
+	struct drm_bridge_state *(*atomic_duplicate_state)(struct drm_bridge *bridge);
+
+	/**
+	 * @atomic_destroy_state:
+	 *
+	 * Destroy a bridge state object previously allocated by
+	 * &drm_bridge_funcs.atomic_duplicate_state().
+	 *
+	 * The atomic_destroy_state hook is optional, the coref falls back on
+	 * &drm_atomic_helper_bridge_destroy_state() when not implemented.
+	 */
+	void (*atomic_destroy_state)(struct drm_bridge *bridge,
+				     struct drm_bridge_state *state);
+
+	/**
+	 * @atomic_reset:
+	 *
+	 * Reset the bridge to a predefined state (or retrieve its current
+	 * state) and return a &drm_bridge_state object matching this state.
+	 * This function is called at attach time.
+	 *
+	 * The atomic_reset hook is optional, the core falls back on
+	 * &drm_atomic_helper_bridge_reset() when not implemented.
+	 *
+	 * RETURNS:
+	 * A valid drm_bridge_state object in case of success, an ERR_PTR()
+	 * giving the reaon of the failure otherwise.
+	 */
+	struct drm_bridge_state *(*atomic_reset)(struct drm_bridge *bridge);
 };
 
 /**
@@ -379,6 +439,8 @@ struct drm_bridge_timings {
  * struct drm_bridge - central DRM bridge control structure
  */
 struct drm_bridge {
+	/** @base: inherit from &drm_private_object */
+	struct drm_private_obj base;
 	/** @dev: DRM device this bridge belongs to */
 	struct drm_device *dev;
 	/** @encoder: encoder to which this bridge is connected */
@@ -403,6 +465,12 @@ struct drm_bridge {
 	void *driver_private;
 };
 
+static inline struct drm_bridge *
+drm_priv_to_bridge(struct drm_private_obj *priv)
+{
+	return container_of(priv, struct drm_bridge, base);
+}
+
 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);
@@ -445,6 +513,56 @@ void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge,
 void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge,
 				    struct drm_atomic_state *state);
 
+void __drm_atomic_helper_bridge_reset(struct drm_bridge *bridge,
+				      struct drm_bridge_state *state);
+struct drm_bridge_state *
+drm_atomic_helper_bridge_reset(struct drm_bridge *bridge);
+void drm_atomic_helper_bridge_destroy_state(struct drm_bridge *bridge,
+					    struct drm_bridge_state *state);
+void __drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge,
+						struct drm_bridge_state *new);
+struct drm_bridge_state *
+drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge);
+
+static inline struct drm_bridge_state *
+drm_atomic_get_bridge_state(struct drm_atomic_state *state,
+			    struct drm_bridge *bridge)
+{
+	struct drm_private_state *obj_state;
+
+	obj_state = drm_atomic_get_private_obj_state(state, &bridge->base);
+	if (!obj_state)
+		return NULL;
+
+	return drm_priv_to_bridge_state(obj_state);
+}
+
+static inline struct drm_bridge_state *
+drm_atomic_get_old_bridge_state(struct drm_atomic_state *state,
+				struct drm_bridge *bridge)
+{
+	struct drm_private_state *obj_state;
+
+	obj_state = drm_atomic_get_old_private_obj_state(state, &bridge->base);
+	if (!obj_state)
+		return NULL;
+
+	return drm_priv_to_bridge_state(obj_state);
+}
+
+static inline struct drm_bridge_state *
+drm_atomic_get_new_bridge_state(struct drm_atomic_state *state,
+				struct drm_bridge *bridge)
+{
+	struct drm_private_state *obj_state;
+
+	obj_state = drm_atomic_get_new_private_obj_state(state, &bridge->base);
+	if (!obj_state)
+		return NULL;
+
+	return drm_priv_to_bridge_state(obj_state);
+}
+
 #ifdef CONFIG_DRM_PANEL_BRIDGE
 struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel,
 					u32 connector_type);
-- 
2.21.0

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

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

* [PATCH v2 13/21] drm/bridge: Patch atomic hooks to take a drm_bridge_state
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
                   ` (11 preceding siblings ...)
  2019-08-26 15:26 ` [PATCH v2 12/21] drm/bridge: Add a drm_bridge_state object Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  2019-08-26 15:26 ` [PATCH v2 14/21] drm/bridge: Add an ->atomic_check() hook Boris Brezillon
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

Instead of a drm_atomic_state. The only driver implementing those hooks
is patched too.

While at it, adjust the documentation and argument names to clarify the
fact that the state being passed to those functions/hooks is the old
state.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
Changes in v2:
* Pass the old bridge state
---
 .../drm/bridge/analogix/analogix_dp_core.c    | 12 ++-
 drivers/gpu/drm/drm_bridge.c                  | 73 ++++++++++++++-----
 include/drm/drm_bridge.h                      | 23 ++++--
 3 files changed, 76 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index bb411fe52ae8..e438e757f2ce 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1290,8 +1290,9 @@ struct drm_crtc *analogix_dp_get_new_crtc(struct analogix_dp_device *dp,
 }
 
 static void analogix_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge,
-						 struct drm_atomic_state *state)
+						 struct drm_bridge_state *bstate)
 {
+	struct drm_atomic_state *state = bstate->base.state;
 	struct analogix_dp_device *dp = bridge->driver_private;
 	struct drm_crtc *crtc;
 	struct drm_crtc_state *old_crtc_state;
@@ -1367,8 +1368,9 @@ static int analogix_dp_set_bridge(struct analogix_dp_device *dp)
 }
 
 static void analogix_dp_bridge_atomic_enable(struct drm_bridge *bridge,
-					     struct drm_atomic_state *state)
+					     struct drm_bridge_state *bstate)
 {
+	struct drm_atomic_state *state = bstate->base.state;
 	struct analogix_dp_device *dp = bridge->driver_private;
 	struct drm_crtc *crtc;
 	struct drm_crtc_state *old_crtc_state;
@@ -1441,8 +1443,9 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge)
 }
 
 static void analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge,
-					      struct drm_atomic_state *state)
+					      struct drm_bridge_state *bstate)
 {
+	struct drm_atomic_state *state = bstate->base.state;
 	struct analogix_dp_device *dp = bridge->driver_private;
 	struct drm_crtc *crtc;
 	struct drm_crtc_state *new_crtc_state = NULL;
@@ -1465,8 +1468,9 @@ static void analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge,
 
 static
 void analogix_dp_bridge_atomic_post_disable(struct drm_bridge *bridge,
-					    struct drm_atomic_state *state)
+					    struct drm_bridge_state *bstate)
 {
+	struct drm_atomic_state *state = bstate->base.state;
 	struct analogix_dp_device *dp = bridge->driver_private;
 	struct drm_crtc *crtc;
 	struct drm_crtc_state *new_crtc_state;
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 6c2d7691455b..5c83cac7975e 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -437,7 +437,7 @@ EXPORT_SYMBOL(drm_bridge_chain_enable);
 /**
  * drm_atomic_bridge_chain_disable - disables all bridges in the encoder chain
  * @bridge: bridge control structure
- * @state: atomic state being committed
+ * @old_state: old atomic state
  *
  * Calls &drm_bridge_funcs.atomic_disable (falls back on
  * &drm_bridge_funcs.disable) op for all the bridges in the encoder chain,
@@ -447,16 +447,24 @@ EXPORT_SYMBOL(drm_bridge_chain_enable);
  * Note: the bridge passed should be the one closest to the encoder
  */
 void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge,
-				     struct drm_atomic_state *state)
+				     struct drm_atomic_state *old_state)
 {
 	struct drm_encoder *encoder = bridge->encoder;
 	struct drm_bridge *iter;
 
 	list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
-		if (iter->funcs->atomic_disable)
-			iter->funcs->atomic_disable(iter, state);
-		else if (iter->funcs->disable)
+		if (iter->funcs->atomic_disable) {
+			struct drm_bridge_state *bridge_state;
+
+			bridge_state = drm_atomic_get_old_bridge_state(old_state,
+								       iter);
+			if (WARN_ON(!bridge_state))
+				return;
+
+			iter->funcs->atomic_disable(iter, bridge_state);
+		} else if (iter->funcs->disable) {
 			iter->funcs->disable(iter);
+		}
 
 		if (iter == bridge)
 			break;
@@ -468,7 +476,7 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_disable);
  * drm_atomic_bridge_chain_post_disable - cleans up after disabling all bridges
  *					  in the encoder chain
  * @bridge: bridge control structure
- * @state: atomic state being committed
+ * @old_state: old atomic state
  *
  * Calls &drm_bridge_funcs.atomic_post_disable (falls back on
  * &drm_bridge_funcs.post_disable) op for all the bridges in the encoder chain,
@@ -478,15 +486,24 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_disable);
  * Note: the bridge passed should be the one closest to the encoder
  */
 void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
-					  struct drm_atomic_state *state)
+					  struct drm_atomic_state *old_state)
 {
 	struct drm_encoder *encoder = bridge->encoder;
 
 	list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
-		if (bridge->funcs->atomic_post_disable)
-			bridge->funcs->atomic_post_disable(bridge, state);
-		else if (bridge->funcs->post_disable)
+		if (bridge->funcs->atomic_post_disable) {
+			struct drm_bridge_state *bridge_state;
+
+			bridge_state = drm_atomic_get_old_bridge_state(old_state,
+								       bridge);
+			if (WARN_ON(!bridge_state))
+				return;
+
+			bridge->funcs->atomic_post_disable(bridge,
+							   bridge_state);
+		} else if (bridge->funcs->post_disable) {
 			bridge->funcs->post_disable(bridge);
+		}
 	}
 }
 EXPORT_SYMBOL(drm_atomic_bridge_chain_post_disable);
@@ -495,7 +512,7 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_post_disable);
  * drm_atomic_bridge_chain_pre_enable - prepares for enabling all bridges in
  *					the encoder chain
  * @bridge: bridge control structure
- * @state: atomic state being committed
+ * @old_state: old atomic state
  *
  * Calls &drm_bridge_funcs.atomic_pre_enable (falls back on
  * &drm_bridge_funcs.pre_enable) op for all the bridges in the encoder chain,
@@ -505,16 +522,24 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_post_disable);
  * Note: the bridge passed should be the one closest to the encoder
  */
 void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge,
-					struct drm_atomic_state *state)
+					struct drm_atomic_state *old_state)
 {
 	struct drm_encoder *encoder = bridge->encoder;
 	struct drm_bridge *iter;
 
 	list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
-		if (iter->funcs->atomic_pre_enable)
-			iter->funcs->atomic_pre_enable(iter, state);
-		else if (iter->funcs->pre_enable)
+		if (iter->funcs->atomic_pre_enable) {
+			struct drm_bridge_state *bridge_state;
+
+			bridge_state = drm_atomic_get_old_bridge_state(old_state,
+								       iter);
+			if (WARN_ON(!bridge_state))
+				return;
+
+			iter->funcs->atomic_pre_enable(iter, bridge_state);
+		} else if (iter->funcs->pre_enable) {
 			iter->funcs->pre_enable(iter);
+		}
 
 		if (iter == bridge)
 			break;
@@ -525,7 +550,7 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_pre_enable);
 /**
  * drm_atomic_bridge_chain_enable - enables all bridges in the encoder chain
  * @bridge: bridge control structure
- * @state: atomic state being committed
+ * @old_state: old atomic state
  *
  * Calls &drm_bridge_funcs.atomic_enable (falls back on
  * &drm_bridge_funcs.enable) op for all the bridges in the encoder chain,
@@ -535,15 +560,23 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_pre_enable);
  * Note: the bridge passed should be the one closest to the encoder
  */
 void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge,
-				    struct drm_atomic_state *state)
+				    struct drm_atomic_state *old_state)
 {
 	struct drm_encoder *encoder = bridge->encoder;
 
 	list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
-		if (bridge->funcs->atomic_enable)
-			bridge->funcs->atomic_enable(bridge, state);
-		else if (bridge->funcs->enable)
+		if (bridge->funcs->atomic_enable) {
+			struct drm_bridge_state *bridge_state;
+
+			bridge_state = drm_atomic_get_old_bridge_state(old_state,
+								       bridge);
+			if (WARN_ON(!bridge_state))
+				return;
+
+			bridge->funcs->atomic_enable(bridge, bridge_state);
+		} else if (bridge->funcs->enable) {
 			bridge->funcs->enable(bridge);
+		}
 	}
 }
 EXPORT_SYMBOL(drm_atomic_bridge_chain_enable);
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 11b20e2a9fc6..231f62cd681d 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -264,7 +264,8 @@ struct drm_bridge_funcs {
 	 * preceding element is a bridge this means it's called before that
 	 * bridge's @atomic_pre_enable or @pre_enable function. If the preceding
 	 * element is a &drm_encoder it's called right before the encoder's
-	 * &drm_encoder_helper_funcs.atomic_enable hook.
+	 * &drm_encoder_helper_funcs.atomic_enable hook. This hook is passed the
+	 * old bridge state (the new one can be retrieved from bridge->state).
 	 *
 	 * The display pipe (i.e. clocks and timing signals) feeding this bridge
 	 * will not yet be running when this callback is called. The bridge must
@@ -280,7 +281,7 @@ struct drm_bridge_funcs {
 	 * The @atomic_pre_enable callback is optional.
 	 */
 	void (*atomic_pre_enable)(struct drm_bridge *bridge,
-				  struct drm_atomic_state *state);
+				  struct drm_bridge_state *old_bridge_state);
 
 	/**
 	 * @atomic_enable:
@@ -290,7 +291,9 @@ struct drm_bridge_funcs {
 	 * preceding element is a bridge this means it's called after that
 	 * bridge's @atomic_enable or @enable function. If the preceding element
 	 * is a &drm_encoder it's called right after the encoder's
-	 * &drm_encoder_helper_funcs.atomic_enable hook.
+	 * &drm_encoder_helper_funcs.atomic_enable hook. This hook is passed
+	 * the old bridge state (the new one can be retrieved from
+	 * bridge->state).
 	 *
 	 * The bridge can assume that the display pipe (i.e. clocks and timing
 	 * signals) feeding it is running when this callback is called. This
@@ -305,7 +308,7 @@ struct drm_bridge_funcs {
 	 * The enable callback is optional.
 	 */
 	void (*atomic_enable)(struct drm_bridge *bridge,
-			      struct drm_atomic_state *state);
+			      struct drm_bridge_state *old_bridge_state);
 	/**
 	 * @atomic_disable:
 	 *
@@ -314,7 +317,9 @@ struct drm_bridge_funcs {
 	 * preceding element is a bridge this means it's called before that
 	 * bridge's @atomic_disable or @disable vfunc. If the preceding element
 	 * is a &drm_encoder it's called right before the
-	 * &drm_encoder_helper_funcs.atomic_disable hook.
+	 * &drm_encoder_helper_funcs.atomic_disable hook. This hook is passed
+	 * the old bridge state (the new one can be retrieved from
+	 * bridge->state).
 	 *
 	 * The bridge can assume that the display pipe (i.e. clocks and timing
 	 * signals) feeding it is still running when this callback is called.
@@ -328,7 +333,7 @@ struct drm_bridge_funcs {
 	 * The disable callback is optional.
 	 */
 	void (*atomic_disable)(struct drm_bridge *bridge,
-			       struct drm_atomic_state *state);
+			       struct drm_bridge_state *old_bridge_state);
 
 	/**
 	 * @atomic_post_disable:
@@ -338,7 +343,9 @@ struct drm_bridge_funcs {
 	 * element is a bridge this means it's called after that bridge's
 	 * @atomic_post_disable or @post_disable function. If the preceding
 	 * element is a &drm_encoder it's called right after the encoder's
-	 * &drm_encoder_helper_funcs.atomic_disable hook.
+	 * &drm_encoder_helper_funcs.atomic_disable hook. This hook is passed
+	 * the old bridge state (the new one can be retrieved from
+	 * bridge->state).
 	 *
 	 * The bridge must assume that the display pipe (i.e. clocks and timing
 	 * signals) feeding it is no longer running when this callback is
@@ -354,7 +361,7 @@ struct drm_bridge_funcs {
 	 * The post_disable callback is optional.
 	 */
 	void (*atomic_post_disable)(struct drm_bridge *bridge,
-				    struct drm_atomic_state *state);
+				    struct drm_bridge_state *old_bridge_state);
 
 	/**
 	 * @atomic_duplicate_state:
-- 
2.21.0

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

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

* [PATCH v2 14/21] drm/bridge: Add an ->atomic_check() hook
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
                   ` (12 preceding siblings ...)
  2019-08-26 15:26 ` [PATCH v2 13/21] drm/bridge: Patch atomic hooks to take a drm_bridge_state Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  2019-08-26 15:26 ` [PATCH v2 15/21] drm/bridge: Add the drm_bridge_chain_get_prev_bridge() helper Boris Brezillon
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

So that bridge drivers have a way to check/reject an atomic operation.
The drm_atomic_bridge_chain_check() (which is just a wrapper around
the ->atomic_check() hook) is called in place of
drm_bridge_chain_mode_fixup() (when ->atomic_check() is not implemented,
the core falls back to ->mode_fixup(), so the behavior should stay
the same for existing bridge drivers).

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
Laurent,

I haven't clarified what's allowed to be changed in
->mode_fixup()/->atomic_check() simply because I don't know what the
constraints are. Since the problem already exists with the
->mode_fixup() hook, and given the goal of this series is to support
bus_format negotation (which does not involve tweaking the display
mode), I'd prefer to delay these semantic adjustments if you're okay
with that.

Regards,

Boris

Changes in v2:
* Clarify the fact that ->atomic_check() is replacing ->mode_fixup()
---
 drivers/gpu/drm/drm_atomic_helper.c | 12 +++---
 drivers/gpu/drm/drm_bridge.c        | 62 +++++++++++++++++++++++++++++
 include/drm/drm_bridge.h            | 29 +++++++++++++-
 3 files changed, 96 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index b3f59e757b30..2a4ac69ccc93 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -445,12 +445,12 @@ mode_fixup(struct drm_atomic_state *state)
 		encoder = new_conn_state->best_encoder;
 		funcs = encoder->helper_private;
 
-		ret = drm_bridge_chain_mode_fixup(&encoder->bridge,
-					&new_crtc_state->mode,
-					&new_crtc_state->adjusted_mode);
-		if (!ret) {
-			DRM_DEBUG_ATOMIC("Bridge fixup failed\n");
-			return -EINVAL;
+		ret = drm_atomic_bridge_chain_check(&encoder->bridge,
+						    new_crtc_state,
+						    new_conn_state);
+		if (ret) {
+			DRM_DEBUG_ATOMIC("Bridge atomic check failed\n");
+			return ret;
 		}
 
 		if (funcs && funcs->atomic_check) {
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 5c83cac7975e..7f7e0ea5b06c 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -581,6 +581,68 @@ void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge,
 }
 EXPORT_SYMBOL(drm_atomic_bridge_chain_enable);
 
+static int drm_atomic_bridge_check(struct drm_bridge *bridge,
+				   struct drm_crtc_state *crtc_state,
+				   struct drm_connector_state *conn_state)
+{
+	if (bridge->funcs->atomic_check) {
+		struct drm_bridge_state *bridge_state;
+		int ret;
+
+		bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state,
+							       bridge);
+		if (WARN_ON(!bridge_state))
+			return -EINVAL;
+
+		ret = bridge->funcs->atomic_check(bridge, bridge_state,
+						  crtc_state, conn_state);
+		if (ret)
+			return ret;
+	} else if (bridge->funcs->mode_fixup) {
+		if (!bridge->funcs->mode_fixup(bridge, &crtc_state->mode,
+					       &crtc_state->adjusted_mode))
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * drm_atomic_bridge_chain_check() - Do an atomic check on the bridge chain
+ * @bridge: bridge control structure
+ * @crtc_state: new CRTC state
+ * @conn_state: new connector state
+ *
+ * Calls &drm_bridge_funcs.atomic_check() (falls back on
+ * &drm_bridge_funcs.mode_fixup()) op for all the bridges in the encoder chain,
+ * starting from the last bridge to the first. These are called before calling
+ * &drm_encoder_helper_funcs.atomic_check()
+ *
+ * RETURNS:
+ * 0 on success, a negative error code on failure
+ */
+int drm_atomic_bridge_chain_check(struct drm_bridge *bridge,
+				  struct drm_crtc_state *crtc_state,
+				  struct drm_connector_state *conn_state)
+{
+	struct drm_encoder *encoder = bridge->encoder;
+	struct drm_bridge *iter;
+
+	list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
+		int ret;
+
+		ret = drm_atomic_bridge_check(iter, crtc_state, conn_state);
+		if (ret)
+			return ret;
+
+		if (iter == bridge)
+			break;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_atomic_bridge_chain_check);
+
 /**
  * drm_atomic_helper_bridge_destroy_state() - Default destroy state helper
  * @bridge: the bridge this state refers to
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 231f62cd681d..7fdce6dc5f26 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -126,7 +126,9 @@ struct drm_bridge_funcs {
 	 * this function passes all other callbacks must succeed for this
 	 * configuration.
 	 *
-	 * The mode_fixup callback is optional.
+	 * The mode_fixup callback is optional. &drm_bridge_funcs.mode_fixup()
+	 * is not called when &drm_bridge_funcs.atomic_check() is implemented,
+	 * so only one of them should be provided.
 	 *
 	 * NOTE:
 	 *
@@ -389,6 +391,28 @@ struct drm_bridge_funcs {
 	void (*atomic_destroy_state)(struct drm_bridge *bridge,
 				     struct drm_bridge_state *state);
 
+	/**
+	 * @atomic_check:
+	 *
+	 * This method is responsible for checking bridge state correctness.
+	 * It can also check the state of the surrounding components in chain
+	 * to make sure the whole pipeline can work properly.
+	 *
+	 * &drm_bridge_funcs.atomic_check() hooks are called in reverse
+	 * order (from the last to the first bridge).
+	 *
+	 * This method is optional. &drm_bridge_funcs.mode_fixup() is not
+	 * called when &drm_bridge_funcs.atomic_check() is implemented, so only
+	 * one of them should be provided.
+	 *
+	 * RETURNS:
+	 * zero if the check passed, a negative error code otherwise.
+	 */
+	int (*atomic_check)(struct drm_bridge *bridge,
+			    struct drm_bridge_state *bridge_state,
+			    struct drm_crtc_state *crtc_state,
+			    struct drm_connector_state *conn_state);
+
 	/**
 	 * @atomic_reset:
 	 *
@@ -511,6 +535,9 @@ void drm_bridge_chain_mode_set(struct drm_bridge *bridge,
 void drm_bridge_chain_pre_enable(struct drm_bridge *bridge);
 void drm_bridge_chain_enable(struct drm_bridge *bridge);
 
+int drm_atomic_bridge_chain_check(struct drm_bridge *bridge,
+				  struct drm_crtc_state *crtc_state,
+				  struct drm_connector_state *conn_state);
 void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge,
 				     struct drm_atomic_state *state);
 void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
-- 
2.21.0

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

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

* [PATCH v2 15/21] drm/bridge: Add the drm_bridge_chain_get_prev_bridge() helper
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
                   ` (13 preceding siblings ...)
  2019-08-26 15:26 ` [PATCH v2 14/21] drm/bridge: Add an ->atomic_check() hook Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  2019-08-27  7:26   ` Neil Armstrong
  2019-08-26 15:26 ` [PATCH v2 16/21] drm/bridge: Add the necessary bits to support bus format negotiation Boris Brezillon
                   ` (5 subsequent siblings)
  20 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

Will be useful for bridge drivers that want to do bus format
negotiation with their neighbours.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
Changes in v2:
* Fix the kerneldoc
* Drop the !bridge || !bridge->encoder check
---
 drivers/gpu/drm/drm_bridge.c | 17 +++++++++++++++++
 include/drm/drm_bridge.h     |  2 ++
 2 files changed, 19 insertions(+)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 7f7e0ea5b06c..9c74b285da9d 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -238,6 +238,23 @@ drm_bridge_chain_get_next_bridge(struct drm_bridge *bridge)
 }
 EXPORT_SYMBOL(drm_bridge_chain_get_next_bridge);
 
+/**
+ * drm_bridge_chain_get_prev_bridge() - Get the previous bridge in the chain
+ * @bridge: bridge object
+ *
+ * RETURNS:
+ * the previous bridge in the chain, or NULL if @bridge is the last.
+ */
+struct drm_bridge *
+drm_bridge_chain_get_prev_bridge(struct drm_bridge *bridge)
+{
+	if (list_is_first(&bridge->chain_node, &bridge->encoder->bridge_chain))
+		return NULL;
+
+	return list_prev_entry(bridge, chain_node);
+}
+EXPORT_SYMBOL(drm_bridge_chain_get_prev_bridge);
+
 /**
  * DOC: bridge callbacks
  *
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 7fdce6dc5f26..95dc58c3a4e8 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -521,6 +521,8 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
 
 struct drm_bridge *
 drm_bridge_chain_get_next_bridge(struct drm_bridge *bridge);
+struct drm_bridge *
+drm_bridge_chain_get_prev_bridge(struct drm_bridge *bridge);
 bool drm_bridge_chain_mode_fixup(struct drm_bridge *bridge,
 				 const struct drm_display_mode *mode,
 				 struct drm_display_mode *adjusted_mode);
-- 
2.21.0

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

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

* [PATCH v2 16/21] drm/bridge: Add the necessary bits to support bus format negotiation
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
                   ` (14 preceding siblings ...)
  2019-08-26 15:26 ` [PATCH v2 15/21] drm/bridge: Add the drm_bridge_chain_get_prev_bridge() helper Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  2019-08-27  8:18   ` Neil Armstrong
  2019-08-26 15:26 ` [PATCH v2 17/21] drm/imx: pd: Use bus format/flags provided by the bridge when available Boris Brezillon
                   ` (4 subsequent siblings)
  20 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

This takes the form of various helpers, plus the addition of 2 new
structs:
* drm_bus_caps: describe the bus capabilities of a bridge/encoder. For
  bridges we have one for the input port and one for the output port.
  Encoders just have one output port.
* drm_bus_cfg: added to the drm_bridge_state. It's supposed to store
  bus configuration information. For now we just have format and flags
  but more fields might be added in the future. Again, each
  drm_bridge_state contains 2 drm_bus_cfg elements: one for the output
  port and one for the input port

Helpers can be used from bridge drivers' ->atomic_check() implementation
to negotiate the bus format to use. Negotiation happens in reserve order,
starting from the last element of the bridge chain (the one directly
connected to the display) to the first element of the chain (the one
connected to the encoder).

Negotiation usually takes place in 2 steps:
* make sure the input end of the next element in the chain picked a
  format that's supported by the output end of our bridge. That's done
  with drm_atomic_bridge_choose_output_bus_cfg().
* choose a format for the input end of our bridge based on what's
  supported by the previous bridge in the chain. This is achieved by
  calling drm_atomic_bridge_choose_input_bus_cfg()

Note that those helpers are a bit lax when it comes to uninitialized
bus format validation. That's intentional. If we don't do that we'll
basically break things if we start adding support for bus format
negotiation to some elements of the pipeline leaving others on the
side, and that's likely to happen for all external bridges since we
can't necessarily tell where they are used.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
Changes in v2:
* Rework things to support more complex use cases
---
 drivers/gpu/drm/drm_bridge.c | 179 ++++++++++++++++++++++++++++++++++-
 include/drm/drm_bridge.h     |  82 ++++++++++++++++
 2 files changed, 260 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 9c74b285da9d..b53732ac997d 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -624,13 +624,184 @@ static int drm_atomic_bridge_check(struct drm_bridge *bridge,
 	return 0;
 }
 
+static int select_bus_fmt_recursive(struct drm_bridge *first,
+				    struct drm_bridge *cur,
+				    struct drm_crtc_state *crtc_state,
+				    struct drm_connector_state *conn_state,
+				    u32 out_bus_fmt)
+{
+	struct drm_bridge_state *cur_state;
+	unsigned int num_in_bus_fmts, i;
+	struct drm_bridge *prev;
+	u32 *in_bus_fmts;
+	int ret;
+
+	prev = drm_bridge_chain_get_prev_bridge(cur);
+	cur_state = drm_atomic_get_new_bridge_state(crtc_state->state, cur);
+	if (WARN_ON(!cur_state))
+		return -EINVAL;
+
+	/*
+	 * Bus format negotiation is not supported by this bridge, let's pass
+	 * MEDIA_BUS_FMT_FIXED to the previous bridge in the chain and hope
+	 * that it can handle this situation gracefully (by providing
+	 * appropriate default values).
+	 */
+	if (!cur->funcs->atomic_get_input_bus_fmts) {
+		if (cur != first) {
+			ret = select_bus_fmt_recursive(first, prev, crtc_state,
+						       conn_state,
+						       MEDIA_BUS_FMT_FIXED);
+			if (ret)
+				return ret;
+		}
+
+		cur_state->input_bus_cfg.fmt = MEDIA_BUS_FMT_FIXED;
+		cur_state->output_bus_cfg.fmt = out_bus_fmt;
+		return 0;
+	}
+
+	cur->funcs->atomic_get_input_bus_fmts(cur, cur_state, crtc_state,
+					      conn_state, out_bus_fmt,
+					      &num_in_bus_fmts, NULL);
+	if (!num_in_bus_fmts)
+		return -ENOTSUPP;
+
+	in_bus_fmts = kcalloc(num_in_bus_fmts, sizeof(*in_bus_fmts),
+			      GFP_KERNEL);
+	if (!in_bus_fmts)
+		return -ENOMEM;
+
+	cur->funcs->atomic_get_input_bus_fmts(cur, cur_state, crtc_state,
+					      conn_state, out_bus_fmt,
+					      &num_in_bus_fmts, in_bus_fmts);
+
+	if (first == cur) {
+		cur_state->input_bus_cfg.fmt = in_bus_fmts[0];
+		cur_state->output_bus_cfg.fmt = out_bus_fmt;
+		kfree(in_bus_fmts);
+		return 0;
+	}
+
+	for (i = 0; i < num_in_bus_fmts; i++) {
+		ret = select_bus_fmt_recursive(first, prev, crtc_state,
+					       conn_state, in_bus_fmts[i]);
+		if (ret != -ENOTSUPP)
+			break;
+	}
+
+	if (!ret) {
+		cur_state->input_bus_cfg.fmt = in_bus_fmts[i];
+		cur_state->output_bus_cfg.fmt = out_bus_fmt;
+	}
+
+	kfree(in_bus_fmts);
+	return ret;
+}
+
+/*
+ * This function is called by &drm_atomic_bridge_chain_check() just before
+ * calling &drm_bridge_funcs.atomic_check() on all elements of the chain.
+ * It's providing bus format negotiation between bridge elements. The
+ * negotiation happens in reverse order, starting from the last element in
+ * the chain up to @bridge.
+ *
+ * Negotiation starts by retrieving supported output bus formats on the last
+ * bridge element and testing them one by one. The test is recursive, meaning
+ * that for each tested output format, the whole chain will be walked backward,
+ * and each element will have to choose an input bus format that can be
+ * transcoded to the requested output format. When a bridge element does not
+ * support transcoding into a specific output format -ENOTSUPP is returned and
+ * the next bridge element will have to try a different format. If none of the
+ * combinations worked, -ENOTSUPP is returned and the atomic modeset will fail.
+ *
+ * This implementation is relying on
+ * &drm_bridge_funcs.atomic_get_output_bus_fmts() and
+ * &drm_bridge_funcs.atomic_get_input_bus_fmts() to gather supported
+ * input/output formats.
+ * When &drm_bridge_funcs.atomic_get_output_bus_fmts() is not implemented by
+ * the last element of the chain, &drm_atomic_bridge_chain_select_bus_fmts()
+ * tries a single format: &drm_connector.display_info.bus_formats[0] if
+ * available, MEDIA_BUS_FMT_FIXED otherwise.
+ * When &drm_bridge_funcs.atomic_get_input_bus_fmts() is not implemented,
+ * &drm_atomic_bridge_chain_select_bus_fmts() skips the negotiation on the
+ * bridge element that lacks this hook and asks the previous element in the
+ * chain to try MEDIA_BUS_FMT_FIXED. It's up to bridge drivers to decide what
+ * to do in that case (fail if they want to enforce bus format negotiation, or
+ * provide a reasonable default if they need to support pipelines where not
+ * all elements support bus format negotiation).
+ */
+static int
+drm_atomic_bridge_chain_select_bus_fmts(struct drm_bridge *bridge,
+					struct drm_crtc_state *crtc_state,
+					struct drm_connector_state *conn_state)
+{
+	struct drm_connector *conn = conn_state->connector;
+	struct drm_encoder *encoder = bridge->encoder;
+	struct drm_bridge_state *last_bridge_state;
+	unsigned int i, num_out_bus_fmts;
+	struct drm_bridge *last_bridge;
+	u32 *out_bus_fmts;
+	int ret = 0;
+
+	last_bridge = list_last_entry(&encoder->bridge_chain,
+				      struct drm_bridge, chain_node);
+	last_bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state,
+							    last_bridge);
+	if (WARN_ON(!last_bridge_state))
+		return -EINVAL;
+
+	if (last_bridge->funcs->atomic_get_output_bus_fmts)
+		last_bridge->funcs->atomic_get_output_bus_fmts(last_bridge,
+							last_bridge_state,
+							crtc_state,
+							conn_state,
+							&num_out_bus_fmts,
+							NULL);
+	else
+		num_out_bus_fmts = 1;
+
+	if (!num_out_bus_fmts)
+		return -ENOTSUPP;
+
+	out_bus_fmts = kcalloc(num_out_bus_fmts, sizeof(*out_bus_fmts),
+			       GFP_KERNEL);
+	if (!out_bus_fmts)
+		return -ENOMEM;
+
+	if (last_bridge->funcs->atomic_get_output_bus_fmts)
+		last_bridge->funcs->atomic_get_output_bus_fmts(last_bridge,
+							last_bridge_state,
+							crtc_state,
+							conn_state,
+							&num_out_bus_fmts,
+							out_bus_fmts);
+	else if (conn->display_info.num_bus_formats &&
+		 conn->display_info.bus_formats)
+		out_bus_fmts[0] = conn->display_info.bus_formats[0];
+	else
+		out_bus_fmts[0] = MEDIA_BUS_FMT_FIXED;
+
+	for (i = 0; i < num_out_bus_fmts; i++) {
+		ret = select_bus_fmt_recursive(bridge, last_bridge, crtc_state,
+					       conn_state, out_bus_fmts[i]);
+		if (ret != -ENOTSUPP)
+			break;
+	}
+
+	kfree(out_bus_fmts);
+
+	return ret;
+}
+
 /**
  * drm_atomic_bridge_chain_check() - Do an atomic check on the bridge chain
  * @bridge: bridge control structure
  * @crtc_state: new CRTC state
  * @conn_state: new connector state
  *
- * Calls &drm_bridge_funcs.atomic_check() (falls back on
+ * First trigger a bus format negotiation before calling
+ * &drm_bridge_funcs.atomic_check() (falls back on
  * &drm_bridge_funcs.mode_fixup()) op for all the bridges in the encoder chain,
  * starting from the last bridge to the first. These are called before calling
  * &drm_encoder_helper_funcs.atomic_check()
@@ -644,6 +815,12 @@ int drm_atomic_bridge_chain_check(struct drm_bridge *bridge,
 {
 	struct drm_encoder *encoder = bridge->encoder;
 	struct drm_bridge *iter;
+	int ret;
+
+	ret = drm_atomic_bridge_chain_select_bus_fmts(bridge, crtc_state,
+						      conn_state);
+	if (ret)
+		return ret;
 
 	list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
 		int ret;
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 95dc58c3a4e8..96df3bedfee4 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -33,15 +33,33 @@ struct drm_bridge;
 struct drm_bridge_timings;
 struct drm_panel;
 
+/**
+ * struct drm_bus_cfg - bus configuration
+ * @fmt: format used on this bus
+ * @flags: DRM_BUS_ flags used on this bus
+ *
+ * Encodes the bus format and bus flags used by one end of the bridge or
+ * by the encoder output.
+ */
+struct drm_bus_cfg {
+	u32 fmt;
+	u32 flags;
+};
+
 /**
  * struct drm_bridge_state - Atomic bridge state object
  * @base: inherit from &drm_private_state
  * @bridge: the bridge this state refers to
+ * @input_bus_info: input bus information
+ * @output_bus_info: output bus information
  */
 struct drm_bridge_state {
 	struct drm_private_state base;
 
 	struct drm_bridge *bridge;
+
+	struct drm_bus_cfg input_bus_cfg;
+	struct drm_bus_cfg output_bus_cfg;
 };
 
 static inline struct drm_bridge_state *
@@ -391,6 +409,70 @@ struct drm_bridge_funcs {
 	void (*atomic_destroy_state)(struct drm_bridge *bridge,
 				     struct drm_bridge_state *state);
 
+	/**
+	 * @atomic_get_output_bus_fmts:
+	 *
+	 * Return the supported bus formats on the output end of a bridge.
+	 * This method is called twice. Once with output_fmts set NULL, in this
+	 * case the driver should set num_output_fmts to the number of
+	 * supported output bus formats such that the core can allocate an
+	 * array of the right dimension. The second time it's called with a
+	 * non-NULL output_fmts, and the driver is expected to fill the
+	 * output_fmts array. The output_fmts array passed to the driver is
+	 * guaranteed to be big enough to store the number of entries returned
+	 * on the first call (no need to check num_output_fmts).
+	 *
+	 * This method is only called on the last element of the bridge chain
+	 * as part of the bus format negotiation process that happens in
+	 * &drm_atomic_bridge_chain_select_bus_fmts().
+	 * This method is optional. When not implemented, the core will
+	 * fallback to &drm_connector.display_info.bus_formats[0] if
+	 * &drm_connector.display_info.num_bus_formats > 0,
+	 * MEDIA_BUS_FMT_FIXED otherwise.
+	 */
+	void (*atomic_get_output_bus_fmts)(struct drm_bridge *bridge,
+					   struct drm_bridge_state *bridge_state,
+					   struct drm_crtc_state *crtc_state,
+					   struct drm_connector_state *conn_state,
+					   unsigned int *num_output_fmts,
+					   u32 *output_fmts);
+
+	/**
+	 * @atomic_get_input_bus_fmts:
+	 *
+	 * Return the supported bus formats on the input end of a bridge for
+	 * a specific output bus format.
+	 * This method is called twice. Once with input_fmts set NULL, in this
+	 * case the driver should set num_input_fmts to the number of
+	 * supported input bus formats such that the core can allocate an array
+	 * of the right dimension. The second time it's called with a non-NULL
+	 * input_fmts, and the driver is expected to fill the input_fmts array.
+	 * The input_fmts array passed to the driver is guaranteed to be big
+	 * enough to store the number of entries returned on the first call (no
+	 * need to check num_input_fmts).
+	 *
+	 * This method is called on all element of the bridge chain as part of
+	 * the bus format negotiation process that happens in
+	 * &drm_atomic_bridge_chain_select_bus_fmts().
+	 * This method is optional. When not implemented, the core will bypass
+	 * bus format negotiation on this element of the bridge without
+	 * failing, and the previous element in the chain will be passed
+	 * MEDIA_BUS_FMT_FIXED as its output bus format.
+	 *
+	 * Bridge drivers that need to support being linked to bridges that are
+	 * not supporting bus format negotiation should handle the
+	 * output_fmt == MEDIA_BUS_FMT_FIXED case appropriately, by selecting a
+	 * sensible default value or extracting this information from somewhere
+	 * else (FW property, &drm_display_mode, &drm_display_info, ...)
+	 */
+	void (*atomic_get_input_bus_fmts)(struct drm_bridge *bridge,
+					  struct drm_bridge_state *bridge_state,
+					  struct drm_crtc_state *crtc_state,
+					  struct drm_connector_state *conn_state,
+					  u32 output_fmt,
+					  unsigned int *num_input_fmts,
+					  u32 *input_fmts);
+
 	/**
 	 * @atomic_check:
 	 *
-- 
2.21.0

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

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

* [PATCH v2 17/21] drm/imx: pd: Use bus format/flags provided by the bridge when available
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
                   ` (15 preceding siblings ...)
  2019-08-26 15:26 ` [PATCH v2 16/21] drm/bridge: Add the necessary bits to support bus format negotiation Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  2019-08-27  8:15   ` Philipp Zabel
  2019-08-26 15:26 ` [PATCH v2 18/21] drm/bridge: lvds-encoder: Implement basic bus format negotiation Boris Brezillon
                   ` (3 subsequent siblings)
  20 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

Now that bridges can expose the bus format/flags they expect, we can
use those instead of the relying on the display_info provided by the
connector (which is only valid if the encoder is directly connected
to bridge element driving the panel/display).

We also explicitly expose the bus formats supported by our encoder by
filling encoder->output_bus_caps with proper info.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
Changes in v2:
* Adjust things to match the new bus-format negotiation infra
---
 drivers/gpu/drm/imx/parallel-display.c | 136 ++++++++++++++++++++++---
 1 file changed, 120 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
index 35518e5de356..df47cb74759f 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -89,37 +89,139 @@ static struct drm_encoder *imx_pd_connector_best_encoder(
 	return &imxpd->encoder;
 }
 
-static void imx_pd_encoder_enable(struct drm_encoder *encoder)
+static void imx_pd_bridge_enable(struct drm_bridge *bridge)
 {
+	struct drm_encoder *encoder = bridge_to_encoder(bridge);
 	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
 
 	drm_panel_prepare(imxpd->panel);
 	drm_panel_enable(imxpd->panel);
 }
 
-static void imx_pd_encoder_disable(struct drm_encoder *encoder)
+static void imx_pd_bridge_disable(struct drm_bridge *bridge)
 {
+	struct drm_encoder *encoder = bridge_to_encoder(bridge);
 	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
 
 	drm_panel_disable(imxpd->panel);
 	drm_panel_unprepare(imxpd->panel);
 }
 
-static int imx_pd_encoder_atomic_check(struct drm_encoder *encoder,
-				       struct drm_crtc_state *crtc_state,
-				       struct drm_connector_state *conn_state)
+static const u32 imx_pd_bus_fmts[] = {
+	MEDIA_BUS_FMT_RGB888_1X24,
+	MEDIA_BUS_FMT_RGB565_1X16,
+	MEDIA_BUS_FMT_RGB666_1X18,
+	MEDIA_BUS_FMT_RGB666_1X24_CPADHI,
+};
+
+static void
+imx_pd_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
+					 struct drm_bridge_state *bridge_state,
+					 struct drm_crtc_state *crtc_state,
+					 struct drm_connector_state *conn_state,
+					 unsigned int *num_output_fmts,
+					 u32 *output_fmts)
 {
+	struct drm_display_info *di = &conn_state->connector->display_info;
+	struct drm_encoder *encoder = bridge_to_encoder(bridge);
+	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
+
+	*num_output_fmts = 1;
+	if (imxpd->bus_format) {
+		if (output_fmts)
+			output_fmts[0] = imxpd->bus_format;
+	} else if (di->num_bus_formats) {
+		*num_output_fmts = 1;
+		if (output_fmts)
+			output_fmts[0] = di->bus_formats[0];
+	} else {
+		*num_output_fmts = ARRAY_SIZE(imx_pd_bus_fmts);
+		if (output_fmts)
+			memcpy(output_fmts, imx_pd_bus_fmts,
+			       ARRAY_SIZE(imx_pd_bus_fmts));
+	}
+}
+
+static void
+imx_pd_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
+					struct drm_bridge_state *bridge_state,
+					struct drm_crtc_state *crtc_state,
+					struct drm_connector_state *conn_state,
+					u32 output_fmt,
+					unsigned int *num_input_fmts,
+					u32 *input_fmts)
+{
+	struct drm_encoder *encoder = bridge_to_encoder(bridge);
+	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
+
+	*num_input_fmts = 0;
+	if (output_fmt == MEDIA_BUS_FMT_FIXED) {
+		*num_input_fmts = 1;
+	} else if (!imxpd->bus_format) {
+		unsigned int i;
+
+		for (i = 0; i < ARRAY_SIZE(imx_pd_bus_fmts); i++) {
+			if (imx_pd_bus_fmts[i] == output_fmt) {
+				*num_input_fmts = 1;
+				break;
+			}
+		}
+	} else if (imxpd->bus_format == output_fmt) {
+		*num_input_fmts = 1;
+	}
+
+	if (*num_input_fmts && input_fmts)
+		input_fmts[0] = MEDIA_BUS_FMT_FIXED;
+}
+
+static int imx_pd_bridge_atomic_check(struct drm_bridge *bridge,
+				      struct drm_bridge_state *bridge_state,
+				      struct drm_crtc_state *crtc_state,
+				      struct drm_connector_state *conn_state)
+{
+	struct drm_encoder *encoder = bridge_to_encoder(bridge);
 	struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc_state);
 	struct drm_display_info *di = &conn_state->connector->display_info;
 	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
+	struct drm_bridge_state *next_bridge_state = NULL;
+	struct drm_bridge *next_bridge;
+	u32 bus_flags, bus_fmt;
+	unsigned int i;
 
-	if (!imxpd->bus_format && di->num_bus_formats) {
-		imx_crtc_state->bus_flags = di->bus_flags;
-		imx_crtc_state->bus_format = di->bus_formats[0];
-	} else {
-		imx_crtc_state->bus_flags = imxpd->bus_flags;
-		imx_crtc_state->bus_format = imxpd->bus_format;
+	next_bridge = drm_bridge_chain_get_next_bridge(bridge);
+	if (next_bridge)
+		next_bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state,
+								    next_bridge);
+
+	bus_fmt = bridge_state->output_bus_cfg.fmt;
+	if (bus_fmt == MEDIA_BUS_FMT_FIXED)
+		bus_fmt = 0;
+
+	if (next_bridge_state)
+		bus_flags = next_bridge_state->input_bus_cfg.flags;
+	else if (!imxpd->bus_format && di->num_bus_formats)
+		bus_flags = di->bus_flags;
+	else
+		bus_flags = imxpd->bus_flags;
+
+	for (i = 0; bus_fmt && i < ARRAY_SIZE(imx_pd_bus_fmts); i++) {
+		if (imx_pd_bus_fmts[i] == bridge_state->output_bus_cfg.fmt)
+			break;
 	}
+
+	if (i == ARRAY_SIZE(imx_pd_bus_fmts))
+		return -EINVAL;
+
+	if (bus_flags &
+	    ~(DRM_BUS_FLAG_DE_LOW | DRM_BUS_FLAG_DE_HIGH |
+	      DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE |
+	      DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE))
+		return -EINVAL;
+
+	bridge_state->output_bus_cfg.flags = bus_flags;
+	bridge_state->input_bus_cfg.flags = bus_flags;
+	imx_crtc_state->bus_flags = bus_flags;
+	imx_crtc_state->bus_format = bridge_state->output_bus_cfg.fmt;
 	imx_crtc_state->di_hsync_pin = 2;
 	imx_crtc_state->di_vsync_pin = 3;
 
@@ -143,10 +245,12 @@ static const struct drm_encoder_funcs imx_pd_encoder_funcs = {
 	.destroy = imx_drm_encoder_destroy,
 };
 
-static const struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = {
-	.enable = imx_pd_encoder_enable,
-	.disable = imx_pd_encoder_disable,
-	.atomic_check = imx_pd_encoder_atomic_check,
+static const struct drm_bridge_funcs imx_pd_bridge_funcs = {
+	.enable = imx_pd_bridge_enable,
+	.disable = imx_pd_bridge_disable,
+	.atomic_check = imx_pd_bridge_atomic_check,
+	.atomic_get_input_bus_fmts = imx_pd_bridge_atomic_get_input_bus_fmts,
+	.atomic_get_output_bus_fmts = imx_pd_bridge_atomic_get_output_bus_fmts,
 };
 
 static int imx_pd_register(struct drm_device *drm,
@@ -166,7 +270,7 @@ static int imx_pd_register(struct drm_device *drm,
 	 */
 	imxpd->connector.dpms = DRM_MODE_DPMS_OFF;
 
-	drm_encoder_helper_add(encoder, &imx_pd_encoder_helper_funcs);
+	encoder->bridge.funcs = &imx_pd_bridge_funcs;
 	drm_encoder_init(drm, encoder, &imx_pd_encoder_funcs,
 			 DRM_MODE_ENCODER_NONE, NULL);
 
-- 
2.21.0

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

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

* [PATCH v2 18/21] drm/bridge: lvds-encoder: Implement basic bus format negotiation
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
                   ` (16 preceding siblings ...)
  2019-08-26 15:26 ` [PATCH v2 17/21] drm/imx: pd: Use bus format/flags provided by the bridge when available Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  2019-08-26 16:15   ` Jernej Škrabec
  2019-08-26 15:26 ` [PATCH v2 19/21] drm/bridge: panel: Propage bus format/flags Boris Brezillon
                   ` (2 subsequent siblings)
  20 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

Some LVDS encoder might support several input/output bus formats. Add
a way to describe the one used on a specific design by adding optional
'data-mapping' properties to the input/output ports.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
Changes in v2:
* Make the bus-format negotiation logic more generic
---
 .../display/bridge/lvds-transmitter.txt       |  12 ++
 drivers/gpu/drm/bridge/lvds-encoder.c         | 105 ++++++++++++++++++
 2 files changed, 117 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
index 60091db5dfa5..db51eab216f7 100644
--- a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
+++ b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
@@ -36,6 +36,18 @@ graph bindings specified in Documentation/devicetree/bindings/graph.txt.
 - Video port 0 for parallel input
 - Video port 1 for LVDS output
 
+Optional port 0 node properties:
+
+- data-mapping: can be one of the following values
+	"rgb-24"
+	"rgb-18"
+
+Optional port 0 node properties:
+
+- data-mapping: can be one of the following values
+	"jeida-18"
+	"jeida-24"
+	"vesa-24"
 
 Example
 -------
diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c b/drivers/gpu/drm/bridge/lvds-encoder.c
index 2ab2c234f26c..38cad7a7d828 100644
--- a/drivers/gpu/drm/bridge/lvds-encoder.c
+++ b/drivers/gpu/drm/bridge/lvds-encoder.c
@@ -6,6 +6,7 @@
 #include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/of_graph.h>
 #include <linux/platform_device.h>
 
@@ -16,6 +17,8 @@ struct lvds_encoder {
 	struct drm_bridge bridge;
 	struct drm_bridge *panel_bridge;
 	struct gpio_desc *powerdown_gpio;
+	u32 output_fmt;
+	u32 input_fmt;
 };
 
 static int lvds_encoder_attach(struct drm_bridge *bridge)
@@ -48,12 +51,86 @@ static void lvds_encoder_disable(struct drm_bridge *bridge)
 		gpiod_set_value_cansleep(lvds_encoder->powerdown_gpio, 1);
 }
 
+static void lvds_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
+					   struct drm_bridge_state *bridge_state,
+					   struct drm_crtc_state *crtc_state,
+					   struct drm_connector_state *conn_state,
+					   u32 output_fmt,
+					   unsigned int *num_input_fmts,
+					   u32 *input_fmts)
+{
+	struct lvds_encoder *lvds_encoder = container_of(bridge,
+							 struct lvds_encoder,
+							 bridge);
+
+	if (output_fmt == MEDIA_BUS_FMT_FIXED ||
+	    output_fmt == lvds_encoder->output_fmt)
+		*num_input_fmts = 1;
+	else
+		*num_input_fmts = 0;
+
+	if (*num_input_fmts && input_fmts)
+		input_fmts[0] = lvds_encoder->input_fmt;
+}
+
+static int lvds_encoder_atomic_check(struct drm_bridge *bridge,
+				     struct drm_bridge_state *bridge_state,
+				     struct drm_crtc_state *crtc_state,
+				     struct drm_connector_state *conn_state)
+{
+	/* Propagate the bus_flags. */
+	bridge_state->input_bus_cfg.flags = bridge_state->output_bus_cfg.flags;
+	return 0;
+}
+
 static struct drm_bridge_funcs funcs = {
 	.attach = lvds_encoder_attach,
 	.enable = lvds_encoder_enable,
 	.disable = lvds_encoder_disable,
+	.atomic_get_input_bus_fmts = lvds_atomic_get_input_bus_fmts,
+	.atomic_check = lvds_encoder_atomic_check,
 };
 
+struct of_data_mapping {
+	const char *name;
+	u32 id;
+};
+
+static const struct of_data_mapping output_data_mappings[] = {
+	{ "jeida-18", MEDIA_BUS_FMT_RGB666_1X7X3_SPWG },
+	{ "jeida-24", MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA },
+	{ "vesa-24", MEDIA_BUS_FMT_RGB888_1X7X4_SPWG },
+};
+
+static const struct of_data_mapping input_data_mappings[] = {
+	{ "rgb-24", MEDIA_BUS_FMT_RGB888_1X24 },
+	{ "rgb-18", MEDIA_BUS_FMT_RGB666_1X18 },
+};
+
+static int of_get_data_mapping(struct device_node *port,
+			       const struct of_data_mapping *mappings,
+			       unsigned int num_mappings,
+			       u32 *fmt)
+{
+	const char *name = NULL;
+	unsigned int i;
+
+	of_property_read_string(port, "data-mapping", &name);
+	if (!name) {
+		*fmt = MEDIA_BUS_FMT_FIXED;
+		return 0;
+	}
+
+	for (i = 0; i < num_mappings; i++) {
+		if (!strcmp(mappings[i].name, name)) {
+			*fmt = mappings[i].id;
+			return 0;
+		}
+	}
+
+	return -ENOTSUPP;
+}
+
 static int lvds_encoder_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -62,11 +139,15 @@ static int lvds_encoder_probe(struct platform_device *pdev)
 	struct device_node *panel_node;
 	struct drm_panel *panel;
 	struct lvds_encoder *lvds_encoder;
+	int ret;
 
 	lvds_encoder = devm_kzalloc(dev, sizeof(*lvds_encoder), GFP_KERNEL);
 	if (!lvds_encoder)
 		return -ENOMEM;
 
+	lvds_encoder->input_fmt = MEDIA_BUS_FMT_FIXED;
+	lvds_encoder->output_fmt = MEDIA_BUS_FMT_FIXED;
+
 	lvds_encoder->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown",
 							       GPIOD_OUT_HIGH);
 	if (IS_ERR(lvds_encoder->powerdown_gpio)) {
@@ -77,6 +158,21 @@ static int lvds_encoder_probe(struct platform_device *pdev)
 		return err;
 	}
 
+	port = of_graph_get_port_by_id(dev->of_node, 0);
+	if (!port) {
+		dev_dbg(dev, "port 0 not found\n");
+		return -ENXIO;
+	}
+
+	ret = of_get_data_mapping(port, input_data_mappings,
+				  ARRAY_SIZE(input_data_mappings),
+				  &lvds_encoder->input_fmt);
+	of_node_put(port);
+	if (ret) {
+		dev_dbg(dev, "unsupported input data-mapping\n");
+		return ret;
+	}
+
 	/* Locate the panel DT node. */
 	port = of_graph_get_port_by_id(dev->of_node, 1);
 	if (!port) {
@@ -84,6 +180,15 @@ static int lvds_encoder_probe(struct platform_device *pdev)
 		return -ENXIO;
 	}
 
+	ret = of_get_data_mapping(port, output_data_mappings,
+				  ARRAY_SIZE(output_data_mappings),
+				  &lvds_encoder->output_fmt);
+	if (ret) {
+		of_node_put(port);
+		dev_dbg(dev, "unsupported output data-mapping\n");
+		return ret;
+	}
+
 	endpoint = of_get_child_by_name(port, "endpoint");
 	of_node_put(port);
 	if (!endpoint) {
-- 
2.21.0

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

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

* [PATCH v2 19/21] drm/bridge: panel: Propage bus format/flags
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
                   ` (17 preceding siblings ...)
  2019-08-26 15:26 ` [PATCH v2 18/21] drm/bridge: lvds-encoder: Implement basic bus format negotiation Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  2019-08-26 15:26 ` [PATCH v2 20/21] drm/panel: simple: Add support for Toshiba LTA089AC29000 panel Boris Brezillon
  2019-08-26 15:26 ` [PATCH v2 21/21] ARM: dts: imx: imx51-zii-rdu1: Fix the display pipeline definition Boris Brezillon
  20 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

So that the previous bridge element in the chain knows which input
format the panel bridge expects.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
Laurent,

I intentionally left your comments unaddressed in this patch as I'm
more interested in discussing the preparation patches. Once we've
settled on something regarding the bus-format negotiation stuff I'll
rework the binding/driver to support the data-mapping DT prop.

Regards,

Boris

Changes in v2:
* Adjust things to match the new bus-format negotiation approach
---
 drivers/gpu/drm/bridge/panel.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index 6cffeb4a42f2..3eeb40d37a89 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -120,6 +120,34 @@ static void panel_bridge_post_disable(struct drm_bridge *bridge)
 	drm_panel_unprepare(panel_bridge->panel);
 }
 
+static void
+panel_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
+				       struct drm_bridge_state *bridge_state,
+				       struct drm_crtc_state *crtc_state,
+				       struct drm_connector_state *conn_state,
+				       u32 output_fmt,
+				       unsigned int *num_input_fmts,
+				       u32 *input_fmts)
+{
+	*num_input_fmts = 1;
+	if (!input_fmts)
+		return;
+
+	input_fmts[0] = output_fmt;
+}
+
+static int panel_bridge_atomic_check(struct drm_bridge *bridge,
+				     struct drm_bridge_state *bridge_state,
+				     struct drm_crtc_state *crtc_state,
+				     struct drm_connector_state *conn_state)
+{
+	if (bridge_state->input_bus_cfg.fmt != bridge_state->output_bus_cfg.fmt)
+		return -EINVAL;
+
+	bridge_state->input_bus_cfg.flags = bridge_state->output_bus_cfg.flags;
+	return 0;
+}
+
 static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
 	.attach = panel_bridge_attach,
 	.detach = panel_bridge_detach,
@@ -127,6 +155,8 @@ static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
 	.enable = panel_bridge_enable,
 	.disable = panel_bridge_disable,
 	.post_disable = panel_bridge_post_disable,
+	.atomic_check = panel_bridge_atomic_check,
+	.atomic_get_input_bus_fmts = panel_bridge_atomic_get_input_bus_fmts,
 };
 
 /**
-- 
2.21.0

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

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

* [PATCH v2 20/21] drm/panel: simple: Add support for Toshiba LTA089AC29000 panel
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
                   ` (18 preceding siblings ...)
  2019-08-26 15:26 ` [PATCH v2 19/21] drm/bridge: panel: Propage bus format/flags Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  2019-08-26 15:26 ` [PATCH v2 21/21] ARM: dts: imx: imx51-zii-rdu1: Fix the display pipeline definition Boris Brezillon
  20 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

Add a new entry for the Toshiba LTA089AC29000 panel.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 .../display/panel/toshiba,lt089ac29000.txt    |  5 ++-
 drivers/gpu/drm/panel/panel-simple.c          | 36 +++++++++++++++++++
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/panel/toshiba,lt089ac29000.txt b/Documentation/devicetree/bindings/display/panel/toshiba,lt089ac29000.txt
index 89826116628c..26ebfa098966 100644
--- a/Documentation/devicetree/bindings/display/panel/toshiba,lt089ac29000.txt
+++ b/Documentation/devicetree/bindings/display/panel/toshiba,lt089ac29000.txt
@@ -1,7 +1,10 @@
 Toshiba 8.9" WXGA (1280x768) TFT LCD panel
 
 Required properties:
-- compatible: should be "toshiba,lt089ac29000"
+- compatible: should be one of the following
+	      "toshiba,lt089ac29000"
+	      "toshiba,lta089ac29000"
+
 - power-supply: as specified in the base binding
 
 This binding is compatible with the simple-panel binding, which is specified
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 28fa6ba7b767..0601570404b1 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -2915,6 +2915,39 @@ static const struct panel_desc toshiba_lt089ac29000 = {
 	.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
 };
 
+static const struct drm_display_mode toshiba_lta089ac29000_mode = {
+	.clock = 79500,
+	.hdisplay = 1280,
+	.hsync_start = 1280 + 192,
+	.hsync_end = 1280 + 192 + 128,
+	.htotal = 1280 + 192 + 128 + 64,
+	.vdisplay = 768,
+	.vsync_start = 768 + 20,
+	.vsync_end = 768 + 20 + 7,
+	.vtotal = 768 + 20 + 7 + 3,
+	.vrefresh = 60,
+};
+
+static const struct panel_desc toshiba_lta089ac29000 = {
+	.modes = &toshiba_lta089ac29000_mode,
+	.num_modes = 1,
+	.size = {
+		.width = 194,
+		.height = 116,
+	},
+	/*
+	 * FIXME:
+	 * The panel supports 2 bus formats: jeida-24 and jeida-18. The
+	 * mode is selected through the 8b6b_SEL pin. If anyone ever needs
+	 * support for jeida-18 we should probably parse the 'data-mapping'
+	 * property.
+	 * In the unlikely event where 8b6b_SEL is connected to a GPIO, we'd
+	 * need a new infra to allow bus format negotiation at the panel level.
+	 */
+	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA,
+	.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
+};
+
 static const struct drm_display_mode tpk_f07a_0102_mode = {
 	.clock = 33260,
 	.hdisplay = 800,
@@ -3369,6 +3402,9 @@ static const struct of_device_id platform_of_match[] = {
 	}, {
 		.compatible = "toshiba,lt089ac29000",
 		.data = &toshiba_lt089ac29000,
+	}, {
+		.compatible = "toshiba,lta089ac29000",
+		.data = &toshiba_lta089ac29000,
 	}, {
 		.compatible = "tpk,f07a-0102",
 		.data = &tpk_f07a_0102,
-- 
2.21.0

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

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

* [PATCH v2 21/21] ARM: dts: imx: imx51-zii-rdu1: Fix the display pipeline definition
  2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
                   ` (19 preceding siblings ...)
  2019-08-26 15:26 ` [PATCH v2 20/21] drm/panel: simple: Add support for Toshiba LTA089AC29000 panel Boris Brezillon
@ 2019-08-26 15:26 ` Boris Brezillon
  20 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 15:26 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, Boris Brezillon,
	kernel, Sam Ravnborg

The current definition does not represent the exact display pipeline we
have on the board: the LVDS panel is actually connected through a
parallel -> LVDS bridge. Let's fix that so the driver can select the
proper bus format on the CRTC end.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
Changes in v2:
* None
---
 arch/arm/boot/dts/imx51-zii-rdu1.dts | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/imx51-zii-rdu1.dts b/arch/arm/boot/dts/imx51-zii-rdu1.dts
index 3596060f52e7..b9c8e93cd5db 100644
--- a/arch/arm/boot/dts/imx51-zii-rdu1.dts
+++ b/arch/arm/boot/dts/imx51-zii-rdu1.dts
@@ -95,6 +95,28 @@
 			reg = <1>;
 
 			display_out: endpoint {
+				remote-endpoint = <&lvds_encoder_in>;
+			};
+		};
+	};
+
+	lvds-encoder {
+		compatible = "ti,sn75lvds83", "lvds-encoder";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+			data-mapping = "rgb-24";
+			lvds_encoder_in: endpoint {
+				remote-endpoint = <&display_out>;
+			};
+		};
+
+		port@1 {
+			reg = <1>;
+			data-mapping = "jeida-24";
+			lvds_encoder_out: endpoint {
 				remote-endpoint = <&panel_in>;
 			};
 		};
@@ -110,7 +132,7 @@
 
 		port {
 			panel_in: endpoint {
-				remote-endpoint = <&display_out>;
+				remote-endpoint = <&lvds_encoder_out>;
 			};
 		};
 	};
-- 
2.21.0

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

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

* Re: [PATCH v2 18/21] drm/bridge: lvds-encoder: Implement basic bus format negotiation
  2019-08-26 15:26 ` [PATCH v2 18/21] drm/bridge: lvds-encoder: Implement basic bus format negotiation Boris Brezillon
@ 2019-08-26 16:15   ` Jernej Škrabec
  2019-08-26 18:17     ` Boris Brezillon
  0 siblings, 1 reply; 46+ messages in thread
From: Jernej Škrabec @ 2019-08-26 16:15 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Nikita Yushchenko, Laurent Pinchart, Neil Armstrong,
	Andrey Smirnov, Jonas Karlman, Seung-Woo Kim, dri-devel,
	Kyungmin Park, Thierry Reding, Chris Healy, kernel, Sam Ravnborg

Hi Boris!

Dne ponedeljek, 26. avgust 2019 ob 17:26:46 CEST je Boris Brezillon 
napisal(a):
> Some LVDS encoder might support several input/output bus formats. Add
> a way to describe the one used on a specific design by adding optional
> 'data-mapping' properties to the input/output ports.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> ---
> Changes in v2:
> * Make the bus-format negotiation logic more generic
> ---
>  .../display/bridge/lvds-transmitter.txt       |  12 ++
>  drivers/gpu/drm/bridge/lvds-encoder.c         | 105 ++++++++++++++++++
>  2 files changed, 117 insertions(+)
> 
> diff --git
> a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
> b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
> index 60091db5dfa5..db51eab216f7 100644
> --- a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
> +++ b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
> @@ -36,6 +36,18 @@ graph bindings specified in
> Documentation/devicetree/bindings/graph.txt. - Video port 0 for parallel
> input
>  - Video port 1 for LVDS output
> 
> +Optional port 0 node properties:
> +
> +- data-mapping: can be one of the following values
> +	"rgb-24"
> +	"rgb-18"
> +
> +Optional port 0 node properties:

You probably mean port 1 ^^^ ?

Anyway, devicetree doc changes should be separate patch and be send to DT ML 
(I can't see it in CC).

Best regards,
Jernej

> +
> +- data-mapping: can be one of the following values
> +	"jeida-18"
> +	"jeida-24"
> +	"vesa-24"
> 
>  Example
>  -------
> diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c
> b/drivers/gpu/drm/bridge/lvds-encoder.c index 2ab2c234f26c..38cad7a7d828
> 100644
> --- a/drivers/gpu/drm/bridge/lvds-encoder.c
> +++ b/drivers/gpu/drm/bridge/lvds-encoder.c
> @@ -6,6 +6,7 @@
>  #include <linux/gpio/consumer.h>
>  #include <linux/module.h>
>  #include <linux/of.h>
> +#include <linux/of_device.h>
>  #include <linux/of_graph.h>
>  #include <linux/platform_device.h>
> 
> @@ -16,6 +17,8 @@ struct lvds_encoder {
>  	struct drm_bridge bridge;
>  	struct drm_bridge *panel_bridge;
>  	struct gpio_desc *powerdown_gpio;
> +	u32 output_fmt;
> +	u32 input_fmt;
>  };
> 
>  static int lvds_encoder_attach(struct drm_bridge *bridge)
> @@ -48,12 +51,86 @@ static void lvds_encoder_disable(struct drm_bridge
> *bridge) gpiod_set_value_cansleep(lvds_encoder->powerdown_gpio, 1);
>  }
> 
> +static void lvds_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
> +					   struct 
drm_bridge_state *bridge_state,
> +					   struct 
drm_crtc_state *crtc_state,
> +					   struct 
drm_connector_state *conn_state,
> +					   u32 output_fmt,
> +					   unsigned int 
*num_input_fmts,
> +					   u32 *input_fmts)
> +{
> +	struct lvds_encoder *lvds_encoder = container_of(bridge,
> +							 
struct lvds_encoder,
> +							 
bridge);
> +
> +	if (output_fmt == MEDIA_BUS_FMT_FIXED ||
> +	    output_fmt == lvds_encoder->output_fmt)
> +		*num_input_fmts = 1;
> +	else
> +		*num_input_fmts = 0;
> +
> +	if (*num_input_fmts && input_fmts)
> +		input_fmts[0] = lvds_encoder->input_fmt;
> +}
> +
> +static int lvds_encoder_atomic_check(struct drm_bridge *bridge,
> +				     struct drm_bridge_state 
*bridge_state,
> +				     struct drm_crtc_state 
*crtc_state,
> +				     struct drm_connector_state 
*conn_state)
> +{
> +	/* Propagate the bus_flags. */
> +	bridge_state->input_bus_cfg.flags = bridge_state-
>output_bus_cfg.flags;
> +	return 0;
> +}
> +
>  static struct drm_bridge_funcs funcs = {
>  	.attach = lvds_encoder_attach,
>  	.enable = lvds_encoder_enable,
>  	.disable = lvds_encoder_disable,
> +	.atomic_get_input_bus_fmts = lvds_atomic_get_input_bus_fmts,
> +	.atomic_check = lvds_encoder_atomic_check,
>  };
> 
> +struct of_data_mapping {
> +	const char *name;
> +	u32 id;
> +};
> +
> +static const struct of_data_mapping output_data_mappings[] = {
> +	{ "jeida-18", MEDIA_BUS_FMT_RGB666_1X7X3_SPWG },
> +	{ "jeida-24", MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA },
> +	{ "vesa-24", MEDIA_BUS_FMT_RGB888_1X7X4_SPWG },
> +};
> +
> +static const struct of_data_mapping input_data_mappings[] = {
> +	{ "rgb-24", MEDIA_BUS_FMT_RGB888_1X24 },
> +	{ "rgb-18", MEDIA_BUS_FMT_RGB666_1X18 },
> +};
> +
> +static int of_get_data_mapping(struct device_node *port,
> +			       const struct of_data_mapping 
*mappings,
> +			       unsigned int num_mappings,
> +			       u32 *fmt)
> +{
> +	const char *name = NULL;
> +	unsigned int i;
> +
> +	of_property_read_string(port, "data-mapping", &name);
> +	if (!name) {
> +		*fmt = MEDIA_BUS_FMT_FIXED;
> +		return 0;
> +	}
> +
> +	for (i = 0; i < num_mappings; i++) {
> +		if (!strcmp(mappings[i].name, name)) {
> +			*fmt = mappings[i].id;
> +			return 0;
> +		}
> +	}
> +
> +	return -ENOTSUPP;
> +}
> +
>  static int lvds_encoder_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> @@ -62,11 +139,15 @@ static int lvds_encoder_probe(struct platform_device
> *pdev) struct device_node *panel_node;
>  	struct drm_panel *panel;
>  	struct lvds_encoder *lvds_encoder;
> +	int ret;
> 
>  	lvds_encoder = devm_kzalloc(dev, sizeof(*lvds_encoder), 
GFP_KERNEL);
>  	if (!lvds_encoder)
>  		return -ENOMEM;
> 
> +	lvds_encoder->input_fmt = MEDIA_BUS_FMT_FIXED;
> +	lvds_encoder->output_fmt = MEDIA_BUS_FMT_FIXED;
> +
>  	lvds_encoder->powerdown_gpio = devm_gpiod_get_optional(dev, 
"powerdown",
>  							       
GPIOD_OUT_HIGH);
>  	if (IS_ERR(lvds_encoder->powerdown_gpio)) {
> @@ -77,6 +158,21 @@ static int lvds_encoder_probe(struct platform_device
> *pdev) return err;
>  	}
> 
> +	port = of_graph_get_port_by_id(dev->of_node, 0);
> +	if (!port) {
> +		dev_dbg(dev, "port 0 not found\n");
> +		return -ENXIO;
> +	}
> +
> +	ret = of_get_data_mapping(port, input_data_mappings,
> +				  ARRAY_SIZE(input_data_mappings),
> +				  &lvds_encoder->input_fmt);
> +	of_node_put(port);
> +	if (ret) {
> +		dev_dbg(dev, "unsupported input data-mapping\n");
> +		return ret;
> +	}
> +
>  	/* Locate the panel DT node. */
>  	port = of_graph_get_port_by_id(dev->of_node, 1);
>  	if (!port) {
> @@ -84,6 +180,15 @@ static int lvds_encoder_probe(struct platform_device
> *pdev) return -ENXIO;
>  	}
> 
> +	ret = of_get_data_mapping(port, output_data_mappings,
> +				  
ARRAY_SIZE(output_data_mappings),
> +				  &lvds_encoder->output_fmt);
> +	if (ret) {
> +		of_node_put(port);
> +		dev_dbg(dev, "unsupported output data-mapping\n");
> +		return ret;
> +	}
> +
>  	endpoint = of_get_child_by_name(port, "endpoint");
>  	of_node_put(port);
>  	if (!endpoint) {




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

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

* Re: [PATCH v2 18/21] drm/bridge: lvds-encoder: Implement basic bus format negotiation
  2019-08-26 16:15   ` Jernej Škrabec
@ 2019-08-26 18:17     ` Boris Brezillon
  0 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2019-08-26 18:17 UTC (permalink / raw)
  To: Jernej Škrabec
  Cc: Nikita Yushchenko, Laurent Pinchart, Neil Armstrong,
	Andrey Smirnov, Jonas Karlman, Seung-Woo Kim, dri-devel,
	Kyungmin Park, Thierry Reding, Chris Healy, kernel, Sam Ravnborg

On Mon, 26 Aug 2019 18:15:41 +0200
Jernej Škrabec <jernej.skrabec@siol.net> wrote:

> Hi Boris!
> 
> Dne ponedeljek, 26. avgust 2019 ob 17:26:46 CEST je Boris Brezillon 
> napisal(a):
> > Some LVDS encoder might support several input/output bus formats. Add
> > a way to describe the one used on a specific design by adding optional
> > 'data-mapping' properties to the input/output ports.
> > 
> > Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> > ---
> > Changes in v2:
> > * Make the bus-format negotiation logic more generic
> > ---
> >  .../display/bridge/lvds-transmitter.txt       |  12 ++
> >  drivers/gpu/drm/bridge/lvds-encoder.c         | 105 ++++++++++++++++++
> >  2 files changed, 117 insertions(+)
> > 
> > diff --git
> > a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
> > b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
> > index 60091db5dfa5..db51eab216f7 100644
> > --- a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
> > +++ b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
> > @@ -36,6 +36,18 @@ graph bindings specified in
> > Documentation/devicetree/bindings/graph.txt. - Video port 0 for parallel
> > input
> >  - Video port 1 for LVDS output
> > 
> > +Optional port 0 node properties:
> > +
> > +- data-mapping: can be one of the following values
> > +	"rgb-24"
> > +	"rgb-18"
> > +
> > +Optional port 0 node properties:  
> 
> You probably mean port 1 ^^^ ?

Yes.

> 
> Anyway, devicetree doc changes should be separate patch and be send to DT ML 
> (I can't see it in CC).

I'll fix that in v3. In the meantime, I'd really like to have feedback
on patches 1 to 16 as this is where core changes are.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 09/21] drm/bridge: Introduce drm_bridge_chain_get_next_bridge()
  2019-08-26 15:26 ` [PATCH v2 09/21] drm/bridge: Introduce drm_bridge_chain_get_next_bridge() Boris Brezillon
@ 2019-08-27  7:19   ` Neil Armstrong
  0 siblings, 0 replies; 46+ messages in thread
From: Neil Armstrong @ 2019-08-27  7:19 UTC (permalink / raw)
  To: Boris Brezillon, dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Jonas Karlman, Andrey Smirnov, Seung-Woo Kim, Kyungmin Park,
	Thierry Reding, Chris Healy, kernel, Sam Ravnborg

On 26/08/2019 17:26, Boris Brezillon wrote:
> And use it in drivers accessing the bridge->next field directly.
> This is part of our attempt to make the bridge chain a double-linked list
> based on the generic list helpers.

Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>

> 
> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> ---
> Changes in v2:
> * Kill the last/first helpers (they're not really needed)
> * Drop the !bridge || !bridge->encoder test
> ---
>  drivers/gpu/drm/drm_bridge.c           | 14 ++++++++++++++
>  drivers/gpu/drm/mediatek/mtk_hdmi.c    |  6 ++++--
>  drivers/gpu/drm/msm/edp/edp_bridge.c   | 10 ++++++++--
>  drivers/gpu/drm/omapdrm/omap_drv.c     |  4 ++--
>  drivers/gpu/drm/omapdrm/omap_encoder.c |  3 ++-
>  drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 10 +++++++---
>  drivers/gpu/drm/vc4/vc4_dsi.c          |  4 +++-
>  include/drm/drm_bridge.h               |  2 ++
>  8 files changed, 42 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index 52f1263530b7..3d9a6c6a7d4e 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -160,6 +160,20 @@ void drm_bridge_detach(struct drm_bridge *bridge)
>  	bridge->dev = NULL;
>  }
>  
> +/**
> + * drm_bridge_chain_get_next_bridge() - Get the next bridge in the chain
> + * @bridge: bridge object
> + *
> + * RETURNS:
> + * the next bridge in the chain, or NULL if @bridge is the last.
> + */
> +struct drm_bridge *
> +drm_bridge_chain_get_next_bridge(struct drm_bridge *bridge)
> +{
> +	return bridge->next;
> +}
> +EXPORT_SYMBOL(drm_bridge_chain_get_next_bridge);
> +
>  /**
>   * DOC: bridge callbacks
>   *
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index ea68b5adccbe..cfaa5aab8876 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -1238,16 +1238,18 @@ static int mtk_hdmi_conn_mode_valid(struct drm_connector *conn,
>  				    struct drm_display_mode *mode)
>  {
>  	struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn);
> +	struct drm_bridge *next_bridge;
>  
>  	dev_dbg(hdmi->dev, "xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
>  		mode->hdisplay, mode->vdisplay, mode->vrefresh,
>  		!!(mode->flags & DRM_MODE_FLAG_INTERLACE), mode->clock * 1000);
>  
> -	if (hdmi->bridge.next) {
> +	next_bridge = drm_bridge_chain_get_next_bridge(&hdmi->bridge);
> +	if (next_bridge) {
>  		struct drm_display_mode adjusted_mode;
>  
>  		drm_mode_copy(&adjusted_mode, mode);
> -		if (!drm_bridge_chain_mode_fixup(hdmi->bridge.next, mode,
> +		if (!drm_bridge_chain_mode_fixup(next_bridge, mode,
>  						 &adjusted_mode))
>  			return MODE_BAD;
>  	}
> diff --git a/drivers/gpu/drm/msm/edp/edp_bridge.c b/drivers/gpu/drm/msm/edp/edp_bridge.c
> index 446acca110e9..772408c94643 100644
> --- a/drivers/gpu/drm/msm/edp/edp_bridge.c
> +++ b/drivers/gpu/drm/msm/edp/edp_bridge.c
> @@ -55,8 +55,14 @@ static void edp_bridge_mode_set(struct drm_bridge *bridge,
>  	DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode));
>  
>  	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> -		if ((connector->encoder != NULL) &&
> -			(connector->encoder->bridge.next == bridge)) {
> +		struct drm_encoder *encoder = connector->encoder;
> +		struct drm_bridge *first_bridge;
> +
> +		if (!encoder)
> +			continue;
> +
> +		first_bridge = drm_bridge_chain_get_next_bridge(&encoder->bridge);
> +		if (bridge == first_bridge) {
>  			msm_edp_ctrl_timing_cfg(edp->ctrl,
>  				adjusted_mode, &connector->display_info);
>  			break;
> diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
> index 224ec6fdc800..ba59881bcf3f 100644
> --- a/drivers/gpu/drm/omapdrm/omap_drv.c
> +++ b/drivers/gpu/drm/omapdrm/omap_drv.c
> @@ -217,8 +217,8 @@ static int omap_display_id(struct omap_dss_device *output)
>  	} else if (output->bridge) {
>  		struct drm_bridge *bridge = output->bridge;
>  
> -		while (bridge->next)
> -			bridge = bridge->next;
> +		while (drm_bridge_chain_get_next_bridge(bridge))
> +			bridge = drm_bridge_chain_get_next_bridge(bridge);
>  
>  		node = bridge->of_node;
>  	} else if (output->panel) {
> diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
> index 24bbe9f2a32e..8ca54081997e 100644
> --- a/drivers/gpu/drm/omapdrm/omap_encoder.c
> +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
> @@ -126,7 +126,8 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
>  	for (dssdev = output; dssdev; dssdev = dssdev->next)
>  		omap_encoder_update_videomode_flags(&vm, dssdev->bus_flags);
>  
> -	for (bridge = output->bridge; bridge; bridge = bridge->next) {
> +	for (bridge = output->bridge; bridge;
> +	     bridge = drm_bridge_chain_get_next_bridge(bridge)) {
>  		if (!bridge->timings)
>  			continue;
>  
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> index 1bd748202946..bcccdccd2878 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> @@ -14,6 +14,7 @@
>  
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_device.h>
>  #include <drm/drm_fb_cma_helper.h>
> @@ -680,9 +681,10 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
>  			rcdu->encoders[RCAR_DU_OUTPUT_LVDS0 + rcrtc->index];
>  		const struct drm_display_mode *mode =
>  			&crtc->state->adjusted_mode;
> +		struct drm_bridge *bridge;
>  
> -		rcar_lvds_clk_enable(encoder->base.bridge.next,
> -				     mode->clock * 1000);
> +		bridge = drm_bridge_chain_get_next_bridge(&encoder->base.bridge);
> +		rcar_lvds_clk_enable(bridge, mode->clock * 1000);
>  	}
>  
>  	rcar_du_crtc_start(rcrtc);
> @@ -702,12 +704,14 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
>  	    rstate->outputs == BIT(RCAR_DU_OUTPUT_DPAD0)) {
>  		struct rcar_du_encoder *encoder =
>  			rcdu->encoders[RCAR_DU_OUTPUT_LVDS0 + rcrtc->index];
> +		struct drm_bridge *bridge;
>  
>  		/*
>  		 * Disable the LVDS clock output, see
>  		 * rcar_du_crtc_atomic_enable().
>  		 */
> -		rcar_lvds_clk_disable(encoder->base.bridge.next);
> +		bridge = drm_bridge_chain_get_next_bridge(&encoder->base.bridge);
> +		rcar_lvds_clk_disable(bridge);
>  	}
>  
>  	spin_lock_irq(&crtc->dev->event_lock);
> diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
> index 4aa4c1a94f17..4ea352567cfb 100644
> --- a/drivers/gpu/drm/vc4/vc4_dsi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dsi.c
> @@ -1636,8 +1636,10 @@ static void vc4_dsi_unbind(struct device *dev, struct device *master,
>  	struct drm_device *drm = dev_get_drvdata(master);
>  	struct vc4_dev *vc4 = to_vc4_dev(drm);
>  	struct vc4_dsi *dsi = dev_get_drvdata(dev);
> +	struct drm_bridge *bridge;
>  
> -	if (dsi->encoder->bridge.next)
> +	bridge = drm_bridge_chain_get_next_bridge(&dsi->encoder->bridge);
> +	if (bridge)
>  		pm_runtime_disable(dev);
>  
>  	vc4_dsi_encoder_destroy(dsi->encoder);
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 442a0654e1bf..7809fca99b2d 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -409,6 +409,8 @@ 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 *
> +drm_bridge_chain_get_next_bridge(struct drm_bridge *bridge);
>  bool drm_bridge_chain_mode_fixup(struct drm_bridge *bridge,
>  				 const struct drm_display_mode *mode,
>  				 struct drm_display_mode *adjusted_mode);
> 

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

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

* Re: [PATCH v2 15/21] drm/bridge: Add the drm_bridge_chain_get_prev_bridge() helper
  2019-08-26 15:26 ` [PATCH v2 15/21] drm/bridge: Add the drm_bridge_chain_get_prev_bridge() helper Boris Brezillon
@ 2019-08-27  7:26   ` Neil Armstrong
  0 siblings, 0 replies; 46+ messages in thread
From: Neil Armstrong @ 2019-08-27  7:26 UTC (permalink / raw)
  To: Boris Brezillon, dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Jonas Karlman, Andrey Smirnov, Seung-Woo Kim, Kyungmin Park,
	Thierry Reding, Chris Healy, kernel, Sam Ravnborg

On 26/08/2019 17:26, Boris Brezillon wrote:
> Will be useful for bridge drivers that want to do bus format
> negotiation with their neighbours.

Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>

> 
> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> ---
> Changes in v2:
> * Fix the kerneldoc
> * Drop the !bridge || !bridge->encoder check
> ---
>  drivers/gpu/drm/drm_bridge.c | 17 +++++++++++++++++
>  include/drm/drm_bridge.h     |  2 ++
>  2 files changed, 19 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index 7f7e0ea5b06c..9c74b285da9d 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -238,6 +238,23 @@ drm_bridge_chain_get_next_bridge(struct drm_bridge *bridge)
>  }
>  EXPORT_SYMBOL(drm_bridge_chain_get_next_bridge);
>  
> +/**
> + * drm_bridge_chain_get_prev_bridge() - Get the previous bridge in the chain
> + * @bridge: bridge object
> + *
> + * RETURNS:
> + * the previous bridge in the chain, or NULL if @bridge is the last.
> + */
> +struct drm_bridge *
> +drm_bridge_chain_get_prev_bridge(struct drm_bridge *bridge)
> +{
> +	if (list_is_first(&bridge->chain_node, &bridge->encoder->bridge_chain))
> +		return NULL;
> +
> +	return list_prev_entry(bridge, chain_node);
> +}
> +EXPORT_SYMBOL(drm_bridge_chain_get_prev_bridge);
> +
>  /**
>   * DOC: bridge callbacks
>   *
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 7fdce6dc5f26..95dc58c3a4e8 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -521,6 +521,8 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
>  
>  struct drm_bridge *
>  drm_bridge_chain_get_next_bridge(struct drm_bridge *bridge);
> +struct drm_bridge *
> +drm_bridge_chain_get_prev_bridge(struct drm_bridge *bridge);
>  bool drm_bridge_chain_mode_fixup(struct drm_bridge *bridge,
>  				 const struct drm_display_mode *mode,
>  				 struct drm_display_mode *adjusted_mode);
> 

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

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

* Re: [PATCH v2 11/21] drm/bridge: Add the drm_for_each_bridge_in_chain() helper
  2019-08-26 15:26 ` [PATCH v2 11/21] drm/bridge: Add the drm_for_each_bridge_in_chain() helper Boris Brezillon
@ 2019-08-27  7:26   ` Neil Armstrong
  0 siblings, 0 replies; 46+ messages in thread
From: Neil Armstrong @ 2019-08-27  7:26 UTC (permalink / raw)
  To: Boris Brezillon, dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Jonas Karlman, Andrey Smirnov, Seung-Woo Kim, Kyungmin Park,
	Thierry Reding, Chris Healy, kernel, Sam Ravnborg

On 26/08/2019 17:26, Boris Brezillon wrote:
> To iterate over all bridges attached to a specific encoder.
> 
> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>

Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>

> ---
> Changes in v2:
> * New patch
> ---
>  include/drm/drm_bridge.h | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 8af92f0a9541..cf05b30f2967 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -409,6 +409,17 @@ 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);
>  
> +/**
> + * for_each_bridge_in_chain() - Iterate over all bridges present in a chain
> + * @encoder: the encoder to iterate bridges on
> + * @bridge: a bridge pointer updated to point to the current bridge at each
> + *	    iteration
> + *
> + * Iterate over all bridges present in the bridge chain attached to @encoder.
> + */
> +#define drm_for_each_bridge_in_chain(encoder, bridge)			\
> +	list_for_each_entry(bridge, &(encoder)->bridge_chain, chain_node)
> +
>  struct drm_bridge *
>  drm_bridge_chain_get_next_bridge(struct drm_bridge *bridge);
>  bool drm_bridge_chain_mode_fixup(struct drm_bridge *bridge,
> 

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

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

* Re: [PATCH v2 17/21] drm/imx: pd: Use bus format/flags provided by the bridge when available
  2019-08-26 15:26 ` [PATCH v2 17/21] drm/imx: pd: Use bus format/flags provided by the bridge when available Boris Brezillon
@ 2019-08-27  8:15   ` Philipp Zabel
  2019-08-27  8:43     ` Boris Brezillon
  0 siblings, 1 reply; 46+ messages in thread
From: Philipp Zabel @ 2019-08-27  8:15 UTC (permalink / raw)
  To: Boris Brezillon, dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, kernel, Sam Ravnborg

Hi Boris,

On Mon, 2019-08-26 at 17:26 +0200, Boris Brezillon wrote:
> Now that bridges can expose the bus format/flags they expect, we can
> use those instead of the relying on the display_info provided by the
> connector (which is only valid if the encoder is directly connected
> to bridge element driving the panel/display).
> 
> We also explicitly expose the bus formats supported by our encoder by
> filling encoder->output_bus_caps with proper info.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> ---
> Changes in v2:
> * Adjust things to match the new bus-format negotiation infra
> ---
>  drivers/gpu/drm/imx/parallel-display.c | 136 ++++++++++++++++++++++---
>  1 file changed, 120 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
> index 35518e5de356..df47cb74759f 100644
> --- a/drivers/gpu/drm/imx/parallel-display.c
> +++ b/drivers/gpu/drm/imx/parallel-display.c
> @@ -89,37 +89,139 @@ static struct drm_encoder *imx_pd_connector_best_encoder(
>  	return &imxpd->encoder;
>  }
>  
> -static void imx_pd_encoder_enable(struct drm_encoder *encoder)
> +static void imx_pd_bridge_enable(struct drm_bridge *bridge)
>  {
> +	struct drm_encoder *encoder = bridge_to_encoder(bridge);
>  	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
>  
>  	drm_panel_prepare(imxpd->panel);
>  	drm_panel_enable(imxpd->panel);
>  }
>  
> -static void imx_pd_encoder_disable(struct drm_encoder *encoder)
> +static void imx_pd_bridge_disable(struct drm_bridge *bridge)
>  {
> +	struct drm_encoder *encoder = bridge_to_encoder(bridge);
>  	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
>  
>  	drm_panel_disable(imxpd->panel);
>  	drm_panel_unprepare(imxpd->panel);
>  }
>  
> -static int imx_pd_encoder_atomic_check(struct drm_encoder *encoder,
> -				       struct drm_crtc_state *crtc_state,
> -				       struct drm_connector_state *conn_state)
> +static const u32 imx_pd_bus_fmts[] = {
> +	MEDIA_BUS_FMT_RGB888_1X24,
> +	MEDIA_BUS_FMT_RGB565_1X16,
> +	MEDIA_BUS_FMT_RGB666_1X18,
> +	MEDIA_BUS_FMT_RGB666_1X24_CPADHI,

ipu-dc.c also supports MEDIA_BUS_FMT_BGR888_1X24.

> +};
> +
> +static void
> +imx_pd_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
> +					 struct drm_bridge_state *bridge_state,
> +					 struct drm_crtc_state *crtc_state,
> +					 struct drm_connector_state *conn_state,
> +					 unsigned int *num_output_fmts,
> +					 u32 *output_fmts)
>  {
> +	struct drm_display_info *di = &conn_state->connector->display_info;
> +	struct drm_encoder *encoder = bridge_to_encoder(bridge);
> +	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
> +
> +	*num_output_fmts = 1;
> +	if (imxpd->bus_format) {
> +		if (output_fmts)
> +			output_fmts[0] = imxpd->bus_format;

This is the legacy DT configured interface-pix-fmt. Maybe this should be
moved to the last place.

> +	} else if (di->num_bus_formats) {
> +		*num_output_fmts = 1;

num_output_fmts is already set to one above.

> +		if (output_fmts)
> +			output_fmts[0] = di->bus_formats[0];
> +	} else {
> +		*num_output_fmts = ARRAY_SIZE(imx_pd_bus_fmts);
> +		if (output_fmts)
> +			memcpy(output_fmts, imx_pd_bus_fmts,
> +			       ARRAY_SIZE(imx_pd_bus_fmts));
> +	}
> +}
> +
> +static void
> +imx_pd_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
> +					struct drm_bridge_state *bridge_state,
> +					struct drm_crtc_state *crtc_state,
> +					struct drm_connector_state *conn_state,
> +					u32 output_fmt,
> +					unsigned int *num_input_fmts,
> +					u32 *input_fmts)
> +{
> +	struct drm_encoder *encoder = bridge_to_encoder(bridge);
> +	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
> +
> +	*num_input_fmts = 0;
> +	if (output_fmt == MEDIA_BUS_FMT_FIXED) {
> +		*num_input_fmts = 1;

I don't understand this. The bus format stored in imx_crtc_state by
atomic_check is used to configure the DC later. This should never be
MEDIA_BUS_FMT_FIXED, that would trigger a WARN_ON in
ipu_bus_format_to_map().

> +	} else if (!imxpd->bus_format) {
> +		unsigned int i;
> +
> +		for (i = 0; i < ARRAY_SIZE(imx_pd_bus_fmts); i++) {
> +			if (imx_pd_bus_fmts[i] == output_fmt) {
> +				*num_input_fmts = 1;
> +				break;
> +			}
> +		}
> +	} else if (imxpd->bus_format == output_fmt) {
> +		*num_input_fmts = 1;
> +	}
> +
> +	if (*num_input_fmts && input_fmts)
> +		input_fmts[0] = MEDIA_BUS_FMT_FIXED;

The parallel-display driver basically represents the wiring, pinmux, and
drivers between the IPU DI and the DISP pads. The input format should
always be identical to the output format.

> +}
> +
> +static int imx_pd_bridge_atomic_check(struct drm_bridge *bridge,
> +				      struct drm_bridge_state *bridge_state,
> +				      struct drm_crtc_state *crtc_state,
> +				      struct drm_connector_state *conn_state)
> +{
> +	struct drm_encoder *encoder = bridge_to_encoder(bridge);
>  	struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc_state);
>  	struct drm_display_info *di = &conn_state->connector->display_info;
>  	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
> +	struct drm_bridge_state *next_bridge_state = NULL;
> +	struct drm_bridge *next_bridge;
> +	u32 bus_flags, bus_fmt;
> +	unsigned int i;
>  
> -	if (!imxpd->bus_format && di->num_bus_formats) {
> -		imx_crtc_state->bus_flags = di->bus_flags;
> -		imx_crtc_state->bus_format = di->bus_formats[0];
> -	} else {
> -		imx_crtc_state->bus_flags = imxpd->bus_flags;
> -		imx_crtc_state->bus_format = imxpd->bus_format;
> +	next_bridge = drm_bridge_chain_get_next_bridge(bridge);
> +	if (next_bridge)
> +		next_bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state,
> +								    next_bridge);
> +
> +	bus_fmt = bridge_state->output_bus_cfg.fmt;
> +	if (bus_fmt == MEDIA_BUS_FMT_FIXED)
> +		bus_fmt = 0;

I would expect this to return with -EINVAL if bridge_state-
>output_bus_cfg.fmt is not in the list of supported formats.

> +
> +	if (next_bridge_state)
> +		bus_flags = next_bridge_state->input_bus_cfg.flags;
> +	else if (!imxpd->bus_format && di->num_bus_formats)
> +		bus_flags = di->bus_flags;
> +	else
> +		bus_flags = imxpd->bus_flags;
> +
> +	for (i = 0; bus_fmt && i < ARRAY_SIZE(imx_pd_bus_fmts); i++) {
> +		if (imx_pd_bus_fmts[i] == bridge_state->output_bus_cfg.fmt)
> +			break;
>  	}
> +
> +	if (i == ARRAY_SIZE(imx_pd_bus_fmts))
> +		return -EINVAL;
> +
> +	if (bus_flags &
> +	    ~(DRM_BUS_FLAG_DE_LOW | DRM_BUS_FLAG_DE_HIGH |
> +	      DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE |
> +	      DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE))
> +		return -EINVAL;

This could allow DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE/NEGEDGE as well, if
they are not opposite to PIXDATA_DRIVE.

> +	bridge_state->output_bus_cfg.flags = bus_flags;
> +	bridge_state->input_bus_cfg.flags = bus_flags;
> +	imx_crtc_state->bus_flags = bus_flags;
> +	imx_crtc_state->bus_format = bridge_state->output_bus_cfg.fmt;

This should be the input bus format.

>  	imx_crtc_state->di_hsync_pin = 2;
>  	imx_crtc_state->di_vsync_pin = 3;
>  
> @@ -143,10 +245,12 @@ static const struct drm_encoder_funcs imx_pd_encoder_funcs = {
>  	.destroy = imx_drm_encoder_destroy,
>  };
>  
> -static const struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = {
> -	.enable = imx_pd_encoder_enable,
> -	.disable = imx_pd_encoder_disable,
> -	.atomic_check = imx_pd_encoder_atomic_check,
> +static const struct drm_bridge_funcs imx_pd_bridge_funcs = {
> +	.enable = imx_pd_bridge_enable,
> +	.disable = imx_pd_bridge_disable,
> +	.atomic_check = imx_pd_bridge_atomic_check,
> +	.atomic_get_input_bus_fmts = imx_pd_bridge_atomic_get_input_bus_fmts,
> +	.atomic_get_output_bus_fmts = imx_pd_bridge_atomic_get_output_bus_fmts,
>  };
>  
>  static int imx_pd_register(struct drm_device *drm,
> @@ -166,7 +270,7 @@ static int imx_pd_register(struct drm_device *drm,
>  	 */
>  	imxpd->connector.dpms = DRM_MODE_DPMS_OFF;
>  
> -	drm_encoder_helper_add(encoder, &imx_pd_encoder_helper_funcs);
> +	encoder->bridge.funcs = &imx_pd_bridge_funcs;
>  	drm_encoder_init(drm, encoder, &imx_pd_encoder_funcs,
>  			 DRM_MODE_ENCODER_NONE, NULL);

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

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

* Re: [PATCH v2 16/21] drm/bridge: Add the necessary bits to support bus format negotiation
  2019-08-26 15:26 ` [PATCH v2 16/21] drm/bridge: Add the necessary bits to support bus format negotiation Boris Brezillon
@ 2019-08-27  8:18   ` Neil Armstrong
  0 siblings, 0 replies; 46+ messages in thread
From: Neil Armstrong @ 2019-08-27  8:18 UTC (permalink / raw)
  To: Boris Brezillon, dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Jonas Karlman, Andrey Smirnov, Seung-Woo Kim, Kyungmin Park,
	Thierry Reding, Chris Healy, kernel, Sam Ravnborg

On 26/08/2019 17:26, Boris Brezillon wrote:
> This takes the form of various helpers, plus the addition of 2 new
> structs:
> * drm_bus_caps: describe the bus capabilities of a bridge/encoder. For
>   bridges we have one for the input port and one for the output port.
>   Encoders just have one output port.
> * drm_bus_cfg: added to the drm_bridge_state. It's supposed to store
>   bus configuration information. For now we just have format and flags
>   but more fields might be added in the future. Again, each
>   drm_bridge_state contains 2 drm_bus_cfg elements: one for the output
>   port and one for the input port
> 
> Helpers can be used from bridge drivers' ->atomic_check() implementation
> to negotiate the bus format to use. Negotiation happens in reserve order,
> starting from the last element of the bridge chain (the one directly
> connected to the display) to the first element of the chain (the one
> connected to the encoder).
> 
> Negotiation usually takes place in 2 steps:
> * make sure the input end of the next element in the chain picked a
>   format that's supported by the output end of our bridge. That's done
>   with drm_atomic_bridge_choose_output_bus_cfg().
> * choose a format for the input end of our bridge based on what's
>   supported by the previous bridge in the chain. This is achieved by
>   calling drm_atomic_bridge_choose_input_bus_cfg()
> 
> Note that those helpers are a bit lax when it comes to uninitialized
> bus format validation. That's intentional. If we don't do that we'll
> basically break things if we start adding support for bus format
> negotiation to some elements of the pipeline leaving others on the
> side, and that's likely to happen for all external bridges since we
> can't necessarily tell where they are used.

I'll wait Laurent's feedback on this one, but I implemented the DW-HDMI
negotiation with it, and it works fine, see [1]

Tested-by: Neil Armstrong <narmstrong@baylibre.com>

[1] https://patchwork.freedesktop.org/patch/msgid/20190827081425.15011-4-narmstrong@baylibre.com

> 
> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> ---
> Changes in v2:
> * Rework things to support more complex use cases
> ---
>  drivers/gpu/drm/drm_bridge.c | 179 ++++++++++++++++++++++++++++++++++-
>  include/drm/drm_bridge.h     |  82 ++++++++++++++++
>  2 files changed, 260 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index 9c74b285da9d..b53732ac997d 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -624,13 +624,184 @@ static int drm_atomic_bridge_check(struct drm_bridge *bridge,
>  	return 0;
>  }
>  
> +static int select_bus_fmt_recursive(struct drm_bridge *first,
> +				    struct drm_bridge *cur,
> +				    struct drm_crtc_state *crtc_state,
> +				    struct drm_connector_state *conn_state,
> +				    u32 out_bus_fmt)
> +{
> +	struct drm_bridge_state *cur_state;
> +	unsigned int num_in_bus_fmts, i;
> +	struct drm_bridge *prev;
> +	u32 *in_bus_fmts;
> +	int ret;
> +
> +	prev = drm_bridge_chain_get_prev_bridge(cur);
> +	cur_state = drm_atomic_get_new_bridge_state(crtc_state->state, cur);
> +	if (WARN_ON(!cur_state))
> +		return -EINVAL;
> +
> +	/*
> +	 * Bus format negotiation is not supported by this bridge, let's pass
> +	 * MEDIA_BUS_FMT_FIXED to the previous bridge in the chain and hope
> +	 * that it can handle this situation gracefully (by providing
> +	 * appropriate default values).
> +	 */
> +	if (!cur->funcs->atomic_get_input_bus_fmts) {
> +		if (cur != first) {
> +			ret = select_bus_fmt_recursive(first, prev, crtc_state,
> +						       conn_state,
> +						       MEDIA_BUS_FMT_FIXED);
> +			if (ret)
> +				return ret;
> +		}
> +
> +		cur_state->input_bus_cfg.fmt = MEDIA_BUS_FMT_FIXED;
> +		cur_state->output_bus_cfg.fmt = out_bus_fmt;
> +		return 0;
> +	}
> +
> +	cur->funcs->atomic_get_input_bus_fmts(cur, cur_state, crtc_state,
> +					      conn_state, out_bus_fmt,
> +					      &num_in_bus_fmts, NULL);
> +	if (!num_in_bus_fmts)
> +		return -ENOTSUPP;
> +
> +	in_bus_fmts = kcalloc(num_in_bus_fmts, sizeof(*in_bus_fmts),
> +			      GFP_KERNEL);
> +	if (!in_bus_fmts)
> +		return -ENOMEM;
> +
> +	cur->funcs->atomic_get_input_bus_fmts(cur, cur_state, crtc_state,
> +					      conn_state, out_bus_fmt,
> +					      &num_in_bus_fmts, in_bus_fmts);
> +
> +	if (first == cur) {
> +		cur_state->input_bus_cfg.fmt = in_bus_fmts[0];
> +		cur_state->output_bus_cfg.fmt = out_bus_fmt;
> +		kfree(in_bus_fmts);
> +		return 0;
> +	}
> +
> +	for (i = 0; i < num_in_bus_fmts; i++) {
> +		ret = select_bus_fmt_recursive(first, prev, crtc_state,
> +					       conn_state, in_bus_fmts[i]);
> +		if (ret != -ENOTSUPP)
> +			break;
> +	}
> +
> +	if (!ret) {
> +		cur_state->input_bus_cfg.fmt = in_bus_fmts[i];
> +		cur_state->output_bus_cfg.fmt = out_bus_fmt;
> +	}
> +
> +	kfree(in_bus_fmts);
> +	return ret;
> +}
> +
> +/*
> + * This function is called by &drm_atomic_bridge_chain_check() just before
> + * calling &drm_bridge_funcs.atomic_check() on all elements of the chain.
> + * It's providing bus format negotiation between bridge elements. The
> + * negotiation happens in reverse order, starting from the last element in
> + * the chain up to @bridge.
> + *
> + * Negotiation starts by retrieving supported output bus formats on the last
> + * bridge element and testing them one by one. The test is recursive, meaning
> + * that for each tested output format, the whole chain will be walked backward,
> + * and each element will have to choose an input bus format that can be
> + * transcoded to the requested output format. When a bridge element does not
> + * support transcoding into a specific output format -ENOTSUPP is returned and
> + * the next bridge element will have to try a different format. If none of the
> + * combinations worked, -ENOTSUPP is returned and the atomic modeset will fail.
> + *
> + * This implementation is relying on
> + * &drm_bridge_funcs.atomic_get_output_bus_fmts() and
> + * &drm_bridge_funcs.atomic_get_input_bus_fmts() to gather supported
> + * input/output formats.
> + * When &drm_bridge_funcs.atomic_get_output_bus_fmts() is not implemented by
> + * the last element of the chain, &drm_atomic_bridge_chain_select_bus_fmts()
> + * tries a single format: &drm_connector.display_info.bus_formats[0] if
> + * available, MEDIA_BUS_FMT_FIXED otherwise.
> + * When &drm_bridge_funcs.atomic_get_input_bus_fmts() is not implemented,
> + * &drm_atomic_bridge_chain_select_bus_fmts() skips the negotiation on the
> + * bridge element that lacks this hook and asks the previous element in the
> + * chain to try MEDIA_BUS_FMT_FIXED. It's up to bridge drivers to decide what
> + * to do in that case (fail if they want to enforce bus format negotiation, or
> + * provide a reasonable default if they need to support pipelines where not
> + * all elements support bus format negotiation).
> + */
> +static int
> +drm_atomic_bridge_chain_select_bus_fmts(struct drm_bridge *bridge,
> +					struct drm_crtc_state *crtc_state,
> +					struct drm_connector_state *conn_state)
> +{
> +	struct drm_connector *conn = conn_state->connector;
> +	struct drm_encoder *encoder = bridge->encoder;
> +	struct drm_bridge_state *last_bridge_state;
> +	unsigned int i, num_out_bus_fmts;
> +	struct drm_bridge *last_bridge;
> +	u32 *out_bus_fmts;
> +	int ret = 0;
> +
> +	last_bridge = list_last_entry(&encoder->bridge_chain,
> +				      struct drm_bridge, chain_node);
> +	last_bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state,
> +							    last_bridge);
> +	if (WARN_ON(!last_bridge_state))
> +		return -EINVAL;
> +
> +	if (last_bridge->funcs->atomic_get_output_bus_fmts)
> +		last_bridge->funcs->atomic_get_output_bus_fmts(last_bridge,
> +							last_bridge_state,
> +							crtc_state,
> +							conn_state,
> +							&num_out_bus_fmts,
> +							NULL);
> +	else
> +		num_out_bus_fmts = 1;
> +
> +	if (!num_out_bus_fmts)
> +		return -ENOTSUPP;
> +
> +	out_bus_fmts = kcalloc(num_out_bus_fmts, sizeof(*out_bus_fmts),
> +			       GFP_KERNEL);
> +	if (!out_bus_fmts)
> +		return -ENOMEM;
> +
> +	if (last_bridge->funcs->atomic_get_output_bus_fmts)
> +		last_bridge->funcs->atomic_get_output_bus_fmts(last_bridge,
> +							last_bridge_state,
> +							crtc_state,
> +							conn_state,
> +							&num_out_bus_fmts,
> +							out_bus_fmts);
> +	else if (conn->display_info.num_bus_formats &&
> +		 conn->display_info.bus_formats)
> +		out_bus_fmts[0] = conn->display_info.bus_formats[0];
> +	else
> +		out_bus_fmts[0] = MEDIA_BUS_FMT_FIXED;
> +
> +	for (i = 0; i < num_out_bus_fmts; i++) {
> +		ret = select_bus_fmt_recursive(bridge, last_bridge, crtc_state,
> +					       conn_state, out_bus_fmts[i]);
> +		if (ret != -ENOTSUPP)
> +			break;
> +	}
> +
> +	kfree(out_bus_fmts);
> +
> +	return ret;
> +}
> +
>  /**
>   * drm_atomic_bridge_chain_check() - Do an atomic check on the bridge chain
>   * @bridge: bridge control structure
>   * @crtc_state: new CRTC state
>   * @conn_state: new connector state
>   *
> - * Calls &drm_bridge_funcs.atomic_check() (falls back on
> + * First trigger a bus format negotiation before calling
> + * &drm_bridge_funcs.atomic_check() (falls back on
>   * &drm_bridge_funcs.mode_fixup()) op for all the bridges in the encoder chain,
>   * starting from the last bridge to the first. These are called before calling
>   * &drm_encoder_helper_funcs.atomic_check()
> @@ -644,6 +815,12 @@ int drm_atomic_bridge_chain_check(struct drm_bridge *bridge,
>  {
>  	struct drm_encoder *encoder = bridge->encoder;
>  	struct drm_bridge *iter;
> +	int ret;
> +
> +	ret = drm_atomic_bridge_chain_select_bus_fmts(bridge, crtc_state,
> +						      conn_state);
> +	if (ret)
> +		return ret;
>  
>  	list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
>  		int ret;
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 95dc58c3a4e8..96df3bedfee4 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -33,15 +33,33 @@ struct drm_bridge;
>  struct drm_bridge_timings;
>  struct drm_panel;
>  
> +/**
> + * struct drm_bus_cfg - bus configuration
> + * @fmt: format used on this bus
> + * @flags: DRM_BUS_ flags used on this bus
> + *
> + * Encodes the bus format and bus flags used by one end of the bridge or
> + * by the encoder output.
> + */
> +struct drm_bus_cfg {
> +	u32 fmt;
> +	u32 flags;
> +};
> +
>  /**
>   * struct drm_bridge_state - Atomic bridge state object
>   * @base: inherit from &drm_private_state
>   * @bridge: the bridge this state refers to
> + * @input_bus_info: input bus information
> + * @output_bus_info: output bus information
>   */
>  struct drm_bridge_state {
>  	struct drm_private_state base;
>  
>  	struct drm_bridge *bridge;
> +
> +	struct drm_bus_cfg input_bus_cfg;
> +	struct drm_bus_cfg output_bus_cfg;
>  };
>  
>  static inline struct drm_bridge_state *
> @@ -391,6 +409,70 @@ struct drm_bridge_funcs {
>  	void (*atomic_destroy_state)(struct drm_bridge *bridge,
>  				     struct drm_bridge_state *state);
>  
> +	/**
> +	 * @atomic_get_output_bus_fmts:
> +	 *
> +	 * Return the supported bus formats on the output end of a bridge.
> +	 * This method is called twice. Once with output_fmts set NULL, in this
> +	 * case the driver should set num_output_fmts to the number of
> +	 * supported output bus formats such that the core can allocate an
> +	 * array of the right dimension. The second time it's called with a
> +	 * non-NULL output_fmts, and the driver is expected to fill the
> +	 * output_fmts array. The output_fmts array passed to the driver is
> +	 * guaranteed to be big enough to store the number of entries returned
> +	 * on the first call (no need to check num_output_fmts).
> +	 *
> +	 * This method is only called on the last element of the bridge chain
> +	 * as part of the bus format negotiation process that happens in
> +	 * &drm_atomic_bridge_chain_select_bus_fmts().
> +	 * This method is optional. When not implemented, the core will
> +	 * fallback to &drm_connector.display_info.bus_formats[0] if
> +	 * &drm_connector.display_info.num_bus_formats > 0,
> +	 * MEDIA_BUS_FMT_FIXED otherwise.
> +	 */
> +	void (*atomic_get_output_bus_fmts)(struct drm_bridge *bridge,
> +					   struct drm_bridge_state *bridge_state,
> +					   struct drm_crtc_state *crtc_state,
> +					   struct drm_connector_state *conn_state,
> +					   unsigned int *num_output_fmts,
> +					   u32 *output_fmts);
> +
> +	/**
> +	 * @atomic_get_input_bus_fmts:
> +	 *
> +	 * Return the supported bus formats on the input end of a bridge for
> +	 * a specific output bus format.
> +	 * This method is called twice. Once with input_fmts set NULL, in this
> +	 * case the driver should set num_input_fmts to the number of
> +	 * supported input bus formats such that the core can allocate an array
> +	 * of the right dimension. The second time it's called with a non-NULL
> +	 * input_fmts, and the driver is expected to fill the input_fmts array.
> +	 * The input_fmts array passed to the driver is guaranteed to be big
> +	 * enough to store the number of entries returned on the first call (no
> +	 * need to check num_input_fmts).
> +	 *
> +	 * This method is called on all element of the bridge chain as part of
> +	 * the bus format negotiation process that happens in
> +	 * &drm_atomic_bridge_chain_select_bus_fmts().
> +	 * This method is optional. When not implemented, the core will bypass
> +	 * bus format negotiation on this element of the bridge without
> +	 * failing, and the previous element in the chain will be passed
> +	 * MEDIA_BUS_FMT_FIXED as its output bus format.
> +	 *
> +	 * Bridge drivers that need to support being linked to bridges that are
> +	 * not supporting bus format negotiation should handle the
> +	 * output_fmt == MEDIA_BUS_FMT_FIXED case appropriately, by selecting a
> +	 * sensible default value or extracting this information from somewhere
> +	 * else (FW property, &drm_display_mode, &drm_display_info, ...)
> +	 */
> +	void (*atomic_get_input_bus_fmts)(struct drm_bridge *bridge,
> +					  struct drm_bridge_state *bridge_state,
> +					  struct drm_crtc_state *crtc_state,
> +					  struct drm_connector_state *conn_state,
> +					  u32 output_fmt,
> +					  unsigned int *num_input_fmts,
> +					  u32 *input_fmts);
> +
>  	/**
>  	 * @atomic_check:
>  	 *
> 

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

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

* Re: [PATCH v2 17/21] drm/imx: pd: Use bus format/flags provided by the bridge when available
  2019-08-27  8:15   ` Philipp Zabel
@ 2019-08-27  8:43     ` Boris Brezillon
  2019-08-27  9:23       ` Philipp Zabel
  0 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2019-08-27  8:43 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	dri-devel, Kyungmin Park, Thierry Reding, Chris Healy, kernel,
	Sam Ravnborg

On Tue, 27 Aug 2019 10:15:19 +0200
Philipp Zabel <p.zabel@pengutronix.de> wrote:

> Hi Boris,
> 
> On Mon, 2019-08-26 at 17:26 +0200, Boris Brezillon wrote:
> > Now that bridges can expose the bus format/flags they expect, we can
> > use those instead of the relying on the display_info provided by the
> > connector (which is only valid if the encoder is directly connected
> > to bridge element driving the panel/display).
> > 
> > We also explicitly expose the bus formats supported by our encoder by
> > filling encoder->output_bus_caps with proper info.
> > 
> > Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> > ---
> > Changes in v2:
> > * Adjust things to match the new bus-format negotiation infra
> > ---
> >  drivers/gpu/drm/imx/parallel-display.c | 136 ++++++++++++++++++++++---
> >  1 file changed, 120 insertions(+), 16 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
> > index 35518e5de356..df47cb74759f 100644
> > --- a/drivers/gpu/drm/imx/parallel-display.c
> > +++ b/drivers/gpu/drm/imx/parallel-display.c
> > @@ -89,37 +89,139 @@ static struct drm_encoder *imx_pd_connector_best_encoder(
> >  	return &imxpd->encoder;
> >  }
> >  
> > -static void imx_pd_encoder_enable(struct drm_encoder *encoder)
> > +static void imx_pd_bridge_enable(struct drm_bridge *bridge)
> >  {
> > +	struct drm_encoder *encoder = bridge_to_encoder(bridge);
> >  	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
> >  
> >  	drm_panel_prepare(imxpd->panel);
> >  	drm_panel_enable(imxpd->panel);
> >  }
> >  
> > -static void imx_pd_encoder_disable(struct drm_encoder *encoder)
> > +static void imx_pd_bridge_disable(struct drm_bridge *bridge)
> >  {
> > +	struct drm_encoder *encoder = bridge_to_encoder(bridge);
> >  	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
> >  
> >  	drm_panel_disable(imxpd->panel);
> >  	drm_panel_unprepare(imxpd->panel);
> >  }
> >  
> > -static int imx_pd_encoder_atomic_check(struct drm_encoder *encoder,
> > -				       struct drm_crtc_state *crtc_state,
> > -				       struct drm_connector_state *conn_state)
> > +static const u32 imx_pd_bus_fmts[] = {
> > +	MEDIA_BUS_FMT_RGB888_1X24,
> > +	MEDIA_BUS_FMT_RGB565_1X16,
> > +	MEDIA_BUS_FMT_RGB666_1X18,
> > +	MEDIA_BUS_FMT_RGB666_1X24_CPADHI,  
> 
> ipu-dc.c also supports MEDIA_BUS_FMT_BGR888_1X24.

Will add that one to the list.

> 
> > +};
> > +
> > +static void
> > +imx_pd_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
> > +					 struct drm_bridge_state *bridge_state,
> > +					 struct drm_crtc_state *crtc_state,
> > +					 struct drm_connector_state *conn_state,
> > +					 unsigned int *num_output_fmts,
> > +					 u32 *output_fmts)
> >  {
> > +	struct drm_display_info *di = &conn_state->connector->display_info;
> > +	struct drm_encoder *encoder = bridge_to_encoder(bridge);
> > +	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
> > +
> > +	*num_output_fmts = 1;
> > +	if (imxpd->bus_format) {
> > +		if (output_fmts)
> > +			output_fmts[0] = imxpd->bus_format;  
> 
> This is the legacy DT configured interface-pix-fmt. Maybe this should be
> moved to the last place.

Hm, shouldn't we restrict things to a single format when we have the
DT prop defined?

> 
> > +	} else if (di->num_bus_formats) {
> > +		*num_output_fmts = 1;  
> 
> num_output_fmts is already set to one above.

Correct, I'll get rid of this assignment.

> 
> > +		if (output_fmts)
> > +			output_fmts[0] = di->bus_formats[0];
> > +	} else {
> > +		*num_output_fmts = ARRAY_SIZE(imx_pd_bus_fmts);
> > +		if (output_fmts)
> > +			memcpy(output_fmts, imx_pd_bus_fmts,
> > +			       ARRAY_SIZE(imx_pd_bus_fmts));
> > +	}
> > +}
> > +
> > +static void
> > +imx_pd_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
> > +					struct drm_bridge_state *bridge_state,
> > +					struct drm_crtc_state *crtc_state,
> > +					struct drm_connector_state *conn_state,
> > +					u32 output_fmt,
> > +					unsigned int *num_input_fmts,
> > +					u32 *input_fmts)
> > +{
> > +	struct drm_encoder *encoder = bridge_to_encoder(bridge);
> > +	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
> > +
> > +	*num_input_fmts = 0;
> > +	if (output_fmt == MEDIA_BUS_FMT_FIXED) {
> > +		*num_input_fmts = 1;  
> 
> I don't understand this. The bus format stored in imx_crtc_state by
> atomic_check is used to configure the DC later. This should never be
> MEDIA_BUS_FMT_FIXED, that would trigger a WARN_ON in
> ipu_bus_format_to_map().

MEDIA_BUS_FMT_FIXED is the default value used when the next bridge in
the chain does not support bus format negotiation. When the driver
receives this value, it should pick a default value (which I might have
gotten wrong here) so that it keeps working even if some elements of
the bridge chain don't support negotiating the bus format yet.

> 
> > +	} else if (!imxpd->bus_format) {
> > +		unsigned int i;
> > +
> > +		for (i = 0; i < ARRAY_SIZE(imx_pd_bus_fmts); i++) {
> > +			if (imx_pd_bus_fmts[i] == output_fmt) {
> > +				*num_input_fmts = 1;
> > +				break;
> > +			}
> > +		}
> > +	} else if (imxpd->bus_format == output_fmt) {
> > +		*num_input_fmts = 1;
> > +	}
> > +
> > +	if (*num_input_fmts && input_fmts)
> > +		input_fmts[0] = MEDIA_BUS_FMT_FIXED;  
> 
> The parallel-display driver basically represents the wiring, pinmux, and
> drivers between the IPU DI and the DISP pads. The input format should
> always be identical to the output format.

I can do that if you like. Note that we are forwarding
the ->output_bus_cfg.fmt value to the IPU DI, not ->input_bus_cfg.fmt.
I just assumed that input format wouldn't be used in the dummy bridge
element (the one embedded in the encoder) since encoders only have an
output end (input port is likely to be a SoC specific link between the
CRTC and the encoder which we probably don't need/want to expose).

> 
> > +}
> > +
> > +static int imx_pd_bridge_atomic_check(struct drm_bridge *bridge,
> > +				      struct drm_bridge_state *bridge_state,
> > +				      struct drm_crtc_state *crtc_state,
> > +				      struct drm_connector_state *conn_state)
> > +{
> > +	struct drm_encoder *encoder = bridge_to_encoder(bridge);
> >  	struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc_state);
> >  	struct drm_display_info *di = &conn_state->connector->display_info;
> >  	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
> > +	struct drm_bridge_state *next_bridge_state = NULL;
> > +	struct drm_bridge *next_bridge;
> > +	u32 bus_flags, bus_fmt;
> > +	unsigned int i;
> >  
> > -	if (!imxpd->bus_format && di->num_bus_formats) {
> > -		imx_crtc_state->bus_flags = di->bus_flags;
> > -		imx_crtc_state->bus_format = di->bus_formats[0];
> > -	} else {
> > -		imx_crtc_state->bus_flags = imxpd->bus_flags;
> > -		imx_crtc_state->bus_format = imxpd->bus_format;
> > +	next_bridge = drm_bridge_chain_get_next_bridge(bridge);
> > +	if (next_bridge)
> > +		next_bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state,
> > +								    next_bridge);
> > +
> > +	bus_fmt = bridge_state->output_bus_cfg.fmt;
> > +	if (bus_fmt == MEDIA_BUS_FMT_FIXED)
> > +		bus_fmt = 0;  
> 
> I would expect this to return with -EINVAL if bridge_state-
> >output_bus_cfg.fmt is not in the list of supported formats.

As said above, we need a way to support bridge chains where not all
elements support negotiating the bus format, that's what this fallback
is for, but maybe 0 is not an appropriate value to mean 'pick the
default format'.

> 
> > +
> > +	if (next_bridge_state)
> > +		bus_flags = next_bridge_state->input_bus_cfg.flags;
> > +	else if (!imxpd->bus_format && di->num_bus_formats)
> > +		bus_flags = di->bus_flags;
> > +	else
> > +		bus_flags = imxpd->bus_flags;
> > +
> > +	for (i = 0; bus_fmt && i < ARRAY_SIZE(imx_pd_bus_fmts); i++) {
> > +		if (imx_pd_bus_fmts[i] == bridge_state->output_bus_cfg.fmt)
> > +			break;
> >  	}
> > +
> > +	if (i == ARRAY_SIZE(imx_pd_bus_fmts))
> > +		return -EINVAL;
> > +
> > +	if (bus_flags &
> > +	    ~(DRM_BUS_FLAG_DE_LOW | DRM_BUS_FLAG_DE_HIGH |
> > +	      DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE |
> > +	      DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE))
> > +		return -EINVAL;  
> 
> This could allow DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE/NEGEDGE as well, if
> they are not opposite to PIXDATA_DRIVE.

Okay, will add those flags and check that PIXDATA and SYNC are
consistent.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 17/21] drm/imx: pd: Use bus format/flags provided by the bridge when available
  2019-08-27  8:43     ` Boris Brezillon
@ 2019-08-27  9:23       ` Philipp Zabel
  2019-08-27  9:57         ` Boris Brezillon
  0 siblings, 1 reply; 46+ messages in thread
From: Philipp Zabel @ 2019-08-27  9:23 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	dri-devel, Kyungmin Park, Thierry Reding, Chris Healy, kernel,
	Sam Ravnborg

On Tue, 2019-08-27 at 10:43 +0200, Boris Brezillon wrote:
[...]
> > > +static void
> > > +imx_pd_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
> > > +					 struct drm_bridge_state *bridge_state,
> > > +					 struct drm_crtc_state *crtc_state,
> > > +					 struct drm_connector_state *conn_state,
> > > +					 unsigned int *num_output_fmts,
> > > +					 u32 *output_fmts)
> > >  {
> > > +	struct drm_display_info *di = &conn_state->connector->display_info;
> > > +	struct drm_encoder *encoder = bridge_to_encoder(bridge);
> > > +	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
> > > +
> > > +	*num_output_fmts = 1;
> > > +	if (imxpd->bus_format) {
> > > +		if (output_fmts)
> > > +			output_fmts[0] = imxpd->bus_format;  
> > 
> > This is the legacy DT configured interface-pix-fmt. Maybe this should be
> > moved to the last place.
> 
> Hm, shouldn't we restrict things to a single format when we have the
> DT prop defined?

Absolutely. This was just a cosmetic remark. I'm suggesting to put this
branch below the other two, to indicate its relative importance.

[...]
> > > +static void
> > > +imx_pd_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
> > > +					struct drm_bridge_state *bridge_state,
> > > +					struct drm_crtc_state *crtc_state,
> > > +					struct drm_connector_state *conn_state,
> > > +					u32 output_fmt,
> > > +					unsigned int *num_input_fmts,
> > > +					u32 *input_fmts)
> > > +{
> > > +	struct drm_encoder *encoder = bridge_to_encoder(bridge);
> > > +	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
> > > +
> > > +	*num_input_fmts = 0;
> > > +	if (output_fmt == MEDIA_BUS_FMT_FIXED) {
> > > +		*num_input_fmts = 1;  
> > 
> > I don't understand this. The bus format stored in imx_crtc_state by
> > atomic_check is used to configure the DC later. This should never be
> > MEDIA_BUS_FMT_FIXED, that would trigger a WARN_ON in
> > ipu_bus_format_to_map().
> 
> MEDIA_BUS_FMT_FIXED is the default value used when the next bridge in
> the chain does not support bus format negotiation. When the driver
> receives this value, it should pick a default value (which I might have
> gotten wrong here) so that it keeps working even if some elements of
> the bridge chain don't support negotiating the bus format yet.

That was unexpected, as MEDIA_BUS_FMT_FIXED is documented as:

  "MEDIA_BUS_FMT_FIXED shall be used by host-client pairs,
   where the data format is fixed."

in include/uapi/linux/media-bus-format.h. I read this as something for a
fixed link between two known devices where there is only one possible
format. Here we can't possibly know what the other side expects.

Is this something that is planned to be removed in the future, once
negotiation support is commonplace?

> > 
> > > +	} else if (!imxpd->bus_format) {
> > > +		unsigned int i;
> > > +
> > > +		for (i = 0; i < ARRAY_SIZE(imx_pd_bus_fmts); i++) {
> > > +			if (imx_pd_bus_fmts[i] == output_fmt) {
> > > +				*num_input_fmts = 1;
> > > +				break;
> > > +			}
> > > +		}
> > > +	} else if (imxpd->bus_format == output_fmt) {
> > > +		*num_input_fmts = 1;
> > > +	}
> > > +
> > > +	if (*num_input_fmts && input_fmts)
> > > +		input_fmts[0] = MEDIA_BUS_FMT_FIXED;  
> > 
> > The parallel-display driver basically represents the wiring, pinmux, and
> > drivers between the IPU DI and the DISP pads. The input format should
> > always be identical to the output format.
> 
> I can do that if you like. Note that we are forwarding
> the ->output_bus_cfg.fmt value to the IPU DI, not ->input_bus_cfg.fmt.
> I just assumed that input format wouldn't be used in the dummy bridge
> element (the one embedded in the encoder) since encoders only have an
> output end (input port is likely to be a SoC specific link between the
> CRTC and the encoder which we probably don't need/want to expose).

Then why (would this driver have to) implement get_input_fmts at all?

I'd like this to be consistent. If encoder-bridges don't use the input
bus format in general, I'm fine with this.

I was just confused that the bridge takes part in input format
negotiation and then carries on using the output format to configure its
input.

> > > +static int imx_pd_bridge_atomic_check(struct drm_bridge *bridge,
> > > +				      struct drm_bridge_state *bridge_state,
> > > +				      struct drm_crtc_state *crtc_state,
> > > +				      struct drm_connector_state *conn_state)
> > > +{
> > > +	struct drm_encoder *encoder = bridge_to_encoder(bridge);
> > >  	struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc_state);
> > >  	struct drm_display_info *di = &conn_state->connector->display_info;
> > >  	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
> > > +	struct drm_bridge_state *next_bridge_state = NULL;
> > > +	struct drm_bridge *next_bridge;
> > > +	u32 bus_flags, bus_fmt;
> > > +	unsigned int i;
> > >  
> > > -	if (!imxpd->bus_format && di->num_bus_formats) {
> > > -		imx_crtc_state->bus_flags = di->bus_flags;
> > > -		imx_crtc_state->bus_format = di->bus_formats[0];
> > > -	} else {
> > > -		imx_crtc_state->bus_flags = imxpd->bus_flags;
> > > -		imx_crtc_state->bus_format = imxpd->bus_format;
> > > +	next_bridge = drm_bridge_chain_get_next_bridge(bridge);
> > > +	if (next_bridge)
> > > +		next_bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state,
> > > +								    next_bridge);
> > > +
> > > +	bus_fmt = bridge_state->output_bus_cfg.fmt;
> > > +	if (bus_fmt == MEDIA_BUS_FMT_FIXED)
> > > +		bus_fmt = 0;  
> > 
> > I would expect this to return with -EINVAL if bridge_state-
> > > output_bus_cfg.fmt is not in the list of supported formats.
> 
> As said above, we need a way to support bridge chains where not all
> elements support negotiating the bus format, that's what this fallback
> is for, but maybe 0 is not an appropriate value to mean 'pick the
> default format'.

We'd actually have to pick one here. If set, that should be
imxpd->bus_format.

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

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

* Re: [PATCH v2 17/21] drm/imx: pd: Use bus format/flags provided by the bridge when available
  2019-08-27  9:23       ` Philipp Zabel
@ 2019-08-27  9:57         ` Boris Brezillon
  2019-08-27 12:51           ` Philipp Zabel
  0 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2019-08-27  9:57 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	dri-devel, Kyungmin Park, Thierry Reding, Chris Healy, kernel,
	Sam Ravnborg

On Tue, 27 Aug 2019 11:23:02 +0200
Philipp Zabel <p.zabel@pengutronix.de> wrote:

> On Tue, 2019-08-27 at 10:43 +0200, Boris Brezillon wrote:
> [...]
> > > > +static void
> > > > +imx_pd_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
> > > > +					 struct drm_bridge_state *bridge_state,
> > > > +					 struct drm_crtc_state *crtc_state,
> > > > +					 struct drm_connector_state *conn_state,
> > > > +					 unsigned int *num_output_fmts,
> > > > +					 u32 *output_fmts)
> > > >  {
> > > > +	struct drm_display_info *di = &conn_state->connector->display_info;
> > > > +	struct drm_encoder *encoder = bridge_to_encoder(bridge);
> > > > +	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
> > > > +
> > > > +	*num_output_fmts = 1;
> > > > +	if (imxpd->bus_format) {
> > > > +		if (output_fmts)
> > > > +			output_fmts[0] = imxpd->bus_format;    
> > > 
> > > This is the legacy DT configured interface-pix-fmt. Maybe this should be
> > > moved to the last place.  
> > 
> > Hm, shouldn't we restrict things to a single format when we have the
> > DT prop defined?  
> 
> Absolutely. This was just a cosmetic remark. I'm suggesting to put this
> branch below the other two, to indicate its relative importance.

Okay, something like that?

	*num_output_fmts = 1;
	if (!imxpd->bus_format && di->num_bus_formats) {
		if (output_fmts)
			output_fmts[0] = di->bus_formats[0];
	} else if (!imxpd->bus_format) {
		*num_output_fmts = ARRAY_SIZE(imx_pd_bus_fmts);
		if (output_fmts)
			memcpy(output_fmts, imx_pd_bus_fmts,
			       ARRAY_SIZE(imx_pd_bus_fmts));
	} else if (output_fmts) {
		output_fmts[0] = imxpd->bus_format;
	}


> 
> [...]
> > > > +static void
> > > > +imx_pd_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
> > > > +					struct drm_bridge_state *bridge_state,
> > > > +					struct drm_crtc_state *crtc_state,
> > > > +					struct drm_connector_state *conn_state,
> > > > +					u32 output_fmt,
> > > > +					unsigned int *num_input_fmts,
> > > > +					u32 *input_fmts)
> > > > +{
> > > > +	struct drm_encoder *encoder = bridge_to_encoder(bridge);
> > > > +	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
> > > > +
> > > > +	*num_input_fmts = 0;
> > > > +	if (output_fmt == MEDIA_BUS_FMT_FIXED) {
> > > > +		*num_input_fmts = 1;    
> > > 
> > > I don't understand this. The bus format stored in imx_crtc_state by
> > > atomic_check is used to configure the DC later. This should never be
> > > MEDIA_BUS_FMT_FIXED, that would trigger a WARN_ON in
> > > ipu_bus_format_to_map().  
> > 
> > MEDIA_BUS_FMT_FIXED is the default value used when the next bridge in
> > the chain does not support bus format negotiation. When the driver
> > receives this value, it should pick a default value (which I might have
> > gotten wrong here) so that it keeps working even if some elements of
> > the bridge chain don't support negotiating the bus format yet.  
> 
> That was unexpected, as MEDIA_BUS_FMT_FIXED is documented as:
> 
>   "MEDIA_BUS_FMT_FIXED shall be used by host-client pairs,
>    where the data format is fixed."
> 
> in include/uapi/linux/media-bus-format.h. I read this as something for a
> fixed link between two known devices where there is only one possible
> format. Here we can't possibly know what the other side expects.

Well, it's more or less what happens right now without the bus format
negotiation: bridge elements consider that the link uses a fixed format
that's known by both ends in advance.

> 
> Is this something that is planned to be removed in the future, once
> negotiation support is commonplace?

Ideally yes.

> 
> > >   
> > > > +	} else if (!imxpd->bus_format) {
> > > > +		unsigned int i;
> > > > +
> > > > +		for (i = 0; i < ARRAY_SIZE(imx_pd_bus_fmts); i++) {
> > > > +			if (imx_pd_bus_fmts[i] == output_fmt) {
> > > > +				*num_input_fmts = 1;
> > > > +				break;
> > > > +			}
> > > > +		}
> > > > +	} else if (imxpd->bus_format == output_fmt) {
> > > > +		*num_input_fmts = 1;
> > > > +	}
> > > > +
> > > > +	if (*num_input_fmts && input_fmts)
> > > > +		input_fmts[0] = MEDIA_BUS_FMT_FIXED;    
> > > 
> > > The parallel-display driver basically represents the wiring, pinmux, and
> > > drivers between the IPU DI and the DISP pads. The input format should
> > > always be identical to the output format.  
> > 
> > I can do that if you like. Note that we are forwarding
> > the ->output_bus_cfg.fmt value to the IPU DI, not ->input_bus_cfg.fmt.
> > I just assumed that input format wouldn't be used in the dummy bridge
> > element (the one embedded in the encoder) since encoders only have an
> > output end (input port is likely to be a SoC specific link between the
> > CRTC and the encoder which we probably don't need/want to expose).  
> 
> Then why (would this driver have to) implement get_input_fmts at all?

That's the only way we can check if an output format is supported: bus
format negotiation is based on a trial and error logic that starts from
the end of the pipeline (last bridge element) and goes backward until
it reaches the first bridge (the dummy encoder bridge). A bus format
setting is validated when all ->get_input_bus_fmts() hooks returned at
least one possible format (*num_input_formats > 0) for the output format
being tested by the next element in the chain. And that's why even the
dummy encoder bridge has to implement this hook unless it only supports
one output format (the core returns MEDIA_BUS_FMT_FIXED when
->get_input_bus_fmts is NULL).

> 
> I'd like this to be consistent. If encoder-bridges don't use the input
> bus format in general, I'm fine with this.

Propagating output to input doesn't hurt, and if you think that's
clearer this way I'm perfectly fine adjusting the driver accordingly.

> 
> I was just confused that the bridge takes part in input format
> negotiation and then carries on using the output format to configure its
> input.

Maybe I'm wrong, but I thought it was the parallel (AKA DPI) encoder
output we were configuring here. Anyway, I'll choose one semantic and
document it.

> 
> > > > +static int imx_pd_bridge_atomic_check(struct drm_bridge *bridge,
> > > > +				      struct drm_bridge_state *bridge_state,
> > > > +				      struct drm_crtc_state *crtc_state,
> > > > +				      struct drm_connector_state *conn_state)
> > > > +{
> > > > +	struct drm_encoder *encoder = bridge_to_encoder(bridge);
> > > >  	struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc_state);
> > > >  	struct drm_display_info *di = &conn_state->connector->display_info;
> > > >  	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
> > > > +	struct drm_bridge_state *next_bridge_state = NULL;
> > > > +	struct drm_bridge *next_bridge;
> > > > +	u32 bus_flags, bus_fmt;
> > > > +	unsigned int i;
> > > >  
> > > > -	if (!imxpd->bus_format && di->num_bus_formats) {
> > > > -		imx_crtc_state->bus_flags = di->bus_flags;
> > > > -		imx_crtc_state->bus_format = di->bus_formats[0];
> > > > -	} else {
> > > > -		imx_crtc_state->bus_flags = imxpd->bus_flags;
> > > > -		imx_crtc_state->bus_format = imxpd->bus_format;
> > > > +	next_bridge = drm_bridge_chain_get_next_bridge(bridge);
> > > > +	if (next_bridge)
> > > > +		next_bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state,
> > > > +								    next_bridge);
> > > > +
> > > > +	bus_fmt = bridge_state->output_bus_cfg.fmt;
> > > > +	if (bus_fmt == MEDIA_BUS_FMT_FIXED)
> > > > +		bus_fmt = 0;    
> > > 
> > > I would expect this to return with -EINVAL if bridge_state-  
> > > > output_bus_cfg.fmt is not in the list of supported formats.  
> > 
> > As said above, we need a way to support bridge chains where not all
> > elements support negotiating the bus format, that's what this fallback
> > is for, but maybe 0 is not an appropriate value to mean 'pick the
> > default format'.  
> 
> We'd actually have to pick one here. If set, that should be
> imxpd->bus_format.

What if imxpd->bus_format is 0? Should I return -EINVAL?
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 17/21] drm/imx: pd: Use bus format/flags provided by the bridge when available
  2019-08-27  9:57         ` Boris Brezillon
@ 2019-08-27 12:51           ` Philipp Zabel
  2019-08-27 13:20             ` Boris Brezillon
  0 siblings, 1 reply; 46+ messages in thread
From: Philipp Zabel @ 2019-08-27 12:51 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	dri-devel, Kyungmin Park, Thierry Reding, Chris Healy, kernel,
	Sam Ravnborg

On Tue, 2019-08-27 at 11:57 +0200, Boris Brezillon wrote:
> On Tue, 27 Aug 2019 11:23:02 +0200
> Philipp Zabel <p.zabel@pengutronix.de> wrote:
> > On Tue, 2019-08-27 at 10:43 +0200, Boris Brezillon wrote:
[...]
> > Absolutely. This was just a cosmetic remark. I'm suggesting to put this
> > branch below the other two, to indicate its relative importance.
> 
> Okay, something like that?
> 
> 	*num_output_fmts = 1;
> 	if (!imxpd->bus_format && di->num_bus_formats) {
> 		if (output_fmts)
> 			output_fmts[0] = di->bus_formats[0];
> 	} else if (!imxpd->bus_format) {
> 		*num_output_fmts = ARRAY_SIZE(imx_pd_bus_fmts);
> 		if (output_fmts)
> 			memcpy(output_fmts, imx_pd_bus_fmts,
> 			       ARRAY_SIZE(imx_pd_bus_fmts));
> 	} else if (output_fmts) {
> 		output_fmts[0] = imxpd->bus_format;
> 	}

Yes, thank you.

[...]
> > That was unexpected, as MEDIA_BUS_FMT_FIXED is documented as:
> > 
> >   "MEDIA_BUS_FMT_FIXED shall be used by host-client pairs,
> >    where the data format is fixed."
> > 
> > in include/uapi/linux/media-bus-format.h. I read this as something for a
> > fixed link between two known devices where there is only one possible
> > format. Here we can't possibly know what the other side expects.
> 
> Well, it's more or less what happens right now without the bus format
> negotiation: bridge elements consider that the link uses a fixed format
> that's known by both ends in advance.

Ok. And with the legacy DT provided bus format we can even choose a
sensible format.

[...]
> > > I can do that if you like. Note that we are forwarding
> > > the ->output_bus_cfg.fmt value to the IPU DI, not ->input_bus_cfg.fmt.
> > > I just assumed that input format wouldn't be used in the dummy bridge
> > > element (the one embedded in the encoder) since encoders only have an
> > > output end (input port is likely to be a SoC specific link between the
> > > CRTC and the encoder which we probably don't need/want to expose).  
> > 
> > Then why (would this driver have to) implement get_input_fmts at all?
> 
> That's the only way we can check if an output format is supported: bus
> format negotiation is based on a trial and error logic that starts from
> the end of the pipeline (last bridge element) and goes backward until
> it reaches the first bridge (the dummy encoder bridge). A bus format
> setting is validated when all ->get_input_bus_fmts() hooks returned at
> least one possible format (*num_input_formats > 0) for the output format
> being tested by the next element in the chain. And that's why even the
> dummy encoder bridge has to implement this hook unless it only supports
> one output format (the core returns MEDIA_BUS_FMT_FIXED when
> ->get_input_bus_fmts is NULL).

This function (currently) also only returns MEDIA_BUS_FMT_FIXED, so
there is no difference in return value (if queried with a supported
output_fmt).
select_bus_fmt_recursive could just check atomic_get_output_bus_fmts if
that is implemented, but atomic_get_input_bus_fmts isn't.

That point is moot though, if we propagate the output format to the
input format.

> > I'd like this to be consistent. If encoder-bridges don't use the input
> > bus format in general, I'm fine with this.
> 
> Propagating output to input doesn't hurt, and if you think that's
> clearer this way I'm perfectly fine adjusting the driver accordingly.

Yes, I'd like that.

> > I was just confused that the bridge takes part in input format
> > negotiation and then carries on using the output format to configure its
> > input.
> 
> Maybe I'm wrong, but I thought it was the parallel (AKA DPI) encoder
> output we were configuring here.
> Anyway, I'll choose one semantic and document it.

Semantics :) You are not wrong, the IPU DIs technically output DPI
compatible signals, internally. Those are fed through muxes either into
the HDMI/LVDS/TV encoders, or directly into the IOMUX block, which
drives them onto the DISP pads.

The IPU driver is from a time before bridges and of-graph bindings were
established. We chose to consider the whole IDMAC/DP/DC/DI path as crtc,
and the HDMI / LVDS / IOMUX/DISP blocks as encoder, because the crtc-
encoder assignment mapped well to configuring the muxes between the
components.
Technically we could just as well consider IDMAC/DP/part-of-DC to be the
crtc and part-of-DC/DI to be a DPI encoder to which the HDMI/LVDS/TV
bridges are connected, but today we'd still miss the possibility to
multiplex several encoders into the same bridge.

[...]
> > > As said above, we need a way to support bridge chains where not all
> > > elements support negotiating the bus format, that's what this fallback
> > > is for, but maybe 0 is not an appropriate value to mean 'pick the
> > > default format'.  
> > 
> > We'd actually have to pick one here. If set, that should be
> > imxpd->bus_format.
> 
> What if imxpd->bus_format is 0? Should I return -EINVAL?

I think so. That would certainly be easier to debug than "strange
colours" when hooking up a bridge that is incompatible with whatever
we'd choose.

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

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

* Re: [PATCH v2 17/21] drm/imx: pd: Use bus format/flags provided by the bridge when available
  2019-08-27 12:51           ` Philipp Zabel
@ 2019-08-27 13:20             ` Boris Brezillon
  2019-08-27 13:49               ` Philipp Zabel
  0 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2019-08-27 13:20 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	dri-devel, Kyungmin Park, Thierry Reding, Chris Healy, kernel,
	Sam Ravnborg

On Tue, 27 Aug 2019 14:51:20 +0200
Philipp Zabel <p.zabel@pengutronix.de> wrote:
 
> [...]
> > > > I can do that if you like. Note that we are forwarding
> > > > the ->output_bus_cfg.fmt value to the IPU DI, not ->input_bus_cfg.fmt.
> > > > I just assumed that input format wouldn't be used in the dummy bridge
> > > > element (the one embedded in the encoder) since encoders only have an
> > > > output end (input port is likely to be a SoC specific link between the
> > > > CRTC and the encoder which we probably don't need/want to expose).    
> > > 
> > > Then why (would this driver have to) implement get_input_fmts at all?  
> > 
> > That's the only way we can check if an output format is supported: bus
> > format negotiation is based on a trial and error logic that starts from
> > the end of the pipeline (last bridge element) and goes backward until
> > it reaches the first bridge (the dummy encoder bridge). A bus format
> > setting is validated when all ->get_input_bus_fmts() hooks returned at
> > least one possible format (*num_input_formats > 0) for the output format
> > being tested by the next element in the chain. And that's why even the
> > dummy encoder bridge has to implement this hook unless it only supports
> > one output format (the core returns MEDIA_BUS_FMT_FIXED when  
> > ->get_input_bus_fmts is NULL).  
> 
> This function (currently) also only returns MEDIA_BUS_FMT_FIXED, so
> there is no difference in return value (if queried with a supported
> output_fmt).

There's a small difference actually: when output_fmt !=
MEDIA_BUS_FMT_FIXED, we make sure output_fmt is something we support. If
you don't implement ->get_input_bus_fmts() you'll just accept any format
requested by the next element in the pipeline.

> select_bus_fmt_recursive could just check atomic_get_output_bus_fmts if
> that is implemented, but atomic_get_input_bus_fmts isn't.

I'd like to use ->get_output_bus_fmts() only to retrieve supported
output formats on the last bridge element, otherwise it makes the
whole thing even more complex.

> 
> That point is moot though, if we propagate the output format to the
> input format.

I'll do that then (and mandate that all encoder drivers do the same).

> 
> [...]
> > > > As said above, we need a way to support bridge chains where not all
> > > > elements support negotiating the bus format, that's what this fallback
> > > > is for, but maybe 0 is not an appropriate value to mean 'pick the
> > > > default format'.    
> > > 
> > > We'd actually have to pick one here. If set, that should be
> > > imxpd->bus_format.  
> > 
> > What if imxpd->bus_format is 0? Should I return -EINVAL?  
> 
> I think so. That would certainly be easier to debug than "strange
> colours" when hooking up a bridge that is incompatible with whatever
> we'd choose.

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

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

* Re: [PATCH v2 17/21] drm/imx: pd: Use bus format/flags provided by the bridge when available
  2019-08-27 13:20             ` Boris Brezillon
@ 2019-08-27 13:49               ` Philipp Zabel
  0 siblings, 0 replies; 46+ messages in thread
From: Philipp Zabel @ 2019-08-27 13:49 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	dri-devel, Kyungmin Park, Thierry Reding, Chris Healy, kernel,
	Sam Ravnborg

On Tue, 2019-08-27 at 15:20 +0200, Boris Brezillon wrote:
> On Tue, 27 Aug 2019 14:51:20 +0200
> Philipp Zabel <p.zabel@pengutronix.de> wrote:
>  
> > [...]
> > > > > I can do that if you like. Note that we are forwarding
> > > > > the ->output_bus_cfg.fmt value to the IPU DI, not ->input_bus_cfg.fmt.
> > > > > I just assumed that input format wouldn't be used in the dummy bridge
> > > > > element (the one embedded in the encoder) since encoders only have an
> > > > > output end (input port is likely to be a SoC specific link between the
> > > > > CRTC and the encoder which we probably don't need/want to expose).    
> > > > 
> > > > Then why (would this driver have to) implement get_input_fmts at all?  
> > > 
> > > That's the only way we can check if an output format is supported: bus
> > > format negotiation is based on a trial and error logic that starts from
> > > the end of the pipeline (last bridge element) and goes backward until
> > > it reaches the first bridge (the dummy encoder bridge). A bus format
> > > setting is validated when all ->get_input_bus_fmts() hooks returned at
> > > least one possible format (*num_input_formats > 0) for the output format
> > > being tested by the next element in the chain. And that's why even the
> > > dummy encoder bridge has to implement this hook unless it only supports
> > > one output format (the core returns MEDIA_BUS_FMT_FIXED when  
> > > ->get_input_bus_fmts is NULL).  
> > 
> > This function (currently) also only returns MEDIA_BUS_FMT_FIXED, so
> > there is no difference in return value (if queried with a supported
> > output_fmt).
> 
> There's a small difference actually: when output_fmt !=
> MEDIA_BUS_FMT_FIXED, we make sure output_fmt is something we support. If
> you don't implement ->get_input_bus_fmts() you'll just accept any format
> requested by the next element in the pipeline.

I see. My whole point was predicated on the incorrect assumption that
get_input_bus_fmts would not have to be fed usupported output_fmts.

> > select_bus_fmt_recursive could just check atomic_get_output_bus_fmts if
> > that is implemented, but atomic_get_input_bus_fmts isn't.
> 
> I'd like to use ->get_output_bus_fmts() only to retrieve supported
> output formats on the last bridge element, otherwise it makes the
> whole thing even more complex.

Ok, I should have paid more attention to the documentation in patch 16.

> > That point is moot though, if we propagate the output format to the
> > input format.
> 
> I'll do that then (and mandate that all encoder drivers do the same).

Sounds good. At least then there aren't two classes of bridges that
implement the negotiation callbacks differently.

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

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

* Re: [PATCH v2 08/21] drm/msm: Use drm_attach_bridge() to attach a bridge to an encoder
  2019-08-26 15:26 ` [PATCH v2 08/21] drm/msm: Use drm_attach_bridge() to attach a bridge to an encoder Boris Brezillon
@ 2019-08-28 15:22   ` Sean Paul
  2019-08-28 15:25     ` Boris Brezillon
  0 siblings, 1 reply; 46+ messages in thread
From: Sean Paul @ 2019-08-28 15:22 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Nikita Yushchenko, Jernej Skrabec, Neil Armstrong,
	Andrey Smirnov, Jonas Karlman, Seung-Woo Kim, dri-devel,
	Kyungmin Park, Thierry Reding, Laurent Pinchart, kernel,
	Sam Ravnborg, Chris Healy

On Mon, Aug 26, 2019 at 05:26:36PM +0200, Boris Brezillon wrote:
> This is part of our attempt to make the bridge chain a double-linked
> list based on the generic list helpers. In order to do that, we must
> patch all drivers manipulating the encoder->bridge field directly.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Do you want to take this through -misc?

Reviewed-by: Sean Paul <sean@poorly.run>


> ---
> Changes in v2:
> * Add Laurent and Sam R-b (waiting for a R-b from a drm/msm maintainer
>   now)
> ---
>  drivers/gpu/drm/msm/edp/edp.c   | 4 +++-
>  drivers/gpu/drm/msm/hdmi/hdmi.c | 4 +++-
>  2 files changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c
> index b54559a79d36..ad4e963ccd9b 100644
> --- a/drivers/gpu/drm/msm/edp/edp.c
> +++ b/drivers/gpu/drm/msm/edp/edp.c
> @@ -178,7 +178,9 @@ int msm_edp_modeset_init(struct msm_edp *edp, struct drm_device *dev,
>  		goto fail;
>  	}
>  
> -	encoder->bridge.next = edp->bridge;
> +	ret = drm_bridge_attach(encoder, edp->bridge, NULL);
> +	if (ret)
> +		goto fail;
>  
>  	priv->bridges[priv->num_bridges++]       = edp->bridge;
>  	priv->connectors[priv->num_connectors++] = edp->connector;
> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
> index 9d94a88dd8d6..55b9a8c8312b 100644
> --- a/drivers/gpu/drm/msm/hdmi/hdmi.c
> +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
> @@ -327,7 +327,9 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
>  		goto fail;
>  	}
>  
> -	encoder->bridge.next = hdmi->bridge;
> +	ret = drm_bridge_attach(encoder, hdmi->bridge, NULL);
> +	if (ret)
> +		goto fail;
>  
>  	priv->bridges[priv->num_bridges++]       = hdmi->bridge;
>  	priv->connectors[priv->num_connectors++] = hdmi->connector;
> -- 
> 2.21.0
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Sean Paul, Software Engineer, Google / Chromium OS
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 08/21] drm/msm: Use drm_attach_bridge() to attach a bridge to an encoder
  2019-08-28 15:22   ` Sean Paul
@ 2019-08-28 15:25     ` Boris Brezillon
  2019-08-28 15:30       ` Sean Paul
  0 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2019-08-28 15:25 UTC (permalink / raw)
  To: Sean Paul
  Cc: Nikita Yushchenko, Jernej Skrabec, Neil Armstrong,
	Andrey Smirnov, Jonas Karlman, Seung-Woo Kim, dri-devel,
	Kyungmin Park, Thierry Reding, Laurent Pinchart, kernel,
	Sam Ravnborg, Chris Healy

On Wed, 28 Aug 2019 11:22:57 -0400
Sean Paul <sean@poorly.run> wrote:

> On Mon, Aug 26, 2019 at 05:26:36PM +0200, Boris Brezillon wrote:
> > This is part of our attempt to make the bridge chain a double-linked
> > list based on the generic list helpers. In order to do that, we must
> > patch all drivers manipulating the encoder->bridge field directly.
> > 
> > Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> > Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>  
> 
> Do you want to take this through -misc?
> 
> Reviewed-by: Sean Paul <sean@poorly.run>

Yes, that was the plan, unless you want to apply it to the msm tree
(not sure if there's such a tree).

> 
> 
> > ---
> > Changes in v2:
> > * Add Laurent and Sam R-b (waiting for a R-b from a drm/msm maintainer
> >   now)
> > ---
> >  drivers/gpu/drm/msm/edp/edp.c   | 4 +++-
> >  drivers/gpu/drm/msm/hdmi/hdmi.c | 4 +++-
> >  2 files changed, 6 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c
> > index b54559a79d36..ad4e963ccd9b 100644
> > --- a/drivers/gpu/drm/msm/edp/edp.c
> > +++ b/drivers/gpu/drm/msm/edp/edp.c
> > @@ -178,7 +178,9 @@ int msm_edp_modeset_init(struct msm_edp *edp, struct drm_device *dev,
> >  		goto fail;
> >  	}
> >  
> > -	encoder->bridge.next = edp->bridge;
> > +	ret = drm_bridge_attach(encoder, edp->bridge, NULL);
> > +	if (ret)
> > +		goto fail;
> >  
> >  	priv->bridges[priv->num_bridges++]       = edp->bridge;
> >  	priv->connectors[priv->num_connectors++] = edp->connector;
> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
> > index 9d94a88dd8d6..55b9a8c8312b 100644
> > --- a/drivers/gpu/drm/msm/hdmi/hdmi.c
> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
> > @@ -327,7 +327,9 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
> >  		goto fail;
> >  	}
> >  
> > -	encoder->bridge.next = hdmi->bridge;
> > +	ret = drm_bridge_attach(encoder, hdmi->bridge, NULL);
> > +	if (ret)
> > +		goto fail;
> >  
> >  	priv->bridges[priv->num_bridges++]       = hdmi->bridge;
> >  	priv->connectors[priv->num_connectors++] = hdmi->connector;
> > -- 
> > 2.21.0
> > 
> > _______________________________________________
> > 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] 46+ messages in thread

* Re: [PATCH v2 08/21] drm/msm: Use drm_attach_bridge() to attach a bridge to an encoder
  2019-08-28 15:25     ` Boris Brezillon
@ 2019-08-28 15:30       ` Sean Paul
  2019-08-28 20:27         ` Boris Brezillon
  0 siblings, 1 reply; 46+ messages in thread
From: Sean Paul @ 2019-08-28 15:30 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Nikita Yushchenko, Jernej Skrabec, Neil Armstrong,
	Andrey Smirnov, Jonas Karlman, Seung-Woo Kim, dri-devel,
	Kyungmin Park, Thierry Reding, Laurent Pinchart, kernel,
	Sam Ravnborg, Chris Healy

On Wed, Aug 28, 2019 at 11:25 AM Boris Brezillon
<boris.brezillon@collabora.com> wrote:
>
> On Wed, 28 Aug 2019 11:22:57 -0400
> Sean Paul <sean@poorly.run> wrote:
>
> > On Mon, Aug 26, 2019 at 05:26:36PM +0200, Boris Brezillon wrote:
> > > This is part of our attempt to make the bridge chain a double-linked
> > > list based on the generic list helpers. In order to do that, we must
> > > patch all drivers manipulating the encoder->bridge field directly.
> > >
> > > Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> > > Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
> > > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >
> > Do you want to take this through -misc?
> >
> > Reviewed-by: Sean Paul <sean@poorly.run>
>
> Yes, that was the plan, unless you want to apply it to the msm tree
> (not sure if there's such a tree).
>

There is, but I think it's fine to take this through -misc.

Sean

> >
> >
> > > ---
> > > Changes in v2:
> > > * Add Laurent and Sam R-b (waiting for a R-b from a drm/msm maintainer
> > >   now)
> > > ---
> > >  drivers/gpu/drm/msm/edp/edp.c   | 4 +++-
> > >  drivers/gpu/drm/msm/hdmi/hdmi.c | 4 +++-
> > >  2 files changed, 6 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c
> > > index b54559a79d36..ad4e963ccd9b 100644
> > > --- a/drivers/gpu/drm/msm/edp/edp.c
> > > +++ b/drivers/gpu/drm/msm/edp/edp.c
> > > @@ -178,7 +178,9 @@ int msm_edp_modeset_init(struct msm_edp *edp, struct drm_device *dev,
> > >             goto fail;
> > >     }
> > >
> > > -   encoder->bridge.next = edp->bridge;
> > > +   ret = drm_bridge_attach(encoder, edp->bridge, NULL);
> > > +   if (ret)
> > > +           goto fail;
> > >
> > >     priv->bridges[priv->num_bridges++]       = edp->bridge;
> > >     priv->connectors[priv->num_connectors++] = edp->connector;
> > > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
> > > index 9d94a88dd8d6..55b9a8c8312b 100644
> > > --- a/drivers/gpu/drm/msm/hdmi/hdmi.c
> > > +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
> > > @@ -327,7 +327,9 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
> > >             goto fail;
> > >     }
> > >
> > > -   encoder->bridge.next = hdmi->bridge;
> > > +   ret = drm_bridge_attach(encoder, hdmi->bridge, NULL);
> > > +   if (ret)
> > > +           goto fail;
> > >
> > >     priv->bridges[priv->num_bridges++]       = hdmi->bridge;
> > >     priv->connectors[priv->num_connectors++] = hdmi->connector;
> > > --
> > > 2.21.0
> > >
> > > _______________________________________________
> > > 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] 46+ messages in thread

* Re: [PATCH v2 01/21] drm: Stop including drm_bridge.h from drm_crtc.h
  2019-08-26 15:26 ` [PATCH v2 01/21] drm: Stop including drm_bridge.h from drm_crtc.h Boris Brezillon
@ 2019-08-28 20:27   ` Boris Brezillon
  0 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2019-08-28 20:27 UTC (permalink / raw)
  To: dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Jonas Karlman, Andrey Smirnov,
	Neil Armstrong, Seung-Woo Kim, Kyungmin Park, Thierry Reding,
	Laurent Pinchart, kernel, Sam Ravnborg, Chris Healy

On Mon, 26 Aug 2019 17:26:29 +0200
Boris Brezillon <boris.brezillon@collabora.com> wrote:

> We are about to add a drm_bridge_state that inherits from
> drm_private_state which is defined in drm_atomic.h. Problem is,
> drm_atomic.h includes drm_crtc.h which in turn includes drm_bridge.h,
> leading to "drm_private_state has incomplete type" error.
> 
> Let's force all users of the drm_bridge API to explicitly include
> drm_bridge.h.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> Reviewed-by: Sam Ravnborg <sam@ravnborg.org>

Queued to drm-misc-next.

> ---
> Changes in v2:
> * Fix inclusion order (Sam Ravnog)
> * Add Sam's R-b
> ---
>  drivers/gpu/drm/arc/arcpgu_hdmi.c                        | 1 +
>  drivers/gpu/drm/bridge/analogix-anx78xx.c                | 1 +
>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c       | 1 +
>  drivers/gpu/drm/bridge/dumb-vga-dac.c                    | 1 +
>  drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 1 +
>  drivers/gpu/drm/bridge/nxp-ptn3460.c                     | 1 +
>  drivers/gpu/drm/bridge/panel.c                           | 1 +
>  drivers/gpu/drm/bridge/parade-ps8622.c                   | 1 +
>  drivers/gpu/drm/bridge/sii902x.c                         | 1 +
>  drivers/gpu/drm/bridge/sii9234.c                         | 1 +
>  drivers/gpu/drm/bridge/sil-sii8620.c                     | 1 +
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c                | 1 +
>  drivers/gpu/drm/bridge/tc358764.c                        | 1 +
>  drivers/gpu/drm/bridge/tc358767.c                        | 1 +
>  drivers/gpu/drm/bridge/ti-sn65dsi86.c                    | 1 +
>  drivers/gpu/drm/bridge/ti-tfp410.c                       | 1 +
>  drivers/gpu/drm/drm_atomic_helper.c                      | 1 +
>  drivers/gpu/drm/drm_crtc_helper.c                        | 1 +
>  drivers/gpu/drm/drm_encoder.c                            | 1 +
>  drivers/gpu/drm/drm_probe_helper.c                       | 1 +
>  drivers/gpu/drm/drm_simple_kms_helper.c                  | 1 +
>  drivers/gpu/drm/exynos/exynos_dp.c                       | 1 +
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c                  | 1 +
>  drivers/gpu/drm/exynos/exynos_drm_mic.c                  | 1 +
>  drivers/gpu/drm/exynos/exynos_hdmi.c                     | 1 +
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c                | 1 +
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c             | 1 +
>  drivers/gpu/drm/i2c/tda998x_drv.c                        | 1 +
>  drivers/gpu/drm/imx/imx-ldb.c                            | 1 +
>  drivers/gpu/drm/imx/parallel-display.c                   | 1 +
>  drivers/gpu/drm/ingenic/ingenic-drm.c                    | 1 +
>  drivers/gpu/drm/mediatek/mtk_dpi.c                       | 1 +
>  drivers/gpu/drm/mediatek/mtk_dsi.c                       | 1 +
>  drivers/gpu/drm/mediatek/mtk_hdmi.c                      | 1 +
>  drivers/gpu/drm/msm/dsi/dsi.h                            | 1 +
>  drivers/gpu/drm/msm/edp/edp.h                            | 1 +
>  drivers/gpu/drm/msm/hdmi/hdmi.h                          | 2 ++
>  drivers/gpu/drm/omapdrm/dss/output.c                     | 1 +
>  drivers/gpu/drm/omapdrm/omap_drv.c                       | 1 +
>  drivers/gpu/drm/omapdrm/omap_encoder.c                   | 1 +
>  drivers/gpu/drm/rcar-du/rcar_du_encoder.c                | 1 +
>  drivers/gpu/drm/rockchip/rockchip_lvds.c                 | 1 +
>  drivers/gpu/drm/rockchip/rockchip_rgb.c                  | 1 +
>  drivers/gpu/drm/sti/sti_dvo.c                            | 1 +
>  drivers/gpu/drm/sti/sti_hda.c                            | 1 +
>  drivers/gpu/drm/sti/sti_hdmi.c                           | 1 +
>  drivers/gpu/drm/sun4i/sun4i_lvds.c                       | 1 +
>  drivers/gpu/drm/sun4i/sun4i_rgb.c                        | 1 +
>  drivers/gpu/drm/sun4i/sun4i_tcon.c                       | 1 +
>  drivers/gpu/drm/tilcdc/tilcdc_external.c                 | 1 +
>  drivers/gpu/drm/vc4/vc4_dsi.c                            | 1 +
>  include/drm/drm_crtc.h                                   | 1 -
>  52 files changed, 52 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/arc/arcpgu_hdmi.c b/drivers/gpu/drm/arc/arcpgu_hdmi.c
> index 98aac743cc26..8fd7094beece 100644
> --- a/drivers/gpu/drm/arc/arcpgu_hdmi.c
> +++ b/drivers/gpu/drm/arc/arcpgu_hdmi.c
> @@ -5,6 +5,7 @@
>   * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
>   */
>  
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_encoder.h>
>  #include <drm/drm_device.h>
> diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix-anx78xx.c
> index 3c7cc5af735c..e3f4fd2a5ad4 100644
> --- a/drivers/gpu/drm/bridge/analogix-anx78xx.c
> +++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c
> @@ -19,6 +19,7 @@
>  #include <linux/types.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_dp_helper.h>
>  #include <drm/drm_edid.h>
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 22885dceaa17..bb411fe52ae8 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -21,6 +21,7 @@
>  #include <drm/bridge/analogix_dp.h>
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_device.h>
>  #include <drm/drm_panel.h>
> diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
> index 7aa789c35882..cc33dc411b9e 100644
> --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
> +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
> @@ -12,6 +12,7 @@
>  #include <linux/regulator/consumer.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>
> 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..e8a49f6146c6 100644
> --- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
> +++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
> @@ -25,6 +25,7 @@
>  
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_edid.h>
>  #include <drm/drm_print.h>
>  #include <drm/drm_probe_helper.h>
> diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c
> index d4a1cc5052c3..57ff01339559 100644
> --- a/drivers/gpu/drm/bridge/nxp-ptn3460.c
> +++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c
> @@ -11,6 +11,7 @@
>  #include <linux/module.h>
>  #include <linux/of.h>
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_edid.h>
>  #include <drm/drm_of.h>
> diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
> index b12ae3a4c5f1..6cffeb4a42f2 100644
> --- a/drivers/gpu/drm/bridge/panel.c
> +++ b/drivers/gpu/drm/bridge/panel.c
> @@ -5,6 +5,7 @@
>   */
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_connector.h>
>  #include <drm/drm_encoder.h>
>  #include <drm/drm_modeset_helper_vtables.h>
> diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c
> index 93c68e2e9484..b7a72dfdcac3 100644
> --- a/drivers/gpu/drm/bridge/parade-ps8622.c
> +++ b/drivers/gpu/drm/bridge/parade-ps8622.c
> @@ -17,6 +17,7 @@
>  #include <linux/regulator/consumer.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_of.h>
>  #include <drm/drm_panel.h>
> diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
> index 38f75ac580df..b70e8c5cf2e1 100644
> --- a/drivers/gpu/drm/bridge/sii902x.c
> +++ b/drivers/gpu/drm/bridge/sii902x.c
> @@ -20,6 +20,7 @@
>  #include <linux/clk.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_drv.h>
>  #include <drm/drm_edid.h>
>  #include <drm/drm_print.h>
> diff --git a/drivers/gpu/drm/bridge/sii9234.c b/drivers/gpu/drm/bridge/sii9234.c
> index 25d4ad8c7ad6..ad00d841ed9e 100644
> --- a/drivers/gpu/drm/bridge/sii9234.c
> +++ b/drivers/gpu/drm/bridge/sii9234.c
> @@ -13,6 +13,7 @@
>   *    Dharam Kumar <dharam.kr@samsung.com>
>   */
>  #include <drm/bridge/mhl.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_edid.h>
>  
> diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
> index bd3165ee5354..14643923a721 100644
> --- a/drivers/gpu/drm/bridge/sil-sii8620.c
> +++ b/drivers/gpu/drm/bridge/sil-sii8620.c
> @@ -9,6 +9,7 @@
>  #include <asm/unaligned.h>
>  
>  #include <drm/bridge/mhl.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_edid.h>
>  #include <drm/drm_encoder.h>
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index 355877f0ad7a..bd65d0479683 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -26,6 +26,7 @@
>  
>  #include <drm/bridge/dw_hdmi.h>
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_edid.h>
>  #include <drm/drm_encoder_slave.h>
>  #include <drm/drm_of.h>
> diff --git a/drivers/gpu/drm/bridge/tc358764.c b/drivers/gpu/drm/bridge/tc358764.c
> index 170f162ffa55..db298f550a5a 100644
> --- a/drivers/gpu/drm/bridge/tc358764.c
> +++ b/drivers/gpu/drm/bridge/tc358764.c
> @@ -16,6 +16,7 @@
>  #include <video/mipi_display.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/drm_mipi_dsi.h>
> diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
> index cebc8e620820..51664a2df731 100644
> --- a/drivers/gpu/drm/bridge/tc358767.c
> +++ b/drivers/gpu/drm/bridge/tc358767.c
> @@ -26,6 +26,7 @@
>  #include <linux/slab.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_dp_helper.h>
>  #include <drm/drm_edid.h>
>  #include <drm/drm_of.h>
> diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> index 0a580957c8cf..43abf01ebd4c 100644
> --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> @@ -17,6 +17,7 @@
>  
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_dp_helper.h>
>  #include <drm/drm_mipi_dsi.h>
>  #include <drm/drm_of.h>
> diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
> index 61cc2354ef1b..aa3198dc9903 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>
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> index aa16ea17ff9b..4706439fb490 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -30,6 +30,7 @@
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
>  #include <drm/drm_atomic_uapi.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_damage_helper.h>
>  #include <drm/drm_device.h>
>  #include <drm/drm_plane_helper.h>
> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
> index 6dd49a60deac..fa3694836c22 100644
> --- a/drivers/gpu/drm/drm_crtc_helper.c
> +++ b/drivers/gpu/drm/drm_crtc_helper.c
> @@ -36,6 +36,7 @@
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
>  #include <drm/drm_atomic_uapi.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_crtc_helper.h>
>  #include <drm/drm_drv.h>
> diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
> index 7fb47b7b8b44..80d88a55302e 100644
> --- a/drivers/gpu/drm/drm_encoder.c
> +++ b/drivers/gpu/drm/drm_encoder.c
> @@ -22,6 +22,7 @@
>  
>  #include <linux/export.h>
>  
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_device.h>
>  #include <drm/drm_drv.h>
>  #include <drm/drm_encoder.h>
> diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
> index ef2c468205a2..351cbc40f0f8 100644
> --- a/drivers/gpu/drm/drm_probe_helper.c
> +++ b/drivers/gpu/drm/drm_probe_helper.c
> @@ -32,6 +32,7 @@
>  #include <linux/export.h>
>  #include <linux/moduleparam.h>
>  
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_client.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_edid.h>
> diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
> index b11910f14c46..046055719245 100644
> --- a/drivers/gpu/drm/drm_simple_kms_helper.c
> +++ b/drivers/gpu/drm/drm_simple_kms_helper.c
> @@ -8,6 +8,7 @@
>  
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_plane_helper.h>
>  #include <drm/drm_probe_helper.h>
>  #include <drm/drm_simple_kms_helper.h>
> diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
> index 3a0f0ba8c63a..1e6aa24bf45e 100644
> --- a/drivers/gpu/drm/exynos/exynos_dp.c
> +++ b/drivers/gpu/drm/exynos/exynos_dp.c
> @@ -19,6 +19,7 @@
>  
>  #include <drm/bridge/analogix_dp.h>
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_of.h>
>  #include <drm/drm_panel.h>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index 6926cee91b36..72726f2c7a9f 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -24,6 +24,7 @@
>  #include <video/videomode.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/drm_mipi_dsi.h>
>  #include <drm/drm_panel.h>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c
> index b78e8c5ba553..f41d75923557 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
> @@ -21,6 +21,7 @@
>  #include <video/of_videomode.h>
>  #include <video/videomode.h>
>  
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_encoder.h>
>  #include <drm/drm_print.h>
>  
> diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
> index bc1565f1822a..2e3795c2c794 100644
> --- a/drivers/gpu/drm/exynos/exynos_hdmi.c
> +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
> @@ -34,6 +34,7 @@
>  #include <media/cec-notifier.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_edid.h>
>  #include <drm/drm_print.h>
>  #include <drm/drm_probe_helper.h>
> 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..82c972e9c024 100644
> --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> @@ -9,6 +9,7 @@
>  #include <linux/of_graph.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_of.h>
>  #include <drm/drm_panel.h>
>  #include <drm/drm_probe_helper.h>
> diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> index 5bf8138941de..bdcf9c6ae9e9 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> @@ -18,6 +18,7 @@
>  #include <linux/platform_device.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_device.h>
>  #include <drm/drm_encoder_slave.h>
>  #include <drm/drm_mipi_dsi.h>
> diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
> index 84c6d4c91c65..6c218bace2ce 100644
> --- a/drivers/gpu/drm/i2c/tda998x_drv.c
> +++ b/drivers/gpu/drm/i2c/tda998x_drv.c
> @@ -14,6 +14,7 @@
>  #include <sound/hdmi-codec.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_edid.h>
>  #include <drm/drm_of.h>
>  #include <drm/drm_print.h>
> diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
> index 695f307f36b2..208069faf183 100644
> --- a/drivers/gpu/drm/imx/imx-ldb.c
> +++ b/drivers/gpu/drm/imx/imx-ldb.c
> @@ -20,6 +20,7 @@
>  
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/drm_of.h>
>  #include <drm/drm_panel.h>
> diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
> index e7ce17503ae1..35518e5de356 100644
> --- a/drivers/gpu/drm/imx/parallel-display.c
> +++ b/drivers/gpu/drm/imx/parallel-display.c
> @@ -13,6 +13,7 @@
>  #include <video/of_display_timing.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/drm_of.h>
>  #include <drm/drm_panel.h>
> diff --git a/drivers/gpu/drm/ingenic/ingenic-drm.c b/drivers/gpu/drm/ingenic/ingenic-drm.c
> index ce1fae3a78a9..1daa1378fc36 100644
> --- a/drivers/gpu/drm/ingenic/ingenic-drm.c
> +++ b/drivers/gpu/drm/ingenic/ingenic-drm.c
> @@ -13,6 +13,7 @@
>  
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_crtc_helper.h>
>  #include <drm/drm_drv.h>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index be6d95c5ff25..01fa8b8d763d 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -17,6 +17,7 @@
>  #include <video/videomode.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_of.h>
>  
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 224afb666881..a413f5ff442d 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -16,6 +16,7 @@
>  #include <video/videomode.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_mipi_dsi.h>
>  #include <drm/drm_of.h>
>  #include <drm/drm_panel.h>
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index ce91b61364eb..c79b1f855d89 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -23,6 +23,7 @@
>  #include <sound/hdmi-codec.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_edid.h>
>  #include <drm/drm_print.h>
> diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
> index 0da8a4e428ad..eff1a4c61258 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi.h
> +++ b/drivers/gpu/drm/msm/dsi/dsi.h
> @@ -9,6 +9,7 @@
>  #include <linux/of_platform.h>
>  #include <linux/platform_device.h>
>  
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_mipi_dsi.h>
>  #include <drm/drm_panel.h>
> diff --git a/drivers/gpu/drm/msm/edp/edp.h b/drivers/gpu/drm/msm/edp/edp.h
> index f2c17858a703..eb34243dad53 100644
> --- a/drivers/gpu/drm/msm/edp/edp.h
> +++ b/drivers/gpu/drm/msm/edp/edp.h
> @@ -10,6 +10,7 @@
>  #include <linux/interrupt.h>
>  #include <linux/kernel.h>
>  #include <linux/platform_device.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_dp_helper.h>
>  
> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
> index 982865866a29..4aba397a889b 100644
> --- a/drivers/gpu/drm/msm/hdmi/hdmi.h
> +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
> @@ -13,6 +13,8 @@
>  #include <linux/regulator/consumer.h>
>  #include <linux/hdmi.h>
>  
> +#include <drm/drm_bridge.h>
> +
>  #include "msm_drv.h"
>  #include "hdmi.xml.h"
>  
> diff --git a/drivers/gpu/drm/omapdrm/dss/output.c b/drivers/gpu/drm/omapdrm/dss/output.c
> index de0f882f0f7b..de500bb05bdc 100644
> --- a/drivers/gpu/drm/omapdrm/dss/output.c
> +++ b/drivers/gpu/drm/omapdrm/dss/output.c
> @@ -11,6 +11,7 @@
>  #include <linux/of.h>
>  #include <linux/of_graph.h>
>  
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_panel.h>
>  
>  #include "dss.h"
> diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
> index 9f652d2e7af1..224ec6fdc800 100644
> --- a/drivers/gpu/drm/omapdrm/omap_drv.c
> +++ b/drivers/gpu/drm/omapdrm/omap_drv.c
> @@ -11,6 +11,7 @@
>  
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_drv.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/drm_file.h>
> diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
> index 6fe14111cd95..24bbe9f2a32e 100644
> --- a/drivers/gpu/drm/omapdrm/omap_encoder.c
> +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
> @@ -6,6 +6,7 @@
>  
>  #include <linux/list.h>
>  
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_modeset_helper_vtables.h>
>  #include <drm/drm_edid.h>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
> index 0f00bdfe2366..3a1139b725c0 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
> @@ -9,6 +9,7 @@
>  
>  #include <linux/export.h>
>  
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_modeset_helper_vtables.h>
>  #include <drm/drm_panel.h>
> diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c
> index 64aefa856896..8a4c9af0ba73 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
> @@ -16,6 +16,7 @@
>  #include <linux/regmap.h>
>  #include <linux/reset.h>
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  
>  #include <drm/drm_dp_helper.h>
>  #include <drm/drm_of.h>
> diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.c b/drivers/gpu/drm/rockchip/rockchip_rgb.c
> index 89e0bb0fe0ab..db1be1f3925c 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_rgb.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_rgb.c
> @@ -9,6 +9,7 @@
>  #include <linux/of_graph.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_dp_helper.h>
>  #include <drm/drm_of.h>
>  #include <drm/drm_panel.h>
> diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
> index e55870190bf5..0a4f00253f39 100644
> --- a/drivers/gpu/drm/sti/sti_dvo.c
> +++ b/drivers/gpu/drm/sti/sti_dvo.c
> @@ -12,6 +12,7 @@
>  #include <linux/platform_device.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_device.h>
>  #include <drm/drm_panel.h>
>  #include <drm/drm_print.h>
> diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
> index 94e404f13234..9d3fd6370a29 100644
> --- a/drivers/gpu/drm/sti/sti_hda.c
> +++ b/drivers/gpu/drm/sti/sti_hda.c
> @@ -12,6 +12,7 @@
>  #include <linux/seq_file.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_debugfs.h>
>  #include <drm/drm_device.h>
>  #include <drm/drm_file.h>
> diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
> index 9862c322f0c4..84318d0832a0 100644
> --- a/drivers/gpu/drm/sti/sti_hdmi.c
> +++ b/drivers/gpu/drm/sti/sti_hdmi.c
> @@ -14,6 +14,7 @@
>  #include <linux/reset.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_debugfs.h>
>  #include <drm/drm_drv.h>
>  #include <drm/drm_edid.h>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c
> index 7fbf425acb55..25ab2ef6d545 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_lvds.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c
> @@ -7,6 +7,7 @@
>  #include <linux/clk.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_of.h>
>  #include <drm/drm_panel.h>
>  #include <drm/drm_print.h>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> index aac56983f208..e74b9eddca01 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> @@ -9,6 +9,7 @@
>  #include <linux/clk.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_of.h>
>  #include <drm/drm_panel.h>
>  #include <drm/drm_print.h>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index 690aeb822704..eb187da56aba 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -16,6 +16,7 @@
>  #include <linux/reset.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_connector.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_encoder.h>
> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_external.c b/drivers/gpu/drm/tilcdc/tilcdc_external.c
> index 43d756b7810e..4fc10838de80 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_external.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c
> @@ -8,6 +8,7 @@
>  #include <linux/of_graph.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_of.h>
>  
>  #include "tilcdc_drv.h"
> diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
> index c78fa8144776..3f63943e5472 100644
> --- a/drivers/gpu/drm/vc4/vc4_dsi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dsi.c
> @@ -31,6 +31,7 @@
>  #include <linux/pm_runtime.h>
>  
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
>  #include <drm/drm_edid.h>
>  #include <drm/drm_mipi_dsi.h>
>  #include <drm/drm_of.h>
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 7d14c11bdc0a..7e2963cad543 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -41,7 +41,6 @@
>  #include <drm/drm_connector.h>
>  #include <drm/drm_device.h>
>  #include <drm/drm_property.h>
> -#include <drm/drm_bridge.h>
>  #include <drm/drm_edid.h>
>  #include <drm/drm_plane.h>
>  #include <drm/drm_blend.h>

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

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

* Re: [PATCH v2 08/21] drm/msm: Use drm_attach_bridge() to attach a bridge to an encoder
  2019-08-28 15:30       ` Sean Paul
@ 2019-08-28 20:27         ` Boris Brezillon
  0 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2019-08-28 20:27 UTC (permalink / raw)
  To: Sean Paul
  Cc: Nikita Yushchenko, Jernej Skrabec, Jonas Karlman, Andrey Smirnov,
	Neil Armstrong, Seung-Woo Kim, dri-devel, Kyungmin Park,
	Thierry Reding, Laurent Pinchart, kernel, Sam Ravnborg,
	Chris Healy

On Wed, 28 Aug 2019 11:30:43 -0400
Sean Paul <sean@poorly.run> wrote:

> On Wed, Aug 28, 2019 at 11:25 AM Boris Brezillon
> <boris.brezillon@collabora.com> wrote:
> >
> > On Wed, 28 Aug 2019 11:22:57 -0400
> > Sean Paul <sean@poorly.run> wrote:
> >  
> > > On Mon, Aug 26, 2019 at 05:26:36PM +0200, Boris Brezillon wrote:  
> > > > This is part of our attempt to make the bridge chain a double-linked
> > > > list based on the generic list helpers. In order to do that, we must
> > > > patch all drivers manipulating the encoder->bridge field directly.
> > > >
> > > > Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> > > > Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
> > > > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>  
> > >
> > > Do you want to take this through -misc?
> > >
> > > Reviewed-by: Sean Paul <sean@poorly.run>  
> >
> > Yes, that was the plan, unless you want to apply it to the msm tree
> > (not sure if there's such a tree).
> >  
> 
> There is, but I think it's fine to take this through -misc.

Queued to drm-misc-next.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 04/21] drm/exynos: Fix potential unbalanced calls to pm_runtime_put
  2019-08-26 15:26 ` [PATCH v2 04/21] drm/exynos: Fix potential unbalanced calls to pm_runtime_put Boris Brezillon
@ 2019-10-11 13:31   ` Boris Brezillon
  2019-10-11 13:54   ` Andrzej Hajda
  1 sibling, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2019-10-11 13:31 UTC (permalink / raw)
  To: dri-devel, Inki Dae
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, kernel, Sam Ravnborg

Hi Inki,

On Mon, 26 Aug 2019 17:26:32 +0200
Boris Brezillon <boris.brezillon@collabora.com> wrote:

> The encoder->enable() can't report errors and is expected to always
> succeed. If we call pm_runtime_put() in the exynos_dsi_enable() error
> path (as currently done) we'll have unbalanced get/put calls when
> encoder->disable() is called.
> 
> The situation is not ideal since drm_panel_{prepare,enable}() can
> theoretically return an error (even if in practice I don't think any
> panel driver does that). Putting a WARN_ON() is the best we can do,
> unfortunately. Note that -ENOSYS is actually a valid case, it just
> means the panel driver does not implement the hook.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>

Did you have a chance to look at this patch 4 and 5 of this series? I'd
really like to get those 2 patches merged.

Thanks,

Boris

> ---
> Changes in v2:
> * New patch
> ---
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c | 14 ++------------
>  1 file changed, 2 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index 8e655ae1fb0c..c555cecfe1f5 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -1387,8 +1387,7 @@ static void exynos_dsi_enable(struct drm_encoder *encoder)
>  
>  	if (dsi->panel) {
>  		ret = drm_panel_prepare(dsi->panel);
> -		if (ret < 0)
> -			goto err_put_sync;
> +		WARN_ON(ret && ret != -ENOSYS);
>  	} else {
>  		drm_bridge_pre_enable(dsi->out_bridge);
>  	}
> @@ -1398,22 +1397,13 @@ static void exynos_dsi_enable(struct drm_encoder *encoder)
>  
>  	if (dsi->panel) {
>  		ret = drm_panel_enable(dsi->panel);
> -		if (ret < 0)
> -			goto err_display_disable;
> +		WARN_ON(ret && ret != -ENOSYS);
>  	} else {
>  		drm_bridge_enable(dsi->out_bridge);
>  	}
>  
>  	dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
>  	return;
> -
> -err_display_disable:
> -	exynos_dsi_set_display_enable(dsi, false);
> -	drm_panel_unprepare(dsi->panel);
> -
> -err_put_sync:
> -	dsi->state &= ~DSIM_STATE_ENABLED;
> -	pm_runtime_put(dsi->dev);
>  }
>  
>  static void exynos_dsi_disable(struct drm_encoder *encoder)

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

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

* Re: [PATCH v2 04/21] drm/exynos: Fix potential unbalanced calls to pm_runtime_put
  2019-08-26 15:26 ` [PATCH v2 04/21] drm/exynos: Fix potential unbalanced calls to pm_runtime_put Boris Brezillon
  2019-10-11 13:31   ` Boris Brezillon
@ 2019-10-11 13:54   ` Andrzej Hajda
  2019-10-11 14:20     ` Boris Brezillon
  2019-10-22 17:23     ` Boris Brezillon
  1 sibling, 2 replies; 46+ messages in thread
From: Andrzej Hajda @ 2019-10-11 13:54 UTC (permalink / raw)
  To: Boris Brezillon, dri-devel
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	Kyungmin Park, Thierry Reding, Chris Healy, kernel, Sam Ravnborg

On 26.08.2019 17:26, Boris Brezillon wrote:
> The encoder->enable() can't report errors and is expected to always
> succeed. If we call pm_runtime_put() in the exynos_dsi_enable() error
> path (as currently done) we'll have unbalanced get/put calls when
> encoder->disable() is called.


True


>
> The situation is not ideal since drm_panel_{prepare,enable}() can
> theoretically return an error (even if in practice I don't think any
> panel driver does that).


So why do you want to fix it at all, if you think return value is always
0 :) ?


git grep -p -A30 '_prepare' drivers/gpu/drm/panel/ shows that many of
them can return errors.


>  Putting a WARN_ON() is the best we can do,
> unfortunately.


I guess optimally we should use DRM_MODE_LINK_STATUS_BAD, but I am not
sure how exactly it should be handled.


> Note that -ENOSYS is actually a valid case, it just
> means the panel driver does not implement the hook.


It would be good then to fix it in panel framework, ie without hook
drm_panel_* function should return 0, ENOSYS makes no sense here.


Regards

Andrzej


>
> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> ---
> Changes in v2:
> * New patch
> ---
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c | 14 ++------------
>  1 file changed, 2 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index 8e655ae1fb0c..c555cecfe1f5 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -1387,8 +1387,7 @@ static void exynos_dsi_enable(struct drm_encoder *encoder)
>  
>  	if (dsi->panel) {
>  		ret = drm_panel_prepare(dsi->panel);
> -		if (ret < 0)
> -			goto err_put_sync;
> +		WARN_ON(ret && ret != -ENOSYS);
>  	} else {
>  		drm_bridge_pre_enable(dsi->out_bridge);
>  	}
> @@ -1398,22 +1397,13 @@ static void exynos_dsi_enable(struct drm_encoder *encoder)
>  
>  	if (dsi->panel) {
>  		ret = drm_panel_enable(dsi->panel);
> -		if (ret < 0)
> -			goto err_display_disable;
> +		WARN_ON(ret && ret != -ENOSYS);
>  	} else {
>  		drm_bridge_enable(dsi->out_bridge);
>  	}
>  
>  	dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
>  	return;
> -
> -err_display_disable:
> -	exynos_dsi_set_display_enable(dsi, false);
> -	drm_panel_unprepare(dsi->panel);
> -
> -err_put_sync:
> -	dsi->state &= ~DSIM_STATE_ENABLED;
> -	pm_runtime_put(dsi->dev);
>  }
>  
>  static void exynos_dsi_disable(struct drm_encoder *encoder)


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

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

* Re: [PATCH v2 04/21] drm/exynos: Fix potential unbalanced calls to pm_runtime_put
  2019-10-11 13:54   ` Andrzej Hajda
@ 2019-10-11 14:20     ` Boris Brezillon
  2019-10-12  7:15       ` Sam Ravnborg
  2019-10-22 17:23     ` Boris Brezillon
  1 sibling, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2019-10-11 14:20 UTC (permalink / raw)
  To: Andrzej Hajda
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	dri-devel, Kyungmin Park, Thierry Reding, Chris Healy, kernel,
	Sam Ravnborg

On Fri, 11 Oct 2019 15:54:53 +0200
Andrzej Hajda <a.hajda@samsung.com> wrote:

> On 26.08.2019 17:26, Boris Brezillon wrote:
> > The encoder->enable() can't report errors and is expected to always
> > succeed. If we call pm_runtime_put() in the exynos_dsi_enable() error
> > path (as currently done) we'll have unbalanced get/put calls when
> > encoder->disable() is called.  
> 
> 
> True
> 
> 
> >
> > The situation is not ideal since drm_panel_{prepare,enable}() can
> > theoretically return an error (even if in practice I don't think any
> > panel driver does that).  
> 
> 
> So why do you want to fix it at all, if you think return value is always
> 0 :) ?
> 
> 
> git grep -p -A30 '_prepare' drivers/gpu/drm/panel/ shows that many of
> them can return errors.

Then I was wrong :-).

> 
> 
> >  Putting a WARN_ON() is the best we can do,
> > unfortunately.  
> 
> 
> I guess optimally we should use DRM_MODE_LINK_STATUS_BAD, but I am not
> sure how exactly it should be handled.

You mean call
drm_connector_set_link_status_property(DRM_MODE_LINK_STATUS_BAD) ?

> 
> 
> > Note that -ENOSYS is actually a valid case, it just
> > means the panel driver does not implement the hook.  
> 
> 
> It would be good then to fix it in panel framework, ie without hook
> drm_panel_* function should return 0, ENOSYS makes no sense here.

I'm fine with that. Thierry, Sam, any opinion?
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 04/21] drm/exynos: Fix potential unbalanced calls to pm_runtime_put
  2019-10-11 14:20     ` Boris Brezillon
@ 2019-10-12  7:15       ` Sam Ravnborg
  2019-10-22  9:14         ` Boris Brezillon
  0 siblings, 1 reply; 46+ messages in thread
From: Sam Ravnborg @ 2019-10-12  7:15 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	dri-devel, Kyungmin Park, Thierry Reding, Chris Healy, kernel

Hi Boris/Andrzej.

> 
> > 
> > 
> > > Note that -ENOSYS is actually a valid case, it just
> > > means the panel driver does not implement the hook.  
> > 
> > 
> > It would be good then to fix it in panel framework, ie without hook
> > drm_panel_* function should return 0, ENOSYS makes no sense here.
> 
> I'm fine with that. Thierry, Sam, any opinion?

Agreed, I have following patch in my panel patch queue:

drm/drm_panel: no error when no callback

    The callbacks in drm_panel_funcs are optional, so do not
    return an error just because no callback is assigned.

    Signed-off-by: Sam Ravnborg <sam@ravnborg.org>

If I get time this weekend I will rebase/test and send the
set of patches out.

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

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

* Re: [PATCH v2 04/21] drm/exynos: Fix potential unbalanced calls to pm_runtime_put
  2019-10-12  7:15       ` Sam Ravnborg
@ 2019-10-22  9:14         ` Boris Brezillon
  0 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2019-10-22  9:14 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: Nikita Yushchenko, Jernej Skrabec, Jonas Karlman, Andrey Smirnov,
	Neil Armstrong, Seung-Woo Kim, dri-devel, Kyungmin Park,
	Thierry Reding, Laurent Pinchart, kernel, Chris Healy

On Sat, 12 Oct 2019 09:15:26 +0200
Sam Ravnborg <sam@ravnborg.org> wrote:

> Hi Boris/Andrzej.
> 
> >   
> > > 
> > >   
> > > > Note that -ENOSYS is actually a valid case, it just
> > > > means the panel driver does not implement the hook.    
> > > 
> > > 
> > > It would be good then to fix it in panel framework, ie without hook
> > > drm_panel_* function should return 0, ENOSYS makes no sense here.  
> > 
> > I'm fine with that. Thierry, Sam, any opinion?  
> 
> Agreed, I have following patch in my panel patch queue:
> 
> drm/drm_panel: no error when no callback
> 
>     The callbacks in drm_panel_funcs are optional, so do not
>     return an error just because no callback is assigned.
> 
>     Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
> 
> If I get time this weekend I will rebase/test and send the
> set of patches out.

Any progress on that? Can I rebase/send it for you if you don't have
time?
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v2 04/21] drm/exynos: Fix potential unbalanced calls to pm_runtime_put
  2019-10-11 13:54   ` Andrzej Hajda
  2019-10-11 14:20     ` Boris Brezillon
@ 2019-10-22 17:23     ` Boris Brezillon
  1 sibling, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2019-10-22 17:23 UTC (permalink / raw)
  To: Andrzej Hajda
  Cc: Nikita Yushchenko, Jernej Skrabec, Laurent Pinchart,
	Neil Armstrong, Andrey Smirnov, Jonas Karlman, Seung-Woo Kim,
	dri-devel, Kyungmin Park, Thierry Reding, Chris Healy, kernel,
	Sam Ravnborg

On Fri, 11 Oct 2019 15:54:53 +0200
Andrzej Hajda <a.hajda@samsung.com> wrote:

> On 26.08.2019 17:26, Boris Brezillon wrote:
> > The encoder->enable() can't report errors and is expected to always
> > succeed. If we call pm_runtime_put() in the exynos_dsi_enable() error
> > path (as currently done) we'll have unbalanced get/put calls when
> > encoder->disable() is called.  
> 
> 
> True

I just realized this is actually not the case, because the
DSIM_STATE_ENABLED flag is cleared in the error path, and
exynos_dsi_disable() bails out early when DSIM_STATE_ENABLED is not set.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

end of thread, other threads:[~2019-10-22 17:23 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-26 15:26 [PATCH v2 00/21] drm: Add support for bus-format negotiation Boris Brezillon
2019-08-26 15:26 ` [PATCH v2 01/21] drm: Stop including drm_bridge.h from drm_crtc.h Boris Brezillon
2019-08-28 20:27   ` Boris Brezillon
2019-08-26 15:26 ` [PATCH v2 02/21] drm: Add a dummy bridge object to drm_encoder Boris Brezillon
2019-08-26 15:26 ` [PATCH v2 03/21] drm/vc4: Implement bridge_funcs instead of encoder_helper_funcs Boris Brezillon
2019-08-26 15:26 ` [PATCH v2 04/21] drm/exynos: Fix potential unbalanced calls to pm_runtime_put Boris Brezillon
2019-10-11 13:31   ` Boris Brezillon
2019-10-11 13:54   ` Andrzej Hajda
2019-10-11 14:20     ` Boris Brezillon
2019-10-12  7:15       ` Sam Ravnborg
2019-10-22  9:14         ` Boris Brezillon
2019-10-22 17:23     ` Boris Brezillon
2019-08-26 15:26 ` [PATCH v2 05/21] drm/exynos: Don't reset bridge->next Boris Brezillon
2019-08-26 15:26 ` [PATCH v2 06/21] drm/exynos: Implement bridge_funcs instead of encoder_helper_funcs Boris Brezillon
2019-08-26 15:26 ` [PATCH v2 07/21] drm/bridge: Rename bridge helpers targeting a bridge chain Boris Brezillon
2019-08-26 15:26 ` [PATCH v2 08/21] drm/msm: Use drm_attach_bridge() to attach a bridge to an encoder Boris Brezillon
2019-08-28 15:22   ` Sean Paul
2019-08-28 15:25     ` Boris Brezillon
2019-08-28 15:30       ` Sean Paul
2019-08-28 20:27         ` Boris Brezillon
2019-08-26 15:26 ` [PATCH v2 09/21] drm/bridge: Introduce drm_bridge_chain_get_next_bridge() Boris Brezillon
2019-08-27  7:19   ` Neil Armstrong
2019-08-26 15:26 ` [PATCH v2 10/21] drm/bridge: Make the bridge chain a double-linked list Boris Brezillon
2019-08-26 15:26 ` [PATCH v2 11/21] drm/bridge: Add the drm_for_each_bridge_in_chain() helper Boris Brezillon
2019-08-27  7:26   ` Neil Armstrong
2019-08-26 15:26 ` [PATCH v2 12/21] drm/bridge: Add a drm_bridge_state object Boris Brezillon
2019-08-26 15:26 ` [PATCH v2 13/21] drm/bridge: Patch atomic hooks to take a drm_bridge_state Boris Brezillon
2019-08-26 15:26 ` [PATCH v2 14/21] drm/bridge: Add an ->atomic_check() hook Boris Brezillon
2019-08-26 15:26 ` [PATCH v2 15/21] drm/bridge: Add the drm_bridge_chain_get_prev_bridge() helper Boris Brezillon
2019-08-27  7:26   ` Neil Armstrong
2019-08-26 15:26 ` [PATCH v2 16/21] drm/bridge: Add the necessary bits to support bus format negotiation Boris Brezillon
2019-08-27  8:18   ` Neil Armstrong
2019-08-26 15:26 ` [PATCH v2 17/21] drm/imx: pd: Use bus format/flags provided by the bridge when available Boris Brezillon
2019-08-27  8:15   ` Philipp Zabel
2019-08-27  8:43     ` Boris Brezillon
2019-08-27  9:23       ` Philipp Zabel
2019-08-27  9:57         ` Boris Brezillon
2019-08-27 12:51           ` Philipp Zabel
2019-08-27 13:20             ` Boris Brezillon
2019-08-27 13:49               ` Philipp Zabel
2019-08-26 15:26 ` [PATCH v2 18/21] drm/bridge: lvds-encoder: Implement basic bus format negotiation Boris Brezillon
2019-08-26 16:15   ` Jernej Škrabec
2019-08-26 18:17     ` Boris Brezillon
2019-08-26 15:26 ` [PATCH v2 19/21] drm/bridge: panel: Propage bus format/flags Boris Brezillon
2019-08-26 15:26 ` [PATCH v2 20/21] drm/panel: simple: Add support for Toshiba LTA089AC29000 panel Boris Brezillon
2019-08-26 15:26 ` [PATCH v2 21/21] ARM: dts: imx: imx51-zii-rdu1: Fix the display pipeline definition Boris Brezillon

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.