Commit 4280e1a0 authored by Maxime Ripard's avatar Maxime Ripard

drm/kirin: dsi: Adjust probe order

Without proper care and an agreement between how DSI hosts and devices
drivers register their MIPI-DSI entities and potential components, we can
end up in a situation where the drivers can never probe.

Most drivers were taking evasive maneuvers to try to workaround this,
but not all of them were following the same conventions, resulting in
various incompatibilities between DSI hosts and devices.

Now that we have a sequence agreed upon and documented, let's convert
kirin to it.
Acked-by: default avatarJohn Stultz <john.stultz@linaro.org>
Tested-by: default avatarJohn Stultz <john.stultz@linaro.org>
Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20211025151536.1048186-21-maxime@cerno.tech
parent 4d77688f
...@@ -81,7 +81,7 @@ struct dsi_hw_ctx { ...@@ -81,7 +81,7 @@ struct dsi_hw_ctx {
struct dw_dsi { struct dw_dsi {
struct drm_encoder encoder; struct drm_encoder encoder;
struct drm_bridge *bridge; struct device *dev;
struct mipi_dsi_host host; struct mipi_dsi_host host;
struct drm_display_mode cur_mode; struct drm_display_mode cur_mode;
struct dsi_hw_ctx *ctx; struct dsi_hw_ctx *ctx;
...@@ -720,10 +720,13 @@ static int dw_drm_encoder_init(struct device *dev, ...@@ -720,10 +720,13 @@ static int dw_drm_encoder_init(struct device *dev,
return 0; return 0;
} }
static const struct component_ops dsi_ops;
static int dsi_host_attach(struct mipi_dsi_host *host, static int dsi_host_attach(struct mipi_dsi_host *host,
struct mipi_dsi_device *mdsi) struct mipi_dsi_device *mdsi)
{ {
struct dw_dsi *dsi = host_to_dsi(host); struct dw_dsi *dsi = host_to_dsi(host);
struct device *dev = host->dev;
int ret;
if (mdsi->lanes < 1 || mdsi->lanes > 4) { if (mdsi->lanes < 1 || mdsi->lanes > 4) {
DRM_ERROR("dsi device params invalid\n"); DRM_ERROR("dsi device params invalid\n");
...@@ -734,13 +737,20 @@ static int dsi_host_attach(struct mipi_dsi_host *host, ...@@ -734,13 +737,20 @@ static int dsi_host_attach(struct mipi_dsi_host *host,
dsi->format = mdsi->format; dsi->format = mdsi->format;
dsi->mode_flags = mdsi->mode_flags; dsi->mode_flags = mdsi->mode_flags;
ret = component_add(dev, &dsi_ops);
if (ret)
return ret;
return 0; return 0;
} }
static int dsi_host_detach(struct mipi_dsi_host *host, static int dsi_host_detach(struct mipi_dsi_host *host,
struct mipi_dsi_device *mdsi) struct mipi_dsi_device *mdsi)
{ {
/* do nothing */ struct device *dev = host->dev;
component_del(dev, &dsi_ops);
return 0; return 0;
} }
...@@ -768,7 +778,17 @@ static int dsi_host_init(struct device *dev, struct dw_dsi *dsi) ...@@ -768,7 +778,17 @@ static int dsi_host_init(struct device *dev, struct dw_dsi *dsi)
static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi) static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi)
{ {
struct drm_encoder *encoder = &dsi->encoder; struct drm_encoder *encoder = &dsi->encoder;
struct drm_bridge *bridge = dsi->bridge; struct drm_bridge *bridge;
struct device_node *np = dsi->dev->of_node;
int ret;
/*
* Get the endpoint node. In our case, dsi has one output port1
* to which the external HDMI bridge is connected.
*/
ret = drm_of_find_panel_or_bridge(np, 1, 0, NULL, &bridge);
if (ret)
return ret;
/* associate the bridge to dsi encoder */ /* associate the bridge to dsi encoder */
return drm_bridge_attach(encoder, bridge, NULL, 0); return drm_bridge_attach(encoder, bridge, NULL, 0);
...@@ -785,10 +805,6 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) ...@@ -785,10 +805,6 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
if (ret) if (ret)
return ret; return ret;
ret = dsi_host_init(dev, dsi);
if (ret)
return ret;
ret = dsi_bridge_init(drm_dev, dsi); ret = dsi_bridge_init(drm_dev, dsi);
if (ret) if (ret)
return ret; return ret;
...@@ -809,17 +825,7 @@ static const struct component_ops dsi_ops = { ...@@ -809,17 +825,7 @@ static const struct component_ops dsi_ops = {
static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi) static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi)
{ {
struct dsi_hw_ctx *ctx = dsi->ctx; struct dsi_hw_ctx *ctx = dsi->ctx;
struct device_node *np = pdev->dev.of_node;
struct resource *res; struct resource *res;
int ret;
/*
* Get the endpoint node. In our case, dsi has one output port1
* to which the external HDMI bridge is connected.
*/
ret = drm_of_find_panel_or_bridge(np, 1, 0, NULL, &dsi->bridge);
if (ret)
return ret;
ctx->pclk = devm_clk_get(&pdev->dev, "pclk"); ctx->pclk = devm_clk_get(&pdev->dev, "pclk");
if (IS_ERR(ctx->pclk)) { if (IS_ERR(ctx->pclk)) {
...@@ -852,6 +858,7 @@ static int dsi_probe(struct platform_device *pdev) ...@@ -852,6 +858,7 @@ static int dsi_probe(struct platform_device *pdev)
dsi = &data->dsi; dsi = &data->dsi;
ctx = &data->ctx; ctx = &data->ctx;
dsi->ctx = ctx; dsi->ctx = ctx;
dsi->dev = &pdev->dev;
ret = dsi_parse_dt(pdev, dsi); ret = dsi_parse_dt(pdev, dsi);
if (ret) if (ret)
...@@ -859,12 +866,19 @@ static int dsi_probe(struct platform_device *pdev) ...@@ -859,12 +866,19 @@ static int dsi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, data); platform_set_drvdata(pdev, data);
return component_add(&pdev->dev, &dsi_ops); ret = dsi_host_init(&pdev->dev, dsi);
if (ret)
return ret;
return 0;
} }
static int dsi_remove(struct platform_device *pdev) static int dsi_remove(struct platform_device *pdev)
{ {
component_del(&pdev->dev, &dsi_ops); struct dsi_data *data = platform_get_drvdata(pdev);
struct dw_dsi *dsi = &data->dsi;
mipi_dsi_host_unregister(&dsi->host);
return 0; return 0;
} }
......
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