diff options
author | Maxime Ripard <maxime@cerno.tech> | 2021-10-25 18:15:32 +0300 |
---|---|---|
committer | Maxime Ripard <maxime@cerno.tech> | 2021-10-27 23:07:58 +0300 |
commit | c3b75d4734cb82f7dfd42b0a8243f37bca85bd95 (patch) | |
tree | bab9b9dd7e901dc22e14c6d618e688e0b4b9f072 /drivers/gpu/drm/bridge | |
parent | 77d2a71b94e3dd2966d8c595fc6443951f1e06f4 (diff) | |
download | linux-c3b75d4734cb82f7dfd42b0a8243f37bca85bd95.tar.xz |
drm/bridge: sn65dsi86: Register and attach our DSI device at probe
In order to avoid any probe ordering issue, the best practice is to move
the secondary MIPI-DSI device registration and attachment to the
MIPI-DSI host at probe time. Let's do this.
Acked-by: Sam Ravnborg <sam@ravnborg.org>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20211025151536.1048186-18-maxime@cerno.tech
Diffstat (limited to 'drivers/gpu/drm/bridge')
-rw-r--r-- | drivers/gpu/drm/bridge/ti-sn65dsi86.c | 77 |
1 files changed, 40 insertions, 37 deletions
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 6ca610ddab9e..ae15baaca476 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -702,58 +702,27 @@ static struct ti_sn65dsi86 *bridge_to_ti_sn65dsi86(struct drm_bridge *bridge) return container_of(bridge, struct ti_sn65dsi86, bridge); } -static int ti_sn_bridge_attach(struct drm_bridge *bridge, - enum drm_bridge_attach_flags flags) +static int ti_sn_attach_host(struct ti_sn65dsi86 *pdata) { int ret, val; - struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); struct mipi_dsi_host *host; struct mipi_dsi_device *dsi; struct device *dev = pdata->dev; const struct mipi_dsi_device_info info = { .type = "ti_sn_bridge", .channel = 0, .node = NULL, - }; - - if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { - DRM_ERROR("Fix bridge driver to make connector optional!"); - return -EINVAL; - } - - pdata->aux.drm_dev = bridge->dev; - ret = drm_dp_aux_register(&pdata->aux); - if (ret < 0) { - drm_err(bridge->dev, "Failed to register DP AUX channel: %d\n", ret); - return ret; - } - - ret = ti_sn_bridge_connector_init(pdata); - if (ret < 0) - goto err_conn_init; + }; - /* - * TODO: ideally finding host resource and dsi dev registration needs - * to be done in bridge probe. But some existing DSI host drivers will - * wait for any of the drm_bridge/drm_panel to get added to the global - * bridge/panel list, before completing their probe. So if we do the - * dsi dev registration part in bridge probe, before populating in - * the global bridge list, then it will cause deadlock as dsi host probe - * will never complete, neither our bridge probe. So keeping it here - * will satisfy most of the existing host drivers. Once the host driver - * is fixed we can move the below code to bridge probe safely. - */ host = of_find_mipi_dsi_host_by_node(pdata->host_node); if (!host) { DRM_ERROR("failed to find dsi host\n"); - ret = -ENODEV; - goto err_dsi_host; + return -ENODEV; } dsi = devm_mipi_dsi_device_register_full(dev, host, &info); if (IS_ERR(dsi)) { DRM_ERROR("failed to create dsi device\n"); - ret = PTR_ERR(dsi); - goto err_dsi_host; + return PTR_ERR(dsi); } /* TODO: setting to 4 MIPI lanes always for now */ @@ -768,12 +737,38 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge, if (!(val & DPPLL_CLK_SRC_DSICLK)) dsi->mode_flags |= MIPI_DSI_CLOCK_NON_CONTINUOUS; + pdata->dsi = dsi; + ret = devm_mipi_dsi_attach(dev, dsi); if (ret < 0) { DRM_ERROR("failed to attach dsi to host\n"); - goto err_dsi_host; + return ret; } - pdata->dsi = dsi; + + return 0; +} + +static int ti_sn_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); + int ret; + + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { + DRM_ERROR("Fix bridge driver to make connector optional!"); + return -EINVAL; + } + + pdata->aux.drm_dev = bridge->dev; + ret = drm_dp_aux_register(&pdata->aux); + if (ret < 0) { + drm_err(bridge->dev, "Failed to register DP AUX channel: %d\n", ret); + return ret; + } + + ret = ti_sn_bridge_connector_init(pdata); + if (ret < 0) + goto err_conn_init; /* We never want the next bridge to *also* create a connector: */ flags |= DRM_BRIDGE_ATTACH_NO_CONNECTOR; @@ -1271,7 +1266,15 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev, drm_bridge_add(&pdata->bridge); + ret = ti_sn_attach_host(pdata); + if (ret) + goto err_remove_bridge; + return 0; + +err_remove_bridge: + drm_bridge_remove(&pdata->bridge); + return ret; } static void ti_sn_bridge_remove(struct auxiliary_device *adev) |