For reference, here's a patch converting radeon to the new vblank
infrastructure.  The basics are pretty easy:
  - add a get_vblank_counter hook to return the current vblank event
    count
  - add enable/disable_vblank hooks to enable/disable the vblank
    interrupt
  - init the vblank core (drm_vblank_init) with the number of crtcs
    you have in your chip & configuration
  - init the max_vblank_count value to the highest value your vblank
    counter register can handle
  - update your interrupt handler to use the new drm_handle_vblank
    routine, it'll take care of updating the master vblank count,
    wakeup any clients waiting for events, and send any signals
  - if needed, convert your internal routines that use vblank
    events to use the new drm_vblank_get/put routines, around the
    sections of code that need to have vblank interrupts enabled
    (like the i915 buffer swap code)

If your device doesn't have a vblank counter register, you can simply
keep interrupts enabled (making the enable/disable hooks into no-ops,
though we could check for their existence in the core if needed), and
make the get_counter hook return the current master value and set your
max_vblank_count to ~0.

Alternately, to save power, you could make your get_counter hook use
wall time to calculate how many events have occurred since it was last
called, and make the enable/disable hooks have proper interrupt
control.  This allows interrupts to be disabled for longer periods,
saving power.

Note that this particular patch is untested (testing now), and can
probably be simplified more once one of the radeon guys looks at it
(as it stands, it still removes more lines than it adds, which is
nice).

Thanks,
Jesse

diff --git a/linux-core/radeon_drv.c b/linux-core/radeon_drv.c
index 327a6a9..39c3513 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 283dee3..5f671df 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 2534ff1..46ec035 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)

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
--
_______________________________________________
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to