static int rcar_du_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event, uint32_t page_flip_flags) { struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); struct drm_device *dev = rcrtc->crtc.dev; unsigned long flags; spin_lock_irqsave(&dev->event_lock, flags); if (rcrtc->event != NULL) { spin_unlock_irqrestore(&dev->event_lock, flags); return -EBUSY; } spin_unlock_irqrestore(&dev->event_lock, flags); crtc->fb = fb; rcar_du_crtc_update_base(rcrtc); if (event) { event->pipe = rcrtc->index; drm_vblank_get(dev, rcrtc->index); spin_lock_irqsave(&dev->event_lock, flags); rcrtc->event = event; spin_unlock_irqrestore(&dev->event_lock, flags); } return 0; }
static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event) { struct drm_device *dev = crtc->dev; struct exynos_drm_private *dev_priv = dev->dev_private; struct exynos_drm_crtc *exynos_crtc = to_exynos_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"); return -EINVAL; } mutex_lock(&dev->struct_mutex); if (event) { /* * the pipe from user always is 0 so we can set pipe number * of current owner to event. */ event->pipe = exynos_crtc->pipe; ret = drm_vblank_get(dev, exynos_crtc->pipe); if (ret) { DRM_DEBUG("failed to acquire vblank counter\n"); goto out; } 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, NULL); if (ret) { crtc->fb = old_fb; spin_lock_irq(&dev->event_lock); drm_vblank_put(dev, exynos_crtc->pipe); list_del(&event->base.link); spin_unlock_irq(&dev->event_lock); goto out; } } out: mutex_unlock(&dev->struct_mutex); return ret; }
void MRSTLFBEnableVSyncInterrupt(MRSTLFB_DEVINFO * psDevinfo) { #if defined(MRST_USING_INTERRUPTS) if( drm_vblank_get( psDevinfo->psDrmDevice , psDevinfo->ui32MainPipe ) ) { DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX "Couldn't get vsync enabled")); } #endif }
static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event) { struct drm_device *dev = crtc->dev; struct exynos_drm_private *dev_priv = dev->dev_private; struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); struct drm_framebuffer *old_fb = crtc->fb; int ret = -EINVAL; DRM_DEBUG_KMS("%s\n", __FILE__); mutex_lock(&dev->struct_mutex); if (event) { /* * the pipe from user always is 0 so we can set pipe number * of current owner to event. */ event->pipe = exynos_crtc->pipe; 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; } list_add_tail(&event->base.link, &dev_priv->pageflip_event_list); crtc->fb = fb; ret = exynos_drm_crtc_update(crtc); if (ret) { crtc->fb = old_fb; drm_vblank_put(dev, exynos_crtc->pipe); list_del(&event->base.link); goto out; } /* * the values related to a buffer of the drm framebuffer * to be applied should be set at here. because these values * first, are set to shadow registers and then to * real registers at vsync front porch period. */ exynos_drm_crtc_apply(crtc); } out: mutex_unlock(&dev->struct_mutex); return ret; }
static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event) { struct drm_device *dev = crtc->dev; struct exynos_drm_private *dev_priv = dev->dev_private; struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); struct drm_framebuffer *old_fb = crtc->fb; int ret = -EINVAL; DRM_DEBUG_KMS("%s\n", __FILE__); mutex_lock(&dev->struct_mutex); if (event) { /* */ event->pipe = exynos_crtc->pipe; 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; } list_add_tail(&event->base.link, &dev_priv->pageflip_event_list); crtc->fb = fb; ret = exynos_drm_crtc_update(crtc); if (ret) { crtc->fb = old_fb; drm_vblank_put(dev, exynos_crtc->pipe); list_del(&event->base.link); goto out; } /* */ exynos_drm_crtc_apply(crtc); } out: mutex_unlock(&dev->struct_mutex); return ret; }
void armada_drm_vbl_event_add(struct armada_crtc *dcrtc, struct armada_vbl_event *evt) { unsigned long flags; spin_lock_irqsave(&dcrtc->irq_lock, flags); if (list_empty(&evt->node)) { list_add_tail(&evt->node, &dcrtc->vbl_list); drm_vblank_get(dcrtc->crtc.dev, dcrtc->num); } spin_unlock_irqrestore(&dcrtc->irq_lock, flags); }
int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct timeval now; union drm_wait_vblank *vblwait = data; int ret, flags, crtc, seq; if (!dev->irq_enabled || dev->vblank == NULL || vblwait->request.type & _DRM_VBLANK_SIGNAL) return (EINVAL); flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK; crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0; if (crtc >= dev->vblank->vb_num) return (EINVAL); if ((ret = drm_vblank_get(dev, crtc)) != 0) return (ret); seq = drm_vblank_count(dev, crtc); if (vblwait->request.type & _DRM_VBLANK_RELATIVE) { vblwait->request.sequence += seq; vblwait->request.type &= ~_DRM_VBLANK_RELATIVE; } flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK; if ((flags & _DRM_VBLANK_NEXTONMISS) && (seq - vblwait->request.sequence) <= (1<<23)) { vblwait->request.sequence = seq + 1; } if (flags & _DRM_VBLANK_EVENT) return (drm_queue_vblank_event(dev, crtc, vblwait, file_priv)); DPRINTF("%s: %d waiting on %d, current %d\n", __func__, crtc, vblwait->request.sequence, drm_vblank_count(dev, crtc)); DRM_WAIT_ON(ret, &dev->vblank->vb_crtcs[crtc], &dev->vblank->vb_lock, 3 * hz, "drmvblq", ((drm_vblank_count(dev, crtc) - vblwait->request.sequence) <= (1 << 23)) || dev->irq_enabled == 0); microtime(&now); vblwait->reply.tval_sec = now.tv_sec; vblwait->reply.tval_usec = now.tv_usec; vblwait->reply.sequence = drm_vblank_count(dev, crtc); DPRINTF("%s: %d done waiting, seq = %d\n", __func__, crtc, vblwait->reply.sequence); drm_vblank_put(dev, crtc); return (ret); }
int drm_modeset_ctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_modeset_ctl *modeset = data; struct drm_vblank *vbl; int crtc, ret = 0; /* not initialised yet, just noop */ if (dev->vblank == NULL) return (0); crtc = modeset->crtc; if (crtc >= dev->vblank->vb_num || crtc < 0) return (EINVAL); vbl = &dev->vblank->vb_crtcs[crtc]; /* * If interrupts are enabled/disabled between calls to this ioctl then * it can get nasty. So just grab a reference so that the interrupts * keep going through the modeset */ switch (modeset->cmd) { case _DRM_PRE_MODESET: DPRINTF("%s: pre modeset on %d\n", __func__, crtc); if (vbl->vbl_inmodeset == 0) { mtx_enter(&dev->vblank->vb_lock); vbl->vbl_inmodeset = 0x1; mtx_leave(&dev->vblank->vb_lock); if (drm_vblank_get(dev, crtc) == 0) vbl->vbl_inmodeset |= 0x2; } break; case _DRM_POST_MODESET: DPRINTF("%s: post modeset on %d\n", __func__, crtc); if (vbl->vbl_inmodeset) { if (vbl->vbl_inmodeset & 0x2) drm_vblank_put(dev, crtc); vbl->vbl_inmodeset = 0; } break; default: ret = EINVAL; break; } return (ret); }
static int vigs_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event) { unsigned long flags; struct vigs_device *vigs_dev = crtc->dev->dev_private; struct drm_framebuffer *old_fb = crtc->fb; int ret = -EINVAL; mutex_lock(&vigs_dev->drm_dev->struct_mutex); if (event) { event->pipe = 0; ret = drm_vblank_get(vigs_dev->drm_dev, 0); if (ret != 0) { DRM_ERROR("failed to acquire vblank counter\n"); goto out; } spin_lock_irqsave(&vigs_dev->drm_dev->event_lock, flags); list_add_tail(&event->base.link, &vigs_dev->pageflip_event_list); spin_unlock_irqrestore(&vigs_dev->drm_dev->event_lock, flags); crtc->fb = fb; ret = vigs_crtc_update(crtc, old_fb); if (ret != 0) { crtc->fb = old_fb; spin_lock_irqsave(&vigs_dev->drm_dev->event_lock, flags); if (atomic_read(&vigs_dev->drm_dev->vblank_refcount[0]) > 0) { /* * Only do this if event wasn't already processed. */ drm_vblank_put(vigs_dev->drm_dev, 0); list_del(&event->base.link); } spin_unlock_irqrestore(&vigs_dev->drm_dev->event_lock, flags); goto out; } } out: mutex_unlock(&vigs_dev->drm_dev->struct_mutex); return ret; }
static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event) { struct drm_device *dev = crtc->dev; struct exynos_drm_private *dev_priv = dev->dev_private; struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); struct drm_framebuffer *old_fb = crtc->fb; int ret = -EINVAL; DRM_DEBUG_KMS("%s\n", __FILE__); mutex_lock(&dev->struct_mutex); if (event) { /* * the pipe from user always is 0 so we can set pipe number * of current owner to event. */ event->pipe = exynos_crtc->pipe; 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; } list_add_tail(&event->base.link, &dev_priv->pageflip_event_list); crtc->fb = fb; ret = exynos_drm_crtc_mode_set_base(crtc, crtc->x, crtc->y, NULL); if (ret) { crtc->fb = old_fb; drm_vblank_put(dev, exynos_crtc->pipe); list_del(&event->base.link); goto out; } } out: mutex_unlock(&dev->struct_mutex); return ret; }
/** * drm_vblank_pre_modeset - account for vblanks across mode sets * @dev: DRM device * @crtc: CRTC in question * * Account for vblank events across mode setting events, which will likely * reset the hardware frame counter. */ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) { /* vblank is not initialized (IRQ not installed ?) */ if (!dev->num_crtcs) return; /* * To avoid all the problems that might happen if interrupts * were enabled/disabled around or between these calls, we just * have the kernel take a reference on the CRTC (just once though * to avoid corrupting the count if multiple, mismatch calls occur), * so that interrupts remain enabled in the interim. */ if (!dev->vblank_inmodeset[crtc]) { dev->vblank_inmodeset[crtc] = 0x1; if (drm_vblank_get(dev, crtc) == 0) dev->vblank_inmodeset[crtc] |= 0x2; } }
static int xylon_drm_crtc_page_flip(struct drm_crtc *base_crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event, u32 page_flip_flags) { struct drm_device *dev = base_crtc->dev; struct xylon_drm_crtc *crtc = to_xylon_crtc(base_crtc); unsigned long flags; int ret; spin_lock_irqsave(&dev->event_lock, flags); if (crtc->event != NULL) { spin_unlock_irqrestore(&dev->event_lock, flags); return -EBUSY; } spin_unlock_irqrestore(&dev->event_lock, flags); ret = xylon_drm_plane_fb_set(base_crtc->primary, fb, 0, 0, base_crtc->hwmode.hdisplay, base_crtc->hwmode.vdisplay, base_crtc->x, base_crtc->y, base_crtc->hwmode.hdisplay, base_crtc->hwmode.vdisplay); if (ret) { DRM_ERROR("failed mode set plane\n"); return ret; } xylon_drm_plane_commit(base_crtc->primary); base_crtc->primary->fb = fb; if (event) { event->pipe = 0; drm_vblank_get(dev, 0); spin_lock_irqsave(&dev->event_lock, flags); crtc->event = event; spin_unlock_irqrestore(&dev->event_lock, flags); } return 0; }
/* page flip functions */ static int xilinx_drm_crtc_page_flip(struct drm_crtc *base_crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event, uint32_t page_flip_flags) { struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc); struct drm_device *drm = base_crtc->dev; unsigned long flags; int ret; spin_lock_irqsave(&drm->event_lock, flags); if (crtc->event != NULL) { spin_unlock_irqrestore(&drm->event_lock, flags); return -EBUSY; } spin_unlock_irqrestore(&drm->event_lock, flags); /* configure a plane */ ret = _xilinx_drm_crtc_mode_set_base(base_crtc, fb, base_crtc->x, base_crtc->y); if (ret) { DRM_ERROR("failed to mode set a plane\n"); return ret; } base_crtc->fb = fb; if (event) { event->pipe = 0; drm_vblank_get(drm, 0); spin_lock_irqsave(&drm->event_lock, flags); crtc->event = event; spin_unlock_irqrestore(&drm->event_lock, flags); } return 0; }