diff options
author | Sai Srujana Oruganti <quic_osaisruj@quicinc.com> | 2022-11-08 11:49:14 +0530 |
---|---|---|
committer | Sai Srujana Oruganti <quic_osaisruj@quicinc.com> | 2022-12-13 17:09:08 +0530 |
commit | 71b20e8919872bce4ef64828337794b47081053f (patch) | |
tree | b79ecda6f005b3741eaa789522042bde91ffd843 | |
parent | 946a38599c2a9ae61be0ad39def8dfb44311fd5b (diff) | |
download | display-drivers-71b20e8919872bce4ef64828337794b47081053f.tar.gz |
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: Sai Srujana Oruganti <quic_osaisruj@quicinc.com>
-rw-r--r-- | msm/dsi/dsi_display.c | 5 | ||||
-rw-r--r-- | msm/dsi/dsi_display.h | 10 | ||||
-rw-r--r-- | msm/sde/sde_kms.c | 48 |
3 files changed, 62 insertions, 1 deletions
diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index 00000955..9aabafff 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -2713,7 +2713,7 @@ error: return rc; } -static int dsi_display_set_clk_src(struct dsi_display *display, bool set_xo) +int dsi_display_set_clk_src(struct dsi_display *display, bool set_xo) { int rc = 0; int i; @@ -4192,6 +4192,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 37b9481f..8841a4de 100644 --- a/msm/dsi/dsi_display.h +++ b/msm/dsi/dsi_display.h @@ -149,6 +149,7 @@ struct dsi_display_ext_bridge { * @disp_te_gpio: GPIO for panel TE interrupt. * @is_te_irq_enabled:bool to specify whether TE interrupt is enabled. * @esd_te_gate: completion gate to signal TE interrupt. + * @needs_clk_src_reset: Is clock source reset needed. * @ctrl_count: Number of DSI interfaces required by panel. * @ctrl: Controller information for DSI display. * @panel: Handle to DSI panel. @@ -213,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]; @@ -842,4 +844,12 @@ bool dsi_display_mode_match(const struct dsi_display_mode *mode1, */ int dsi_display_update_transfer_time(void *display, u32 transfer_time); +/** + * dsi_display_set_clk_src() - set the clocks source + * @display: handle to display + * @set_xo: check clk source is xo clk or not + * Return: Zero on Success + */ +int dsi_display_set_clk_src(struct dsi_display *display, bool set_xo); + #endif /* _DSI_DISPLAY_H_ */ diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 2271360e..a9063f35 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -3915,6 +3915,48 @@ static int sde_kms_trigger_null_flush(struct msm_kms *kms) return rc; } +#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 (!pm_suspend_via_firmware()) + return 0; + else { + 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, false); + else + rc = dsi_display_set_clk_src(dsi_display, true); + + 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) { @@ -4124,6 +4166,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); @@ -4162,6 +4207,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) { |