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);
 
 
        }
 
        if (bridge) {
-               ret = drm_bridge_attach(&output->encoder, bridge, NULL);
+               ret = drm_bridge_attach(&output->encoder, bridge, NULL, 0);
                if (!ret)
                        return 0;
 
 
        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) {
+               DRM_ERROR("Fix bridge driver to make connector optional!");
+               return -EINVAL;
+       }
+
        if (!bridge->encoder) {
                DRM_ERROR("Parent encoder object not found");
                return -ENODEV;
 
        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
-static int anx6345_bridge_attach(struct drm_bridge *bridge)
+static int anx6345_bridge_attach(struct drm_bridge *bridge,
+                                enum drm_bridge_attach_flags flags)
 {
        struct anx6345 *anx6345 = bridge_to_anx6345(bridge);
        int err;
 
+       if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
+               DRM_ERROR("Fix bridge driver to make connector optional!");
+               return -EINVAL;
+       }
+
        if (!bridge->encoder) {
                DRM_ERROR("Parent encoder object not found");
                return -ENODEV;
 
        .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) {
+               DRM_ERROR("Fix bridge driver to make connector optional!");
+               return -EINVAL;
+       }
+
        if (!bridge->encoder) {
                DRM_ERROR("Parent encoder object not found");
                return -ENODEV;
 
        .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) {
+               DRM_ERROR("Fix bridge driver to make connector optional!");
+               return -EINVAL;
+       }
+
        if (!bridge->encoder) {
                DRM_ERROR("Parent encoder object not found");
                return -ENODEV;
        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;
 
        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);
                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
 
        .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) {
+               DRM_ERROR("Fix bridge driver to make connector optional!");
+               return -EINVAL;
+       }
+
        if (!bridge->encoder) {
                DRM_ERROR("Missing encoder\n");
                return -ENODEV;
 
        return container_of(bridge, struct lvds_codec, bridge);
 }
 
-static int lvds_codec_attach(struct drm_bridge *bridge)
+static int lvds_codec_attach(struct drm_bridge *bridge,
+                            enum drm_bridge_attach_flags flags)
 {
        struct lvds_codec *lvds_codec = to_lvds_codec(bridge);
 
        return drm_bridge_attach(bridge->encoder, lvds_codec->panel_bridge,
-                                bridge);
+                                bridge, flags);
 }
 
 static void lvds_codec_enable(struct drm_bridge *bridge)
 
        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) {
+               DRM_ERROR("Fix bridge driver to make connector optional!");
+               return -EINVAL;
+       }
+
        if (!bridge->encoder) {
                DRM_ERROR("Parent encoder object not found");
                return -ENODEV;
 
        .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) {
+               DRM_ERROR("Fix bridge driver to make connector optional!");
+               return -EINVAL;
+       }
+
        if (!bridge->encoder) {
                DRM_ERROR("Parent encoder object not found");
                return -ENODEV;
 
        .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) {
+               DRM_ERROR("Fix bridge driver to make connector optional!");
+               return -EINVAL;
+       }
+
        if (!bridge->encoder) {
                DRM_ERROR("Missing encoder\n");
                return -ENODEV;
 
        .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) {
+               DRM_ERROR("Fix bridge driver to make connector optional!");
+               return -EINVAL;
+       }
+
        if (!bridge->encoder) {
                DRM_ERROR("Parent encoder object not found");
                return -ENODEV;
 
                DRM_ERROR("cannot disable regulators %d\n", ret);
 }
 
-static int ps8640_bridge_attach(struct drm_bridge *bridge)
+static int ps8640_bridge_attach(struct drm_bridge *bridge,
+                               enum drm_bridge_attach_flags flags)
 {
        struct ps8640 *ps_bridge = bridge_to_ps8640(bridge);
        struct device *dev = &ps_bridge->page[0]->dev;
 
        /* Attach the panel-bridge to the dsi bridge */
        return drm_bridge_attach(bridge->encoder, ps_bridge->panel_bridge,
-                                &ps_bridge->bridge);
+                                &ps_bridge->bridge, flags);
 
 err_dsi_attach:
        mipi_dsi_device_unregister(dsi);
 
        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) {
+               DRM_ERROR("Fix bridge driver to make connector optional!");
+               return -EINVAL;
+       }
+
        drm_connector_helper_add(&sii902x->connector,
                                 &sii902x_connector_helper_funcs);
 
 
        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);
 
 
        .atomic_check = dw_hdmi_connector_atomic_check,
 };
 
-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 cec_connector_info conn_info;
        struct cec_notifier *notifier;
 
+       if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
+               DRM_ERROR("Fix bridge driver to make connector optional!");
+               return -EINVAL;
+       }
+
        connector->interlace_allowed = 1;
        connector->polled = DRM_CONNECTOR_POLL_HPD;
 
        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");
 
        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);
 
        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 = {
 {
        int ret;
 
-       ret = drm_bridge_attach(encoder, &dsi->bridge, NULL);
+       ret = drm_bridge_attach(encoder, &dsi->bridge, NULL, 0);
        if (ret) {
                DRM_ERROR("Failed to initialize bridge with drm\n");
                return ret;
 
                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) {
+               DRM_ERROR("Fix bridge driver to make connector optional!");
+               return -EINVAL;
+       }
+
        ctx->connector.polled = DRM_CONNECTOR_POLL_HPD;
        ret = drm_connector_init(drm, &ctx->connector,
                                 &tc358764_connector_funcs,
 
 #include <drm/drm_edid.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
+#include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
 
 /* Registers */
        .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) {
+               DRM_ERROR("Fix bridge driver to make connector optional!");
+               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,
 
        .transfer = tc358768_dsi_host_transfer,
 };
 
-static int tc358768_bridge_attach(struct drm_bridge *bridge)
+static int tc358768_bridge_attach(struct drm_bridge *bridge,
+                                 enum drm_bridge_attach_flags flags)
 {
        struct tc358768_priv *priv = bridge_to_tc358768(bridge);
 
                return -ENOTSUPP;
        }
 
-       return drm_bridge_attach(bridge->encoder, priv->output.bridge, bridge);
+       return drm_bridge_attach(bridge->encoder, priv->output.bridge, bridge,
+                                flags);
 }
 
 static enum drm_mode_status
 
        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,
 
                                       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);
                                                   .node = NULL,
                                                 };
 
+       if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
+               DRM_ERROR("Fix bridge driver to make connector optional!");
+               return -EINVAL;
+       }
+
        ret = drm_connector_init(bridge->dev, &pdata->connector,
                                 &ti_sn_bridge_connector_funcs,
                                 DRM_MODE_CONNECTOR_eDP);
 
        .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) {
+               DRM_ERROR("Fix bridge driver to make connector optional!");
+               return -EINVAL;
+       }
+
        if (!bridge->encoder) {
                dev_err(dvi->dev, "Missing encoder\n");
                return -ENODEV;
 
  * @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
  * 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;
 
                list_add(&bridge->chain_node, &encoder->bridge_chain);
 
        if (bridge->funcs->attach) {
-               ret = bridge->funcs->attach(bridge);
+               ret = bridge->funcs->attach(bridge, flags);
                if (ret < 0)
                        goto err_reset_bridge;
        }
  *   allows providing a single static const &drm_bridge_funcs instance in
  *   bridge drivers, improving security by storing function pointers in
  *   read-only memory.
+ *
+ *   In order to ease transition, bridge drivers may support both the old and
+ *   new models by making connector creation optional and implementing the
+ *   connected-related bridge operations. Connector creation is then controlled
+ *   by the flags argument to the drm_bridge_attach() function. Display drivers
+ *   that support the new model and create connectors themselves shall set the
+ *   %DRM_BRIDGE_ATTACH_NO_CONNECTOR flag, and bridge drivers shall then skip
+ *   connector creation. For intermediate bridges in the chain, the flag shall
+ *   be passed to the drm_bridge_attach() call for the downstream bridge.
+ *   Bridge drivers that implement the new model only shall return an error
+ *   from their &drm_bridge_funcs.attach handler when the
+ *   %DRM_BRIDGE_ATTACH_NO_CONNECTOR flag is not set. New display drivers
+ *   should use the new model, and convert the bridge drivers they use if
+ *   needed, in order to gradually transition to the new model.
  */
 
 /**
 
 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);
 
 
 
        /* 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");
 
 
        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;
                list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain);
        } else {
        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);
 
        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");
        }
 
                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);
 }
 
        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;
 
 
 /* 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) {
+               DRM_ERROR("Fix bridge driver to make connector optional!");
+               return -EINVAL;
+       }
+
        return tda998x_connector_init(priv, bridge->dev);
 }
 
        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;
 
 
 
        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;
 
                         DRM_MODE_ENCODER_NONE, NULL);
 
        imxpd->bridge.funcs = &imx_pd_bridge_funcs;
-       drm_bridge_attach(encoder, &imxpd->bridge, NULL);
+       drm_bridge_attach(encoder, &imxpd->bridge, NULL, 0);
 
        if (!imxpd->next_bridge) {
                drm_connector_helper_add(&imxpd->connector,
 
        if (imxpd->next_bridge) {
                ret = drm_bridge_attach(encoder, imxpd->next_bridge,
-                                       &imxpd->bridge);
+                                       &imxpd->bridge, 0);
                if (ret < 0) {
                        dev_err(imxpd->dev, "failed to attach bridge: %d\n",
                                ret);
 
                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;
 
        clk_disable_unprepare(d->lp_clk);
 }
 
-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;
        }
 
        /* 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;
 
        /* 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;
 
 
        /* 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;
 
  * 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) {
+               DRM_ERROR("Fix bridge driver to make connector optional!");
+               return -EINVAL;
+       }
+
        ret = drm_connector_init_with_ddc(bridge->encoder->dev, &hdmi->conn,
                                          &mtk_hdmi_connector_funcs,
                                          DRM_MODE_CONNECTOR_HDMIA,
 
        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);
 
        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;
 
        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
 
                goto fail;
        }
 
-       ret = drm_bridge_attach(encoder, edp->bridge, NULL);
+       ret = drm_bridge_attach(encoder, edp->bridge, NULL, 0);
        if (ret)
                goto fail;
 
 
        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;
 
 
                goto fail;
        }
 
-       ret = drm_bridge_attach(encoder, hdmi->bridge, NULL);
+       ret = drm_bridge_attach(encoder, hdmi->bridge, NULL, 0);
        if (ret)
                goto fail;
 
 
        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;
 
 
 
                if (pipe->output->bridge) {
                        ret = drm_bridge_attach(pipe->encoder,
-                                               pipe->output->bridge, NULL);
+                                               pipe->output->bridge, NULL, 0);
                        if (ret < 0)
                                return ret;
                }
 
         * 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;
 
 #include <drm/drm_bridge.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
+#include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
 
 #include "rcar_lvds.h"
        return true;
 }
 
-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;
        /* 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) {
+               DRM_ERROR("Fix bridge driver to make connector optional!");
+               return -EINVAL;
+       }
 
        /* Otherwise if we have a panel, create a connector. */
        if (!lvds->panel)
 
                        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);
 
 
        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);
 
        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;
 
 
        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;
 
 
 
        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;
 
 
 
        drm_encoder_helper_add(encoder, <dc_encoder_helper_funcs);
 
-       ret = drm_bridge_attach(encoder, bridge, NULL);
+       ret = drm_bridge_attach(encoder, bridge, NULL, 0);
        if (ret) {
                drm_encoder_cleanup(encoder);
                return -EINVAL;
 
        }
 
        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;
 
        }
 
        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;
 
                        return PTR_ERR(enc);
                }
 
-               ret = drm_bridge_attach(enc, pipes[i].bridge, NULL);
+               ret = drm_bridge_attach(enc, pipes[i].bridge, NULL, 0);
                if (ret) {
                        dev_err(tidss->dev, "bridge attach failed: %d\n", ret);
                        return ret;
 
 
        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;
 
                bridge = drm_panel_bridge_add_typed(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)
 
                         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;
 
 struct edid;
 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
  */
         * @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.
         *
         *
         * 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:
 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);
 
 /**
  * drm_bridge_get_next_bridge() - Get the next bridge in the chain