[PATCH] drm/i915: Use vblank evade mechanism in mmio_flip

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

 



From: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@xxxxxxxxx>

Currently we program just DPSCNTR and DSPSTRIDE directly from the ring
interrupt handler, which is fine since the hardware guarantees that
those are update atomically. When we have atomic page flips we'll want
to be able to update also the offset registers, and then we need to use
the vblank evade mechanism to guarantee atomicity.

Signed-off-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@xxxxxxxxx>
---
 drivers/gpu/drm/i915/intel_display.c | 21 ++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_drv.h     |  5 ++++-
 drivers/gpu/drm/i915/intel_sprite.c  |  4 ++--
 3 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 6e6f150..6a234cf 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -9563,11 +9563,15 @@ static void intel_do_mmio_flip(struct intel_crtc *intel_crtc)
 	struct intel_framebuffer *intel_fb =
 		to_intel_framebuffer(intel_crtc->base.primary->fb);
 	struct drm_i915_gem_object *obj = intel_fb->obj;
+	bool atomic_update;
+	u32 start_vbl_count;
 	u32 dspcntr;
 	u32 reg;
 
 	intel_mark_page_flip_active(intel_crtc);
 
+	atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
+
 	reg = DSPCNTR(intel_crtc->plane);
 	dspcntr = I915_READ(reg);
 
@@ -9582,6 +9586,19 @@ static void intel_do_mmio_flip(struct intel_crtc *intel_crtc)
 	I915_WRITE(DSPSURF(intel_crtc->plane),
 		   intel_crtc->unpin_work->gtt_offset);
 	POSTING_READ(DSPSURF(intel_crtc->plane));
+
+	if (atomic_update)
+		intel_pipe_update_end(intel_crtc, start_vbl_count);
+}
+
+static void intel_mmio_flip_work_func(struct work_struct *work)
+{
+	struct intel_crtc *intel_crtc =
+		container_of(work, struct intel_crtc, mmio_flip.work);
+
+	drm_modeset_lock(&intel_crtc->base.mutex, NULL);
+	intel_do_mmio_flip(intel_crtc);
+	drm_modeset_unlock(&intel_crtc->base.mutex);
 }
 
 static int intel_postpone_flip(struct drm_i915_gem_object *obj)
@@ -9631,7 +9648,7 @@ void intel_notify_mmio_flip(struct intel_engine_cs *ring)
 			continue;
 
 		if (i915_seqno_passed(seqno, mmio_flip->seqno)) {
-			intel_do_mmio_flip(intel_crtc);
+			schedule_work(&intel_crtc->mmio_flip.work);
 			mmio_flip->seqno = 0;
 			ring->irq_put(ring);
 		}
@@ -9661,6 +9678,8 @@ static int intel_queue_mmio_flip(struct drm_device *dev,
 		return 0;
 	}
 
+	INIT_WORK(&intel_crtc->mmio_flip.work, intel_mmio_flip_work_func);
+
 	spin_lock_irq(&dev_priv->mmio_flip_lock);
 	intel_crtc->mmio_flip.seqno = obj->last_write_seqno;
 	intel_crtc->mmio_flip.ring_id = obj->ring->id;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 5ab813c..5649776 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -400,6 +400,7 @@ struct intel_pipe_wm {
 struct intel_mmio_flip {
 	u32 seqno;
 	u32 ring_id;
+	struct work_struct work;
 };
 
 struct intel_crtc {
@@ -1158,7 +1159,9 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
 			      struct drm_file *file_priv);
 int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
 			      struct drm_file *file_priv);
-
+bool intel_pipe_update_start(struct intel_crtc *crtc,
+			     uint32_t *start_vbl_count);
+void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count);
 
 /* intel_tv.c */
 void intel_tv_init(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 2c060ad..3e7480a 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -46,7 +46,7 @@ static int usecs_to_scanlines(const struct drm_display_mode *mode, int usecs)
 	return DIV_ROUND_UP(usecs * mode->crtc_clock, 1000 * mode->crtc_htotal);
 }
 
-static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl_count)
+bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl_count)
 {
 	struct drm_device *dev = crtc->base.dev;
 	const struct drm_display_mode *mode = &crtc->config.adjusted_mode;
@@ -112,7 +112,7 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl
 	return true;
 }
 
-static void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count)
+void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count)
 {
 	struct drm_device *dev = crtc->base.dev;
 	enum pipe pipe = crtc->pipe;
-- 
1.8.3.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/intel-gfx




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux