Make the exynos_dsi driver a full drm bridge that can be found and used from other drivers. Signed-off-by: Michael Tretter <m.tretter@xxxxxxxxxxxxxx> --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 45 +++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index ddbda33dea91..4d19630f33e7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -253,6 +253,7 @@ struct exynos_dsi_driver_data { struct exynos_dsi { struct drm_encoder encoder; + struct drm_bridge bridge; struct mipi_dsi_host dsi_host; struct drm_connector connector; struct drm_panel *panel; @@ -1523,19 +1524,43 @@ static const struct drm_encoder_helper_funcs exynos_dsi_encoder_helper_funcs = { .disable = exynos_dsi_disable, }; +static int exynos_dsi_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct exynos_dsi *dsi = bridge->driver_private; + + if (!bridge->encoder) { + dev_err(dsi->dev, "missing encoder\n"); + return -ENODEV; + } + + return 0; +} + +static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = { + .attach = exynos_dsi_bridge_attach, +}; + MODULE_DEVICE_TABLE(of, exynos_dsi_of_match); static int exynos_dsi_host_attach(struct mipi_dsi_host *host, struct mipi_dsi_device *device) { struct exynos_dsi *dsi = host_to_dsi(host); - struct drm_encoder *encoder = &dsi->encoder; - struct drm_device *drm = encoder->dev; + struct drm_bridge *bridge = &dsi->bridge; + struct drm_encoder *encoder; + struct drm_device *drm; struct drm_bridge *out_bridge; + if (!bridge->encoder) + return -EPROBE_DEFER; + + encoder = bridge->encoder; + drm = encoder->dev; + out_bridge = of_drm_find_bridge(device->dev.of_node); if (out_bridge) { - drm_bridge_attach(encoder, out_bridge, NULL, 0); + drm_bridge_attach(encoder, out_bridge, bridge, 0); dsi->out_bridge = out_bridge; list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain); } else { @@ -1715,6 +1740,10 @@ static int exynos_dsi_bind(struct device *dev, struct device *master, of_node_put(in_bridge_node); } + ret = drm_bridge_attach(encoder, &dsi->bridge, in_bridge, 0); + if (ret) + return ret; + return mipi_dsi_host_register(&dsi->dsi_host); } @@ -1740,6 +1769,7 @@ static struct exynos_dsi *__exynos_dsi_probe(struct platform_device *pdev) struct resource *res; struct exynos_dsi *dsi; int ret, i; + struct drm_bridge *bridge; dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); if (!dsi) @@ -1823,11 +1853,20 @@ static struct exynos_dsi *__exynos_dsi_probe(struct platform_device *pdev) pm_runtime_enable(dev); + bridge = &dsi->bridge; + bridge->driver_private = dsi; + bridge->funcs = &exynos_dsi_bridge_funcs; + bridge->of_node = dev->of_node; + + drm_bridge_add(bridge); + return dsi; } static void __exynos_dsi_remove(struct exynos_dsi *dsi) { + drm_bridge_remove(&dsi->bridge); + pm_runtime_disable(dsi->dev); } -- 2.20.1