msm: mdss: Add low persistence mode support for display
Snapshot of low persistence mode changes as of 26cfe58bd94a ("msm: mdss: Add support for low persistence display mode") and a805a3e1e791 ("arm64/dts: angler: Don't blank screen when leaving low persistence mode"), to add low persistence mode support for display. Also, add some changes to optimize the implementation for LP mode and fix crash issue when VR APP is up. CRs-Fixed: 1104888 1108207 Change-Id: I509fb5c87d93e2416882942a226cb9b48bc1d3bf Signed-off-by: Yahui Wang <yahuiw@codeaurora.org>
This commit is contained in:
parent
d9ac8efbd9
commit
e6819350df
7 changed files with 246 additions and 6 deletions
|
@ -61,6 +61,30 @@ Required properties:
|
|||
transmitted
|
||||
byte 5, 6: 16 bits length in network byte order
|
||||
byte 7 and beyond: number byte of payload
|
||||
- qcom,mdss-dsi-lp-mode-on: This is used to enable display low persistence mode.
|
||||
A byte stream formed by multiple dcs packets base on
|
||||
qcom dsi controller protocol.
|
||||
byte 0: dcs data type
|
||||
byte 1: set to indicate this is an individual packet
|
||||
(no chain)
|
||||
byte 2: virtual channel number
|
||||
byte 3: expect ack from client (dcs read command)
|
||||
byte 4: wait number of specified ms after dcs command
|
||||
transmitted
|
||||
byte 5, 6: 16 bits length in network byte order
|
||||
byte 7 and beyond: number byte of payload
|
||||
- qcom,mdss-dsi-lp-mode-off: This is used to disable display low persistence mode.
|
||||
A byte stream formed by multiple dcs packets base on
|
||||
qcom dsi controller protocol.
|
||||
byte 0: dcs data type
|
||||
byte 1: set to indicate this is an individual packet
|
||||
(no chain)
|
||||
byte 2: virtual channel number
|
||||
byte 3: expect ack from client (dcs read command)
|
||||
byte 4: wait number of specified ms after dcs command
|
||||
transmitted
|
||||
byte 5, 6: 16 bits length in network byte order
|
||||
byte 7 and beyond: number byte of payload
|
||||
- qcom,mdss-dsi-post-panel-on-command: same as "qcom,mdss-dsi-on-command" except commands are
|
||||
sent after displaying an image.
|
||||
|
||||
|
@ -648,6 +672,9 @@ Example:
|
|||
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
|
||||
qcom,mdss-dsi-off-command = [22 01 00 00 00 00 00];
|
||||
qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
|
||||
qcom,mdss-dsi-lp-mode-on = [32 01 00 00 00 00 02 00 00
|
||||
29 01 00 00 10 00 02 FF 99];
|
||||
qcom,mdss-dsi-lp-mode-off = [22 01 00 00 00 00 00];
|
||||
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
|
||||
qcom,mdss-dsi-pan-enable-dynamic-fps;
|
||||
qcom,mdss-dsi-pan-fps-update = "dfps_suspend_resume_mode";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -57,6 +57,60 @@
|
|||
05 01 00 00 b4 00 02 10 00];
|
||||
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
|
||||
qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
|
||||
qcom,mdss-dsi-lp-mode-on = [39 00 00 00 05 00 03 f0 5a 5a
|
||||
39 00 00 00 05 00 03 f1 5a 5a
|
||||
39 00 00 00 05 00 03 fc 5a 5a
|
||||
39 00 00 00 05 00 02 b0 17
|
||||
39 00 00 00 05 00 02 cb 10
|
||||
39 00 00 00 05 00 02 b0 2d
|
||||
39 00 00 00 05 00 02 cb cd
|
||||
39 00 00 00 05 00 02 b0 0e
|
||||
39 00 00 00 05 00 02 cb 02
|
||||
39 00 00 00 05 00 02 b0 0f
|
||||
39 00 00 00 05 00 02 cb 09
|
||||
39 00 00 00 05 00 02 b0 02
|
||||
39 00 00 00 05 00 02 f2 c9
|
||||
39 00 00 00 05 00 02 b0 03
|
||||
39 00 00 00 05 00 02 f2 c0
|
||||
39 00 00 00 05 00 02 b0 03
|
||||
39 00 00 00 05 00 02 f4 aa
|
||||
39 00 00 00 05 00 02 b0 08
|
||||
39 00 00 00 05 00 02 b1 30
|
||||
39 00 00 00 05 00 02 b0 09
|
||||
39 00 00 00 05 00 02 b1 0a
|
||||
39 00 00 00 05 00 02 b0 0d
|
||||
39 00 00 00 05 00 02 b1 10
|
||||
39 00 00 00 05 00 02 b0 00
|
||||
39 00 00 00 05 00 02 f7 03
|
||||
39 00 00 00 05 00 02 fe 30
|
||||
39 01 00 00 05 00 02 fe b0];
|
||||
qcom,mdss-dsi-lp-mode-off = [39 00 00 00 05 00 03 f0 5a 5a
|
||||
39 00 00 00 05 00 03 f1 5a 5a
|
||||
39 00 00 00 05 00 03 fc 5a 5a
|
||||
39 00 00 00 05 00 02 b0 2d
|
||||
39 00 00 00 05 00 02 cb 4d
|
||||
39 00 00 00 05 00 02 b0 17
|
||||
39 00 00 00 05 00 02 cb 04
|
||||
39 00 00 00 05 00 02 b0 0e
|
||||
39 00 00 00 05 00 02 cb 06
|
||||
39 00 00 00 05 00 02 b0 0f
|
||||
39 00 00 00 05 00 02 cb 05
|
||||
39 00 00 00 05 00 02 b0 02
|
||||
39 00 00 00 05 00 02 f2 b8
|
||||
39 00 00 00 05 00 02 b0 03
|
||||
39 00 00 00 05 00 02 f2 80
|
||||
39 00 00 00 05 00 02 b0 03
|
||||
39 00 00 00 05 00 02 f4 8a
|
||||
39 00 00 00 05 00 02 b0 08
|
||||
39 00 00 00 05 00 02 b1 10
|
||||
39 00 00 00 05 00 02 b0 09
|
||||
39 00 00 00 05 00 02 b1 0a
|
||||
39 00 00 00 05 00 02 b0 0d
|
||||
39 00 00 00 05 00 02 b1 80
|
||||
39 00 00 00 05 00 02 b0 00
|
||||
39 00 00 00 05 00 02 f7 03
|
||||
39 00 00 00 05 00 02 fe 30
|
||||
39 01 00 00 05 00 02 fe b0];
|
||||
qcom,mdss-dsi-h-sync-pulse = <0>;
|
||||
qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
|
||||
qcom,mdss-dsi-lane-map = "lane_map_0123";
|
||||
|
|
|
@ -487,6 +487,8 @@ struct mdss_dsi_ctrl_pdata {
|
|||
struct dsi_panel_cmds post_dms_on_cmds;
|
||||
struct dsi_panel_cmds post_panel_on_cmds;
|
||||
struct dsi_panel_cmds off_cmds;
|
||||
struct dsi_panel_cmds lp_on_cmds;
|
||||
struct dsi_panel_cmds lp_off_cmds;
|
||||
struct dsi_panel_cmds status_cmds;
|
||||
u32 *status_valid_params;
|
||||
u32 *status_cmds_rlen;
|
||||
|
|
|
@ -160,6 +160,27 @@ int mdss_dsi_panel_cmd_read(struct mdss_dsi_ctrl_pdata *ctrl, char cmd0,
|
|||
return mdss_dsi_cmdlist_put(ctrl, &cmdreq);
|
||||
}
|
||||
|
||||
static void mdss_dsi_panel_apply_settings(struct mdss_dsi_ctrl_pdata *ctrl,
|
||||
struct dsi_panel_cmds *pcmds)
|
||||
{
|
||||
struct dcs_cmd_req cmdreq;
|
||||
struct mdss_panel_info *pinfo;
|
||||
|
||||
pinfo = &(ctrl->panel_data.panel_info);
|
||||
if ((pinfo->dcs_cmd_by_left) && (ctrl->ndx != DSI_CTRL_LEFT))
|
||||
return;
|
||||
|
||||
memset(&cmdreq, 0, sizeof(cmdreq));
|
||||
cmdreq.cmds = pcmds->cmds;
|
||||
cmdreq.cmds_cnt = pcmds->cmd_cnt;
|
||||
cmdreq.flags = CMD_REQ_COMMIT;
|
||||
cmdreq.rlen = 0;
|
||||
cmdreq.cb = NULL;
|
||||
|
||||
mdss_dsi_cmdlist_put(ctrl, &cmdreq);
|
||||
}
|
||||
|
||||
|
||||
static void mdss_dsi_panel_cmds_send(struct mdss_dsi_ctrl_pdata *ctrl,
|
||||
struct dsi_panel_cmds *pcmds, u32 flags)
|
||||
{
|
||||
|
@ -660,6 +681,38 @@ end:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mdss_dsi_panel_apply_display_setting(struct mdss_panel_data *pdata,
|
||||
u32 mode)
|
||||
{
|
||||
struct mdss_dsi_ctrl_pdata *ctrl = NULL;
|
||||
struct dsi_panel_cmds *lp_on_cmds;
|
||||
struct dsi_panel_cmds *lp_off_cmds;
|
||||
|
||||
if (pdata == NULL) {
|
||||
pr_err("%s: Invalid input data\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata,
|
||||
panel_data);
|
||||
|
||||
lp_on_cmds = &ctrl->lp_on_cmds;
|
||||
lp_off_cmds = &ctrl->lp_off_cmds;
|
||||
|
||||
/* Apply display settings for low-persistence mode */
|
||||
if ((mode == MDSS_PANEL_LOW_PERSIST_MODE_ON) &&
|
||||
(lp_on_cmds->cmd_cnt))
|
||||
mdss_dsi_panel_apply_settings(ctrl, lp_on_cmds);
|
||||
else if ((mode == MDSS_PANEL_LOW_PERSIST_MODE_OFF) &&
|
||||
(lp_on_cmds->cmd_cnt))
|
||||
mdss_dsi_panel_apply_settings(ctrl, lp_off_cmds);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
pr_debug("%s: Persistence mode %d applied\n", __func__, mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mdss_dsi_panel_switch_mode(struct mdss_panel_data *pdata,
|
||||
int mode)
|
||||
{
|
||||
|
@ -822,6 +875,10 @@ static int mdss_dsi_panel_on(struct mdss_panel_data *pdata)
|
|||
|
||||
if (ctrl->ds_registered)
|
||||
mdss_dba_utils_video_on(pinfo->dba_data, pinfo);
|
||||
|
||||
/* Ensure low persistence mode is set as before */
|
||||
mdss_dsi_panel_apply_display_setting(pdata, pinfo->persist_mode);
|
||||
|
||||
end:
|
||||
pr_debug("%s:-\n", __func__);
|
||||
return ret;
|
||||
|
@ -2046,6 +2103,12 @@ static int mdss_dsi_parse_panel_features(struct device_node *np,
|
|||
__func__, __LINE__);
|
||||
}
|
||||
|
||||
mdss_dsi_parse_dcs_cmds(np, &ctrl->lp_on_cmds,
|
||||
"qcom,mdss-dsi-lp-mode-on", NULL);
|
||||
|
||||
mdss_dsi_parse_dcs_cmds(np, &ctrl->lp_off_cmds,
|
||||
"qcom,mdss-dsi-lp-mode-off", NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2796,12 +2859,15 @@ int mdss_dsi_panel_init(struct device_node *node,
|
|||
pinfo->dynamic_switch_pending = false;
|
||||
pinfo->is_lpm_mode = false;
|
||||
pinfo->esd_rdy = false;
|
||||
pinfo->persist_mode = false;
|
||||
|
||||
ctrl_pdata->on = mdss_dsi_panel_on;
|
||||
ctrl_pdata->post_panel_on = mdss_dsi_post_panel_on;
|
||||
ctrl_pdata->off = mdss_dsi_panel_off;
|
||||
ctrl_pdata->low_power_config = mdss_dsi_panel_low_power_config;
|
||||
ctrl_pdata->panel_data.set_backlight = mdss_dsi_panel_bl_ctrl;
|
||||
ctrl_pdata->panel_data.apply_display_setting =
|
||||
mdss_dsi_panel_apply_display_setting;
|
||||
ctrl_pdata->switch_mode = mdss_dsi_panel_switch_mode;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Core MDSS framebuffer driver.
|
||||
*
|
||||
* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2007 Google Incorporated
|
||||
* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
|
@ -823,6 +823,74 @@ static ssize_t mdss_fb_get_dfps_mode(struct device *dev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t mdss_fb_change_persist_mode(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t len)
|
||||
{
|
||||
struct fb_info *fbi = dev_get_drvdata(dev);
|
||||
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
|
||||
struct mdss_panel_info *pinfo = NULL;
|
||||
struct mdss_panel_data *pdata;
|
||||
int ret = 0;
|
||||
u32 persist_mode;
|
||||
|
||||
if (!mfd || !mfd->panel_info) {
|
||||
pr_err("%s: Panel info is NULL!\n", __func__);
|
||||
return len;
|
||||
}
|
||||
|
||||
pinfo = mfd->panel_info;
|
||||
|
||||
if (kstrtouint(buf, 0, &persist_mode)) {
|
||||
pr_err("kstrtouint buf error!\n");
|
||||
return len;
|
||||
}
|
||||
|
||||
mutex_lock(&mfd->mdss_sysfs_lock);
|
||||
if (mdss_panel_is_power_off(mfd->panel_power_state)) {
|
||||
pinfo->persist_mode = persist_mode;
|
||||
goto end;
|
||||
}
|
||||
|
||||
mutex_lock(&mfd->bl_lock);
|
||||
|
||||
pdata = dev_get_platdata(&mfd->pdev->dev);
|
||||
if ((pdata) && (pdata->apply_display_setting))
|
||||
ret = pdata->apply_display_setting(pdata, persist_mode);
|
||||
|
||||
mutex_unlock(&mfd->bl_lock);
|
||||
|
||||
if (!ret) {
|
||||
pr_debug("%s: Persist mode %d\n", __func__, persist_mode);
|
||||
pinfo->persist_mode = persist_mode;
|
||||
}
|
||||
|
||||
end:
|
||||
mutex_unlock(&mfd->mdss_sysfs_lock);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t mdss_fb_get_persist_mode(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct fb_info *fbi = dev_get_drvdata(dev);
|
||||
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
|
||||
struct mdss_panel_data *pdata;
|
||||
struct mdss_panel_info *pinfo;
|
||||
int ret;
|
||||
|
||||
pdata = dev_get_platdata(&mfd->pdev->dev);
|
||||
if (!pdata) {
|
||||
pr_err("no panel connected!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
pinfo = &pdata->panel_info;
|
||||
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%d\n", pinfo->persist_mode);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(msm_fb_type, S_IRUGO, mdss_fb_get_type, NULL);
|
||||
static DEVICE_ATTR(msm_fb_split, S_IRUGO | S_IWUSR, mdss_fb_show_split,
|
||||
mdss_fb_store_split);
|
||||
|
@ -841,6 +909,8 @@ static DEVICE_ATTR(msm_fb_dfps_mode, S_IRUGO | S_IWUSR,
|
|||
mdss_fb_get_dfps_mode, mdss_fb_change_dfps_mode);
|
||||
static DEVICE_ATTR(measured_fps, S_IRUGO | S_IWUSR | S_IWGRP,
|
||||
mdss_fb_get_fps_info, NULL);
|
||||
static DEVICE_ATTR(msm_fb_persist_mode, S_IRUGO | S_IWUSR,
|
||||
mdss_fb_get_persist_mode, mdss_fb_change_persist_mode);
|
||||
static struct attribute *mdss_fb_attrs[] = {
|
||||
&dev_attr_msm_fb_type.attr,
|
||||
&dev_attr_msm_fb_split.attr,
|
||||
|
@ -853,6 +923,7 @@ static struct attribute *mdss_fb_attrs[] = {
|
|||
&dev_attr_msm_fb_panel_status.attr,
|
||||
&dev_attr_msm_fb_dfps_mode.attr,
|
||||
&dev_attr_measured_fps.attr,
|
||||
&dev_attr_msm_fb_persist_mode.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
@ -1203,6 +1274,7 @@ static int mdss_fb_probe(struct platform_device *pdev)
|
|||
INIT_LIST_HEAD(&mfd->file_list);
|
||||
|
||||
mutex_init(&mfd->bl_lock);
|
||||
mutex_init(&mfd->mdss_sysfs_lock);
|
||||
mutex_init(&mfd->switch_lock);
|
||||
|
||||
fbi_list[fbi_list_index++] = fbi;
|
||||
|
@ -1971,6 +2043,8 @@ static int mdss_fb_blank(int blank_mode, struct fb_info *info)
|
|||
return ret;
|
||||
}
|
||||
|
||||
mutex_lock(&mfd->mdss_sysfs_lock);
|
||||
|
||||
if (mfd->op_enable == 0) {
|
||||
if (blank_mode == FB_BLANK_UNBLANK)
|
||||
mfd->suspend.panel_power_state = MDSS_PANEL_POWER_ON;
|
||||
|
@ -1980,7 +2054,9 @@ static int mdss_fb_blank(int blank_mode, struct fb_info *info)
|
|||
mfd->suspend.panel_power_state = MDSS_PANEL_POWER_LP1;
|
||||
else
|
||||
mfd->suspend.panel_power_state = MDSS_PANEL_POWER_OFF;
|
||||
return 0;
|
||||
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
pr_debug("mode: %d\n", blank_mode);
|
||||
|
||||
|
@ -1997,7 +2073,12 @@ static int mdss_fb_blank(int blank_mode, struct fb_info *info)
|
|||
if (pdata->panel_disable_mode)
|
||||
mdss_mdp_enable_panel_disable_mode(mfd, false);
|
||||
|
||||
return mdss_fb_blank_sub(blank_mode, info, mfd->op_enable);
|
||||
ret = mdss_fb_blank_sub(blank_mode, info, mfd->op_enable);
|
||||
|
||||
end:
|
||||
mutex_unlock(&mfd->mdss_sysfs_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int mdss_fb_create_ion_client(struct msm_fb_data_type *mfd)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -310,6 +310,7 @@ struct msm_fb_data_type {
|
|||
bool allow_bl_update;
|
||||
u32 bl_level_scaled;
|
||||
struct mutex bl_lock;
|
||||
struct mutex mdss_sysfs_lock;
|
||||
bool ipc_resume;
|
||||
|
||||
struct platform_device *pdev;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -117,6 +117,11 @@ enum {
|
|||
MDSS_PANEL_BLANK_LOW_POWER,
|
||||
};
|
||||
|
||||
enum {
|
||||
MDSS_PANEL_LOW_PERSIST_MODE_OFF = 0,
|
||||
MDSS_PANEL_LOW_PERSIST_MODE_ON,
|
||||
};
|
||||
|
||||
enum {
|
||||
MODE_GPIO_NOT_VALID = 0,
|
||||
MODE_SEL_DUAL_PORT,
|
||||
|
@ -892,6 +897,9 @@ struct mdss_panel_info {
|
|||
/* debugfs structure for the panel */
|
||||
struct mdss_panel_debugfs_info *debugfs_info;
|
||||
|
||||
/* persistence mode on/off */
|
||||
bool persist_mode;
|
||||
|
||||
/* stores initial adaptive variable refresh vtotal value */
|
||||
u32 saved_avr_vtotal;
|
||||
|
||||
|
@ -936,6 +944,7 @@ struct mdss_panel_timing {
|
|||
struct mdss_panel_data {
|
||||
struct mdss_panel_info panel_info;
|
||||
void (*set_backlight) (struct mdss_panel_data *pdata, u32 bl_level);
|
||||
int (*apply_display_setting)(struct mdss_panel_data *pdata, u32 mode);
|
||||
unsigned char *mmss_cc_base;
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue