summaryrefslogtreecommitdiff
path: root/shared-core
diff options
context:
space:
mode:
Diffstat (limited to 'shared-core')
-rw-r--r--shared-core/via_dma.c17
-rw-r--r--shared-core/via_drm.h34
-rw-r--r--shared-core/via_drv.h34
-rw-r--r--shared-core/via_irq.c55
-rw-r--r--shared-core/via_map.c4
5 files changed, 128 insertions, 16 deletions
diff --git a/shared-core/via_dma.c b/shared-core/via_dma.c
index ff9fca4b..327d48f7 100644
--- a/shared-core/via_dma.c
+++ b/shared-core/via_dma.c
@@ -740,6 +740,19 @@ via_cmdbuf_size(DRM_IOCTL_ARGS)
return ret;
}
+#ifndef VIA_HAVE_DMABLIT
+int
+via_dma_blit_sync( DRM_IOCTL_ARGS ) {
+ DRM_ERROR("PCI DMA BitBlt is not implemented for this system.\n");
+ return DRM_ERR(EINVAL);
+}
+int
+via_dma_blit( DRM_IOCTL_ARGS ) {
+ DRM_ERROR("PCI DMA BitBlt is not implemented for this system.\n");
+ return DRM_ERR(EINVAL);
+}
+#endif
+
drm_ioctl_desc_t via_ioctls[] = {
[DRM_IOCTL_NR(DRM_VIA_ALLOCMEM)] = {via_mem_alloc, DRM_AUTH},
[DRM_IOCTL_NR(DRM_VIA_FREEMEM)] = {via_mem_free, DRM_AUTH},
@@ -752,7 +765,9 @@ drm_ioctl_desc_t via_ioctls[] = {
[DRM_IOCTL_NR(DRM_VIA_FLUSH)] = {via_flush_ioctl, DRM_AUTH},
[DRM_IOCTL_NR(DRM_VIA_PCICMD)] = {via_pci_cmdbuffer, DRM_AUTH},
[DRM_IOCTL_NR(DRM_VIA_CMDBUF_SIZE)] = {via_cmdbuf_size, DRM_AUTH},
- [DRM_IOCTL_NR(DRM_VIA_WAIT_IRQ)] = {via_wait_irq, DRM_AUTH}
+ [DRM_IOCTL_NR(DRM_VIA_WAIT_IRQ)] = {via_wait_irq, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_DMA_BLIT)] = {via_dma_blit, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_BLIT_SYNC)] = {via_dma_blit_sync, DRM_AUTH}
};
int via_max_ioctl = DRM_ARRAY_SIZE(via_ioctls);
diff --git a/shared-core/via_drm.h b/shared-core/via_drm.h
index cc129a36..292106ab 100644
--- a/shared-core/via_drm.h
+++ b/shared-core/via_drm.h
@@ -75,6 +75,8 @@
#define DRM_VIA_CMDBUF_SIZE 0x0b
#define NOT_USED
#define DRM_VIA_WAIT_IRQ 0x0d
+#define DRM_VIA_DMA_BLIT 0x0e
+#define DRM_VIA_BLIT_SYNC 0x0f
#define DRM_IOCTL_VIA_ALLOCMEM DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_ALLOCMEM, drm_via_mem_t)
#define DRM_IOCTL_VIA_FREEMEM DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_FREEMEM, drm_via_mem_t)
@@ -89,6 +91,8 @@
#define DRM_IOCTL_VIA_CMDBUF_SIZE DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_CMDBUF_SIZE, \
drm_via_cmdbuf_size_t)
#define DRM_IOCTL_VIA_WAIT_IRQ DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_WAIT_IRQ, drm_via_irqwait_t)
+#define DRM_IOCTL_VIA_DMA_BLIT DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_DMA_BLIT, drm_via_dmablit_t)
+#define DRM_IOCTL_VIA_BLIT_SYNC DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_BLIT_SYNC, drm_via_blitsync_t)
/* Indices into buf.Setup where various bits of state are mirrored per
* context and per buffer. These can be fired at the card as a unit,
@@ -212,6 +216,14 @@ typedef enum {
#define VIA_IRQ_FLAGS_MASK 0xF0000000
+enum drm_via_irqs{drm_via_irq_hqv0 = 0,
+ drm_via_irq_hqv1,
+ drm_via_irq_dma0_dd,
+ drm_via_irq_dma0_td,
+ drm_via_irq_dma1_dd,
+ drm_via_irq_dma1_td,
+ drm_via_irq_num};
+
struct drm_via_wait_irq_request{
unsigned irq;
via_irq_seq_type_t type;
@@ -224,4 +236,26 @@ typedef union drm_via_irqwait {
struct drm_wait_vblank_reply reply;
} drm_via_irqwait_t;
+typedef struct drm_via_blitsync {
+ uint32_t sync_handle;
+ unsigned engine;
+} drm_via_blitsync_t;
+
+typedef struct drm_via_dmablit {
+ uint32_t num_lines;
+ uint32_t line_length;
+
+ uint32_t fb_addr;
+ uint32_t fb_stride;
+
+ unsigned char *mem_addr;
+ uint32_t mem_stride;
+
+ int bounce_buffer;
+ int to_fb;
+
+ drm_via_blitsync_t sync;
+} drm_via_dmablit_t;
+
+
#endif /* _VIA_DRM_H_ */
diff --git a/shared-core/via_drv.h b/shared-core/via_drv.h
index acbf17e1..9e4f303a 100644
--- a/shared-core/via_drv.h
+++ b/shared-core/via_drv.h
@@ -24,23 +24,31 @@
#ifndef _VIA_DRV_H_
#define _VIA_DRV_H_
-#define DRIVER_AUTHOR "VIA"
+#define DRIVER_AUTHOR "Various"
#define DRIVER_NAME "via"
#define DRIVER_DESC "VIA Unichrome / Pro"
-#define DRIVER_DATE "20050814"
+#define DRIVER_DATE "20050925"
#define DRIVER_MAJOR 2
-#define DRIVER_MINOR 6
-#define DRIVER_PATCHLEVEL 7
+#define DRIVER_MINOR 7
+#define DRIVER_PATCHLEVEL 0
#include "via_verifier.h"
-#define VIA_PCI_BUF_SIZE 60000
-#define VIA_FIRE_BUF_SIZE 1024
-#define VIA_NUM_IRQS 2
+#if defined(__linux__)
+#include "via_dmablit.h"
+/*
+ * This define and all its references can be removed when
+ * the DMA blit code has been implemented for FreeBSD.
+ */
+#define VIA_HAVE_DMABLIT 1
+#endif
+#define VIA_PCI_BUF_SIZE 60000
+#define VIA_FIRE_BUF_SIZE 1024
+#define VIA_NUM_IRQS 4
typedef struct drm_via_ring_buffer {
drm_local_map_t map;
@@ -84,6 +92,10 @@ typedef struct drm_via_private {
maskarray_t *irq_masks;
uint32_t irq_enable_mask;
uint32_t irq_pending_mask;
+ int *irq_map;
+#ifdef VIA_HAVE_DMABLIT
+ drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
+#endif
} drm_via_private_t;
enum via_family {
@@ -111,6 +123,8 @@ extern int via_flush_ioctl(DRM_IOCTL_ARGS);
extern int via_pci_cmdbuffer(DRM_IOCTL_ARGS);
extern int via_cmdbuf_size(DRM_IOCTL_ARGS);
extern int via_wait_irq(DRM_IOCTL_ARGS);
+extern int via_dma_blit_sync( DRM_IOCTL_ARGS );
+extern int via_dma_blit( DRM_IOCTL_ARGS );
extern int via_driver_load(drm_device_t *dev, unsigned long chipset);
extern int via_driver_unload(drm_device_t *dev);
@@ -131,5 +145,11 @@ extern int via_driver_dma_quiescent(drm_device_t * dev);
extern void via_init_futex(drm_via_private_t *dev_priv);
extern void via_cleanup_futex(drm_via_private_t *dev_priv);
extern void via_release_futex(drm_via_private_t *dev_priv, int context);
+extern int via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
+ unsigned int *sequence);
+#ifdef VIA_HAVE_DMABLIT
+extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq);
+extern void via_init_dmablit(drm_device_t *dev);
+#endif
#endif
diff --git a/shared-core/via_irq.c b/shared-core/via_irq.c
index f87b2f2c..96be8e3d 100644
--- a/shared-core/via_irq.c
+++ b/shared-core/via_irq.c
@@ -50,6 +50,15 @@
#define VIA_IRQ_HQV1_ENABLE (1 << 25)
#define VIA_IRQ_HQV0_PENDING (1 << 9)
#define VIA_IRQ_HQV1_PENDING (1 << 10)
+#define VIA_IRQ_DMA0_DD_ENABLE (1 << 20)
+#define VIA_IRQ_DMA0_TD_ENABLE (1 << 21)
+#define VIA_IRQ_DMA1_DD_ENABLE (1 << 22)
+#define VIA_IRQ_DMA1_TD_ENABLE (1 << 23)
+#define VIA_IRQ_DMA0_DD_PENDING (1 << 4)
+#define VIA_IRQ_DMA0_TD_PENDING (1 << 5)
+#define VIA_IRQ_DMA1_DD_PENDING (1 << 6)
+#define VIA_IRQ_DMA1_TD_PENDING (1 << 7)
+
/*
* Device-specific IRQs go here. This type might need to be extended with
@@ -57,13 +66,26 @@
* Currently we activate the HQV interrupts of Unichrome Pro group A.
*/
+
static maskarray_t via_pro_group_a_irqs[] = {
{VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010, 0x00000000 },
- {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010, 0x00000000 }};
+ {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010, 0x00000000 },
+ {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
+ VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
+ {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
+ VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}
+};
static int via_num_pro_group_a = sizeof(via_pro_group_a_irqs)/sizeof(maskarray_t);
-
-static maskarray_t via_unichrome_irqs[] = {};
+static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3};
+
+static maskarray_t via_unichrome_irqs[] = {
+ {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
+ VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
+ {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
+ VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}
+};
static int via_num_unichrome = sizeof(via_unichrome_irqs)/sizeof(maskarray_t);
+static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
static unsigned time_diff(struct timeval *now,struct timeval *then)
@@ -111,9 +133,17 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
for (i=0; i<dev_priv->num_irqs; ++i) {
if (status & cur_irq->pending_mask) {
+ DRM_DEBUG("Received IRQ %d\n", i);
atomic_inc( &cur_irq->irq_received );
DRM_WAKEUP( &cur_irq->irq_queue );
handled = 1;
+#ifdef VIA_HAVE_DMABLIT
+ if (dev_priv->irq_map[drm_via_irq_dma0_td] == i) {
+ via_dmablit_handler(dev, 0, 1);
+ } else if (dev_priv->irq_map[drm_via_irq_dma1_td] == i) {
+ via_dmablit_handler(dev, 1, 1);
+ }
+#endif
}
cur_irq++;
}
@@ -167,7 +197,7 @@ int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
return ret;
}
-static int
+int
via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
unsigned int *sequence)
{
@@ -176,6 +206,7 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
drm_via_irq_t *cur_irq = dev_priv->via_irqs;
int ret = 0;
maskarray_t *masks = dev_priv->irq_masks;
+ int real_irq;
DRM_DEBUG("%s\n", __FUNCTION__);
@@ -184,14 +215,22 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
return DRM_ERR(EINVAL);
}
- if (irq >= dev_priv->num_irqs ) {
+ if (irq >= drm_via_irq_num ) {
DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__, irq);
return DRM_ERR(EINVAL);
}
- cur_irq += irq;
+ real_irq = dev_priv->irq_map[irq];
+
+ if (real_irq < 0) {
+ DRM_ERROR("%s Video IRQ %d is not available on this hardware.\n", __FUNCTION__, irq);
+ return DRM_ERR(EINVAL);
+ }
+
+
+ cur_irq += real_irq;
- if (masks[irq][2] && !force_sequence) {
+ if (masks[real_irq][2] && !force_sequence) {
DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
((VIA_READ(masks[irq][2]) & masks[irq][3]) == masks[irq][4]));
cur_irq_sequence = atomic_read(&cur_irq->irq_received);
@@ -226,6 +265,8 @@ void via_driver_irq_preinstall(drm_device_t * dev)
via_pro_group_a_irqs : via_unichrome_irqs;
dev_priv->num_irqs = (dev_priv->pro_group_a) ?
via_num_pro_group_a : via_num_unichrome;
+ dev_priv->irq_map = (dev_priv->pro_group_a) ?
+ via_irqmap_pro_group_a : via_irqmap_unichrome;
for(i=0; i < dev_priv->num_irqs; ++i) {
atomic_set(&cur_irq->irq_received, 0);
diff --git a/shared-core/via_map.c b/shared-core/via_map.c
index 8e405418..2b653d75 100644
--- a/shared-core/via_map.c
+++ b/shared-core/via_map.c
@@ -61,7 +61,9 @@ static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init)
dev_priv->agpAddr = init->agpAddr;
via_init_futex( dev_priv );
-
+#ifdef VIA_HAVE_DMABLIT
+ via_init_dmablit( dev );
+#endif
dev->dev_private = (void *)dev_priv;
return 0;
}