[PATCH 21/26] drm/i915: Allow async modeset enable.

Maarten Lankhorst maarten.lankhorst at linux.intel.com
Thu May 12 20:50:26 UTC 2016


Transitioning from enable -> disable or enable -> enable is not yet
allowed. This cannot be run async yet.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 105 ++++++++++++++++++-----------------
 1 file changed, 55 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b9f1712569c1..a6edfea5da27 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -10938,6 +10938,45 @@ void intel_finish_page_flip_mmio(struct drm_i915_private *dev_priv, int pipe)
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 }
 
+static void update_scanline_offset(struct intel_crtc *crtc,
+				   struct intel_crtc_state *pipe_config)
+{
+	struct drm_device *dev = crtc->base.dev;
+
+	/*
+	 * The scanline counter increments at the leading edge of hsync.
+	 *
+	 * On most platforms it starts counting from vtotal-1 on the
+	 * first active line. That means the scanline counter value is
+	 * always one less than what we would expect. Ie. just after
+	 * start of vblank, which also occurs at start of hsync (on the
+	 * last active line), the scanline counter will read vblank_start-1.
+	 *
+	 * On gen2 the scanline counter starts counting from 1 instead
+	 * of vtotal-1, so we have to subtract one (or rather add vtotal-1
+	 * to keep the value positive), instead of adding one.
+	 *
+	 * On HSW+ the behaviour of the scanline counter depends on the output
+	 * type. For DP ports it behaves like most other platforms, but on HDMI
+	 * there's an extra 1 line difference. So we need to add two instead of
+	 * one to the value.
+	 */
+	if (IS_GEN2(dev)) {
+		const struct drm_display_mode *mode = &pipe_config->base.adjusted_mode;
+		int vtotal;
+
+		vtotal = mode->crtc_vtotal;
+		if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+			vtotal /= 2;
+
+		crtc->scanline_offset = vtotal - 1;
+	} else if (HAS_DDI(dev) &&
+		   intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
+		crtc->scanline_offset = 2;
+	} else
+		crtc->scanline_offset = 1;
+}
+
 static void intel_mmio_flip_work_func(struct work_struct *w)
 {
 	struct intel_flip_work *work =
@@ -10970,6 +11009,11 @@ static void intel_mmio_flip_work_func(struct work_struct *w)
 					    &dev_priv->rps.mmioflips));
 	}
 
+	if (needs_modeset(&crtc_state->base)) {
+		update_scanline_offset(intel_crtc, crtc_state);
+		dev_priv->display.crtc_enable(crtc);
+	}
+
 	ret = drm_crtc_vblank_get(crtc);
 	I915_STATE_WARN(ret < 0, "enabling vblank failed with %i\n", ret);
 
@@ -12347,44 +12391,6 @@ intel_modeset_verify_disabled(struct drm_device *dev)
 	verify_disabled_dpll_state(dev);
 }
 
-static void update_scanline_offset(struct intel_crtc *crtc)
-{
-	struct drm_device *dev = crtc->base.dev;
-
-	/*
-	 * The scanline counter increments at the leading edge of hsync.
-	 *
-	 * On most platforms it starts counting from vtotal-1 on the
-	 * first active line. That means the scanline counter value is
-	 * always one less than what we would expect. Ie. just after
-	 * start of vblank, which also occurs at start of hsync (on the
-	 * last active line), the scanline counter will read vblank_start-1.
-	 *
-	 * On gen2 the scanline counter starts counting from 1 instead
-	 * of vtotal-1, so we have to subtract one (or rather add vtotal-1
-	 * to keep the value positive), instead of adding one.
-	 *
-	 * On HSW+ the behaviour of the scanline counter depends on the output
-	 * type. For DP ports it behaves like most other platforms, but on HDMI
-	 * there's an extra 1 line difference. So we need to add two instead of
-	 * one to the value.
-	 */
-	if (IS_GEN2(dev)) {
-		const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
-		int vtotal;
-
-		vtotal = adjusted_mode->crtc_vtotal;
-		if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
-			vtotal /= 2;
-
-		crtc->scanline_offset = vtotal - 1;
-	} else if (HAS_DDI(dev) &&
-		   intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
-		crtc->scanline_offset = 2;
-	} else
-		crtc->scanline_offset = 1;
-}
-
 static void intel_modeset_clear_plls(struct drm_atomic_state *state)
 {
 	struct drm_device *dev = state->dev;
@@ -12722,7 +12728,7 @@ static int intel_atomic_prepare_commit(struct drm_device *dev,
 	struct drm_crtc_state *crtc_state;
 	struct drm_plane *plane;
 	struct drm_crtc *crtc;
-	int i, ret;
+	int i, ret, num_ms_disable = 0;
 
 	for_each_crtc_in_state(state, crtc, crtc_state, i) {
 		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -12736,10 +12742,12 @@ static int intel_atomic_prepare_commit(struct drm_device *dev,
 				flush_workqueue(dev_priv->wq);
 		}
 
-		/* test if we need to update something */
 		if (!needs_work(crtc_state))
 			continue;
 
+		if (needs_modeset(crtc_state) && crtc->state->active)
+			num_ms_disable++;
+
 		intel_state->work[i] =
 			kzalloc(sizeof(**intel_state->work), GFP_KERNEL);
 
@@ -12747,8 +12755,8 @@ static int intel_atomic_prepare_commit(struct drm_device *dev,
 			return -ENOMEM;
 	}
 
-	if (intel_state->modeset && nonblock) {
-		DRM_DEBUG_ATOMIC("Nonblock modesets are not yet supported!\n");
+	if (nonblock && num_ms_disable) {
+		DRM_DEBUG_ATOMIC("Nonblocking modeset disable/toggling is not yet supported!\n");
 		return -EINVAL;
 	}
 
@@ -13019,11 +13027,6 @@ static int intel_atomic_commit(struct drm_device *dev,
 		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 		bool modeset = needs_modeset(crtc->state);
 
-		if (modeset && crtc->state->active) {
-			update_scanline_offset(to_intel_crtc(crtc));
-			dev_priv->display.crtc_enable(crtc);
-		}
-
 		if (!modeset)
 			intel_pre_plane_update(to_intel_crtc_state(old_crtc_state));
 
@@ -15188,7 +15191,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
 			crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED;
 
 			drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode);
-			update_scanline_offset(crtc);
+			update_scanline_offset(crtc, crtc->config);
 		}
 
 		intel_pipe_config_sanity_check(dev_priv, crtc->config);
@@ -15246,8 +15249,10 @@ intel_modeset_setup_hw_state(struct drm_device *dev)
 		unsigned long put_domains;
 
 		put_domains = modeset_get_crtc_power_domains(&crtc->base, crtc->config);
-		if (WARN_ON(put_domains))
-			modeset_put_power_domains(dev_priv, put_domains);
+
+		WARN_ON(put_domains);
+
+		modeset_put_power_domains(dev_priv, put_domains);
 	}
 	intel_display_set_init_power(dev_priv, false);
 
-- 
2.5.5



More information about the Intel-gfx-trybot mailing list