dsk5402_mcbsp_ad50.c
上传用户:dahaojd
上传日期:2008-01-29
资源大小:14357k
文件大小:11k
- /*
- * 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)" */
- /*
- * ======== dsk5402_mcbsp_ad50.c ========
- *
- * MCBSP sample-by-sample device driver for TI.
- * 5402 DSK. Uses the C54x Chip Support Library.
- */
- #include <std.h>
- #include <atm.h>
- #include <hwi.h>
- #include <que.h>
- #include <csl.h>
- #include <csl_mcbsp.h>
- #include <csl_irq.h>
- #include <iom.h>
- #include <dsk5402_mcbsp_ad50.h>
- #include <ad50.h>
- typedef struct ChanObj {
- Bool inuse; /* TRUE => channel has been opened */
- Int mode; /* IOM_INPUT or IOM_OUTPUT */
- IOM_Packet *dataPacket; /* current active I/O packet */
- QUE_Obj pendList; /* list of packets for I/O */
- Uns *bufptr; /* pointer *within* current buffer */
- Uns bufcnt; /* remaining samples to be handled */
- IOM_TiomCallback cbFxn; /* used to notify client when I/O complete */
- Ptr cbArg;
- } ChanObj, *ChanHandle;
- #define INPUT 0 /* Used as index since IOM mode is a bit mask, not index */
- #define OUTPUT 1
- #define NUMCHANS 2 /* INPUT and OUTPUT */
- static ChanObj chans[NUMCHANS] = {
- { FALSE, INPUT, NULL, { NULL, NULL }, NULL, 0, NULL, NULL },
- { FALSE, OUTPUT, NULL, { NULL, NULL }, NULL, 0, NULL, NULL }
- };
- static MCBSP_Handle hMcbsp;
- /*
- * Forward declaration of IOM interface 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);
- /*
- * Public IOM interface table.
- */
- IOM_Fxns DSK5402_MCBSP_AD50_FXNS = {
- mdBindDev,
- IOM_UNBINDDEVNOTIMPL,
- mdControlChan,
- mdCreateChan,
- mdDeleteChan,
- mdSubmitChan
- };
- /*
- * Public driver setup data object. Used if the user passes NULL as
- * setup() argument, or by the user to modify the default parameters.
- */
- DSK5402_MCBSP_AD50_DevParams DSK5402_MCBSP_AD50_DEVPARAMS = {
- AD50_DEFAULTPARAMS, /* default codec parameters */
- };
- /*
- * local ISR functions.
- * rxIsr() and txIsr() are plugged using HWI_dispatchPlug() in mdBindDev().
- */
- static Void rxIsr(void);
- static Void txIsr(void);
- static Void updateChan(ChanHandle chan);
- static Void abortio(ChanHandle chan);
- /*
- * ======== mdBindDev ========
- * This function is called by DSP/BIOS during device initialization.
- * It is called after DSK5402_MCBSP_AD50_init().
- *
- */
- #pragma CODE_SECTION(mdBindDev, ".text:init")
- static Int mdBindDev(Ptr *devp, Int devid, Ptr devParams)
- {
- DSK5402_MCBSP_AD50_DevParams *params =
- (DSK5402_MCBSP_AD50_DevParams *)devParams;
- static Bool curinit = FALSE;
- /* CSL handle to the McBSP. The McBSP is shared between the two channels */
- static MCBSP_Config mcbspCfg0 = {
- 0x0021, /* Serial Port Control Register 1 */
- 0x0201, /* Serial Port Control Register 2 */
- 0x0040, /* Receive Control Register 1 */
- 0x0000, /* Receive Control Register 2 */
- 0x0040, /* Transmit Control Register 1 */
- 0x0000, /* Transmit Control Register 2 */
- 0x0000, /* Sample Rate Generator Register 1 */
- 0x0000, /* Sample Rate Generator Register 2 */
- 0x0000, /* Multichannel Control Register 1 */
- 0x0000, /* Multichannel Control Register 2 */
- 0x000c, /* Pin Control Register */
- 0x0000, /* Receive Channel Enable Register Partition A */
- 0x0000, /* Receive Channel Enable Register Partition B */
- 0x0000, /* Transmit Channel Enable Register Partition A */
- 0x0000 /* Transmit Channel Enable Register Partition B */
- };
- static volatile ioport unsigned port04; /* for CPLD CTRL 2 */
- if (curinit) {
- return (IOM_EBADIO);
- }
- curinit = TRUE;
- /* use default parameters if none are given */
- if (params == NULL) {
- params = &DSK5402_MCBSP_AD50_DEVPARAMS;
- }
- /* open the McBSP */
- hMcbsp = MCBSP_open(MCBSP_PORT1, MCBSP_OPEN_RESET);
- MCBSP_config(hMcbsp, &mcbspCfg0);
- /*
- * DSK5402 board setup ...
- * Select McBSP1 mapped to Audio Codec (CPLD Register)
- * and FC bit = 0 (secondary control off)
- */
- port04 &= 0xf5;
- /* start the McBSP */
- MCBSP_start(hMcbsp, MCBSP_XMIT_START | MCBSP_RCV_START, 0x0);
- /* set codec parameters (this will also initialize the codec) */
- AD50_setParams(hMcbsp, &(params->ad50) );
- /* bind Rx/Tx interrupts and use DSP/BIOS HWI dispatcher */
- HWI_dispatchPlug(IRQ_EVT_RINT1, (Fxn)rxIsr, NULL);
- HWI_dispatchPlug(IRQ_EVT_XINT1, (Fxn)txIsr, NULL);
- *devp = chans;
- return (IOM_COMPLETED);
- }
- /*
- * ======== mdControlChan ========
- */
- static Int mdControlChan(Ptr chanp, Uns cmd, Ptr args)
- {
- /*
- * If a channel timeouts(in IOM class driver) a calldown is made to mdControlChan w/
- * cmd = IOM_CHAN_TIMED out. Timeout processing is optionally implemented here.
- * If not performed return status of IOM_ENOTIMPL.
- */
- if (cmd == IOM_CHAN_TIMEDOUT) {
- /*
- * Channel timed out. Perform needed channel cleanup.
- */
- abortio(chanp);
- }
- else {
- return (IOM_ENOTIMPL); /* return IOM_ENOTIMPL for codes not handled */
- }
-
- return (IOM_COMPLETED);
- }
- /*
- * ======== mdCreateChan ========
- */
- static Int mdCreateChan(Ptr *chanp, Ptr devp, String name, Int mode,
- Ptr chanParams, IOM_TiomCallback cbFxn, Ptr cbArg)
- {
- ChanHandle chans = (ChanHandle)devp;
- ChanHandle chan;
-
- if (mode == IOM_INPUT) {
- chan = &chans[INPUT]; /* input only channel */
- }
- else if (mode == IOM_OUTPUT) {
- chan = &chans[OUTPUT]; /* output only channel */
- }
- else {
- return (IOM_EBADMODE); /* bi-directional channels not supported */
- }
-
- /*
- * Check check if channel is already in use.
- * Use ATM_setu() for atomic test-and-set.
- */
- if (ATM_setu((Uns *)&chan->inuse, TRUE)) {
- return (IOM_EBADIO); /* ERROR! channel is already open! */
- }
- QUE_new(&chan->pendList);
- chan->dataPacket = NULL;
- /* no need to initialize chan->bufptr */
- chan->cbFxn = cbFxn;
- chan->cbArg = cbArg;
- if (chan->mode == INPUT) {
- IRQ_enable(IRQ_EVT_RINT1); /* Rx Intr enable */
- }
- else {
- IRQ_enable(IRQ_EVT_XINT1); /* Tx intr enable */
- }
- *chanp = chan; /* return channel handle */
- return (IOM_COMPLETED); /* success */
- }
- /*
- * ======== mdDeleteChan ========
- * Mark the channel available and disable the appropriate interrupt.
- */
- static Int mdDeleteChan(Ptr chanp)
- {
- ChanHandle chan = (ChanHandle)chanp;
- chan->inuse = FALSE;
- if (chan->mode == INPUT) {
- IRQ_disable(IRQ_EVT_RINT1);
- }
- else {
- IRQ_disable(IRQ_EVT_XINT1);
- }
- return (IOM_COMPLETED);
- }
- /*
- * ======== mdSubmitChan ========
- * Sets the buf variables in the channel object. ISR will then
- * emtpy or fill this buffer.
- */
- static Int mdSubmitChan(Ptr chanp, IOM_Packet *packet)
- {
- ChanHandle chan = (ChanHandle)chanp;
- Uns imask;
- /*
- * First check if command is to abort or flush this channel.
- * Note: For this audio codec we are going to toss the output data even
- * when flushing.
- */
- if (packet->cmd == IOM_FLUSH || packet->cmd == IOM_ABORT) {
- abortio(chan);
-
- packet->status = IOM_COMPLETED; /* flush/abort pkt completed */
- return (IOM_COMPLETED);
- }
- imask = HWI_disable();
- if (chan->dataPacket == NULL) {
- chan->bufptr = (Uns *)packet->addr;
- chan->bufcnt = packet->size;
- /* 'dataPacket' must be set last to synchronize with ISR */
- chan->dataPacket = packet;
- }
- else {
- QUE_put(&chan->pendList, packet);
- }
- HWI_restore(imask);
- return (IOM_PENDING);
- }
- /*
- * ======== DSK5402_MCBSP_AD50_init ========
- */
- #pragma CODE_SECTION(DSK5402_MCBSP_AD50_init, ".text:init")
- Void DSK5402_MCBSP_AD50_init(Void)
- {
- }
- /*
- * ======== rxIsr ========
- * Handle receive (input) interrupt.
- *
- * Copies a new sample from McBSP to buffer. If buffer is full, then call
- * the registered callback function with the registered argument and the
- * size of the buffer.
- */
- static Void rxIsr(Void)
- {
- ChanHandle chan = &chans[INPUT];
- if (chan->dataPacket == NULL) {
- MCBSP_read(hMcbsp); /* toss data */
- return;
- }
- *chan->bufptr = MCBSP_read(hMcbsp);
- updateChan(chan);
- }
- /*
- * ======== txIsr ========
- * Handle transmit (output) interrupt.
- *
- * Copies a new sample from the buffer to MCBSP. If buffer is empty, then
- * call the registered callback function with the registered argument and
- * the size of the buffer.
- */
- static Void txIsr(Void)
- {
- ChanHandle chan = &chans[OUTPUT];
- if (chan->dataPacket == NULL) {
- MCBSP_write(hMcbsp, 0); /* output dummy sample */
- return;
- }
- MCBSP_write(hMcbsp, *chan->bufptr & 0xfffe);
- updateChan(chan);
- }
- /*
- * ======== updateChan ========
- * updateChan() is called at ISR context with appropriate ISR disabled.
- * updateChan() is used by the rx and tx ISRs to update the channel
- * structures after input or output sample has been handled.
- */
- static Void updateChan(ChanHandle chan)
- {
- IOM_Packet *tmpPacket;
- chan->bufptr++;
- chan->bufcnt--;
- /* Is this buffer finished? */
- if (chan->bufcnt == 0) {
- chan->dataPacket->status = IOM_COMPLETED;
- tmpPacket = chan->dataPacket;
- chan->dataPacket = QUE_get(&chan->pendList);
- if (chan->dataPacket == (IOM_Packet *)&chan->pendList) {
- chan->dataPacket = NULL;
- }
- else {
- chan->bufptr = chan->dataPacket->addr;
- chan->bufcnt = chan->dataPacket->size;
- }
- (*chan->cbFxn)(chan->cbArg, tmpPacket);
- }
- }
- /*
- * ======== abortio ========
- * Aborts uncompleted i/o packet requests.
- */
- static Void abortio(ChanHandle chan)
- {
- IOM_Packet *tmpPacket;
- HWI_disable();
- tmpPacket = chan->dataPacket;
- chan->dataPacket = NULL;
- HWI_enable();
-
- if (tmpPacket) {
- tmpPacket->status = IOM_ABORTED; /* abort current request */
- (*chan->cbFxn)(chan->cbArg, tmpPacket);
-
- tmpPacket = QUE_get(&chan->pendList);
- while (tmpPacket != (IOM_Packet *)&chan->pendList) {
- tmpPacket->status = IOM_ABORTED; /* abort queued requests */
- (*chan->cbFxn)(chan->cbArg, tmpPacket);
- tmpPacket = QUE_get(&chan->pendList);
- }
- }
- }