aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_crtc.c
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2009-12-01 12:01:54 -0500
committerEric Anholt <eric@anholt.net>2009-12-01 12:01:54 -0500
commitf40d6817a5c2bf84f5fe7b5d1a83f1e8f8669951 (patch)
tree1c515a34a60f65cbfd3cf1a387427d0a9fdf878f /drivers/gpu/drm/drm_crtc.c
parent103a196f4224dc6872081305cf7f82ebf67aa7bd (diff)
parent46557bef3f3834ac33031c7be27d39d90d507442 (diff)
Merge remote branch 'airlied/drm-next' into drm-intel-next
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 ee0cde1ecca5..ac2fa193072b 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2479,3 +2479,72 @@ out:
2479 mutex_unlock(&dev->mode_config.mutex); 2479 mutex_unlock(&dev->mode_config.mutex);
2480 return ret; 2480 return ret;
2481} 2481}
2482
2483int drm_mode_page_flip_ioctl(struct drm_device *dev,
2484 void *data, struct drm_file *file_priv)
2485{
2486 struct drm_mode_crtc_page_flip *page_flip = data;
2487 struct drm_mode_object *obj;
2488 struct drm_crtc *crtc;
2489 struct drm_framebuffer *fb;
2490 struct drm_pending_vblank_event *e = NULL;
2491 unsigned long flags;
2492 int ret = -EINVAL;
2493
2494 if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
2495 page_flip->reserved != 0)
2496 return -EINVAL;
2497
2498 mutex_lock(&dev->mode_config.mutex);
2499 obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC);
2500 if (!obj)
2501 goto out;
2502 crtc = obj_to_crtc(obj);
2503
2504 if (crtc->funcs->page_flip == NULL)
2505 goto out;
2506
2507 obj = drm_mode_object_find(dev, page_flip->fb_id, DRM_MODE_OBJECT_FB);
2508 if (!obj)
2509 goto out;
2510 fb = obj_to_fb(obj);
2511
2512 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
2513 ret = -ENOMEM;
2514 spin_lock_irqsave(&dev->event_lock, flags);
2515 if (file_priv->event_space < sizeof e->event) {
2516 spin_unlock_irqrestore(&dev->event_lock, flags);
2517 goto out;
2518 }
2519 file_priv->event_space -= sizeof e->event;
2520 spin_unlock_irqrestore(&dev->event_lock, flags);
2521
2522 e = kzalloc(sizeof *e, GFP_KERNEL);
2523 if (e == NULL) {
2524 spin_lock_irqsave(&dev->event_lock, flags);
2525 file_priv->event_space += sizeof e->event;
2526 spin_unlock_irqrestore(&dev->event_lock, flags);
2527 goto out;
2528 }
2529
2530 e->event.base.type = DRM_EVENT_VBLANK;
2531 e->event.base.length = sizeof e->event;
2532 e->event.user_data = page_flip->user_data;
2533 e->base.event = &e->event.base;
2534 e->base.file_priv = file_priv;
2535 e->base.destroy =
2536 (void (*) (struct drm_pending_event *)) kfree;
2537 }
2538
2539 ret = crtc->funcs->page_flip(crtc, fb, e);
2540 if (ret) {
2541 spin_lock_irqsave(&dev->event_lock, flags);
2542 file_priv->event_space += sizeof e->event;
2543 spin_unlock_irqrestore(&dev->event_lock, flags);
2544 kfree(e);
2545 }
2546
2547out:
2548 mutex_unlock(&dev->mode_config.mutex);
2549 return ret;
2550}