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 - 2018 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 #ifdef __cplusplus
65 #pragma DATA_SECTION (".mcbsp")
66 #pragma DATA_ALIGN (MCBSP_MAX_CACHE_ALIGN)
67 #else
68 #pragma DATA_SECTION (Mcbsp_Instances, ".mcbsp");
69 #pragma DATA_ALIGN (Mcbsp_Instances, MCBSP_MAX_CACHE_ALIGN)
70 #endif
72 Mcbsp_Object Mcbsp_Instances[CSL_MCBSP_PER_CNT];
74 /**
75 * \brief Mcbsp structure containing the information specific to an instance.
76 */
77 /* Shared Memory Variable to ensure synchronizing SRIO initialization
78 * with all the other cores. */
79 /* Created an array to pad the cache line with MCBSP_MAX_CACHE_ALIGN size */
80 #ifdef __cplusplus
81 #pragma DATA_SECTION (".mcbsp")
82 #pragma DATA_ALIGN (MCBSP_MAX_CACHE_ALIGN)
83 #else
84 #pragma DATA_SECTION (Mcbsp_deviceInstInfo, ".mcbsp");
85 #pragma DATA_ALIGN (Mcbsp_deviceInstInfo, MCBSP_MAX_CACHE_ALIGN)
86 #endif
87 Mcbsp_HwInfo Mcbsp_deviceInstInfo[CSL_MCBSP_PER_CNT];
89 /**
90 * \brief Mute buffer per instance
91 *
92 * \note Buffer used when the mcbsp is placed in mute.
93 */
94 #ifdef __cplusplus
95 #pragma DATA_SECTION (".mcbsp")
96 #pragma DATA_ALIGN (MCBSP_MAX_CACHE_ALIGN)
97 #else
98 #pragma DATA_SECTION (Mcbsp_muteBuf, ".mcbsp");
99 #pragma DATA_ALIGN (Mcbsp_muteBuf, MCBSP_MAX_CACHE_ALIGN)
100 #endif
101 Mcbsp_TempBuffer Mcbsp_muteBuf[CSL_MCBSP_PER_CNT];
103 #ifdef MCBSP_LOOPJOB_ENABLE
104 /**
105 * \brief Destination loop buffer per instance
106 *
107 * \note Buffer used during the loop job mode for the Transmit section
108 */
109 #ifdef __cplusplus
110 #pragma DATA_SECTION (".mcbsp")
111 #pragma DATA_ALIGN (MCBSP_MAX_CACHE_ALIGN)
112 #else
113 #pragma DATA_SECTION (Mcbsp_loopDstBuf, ".mcbsp");
114 #pragma DATA_ALIGN (Mcbsp_loopDstBuf, MCBSP_MAX_CACHE_ALIGN)
115 #endif
116 Mcbsp_TempBuffer Mcbsp_loopDstBuf[CSL_MCBSP_PER_CNT];
118 /**
119 * \brief Receive loop buffer per instance
120 *
121 * \note Buffer used during the loop job mode for the Receive section
122 */
123 #ifdef __cplusplus
124 #pragma DATA_SECTION (".mcbsp")
125 #pragma DATA_ALIGN (MCBSP_MAX_CACHE_ALIGN)
126 #else
127 #pragma DATA_SECTION (Mcbsp_loopSrcBuf, ".mcbsp");
128 #pragma DATA_ALIGN (Mcbsp_loopSrcBuf, MCBSP_MAX_CACHE_ALIGN)
129 #endif
130 Mcbsp_TempBuffer Mcbsp_loopSrcBuf[CSL_MCBSP_PER_CNT];
131 #endif /* MCBSP_LOOPJOB_ENABLE */
133 /*============================================================================*/
134 /* LOCAL FUNCTION PROTOTYPES */
135 /*============================================================================*/
136 int32_t mcbspSubmitReq(Mcbsp_Object_Unpadded *instHandle,
137 Mcbsp_ChannelObj *chanHandle,
138 Mcbsp_IOBuf *ioBuf);
139 void mcbspConfigureFifo(Mcbsp_HwInfo_Unpadded *hMcbsp,
140 Mcbsp_ChannelObj *chanHandle,
141 Bool enableHwFifo);
143 #ifndef MCBSP_LOOPJOB_ENABLE
144 extern uint32_t Mcbsp_edmaChanNum;
145 #endif /* MCBSP_LOOPJOB_ENABLE */
148 /* ========================================================================== */
149 /* MODULE PUBLIC FUNCTIONS */
150 /* ========================================================================== */
152 /**
153 * @b Description
154 * @n
155 * This is the MCBSP Driver Initialization API which needs to be
156 * invoked by the users to initialize the MCBSP peripheral. This call
157 * is *mandatory* and should be called before calling any of the
158 * other driver API's.
159 *
160 * This should only be called *ONCE* for the device.
161 *
162 * @retval
163 * MCBSP_STATUS_COMPLETED if successful
164 * @retval
165 * MCBSP_ERR_BADARGS if not successful
166 * MCBSP_ERR_ALLOC
167 */
168 int32_t mcbspInit (void)
169 {
170 int32_t devId = 0;
171 void *criticalSectionInfo;
173 /* Begin Critical Section before accessing shared resources. */
174 criticalSectionInfo = Mcbsp_osalEnterMultipleCoreCriticalSection ();
176 /* Invalidate the Cache Contents */
177 Mcbsp_osalBeginMemAccess ((void *)Mcbsp_Instances, sizeof(Mcbsp_Instances));
179 /* initialize the information for all the device instances */
180 for (devId = 0; devId < CSL_MCBSP_PER_CNT; devId++)
181 {
182 /* initialise the instance object */
183 memset((void *)&Mcbsp_Instances[devId], 0, sizeof(Mcbsp_Object));
184 Mcbsp_Instances[devId].obj.inUse = FALSE;
185 }
187 /* Writeback Global Object */
188 Mcbsp_osalEndMemAccess ((void *)Mcbsp_Instances, sizeof(Mcbsp_Instances));
190 /* End Critical Section */
191 Mcbsp_osalExitMultipleCoreCriticalSection (criticalSectionInfo);
193 return MCBSP_STATUS_COMPLETED;
194 }
196 /**
197 * \brief Allocates and configures the McBSP instance specified by devid.
198 *
199 * Acquires the Handle of the McBSP and configure the McBSP by
200 * default for the following things.
201 * o Data output for audio playback
202 * o Data input for audio recording
203 * o Configure the McBSP in DSP/TDM data format mode of the audio
204 * codec.
205 * o Configure the McBSP to receive the Frame Sync and bit clock
206 * externally for both receiver and transmitter.
207 * o McBSP can also be configured to generate Frame Sync and
208 * bit clock internally by enabling sample rate generator and
209 * frame sync generator blocks respectively depending on the
210 * fields set in the device parameter structure which shall
211 * be passed to mcbspBindDev() function as one of the parameter.
212 *
213 * \param devp [OUT] pointer to hold allocated instance object ptr
214 * \param devid [IN] instance number of the mcbsp
215 * \param devParams [IN] user supplied data params.
216 *
217 * \return MCBSP_STATUS_COMPLETED if successful
218 *
219 * MCBSP_ERR_BADARGS if not successful
220 * MCBSP_ERR_ALLOC
221 *
222 * \enter devp should be non NULL and valid pointer,
223 * devId should be < CSL_MCBSP_PER_CNT
224 * devParams should be non NULL and valid pointer,
225 *
226 * \leave Not implemented
227 */
228 int32_t mcbspBindDev(void* *devp, int32_t devid, void* devParams)
229 {
230 Mcbsp_Object_Unpadded *instHandle = NULL;
231 Mcbsp_Params *params = NULL;
232 uint32_t ctrlMask = 0x00;
233 uint32_t count = 0x00;
234 int32_t status = MCBSP_STATUS_COMPLETED;
235 void *criticalSectionInfo;
237 /* Begin Critical Section before accessing shared resources. */
238 criticalSectionInfo = Mcbsp_osalEnterMultipleCoreCriticalSection ();
240 /* Invalidate the Cache Contents */
241 Mcbsp_osalBeginMemAccess ((void *)Mcbsp_Instances, sizeof(Mcbsp_Instances));
242 Mcbsp_osalBeginMemAccess ((void *)Mcbsp_deviceInstInfo, sizeof(Mcbsp_deviceInstInfo));
244 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
245 if ((NULL == devp) || (NULL == devParams) || (devid >= CSL_MCBSP_PER_CNT))
246 {
247 status = MCBSP_ERR_BADARGS;
248 }
250 if (MCBSP_STATUS_COMPLETED == status)
251 {
252 if (TRUE == Mcbsp_Instances[devid].obj.inUse)
253 {
254 status = MCBSP_ERR_INUSE;
255 }
256 else
257 {
258 #endif /* MCBSP_DISABLE_INPUT_PARAM_CHECK */
259 /* copy the pointer to the instance object */
260 instHandle = &(Mcbsp_Instances[devid].obj);
262 /* set the module state as in use */
263 Mcbsp_Instances[devid].obj.inUse = TRUE;
265 params = (Mcbsp_Params *)devParams;
267 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
268 /* Only DMA mode of the operation is supported for Mcbsp mode */
269 if ((Mcbsp_DevMode_McBSP == params->mode) &&
270 (Mcbsp_OpMode_DMAINTERRUPT != params->opMode))
271 {
272 status = MCBSP_ERR_BADMODE;
273 }
274 else
275 {
276 if (NULL == params->srgSetup)
277 {
278 status = MCBSP_ERR_BADMODE;
279 }
280 }
281 }
282 }
283 #endif /* MCBSP_DISABLE_INPUT_PARAM_CHECK */
285 if (MCBSP_STATUS_COMPLETED == status)
286 {
287 /* update the instance of the device being created */
288 instHandle->instNum = devid;
290 /* update the user supplied params to the instance object */
291 instHandle->mode = params->mode;
292 instHandle->opMode = params->opMode;
293 instHandle->enablecache = params->enablecache;
295 /* copy the SOC related information in to the instance object */
296 instHandle->hwInfo = Mcbsp_deviceInstInfo[devid].obj;
298 /* stop the state machine of RX and TX */
299 instHandle->stopSmFsXmt = TRUE;
300 instHandle->stopSmFsRcv = TRUE;
302 instHandle->retryCount = Mcbsp_POLLED_RETRYCOUNT;
304 /* configure the default values for the transmit channel */
305 instHandle->xmtObj.mode = (uint16_t)MCBSP_MODE_OUTPUT;
306 instHandle->xmtObj.devHandle = NULL;
307 instHandle->xmtObj.cbFxn = NULL;
308 instHandle->xmtObj.cbArg = NULL;
309 instHandle->xmtObj.edmaHandle = NULL;
310 instHandle->xmtObj.edmaEventQue = Mcbsp_TXEVENTQUE;
311 instHandle->xmtObj.edmaCallback = NULL;
312 instHandle->xmtObj.xferChan = 0x00;
313 instHandle->xmtObj.tcc = 0x00;
314 instHandle->xmtObj.tempIOBuf = NULL;
315 instHandle->xmtObj.submitCount = 0x00;
316 instHandle->xmtObj.dataFormat = Mcbsp_BufferFormat_1SLOT;
317 instHandle->xmtObj.bMuteON = FALSE;
318 instHandle->xmtObj.paused = FALSE;
319 instHandle->xmtObj.flush = FALSE;
320 instHandle->xmtObj.isTempIOBufValid = FALSE;
321 instHandle->xmtObj.enableHwFifo = TRUE;
322 instHandle->xmtObj.gblErrCbk = NULL;
323 instHandle->xmtObj.userDataBufferSize = 0x00;
324 instHandle->xmtObj.loopJobBuffer = NULL;
325 instHandle->xmtObj.loopJobLength = 0x00;
326 instHandle->xmtObj.nextLinkParamSetToBeUpdated = 0x00;
327 instHandle->xmtObj.loopjobUpdatedinParamset = FALSE;
328 instHandle->xmtObj.roundedWordWidth = 0x00;
330 instHandle->rcvObj.mode = (uint16_t)MCBSP_MODE_INPUT;
331 instHandle->rcvObj.devHandle = NULL;
332 instHandle->rcvObj.cbFxn = NULL;
333 instHandle->rcvObj.cbArg = NULL;
334 instHandle->rcvObj.edmaHandle = NULL;
335 instHandle->rcvObj.edmaEventQue = Mcbsp_RXEVENTQUE;
336 instHandle->rcvObj.edmaCallback = NULL;
337 instHandle->rcvObj.xferChan = 0x00;
338 instHandle->rcvObj.tcc = 0x00;
339 instHandle->rcvObj.tempIOBuf = NULL;
340 instHandle->rcvObj.submitCount = 0x00;
341 instHandle->rcvObj.dataFormat = Mcbsp_BufferFormat_1SLOT;
342 instHandle->rcvObj.bMuteON = FALSE;
343 instHandle->rcvObj.paused = FALSE;
344 instHandle->rcvObj.flush = FALSE;
345 instHandle->rcvObj.isTempIOBufValid = FALSE;
346 instHandle->rcvObj.enableHwFifo = TRUE;
347 instHandle->rcvObj.gblErrCbk = NULL;
348 instHandle->rcvObj.userDataBufferSize = 0x00;
349 instHandle->rcvObj.loopJobBuffer = NULL;
350 instHandle->rcvObj.loopJobLength = 0x00;
351 instHandle->rcvObj.nextLinkParamSetToBeUpdated = 0x00;
352 instHandle->rcvObj.loopjobUpdatedinParamset = FALSE;
353 instHandle->rcvObj.roundedWordWidth = 0x00;
355 #ifdef MCBSP_LOOPJOB_ENABLE
356 /* driver is compiled in loop Job mode */
357 instHandle->loopJobMode = TRUE;
358 #else
359 instHandle->loopJobMode = FALSE;
360 #endif
362 for (count = 0; count < Mcbsp_MAXLINKCNT; count++)
363 {
364 instHandle->xmtObj.pramTbl[count] = 0x00;
365 instHandle->rcvObj.pramTbl[count] = 0x00;
366 instHandle->xmtObj.pramTblAddr[count] = 0x00;
367 instHandle->rcvObj.pramTblAddr[count] = 0x00;
368 }
370 /* set the status of the channel to closed */
371 instHandle->xmtObj.chanState = Mcbsp_DriverState_CLOSED;
372 instHandle->rcvObj.chanState = Mcbsp_DriverState_CLOSED;
374 /* Pending and Floating queues for TX and RX channels */
375 instHandle->xmtObj.ptrQPendList = params->txQPendingList;
376 instHandle->xmtObj.ptrQFloatList = params->txQFloatingList;
377 instHandle->rcvObj.ptrQPendList = params->rxQPendingList;
378 instHandle->rcvObj.ptrQFloatList = params->rxQFloatingList;
380 if (MCBSP_STATUS_COMPLETED == status)
381 {
382 /* Reset the McBSP Transmitter, receiver and SRGR before *
383 * configuration */
384 ctrlMask = ((Mcbsp_SpcrCtrl_TX_DISABLE |
385 Mcbsp_SpcrCtrl_RX_DISABLE) |
386 (Mcbsp_SpcrCtrl_SRG_DISABLE |
387 Mcbsp_SpcrCtrl_FSYNC_DISABLE));
389 status = Mcbsp_localResetCtrl(instHandle,ctrlMask);
390 if (MCBSP_STATUS_COMPLETED != status)
391 {
392 /* Writeback Global Object */
393 Mcbsp_osalEndMemAccess ((void *)Mcbsp_Instances, sizeof(Mcbsp_Instances));
394 Mcbsp_osalEndMemAccess ((void *)Mcbsp_deviceInstInfo, sizeof(Mcbsp_deviceInstInfo));
396 /* End Critical Section */
397 Mcbsp_osalExitMultipleCoreCriticalSection (criticalSectionInfo);
399 return status;
400 }
402 /* copy the configuration for the sample rate generator and config*
403 * the emulation mode and DLB mode settings */
405 /* Configure the McBSP with user supplied parameters */
406 instHandle->srgrConfig = *(params->srgSetup);
408 /* reset the Mcbsp */
409 instHandle->hwInfo.regs->SPCR = 0x00u;
411 /* set the DLB mode settings */
412 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_DLB_MASK);
413 instHandle->hwInfo.regs->SPCR |=
414 (params->dlbMode << CSL_MCBSP_SPCR_DLB_SHIFT);
416 /* set the clock stop mode settings */
417 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_CLKSTP_MASK);
419 /* set the emulation state */
420 instHandle->hwInfo.regs->SPCR &= (~(CSL_MCBSP_SPCR_SOFT_MASK |
421 CSL_MCBSP_SPCR_FREE_MASK));
422 instHandle->hwInfo.regs->SPCR |=
423 (params->emulationMode << CSL_MCBSP_SPCR_SOFT_SHIFT);
424 }
426 if (MCBSP_STATUS_COMPLETED != status)
427 {
428 *devp = NULL;
429 }
430 else
431 {
432 *devp = &(Mcbsp_Instances[devid]);
434 /* set the status of the driver to created */
435 instHandle->devState = Mcbsp_DriverState_CREATED;
436 }
437 }
439 /* Writeback Global Object */
440 Mcbsp_osalEndMemAccess ((void *)Mcbsp_Instances, sizeof(Mcbsp_Instances));
441 Mcbsp_osalEndMemAccess ((void *)Mcbsp_deviceInstInfo, sizeof(Mcbsp_deviceInstInfo));
443 /* End Critical Section */
444 Mcbsp_osalExitMultipleCoreCriticalSection (criticalSectionInfo);
446 return status;
447 }
449 /**
450 * \brief Creates a communication channel in specified mode to communicate
451 * data between the application and the McBSP device instance. This
452 * function sets the required hardware configurations for the data
453 * transactions. It returns configured channel handle to application
454 * which will be used in all further transactions with the channel.
455 *
456 * Pre-requisites:
457 * 1. Valid chanParams structure
458 * This takes much information pertaining to mcbsp channel
459 * configuration such as how many slots are used for this
460 * channel what are their communication parameters, clock settings etc.
461 * 2. Valid device pointer
462 *
463 * \param chanp [IN] Channel Handler
464 * \param devp [IN] Device pointer
465 * \param mode [IN] channel mode -> input or output
466 * \param chanParams [IN] channel parameters from user
467 * \param cbFxn [IN] callback function pointer
468 * \param cbArg [IN] callback function Arguments
469 *
470 * \return MCBSP_STATUS_COMPLETED if successful
471 * MCBSP_ERR_BADIO if not successful
472 * MCBSP_ERR_ALLOC "
473 * MCBSP_ERR_BADARGS if passed invalid chanParams structure
474 */
475 int32_t mcbspCreateChan(void* *chanp,
476 void* devp,
477 int32_t mode,
478 void* chanParams,
479 Mcbsp_CallbackFxn cbFxn,
480 void* cbArg)
481 {
482 Mcbsp_Object *hInst = NULL;
483 Mcbsp_Object_Unpadded *instHandle = NULL;
484 Mcbsp_ChannelObj *chanHandle = NULL;
485 Mcbsp_ChanParams *chanparam = NULL;
486 void* criticalSectionInfo;
487 int32_t status = MCBSP_STATUS_COMPLETED;
489 /* Begin parameter checking */
490 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
491 if (((NULL == chanParams)
492 || (NULL == cbFxn)
493 || (NULL == cbArg)
494 || (NULL == devp))
495 || ((MCBSP_MODE_INPUT != mode) && (MCBSP_MODE_OUTPUT != mode)))
496 {
497 return MCBSP_ERR_BADARGS;
498 }
499 else
500 {
501 #endif
502 chanparam = (Mcbsp_ChanParams *)chanParams;
503 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
504 if (NULL == chanparam->edmaHandle)
505 {
506 return MCBSP_ERR_BADARGS;
507 }
508 }
509 #endif /* MCBSP_DISABLE_INPUT_PARAM_CHECK */
510 /* End parameter checking */
512 /* Begin Critical Section before accessing shared resources. */
513 criticalSectionInfo = Mcbsp_osalEnterMultipleCoreCriticalSection ();
515 /* Invalidate the Cache Contents */
516 Mcbsp_osalBeginMemAccess ((void *)devp, sizeof(Mcbsp_Object));
518 if (MCBSP_STATUS_COMPLETED == status)
519 {
520 hInst = (Mcbsp_Object *)devp;
521 instHandle = (Mcbsp_Object_Unpadded *)&(hInst->obj);
523 /* get the pointer to the required channel structure */
524 if (MCBSP_MODE_INPUT == mode)
525 {
526 chanHandle = &instHandle->rcvObj;
527 }
528 else
529 {
530 chanHandle = &instHandle->xmtObj;
531 }
533 /* we will check if the current requested channel is availablehere*
534 * protect the channel status so that multiple threads requesting *
535 * same channel do not cause a corruption */
536 if (Mcbsp_DriverState_CLOSED == chanHandle->chanState)
537 {
538 chanHandle->chanState = Mcbsp_DriverState_OPENED;
539 }
540 else
541 {
542 /* Requested channel is already taken hence we will set status*
543 * as invalid */
544 status = MCBSP_ERR_BADMODE;
545 }
547 if (MCBSP_STATUS_COMPLETED == status)
548 {
549 chanHandle->mode = (uint16_t)mode;
550 chanHandle->devHandle = hInst;
552 /* Assign the respective callback function */
553 chanHandle->cbFxn = cbFxn;
554 chanHandle->cbArg = cbArg;
556 /* This is used in EDMA mode to populate paramsets in PINGPONG */
557 chanHandle->nextLinkParamSetToBeUpdated = 0;
559 /* Initialize Mute parameter */
560 chanHandle->bMuteON = FALSE;
562 chanHandle->isTempIOBufValid = FALSE;
564 /* Counter that counts outstanding requests of this channel */
565 chanHandle->submitCount = 0;
567 /* Global error callback registered to channel */
568 chanHandle->gblErrCbk = chanparam->gblCbk;
570 /* copy the edma event queue details */
571 chanHandle->edmaEventQue = chanparam->edmaEventQue;
573 /* store the EDMA3 module handle */
574 chanHandle->edmaHandle = chanparam->edmaHandle;
576 /* configure the FIFO */
577 chanHandle->enableHwFifo = chanparam->enableHwFifo;
579 /* copy the user settings in to the channel object */
580 chanHandle->chanConfig = *(chanparam->chanConfig);
581 chanHandle->clkSetup = *(chanparam->clkSetup);
582 chanHandle->numEnabledChannels = chanparam->numEnabledChannels;
583 chanHandle->dataFormat = chanparam->dataFormat;
584 }
586 if (MCBSP_STATUS_COMPLETED == status)
587 {
588 /* configure the actual wordwidth to be used */
589 switch (chanparam->wordWidth)
590 {
591 case Mcbsp_WordLength_8:
592 chanHandle->roundedWordWidth = 1u;
593 break;
594 case Mcbsp_WordLength_12:
595 case Mcbsp_WordLength_16:
596 chanHandle->roundedWordWidth = 2u;
597 break;
598 case Mcbsp_WordLength_20:
599 case Mcbsp_WordLength_24:
600 chanHandle->roundedWordWidth = 3u;
601 break;
602 case Mcbsp_WordLength_32:
603 default:
604 chanHandle->roundedWordWidth = 4u;
605 break;
606 }
608 #ifdef MCBSP_LOOPJOB_ENABLE
609 /* Configure the loop job for the user specified buffer if given */
610 if (NULL == chanparam->userLoopJobBuffer)
611 {
612 if (MCBSP_MODE_INPUT == chanHandle->mode)
613 {
614 chanHandle->loopJobBuffer =
615 Mcbsp_loopDstBuf[instHandle->instNum].scratchBuffer;
616 }
617 else
618 {
619 chanHandle->loopJobBuffer =
620 Mcbsp_loopSrcBuf[instHandle->instNum].scratchBuffer;
621 }
622 chanHandle->loopJobLength = chanHandle->roundedWordWidth;
623 }
624 else
625 {
626 /* Apps has preference on the loopjob buffer & lets use it */
627 chanHandle->loopJobBuffer = chanparam->userLoopJobBuffer;
628 chanHandle->userLoopJobLength = chanparam->userLoopJobLength;
630 /* user loopJob is being used */
631 chanHandle->userLoopJob = TRUE;
632 if (chanHandle->roundedWordWidth >
633 chanparam->userLoopJobLength)
634 {
635 /* not enough loopjob buffer has been provided we *
636 * should have at least loopbuffer for 1 sync event */
637 status = MCBSP_ERR_BADARGS;
638 }
639 }
640 #endif
641 }
643 if ((Mcbsp_DevMode_McBSP == instHandle->mode) && (MCBSP_STATUS_COMPLETED == status))
644 {
645 if (MCBSP_MODE_INPUT == chanHandle->mode)
646 {
647 /* Assign the Channel ID and TCC */
648 chanHandle->xferChan = instHandle->hwInfo.edmaRxEventNum;
649 chanHandle->tcc = instHandle->hwInfo.edmaRxEventNum;
650 chanHandle->edmaCallback =
651 (EDMA3_RM_TccCallback)&Mcbsp_localEdmaCallback;
652 }
653 else
654 {
655 /* Assign the Channel ID and TCC */
656 chanHandle->xferChan = instHandle->hwInfo.edmaTxEventNum;
657 chanHandle->tcc = instHandle->hwInfo.edmaTxEventNum;
658 chanHandle->edmaCallback =
659 (EDMA3_RM_TccCallback)&Mcbsp_localEdmaCallback;
660 }
662 if (MCBSP_STATUS_COMPLETED == status)
663 {
664 mcbspConfigureFifo(&(instHandle->hwInfo),
665 chanHandle,
666 chanHandle->enableHwFifo);
667 }
669 if (MCBSP_MODE_INPUT == chanHandle->mode)
670 {
671 /* configure the RX section */
672 status = Mcbsp_localConfigureRcvChannel(instHandle,chanparam);
673 }
674 else
675 {
676 /* configure the TX section */
677 status = Mcbsp_localConfigureXmtChannel(instHandle,chanparam);
678 }
680 if (MCBSP_STATUS_COMPLETED == status)
681 {
682 /* configure the sample rate generator */
683 status = Mcbsp_localConfigureSrgr(instHandle,chanHandle);
684 }
686 if (MCBSP_STATUS_COMPLETED == status)
687 {
688 /* enable the internal sample rate generator if required */
689 if (((MCBSP_MODE_INPUT == chanHandle->mode) &&
690 (TRUE == instHandle->rxSrgEnable)) ||
691 ((MCBSP_MODE_OUTPUT == chanHandle->mode) &&
692 (TRUE == instHandle->txSrgEnable)))
693 {
694 /* enable the sample rate generator */
695 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_SRG_ENABLE);
696 instHandle->srgEnabled = TRUE;
698 /* wait for the 2CLKG clock cycles */
699 Mcbsp_osalWaitNBitClocks(2u);
700 }
702 /* clear the XSYNCERR (to be done only if TX is used) */
703 if (MCBSP_MODE_OUTPUT == chanHandle->mode)
704 {
705 /* Enable the TX section */
706 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_TX_ENABLE);
708 /* wait for 2 CLKR or CLX cycles */
709 Mcbsp_osalWaitNBitClocks(2u);
711 /* Disable the TX section to clear any XYNCERR */
712 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_TX_DISABLE);
713 }
715 /* complete the EDMA setup for the driver */
716 status = Mcbsp_localSetupEdmaDuringOpen(chanHandle);
717 }
719 #ifdef MCBSP_LOOPJOB_ENABLE
720 if (MCBSP_STATUS_COMPLETED == status)
721 {
722 /* configure the FIFO for the specific channel */
723 if (TRUE == chanHandle->enableHwFifo)
724 {
725 /* Disable and enable the FIFO so that the events are *
726 * generated to the Mcbsp for the first time */
727 mcbspConfigureFifo(&instHandle->hwInfo,chanHandle,FALSE);
728 mcbspConfigureFifo(&instHandle->hwInfo,chanHandle,TRUE);
729 }
731 /* enable the EDMA transfer for the channel so that it is *
732 * ready to transfer the data as soon as the state machine is *
733 * enabled */
734 EDMA3_DRV_enableTransfer(
735 chanHandle->edmaHandle,
736 chanHandle->xferChan,
737 EDMA3_DRV_TRIG_MODE_EVENT);
739 /* Start the McBSP hardware */
740 if (MCBSP_MODE_INPUT == chanHandle->mode)
741 {
742 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_RX_ENABLE);
743 }
744 else
745 {
746 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_TX_ENABLE);
747 }
749 if (MCBSP_MODE_INPUT == chanHandle->mode)
750 {
751 if (TRUE == instHandle->rxFsgEnable)
752 {
753 /* enable the sample rate generator */
754 Mcbsp_localResetCtrl(
755 instHandle,
756 Mcbsp_SpcrCtrl_FSYNC_ENABLE);
757 }
758 }
759 else
760 {
761 if (TRUE == instHandle->txFsgEnable)
762 {
763 /* enable the sample rate generator */
764 Mcbsp_localResetCtrl(
765 instHandle,
766 Mcbsp_SpcrCtrl_FSYNC_ENABLE);
767 }
768 }
770 /* State machine stop status */
771 if (MCBSP_MODE_INPUT == chanHandle->mode)
772 {
773 instHandle->stopSmFsRcv = FALSE;
774 }
775 else
776 {
777 instHandle->stopSmFsXmt = FALSE;
778 }
779 }
780 #endif
781 }
782 }
784 if (MCBSP_STATUS_COMPLETED != status )
785 {
786 if (NULL != chanHandle)
787 {
788 /* set the status of the channel to closed */
789 chanHandle->mode = (uint16_t)Mcbsp_DriverState_CLOSED;
790 }
792 /* channel opening for transaction has failed */
793 chanHandle = NULL;
794 }
795 else
796 {
797 *chanp = chanHandle;
798 }
800 /* Writeback Global Object */
801 Mcbsp_osalEndMemAccess ((void *)devp, sizeof(Mcbsp_Object));
803 /* End Critical Section */
804 Mcbsp_osalExitMultipleCoreCriticalSection (criticalSectionInfo);
806 return status;
807 }
809 /**
810 * \brief frees a channel and all it's associated resources.
811 *
812 * Frees the EDMA resources including EDMA master channel and link
813 * PaRAM entries held by the channel.it also unregisters all the
814 * interrupt handlers.
815 *
816 * \param chanp [IN] Handle to the channel
817 *
818 * \return MCBSP_STATUS_COMPLETED if successful
819 * MCBSP_STATUS_ABORTED if not successful
820 *
821 * \enter chanp should be non NULL and valid pointer,
822 *
823 * \leave Not implemented
824 */
825 int32_t mcbspDeleteChan(void* chanp)
826 {
827 Mcbsp_Object_Unpadded *instHandle = NULL;
828 Mcbsp_ChannelObj *chanHandle = NULL;
829 Uint8 linkCnt = 0;
830 uint32_t timeOut = 0x00;
831 int32_t status = MCBSP_STATUS_COMPLETED;
832 void *criticalSectionInfo;
834 /* Begin Critical Section before accessing shared resources. */
835 criticalSectionInfo = Mcbsp_osalEnterMultipleCoreCriticalSection ();
837 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
838 if (NULL == chanp)
839 {
840 status = MCBSP_ERR_BADARGS;
841 }
842 else
843 {
844 #endif /* MCBSP_DISABLE_INPUT_PARAM_CHECK */
845 chanHandle = (Mcbsp_ChannelObj *)chanp;
847 /* Invalidate the Cache Contents */
848 Mcbsp_osalBeginMemAccess ((void *)chanHandle->devHandle, sizeof(Mcbsp_Object));
850 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
851 if (Mcbsp_DriverState_OPENED != chanHandle->chanState)
852 {
853 status = MCBSP_ERR_BADMODE;
854 }
855 else
856 {
857 if (NULL == chanHandle->devHandle)
858 {
859 status = MCBSP_ERR_BADARGS;
860 }
861 else
862 {
863 #endif
864 instHandle = (Mcbsp_Object_Unpadded *)&(chanHandle->devHandle->obj);
866 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
867 if (NULL == instHandle)
868 {
869 status = MCBSP_ERR_BADARGS;
870 }
871 }
872 }
873 }
874 #endif /* MCBSP_DISABLE_INPUT_PARAM_CHECK */
876 if (MCBSP_STATUS_COMPLETED == status)
877 {
878 /* reset the channel . */
879 Mcbsp_localAbortReset(chanHandle);
881 /* Disable the current transfer to make sure that there is no *
882 * running EDMA transfer taking place */
883 status = EDMA3_DRV_disableTransfer(
884 chanHandle->edmaHandle,
885 chanHandle->xferChan,
886 EDMA3_DRV_TRIG_MODE_EVENT);
888 /* Disable current EDMA transfer */
889 if (MCBSP_STATUS_COMPLETED == status)
890 {
891 if (MCBSP_MODE_OUTPUT == chanHandle->mode)
892 {
893 timeOut = instHandle->retryCount;
895 /* Poll for TXEMPTY */
896 while ((CSL_MCBSP_SPCR_XEMPTY_MASK ==
897 (CSL_MCBSP_SPCR_XEMPTY_MASK & instHandle->hwInfo.regs->SPCR))
898 && (0 != timeOut))
899 {
900 timeOut--;
901 }
902 }
904 /* Reset McBSP before freeing the edma channels */
905 if (MCBSP_MODE_INPUT == chanHandle->mode)
906 {
907 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_RX_DISABLE);
908 }
909 else
910 {
911 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_TX_DISABLE);
912 }
914 /* Free Edma channels */
915 status = EDMA3_DRV_freeChannel(
916 chanHandle->edmaHandle,
917 chanHandle->xferChan);
918 #ifndef MCBSP_LOOPJOB_ENABLE
920 /* free the already allocated dummy PaRAM entries */
921 EDMA3_DRV_freeChannel(chanHandle->edmaHandle,
922 Mcbsp_edmaChanNum);
923 #endif
925 if (MCBSP_STATUS_COMPLETED == status)
926 {
927 /* free the EDMA PaRAM entries used for Ping pong buffer */
928 for (linkCnt = 0; linkCnt < Mcbsp_MAXLINKCNT; linkCnt++)
929 {
930 status = EDMA3_DRV_freeChannel(
931 chanHandle->edmaHandle,
932 chanHandle->pramTbl[linkCnt]);
933 if (MCBSP_STATUS_COMPLETED != status)
934 {
935 break;
936 }
937 }
938 }
940 if (MCBSP_STATUS_COMPLETED == status)
941 {
942 /* Set the state of the channel as closed */
943 chanHandle->chanState = Mcbsp_DriverState_CLOSED;
945 /* Set the Muted state to FALSE */
946 chanHandle->bMuteON = FALSE;
948 /* Set the Paused state to FALSE */
949 chanHandle->paused = FALSE;
950 }
951 }
953 /* Writeback Global Object */
954 Mcbsp_osalEndMemAccess ((void *)chanHandle->devHandle, sizeof(Mcbsp_Object));
955 }
957 /* End Critical Section */
958 Mcbsp_osalExitMultipleCoreCriticalSection (criticalSectionInfo);
960 return (status);
961 }
963 /**
964 * \brief Closes the McBSP device instance from use.
965 * This API is called by the application when it no longer requires the
966 * device instance. Note that all the channels have to be closed for
967 * the device instance to be deleted sucessfully.
968 *
969 * \param devp [IN] Handle to the device created.
970 *
971 * \return MCBSP_STATUS_COMPLETED if successful
972 * MCBSP_STATUS_ABORTED if not successful
973 *
974 * \enter devp should be non NULL and valid pointer,
975 *
976 * \leave Not implemented
977 */
978 int32_t mcbspUnBindDev(void* devp)
979 {
980 Mcbsp_Object *hInst = NULL;
981 Mcbsp_Object_Unpadded *instHandle = NULL;
982 int32_t status = MCBSP_STATUS_COMPLETED;
983 void* criticalSectionInfo;
985 /* Begin Critical Section before accessing shared resources. */
986 criticalSectionInfo = Mcbsp_osalEnterMultipleCoreCriticalSection ();
988 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
989 if (NULL == devp)
990 {
991 status = MCBSP_ERR_BADARGS;
992 }
993 else
994 {
995 #endif /* MCBSP_DISABLE_INPUT_PARAM_CHECK */
997 hInst = (Mcbsp_Object *)devp;
999 /* Invalidate the Cache Contents */
1000 Mcbsp_osalBeginMemAccess ((void *)hInst, sizeof(Mcbsp_Object));
1002 instHandle = (Mcbsp_Object_Unpadded *)&(hInst->obj);
1004 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
1005 if ((CSL_MCBSP_PER_CNT <= instHandle->instNum) ||
1006 (Mcbsp_DriverState_CLOSED != instHandle->xmtObj.chanState) ||
1007 (Mcbsp_DriverState_CLOSED != instHandle->rcvObj.chanState))
1008 {
1009 status = MCBSP_ERR_BADARGS;
1010 }
1011 }
1012 #endif /* MCBSP_DISABLE_INPUT_PARAM_CHECK */
1014 if (MCBSP_STATUS_COMPLETED == status)
1015 {
1016 /* reset the Mcbsp */
1017 instHandle->hwInfo.regs->SPCR = 0x00u;
1019 /* Mark driver state as deleted and module as not in use */
1020 instHandle->devState = Mcbsp_DriverState_DELETED;
1021 instHandle->inUse = FALSE;
1023 /* update the user params to the instance object */
1024 instHandle->instNum = -1;
1026 /* Intialize the mcbsp driver to default values */
1027 memset(instHandle, 0, sizeof(Mcbsp_Object_Unpadded));
1029 /* Writeback Global Object */
1030 Mcbsp_osalEndMemAccess ((void *)hInst, sizeof(Mcbsp_Object));
1031 }
1033 /* End Critical Section */
1034 Mcbsp_osalExitMultipleCoreCriticalSection (criticalSectionInfo);
1036 return status;
1037 }
1039 /**
1040 * \brief Submit a I/O buffer to a channel for processing
1041 *
1042 * The application calls this function to cause the driver
1043 * to process the Mcbsp_IOBuf for read/write/flush/abort operations.
1044 *
1045 * \param chanp [IN] Pointer to channel
1046 * \param ioBuf [IN] Pointer to buffer to be submitted
1047 *
1048 * \return MCBSP_STATUS_COMPLETED, if buffer is fully processed
1049 * MCBSP_STATUS_ABORTED, if buffer is aborted
1050 * MCBSP_STATUS_PENDING, if buffer is not fully processed
1051 * MCBSP_ERR_BADIO in case of an error in processing
1052 *
1053 */
1054 int32_t mcbspSubmitChan(void* chanp, Mcbsp_IOBuf *const ioBuf)
1055 {
1056 Mcbsp_Object_Unpadded *instHandle = NULL;
1057 Mcbsp_ChannelObj *chanHandle = NULL;
1058 int32_t status = MCBSP_STATUS_COMPLETED;
1060 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
1061 if ((NULL == chanp) || ( NULL == ioBuf))
1062 {
1063 status = MCBSP_ERR_BADARGS;
1064 }
1065 else
1066 {
1067 #endif
1068 chanHandle = (Mcbsp_ChannelObj *)chanp;
1070 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
1072 if ((NULL == chanHandle) || (NULL == chanHandle->devHandle))
1073 {
1074 status = MCBSP_ERR_BADARGS;
1075 }
1076 else
1077 {
1078 #endif
1079 instHandle = (Mcbsp_Object_Unpadded *)&(chanHandle->devHandle->obj);
1080 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
1081 if (NULL == instHandle)
1082 {
1083 status = MCBSP_ERR_BADARGS;
1084 }
1085 else
1086 {
1087 if (NULL == ioBuf->addr)
1088 {
1089 if ((Mcbsp_IOBuf_Cmd_READ == ioBuf->cmd) ||
1090 (Mcbsp_IOBuf_Cmd_WRITE == ioBuf->cmd))
1091 {
1092 status = MCBSP_ERR_BADARGS;
1093 }
1094 }
1095 }
1096 }
1097 }
1098 #endif /* MCBSP_DISABLE_INPUT_PARAM_CHECK */
1100 if (MCBSP_STATUS_COMPLETED == status)
1101 {
1102 /* process the command sent by the application */
1103 switch (ioBuf->cmd)
1104 {
1105 case Mcbsp_IOBuf_Cmd_READ:
1106 case Mcbsp_IOBuf_Cmd_WRITE:
1107 if (TRUE != chanHandle->flush)
1108 {
1109 status = mcbspSubmitReq(instHandle,chanHandle,ioBuf);
1110 }
1111 else
1112 {
1113 status = MCBSP_ERR_BADIO;
1114 }
1115 break;
1116 case Mcbsp_IOBuf_Cmd_FLUSH:
1117 /* Flush command has been issued need to abort the receive *
1118 * channel buffers and complete the TX buffers normally */
1119 chanHandle->flush = TRUE;
1120 Mcbsp_localAbortReset(chanHandle);
1121 chanHandle->flush = FALSE;
1122 break;
1123 case Mcbsp_IOBuf_Cmd_ABORT:
1124 Mcbsp_localAbortReset(chanHandle);
1125 break;
1126 default:
1127 status = MCBSP_ERR_BADIO;
1128 break;
1129 }
1130 }
1132 return status;
1133 }
1135 /**
1136 * \brief Implements the IOCTLS for McBSP driver.
1137 *
1138 * ControlChan() implements recieved IOCTL commands from the
1139 * application and executes them accordingly.
1140 *
1141 * \param chanp [IN] Pointer to channel
1142 * \param cmd [IN] specific IOCTL command
1143 * \param arg [IN] arguments required for specific commands
1144 *
1145 * \return MCBSP_STATUS_COMPLETED, if command is executed correctly
1146 * MCBSP_STATUS_ABORTED, if command returns error during execution
1147 * MCBSP_ERR_NOTIMPL, if command is not supported
1148 * MCBSP_ERR_BADARGS if args are not correct
1149 */
1150 int32_t mcbspControlChan(void* chanp, Mcbsp_IOCTL cmd, void* arg)
1151 {
1152 Mcbsp_ChannelObj *chanHandle = NULL;
1153 int32_t status = MCBSP_STATUS_COMPLETED;
1155 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
1156 if (NULL == chanp)
1157 {
1158 status = MCBSP_ERR_BADARGS;
1159 }
1160 else
1161 {
1162 #endif /* MCBSP_DISABLE_INPUT_PARAM_CHECK */
1164 chanHandle = (Mcbsp_ChannelObj *)chanp;
1166 /* Invalidate the Cache Contents */
1167 Mcbsp_osalBeginMemAccess ((void *)chanHandle->devHandle, sizeof(Mcbsp_Object));
1169 #ifndef MCBSP_DISABLE_INPUT_PARAM_CHECK
1170 if (NULL == chanHandle->devHandle)
1171 {
1172 status = MCBSP_ERR_BADARGS;
1173 }
1174 }
1175 #endif
1177 if (MCBSP_STATUS_COMPLETED == status)
1178 {
1179 /* call the function to process the IOCTL command */
1180 status = Mcbsp_localSubmitIoctl(
1181 chanHandle,
1182 cmd,
1183 arg,
1184 NULL);
1185 }
1187 /* Writeback Global Object */
1188 Mcbsp_osalEndMemAccess ((void *)chanHandle->devHandle, sizeof(Mcbsp_Object));
1190 return (status);
1191 }
1193 /**
1194 * \brief McBSP Tx ISR function
1195 *
1196 * This Function is the interrupt service routine for the Mcbsp TX
1197 * event.
1198 *
1199 * \param hChan [IN] Handle to the channel
1200 *
1201 * \return None
1202 */
1203 void mcbspGblXmtIsr(void *hChan)
1204 {
1205 Mcbsp_Object_Unpadded *instHandle = NULL;
1206 Mcbsp_ChannelObj *chanHandle = (Mcbsp_ChannelObj *)hChan;
1208 instHandle = (Mcbsp_Object_Unpadded *)&(chanHandle->devHandle->obj);
1210 /* Only DMA mode of operation is supported by the Mcbsp driver hence we *
1211 * will only check if there is an sync error and notify the application */
1212 if (CSL_MCBSP_SPCR_XSYNCERR_MASK ==
1213 (CSL_MCBSP_SPCR_XSYNCERR_MASK & instHandle->hwInfo.regs->SPCR))
1214 {
1215 /* call the application registered global callback function */
1216 if (NULL != chanHandle->gblErrCbk)
1217 {
1218 (*chanHandle->gblErrCbk)((uint32_t)chanHandle,
1219 instHandle->hwInfo.regs->SPCR,
1220 NULL);
1221 }
1222 }
1224 return;
1225 }
1227 /**
1228 * \brief McBSP Rx ISR function
1229 *
1230 * This Function is the interrupt service routine for the Mcbsp RX
1231 * event.
1232 *
1233 * \param hChan [IN] Handle to the channel
1234 *
1235 * \return None
1236 */
1237 void mcbspGblRcvIsr(void *hChan)
1238 {
1239 Mcbsp_Object_Unpadded *instHandle = NULL;
1240 Mcbsp_ChannelObj *chanHandle = (Mcbsp_ChannelObj *)hChan;
1242 instHandle = (Mcbsp_Object_Unpadded *)&(chanHandle->devHandle->obj);
1244 /* Only DMA mode of operation is supported by the Mcbsp driver hence we *
1245 * will only check if there is an sync error and notify the application */
1246 if (CSL_MCBSP_SPCR_RSYNCERR_MASK ==
1247 (CSL_MCBSP_SPCR_RSYNCERR_MASK & instHandle->hwInfo.regs->SPCR))
1248 {
1249 /* call the application registered global callback function */
1250 if (NULL != chanHandle->gblErrCbk)
1251 {
1252 (*chanHandle->gblErrCbk)((uint32_t)chanHandle,
1253 instHandle->hwInfo.regs->SPCR,
1254 NULL);
1255 }
1256 }
1258 return;
1259 }
1261 /*============================================================================*/
1262 /* LOCAL FUNCTION DEFINTIONS */
1263 /*============================================================================*/
1265 /**
1266 * \brief Submit a I/O buffer to a channel for processing
1267 *
1268 * This function is called with the Mcbsp_IOBuf_Cmd_READ or Mcbsp_IOBuf_Cmd_WRITE
1269 * command to process the IOP. The function handles the MCBSP mode. In case
1270 * that the driver is currently idle it sets up buffer for transfer. In case
1271 * that the driver is currently processing a buffer then it will queue up the
1272 * current buffer and exit.
1273 *
1274 * \param instHandle [IN] pointer to the instance object
1275 * \param chanHandle [IN] handle to the channel
1276 * \param ioBuf [IN] pointer to Mcbsp I/O buffer.
1277 *
1278 * \return MCBSP_STATUS_PENDING in case the buffer is sucesfully processed
1279 * MCBSP_ERR_BADIO in case of any error.
1280 */
1281 int32_t mcbspSubmitReq(Mcbsp_Object_Unpadded *instHandle,
1282 Mcbsp_ChannelObj *chanHandle,
1283 Mcbsp_IOBuf *ioBuf)
1284 {
1285 void* criticalSectionInfo;
1286 int32_t status = MCBSP_STATUS_COMPLETED;
1288 if ((NULL == chanHandle) || (NULL == ioBuf) || (NULL == instHandle))
1289 {
1290 return MCBSP_ERR_BADIO;
1291 }
1292 if((0 == ioBuf->size) || (ioBuf->size > Mcbsp_MAX_IOBUF_SIZE))
1293 {
1294 return MCBSP_ERR_BADIO;
1295 }
1297 /* clean the buffers if the cache operation mode is enabled */
1298 if (TRUE == instHandle->enablecache)
1299 {
1300 if (MCBSP_MODE_INPUT == chanHandle->mode)
1301 {
1302 /* Invalidate the cache */
1303 Mcbsp_osalBeginMemAccess(ioBuf->addr, ioBuf->size);
1304 }
1305 else
1306 {
1307 /* Writeback the cache */
1308 Mcbsp_osalEndMemAccess(ioBuf->addr, ioBuf->size);
1309 }
1310 }
1312 /*==========================MCBSP MODE ===================================*/
1313 if (Mcbsp_DevMode_McBSP == instHandle->mode)
1314 {
1315 /* We are entering the crictical section because the current active *
1316 * IOP is being check and it can become NULL at any point. Hence we *
1317 * will protect this code from the interrupt handler. */
1318 criticalSectionInfo = Mcbsp_osalEnterSingleCoreCriticalSection();
1320 #ifdef MCBSP_LOOPJOB_ENABLE
1321 if ((Mcbsp_MAXLINKCNT <= chanHandle->submitCount) ||
1322 #else
1323 /* We now have 3 buffers loaded in the EDMA */
1324 if (((Mcbsp_MAXLINKCNT + 1) <= chanHandle->submitCount) ||
1325 #endif
1326 (TRUE == chanHandle->paused))
1327 {
1328 /* There are enough buffers programmed in the EDMA or if the MCBSP*
1329 * is issued a pause command,hence queue buffer in to the pending *
1330 * queue */
1331 chanHandle->submitCount++;
1333 Mcbsp_osalQueuePut(chanHandle->ptrQPendList, (Mcbsp_QueueElem *)ioBuf);
1335 /* critical section ends */
1336 Mcbsp_osalExitSingleCoreCriticalSection(criticalSectionInfo);
1337 }
1338 else
1339 {
1340 /* Either one of the paramset or Both the paramsets are free */
1342 /* increment the submit count */
1343 chanHandle->submitCount++;
1345 Mcbsp_osalQueuePut(chanHandle->ptrQFloatList, (Mcbsp_QueueElem *)ioBuf);
1347 Mcbsp_localLoadPktToEdma(chanHandle,ioBuf);
1349 /* critical section ends */
1350 Mcbsp_osalExitSingleCoreCriticalSection(criticalSectionInfo);
1352 } /* Pending queue empty or not*/
1353 }
1354 if (MCBSP_STATUS_COMPLETED == status)
1355 {
1356 status = MCBSP_STATUS_PENDING;
1357 }
1358 return (status);
1359 }
1361 /**
1362 * \brief McBSP SPCR configuration function
1363 *
1364 * This Function is used to set/reset specific bit of SPCR as specified in
1365 * the given mask.
1366 *
1367 * \param instHandle [IN] pointer to the mcbsp instance object.
1368 * \param selectMask [IN] the SPCR control mask
1369 *
1370 * \return MCBSP_STATUS_COMPLETED if successful
1371 *
1372 * MCBSP_ERR_BADARGS if not successful
1373 */
1374 int32_t Mcbsp_localResetCtrl(Mcbsp_Object_Unpadded *instHandle, uint32_t selectMask)
1375 {
1376 if ((NULL == instHandle) || (NULL == instHandle->hwInfo.regs))
1377 {
1378 return MCBSP_ERR_BADARGS;
1379 }
1381 /* Configuring SPCR for Frame sync generator enable/disable */
1382 if (0u != (selectMask & Mcbsp_SpcrCtrl_FSYNC_DISABLE))
1383 {
1384 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_FRST_MASK );
1385 }
1387 if (0 != (selectMask & Mcbsp_SpcrCtrl_RX_DISABLE))
1388 {
1389 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_RRST_MASK );
1390 }
1392 /* start the sample rate generator */
1393 if (0u != (selectMask & Mcbsp_SpcrCtrl_SRG_ENABLE))
1394 {
1395 instHandle->hwInfo.regs->SPCR |= CSL_MCBSP_SPCR_GRST_MASK;
1396 }
1398 /* Configuring SPCR for Transmit enable/disable */
1399 if (0 != (selectMask & Mcbsp_SpcrCtrl_TX_DISABLE))
1400 {
1401 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_XRST_MASK);
1402 }
1404 /* Configuring SPCR for transmit section enable */
1405 if (0 != (selectMask & Mcbsp_SpcrCtrl_TX_ENABLE))
1406 {
1407 instHandle->hwInfo.regs->SPCR |= CSL_MCBSP_SPCR_XRST_MASK;
1408 }
1410 /* Configuring SPCR for Receive section enable */
1411 if (0 != (selectMask & Mcbsp_SpcrCtrl_RX_ENABLE))
1412 {
1413 instHandle->hwInfo.regs->SPCR |= CSL_MCBSP_SPCR_RRST_MASK ;
1414 }
1416 /* Set the FRST bit to 1 to start the internal frame sync generator */
1417 if (0u != (selectMask & Mcbsp_SpcrCtrl_FSYNC_ENABLE))
1418 {
1419 instHandle->hwInfo.regs->SPCR |= CSL_MCBSP_SPCR_FRST_MASK;
1420 }
1422 /* Configuring SPCR for sample rate generator enable/disable */
1423 if (0u != (selectMask & Mcbsp_SpcrCtrl_SRG_DISABLE))
1424 {
1425 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_GRST_MASK);
1426 }
1428 return MCBSP_STATUS_COMPLETED;
1429 }
1431 /**
1432 * \brief This function completes the current pending request and then
1433 * invokes the application registered callback.
1434 *
1435 * \param chanHandle [IN] Handle to the channel
1436 *
1437 * \return None
1438 *
1439 * \enter chanHandle is a valid non null pointer
1440 *
1441 * \leave Not implemented
1442 */
1443 void Mcbsp_localCompleteCurrentIo(Mcbsp_ChannelObj *chanHandle)
1444 {
1445 Mcbsp_IOBuf *ioBuf = NULL;
1447 if (TRUE == chanHandle->isTempIOBufValid)
1448 {
1449 ioBuf = chanHandle->tempIOBuf;
1451 chanHandle->tempIOBuf = NULL;
1452 chanHandle->isTempIOBufValid = FALSE;
1453 /* call the completion callback function registered with us *
1454 * during channel creation */
1455 if ((NULL != chanHandle->cbFxn) && (NULL != chanHandle->cbArg))
1456 {
1457 /* Application callback */
1458 (*chanHandle->cbFxn)((void*)chanHandle->cbArg,ioBuf);
1459 }
1460 }
1462 chanHandle->currentError = MCBSP_STATUS_COMPLETED;
1463 chanHandle->userDataBufferSize = 0;
1464 }
1466 /**
1467 * \brief This function configures the transmit section of the mcbsp
1468 * sync properties.
1469 *
1470 * \param instHandle [IN] pointer to the instance object.
1471 * \param params [IN] User supplied channel parameters
1472 *
1473 * \return MCBSP_ERR_BADARGS if configuration fails.
1474 * MCBSP_STATUS_COMPLETED if configuration is sucessful.
1475 */
1476 int32_t Mcbsp_localConfigureXmtChannel(Mcbsp_Object_Unpadded *instHandle,
1477 Mcbsp_ChanParams *params)
1478 {
1479 uint32_t tempVal = 0x00;
1480 int32_t status = MCBSP_STATUS_COMPLETED;
1482 if ((NULL == instHandle) || (NULL == params))
1483 {
1484 return MCBSP_ERR_BADARGS;
1485 }
1487 /* configure the transmit section */
1488 /* configure the transmit interrupt setting */
1489 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_XINTM_MASK);
1490 instHandle->hwInfo.regs->SPCR |=
1491 (params->chanConfig->intMode << CSL_MCBSP_SPCR_XINTM_SHIFT);
1493 /* configure the DX enabler */
1494 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_DXENA_MASK);
1495 instHandle->hwInfo.regs->SPCR |=
1496 (params->chanConfig->dxState << CSL_MCBSP_SPCR_DXENA_SHIFT);
1498 /* configure the transmit control register settings */
1499 instHandle->hwInfo.regs->XCR &= (~CSL_MCBSP_XCR_XPHASE_MASK);
1500 instHandle->hwInfo.regs->XCR |=
1501 (params->chanConfig->phaseNum << CSL_MCBSP_XCR_XPHASE_SHIFT);
1503 /* configure the frame length for single and dual phase frames */
1504 instHandle->hwInfo.regs->XCR &= (~CSL_MCBSP_XCR_XFRLEN1_MASK);
1505 instHandle->hwInfo.regs->XCR |=
1506 ((params->chanConfig->frmLen1 - 1u) << CSL_MCBSP_XCR_XFRLEN1_SHIFT);
1508 /* configure the word length of the single and dual phase frames */
1509 switch (params->chanConfig->wrdLen1)
1510 {
1511 case Mcbsp_WordLength_8:
1512 tempVal = 0u;
1513 break;
1514 case Mcbsp_WordLength_12:
1515 tempVal = 1u;
1516 break;
1517 case Mcbsp_WordLength_16:
1518 tempVal = 2u;
1519 break;
1520 case Mcbsp_WordLength_20:
1521 tempVal = 3u;
1522 break;
1523 case Mcbsp_WordLength_24:
1524 tempVal = 4u;
1525 break;
1526 case Mcbsp_WordLength_32:
1527 tempVal = 5u;
1528 break;
1529 default:
1530 /* wordlength is not supported by the driver */
1531 status = MCBSP_ERR_BADARGS;
1532 break;
1533 }
1535 instHandle->hwInfo.regs->XCR &= (~CSL_MCBSP_XCR_XWDLEN1_MASK);
1536 instHandle->hwInfo.regs->XCR |=
1537 (tempVal << CSL_MCBSP_XCR_XWDLEN1_SHIFT);
1539 if (Mcbsp_Phase_DUAL == params->chanConfig->phaseNum)
1540 {
1542 instHandle->hwInfo.regs->XCR &= (~CSL_MCBSP_XCR_XFRLEN2_MASK);
1543 instHandle->hwInfo.regs->XCR |=
1544 ((params->chanConfig->frmLen2 -1u) << CSL_MCBSP_XCR_XFRLEN2_SHIFT);
1546 /* configure the word length of the single and dual phase frames */
1547 switch (params->chanConfig->wrdLen2)
1548 {
1549 case Mcbsp_WordLength_8:
1550 tempVal = 0u;
1551 break;
1552 case Mcbsp_WordLength_12:
1553 tempVal = 1u;
1554 break;
1555 case Mcbsp_WordLength_16:
1556 tempVal = 2u;
1557 break;
1558 case Mcbsp_WordLength_20:
1559 tempVal = 3u;
1560 break;
1561 case Mcbsp_WordLength_24:
1562 tempVal = 4u;
1563 break;
1564 case Mcbsp_WordLength_32:
1565 tempVal = 5u;
1566 break;
1567 default:
1568 /* wordlength is not supported by the driver */
1569 status = MCBSP_ERR_BADARGS;
1570 break;
1571 }
1573 instHandle->hwInfo.regs->XCR &= (~CSL_MCBSP_XCR_XWDLEN2_MASK);
1574 instHandle->hwInfo.regs->XCR |=
1575 (tempVal << CSL_MCBSP_XCR_XWDLEN2_SHIFT);
1576 }
1577 /* set the companding selection */
1578 instHandle->hwInfo.regs->XCR &= (~CSL_MCBSP_XCR_XCOMPAND_MASK);
1579 instHandle->hwInfo.regs->XCR |=
1580 (params->chanConfig->compandSel << CSL_MCBSP_XCR_XCOMPAND_SHIFT);
1582 /* set the bit reverse settings */
1583 instHandle->hwInfo.regs->XCR &= (~CSL_MCBSP_XCR_XWDREVRS_MASK);
1584 instHandle->hwInfo.regs->XCR |=
1585 (params->chanConfig->bitReversal << CSL_MCBSP_XCR_XWDREVRS_SHIFT);
1587 /* frame ignore settings */
1588 instHandle->hwInfo.regs->XCR &= (~CSL_MCBSP_XCR_XFIG_MASK);
1589 instHandle->hwInfo.regs->XCR |=
1590 (params->chanConfig->frmSyncIgn << CSL_MCBSP_XCR_XFIG_SHIFT);
1592 /* configure the data delay */
1593 instHandle->hwInfo.regs->XCR &= (~CSL_MCBSP_XCR_XDATDLY_MASK);
1594 instHandle->hwInfo.regs->XCR |=
1595 (params->chanConfig->dataDelay << CSL_MCBSP_XCR_XDATDLY_SHIFT);
1597 /* configure the multi channel control register settings */
1598 instHandle->hwInfo.regs->MCR &= (~CSL_MCBSP_MCR_XMCM_MASK);
1599 instHandle->hwInfo.regs->MCR |= (params->multiChanCtrl->multiChanMode
1600 << CSL_MCBSP_MCR_XMCM_SHIFT);
1602 /* select the partition mode and the channel selection controls */
1603 instHandle->hwInfo.regs->MCR &= (~CSL_MCBSP_MCR_XPABLK_MASK);
1604 instHandle->hwInfo.regs->MCR |= (params->multiChanCtrl->partitionSelA
1605 << CSL_MCBSP_MCR_XPABLK_SHIFT);
1607 instHandle->hwInfo.regs->MCR &= (~CSL_MCBSP_MCR_XPBBLK_MASK);
1608 instHandle->hwInfo.regs->MCR |= (params->multiChanCtrl->partitionSelB
1609 << CSL_MCBSP_MCR_XPBBLK_SHIFT);
1611 instHandle->hwInfo.regs->MCR &= (~CSL_MCBSP_MCR_XMCME_MASK);
1612 instHandle->hwInfo.regs->MCR |= (params->multiChanCtrl->partitionMode
1613 << CSL_MCBSP_MCR_XMCME_SHIFT);
1615 /* Configure the channels to be enabled */
1616 instHandle->hwInfo.regs->XCERE0 = params->chanEnableMask[0];
1617 instHandle->hwInfo.regs->XCERE1 = params->chanEnableMask[1];
1618 instHandle->hwInfo.regs->XCERE2 = params->chanEnableMask[2];
1619 instHandle->hwInfo.regs->XCERE3 = params->chanEnableMask[3];
1622 /* configure the clock polarity */
1623 if (Mcbsp_ClkPol_RISING_EDGE == params->clkSetup->clkPolarity)
1624 {
1625 /* clock data sampled on rising edge */
1626 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_CLKXP_MASK);
1627 }
1628 else
1629 {
1630 /* clock data sampled on falling edge */
1631 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_CLKXP_MASK);
1632 }
1634 /* configure the frame sync polarity */
1635 if (Mcbsp_FsPol_ACTIVE_HIGH == params->clkSetup->frmSyncPolarity)
1636 {
1637 /* frame sync polarity is active high */
1638 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_FSXP_MASK);
1639 }
1640 else
1641 {
1642 /* frame sync polarity is active low */
1643 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_FSXP_MASK);
1644 }
1646 /* check if the frame sync generator is to be enabled for this TX section */
1647 if (Mcbsp_FsClkMode_EXTERNAL == params->clkSetup->frmSyncMode)
1648 {
1649 /* External frame sync to be used */
1650 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_FSXM_MASK);
1652 /* frame sync generator needs to be disabled */
1653 instHandle->txFsgEnable = FALSE;
1654 }
1655 else
1656 {
1657 /* internal frame sync to be used */
1658 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_FSXM_MASK);
1660 /* The FRST and GRST has to be cleared to configure the FSGM bit.
1661 * By clearing the FRST and GRST bit, the sample rate generator and the
1662 * frame sync generator will be kept in the reset mode.
1663 * Ref IR SDOCM00077966
1664 */
1665 tempVal = instHandle->hwInfo.regs->SPCR;
1666 instHandle->hwInfo.regs->SPCR &= ~(CSL_MCBSP_SPCR_FRST_MASK |
1667 CSL_MCBSP_SPCR_GRST_MASK );
1669 /* could be internal or configured for DXR to XSR copy */
1670 if (Mcbsp_FsClkMode_INTERNAL == params->clkSetup->frmSyncMode)
1671 {
1672 /* set the FSGM bit in the SRGR register */
1673 instHandle->hwInfo.regs->SRGR |= (CSL_MCBSP_SRGR_FSGM_MASK);
1675 /* frame sync generator needs to be enabled */
1676 instHandle->txFsgEnable = TRUE;
1677 }
1678 else
1679 { /* DXR to XSR copy generates frame sync */
1680 /* reset the FSGM bit in the SRGR register */
1681 instHandle->hwInfo.regs->SRGR &= (~CSL_MCBSP_SRGR_FSGM_MASK);
1683 /* frame sync generator needs to be disabled */
1684 instHandle->txFsgEnable = FALSE;
1685 }
1686 /* The SPCR register values are reverted back once the FSGM bit is set
1687 */
1688 instHandle->hwInfo.regs->SPCR = tempVal;
1689 }
1691 /* configure the clock mode (external or internal) */
1692 if (Mcbsp_TxRxClkMode_EXTERNAL == params->clkSetup->clkMode)
1693 {
1694 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_CLKXM_MASK);
1696 if (TRUE == instHandle->txFsgEnable)
1697 {
1698 /* frame sync generator is using the internal clock hence need to *
1699 * enable the sample rate generator */
1700 instHandle->txSrgEnable = TRUE;
1701 }
1702 else
1703 {
1704 /* dont require to enable the sample rate generator */
1705 instHandle->txSrgEnable = FALSE;
1706 }
1707 }
1708 else
1709 {
1710 /* external mode clock enabled */
1711 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_CLKXM_MASK);
1713 /* sample rate generator is enabled */
1714 instHandle->txSrgEnable = TRUE;
1715 }
1717 return (status);
1718 }
1721 /**
1722 * \brief This function configures the receives section of the mcbsp.
1723 *
1724 * \param instHandle [IN] pointer to the instance object.
1725 * \param params [IN] User supplied channel parameters
1726 *
1727 * \return MCBSP_ERR_BADARGS if configuration fails.
1728 * MCBSP_STATUS_COMPLETED if confioguration is sucessful.
1729 */
1730 int32_t Mcbsp_localConfigureRcvChannel(Mcbsp_Object_Unpadded *instHandle,
1731 Mcbsp_ChanParams *params)
1732 {
1733 uint32_t tempVal = 0x00;
1734 int32_t status = MCBSP_STATUS_COMPLETED;
1736 if ((NULL == instHandle) || (NULL == params))
1737 {
1738 return MCBSP_ERR_BADARGS;
1739 }
1741 /* configure the receive section */
1742 /* configure the receive interrupt setting */
1743 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_RINTM_MASK);
1744 instHandle->hwInfo.regs->SPCR |=
1745 (params->chanConfig->intMode << CSL_MCBSP_SPCR_RINTM_SHIFT);
1747 /* configure the Receive sign-extension and justification */
1748 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_RJUST_MASK);
1749 instHandle->hwInfo.regs->SPCR |=
1750 (params->chanConfig->rjust << CSL_MCBSP_SPCR_RJUST_SHIFT);
1752 /* configure the receive control register settings */
1753 instHandle->hwInfo.regs->RCR &= (~CSL_MCBSP_RCR_RPHASE_MASK);
1754 instHandle->hwInfo.regs->RCR |=
1755 (params->chanConfig->phaseNum << CSL_MCBSP_RCR_RPHASE_SHIFT);
1757 /* configure the frame length for single and dual phase frames */
1758 instHandle->hwInfo.regs->RCR &= (~CSL_MCBSP_RCR_RFRLEN1_MASK);
1759 instHandle->hwInfo.regs->RCR |=
1760 ((params->chanConfig->frmLen1 - 1u) << CSL_MCBSP_RCR_RFRLEN1_SHIFT);
1762 /* configure the word length of the single and dual phase frames */
1763 switch (params->chanConfig->wrdLen1)
1764 {
1765 case Mcbsp_WordLength_8:
1766 tempVal = 0u;
1767 break;
1768 case Mcbsp_WordLength_12:
1769 tempVal = 1u;
1770 break;
1771 case Mcbsp_WordLength_16:
1772 tempVal = 2u;
1773 break;
1774 case Mcbsp_WordLength_20:
1775 tempVal = 3u;
1776 break;
1777 case Mcbsp_WordLength_24:
1778 tempVal = 4u;
1779 break;
1780 case Mcbsp_WordLength_32:
1781 tempVal = 5u;
1782 break;
1783 default:
1784 /* wordlength is not supported by the driver */
1785 status = MCBSP_ERR_BADARGS;
1786 break;
1787 }
1790 instHandle->hwInfo.regs->RCR &= (~CSL_MCBSP_RCR_RWDLEN1_MASK);
1791 instHandle->hwInfo.regs->RCR |=
1792 (tempVal << CSL_MCBSP_RCR_RWDLEN1_SHIFT);
1794 if (Mcbsp_Phase_DUAL == params->chanConfig->phaseNum)
1795 {
1796 instHandle->hwInfo.regs->RCR &= (~CSL_MCBSP_RCR_RFRLEN2_MASK);
1797 instHandle->hwInfo.regs->RCR |=
1798 ((params->chanConfig->frmLen2 - 1u) << CSL_MCBSP_RCR_RFRLEN2_SHIFT);
1800 /* configure the word length of the single and dual phase frames */
1801 switch (params->chanConfig->wrdLen2)
1802 {
1803 case Mcbsp_WordLength_8:
1804 tempVal = 0u;
1805 break;
1806 case Mcbsp_WordLength_12:
1807 tempVal = 1u;
1808 break;
1809 case Mcbsp_WordLength_16:
1810 tempVal = 2u;
1811 break;
1812 case Mcbsp_WordLength_20:
1813 tempVal = 3u;
1814 break;
1815 case Mcbsp_WordLength_24:
1816 tempVal = 4u;
1817 break;
1818 case Mcbsp_WordLength_32:
1819 tempVal = 5u;
1820 break;
1821 default:
1822 /* wordlength is not supported by the driver */
1823 status = MCBSP_ERR_BADARGS;
1824 break;
1825 }
1827 instHandle->hwInfo.regs->RCR &= (~CSL_MCBSP_RCR_RWDLEN2_MASK);
1828 instHandle->hwInfo.regs->RCR |=
1829 (tempVal << CSL_MCBSP_RCR_RWDLEN2_SHIFT);
1830 }
1831 /* set the companding selection */
1832 instHandle->hwInfo.regs->RCR &= (~CSL_MCBSP_RCR_RCOMPAND_MASK);
1833 instHandle->hwInfo.regs->RCR |=
1834 (params->chanConfig->compandSel << CSL_MCBSP_RCR_RCOMPAND_SHIFT);
1836 /* set the bit reverse settings */
1837 instHandle->hwInfo.regs->RCR &= (~CSL_MCBSP_RCR_RWDREVRS_MASK);
1838 instHandle->hwInfo.regs->RCR |=
1839 (params->chanConfig->bitReversal << CSL_MCBSP_RCR_RWDREVRS_SHIFT);
1841 /* frame ignore settings */
1842 instHandle->hwInfo.regs->RCR &= (~CSL_MCBSP_RCR_RFIG_MASK);
1843 instHandle->hwInfo.regs->RCR |=
1844 (params->chanConfig->frmSyncIgn << CSL_MCBSP_RCR_RFIG_SHIFT);
1846 /* configure the data delay */
1847 instHandle->hwInfo.regs->RCR &= (~CSL_MCBSP_RCR_RDATDLY_MASK);
1848 instHandle->hwInfo.regs->RCR |=
1849 (params->chanConfig->dataDelay << CSL_MCBSP_RCR_RDATDLY_SHIFT);
1851 /* Configure the channels to be enabled */
1852 instHandle->hwInfo.regs->RCERE0 = params->chanEnableMask[0];
1853 instHandle->hwInfo.regs->RCERE1 = params->chanEnableMask[1];
1854 instHandle->hwInfo.regs->RCERE2 = params->chanEnableMask[2];
1855 instHandle->hwInfo.regs->RCERE3 = params->chanEnableMask[3];
1857 /* configure the MCR register */
1858 switch (params->multiChanCtrl->multiChanMode)
1859 {
1860 case Mcbsp_McmMode_ALL_CHAN_ENABLED_UNMASKED:
1861 case Mcbsp_McmMode_ALL_CHAN_DISABLED_UNMASKED:
1862 break;
1863 default:
1864 status = MCBSP_ERR_BADARGS;
1865 break;
1866 }
1868 if (MCBSP_STATUS_COMPLETED == status)
1869 {
1870 instHandle->hwInfo.regs->MCR &= (~CSL_MCBSP_MCR_RMCM_MASK);
1871 instHandle->hwInfo.regs->MCR |= (params->multiChanCtrl->multiChanMode
1872 << CSL_MCBSP_MCR_RMCM_SHIFT);
1873 }
1875 /* select the partition mode and the channel selection controls */
1876 instHandle->hwInfo.regs->MCR &= (~CSL_MCBSP_MCR_RPABLK_MASK);
1877 instHandle->hwInfo.regs->MCR |= (params->multiChanCtrl->partitionSelA
1878 << CSL_MCBSP_MCR_RPABLK_SHIFT);
1880 instHandle->hwInfo.regs->MCR &= (~CSL_MCBSP_MCR_RPBBLK_MASK);
1881 instHandle->hwInfo.regs->MCR |= (params->multiChanCtrl->partitionSelB
1882 << CSL_MCBSP_MCR_RPBBLK_SHIFT);
1884 instHandle->hwInfo.regs->MCR &= (~CSL_MCBSP_MCR_RMCME_MASK);
1885 instHandle->hwInfo.regs->MCR |= (params->multiChanCtrl->partitionMode
1886 << CSL_MCBSP_MCR_RMCME_SHIFT);
1888 /* configure the clock polarity */
1889 if (Mcbsp_ClkPol_RISING_EDGE == params->clkSetup->clkPolarity)
1890 {
1891 /* clock data sampled on rising edge */
1892 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_CLKRP_MASK);
1893 }
1894 else
1895 {
1896 /* clock data sampled on falling edge */
1897 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_CLKRP_MASK);
1898 }
1900 /* configure the frame sync polarity */
1901 if (Mcbsp_FsPol_ACTIVE_HIGH == params->clkSetup->frmSyncPolarity)
1902 {
1903 /* frame sync polarity is active high */
1904 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_FSRP_MASK);
1905 }
1906 else
1907 {
1908 /* frame sync polarity is active low */
1909 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_FSRP_MASK);
1910 }
1913 /* check if the frame sync generator is to be enabled for this section */
1914 if (Mcbsp_FsClkMode_INTERNAL == params->clkSetup->frmSyncMode)
1915 {
1916 /* set the frame sync generation mode */
1917 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_FSRM_MASK);
1919 /* frame sync generator needs to be enabled */
1920 instHandle->rxFsgEnable = TRUE;
1921 }
1922 else
1923 {
1924 /* reset the frame sync generation mode */
1925 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_FSRM_MASK);
1927 /* frame sync generator needs to be disabled */
1928 instHandle->rxFsgEnable = FALSE;
1929 }
1931 /* configure the clock mode (external or internal) */
1932 if (Mcbsp_TxRxClkMode_EXTERNAL == params->clkSetup->clkMode)
1933 {
1934 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_CLKRM_MASK);
1936 if (TRUE == instHandle->rxFsgEnable)
1937 {
1938 /* frame sync generator is using the internal clock hence need to *
1939 * enable the sample rate generator */
1940 instHandle->rxSrgEnable = TRUE;
1941 }
1942 else
1943 {
1944 /* dont require to enable the sample rate generator */
1945 instHandle->rxSrgEnable = FALSE;
1946 }
1947 }
1948 else
1949 {
1950 /* external mode clock */
1951 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_CLKRM_MASK);
1953 /* sample rate generator is enabled */
1954 instHandle->rxSrgEnable = TRUE;
1955 }
1956 return (status);
1957 }
1959 /**
1960 * \brief This function configures the sample rate generator and frame
1961 * sync properties.
1962 *
1963 * \param instHandle [IN] pointer to the instance object.
1964 * \param chanHandle [IN] Handle to the channel.
1965 *
1966 * \return MCBSP_ERR_BADARGS if calculation fails.
1967 * MCBSP_STATUS_COMPLETED if calculation is sucessful.
1968 */
1969 int32_t Mcbsp_localConfigureSrgr(Mcbsp_Object_Unpadded *instHandle,
1970 Mcbsp_ChannelObj *chanHandle)
1971 {
1972 Bool srgrConfig = FALSE;
1973 uint32_t clkgDiv = 0x00;
1974 uint32_t noOfBits = 0x00;
1975 uint32_t framePeriod = 0x00;
1976 Bool sclkme = 0x00;
1977 Bool clksm = 0x00;
1978 int32_t status = MCBSP_STATUS_COMPLETED;
1979 void* criticalSectionInfo;
1981 if ((NULL == instHandle) || (NULL == chanHandle))
1982 {
1983 return MCBSP_ERR_BADARGS;
1984 }
1986 /* check if the SRGR is not configured already */
1987 /* critical section starts */
1988 criticalSectionInfo = Mcbsp_osalEnterSingleCoreCriticalSection();
1990 if (FALSE == instHandle->srgConfigured)
1991 {
1992 /* set the status that SRGR is configured */
1993 instHandle->srgConfigured = TRUE;
1995 /* critical section ends */
1996 Mcbsp_osalExitSingleCoreCriticalSection(criticalSectionInfo);
1998 /* check if this channel requires the SRGR to be enabled */
1999 if (MCBSP_MODE_INPUT == chanHandle->mode)
2000 {
2001 if (TRUE == instHandle->rxSrgEnable)
2002 {
2003 /* Need to configure the SRGR */
2004 srgrConfig = TRUE;
2005 }
2006 else
2007 {
2008 instHandle->srgConfigured = FALSE;
2009 }
2010 }
2011 else
2012 {
2013 if (TRUE == instHandle->txSrgEnable)
2014 {
2015 /* Need to configure the SRGR */
2016 srgrConfig = TRUE;
2017 }
2018 else
2019 {
2020 instHandle->srgConfigured = FALSE;
2021 }
2022 }
2023 }
2024 else
2025 {
2026 /* critical section ends */
2027 Mcbsp_osalExitSingleCoreCriticalSection(criticalSectionInfo);
2028 }
2030 if (TRUE == srgrConfig)
2031 {
2032 /* set the input clock selection for Sample rate generator */
2033 switch (instHandle->srgrConfig.srgInputClkMode)
2034 {
2035 /* Input clock is CLKS */
2036 case Mcbsp_SrgClk_CLKS:
2037 sclkme = 0x00;
2038 clksm = 0x00;
2040 /* set the CLKS polarity (only if CLKS is used) */
2041 instHandle->hwInfo.regs->SRGR &= (~CSL_MCBSP_SRGR_CLKSP_MASK);
2042 instHandle->hwInfo.regs->SRGR |=
2043 (instHandle->srgrConfig.clksPolarity
2044 << CSL_MCBSP_SRGR_CLKSP_SHIFT);
2046 /* set the GSYNC option */
2047 instHandle->hwInfo.regs->SRGR &= (~CSL_MCBSP_SRGR_GSYNC_MASK);
2048 instHandle->hwInfo.regs->SRGR |=
2049 (instHandle->srgrConfig.gSync
2050 << CSL_MCBSP_SRGR_GSYNC_SHIFT);
2051 break;
2052 /* Input clock for SRG is from CPU clock */
2053 case Mcbsp_SrgClk_CLKCPU:
2054 sclkme = 0x00;
2055 clksm = 0x01u;
2056 break;
2057 /* Input clock is from receive pin */
2058 case Mcbsp_SrgClk_CLKR:
2059 sclkme = 0x01u;
2060 clksm = 0x00;
2061 break;
2062 /* Input clock is from transmit pin */
2063 case Mcbsp_SrgClk_CLKX:
2064 sclkme = 0x01u;
2065 clksm = 0x01u;
2066 break;
2067 default:
2068 status = MCBSP_ERR_BADARGS;
2069 break;
2070 }
2072 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_SCLKME_MASK);
2073 instHandle->hwInfo.regs->PCR |= (sclkme << CSL_MCBSP_PCR_SCLKME_SHIFT);
2075 instHandle->hwInfo.regs->SRGR &= (~CSL_MCBSP_SRGR_CLKSM_MASK);
2076 instHandle->hwInfo.regs->SRGR |= (clksm << CSL_MCBSP_SRGR_CLKSM_SHIFT);
2078 /* calculate and set the CLKG div values */
2079 if (Mcbsp_Phase_DUAL == chanHandle->chanConfig.phaseNum)
2080 {
2081 noOfBits = ((chanHandle->chanConfig.wrdLen1
2082 * chanHandle->chanConfig.frmLen1)
2083 + (chanHandle->chanConfig.wrdLen2
2084 * chanHandle->chanConfig.frmLen2));
2085 }
2086 else
2087 {
2088 noOfBits = (chanHandle->chanConfig.wrdLen1
2089 * chanHandle->chanConfig.frmLen1);
2090 }
2092 clkgDiv = ((instHandle->srgrConfig.srgrInputFreq/
2093 (chanHandle->clkSetup.samplingRate
2094 * noOfBits)) - 1u);
2096 framePeriod = (noOfBits - 1u);
2098 if ((0xFF < clkgDiv) || (0xFFF < framePeriod) ||
2099 (MCBSP_STATUS_COMPLETED != status))
2100 {
2101 /* The CLKGDIV or frame period value has exceeded the limit */
2102 status = MCBSP_ERR_BADARGS;
2103 }
2104 else
2105 {
2106 /* set the value of the CLKGDIV */
2107 instHandle->hwInfo.regs->SRGR &= (~CSL_MCBSP_SRGR_CLKGDV_MASK);
2108 instHandle->hwInfo.regs->SRGR |= clkgDiv;
2110 /* set the value of the frame period */
2111 instHandle->hwInfo.regs->SRGR &= (~CSL_MCBSP_SRGR_FPER_MASK);
2112 instHandle->hwInfo.regs->SRGR |=
2113 (framePeriod << CSL_MCBSP_SRGR_FPER_SHIFT);
2115 /* set the frame width */
2116 instHandle->hwInfo.regs->SRGR &= (~CSL_MCBSP_SRGR_FWID_MASK);
2117 instHandle->hwInfo.regs->SRGR |=
2118 (instHandle->srgrConfig.srgFrmPulseWidth <<
2119 CSL_MCBSP_SRGR_FWID_SHIFT);
2120 }
2121 }
2123 return (status);
2124 }
2126 /**
2127 * \brief Abort the queued up requests.
2128 *
2129 * This commands aborts all the pending IO requests and returns them
2130 * to the application. The current state of the IO request will be set
2131 * to ABORTED.
2132 *
2133 * \param chanHandle [IN] Handle to the channel whose requests are to be
2134 * aborted
2135 *
2136 * \return None
2137 */
2138 void Mcbsp_localAbortReset(Mcbsp_ChannelObj *chanHandle)
2139 {
2140 Mcbsp_Object_Unpadded *instHandle = NULL;
2141 Mcbsp_IOBuf *ioBuf = NULL;
2142 void* criticalSectionInfo;
2143 uint32_t timeoutCount = 0x00;
2145 instHandle = (Mcbsp_Object_Unpadded *)&(chanHandle->devHandle->obj);
2147 /* initialize the retry count value */
2148 timeoutCount = instHandle->retryCount;
2150 /* critical section starts */
2151 criticalSectionInfo = Mcbsp_osalEnterSingleCoreCriticalSection();
2153 if (Mcbsp_DevMode_McBSP == instHandle->mode)
2154 {
2155 /* Disable the EDMA transfer for the current transfer channel */
2156 EDMA3_DRV_disableTransfer(
2157 chanHandle->edmaHandle,
2158 chanHandle->xferChan,
2159 EDMA3_DRV_TRIG_MODE_EVENT);
2161 if (MCBSP_MODE_OUTPUT == chanHandle->mode)
2162 {
2163 /* Wait for the TX to be empty */
2164 while ((CSL_MCBSP_SPCR_XEMPTY_MASK ==
2165 (CSL_MCBSP_SPCR_XEMPTY_MASK & instHandle->hwInfo.regs->SPCR)) &&
2166 (0 != timeoutCount))
2167 {
2168 timeoutCount--;
2169 }
2170 }
2172 /* Stop the McBSP instance */
2173 if (MCBSP_MODE_INPUT == chanHandle->mode)
2174 {
2175 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_RX_DISABLE);
2176 }
2177 else
2178 {
2179 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_TX_DISABLE);
2180 }
2182 /* Empty the floating queue. Aborted request is currently enqueued *
2183 * in the floating queue. Dequeue the floating request in EDMA *
2184 * param table and return the actual transfer element count */
2185 while (TRUE != Mcbsp_osalQueueEmpty(chanHandle->ptrQFloatList))
2186 {
2187 ioBuf = (Mcbsp_IOBuf *) Mcbsp_osalQueueGet(chanHandle->ptrQFloatList);
2189 if (NULL != ioBuf)
2190 {
2191 /* if FLUSH cmd called for INPUT channel then status is equal *
2192 * to FLUSHED otherwise status is equal to ABORTED */
2193 if ((TRUE == chanHandle->flush) &&
2194 (MCBSP_MODE_INPUT == chanHandle->mode))
2195 {
2196 ioBuf->status = MCBSP_STATUS_FLUSHED;
2197 }
2198 else
2199 {
2200 ioBuf->status = MCBSP_STATUS_ABORTED;
2201 }
2203 if ((NULL != chanHandle->cbFxn) && (NULL != chanHandle->cbArg))
2204 {
2205 /* Application callback */
2206 (*chanHandle->cbFxn)((void*)chanHandle->cbArg,ioBuf);
2207 }
2208 /* Decrement the submit count */
2209 chanHandle->submitCount--;
2210 }
2211 }
2213 /* Empty the pending queue */
2214 while (TRUE != Mcbsp_osalQueueEmpty(chanHandle->ptrQPendList))
2215 {
2216 ioBuf = (Mcbsp_IOBuf *) Mcbsp_osalQueueGet(chanHandle->ptrQPendList);
2218 if (NULL != ioBuf)
2219 {
2220 /* if FLUSH cmd called for INPUT channel then status is equal *
2221 * to MCBSP_STATUS_FLUSHED otherwise status is equal to MCBSP_STATUS_ABORTED */
2222 if ((TRUE == chanHandle->flush) &&
2223 (MCBSP_MODE_INPUT == chanHandle->mode))
2224 {
2225 ioBuf->status = MCBSP_STATUS_FLUSHED;
2226 }
2227 else
2228 {
2229 ioBuf->status = MCBSP_STATUS_ABORTED;
2230 }
2232 if ((NULL != chanHandle->cbFxn) && (NULL != chanHandle->cbArg))
2233 {
2234 /* Application callback */
2235 (*chanHandle->cbFxn)((void*)chanHandle->cbArg,ioBuf);
2236 }
2238 /* Decrement the submit count */
2239 chanHandle->submitCount--;
2240 }
2241 }
2243 /* As EDMA is disabled it might have thrown an error and set error bit*
2244 * Clear the error bit to enable the transfer again */
2245 EDMA3_DRV_clearErrorBits(chanHandle->edmaHandle,chanHandle->xferChan);
2247 /* Configure the EDMA channel and EDMA param tables with *
2248 * intialization configuration as they are configured at the *
2249 * create time. */
2250 Mcbsp_localEdmaChanPaRAMsetup(chanHandle);
2252 #ifdef MCBSP_LOOPJOB_ENABLE
2254 /* configure the FIFO for the specific channel */
2255 if (TRUE == chanHandle->enableHwFifo)
2256 {
2257 /* Disable and enable the FIFO so that the events are *
2258 * generated to the Mcbsp for the first time */
2259 mcbspConfigureFifo(&instHandle->hwInfo,chanHandle,FALSE);
2260 mcbspConfigureFifo(&instHandle->hwInfo,chanHandle,TRUE);
2261 }
2263 /* Enable the EDMA transfer to start the Loop job running */
2264 EDMA3_DRV_enableTransfer(
2265 chanHandle->edmaHandle,
2266 chanHandle->xferChan,
2267 EDMA3_DRV_TRIG_MODE_EVENT);
2269 chanHandle->loopjobUpdatedinParamset = TRUE;
2270 chanHandle->nextLinkParamSetToBeUpdated = 0;
2272 /* start the Mcbsp channel */
2273 if (MCBSP_MODE_INPUT == chanHandle->mode)
2274 {
2275 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_RX_ENABLE);
2276 }
2277 else
2278 {
2279 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_TX_ENABLE);
2280 }
2281 #endif
2282 }
2283 /* critical section ends */
2284 Mcbsp_osalExitSingleCoreCriticalSection(criticalSectionInfo);
2285 }
2286 /**
2287 *
2288 * \brief This function configures the Hardware FIFO
2289 *
2290 * \param hMcbsp [IN] pointer to the Mcbsp Hardware information struct
2291 * \param chanHandle [IN] handle to the channel
2292 * \param enableHwFifo [IN] option to Enable or disbale the FIFO
2293 *
2294 * \return None
2295 *
2296 * \enter hMcbsp is a valid non null pointer
2297 * chanHandle is a valid non null pointer
2298 *
2299 * \leave Not implemented
2300 *
2301 */
2302 void mcbspConfigureFifo(Mcbsp_HwInfo_Unpadded *hMcbsp,
2303 Mcbsp_ChannelObj *chanHandle,
2304 Bool enableHwFifo)
2305 {
2306 /* check if the HW FIFO usage is requested by the user for this channel */
2307 if (TRUE == enableHwFifo)
2308 {
2309 if (MCBSP_MODE_INPUT == chanHandle->mode)
2310 {
2311 /* configure the receive channel */
2312 /* Step 1 : configure the "WNUMDMA" and "WNUMEVT" bits before *
2313 * enabling the FIFO */
2314 hMcbsp->fifoRegs->RFIFOCTL =
2315 (1 << CSL_BFIFO_RFIFOCTL_RNUMEVT_SHIFT);
2317 hMcbsp->fifoRegs->RFIFOCTL |=
2318 (CSL_BFIFO_RFIFOCTL_RNUMDMA_1WORDS
2319 << CSL_BFIFO_RFIFOCTL_RNUMDMA_SHIFT);
2321 /* enable the FIFO now by setting the "WENA" bit */
2322 hMcbsp->fifoRegs->RFIFOCTL |=
2323 (CSL_BFIFO_RFIFOCTL_RENA_ENABLED
2324 << CSL_BFIFO_RFIFOCTL_RENA_SHIFT);
2325 }
2326 else
2327 {
2328 /* configure the transmit channel */
2329 /* Step 1 : configure the "WNUMDMA" and "WNUMEVT" bits before *
2330 * enabling the FIFO */
2331 hMcbsp->fifoRegs->WFIFOCTL =
2332 (1 << CSL_BFIFO_WFIFOCTL_WNUMEVT_SHIFT);
2334 hMcbsp->fifoRegs->WFIFOCTL |=
2335 (CSL_BFIFO_WFIFOCTL_WNUMDMA_1WORDS
2336 << CSL_BFIFO_WFIFOCTL_WNUMDMA_SHIFT);
2338 /* enable the FIFO now by setting the "WENA" bit */
2339 hMcbsp->fifoRegs->WFIFOCTL |=
2340 (CSL_BFIFO_WFIFOCTL_WENA_ENABLED
2341 << CSL_BFIFO_WFIFOCTL_WENA_SHIFT);
2342 }
2343 }
2344 else
2345 {
2346 /* FIFO needs to be disabled */
2347 if (MCBSP_MODE_INPUT == chanHandle->mode)
2348 {
2349 /* disable the FIFO now by resetting the "WENA" bit */
2350 hMcbsp->fifoRegs->RFIFOCTL =
2351 (CSL_BFIFO_RFIFOCTL_RENA_DISABLED
2352 << CSL_BFIFO_RFIFOCTL_RENA_SHIFT);
2353 }
2354 else
2355 {
2356 /* disable the FIFO now by resetting the "WENA" bit */
2357 hMcbsp->fifoRegs->WFIFOCTL =
2358 (CSL_BFIFO_WFIFOCTL_WENA_DISABLED
2359 << CSL_BFIFO_WFIFOCTL_WENA_SHIFT);
2360 }
2361 }
2362 }
2364 /**
2365 * \brief This is going to complete the current request and abort
2366 * all other reqest.
2367 *
2368 * \param chanHandle [IN] Channel handle
2369 *
2370 * \return None
2371 *
2372 * \enter chanHandle is a valid non null pointer
2373 *
2374 * \leave Not implemented
2375 */
2376 void Mcbsp_localCancelAndAbortAllIo(Mcbsp_ChannelObj *chanHandle)
2377 {
2378 chanHandle->submitCount--;
2379 chanHandle->tempIOBuf->status = MCBSP_STATUS_ABORTED;
2381 Mcbsp_localCompleteCurrentIo(chanHandle);
2383 Mcbsp_localAbortReset(chanHandle);
2384 }
2386 #ifndef MCBSP_LOOPJOB_ENABLE
2387 /**
2388 * \brief This function waits for the FIFO to be emptied(if enabled) and the
2389 * TX empty bit to be set so that the TX section could be disabled when
2390 * there is no data present.
2391 *
2392 * \param arg0 [IN] Handle to the TX channel
2393 * \param arg1 [IN] unused
2394 *
2395 * \return None
2396 *
2397 * \enter arg0 is a valid non null pointer
2398 *
2399 * \leave Not implemented
2400 */
2401 void Mcbsp_TxFifo(int32_t arg0, int32_t arg1)
2402 {
2403 Mcbsp_ChannelObj *chanHandle = NULL;
2404 Mcbsp_Object *hInst = NULL;
2405 Mcbsp_Object_Unpadded *instHandle = NULL;
2406 uint32_t timeOut = 0x00;
2407 void* criticalSectionInfo;
2409 chanHandle = (Mcbsp_ChannelObj *)arg0;
2410 hInst = (Mcbsp_Object *)arg1;
2411 instHandle = (Mcbsp_Object_Unpadded *)&(hInst->obj);
2413 /* critical section starts */
2414 criticalSectionInfo = Mcbsp_osalEnterSingleCoreCriticalSection();
2416 /* update the timeout value from the instance handle */
2417 timeOut = instHandle->retryCount;
2419 /* we have come here means that the Mcbsp has got an callback but it *
2420 * did have any more buffer to load Hence here we will wait for the *
2421 * FIFO to become empty (if FIFO is enabled) else wait for the TX to *
2422 * become empty.then we will disable the TX section */
2423 if (TRUE == chanHandle->enableHwFifo)
2424 {
2425 while ((0 != (instHandle->hwInfo.fifoRegs->WFIFOSTS &
2426 CSL_BFIFO_WFIFOSTS_WLVL_MASK))
2427 && (0 != timeOut))
2428 {
2429 /* reduce the timeout count and check if the FIFO is empty */
2430 timeOut--;
2431 }
2432 }
2434 /* reinitialize the retry count */
2435 timeOut = instHandle->retryCount;
2437 while ((CSL_MCBSP_SPCR_XEMPTY_MASK ==
2438 (instHandle->hwInfo.regs->SPCR & CSL_MCBSP_SPCR_XEMPTY_MASK))
2439 && (0 != timeOut))
2440 {
2441 /* reduce the retry count and check if the TX has completed *
2442 * transmitting all the bytes */
2443 timeOut--;
2444 }
2446 /* we need to stop the frame sycn generator now.But also need to check *
2447 * if 1.The frame sycn generator is actually started By TX. *
2448 * 2.The RX is not feeding of the sample rate generator */
2449 if ((TRUE == instHandle->txFsgEnable) &&
2450 ((TRUE != instHandle->rxFsgEnable)
2451 || (TRUE == instHandle->stopSmFsRcv)))
2452 {
2453 /* Now we can disable the frame sync generator */
2454 Mcbsp_localResetCtrl(
2455 (Mcbsp_Object_Unpadded *)&(chanHandle->devHandle->obj),
2456 Mcbsp_SpcrCtrl_FSYNC_DISABLE);
2457 instHandle->fsgEnabled = FALSE;
2458 }
2460 /* Stop the TX section */
2461 Mcbsp_localResetCtrl(
2462 (Mcbsp_Object_Unpadded *)&(chanHandle->devHandle->obj),
2463 Mcbsp_SpcrCtrl_TX_DISABLE);
2465 /* Transmit state machine is stopped */
2466 instHandle->stopSmFsXmt = TRUE;
2468 /* clear the error bits in the EDMA(as this is the last buffer) */
2469 EDMA3_DRV_clearErrorBits(
2470 chanHandle->edmaHandle,
2471 chanHandle->xferChan);
2473 /* complete the IOP now and call the callback to the stream */
2474 chanHandle->tempIOBuf = (Mcbsp_IOBuf *) Mcbsp_osalQueueGet(chanHandle->ptrQFloatList);
2476 /* Decrement the submit count for the IO buffers */
2477 chanHandle->submitCount--;
2479 chanHandle->isTempIOBufValid = TRUE;
2480 chanHandle->tempIOBuf->status = chanHandle->currentError;
2481 Mcbsp_localCompleteCurrentIo(chanHandle);
2483 /* critical section ends */
2484 Mcbsp_osalExitSingleCoreCriticalSection(criticalSectionInfo);
2487 }
2488 #endif /* #ifndef MCBSP_LOOPJOB_ENABLE */
2491 /**
2492 * \brief This function toggles the index of the edma params
2493 *
2494 * \param index [IN] pointer to current index
2495 *
2496 * \return None
2497 *
2498 * \enter index is a valid non null pointer
2499 *
2500 * \leave Not implemented
2501 */
2502 void Mcbsp_localGetNextIndex(uint32_t *index)
2503 {
2504 *index = (((*index) + 1u) & 0x01u);
2505 }
2507 /**
2508 * \brief This function loads the buffers to the actual EDMA paramset.
2509 *
2510 * \param chanHandle [IN] Handle to channel.
2511 * \param ioBuf [IN] pointer to the ioBuf
2512 *
2513 * \return None
2514 *
2515 * \enter Not implemented
2516 *
2517 * \leave Not implemented
2518 */
2519 void Mcbsp_localLoadPktToEdma(Mcbsp_ChannelObj *chanHandle,Mcbsp_IOBuf *ioBuf)
2520 {
2521 #ifndef MCBSP_LOOPJOB_ENABLE
2522 Mcbsp_Object_Unpadded *instHandle = NULL;
2523 #endif
2524 int32_t status = MCBSP_STATUS_COMPLETED;
2526 #ifndef MCBSP_LOOPJOB_ENABLE
2527 instHandle = (Mcbsp_Object_Unpadded *)&(chanHandle->devHandle->obj);
2528 #endif
2530 chanHandle->currentDataSize = (uint16_t)ioBuf->size;
2531 chanHandle->userDataBufferSize = (uint32_t)ioBuf->size;
2533 #ifdef MCBSP_LOOPJOB_ENABLE
2534 if (Mcbsp_MAXLINKCNT == chanHandle->submitCount)
2535 {
2536 #else
2537 /* The second and the third buffer will go the link paramsets */
2538 if (Mcbsp_MAXLINKCNT <= chanHandle->submitCount)
2539 {
2540 #endif
2541 /* Though we have to post to param set directly from here, *
2542 * there will be differene between first such buffer and *
2543 * second buffer. As we have control here we are second buffer *
2544 * and first buffer has not yet returned (or corresponding *
2545 * edma callback has not been called.For second buffer, we *
2546 * will be updating the second param set, which is currently *
2547 * hosting loopjob parameter. Hence increment the index to *
2548 * point second paramset and since we are moving out loopjob *
2549 * from both param sets, the loopjobUpdatedinParamset is reset */
2550 chanHandle->loopjobUpdatedinParamset = FALSE;
2551 Mcbsp_localGetNextIndex(
2552 &chanHandle->nextLinkParamSetToBeUpdated);
2553 }
2555 /* Now update the data buffer to the link params. The paramset to *
2556 * be updated is decidec by the "nextLinkParamSetToBeUpdated" */
2557 if (MCBSP_STATUS_COMPLETED != Mcbsp_localUpdtDtPktToLnkPrms(chanHandle,ioBuf))
2558 {
2559 status = MCBSP_ERR_BADIO;
2560 }
2562 if ((1u == chanHandle->submitCount) && (MCBSP_STATUS_COMPLETED == status))
2563 {
2564 #ifdef MCBSP_LOOPJOB_ENABLE
2565 /* if at all this is the very first buffer, then one param set *
2566 * has loop job loaded , self linked and active with the main *
2567 * xfer channel param. other param set is ready loaded (just *
2568 * now)and has link param set as the one having loopjob (this *
2569 * is to ensure that if at all we are not getting any more *
2570 * buffers loopjob be will taken over). Now we have to link *
2571 * the floating / newly loaded param set to xfer channel. */
2572 if (MCBSP_STATUS_COMPLETED != EDMA3_DRV_linkChannel(
2573 chanHandle->edmaHandle,
2574 chanHandle->xferChan,
2575 chanHandle->pramTbl[chanHandle->nextLinkParamSetToBeUpdated]))
2576 {
2577 status = MCBSP_ERR_BADIO;
2578 }
2579 #else
2580 /* configure the FIFO for the specific channel */
2581 if (TRUE == chanHandle->enableHwFifo)
2582 {
2583 /* Disable and enable the FIFO so that the events are *
2584 * generated to the Mcbsp for the first time */
2585 mcbspConfigureFifo(&instHandle->hwInfo,chanHandle,FALSE);
2586 mcbspConfigureFifo(&instHandle->hwInfo,chanHandle,TRUE);
2587 }
2589 /* enable the EDMA transfer for the channel so that it is *
2590 * ready to transfer the data as soon as the state machine is *
2591 * enabled */
2592 EDMA3_DRV_enableTransfer(
2593 chanHandle->edmaHandle,
2594 chanHandle->xferChan,
2595 EDMA3_DRV_TRIG_MODE_EVENT);
2597 /* Start the McBSP hardware */
2598 if (MCBSP_MODE_INPUT == chanHandle->mode)
2599 {
2600 instHandle->stopSmFsRcv = FALSE;
2601 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_RX_ENABLE);
2602 }
2603 else
2604 {
2605 instHandle->stopSmFsXmt = FALSE;
2606 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_TX_ENABLE);
2607 }
2609 if (((MCBSP_MODE_INPUT == chanHandle->mode) &&
2610 (TRUE == instHandle->rxFsgEnable)) ||
2611 ((MCBSP_MODE_OUTPUT == chanHandle->mode) &&
2612 (TRUE == instHandle->txFsgEnable)))
2613 {
2614 /* enable the sample rate generator */
2615 Mcbsp_localResetCtrl(
2616 instHandle,
2617 Mcbsp_SpcrCtrl_FSYNC_ENABLE);
2618 }
2619 #endif /* MCBSP_LOOPJOB_ENABLE */
2620 }
2621 }
2623 /**
2624 * \brief Function to modify the sample rate generator configuration
2625 *
2626 * \param chanHandle [IN] Handle to the channel
2627 * \param arg [IN] pointer to the srg config setup
2628 *
2629 * \return None
2630 */
2631 int32_t Mcbsp_localModifySampleRate(Mcbsp_ChannelObj *chanHandle,void* arg)
2632 {
2633 Mcbsp_Object_Unpadded *instHandle = NULL;
2634 Mcbsp_ClkSetup *clkConfig = NULL;
2635 int32_t status = MCBSP_STATUS_COMPLETED;
2637 if ((NULL == arg) || (NULL == chanHandle))
2638 {
2639 return MCBSP_ERR_BADARGS;
2640 }
2642 instHandle = &(chanHandle->devHandle->obj);
2643 if (NULL == instHandle)
2644 {
2645 return MCBSP_ERR_BADARGS;
2646 }
2648 clkConfig = (Mcbsp_ClkSetup *)arg;
2650 /* check if the Frame sync clock is generated by the module */
2651 if (TRUE == instHandle->srgConfigured)
2652 {
2653 /* Configure the McBSP with user supplied parameters */
2654 chanHandle->clkSetup = *(clkConfig);
2655 instHandle->srgConfigured = FALSE;
2657 /* stop the sample rate generator */
2658 if (TRUE == instHandle->srgEnabled)
2659 {
2660 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_SRG_DISABLE);
2662 status = Mcbsp_localConfigureSrgr(instHandle,chanHandle);
2664 if (MCBSP_STATUS_COMPLETED == status)
2665 {
2666 /* enable the sample rate generator */
2667 Mcbsp_localResetCtrl(
2668 instHandle,
2669 Mcbsp_SpcrCtrl_SRG_ENABLE);
2671 /* wait for the 2CLKG clock cycles */
2672 Mcbsp_osalWaitNBitClocks(2u);
2673 }
2675 /* clear the XSYNCERR (to be done only if TX is used) */
2676 if (MCBSP_MODE_OUTPUT == chanHandle->mode)
2677 {
2678 /* Enable the TX section */
2679 Mcbsp_localResetCtrl(
2680 instHandle,
2681 Mcbsp_SpcrCtrl_TX_ENABLE);
2683 /* wait for 2 CLKR or CLX cycles */
2684 Mcbsp_osalWaitNBitClocks(2u);
2686 /* Disable the TX section to clear any XYNCERR */
2687 Mcbsp_localResetCtrl(
2688 instHandle,
2689 Mcbsp_SpcrCtrl_TX_DISABLE);
2690 }
2691 }
2692 }
2693 else
2694 {
2695 status = MCBSP_ERR_BADMODE;
2697 if (MCBSP_MODE_INPUT == chanHandle->mode)
2698 {
2699 if (TRUE != instHandle->rxSrgEnable)
2700 {
2701 /* Since this mode does not use the sample rate generator, so
2702 * there is no point in changing the sample rate. So return
2703 * with success*/
2704 status = MCBSP_STATUS_COMPLETED;
2705 }
2706 }
2707 else
2708 {
2709 if (TRUE != instHandle->txSrgEnable)
2710 {
2711 /* Since this mode does not use the sample rate generator, so
2712 * there is no point in changing the sample rate. So return
2713 * with success*/
2714 status = MCBSP_STATUS_COMPLETED;
2715 }
2716 }
2717 }
2718 return (status);
2719 }
2721 /* ========================================================================== */
2722 /* END OF FILE */
2723 /* ========================================================================== */