diff options
author | Gareth Hughes <gareth@users.sourceforge.net> | 2001-01-01 12:51:30 +0000 |
---|---|---|
committer | Gareth Hughes <gareth@users.sourceforge.net> | 2001-01-01 12:51:30 +0000 |
commit | 5f32ef20720647e117845295fbe706ce39b28685 (patch) | |
tree | 64e9a545682028c272bad9c02c93dc258a08efb7 | |
parent | 7c213c834b226e952faf2e1174e40b39350643d6 (diff) |
- Removal of SubmitPackets routines, replaced with root-only indirect
buffer firing. Currently only implemented in Radeon driver.
- Force old "UseCPFor2D" option to be on in Radeon driver and remove it. CP
must be running (and stay running) for direct rendering support.
- Cleanup of basic CP acceleration in Radeon driver for better interaction
with direct rendering clients (hardware state cleanup for 2D and so
on).
- Better fullscreen mode support.
-rw-r--r-- | linux-core/r128_drv.c | 44 | ||||
-rw-r--r-- | linux-core/radeon_drv.c | 48 | ||||
-rw-r--r-- | linux/drm.h | 23 | ||||
-rw-r--r-- | linux/r128_cce.c | 421 | ||||
-rw-r--r-- | linux/r128_drm.h | 33 | ||||
-rw-r--r-- | linux/r128_drv.c | 44 | ||||
-rw-r--r-- | linux/r128_drv.h | 26 | ||||
-rw-r--r-- | linux/r128_state.c | 281 | ||||
-rw-r--r-- | linux/radeon_cp.c | 416 | ||||
-rw-r--r-- | linux/radeon_drm.h | 23 | ||||
-rw-r--r-- | linux/radeon_drv.c | 48 | ||||
-rw-r--r-- | linux/radeon_drv.h | 65 | ||||
-rw-r--r-- | linux/radeon_state.c | 110 | ||||
-rw-r--r-- | shared-core/drm.h | 23 | ||||
-rw-r--r-- | shared/drm.h | 23 |
15 files changed, 557 insertions, 1071 deletions
diff --git a/linux-core/r128_drv.c b/linux-core/r128_drv.c index dbfc9b74..cf258925 100644 --- a/linux-core/r128_drv.c +++ b/linux-core/r128_drv.c @@ -37,10 +37,10 @@ #define R128_NAME "r128" #define R128_DESC "ATI Rage 128" -#define R128_DATE "20001215" +#define R128_DATE "20010101" #define R128_MAJOR 2 #define R128_MINOR 1 -#define R128_PATCHLEVEL 2 +#define R128_PATCHLEVEL 4 static drm_device_t r128_device; drm_ctx_t r128_res_ctx; @@ -108,20 +108,22 @@ static drm_ioctl_desc_t r128_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 }, #endif - [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_cce_init, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_START)] = { r128_cce_start, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_STOP)] = { r128_cce_stop, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_RESET)] = { r128_cce_reset, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_IDLE)] = { r128_cce_idle, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_engine_reset, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_SWAP)] = { r128_cce_swap, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_CLEAR)] = { r128_cce_clear, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_INDICES)] = { r128_cce_indices, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_BLIT)] = { r128_cce_blit, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_DEPTH)] = { r128_cce_depth, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_STIPPLE)] = { r128_cce_stipple, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_PACKET)] = { r128_cce_packet, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_cce_init, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_START)] = { r128_cce_start, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_STOP)] = { r128_cce_stop, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_RESET)] = { r128_cce_reset, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_IDLE)] = { r128_cce_idle, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_engine_reset, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_FULLSCREEN)]= { r128_fullscreen, 1, 0 }, + + [DRM_IOCTL_NR(DRM_IOCTL_R128_SWAP)] = { r128_cce_swap, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CLEAR)] = { r128_cce_clear, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_INDICES)] = { r128_cce_indices, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_BLIT)] = { r128_cce_blit, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_DEPTH)] = { r128_cce_depth, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_STIPPLE)] = { r128_cce_stipple, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_INDIRECT)] = { r128_cce_indirect, 1, 1 }, }; #define R128_IOCTL_COUNT DRM_ARRAY_SIZE(r128_ioctls) @@ -489,7 +491,17 @@ int r128_release(struct inode *inode, struct file *filp) lock_kernel(); dev = priv->dev; + DRM_DEBUG("open_count = %d\n", dev->open_count); + + /* Force the cleanup of page flipping when required */ + if ( dev->dev_private ) { + drm_r128_private_t *dev_priv = dev->dev_private; + if ( dev_priv->page_flipping ) { + r128_do_cleanup_pageflip( dev ); + } + } + if (!(retcode = drm_release(inode, filp))) { #if LINUX_VERSION_CODE < 0x020333 MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */ diff --git a/linux-core/radeon_drv.c b/linux-core/radeon_drv.c index 93ad2f0d..07f85981 100644 --- a/linux-core/radeon_drv.c +++ b/linux-core/radeon_drv.c @@ -34,7 +34,7 @@ #define RADEON_NAME "radeon" #define RADEON_DESC "ATI Radeon" -#define RADEON_DATE "20001228" +#define RADEON_DATE "20001230" #define RADEON_MAJOR 1 #define RADEON_MINOR 0 #define RADEON_PATCHLEVEL 0 @@ -105,20 +105,21 @@ static drm_ioctl_desc_t radeon_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 }, #endif - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_INIT)] = { radeon_cp_init, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_START)]= { radeon_cp_start, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_STOP)] = { radeon_cp_stop, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_RESET)]= { radeon_cp_reset, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_IDLE)] = { radeon_cp_idle, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_RESET)] = { radeon_engine_reset,1,0 }, - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_PAGEFLIP)]= { radeon_cp_pageflip,1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_INIT)] = { radeon_cp_init, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_START)] = { radeon_cp_start, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_STOP)] = { radeon_cp_stop, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_RESET)] = { radeon_cp_reset, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_IDLE)] = { radeon_cp_idle, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_RESET)] = { radeon_engine_reset, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FULLSCREEN)] = { radeon_fullscreen, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SWAP)] = { radeon_cp_swap, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CLEAR)] = { radeon_cp_clear, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX)] = { radeon_cp_vertex, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDICES)] = { radeon_cp_indices, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_RADEON_BLIT)] = { radeon_cp_blit, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_RADEON_STIPPLE)] = { radeon_cp_stipple, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_PACKET)] = { radeon_cp_packet, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDIRECT)]= { radeon_cp_indirect,1, 1 }, }; #define RADEON_IOCTL_COUNT DRM_ARRAY_SIZE(radeon_ioctls) @@ -612,9 +613,6 @@ int radeon_lock(struct inode *inode, struct file *filp, unsigned int cmd, /* Contention */ atomic_inc(&dev->total_sleeps); -#if 1 - current->policy |= SCHED_YIELD; -#endif schedule(); if (signal_pending(current)) { ret = -ERESTARTSYS; @@ -625,32 +623,6 @@ int radeon_lock(struct inode *inode, struct file *filp, unsigned int cmd, remove_wait_queue(&dev->lock.lock_queue, &entry); } -#if 0 - if (!ret && dev->last_context != lock.context && - lock.context != radeon_res_ctx.handle && - dev->last_context != radeon_res_ctx.handle) { - add_wait_queue(&dev->context_wait, &entry); - current->state = TASK_INTERRUPTIBLE; - /* PRE: dev->last_context != lock.context */ - radeon_context_switch(dev, dev->last_context, lock.context); - /* POST: we will wait for the context - switch and will dispatch on a later call - when dev->last_context == lock.context - NOTE WE HOLD THE LOCK THROUGHOUT THIS - TIME! */ - current->policy |= SCHED_YIELD; - schedule(); - current->state = TASK_RUNNING; - remove_wait_queue(&dev->context_wait, &entry); - if (signal_pending(current)) { - ret = -EINTR; - } else if (dev->last_context != lock.context) { - DRM_ERROR("Context mismatch: %d %d\n", - dev->last_context, lock.context); - } - } -#endif - if (!ret) { sigemptyset(&dev->sigmask); sigaddset(&dev->sigmask, SIGSTOP); diff --git a/linux/drm.h b/linux/drm.h index b892682a..e8bccd86 100644 --- a/linux/drm.h +++ b/linux/drm.h @@ -370,14 +370,15 @@ typedef struct drm_agp_info { #define DRM_IOCTL_R128_CCE_RESET DRM_IO( 0x43) #define DRM_IOCTL_R128_CCE_IDLE DRM_IO( 0x44) #define DRM_IOCTL_R128_RESET DRM_IO( 0x46) -#define DRM_IOCTL_R128_SWAP DRM_IO( 0x47) -#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x48, drm_r128_clear_t) -#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x49, drm_r128_vertex_t) -#define DRM_IOCTL_R128_INDICES DRM_IOW( 0x4a, drm_r128_indices_t) -#define DRM_IOCTL_R128_BLIT DRM_IOW( 0x4b, drm_r128_blit_t) -#define DRM_IOCTL_R128_DEPTH DRM_IOW( 0x4c, drm_r128_depth_t) -#define DRM_IOCTL_R128_STIPPLE DRM_IOW( 0x4d, drm_r128_stipple_t) -#define DRM_IOCTL_R128_PACKET DRM_IOWR(0x4e, drm_r128_packet_t) +#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( 0x47, drm_r128_fullscreen_t) +#define DRM_IOCTL_R128_SWAP DRM_IO( 0x48) +#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x49, drm_r128_clear_t) +#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x4a, drm_r128_vertex_t) +#define DRM_IOCTL_R128_INDICES DRM_IOW( 0x4b, drm_r128_indices_t) +#define DRM_IOCTL_R128_BLIT DRM_IOW( 0x4c, drm_r128_blit_t) +#define DRM_IOCTL_R128_DEPTH DRM_IOW( 0x4d, drm_r128_depth_t) +#define DRM_IOCTL_R128_STIPPLE DRM_IOW( 0x4e, drm_r128_stipple_t) +#define DRM_IOCTL_R128_INDIRECT DRM_IOWR(0x4f, drm_r128_indirect_t) /* Radeon specific ioctls */ #define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( 0x40, drm_radeon_init_t) @@ -386,14 +387,14 @@ typedef struct drm_agp_info { #define DRM_IOCTL_RADEON_CP_RESET DRM_IO( 0x43) #define DRM_IOCTL_RADEON_CP_IDLE DRM_IO( 0x44) #define DRM_IOCTL_RADEON_RESET DRM_IO( 0x45) -#define DRM_IOCTL_RADEON_PAGEFLIP DRM_IOW( 0x46, drm_radeon_pageflip_t) +#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( 0x46, drm_radeon_fullscreen_t) #define DRM_IOCTL_RADEON_SWAP DRM_IO( 0x47) #define DRM_IOCTL_RADEON_CLEAR DRM_IOW( 0x48, drm_radeon_clear_t) #define DRM_IOCTL_RADEON_VERTEX DRM_IOW( 0x49, drm_radeon_vertex_t) #define DRM_IOCTL_RADEON_INDICES DRM_IOW( 0x4a, drm_radeon_indices_t) #define DRM_IOCTL_RADEON_BLIT DRM_IOW( 0x4b, drm_radeon_blit_t) -#define DRM_IOCTL_RADEON_STIPPLE DRM_IOWR(0x4c, drm_radeon_stipple_t) -#define DRM_IOCTL_RADEON_PACKET DRM_IOWR(0x4d, drm_radeon_packet_t) +#define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( 0x4c, drm_radeon_stipple_t) +#define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(0x4d, drm_radeon_indirect_t) /* SiS specific ioctls */ #define SIS_IOCTL_FB_ALLOC DRM_IOWR(0x44, drm_sis_mem_t) diff --git a/linux/r128_cce.c b/linux/r128_cce.c index c2281fc5..d4035045 100644 --- a/linux/r128_cce.c +++ b/linux/r128_cce.c @@ -36,9 +36,8 @@ #include <linux/interrupt.h> /* For task queue support */ #include <linux/delay.h> +#define R128_FIFO_DEBUG 0 -/* FIXME: Temporary CCE packet buffer */ -u32 r128_cce_buffer[(1 << 14)] __attribute__ ((aligned (32))); /* CCE microcode (from ATI) */ static u32 r128_cce_microcode[] = { @@ -114,7 +113,7 @@ int R128_READ_PLL(drm_device_t *dev, int addr) return R128_READ(R128_CLOCK_CNTL_DATA); } -#if 0 +#if R128_FIFO_DEBUG static void r128_status( drm_r128_private_t *dev_priv ) { printk( "GUI_STAT = 0x%08x\n", @@ -241,7 +240,7 @@ static int r128_do_cce_idle( drm_r128_private_t *dev_priv ) udelay( 1 ); } -#if 0 +#if R128_FIFO_DEBUG DRM_ERROR( "failed!\n" ); r128_status( dev_priv ); #endif @@ -395,7 +394,6 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) } dev_priv->cce_mode = init->cce_mode; - dev_priv->cce_secure = init->cce_secure; /* GH: Simple idle check. */ @@ -697,6 +695,69 @@ int r128_engine_reset( struct inode *inode, struct file *filp, /* ================================================================ + * Fullscreen mode + */ + +static int r128_do_init_pageflip( drm_device_t *dev ) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + dev_priv->crtc_offset = R128_READ( R128_CRTC_OFFSET ); + dev_priv->crtc_offset_cntl = R128_READ( R128_CRTC_OFFSET_CNTL ); + + R128_WRITE( R128_CRTC_OFFSET, dev_priv->front_offset ); + R128_WRITE( R128_CRTC_OFFSET_CNTL, + dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL ); + + dev_priv->page_flipping = 1; + dev_priv->current_page = 0; + + return 0; +} + +int r128_do_cleanup_pageflip( drm_device_t *dev ) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + R128_WRITE( R128_CRTC_OFFSET, dev_priv->crtc_offset ); + R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl ); + + dev_priv->page_flipping = 0; + dev_priv->current_page = 0; + + return 0; +} + +int r128_fullscreen( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_r128_fullscreen_t fs; + + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || + dev->lock.pid != current->pid ) { + DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); + return -EINVAL; + } + + if ( copy_from_user( &fs, (drm_r128_fullscreen_t *)arg, sizeof(fs) ) ) + return -EFAULT; + + switch ( fs.func ) { + case R128_INIT_FULLSCREEN: + return r128_do_init_pageflip( dev ); + case R128_CLEANUP_FULLSCREEN: + return r128_do_cleanup_pageflip( dev ); + } + + return -EINVAL; +} + + +/* ================================================================ * Freelist management */ #define R128_BUFFER_USED 0xffffffff @@ -802,7 +863,7 @@ void r128_freelist_reset( drm_device_t *dev ) /* ================================================================ - * CCE packet submission + * CCE command submission */ int r128_wait_ring( drm_r128_private_t *dev_priv, int n ) @@ -821,6 +882,8 @@ int r128_wait_ring( drm_r128_private_t *dev_priv, int n ) udelay( 1 ); } + /* FIXME: This is being ignored... */ + DRM_ERROR( "failed!\n" ); return -EBUSY; } @@ -837,352 +900,6 @@ void r128_update_ring_snapshot( drm_r128_private_t *dev_priv ) ring->space += ring->size; } -#if 0 -static int r128_verify_command( drm_r128_private_t *dev_priv, - u32 cmd, int *size ) -{ - int writing = 1; - - *size = 0; - - switch ( cmd & R128_CCE_PACKET_MASK ) { - case R128_CCE_PACKET0: - if ( (cmd & R128_CCE_PACKET0_REG_MASK) <= (0x1004 >> 2) && - (cmd & R128_CCE_PACKET0_REG_MASK) != - (R128_PM4_VC_FPU_SETUP >> 2) ) { - writing = 0; - } - *size = ((cmd & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2; - break; - - case R128_CCE_PACKET1: - if ( (cmd & R128_CCE_PACKET1_REG0_MASK) <= (0x1004 >> 2) && - (cmd & R128_CCE_PACKET1_REG0_MASK) != - (R128_PM4_VC_FPU_SETUP >> 2) ) { - writing = 0; - } - if ( (cmd & R128_CCE_PACKET1_REG1_MASK) <= (0x1004 << 9) && - (cmd & R128_CCE_PACKET1_REG1_MASK) != - (R128_PM4_VC_FPU_SETUP << 9) ) { - writing = 0; - } - *size = 3; - break; - - case R128_CCE_PACKET2: - break; - - case R128_CCE_PACKET3: - *size = ((cmd & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2; - break; - - } - - return writing; -} - -static int r128_submit_packet_ring_secure( drm_r128_private_t *dev_priv, - u32 *commands, int *count ) -{ -#if 0 - int write = dev_priv->sarea_priv->ring_write; - int *write_ptr = dev_priv->ring_start + write; - int c = *count; - u32 tmp = 0; - int psize = 0; - int writing = 1; - int timeout; - - while ( c > 0 ) { - tmp = *commands++; - if ( !psize ) { - writing = r128_verify_command( dev_priv, tmp, &psize ); - } - psize--; - - if ( writing ) { - write++; - *write_ptr++ = tmp; - } - if ( write >= dev_priv->ring_entries ) { - write = 0; - write_ptr = dev_priv->ring_start; - } - timeout = 0; - while ( write == *dev_priv->ring_read_ptr ) { - R128_READ( R128_PM4_BUFFER_DL_RPTR ); - if ( timeout++ >= dev_priv->usec_timeout ) - return -EBUSY; - udelay( 1 ); - } - c--; - } - - if ( write < 32 ) { - memcpy( dev_priv->ring_end, - dev_priv->ring_start, - write * sizeof(u32) ); - } - - /* Make sure WC cache has been flushed */ - r128_flush_write_combine(); - - dev_priv->sarea_priv->ring_write = write; - R128_WRITE( R128_PM4_BUFFER_DL_WPTR, write ); - - *count = 0; -#endif - return 0; -} - -static int r128_submit_packet_ring_insecure( drm_r128_private_t *dev_priv, - u32 *commands, int *count ) -{ -#if 0 - int write = dev_priv->sarea_priv->ring_write; - int *write_ptr = dev_priv->ring_start + write; - int c = *count; - int timeout; - - while ( c > 0 ) { - write++; - *write_ptr++ = *commands++; - if ( write >= dev_priv->ring_entries ) { - write = 0; - write_ptr = dev_priv->ring_start; - } - - timeout = 0; - while ( write == *dev_priv->ring_read_ptr ) { - R128_READ( R128_PM4_BUFFER_DL_RPTR ); - if ( timeout++ >= dev_priv->usec_timeout ) - return -EBUSY; - udelay( 1 ); - } - c--; - } - - if ( write < 32 ) { - memcpy( dev_priv->ring_end, - dev_priv->ring_start, - write * sizeof(u32) ); - } - - /* Make sure WC cache has been flushed */ - r128_flush_write_combine(); - - dev_priv->sarea_priv->ring_write = write; - R128_WRITE( R128_PM4_BUFFER_DL_WPTR, write ); - - *count = 0; -#endif - return 0; -} -#endif - -/* Internal packet submission routine. This uses the insecure versions - * of the packet submission functions, and thus should only be used for - * packets generated inside the kernel module. - */ -int r128_do_submit_packet( drm_r128_private_t *dev_priv, - u32 *buffer, int count ) -{ - int c = count; - int ret = 0; - -#if 0 - int left = 0; - - if ( c >= dev_priv->ring_entries ) { - c = dev_priv->ring_entries - 1; - left = count - c; - } - - /* Since this is only used by the kernel we can use the - * insecure ring buffer submit packet routine. - */ - ret = r128_submit_packet_ring_insecure( dev_priv, buffer, &c ); - c += left; -#endif - - return ( ret < 0 ) ? ret : c; -} - -/* External packet submission routine. This uses the secure versions - * by default, and can thus submit packets received from user space. - */ -int r128_cce_packet( struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg ) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_packet_t packet; - u32 *buffer; - int c; - int size; - int ret = 0; - -#if 0 - /* GH: Disable packet submission for now. - */ - return -EINVAL; -#endif - - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || - dev->lock.pid != current->pid ) { - DRM_ERROR( "r128_submit_packet called without lock held\n" ); - return -EINVAL; - } - - if ( copy_from_user( &packet, (drm_r128_packet_t *)arg, - sizeof(packet) ) ) - return -EFAULT; - -#if 0 - c = packet.count; - size = c * sizeof(*buffer); - - { - int left = 0; - - if ( c >= dev_priv->ring_entries ) { - c = dev_priv->ring_entries - 1; - size = c * sizeof(*buffer); - left = packet.count - c; - } - - buffer = kmalloc( size, 0 ); - if ( buffer == NULL) - return -ENOMEM; - if ( copy_from_user( buffer, packet.buffer, size ) ) - return -EFAULT; - - if ( dev_priv->cce_secure ) { - ret = r128_submit_packet_ring_secure( dev_priv, - buffer, &c ); - } else { - ret = r128_submit_packet_ring_insecure( dev_priv, - buffer, &c ); - } - c += left; - } - - kfree( buffer ); -#else - c = 0; -#endif - - packet.count = c; - if ( copy_to_user( (drm_r128_packet_t *)arg, &packet, - sizeof(packet) ) ) - return -EFAULT; - - if ( ret ) { - return ret; - } else if ( c > 0 ) { - return -EAGAIN; - } - return 0; -} - -#if 0 -static int r128_send_vertbufs( drm_device_t *dev, drm_r128_vertex_t *v ) -{ - drm_device_dma_t *dma = dev->dma; - drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_buf_priv_t *buf_priv; - drm_buf_t *buf; - int i, ret; - RING_LOCALS; - - /* Make sure we have valid data */ - for (i = 0; i < v->send_count; i++) { - int idx = v->send_indices[i]; - - if (idx < 0 || idx >= dma->buf_count) { - DRM_ERROR("Index %d (of %d max)\n", - idx, dma->buf_count - 1); - return -EINVAL; - } - buf = dma->buflist[idx]; - if (buf->pid != current->pid) { - DRM_ERROR("Process %d using buffer owned by %d\n", - current->pid, buf->pid); - return -EINVAL; - } - if (buf->pending) { - DRM_ERROR("Sending pending buffer:" - " buffer %d, offset %d\n", - v->send_indices[i], i); - return -EINVAL; - } - } - - /* Wait for idle, if we've wrapped to make sure that all pending - buffers have been processed */ - if (dev_priv->submit_age == R128_MAX_VBUF_AGE) { - if ((ret = r128_do_cce_idle(dev)) < 0) return ret; - dev_priv->submit_age = 0; - r128_freelist_reset(dev); - } - - /* Make sure WC cache has been flushed (if in PIO mode) */ - if (!dev_priv->cce_is_bm_mode) r128_flush_write_combine(); - - /* FIXME: Add support for sending vertex buffer to the CCE here - instead of in client code. The v->prim holds the primitive - type that should be drawn. Loop over the list buffers in - send_indices[] and submit a packet for each VB. - - This will require us to loop over the clip rects here as - well, which implies that we extend the kernel driver to allow - cliprects to be stored here. Note that the cliprects could - possibly come from the X server instead of the client, but - this will require additional changes to the DRI to allow for - this optimization. */ - - /* Submit a CCE packet that writes submit_age to R128_VB_AGE_REG */ -#if 0 - cce_buffer[0] = R128CCE0(R128_CCE_PACKET0, R128_VB_AGE_REG, 0); - cce_buffer[1] = dev_priv->submit_age; - - if ((ret = r128_do_submit_packet(dev, cce_buffer, 2)) < 0) { - /* Until we add support for sending VBs to the CCE in - this routine, we can recover from this error. After - we add that support, we won't be able to easily - recover, so we will probably have to implement - another mechanism for handling timeouts from packets - submitted directly by the kernel. */ - return ret; - } -#else - BEGIN_RING( 2 ); - - OUT_RING( CCE_PACKET0( R128_VB_AGE_REG, 0 ) ); - OUT_RING( dev_priv->submit_age ); - - ADVANCE_RING(); -#endif - /* Now that the submit packet request has succeeded, we can mark - the buffers as pending */ - for (i = 0; i < v->send_count; i++) { - buf = dma->buflist[v->send_indices[i]]; - buf->pending = 1; - - buf_priv = buf->dev_private; - buf_priv->age = dev_priv->submit_age; - } - - dev_priv->submit_age++; - - return 0; -} -#endif - - - - static int r128_cce_get_buffers( drm_device_t *dev, drm_dma_t *d ) { int i; diff --git a/linux/r128_drm.h b/linux/r128_drm.h index 57cb5c3d..94dba1ed 100644 --- a/linux/r128_drm.h +++ b/linux/r128_drm.h @@ -30,8 +30,8 @@ * */ -#ifndef _R128_DRM_H_ -#define _R128_DRM_H_ +#ifndef __R128_DRM_H__ +#define __R128_DRM_H__ /* WARNING: If you change any of these defines, make sure to change the * defines in the X server file (r128_sarea.h) @@ -69,21 +69,13 @@ /* Vertex/indirect buffer size */ -#if 1 #define R128_BUFFER_SIZE 16384 -#else -#define R128_BUFFER_SIZE (128 * 1024) -#endif /* Byte offsets for indirect buffer data */ #define R128_INDEX_PRIM_OFFSET 20 #define R128_HOSTDATA_BLIT_OFFSET 32 -/* 2048x2048 @ 32bpp texture requires this many indirect buffers - */ -#define R128_MAX_BLIT_BUFFERS ((2048 * 2048 * 4) / R128_BUFFER_SIZE) - /* Keep these small for testing. */ #define R128_NR_SAREA_CLIPRECTS 12 @@ -139,7 +131,8 @@ typedef struct { unsigned int scale_3d_cntl; } drm_r128_context_regs_t; -/* Setup registers for each texture unit */ +/* Setup registers for each texture unit + */ typedef struct { unsigned int tex_cntl; unsigned int tex_combine_cntl; @@ -216,6 +209,13 @@ typedef struct drm_r128_cce_stop { int idle; } drm_r128_cce_stop_t; +typedef struct drm_r128_fullscreen { + enum { + R128_INIT_FULLSCREEN = 0x01, + R128_CLEANUP_FULLSCREEN = 0x02 + } func; +} drm_r128_fullscreen_t; + typedef struct drm_r128_clear { unsigned int flags; int x, y, w, h; @@ -265,10 +265,11 @@ typedef struct drm_r128_stipple { unsigned int *mask; } drm_r128_stipple_t; -typedef struct drm_r128_packet { - unsigned int *buffer; - int count; - int flags; -} drm_r128_packet_t; +typedef struct drm_r128_indirect { + int idx; + int start; + int end; + int discard; +} drm_r128_indirect_t; #endif diff --git a/linux/r128_drv.c b/linux/r128_drv.c index dbfc9b74..cf258925 100644 --- a/linux/r128_drv.c +++ b/linux/r128_drv.c @@ -37,10 +37,10 @@ #define R128_NAME "r128" #define R128_DESC "ATI Rage 128" -#define R128_DATE "20001215" +#define R128_DATE "20010101" #define R128_MAJOR 2 #define R128_MINOR 1 -#define R128_PATCHLEVEL 2 +#define R128_PATCHLEVEL 4 static drm_device_t r128_device; drm_ctx_t r128_res_ctx; @@ -108,20 +108,22 @@ static drm_ioctl_desc_t r128_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 }, #endif - [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_cce_init, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_START)] = { r128_cce_start, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_STOP)] = { r128_cce_stop, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_RESET)] = { r128_cce_reset, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_IDLE)] = { r128_cce_idle, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_engine_reset, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_SWAP)] = { r128_cce_swap, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_CLEAR)] = { r128_cce_clear, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_INDICES)] = { r128_cce_indices, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_BLIT)] = { r128_cce_blit, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_DEPTH)] = { r128_cce_depth, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_STIPPLE)] = { r128_cce_stipple, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_PACKET)] = { r128_cce_packet, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_cce_init, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_START)] = { r128_cce_start, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_STOP)] = { r128_cce_stop, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_RESET)] = { r128_cce_reset, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_IDLE)] = { r128_cce_idle, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_engine_reset, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_FULLSCREEN)]= { r128_fullscreen, 1, 0 }, + + [DRM_IOCTL_NR(DRM_IOCTL_R128_SWAP)] = { r128_cce_swap, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CLEAR)] = { r128_cce_clear, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_INDICES)] = { r128_cce_indices, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_BLIT)] = { r128_cce_blit, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_DEPTH)] = { r128_cce_depth, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_STIPPLE)] = { r128_cce_stipple, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_INDIRECT)] = { r128_cce_indirect, 1, 1 }, }; #define R128_IOCTL_COUNT DRM_ARRAY_SIZE(r128_ioctls) @@ -489,7 +491,17 @@ int r128_release(struct inode *inode, struct file *filp) lock_kernel(); dev = priv->dev; + DRM_DEBUG("open_count = %d\n", dev->open_count); + + /* Force the cleanup of page flipping when required */ + if ( dev->dev_private ) { + drm_r128_private_t *dev_priv = dev->dev_private; + if ( dev_priv->page_flipping ) { + r128_do_cleanup_pageflip( dev ); + } + } + if (!(retcode = drm_release(inode, filp))) { #if LINUX_VERSION_CODE < 0x020333 MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */ diff --git a/linux/r128_drv.h b/linux/r128_drv.h index cffd0800..08ef5dc9 100644 --- a/linux/r128_drv.h +++ b/linux/r128_drv.h @@ -59,7 +59,6 @@ typedef struct drm_r128_private { int cce_mode; int cce_fifo_size; - int cce_secure; int cce_running; drm_r128_freelist_t *head; @@ -70,6 +69,11 @@ typedef struct drm_r128_private { atomic_t idle_count; + int page_flipping; + int current_page; + u32 crtc_offset; + u32 crtc_offset_cntl; + unsigned int fb_bpp; unsigned int front_offset; unsigned int front_pitch; @@ -128,7 +132,7 @@ extern int r128_cce_idle( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int r128_engine_reset( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); -extern int r128_cce_packet( struct inode *inode, struct file *filp, +extern int r128_fullscreen( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int r128_cce_buffers( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); @@ -139,6 +143,8 @@ extern drm_buf_t *r128_freelist_get( drm_device_t *dev ); extern int r128_wait_ring( drm_r128_private_t *dev_priv, int n ); extern void r128_update_ring_snapshot( drm_r128_private_t *dev_priv ); +extern int r128_do_cleanup_pageflip( drm_device_t *dev ); + /* r128_state.c */ extern int r128_cce_clear( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); @@ -154,6 +160,8 @@ extern int r128_cce_depth( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int r128_cce_stipple( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); +extern int r128_cce_indirect( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); /* r128_bufs.c */ extern int r128_addbufs(struct inode *inode, struct file *filp, @@ -215,8 +223,10 @@ extern int r128_context_switch_complete(drm_device_t *dev, int new); #define R128_CLOCK_CNTL_INDEX 0x0008 #define R128_CLOCK_CNTL_DATA 0x000c # define R128_PLL_WR_EN (1 << 7) - #define R128_CONSTANT_COLOR_C 0x1d34 +#define R128_CRTC_OFFSET 0x0224 +#define R128_CRTC_OFFSET_CNTL 0x0228 +# define R128_CRTC_OFFSET_FLIP_CNTL (1 << 16) #define R128_DP_GUI_MASTER_CNTL 0x146c # define R128_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0) @@ -431,12 +441,12 @@ extern int R128_READ_PLL(drm_device_t *dev, int addr); #define BEGIN_RING( n ) do { \ if ( R128_VERBOSE ) { \ DRM_INFO( "BEGIN_RING( %d ) in %s\n", \ - n, __FUNCTION__ ); \ + (n), __FUNCTION__ ); \ } \ - if ( dev_priv->ring.space < n * sizeof(u32) ) { \ - r128_wait_ring( dev_priv, n * sizeof(u32) ); \ + if ( dev_priv->ring.space < (n) * sizeof(u32) ) { \ + r128_wait_ring( dev_priv, (n) * sizeof(u32) ); \ } \ - dev_priv->ring.space -= n * sizeof(u32); \ + dev_priv->ring.space -= (n) * sizeof(u32); \ ring = dev_priv->ring.start; \ write = dev_priv->ring.tail; \ tail_mask = dev_priv->ring.tail_mask; \ @@ -457,7 +467,7 @@ extern int R128_READ_PLL(drm_device_t *dev, int addr); DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \ (unsigned int)(x), write ); \ } \ - ring[write++] = x; \ + ring[write++] = (x); \ write &= tail_mask; \ } while (0) diff --git a/linux/r128_state.c b/linux/r128_state.c index cdeb1bb5..cf54ed59 100644 --- a/linux/r128_state.c +++ b/linux/r128_state.c @@ -310,13 +310,13 @@ static void r128_clear_box( drm_r128_private_t *dev_priv, BEGIN_RING( 6 ); OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); - OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL - | R128_GMC_BRUSH_SOLID_COLOR - | fb_bpp - | R128_GMC_SRC_DATATYPE_COLOR - | R128_ROP3_P - | R128_GMC_CLR_CMP_CNTL_DIS - | R128_GMC_AUX_CLIP_DIS ); + OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL | + R128_GMC_BRUSH_SOLID_COLOR | + fb_bpp | + R128_GMC_SRC_DATATYPE_COLOR | + R128_ROP3_P | + R128_GMC_CLR_CMP_CNTL_DIS | + R128_GMC_AUX_CLIP_DIS ); OUT_RING( (pitch << 21) | (offset >> 5) ); OUT_RING( color ); @@ -398,6 +398,14 @@ static void r128_cce_dispatch_clear( drm_device_t *dev, return; } + if ( dev_priv->page_flipping && dev_priv->current_page == 1) { + unsigned int tmp = flags; + + flags &= ~(R128_FRONT | R128_BACK); + if ( tmp & R128_FRONT ) flags |= R128_BACK; + if ( tmp & R128_BACK ) flags |= R128_FRONT; + } + for ( i = 0 ; i < nbox ; i++ ) { int x = pbox[i].x1; int y = pbox[i].y1; @@ -421,13 +429,13 @@ static void r128_cce_dispatch_clear( drm_device_t *dev, BEGIN_RING( 6 ); OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); - OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL - | R128_GMC_BRUSH_SOLID_COLOR - | fb_bpp - | R128_GMC_SRC_DATATYPE_COLOR - | R128_ROP3_P - | R128_GMC_CLR_CMP_CNTL_DIS - | R128_GMC_AUX_CLIP_DIS ); + OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL | + R128_GMC_BRUSH_SOLID_COLOR | + fb_bpp | + R128_GMC_SRC_DATATYPE_COLOR | + R128_ROP3_P | + R128_GMC_CLR_CMP_CNTL_DIS | + R128_GMC_AUX_CLIP_DIS ); OUT_RING( dev_priv->front_pitch_offset_c ); OUT_RING( clear_color ); @@ -442,13 +450,13 @@ static void r128_cce_dispatch_clear( drm_device_t *dev, BEGIN_RING( 6 ); OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); - OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL - | R128_GMC_BRUSH_SOLID_COLOR - | fb_bpp - | R128_GMC_SRC_DATATYPE_COLOR - | R128_ROP3_P - | R128_GMC_CLR_CMP_CNTL_DIS - | R128_GMC_AUX_CLIP_DIS ); + OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL | + R128_GMC_BRUSH_SOLID_COLOR | + fb_bpp | + R128_GMC_SRC_DATATYPE_COLOR | + R128_ROP3_P | + R128_GMC_CLR_CMP_CNTL_DIS | + R128_GMC_AUX_CLIP_DIS ); OUT_RING( dev_priv->back_pitch_offset_c ); OUT_RING( clear_color ); @@ -463,14 +471,14 @@ static void r128_cce_dispatch_clear( drm_device_t *dev, BEGIN_RING( 6 ); OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); - OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL - | R128_GMC_BRUSH_SOLID_COLOR - | depth_bpp - | R128_GMC_SRC_DATATYPE_COLOR - | R128_ROP3_P - | R128_GMC_CLR_CMP_CNTL_DIS - | R128_GMC_AUX_CLIP_DIS - | R128_GMC_WR_MSK_DIS ); + OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL | + R128_GMC_BRUSH_SOLID_COLOR | + depth_bpp | + R128_GMC_SRC_DATATYPE_COLOR | + R128_ROP3_P | + R128_GMC_CLR_CMP_CNTL_DIS | + R128_GMC_AUX_CLIP_DIS | + R128_GMC_WR_MSK_DIS ); OUT_RING( dev_priv->depth_pitch_offset_c ); OUT_RING( clear_depth ); @@ -521,16 +529,16 @@ static void r128_cce_dispatch_swap( drm_device_t *dev ) BEGIN_RING( 7 ); OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) ); - OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL - | R128_GMC_DST_PITCH_OFFSET_CNTL - | R128_GMC_BRUSH_NONE - | fb_bpp - | R128_GMC_SRC_DATATYPE_COLOR - | R128_ROP3_S - | R128_DP_SRC_SOURCE_MEMORY - | R128_GMC_CLR_CMP_CNTL_DIS - | R128_GMC_AUX_CLIP_DIS - | R128_GMC_WR_MSK_DIS ); + OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL | + R128_GMC_DST_PITCH_OFFSET_CNTL | + R128_GMC_BRUSH_NONE | + fb_bpp | + R128_GMC_SRC_DATATYPE_COLOR | + R128_ROP3_S | + R128_DP_SRC_SOURCE_MEMORY | + R128_GMC_CLR_CMP_CNTL_DIS | + R128_GMC_AUX_CLIP_DIS | + R128_GMC_WR_MSK_DIS ); OUT_RING( dev_priv->back_pitch_offset_c ); OUT_RING( dev_priv->front_pitch_offset_c ); @@ -556,6 +564,48 @@ static void r128_cce_dispatch_swap( drm_device_t *dev ) ADVANCE_RING(); } +static void r128_cce_dispatch_flip( drm_device_t *dev ) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + RING_LOCALS; + DRM_DEBUG( "%s: page=%d\n", __FUNCTION__, dev_priv->current_page ); + + r128_update_ring_snapshot( dev_priv ); + +#if R128_PERFORMANCE_BOXES + /* Do some trivial performance monitoring... + */ + r128_cce_performance_boxes( dev_priv ); +#endif + + BEGIN_RING( 2 ); + + OUT_RING( CCE_PACKET0( R128_CRTC_OFFSET, 0 ) ); + + if ( dev_priv->current_page == 0 ) { + OUT_RING( dev_priv->back_offset ); + dev_priv->current_page = 1; + } else { + OUT_RING( dev_priv->front_offset ); + dev_priv->current_page = 0; + } + + ADVANCE_RING(); + + /* Increment the frame counter. The client-side 3D driver must + * throttle the framerate by waiting for this value before + * performing the swapbuffer ioctl. + */ + dev_priv->sarea_priv->last_frame++; + + BEGIN_RING( 2 ); + + OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) ); + OUT_RING( dev_priv->sarea_priv->last_frame ); + + ADVANCE_RING(); +} + static void r128_cce_dispatch_vertex( drm_device_t *dev, drm_buf_t *buf ) { @@ -821,13 +871,17 @@ static int r128_cce_dispatch_blit( drm_device_t *dev, * use a shift instead. */ switch ( blit->format ) { + case R128_DATATYPE_ARGB8888: + dword_shift = 0; + break; case R128_DATATYPE_ARGB1555: case R128_DATATYPE_RGB565: case R128_DATATYPE_ARGB4444: dword_shift = 1; break; - case R128_DATATYPE_ARGB8888: - dword_shift = 0; + case R128_DATATYPE_CI8: + case R128_DATATYPE_RGB8: + dword_shift = 2; break; default: DRM_ERROR( "invalid blit format %d\n", blit->format ); @@ -868,15 +922,15 @@ static int r128_cce_dispatch_blit( drm_device_t *dev, data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset); data[0] = CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 ); - data[1] = ( R128_GMC_DST_PITCH_OFFSET_CNTL - | R128_GMC_BRUSH_NONE - | (blit->format << 8) - | R128_GMC_SRC_DATATYPE_COLOR - | R128_ROP3_S - | R128_DP_SRC_SOURCE_HOST_DATA - | R128_GMC_CLR_CMP_CNTL_DIS - | R128_GMC_AUX_CLIP_DIS - | R128_GMC_WR_MSK_DIS ); + data[1] = (R128_GMC_DST_PITCH_OFFSET_CNTL | + R128_GMC_BRUSH_NONE | + (blit->format << 8) | + R128_GMC_SRC_DATATYPE_COLOR | + R128_ROP3_S | + R128_DP_SRC_SOURCE_HOST_DATA | + R128_GMC_CLR_CMP_CNTL_DIS | + R128_GMC_AUX_CLIP_DIS | + R128_GMC_WR_MSK_DIS); data[2] = (blit->pitch << 21) | (blit->offset >> 5); data[3] = 0xffffffff; @@ -971,15 +1025,14 @@ static int r128_cce_dispatch_write_span( drm_device_t *dev, if ( mask[i] ) { BEGIN_RING( 6 ); - OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, - 4 ) ); - OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL - | R128_GMC_BRUSH_SOLID_COLOR - | depth_bpp - | R128_GMC_SRC_DATATYPE_COLOR - | R128_ROP3_P - | R128_GMC_CLR_CMP_CNTL_DIS - | R128_GMC_WR_MSK_DIS ); + OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); + OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL | + R128_GMC_BRUSH_SOLID_COLOR | + depth_bpp | + R128_GMC_SRC_DATATYPE_COLOR | + R128_ROP3_P | + R128_GMC_CLR_CMP_CNTL_DIS | + R128_GMC_WR_MSK_DIS ); OUT_RING( dev_priv->depth_pitch_offset_c ); OUT_RING( buffer[i] ); @@ -997,13 +1050,13 @@ static int r128_cce_dispatch_write_span( drm_device_t *dev, BEGIN_RING( 6 ); OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); - OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL - | R128_GMC_BRUSH_SOLID_COLOR - | depth_bpp - | R128_GMC_SRC_DATATYPE_COLOR - | R128_ROP3_P - | R128_GMC_CLR_CMP_CNTL_DIS - | R128_GMC_WR_MSK_DIS ); + OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL | + R128_GMC_BRUSH_SOLID_COLOR | + depth_bpp | + R128_GMC_SRC_DATATYPE_COLOR | + R128_ROP3_P | + R128_GMC_CLR_CMP_CNTL_DIS | + R128_GMC_WR_MSK_DIS ); OUT_RING( dev_priv->depth_pitch_offset_c ); OUT_RING( buffer[i] ); @@ -1103,15 +1156,14 @@ static int r128_cce_dispatch_write_pixels( drm_device_t *dev, if ( mask[i] ) { BEGIN_RING( 6 ); - OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, - 4 ) ); - OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL - | R128_GMC_BRUSH_SOLID_COLOR - | depth_bpp - | R128_GMC_SRC_DATATYPE_COLOR - | R128_ROP3_P - | R128_GMC_CLR_CMP_CNTL_DIS - | R128_GMC_WR_MSK_DIS ); + OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); + OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL | + R128_GMC_BRUSH_SOLID_COLOR | + depth_bpp | + R128_GMC_SRC_DATATYPE_COLOR | + R128_ROP3_P | + R128_GMC_CLR_CMP_CNTL_DIS | + R128_GMC_WR_MSK_DIS ); OUT_RING( dev_priv->depth_pitch_offset_c ); OUT_RING( buffer[i] ); @@ -1129,13 +1181,13 @@ static int r128_cce_dispatch_write_pixels( drm_device_t *dev, BEGIN_RING( 6 ); OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); - OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL - | R128_GMC_BRUSH_SOLID_COLOR - | depth_bpp - | R128_GMC_SRC_DATATYPE_COLOR - | R128_ROP3_P - | R128_GMC_CLR_CMP_CNTL_DIS - | R128_GMC_WR_MSK_DIS ); + OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL | + R128_GMC_BRUSH_SOLID_COLOR | + depth_bpp | + R128_GMC_SRC_DATATYPE_COLOR | + R128_ROP3_P | + R128_GMC_CLR_CMP_CNTL_DIS | + R128_GMC_WR_MSK_DIS ); OUT_RING( dev_priv->depth_pitch_offset_c ); OUT_RING( buffer[i] ); @@ -1188,15 +1240,15 @@ static int r128_cce_dispatch_read_span( drm_device_t *dev, BEGIN_RING( 7 ); OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) ); - OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL - | R128_GMC_DST_PITCH_OFFSET_CNTL - | R128_GMC_BRUSH_NONE - | depth_bpp - | R128_GMC_SRC_DATATYPE_COLOR - | R128_ROP3_S - | R128_DP_SRC_SOURCE_MEMORY - | R128_GMC_CLR_CMP_CNTL_DIS - | R128_GMC_WR_MSK_DIS ); + OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL | + R128_GMC_DST_PITCH_OFFSET_CNTL | + R128_GMC_BRUSH_NONE | + depth_bpp | + R128_GMC_SRC_DATATYPE_COLOR | + R128_ROP3_S | + R128_DP_SRC_SOURCE_MEMORY | + R128_GMC_CLR_CMP_CNTL_DIS | + R128_GMC_WR_MSK_DIS ); OUT_RING( dev_priv->depth_pitch_offset_c ); OUT_RING( dev_priv->span_pitch_offset_c ); @@ -1263,15 +1315,15 @@ static int r128_cce_dispatch_read_pixels( drm_device_t *dev, BEGIN_RING( 7 ); OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) ); - OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL - | R128_GMC_DST_PITCH_OFFSET_CNTL - | R128_GMC_BRUSH_NONE - | depth_bpp - | R128_GMC_SRC_DATATYPE_COLOR - | R128_ROP3_S - | R128_DP_SRC_SOURCE_MEMORY - | R128_GMC_CLR_CMP_CNTL_DIS - | R128_GMC_WR_MSK_DIS ); + OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL | + R128_GMC_DST_PITCH_OFFSET_CNTL | + R128_GMC_BRUSH_NONE | + depth_bpp | + R128_GMC_SRC_DATATYPE_COLOR | + R128_ROP3_S | + R128_DP_SRC_SOURCE_MEMORY | + R128_GMC_CLR_CMP_CNTL_DIS | + R128_GMC_WR_MSK_DIS ); OUT_RING( dev_priv->depth_pitch_offset_c ); OUT_RING( dev_priv->span_pitch_offset_c ); @@ -1370,11 +1422,13 @@ int r128_cce_swap( struct inode *inode, struct file *filp, if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS ) sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; - r128_cce_dispatch_swap( dev ); - - /* Make sure we restore the 3D state next time. - */ - dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS; + if ( !dev_priv->page_flipping ) { + r128_cce_dispatch_swap( dev ); + dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT | + R128_UPLOAD_MASKS); + } else { + r128_cce_dispatch_flip( dev ); + } return 0; } @@ -1603,3 +1657,20 @@ int r128_cce_stipple( struct inode *inode, struct file *filp, return 0; } + +int r128_cce_indirect( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || + dev->lock.pid != current->pid ) { + DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); + return -EINVAL; + } + + /* Indirect buffer firing is not supported at this time. + */ + return -EINVAL; +} diff --git a/linux/radeon_cp.c b/linux/radeon_cp.c index 68a014cf..ac4d7823 100644 --- a/linux/radeon_cp.c +++ b/linux/radeon_cp.c @@ -36,6 +36,8 @@ #include <linux/interrupt.h> /* For task queue support */ #include <linux/delay.h> +#define RADEON_FIFO_DEBUG 0 + /* CP microcode (from ATI) */ static u32 radeon_cp_microcode[][2] = { @@ -326,24 +328,9 @@ int RADEON_READ_PLL(drm_device_t *dev, int addr) return RADEON_READ(RADEON_CLOCK_CNTL_DATA); } - +#if RADEON_FIFO_DEBUG static void radeon_status( drm_radeon_private_t *dev_priv ) { -#if 0 - printk( "GUI_STAT = 0x%08x\n", - (unsigned int)RADEON_READ( RADEON_GUI_STAT ) ); - printk( "PM4_STAT = 0x%08x\n", - (unsigned int)RADEON_READ( RADEON_PM4_STAT ) ); - printk( "PM4_BUFFER_DL_WPTR = 0x%08x\n", - (unsigned int)RADEON_READ( RADEON_PM4_BUFFER_DL_WPTR ) ); - printk( "PM4_BUFFER_DL_RPTR = 0x%08x\n", - (unsigned int)RADEON_READ( RADEON_PM4_BUFFER_DL_RPTR ) ); - printk( "PM4_MICRO_CNTL = 0x%08x\n", - (unsigned int)RADEON_READ( RADEON_PM4_MICRO_CNTL ) ); - printk( "PM4_BUFFER_CNTL = 0x%08x\n", - (unsigned int)RADEON_READ( RADEON_PM4_BUFFER_CNTL ) ); -#endif - printk( "%s:\n", __FUNCTION__ ); printk( "RBBM_STATUS = 0x%08x\n", (unsigned int)RADEON_READ( RADEON_RBBM_STATUS ) ); @@ -352,6 +339,7 @@ static void radeon_status( drm_radeon_private_t *dev_priv ) printk( "CP_RB_WTPR = 0x%08x\n", (unsigned int)RADEON_READ( RADEON_CP_RB_WPTR ) ); } +#endif /* ================================================================ @@ -375,7 +363,10 @@ static int radeon_do_pixcache_flush( drm_radeon_private_t *dev_priv ) udelay( 1 ); } +#if RADEON_FIFO_DEBUG DRM_ERROR( "failed!\n" ); + radeon_status( dev_priv ); +#endif return -EBUSY; } @@ -391,7 +382,7 @@ static int radeon_do_wait_for_fifo( drm_radeon_private_t *dev_priv, udelay( 1 ); } -#if 1 +#if RADEON_FIFO_DEBUG DRM_ERROR( "failed!\n" ); radeon_status( dev_priv ); #endif @@ -414,8 +405,9 @@ static int radeon_do_wait_for_idle( drm_radeon_private_t *dev_priv ) udelay( 1 ); } -#if 0 +#if RADEON_FIFO_DEBUG DRM_ERROR( "failed!\n" ); + radeon_status( dev_priv ); #endif return -EBUSY; } @@ -459,12 +451,6 @@ static void radeon_do_cp_flush( drm_radeon_private_t *dev_priv ) */ static int radeon_do_cp_idle( drm_radeon_private_t *dev_priv ) { - RING_LOCALS; - - RADEON_WAIT_UNTIL_IDLE(); - RADEON_FLUSH_CACHE(); - RADEON_FLUSH_ZCACHE(); - return radeon_do_wait_for_idle( dev_priv ); } @@ -505,14 +491,6 @@ static void radeon_do_cp_reset( drm_radeon_private_t *dev_priv ) */ static void radeon_do_cp_stop( drm_radeon_private_t *dev_priv ) { - if ( dev_priv->cp_running ) { - RING_LOCALS; - - RADEON_WAIT_UNTIL_IDLE(); - RADEON_FLUSH_CACHE(); - RADEON_FLUSH_ZCACHE(); - } - RADEON_WRITE( RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS ); dev_priv->cp_running = 0; @@ -524,6 +502,7 @@ static int radeon_do_engine_reset( drm_device_t *dev ) { drm_radeon_private_t *dev_priv = dev->dev_private; u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset; + DRM_DEBUG( "%s\n", __FUNCTION__ ); radeon_do_pixcache_flush( dev_priv ); @@ -618,10 +597,11 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev ) RADEON_WRITE( RADEON_BUS_CNTL, tmp ); /* Sync everything up */ - RADEON_WRITE( RADEON_ISYNC_CNTL, (RADEON_ISYNC_ANY2D_IDLE3D | - RADEON_ISYNC_ANY3D_IDLE2D | - RADEON_ISYNC_WAIT_IDLEGUI | - RADEON_ISYNC_CPSCRATCH_IDLEGUI) ); + RADEON_WRITE( RADEON_ISYNC_CNTL, + (RADEON_ISYNC_ANY2D_IDLE3D | + RADEON_ISYNC_ANY3D_IDLE2D | + RADEON_ISYNC_WAIT_IDLEGUI | + RADEON_ISYNC_CPSCRATCH_IDLEGUI) ); } static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) @@ -943,20 +923,21 @@ int radeon_engine_reset( struct inode *inode, struct file *filp, /* ================================================================ - * Page flipping + * Fullscreen mode */ static int radeon_do_init_pageflip( drm_device_t *dev ) { drm_radeon_private_t *dev_priv = dev->dev_private; - u32 crtc_offset_cntl; DRM_DEBUG( "%s\n", __FUNCTION__ ); - RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->front_offset ); + dev_priv->crtc_offset = RADEON_READ( RADEON_CRTC_OFFSET ); + dev_priv->crtc_offset_cntl = RADEON_READ( RADEON_CRTC_OFFSET_CNTL ); - crtc_offset_cntl = RADEON_READ( RADEON_CRTC_OFFSET_CNTL ); + RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->front_offset ); RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL, - crtc_offset_cntl | RADEON_CRTC_OFFSET_FLIP_CNTL ); + dev_priv->crtc_offset_cntl | + RADEON_CRTC_OFFSET_FLIP_CNTL ); dev_priv->page_flipping = 1; dev_priv->current_page = 0; @@ -967,14 +948,10 @@ static int radeon_do_init_pageflip( drm_device_t *dev ) int radeon_do_cleanup_pageflip( drm_device_t *dev ) { drm_radeon_private_t *dev_priv = dev->dev_private; - u32 crtc_offset_cntl; DRM_DEBUG( "%s\n", __FUNCTION__ ); - RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->front_offset ); - - crtc_offset_cntl = RADEON_READ( RADEON_CRTC_OFFSET_CNTL ); - RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL, - crtc_offset_cntl & ~RADEON_CRTC_OFFSET_FLIP_CNTL ); + RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->crtc_offset ); + RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl ); dev_priv->page_flipping = 0; dev_priv->current_page = 0; @@ -982,12 +959,12 @@ int radeon_do_cleanup_pageflip( drm_device_t *dev ) return 0; } -int radeon_cp_pageflip( struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg ) +int radeon_fullscreen( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - drm_radeon_pageflip_t p; + drm_radeon_fullscreen_t fs; if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || dev->lock.pid != current->pid ) { @@ -995,13 +972,14 @@ int radeon_cp_pageflip( struct inode *inode, struct file *filp, return -EINVAL; } - if ( copy_from_user( &p, (drm_radeon_pageflip_t *)arg, sizeof(p) ) ) + if ( copy_from_user( &fs, (drm_radeon_fullscreen_t *)arg, + sizeof(fs) ) ) return -EFAULT; - switch ( p.func ) { - case RADEON_INIT_PAGEFLIP: + switch ( fs.func ) { + case RADEON_INIT_FULLSCREEN: return radeon_do_init_pageflip( dev ); - case RADEON_CLEANUP_PAGEFLIP: + case RADEON_CLEANUP_FULLSCREEN: return radeon_do_cleanup_pageflip( dev ); } @@ -1015,6 +993,7 @@ int radeon_cp_pageflip( struct inode *inode, struct file *filp, #define RADEON_BUFFER_USED 0xffffffff #define RADEON_BUFFER_FREE 0 +#if 0 static int radeon_freelist_init( drm_device_t *dev ) { drm_device_dma_t *dma = dev->dma; @@ -1060,6 +1039,7 @@ static int radeon_freelist_init( drm_device_t *dev ) return 0; } +#endif drm_buf_t *radeon_freelist_get( drm_device_t *dev ) { @@ -1142,7 +1122,7 @@ void radeon_freelist_reset( drm_device_t *dev ) /* ================================================================ - * CP packet submission + * CP command submission */ int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n ) @@ -1175,334 +1155,8 @@ void radeon_update_ring_snapshot( drm_radeon_private_t *dev_priv ) atomic_inc( &dev_priv->idle_count ); if ( ring->space <= 0 ) ring->space += ring->size; - - if ( 0 ) { - DRM_INFO( "update_ring: size=0x%x space=%d\n", - ring->size, ring->space ); - DRM_INFO( "tail=0x%04x\n", ring->tail ); - DRM_INFO( "head=0x%04x\n", *ring->head ); - } -} - -#if 0 -static int radeon_verify_command( drm_radeon_private_t *dev_priv, - u32 cmd, int *size ) -{ - int writing = 1; - - *size = 0; - - switch ( cmd & RADEON_CP_PACKET_MASK ) { - case RADEON_CP_PACKET0: - if ( (cmd & RADEON_CP_PACKET0_REG_MASK) <= (0x1004 >> 2) && - (cmd & RADEON_CP_PACKET0_REG_MASK) != - (RADEON_PM4_VC_FPU_SETUP >> 2) ) { - writing = 0; - } - *size = ((cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16) + 2; - break; - - case RADEON_CP_PACKET1: - if ( (cmd & RADEON_CP_PACKET1_REG0_MASK) <= (0x1004 >> 2) && - (cmd & RADEON_CP_PACKET1_REG0_MASK) != - (RADEON_PM4_VC_FPU_SETUP >> 2) ) { - writing = 0; - } - if ( (cmd & RADEON_CP_PACKET1_REG1_MASK) <= (0x1004 << 9) && - (cmd & RADEON_CP_PACKET1_REG1_MASK) != - (RADEON_PM4_VC_FPU_SETUP << 9) ) { - writing = 0; - } - *size = 3; - break; - - case RADEON_CP_PACKET2: - break; - - case RADEON_CP_PACKET3: - *size = ((cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16) + 2; - break; - - } - - return writing; -} - -static int radeon_submit_packet_ring_secure( drm_radeon_private_t *dev_priv, - u32 *commands, int *count ) -{ -#if 0 - int write = dev_priv->sarea_priv->ring_write; - int *write_ptr = dev_priv->ring_start + write; - int c = *count; - u32 tmp = 0; - int psize = 0; - int writing = 1; - int timeout; - - while ( c > 0 ) { - tmp = *commands++; - if ( !psize ) { - writing = radeon_verify_command( dev_priv, tmp, &psize ); - } - psize--; - - if ( writing ) { - write++; - *write_ptr++ = tmp; - } - if ( write >= dev_priv->ring_entries ) { - write = 0; - write_ptr = dev_priv->ring_start; - } - timeout = 0; - while ( write == *dev_priv->ring_read_ptr ) { - RADEON_READ( RADEON_PM4_BUFFER_DL_RPTR ); - if ( timeout++ >= dev_priv->usec_timeout ) - return -EBUSY; - udelay( 1 ); - } - c--; - } - - /* Make sure WC cache has been flushed */ - radeon_flush_write_combine(); - - dev_priv->sarea_priv->ring_write = write; - RADEON_WRITE( RADEON_PM4_BUFFER_DL_WPTR, write ); - - *count = 0; -#endif - return 0; -} - -static int radeon_submit_packet_ring_insecure( drm_radeon_private_t *dev_priv, - u32 *commands, int *count ) -{ -#if 0 - int write = dev_priv->sarea_priv->ring_write; - int *write_ptr = dev_priv->ring_start + write; - int c = *count; - int timeout; - - while ( c > 0 ) { - write++; - *write_ptr++ = *commands++; - if ( write >= dev_priv->ring_entries ) { - write = 0; - write_ptr = dev_priv->ring_start; - } - - timeout = 0; - while ( write == *dev_priv->ring_read_ptr ) { - RADEON_READ( RADEON_PM4_BUFFER_DL_RPTR ); - if ( timeout++ >= dev_priv->usec_timeout ) - return -EBUSY; - udelay( 1 ); - } - c--; - } - - /* Make sure WC cache has been flushed */ - radeon_flush_write_combine(); - - dev_priv->sarea_priv->ring_write = write; - RADEON_WRITE( RADEON_PM4_BUFFER_DL_WPTR, write ); - - *count = 0; -#endif - return 0; -} -#endif - -/* Internal packet submission routine. This uses the insecure versions - * of the packet submission functions, and thus should only be used for - * packets generated inside the kernel module. - */ -int radeon_do_submit_packet( drm_radeon_private_t *dev_priv, - u32 *buffer, int count ) -{ - int c = count; - int ret = 0; - -#if 0 - int left = 0; - - if ( c >= dev_priv->ring_entries ) { - c = dev_priv->ring_entries - 1; - left = count - c; - } - - /* Since this is only used by the kernel we can use the - * insecure ring buffer submit packet routine. - */ - ret = radeon_submit_packet_ring_insecure( dev_priv, buffer, &c ); - c += left; -#endif - - return ( ret < 0 ) ? ret : c; } -static int radeon_do_cp_packet( drm_radeon_private_t *dev_priv, - u32 *commands, int count ) -{ - int c; - RING_LOCALS; - - /* FIXME: Optimize!!! GH: Why bother? */ - for ( c = 0 ; c < count ; c++ ) { - BEGIN_RING( 1 ); - OUT_RING( commands[c] ); - ADVANCE_RING(); - } - - return 0; -} - -/* External packet submission routine. This uses the secure versions - * by default, and can thus submit packets received from user space. - */ -int radeon_cp_packet( struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg ) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_packet_t packet; - u32 *buffer; - int ret; - - if ( !capable( CAP_SYS_ADMIN ) ) { - DRM_ERROR( "radeon_cp_packet called without permission\n" ); - return -EACCES; - } - - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || - dev->lock.pid != current->pid ) { - DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); - return -EINVAL; - } - - if ( copy_from_user( &packet, (drm_radeon_packet_t *)arg, - sizeof(packet) ) ) - return -EFAULT; - - buffer = kmalloc( packet.count * sizeof(*buffer), 0 ); - if ( buffer == NULL) - return -ENOMEM; - if ( copy_from_user( buffer, packet.buffer, - packet.count * sizeof(*buffer) ) ) - return -EFAULT; - - ret = radeon_do_cp_packet( dev_priv, buffer, packet.count ); - - kfree( buffer ); - - packet.count = 0; - if ( copy_to_user( (drm_radeon_packet_t *)arg, &packet, - sizeof(packet) ) ) - return -EFAULT; - - return ret; -} - -#if 0 -static int radeon_send_vertbufs( drm_device_t *dev, drm_radeon_vertex_t *v ) -{ - drm_device_dma_t *dma = dev->dma; - drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_buf_priv_t *buf_priv; - drm_buf_t *buf; - int i, ret; - RING_LOCALS; - - /* Make sure we have valid data */ - for (i = 0; i < v->send_count; i++) { - int idx = v->send_indices[i]; - - if (idx < 0 || idx >= dma->buf_count) { - DRM_ERROR("Index %d (of %d max)\n", - idx, dma->buf_count - 1); - return -EINVAL; - } - buf = dma->buflist[idx]; - if (buf->pid != current->pid) { - DRM_ERROR("Process %d using buffer owned by %d\n", - current->pid, buf->pid); - return -EINVAL; - } - if (buf->pending) { - DRM_ERROR("Sending pending buffer:" - " buffer %d, offset %d\n", - v->send_indices[i], i); - return -EINVAL; - } - } - - /* Wait for idle, if we've wrapped to make sure that all pending - buffers have been processed */ - if (dev_priv->submit_age == RADEON_MAX_VBUF_AGE) { - if ((ret = radeon_do_cp_idle(dev)) < 0) return ret; - dev_priv->submit_age = 0; - radeon_freelist_reset(dev); - } - - /* Make sure WC cache has been flushed (if in PIO mode) */ - if (!dev_priv->cp_is_bm_mode) radeon_flush_write_combine(); - - /* FIXME: Add support for sending vertex buffer to the CP here - instead of in client code. The v->prim holds the primitive - type that should be drawn. Loop over the list buffers in - send_indices[] and submit a packet for each VB. - - This will require us to loop over the clip rects here as - well, which implies that we extend the kernel driver to allow - cliprects to be stored here. Note that the cliprects could - possibly come from the X server instead of the client, but - this will require additional changes to the DRI to allow for - this optimization. */ - - /* Submit a CP packet that writes submit_age to RADEON_VB_AGE_REG */ -#if 0 - cp_buffer[0] = RADEONCP0(RADEON_CP_PACKET0, RADEON_VB_AGE_REG, 0); - cp_buffer[1] = dev_priv->submit_age; - - if ((ret = radeon_do_submit_packet(dev, cp_buffer, 2)) < 0) { - /* Until we add support for sending VBs to the CP in - this routine, we can recover from this error. After - we add that support, we won't be able to easily - recover, so we will probably have to implement - another mechanism for handling timeouts from packets - submitted directly by the kernel. */ - return ret; - } -#else - BEGIN_RING( 2 ); - - OUT_RING( CP_PACKET0( RADEON_VB_AGE_REG, 0 ) ); - OUT_RING( dev_priv->submit_age ); - - ADVANCE_RING(); -#endif - /* Now that the submit packet request has succeeded, we can mark - the buffers as pending */ - for (i = 0; i < v->send_count; i++) { - buf = dma->buflist[v->send_indices[i]]; - buf->pending = 1; - - buf_priv = buf->dev_private; - buf_priv->age = dev_priv->submit_age; - } - - dev_priv->submit_age++; - - return 0; -} -#endif - - - - static int radeon_cp_get_buffers( drm_device_t *dev, drm_dma_t *d ) { int i; diff --git a/linux/radeon_drm.h b/linux/radeon_drm.h index 73eabd9c..03f29737 100644 --- a/linux/radeon_drm.h +++ b/linux/radeon_drm.h @@ -132,9 +132,6 @@ typedef struct { unsigned int se_line_width; /* 0x1db8 */ - /* Texture state */ - unsigned int pp_tfactor; - /* Bumpmap state */ unsigned int pp_lum_matrix; /* 0x1d00 */ @@ -187,6 +184,7 @@ typedef struct { unsigned int pp_txoffset; unsigned int pp_txcblend; unsigned int pp_txablend; + unsigned int pp_tfactor; unsigned int pp_border_color; @@ -262,12 +260,12 @@ typedef struct drm_radeon_cp_stop { int idle; } drm_radeon_cp_stop_t; -typedef struct drm_radeon_pageflip { +typedef struct drm_radeon_fullscreen { enum { - RADEON_INIT_PAGEFLIP = 0x01, - RADEON_CLEANUP_PAGEFLIP = 0x02 + RADEON_INIT_FULLSCREEN = 0x01, + RADEON_CLEANUP_FULLSCREEN = 0x02 } func; -} drm_radeon_pageflip_t; +} drm_radeon_fullscreen_t; typedef struct drm_radeon_clear { unsigned int flags; @@ -304,10 +302,11 @@ typedef struct drm_radeon_stipple { unsigned int *mask; } drm_radeon_stipple_t; -typedef struct drm_radeon_packet { - unsigned int *buffer; - int count; - int flags; -} drm_radeon_packet_t; +typedef struct drm_radeon_indirect { + int idx; + int start; + int end; + int discard; +} drm_radeon_indirect_t; #endif diff --git a/linux/radeon_drv.c b/linux/radeon_drv.c index 93ad2f0d..07f85981 100644 --- a/linux/radeon_drv.c +++ b/linux/radeon_drv.c @@ -34,7 +34,7 @@ #define RADEON_NAME "radeon" #define RADEON_DESC "ATI Radeon" -#define RADEON_DATE "20001228" +#define RADEON_DATE "20001230" #define RADEON_MAJOR 1 #define RADEON_MINOR 0 #define RADEON_PATCHLEVEL 0 @@ -105,20 +105,21 @@ static drm_ioctl_desc_t radeon_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 }, #endif - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_INIT)] = { radeon_cp_init, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_START)]= { radeon_cp_start, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_STOP)] = { radeon_cp_stop, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_RESET)]= { radeon_cp_reset, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_IDLE)] = { radeon_cp_idle, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_RESET)] = { radeon_engine_reset,1,0 }, - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_PAGEFLIP)]= { radeon_cp_pageflip,1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_INIT)] = { radeon_cp_init, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_START)] = { radeon_cp_start, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_STOP)] = { radeon_cp_stop, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_RESET)] = { radeon_cp_reset, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_IDLE)] = { radeon_cp_idle, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_RESET)] = { radeon_engine_reset, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FULLSCREEN)] = { radeon_fullscreen, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SWAP)] = { radeon_cp_swap, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CLEAR)] = { radeon_cp_clear, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX)] = { radeon_cp_vertex, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDICES)] = { radeon_cp_indices, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_RADEON_BLIT)] = { radeon_cp_blit, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_RADEON_STIPPLE)] = { radeon_cp_stipple, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_PACKET)] = { radeon_cp_packet, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDIRECT)]= { radeon_cp_indirect,1, 1 }, }; #define RADEON_IOCTL_COUNT DRM_ARRAY_SIZE(radeon_ioctls) @@ -612,9 +613,6 @@ int radeon_lock(struct inode *inode, struct file *filp, unsigned int cmd, /* Contention */ atomic_inc(&dev->total_sleeps); -#if 1 - current->policy |= SCHED_YIELD; -#endif schedule(); if (signal_pending(current)) { ret = -ERESTARTSYS; @@ -625,32 +623,6 @@ int radeon_lock(struct inode *inode, struct file *filp, unsigned int cmd, remove_wait_queue(&dev->lock.lock_queue, &entry); } -#if 0 - if (!ret && dev->last_context != lock.context && - lock.context != radeon_res_ctx.handle && - dev->last_context != radeon_res_ctx.handle) { - add_wait_queue(&dev->context_wait, &entry); - current->state = TASK_INTERRUPTIBLE; - /* PRE: dev->last_context != lock.context */ - radeon_context_switch(dev, dev->last_context, lock.context); - /* POST: we will wait for the context - switch and will dispatch on a later call - when dev->last_context == lock.context - NOTE WE HOLD THE LOCK THROUGHOUT THIS - TIME! */ - current->policy |= SCHED_YIELD; - schedule(); - current->state = TASK_RUNNING; - remove_wait_queue(&dev->context_wait, &entry); - if (signal_pending(current)) { - ret = -EINTR; - } else if (dev->last_context != lock.context) { - DRM_ERROR("Context mismatch: %d %d\n", - dev->last_context, lock.context); - } - } -#endif - if (!ret) { sigemptyset(&dev->sigmask); sigaddset(&dev->sigmask, SIGSTOP); diff --git a/linux/radeon_drv.h b/linux/radeon_drv.h index 93c83e9e..8456a8a9 100644 --- a/linux/radeon_drv.h +++ b/linux/radeon_drv.h @@ -81,6 +81,8 @@ typedef struct drm_radeon_private { int page_flipping; int current_page; + u32 crtc_offset; + u32 crtc_offset_cntl; unsigned int fb_bpp; unsigned int front_offset; @@ -138,10 +140,8 @@ extern int radeon_cp_idle( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int radeon_engine_reset( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); -extern int radeon_cp_pageflip( struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg ); -extern int radeon_cp_packet( struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg ); +extern int radeon_fullscreen( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); extern int radeon_cp_buffers( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); @@ -166,6 +166,8 @@ extern int radeon_cp_blit( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int radeon_cp_stipple( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); +extern int radeon_cp_indirect( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); /* radeon_bufs.c */ extern int radeon_addbufs(struct inode *inode, struct file *filp, @@ -214,6 +216,7 @@ extern int radeon_context_switch_complete(drm_device_t *dev, int new); #define RADEON_CONFIG_APER_SIZE 0x0108 #define RADEON_CRTC_OFFSET 0x0224 #define RADEON_CRTC_OFFSET_CNTL 0x0228 +# define RADEON_CRTC_TILE_EN (1 << 15) # define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16) #define RADEON_DP_GUI_MASTER_CNTL 0x146c @@ -233,6 +236,12 @@ extern int radeon_context_switch_complete(drm_device_t *dev, int new); # define RADEON_ROP3_S 0x00cc0000 # define RADEON_ROP3_P 0x00f00000 #define RADEON_DP_WRITE_MASK 0x16cc +#define RADEON_DST_PITCH_OFFSET 0x142c +#define RADEON_DST_PITCH_OFFSET_C 0x1c80 +# define RADEON_DST_TILE_LINEAR (0 << 30) +# define RADEON_DST_TILE_MACRO (1 << 30) +# define RADEON_DST_TILE_MICRO (2 << 30) +# define RADEON_DST_TILE_BOTH (3 << 30) #define RADEON_GUI_SCRATCH_REG0 0x15e0 #define RADEON_GUI_SCRATCH_REG1 0x15e4 @@ -367,8 +376,6 @@ extern int radeon_context_switch_complete(drm_device_t *dev, int new); #define RADEON_WAIT_UNTIL 0x1720 # define RADEON_WAIT_CRTC_PFLIP (1 << 0) -# define RADEON_WAIT_2D_IDLE (1 << 14) -# define RADEON_WAIT_3D_IDLE (1 << 15) # define RADEON_WAIT_2D_IDLECLEAN (1 << 16) # define RADEON_WAIT_3D_IDLECLEAN (1 << 17) # define RADEON_WAIT_HOST_IDLECLEAN (1 << 18) @@ -451,11 +458,7 @@ extern int radeon_context_switch_complete(drm_device_t *dev, int new); #define RADEON_COLOR_FORMAT_RGB565 4 #define RADEON_COLOR_FORMAT_ARGB8888 6 #define RADEON_COLOR_FORMAT_RGB332 7 -#define RADEON_COLOR_FORMAT_Y8 8 #define RADEON_COLOR_FORMAT_RGB8 9 -#define RADEON_COLOR_FORMAT_YUV422_VYUY 11 -#define RADEON_COLOR_FORMAT_YUV422_YVYU 12 -#define RADEON_COLOR_FORMAT_aYUV444 14 #define RADEON_COLOR_FORMAT_ARGB4444 15 #define RADEON_TXF_8BPP_I 0 @@ -512,45 +515,63 @@ extern int RADEON_READ_PLL(drm_device_t *dev, int addr); /* */ +#define RADEON_WAIT_UNTIL_2D_IDLE() \ +do { \ + BEGIN_RING( 2 ); \ + OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \ + OUT_RING( (RADEON_WAIT_2D_IDLECLEAN | \ + RADEON_WAIT_HOST_IDLECLEAN) ); \ + ADVANCE_RING(); \ +} while (0) + +#define RADEON_WAIT_UNTIL_3D_IDLE() \ +do { \ + BEGIN_RING( 2 ); \ + OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \ + OUT_RING( (RADEON_WAIT_3D_IDLECLEAN | \ + RADEON_WAIT_HOST_IDLECLEAN) ); \ + ADVANCE_RING(); \ +} while (0) + #define RADEON_WAIT_UNTIL_IDLE() \ do { \ BEGIN_RING( 2 ); \ - \ OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \ OUT_RING( (RADEON_WAIT_2D_IDLECLEAN | \ RADEON_WAIT_3D_IDLECLEAN | \ RADEON_WAIT_HOST_IDLECLEAN) ); \ - \ ADVANCE_RING(); \ } while (0) #define RADEON_WAIT_UNTIL_PAGE_FLIPPED() \ do { \ BEGIN_RING( 2 ); \ - \ OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \ OUT_RING( RADEON_WAIT_CRTC_PFLIP ); \ - \ ADVANCE_RING(); \ } while (0) #define RADEON_FLUSH_CACHE() \ do { \ BEGIN_RING( 2 ); \ - \ OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) ); \ OUT_RING( RADEON_RB2D_DC_FLUSH ); \ - \ + ADVANCE_RING(); \ +} while (0) + +#define RADEON_PURGE_CACHE() \ +do { \ + BEGIN_RING( 2 ); \ + OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) ); \ + OUT_RING( RADEON_RB2D_DC_FLUSH_ALL ); \ ADVANCE_RING(); \ } while (0) #define RADEON_FLUSH_ZCACHE() \ do { \ BEGIN_RING( 2 ); \ - \ OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) ); \ OUT_RING( RADEON_RB3D_ZC_FLUSH ); \ - \ ADVANCE_RING(); \ } while (0) @@ -567,10 +588,10 @@ do { \ DRM_INFO( "BEGIN_RING( %d ) in %s\n", \ n, __FUNCTION__ ); \ } \ - if ( dev_priv->ring.space < n * sizeof(u32) ) { \ - radeon_wait_ring( dev_priv, n * sizeof(u32) ); \ + if ( dev_priv->ring.space < (n) * sizeof(u32) ) { \ + radeon_wait_ring( dev_priv, (n) * sizeof(u32) ); \ } \ - dev_priv->ring.space -= n * sizeof(u32); \ + dev_priv->ring.space -= (n) * sizeof(u32); \ ring = dev_priv->ring.start; \ write = dev_priv->ring.tail; \ mask = dev_priv->ring.tail_mask; \ @@ -591,7 +612,7 @@ do { \ DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \ (unsigned int)(x), write ); \ } \ - ring[write++] = x; \ + ring[write++] = (x); \ write &= mask; \ } while (0) diff --git a/linux/radeon_state.c b/linux/radeon_state.c index c99e1ad7..f94f965f 100644 --- a/linux/radeon_state.c +++ b/linux/radeon_state.c @@ -34,9 +34,6 @@ #include "drm.h" #include <linux/delay.h> -/* This must be defined to 1 for now */ -#define USE_OLD_BLITS 0 - /* ================================================================ * CP hardware state programming functions @@ -235,9 +232,9 @@ static inline void radeon_emit_setup( drm_radeon_private_t *dev_priv ) ADVANCE_RING(); } -#ifdef TCL_ENABLE static inline void radeon_emit_tcl( drm_radeon_private_t *dev_priv ) { +#ifdef TCL_ENABLE drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_radeon_context_regs_t *ctx = &sarea_priv->context_state; RING_LOCALS; @@ -275,8 +272,10 @@ static inline void radeon_emit_tcl( drm_radeon_private_t *dev_priv ) } ADVANCE_RING(); -} +#else + DRM_ERROR( "TCL not enabled!\n" ); #endif +} static inline void radeon_emit_misc( drm_radeon_private_t *dev_priv ) { @@ -297,7 +296,6 @@ static inline void radeon_emit_misc( drm_radeon_private_t *dev_priv ) static inline void radeon_emit_tex0( drm_radeon_private_t *dev_priv ) { drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_radeon_context_regs_t *ctx = &sarea_priv->context_state; drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[0]; RING_LOCALS; DRM_DEBUG( " %s: offset=0x%x\n", __FUNCTION__, tex->pp_txoffset ); @@ -310,7 +308,7 @@ static inline void radeon_emit_tex0( drm_radeon_private_t *dev_priv ) OUT_RING( tex->pp_txoffset ); OUT_RING( tex->pp_txcblend ); OUT_RING( tex->pp_txablend ); - OUT_RING( ctx->pp_tfactor ); + OUT_RING( tex->pp_tfactor ); OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_0, 0 ) ); OUT_RING( tex->pp_border_color ); @@ -321,7 +319,6 @@ static inline void radeon_emit_tex0( drm_radeon_private_t *dev_priv ) static inline void radeon_emit_tex1( drm_radeon_private_t *dev_priv ) { drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_radeon_context_regs_t *ctx = &sarea_priv->context_state; drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[1]; RING_LOCALS; DRM_DEBUG( " %s: offset=0x%x\n", __FUNCTION__, tex->pp_txoffset ); @@ -334,7 +331,7 @@ static inline void radeon_emit_tex1( drm_radeon_private_t *dev_priv ) OUT_RING( tex->pp_txoffset ); OUT_RING( tex->pp_txcblend ); OUT_RING( tex->pp_txablend ); - OUT_RING( ctx->pp_tfactor ); + OUT_RING( tex->pp_tfactor ); OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_1, 0 ) ); OUT_RING( tex->pp_border_color ); @@ -345,7 +342,6 @@ static inline void radeon_emit_tex1( drm_radeon_private_t *dev_priv ) static inline void radeon_emit_tex2( drm_radeon_private_t *dev_priv ) { drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_radeon_context_regs_t *ctx = &sarea_priv->context_state; drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[2]; RING_LOCALS; DRM_DEBUG( " %s\n", __FUNCTION__ ); @@ -358,7 +354,7 @@ static inline void radeon_emit_tex2( drm_radeon_private_t *dev_priv ) OUT_RING( tex->pp_txoffset ); OUT_RING( tex->pp_txcblend ); OUT_RING( tex->pp_txablend ); - OUT_RING( ctx->pp_tfactor ); + OUT_RING( tex->pp_tfactor ); OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_2, 0 ) ); OUT_RING( tex->pp_border_color ); @@ -408,12 +404,12 @@ static inline void radeon_emit_state( drm_radeon_private_t *dev_priv ) sarea_priv->dirty &= ~RADEON_UPLOAD_SETUP; } -#ifdef TCL_ENABLE if ( dirty & RADEON_UPLOAD_TCL ) { +#ifdef TCL_ENABLE radeon_emit_tcl( dev_priv ); +#endif sarea_priv->dirty &= ~RADEON_UPLOAD_TCL; } -#endif if ( dirty & RADEON_UPLOAD_MISC ) { radeon_emit_misc( dev_priv ); @@ -437,11 +433,6 @@ static inline void radeon_emit_state( drm_radeon_private_t *dev_priv ) sarea_priv->dirty &= ~RADEON_UPLOAD_TEX2; } -#if 0 - /* Turn off the texture cache flushing */ - sarea_priv->context_state.tex_cntl_c &= ~RADEON_TEX_CACHE_FLUSH; -#endif - sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | RADEON_UPLOAD_TEX1IMAGES | RADEON_UPLOAD_TEX2IMAGES | @@ -576,16 +567,11 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev, unsigned int tmp = flags; flags &= ~(RADEON_FRONT | RADEON_BACK); - if ( tmp & RADEON_FRONT ) - flags |= RADEON_BACK; - if ( tmp & RADEON_BACK ) - flags |= RADEON_FRONT; + if ( tmp & RADEON_FRONT ) flags |= RADEON_BACK; + if ( tmp & RADEON_BACK ) flags |= RADEON_FRONT; } RADEON_WAIT_UNTIL_IDLE(); -#if 0 - RADEON_FLUSH_CACHE(); -#endif for ( i = 0 ; i < nbox ; i++ ) { int x = pbox[i].x1; @@ -817,21 +803,12 @@ static void radeon_cp_dispatch_swap( drm_device_t *dev ) RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS ); -#if 0 OUT_RING( dev_priv->back_pitch_offset ); OUT_RING( dev_priv->front_pitch_offset ); OUT_RING( (x << 16) | y ); OUT_RING( (x << 16) | y ); OUT_RING( (w << 16) | h ); -#else - OUT_RING( dev_priv->depth_pitch_offset ); - OUT_RING( dev_priv->front_pitch_offset ); - - OUT_RING( (0 << 16) | 0 ); - OUT_RING( (0 << 16) | 0 ); - OUT_RING( (832 << 16) | 600 ); -#endif ADVANCE_RING(); } @@ -1499,3 +1476,68 @@ int radeon_cp_stipple( struct inode *inode, struct file *filp, return -EINVAL; } + +int radeon_cp_indirect( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_device_dma_t *dma = dev->dma; + drm_buf_t *buf; + drm_radeon_buf_priv_t *buf_priv; + drm_radeon_indirect_t indirect; + RING_LOCALS; + + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || + dev->lock.pid != current->pid ) { + DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); + return -EINVAL; + } + if ( !dev_priv || dev_priv->is_pci ) { + DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ ); + return -EINVAL; + } + + if ( copy_from_user( &indirect, (drm_radeon_indirect_t *)arg, + sizeof(indirect) ) ) + return -EFAULT; + + DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n", + indirect.idx, indirect.start, + indirect.end, indirect.discard ); + + if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) { + DRM_ERROR( "buffer index %d (of %d max)\n", + indirect.idx, dma->buf_count - 1 ); + return -EINVAL; + } + + buf = dma->buflist[indirect.idx]; + buf_priv = buf->dev_private; + + if ( buf->pid != current->pid ) { + DRM_ERROR( "process %d using buffer owned by %d\n", + current->pid, buf->pid ); + return -EINVAL; + } + if ( buf->pending ) { + DRM_ERROR( "sending pending buffer %d\n", indirect.idx ); + return -EINVAL; + } + + if ( indirect.start < buf->used ) { + DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n", + indirect.start, buf->used ); + return -EINVAL; + } + + buf->used = indirect.end; + buf_priv->discard = indirect.discard; + + RADEON_WAIT_UNTIL_3D_IDLE(); + + radeon_cp_dispatch_indirect( dev, buf, indirect.start, indirect.end ); + + return 0; +} diff --git a/shared-core/drm.h b/shared-core/drm.h index b892682a..e8bccd86 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -370,14 +370,15 @@ typedef struct drm_agp_info { #define DRM_IOCTL_R128_CCE_RESET DRM_IO( 0x43) #define DRM_IOCTL_R128_CCE_IDLE DRM_IO( 0x44) #define DRM_IOCTL_R128_RESET DRM_IO( 0x46) -#define DRM_IOCTL_R128_SWAP DRM_IO( 0x47) -#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x48, drm_r128_clear_t) -#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x49, drm_r128_vertex_t) -#define DRM_IOCTL_R128_INDICES DRM_IOW( 0x4a, drm_r128_indices_t) -#define DRM_IOCTL_R128_BLIT DRM_IOW( 0x4b, drm_r128_blit_t) -#define DRM_IOCTL_R128_DEPTH DRM_IOW( 0x4c, drm_r128_depth_t) -#define DRM_IOCTL_R128_STIPPLE DRM_IOW( 0x4d, drm_r128_stipple_t) -#define DRM_IOCTL_R128_PACKET DRM_IOWR(0x4e, drm_r128_packet_t) +#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( 0x47, drm_r128_fullscreen_t) +#define DRM_IOCTL_R128_SWAP DRM_IO( 0x48) +#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x49, drm_r128_clear_t) +#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x4a, drm_r128_vertex_t) +#define DRM_IOCTL_R128_INDICES DRM_IOW( 0x4b, drm_r128_indices_t) +#define DRM_IOCTL_R128_BLIT DRM_IOW( 0x4c, drm_r128_blit_t) +#define DRM_IOCTL_R128_DEPTH DRM_IOW( 0x4d, drm_r128_depth_t) +#define DRM_IOCTL_R128_STIPPLE DRM_IOW( 0x4e, drm_r128_stipple_t) +#define DRM_IOCTL_R128_INDIRECT DRM_IOWR(0x4f, drm_r128_indirect_t) /* Radeon specific ioctls */ #define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( 0x40, drm_radeon_init_t) @@ -386,14 +387,14 @@ typedef struct drm_agp_info { #define DRM_IOCTL_RADEON_CP_RESET DRM_IO( 0x43) #define DRM_IOCTL_RADEON_CP_IDLE DRM_IO( 0x44) #define DRM_IOCTL_RADEON_RESET DRM_IO( 0x45) -#define DRM_IOCTL_RADEON_PAGEFLIP DRM_IOW( 0x46, drm_radeon_pageflip_t) +#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( 0x46, drm_radeon_fullscreen_t) #define DRM_IOCTL_RADEON_SWAP DRM_IO( 0x47) #define DRM_IOCTL_RADEON_CLEAR DRM_IOW( 0x48, drm_radeon_clear_t) #define DRM_IOCTL_RADEON_VERTEX DRM_IOW( 0x49, drm_radeon_vertex_t) #define DRM_IOCTL_RADEON_INDICES DRM_IOW( 0x4a, drm_radeon_indices_t) #define DRM_IOCTL_RADEON_BLIT DRM_IOW( 0x4b, drm_radeon_blit_t) -#define DRM_IOCTL_RADEON_STIPPLE DRM_IOWR(0x4c, drm_radeon_stipple_t) -#define DRM_IOCTL_RADEON_PACKET DRM_IOWR(0x4d, drm_radeon_packet_t) +#define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( 0x4c, drm_radeon_stipple_t) +#define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(0x4d, drm_radeon_indirect_t) /* SiS specific ioctls */ #define SIS_IOCTL_FB_ALLOC DRM_IOWR(0x44, drm_sis_mem_t) diff --git a/shared/drm.h b/shared/drm.h index b892682a..e8bccd86 100644 --- a/shared/drm.h +++ b/shared/drm.h @@ -370,14 +370,15 @@ typedef struct drm_agp_info { #define DRM_IOCTL_R128_CCE_RESET DRM_IO( 0x43) #define DRM_IOCTL_R128_CCE_IDLE DRM_IO( 0x44) #define DRM_IOCTL_R128_RESET DRM_IO( 0x46) -#define DRM_IOCTL_R128_SWAP DRM_IO( 0x47) -#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x48, drm_r128_clear_t) -#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x49, drm_r128_vertex_t) -#define DRM_IOCTL_R128_INDICES DRM_IOW( 0x4a, drm_r128_indices_t) -#define DRM_IOCTL_R128_BLIT DRM_IOW( 0x4b, drm_r128_blit_t) -#define DRM_IOCTL_R128_DEPTH DRM_IOW( 0x4c, drm_r128_depth_t) -#define DRM_IOCTL_R128_STIPPLE DRM_IOW( 0x4d, drm_r128_stipple_t) -#define DRM_IOCTL_R128_PACKET DRM_IOWR(0x4e, drm_r128_packet_t) +#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( 0x47, drm_r128_fullscreen_t) +#define DRM_IOCTL_R128_SWAP DRM_IO( 0x48) +#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x49, drm_r128_clear_t) +#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x4a, drm_r128_vertex_t) +#define DRM_IOCTL_R128_INDICES DRM_IOW( 0x4b, drm_r128_indices_t) +#define DRM_IOCTL_R128_BLIT DRM_IOW( 0x4c, drm_r128_blit_t) +#define DRM_IOCTL_R128_DEPTH DRM_IOW( 0x4d, drm_r128_depth_t) +#define DRM_IOCTL_R128_STIPPLE DRM_IOW( 0x4e, drm_r128_stipple_t) +#define DRM_IOCTL_R128_INDIRECT DRM_IOWR(0x4f, drm_r128_indirect_t) /* Radeon specific ioctls */ #define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( 0x40, drm_radeon_init_t) @@ -386,14 +387,14 @@ typedef struct drm_agp_info { #define DRM_IOCTL_RADEON_CP_RESET DRM_IO( 0x43) #define DRM_IOCTL_RADEON_CP_IDLE DRM_IO( 0x44) #define DRM_IOCTL_RADEON_RESET DRM_IO( 0x45) -#define DRM_IOCTL_RADEON_PAGEFLIP DRM_IOW( 0x46, drm_radeon_pageflip_t) +#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( 0x46, drm_radeon_fullscreen_t) #define DRM_IOCTL_RADEON_SWAP DRM_IO( 0x47) #define DRM_IOCTL_RADEON_CLEAR DRM_IOW( 0x48, drm_radeon_clear_t) #define DRM_IOCTL_RADEON_VERTEX DRM_IOW( 0x49, drm_radeon_vertex_t) #define DRM_IOCTL_RADEON_INDICES DRM_IOW( 0x4a, drm_radeon_indices_t) #define DRM_IOCTL_RADEON_BLIT DRM_IOW( 0x4b, drm_radeon_blit_t) -#define DRM_IOCTL_RADEON_STIPPLE DRM_IOWR(0x4c, drm_radeon_stipple_t) -#define DRM_IOCTL_RADEON_PACKET DRM_IOWR(0x4d, drm_radeon_packet_t) +#define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( 0x4c, drm_radeon_stipple_t) +#define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(0x4d, drm_radeon_indirect_t) /* SiS specific ioctls */ #define SIS_IOCTL_FB_ALLOC DRM_IOWR(0x44, drm_sis_mem_t) |