summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shared-core/via_3d_reg.h4
-rw-r--r--shared-core/via_dma.c74
-rw-r--r--shared-core/via_drm.h7
-rw-r--r--shared-core/via_drv.h12
-rw-r--r--shared-core/via_irq.c25
-rw-r--r--shared-core/via_map.c1
-rw-r--r--shared-core/via_mm.c1
-rw-r--r--shared/via.h8
-rw-r--r--shared/via_3d_reg.h4
-rw-r--r--shared/via_dma.c74
-rw-r--r--shared/via_drm.h7
-rw-r--r--shared/via_drv.h6
-rw-r--r--shared/via_irq.c25
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);
}
}
+