瀏覽代碼

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 <[email protected]>
Anand Tarakh 2 年之前
父節點
當前提交
307aea3dc1
共有 4 個文件被更改,包括 126 次插入19 次删除
  1. 22 2
      msm/dsi/dsi_clk.h
  2. 51 1
      msm/dsi/dsi_clk_manager.c
  3. 1 6
      msm/dsi/dsi_ctrl.c
  4. 52 10
      msm/dsi/dsi_display.c

+ 22 - 2
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_ */

+ 51 - 1
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 <linux/of.h>
@@ -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);
+}

+ 1 - 6
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;
 }
 

+ 52 - 10
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;