@@ -34,6 +34,32 @@ static struct msm_dsi_manager msm_dsim_glb;
#define IS_SYNC_NEEDED() (msm_dsim_glb.is_sync_needed)
#define IS_MASTER_DSI_LINK(id) (msm_dsim_glb.master_dsi_link_id == id)
+#ifdef CONFIG_OF
+static bool dsi_mgr_power_on_early(struct drm_bridge *bridge)
+{
+ struct drm_bridge *next_bridge = drm_bridge_get_next_bridge(bridge);
+
+ /*
+ * If the next bridge in the chain is the Parade ps8640 bridge chip
+ * then don't power on early since it seems to violate the expectations
+ * of the firmware that the bridge chip is running.
+ *
+ * NOTE: this is expected to be a temporary special case. It's expected
+ * that we'll eventually have a framework that allows the next level
+ * bridge to indicate whether it needs us to power on before it or
+ * after it. When that framework is in place then we'll use it and
+ * remove this special case.
+ */
+ return !(next_bridge && next_bridge->of_node &&
+ of_device_is_compatible(next_bridge->of_node, "parade,ps8640"));
+}
+#else
+static inline bool dsi_mgr_power_on_early(struct drm_bridge *bridge)
+{
+ return true;
+}
+#endif
+
static inline struct msm_dsi *dsi_mgr_get_dsi(int id)
{
return msm_dsim_glb.dsi[id];
@@ -389,6 +415,9 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
return;
+ if (!dsi_mgr_power_on_early(bridge))
+ dsi_mgr_bridge_power_on(bridge);
+
/* Always call panel functions once, because even for dual panels,
* there is only one drm_panel instance.
*/
@@ -570,7 +599,8 @@ static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge,
if (is_bonded_dsi && other_dsi)
msm_dsi_host_set_display_mode(other_dsi->host, adjusted_mode);
- dsi_mgr_bridge_power_on(bridge);
+ if (dsi_mgr_power_on_early(bridge))
+ dsi_mgr_bridge_power_on(bridge);
}
static enum drm_mode_status dsi_mgr_bridge_mode_valid(struct drm_bridge *bridge,