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 <aravindh@codeaurora.org>
This commit is contained in:
@@ -288,11 +288,15 @@ enum dsi_cmd_set_state {
|
||||
* @PIXEL_CLK: DSI pixel clock.
|
||||
* @BYTE_CLK: DSI byte clock.
|
||||
* @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 {
|
||||
PIXEL_CLK = 1,
|
||||
BYTE_CLK = 2,
|
||||
DSI_PHY = 4,
|
||||
DSI_CLK_ALL = (PIXEL_CLK | BYTE_CLK | DSI_PHY),
|
||||
DSI_CLK_NONE = 8,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -70,6 +70,8 @@ static int dsi_display_config_clk_gating(struct dsi_display *display,
|
||||
{
|
||||
int rc = 0, i = 0;
|
||||
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) {
|
||||
pr_err("Invalid params\n");
|
||||
@@ -82,12 +84,28 @@ static int dsi_display_config_clk_gating(struct dsi_display *display,
|
||||
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) {
|
||||
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",
|
||||
rc);
|
||||
clk_selection, 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
|
||||
* 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) {
|
||||
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",
|
||||
rc);
|
||||
clk_selection, rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
@@ -1592,6 +1612,13 @@ static int dsi_display_debugfs_init(struct dsi_display *display)
|
||||
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;
|
||||
dsi_parser_dbg_init(display->parser, dir);
|
||||
|
||||
|
@@ -181,6 +181,7 @@ struct dsi_display_ext_bridge {
|
||||
* @misr_frame_count Number of frames to accumulate the MISR value
|
||||
* @esd_trigger field indicating ESD trigger through debugfs
|
||||
* @te_source vsync source pin information
|
||||
* @clk_gating_config Clocks for which clock gating needs to be enabled
|
||||
*/
|
||||
struct dsi_display {
|
||||
struct platform_device *pdev;
|
||||
@@ -264,6 +265,7 @@ struct dsi_display {
|
||||
struct dsi_display_boot_param *boot_disp;
|
||||
|
||||
u32 te_source;
|
||||
u32 clk_gating_config;
|
||||
};
|
||||
|
||||
int dsi_display_dev_probe(struct platform_device *pdev);
|
||||
|
Reference in New Issue
Block a user