summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSai Srujana Oruganti <quic_osaisruj@quicinc.com>2022-11-08 11:49:14 +0530
committerSai Srujana Oruganti <quic_osaisruj@quicinc.com>2022-12-13 17:09:08 +0530
commit71b20e8919872bce4ef64828337794b47081053f (patch)
treeb79ecda6f005b3741eaa789522042bde91ffd843
parent946a38599c2a9ae61be0ad39def8dfb44311fd5b (diff)
downloaddisplay-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.c5
-rw-r--r--msm/dsi/dsi_display.h10
-rw-r--r--msm/sde/sde_kms.c48
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) {