From 307aea3dc10c85f4d9b1dda25991a93c2f703cfd Mon Sep 17 00:00:00 2001 From: Anand Tarakh Date: Thu, 23 Feb 2023 15:33:21 +0530 Subject: [PATCH] disp: msm: dsi: add mutex lock before link clock frequency update Acquire mngr clk_mutex before updating link clock frequencies. Failing this may lead to race around condition while setting the link clock frequency rates. Make sure byteclk and pclk rates of PLL are configured according to clock manager and not the controller. Change-Id: I2cd26e659ce166d5bc55eb6c060672eeee192bea Signed-off-by: Anand Tarakh --- msm/dsi/dsi_clk.h | 24 +++++++++++++-- msm/dsi/dsi_clk_manager.c | 52 +++++++++++++++++++++++++++++++- msm/dsi/dsi_ctrl.c | 7 +---- msm/dsi/dsi_display.c | 62 ++++++++++++++++++++++++++++++++------- 4 files changed, 126 insertions(+), 19 deletions(-) diff --git a/msm/dsi/dsi_clk.h b/msm/dsi/dsi_clk.h index c450b30c86..443d5d063f 100644 --- a/msm/dsi/dsi_clk.h +++ b/msm/dsi/dsi_clk.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _DSI_CLK_H_ @@ -304,6 +304,15 @@ int dsi_display_clk_ctrl(void *handle, u32 clk_type, u32 clk_state); int dsi_clk_set_link_frequencies(void *client, struct link_clk_freq freq, u32 index); +/** + * dsi_clk_get_link_frequencies() - get link clk frequencies + * @link_freq: Structure to get link clock frequencies + * @client: DSI clock client pointer. + * @index: Index of the DSI controller. + * + * return: error code in case of failure or 0 for success. + */ +int dsi_clk_get_link_frequencies(struct link_clk_freq *link_freq, void *client, u32 index); /** * dsi_clk_set_pixel_clk_rate() - set frequency for pixel_clk @@ -314,7 +323,6 @@ int dsi_clk_set_link_frequencies(void *client, struct link_clk_freq freq, */ int dsi_clk_set_pixel_clk_rate(void *client, u64 pixel_clk, u32 index); - /** * dsi_clk_set_byte_clk_rate() - set frequency for byte clock * @client: DSI clock client pointer. @@ -354,4 +362,16 @@ void dsi_clk_disable_unprepare(struct dsi_clk_link_set *clk); */ int dsi_display_dump_clk_handle_state(void *client); +/** + * dsi_clk_acquire_mngr_lock() - acquire clk manager mutex lock + * @client: DSI clock client pointer. + */ +void dsi_clk_acquire_mngr_lock(void *client); + +/** + * dsi_clk_release_mngr_lock() - release clk manager mutex lock + * @client: DSI clock client pointer. + */ +void dsi_clk_release_mngr_lock(void *client); + #endif /* _DSI_CLK_H_ */ diff --git a/msm/dsi/dsi_clk_manager.c b/msm/dsi/dsi_clk_manager.c index 3da5dbaa33..a0e7d28ae9 100644 --- a/msm/dsi/dsi_clk_manager.c +++ b/msm/dsi/dsi_clk_manager.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -106,6 +106,30 @@ int dsi_clk_set_link_frequencies(void *client, struct link_clk_freq freq, return rc; } +/** + * dsi_clk_get_link_frequencies() - get link clk frequencies + * @link_freq: Structure to get link clock frequencies + * @client: DSI clock client pointer. + * @index: Index of the DSI controller. + * + * return: error code in case of failure or 0 for success. + */ +int dsi_clk_get_link_frequencies(struct link_clk_freq *link_freq, void *client, u32 index) +{ + struct dsi_clk_client_info *c = client; + struct dsi_clk_mngr *mngr; + + if (!client || !link_freq) { + DSI_ERR("invalid params\n"); + return -EINVAL; + } + + mngr = c->mngr; + memcpy(link_freq, &mngr->link_clks[index].freq, sizeof(struct link_clk_freq)); + + return 0; +} + /** * dsi_clk_set_pixel_clk_rate() - set frequency for pixel clock * @clks: DSI link clock information. @@ -1505,3 +1529,29 @@ int dsi_display_clk_mngr_deregister(void *clk_mngr) kfree(mngr); return rc; } + +/** + * dsi_clk_acquire_mngr_lock() - acquire clk manager mutex lock + * @client: DSI clock client pointer. + */ +void dsi_clk_acquire_mngr_lock(void *client) +{ + struct dsi_clk_mngr *mngr; + struct dsi_clk_client_info *c = client; + + mngr = c->mngr; + mutex_lock(&mngr->clk_mutex); +} + +/** + * dsi_clk_release_mngr_lock() - release clk manager mutex lock + * @client: DSI clock client pointer. + */ +void dsi_clk_release_mngr_lock(void *client) +{ + struct dsi_clk_mngr *mngr; + struct dsi_clk_client_info *c = client; + + mngr = c->mngr; + mutex_unlock(&mngr->clk_mutex); +} diff --git a/msm/dsi/dsi_ctrl.c b/msm/dsi/dsi_ctrl.c index 35e90f1e3b..440a682a97 100644 --- a/msm/dsi/dsi_ctrl.c +++ b/msm/dsi/dsi_ctrl.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ @@ -1114,11 +1114,6 @@ static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl, dsi_ctrl->clk_freq.pix_clk_rate = pclk_rate; dsi_ctrl->clk_freq.esc_clk_rate = config->esc_clk_rate_hz; - rc = dsi_clk_set_link_frequencies(clk_handle, dsi_ctrl->clk_freq, - dsi_ctrl->cell_index); - if (rc) - DSI_CTRL_ERR(dsi_ctrl, "Failed to update link frequencies\n"); - return rc; } diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index 84480e3f52..b8650e3522 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -2840,7 +2840,7 @@ int dsi_display_phy_configure(void *priv, bool commit) struct dsi_display *display = priv; struct dsi_display_ctrl *m_ctrl; struct dsi_pll_resource *pll_res; - struct dsi_ctrl *ctrl; + struct link_clk_freq link_freq; if (!display) { DSI_ERR("invalid arguments\n"); @@ -2862,9 +2862,15 @@ int dsi_display_phy_configure(void *priv, bool commit) return -EINVAL; } - ctrl = m_ctrl->ctrl; - pll_res->byteclk_rate = ctrl->clk_freq.byte_clk_rate; - pll_res->pclk_rate = ctrl->clk_freq.pix_clk_rate; + rc = dsi_clk_get_link_frequencies(&link_freq, display->dsi_clk_handle, + display->clk_master_idx); + if (rc) { + DSI_ERR("Failed to get link frequencies\n"); + return rc; + } + + pll_res->byteclk_rate = link_freq.byte_clk_rate; + pll_res->pclk_rate = link_freq.pix_clk_rate; rc = dsi_phy_configure(m_ctrl->phy, commit); @@ -4481,6 +4487,26 @@ void dsi_display_update_byte_intf_div(struct dsi_display *display) config->byte_intf_clk_div = 2; } +static int dsi_display_set_link_frequencies(struct dsi_display *display) +{ + int rc = 0, i = 0; + + dsi_clk_acquire_mngr_lock(display->dsi_clk_handle); + display_for_each_ctrl(i, display) { + struct dsi_display_ctrl *ctrl = &display->ctrl[i]; + + rc = dsi_clk_set_link_frequencies(display->dsi_clk_handle, ctrl->ctrl->clk_freq, i); + if (rc) { + DSI_ERR("Failed to update link frequencies of ctrl_%d, rc=%d\n", i, rc); + dsi_clk_release_mngr_lock(display->dsi_clk_handle); + return rc; + } + } + dsi_clk_release_mngr_lock(display->dsi_clk_handle); + + return rc; +} + static int dsi_display_update_dsi_bitrate(struct dsi_display *display, u32 bit_clk_rate) { @@ -4563,12 +4589,6 @@ static int dsi_display_update_dsi_bitrate(struct dsi_display *display, ctrl->clk_freq.byte_clk_rate = byte_clk_rate; ctrl->clk_freq.byte_intf_clk_rate = byte_intf_clk_rate; ctrl->clk_freq.pix_clk_rate = pclk_rate; - rc = dsi_clk_set_link_frequencies(display->dsi_clk_handle, - ctrl->clk_freq, ctrl->cell_index); - if (rc) { - DSI_ERR("Failed to update link frequencies\n"); - goto error; - } ctrl->host_config.bit_clk_rate_hz = bit_clk_rate; error: @@ -4579,6 +4599,12 @@ error: return rc; } + rc = dsi_display_set_link_frequencies(display); + if (rc) { + DSI_ERR("Failed to set display link frequencies\n"); + return rc; + } + return 0; } @@ -5233,6 +5259,15 @@ static int dsi_display_set_mode_sub(struct dsi_display *display, } } + if (!(mode->dsi_mode_flags & (DSI_MODE_FLAG_SEAMLESS | DSI_MODE_FLAG_VRR | + DSI_MODE_FLAG_DYN_CLK))) { + rc = dsi_display_set_link_frequencies(display); + if (rc) { + DSI_ERR("Failed to set display link frequencies\n"); + goto error; + } + } + if ((mode->dsi_mode_flags & DSI_MODE_FLAG_DMS) && (display->panel->panel_mode == DSI_OP_CMD_MODE)) { u64 cur_bitclk = display->panel->cur_mode->timing.clk_rate_hz; @@ -7461,6 +7496,13 @@ int dsi_display_update_transfer_time(void *display, u32 transfer_time) return rc; } } + + rc = dsi_display_set_link_frequencies(disp); + if (rc) { + DSI_ERR("Failed to set display link frequencies\n"); + return rc; + } + atomic_set(&disp->clkrate_change_pending, 1); return 0;