mirror of
https://github.com/mpv-player/mpv
synced 2024-12-20 09:05:56 +01:00
Overlay support (now vo_xtdfx is possible :) and yet another way to
access the mem. Still the same problem than with the page fault handler :( But it doesn't need a patched agpgart. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@9567 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
555b3f61fe
commit
6b271acc7e
@ -248,6 +248,12 @@ typedef struct voodoo_yuv_fb_t voodoo_yuv_fb;
|
||||
|
||||
#define COMMAND_3D (0x00200000 + 0x120)
|
||||
|
||||
#define SWAPBUFCMD (0x00200000 + 0x128)
|
||||
#define SWAPPENDING (0x00200000 + 0x24C)
|
||||
#define LEFTOVBUF (0x00200000 + 0x250)
|
||||
#define RIGHTOVBUF (0x00200000 + 0x254)
|
||||
#define FBISWAPBUFHIST (0x00200000 + 0x258)
|
||||
|
||||
/* register bitfields (not all, only as needed) */
|
||||
|
||||
#define BIT(x) (1UL << (x))
|
||||
|
@ -31,6 +31,7 @@
|
||||
#define TDFX_VID_MAJOR 178
|
||||
|
||||
MODULE_AUTHOR("Albeu");
|
||||
MODULE_DESCRIPTION("A driver for Banshee targeted for video app");
|
||||
|
||||
#ifdef MODULE_LICENSE
|
||||
MODULE_LICENSE("GPL");
|
||||
@ -55,9 +56,16 @@ 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);
|
||||
static unsigned long map_base = 0;
|
||||
|
||||
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);
|
||||
@ -224,14 +232,14 @@ static void agp_close(void) {
|
||||
|
||||
|
||||
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)
|
||||
if(!(agp_mem||map_start))
|
||||
return (-EAGAIN);
|
||||
|
||||
if(m->move2 > 3) {
|
||||
@ -240,8 +248,10 @@ static int agp_move(tdfx_vid_agp_move_t* m) {
|
||||
return (-EAGAIN);
|
||||
}
|
||||
|
||||
|
||||
src = agp_info.aper_base + m->src;
|
||||
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;
|
||||
@ -317,7 +327,7 @@ static void tdfx_vid_get_config(tdfx_vid_config_t* cfg) {
|
||||
cfg->screen_format = 0;
|
||||
break;
|
||||
}
|
||||
cfg->screen_stride = tdfx_inl(VIDDESKSTRIDE);
|
||||
cfg->screen_stride = tdfx_inl(VIDDESKSTRIDE) & 0x7FFF;
|
||||
cfg->screen_start = tdfx_inl(VIDDESKSTART);
|
||||
}
|
||||
|
||||
@ -373,9 +383,9 @@ inline static u32 tdfx_vid_make_format(int src,u16 stride,u32 fmt) {
|
||||
}
|
||||
|
||||
static int tdfx_vid_blit(tdfx_vid_blit_t* blit) {
|
||||
u32 src_fmt,dst_fmt;
|
||||
u32 src_fmt,dst_fmt,cmd = 2;
|
||||
u32 cmin,cmax,srcbase,srcxy,srcfmt,srcsize;
|
||||
u32 dstbase,dstxy,dstfmt,dstsize;
|
||||
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);
|
||||
@ -390,6 +400,12 @@ static int tdfx_vid_blit(tdfx_vid_blit_t* blit) {
|
||||
// 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 ...
|
||||
@ -403,7 +419,8 @@ static int tdfx_vid_blit(tdfx_vid_blit_t* blit) {
|
||||
dstbase = tdfx_inl(DSTBASE);
|
||||
dstxy = tdfx_inl(DSTXY);
|
||||
dstfmt = tdfx_inl(DSTFORMAT);
|
||||
dstsize = tdfx_inl(DSTSIZE);
|
||||
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);
|
||||
@ -437,10 +454,11 @@ static int tdfx_vid_blit(tdfx_vid_blit_t* blit) {
|
||||
tdfx_outl(DSTBASE,blit->dst & 0x00FFFFFF);
|
||||
tdfx_outl(DSTXY,XYREG(blit->dst_x,blit->dst_y));
|
||||
tdfx_outl(DSTFORMAT,dst_fmt);
|
||||
tdfx_outl(DSTSIZE,XYREG(blit->dst_w,blit->dst_h));
|
||||
if(cmd == 2)
|
||||
tdfx_outl(DSTSIZE,XYREG(blit->dst_w,blit->dst_h));
|
||||
|
||||
// Send the command
|
||||
tdfx_outl(COMMAND_2D,0x102 | (blit->rop[0] << 24));
|
||||
tdfx_outl(COMMAND_2D,cmd | 0x100 | (blit->rop[0] << 24));
|
||||
banshee_wait_idle();
|
||||
|
||||
// Now restore the regs to make fb happy
|
||||
@ -453,7 +471,8 @@ static int tdfx_vid_blit(tdfx_vid_blit_t* blit) {
|
||||
tdfx_outl(DSTBASE, dstbase);
|
||||
tdfx_outl(DSTXY, dstxy);
|
||||
tdfx_outl(DSTFORMAT, dstfmt);
|
||||
tdfx_outl(DSTSIZE, dstsize);
|
||||
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]);
|
||||
@ -499,6 +518,170 @@ static int tdfx_vid_get_yuv(unsigned long arg) {
|
||||
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_x < 0 || ov.dst_y < 0) {
|
||||
printk(KERN_DEBUG "tdfx_vid: Negative x/y not yet supported\n");
|
||||
return(-EFAULT);
|
||||
}
|
||||
|
||||
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
|
||||
tdfx_outl(VIDOVRSTARTCRD,(ov.dst_x & 0xFFF)|((ov.dst_y & 0xFFF)<<12));
|
||||
// End coord
|
||||
tdfx_outl(VIDOVRENDCRD, ((ov.dst_x + disp_w) & 0xFFF)|
|
||||
(((ov.dst_y + disp_h) & 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 alredy on
|
||||
printk(KERN_DEBUG "tdfx_vid: Overlay is alredy 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 alredy 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;
|
||||
@ -544,6 +727,12 @@ static int tdfx_vid_ioctl(struct inode *inode, struct file *file, unsigned int c
|
||||
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);
|
||||
@ -642,11 +831,31 @@ static int tdfx_vid_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
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);
|
||||
|
||||
size = (vma->vm_end-vma->vm_start + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
|
||||
|
||||
agp_mem = drm_agp->allocate_memory(size,AGP_NORMAL_MEMORY);
|
||||
if(!agp_mem) {
|
||||
printk(KERN_ERR "Failed to allocate AGP memory\n");
|
||||
@ -681,8 +890,8 @@ static int tdfx_vid_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
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");
|
||||
}
|
||||
printk(KERN_INFO "Page fault handler ready !!!!!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -80,11 +80,27 @@ typedef struct tdfx_vid_yuv_s {
|
||||
uint16_t stride;
|
||||
} tdfx_vid_yuv_t;
|
||||
|
||||
typedef struct tdfx_vid_overlay_s {
|
||||
uint32_t src[2]; // left and right buffer (2 buffer may be NULL)
|
||||
uint16_t src_width,src_height;
|
||||
uint16_t src_stride;
|
||||
uint32_t format;
|
||||
|
||||
uint16_t dst_width,dst_height;
|
||||
int16_t dst_x,dst_y;
|
||||
|
||||
uint8_t use_colorkey;
|
||||
uint32_t colorkey[2]; // min/max
|
||||
uint8_t invert_colorkey;
|
||||
} tdfx_vid_overlay_t;
|
||||
|
||||
#define TDFX_VID_GET_CONFIG _IOR('J', 1, tdfx_vid_config_t)
|
||||
#define TDFX_VID_AGP_MOVE _IOR('J', 2, tdfx_vid_agp_move_t)
|
||||
#define TDFX_VID_BLIT _IOR('J', 3, tdfx_vid_blit_t)
|
||||
#define TDFX_VID_SET_YUV _IOR('J', 4, tdfx_vid_blit_t)
|
||||
#define TDFX_VID_AGP_MOVE _IOW('J', 2, tdfx_vid_agp_move_t)
|
||||
#define TDFX_VID_BLIT _IOW('J', 3, tdfx_vid_blit_t)
|
||||
#define TDFX_VID_SET_YUV _IOW('J', 4, tdfx_vid_blit_t)
|
||||
#define TDFX_VID_GET_YUV _IOR('J', 5, tdfx_vid_blit_t)
|
||||
|
||||
#define TDFX_VID_BUMP0 _IOR('J', 6, u16)
|
||||
#define TDFX_VID_BUMP0 _IOW('J', 6, u16)
|
||||
#define TDFX_VID_SET_OVERLAY _IOW('J', 7, tdfx_vid_overlay_t)
|
||||
#define TDFX_VID_OVERLAY_ON _IO ('J', 8)
|
||||
#define TDFX_VID_OVERLAY_OFF _IO ('J', 9)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user