mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-07 20:33:58 -04:00
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 <quic_vvalluru@quicinc.com>
This commit is contained in:
parent
1438587222
commit
9a6ed8620e
3 changed files with 67 additions and 3 deletions
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/of_irq.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <drm/drm_atomic_uapi.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue