|
@@ -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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1596,6 +1616,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);
|
|
|
|
|