📄 vp_capture.c
字号:
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 + -