diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index c086f72..1076bc0 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -76,6 +76,7 @@ struct omap_crtc {
 	 */
 	enum omap_page_flip_state flip_state;
 	struct drm_pending_vblank_event *flip_event;
+	wait_queue_head_t flip_wait;
 	struct work_struct flip_work;
 
 	struct completion completion;
@@ -309,6 +310,61 @@ static void omap_crtc_complete_page_flip(struct drm_crtc *crtc,
 	}
 
 	omap_crtc->flip_state = state;
+
+	if (state == OMAP_PAGE_FLIP_IDLE)
+		wake_up(&omap_crtc->flip_wait);
+}
+
+static bool omap_crtc_page_flip_pending(struct drm_crtc *crtc)
+{
+	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	unsigned long flags;
+	bool pending;
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+	pending = omap_crtc->flip_state != OMAP_PAGE_FLIP_IDLE;
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+	return pending;
+}
+
+static void omap_crtc_wait_page_flip(struct drm_crtc *crtc)
+{
+	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	bool cancelled = false;
+	unsigned long flags;
+
+	/*
+	 * If we're still waiting for the GEM async operation to complete just
+	 * cancel the page flip, as we're holding the CRTC mutex preventing the
+	 * page flip work handler from queueing the page flip.
+	 *
+	 * We can't release the reference to the frame buffer here as the async
+	 * operation doesn't keep its own reference to the buffer. We'll just
+	 * let the page flip work queue handle that.
+	 */
+	spin_lock_irqsave(&dev->event_lock, flags);
+	if (omap_crtc->flip_state == OMAP_PAGE_FLIP_WAIT) {
+		omap_crtc_complete_page_flip(crtc, OMAP_PAGE_FLIP_CANCELLED);
+		cancelled = true;
+	}
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+	if (cancelled)
+		return;
+
+	if (wait_event_timeout(omap_crtc->flip_wait,
+			       !omap_crtc_page_flip_pending(crtc),
+			       msecs_to_jiffies(50)))
+		return;
+
+	dev_warn(crtc->dev->dev, "page flip timeout!\n");
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+	omap_crtc_complete_page_flip(crtc, OMAP_PAGE_FLIP_IDLE);
+	spin_unlock_irqrestore(&dev->event_lock, flags);
 }
 
 static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
@@ -455,26 +511,39 @@ static void omap_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
 	struct omap_drm_private *priv = crtc->dev->dev_private;
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-	bool enabled = (mode == DRM_MODE_DPMS_ON);
+	bool enable = (mode == DRM_MODE_DPMS_ON);
 	int i;
 
 	DBG("%s: %d", omap_crtc->name, mode);
 
-	if (enabled == omap_crtc->enabled)
+	if (enable == omap_crtc->enabled)
 		return;
 
+	if (!enable) {
+		omap_crtc_wait_page_flip(crtc);
+		dispc_runtime_get();
+		drm_crtc_vblank_off(crtc);
+		dispc_runtime_put();
+	}
+
 	/* Enable/disable all planes associated with the CRTC. */
 	for (i = 0; i < priv->num_planes; i++) {
 		struct drm_plane *plane = priv->planes[i];
 
 		if (plane->crtc == crtc)
-			WARN_ON(omap_plane_set_enable(plane, enabled));
+			WARN_ON(omap_plane_set_enable(plane, enable));
 	}
 
-	omap_crtc->enabled = enabled;
+	omap_crtc->enabled = enable;
 
 	omap_crtc_setup(crtc);
 	omap_crtc_flush(crtc);
+
+	if (enable) {
+		dispc_runtime_get();
+		drm_crtc_vblank_on(crtc);
+		dispc_runtime_put();
+	}
 }
 
 static bool omap_crtc_mode_fixup(struct drm_crtc *crtc,
@@ -709,6 +778,7 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 	crtc = &omap_crtc->base;
 
 	INIT_WORK(&omap_crtc->flip_work, page_flip_worker);
+	init_waitqueue_head(&omap_crtc->flip_wait);
 
 	INIT_LIST_HEAD(&omap_crtc->pending_unpins);
 
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index cf1b37e..e81fbc0 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -502,6 +502,7 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
 {
 	struct omap_drm_platform_data *pdata = dev->dev->platform_data;
 	struct omap_drm_private *priv;
+	unsigned int i;
 	int ret;
 
 	DBG("load: dev=%p", dev);
@@ -529,10 +530,14 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
 		return ret;
 	}
 
+	/* Initialize vblank handling, start with all CRTCs disabled. */
 	ret = drm_vblank_init(dev, priv->num_crtcs);
 	if (ret)
 		dev_warn(dev->dev, "could not init vblank\n");
 
+	for (i = 0; i < priv->num_crtcs; i++)
+		drm_crtc_vblank_off(priv->crtcs[i]);
+
 	priv->fbdev = omap_fbdev_init(dev);
 	if (!priv->fbdev) {
 		dev_warn(dev->dev, "omap_fbdev_init failed\n");
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index 803aff0..249c0330 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -152,12 +152,10 @@ int omap_irq_enable_vblank(struct drm_device *dev, int crtc_id)
 
 	DBG("dev=%p, crtc=%d", dev, crtc_id);
 
-	dispc_runtime_get();
 	spin_lock_irqsave(&list_lock, flags);
 	priv->vblank_mask |= pipe2vbl(crtc);
 	omap_irq_update(dev);
 	spin_unlock_irqrestore(&list_lock, flags);
-	dispc_runtime_put();
 
 	return 0;
 }
@@ -179,12 +177,10 @@ void omap_irq_disable_vblank(struct drm_device *dev, int crtc_id)
 
 	DBG("dev=%p, crtc=%d", dev, crtc_id);
 
-	dispc_runtime_get();
 	spin_lock_irqsave(&list_lock, flags);
 	priv->vblank_mask &= ~pipe2vbl(crtc);
 	omap_irq_update(dev);
 	spin_unlock_irqrestore(&list_lock, flags);
-	dispc_runtime_put();
 }
 
 static irqreturn_t omap_irq_handler(int irq, void *arg)
