mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
Merge "video: fbdev: msm: Add support for ultra low power state"
This commit is contained in:
commit
327aa391ef
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user