drm_irq.c revision 189130
1145132Sanholt/*- 2145132Sanholt * Copyright 2003 Eric Anholt 3145132Sanholt * All Rights Reserved. 4145132Sanholt * 5145132Sanholt * Permission is hereby granted, free of charge, to any person obtaining a 6145132Sanholt * copy of this software and associated documentation files (the "Software"), 7145132Sanholt * to deal in the Software without restriction, including without limitation 8145132Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9145132Sanholt * and/or sell copies of the Software, and to permit persons to whom the 10145132Sanholt * Software is furnished to do so, subject to the following conditions: 11145132Sanholt * 12145132Sanholt * The above copyright notice and this permission notice (including the next 13145132Sanholt * paragraph) shall be included in all copies or substantial portions of the 14145132Sanholt * Software. 15145132Sanholt * 16145132Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17145132Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18145132Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19145132Sanholt * ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20145132Sanholt * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21145132Sanholt * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22145132Sanholt * 23145132Sanholt * Authors: 24145132Sanholt * Eric Anholt <anholt@FreeBSD.org> 25145132Sanholt * 26145132Sanholt */ 27145132Sanholt 28152909Sanholt#include <sys/cdefs.h> 29152909Sanholt__FBSDID("$FreeBSD: head/sys/dev/drm/drm_irq.c 189130 2009-02-28 02:37:55Z rnoland $"); 30152909Sanholt 31182080Srnoland/** @file drm_irq.c 32182080Srnoland * Support code for handling setup/teardown of interrupt handlers and 33182080Srnoland * handing interrupt handlers off to the drivers. 34182080Srnoland */ 35182080Srnoland 36145132Sanholt#include "dev/drm/drmP.h" 37145132Sanholt#include "dev/drm/drm.h" 38145132Sanholt 39182080Srnolandint drm_irq_by_busid(struct drm_device *dev, void *data, 40182080Srnoland struct drm_file *file_priv) 41145132Sanholt{ 42183573Srnoland struct drm_irq_busid *irq = data; 43145132Sanholt 44182080Srnoland if ((irq->busnum >> 8) != dev->pci_domain || 45182080Srnoland (irq->busnum & 0xff) != dev->pci_bus || 46182080Srnoland irq->devnum != dev->pci_slot || 47182080Srnoland irq->funcnum != dev->pci_func) 48145132Sanholt return EINVAL; 49145132Sanholt 50182080Srnoland irq->irq = dev->irq; 51145132Sanholt 52145132Sanholt DRM_DEBUG("%d:%d:%d => IRQ %d\n", 53183573Srnoland irq->busnum, irq->devnum, irq->funcnum, irq->irq); 54145132Sanholt 55145132Sanholt return 0; 56145132Sanholt} 57145132Sanholt 58145132Sanholtstatic irqreturn_t 59145132Sanholtdrm_irq_handler_wrap(DRM_IRQ_ARGS) 60145132Sanholt{ 61182080Srnoland struct drm_device *dev = arg; 62145132Sanholt 63145132Sanholt DRM_SPINLOCK(&dev->irq_lock); 64183573Srnoland dev->driver->irq_handler(arg); 65145132Sanholt DRM_SPINUNLOCK(&dev->irq_lock); 66145132Sanholt} 67145132Sanholt 68182080Srnolandstatic void vblank_disable_fn(void *arg) 69145132Sanholt{ 70182080Srnoland struct drm_device *dev = (struct drm_device *)arg; 71182080Srnoland int i; 72182080Srnoland 73182080Srnoland if (callout_pending(&dev->vblank_disable_timer)) { 74182080Srnoland /* callout was reset */ 75182080Srnoland return; 76182080Srnoland } 77182080Srnoland if (!callout_active(&dev->vblank_disable_timer)) { 78182080Srnoland /* callout was stopped */ 79182080Srnoland return; 80182080Srnoland } 81182080Srnoland callout_deactivate(&dev->vblank_disable_timer); 82182080Srnoland 83183573Srnoland DRM_DEBUG("vblank_disable_allowed=%d\n", dev->vblank_disable_allowed); 84182080Srnoland if (!dev->vblank_disable_allowed) 85182080Srnoland return; 86182080Srnoland 87182080Srnoland for (i = 0; i < dev->num_crtcs; i++) { 88182080Srnoland if (atomic_read(&dev->vblank[i].refcount) == 0 && 89182080Srnoland dev->vblank[i].enabled) { 90182080Srnoland DRM_DEBUG("disabling vblank on crtc %d\n", i); 91182080Srnoland dev->vblank[i].last = 92183573Srnoland dev->driver->get_vblank_counter(dev, i); 93183573Srnoland dev->driver->disable_vblank(dev, i); 94182080Srnoland dev->vblank[i].enabled = 0; 95182080Srnoland } 96182080Srnoland } 97182080Srnoland} 98182080Srnoland 99189130Srnolandvoid drm_vblank_cleanup(struct drm_device *dev) 100182080Srnoland{ 101182080Srnoland unsigned long irqflags; 102182080Srnoland 103182080Srnoland /* Bail if the driver didn't call drm_vblank_init() */ 104182080Srnoland if (dev->num_crtcs == 0) 105183573Srnoland return; 106182080Srnoland 107182080Srnoland DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags); 108182080Srnoland callout_stop(&dev->vblank_disable_timer); 109182080Srnoland DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags); 110182080Srnoland 111182080Srnoland callout_drain(&dev->vblank_disable_timer); 112182080Srnoland 113182080Srnoland vblank_disable_fn((void *)dev); 114182080Srnoland 115183833Srnoland free(dev->vblank, DRM_MEM_DRIVER); 116182080Srnoland 117182080Srnoland dev->num_crtcs = 0; 118182080Srnoland} 119182080Srnoland 120182080Srnolandint drm_vblank_init(struct drm_device *dev, int num_crtcs) 121182080Srnoland{ 122182080Srnoland int i, ret = ENOMEM; 123182080Srnoland 124182080Srnoland callout_init_mtx(&dev->vblank_disable_timer, &dev->vbl_lock, 0); 125182080Srnoland atomic_set(&dev->vbl_signal_pending, 0); 126182080Srnoland dev->num_crtcs = num_crtcs; 127182080Srnoland 128183833Srnoland dev->vblank = malloc(sizeof(struct drm_vblank_info) * num_crtcs, 129183833Srnoland DRM_MEM_DRIVER, M_NOWAIT | M_ZERO); 130182080Srnoland if (!dev->vblank) 131182080Srnoland goto err; 132182080Srnoland 133183573Srnoland DRM_DEBUG("\n"); 134183573Srnoland 135182080Srnoland /* Zero per-crtc vblank stuff */ 136182080Srnoland for (i = 0; i < num_crtcs; i++) { 137182080Srnoland DRM_INIT_WAITQUEUE(&dev->vblank[i].queue); 138182080Srnoland TAILQ_INIT(&dev->vblank[i].sigs); 139182080Srnoland atomic_set(&dev->vblank[i].count, 0); 140182080Srnoland atomic_set(&dev->vblank[i].refcount, 0); 141182080Srnoland } 142182080Srnoland 143182080Srnoland dev->vblank_disable_allowed = 0; 144182080Srnoland 145182080Srnoland return 0; 146182080Srnoland 147182080Srnolanderr: 148182080Srnoland drm_vblank_cleanup(dev); 149182080Srnoland return ret; 150182080Srnoland} 151182080Srnoland 152182080Srnolandint drm_irq_install(struct drm_device *dev) 153182080Srnoland{ 154145132Sanholt int retcode; 155145132Sanholt 156145132Sanholt if (dev->irq == 0 || dev->dev_private == NULL) 157182080Srnoland return EINVAL; 158145132Sanholt 159183573Srnoland DRM_DEBUG("irq=%d\n", dev->irq); 160145132Sanholt 161145132Sanholt DRM_LOCK(); 162145132Sanholt if (dev->irq_enabled) { 163145132Sanholt DRM_UNLOCK(); 164182080Srnoland return EBUSY; 165145132Sanholt } 166145132Sanholt dev->irq_enabled = 1; 167145132Sanholt 168145132Sanholt dev->context_flag = 0; 169145132Sanholt 170183573Srnoland /* Before installing handler */ 171183573Srnoland dev->driver->irq_preinstall(dev); 172145132Sanholt DRM_UNLOCK(); 173145132Sanholt 174183573Srnoland /* Install handler */ 175182080Srnoland#if __FreeBSD_version >= 700031 176182080Srnoland retcode = bus_setup_intr(dev->device, dev->irqr, 177182080Srnoland INTR_TYPE_TTY | INTR_MPSAFE, 178182080Srnoland NULL, drm_irq_handler_wrap, dev, &dev->irqh); 179145132Sanholt#else 180182080Srnoland retcode = bus_setup_intr(dev->device, dev->irqr, 181182080Srnoland INTR_TYPE_TTY | INTR_MPSAFE, 182182080Srnoland drm_irq_handler_wrap, dev, &dev->irqh); 183145132Sanholt#endif 184145132Sanholt if (retcode != 0) 185145132Sanholt goto err; 186145132Sanholt 187183573Srnoland /* After installing handler */ 188145132Sanholt DRM_LOCK(); 189183573Srnoland dev->driver->irq_postinstall(dev); 190145132Sanholt DRM_UNLOCK(); 191145132Sanholt 192145132Sanholt return 0; 193145132Sanholterr: 194145132Sanholt DRM_LOCK(); 195145132Sanholt dev->irq_enabled = 0; 196145132Sanholt DRM_UNLOCK(); 197189052Srnoland 198145132Sanholt return retcode; 199145132Sanholt} 200145132Sanholt 201182080Srnolandint drm_irq_uninstall(struct drm_device *dev) 202145132Sanholt{ 203145132Sanholt if (!dev->irq_enabled) 204182080Srnoland return EINVAL; 205145132Sanholt 206145132Sanholt dev->irq_enabled = 0; 207145132Sanholt 208183573Srnoland DRM_DEBUG("irq=%d\n", dev->irq); 209145132Sanholt 210183573Srnoland dev->driver->irq_uninstall(dev); 211145132Sanholt 212145132Sanholt DRM_UNLOCK(); 213145132Sanholt bus_teardown_intr(dev->device, dev->irqr, dev->irqh); 214145132Sanholt DRM_LOCK(); 215183573Srnoland 216145132Sanholt return 0; 217145132Sanholt} 218145132Sanholt 219182080Srnolandint drm_control(struct drm_device *dev, void *data, struct drm_file *file_priv) 220145132Sanholt{ 221183573Srnoland struct drm_control *ctl = data; 222145132Sanholt int err; 223145132Sanholt 224183573Srnoland switch (ctl->func) { 225145132Sanholt case DRM_INST_HANDLER: 226145132Sanholt /* Handle drivers whose DRM used to require IRQ setup but the 227145132Sanholt * no longer does. 228145132Sanholt */ 229183573Srnoland if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 230145132Sanholt return 0; 231145132Sanholt if (dev->if_version < DRM_IF_VERSION(1, 2) && 232182080Srnoland ctl->irq != dev->irq) 233182080Srnoland return EINVAL; 234145132Sanholt return drm_irq_install(dev); 235145132Sanholt case DRM_UNINST_HANDLER: 236183573Srnoland if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 237145132Sanholt return 0; 238145132Sanholt DRM_LOCK(); 239145132Sanholt err = drm_irq_uninstall(dev); 240145132Sanholt DRM_UNLOCK(); 241145132Sanholt return err; 242145132Sanholt default: 243182080Srnoland return EINVAL; 244145132Sanholt } 245145132Sanholt} 246145132Sanholt 247182080Srnolandu32 drm_vblank_count(struct drm_device *dev, int crtc) 248145132Sanholt{ 249182080Srnoland return atomic_read(&dev->vblank[crtc].count); 250182080Srnoland} 251145132Sanholt 252182080Srnolandstatic void drm_update_vblank_count(struct drm_device *dev, int crtc) 253182080Srnoland{ 254182080Srnoland u32 cur_vblank, diff; 255182080Srnoland 256182080Srnoland /* 257182080Srnoland * Interrupts were disabled prior to this call, so deal with counter 258182080Srnoland * wrap if needed. 259182080Srnoland * NOTE! It's possible we lost a full dev->max_vblank_count events 260182080Srnoland * here if the register is small or we had vblank interrupts off for 261182080Srnoland * a long time. 262182080Srnoland */ 263183573Srnoland cur_vblank = dev->driver->get_vblank_counter(dev, crtc); 264182080Srnoland diff = cur_vblank - dev->vblank[crtc].last; 265182080Srnoland if (cur_vblank < dev->vblank[crtc].last) { 266182080Srnoland diff += dev->max_vblank_count; 267182080Srnoland 268183573Srnoland DRM_DEBUG("vblank[%d].last=0x%x, cur_vblank=0x%x => diff=0x%x\n", 269182080Srnoland crtc, dev->vblank[crtc].last, cur_vblank, diff); 270182080Srnoland } 271182080Srnoland 272182080Srnoland DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n", 273182080Srnoland crtc, diff); 274182080Srnoland 275182080Srnoland atomic_add(diff, &dev->vblank[crtc].count); 276182080Srnoland} 277182080Srnoland 278182080Srnolandint drm_vblank_get(struct drm_device *dev, int crtc) 279182080Srnoland{ 280182080Srnoland unsigned long irqflags; 281182080Srnoland int ret = 0; 282182080Srnoland 283182080Srnoland DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags); 284182080Srnoland /* Going from 0->1 means we have to enable interrupts again */ 285182080Srnoland atomic_add_acq_int(&dev->vblank[crtc].refcount, 1); 286189050Srnoland DRM_DEBUG("vblank refcount = %d\n", dev->vblank[crtc].refcount); 287182080Srnoland if (dev->vblank[crtc].refcount == 1 && 288182080Srnoland !dev->vblank[crtc].enabled) { 289183573Srnoland ret = dev->driver->enable_vblank(dev, crtc); 290182080Srnoland if (ret) 291182080Srnoland atomic_dec(&dev->vblank[crtc].refcount); 292182080Srnoland else { 293182080Srnoland dev->vblank[crtc].enabled = 1; 294182080Srnoland drm_update_vblank_count(dev, crtc); 295182080Srnoland } 296182080Srnoland } 297182080Srnoland DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags); 298182080Srnoland 299182080Srnoland return ret; 300182080Srnoland} 301182080Srnoland 302182080Srnolandvoid drm_vblank_put(struct drm_device *dev, int crtc) 303182080Srnoland{ 304182080Srnoland unsigned long irqflags; 305182080Srnoland 306182080Srnoland DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags); 307182080Srnoland /* Last user schedules interrupt disable */ 308182080Srnoland atomic_subtract_acq_int(&dev->vblank[crtc].refcount, 1); 309189050Srnoland DRM_DEBUG("vblank refcount = %d\n", dev->vblank[crtc].refcount); 310182080Srnoland if (dev->vblank[crtc].refcount == 0) 311182080Srnoland callout_reset(&dev->vblank_disable_timer, 5 * DRM_HZ, 312182080Srnoland (timeout_t *)vblank_disable_fn, (void *)dev); 313182080Srnoland DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags); 314182080Srnoland} 315182080Srnoland 316182080Srnolandint drm_modeset_ctl(struct drm_device *dev, void *data, 317182080Srnoland struct drm_file *file_priv) 318182080Srnoland{ 319182080Srnoland struct drm_modeset_ctl *modeset = data; 320182080Srnoland unsigned long irqflags; 321182080Srnoland int crtc, ret = 0; 322182080Srnoland 323183573Srnoland DRM_DEBUG("num_crtcs=%d\n", dev->num_crtcs); 324182080Srnoland /* If drm_vblank_init() hasn't been called yet, just no-op */ 325182080Srnoland if (!dev->num_crtcs) 326183573Srnoland goto out; 327182080Srnoland 328182080Srnoland crtc = modeset->crtc; 329183573Srnoland DRM_DEBUG("crtc=%d\n", crtc); 330182080Srnoland if (crtc >= dev->num_crtcs) { 331182080Srnoland ret = EINVAL; 332182080Srnoland goto out; 333182080Srnoland } 334182080Srnoland 335182080Srnoland /* 336182080Srnoland * To avoid all the problems that might happen if interrupts 337182080Srnoland * were enabled/disabled around or between these calls, we just 338182080Srnoland * have the kernel take a reference on the CRTC (just once though 339182080Srnoland * to avoid corrupting the count if multiple, mismatch calls occur), 340182080Srnoland * so that interrupts remain enabled in the interim. 341182080Srnoland */ 342182080Srnoland switch (modeset->cmd) { 343182080Srnoland case _DRM_PRE_MODESET: 344183573Srnoland DRM_DEBUG("pre-modeset\n"); 345182080Srnoland if (!dev->vblank[crtc].inmodeset) { 346182080Srnoland dev->vblank[crtc].inmodeset = 1; 347182080Srnoland drm_vblank_get(dev, crtc); 348182080Srnoland } 349182080Srnoland break; 350182080Srnoland case _DRM_POST_MODESET: 351183573Srnoland DRM_DEBUG("post-modeset\n"); 352182080Srnoland if (dev->vblank[crtc].inmodeset) { 353182080Srnoland DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags); 354182080Srnoland dev->vblank_disable_allowed = 1; 355182080Srnoland dev->vblank[crtc].inmodeset = 0; 356182080Srnoland DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags); 357182080Srnoland drm_vblank_put(dev, crtc); 358182080Srnoland } 359182080Srnoland break; 360182080Srnoland default: 361182080Srnoland ret = EINVAL; 362182080Srnoland break; 363182080Srnoland } 364182080Srnoland 365182080Srnolandout: 366182080Srnoland return ret; 367182080Srnoland} 368182080Srnoland 369182080Srnolandint drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv) 370182080Srnoland{ 371183573Srnoland union drm_wait_vblank *vblwait = data; 372189050Srnoland unsigned int flags, seq, crtc; 373182080Srnoland int ret = 0; 374182080Srnoland 375145132Sanholt if (!dev->irq_enabled) 376182080Srnoland return EINVAL; 377145132Sanholt 378182080Srnoland if (vblwait->request.type & 379182080Srnoland ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) { 380182080Srnoland DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n", 381182080Srnoland vblwait->request.type, 382182080Srnoland (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)); 383182080Srnoland return EINVAL; 384182080Srnoland } 385145132Sanholt 386182080Srnoland flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK; 387182080Srnoland crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0; 388182080Srnoland 389182080Srnoland if (crtc >= dev->num_crtcs) 390182080Srnoland return EINVAL; 391182080Srnoland 392182080Srnoland ret = drm_vblank_get(dev, crtc); 393189050Srnoland if (ret) { 394189050Srnoland DRM_ERROR("failed to acquire vblank counter, %d\n", ret); 395183573Srnoland return ret; 396189050Srnoland } 397182080Srnoland seq = drm_vblank_count(dev, crtc); 398182080Srnoland 399182080Srnoland switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) { 400182080Srnoland case _DRM_VBLANK_RELATIVE: 401182080Srnoland vblwait->request.sequence += seq; 402182080Srnoland vblwait->request.type &= ~_DRM_VBLANK_RELATIVE; 403182080Srnoland case _DRM_VBLANK_ABSOLUTE: 404182080Srnoland break; 405182080Srnoland default: 406182080Srnoland ret = EINVAL; 407182080Srnoland goto done; 408145132Sanholt } 409145132Sanholt 410182080Srnoland if ((flags & _DRM_VBLANK_NEXTONMISS) && 411182080Srnoland (seq - vblwait->request.sequence) <= (1<<23)) { 412182080Srnoland vblwait->request.sequence = seq + 1; 413182080Srnoland } 414182080Srnoland 415145132Sanholt if (flags & _DRM_VBLANK_SIGNAL) { 416145132Sanholt#if 0 /* disabled */ 417183833Srnoland drm_vbl_sig_t *vbl_sig = malloc(sizeof(drm_vbl_sig_t), 418183833Srnoland DRM_MEM_DRIVER, M_NOWAIT | M_ZERO); 419145132Sanholt if (vbl_sig == NULL) 420145132Sanholt return ENOMEM; 421145132Sanholt 422182080Srnoland vbl_sig->sequence = vblwait->request.sequence; 423182080Srnoland vbl_sig->signo = vblwait->request.signal; 424145132Sanholt vbl_sig->pid = DRM_CURRENTPID; 425145132Sanholt 426182080Srnoland vblwait->reply.sequence = atomic_read(&dev->vbl_received); 427145132Sanholt 428182080Srnoland DRM_SPINLOCK(&dev->vbl_lock); 429145132Sanholt TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link); 430182080Srnoland DRM_SPINUNLOCK(&dev->vbl_lock); 431145132Sanholt ret = 0; 432145132Sanholt#endif 433145132Sanholt ret = EINVAL; 434145132Sanholt } else { 435189050Srnoland DRM_DEBUG("waiting on vblank count %d, crtc %d\n", 436189050Srnoland vblwait->request.sequence, crtc); 437189050Srnoland for ( ret = 0 ; !ret && !((drm_vblank_count(dev, crtc) - 438189050Srnoland vblwait->request.sequence) <= (1 << 23)) ; ) { 439189050Srnoland mtx_lock(&dev->irq_lock); 440189050Srnoland if (!((drm_vblank_count(dev, crtc) - 441189050Srnoland vblwait->request.sequence) <= (1 << 23))) 442189050Srnoland ret = mtx_sleep(&dev->vblank[crtc].queue, 443189050Srnoland &dev->irq_lock, PCATCH, "vblwtq", 444189050Srnoland 3 * DRM_HZ); 445189050Srnoland mtx_unlock(&dev->irq_lock); 446189050Srnoland } 447182080Srnoland 448189050Srnoland DRM_DEBUG("return = %d\n", ret); 449182080Srnoland if (ret != EINTR) { 450182080Srnoland struct timeval now; 451182080Srnoland 452182080Srnoland microtime(&now); 453182080Srnoland vblwait->reply.tval_sec = now.tv_sec; 454182080Srnoland vblwait->reply.tval_usec = now.tv_usec; 455182080Srnoland vblwait->reply.sequence = drm_vblank_count(dev, crtc); 456189050Srnoland DRM_DEBUG("returning %d to client\n", 457189050Srnoland vblwait->reply.sequence); 458189050Srnoland } else { 459189050Srnoland DRM_DEBUG("vblank wait interrupted by signal\n"); 460182080Srnoland } 461145132Sanholt } 462145132Sanholt 463182080Srnolanddone: 464182080Srnoland drm_vblank_put(dev, crtc); 465145132Sanholt return ret; 466145132Sanholt} 467145132Sanholt 468182080Srnolandvoid drm_vbl_send_signals(struct drm_device *dev, int crtc) 469145132Sanholt{ 470145132Sanholt} 471145132Sanholt 472145132Sanholt#if 0 /* disabled */ 473182080Srnolandvoid drm_vbl_send_signals(struct drm_device *dev, int crtc ) 474145132Sanholt{ 475145132Sanholt drm_vbl_sig_t *vbl_sig; 476145132Sanholt unsigned int vbl_seq = atomic_read( &dev->vbl_received ); 477145132Sanholt struct proc *p; 478145132Sanholt 479145132Sanholt vbl_sig = TAILQ_FIRST(&dev->vbl_sig_list); 480145132Sanholt while (vbl_sig != NULL) { 481145132Sanholt drm_vbl_sig_t *next = TAILQ_NEXT(vbl_sig, link); 482145132Sanholt 483183573Srnoland if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) { 484145132Sanholt p = pfind(vbl_sig->pid); 485145132Sanholt if (p != NULL) 486145132Sanholt psignal(p, vbl_sig->signo); 487145132Sanholt 488145132Sanholt TAILQ_REMOVE(&dev->vbl_sig_list, vbl_sig, link); 489145132Sanholt DRM_FREE(vbl_sig,sizeof(*vbl_sig)); 490145132Sanholt } 491145132Sanholt vbl_sig = next; 492145132Sanholt } 493145132Sanholt} 494145132Sanholt#endif 495182080Srnoland 496182080Srnolandvoid drm_handle_vblank(struct drm_device *dev, int crtc) 497182080Srnoland{ 498182080Srnoland atomic_inc(&dev->vblank[crtc].count); 499182080Srnoland DRM_WAKEUP(&dev->vblank[crtc].queue); 500182080Srnoland drm_vbl_send_signals(dev, crtc); 501182080Srnoland} 502182080Srnoland 503