?? vportdis.c
字號:
EDMA_RSETH(chan->hRld[8 + offset], SRC,
viop->frame.iFrm.cr1);
}
} /* if(chan->mergeFlds) */
} else {
QUE_enqueue(&chan->qIn, (QUE_Handle)viop);
}
chan->queEmpty = FALSE;
}
else {
QUE_enqueue(&chan->qIn, (QUE_Handle)viop);
}
retVal = packet->status = IOM_COMPLETED;
}
if(packet->cmd != FVID_FREE) { /* FVID_ALLOC or FVID_EXCHANGE */
if(chan->packetIOM == INV){
if((viop = (FVID_Frame *)QUE_dequeue(&chan->qOut))
!=(FVID_Frame *)&chan->qOut) {
/* only when there is no outstanding pending request */
*(void **)packet->addr = (void *)viop;
packet->size = sizeof(FVID_Frame);
retVal = packet->status = IOM_COMPLETED;
}
else {
chan->packetIOM = packet;
retVal = packet->status = IOM_PENDING;
}
}else retVal = IOM_EINUSE;
}
IRQ_globalRestore(gie);
return retVal;
}
/*
* ======== _configAsnycMode ========
*/
static Int _configAsyncMode(Ptr chanp, Uns cmd, Ptr args)
{
_VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
volatile Int* base = (volatile Int *)chan->base;
VPORTDIS_AsyncModeParam *params = (VPORTDIS_AsyncModeParam *) args;
Uint32 gie = IRQ_globalDisable();
Int vif1 = 0, vif2 = 0;
Int vInt1 = 0, vInt2 = 0;
Int i;
HWI_Attrs attrs = HWI_ATTRS;
Int mask = 0;
Ptr elem;
chan->asyncFrameCt = 0;
/* set the interrupt to happen 30 lines before frame complete */
/* to give enough time for the application call-back function */
/* to execute successfully */
if(chan->interlaced) {
vif2 = 1;
vInt2 = chan->frmSz - 30;
mask = VPORT_INT_VINT2;
} else {
vif1 = 1;
vInt1 = chan->frmSz - 30;
mask = VPORT_INT_VINT1;
}
if(cmd == VPORTDIS_CMD_ASYNC_MODE_ENABLE) {
chan->asyncModeEnable = TRUE;
chan->asyncCbArg = params->arg;
chan->asyncCallBackFxn = (Fxn)params->callBackFxn;
chan->queEmpty = TRUE; /* always TRUE */
if(params->mode == VPORTDIS_PULLDOWN_24P_30I){
assert(chan->numFrms > 4);
assert(chan->mergeFlds); /* make sure the mergeFlds flag is enabled */
} else {
assert(chan->numFrms > 2);
}
base[_VP_VDVINT_OFFSET] = VP_VDVINT_RMK(vif2,
vInt2, vif1, vInt1);
chan->pullDownMode = params->mode;
if(params->irqId != -1) {
attrs.arg = chan->portNum;
IRQ_map(IRQ_EVT_VINT0 + chan->portNum, params->irqId);
HWI_dispatchPlug(params->irqId, (Fxn)displayISR, -1, &attrs);
IRQ_disable(IRQ_EVT_VINT0 + chan->portNum);
IRQ_clear(IRQ_EVT_VINT0 + chan->portNum);
}
/* clear vertical interrupts */
base[_VP_VPIE_OFFSET] &= ~mask;
/* enable the correct one */
base[_VP_VPIE_OFFSET] |= mask;
chan->vIntMask |= mask;
IRQ_enable(IRQ_EVT_VINT0 + chan->portNum);
while((elem = QUE_dequeue(&chan->qIn))!= &chan->qIn){
QUE_enqueue(&chan->qOut, elem);
}
} else if(cmd == VPORTDIS_CMD_ASYNC_MODE_DISABLE) {
if(chan->vIntFxn == INV) {
IRQ_disable(IRQ_EVT_VINT0 + chan->portNum);
IRQ_clear(IRQ_EVT_VINT0 + chan->portNum);
}
/* clear vertical interrupts */
base[_VP_VPIE_OFFSET] &= (~mask);
chan->asyncModeEnable = FALSE;
chan->asyncCallBackFxn = (Fxn)INV;
QUE_new(&chan->qIn);
QUE_new(&chan->qOut);
for(i = 0; i < chan->numFrms; i++) {
if(&chan->viops[i] != chan->curViop &&
&chan->viops[i] != chan->nextViop){
QUE_enqueue(&chan->qOut, &chan->viops[i]);
}
}
} else if(cmd == VPORTDIS_CMD_ASYNC_MODE_RESET_FRAMECT) {
while(!QUE_empty(&chan->qIn)) {
QUE_enqueue(&chan->qOut, QUE_dequeue(&chan->qIn));
}
} else {
return IOM_EBADARGS;
}
IRQ_globalRestore(gie);
return IOM_COMPLETED;
}
/*
* ======== _configChan ========
*/
static Int _configChan(Ptr chanp, Ptr args)
{
_VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
VPORTDIS_Params* params = (VPORTDIS_Params* )args;
Int retVal;
if(!(chan->status & _VPORT_CFGED)) {
chan->lastLineNum = _getlastActiveLine(params);
/* configure video port channel A/B control register */
_configRegs(chanp, params);
/* configure EDMA and frame buffer */
retVal = _configEDMA(chanp, params);
} else {
retVal = IOM_EINUSE;
}
return retVal;
}
/*
* ======== _configEDMA ========
*/
static Int _configEDMA(Ptr chanp, VPORTDIS_Params *params)
{
_VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
Int i;
Int j;
EDMA_Config cfgEdma;
Int thrld;
Int edmaChans;
Int8* curAddr;
Bool success;
if(chan->status & _VPORT_CFGED) {
assert(params->numFrmBufs >= 2
&& params->numFrmBufs <= VPORT_MAX_NUM_FRMBUFS);
chan->numFrms = params->numFrmBufs;
chan->segId = params->segId;
/* allocate frame buffers */
chan->bufSz = chan->yPitch * chan->numLines
+ chan->cPitch * chan->numLines * 2;
for(i = 0; i < chan->numFrms; i ++) {
if((curAddr = MEM_alloc(params->segId,chan->bufSz,
params->alignment)) == MEM_ILLEGAL){
for(j = 0; j < i ; j ++) {
MEM_free(params->segId, chan->viops[j].frame.iFrm.y1,
chan->bufSz);
}
/* memory allocation fails */
return IOM_EALLOC;
}
/* field 1 */
chan->viops[i].frame.iFrm.y1 = curAddr;
curAddr += chan->numLines*chan->yPitch;
chan->viops[i].frame.iFrm.cb1 = curAddr;
curAddr += chan->numLines*chan->cPitch;
chan->viops[i].frame.iFrm.cr1 = curAddr;
curAddr += chan->numLines*chan->cPitch;
CACHE_clean(CACHE_L2, (void *)fillValue, 16);
success = DAT_open(DAT_CHAANY, DAT_PRI_LOW, 0);
for( j = 0; j < chan->numLines; j ++) {
DAT_fill(chan->viops[i].frame.iFrm.y1 + j * chan->yPitch, chan->yPitch, (Uint32 *)fillValue);
DAT_fill(chan->viops[i].frame.iFrm.cb1 + j * chan->cPitch, chan->cPitch, (Uint32 *)&fillValue[2]);
DAT_fill(chan->viops[i].frame.iFrm.cr1 + j * chan->cPitch, chan->cPitch, (Uint32 *)&fillValue[2]);
}
if(success) {
DAT_close();
}
/* field 2 */
if(params->fldOp == VPORT_FLDOP_FLD2) {
chan->viops[i].frame.iFrm.y2 = chan->viops[i].frame.iFrm.y1;
chan->viops[i].frame.iFrm.cb2 = chan->viops[i].frame.iFrm.cb1;
chan->viops[i].frame.iFrm.cr2 = chan->viops[i].frame.iFrm.cr1;
} else if(chan->mergeFlds) {
chan->viops[i].frame.iFrm.y2 = chan->viops[i].frame.iFrm.y1
+ chan->yPitch;
chan->viops[i].frame.iFrm.cb2 = chan->viops[i].frame.iFrm.cb1
+ chan->cPitch;
chan->viops[i].frame.iFrm.cr2 = chan->viops[i].frame.iFrm.cr1
+ chan->cPitch;
}else {
chan->viops[i].frame.iFrm.y2 = chan->viops[i].frame.iFrm.y1
+ (chan->numLinesFld1*chan->yPitch);
chan->viops[i].frame.iFrm.cb2 = chan->viops[i].frame.iFrm.cb1
+ (chan->numLinesFld1*chan->cPitch);
chan->viops[i].frame.iFrm.cr2 = chan->viops[i].frame.iFrm.cr1
+ (chan->numLinesFld1*chan->cPitch);
}
if(i > 0) {
/* don't put the first 1 viop into the queue */
QUE_enqueue(&chan->qOut, (QUE_Handle)&chan->viops[i]);
}
}
chan->nextViop = &chan->viops[0];
chan->curViop = &chan->viops[0];
chan->queEmpty = TRUE;
CACHE_clean(CACHE_L2ALL, NULL, NULL);
if(chan->mode & _VPORT_MASK_RAW) edmaChans = 1;
else edmaChans = 3;
for(i = 0; i < edmaChans; i ++) {
Int optFld1 = EDMA_OPT_RMK(
params->edmaPri,
EDMA_OPT_ESIZE_32BIT,
EDMA_OPT_2DS_YES,
EDMA_OPT_SUM_INC,
EDMA_OPT_2DD_NO,
EDMA_OPT_DUM_NONE,
EDMA_OPT_TCINT_NO,
EDMA_OPT_TCC_OF(0),
EDMA_OPT_TCCM_OF(0),
EDMA_OPT_ATCINT_NO,
EDMA_OPT_ATCC_DEFAULT,
EDMA_OPT_PDTS_DISABLE,
EDMA_OPT_PDTD_DISABLE,
EDMA_OPT_LINK_YES,
EDMA_OPT_FS_NO
);
Int optFld2a = EDMA_OPT_RMK(
params->edmaPri,
EDMA_OPT_ESIZE_32BIT,
EDMA_OPT_2DS_YES,
EDMA_OPT_SUM_INC,
EDMA_OPT_2DD_NO,
EDMA_OPT_DUM_NONE,
(i == 0 ? EDMA_OPT_TCINT_YES:EDMA_OPT_TCINT_NO),
EDMA_OPT_TCC_OF(i == 0 ? chan->tcc[0] & 0x0f : 0),
EDMA_OPT_TCCM_OF(i == 0 ? chan->tcc[0] >> 4 : 0),
EDMA_OPT_ATCINT_NO,
EDMA_OPT_ATCC_DEFAULT,
EDMA_OPT_PDTS_DISABLE,
EDMA_OPT_PDTD_DISABLE,
EDMA_OPT_LINK_YES,
EDMA_OPT_FS_NO
);
Int optFld2b = EDMA_OPT_RMK(
params->edmaPri,
EDMA_OPT_ESIZE_32BIT,
EDMA_OPT_2DS_YES,
EDMA_OPT_SUM_INC,
EDMA_OPT_2DD_NO,
EDMA_OPT_DUM_NONE,
(i == 0 ? EDMA_OPT_TCINT_YES:EDMA_OPT_TCINT_NO),
EDMA_OPT_TCC_OF(i == 0 ? chan->tcc[1] & 0x0f : 0),
EDMA_OPT_TCCM_OF(i == 0 ? chan->tcc[1] >> 4 : 0),
EDMA_OPT_ATCINT_NO,
EDMA_OPT_ATCC_DEFAULT,
EDMA_OPT_PDTS_DISABLE,
EDMA_OPT_PDTD_DISABLE,
EDMA_OPT_LINK_YES,
EDMA_OPT_FS_NO
);
thrld = (i == 0)? chan->yThrld:chan->cThrld;
cfgEdma.dst = EDMA_DST_RMK(chan->edmaAddr[i]);
if(chan->mergeFlds) {
/* to merge the two fields together */
/* EDMA is configured to transfer only field 1 initially */
/* line pitch is twice the line size */
/* this requires that the threlhold is the same as line size*/
/* PaRAM and reload Entries */
/* first field */
cfgEdma.opt = optFld1;
cfgEdma.cnt = EDMA_CNT_RMK(
(chan->numEventsFld1) - 1, (thrld << 1));
cfgEdma.idx = EDMA_IDX_RMK(thrld << 4, 0);
/* hard code the field 1 & 2 of the first */
/* frame buffer as current and reload buffers */
cfgEdma.src = EDMA_SRC_RMK(
*((Int *)(&chan->viops[0].frame.iFrm.y1) + i));
cfgEdma.rld = EDMA_RLD_RMK(0, chan->hRld[4*i + 1]);
EDMA_config(chan->hEdma[i], &cfgEdma);
EDMA_config(chan->hRld[4 * i], &cfgEdma);
cfgEdma.rld = EDMA_RLD_RMK(0, chan->hRld[4*i + 3]);
EDMA_config(chan->hRld[4 * i + 2], &cfgEdma);
/* second field */
cfgEdma.opt = optFld2a;
cfgEdma.rld = EDMA_RLD_RMK(0, chan->hRld[4 * i + 2]);
cfgEdma.cnt = EDMA_CNT_RMK(
(chan->numEvents-chan->numEventsFld1) - 1, (thrld << 1));
cfgEdma.src = EDMA_SRC_RMK(
*((Int *)(&chan->viops[0].frame.iFrm.y2) + i));
EDMA_config(chan->hRld[4 * i + 1], &cfgEdma);
cfgEdma.opt = optFld2b;
cfgEdma.rld = EDMA_RLD_RMK(0, chan->hRld[4*i]);
EDMA_config(chan->hRld[4 * i + 3], &cfgEdma);
}else {/* if fields are not merged, configure EDMA to transfer */
/* for both field1 and field 2 */
/* the line pitch is just the line size */
cfgEdma.opt = optFld2a;
cfgEdma.cnt = EDMA_CNT_RMK((chan->numEvents) - 1, (thrld << 1));
cfgEdma.idx = EDMA_IDX_RMK(thrld << 3, 0);
/* hard code the first frame buffer as current */
/*and reload buffers */
cfgEdma.src = EDMA_SRC_RMK(
*((Int *)(&chan->viops[0].frame.iFrm.y1) + i));
cfgEdma.rld = EDMA_RLD_RMK(0, chan->hRld[4 * i + 2]);
EDMA_config(chan->hEdma[i], &cfgEdma);
cfgEdma.src = EDMA_SRC_RMK(
*((Int *)(&chan->viops[0].frame.iFrm.y1) + i));
EDMA_config(chan->hRld[4 * i], &cfgEdma);
cfgEdma.opt = optFld2b;
cfgEdma.rld = EDMA_RLD_RMK(0, chan->hRld[4 * i]);
EDMA_config(chan->hRld[4 * i + 2], &cfgEdma);
}
}
chan->nextEDMARlds = 1;
/* enable EDMA channel */
if(!(chan->mode & _VPORT_MASK_RAW)) {
EDMA_disableChannel(chan->hEdma[1]);
EDMA_clearChannel(chan->hEdma[1]);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -