⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mach64_vid.c

📁 原名叫avifile
💻 C
📖 第 1 页 / 共 3 页
字号:
}int VIDIX_NAME(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("[mach64] Error occured 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(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");	}	if(idx != -1) is_agp = ati_card_ids[idx].is_agp;	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);  }}typedef struct saved_regs_s{    uint32_t overlay_video_key_clr;    uint32_t overlay_video_key_msk;    uint32_t overlay_graphics_key_clr;    uint32_t overlay_graphics_key_msk;    uint32_t overlay_key_cntl;    uint32_t bus_cntl;}saved_regs_t;static saved_regs_t savreg;static void save_regs( void ){    mach64_fifo_wait(6);    savreg.overlay_video_key_clr	= INREG(OVERLAY_VIDEO_KEY_CLR);    savreg.overlay_video_key_msk	= INREG(OVERLAY_VIDEO_KEY_MSK);    savreg.overlay_graphics_key_clr	= INREG(OVERLAY_GRAPHICS_KEY_CLR);    savreg.overlay_graphics_key_msk	= INREG(OVERLAY_GRAPHICS_KEY_MSK);    savreg.overlay_key_cntl		= INREG(OVERLAY_KEY_CNTL);    savreg.bus_cntl			= INREG(BUS_CNTL);}static void restore_regs( void ){    mach64_fifo_wait(6);    OUTREG(OVERLAY_VIDEO_KEY_CLR,savreg.overlay_video_key_clr);    OUTREG(OVERLAY_VIDEO_KEY_MSK,savreg.overlay_video_key_msk);    OUTREG(OVERLAY_GRAPHICS_KEY_CLR,savreg.overlay_graphics_key_clr);    OUTREG(OVERLAY_GRAPHICS_KEY_MSK,savreg.overlay_graphics_key_msk);    OUTREG(OVERLAY_KEY_CNTL,savreg.overlay_key_cntl);    OUTREG(BUS_CNTL,savreg.bus_cntl|BUS_MASTER_DIS);}static int forced_irq=INT_MAX;static int can_use_irq=0;static int irq_installed=0;static void init_irq(void){	irq_installed=1;	if(forced_irq != INT_MAX) pci_info.irq=forced_irq;	if(hwirq_install(pci_info.bus,pci_info.card,pci_info.func,			 2,CRTC_INT_CNTL,CRTC_BUSMASTER_EOL_INT) == 0)	{	    can_use_irq=1;	    if(__verbose) printf("[mach64] Will use %u irq line\n",pci_info.irq);	}	else 	    if(__verbose) printf("[mach64] Can't initialize irq handling: %s\n"				 "[mach64]irq_param: line=%u pin=%u gnt=%u lat=%u\n"				 ,strerror(errno)				 ,pci_info.irq,pci_info.ipin,pci_info.gnt,pci_info.lat);}int VIDIX_NAME(vixInit)(const char *args){  int err;  unsigned i;  if(!probed)  {    printf("[mach64] Driver was not probed but is being initializing\n");    return EINTR;  }  if(__verbose>0) printf("[mach64] version %d args='%s'\n", VIDIX_VERSION,args);  if(args)  if(strncmp(args,"irq=",4) == 0)   {    forced_irq=atoi(&args[4]);    if(__verbose>0) printf("[mach64] forcing IRQ to %u\n",forced_irq);       }  if((mach64_mmio_base = map_phys_mem(pci_info.base2,0x4000))==(void *)-1) return ENOMEM;  mach64_wait_for_idle();  mach64_ram_size = INREG(MEM_CNTL) & CTL_MEM_SIZEB;  if (mach64_ram_size < 8) mach64_ram_size = (mach64_ram_size + 1) * 512;  else if (mach64_ram_size < 12) mach64_ram_size = (mach64_ram_size - 3) * 1024;  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_regs();  /* 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;  }  printf("[mach64] Planar YUV formats are %s supported\n",supports_planar?"":"not");  supports_colour_adj=0;  OUTREG(SCALER_COLOUR_CNTL,-1);  if(INREG(SCALER_COLOUR_CNTL)) supports_colour_adj=1;  supports_idct=0;  OUTREG(IDCT_CONTROL,-1);  if(INREG(IDCT_CONTROL)) supports_idct=1;  OUTREG(IDCT_CONTROL,0);  printf("[mach64] IDCT is %s supported\n",supports_idct?"":"not");  supports_subpic=0;  OUTREG(SUBPIC_CNTL,-1);  if(INREG(SUBPIC_CNTL)) supports_subpic=1;  OUTREG(SUBPIC_CNTL,0);  printf("[mach64] subpictures are %s supported\n",supports_subpic?"":"not");  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();#ifdef MACH64_ENABLE_BM  if(!(INREG(BUS_CNTL) & BUS_MASTER_DIS))		OUTREG(BUS_CNTL,INREG(BUS_CNTL)|BUS_MSTR_RESET);  if(bm_open() == 0)  {	mach64_cap.flags |= FLAG_DMA | FLAG_EQ_DMA;	if((dma_phys_addrs = malloc(mach64_ram_size*sizeof(unsigned long)/4096)) == 0)	{	    out_mem:	    printf("[mach64] Can't allocate temporary buffer for DMA\n");	    mach64_cap.flags &= ~FLAG_DMA & ~FLAG_EQ_DMA;	    return 0;	}	/*	    WARNING: We MUST have continigous descriptors!!!	    But: (720*720*2(YUV422)*16(sizeof(bm_descriptor)))/4096=4050	    Thus one 4K page is far enough to describe max movie size.	*/	for(i=0;i<64;i++)	    if((mach64_dma_desc_base[i] = memalign(4096,mach64_ram_size*sizeof(bm_list_descriptor)/4096)) == 0)		goto out_mem;#if 0	if(!is_agp)	{	    long tst;	    if(pci_config_read(pci_info.bus,pci_info.card,pci_info.func,4,4,&pci_command) == 0)		pci_config_write(pci_info.bus,pci_info.card,pci_info.func,4,4,pci_command|0x14);	    pci_config_read(pci_info.bus,pci_info.card,pci_info.func,4,4,&tst);	}#endif  }  else    if(__verbose) printf("[mach64] Can't initialize busmastering: %s\n",strerror(errno));#endif  return 0;}void VIDIX_NAME(vixDestroy)(void){  unsigned i;  restore_regs();#ifdef MACH64_ENABLE_BM  mach64_engine_reset();#endif  unmap_phys_mem(mach64_mem_base,mach64_ram_size);  unmap_phys_mem(mach64_mmio_base,0x4000);#ifdef MACH64_ENABLE_BM  bm_close();  if(can_use_irq && irq_installed) hwirq_uninstall(pci_info.bus,pci_info.card,pci_info.func);  if(dma_phys_addrs) free(dma_phys_addrs);  for(i=0;i<64;i++)   {    if(mach64_dma_desc_base[i]) free(mach64_dma_desc_base[i]);  }#endif}int VIDIX_NAME(vixGetCapability)(vidix_capability_t *to){    memcpy(to, &mach64_cap, sizeof(vidix_capability_t));    return 0;}static unsigned mach64_query_pitch(unsigned fourcc,const vidix_yuv_t *spitch){  unsigned pitch,spy,spv,spu;  spy = spv = spu = 0;  switch(spitch->y)  {    case 16:    case 32:    case 64:    case 128:    case 256: spy = spitch->y; break;    default: break;  }  switch(spitch->u)  {    case 16:    case 32:    case 64:    case 128:    case 256: spu = spitch->u; break;    default: break;  }  switch(spitch->v)  {    case 16:    case 32:    case 64:    case 128:    case 256: spv = spitch->v; break;    default: break;  }  switch(fourcc)  {	/* 4:2:0 */	case IMGFMT_IYUV:	case IMGFMT_YV12:	case IMGFMT_I420:		if(spy > 16 && spu == spy/2 && spv == spy/2)	pitch = spy;		else						pitch = 32;		break;	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 void mach64_compute_framesize(vidix_playback_t *info){  unsigned pitch,awidth;  pitch = mach64_query_pitch(info->fourcc,&info->src.pitch);  switch(info->fourcc)  {    case IMGFMT_I420:    case IMGFMT_YV12:    case IMGFMT_IYUV:		awidth = (info->src.w + (pitch-1)) & ~(pitch-1);		info->frame_size = awidth*(info->src.h+info->src.h/2);		break;    case IMGFMT_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;  }  info->frame_size+=256; // so we have some space for alignment & such  info->frame_size&=~16;}static void mach64_vid_stop_video( void ){    mach64_fifo_wait(14);    OUTREG(OVERLAY_SCALE_CNTL, 0x80000000);    OUTREG(OVERLAY_EXCLUSIVE_HORZ, 0);    OUTREG(OVERLAY_EXCLUSIVE_VERT, 0);    OUTREG(SCALER_H_COEFF0, 0x00002000);    OUTREG(SCALER_H_COEFF1, 0x0D06200D);    OUTREG(SCALER_H_COEFF2, 0x0D0A1C0D);    OUTREG(SCALER_H_COEFF3, 0x0C0E1A0C);    OUTREG(SCALER_H_COEFF4, 0x0C14140C);    OUTREG(VIDEO_FORMAT, 0xB000B);    OUTREG(OVERLAY_TEST, 0x0);}static void mach64_vid_display_video( void ){    uint32_t vf,sc,width;    mach64_fifo_wait(14);    OUTREG(OVERLAY_Y_X_START,			besr.y_x_start);    OUTREG(OVERLAY_Y_X_END,			besr.y_x_end);    OUTREG(OVERLAY_SCALE_INC,			besr.scale_inc);    OUTREG(SCALER_BUF_PITCH,			besr.vid_buf_pitch);    OUTREG(SCALER_HEIGHT_WIDTH,			besr.height_width);    OUTREG(SCALER_BUF0_OFFSET,			mach64_buffer_base[0][0]);    OUTREG(SCALER_BUF0_OFFSET_U,		mach64_buffer_base[0][1]);    OUTREG(SCALER_BUF0_OFFSET_V,		mach64_buffer_base[0][2]);    OUTREG(SCALER_BUF1_OFFSET,			mach64_buffer_base[0][0]);    OUTREG(SCALER_BUF1_OFFSET_U,		mach64_buffer_base[0][1]);    OUTREG(SCALER_BUF1_OFFSET_V,		mach64_buffer_base[0][2]);    mach64_wait_vsync();    width = (besr.height_width >> 16 & 0x03FF);    sc = 	SCALE_EN | OVERLAY_EN | 		SCALE_BANDWIDTH | /* reset bandwidth status */		SCALE_PIX_EXPAND | /* dynamic range correct */		SCALE_Y2R_TEMP; /* use the equal temparature for every component of RGB */    /* Force clocks of scaler. */    if(width > 360 && !supports_planar && !mach64_is_interlace())	     sc |= SCALE_CLK_FORCE_ON;    /* Do we need that? And how we can improve the quality of 3dRageII scaler ?       3dRageII+ (non pro) is really crapped HW :(       ^^^^^^^^^^^^^^^^^^^	!!SCALER_WIDTH <= 360 provides full scaling functionality !!!!!!!!!!!!!	!!360 < SCALER_WIDTH <= 720 provides scaling with vertical replication (crap)	!!SCALER_WIDTH > 720 is illegal. (no comments)	       As for me - I would prefer to limit movie's width with 360 but it provides only       half of picture but with perfect quality. (NK) */    mach64_fifo_wait(10);    OUTREG(OVERLAY_SCALE_CNTL, sc);    mach64_wait_for_idle();    switch(besr.fourcc)    {	/* BGR formats */	case IMGFMT_BGR15: vf = SCALER_IN_RGB15;  break;	case IMGFMT_BGR16: vf = SCALER_IN_RGB16;  break;	case IMGFMT_BGR32: vf = SCALER_IN_RGB32;  break;        /* 4:2:0 */	case IMGFMT_IYUV:	case IMGFMT_I420:	case IMGFMT_YV12:  vf = SCALER_IN_YUV12;  break;	/* 4:1:0 */	case IMGFMT_YVU9:  vf = SCALER_IN_YUV9;  break;        /* 4:2:2 */        case IMGFMT_YVYU:	case IMGFMT_UYVY:  vf = SCALER_IN_YVYU422; break;	case IMGFMT_YUY2:	default:           vf = SCALER_IN_VYUY422; break;    }    OUTREG(VIDEO_FORMAT,vf);    if(__verbose > VERBOSE_LEVEL) mach64_vid_dump_regs();}/* Goal of this function: hide RGB background and provide black screen around movie.   Useful in '-vo fbdev:vidix -fs -zoom' mode.   Reverse effect to colorkey */static void mach64_vid_exclusive( void ){    unsigned screenw,screenh;    screenw = mach64_get_xres();    screenh = mach64_get_yres();    OUTREG(OVERLAY_EXCLUSIVE_VERT,(((screenh-1)<<16)&EXCLUSIVE_VERT_END));    OUTREG(OVERLAY_EXCLUSIVE_HORZ,(((screenw/8+1)<<8)&EXCLUSIVE_HORZ_END)|EXCLUSIVE_EN);}static void mach64_vid_non_exclusive( void ){    OUTREG(OVERLAY_EXCLUSIVE_HORZ,0);}static int mach64_vid_init_video( vidix_playback_t *config ){    uint32_t src_w,src_h,dest_w,dest_h,pitch,h_inc,v_inc,left,leftUV,top,ecp,y_pos;    int is_420,best_pitch,mpitch;    int src_offset_y, src_offset_u, src_offset_v;    unsigned int i;    mach64_vid_stop_video();/* warning, if left or top are != 0 this will fail, as the framesize is too small then */    left = config->src.x;    top =  config->src.y;    src_h = config->src.h;    src_w = config->src.w;    is_420 = 0;    if(config->fourcc == IMGFMT_YV12 ||       config->fourcc == IMGFMT_I420 ||       config->fourcc == IMGFMT_IYUV) is_420 = 1;    best_pitch = mach64_query_pitch(config->fourcc,&config->src.pitch);    mpitch = best_pitch-1;    switch(config->fourcc)    {	case IMGFMT_YVU9:	/* 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;			  besr.vid_buf_pitch= 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;			  besr.vid_buf_pitch= pitch>>2;			  break;	/* 4:2:2 */        default: /* RGB15, RGB16, YVYU, UYVY, YUY2 */			  pitch = ((src_w*2) + mpitch) & ~mpitch;			  config->dest.pitch.y =			  config->dest.pitch.u =

⌨️ 快捷键说明

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