aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index db3decffc985..c200e4d71e3d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -48,6 +48,8 @@ struct exynos_drm_crtc {
48 unsigned int pipe; 48 unsigned int pipe;
49 unsigned int dpms; 49 unsigned int dpms;
50 enum exynos_crtc_mode mode; 50 enum exynos_crtc_mode mode;
51 wait_queue_head_t pending_flip_queue;
52 atomic_t pending_flip;
51}; 53};
52 54
53static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) 55static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
@@ -61,6 +63,13 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
61 return; 63 return;
62 } 64 }
63 65
66 if (mode > DRM_MODE_DPMS_ON) {
67 /* wait for the completion of page flip. */
68 wait_event(exynos_crtc->pending_flip_queue,
69 atomic_read(&exynos_crtc->pending_flip) == 0);
70 drm_vblank_off(crtc->dev, exynos_crtc->pipe);
71 }
72
64 exynos_drm_fn_encoder(crtc, &mode, exynos_drm_encoder_crtc_dpms); 73 exynos_drm_fn_encoder(crtc, &mode, exynos_drm_encoder_crtc_dpms);
65 exynos_crtc->dpms = mode; 74 exynos_crtc->dpms = mode;
66} 75}
@@ -224,6 +233,7 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
224 spin_lock_irq(&dev->event_lock); 233 spin_lock_irq(&dev->event_lock);
225 list_add_tail(&event->base.link, 234 list_add_tail(&event->base.link,
226 &dev_priv->pageflip_event_list); 235 &dev_priv->pageflip_event_list);
236 atomic_set(&exynos_crtc->pending_flip, 1);
227 spin_unlock_irq(&dev->event_lock); 237 spin_unlock_irq(&dev->event_lock);
228 238
229 crtc->fb = fb; 239 crtc->fb = fb;
@@ -343,6 +353,8 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
343 353
344 exynos_crtc->pipe = nr; 354 exynos_crtc->pipe = nr;
345 exynos_crtc->dpms = DRM_MODE_DPMS_OFF; 355 exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
356 init_waitqueue_head(&exynos_crtc->pending_flip_queue);
357 atomic_set(&exynos_crtc->pending_flip, 0);
346 exynos_crtc->plane = exynos_plane_init(dev, 1 << nr, true); 358 exynos_crtc->plane = exynos_plane_init(dev, 1 << nr, true);
347 if (!exynos_crtc->plane) { 359 if (!exynos_crtc->plane) {
348 kfree(exynos_crtc); 360 kfree(exynos_crtc);
@@ -397,6 +409,8 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc)
397{ 409{
398 struct exynos_drm_private *dev_priv = dev->dev_private; 410 struct exynos_drm_private *dev_priv = dev->dev_private;
399 struct drm_pending_vblank_event *e, *t; 411 struct drm_pending_vblank_event *e, *t;
412 struct drm_crtc *drm_crtc = dev_priv->crtc[crtc];
413 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(drm_crtc);
400 unsigned long flags; 414 unsigned long flags;
401 415
402 DRM_DEBUG_KMS("%s\n", __FILE__); 416 DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -412,6 +426,8 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc)
412 list_del(&e->base.link); 426 list_del(&e->base.link);
413 drm_send_vblank_event(dev, -1, e); 427 drm_send_vblank_event(dev, -1, e);
414 drm_vblank_put(dev, crtc); 428 drm_vblank_put(dev, crtc);
429 atomic_set(&exynos_crtc->pending_flip, 0);
430 wake_up(&exynos_crtc->pending_flip_queue);
415 } 431 }
416 432
417 spin_unlock_irqrestore(&dev->event_lock, flags); 433 spin_unlock_irqrestore(&dev->event_lock, flags);