Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2f06b274 authored by Yahui Wang's avatar Yahui Wang Committed by raghavendra ambadas
Browse files

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: default avatarYahui Wang <yahuiw@codeaurora.org>
parent 03e42ff6
Loading
Loading
Loading
Loading
+27 −0
Original line number Original line Diff line number Diff line
@@ -61,6 +61,30 @@ Required properties:
						 transmitted
						 transmitted
					byte 5, 6: 16 bits length in network byte order
					byte 5, 6: 16 bits length in network byte order
					byte 7 and beyond: number byte of payload
					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
- qcom,mdss-dsi-post-panel-on-command:	same as "qcom,mdss-dsi-on-command" except commands are
					sent after displaying an image.
					sent after displaying an image.


@@ -611,6 +635,9 @@ Example:
		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
		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 = [22 01 00 00 00 00 00];
		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
		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-bl-pmic-control-type = "bl_ctrl_wled";
		qcom,mdss-dsi-pan-enable-dynamic-fps;
		qcom,mdss-dsi-pan-enable-dynamic-fps;
		qcom,mdss-dsi-pan-fps-update = "dfps_suspend_resume_mode";
		qcom,mdss-dsi-pan-fps-update = "dfps_suspend_resume_mode";
+55 −1
Original line number Original line Diff line number Diff line
/* 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
 * 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
 * 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];
					05 01 00 00 b4 00 02 10 00];
		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
		qcom,mdss-dsi-off-command-state = "dsi_hs_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-h-sync-pulse = <0>;
		qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
		qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
		qcom,mdss-dsi-lane-map = "lane_map_0123";
		qcom,mdss-dsi-lane-map = "lane_map_0123";
+2 −0
Original line number Original line Diff line number Diff line
@@ -470,6 +470,8 @@ struct mdss_dsi_ctrl_pdata {
	struct dsi_panel_cmds post_dms_on_cmds;
	struct dsi_panel_cmds post_dms_on_cmds;
	struct dsi_panel_cmds post_panel_on_cmds;
	struct dsi_panel_cmds post_panel_on_cmds;
	struct dsi_panel_cmds off_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;
	struct dsi_panel_cmds status_cmds;
	struct dsi_panel_cmds idle_on_cmds; /* for lp mode */
	struct dsi_panel_cmds idle_on_cmds; /* for lp mode */
	struct dsi_panel_cmds idle_off_cmds;
	struct dsi_panel_cmds idle_off_cmds;
+63 −0
Original line number Original line Diff line number Diff line
@@ -161,6 +161,25 @@ int mdss_dsi_panel_cmd_read(struct mdss_dsi_ctrl_pdata *ctrl, char cmd0,
	return mdss_dsi_cmdlist_put(ctrl, &cmdreq);
	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,
static void mdss_dsi_panel_cmds_send(struct mdss_dsi_ctrl_pdata *ctrl,
			struct dsi_panel_cmds *pcmds, u32 flags)
			struct dsi_panel_cmds *pcmds, u32 flags)
{
{
@@ -665,6 +684,38 @@ end:
	return 0;
	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_off_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,
static void mdss_dsi_panel_switch_mode(struct mdss_panel_data *pdata,
							int mode)
							int mode)
{
{
@@ -838,6 +889,9 @@ static int mdss_dsi_panel_on(struct mdss_panel_data *pdata)


	mdss_dsi_panel_on_hdmi(ctrl, pinfo);
	mdss_dsi_panel_on_hdmi(ctrl, pinfo);


	/* Ensure low persistence mode is set as before */
	mdss_dsi_panel_apply_display_setting(pdata, pinfo->persist_mode);

end:
end:
	pr_debug("%s:-\n", __func__);
	pr_debug("%s:-\n", __func__);
	return ret;
	return ret;
@@ -2019,6 +2073,12 @@ static int mdss_dsi_parse_panel_features(struct device_node *np,
					__func__, __LINE__);
					__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;
	return 0;
}
}


@@ -2807,12 +2867,15 @@ int mdss_dsi_panel_init(struct device_node *node,
	pinfo->dynamic_switch_pending = false;
	pinfo->dynamic_switch_pending = false;
	pinfo->is_lpm_mode = false;
	pinfo->is_lpm_mode = false;
	pinfo->esd_rdy = false;
	pinfo->esd_rdy = false;
	pinfo->persist_mode = false;


	ctrl_pdata->on = mdss_dsi_panel_on;
	ctrl_pdata->on = mdss_dsi_panel_on;
	ctrl_pdata->post_panel_on = mdss_dsi_post_panel_on;
	ctrl_pdata->post_panel_on = mdss_dsi_post_panel_on;
	ctrl_pdata->off = mdss_dsi_panel_off;
	ctrl_pdata->off = mdss_dsi_panel_off;
	ctrl_pdata->low_power_config = mdss_dsi_panel_low_power_config;
	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.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;
	ctrl_pdata->switch_mode = mdss_dsi_panel_switch_mode;
	ctrl_pdata->panel_data.get_idle = mdss_dsi_panel_get_idle_mode;
	ctrl_pdata->panel_data.get_idle = mdss_dsi_panel_get_idle_mode;
	return 0;
	return 0;
+79 −3
Original line number Original line Diff line number Diff line
@@ -816,6 +816,73 @@ static ssize_t mdss_fb_get_dfps_mode(struct device *dev,
	return ret;
	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_type, S_IRUGO, mdss_fb_get_type, NULL);
static DEVICE_ATTR(msm_fb_split, S_IRUGO | S_IWUSR, mdss_fb_show_split,
static DEVICE_ATTR(msm_fb_split, S_IRUGO | S_IWUSR, mdss_fb_show_split,
					mdss_fb_store_split);
					mdss_fb_store_split);
@@ -834,6 +901,8 @@ static DEVICE_ATTR(msm_fb_dfps_mode, S_IRUGO | S_IWUSR,
	mdss_fb_get_dfps_mode, mdss_fb_change_dfps_mode);
	mdss_fb_get_dfps_mode, mdss_fb_change_dfps_mode);
static DEVICE_ATTR(measured_fps, S_IRUGO | S_IWUSR | S_IWGRP,
static DEVICE_ATTR(measured_fps, S_IRUGO | S_IWUSR | S_IWGRP,
	mdss_fb_get_fps_info, NULL);
	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[] = {
static struct attribute *mdss_fb_attrs[] = {
	&dev_attr_msm_fb_type.attr,
	&dev_attr_msm_fb_type.attr,
	&dev_attr_msm_fb_split.attr,
	&dev_attr_msm_fb_split.attr,
@@ -846,6 +915,7 @@ static struct attribute *mdss_fb_attrs[] = {
	&dev_attr_msm_fb_panel_status.attr,
	&dev_attr_msm_fb_panel_status.attr,
	&dev_attr_msm_fb_dfps_mode.attr,
	&dev_attr_msm_fb_dfps_mode.attr,
	&dev_attr_measured_fps.attr,
	&dev_attr_measured_fps.attr,
	&dev_attr_msm_fb_persist_mode.attr,
	NULL,
	NULL,
};
};


@@ -1196,6 +1266,7 @@ static int mdss_fb_probe(struct platform_device *pdev)
	INIT_LIST_HEAD(&mfd->file_list);
	INIT_LIST_HEAD(&mfd->file_list);


	mutex_init(&mfd->bl_lock);
	mutex_init(&mfd->bl_lock);
	mutex_init(&mfd->mdss_sysfs_lock);
	mutex_init(&mfd->switch_lock);
	mutex_init(&mfd->switch_lock);


	fbi_list[fbi_list_index++] = fbi;
	fbi_list[fbi_list_index++] = fbi;
@@ -1962,7 +2033,7 @@ static int mdss_fb_blank(int blank_mode, struct fb_info *info)
			mfd->index, ret);
			mfd->index, ret);
		return ret;
		return ret;
	}
	}

	mutex_lock(&mfd->mdss_sysfs_lock);
	if (mfd->op_enable == 0) {
	if (mfd->op_enable == 0) {
		if (blank_mode == FB_BLANK_UNBLANK)
		if (blank_mode == FB_BLANK_UNBLANK)
			mfd->suspend.panel_power_state = MDSS_PANEL_POWER_ON;
			mfd->suspend.panel_power_state = MDSS_PANEL_POWER_ON;
@@ -1972,7 +2043,8 @@ static int mdss_fb_blank(int blank_mode, struct fb_info *info)
			mfd->suspend.panel_power_state = MDSS_PANEL_POWER_LP1;
			mfd->suspend.panel_power_state = MDSS_PANEL_POWER_LP1;
		else
		else
			mfd->suspend.panel_power_state = MDSS_PANEL_POWER_OFF;
			mfd->suspend.panel_power_state = MDSS_PANEL_POWER_OFF;
		return 0;
		ret = 0;
		goto end;
	}
	}
	pr_debug("mode: %d\n", blank_mode);
	pr_debug("mode: %d\n", blank_mode);


@@ -1986,7 +2058,11 @@ static int mdss_fb_blank(int blank_mode, struct fb_info *info)
		pdata->panel_info.is_lpm_mode = false;
		pdata->panel_info.is_lpm_mode = 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)
static inline int mdss_fb_create_ion_client(struct msm_fb_data_type *mfd)
Loading