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