aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_crtc.c
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2009-11-17 12:43:55 -0500
committerDave Airlie <airlied@redhat.com>2009-11-17 19:05:47 -0500
commitd91d8a3f88059d93e34ac70d059153ec69a9ffc7 (patch)
tree13810c8dbc35522d930b5fc17db35570f3d1e821 /drivers/gpu/drm/drm_crtc.c
parentdad07ca71719598bc990dbdbeda763d15a10e98b (diff)
drm/kms: add page flipping ioctl
This adds a page flipping ioctl to the KMS API. The ioctl takes an fb ID and a ctrc ID and flips the crtc to the given fb at the next vblank. The ioctl returns immediately but the flip doesn't happen until after any rendering that's currently queued up against the new framebuffer is done. After submitting a page flip, any execbuffer involving the old front buffer will block until the flip is completed. Optionally, a vblank event can be generated when the swap eventually happens. Signed-off-by: Kristian Høgsberg <krh@bitplanet.net> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r--drivers/gpu/drm/drm_crtc.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 5cae0b3eee9b..32756e67dd56 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2478,3 +2478,72 @@ out:
2478 mutex_unlock(&dev->mode_config.mutex); 2478 mutex_unlock(&dev->mode_config.mutex);
2479 return ret; 2479 return ret;
2480} 2480}
2481
2482int drm_mode_page_flip_ioctl(struct drm_device *dev,
2483 void *data, struct drm_file *file_priv)
2484{
2485 struct drm_mode_crtc_page_flip *page_flip = data;
2486 struct drm_mode_object *obj;
2487 struct drm_crtc *crtc;
2488 struct drm_framebuffer *fb;
2489 struct drm_pending_vblank_event *e = NULL;
2490 unsigned long flags;
2491 int ret = -EINVAL;
2492
2493 if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
2494 page_flip->reserved != 0)
2495 return -EINVAL;
2496
2497 mutex_lock(&dev->mode_config.mutex);
2498 obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC);
2499 if (!obj)
2500 goto out;
2501 crtc = obj_to_crtc(obj);
2502
2503 if (crtc->funcs->page_flip == NULL)
2504 goto out;
2505
2506 obj = drm_mode_object_find(dev, page_flip->fb_id, DRM_MODE_OBJECT_FB);
2507 if (!obj)
2508 goto out;
2509 fb = obj_to_fb(obj);
2510
2511 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
2512 ret = -ENOMEM;
2513 spin_lock_irqsave(&dev->event_lock, flags);
2514 if (file_priv->event_space < sizeof e->event) {
2515 spin_unlock_irqrestore(&dev->event_lock, flags);
2516 goto out;
2517 }
2518 file_priv->event_space -= sizeof e->event;
2519 spin_unlock_irqrestore(&dev->event_lock, flags);
2520
2521 e = kzalloc(sizeof *e, GFP_KERNEL);
2522 if (e == NULL) {
2523 spin_lock_irqsave(&dev->event_lock, flags);
2524 file_priv->event_space += sizeof e->event;
2525 spin_unlock_irqrestore(&dev->event_lock, flags);
2526 goto out;
2527 }
2528
2529 e->event.base.type = DRM_EVENT_VBLANK;
2530 e->event.base.length = sizeof e->event;
2531 e->event.user_data = page_flip->user_data;
2532 e->base.event = &e->event.base;
2533 e->base.file_priv = file_priv;
2534 e->base.destroy =
2535 (void (*) (struct drm_pending_event *)) kfree;
2536 }
2537
2538 ret = crtc->funcs->page_flip(crtc, fb, e);
2539 if (ret) {
2540 spin_lock_irqsave(&dev->event_lock, flags);
2541 file_priv->event_space += sizeof e->event;
2542 spin_unlock_irqrestore(&dev->event_lock, flags);
2543 kfree(e);
2544 }
2545
2546out:
2547 mutex_unlock(&dev->mode_config.mutex);
2548 return ret;
2549}