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

📄 copy of vportcap.c

📁 dm642_video_stream
💻 C
📖 第 1 页 / 共 4 页
字号:


/*
 *  ======== mdSubmitChan ========
 */
static Int  mdSubmitChan(Ptr chanp, IOM_Packet *packet)
{
    _VPORT_ChanObj *pChan = (_VPORT_ChanObj*)chanp;
    FVID_Frame *viop;                             
    Uint32 gie = IRQ_globalDisable();
    Int retVal = IOM_PENDING;  
    Int offset = pChan->nextEDMARlds << 1;
    Bool nextViopChanged = FALSE;             
    Bool notTooLate = TRUE;
    volatile Int *chBase = (volatile Int*)pChan->base;
    Int capStatReg;
    volatile Int* base = (volatile Int *)gsPortObjs[pChan->portNum].base;
    Int vpis = base[_VP_VPIS_OFFSET];
    short lineNum;
                   
    if (pChan->chanNum == 0)
    { /*channel A*/             
    	capStatReg = chBase[_VP_VCASTAT_OFFSETA];
    	
    	/* get the current line number being captured */
    	lineNum = (capStatReg & _VP_VCASTAT_VCYPOS_MASK)
        	                   >> _VP_VCASTAT_VCYPOS_SHIFT;                      
    
		/* account for field/frame operation modes */         	                       	                   
        lineNum += pChan->numLinesFld1 
        	* ((capStatReg & _VP_VCASTAT_VCFLD_MASK) >> _VP_VCASTAT_VCFLD_SHIFT);            	                   
    }
    else if (pChan->chanNum == 1)
    { /*channel B*/
    	capStatReg = chBase[_VP_VCBSTAT_OFFSETB];       
    	
    	/* get the current line number being captured */
       	lineNum = (capStatReg & _VP_VCBSTAT_VCYPOS_MASK)
        	                   >> _VP_VCBSTAT_VCYPOS_SHIFT;
		
		/* account for field/frame operation modes */						
		lineNum += pChan->numLinesFld1 
        	* ((capStatReg & _VP_VCBSTAT_VCFLD_MASK) >> _VP_VCBSTAT_VCFLD_SHIFT);            	                   
    }
    
    /* make sure we are not too close to the end of a frame */
    notTooLate = (lineNum < (pChan->lastLineNum - 5));
      
    if (!(pChan->status & _VPORT_READY))
    {
    	assert(pChan->status & _VPORT_READY); 
    }
        
    if (packet->cmd != FVID_ALLOC && packet->cmd != FVID_FREE && packet->cmd != FVID_EXCHANGE)
    {    
    	IRQ_globalRestore(gie);
        /* 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 (pChan->queEmpty && notTooLate) 
        {
            /* don't put it into queue, update the rld register directly */
            pChan->nextViop = viop; 
            nextViopChanged = TRUE;
        } 
        else 
        {               
            QUE_enqueue(&pChan->qIn, (QUE_Handle)viop);    
        }
        pChan->queEmpty = FALSE;
        retVal = packet->status = IOM_COMPLETED;
    }     
    
    if (packet->cmd != FVID_FREE) 
    {/* FVID_ALLOC or FVID_EXCHANGE */
    
        if (pChan->mrViop != INV) 
        {
            /* only when there is no outstanding pending request */
            if (pChan->packetIOM == INV)
            {
                if (pChan->nextViop != pChan->mrViop)
                {
                    *(void**)packet->addr = (void*)pChan->mrViop;
                    pChan->mrViop = INV;
                    packet->size = sizeof(FVID_Frame);
                    retVal = packet->status = IOM_COMPLETED;                
                } 
                else 
                {
                    if (notTooLate) 
                    {
                        *(void**)packet->addr = (void*)pChan->mrViop;
                        pChan->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              */
                        pChan->nextViop = pChan->curViop;
                    } 
                    else 
                    {
                        pChan->mrViop = INV; /* too late, just recycle the mrViop */                    
                        pChan->packetIOM = packet;
                        retVal = packet->status = IOM_PENDING;
                    }
                }
            }
            else 
            	retVal = IOM_EINUSE;    
        } 
        else 
        {
            pChan->packetIOM = packet;
            retVal = packet->status = IOM_PENDING;
        }        
    }    
    
    if (nextViopChanged) 
    {
        /* now modify the EDMA rld entries */
        if(pChan->mergeFlds)
        {
            EDMA_RSETH(pChan->hRld[offset], DST, 
                pChan->nextViop->frame.iFrm.y1);
            EDMA_RSETH(pChan->hRld[offset + 1], DST, 
                pChan->nextViop->frame.iFrm.y2);
            EDMA_RSETH(pChan->hRld[4 + offset], DST, 
                pChan->nextViop->frame.iFrm.cb1);     
            EDMA_RSETH(pChan->hRld[5 + offset], DST, 
                pChan->nextViop->frame.iFrm.cb2);                         
            EDMA_RSETH(pChan->hRld[8 + offset], DST, 
                pChan->nextViop->frame.iFrm.cr1);     
            EDMA_RSETH(pChan->hRld[9 + offset], DST, 
                pChan->nextViop->frame.iFrm.cr2);              
        } 
        else 
        {
            EDMA_RSETH(pChan->hRld[offset], DST, 
                pChan->nextViop->frame.iFrm.y1);
            EDMA_RSETH(pChan->hRld[4 + offset], DST, 
                pChan->nextViop->frame.iFrm.cb1);     
            EDMA_RSETH(pChan->hRld[8 + offset], DST, 
                pChan->nextViop->frame.iFrm.cr1);                         
        } /* if(pChan->mergeFlds) */            
    } 

	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 ++) 
    {   /*_VP_PORT_CNT = 3*/
        for (i = 0; i < _VPORT_CHAN_CNT; i ++ )
        { /* _VPORT_CHAN_CNT = 2 defined in _vport.h, loop through two channels */
            _VPORT_ChanObj *pChan = &gsPortObjs[j].chanObj[i];    
            if ((pChan->status & _VPORT_READY) && (tcc == pChan->tcc[0] || tcc == pChan->tcc[1]))
            {
				if (pChan->autoSyncEnable) 
				{
                   _autoSync(pChan);
                }

                /* re-sync tcc with activeEDMARlds */
                /* they may be out of sync after interrupt over-run */
                /* e.g. execution is halted at break-point */
                pChan->nextEDMARlds = (tcc == pChan->tcc[0]) ? 0 : 1;
                offset = pChan->nextEDMARlds << 1;

                /* update the current and next viop pointers */
                curViop = pChan->curViop;
                pChan->curViop = pChan->nextViop;             
                
                /* update the most recent viop */
                if (curViop != pChan->mrViop  && pChan->mrViop != INV) 
                {
                	QUE_enqueue(&pChan->qIn, pChan->mrViop);
                }
                 
                pChan->mrViop = curViop;

                if ((viop = (FVID_Frame*)QUE_dequeue(&pChan->qIn))
                    != (FVID_Frame*)&pChan->qIn) 
                {
                    /* queue IS not empty */
                    pChan->nextViop = viop;
                }
                else 
                {
                    if(pChan->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     */
                        pChan->nextViop = curViop;
                    }
                    pChan->queEmpty = TRUE;
                }                              

                /* call the channel's callback function */
                if (curViop != pChan->curViop) 
                {
                    if (pChan->packetIOM != INV) 
                    {
                         /* call the channel's callback function */
                         *(void **)pChan->packetIOM->addr = curViop;             
                         pChan->packetIOM->size = sizeof(FVID_Frame);
                         pChan->cbFxn((Ptr)pChan->cbArg, pChan->packetIOM);   
                         pChan->packetIOM = INV;
                         pChan->mrViop = INV;
                    }
                    else if(pChan->queEmpty)
                    {
                        pChan->nextViop = pChan->mrViop;
                    }
                }
                else 
                {
                    pChan->mrViop = INV;
                }   
                     
                /* Update the EDMA reload entry  */
                if (pChan->mergeFlds)
                {
                    EDMA_RSETH(pChan->hRld[offset], DST, 
                        pChan->nextViop->frame.iFrm.y1);
                    EDMA_RSETH(pChan->hRld[offset + 1], DST, 
                        pChan->nextViop->frame.iFrm.y2);
                    EDMA_RSETH(pChan->hRld[offset + 4], DST, 
                        pChan->nextViop->frame.iFrm.cb1);     
                    EDMA_RSETH(pChan->hRld[offset + 5], DST, 
                        pChan->nextViop->frame.iFrm.cb2);                         
                    EDMA_RSETH(pChan->hRld[offset + 8], DST, 
                        pChan->nextViop->frame.iFrm.cr1);     
                    EDMA_RSETH(pChan->hRld[offset + 9], DST, 
                        pChan->nextViop->frame.iFrm.cr2);                         
                }
                else 
                {
                    EDMA_RSETH(pChan->hRld[offset], DST, 
                        pChan->nextViop->frame.iFrm.y1);
                    EDMA_RSETH(pChan->hRld[offset + 4], DST, 
                        pChan->nextViop->frame.iFrm.cb1);
                    EDMA_RSETH(pChan->hRld[offset + 8], DST, 
                        pChan->nextViop->frame.iFrm.cr1);
                }/* if(pChan->mergeFlds) {*/
            }    
        }
    }
}


/*
 *  ======== ConfigChannel ========
 *  configure video port channel settings
 */
static Int ConfigChannel(Ptr chanp, VPChanCap_Params *params)
{
    _VPORT_ChanObj *pChan= (_VPORT_ChanObj*)chanp;
    volatile Int vpCtl, vcCtl, fld1Strt, fld2Strt, fld1Stop, fld2Stop;
    volatile Int *base = (volatile Int*)pChan->base;                         
    Int retVal = IOM_EBADIO;
    Int numPixels, numLines, numCPixels;  
    
    if (!(pChan->status & _VPORT_OPENED)) 
    	return retVal;
    
    pChan->autoSyncEnable = params->autoSyncEnable;
    	
    if (pChan->chanNum == 0)
    { /*channel A*/
        /* control register  */
        vcCtl = VP_VCACTL_RMK(0,1,0,params->fldInv, 
            					params->extCtl, params->fldDect, params->vCtRst,
            					params->hCtRst, 0, params->bpk10Bit, 0, 0, 
            					params->resmpl,params->scale,1,
            					((params->fldOp & 4) >> 2), 
            					((params->fldOp & 2) >> 1), 
            					(params->fldOp & 1), 
            					params->cmode);

		/*YStart1 value will be put from the 16th bits in VCASTRT1 register*/
        fld1Strt = params->fldXStrt1 + (params->fldYStrt1 << 16);         
		
		/*YStop1 value will be put from the 16th bits in VCASTOP1 register*/		                
        fld1Stop = params->fldXStop1 + (params->fldYStop1 << 16);
        
        /*YStart2 value will be put from the 16th bits in VCASTRT2 register*/
        fld2Strt = params->fldXStrt2 + (params->fldYStrt2 << 16);
        
        /*YStop2 value will be put from the 16th bits in VCASTOP2 register*/
        fld2Stop = params->fldXStop2 + (params->fldYStop2 << 16);           
        
        if(params->fldOp == VPORT_FLDOP_FRAME) 
        {
            assert(params->fldXStrt1 == params->fldXStrt2);
            assert(params->fldXStop1 == params->fldXStop2);
        }
       
       	/* 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;
        }
        
        pChan->numLinesFld1 = numLines;
		pChan->numTotalLinesFld1 = params->fldYStop1;
        
        if(params->fldOp == VPORT_FLDOP_FLD2
          || params->fldOp == VPORT_FLDOP_FRAME)
        {
            numLines += params->fldYStop2 - params->fldYStrt2 + 1;
        }
        
        pChan->resmpl = params->resmpl;
        pChan->scale = params->scale;
        pChan->numLines = numLines;  
        
        numPixels >>= params->scale;
        numCPixels = numPixels >> 1;         
        
        /* set both field1 and field2 threshold to the line size */
        pChan->numPixels = numPixels;
        pChan->lastLineNum = pChan->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)
            {
                pChan->yPitch = (numPixels * 2 + 7) & (~ 7);
                pChan->cPitch = (numCPixels * 2 + 7) & (~ 7);
            }
            else
            {
                pChan->yPitch = (numPixels * 4 / 3 + 7) & (~ 7);
                pChan->cPitch = (numCPixels* 4 / 3 + 7) & (~ 7);
            }
        } 
        else 
        {/* 8-bit BT.656 or 16-bit Y/C mode */
            pChan->yPitch = (numPixels + 7) & (~ 7);
            pChan->cPitch = (numCPixels + 7) & (~ 7);
        }
             
        pChan->yThrld = params->thrld;     /* thrld = 88 , number of doublewords threshold in the FIFO*/
		pChan->interlaced = TRUE;

        if(params->mergeFlds && params->fldOp == VPORT_FLDOP_FRAME) 
        { 
            /* merge field comments */
            /* frame capture and merge 2 fields into one frame */
            /* set threshold is same as line size */
            pChan->yThrld = pChan->yPitch >> 3;
            pChan->numEventsFld1 = pChan->numLinesFld1;
            pChan->numEvents = pChan->numLines;
            pChan->mergeFlds = TRUE;  
        }
        else 
        {            
            assert(((pChan->yPitch * pChan->numLinesFld1) / (pChan->yThrld << 3)) 
                *(pChan->yThrld << 3) == (pChan->yPitch * pChan->numLinesFld1));
            assert(((pChan->yPitch * pChan->numLines) / (pChan->yThrld << 3)) 
                *(pChan->yThrld << 3) == (pChan->yPitch * pChan->numLines));
            pChan->numEventsFld1 = 
                pChan->yPitch * pChan->numLinesFld1 / (pChan->yThrld << 3);
            pChan->numEvents = 
                pChan->yPitch * pChan->numLines / (pChan->yThrld << 3);
            
            pChan->mergeFlds = FALSE;
			
			if (params->fldOp != VPORT_FLDOP_FRAME) 
				pChan->interlaced = FALSE;
	        

⌨️ 快捷键说明

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