msm: mdss: add support for LP2 low power state
Define a new low power state for display (LP2), in which the panel is on but cannot accept any updates. Add support for transitions in and out of this new power state. Change-Id: Ie25ec157bf6bb16efb76d535822c2e978a0bc2e1 Signed-off-by: Aravind Venkateswaran <aravindh@codeaurora.org>
This commit is contained in:
parent
fa69b02d44
commit
fbcc005c2b
5 changed files with 243 additions and 112 deletions
|
@ -184,9 +184,9 @@ error:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int mdss_dsi_panel_power_doze(struct mdss_panel_data *pdata, int enable)
|
||||
static int mdss_dsi_panel_power_lp(struct mdss_panel_data *pdata, int enable)
|
||||
{
|
||||
/* Panel power control when entering/exiting doze mode */
|
||||
/* Panel power control when entering/exiting lp mode */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -223,12 +223,13 @@ static int mdss_dsi_panel_power_ctrl(struct mdss_panel_data *pdata,
|
|||
break;
|
||||
case MDSS_PANEL_POWER_ON:
|
||||
if (mdss_dsi_is_panel_on_lp(pdata))
|
||||
ret = mdss_dsi_panel_power_doze(pdata, false);
|
||||
ret = mdss_dsi_panel_power_lp(pdata, false);
|
||||
else
|
||||
ret = mdss_dsi_panel_power_on(pdata);
|
||||
break;
|
||||
case MDSS_PANEL_POWER_DOZE:
|
||||
ret = mdss_dsi_panel_power_doze(pdata, true);
|
||||
case MDSS_PANEL_POWER_LP1:
|
||||
case MDSS_PANEL_POWER_LP2:
|
||||
ret = mdss_dsi_panel_power_lp(pdata, true);
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: unknown panel power state requested (%d)\n",
|
||||
|
@ -472,7 +473,7 @@ static int mdss_dsi_off(struct mdss_panel_data *pdata, int power_state)
|
|||
goto end;
|
||||
}
|
||||
|
||||
if (power_state != MDSS_PANEL_POWER_OFF) {
|
||||
if (mdss_panel_is_power_on(power_state)) {
|
||||
pr_debug("%s: dsi_off with panel always on\n", __func__);
|
||||
goto panel_power_ctrl;
|
||||
}
|
||||
|
@ -745,7 +746,7 @@ static int mdss_dsi_blank(struct mdss_panel_data *pdata, int power_state)
|
|||
|
||||
mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1);
|
||||
|
||||
if (power_state == MDSS_PANEL_POWER_DOZE) {
|
||||
if (mdss_panel_is_power_on_lp(power_state)) {
|
||||
pr_debug("%s: low power state requested\n", __func__);
|
||||
if (ctrl_pdata->low_power_config)
|
||||
ret = ctrl_pdata->low_power_config(pdata, true);
|
||||
|
|
|
@ -67,6 +67,10 @@
|
|||
#endif
|
||||
|
||||
#define MAX_FBI_LIST 32
|
||||
|
||||
#define BLANK_FLAG_LP FB_BLANK_VSYNC_SUSPEND
|
||||
#define BLANK_FLAG_ULP FB_BLANK_NORMAL
|
||||
|
||||
static struct fb_info *fbi_list[MAX_FBI_LIST];
|
||||
static int fbi_list_index;
|
||||
|
||||
|
@ -854,10 +858,11 @@ static int mdss_fb_suspend_sub(struct msm_fb_data_type *mfd)
|
|||
/*
|
||||
* Ideally, display should have either been blanked by now, or
|
||||
* should have transitioned to a low power state. If not, then
|
||||
* as a fall back option, blank the display.
|
||||
* as a fall back option, enter ulp state to leave the display
|
||||
* on, but turn off all interface clocks.
|
||||
*/
|
||||
if (mdss_fb_is_power_on_interactive(mfd)) {
|
||||
ret = mdss_fb_blank_sub(FB_BLANK_POWERDOWN, mfd->fbi,
|
||||
if (mdss_fb_is_power_on(mfd)) {
|
||||
ret = mdss_fb_blank_sub(BLANK_FLAG_ULP, mfd->fbi,
|
||||
mfd->suspend.op_enable);
|
||||
if (ret) {
|
||||
pr_err("can't turn off display!\n");
|
||||
|
@ -893,13 +898,16 @@ static int mdss_fb_resume_sub(struct msm_fb_data_type *mfd)
|
|||
mfd->op_enable = mfd->suspend.op_enable;
|
||||
|
||||
/*
|
||||
* If the fb was explicitly blanked during suspend, then unblank it
|
||||
* during resume.
|
||||
* If the fb was explicitly blanked or transitioned to ulp during
|
||||
* suspend, then undo it during resume with the appropriate unblank
|
||||
* flag. If fb was in ulp state when entering suspend, then nothing
|
||||
* needs to be done.
|
||||
*/
|
||||
if (mdss_panel_is_power_on(mfd->suspend.panel_power_state)) {
|
||||
if (mdss_panel_is_power_on(mfd->suspend.panel_power_state) &&
|
||||
!mdss_panel_is_power_on_ulp(mfd->suspend.panel_power_state)) {
|
||||
int unblank_flag = mdss_panel_is_power_on_interactive(
|
||||
mfd->suspend.panel_power_state) ? FB_BLANK_UNBLANK :
|
||||
FB_BLANK_VSYNC_SUSPEND;
|
||||
BLANK_FLAG_LP;
|
||||
|
||||
ret = mdss_fb_blank_sub(unblank_flag, mfd->fbi, mfd->op_enable);
|
||||
if (ret)
|
||||
|
@ -1180,7 +1188,61 @@ static void mdss_panel_validate_debugfs_info(struct msm_fb_data_type *mfd)
|
|||
}
|
||||
}
|
||||
|
||||
static int mdss_fb_unblank_sub(struct msm_fb_data_type *mfd)
|
||||
static int mdss_fb_blank_blank(struct msm_fb_data_type *mfd,
|
||||
int req_power_state)
|
||||
{
|
||||
int ret = 0;
|
||||
int cur_power_state;
|
||||
|
||||
if (!mfd)
|
||||
return -EINVAL;
|
||||
|
||||
if (!mdss_fb_is_power_on(mfd) || !mfd->mdp.off_fnc)
|
||||
return 0;
|
||||
|
||||
cur_power_state = mfd->panel_power_state;
|
||||
|
||||
pr_debug("Transitioning from %d --> %d\n", cur_power_state,
|
||||
req_power_state);
|
||||
|
||||
if (cur_power_state == req_power_state) {
|
||||
pr_debug("No change in power state\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mutex_lock(&mfd->update.lock);
|
||||
mfd->update.type = NOTIFY_TYPE_SUSPEND;
|
||||
mfd->update.is_suspend = 1;
|
||||
mutex_unlock(&mfd->update.lock);
|
||||
complete(&mfd->update.comp);
|
||||
del_timer(&mfd->no_update.timer);
|
||||
mfd->no_update.value = NOTIFY_TYPE_SUSPEND;
|
||||
complete(&mfd->no_update.comp);
|
||||
|
||||
mfd->op_enable = false;
|
||||
mutex_lock(&mfd->bl_lock);
|
||||
if (mdss_panel_is_power_off(req_power_state)) {
|
||||
/* Stop Display thread */
|
||||
if (mfd->disp_thread)
|
||||
mdss_fb_stop_disp_thread(mfd);
|
||||
mdss_fb_set_backlight(mfd, 0);
|
||||
mfd->bl_updated = 0;
|
||||
}
|
||||
mfd->panel_power_state = req_power_state;
|
||||
mutex_unlock(&mfd->bl_lock);
|
||||
|
||||
ret = mfd->mdp.off_fnc(mfd);
|
||||
if (ret)
|
||||
mfd->panel_power_state = cur_power_state;
|
||||
else if (mdss_panel_is_power_off(req_power_state))
|
||||
mdss_fb_release_fences(mfd);
|
||||
mfd->op_enable = true;
|
||||
complete(&mfd->power_off_comp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mdss_fb_blank_unblank(struct msm_fb_data_type *mfd)
|
||||
{
|
||||
int ret = 0;
|
||||
int cur_power_state;
|
||||
|
@ -1199,16 +1261,23 @@ static int mdss_fb_unblank_sub(struct msm_fb_data_type *mfd)
|
|||
}
|
||||
|
||||
cur_power_state = mfd->panel_power_state;
|
||||
if (!mdss_panel_is_power_on_interactive(cur_power_state) &&
|
||||
mfd->mdp.on_fnc) {
|
||||
pr_debug("Transitioning from %d --> %d\n", cur_power_state,
|
||||
MDSS_PANEL_POWER_ON);
|
||||
|
||||
if (mdss_panel_is_power_on_interactive(cur_power_state)) {
|
||||
pr_debug("No change in power state\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mfd->mdp.on_fnc) {
|
||||
ret = mfd->mdp.on_fnc(mfd);
|
||||
if (ret == 0) {
|
||||
mfd->panel_power_state = MDSS_PANEL_POWER_ON;
|
||||
mfd->panel_info->panel_dead = false;
|
||||
} else if (mfd->disp_thread) {
|
||||
if (ret) {
|
||||
mdss_fb_stop_disp_thread(mfd);
|
||||
goto error;
|
||||
}
|
||||
|
||||
mfd->panel_power_state = MDSS_PANEL_POWER_ON;
|
||||
mfd->panel_info->panel_dead = false;
|
||||
mutex_lock(&mfd->update.lock);
|
||||
mfd->update.type = NOTIFY_TYPE_UPDATE;
|
||||
mfd->update.is_suspend = 0;
|
||||
|
@ -1253,82 +1322,67 @@ static int mdss_fb_blank_sub(int blank_mode, struct fb_info *info,
|
|||
cur_power_state = mfd->panel_power_state;
|
||||
|
||||
/*
|
||||
* If doze mode is requested for video mode panels, treat
|
||||
* the request as full unblank as there are no low power mode
|
||||
* settings for video mode panels.
|
||||
* Low power (lp) and ultra low pwoer (ulp) modes are currently only
|
||||
* supported for command mode panels. For all other panel, treat lp
|
||||
* mode as full unblank and ulp mode as full blank.
|
||||
*/
|
||||
if ((FB_BLANK_VSYNC_SUSPEND == blank_mode) &&
|
||||
(mfd->panel_info->type != MIPI_CMD_PANEL)) {
|
||||
pr_debug("Doze mode only valid for cmd mode panels\n");
|
||||
|
||||
if (mdss_panel_is_power_on(cur_power_state))
|
||||
return 0;
|
||||
else
|
||||
blank_mode = FB_BLANK_UNBLANK;
|
||||
if (mfd->panel_info->type != MIPI_CMD_PANEL) {
|
||||
if (BLANK_FLAG_LP == blank_mode) {
|
||||
pr_debug("lp mode only valid for cmd mode panels\n");
|
||||
if (mdss_fb_is_power_on_interactive(mfd))
|
||||
return 0;
|
||||
else
|
||||
blank_mode = FB_BLANK_UNBLANK;
|
||||
} else if (BLANK_FLAG_ULP == blank_mode) {
|
||||
pr_debug("ulp mode valid for cmd mode panels\n");
|
||||
if (mdss_fb_is_power_off(mfd))
|
||||
return 0;
|
||||
else
|
||||
blank_mode = FB_BLANK_POWERDOWN;
|
||||
}
|
||||
}
|
||||
|
||||
switch (blank_mode) {
|
||||
case FB_BLANK_UNBLANK:
|
||||
pr_debug("unblank called. cur pwr state=%d\n", cur_power_state);
|
||||
ret = mdss_fb_unblank_sub(mfd);
|
||||
ret = mdss_fb_blank_unblank(mfd);
|
||||
break;
|
||||
case BLANK_FLAG_ULP:
|
||||
req_power_state = MDSS_PANEL_POWER_LP2;
|
||||
pr_debug("ultra low power mode requested\n");
|
||||
if (mdss_fb_is_power_off(mfd)) {
|
||||
pr_debug("Unsupp transition: off --> ulp\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
case FB_BLANK_VSYNC_SUSPEND:
|
||||
req_power_state = MDSS_PANEL_POWER_DOZE;
|
||||
pr_debug("Doze power mode requested\n");
|
||||
ret = mdss_fb_blank_blank(mfd, req_power_state);
|
||||
break;
|
||||
case BLANK_FLAG_LP:
|
||||
req_power_state = MDSS_PANEL_POWER_LP1;
|
||||
pr_debug(" power mode requested\n");
|
||||
|
||||
/*
|
||||
* If doze mode is requested when panel is already off,
|
||||
* then first unblank the panel before entering doze mode
|
||||
* If low power mode is requested when panel is already off,
|
||||
* then first unblank the panel before entering low power mode
|
||||
*/
|
||||
if (mdss_fb_is_power_off(mfd) && mfd->mdp.on_fnc) {
|
||||
pr_debug("off --> doze. switch to on first\n");
|
||||
ret = mdss_fb_unblank_sub(mfd);
|
||||
pr_debug("off --> lp. switch to on first\n");
|
||||
ret = mdss_fb_blank_unblank(mfd);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Enter doze mode only if unblank succeeded */
|
||||
if (ret)
|
||||
break;
|
||||
ret = mdss_fb_blank_blank(mfd, req_power_state);
|
||||
break;
|
||||
case FB_BLANK_HSYNC_SUSPEND:
|
||||
case FB_BLANK_NORMAL:
|
||||
case FB_BLANK_POWERDOWN:
|
||||
default:
|
||||
pr_debug("blank powerdown called. cur mode=%d, req mode=%d\n",
|
||||
cur_power_state, req_power_state);
|
||||
if (mdss_fb_is_power_on(mfd) && mfd->mdp.off_fnc) {
|
||||
cur_power_state = mfd->panel_power_state;
|
||||
|
||||
mutex_lock(&mfd->update.lock);
|
||||
mfd->update.type = NOTIFY_TYPE_SUSPEND;
|
||||
mfd->update.is_suspend = 1;
|
||||
mutex_unlock(&mfd->update.lock);
|
||||
complete(&mfd->update.comp);
|
||||
del_timer(&mfd->no_update.timer);
|
||||
mfd->no_update.value = NOTIFY_TYPE_SUSPEND;
|
||||
complete(&mfd->no_update.comp);
|
||||
|
||||
mfd->op_enable = false;
|
||||
mutex_lock(&mfd->bl_lock);
|
||||
if (mdss_panel_is_power_off(req_power_state)) {
|
||||
/* Stop Display thread */
|
||||
if (mfd->disp_thread)
|
||||
mdss_fb_stop_disp_thread(mfd);
|
||||
mdss_fb_set_backlight(mfd, 0);
|
||||
mfd->bl_updated = 0;
|
||||
}
|
||||
mfd->panel_power_state = req_power_state;
|
||||
mutex_unlock(&mfd->bl_lock);
|
||||
|
||||
ret = mfd->mdp.off_fnc(mfd);
|
||||
if (ret)
|
||||
mfd->panel_power_state = cur_power_state;
|
||||
else if (mdss_panel_is_power_off(req_power_state))
|
||||
mdss_fb_release_fences(mfd);
|
||||
mfd->op_enable = true;
|
||||
complete(&mfd->power_off_comp);
|
||||
}
|
||||
req_power_state = MDSS_PANEL_POWER_OFF;
|
||||
pr_debug("blank powerdown called\n");
|
||||
ret = mdss_fb_blank_blank(mfd, req_power_state);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Notify listeners */
|
||||
sysfs_notify(&mfd->fbi->dev->kobj, NULL, "show_blank_event");
|
||||
|
||||
|
@ -1344,8 +1398,10 @@ static int mdss_fb_blank(int blank_mode, struct fb_info *info)
|
|||
if (mfd->op_enable == 0) {
|
||||
if (blank_mode == FB_BLANK_UNBLANK)
|
||||
mfd->suspend.panel_power_state = MDSS_PANEL_POWER_ON;
|
||||
else if (blank_mode == FB_BLANK_VSYNC_SUSPEND)
|
||||
mfd->suspend.panel_power_state = MDSS_PANEL_POWER_DOZE;
|
||||
else if (blank_mode == BLANK_FLAG_ULP)
|
||||
mfd->suspend.panel_power_state = MDSS_PANEL_POWER_LP2;
|
||||
else if (blank_mode == BLANK_FLAG_LP)
|
||||
mfd->suspend.panel_power_state = MDSS_PANEL_POWER_LP1;
|
||||
else
|
||||
mfd->suspend.panel_power_state = MDSS_PANEL_POWER_OFF;
|
||||
return 0;
|
||||
|
|
|
@ -2579,11 +2579,12 @@ int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl, int power_state)
|
|||
mdss_mdp_ctl_write(ctl, off, 0);
|
||||
}
|
||||
|
||||
ctl->power_state = power_state;
|
||||
ctl->play_cnt = 0;
|
||||
mdss_mdp_ctl_perf_update(ctl, 0);
|
||||
|
||||
end:
|
||||
if (!ret)
|
||||
ctl->power_state = power_state;
|
||||
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
|
||||
|
||||
mutex_unlock(&ctl->lock);
|
||||
|
|
|
@ -731,6 +731,8 @@ static int mdss_mdp_cmd_panel_on(struct mdss_mdp_ctl *ctl,
|
|||
mdss_mdp_ctl_intf_event(ctl,
|
||||
MDSS_EVENT_REGISTER_RECOVERY_HANDLER,
|
||||
(void *)&ctx->intf_recovery);
|
||||
|
||||
ctx->intf_stopped = 0;
|
||||
} else {
|
||||
pr_err("%s: Panel already on\n", __func__);
|
||||
}
|
||||
|
@ -878,7 +880,6 @@ int mdss_mdp_cmd_intfs_stop(struct mdss_mdp_ctl *ctl, int session,
|
|||
pr_err("invalid ctx session: %d\n", session);
|
||||
return -ENODEV;
|
||||
}
|
||||
ctx->ref_cnt--;
|
||||
|
||||
/* intf stopped, no more kickoff */
|
||||
ctx->intf_stopped = 1;
|
||||
|
@ -919,6 +920,11 @@ int mdss_mdp_cmd_intfs_stop(struct mdss_mdp_ctl *ctl, int session,
|
|||
flush_work(&ctx->pp_done_work);
|
||||
mdss_mdp_cmd_tearcheck_setup(ctl, false);
|
||||
|
||||
if (mdss_panel_is_power_on(panel_power_state)) {
|
||||
pr_debug("%s: intf stopped with panel on\n", __func__);
|
||||
goto end;
|
||||
}
|
||||
|
||||
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR,
|
||||
ctx->pp_num, NULL, NULL);
|
||||
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP,
|
||||
|
@ -926,6 +932,7 @@ int mdss_mdp_cmd_intfs_stop(struct mdss_mdp_ctl *ctl, int session,
|
|||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
end:
|
||||
pr_debug("%s:-\n", __func__);
|
||||
|
||||
return 0;
|
||||
|
@ -944,17 +951,6 @@ static int mdss_mdp_cmd_stop_sub(struct mdss_mdp_ctl *ctl,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* if power state already updated, skip this */
|
||||
if (ctx->panel_power_state == panel_power_state)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If the panel will be left on, then we do not need to turn off
|
||||
* interface clocks since we may continue to get display updates.
|
||||
*/
|
||||
if (mdss_panel_is_power_on(panel_power_state))
|
||||
return 0;
|
||||
|
||||
list_for_each_entry_safe(handle, tmp, &ctx->vsync_handlers, list)
|
||||
mdss_mdp_cmd_remove_vsync_handler(ctl, handle);
|
||||
MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled,
|
||||
|
@ -969,30 +965,92 @@ int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl, int panel_power_state)
|
|||
{
|
||||
struct mdss_mdp_cmd_ctx *ctx = ctl->priv_data;
|
||||
struct mdss_mdp_ctl *sctl = mdss_mdp_get_split_ctl(ctl);
|
||||
int ret;
|
||||
bool panel_off = false;
|
||||
bool turn_off_clocks = false;
|
||||
bool send_panel_events = false;
|
||||
int ret = 0;
|
||||
|
||||
if (!ctx) {
|
||||
pr_err("invalid ctx\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (ctx->panel_power_state != panel_power_state) {
|
||||
ret = mdss_mdp_cmd_stop_sub(ctl, panel_power_state);
|
||||
if (ctx->panel_power_state == panel_power_state)
|
||||
return 0;
|
||||
|
||||
if (__mdss_mdp_cmd_is_panel_power_off(ctx)) {
|
||||
pr_debug("%s: panel already off\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->panel_power_state == panel_power_state) {
|
||||
pr_debug("%s: no transition needed %d --> %d\n", __func__,
|
||||
ctx->panel_power_state, panel_power_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pr_debug("%s: transition from %d --> %d\n", __func__,
|
||||
ctx->panel_power_state, panel_power_state);
|
||||
|
||||
if (__mdss_mdp_cmd_is_panel_power_on_interactive(ctx)) {
|
||||
if (mdss_panel_is_power_on_lp(panel_power_state)) {
|
||||
/*
|
||||
* If we are transitioning from interactive to low
|
||||
* power, then we need to send events to the interface
|
||||
* so that the panel can be configured in low power
|
||||
* mode.
|
||||
*/
|
||||
send_panel_events = true;
|
||||
if (mdss_panel_is_power_on_ulp(panel_power_state))
|
||||
turn_off_clocks = true;
|
||||
} else if (mdss_panel_is_power_off(panel_power_state)) {
|
||||
send_panel_events = true;
|
||||
turn_off_clocks = true;
|
||||
panel_off = true;
|
||||
}
|
||||
} else {
|
||||
if (mdss_panel_is_power_on_ulp(panel_power_state)) {
|
||||
/*
|
||||
* If we are transitioning from low power to ultra low
|
||||
* power mode, no more display updates are expected.
|
||||
* Turn off the interface clocks.
|
||||
*/
|
||||
pr_debug("%s: turn off clocks\n", __func__);
|
||||
turn_off_clocks = true;
|
||||
} else {
|
||||
/*
|
||||
* Transition from ultra low power to low power does
|
||||
* not require any special handling. The clocks would
|
||||
* get turned on when the first update comes.
|
||||
*/
|
||||
pr_debug("%s: nothing to be done.\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!turn_off_clocks)
|
||||
goto panel_events;
|
||||
|
||||
pr_debug("%s: turn off interface clocks\n", __func__);
|
||||
ret = mdss_mdp_cmd_stop_sub(ctl, panel_power_state);
|
||||
if (IS_ERR_VALUE(ret)) {
|
||||
pr_err("%s: unable to stop interface: %d\n",
|
||||
__func__, ret);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (sctl) {
|
||||
mdss_mdp_cmd_stop_sub(sctl, panel_power_state);
|
||||
if (IS_ERR_VALUE(ret)) {
|
||||
pr_err("%s: unable to stop interface: %d\n",
|
||||
pr_err("%s: unable to stop slave intf: %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (sctl) {
|
||||
mdss_mdp_cmd_stop_sub(sctl, panel_power_state);
|
||||
if (IS_ERR_VALUE(ret)) {
|
||||
pr_err("%s: unable to stop slave intf: %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
panel_events:
|
||||
if ((ctl->num == 0) && send_panel_events) {
|
||||
pr_debug("%s: send panel events\n", __func__);
|
||||
ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_BLANK,
|
||||
(void *) (long int) panel_power_state);
|
||||
WARN(ret, "intf %d unblank error (%d)\n", ctl->intf_num, ret);
|
||||
|
@ -1004,11 +1062,12 @@ int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl, int panel_power_state)
|
|||
|
||||
ctx->panel_power_state = panel_power_state;
|
||||
|
||||
if (mdss_panel_is_power_on(panel_power_state)) {
|
||||
if (!panel_off) {
|
||||
pr_debug("%s: cmd_stop with panel always on\n", __func__);
|
||||
goto end;
|
||||
}
|
||||
|
||||
pr_debug("%s: turn off panel\n", __func__);
|
||||
ctl->priv_data = NULL;
|
||||
ctl->stop_fnc = NULL;
|
||||
ctl->display_fnc = NULL;
|
||||
|
@ -1021,7 +1080,7 @@ end:
|
|||
ctx->rdptr_enabled, XLOG_FUNC_EXIT);
|
||||
pr_debug("%s:-\n", __func__);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mdss_mdp_cmd_intfs_setup(struct mdss_mdp_ctl *ctl,
|
||||
|
|
|
@ -91,7 +91,8 @@ enum {
|
|||
enum {
|
||||
MDSS_PANEL_POWER_OFF = 0,
|
||||
MDSS_PANEL_POWER_ON,
|
||||
MDSS_PANEL_POWER_DOZE,
|
||||
MDSS_PANEL_POWER_LP1,
|
||||
MDSS_PANEL_POWER_LP2,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -623,8 +624,8 @@ static inline bool mdss_panel_is_power_on(int panel_power_state)
|
|||
* @panel_power_state: enum identifying the power state to be checked
|
||||
*
|
||||
* This function returns true if the panel is in an intermediate low power
|
||||
* state where it is still on but not fully interactive. It may still accept
|
||||
* commands and display updates but would be operating in a low power mode.
|
||||
* state where it is still on but not fully interactive. It may or may not
|
||||
* accept any commands and display updates.
|
||||
*/
|
||||
static inline bool mdss_panel_is_power_on_lp(int panel_power_state)
|
||||
{
|
||||
|
@ -632,6 +633,19 @@ static inline bool mdss_panel_is_power_on_lp(int panel_power_state)
|
|||
!mdss_panel_is_power_on_interactive(panel_power_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_panel_is_panel_power_on_ulp: - checks if panel is in ultra low power mode
|
||||
* @pdata: pointer to the panel struct associated to the panel
|
||||
* @panel_power_state: enum identifying the power state to be checked
|
||||
*
|
||||
* This function returns true if the panel is in a ultra low power
|
||||
* state where it is still on but cannot recieve any display updates.
|
||||
*/
|
||||
static inline bool mdss_panel_is_power_on_ulp(int panel_power_state)
|
||||
{
|
||||
return panel_power_state == MDSS_PANEL_POWER_LP2;
|
||||
}
|
||||
|
||||
/**
|
||||
* mdss_panel_intf_type: - checks if a given intf type is primary
|
||||
* @intf_val: panel interface type of the individual controller
|
||||
|
|
Loading…
Add table
Reference in a new issue