diff options
Diffstat (limited to 'vidix/radeon_vid.c')
-rw-r--r-- | vidix/radeon_vid.c | 2101 |
1 files changed, 2101 insertions, 0 deletions
diff --git a/vidix/radeon_vid.c b/vidix/radeon_vid.c new file mode 100644 index 0000000000..3b3031be80 --- /dev/null +++ b/vidix/radeon_vid.c @@ -0,0 +1,2101 @@ +/* + 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 "../libavutil/common.h" +#include "../mpbswap.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; +#ifdef WORDS_BIGENDIAN +static uint32_t SAVED_CONFIG_CNTL = 0; +#if defined(RAGE128) +#define APER_0_BIG_ENDIAN_16BPP_SWAP (1<<0) +#define APER_0_BIG_ENDIAN_32BPP_SWAP (2<<0) +#else +#define RADEON_SURFACE_CNTL 0x0b00 +#define RADEON_NONSURF_AP0_SWP_16BPP (1 << 20) +#define RADEON_NONSURF_AP0_SWP_32BPP (1 << 21) +#endif +#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,(uint8_t*)(radeon_mmio_base),addr) +#define OUTREG8(addr,val) SETREG(uint8_t,(uint8_t*)(radeon_mmio_base),addr,val) + +static inline uint32_t INREG (uint32_t addr) { + uint32_t tmp = GETREG(uint32_t,(uint8_t*)(radeon_mmio_base),addr); + return le2me_32(tmp); +} +//#define OUTREG(addr,val) SETREG(uint32_t,(uint8_t*)(radeon_mmio_base),addr,val) +#define OUTREG(addr,val) SETREG(uint32_t,(uint8_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; +} + +/* get flat panel x resolution*/ +static uint32_t radeon_get_fp_xres( void ){ + uint32_t xres=(INREG(FP_HORZ_STRETCH)&0x00fff000)>>16; + xres=(xres+1)*8; + return xres; +} + +/* get flat panel y resolution*/ +static uint32_t radeon_get_fp_yres( void ){ + uint32_t yres=(INREG(FP_VERT_STRETCH)&0x00fff000)>>12; + 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_QM, + 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_RV370_5B60_RADEON, + 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_RV280_RADEON_92006, + DEVICE_ATI_RADEON_R300_ND, + DEVICE_ATI_RADEON_R300_NE, + DEVICE_ATI_RADEON_R300_NF, + DEVICE_ATI_RADEON_R300_NG, + DEVICE_ATI_RADEON_R300_AE, + DEVICE_ATI_RADEON_R300_AF, + DEVICE_ATI_RADEON_RV350_AP, + DEVICE_ATI_RADEON_RV350_AQ, + DEVICE_ATI_RADEON_RV350_AR, + DEVICE_ATI_RADEON_RV350_BK, + DEVICE_ATI_RADEON_R350_AH, + DEVICE_ATI_RADEON_R350_AI, + DEVICE_ATI_RADEON_R350_NH, + DEVICE_ATI_RADEON_R360_NJ, + 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 +static void probe_fireGL_driver(void) { + Display *dp = XOpenDisplay ((void*)0); + int n = 0; + char **extlist; + if (dp==NULL) { + return; + } + 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 0 + if ((lst[i].command & PCI_COMMAND_IO) == 0) + { + printf("[radeon] Device is disabled, ignoring\n"); + continue; + } +#endif +#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_QM: + 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: + case DEVICE_ATI_RV280_RADEON_92006: + 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: + case DEVICE_ATI_RADEON_R300_AE: + case DEVICE_ATI_RADEON_R300_AF: + RadeonFamily = 300; + break; + + /* Radeon 9600/9800 */ + case DEVICE_ATI_RV370_5B60_RADEON: + case DEVICE_ATI_RADEON_RV350_AP: + case DEVICE_ATI_RADEON_RV350_AQ: + case DEVICE_ATI_RADEON_RV350_AR: + case DEVICE_ATI_RADEON_RV350_BK: + case DEVICE_ATI_RADEON_R350_NH: + case DEVICE_ATI_RADEON_R350_AH: + case DEVICE_ATI_RADEON_R350_AI: + case DEVICE_ATI_RADEON_R360_NJ: + 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"); < |