Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/bridge: Extend bridge API to disable connector creation

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 flags argument to
the bridge .attach() operation allows instructing the bridge driver to
skip creating a connector. Unconditionally set the new flags argument to
0 for now to keep the existing behaviour, 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) {
+ DRM_ERROR("Fix bridge driver to make connector optional!");
+ return -EINVAL;
+ }
+
S1
...
}

@ depends on rule1 @
identifier rule1.fn;
identifier bridge, flags;
expression E1, E2, E3;
@@
int fn(
struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags
) {
<...
drm_bridge_attach(E1, E2, E3
+ , flags
)
...>
}

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

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Acked-by: Sam Ravnborg <sam@ravnborg.org>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Tested-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200226112514.12455-10-laurent.pinchart@ideasonboard.com

authored by

Laurent Pinchart and committed by
Tomi Valkeinen
a25b988f 64d05ff7

+231 -79
+1 -1
drivers/gpu/drm/arc/arcpgu_hdmi.c
··· 40 40 return ret; 41 41 42 42 /* Link drm_bridge to encoder */ 43 - ret = drm_bridge_attach(encoder, bridge, NULL); 43 + ret = drm_bridge_attach(encoder, bridge, NULL, 0); 44 44 if (ret) 45 45 drm_encoder_cleanup(encoder); 46 46
+1 -1
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
··· 114 114 } 115 115 116 116 if (bridge) { 117 - ret = drm_bridge_attach(&output->encoder, bridge, NULL); 117 + ret = drm_bridge_attach(&output->encoder, bridge, NULL, 0); 118 118 if (!ret) 119 119 return 0; 120 120
+7 -1
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
··· 847 847 adv7511_mode_set(adv, mode, adj_mode); 848 848 } 849 849 850 - static int adv7511_bridge_attach(struct drm_bridge *bridge) 850 + static int adv7511_bridge_attach(struct drm_bridge *bridge, 851 + enum drm_bridge_attach_flags flags) 851 852 { 852 853 struct adv7511 *adv = bridge_to_adv7511(bridge); 853 854 int ret; 855 + 856 + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { 857 + DRM_ERROR("Fix bridge driver to make connector optional!"); 858 + return -EINVAL; 859 + } 854 860 855 861 if (!bridge->encoder) { 856 862 DRM_ERROR("Parent encoder object not found");
+7 -1
drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
··· 520 520 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 521 521 }; 522 522 523 - static int anx6345_bridge_attach(struct drm_bridge *bridge) 523 + static int anx6345_bridge_attach(struct drm_bridge *bridge, 524 + enum drm_bridge_attach_flags flags) 524 525 { 525 526 struct anx6345 *anx6345 = bridge_to_anx6345(bridge); 526 527 int err; 528 + 529 + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { 530 + DRM_ERROR("Fix bridge driver to make connector optional!"); 531 + return -EINVAL; 532 + } 527 533 528 534 if (!bridge->encoder) { 529 535 DRM_ERROR("Parent encoder object not found");
+7 -1
drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c
··· 886 886 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 887 887 }; 888 888 889 - static int anx78xx_bridge_attach(struct drm_bridge *bridge) 889 + static int anx78xx_bridge_attach(struct drm_bridge *bridge, 890 + enum drm_bridge_attach_flags flags) 890 891 { 891 892 struct anx78xx *anx78xx = bridge_to_anx78xx(bridge); 892 893 int err; 894 + 895 + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { 896 + DRM_ERROR("Fix bridge driver to make connector optional!"); 897 + return -EINVAL; 898 + } 893 899 894 900 if (!bridge->encoder) { 895 901 DRM_ERROR("Parent encoder object not found");
+8 -2
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
··· 1216 1216 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 1217 1217 }; 1218 1218 1219 - static int analogix_dp_bridge_attach(struct drm_bridge *bridge) 1219 + static int analogix_dp_bridge_attach(struct drm_bridge *bridge, 1220 + enum drm_bridge_attach_flags flags) 1220 1221 { 1221 1222 struct analogix_dp_device *dp = bridge->driver_private; 1222 1223 struct drm_encoder *encoder = dp->encoder; 1223 1224 struct drm_connector *connector = NULL; 1224 1225 int ret = 0; 1226 + 1227 + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { 1228 + DRM_ERROR("Fix bridge driver to make connector optional!"); 1229 + return -EINVAL; 1230 + } 1225 1231 1226 1232 if (!bridge->encoder) { 1227 1233 DRM_ERROR("Parent encoder object not found"); ··· 1604 1598 bridge->driver_private = dp; 1605 1599 bridge->funcs = &analogix_dp_bridge_funcs; 1606 1600 1607 - ret = drm_bridge_attach(dp->encoder, bridge, NULL); 1601 + ret = drm_bridge_attach(dp->encoder, bridge, NULL, 0); 1608 1602 if (ret) { 1609 1603 DRM_ERROR("failed to attach drm bridge\n"); 1610 1604 return -EINVAL;
+4 -2
drivers/gpu/drm/bridge/cdns-dsi.c
··· 644 644 return 0; 645 645 } 646 646 647 - static int cdns_dsi_bridge_attach(struct drm_bridge *bridge) 647 + static int cdns_dsi_bridge_attach(struct drm_bridge *bridge, 648 + enum drm_bridge_attach_flags flags) 648 649 { 649 650 struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge); 650 651 struct cdns_dsi *dsi = input_to_dsi(input); ··· 657 656 return -ENOTSUPP; 658 657 } 659 658 660 - return drm_bridge_attach(bridge->encoder, output->bridge, bridge); 659 + return drm_bridge_attach(bridge->encoder, output->bridge, bridge, 660 + flags); 661 661 } 662 662 663 663 static enum drm_mode_status
+7 -1
drivers/gpu/drm/bridge/dumb-vga-dac.c
··· 100 100 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 101 101 }; 102 102 103 - static int dumb_vga_attach(struct drm_bridge *bridge) 103 + static int dumb_vga_attach(struct drm_bridge *bridge, 104 + enum drm_bridge_attach_flags flags) 104 105 { 105 106 struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge); 106 107 int ret; 108 + 109 + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { 110 + DRM_ERROR("Fix bridge driver to make connector optional!"); 111 + return -EINVAL; 112 + } 107 113 108 114 if (!bridge->encoder) { 109 115 DRM_ERROR("Missing encoder\n");
+3 -2
drivers/gpu/drm/bridge/lvds-codec.c
··· 26 26 return container_of(bridge, struct lvds_codec, bridge); 27 27 } 28 28 29 - static int lvds_codec_attach(struct drm_bridge *bridge) 29 + static int lvds_codec_attach(struct drm_bridge *bridge, 30 + enum drm_bridge_attach_flags flags) 30 31 { 31 32 struct lvds_codec *lvds_codec = to_lvds_codec(bridge); 32 33 33 34 return drm_bridge_attach(bridge->encoder, lvds_codec->panel_bridge, 34 - bridge); 35 + bridge, flags); 35 36 } 36 37 37 38 static void lvds_codec_enable(struct drm_bridge *bridge)
+7 -1
drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
··· 206 206 return IRQ_HANDLED; 207 207 } 208 208 209 - static int ge_b850v3_lvds_attach(struct drm_bridge *bridge) 209 + static int ge_b850v3_lvds_attach(struct drm_bridge *bridge, 210 + enum drm_bridge_attach_flags flags) 210 211 { 211 212 struct drm_connector *connector = &ge_b850v3_lvds_ptr->connector; 212 213 struct i2c_client *stdp4028_i2c 213 214 = ge_b850v3_lvds_ptr->stdp4028_i2c; 214 215 int ret; 216 + 217 + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { 218 + DRM_ERROR("Fix bridge driver to make connector optional!"); 219 + return -EINVAL; 220 + } 215 221 216 222 if (!bridge->encoder) { 217 223 DRM_ERROR("Parent encoder object not found");
+7 -1
drivers/gpu/drm/bridge/nxp-ptn3460.c
··· 236 236 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 237 237 }; 238 238 239 - static int ptn3460_bridge_attach(struct drm_bridge *bridge) 239 + static int ptn3460_bridge_attach(struct drm_bridge *bridge, 240 + enum drm_bridge_attach_flags flags) 240 241 { 241 242 struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge); 242 243 int ret; 244 + 245 + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { 246 + DRM_ERROR("Fix bridge driver to make connector optional!"); 247 + return -EINVAL; 248 + } 243 249 244 250 if (!bridge->encoder) { 245 251 DRM_ERROR("Parent encoder object not found");
+7 -1
drivers/gpu/drm/bridge/panel.c
··· 53 53 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 54 54 }; 55 55 56 - static int panel_bridge_attach(struct drm_bridge *bridge) 56 + static int panel_bridge_attach(struct drm_bridge *bridge, 57 + enum drm_bridge_attach_flags flags) 57 58 { 58 59 struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge); 59 60 struct drm_connector *connector = &panel_bridge->connector; 60 61 int ret; 62 + 63 + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { 64 + DRM_ERROR("Fix bridge driver to make connector optional!"); 65 + return -EINVAL; 66 + } 61 67 62 68 if (!bridge->encoder) { 63 69 DRM_ERROR("Missing encoder\n");
+7 -1
drivers/gpu/drm/bridge/parade-ps8622.c
··· 476 476 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 477 477 }; 478 478 479 - static int ps8622_attach(struct drm_bridge *bridge) 479 + static int ps8622_attach(struct drm_bridge *bridge, 480 + enum drm_bridge_attach_flags flags) 480 481 { 481 482 struct ps8622_bridge *ps8622 = bridge_to_ps8622(bridge); 482 483 int ret; 484 + 485 + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { 486 + DRM_ERROR("Fix bridge driver to make connector optional!"); 487 + return -EINVAL; 488 + } 483 489 484 490 if (!bridge->encoder) { 485 491 DRM_ERROR("Parent encoder object not found");
+3 -2
drivers/gpu/drm/bridge/parade-ps8640.c
··· 187 187 DRM_ERROR("cannot disable regulators %d\n", ret); 188 188 } 189 189 190 - static int ps8640_bridge_attach(struct drm_bridge *bridge) 190 + static int ps8640_bridge_attach(struct drm_bridge *bridge, 191 + enum drm_bridge_attach_flags flags) 191 192 { 192 193 struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); 193 194 struct device *dev = &ps_bridge->page[0]->dev; ··· 235 234 236 235 /* Attach the panel-bridge to the dsi bridge */ 237 236 return drm_bridge_attach(bridge->encoder, ps_bridge->panel_bridge, 238 - &ps_bridge->bridge); 237 + &ps_bridge->bridge, flags); 239 238 240 239 err_dsi_attach: 241 240 mipi_dsi_device_unregister(dsi);
+7 -1
drivers/gpu/drm/bridge/sii902x.c
··· 399 399 mutex_unlock(&sii902x->mutex); 400 400 } 401 401 402 - static int sii902x_bridge_attach(struct drm_bridge *bridge) 402 + static int sii902x_bridge_attach(struct drm_bridge *bridge, 403 + enum drm_bridge_attach_flags flags) 403 404 { 404 405 struct sii902x *sii902x = bridge_to_sii902x(bridge); 405 406 struct drm_device *drm = bridge->dev; 406 407 int ret; 408 + 409 + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { 410 + DRM_ERROR("Fix bridge driver to make connector optional!"); 411 + return -EINVAL; 412 + } 407 413 408 414 drm_connector_helper_add(&sii902x->connector, 409 415 &sii902x_connector_helper_funcs);
+2 -1
drivers/gpu/drm/bridge/sil-sii8620.c
··· 2202 2202 return container_of(bridge, struct sii8620, bridge); 2203 2203 } 2204 2204 2205 - static int sii8620_attach(struct drm_bridge *bridge) 2205 + static int sii8620_attach(struct drm_bridge *bridge, 2206 + enum drm_bridge_attach_flags flags) 2206 2207 { 2207 2208 struct sii8620 *ctx = bridge_to_sii8620(bridge); 2208 2209
+8 -2
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
··· 2371 2371 .atomic_check = dw_hdmi_connector_atomic_check, 2372 2372 }; 2373 2373 2374 - static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) 2374 + static int dw_hdmi_bridge_attach(struct drm_bridge *bridge, 2375 + enum drm_bridge_attach_flags flags) 2375 2376 { 2376 2377 struct dw_hdmi *hdmi = bridge->driver_private; 2377 2378 struct drm_encoder *encoder = bridge->encoder; 2378 2379 struct drm_connector *connector = &hdmi->connector; 2379 2380 struct cec_connector_info conn_info; 2380 2381 struct cec_notifier *notifier; 2382 + 2383 + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { 2384 + DRM_ERROR("Fix bridge driver to make connector optional!"); 2385 + return -EINVAL; 2386 + } 2381 2387 2382 2388 connector->interlace_allowed = 1; 2383 2389 connector->polled = DRM_CONNECTOR_POLL_HPD; ··· 3082 3076 if (IS_ERR(hdmi)) 3083 3077 return hdmi; 3084 3078 3085 - ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL); 3079 + ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL, 0); 3086 3080 if (ret) { 3087 3081 dw_hdmi_remove(hdmi); 3088 3082 DRM_ERROR("Failed to initialize bridge with drm\n");
+5 -3
drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
··· 936 936 return mode_status; 937 937 } 938 938 939 - static int dw_mipi_dsi_bridge_attach(struct drm_bridge *bridge) 939 + static int dw_mipi_dsi_bridge_attach(struct drm_bridge *bridge, 940 + enum drm_bridge_attach_flags flags) 940 941 { 941 942 struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge); 942 943 ··· 950 949 bridge->encoder->encoder_type = DRM_MODE_ENCODER_DSI; 951 950 952 951 /* Attach the panel-bridge to the dsi bridge */ 953 - return drm_bridge_attach(bridge->encoder, dsi->panel_bridge, bridge); 952 + return drm_bridge_attach(bridge->encoder, dsi->panel_bridge, bridge, 953 + flags); 954 954 } 955 955 956 956 static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = { ··· 1122 1120 { 1123 1121 int ret; 1124 1122 1125 - ret = drm_bridge_attach(encoder, &dsi->bridge, NULL); 1123 + ret = drm_bridge_attach(encoder, &dsi->bridge, NULL, 0); 1126 1124 if (ret) { 1127 1125 DRM_ERROR("Failed to initialize bridge with drm\n"); 1128 1126 return ret;
+7 -1
drivers/gpu/drm/bridge/tc358764.c
··· 349 349 dev_err(ctx->dev, "error enabling panel (%d)\n", ret); 350 350 } 351 351 352 - static int tc358764_attach(struct drm_bridge *bridge) 352 + static int tc358764_attach(struct drm_bridge *bridge, 353 + enum drm_bridge_attach_flags flags) 353 354 { 354 355 struct tc358764 *ctx = bridge_to_tc358764(bridge); 355 356 struct drm_device *drm = bridge->dev; 356 357 int ret; 358 + 359 + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { 360 + DRM_ERROR("Fix bridge driver to make connector optional!"); 361 + return -EINVAL; 362 + } 357 363 358 364 ctx->connector.polled = DRM_CONNECTOR_POLL_HPD; 359 365 ret = drm_connector_init(drm, &ctx->connector,
+8 -1
drivers/gpu/drm/bridge/tc358767.c
··· 31 31 #include <drm/drm_edid.h> 32 32 #include <drm/drm_of.h> 33 33 #include <drm/drm_panel.h> 34 + #include <drm/drm_print.h> 34 35 #include <drm/drm_probe_helper.h> 35 36 36 37 /* Registers */ ··· 1404 1403 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 1405 1404 }; 1406 1405 1407 - static int tc_bridge_attach(struct drm_bridge *bridge) 1406 + static int tc_bridge_attach(struct drm_bridge *bridge, 1407 + enum drm_bridge_attach_flags flags) 1408 1408 { 1409 1409 u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24; 1410 1410 struct tc_data *tc = bridge_to_tc(bridge); 1411 1411 struct drm_device *drm = bridge->dev; 1412 1412 int ret; 1413 + 1414 + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { 1415 + DRM_ERROR("Fix bridge driver to make connector optional!"); 1416 + return -EINVAL; 1417 + } 1413 1418 1414 1419 /* Create DP/eDP connector */ 1415 1420 drm_connector_helper_add(&tc->connector, &tc_connector_helper_funcs);
+4 -2
drivers/gpu/drm/bridge/tc358768.c
··· 511 511 .transfer = tc358768_dsi_host_transfer, 512 512 }; 513 513 514 - static int tc358768_bridge_attach(struct drm_bridge *bridge) 514 + static int tc358768_bridge_attach(struct drm_bridge *bridge, 515 + enum drm_bridge_attach_flags flags) 515 516 { 516 517 struct tc358768_priv *priv = bridge_to_tc358768(bridge); 517 518 ··· 521 520 return -ENOTSUPP; 522 521 } 523 522 524 - return drm_bridge_attach(bridge->encoder, priv->output.bridge, bridge); 523 + return drm_bridge_attach(bridge->encoder, priv->output.bridge, bridge, 524 + flags); 525 525 } 526 526 527 527 static enum drm_mode_status
+3 -2
drivers/gpu/drm/bridge/thc63lvd1024.c
··· 42 42 return container_of(bridge, struct thc63_dev, bridge); 43 43 } 44 44 45 - static int thc63_attach(struct drm_bridge *bridge) 45 + static int thc63_attach(struct drm_bridge *bridge, 46 + enum drm_bridge_attach_flags flags) 46 47 { 47 48 struct thc63_dev *thc63 = to_thc63(bridge); 48 49 49 - return drm_bridge_attach(bridge->encoder, thc63->next, bridge); 50 + return drm_bridge_attach(bridge->encoder, thc63->next, bridge, flags); 50 51 } 51 52 52 53 static enum drm_mode_status thc63_mode_valid(struct drm_bridge *bridge,
+7 -1
drivers/gpu/drm/bridge/ti-sn65dsi86.c
··· 266 266 pdata->supplies); 267 267 } 268 268 269 - static int ti_sn_bridge_attach(struct drm_bridge *bridge) 269 + static int ti_sn_bridge_attach(struct drm_bridge *bridge, 270 + enum drm_bridge_attach_flags flags) 270 271 { 271 272 int ret, val; 272 273 struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge); ··· 277 276 .channel = 0, 278 277 .node = NULL, 279 278 }; 279 + 280 + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { 281 + DRM_ERROR("Fix bridge driver to make connector optional!"); 282 + return -EINVAL; 283 + } 280 284 281 285 ret = drm_connector_init(bridge->dev, &pdata->connector, 282 286 &ti_sn_bridge_connector_funcs,
+7 -1
drivers/gpu/drm/bridge/ti-tfp410.c
··· 118 118 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 119 119 }; 120 120 121 - static int tfp410_attach(struct drm_bridge *bridge) 121 + static int tfp410_attach(struct drm_bridge *bridge, 122 + enum drm_bridge_attach_flags flags) 122 123 { 123 124 struct tfp410 *dvi = drm_bridge_to_tfp410(bridge); 124 125 int ret; 126 + 127 + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { 128 + DRM_ERROR("Fix bridge driver to make connector optional!"); 129 + return -EINVAL; 130 + } 125 131 126 132 if (!bridge->encoder) { 127 133 dev_err(dvi->dev, "Missing encoder\n");
+18 -2
drivers/gpu/drm/drm_bridge.c
··· 149 149 * @encoder: DRM encoder 150 150 * @bridge: bridge to attach 151 151 * @previous: previous bridge in the chain (optional) 152 + * @flags: DRM_BRIDGE_ATTACH_* flags 152 153 * 153 154 * Called by a kms driver to link the bridge to an encoder's chain. The previous 154 155 * argument specifies the previous bridge in the chain. If NULL, the bridge is ··· 167 166 * Zero on success, error code on failure 168 167 */ 169 168 int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge, 170 - struct drm_bridge *previous) 169 + struct drm_bridge *previous, 170 + enum drm_bridge_attach_flags flags) 171 171 { 172 172 int ret; 173 173 ··· 190 188 list_add(&bridge->chain_node, &encoder->bridge_chain); 191 189 192 190 if (bridge->funcs->attach) { 193 - ret = bridge->funcs->attach(bridge); 191 + ret = bridge->funcs->attach(bridge, flags); 194 192 if (ret < 0) 195 193 goto err_reset_bridge; 196 194 } ··· 314 312 * allows providing a single static const &drm_bridge_funcs instance in 315 313 * bridge drivers, improving security by storing function pointers in 316 314 * read-only memory. 315 + * 316 + * In order to ease transition, bridge drivers may support both the old and 317 + * new models by making connector creation optional and implementing the 318 + * connected-related bridge operations. Connector creation is then controlled 319 + * by the flags argument to the drm_bridge_attach() function. Display drivers 320 + * that support the new model and create connectors themselves shall set the 321 + * %DRM_BRIDGE_ATTACH_NO_CONNECTOR flag, and bridge drivers shall then skip 322 + * connector creation. For intermediate bridges in the chain, the flag shall 323 + * be passed to the drm_bridge_attach() call for the downstream bridge. 324 + * Bridge drivers that implement the new model only shall return an error 325 + * from their &drm_bridge_funcs.attach handler when the 326 + * %DRM_BRIDGE_ATTACH_NO_CONNECTOR flag is not set. New display drivers 327 + * should use the new model, and convert the bridge drivers they use if 328 + * needed, in order to gradually transition to the new model. 317 329 */ 318 330 319 331 /**
+1 -1
drivers/gpu/drm/drm_simple_kms_helper.c
··· 229 229 int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe, 230 230 struct drm_bridge *bridge) 231 231 { 232 - return drm_bridge_attach(&pipe->encoder, bridge, NULL); 232 + return drm_bridge_attach(&pipe->encoder, bridge, NULL, 0); 233 233 } 234 234 EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge); 235 235
+2 -1
drivers/gpu/drm/exynos/exynos_dp.c
··· 106 106 107 107 /* Pre-empt DP connector creation if there's a bridge */ 108 108 if (dp->ptn_bridge) { 109 - ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge); 109 + ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge, 110 + 0); 110 111 if (ret) { 111 112 DRM_DEV_ERROR(dp->dev, 112 113 "Failed to attach bridge to drm\n");
+2 -2
drivers/gpu/drm/exynos/exynos_drm_dsi.c
··· 1540 1540 1541 1541 out_bridge = of_drm_find_bridge(device->dev.of_node); 1542 1542 if (out_bridge) { 1543 - drm_bridge_attach(encoder, out_bridge, NULL); 1543 + drm_bridge_attach(encoder, out_bridge, NULL, 0); 1544 1544 dsi->out_bridge = out_bridge; 1545 1545 list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain); 1546 1546 } else { ··· 1717 1717 if (dsi->in_bridge_node) { 1718 1718 in_bridge = of_drm_find_bridge(dsi->in_bridge_node); 1719 1719 if (in_bridge) 1720 - drm_bridge_attach(encoder, in_bridge, NULL); 1720 + drm_bridge_attach(encoder, in_bridge, NULL, 0); 1721 1721 } 1722 1722 1723 1723 return mipi_dsi_host_register(&dsi->dsi_host);
+1 -1
drivers/gpu/drm/exynos/exynos_hdmi.c
··· 960 960 drm_connector_attach_encoder(connector, encoder); 961 961 962 962 if (hdata->bridge) { 963 - ret = drm_bridge_attach(encoder, hdata->bridge, NULL); 963 + ret = drm_bridge_attach(encoder, hdata->bridge, NULL, 0); 964 964 if (ret) 965 965 DRM_DEV_ERROR(hdata->dev, "Failed to attach bridge\n"); 966 966 }
+1 -1
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
··· 151 151 return fsl_dcu_attach_panel(fsl_dev, panel); 152 152 } 153 153 154 - return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL); 154 + return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL, 0); 155 155 }
+1 -1
drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
··· 777 777 int ret; 778 778 779 779 /* associate the bridge to dsi encoder */ 780 - ret = drm_bridge_attach(encoder, bridge, NULL); 780 + ret = drm_bridge_attach(encoder, bridge, NULL, 0); 781 781 if (ret) { 782 782 DRM_ERROR("failed to attach external bridge\n"); 783 783 return ret;
+8 -2
drivers/gpu/drm/i2c/tda998x_drv.c
··· 1356 1356 1357 1357 /* DRM bridge functions */ 1358 1358 1359 - static int tda998x_bridge_attach(struct drm_bridge *bridge) 1359 + static int tda998x_bridge_attach(struct drm_bridge *bridge, 1360 + enum drm_bridge_attach_flags flags) 1360 1361 { 1361 1362 struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge); 1363 + 1364 + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { 1365 + DRM_ERROR("Fix bridge driver to make connector optional!"); 1366 + return -EINVAL; 1367 + } 1362 1368 1363 1369 return tda998x_connector_init(priv, bridge->dev); 1364 1370 } ··· 2028 2022 if (ret) 2029 2023 goto err_encoder; 2030 2024 2031 - ret = drm_bridge_attach(&priv->encoder, &priv->bridge, NULL); 2025 + ret = drm_bridge_attach(&priv->encoder, &priv->bridge, NULL, 0); 2032 2026 if (ret) 2033 2027 goto err_bridge; 2034 2028
+1 -1
drivers/gpu/drm/imx/imx-ldb.c
··· 446 446 447 447 if (imx_ldb_ch->bridge) { 448 448 ret = drm_bridge_attach(&imx_ldb_ch->encoder, 449 - imx_ldb_ch->bridge, NULL); 449 + imx_ldb_ch->bridge, NULL, 0); 450 450 if (ret) { 451 451 DRM_ERROR("Failed to initialize bridge with drm\n"); 452 452 return ret;
+2 -2
drivers/gpu/drm/imx/parallel-display.c
··· 292 292 DRM_MODE_ENCODER_NONE, NULL); 293 293 294 294 imxpd->bridge.funcs = &imx_pd_bridge_funcs; 295 - drm_bridge_attach(encoder, &imxpd->bridge, NULL); 295 + drm_bridge_attach(encoder, &imxpd->bridge, NULL, 0); 296 296 297 297 if (!imxpd->next_bridge) { 298 298 drm_connector_helper_add(&imxpd->connector, ··· 307 307 308 308 if (imxpd->next_bridge) { 309 309 ret = drm_bridge_attach(encoder, imxpd->next_bridge, 310 - &imxpd->bridge); 310 + &imxpd->bridge, 0); 311 311 if (ret < 0) { 312 312 dev_err(imxpd->dev, "failed to attach bridge: %d\n", 313 313 ret);
+1 -1
drivers/gpu/drm/ingenic/ingenic-drm.c
··· 737 737 return ret; 738 738 } 739 739 740 - ret = drm_bridge_attach(&priv->encoder, bridge, NULL); 740 + ret = drm_bridge_attach(&priv->encoder, bridge, NULL, 0); 741 741 if (ret) { 742 742 dev_err(dev, "Unable to attach bridge"); 743 743 return ret;
+3 -2
drivers/gpu/drm/mcde/mcde_dsi.c
··· 986 986 clk_disable_unprepare(d->lp_clk); 987 987 } 988 988 989 - static int mcde_dsi_bridge_attach(struct drm_bridge *bridge) 989 + static int mcde_dsi_bridge_attach(struct drm_bridge *bridge, 990 + enum drm_bridge_attach_flags flags) 990 991 { 991 992 struct mcde_dsi *d = bridge_to_mcde_dsi(bridge); 992 993 struct drm_device *drm = bridge->dev; ··· 999 998 } 1000 999 1001 1000 /* Attach the DSI bridge to the output (panel etc) bridge */ 1002 - ret = drm_bridge_attach(bridge->encoder, d->bridge_out, bridge); 1001 + ret = drm_bridge_attach(bridge->encoder, d->bridge_out, bridge, flags); 1003 1002 if (ret) { 1004 1003 dev_err(d->dev, "failed to attach the DSI bridge\n"); 1005 1004 return ret;
+1 -1
drivers/gpu/drm/mediatek/mtk_dpi.c
··· 607 607 /* Currently DPI0 is fixed to be driven by OVL1 */ 608 608 dpi->encoder.possible_crtcs = BIT(1); 609 609 610 - ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL); 610 + ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL, 0); 611 611 if (ret) { 612 612 dev_err(dev, "Failed to attach bridge: %d\n", ret); 613 613 goto err_cleanup;
+1 -1
drivers/gpu/drm/mediatek/mtk_dsi.c
··· 904 904 905 905 /* If there's a bridge, attach to it and let it create the connector */ 906 906 if (dsi->bridge) { 907 - ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL); 907 + ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL, 0); 908 908 if (ret) { 909 909 DRM_ERROR("Failed to attach bridge to drm\n"); 910 910 goto err_encoder_cleanup;
+8 -2
drivers/gpu/drm/mediatek/mtk_hdmi.c
··· 1297 1297 * Bridge callbacks 1298 1298 */ 1299 1299 1300 - static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge) 1300 + static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge, 1301 + enum drm_bridge_attach_flags flags) 1301 1302 { 1302 1303 struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); 1303 1304 int ret; 1305 + 1306 + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { 1307 + DRM_ERROR("Fix bridge driver to make connector optional!"); 1308 + return -EINVAL; 1309 + } 1304 1310 1305 1311 ret = drm_connector_init_with_ddc(bridge->encoder->dev, &hdmi->conn, 1306 1312 &mtk_hdmi_connector_funcs, ··· 1332 1326 1333 1327 if (hdmi->next_bridge) { 1334 1328 ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge, 1335 - bridge); 1329 + bridge, flags); 1336 1330 if (ret) { 1337 1331 dev_err(hdmi->dev, 1338 1332 "Failed to attach external bridge: %d\n", ret);
+2 -2
drivers/gpu/drm/msm/dsi/dsi_manager.c
··· 684 684 bridge = &dsi_bridge->base; 685 685 bridge->funcs = &dsi_mgr_bridge_funcs; 686 686 687 - ret = drm_bridge_attach(encoder, bridge, NULL); 687 + ret = drm_bridge_attach(encoder, bridge, NULL, 0); 688 688 if (ret) 689 689 goto fail; 690 690 ··· 713 713 encoder = msm_dsi->encoder; 714 714 715 715 /* link the internal dsi bridge to the external bridge */ 716 - drm_bridge_attach(encoder, ext_bridge, int_bridge); 716 + drm_bridge_attach(encoder, ext_bridge, int_bridge, 0); 717 717 718 718 /* 719 719 * we need the drm_connector created by the external bridge
+1 -1
drivers/gpu/drm/msm/edp/edp.c
··· 178 178 goto fail; 179 179 } 180 180 181 - ret = drm_bridge_attach(encoder, edp->bridge, NULL); 181 + ret = drm_bridge_attach(encoder, edp->bridge, NULL, 0); 182 182 if (ret) 183 183 goto fail; 184 184
+1 -1
drivers/gpu/drm/msm/edp/edp_bridge.c
··· 97 97 bridge = &edp_bridge->base; 98 98 bridge->funcs = &edp_bridge_funcs; 99 99 100 - ret = drm_bridge_attach(edp->encoder, bridge, NULL); 100 + ret = drm_bridge_attach(edp->encoder, bridge, NULL, 0); 101 101 if (ret) 102 102 goto fail; 103 103
+1 -1
drivers/gpu/drm/msm/hdmi/hdmi.c
··· 327 327 goto fail; 328 328 } 329 329 330 - ret = drm_bridge_attach(encoder, hdmi->bridge, NULL); 330 + ret = drm_bridge_attach(encoder, hdmi->bridge, NULL, 0); 331 331 if (ret) 332 332 goto fail; 333 333
+1 -1
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
··· 287 287 bridge = &hdmi_bridge->base; 288 288 bridge->funcs = &msm_hdmi_bridge_funcs; 289 289 290 - ret = drm_bridge_attach(hdmi->encoder, bridge, NULL); 290 + ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, 0); 291 291 if (ret) 292 292 goto fail; 293 293
+1 -1
drivers/gpu/drm/omapdrm/omap_drv.c
··· 297 297 298 298 if (pipe->output->bridge) { 299 299 ret = drm_bridge_attach(pipe->encoder, 300 - pipe->output->bridge, NULL); 300 + pipe->output->bridge, NULL, 0); 301 301 if (ret < 0) 302 302 return ret; 303 303 }
+1 -1
drivers/gpu/drm/rcar-du/rcar_du_encoder.c
··· 121 121 * Attach the bridge to the encoder. The bridge will create the 122 122 * connector. 123 123 */ 124 - ret = drm_bridge_attach(encoder, bridge, NULL); 124 + ret = drm_bridge_attach(encoder, bridge, NULL, 0); 125 125 if (ret) { 126 126 drm_encoder_cleanup(encoder); 127 127 return ret;
+9 -2
drivers/gpu/drm/rcar-du/rcar_lvds.c
··· 23 23 #include <drm/drm_bridge.h> 24 24 #include <drm/drm_of.h> 25 25 #include <drm/drm_panel.h> 26 + #include <drm/drm_print.h> 26 27 #include <drm/drm_probe_helper.h> 27 28 28 29 #include "rcar_lvds.h" ··· 644 643 return true; 645 644 } 646 645 647 - static int rcar_lvds_attach(struct drm_bridge *bridge) 646 + static int rcar_lvds_attach(struct drm_bridge *bridge, 647 + enum drm_bridge_attach_flags flags) 648 648 { 649 649 struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); 650 650 struct drm_connector *connector = &lvds->connector; ··· 655 653 /* If we have a next bridge just attach it. */ 656 654 if (lvds->next_bridge) 657 655 return drm_bridge_attach(bridge->encoder, lvds->next_bridge, 658 - bridge); 656 + bridge, flags); 657 + 658 + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { 659 + DRM_ERROR("Fix bridge driver to make connector optional!"); 660 + return -EINVAL; 661 + } 659 662 660 663 /* Otherwise if we have a panel, create a connector. */ 661 664 if (!lvds->panel)
+1 -1
drivers/gpu/drm/rockchip/rockchip_lvds.c
··· 646 646 goto err_free_connector; 647 647 } 648 648 } else { 649 - ret = drm_bridge_attach(encoder, lvds->bridge, NULL); 649 + ret = drm_bridge_attach(encoder, lvds->bridge, NULL, 0); 650 650 if (ret) { 651 651 DRM_DEV_ERROR(drm_dev->dev, 652 652 "failed to attach bridge: %d\n", ret);
+1 -1
drivers/gpu/drm/rockchip/rockchip_rgb.c
··· 144 144 145 145 rgb->bridge = bridge; 146 146 147 - ret = drm_bridge_attach(encoder, rgb->bridge, NULL); 147 + ret = drm_bridge_attach(encoder, rgb->bridge, NULL, 0); 148 148 if (ret) { 149 149 DRM_DEV_ERROR(drm_dev->dev, 150 150 "failed to attach bridge: %d\n", ret);
+1 -1
drivers/gpu/drm/sti/sti_dvo.c
··· 467 467 bridge->of_node = dvo->dev.of_node; 468 468 drm_bridge_add(bridge); 469 469 470 - err = drm_bridge_attach(encoder, bridge, NULL); 470 + err = drm_bridge_attach(encoder, bridge, NULL, 0); 471 471 if (err) { 472 472 DRM_ERROR("Failed to attach bridge\n"); 473 473 return err;
+1 -1
drivers/gpu/drm/sti/sti_hda.c
··· 701 701 702 702 bridge->driver_private = hda; 703 703 bridge->funcs = &sti_hda_bridge_funcs; 704 - drm_bridge_attach(encoder, bridge, NULL); 704 + drm_bridge_attach(encoder, bridge, NULL, 0); 705 705 706 706 connector->encoder = encoder; 707 707
+1 -1
drivers/gpu/drm/sti/sti_hdmi.c
··· 1281 1281 1282 1282 bridge->driver_private = hdmi; 1283 1283 bridge->funcs = &sti_hdmi_bridge_funcs; 1284 - drm_bridge_attach(encoder, bridge, NULL); 1284 + drm_bridge_attach(encoder, bridge, NULL, 0); 1285 1285 1286 1286 connector->encoder = encoder; 1287 1287
+1 -1
drivers/gpu/drm/stm/ltdc.c
··· 1109 1109 1110 1110 drm_encoder_helper_add(encoder, &ltdc_encoder_helper_funcs); 1111 1111 1112 - ret = drm_bridge_attach(encoder, bridge, NULL); 1112 + ret = drm_bridge_attach(encoder, bridge, NULL, 0); 1113 1113 if (ret) { 1114 1114 drm_encoder_cleanup(encoder); 1115 1115 return -EINVAL;
+1 -1
drivers/gpu/drm/sun4i/sun4i_lvds.c
··· 156 156 } 157 157 158 158 if (bridge) { 159 - ret = drm_bridge_attach(encoder, bridge, NULL); 159 + ret = drm_bridge_attach(encoder, bridge, NULL, 0); 160 160 if (ret) { 161 161 dev_err(drm->dev, "Couldn't attach our bridge\n"); 162 162 goto err_cleanup_connector;
+1 -1
drivers/gpu/drm/sun4i/sun4i_rgb.c
··· 253 253 } 254 254 255 255 if (rgb->bridge) { 256 - ret = drm_bridge_attach(encoder, rgb->bridge, NULL); 256 + ret = drm_bridge_attach(encoder, rgb->bridge, NULL, 0); 257 257 if (ret) { 258 258 dev_err(drm->dev, "Couldn't attach our bridge\n"); 259 259 goto err_cleanup_connector;
+1 -1
drivers/gpu/drm/tidss/tidss_kms.c
··· 172 172 return PTR_ERR(enc); 173 173 } 174 174 175 - ret = drm_bridge_attach(enc, pipes[i].bridge, NULL); 175 + ret = drm_bridge_attach(enc, pipes[i].bridge, NULL, 0); 176 176 if (ret) { 177 177 dev_err(tidss->dev, "bridge attach failed: %d\n", ret); 178 178 return ret;
+1 -1
drivers/gpu/drm/tilcdc/tilcdc_external.c
··· 95 95 96 96 priv->external_encoder->possible_crtcs = BIT(0); 97 97 98 - ret = drm_bridge_attach(priv->external_encoder, bridge, NULL); 98 + ret = drm_bridge_attach(priv->external_encoder, bridge, NULL, 0); 99 99 if (ret) { 100 100 dev_err(ddev->dev, "drm_bridge_attach() failed %d\n", ret); 101 101 return ret;
+1 -1
drivers/gpu/drm/vc4/vc4_dpi.c
··· 252 252 bridge = drm_panel_bridge_add_typed(panel, 253 253 DRM_MODE_CONNECTOR_DPI); 254 254 255 - return drm_bridge_attach(dpi->encoder, bridge, NULL); 255 + return drm_bridge_attach(dpi->encoder, bridge, NULL, 0); 256 256 } 257 257 258 258 static int vc4_dpi_bind(struct device *dev, struct device *master, void *data)
+1 -1
drivers/gpu/drm/vc4/vc4_dsi.c
··· 1619 1619 DRM_MODE_ENCODER_DSI, NULL); 1620 1620 drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs); 1621 1621 1622 - ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL); 1622 + ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL, 0); 1623 1623 if (ret) { 1624 1624 dev_err(dev, "bridge attach failed: %d\n", ret); 1625 1625 return ret;
+17 -3
include/drm/drm_bridge.h
··· 40 40 struct i2c_adapter; 41 41 42 42 /** 43 + * enum drm_bridge_attach_flags - Flags for &drm_bridge_funcs.attach 44 + */ 45 + enum drm_bridge_attach_flags { 46 + /** 47 + * @DRM_BRIDGE_ATTACH_NO_CONNECTOR: When this flag is set the bridge 48 + * shall not create a drm_connector. 49 + */ 50 + DRM_BRIDGE_ATTACH_NO_CONNECTOR = BIT(0), 51 + }; 52 + 53 + /** 43 54 * struct drm_bridge_funcs - drm_bridge control functions 44 55 */ 45 56 struct drm_bridge_funcs { ··· 58 47 * @attach: 59 48 * 60 49 * This callback is invoked whenever our bridge is being attached to a 61 - * &drm_encoder. 50 + * &drm_encoder. The flags argument tunes the behaviour of the attach 51 + * operation (see DRM_BRIDGE_ATTACH_*). 62 52 * 63 53 * The @attach callback is optional. 64 54 * ··· 67 55 * 68 56 * Zero on success, error code on failure. 69 57 */ 70 - int (*attach)(struct drm_bridge *bridge); 58 + int (*attach)(struct drm_bridge *bridge, 59 + enum drm_bridge_attach_flags flags); 71 60 72 61 /** 73 62 * @detach: ··· 770 757 void drm_bridge_remove(struct drm_bridge *bridge); 771 758 struct drm_bridge *of_drm_find_bridge(struct device_node *np); 772 759 int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge, 773 - struct drm_bridge *previous); 760 + struct drm_bridge *previous, 761 + enum drm_bridge_attach_flags flags); 774 762 775 763 /** 776 764 * drm_bridge_get_next_bridge() - Get the next bridge in the chain