diff options
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_crtc.c')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_crtc.c | 66 |
1 files changed, 23 insertions, 43 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index e8894bc9e6d5..9a35d171a6d3 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 { unsigned int pipe; unsigned int dpms; enum exynos_crtc_mode mode; + wait_queue_head_t pending_flip_queue; + atomic_t pending_flip; }; static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) @@ -61,14 +63,19 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) return; } + if (mode > DRM_MODE_DPMS_ON) { + /* wait for the completion of page flip. */ + wait_event(exynos_crtc->pending_flip_queue, + atomic_read(&exynos_crtc->pending_flip) == 0); + drm_vblank_off(crtc->dev, exynos_crtc->pipe); + } + exynos_drm_fn_encoder(crtc, &mode, exynos_drm_encoder_crtc_dpms); exynos_crtc->dpms = mode; } static void exynos_drm_crtc_prepare(struct drm_crtc *crtc) { - DRM_DEBUG_KMS("%s\n", __FILE__); - /* drm framework doesn't check NULL. */ } @@ -76,8 +83,6 @@ static void exynos_drm_crtc_commit(struct drm_crtc *crtc) { struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - DRM_DEBUG_KMS("%s\n", __FILE__); - exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON); exynos_plane_commit(exynos_crtc->plane); exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_ON); @@ -88,8 +93,6 @@ exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - DRM_DEBUG_KMS("%s\n", __FILE__); - /* drm framework doesn't check NULL */ return true; } @@ -106,8 +109,6 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, int pipe = exynos_crtc->pipe; int ret; - DRM_DEBUG_KMS("%s\n", __FILE__); - /* * copy the mode data adjusted by mode_fixup() into crtc->mode * so that hardware can be seet to proper mode. @@ -130,7 +131,7 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, return 0; } -static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, +static int exynos_drm_crtc_mode_set_commit(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb) { struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); @@ -139,8 +140,6 @@ static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, unsigned int crtc_h; int ret; - DRM_DEBUG_KMS("%s\n", __FILE__); - /* when framebuffer changing is requested, crtc's dpms should be on */ if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) { DRM_ERROR("failed framebuffer changing request.\n"); @@ -160,18 +159,16 @@ static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, return 0; } -static void exynos_drm_crtc_load_lut(struct drm_crtc *crtc) +static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb) { - DRM_DEBUG_KMS("%s\n", __FILE__); - /* drm framework doesn't check NULL */ + return exynos_drm_crtc_mode_set_commit(crtc, x, y, old_fb); } static void exynos_drm_crtc_disable(struct drm_crtc *crtc) { struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - DRM_DEBUG_KMS("%s\n", __FILE__); - exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_OFF); exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); } @@ -183,7 +180,6 @@ static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = { .mode_fixup = exynos_drm_crtc_mode_fixup, .mode_set = exynos_drm_crtc_mode_set, .mode_set_base = exynos_drm_crtc_mode_set_base, - .load_lut = exynos_drm_crtc_load_lut, .disable = exynos_drm_crtc_disable, }; @@ -197,8 +193,6 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *old_fb = crtc->fb; int ret = -EINVAL; - DRM_DEBUG_KMS("%s\n", __FILE__); - /* when the page flip is requested, crtc's dpms should be on */ if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) { DRM_ERROR("failed page flip request.\n"); @@ -217,7 +211,6 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, ret = drm_vblank_get(dev, exynos_crtc->pipe); if (ret) { DRM_DEBUG("failed to acquire vblank counter\n"); - list_del(&event->base.link); goto out; } @@ -225,10 +218,11 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, spin_lock_irq(&dev->event_lock); list_add_tail(&event->base.link, &dev_priv->pageflip_event_list); + atomic_set(&exynos_crtc->pending_flip, 1); spin_unlock_irq(&dev->event_lock); crtc->fb = fb; - ret = exynos_drm_crtc_mode_set_base(crtc, crtc->x, crtc->y, + ret = exynos_drm_crtc_mode_set_commit(crtc, crtc->x, crtc->y, NULL); if (ret) { crtc->fb = old_fb; @@ -251,8 +245,6 @@ static void exynos_drm_crtc_destroy(struct drm_crtc *crtc) struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); struct exynos_drm_private *private = crtc->dev->dev_private; - DRM_DEBUG_KMS("%s\n", __FILE__); - private->crtc[exynos_crtc->pipe] = NULL; drm_crtc_cleanup(crtc); @@ -267,8 +259,6 @@ static int exynos_drm_crtc_set_property(struct drm_crtc *crtc, struct exynos_drm_private *dev_priv = dev->dev_private; struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - DRM_DEBUG_KMS("%s\n", __func__); - if (property == dev_priv->crtc_mode_property) { enum exynos_crtc_mode mode = val; @@ -313,8 +303,6 @@ static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc) struct exynos_drm_private *dev_priv = dev->dev_private; struct drm_property *prop; - DRM_DEBUG_KMS("%s\n", __func__); - prop = dev_priv->crtc_mode_property; if (!prop) { prop = drm_property_create_enum(dev, 0, "mode", mode_names, @@ -334,8 +322,6 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr) struct exynos_drm_private *private = dev->dev_private; struct drm_crtc *crtc; - DRM_DEBUG_KMS("%s\n", __FILE__); - exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL); if (!exynos_crtc) { DRM_ERROR("failed to allocate exynos crtc\n"); @@ -344,6 +330,8 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr) exynos_crtc->pipe = nr; exynos_crtc->dpms = DRM_MODE_DPMS_OFF; + init_waitqueue_head(&exynos_crtc->pending_flip_queue); + atomic_set(&exynos_crtc->pending_flip, 0); exynos_crtc->plane = exynos_plane_init(dev, 1 << nr, true); if (!exynos_crtc->plane) { kfree(exynos_crtc); @@ -368,8 +356,6 @@ int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc) struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(private->crtc[crtc]); - DRM_DEBUG_KMS("%s\n", __FILE__); - if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) return -EPERM; @@ -385,8 +371,6 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc) struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(private->crtc[crtc]); - DRM_DEBUG_KMS("%s\n", __FILE__); - if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) return; @@ -398,11 +382,10 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc) { struct exynos_drm_private *dev_priv = dev->dev_private; struct drm_pending_vblank_event *e, *t; - struct timeval now; + struct drm_crtc *drm_crtc = dev_priv->crtc[crtc]; + struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(drm_crtc); unsigned long flags; - DRM_DEBUG_KMS("%s\n", __FILE__); - spin_lock_irqsave(&dev->event_lock, flags); list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list, @@ -411,14 +394,11 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc) if (crtc != e->pipe) continue; - do_gettimeofday(&now); - e->event.sequence = 0; - e->event.tv_sec = now.tv_sec; - e->event.tv_usec = now.tv_usec; - - list_move_tail(&e->base.link, &e->base.file_priv->event_list); - wake_up_interruptible(&e->base.file_priv->event_wait); + list_del(&e->base.link); + drm_send_vblank_event(dev, -1, e); drm_vblank_put(dev, crtc); + atomic_set(&exynos_crtc->pending_flip, 0); + wake_up(&exynos_crtc->pending_flip_queue); } spin_unlock_irqrestore(&dev->event_lock, flags); |