?? mach64_vid.c
字號:
config->dest.pitch.v = best_pitch; besr.vid_buf_pitch= pitch>>1; break; } dest_w = config->dest.w; dest_h = config->dest.h; besr.fourcc = config->fourcc; ecp = (INPLL(PLL_VCLK_CNTL) & PLL_ECP_DIV) >> 4;#if 0{int i;for(i=0; i<32; i++){ printf("%X ", INPLL(i));}}#endif if(__verbose>0) printf("[mach64] ecp: %d\n", ecp); v_inc = src_h * mach64_get_vert_stretch(); if(mach64_is_interlace()) v_inc<<=1; if(mach64_is_dbl_scan() ) v_inc>>=1; v_inc/= dest_h; v_inc>>=4; // convert 16.16 -> 4.12 h_inc = (src_w << (12+ecp)) / dest_w; /* keep everything in 4.12 */ config->offsets[0] = 0; for(i=1; i<config->num_frames; i++) config->offsets[i] = config->offsets[i-1] + config->frame_size; /*FIXME the left / top stuff is broken (= zoom a src rectangle from a larger one) 1. the framesize isnt known as the outer src rectangle dimensions arent known 2. the mach64 needs aligned addresses so it cant work anyway -> so we could shift the outer buffer to compensate that but that would mean alignment problems for the code which writes into it */ if(is_420) { config->offset.y= 0; config->offset.u= (pitch*src_h + 15)&~15; config->offset.v= (config->offset.u + (pitch*src_h>>2) + 15)&~15; src_offset_y= config->offset.y + top*pitch + left; src_offset_u= config->offset.u + (top*pitch>>2) + (left>>1); src_offset_v= config->offset.v + (top*pitch>>2) + (left>>1); if(besr.fourcc == IMGFMT_I420 || besr.fourcc == IMGFMT_IYUV) { uint32_t tmp; tmp = config->offset.u; config->offset.u = config->offset.v; config->offset.v = tmp; src_offset_u=config->offset.u; src_offset_v=config->offset.v; } } else if(besr.fourcc == IMGFMT_YVU9) { config->offset.y= 0; config->offset.u= (pitch*src_h + 15)&~15; config->offset.v= (config->offset.u + (pitch*src_h>>4) + 15)&~15; src_offset_y= config->offset.y + top*pitch + left; src_offset_u= config->offset.u + (top*pitch>>4) + (left>>1); src_offset_v= config->offset.v + (top*pitch>>4) + (left>>1); } else if(besr.fourcc == IMGFMT_BGR32) { config->offset.y = config->offset.u = config->offset.v = 0; src_offset_y= src_offset_u= src_offset_v= top*pitch + (left << 2); } else { config->offset.y = config->offset.u = config->offset.v = 0; src_offset_y= src_offset_u= src_offset_v= top*pitch + (left << 1); } num_mach64_buffers= config->num_frames; for(i=0; i<config->num_frames; i++) { mach64_buffer_base[i][0]= (mach64_overlay_offset + config->offsets[i] + src_offset_y)&~15; mach64_buffer_base[i][1]= (mach64_overlay_offset + config->offsets[i] + src_offset_u)&~15; mach64_buffer_base[i][2]= (mach64_overlay_offset + config->offsets[i] + src_offset_v)&~15; } leftUV = (left >> 17) & 15; left = (left >> 16) & 15; besr.scale_inc = ( h_inc << 16 ) | v_inc; y_pos = config->dest.y; if(mach64_is_dbl_scan()) y_pos*=2; else if(mach64_is_interlace()) y_pos/=2; besr.y_x_start = y_pos | (config->dest.x << 16); y_pos =config->dest.y + dest_h; if(mach64_is_dbl_scan()) y_pos*=2; else if(mach64_is_interlace()) y_pos/=2; besr.y_x_end = y_pos | ((config->dest.x + dest_w) << 16); besr.height_width = ((src_w - left)<<16) | (src_h - top); return 0;}static int is_supported_fourcc(uint32_t fourcc){ switch(fourcc) { case IMGFMT_YV12: case IMGFMT_I420: case IMGFMT_YVU9: case IMGFMT_IYUV: return supports_planar; case IMGFMT_YUY2: case IMGFMT_UYVY: case IMGFMT_BGR15: case IMGFMT_BGR16: case IMGFMT_BGR32: return 1; default: return 0; }}int VIDIX_NAME(vixQueryFourcc)(vidix_fourcc_t *to){ if(is_supported_fourcc(to->fourcc)) { to->depth = VID_DEPTH_1BPP | VID_DEPTH_2BPP | VID_DEPTH_4BPP | VID_DEPTH_8BPP | VID_DEPTH_12BPP| VID_DEPTH_15BPP| VID_DEPTH_16BPP| VID_DEPTH_24BPP| VID_DEPTH_32BPP; to->flags = VID_CAP_EXPAND | VID_CAP_SHRINK | VID_CAP_COLORKEY; return 0; } else to->depth = to->flags = 0; return ENOSYS;}int VIDIX_NAME(vixConfigPlayback)(vidix_playback_t *info){ unsigned rgb_size,nfr; uint32_t mach64_video_size; if(!is_supported_fourcc(info->fourcc)) return ENOSYS; if(info->src.h > 720 || info->src.w > 720) { printf("[mach64] Can't apply width or height > 720\n"); return EINVAL; } if(info->num_frames>VID_PLAY_MAXFRAMES) info->num_frames=VID_PLAY_MAXFRAMES; mach64_compute_framesize(info); rgb_size = mach64_get_xres()*mach64_get_yres()*((mach64_vid_get_dbpp()+7)/8); nfr = info->num_frames; mach64_video_size = mach64_ram_size; for(;nfr>0;nfr--) { mach64_overlay_offset = mach64_video_size - info->frame_size*nfr; mach64_overlay_offset &= 0xffff0000; if(mach64_overlay_offset >= (int)rgb_size ) break; } if(nfr <= 3) { nfr = info->num_frames; for(;nfr>0;nfr--) { mach64_overlay_offset = mach64_video_size - info->frame_size*nfr; mach64_overlay_offset &= 0xffff0000; if(mach64_overlay_offset>=0) break; } } if(nfr <= 0) return EINVAL; info->num_frames=nfr; num_mach64_buffers = info->num_frames; info->dga_addr = (char *)mach64_mem_base + mach64_overlay_offset; mach64_vid_init_video(info); return 0;}int VIDIX_NAME(vixPlaybackOn)(void){ int err; unsigned dw,dh; dw = (besr.y_x_end >> 16) - (besr.y_x_start >> 16); dh = (besr.y_x_end & 0xFFFF) - (besr.y_x_start & 0xFFFF); if(dw == mach64_get_xres() || dh == mach64_get_yres()) mach64_vid_exclusive(); else mach64_vid_non_exclusive(); mach64_vid_display_video(); err = INREG(SCALER_BUF_PITCH) == besr.vid_buf_pitch ? 0 : EINTR; if(err) { printf("[mach64] *** Internal fatal error ***: Detected pitch corruption\n" "[mach64] Try decrease number of buffers\n"); } return err;}int VIDIX_NAME(vixPlaybackOff)(void){ mach64_vid_stop_video(); return 0;}int VIDIX_NAME(vixPlaybackFrameSelect)(unsigned int frame){ uint32_t off[6]; int i; int last_frame= (frame-1+num_mach64_buffers) % num_mach64_buffers; /* buf3-5 always should point onto second buffer for better deinterlacing and TV-in */ if(num_mach64_buffers==1) return 0; for(i=0; i<3; i++) { off[i] = mach64_buffer_base[frame][i]; off[i+3]= mach64_buffer_base[last_frame][i]; } if(__verbose > VERBOSE_LEVEL) printf("mach64_vid: flip_page = %u\n",frame);#if 0 // delay routine so the individual frames can be ssen better{volatile int i=0;for(i=0; i<10000000; i++);}#endif mach64_wait_for_idle(); mach64_fifo_wait(7); OUTREG(SCALER_BUF0_OFFSET, off[0]); OUTREG(SCALER_BUF0_OFFSET_U, off[1]); OUTREG(SCALER_BUF0_OFFSET_V, off[2]); OUTREG(SCALER_BUF1_OFFSET, off[3]); OUTREG(SCALER_BUF1_OFFSET_U, off[4]); OUTREG(SCALER_BUF1_OFFSET_V, off[5]); if(num_mach64_buffers==2) mach64_wait_vsync(); //only wait for vsync if we do double buffering if(__verbose > VERBOSE_LEVEL) mach64_vid_dump_regs(); return 0;}vidix_video_eq_t equal ={ VEQ_CAP_BRIGHTNESS | VEQ_CAP_SATURATION , 0, 0, 0, 0, 0, 0, 0, 0 };int VIDIX_NAME(vixPlaybackGetEq)( vidix_video_eq_t * eq){ memcpy(eq,&equal,sizeof(vidix_video_eq_t)); if(!supports_colour_adj) eq->cap = VEQ_CAP_BRIGHTNESS; return 0;}int VIDIX_NAME(vixPlaybackSetEq)( const vidix_video_eq_t * eq){ int br,sat; if(eq->cap & VEQ_CAP_BRIGHTNESS) equal.brightness = eq->brightness; if(eq->cap & VEQ_CAP_CONTRAST) equal.contrast = eq->contrast; if(eq->cap & VEQ_CAP_SATURATION) equal.saturation = eq->saturation; if(eq->cap & VEQ_CAP_HUE) equal.hue = eq->hue; if(eq->cap & VEQ_CAP_RGB_INTENSITY) { equal.red_intensity = eq->red_intensity; equal.green_intensity = eq->green_intensity; equal.blue_intensity = eq->blue_intensity; } if(supports_colour_adj) { equal.flags = eq->flags; br = equal.brightness * 64 / 1000; if(br < -64) br = -64; if(br > 63) br = 63; sat = (equal.saturation + 1000) * 16 / 1000; if(sat < 0) sat = 0; if(sat > 31) sat = 31; OUTREG(SCALER_COLOUR_CNTL, (br & 0x7f) | (sat << 8) | (sat << 16)); } else { unsigned gamma; br = equal.brightness * 3 / 1000; if(br < 0) br = 0; switch(br) { default:gamma = SCALE_GAMMA_SEL_BRIGHT; break; case 1: gamma = SCALE_GAMMA_SEL_G14; break; case 2: gamma = SCALE_GAMMA_SEL_G18; break; case 3: gamma = SCALE_GAMMA_SEL_G22; break; } OUTREG(OVERLAY_SCALE_CNTL,(INREG(OVERLAY_SCALE_CNTL) & ~SCALE_GAMMA_SEL_MSK) | gamma); } return 0;}int VIDIX_NAME(vixGetGrKeys)(vidix_grkey_t *grkey){ memcpy(grkey, &mach64_grkey, sizeof(vidix_grkey_t)); return(0);}int VIDIX_NAME(vixSetGrKeys)(const vidix_grkey_t *grkey){ memcpy(&mach64_grkey, grkey, sizeof(vidix_grkey_t)); if(mach64_grkey.ckey.op == CKEY_TRUE) { besr.ckey_on=1; switch(mach64_vid_get_dbpp()) { case 15: besr.graphics_key_msk=0x7FFF; besr.graphics_key_clr= ((mach64_grkey.ckey.blue &0xF8)>>3) | ((mach64_grkey.ckey.green&0xF8)<<2) | ((mach64_grkey.ckey.red &0xF8)<<7); break; case 16: besr.graphics_key_msk=0xFFFF; besr.graphics_key_clr= ((mach64_grkey.ckey.blue &0xF8)>>3) | ((mach64_grkey.ckey.green&0xFC)<<3) | ((mach64_grkey.ckey.red &0xF8)<<8); break; case 24: besr.graphics_key_msk=0xFFFFFF; besr.graphics_key_clr= ((mach64_grkey.ckey.blue &0xFF)) | ((mach64_grkey.ckey.green&0xFF)<<8) | ((mach64_grkey.ckey.red &0xFF)<<16); break; case 32: besr.graphics_key_msk=0xFFFFFF; besr.graphics_key_clr= ((mach64_grkey.ckey.blue &0xFF)) | ((mach64_grkey.ckey.green&0xFF)<<8) | ((mach64_grkey.ckey.red &0xFF)<<16); break; default: besr.ckey_on=0; besr.graphics_key_msk=0; besr.graphics_key_clr=0; } } else { besr.ckey_on=0; besr.graphics_key_msk=0; besr.graphics_key_clr=0; } mach64_fifo_wait(4); OUTREG(OVERLAY_GRAPHICS_KEY_MSK, besr.graphics_key_msk); OUTREG(OVERLAY_GRAPHICS_KEY_CLR, besr.graphics_key_clr);// OUTREG(OVERLAY_VIDEO_KEY_MSK, 0);// OUTREG(OVERLAY_VIDEO_KEY_CLR, 0); if(besr.ckey_on) OUTREG(OVERLAY_KEY_CNTL,VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_EQ|CMP_MIX_AND); else OUTREG(OVERLAY_KEY_CNTL,VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND); return(0);}#ifdef MACH64_ENABLE_BMstatic int mach64_setup_frame( vidix_dma_t * dmai ){ if(mach64_overlay_offset + dmai->dest_offset + dmai->size > mach64_ram_size) return E2BIG; if(dmai->idx > VID_PLAY_MAXFRAMES-1) dmai->idx=0; if(!(dmai->internal[dmai->idx] && (dmai->flags & BM_DMA_FIXED_BUFFS))) { bm_list_descriptor * list = (bm_list_descriptor *)mach64_dma_desc_base[dmai->idx]; unsigned long dest_ptr; unsigned i,n,count; int retval; n = dmai->size / 4096; if(dmai->size % 4096) n++; if((retval = VIRT_TO_CARD(dmai->src,dmai->size,dma_phys_addrs)) != 0) return retval; dmai->internal[dmai->idx] = mach64_dma_desc_base[dmai->idx]; dest_ptr = dmai->dest_offset; count = dmai->size;#if 0printf("MACH64_DMA_REQUEST va=%X size=%X\n",dmai->src,dmai->size);#endif for(i=0;i<n;i++) { list[i].framebuf_offset = mach64_overlay_offset + dest_ptr; /* offset within of video memory */ list[i].sys_addr = dma_phys_addrs[i]; list[i].command = (count > 4096 ? 4096 : (count | DMA_GUI_COMMAND__EOL)); list[i].reserved = 0;#if 0printf("MACH64_DMA_TABLE[%i] fboff=%X pa=%X cmd=%X rsrvd=%X\n",i,list[i].framebuf_offset,list[i].sys_addr,list[i].command,list[i].reserved);#endif dest_ptr += 4096; count -= 4096; } cpu_flush(list,4096); } return 0;}static int mach64_transfer_frame( unsigned long ba_dma_desc,int sync_mode ){ uint32_t crtc_int; mach64_wait_for_idle(); mach64_fifo_wait(4); OUTREG(BUS_CNTL,(INREG(BUS_CNTL)|BUS_EXT_REG_EN)&(~BUS_MASTER_DIS)); crtc_int = INREG(CRTC_INT_CNTL); if(sync_mode && can_use_irq) OUTREG(CRTC_INT_CNTL,crtc_int|CRTC_BUSMASTER_EOL_INT|CRTC_BUSMASTER_EOL_INT_EN); else OUTREG(CRTC_INT_CNTL,crtc_int|CRTC_BUSMASTER_EOL_INT); OUTREG(BM_SYSTEM_TABLE,ba_dma_desc|SYSTEM_TRIGGER_SYSTEM_TO_VIDEO); if(__verbose > VERBOSE_LEVEL) mach64_vid_dump_regs(); #if 0 mach64_fifo_wait(4); mach64_fifo_wait(16); printf("MACH64_DMA_DBG: bm_fb_off=%08X bm_sysmem_addr=%08X bm_cmd=%08X bm_status=%08X bm_agp_base=%08X bm_agp_cntl=%08X\n", INREG(BM_FRAME_BUF_OFFSET), INREG(BM_SYSTEM_MEM_ADDR), INREG(BM_COMMAND), INREG(BM_STATUS), INREG(AGP_BASE), INREG(AGP_CNTL));#endif return 0;}int VIDIX_NAME(vixQueryDMAStatus)( void ){ int bm_off; unsigned crtc_int_cntl; mach64_wait_for_idle(); mach64_fifo_wait(2); crtc_int_cntl = INREG(CRTC_INT_CNTL); bm_off = crtc_int_cntl & CRTC_BUSMASTER_EOL_INT;// if(bm_off) OUTREG(CRTC_INT_CNTL,crtc_int_cntl | CRTC_BUSMASTER_EOL_INT); return bm_off?0:1;}int VIDIX_NAME(vixPlaybackCopyFrame)( vidix_dma_t * dmai ){ int retval,sync_mode; if(!(dmai->flags & BM_DMA_FIXED_BUFFS)) if(bm_lock_mem(dmai->src,dmai->size) != 0) return errno; sync_mode = (dmai->flags & BM_DMA_SYNC) == BM_DMA_SYNC; if(sync_mode) { if(!irq_installed) init_irq(); /* burn CPU instead of PCI bus here */ while(vixQueryDMAStatus()!=0){ if(can_use_irq) hwirq_wait(pci_info.irq); else usleep(0); /* ugly but may help */ } } mach64_engine_reset(); retval = mach64_setup_frame(dmai); VIRT_TO_CARD(mach64_dma_desc_base[dmai->idx],1,&bus_addr_dma_desc); if(retval == 0) retval = mach64_transfer_frame(bus_addr_dma_desc,sync_mode); if(!(dmai->flags & BM_DMA_FIXED_BUFFS)) bm_unlock_mem(dmai->src,dmai->size); return retval;}#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -