?? mach64_vid.c
字號(hào):
/* mach64_vid - VIDIX based video driver for Mach64 and 3DRage chips 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 IS IN BETTA STAGE*/#include "../../config.h"#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <math.h>#include <inttypes.h>#include <fcntl.h>#include <limits.h>#include <sys/mman.h> /* for m(un)lock */#ifdef HAVE_MALLOC_H#include <malloc.h>#ifdef HAVE_MEMALIGN#define MACH64_ENABLE_BM 1#endif#endif#include "../../config.h"#include "../../bswap.h"#include "../vidix.h"#include "../fourcc.h"#include "../../libdha/libdha.h"#include "../../libdha/pci_ids.h"#include "../../libdha/pci_names.h"#include "mach64.h"#define UNUSED(x) ((void)(x)) /**< Removes warning about unused arguments */#define VIDIX_STATIC mach64_#ifdef MACH64_ENABLE_BM#define cpu_to_le32(a) (a)#define VIRT_TO_CARD(a,b,c) bm_virt_to_bus(a,b,c)#pragma pack(1)typedef struct{ uint32_t framebuf_offset; uint32_t sys_addr; uint32_t command; uint32_t reserved;} bm_list_descriptor;#pragma pack()static void *mach64_dma_desc_base[64];static unsigned long bus_addr_dma_desc = 0;static unsigned long *dma_phys_addrs;#endifstatic void *mach64_mmio_base = 0;static void *mach64_mem_base = 0;static int32_t mach64_overlay_offset = 0;static uint32_t mach64_ram_size = 0;static uint32_t mach64_buffer_base[64][3];static int num_mach64_buffers=-1;static int supports_planar=0;static int supports_colour_adj=0;static int supports_idct=0;static int supports_subpic=0;static int supports_lcd_v_stretch=0;pciinfo_t pci_info;static int probed = 0;static int __verbose = 0;#define VERBOSE_LEVEL 2typedef 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 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 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;/* Graphic keys */static vidix_grkey_t mach64_grkey;#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), DECLARE_VREG(BUS_CNTL), DECLARE_VREG(SRC_CNTL), DECLARE_VREG(GUI_STAT), DECLARE_VREG(BM_ADDR), DECLARE_VREG(BM_DATA), DECLARE_VREG(BM_HOSTDATA), DECLARE_VREG(BM_GUI_TABLE_CMD), DECLARE_VREG(BM_FRAME_BUF_OFFSET), DECLARE_VREG(BM_SYSTEM_MEM_ADDR), DECLARE_VREG(BM_COMMAND), DECLARE_VREG(BM_STATUS), DECLARE_VREG(BM_GUI_TABLE), DECLARE_VREG(BM_SYSTEM_TABLE), DECLARE_VREG(AGP_BASE), DECLARE_VREG(AGP_CNTL), DECLARE_VREG(CRTC_INT_CNTL)};/* 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)static inline uint32_t INREG (uint32_t addr) { uint32_t tmp = GETREG(uint32_t,(uint32_t)mach64_mmio_base,((addr)^0x100)<<2); return le2me_32(tmp);}#define OUTREG(addr,val) SETREG(uint32_t,(uint32_t)mach64_mmio_base,((addr)^0x100)<<2,me2le_32(val))#define OUTREGP(addr,val,mask) \ do { \ unsigned int _tmp = INREG(addr); \ _tmp &= (mask); \ _tmp |= (val); \ OUTREG(addr, _tmp); \ } while (0)static __inline__ int ATIGetMach64LCDReg(int _Index){ OUTREG8(LCD_INDEX, _Index); return INREG(LCD_DATA);}static __inline__ uint32_t INPLL(uint32_t addr){ uint32_t res; uint32_t in; in= INREG(CLOCK_CNTL); in &= ~((PLL_WR_EN | PLL_ADDR)); //clean some stuff OUTREG(CLOCK_CNTL, in | (addr<<10)); /* read the register value */ res = (INREG(CLOCK_CNTL)>>16)&0xFF; return res;}static __inline__ void OUTPLL(uint32_t addr,uint32_t val){//FIXME buggy but its not used /* 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); \ _tmp &= (mask); \ _tmp |= (val); \ OUTPLL(addr, _tmp); \ } while (0) static void mach64_engine_reset( void ){ /* Kill off bus mastering with extreme predjudice... */ OUTREG(BUS_CNTL, INREG(BUS_CNTL) | BUS_MASTER_DIS); OUTREG(CRTC_INT_CNTL,INREG(CRTC_INT_CNTL)&~(CRTC_BUSMASTER_EOL_INT|CRTC_BUSMASTER_EOL_INT_EN)); /* Reset engine -- This is accomplished by setting bit 8 of the GEN_TEST_CNTL register high, then low (per the documentation, it's on high to low transition that the GUI engine gets reset...) */ OUTREG( GEN_TEST_CNTL, INREG( GEN_TEST_CNTL ) | GEN_GUI_EN ); OUTREG( GEN_TEST_CNTL, INREG( GEN_TEST_CNTL ) & ~GEN_GUI_EN );}static void mach64_fifo_wait(unsigned n) { while ((INREG(FIFO_STAT) & 0xffff) > ((uint32_t)(0x8000 >> n)));}static void mach64_wait_for_idle( void ) { unsigned i; mach64_fifo_wait(16); for (i=0; i<2000000; i++) if((INREG(GUI_STAT) & GUI_ACTIVE) == 0) break; if((INREG(GUI_STAT) & 1) != 0) mach64_engine_reset(); /* due card lookup */}static void mach64_wait_vsync( void ){ int i; for(i=0; i<2000000; i++) if( (INREG(CRTC_INT_CNTL)&CRTC_VBLANK)==0 ) break; for(i=0; i<2000000; i++) if( (INREG(CRTC_INT_CNTL)&CRTC_VBLANK) ) break;}static vidix_capability_t mach64_cap ={ "BES driver for Mach64/3DRage cards", "Nick Kurshev and Michael Niedermayer", TYPE_OUTPUT, { 0, 0, 0, 0 }, 2048, 2048, 4, 4, -1, FLAG_UPSCALER|FLAG_DOWNSCALER, VENDOR_ATI, -1, { 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;}// returns the verical stretch factor in 16.16static int mach64_get_vert_stretch(void){ int lcd_index; int vert_stretching; int ext_vert_stretch; int ret; int yres= mach64_get_yres(); if(!supports_lcd_v_stretch){ if(__verbose>0) printf("[mach64] vertical stretching not supported\n"); return 1<<16; } lcd_index= INREG(LCD_INDEX); vert_stretching= ATIGetMach64LCDReg(LCD_VERT_STRETCHING); if(!(vert_stretching&VERT_STRETCH_EN)) ret= 1<<16; else { int panel_size; ext_vert_stretch= ATIGetMach64LCDReg(LCD_EXT_VERT_STRETCH); panel_size= (ext_vert_stretch&VERT_PANEL_SIZE)>>11; panel_size++; ret= ((yres<<16) + (panel_size>>1))/panel_size; } // lcd_gen_ctrl = ATIGetMach64LCDReg(LCD_GEN_CNTL); OUTREG(LCD_INDEX, lcd_index); if(__verbose>0) printf("[mach64] vertical stretching factor= %d\n", ret); return ret;}static void mach64_vid_make_default(){ mach64_fifo_wait(5); OUTREG(SCALER_COLOUR_CNTL,0x00101000); besr.ckey_on=0; besr.graphics_key_msk=0; besr.graphics_key_clr=0; OUTREG(OVERLAY_GRAPHICS_KEY_MSK, besr.graphics_key_msk); OUTREG(OVERLAY_GRAPHICS_KEY_CLR, besr.graphics_key_clr); OUTREG(OVERLAY_KEY_CNTL,VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_EQ|CMP_MIX_AND);}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(); mach64_fifo_wait(2); printf("[mach64] %s = %08X\n",vregs[i].sname,INREG(vregs[i].name)); } printf("[mach64] *** End of OV0 registers dump ***\n");}unsigned int VIDIX_NAME(vixGetVersion)(void){ return(VIDIX_VERSION);}typedef struct ati_chip_id_s{ unsigned short id; unsigned short is_agp;}ati_chip_id_t;static ati_chip_id_t ati_card_ids[] = { { DEVICE_ATI_215CT_MACH64_CT, 0 }, { DEVICE_ATI_210888CX_MACH64_CX, 0 }, { DEVICE_ATI_210888ET_MACH64_ET, 0 }, { DEVICE_ATI_MACH64_VT, 0 }, { DEVICE_ATI_210888GX_MACH64_GX, 0 }, { DEVICE_ATI_264LT_MACH64_LT, 0 }, { DEVICE_ATI_264VT_MACH64_VT, 0 }, { DEVICE_ATI_264VT3_MACH64_VT3, 0 }, { DEVICE_ATI_264VT4_MACH64_VT4, 0 }, /**/ { DEVICE_ATI_3D_RAGE_PRO, 1 }, { DEVICE_ATI_3D_RAGE_PRO2, 1 }, { DEVICE_ATI_3D_RAGE_PRO3, 0 }, { DEVICE_ATI_3D_RAGE_PRO4, 0 }, { DEVICE_ATI_RAGE_XC, 0 }, { DEVICE_ATI_RAGE_XL_AGP, 1 }, { DEVICE_ATI_RAGE_XC_AGP, 1 }, { DEVICE_ATI_RAGE_XL, 0 }, { DEVICE_ATI_3D_RAGE_PRO5, 0 }, { DEVICE_ATI_3D_RAGE_PRO6, 0 }, { DEVICE_ATI_RAGE_XL2, 0 }, { DEVICE_ATI_RAGE_XC2, 0 }, { DEVICE_ATI_3D_RAGE_I_II, 0 }, { DEVICE_ATI_3D_RAGE_II, 0 }, { DEVICE_ATI_3D_RAGE_IIC, 1 }, { DEVICE_ATI_3D_RAGE_IIC2, 0 }, { DEVICE_ATI_3D_RAGE_IIC3, 0 }, { DEVICE_ATI_3D_RAGE_IIC4, 1 }, { DEVICE_ATI_3D_RAGE_LT, 1 }, { DEVICE_ATI_3D_RAGE_LT2, 1 }, { DEVICE_ATI_3D_RAGE_LT_G, 0 }, { DEVICE_ATI_3D_RAGE_LT3, 0 }, { DEVICE_ATI_RAGE_MOBILITY_P_M, 1 }, { DEVICE_ATI_RAGE_MOBILITY_L, 1 }, { DEVICE_ATI_3D_RAGE_LT4, 0 }, { DEVICE_ATI_3D_RAGE_LT5, 0 }, { DEVICE_ATI_RAGE_MOBILITY_P_M2, 0 }, { DEVICE_ATI_RAGE_MOBILITY_L2, 0 }};static int is_agp;static int find_chip(unsigned chip_id){ unsigned i; for(i = 0;i < sizeof(ati_card_ids)/sizeof(ati_chip_id_t);i++) { if(chip_id == ati_card_ids[i].id) return i; } return -1;
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -