[PATCH 66/81] drm/i915: Make a copy of the calculated plane regs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx>

The register values are computed when the flip ioctl is issued, and
they're used only after we've waited for the GPU to finish rendering.
The computed values are store in the intel_crtc and intel_plane structs,
so issuing another flip before the previous one has been fully completed
would clobber those stored registers. Fix the problem by making a copy
of the calculated register values inside the intel_flip structure. The
copy is then used when it's time to commit the registers to the hardware.

Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx>
---
 drivers/gpu/drm/i915/i915_drv.h      |    4 +++-
 drivers/gpu/drm/i915/intel_atomic.c  |    8 ++++++--
 drivers/gpu/drm/i915/intel_display.c |   14 ++++++++------
 drivers/gpu/drm/i915/intel_drv.h     |    2 +-
 drivers/gpu/drm/i915/intel_sprite.c  |   24 ++++++++++++------------
 5 files changed, 30 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 80b4b30..d8e8a4f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -269,6 +269,8 @@ struct drm_i915_error_state {
 	struct intel_display_error_state *display;
 };
 
+struct intel_plane_regs;
+
 struct drm_i915_display_funcs {
 	bool (*fbc_enabled)(struct drm_device *dev);
 	void (*enable_fbc)(struct drm_crtc *crtc, unsigned long interval);
@@ -300,7 +302,7 @@ struct drm_i915_display_funcs {
 			    int x, int y);
 	int (*calc_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 			  int x, int y);
-	void (*commit_plane)(struct drm_crtc *crtc);
+	void (*commit_plane)(struct drm_crtc *crtc, const struct intel_plane_regs *regs);
 	/* clock updates for mode set */
 	/* cursor updates */
 	/* render clock increase/decrease */
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index f59be7f..e52d92a 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -47,6 +47,8 @@ struct intel_flip {
 	struct intel_ring_buffer *ring;
 	u32 seqno;
 	unsigned int flip_seq;
+	/* FIXME need cursor regs too */
+	struct intel_plane_regs regs;
 };
 
 struct intel_plane_state {
@@ -1986,11 +1988,11 @@ static bool intel_flip_flip(struct drm_flip *flip,
 		struct drm_plane *plane = intel_flip->plane;
 		struct intel_plane *intel_plane = to_intel_plane(plane);
 
-		intel_plane->commit(plane);
+		intel_plane->commit(plane, &intel_flip->regs);
 	} else {
 		struct drm_i915_private *dev_priv = dev->dev_private;
 
-		dev_priv->display.commit_plane(crtc);
+		dev_priv->display.commit_plane(crtc, &intel_flip->regs);
 	}
 
 	if (intel_flip->has_cursor)
@@ -2321,6 +2323,7 @@ static void atomic_pipe_commit(struct drm_device *dev,
 		/* should already be checked so can't fail */
 		/* FIXME refactor the failing parts? */
 		dev_priv->display.calc_plane(crtc, crtc->fb, crtc->x, crtc->y);
+		intel_flip->regs = intel_crtc->primary_regs;
 
 		if (st->cursor_dirty) {
 			intel_flip->has_cursor = true;
@@ -2387,6 +2390,7 @@ static void atomic_pipe_commit(struct drm_device *dev,
 		}
 
 		intel_plane->calc(plane, plane->fb, &st->coords);
+		intel_flip->regs = intel_plane->regs;
 
 		if (st->old.fb)
 			intel_flip->old_fb_id = st->old.fb->base.id;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c84a839..390251d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1979,13 +1979,13 @@ unsigned long intel_gen4_compute_offset_xtiled(int *x, int *y,
 	return tile_rows * pitch * 8 + tiles * 4096;
 }
 
-static void intel_commit_plane(struct drm_crtc *crtc)
+static void intel_commit_plane(struct drm_crtc *crtc,
+			       const struct intel_plane_regs *regs)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int plane = intel_crtc->plane;
-	const struct intel_plane_regs *regs = &intel_crtc->primary_regs;
 
 	I915_WRITE(DSPCNTR(plane), regs->cntr);
 	I915_WRITE(DSPSTRIDE(plane), regs->stride);
@@ -2102,15 +2102,16 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 			     int x, int y)
 {
 	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int ret;
 
 	ret = i9xx_calc_plane(crtc, fb, x, y);
 	if (ret)
 		return ret;
 
-	intel_commit_plane(crtc);
+	intel_commit_plane(crtc, &intel_crtc->primary_regs);
 
-	POSTING_READ(DSPCNTR(to_intel_crtc(crtc)->plane));
+	POSTING_READ(DSPCNTR(intel_crtc->plane));
 
 	return 0;
 }
@@ -2206,15 +2207,16 @@ static int ironlake_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *
 				 int x, int y)
 {
 	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int ret;
 
 	ret = ironlake_calc_plane(crtc, fb, x, y);
 	if (ret)
 		return ret;
 
-	intel_commit_plane(crtc);
+	intel_commit_plane(crtc, &intel_crtc->primary_regs);
 
-	POSTING_READ(DSPCNTR(to_intel_crtc(crtc)->plane));
+	POSTING_READ(DSPCNTR(intel_crtc->plane));
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 33fac47..e39a10b 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -277,7 +277,7 @@ struct intel_plane {
 	void (*calc)(struct drm_plane *plane, struct drm_framebuffer *fb,
 		     const struct intel_plane_coords *clip);
 	void (*prepare)(struct drm_plane *plane);
-	void (*commit)(struct drm_plane *plane);
+	void (*commit)(struct drm_plane *plane, const struct intel_plane_regs *regs);
 	struct intel_plane_regs regs;
 	struct drm_flip_helper flip_helper;
 };
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index ce3b950..d960e19 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -300,13 +300,13 @@ ivb_calc_plane(struct drm_plane *plane,
 }
 
 static void
-ivb_commit_plane(struct drm_plane *plane)
+ivb_commit_plane(struct drm_plane *plane,
+		 const struct intel_plane_regs *regs)
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_plane *intel_plane = to_intel_plane(plane);
 	int pipe = intel_plane->pipe;
-	const struct intel_plane_regs *regs = &intel_plane->regs;
 
 	I915_WRITE(SPRKEYVAL(pipe), regs->keyval);
 	I915_WRITE(SPRKEYMAX(pipe), regs->keymaxval);
@@ -371,7 +371,7 @@ ivb_update_plane(struct drm_plane *plane,
 
 	ivb_calc_plane(plane, fb, coords);
 	ivb_prepare_plane(plane);
-	ivb_commit_plane(plane);
+	ivb_commit_plane(plane, &intel_plane->regs);
 	POSTING_READ(SPRSURF(pipe));
 }
 
@@ -387,7 +387,7 @@ ivb_disable_plane(struct drm_plane *plane)
 	regs->cntr &= ~SPRITE_ENABLE;
 	/* Can't leave the scaler enabled... */
 	regs->scale = 0;
-	ivb_commit_plane(plane);
+	ivb_commit_plane(plane, regs);
 	POSTING_READ(SPRSURF(pipe));
 
 	dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
@@ -413,7 +413,7 @@ ivb_update_colorkey(struct drm_plane *plane,
 	else if (key->flags & I915_SET_COLORKEY_SOURCE)
 		regs->cntr |= SPRITE_SOURCE_KEY;
 
-	ivb_commit_plane(plane);
+	ivb_commit_plane(plane, regs);
 	POSTING_READ(SPRKEYMSK(intel_plane->pipe));
 
 	return 0;
@@ -546,13 +546,13 @@ ilk_prepare_plane(struct drm_plane *plane)
 }
 
 static void
-ilk_commit_plane(struct drm_plane *plane)
+ilk_commit_plane(struct drm_plane *plane,
+		 const struct intel_plane_regs *regs)
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_plane *intel_plane = to_intel_plane(plane);
 	int pipe = intel_plane->pipe;
-	const struct intel_plane_regs *regs = &intel_plane->regs;
 
 	I915_WRITE(DVSKEYVAL(pipe), regs->keyval);
 	I915_WRITE(DVSKEYMAX(pipe), regs->keymaxval);
@@ -579,7 +579,7 @@ ilk_update_plane(struct drm_plane *plane,
 
 	ilk_calc_plane(plane, fb, coords);
 	ilk_prepare_plane(plane);
-	ilk_commit_plane(plane);
+	ilk_commit_plane(plane, &intel_plane->regs);
 	POSTING_READ(DVSSURF(pipe));
 }
 
@@ -595,7 +595,7 @@ ilk_disable_plane(struct drm_plane *plane)
 	regs->cntr &= ~DVS_ENABLE;
 	/* Disable the scaler */
 	regs->scale = 0;
-	ilk_commit_plane(plane);
+	ilk_commit_plane(plane, regs);
 	POSTING_READ(DVSSURF(pipe));
 }
 
@@ -627,7 +627,7 @@ intel_enable_primary(struct drm_crtc *crtc)
 	intel_update_fbc(dev);
 
 	regs->cntr = I915_READ(reg) | DISPLAY_PLANE_ENABLE;
-	dev_priv->display.commit_plane(crtc);
+	dev_priv->display.commit_plane(crtc, regs);
 }
 
 void
@@ -643,7 +643,7 @@ intel_disable_primary(struct drm_crtc *crtc)
 		return;
 
 	regs->cntr = I915_READ(reg) & ~DISPLAY_PLANE_ENABLE;
-	dev_priv->display.commit_plane(crtc);
+	dev_priv->display.commit_plane(crtc, regs);
 
 	intel_crtc->primary_disabled = true;
 	intel_update_fbc(dev);
@@ -668,7 +668,7 @@ ilk_update_colorkey(struct drm_plane *plane,
 	else if (key->flags & I915_SET_COLORKEY_SOURCE)
 		regs->cntr |= DVS_SOURCE_KEY;
 
-	ilk_commit_plane(plane);
+	ilk_commit_plane(plane, regs);
 	POSTING_READ(DVSKEYMSK(intel_plane->pipe));
 
 	return 0;
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/dri-devel



[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux