📄 vportdis.c
字号:
if(chanObjs[portNum].asyncModeEnable) {
if(chanObjs[portNum].interlaced && (mask & VPORT_INT_VINT2)
||!chanObjs[portNum].interlaced && (mask & VPORT_INT_VINT1) )
_frmAlmostCmopleteIsr(portNum);
} else if(mask && chanObjs[portNum].vIntFxn != INV) {
chanObjs[portNum].vIntFxn(chanObjs[portNum].vIntCbArg, mask);
}
/* clear interrupts that has been handled */
base[_VP_VPIS_OFFSET] |= vpis;
}
/*
* ======== _displayStart ========
* start video display
*/
static Int _displayStart(Ptr chanp)
{
_VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
volatile Int* base = (volatile Int *)chan->base;
volatile Int stat;
volatile Int i = 0;
/* enable port and display */
base[_VP_VPCTL_OFFSET] |= VP_VPCTL_VPHLT_CLEAR << _VP_VPCTL_VPHLT_SHIFT;
base[_VP_VDCTL_OFFSET] |= VP_VDCTL_VDEN_ENABLE << _VP_VDCTL_VDEN_SHIFT;
/* wait for display counters and control signals to sync up */
do {
stat = base[_VP_VDSTAT_OFFSET];
i ++ ;
}while(!(stat & 0x70000000) && i < 1000000);
base[_VP_VDSTAT_OFFSET] = stat;
do {
stat = base[_VP_VDSTAT_OFFSET];
i ++;
}while(!(stat & 0x70000000) && i < 1000000);
base[_VP_VDSTAT_OFFSET] = stat;
base[_VP_VDCTL_OFFSET] &= ~ (_VP_VDCTL_BLKDIS_MASK);
/* enable interrupt */
base[_VP_VPIE_OFFSET] |= VP_VPIE_VIE_ENABLE << _VP_VPIE_VIE_SHIFT;
base[_VP_VPIS_OFFSET] |= 0XFFFFFFFF;
IRQ_clear(IRQ_EVT_VINT0 + chan->portNum);
IRQ_enable(IRQ_EVT_VINT0 + chan->portNum);
return IOM_COMPLETED;
}
/*
* ======== _displayStop ========
* stop video display
*/
static Int _displayStop(Ptr chanp)
{
_VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
volatile Int* base = (volatile Int *)chan->base;
base[_VP_VDCTL_OFFSET] &= ~ (VP_VDCTL_VDEN_ENABLE << _VP_VDCTL_VDEN_SHIFT);
return IOM_COMPLETED;
}
/*
* ======== _dundRecover ========
* force recover from display under-run
*/
static Int _dundRecover(Ptr chanp)
{
_VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
Int i;
Int stat;
Int numEvents;
volatile Int* base = (volatile Int *)chan->base;
/* disable under run interrupt */
base[_VP_VPIE_OFFSET] &= ~ (_VP_VPIE_DUND_MASK);
/* clear any pending under-run interrupt */
base[_VP_VPIS_OFFSET] &= ~ (_VP_VPIS_DUND_MASK);
/* block display events */
base[_VP_VDCTL_OFFSET] |= _VP_VDCTL_BLKDIS_MASK;
/* Disable the edmas before settings them up */
if(!(chan->mode & _VPORT_MASK_RAW)){
EDMA_disableChannel(chan->hEdma[1]);
EDMA_clearChannel(chan->hEdma[1]);
EDMA_disableChannel(chan->hEdma[2]);
EDMA_clearChannel(chan->hEdma[2]);
}
EDMA_intDisable(chan->tcc[0]);
EDMA_intDisable(chan->tcc[1]);
EDMA_disableChannel(chan->hEdma[0]);
EDMA_clearChannel(chan->hEdma[0]);
if(chan->mergeFlds) {
numEvents = chan->numEventsFld1;
} else {
numEvents = chan->numEvents;
}
/* set up DMA parameters again */
EDMA_RSETH(chan->hEdma[0], SRC, chan->curViop->frame.iFrm.y1);
EDMA_RSETH(chan->hEdma[0], CNT, EDMA_CNT_RMK(numEvents - 1,
chan->yThrld << 1));
if(!(chan->mode & _VPORT_MASK_RAW)){
EDMA_RSETH(chan->hEdma[1], SRC, chan->curViop->frame.iFrm.cb1);
EDMA_RSETH(chan->hEdma[2], SRC, chan->curViop->frame.iFrm.cr1);
EDMA_RSETH(chan->hEdma[1], CNT,
EDMA_CNT_RMK(numEvents - 1, chan->cThrld << 1));
EDMA_RSETH(chan->hEdma[2], CNT,
EDMA_CNT_RMK(numEvents - 1, chan->cThrld << 1));
}
/* enable the edma events again before settings them up */
EDMA_enableChannel(chan->hEdma[1]);
EDMA_enableChannel(chan->hEdma[2]);
EDMA_intEnable(chan->tcc[0]);
EDMA_intEnable(chan->tcc[1]);
EDMA_enableChannel(chan->hEdma[0]);
base[_VP_VDCTL_OFFSET] |= VP_VDCTL_VDEN_ENABLE << _VP_VDCTL_VDEN_SHIFT;
/* wait for display counters and control signals to sync up */
do {
stat = base[_VP_VDSTAT_OFFSET];
i ++ ;
}while(!(stat & 0x70000000) && i < 1000000);
base[_VP_VDSTAT_OFFSET] = stat;
do {
stat = base[_VP_VDSTAT_OFFSET];
i ++;
}while(!(stat & 0x70000000) && i < 1000000);
base[_VP_VDCTL_OFFSET] &= ~(_VP_VDCTL_BLKDIS_MASK);
/* re-enable under run interrupt */
base[_VP_VPIE_OFFSET] |= _VP_VPIE_DUND_MASK;
return IOM_COMPLETED;
}
/*
* ======== _getlastActiveLine ========
* get the line number of the last active line
*/
static Int _getlastActiveLine(VPORTDIS_Params* params)
{
int lastActiveLine = -1;
switch (params->fldOp){
case VPORT_FLDOP_FRAME:
case VPORT_FLDOP_FLD2:
lastActiveLine = params->vBlnkYStopFld2
+ params->imgVOffsetFld2
+ params->imgVSizeFld2;
break;
case VPORT_FLDOP_FLD1:
case VPORT_FLDOP_PROGRESSIVE:
lastActiveLine = params->vBlnkYStopFld1
+ params->imgVOffsetFld1
+ params->imgVSizeFld1;
break;
}
return lastActiveLine;
}
/*
* ======== _getNumPendingIORqsts ========
* get number of frames in qIn
*/
static Int _getNumPendingIORqsts(Ptr chanp, Ptr args)
{
_VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
QUE_Handle nextElem = &chan->qIn;
int i = 0;
while((nextElem = QUE_next(nextElem)) != &chan->qIn){
i++;
}
if(chan->curViop != chan->nextViop) i++;
*(int *)args = i;
return IOM_COMPLETED;
}
/*
* ======== _setVIntCb ========
* set video port interrutp call-back
*/
static Int _setVIntCb(Ptr chanp, Ptr args)
{
_VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
volatile Int* base = (volatile Int *)chan->base;
VPORT_VIntCbParams* vIntCbParams = (void *)args;
Int mask = vIntCbParams->vIntMask;
Uns vif2 = 0, vInt2 = 0, vif1 = 0, vInt1 = 0;
HWI_Attrs attrs = HWI_ATTRS;
chan->vIntMask = mask;
/* check to see if vertical interrupt is enabled */
if(!chan->asyncModeEnable) {
if(mask & VPORT_INT_VINT1) {
vif1 = 1;
vInt1 = vIntCbParams->vIntLine;
}
if(mask & VPORT_INT_VINT2) {
vif2 = 1;
vInt2 = vIntCbParams->vIntLine;
}
} else {
return IOM_EINUSE;
}
base[_VP_VDVINT_OFFSET] = VP_VDVINT_RMK(vif2,
vInt2, vif1, vInt1);
if(mask) {
mask |= 1; /* turn on video port interrupt */
attrs.arg = chan->portNum;
IRQ_map(IRQ_EVT_VINT0 + chan->portNum, vIntCbParams->irqId);
HWI_dispatchPlug(vIntCbParams->irqId, (Fxn)displayISR, -1, &attrs);
IRQ_disable(IRQ_EVT_VINT0 + chan->portNum);
IRQ_clear(IRQ_EVT_VINT0 + chan->portNum);
}
base[_VP_VPIE_OFFSET] |= mask; /* register write */
chan->vIntFxn = vIntCbParams->vIntCbFxn;
chan->vIntCbArg = vIntCbParams->cbArg;
return IOM_COMPLETED;
}
static Int _frmAlmostCmopleteIsr(int portNum)
{
_VPORT_ChanObj* chan = &chanObjs[portNum];
FVID_Frame *viop, *viopOut;
Uint32 gie = IRQ_globalDisable();
Int offset = chan->nextEDMARlds << 1;
if(!chan->startFlag) return -1;
assert(chan->asyncCallBackFxn != INV);
if((viop = (FVID_Frame *)QUE_dequeue(&chan->qOut))
==(FVID_Frame *)&chan->qOut) {
/* queue enpty */
viop = INV;
}
viopOut = viop;
if(chan->pullDownMode == VPORTDIS_PULLDOWN_24P_30I){
if(chan->asyncFrameCt < 2){ /* 0, 1 */
chan->asyncCallBackFxn(chan->asyncCbArg, chan->asyncFrameCt, &viopOut);
if(viop == viopOut && viopOut != INV){
QUE_enqueue(&chan->qOut, viopOut);
} else if(viopOut != INV){
chan->nextViop = viopOut;
/* now modify the EDMA rld entries */
EDMA_RSETH(chan->hRld[offset], SRC,
viopOut->frame.iFrm.y1);
EDMA_RSETH(chan->hRld[offset + 1], SRC,
viopOut->frame.iFrm.y2);
if(!(chan->mode & _VPORT_MASK_RAW)){
EDMA_RSETH(chan->hRld[4 + offset], SRC,
viopOut->frame.iFrm.cb1);
EDMA_RSETH(chan->hRld[5 + offset], SRC,
viopOut->frame.iFrm.cb2);
EDMA_RSETH(chan->hRld[8 + offset], SRC,
viopOut->frame.iFrm.cr1);
EDMA_RSETH(chan->hRld[9 + offset], SRC,
viopOut->frame.iFrm.cr2);
}
chan->asyncFrameCt ++;
} else {
chan->asyncFrameCt = 0;
}
}else if(chan->asyncFrameCt < 4) { /* 2, 3 */
chan->asyncCallBackFxn(chan->asyncCbArg, chan->asyncFrameCt, &viopOut);
if(viop == viopOut && viopOut != INV){
QUE_enqueue(&chan->qOut, viopOut);
} else if(viopOut != INV){
chan->nextViop = viopOut;
EDMA_RSETH(chan->hRld[offset + 1], SRC,
viopOut->frame.iFrm.y2);
if(!(chan->mode & _VPORT_MASK_RAW)){
EDMA_RSETH(chan->hRld[5 + offset], SRC,
viopOut->frame.iFrm.cb2);
EDMA_RSETH(chan->hRld[9 + offset], SRC,
viopOut->frame.iFrm.cr2);
}
chan->asyncFrameCt ++;
} else {
chan->asyncFrameCt = 0;
}
}else { /* 4 */
chan->asyncFrameCt = 0;
QUE_enqueue(&chan->qOut, viop);
}
} else if(chan->pullDownMode == VPORTDIS_PULLDOWN_24P_60P){
if(chan->asyncFrameCt == 1 || chan->asyncFrameCt == 4) {
chan->asyncCallBackFxn(chan->asyncCbArg, &viopOut);
if(viop == viopOut && viopOut != INV){
QUE_enqueue(&chan->qOut, viopOut);
} else if(viopOut != INV){
chan->nextViop = viopOut;
EDMA_RSETH(chan->hRld[offset], SRC,
viopOut->frame.iFrm.y1);
if(!(chan->mode & _VPORT_MASK_RAW)){
EDMA_RSETH(chan->hRld[4 + offset], SRC,
viopOut->frame.iFrm.cb1);
EDMA_RSETH(chan->hRld[8 + offset], SRC,
viopOut->frame.iFrm.cr1);
}
}
chan->asyncFrameCt ++;
if(chan->asyncFrameCt == 5) chan->asyncFrameCt = 0;
} else {
QUE_enqueue(&chan->qOut, viop);
chan->asyncFrameCt = 0;
}
} else { /* not in pull-down modes */
chan->asyncCallBackFxn(chan->asyncCbArg, chan->asyncFrameCt, &viopOut);
if(viop == viopOut && viopOut != INV){
QUE_enqueue(&chan->qOut, viopOut);
} else if(viopOut != INV){
chan->nextViop = viopOut;
if(chan->mergeFlds){
EDMA_RSETH(chan->hRld[offset], SRC,
viopOut->frame.iFrm.y1);
EDMA_RSETH(chan->hRld[offset + 1], SRC,
viopOut->frame.iFrm.y2);
if(!(chan->mode & _VPORT_MASK_RAW)){
EDMA_RSETH(chan->hRld[4 + offset], SRC,
viopOut->frame.iFrm.cb1);
EDMA_RSETH(chan->hRld[5 + offset], SRC,
viopOut->frame.iFrm.cb2);
EDMA_RSETH(chan->hRld[8 + offset], SRC,
viopOut->frame.iFrm.cr1);
EDMA_RSETH(chan->hRld[9 + offset], SRC,
viopOut->frame.iFrm.cr2);
}
} else {
EDMA_RSETH(chan->hRld[offset], SRC,
viopOut->frame.iFrm.y1);
if(!(chan->mode & _VPORT_MASK_RAW)){
EDMA_RSETH(chan->hRld[4 + offset], SRC,
viopOut->frame.iFrm.cb1);
EDMA_RSETH(chan->hRld[8 + offset], SRC,
viopOut->frame.iFrm.cr1);
}
} /* if(chan->mergeFlds) */
}
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -