dsk5402_mcbsp_ad50.c
上传用户:dahaojd
上传日期:2008-01-29
资源大小:14357k
文件大小:11k
源码类别:

DSP编程

开发平台:

C/C++

  1. /*
  2.  *  Copyright 2003 by Texas Instruments Incorporated.
  3.  *  All rights reserved. Property of Texas Instruments Incorporated.
  4.  *  Restricted rights to use, duplicate or disclose this code are
  5.  *  granted through contract.
  6.  *  
  7.  */
  8. /* "@(#) DDK 1.11.00.00 11-04-03 (ddk-b13)" */
  9. /*
  10.  *  ======== dsk5402_mcbsp_ad50.c ========
  11.  *
  12.  *  MCBSP sample-by-sample device driver for TI.
  13.  *  5402 DSK. Uses the C54x Chip Support Library. 
  14.  */
  15. #include <std.h>
  16. #include <atm.h>
  17. #include <hwi.h>
  18. #include <que.h>
  19. #include <csl.h>
  20. #include <csl_mcbsp.h>
  21. #include <csl_irq.h>
  22. #include <iom.h>
  23. #include <dsk5402_mcbsp_ad50.h>
  24. #include <ad50.h>
  25. typedef struct ChanObj {
  26.     Bool        inuse;          /* TRUE => channel has been opened */
  27.     Int         mode;           /* IOM_INPUT or IOM_OUTPUT */
  28.     IOM_Packet  *dataPacket;    /* current active I/O packet */
  29.     QUE_Obj     pendList;       /* list of packets for I/O */
  30.     Uns         *bufptr;        /* pointer *within* current buffer */
  31.     Uns         bufcnt;         /* remaining samples to be handled */
  32.     IOM_TiomCallback cbFxn;     /* used to notify client when I/O complete */
  33.     Ptr         cbArg;
  34. } ChanObj, *ChanHandle;
  35. #define INPUT  0  /* Used as index since IOM mode is a bit mask, not index */
  36. #define OUTPUT 1
  37. #define NUMCHANS        2       /* INPUT and OUTPUT */
  38. static ChanObj chans[NUMCHANS] = {
  39.     { FALSE, INPUT, NULL, { NULL, NULL }, NULL, 0, NULL, NULL },
  40.     { FALSE, OUTPUT, NULL, { NULL, NULL }, NULL, 0, NULL, NULL }
  41. };
  42. static MCBSP_Handle hMcbsp;
  43. /*
  44.  * Forward declaration of IOM interface functions.
  45.  */
  46. static Int mdBindDev(Ptr *devp, Int devid, Ptr devParams);
  47. static Int mdControlChan(Ptr chanp, Uns cmd, Ptr args);
  48. static Int mdCreateChan(Ptr *chanp, Ptr devp, String name, Int mode,
  49.         Ptr chanParams, IOM_TiomCallback cbFxn, Ptr cbArg);
  50. static Int mdDeleteChan(Ptr chanp);
  51. static Int mdSubmitChan(Ptr chanp, IOM_Packet *packet);
  52. /*
  53.  * Public IOM interface table.
  54.  */
  55. IOM_Fxns DSK5402_MCBSP_AD50_FXNS = {
  56.     mdBindDev,
  57.     IOM_UNBINDDEVNOTIMPL,
  58.     mdControlChan,
  59.     mdCreateChan,
  60.     mdDeleteChan,
  61.     mdSubmitChan
  62. };
  63. /*
  64.  *  Public driver setup data object. Used if the user passes NULL as
  65.  *  setup() argument, or by the user to modify the default parameters.
  66.  */
  67. DSK5402_MCBSP_AD50_DevParams DSK5402_MCBSP_AD50_DEVPARAMS = {
  68.     AD50_DEFAULTPARAMS,              /* default codec parameters */
  69. };
  70. /*
  71.  * local ISR functions.
  72.  * rxIsr() and txIsr() are plugged using HWI_dispatchPlug() in mdBindDev().
  73.  */
  74. static Void rxIsr(void);
  75. static Void txIsr(void);
  76. static Void updateChan(ChanHandle chan);
  77. static Void abortio(ChanHandle chan);
  78. /*
  79.  *  ======== mdBindDev ========
  80.  *  This function is called by DSP/BIOS during device initialization.
  81.  *  It is called after DSK5402_MCBSP_AD50_init().
  82.  *  
  83.  */
  84. #pragma CODE_SECTION(mdBindDev, ".text:init")
  85. static Int mdBindDev(Ptr *devp, Int devid, Ptr devParams)
  86. {
  87.     DSK5402_MCBSP_AD50_DevParams *params = 
  88.         (DSK5402_MCBSP_AD50_DevParams *)devParams;
  89.     static Bool curinit = FALSE;
  90.     /* CSL handle to the McBSP. The McBSP is shared between the two channels */
  91.     static MCBSP_Config mcbspCfg0 = {
  92.         0x0021,        /*  Serial Port Control Register 1   */
  93.         0x0201,        /*  Serial Port Control Register 2   */
  94.         0x0040,        /*  Receive Control Register 1   */
  95.         0x0000,        /*  Receive Control Register 2   */
  96.         0x0040,        /*  Transmit Control Register 1   */
  97.         0x0000,        /*  Transmit Control Register 2   */
  98.         0x0000,        /*  Sample Rate Generator Register 1   */
  99.         0x0000,        /*  Sample Rate Generator Register 2   */
  100.         0x0000,        /*  Multichannel Control Register 1   */
  101.         0x0000,        /*  Multichannel Control Register 2   */
  102.         0x000c,        /*  Pin Control Register   */
  103.         0x0000,        /*  Receive Channel Enable Register Partition A   */
  104.         0x0000,        /*  Receive Channel Enable Register Partition B   */
  105.         0x0000,        /*  Transmit Channel Enable Register Partition A   */
  106.         0x0000         /*  Transmit Channel Enable Register Partition B   */
  107.     };
  108.     static volatile ioport unsigned port04;     /* for CPLD CTRL 2 */
  109.     if (curinit) {
  110.         return (IOM_EBADIO);
  111.     }
  112.     curinit = TRUE; 
  113.     /* use default parameters if none are given */
  114.     if (params == NULL) {
  115.         params = &DSK5402_MCBSP_AD50_DEVPARAMS;
  116.     }
  117.     /* open the McBSP */
  118.     hMcbsp = MCBSP_open(MCBSP_PORT1, MCBSP_OPEN_RESET);
  119.     MCBSP_config(hMcbsp, &mcbspCfg0);
  120.     /*
  121.      * DSK5402 board setup ...
  122.      * Select McBSP1 mapped to Audio Codec (CPLD Register)
  123.      * and FC bit = 0 (secondary control off)
  124.      */
  125.     port04 &= 0xf5;
  126.     /* start the McBSP */
  127.     MCBSP_start(hMcbsp, MCBSP_XMIT_START | MCBSP_RCV_START, 0x0);
  128.     /* set codec parameters (this will also initialize the codec) */
  129.     AD50_setParams(hMcbsp, &(params->ad50) );
  130.     /* bind Rx/Tx interrupts and use DSP/BIOS HWI dispatcher */
  131.     HWI_dispatchPlug(IRQ_EVT_RINT1, (Fxn)rxIsr, NULL);
  132.     HWI_dispatchPlug(IRQ_EVT_XINT1, (Fxn)txIsr, NULL);
  133.     *devp = chans;
  134.     return (IOM_COMPLETED);
  135. }
  136. /*
  137.  *  ======== mdControlChan ========
  138.  */
  139. static Int mdControlChan(Ptr chanp, Uns cmd, Ptr args)
  140. {
  141.         /*
  142.          * If a channel timeouts(in IOM class driver) a calldown is made to mdControlChan w/
  143.          *   cmd = IOM_CHAN_TIMED out. Timeout processing is optionally implemented here.
  144.          * If not performed return status of IOM_ENOTIMPL.
  145.          */
  146.         if (cmd == IOM_CHAN_TIMEDOUT) {
  147.         /*
  148.          *  Channel timed out. Perform needed channel cleanup.
  149.          */ 
  150.                 abortio(chanp);
  151.     }
  152.     else {
  153.         return (IOM_ENOTIMPL); /* return IOM_ENOTIMPL for codes not handled */    
  154.     }
  155.     
  156.     return (IOM_COMPLETED);
  157. }
  158. /*
  159.  *  ======== mdCreateChan ========
  160.  */
  161. static Int mdCreateChan(Ptr *chanp, Ptr devp, String name, Int mode,
  162.                 Ptr chanParams, IOM_TiomCallback cbFxn, Ptr cbArg)
  163. {
  164.     ChanHandle  chans = (ChanHandle)devp;
  165.     ChanHandle  chan;
  166.     
  167.     if (mode == IOM_INPUT) {
  168.         chan = &chans[INPUT];     /* input only channel */
  169.     }
  170.     else if (mode == IOM_OUTPUT) {
  171.         chan = &chans[OUTPUT];    /* output only channel */
  172.     }
  173.     else {
  174.         return (IOM_EBADMODE); /* bi-directional channels not supported */
  175.     }
  176.     
  177.     /*
  178.      * Check check if channel is already in use.
  179.      * Use ATM_setu() for atomic test-and-set.
  180.      */
  181.     if (ATM_setu((Uns *)&chan->inuse, TRUE)) {
  182.         return (IOM_EBADIO);            /* ERROR! channel is already open! */
  183.     }
  184.     QUE_new(&chan->pendList);
  185.     chan->dataPacket = NULL;
  186.     /* no need to initialize chan->bufptr */
  187.     chan->cbFxn = cbFxn;
  188.     chan->cbArg = cbArg;
  189.     if (chan->mode == INPUT) {
  190.         IRQ_enable(IRQ_EVT_RINT1);  /* Rx Intr enable */
  191.     }
  192.     else {
  193.         IRQ_enable(IRQ_EVT_XINT1);  /* Tx intr enable */
  194.     }
  195.     *chanp = chan;                  /* return channel handle */
  196.     return (IOM_COMPLETED);         /* success */
  197. }
  198. /*
  199.  *  ======== mdDeleteChan ========
  200.  *  Mark the channel available and disable the appropriate interrupt.
  201.  */
  202. static Int mdDeleteChan(Ptr chanp)
  203. {
  204.     ChanHandle chan = (ChanHandle)chanp;
  205.     chan->inuse = FALSE;
  206.     if (chan->mode == INPUT) {
  207.         IRQ_disable(IRQ_EVT_RINT1);
  208.     }
  209.     else {
  210.         IRQ_disable(IRQ_EVT_XINT1);
  211.     }
  212.     return (IOM_COMPLETED);
  213. }
  214. /*
  215.  *  ======== mdSubmitChan ========
  216.  *  Sets the buf variables in the channel object.  ISR will then
  217.  *  emtpy or fill this buffer.
  218.  */
  219. static Int mdSubmitChan(Ptr chanp, IOM_Packet *packet)
  220. {
  221.     ChanHandle chan = (ChanHandle)chanp;
  222.     Uns         imask;
  223.     /*
  224.      * First check if command is to abort or flush this channel.
  225.      * Note: For this audio codec we are going to toss the output data even 
  226.      *       when flushing.
  227.      */
  228.     if (packet->cmd == IOM_FLUSH || packet->cmd == IOM_ABORT) {
  229.         abortio(chan);  
  230.         
  231.         packet->status = IOM_COMPLETED; /* flush/abort pkt completed */
  232.         return (IOM_COMPLETED);
  233.     }
  234.     imask = HWI_disable();
  235.     if (chan->dataPacket == NULL) {
  236.         chan->bufptr = (Uns *)packet->addr;
  237.         chan->bufcnt = packet->size;
  238.         /* 'dataPacket' must be set last to synchronize with ISR */
  239.         chan->dataPacket = packet;
  240.     }
  241.     else {
  242.         QUE_put(&chan->pendList, packet);
  243.     }
  244.     HWI_restore(imask);
  245.     return (IOM_PENDING);
  246. }
  247. /*
  248.  *  ======== DSK5402_MCBSP_AD50_init ========
  249.  */
  250. #pragma CODE_SECTION(DSK5402_MCBSP_AD50_init, ".text:init")
  251. Void DSK5402_MCBSP_AD50_init(Void)
  252. {
  253. }
  254. /*
  255.  *  ======== rxIsr ========
  256.  *  Handle receive (input) interrupt.
  257.  *
  258.  *  Copies a new sample from McBSP to buffer.  If buffer is full, then call
  259.  *  the registered callback function with the registered argument and the
  260.  *  size of the buffer.
  261.  */
  262. static Void rxIsr(Void)
  263. {
  264.     ChanHandle  chan = &chans[INPUT];
  265.     if (chan->dataPacket == NULL) {
  266.         MCBSP_read(hMcbsp);             /* toss data */
  267.         return;
  268.     }
  269.     *chan->bufptr = MCBSP_read(hMcbsp);
  270.     updateChan(chan);
  271. }
  272. /*
  273.  *  ======== txIsr ========
  274.  *  Handle transmit (output) interrupt.
  275.  *
  276.  *  Copies a new sample from the buffer to MCBSP.  If buffer is empty, then
  277.  *  call the registered callback function with the registered argument and
  278.  *  the size of the buffer.
  279.  */
  280. static Void txIsr(Void)
  281. {
  282.     ChanHandle  chan = &chans[OUTPUT];
  283.     if (chan->dataPacket == NULL) {
  284.         MCBSP_write(hMcbsp, 0);         /* output dummy sample */
  285.         return;
  286.     }
  287.     MCBSP_write(hMcbsp, *chan->bufptr & 0xfffe);
  288.     updateChan(chan);
  289. }
  290. /*
  291.  *  ======== updateChan ========
  292.  *  updateChan() is called at ISR context with appropriate ISR disabled.
  293.  *  updateChan() is used by the rx and tx ISRs to update the channel
  294.  *  structures after input or output sample has been handled.
  295.  */
  296. static Void updateChan(ChanHandle chan)
  297. {
  298.     IOM_Packet *tmpPacket;
  299.     chan->bufptr++;
  300.     chan->bufcnt--;
  301.     /* Is this buffer finished? */
  302.     if (chan->bufcnt == 0) {
  303.         chan->dataPacket->status = IOM_COMPLETED;
  304.         tmpPacket = chan->dataPacket;
  305.         chan->dataPacket = QUE_get(&chan->pendList);
  306.         if (chan->dataPacket == (IOM_Packet *)&chan->pendList) {
  307.             chan->dataPacket = NULL;
  308.         }
  309.         else {
  310.             chan->bufptr = chan->dataPacket->addr;
  311.             chan->bufcnt = chan->dataPacket->size;
  312.         }
  313.         (*chan->cbFxn)(chan->cbArg, tmpPacket);
  314.     }
  315. }
  316. /*
  317.  *  ======== abortio ========
  318.  *  Aborts uncompleted i/o packet requests.
  319.  */
  320. static Void abortio(ChanHandle chan)
  321. {
  322.     IOM_Packet *tmpPacket;
  323.     HWI_disable();
  324.     tmpPacket = chan->dataPacket;
  325.     chan->dataPacket = NULL;
  326.     HWI_enable();
  327.         
  328.     if (tmpPacket) {     
  329.         tmpPacket->status = IOM_ABORTED;   /* abort current request */
  330.         (*chan->cbFxn)(chan->cbArg, tmpPacket); 
  331.                 
  332.         tmpPacket = QUE_get(&chan->pendList);
  333.         while (tmpPacket != (IOM_Packet *)&chan->pendList) {
  334.             tmpPacket->status = IOM_ABORTED;   /* abort queued requests */
  335.             (*chan->cbFxn)(chan->cbArg, tmpPacket);
  336.             tmpPacket = QUE_get(&chan->pendList);
  337.         }
  338.     }
  339. }