disp: msm: Add support for seamless panel operating mode switch

DSI display may support video mode and command mode both and it may
support transition between these two modes.
This change adds seamless transition between these two modes for DSI
display by avoiding crtc enable/disable and panel power on/off
during modeset.

Change-Id: Id7ddaef7d1f0f7cc7d52283755bad53a246adec6
Signed-off-by: Lei Chen <chenlei@codeaurora.org>
This commit is contained in:
Lei Chen
2019-04-25 17:57:09 +08:00
committed by Gerrit - the friendly Code Review server
parent e6933ff2dc
commit 21edecd3b1
12 changed files with 376 additions and 85 deletions

View File

@@ -3971,6 +3971,10 @@ static int dsi_display_set_mode_sub(struct dsi_display *display,
return -EINVAL;
}
if (mode->dsi_mode_flags & DSI_MODE_FLAG_POMS) {
display->config.panel_mode = mode->panel_mode;
display->panel->panel_mode = mode->panel_mode;
}
rc = dsi_panel_get_host_cfg_for_mode(display->panel,
mode,
&display->config);
@@ -5039,7 +5043,8 @@ static int dsi_display_ext_get_info(struct drm_connector *connector,
info->is_primary = false;
info->capabilities |= (MSM_DISPLAY_CAP_VID_MODE |
MSM_DISPLAY_CAP_EDID | MSM_DISPLAY_CAP_HOT_PLUG);
MSM_DISPLAY_CAP_EDID | MSM_DISPLAY_CAP_HOT_PLUG);
info->curr_panel_mode = MSM_DISPLAY_VIDEO_MODE;
mutex_unlock(&display->display_lock);
return 0;
@@ -5403,10 +5408,16 @@ int dsi_display_get_info(struct drm_connector *connector,
switch (display->panel->panel_mode) {
case DSI_OP_VIDEO_MODE:
info->curr_panel_mode = MSM_DISPLAY_VIDEO_MODE;
info->capabilities |= MSM_DISPLAY_CAP_VID_MODE;
if (display->panel->panel_mode_switch_enabled)
info->capabilities |= MSM_DISPLAY_CAP_CMD_MODE;
break;
case DSI_OP_CMD_MODE:
info->curr_panel_mode = MSM_DISPLAY_CMD_MODE;
info->capabilities |= MSM_DISPLAY_CAP_CMD_MODE;
if (display->panel->panel_mode_switch_enabled)
info->capabilities |= MSM_DISPLAY_CAP_VID_MODE;
info->is_te_using_watchdog_timer =
display->panel->te_using_watchdog_timer |
display->sw_te_using_wd;
@@ -5704,7 +5715,8 @@ int dsi_display_find_mode(struct dsi_display *display,
if (cmp->timing.v_active == m->timing.v_active &&
cmp->timing.h_active == m->timing.h_active &&
cmp->timing.refresh_rate == m->timing.refresh_rate) {
cmp->timing.refresh_rate == m->timing.refresh_rate &&
cmp->panel_mode == m->panel_mode) {
*out_mode = m;
rc = 0;
break;
@@ -6314,7 +6326,8 @@ int dsi_display_prepare(struct dsi_display *display)
goto error;
}
if (!display->is_cont_splash_enabled) {
if (!(mode->dsi_mode_flags & DSI_MODE_FLAG_POMS) &&
(!display->is_cont_splash_enabled)) {
/*
* For continuous splash usecase we skip panel
* pre prepare since the regulator vote is already
@@ -6403,11 +6416,13 @@ int dsi_display_prepare(struct dsi_display *display)
goto error_ctrl_link_off;
}
rc = dsi_panel_prepare(display->panel);
if (rc) {
pr_err("[%s] panel prepare failed, rc=%d\n",
display->name, rc);
goto error_ctrl_link_off;
if (!(mode->dsi_mode_flags & DSI_MODE_FLAG_POMS)) {
rc = dsi_panel_prepare(display->panel);
if (rc) {
pr_err("[%s] panel prepare failed, rc=%d\n",
display->name, rc);
goto error_ctrl_link_off;
}
}
}
goto error;
@@ -6728,7 +6743,8 @@ int dsi_display_enable(struct dsi_display *display)
display->name, rc);
goto error;
}
} else {
} else if (!(display->panel->cur_mode->dsi_mode_flags &
DSI_MODE_FLAG_POMS)){
rc = dsi_panel_enable(display->panel);
if (rc) {
pr_err("[%s] failed to enable DSI panel, rc=%d\n",
@@ -6757,6 +6773,7 @@ int dsi_display_enable(struct dsi_display *display)
}
if (display->config.panel_mode == DSI_OP_VIDEO_MODE) {
pr_debug("%s:enable video timing eng\n", __func__);
rc = dsi_display_vid_engine_enable(display);
if (rc) {
pr_err("[%s]failed to enable DSI video engine, rc=%d\n",
@@ -6764,6 +6781,7 @@ int dsi_display_enable(struct dsi_display *display)
goto error_disable_panel;
}
} else if (display->config.panel_mode == DSI_OP_CMD_MODE) {
pr_debug("%s:enable command timing eng\n", __func__);
rc = dsi_display_cmd_engine_enable(display);
if (rc) {
pr_err("[%s]failed to enable DSI cmd engine, rc=%d\n",
@@ -6797,10 +6815,18 @@ int dsi_display_post_enable(struct dsi_display *display)
mutex_lock(&display->display_lock);
rc = dsi_panel_post_enable(display->panel);
if (rc)
pr_err("[%s] panel post-enable failed, rc=%d\n",
display->name, rc);
if (display->panel->cur_mode->dsi_mode_flags & DSI_MODE_FLAG_POMS) {
if (display->config.panel_mode == DSI_OP_CMD_MODE)
dsi_panel_mode_switch_to_cmd(display->panel);
if (display->config.panel_mode == DSI_OP_VIDEO_MODE)
dsi_panel_mode_switch_to_vid(display->panel);
} else {
rc = dsi_panel_post_enable(display->panel);
if (rc)
pr_err("[%s] panel post-enable failed, rc=%d\n",
display->name, rc);
}
/* remove the clk vote for CMD mode panels */
if (display->config.panel_mode == DSI_OP_CMD_MODE)
@@ -6826,12 +6852,18 @@ int dsi_display_pre_disable(struct dsi_display *display)
if (display->config.panel_mode == DSI_OP_CMD_MODE)
dsi_display_clk_ctrl(display->dsi_clk_handle,
DSI_ALL_CLKS, DSI_CLK_ON);
if (display->poms_pending) {
if (display->config.panel_mode == DSI_OP_CMD_MODE)
dsi_panel_pre_mode_switch_to_video(display->panel);
rc = dsi_panel_pre_disable(display->panel);
if (rc)
pr_err("[%s] panel pre-disable failed, rc=%d\n",
display->name, rc);
if (display->config.panel_mode == DSI_OP_VIDEO_MODE)
dsi_panel_pre_mode_switch_to_cmd(display->panel);
} else {
rc = dsi_panel_pre_disable(display->panel);
if (rc)
pr_err("[%s] panel pre-disable failed, rc=%d\n",
display->name, rc);
}
mutex_unlock(&display->display_lock);
return rc;
}
@@ -6868,11 +6900,12 @@ int dsi_display_disable(struct dsi_display *display)
rc = -EINVAL;
}
rc = dsi_panel_disable(display->panel);
if (rc)
pr_err("[%s] failed to disable DSI panel, rc=%d\n",
display->name, rc);
if (!display->poms_pending) {
rc = dsi_panel_disable(display->panel);
if (rc)
pr_err("[%s] failed to disable DSI panel, rc=%d\n",
display->name, rc);
}
mutex_unlock(&display->display_lock);
SDE_EVT32(SDE_EVTLOG_FUNC_EXIT);
return rc;
@@ -6911,12 +6944,12 @@ int dsi_display_unprepare(struct dsi_display *display)
if (rc)
pr_err("[%s] display wake up failed, rc=%d\n",
display->name, rc);
rc = dsi_panel_unprepare(display->panel);
if (rc)
pr_err("[%s] panel unprepare failed, rc=%d\n",
display->name, rc);
if (!display->poms_pending) {
rc = dsi_panel_unprepare(display->panel);
if (rc)
pr_err("[%s] panel unprepare failed, rc=%d\n",
display->name, rc);
}
rc = dsi_display_ctrl_host_disable(display);
if (rc)
pr_err("[%s] failed to disable DSI host, rc=%d\n",
@@ -6949,10 +6982,12 @@ int dsi_display_unprepare(struct dsi_display *display)
/* destrory dsi isr set up */
dsi_display_ctrl_isr_configure(display, false);
rc = dsi_panel_post_unprepare(display->panel);
if (rc)
pr_err("[%s] panel post-unprepare failed, rc=%d\n",
display->name, rc);
if (!display->poms_pending) {
rc = dsi_panel_post_unprepare(display->panel);
if (rc)
pr_err("[%s] panel post-unprepare failed, rc=%d\n",
display->name, rc);
}
mutex_unlock(&display->display_lock);