@@ -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;
@@ -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);
@@ -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;