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

Commit 7d12ce0b authored by Lloyd Atkinson's avatar Lloyd Atkinson
Browse files

drm/msm/dsi-staging: fix dynamic fps mode checks and tracking



Do not store one-time transient mode flags into the DSI panel's
current mode. Do not fail when DSI is asked to transition to the
same fps.

CRs-Fixed: 2005394
Change-Id: I89d6bc8eb8d7fd8cd6aa5ba3f493c4edd348bba5
Signed-off-by: default avatarLloyd Atkinson <latkinso@codeaurora.org>
parent 940340de
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -383,14 +383,13 @@ struct dsi_host_config {
 * @timing:         Timing parameters for the panel.
 * @pixel_clk_khz:  Pixel clock in Khz.
 * @panel_mode:     Panel operation mode.
 * @flags:          Additional flags.
 * @dsi_mode_flags: Flags to signal other drm components via private flags
 */
struct dsi_display_mode {
	struct dsi_mode_info timing;
	u32 pixel_clk_khz;
	enum dsi_op_mode panel_mode;

	u32 flags;
	u32 dsi_mode_flags;
};

#endif /* _DSI_DEFS_H_ */
+15 −9
Original line number Diff line number Diff line
@@ -1884,12 +1884,10 @@ static bool dsi_display_is_seamless_dfps_possible(

	/* skip polarity comparison */

	if (cur->timing.refresh_rate == tgt->timing.refresh_rate) {
	if (cur->timing.refresh_rate == tgt->timing.refresh_rate)
		pr_debug("timing.refresh_rate identical %d %d\n",
				cur->timing.refresh_rate,
				tgt->timing.refresh_rate);
		return false;
	}

	if (cur->pixel_clk_khz != tgt->pixel_clk_khz)
		pr_debug("pixel_clk_khz differs %d %d\n",
@@ -1901,8 +1899,9 @@ static bool dsi_display_is_seamless_dfps_possible(
		return false;
	}

	if (cur->flags != tgt->flags)
		pr_debug("flags differs %d %d\n", cur->flags, tgt->flags);
	if (cur->dsi_mode_flags != tgt->dsi_mode_flags)
		pr_debug("flags differs %d %d\n",
				cur->dsi_mode_flags, tgt->dsi_mode_flags);

	return true;
}
@@ -1962,6 +1961,13 @@ static int dsi_display_dfps_update(struct dsi_display *display,

	panel_mode = &display->panel->mode;
	memcpy(panel_mode, dsi_mode, sizeof(*panel_mode));
	/*
	 * dsi_mode_flags flags are used to communicate with other drm driver
	 * components, and are transient. They aren't inherently part of the
	 * display panel's mode and shouldn't be saved into the cached currently
	 * active mode.
	 */
	panel_mode->dsi_mode_flags = 0;

error:
	return rc;
@@ -2094,7 +2100,7 @@ static bool dsi_display_validate_mode_seamless(struct dsi_display *display,
		pr_debug("Dynamic FPS not supported for seamless\n");
	} else {
		pr_debug("Mode switch is seamless Dynamic FPS\n");
		adj_mode->flags |= DSI_MODE_FLAG_DFPS |
		adj_mode->dsi_mode_flags |= DSI_MODE_FLAG_DFPS |
				DSI_MODE_FLAG_VBLANK_PRE_MODESET;
	}

@@ -2121,7 +2127,7 @@ static int dsi_display_set_mode_sub(struct dsi_display *display,
	memcpy(&display->config.lane_map, &display->lane_map,
	       sizeof(display->lane_map));

	if (mode->flags & DSI_MODE_FLAG_DFPS) {
	if (mode->dsi_mode_flags & DSI_MODE_FLAG_DFPS) {
		rc = dsi_display_dfps_update(display, mode);
		if (rc) {
			pr_err("[%s]DSI dfps update failed, rc=%d\n",
@@ -2133,7 +2139,7 @@ static int dsi_display_set_mode_sub(struct dsi_display *display,
	for (i = 0; i < display->ctrl_count; i++) {
		ctrl = &display->ctrl[i];
		rc = dsi_ctrl_update_host_config(ctrl->ctrl, &display->config,
				mode->flags, display->dsi_clk_handle);
				mode->dsi_mode_flags, display->dsi_clk_handle);
		if (rc) {
			pr_err("[%s] failed to update ctrl config, rc=%d\n",
			       display->name, rc);
@@ -2813,7 +2819,7 @@ int dsi_display_validate_mode(struct dsi_display *display,
	}

	if ((flags & DSI_VALIDATE_FLAG_ALLOW_ADJUST) &&
			(mode->flags & DSI_MODE_FLAG_SEAMLESS)) {
			(mode->dsi_mode_flags & DSI_MODE_FLAG_SEAMLESS)) {
		rc = dsi_display_validate_mode_seamless(display, mode);
		if (rc) {
			pr_err("[%s] seamless not possible rc=%d\n",
+9 −9
Original line number 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
 * it under the terms of the GNU General Public License version 2 and
@@ -51,11 +51,11 @@ static void convert_to_dsi_mode(const struct drm_display_mode *drm_mode,
	dsi_mode->panel_mode = 0; /* TODO: Panel Mode */

	if (msm_is_mode_seamless(drm_mode))
		dsi_mode->flags |= DSI_MODE_FLAG_SEAMLESS;
		dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_SEAMLESS;
	if (msm_is_mode_dynamic_fps(drm_mode))
		dsi_mode->flags |= DSI_MODE_FLAG_DFPS;
		dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DFPS;
	if (msm_needs_vblank_pre_modeset(drm_mode))
		dsi_mode->flags |= DSI_MODE_FLAG_VBLANK_PRE_MODESET;
		dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_VBLANK_PRE_MODESET;
}

static void convert_to_drm_mode(const struct dsi_display_mode *dsi_mode,
@@ -81,11 +81,11 @@ static void convert_to_drm_mode(const struct dsi_display_mode *dsi_mode,
	drm_mode->vrefresh = dsi_mode->timing.refresh_rate;
	drm_mode->clock = dsi_mode->pixel_clk_khz;

	if (dsi_mode->flags & DSI_MODE_FLAG_SEAMLESS)
	if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_SEAMLESS)
		drm_mode->flags |= DRM_MODE_FLAG_SEAMLESS;
	if (dsi_mode->flags & DSI_MODE_FLAG_DFPS)
	if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_DFPS)
		drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_DYNAMIC_FPS;
	if (dsi_mode->flags & DSI_MODE_FLAG_VBLANK_PRE_MODESET)
	if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_VBLANK_PRE_MODESET)
		drm_mode->private_flags |= MSM_MODE_FLAG_VBLANK_PRE_MODESET;

	drm_mode_set_name(drm_mode);
@@ -125,7 +125,7 @@ static void dsi_bridge_pre_enable(struct drm_bridge *bridge)
		return;
	}

	if (c_bridge->dsi_mode.flags & DSI_MODE_FLAG_SEAMLESS) {
	if (c_bridge->dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_SEAMLESS) {
		pr_debug("[%d] seamless pre-enable\n", c_bridge->id);
		return;
	}
@@ -155,7 +155,7 @@ static void dsi_bridge_enable(struct drm_bridge *bridge)
		return;
	}

	if (c_bridge->dsi_mode.flags & DSI_MODE_FLAG_SEAMLESS) {
	if (c_bridge->dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_SEAMLESS) {
		pr_debug("[%d] seamless enable\n", c_bridge->id);
		return;
	}