vportdis.c
上传用户:dahaojd
上传日期:2008-01-29
资源大小:14357k
文件大小:42k
源码类别:

DSP编程

开发平台:

C/C++

  1. /*
  2.  *  Copyright 2003 by Texas Instruments Incorporated.
  3.  *  All rights reserved. Property of Texas Instruments Incorporated.
  4.  *  Restricted rights to use, duplicate or disclose this code are
  5.  *  granted through contract.
  6.  *  
  7.  */
  8. /* "@(#) DDK 1.10.00.23 07-02-03 (ddk-b12)" */
  9. /* DSP/BIOS standard include files */
  10. #include <std.h>
  11. #include <mem.h>
  12. #include <que.h>    
  13. #include <tsk.h>
  14. /* Chip-support library include files */
  15. #include <csl.h>
  16. #include <csl_edma.h>
  17. #include <csl_vphal.h>         
  18. #include <csl_irq.h>
  19. #include <csl_cache.h>
  20. #include <csl_dat.h>
  21. /* IOM/GIO driver model include files */
  22. #include <iom.h>
  23. #include <fvid.h>                       
  24. /* video driver specif-ic include files */
  25. #include <vport.h>
  26. #include <vportdis.h>
  27. #include <edc.h>
  28. #include "_vport.h"
  29. /* debug include files */
  30. /* to minimize code size and cycle count overhead of the driver */             
  31. /* error checking is only performed at debug time               */
  32. #include <assert.h>
  33. /* mini-driver API functions */
  34. static Int mdBindDev(Ptr *devp, Int devid, Ptr devParams);
  35. static Int mdControlChan(Ptr chanp, Uns cmd, Ptr args);
  36. static Int mdCreateChan(Ptr *chanp, Ptr devp, String name, Int mode,
  37.         Ptr chanParams, IOM_TiomCallback cbFxn, Ptr cbArg);
  38. static Int mdDeleteChan(Ptr chanp);
  39. static Int mdSubmitChan(Ptr chanp, IOM_Packet *packet);
  40. /* local functions */
  41. static Int _configChan(Ptr chanp, Ptr args);
  42. static Int _configEDMA(Ptr chanp, VPORTDIS_Params *params);
  43. static Int _configPort(Ptr chanp, Ptr args);
  44. static Int _configRegs(Ptr chanp, VPORTDIS_Params *params);
  45. static void displayEdmaISR(Int tcc);
  46. static void displayISR(int portNum);
  47. static Int _displayStart(Ptr chanp);
  48. static Int _displayStop(Ptr chanp);
  49. static Int _dundRecover(Ptr chanp);
  50. static Int _getlastActiveLine(VPORTDIS_Params* params);
  51. static Int _setVIntCb(Ptr chanp, Ptr args);
  52. /* global and static variables */
  53. IOM_Fxns VPORTDIS_Fxns = {
  54.     mdBindDev,    
  55.     (IOM_TmdUnBindDev)IOM_mdNotImpl,
  56.     mdControlChan,
  57.     mdCreateChan,
  58.     mdDeleteChan,
  59.     mdSubmitChan
  60. };
  61. /**************************************************************
  62.  * Static allocation and initialization of port objects       *
  63.  * as display supports only 1 channel, the same channel       *
  64.  * object for capture is used here for the whoel port         *
  65.  **************************************************************/
  66. _VPORT_ChanObj chanObjs[_VP_PORT_CNT] = {
  67.     {0, 0, 0, _VP_BASE_PORT0, EDMA_CHA_VP0EVTYA, EDMA_CHA_VP0EVTUA, 
  68.         EDMA_CHA_VP0EVTVA, _VP_YDSTA0_ADDR, _VP_CBDST0_ADDR, _VP_CRDST0_ADDR}, 
  69.     {0, 1, 0, _VP_BASE_PORT1, EDMA_CHA_VP1EVTYA, EDMA_CHA_VP1EVTUA, 
  70.         EDMA_CHA_VP1EVTVA,  _VP_YDSTA1_ADDR, _VP_CBDST1_ADDR, _VP_CRDST1_ADDR}, 
  71.     {0, 2, 0, _VP_BASE_PORT2, EDMA_CHA_VP2EVTYA, EDMA_CHA_VP2EVTUA, 
  72.         EDMA_CHA_VP2EVTVA, _VP_YDSTA2_ADDR, _VP_CBDST2_ADDR, _VP_CRDST2_ADDR },
  73. };     
  74. /*
  75.  *  ======== mdBindDev ========
  76.  *  Register all external devices to video port display driver 
  77.  */
  78. static Int mdBindDev(Ptr *devp, Int devid, Ptr devParams)
  79. {
  80.    Int portNum = devid;
  81.    volatile Int i;
  82.    volatile Int* base = (volatile Int *)chanObjs[portNum].base;                       
  83.    
  84.    assert(portNum < _VP_PORT_CNT);
  85.    base[_VP_VPCTL_OFFSET] = 
  86.              VP_VPCTL_VPRST_RESET << _VP_VPCTL_VPRST_SHIFT;
  87.    for(i = 0; i < 100000; i ++);      
  88.     *devp = &chanObjs[portNum];                                                                                           
  89.    return mdControlChan(&chanObjs[portNum], 
  90.            VPORT_CMD_CONFIG_PORT, devParams);
  91. }
  92. /*
  93.  *  ======== mdControlChan ========
  94.  */
  95. static Int mdControlChan(Ptr chanp, Uns cmd, Ptr args)
  96. {
  97.     Int retVal = IOM_COMPLETED;
  98.     _VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
  99.     
  100.     /* command dispatcher */
  101.     switch (cmd){
  102.         case VPORT_CMD_START:
  103.         retVal = _displayStart(chanp);
  104.         break;
  105.         case VPORT_CMD_STOP:
  106.         retVal = _displayStop(chanp);
  107.         break;
  108.         case VPORT_CMD_CONFIG_CHAN:
  109.         retVal = _configChan(chanp, args);
  110.         break;
  111.         
  112.         case VPORT_CMD_SET_VINTCB:
  113.         _setVIntCb(chanp, args);
  114.         break;
  115.         case VPORT_CMD_DUND_RECOVER:
  116.         retVal = _dundRecover(chanp);
  117.         break;
  118.         case VPORT_CMD_CONFIG_PORT:
  119.         retVal = _configPort(chanp, args);
  120.         break;
  121.         default:
  122.         if(chan->edcFxns!=INV) {
  123.             retVal =  chan->edcFxns->ctrl(chan->edcHandle, 
  124.                 cmd-VPORT_CMD_EDC_BASE,(Arg)args);
  125.         }else {
  126.             retVal = IOM_ENOTIMPL;
  127.         }
  128.    }    
  129.    return retVal;
  130. }              
  131. /*
  132.  *  ======== mdCreateChan ========
  133.  *  create a channel
  134.  */
  135. static Int  mdCreateChan(Ptr *chanp, Ptr devp, String name, Int mode,
  136.               Ptr chanParams, IOM_TiomCallback cbFxn, Ptr cbArg)
  137. {
  138.     _VPORT_ChanObj* chan;
  139.     Int retVal = IOM_COMPLETED;   
  140.     Int j;     
  141.     if(mode != IOM_OUTPUT){
  142.         return IOM_EBADARGS;
  143.     }
  144.     
  145.     chan = (_VPORT_ChanObj *)devp;
  146.     if(chan->edcFxns != INV) {
  147.         /* open external device */
  148.         chan->edcHandle 
  149.            = chan->edcFxns->open(name, (Arg)INV);
  150.     } 
  151.     if(! (chan->status & _VPORT_OPENED)) {
  152.         chan->status |= _VPORT_OPENED;
  153.         
  154.         chan->vIntMask = 0;
  155.         QUE_new(&chan->qIn);
  156.         QUE_new(&chan->qOut);
  157.         chan->cbFxn = cbFxn;
  158.         chan->vIntFxn = (VPORT_IntCallBack)INV;
  159.         chan->queEmpty = FALSE;   
  160.         chan->cbArg = (Arg)cbArg;
  161.         chan->packetIOM = INV;     
  162.         chan->vIntCbArg = (Int)INV;        
  163.         chan->bufSz = 0;
  164.         /* allocate EDMA PaRAM and RLD entries */
  165.         for(j = 0; j < _VPORT_NUM_EDMA_CHANS 
  166.           && retVal == IOM_COMPLETED; j ++ ) {
  167.             if((chan->hEdma[j] = 
  168.              EDMA_open(chan->edmaChanNum[j], EDMA_OPEN_RESET)) == EDMA_HINV
  169.              || (chan->hRld[4 * j] = EDMA_allocTable(-1)) == EDMA_HINV 
  170.              || (chan->hRld[4 * j + 1] =EDMA_allocTable(-1)) == EDMA_HINV 
  171.              || (chan->hRld[4 * j + 2] =EDMA_allocTable(-1)) == EDMA_HINV 
  172.              || (chan->hRld[4 * j + 3] =EDMA_allocTable(-1)) == EDMA_HINV 
  173.              ||  (chan->tcc[j] = EDMA_intAlloc(chan->edmaChanNum[j])) == -1){
  174.                 retVal = IOM_EALLOC;
  175.                 retVal = IOM_EALLOC;
  176.             }/* if((chan->...*/ 
  177.         }/* for(j = 0; j < NUM_EDMA_CHANS; j++) {...*/
  178.         
  179.         /* if EDMA resources are allocated successfully, go ahead */
  180.         /* and configure the channel                              */
  181.         if(retVal == IOM_COMPLETED && (void *)chanParams != INV) {
  182.             retVal = mdControlChan(chan, VPORT_CMD_CONFIG_CHAN, chanParams); 
  183.         }
  184.         if(! retVal) {
  185.              /* configured the channel successfully, return handle */
  186.              *chanp = chan;
  187.         }else {
  188.             /* failed, free all resources and return error */
  189.             mdDeleteChan(chan);
  190.             *chanp = INV;
  191.         }               
  192.     } /*if(!chan->opened) */
  193.     return retVal;
  194. }               
  195. /*
  196.  *  ======== mdDeleteChan ========
  197.  *  delete the channel
  198.  */
  199. static Int  mdDeleteChan(Ptr chanp)
  200. {
  201.     _VPORT_ChanObj* chan = (_VPORT_ChanObj* )chanp;
  202.     Int j;
  203.     volatile Int* base;
  204.     
  205.     if(chan->status & _VPORT_OPENED) {
  206.         chan->status = 0;
  207.         mdControlChan(chanp, VPORT_CMD_STOP, NULL);
  208.         for(j = 0; j < _VPORT_NUM_EDMA_CHANS; j ++) {
  209.             EDMA_disableChannel(chan->hEdma[j]);
  210.             EDMA_clearChannel(chan->hEdma[j]);
  211.             EDMA_close(chan->hEdma[j]);
  212.             EDMA_freeTable(chan->hRld[4 * j]);
  213.             EDMA_freeTable(chan->hRld[4 * j + 1]);
  214.             EDMA_freeTable(chan->hRld[4 * j + 2]);
  215.             EDMA_freeTable(chan->hRld[4 * j + 3]);
  216.             EDMA_intFree(chan->tcc[j]);
  217.         }      
  218.         
  219.         for(j = 0; j < chan->numFrms ; j ++) {
  220.             MEM_free(chan->segId, chan->viops[j].frame.iFrm.y1, chan->bufSz);
  221.         }        
  222.         
  223.         base = (volatile Int *)chan->base;
  224.         /* reset display */
  225.         base[_VP_VDCTL_OFFSET] |= 
  226.             VP_VDCTL_RSTCH_RESET << _VP_VDCTL_RSTCH_SHIFT;
  227.         /* reset video port */
  228.         base[_VP_VPCTL_OFFSET] |= 
  229.             VP_VPCTL_VPRST_RESET << _VP_VPCTL_VPRST_SHIFT;
  230.         
  231.         chan->status = 0;
  232.         /* close external device */
  233.         if(chan->edcFxns != INV) {
  234.             chan->edcFxns->close(chan->edcHandle);
  235.         }
  236.         
  237.     }    
  238.     return IOM_COMPLETED;
  239. }
  240. /*
  241.  *  ======== mdSubmitChan ========
  242.  */
  243. static Int  mdSubmitChan(Ptr chanp, IOM_Packet *packet)
  244. {
  245.     _VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
  246.     FVID_Frame* viop;                             
  247.     Int retVal = IOM_PENDING;
  248.     Uint32 gie = IRQ_globalDisable();     
  249.     
  250.     if(packet->cmd != FVID_ALLOC 
  251.         && packet->cmd != FVID_FREE 
  252.         && packet->cmd != FVID_EXCHANGE){        
  253.         /* other commands not supported */
  254.         return IOM_ENOTIMPL;    
  255.     }
  256.     
  257.     if(packet->cmd != FVID_ALLOC) {/* FVID_FREE or FVID_EXCHANGE */
  258.         viop = *(void **)packet->addr; /* pointer of a video I/O packet */
  259.         if(chan->queEmpty) {
  260.             /* check to make sure it is not to at the end of a frame */
  261.             /* to avoid any race condition                           */
  262.             volatile Int* base = (volatile Int *)chan->base;
  263.             short lineNum = (base[_VP_VDSTAT_OFFSET] & _VP_VDSTAT_VDYPOS_MASK)
  264.                            >> _VP_VDSTAT_VDYPOS_SHIFT;
  265.             /* make sure we are at least five lines before completion */
  266.             /* to prevent EDMA reload happening while it is being modified */
  267.             if(lineNum <= chan->lastLineNum - 5) {
  268.                 Int offset = chan->nextEDMARlds << 1;
  269.                 chan->nextViop = viop;
  270.                 /* now modify the EDMA rld entries */
  271.                 if(chan->mergeFlds){
  272.                     EDMA_RSETH(chan->hRld[offset], SRC, 
  273.                         viop->frame.iFrm.y1);
  274.                     EDMA_RSETH(chan->hRld[offset + 1], SRC, 
  275.                         viop->frame.iFrm.y2);
  276.                     if(!(chan->mode & _VPORT_MASK_RAW)){
  277.                         EDMA_RSETH(chan->hRld[4 + offset], SRC, 
  278.                           viop->frame.iFrm.cb1);     
  279.                         EDMA_RSETH(chan->hRld[5 + offset], SRC, 
  280.                           viop->frame.iFrm.cb2);                         
  281.                         EDMA_RSETH(chan->hRld[8 + offset], SRC, 
  282.                           viop->frame.iFrm.cr1);     
  283.                         EDMA_RSETH(chan->hRld[9 + offset], SRC, 
  284.                           viop->frame.iFrm.cr2);              
  285.                     }           
  286.                 } else {
  287.                     EDMA_RSETH(chan->hRld[offset], SRC, 
  288.                         viop->frame.iFrm.y1);
  289.                     if(!(chan->mode & _VPORT_MASK_RAW)){
  290.                         EDMA_RSETH(chan->hRld[4 + offset], SRC, 
  291.                           viop->frame.iFrm.cb1);     
  292.                         EDMA_RSETH(chan->hRld[8 + offset], SRC, 
  293.                           viop->frame.iFrm.cr1);                         
  294.                     }                                           
  295.                 } /* if(chan->mergeFlds) */
  296.             } else {
  297.                 QUE_enqueue(&chan->qIn, (QUE_Handle)viop);                    
  298.             }
  299.             chan->queEmpty = FALSE;                   
  300.         }
  301.         else {
  302.             QUE_enqueue(&chan->qIn, (QUE_Handle)viop);        
  303.         }
  304.         retVal = packet->status = IOM_COMPLETED;
  305.     }
  306.     if(packet->cmd != FVID_FREE) { /* FVID_ALLOC or FVID_EXCHANGE */
  307.         if(chan->packetIOM == INV){
  308.             if((viop = (FVID_Frame *)QUE_dequeue(&chan->qOut))
  309.                 !=(FVID_Frame *)&chan->qOut) {
  310.                 /* only when there is no outstanding pending request */
  311.                 *(void **)packet->addr = (void *)viop;
  312.                 packet->size = sizeof(FVID_Frame);
  313.                 retVal = packet->status = IOM_COMPLETED;
  314.             }
  315.             else {
  316.                 chan->packetIOM = packet;
  317.                 retVal = packet->status = IOM_PENDING;
  318.             }
  319.         }else retVal = IOM_EINUSE;    
  320.                     
  321.     }    
  322.     IRQ_globalRestore(gie);
  323.     return retVal;
  324. }
  325. /*
  326.  *  ========  _configChan ========
  327.  */
  328. static Int _configChan(Ptr chanp, Ptr args)
  329. {
  330.     _VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
  331.     VPORTDIS_Params*   params = (VPORTDIS_Params* )args; 
  332.     Int retVal;           
  333.     
  334.     
  335.     if(!(chan->status & _VPORT_CFGED)) {
  336.         chan->lastLineNum = _getlastActiveLine(params);
  337.         /* configure video port channel A/B control register */
  338.         _configRegs(chanp, params);
  339.         /* configure EDMA and frame buffer */
  340.         retVal = _configEDMA(chanp, params);
  341.     } else {
  342.         retVal = IOM_EINUSE;
  343.     }    
  344.     return retVal;
  345. }                     
  346. static const Int fillValue[4] = {
  347. 0, 0, 0x80808080, 0x80808080
  348. };
  349. /*
  350.  *  ======== _configEDMA ========
  351.  */
  352. static Int _configEDMA(Ptr chanp, VPORTDIS_Params *params)
  353. {
  354.     _VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
  355.     Int i;
  356.     Int j;               
  357.     EDMA_Config  cfgEdma;
  358.     Int thrld;
  359.     Int edmaChans;
  360.     Int8* curAddr;
  361.     Bool success;
  362.     
  363.     if(chan->status & _VPORT_CFGED) {
  364.         assert(params->numFrmBufs  >= 2 
  365.             && params->numFrmBufs <= VPORT_MAX_NUM_FRMBUFS);
  366.         chan->numFrms = params->numFrmBufs;
  367.         chan->segId = params->segId;
  368.         /* allocate frame buffers */
  369.         chan->bufSz = chan->yPitch * chan->numLines 
  370.               + chan->cPitch * chan->numLines * 2;
  371.         for(i = 0; i < chan->numFrms; i ++) {  
  372.             if((curAddr = MEM_alloc(params->segId,chan->bufSz, 
  373.                 params->alignment)) == MEM_ILLEGAL){
  374.                 for(j = 0; j < i ; j ++) {
  375.                     MEM_free(params->segId, chan->viops[j].frame.iFrm.y1, 
  376.                         chan->bufSz);
  377.                 }
  378.                 /* memory allocation fails */
  379.                 return IOM_EALLOC;
  380.             }    
  381.             /* field 1 */
  382.             chan->viops[i].frame.iFrm.y1 = curAddr;
  383.             curAddr += chan->numLines*chan->yPitch;
  384.             chan->viops[i].frame.iFrm.cb1 = curAddr;
  385.             curAddr += chan->numLines*chan->cPitch;
  386.             chan->viops[i].frame.iFrm.cr1 = curAddr;
  387.             curAddr += chan->numLines*chan->cPitch;
  388.             
  389.             CACHE_clean(CACHE_L2, (void *)fillValue, 16);
  390.             success = DAT_open(DAT_CHAANY, DAT_PRI_LOW, 0);          
  391.             
  392.             for( j = 0; j < chan->numLines; j ++) {
  393.                 DAT_fill(chan->viops[i].frame.iFrm.y1 + j * chan->yPitch, chan->yPitch, (Uint32 *)fillValue);
  394.                 DAT_fill(chan->viops[i].frame.iFrm.cb1 + j * chan->cPitch, chan->cPitch, (Uint32 *)&fillValue[2]);
  395.                 DAT_fill(chan->viops[i].frame.iFrm.cr1 + j * chan->cPitch, chan->cPitch, (Uint32 *)&fillValue[2]);
  396.             }
  397.             if(success) {
  398.                 DAT_close();
  399.             }
  400.             /* field 2 */
  401.             if(params->fldOp == VPORT_FLDOP_FLD2) {
  402.                 chan->viops[i].frame.iFrm.y2 = chan->viops[i].frame.iFrm.y1;
  403.                 chan->viops[i].frame.iFrm.cb2 = chan->viops[i].frame.iFrm.cb1;
  404.                 chan->viops[i].frame.iFrm.cr2 = chan->viops[i].frame.iFrm.cr1;
  405.             } else if(chan->mergeFlds) {
  406.                 chan->viops[i].frame.iFrm.y2 = chan->viops[i].frame.iFrm.y1
  407.                     + chan->yPitch;
  408.                 chan->viops[i].frame.iFrm.cb2 = chan->viops[i].frame.iFrm.cb1
  409.                     + chan->cPitch;
  410.                 chan->viops[i].frame.iFrm.cr2 = chan->viops[i].frame.iFrm.cr1
  411.                     + chan->cPitch;
  412.             }else {
  413.                 chan->viops[i].frame.iFrm.y2 = chan->viops[i].frame.iFrm.y1
  414.                     + (chan->numLinesFld1*chan->yPitch);
  415.                 chan->viops[i].frame.iFrm.cb2 = chan->viops[i].frame.iFrm.cb1
  416.                     + (chan->numLinesFld1*chan->cPitch);
  417.                 chan->viops[i].frame.iFrm.cr2 = chan->viops[i].frame.iFrm.cr1
  418.                     + (chan->numLinesFld1*chan->cPitch);            
  419.             }    
  420.             if(i > 0) {
  421.                 /* don't put the first 1 viop into the queue */
  422.                 QUE_enqueue(&chan->qOut, (QUE_Handle)&chan->viops[i]);
  423.             }
  424.         }
  425.         chan->nextViop = &chan->viops[0];
  426.         chan->curViop = &chan->viops[0];
  427.         chan->queEmpty = TRUE;
  428.         CACHE_clean(CACHE_L2ALL, NULL, NULL);
  429.     
  430.         if(chan->mode & _VPORT_MASK_RAW) edmaChans = 1;
  431.         else edmaChans = 3;
  432.         for(i = 0; i < edmaChans; i ++) {
  433.             Int optFld1 = EDMA_OPT_RMK(
  434.                   params->edmaPri,
  435.                   EDMA_OPT_ESIZE_32BIT,
  436.                   EDMA_OPT_2DS_YES, 
  437.                   EDMA_OPT_SUM_INC,
  438.                   EDMA_OPT_2DD_NO,
  439.                   EDMA_OPT_DUM_NONE,
  440.                   EDMA_OPT_TCINT_NO,
  441.                   EDMA_OPT_TCC_OF(0), 
  442.                   EDMA_OPT_TCCM_OF(0),
  443.                   EDMA_OPT_ATCINT_NO,
  444.                   EDMA_OPT_ATCC_DEFAULT,
  445.                   EDMA_OPT_PDTS_DISABLE,
  446.                   EDMA_OPT_PDTD_DISABLE,
  447.                   EDMA_OPT_LINK_YES,
  448.                   EDMA_OPT_FS_NO
  449.             );
  450.             Int optFld2a = EDMA_OPT_RMK(
  451.                 
  452.                   params->edmaPri,
  453.                   EDMA_OPT_ESIZE_32BIT,
  454.                   EDMA_OPT_2DS_YES, 
  455.                   EDMA_OPT_SUM_INC,
  456.                   EDMA_OPT_2DD_NO,
  457.                   EDMA_OPT_DUM_NONE,
  458.                   (i == 0 ? EDMA_OPT_TCINT_YES:EDMA_OPT_TCINT_NO),
  459.                   EDMA_OPT_TCC_OF(i == 0 ? chan->tcc[0] & 0x0f : 0), 
  460.                   EDMA_OPT_TCCM_OF(i == 0 ? chan->tcc[0] >> 4 : 0),
  461.                   EDMA_OPT_ATCINT_NO,
  462.                   EDMA_OPT_ATCC_DEFAULT,
  463.                   EDMA_OPT_PDTS_DISABLE,
  464.                   EDMA_OPT_PDTD_DISABLE,
  465.                   EDMA_OPT_LINK_YES,
  466.                   EDMA_OPT_FS_NO
  467.             );
  468.             Int optFld2b = EDMA_OPT_RMK(
  469.                 
  470.                   params->edmaPri,
  471.                   EDMA_OPT_ESIZE_32BIT,
  472.                   EDMA_OPT_2DS_YES, 
  473.                   EDMA_OPT_SUM_INC,
  474.                   EDMA_OPT_2DD_NO,
  475.                   EDMA_OPT_DUM_NONE,
  476.                   (i == 0 ? EDMA_OPT_TCINT_YES:EDMA_OPT_TCINT_NO),
  477.                   EDMA_OPT_TCC_OF(i == 0 ? chan->tcc[1] & 0x0f : 0), 
  478.                   EDMA_OPT_TCCM_OF(i == 0 ? chan->tcc[1] >> 4 : 0),
  479.                   EDMA_OPT_ATCINT_NO,
  480.                   EDMA_OPT_ATCC_DEFAULT,
  481.                   EDMA_OPT_PDTS_DISABLE,
  482.                   EDMA_OPT_PDTD_DISABLE,
  483.                   EDMA_OPT_LINK_YES,
  484.                   EDMA_OPT_FS_NO
  485.             );
  486.             thrld = (i == 0)? chan->yThrld:chan->cThrld;
  487.             cfgEdma.dst = EDMA_DST_RMK(chan->edmaAddr[i]);
  488.             if(chan->mergeFlds) {
  489.                 /* to merge the two fields together */
  490.                 /* EDMA is configured to transfer only field 1 initially */
  491.                 /* line pitch is twice the line size */
  492.                 /* this requires that the threlhold is the same as line size*/
  493.                 /* PaRAM and reload Entries */
  494.                 /* first field */
  495.                 cfgEdma.opt = optFld1;
  496.                 cfgEdma.cnt = EDMA_CNT_RMK(
  497.                     (chan->numEventsFld1) - 1, (thrld << 1));
  498.                 cfgEdma.idx = EDMA_IDX_RMK(thrld << 4, 0);
  499.                 /* hard code the field 1 & 2 of the first     */
  500.                 /* frame buffer as current and reload buffers */
  501.                 cfgEdma.src = EDMA_SRC_RMK(
  502.                     *((Int *)(&chan->viops[0].frame.iFrm.y1) + i));
  503.                 cfgEdma.rld = EDMA_RLD_RMK(0, chan->hRld[4*i + 1]);
  504.                 EDMA_config(chan->hEdma[i], &cfgEdma);
  505.                 EDMA_config(chan->hRld[4 * i], &cfgEdma);
  506.                 cfgEdma.rld = EDMA_RLD_RMK(0, chan->hRld[4*i + 3]);
  507.                 EDMA_config(chan->hRld[4 * i + 2], &cfgEdma);
  508.                 
  509.                 /* second field */
  510.                 cfgEdma.opt = optFld2a;
  511.                 cfgEdma.rld = EDMA_RLD_RMK(0, chan->hRld[4 * i + 2]);
  512.                 cfgEdma.cnt = EDMA_CNT_RMK(
  513.                     (chan->numEvents-chan->numEventsFld1) - 1, (thrld << 1));
  514.                 cfgEdma.src = EDMA_SRC_RMK(
  515.                     *((Int *)(&chan->viops[0].frame.iFrm.y2) + i));
  516.                 EDMA_config(chan->hRld[4 * i + 1], &cfgEdma); 
  517.                 cfgEdma.opt = optFld2b;
  518.                 cfgEdma.rld = EDMA_RLD_RMK(0, chan->hRld[4*i]);
  519.                 EDMA_config(chan->hRld[4 * i + 3], &cfgEdma);
  520.                 
  521.             }else {/* if fields are not merged, configure EDMA to transfer */
  522.                    /* for both field1 and field 2                          */
  523.                    /* the line pitch is just the line size                 */
  524.                 cfgEdma.opt = optFld2a;
  525.                 cfgEdma.cnt = EDMA_CNT_RMK((chan->numEvents) - 1, (thrld << 1));
  526.                 cfgEdma.idx = EDMA_IDX_RMK(thrld << 3, 0);
  527.                 /* hard code the first frame buffer as current  */
  528.                 /*and reload buffers */
  529.                 cfgEdma.src = EDMA_SRC_RMK(
  530.                     *((Int *)(&chan->viops[0].frame.iFrm.y1) + i));
  531.                 cfgEdma.rld = EDMA_RLD_RMK(0, chan->hRld[4 * i + 2]);
  532.                 EDMA_config(chan->hEdma[i], &cfgEdma);
  533.                 cfgEdma.src = EDMA_SRC_RMK(
  534.                     *((Int *)(&chan->viops[0].frame.iFrm.y1) + i));
  535.                 EDMA_config(chan->hRld[4 * i], &cfgEdma);
  536.                 cfgEdma.opt = optFld2b;
  537.                 cfgEdma.rld = EDMA_RLD_RMK(0, chan->hRld[4 * i]);
  538.                 EDMA_config(chan->hRld[4 * i + 2], &cfgEdma);
  539.             }
  540.         }
  541.         chan->nextEDMARlds = 1;        
  542.         
  543.         /* enable EDMA channel */        
  544.         if(!(chan->mode & _VPORT_MASK_RAW)) {
  545.             EDMA_disableChannel(chan->hEdma[1]);
  546.             EDMA_clearChannel(chan->hEdma[1]);
  547.             EDMA_enableChannel(chan->hEdma[1]);
  548.             EDMA_disableChannel(chan->hEdma[2]);
  549.             EDMA_clearChannel(chan->hEdma[2]);
  550.             EDMA_enableChannel(chan->hEdma[2]);
  551.         }   
  552.           
  553.         /*
  554.          * The EDMA interrupt dispatcher will be called by the
  555.          * BIOS HWI interrupt dispatcher.
  556.          */
  557.         IRQ_map(IRQ_EVT_EDMAINT, params->irqId);
  558.         HWI_dispatchPlug(params->irqId, (Fxn)EDMA_intDispatcher, -1, NULL);
  559.         EDMA_disableChannel(chan->hEdma[0]);
  560.         EDMA_clearChannel(chan->hEdma[0]);
  561.         EDMA_enableChannel(chan->hEdma[0]);
  562.         EDMA_intClear(chan->tcc[0]);
  563.         EDMA_intEnable(chan->tcc[0]);
  564.         EDMA_intHook(chan->tcc[0], displayEdmaISR);     
  565.         
  566.         EDMA_intClear(chan->tcc[1]);
  567.         EDMA_intEnable(chan->tcc[1]);
  568.         EDMA_intHook(chan->tcc[1], displayEdmaISR);     
  569.         
  570.         chan->status |= _VPORT_READY;
  571.         IRQ_enable(IRQ_EVT_EDMAINT);
  572.     }   
  573.     return IOM_COMPLETED;
  574. }
  575. /*
  576.  *  ======== _configPort ========
  577.  */
  578. static Int _configPort(Ptr chanp, Ptr args)
  579. {
  580.     _VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
  581.     VPORT_PortParams* portParams = (VPORT_PortParams*)args; 
  582.     volatile Int* base = (volatile Int *)chan->base;  
  583.     /* reset video port */
  584.     base[_VP_VPCTL_OFFSET] = 
  585.          VP_VPCTL_VPRST_RESET << _VP_VPCTL_VPRST_SHIFT;
  586.     /* enable video port */
  587.     base[_VP_PCR_OFFSET] |= 
  588.          VP_PCR_PEREN_ENABLE << _VP_PCR_PEREN_SHIFT;
  589.             
  590.     base[_VP_VDCTL_OFFSET] = 
  591.          (Int)VP_VDCTL_RSTCH_RESET << _VP_VDCTL_RSTCH_SHIFT;
  592.     
  593.     /* configure video port control register */
  594.     base[_VP_VPCTL_OFFSET] = VP_VPCTL_RMK(0,0,1,portParams->vc3Polarity,
  595.         portParams->vc2Polarity,portParams->vc1Polarity,0,1,0);
  596.     /* enable video port */
  597.     base[_VP_VPCTL_OFFSET] |= (VP_VPCTL_VPHLT_CLEAR << _VP_VPCTL_VPHLT_SHIFT);
  598.     chan->edcFxns = portParams->edcTbl[0];
  599.     return IOM_COMPLETED;
  600. }
  601.                      
  602. /*
  603.  *  ======== _configRegs ========
  604.  * configure video port registers for display 
  605.  */
  606. static  Int _configRegs(Ptr chanp, VPORTDIS_Params* params)
  607. {
  608.     _VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
  609.     volatile Int* base = (volatile Int *)chan->base;                          
  610.     Int numPixels, numLines, numCPixels;
  611.     Int vdCtl;
  612.     Int nh1 = 0, nh2 = 0, nv1 = 0, nv2 = 0;    
  613.     
  614.     
  615.     if(chan->status & _VPORT_OPENED) {
  616.         /* configure display settings  */
  617.         chan->status |= _VPORT_CFGED;
  618.         vdCtl = VP_VDCTL_RMK(0,1,0,((params->extCtl&4) >> 2),
  619.             ((params->extCtl&2)>>1), params->extCtl&1,params->vctl3Config,
  620.             params->vctl2Config,params->vctl1Config,0, params->bpk10Bit,
  621.             params->rgbX,0,params->defValEn,params->resmpl,
  622.             params->scale, 1,((params->fldOp & 4) >> 2),
  623.             ((params->fldOp & 2) >> 1), 
  624.             (params->fldOp & 1), 
  625.             params->dmode);
  626.         numLines = 0;
  627.         numPixels = 0;
  628.         if(params->fldOp != VPORT_FLDOP_FLD2){
  629.             // progressive scan, or field 1 or frame
  630.             numPixels = params->imgHSizeFld1;
  631.             numLines = params->imgVSizeFld1;
  632.         } 
  633.         chan->numLinesFld1 = numLines;
  634.         if(params->fldOp == VPORT_FLDOP_FLD2 || 
  635.            params->fldOp == VPORT_FLDOP_FRAME){
  636.             if(!numPixels) numPixels = params->imgHSizeFld2;
  637.             numLines += params->imgVSizeFld2;
  638.         }
  639.         chan->numLines = numLines;
  640.         base[_VP_VDCTL_OFFSET] = vdCtl;
  641.         base[_VP_VDFRMSZ_OFFSET]   = 
  642.             VP_VDFRMSZ_RMK(params->frmVSize, params->frmHSize);
  643.         base[_VP_VDHBLNK_OFFSET]   = 
  644.             VP_VDHBLNK_RMK(params->hBlnkStop, !(params->dmode&_VPORT_MASK_RAW), 
  645.             params->hBlnkStart);
  646.         
  647.         base[_VP_VDVBLKS1_OFFSET]  = 
  648.             VP_VDVBLKS1_RMK(params->vBlnkYStartFld1, params->vBlnkXStartFld1);
  649.         base[_VP_VDVBLKE1_OFFSET]  = 
  650.             VP_VDVBLKE1_RMK(params->vBlnkYStopFld1, params->vBlnkXStopFld1);
  651.         base[_VP_VDVBLKS2_OFFSET]  = 
  652.             VP_VDVBLKS2_RMK(params->vBlnkYStartFld2, params->vBlnkXStartFld2);
  653.         base[_VP_VDVBLKE2_OFFSET]  = 
  654.             VP_VDVBLKE2_RMK(params->vBlnkYStopFld2, params->vBlnkXStopFld2);
  655.         base[_VP_VDVBIT1_OFFSET]   = 
  656.             VP_VDVBIT1_RMK(params->vBlnkYStopFld1, params->vBlnkYStartFld1);
  657.         base[_VP_VDVBIT2_OFFSET] = 
  658.             VP_VDVBIT1_RMK(params->vBlnkYStopFld2, params->vBlnkYStartFld2);
  659.         
  660.         if(params->imgHOffsetFld1<0) {
  661.             nh1 = 1;
  662.             params->imgHOffsetFld1 = -params->imgHOffsetFld1;
  663.         }
  664.         if(params->imgHOffsetFld2<0) {
  665.             nh2 = 1;
  666.             params->imgHOffsetFld2 = -params->imgHOffsetFld2;
  667.         }
  668.         if(params->imgVOffsetFld1<0) {
  669.             nv1 = 1;
  670.             params->imgVOffsetFld1 = -params->imgVOffsetFld1;
  671.         }
  672.         if(params->imgHOffsetFld2<0) {
  673.             nv2 = 1;
  674.             params->imgVOffsetFld2 = -params->imgVOffsetFld2;
  675.         }
  676.         
  677.         base[_VP_VDIMGOFF1_OFFSET] = 
  678.             VP_VDIMGOFF1_RMK(nv1, params->imgVOffsetFld1, nh1, 
  679.             params->imgHOffsetFld1);
  680.         base[_VP_VDIMGSZ1_OFFSET]  = 
  681.             VP_VDIMGSZ1_RMK(params->imgVSizeFld1, params->imgHSizeFld1);
  682.         base[_VP_VDIMGOFF2_OFFSET] = 
  683.             VP_VDIMGOFF2_RMK(nv2, params->imgVOffsetFld2, nh2, 
  684.             params->imgHOffsetFld2);
  685.         base[_VP_VDIMGSZ2_OFFSET]  = 
  686.             VP_VDIMGSZ2_RMK(params->imgVSizeFld2, params->imgHSizeFld2);
  687.         base[_VP_VDFLDT1_OFFSET]   = 
  688.             VP_VDFLDT1_RMK(params->yStartFld1, params->xStartFld1);  
  689.         base[_VP_VDFLDT2_OFFSET]   = 
  690.             VP_VDFLDT2_RMK(params->yStartFld2, params->xStartFld2); 
  691.         base[_VP_VDFBIT_OFFSET]   = 
  692.             VP_VDFBIT_RMK(params->yStartFld2, params->yStartFld1);
  693.         
  694.         base[_VP_VDHSYNC_OFFSET]   = 
  695.             VP_VDHSYNC_RMK(params->hSyncStop, params->hSyncStart);
  696.         base[_VP_VDVSYNS1_OFFSET]  = 
  697.             VP_VDVSYNS1_RMK(params->vSyncYStartFld1, params->vSyncXStartFld1);
  698.         base[_VP_VDVSYNE1_OFFSET]  = 
  699.             VP_VDVSYNE1_RMK(params->vSyncYStopFld1, params->vSyncXStopFld1);  
  700.         base[_VP_VDVSYNS2_OFFSET]  = 
  701.             VP_VDVSYNS2_RMK(params->vSyncYStartFld2, params->vSyncXStartFld2);
  702.         base[_VP_VDVSYNE2_OFFSET]  = 
  703.             VP_VDVSYNE2_RMK(params->vSyncYStopFld2, params->vSyncXStopFld2);  
  704.         base[_VP_VDCLIP_OFFSET]    = 
  705.             VP_VDCLIP_RMK(params->cClipHigh, params->cClipLow,
  706.             params->yClipHigh, params->yClipLow);
  707.         base[_VP_VDDEFVAL_OFFSET]  = params->yDefVal |
  708.            (params->cbDefVal << 16) | (params->crDefVal << 24);
  709.         
  710.         chan->resmpl = params->resmpl;
  711.         chan->scale = params->scale;
  712.         numPixels >>= params->scale;
  713.         chan->numPixels = numPixels;
  714.         numCPixels = (params->dmode & _VPORT_MASK_RAW) ? 0 : numPixels >> 1;
  715.         
  716.         if(params->dmode & _VPORT_MASK_RAW) { /* raw mode */
  717.             chan->cPitch = 0;
  718.             if(params->dmode == VPORT_MODE_RAW_8BIT) {
  719.                 chan->yPitch = (numPixels + 7) & (~ 7);
  720.                 chan->cPitch = (numCPixels + 7) & (~ 7);
  721.             } else if(params->dmode == VPORT_MODE_RAW_10BIT) {
  722.                 if(params->bpk10Bit == VPORTDIS_BPK_10BIT_DENSE){
  723.                     chan->yPitch = (numPixels * 4 / 3 + 7) & (~ 7);
  724.                 }else {
  725.                     chan->yPitch = (numPixels * 2 + 7) & (~ 7);
  726.                 }
  727.             } else if(params->dmode == VPORT_MODE_RAW_16BIT) {
  728.                 chan->yPitch = (numPixels * 2 + 7) & (~ 7);
  729.             } else {
  730.                 chan->yPitch = (numPixels * 4 + 7) & (~ 7);
  731.             }                                                                        
  732.         } else {
  733.             if(params->dmode & _VPORT_MASK_10BIT) {
  734.                 if(params->bpk10Bit == VPORTDIS_BPK_10BIT_DENSE){
  735.                     chan->yPitch = (numPixels * 4 / 3 + 7) & (~ 7);
  736.                     chan->cPitch = (numCPixels* 4 / 3 + 7) & (~ 7);
  737.                 }else {
  738.                     chan->yPitch = (numPixels * 2 + 7) & (~ 7);
  739.                     chan->cPitch = (numCPixels * 2 + 7) & (~ 7);
  740.                 }
  741.             } else {/* 8 bit mode */
  742.                 chan->yPitch = (numPixels + 7) & (~ 7);
  743.                 chan->cPitch = (numCPixels + 7) & (~ 7);
  744.             }
  745.         }
  746.         chan->yThrld = params->thrld;       
  747.         if(params->mergeFlds && params->fldOp == VPORT_FLDOP_FRAME) {
  748.             /* frame capture and merge 2 fields into one frame */
  749.             /* make sure threshold is same as line size */
  750.             chan->yThrld = chan->yPitch >> 3;
  751.             chan->numEventsFld1 = chan->numLinesFld1;
  752.             chan->numEvents = chan->numLines;
  753.             chan->mergeFlds = TRUE;  
  754.         }else {            
  755.             /* these two asserts make sure that total transfer sizes of */
  756.             /* both the whole frame and the first field are multiples   */
  757.             /* of the threshold                                         */
  758.             assert(((chan->yPitch*chan->numLinesFld1)/(chan->yThrld << 3)) 
  759.                 *(chan->yThrld << 3) == (chan->yPitch*chan->numLinesFld1));
  760.             assert(((chan->yPitch*chan->numLines)/(chan->yThrld << 3)) 
  761.                 *(chan->yThrld << 3) == (chan->yPitch*chan->numLines));
  762.             chan->numEventsFld1 = 
  763.                 chan->yPitch * chan->numLinesFld1 / (chan->yThrld << 3);
  764.             chan->numEvents = 
  765.                 chan->yPitch * chan->numLines / (chan->yThrld << 3);
  766.             chan->mergeFlds = FALSE;
  767.         }                    
  768.         if(params->dmode & _VPORT_MASK_RAW) {
  769.             chan->cThrld = 0;
  770.         }    
  771.         else {
  772.             chan->cThrld = (chan->yThrld + 1) >> 1;
  773.         }    
  774.         base[_VP_VDTHRLD_OFFSET] = 
  775.             VP_VDTHRLD_RMK(chan->yThrld,params->incPix,chan->yThrld);
  776.         base[_VP_VDDISPEVT_OFFSET] = 
  777.             VP_VDDISPEVT_RMK((chan->numEvents-chan->numEventsFld1), 
  778.             chan->numEventsFld1 );  
  779.         
  780.         chan->mode = params->dmode;
  781.         chan->status |= _VPORT_CFGED;
  782.     }
  783.     return IOM_COMPLETED;
  784. }
  785. /*
  786.  *  ======== displayEdmaISR ========
  787.  */
  788. static void displayEdmaISR(tcc) 
  789. {
  790.     Int i;
  791.     FVID_Frame *viop, *curViop;      
  792.     Int offset;
  793.     
  794.     
  795.     /* find out the source of the edma interrupt */
  796.     for(i = 0; i < _VP_PORT_CNT; i ++) {      
  797.         _VPORT_ChanObj* chan = &chanObjs[i];
  798.         if((chan->status & _VPORT_READY) && 
  799.           (tcc == chan->tcc[0] || tcc == chan->tcc[1])){
  800.             /* re-sync tcc with activeEDMARlds */
  801.             /* they may be out of sync after interrupt over-run */
  802.             /* e.g. execution is halted at break-point */
  803.             chan->nextEDMARlds = (tcc == chan->tcc[0]) ? 0 : 1;
  804.             offset = chan->nextEDMARlds << 1;
  805.             /* update the current and next viop pointers */
  806.             curViop = chan->curViop;
  807.             chan->curViop = chan->nextViop;
  808.             if((viop = (FVID_Frame *)QUE_dequeue(&chan->qIn))
  809.                 != (FVID_Frame *)&chan->qIn) {
  810.                 /* queue IS not empty */
  811.                 chan->nextViop = viop;
  812.             }else {
  813.                 chan->queEmpty = TRUE;
  814.             }
  815.             /* Update the EDMA reload entry  */
  816.             if(chan->mergeFlds){
  817.                 EDMA_RSETH(chan->hRld[offset], SRC, 
  818.                     chan->nextViop->frame.iFrm.y1);
  819.                 EDMA_RSETH(chan->hRld[offset + 1], SRC, 
  820.                     chan->nextViop->frame.iFrm.y2);
  821.                 if(!(chan->mode & _VPORT_MASK_RAW)){
  822.                     EDMA_RSETH(chan->hRld[4 + offset], SRC, 
  823.                         chan->nextViop->frame.iFrm.cb1);     
  824.                     EDMA_RSETH(chan->hRld[5 + offset], SRC, 
  825.                         chan->nextViop->frame.iFrm.cb2);                         
  826.                     EDMA_RSETH(chan->hRld[8 + offset], SRC, 
  827.                         chan->nextViop->frame.iFrm.cr1);     
  828.                     EDMA_RSETH(chan->hRld[9 + offset], SRC, 
  829.                         chan->nextViop->frame.iFrm.cr2);                         
  830.                 }
  831.             } else {
  832.                 EDMA_RSETH(chan->hRld[offset], SRC, 
  833.                     chan->nextViop->frame.iFrm.y1);
  834.                 if(! (chan->mode & _VPORT_MASK_RAW)){
  835.                     EDMA_RSETH(chan->hRld[offset + 4], SRC, 
  836.                         chan->nextViop->frame.iFrm.cb1);
  837.                     EDMA_RSETH(chan->hRld[offset + 8], SRC, 
  838.                         chan->nextViop->frame.iFrm.cr1);
  839.                 }
  840.             }/* if(chan->mergeFlds) {*/
  841.             
  842.             if(curViop != chan->curViop) {
  843.                 if(chan->packetIOM != INV) {
  844.                     /* call the channel's callback function */
  845.                     *(void **)chan->packetIOM->addr = curViop;             
  846.                     chan->packetIOM->size = sizeof(FVID_Frame);
  847.                     chan->cbFxn((Ptr)chan->cbArg, chan->packetIOM);  
  848.                     chan->packetIOM = INV;
  849.                 }else {
  850.                     QUE_enqueue(&chan->qOut,curViop);
  851.                 }
  852.             }/*if(curViop != chan->curViop) {*/  
  853.         }/*if((chan->status & READY) && tcc == chan->tcc){*/
  854.     } /*for(i = 0; i <_VP_PORT_CNT; i++) {  */
  855. }
  856. /*
  857.  *  ======== displayISR ========
  858.  */
  859. static void displayISR(int portNum)
  860. {
  861.     volatile Int *base =  
  862.         (volatile Int *)chanObjs[portNum].base;
  863.     Int vpis = base[_VP_VPIS_OFFSET];
  864.     Int mask = vpis & chanObjs[portNum].vIntMask;
  865.         
  866.     if(mask && chanObjs[portNum].vIntFxn != INV) {
  867.         chanObjs[portNum].vIntFxn(chanObjs[portNum].cbArg, mask);
  868.     }
  869.     /* clear interrupts that has been handled */
  870.     base[_VP_VPIS_OFFSET] |= vpis;
  871. }  
  872. /*
  873.  *  ======== _displayStart ========
  874.  *  start video display
  875.  */
  876. static Int _displayStart(Ptr chanp)
  877. {
  878.     _VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
  879.     volatile Int* base = (volatile Int *)chan->base;  
  880.     volatile Int stat;
  881.     volatile Int i = 0;
  882.                                       
  883.     /* enable port and display */
  884.     base[_VP_VPCTL_OFFSET] |= VP_VPCTL_VPHLT_CLEAR << _VP_VPCTL_VPHLT_SHIFT;
  885.     base[_VP_VDCTL_OFFSET] |= VP_VDCTL_VDEN_ENABLE << _VP_VDCTL_VDEN_SHIFT;
  886.     /* wait for display counters and control signals to sync up */
  887.     do {
  888.         stat = base[_VP_VDSTAT_OFFSET];
  889.         i ++ ;
  890.     }while(!(stat & 0x70000000) && i < 1000000);
  891.     base[_VP_VDSTAT_OFFSET] = stat;
  892.     
  893.     do {
  894.         stat = base[_VP_VDSTAT_OFFSET];
  895.         i ++;
  896.     }while(!(stat & 0x70000000) && i < 1000000);
  897.     base[_VP_VDSTAT_OFFSET] = stat;
  898.     base[_VP_VDCTL_OFFSET] &= ~ (_VP_VDCTL_BLKDIS_MASK);
  899.     /* enable interrupt */
  900.     base[_VP_VPIE_OFFSET] |= VP_VPIE_VIE_ENABLE << _VP_VPIE_VIE_SHIFT;     
  901.     IRQ_clear(IRQ_EVT_VINT0 + chan->portNum);
  902.     IRQ_enable(IRQ_EVT_VINT0 + chan->portNum);
  903.     return IOM_COMPLETED;
  904. }        
  905. /*
  906.  *  ======== _displayStop ========
  907.  *  stop video display
  908.  */
  909. static Int _displayStop(Ptr chanp)
  910. {
  911.     _VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
  912.     volatile Int* base = (volatile Int *)chan->base;    
  913.     
  914.     
  915.     base[_VP_VDCTL_OFFSET] &= ~  (VP_VDCTL_VDEN_ENABLE << _VP_VDCTL_VDEN_SHIFT);
  916.     return IOM_COMPLETED;
  917. }
  918. /*
  919.  *  ======== _dundRecover ========
  920.  *  force recover from display under-run
  921.  */
  922. static Int _dundRecover(Ptr chanp)
  923. {
  924.     _VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
  925.     Int i;          
  926.     Int stat;
  927.     Int numEvents;
  928.     volatile Int* base = (volatile Int *)chan->base;  
  929.     
  930.     
  931.     /* disable under run interrupt */
  932.     base[_VP_VPIE_OFFSET] &= ~ (_VP_VPIE_DUND_MASK);
  933.     /* clear any pending under-run interrupt */
  934.     base[_VP_VPIS_OFFSET] &= ~ (_VP_VPIS_DUND_MASK);
  935.      /* block display events */
  936.     base[_VP_VDCTL_OFFSET] |= _VP_VDCTL_BLKDIS_MASK;
  937.     /* Disable the edmas before settings them up */
  938.     if(!(chan->mode & _VPORT_MASK_RAW)){
  939.         EDMA_disableChannel(chan->hEdma[1]);
  940.         EDMA_clearChannel(chan->hEdma[1]);
  941.         EDMA_disableChannel(chan->hEdma[2]);
  942.         EDMA_clearChannel(chan->hEdma[2]);
  943.     }
  944.     EDMA_intDisable(chan->tcc[0]);
  945.     EDMA_intDisable(chan->tcc[1]);
  946.     EDMA_disableChannel(chan->hEdma[0]);            
  947.     EDMA_clearChannel(chan->hEdma[0]);
  948.     
  949.     if(chan->mergeFlds) {
  950.         numEvents = chan->numEventsFld1;        
  951.     } else {
  952.         numEvents = chan->numEvents;
  953.     }
  954.     /* set up DMA parameters again */
  955.     EDMA_RSETH(chan->hEdma[0], SRC, chan->curViop->frame.iFrm.y1);
  956.     EDMA_RSETH(chan->hEdma[0], CNT, EDMA_CNT_RMK(numEvents - 1, 
  957.         chan->yThrld << 1));
  958.     if(!(chan->mode & _VPORT_MASK_RAW)){
  959.         EDMA_RSETH(chan->hEdma[1], SRC, chan->curViop->frame.iFrm.cb1);
  960.         EDMA_RSETH(chan->hEdma[2], SRC, chan->curViop->frame.iFrm.cr1);
  961.         EDMA_RSETH(chan->hEdma[1], CNT, 
  962.             EDMA_CNT_RMK(numEvents - 1, chan->cThrld << 1));
  963.         EDMA_RSETH(chan->hEdma[2], CNT, 
  964.             EDMA_CNT_RMK(numEvents - 1, chan->cThrld << 1));
  965.     }    
  966.    
  967.     /* enable the edma events again before settings them up */
  968.     EDMA_enableChannel(chan->hEdma[1]);
  969.     EDMA_enableChannel(chan->hEdma[2]);          
  970.    
  971.     EDMA_intEnable(chan->tcc[0]);
  972.     EDMA_intEnable(chan->tcc[1]);
  973.     EDMA_enableChannel(chan->hEdma[0]);
  974.     base[_VP_VDCTL_OFFSET] |= VP_VDCTL_VDEN_ENABLE << _VP_VDCTL_VDEN_SHIFT;
  975.     /* wait for display counters and control signals to sync up */
  976.     do {
  977.         stat = base[_VP_VDSTAT_OFFSET];
  978.         i ++ ;
  979.     }while(!(stat & 0x70000000) && i < 1000000);
  980.     base[_VP_VDSTAT_OFFSET] = stat;
  981.     
  982.     do {
  983.         stat = base[_VP_VDSTAT_OFFSET];
  984.         i ++;
  985.     }while(!(stat & 0x70000000) && i < 1000000);
  986.     base[_VP_VDCTL_OFFSET] &= ~(_VP_VDCTL_BLKDIS_MASK);
  987.     /* re-enable under run interrupt */
  988.     base[_VP_VPIE_OFFSET] |= _VP_VPIE_DUND_MASK;
  989.     return IOM_COMPLETED;
  990. }
  991. /*
  992.  *  ======== _getlastActiveLine ========
  993.  *  get the line number of the last active line
  994.  */
  995. static Int _getlastActiveLine(VPORTDIS_Params* params)
  996. {
  997.     int lastActiveLine = -1;
  998.     switch (params->fldOp){
  999.         case VPORT_FLDOP_FRAME:
  1000.         case VPORT_FLDOP_FLD2:  
  1001.             lastActiveLine = params->vBlnkYStopFld2 
  1002.               + params->imgVOffsetFld2
  1003.               + params->imgVSizeFld2;
  1004.             
  1005.        break;                      
  1006.         case VPORT_FLDOP_FLD1:
  1007.         case VPORT_FLDOP_PROGRESSIVE:
  1008.             lastActiveLine = params->vBlnkYStopFld1 
  1009.               + params->imgVOffsetFld1
  1010.               + params->imgVSizeFld1;
  1011.         break;        
  1012.     }
  1013.     return lastActiveLine;
  1014. }    
  1015. /*
  1016.  *  ======== _setVIntCb ========
  1017.  *  set video port interrutp call-back
  1018.  */
  1019. static Int _setVIntCb(Ptr chanp, Ptr args)
  1020. {
  1021.     _VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
  1022.     volatile Int* base = (volatile Int *)chan->base;  
  1023.     VPORT_VIntCbParams* vIntCbParams = (void *)args;
  1024.     Int mask = vIntCbParams->vIntMask;
  1025.     Uns vif2 = 0, vInt2 = 0, vif1 = 0, vInt1 = 0;
  1026.     chan->vIntMask = mask;
  1027.     /* check to see if vertical interrupt is enabled */
  1028.     if(mask & VPORT_INT_VINT1) {
  1029.         vif1 = 1;
  1030.         vInt1 = vIntCbParams->vIntLine;
  1031.     }
  1032.     if(mask & VPORT_INT_VINT2) {
  1033.         vif2 = 1;
  1034.         vInt2 = vIntCbParams->vIntLine;    
  1035.     }
  1036.     base[_VP_VDVINT_OFFSET] = VP_VDVINT_RMK(vif2, 
  1037.         vInt2, vif1, vInt1);
  1038.     if(mask) {
  1039.         mask |= 1; /* turn on video port interrupt */
  1040.         IRQ_map(IRQ_EVT_VINT0 + chan->portNum, vIntCbParams->irqId);    
  1041.         HWI_dispatchPlug(vIntCbParams->irqId, (Fxn)displayISR, -1, NULL);
  1042.         IRQ_disable(IRQ_EVT_VINT0 + chan->portNum);
  1043.         IRQ_clear(IRQ_EVT_VINT0 + chan->portNum);
  1044.     }
  1045.     base[_VP_VPIE_OFFSET] |= mask;  /* register write */    
  1046.     chan->vIntFxn =  vIntCbParams->vIntCbFxn;       
  1047.     return IOM_COMPLETED;
  1048. }