From b6610363e373c13a2e7fdee8691756e1768bdd57 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 15 Jun 2007 11:21:57 -0700 Subject: [PATCH] First cut at radeon support for the vblank rework. --- linux-core/radeon_drv.c | 8 +-- shared-core/radeon_drv.h | 12 ++-- shared-core/radeon_irq.c | 158 ++++++++++++++++++++--------------------------- 3 files changed, 79 insertions(+), 99 deletions(-) diff --git a/linux-core/radeon_drv.c b/linux-core/radeon_drv.c index 327a6a97..39c35134 100644 --- a/linux-core/radeon_drv.c +++ b/linux-core/radeon_drv.c @@ -60,8 +60,7 @@ static int probe(struct pci_dev *pdev, const struct pci_device_id *ent); static struct drm_driver driver = { .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | - DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | - DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2, + DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED, .dev_priv_size = sizeof(drm_radeon_buf_priv_t), .load = radeon_driver_load, .firstopen = radeon_driver_firstopen, @@ -70,8 +69,9 @@ static struct drm_driver driver = { .postclose = radeon_driver_postclose, .lastclose = radeon_driver_lastclose, .unload = radeon_driver_unload, - .vblank_wait = radeon_driver_vblank_wait, - .vblank_wait2 = radeon_driver_vblank_wait2, + .get_vblank_counter = radeon_get_vblank_counter, + .enable_vblank = radeon_enable_vblank, + .disable_vblank = radeon_disable_vblank, .dri_library_name = dri_library_name, .irq_preinstall = radeon_driver_irq_preinstall, .irq_postinstall = radeon_driver_irq_postinstall, diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index 283dee33..5f671df6 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -366,13 +366,12 @@ extern int radeon_irq_emit(DRM_IOCTL_ARGS); extern int radeon_irq_wait(DRM_IOCTL_ARGS); extern void radeon_do_release(drm_device_t * dev); -extern int radeon_driver_vblank_wait(drm_device_t * dev, - unsigned int *sequence, int relative); -extern int radeon_driver_vblank_wait2(drm_device_t * dev, - unsigned int *sequence, int relative); +extern u32 radeon_get_vblank_counter(drm_device_t *dev, int crtc); +extern int radeon_enable_vblank(drm_device_t *dev, int crtc); +extern void radeon_disable_vblank(drm_device_t *dev, int crtc); extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS); extern void radeon_driver_irq_preinstall(drm_device_t * dev); -extern void radeon_driver_irq_postinstall(drm_device_t * dev); +extern int radeon_driver_irq_postinstall(drm_device_t * dev); extern void radeon_driver_irq_uninstall(drm_device_t * dev); extern int radeon_vblank_crtc_get(drm_device_t *dev); extern int radeon_vblank_crtc_set(drm_device_t *dev, int64_t value); @@ -513,6 +512,9 @@ extern int r300_do_cp_cmdbuf(drm_device_t *dev, DRMFILE filp, #define RADEON_CRTC_CRNT_FRAME 0x0214 #define RADEON_CRTC2_CRNT_FRAME 0x0314 +#define RADEON_CRTC_CRNT_FRAME 0x0214 +#define RADEON_CRTC2_CRNT_FRAME 0x0314 + #define RADEON_GEN_INT_CNTL 0x0040 # define RADEON_CRTC_VBLANK_MASK (1 << 0) # define RADEON_CRTC2_VBLANK_MASK (1 << 9) diff --git a/shared-core/radeon_irq.c b/shared-core/radeon_irq.c index 2534ff10..46ec035d 100644 --- a/shared-core/radeon_irq.c +++ b/shared-core/radeon_irq.c @@ -47,6 +47,50 @@ static void radeon_irq_set_state(drm_device_t *dev, u32 mask, int state) RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); } +int radeon_enable_vblank(drm_device_t *dev, int crtc) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + if (!(dev_priv->vblank_crtc & (1 << crtc))) + return -EINVAL; + + switch (crtc) { + case 0: + radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1); + break; + case 1: + radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1); + break; + default: + DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", + crtc); + break; + } + + return 0; +} + +void radeon_disable_vblank(drm_device_t *dev, int crtc) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + if (!(dev_priv->vblank_crtc & (1 << crtc))) + return; + + switch (crtc) { + case 0: + radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0); + break; + case 1: + radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0); + break; + default: + DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", + crtc); + break; + } +} + static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv, u32 mask) { @@ -89,30 +133,14 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) return IRQ_NONE; /* SW interrupt */ - if (stat & RADEON_SW_INT_TEST) { + if (stat & RADEON_SW_INT_TEST) DRM_WAKEUP(&dev_priv->swi_queue); - } /* VBLANK interrupt */ - if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) { - int vblank_crtc = dev_priv->vblank_crtc; - - if ((vblank_crtc & - (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) == - (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) { - if (stat & RADEON_CRTC_VBLANK_STAT) - atomic_inc(&dev->vbl_received); - if (stat & RADEON_CRTC2_VBLANK_STAT) - atomic_inc(&dev->vbl_received2); - } else if (((stat & RADEON_CRTC_VBLANK_STAT) && - (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) || - ((stat & RADEON_CRTC2_VBLANK_STAT) && - (vblank_crtc & DRM_RADEON_VBLANK_CRTC2))) - atomic_inc(&dev->vbl_received); - - DRM_WAKEUP(&dev->vbl_queue); - drm_vbl_send_signals(dev); - } + if (stat & RADEON_CRTC_VBLANK_STAT) + drm_handle_vblank(dev, 0); + if (stat & RADEON_CRTC2_VBLANK_STAT) + drm_handle_vblank(dev, 1); return IRQ_HANDLED; } @@ -152,80 +180,21 @@ static int radeon_wait_irq(drm_device_t * dev, int swi_nr) return ret; } -int radeon_driver_vblank_do_wait(drm_device_t * dev, unsigned int *sequence, - int crtc, int relative) +u32 radeon_get_vblank_counter(drm_device_t *dev, int crtc) { - drm_radeon_private_t *dev_priv = - (drm_radeon_private_t *) dev->dev_private; - unsigned int cur_vblank, diff, irqflags, current_cnt; - int ret = 0; - int ack = 0; - atomic_t *counter; - unsigned int *last_cnt; - int crtc_cnt_reg; - - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } + drm_radeon_private_t *dev_priv = dev->dev_private; + u32 crtc_cnt_reg, current_cnt; - if (crtc == DRM_RADEON_VBLANK_CRTC1) { - counter = &dev->vbl_received; - ack = RADEON_CRTC_VBLANK_STAT; - last_cnt = &dev_priv->crtc_last_cnt; + if (crtc == DRM_RADEON_VBLANK_CRTC1) crtc_cnt_reg = RADEON_CRTC_CRNT_FRAME; - } else if (crtc == DRM_RADEON_VBLANK_CRTC2) { - counter = &dev->vbl_received2; - ack = RADEON_CRTC2_VBLANK_STAT; - last_cnt = &dev_priv->crtc2_last_cnt; + else if (crtc == DRM_RADEON_VBLANK_CRTC2) crtc_cnt_reg = RADEON_CRTC2_CRNT_FRAME; - } else - return DRM_ERR(EINVAL); - - radeon_acknowledge_irqs(dev_priv, ack); - - dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; - - if (!relative) { - /* - * Assume we haven't missed more than several hours of vblank - * events, or that it won't matter if they're not accounted - * for in the master counter. - */ - spin_lock_irqsave(&dev->vbl_lock, irqflags); - current_cnt = RADEON_READ(crtc_cnt_reg); - if (current_cnt < *last_cnt) { - current_cnt += (1 << 21) - *last_cnt; - *last_cnt = 0; - } - diff = current_cnt - *last_cnt; - *last_cnt = RADEON_READ(crtc_cnt_reg); - spin_unlock_irqrestore(&dev->vbl_lock, irqflags); - atomic_add(diff, counter); - } - - /* Assume that the user has missed the current sequence number - * by about a day rather than she wants to wait for years - * using vertical blanks... - */ - radeon_irq_set_state(dev, ack, 1); - DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, - (((cur_vblank = atomic_read(counter)) - - *sequence) <= (1 << 23))); - radeon_irq_set_state(dev, ack, 0); - *sequence = cur_vblank; - - return ret; -} + else + return 0; -int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence, int relative) -{ - return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1, relative); -} + current_cnt = RADEON_READ(crtc_cnt_reg); -int radeon_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence, int relative) -{ - return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2, relative); + return current_cnt; } /* Needs the lock as it touches the ring. @@ -294,15 +263,24 @@ void radeon_driver_irq_preinstall(drm_device_t * dev) RADEON_CRTC2_VBLANK_STAT)); } -void radeon_driver_irq_postinstall(drm_device_t * dev) +int radeon_driver_irq_postinstall(drm_device_t * dev) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; + int num_pipes = 2, ret; atomic_set(&dev_priv->swi_emitted, 0); DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); + ret = drm_vblank_init(dev, num_pipes); + if (ret) + return ret; + + dev->max_vblank_count = 0xffffffff; + radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1); + + return 0; } void radeon_driver_irq_uninstall(drm_device_t * dev) -- 2.11.0