Loading msm/dsi/dsi_display.c +60 −0 Original line number Diff line number Diff line Loading @@ -2455,6 +2455,63 @@ void dsi_display_enable_event(struct drm_connector *connector, } } int dsi_display_ctrl_vreg_on(struct dsi_display *display) { int rc = 0; int i; struct dsi_display_ctrl *ctrl; struct dsi_ctrl *dsi_ctrl; display_for_each_ctrl(i, display) { ctrl = &display->ctrl[i]; if (!ctrl->ctrl) continue; dsi_ctrl = ctrl->ctrl; if (dsi_ctrl->current_state.host_initialized) { rc = dsi_pwr_enable_regulator( &dsi_ctrl->pwr_info.host_pwr, true); if (rc) { DSI_ERR("[%s] Failed to enable vreg, rc=%d\n", dsi_ctrl->name, rc); goto error; } DSI_DEBUG("[%s] Enable ctrl vreg\n", dsi_ctrl->name); } } error: return rc; } int dsi_display_ctrl_vreg_off(struct dsi_display *display) { int rc = 0; int i; struct dsi_display_ctrl *ctrl; struct dsi_ctrl *dsi_ctrl; display_for_each_ctrl(i, display) { ctrl = &display->ctrl[i]; if (!ctrl->ctrl) continue; dsi_ctrl = ctrl->ctrl; if (dsi_ctrl->current_state.host_initialized) { rc = dsi_pwr_enable_regulator( &dsi_ctrl->pwr_info.host_pwr, false); if (rc) { DSI_ERR("[%s] Failed to disable vreg, rc=%d\n", dsi_ctrl->name, rc); goto error; } DSI_DEBUG("[%s] Disable ctrl vreg\n", dsi_ctrl->name); } } error: return rc; } static int dsi_display_ctrl_power_on(struct dsi_display *display) { int rc = 0; Loading Loading @@ -4204,6 +4261,9 @@ static int dsi_display_parse_dt(struct dsi_display *display) display->needs_clk_src_reset = of_property_read_bool(of_node, "qcom,needs-clk-src-reset"); display->needs_ctrl_vreg_disable = of_property_read_bool(of_node, "qcom,needs-ctrl-vreg-disable"); /* Parse all external bridges from port 0 */ display_for_each_ctrl(i, display) { display->ext_bridge[i].node_of = Loading msm/dsi/dsi_display.h +18 −0 Original line number Diff line number Diff line Loading @@ -215,6 +215,7 @@ struct dsi_display { bool is_te_irq_enabled; struct completion esd_te_gate; bool needs_clk_src_reset; bool needs_ctrl_vreg_disable; u32 ctrl_count; struct dsi_display_ctrl ctrl[MAX_DSI_CTRLS_PER_DISPLAY]; Loading Loading @@ -817,4 +818,21 @@ int dsi_display_unset_clk_src(struct dsi_display *display); * Return: Zero on Success */ int dsi_display_set_clk_src(struct dsi_display *display); /** * dsi_display_ctrl_vreg_on() - enable dsi ctrl regulator * @display: Handle to display * * Return: Zero on Success */ int dsi_display_ctrl_vreg_on(struct dsi_display *display); /** * dsi_display_ctrl_vreg_off() - disable dsi ctrl regulator * @display: Handle to display * * Return: Zero on Success */ int dsi_display_ctrl_vreg_off(struct dsi_display *display); #endif /* _DSI_DISPLAY_H_ */ msm/sde/sde_kms.c +33 −21 Original line number Diff line number Diff line Loading @@ -3715,38 +3715,51 @@ void sde_kms_display_early_wakeup(struct drm_device *dev, } #ifdef CONFIG_DEEPSLEEP static int _sde_kms_pm_set_clk_src(struct sde_kms *sde_kms, bool enable) static int _sde_kms_pm_deepsleep_helper(struct sde_kms *sde_kms, bool enter) { int i, rc = 0; void *display; struct dsi_display *dsi_display; if (mem_sleep_current == PM_SUSPEND_MEM) { SDE_INFO("Deepsleep\n"); if (mem_sleep_current != PM_SUSPEND_MEM) return 0; SDE_INFO("Deepsleep : enter %d\n", enter); for (i = 0; i < sde_kms->dsi_display_count; i++) { display = sde_kms->dsi_displays[i]; dsi_display = (struct dsi_display *)display; if (!dsi_display->needs_clk_src_reset) continue; if (enable) rc = dsi_display_set_clk_src(dsi_display); else rc = dsi_display_unset_clk_src(dsi_display); if (enter) { /* During deepsleep, clk_parent are reset at HW * but sw caching is retained in clk framework. To * maintain same state. unset parents and restore * during exit. */ if (dsi_display->needs_clk_src_reset) (void)dsi_display_unset_clk_src(dsi_display); /* DSI ctrl regulator can be disabled, even in static * screen, during deepsleep */ if (dsi_display->needs_ctrl_vreg_disable) (void)dsi_display_ctrl_vreg_off(dsi_display); } else { if (dsi_display->needs_ctrl_vreg_disable) (void)dsi_display_ctrl_vreg_on(dsi_display); if (dsi_display->needs_clk_src_reset) (void)dsi_display_set_clk_src(dsi_display); if (rc) { SDE_ERROR("failed to set clks rc:%d\n", rc); return rc; } } } return rc; } #else static inline int _sde_kms_pm_set_clk_src(struct sde_kms *sde_kms, bool enable) static inline int _sde_kms_pm_deepsleep_helper(struct sde_kms *sde_kms, bool enter) { return 0; } Loading Loading @@ -3943,8 +3956,7 @@ static int sde_kms_pm_suspend(struct device *dev) pm_runtime_put_sync(dev); pm_runtime_get_noresume(dev); /* reset clock source based on PM suspend state */ _sde_kms_pm_set_clk_src(sde_kms, false); _sde_kms_pm_deepsleep_helper(sde_kms, true); /* dump clock state before entering suspend */ if (sde_kms->pm_suspend_clk_dump) Loading Loading @@ -3983,8 +3995,8 @@ static int sde_kms_pm_resume(struct device *dev) goto end; } /* reset clock source based on PM suspend state */ _sde_kms_pm_set_clk_src(sde_kms, true); /* If coming out of deepsleep, restore resources.*/ _sde_kms_pm_deepsleep_helper(sde_kms, false); sde_kms->suspend_block = false; Loading Loading
msm/dsi/dsi_display.c +60 −0 Original line number Diff line number Diff line Loading @@ -2455,6 +2455,63 @@ void dsi_display_enable_event(struct drm_connector *connector, } } int dsi_display_ctrl_vreg_on(struct dsi_display *display) { int rc = 0; int i; struct dsi_display_ctrl *ctrl; struct dsi_ctrl *dsi_ctrl; display_for_each_ctrl(i, display) { ctrl = &display->ctrl[i]; if (!ctrl->ctrl) continue; dsi_ctrl = ctrl->ctrl; if (dsi_ctrl->current_state.host_initialized) { rc = dsi_pwr_enable_regulator( &dsi_ctrl->pwr_info.host_pwr, true); if (rc) { DSI_ERR("[%s] Failed to enable vreg, rc=%d\n", dsi_ctrl->name, rc); goto error; } DSI_DEBUG("[%s] Enable ctrl vreg\n", dsi_ctrl->name); } } error: return rc; } int dsi_display_ctrl_vreg_off(struct dsi_display *display) { int rc = 0; int i; struct dsi_display_ctrl *ctrl; struct dsi_ctrl *dsi_ctrl; display_for_each_ctrl(i, display) { ctrl = &display->ctrl[i]; if (!ctrl->ctrl) continue; dsi_ctrl = ctrl->ctrl; if (dsi_ctrl->current_state.host_initialized) { rc = dsi_pwr_enable_regulator( &dsi_ctrl->pwr_info.host_pwr, false); if (rc) { DSI_ERR("[%s] Failed to disable vreg, rc=%d\n", dsi_ctrl->name, rc); goto error; } DSI_DEBUG("[%s] Disable ctrl vreg\n", dsi_ctrl->name); } } error: return rc; } static int dsi_display_ctrl_power_on(struct dsi_display *display) { int rc = 0; Loading Loading @@ -4204,6 +4261,9 @@ static int dsi_display_parse_dt(struct dsi_display *display) display->needs_clk_src_reset = of_property_read_bool(of_node, "qcom,needs-clk-src-reset"); display->needs_ctrl_vreg_disable = of_property_read_bool(of_node, "qcom,needs-ctrl-vreg-disable"); /* Parse all external bridges from port 0 */ display_for_each_ctrl(i, display) { display->ext_bridge[i].node_of = Loading
msm/dsi/dsi_display.h +18 −0 Original line number Diff line number Diff line Loading @@ -215,6 +215,7 @@ struct dsi_display { bool is_te_irq_enabled; struct completion esd_te_gate; bool needs_clk_src_reset; bool needs_ctrl_vreg_disable; u32 ctrl_count; struct dsi_display_ctrl ctrl[MAX_DSI_CTRLS_PER_DISPLAY]; Loading Loading @@ -817,4 +818,21 @@ int dsi_display_unset_clk_src(struct dsi_display *display); * Return: Zero on Success */ int dsi_display_set_clk_src(struct dsi_display *display); /** * dsi_display_ctrl_vreg_on() - enable dsi ctrl regulator * @display: Handle to display * * Return: Zero on Success */ int dsi_display_ctrl_vreg_on(struct dsi_display *display); /** * dsi_display_ctrl_vreg_off() - disable dsi ctrl regulator * @display: Handle to display * * Return: Zero on Success */ int dsi_display_ctrl_vreg_off(struct dsi_display *display); #endif /* _DSI_DISPLAY_H_ */
msm/sde/sde_kms.c +33 −21 Original line number Diff line number Diff line Loading @@ -3715,38 +3715,51 @@ void sde_kms_display_early_wakeup(struct drm_device *dev, } #ifdef CONFIG_DEEPSLEEP static int _sde_kms_pm_set_clk_src(struct sde_kms *sde_kms, bool enable) static int _sde_kms_pm_deepsleep_helper(struct sde_kms *sde_kms, bool enter) { int i, rc = 0; void *display; struct dsi_display *dsi_display; if (mem_sleep_current == PM_SUSPEND_MEM) { SDE_INFO("Deepsleep\n"); if (mem_sleep_current != PM_SUSPEND_MEM) return 0; SDE_INFO("Deepsleep : enter %d\n", enter); for (i = 0; i < sde_kms->dsi_display_count; i++) { display = sde_kms->dsi_displays[i]; dsi_display = (struct dsi_display *)display; if (!dsi_display->needs_clk_src_reset) continue; if (enable) rc = dsi_display_set_clk_src(dsi_display); else rc = dsi_display_unset_clk_src(dsi_display); if (enter) { /* During deepsleep, clk_parent are reset at HW * but sw caching is retained in clk framework. To * maintain same state. unset parents and restore * during exit. */ if (dsi_display->needs_clk_src_reset) (void)dsi_display_unset_clk_src(dsi_display); /* DSI ctrl regulator can be disabled, even in static * screen, during deepsleep */ if (dsi_display->needs_ctrl_vreg_disable) (void)dsi_display_ctrl_vreg_off(dsi_display); } else { if (dsi_display->needs_ctrl_vreg_disable) (void)dsi_display_ctrl_vreg_on(dsi_display); if (dsi_display->needs_clk_src_reset) (void)dsi_display_set_clk_src(dsi_display); if (rc) { SDE_ERROR("failed to set clks rc:%d\n", rc); return rc; } } } return rc; } #else static inline int _sde_kms_pm_set_clk_src(struct sde_kms *sde_kms, bool enable) static inline int _sde_kms_pm_deepsleep_helper(struct sde_kms *sde_kms, bool enter) { return 0; } Loading Loading @@ -3943,8 +3956,7 @@ static int sde_kms_pm_suspend(struct device *dev) pm_runtime_put_sync(dev); pm_runtime_get_noresume(dev); /* reset clock source based on PM suspend state */ _sde_kms_pm_set_clk_src(sde_kms, false); _sde_kms_pm_deepsleep_helper(sde_kms, true); /* dump clock state before entering suspend */ if (sde_kms->pm_suspend_clk_dump) Loading Loading @@ -3983,8 +3995,8 @@ static int sde_kms_pm_resume(struct device *dev) goto end; } /* reset clock source based on PM suspend state */ _sde_kms_pm_set_clk_src(sde_kms, true); /* If coming out of deepsleep, restore resources.*/ _sde_kms_pm_deepsleep_helper(sde_kms, false); sde_kms->suspend_block = false; Loading