summaryrefslogtreecommitdiffstats
path: root/drivers/tdfx_vid.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tdfx_vid.c')
-rw-r--r--drivers/tdfx_vid.c1049
1 files changed, 0 insertions, 1049 deletions
diff --git a/drivers/tdfx_vid.c b/drivers/tdfx_vid.c
deleted file mode 100644
index 501f5fc603..0000000000
--- a/drivers/tdfx_vid.c
+++ /dev/null
@@ -1,1049 +0,0 @@
-/*
- * Copyright (C) 2003 Alban Bedel
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/config.h>
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10)
-#include <linux/malloc.h>
-#else
-#include <linux/slab.h>
-#endif
-
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/agp_backend.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include "tdfx_vid.h"
-#include "3dfx.h"
-
-
-#define TDFX_VID_MAJOR 178
-
-MODULE_AUTHOR("Albeu");
-MODULE_DESCRIPTION("A driver for Banshee targeted for video app");
-
-#ifdef MODULE_LICENSE
-MODULE_LICENSE("GPL");
-#endif
-
-#ifndef min
-#define min(x,y) (((x)<(y))?(x):(y))
-#endif
-
-static struct pci_dev *pci_dev;
-
-static uint8_t *tdfx_mmio_base = 0;
-static uint32_t tdfx_mem_base = 0;
-static uint32_t tdfx_io_base = 0;
-
-static int tdfx_ram_size = 0;
-
-static int tdfx_vid_in_use = 0;
-
-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;
-static __initdata unsigned long map_start = 0; //0x7300000;
-static __initdata unsigned long map_max = (10*1024*1024);
-
-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");
-MODULE_PARM(map_start,"l");
-MODULE_PARM_DESC(map_start,"Use a block of physical mem instead of the agp arerture.");
-MODULE_PARM(map_max,"l");
-MODULE_PARM_DESC(map_max, "Maximum amout of physical memory (in bytes) that can be used\n");
-
-static inline u32 tdfx_inl(unsigned int reg) {
- return readl(tdfx_mmio_base + reg);
-}
-
-static inline void tdfx_outl(unsigned int reg, u32 val) {
- writel(val,tdfx_mmio_base + reg);
-}
-
-static inline void banshee_make_room(int size) {
- while((tdfx_inl(STATUS) & 0x1f) < size);
-}
-
-static inline void banshee_wait_idle(void) {
- int i = 0;
-
- banshee_make_room(1);
- tdfx_outl(COMMAND_3D, COMMAND_3D_NOP);
-
- while(1) {
- i = (tdfx_inl(STATUS) & STATUS_BUSY) ? 0 : i + 1;
- if(i == 3) break;
- }
-}
-
-static unsigned long get_lfb_size(void) {
- u32 draminit0 = 0;
- u32 draminit1 = 0;
- // u32 miscinit1 = 0;
- u32 lfbsize = 0;
- int sgram_p = 0;
-
- draminit0 = tdfx_inl(DRAMINIT0);
- draminit1 = tdfx_inl(DRAMINIT1);
-
- if ((pci_dev->device == PCI_DEVICE_ID_3DFX_BANSHEE) ||
- (pci_dev->device == PCI_DEVICE_ID_3DFX_VOODOO3)) {
- sgram_p = (draminit1 & DRAMINIT1_MEM_SDRAM) ? 0 : 1;
-
- lfbsize = sgram_p ?
- (((draminit0 & DRAMINIT0_SGRAM_NUM) ? 2 : 1) *
- ((draminit0 & DRAMINIT0_SGRAM_TYPE) ? 8 : 4) * 1024 * 1024) :
- 16 * 1024 * 1024;
- } else {
- /* Voodoo4/5 */
- u32 chips, psize, banks;
-
- chips = ((draminit0 & (1 << 26)) == 0) ? 4 : 8;
- psize = 1 << ((draminit0 & 0x38000000) >> 28);
- banks = ((draminit0 & (1 << 30)) == 0) ? 2 : 4;
- lfbsize = chips * psize * banks;
- lfbsize <<= 20;
- }
-
-#if 0
- /* disable block writes for SDRAM (why?) */
- miscinit1 = tdfx_inl(MISCINIT1);
- miscinit1 |= sgram_p ? 0 : MISCINIT1_2DBLOCK_DIS;
- miscinit1 |= MISCINIT1_CLUT_INV;
-
- banshee_make_room(1);
- tdfx_outl(MISCINIT1, miscinit1);
-#endif
-
- return lfbsize;
-}
-
-static int tdfx_vid_find_card(void)
-{
- struct pci_dev *dev = NULL;
- // unsigned int card_option;
-
- if((dev = pci_find_device(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE, NULL)))
- printk(KERN_INFO "tdfx_vid: Found VOODOO BANSHEE\n");
- else if((dev = pci_find_device(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3, NULL)))
- printk(KERN_INFO "tdfx_vid: Found VOODOO 3 \n");
- else
- return 0;
-
-
- pci_dev = dev;
-
-#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_ram_size = get_lfb_size();
-
- printk(KERN_INFO "tdfx_vid: Found %d MB (%d bytes) of memory\n",
- tdfx_ram_size / 1024 / 1024,tdfx_ram_size);
-
-
-#if 0
- {
- int temp;
- printk("List resources -----------\n");
- for(temp=0;temp<DEVICE_COUNT_RESOURCE;temp++){
- struct resource *res=&pci_dev->resource[temp];
- if(res->flags){
- int size=(1+res->end-res->start)>>20;
- printk(KERN_DEBUG "res %d: start: 0x%X end: 0x%X (%d MB) flags=0x%X\n",temp,res->start,res->end,size,res->flags);
- if(res->flags&(IORESOURCE_MEM|IORESOURCE_PREFETCH)){
- if(size>tdfx_ram_size && size<=64) tdfx_ram_size=size;
- }
- }
- }
- }
-#endif
-
-
- return 1;
-}
-
-static int agp_init(void) {
-
- drm_agp = (drm_agp_t*)inter_module_get("drm_agp");
-
- if(!drm_agp) {
- printk(KERN_ERR "tdfx_vid: Unable to get drm_agp pointer\n");
- return 0;
- }
-
- if(drm_agp->acquire()) {
- printk(KERN_ERR "tdfx_vid: Unable to acquire the agp backend\n");
- drm_agp = NULL;
- return 0;
- }
-
- drm_agp->copy_info(&agp_info);
-#if 0
- printk(KERN_DEBUG "AGP Version : %d %d\n"
- "AGP Mode: %#X\nAperture Base: %p\nAperture Size: %d\n"
- "Max memory = %d\nCurrent mem = %d\nCan use perture : %s\n"
- "Page mask = %#X\n",
- agp_info.version.major,agp_info.version.minor,
- agp_info.mode,agp_info.aper_base,agp_info.aper_size,
- agp_info.max_memory,agp_info.current_memory,
- agp_info.cant_use_aperture ? "no" : "yes",
- agp_info.page_mask);
-#endif
- drm_agp->enable(agp_info.mode);
-
-
- printk(KERN_INFO "AGP Enabled\n");
-
- return 1;
-}
-
-static void agp_close(void) {
-
- if(!drm_agp) return;
-
- if(agp_mem) {
- drm_agp->unbind_memory(agp_mem);
- drm_agp->free_memory(agp_mem);
- agp_mem = NULL;
- }
-
-
- drm_agp->release();
- inter_module_put("drm_agp");
-}
-
-static int agp_move(tdfx_vid_agp_move_t* m) {
- u32 src = 0;
- u32 src_h,src_l;
-
- if(!(agp_mem||map_start))
- return -EAGAIN;
-
- if(m->move2 > 3) {
- printk(KERN_DEBUG "tdfx_vid: AGP move invalid destination %d\n",
- m->move2);
- return -EAGAIN;
- }
-
- if(map_start)
- src = map_start + m->src;
- else
- src = agp_info.aper_base + m->src;
-
- src_l = (u32)src;
- src_h = (m->width | (m->src_stride << 14)) & 0x0FFFFFFF;
-
- // banshee_wait_idle();
- banshee_make_room(6);
- tdfx_outl(AGPHOSTADDRESSHIGH,src_h);
- tdfx_outl(AGPHOSTADDRESSLOW,src_l);
-
- tdfx_outl(AGPGRAPHICSADDRESS, m->dst);
- tdfx_outl(AGPGRAPHICSSTRIDE, m->dst_stride);
- tdfx_outl(AGPREQSIZE,m->src_stride*m->height);
-
- tdfx_outl(AGPMOVECMD,m->move2 << 3);
- banshee_wait_idle();
-
- return 0;
-}
-
-#if 0
-static void setup_fifo(u32 offset,ssize_t pages) {
- long addr = agp_info.aper_base + offset;
- u32 size = pages | 0x700; // fifo on, in agp mem, disable hole cnt
-
- banshee_wait_idle();
-
- tdfx_outl(CMDBASEADDR0,addr >> 4);
- tdfx_outl(CMDRDPTRL0, addr << 4);
- tdfx_outl(CMDRDPTRH0, addr >> 28);
- tdfx_outl(CMDAMIN0, (addr - 4) & 0xFFFFFF);
- tdfx_outl(CMDAMAX0, (addr - 4) & 0xFFFFFF);
- tdfx_outl(CMDFIFODEPTH0, 0);
- tdfx_outl(CMDHOLECNT0, 0);
- tdfx_outl(CMDBASESIZE0,size);
-
- banshee_wait_idle();
-
-}
-#endif
-
-static int bump_fifo(u16 size) {
-
- banshee_wait_idle();
- tdfx_outl(CMDBUMP0 , size);
- banshee_wait_idle();
-
- return 0;
-}
-
-static void tdfx_vid_get_config(tdfx_vid_config_t* cfg) {
- u32 in;
-
- cfg->version = TDFX_VID_VERSION;
- cfg->ram_size = tdfx_ram_size;
-
- in = tdfx_inl(VIDSCREENSIZE);
- cfg->screen_width = in & 0xFFF;
- cfg->screen_height = (in >> 12) & 0xFFF;
- in = (tdfx_inl(VIDPROCCFG)>> 18)& 0x7;
- switch(in) {
- case 0:
- cfg->screen_format = TDFX_VID_FORMAT_BGR8;
- break;
- case 1:
- cfg->screen_format = TDFX_VID_FORMAT_BGR16;
- break;
- case 2:
- cfg->screen_format = TDFX_VID_FORMAT_BGR24;
- break;
- case 3:
- cfg->screen_format = TDFX_VID_FORMAT_BGR32;
- break;
- default:
- printk(KERN_INFO "tdfx_vid: unknown screen format %d\n",in);
- cfg->screen_format = 0;
- break;
- }
- cfg->screen_stride = tdfx_inl(VIDDESKSTRIDE) & 0x7FFF;
- cfg->screen_start = tdfx_inl(VIDDESKSTART);
-}
-
-inline static u32 tdfx_vid_make_format(int src,u16 stride,u32 fmt) {
- u32 r = stride & 0xFFF3;
- u32 tdfx_fmt = 0;
-
- // src and dest formats
- switch(fmt) {
- case TDFX_VID_FORMAT_BGR8:
- tdfx_fmt = 1;
- break;
- case TDFX_VID_FORMAT_BGR16:
- tdfx_fmt = 3;
- break;
- case TDFX_VID_FORMAT_BGR24:
- tdfx_fmt = 4;
- break;
- case TDFX_VID_FORMAT_BGR32:
- tdfx_fmt = 5;
- break;
- }
-
- if(!src && !tdfx_fmt) {
- printk(KERN_INFO "tdfx_vid: Invalid destination format %#X\n",fmt);
- return 0;
- }
-
- if(src && !tdfx_fmt) {
- // src only format
- switch(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;
- case TDFX_VID_FORMAT_UYVY:
- tdfx_fmt = 9;
- break;
- default:
- printk(KERN_INFO "tdfx_vid: Invalid source format %#X\n",fmt);
- return 0;
- }
- }
-
- r |= tdfx_fmt << 16;
-
- return r;
-}
-
-static int tdfx_vid_blit(tdfx_vid_blit_t* blit) {
- u32 src_fmt,dst_fmt,cmd = 2;
- u32 cmin,cmax,srcbase,srcxy,srcfmt,srcsize;
- u32 dstbase,dstxy,dstfmt,dstsize = 0;
- 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);
- if(!src_fmt)
- return 0;
- //printk(KERN_INFO "tdfx_vid: Make dst fmt 0x%x\n", blit->dst_format);
- 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;
- // No stretch : fix me the cmd should be 1 but it
- // doesn't work. Maybe some other regs need to be set
- // as non-stretch blit have more options
- if(((!blit->dst_w) && (!blit->dst_h)) ||
- ((blit->dst_w == blit->src_w) && (blit->dst_h == blit->src_h)))
- cmd = 2;
-
- // 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);
- srcxy = tdfx_inl(SRCXY);
- srcfmt = tdfx_inl(SRCFORMAT);
- srcsize = tdfx_inl(SRCSIZE);
- dstbase = tdfx_inl(DSTBASE);
- dstxy = tdfx_inl(DSTXY);
- dstfmt = tdfx_inl(DSTFORMAT);
- if(cmd == 2)
- 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
- tdfx_outl(CLIP0MIN,0);
- tdfx_outl(CLIP0MAX,0x0fff0fff);
-
- // Setup the src
- tdfx_outl(SRCBASE,blit->src & 0x00FFFFFF);
- tdfx_outl(SRCXY,XYREG(blit->src_x,blit->src_y));
- tdfx_outl(SRCFORMAT,src_fmt);
- tdfx_outl(SRCSIZE,XYREG(blit->src_w,blit->src_h));
-
- // Setup the dst
- tdfx_outl(DSTBASE,blit->dst & 0x00FFFFFF);
- tdfx_outl(DSTXY,XYREG(blit->dst_x,blit->dst_y));
- tdfx_outl(DSTFORMAT,dst_fmt);
- if(cmd == 2)
- tdfx_outl(DSTSIZE,XYREG(blit->dst_w,blit->dst_h));
-
- // Send the command
- tdfx_outl(COMMAND_2D,cmd | 0x100 | (blit->rop[0] << 24));
- banshee_wait_idle();
-
- // Now restore the regs to make fb happy
- tdfx_outl(CLIP0MIN, cmin);
- tdfx_outl(CLIP0MAX, cmax);
- tdfx_outl(SRCBASE, srcbase);
- tdfx_outl(SRCXY, srcxy);
- tdfx_outl(SRCFORMAT, srcfmt);
- tdfx_outl(SRCSIZE, srcsize);
- tdfx_outl(DSTBASE, dstbase);
- tdfx_outl(DSTXY, dstxy);
- tdfx_outl(DSTFORMAT, dstfmt);
- if(cmd == 2)
- tdfx_outl(DSTSIZE, dstsize);
- 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;
-}
-
-static int tdfx_vid_set_yuv(unsigned long arg) {
- tdfx_vid_yuv_t yuv;
-
- if(copy_from_user(&yuv,(tdfx_vid_yuv_t*)arg,sizeof(tdfx_vid_yuv_t))) {
- printk(KERN_DEBUG "tdfx_vid:failed copy from userspace\n");
- return -EFAULT;
- }
- banshee_make_room(2);
- tdfx_outl(YUVBASEADDRESS,yuv.base & 0x01FFFFFF);
- tdfx_outl(YUVSTRIDE, yuv.stride & 0x3FFF);
-
- banshee_wait_idle();
-
- return 0;
-}
-
-static int tdfx_vid_get_yuv(unsigned long arg) {
- tdfx_vid_yuv_t yuv;
-
- yuv.base = tdfx_inl(YUVBASEADDRESS) & 0x01FFFFFF;
- yuv.stride = tdfx_inl(YUVSTRIDE) & 0x3FFF;
-
- if(copy_to_user((tdfx_vid_yuv_t*)arg,&yuv,sizeof(tdfx_vid_yuv_t))) {
- printk(KERN_INFO "tdfx_vid:failed copy to userspace\n");
- return -EFAULT;
- }
-
- return 0;
-}
-
-static int tdfx_vid_set_overlay(unsigned long arg) {
- tdfx_vid_overlay_t ov;
- uint32_t screen_w,screen_h;
- uint32_t vidcfg,stride,vidbuf;
- int disp_w,disp_h;
-
- if(copy_from_user(&ov,(tdfx_vid_overlay_t*)arg,sizeof(tdfx_vid_overlay_t))) {
- printk(KERN_DEBUG "tdfx_vid:failed copy from userspace\n");
- return -EFAULT;
- }
-
- if(ov.dst_y < 0) {
- int shift;
- if(-ov.dst_y >= ov.src_height) {
- printk(KERN_DEBUG "tdfx_vid: Overlay outside of the screen ????\n");
- return -EFAULT;
- }
- shift = (-ov.dst_y)/(double)ov.dst_height*ov.src_height;
- ov.src[0] += shift*ov.src_stride;
- ov.src_height -= shift;
- ov.dst_height += ov.dst_y;
- ov.dst_y = 0;
- }
-
- if(ov.dst_x < 0) {
- int shift;
- if(-ov.dst_x >= ov.src_width) {
- printk(KERN_DEBUG "tdfx_vid: Overlay outside of the screen ????\n");
- return -EFAULT;
- }
- shift = (-ov.dst_x)/(double)ov.dst_width*ov.src_width;
- shift = ((shift+3)/2)*2;
- ov.src[0] += shift*2;
- ov.src_width -= shift;
- ov.dst_width += ov.dst_x;
- ov.dst_x = 0;
- }
-
- vidcfg = tdfx_inl(VIDPROCCFG);
- // clear the overlay fmt
- vidcfg &= ~(7 << 21);
- switch(ov.format) {
- case TDFX_VID_FORMAT_BGR15:
- vidcfg |= (1 << 21);
- break;
- case TDFX_VID_FORMAT_BGR16:
- vidcfg |= (7 << 21);
- break;
- case TDFX_VID_FORMAT_YUY2:
- vidcfg |= (5 << 21);
- break;
- case TDFX_VID_FORMAT_UYVY:
- vidcfg |= (6 << 21);
- break;
- default:
- printk(KERN_DEBUG "tdfx_vid: Invalid overlay fmt 0x%x\n",ov.format);
- return -EFAULT;
- }
-
- // YUV422 need 4 bytes aligned stride and address
- if((ov.format == TDFX_VID_FORMAT_YUY2 ||
- ov.format == TDFX_VID_FORMAT_UYVY)) {
- if((ov.src_stride & ~0x3) != ov.src_stride) {
- printk(KERN_DEBUG "tdfx_vid: YUV need a 4 bytes aligned stride %d\n",ov.src_stride);
- return -EFAULT;
- }
- if((ov.src[0] & ~0x3) != ov.src[0] || (ov.src[1] & ~0x3) != ov.src[1]){
- printk(KERN_DEBUG "tdfx_vid: YUV need a 4 bytes aligned address 0x%x 0x%x\n",ov.src[0],ov.src[1]);
- return -EFAULT;
- }
- }
-
- // Now we have a good input format
- // but first get the screen size to check a bit
- // if the size/position is valid
- screen_w = tdfx_inl(VIDSCREENSIZE);
- screen_h = (screen_w >> 12) & 0xFFF;
- screen_w &= 0xFFF;
- disp_w = ov.dst_x + ov.dst_width >= screen_w ?
- screen_w - ov.dst_x : ov.dst_width;
- disp_h = ov.dst_y + ov.dst_height >= screen_h ?
- screen_h - ov.dst_y : ov.dst_height;
-
- if(ov.dst_x >= screen_w || ov.dst_y >= screen_h ||
- disp_h <= 0 || disp_h > screen_h || disp_w <= 0 || disp_w > screen_w) {
- printk(KERN_DEBUG "tdfx_vid: Invalid overlay dimension and/or position\n");
- return -EFAULT;
- }
- // Setup the vidproc
- // H scaling
- if(ov.src_width < ov.dst_width)
- vidcfg |= (1<<14);
- else
- vidcfg &= ~(1<<14);
- // V scaling
- if(ov.src_height < ov.dst_height)
- vidcfg |= (1<<15);
- else
- vidcfg &= ~(1<<15);
- // Filtering can only be used in 1x mode
- if(!(vidcfg | (1<<26)))
- vidcfg |= (3<<16);
- else
- vidcfg &= ~(3<<16);
- // disable overlay stereo mode
- vidcfg &= ~(1<<2);
- // Colorkey on/off
- if(ov.use_colorkey) {
- // Colorkey inversion
- if(ov.invert_colorkey)
- vidcfg |= (1<<6);
- else
- vidcfg &= ~(1<<6);
- vidcfg |= (1<<5);
- } else
- vidcfg &= ~(1<<5);
- // Overlay isn't VidIn
- vidcfg &= ~(1<<9);
- // vidcfg |= (1<<8);
- tdfx_outl(VIDPROCCFG,vidcfg);
-
- // Start coord
- //printk(KERN_DEBUG "tdfx_vid: start %dx%d\n",ov.dst_x & 0xFFF,ov.dst_y & 0xFFF);
- tdfx_outl(VIDOVRSTARTCRD,(ov.dst_x & 0xFFF)|((ov.dst_y & 0xFFF)<<12));
- // End coord
- tdfx_outl(VIDOVRENDCRD, ((ov.dst_x + disp_w-1) & 0xFFF)|
- (((ov.dst_y + disp_h-1) & 0xFFF)<<12));
- // H Scaling
- tdfx_outl(VIDOVRDUDX,( ((u32)ov.src_width) << 20) / ov.dst_width);
- // Src offset and width (in bytes)
- tdfx_outl(VIDOVRDUDXOFF,((ov.src_width<<1) & 0xFFF) << 19);
- // V Scaling
- tdfx_outl(VIDOVRDVDY, ( ((u32)ov.src_height) << 20) / ov.dst_height);
- //else
- // tdfx_outl(VIDOVRDVDY,0);
- // V Offset
- tdfx_outl(VIDOVRDVDYOFF,0);
- // Overlay stride
- stride = tdfx_inl(VIDDESKSTRIDE) & 0xFFFF;
- tdfx_outl(VIDDESKSTRIDE,stride | (((u32)ov.src_stride) << 16));
- // Buffers address
- tdfx_outl(LEFTOVBUF, ov.src[0]);
- tdfx_outl(RIGHTOVBUF, ov.src[1]);
-
- // Send a swap buffer cmd if we are not on one of the 2 buffers
- vidbuf = tdfx_inl(VIDCUROVRSTART);
- if(vidbuf != ov.src[0] && vidbuf != ov.src[1]) {
- tdfx_outl(SWAPPENDING,0);
- tdfx_outl(SWAPBUFCMD, 1);
- }
- //printk(KERN_DEBUG "tdfx_vid: Buf0=0x%x Buf1=0x%x Current=0x%x\n",
- // ov.src[0],ov.src[1],tdfx_inl(VIDCUROVRSTART));
- // Colorkey
- if(ov.use_colorkey) {
- tdfx_outl(VIDCHRMIN,ov.colorkey[0]);
- tdfx_outl(VIDCHRMAX,ov.colorkey[1]);
- }
-
- return 0;
-}
-
-static int tdfx_vid_overlay_on(void) {
- uint32_t vidcfg = tdfx_inl(VIDPROCCFG);
- //return 0;
- if(vidcfg & (1<<8)) { // Overlay is already on
- //printk(KERN_DEBUG "tdfx_vid: Overlay is already on.\n");
- return -EFAULT;
- }
- vidcfg |= (1<<8);
- tdfx_outl(VIDPROCCFG,vidcfg);
- return 0;
-}
-
-static int tdfx_vid_overlay_off(void) {
- uint32_t vidcfg = tdfx_inl(VIDPROCCFG);
-
- if(vidcfg & (1<<8)) {
- vidcfg &= ~(1<<8);
- tdfx_outl(VIDPROCCFG,vidcfg);
- return 0;
- }
-
- printk(KERN_DEBUG "tdfx_vid: Overlay is already off.\n");
- return -EFAULT;
-}
-
-
-static int tdfx_vid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
- tdfx_vid_agp_move_t move;
- tdfx_vid_config_t cfg;
- tdfx_vid_blit_t blit;
- u16 int16;
-
- switch(cmd) {
- case TDFX_VID_AGP_MOVE:
- if(copy_from_user(&move,(tdfx_vid_agp_move_t*)arg,sizeof(tdfx_vid_agp_move_t))) {
- printk(KERN_INFO "tdfx_vid:failed copy from userspace\n");
- return -EFAULT;
- }
- return agp_move(&move);
- case TDFX_VID_BUMP0:
- if(copy_from_user(&int16,(u16*)arg,sizeof(u16))) {
- printk(KERN_INFO "tdfx_vid:failed copy from userspace\n");
- return -EFAULT;
- }
- return bump_fifo(int16);
- case TDFX_VID_BLIT:
- if(copy_from_user(&blit,(tdfx_vid_blit_t*)arg,sizeof(tdfx_vid_blit_t))) {
- printk(KERN_INFO "tdfx_vid:failed copy from userspace\n");
- return -EFAULT;
- }
- if(!tdfx_vid_blit(&blit)) {
- printk(KERN_INFO "tdfx_vid: Blit failed\n");
- return -EFAULT;
- }
- return 0;
- case TDFX_VID_GET_CONFIG:
- if(copy_from_user(&cfg,(tdfx_vid_config_t*)arg,sizeof(tdfx_vid_config_t))) {
- printk(KERN_INFO "tdfx_vid:failed copy from userspace\n");
- return -EFAULT;
- }
- tdfx_vid_get_config(&cfg);
- if(copy_to_user((tdfx_vid_config_t*)arg,&cfg,sizeof(tdfx_vid_config_t))) {
- printk(KERN_INFO "tdfx_vid:failed copy to userspace\n");
- return -EFAULT;
- }
- return 0;
- case TDFX_VID_SET_YUV:
- return tdfx_vid_set_yuv(arg);
- case TDFX_VID_GET_YUV:
- return tdfx_vid_get_yuv(arg);
- case TDFX_VID_SET_OVERLAY:
- return tdfx_vid_set_overlay(arg);
- case TDFX_VID_OVERLAY_ON:
- return tdfx_vid_overlay_on();
- case TDFX_VID_OVERLAY_OFF:
- return tdfx_vid_overlay_off();
- default:
- printk(KERN_ERR "tdfx_vid: Invalid ioctl %d\n",cmd);
- return -EINVAL;
- }
- return 0;
-}
-
-
-
-static ssize_t tdfx_vid_read(struct file *file, char *buf, size_t count, loff_t *ppos)
-{
- return 0;
-}
-
-static ssize_t tdfx_vid_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
-
- 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;
-#ifdef MP_DEBUG
- printk(KERN_DEBUG "tdfx_vid: mapping agp memory into userspace\n");
-#endif
-
- size = (vma->vm_end-vma->vm_start + PAGE_SIZE - 1) / PAGE_SIZE;
-
- if(map_start) { // Ok we map directly in the physcal ram
- if(size*PAGE_SIZE > map_max) {
- printk(KERN_ERR "tdfx_vid: Not enouth mem\n");
- return -EAGAIN;
- }
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,3)
- if(remap_page_range(vma, vma->vm_start,map_start,
- vma->vm_end - vma->vm_start, vma->vm_page_prot))
-#else
- if(remap_page_range(vma->vm_start, (unsigned long)map_start,
- 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 "Physical mem 0x%lx mapped in userspace\n",map_start);
- return 0;
- }
-
- if(agp_mem)
- return -EAGAIN;
-
- agp_mem = drm_agp->allocate_memory(size,AGP_NORMAL_MEMORY);
- if(!agp_mem) {
- printk(KERN_ERR "Failed to allocate AGP memory\n");
- return -ENOMEM;
- }
-
- if(drm_agp->bind_memory(agp_mem,0)) {
- printk(KERN_ERR "Failed to bind the AGP memory\n");
- drm_agp->free_memory(agp_mem);
- agp_mem = NULL;
- return -ENOMEM;
- }
-
- printk(KERN_INFO "%d pages of AGP mem allocated (%ld/%ld bytes) :)))\n",
- size,vma->vm_end-vma->vm_start,size*PAGE_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))
-#else
- 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;
- }
- } 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;
-}
-
-
-static int tdfx_vid_release(struct inode *inode, struct file *file)
-{
-#ifdef MP_DEBUG
- printk(KERN_DEBUG "tdfx_vid: Video OFF (release)\n");
-#endif
-
- // Release the agp mem
- if(agp_mem) {
- drm_agp->unbind_memory(agp_mem);
- drm_agp->free_memory(agp_mem);
- agp_mem = NULL;
- }
-
- tdfx_vid_in_use = 0;
-
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-static long long tdfx_vid_lseek(struct file *file, long long offset, int origin)
-{
- return -ESPIPE;
-}
-
-static int tdfx_vid_open(struct inode *inode, struct file *file)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2)
- int minor = MINOR(inode->i_rdev.value);
-#else
- int minor = MINOR(inode->i_rdev);
-#endif
-
- if(minor != 0)
- return -ENXIO;
-
- if(tdfx_vid_in_use == 1)
- return -EBUSY;
-
- tdfx_vid_in_use = 1;
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-#if LINUX_VERSION_CODE >= 0x020400
-static struct file_operations tdfx_vid_fops =
-{
- llseek: tdfx_vid_lseek,
- read: tdfx_vid_read,
- write: tdfx_vid_write,
- ioctl: tdfx_vid_ioctl,
- mmap: tdfx_vid_mmap,
- open: tdfx_vid_open,
- release: tdfx_vid_release
-};
-#else
-static struct file_operations tdfx_vid_fops =
-{
- tdfx_vid_lseek,
- tdfx_vid_read,
- tdfx_vid_write,
- NULL,
- NULL,
- tdfx_vid_ioctl,
- tdfx_vid_mmap,
- tdfx_vid_open,
- NULL,
- tdfx_vid_release
-};
-#endif
-
-
-int init_module(void)
-{
- tdfx_vid_in_use = 0;
-
- if(register_chrdev(TDFX_VID_MAJOR, "tdfx_vid", &tdfx_vid_fops)) {
- printk(KERN_ERR "tdfx_vid: unable to get major: %d\n", TDFX_VID_MAJOR);
- return -EIO;
- }
-
- if(!agp_init()) {
- printk(KERN_ERR "tdfx_vid: AGP init failed\n");
- unregister_chrdev(TDFX_VID_MAJOR, "tdfx_vid");
- return -EINVAL;
- }
-
- if (!tdfx_vid_find_card()) {
- printk(KERN_ERR "tdfx_vid: no supported devices found\n");
- agp_close();
- unregister_chrdev(TDFX_VID_MAJOR, "tdfx_vid");
- return -EINVAL;
- }
-
-
-
- return 0;
-
-}
-
-void cleanup_module(void)
-{
- if(tdfx_mmio_base)
- iounmap(tdfx_mmio_base);
- agp_close();
- printk(KERN_INFO "tdfx_vid: Cleaning up module\n");
- unregister_chrdev(TDFX_VID_MAJOR, "tdfx_vid");
-}