Merge "video: fbdev: msm: Add support for ultra low power state"

This commit is contained in:
qctecmdr 2020-09-18 10:11:45 -07:00 committed by Gerrit - the friendly Code Review server
commit 327aa391ef
3 changed files with 115 additions and 7 deletions

View File

@ -444,11 +444,62 @@ static int mdss_dsi_panel_power_lp(struct mdss_panel_data *pdata, int enable)
return 0;
}
static int mdss_dsi_panel_power_ctrl(struct mdss_panel_data *pdata,
static int mdss_dsi_panel_power_ulp(struct mdss_panel_data *pdata,
int enable)
{
int ret = 0, i;
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
u32 mode = enable ? DSS_REG_MODE_ULP : DSS_REG_MODE_ENABLE;
struct dsi_shared_data *sdata;
pr_debug("%s: +\n", __func__);
if (pdata == NULL) {
pr_err("%s: Invalid input data\n", __func__);
return -EINVAL;
}
ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
panel_data);
sdata = ctrl_pdata->shared_data;
for (i = 0; i < DSI_MAX_PM; i++) {
/*
* Core power module need to be controlled along with
* DSI core clocks.
*/
if (i == DSI_CORE_PM)
continue;
if (i == DSI_PANEL_PM)
ret = msm_dss_config_vreg_opt_mode(
ctrl_pdata->panel_power_data.vreg_config,
ctrl_pdata->panel_power_data.num_vreg, mode);
else
ret = msm_dss_config_vreg_opt_mode(
sdata->power_data[i].vreg_config,
sdata->power_data[i].num_vreg, mode);
if (ret) {
pr_err("%s: failed to config ulp opt mode for %s.rc=%d\n",
__func__, __mdss_dsi_pm_name(i), ret);
break;
}
}
if (ret) {
mode = enable ? DSS_REG_MODE_ENABLE : DSS_REG_MODE_ULP;
for (; i >= 0; i--)
msm_dss_config_vreg_opt_mode(
ctrl_pdata->power_data[i].vreg_config,
ctrl_pdata->power_data[i].num_vreg, mode);
}
return ret;
}
int mdss_dsi_panel_power_ctrl(struct mdss_panel_data *pdata,
int power_state)
{
int ret = 0;
struct mdss_panel_info *pinfo;
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
if (pdata == NULL) {
pr_err("%s: Invalid input data\n", __func__);
@ -456,7 +507,8 @@ static int mdss_dsi_panel_power_ctrl(struct mdss_panel_data *pdata,
}
pinfo = &pdata->panel_info;
pr_debug("%s: cur_power_state=%d req_power_state=%d\n", __func__,
pr_debug("%pS->%s: cur_power_state=%d req_power_state=%d\n",
__builtin_return_address(0), __func__,
pinfo->panel_power_state, power_state);
if (pinfo->panel_power_state == power_state) {
@ -464,6 +516,9 @@ static int mdss_dsi_panel_power_ctrl(struct mdss_panel_data *pdata,
return 0;
}
ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
panel_data);
/*
* If a dynamic mode switch is pending, the regulators should not
* be turned off or on.
@ -480,14 +535,31 @@ static int mdss_dsi_panel_power_ctrl(struct mdss_panel_data *pdata,
ret = mdss_dsi_panel_power_off(pdata);
break;
case MDSS_PANEL_POWER_ON:
if (mdss_dsi_is_panel_on_lp(pdata))
if (mdss_dsi_is_panel_on_ulp(pdata)) {
ret = mdss_dsi_panel_power_ulp(pdata, false);
goto end;
} else if (mdss_dsi_is_panel_on_lp(pdata)) {
ret = mdss_dsi_panel_power_lp(pdata, false);
else
goto end;
} else {
ret = mdss_dsi_panel_power_on(pdata);
}
break;
case MDSS_PANEL_POWER_LP1:
if (mdss_dsi_is_panel_on_ulp(pdata))
ret = mdss_dsi_panel_power_ulp(pdata, false);
else
ret = mdss_dsi_panel_power_lp(pdata, true);
/*
* temp workaround until framework issues pertaining to LP2
* power state transitions are fixed. For now, we internally
* transition to LP2 state whenever core power is turned off
* in LP1 state
*/
break;
case MDSS_PANEL_POWER_LP2:
ret = mdss_dsi_panel_power_lp(pdata, true);
if (!ctrl_pdata->core_power)
ret = mdss_dsi_panel_power_ulp(pdata, true);
break;
default:
pr_err("%s: unknown panel power state requested (%d)\n",
@ -497,7 +569,7 @@ static int mdss_dsi_panel_power_ctrl(struct mdss_panel_data *pdata,
if (!ret)
pinfo->panel_power_state = power_state;
end:
return ret;
}
@ -618,6 +690,16 @@ int mdss_dsi_get_dt_vreg_data(struct device *dev,
}
mp->vreg_config[i].load[DSS_REG_MODE_DISABLE] = tmp;
rc = of_property_read_u32(supply_node,
"qcom,supply-ulp-load", &tmp);
if (rc) {
pr_warn("%s: error reading ulp load. rc=%d\n",
__func__, rc);
rc = 0;
}
mp->vreg_config[i].load[DSS_REG_MODE_ULP] = (!rc ? tmp :
mp->vreg_config[i].load[DSS_REG_MODE_ENABLE]);
/* pre-sleep */
rc = of_property_read_u32(supply_node,
"qcom,supply-pre-on-sleep", &tmp);

View File

@ -726,6 +726,7 @@ void mdss_dsi_cfg_lane_ctrl(struct mdss_dsi_ctrl_pdata *ctrl,
void mdss_dsi_set_reg(struct mdss_dsi_ctrl_pdata *ctrl, int off,
u32 mask, u32 val);
int mdss_dsi_phy_pll_reset_status(struct mdss_dsi_ctrl_pdata *ctrl);
int mdss_dsi_panel_power_ctrl(struct mdss_panel_data *pdata, int power_state);
int mdss_dsi_check_panel_status(struct mdss_dsi_ctrl_pdata *ctrl, void *arg);
void mdss_dsi_debug_bus_init(struct mdss_dsi_data *sdata);
@ -938,6 +939,11 @@ static inline bool mdss_dsi_is_panel_on_lp(struct mdss_panel_data *pdata)
return mdss_panel_is_power_on_lp(pdata->panel_info.panel_power_state);
}
static inline bool mdss_dsi_is_panel_on_ulp(struct mdss_panel_data *pdata)
{
return mdss_panel_is_power_on_ulp(pdata->panel_info.panel_power_state);
}
static inline bool mdss_dsi_ulps_feature_enabled(
struct mdss_panel_data *pdata)
{

View File

@ -2698,7 +2698,8 @@ int mdss_dsi_post_clkoff_cb(void *priv,
* supplies which support turning off in low power
* state
*/
if (ctrl->ctrl_state & CTRL_STATE_DSI_ACTIVE)
if ((ctrl->ctrl_state & CTRL_STATE_DSI_ACTIVE) &&
(i != DSI_CORE_PM))
if (!sdata->power_data[i].vreg_config
->lp_disable_allowed)
continue;
@ -2721,6 +2722,16 @@ int mdss_dsi_post_clkoff_cb(void *priv,
ctrl->core_power = false;
}
}
/*
* temp workaround until framework issues pertaining to LP2
* power state transitions are fixed. For now, we internally
* transition to LP2 state whenever core power is turned off
* in LP1 state
*/
if (mdss_dsi_is_panel_on_lp(pdata))
mdss_dsi_panel_power_ctrl(pdata,
MDSS_PANEL_POWER_LP2);
}
return rc;
}
@ -2758,6 +2769,7 @@ int mdss_dsi_pre_clkon_cb(void *priv,
for (i = DSI_CORE_PM; i < DSI_MAX_PM; i++) {
if ((ctrl->ctrl_state & CTRL_STATE_DSI_ACTIVE) &&
(!pdata->panel_info.cont_splash_enabled) &&
(i != DSI_CORE_PM) &&
(!sdata->power_data[i].vreg_config
->lp_disable_allowed))
continue;
@ -2778,6 +2790,14 @@ int mdss_dsi_pre_clkon_cb(void *priv,
}
}
/*
* temp workaround until framework issues pertaining to LP2
* power state transitions are fixed. For now, if we intend to
* send a frame update when in LP1, we have to explicitly exit
* LP2 state here
*/
if (mdss_dsi_is_panel_on_ulp(pdata))
mdss_dsi_panel_power_ctrl(pdata, MDSS_PANEL_POWER_LP1);
}
/* Disable dynamic clock gating*/