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

drm: bridge: Link encoder and bridge in core code

Instead of linking encoders and bridges in every driver (and getting it
wrong half of the time, as many drivers forget to set the drm_bridge
encoder pointer), do so in core code. The drm_bridge_attach() function
needs the encoder and optional previous bridge to perform that task,
update all the callers.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Acked-by: Stefan Agner <stefan@agner.ch> # For DCU
Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com> # For atmel-hlcdc
Acked-by: Vincent Abriou <vincent.abriou@st.com> # For STI
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com> # For sun4i
Acked-by: Xinliang Liu <z.liuxinliang@hisilicon.com> # For hisilicon
Acked-by: Jyri Sarha <jsarha@ti.com> # For tilcdc
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Archit Taneja <architt@codeaurora.org>
Link: http://patchwork.freedesktop.org/patch/msgid/1481709550-29226-4-git-send-email-laurent.pinchart+renesas@ideasonboard.com

authored by

Laurent Pinchart and committed by
Archit Taneja
3bb80f24 2407d1dc

+85 -110
+1 -4
drivers/gpu/drm/arc/arcpgu_hdmi.c
··· 47 47 return ret; 48 48 49 49 /* Link drm_bridge to encoder */ 50 - bridge->encoder = encoder; 51 - encoder->bridge = bridge; 52 - 53 - ret = drm_bridge_attach(drm, bridge); 50 + ret = drm_bridge_attach(encoder, bridge, NULL); 54 51 if (ret) 55 52 drm_encoder_cleanup(encoder); 56 53
+1 -3
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
··· 230 230 of_node_put(np); 231 231 232 232 if (bridge) { 233 - output->encoder.bridge = bridge; 234 - bridge->encoder = &output->encoder; 235 - ret = drm_bridge_attach(dev, bridge); 233 + ret = drm_bridge_attach(&output->encoder, bridge, NULL); 236 234 if (!ret) 237 235 return 0; 238 236 }
+1 -3
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
··· 1232 1232 1233 1233 dp->bridge = bridge; 1234 1234 1235 - dp->encoder->bridge = bridge; 1236 1235 bridge->driver_private = dp; 1237 - bridge->encoder = dp->encoder; 1238 1236 bridge->funcs = &analogix_dp_bridge_funcs; 1239 1237 1240 - ret = drm_bridge_attach(drm_dev, bridge); 1238 + ret = drm_bridge_attach(dp->encoder, bridge, NULL); 1241 1239 if (ret) { 1242 1240 DRM_ERROR("failed to attach drm bridge\n"); 1243 1241 return -EINVAL;
+1 -2
drivers/gpu/drm/bridge/dw-hdmi.c
··· 1841 1841 hdmi->bridge = bridge; 1842 1842 bridge->driver_private = hdmi; 1843 1843 bridge->funcs = &dw_hdmi_bridge_funcs; 1844 - ret = drm_bridge_attach(drm, bridge); 1844 + ret = drm_bridge_attach(encoder, bridge, NULL); 1845 1845 if (ret) { 1846 1846 DRM_ERROR("Failed to initialize bridge with drm\n"); 1847 1847 return -EINVAL; 1848 1848 } 1849 1849 1850 - encoder->bridge = bridge; 1851 1850 hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD; 1852 1851 1853 1852 drm_connector_helper_add(&hdmi->connector,
+34 -12
drivers/gpu/drm/drm_bridge.c
··· 26 26 #include <linux/mutex.h> 27 27 28 28 #include <drm/drm_bridge.h> 29 + #include <drm/drm_encoder.h> 29 30 30 31 /** 31 32 * DOC: overview ··· 93 92 EXPORT_SYMBOL(drm_bridge_remove); 94 93 95 94 /** 96 - * drm_bridge_attach - associate given bridge to our DRM device 95 + * drm_bridge_attach - attach the bridge to an encoder's chain 97 96 * 98 - * @dev: DRM device 99 - * @bridge: bridge control structure 97 + * @encoder: DRM encoder 98 + * @bridge: bridge to attach 99 + * @previous: previous bridge in the chain (optional) 100 100 * 101 - * Called by a kms driver to link one of our encoder/bridge to the given 102 - * bridge. 101 + * Called by a kms driver to link the bridge to an encoder's chain. The previous 102 + * argument specifies the previous bridge in the chain. If NULL, the bridge is 103 + * linked directly at the encoder's output. Otherwise it is linked at the 104 + * previous bridge's output. 103 105 * 104 - * Note that setting up links between the bridge and our encoder/bridge 105 - * objects needs to be handled by the kms driver itself. 106 + * If non-NULL the previous bridge must be already attached by a call to this 107 + * function. 106 108 * 107 109 * RETURNS: 108 110 * Zero on success, error code on failure 109 111 */ 110 - int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge) 112 + int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge, 113 + struct drm_bridge *previous) 111 114 { 112 - if (!dev || !bridge) 115 + int ret; 116 + 117 + if (!encoder || !bridge) 118 + return -EINVAL; 119 + 120 + if (previous && (!previous->dev || previous->encoder != encoder)) 113 121 return -EINVAL; 114 122 115 123 if (bridge->dev) 116 124 return -EBUSY; 117 125 118 - bridge->dev = dev; 126 + bridge->dev = encoder->dev; 127 + bridge->encoder = encoder; 119 128 120 - if (bridge->funcs->attach) 121 - return bridge->funcs->attach(bridge); 129 + if (bridge->funcs->attach) { 130 + ret = bridge->funcs->attach(bridge); 131 + if (ret < 0) { 132 + bridge->dev = NULL; 133 + bridge->encoder = NULL; 134 + return ret; 135 + } 136 + } 137 + 138 + if (previous) 139 + previous->next = bridge; 140 + else 141 + encoder->bridge = bridge; 122 142 123 143 return 0; 124 144 }
+1 -3
drivers/gpu/drm/drm_simple_kms_helper.c
··· 182 182 int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe, 183 183 struct drm_bridge *bridge) 184 184 { 185 - bridge->encoder = &pipe->encoder; 186 - pipe->encoder.bridge = bridge; 187 - return drm_bridge_attach(pipe->encoder.dev, bridge); 185 + return drm_bridge_attach(&pipe->encoder, bridge, NULL); 188 186 } 189 187 EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge); 190 188
+1 -4
drivers/gpu/drm/exynos/exynos_dp.c
··· 99 99 struct drm_connector *connector) 100 100 { 101 101 struct exynos_dp_device *dp = to_dp(plat_data); 102 - struct drm_encoder *encoder = &dp->encoder; 103 102 int ret; 104 103 105 104 drm_connector_register(connector); ··· 106 107 107 108 /* Pre-empt DP connector creation if there's a bridge */ 108 109 if (dp->ptn_bridge) { 109 - bridge->next = dp->ptn_bridge; 110 - dp->ptn_bridge->encoder = encoder; 111 - ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge); 110 + ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge); 112 111 if (ret) { 113 112 DRM_ERROR("Failed to attach bridge to drm\n"); 114 113 bridge->next = NULL;
+2 -4
drivers/gpu/drm/exynos/exynos_drm_dsi.c
··· 1718 1718 } 1719 1719 1720 1720 bridge = of_drm_find_bridge(dsi->bridge_node); 1721 - if (bridge) { 1722 - encoder->bridge = bridge; 1723 - drm_bridge_attach(drm_dev, bridge); 1724 - } 1721 + if (bridge) 1722 + drm_bridge_attach(encoder, bridge, NULL); 1725 1723 1726 1724 return mipi_dsi_host_register(&dsi->dsi_host); 1727 1725 }
+1 -4
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
··· 160 160 if (!bridge) 161 161 return -ENODEV; 162 162 163 - fsl_dev->encoder.bridge = bridge; 164 - bridge->encoder = &fsl_dev->encoder; 165 - 166 - return drm_bridge_attach(fsl_dev->drm, bridge); 163 + return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL); 167 164 } 168 165 169 166 int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
+1 -4
drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
··· 709 709 int ret; 710 710 711 711 /* associate the bridge to dsi encoder */ 712 - encoder->bridge = bridge; 713 - bridge->encoder = encoder; 714 - 715 - ret = drm_bridge_attach(dev, bridge); 712 + ret = drm_bridge_attach(encoder, bridge, NULL); 716 713 if (ret) { 717 714 DRM_ERROR("failed to attach external bridge\n"); 718 715 return ret;
+2 -4
drivers/gpu/drm/imx/imx-ldb.c
··· 454 454 DRM_MODE_ENCODER_LVDS, NULL); 455 455 456 456 if (imx_ldb_ch->bridge) { 457 - imx_ldb_ch->bridge->encoder = encoder; 458 - 459 - imx_ldb_ch->encoder.bridge = imx_ldb_ch->bridge; 460 - ret = drm_bridge_attach(drm, imx_ldb_ch->bridge); 457 + ret = drm_bridge_attach(&imx_ldb_ch->encoder, 458 + imx_ldb_ch->bridge, NULL); 461 459 if (ret) { 462 460 DRM_ERROR("Failed to initialize bridge with drm\n"); 463 461 return ret;
+1 -3
drivers/gpu/drm/imx/parallel-display.c
··· 191 191 drm_panel_attach(imxpd->panel, &imxpd->connector); 192 192 193 193 if (imxpd->bridge) { 194 - imxpd->bridge->encoder = encoder; 195 - encoder->bridge = imxpd->bridge; 196 - ret = drm_bridge_attach(drm, imxpd->bridge); 194 + ret = drm_bridge_attach(encoder, imxpd->bridge, NULL); 197 195 if (ret < 0) { 198 196 dev_err(imxpd->dev, "failed to attach bridge: %d\n", 199 197 ret);
+4 -4
drivers/gpu/drm/mediatek/mtk_dpi.c
··· 63 63 struct mtk_dpi { 64 64 struct mtk_ddp_comp ddp_comp; 65 65 struct drm_encoder encoder; 66 + struct drm_bridge *bridge; 66 67 void __iomem *regs; 67 68 struct device *dev; 68 69 struct clk *engine_clk; ··· 621 620 /* Currently DPI0 is fixed to be driven by OVL1 */ 622 621 dpi->encoder.possible_crtcs = BIT(1); 623 622 624 - dpi->encoder.bridge->encoder = &dpi->encoder; 625 - ret = drm_bridge_attach(dpi->encoder.dev, dpi->encoder.bridge); 623 + ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL); 626 624 if (ret) { 627 625 dev_err(dev, "Failed to attach bridge: %d\n", ret); 628 626 goto err_cleanup; ··· 718 718 719 719 dev_info(dev, "Found bridge node: %s\n", bridge_node->full_name); 720 720 721 - dpi->encoder.bridge = of_drm_find_bridge(bridge_node); 721 + dpi->bridge = of_drm_find_bridge(bridge_node); 722 722 of_node_put(bridge_node); 723 - if (!dpi->encoder.bridge) 723 + if (!dpi->bridge) 724 724 return -EPROBE_DEFER; 725 725 726 726 comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI);
+3 -21
drivers/gpu/drm/mediatek/mtk_dsi.c
··· 622 622 .get_modes = mtk_dsi_connector_get_modes, 623 623 }; 624 624 625 - static int mtk_drm_attach_bridge(struct drm_bridge *bridge, 626 - struct drm_encoder *encoder) 627 - { 628 - int ret; 629 - 630 - if (!bridge) 631 - return -ENOENT; 632 - 633 - encoder->bridge = bridge; 634 - bridge->encoder = encoder; 635 - ret = drm_bridge_attach(encoder->dev, bridge); 636 - if (ret) { 637 - DRM_ERROR("Failed to attach bridge to drm\n"); 638 - encoder->bridge = NULL; 639 - bridge->encoder = NULL; 640 - } 641 - 642 - return ret; 643 - } 644 - 645 625 static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi) 646 626 { 647 627 int ret; ··· 672 692 dsi->encoder.possible_crtcs = 1; 673 693 674 694 /* If there's a bridge, attach to it and let it create the connector */ 675 - ret = mtk_drm_attach_bridge(dsi->bridge, &dsi->encoder); 695 + ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL); 676 696 if (ret) { 697 + DRM_ERROR("Failed to attach bridge to drm\n"); 698 + 677 699 /* Otherwise create our own connector and attach to a panel */ 678 700 ret = mtk_dsi_create_connector(drm, dsi); 679 701 if (ret)
+6 -5
drivers/gpu/drm/mediatek/mtk_hdmi.c
··· 149 149 150 150 struct mtk_hdmi { 151 151 struct drm_bridge bridge; 152 + struct drm_bridge *next_bridge; 152 153 struct drm_connector conn; 153 154 struct device *dev; 154 155 struct phy *phy; ··· 1315 1314 return ret; 1316 1315 } 1317 1316 1318 - if (bridge->next) { 1319 - bridge->next->encoder = bridge->encoder; 1320 - ret = drm_bridge_attach(bridge->encoder->dev, bridge->next); 1317 + if (hdmi->next_bridge) { 1318 + ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge, 1319 + bridge); 1321 1320 if (ret) { 1322 1321 dev_err(hdmi->dev, 1323 1322 "Failed to attach external bridge: %d\n", ret); ··· 1511 1510 of_node_put(ep); 1512 1511 1513 1512 if (!of_device_is_compatible(remote, "hdmi-connector")) { 1514 - hdmi->bridge.next = of_drm_find_bridge(remote); 1515 - if (!hdmi->bridge.next) { 1513 + hdmi->next_bridge = of_drm_find_bridge(remote); 1514 + if (!hdmi->next_bridge) { 1516 1515 dev_err(dev, "Waiting for external bridge\n"); 1517 1516 of_node_put(remote); 1518 1517 return -EPROBE_DEFER;
+11 -6
drivers/gpu/drm/msm/dsi/dsi_manager.c
··· 579 579 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); 580 580 struct drm_bridge *bridge = NULL; 581 581 struct dsi_bridge *dsi_bridge; 582 + struct drm_encoder *encoder; 582 583 int ret; 583 584 584 585 dsi_bridge = devm_kzalloc(msm_dsi->dev->dev, ··· 591 590 592 591 dsi_bridge->id = id; 593 592 593 + /* 594 + * HACK: we may not know the external DSI bridge device's mode 595 + * flags here. We'll get to know them only when the device 596 + * attaches to the dsi host. For now, assume the bridge supports 597 + * DSI video mode 598 + */ 599 + encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID]; 600 + 594 601 bridge = &dsi_bridge->base; 595 602 bridge->funcs = &dsi_mgr_bridge_funcs; 596 603 597 - ret = drm_bridge_attach(msm_dsi->dev, bridge); 604 + ret = drm_bridge_attach(encoder, bridge, NULL); 598 605 if (ret) 599 606 goto fail; 600 607 ··· 637 628 encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID]; 638 629 639 630 /* link the internal dsi bridge to the external bridge */ 640 - int_bridge->next = ext_bridge; 641 - /* set the external bridge's encoder as dsi's encoder */ 642 - ext_bridge->encoder = encoder; 643 - 644 - drm_bridge_attach(dev, ext_bridge); 631 + drm_bridge_attach(encoder, ext_bridge, int_bridge); 645 632 646 633 /* 647 634 * we need the drm_connector created by the external bridge
+1 -1
drivers/gpu/drm/msm/edp/edp_bridge.c
··· 106 106 bridge = &edp_bridge->base; 107 107 bridge->funcs = &edp_bridge_funcs; 108 108 109 - ret = drm_bridge_attach(edp->dev, bridge); 109 + ret = drm_bridge_attach(edp->encoder, bridge, NULL); 110 110 if (ret) 111 111 goto fail; 112 112
+1 -1
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
··· 227 227 bridge = &hdmi_bridge->base; 228 228 bridge->funcs = &msm_hdmi_bridge_funcs; 229 229 230 - ret = drm_bridge_attach(hdmi->dev, bridge); 230 + ret = drm_bridge_attach(hdmi->encoder, bridge, NULL); 231 231 if (ret) 232 232 goto fail; 233 233
+1 -4
drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
··· 124 124 hdmienc->renc = renc; 125 125 126 126 /* Link the bridge to the encoder. */ 127 - bridge->encoder = encoder; 128 - encoder->bridge = bridge; 129 - 130 - ret = drm_bridge_attach(rcdu->ddev, bridge); 127 + ret = drm_bridge_attach(encoder, bridge, NULL); 131 128 if (ret) { 132 129 drm_encoder_cleanup(encoder); 133 130 return ret;
+1 -2
drivers/gpu/drm/sti/sti_dvo.c
··· 478 478 return err; 479 479 } 480 480 481 - err = drm_bridge_attach(drm_dev, bridge); 481 + err = drm_bridge_attach(encoder, bridge, NULL); 482 482 if (err) { 483 483 DRM_ERROR("Failed to attach bridge\n"); 484 484 return err; 485 485 } 486 486 487 487 dvo->bridge = bridge; 488 - encoder->bridge = bridge; 489 488 connector->encoder = encoder; 490 489 dvo->encoder = encoder; 491 490
+1 -2
drivers/gpu/drm/sti/sti_hda.c
··· 707 707 708 708 bridge->driver_private = hda; 709 709 bridge->funcs = &sti_hda_bridge_funcs; 710 - drm_bridge_attach(drm_dev, bridge); 710 + drm_bridge_attach(encoder, bridge, NULL); 711 711 712 - encoder->bridge = bridge; 713 712 connector->encoder = encoder; 714 713 715 714 drm_connector = (struct drm_connector *)connector;
+1 -2
drivers/gpu/drm/sti/sti_hdmi.c
··· 1308 1308 1309 1309 bridge->driver_private = hdmi; 1310 1310 bridge->funcs = &sti_hdmi_bridge_funcs; 1311 - drm_bridge_attach(drm_dev, bridge); 1311 + drm_bridge_attach(encoder, bridge, NULL); 1312 1312 1313 - encoder->bridge = bridge; 1314 1313 connector->encoder = encoder; 1315 1314 1316 1315 drm_connector = (struct drm_connector *)connector;
+5 -8
drivers/gpu/drm/sun4i/sun4i_rgb.c
··· 208 208 struct sun4i_drv *drv = drm->dev_private; 209 209 struct sun4i_tcon *tcon = drv->tcon; 210 210 struct drm_encoder *encoder; 211 + struct drm_bridge *bridge; 211 212 struct sun4i_rgb *rgb; 212 213 int ret; 213 214 ··· 219 218 encoder = &rgb->encoder; 220 219 221 220 tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node); 222 - encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node); 223 - if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) { 221 + bridge = sun4i_tcon_find_bridge(tcon->dev->of_node); 222 + if (IS_ERR(tcon->panel) && IS_ERR(bridge)) { 224 223 dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n"); 225 224 return 0; 226 225 } ··· 261 260 } 262 261 } 263 262 264 - if (!IS_ERR(encoder->bridge)) { 265 - encoder->bridge->encoder = &rgb->encoder; 266 - 267 - ret = drm_bridge_attach(drm, encoder->bridge); 263 + if (!IS_ERR(bridge)) { 264 + ret = drm_bridge_attach(encoder, bridge, NULL); 268 265 if (ret) { 269 266 dev_err(drm->dev, "Couldn't attach our bridge\n"); 270 267 goto err_cleanup_connector; 271 268 } 272 - } else { 273 - encoder->bridge = NULL; 274 269 } 275 270 276 271 return 0;
+1 -3
drivers/gpu/drm/tilcdc/tilcdc_external.c
··· 167 167 int ret; 168 168 169 169 priv->external_encoder->possible_crtcs = BIT(0); 170 - priv->external_encoder->bridge = bridge; 171 - bridge->encoder = priv->external_encoder; 172 170 173 - ret = drm_bridge_attach(ddev, bridge); 171 + ret = drm_bridge_attach(priv->external_encoder, bridge, NULL); 174 172 if (ret) { 175 173 dev_err(ddev->dev, "drm_bridge_attach() failed %d\n", ret); 176 174 return ret;
+2 -1
include/drm/drm_bridge.h
··· 201 201 int drm_bridge_add(struct drm_bridge *bridge); 202 202 void drm_bridge_remove(struct drm_bridge *bridge); 203 203 struct drm_bridge *of_drm_find_bridge(struct device_node *np); 204 - int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge); 204 + int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge, 205 + struct drm_bridge *previous); 205 206 void drm_bridge_detach(struct drm_bridge *bridge); 206 207 207 208 bool drm_bridge_mode_fixup(struct drm_bridge *bridge,