@@ -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);
}
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@pengutronix.de> --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 45 +++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-)