diff options
-rw-r--r-- | shared-core/via_3d_reg.h | 4 | ||||
-rw-r--r-- | shared-core/via_dma.c | 74 | ||||
-rw-r--r-- | shared-core/via_drm.h | 7 | ||||
-rw-r--r-- | shared-core/via_drv.h | 12 | ||||
-rw-r--r-- | shared-core/via_irq.c | 25 | ||||
-rw-r--r-- | shared-core/via_map.c | 1 | ||||
-rw-r--r-- | shared-core/via_mm.c | 1 | ||||
-rw-r--r-- | shared/via.h | 8 | ||||
-rw-r--r-- | shared/via_3d_reg.h | 4 | ||||
-rw-r--r-- | shared/via_dma.c | 74 | ||||
-rw-r--r-- | shared/via_drm.h | 7 | ||||
-rw-r--r-- | shared/via_drv.h | 6 | ||||
-rw-r--r-- | shared/via_irq.c | 25 |
13 files changed, 165 insertions, 83 deletions
diff --git a/shared-core/via_3d_reg.h b/shared-core/via_3d_reg.h index 3bb59a34..43c01836 100644 --- a/shared-core/via_3d_reg.h +++ b/shared-core/via_3d_reg.h @@ -26,6 +26,8 @@ #define VIA_3D_REG_H #define HC_REG_BASE 0x0400 +#define HC_REG_TRANS_SPACE 0x0040 + #define HC_ParaN_MASK 0xffffffff #define HC_Para_MASK 0x00ffffff #define HC_SubA_MASK 0xff000000 @@ -1621,7 +1623,7 @@ #define HALCYON_CMDB 0XEC000000 #define HALCYON_CMDBMASK 0XFFFE0000 #define HALCYON_SUB_ADDR0 0X00000000 -#define HALCYON_HEADER1MASK 0XFFFFFF00 +#define HALCYON_HEADER1MASK 0XFFFFFC00 #define HALCYON_HEADER1 0XF0000000 #define HC_SubA_HAGPBstL 0x0060 #define HC_SubA_HAGPBendL 0x0061 diff --git a/shared-core/via_dma.c b/shared-core/via_dma.c index ee4a02ab..179636ea 100644 --- a/shared-core/via_dma.c +++ b/shared-core/via_dma.c @@ -26,7 +26,11 @@ *vb++ = (w2); \ dev_priv->dma_low += 8; - +#define PCI_BUF_SIZE 1024000 + +static char pci_buf[PCI_BUF_SIZE]; +static unsigned long pci_bufsiz = PCI_BUF_SIZE; + static void via_cmdbuf_start(drm_via_private_t * dev_priv); static void via_cmdbuf_pause(drm_via_private_t * dev_priv); @@ -203,6 +207,9 @@ int via_dma_init(DRM_IOCTL_ARGS) case VIA_CLEANUP_DMA: retcode = via_dma_cleanup(dev); break; + case VIA_DMA_INITIALIZED: + retcode = (dev_priv->ring.virtual_start != NULL) ? 0: DRM_ERR( EFAULT ); + break; default: retcode = DRM_ERR(EINVAL); break; @@ -278,52 +285,55 @@ static int via_parse_pci_cmdbuffer(drm_device_t * dev, const char *buf, unsigned int size) { drm_via_private_t *dev_priv = dev->dev_private; - uint32_t offset, value; const uint32_t *regbuf = (uint32_t *) buf; - unsigned int i; + const uint32_t *regend = regbuf + (size >> 2); int ret; + int check_2d_cmd = 1; if ((ret = via_check_command_stream(regbuf, size))) return ret; - size >>= 3; - for (i = 0; i < size; ++i) { - offset = (*regbuf++ & ~HALCYON_HEADER1) << 2; - value = *regbuf++; - VIA_WRITE(offset, value); - } + while (regbuf != regend) { + if ( *regbuf == HALCYON_HEADER2 ) { + + regbuf++; + check_2d_cmd = ( *regbuf != HALCYON_SUB_ADDR0 ); + VIA_WRITE(HC_REG_TRANS_SET + HC_REG_BASE, *regbuf++); + + } else if ( check_2d_cmd && ((*regbuf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 )) { + + register uint32_t addr = ( (*regbuf++ ) & ~HALCYON_HEADER1MASK) << 2; + VIA_WRITE( addr, *regbuf++ ); + + } else if ( ( *regbuf & HALCYON_FIREMASK ) == HALCYON_FIRECMD ) { + + VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE, *regbuf++); + if ( ( regbuf != regend ) && + ((*regbuf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) + regbuf++; + if (( *regbuf & HALCYON_CMDBMASK ) != HC_ACMD_HCmdB ) + check_2d_cmd = 1; + } else { + + VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE , *regbuf++); + + } + } return 0; + } static int via_dispatch_pci_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd) { - drm_via_private_t *dev_priv = dev->dev_private; - char *hugebuf; int ret; - /* - * We must be able to parse the buffer all at a time, so as - * to return an error on an invalid operation without doing - * anything. - * Small buffers must, on the other hand be handled fast. - */ - - if (cmd->size > VIA_MAX_PCI_SIZE) { + if (cmd->size > pci_bufsiz && pci_bufsiz > 0) { return DRM_ERR(ENOMEM); - } else if (cmd->size > VIA_PREALLOCATED_PCI_SIZE) { - if (NULL == (hugebuf = (char *)kmalloc(cmd->size, GFP_KERNEL))) - return DRM_ERR(ENOMEM); - if (DRM_COPY_FROM_USER(hugebuf, cmd->buf, cmd->size)) - return DRM_ERR(EFAULT); - ret = via_parse_pci_cmdbuffer(dev, hugebuf, cmd->size); - kfree(hugebuf); - } else { - if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size)) - return DRM_ERR(EFAULT); - ret = - via_parse_pci_cmdbuffer(dev, dev_priv->pci_buf, cmd->size); - } + } + if (DRM_COPY_FROM_USER(pci_buf, cmd->buf, cmd->size)) + return DRM_ERR(EFAULT); + ret = via_parse_pci_cmdbuffer(dev, pci_buf, cmd->size); return ret; } diff --git a/shared-core/via_drm.h b/shared-core/via_drm.h index 75c72806..142b8dac 100644 --- a/shared-core/via_drm.h +++ b/shared-core/via_drm.h @@ -38,8 +38,6 @@ #define VIA_NR_XVMC_PORTS 10 #define VIA_NR_XVMC_LOCKS 5 #define VIA_MAX_CACHELINE_SIZE 64 -#define VIA_PREALLOCATED_PCI_SIZE 16384 -#define VIA_MAX_PCI_SIZE 65536 #define XVMCLOCKPTR(saPriv,lockNo) \ ((volatile int *)(((((unsigned long) (saPriv)->XvMCLockArea) + \ (VIA_MAX_CACHELINE_SIZE - 1)) & \ @@ -143,7 +141,8 @@ typedef struct _drm_via_futex { typedef struct _drm_via_dma_init { enum { VIA_INIT_DMA = 0x01, - VIA_CLEANUP_DMA = 0x02 + VIA_CLEANUP_DMA = 0x02, + VIA_DMA_INITIALIZED = 0x03 } func; unsigned long offset; @@ -202,6 +201,8 @@ typedef struct _drm_via_flush_sys { int discard; /* client is finished with the buffer? */ } drm_via_flush_sys_t; + + #ifdef __KERNEL__ int via_fb_init(DRM_IOCTL_ARGS); diff --git a/shared-core/via_drv.h b/shared-core/via_drv.h index 14afaa13..3bca72f3 100644 --- a/shared-core/via_drv.h +++ b/shared-core/via_drv.h @@ -28,11 +28,11 @@ #define DRIVER_NAME "via" #define DRIVER_DESC "VIA Unichrome" -#define DRIVER_DATE "20041103" +#define DRIVER_DATE "20041127" #define DRIVER_MAJOR 2 -#define DRIVER_MINOR 0 -#define DRIVER_PATCHLEVEL 4 +#define DRIVER_MINOR 1 +#define DRIVER_PATCHLEVEL 0 typedef struct drm_via_ring_buffer { drm_map_t map; @@ -53,7 +53,9 @@ typedef struct drm_via_private { volatile uint32_t *last_pause_ptr; volatile uint32_t *hw_addr_ptr; drm_via_ring_buffer_t ring; - char pci_buf[VIA_PREALLOCATED_PCI_SIZE]; + struct timeval last_vblank; + int last_vblank_valid; + unsigned usec_per_vblank; } drm_via_private_t; /* VIA MMIO register access */ @@ -80,6 +82,6 @@ extern void via_driver_irq_uninstall(drm_device_t * dev); extern int via_dma_cleanup(drm_device_t * dev); -extern int via_dma_cleanup(drm_device_t * dev); + #endif diff --git a/shared-core/via_irq.c b/shared-core/via_irq.c index 3d54edc2..2d78dd44 100644 --- a/shared-core/via_irq.c +++ b/shared-core/via_irq.c @@ -45,16 +45,39 @@ #define VIA_IRQ_VBI_ENABLE (1 << 19) #define VIA_IRQ_VBI_PENDING (1 << 3) + + +static unsigned time_diff(struct timeval *now,struct timeval *then) +{ + return (now->tv_usec >= then->tv_usec) ? + now->tv_usec - then->tv_usec : + 1000000 - (then->tv_usec - now->tv_usec); +} + irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) { drm_device_t *dev = (drm_device_t *) arg; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; u32 status; int handled = 0; + struct timeval cur_vblank; status = VIA_READ(VIA_REG_INTERRUPT); if (status & VIA_IRQ_VBI_PENDING) { atomic_inc(&dev->vbl_received); + if (!(atomic_read(&dev->vbl_received) & 0x0F)) { + do_gettimeofday(&cur_vblank); + if (dev_priv->last_vblank_valid) { + dev_priv->usec_per_vblank = + time_diff( &cur_vblank,&dev_priv->last_vblank) >> 4; + } + dev_priv->last_vblank = cur_vblank; + dev_priv->last_vblank_valid = 1; + } + if (!(atomic_read(&dev->vbl_received) & 0xFF)) { + DRM_DEBUG("US per vblank is: %u\n", + dev_priv->usec_per_vblank); + } DRM_WAKEUP(&dev->vbl_queue); drm_vbl_send_signals(dev); handled = 1; @@ -116,6 +139,7 @@ void via_driver_irq_preinstall(drm_device_t * dev) DRM_DEBUG("driver_irq_preinstall: dev_priv: %p\n", dev_priv); if (dev_priv) { + dev_priv->last_vblank_valid = 0; DRM_DEBUG("mmio: %p\n", dev_priv->mmio); status = VIA_READ(VIA_REG_INTERRUPT); DRM_DEBUG("intreg: %x\n", status & VIA_IRQ_VBI_ENABLE); @@ -163,3 +187,4 @@ void via_driver_irq_uninstall(drm_device_t * dev) VIA_WRITE(VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBI_ENABLE); } } + diff --git a/shared-core/via_map.c b/shared-core/via_map.c index dcf714db..e00dc64a 100644 --- a/shared-core/via_map.c +++ b/shared-core/via_map.c @@ -136,3 +136,4 @@ int via_decoder_futex(DRM_IOCTL_ARGS) } return 0; } + diff --git a/shared-core/via_mm.c b/shared-core/via_mm.c index 985ad0d9..5199f6c9 100644 --- a/shared-core/via_mm.c +++ b/shared-core/via_mm.c @@ -170,6 +170,7 @@ int via_final_context(struct drm_device *dev, int context) /* Linux specific until context tracking code gets ported to BSD */ /* Last context, perform cleanup */ if (dev->ctx_count == 1 && dev->dev_private) { + DRM_DEBUG("Last Context\n"); if (dev->irq) drm_irq_uninstall(dev); diff --git a/shared/via.h b/shared/via.h index 0746a46d..6b312210 100644 --- a/shared/via.h +++ b/shared/via.h @@ -30,11 +30,11 @@ #define DRIVER_NAME "via" #define DRIVER_DESC "VIA Unichrome" -#define DRIVER_DATE "20041103" +#define DRIVER_DATE "20041127" #define DRIVER_MAJOR 2 -#define DRIVER_MINOR 0 -#define DRIVER_PATCHLEVEL 4 +#define DRIVER_MINOR 1 +#define DRIVER_PATCHLEVEL 0 #define DRIVER_IOCTLS \ [DRM_IOCTL_NR(DRM_IOCTL_VIA_ALLOCMEM)] = { via_mem_alloc, 1, 0 }, \ @@ -46,6 +46,6 @@ [DRM_IOCTL_NR(DRM_IOCTL_VIA_DMA_INIT)] = { via_dma_init, 1, 0}, \ [DRM_IOCTL_NR(DRM_IOCTL_VIA_CMDBUFFER)] = { via_cmdbuffer, 1, 0}, \ [DRM_IOCTL_NR(DRM_IOCTL_VIA_FLUSH)] = { via_flush_ioctl, 1, 0}, \ - [DRM_IOCTL_NR(DRM_IOCTL_VIA_PCICMD)] = { via_pci_cmdbuffer, 1, 0} + [DRM_IOCTL_NR(DRM_IOCTL_VIA_PCICMD)] = { via_pci_cmdbuffer, 1, 0} #endif diff --git a/shared/via_3d_reg.h b/shared/via_3d_reg.h index 38ab25bc..90010cdc 100644 --- a/shared/via_3d_reg.h +++ b/shared/via_3d_reg.h @@ -26,6 +26,8 @@ #define VIA_3D_REG_H #define HC_REG_BASE 0x0400 +#define HC_REG_TRANS_SPACE 0x0040 + #define HC_ParaN_MASK 0xffffffff #define HC_Para_MASK 0x00ffffff #define HC_SubA_MASK 0xff000000 @@ -1621,7 +1623,7 @@ #define HALCYON_CMDB 0XEC000000 #define HALCYON_CMDBMASK 0XFFFE0000 #define HALCYON_SUB_ADDR0 0X00000000 -#define HALCYON_HEADER1MASK 0XFFFFFF00 +#define HALCYON_HEADER1MASK 0XFFFFFC00 #define HALCYON_HEADER1 0XF0000000 #define HC_SubA_HAGPBstL 0x0060 #define HC_SubA_HAGPBendL 0x0061 diff --git a/shared/via_dma.c b/shared/via_dma.c index 39613bc5..4b591fa4 100644 --- a/shared/via_dma.c +++ b/shared/via_dma.c @@ -27,7 +27,11 @@ *vb++ = (w2); \ dev_priv->dma_low += 8; - +#define PCI_BUF_SIZE 1024000 + +static char pci_buf[PCI_BUF_SIZE]; +static unsigned long pci_bufsiz = PCI_BUF_SIZE; + static void via_cmdbuf_start(drm_via_private_t * dev_priv); static void via_cmdbuf_pause(drm_via_private_t * dev_priv); @@ -204,6 +208,9 @@ int via_dma_init(DRM_IOCTL_ARGS) case VIA_CLEANUP_DMA: retcode = via_dma_cleanup(dev); break; + case VIA_DMA_INITIALIZED: + retcode = (dev_priv->ring.virtual_start != NULL) ? 0: DRM_ERR( EFAULT ); + break; default: retcode = DRM_ERR(EINVAL); break; @@ -279,52 +286,55 @@ static int via_parse_pci_cmdbuffer(drm_device_t * dev, const char *buf, unsigned int size) { drm_via_private_t *dev_priv = dev->dev_private; - uint32_t offset, value; const uint32_t *regbuf = (uint32_t *) buf; - unsigned int i; + const uint32_t *regend = regbuf + (size >> 2); int ret; + int check_2d_cmd = 1; if ((ret = via_check_command_stream(regbuf, size))) return ret; - size >>= 3; - for (i = 0; i < size; ++i) { - offset = (*regbuf++ & ~HALCYON_HEADER1) << 2; - value = *regbuf++; - VIA_WRITE(offset, value); - } + while (regbuf != regend) { + if ( *regbuf == HALCYON_HEADER2 ) { + + regbuf++; + check_2d_cmd = ( *regbuf != HALCYON_SUB_ADDR0 ); + VIA_WRITE(HC_REG_TRANS_SET + HC_REG_BASE, *regbuf++); + + } else if ( check_2d_cmd && ((*regbuf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 )) { + + register uint32_t addr = ( (*regbuf++ ) & ~HALCYON_HEADER1MASK) << 2; + VIA_WRITE( addr, *regbuf++ ); + + } else if ( ( *regbuf & HALCYON_FIREMASK ) == HALCYON_FIRECMD ) { + + VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE, *regbuf++); + if ( ( regbuf != regend ) && + ((*regbuf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) + regbuf++; + if (( *regbuf & HALCYON_CMDBMASK ) != HC_ACMD_HCmdB ) + check_2d_cmd = 1; + } else { + + VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE , *regbuf++); + + } + } return 0; + } static int via_dispatch_pci_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd) { - drm_via_private_t *dev_priv = dev->dev_private; - char *hugebuf; int ret; - /* - * We must be able to parse the buffer all at a time, so as - * to return an error on an invalid operation without doing - * anything. - * Small buffers must, on the other hand be handled fast. - */ - - if (cmd->size > VIA_MAX_PCI_SIZE) { + if (cmd->size > pci_bufsiz && pci_bufsiz > 0) { return DRM_ERR(ENOMEM); - } else if (cmd->size > VIA_PREALLOCATED_PCI_SIZE) { - if (NULL == (hugebuf = (char *)kmalloc(cmd->size, GFP_KERNEL))) - return DRM_ERR(ENOMEM); - if (DRM_COPY_FROM_USER(hugebuf, cmd->buf, cmd->size)) - return DRM_ERR(EFAULT); - ret = via_parse_pci_cmdbuffer(dev, hugebuf, cmd->size); - kfree(hugebuf); - } else { - if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size)) - return DRM_ERR(EFAULT); - ret = - via_parse_pci_cmdbuffer(dev, dev_priv->pci_buf, cmd->size); - } + } + if (DRM_COPY_FROM_USER(pci_buf, cmd->buf, cmd->size)) + return DRM_ERR(EFAULT); + ret = via_parse_pci_cmdbuffer(dev, pci_buf, cmd->size); return ret; } diff --git a/shared/via_drm.h b/shared/via_drm.h index ed2ee2ac..ee703c79 100644 --- a/shared/via_drm.h +++ b/shared/via_drm.h @@ -38,8 +38,6 @@ #define VIA_NR_XVMC_PORTS 10 #define VIA_NR_XVMC_LOCKS 5 #define VIA_MAX_CACHELINE_SIZE 64 -#define VIA_PREALLOCATED_PCI_SIZE 16384 -#define VIA_MAX_PCI_SIZE 65536 #define XVMCLOCKPTR(saPriv,lockNo) \ ((volatile int *)(((((unsigned long) (saPriv)->XvMCLockArea) + \ (VIA_MAX_CACHELINE_SIZE - 1)) & \ @@ -131,7 +129,8 @@ typedef struct _drm_via_futex { typedef struct _drm_via_dma_init { enum { VIA_INIT_DMA = 0x01, - VIA_CLEANUP_DMA = 0x02 + VIA_CLEANUP_DMA = 0x02, + VIA_DMA_INITIALIZED = 0x03 } func; unsigned long offset; @@ -190,6 +189,8 @@ typedef struct _drm_via_flush_sys { int discard; /* client is finished with the buffer? */ } drm_via_flush_sys_t; + + #ifdef __KERNEL__ int via_fb_init(DRM_IOCTL_ARGS); diff --git a/shared/via_drv.h b/shared/via_drv.h index 91edbab8..9ed8cd3a 100644 --- a/shared/via_drv.h +++ b/shared/via_drv.h @@ -45,7 +45,9 @@ typedef struct drm_via_private { volatile uint32_t *last_pause_ptr; volatile uint32_t *hw_addr_ptr; drm_via_ring_buffer_t ring; - char pci_buf[VIA_PREALLOCATED_PCI_SIZE]; + struct timeval last_vblank; + int last_vblank_valid; + unsigned usec_per_vblank; } drm_via_private_t; /* VIA MMIO register access */ @@ -72,6 +74,6 @@ extern void via_driver_irq_uninstall(drm_device_t * dev); extern int via_dma_cleanup(drm_device_t * dev); -extern int via_dma_cleanup(drm_device_t * dev); + #endif diff --git a/shared/via_irq.c b/shared/via_irq.c index da3c1414..a58717ee 100644 --- a/shared/via_irq.c +++ b/shared/via_irq.c @@ -46,16 +46,39 @@ #define VIA_IRQ_VBI_ENABLE (1 << 19) #define VIA_IRQ_VBI_PENDING (1 << 3) + + +static unsigned time_diff(struct timeval *now,struct timeval *then) +{ + return (now->tv_usec >= then->tv_usec) ? + now->tv_usec - then->tv_usec : + 1000000 - (then->tv_usec - now->tv_usec); +} + irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) { drm_device_t *dev = (drm_device_t *) arg; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; u32 status; int handled = 0; + struct timeval cur_vblank; status = VIA_READ(VIA_REG_INTERRUPT); if (status & VIA_IRQ_VBI_PENDING) { atomic_inc(&dev->vbl_received); + if (!(atomic_read(&dev->vbl_received) & 0x0F)) { + do_gettimeofday(&cur_vblank); + if (dev_priv->last_vblank_valid) { + dev_priv->usec_per_vblank = + time_diff( &cur_vblank,&dev_priv->last_vblank) >> 4; + } + dev_priv->last_vblank = cur_vblank; + dev_priv->last_vblank_valid = 1; + } + if (!(atomic_read(&dev->vbl_received) & 0xFF)) { + DRM_DEBUG("US per vblank is: %u\n", + dev_priv->usec_per_vblank); + } DRM_WAKEUP(&dev->vbl_queue); DRM(vbl_send_signals) (dev); handled = 1; @@ -117,6 +140,7 @@ void via_driver_irq_preinstall(drm_device_t * dev) DRM_DEBUG("driver_irq_preinstall: dev_priv: %p\n", dev_priv); if (dev_priv) { + dev_priv->last_vblank_valid = 0; DRM_DEBUG("mmio: %p\n", dev_priv->mmio); status = VIA_READ(VIA_REG_INTERRUPT); DRM_DEBUG("intreg: %x\n", status & VIA_IRQ_VBI_ENABLE); @@ -164,3 +188,4 @@ void via_driver_irq_uninstall(drm_device_t * dev) VIA_WRITE(VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBI_ENABLE); } } + |