Mercurial > mplayer.hg
changeset 4721:e441ca06638d
Works with YUY2 fourcc
author | nick |
---|---|
date | Sat, 16 Feb 2002 07:55:44 +0000 |
parents | 10ad330c1733 |
children | 39f3bfae472c |
files | vidix/drivers/mach64_vid.c |
diffstat | 1 files changed, 549 insertions(+), 21 deletions(-) [+] |
line wrap: on
line diff
--- a/vidix/drivers/mach64_vid.c Sat Feb 16 05:45:16 2002 +0000 +++ b/vidix/drivers/mach64_vid.c Sat Feb 16 07:55:44 2002 +0000 @@ -3,8 +3,7 @@ Copyrights 2002 Nick Kurshev. This file is based on sources from GATOS (gatos.sf.net) and X11 (www.xfree86.org) Licence: GPL - WARNING: THIS DRIVER WAS UNFINISHED! PLEASE DON'T TRY TO USE THAT!!! - IT'S JUST SCRATCH FOR VOLUNTEERS!!! + WARNING: THIS DRIVER IS IN BETTA STAGE AND DOESN'T WORK WITH PLANAR FOURCCS! */ #include <errno.h> #include <stdio.h> @@ -26,22 +25,104 @@ static void *mach64_mmio_base = 0; static void *mach64_mem_base = 0; -static int32_t overlay_offset = 0; +static int32_t mach64_overlay_offset = 0; static uint32_t mach64_ram_size = 0; pciinfo_t pci_info; static int probed = 0; static int __verbose = 0; + +typedef struct bes_registers_s +{ + /* base address of yuv framebuffer */ + uint32_t yuv_base; + uint32_t fourcc; + /* YUV BES registers */ + uint32_t reg_load_cntl; + uint32_t scale_inc; + uint32_t y_x_start; + uint32_t y_x_end; + uint32_t vid_buf_pitch; + uint32_t height_width; + uint32_t vid_buf0_base_adrs; + uint32_t vid_buf1_base_adrs; + uint32_t vid_buf2_base_adrs; + uint32_t vid_buf3_base_adrs; + uint32_t vid_buf4_base_adrs; + uint32_t vid_buf5_base_adrs; + + uint32_t scale_cntl; + uint32_t exclusive_horz; + uint32_t auto_flip_cntl; + uint32_t filter_cntl; + uint32_t key_cntl; + uint32_t test; + /* Configurable stuff */ + int double_buff; + + int brightness; + int saturation; + + int ckey_on; + uint32_t graphics_key_clr; + uint32_t graphics_key_msk; + + int deinterlace_on; + uint32_t deinterlace_pattern; + +} bes_registers_t; + +static bes_registers_t besr; + +typedef struct video_registers_s +{ + const char * sname; + uint32_t name; + uint32_t value; +}video_registers_t; + +static bes_registers_t besr; +#define DECLARE_VREG(name) { #name, name, 0 } +static video_registers_t vregs[] = +{ + DECLARE_VREG(OVERLAY_SCALE_INC), + DECLARE_VREG(OVERLAY_Y_X_START), + DECLARE_VREG(OVERLAY_Y_X_END), + DECLARE_VREG(OVERLAY_SCALE_CNTL), + DECLARE_VREG(OVERLAY_EXCLUSIVE_HORZ), + DECLARE_VREG(OVERLAY_EXCLUSIVE_VERT), + DECLARE_VREG(OVERLAY_TEST), + DECLARE_VREG(SCALER_BUF_PITCH), + DECLARE_VREG(SCALER_HEIGHT_WIDTH), + DECLARE_VREG(SCALER_BUF0_OFFSET), + DECLARE_VREG(SCALER_BUF0_OFFSET_U), + DECLARE_VREG(SCALER_BUF0_OFFSET_V), + DECLARE_VREG(SCALER_BUF1_OFFSET), + DECLARE_VREG(SCALER_BUF1_OFFSET_U), + DECLARE_VREG(SCALER_BUF1_OFFSET_V), + DECLARE_VREG(SCALER_H_COEFF0), + DECLARE_VREG(SCALER_H_COEFF1), + DECLARE_VREG(SCALER_H_COEFF2), + DECLARE_VREG(SCALER_H_COEFF3), + DECLARE_VREG(SCALER_H_COEFF4), + DECLARE_VREG(SCALER_COLOUR_CNTL), + DECLARE_VREG(SCALER_THRESHOLD), + DECLARE_VREG(VIDEO_FORMAT), + DECLARE_VREG(VIDEO_CONFIG), + DECLARE_VREG(VIDEO_SYNC_TEST), + DECLARE_VREG(VIDEO_SYNC_TEST_B) +}; + /* VIDIX exports */ /* MMIO space*/ #define GETREG(TYPE,PTR,OFFZ) (*((volatile TYPE*)((PTR)+(OFFZ)))) #define SETREG(TYPE,PTR,OFFZ,VAL) (*((volatile TYPE*)((PTR)+(OFFZ))))=VAL -#define INREG8(addr) GETREG(uint8_t,(uint32_t)(mach64_mmio_base),(addr^0x100)<<2) -#define OUTREG8(addr,val) SETREG(uint8_t,(uint32_t)(mach64_mmio_base),(addr^0x100)<<2,val) -#define INREG(addr) GETREG(uint32_t,(uint32_t)(mach64_mmio_base),(addr^0x100)<<2) -#define OUTREG(addr,val) SETREG(uint32_t,(uint32_t)(mach64_mmio_base),(addr^0x100)<<2,val) +#define INREG8(addr) GETREG(uint8_t,(uint32_t)mach64_mmio_base,((addr)^0x100)<<2) +#define OUTREG8(addr,val) SETREG(uint8_t,(uint32_t)mach64_mmio_base,((addr)^0x100)<<2,val) +#define INREG(addr) GETREG(uint32_t,(uint32_t)mach64_mmio_base,((addr)^0x100)<<2) +#define OUTREG(addr,val) SETREG(uint32_t,(uint32_t)mach64_mmio_base,((addr)^0x100)<<2,val) #define OUTREGP(addr,val,mask) \ do { \ @@ -53,12 +134,24 @@ static __inline__ uint32_t INPLL(uint32_t addr) { - OUTREG8(0x491, (addr & 0x0000001f)); - return (INREG(0x492)); + uint32_t res; + + /* write addr byte */ + OUTREG8(CLOCK_CNTL + 1, (addr << 2)); + /* read the register value */ + res = INREG(CLOCK_CNTL + 2); + return res; } -#define OUTPLL(addr,val) OUTREG8(0x491, (addr & 0x0000001f) | 0x00000080); \ - OUTREG(0x492, val) +static __inline__ void OUTPLL(uint32_t addr,uint32_t val) +{ + /* write addr byte */ + OUTREG8(CLOCK_CNTL + 1, (addr << 2) | PLL_WR_EN); + /* write the register value */ + OUTREG(CLOCK_CNTL + 2, val); + OUTREG8(CLOCK_CNTL + 1, (addr << 2) & ~PLL_WR_EN); +} + #define OUTPLLP(addr,val,mask) \ do { \ unsigned int _tmp = INPLL(addr); \ @@ -67,6 +160,17 @@ OUTPLL(addr, _tmp); \ } while (0) +static void mach64_fifo_wait(unsigned n) +{ + while ((INREG(FIFO_STAT) & 0xffff) > ((uint32_t)(0x8000 >> n))); +} + +static void mach64_wait_for_idle( void ) +{ + mach64_fifo_wait(16); + while ((INREG(GUI_STAT) & 1)!= 0); +} + static vidix_capability_t mach64_cap = { "BES driver for Mach64/3DRage cards", @@ -84,6 +188,75 @@ { 0, 0, 0, 0 } }; +static uint32_t mach64_vid_get_dbpp( void ) +{ + uint32_t dbpp,retval; + dbpp = (INREG(CRTC_GEN_CNTL)>>8)& 0x7; + switch(dbpp) + { + case 1: retval = 4; break; + case 2: retval = 8; break; + case 3: retval = 15; break; + case 4: retval = 16; break; + case 5: retval = 24; break; + default: retval=32; break; + } + return retval; +} + +static int mach64_is_dbl_scan( void ) +{ + return INREG(CRTC_GEN_CNTL) & CRTC_DBL_SCAN_EN; +} + +static int mach64_is_interlace( void ) +{ + return INREG(CRTC_GEN_CNTL) & CRTC_INTERLACE_EN; +} + +static uint32_t mach64_get_xres( void ) +{ + /* FIXME: currently we extract that from CRTC!!!*/ + uint32_t xres,h_total; + h_total = INREG(CRTC_H_TOTAL_DISP); + xres = (h_total >> 16) & 0xffff; + return (xres + 1)*8; +} + +static uint32_t mach64_get_yres( void ) +{ + /* FIXME: currently we extract that from CRTC!!!*/ + uint32_t yres,v_total; + v_total = INREG(CRTC_V_TOTAL_DISP); + yres = (v_total >> 16) & 0xffff; + return yres + 1; +} + +static void mach64_vid_make_default() +{ + mach64_fifo_wait(2); + OUTREG(SCALER_COLOUR_CNTL,0x0010103f); +} + +static void mach64_vid_dump_regs( void ) +{ + size_t i; + printf("[mach64] *** Begin of DRIVER variables dump ***\n"); + printf("[mach64] mach64_mmio_base=%p\n",mach64_mmio_base); + printf("[mach64] mach64_mem_base=%p\n",mach64_mem_base); + printf("[mach64] mach64_overlay_off=%08X\n",mach64_overlay_offset); + printf("[mach64] mach64_ram_size=%08X\n",mach64_ram_size); + printf("[mach64] video mode: %ux%u@%u\n",mach64_get_xres(),mach64_get_yres(),mach64_vid_get_dbpp()); + printf("[mach64] *** Begin of OV0 registers dump ***\n"); + for(i=0;i<sizeof(vregs)/sizeof(video_registers_t);i++) + { + mach64_wait_for_idle(); + printf("[mach64] %s = %08X\n",vregs[i].sname,INREG(vregs[i].name)); + } + printf("[mach64] *** End of OV0 registers dump ***\n"); +} + + unsigned int vixGetVersion(void) { return(VIDIX_VERSION); @@ -187,6 +360,17 @@ return err; } +static void reset_regs( void ) +{ + size_t i; + for(i=0;i<sizeof(vregs)/sizeof(video_registers_t);i++) + { + mach64_fifo_wait(2); + OUTREG(vregs[i].name,-1); + } +} + + int vixInit(void) { int err; @@ -195,7 +379,8 @@ printf("[mach64] Driver was not probed but is being initializing\n"); return EINTR; } - if((mach64_mmio_base = map_phys_mem(pci_info.base2,0x4096))==(void *)-1) return ENOMEM; + if((mach64_mmio_base = map_phys_mem(pci_info.base2,0x4000))==(void *)-1) return ENOMEM; + mach64_wait_for_idle(); mach64_ram_size = INREG(MEM_CNTL) & CTL_MEM_SIZEB; if (mach64_ram_size < 8) mach64_ram_size = (mach64_ram_size + 1) * 512; else if (mach64_ram_size < 12) mach64_ram_size = (mach64_ram_size - 3) * 1024; @@ -203,17 +388,19 @@ mach64_ram_size *= 0x400; /* KB -> bytes */ if((mach64_mem_base = map_phys_mem(pci_info.base0,mach64_ram_size))==(void *)-1) return ENOMEM; // memset(&besr,0,sizeof(bes_registers_t)); -// mach64_vid_make_default(); + mach64_vid_make_default(); printf("[mach64] Video memory = %uMb\n",mach64_ram_size/0x100000); err = mtrr_set_type(pci_info.base0,mach64_ram_size,MTRR_TYPE_WRCOMB); if(!err) printf("[mach64] Set write-combining type of video memory\n"); + reset_regs(); + mach64_vid_dump_regs(); return 0; } void vixDestroy(void) { unmap_phys_mem(mach64_mem_base,mach64_ram_size); - unmap_phys_mem(mach64_mmio_base,0x4096); + unmap_phys_mem(mach64_mmio_base,0x4000); } int vixGetCapability(vidix_capability_t *to) @@ -222,30 +409,371 @@ return 0; } +static unsigned mach64_query_pitch(unsigned fourcc,const vidix_yuv_t *spitch) +{ + unsigned pitch,spy,spv,spu; + spy = spv = spu = 0; + switch(spitch->y) + { + case 16: + case 32: + case 64: + case 128: + case 256: spy = spitch->y; break; + default: break; + } + switch(spitch->u) + { + case 16: + case 32: + case 64: + case 128: + case 256: spu = spitch->u; break; + default: break; + } + switch(spitch->v) + { + case 16: + case 32: + case 64: + case 128: + case 256: spv = spitch->v; break; + default: break; + } + switch(fourcc) + { + /* 4:2:0 */ + case IMGFMT_IYUV: + case IMGFMT_YV12: + case IMGFMT_I420: + if(spy > 16 && spu == spy/2 && spv == spy/2) pitch = spy; + else pitch = 32; + break; + default: + if(spy > 16) pitch = spy; + else pitch = 32; + break; + } + return pitch; +} + +static void mach64_compute_framesize(vidix_playback_t *info) +{ + unsigned pitch,awidth; + pitch = mach64_query_pitch(info->fourcc,&info->src.pitch); + switch(info->fourcc) + { + case IMGFMT_I420: + case IMGFMT_YV12: + case IMGFMT_IYUV: + awidth = (info->src.w + (pitch-1)) & ~(pitch-1); + info->frame_size = awidth*(info->src.h+info->src.h/2); + break; + case IMGFMT_RGB32: + case IMGFMT_BGR32: + awidth = (info->src.w*4 + (pitch-1)) & ~(pitch-1); + info->frame_size = (awidth*info->src.h); + break; + /* YUY2 YVYU, RGB15, RGB16 */ + default: + awidth = (info->src.w*2 + (pitch-1)) & ~(pitch-1); + info->frame_size = (awidth*info->src.h); + break; + } +} + +static void mach64_vid_stop_video( void ) +{ + mach64_fifo_wait(14); + OUTREG(OVERLAY_SCALE_CNTL, 0x80000000); + OUTREG(OVERLAY_EXCLUSIVE_HORZ, 0); + OUTREG(OVERLAY_EXCLUSIVE_VERT, 0); + OUTREG(SCALER_H_COEFF0, 0x00002000); + OUTREG(SCALER_H_COEFF1, 0x0D06200D); + OUTREG(SCALER_H_COEFF2, 0x0D0A1C0D); + OUTREG(SCALER_H_COEFF3, 0x0C0E1A0C); + OUTREG(SCALER_H_COEFF4, 0x0C14140C); + OUTREG(VIDEO_FORMAT, 0xB000B); + OUTREG(OVERLAY_GRAPHICS_KEY_MSK, 0); + OUTREG(OVERLAY_GRAPHICS_KEY_CLR, 0); + OUTREG(OVERLAY_KEY_CNTL, 0x50); + OUTREG(OVERLAY_TEST, 0x0); +} + +static void mach64_vid_display_video( void ) +{ + uint32_t vf; + mach64_fifo_wait(14); + + OUTREG(OVERLAY_Y_X_START, besr.y_x_start); + OUTREG(OVERLAY_Y_X_END, besr.y_x_end); + OUTREG(OVERLAY_SCALE_INC, besr.scale_inc); + OUTREG(SCALER_BUF_PITCH, besr.vid_buf_pitch); + OUTREG(SCALER_HEIGHT_WIDTH, besr.height_width); + OUTREG(SCALER_BUF0_OFFSET, besr.vid_buf0_base_adrs); + OUTREG(SCALER_BUF0_OFFSET_U, besr.vid_buf1_base_adrs); + OUTREG(SCALER_BUF0_OFFSET_V, besr.vid_buf2_base_adrs); + OUTREG(SCALER_BUF1_OFFSET, besr.vid_buf3_base_adrs); + OUTREG(SCALER_BUF1_OFFSET_U, besr.vid_buf4_base_adrs); + OUTREG(SCALER_BUF1_OFFSET_V, besr.vid_buf5_base_adrs); + OUTREG(OVERLAY_SCALE_CNTL, 0x04000001 | (3<<30)); + mach64_wait_for_idle(); + vf = INREG(VIDEO_FORMAT); + switch(besr.fourcc) + { + /* 4:2:0 */ + case IMGFMT_IYUV: + case IMGFMT_I420: + case IMGFMT_YV12: OUTREG(VIDEO_FORMAT, (vf & ~0xF000) | 0xA000); break; + /* 4:2:2 */ + case IMGFMT_YVYU: + case IMGFMT_UYVY: OUTREG(VIDEO_FORMAT, (vf & ~0xF000) | 0xB000); break; + case IMGFMT_YUY2: + default: OUTREG(VIDEO_FORMAT, (vf & ~0xF000) | 0xC000); break; + } +// OUTPLL(PLL_SCALER_LOCK_EN, 0); + if(__verbose > 1) mach64_vid_dump_regs(); +} + +static int mach64_vid_init_video( vidix_playback_t *config ) +{ + uint32_t src_w,src_h,dest_w,dest_h,pitch,h_inc,v_inc,left,leftUV,top,ecp; + int is_420,best_pitch,mpitch; + mach64_vid_stop_video(); + left = config->src.x << 16; + top = config->src.y << 16; + src_h = config->src.h; + src_w = config->src.w; + is_420 = 0; + if(config->fourcc == IMGFMT_YV12 || + config->fourcc == IMGFMT_I420 || + config->fourcc == IMGFMT_IYUV) is_420 = 1; + best_pitch = mach64_query_pitch(config->fourcc,&config->src.pitch); + mpitch = best_pitch-1; + switch(config->fourcc) + { + /* 4:2:0 */ + case IMGFMT_IYUV: + case IMGFMT_YV12: + case IMGFMT_I420: pitch = (src_w + mpitch) & ~mpitch; + config->dest.pitch.y = + config->dest.pitch.u = + config->dest.pitch.v = best_pitch; + break; + /* RGB 4:4:4:4 */ + case IMGFMT_RGB32: + case IMGFMT_BGR32: pitch = (src_w*4 + mpitch) & ~mpitch; + config->dest.pitch.y = + config->dest.pitch.u = + config->dest.pitch.v = best_pitch; + break; + /* 4:2:2 */ + default: /* RGB15, RGB16, YVYU, UYVY, YUY2 */ + pitch = ((src_w*2) + mpitch) & ~mpitch; + config->dest.pitch.y = + config->dest.pitch.u = + config->dest.pitch.v = best_pitch; + break; + } + dest_w = config->dest.w; + dest_h = config->dest.h; + besr.fourcc = config->fourcc; + ecp = (INPLL(PLL_VCLK_CNTL) & PLL_ECP_DIV) >> 4; + v_inc = (src_h << (12 + +(mach64_is_interlace()?1:0) + -(mach64_is_dbl_scan()?1:0) + )) / dest_h; + h_inc = (src_w << (12+ecp)) / dest_w; + v_inc /= 2; + /* keep everything in 16.16 */ + config->offsets[0] = 0; + config->offsets[1] = config->frame_size; + if(is_420) + { + uint32_t d1line,d2line,d3line; + d1line = top*pitch; + d2line = src_h*pitch+(d1line>>2); + d3line = d2line+((src_h*pitch)>>2); + d1line += (left >> 16) & ~15; + d2line += (left >> 17) & ~15; + d3line += (left >> 17) & ~15; + config->offset.y = d1line & ~15; + config->offset.v = d2line & ~15; + config->offset.u = d3line & ~15; + besr.vid_buf0_base_adrs=((mach64_overlay_offset+config->offsets[0]+config->offset.y)&~15); + besr.vid_buf1_base_adrs=((mach64_overlay_offset+config->offsets[0]+config->offset.v)&~15); + besr.vid_buf2_base_adrs=((mach64_overlay_offset+config->offsets[0]+config->offset.u)&~15); + besr.vid_buf3_base_adrs=((mach64_overlay_offset+config->offsets[1]+config->offset.y)&~15); + besr.vid_buf4_base_adrs=((mach64_overlay_offset+config->offsets[1]+config->offset.v)&~15); + besr.vid_buf5_base_adrs=((mach64_overlay_offset+config->offsets[1]+config->offset.u)&~15); + config->offset.y = ((besr.vid_buf0_base_adrs)&~15) - mach64_overlay_offset; + config->offset.v = ((besr.vid_buf1_base_adrs)&~15) - mach64_overlay_offset; + config->offset.u = ((besr.vid_buf2_base_adrs)&~15) - mach64_overlay_offset; + if(besr.fourcc == IMGFMT_I420 || besr.fourcc == IMGFMT_IYUV) + { + uint32_t tmp; + tmp = config->offset.u; + config->offset.u = config->offset.v; + config->offset.v = tmp; + } + } + else + { + besr.vid_buf0_base_adrs = mach64_overlay_offset; + config->offset.y = config->offset.u = config->offset.v = ((left & ~7) << 1)&~15; + besr.vid_buf0_base_adrs += config->offset.y; + besr.vid_buf1_base_adrs = besr.vid_buf0_base_adrs; + besr.vid_buf2_base_adrs = besr.vid_buf0_base_adrs; + besr.vid_buf3_base_adrs = besr.vid_buf0_base_adrs+config->frame_size; + besr.vid_buf4_base_adrs = besr.vid_buf0_base_adrs+config->frame_size; + besr.vid_buf5_base_adrs = besr.vid_buf0_base_adrs+config->frame_size; + } + + leftUV = (left >> 17) & 15; + left = (left >> 16) & 15; + besr.scale_inc = ( h_inc << 16 ) | v_inc; + besr.y_x_start = config->dest.y | (config->dest.x << 16); + besr.y_x_end = (config->dest.y + dest_h) | ((config->dest.x + dest_w) << 16); + besr.height_width = ((src_w - left)<<16) | (src_h - top); + besr.vid_buf_pitch = pitch; + return 0; +} + + +uint32_t supported_fourcc[] = +{ + IMGFMT_YV12, IMGFMT_I420, IMGFMT_IYUV, + IMGFMT_UYVY, IMGFMT_YUY2, IMGFMT_YVYU +}; + +__inline__ static int is_supported_fourcc(uint32_t fourcc) +{ + unsigned i; + for(i=0;i<sizeof(supported_fourcc)/sizeof(uint32_t);i++) + { + if(fourcc==supported_fourcc[i]) return 1; + } + return 0; +} + int vixQueryFourcc(vidix_fourcc_t *to) { - UNUSED(to); + if(is_supported_fourcc(to->fourcc)) + { + to->depth = VID_DEPTH_1BPP | VID_DEPTH_2BPP | + VID_DEPTH_4BPP | VID_DEPTH_8BPP | + VID_DEPTH_12BPP| VID_DEPTH_15BPP| + VID_DEPTH_16BPP| VID_DEPTH_24BPP| + VID_DEPTH_32BPP; + to->flags = VID_CAP_EXPAND | VID_CAP_SHRINK; + return 0; + } + else to->depth = to->flags = 0; return ENOSYS; } int vixConfigPlayback(vidix_playback_t *info) { - UNUSED(info); - return ENOSYS; + if(!is_supported_fourcc(info->fourcc)) return ENOSYS; + if(info->num_frames>2) info->num_frames=2; + if(info->num_frames==1) besr.double_buff=0; + else besr.double_buff=1; + mach64_compute_framesize(info); + mach64_overlay_offset = mach64_ram_size - info->frame_size*info->num_frames; + mach64_overlay_offset &= 0xffff0000; + if(mach64_overlay_offset < 0) return EINVAL; + info->dga_addr = (char *)mach64_mem_base + mach64_overlay_offset; + mach64_vid_init_video(info); + return 0; } int vixPlaybackOn(void) { - return ENOSYS; + mach64_vid_display_video(); + return 0; } int vixPlaybackOff(void) { - return ENOSYS; + mach64_vid_stop_video(); + return 0; +} + +static void mach64_wait_vsync( void ) +{ +#warning MACH64 VSYNC WAS NOT IMPLEMENTED!!! } int vixPlaybackFrameSelect(unsigned int frame) { - UNUSED(frame); - return ENOSYS; + uint32_t off[6]; + /* + buf3-5 always should point onto second buffer for better + deinterlacing and TV-in + */ + if(!besr.double_buff) return 0; + if((frame%2)) + { + off[0] = besr.vid_buf3_base_adrs; + off[1] = besr.vid_buf4_base_adrs; + off[2] = besr.vid_buf5_base_adrs; + off[3] = besr.vid_buf0_base_adrs; + off[4] = besr.vid_buf1_base_adrs; + off[5] = besr.vid_buf2_base_adrs; + } + else + { + off[0] = besr.vid_buf0_base_adrs; + off[1] = besr.vid_buf1_base_adrs; + off[2] = besr.vid_buf2_base_adrs; + off[3] = besr.vid_buf3_base_adrs; + off[4] = besr.vid_buf4_base_adrs; + off[5] = besr.vid_buf5_base_adrs; + } + + mach64_wait_vsync(); + mach64_wait_for_idle(); + mach64_fifo_wait(7); + OUTREG(SCALER_BUF0_OFFSET, off[0]); + OUTREG(SCALER_BUF0_OFFSET_U, off[1]); + OUTREG(SCALER_BUF0_OFFSET_V, off[2]); + OUTREG(SCALER_BUF1_OFFSET, off[3]); + OUTREG(SCALER_BUF1_OFFSET_U, off[4]); + OUTREG(SCALER_BUF1_OFFSET_V, off[5]); + if(__verbose > 1) mach64_vid_dump_regs(); + return 0; } + +vidix_video_eq_t equal = +{ + VEQ_CAP_BRIGHTNESS | VEQ_CAP_SATURATION + , + 0, 0, 0, 0, 0, 0, 0, 0 }; + +int vixPlaybackGetEq( vidix_video_eq_t * eq) +{ + memcpy(eq,&equal,sizeof(vidix_video_eq_t)); + return 0; +} + +int vixPlaybackSetEq( const vidix_video_eq_t * eq) +{ + int br,sat; + if(eq->cap & VEQ_CAP_BRIGHTNESS) equal.brightness = eq->brightness; + if(eq->cap & VEQ_CAP_CONTRAST) equal.contrast = eq->contrast; + if(eq->cap & VEQ_CAP_SATURATION) equal.saturation = eq->saturation; + if(eq->cap & VEQ_CAP_HUE) equal.hue = eq->hue; + if(eq->cap & VEQ_CAP_RGB_INTENSITY) + { + equal.red_intensity = eq->red_intensity; + equal.green_intensity = eq->green_intensity; + equal.blue_intensity = eq->blue_intensity; + } + equal.flags = eq->flags; + br = equal.brightness * 64 / 1000; + if(br < -64) br = -64; if(br > 63) br = 63; + sat = (equal.saturation + 1000) * 16 / 1000; + if(sat < 0) sat = 0; if(sat > 31) sat = 31; + OUTREG(SCALER_COLOUR_CNTL, (br & 0x7f) | (sat << 8) | (sat << 16)); + return 0; +}