/*
* Copyright 2003 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.
*
*/
/* "@(#) DDK 1.11.00.00 11-04-03 (ddk-b13)" */
/* 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>
#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 _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 _getlastActiveLine(VPORTDIS_Params* params);
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;
/* 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]);
}