Merge "msm: mdss: Add low persistence mode support for display"

This commit is contained in:
Linux Build Service Account 2017-01-28 08:41:41 -08:00 committed by Gerrit - the friendly Code Review server
commit 8ba01a8781
7 changed files with 245 additions and 5 deletions

View file

@ -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";

View file

@ -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";

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

@ -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;

View file

@ -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,
@ -894,6 +899,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;
@ -938,6 +946,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;
/**