1 /*
2 * mcbsp_ioctl.c
3 *
4 * This file contains local functions for McBSP driver which contain implemen-
5 * tation for control operation specifc for the McBSP peripheral.
6 *
7 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
8 *
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 *
17 * Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the
20 * distribution.
21 *
22 * Neither the name of Texas Instruments Incorporated nor the names of
23 * its contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 *
38 */
40 /* ========================================================================== */
41 /* INCLUDE FILES */
42 /* ========================================================================== */
44 /* MCBSP CSL-RL */
45 #include <ti/csl/cslr_mcbsp.h>
47 /* MCBSP Types includes */
48 #include <mcbsp_types.h>
50 /* MCBSP LLD includes */
51 #include <ti/drv/mcbsp/mcbsp_drv.h>
52 #include <ti/drv/mcbsp/include/mcbsp_pvt.h>
54 /* MCBSP OSAL layer */
55 #include <mcbsp_osal.h>
57 #ifdef MCBSP_LOOPJOB_ENABLE
58 extern far Mcbsp_TempBuffer Mcbsp_loopDstBuf[CSL_MCBSP_PER_CNT];
59 extern far Mcbsp_TempBuffer Mcbsp_loopSrcBuf[CSL_MCBSP_PER_CNT];
60 #endif
62 /* ========================================================================== */
63 /* FUNCTION DEFINTIONS */
64 /* ========================================================================== */
66 /**
67 * \brief Implements the IOCTLS for McBSP driver.
68 *
69 * This function implements the McBSP device specific control operations
70 * including Start/Stop, Pause/Resume, Channel and Device Reset,
71 * Mute-ON/OFF, McBSP sample rate generator configuration etc.
72 *
73 * \param chanHandle [IN] Handle to channel
74 * \param cmd [IN] Control command number
75 * \param arg [IN] Arguments for control command
76 * \param param [IN] user defined data structure
77 *
78 * \return MCBSP_STATUS_COMPLETED in case of sucess.
79 * MCBSP_ERR_NOTIMPL in case the command is not supported.
80 * MCBSP driver error code in case of any error.
81 */
82 int32_t Mcbsp_localSubmitIoctl(Mcbsp_ChannelObj *chanHandle,
83 Mcbsp_IOCTL cmd,
84 void* arg,
85 void* param)
86 {
87 Mcbsp_Object_Unpadded *instHandle = NULL;
88 Mcbsp_srgConfig *srgConfig = NULL;
89 int32_t status = MCBSP_STATUS_COMPLETED;
90 #ifdef MCBSP_LOOPJOB_ENABLE
91 Mcbsp_IOBuf *ioBuf = NULL;
92 uint16_t linkCnt = 0;
93 Mcbsp_ChanParams *params = NULL;
94 #endif
96 if ((NULL == chanHandle) || (NULL == chanHandle->devHandle))
97 {
98 return MCBSP_ERR_BADARGS;
99 }
101 instHandle = &(chanHandle->devHandle->obj);
102 if (NULL == instHandle)
103 {
104 return MCBSP_ERR_BADARGS;
105 }
107 /* To remove compiler warning */
108 param = param;
110 /********************command to start the Mcbsp section********************/
111 if (Mcbsp_IOCTL_START == cmd)
112 {
113 /* stop the Mcbsp channel */
114 if (MCBSP_MODE_INPUT == chanHandle->mode)
115 {
116 if (TRUE == instHandle->stopSmFsRcv)
117 {
118 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_RX_ENABLE);
119 instHandle->stopSmFsRcv = FALSE;
120 }
121 else
122 {
123 /* Already stop port command is issued. This is a redundant *
124 * command. */
125 status = MCBSP_ERR_BADARGS;
126 }
127 }
128 else
129 {
130 if (TRUE == instHandle->stopSmFsXmt)
131 {
132 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_TX_ENABLE);
133 instHandle->stopSmFsXmt = FALSE;
134 }
135 else
136 {
137 /* Already stop port command is issued. This is a redundant *
138 * command. */
139 status = MCBSP_ERR_BADARGS;
140 }
141 }
142 }
144 /********************command to stop the Mcbsp section*********************/
145 else if (Mcbsp_IOCTL_STOP == cmd)
146 {
147 /* abort all the buffers in the driver */
148 Mcbsp_localAbortReset(chanHandle);
150 /* stop the hardware */
151 if (MCBSP_MODE_INPUT == chanHandle->mode)
152 {
153 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_RX_DISABLE);
154 instHandle->stopSmFsRcv = TRUE;
155 }
156 else
157 {
158 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_TX_DISABLE);
159 instHandle->stopSmFsXmt = TRUE;
160 }
161 }
162 /****************command to start sample rate generator********************/
163 else if (Mcbsp_IOCTL_SRGR_START == cmd)
164 {
165 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_SRG_ENABLE);
166 }
167 /*****************command to stop sample rate generator********************/
168 else if (Mcbsp_IOCTL_SRGR_STOP == cmd)
169 {
170 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_SRG_DISABLE);
171 }
172 /*****************command to start frame sync generator********************/
173 else if (Mcbsp_IOCTL_FSGR_START == cmd)
174 {
175 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_FSYNC_ENABLE);
176 }
177 else if (Mcbsp_IOCTL_FSGR_STOP == cmd)
178 {
179 Mcbsp_localResetCtrl(instHandle,Mcbsp_SpcrCtrl_FSYNC_DISABLE);
180 }
181 /******************command to configure the clock polarity*****************/
182 else if (Mcbsp_IOCTL_SET_BCLK_POL == cmd)
183 {
184 if (NULL == arg)
185 {
186 return MCBSP_ERR_BADARGS;
187 }
189 if (MCBSP_MODE_INPUT == chanHandle->mode)
190 {
191 if (Mcbsp_ClkPol_FALLING_EDGE == (Mcbsp_ClkPol)(*(uint32_t *)arg))
192 {
193 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_CLKRP_MASK);
194 }
195 else
196 {
197 instHandle->hwInfo.regs->PCR |= CSL_MCBSP_PCR_CLKRP_MASK;
198 }
199 }
200 else
201 {
202 if (Mcbsp_ClkPol_FALLING_EDGE == (Mcbsp_ClkPol)(*(uint32_t *)arg))
203 {
204 instHandle->hwInfo.regs->PCR |= CSL_MCBSP_PCR_CLKXP_MASK;
205 }
206 else
207 {
208 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_CLKXP_MASK);
209 }
210 }
211 }
212 /*****************command to configure the frame sync polarity*************/
213 else if (Mcbsp_IOCTL_SET_FRMSYNC_POL == cmd)
214 {
215 if (MCBSP_MODE_INPUT == chanHandle->mode)
216 {
217 if (Mcbsp_FsPol_ACTIVE_LOW == (Mcbsp_FsPol)(*(uint32_t *)arg))
218 {
219 instHandle->hwInfo.regs->PCR |= CSL_MCBSP_PCR_FSRP_MASK;
220 }
221 else
222 {
223 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_FSRP_MASK);
224 }
225 }
226 else
227 {
228 if (Mcbsp_FsPol_ACTIVE_LOW == (Mcbsp_FsPol)(*(uint32_t *)arg))
229 {
230 instHandle->hwInfo.regs->PCR |= CSL_MCBSP_PCR_FSXP_MASK;
231 }
232 else
233 {
234 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_FSXP_MASK);
235 }
236 }
237 }
238 /****************** commmand to enable the sync error interrupt************/
239 else if (Mcbsp_IOCTL_SYNCERR_INT_ENABLE == cmd)
240 {
241 if (MCBSP_MODE_INPUT == chanHandle->mode)
242 {
243 instHandle->hwInfo.regs->SPCR |= CSL_MCBSP_SPCR_RINTM_MASK;
244 }
245 else
246 {
247 instHandle->hwInfo.regs->SPCR |= CSL_MCBSP_SPCR_XINTM_MASK;
248 }
249 }
250 /*****************command to enable disable the LOOP back mode*************/
251 else if (Mcbsp_IOCTL_LOOPBACK == cmd)
252 {
253 if (NULL != arg)
254 {
255 if (Mcbsp_Loopback_DISABLE == (Mcbsp_Loopback)(*(uint32_t *)arg))
256 {
257 instHandle->hwInfo.regs->SPCR |= (CSL_MCBSP_SPCR_DLB_MASK);
258 }
259 else
260 {
261 instHandle->hwInfo.regs->SPCR &= (~CSL_MCBSP_SPCR_DLB_MASK);
262 }
263 }
264 else
265 {
266 status = MCBSP_ERR_BADARGS;
267 }
268 }
269 /*********************command to set the bit clock mode *******************/
270 else if (Mcbsp_IOCTL_SET_CLKMODE == cmd)
271 {
272 if (MCBSP_MODE_INPUT == chanHandle->mode)
273 {
274 /* configure the clock mode (external or internal) */
275 if (Mcbsp_TxRxClkMode_EXTERNAL == (Mcbsp_TxRxClkMode)(*(Uint8 *)arg))
276 {
277 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_CLKRM_MASK);
279 if (TRUE == instHandle->rxFsgEnable)
280 {
281 /* frame sync generator is using the internal clock hence *
282 * need to enable the sample rate generator */
283 instHandle->rxSrgEnable = TRUE;
284 }
285 else
286 {
287 /* dont require to enable the sample rate generator */
288 instHandle->rxSrgEnable = FALSE;
289 }
290 }
291 else
292 {
293 /* external mode clock */
294 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_CLKRM_MASK);
296 /* sample rate generator is enabled */
297 instHandle->rxSrgEnable = TRUE;
298 }
300 }
301 else
302 {
303 /* configure the clock mode (external or internal) */
304 if (Mcbsp_TxRxClkMode_EXTERNAL == (Mcbsp_TxRxClkMode)(*(Uint8 *)arg))
305 {
306 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_CLKXM_MASK);
308 if (TRUE == instHandle->txFsgEnable)
309 {
310 /* frame sync generator is using the internal clock hence *
311 * need to enable the sample rate generator */
312 instHandle->txSrgEnable = TRUE;
313 }
314 else
315 {
316 /* dont require to enable the sample rate generator */
317 instHandle->txSrgEnable = FALSE;
318 }
319 }
320 else
321 {
322 /* external mode clock enabled */
323 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_CLKXM_MASK);
325 /* sample rate generator is enabled */
326 instHandle->txSrgEnable = TRUE;
327 }
328 }
329 }
331 /******************** Command to set the frame sycn mode*******************/
332 else if (Mcbsp_IOCTL_SET_FRMSYNCMODE == cmd)
333 {
334 /* Reciever Bit Clock mode */
335 if (MCBSP_MODE_INPUT == chanHandle->mode)
336 {
337 /* check if the frame sync generator is to be enabled for section */
338 if (Mcbsp_FsClkMode_INTERNAL == (Mcbsp_FsClkMode)(*(Uint8 *)arg))
339 {
340 /* set the frame sync generation mode */
341 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_FSRM_MASK);
343 /* frame sync generator needs to be enabled */
344 instHandle->rxFsgEnable = TRUE;
345 }
346 else
347 {
348 /* reset the frame sync generation mode */
349 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_FSRM_MASK);
351 /* frame sync generator needs to be disabled */
352 instHandle->rxFsgEnable = FALSE;
353 }
354 }
355 else
356 {
357 /* check if the frame sync generator is to be enabled for section */
358 if (Mcbsp_FsClkMode_EXTERNAL == (Mcbsp_FsClkMode)(*(Uint8 *)arg))
359 {
360 /* External frame sync to be used */
361 instHandle->hwInfo.regs->PCR &= (~CSL_MCBSP_PCR_FSXM_MASK);
363 /* frame sync generator needs to be disabled */
364 instHandle->txFsgEnable = FALSE;
365 }
366 else
367 {
368 /* could be internal or configured for DXR to XSR copy */
369 if (Mcbsp_FsClkMode_INTERNAL == (Mcbsp_FsClkMode)(*(Uint8 *)arg))
370 {
371 /* internal frame sync to be used */
372 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_FSXM_MASK);
374 /* set the FSGM bit in the SRGR register */
375 instHandle->hwInfo.regs->SRGR |= (CSL_MCBSP_SRGR_FSGM_MASK);
377 /* frame sync generator needs to be enabled */
378 instHandle->txFsgEnable = TRUE;
379 }
380 else
381 { /* DXR to XSR copy generates frame sync */
382 /* internal frame sync to be used */
383 instHandle->hwInfo.regs->PCR |= (CSL_MCBSP_PCR_FSXM_MASK);
385 /* reset the FSGM bit in the SRGR register */
386 instHandle->hwInfo.regs->SRGR &= (~CSL_MCBSP_SRGR_FSGM_MASK);
388 /* frame sync generator needs to be disabled */
389 instHandle->txFsgEnable = FALSE;
390 }
391 }
392 }
393 }
394 /****************** command to configure the sample rate generator*********/
395 else if (Mcbsp_IOCTL_CONFIG_SRGR == cmd)
396 {
397 if (NULL == arg)
398 {
399 return MCBSP_ERR_BADARGS;
400 }
402 srgConfig = (Mcbsp_srgConfig *)(arg);
404 memcpy(&instHandle->srgrConfig,srgConfig,sizeof(Mcbsp_srgConfig));
406 Mcbsp_localConfigureSrgr(instHandle,chanHandle);
407 }
408 /********************command to reset the channel**************************/
409 else if ((Mcbsp_IOCTL_CHAN_RESET == cmd) || (MCBSP_CTRL_CHAN_RESET == cmd))
410 {
411 Mcbsp_localAbortReset(chanHandle);
412 }
413 /********************command to reset the device***************************/
414 else if ((Mcbsp_IOCTL_DEVICE_RESET == cmd) || (MCBSP_CTRL_DEVICE_RESET == cmd))
415 {
416 Mcbsp_localAbortReset(&instHandle->rcvObj);
417 Mcbsp_localAbortReset(&instHandle->xmtObj);
418 }
419 /********************command to change the sample rate*********************/
420 else if (Mcbsp_IOCTL_SAMPLE_RATE_CHANGE == cmd)
421 {
422 status = Mcbsp_localModifySampleRate(chanHandle,arg);
423 }
424 /********************command to cancel pending IO**************************/
425 else if (Mcbsp_IOCTL_CANCEL_PENDING_IO == cmd)
426 {
427 Mcbsp_localAbortReset(chanHandle);
428 }
429 #ifdef MCBSP_LOOPJOB_ENABLE
430 /****************command to pause the Mcbsp channel************************/
431 else if (Mcbsp_IOCTL_PAUSE == cmd)
432 {
433 if (FALSE == chanHandle->paused)
434 {
435 chanHandle->paused = TRUE;
436 }
437 else
438 {
439 status = MCBSP_ERR_BADMODE;
440 }
441 }
442 /***************** command to resume the Mcbsp channel*********************/
443 else if (Mcbsp_IOCTL_RESUME == cmd)
444 {
445 if (TRUE == Mcbsp_osalQueueEmpty(chanHandle->ptrQFloatList))
446 {
447 for (linkCnt = 0;linkCnt < Mcbsp_MAXLINKCNT;linkCnt++)
448 {
449 if (FALSE == Mcbsp_osalQueueEmpty(chanHandle->ptrQPendList))
450 {
451 ioBuf = (Mcbsp_IOBuf *)Mcbsp_osalQueueGet(chanHandle->ptrQPendList);
453 if (NULL == ioBuf)
454 {
455 return MCBSP_ERR_BADARGS;
456 }
458 /* floating queue not full . Process this request. */
459 Mcbsp_osalQueuePut(chanHandle->ptrQFloatList, (void*)ioBuf);
461 chanHandle->currentDataSize = (uint16_t)ioBuf->size;
462 chanHandle->userDataBufferSize = (uint32_t)ioBuf->size;
464 /* for DMA mode we will not use chanHandke->dataIOBuf *
465 * to hold current buffer - we use floatingqueue */
466 chanHandle->dataIOBuf = NULL;
468 if ((Mcbsp_MAXLINKCNT - 1u) == linkCnt)
469 {
470 /* Though we have to post to param set directly *
471 * from here,there will be differene between first *
472 * such buffer and second buffer. As we have control *
473 * here we are second buffer and first buffer has not *
474 * yet returned (or corresponding edma callback has *
475 * not been called.For second buffer, we will be *
476 * updating the second param set, which is currently *
477 * hosting loopjob parameter. Hence increment the *
478 * index to point second paramset and since we are *
479 * moving out loopjob from both param sets, the *
480 * oopjobUpdatedinParamset is reset */
481 chanHandle->loopjobUpdatedinParamset =FALSE;
482 Mcbsp_localGetNextIndex(
483 &chanHandle->nextLinkParamSetToBeUpdated);
484 }
486 /* Now update the data buffer to the link params. The *
487 * paramset to be updated is decidec by the *
488 * "nextLinkParamSetToBeUpdated" */
489 if (MCBSP_STATUS_COMPLETED !=
490 Mcbsp_localUpdtDtPktToLnkPrms(chanHandle,ioBuf))
491 {
492 status = MCBSP_ERR_BADIO;
493 break;
494 }
496 if (0 == linkCnt)
497 {
498 /* if at all this is the very first buffer, then *
499 * one param set has loop job loaded , self linked *
500 * and active with the main xfer channel param. *
501 * other param set is ready loaded (just now and *
502 * has link paramater set as the one having loopjob *
503 * (this is to ensure that if at all we are not *
504 * getting any more buffers loopjob be will taken *
505 * over). Now we have to link the floating / newly *
506 * loaded param set to xfer channel. */
507 status = EDMA3_DRV_linkChannel(
508 chanHandle->edmaHandle,
509 chanHandle->xferChan,
510 chanHandle->pramTbl[chanHandle->nextLinkParamSetToBeUpdated]);
512 if (MCBSP_STATUS_COMPLETED != status)
513 {
514 status = MCBSP_ERR_BADIO;
515 break;
516 }
517 else
518 {
519 EDMA3_DRV_enableTransfer(
520 chanHandle->edmaHandle,
521 chanHandle->xferChan,
522 EDMA3_DRV_TRIG_MODE_EVENT);
523 }
524 }
525 }
526 }
527 }
528 chanHandle->paused = FALSE;
529 }
530 /********************command to Mute the Mcbsp section*********************/
531 else if (Mcbsp_IOCTL_MUTE_ON == cmd)
532 {
533 if (MCBSP_MODE_OUTPUT == chanHandle->mode)
534 {
535 if(TRUE == chanHandle->bMuteON)
536 {
537 status = MCBSP_ERR_BADMODE;
538 }
539 else
540 {
541 chanHandle->bMuteON = (Bool)TRUE;
542 }
543 }
544 else
545 {
546 status = MCBSP_ERR_BADMODE;
547 }
548 }
549 /********************command to UnMute the Mcbsp section*******************/
550 else if (Mcbsp_IOCTL_MUTE_OFF == cmd)
551 {
552 /* Take out from the the Muted state */
553 if (MCBSP_MODE_OUTPUT == chanHandle->mode)
554 {
555 /* Check if mute is not ON */
556 if (FALSE == chanHandle->bMuteON)
557 {
558 status = MCBSP_ERR_BADARGS;
559 }
560 else
561 {
562 chanHandle->bMuteON =(Bool)FALSE;
563 }
564 }
565 else
566 {
567 status = MCBSP_ERR_NOTIMPL;
568 }
569 }
570 /********************command to Modify the loop job buffer*****************/
571 else if (Mcbsp_IOCTL_MODIFY_LOOPJOB == cmd)
572 {
573 params = (Mcbsp_ChanParams *)arg;
574 if (NULL == params)
575 {
576 return MCBSP_ERR_BADARGS;
577 }
579 if (NULL == params->userLoopJobBuffer)
580 {
581 if (MCBSP_MODE_OUTPUT == chanHandle->mode)
582 {
583 chanHandle->loopJobBuffer = &Mcbsp_loopSrcBuf[instHandle->instNum].scratchBuffer;
584 }
585 else
586 {
587 chanHandle->loopJobBuffer = &Mcbsp_loopDstBuf[instHandle->instNum].scratchBuffer;
588 }
589 chanHandle->userLoopJob = FALSE;
590 }
591 else
592 {
593 chanHandle->loopJobBuffer = params->userLoopJobBuffer;
595 if (chanHandle->roundedWordWidth > params->userLoopJobLength)
596 {
597 chanHandle->loopJobLength = chanHandle->roundedWordWidth;
598 }
599 else
600 {
601 chanHandle->loopJobLength = params->userLoopJobLength;
602 chanHandle->userLoopJobLength = params->userLoopJobLength;
603 chanHandle->userLoopJob = TRUE;
604 }
605 }
606 }
607 #endif
608 #ifndef MCBSP_LOOPJOB_ENABLE
609 /*****************command to modify the Timeout count value****************/
610 else if (Mcbsp_IOCTL_SET_TIMEOUT == cmd)
611 {
612 if (NULL == arg)
613 {
614 return MCBSP_ERR_BADARGS;
615 }
617 /* modify the retry count value to be used */
618 instHandle->retryCount = *(uint32_t *)arg;
619 }
620 #endif
621 else
622 {
623 status = MCBSP_ERR_NOTIMPL;
624 }
625 return (status);
626 }
628 /*============================================================================*/
629 /* END OF FILE */
630 /*============================================================================*/