From 9a6ed8620ef75cd7162fc73e63402c25bea8466f Mon Sep 17 00:00:00 2001 From: Venkata Prahlad Valluru Date: Tue, 12 Apr 2022 22:36:32 +0530 Subject: [PATCH] disp: msm: sde: unset and set clk parents during pm_suspend Currently link clk parent set/unset are done as part of dsi_prepare and dsi_unprepare, but in case of deepsleep with display ON, these will not be called. Due to mismatch in parent between clk framework and actual parent, subsequent clk_set_parent will early return without setting the parent. To avoid this condition, do set parent to xo, as part of pm_suspend and restore to link clk source in pm_resume. Change-Id: I626899304580f9d9fbcc92cd8b139cd89cd48999 Signed-off-by: Venkata Prahlad Valluru --- msm/dsi/dsi_display.c | 9 ++++++--- msm/dsi/dsi_display.h | 16 +++++++++++++++ msm/sde/sde_kms.c | 45 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index e6c03fc7f6c0..1d6aa9ba0a66 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -2659,7 +2659,7 @@ error: } #ifdef CONFIG_DEEPSLEEP -static int dsi_display_unset_clk_src(struct dsi_display *display) +int dsi_display_unset_clk_src(struct dsi_display *display) { int rc = 0; int i; @@ -2684,13 +2684,13 @@ static int dsi_display_unset_clk_src(struct dsi_display *display) return 0; } #else -static inline int dsi_display_unset_clk_src(struct dsi_display *display) +inline int dsi_display_unset_clk_src(struct dsi_display *display) { return 0; } #endif -static int dsi_display_set_clk_src(struct dsi_display *display) +int dsi_display_set_clk_src(struct dsi_display *display) { int rc = 0; int i; @@ -4200,6 +4200,9 @@ static int dsi_display_parse_dt(struct dsi_display *display) /* Parse TE data */ dsi_display_parse_te_data(display); + display->needs_clk_src_reset = of_property_read_bool(of_node, + "qcom,needs-clk-src-reset"); + /* Parse all external bridges from port 0 */ display_for_each_ctrl(i, display) { display->ext_bridge[i].node_of = diff --git a/msm/dsi/dsi_display.h b/msm/dsi/dsi_display.h index e2932a0d530d..cac84cd6a8a8 100644 --- a/msm/dsi/dsi_display.h +++ b/msm/dsi/dsi_display.h @@ -214,6 +214,7 @@ struct dsi_display { int disp_te_gpio; bool is_te_irq_enabled; struct completion esd_te_gate; + bool needs_clk_src_reset; u32 ctrl_count; struct dsi_display_ctrl ctrl[MAX_DSI_CTRLS_PER_DISPLAY]; @@ -801,4 +802,19 @@ int dsi_display_dump_clks_state(struct dsi_display *display); */ void dsi_display_dfps_update_parent(struct dsi_display *display); +/** + * dsi_display_unset_clk_src() - reset the clocks source to default + * @display: Handle to display + * + * Return: Zero on Success + */ +int dsi_display_unset_clk_src(struct dsi_display *display); + +/** + * dsi_display_set_clk_src() - set the clocks source + * @display: Handle to display + * + * Return: Zero on Success + */ +int dsi_display_set_clk_src(struct dsi_display *display); #endif /* _DSI_DISPLAY_H_ */ diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index b9609ec6fc0f..9a11a6654f8f 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -3713,6 +3714,44 @@ void sde_kms_display_early_wakeup(struct drm_device *dev, drm_connector_list_iter_end(&conn_iter); } +#ifdef CONFIG_DEEPSLEEP +static int _sde_kms_pm_set_clk_src(struct sde_kms *sde_kms, bool enable) +{ + int i, rc = 0; + void *display; + struct dsi_display *dsi_display; + + if (mem_sleep_current == PM_SUSPEND_MEM) { + SDE_INFO("Deepsleep\n"); + + 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 (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) +{ + return 0; +} +#endif + static void _sde_kms_pm_suspend_idle_helper(struct sde_kms *sde_kms, struct device *dev) { @@ -3904,6 +3943,9 @@ unlock: 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); + /* dump clock state before entering suspend */ if (sde_kms->pm_suspend_clk_dump) _sde_kms_dump_clks_state(sde_kms); @@ -3941,6 +3983,9 @@ retry: goto end; } + /* reset clock source based on PM suspend state */ + _sde_kms_pm_set_clk_src(sde_kms, true); + sde_kms->suspend_block = false; if (sde_kms->suspend_state) {