From 201b73078ff582cac5be33a4b171b3837ff8834c Mon Sep 17 00:00:00 2001 From: Nickey Yang Date: Wed, 3 Jun 2020 11:35:53 +0800 Subject: [PATCH] drm/rockchip: dsi: support dsi bridge This patch supports bridge driver which convert DSI to other display interfaces. At the same time,it uses port method to complete the analysis of panel or bridge in dts. After this patch, the exampl of dsi node in dts: &dsi { status = "okay"; panel@0 { compatible = "xxx", "simple-panel-dsi"; reg = <0>; ports { #address-cells = <1>; #size-cells = <0>; port@0 { reg = <0>; panel_in_dsi: endpoint { remote-endpoint = <&dsi_out_panel>; }; }; }; }; ports { #address-cells = <1>; #size-cells = <0>; port@1 { reg = <1>; dsi_out_panel: endpoint { remote-endpoint = <&panel_in_dsi>; }; }; }; }; Signed-off-by: Nickey Yang Change-Id: Ic4ad8ac66f479189d7193a69a02337e1cac3dcb8 --- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 69 ++++++++++++++++++-------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c index dd9f999c1734..94b03fb4d51c 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c @@ -253,6 +253,7 @@ struct mipi_dphy { struct dw_mipi_dsi { struct drm_encoder encoder; struct drm_connector connector; + struct drm_bridge *bridge; struct mipi_dsi_host host; struct drm_panel *panel; struct drm_display_mode mode; @@ -1075,9 +1076,11 @@ static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder) { struct dw_mipi_dsi *dsi = encoder_to_dsi(encoder); - drm_panel_disable(dsi->panel); + if (dsi->panel) + drm_panel_disable(dsi->panel); dw_mipi_dsi_disable(dsi); - drm_panel_unprepare(dsi->panel); + if (dsi->panel) + drm_panel_unprepare(dsi->panel); dw_mipi_dsi_post_disable(dsi); } @@ -1310,9 +1313,11 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) dw_mipi_dsi_vop_routing(dsi); dw_mipi_dsi_pre_enable(dsi); - drm_panel_prepare(dsi->panel); + if (dsi->panel) + drm_panel_prepare(dsi->panel); dw_mipi_dsi_enable(dsi); - drm_panel_enable(dsi->panel); + if (dsi->panel) + drm_panel_enable(dsi->panel); } static int @@ -1475,9 +1480,12 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, if (dsi->master) return 0; - dsi->panel = of_drm_find_panel(dsi->client); - if (IS_ERR(dsi->panel)) - return -EPROBE_DEFER; + ret = drm_of_find_panel_or_bridge(dev->of_node, 1, -1, + &dsi->panel, &dsi->bridge); + if (ret) { + DRM_DEV_ERROR(dev, "Failed to find panel or bridge: %d\n", ret); + return ret; + } encoder->port = dev->of_node; encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, @@ -1494,24 +1502,43 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, ret = drm_encoder_init(drm, encoder, &dw_mipi_dsi_encoder_funcs, DRM_MODE_ENCODER_DSI, NULL); if (ret) { - DRM_DEV_ERROR(dev, "Failed to initialize encoder with drm\n"); + DRM_DEV_ERROR(dev, "Failed to initialize encoder\n"); return ret; } drm_encoder_helper_add(encoder, &dw_mipi_dsi_encoder_helper_funcs); - connector->port = dev->of_node; + if (dsi->panel) { + ret = drm_connector_init(drm, connector, &dw_mipi_dsi_atomic_connector_funcs, + DRM_MODE_CONNECTOR_DSI); + if (ret) { + DRM_DEV_ERROR(dev, "Failed to initialize connector\n"); + goto encoder_cleanup; + } + drm_connector_helper_add(connector, + &dw_mipi_dsi_connector_helper_funcs); + drm_connector_attach_encoder(connector, encoder); + if (ret < 0) { + DRM_DEV_ERROR(dev, "Failed to attach encoder: %d\n", ret); + goto connector_cleanup; + } - drm_connector_init(drm, connector, &dw_mipi_dsi_atomic_connector_funcs, - DRM_MODE_CONNECTOR_DSI); - drm_connector_helper_add(connector, - &dw_mipi_dsi_connector_helper_funcs); - drm_connector_attach_encoder(connector, encoder); + ret = drm_panel_attach(dsi->panel, connector); + if (ret) { + DRM_DEV_ERROR(dev, "Failed to attach panel: %d\n", ret); + goto connector_cleanup; + } + connector->port = dev->of_node; + } else { + dsi->bridge->driver_private = &dsi->host; + dsi->bridge->encoder = encoder; - ret = drm_panel_attach(dsi->panel, connector); - if (ret) { - DRM_DEV_ERROR(dsi->dev, "Failed to attach panel: %d\n", ret); - goto err_cleanup; + ret = drm_bridge_attach(encoder, dsi->bridge, NULL); + if (ret) { + DRM_DEV_ERROR(dev, "Failed to attach bridge: %d\n", ret); + goto encoder_cleanup; + } + encoder->bridge = dsi->bridge; } pm_runtime_enable(dsi->dev); @@ -1520,8 +1547,9 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, return 0; -err_cleanup: +connector_cleanup: connector->funcs->destroy(connector); +encoder_cleanup: encoder->funcs->destroy(encoder); return ret; } @@ -1535,7 +1563,8 @@ static void dw_mipi_dsi_unbind(struct device *dev, struct device *master, if (dsi->slave) pm_runtime_disable(dsi->slave->dev); - drm_panel_detach(dsi->panel); + if (dsi->panel) + drm_panel_detach(dsi->panel); dsi->connector.funcs->destroy(&dsi->connector); dsi->encoder.funcs->destroy(&dsi->encoder);