📄 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.
*
*/
/* DSP/BIOS standard include files */
#include <std.h>
#include <mem.h>
#include <que.h>
#include <tsk.h>
/* Chip-support library include files */
#include <csl.h>
#include <csl_edma.h>
#include <csl_vphal.h>
#include <csl_irq.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 _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 _setVIntCb(Ptr chanp, Ptr args);
/* 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;
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;
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[2 * j] = EDMA_allocTable(-1)) == EDMA_HINV
|| (chan->hRld[2 * j + 1] =EDMA_allocTable(-1)) == EDMA_HINV
|| (chan->tcc[j] = EDMA_intAlloc(chan->edmaChanNum[j])) == -1){
retVal = IOM_EALLOC;
}/* if((chan->...*/
}/* for(j = 0; j < NUM_EDMA_CHANS; j++) {...*/
/* if EDMAs are not allocated successfully, */
/* delete the channel just created */
if(retVal == IOM_COMPLETED && (void *)chanParams != INV) {
retVal = mdControlChan(chan, VPORT_CMD_CONFIG_CHAN, chanParams);
}
if(! retVal) {
/* configure the channel */
*chanp = chan;
}else {
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_close(chan->hEdma[j]);
EDMA_freeTable(chan->hRld[2 * j]);
EDMA_freeTable(chan->hRld[2 * j + 1]);
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;
/* reset video port */
base[_VP_VPCTL_OFFSET] |=
VP_VPCTL_VPRST_RESET << _VP_VPCTL_VPRST_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 != FVID_ALLOC) {/* FVID_FREE or FVID_EXCHANGE */
viop = *(void **)packet->addr; /* pointer of a video I/O packet */
if(chan->queEmpty) {
/* don't put it into queue, update the rld register directly */
chan->queEmpty = FALSE;
}
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;
}
/*
* ======== _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)) {
/* 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;
EDMA_Config cfgEdma;
Int thrld;
Int edmaChans;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -