瀏覽代碼

disp: msm: dsi: set source to xo while turning off PLL

HW recommendation is to park the DSI byte clock and pixel clock at XO
before turning them off. The change parses XO from the DT and sets the
clock source as XO while turning off the PLL.

Change-Id: I788951d6341149300e80e8db4a5a3fd2c4eb3e03
Signed-off-by: Satya Rama Aditya Pinapala <[email protected]>
Satya Rama Aditya Pinapala 4 年之前
父節點
當前提交
3ff78e8f7d
共有 3 個文件被更改,包括 59 次插入58 次删除
  1. 9 0
      msm/dsi/dsi_ctrl.c
  2. 2 0
      msm/dsi/dsi_ctrl.h
  3. 48 58
      msm/dsi/dsi_display.c

+ 9 - 0
msm/dsi/dsi_ctrl.c

@@ -719,6 +719,7 @@ static int dsi_ctrl_clocks_init(struct platform_device *pdev,
 	struct dsi_link_lp_clk_info *lp_link = &ctrl->clk_info.lp_link_clks;
 	struct dsi_link_hs_clk_info *hs_link = &ctrl->clk_info.hs_link_clks;
 	struct dsi_clk_link_set *rcg = &ctrl->clk_info.rcg_clks;
+	struct dsi_clk_link_set *xo = &ctrl->clk_info.xo_clk;
 
 	core->mdp_core_clk = devm_clk_get(&pdev->dev, "mdp_core_clk");
 	if (IS_ERR(core->mdp_core_clk)) {
@@ -792,6 +793,14 @@ static int dsi_ctrl_clocks_init(struct platform_device *pdev,
 		goto fail;
 	}
 
+	xo->byte_clk = devm_clk_get(&pdev->dev, "xo");
+	if (IS_ERR(xo->byte_clk)) {
+		xo->byte_clk = NULL;
+		DSI_CTRL_DEBUG(ctrl, "failed to get xo clk, rc=%d\n", rc);
+	}
+
+	xo->pixel_clk = xo->byte_clk;
+
 	return 0;
 fail:
 	dsi_ctrl_clocks_deinit(ctrl);

+ 2 - 0
msm/dsi/dsi_ctrl.h

@@ -119,6 +119,7 @@ struct dsi_ctrl_power_info {
  *			output of the PLL is set as parent for these root
  *			clocks. These clocks are specific to controller
  *			instance.
+ * @xo_clk:             XO clocks used to park the DSI PLL before turning off.
  * @mux_clks:           Mux clocks used for Dynamic refresh feature.
  * @ext_clks:           External byte/pixel clocks from the MMSS block. These
  *			clocks are set as parent to rcg clocks.
@@ -131,6 +132,7 @@ struct dsi_ctrl_clk_info {
 	struct dsi_link_hs_clk_info hs_link_clks;
 	struct dsi_link_lp_clk_info lp_link_clks;
 	struct dsi_clk_link_set rcg_clks;
+	struct dsi_clk_link_set xo_clk;
 
 	/* Clocks set by DSI Manager */
 	struct dsi_clk_link_set mux_clks;

+ 48 - 58
msm/dsi/dsi_display.c

@@ -2647,6 +2647,52 @@ error:
 	return rc;
 }
 
+static int dsi_display_set_clk_src(struct dsi_display *display, bool set_xo)
+{
+	int rc = 0;
+	int i;
+	struct dsi_display_ctrl *m_ctrl, *ctrl;
+	struct dsi_ctrl_clk_info *info;
+
+	if (display->trusted_vm_env)
+		return 0;
+	/*
+	 * In case of split DSI usecases, the clock for master controller should
+	 * be enabled before the other controller. Master controller in the
+	 * clock context refers to the controller that sources the clock. While turning off the
+	 * clocks, the source is set to xo.
+	 */
+	m_ctrl = &display->ctrl[display->clk_master_idx];
+	info = &m_ctrl->ctrl->clk_info;
+
+	if (!set_xo)
+		rc = dsi_ctrl_set_clock_source(m_ctrl->ctrl, &display->clock_info.pll_clks);
+	else if ((info->xo_clk.byte_clk) && (info->xo_clk.pixel_clk))
+		rc = dsi_ctrl_set_clock_source(m_ctrl->ctrl, &info->xo_clk);
+	if (rc) {
+		DSI_ERR("[%s] failed to set source clocks for master, rc=%d\n", display->name, rc);
+		return rc;
+	}
+
+	/* Set source for the rest of the controllers */
+	display_for_each_ctrl(i, display) {
+		ctrl = &display->ctrl[i];
+		if (!ctrl->ctrl || (ctrl == m_ctrl))
+			continue;
+
+		info = &ctrl->ctrl->clk_info;
+		if (!set_xo)
+			rc = dsi_ctrl_set_clock_source(ctrl->ctrl, &display->clock_info.pll_clks);
+		else if ((info->xo_clk.byte_clk) && (info->xo_clk.pixel_clk))
+			rc = dsi_ctrl_set_clock_source(ctrl->ctrl, &info->xo_clk);
+		if (rc) {
+			DSI_ERR("[%s] failed to set source clocks, rc=%d\n", display->name, rc);
+			return rc;
+		}
+	}
+	return 0;
+}
+
 int dsi_display_phy_pll_toggle(void *priv, bool prepare)
 {
 	int rc = 0;
@@ -2658,6 +2704,8 @@ int dsi_display_phy_pll_toggle(void *priv, bool prepare)
 		return -EINVAL;
 	}
 
+	rc = dsi_display_set_clk_src(display, !prepare);
+
 	m_ctrl = &display->ctrl[display->clk_master_idx];
 	if (!m_ctrl->phy) {
 		DSI_ERR("[%s] PHY not found\n", display->name);
@@ -2703,44 +2751,6 @@ int dsi_display_phy_configure(void *priv, bool commit)
 	return rc;
 }
 
-static int dsi_display_set_clk_src(struct dsi_display *display)
-{
-	int rc = 0;
-	int i;
-	struct dsi_display_ctrl *m_ctrl, *ctrl;
-
-	/*
-	 * In case of split DSI usecases, the clock for master controller should
-	 * be enabled before the other controller. Master controller in the
-	 * clock context refers to the controller that sources the clock.
-	 */
-	m_ctrl = &display->ctrl[display->clk_master_idx];
-
-	rc = dsi_ctrl_set_clock_source(m_ctrl->ctrl,
-			&display->clock_info.pll_clks);
-	if (rc) {
-		DSI_ERR("[%s] failed to set source clocks for master, rc=%d\n",
-			   display->name, rc);
-		return rc;
-	}
-
-	/* Turn on rest of the controllers */
-	display_for_each_ctrl(i, display) {
-		ctrl = &display->ctrl[i];
-		if (!ctrl->ctrl || (ctrl == m_ctrl))
-			continue;
-
-		rc = dsi_ctrl_set_clock_source(ctrl->ctrl,
-			   &display->clock_info.pll_clks);
-		if (rc) {
-			DSI_ERR("[%s] failed to set source clocks, rc=%d\n",
-				   display->name, rc);
-			return rc;
-		}
-	}
-	return 0;
-}
-
 static int dsi_display_phy_reset_config(struct dsi_display *display,
 		bool enable)
 {
@@ -7241,16 +7251,6 @@ static int dsi_display_pre_switch(struct dsi_display *display)
 		goto error_ctrl_clk_off;
 	}
 
-	if (!display->trusted_vm_env) {
-		rc = dsi_display_set_clk_src(display);
-		if (rc) {
-			DSI_ERR(
-			"[%s] failed to set DSI link clock source, rc=%d\n",
-			display->name, rc);
-			goto error_ctrl_deinit;
-		}
-	}
-
 	rc = dsi_display_clk_ctrl(display->dsi_clk_handle,
 			DSI_LINK_CLK, DSI_CLK_ON);
 	if (rc) {
@@ -7650,16 +7650,6 @@ int dsi_display_prepare(struct dsi_display *display)
 		}
 	}
 
-	if (!display->trusted_vm_env) {
-		rc = dsi_display_set_clk_src(display);
-		if (rc) {
-			DSI_ERR(
-			"[%s] failed to set DSI link clock source, rc=%d\n",
-				display->name, rc);
-			goto error_phy_disable;
-		}
-	}
-
 	rc = dsi_display_ctrl_init(display);
 	if (rc) {
 		DSI_ERR("[%s] failed to setup DSI controller, rc=%d\n",