Esempio n. 1
0
int
drm_vblank_get(struct drm_device *dev, int crtc)
{
	struct drm_vblank_info	*vbl = dev->vblank;
	int			 ret = 0;

	if (dev->irq_enabled == 0)
		return (EINVAL);

	mtx_enter(&vbl->vb_lock);
	DPRINTF("%s: %d refs = %d\n", __func__, crtc,
	    vbl->vb_crtcs[crtc].vbl_refs);
	vbl->vb_crtcs[crtc].vbl_refs++;
	if (vbl->vb_crtcs[crtc].vbl_refs == 1 &&
	    vbl->vb_crtcs[crtc].vbl_enabled == 0) {
		if ((ret = dev->driver->enable_vblank(dev, crtc)) == 0) {
			vbl->vb_crtcs[crtc].vbl_enabled = 1;
			drm_update_vblank_count(dev, crtc);
		} else {
			vbl->vb_crtcs[crtc].vbl_refs--;
		}

	}
	mtx_leave(&vbl->vb_lock);

	return (ret);
}
Esempio n. 2
0
/**
 * drm_vblank_get - get a reference count on vblank events
 * @dev: DRM device
 * @crtc: which CRTC to own
 *
 * Acquire a reference count on vblank events to avoid having them disabled
 * while in use.
 *
 * RETURNS
 * Zero on success, nonzero on failure.
 */
int drm_vblank_get(struct drm_device *dev, int crtc)
{
	int ret = 0;

	mtx_enter(&dev->vbl_lock);
	/* Going from 0->1 means we have to enable interrupts again */
	if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) {
		mtx_enter(&dev->vblank_time_lock);
		if (!dev->vblank_enabled[crtc]) {
			/* Enable vblank irqs under vblank_time_lock protection.
			 * All vblank count & timestamp updates are held off
			 * until we are done reinitializing master counter and
			 * timestamps. Filtercode in drm_handle_vblank() will
			 * prevent double-accounting of same vblank interval.
			 */
			ret = dev->driver->enable_vblank(dev, crtc);
			DPRINTF("enabling vblank on crtc %d, ret: %d\n",
				  crtc, ret);
			if (ret)
				atomic_dec(&dev->vblank_refcount[crtc]);
			else {
				dev->vblank_enabled[crtc] = 1;
				drm_update_vblank_count(dev, crtc);
			}
		}
		mtx_leave(&dev->vblank_time_lock);
	} else {
		if (!dev->vblank_enabled[crtc]) {
			atomic_dec(&dev->vblank_refcount[crtc]);
			ret = -EINVAL;
		}
	}
	mtx_leave(&dev->vbl_lock);

	return ret;
}