BSD vblank framework.
authorEric Anholt <anholt@freebsd.org>
Thu, 26 Sep 2002 07:45:07 +0000 (07:45 +0000)
committerEric Anholt <anholt@freebsd.org>
Thu, 26 Sep 2002 07:45:07 +0000 (07:45 +0000)
13 files changed:
bsd-core/drmP.h
bsd-core/drm_dma.c
bsd-core/drm_drv.c
bsd-core/drm_os_freebsd.h
bsd/drm.h
bsd/drmP.h
bsd/drm_dma.h
bsd/drm_drv.h
bsd/drm_os_freebsd.h
bsd/gamma.h
bsd/gamma_dma.c
shared-core/radeon_drv.h
shared/radeon_drv.h

index f323e8e..1adaa0e 100644 (file)
@@ -465,6 +465,10 @@ struct drm_device {
 #if __FreeBSD_version >= 400005
        struct task       task;
 #endif
+#if __HAVE_VBL_IRQ
+       wait_queue_head_t vbl_queue;    /* vbl wait channel */
+       atomic_t          vbl_received;
+#endif
        cycles_t          ctx_start;
        cycles_t          lck_start;
 #if __HAVE_DMA_HISTOGRAM
@@ -579,6 +583,9 @@ extern int       DRM(dma_get_buffers)(drm_device_t *dev, drm_dma_t *dma);
 extern int           DRM(irq_install)( drm_device_t *dev, int irq );
 extern int           DRM(irq_uninstall)( drm_device_t *dev );
 extern void          DRM(dma_service)( DRM_IRQ_ARGS );
+extern void          DRM(driver_irq_preinstall)( drm_device_t *dev );
+extern void          DRM(driver_irq_postinstall)( drm_device_t *dev );
+extern void          DRM(driver_irq_uninstall)( drm_device_t *dev );
 #if __HAVE_DMA_IRQ_BH
 extern void          DRM(dma_immediate_bh)( DRM_TASKQUEUE_ARGS );
 #endif
@@ -603,6 +610,9 @@ extern int       DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl,
 extern drm_buf_t     *DRM(freelist_get)(drm_freelist_t *bl, int block);
 #endif
 #endif /* __HAVE_DMA */
+#if __HAVE_VBL_IRQ
+extern int           DRM(vblank_wait)(drm_device_t *dev, unsigned int *vbl_seq);
+#endif
 
 #if __REALLY_HAVE_AGP
                                /* AGP/GART support (drm_agpsupport.h) */
index 3e4a5e1..ebb6fbf 100644 (file)
@@ -532,7 +532,7 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
 #endif
 
                                /* Before installing handler */
-       DRIVER_PREINSTALL();
+       DRM(driver_irq_preinstall)( dev );
 
                                /* Install handler */
        rid = 0;
@@ -552,7 +552,7 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
        }
 
                                /* After installing handler */
-       DRIVER_POSTINSTALL();
+       DRM(driver_irq_postinstall)( dev );
 
        return 0;
 }
@@ -571,7 +571,7 @@ int DRM(irq_uninstall)( drm_device_t *dev )
 
        DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
 
-       DRIVER_UNINSTALL();
+       DRM(driver_irq_uninstall)( dev );
 
        bus_teardown_intr(dev->device, dev->irqr, dev->irqh);
        bus_release_resource(dev->device, SYS_RES_IRQ, 0, dev->irqr);
@@ -596,6 +596,58 @@ int DRM(control)( DRM_IOCTL_ARGS )
        }
 }
 
+#if __HAVE_VBL_IRQ
+
+int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence)
+{
+       unsigned int cur_vblank;
+       int ret = 0;
+
+       /* 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 :)
+        */
+       while ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) )
+               + ~*sequence + 1 ) > (1<<23) ) {
+               ret = tsleep( &dev->vbl_queue, 3*hz, "rdnvbl", PZERO | PCATCH);
+               if (ret)
+                       break;
+       }
+
+       *sequence = cur_vblank;
+
+       return ret;
+}
+
+int DRM(wait_vblank)( DRM_IOCTL_ARGS )
+{
+       DRM_DEVICE;
+       drm_wait_vblank_t vblwait;
+       struct timeval now;
+       int ret;
+
+       if (!dev->irq)
+               return DRM_ERR(EINVAL);
+
+       DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
+                                 sizeof(vblwait) );
+
+       if ( vblwait.type == _DRM_VBLANK_RELATIVE ) {
+               vblwait.sequence += atomic_read( &dev->vbl_received );
+       }
+
+       ret = DRM(vblank_wait)( dev, &vblwait.sequence );
+
+       microtime( &now );
+       vblwait.tval_sec = now.tv_sec;
+       vblwait.tval_usec = now.tv_usec;
+
+       DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait,
+                               sizeof(vblwait) );
+
+       return ret;
+}
+#endif /*  __HAVE_VBL_IRQ */
+
 #else
 
 int DRM(control)( DRM_IOCTL_ARGS )
@@ -616,3 +668,4 @@ int DRM(control)( DRM_IOCTL_ARGS )
 #endif /* __HAVE_DMA_IRQ */
 
 #endif /* __HAVE_DMA */
+
index 0b88004..872f6bc 100644 (file)
@@ -217,6 +217,10 @@ static drm_ioctl_desc_t              DRM(ioctls)[] = {
        [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)]       = { DRM(sg_free),     1, 1 },
 #endif
 
+#if __HAVE_VBL_IRQ
+       [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)]   = { DRM(wait_vblank), 0, 0 },
+#endif
+
        DRIVER_IOCTLS
 };
 
index fa0c916..70ca60a 100644 (file)
@@ -407,6 +407,9 @@ extern int          DRM(mem_info) DRM_SYSCTL_HANDLER_ARGS;
 #if __HAVE_DMA
 extern d_ioctl_t       DRM(control);
 #endif
+#if __HAVE_VBL_IRQ
+extern d_ioctl_t       DRM(wait_vblank);
+#endif
 
 /* AGP/GART support (drm_agpsupport.h) */
 #if __REALLY_HAVE_AGP
index 376568e..f45f088 100644 (file)
--- a/bsd/drm.h
+++ b/bsd/drm.h
@@ -345,6 +345,18 @@ typedef struct drm_irq_busid {
        int funcnum;
 } drm_irq_busid_t;
 
+typedef enum {
+    _DRM_VBLANK_ABSOLUTE = 0x0,        /* Wait for specific vblank sequence number */
+    _DRM_VBLANK_RELATIVE = 0x1 /* Wait for given number of vblanks */
+} drm_vblank_seq_type_t;
+
+typedef struct drm_radeon_vbl_wait {
+       drm_vblank_seq_type_t type;
+       unsigned int sequence;
+       long tval_sec;
+       long tval_usec;
+} drm_wait_vblank_t;
+
 typedef struct drm_agp_mode {
        unsigned long mode;
 } drm_agp_mode_t;
@@ -439,6 +451,8 @@ typedef struct drm_scatter_gather {
 #define DRM_IOCTL_SG_ALLOC             DRM_IOW( 0x38, drm_scatter_gather_t)
 #define DRM_IOCTL_SG_FREE              DRM_IOW( 0x39, drm_scatter_gather_t)
 
+#define DRM_IOCTL_WAIT_VBLANK          DRM_IOWR(0x3a, drm_wait_vblank_t)
+
 /* Device specfic ioctls should only be in their respective headers
  * The device specific ioctl range is 0x40 to 0x79.                  */
 #define DRM_COMMAND_BASE                0x40
index f323e8e..1adaa0e 100644 (file)
@@ -465,6 +465,10 @@ struct drm_device {
 #if __FreeBSD_version >= 400005
        struct task       task;
 #endif
+#if __HAVE_VBL_IRQ
+       wait_queue_head_t vbl_queue;    /* vbl wait channel */
+       atomic_t          vbl_received;
+#endif
        cycles_t          ctx_start;
        cycles_t          lck_start;
 #if __HAVE_DMA_HISTOGRAM
@@ -579,6 +583,9 @@ extern int       DRM(dma_get_buffers)(drm_device_t *dev, drm_dma_t *dma);
 extern int           DRM(irq_install)( drm_device_t *dev, int irq );
 extern int           DRM(irq_uninstall)( drm_device_t *dev );
 extern void          DRM(dma_service)( DRM_IRQ_ARGS );
+extern void          DRM(driver_irq_preinstall)( drm_device_t *dev );
+extern void          DRM(driver_irq_postinstall)( drm_device_t *dev );
+extern void          DRM(driver_irq_uninstall)( drm_device_t *dev );
 #if __HAVE_DMA_IRQ_BH
 extern void          DRM(dma_immediate_bh)( DRM_TASKQUEUE_ARGS );
 #endif
@@ -603,6 +610,9 @@ extern int       DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl,
 extern drm_buf_t     *DRM(freelist_get)(drm_freelist_t *bl, int block);
 #endif
 #endif /* __HAVE_DMA */
+#if __HAVE_VBL_IRQ
+extern int           DRM(vblank_wait)(drm_device_t *dev, unsigned int *vbl_seq);
+#endif
 
 #if __REALLY_HAVE_AGP
                                /* AGP/GART support (drm_agpsupport.h) */
index 3e4a5e1..ebb6fbf 100644 (file)
@@ -532,7 +532,7 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
 #endif
 
                                /* Before installing handler */
-       DRIVER_PREINSTALL();
+       DRM(driver_irq_preinstall)( dev );
 
                                /* Install handler */
        rid = 0;
@@ -552,7 +552,7 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
        }
 
                                /* After installing handler */
-       DRIVER_POSTINSTALL();
+       DRM(driver_irq_postinstall)( dev );
 
        return 0;
 }
@@ -571,7 +571,7 @@ int DRM(irq_uninstall)( drm_device_t *dev )
 
        DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
 
-       DRIVER_UNINSTALL();
+       DRM(driver_irq_uninstall)( dev );
 
        bus_teardown_intr(dev->device, dev->irqr, dev->irqh);
        bus_release_resource(dev->device, SYS_RES_IRQ, 0, dev->irqr);
@@ -596,6 +596,58 @@ int DRM(control)( DRM_IOCTL_ARGS )
        }
 }
 
+#if __HAVE_VBL_IRQ
+
+int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence)
+{
+       unsigned int cur_vblank;
+       int ret = 0;
+
+       /* 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 :)
+        */
+       while ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) )
+               + ~*sequence + 1 ) > (1<<23) ) {
+               ret = tsleep( &dev->vbl_queue, 3*hz, "rdnvbl", PZERO | PCATCH);
+               if (ret)
+                       break;
+       }
+
+       *sequence = cur_vblank;
+
+       return ret;
+}
+
+int DRM(wait_vblank)( DRM_IOCTL_ARGS )
+{
+       DRM_DEVICE;
+       drm_wait_vblank_t vblwait;
+       struct timeval now;
+       int ret;
+
+       if (!dev->irq)
+               return DRM_ERR(EINVAL);
+
+       DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
+                                 sizeof(vblwait) );
+
+       if ( vblwait.type == _DRM_VBLANK_RELATIVE ) {
+               vblwait.sequence += atomic_read( &dev->vbl_received );
+       }
+
+       ret = DRM(vblank_wait)( dev, &vblwait.sequence );
+
+       microtime( &now );
+       vblwait.tval_sec = now.tv_sec;
+       vblwait.tval_usec = now.tv_usec;
+
+       DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait,
+                               sizeof(vblwait) );
+
+       return ret;
+}
+#endif /*  __HAVE_VBL_IRQ */
+
 #else
 
 int DRM(control)( DRM_IOCTL_ARGS )
@@ -616,3 +668,4 @@ int DRM(control)( DRM_IOCTL_ARGS )
 #endif /* __HAVE_DMA_IRQ */
 
 #endif /* __HAVE_DMA */
+
index 0b88004..872f6bc 100644 (file)
@@ -217,6 +217,10 @@ static drm_ioctl_desc_t              DRM(ioctls)[] = {
        [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)]       = { DRM(sg_free),     1, 1 },
 #endif
 
+#if __HAVE_VBL_IRQ
+       [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)]   = { DRM(wait_vblank), 0, 0 },
+#endif
+
        DRIVER_IOCTLS
 };
 
index fa0c916..70ca60a 100644 (file)
@@ -407,6 +407,9 @@ extern int          DRM(mem_info) DRM_SYSCTL_HANDLER_ARGS;
 #if __HAVE_DMA
 extern d_ioctl_t       DRM(control);
 #endif
+#if __HAVE_VBL_IRQ
+extern d_ioctl_t       DRM(wait_vblank);
+#endif
 
 /* AGP/GART support (drm_agpsupport.h) */
 #if __REALLY_HAVE_AGP
index 232ed01..161dc04 100644 (file)
 
 #define __HAVE_DMA_IRQ                 1
 #define __HAVE_DMA_IRQ_BH              1
-#define DRIVER_PREINSTALL() do {                                       \
-       drm_gamma_private_t *dev_priv =                                 \
-                               (drm_gamma_private_t *)dev->dev_private;\
-       GAMMA_WRITE( GAMMA_GCOMMANDMODE,        0x00000000 );           \
-       GAMMA_WRITE( GAMMA_GDMACONTROL,         0x00000000 );           \
-} while (0)
-
-#define DRIVER_POSTINSTALL() do {                                      \
-       drm_gamma_private_t *dev_priv =                                 \
-                               (drm_gamma_private_t *)dev->dev_private;\
-       GAMMA_WRITE( GAMMA_GINTENABLE,          0x00002001 );           \
-       GAMMA_WRITE( GAMMA_COMMANDINTENABLE,    0x00000008 );           \
-       GAMMA_WRITE( GAMMA_GDELAYTIMER,         0x00039090 );           \
-} while (0)
-
-#define DRIVER_UNINSTALL() do {                                                \
-       drm_gamma_private_t *dev_priv =                                 \
-                               (drm_gamma_private_t *)dev->dev_private;\
-       GAMMA_WRITE( GAMMA_GDELAYTIMER,         0x00000000 );           \
-       GAMMA_WRITE( GAMMA_COMMANDINTENABLE,    0x00000000 );           \
-       GAMMA_WRITE( GAMMA_GINTENABLE,          0x00000000 );           \
-} while (0)
 
 #endif /* __GAMMA_H__ */
index 20b2979..714554d 100644 (file)
@@ -567,3 +567,45 @@ int gamma_dma( DRM_IOCTL_ARGS )
 
        return retcode;
 }
+
+void DRM(driver_irq_preinstall)(drm_device_t *dev) {
+       drm_gamma_private_t *dev_priv = 
+               (drm_gamma_private_t *)dev->dev_private;
+#if 1
+       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
+       GAMMA_WRITE( GAMMA_GCOMMANDMODE,        0x00000004 );
+       GAMMA_WRITE( GAMMA_GDMACONTROL,         0x00000000 );
+#else
+       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
+       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
+       GAMMA_WRITE( GAMMA_GCOMMANDMODE,        GAMMA_QUEUED_DMA_MODE );
+       GAMMA_WRITE( GAMMA_GDMACONTROL,         0x00000000 );
+#endif
+}
+
+void DRM(driver_irq_postinstall)(drm_device_t *dev) {
+       drm_gamma_private_t *dev_priv = 
+               (drm_gamma_private_t *)dev->dev_private;
+#if 1
+       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
+       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3);
+       GAMMA_WRITE( GAMMA_GINTENABLE,          0x00002001 );
+       GAMMA_WRITE( GAMMA_COMMANDINTENABLE,    0x00000008 );
+       GAMMA_WRITE( GAMMA_GDELAYTIMER,         0x00039090 );
+#else
+       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
+       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
+       GAMMA_WRITE( GAMMA_GINTENABLE,          0x00002000 );
+       GAMMA_WRITE( GAMMA_COMMANDINTENABLE,    0x00000004 );
+#endif
+}
+
+void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
+       drm_gamma_private_t *dev_priv =
+               (drm_gamma_private_t *)dev->dev_private;
+       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
+       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3);
+       GAMMA_WRITE( GAMMA_GDELAYTIMER,         0x00000000 );
+       GAMMA_WRITE( GAMMA_COMMANDINTENABLE,    0x00000000 );
+       GAMMA_WRITE( GAMMA_GINTENABLE,          0x00000000 );
+}
index 5c43ebc..ed4a50f 100644 (file)
@@ -195,7 +195,6 @@ extern int radeon_irq_wait( DRM_IOCTL_ARGS );
 extern int radeon_emit_and_wait_irq(drm_device_t *dev);
 extern int radeon_wait_irq(drm_device_t *dev, int swi_nr);
 extern int radeon_emit_irq(drm_device_t *dev);
-extern int radeon_vblank_wait(drm_device_t *dev, unsigned int *vbl_seq);
 
 
 /* Flags for stats.boxes
index 5c43ebc..ed4a50f 100644 (file)
@@ -195,7 +195,6 @@ extern int radeon_irq_wait( DRM_IOCTL_ARGS );
 extern int radeon_emit_and_wait_irq(drm_device_t *dev);
 extern int radeon_wait_irq(drm_device_t *dev, int swi_nr);
 extern int radeon_emit_irq(drm_device_t *dev);
-extern int radeon_vblank_wait(drm_device_t *dev, unsigned int *vbl_seq);
 
 
 /* Flags for stats.boxes