?? vportdis.c
字號:
/*
* Copyright 2004 by Texas Instruments Incorporated.
* All rights reserved. Property of Texas Instruments Incorporated.
* Restricted rights to use, duplicate or disclose this code are
* granted through contract.
*
*/
/* August 2004 */
/**************************************************************************/
/* vportdis.c file */
/**************************************************************************/
/* DSP/BIOS standard include files */
#include <std.h>
#include <mem.h>
#include <que.h>
#include <tsk.h>
#include <hwi.h>
/* Chip-support library include files */
#include <csl.h>
#include <csl_edma.h>
#include <csl_vphal.h>
#include <csl_irq.h>
#include <csl_cache.h>
#include <csl_dat.h>
/* IOM/GIO driver model include files */
#include <iom.h>
#include <fvid.h>
/* video driver specif-ic include files */
#include <vport.h>
#include <vportdis.h>
#include <edc.h>
#include "_vport.h"
/* debug include files */
/* to minimize code size and cycle count overhead of the driver */
/* error checking is only performed at debug time */
#include <assert.h>
/* mini-driver API functions */
static Int mdBindDev(Ptr *devp, Int devid, Ptr devParams);
static Int mdControlChan(Ptr chanp, Uns cmd, Ptr args);
static Int mdCreateChan(Ptr *chanp, Ptr devp, String name, Int mode,
Ptr chanParams, IOM_TiomCallback cbFxn, Ptr cbArg);
static Int mdDeleteChan(Ptr chanp);
static Int mdSubmitChan(Ptr chanp, IOM_Packet *packet);
/* local functions */
static Int _configAsyncMode(Ptr chanp, Uns cmd, Ptr args);
static Int _configChan(Ptr chanp, Ptr args);
static Int _configEDMA(Ptr chanp, VPORTDIS_Params *params);
static Int _configPort(Ptr chanp, Ptr args);
static Int _configRegs(Ptr chanp, VPORTDIS_Params *params);
static void displayEdmaISR(Int tcc);
static void displayISR(int portNum);
static Int _displayStart(Ptr chanp);
static Int _displayStop(Ptr chanp);
static Int _dundRecover(Ptr chanp);
static Int _frmAlmostCmopleteIsr(int portNum);
static Int _getlastActiveLine(VPORTDIS_Params* params);
static Int _getNumPendingIORqsts(Ptr chanp, Ptr args);
static Int _setVIntCb(Ptr chanp, Ptr args);
/* constant data for initialization of image buffers */
/* 0 for Y, 0x80 for cb and cr */
static const Int fillValue[4] = {
0, 0, 0x80808080, 0x80808080
};
/* global and static variables */
IOM_Fxns VPORTDIS_Fxns = {
mdBindDev,
(IOM_TmdUnBindDev)IOM_mdNotImpl,
mdControlChan,
mdCreateChan,
mdDeleteChan,
mdSubmitChan
};
/**************************************************************
* Static allocation and initialization of port objects *
* as display supports only 1 channel, the same channel *
* object for capture is used here for the whoel port *
**************************************************************/
_VPORT_ChanObj chanObjs[_VP_PORT_CNT] = {
{0, 0, 0, _VP_BASE_PORT0, EDMA_CHA_VP0EVTYA, EDMA_CHA_VP0EVTUA,
EDMA_CHA_VP0EVTVA, _VP_YDSTA0_ADDR, _VP_CBDST0_ADDR, _VP_CRDST0_ADDR},
{0, 1, 0, _VP_BASE_PORT1, EDMA_CHA_VP1EVTYA, EDMA_CHA_VP1EVTUA,
EDMA_CHA_VP1EVTVA, _VP_YDSTA1_ADDR, _VP_CBDST1_ADDR, _VP_CRDST1_ADDR},
{0, 2, 0, _VP_BASE_PORT2, EDMA_CHA_VP2EVTYA, EDMA_CHA_VP2EVTUA,
EDMA_CHA_VP2EVTVA, _VP_YDSTA2_ADDR, _VP_CBDST2_ADDR, _VP_CRDST2_ADDR },
};
/*
* ======== mdBindDev ========
* Register all external devices to video port display driver
*/
static Int mdBindDev(Ptr *devp, Int devid, Ptr devParams)
{
Int portNum = devid;
volatile Int i;
volatile Int* base = (volatile Int *)chanObjs[portNum].base;
assert(portNum < _VP_PORT_CNT);
base[_VP_VPCTL_OFFSET] =
VP_VPCTL_VPRST_RESET << _VP_VPCTL_VPRST_SHIFT;
for(i = 0; i < 100000; i ++);
*devp = &chanObjs[portNum];
return mdControlChan(&chanObjs[portNum],
VPORT_CMD_CONFIG_PORT, devParams);
}
/*
* ======== mdControlChan ========
*/
static Int mdControlChan(Ptr chanp, Uns cmd, Ptr args)
{
Int retVal = IOM_COMPLETED;
_VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
/* command dispatcher */
switch (cmd){
case VPORT_CMD_START:
retVal = _displayStart(chanp);
break;
case VPORT_CMD_STOP:
retVal = _displayStop(chanp);
break;
case VPORT_CMD_CONFIG_CHAN:
retVal = _configChan(chanp, args);
break;
case VPORT_CMD_SET_VINTCB:
_setVIntCb(chanp, args);
break;
case VPORT_CMD_DUND_RECOVER:
retVal = _dundRecover(chanp);
break;
case VPORT_CMD_CONFIG_PORT:
retVal = _configPort(chanp, args);
break;
case VPORTDIS_CMD_ASYNC_MODE_ENABLE:
case VPORTDIS_CMD_ASYNC_MODE_DISABLE:
case VPORTDIS_CMD_ASYNC_MODE_RESET_FRAMECT:
retVal = _configAsyncMode(chanp, cmd, args);
break;
case VPORT_CMD_GET_NUM_IORQST_PENDING:
retVal = _getNumPendingIORqsts(chanp, args);
break;
default:
if(chan->edcFxns!=INV) {
retVal = chan->edcFxns->ctrl(chan->edcHandle,
cmd-VPORT_CMD_EDC_BASE,(Arg)args);
}else {
retVal = IOM_ENOTIMPL;
}
}
return retVal;
}
/*
* ======== mdCreateChan ========
* create a channel
*/
static Int mdCreateChan(Ptr *chanp, Ptr devp, String name, Int mode,
Ptr chanParams, IOM_TiomCallback cbFxn, Ptr cbArg)
{
_VPORT_ChanObj* chan;
Int retVal = IOM_COMPLETED;
Int j;
if(mode != IOM_OUTPUT){
return IOM_EBADARGS;
}
chan = (_VPORT_ChanObj *)devp;
if(chan->edcFxns != INV) {
/* open external device */
chan->edcHandle
= chan->edcFxns->open(name, (Arg)INV);
}
if(! (chan->status & _VPORT_OPENED)) {
chan->status |= _VPORT_OPENED;
chan->vIntMask = 0;
QUE_new(&chan->qIn);
QUE_new(&chan->qOut);
chan->cbFxn = cbFxn;
chan->vIntFxn = (VPORT_IntCallBack)INV;
chan->queEmpty = FALSE;
chan->cbArg = (Arg)cbArg;
chan->packetIOM = INV;
chan->vIntCbArg = (Int)INV;
chan->bufSz = 0;
chan->asyncModeEnable = 0; /* disable async mode(call-back mode) be default */
chan->pullDownMode = VPORTDIS_PULLDOWN_DISABLE; /* disable 3:2 pull-down */
chan->asyncCallBackFxn = (Fxn)INV;
chan->startFlag = 0;
/* allocate EDMA PaRAM and RLD entries */
for(j = 0; j < _VPORT_NUM_EDMA_CHANS
&& retVal == IOM_COMPLETED; j ++ ) {
if((chan->hEdma[j] =
EDMA_open(chan->edmaChanNum[j], EDMA_OPEN_RESET)) == EDMA_HINV
|| (chan->hRld[4 * j] = EDMA_allocTable(-1)) == EDMA_HINV
|| (chan->hRld[4 * j + 1] =EDMA_allocTable(-1)) == EDMA_HINV
|| (chan->hRld[4 * j + 2] =EDMA_allocTable(-1)) == EDMA_HINV
|| (chan->hRld[4 * j + 3] =EDMA_allocTable(-1)) == EDMA_HINV
|| (chan->tcc[j] = EDMA_intAlloc(chan->edmaChanNum[j])) == -1){
retVal = IOM_EALLOC;
retVal = IOM_EALLOC;
}/* if((chan->...*/
}/* for(j = 0; j < NUM_EDMA_CHANS; j++) {...*/
/* if EDMA resources are allocated successfully, go ahead */
/* and configure the channel */
if(retVal == IOM_COMPLETED && (void *)chanParams != INV) {
retVal = mdControlChan(chan, VPORT_CMD_CONFIG_CHAN, chanParams);
}
if(! retVal) {
/* configured the channel successfully, return handle */
*chanp = chan;
}else {
/* failed, free all resources and return error */
mdDeleteChan(chan);
*chanp = INV;
}
} /*if(!chan->opened) */
return retVal;
}
/*
* ======== mdDeleteChan ========
* delete the channel
*/
static Int mdDeleteChan(Ptr chanp)
{
_VPORT_ChanObj* chan = (_VPORT_ChanObj* )chanp;
Int j;
volatile Int* base;
if(chan->status & _VPORT_OPENED) {
chan->status = 0;
mdControlChan(chanp, VPORT_CMD_STOP, NULL);
for(j = 0; j < _VPORT_NUM_EDMA_CHANS; j ++) {
EDMA_disableChannel(chan->hEdma[j]);
EDMA_clearChannel(chan->hEdma[j]);
EDMA_close(chan->hEdma[j]);
EDMA_freeTable(chan->hRld[4 * j]);
EDMA_freeTable(chan->hRld[4 * j + 1]);
EDMA_freeTable(chan->hRld[4 * j + 2]);
EDMA_freeTable(chan->hRld[4 * j + 3]);
EDMA_intFree(chan->tcc[j]);
}
for(j = 0; j < chan->numFrms ; j ++) {
MEM_free(chan->segId, chan->viops[j].frame.iFrm.y1, chan->bufSz);
}
base = (volatile Int *)chan->base;
/* reset display */
base[_VP_VDCTL_OFFSET] |=
VP_VDCTL_RSTCH_RESET << _VP_VDCTL_RSTCH_SHIFT;
chan->status = 0;
/* close external device */
if(chan->edcFxns != INV) {
chan->edcFxns->close(chan->edcHandle);
}
}
return IOM_COMPLETED;
}
/*
* ======== mdSubmitChan ========
*/
static Int mdSubmitChan(Ptr chanp, IOM_Packet *packet)
{
_VPORT_ChanObj* chan = (_VPORT_ChanObj *)chanp;
FVID_Frame* viop;
Int retVal = IOM_PENDING;
Uint32 gie = IRQ_globalDisable();
if(packet->cmd == IOM_ABORT) {
/* clear all pending I/O requests */
while(!QUE_empty(&chan->qIn)) {
QUE_enqueue(&chan->qOut, QUE_dequeue(&chan->qIn));
}
return IOM_ABORTED;
}else 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 */
if(chan->asyncModeEnable) {
/* In async mode, FVID_free and FVID_exchange is not supported.*/
return IOM_EINUSE;
}
viop = *(void **)packet->addr; /* pointer of a video I/O packet */
if(chan->queEmpty) {
/* check to make sure it is not to at the end of a frame */
/* to avoid any race condition */
volatile Int* base = (volatile Int *)chan->base;
short lineNum = (base[_VP_VDSTAT_OFFSET] & _VP_VDSTAT_VDYPOS_MASK)
>> _VP_VDSTAT_VDYPOS_SHIFT;
/* make sure we are at least five lines before completion */
/* to prevent EDMA reload happening while it is being modified */
if(lineNum <= chan->lastLineNum - 5) {
Int offset = chan->nextEDMARlds << 1;
chan->nextViop = viop;
/* now modify the EDMA rld entries */
if(chan->mergeFlds){
EDMA_RSETH(chan->hRld[offset], SRC,
viop->frame.iFrm.y1);
EDMA_RSETH(chan->hRld[offset + 1], SRC,
viop->frame.iFrm.y2);
if(!(chan->mode & _VPORT_MASK_RAW)){
EDMA_RSETH(chan->hRld[4 + offset], SRC,
viop->frame.iFrm.cb1);
EDMA_RSETH(chan->hRld[5 + offset], SRC,
viop->frame.iFrm.cb2);
EDMA_RSETH(chan->hRld[8 + offset], SRC,
viop->frame.iFrm.cr1);
EDMA_RSETH(chan->hRld[9 + offset], SRC,
viop->frame.iFrm.cr2);
}
} else {
EDMA_RSETH(chan->hRld[offset], SRC,
viop->frame.iFrm.y1);
if(!(chan->mode & _VPORT_MASK_RAW)){
EDMA_RSETH(chan->hRld[4 + offset], SRC,
viop->frame.iFrm.cb1);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -