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

Commit d54b69e2 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "disp: msm: Add support for seamless panel operating mode switch"

parents 8b3b1d3f 21edecd3
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -74,6 +74,8 @@ enum dsi_op_mode {
 * @DSI_MODE_FLAG_DMS: Seamless transition is dynamic mode switch
 * @DSI_MODE_FLAG_DMS: Seamless transition is dynamic mode switch
 * @DSI_MODE_FLAG_VRR: Seamless transition is DynamicFPS.
 * @DSI_MODE_FLAG_VRR: Seamless transition is DynamicFPS.
 *                     New timing values are sent from DAL.
 *                     New timing values are sent from DAL.
 * @DSI_MODE_FLAG_POMS:
 *         Seamless transition is dynamic panel operating mode switch
 */
 */
enum dsi_mode_flags {
enum dsi_mode_flags {
	DSI_MODE_FLAG_SEAMLESS			= BIT(0),
	DSI_MODE_FLAG_SEAMLESS			= BIT(0),
@@ -81,6 +83,7 @@ enum dsi_mode_flags {
	DSI_MODE_FLAG_VBLANK_PRE_MODESET	= BIT(2),
	DSI_MODE_FLAG_VBLANK_PRE_MODESET	= BIT(2),
	DSI_MODE_FLAG_DMS			= BIT(3),
	DSI_MODE_FLAG_DMS			= BIT(3),
	DSI_MODE_FLAG_VRR			= BIT(4),
	DSI_MODE_FLAG_VRR			= BIT(4),
	DSI_MODE_FLAG_POMS			= BIT(5),
};
};


/**
/**
@@ -555,12 +558,14 @@ struct dsi_display_mode_priv_info {
 * @timing:         Timing parameters for the panel.
 * @timing:         Timing parameters for the panel.
 * @pixel_clk_khz:  Pixel clock in Khz.
 * @pixel_clk_khz:  Pixel clock in Khz.
 * @dsi_mode_flags: Flags to signal other drm components via private flags
 * @dsi_mode_flags: Flags to signal other drm components via private flags
 * @panel_mode:      Panel mode
 * @priv_info:      Mode private info
 * @priv_info:      Mode private info
 */
 */
struct dsi_display_mode {
struct dsi_display_mode {
	struct dsi_mode_info timing;
	struct dsi_mode_info timing;
	u32 pixel_clk_khz;
	u32 pixel_clk_khz;
	u32 dsi_mode_flags;
	u32 dsi_mode_flags;
	enum dsi_op_mode panel_mode;
	struct dsi_display_mode_priv_info *priv_info;
	struct dsi_display_mode_priv_info *priv_info;
};
};


+68 −33
Original line number Original line Diff line number Diff line
@@ -3971,6 +3971,10 @@ static int dsi_display_set_mode_sub(struct dsi_display *display,
		return -EINVAL;
		return -EINVAL;
	}
	}


	if (mode->dsi_mode_flags & DSI_MODE_FLAG_POMS) {
		display->config.panel_mode = mode->panel_mode;
		display->panel->panel_mode = mode->panel_mode;
	}
	rc = dsi_panel_get_host_cfg_for_mode(display->panel,
	rc = dsi_panel_get_host_cfg_for_mode(display->panel,
					     mode,
					     mode,
					     &display->config);
					     &display->config);
@@ -5040,6 +5044,7 @@ static int dsi_display_ext_get_info(struct drm_connector *connector,


	info->capabilities |= (MSM_DISPLAY_CAP_VID_MODE |
	info->capabilities |= (MSM_DISPLAY_CAP_VID_MODE |
			MSM_DISPLAY_CAP_EDID | MSM_DISPLAY_CAP_HOT_PLUG);
			MSM_DISPLAY_CAP_EDID | MSM_DISPLAY_CAP_HOT_PLUG);
	info->curr_panel_mode = MSM_DISPLAY_VIDEO_MODE;


	mutex_unlock(&display->display_lock);
	mutex_unlock(&display->display_lock);
	return 0;
	return 0;
@@ -5403,10 +5408,16 @@ int dsi_display_get_info(struct drm_connector *connector,


	switch (display->panel->panel_mode) {
	switch (display->panel->panel_mode) {
	case DSI_OP_VIDEO_MODE:
	case DSI_OP_VIDEO_MODE:
		info->curr_panel_mode = MSM_DISPLAY_VIDEO_MODE;
		info->capabilities |= MSM_DISPLAY_CAP_VID_MODE;
		info->capabilities |= MSM_DISPLAY_CAP_VID_MODE;
		if (display->panel->panel_mode_switch_enabled)
			info->capabilities |= MSM_DISPLAY_CAP_CMD_MODE;
		break;
		break;
	case DSI_OP_CMD_MODE:
	case DSI_OP_CMD_MODE:
		info->curr_panel_mode = MSM_DISPLAY_CMD_MODE;
		info->capabilities |= MSM_DISPLAY_CAP_CMD_MODE;
		info->capabilities |= MSM_DISPLAY_CAP_CMD_MODE;
		if (display->panel->panel_mode_switch_enabled)
			info->capabilities |= MSM_DISPLAY_CAP_VID_MODE;
		info->is_te_using_watchdog_timer =
		info->is_te_using_watchdog_timer =
			display->panel->te_using_watchdog_timer |
			display->panel->te_using_watchdog_timer |
			display->sw_te_using_wd;
			display->sw_te_using_wd;
@@ -5704,7 +5715,8 @@ int dsi_display_find_mode(struct dsi_display *display,


		if (cmp->timing.v_active == m->timing.v_active &&
		if (cmp->timing.v_active == m->timing.v_active &&
			cmp->timing.h_active == m->timing.h_active &&
			cmp->timing.h_active == m->timing.h_active &&
			cmp->timing.refresh_rate == m->timing.refresh_rate) {
			cmp->timing.refresh_rate == m->timing.refresh_rate &&
			cmp->panel_mode == m->panel_mode) {
			*out_mode = m;
			*out_mode = m;
			rc = 0;
			rc = 0;
			break;
			break;
@@ -6314,7 +6326,8 @@ int dsi_display_prepare(struct dsi_display *display)
		goto error;
		goto error;
	}
	}


	if (!display->is_cont_splash_enabled) {
	if (!(mode->dsi_mode_flags & DSI_MODE_FLAG_POMS) &&
		(!display->is_cont_splash_enabled)) {
		/*
		/*
		 * For continuous splash usecase we skip panel
		 * For continuous splash usecase we skip panel
		 * pre prepare since the regulator vote is already
		 * pre prepare since the regulator vote is already
@@ -6403,6 +6416,7 @@ int dsi_display_prepare(struct dsi_display *display)
			goto error_ctrl_link_off;
			goto error_ctrl_link_off;
		}
		}


		if (!(mode->dsi_mode_flags & DSI_MODE_FLAG_POMS)) {
			rc = dsi_panel_prepare(display->panel);
			rc = dsi_panel_prepare(display->panel);
			if (rc) {
			if (rc) {
				pr_err("[%s] panel prepare failed, rc=%d\n",
				pr_err("[%s] panel prepare failed, rc=%d\n",
@@ -6410,6 +6424,7 @@ int dsi_display_prepare(struct dsi_display *display)
				goto error_ctrl_link_off;
				goto error_ctrl_link_off;
			}
			}
		}
		}
	}
	goto error;
	goto error;


error_ctrl_link_off:
error_ctrl_link_off:
@@ -6728,7 +6743,8 @@ int dsi_display_enable(struct dsi_display *display)
				   display->name, rc);
				   display->name, rc);
			goto error;
			goto error;
		}
		}
	} else {
	} else if (!(display->panel->cur_mode->dsi_mode_flags &
			DSI_MODE_FLAG_POMS)){
		rc = dsi_panel_enable(display->panel);
		rc = dsi_panel_enable(display->panel);
		if (rc) {
		if (rc) {
			pr_err("[%s] failed to enable DSI panel, rc=%d\n",
			pr_err("[%s] failed to enable DSI panel, rc=%d\n",
@@ -6757,6 +6773,7 @@ int dsi_display_enable(struct dsi_display *display)
	}
	}


	if (display->config.panel_mode == DSI_OP_VIDEO_MODE) {
	if (display->config.panel_mode == DSI_OP_VIDEO_MODE) {
		pr_debug("%s:enable video timing eng\n", __func__);
		rc = dsi_display_vid_engine_enable(display);
		rc = dsi_display_vid_engine_enable(display);
		if (rc) {
		if (rc) {
			pr_err("[%s]failed to enable DSI video engine, rc=%d\n",
			pr_err("[%s]failed to enable DSI video engine, rc=%d\n",
@@ -6764,6 +6781,7 @@ int dsi_display_enable(struct dsi_display *display)
			goto error_disable_panel;
			goto error_disable_panel;
		}
		}
	} else if (display->config.panel_mode == DSI_OP_CMD_MODE) {
	} else if (display->config.panel_mode == DSI_OP_CMD_MODE) {
		pr_debug("%s:enable command timing eng\n", __func__);
		rc = dsi_display_cmd_engine_enable(display);
		rc = dsi_display_cmd_engine_enable(display);
		if (rc) {
		if (rc) {
			pr_err("[%s]failed to enable DSI cmd engine, rc=%d\n",
			pr_err("[%s]failed to enable DSI cmd engine, rc=%d\n",
@@ -6797,10 +6815,18 @@ int dsi_display_post_enable(struct dsi_display *display)


	mutex_lock(&display->display_lock);
	mutex_lock(&display->display_lock);


	if (display->panel->cur_mode->dsi_mode_flags & DSI_MODE_FLAG_POMS) {
		if (display->config.panel_mode == DSI_OP_CMD_MODE)
			dsi_panel_mode_switch_to_cmd(display->panel);

		if (display->config.panel_mode == DSI_OP_VIDEO_MODE)
			dsi_panel_mode_switch_to_vid(display->panel);
	} else {
		rc = dsi_panel_post_enable(display->panel);
		rc = dsi_panel_post_enable(display->panel);
		if (rc)
		if (rc)
			pr_err("[%s] panel post-enable failed, rc=%d\n",
			pr_err("[%s] panel post-enable failed, rc=%d\n",
				display->name, rc);
				display->name, rc);
	}


	/* remove the clk vote for CMD mode panels */
	/* remove the clk vote for CMD mode panels */
	if (display->config.panel_mode == DSI_OP_CMD_MODE)
	if (display->config.panel_mode == DSI_OP_CMD_MODE)
@@ -6826,12 +6852,18 @@ int dsi_display_pre_disable(struct dsi_display *display)
	if (display->config.panel_mode == DSI_OP_CMD_MODE)
	if (display->config.panel_mode == DSI_OP_CMD_MODE)
		dsi_display_clk_ctrl(display->dsi_clk_handle,
		dsi_display_clk_ctrl(display->dsi_clk_handle,
			DSI_ALL_CLKS, DSI_CLK_ON);
			DSI_ALL_CLKS, DSI_CLK_ON);
	if (display->poms_pending) {
		if (display->config.panel_mode == DSI_OP_CMD_MODE)
			dsi_panel_pre_mode_switch_to_video(display->panel);


		if (display->config.panel_mode == DSI_OP_VIDEO_MODE)
			dsi_panel_pre_mode_switch_to_cmd(display->panel);
	} else {
		rc = dsi_panel_pre_disable(display->panel);
		rc = dsi_panel_pre_disable(display->panel);
		if (rc)
		if (rc)
			pr_err("[%s] panel pre-disable failed, rc=%d\n",
			pr_err("[%s] panel pre-disable failed, rc=%d\n",
				display->name, rc);
				display->name, rc);

	}
	mutex_unlock(&display->display_lock);
	mutex_unlock(&display->display_lock);
	return rc;
	return rc;
}
}
@@ -6868,11 +6900,12 @@ int dsi_display_disable(struct dsi_display *display)
		rc = -EINVAL;
		rc = -EINVAL;
	}
	}


	if (!display->poms_pending) {
		rc = dsi_panel_disable(display->panel);
		rc = dsi_panel_disable(display->panel);
		if (rc)
		if (rc)
			pr_err("[%s] failed to disable DSI panel, rc=%d\n",
			pr_err("[%s] failed to disable DSI panel, rc=%d\n",
				display->name, rc);
				display->name, rc);

	}
	mutex_unlock(&display->display_lock);
	mutex_unlock(&display->display_lock);
	SDE_EVT32(SDE_EVTLOG_FUNC_EXIT);
	SDE_EVT32(SDE_EVTLOG_FUNC_EXIT);
	return rc;
	return rc;
@@ -6911,12 +6944,12 @@ int dsi_display_unprepare(struct dsi_display *display)
	if (rc)
	if (rc)
		pr_err("[%s] display wake up failed, rc=%d\n",
		pr_err("[%s] display wake up failed, rc=%d\n",
		       display->name, rc);
		       display->name, rc);

	if (!display->poms_pending) {
		rc = dsi_panel_unprepare(display->panel);
		rc = dsi_panel_unprepare(display->panel);
		if (rc)
		if (rc)
			pr_err("[%s] panel unprepare failed, rc=%d\n",
			pr_err("[%s] panel unprepare failed, rc=%d\n",
			       display->name, rc);
			       display->name, rc);

	}
	rc = dsi_display_ctrl_host_disable(display);
	rc = dsi_display_ctrl_host_disable(display);
	if (rc)
	if (rc)
		pr_err("[%s] failed to disable DSI host, rc=%d\n",
		pr_err("[%s] failed to disable DSI host, rc=%d\n",
@@ -6949,10 +6982,12 @@ int dsi_display_unprepare(struct dsi_display *display)
	/* destrory dsi isr set up */
	/* destrory dsi isr set up */
	dsi_display_ctrl_isr_configure(display, false);
	dsi_display_ctrl_isr_configure(display, false);


	if (!display->poms_pending) {
		rc = dsi_panel_post_unprepare(display->panel);
		rc = dsi_panel_post_unprepare(display->panel);
		if (rc)
		if (rc)
			pr_err("[%s] panel post-unprepare failed, rc=%d\n",
			pr_err("[%s] panel post-unprepare failed, rc=%d\n",
			       display->name, rc);
			       display->name, rc);
	}


	mutex_unlock(&display->display_lock);
	mutex_unlock(&display->display_lock);


+2 −0
Original line number Original line Diff line number Diff line
@@ -166,6 +166,7 @@ struct dsi_display_ext_bridge {
 * @cmdline_topology: Display topology shared from kernel command line.
 * @cmdline_topology: Display topology shared from kernel command line.
 * @cmdline_timing:   Display timing shared from kernel command line.
 * @cmdline_timing:   Display timing shared from kernel command line.
 * @is_tpg_enabled:   TPG state.
 * @is_tpg_enabled:   TPG state.
 * @poms_pending;      Flag indicating the pending panel operating mode switch.
 * @ulps_enabled:     ulps state.
 * @ulps_enabled:     ulps state.
 * @clamp_enabled:    clamp state.
 * @clamp_enabled:    clamp state.
 * @phy_idle_power_off:   PHY power state.
 * @phy_idle_power_off:   PHY power state.
@@ -226,6 +227,7 @@ struct dsi_display {
	int cmdline_topology;
	int cmdline_topology;
	int cmdline_timing;
	int cmdline_timing;
	bool is_tpg_enabled;
	bool is_tpg_enabled;
	bool poms_pending;
	bool ulps_enabled;
	bool ulps_enabled;
	bool clamp_enabled;
	bool clamp_enabled;
	bool phy_idle_power_off;
	bool phy_idle_power_off;
+34 −2
Original line number Original line Diff line number Diff line
@@ -71,11 +71,18 @@ static void convert_to_dsi_mode(const struct drm_display_mode *drm_mode,
		dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DMS;
		dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DMS;
	if (msm_is_mode_seamless_vrr(drm_mode))
	if (msm_is_mode_seamless_vrr(drm_mode))
		dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_VRR;
		dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_VRR;
	if (msm_is_mode_seamless_poms(drm_mode))
		dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_POMS;


	dsi_mode->timing.h_sync_polarity =
	dsi_mode->timing.h_sync_polarity =
			!!(drm_mode->flags & DRM_MODE_FLAG_PHSYNC);
			!!(drm_mode->flags & DRM_MODE_FLAG_PHSYNC);
	dsi_mode->timing.v_sync_polarity =
	dsi_mode->timing.v_sync_polarity =
			!!(drm_mode->flags & DRM_MODE_FLAG_PVSYNC);
			!!(drm_mode->flags & DRM_MODE_FLAG_PVSYNC);

	if (drm_mode->flags & DRM_MODE_FLAG_VID_MODE_PANEL)
		dsi_mode->panel_mode = DSI_OP_VIDEO_MODE;
	if (drm_mode->flags & DRM_MODE_FLAG_CMD_MODE_PANEL)
		dsi_mode->panel_mode = DSI_OP_CMD_MODE;
}
}


void dsi_convert_to_drm_mode(const struct dsi_display_mode *dsi_mode,
void dsi_convert_to_drm_mode(const struct dsi_display_mode *dsi_mode,
@@ -113,12 +120,19 @@ void dsi_convert_to_drm_mode(const struct dsi_display_mode *dsi_mode,
		drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_DMS;
		drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_DMS;
	if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_VRR)
	if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_VRR)
		drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_VRR;
		drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_VRR;
	if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_POMS)
		drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_POMS;


	if (dsi_mode->timing.h_sync_polarity)
	if (dsi_mode->timing.h_sync_polarity)
		drm_mode->flags |= DRM_MODE_FLAG_PHSYNC;
		drm_mode->flags |= DRM_MODE_FLAG_PHSYNC;
	if (dsi_mode->timing.v_sync_polarity)
	if (dsi_mode->timing.v_sync_polarity)
		drm_mode->flags |= DRM_MODE_FLAG_PVSYNC;
		drm_mode->flags |= DRM_MODE_FLAG_PVSYNC;


	if (dsi_mode->panel_mode == DSI_OP_VIDEO_MODE)
		drm_mode->flags |= DRM_MODE_FLAG_VID_MODE_PANEL;
	if (dsi_mode->panel_mode == DSI_OP_CMD_MODE)
		drm_mode->flags |= DRM_MODE_FLAG_CMD_MODE_PANEL;

	drm_mode_set_name(drm_mode);
	drm_mode_set_name(drm_mode);
}
}


@@ -233,8 +247,18 @@ static void dsi_bridge_disable(struct drm_bridge *bridge)
	}
	}
	display = c_bridge->display;
	display = c_bridge->display;


	if (display && display->drm_conn)
	if (display && display->drm_conn) {
		if (bridge->encoder->crtc->state->adjusted_mode.private_flags &
			MSM_MODE_FLAG_SEAMLESS_POMS) {
			display->poms_pending = true;
			/* Disable ESD thread, during panel mode switch */
			sde_connector_schedule_status_work(display->drm_conn,
				false);
		} else {
			display->poms_pending = false;
			sde_connector_helper_bridge_disable(display->drm_conn);
			sde_connector_helper_bridge_disable(display->drm_conn);
		}
	}


	rc = dsi_display_pre_disable(c_bridge->display);
	rc = dsi_display_pre_disable(c_bridge->display);
	if (rc) {
	if (rc) {
@@ -363,9 +387,17 @@ static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge,


		cur_mode = crtc_state->crtc->mode;
		cur_mode = crtc_state->crtc->mode;


		/* No panel mode switch when drm pipeline is changing */
		if ((dsi_mode.panel_mode != cur_dsi_mode.panel_mode) &&
			(!(dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_VRR)) &&
			(!crtc_state->active_changed ||
			display->is_cont_splash_enabled))
			dsi_mode.dsi_mode_flags |= DSI_MODE_FLAG_POMS;

		/* No DMS/VRR when drm pipeline is changing */
		/* No DMS/VRR when drm pipeline is changing */
		if (!drm_mode_equal(&cur_mode, adjusted_mode) &&
		if (!drm_mode_equal(&cur_mode, adjusted_mode) &&
			(!(dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_VRR)) &&
			(!(dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_VRR)) &&
			(!(dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_POMS)) &&
			(!crtc_state->active_changed ||
			(!crtc_state->active_changed ||
			 display->is_cont_splash_enabled))
			 display->is_cont_splash_enabled))
			dsi_mode.dsi_mode_flags |= DSI_MODE_FLAG_DMS;
			dsi_mode.dsi_mode_flags |= DSI_MODE_FLAG_DMS;
+128 −2
Original line number Original line Diff line number Diff line
@@ -1365,6 +1365,7 @@ static int dsi_panel_parse_panel_mode(struct dsi_panel *panel)
{
{
	int rc = 0;
	int rc = 0;
	struct dsi_parser_utils *utils = &panel->utils;
	struct dsi_parser_utils *utils = &panel->utils;
	bool panel_mode_switch_enabled;
	enum dsi_op_mode panel_mode;
	enum dsi_op_mode panel_mode;
	const char *mode;
	const char *mode;


@@ -1383,7 +1384,13 @@ static int dsi_panel_parse_panel_mode(struct dsi_panel *panel)
		goto error;
		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,
		rc = dsi_panel_parse_video_host_config(&panel->video_config,
						       utils,
						       utils,
						       panel->name);
						       panel->name);
@@ -1394,7 +1401,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,
		rc = dsi_panel_parse_cmd_host_config(&panel->cmd_config,
						     utils,
						     utils,
						     panel->name);
						     panel->name);
@@ -1406,6 +1413,7 @@ static int dsi_panel_parse_panel_mode(struct dsi_panel *panel)
	}
	}


	panel->panel_mode = panel_mode;
	panel->panel_mode = panel_mode;
	panel->panel_mode_switch_enabled = panel_mode_switch_enabled;
error:
error:
	return rc;
	return rc;
}
}
@@ -2663,6 +2671,33 @@ static int dsi_panel_parse_partial_update_caps(struct dsi_display_mode *mode,
	return rc;
	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)
static int dsi_panel_parse_dms_info(struct dsi_panel *panel)
{
{
	int dms_enabled;
	int dms_enabled;
@@ -3349,6 +3384,17 @@ int dsi_panel_get_mode(struct dsi_panel *panel,
		rc = dsi_panel_parse_partial_update_caps(mode, utils);
		rc = dsi_panel_parse_partial_update_caps(mode, utils);
		if (rc)
		if (rc)
			pr_err("failed to partial update caps, rc=%d\n", 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;
	goto done;


@@ -3707,6 +3753,86 @@ int dsi_panel_send_roi_dcs(struct dsi_panel *panel, int ctrl_idx,
	return rc;
	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 dsi_panel_switch(struct dsi_panel *panel)
{
{
	int rc = 0;
	int rc = 0;
Loading