Commit c3b75d47 authored by Maxime Ripard's avatar Maxime Ripard

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: default avatarSam Ravnborg <sam@ravnborg.org>
Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20211025151536.1048186-18-maxime@cerno.tech
parent 77d2a71b
...@@ -702,58 +702,27 @@ static struct ti_sn65dsi86 *bridge_to_ti_sn65dsi86(struct drm_bridge *bridge) ...@@ -702,58 +702,27 @@ static struct ti_sn65dsi86 *bridge_to_ti_sn65dsi86(struct drm_bridge *bridge)
return container_of(bridge, struct ti_sn65dsi86, bridge); return container_of(bridge, struct ti_sn65dsi86, bridge);
} }
static int ti_sn_bridge_attach(struct drm_bridge *bridge, static int ti_sn_attach_host(struct ti_sn65dsi86 *pdata)
enum drm_bridge_attach_flags flags)
{ {
int ret, val; int ret, val;
struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge);
struct mipi_dsi_host *host; struct mipi_dsi_host *host;
struct mipi_dsi_device *dsi; struct mipi_dsi_device *dsi;
struct device *dev = pdata->dev; struct device *dev = pdata->dev;
const struct mipi_dsi_device_info info = { .type = "ti_sn_bridge", const struct mipi_dsi_device_info info = { .type = "ti_sn_bridge",
.channel = 0, .channel = 0,
.node = NULL, .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); host = of_find_mipi_dsi_host_by_node(pdata->host_node);
if (!host) { if (!host) {
DRM_ERROR("failed to find dsi host\n"); DRM_ERROR("failed to find dsi host\n");
ret = -ENODEV; return -ENODEV;
goto err_dsi_host;
} }
dsi = devm_mipi_dsi_device_register_full(dev, host, &info); dsi = devm_mipi_dsi_device_register_full(dev, host, &info);
if (IS_ERR(dsi)) { if (IS_ERR(dsi)) {
DRM_ERROR("failed to create dsi device\n"); DRM_ERROR("failed to create dsi device\n");
ret = PTR_ERR(dsi); return PTR_ERR(dsi);
goto err_dsi_host;
} }
/* TODO: setting to 4 MIPI lanes always for now */ /* TODO: setting to 4 MIPI lanes always for now */
...@@ -768,12 +737,38 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge, ...@@ -768,12 +737,38 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge,
if (!(val & DPPLL_CLK_SRC_DSICLK)) if (!(val & DPPLL_CLK_SRC_DSICLK))
dsi->mode_flags |= MIPI_DSI_CLOCK_NON_CONTINUOUS; dsi->mode_flags |= MIPI_DSI_CLOCK_NON_CONTINUOUS;
pdata->dsi = dsi;
ret = devm_mipi_dsi_attach(dev, dsi); ret = devm_mipi_dsi_attach(dev, dsi);
if (ret < 0) { if (ret < 0) {
DRM_ERROR("failed to attach dsi to host\n"); 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: */ /* We never want the next bridge to *also* create a connector: */
flags |= DRM_BRIDGE_ATTACH_NO_CONNECTOR; flags |= DRM_BRIDGE_ATTACH_NO_CONNECTOR;
...@@ -1271,7 +1266,15 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev, ...@@ -1271,7 +1266,15 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev,
drm_bridge_add(&pdata->bridge); drm_bridge_add(&pdata->bridge);
ret = ti_sn_attach_host(pdata);
if (ret)
goto err_remove_bridge;
return 0; return 0;
err_remove_bridge:
drm_bridge_remove(&pdata->bridge);
return ret;
} }
static void ti_sn_bridge_remove(struct auxiliary_device *adev) static void ti_sn_bridge_remove(struct auxiliary_device *adev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment