From 74924557842e3e4f64e34f59d57ec118be3d7086 Mon Sep 17 00:00:00 2001 From: Venkata Prahlad Valluru Date: Mon, 24 Jan 2022 12:35:40 +0530 Subject: [PATCH] disp: msm: sde: set parent to xo for link clks while enterting suspend Clk framework will cache current parent and skip subsequent clk_set_parent calls if same parent is set. In case of deepsleep, clk's parent is reset to xo clks for link clocks but framework will still see cached parent and skip set_parent call. To avoid this state, set parent to xo clock for link clocks, before we enter suspend, so that framework and hw state are in correct state, when we exit from deepsleep. Change-Id: Ic7f70ec13497c70a8b4351ebfa49c0db98fc63ab Signed-off-by: Venkata Prahlad Valluru --- msm/dsi/dsi_clk_manager.c | 11 +++++++ msm/dsi/dsi_display.c | 60 +++++++++++++++++++++++++++++++++++++++ msm/dsi/dsi_display.h | 2 ++ 3 files changed, 73 insertions(+) diff --git a/msm/dsi/dsi_clk_manager.c b/msm/dsi/dsi_clk_manager.c index b8b5bec682c4..a213c6959b38 100644 --- a/msm/dsi/dsi_clk_manager.c +++ b/msm/dsi/dsi_clk_manager.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ @@ -172,6 +173,16 @@ int dsi_clk_update_parent(struct dsi_clk_link_set *parent, { int rc = 0; + if (!parent->byte_clk || !parent->pixel_clk) { + DSI_ERR("Invalid parent\n"); + return -EINVAL; + } + + if (!child->byte_clk || !child->pixel_clk) { + DSI_ERR("Invalid child\n"); + return -EINVAL; + } + rc = clk_set_parent(child->byte_clk, parent->byte_clk); if (rc) { DSI_ERR("failed to set byte clk parent\n"); diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index 2330d73f5c0f..b72dabdc7b59 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ @@ -2657,6 +2658,38 @@ error: return rc; } +#ifdef CONFIG_DEEPSLEEP +static int dsi_display_unset_clk_src(struct dsi_display *display) +{ + int rc = 0; + int i; + struct dsi_display_ctrl *ctrl; + + DSI_DEBUG("[%s] unset source clocks\n", display->name); + + display_for_each_ctrl(i, display) { + ctrl = &display->ctrl[i]; + if (!ctrl->ctrl) + continue; + + /* set ctrl clocks to xo source */ + rc = dsi_ctrl_set_clock_source(ctrl->ctrl, + &display->clock_info.xo_clks); + if (rc) { + DSI_ERR("[%s] failed to set source clocks, rc=%d\n", + display->name, rc); + return rc; + } + } + return 0; +} +#else +static 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 rc = 0; @@ -3442,6 +3475,7 @@ static int dsi_display_clocks_init(struct dsi_display *display) { int i, rc = 0, num_clk = 0; const char *clk_name; + const char *xo_byte = "xo_byte", *xo_pixel = "xo_pixel"; const char *src_byte = "src_byte", *src_pixel = "src_pixel"; const char *mux_byte = "mux_byte", *mux_pixel = "mux_pixel"; const char *cphy_byte = "cphy_byte", *cphy_pixel = "cphy_pixel"; @@ -3449,6 +3483,7 @@ static int dsi_display_clocks_init(struct dsi_display *display) const char *shadow_cphybyte = "shadow_cphybyte", *shadow_cphypixel = "shadow_cphypixel"; struct clk *dsi_clk; + struct dsi_clk_link_set *xo = &display->clock_info.xo_clks; struct dsi_clk_link_set *src = &display->clock_info.src_clks; struct dsi_clk_link_set *mux = &display->clock_info.mux_clks; struct dsi_clk_link_set *cphy = &display->clock_info.cphy_clks; @@ -3479,6 +3514,15 @@ static int dsi_display_clocks_init(struct dsi_display *display) DSI_ERR("failed to get %s, rc=%d\n", clk_name, rc); + if (dsi_display_check_prefix(xo_byte, clk_name)) { + xo->byte_clk = NULL; + goto error; + } + if (dsi_display_check_prefix(xo_pixel, clk_name)) { + xo->pixel_clk = NULL; + goto error; + } + if (dsi_display_check_prefix(mux_byte, clk_name)) { mux->byte_clk = NULL; goto error; @@ -3524,6 +3568,16 @@ static int dsi_display_clocks_init(struct dsi_display *display) } } + if (dsi_display_check_prefix(xo_byte, clk_name)) { + xo->byte_clk = dsi_clk; + continue; + } + + if (dsi_display_check_prefix(xo_pixel, clk_name)) { + xo->pixel_clk = dsi_clk; + continue; + } + if (dsi_display_check_prefix(src_byte, clk_name)) { src->byte_clk = dsi_clk; continue; @@ -8586,6 +8640,12 @@ int dsi_display_unprepare(struct dsi_display *display) DSI_ERR("[%s] failed to disable Link clocks, rc=%d\n", display->name, rc); + /* set to dsi clocks to xo clocks */ + rc = dsi_display_unset_clk_src(display); + if (rc) + DSI_ERR("[%s] failed to unset clocks, rc=%d\n", + display->name, rc); + rc = dsi_display_ctrl_deinit(display); if (rc) DSI_ERR("[%s] failed to deinit controller, rc=%d\n", diff --git a/msm/dsi/dsi_display.h b/msm/dsi/dsi_display.h index 2dc7bc7dd137..e2932a0d530d 100644 --- a/msm/dsi/dsi_display.h +++ b/msm/dsi/dsi_display.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ @@ -110,6 +111,7 @@ struct dsi_display_boot_param { * @shadow_cphy_clks: Used for C-phy clock switch. */ struct dsi_display_clk_info { + struct dsi_clk_link_set xo_clks; struct dsi_clk_link_set src_clks; struct dsi_clk_link_set mux_clks; struct dsi_clk_link_set cphy_clks;