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

📄 vp_capture.c

📁 DM642的VP口驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
/************************************************************************
 *  DM642 video port driver based on DSP/BIOS DDK.						*
 *																		*
 *  Copyright(C) 2004 ZhongQing in Beijing. 							*
 ************************************************************************/
 
/* 
 *  DSP/BIOS standard include files. 
 */
#include <std.h>
#include <csl_vp.h>
#include <csl_edma.h>
#include <edc.h>
#include <iom.h>
#include <que.h>

#include <saa7115.h>
#include <CapVP.h>

/*
 * mini-driver API functions. 
 */
static Int mdBindDev(Ptr *devp, Int devid, Ptr devParams);
static Int mdControlChan(Ptr chanp, Uns cmd, Ptr args);
static Int mdCreateChan(Ptr *chanp, Ptr devp, String name, Int mode, Ptr chanParams, IOM_TiomCallback cbFxn, Ptr cbArg);
static Int mdDeleteChan(Ptr chanp);
static Int mdSubmitChan(Ptr chanp, IOM_Packet *packet);

/*
 * global and static variables. 
 */
IOM_Fxns CapVP_mdFxns = {
    mdBindDev,    
    (IOM_TmdUnBindDev)IOM_mdNotImpl,
    mdControlChan,
    mdCreateChan,
    mdDeleteChan,
    mdSubmitChan
};

/*
 * video capture channel parameter.
 */
CapChan_Params CapChanParams = {
	VP_VCACTL_CMODE_BT656B,
	VP_VCACTL_CON_DISABLE,
	VP_VCACTL_SCALE_NONE,
	VP_VCACTL_RESMPL_DISABLE,
	VP_VCACTL_PK10B_ZERO,
	VP_VCACTL_HRST_SAV,
	VP_VCACTL_VRST_V0EAV,
	VP_VCACTL_FLDD_EAVFID,
	VP_VCACTL_EXC_EXTERN,
	VP_VCACTL_FINV_FIELD1,
	20, 20, 175+20, 144+20,
	20, 20, 175+20, 144+20,
	(352 >> 3),
	(352 >> 3),
	8,
	0,
	0,
	5
};

/*
 * video port parameter.
 */
CapVP_Params CapVideoPortsParams = {
	SINGLE,
	LOW,
	HIGH,
	HIGH,
	&SAA7115_Fxns,
	INV
};

/*
 * video port objects.
 */
CapVP_Elem CapVideoPorts[_VP_PORT_CNT] = {
	{VP_STATUS_UNUSED, VP_SUPCMODE_NONE, _VP_BASE_PORT0, {{&CapVideoPorts[0], 0, _VP_BASE_CHAPORT0, _VP_AFBASE_PORT0, EDMA_CHA_VP0EVTYA, EDMA_CHA_VP0EVTUA, EDMA_CHA_VP0EVTVA}, {&CapVideoPorts[0], 1, _VP_BASE_CHAPORT0, _VP_BFBASE_PORT0, EDMA_CHA_VP0EVTYB, EDMA_CHA_VP0EVTUB, EDMA_CHA_VP0EVTVB}}},
	{VP_STATUS_UNUSED, VP_SUPCMODE_NONE, _VP_BASE_PORT1, {{&CapVideoPorts[1], 0, _VP_BASE_CHAPORT1, _VP_AFBASE_PORT1, EDMA_CHA_VP1EVTYA, EDMA_CHA_VP1EVTUA, EDMA_CHA_VP1EVTVA}, {&CapVideoPorts[1], 1, _VP_BASE_CHAPORT1, _VP_BFBASE_PORT1, EDMA_CHA_VP1EVTYB, EDMA_CHA_VP1EVTUB, EDMA_CHA_VP1EVTVB}}},
	{VP_STATUS_UNUSED, VP_SUPCMODE_NONE, _VP_BASE_PORT2, {{&CapVideoPorts[2], 0, _VP_BASE_CHAPORT2, _VP_AFBASE_PORT2, EDMA_CHA_VP2EVTYA, EDMA_CHA_VP2EVTUA, EDMA_CHA_VP2EVTVA}, {&CapVideoPorts[2], 1, _VP_BASE_CHAPORT2, _VP_BFBASE_PORT2, EDMA_CHA_VP2EVTYB, EDMA_CHA_VP2EVTUB, EDMA_CHA_VP2EVTVB}}}
};
 
/*
 *  =================== IsrForVideoCapEDMA ============================
 *  Interrupt service for edma which transfer data from video port fifo to memory.
 */
void IsrForVideoCapEDMA(Int edmaTcc)
{
	Int						i, j, k;
	Uns						*baseAddr;
   	Char					**ycbrBuf;
	IOM_Packet				*hIomPkt;
	CapVP_Handle 			hCapVP;
	CapChan_Handle			hCapChan;
	CapChan_VideoBufElem	*hVideoBuf;

	for(i=0; i<_VP_PORT_CNT; i++){
		hCapVP = &CapVideoPorts[i];
		if(hCapVP->status & VP_STATUS_OPENED){
			//Note: j==0 for A channel; j==1 for B channel.
			for(j=0; j<VP_CHAN_CNT; j++){
				hCapChan = &hCapVP->capChan[j];
				if((hCapVP->status & ((j == 0) ? VP_STATUS_CHAOPENED  : VP_STATUS_CHBOPENED )) &&
				   (hCapVP->status & ((j == 0) ? VP_STATUS_CHASUPPORT : VP_STATUS_CHBSUPPORT))){
					hVideoBuf = (CapChan_VideoBufElem *)QUE_head(&hCapChan->vFillingBufQue);
					
					for(k=0; k<VP_YCBR_CHAN_CNT; k++){
						if(edmaTcc == hCapChan->edmaTcc[k]){
							hVideoBuf->bufSt[k] = VP_VBUF_IS_FULL;
						}
					}
					
					if((hVideoBuf->bufSt[0] == VP_VBUF_IS_FULL) &&
					   (hVideoBuf->bufSt[1] == VP_VBUF_IS_FULL) &&
					   (hVideoBuf->bufSt[2] == VP_VBUF_IS_FULL)){
					   	hVideoBuf = (CapChan_VideoBufElem *)QUE_get(&hCapChan->vFillingBufQue);
					    
					    if(!QUE_empty(&hCapChan->iomPktQue)){
					    	QUE_put(&hCapChan->vEmptingBufQue, hVideoBuf);
					    	
					   		hIomPkt = (IOM_Packet *)QUE_get(&hCapChan->iomPktQue);
					   		ycbrBuf = (char **)hIomPkt->addr;
							for(i=0; i<VP_YCBR_CHAN_CNT; i++){
								*(ycbrBuf + i) = hVideoBuf->ycrbBuf.ycbr[i];
							}

						   	if(!QUE_empty(&hCapChan->vEmptyBufQue)){
		   						hVideoBuf = (CapChan_VideoBufElem *)QUE_get(&hCapChan->vEmptyBufQue);
	
								QUE_put(&hCapChan->vFillingBufQue, hVideoBuf);
								
						   		hCapChan->edmaCfg[0].dst = (Uint32)hVideoBuf->ycrbBuf.ycbr[0];
						   		hCapChan->edmaCfg[1].dst = (Uint32)hVideoBuf->ycrbBuf.ycbr[1];
						   		hCapChan->edmaCfg[2].dst = (Uint32)hVideoBuf->ycrbBuf.ycbr[2];
							   	
							   	EDMA_config(hCapChan->hEdma[0], &hCapChan->edmaCfg[0]);	
							   	EDMA_config(hCapChan->hEdma[1], &hCapChan->edmaCfg[1]);
							   	EDMA_config(hCapChan->hEdma[2], &hCapChan->edmaCfg[2]);
	
							   	EDMA_link(hCapChan->hEdma[0], EDMA_hNull);
							   	EDMA_link(hCapChan->hEdma[1], EDMA_hNull);
							   	EDMA_link(hCapChan->hEdma[2], EDMA_hNull);
							   	
							   	hCapChan->edmaConfigFlg = TRUE;
								
								if(VP_CAP_SINGLE == hCapChan->vConCap){							   	
							    	if(!QUE_empty(&hCapChan->iomPktQue)){
										baseAddr = (Uns *)hCapChan->baseAddr;
										baseAddr[_VP_VCACTL_OFFSETA] |= _VP_VCACTL_BLKCAP_MASK;
										baseAddr[_VP_VCASTAT_OFFSETA] = VP_VCASTAT_RMK(VP_VCASTAT_FRMC_CLEAR, VP_VCASTAT_F2C_CLEAR, VP_VCASTAT_F1C_CLEAR);
										baseAddr[_VP_VCACTL_OFFSETA] &= ~_VP_VCACTL_BLKCAP_MASK;
									
										hCapChan->edmaConfigFlg = FALSE;
									}
								}
							}

					   		hCapChan->cbFxn((Ptr)hCapChan->cbArg, hIomPkt);
					    }else{
					    	QUE_put(&hCapChan->vFullBufQue, hVideoBuf);
					    	
						   	if(!QUE_empty(&hCapChan->vEmptyBufQue)){
		   						hVideoBuf = (CapChan_VideoBufElem *)QUE_get(&hCapChan->vEmptyBufQue);
	
								QUE_put(&hCapChan->vFillingBufQue, hVideoBuf);
								
						   		hCapChan->edmaCfg[0].dst = (Uint32)hVideoBuf->ycrbBuf.ycbr[0];
						   		hCapChan->edmaCfg[1].dst = (Uint32)hVideoBuf->ycrbBuf.ycbr[1];
						   		hCapChan->edmaCfg[2].dst = (Uint32)hVideoBuf->ycrbBuf.ycbr[2];
							   	
							   	EDMA_config(hCapChan->hEdma[0], &hCapChan->edmaCfg[0]);	
							   	EDMA_config(hCapChan->hEdma[1], &hCapChan->edmaCfg[1]);
							   	EDMA_config(hCapChan->hEdma[2], &hCapChan->edmaCfg[2]);
	
							   	EDMA_link(hCapChan->hEdma[0], EDMA_hNull);
							   	EDMA_link(hCapChan->hEdma[1], EDMA_hNull);
							   	EDMA_link(hCapChan->hEdma[2], EDMA_hNull);
							   	
							   	hCapChan->edmaConfigFlg = TRUE;
							}
					    }
					}
				}
			}
		}
	}
}

/*
 *  ======== CapChan_chanConfig ========
 *	Config the channel register: 
 *  VCxCTL, VCxSTRT1, VCxSTOP1, VCxSTRT2, VCxSTOP2, VCxTHRLD, VCxEVTCT. 
 *  Note: The control register of channel A is not all the same
 *	with the control register of channel B, so the configuration 
 *	of VCACTL has little difference with the one of VCBCTL.
 */
Int CapChan_chanConfig(CapChan_Handle hCapChan, CapChan_Params *paramCapChan)
{
	CapChan_Params *param = paramCapChan;
	Bool fld1Cap, fld2Cap, frmCap;
	Uns	 *baseAddr;
	Uns  widthPixelCnt, heighPixelCnt;
	Uns  lineYDwCnt, fieldYDwCnt, lineCrbDwCnt, fieldCrbDwCnt;
	Uns  YThrld, CrbThrld, field1Evtct = 0, field2Evtct = 0;
	Uns  vcCtl, vcStrt1, vcStrt2, vcStop1, vcStop2, vcThrld, vcEvtct;

	
	//检查用户参数配置是否正确;
	hCapChan->vConCap = param->conCap;

	//Field 1 参数校验
	widthPixelCnt = param->fld1XStop - param->fld1XStart + 1;
	heighPixelCnt = param->fld1YStop - param->fld1YStart;
	YThrld		  = param->fld1Thrld;
	CrbThrld	  =(YThrld + 1)>> 1;
	if(param->scale){
		if(widthPixelCnt % 4){
			return(IOM_EBADARGS);
		}
		if(paramCapChan->bpkMode == VP_VCACTL_PK10B_DENSEPK){
			lineYDwCnt   = ((widthPixelCnt >> 1) + 5) / 6;
			lineCrbDwCnt = ((widthPixelCnt >> 2) + 5) / 6;
		}else{
			lineYDwCnt   = (((widthPixelCnt >> 1) + 7) >> 3);
			lineCrbDwCnt = (((widthPixelCnt >> 2) + 7) >> 3);
		}
	}else{
		if(widthPixelCnt % 2){
			return(IOM_EBADARGS);
		}
		if(paramCapChan->bpkMode == VP_VCACTL_PK10B_DENSEPK){
			lineYDwCnt   = ((widthPixelCnt     ) + 5) / 6;
			lineCrbDwCnt = ((widthPixelCnt >> 1) + 5) / 6;
		}else{
			lineYDwCnt   = (((widthPixelCnt     ) + 7) >> 3);
			lineCrbDwCnt = (((widthPixelCnt >> 1) + 7) >> 3);
		}
	}
	fieldYDwCnt   = lineYDwCnt   * heighPixelCnt;
	fieldCrbDwCnt = lineCrbDwCnt * heighPixelCnt;
	
	if((fieldYDwCnt % YThrld) || (fieldCrbDwCnt % CrbThrld)){
		return(IOM_EBADARGS);
	}else{
		field1Evtct = fieldYDwCnt / YThrld;
	}
	
	if(fieldYDwCnt){
		fld1Cap = TRUE;
	}else{
		fld2Cap = FALSE;
	}
	hCapChan->vFld1Cnt[0] = 					   ((field1Evtct - 1) << 16) + ((YThrld)      << 1);
	hCapChan->vFld1Cnt[1] = hCapChan->vFld1Cnt[2] =((field1Evtct - 1) << 16) + ((YThrld >> 1) << 1);
	hCapChan->vFld1YBufSz = (fieldYDwCnt << 3);
	
	//Field 2 参数校验
	widthPixelCnt = param->fld2XStop - param->fld2XStart + 1;
	heighPixelCnt = param->fld2YStop - param->fld2YStart;
	YThrld		  = param->fld2Thrld;
	CrbThrld	  =(param->fld2Thrld + 1)>> 1;
	if(param->scale){
		if(widthPixelCnt % 4){
			return(IOM_EBADARGS);
		}
		lineYDwCnt   = (((widthPixelCnt >> 1) + 7) >> 3);
		lineCrbDwCnt = (((widthPixelCnt >> 2) + 7) >> 3);
	}else{
		if(widthPixelCnt % 2){
			return(IOM_EBADARGS);
		}
		lineYDwCnt   = (((widthPixelCnt     ) + 7) >> 3);
		lineCrbDwCnt = (((widthPixelCnt >> 1) + 7) >> 3);
	}
	fieldYDwCnt   = lineYDwCnt   * heighPixelCnt;
	fieldCrbDwCnt = lineCrbDwCnt * heighPixelCnt;
	if((fieldYDwCnt % YThrld) || (fieldCrbDwCnt % CrbThrld)){
		return(IOM_EBADARGS);
	}else{
		field2Evtct = fieldYDwCnt / YThrld;
	}
	
	if(fieldYDwCnt){
		fld2Cap = TRUE;
	}else{
		fld2Cap = FALSE;
	}
	hCapChan->vFld2Cnt[0] = 				 		((field2Evtct - 1) << 16) + ((YThrld)      << 1);
	hCapChan->vFld2Cnt[1] = hCapChan->vFld2Cnt[2] = ((field2Evtct - 1) << 16) + ((YThrld >> 1) << 1);
	hCapChan->vFld2YBufSz = (fieldYDwCnt << 3);
	
	//Frame 参数设置
	if(fld1Cap && fld2Cap){
		if((param->fld1XStart != param->fld2XStart) ||
		   (param->fld1YStart != param->fld2YStart) ||
		   (param->fld1XStop  != param->fld2XStop)  ||
		   (param->fld1YStop  != param->fld2YStop)	||
		   (param->fld1Thrld  != param->fld2Thrld)){
		   return(IOM_EBADARGS);
		}else{
			if(param->conCap){
				fld1Cap = FALSE;
				fld2Cap = FALSE;
			}
			frmCap  = TRUE;
		}
	}else{
		frmCap = FALSE;
	}
	
	if(frmCap){
		hCapChan->vCapScope   = VP_CAPTURE_FRAME;
		hCapChan->vFramCnt[0] = 					    ((field1Evtct + field2Evtct - 1) << 16) + ((YThrld)      << 1);
		hCapChan->vFramCnt[1] = hCapChan->vFramCnt[2] = ((field1Evtct + field2Evtct - 1) << 16) + ((YThrld >> 1) << 1);
		hCapChan->vFramYBufSz = hCapChan->vFld1YBufSz + hCapChan->vFld2YBufSz;
	}else{
		if(fld1Cap){
			hCapChan->vCapScope   = VP_CAPTURE_FIELD1;
		}else if(fld2Cap){
			hCapChan->vCapScope   = VP_CAPTURE_FIELD2;
		}
		hCapChan->vFramCnt[0] = hCapChan->vFramCnt[1] = hCapChan->vFramCnt[2] = 0;
		hCapChan->vFramYBufSz = 0;
	}

	//构建通道控制寄存器值
	vcCtl = VP_VCACTL_RMK(VP_VCACTL_RSTCH_NONE,
						  VP_VCACTL_BLKCAP_BLOCK,
						  VP_VCACTL_RDFE_DISABLE,
						  param->fldModeSel,
						  param->synModeSel,

⌨️ 快捷键说明

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