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

Commit d3002314 authored by Sachin Bhayare's avatar Sachin Bhayare Committed by Krishna Manikandan
Browse files

msm: mdss: Add interface to send idle on/off command to panel



This allows the use of different refresh rates during idle and active state
of the panel. This helps in reducing panel power consumption
in idle state.

Change-Id: I83d2d71a210c1ac34dc52c11cab698b19a0089a6
Signed-off-by: default avatarKrishna Manikandan <mkrishn@codeaurora.org>
Signed-off-by: default avatarSachin Bhayare <sachin.bhayare@codeaurora.org>
parent c3cad444
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -64,6 +64,12 @@ Required properties:
- qcom,mdss-dsi-post-panel-on-command:	same as "qcom,mdss-dsi-on-command" except commands are
					sent after displaying an image.

- qcom,mdss-dsi-idle-on-command:	same as "qcom,mdss-dsi-on-command". Set of DCS command
					used for idle mode entry.

- qcom,mdss-dsi-idle-off-command:	same as "qcom,mdss-dsi-on-command". Set of DCS command
					used for idle mode exit.

Note, if a short DCS packet(i.e packet with Byte 0:dcs data type as 05) mentioned in
qcom,mdss-dsi-on-command/qcom,mdss-dsi-off-command stream fails to transmit,
then 3 options can be tried.
+3 −0
Original line number Diff line number Diff line
@@ -447,6 +447,7 @@ struct mdss_dsi_ctrl_pdata {
	bool dsi_irq_line;
	bool dcs_cmd_insert;
	atomic_t te_irq_ready;
	bool idle;

	bool cmd_sync_wait_broadcast;
	bool cmd_sync_wait_trigger;
@@ -470,6 +471,8 @@ struct mdss_dsi_ctrl_pdata {
	struct dsi_panel_cmds post_panel_on_cmds;
	struct dsi_panel_cmds off_cmds;
	struct dsi_panel_cmds status_cmds;
	struct dsi_panel_cmds idle_on_cmds; /* for lp mode */
	struct dsi_panel_cmds idle_off_cmds;
	u32 *status_valid_params;
	u32 *status_cmds_rlen;
	u32 *status_value;
+68 −2
Original line number Diff line number Diff line
@@ -221,6 +221,55 @@ static void mdss_dsi_panel_bklt_dcs(struct mdss_dsi_ctrl_pdata *ctrl, int level)
	mdss_dsi_cmdlist_put(ctrl, &cmdreq);
}

static void mdss_dsi_panel_set_idle_mode(struct mdss_panel_data *pdata,
							bool enable)
{
	struct mdss_dsi_ctrl_pdata *ctrl = NULL;

	if (pdata == NULL) {
		pr_err("%s: Invalid input data\n", __func__);
		return;
	}

	ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata,
						panel_data);

	pr_debug("%s: Idle (%d->%d)\n", __func__, ctrl->idle, enable);

	if (ctrl->idle == enable)
		return;

	if (enable) {
		if (ctrl->idle_on_cmds.cmd_cnt) {
			mdss_dsi_panel_cmds_send(ctrl, &ctrl->idle_on_cmds,
					CMD_REQ_COMMIT);
			ctrl->idle = true;
			pr_debug("Idle on\n");
		}
	} else {
		if (ctrl->idle_off_cmds.cmd_cnt) {
			mdss_dsi_panel_cmds_send(ctrl, &ctrl->idle_off_cmds,
					CMD_REQ_COMMIT);
			ctrl->idle = false;
			pr_debug("Idle off\n");
		}
	}
}

static bool mdss_dsi_panel_get_idle_mode(struct mdss_panel_data *pdata)

{
	struct mdss_dsi_ctrl_pdata *ctrl = NULL;

	if (pdata == NULL) {
		pr_err("%s: Invalid input data\n", __func__);
		return 0;
	}
	ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata,
						panel_data);
	return ctrl->idle;
}

static int mdss_dsi_request_gpios(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
	int rc = 0;
@@ -891,6 +940,8 @@ static int mdss_dsi_panel_off(struct mdss_panel_data *pdata)
	mdss_dsi_panel_off_hdmi(ctrl, pinfo);

end:
	/* clear idle state */
	ctrl->idle = false;
	pr_debug("%s:-\n", __func__);
	return 0;
}
@@ -914,7 +965,11 @@ static int mdss_dsi_panel_low_power_config(struct mdss_panel_data *pdata,
		enable);

	/* Any panel specific low power commands/config */

	/* Control idle mode for panel */
	if (enable)
		mdss_dsi_panel_set_idle_mode(pdata, true);
	else
		mdss_dsi_panel_set_idle_mode(pdata, false);
	pr_debug("%s:-\n", __func__);
	return 0;
}
@@ -2666,6 +2721,17 @@ static int mdss_panel_parse_dt(struct device_node *np,
	mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->off_cmds,
		"qcom,mdss-dsi-off-command", "qcom,mdss-dsi-off-command-state");

	mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->idle_on_cmds,
		"qcom,mdss-dsi-idle-on-command",
		"qcom,mdss-dsi-idle-on-command-state");

	mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->idle_off_cmds,
		"qcom,mdss-dsi-idle-off-command",
		"qcom,mdss-dsi-idle-off-command-state");

	rc = of_property_read_u32(np, "qcom,mdss-dsi-idle-fps", &tmp);
	pinfo->mipi.frame_rate_idle = (!rc ? tmp : 60);

	rc = of_property_read_u32(np, "qcom,adjust-timer-wakeup-ms", &tmp);
	pinfo->adjust_timer_delay_ms = (!rc ? tmp : 0);

@@ -2733,6 +2799,6 @@ int mdss_dsi_panel_init(struct device_node *node,
	ctrl_pdata->low_power_config = mdss_dsi_panel_low_power_config;
	ctrl_pdata->panel_data.set_backlight = mdss_dsi_panel_bl_ctrl;
	ctrl_pdata->switch_mode = mdss_dsi_panel_switch_mode;

	ctrl_pdata->panel_data.get_idle = mdss_dsi_panel_get_idle_mode;
	return 0;
}
+13 −1
Original line number Diff line number Diff line
/* 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
@@ -390,6 +390,7 @@ struct mipi_panel_info {
	char traffic_mode;
	char frame_rate;
	/* command mode */
	char frame_rate_idle;
	char interleave_max;
	char insert_dcs_cmd;
	char wr_mem_continue;
@@ -797,6 +798,7 @@ struct mdss_panel_data {
	 */
	int (*event_handler) (struct mdss_panel_data *pdata, int e, void *arg);
	struct device_node *(*get_fb_node)(struct platform_device *pdev);
	bool (*get_idle)(struct mdss_panel_data *pdata);

	struct list_head timings_list;
	struct mdss_panel_timing *current_timing;
@@ -824,6 +826,10 @@ static inline u32 mdss_panel_get_framerate(struct mdss_panel_info *panel_info,
{
	u32 frame_rate, pixel_total;
	u64 rate;
	struct mdss_panel_data *panel_data =
			container_of(panel_info, typeof(*panel_data),
					panel_info);
	bool idle = false;

	if (panel_info == NULL) {
		frame_rate = DEFAULT_FRAME_RATE;
@@ -834,6 +840,12 @@ static inline u32 mdss_panel_get_framerate(struct mdss_panel_info *panel_info,
	case MIPI_VIDEO_PANEL:
	case MIPI_CMD_PANEL:
		frame_rate = panel_info->mipi.frame_rate;
		if (panel_data->get_idle)
			idle = panel_data->get_idle(panel_data);
		if (idle)
			frame_rate = panel_info->mipi.frame_rate_idle;
		else
			frame_rate = panel_info->mipi.frame_rate;
		break;
	case EDP_PANEL:
		frame_rate = panel_info->edp.frame_rate;