[PATCH v2 05/50] drm/bridge: Extend bridge API to disable connector creation

Boris Brezillon boris.brezillon at collabora.com
Thu Aug 22 15:34:16 UTC 2019


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

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

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

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

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

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

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



More information about the dri-devel mailing list