diff options
-rw-r--r-- | bsd-core/drmP.h | 10 | ||||
-rw-r--r-- | bsd-core/drm_dma.c | 59 | ||||
-rw-r--r-- | bsd-core/drm_drv.c | 4 | ||||
-rw-r--r-- | bsd-core/drm_os_freebsd.h | 3 | ||||
-rw-r--r-- | bsd/drm.h | 14 | ||||
-rw-r--r-- | bsd/drmP.h | 10 | ||||
-rw-r--r-- | bsd/drm_dma.h | 59 | ||||
-rw-r--r-- | bsd/drm_drv.h | 4 | ||||
-rw-r--r-- | bsd/drm_os_freebsd.h | 3 | ||||
-rw-r--r-- | bsd/gamma.h | 22 | ||||
-rw-r--r-- | bsd/gamma_dma.c | 42 | ||||
-rw-r--r-- | shared-core/radeon_drv.h | 1 | ||||
-rw-r--r-- | shared/radeon_drv.h | 1 |
13 files changed, 202 insertions, 30 deletions
diff --git a/bsd-core/drmP.h b/bsd-core/drmP.h index f323e8ef..1adaa0e5 100644 --- a/bsd-core/drmP.h +++ b/bsd-core/drmP.h @@ -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) */ diff --git a/bsd-core/drm_dma.c b/bsd-core/drm_dma.c index 3e4a5e17..ebb6fbf6 100644 --- a/bsd-core/drm_dma.c +++ b/bsd-core/drm_dma.c @@ -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 */ + diff --git a/bsd-core/drm_drv.c b/bsd-core/drm_drv.c index 0b880047..872f6bc6 100644 --- a/bsd-core/drm_drv.c +++ b/bsd-core/drm_drv.c @@ -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 }; diff --git a/bsd-core/drm_os_freebsd.h b/bsd-core/drm_os_freebsd.h index fa0c916f..70ca60a6 100644 --- a/bsd-core/drm_os_freebsd.h +++ b/bsd-core/drm_os_freebsd.h @@ -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 @@ -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 @@ -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) */ diff --git a/bsd/drm_dma.h b/bsd/drm_dma.h index 3e4a5e17..ebb6fbf6 100644 --- a/bsd/drm_dma.h +++ b/bsd/drm_dma.h @@ -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 */ + diff --git a/bsd/drm_drv.h b/bsd/drm_drv.h index 0b880047..872f6bc6 100644 --- a/bsd/drm_drv.h +++ b/bsd/drm_drv.h @@ -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 }; diff --git a/bsd/drm_os_freebsd.h b/bsd/drm_os_freebsd.h index fa0c916f..70ca60a6 100644 --- a/bsd/drm_os_freebsd.h +++ b/bsd/drm_os_freebsd.h @@ -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 diff --git a/bsd/gamma.h b/bsd/gamma.h index 232ed018..161dc048 100644 --- a/bsd/gamma.h +++ b/bsd/gamma.h @@ -67,27 +67,5 @@ #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__ */ diff --git a/bsd/gamma_dma.c b/bsd/gamma_dma.c index 20b29793..714554d2 100644 --- a/bsd/gamma_dma.c +++ b/bsd/gamma_dma.c @@ -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 ); +} diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index 5c43ebc6..ed4a50f5 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -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 diff --git a/shared/radeon_drv.h b/shared/radeon_drv.h index 5c43ebc6..ed4a50f5 100644 --- a/shared/radeon_drv.h +++ b/shared/radeon_drv.h @@ -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 |