diff options
-rw-r--r-- | drivers/tdfx_vid.c | 171 | ||||
-rw-r--r-- | drivers/tdfx_vid.h | 18 |
2 files changed, 152 insertions, 37 deletions
diff --git a/drivers/tdfx_vid.c b/drivers/tdfx_vid.c index 80841a3b5a..541ff18cf1 100644 --- a/drivers/tdfx_vid.c +++ b/drivers/tdfx_vid.c @@ -44,7 +44,7 @@ static struct pci_dev *pci_dev; static uint8_t *tdfx_mmio_base = 0; static uint32_t tdfx_mem_base = 0; -static struct voodoo_2d_reg_t* tdfx_2d_regs = NULL; +static uint32_t tdfx_io_base = 0; static int tdfx_ram_size = 0; @@ -54,7 +54,10 @@ static drm_agp_t *drm_agp = NULL; static agp_kern_info agp_info; static agp_memory *agp_mem = NULL; +static __initdata int tdfx_map_io = 1; +MODULE_PARM(tdfx_map_io,"i"); +MODULE_PARM_DESC(tdfx_map_io, "Set to 0 to use the page fault handler (you need to patch agpgart_be.c to allow the mapping in user space)\n"); static inline u32 tdfx_inl(unsigned int reg) { return readl(tdfx_mmio_base + reg); @@ -140,12 +143,13 @@ static int tdfx_vid_find_card(void) #if LINUX_VERSION_CODE >= 0x020300 tdfx_mmio_base = ioremap_nocache(dev->resource[0].start,1 << 24); tdfx_mem_base = dev->resource[1].start; + tdfx_io_base = dev->resource[2].start; #else tdfx_mmio_base = ioremap_nocache(dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK,0x4000); tdfx_mem_base = dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK; + tdfx_io_base = dev->base_address[2] & PCI_BASE_ADDRESS_MEM_MASK; #endif printk(KERN_INFO "tdfx_vid: MMIO at 0x%p\n", tdfx_mmio_base); - tdfx_2d_regs = (struct voodoo_2d_reg_t*)tdfx_mmio_base; tdfx_ram_size = get_lfb_size(); printk(KERN_INFO "tdfx_vid: Found %d MB (%d bytes) of memory\n", @@ -224,7 +228,6 @@ static void agp_close(void) { } static int agp_move(tdfx_vid_agp_move_t* m) { - // u32 mov = 0; u32 src = 0; u32 src_h,src_l; @@ -255,15 +258,6 @@ static int agp_move(tdfx_vid_agp_move_t* m) { tdfx_outl(AGPMOVECMD,m->move2 << 3); banshee_wait_idle(); - banshee_make_room(5); - tdfx_outl(AGPHOSTADDRESSHIGH,0); - tdfx_outl(AGPHOSTADDRESSLOW,0); - - tdfx_outl(AGPGRAPHICSADDRESS,0); - tdfx_outl(AGPGRAPHICSSTRIDE,0); - tdfx_outl(AGPREQSIZE,0); - banshee_wait_idle(); - return 0; } @@ -358,6 +352,9 @@ inline static u32 tdfx_vid_make_format(int src,u16 stride,u32 fmt) { case TDFX_VID_FORMAT_BGR1: tdfx_fmt = 0; break; + case TDFX_VID_FORMAT_BGR15: // To check + tdfx_fmt = 2; + break; case TDFX_VID_FORMAT_YUY2: tdfx_fmt = 8; break; @@ -379,6 +376,7 @@ static int tdfx_vid_blit(tdfx_vid_blit_t* blit) { u32 src_fmt,dst_fmt; u32 cmin,cmax,srcbase,srcxy,srcfmt,srcsize; u32 dstbase,dstxy,dstfmt,dstsize; + u32 cmd_extra = 0,src_ck[2],dst_ck[2],rop123=0; //printk(KERN_INFO "tdfx_vid: Make src fmt 0x%x\n",blit->src_format); src_fmt = tdfx_vid_make_format(1,blit->src_stride,blit->src_format); @@ -388,9 +386,14 @@ static int tdfx_vid_blit(tdfx_vid_blit_t* blit) { dst_fmt = tdfx_vid_make_format(0,blit->dst_stride,blit->dst_format); if(!dst_fmt) return 0; - + blit->colorkey &= 0x3; + // Be nice if user just want a simple blit + if((!blit->colorkey) && (!blit->rop[0])) + blit->rop[0] = TDFX_VID_ROP_COPY; + // Save the regs otherwise fb get crazy // we can perhaps avoid some ... + banshee_wait_idle(); cmin = tdfx_inl(CLIP0MIN); cmax = tdfx_inl(CLIP0MAX); srcbase = tdfx_inl(SRCBASE); @@ -401,10 +404,26 @@ static int tdfx_vid_blit(tdfx_vid_blit_t* blit) { dstxy = tdfx_inl(DSTXY); dstfmt = tdfx_inl(DSTFORMAT); dstsize = tdfx_inl(DSTSIZE); - + if(blit->colorkey & TDFX_VID_SRC_COLORKEY) { + src_ck[0] = tdfx_inl(SRCCOLORKEYMIN); + src_ck[1] = tdfx_inl(SRCCOLORKEYMAX); + tdfx_outl(SRCCOLORKEYMIN,blit->src_colorkey[0]); + tdfx_outl(SRCCOLORKEYMAX,blit->src_colorkey[1]); + } + if(blit->colorkey & TDFX_VID_DST_COLORKEY) { + dst_ck[0] = tdfx_inl(DSTCOLORKEYMIN); + dst_ck[1] = tdfx_inl(DSTCOLORKEYMAX); + tdfx_outl(SRCCOLORKEYMIN,blit->dst_colorkey[0]); + tdfx_outl(SRCCOLORKEYMAX,blit->dst_colorkey[1]); + } + if(blit->colorkey) { + cmd_extra = tdfx_inl(COMMANDEXTRA_2D); + rop123 = tdfx_inl(ROP123); + tdfx_outl(COMMANDEXTRA_2D, blit->colorkey); + tdfx_outl(ROP123,(blit->rop[1] | (blit->rop[2] << 8) | blit->rop[3] << 16)); + + } // Get rid of the clipping at the moment - banshee_make_room(11); - tdfx_outl(CLIP0MIN,0); tdfx_outl(CLIP0MAX,0x0fff0fff); @@ -421,11 +440,10 @@ static int tdfx_vid_blit(tdfx_vid_blit_t* blit) { tdfx_outl(DSTSIZE,XYREG(blit->dst_w,blit->dst_h)); // Send the command - tdfx_outl(COMMAND_2D,0xcc000102); // | (ROP_COPY << 24)); + tdfx_outl(COMMAND_2D,0x102 | (blit->rop[0] << 24)); banshee_wait_idle(); // Now restore the regs to make fb happy - banshee_make_room(10); tdfx_outl(CLIP0MIN, cmin); tdfx_outl(CLIP0MAX, cmax); tdfx_outl(SRCBASE, srcbase); @@ -436,8 +454,18 @@ static int tdfx_vid_blit(tdfx_vid_blit_t* blit) { tdfx_outl(DSTXY, dstxy); tdfx_outl(DSTFORMAT, dstfmt); tdfx_outl(DSTSIZE, dstsize); - banshee_wait_idle(); - + if(blit->colorkey & TDFX_VID_SRC_COLORKEY) { + tdfx_outl(SRCCOLORKEYMIN,src_ck[0]); + tdfx_outl(SRCCOLORKEYMAX,src_ck[1]); + } + if(blit->colorkey & TDFX_VID_DST_COLORKEY) { + tdfx_outl(SRCCOLORKEYMIN,dst_ck[0]); + tdfx_outl(SRCCOLORKEYMAX,dst_ck[1]); + } + if(blit->colorkey) { + tdfx_outl(COMMANDEXTRA_2D,cmd_extra); + tdfx_outl(ROP123,rop123); + } return 1; } @@ -536,18 +564,87 @@ static ssize_t tdfx_vid_write(struct file *file, const char *buf, size_t count, return 0; } +static void tdfx_vid_mopen(struct vm_area_struct *vma) { + int i; + struct page *page; + unsigned long phys; + + printk(KERN_DEBUG "tdfx_vid: mopen\n"); + + for(i = 0 ; i < agp_mem->page_count ; i++) { + phys = agp_mem->memory[i] & ~(0x00000fff); + page = virt_to_page(phys_to_virt(phys)); + if(!page) { + printk(KERN_DEBUG "tdfx_vid: Can't get the page %d\%d\n",i,agp_mem->page_count); + return; + } + get_page(page); + } + MOD_INC_USE_COUNT; +} + +static void tdfx_vid_mclose(struct vm_area_struct *vma) { + int i; + struct page *page; + unsigned long phys; + + printk(KERN_DEBUG "tdfx_vid: mclose\n"); + + for(i = 0 ; i < agp_mem->page_count ; i++) { + phys = agp_mem->memory[i] & ~(0x00000fff); + page = virt_to_page(phys_to_virt(phys)); + if(!page) { + printk(KERN_DEBUG "tdfx_vid: Can't get the page %d\%d\n",i,agp_mem->page_count); + return; + } + put_page(page); + } + + MOD_DEC_USE_COUNT; +} + +static struct page *tdfx_vid_nopage(struct vm_area_struct *vma, + unsigned long address, + int write_access) { + unsigned long off; + uint32_t n; + struct page *page; + unsigned long phys; + + off = address - vma->vm_start + (vma->vm_pgoff<<PAGE_SHIFT); + n = off / PAGE_SIZE; + + if(n >= agp_mem->page_count) { + printk(KERN_DEBUG "tdfx_vid: Too far away\n"); + return ((struct page *)0UL); + } + phys = agp_mem->memory[n] & ~(0x00000fff); + page = virt_to_page(phys_to_virt(phys)); + if(!page) { + printk(KERN_DEBUG "tdfx_vid: Can't get the page\n"); + return ((struct page *)0UL); + } + return page; +} + +/* memory handler functions */ +static struct vm_operations_struct tdfx_vid_vm_ops = { + open: tdfx_vid_mopen, /* mmap-open */ + close: tdfx_vid_mclose,/* mmap-close */ + nopage: tdfx_vid_nopage, /* no-page fault handler */ +}; + static int tdfx_vid_mmap(struct file *file, struct vm_area_struct *vma) { size_t size; - //u32 pages; #ifdef MP_DEBUG printk(KERN_DEBUG "tdfx_vid: mapping agp memory into userspace\n"); #endif if(agp_mem) return(-EAGAIN); - + size = (vma->vm_end-vma->vm_start + PAGE_SIZE - 1) / PAGE_SIZE; agp_mem = drm_agp->allocate_memory(size,AGP_NORMAL_MEMORY); @@ -566,23 +663,26 @@ static int tdfx_vid_mmap(struct file *file, struct vm_area_struct *vma) printk(KERN_INFO "%d pages of AGP mem allocated (%ld/%ld bytes) :)))\n", size,vma->vm_end-vma->vm_start,size*PAGE_SIZE); - //setup_fifo(0,size); - + if(tdfx_map_io) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,3) - if(remap_page_range(vma, vma->vm_start,agp_info.aper_base, - vma->vm_end - vma->vm_start, vma->vm_page_prot)) + if(remap_page_range(vma, vma->vm_start,agp_info.aper_base, + vma->vm_end - vma->vm_start, vma->vm_page_prot)) #else - if(remap_page_range(vma->vm_start, (unsigned long)agp_info.aper_base, - vma->vm_end - vma->vm_start, vma->vm_page_prot)) + if(remap_page_range(vma->vm_start, (unsigned long)agp_info.aper_base, + vma->vm_end - vma->vm_start, vma->vm_page_prot)) #endif - { - printk(KERN_ERR "tdfx_vid: error mapping video memory\n"); - return(-EAGAIN); - } - - - printk(KERN_INFO "AGP Mem mapped in user space !!!!!\n"); + { + printk(KERN_ERR "tdfx_vid: error mapping video memory\n"); + return(-EAGAIN); + } + } else { + // Never swap it out + vma->vm_flags |= VM_LOCKED | VM_IO; + vma->vm_ops = &tdfx_vid_vm_ops; + vma->vm_ops->open(vma); + } + printk(KERN_INFO "Page fault handler ready !!!!!\n"); return 0; } @@ -590,7 +690,6 @@ static int tdfx_vid_mmap(struct file *file, struct vm_area_struct *vma) static int tdfx_vid_release(struct inode *inode, struct file *file) { - //Close the window just in case #ifdef MP_DEBUG printk(KERN_DEBUG "tdfx_vid: Video OFF (release)\n"); #endif diff --git a/drivers/tdfx_vid.h b/drivers/tdfx_vid.h index cb8d4fbc5b..7fb7b12db2 100644 --- a/drivers/tdfx_vid.h +++ b/drivers/tdfx_vid.h @@ -7,14 +7,23 @@ #define TDFX_VID_MOVE_2_3D 2 #define TDFX_VID_MOVE_2_TEXTURE 3 +#define TDFX_VID_SRC_COLORKEY 0x1 +#define TDFX_VID_DST_COLORKEY 0x2 + +#define TDFX_VID_ROP_COPY 0xcc // src +#define TDFX_VID_ROP_INVERT 0x55 // NOT dst +#define TDFX_VID_ROP_XOR 0x66 // src XOR dst +#define TDFX_VID_ROP_OR 0xee // src OR dst + #define TDFX_VID_FORMAT_BGR1 (('B'<<24)|('G'<<16)|('R'<<8)|1) #define TDFX_VID_FORMAT_BGR8 (('B'<<24)|('G'<<16)|('R'<<8)|8) +#define TDFX_VID_FORMAT_BGR15 (('B'<<24)|('G'<<16)|('R'<<8)|15) #define TDFX_VID_FORMAT_BGR16 (('B'<<24)|('G'<<16)|('R'<<8)|16) #define TDFX_VID_FORMAT_BGR24 (('B'<<24)|('G'<<16)|('R'<<8)|24) #define TDFX_VID_FORMAT_BGR32 (('B'<<24)|('G'<<16)|('R'<<8)|32) #define TDFX_VID_FORMAT_YUY2 (('2'<<24)|('Y'<<16)|('U'<<8)|'Y') -#define TDFX_VID_FORMAT_UYVY (('U'<<24)|('Y'<<16)|('V'<<8)|'Y') +#define TDFX_VID_FORMAT_UYVY (('Y'<<24)|('V'<<16)|('Y'<<8)|'U') #define TDFX_VID_FORMAT_YV12 0x32315659 #define TDFX_VID_FORMAT_IYUV (('I'<<24)|('Y'<<16)|('U'<<8)|'V') @@ -36,6 +45,12 @@ typedef struct tdfx_vid_blit_s { uint16_t dst_x,dst_y; uint16_t dst_w,dst_h; uint32_t dst_format; + + uint32_t src_colorkey[2]; + uint32_t dst_colorkey[2]; + + uint8_t colorkey; + uint8_t rop[4]; } tdfx_vid_blit_t; typedef struct tdfx_vid_config_s { @@ -72,3 +87,4 @@ typedef struct tdfx_vid_yuv_s { #define TDFX_VID_GET_YUV _IOR('J', 5, tdfx_vid_blit_t) #define TDFX_VID_BUMP0 _IOR('J', 6, u16) + |