summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/msm/dsi/dsi_host.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/msm/dsi/dsi_host.c')
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index de0400923303..932efabeef2e 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -219,6 +219,9 @@ struct msm_dsi_host {
enum mipi_dsi_pixel_format format;
unsigned long mode_flags;
+ /* external bridge info */
+ struct device_node *ext_bridge_node;
+
u32 dma_cmd_ctrl_restore;
bool registered;
@@ -1372,6 +1375,7 @@ static int dsi_host_attach(struct mipi_dsi_host *host,
struct mipi_dsi_device *dsi)
{
struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+ struct device_node *bridge, *np = msm_host->pdev->dev.of_node;
int ret;
msm_host->channel = dsi->channel;
@@ -1379,6 +1383,13 @@ static int dsi_host_attach(struct mipi_dsi_host *host,
msm_host->format = dsi->format;
msm_host->mode_flags = dsi->mode_flags;
+ /* if we have an external bridge, don't populate panel data */
+ bridge = of_get_child_by_name(np, "bridge");
+ if (bridge) {
+ of_node_put(bridge);
+ return 0;
+ }
+
msm_host->panel_node = dsi->dev.of_node;
/* Some gpios defined in panel DT need to be controlled by host */
@@ -1579,11 +1590,26 @@ int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer)
* create framebuffer.
*/
if (check_defer) {
+ /*
+ * first look for a child panel node, if a panel node
+ * exists but the corresponding panel device isn't
+ * probed, defer msm dsi's probe
+ *
+ * if a child panel isn't specified at all, try to look
+ * for a bridge phandle, defer probe if it there is a
+ * bridge phandle but the bridge device isn't added yet
+ */
node = of_get_child_by_name(msm_host->pdev->dev.of_node,
"panel");
if (node) {
if (!of_drm_find_panel(node))
return -EPROBE_DEFER;
+ } else {
+ struct drm_bridge *bridge;
+
+ bridge = msm_dsi_host_get_ext_bridge(host);
+ if (!bridge)
+ return -EPROBE_DEFER;
}
}
}
@@ -1882,7 +1908,6 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host)
DBG("dsi host already on");
goto unlock_ret;
}
-
ret = dsi_calc_clk_rate(msm_host);
if (ret) {
pr_err("%s: unable to calc clk rate, %d\n", __func__, ret);
@@ -1905,7 +1930,7 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host)
dsi_phy_sw_reset(msm_host);
ret = msm_dsi_manager_phy_enable(msm_host->id,
msm_host->byte_clk_rate * 8,
- clk_get_rate(msm_host->esc_clk),
+ 19200000,/*clk_get_rate(msm_host->esc_clk),*/
&clk_pre, &clk_post);
dsi_bus_clk_disable(msm_host);
if (ret) {
@@ -2000,3 +2025,21 @@ struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host,
return panel;
}
+struct drm_bridge *msm_dsi_host_get_ext_bridge(struct mipi_dsi_host *host)
+{
+ struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+ struct drm_bridge *bridge;
+ struct device_node *np = msm_host->pdev->dev.of_node;
+
+ msm_host->ext_bridge_node = of_get_child_by_name(np, "bridge");
+ if (!msm_host->ext_bridge_node) {
+ dev_err(&msm_host->pdev->dev, "bridge not found\n");
+ return NULL;
+ }
+
+ bridge = of_drm_find_bridge(msm_host->ext_bridge_node);
+
+ of_node_put(msm_host->ext_bridge_node);
+
+ return bridge;
+}