Browse Source

disp: msm: dsi: add debug support to configure clock gating

Add support to selectively enable clock gating for supported
DSI clocks using a new debugfs node - config_clk_gating. This
new node would be created for every display node. See below
for usage examples:

To enable clock gating only for BYTE clock:
echo 1 > /sys/kernel/debug/<display_name>/config_clock_gating

To enable clock gating only for PIXEL clock:
echo 2 > /sys/kernel/debug/<display_name>/config_clock_gating

To enable clock gating only for PHY clock:
echo 4 > /sys/kernel/debug/<display_name>/config_clock_gating

To enable clock gating only for all clock:
echo 7 > /sys/kernel/debug/<display_name>/config_clock_gating

To disable clock gating for all clocks:
echo 8 > /sys/kernel/debug/<display_name>/config_clock_gating

To go back to default setting:
echo 0 > /sys/kernel/debug/<display_name>/config_clock_gating

Change-Id: I83713d86eb1b9675d40d51fc20de81cca0aeb1c0
Signed-off-by: Aravind Venkateswaran <[email protected]>
Aravind Venkateswaran 6 years ago
parent
commit
dc65566994
3 changed files with 40 additions and 7 deletions
  1. 4 0
      msm/dsi/dsi_defs.h
  2. 34 7
      msm/dsi/dsi_display.c
  3. 2 0
      msm/dsi/dsi_display.h

+ 4 - 0
msm/dsi/dsi_defs.h

@@ -288,11 +288,15 @@ enum dsi_cmd_set_state {
  * @PIXEL_CLK:  DSI pixel clock.
  * @PIXEL_CLK:  DSI pixel clock.
  * @BYTE_CLK:   DSI byte clock.
  * @BYTE_CLK:   DSI byte clock.
  * @DSI_PHY:    DSI PHY.
  * @DSI_PHY:    DSI PHY.
+ * @DSI_CLK_ALL: All available DSI clocks
+ * @DSI_CLK_NONE: None of the clocks should be gated
  */
  */
 enum dsi_clk_gate_type {
 enum dsi_clk_gate_type {
 	PIXEL_CLK = 1,
 	PIXEL_CLK = 1,
 	BYTE_CLK = 2,
 	BYTE_CLK = 2,
 	DSI_PHY = 4,
 	DSI_PHY = 4,
+	DSI_CLK_ALL = (PIXEL_CLK | BYTE_CLK | DSI_PHY),
+	DSI_CLK_NONE = 8,
 };
 };
 
 
 /**
 /**

+ 34 - 7
msm/dsi/dsi_display.c

@@ -70,6 +70,8 @@ static int dsi_display_config_clk_gating(struct dsi_display *display,
 {
 {
 	int rc = 0, i = 0;
 	int rc = 0, i = 0;
 	struct dsi_display_ctrl *mctrl, *ctrl;
 	struct dsi_display_ctrl *mctrl, *ctrl;
+	enum dsi_clk_gate_type clk_selection;
+	enum dsi_clk_gate_type const default_clk_select = PIXEL_CLK | DSI_PHY;
 
 
 	if (!display) {
 	if (!display) {
 		pr_err("Invalid params\n");
 		pr_err("Invalid params\n");
@@ -82,12 +84,28 @@ static int dsi_display_config_clk_gating(struct dsi_display *display,
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	rc = dsi_ctrl_config_clk_gating(mctrl->ctrl, enable, PIXEL_CLK |
-							DSI_PHY);
+	clk_selection = display->clk_gating_config;
+
+	if (!enable) {
+		/* for disable path, make sure to disable all clk gating */
+		clk_selection = DSI_CLK_ALL;
+	} else if (!clk_selection || clk_selection > DSI_CLK_NONE) {
+		/* Default selection, no overrides */
+		clk_selection = default_clk_select;
+	} else if (clk_selection == DSI_CLK_NONE) {
+		clk_selection = 0;
+	}
+
+	pr_debug("%s clock gating Byte:%s Pixel:%s PHY:%s\n",
+		enable ? "Enabling" : "Disabling",
+		clk_selection & BYTE_CLK ? "yes" : "no",
+		clk_selection & PIXEL_CLK ? "yes" : "no",
+		clk_selection & DSI_PHY ? "yes" : "no");
+	rc = dsi_ctrl_config_clk_gating(mctrl->ctrl, enable, clk_selection);
 	if (rc) {
 	if (rc) {
-		pr_err("[%s] failed to %s clk gating, rc=%d\n",
+		pr_err("[%s] failed to %s clk gating for clocks %d, rc=%d\n",
 				display->name, enable ? "enable" : "disable",
 				display->name, enable ? "enable" : "disable",
-				rc);
+				clk_selection, rc);
 		return rc;
 		return rc;
 	}
 	}
 
 
@@ -99,11 +117,13 @@ static int dsi_display_config_clk_gating(struct dsi_display *display,
 		 * In Split DSI usecase we should not enable clock gating on
 		 * In Split DSI usecase we should not enable clock gating on
 		 * DSI PHY1 to ensure no display atrifacts are seen.
 		 * DSI PHY1 to ensure no display atrifacts are seen.
 		 */
 		 */
-		rc = dsi_ctrl_config_clk_gating(ctrl->ctrl, enable, PIXEL_CLK);
+		clk_selection &= ~DSI_PHY;
+		rc = dsi_ctrl_config_clk_gating(ctrl->ctrl, enable,
+				clk_selection);
 		if (rc) {
 		if (rc) {
-			pr_err("[%s] failed to %s pixel clk gating, rc=%d\n",
+			pr_err("[%s] failed to %s clk gating for clocks %d, rc=%d\n",
 				display->name, enable ? "enable" : "disable",
 				display->name, enable ? "enable" : "disable",
-				rc);
+				clk_selection, rc);
 			return rc;
 			return rc;
 		}
 		}
 	}
 	}
@@ -1592,6 +1612,13 @@ static int dsi_display_debugfs_init(struct dsi_display *display)
 		goto error_remove_dir;
 		goto error_remove_dir;
 	}
 	}
 
 
+	if (!debugfs_create_u32("clk_gating_config", 0600, dir,
+			&display->clk_gating_config)) {
+		pr_err("[%s] debugfs create clk gating config failed\n",
+		       display->name);
+		goto error_remove_dir;
+	}
+
 	display->root = dir;
 	display->root = dir;
 	dsi_parser_dbg_init(display->parser, dir);
 	dsi_parser_dbg_init(display->parser, dir);
 
 

+ 2 - 0
msm/dsi/dsi_display.h

@@ -181,6 +181,7 @@ struct dsi_display_ext_bridge {
  * @misr_frame_count  Number of frames to accumulate the MISR value
  * @misr_frame_count  Number of frames to accumulate the MISR value
  * @esd_trigger       field indicating ESD trigger through debugfs
  * @esd_trigger       field indicating ESD trigger through debugfs
  * @te_source         vsync source pin information
  * @te_source         vsync source pin information
+ * @clk_gating_config Clocks for which clock gating needs to be enabled
  */
  */
 struct dsi_display {
 struct dsi_display {
 	struct platform_device *pdev;
 	struct platform_device *pdev;
@@ -264,6 +265,7 @@ struct dsi_display {
 	struct dsi_display_boot_param *boot_disp;
 	struct dsi_display_boot_param *boot_disp;
 
 
 	u32 te_source;
 	u32 te_source;
+	u32 clk_gating_config;
 };
 };
 
 
 int dsi_display_dev_probe(struct platform_device *pdev);
 int dsi_display_dev_probe(struct platform_device *pdev);