📄 vportdis.c
字号:
VP_VDVSYNS2_RMK(params->vSyncYStartFld2, params->vSyncXStartFld2);
base[_VP_VDVSYNE2_OFFSET] =
VP_VDVSYNE2_RMK(params->vSyncYStopFld2, params->vSyncXStopFld2);
base[_VP_VDCLIP_OFFSET] =
VP_VDCLIP_RMK(params->cClipHigh, params->cClipLow,
params->yClipHigh, params->yClipLow);
base[_VP_VDDEFVAL_OFFSET] = params->yDefVal |
(params->cbDefVal << 16) | (params->crDefVal << 24);
chan->resmpl = params->resmpl;
chan->scale = params->scale;
numPixels >>= params->scale;
chan->numPixels = numPixels;
numCPixels = (params->dmode & _VPORT_MASK_RAW) ? 0 : numPixels >> 1;
if(params->dmode & _VPORT_MASK_RAW) { /* raw mode */
chan->cPitch = 0;
if(params->dmode == VPORT_MODE_RAW_8BIT) {
chan->yPitch = (numPixels + 7) & (~ 7);
chan->cPitch = (numCPixels + 7) & (~ 7);
} else if(params->dmode == VPORT_MODE_RAW_10BIT) {
if(params->bpk10Bit == VPORTDIS_BPK_10BIT_DENSE){
chan->yPitch = (numPixels * 4 / 3 + 7) & (~ 7);
}else {
chan->yPitch = (numPixels * 2 + 7) & (~ 7);
}
} else if(params->dmode == VPORT_MODE_RAW_16BIT) {
chan->yPitch = (numPixels * 2 + 7) & (~ 7);
} else {
chan->yPitch = (numPixels * 4 + 7) & (~ 7);
}
} else {
if(params->dmode & _VPORT_MASK_10BIT) {
if(params->bpk10Bit == VPORTDIS_BPK_10BIT_DENSE){
chan->yPitch = (numPixels * 4 / 3 + 7) & (~ 7);
chan->cPitch = (numCPixels* 4 / 3 + 7) & (~ 7);
}else {
chan->yPitch = (numPixels * 2 + 7) & (~ 7);
chan->cPitch = (numCPixels * 2 + 7) & (~ 7);
}
} else {/* 8 bit mode */
chan->yPitch = (numPixels + 7) & (~ 7);
chan->cPitch = (numCPixels + 7) & (~ 7);
}
}
chan->yThrld = params->thrld;
if(params->mergeFlds && params->fldOp == VPORT_FLDOP_FRAME) {
/* frame capture and merge 2 fields into one frame */
/* make sure threshold is same as line size */
chan->yThrld = chan->yPitch >> 3;
chan->numEventsFld1 = chan->numLinesFld1;
chan->numEvents = chan->numLines;
chan->mergeFlds = TRUE;
}else {
/* these two asserts make sure that total transfer sizes of */
/* both the whole frame and the first field are multiples */
/* of the threshold */
assert(((chan->yPitch*chan->numLinesFld1)/(chan->yThrld << 3))
*(chan->yThrld << 3) == (chan->yPitch*chan->numLinesFld1));
assert(((chan->yPitch*chan->numLines)/(chan->yThrld << 3))
*(chan->yThrld << 3) == (chan->yPitch*chan->numLines));
chan->numEventsFld1 =
chan->yPitch * chan->numLinesFld1 / (chan->yThrld << 3);
chan->numEvents =
chan->yPitch * chan->numLines / (chan->yThrld << 3);
chan->mergeFlds = FALSE;
}
if(params->dmode & _VPORT_MASK_RAW) {
chan->cThrld = 0;
}
else {
chan->cThrld = (chan->yThrld + 1) >> 1;
}
base[_VP_VDTHRLD_OFFSET] =
VP_VDTHRLD_RMK(chan->yThrld,params->incPix,chan->yThrld);
base[_VP_VDDISPEVT_OFFSET] =
VP_VDDISPEVT_RMK((chan->numEvents-chan->numEventsFld1),
chan->numEventsFld1 );
chan->mode = params->dmode;
chan->status |= _VPORT_CFGED;
}
return IOM_COMPLETED;
}
/*
* ======== displayEdmaISR ========
*/
static void displayEdmaISR(tcc)
{
Int i;
FVID_Frame *viop, *curViop;
Int offset;
/* find out the source of the edma interrupt */
for(i = 0; i < _VP_PORT_CNT; i ++) {
_VPORT_ChanObj* chan = &chanObjs[i];
if((chan->status & _VPORT_READY) &&
(tcc == chan->tcc[0] || tcc == chan->tcc[1])){
/* re-sync tcc with activeEDMARlds */
/* they may be out of sync after interrupt over-run */
/* e.g. execution is halted at break-point */
chan->nextEDMARlds = (tcc == chan->tcc[0]) ? 0 : 1;
offset = chan->nextEDMARlds << 1;
/* update the current and next viop pointers */
curViop = chan->curViop;
chan->curViop = chan->nextViop;
if((viop = (FVID_Frame *)QUE_dequeue(&chan->qIn))
!= (FVID_Frame *)&chan->qIn) {
/* queue IS not empty */
chan->nextViop = viop;
}else {
chan->queEmpty = TRUE;
}
/* Update the EDMA reload entry */
if(chan->mergeFlds){
EDMA_RSETH(chan->hRld[offset], SRC,
chan->nextViop->frame.iFrm.y1);
EDMA_RSETH(chan->hRld[offset + 1], SRC,
chan->nextViop->frame.iFrm.y2);
if(!(chan->mode & _VPORT_MASK_RAW)){
EDMA_RSETH(chan->hRld[4 + offset], SRC,
chan->nextViop->frame.iFrm.cb1);
EDMA_RSETH(chan->hRld[5 + offset], SRC,
chan->nextViop->frame.iFrm.cb2);
EDMA_RSETH(chan->hRld[8 + offset], SRC,
chan->nextViop->frame.iFrm.cr1);
EDMA_RSETH(chan->hRld[9 + offset], SRC,
chan->nextViop->frame.iFrm.cr2);
}
} else {
EDMA_RSETH(chan->hRld[offset], SRC,
chan->nextViop->frame.iFrm.y1);
if(! (chan->mode & _VPORT_MASK_RAW)){
EDMA_RSETH(chan->hRld[offset + 4], SRC,
chan->nextViop->frame.iFrm.cb1);
EDMA_RSETH(chan->hRld[offset + 8], SRC,
chan->nextViop->frame.iFrm.cr1);
}
}/* if(chan->mergeFlds) {*/
if(curViop != chan->curViop) {
if(chan->packetIOM != INV) {
/* call the channel's callback function */
*(void **)chan->packetIOM->addr = curViop;
chan->packetIOM->size = sizeof(FVID_Frame);
chan->cbFxn((Ptr)chan->cbArg, chan->packetIOM);
chan->packetIOM = INV;
}else {
QUE_enqueue(&chan->qOut,curViop);
}
}/*if(curViop != chan->curViop) {*/
}/*if((chan->status & READY) && tcc == chan->tcc){*/
} /*for(i = 0; i <_VP_PORT_CNT; i++) { */
}
/*
* ======== displayISR ========
*/
static void displayISR(int portNum)
{
volatile Int *base =
(volatile Int *)chanObjs[portNum].base;
Int vpis = base[_VP_VPIS_OFFSET];
Int mask = vpis & chanObjs[portNum].vIntMask;
if(mask && chanObjs[portNum].vIntFxn != INV) {
chanObjs[portNum].vIntFxn(chanObjs[portNum].cbArg, 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;
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;
}
/*
* ======== _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;
chan->vIntMask = mask;
/* check to see if vertical interrupt is enabled */
if(mask & VPORT_INT_VINT1) {
vif1 = 1;
vInt1 = vIntCbParams->vIntLine;
}
if(mask & VPORT_INT_VINT2) {
vif2 = 1;
vInt2 = vIntCbParams->vIntLine;
}
base[_VP_VDVINT_OFFSET] = VP_VDVINT_RMK(vif2,
vInt2, vif1, vInt1);
if(mask) {
mask |= 1; /* turn on video port interrupt */
IRQ_map(IRQ_EVT_VINT0 + chan->portNum, vIntCbParams->irqId);
HWI_dispatchPlug(vIntCbParams->irqId, (Fxn)displayISR, -1, NULL);
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;
return IOM_COMPLETED;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -