📄 copy of vportcap.c
字号:
and idx = 88 * 8 * 2 = 1408;
thrld is different for y and cb/cr.*/
cfgEdma.idx = EDMA_IDX_RMK(thrld << 4, 0);
/* hard code the first two frames as current and reload buffers */
/* hRld[4*i] - frame A field 1; link to hRld[4*i + 1]
hRld[4*i + 1] - frame A field 2; link to hRld[4*i + 2]
hRld[4*i + 2] - frame B field 1; link to hRld[4*i + 3]
hRld[4*i + 3] - frame B field 2; link to hRld[4*i] */
/* first field */
cfgEdma.opt = optFld1;
/*get the start address for y/cb/cr respectively base on i*/
/*first frame*/
cfgEdma.dst = EDMA_DST_RMK(*((Int *)(&pChan->viops[0].frame.iFrm.y1) + i));
cfgEdma.rld = EDMA_RLD_RMK(0, pChan->hRld[4 * i + 1]);
EDMA_config(pChan->hEdma[i], &cfgEdma);
EDMA_config(pChan->hRld[4 * i], &cfgEdma);
/*second frame*/
cfgEdma.dst = EDMA_DST_RMK(*((Int *)(&pChan->viops[1].frame.iFrm.y1) + i));
cfgEdma.rld = EDMA_RLD_RMK(0, pChan->hRld[4 * i + 3]);
EDMA_config(pChan->hRld[4 * i + 2], &cfgEdma);
/* second field */
cfgEdma.cnt = EDMA_CNT_RMK((pChan->numEvents - pChan->numEventsFld1) - 1,
(thrld << 1));
/*first frame*/
cfgEdma.opt = optFld2a;
cfgEdma.dst = EDMA_DST_RMK(*((Int *)(&pChan->viops[0].frame.iFrm.y2) + i));
cfgEdma.rld = EDMA_RLD_RMK(0, pChan->hRld[4 * i + 2]);
EDMA_config(pChan->hRld[4 * i + 1], &cfgEdma);
/*second frame*/
cfgEdma.opt = optFld2b;
cfgEdma.dst = EDMA_DST_RMK(*((Int *)(&pChan->viops[1].frame.iFrm.y2) + i));
cfgEdma.rld = EDMA_RLD_RMK(0, pChan->hRld[4 * i]);
EDMA_config(pChan->hRld[4 * i + 3], &cfgEdma);
}
else
{/* if fields are not merged, configure EDMA to transfer */
/* for both field1 and field 2 */
/* the line pitch is just the line size */
cfgEdma.opt = optFld2a;
cfgEdma.cnt = EDMA_CNT_RMK((pChan->numEvents) - 1, (thrld << 1));
cfgEdma.idx = EDMA_IDX_RMK(thrld << 3, 0);
cfgEdma.rld = EDMA_RLD_RMK(0, pChan->hRld[4 * i + 2]);
/* hard code the first and second frame buffer as current */
/* and reload buffers */
cfgEdma.dst = EDMA_DST_RMK(
*((Int *)(&pChan->viops[0].frame.iFrm.y1) + i));
EDMA_config(pChan->hEdma[i], &cfgEdma);
EDMA_config(pChan->hRld[4 * i], &cfgEdma);
cfgEdma.opt = optFld2b;
cfgEdma.rld = EDMA_RLD_RMK(0, pChan->hRld[4 * i]);
cfgEdma.dst = EDMA_DST_RMK(*((Int *)(&pChan->viops[1].frame.iFrm.y1) + i));
EDMA_config(pChan->hRld[4 * i + 2], &cfgEdma);
}
}
pChan->nextEDMARlds = 1;
/* enable EDMA channel */
/*
* The EDMA interrupt dispatcher will be called by the
* BIOS HWI interrupt dispatcher.
*/
IRQ_map(IRQ_EVT_EDMAINT, params->irqId);
HWI_dispatchPlug(params->irqId, (Fxn)EDMA_intDispatcher, -1, NULL);
//HWI_dispatchPlug(params->irqId, (Fxn)IsrForEDMA, -1, NULL);
EDMA_intClear(pChan->tcc[0]);
EDMA_intHook(pChan->tcc[0], captureEdmaISR);
EDMA_intEnable(pChan->tcc[0]);
EDMA_intClear(pChan->tcc[1]);
EDMA_intHook(pChan->tcc[1], captureEdmaISR);
EDMA_intEnable(pChan->tcc[1]);
for(i = 0; i < _VPORT_NUM_EDMA_CHANS; i ++)
{
EDMA_disableChannel(pChan->hEdma[i]);
EDMA_clearChannel(pChan->hEdma[i]);
EDMA_enableChannel(pChan->hEdma[i]);
}
pChan->status |= _VPORT_READY;
IRQ_enable(IRQ_EVT_EDMAINT);
}
return IOM_COMPLETED;
}
/*
* ======== _covrRecover ========
* force recover from FIFO over-run
*/
static Int _covrRecover(Ptr chanp)
{
_VPORT_ChanObj *pChan = (_VPORT_ChanObj*)chanp;
PortObj *pPort = &gsPortObjs[pChan->portNum];
volatile Int *base = (volatile Int*)pPort->base;
volatile Int *chBase = (volatile Int*)pChan->base;
Int numEvents;
volatile Int i;
/* disable over-run interrupt */
base[_VP_VPIE_OFFSET] &= ~(_VP_VPIE_COVRA_MASK<<(pChan->chanNum*16));
/* block capture events */
if (pChan->chanNum == 0)
chBase[_VP_VCACTL_OFFSETA] |= _VP_VCACTL_BLKCAP_MASK;
else if (pChan->chanNum == 1)
chBase[_VP_VCBCTL_OFFSETB] |= _VP_VCBCTL_BLKCAP_MASK;
/* Disable the edmas before settings them up */
EDMA_intDisable(pChan->tcc[0]);
EDMA_intDisable(pChan->tcc[1]);
for (i=0; i<_VPORT_NUM_EDMA_CHANS; i++)
{
EDMA_disableChannel(pChan->hEdma[i]);
EDMA_clearChannel(pChan->hEdma[i]);
}
/*
if (pChan->mergeFlds)
{
numEvents = pChan->numEventsFld1;
}
else
{
numEvents = pChan->numEvents;
}*/
if (pChan->mergeFlds)
numEvents = pChan->numEvents;
else
numEvents = pChan->numEventsFld1;
/* set up DMA parameters again */
EDMA_RSETH(pChan->hEdma[0], DST, pChan->curViop->frame.iFrm.y1);
EDMA_RSETH(pChan->hEdma[1], DST, pChan->curViop->frame.iFrm.cb1);
EDMA_RSETH(pChan->hEdma[2], DST, pChan->curViop->frame.iFrm.cr1);
EDMA_RSETH(pChan->hEdma[0], CNT, EDMA_CNT_RMK(numEvents-1, (pChan->yThrld<<1)) );
EDMA_RSETH(pChan->hEdma[1], CNT, EDMA_CNT_RMK(numEvents-1, (pChan->cThrld<<1)) );
EDMA_RSETH(pChan->hEdma[2], CNT, EDMA_CNT_RMK(numEvents-1, (pChan->cThrld<<1)) );
/* enable the edma events again before settings them up */
EDMA_intEnable(pChan->tcc[0]);
EDMA_intEnable(pChan->tcc[1]);
for (i=0; i<_VPORT_NUM_EDMA_CHANS; i++)
EDMA_enableChannel(pChan->hEdma[i]);
/* delay */
for (i = 0; i < 100000; i ++);
if (pChan->chanNum == 0)
{
/* clear any pending over-run interrupt */
base[_VP_VPIS_OFFSET] |= _VP_VPIS_COVRA_MASK;
/* enable event generation */
chBase[_VP_VCACTL_OFFSETA] &= ~(_VP_VCACTL_BLKCAP_MASK);
/* enable over-run interrupt */
base[_VP_VPIE_OFFSET] |= _VP_VPIE_COVRA_MASK << (pChan->chanNum * 16);
}
else if (pChan->chanNum == 1)
{
/* clear any pending over-run interrupt */
base[_VP_VPIS_OFFSET] |= _VP_VPIS_COVRB_MASK;
/* enable event generation */
chBase[_VP_VCBCTL_OFFSETB] &= ~(_VP_VCBCTL_BLKCAP_MASK);
/* enable over-run interrupt */
base[_VP_VPIE_OFFSET] |= _VP_VPIE_COVRB_MASK << (pChan->chanNum * 16);
}
return IOM_COMPLETED;
}
/*
* ======== _setVIntCb ========
* setup video port interrupt call-back
*/
static Int _setVIntCb(Ptr chanp, Ptr args)
{
_VPORT_ChanObj *pChan = (_VPORT_ChanObj* )chanp;
PortObj *pPort = &gsPortObjs[pChan->portNum];
volatile Int *portBase = (volatile Int *)pPort->base;
volatile Int *chBase = (volatile Int *)pChan->base;
VPORT_VIntCbParams *pvIntCbParams = (void *)args;
/* for either channel A or B*/
Int mask = pvIntCbParams->vIntMask;
Uns vif2 = 0, vInt2 = 0, vif1 = 0, vInt1 = 0, fscl2 = 0;
/* check to see if vertical interrupt is enabled */
if(mask & VPORT_INT_VINT1)
{
vif1 = 1;
vInt1 = pvIntCbParams->vIntLine;
}
if(mask & VPORT_INT_VINT2)
{
vif2 = 1;
vInt2 = pvIntCbParams->vIntLine;
}
fscl2 = vif2 & (~ vif1);
/* setup vertical interrupt */
if (pChan->chanNum == 0)
{/* channel A */
chBase[_VP_VCAVINT_OFFSETA] = VP_VCAVINT_RMK(vif2,fscl2,
vInt2, vif1, vInt1);
}
else
{/* channel B */
chBase[_VP_VCBVINT_OFFSETB] = VP_VCBVINT_RMK(vif2,fscl2,
vInt2, vif1, vInt1);
mask <<= 16;
}
pChan->vIntMask = mask;
if(mask)
{
mask |= 1; /* turn on video port interrupt */
IRQ_map(IRQ_EVT_VINT0 + pChan->portNum, pvIntCbParams->irqId);
HWI_dispatchPlug(pvIntCbParams->irqId, (Fxn)captureISR, -1, NULL);
IRQ_disable(IRQ_EVT_VINT0 + pChan->portNum);
IRQ_clear(IRQ_EVT_VINT0 + pChan->portNum);
}
portBase[_VP_VPIE_OFFSET] |= mask; /* register write */
pChan->vIntFxn = pvIntCbParams->vIntCbFxn;
pChan->vIntCbArg = pvIntCbParams->cbArg;
return IOM_COMPLETED;
}
/*
* ======== _startVPCapture ========
* start video port capture operation
*/
static Int _startVPCapture(Ptr chanp)
{
_VPORT_ChanObj *pChan = (_VPORT_ChanObj*)chanp;
PortObj *pPort = &gsPortObjs[pChan->portNum];
volatile Int *portBase = (volatile Int*)pPort->base;
volatile Int *chBase = (volatile Int*)pChan->base;
if (pChan->chanNum == 0)
{
/* enable channel A*/
chBase[_VP_VCACTL_OFFSETA] |= VP_VCACTL_VCEN_ENABLE << _VP_VCACTL_VCEN_SHIFT;
_delay(20000000);
/* clear the block capture event mask bit to enable */
/* generating capture events */
chBase[_VP_VCACTL_OFFSETA] &= ~ (_VP_VCACTL_BLKCAP_MASK);
}
else
{
/* enable channel B*/
chBase[_VP_VCBCTL_OFFSETB] |= VP_VCBCTL_VCEN_ENABLE << _VP_VCBCTL_VCEN_SHIFT;
_delay(20000000);
/* clear the block capture event mask bit to enable */
/* generating capture events */
chBase[_VP_VCBCTL_OFFSETB] &= ~ (_VP_VCBCTL_BLKCAP_MASK);
}
/* enable interrupt generation in video port level */
portBase[_VP_VPIE_OFFSET] |= VP_VPIE_VIE_ENABLE << _VP_VPIE_VIE_SHIFT;
portBase[_VP_VPIS_OFFSET] |= 0XFFFFFFFF;
/* clear any pending video port interrupt */
IRQ_clear(IRQ_EVT_VINT0 + pChan->portNum);
/* enable corresponding video port interrupt in chip-level*/
IRQ_enable(IRQ_EVT_VINT0 + pChan->portNum);
EDMA_intClear(pChan->tcc[0]);
EDMA_intEnable(pChan->tcc[0]);
EDMA_intClear(pChan->tcc[1]);
EDMA_intEnable(pChan->tcc[1]);
return IOM_COMPLETED;
}
/*
* ======== _stopVPCapture ========
* stop video port capture operation
*/
static Int _stopVPCapture(Ptr chanp)
{
_VPORT_ChanObj *pChan = (_VPORT_ChanObj* )chanp;
PortObj *pPort = &gsPortObjs[pChan->portNum];
volatile Int *chBase = (volatile Int *)pChan->base;
volatile Int *portBase = (volatile Int *)pPort->base;
/* block events generation */
if (pChan->chanNum == 0)
{
/* enable channel A*/
chBase[_VP_VCACTL_OFFSETA] |= (_VP_VCACTL_BLKCAP_MASK);
/* disable channel */
chBase[_VP_VCACTL_OFFSETA] &=
~ (VP_VCACTL_VCEN_ENABLE << _VP_VCACTL_VCEN_SHIFT);
}
else
{
/* enable channel B*/
chBase[_VP_VCBCTL_OFFSETB] |= (_VP_VCBCTL_BLKCAP_MASK);
/* disable channel */
chBase[_VP_VCBCTL_OFFSETB] &=
~ (VP_VCBCTL_VCEN_ENABLE << _VP_VCBCTL_VCEN_SHIFT);
}
/* disable interrupt generation in video port level */
portBase[_VP_VPIE_OFFSET] &= ~ (VP_VPIE_VIE_ENABLE << _VP_VPIE_VIE_SHIFT);
portBase[_VP_VPIS_OFFSET] |= 0XFFFFFFFF;
/* disble corresponding video port interrupt in chip-level*/
IRQ_disable(IRQ_EVT_VINT0 + pChan->portNum);
/* clear any pending video port interrupt */
IRQ_clear(IRQ_EVT_VINT0 + pChan->portNum);
EDMA_intDisable(pChan->tcc[0]);
EDMA_intClear(pChan->tcc[0]);
EDMA_intDisable(pChan->tcc[1]);
EDMA_intClear(pChan->tcc[1]);
pChan->numFrms = 0;
return IOM_COMPLETED;
}
/*
* ======== captureISR ========
*/
static void captureISR(Int portNum)
{
volatile Int *base = (volatile Int*)gsPortObjs[portNum].base;
Int vpis = base[_VP_VPIS_OFFSET];
Int mask = vpis;
_VPORT_ChanObj *chanObjs = gsPortObjs[portNum].chanObj;
if(vpis & chanObjs[0].vIntMask && chanObjs[0].vIntFxn != INV)
{
chanObjs[0].vIntFxn(chanObjs[0].vIntCbArg, vpis);
mask &= chanObjs[0].vIntMask;
}
else if(vpis & chanObjs[1].vIntMask && chanObjs[1].vIntFxn != INV)
{
chanObjs[1].vIntFxn(chanObjs[1].vIntCbArg, (vpis >> 16));
mask &= chanObjs[1].vIntMask;
}
/* clear interrupts that has been handled */
base[_VP_VPIS_OFFSET] |= mask;
}
static void _autoSync(_VPORT_ChanObj *pChan)
{
volatile Int *chBase = (volatile Int*)pChan->base;
volatile Int fid_stat;
volatile Int ypos;
Int offset = pChan->nextEDMARlds << 1;
if (pChan->chanNum == 0)
{
fid_stat = (chBase[_VP_VCASTAT_OFFSETA]&_VP_VCASTAT_VCFLD_MASK) >> _VP_VCASTAT_VCFLD_SHIFT;
ypos = (chBase[_VP_VCASTAT_OFFSETA]&_VP_VCASTAT_VCYPOS_MASK) >> _VP_VCASTAT_VCYPOS_SHIFT;
}
else if (pChan->chanNum == 1)
{
fid_stat = (chBase[_VP_VCBSTAT_OFFSETB]&_VP_VCBSTAT_VCFLD_MASK) >> _VP_VCBSTAT_VCFLD_SHIFT;
ypos = (chBase[_VP_VCBSTAT_OFFSETB]&_VP_VCBSTAT_VCYPOS_MASK) >> _VP_VCBSTAT_VCYPOS_SHIFT;
}
if (pChan->interlaced && ( fid_stat == 0 && ypos >= pChan->numTotalLinesFld1
|| fid_stat == 1 && ypos <= pChan->numLinesFld1))
{
/* Reconfig the EDMA to link to field 0 of the current transfer */
EDMA_link(pChan->hEdma[0], pChan->hRld[offset]);
EDMA_link(pChan->hEdma[1], pChan->hRld[offset+4]);
EDMA_link(pChan->hEdma[2], pChan->hRld[offset+8]);
}
}
static void _delay(Int delayTime)
{
asm("loop1: BDEC loop1, A4");
asm(" NOP 5");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -