⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vportcap.c

📁 dm642evm板的音视频驱动源文件
💻 C
📖 第 1 页 / 共 4 页
字号:
    FVID_Frame* viop;                             
    Uint32 gie = IRQ_globalDisable();
    Int retVal = IOM_PENDING;  
    Int offset = chan->nextEDMARlds << 1;
    Bool nextViopChanged = FALSE;             
    Bool notToLate = TRUE;
    volatile Int* cBase = (volatile Int *)chan->base;
    Int capStatReg = cBase[_VP_VCASTAT_OFFSETA];
    volatile Int* base = (volatile Int *)portObjs[chan->portNum].base;
    Int vpis = base[_VP_VPIS_OFFSET];
    short lineNum;
    
     
    /* get the current line number being captured */
    lineNum = (capStatReg & _VP_VCASTAT_VCYPOS_MASK)
                           >> _VP_VCASTAT_VCYPOS_SHIFT;
            
    /* account for field/frame operation modes */ 
    lineNum += chan->numLinesFld1 
        * ((capStatReg & _VP_VCASTAT_VCFLD_MASK) >> _VP_VCASTAT_VCFLD_SHIFT);    

    /* make sure we are not too close to the end of a frame */
    notToLate = (lineNum < (chan->lastLineNum - 5));

    assert(chan->status & _VPORT_READY);
    if(packet->cmd != FVID_ALLOC 
        && packet->cmd != FVID_FREE 
        && packet->cmd != FVID_EXCHANGE){    
        /* other commands not supported */
        return IOM_ENOTIMPL;    
    }
    
    if(packet->cmd != FVID_ALLOC) {/* FVID_FREE or FVID_EXCHANGE */
        viop = *(void **)packet->addr; /* pointer of a video I/O packet */
        if(chan->queEmpty && notToLate) {
            /* don't put it into queue, update the rld register directly */
            chan->nextViop = viop; 
            nextViopChanged = TRUE;
        } 
        else {               
            QUE_enqueue(&chan->qIn, (QUE_Handle)viop);    
        }
        chan->queEmpty = FALSE;
        retVal = packet->status = IOM_COMPLETED;
    }
    if(packet->cmd != FVID_FREE) {/* FVID_ALLOC or FVID_EXCHANGE */
        if(chan->mrViop != INV) {
            /* only when there is no outstanding pending request */
            if(chan->packetIOM == INV){
                if(chan->nextViop != chan->mrViop){
                    *(void **)packet->addr = (void *)chan->mrViop;
                    chan->mrViop = INV;
                    packet->size = sizeof(FVID_Frame);
                    retVal = packet->status = IOM_COMPLETED;                
                } else {
                    if (notToLate) {
                        *(void **)packet->addr = (void *)chan->mrViop;
                        chan->mrViop = INV;
                        packet->size = sizeof(FVID_Frame);
                        retVal = packet->status = IOM_COMPLETED;
                        /* If queue is already empty, it means the driver currently*/
                        /* only owns one frame, which is the current frame. So make*/
                        /* the next frame the same as the current one              */
                        chan->nextViop = chan->curViop;
                    } else {
                        chan->mrViop = INV; /* too late, just recycle the mrViop */                    
                        chan->packetIOM = packet;
                        retVal = packet->status = IOM_PENDING;
                    }
                }
            }
            else retVal = IOM_EINUSE;    
        } else {
            chan->packetIOM = packet;
            retVal = packet->status = IOM_PENDING;
        }        
    }    
    if(nextViopChanged) {
        /* now modify the EDMA rld entries */
        if(chan->interlaced){
            EDMA_RSETH(chan->hRld[offset], DST, 
                chan->nextViop->frame.iFrm.y1);
            EDMA_RSETH(chan->hRld[offset + 1], DST, 
                chan->nextViop->frame.iFrm.y2);
            EDMA_RSETH(chan->hRld[4 + offset], DST, 
                chan->nextViop->frame.iFrm.cb1);     
            EDMA_RSETH(chan->hRld[5 + offset], DST, 
                chan->nextViop->frame.iFrm.cb2);                         
            EDMA_RSETH(chan->hRld[8 + offset], DST, 
                chan->nextViop->frame.iFrm.cr1);     
            EDMA_RSETH(chan->hRld[9 + offset], DST, 
                chan->nextViop->frame.iFrm.cr2);              
        } else {
            EDMA_RSETH(chan->hRld[offset], DST, 
                chan->nextViop->frame.iFrm.y1);
            EDMA_RSETH(chan->hRld[4 + offset], DST, 
                chan->nextViop->frame.iFrm.cb1);     
            EDMA_RSETH(chan->hRld[8 + offset], DST, 
                chan->nextViop->frame.iFrm.cr1);                         
        } /* if(chan->interlaced) */            
    }    
    
    if(vpis & 0x40) {/* short field detected, re-sync */
        _covrRecover(chanp);
    }    
            
    IRQ_globalRestore(gie);
    return retVal;
}


/*
 *  ======== _captureEdmaISR ========
 *  EDMA ISR
 */            
static void captureEdmaISR(Int tcc) 
{
    Int i, j;
    Int offset;
    FVID_Frame *viop, *curViop;      

    /* find out the source of the edma interrupt */
    for(j = 0; j < _VP_PORT_CNT; j ++) {
        for(i = 0; i < _VPORT_CHAN_CNT; i ++ ){ /* loop through two channels */
            _VPORT_ChanObj* chan = &portObjs[j].chanObj[i];    

            if((chan->status & _VPORT_READY)
              && (tcc == chan->tcc[0] || tcc == chan->tcc[1])){

                if(chan->autoSyncEnable) {
                   _autoSync(chan);
                }

                /* 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;             
                
                /* update the most recent viop */
                if(curViop != chan->mrViop  && chan->mrViop != INV) {
                      QUE_enqueue(&chan->qIn, chan->mrViop);
                } 
                chan->mrViop = curViop;

                if((viop = (FVID_Frame *)QUE_dequeue(&chan->qIn))
                    !=(FVID_Frame *)&chan->qIn) {
                    /* queue IS not empty */
                    chan->nextViop = viop;
                }else {
                    if(chan->packetIOM == INV) {
                        /* in queue is empty, but no request is pending */
                        /* recycle the current VIOP back                */
                        /* but still set it as the most recent VIOP     */
                        chan->nextViop = curViop;
                    }
                    chan->queEmpty = TRUE;
                }                              

                /* call the channel's callback function */
                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->packetIOM->status = IOM_COMPLETED;
                         chan->cbFxn((Ptr)chan->cbArg, chan->packetIOM);   
                         chan->packetIOM = INV;
                         chan->mrViop = INV;
                    }else if(chan->queEmpty){
                        chan->nextViop = chan->mrViop;
                    }
                }else {
                    chan->mrViop = INV;
                }        
                /* Update the EDMA reload entry  */
                if(chan->interlaced){
                    EDMA_RSETH(chan->hRld[offset], DST, 
                        chan->nextViop->frame.iFrm.y1);
                    EDMA_RSETH(chan->hRld[offset + 1], DST, 
                        chan->nextViop->frame.iFrm.y2);
                    if(!(chan->mode & _VPORT_MASK_RAW)){
                        EDMA_RSETH(chan->hRld[4 + offset], DST, 
                            chan->nextViop->frame.iFrm.cb1);     
	                    EDMA_RSETH(chan->hRld[5 + offset], DST, 
	                        chan->nextViop->frame.iFrm.cb2);                         
	                    EDMA_RSETH(chan->hRld[8 + offset], DST, 
	                        chan->nextViop->frame.iFrm.cr1);     
	                    EDMA_RSETH(chan->hRld[9 + offset], DST, 
	                        chan->nextViop->frame.iFrm.cr2);                         
	                }
                }else {
                    EDMA_RSETH(chan->hRld[offset], DST, 
                        chan->nextViop->frame.iFrm.y1);
                    if(!(chan->mode & _VPORT_MASK_RAW)){
	                    EDMA_RSETH(chan->hRld[offset + 4], DST, 
	                        chan->nextViop->frame.iFrm.cb1);
	                    EDMA_RSETH(chan->hRld[offset + 8], DST, 
	                        chan->nextViop->frame.iFrm.cr1);
                    }
                }/* if(chan->interlaced) {*/


            }    
        }
    }
}


/*
 *  ======== _configCh ========
 *  configure video port channel settings
 */
static Int _configCh(
        Ptr                 chanp, 
        VPORTCAP_Params  *params
        )
{
    _VPORT_ChanObj* chan= (_VPORT_ChanObj *)chanp;
    volatile Int vpCtl, vcCtl, fld1Strt, fld2Strt, fld1Stop, fld2Stop;
    volatile Int* base = (volatile Int *)chan->base;                         
    Int retVal = IOM_COMPLETED;
    Int numPixels, numLines, numCPixels;  
    
    
    if(chan->status & _VPORT_OPENED) { 
        chan->vIntMask = 0;
        QUE_new(&chan->qIn);
        chan->vIntFxn = (VPORT_IntCallBack)INV;
        chan->queEmpty = FALSE;   
        chan->mrViop = INV;
        chan->packetIOM = INV;     
        chan->vIntCbArg = (Int)INV;
        chan->bufSz = 0;
        chan->mode = params->cmode;
        if(chan->mode & _VPORT_MASK_RAW) {
            chan->autoSyncEnable = FALSE; // no auto-sync in raw mode 
        } else {
            chan->autoSyncEnable = params->autoSyncEnable;
        }

        if(!(chan->mode & _VPORT_MASK_RAW)) {        
	        /* configure channel A capture settings  */
	        vcCtl = VP_VCACTL_RMK(0,1,0,params->fldInv, 
	            params->extCtl, params->fldDect, params->vCtRst,
	            params->hCtRst, 0, params->bpk10Bit,1,1, 
	            params->resmpl,params->scale,1,
	            ((params->fldOp & 4) >> 2), 
	            ((params->fldOp & 2) >> 1), 
	            (params->fldOp & 1), 
	            params->cmode);
	
	        fld1Strt = params->fldXStrt1 + (params->fldYStrt1 << 16);
	        fld1Stop = params->fldXStop1 + (params->fldYStop1 << 16);
	        fld2Strt = params->fldXStrt2 + (params->fldYStrt2 << 16);
	        fld2Stop = params->fldXStop2 + (params->fldYStop2 << 16);
	        if(params->fldOp == VPORT_FLDOP_FRAME) {
	            assert(params->fldXStop1 == params->fldXStop2);
	            assert(params->fldXStrt1 == params->fldXStrt2);
	        }   
	        /* reset channel */
	        base[_VP_VCACTL_OFFSETA] |=  
	          VP_VCACTL_RSTCH_RESET << _VP_VCACTL_RSTCH_SHIFT;
	        _delay(2000);
	        base[_VP_VCACTL_OFFSETA]   = vcCtl;
	        base[_VP_VCASTRT1_OFFSETA] = fld1Strt;
	        base[_VP_VCASTOP1_OFFSETA] = fld1Stop;
	        base[_VP_VCASTRT2_OFFSETA] = fld2Strt;
	        base[_VP_VCASTOP2_OFFSETA] = fld2Stop;
	        numPixels = params->fldXStop1 - params->fldXStrt1 + 1;/* line size */
	        numLines = 0;
	        
	        if(params->fldOp != VPORT_FLDOP_FLD2){
	            numLines += params->fldYStop1 - params->fldYStrt1 + 1;
	        }
	        chan->numLinesFld1 = numLines;
	        chan->numTotalLinesFld1 = params->fldYStop1;
	        
	        if(params->fldOp == VPORT_FLDOP_FLD2
	          || params->fldOp == VPORT_FLDOP_FRAME){
	            numLines += params->fldYStop2 - params->fldYStrt2 + 1;
	        }
	        chan->resmpl = params->resmpl;
	        chan->scale = params->scale;
	        chan->numLines = numLines;
	        numPixels >>= params->scale;
	        numCPixels = numPixels >> 1;
	        /* set both field1 and field2 threshold to the line size */
	        chan->numPixels = numPixels;
	        chan->lastLineNum = chan->numLines;        
	        if(params->cmode & _VPORT_MASK_10BIT){
	            /* 10-bit BT.656 or 20-bit Y/C mode */
	            if( params->bpk10Bit == VPORTCAP_BPK_10BIT_ZERO_EXTENDED
	             || params->bpk10Bit == VPORTCAP_BPK_10BIT_SIGN_EXTENDED){
	                chan->yPitch = (numPixels * 2 + 7) & (~ 7);
	                chan->cPitch = (numCPixels * 2 + 7) & (~ 7);
	            }else {
	                chan->yPitch = (numPixels * 4 / 3 + 7) & (~ 7);
	                chan->cPitch = (numCPixels* 4 / 3 + 7) & (~ 7);
	            }
	        } else {/* 8-bit BT.656 or 16-bit Y/C mode */
	            chan->yPitch = (numPixels + 7) & (~ 7);
	            chan->cPitch = (numCPixels + 7) & (~ 7);
	        }     
	        chan->yThrld = params->thrld;
	        chan->interlaced = TRUE;  
	        if(params->fldOp == VPORT_FLDOP_FRAME && params->mergeFlds) { 
	            /* merge field comments */
	            /* frame capture and merge 2 fields into one frame */
	            /* set threshold is same as line size */
	            chan->yThrld = chan->yPitch >> 3;
	            chan->numEventsFld1 = chan->numLinesFld1;
	            chan->numEvents = chan->numLines;
	        }else {            
	            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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -