disp: msm: dsi: add support for dsi dynamic clock switch

This change adds support for dynamic switching of dsi clocks
to avoid RF interference issues. Also with dynamic dsi clock
switch feature coming into picture, now populate the supported
refresh rate as list instead of providing a range. Modify the
logic to enumerate all the modes in dsi driver, taking dynamic
bit clocks, resolutions and refresh rates into account.

Change-Id: I5b6e62bc935cf2234bdd96fcb3c7537b4e735fff
Signed-off-by: Sandeep Panda <spanda@codeaurora.org>
Signed-off-by: Ritesh Kumar <riteshk@codeaurora.org>
Signed-off-by: Yujun Zhang <yujunzhang@codeaurora.org>
This commit is contained in:
Yujun Zhang
2018-10-25 15:49:16 +05:30
bovenliggende 6ec69969e2
commit b0f2e2222e
27 gewijzigde bestanden met toevoegingen van 1331 en 446 verwijderingen

Bestand weergeven

@@ -1155,6 +1155,48 @@ static int dsi_panel_parse_qsync_caps(struct dsi_panel *panel,
return rc;
}
static int dsi_panel_parse_dyn_clk_caps(struct dsi_panel *panel)
{
int rc = 0;
bool supported = false;
struct dsi_dyn_clk_caps *dyn_clk_caps = &panel->dyn_clk_caps;
struct dsi_parser_utils *utils = &panel->utils;
const char *name = panel->name;
supported = utils->read_bool(utils->data, "qcom,dsi-dyn-clk-enable");
if (!supported) {
dyn_clk_caps->dyn_clk_support = false;
return rc;
}
dyn_clk_caps->bit_clk_list_len = utils->count_u32_elems(utils->data,
"qcom,dsi-dyn-clk-list");
if (dyn_clk_caps->bit_clk_list_len < 1) {
pr_err("[%s] failed to get supported bit clk list\n", name);
return -EINVAL;
}
dyn_clk_caps->bit_clk_list = kcalloc(dyn_clk_caps->bit_clk_list_len,
sizeof(u32), GFP_KERNEL);
if (!dyn_clk_caps->bit_clk_list)
return -ENOMEM;
rc = utils->read_u32_array(utils->data, "qcom,dsi-dyn-clk-list",
dyn_clk_caps->bit_clk_list,
dyn_clk_caps->bit_clk_list_len);
if (rc) {
pr_err("[%s] failed to parse supported bit clk list\n", name);
return -EINVAL;
}
dyn_clk_caps->dyn_clk_support = true;
return 0;
}
static int dsi_panel_parse_dfps_caps(struct dsi_panel *panel)
{
int rc = 0;
@@ -1163,7 +1205,7 @@ static int dsi_panel_parse_dfps_caps(struct dsi_panel *panel)
struct dsi_parser_utils *utils = &panel->utils;
const char *name = panel->name;
const char *type;
u32 val = 0;
u32 i;
supported = utils->read_bool(utils->data,
"qcom,mdss-dsi-pan-enable-dynamic-fps");
@@ -1171,66 +1213,64 @@ static int dsi_panel_parse_dfps_caps(struct dsi_panel *panel)
if (!supported) {
pr_debug("[%s] DFPS is not supported\n", name);
dfps_caps->dfps_support = false;
return rc;
}
type = utils->get_property(utils->data,
"qcom,mdss-dsi-pan-fps-update", NULL);
if (!type) {
pr_err("[%s] dfps type not defined\n", name);
rc = -EINVAL;
goto error;
} else if (!strcmp(type, "dfps_suspend_resume_mode")) {
dfps_caps->type = DSI_DFPS_SUSPEND_RESUME;
} else if (!strcmp(type, "dfps_immediate_clk_mode")) {
dfps_caps->type = DSI_DFPS_IMMEDIATE_CLK;
} else if (!strcmp(type, "dfps_immediate_porch_mode_hfp")) {
dfps_caps->type = DSI_DFPS_IMMEDIATE_HFP;
} else if (!strcmp(type, "dfps_immediate_porch_mode_vfp")) {
dfps_caps->type = DSI_DFPS_IMMEDIATE_VFP;
} else {
pr_err("[%s] dfps type is not recognized\n", name);
rc = -EINVAL;
goto error;
}
type = utils->get_property(utils->data,
"qcom,mdss-dsi-pan-fps-update",
NULL);
if (!type) {
pr_err("[%s] dfps type not defined\n", name);
rc = -EINVAL;
goto error;
} else if (!strcmp(type, "dfps_suspend_resume_mode")) {
dfps_caps->type = DSI_DFPS_SUSPEND_RESUME;
} else if (!strcmp(type, "dfps_immediate_clk_mode")) {
dfps_caps->type = DSI_DFPS_IMMEDIATE_CLK;
} else if (!strcmp(type, "dfps_immediate_porch_mode_hfp")) {
dfps_caps->type = DSI_DFPS_IMMEDIATE_HFP;
} else if (!strcmp(type, "dfps_immediate_porch_mode_vfp")) {
dfps_caps->type = DSI_DFPS_IMMEDIATE_VFP;
} else {
pr_err("[%s] dfps type is not recognized\n", name);
rc = -EINVAL;
goto error;
}
dfps_caps->dfps_list_len = utils->count_u32_elems(utils->data,
"qcom,dsi-supported-dfps-list");
if (dfps_caps->dfps_list_len < 1) {
pr_err("[%s] dfps refresh list not present\n", name);
rc = -EINVAL;
goto error;
}
rc = utils->read_u32(utils->data,
"qcom,mdss-dsi-min-refresh-rate",
&val);
if (rc) {
pr_err("[%s] Min refresh rate is not defined\n", name);
rc = -EINVAL;
goto error;
}
dfps_caps->min_refresh_rate = val;
dfps_caps->dfps_list = kcalloc(dfps_caps->dfps_list_len, sizeof(u32),
GFP_KERNEL);
if (!dfps_caps->dfps_list) {
rc = -ENOMEM;
goto error;
}
rc = utils->read_u32(utils->data,
"qcom,mdss-dsi-max-refresh-rate",
&val);
if (rc) {
pr_debug("[%s] Using default refresh rate\n", name);
rc = utils->read_u32(utils->data,
"qcom,mdss-dsi-panel-framerate",
&val);
if (rc) {
pr_err("[%s] max refresh rate is not defined\n",
name);
rc = -EINVAL;
goto error;
}
}
dfps_caps->max_refresh_rate = val;
rc = utils->read_u32_array(utils->data,
"qcom,dsi-supported-dfps-list",
dfps_caps->dfps_list,
dfps_caps->dfps_list_len);
if (rc) {
pr_err("[%s] dfps refresh rate list parse failed\n", name);
rc = -EINVAL;
goto error;
}
dfps_caps->dfps_support = true;
if (dfps_caps->min_refresh_rate > dfps_caps->max_refresh_rate) {
pr_err("[%s] min rate > max rate\n", name);
rc = -EINVAL;
}
/* calculate max and min fps */
dfps_caps->max_refresh_rate = dfps_caps->dfps_list[0];
dfps_caps->min_refresh_rate = dfps_caps->dfps_list[0];
pr_debug("[%s] DFPS is supported %d-%d, mode %d\n", name,
dfps_caps->min_refresh_rate,
dfps_caps->max_refresh_rate,
dfps_caps->type);
dfps_caps->dfps_support = true;
for (i = 1; i < dfps_caps->dfps_list_len; i++) {
if (dfps_caps->dfps_list[i] < dfps_caps->min_refresh_rate)
dfps_caps->min_refresh_rate = dfps_caps->dfps_list[i];
else if (dfps_caps->dfps_list[i] > dfps_caps->max_refresh_rate)
dfps_caps->max_refresh_rate = dfps_caps->dfps_list[i];
}
error:
@@ -3053,6 +3093,13 @@ struct dsi_panel *dsi_panel_get(struct device *parent,
pr_err("failed to parse qsync features, rc=%d\n", rc);
}
if (panel->panel_mode == DSI_OP_VIDEO_MODE) {
rc = dsi_panel_parse_dyn_clk_caps(panel);
if (rc)
pr_err("failed to parse dynamic clk config, rc=%d\n",
rc);
}
rc = dsi_panel_parse_phy_props(panel);
if (rc) {
pr_err("failed to parse panel physical dimension, rc=%d\n", rc);