diff options
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_crtc.c | 16 |
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 | ||
53 | static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) | 55 | static 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); |