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>
このコミットが含まれているのは:

committed by
Gerrit - the friendly Code Review server

コミット
21edecd3b1
@@ -1360,6 +1360,7 @@ static int dsi_panel_parse_panel_mode(struct dsi_panel *panel)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dsi_parser_utils *utils = &panel->utils;
|
||||
bool panel_mode_switch_enabled;
|
||||
enum dsi_op_mode panel_mode;
|
||||
const char *mode;
|
||||
|
||||
@@ -1378,7 +1379,13 @@ static int dsi_panel_parse_panel_mode(struct dsi_panel *panel)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (panel_mode == DSI_OP_VIDEO_MODE) {
|
||||
panel_mode_switch_enabled = utils->read_bool(utils->data,
|
||||
"qcom,mdss-dsi-panel-mode-switch");
|
||||
|
||||
pr_info("%s: panel operating mode switch feature %s\n", __func__,
|
||||
(panel_mode_switch_enabled ? "enabled" : "disabled"));
|
||||
|
||||
if (panel_mode == DSI_OP_VIDEO_MODE || panel_mode_switch_enabled) {
|
||||
rc = dsi_panel_parse_video_host_config(&panel->video_config,
|
||||
utils,
|
||||
panel->name);
|
||||
@@ -1389,7 +1396,7 @@ static int dsi_panel_parse_panel_mode(struct dsi_panel *panel)
|
||||
}
|
||||
}
|
||||
|
||||
if (panel_mode == DSI_OP_CMD_MODE) {
|
||||
if (panel_mode == DSI_OP_CMD_MODE || panel_mode_switch_enabled) {
|
||||
rc = dsi_panel_parse_cmd_host_config(&panel->cmd_config,
|
||||
utils,
|
||||
panel->name);
|
||||
@@ -1401,6 +1408,7 @@ static int dsi_panel_parse_panel_mode(struct dsi_panel *panel)
|
||||
}
|
||||
|
||||
panel->panel_mode = panel_mode;
|
||||
panel->panel_mode_switch_enabled = panel_mode_switch_enabled;
|
||||
error:
|
||||
return rc;
|
||||
}
|
||||
@@ -2654,6 +2662,33 @@ static int dsi_panel_parse_partial_update_caps(struct dsi_display_mode *mode,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dsi_panel_parse_panel_mode_caps(struct dsi_display_mode *mode,
|
||||
struct dsi_parser_utils *utils)
|
||||
{
|
||||
bool vid_mode_support, cmd_mode_support;
|
||||
|
||||
if (!mode || !mode->priv_info) {
|
||||
pr_err("invalid arguments\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vid_mode_support = utils->read_bool(utils->data,
|
||||
"qcom,mdss-dsi-video-mode");
|
||||
|
||||
cmd_mode_support = utils->read_bool(utils->data,
|
||||
"qcom,mdss-dsi-cmd-mode");
|
||||
|
||||
if (cmd_mode_support)
|
||||
mode->panel_mode = DSI_OP_CMD_MODE;
|
||||
else if (vid_mode_support)
|
||||
mode->panel_mode = DSI_OP_VIDEO_MODE;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
static int dsi_panel_parse_dms_info(struct dsi_panel *panel)
|
||||
{
|
||||
int dms_enabled;
|
||||
@@ -3340,6 +3375,17 @@ int dsi_panel_get_mode(struct dsi_panel *panel,
|
||||
rc = dsi_panel_parse_partial_update_caps(mode, utils);
|
||||
if (rc)
|
||||
pr_err("failed to partial update caps, rc=%d\n", rc);
|
||||
|
||||
if (panel->panel_mode_switch_enabled) {
|
||||
rc = dsi_panel_parse_panel_mode_caps(mode, utils);
|
||||
if (rc) {
|
||||
pr_err("PMS: failed to parse panel mode\n");
|
||||
rc = 0;
|
||||
mode->panel_mode = panel->panel_mode;
|
||||
}
|
||||
} else {
|
||||
mode->panel_mode = panel->panel_mode;
|
||||
}
|
||||
}
|
||||
goto done;
|
||||
|
||||
@@ -3698,6 +3744,86 @@ int dsi_panel_send_roi_dcs(struct dsi_panel *panel, int ctrl_idx,
|
||||
return rc;
|
||||
}
|
||||
|
||||
int dsi_panel_pre_mode_switch_to_video(struct dsi_panel *panel)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!panel) {
|
||||
pr_err("Invalid params\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&panel->panel_lock);
|
||||
|
||||
rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_CMD_TO_VID_SWITCH);
|
||||
if (rc)
|
||||
pr_err("[%s] failed to send DSI_CMD_SET_CMD_TO_VID_SWITCH cmds, rc=%d\n",
|
||||
panel->name, rc);
|
||||
|
||||
mutex_unlock(&panel->panel_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int dsi_panel_pre_mode_switch_to_cmd(struct dsi_panel *panel)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!panel) {
|
||||
pr_err("Invalid params\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&panel->panel_lock);
|
||||
|
||||
rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_VID_TO_CMD_SWITCH);
|
||||
if (rc)
|
||||
pr_err("[%s] failed to send DSI_CMD_SET_CMD_TO_VID_SWITCH cmds, rc=%d\n",
|
||||
panel->name, rc);
|
||||
|
||||
mutex_unlock(&panel->panel_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int dsi_panel_mode_switch_to_cmd(struct dsi_panel *panel)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!panel) {
|
||||
pr_err("Invalid params\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&panel->panel_lock);
|
||||
|
||||
rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_POST_VID_TO_CMD_SWITCH);
|
||||
if (rc)
|
||||
pr_err("[%s] failed to send DSI_CMD_SET_CMD_TO_VID_SWITCH cmds, rc=%d\n",
|
||||
panel->name, rc);
|
||||
|
||||
mutex_unlock(&panel->panel_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int dsi_panel_mode_switch_to_vid(struct dsi_panel *panel)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!panel) {
|
||||
pr_err("Invalid params\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&panel->panel_lock);
|
||||
|
||||
rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_POST_CMD_TO_VID_SWITCH);
|
||||
if (rc)
|
||||
pr_err("[%s] failed to send DSI_CMD_SET_CMD_TO_VID_SWITCH cmds, rc=%d\n",
|
||||
panel->name, rc);
|
||||
|
||||
mutex_unlock(&panel->panel_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int dsi_panel_switch(struct dsi_panel *panel)
|
||||
{
|
||||
int rc = 0;
|
||||
|
新しいイシューから参照
ユーザーをブロックする