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

📄 vp_capture.c

📁 DM642的VP口驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
						  param->fldDectMode,
						  param->vCtRstMode,
						  param->hCtRstMode,
						  VP_VCACTL_VCEN_DISABLE,
						  param->bpkMode,
						  VP_VCACTL_LFDE_DISABLE,
						  VP_VCACTL_SFDE_DISABLE,
						  param->resmpl,
						  param->scale,
						  param->conCap,
						  frmCap,
						  fld2Cap,
						  fld1Cap,
						  param->capMode);

	//构建图象窗寄存器值
	vcStrt1 = VP_VCASTRT1_RMK(param->fld1YStart, VP_VCASTRT1_SSE_DISABLE, param->fld1XStart);
	vcStrt2 = VP_VCASTRT2_RMK(param->fld2YStart,                          param->fld2XStart);	
	vcStop1 = VP_VCASTOP1_RMK(param->fld1YStop,                           param->fld1XStop);
	vcStop2 = VP_VCASTOP2_RMK(param->fld2YStop,                           param->fld2XStop);
	vcThrld = VP_VCATHRLD_RMK(param->fld1Thrld,							  param->fld2Thrld);
	vcEvtct = VP_VCAEVTCT_RMK(field2Evtct, field1Evtct);
	
	//写寄存器(通道A的寄存器和通道B的寄存器分布有着相同便宜)
	baseAddr = (Uns *)hCapChan->baseAddr;
	baseAddr[_VP_VCACTL_OFFSETA]   = vcCtl;
	baseAddr[_VP_VCASTRT1_OFFSETA] = vcStrt1;
	baseAddr[_VP_VCASTRT2_OFFSETA] = vcStrt2;
	baseAddr[_VP_VCASTOP1_OFFSETA] = vcStop1;
	baseAddr[_VP_VCASTOP2_OFFSETA] = vcStop2;
	baseAddr[_VP_VCATHRLD_OFFSETA] = vcThrld;
	baseAddr[_VP_VCAEVTCT_OFFSETA] = vcEvtct;

	//返回
	return(IOM_COMPLETED);
}

/*
 *  ======== CapChan_memAlloc ========
 */
Int CapChan_memAlloc(CapChan_Handle hCapChan, CapChan_Params *paramCapChan)
{
	Int	 i, j;
	Char *frmBuf;	
	Int  heapSegIid, heapSegSid;
    CapChan_VideoBufElem *hVideoBuf;
    
    //Segment ID.
    hCapChan->heapSegIid = heapSegIid = paramCapChan->heapSegIid;
    hCapChan->heapSegSid = heapSegSid = paramCapChan->heapSegSid;

    //QUE初始化.
    QUE_new(&hCapChan->vEmptyBufQue);
    QUE_new(&hCapChan->vFillingBufQue);
    QUE_new(&hCapChan->vFullBufQue);
    QUE_new(&hCapChan->vEmptingBufQue);
    
	for(i=0; i<paramCapChan->vBufCnt; i++){
		//帧管理器分配.
		hVideoBuf = (CapChan_VideoBufElem *)MEM_alloc(heapSegIid,sizeof(CapChan_VideoBufElem), 4);
		if(MEM_ILLEGAL == hVideoBuf){
			return(IOM_EALLOC);
		}else{
			QUE_put(&hCapChan->vEmptyBufQue, hVideoBuf);
		}
		
		//设置缓冲区起始状态;
		for(j=0; j<VP_YCBR_CHAN_CNT; j++){
			hVideoBuf->bufSt[j] = VP_VBUF_IS_EMPTY;
		}
		
		//分配视频YUV数据缓冲区.
		if(VP_CAPTURE_FRAME == hCapChan->vCapScope){
			if(MEM_ILLEGAL == (frmBuf =(Char *)MEM_alloc(heapSegSid, hCapChan->vFramYBufSz * 2, 128))){
				return(IOM_EALLOC);
			}else{
				hVideoBuf->ycrbBuf.ycbr[0] = frmBuf;
				hVideoBuf->ycrbBuf.ycbr[1] = frmBuf + hCapChan->vFramYBufSz;
				hVideoBuf->ycrbBuf.ycbr[2] = frmBuf + hCapChan->vFramYBufSz * 3 / 2;
			}
		}else{
			if(VP_CAPTURE_FIELD1 == hCapChan->vCapScope){
				if(MEM_ILLEGAL == (frmBuf =(Char *)MEM_alloc(heapSegSid, hCapChan->vFld1YBufSz * 2, 128))){
					return(IOM_EALLOC);
				}else{
					hVideoBuf->ycrbBuf.ycbr[0] = frmBuf;
					hVideoBuf->ycrbBuf.ycbr[1] = frmBuf + hCapChan->vFld1YBufSz;
					hVideoBuf->ycrbBuf.ycbr[2] = frmBuf + hCapChan->vFld1YBufSz * 3 / 2;
				}
			}else if(VP_CAPTURE_FIELD2 == hCapChan->vCapScope){
				if(MEM_ILLEGAL == (frmBuf =(Char *)MEM_alloc(heapSegSid, hCapChan->vFld2YBufSz * 2, 128))){
					return(IOM_EALLOC);
				}else{
					hVideoBuf->ycrbBuf.ycbr[0] = frmBuf;
					hVideoBuf->ycrbBuf.ycbr[1] = frmBuf + hCapChan->vFld2YBufSz;
					hVideoBuf->ycrbBuf.ycbr[2] = frmBuf + hCapChan->vFld2YBufSz * 3 / 2;
				}
			}
		}
	}

	return(IOM_COMPLETED);
}

/*
 *  ======== CapChan_edmaAllocConfig ========
 */
Int CapChan_edmaAllocConfig(CapChan_Handle hCapChan, CapChan_Params *paramCapChan)
{
	Int	i;
	Uns	edmaTcc;
    EDMA_Handle hVPEdma;
	EDMA_Config	*hEdmaCfg;
	CapChan_VideoBufElem *hVideoBuf;

	//中断安装.
	IRQ_map(IRQ_EVT_EDMAINT, paramCapChan->edmaIRQid);
    HWI_dispatchPlug(paramCapChan->edmaIRQid, (Fxn)EDMA_intDispatcher, -1, NULL);
    
	//QUE processing.
	hVideoBuf = (CapChan_VideoBufElem *)QUE_get(&hCapChan->vEmptyBufQue);
	QUE_put(&hCapChan->vFillingBufQue, hVideoBuf);
	
    //Note: i=0 for Y, i=1 for Cb, i=2 for Cr.
	for(i=0; i<VP_YCBR_CHAN_CNT; i++){
		//EDMA 分配.
		if(((hCapChan->hEdma[i]   = EDMA_open(hCapChan->edmaChanid[i], EDMA_OPEN_RESET))== EDMA_HINV) || 
		   ((hCapChan->edmaTcc[i] = EDMA_intAlloc(hCapChan->edmaChanid[i])) 		    == -1)){
			return(IOM_EALLOC);
	    }
	    
	    //EDMA 配置.
		hVPEdma  = hCapChan->hEdma[i];
		edmaTcc  = hCapChan->edmaTcc[i];
		hEdmaCfg = &hCapChan->edmaCfg[i];
		
		hEdmaCfg->opt = EDMA_OPT_RMK(EDMA_OPT_PRI_HIGH,
								     EDMA_OPT_ESIZE_32BIT,
								     EDMA_OPT_2DS_NO,
								     EDMA_OPT_SUM_NONE,
								     EDMA_OPT_2DD_YES,
								     EDMA_OPT_DUM_INC,
								     EDMA_OPT_TCINT_YES,
								     EDMA_OPT_TCC_OF(edmaTcc & 0x0000000F),
								     EDMA_OPT_TCCM_OF((edmaTcc >> 4) & 0x00000003),
								     EDMA_OPT_ATCINT_NO,
								     EDMA_OPT_ATCC_DEFAULT,
								     EDMA_OPT_PDTS_DISABLE,
								     EDMA_OPT_PDTD_DISABLE,
								     EDMA_OPT_LINK_YES,
								     EDMA_OPT_FS_NO);
		hEdmaCfg->src = (Uint32)(hCapChan->yCbrSrcAddr + i * 8);
		hEdmaCfg->dst = (Uint32)(hVideoBuf->ycrbBuf.ycbr[i]);
		if(VP_CAPTURE_FRAME == hCapChan->vCapScope){
			hEdmaCfg->cnt = (Uint32)(hCapChan->vFramCnt[i]);
			hEdmaCfg->idx = (Uint32)(((hCapChan->vFramCnt[i]) & 0x0000FFFF) << 18);
			hEdmaCfg->rld = (Uint32)((hCapChan->vFramCnt[i]) << 16);
		}else{
	    	if(VP_CAPTURE_FIELD1 == hCapChan->vCapScope){
				hEdmaCfg->cnt = (Uint32)(hCapChan->vFld1Cnt[i]);
				hEdmaCfg->idx = (Uint32)(((hCapChan->vFld1Cnt[i]) & 0x0000FFFF) << 18);
				hEdmaCfg->rld = (Uint32)((hCapChan->vFld1Cnt[i]) << 16);
			}else if(VP_CAPTURE_FIELD2 == hCapChan->vCapScope){
				hEdmaCfg->cnt = (Uint32)(hCapChan->vFld2Cnt[i]);
				hEdmaCfg->idx = (Uint32)(((hCapChan->vFld2Cnt[i]) & 0x0000FFFF) << 18);
				hEdmaCfg->rld = (Uint32)((hCapChan->vFld2Cnt[i]) << 16);
			}
		}
		
		EDMA_config(hVPEdma, hEdmaCfg);
		EDMA_link(hVPEdma, EDMA_hNull);
	    EDMA_intClear(edmaTcc);
	    EDMA_intHook(edmaTcc, IsrForVideoCapEDMA);
	    EDMA_intEnable(edmaTcc);
	    EDMA_enableChannel(hVPEdma);
    }
	hCapChan->edmaConfigFlg = TRUE;
    IRQ_enable(IRQ_EVT_EDMAINT);

    return(IOM_COMPLETED);
}

/*
 *  ======== CapChan_memFree ========
 */
void CapChan_memFree(CapChan_Handle hCapChan)
{
	Int	i;
	Int heapSegIid, heapSegSid;
	QUE_Handle hQue[4];
	CapChan_VideoBufElem *hVideoBuf;
	
    //Segment ID.
    heapSegIid = hCapChan->heapSegIid;
    heapSegSid = hCapChan->heapSegSid;

	//枚举所有队列.
	hQue[0] = &hCapChan->vEmptyBufQue;
	hQue[1] = &hCapChan->vFillingBufQue;
	hQue[2] = &hCapChan->vFullBufQue;
	hQue[3] = &hCapChan->vFullBufQue;
	
	for(i=0; i<4; i++){
		for(; !QUE_empty(hQue[i]); ){
			hVideoBuf = (CapChan_VideoBufElem *)QUE_get(hQue[i]);
			
			//释放视频缓冲区.
			if(VP_CAPTURE_FRAME == hCapChan->vCapScope){
				if(MEM_ILLEGAL != hVideoBuf->ycrbBuf.ycbr[0]){
					MEM_free(heapSegSid, hVideoBuf->ycrbBuf.ycbr[0], hCapChan->vFramYBufSz * 3 / 2);
				}
			}else{
				if(VP_CAPTURE_FIELD1 == hCapChan->vCapScope){
					if(MEM_ILLEGAL != hVideoBuf->ycrbBuf.ycbr[0]){
						MEM_free(heapSegSid, hVideoBuf->ycrbBuf.ycbr[0], hCapChan->vFld1YBufSz * 3 / 2);
					}
				}else if(VP_CAPTURE_FIELD1 == hCapChan->vCapScope){
					if(MEM_ILLEGAL != hVideoBuf->ycrbBuf.ycbr[0]){
						MEM_free(heapSegSid, hVideoBuf->ycrbBuf.ycbr[0], hCapChan->vFld1YBufSz * 3 / 2);
					}
				}
			}
			
			//释放管理模块;
			MEM_free(heapSegIid, hVideoBuf, sizeof(CapChan_VideoBufElem));
		}
	}
}

/*
 *  ======== CapChan_edmaFree ========
 */
void CapChan_edmaFree(CapChan_Handle hCapChan)
{
	Int	i;

    //Note: i=0 for Y, i=1 for Cb, i=2 for Cr.
	for(i=0; i<VP_YCBR_CHAN_CNT; i++){
		//禁止事件触发并清除标志位.
	    EDMA_intDisable(hCapChan->edmaTcc[i]);
	    EDMA_intClear(hCapChan->edmaTcc[i]);
		
		//释放TCC.
		if(-1 != hCapChan->edmaTcc[i]){
			EDMA_intFree(hCapChan->edmaTcc[i]);
		}
		
		//释放EDMA.
		if(INV != (void *)hCapChan->hEdma[i]){
			EDMA_close(hCapChan->hEdma[i]);
	    }
	}
	
    IRQ_disable(IRQ_EVT_EDMAINT);
}

/*
 *  =================== mdBindDev ============================
 *  Register all external devices to video port capture driver. 
 */
static Int mdBindDev(Ptr *devp, 	//Point to DEV_Device.devp.	 Configed with CDB and can changed by mdBindDev().
					 Int devid, 	//Get from DEV_Device.devid. Configed with CDB.
					 Ptr devParams)	//Get from DEV_Device.params Configed with CDB.
{
	Uns	*baseAddr;
    Int portid =  devid;   
	CapVP_Params  *portParams = (CapVP_Params *)devParams; 
	CapVP_Handle  hCapVP;
	
    //初始化DEV_Device.devp
    *devp = hCapVP = &CapVideoPorts[portid];
    
    //检查并设置视频端口状态
    if(hCapVP->status & VP_STATUS_OPENED){
    	return(IOM_EINUSE);
    }else{
    	hCapVP->status |= VP_STATUS_OPENED;
    	baseAddr = (Uns *)hCapVP->baseAddr;
    }

    //端口通道可能支持的模式;
    if(portParams->chanMode == SINGLE){
    	hCapVP->status  |= (VP_STATUS_CHASUPPORT);  
    	hCapVP->supCMode = (((Uns) 1) << VP_VCACTL_CMODE_BT656B) | 
    					   (((Uns) 1) << VP_VCACTL_CMODE_BT656D) |
     					   (((Uns) 1) << VP_VCACTL_CMODE_YCB)    | 
     					   (((Uns) 1) << VP_VCACTL_CMODE_YCD);
    }else if(portParams->chanMode == DUAL){
    	hCapVP->status  |= (VP_STATUS_CHASUPPORT | VP_STATUS_CHBSUPPORT);      
    	hCapVP->supCMode = (((Uns) 1) << VP_VCACTL_CMODE_BT656B) |
    	                   (((Uns) 1) << VP_VCACTL_CMODE_BT656D);   
    }else{
    	return(IOM_EBADARGS);
    }
	//EDC函数表链接
	hCapVP->capChan[0].edcFxns = portParams->edcFxns[0];
	hCapVP->capChan[1].edcFxns = portParams->edcFxns[1];
	
    //使能该视频端口
    baseAddr[_VP_PCR_OFFSET]   = VP_PCR_DEFAULT | (VP_PCR_PEREN_ENABLE << _VP_PCR_PEREN_SHIFT);
    
    //复位该视频端口
    baseAddr[_VP_VPCTL_OFFSET] = VP_VPCTL_DEFAULT | (VP_VPCTL_VPRST_RESET << _VP_VPCTL_VPRST_SHIFT);
    
    //配置该视频端口,禁止所有中断使能并清除所有中断源标志
    baseAddr[_VP_VPCTL_OFFSET] = VP_VPCTL_RMK(VP_VPCTL_VPRST_NO,
    							 			  VP_VPCTL_VPHLT_CLEAR,
    							 			  VP_VPCTL_VCLK2P_NONE,
    							 			  portParams->vctl3Pol,
    							 			  portParams->vctl2Pol,
    							 		 	  portParams->vctl1Pol,
    							  			  VP_VPCTL_TSI_NONE,
    							 			  VP_VPCTL_DISP_CAPTURE,
    							 			  portParams->chanMode);
    baseAddr[_VP_VPIE_OFFSET]  = VP_VPSTAT_DEFAULT;
    baseAddr[_VP_VPIS_OFFSET]  = VP_VPIE_DEFAULT;
    
    //复位该视频端口的两个通道
    baseAddr[_VP_VCACTL_OFFSET] = VP_VCACTL_DEFAULT | (VP_VCACTL_RSTCH_RESET << _VP_VCACTL_RSTCH_SHIFT);
    baseAddr[_VP_VCBCTL_OFFSET] = VP_VCBCTL_DEFAULT | (VP_VCBCTL_RSTCH_RESET << _VP_VCBCTL_RSTCH_SHIFT);
    
    return(IOM_COMPLETED); 
}

/*
 *  =================== mdCreateChan ============================
 *  create a capture channel
 */
static Int mdCreateChan(Ptr *chanp, 			//Point to GIO_Obj.mdChan	
						Ptr devp, 				//Get from DEV_Device.devp and point to CapVideoPorts[i]
						String name, 			//Get from GIO_create() used to specify the channel number
						Int mode,				//Get from GIO_create() used to specify the channel mode
                      	Ptr chanParams, 		//Get from GIO_create() used to set the channel
                      	IOM_TiomCallback cbFxn, //Point to _GIO_iomCallback()

⌨️ 快捷键说明

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