msm: mdss: fix transitions from off to doze mode
When doze mode is requested while the panel in powered off, the panel needs to be first unblanked and then configured into low power mode. While this sequence exists in the current implementation, the execution sequence only calls MDP's on function while unblanking the panel. The correct approach is to go through the full unblank sequence which would also start the display commit thread. Without this, screen updates while in doze mode will not work and could lead to unexpected behaviors. Change-Id: I4f65764acaf01d61d129e00179930af9ebb79c77 Signed-off-by: Aravind Venkateswaran <aravindh@codeaurora.org>
This commit is contained in:
parent
ef6fec42a8
commit
605c69f9b4
1 changed files with 65 additions and 47 deletions
|
@ -1185,6 +1185,57 @@ static void mdss_fb_stop_disp_thread(struct msm_fb_data_type *mfd)
|
|||
mfd->disp_thread = NULL;
|
||||
}
|
||||
|
||||
static int mdss_fb_unblank_sub(struct msm_fb_data_type *mfd)
|
||||
{
|
||||
int ret = 0;
|
||||
int cur_power_state;
|
||||
|
||||
if (!mfd)
|
||||
return -EINVAL;
|
||||
|
||||
/* Start Display thread */
|
||||
if (mfd->disp_thread == NULL) {
|
||||
ret = mdss_fb_start_disp_thread(mfd);
|
||||
if (IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
}
|
||||
|
||||
cur_power_state = mfd->panel_power_state;
|
||||
if (!mdss_panel_is_power_on_interactive(cur_power_state) &&
|
||||
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) {
|
||||
mdss_fb_stop_disp_thread(mfd);
|
||||
goto error;
|
||||
}
|
||||
mutex_lock(&mfd->update.lock);
|
||||
mfd->update.type = NOTIFY_TYPE_UPDATE;
|
||||
mfd->update.is_suspend = 0;
|
||||
mutex_unlock(&mfd->update.lock);
|
||||
|
||||
/* Start the work thread to signal idle time */
|
||||
if (mfd->idle_time)
|
||||
schedule_delayed_work(&mfd->idle_notify_work,
|
||||
msecs_to_jiffies(mfd->idle_time));
|
||||
}
|
||||
|
||||
/* Reset the backlight only if the panel was off */
|
||||
if (mdss_panel_is_power_off(cur_power_state)) {
|
||||
mutex_lock(&mfd->bl_lock);
|
||||
if (!mfd->bl_updated) {
|
||||
mfd->bl_updated = 1;
|
||||
mdss_fb_set_backlight(mfd, mfd->unset_bl_level);
|
||||
}
|
||||
mutex_unlock(&mfd->bl_lock);
|
||||
}
|
||||
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mdss_fb_blank_sub(int blank_mode, struct fb_info *info,
|
||||
int op_enable)
|
||||
{
|
||||
|
@ -1221,64 +1272,31 @@ static int mdss_fb_blank_sub(int blank_mode, struct fb_info *info,
|
|||
switch (blank_mode) {
|
||||
case FB_BLANK_UNBLANK:
|
||||
pr_debug("unblank called. cur pwr state=%d\n", cur_power_state);
|
||||
/* Start Display thread */
|
||||
if (mfd->disp_thread == NULL) {
|
||||
ret = mdss_fb_start_disp_thread(mfd);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!mdss_panel_is_power_on_interactive(cur_power_state) &&
|
||||
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) {
|
||||
mdss_fb_stop_disp_thread(mfd);
|
||||
}
|
||||
mutex_lock(&mfd->update.lock);
|
||||
mfd->update.type = NOTIFY_TYPE_UPDATE;
|
||||
mfd->update.is_suspend = 0;
|
||||
mutex_unlock(&mfd->update.lock);
|
||||
|
||||
/* Start the work thread to signal idle time */
|
||||
if (mfd->idle_time)
|
||||
schedule_delayed_work(&mfd->idle_notify_work,
|
||||
msecs_to_jiffies(mfd->idle_time));
|
||||
}
|
||||
|
||||
/* Reset the backlight only if the panel was off */
|
||||
if (mdss_panel_is_power_off(cur_power_state)) {
|
||||
mutex_lock(&mfd->bl_lock);
|
||||
if (!mfd->bl_updated) {
|
||||
mfd->bl_updated = 1;
|
||||
mdss_fb_set_backlight(mfd, mfd->unset_bl_level);
|
||||
}
|
||||
mutex_unlock(&mfd->bl_lock);
|
||||
}
|
||||
ret = mdss_fb_unblank_sub(mfd);
|
||||
break;
|
||||
|
||||
case FB_BLANK_VSYNC_SUSPEND:
|
||||
req_power_state = MDSS_PANEL_POWER_DOZE;
|
||||
pr_debug("Doze power mode requested\n");
|
||||
|
||||
/*
|
||||
* If doze mode is requested when panel is already off,
|
||||
* then first unblank the panel before entering doze 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);
|
||||
}
|
||||
|
||||
/* Enter doze mode only if unblank succeeded */
|
||||
if (ret)
|
||||
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 doze mode is requested when panel is already off,
|
||||
* then first unblank the panel before entering doze mode
|
||||
*/
|
||||
if ((MDSS_PANEL_POWER_DOZE == req_power_state) &&
|
||||
mdss_fb_is_power_off(mfd) && mfd->mdp.on_fnc) {
|
||||
pr_debug("off --> doze. switch to on first\n");
|
||||
ret = mfd->mdp.on_fnc(mfd);
|
||||
if (ret == 0)
|
||||
mfd->panel_power_state = MDSS_PANEL_POWER_ON;
|
||||
}
|
||||
if (mdss_fb_is_power_on(mfd) && mfd->mdp.off_fnc) {
|
||||
cur_power_state = mfd->panel_power_state;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue