2f06774f92d8378b2c89cc3866f2258327669a47
1 /*
2 * mcbsp_drv.c
3 *
4 * This file contains Driver Layer Interface implementation for the McBSP Driver.
5 * McBSP Driver provides Driver Layer Interface to do operations on the McBSP
6 * peripheral like device initialization, channel creation, control commands for
7 * peripheral specific operations etc. It uses EDMA3 for data transfer.
8 *
9 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
10 *
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 *
16 * Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 *
19 * Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the
22 * distribution.
23 *
24 * Neither the name of Texas Instruments Incorporated nor the names of
25 * its contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 */
42 /*============================================================================*/
43 /* INCLUDE FILES */
44 /*============================================================================*/
46 /* MCBSP Types and OSAL definitions: These files can be override by customers
47 * to point to their copies. Because of this the files have not been explicitly
48 * specified to include the driver path.*/
49 #include <mcbsp_types.h>
50 #include <mcbsp_osal.h>
52 /* MCBSP Driver Includes */
53 #include <ti/drv/mcbsp/mcbsp_drv.h>
54 #include <ti/drv/mcbsp/include/mcbsp_pvt.h>
57 /* ========================================================================== */
58 /* GLOBAL MODULE STATE */
59 /* ========================================================================== */
61 /**
62 * \brief Array of Mcbsp instance State objects array
63 */
64 #pragma DATA_SECTION (Mcbsp_Instances, ".mcbsp");
65 #pragma DATA_ALIGN (Mcbsp_Instances, MCBSP_MAX_CACHE_ALIGN)
66 Mcbsp_Object Mcbsp_Instances[CSL_MCBSP_PER_CNT];
68 /**
69 * \brief Mcbsp structure containing the information specific to an instance.
70 */
71 /* Shared Memory Variable to ensure synchronizing SRIO initialization
72 * with all the other cores. */
73 /* Created an array to pad the cache line with MCBSP_MAX_CACHE_ALIGN size */
74 #pragma DATA_SECTION (Mcbsp_deviceInstInfo, ".mcbsp");
75 #pragma DATA_ALIGN (Mcbsp_deviceInstInfo, MCBSP_MAX_CACHE_ALIGN)
76 Mcbsp_HwInfo Mcbsp_deviceInstInfo[CSL_MCBSP_PER_CNT];
78 /**
79 * \brief Mute buffer per instance
80 *
81 * \note Buffer used when the mcbsp is placed in mute.
82 */
83 #pragma DATA_SECTION (Mcbsp_muteBuf, ".mcbsp");
84 #pragma DATA_ALIGN (Mcbsp_muteBuf, MCBSP_MAX_CACHE_ALIGN)
85 Mcbsp_TempBuffer Mcbsp_muteBuf[CSL_MCBSP_PER_CNT];
87 #ifdef MCBSP_LOOPJOB_ENABLE
88 /**
89 * \brief Destination loop buffer per instance
90 *
91 * \note Buffer used during the loop job mode for the Transmit section
92 */
93 #pragma DATA_SECTION (Mcbsp_loopDstBuf, ".mcbsp");
94 #pragma DATA_ALIGN (Mcbsp_loopDstBuf, MCBSP_MAX_CACHE_ALIGN)
95 Mcbsp_TempBuffer Mcbsp_loopDstBuf[CSL_MCBSP_PER_CNT];
97 /**
98 * \brief Receive loop buffer per instance
99 *
100 * \note Buffer used during the loop job mode for the Receive section
101 */
102 #pragma DATA_SECTION (Mcbsp_loopSrcBuf, ".mcbsp");
103 #pragma DATA_ALIGN (Mcbsp_loopSrcBuf, MCBSP_MAX_CACHE_ALIGN)
104 Mcbsp_TempBuffer Mcbsp_loopSrcBuf[CSL_MCBSP_PER_CNT];
105 #endif /* MCBSP_LOOPJOB_ENABLE */
107 /*============================================================================*/
108 /* LOCAL FUNCTION PROTOTYPES */
109 /*============================================================================*/
110 int32_t mcbspSubmitReq(Mcbsp_Object_Unpadded *instHandle,
111 Mcbsp_ChannelObj *chanHandle,
112 Mcbsp_IOBuf *ioBuf);
113 void mcbspConfigureFifo(Mcbsp_HwInfo_Unpadded *hMcbsp,
114 Mcbsp_ChannelObj *chanHandle,
115 Bool enableHwFifo);
117 #ifndef MCBSP_LOOPJOB_ENABLE
118 extern uint32_t Mcbsp_edmaChanNum;
119 #endif /* MCBSP_LOOPJOB_ENABLE */
122 /* ========================================================================== */
123 /* MODULE PUBLIC FUNCTIONS */
124 /* ========================================================================== */
126 /**
127 * @b Description
128 * @n
129 * This is the MCBSP Driver Initialization API which needs to be
130 * invoked by the users to initialize the MCBSP peripheral. This call
131 * is *mandatory* and should be called before calling any of the
132 * other driver API's.
133 *
134 * This should only be called *ONCE* for the device.
135 *
136 * @retval
137 * MCBSP_STATUS_COMPLETED if successful
138 * @retval
139 * MCBSP_ERR_BADARGS if not successful
140 * MCBSP_ERR_ALLOC
141 */
142 int32_t mcbspInit (void)
143 {
144 int32_t devId = 0;
145 void *criticalSectionInfo;
147 /* Begin Critical Section before accessing shared resources. */
148 criticalSectionInfo = Mcbsp_osalEnterMultipleCoreCriticalSection ();
150 /* Invalidate the Cache Contents */
151 Mcbsp_osalBeginMemAccess ((void *)Mcbsp_Instances, sizeof(Mcbsp_Instances));
153 /* initialize the information for all the device instances */
154 for (devId = 0; devId < CSL_MCBSP_PER_CNT; devId++)
155 {
156 /* initialise the instance object */
157 memset((void *)&Mcbsp_Instances[devId], 0, sizeof(Mcbsp_Object));
158 Mcbsp_Instances[devId].obj.inUse = FALSE;
159 }
161 /* Writeback Global Object */
162 Mcbsp_osalEndMemAccess ((void *)Mcbsp_Instances, sizeof(Mcbsp_Instances));
164 /* End Critical Section */
165 Mcbsp_osalExitMultipleCoreCriticalSection (criticalSectionInfo);
167 return MCBSP_STATUS_COMPLETED;
168 }
170 /**
171 * \brief Allocates and configures the McBSP instance specified by devid.
172 *
173 * Acquires the Handle of the McBSP and configure the McBSP by
174 * default for the following things.
175 * o Data output for audio playback
176 * o Data input for audio recording
177 * o Configure the McBSP in DSP/TDM data format mode of the audio
178 * codec.
179 * o Configure the McBSP to receive the Frame Sync and bit clock
180 * externally for both receiver and transmitter.
181 * o McBSP can also be configured to generate Frame Sync and
182 * bit clock internally by enabling sample rate generator and
183 * frame sync generator blocks respectively depending on the
184 * fields set in the device parameter structure which shall
185 * be passed to mcbspBindDev() function as one of the parameter.
186 *
187 * \param devp [OUT] pointer to hold allocated instance object ptr
188 * \param devid [IN] instance number of the mcbsp
189 * \param devParams [IN] user supplied data params.
190 *
191 * \return MCBSP_STATUS_COMPLETED if successful
192 *
193 * MCBSP_ERR_BADARGS if not successful
194 * MCBSP_ERR_ALLOC
195 *
196 * \enter devp should be non NULL and valid pointer,
197 * devId should be < CSL_MCBSP_PER_CNT
198 * devParams should be non NULL and valid pointer,
199 *
200 * \leave Not implemented
201 */
202 int32_t mcbspBindDev(void* *devp, int32_t devid, void* devParams)
203 {
204 Mcbsp_Object_Unpadded *instHandle = NULL;
205 Mcbsp_Params *params = NULL;
206 uint32_t ctrlMask = 0x00;
207 uint32_t count = 0x00;
208 int32_t status = MCBSP_STATUS_COMPLETED;
209 void *criticalSectionInfo;
211 /* Begin Critical Section before accessing shared resources. */
212 criticalSectionInfo = Mcbsp_osalEnterMultipleCoreCriticalSection ();
214 /* Invalidate the Cache Contents */
215 Mcbsp_osalBeginMemAccess ((void *)Mcbsp_Instances, sizeof(Mcbsp_Instances));
216 Mcbsp_osalBeginMemAccess ((void *)Mcbsp_deviceInstInfo, sizeof(Mcbsp_deviceInstInfo));
218 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
219 if ((NULL == devp) || (NULL == devParams) || (devid >= CSL_MCBSP_PER_CNT))
220 {
221 status = MCBSP_ERR_BADARGS;
222 }
224 if (MCBSP_STATUS_COMPLETED == status)
225 {
226 if (TRUE == Mcbsp_Instances[devid].obj.inUse)
227 {
228 status = MCBSP_ERR_INUSE;
229 }
230 else
231 {
232 #endif /* MCBSP_DISABLE_INPUT_PARAM_CHECK */
233 /* copy the pointer to the instance object */
234 instHandle = &(Mcbsp_Instances[devid].obj);
236 /* set the module state as in use */
237 Mcbsp_Instances[devid].obj.inUse = TRUE;
239 params = (Mcbsp_Params *)devParams;
241 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
242 /* Only DMA mode of the operation is supported for Mcbsp mode */
243 if ((Mcbsp_DevMode_McBSP == params->mode) &&
244 (Mcbsp_OpMode_DMAINTERRUPT != params->opMode))
245 {
246 status = MCBSP_ERR_BADMODE;
247 }
248 else
249 {
250 if (NULL == params->srgSetup)
251 {
252 status = MCBSP_ERR_BADMODE;
253 }
254 }
255 }
256 }
257 #endif /* MCBSP_DISABLE_INPUT_PARAM_CHECK */
259 if (MCBSP_STATUS_COMPLETED == status)
260 {
261 /* update the instance of the device being created */
262 instHandle->instNum = devid;
264 /* update the user supplied params to the instance object */
265 instHandle->mode = params->mode;
266 instHandle->opMode = params->opMode;
267 instHandle->enablecache = params->enablecache;
269 /* copy the SOC related information in to the instance object */
270 instHandle->hwInfo = Mcbsp_deviceInstInfo[devid].obj;
272 /* stop the state machine of RX and TX */
273 instHandle->stopSmFsXmt = TRUE;
274 instHandle->stopSmFsRcv = TRUE;
276 instHandle->retryCount = Mcbsp_POLLED_RETRYCOUNT;
278 /* configure the default values for the transmit channel */
279 instHandle->xmtObj.mode = (uint16_t)MCBSP_MODE_OUTPUT;
280 instHandle->xmtObj.devHandle = NULL;
281 instHandle->xmtObj.cbFxn = NULL;
282 instHandle->xmtObj.cbArg = NULL;
283 instHandle->xmtObj.edmaHandle = NULL;
284 instHandle->xmtObj.edmaEventQue = Mcbsp_TXEVENTQUE;
285 instHandle->xmtObj.edmaCallback = NULL;
286 instHandle->xmtObj.xferChan = 0x00;
287 instHandle->xmtObj.tcc = 0x00;
288 instHandle->xmtObj.tempIOBuf = NULL;
289 instHandle->xmtObj.submitCount = 0x00;
290 instHandle->xmtObj.dataFormat = Mcbsp_BufferFormat_1SLOT;
291 instHandle->xmtObj.bMuteON = FALSE;
292 instHandle->xmtObj.paused = FALSE;
293 instHandle->xmtObj.flush = FALSE;
294 instHandle->xmtObj.isTempIOBufValid = FALSE;
295 instHandle->xmtObj.enableHwFifo = TRUE;
296 instHandle->xmtObj.gblErrCbk = NULL;
297 instHandle->xmtObj.userDataBufferSize = 0x00;
298 instHandle->xmtObj.loopJobBuffer = NULL;
299 instHandle->xmtObj.loopJobLength = 0x00;
300 instHandle->xmtObj.nextLinkParamSetToBeUpdated = 0x00;
301 instHandle->xmtObj.loopjobUpdatedinParamset = FALSE;
302 instHandle->xmtObj.roundedWordWidth = 0x00;
304 instHandle->rcvObj.mode = (uint16_t)MCBSP_MODE_INPUT;
305 instHandle->rcvObj.devHandle = NULL;
306 instHandle->rcvObj.cbFxn = NULL;
307 instHandle->rcvObj.cbArg = NULL;
308 instHandle->rcvObj.edmaHandle = NULL;
309 instHandle->rcvObj.edmaEventQue = Mcbsp_RXEVENTQUE;
310 instHandle->rcvObj.edmaCallback = NULL;
311 instHandle->rcvObj.xferChan = 0x00;
312 instHandle->rcvObj.tcc = 0x00;
313 instHandle->rcvObj.tempIOBuf = NULL;
314 instHandle->rcvObj.submitCount = 0x00;
315 instHandle->rcvObj.dataFormat = Mcbsp_BufferFormat_1SLOT;
316 instHandle->rcvObj.bMuteON = FALSE;
317 instHandle->rcvObj.paused = FALSE;
318 instHandle->rcvObj.flush = FALSE;
319 instHandle->rcvObj.isTempIOBufValid = FALSE;
320 instHandle->rcvObj.enableHwFifo = TRUE;
321 instHandle->rcvObj.gblErrCbk = NULL;
322 instHandle->rcvObj.userDataBufferSize = 0x00;
323 instHandle->rcvObj.loopJobBuffer = NULL;
324 instHandle->rcvObj.loopJobLength = 0x00;
325 instHandle->rcvObj.nextLinkParamSetToBeUpdated = 0x00;
326 instHandle->rcvObj.loopjobUpdatedinParamset = FALSE;
327 instHandle->rcvObj.roundedWordWidth = 0x00;
329 #ifdef MCBSP_LOOPJOB_ENABLE
330 /* driver is compiled in loop Job mode */
331 instHandle->loopJobMode = TRUE;
332 #else
333 instHandle->loopJobMode = FALSE;
334 #endif
336 for (count = 0; count < Mcbsp_MAXLINKCNT; count++)
337 {
338 instHandle->xmtObj.pramTbl[count] = 0x00;
339 instHandle->rcvObj.pramTbl[count] = 0x00;
340 instHandle->xmtObj.pramTblAddr[count] = 0x00;
341 instHandle->rcvObj.pramTblAddr[count] = 0x00;
342 }
344 /* set the status of the channel to closed */
345 instHandle->xmtObj.chanState = Mcbsp_DriverState_CLOSED;
346 instHandle->rcvObj.chanState = Mcbsp_DriverState_CLOSED;
348 /* Pending and Floating queues for TX and RX channels */
349 instHandle->xmtObj.ptrQPendList = params->txQPendingList;
350 instHandle->xmtObj.ptrQFloatList = params->txQFloatingList;
351 instHandle->rcvObj.ptrQPendList = params->rxQPendingList;
352 instHandle->rcvObj.ptrQFloatList = params->rxQFloatingList;
354 if (MCBSP_STATUS_COMPLETED == status)
355 {
356 /* Reset the McBSP Transmitter, receiver and SRGR before *
357 * configuration */
358 ctrlMask = ((Mcbsp_SpcrCtrl_TX_DISABLE |
359 Mcbsp_SpcrCtrl_RX_DISABLE) |
360 (Mcbsp_SpcrCtrl_SRG_DISABLE |
361 Mcbsp_SpcrCtrl_FSYNC_DISABLE));
363 status = Mcbsp_localResetCtrl(instHandle,ctrlMask);
364 if (MCBSP_STATUS_COMPLETED != status)
365 {
366 /* Writeback Global Object */
367 Mcbsp_osalEndMemAccess ((void *)Mcbsp_Instances, sizeof(Mcbsp_Instances));
368 Mcbsp_osalEndMemAccess ((void *)Mcbsp_deviceInstInfo, sizeof(Mcbsp_deviceInstInfo));
370 /* End Critical Section */
371 Mcbsp_osalExitMultipleCoreCriticalSection (criticalSectionInfo);
373 return status;
374 }
376 /* copy the configuration for the sample rate generator and config*
377 * the emulation mode and DLB mode settings */
379 /* Configure the McBSP with user supplied parameters */
380 instHandle->srgrConfig = *(params->srgSetup);
382 /* reset the Mcbsp */
383 instHandle->hwInfo.regs->SPCR = 0x00u;
385 /* set the DLB mode settings */
386 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_DLB_MASK);
387 instHandle->hwInfo.regs->SPCR |=
388 (params->dlbMode << CSL_MCBSP_SPCR_DLB_SHIFT);
390 /* set the clock stop mode settings */
391 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_CLKSTP_MASK);
393 /* set the emulation state */
394 instHandle->hwInfo.regs->SPCR &= (~(CSL_MCBSP_SPCR_SOFT_MASK |
395 CSL_MCBSP_SPCR_FREE_MASK));
396 instHandle->hwInfo.regs->SPCR |=
397 (params->emulationMode << CSL_MCBSP_SPCR_SOFT_SHIFT);
398 }
400 if (MCBSP_STATUS_COMPLETED != status)
401 {
402 *devp = NULL;
403 }
404 else
405 {
406 *devp = &(Mcbsp_Instances[devid]);
408 /* set the status of the driver to created */
409 instHandle->devState = Mcbsp_DriverState_CREATED;
410 }
411 }
413 /* Writeback Global Object */
414 Mcbsp_osalEndMemAccess ((void *)Mcbsp_Instances, sizeof(Mcbsp_Instances));
415 Mcbsp_osalEndMemAccess ((void *)Mcbsp_deviceInstInfo, sizeof(Mcbsp_deviceInstInfo));
417 /* End Critical Section */
418 Mcbsp_osalExitMultipleCoreCriticalSection (criticalSectionInfo);
420 return status;
421 }
423 /**
424 * \brief Creates a communication channel in specified mode to communicate
425 * data between the application and the McBSP device instance. This
426 * function sets the required hardware configurations for the data
427 * transactions. It returns configured channel handle to application
428 * which will be used in all further transactions with the channel.
429 *
430 * Pre-requisites:
431 * 1. Valid chanParams structure
432 * This takes much information pertaining to mcbsp channel
433 * configuration such as how many slots are used for this
434 * channel what are their communication parameters, clock settings etc.
435 * 2. Valid device pointer
436 *
437 * \param chanp [IN] Channel Handler
438 * \param devp [IN] Device pointer
439 * \param mode [IN] channel mode -> input or output
440 * \param chanParams [IN] channel parameters from user
441 * \param cbFxn [IN] callback function pointer
442 * \param cbArg [IN] callback function Arguments
443 *
444 * \return MCBSP_STATUS_COMPLETED if successful
445 * MCBSP_ERR_BADIO if not successful
446 * MCBSP_ERR_ALLOC "
447 * MCBSP_ERR_BADARGS if passed invalid chanParams structure
448 */
449 int32_t mcbspCreateChan(void* *chanp,
450 void* devp,
451 int32_t mode,
452 void* chanParams,
453 Mcbsp_CallbackFxn cbFxn,
454 void* cbArg)
455 {
456 Mcbsp_Object *hInst = NULL;
457 Mcbsp_Object_Unpadded *instHandle = NULL;
458 Mcbsp_ChannelObj *chanHandle = NULL;
459 Mcbsp_ChanParams *chanparam = NULL;
460 void* criticalSectionInfo;
461 int32_t status = MCBSP_STATUS_COMPLETED;
463 /* Begin parameter checking */
464 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
465 if (((NULL == chanParams)
466 || (NULL == cbFxn)
467 || (NULL == cbArg)
468 || (NULL == devp))
469 || ((MCBSP_MODE_INPUT != mode) && (MCBSP_MODE_OUTPUT != mode)))
470 {
471 return MCBSP_ERR_BADARGS;
472 }
473 else
474 {
475 #endif
476 chanparam = (Mcbsp_ChanParams *)chanParams;
477 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
478 if (NULL == chanparam->edmaHandle)
479 {
480 return MCBSP_ERR_BADARGS;
481 }
482 }
483 #endif /* MCBSP_DISABLE_INPUT_PARAM_CHECK */
484 /* End parameter checking */
486 /* Begin Critical Section before accessing shared resources. */
487 criticalSectionInfo = Mcbsp_osalEnterMultipleCoreCriticalSection ();
489 /* Invalidate the Cache Contents */
490 Mcbsp_osalBeginMemAccess ((void *)devp, sizeof(Mcbsp_Object));
492 if (MCBSP_STATUS_COMPLETED == status)
493 {
494 hInst = (Mcbsp_Object *)devp;
495 instHandle = (Mcbsp_Object_Unpadded *)&(hInst->obj);
497 /* get the pointer to the required channel structure */
498 if (MCBSP_MODE_INPUT == mode)
499 {
500 chanHandle = &instHandle->rcvObj;
501 }
502 else
503 {
504 chanHandle = &instHandle->xmtObj;
505 }
507 /* we will check if the current requested channel is availablehere*
508 * protect the channel status so that multiple threads requesting *
509 * same channel do not cause a corruption */
510 if (Mcbsp_DriverState_CLOSED == chanHandle->chanState)
511 {
512 chanHandle->chanState = Mcbsp_DriverState_OPENED;
513 }
514 else
515 {
516 /* Requested channel is already taken hence we will set status*
517 * as invalid */
518 status = MCBSP_ERR_BADMODE;
519 }
521 if (MCBSP_STATUS_COMPLETED == status)
522 {
523 chanHandle->mode = (uint16_t)mode;
524 chanHandle->devHandle = hInst;
526 /* Assign the respective callback function */
527 chanHandle->cbFxn = cbFxn;
528 chanHandle->cbArg = cbArg;
530 /* This is used in EDMA mode to populate paramsets in PINGPONG */
531 chanHandle->nextLinkParamSetToBeUpdated = 0;
533 /* Initialize Mute parameter */
534 chanHandle->bMuteON = FALSE;
536 chanHandle->isTempIOBufValid = FALSE;
538 /* Counter that counts outstanding requests of this channel */
539 chanHandle->submitCount = 0;
541 /* Global error callback registered to channel */
542 chanHandle->gblErrCbk = chanparam->gblCbk;
544 /* copy the edma event queue details */
545 chanHandle->edmaEventQue = chanparam->edmaEventQue;
547 /* store the EDMA3 module handle */
548 chanHandle->edmaHandle = chanparam->edmaHandle;
550 /* configure the FIFO */
551 chanHandle->enableHwFifo = chanparam->enableHwFifo;
553 /* copy the user settings in to the channel object */
554 chanHandle->chanConfig = *(chanparam->chanConfig);
555 chanHandle->clkSetup = *(chanparam->clkSetup);
556 chanHandle->numEnabledChannels = chanparam->numEnabledChannels;
557 chanHandle->dataFormat = chanparam->dataFormat;
558 }
560 if (MCBSP_STATUS_COMPLETED == status)
561 {
562 /* configure the actual wordwidth to be used */
563 switch (chanparam->wordWidth)
564 {
565 case Mcbsp_WordLength_8:
566 chanHandle->roundedWordWidth = 1u;
567 break;
568 case Mcbsp_WordLength_12:
569 case Mcbsp_WordLength_16:
570 chanHandle->roundedWordWidth = 2u;
571 break;
572 case Mcbsp_WordLength_20:
573 case Mcbsp_WordLength_24:
574 chanHandle->roundedWordWidth = 3u;
575 break;
576 case Mcbsp_WordLength_32:
577 default:
578 chanHandle->roundedWordWidth = 4u;
579 break;
580 }
582 #ifdef MCBSP_LOOPJOB_ENABLE
583 /* Configure the loop job for the user specified buffer if given */
584 if (NULL == chanparam->userLoopJobBuffer)
585 {
586 if (MCBSP_MODE_INPUT == chanHandle->mode)
587 {
588 chanHandle->loopJobBuffer =
589 Mcbsp_loopDstBuf[instHandle->instNum].scratchBuffer;
590 }
591 else
592 {
593 chanHandle->loopJobBuffer =
594 Mcbsp_loopSrcBuf[instHandle->instNum].scratchBuffer;
595 }
596 chanHandle->loopJobLength = chanHandle->roundedWordWidth;
597 }
598 else
599 {
600 /* Apps has preference on the loopjob buffer & lets use it */
601 chanHandle->loopJobBuffer = chanparam->userLoopJobBuffer;
602 chanHandle->userLoopJobLength = chanparam->userLoopJobLength;
604 /* user loopJob is being used */
605 chanHandle->userLoopJob = TRUE;
606 if (chanHandle->roundedWordWidth >
607 chanparam->userLoopJobLength)
608 {
609 /* not enough loopjob buffer has been provided we *
610 * should have at least loopbuffer for 1 sync event */
611 status = MCBSP_ERR_BADARGS;
612 }
613 }
614 #endif
615 }
617 if ((Mcbsp_DevMode_McBSP == instHandle->mode) && (MCBSP_STATUS_COMPLETED == status))
618 {
619 if (MCBSP_MODE_INPUT == chanHandle->mode)
620 {
621 /* Assign the Channel ID and TCC */
622 chanHandle->xferChan = instHandle->hwInfo.edmaRxEventNum;
623 chanHandle->tcc = instHandle->hwInfo.edmaRxEventNum;
624 chanHandle->edmaCallback =
625 (EDMA3_RM_TccCallback)&Mcbsp_localEdmaCallback;
626 }
627 else
628 {
629 /* Assign the Channel ID and TCC */
630 chanHandle->xferChan = instHandle->hwInfo.edmaTxEventNum;
631 chanHandle->tcc = instHandle->hwInfo.edmaTxEventNum;
632 chanHandle->edmaCallback =
633 (EDMA3_RM_TccCallback)&Mcbsp_localEdmaCallback;
634 }
636 if (MCBSP_STATUS_COMPLETED == status)
637 {
638 mcbspConfigureFifo(&(instHandle->hwInfo),
639 chanHandle,
640 chanHandle->enableHwFifo);
641 }
643 if (MCBSP_MODE_INPUT == chanHandle->mode)
644 {
645 /* configure the RX section */
646 status = Mcbsp_localConfigureRcvChannel(instHandle,chanparam);
647 }
648 else
649 {
650 /* configure the TX section */
651 status = Mcbsp_localConfigureXmtChannel(instHandle,chanparam);
652 }
654 if (MCBSP_STATUS_COMPLETED == status)
655 {
656 /* configure the sample rate generator */
657 status = Mcbsp_localConfigureSrgr(instHandle,chanHandle);
658 }
660 if (MCBSP_STATUS_COMPLETED == status)
661 {
662 /* enable the internal sample rate generator if required */
663 if (((MCBSP_MODE_INPUT == chanHandle->mode) &&
664 (TRUE == instHandle->rxSrgEnable)) ||
665 ((MCBSP_MODE_OUTPUT == chanHandle->mode) &&
666 (TRUE == instHandle->txSrgEnable)))
667 {
668 /* enable the sample rate generator */
669 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_SRG_ENABLE);
670 instHandle->srgEnabled = TRUE;
672 /* wait for the 2CLKG clock cycles */
673 Mcbsp_osalWaitNBitClocks(2u);
674 }
676 /* clear the XSYNCERR (to be done only if TX is used) */
677 if (MCBSP_MODE_OUTPUT == chanHandle->mode)
678 {
679 /* Enable the TX section */
680 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_TX_ENABLE);
682 /* wait for 2 CLKR or CLX cycles */
683 Mcbsp_osalWaitNBitClocks(2u);
685 /* Disable the TX section to clear any XYNCERR */
686 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_TX_DISABLE);
687 }
689 /* complete the EDMA setup for the driver */
690 status = Mcbsp_localSetupEdmaDuringOpen(chanHandle);
691 }
693 #ifdef MCBSP_LOOPJOB_ENABLE
694 if (MCBSP_STATUS_COMPLETED == status)
695 {
696 /* configure the FIFO for the specific channel */
697 if (TRUE == chanHandle->enableHwFifo)
698 {
699 /* Disable and enable the FIFO so that the events are *
700 * generated to the Mcbsp for the first time */
701 mcbspConfigureFifo(&instHandle->hwInfo,chanHandle,FALSE);
702 mcbspConfigureFifo(&instHandle->hwInfo,chanHandle,TRUE);
703 }
705 /* enable the EDMA transfer for the channel so that it is *
706 * ready to transfer the data as soon as the state machine is *
707 * enabled */
708 EDMA3_DRV_enableTransfer(
709 chanHandle->edmaHandle,
710 chanHandle->xferChan,
711 EDMA3_DRV_TRIG_MODE_EVENT);
713 /* Start the McBSP hardware */
714 if (MCBSP_MODE_INPUT == chanHandle->mode)
715 {
716 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_RX_ENABLE);
717 }
718 else
719 {
720 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_TX_ENABLE);
721 }
723 if (MCBSP_MODE_INPUT == chanHandle->mode)
724 {
725 if (TRUE == instHandle->rxFsgEnable)
726 {
727 /* enable the sample rate generator */
728 Mcbsp_localResetCtrl(
729 instHandle,
730 Mcbsp_SpcrCtrl_FSYNC_ENABLE);
731 }
732 }
733 else
734 {
735 if (TRUE == instHandle->txFsgEnable)
736 {
737 /* enable the sample rate generator */
738 Mcbsp_localResetCtrl(
739 instHandle,
740 Mcbsp_SpcrCtrl_FSYNC_ENABLE);
741 }
742 }
744 /* State machine stop status */
745 if (MCBSP_MODE_INPUT == chanHandle->mode)
746 {
747 instHandle->stopSmFsRcv = FALSE;
748 }
749 else
750 {
751 instHandle->stopSmFsXmt = FALSE;
752 }
753 }
754 #endif
755 }
756 }
758 if (MCBSP_STATUS_COMPLETED != status )
759 {
760 if (NULL != chanHandle)
761 {
762 /* set the status of the channel to closed */
763 chanHandle->mode = (uint16_t)Mcbsp_DriverState_CLOSED;
764 }
766 /* channel opening for transaction has failed */
767 chanHandle = NULL;
768 }
769 else
770 {
771 *chanp = chanHandle;
772 }
774 /* Writeback Global Object */
775 Mcbsp_osalEndMemAccess ((void *)devp, sizeof(Mcbsp_Object));
777 /* End Critical Section */
778 Mcbsp_osalExitMultipleCoreCriticalSection (criticalSectionInfo);
780 return status;
781 }
783 /**
784 * \brief frees a channel and all it's associated resources.
785 *
786 * Frees the EDMA resources including EDMA master channel and link
787 * PaRAM entries held by the channel.it also unregisters all the
788 * interrupt handlers.
789 *
790 * \param chanp [IN] Handle to the channel
791 *
792 * \return MCBSP_STATUS_COMPLETED if successful
793 * MCBSP_STATUS_ABORTED if not successful
794 *
795 * \enter chanp should be non NULL and valid pointer,
796 *
797 * \leave Not implemented
798 */
799 int32_t mcbspDeleteChan(void* chanp)
800 {
801 Mcbsp_Object_Unpadded *instHandle = NULL;
802 Mcbsp_ChannelObj *chanHandle = NULL;
803 Uint8 linkCnt = 0;
804 uint32_t timeOut = 0x00;
805 int32_t status = MCBSP_STATUS_COMPLETED;
806 void *criticalSectionInfo;
808 /* Begin Critical Section before accessing shared resources. */
809 criticalSectionInfo = Mcbsp_osalEnterMultipleCoreCriticalSection ();
811 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
812 if (NULL == chanp)
813 {
814 status = MCBSP_ERR_BADARGS;
815 }
816 else
817 {
818 #endif /* MCBSP_DISABLE_INPUT_PARAM_CHECK */
819 chanHandle = (Mcbsp_ChannelObj *)chanp;
821 /* Invalidate the Cache Contents */
822 Mcbsp_osalBeginMemAccess ((void *)chanHandle->devHandle, sizeof(Mcbsp_Object));
824 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
825 if (Mcbsp_DriverState_OPENED != chanHandle->chanState)
826 {
827 status = MCBSP_ERR_BADMODE;
828 }
829 else
830 {
831 if (NULL == chanHandle->devHandle)
832 {
833 status = MCBSP_ERR_BADARGS;
834 }
835 else
836 {
837 #endif
838 instHandle = (Mcbsp_Object_Unpadded *)&(chanHandle->devHandle->obj);
840 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
841 if (NULL == instHandle)
842 {
843 status = MCBSP_ERR_BADARGS;
844 }
845 }
846 }
847 }
848 #endif /* MCBSP_DISABLE_INPUT_PARAM_CHECK */
850 if (MCBSP_STATUS_COMPLETED == status)
851 {
852 /* reset the channel . */
853 Mcbsp_localAbortReset(chanHandle);
855 /* Disable the current transfer to make sure that there is no *
856 * running EDMA transfer taking place */
857 status = EDMA3_DRV_disableTransfer(
858 chanHandle->edmaHandle,
859 chanHandle->xferChan,
860 EDMA3_DRV_TRIG_MODE_EVENT);
862 /* Disable current EDMA transfer */
863 if (MCBSP_STATUS_COMPLETED == status)
864 {
865 if (MCBSP_MODE_OUTPUT == chanHandle->mode)
866 {
867 timeOut = instHandle->retryCount;
869 /* Poll for TXEMPTY */
870 while ((CSL_MCBSP_SPCR_XEMPTY_MASK ==
871 (CSL_MCBSP_SPCR_XEMPTY_MASK & instHandle->hwInfo.regs->SPCR))
872 && (0 != timeOut))
873 {
874 timeOut--;
875 }
876 }
878 /* Reset McBSP before freeing the edma channels */
879 if (MCBSP_MODE_INPUT == chanHandle->mode)
880 {
881 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_RX_DISABLE);
882 }
883 else
884 {
885 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_TX_DISABLE);
886 }
888 /* Free Edma channels */
889 status = EDMA3_DRV_freeChannel(
890 chanHandle->edmaHandle,
891 chanHandle->xferChan);
892 #ifndef MCBSP_LOOPJOB_ENABLE
894 /* free the already allocated dummy PaRAM entries */
895 EDMA3_DRV_freeChannel(chanHandle->edmaHandle,
896 Mcbsp_edmaChanNum);
897 #endif
899 if (MCBSP_STATUS_COMPLETED == status)
900 {
901 /* free the EDMA PaRAM entries used for Ping pong buffer */
902 for (linkCnt = 0; linkCnt < Mcbsp_MAXLINKCNT; linkCnt++)
903 {
904 status = EDMA3_DRV_freeChannel(
905 chanHandle->edmaHandle,
906 chanHandle->pramTbl[linkCnt]);
907 if (MCBSP_STATUS_COMPLETED != status)
908 {
909 break;
910 }
911 }
912 }
914 if (MCBSP_STATUS_COMPLETED == status)
915 {
916 /* Set the state of the channel as closed */
917 chanHandle->chanState = Mcbsp_DriverState_CLOSED;
919 /* Set the Muted state to FALSE */
920 chanHandle->bMuteON = FALSE;
922 /* Set the Paused state to FALSE */
923 chanHandle->paused = FALSE;
924 }
925 }
927 /* Writeback Global Object */
928 Mcbsp_osalEndMemAccess ((void *)chanHandle->devHandle, sizeof(Mcbsp_Object));
929 }
931 /* End Critical Section */
932 Mcbsp_osalExitMultipleCoreCriticalSection (criticalSectionInfo);
934 return (status);
935 }
937 /**
938 * \brief Closes the McBSP device instance from use.
939 * This API is called by the application when it no longer requires the
940 * device instance. Note that all the channels have to be closed for
941 * the device instance to be deleted sucessfully.
942 *
943 * \param devp [IN] Handle to the device created.
944 *
945 * \return MCBSP_STATUS_COMPLETED if successful
946 * MCBSP_STATUS_ABORTED if not successful
947 *
948 * \enter devp should be non NULL and valid pointer,
949 *
950 * \leave Not implemented
951 */
952 int32_t mcbspUnBindDev(void* devp)
953 {
954 Mcbsp_Object *hInst = NULL;
955 Mcbsp_Object_Unpadded *instHandle = NULL;
956 int32_t status = MCBSP_STATUS_COMPLETED;
957 void* criticalSectionInfo;
959 /* Begin Critical Section before accessing shared resources. */
960 criticalSectionInfo = Mcbsp_osalEnterMultipleCoreCriticalSection ();
962 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
963 if (NULL == devp)
964 {
965 status = MCBSP_ERR_BADARGS;
966 }
967 else
968 {
969 #endif /* MCBSP_DISABLE_INPUT_PARAM_CHECK */
971 hInst = (Mcbsp_Object *)devp;
973 /* Invalidate the Cache Contents */
974 Mcbsp_osalBeginMemAccess ((void *)hInst, sizeof(Mcbsp_Object));
976 instHandle = (Mcbsp_Object_Unpadded *)&(hInst->obj);
978 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
979 if ((CSL_MCBSP_PER_CNT <= instHandle->instNum) ||
980 (Mcbsp_DriverState_CLOSED != instHandle->xmtObj.chanState) ||
981 (Mcbsp_DriverState_CLOSED != instHandle->rcvObj.chanState))
982 {
983 status = MCBSP_ERR_BADARGS;
984 }
985 }
986 #endif /* MCBSP_DISABLE_INPUT_PARAM_CHECK */
988 if (MCBSP_STATUS_COMPLETED == status)
989 {
990 /* reset the Mcbsp */
991 instHandle->hwInfo.regs->SPCR = 0x00u;
993 /* Mark driver state as deleted and module as not in use */
994 instHandle->devState = Mcbsp_DriverState_DELETED;
995 instHandle->inUse = FALSE;
997 /* update the user params to the instance object */
998 instHandle->instNum = -1;
1000 /* Intialize the mcbsp driver to default values */
1001 memset(instHandle, 0, sizeof(Mcbsp_Object_Unpadded));
1003 /* Writeback Global Object */
1004 Mcbsp_osalEndMemAccess ((void *)hInst, sizeof(Mcbsp_Object));
1005 }
1007 /* End Critical Section */
1008 Mcbsp_osalExitMultipleCoreCriticalSection (criticalSectionInfo);
1010 return status;
1011 }
1013 /**
1014 * \brief Submit a I/O buffer to a channel for processing
1015 *
1016 * The application calls this function to cause the driver
1017 * to process the Mcbsp_IOBuf for read/write/flush/abort operations.
1018 *
1019 * \param chanp [IN] Pointer to channel
1020 * \param ioBuf [IN] Pointer to buffer to be submitted
1021 *
1022 * \return MCBSP_STATUS_COMPLETED, if buffer is fully processed
1023 * MCBSP_STATUS_ABORTED, if buffer is aborted
1024 * MCBSP_STATUS_PENDING, if buffer is not fully processed
1025 * MCBSP_ERR_BADIO in case of an error in processing
1026 *
1027 */
1028 int32_t mcbspSubmitChan(void* chanp, Mcbsp_IOBuf *const ioBuf)
1029 {
1030 Mcbsp_Object_Unpadded *instHandle = NULL;
1031 Mcbsp_ChannelObj *chanHandle = NULL;
1032 int32_t status = MCBSP_STATUS_COMPLETED;
1034 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
1035 if ((NULL == chanp) || ( NULL == ioBuf))
1036 {
1037 status = MCBSP_ERR_BADARGS;
1038 }
1039 else
1040 {
1041 #endif
1042 chanHandle = (Mcbsp_ChannelObj *)chanp;
1044 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
1046 if ((NULL == chanHandle) || (NULL == chanHandle->devHandle))
1047 {
1048 status = MCBSP_ERR_BADARGS;
1049 }
1050 else
1051 {
1052 #endif
1053 instHandle = (Mcbsp_Object_Unpadded *)&(chanHandle->devHandle->obj);
1054 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
1055 if (NULL == instHandle)
1056 {
1057 status = MCBSP_ERR_BADARGS;
1058 }
1059 else
1060 {
1061 if (NULL == ioBuf->addr)
1062 {
1063 if ((Mcbsp_IOBuf_Cmd_READ == ioBuf->cmd) ||
1064 (Mcbsp_IOBuf_Cmd_WRITE == ioBuf->cmd))
1065 {
1066 status = MCBSP_ERR_BADARGS;
1067 }
1068 }
1069 }
1070 }
1071 }
1072 #endif /* MCBSP_DISABLE_INPUT_PARAM_CHECK */
1074 if (MCBSP_STATUS_COMPLETED == status)
1075 {
1076 /* process the command sent by the application */
1077 switch (ioBuf->cmd)
1078 {
1079 case Mcbsp_IOBuf_Cmd_READ:
1080 case Mcbsp_IOBuf_Cmd_WRITE:
1081 if (TRUE != chanHandle->flush)
1082 {
1083 status = mcbspSubmitReq(instHandle,chanHandle,ioBuf);
1084 }
1085 else
1086 {
1087 status = MCBSP_ERR_BADIO;
1088 }
1089 break;
1090 case Mcbsp_IOBuf_Cmd_FLUSH:
1091 /* Flush command has been issued need to abort the receive *
1092 * channel buffers and complete the TX buffers normally */
1093 chanHandle->flush = TRUE;
1094 Mcbsp_localAbortReset(chanHandle);
1095 chanHandle->flush = FALSE;
1096 break;
1097 case Mcbsp_IOBuf_Cmd_ABORT:
1098 Mcbsp_localAbortReset(chanHandle);
1099 break;
1100 default:
1101 status = MCBSP_ERR_BADIO;
1102 break;
1103 }
1104 }
1106 return status;
1107 }
1109 /**
1110 * \brief Implements the IOCTLS for McBSP driver.
1111 *
1112 * ControlChan() implements recieved IOCTL commands from the
1113 * application and executes them accordingly.
1114 *
1115 * \param chanp [IN] Pointer to channel
1116 * \param cmd [IN] specific IOCTL command
1117 * \param arg [IN] arguments required for specific commands
1118 *
1119 * \return MCBSP_STATUS_COMPLETED, if command is executed correctly
1120 * MCBSP_STATUS_ABORTED, if command returns error during execution
1121 * MCBSP_ERR_NOTIMPL, if command is not supported
1122 * MCBSP_ERR_BADARGS if args are not correct
1123 */
1124 int32_t mcbspControlChan(void* chanp, Mcbsp_IOCTL cmd, void* arg)
1125 {
1126 Mcbsp_ChannelObj *chanHandle = NULL;
1127 int32_t status = MCBSP_STATUS_COMPLETED;
1129 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
1130 if (NULL == chanp)
1131 {
1132 status = MCBSP_ERR_BADARGS;
1133 }
1134 else
1135 {
1136 #endif /* MCBSP_DISABLE_INPUT_PARAM_CHECK */
1138 chanHandle = (Mcbsp_ChannelObj *)chanp;
1140 /* Invalidate the Cache Contents */
1141 Mcbsp_osalBeginMemAccess ((void *)chanHandle->devHandle, sizeof(Mcbsp_Object));
1143 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
1144 if (NULL == chanHandle->devHandle)
1145 {
1146 status = MCBSP_ERR_BADARGS;
1147 }
1148 }
1149 #endif
1151 if (MCBSP_STATUS_COMPLETED == status)
1152 {
1153 /* call the function to process the IOCTL command */
1154 status = Mcbsp_localSubmitIoctl(
1155 chanHandle,
1156 cmd,
1157 arg,
1158 NULL);
1159 }
1161 /* Writeback Global Object */
1162 Mcbsp_osalEndMemAccess ((void *)chanHandle->devHandle, sizeof(Mcbsp_Object));
1164 return (status);
1165 }
1167 /**
1168 * \brief McBSP Tx ISR function
1169 *
1170 * This Function is the interrupt service routine for the Mcbsp TX
1171 * event.
1172 *
1173 * \param hChan [IN] Handle to the channel
1174 *
1175 * \return None
1176 */
1177 void mcbspGblXmtIsr(void *hChan)
1178 {
1179 Mcbsp_Object_Unpadded *instHandle = NULL;
1180 Mcbsp_ChannelObj *chanHandle = (Mcbsp_ChannelObj *)hChan;
1182 instHandle = (Mcbsp_Object_Unpadded *)&(chanHandle->devHandle->obj);
1184 /* Only DMA mode of operation is supported by the Mcbsp driver hence we *
1185 * will only check if there is an sync error and notify the application */
1186 if (CSL_MCBSP_SPCR_XSYNCERR_MASK ==
1187 (CSL_MCBSP_SPCR_XSYNCERR_MASK & instHandle->hwInfo.regs->SPCR))
1188 {
1189 /* call the application registered global callback function */
1190 if (NULL != chanHandle->gblErrCbk)
1191 {
1192 (*chanHandle->gblErrCbk)((uint32_t)chanHandle,
1193 instHandle->hwInfo.regs->SPCR,
1194 NULL);
1195 }
1196 }
1198 return;
1199 }
1201 /**
1202 * \brief McBSP Rx ISR function
1203 *
1204 * This Function is the interrupt service routine for the Mcbsp RX
1205 * event.
1206 *
1207 * \param hChan [IN] Handle to the channel
1208 *
1209 * \return None
1210 */
1211 void mcbspGblRcvIsr(void *hChan)
1212 {
1213 Mcbsp_Object_Unpadded *instHandle = NULL;
1214 Mcbsp_ChannelObj *chanHandle = (Mcbsp_ChannelObj *)hChan;
1216 instHandle = (Mcbsp_Object_Unpadded *)&(chanHandle->devHandle->obj);
1218 /* Only DMA mode of operation is supported by the Mcbsp driver hence we *
1219 * will only check if there is an sync error and notify the application */
1220 if (CSL_MCBSP_SPCR_RSYNCERR_MASK ==
1221 (CSL_MCBSP_SPCR_RSYNCERR_MASK & instHandle->hwInfo.regs->SPCR))
1222 {
1223 /* call the application registered global callback function */
1224 if (NULL != chanHandle->gblErrCbk)
1225 {
1226 (*chanHandle->gblErrCbk)((uint32_t)chanHandle,
1227 instHandle->hwInfo.regs->SPCR,
1228 NULL);
1229 }
1230 }
1232 return;
1233 }
1235 /*============================================================================*/
1236 /* LOCAL FUNCTION DEFINTIONS */
1237 /*============================================================================*/
1239 /**
1240 * \brief Submit a I/O buffer to a channel for processing
1241 *
1242 * This function is called with the Mcbsp_IOBuf_Cmd_READ or Mcbsp_IOBuf_Cmd_WRITE
1243 * command to process the IOP. The function handles the MCBSP mode. In case
1244 * that the driver is currently idle it sets up buffer for transfer. In case
1245 * that the driver is currently processing a buffer then it will queue up the
1246 * current buffer and exit.
1247 *
1248 * \param instHandle [IN] pointer to the instance object
1249 * \param chanHandle [IN] handle to the channel
1250 * \param ioBuf [IN] pointer to Mcbsp I/O buffer.
1251 *
1252 * \return MCBSP_STATUS_PENDING in case the buffer is sucesfully processed
1253 * MCBSP_ERR_BADIO in case of any error.
1254 */
1255 int32_t mcbspSubmitReq(Mcbsp_Object_Unpadded *instHandle,
1256 Mcbsp_ChannelObj *chanHandle,
1257 Mcbsp_IOBuf *ioBuf)
1258 {
1259 void* criticalSectionInfo;
1260 int32_t status = MCBSP_STATUS_COMPLETED;
1262 if ((NULL == chanHandle) || (NULL == ioBuf) || (NULL == instHandle))
1263 {
1264 return MCBSP_ERR_BADIO;
1265 }
1266 if((0 == ioBuf->size) || (ioBuf->size > Mcbsp_MAX_IOBUF_SIZE))
1267 {
1268 return MCBSP_ERR_BADIO;
1269 }
1271 /* clean the buffers if the cache operation mode is enabled */
1272 if (TRUE == instHandle->enablecache)
1273 {
1274 if (MCBSP_MODE_INPUT == chanHandle->mode)
1275 {
1276 /* Invalidate the cache */
1277 Mcbsp_osalBeginMemAccess(ioBuf->addr, ioBuf->size);
1278 }
1279 else
1280 {
1281 /* Writeback the cache */
1282 Mcbsp_osalEndMemAccess(ioBuf->addr, ioBuf->size);
1283 }
1284 }
1286 /*==========================MCBSP MODE ===================================*/
1287 if (Mcbsp_DevMode_McBSP == instHandle->mode)
1288 {
1289 /* We are entering the crictical section because the current active *
1290 * IOP is being check and it can become NULL at any point. Hence we *
1291 * will protect this code from the interrupt handler. */
1292 criticalSectionInfo = Mcbsp_osalEnterSingleCoreCriticalSection();
1294 #ifdef MCBSP_LOOPJOB_ENABLE
1295 if ((Mcbsp_MAXLINKCNT <= chanHandle->submitCount) ||
1296 #else
1297 /* We now have 3 buffers loaded in the EDMA */
1298 if (((Mcbsp_MAXLINKCNT + 1) <= chanHandle->submitCount) ||
1299 #endif
1300 (TRUE == chanHandle->paused))
1301 {
1302 /* There are enough buffers programmed in the EDMA or if the MCBSP*
1303 * is issued a pause command,hence queue buffer in to the pending *
1304 * queue */
1305 chanHandle->submitCount++;
1307 Mcbsp_osalQueuePut(chanHandle->ptrQPendList,(void*)ioBuf);
1309 /* critical section ends */
1310 Mcbsp_osalExitSingleCoreCriticalSection(criticalSectionInfo);
1311 }
1312 else
1313 {
1314 /* Either one of the paramset or Both the paramsets are free */
1316 /* increment the submit count */
1317 chanHandle->submitCount++;
1319 Mcbsp_osalQueuePut(chanHandle->ptrQFloatList, (void*)ioBuf);
1321 Mcbsp_localLoadPktToEdma(chanHandle,ioBuf);
1323 /* critical section ends */
1324 Mcbsp_osalExitSingleCoreCriticalSection(criticalSectionInfo);
1326 } /* Pending queue empty or not*/
1327 }
1328 if (MCBSP_STATUS_COMPLETED == status)
1329 {
1330 status = MCBSP_STATUS_PENDING;
1331 }
1332 return (status);
1333 }
1335 /**
1336 * \brief McBSP SPCR configuration function
1337 *
1338 * This Function is used to set/reset specific bit of SPCR as specified in
1339 * the given mask.
1340 *
1341 * \param instHandle [IN] pointer to the mcbsp instance object.
1342 * \param selectMask [IN] the SPCR control mask
1343 *
1344 * \return MCBSP_STATUS_COMPLETED if successful
1345 *
1346 * MCBSP_ERR_BADARGS if not successful
1347 */
1348 int32_t Mcbsp_localResetCtrl(Mcbsp_Object_Unpadded *instHandle, uint32_t selectMask)
1349 {
1350 if ((NULL == instHandle) || (NULL == instHandle->hwInfo.regs))
1351 {
1352 return MCBSP_ERR_BADARGS;
1353 }
1355 /* Configuring SPCR for Frame sync generator enable/disable */
1356 if (0u != (selectMask & Mcbsp_SpcrCtrl_FSYNC_DISABLE))
1357 {
1358 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_FRST_MASK );
1359 }
1361 if (0 != (selectMask & Mcbsp_SpcrCtrl_RX_DISABLE))
1362 {
1363 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_RRST_MASK );
1364 }
1366 /* start the sample rate generator */
1367 if (0u != (selectMask & Mcbsp_SpcrCtrl_SRG_ENABLE))
1368 {
1369 instHandle->hwInfo.regs->SPCR |= CSL_MCBSP_SPCR_GRST_MASK;
1370 }
1372 /* Configuring SPCR for Transmit enable/disable */
1373 if (0 != (selectMask & Mcbsp_SpcrCtrl_TX_DISABLE))
1374 {
1375 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_XRST_MASK);
1376 }
1378 /* Configuring SPCR for transmit section enable */
1379 if (0 != (selectMask & Mcbsp_SpcrCtrl_TX_ENABLE))
1380 {
1381 instHandle->hwInfo.regs->SPCR |= CSL_MCBSP_SPCR_XRST_MASK;
1382 }
1384 /* Configuring SPCR for Receive section enable */
1385 if (0 != (selectMask & Mcbsp_SpcrCtrl_RX_ENABLE))
1386 {
1387 instHandle->hwInfo.regs->SPCR |= CSL_MCBSP_SPCR_RRST_MASK ;
1388 }
1390 /* Set the FRST bit to 1 to start the internal frame sync generator */
1391 if (0u != (selectMask & Mcbsp_SpcrCtrl_FSYNC_ENABLE))
1392 {
1393 instHandle->hwInfo.regs->SPCR |= CSL_MCBSP_SPCR_FRST_MASK;
1394 }
1396 /* Configuring SPCR for sample rate generator enable/disable */
1397 if (0u != (selectMask & Mcbsp_SpcrCtrl_SRG_DISABLE))
1398 {
1399 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_GRST_MASK);
1400 }
1402 return MCBSP_STATUS_COMPLETED;
1403 }
1405 /**
1406 * \brief This function completes the current pending request and then
1407 * invokes the application registered callback.
1408 *
1409 * \param chanHandle [IN] Handle to the channel
1410 *
1411 * \return None
1412 *
1413 * \enter chanHandle is a valid non null pointer
1414 *
1415 * \leave Not implemented
1416 */
1417 void Mcbsp_localCompleteCurrentIo(Mcbsp_ChannelObj *chanHandle)
1418 {
1419 Mcbsp_IOBuf *ioBuf = NULL;
1421 if (TRUE == chanHandle->isTempIOBufValid)
1422 {
1423 ioBuf = chanHandle->tempIOBuf;
1425 chanHandle->tempIOBuf = NULL;
1426 chanHandle->isTempIOBufValid = FALSE;
1427 /* call the completion callback function registered with us *
1428 * during channel creation */
1429 if ((NULL != chanHandle->cbFxn) && (NULL != chanHandle->cbArg))
1430 {
1431 /* Application callback */
1432 (*chanHandle->cbFxn)((void*)chanHandle->cbArg,ioBuf);
1433 }
1434 }
1436 chanHandle->currentError = MCBSP_STATUS_COMPLETED;
1437 chanHandle->userDataBufferSize = 0;
1438 }
1440 /**
1441 * \brief This function configures the transmit section of the mcbsp
1442 * sync properties.
1443 *
1444 * \param instHandle [IN] pointer to the instance object.
1445 * \param params [IN] User supplied channel parameters
1446 *
1447 * \return MCBSP_ERR_BADARGS if configuration fails.
1448 * MCBSP_STATUS_COMPLETED if configuration is sucessful.
1449 */
1450 int32_t Mcbsp_localConfigureXmtChannel(Mcbsp_Object_Unpadded *instHandle,
1451 Mcbsp_ChanParams *params)
1452 {
1453 uint32_t tempVal = 0x00;
1454 int32_t status = MCBSP_STATUS_COMPLETED;
1456 if ((NULL == instHandle) || (NULL == params))
1457 {
1458 return MCBSP_ERR_BADARGS;
1459 }
1461 /* configure the transmit section */
1462 /* configure the transmit interrupt setting */
1463 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_XINTM_MASK);
1464 instHandle->hwInfo.regs->SPCR |=
1465 (params->chanConfig->intMode << CSL_MCBSP_SPCR_XINTM_SHIFT);
1467 /* configure the DX enabler */
1468 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_DXENA_MASK);
1469 instHandle->hwInfo.regs->SPCR |=
1470 (params->chanConfig->dxState << CSL_MCBSP_SPCR_DXENA_SHIFT);
1472 /* configure the transmit control register settings */
1473 instHandle->hwInfo.regs->XCR &= (~CSL_MCBSP_XCR_XPHASE_MASK);
1474 instHandle->hwInfo.regs->XCR |=
1475 (params->chanConfig->phaseNum << CSL_MCBSP_XCR_XPHASE_SHIFT);
1477 /* configure the frame length for single and dual phase frames */
1478 instHandle->hwInfo.regs->XCR &= (~CSL_MCBSP_XCR_XFRLEN1_MASK);
1479 instHandle->hwInfo.regs->XCR |=
1480 ((params->chanConfig->frmLen1 - 1u) << CSL_MCBSP_XCR_XFRLEN1_SHIFT);
1482 /* configure the word length of the single and dual phase frames */
1483 switch (params->chanConfig->wrdLen1)
1484 {
1485 case Mcbsp_WordLength_8:
1486 tempVal = 0u;
1487 break;
1488 case Mcbsp_WordLength_12:
1489 tempVal = 1u;
1490 break;
1491 case Mcbsp_WordLength_16:
1492 tempVal = 2u;
1493 break;
1494 case Mcbsp_WordLength_20:
1495 tempVal = 3u;
1496 break;
1497 case Mcbsp_WordLength_24:
1498 tempVal = 4u;
1499 break;
1500 case Mcbsp_WordLength_32:
1501 tempVal = 5u;
1502 break;
1503 default:
1504 /* wordlength is not supported by the driver */
1505 status = MCBSP_ERR_BADARGS;
1506 break;
1507 }
1509 instHandle->hwInfo.regs->XCR &= (~CSL_MCBSP_XCR_XWDLEN1_MASK);
1510 instHandle->hwInfo.regs->XCR |=
1511 (tempVal << CSL_MCBSP_XCR_XWDLEN1_SHIFT);
1513 if (Mcbsp_Phase_DUAL == params->chanConfig->phaseNum)
1514 {
1516 instHandle->hwInfo.regs->XCR &= (~CSL_MCBSP_XCR_XFRLEN2_MASK);
1517 instHandle->hwInfo.regs->XCR |=
1518 ((params->chanConfig->frmLen2 -1u) << CSL_MCBSP_XCR_XFRLEN2_SHIFT);
1520 /* configure the word length of the single and dual phase frames */
1521 switch (params->chanConfig->wrdLen2)
1522 {
1523 case Mcbsp_WordLength_8:
1524 tempVal = 0u;
1525 break;
1526 case Mcbsp_WordLength_12:
1527 tempVal = 1u;
1528 break;
1529 case Mcbsp_WordLength_16:
1530 tempVal = 2u;
1531 break;
1532 case Mcbsp_WordLength_20:
1533 tempVal = 3u;
1534 break;
1535 case Mcbsp_WordLength_24:
1536 tempVal = 4u;
1537 break;
1538 case Mcbsp_WordLength_32:
1539 tempVal = 5u;
1540 break;
1541 default:
1542 /* wordlength is not supported by the driver */
1543 status = MCBSP_ERR_BADARGS;
1544 break;
1545 }
1547 instHandle->hwInfo.regs->XCR &= (~CSL_MCBSP_XCR_XWDLEN2_MASK);
1548 instHandle->hwInfo.regs->XCR |=
1549 (tempVal << CSL_MCBSP_XCR_XWDLEN2_SHIFT);
1550 }
1551 /* set the companding selection */
1552 instHandle->hwInfo.regs->XCR &= (~CSL_MCBSP_XCR_XCOMPAND_MASK);
1553 instHandle->hwInfo.regs->XCR |=
1554 (params->chanConfig->compandSel << CSL_MCBSP_XCR_XCOMPAND_SHIFT);
1556 /* set the bit reverse settings */
1557 instHandle->hwInfo.regs->XCR &= (~CSL_MCBSP_XCR_XWDREVRS_MASK);
1558 instHandle->hwInfo.regs->XCR |=
1559 (params->chanConfig->bitReversal << CSL_MCBSP_XCR_XWDREVRS_SHIFT);
1561 /* frame ignore settings */
1562 instHandle->hwInfo.regs->XCR &= (~CSL_MCBSP_XCR_XFIG_MASK);
1563 instHandle->hwInfo.regs->XCR |=
1564 (params->chanConfig->frmSyncIgn << CSL_MCBSP_XCR_XFIG_SHIFT);
1566 /* configure the data delay */
1567 instHandle->hwInfo.regs->XCR &= (~CSL_MCBSP_XCR_XDATDLY_MASK);
1568 instHandle->hwInfo.regs->XCR |=
1569 (params->chanConfig->dataDelay << CSL_MCBSP_XCR_XDATDLY_SHIFT);
1571 /* configure the multi channel control register settings */
1572 instHandle->hwInfo.regs->MCR &= (~CSL_MCBSP_MCR_XMCM_MASK);
1573 instHandle->hwInfo.regs->MCR |= (params->multiChanCtrl->multiChanMode
1574 << CSL_MCBSP_MCR_XMCM_SHIFT);
1576 /* select the partition mode and the channel selection controls */
1577 instHandle->hwInfo.regs->MCR &= (~CSL_MCBSP_MCR_XPABLK_MASK);
1578 instHandle->hwInfo.regs->MCR |= (params->multiChanCtrl->partitionSelA
1579 << CSL_MCBSP_MCR_XPABLK_SHIFT);
1581 instHandle->hwInfo.regs->MCR &= (~CSL_MCBSP_MCR_XPBBLK_MASK);
1582 instHandle->hwInfo.regs->MCR |= (params->multiChanCtrl->partitionSelB
1583 << CSL_MCBSP_MCR_XPBBLK_SHIFT);
1585 instHandle->hwInfo.regs->MCR &= (~CSL_MCBSP_MCR_XMCME_MASK);
1586 instHandle->hwInfo.regs->MCR |= (params->multiChanCtrl->partitionMode
1587 << CSL_MCBSP_MCR_XMCME_SHIFT);
1589 /* Configure the channels to be enabled */
1590 instHandle->hwInfo.regs->XCERE0 = params->chanEnableMask[0];
1591 instHandle->hwInfo.regs->XCERE1 = params->chanEnableMask[1];
1592 instHandle->hwInfo.regs->XCERE2 = params->chanEnableMask[2];
1593 instHandle->hwInfo.regs->XCERE3 = params->chanEnableMask[3];
1596 /* configure the clock polarity */
1597 if (Mcbsp_ClkPol_RISING_EDGE == params->clkSetup->clkPolarity)
1598 {
1599 /* clock data sampled on rising edge */
1600 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_CLKXP_MASK);
1601 }
1602 else
1603 {
1604 /* clock data sampled on falling edge */
1605 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_CLKXP_MASK);
1606 }
1608 /* configure the frame sync polarity */
1609 if (Mcbsp_FsPol_ACTIVE_HIGH == params->clkSetup->frmSyncPolarity)
1610 {
1611 /* frame sync polarity is active high */
1612 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_FSXP_MASK);
1613 }
1614 else
1615 {
1616 /* frame sync polarity is active low */
1617 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_FSXP_MASK);
1618 }
1620 /* check if the frame sync generator is to be enabled for this TX section */
1621 if (Mcbsp_FsClkMode_EXTERNAL == params->clkSetup->frmSyncMode)
1622 {
1623 /* External frame sync to be used */
1624 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_FSXM_MASK);
1626 /* frame sync generator needs to be disabled */
1627 instHandle->txFsgEnable = FALSE;
1628 }
1629 else
1630 {
1631 /* internal frame sync to be used */
1632 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_FSXM_MASK);
1634 /* The FRST and GRST has to be cleared to configure the FSGM bit.
1635 * By clearing the FRST and GRST bit, the sample rate generator and the
1636 * frame sync generator will be kept in the reset mode.
1637 * Ref IR SDOCM00077966
1638 */
1639 tempVal = instHandle->hwInfo.regs->SPCR;
1640 instHandle->hwInfo.regs->SPCR &= ~(CSL_MCBSP_SPCR_FRST_MASK |
1641 CSL_MCBSP_SPCR_GRST_MASK );
1643 /* could be internal or configured for DXR to XSR copy */
1644 if (Mcbsp_FsClkMode_INTERNAL == params->clkSetup->frmSyncMode)
1645 {
1646 /* set the FSGM bit in the SRGR register */
1647 instHandle->hwInfo.regs->SRGR |= (CSL_MCBSP_SRGR_FSGM_MASK);
1649 /* frame sync generator needs to be enabled */
1650 instHandle->txFsgEnable = TRUE;
1651 }
1652 else
1653 { /* DXR to XSR copy generates frame sync */
1654 /* reset the FSGM bit in the SRGR register */
1655 instHandle->hwInfo.regs->SRGR &= (~CSL_MCBSP_SRGR_FSGM_MASK);
1657 /* frame sync generator needs to be disabled */
1658 instHandle->txFsgEnable = FALSE;
1659 }
1660 /* The SPCR register values are reverted back once the FSGM bit is set
1661 */
1662 instHandle->hwInfo.regs->SPCR = tempVal;
1663 }
1665 /* configure the clock mode (external or internal) */
1666 if (Mcbsp_TxRxClkMode_EXTERNAL == params->clkSetup->clkMode)
1667 {
1668 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_CLKXM_MASK);
1670 if (TRUE == instHandle->txFsgEnable)
1671 {
1672 /* frame sync generator is using the internal clock hence need to *
1673 * enable the sample rate generator */
1674 instHandle->txSrgEnable = TRUE;
1675 }
1676 else
1677 {
1678 /* dont require to enable the sample rate generator */
1679 instHandle->txSrgEnable = FALSE;
1680 }
1681 }
1682 else
1683 {
1684 /* external mode clock enabled */
1685 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_CLKXM_MASK);
1687 /* sample rate generator is enabled */
1688 instHandle->txSrgEnable = TRUE;
1689 }
1691 return (status);
1692 }
1695 /**
1696 * \brief This function configures the receives section of the mcbsp.
1697 *
1698 * \param instHandle [IN] pointer to the instance object.
1699 * \param params [IN] User supplied channel parameters
1700 *
1701 * \return MCBSP_ERR_BADARGS if configuration fails.
1702 * MCBSP_STATUS_COMPLETED if confioguration is sucessful.
1703 */
1704 int32_t Mcbsp_localConfigureRcvChannel(Mcbsp_Object_Unpadded *instHandle,
1705 Mcbsp_ChanParams *params)
1706 {
1707 uint32_t tempVal = 0x00;
1708 int32_t status = MCBSP_STATUS_COMPLETED;
1710 if ((NULL == instHandle) || (NULL == params))
1711 {
1712 return MCBSP_ERR_BADARGS;
1713 }
1715 /* configure the receive section */
1716 /* configure the receive interrupt setting */
1717 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_RINTM_MASK);
1718 instHandle->hwInfo.regs->SPCR |=
1719 (params->chanConfig->intMode << CSL_MCBSP_SPCR_RINTM_SHIFT);
1721 /* configure the Receive sign-extension and justification */
1722 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_RJUST_MASK);
1723 instHandle->hwInfo.regs->SPCR |=
1724 (params->chanConfig->rjust << CSL_MCBSP_SPCR_RJUST_SHIFT);
1726 /* configure the receive control register settings */
1727 instHandle->hwInfo.regs->RCR &= (~CSL_MCBSP_RCR_RPHASE_MASK);
1728 instHandle->hwInfo.regs->RCR |=
1729 (params->chanConfig->phaseNum << CSL_MCBSP_RCR_RPHASE_SHIFT);
1731 /* configure the frame length for single and dual phase frames */
1732 instHandle->hwInfo.regs->RCR &= (~CSL_MCBSP_RCR_RFRLEN1_MASK);
1733 instHandle->hwInfo.regs->RCR |=
1734 ((params->chanConfig->frmLen1 - 1u) << CSL_MCBSP_RCR_RFRLEN1_SHIFT);
1736 /* configure the word length of the single and dual phase frames */
1737 switch (params->chanConfig->wrdLen1)
1738 {
1739 case Mcbsp_WordLength_8:
1740 tempVal = 0u;
1741 break;
1742 case Mcbsp_WordLength_12:
1743 tempVal = 1u;
1744 break;
1745 case Mcbsp_WordLength_16:
1746 tempVal = 2u;
1747 break;
1748 case Mcbsp_WordLength_20:
1749 tempVal = 3u;
1750 break;
1751 case Mcbsp_WordLength_24:
1752 tempVal = 4u;
1753 break;
1754 case Mcbsp_WordLength_32:
1755 tempVal = 5u;
1756 break;
1757 default:
1758 /* wordlength is not supported by the driver */
1759 status = MCBSP_ERR_BADARGS;
1760 break;
1761 }
1764 instHandle->hwInfo.regs->RCR &= (~CSL_MCBSP_RCR_RWDLEN1_MASK);
1765 instHandle->hwInfo.regs->RCR |=
1766 (tempVal << CSL_MCBSP_RCR_RWDLEN1_SHIFT);
1768 if (Mcbsp_Phase_DUAL == params->chanConfig->phaseNum)
1769 {
1770 instHandle->hwInfo.regs->RCR &= (~CSL_MCBSP_RCR_RFRLEN2_MASK);
1771 instHandle->hwInfo.regs->RCR |=
1772 ((params->chanConfig->frmLen2 - 1u) << CSL_MCBSP_RCR_RFRLEN2_SHIFT);
1774 /* configure the word length of the single and dual phase frames */
1775 switch (params->chanConfig->wrdLen2)
1776 {
1777 case Mcbsp_WordLength_8:
1778 tempVal = 0u;
1779 break;
1780 case Mcbsp_WordLength_12:
1781 tempVal = 1u;
1782 break;
1783 case Mcbsp_WordLength_16:
1784 tempVal = 2u;
1785 break;
1786 case Mcbsp_WordLength_20:
1787 tempVal = 3u;
1788 break;
1789 case Mcbsp_WordLength_24:
1790 tempVal = 4u;
1791 break;
1792 case Mcbsp_WordLength_32:
1793 tempVal = 5u;
1794 break;
1795 default:
1796 /* wordlength is not supported by the driver */
1797 status = MCBSP_ERR_BADARGS;
1798 break;
1799 }
1801 instHandle->hwInfo.regs->RCR &= (~CSL_MCBSP_RCR_RWDLEN2_MASK);
1802 instHandle->hwInfo.regs->RCR |=
1803 (tempVal << CSL_MCBSP_RCR_RWDLEN2_SHIFT);
1804 }
1805 /* set the companding selection */
1806 instHandle->hwInfo.regs->RCR &= (~CSL_MCBSP_RCR_RCOMPAND_MASK);
1807 instHandle->hwInfo.regs->RCR |=
1808 (params->chanConfig->compandSel << CSL_MCBSP_RCR_RCOMPAND_SHIFT);
1810 /* set the bit reverse settings */
1811 instHandle->hwInfo.regs->RCR &= (~CSL_MCBSP_RCR_RWDREVRS_MASK);
1812 instHandle->hwInfo.regs->RCR |=
1813 (params->chanConfig->bitReversal << CSL_MCBSP_RCR_RWDREVRS_SHIFT);
1815 /* frame ignore settings */
1816 instHandle->hwInfo.regs->RCR &= (~CSL_MCBSP_RCR_RFIG_MASK);
1817 instHandle->hwInfo.regs->RCR |=
1818 (params->chanConfig->frmSyncIgn << CSL_MCBSP_RCR_RFIG_SHIFT);
1820 /* configure the data delay */
1821 instHandle->hwInfo.regs->RCR &= (~CSL_MCBSP_RCR_RDATDLY_MASK);
1822 instHandle->hwInfo.regs->RCR |=
1823 (params->chanConfig->dataDelay << CSL_MCBSP_RCR_RDATDLY_SHIFT);
1825 /* Configure the channels to be enabled */
1826 instHandle->hwInfo.regs->RCERE0 = params->chanEnableMask[0];
1827 instHandle->hwInfo.regs->RCERE1 = params->chanEnableMask[1];
1828 instHandle->hwInfo.regs->RCERE2 = params->chanEnableMask[2];
1829 instHandle->hwInfo.regs->RCERE3 = params->chanEnableMask[3];
1831 /* configure the MCR register */
1832 switch (params->multiChanCtrl->multiChanMode)
1833 {
1834 case Mcbsp_McmMode_ALL_CHAN_ENABLED_UNMASKED:
1835 case Mcbsp_McmMode_ALL_CHAN_DISABLED_UNMASKED:
1836 break;
1837 default:
1838 status = MCBSP_ERR_BADARGS;
1839 break;
1840 }
1842 if (MCBSP_STATUS_COMPLETED == status)
1843 {
1844 instHandle->hwInfo.regs->MCR &= (~CSL_MCBSP_MCR_RMCM_MASK);
1845 instHandle->hwInfo.regs->MCR |= (params->multiChanCtrl->multiChanMode
1846 << CSL_MCBSP_MCR_RMCM_SHIFT);
1847 }
1849 /* select the partition mode and the channel selection controls */
1850 instHandle->hwInfo.regs->MCR &= (~CSL_MCBSP_MCR_RPABLK_MASK);
1851 instHandle->hwInfo.regs->MCR |= (params->multiChanCtrl->partitionSelA
1852 << CSL_MCBSP_MCR_RPABLK_SHIFT);
1854 instHandle->hwInfo.regs->MCR &= (~CSL_MCBSP_MCR_RPBBLK_MASK);
1855 instHandle->hwInfo.regs->MCR |= (params->multiChanCtrl->partitionSelB
1856 << CSL_MCBSP_MCR_RPBBLK_SHIFT);
1858 instHandle->hwInfo.regs->MCR &= (~CSL_MCBSP_MCR_RMCME_MASK);
1859 instHandle->hwInfo.regs->MCR |= (params->multiChanCtrl->partitionMode
1860 << CSL_MCBSP_MCR_RMCME_SHIFT);
1862 /* configure the clock polarity */
1863 if (Mcbsp_ClkPol_RISING_EDGE == params->clkSetup->clkPolarity)
1864 {
1865 /* clock data sampled on rising edge */
1866 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_CLKRP_MASK);
1867 }
1868 else
1869 {
1870 /* clock data sampled on falling edge */
1871 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_CLKRP_MASK);
1872 }
1874 /* configure the frame sync polarity */
1875 if (Mcbsp_FsPol_ACTIVE_HIGH == params->clkSetup->frmSyncPolarity)
1876 {
1877 /* frame sync polarity is active high */
1878 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_FSRP_MASK);
1879 }
1880 else
1881 {
1882 /* frame sync polarity is active low */
1883 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_FSRP_MASK);
1884 }
1887 /* check if the frame sync generator is to be enabled for this section */
1888 if (Mcbsp_FsClkMode_INTERNAL == params->clkSetup->frmSyncMode)
1889 {
1890 /* set the frame sync generation mode */
1891 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_FSRM_MASK);
1893 /* frame sync generator needs to be enabled */
1894 instHandle->rxFsgEnable = TRUE;
1895 }
1896 else
1897 {
1898 /* reset the frame sync generation mode */
1899 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_FSRM_MASK);
1901 /* frame sync generator needs to be disabled */
1902 instHandle->rxFsgEnable = FALSE;
1903 }
1905 /* configure the clock mode (external or internal) */
1906 if (Mcbsp_TxRxClkMode_EXTERNAL == params->clkSetup->clkMode)
1907 {
1908 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_CLKRM_MASK);
1910 if (TRUE == instHandle->rxFsgEnable)
1911 {
1912 /* frame sync generator is using the internal clock hence need to *
1913 * enable the sample rate generator */
1914 instHandle->rxSrgEnable = TRUE;
1915 }
1916 else
1917 {
1918 /* dont require to enable the sample rate generator */
1919 instHandle->rxSrgEnable = FALSE;
1920 }
1921 }
1922 else
1923 {
1924 /* external mode clock */
1925 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_CLKRM_MASK);
1927 /* sample rate generator is enabled */
1928 instHandle->rxSrgEnable = TRUE;
1929 }
1930 return (status);
1931 }
1933 /**
1934 * \brief This function configures the sample rate generator and frame
1935 * sync properties.
1936 *
1937 * \param instHandle [IN] pointer to the instance object.
1938 * \param chanHandle [IN] Handle to the channel.
1939 *
1940 * \return MCBSP_ERR_BADARGS if calculation fails.
1941 * MCBSP_STATUS_COMPLETED if calculation is sucessful.
1942 */
1943 int32_t Mcbsp_localConfigureSrgr(Mcbsp_Object_Unpadded *instHandle,
1944 Mcbsp_ChannelObj *chanHandle)
1945 {
1946 Bool srgrConfig = FALSE;
1947 uint32_t clkgDiv = 0x00;
1948 uint32_t noOfBits = 0x00;
1949 uint32_t framePeriod = 0x00;
1950 Bool sclkme = 0x00;
1951 Bool clksm = 0x00;
1952 int32_t status = MCBSP_STATUS_COMPLETED;
1953 void* criticalSectionInfo;
1955 if ((NULL == instHandle) || (NULL == chanHandle))
1956 {
1957 return MCBSP_ERR_BADARGS;
1958 }
1960 /* check if the SRGR is not configured already */
1961 /* critical section starts */
1962 criticalSectionInfo = Mcbsp_osalEnterSingleCoreCriticalSection();
1964 if (FALSE == instHandle->srgConfigured)
1965 {
1966 /* set the status that SRGR is configured */
1967 instHandle->srgConfigured = TRUE;
1969 /* critical section ends */
1970 Mcbsp_osalExitSingleCoreCriticalSection(criticalSectionInfo);
1972 /* check if this channel requires the SRGR to be enabled */
1973 if (MCBSP_MODE_INPUT == chanHandle->mode)
1974 {
1975 if (TRUE == instHandle->rxSrgEnable)
1976 {
1977 /* Need to configure the SRGR */
1978 srgrConfig = TRUE;
1979 }
1980 else
1981 {
1982 instHandle->srgConfigured = FALSE;
1983 }
1984 }
1985 else
1986 {
1987 if (TRUE == instHandle->txSrgEnable)
1988 {
1989 /* Need to configure the SRGR */
1990 srgrConfig = TRUE;
1991 }
1992 else
1993 {
1994 instHandle->srgConfigured = FALSE;
1995 }
1996 }
1997 }
1998 else
1999 {
2000 /* critical section ends */
2001 Mcbsp_osalExitSingleCoreCriticalSection(criticalSectionInfo);
2002 }
2004 if (TRUE == srgrConfig)
2005 {
2006 /* set the input clock selection for Sample rate generator */
2007 switch (instHandle->srgrConfig.srgInputClkMode)
2008 {
2009 /* Input clock is CLKS */
2010 case Mcbsp_SrgClk_CLKS:
2011 sclkme = 0x00;
2012 clksm = 0x00;
2014 /* set the CLKS polarity (only if CLKS is used) */
2015 instHandle->hwInfo.regs->SRGR &= (~CSL_MCBSP_SRGR_CLKSP_MASK);
2016 instHandle->hwInfo.regs->SRGR |=
2017 (instHandle->srgrConfig.clksPolarity
2018 << CSL_MCBSP_SRGR_CLKSP_SHIFT);
2020 /* set the GSYNC option */
2021 instHandle->hwInfo.regs->SRGR &= (~CSL_MCBSP_SRGR_GSYNC_MASK);
2022 instHandle->hwInfo.regs->SRGR |=
2023 (instHandle->srgrConfig.gSync
2024 << CSL_MCBSP_SRGR_GSYNC_SHIFT);
2025 break;
2026 /* Input clock for SRG is from CPU clock */
2027 case Mcbsp_SrgClk_CLKCPU:
2028 sclkme = 0x00;
2029 clksm = 0x01u;
2030 break;
2031 /* Input clock is from receive pin */
2032 case Mcbsp_SrgClk_CLKR:
2033 sclkme = 0x01u;
2034 clksm = 0x00;
2035 break;
2036 /* Input clock is from transmit pin */
2037 case Mcbsp_SrgClk_CLKX:
2038 sclkme = 0x01u;
2039 clksm = 0x01u;
2040 break;
2041 default:
2042 status = MCBSP_ERR_BADARGS;
2043 break;
2044 }
2046 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_SCLKME_MASK);
2047 instHandle->hwInfo.regs->PCR |= (sclkme << CSL_MCBSP_PCR_SCLKME_SHIFT);
2049 instHandle->hwInfo.regs->SRGR &= (~CSL_MCBSP_SRGR_CLKSM_MASK);
2050 instHandle->hwInfo.regs->SRGR |= (clksm << CSL_MCBSP_SRGR_CLKSM_SHIFT);
2052 /* calculate and set the CLKG div values */
2053 if (Mcbsp_Phase_DUAL == chanHandle->chanConfig.phaseNum)
2054 {
2055 noOfBits = ((chanHandle->chanConfig.wrdLen1
2056 * chanHandle->chanConfig.frmLen1)
2057 + (chanHandle->chanConfig.wrdLen2
2058 * chanHandle->chanConfig.frmLen2));
2059 }
2060 else
2061 {
2062 noOfBits = (chanHandle->chanConfig.wrdLen1
2063 * chanHandle->chanConfig.frmLen1);
2064 }
2066 clkgDiv = ((instHandle->srgrConfig.srgrInputFreq/
2067 (chanHandle->clkSetup.samplingRate
2068 * noOfBits)) - 1u);
2070 framePeriod = (noOfBits - 1u);
2072 if ((0xFF < clkgDiv) || (0xFFF < framePeriod) ||
2073 (MCBSP_STATUS_COMPLETED != status))
2074 {
2075 /* The CLKGDIV or frame period value has exceeded the limit */
2076 status = MCBSP_ERR_BADARGS;
2077 }
2078 else
2079 {
2080 /* set the value of the CLKGDIV */
2081 instHandle->hwInfo.regs->SRGR &= (~CSL_MCBSP_SRGR_CLKGDV_MASK);
2082 instHandle->hwInfo.regs->SRGR |= clkgDiv;
2084 /* set the value of the frame period */
2085 instHandle->hwInfo.regs->SRGR &= (~CSL_MCBSP_SRGR_FPER_MASK);
2086 instHandle->hwInfo.regs->SRGR |=
2087 (framePeriod << CSL_MCBSP_SRGR_FPER_SHIFT);
2089 /* set the frame width */
2090 instHandle->hwInfo.regs->SRGR &= (~CSL_MCBSP_SRGR_FWID_MASK);
2091 instHandle->hwInfo.regs->SRGR |=
2092 (instHandle->srgrConfig.srgFrmPulseWidth <<
2093 CSL_MCBSP_SRGR_FWID_SHIFT);
2094 }
2095 }
2097 return (status);
2098 }
2100 /**
2101 * \brief Abort the queued up requests.
2102 *
2103 * This commands aborts all the pending IO requests and returns them
2104 * to the application. The current state of the IO request will be set
2105 * to ABORTED.
2106 *
2107 * \param chanHandle [IN] Handle to the channel whose requests are to be
2108 * aborted
2109 *
2110 * \return None
2111 */
2112 void Mcbsp_localAbortReset(Mcbsp_ChannelObj *chanHandle)
2113 {
2114 Mcbsp_Object_Unpadded *instHandle = NULL;
2115 Mcbsp_IOBuf *ioBuf = NULL;
2116 void* criticalSectionInfo;
2117 uint32_t timeoutCount = 0x00;
2119 instHandle = (Mcbsp_Object_Unpadded *)&(chanHandle->devHandle->obj);
2121 /* initialize the retry count value */
2122 timeoutCount = instHandle->retryCount;
2124 /* critical section starts */
2125 criticalSectionInfo = Mcbsp_osalEnterSingleCoreCriticalSection();
2127 if (Mcbsp_DevMode_McBSP == instHandle->mode)
2128 {
2129 /* Disable the EDMA transfer for the current transfer channel */
2130 EDMA3_DRV_disableTransfer(
2131 chanHandle->edmaHandle,
2132 chanHandle->xferChan,
2133 EDMA3_DRV_TRIG_MODE_EVENT);
2135 if (MCBSP_MODE_OUTPUT == chanHandle->mode)
2136 {
2137 /* Wait for the TX to be empty */
2138 while ((CSL_MCBSP_SPCR_XEMPTY_MASK ==
2139 (CSL_MCBSP_SPCR_XEMPTY_MASK & instHandle->hwInfo.regs->SPCR)) &&
2140 (0 != timeoutCount))
2141 {
2142 timeoutCount--;
2143 }
2144 }
2146 /* Stop the McBSP instance */
2147 if (MCBSP_MODE_INPUT == chanHandle->mode)
2148 {
2149 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_RX_DISABLE);
2150 }
2151 else
2152 {
2153 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_TX_DISABLE);
2154 }
2156 /* Empty the floating queue. Aborted request is currently enqueued *
2157 * in the floating queue. Dequeue the floating request in EDMA *
2158 * param table and return the actual transfer element count */
2159 while (TRUE != Mcbsp_osalQueueEmpty(chanHandle->ptrQFloatList))
2160 {
2161 ioBuf = Mcbsp_osalQueueGet(chanHandle->ptrQFloatList);
2163 if (NULL != ioBuf)
2164 {
2165 /* if FLUSH cmd called for INPUT channel then status is equal *
2166 * to FLUSHED otherwise status is equal to ABORTED */
2167 if ((TRUE == chanHandle->flush) &&
2168 (MCBSP_MODE_INPUT == chanHandle->mode))
2169 {
2170 ioBuf->status = MCBSP_STATUS_FLUSHED;
2171 }
2172 else
2173 {
2174 ioBuf->status = MCBSP_STATUS_ABORTED;
2175 }
2177 if ((NULL != chanHandle->cbFxn) && (NULL != chanHandle->cbArg))
2178 {
2179 /* Application callback */
2180 (*chanHandle->cbFxn)((void*)chanHandle->cbArg,ioBuf);
2181 }
2182 /* Decrement the submit count */
2183 chanHandle->submitCount--;
2184 }
2185 }
2187 /* Empty the pending queue */
2188 while (TRUE != Mcbsp_osalQueueEmpty(chanHandle->ptrQPendList))
2189 {
2190 ioBuf = Mcbsp_osalQueueGet(chanHandle->ptrQPendList);
2192 if (NULL != ioBuf)
2193 {
2194 /* if FLUSH cmd called for INPUT channel then status is equal *
2195 * to MCBSP_STATUS_FLUSHED otherwise status is equal to MCBSP_STATUS_ABORTED */
2196 if ((TRUE == chanHandle->flush) &&
2197 (MCBSP_MODE_INPUT == chanHandle->mode))
2198 {
2199 ioBuf->status = MCBSP_STATUS_FLUSHED;
2200 }
2201 else
2202 {
2203 ioBuf->status = MCBSP_STATUS_ABORTED;
2204 }
2206 if ((NULL != chanHandle->cbFxn) && (NULL != chanHandle->cbArg))
2207 {
2208 /* Application callback */
2209 (*chanHandle->cbFxn)((void*)chanHandle->cbArg,ioBuf);
2210 }
2212 /* Decrement the submit count */
2213 chanHandle->submitCount--;
2214 }
2215 }
2217 /* As EDMA is disabled it might have thrown an error and set error bit*
2218 * Clear the error bit to enable the transfer again */
2219 EDMA3_DRV_clearErrorBits(chanHandle->edmaHandle,chanHandle->xferChan);
2221 /* Configure the EDMA channel and EDMA param tables with *
2222 * intialization configuration as they are configured at the *
2223 * create time. */
2224 Mcbsp_localEdmaChanPaRAMsetup(chanHandle);
2226 #ifdef MCBSP_LOOPJOB_ENABLE
2228 /* configure the FIFO for the specific channel */
2229 if (TRUE == chanHandle->enableHwFifo)
2230 {
2231 /* Disable and enable the FIFO so that the events are *
2232 * generated to the Mcbsp for the first time */
2233 mcbspConfigureFifo(&instHandle->hwInfo,chanHandle,FALSE);
2234 mcbspConfigureFifo(&instHandle->hwInfo,chanHandle,TRUE);
2235 }
2237 /* Enable the EDMA transfer to start the Loop job running */
2238 EDMA3_DRV_enableTransfer(
2239 chanHandle->edmaHandle,
2240 chanHandle->xferChan,
2241 EDMA3_DRV_TRIG_MODE_EVENT);
2243 chanHandle->loopjobUpdatedinParamset = TRUE;
2244 chanHandle->nextLinkParamSetToBeUpdated = 0;
2246 /* start the Mcbsp channel */
2247 if (MCBSP_MODE_INPUT == chanHandle->mode)
2248 {
2249 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_RX_ENABLE);
2250 }
2251 else
2252 {
2253 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_TX_ENABLE);
2254 }
2255 #endif
2256 }
2257 /* critical section ends */
2258 Mcbsp_osalExitSingleCoreCriticalSection(criticalSectionInfo);
2259 }
2260 /**
2261 *
2262 * \brief This function configures the Hardware FIFO
2263 *
2264 * \param hMcbsp [IN] pointer to the Mcbsp Hardware information struct
2265 * \param chanHandle [IN] handle to the channel
2266 * \param enableHwFifo [IN] option to Enable or disbale the FIFO
2267 *
2268 * \return None
2269 *
2270 * \enter hMcbsp is a valid non null pointer
2271 * chanHandle is a valid non null pointer
2272 *
2273 * \leave Not implemented
2274 *
2275 */
2276 void mcbspConfigureFifo(Mcbsp_HwInfo_Unpadded *hMcbsp,
2277 Mcbsp_ChannelObj *chanHandle,
2278 Bool enableHwFifo)
2279 {
2280 /* check if the HW FIFO usage is requested by the user for this channel */
2281 if (TRUE == enableHwFifo)
2282 {
2283 if (MCBSP_MODE_INPUT == chanHandle->mode)
2284 {
2285 /* configure the receive channel */
2286 /* Step 1 : configure the "WNUMDMA" and "WNUMEVT" bits before *
2287 * enabling the FIFO */
2288 hMcbsp->fifoRegs->RFIFOCTL =
2289 (1 << CSL_BFIFO_RFIFOCTL_RNUMEVT_SHIFT);
2291 hMcbsp->fifoRegs->RFIFOCTL |=
2292 (CSL_BFIFO_RFIFOCTL_RNUMDMA_1WORDS
2293 << CSL_BFIFO_RFIFOCTL_RNUMDMA_SHIFT);
2295 /* enable the FIFO now by setting the "WENA" bit */
2296 hMcbsp->fifoRegs->RFIFOCTL |=
2297 (CSL_BFIFO_RFIFOCTL_RENA_ENABLED
2298 << CSL_BFIFO_RFIFOCTL_RENA_SHIFT);
2299 }
2300 else
2301 {
2302 /* configure the transmit channel */
2303 /* Step 1 : configure the "WNUMDMA" and "WNUMEVT" bits before *
2304 * enabling the FIFO */
2305 hMcbsp->fifoRegs->WFIFOCTL =
2306 (1 << CSL_BFIFO_WFIFOCTL_WNUMEVT_SHIFT);
2308 hMcbsp->fifoRegs->WFIFOCTL |=
2309 (CSL_BFIFO_WFIFOCTL_WNUMDMA_1WORDS
2310 << CSL_BFIFO_WFIFOCTL_WNUMDMA_SHIFT);
2312 /* enable the FIFO now by setting the "WENA" bit */
2313 hMcbsp->fifoRegs->WFIFOCTL |=
2314 (CSL_BFIFO_WFIFOCTL_WENA_ENABLED
2315 << CSL_BFIFO_WFIFOCTL_WENA_SHIFT);
2316 }
2317 }
2318 else
2319 {
2320 /* FIFO needs to be disabled */
2321 if (MCBSP_MODE_INPUT == chanHandle->mode)
2322 {
2323 /* disable the FIFO now by resetting the "WENA" bit */
2324 hMcbsp->fifoRegs->RFIFOCTL =
2325 (CSL_BFIFO_RFIFOCTL_RENA_DISABLED
2326 << CSL_BFIFO_RFIFOCTL_RENA_SHIFT);
2327 }
2328 else
2329 {
2330 /* disable the FIFO now by resetting the "WENA" bit */
2331 hMcbsp->fifoRegs->WFIFOCTL =
2332 (CSL_BFIFO_WFIFOCTL_WENA_DISABLED
2333 << CSL_BFIFO_WFIFOCTL_WENA_SHIFT);
2334 }
2335 }
2336 }
2338 /**
2339 * \brief This is going to complete the current request and abort
2340 * all other reqest.
2341 *
2342 * \param chanHandle [IN] Channel handle
2343 *
2344 * \return None
2345 *
2346 * \enter chanHandle is a valid non null pointer
2347 *
2348 * \leave Not implemented
2349 */
2350 void Mcbsp_localCancelAndAbortAllIo(Mcbsp_ChannelObj *chanHandle)
2351 {
2352 chanHandle->submitCount--;
2353 chanHandle->tempIOBuf->status = MCBSP_STATUS_ABORTED;
2355 Mcbsp_localCompleteCurrentIo(chanHandle);
2357 Mcbsp_localAbortReset(chanHandle);
2358 }
2360 #ifndef MCBSP_LOOPJOB_ENABLE
2361 /**
2362 * \brief This function waits for the FIFO to be emptied(if enabled) and the
2363 * TX empty bit to be set so that the TX section could be disabled when
2364 * there is no data present.
2365 *
2366 * \param arg0 [IN] Handle to the TX channel
2367 * \param arg1 [IN] unused
2368 *
2369 * \return None
2370 *
2371 * \enter arg0 is a valid non null pointer
2372 *
2373 * \leave Not implemented
2374 */
2375 void Mcbsp_TxFifo(int32_t arg0, int32_t arg1)
2376 {
2377 Mcbsp_ChannelObj *chanHandle = NULL;
2378 Mcbsp_Object *hInst = NULL;
2379 Mcbsp_Object_Unpadded *instHandle = NULL;
2380 uint32_t timeOut = 0x00;
2381 void* criticalSectionInfo;
2383 chanHandle = (Mcbsp_ChannelObj *)arg0;
2384 hInst = (Mcbsp_Object *)arg1;
2385 instHandle = (Mcbsp_Object_Unpadded *)&(hInst->obj);
2387 /* critical section starts */
2388 criticalSectionInfo = Mcbsp_osalEnterSingleCoreCriticalSection();
2390 /* update the timeout value from the instance handle */
2391 timeOut = instHandle->retryCount;
2393 /* we have come here means that the Mcbsp has got an callback but it *
2394 * did have any more buffer to load Hence here we will wait for the *
2395 * FIFO to become empty (if FIFO is enabled) else wait for the TX to *
2396 * become empty.then we will disable the TX section */
2397 if (TRUE == chanHandle->enableHwFifo)
2398 {
2399 while ((0 != (instHandle->hwInfo.fifoRegs->WFIFOSTS &
2400 CSL_BFIFO_WFIFOSTS_WLVL_MASK))
2401 && (0 != timeOut))
2402 {
2403 /* reduce the timeout count and check if the FIFO is empty */
2404 timeOut--;
2405 }
2406 }
2408 /* reinitialize the retry count */
2409 timeOut = instHandle->retryCount;
2411 while ((CSL_MCBSP_SPCR_XEMPTY_MASK ==
2412 (instHandle->hwInfo.regs->SPCR & CSL_MCBSP_SPCR_XEMPTY_MASK))
2413 && (0 != timeOut))
2414 {
2415 /* reduce the retry count and check if the TX has completed *
2416 * transmitting all the bytes */
2417 timeOut--;
2418 }
2420 /* we need to stop the frame sycn generator now.But also need to check *
2421 * if 1.The frame sycn generator is actually started By TX. *
2422 * 2.The RX is not feeding of the sample rate generator */
2423 if ((TRUE == instHandle->txFsgEnable) &&
2424 ((TRUE != instHandle->rxFsgEnable)
2425 || (TRUE == instHandle->stopSmFsRcv)))
2426 {
2427 /* Now we can disable the frame sync generator */
2428 Mcbsp_localResetCtrl(
2429 (Mcbsp_Object_Unpadded *)&(chanHandle->devHandle->obj),
2430 Mcbsp_SpcrCtrl_FSYNC_DISABLE);
2431 instHandle->fsgEnabled = FALSE;
2432 }
2434 /* Stop the TX section */
2435 Mcbsp_localResetCtrl(
2436 (Mcbsp_Object_Unpadded *)&(chanHandle->devHandle->obj),
2437 Mcbsp_SpcrCtrl_TX_DISABLE);
2439 /* Transmit state machine is stopped */
2440 instHandle->stopSmFsXmt = TRUE;
2442 /* clear the error bits in the EDMA(as this is the last buffer) */
2443 EDMA3_DRV_clearErrorBits(
2444 chanHandle->edmaHandle,
2445 chanHandle->xferChan);
2447 /* complete the IOP now and call the callback to the stream */
2448 chanHandle->tempIOBuf = Mcbsp_osalQueueGet(chanHandle->ptrQFloatList);
2450 /* Decrement the submit count for the IO buffers */
2451 chanHandle->submitCount--;
2453 chanHandle->isTempIOBufValid = TRUE;
2454 chanHandle->tempIOBuf->status = chanHandle->currentError;
2455 Mcbsp_localCompleteCurrentIo(chanHandle);
2457 /* critical section ends */
2458 Mcbsp_osalExitSingleCoreCriticalSection(criticalSectionInfo);
2461 }
2462 #endif /* #ifndef MCBSP_LOOPJOB_ENABLE */
2465 /**
2466 * \brief This function toggles the index of the edma params
2467 *
2468 * \param index [IN] pointer to current index
2469 *
2470 * \return None
2471 *
2472 * \enter index is a valid non null pointer
2473 *
2474 * \leave Not implemented
2475 */
2476 void Mcbsp_localGetNextIndex(uint32_t *index)
2477 {
2478 *index = (((*index) + 1u) & 0x01u);
2479 }
2481 /**
2482 * \brief This function loads the buffers to the actual EDMA paramset.
2483 *
2484 * \param chanHandle [IN] Handle to channel.
2485 * \param ioBuf [IN] pointer to the ioBuf
2486 *
2487 * \return None
2488 *
2489 * \enter Not implemented
2490 *
2491 * \leave Not implemented
2492 */
2493 void Mcbsp_localLoadPktToEdma(Mcbsp_ChannelObj *chanHandle,Mcbsp_IOBuf *ioBuf)
2494 {
2495 #ifndef MCBSP_LOOPJOB_ENABLE
2496 Mcbsp_Object_Unpadded *instHandle = NULL;
2497 #endif
2498 int32_t status = MCBSP_STATUS_COMPLETED;
2500 #ifndef MCBSP_LOOPJOB_ENABLE
2501 instHandle = (Mcbsp_Object_Unpadded *)&(chanHandle->devHandle->obj);
2502 #endif
2504 chanHandle->currentDataSize = (uint16_t)ioBuf->size;
2505 chanHandle->userDataBufferSize = (uint32_t)ioBuf->size;
2507 #ifdef MCBSP_LOOPJOB_ENABLE
2508 if (Mcbsp_MAXLINKCNT == chanHandle->submitCount)
2509 {
2510 #else
2511 /* The second and the third buffer will go the link paramsets */
2512 if (Mcbsp_MAXLINKCNT <= chanHandle->submitCount)
2513 {
2514 #endif
2515 /* Though we have to post to param set directly from here, *
2516 * there will be differene between first such buffer and *
2517 * second buffer. As we have control here we are second buffer *
2518 * and first buffer has not yet returned (or corresponding *
2519 * edma callback has not been called.For second buffer, we *
2520 * will be updating the second param set, which is currently *
2521 * hosting loopjob parameter. Hence increment the index to *
2522 * point second paramset and since we are moving out loopjob *
2523 * from both param sets, the loopjobUpdatedinParamset is reset */
2524 chanHandle->loopjobUpdatedinParamset = FALSE;
2525 Mcbsp_localGetNextIndex(
2526 &chanHandle->nextLinkParamSetToBeUpdated);
2527 }
2529 /* Now update the data buffer to the link params. The paramset to *
2530 * be updated is decidec by the "nextLinkParamSetToBeUpdated" */
2531 if (MCBSP_STATUS_COMPLETED != Mcbsp_localUpdtDtPktToLnkPrms(chanHandle,ioBuf))
2532 {
2533 status = MCBSP_ERR_BADIO;
2534 }
2536 if ((1u == chanHandle->submitCount) && (MCBSP_STATUS_COMPLETED == status))
2537 {
2538 #ifdef MCBSP_LOOPJOB_ENABLE
2539 /* if at all this is the very first buffer, then one param set *
2540 * has loop job loaded , self linked and active with the main *
2541 * xfer channel param. other param set is ready loaded (just *
2542 * now)and has link param set as the one having loopjob (this *
2543 * is to ensure that if at all we are not getting any more *
2544 * buffers loopjob be will taken over). Now we have to link *
2545 * the floating / newly loaded param set to xfer channel. */
2546 if (MCBSP_STATUS_COMPLETED != EDMA3_DRV_linkChannel(
2547 chanHandle->edmaHandle,
2548 chanHandle->xferChan,
2549 chanHandle->pramTbl[chanHandle->nextLinkParamSetToBeUpdated]))
2550 {
2551 status = MCBSP_ERR_BADIO;
2552 }
2553 #else
2554 /* configure the FIFO for the specific channel */
2555 if (TRUE == chanHandle->enableHwFifo)
2556 {
2557 /* Disable and enable the FIFO so that the events are *
2558 * generated to the Mcbsp for the first time */
2559 mcbspConfigureFifo(&instHandle->hwInfo,chanHandle,FALSE);
2560 mcbspConfigureFifo(&instHandle->hwInfo,chanHandle,TRUE);
2561 }
2563 /* enable the EDMA transfer for the channel so that it is *
2564 * ready to transfer the data as soon as the state machine is *
2565 * enabled */
2566 EDMA3_DRV_enableTransfer(
2567 chanHandle->edmaHandle,
2568 chanHandle->xferChan,
2569 EDMA3_DRV_TRIG_MODE_EVENT);
2571 /* Start the McBSP hardware */
2572 if (MCBSP_MODE_INPUT == chanHandle->mode)
2573 {
2574 instHandle->stopSmFsRcv = FALSE;
2575 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_RX_ENABLE);
2576 }
2577 else
2578 {
2579 instHandle->stopSmFsXmt = FALSE;
2580 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_TX_ENABLE);
2581 }
2583 if (((MCBSP_MODE_INPUT == chanHandle->mode) &&
2584 (TRUE == instHandle->rxFsgEnable)) ||
2585 ((MCBSP_MODE_OUTPUT == chanHandle->mode) &&
2586 (TRUE == instHandle->txFsgEnable)))
2587 {
2588 /* enable the sample rate generator */
2589 Mcbsp_localResetCtrl(
2590 instHandle,
2591 Mcbsp_SpcrCtrl_FSYNC_ENABLE);
2592 }
2593 #endif /* MCBSP_LOOPJOB_ENABLE */
2594 }
2595 }
2597 /**
2598 * \brief Function to modify the sample rate generator configuration
2599 *
2600 * \param chanHandle [IN] Handle to the channel
2601 * \param arg [IN] pointer to the srg config setup
2602 *
2603 * \return None
2604 */
2605 int32_t Mcbsp_localModifySampleRate(Mcbsp_ChannelObj *chanHandle,void* arg)
2606 {
2607 Mcbsp_Object_Unpadded *instHandle = NULL;
2608 Mcbsp_ClkSetup *clkConfig = NULL;
2609 int32_t status = MCBSP_STATUS_COMPLETED;
2611 if ((NULL == arg) || (NULL == chanHandle))
2612 {
2613 return MCBSP_ERR_BADARGS;
2614 }
2616 instHandle = &(chanHandle->devHandle->obj);
2617 if (NULL == instHandle)
2618 {
2619 return MCBSP_ERR_BADARGS;
2620 }
2622 clkConfig = (Mcbsp_ClkSetup *)arg;
2624 /* check if the Frame sync clock is generated by the module */
2625 if (TRUE == instHandle->srgConfigured)
2626 {
2627 /* Configure the McBSP with user supplied parameters */
2628 chanHandle->clkSetup = *(clkConfig);
2629 instHandle->srgConfigured = FALSE;
2631 /* stop the sample rate generator */
2632 if (TRUE == instHandle->srgEnabled)
2633 {
2634 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_SRG_DISABLE);
2636 status = Mcbsp_localConfigureSrgr(instHandle,chanHandle);
2638 if (MCBSP_STATUS_COMPLETED == status)
2639 {
2640 /* enable the sample rate generator */
2641 Mcbsp_localResetCtrl(
2642 instHandle,
2643 Mcbsp_SpcrCtrl_SRG_ENABLE);
2645 /* wait for the 2CLKG clock cycles */
2646 Mcbsp_osalWaitNBitClocks(2u);
2647 }
2649 /* clear the XSYNCERR (to be done only if TX is used) */
2650 if (MCBSP_MODE_OUTPUT == chanHandle->mode)
2651 {
2652 /* Enable the TX section */
2653 Mcbsp_localResetCtrl(
2654 instHandle,
2655 Mcbsp_SpcrCtrl_TX_ENABLE);
2657 /* wait for 2 CLKR or CLX cycles */
2658 Mcbsp_osalWaitNBitClocks(2u);
2660 /* Disable the TX section to clear any XYNCERR */
2661 Mcbsp_localResetCtrl(
2662 instHandle,
2663 Mcbsp_SpcrCtrl_TX_DISABLE);
2664 }
2665 }
2666 }
2667 else
2668 {
2669 status = MCBSP_ERR_BADMODE;
2671 if (MCBSP_MODE_INPUT == chanHandle->mode)
2672 {
2673 if (TRUE != instHandle->rxSrgEnable)
2674 {
2675 /* Since this mode does not use the sample rate generator, so
2676 * there is no point in changing the sample rate. So return
2677 * with success*/
2678 status = MCBSP_STATUS_COMPLETED;
2679 }
2680 }
2681 else
2682 {
2683 if (TRUE != instHandle->txSrgEnable)
2684 {
2685 /* Since this mode does not use the sample rate generator, so
2686 * there is no point in changing the sample rate. So return
2687 * with success*/
2688 status = MCBSP_STATUS_COMPLETED;
2689 }
2690 }
2691 }
2692 return (status);
2693 }
2695 /* ========================================================================== */
2696 /* END OF FILE */
2697 /* ========================================================================== */