diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index b1dbb60af99f..a316f7336aeb 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -5402,6 +5402,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
5402 | struct drm_crtc *crtc; | 5402 | struct drm_crtc *crtc; |
5403 | struct drm_framebuffer *fb = NULL; | 5403 | struct drm_framebuffer *fb = NULL; |
5404 | struct drm_pending_vblank_event *e = NULL; | 5404 | struct drm_pending_vblank_event *e = NULL; |
5405 | u32 target_vblank = 0; | ||
5405 | int ret = -EINVAL; | 5406 | int ret = -EINVAL; |
5406 | 5407 | ||
5407 | if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || | 5408 | if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || |
@@ -5415,6 +5416,19 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
5415 | if (!crtc) | 5416 | if (!crtc) |
5416 | return -ENOENT; | 5417 | return -ENOENT; |
5417 | 5418 | ||
5419 | if (crtc->funcs->page_flip_target) { | ||
5420 | int r; | ||
5421 | |||
5422 | r = drm_crtc_vblank_get(crtc); | ||
5423 | if (r) | ||
5424 | return r; | ||
5425 | |||
5426 | target_vblank = drm_crtc_vblank_count(crtc) + | ||
5427 | !(page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC); | ||
5428 | } else if (crtc->funcs->page_flip == NULL) { | ||
5429 | return -EINVAL; | ||
5430 | } | ||
5431 | |||
5418 | drm_modeset_lock_crtc(crtc, crtc->primary); | 5432 | drm_modeset_lock_crtc(crtc, crtc->primary); |
5419 | if (crtc->primary->fb == NULL) { | 5433 | if (crtc->primary->fb == NULL) { |
5420 | /* The framebuffer is currently unbound, presumably | 5434 | /* The framebuffer is currently unbound, presumably |
@@ -5425,9 +5439,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
5425 | goto out; | 5439 | goto out; |
5426 | } | 5440 | } |
5427 | 5441 | ||
5428 | if (crtc->funcs->page_flip == NULL) | ||
5429 | goto out; | ||
5430 | |||
5431 | fb = drm_framebuffer_lookup(dev, page_flip->fb_id); | 5442 | fb = drm_framebuffer_lookup(dev, page_flip->fb_id); |
5432 | if (!fb) { | 5443 | if (!fb) { |
5433 | ret = -ENOENT; | 5444 | ret = -ENOENT; |
@@ -5468,7 +5479,12 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
5468 | } | 5479 | } |
5469 | 5480 | ||
5470 | crtc->primary->old_fb = crtc->primary->fb; | 5481 | crtc->primary->old_fb = crtc->primary->fb; |
5471 | ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags); | 5482 | if (crtc->funcs->page_flip_target) |
5483 | ret = crtc->funcs->page_flip_target(crtc, fb, e, | ||
5484 | page_flip->flags, | ||
5485 | target_vblank); | ||
5486 | else | ||
5487 | ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags); | ||
5472 | if (ret) { | 5488 | if (ret) { |
5473 | if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) | 5489 | if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) |
5474 | drm_event_cancel_free(dev, &e->base); | 5490 | drm_event_cancel_free(dev, &e->base); |
@@ -5481,6 +5497,8 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
5481 | } | 5497 | } |
5482 | 5498 | ||
5483 | out: | 5499 | out: |
5500 | if (ret) | ||
5501 | drm_crtc_vblank_put(crtc); | ||
5484 | if (fb) | 5502 | if (fb) |
5485 | drm_framebuffer_unreference(fb); | 5503 | drm_framebuffer_unreference(fb); |
5486 | if (crtc->primary->old_fb) | 5504 | if (crtc->primary->old_fb) |