?? mach64_vid.c
字號:
}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 + -