OSDN Git Service

First cut at radeon support for the vblank rework.
authorJesse Barnes <jbarnes@jbarnes-mobile.amr.corp.intel.com>
Fri, 15 Jun 2007 18:21:57 +0000 (11:21 -0700)
committerJesse Barnes <jbarnes@jbarnes-mobile.amr.corp.intel.com>
Fri, 15 Jun 2007 18:21:57 +0000 (11:21 -0700)
linux-core/radeon_drv.c
shared-core/radeon_drv.h
shared-core/radeon_irq.c

index 327a6a9..39c3513 100644 (file)
@@ -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,
index 283dee3..5f671df 100644 (file)
@@ -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)
index 2534ff1..46ec035 100644 (file)
@@ -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)