summaryrefslogtreecommitdiff
path: root/shared
diff options
context:
space:
mode:
authorThomas Hellstrom <unichrome@shipmail.org>2004-11-27 22:55:31 +0000
committerThomas Hellstrom <unichrome@shipmail.org>2004-11-27 22:55:31 +0000
commit4f8fa6028631fa1d799e9a68ed710fbc98976656 (patch)
treedf753d0e728afd97ac03388283df51f4e73a9e0d /shared
parentf0a86288fa4d7b951f33f7b1a6ef36106c7df788 (diff)
Reworked PCI MMIO command buffer parser, and imported code from the Mesa
driver. It can now handle the 3D OpenGL commands from the Mesa unichrome driver. Added vsync frequency detection support. This will be used in the future for XvMC and better frame timing. Bumped minor version number and driver date.
Diffstat (limited to 'shared')
-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
6 files changed, 82 insertions, 42 deletions
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);
}
}
+