static void ipu_crtc_handle_pageflip(struct ipu_crtc *ipu_crtc) { struct drm_pending_vblank_event *e; struct timeval now; unsigned long flags; struct drm_device *drm = ipu_crtc->base.dev; spin_lock_irqsave(&drm->event_lock, flags); e = ipu_crtc->page_flip_event; if (!e) { spin_unlock_irqrestore(&drm->event_lock, flags); return; } do_gettimeofday(&now); e->event.sequence = 0; e->event.tv_sec = now.tv_sec; e->event.tv_usec = now.tv_usec; ipu_crtc->page_flip_event = NULL; imx_drm_crtc_vblank_put(ipu_crtc->imx_crtc); list_add_tail(&e->base.link, &e->base.file_priv->event_list); wake_up_interruptible(&e->base.file_priv->event_wait); spin_unlock_irqrestore(&drm->event_lock, flags); }
static void ipu_crtc_handle_pageflip(struct ipu_crtc *ipu_crtc) { unsigned long flags; struct drm_device *drm = ipu_crtc->base.dev; spin_lock_irqsave(&drm->event_lock, flags); if (ipu_crtc->page_flip_event) drm_send_vblank_event(drm, -1, ipu_crtc->page_flip_event); ipu_crtc->page_flip_event = NULL; imx_drm_crtc_vblank_put(ipu_crtc->imx_crtc); spin_unlock_irqrestore(&drm->event_lock, flags); }
static int ipu_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event, uint32_t page_flip_flags) { struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); struct ipu_flip_work *flip_work; int ret; if (ipu_crtc->flip_state != IPU_FLIP_NONE) return -EBUSY; ret = imx_drm_crtc_vblank_get(ipu_crtc->imx_crtc); if (ret) { dev_dbg(ipu_crtc->dev, "failed to acquire vblank counter\n"); list_del(&event->base.link); return ret; } flip_work = kzalloc(sizeof *flip_work, GFP_KERNEL); if (!flip_work) { ret = -ENOMEM; goto put_vblank; } INIT_WORK(&flip_work->unref_work, ipu_flip_unref_work_func); flip_work->page_flip_event = event; /* get BO backing the old framebuffer and take a reference */ flip_work->bo = &drm_fb_cma_get_gem_obj(crtc->primary->fb, 0)->base; drm_gem_object_reference(flip_work->bo); ipu_crtc->flip_work = flip_work; /* * If the object has a DMABUF attached, we need to wait on its fences * if there are any. */ if (cma_obj->base.dma_buf) { INIT_WORK(&flip_work->fence_work, ipu_flip_fence_work_func); flip_work->crtc = ipu_crtc; ret = reservation_object_get_fences_rcu( cma_obj->base.dma_buf->resv, &flip_work->excl, &flip_work->shared_count, &flip_work->shared); if (unlikely(ret)) { DRM_ERROR("failed to get fences for buffer\n"); goto free_flip_work; } /* No need to queue the worker if the are no fences */ if (!flip_work->excl && !flip_work->shared_count) { ipu_crtc->flip_state = IPU_FLIP_SUBMITTED; } else { ipu_crtc->flip_state = IPU_FLIP_PENDING; queue_work(ipu_crtc->flip_queue, &flip_work->fence_work); } } else { ipu_crtc->flip_state = IPU_FLIP_SUBMITTED; } return 0; free_flip_work: drm_gem_object_unreference_unlocked(flip_work->bo); kfree(flip_work); ipu_crtc->flip_work = NULL; put_vblank: imx_drm_crtc_vblank_put(ipu_crtc->imx_crtc); return ret; }