[PATCH 08/60] drm/bridge: Extend bridge API to disable connector creation

Andrzej Hajda a.hajda at samsung.com
Wed Jul 17 06:39:47 UTC 2019


On 07.07.2019 20:18, Laurent Pinchart 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,
> and modify all existing bridge drivers to return an error when connector
> creation is not requested as they don't support this feature yet.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> ---
>  drivers/gpu/drm/arc/arcpgu_hdmi.c                        | 2 +-
>  drivers/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 +++++-
>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c       | 8 ++++++--
>  drivers/gpu/drm/bridge/cdns-dsi.c                        | 6 ++++--
>  drivers/gpu/drm/bridge/lvds-encoder.c                    | 4 ++--
>  drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 6 +++++-
>  drivers/gpu/drm/bridge/nxp-ptn3460.c                     | 6 +++++-
>  drivers/gpu/drm/bridge/panel.c                           | 5 ++++-
>  drivers/gpu/drm/bridge/parade-ps8622.c                   | 5 ++++-
>  drivers/gpu/drm/bridge/sii902x.c                         | 6 +++++-
>  drivers/gpu/drm/bridge/sil-sii8620.c                     | 2 +-
>  drivers/gpu/drm/bridge/simple-bridge.c                   | 6 +++++-
>  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                        | 5 ++++-
>  drivers/gpu/drm/bridge/tc358767.c                        | 5 ++++-
>  drivers/gpu/drm/bridge/thc63lvd1024.c                    | 5 +++--
>  drivers/gpu/drm/bridge/ti-sn65dsi86.c                    | 5 ++++-
>  drivers/gpu/drm/bridge/ti-tfp410.c                       | 5 ++++-
>  drivers/gpu/drm/drm_bridge.c                             | 5 +++--
>  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/mcde/mcde_dsi.c                          | 6 +++++-
>  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                       | 3 ++-
>  drivers/gpu/drm/rcar-du/rcar_du_encoder.c                | 2 +-
>  drivers/gpu/drm/rcar-du/rcar_lvds.c                      | 7 +++++--
>  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                                 | 4 ++--
>  53 files changed, 140 insertions(+), 67 deletions(-)
>
> diff --git a/drivers/gpu/drm/arc/arcpgu_hdmi.c b/drivers/gpu/drm/arc/arcpgu_hdmi.c
> index 98aac743cc26..739f2358f1d5 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, true);


Few suggestions:

1. Maybe it would be more convenient to add flags argument instead of bool:

- code should be more readable: ret = drm_bridge_attach(encoder, bridge,
NULL, DRM_BRIDGE_FLAG_NO_CONNECTOR)

- it can be easily expanded later with other flags, there at least two
drivers which would benefit from DRM_BRIDGE_FLAG_NO_CHAINING flag.

2. If the patch can be applied atomically it is OK as is, if not you can
use preprocessor vararg magic to support new and old syntax, sth like:

#define _drm_bridge_attach(encoder, bridge, prev, flags, optarg...)
__drm_bridge_attach(encoder, bridge, prev, flags)

#define drm_bridge_attach(encoder, bridge, prev, optarg...)
_drm_bridge_attach(encoder, bridge, prev, ##optarg, 0)

3. Maybe more convenient would be to just set the flags directly before
attachment:

    bridge->dont_create_connector = true;

    ret = drm_bridge_attach(encoder, bridge, NULL);

    This way it will be still expandable, and less changes.


Regards

Andrzej


>  	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 f73d8a92274e..606841d2c0b0 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> @@ -123,7 +123,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, true);
>  		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 f6d2681f6927..c67ba30edec4 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,
> +				 bool create_connector)
>  {
>  	struct adv7511 *adv = bridge_to_adv7511(bridge);
>  	int ret;
>  
> +	if (!create_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..f72755e59e12 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,
> +				 bool create_connector)
>  {
>  	struct anx78xx *anx78xx = bridge_to_anx78xx(bridge);
>  	int err;
>  
> +	if (!create_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 3f7f4880be09..f6a1bdcc09d6 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -1179,13 +1179,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,
> +				     bool create_connector)
>  {
>  	struct analogix_dp_device *dp = bridge->driver_private;
>  	struct drm_encoder *encoder = dp->encoder;
>  	struct drm_connector *connector = NULL;
>  	int ret = 0;
>  
> +	if (!create_connector)
> +		return -EINVAL;
> +
>  	if (!bridge->encoder) {
>  		DRM_ERROR("Parent encoder object not found");
>  		return -ENODEV;
> @@ -1463,7 +1467,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, true);
>  	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..45f50852cfbb 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,
> +				  bool create_connector)
>  {
>  	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,
> +				 create_connector);
>  }
>  
>  static enum drm_mode_status
> diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c b/drivers/gpu/drm/bridge/lvds-encoder.c
> index 2ab2c234f26c..bafab97521af 100644
> --- a/drivers/gpu/drm/bridge/lvds-encoder.c
> +++ b/drivers/gpu/drm/bridge/lvds-encoder.c
> @@ -18,14 +18,14 @@ 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, bool create_connector)
>  {
>  	struct lvds_encoder *lvds_encoder = container_of(bridge,
>  							 struct lvds_encoder,
>  							 bridge);
>  
>  	return drm_bridge_attach(bridge->encoder, lvds_encoder->panel_bridge,
> -				 bridge);
> +				 bridge, create_connector);
>  }
>  
>  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 79311f8354bd..4250e2235f50 100644
> --- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
> +++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
> @@ -206,13 +206,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,
> +				 bool create_connector)
>  {
>  	struct drm_connector *connector = &ge_b850v3_lvds_ptr->connector;
>  	struct i2c_client *stdp4028_i2c
>  			= ge_b850v3_lvds_ptr->stdp4028_i2c;
>  	int ret;
>  
> +	if (!create_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 98bc650b8c95..6bef439261da 100644
> --- a/drivers/gpu/drm/bridge/nxp-ptn3460.c
> +++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c
> @@ -238,11 +238,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,
> +				 bool create_connector)
>  {
>  	struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge);
>  	int ret;
>  
> +	if (!create_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..98ad4abf2409 100644
> --- a/drivers/gpu/drm/bridge/panel.c
> +++ b/drivers/gpu/drm/bridge/panel.c
> @@ -52,12 +52,15 @@ 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, bool create_connector)
>  {
>  	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
>  	struct drm_connector *connector = &panel_bridge->connector;
>  	int ret;
>  
> +	if (!create_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 2d88146e4836..b9243d51489b 100644
> --- a/drivers/gpu/drm/bridge/parade-ps8622.c
> +++ b/drivers/gpu/drm/bridge/parade-ps8622.c
> @@ -476,11 +476,14 @@ 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, bool create_connector)
>  {
>  	struct ps8622_bridge *ps8622 = bridge_to_ps8622(bridge);
>  	int ret;
>  
> +	if (!create_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 dd7aa466b280..18904b1082b6 100644
> --- a/drivers/gpu/drm/bridge/sii902x.c
> +++ b/drivers/gpu/drm/bridge/sii902x.c
> @@ -396,12 +396,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,
> +				 bool create_connector)
>  {
>  	struct sii902x *sii902x = bridge_to_sii902x(bridge);
>  	struct drm_device *drm = bridge->dev;
>  	int ret;
>  
> +	if (!create_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 0cc293a6ac24..ea6529df7d9c 100644
> --- a/drivers/gpu/drm/bridge/sil-sii8620.c
> +++ b/drivers/gpu/drm/bridge/sil-sii8620.c
> @@ -2203,7 +2203,7 @@ 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, bool create_connector)
>  {
>  	struct sii8620 *ctx = bridge_to_sii8620(bridge);
>  
> diff --git a/drivers/gpu/drm/bridge/simple-bridge.c b/drivers/gpu/drm/bridge/simple-bridge.c
> index 7495b9bef865..86885eb6e28d 100644
> --- a/drivers/gpu/drm/bridge/simple-bridge.c
> +++ b/drivers/gpu/drm/bridge/simple-bridge.c
> @@ -108,11 +108,15 @@ static const struct drm_connector_funcs simple_bridge_con_funcs = {
>  	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
>  };
>  
> -static int simple_bridge_attach(struct drm_bridge *bridge)
> +static int simple_bridge_attach(struct drm_bridge *bridge,
> +				bool create_connector)
>  {
>  	struct simple_bridge *sbridge = drm_bridge_to_simple_bridge(bridge);
>  	int ret;
>  
> +	if (!create_connector)
> +		return 0;
> +
>  	if (!bridge->encoder) {
>  		DRM_ERROR("Missing encoder\n");
>  		return -ENODEV;
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index c6490949d9db..930d67c618dd 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -2174,12 +2174,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,
> +				 bool create_connector)
>  {
>  	struct dw_hdmi *hdmi = bridge->driver_private;
>  	struct drm_encoder *encoder = bridge->encoder;
>  	struct drm_connector *connector = &hdmi->connector;
>  
> +	if (!create_connector)
> +		return -EINVAL;
> +
>  	connector->interlace_allowed = 1;
>  	connector->polled = DRM_CONNECTOR_POLL_HPD;
>  
> @@ -2857,7 +2861,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, true);
>  	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 281c58bab1a1..05cf97ad524f 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
> @@ -906,7 +906,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,
> +				     bool create_connector)
>  {
>  	struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
>  
> @@ -919,7 +920,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,
> +				 create_connector);
>  }
>  
>  static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = {
> @@ -1064,7 +1066,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..6016f3aae42f 100644
> --- a/drivers/gpu/drm/bridge/tc358764.c
> +++ b/drivers/gpu/drm/bridge/tc358764.c
> @@ -348,12 +348,15 @@ 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, bool create_connector)
>  {
>  	struct tc358764 *ctx = bridge_to_tc358764(bridge);
>  	struct drm_device *drm = bridge->dev;
>  	int ret;
>  
> +	if (!create_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 13ade28a36a8..e2b2d2660adc 100644
> --- a/drivers/gpu/drm/bridge/tc358767.c
> +++ b/drivers/gpu/drm/bridge/tc358767.c
> @@ -1273,13 +1273,16 @@ 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, bool create_connector)
>  {
>  	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 (!create_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..86f3b96f95db 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, bool create_connector)
>  {
>  	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,
> +				 create_connector);
>  }
>  
>  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 b77a52d05061..dbe265f7112d 100644
> --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
> @@ -224,7 +224,7 @@ 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, bool create_connector)
>  {
>  	int ret, val;
>  	struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge);
> @@ -235,6 +235,9 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge)
>  						   .node = NULL,
>  						 };
>  
> +	if (!create_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 4e76b2b27374..8d4690e436c3 100644
> --- a/drivers/gpu/drm/bridge/ti-tfp410.c
> +++ b/drivers/gpu/drm/bridge/ti-tfp410.c
> @@ -121,11 +121,14 @@ 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, bool create_connector)
>  {
>  	struct tfp410 *dvi = drm_bridge_to_tfp410(bridge);
>  	int ret;
>  
> +	if (!create_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 cba537c99e43..519577f363e3 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -95,6 +95,7 @@ EXPORT_SYMBOL(drm_bridge_remove);
>   * @encoder: DRM encoder
>   * @bridge: bridge to attach
>   * @previous: previous bridge in the chain (optional)
> + * @create_connector: true if the bridge should create a drm_connector
>   *
>   * 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
> @@ -112,7 +113,7 @@ 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, bool create_connector)
>  {
>  	int ret;
>  
> @@ -129,7 +130,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, create_connector);
>  		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..a367ef1e5081 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, true);
>  }
>  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..02b98e6ca52d 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,
> +					true);
>  		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 5f6f523821a2..768acc79d10c 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,
>  
>  	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, true);
>  		dsi->out_bridge = out_bridge;
>  		encoder->bridge = NULL;
>  	} else {
> @@ -1698,7 +1698,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, true);
>  	}
>  
>  	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..808c98101d56 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, true);
>  		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 c49e9e3740f8..8d22618ccf2e 100644
> --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> @@ -159,5 +159,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, true);
>  }
> diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> index 3d6c45097f51..eac8ec1512ab 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> @@ -780,7 +780,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, true);
>  	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 3d368c43185f..6b2e648b6c4d 100644
> --- a/drivers/gpu/drm/i2c/tda998x_drv.c
> +++ b/drivers/gpu/drm/i2c/tda998x_drv.c
> @@ -1366,10 +1366,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,
> +				 bool create_connector)
>  {
>  	struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
>  
> +	if (!create_connector)
> +		return -EINVAL;
> +
>  	return tda998x_connector_init(priv, bridge->dev);
>  }
>  
> @@ -2033,7 +2037,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, true);
>  	if (ret)
>  		goto err_bridge;
>  
> diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
> index 383733302280..845ead25ade7 100644
> --- a/drivers/gpu/drm/imx/imx-ldb.c
> +++ b/drivers/gpu/drm/imx/imx-ldb.c
> @@ -446,7 +446,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, true);
>  		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 1a76de1e8e7b..cd746592d2a7 100644
> --- a/drivers/gpu/drm/imx/parallel-display.c
> +++ b/drivers/gpu/drm/imx/parallel-display.c
> @@ -182,7 +182,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, true);
>  		if (ret < 0) {
>  			dev_err(imxpd->dev, "failed to attach bridge: %d\n",
>  				ret);
> diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c
> index 07f7090d08b3..f2deadc980f8 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,
> +				  bool create_connector)
>  {
>  	struct mcde_dsi *d = bridge_to_mcde_dsi(bridge);
>  	struct drm_device *drm = bridge->dev;
>  	int ret;
>  
> +	if (!create_connector)
> +		return -EINVAL;
> +
>  	drm_connector_helper_add(&d->connector,
>  				 &mcde_dsi_connector_helper_funcs);
>  
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index bacd989cc9aa..1ff27bb17016 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -604,7 +604,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, true);
>  	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 b91c4616644a..9c5bac48b44f 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -819,7 +819,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, true);
>  		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 5d6a9f094df5..d3248a881cf0 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -1290,11 +1290,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,
> +				  bool create_connector)
>  {
>  	struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
>  	int ret;
>  
> +	if (!create_connector)
> +		return -EINVAL;
> +
>  	ret = drm_connector_init(bridge->encoder->dev, &hdmi->conn,
>  				 &mtk_hdmi_connector_funcs,
>  				 DRM_MODE_CONNECTOR_HDMIA);
> @@ -1318,7 +1322,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, create_connector);
>  		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..ca733086041a 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, true);
>  	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, true);
>  
>  	/*
>  	 * 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..32a463c84cc1 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, true);
>  	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 03197b8959ba..d7738aafcff8 100644
> --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> @@ -296,7 +296,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, true);
>  	if (ret)
>  		goto fail;
>  
> diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
> index 672e0f8ad11c..837d0cd20dd1 100644
> --- a/drivers/gpu/drm/omapdrm/omap_drv.c
> +++ b/drivers/gpu/drm/omapdrm/omap_drv.c
> @@ -301,7 +301,8 @@ 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,
> +						true);
>  			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..74c2ae5ce687 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, true);
>  	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..a8d8b05c4731 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> @@ -605,7 +605,7 @@ 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, bool create_connector)
>  {
>  	struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
>  	struct drm_connector *connector = &lvds->connector;
> @@ -615,7 +615,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, create_connector);
> +
> +	if (!create_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 830858a809e5..7ca412d294b2 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, true);
>  		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 ce4d82d293e4..8218bbd09a72 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_rgb.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_rgb.c
> @@ -143,7 +143,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, true);
>  	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 9e6d5d8b7030..f09209621568 100644
> --- a/drivers/gpu/drm/sti/sti_dvo.c
> +++ b/drivers/gpu/drm/sti/sti_dvo.c
> @@ -468,7 +468,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, true);
>  	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..87e0fb742dc8 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, true);
>  
>  	connector->encoder = encoder;
>  
> diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
> index f03d617edc4c..8c0ffe6833f9 100644
> --- a/drivers/gpu/drm/sti/sti_hdmi.c
> +++ b/drivers/gpu/drm/sti/sti_hdmi.c
> @@ -1276,7 +1276,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, true);
>  
>  	connector->encoder = encoder;
>  
> diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
> index 2fe6c4a8d915..10a9f848c5f6 100644
> --- a/drivers/gpu/drm/stm/ltdc.c
> +++ b/drivers/gpu/drm/stm/ltdc.c
> @@ -1053,7 +1053,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, true);
>  	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 3a3ba99fed22..3e5170fa1e67 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, true);
>  		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 a901ec689b62..3f8629445fbb 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, true);
>  		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 e9969cd36610..ec693c11e455 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_external.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c
> @@ -168,7 +168,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, true);
>  	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 34f90ca8f479..2d7c5cf0d468 100644
> --- a/drivers/gpu/drm/vc4/vc4_dpi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dpi.c
> @@ -262,7 +262,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, true);
>  }
>  
>  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 2ea4e20b7b8a..3edd7ffc7383 100644
> --- a/drivers/gpu/drm/vc4/vc4_dsi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dsi.c
> @@ -1607,7 +1607,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, true);
>  	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 7616f6562fe4..08dc15f93ded 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -48,7 +48,7 @@ struct drm_bridge_funcs {
>  	 *
>  	 * Zero on success, error code on failure.
>  	 */
> -	int (*attach)(struct drm_bridge *bridge);
> +	int (*attach)(struct drm_bridge *bridge, bool create_connector);
>  
>  	/**
>  	 * @detach:
> @@ -404,7 +404,7 @@ 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, bool create_connector);
>  
>  bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
>  			   const struct drm_display_mode *mode,




More information about the dri-devel mailing list