📄 r128_cce.c
字号:
dev_priv->cce_fifo_size = 0; break; case R128_PM4_192PIO: case R128_PM4_192BM: dev_priv->cce_fifo_size = 192; break; case R128_PM4_128PIO_64INDBM: case R128_PM4_128BM_64INDBM: dev_priv->cce_fifo_size = 128; break; case R128_PM4_64PIO_128INDBM: case R128_PM4_64BM_128INDBM: case R128_PM4_64PIO_64VCBM_64INDBM: case R128_PM4_64BM_64VCBM_64INDBM: case R128_PM4_64PIO_64VCPIO_64INDPIO: dev_priv->cce_fifo_size = 64; break; } dev_priv->fb_bpp = init->fb_bpp; dev_priv->front_offset = init->front_offset; dev_priv->front_pitch = init->front_pitch; dev_priv->back_offset = init->back_offset; dev_priv->back_pitch = init->back_pitch; dev_priv->depth_bpp = init->depth_bpp; dev_priv->depth_offset = init->depth_offset; dev_priv->depth_pitch = init->depth_pitch; dev_priv->span_offset = init->span_offset; dev_priv->front_pitch_offset_c = (((dev_priv->front_pitch/8) << 21) | (dev_priv->front_offset >> 5)); dev_priv->back_pitch_offset_c = (((dev_priv->back_pitch/8) << 21) | (dev_priv->back_offset >> 5)); dev_priv->depth_pitch_offset_c = (((dev_priv->depth_pitch/8) << 21) | (dev_priv->depth_offset >> 5) | R128_DST_TILE); dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch/8) << 21) | (dev_priv->span_offset >> 5)); /* FIXME: We want multiple shared areas, including one shared * only by the X Server and kernel module. */ for ( i = 0 ; i < dev->map_count ; i++ ) { if ( dev->maplist[i]->type == _DRM_SHM ) { dev_priv->sarea = dev->maplist[i]; break; } } DO_FIND_MAP( dev_priv->fb, init->fb_offset ); DO_FIND_MAP( dev_priv->mmio, init->mmio_offset ); DO_FIND_MAP( dev_priv->cce_ring, init->ring_offset ); DO_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset ); DO_FIND_MAP( dev_priv->buffers, init->buffers_offset ); if ( !dev_priv->is_pci ) { DO_FIND_MAP( dev_priv->agp_textures, init->agp_textures_offset ); } dev_priv->sarea_priv = (drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle + init->sarea_priv_offset); DO_REMAP( dev_priv->cce_ring ); DO_REMAP( dev_priv->ring_rptr ); DO_REMAP( dev_priv->buffers );#if 0 if ( !dev_priv->is_pci ) { DO_REMAP( dev_priv->agp_textures ); }#endif dev_priv->ring.head = ((__volatile__ u32 *) dev_priv->ring_rptr->handle); dev_priv->ring.start = (u32 *)dev_priv->cce_ring->handle; dev_priv->ring.end = ((u32 *)dev_priv->cce_ring->handle + init->ring_size / sizeof(u32)); dev_priv->ring.size = init->ring_size; dev_priv->ring.size_l2qw = drm_order( init->ring_size / 8 ); dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1; dev_priv->sarea_priv->last_frame = 0; R128_WRITE( R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame ); dev_priv->sarea_priv->last_dispatch = 0; R128_WRITE( R128_LAST_DISPATCH_REG, dev_priv->sarea_priv->last_dispatch ); r128_cce_init_ring_buffer( dev ); r128_cce_load_microcode( dev_priv ); r128_do_engine_reset( dev ); return 0;}static int r128_do_cleanup_cce( drm_device_t *dev ){ if ( dev->dev_private ) { drm_r128_private_t *dev_priv = dev->dev_private; DO_REMAPFREE( dev_priv->cce_ring ); DO_REMAPFREE( dev_priv->ring_rptr ); DO_REMAPFREE( dev_priv->buffers );#if 0 if ( !dev_priv->is_pci ) { DO_REMAPFREE( dev_priv->agp_textures ); }#endif drm_free( dev->dev_private, sizeof(drm_r128_private_t), DRM_MEM_DRIVER ); dev->dev_private = NULL; } return 0;}int r128_cce_init( 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_init_t init; if ( copy_from_user( &init, (drm_r128_init_t *)arg, sizeof(init) ) ) return -EFAULT; switch ( init.func ) { case R128_INIT_CCE: return r128_do_init_cce( dev, &init ); case R128_CLEANUP_CCE: return r128_do_cleanup_cce( dev ); } return -EINVAL;}int r128_cce_start( 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_DEBUG( "%s\n", __FUNCTION__ ); 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->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4 ) { DRM_DEBUG( "%s while CCE running\n", __FUNCTION__ ); return 0; } r128_do_cce_start( dev_priv ); return 0;}/* Stop the CCE. The engine must have been idled before calling this * routine. */int r128_cce_stop( 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_cce_stop_t stop; int ret; DRM_DEBUG( "%s\n", __FUNCTION__ ); 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( &stop, (drm_r128_init_t *)arg, sizeof(stop) ) ) return -EFAULT; /* Flush any pending CCE commands. This ensures any outstanding * commands are exectuted by the engine before we turn it off. */ if ( stop.flush ) { r128_do_cce_flush( dev_priv ); } /* If we fail to make the engine go idle, we return an error * code so that the DRM ioctl wrapper can try again. */ if ( stop.idle ) { ret = r128_do_cce_idle( dev_priv ); if ( ret < 0 ) return ret; } /* Finally, we can turn off the CCE. If the engine isn't idle, * we will get some dropped triangles as they won't be fully * rendered before the CCE is shut down. */ r128_do_cce_stop( dev_priv ); /* Reset the engine */ r128_do_engine_reset( dev ); return 0;}/* Just reset the CCE ring. Called as part of an X Server engine reset. */int r128_cce_reset( 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_DEBUG( "%s\n", __FUNCTION__ ); 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 ) { DRM_DEBUG( "%s called before init done\n", __FUNCTION__ ); return -EINVAL; } r128_do_cce_reset( dev_priv ); /* The CCE is no longer running after an engine reset */ dev_priv->cce_running = 0; return 0;}int r128_cce_idle( 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_DEBUG( "%s\n", __FUNCTION__ ); 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->cce_running ) { r128_do_cce_flush( dev_priv ); } return r128_do_cce_idle( dev_priv );}int r128_engine_reset( 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_DEBUG( "%s\n", __FUNCTION__ ); 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; } return r128_do_engine_reset( dev );}/* ================================================================ * Freelist management */#define R128_BUFFER_USED 0xffffffff#define R128_BUFFER_FREE 0#if 0static int r128_freelist_init( drm_device_t *dev ){ drm_device_dma_t *dma = dev->dma; drm_r128_private_t *dev_priv = dev->dev_private; drm_buf_t *buf; drm_r128_buf_priv_t *buf_priv; drm_r128_freelist_t *entry; int i; dev_priv->head = drm_alloc( sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER ); if ( dev_priv->head == NULL ) return -ENOMEM; memset( dev_priv->head, 0, sizeof(drm_r128_freelist_t) ); dev_priv->head->age = R128_BUFFER_USED; for ( i = 0 ; i < dma->buf_count ; i++ ) { buf = dma->buflist[i]; buf_priv = buf->dev_private; entry = drm_alloc( sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER ); if ( !entry ) return -ENOMEM; entry->age = R128_BUFFER_FREE; entry->buf = buf; entry->prev = dev_priv->head; entry->next = dev_priv->head->next; if ( !entry->next ) dev_priv->tail = entry; buf_priv->discard = 0; buf_priv->dispatched = 0; buf_priv->list_entry = entry; dev_priv->head->next = entry; if ( dev_priv->head->next ) dev_priv->head->next->prev = entry; } return 0;}#endifdrm_buf_t *r128_freelist_get( drm_device_t *dev ){ 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, t; /* FIXME: Optimize -- use freelist code */ for ( i = 0 ; i < dma->buf_count ; i++ ) { buf = dma->buflist[i]; buf_priv = buf->dev_private; if ( buf->pid == 0 ) return buf; } for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) { u32 done_age = R128_READ( R128_LAST_DISPATCH_REG ); for ( i = 0 ; i < dma->buf_count ; i++ ) { buf = dma->buflist[i]; buf_priv = buf->dev_private; if ( buf->pending && buf_priv->age <= done_age ) { /* The buffer has been processed, so it * can now be used. */ buf->pending = 0; return buf; } } udelay( 1 ); } DRM_ERROR( "returning NULL!\n" ); return NULL;}void r128_freelist_reset( drm_device_t *dev ){ drm_device_dma_t *dma = dev->dma; int i; for ( i = 0 ; i < dma->buf_count ; i++ ) { drm_buf_t *buf = dma->buflist[i]; drm_r128_buf_priv_t *buf_priv = buf->dev_private; buf_priv->age = 0; }}/* ================================================================ * CCE packet submission */int r128_wait_ring( drm_r128_private_t *dev_priv, int n ){ drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i; for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { ring->space = *ring->head - ring->tail; if ( ring->space <= 0 ) ring->space += ring->size; if ( ring->space >= n ) return 0; udelay( 1 ); } return -EBUSY;}void r128_update_ring_snapshot( drm_r128_private_t *dev_priv ){ drm_r128_ring_buffer_t *ring = &dev_priv->ring; ring->space = *ring->head - ring->tail;#if R128_PERFORMANCE_BOXES if ( ring->space == 0 ) atomic_inc( &dev_priv->idle_count );#endif if ( ring->space <= 0 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -