mach64_vid.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,080 行 · 第 1/2 页

C
1,080
字号
/* * VIDIX driver for ATI Mach64 and 3DRage chipsets. * Copyright (C) 2002 Nick Kurshev * * This file is part of MPlayer. * * MPlayer is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * MPlayer is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MPlayer; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * This file is based on sources from *  GATOS (gatos.sf.net) and X11 (www.xfree86.org) */#include <errno.h>#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include <math.h>#include <inttypes.h>#include <fcntl.h>#include "config.h"#include "libavutil/common.h"#include "mpbswap.h"#include "vidix.h"#include "vidixlib.h"#include "fourcc.h"#include "dha.h"#include "pci_ids.h"#include "pci_names.h"#include "mach64.h"#undef memcpy#define memcpy uc_memcpy#define UNUSED(x) ((void)(x)) /**< Removes warning about unused arguments */static 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[10][3];static int num_mach64_buffers=-1;static int supports_planar=0;static int supports_lcd_v_stretch=0;static pciinfo_t pci_info;static int probed = 0;static int __verbose = 0;#define VERBOSE_LEVEL 1typedef 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;/* 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)};/* have to restore it on exit */static uint32_t SAVED_OVERLAY_GRAPHICS_KEY_CLR;/* 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,(uint8_t *)mach64_mmio_base,((addr)^0x100)<<2)#define OUTREG8(addr,val)	SETREG(uint8_t,(uint8_t *)mach64_mmio_base,((addr)^0x100)<<2,val)static inline uint32_t INREG (uint32_t addr) {	uint32_t tmp = GETREG(uint32_t,(uint8_t *)mach64_mmio_base,((addr)^0x100)<<2);	return le2me_32(tmp);}#define OUTREG(addr,val)	SETREG(uint32_t,(uint8_t *)mach64_mmio_base,((addr)^0x100)<<2,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__ 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_fifo_wait(unsigned n) {    while ((INREG(FIFO_STAT) & 0xffff) > ((uint32_t)(0x8000 >> n)));}static void mach64_wait_for_idle( void ) {    mach64_fifo_wait(16);    while ((INREG(GUI_STAT) & 1)!= 0);}static 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(void){  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();	printf("[mach64] %s = %08X\n",vregs[i].sname,INREG(vregs[i].name));  }  printf("[mach64] *** End of OV0 registers dump ***\n");}static unsigned short ati_card_ids[] = { DEVICE_ATI_215CT_MACH64_CT, DEVICE_ATI_210888CX_MACH64_CX, DEVICE_ATI_210888ET_MACH64_ET, DEVICE_ATI_MACH64_VT, DEVICE_ATI_210888GX_MACH64_GX, DEVICE_ATI_264LT_MACH64_LT, DEVICE_ATI_264VT_MACH64_VT, DEVICE_ATI_264VT3_MACH64_VT3, DEVICE_ATI_264VT4_MACH64_VT4, /**/ DEVICE_ATI_3D_RAGE_PRO, DEVICE_ATI_3D_RAGE_PRO2, DEVICE_ATI_3D_RAGE_PRO3, DEVICE_ATI_3D_RAGE_PRO4, DEVICE_ATI_RAGE_XC, DEVICE_ATI_RAGE_XL_AGP, DEVICE_ATI_RAGE_XC_AGP, DEVICE_ATI_RAGE_XL, DEVICE_ATI_3D_RAGE_PRO5, DEVICE_ATI_3D_RAGE_PRO6, DEVICE_ATI_RAGE_XL2, DEVICE_ATI_RAGE_XC2, DEVICE_ATI_3D_RAGE_I_II, DEVICE_ATI_3D_RAGE_II, DEVICE_ATI_3D_RAGE_IIC, DEVICE_ATI_3D_RAGE_IIC2, DEVICE_ATI_3D_RAGE_IIC3, DEVICE_ATI_3D_RAGE_IIC4, DEVICE_ATI_3D_RAGE_LT, DEVICE_ATI_3D_RAGE_LT2, DEVICE_ATI_3D_RAGE_LT_G, DEVICE_ATI_3D_RAGE_LT3, DEVICE_ATI_RAGE_MOBILITY_P_M, DEVICE_ATI_RAGE_MOBILITY_L, DEVICE_ATI_3D_RAGE_LT4, DEVICE_ATI_3D_RAGE_LT5, DEVICE_ATI_RAGE_MOBILITY_P_M2, DEVICE_ATI_RAGE_MOBILITY_L2};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 int mach64_probe(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("[mach64] 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("[mach64] Found chip: %s\n",dname);#if 0	if ((lst[i].command & PCI_COMMAND_IO) == 0)	{		printf("[mach64] Device is disabled, ignoring\n");		continue;	}#endif	if(force > PROBE_NORMAL)	{	    printf("[mach64] Driver was forced. Was found %sknown chip\n",idx == -1 ? "un" : "");	    if(idx == -1)		printf("[mach64] Assuming it as Mach64\n");	}	mach64_cap.device_id = lst[i].device;	err = 0;	memcpy(&pci_info,&lst[i],sizeof(pciinfo_t));	probed=1;	break;      }    }  }  if(err && verbose) printf("[mach64] Can't find chip\n");  return err;}static void reset_regs( void ){  size_t i;  for(i=0;i<sizeof(vregs)/sizeof(video_registers_t);i++)  {	mach64_fifo_wait(2);	OUTREG(vregs[i].name,0);  }}static int mach64_init(void){  int err;  if(!probed)  {    printf("[mach64] Driver was not probed but is being initializing\n");    return EINTR;  }  if(__verbose>0) printf("[mach64] version %d\n", VIDIX_VERSION);    if((mach64_mmio_base = map_phys_mem(pci_info.base2,0x1000))==(void *)-1) return ENOMEM;  mach64_wait_for_idle();  mach64_ram_size = INREG(MEM_CNTL) & CTL_MEM_SIZEB;  if (mach64_ram_size < 8) mach64_ram_size = (mach64_ram_size + 1) * 512;  else if (mach64_ram_size < 12) mach64_ram_size = (mach64_ram_size - 3) * 1024;  else mach64_ram_size = (mach64_ram_size - 7) * 2048;  mach64_ram_size *= 0x400; /* KB -> bytes */  if((mach64_mem_base = map_phys_mem(pci_info.base0,mach64_ram_size))==(void *)-1) return ENOMEM;  memset(&besr,0,sizeof(bes_registers_t));  printf("[mach64] Video memory = %uMb\n",mach64_ram_size/0x100000);  err = mtrr_set_type(pci_info.base0,mach64_ram_size,MTRR_TYPE_WRCOMB);  if(!err) printf("[mach64] Set write-combining type of video memory\n");  /* save this */  mach64_wait_for_idle();  SAVED_OVERLAY_GRAPHICS_KEY_CLR = INREG(OVERLAY_GRAPHICS_KEY_CLR);    /* check if planar formats are supported */  supports_planar=0;  mach64_wait_for_idle();  mach64_fifo_wait(2);  if(INREG(SCALER_BUF0_OFFSET_U)) supports_planar=1;  else  {	OUTREG(SCALER_BUF0_OFFSET_U,	-1);	mach64_wait_vsync();	mach64_wait_for_idle();	mach64_fifo_wait(2);	if(INREG(SCALER_BUF0_OFFSET_U)) 	supports_planar=1;  }  if(supports_planar)	printf("[mach64] Planar YUV formats are supported :)\n");  else			printf("[mach64] Planar YUV formats are not supported :(\n");    if(   mach64_cap.device_id==DEVICE_ATI_RAGE_MOBILITY_P_M     || mach64_cap.device_id==DEVICE_ATI_RAGE_MOBILITY_P_M2     || mach64_cap.device_id==DEVICE_ATI_RAGE_MOBILITY_L     || mach64_cap.device_id==DEVICE_ATI_RAGE_MOBILITY_L2)         supports_lcd_v_stretch=1;  else         supports_lcd_v_stretch=0;    reset_regs();  mach64_vid_make_default();  if(__verbose > VERBOSE_LEVEL) mach64_vid_dump_regs();  return 0;}static void mach64_destroy(void){  /*restore this*/  mach64_wait_for_idle();  OUTREG(OVERLAY_GRAPHICS_KEY_CLR,SAVED_OVERLAY_GRAPHICS_KEY_CLR);    unmap_phys_mem(mach64_mem_base,mach64_ram_size);  unmap_phys_mem(mach64_mmio_base,0x1000);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?