Mercurial > mplayer.hg
view vidix/drivers/radeon_vid.c @ 12334:eeddcef4fb08
"hard" frame duplication for mencoder. this finally makes it possible
to generate valid mpeg output from avi's that have duplicate frames in
them, or when using inverse telecine filters. to use it, put the
"harddup" filter at the end of your filter chain.
author | rfelker |
---|---|
date | Wed, 28 Apr 2004 04:02:46 +0000 |
parents | b52e831261b1 |
children | a84160d660af |
line wrap: on
line source
/* radeon_vid - VIDIX based video driver for Radeon and Rage128 chips Copyrights 2002 Nick Kurshev. This file is based on sources from GATOS (gatos.sf.net) and X11 (www.xfree86.org) Licence: GPL 31.12.2002 added support for fglrx drivers by Marcel Naziri (zwobbl@zwobbl.de) 6.04.2004 fixes to allow compiling vidix without X11 (broken in original patch) PPC support by Alex Beregszaszi */ #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <inttypes.h> #include "../../config.h" #include "../../bswap.h" #include "../../libdha/pci_ids.h" #include "../../libdha/pci_names.h" #include "../vidix.h" #include "../fourcc.h" #include "../../libdha/libdha.h" #include "radeon.h" #ifdef HAVE_X11 #include <X11/Xlib.h> #endif #ifdef RAGE128 #define RADEON_MSG "[rage128]" #define X_ADJUST 0 #else #define RADEON_MSG "[radeon]" #define X_ADJUST (is_shift_required ? 8 : 0) #ifndef RADEON #define RADEON #endif #endif static int __verbose = 0; #ifdef RADEON static int is_shift_required = 0; #endif typedef struct bes_registers_s { /* base address of yuv framebuffer */ uint32_t yuv_base; uint32_t fourcc; uint32_t dest_bpp; /* YUV BES registers */ uint32_t reg_load_cntl; uint32_t h_inc; uint32_t step_by; uint32_t y_x_start; uint32_t y_x_end; uint32_t v_inc; uint32_t p1_blank_lines_at_top; uint32_t p23_blank_lines_at_top; uint32_t vid_buf_pitch0_value; uint32_t vid_buf_pitch1_value; uint32_t p1_x_start_end; uint32_t p2_x_start_end; uint32_t p3_x_start_end; uint32_t base_addr; uint32_t vid_buf_base_adrs_y[VID_PLAY_MAXFRAMES]; uint32_t vid_buf_base_adrs_u[VID_PLAY_MAXFRAMES]; uint32_t vid_buf_base_adrs_v[VID_PLAY_MAXFRAMES]; uint32_t vid_nbufs; uint32_t p1_v_accum_init; uint32_t p1_h_accum_init; uint32_t p23_v_accum_init; uint32_t p23_h_accum_init; 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; uint32_t ckey_cntl; int deinterlace_on; uint32_t deinterlace_pattern; } bes_registers_t; typedef struct video_registers_s { const char * sname; uint32_t name; uint32_t value; }video_registers_t; static bes_registers_t besr; #ifndef RAGE128 static int RadeonFamily=100; #endif #define DECLARE_VREG(name) { #name, name, 0 } static video_registers_t vregs[] = { DECLARE_VREG(VIDEOMUX_CNTL), DECLARE_VREG(VIPPAD_MASK), DECLARE_VREG(VIPPAD1_A), DECLARE_VREG(VIPPAD1_EN), DECLARE_VREG(VIPPAD1_Y), DECLARE_VREG(OV0_Y_X_START), DECLARE_VREG(OV0_Y_X_END), DECLARE_VREG(OV0_PIPELINE_CNTL), DECLARE_VREG(OV0_EXCLUSIVE_HORZ), DECLARE_VREG(OV0_EXCLUSIVE_VERT), DECLARE_VREG(OV0_REG_LOAD_CNTL), DECLARE_VREG(OV0_SCALE_CNTL), DECLARE_VREG(OV0_V_INC), DECLARE_VREG(OV0_P1_V_ACCUM_INIT), DECLARE_VREG(OV0_P23_V_ACCUM_INIT), DECLARE_VREG(OV0_P1_BLANK_LINES_AT_TOP), DECLARE_VREG(OV0_P23_BLANK_LINES_AT_TOP), #ifdef RADEON DECLARE_VREG(OV0_BASE_ADDR), #endif DECLARE_VREG(OV0_VID_BUF0_BASE_ADRS), DECLARE_VREG(OV0_VID_BUF1_BASE_ADRS), DECLARE_VREG(OV0_VID_BUF2_BASE_ADRS), DECLARE_VREG(OV0_VID_BUF3_BASE_ADRS), DECLARE_VREG(OV0_VID_BUF4_BASE_ADRS), DECLARE_VREG(OV0_VID_BUF5_BASE_ADRS), DECLARE_VREG(OV0_VID_BUF_PITCH0_VALUE), DECLARE_VREG(OV0_VID_BUF_PITCH1_VALUE), DECLARE_VREG(OV0_AUTO_FLIP_CNTL), DECLARE_VREG(OV0_DEINTERLACE_PATTERN), DECLARE_VREG(OV0_SUBMIT_HISTORY), DECLARE_VREG(OV0_H_INC), DECLARE_VREG(OV0_STEP_BY), DECLARE_VREG(OV0_P1_H_ACCUM_INIT), DECLARE_VREG(OV0_P23_H_ACCUM_INIT), DECLARE_VREG(OV0_P1_X_START_END), DECLARE_VREG(OV0_P2_X_START_END), DECLARE_VREG(OV0_P3_X_START_END), DECLARE_VREG(OV0_FILTER_CNTL), DECLARE_VREG(OV0_FOUR_TAP_COEF_0), DECLARE_VREG(OV0_FOUR_TAP_COEF_1), DECLARE_VREG(OV0_FOUR_TAP_COEF_2), DECLARE_VREG(OV0_FOUR_TAP_COEF_3), DECLARE_VREG(OV0_FOUR_TAP_COEF_4), DECLARE_VREG(OV0_FLAG_CNTL), #ifdef RAGE128 DECLARE_VREG(OV0_COLOUR_CNTL), #else DECLARE_VREG(OV0_SLICE_CNTL), #endif DECLARE_VREG(OV0_VID_KEY_CLR), DECLARE_VREG(OV0_VID_KEY_MSK), DECLARE_VREG(OV0_GRAPHICS_KEY_CLR), DECLARE_VREG(OV0_GRAPHICS_KEY_MSK), DECLARE_VREG(OV0_KEY_CNTL), DECLARE_VREG(OV0_TEST), DECLARE_VREG(OV0_LIN_TRANS_A), DECLARE_VREG(OV0_LIN_TRANS_B), DECLARE_VREG(OV0_LIN_TRANS_C), DECLARE_VREG(OV0_LIN_TRANS_D), DECLARE_VREG(OV0_LIN_TRANS_E), DECLARE_VREG(OV0_LIN_TRANS_F), DECLARE_VREG(OV0_GAMMA_0_F), DECLARE_VREG(OV0_GAMMA_10_1F), DECLARE_VREG(OV0_GAMMA_20_3F), DECLARE_VREG(OV0_GAMMA_40_7F), DECLARE_VREG(OV0_GAMMA_380_3BF), DECLARE_VREG(OV0_GAMMA_3C0_3FF), DECLARE_VREG(SUBPIC_CNTL), DECLARE_VREG(SUBPIC_DEFCOLCON), DECLARE_VREG(SUBPIC_Y_X_START), DECLARE_VREG(SUBPIC_Y_X_END), DECLARE_VREG(SUBPIC_V_INC), DECLARE_VREG(SUBPIC_H_INC), DECLARE_VREG(SUBPIC_BUF0_OFFSET), DECLARE_VREG(SUBPIC_BUF1_OFFSET), DECLARE_VREG(SUBPIC_LC0_OFFSET), DECLARE_VREG(SUBPIC_LC1_OFFSET), DECLARE_VREG(SUBPIC_PITCH), DECLARE_VREG(SUBPIC_BTN_HLI_COLCON), DECLARE_VREG(SUBPIC_BTN_HLI_Y_X_START), DECLARE_VREG(SUBPIC_BTN_HLI_Y_X_END), DECLARE_VREG(SUBPIC_PALETTE_INDEX), DECLARE_VREG(SUBPIC_PALETTE_DATA), DECLARE_VREG(SUBPIC_H_ACCUM_INIT), DECLARE_VREG(SUBPIC_V_ACCUM_INIT), DECLARE_VREG(IDCT_RUNS), DECLARE_VREG(IDCT_LEVELS), DECLARE_VREG(IDCT_AUTH_CONTROL), DECLARE_VREG(IDCT_AUTH), DECLARE_VREG(IDCT_CONTROL), DECLARE_VREG(CONFIG_CNTL) }; #ifdef HAVE_X11 static uint32_t firegl_shift = 0; #endif static void * radeon_mmio_base = 0; static void * radeon_mem_base = 0; static int32_t radeon_overlay_off = 0; static uint32_t radeon_ram_size = 0; /* Restore on exit */ static uint32_t SAVED_OV0_GRAPHICS_KEY_CLR = 0; static uint32_t SAVED_OV0_GRAPHICS_KEY_MSK = 0; static uint32_t SAVED_OV0_VID_KEY_CLR = 0; static uint32_t SAVED_OV0_VID_KEY_MSK = 0; static uint32_t SAVED_OV0_KEY_CNTL = 0; #if defined(RAGE128) && (WORDS_BIGENDIAN) static uint32_t SAVED_CONFIG_CNTL = 0; #define APER_0_BIG_ENDIAN_16BPP_SWAP (1<<0) #define APER_0_BIG_ENDIAN_32BPP_SWAP (2<<0) #endif #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)(radeon_mmio_base),addr) #define OUTREG8(addr,val) SETREG(uint8_t,(uint32_t)(radeon_mmio_base),addr,val) static inline uint32_t INREG (uint32_t addr) { uint32_t tmp = GETREG(uint32_t,(uint32_t)(radeon_mmio_base),addr); return le2me_32(tmp); } //#define OUTREG(addr,val) SETREG(uint32_t,(uint32_t)(radeon_mmio_base),addr,val) #define OUTREG(addr,val) SETREG(uint32_t,(uint32_t)(radeon_mmio_base),addr,le2me_32(val)) #define OUTREGP(addr,val,mask) \ do { \ unsigned int _tmp = INREG(addr); \ _tmp &= (mask); \ _tmp |= (val); \ OUTREG(addr, _tmp); \ } while (0) static __inline__ uint32_t INPLL(uint32_t addr) { OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000001f); return (INREG(CLOCK_CNTL_DATA)); } #define OUTPLL(addr,val) OUTREG8(CLOCK_CNTL_INDEX, (addr & 0x0000001f) | 0x00000080); \ OUTREG(CLOCK_CNTL_DATA, val) #define OUTPLLP(addr,val,mask) \ do { \ unsigned int _tmp = INPLL(addr); \ _tmp &= (mask); \ _tmp |= (val); \ OUTPLL(addr, _tmp); \ } while (0) static uint32_t radeon_vid_get_dbpp( void ) { uint32_t dbpp,retval; dbpp = (INREG(CRTC_GEN_CNTL)>>8)& 0xF; switch(dbpp) { case DST_8BPP: retval = 8; break; case DST_15BPP: retval = 15; break; case DST_16BPP: retval = 16; break; case DST_24BPP: retval = 24; break; default: retval=32; break; } return retval; } static int radeon_is_dbl_scan( void ) { return (INREG(CRTC_GEN_CNTL))&CRTC_DBL_SCAN_EN; } static int radeon_is_interlace( void ) { return (INREG(CRTC_GEN_CNTL))&CRTC_INTERLACE_EN; } static uint32_t radeon_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 radeon_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 radeon_wait_vsync(void) { int i; OUTREG(GEN_INT_STATUS, VSYNC_INT_AK); for (i = 0; i < 2000000; i++) { if (INREG(GEN_INT_STATUS) & VSYNC_INT) break; } } #ifdef RAGE128 static void _radeon_engine_idle(void); static void _radeon_fifo_wait(unsigned); #define radeon_engine_idle() _radeon_engine_idle() #define radeon_fifo_wait(entries) _radeon_fifo_wait(entries) /* Flush all dirty data in the Pixel Cache to memory. */ static __inline__ void radeon_engine_flush ( void ) { unsigned i; OUTREGP(PC_NGUI_CTLSTAT, PC_FLUSH_ALL, ~PC_FLUSH_ALL); for (i = 0; i < 2000000; i++) { if (!(INREG(PC_NGUI_CTLSTAT) & PC_BUSY)) break; } } /* Reset graphics card to known state. */ static void radeon_engine_reset( void ) { uint32_t clock_cntl_index; uint32_t mclk_cntl; uint32_t gen_reset_cntl; radeon_engine_flush(); clock_cntl_index = INREG(CLOCK_CNTL_INDEX); mclk_cntl = INPLL(MCLK_CNTL); OUTPLL(MCLK_CNTL, mclk_cntl | FORCE_GCP | FORCE_PIPE3D_CP); gen_reset_cntl = INREG(GEN_RESET_CNTL); OUTREG(GEN_RESET_CNTL, gen_reset_cntl | SOFT_RESET_GUI); INREG(GEN_RESET_CNTL); OUTREG(GEN_RESET_CNTL, gen_reset_cntl & (uint32_t)(~SOFT_RESET_GUI)); INREG(GEN_RESET_CNTL); OUTPLL(MCLK_CNTL, mclk_cntl); OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index); OUTREG(GEN_RESET_CNTL, gen_reset_cntl); } #else static __inline__ void radeon_engine_flush ( void ) { int i; /* initiate flush */ OUTREGP(RB2D_DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL, ~RB2D_DC_FLUSH_ALL); for (i=0; i < 2000000; i++) { if (!(INREG(RB2D_DSTCACHE_CTLSTAT) & RB2D_DC_BUSY)) break; } } static void _radeon_engine_idle(void); static void _radeon_fifo_wait(unsigned); #define radeon_engine_idle() _radeon_engine_idle() #define radeon_fifo_wait(entries) _radeon_fifo_wait(entries) static void radeon_engine_reset( void ) { uint32_t clock_cntl_index, mclk_cntl, rbbm_soft_reset; radeon_engine_flush (); clock_cntl_index = INREG(CLOCK_CNTL_INDEX); mclk_cntl = INPLL(MCLK_CNTL); OUTPLL(MCLK_CNTL, (mclk_cntl | FORCEON_MCLKA | FORCEON_MCLKB | FORCEON_YCLKA | FORCEON_YCLKB | FORCEON_MC | FORCEON_AIC)); rbbm_soft_reset = INREG(RBBM_SOFT_RESET); OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset | SOFT_RESET_CP | SOFT_RESET_HI | SOFT_RESET_SE | SOFT_RESET_RE | SOFT_RESET_PP | SOFT_RESET_E2 | SOFT_RESET_RB | SOFT_RESET_HDP); INREG(RBBM_SOFT_RESET); OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (uint32_t) ~(SOFT_RESET_CP | SOFT_RESET_HI | SOFT_RESET_SE | SOFT_RESET_RE | SOFT_RESET_PP | SOFT_RESET_E2 | SOFT_RESET_RB | SOFT_RESET_HDP)); INREG(RBBM_SOFT_RESET); OUTPLL(MCLK_CNTL, mclk_cntl); OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index); OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset); return; } #endif static void radeon_engine_restore( void ) { #ifndef RAGE128 int pitch64; uint32_t xres,yres,bpp; radeon_fifo_wait(1); xres = radeon_get_xres(); yres = radeon_get_yres(); bpp = radeon_vid_get_dbpp(); /* turn of all automatic flushing - we'll do it all */ OUTREG(RB2D_DSTCACHE_MODE, 0); pitch64 = ((xres * (bpp / 8) + 0x3f)) >> 6; radeon_fifo_wait(1); OUTREG(DEFAULT_OFFSET, (INREG(DEFAULT_OFFSET) & 0xC0000000) | (pitch64 << 22)); radeon_fifo_wait(1); #if defined(WORDS_BIGENDIAN) #ifdef RADEON OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN); #endif #else OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN); #endif radeon_fifo_wait(1); OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX | DEFAULT_SC_BOTTOM_MAX)); radeon_fifo_wait(1); OUTREG(DP_GUI_MASTER_CNTL, (INREG(DP_GUI_MASTER_CNTL) | GMC_BRUSH_SOLID_COLOR | GMC_SRC_DATATYPE_COLOR)); radeon_fifo_wait(7); OUTREG(DST_LINE_START, 0); OUTREG(DST_LINE_END, 0); OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff); OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000); OUTREG(DP_SRC_FRGD_CLR, 0xffffffff); OUTREG(DP_SRC_BKGD_CLR, 0x00000000); OUTREG(DP_WRITE_MASK, 0xffffffff); radeon_engine_idle(); #endif } #ifdef RAGE128 static void _radeon_fifo_wait (unsigned entries) { unsigned i; for(;;) { for (i=0; i<2000000; i++) if ((INREG(GUI_STAT) & GUI_FIFOCNT_MASK) >= entries) return; radeon_engine_reset(); radeon_engine_restore(); } } static void _radeon_engine_idle ( void ) { unsigned i; /* ensure FIFO is empty before waiting for idle */ radeon_fifo_wait (64); for(;;) { for (i=0; i<2000000; i++) { if ((INREG(GUI_STAT) & GUI_ACTIVE) == 0) { radeon_engine_flush (); return; } } radeon_engine_reset(); radeon_engine_restore(); } } #else static void _radeon_fifo_wait (unsigned entries) { unsigned i; for(;;) { for (i=0; i<2000000; i++) if ((INREG(RBBM_STATUS) & RBBM_FIFOCNT_MASK) >= entries) return; radeon_engine_reset(); radeon_engine_restore(); } } static void _radeon_engine_idle ( void ) { int i; /* ensure FIFO is empty before waiting for idle */ radeon_fifo_wait (64); for(;;) { for (i=0; i<2000000; i++) { if (((INREG(RBBM_STATUS) & RBBM_ACTIVE)) == 0) { radeon_engine_flush (); return; } } radeon_engine_reset(); radeon_engine_restore(); } } #endif #ifndef RAGE128 /* Reference color space transform data */ typedef struct tagREF_TRANSFORM { float RefLuma; float RefRCb; float RefRCr; float RefGCb; float RefGCr; float RefBCb; float RefBCr; } REF_TRANSFORM; /* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces */ REF_TRANSFORM trans[2] = { {1.1678, 0.0, 1.6007, -0.3929, -0.8154, 2.0232, 0.0}, /* BT.601 */ {1.1678, 0.0, 1.7980, -0.2139, -0.5345, 2.1186, 0.0} /* BT.709 */ }; /**************************************************************************** * SetTransform * * Function: Calculates and sets color space transform from supplied * * reference transform, gamma, brightness, contrast, hue and * * saturation. * * Inputs: bright - brightness * * cont - contrast * * sat - saturation * * hue - hue * * red_intensity - intense of red component * * green_intensity - intense of green component * * blue_intensity - intense of blue component * * ref - index to the table of refernce transforms * * Outputs: NONE * ****************************************************************************/ static void radeon_set_transform(float bright, float cont, float sat, float hue, float red_intensity, float green_intensity,float blue_intensity, unsigned ref) { float OvHueSin, OvHueCos; float CAdjLuma, CAdjOff; float RedAdj,GreenAdj,BlueAdj; float CAdjRCb, CAdjRCr; float CAdjGCb, CAdjGCr; float CAdjBCb, CAdjBCr; float OvLuma, OvROff, OvGOff, OvBOff; float OvRCb, OvRCr; float OvGCb, OvGCr; float OvBCb, OvBCr; float Loff = 64.0; float Coff = 512.0f; uint32_t dwOvLuma, dwOvROff, dwOvGOff, dwOvBOff; uint32_t dwOvRCb, dwOvRCr; uint32_t dwOvGCb, dwOvGCr; uint32_t dwOvBCb, dwOvBCr; if (ref >= 2) return; OvHueSin = sin((double)hue); OvHueCos = cos((double)hue); CAdjLuma = cont * trans[ref].RefLuma; CAdjOff = cont * trans[ref].RefLuma * bright * 1023.0; RedAdj = cont * trans[ref].RefLuma * red_intensity * 1023.0; GreenAdj = cont * trans[ref].RefLuma * green_intensity * 1023.0; BlueAdj = cont * trans[ref].RefLuma * blue_intensity * 1023.0; CAdjRCb = sat * -OvHueSin * trans[ref].RefRCr; CAdjRCr = sat * OvHueCos * trans[ref].RefRCr; CAdjGCb = sat * (OvHueCos * trans[ref].RefGCb - OvHueSin * trans[ref].RefGCr); CAdjGCr = sat * (OvHueSin * trans[ref].RefGCb + OvHueCos * trans[ref].RefGCr); CAdjBCb = sat * OvHueCos * trans[ref].RefBCb; CAdjBCr = sat * OvHueSin * trans[ref].RefBCb; #if 0 /* default constants */ CAdjLuma = 1.16455078125; CAdjRCb = 0.0; CAdjRCr = 1.59619140625; CAdjGCb = -0.39111328125; CAdjGCr = -0.8125; CAdjBCb = 2.01708984375; CAdjBCr = 0; #endif OvLuma = CAdjLuma; OvRCb = CAdjRCb; OvRCr = CAdjRCr; OvGCb = CAdjGCb; OvGCr = CAdjGCr; OvBCb = CAdjBCb; OvBCr = CAdjBCr; OvROff = RedAdj + CAdjOff - OvLuma * Loff - (OvRCb + OvRCr) * Coff; OvGOff = GreenAdj + CAdjOff - OvLuma * Loff - (OvGCb + OvGCr) * Coff; OvBOff = BlueAdj + CAdjOff - OvLuma * Loff - (OvBCb + OvBCr) * Coff; #if 0 /* default constants */ OvROff = -888.5; OvGOff = 545; OvBOff = -1104; #endif dwOvROff = ((int)(OvROff * 2.0)) & 0x1fff; dwOvGOff = (int)(OvGOff * 2.0) & 0x1fff; dwOvBOff = (int)(OvBOff * 2.0) & 0x1fff; /* Whatever docs say about R200 having 3.8 format instead of 3.11 as in Radeon is a lie */ #if 0 if(RadeonFamily == 100) { #endif dwOvLuma =(((int)(OvLuma * 2048.0))&0x7fff)<<17; dwOvRCb = (((int)(OvRCb * 2048.0))&0x7fff)<<1; dwOvRCr = (((int)(OvRCr * 2048.0))&0x7fff)<<17; dwOvGCb = (((int)(OvGCb * 2048.0))&0x7fff)<<1; dwOvGCr = (((int)(OvGCr * 2048.0))&0x7fff)<<17; dwOvBCb = (((int)(OvBCb * 2048.0))&0x7fff)<<1; dwOvBCr = (((int)(OvBCr * 2048.0))&0x7fff)<<17; #if 0 } else { dwOvLuma = (((int)(OvLuma * 256.0))&0x7ff)<<20; dwOvRCb = (((int)(OvRCb * 256.0))&0x7ff)<<4; dwOvRCr = (((int)(OvRCr * 256.0))&0x7ff)<<20; dwOvGCb = (((int)(OvGCb * 256.0))&0x7ff)<<4; dwOvGCr = (((int)(OvGCr * 256.0))&0x7ff)<<20; dwOvBCb = (((int)(OvBCb * 256.0))&0x7ff)<<4; dwOvBCr = (((int)(OvBCr * 256.0))&0x7ff)<<20; } #endif OUTREG(OV0_LIN_TRANS_A, dwOvRCb | dwOvLuma); OUTREG(OV0_LIN_TRANS_B, dwOvROff | dwOvRCr); OUTREG(OV0_LIN_TRANS_C, dwOvGCb | dwOvLuma); OUTREG(OV0_LIN_TRANS_D, dwOvGOff | dwOvGCr); OUTREG(OV0_LIN_TRANS_E, dwOvBCb | dwOvLuma); OUTREG(OV0_LIN_TRANS_F, dwOvBOff | dwOvBCr); } /* Gamma curve definition */ typedef struct { unsigned int gammaReg; unsigned int gammaSlope; unsigned int gammaOffset; }GAMMA_SETTINGS; /* Recommended gamma curve parameters */ GAMMA_SETTINGS r200_def_gamma[18] = { {OV0_GAMMA_0_F, 0x100, 0x0000}, {OV0_GAMMA_10_1F, 0x100, 0x0020}, {OV0_GAMMA_20_3F, 0x100, 0x0040}, {OV0_GAMMA_40_7F, 0x100, 0x0080}, {OV0_GAMMA_80_BF, 0x100, 0x0100}, {OV0_GAMMA_C0_FF, 0x100, 0x0100}, {OV0_GAMMA_100_13F, 0x100, 0x0200}, {OV0_GAMMA_140_17F, 0x100, 0x0200}, {OV0_GAMMA_180_1BF, 0x100, 0x0300}, {OV0_GAMMA_1C0_1FF, 0x100, 0x0300}, {OV0_GAMMA_200_23F, 0x100, 0x0400}, {OV0_GAMMA_240_27F, 0x100, 0x0400}, {OV0_GAMMA_280_2BF, 0x100, 0x0500}, {OV0_GAMMA_2C0_2FF, 0x100, 0x0500}, {OV0_GAMMA_300_33F, 0x100, 0x0600}, {OV0_GAMMA_340_37F, 0x100, 0x0600}, {OV0_GAMMA_380_3BF, 0x100, 0x0700}, {OV0_GAMMA_3C0_3FF, 0x100, 0x0700} }; GAMMA_SETTINGS r100_def_gamma[6] = { {OV0_GAMMA_0_F, 0x100, 0x0000}, {OV0_GAMMA_10_1F, 0x100, 0x0020}, {OV0_GAMMA_20_3F, 0x100, 0x0040}, {OV0_GAMMA_40_7F, 0x100, 0x0080}, {OV0_GAMMA_380_3BF, 0x100, 0x0100}, {OV0_GAMMA_3C0_3FF, 0x100, 0x0100} }; static void make_default_gamma_correction( void ) { size_t i; if(RadeonFamily == 100) { OUTREG(OV0_LIN_TRANS_A, 0x12A00000); OUTREG(OV0_LIN_TRANS_B, 0x199018FE); OUTREG(OV0_LIN_TRANS_C, 0x12A0F9B0); OUTREG(OV0_LIN_TRANS_D, 0xF2F0043B); OUTREG(OV0_LIN_TRANS_E, 0x12A02050); OUTREG(OV0_LIN_TRANS_F, 0x0000174E); for(i=0; i<6; i++){ OUTREG(r100_def_gamma[i].gammaReg, (r100_def_gamma[i].gammaSlope<<16) | r100_def_gamma[i].gammaOffset); } } else{ OUTREG(OV0_LIN_TRANS_A, 0x12a00000); OUTREG(OV0_LIN_TRANS_B, 0x1990190e); OUTREG(OV0_LIN_TRANS_C, 0x12a0f9c0); OUTREG(OV0_LIN_TRANS_D, 0xf3000442); OUTREG(OV0_LIN_TRANS_E, 0x12a02040); OUTREG(OV0_LIN_TRANS_F, 0x175f); /* Default Gamma, Of 18 segments for gamma cure, all segments in R200 are programmable, while only lower 4 and upper 2 segments are programmable in Radeon*/ for(i=0; i<18; i++){ OUTREG(r200_def_gamma[i].gammaReg, (r200_def_gamma[i].gammaSlope<<16) | r200_def_gamma[i].gammaOffset); } } } #endif static void radeon_vid_make_default(void) { #ifdef RAGE128 OUTREG(OV0_COLOUR_CNTL,0x00101000UL); /* Default brightness and saturation for Rage128 */ #else make_default_gamma_correction(); #endif besr.deinterlace_pattern = 0x900AAAAA; OUTREG(OV0_DEINTERLACE_PATTERN,besr.deinterlace_pattern); besr.deinterlace_on=1; besr.double_buff=1; besr.ckey_on=0; besr.graphics_key_msk=0; besr.graphics_key_clr=0; besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND; } unsigned vixGetVersion( void ) { return VIDIX_VERSION; } static unsigned short ati_card_ids[] = { #ifdef RAGE128 /* This driver should be compatible with Rage128 (pro) chips. (include adaptive deinterlacing!!!). Moreover: the same logic can be used with Mach64 chips. (I mean: mach64xx, 3d rage, 3d rage IIc, 3D rage pro, 3d rage mobility). but they are incompatible by i/o ports. So if enthusiasts will want then they can redefine OUTREG and INREG macros and redefine OV0_* constants. Also it seems that mach64 chips supports only: YUY2, YV12, UYVY fourccs (422 and 420 formats only). */ /* Rage128 Pro GL */ DEVICE_ATI_RAGE_128_PA_PRO, DEVICE_ATI_RAGE_128_PB_PRO, DEVICE_ATI_RAGE_128_PC_PRO, DEVICE_ATI_RAGE_128_PD_PRO, DEVICE_ATI_RAGE_128_PE_PRO, DEVICE_ATI_RAGE_128_PF_PRO, /* Rage128 Pro VR */ DEVICE_ATI_RAGE_128_PG_PRO, DEVICE_ATI_RAGE_128_PH_PRO, DEVICE_ATI_RAGE_128_PI_PRO, DEVICE_ATI_RAGE_128_PJ_PRO, DEVICE_ATI_RAGE_128_PK_PRO, DEVICE_ATI_RAGE_128_PL_PRO, DEVICE_ATI_RAGE_128_PM_PRO, DEVICE_ATI_RAGE_128_PN_PRO, DEVICE_ATI_RAGE_128_PO_PRO, DEVICE_ATI_RAGE_128_PP_PRO, DEVICE_ATI_RAGE_128_PQ_PRO, DEVICE_ATI_RAGE_128_PR_PRO, DEVICE_ATI_RAGE_128_PS_PRO, DEVICE_ATI_RAGE_128_PT_PRO, DEVICE_ATI_RAGE_128_PU_PRO, DEVICE_ATI_RAGE_128_PV_PRO, DEVICE_ATI_RAGE_128_PW_PRO, DEVICE_ATI_RAGE_128_PX_PRO, /* Rage128 GL */ DEVICE_ATI_RAGE_128_RE_SG, DEVICE_ATI_RAGE_128_RF_SG, DEVICE_ATI_RAGE_128_RG, DEVICE_ATI_RAGE_128_RK_VR, DEVICE_ATI_RAGE_128_RL_VR, DEVICE_ATI_RAGE_128_SE_4X, DEVICE_ATI_RAGE_128_SF_4X, DEVICE_ATI_RAGE_128_SG_4X, DEVICE_ATI_RAGE_128_SH, DEVICE_ATI_RAGE_128_SK_4X, DEVICE_ATI_RAGE_128_SL_4X, DEVICE_ATI_RAGE_128_SM_4X, DEVICE_ATI_RAGE_128_4X, DEVICE_ATI_RAGE_128_PRO, DEVICE_ATI_RAGE_128_PRO2, DEVICE_ATI_RAGE_128_PRO3, /* these seem to be based on rage 128 instead of mach64 */ DEVICE_ATI_RAGE_MOBILITY_M3, DEVICE_ATI_RAGE_MOBILITY_M32 #else /* Radeons (indeed: Rage 256 Pro ;) */ DEVICE_ATI_RADEON_R100_QD, DEVICE_ATI_RADEON_R100_QE, DEVICE_ATI_RADEON_R100_QF, DEVICE_ATI_RADEON_R100_QG, DEVICE_ATI_RADEON_VE_QY, DEVICE_ATI_RADEON_VE_QZ, DEVICE_ATI_RADEON_MOBILITY_M7, DEVICE_ATI_RADEON_MOBILITY_M72, DEVICE_ATI_RADEON_MOBILITY_M6, DEVICE_ATI_RADEON_MOBILITY_M62, DEVICE_ATI_RADEON_MOBILITY_U1, DEVICE_ATI_RADEON_R200_BB, DEVICE_ATI_RADEON_R200_QH, DEVICE_ATI_RADEON_R200_QI, DEVICE_ATI_RADEON_R200_QJ, DEVICE_ATI_RADEON_R200_QK, DEVICE_ATI_RADEON_R200_QL, DEVICE_ATI_RADEON_R200_QH2, DEVICE_ATI_RADEON_R200_QI2, DEVICE_ATI_RADEON_R200_QJ2, DEVICE_ATI_RADEON_R200_QK2, DEVICE_ATI_RADEON_RV200_QW, DEVICE_ATI_RADEON_RV200_QX, DEVICE_ATI_RADEON_R250_ID, DEVICE_ATI_RADEON_R250_IE, DEVICE_ATI_RADEON_R250_IF, DEVICE_ATI_RADEON_R250_IG, DEVICE_ATI_RADEON_R250_LD, DEVICE_ATI_RADEON_R250_LE, DEVICE_ATI_RADEON_R250_LF, DEVICE_ATI_RADEON_R250_LG, DEVICE_ATI_RV250_5C61_RADEON, DEVICE_ATI_RV250_5C63_RADEON, DEVICE_ATI_RV280_RADEON_9200, DEVICE_ATI_RV280_RADEON_92002, DEVICE_ATI_RV280_RADEON_92003, DEVICE_ATI_RV280_RADEON_92004, DEVICE_ATI_RV280_RADEON_92005, DEVICE_ATI_RADEON_R300_ND, DEVICE_ATI_RADEON_R300_NE, DEVICE_ATI_RADEON_R300_NF, DEVICE_ATI_RADEON_R300_NG, DEVICE_ATI_RADEON_RV350_AP, DEVICE_ATI_RADEON_R350_NH, DEVICE_ATI_RV350_MOBILITY_RADEON, DEVICE_ATI_RV350_MOBILITY_RADEON2 #endif }; static int find_chip(unsigned chip_id) { unsigned i; for(i = 0;i < sizeof(ati_card_ids)/sizeof(unsigned short);i++) { if(chip_id == ati_card_ids[i]) return i; } return -1; } static pciinfo_t pci_info; static int probed=0; vidix_capability_t def_cap = { #ifdef RAGE128 "BES driver for Rage128 cards", #else "BES driver for Radeon cards", #endif "Nick Kurshev", TYPE_OUTPUT | TYPE_FX, { 0, 0, 0, 0 }, 2048, 2048, 4, 4, -1, FLAG_UPSCALER | FLAG_DOWNSCALER | FLAG_EQUALIZER, VENDOR_ATI, 0, { 0, 0, 0, 0} }; #ifdef HAVE_X11 void probe_fireGL_driver() { Display *dp = XOpenDisplay ((void*)0); int n = 0; char **extlist = XListExtensions (dp, &n); XCloseDisplay (dp); if (extlist) { int i; int ext_fgl = 0, ext_fglrx = 0; for (i = 0; i < n; i++) { if (!strcmp(extlist[i], "ATIFGLEXTENSION")) ext_fgl = 1; if (!strcmp(extlist[i], "ATIFGLRXDRI")) ext_fglrx = 1; } if (ext_fgl) { printf(RADEON_MSG" ATI FireGl driver detected"); firegl_shift = 0x500000; if (!ext_fglrx) { printf(", but DRI seems not to be activated\n"); printf(RADEON_MSG" Output may not work correctly, check your DRI configuration!"); } printf("\n"); } } } #endif int vixProbe( int verbose,int force ) { pciinfo_t lst[MAX_PCI_DEVICES]; unsigned i,num_pci; int err; __verbose = verbose; err = pci_scan(lst,&num_pci); if(err) { printf(RADEON_MSG" Error occurred during pci scan: %s\n",strerror(err)); return err; } else { err = ENXIO; for(i=0;i<num_pci;i++) { if(lst[i].vendor == VENDOR_ATI) { int idx; const char *dname; idx = find_chip(lst[i].device); if(idx == -1 && force == PROBE_NORMAL) continue; dname = pci_device_name(VENDOR_ATI,lst[i].device); dname = dname ? dname : "Unknown chip"; printf(RADEON_MSG" Found chip: %s\n",dname); if ((lst[i].command & PCI_COMMAND_IO) == 0) { printf("[radeon] Device is disabled, ignoring\n"); continue; } #ifndef RAGE128 if(idx != -1) #ifdef HAVE_X11 probe_fireGL_driver(); #endif { switch(ati_card_ids[idx]) { /* Original radeon */ case DEVICE_ATI_RADEON_R100_QD: case DEVICE_ATI_RADEON_R100_QE: case DEVICE_ATI_RADEON_R100_QF: case DEVICE_ATI_RADEON_R100_QG: RadeonFamily = 100; break; /* Radeon VE / Radeon Mobility */ case DEVICE_ATI_RADEON_VE_QY: case DEVICE_ATI_RADEON_VE_QZ: case DEVICE_ATI_RADEON_MOBILITY_M6: case DEVICE_ATI_RADEON_MOBILITY_M62: case DEVICE_ATI_RADEON_MOBILITY_U1: RadeonFamily = 120; break; /* Radeon 7500 / Radeon Mobility 7500 */ case DEVICE_ATI_RADEON_RV200_QW: case DEVICE_ATI_RADEON_RV200_QX: case DEVICE_ATI_RADEON_MOBILITY_M7: case DEVICE_ATI_RADEON_MOBILITY_M72: RadeonFamily = 150; break; /* Radeon 8500 */ case DEVICE_ATI_RADEON_R200_BB: case DEVICE_ATI_RADEON_R200_QH: case DEVICE_ATI_RADEON_R200_QI: case DEVICE_ATI_RADEON_R200_QJ: case DEVICE_ATI_RADEON_R200_QK: case DEVICE_ATI_RADEON_R200_QL: case DEVICE_ATI_RADEON_R200_QH2: case DEVICE_ATI_RADEON_R200_QI2: case DEVICE_ATI_RADEON_R200_QJ2: case DEVICE_ATI_RADEON_R200_QK2: RadeonFamily = 200; break; /* Radeon 9000 */ case DEVICE_ATI_RADEON_R250_ID: case DEVICE_ATI_RADEON_R250_IE: case DEVICE_ATI_RADEON_R250_IF: case DEVICE_ATI_RADEON_R250_IG: case DEVICE_ATI_RADEON_R250_LD: case DEVICE_ATI_RADEON_R250_LE: case DEVICE_ATI_RADEON_R250_LF: case DEVICE_ATI_RADEON_R250_LG: case DEVICE_ATI_RV250_5C61_RADEON: case DEVICE_ATI_RV250_5C63_RADEON: RadeonFamily = 250; break; /* Radeon 9200 */ case DEVICE_ATI_RV280_RADEON_9200: case DEVICE_ATI_RV280_RADEON_92002: case DEVICE_ATI_RV280_RADEON_92003: case DEVICE_ATI_RV280_RADEON_92004: case DEVICE_ATI_RV280_RADEON_92005: RadeonFamily = 280; break; /* Radeon 9700 */ case DEVICE_ATI_RADEON_R300_ND: case DEVICE_ATI_RADEON_R300_NE: case DEVICE_ATI_RADEON_R300_NF: case DEVICE_ATI_RADEON_R300_NG: RadeonFamily = 300; break; /* Radeon 9600/9800 */ case DEVICE_ATI_RADEON_RV350_AP: case DEVICE_ATI_RADEON_R350_NH: case DEVICE_ATI_RV350_MOBILITY_RADEON: case DEVICE_ATI_RV350_MOBILITY_RADEON2: RadeonFamily = 350; break; default: break; } } #endif if(force > PROBE_NORMAL) { printf(RADEON_MSG" Driver was forced. Was found %sknown chip\n",idx == -1 ? "un" : ""); if(idx == -1) #ifdef RAGE128 printf(RADEON_MSG" Assuming it as Rage128\n"); #else printf(RADEON_MSG" Assuming it as Radeon1\n"); #endif } def_cap.device_id = lst[i].device; err = 0; memcpy(&pci_info,&lst[i],sizeof(pciinfo_t)); probed=1; break; } } } if(err && verbose) printf(RADEON_MSG" Can't find chip\n"); return err; } static void radeon_vid_dump_regs( void ); /* forward declaration */ int vixInit( void ) { int err; if(!probed) { printf(RADEON_MSG" Driver was not probed but is being initializing\n"); return EINTR; } if((radeon_mmio_base = map_phys_mem(pci_info.base2,0xFFFF))==(void *)-1) return ENOMEM; radeon_ram_size = INREG(CONFIG_MEMSIZE); /* mem size is bits [28:0], mask off the rest. Range: from 1Mb up to 512 Mb */ radeon_ram_size &= CONFIG_MEMSIZE_MASK; #ifdef RADEON /* according to XFree86 4.2.0, some production M6's return 0 for 8MB */ if (radeon_ram_size == 0 && (def_cap.device_id == DEVICE_ATI_RADEON_MOBILITY_M6 || def_cap.device_id == DEVICE_ATI_RADEON_MOBILITY_M62)) { printf(RADEON_MSG" Workarounding buggy Radeon Mobility M6 (0 vs. 8MB ram)\n"); radeon_ram_size = 8192*1024; } #else /* Rage Mobility (rage128) also has memsize bug */ if (radeon_ram_size == 0 && (def_cap.device_id == DEVICE_ATI_RAGE_MOBILITY_M3 || def_cap.device_id == DEVICE_ATI_RAGE_MOBILITY_M32)) { printf(RADEON_MSG" Workarounding buggy Rage Mobility M3 (0 vs. 8MB ram)\n"); radeon_ram_size = 8192*1024; } #endif #ifdef WIN32 if(radeon_ram_size > 16*1024*1024)radeon_ram_size=16*1024*1024; #endif if((radeon_mem_base = map_phys_mem(pci_info.base0,radeon_ram_size))==(void *)-1) return ENOMEM; memset(&besr,0,sizeof(bes_registers_t)); radeon_vid_make_default(); printf(RADEON_MSG" Video memory = %uMb\n",radeon_ram_size/0x100000); err = mtrr_set_type(pci_info.base0,radeon_ram_size,MTRR_TYPE_WRCOMB); if(!err) printf(RADEON_MSG" Set write-combining type of video memory\n"); radeon_fifo_wait(3); SAVED_OV0_GRAPHICS_KEY_CLR = INREG(OV0_GRAPHICS_KEY_CLR); SAVED_OV0_GRAPHICS_KEY_MSK = INREG(OV0_GRAPHICS_KEY_MSK); SAVED_OV0_VID_KEY_CLR = INREG(OV0_VID_KEY_CLR); SAVED_OV0_VID_KEY_MSK = INREG(OV0_VID_KEY_MSK); SAVED_OV0_KEY_CNTL = INREG(OV0_KEY_CNTL); printf(RADEON_MSG" Saved overlay colorkey settings\n"); #ifdef RADEON switch(RadeonFamily) { case 100: case 120: case 150: case 250: is_shift_required=1; break; default: break; } #endif /* XXX: hack, but it works for me (tm) */ #if defined(RAGE128) && (WORDS_BIGENDIAN) /* code from gatos */ { SAVED_CONFIG_CNTL = INREG(CONFIG_CNTL); OUTREG(CONFIG_CNTL, SAVED_CONFIG_CNTL & ~(APER_0_BIG_ENDIAN_16BPP_SWAP|APER_0_BIG_ENDIAN_32BPP_SWAP)); // printf("saved: %x, current: %x\n", SAVED_CONFIG_CNTL, // INREG(CONFIG_CNTL)); } #endif if(__verbose > 1) radeon_vid_dump_regs(); return 0; } void vixDestroy( void ) { /* remove colorkeying */ radeon_fifo_wait(3); OUTREG(OV0_GRAPHICS_KEY_CLR, SAVED_OV0_GRAPHICS_KEY_CLR); OUTREG(OV0_GRAPHICS_KEY_MSK, SAVED_OV0_GRAPHICS_KEY_MSK); OUTREG(OV0_VID_KEY_CLR, SAVED_OV0_VID_KEY_CLR); OUTREG(OV0_VID_KEY_MSK, SAVED_OV0_VID_KEY_MSK); OUTREG(OV0_KEY_CNTL, SAVED_OV0_KEY_CNTL); printf(RADEON_MSG" Restored overlay colorkey settings\n"); #if defined(RAGE128) && (WORDS_BIGENDIAN) OUTREG(CONFIG_CNTL, SAVED_CONFIG_CNTL); // printf("saved: %x, restored: %x\n", SAVED_CONFIG_CNTL, // INREG(CONFIG_CNTL)); #endif unmap_phys_mem(radeon_mem_base,radeon_ram_size); unmap_phys_mem(radeon_mmio_base,0xFFFF); } int vixGetCapability(vidix_capability_t *to) { memcpy(to,&def_cap,sizeof(vidix_capability_t)); return 0; } /* Full list of fourcc which are supported by Win2K redeon driver: YUY2, UYVY, DDES, OGLT, OGL2, OGLS, OGLB, OGNT, OGNZ, OGNS, IF09, YVU9, IMC4, M2IA, IYUV, VBID, DXT1, DXT2, DXT3, DXT4, DXT5 */ uint32_t supported_fourcc[] = { IMGFMT_Y800, IMGFMT_Y8, IMGFMT_YVU9, IMGFMT_IF09, IMGFMT_YV12, IMGFMT_I420, IMGFMT_IYUV, IMGFMT_UYVY, IMGFMT_YUY2, IMGFMT_YVYU, IMGFMT_RGB15, IMGFMT_BGR15, IMGFMT_RGB16, IMGFMT_BGR16, IMGFMT_RGB32, IMGFMT_BGR32 }; inline static int is_supported_fourcc(uint32_t fourcc) { unsigned int 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) { 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 | VID_CAP_COLORKEY; return 0; } else to->depth = to->flags = 0; return ENOSYS; } static void radeon_vid_dump_regs( void ) { size_t i; printf(RADEON_MSG"*** Begin of DRIVER variables dump ***\n"); printf(RADEON_MSG"radeon_mmio_base=%p\n",radeon_mmio_base); printf(RADEON_MSG"radeon_mem_base=%p\n",radeon_mem_base); printf(RADEON_MSG"radeon_overlay_off=%08X\n",radeon_overlay_off); printf(RADEON_MSG"radeon_ram_size=%08X\n",radeon_ram_size); printf(RADEON_MSG"video mode: %ux%u@%u\n",radeon_get_xres(),radeon_get_yres(),radeon_vid_get_dbpp()); printf(RADEON_MSG"*** Begin of OV0 registers dump ***\n"); for(i=0;i<sizeof(vregs)/sizeof(video_registers_t);i++) printf(RADEON_MSG"%s = %08X\n",vregs[i].sname,INREG(vregs[i].name)); printf(RADEON_MSG"*** End of OV0 registers dump ***\n"); } static void radeon_vid_stop_video( void ) { radeon_engine_idle(); OUTREG(OV0_SCALE_CNTL, SCALER_SOFT_RESET); OUTREG(OV0_EXCLUSIVE_HORZ, 0); OUTREG(OV0_AUTO_FLIP_CNTL, 0); /* maybe */ OUTREG(OV0_FILTER_CNTL, FILTER_HARDCODED_COEF); #ifdef RADEON OUTREG(OV0_KEY_CNTL, GRAPHIC_KEY_FN_EQ); #else OUTREG(OV0_KEY_CNTL, GRAPHIC_KEY_FN_NE); #endif OUTREG(OV0_TEST, 0); } static void radeon_vid_display_video( void ) { int bes_flags; radeon_fifo_wait(2); OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK); radeon_engine_idle(); while(!(INREG(OV0_REG_LOAD_CNTL)®_LD_CTL_LOCK_READBACK)); radeon_fifo_wait(15); /* Shutdown capturing */ OUTREG(FCP_CNTL, FCP_CNTL__GND); OUTREG(CAP0_TRIG_CNTL, 0); OUTREG(VID_BUFFER_CONTROL, (1<<16) | 0x01); OUTREG(DISP_TEST_DEBUG_CNTL, 0); OUTREG(OV0_AUTO_FLIP_CNTL,OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD); if(besr.deinterlace_on) OUTREG(OV0_DEINTERLACE_PATTERN,besr.deinterlace_pattern); #ifdef RAGE128 OUTREG(OV0_COLOUR_CNTL, (((besr.brightness*64)/1000) & 0x7f) | (((besr.saturation*31+31000)/2000) << 8) | (((besr.saturation*31+31000)/2000) << 16)); #endif radeon_fifo_wait(2); OUTREG(OV0_GRAPHICS_KEY_MSK, besr.graphics_key_msk); OUTREG(OV0_GRAPHICS_KEY_CLR, besr.graphics_key_clr); OUTREG(OV0_KEY_CNTL,besr.ckey_cntl); OUTREG(OV0_H_INC, besr.h_inc); OUTREG(OV0_STEP_BY, besr.step_by); OUTREG(OV0_Y_X_START, besr.y_x_start); OUTREG(OV0_Y_X_END, besr.y_x_end); OUTREG(OV0_V_INC, besr.v_inc); OUTREG(OV0_P1_BLANK_LINES_AT_TOP, besr.p1_blank_lines_at_top); OUTREG(OV0_P23_BLANK_LINES_AT_TOP, besr.p23_blank_lines_at_top); OUTREG(OV0_VID_BUF_PITCH0_VALUE, besr.vid_buf_pitch0_value); OUTREG(OV0_VID_BUF_PITCH1_VALUE, besr.vid_buf_pitch1_value); OUTREG(OV0_P1_X_START_END, besr.p1_x_start_end); OUTREG(OV0_P2_X_START_END, besr.p2_x_start_end); OUTREG(OV0_P3_X_START_END, besr.p3_x_start_end); #ifdef RADEON OUTREG(OV0_BASE_ADDR, besr.base_addr); #endif OUTREG(OV0_VID_BUF0_BASE_ADRS, besr.vid_buf_base_adrs_y[0]); OUTREG(OV0_VID_BUF1_BASE_ADRS, besr.vid_buf_base_adrs_v[0]); OUTREG(OV0_VID_BUF2_BASE_ADRS, besr.vid_buf_base_adrs_u[0]); radeon_fifo_wait(9); OUTREG(OV0_VID_BUF3_BASE_ADRS, besr.vid_buf_base_adrs_y[0]); OUTREG(OV0_VID_BUF4_BASE_ADRS, besr.vid_buf_base_adrs_v[0]); OUTREG(OV0_VID_BUF5_BASE_ADRS, besr.vid_buf_base_adrs_u[0]); OUTREG(OV0_P1_V_ACCUM_INIT, besr.p1_v_accum_init); OUTREG(OV0_P1_H_ACCUM_INIT, besr.p1_h_accum_init); OUTREG(OV0_P23_H_ACCUM_INIT, besr.p23_h_accum_init); OUTREG(OV0_P23_V_ACCUM_INIT, besr.p23_v_accum_init); #ifdef RADEON bes_flags = SCALER_ENABLE | SCALER_SMART_SWITCH; // SCALER_HORZ_PICK_NEAREST | // SCALER_VERT_PICK_NEAREST | #endif bes_flags = SCALER_ENABLE | SCALER_SMART_SWITCH | SCALER_Y2R_TEMP | SCALER_PIX_EXPAND; if(besr.double_buff) bes_flags |= SCALER_DOUBLE_BUFFER; if(besr.deinterlace_on) bes_flags |= SCALER_ADAPTIVE_DEINT; #ifdef RAGE128 bes_flags |= SCALER_BURST_PER_PLANE; #endif switch(besr.fourcc) { case IMGFMT_RGB15: case IMGFMT_BGR15: bes_flags |= SCALER_SOURCE_15BPP; break; case IMGFMT_RGB16: case IMGFMT_BGR16: bes_flags |= SCALER_SOURCE_16BPP; break; /* case IMGFMT_RGB24: case IMGFMT_BGR24: bes_flags |= SCALER_SOURCE_24BPP; break; */ case IMGFMT_RGB32: case IMGFMT_BGR32: bes_flags |= SCALER_SOURCE_32BPP; break; /* 4:1:0 */ case IMGFMT_IF09: case IMGFMT_YVU9: bes_flags |= SCALER_SOURCE_YUV9; break; /* 4:0:0 */ case IMGFMT_Y800: case IMGFMT_Y8: /* 4:2:0 */ case IMGFMT_IYUV: case IMGFMT_I420: case IMGFMT_YV12: bes_flags |= SCALER_SOURCE_YUV12; break; /* 4:2:2 */ case IMGFMT_YVYU: case IMGFMT_UYVY: bes_flags |= SCALER_SOURCE_YVYU422; break; case IMGFMT_YUY2: default: bes_flags |= SCALER_SOURCE_VYUY422; break; } OUTREG(OV0_SCALE_CNTL, bes_flags); OUTREG(OV0_REG_LOAD_CNTL, 0); if(__verbose > 1) printf(RADEON_MSG"we wanted: scaler=%08X\n",bes_flags); if(__verbose > 1) radeon_vid_dump_regs(); } static unsigned radeon_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; /* 4:1:0 */ case IMGFMT_IF09: case IMGFMT_YVU9: if(spy > 32 && spu == spy/4 && spv == spy/4) pitch = spy; else pitch = 64; break; default: if(spy >= 16) pitch = spy; else pitch = 16; break; } return pitch; } static int radeon_vid_init_video( vidix_playback_t *config ) { uint32_t i,tmp,src_w,src_h,dest_w,dest_h,pitch,h_inc,step_by,left,leftUV,top; int is_400,is_410,is_420,is_rgb32,is_rgb,best_pitch,mpitch; radeon_vid_stop_video(); left = config->src.x << 16; top = config->src.y << 16; src_h = config->src.h; src_w = config->src.w; is_400 = is_410 = is_420 = is_rgb32 = is_rgb = 0; if(config->fourcc == IMGFMT_YV12 || config->fourcc == IMGFMT_I420 || config->fourcc == IMGFMT_IYUV) is_420 = 1; if(config->fourcc == IMGFMT_YVU9 || config->fourcc == IMGFMT_IF09) is_410 = 1; if(config->fourcc == IMGFMT_Y800 || config->fourcc == IMGFMT_Y8) is_400 = 1; if(config->fourcc == IMGFMT_RGB32 || config->fourcc == IMGFMT_BGR32) is_rgb32 = 1; if(config->fourcc == IMGFMT_RGB32 || config->fourcc == IMGFMT_BGR32 || config->fourcc == IMGFMT_RGB24 || config->fourcc == IMGFMT_BGR24 || config->fourcc == IMGFMT_RGB16 || config->fourcc == IMGFMT_BGR16 || config->fourcc == IMGFMT_RGB15 || config->fourcc == IMGFMT_BGR15) is_rgb = 1; best_pitch = radeon_query_pitch(config->fourcc,&config->src.pitch); mpitch = best_pitch-1; switch(config->fourcc) { /* 4:0:0 */ case IMGFMT_Y800: case IMGFMT_Y8: /* 4:1:0 */ case IMGFMT_YVU9: case IMGFMT_IF09: /* 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; if(radeon_is_dbl_scan()) dest_h *= 2; besr.dest_bpp = radeon_vid_get_dbpp(); besr.fourcc = config->fourcc; besr.v_inc = (src_h << 20) / dest_h; if(radeon_is_interlace()) besr.v_inc *= 2; h_inc = (src_w << 12) / dest_w; { unsigned int ecp_div; ecp_div = (INPLL(VCLK_ECP_CNTL) >> 8) & 3; h_inc <<= ecp_div; } step_by = 1; while(h_inc >= (2 << 12)) { step_by++; h_inc >>= 1; } /* keep everything in 16.16 */ besr.base_addr = INREG(DISPLAY_BASE_ADDR); config->offsets[0] = 0; for(i=1;i<besr.vid_nbufs;i++) config->offsets[i] = config->offsets[i-1]+config->frame_size; if(is_420 || is_410 || is_400) { uint32_t d1line,d2line,d3line; d1line = top*pitch; if(is_420) { d2line = src_h*pitch+(d1line>>2); d3line = d2line+((src_h*pitch)>>2); } else if(is_410) { d2line = src_h*pitch+(d1line>>4); d3line = d2line+((src_h*pitch)>>4); } else { d2line = 0; d3line = 0; } d1line += (left >> 16) & ~15; if(is_420) { d2line += (left >> 17) & ~15; d3line += (left >> 17) & ~15; } else if(is_410) { d2line += (left >> 18) & ~15; d3line += (left >> 18) & ~15; } config->offset.y = d1line & VIF_BUF0_BASE_ADRS_MASK; if(is_400) { config->offset.v = 0; config->offset.u = 0; } else { config->offset.v = d2line & VIF_BUF1_BASE_ADRS_MASK; config->offset.u = d3line & VIF_BUF2_BASE_ADRS_MASK; } for(i=0;i<besr.vid_nbufs;i++) { besr.vid_buf_base_adrs_y[i]=((radeon_overlay_off+config->offsets[i]+config->offset.y)&VIF_BUF0_BASE_ADRS_MASK); if(is_400) { besr.vid_buf_base_adrs_v[i]=0; besr.vid_buf_base_adrs_u[i]=0; } else { if (besr.fourcc == IMGFMT_I420 || besr.fourcc == IMGFMT_IYUV) { besr.vid_buf_base_adrs_u[i]=((radeon_overlay_off+config->offsets[i]+config->offset.v)&VIF_BUF1_BASE_ADRS_MASK)|VIF_BUF1_PITCH_SEL; besr.vid_buf_base_adrs_v[i]=((radeon_overlay_off+config->offsets[i]+config->offset.u)&VIF_BUF2_BASE_ADRS_MASK)|VIF_BUF2_PITCH_SEL; } else { besr.vid_buf_base_adrs_v[i]=((radeon_overlay_off+config->offsets[i]+config->offset.v)&VIF_BUF1_BASE_ADRS_MASK)|VIF_BUF1_PITCH_SEL; besr.vid_buf_base_adrs_u[i]=((radeon_overlay_off+config->offsets[i]+config->offset.u)&VIF_BUF2_BASE_ADRS_MASK)|VIF_BUF2_PITCH_SEL; } } } config->offset.y = ((besr.vid_buf_base_adrs_y[0])&VIF_BUF0_BASE_ADRS_MASK) - radeon_overlay_off; if(is_400) { config->offset.v = 0; config->offset.u = 0; } else { config->offset.v = ((besr.vid_buf_base_adrs_v[0])&VIF_BUF1_BASE_ADRS_MASK) - radeon_overlay_off; config->offset.u = ((besr.vid_buf_base_adrs_u[0])&VIF_BUF2_BASE_ADRS_MASK) - radeon_overlay_off; } } else { config->offset.y = config->offset.u = config->offset.v = ((left & ~7) << 1)&VIF_BUF0_BASE_ADRS_MASK; for(i=0;i<besr.vid_nbufs;i++) { besr.vid_buf_base_adrs_y[i] = besr.vid_buf_base_adrs_u[i] = besr.vid_buf_base_adrs_v[i] = radeon_overlay_off + config->offsets[i] + config->offset.y; } } tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3); besr.p1_h_accum_init = ((tmp << 4) & 0x000f8000) | ((tmp << 12) & 0xf0000000); tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc << 2); besr.p23_h_accum_init = ((tmp << 4) & 0x000f8000) | ((tmp << 12) & 0x70000000); tmp = (top & 0x0000ffff) + 0x00018000; besr.p1_v_accum_init = ((tmp << 4) & OV0_P1_V_ACCUM_INIT_MASK) |(OV0_P1_MAX_LN_IN_PER_LN_OUT & 1); tmp = ((top >> 1) & 0x0000ffff) + 0x00018000; besr.p23_v_accum_init = (is_420||is_410) ? ((tmp << 4) & OV0_P23_V_ACCUM_INIT_MASK) |(OV0_P23_MAX_LN_IN_PER_LN_OUT & 1) : 0; leftUV = (left >> (is_410?18:17)) & 15; left = (left >> 16) & 15; if(is_rgb && !is_rgb32) h_inc<<=1; if(is_rgb32) besr.h_inc = (h_inc >> 1) | ((h_inc >> 1) << 16); else if(is_410) besr.h_inc = h_inc | ((h_inc >> 2) << 16); else besr.h_inc = h_inc | ((h_inc >> 1) << 16); besr.step_by = step_by | (step_by << 8); besr.y_x_start = (config->dest.x+X_ADJUST) | (config->dest.y << 16); besr.y_x_end = (config->dest.x + dest_w+X_ADJUST) | ((config->dest.y + dest_h) << 16); besr.p1_blank_lines_at_top = P1_BLNK_LN_AT_TOP_M1_MASK|((src_h-1)<<16); if(is_420 || is_410) { src_h = (src_h + 1) >> (is_410?2:1); besr.p23_blank_lines_at_top = P23_BLNK_LN_AT_TOP_M1_MASK|((src_h-1)<<16); } else besr.p23_blank_lines_at_top = 0; besr.vid_buf_pitch0_value = pitch; besr.vid_buf_pitch1_value = is_410 ? pitch>>2 : is_420 ? pitch>>1 : pitch; besr.p1_x_start_end = (src_w+left-1)|(left<<16); if (is_410||is_420) src_w>>=is_410?2:1; if(is_400) { besr.p2_x_start_end = 0; besr.p3_x_start_end = 0; } else { besr.p2_x_start_end = (src_w+left-1)|(leftUV<<16); besr.p3_x_start_end = besr.p2_x_start_end; } return 0; } static void radeon_compute_framesize(vidix_playback_t *info) { unsigned pitch,awidth,dbpp; pitch = radeon_query_pitch(info->fourcc,&info->src.pitch); dbpp = radeon_vid_get_dbpp(); 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_Y800: case IMGFMT_Y8: awidth = (info->src.w + (pitch-1)) & ~(pitch-1); info->frame_size = awidth*info->src.h; break; case IMGFMT_IF09: case IMGFMT_YVU9: awidth = (info->src.w + (pitch-1)) & ~(pitch-1); info->frame_size = awidth*(info->src.h+info->src.h/8); 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; } } int vixConfigPlayback(vidix_playback_t *info) { unsigned rgb_size,nfr; if(!is_supported_fourcc(info->fourcc)) return ENOSYS; if(info->num_frames>VID_PLAY_MAXFRAMES) info->num_frames=VID_PLAY_MAXFRAMES; if(info->num_frames==1) besr.double_buff=0; else besr.double_buff=1; radeon_compute_framesize(info); rgb_size = radeon_get_xres()*radeon_get_yres()*((radeon_vid_get_dbpp()+7)/8); nfr = info->num_frames; for(;nfr>0; nfr--) { radeon_overlay_off = radeon_ram_size - info->frame_size*nfr; #ifdef HAVE_X11 radeon_overlay_off -= firegl_shift; #endif radeon_overlay_off &= 0xffff0000; if(radeon_overlay_off >= (int)rgb_size ) break; } if(nfr <= 3) { nfr = info->num_frames; for(;nfr>0; nfr--) { radeon_overlay_off = radeon_ram_size - info->frame_size*nfr; #ifdef HAVE_X11 radeon_overlay_off -= firegl_shift; #endif radeon_overlay_off &= 0xffff0000; if(radeon_overlay_off > 0) break; } } if(nfr <= 0) return EINVAL; info->num_frames = nfr; besr.vid_nbufs = info->num_frames; info->dga_addr = (char *)radeon_mem_base + radeon_overlay_off; radeon_vid_init_video(info); return 0; } int vixPlaybackOn( void ) { radeon_vid_display_video(); return 0; } int vixPlaybackOff( void ) { radeon_vid_stop_video(); return 0; } int vixPlaybackFrameSelect(unsigned frame) { uint32_t off[6]; int prev_frame= (frame-1+besr.vid_nbufs) % besr.vid_nbufs; /* buf3-5 always should point onto second buffer for better deinterlacing and TV-in */ if(!besr.double_buff) return 0; if(frame > besr.vid_nbufs) frame = besr.vid_nbufs-1; if(prev_frame > (int)besr.vid_nbufs) prev_frame = besr.vid_nbufs-1; off[0] = besr.vid_buf_base_adrs_y[frame]; off[1] = besr.vid_buf_base_adrs_v[frame]; off[2] = besr.vid_buf_base_adrs_u[frame]; off[3] = besr.vid_buf_base_adrs_y[prev_frame]; off[4] = besr.vid_buf_base_adrs_v[prev_frame]; off[5] = besr.vid_buf_base_adrs_u[prev_frame]; radeon_fifo_wait(8); OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK); radeon_engine_idle(); while(!(INREG(OV0_REG_LOAD_CNTL)®_LD_CTL_LOCK_READBACK)); OUTREG(OV0_VID_BUF0_BASE_ADRS, off[0]); OUTREG(OV0_VID_BUF1_BASE_ADRS, off[1]); OUTREG(OV0_VID_BUF2_BASE_ADRS, off[2]); OUTREG(OV0_VID_BUF3_BASE_ADRS, off[3]); OUTREG(OV0_VID_BUF4_BASE_ADRS, off[4]); OUTREG(OV0_VID_BUF5_BASE_ADRS, off[5]); OUTREG(OV0_REG_LOAD_CNTL, 0); if(besr.vid_nbufs == 2) radeon_wait_vsync(); if(__verbose > 1) radeon_vid_dump_regs(); return 0; } vidix_video_eq_t equal = { VEQ_CAP_BRIGHTNESS | VEQ_CAP_SATURATION #ifndef RAGE128 | VEQ_CAP_CONTRAST | VEQ_CAP_HUE | VEQ_CAP_RGB_INTENSITY #endif , 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; } #ifndef RAGE128 #define RTFSaturation(a) (1.0 + ((a)*1.0)/1000.0) #define RTFBrightness(a) (((a)*1.0)/2000.0) #define RTFIntensity(a) (((a)*1.0)/2000.0) #define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0) #define RTFHue(a) (((a)*3.1416)/1000.0) #define RTFCheckParam(a) {if((a)<-1000) (a)=-1000; if((a)>1000) (a)=1000;} #endif int vixPlaybackSetEq( const vidix_video_eq_t * eq) { #ifdef RAGE128 int br,sat; #else int itu_space; #endif 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; #ifdef RAGE128 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(OV0_COLOUR_CNTL, (br & 0x7f) | (sat << 8) | (sat << 16)); #else itu_space = equal.flags == VEQ_FLG_ITU_R_BT_709 ? 1 : 0; RTFCheckParam(equal.brightness); RTFCheckParam(equal.saturation); RTFCheckParam(equal.contrast); RTFCheckParam(equal.hue); RTFCheckParam(equal.red_intensity); RTFCheckParam(equal.green_intensity); RTFCheckParam(equal.blue_intensity); radeon_set_transform(RTFBrightness(equal.brightness), RTFContrast(equal.contrast), RTFSaturation(equal.saturation), RTFHue(equal.hue), RTFIntensity(equal.red_intensity), RTFIntensity(equal.green_intensity), RTFIntensity(equal.blue_intensity), itu_space); #endif return 0; } int vixPlaybackSetDeint( const vidix_deinterlace_t * info) { unsigned sflg; switch(info->flags) { default: case CFG_NON_INTERLACED: besr.deinterlace_on = 0; break; case CFG_EVEN_ODD_INTERLACING: case CFG_INTERLACED: besr.deinterlace_on = 1; besr.deinterlace_pattern = 0x900AAAAA; break; case CFG_ODD_EVEN_INTERLACING: besr.deinterlace_on = 1; besr.deinterlace_pattern = 0x00055555; break; case CFG_UNIQUE_INTERLACING: besr.deinterlace_on = 1; besr.deinterlace_pattern = info->deinterlace_pattern; break; } OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK); radeon_engine_idle(); while(!(INREG(OV0_REG_LOAD_CNTL)®_LD_CTL_LOCK_READBACK)); radeon_fifo_wait(15); sflg = INREG(OV0_SCALE_CNTL); if(besr.deinterlace_on) { OUTREG(OV0_SCALE_CNTL,sflg | SCALER_ADAPTIVE_DEINT); OUTREG(OV0_DEINTERLACE_PATTERN,besr.deinterlace_pattern); } else OUTREG(OV0_SCALE_CNTL,sflg & (~SCALER_ADAPTIVE_DEINT)); OUTREG(OV0_REG_LOAD_CNTL, 0); return 0; } int vixPlaybackGetDeint( vidix_deinterlace_t * info) { if(!besr.deinterlace_on) info->flags = CFG_NON_INTERLACED; else { info->flags = CFG_UNIQUE_INTERLACING; info->deinterlace_pattern = besr.deinterlace_pattern; } return 0; } /* Graphic keys */ static vidix_grkey_t radeon_grkey; static void set_gr_key( void ) { if(radeon_grkey.ckey.op == CKEY_TRUE) { int dbpp=radeon_vid_get_dbpp(); besr.ckey_on=1; switch(dbpp) { case 15: #ifdef RADEON if(RadeonFamily > 100) besr.graphics_key_clr= ((radeon_grkey.ckey.blue &0xF8)) | ((radeon_grkey.ckey.green&0xF8)<<8) | ((radeon_grkey.ckey.red &0xF8)<<16); else #endif besr.graphics_key_clr= ((radeon_grkey.ckey.blue &0xF8)>>3) | ((radeon_grkey.ckey.green&0xF8)<<2) | ((radeon_grkey.ckey.red &0xF8)<<7); break; case 16: #ifdef RADEON /* This test may be too general/specific */ if(RadeonFamily > 100) besr.graphics_key_clr= ((radeon_grkey.ckey.blue &0xF8)) | ((radeon_grkey.ckey.green&0xFC)<<8) | ((radeon_grkey.ckey.red &0xF8)<<16); else #endif besr.graphics_key_clr= ((radeon_grkey.ckey.blue &0xF8)>>3) | ((radeon_grkey.ckey.green&0xFC)<<3) | ((radeon_grkey.ckey.red &0xF8)<<8); break; case 24: besr.graphics_key_clr= ((radeon_grkey.ckey.blue &0xFF)) | ((radeon_grkey.ckey.green&0xFF)<<8) | ((radeon_grkey.ckey.red &0xFF)<<16); break; case 32: besr.graphics_key_clr= ((radeon_grkey.ckey.blue &0xFF)) | ((radeon_grkey.ckey.green&0xFF)<<8) | ((radeon_grkey.ckey.red &0xFF)<<16); break; default: besr.ckey_on=0; besr.graphics_key_msk=0; besr.graphics_key_clr=0; } #ifdef RAGE128 besr.graphics_key_msk=(1<<dbpp)-1; besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_NE|CMP_MIX_AND; #else besr.graphics_key_msk=besr.graphics_key_clr; besr.ckey_cntl = VIDEO_KEY_FN_TRUE|CMP_MIX_AND|GRAPHIC_KEY_FN_EQ; #endif } else { besr.ckey_on=0; besr.graphics_key_msk=0; besr.graphics_key_clr=0; besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND; } radeon_fifo_wait(3); OUTREG(OV0_GRAPHICS_KEY_MSK, besr.graphics_key_msk); OUTREG(OV0_GRAPHICS_KEY_CLR, besr.graphics_key_clr); OUTREG(OV0_KEY_CNTL,besr.ckey_cntl); } int vixGetGrKeys(vidix_grkey_t *grkey) { memcpy(grkey, &radeon_grkey, sizeof(vidix_grkey_t)); return(0); } int vixSetGrKeys(const vidix_grkey_t *grkey) { memcpy(&radeon_grkey, grkey, sizeof(vidix_grkey_t)); set_gr_key(); return(0); }