From 903e5701ffbc613373f3ad3c3b7e14d493ec9dbe Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Sun, 25 Sep 2005 12:54:12 +0000 Subject: Add the via PCI DMA blit code. --- shared-core/via_dma.c | 17 +++++++++++++++- shared-core/via_drm.h | 34 +++++++++++++++++++++++++++++++ shared-core/via_drv.h | 34 ++++++++++++++++++++++++------- shared-core/via_irq.c | 55 ++++++++++++++++++++++++++++++++++++++++++++------- shared-core/via_map.c | 4 +++- 5 files changed, 128 insertions(+), 16 deletions(-) (limited to 'shared-core') 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; inum_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; } -- cgit v1.2.3