f46ffd1b074c6178ed6969d44d416acce986a41e
2 /*
3 Copyright (c) 2016, Texas Instruments Incorporated - http://www.ti.com/
4 All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the
16 * distribution.
17 *
18 * Neither the name of Texas Instruments Incorporated nor the names of
19 * its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 */
36 /*
37 * ======== audioStreamInpProcNewIo.c ========
38 */
39 #include <xdc/runtime/Log.h>
40 #include <ti/sysbios/BIOS.h>
42 #include "procsdk_audio_typ.h"
43 #include "audioStreamInpProc.h"
44 #include "audioStreamProc_common.h"
45 #include "asperr.h"
47 #include "audk2g.h"
48 #include "audk2g_audio.h"
49 #include "mcasp_cfg.h"
50 #include "ioConfig.h" //TODO: remove this header
51 #include "ioBuff.h"
52 #include "ioPhy.h"
53 #include "ioData.h"
57 #define SYNC_PC_MASK 0x1F
58 #define SYNC_SUBTYPE_MASK 0x700
59 #define SYNC_SUBTYPE_SHIFT 8
60 #define SYNC_SUBTYPE_DTSHD 0x11
61 #define SYNC_DDP 0x15
62 #define SYNC_THD 0x16
64 #define IEC_HEADER_LENGTH 4
67 //table needed until PAF_SOURCE is reordered to match IEC numbering
68 const SmUns IECpafSource[23] =
69 {
70 PAF_SOURCE_UNKNOWN, // 0: IEC NULL Type
71 PAF_SOURCE_AC3, // 1: Comments on 1-15 match IEC 61937 part 2.
72 PAF_SOURCE_UNKNOWN, // 2: IEC reserved
73 PAF_SOURCE_UNKNOWN, // 3: IEC pause
74 PAF_SOURCE_UNKNOWN, // 4: MPEG 1 layer 1
75 PAF_SOURCE_MP3, // 5: MPEG layer 2 or 3
76 PAF_SOURCE_UNKNOWN, // 6: MPEG 2 data with extension
77 PAF_SOURCE_AAC, // 7: MPEG-2 AAC ADTS
78 PAF_SOURCE_UNKNOWN, // 8: MPEG 2 layer 1 low sampling frequency
79 PAF_SOURCE_UNKNOWN, // 9: MPEG 2 layer 2 or 3 low sampling frequency
80 PAF_SOURCE_UNKNOWN, // 10: reserved
81 PAF_SOURCE_DTS, // 11: DTS type 1 (11 bit: 512 sample repeat period)
82 PAF_SOURCE_DTS12, // 12: DTS type 2 (12 bit: 1024 sample repeat period)
83 PAF_SOURCE_DTS13, // 13: DTS type 3 (13 bit: 2048 sample repeat period)
84 PAF_SOURCE_DTS14, // 14: ATRAC
85 PAF_SOURCE_UNKNOWN, // 15: ATRAC 2/3
86 PAF_SOURCE_THD, // 16
87 PAF_SOURCE_DTSHD, // 17
88 PAF_SOURCE_WMA9PRO, // 18
89 PAF_SOURCE_UNKNOWN, // 19
90 PAF_SOURCE_UNKNOWN, // 20
91 PAF_SOURCE_DDP, // 21
92 PAF_SOURCE_THD, // 22
93 };
95 /*
96 * Functions defined in other files and to be put into proper header files
97 */
98 extern Void taskAsipFxnInit(const PAF_ASIT_Params *pP,const PAF_ASIT_Patchs *pQ);
101 // avoid including sap_d10.h, which would cause symbol redefinition
102 // warning (MCASP_PFUNC_XXX)
103 extern XDAS_Int32 D10_init();
104 extern XDAS_Int32 D10_RxControl(const void *pD10RxParams,
105 XDAS_Int32 code, XDAS_Int32 arg);
107 /*
108 * Functions only used in this file
109 */
110 int asipPrepareProcessing();
111 int asipIoCompsInit(PAF_AST_InpBuf * pInpBuf, PAF_AST_IoInp * pInpIo);
112 void asipProcInit(PAF_AST_IoInp *pInp);
113 void asipIoPhyPrime(PAF_AST_IoInp *pInpIo);
114 void asipPhyTransferPend(void);
115 void asipPhyTransferComplete(PAF_AST_IoInp * pInpIo);
116 void asipPhyTransferStart(PAF_AST_IoInp *pInpIo);
117 Int asipSelectDevices(const PAF_ASIT_Patchs *pQ, PAF_AST_IoInp *pInp);
118 Int asipUpdateInputStatus(const void *pRxParams, PAF_InpBufStatus *pStatus,
119 PAF_InpBufConfig *pInpBuf);
121 //Int asipDecideSource(const PAF_ASIT_Params *pP, PAF_AST_Config *pAstCfg, asipDecProc_t *pDec);
122 Int asipProcessing(PAF_AST_Config *pAstCfg, PAF_AST_IoInp *pInp);
123 void asipErrorHandling(PAF_AST_Config *pAstCfg, int asipErrno);
125 /*
126 * variables/structures to be put into proper global structures
127 */
128 extern Semaphore_Handle asipSemRx;
129 extern PAF_ASIT_Config gPAF_ASIT_config;
131 enum
132 {
133 ASIP_SOURCE_DETECTION,
134 ASIP_DECODE_BITSTREAM,
135 ASIP_SWITCH_TO_PCM,
136 ASIP_DECODE_PCM
137 };
139 enum
140 {
141 ASIP_INPUT_PREPARATION,
142 ASIP_INPUT_PROCESSING
143 };
145 #define ASIP_DEBUG
147 #ifdef ASIP_DEBUG
148 /* define the following as global variables for easy debugging */
149 int asipLoopCount1, asipLoopCount2;
150 Int asipErrno;
151 Int inputReadyForProcessing;
152 #endif
154 /*
155 * ======== taskAsipFxn ========
156 * Audio Stream Input Processing task function
157 */
158 #ifndef PASDK_SIO_DEV
159 #ifndef IO_LOOPBACK_TEST
160 Void taskAsipFxn( // ASIP task function for new I/O
161 #else
162 Void taskAsipFxn_NewIO_Not_Used( // not used for loopback test
163 #endif
164 #else
165 Void taskAsipFxn_NewIO_Not_USED( // not used for SIO/DEV based I/O
166 #endif
167 const PAF_ASIT_Params *pP,
168 const PAF_ASIT_Patchs *pQ)
169 {
170 PAF_ASIT_Config *pAsitCfg; /* ASIT configuration pointer */
171 PAF_AST_Config *pAstCfg; /* AST Common (shared) configuration pointer */
172 PAF_AST_IoInp *pInp; /* Input I/O components */
173 Int as; /* Audio Stream Number (1, 2, etc.) */
174 Int z; /* input/encode/stream/decode/output counter */
175 Int zMI;
176 #ifndef ASIP_DEBUG
177 int asipLoopCount1, asipLoopCount2;
178 Int asipErrno;
179 Int inputReadyForProcessing;
180 #endif
182 Log_info0("Enter taskAsipFxn()");
184 taskAsipFxnInit(pP, pQ); // initialization of input task
186 //
187 // Audio Stream Input Task Configuration (*pAsitCfg):
188 //
189 pAsitCfg = &gPAF_ASIT_config; // initialize pointer to task configuration
190 pAstCfg = pAsitCfg->pAstCfg; // pointer to AST common (shared) configuration
191 pInp = pAsitCfg->pIoInp; // pointer to input I/O components
193 /* Set Audio Stream Number (1, 2, etc.) */
194 as = pAstCfg->as;
196 //
197 // Determine decoder and stream indices associated with the master input
198 //
199 zMI = pP->zone.master;
201 pInp[zMI].numPrimeXfers = NUM_PRIME_XFERS;
202 //asipInitDebug(&pInp[zMI]);
204 for (z=STREAM1; z < STREAMN; z++)
205 {
206 TRACE_VERBOSE1("TaskAsip: AS%d: running", as+z);
207 }
209 TRACE_TERSE0("TaskAsip: Entering Main Loop.");
211 #if 0
212 // Wait until input device is ready - change this to event based scheduling
213 asipErrno = 0;
214 while (!inputReadyForProcessing)
215 {
216 // Indicate decoder no decoding yet
217 pP->fxns->sourceDecode(pP, pQ, pAsitCfg, PAF_SOURCE_NONE);
219 Task_sleep(5); // 5 system tick, or 5 msec. Should remove this later when implementing event based scheduling.
221 inputReadyForProcessing = asipPrepareProcessing(pP, pQ, pAsitCfg, &asipErrno);
223 if(asipErrno) {
224 asipErrorHandling(pAstCfg, asipErrno);
225 }
226 }
228 // .....................................................................
229 // At this point we have an enabled input and want to decode something.
230 // If no decoder selected then do nothing. Need to reset the sourceProgram, since
231 // when no decoder is selected there are no calls to IB
232 asipErrno = asipIoCompsInit(&pAstCfg->xInp[zMI], &pInp[zMI]);
233 if(asipErrno) {
234 printf("ASIP IO components init error!\n");
235 exit(0);
236 }
238 asipProcInit(&pInp[zMI]);
240 // start I/O physical layer by priming McASP LLD for input
241 asipIoPhyPrime(&pInp[zMI]);
243 //
244 // Main processing loop
245 //
246 asipErrno = 0;
247 for (;;)
248 {
249 // Pending on I/O PHY transfer
250 asipPhyTransferPend();
252 // Marks I/O PHY transfer and I/O BUFF write complete
253 asipPhyTransferComplete(&pInp[zMI]);
255 // Main function to process input data
256 asipErrno = asipProcessing(pAstCfg, &pInp[zMI]);
258 // Start next transfer
259 asipPhyTransferStart(&pInp[zMI]);
261 if(asipErrno) {
262 asipErrorHandling(pAstCfg, asipErrno);
263 }
264 }
265 #endif
267 #if 0
268 //
269 // Main processing loop
270 //
271 asipLoopCount1 = 0;
272 asipLoopCount2 = 0;
273 asipErrno = 0;
274 inputReadyForProcessing = FALSE;
275 for (;;)
276 {
277 asipLoopCount1++;
279 if(asipErrno) {
280 asipErrorHandling(pAstCfg, asipErrno);
282 inputReadyForProcessing = FALSE;
283 }
285 // Wait until input device is ready - change this to event based scheduling
286 if(!inputReadyForProcessing) {
287 // Indicate decoder no decoding yet
288 pP->fxns->sourceDecode(pP, pQ, pAsitCfg, PAF_SOURCE_NONE);
290 // 5 system tick, or 5 msec. Should remove this later when implementing
291 // event based scheduling.
292 Task_sleep(5);
294 inputReadyForProcessing = asipPrepareProcessing(pP, pQ, pAsitCfg, &asipErrno);
296 if (inputReadyForProcessing) {
297 // Input is ready for processing, so we initialize the I/O components
298 asipIoCompsInit(&pAstCfg->xInp[zMI], &pInp[zMI]);
300 // Initialize ASIP processing
301 asipProcInit(&pInp[zMI]);
303 // Start I/O physical layer by priming McASP LLD for input
304 asipIoPhyPrime(&pInp[zMI]);
305 }
306 else {
307 // Input is not ready, so go back to the beginning of the loop
308 continue;
309 }
310 } /* if(!inputReadyForProcessing) */
312 // Pending on I/O PHY transfer
313 asipPhyTransferPend();
315 // Marks I/O PHY transfer and I/O BUFF write complete
316 asipPhyTransferComplete(&pInp[zMI]);
318 // Main function to process input data
319 asipErrno = asipProcessing(pAstCfg, &pInp[zMI]);
321 // Start next transfer
322 asipPhyTransferStart(&pInp[zMI]);
324 asipLoopCount2++;
325 } // for (;;)
326 #endif
328 //
329 // Main processing loop
330 //
331 asipLoopCount1 = 0;
332 asipLoopCount2 = 0;
333 asipErrno = 0;
334 inputReadyForProcessing = FALSE;
335 pInp->asipState = ASIP_INPUT_PREPARATION;
337 for (;;)
338 {
339 asipLoopCount1++;
341 switch (pInp->asipState)
342 {
343 case ASIP_INPUT_PREPARATION:
344 // Indicate decoder no decoding yet
345 pP->fxns->sourceDecode(pP, pQ, pAsitCfg, PAF_SOURCE_NONE);
347 // 5 system tick, or 5 msec. Should remove this later when implementing
348 // event based scheduling.
349 Task_sleep(5);
351 inputReadyForProcessing = asipPrepareProcessing(pP, pQ, pAsitCfg, &asipErrno);
353 if (inputReadyForProcessing) {
354 // Input is ready for processing, so we initialize the I/O components
355 asipIoCompsInit(&pAstCfg->xInp[zMI], &pInp[zMI]);
357 // Initialize ASIP processing
358 asipProcInit(&pInp[zMI]);
360 // Start I/O physical layer by priming McASP LLD for input
361 asipIoPhyPrime(&pInp[zMI]);
363 pInp->asipState = ASIP_INPUT_PROCESSING;
364 }
365 break;
367 case ASIP_INPUT_PROCESSING:
368 // Pending on I/O PHY transfer
369 asipPhyTransferPend();
371 // Marks I/O PHY transfer and I/O BUFF write complete
372 asipPhyTransferComplete(&pInp[zMI]);
374 // Main function to process input data
375 asipErrno = asipProcessing(pAstCfg, &pInp[zMI]);
377 // Start next transfer
378 asipPhyTransferStart(&pInp[zMI]);
380 if(asipErrno) {
381 asipErrorHandling(pAstCfg, asipErrno);
383 pInp->asipState = ASIP_INPUT_PREPARATION;
384 }
386 break;
388 default:
389 break;
390 }
391 } // for (;;)
393 } /* taskAsipFxn */
395 extern const MdUns iecFrameLength[23];
396 extern Ptr hMcaspRxChan;
397 #define STRIDE_WORST_CASE 32 // 4-byte (32-bit) word, 2 slots, 4 serializers
400 /*===========================================================================
401 * ASIP processing preparation
402 * Output:
403 * - return TRUE (input is ready) or FALSE (input is not ready)
404 * - *asipErrno Error number
405 ============================================================================*/
406 Int asipPrepareProcessing(const PAF_ASIT_Params *pP,
407 const PAF_ASIT_Patchs *pQ,
408 PAF_ASIT_Config *pC,
409 Int *asipErrno)
410 {
411 Int as, zMS, zMI, zMD;
412 Int sourceConfig, mode;
413 PAF_AST_Config *pAstCfg;
414 PAF_AST_IoInp *pInp; /* I/O components for input */
416 pAstCfg = pC->pAstCfg; // pointer to AST common (shared) configuration
417 as = pAstCfg->as;
418 zMI = pP->zone.master;
419 zMD = pAstCfg->masterDec;
420 zMS = pAstCfg->masterStr;
421 pInp = pC->pIoInp; // pointer to input I/O components
423 *asipErrno = 0;
425 // Select source and initialize physical layer / HW interface
426 *asipErrno = asipSelectDevices(pQ, pInp);
427 if (*asipErrno) {
428 TRACE_TERSE2("TaskAsip: selectDevices returned asipErrno = 0x%04x at line %d. AS%d", *asipErrno, as+zMS);
429 return FALSE; // Input is not ready for processing due to error
430 }
432 // If no master input selected then we don't know what may be at the input,
433 // so set to unknown and skip any remaining processing
434 if (!pInp[zMI].pRxParams) {
435 sharedMemWriteInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceProgram),
436 (Int8)PAF_SOURCE_UNKNOWN, GATEMP_INDEX_DEC);
438 TRACE_VERBOSE1("TaskAsip: AS%d: No input selected...", as+zMS);
439 return FALSE; // No error, but input is not ready for processing
440 }
442 // If here then we have a valid input so query its status
443 *asipErrno = asipUpdateInputStatus(pInp[zMI].pRxParams,
444 &pAstCfg->xInp[zMI].inpBufStatus,
445 &pAstCfg->xInp[zMI].inpBufConfig);
446 if(*asipErrno) {
447 TRACE_VERBOSE1("TaskAsip: updateInputStatus returns 0x%x", *asipErrno);
448 return FALSE; // Input is not ready for processing due to error
449 }
451 // If master decoder is not enabled, or the input is unlocked, then do nothing
452 mode = (Int)sharedMemReadInt8(&(pAstCfg->xDec[zMD].decodeStatus.mode),
453 GATEMP_INDEX_DEC);
454 if (!mode || !pAstCfg->xInp[zMI].inpBufStatus.lock)
455 {
456 TRACE_VERBOSE0("TaskAsip: Not locked, continue");
457 return FALSE; // No error, but input is not ready for processing
458 }
460 // Check selected source: sourceSelect is set by another task, AIP or AFP
461 sourceConfig = (Int)sharedMemReadInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceSelect),
462 GATEMP_INDEX_DEC);
463 // If no source selected then do nothing
464 if(sourceConfig == PAF_SOURCE_NONE) {
465 sharedMemWriteInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceProgram),
466 (Int8)PAF_SOURCE_NONE, GATEMP_INDEX_DEC);
467 TRACE_VERBOSE1("TaskAsip: AS%d: no source selected, continue", as+zMS);
468 return FALSE; // No error, but input is not ready for processing
469 }
471 // If we want pass processing then proceed directly
472 if (sourceConfig == PAF_SOURCE_PASS)
473 {
474 TRACE_VERBOSE1("TaskAsip: AS%d: Pass processing ...", as+zMS);
475 sharedMemWriteInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceProgram),
476 (Int8)PAF_SOURCE_PASS, GATEMP_INDEX_DEC);
478 pP->fxns->sourceDecode(pP, pQ, pC, PAF_SOURCE_PASS);
479 if (pP->fxns->passProcessing) {
480 *asipErrno = pP->fxns->passProcessing(pP, pQ, pC, NULL);
481 }
482 else {
483 TRACE_TERSE2("TaskAsip: AS%d: Pass Processing not supported, asipErrno 0x%x", as+zMS, ASPERR_PASS);
484 *asipErrno = ASPERR_PASS;
485 }
487 TRACE_VERBOSE0("TaskAsip: continue");
488 return FALSE; // Error or not, input is not ready for processing
489 }
491 // No error and input processing is ready
492 return TRUE;
493 } /* asipPrepareProcessing */
495 /*===========================================================================
496 * Initialize I/O components for input processing
497 ============================================================================*/
498 int asipIoCompsInit(PAF_AST_InpBuf * pInpBuf, PAF_AST_IoInp * pInpIo)
499 {
500 // Initialize I/O BUFF and I/O PHY components for input task
501 ioBuffParams_t ioBuffParams;
502 ioPhyParams_t ioPhyParams;
503 ioDataParam_t ioDataCfg;
505 ioBuffParams.base = pInpBuf->inpBufConfig.base.pVoid;
506 ioBuffParams.size = pInpBuf->inpBufConfig.allocation/STRIDE_WORST_CASE*STRIDE_WORST_CASE;
507 ioBuffParams.sync = IOBUFF_WRITE_SYNC;
508 ioBuffParams.nominalDelay = INPUT_FRAME_SIZE_DEF;
509 if(ioBuffInit(pInpIo->hIoBuff, &ioBuffParams) != IOBUFF_NOERR) {
510 return (-1); // to remove magic number
511 }
513 ioPhyParams.ioBuffHandle = pInpIo->hIoBuff;
514 ioPhyParams.xferFrameSize = INPUT_FRAME_SIZE_DEF;
515 ioPhyParams.mcaspChanHandle = hMcaspRxChan;
516 ioPhyParams.ioBuffOp = IOPHY_IOBUFFOP_WRITE;
517 if(ioPhyInit(pInpIo->hIoPhy, &ioPhyParams) != IOPHY_NOERR) {
518 return (-1); // to remove magic number
519 }
521 ioDataCfg.ioBuffHandle = pInpIo->hIoBuff;
522 ioDataCfg.unknownSourceTimeOut = pInpBuf->inpBufConfig.pBufStatus->unknownTimeout;
523 ioDataCfg.frameLengthsIEC = (uint_least16_t *)&iecFrameLength[0];
524 ioDataCfg.frameLengthPCM = INPUT_FRAME_SIZE_PCM / WORD_SIZE_PCM;
525 ioDataCfg.frameLengthDef = INPUT_FRAME_SIZE_DEF / WORD_SIZE_BITSTREAM;
526 ioDataCfg.ibMode = pInpBuf->inpBufConfig.pBufStatus->mode;
527 ioDataCfg.zeroRunRestart = pInpBuf->inpBufConfig.pBufStatus->zeroRunRestart;
528 ioDataCfg.zeroRunTrigger = pInpBuf->inpBufConfig.pBufStatus->zeroRunTrigger;
530 if(ioDataInit(pInpIo->hIoData, &ioDataCfg) != IODATA_NO_ERR) {
531 return (-1); // to remove magic number
532 }
534 pInpIo->phyXferSize = ioPhyParams.xferFrameSize;
535 pInpIo->switchHangOver = 0;
536 pInpIo->syncState = IODATA_SYNC_NONE;
538 return 0;
539 } /* asipIoCompsInit */
541 /*======================================================================================
542 * This function initializes ASIP processing
543 *====================================================================================*/
544 void asipProcInit(PAF_AST_IoInp *pInp)
545 {
546 pInp->swapData = SWAP_INPUT_DATA;
547 pInp->asipProcState = ASIP_SOURCE_DETECTION;
548 pInp->switchHangOver = 0;
549 }
551 /*======================================================================================
552 * I/O physical layer prime operation required by McASP LLD
553 *====================================================================================*/
554 void asipIoPhyPrime(PAF_AST_IoInp *pInp)
555 {
556 Int32 count;
558 for(count = 0; count < pInp->numPrimeXfers; count++)
559 {
560 ioPhyXferSubmit(pInp->hIoPhy);
561 #ifdef ASIP_DEBUG
562 //pInp->numXferStart++;
563 #endif
564 }
565 } /* asipIoPhyPrime */
567 /*======================================================================================
568 * This function pends on I/O PHY transfer for the input task
569 *====================================================================================*/
570 void asipPhyTransferPend()
571 {
572 // asipSemRx needs to be placed into some data structure
573 Semaphore_pend(asipSemRx, BIOS_WAIT_FOREVER);
574 } /* asipPhyTransferPend */
576 /*======================================================================================
577 * This function marks the I/O PHY transfer as complete
578 *====================================================================================*/
579 void asipPhyTransferComplete(PAF_AST_IoInp * pInpIo)
580 {
581 // Mark underlining I/O BUFF write complete and swap data if needed
582 ioPhyXferComplete(pInpIo->hIoPhy, pInpIo->swapData);
583 } /* asipPhyTransferComplete */
586 /*======================================================================================
587 * McASP LLD call back function
588 *====================================================================================*/
589 void asipMcaspCallback(void* arg, MCASP_Packet *mcasp_packet)
590 {
591 /* post semaphore */
592 if(mcasp_packet->arg == IOPHY_XFER_FINAL) {
593 Semaphore_post(asipSemRx);
594 } else {
595 ; // intermediate packet due to buffer wrapping around
596 }
597 }
599 /*======================================================================================
600 * This function checks if McASP Rx for input overruns
601 *====================================================================================*/
602 int asipCheckMcaspRxOverrun(void)
603 {
604 Mcasp_errCbStatus mcaspErrStat;
606 mcaspControlChan(hMcaspRxChan, Mcasp_IOCTL_CHAN_QUERY_ERROR_STATS, &mcaspErrStat);
608 return (mcaspErrStat.isRcvOvrRunOrTxUndRunErr);
609 }
611 /*======================================================================================
612 * This function restarts McASP LLD channel for input
613 *====================================================================================*/
614 void asipMcaspRxRestart(void)
615 {
616 mcaspRxReset();
617 mcaspRxCreate();
618 }
620 /*======================================================================================
621 * This function starts an I/O PHY transfer
622 *====================================================================================*/
623 void asipPhyTransferStart(PAF_AST_IoInp *pInpIo)
624 {
625 if(asipCheckMcaspRxOverrun()) {
626 #ifdef ASIP_DEBUG
627 pInpIo->numInputOverrun++;
628 #endif
629 asipMcaspRxRestart();
630 }
631 else {
632 if(ioPhyXferSubmit(pInpIo->hIoPhy)==IOPHY_ERR_BUFF_OVERFLOW) {
633 // Input buffer overflows!
634 printf("\nInput buffer overflows!\n");
635 exit(0);
636 }
637 else {
638 // Input buffer operates normally
639 ;
640 }
641 #ifdef ASIP_DEBUG
642 //pInpIo->numXferStart++;
643 #endif
644 }
645 }
647 Int d10Initialized = 0;
648 //extern Audk2g_STATUS mcaspAudioConfig(void);
649 extern void McaspDevice_init(void);
651 /*======================================================================================
652 * This function initializes HW interface and selects the right device for input
653 *====================================================================================*/
654 Int asipSelectDevices(const PAF_ASIT_Patchs *pQ, PAF_AST_IoInp *pInp)
655 {
656 Audk2g_STATUS status;
658 //more configuration is needed to abstract out D10
659 if(!d10Initialized) {
660 /* Initialize McASP HW details */
661 McaspDevice_init();
663 D10_init();
665 #ifdef INPUT_SPDIF
666 // Input is DIR
667 status = audk2g_AudioSelectClkSrc(AUDK2G_AUDIO_CLK_SRC_DIR);
668 #else
669 // Input is HDMI
670 status = audk2g_AudioSelectClkSrc(AUDK2G_AUDIO_CLK_SRC_I2S);
671 #endif
672 if(status != Audk2g_EOK) {
673 Log_info0("audk2g_AudioSelectClkSrc Failed!\n");
674 }
675 audk2g_delay(50000); // Without delay between these 2 calls system aborts.
677 /* Initialize McASP module */
678 status = mcaspAudioConfig(); //defined in newio\fw\mcasp_cfg.c
679 if(status != Audk2g_EOK) {
680 TRACE_TERSE0("McASP Configuration Failed!\n");
681 }
683 d10Initialized = 1;
684 }
686 /////////////// TODO: HW interface selection and initialization //////////////
687 #ifdef IO_HW_INTERFACE
688 pInp->pRxParams = pQ->devinp->x[IO_HW_INTERFACE];
689 #else
690 pInp->pRxParams = NULL;
691 #endif
693 return 0;
694 } /* asipSelectDevices */
696 /*======================================================================================
697 * This function updates input status
698 *====================================================================================*/
699 Int asipUpdateInputStatus(const void *pRxParams, PAF_InpBufStatus *pStatus,
700 PAF_InpBufConfig *pInpBuf)
701 {
702 Int asipErrno;
704 PAF_SIO_InputStatus inputStatus;
706 // initialize all values to unknown so that device specific
707 // driver layer need only fill in those entries that it is aware of.
708 // This allows extensibility of the structure without requiring users
709 // to re-code.
710 inputStatus.lock = 0;
711 inputStatus.sampleRateData = PAF_SAMPLERATE_UNKNOWN;
712 inputStatus.sampleRateMeasured = PAF_SAMPLERATE_UNKNOWN;
713 inputStatus.nonaudio = PAF_IEC_AUDIOMODE_UNKNOWN;
714 inputStatus.emphasis = PAF_IEC_PREEMPHASIS_UNKNOWN;
716 //more configuration is needed to abstract out D10
717 asipErrno = D10_RxControl(pRxParams,
718 (Uns)PAF_SIO_CONTROL_GET_INPUT_STATUS,
719 (Arg) &inputStatus);
720 if (asipErrno)
721 return asipErrno;
722 pStatus->sampleRateData = inputStatus.sampleRateData;
723 pStatus->sampleRateMeasured = inputStatus.sampleRateMeasured;
724 pStatus->nonaudio = inputStatus.nonaudio;
725 pStatus->emphasisData = inputStatus.emphasis;
727 // if MSB of override clear then use as reported lock
728 // if = 0x80 then use default [0x81]
729 // if = 0x81 then use measured (from device)
730 // others not defined or implemented
731 if ((pStatus->lockOverride & (XDAS_Int8)0x80) == 0)
732 pStatus->lock = pStatus->lockOverride;
733 else if (pStatus->lockOverride == (XDAS_Int8)0x80)
734 pStatus->lock = inputStatus.lock;
735 else if (pStatus->lockOverride == (XDAS_Int8)0x81)
736 pStatus->lock = inputStatus.lock;
738 // if MSB of override clear then use it as sample rate for system,
739 // if = 0x80 then use default [0x82]
740 // if = 0x81 then use data
741 // if = 0x82 then use measured
742 // others not defined or implemented
743 if ((pStatus->sampleRateOverride & (XDAS_Int8)0x80) == 0)
744 pStatus->sampleRateStatus = pStatus->sampleRateOverride;
745 else if (pStatus->sampleRateOverride == (XDAS_Int8)0x80)
746 pStatus->sampleRateStatus = pStatus->sampleRateMeasured;
747 else if (pStatus->sampleRateOverride == (XDAS_Int8)0x81)
748 pStatus->sampleRateStatus = pStatus->sampleRateData;
749 else if (pStatus->sampleRateOverride == (XDAS_Int8)0x82)
750 pStatus->sampleRateStatus = pStatus->sampleRateMeasured;
752 // Update emphasis status:
753 if ((pStatus->emphasisOverride & (XDAS_Int8)0x80) == 0) {
754 if (pStatus->emphasisData == PAF_IEC_PREEMPHASIS_YES)
755 pStatus->emphasisStatus = PAF_IEC_PREEMPHASIS_YES;
756 else
757 pStatus->emphasisStatus = PAF_IEC_PREEMPHASIS_NO;
758 }
759 else if (pStatus->emphasisOverride ==
760 (XDAS_Int8 )(0x80+PAF_IEC_PREEMPHASIS_YES))
761 pStatus->emphasisStatus = PAF_IEC_PREEMPHASIS_YES;
762 else /* IBEmphasisOverrideNo or other */
763 pStatus->emphasisStatus = PAF_IEC_PREEMPHASIS_NO;
765 // Update precision control
766 pInpBuf->precision = pStatus->precisionInput =
767 pStatus->precisionOverride < 0
768 ? pStatus->precisionDefault
769 : pStatus->precisionOverride > 0
770 ? pStatus->precisionOverride
771 : pStatus->precisionDetect > 0
772 ? pStatus->precisionDetect
773 : pStatus->precisionDefault;
775 return 0;
776 }
779 /*=============================================================================
780 * Main function of ASIP processing
781 *============================================================================*/
782 #define INPUT_SWITCH_HANGOVER 8
784 Int asipProcessing(PAF_AST_Config *pAstCfg, PAF_AST_IoInp *pInp)
785 {
786 int autoDetstatus, syncState;
787 Audk2g_STATUS mcaspStatus;
789 ioDataCtl_t ioDataCtl;
790 ioPhyCtl_t ioPhyCtl;
792 if(pInp->asipProcState == ASIP_SWITCH_TO_PCM) {
793 // When switching to PCM, McASP RFMT register will be modified,
794 // which will cause all 0's in one McASP LLD transfer. This will
795 // be detected as loss of SYNC by auto detection. To prevent that,
796 // skip I/O DATA process for hangover period so that this all 0's
797 // frame will not be seen by auto-detection. Also, playing out PCM
798 // needs to be skipped as well, to prevent from playing out garbage
799 // (16-bit packed data).
800 void *buff1, *buff2;
801 size_t size1, size2;
803 // Get read pointers (or sub-buffers) of the input buffer
804 if (ioBuffGetReadPtrs(pInp->hIoBuff, pInp->phyXferSize,
805 &buff1, &size1, &buff2, &size2)
806 == IOBUFF_ERR_UNDERFLOW) {
807 //printf("Input buffer underflows during switch hangover!\n");
808 return ASIP_ERR_SWITCH_TO_PCM;
809 }
811 ioBuffReadComplete(pInp->hIoBuff, buff1, size1);
813 if(buff2 != NULL) {
814 ioBuffReadComplete(pInp->hIoBuff, buff2, size2);
815 }
816 }
817 else {
818 // Perform auto-detection when not switching
819 autoDetstatus = ioDataProcess(pInp->hIoData);
820 if(autoDetstatus == IODATA_ERR_IOBUF_UNDERFLOW) {
821 // Input buffer underflows - no action is needed
822 //printf("Input buffer underflows.\n");
823 pInp->numUnderflow += 1;
825 // Return since there is no enough data to process
826 return ASIP_NO_ERR;
827 }
828 else if(autoDetstatus != IODATA_NO_ERR) {
829 // Something run happens: print error log and return
830 //printf("IODATA processing error!\n");
831 return ASIP_ERR_AUTO_DETECION;
832 }
833 else {
834 // Normal operation - check auto-detection status
835 ioDataCtl.code = IODATA_CTL_GET_AUTODET_STATUS;
836 ioDataControl(pInp->hIoData, &ioDataCtl);
838 syncState = ioDataCtl.param.autoDetStats.syncState;
839 }
840 }
842 switch(pInp->asipProcState)
843 {
844 case ASIP_SOURCE_DETECTION:
845 // zero out the output buffer
846 rxDecodePlayZero(pInp);
848 ioDataReadComplete(pInp->hIoData);
850 if(syncState == IODATA_SYNC_BITSTREAM || syncState == IODATA_SYNC_PCM) {
851 // Decide input source after SYNC is found, i.e. either
852 // bitstream preamble is detected or it times out to PCM.
853 //sourceSelect = asipDecideSource(pP, pAstCfg, &decProc);
855 }
857 if(syncState == IODATA_SYNC_BITSTREAM) {
858 // Change I/O PHY transfer size to be the same as the bitstream frame size
859 int frameSize;
860 uint_least16_t pc = ioDataCtl.param.autoDetStats.bitStreamInfo & SYNC_PC_MASK; //0x001F
861 frameSize = iecFrameLength[pc] * WORD_SIZE_BITSTREAM;
863 ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
864 ioPhyCtl.params.xferFrameSize = frameSize;
865 ioPhyControl(pInp->hIoPhy, &ioPhyCtl);
866 pInp->phyXferSize = ioPhyCtl.params.xferFrameSize;
868 pInp->asipProcState = ASIP_DECODE_BITSTREAM;
869 pInp->numFrameReceived = 1;
870 }
871 else if(syncState == IODATA_SYNC_PCM) {
872 // reconfigure McASP LLD to transfer 32-bit unpacked data
873 mcaspStatus = mcaspRecfgWordWidth(hMcaspRxChan, Mcasp_WordLength_32);
874 if(mcaspStatus != Audk2g_EOK) {
875 return ASIP_ERR_MCASP_CFG;
876 }
878 // Change I/O PHY transfer size to PCM frame size
879 ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
880 ioPhyCtl.params.xferFrameSize = INPUT_FRAME_SIZE_PCM;
881 ioPhyControl(pInp->hIoPhy, &ioPhyCtl);
882 pInp->phyXferSize = ioPhyCtl.params.xferFrameSize;
884 // Adjust I/O BUFF delay and read pointer - to make sure read pointers always point to
885 // PCM data from 1st I2S (out of 4 for HDMI 4xI2S)
886 // Adjust delay and don't mark input buffer as read complete
887 ioBuffAdjustDelay(pInp->hIoBuff, pInp->phyXferSize);
889 // Stop swapping data
890 pInp->swapData = FALSE;
892 // Go to transition state to switch to PCM
893 pInp->asipProcState = ASIP_SWITCH_TO_PCM;
894 pInp->switchHangOver = INPUT_SWITCH_HANGOVER;
896 pInp->numPcmFrameReceived = 0;
897 }
898 else {
899 // Source is still unknown - take no action
900 ;
901 }
902 break;
904 case ASIP_DECODE_BITSTREAM:
905 if (syncState == IODATA_SYNC_NONE) {
906 // Change I/O PHY transfer size to default
907 ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
908 ioPhyCtl.params.xferFrameSize = INPUT_FRAME_SIZE_DEF;
909 ioPhyControl(pInp->hIoPhy, &ioPhyCtl);
910 pInp->phyXferSize = ioPhyCtl.params.xferFrameSize;
912 pInp->numFrameReceived = 0;
913 pInp->asipProcState = ASIP_SOURCE_DETECTION;
914 }
915 else {
916 pInp->numFrameReceived += 1;
918 rxDecodeBitStream(pInp);
920 ioDataReadComplete(pInp->hIoData);
921 }
922 break;
924 case ASIP_SWITCH_TO_PCM:
925 // zero out the output buffer
926 rxDecodePlayZero(pInp);
928 pInp->switchHangOver--;
929 if(pInp->switchHangOver == 0) {
930 pInp->asipProcState = ASIP_DECODE_PCM;
931 // send message to decoder
932 }
933 break;
935 case ASIP_DECODE_PCM:
936 if (syncState == IODATA_SYNC_NONE) {
937 // reconfigure McASP LLD to receive 16-bit packed bits
938 mcaspStatus = mcaspRecfgWordWidth(hMcaspRxChan, Mcasp_WordLength_16);
939 if(mcaspStatus != Audk2g_EOK) {
940 return ASIP_ERR_MCASP_CFG;
941 }
943 // Change I/O PHY transfer size to default
944 ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
945 ioPhyCtl.params.xferFrameSize = INPUT_FRAME_SIZE_DEF;
946 ioPhyControl(pInp->hIoPhy, &ioPhyCtl);
947 pInp->phyXferSize = ioPhyCtl.params.xferFrameSize;
949 // Start swapping data
950 pInp->swapData = TRUE;
951 pInp->numPcmFrameReceived = 0;
953 pInp->asipProcState = ASIP_SOURCE_DETECTION;
954 }
955 else {
956 pInp->numPcmFrameReceived += 1;
958 rxDecodePcm(pInp);
960 ioDataReadComplete(pInp->hIoData);
961 }
963 break;
965 default:
966 break;
967 }
969 return 0;
970 } /* asipProcessing */
972 /*======================================================================================
973 * This function decides the input source based on auto-detection information.
974 *====================================================================================*/
975 //Int asipDecideSource(const PAF_ASIT_Params *pP, PAF_AST_Config *pAstCfg, asipDecProc_t *pDec)
976 //{
978 //}
981 #ifndef IO_LOOPBACK_TEST
982 #if OUTPUT_FRAME_LENGTH == INPUT_FRAME_LENGTH
983 U8 pcmbuf[OUTPUT_FRAME_SIZE];
984 #else
985 #error Input frame length is not equal to output frame length!
986 #endif
988 Int rxDecodePcm(PAF_AST_IoInp *pInp)
989 {
990 ioDataCtl_t ioDataCtl;
991 void *buffBase;
992 void *dataStartAddress;
993 size_t buffSize, frameSize, size1, size2;
995 /* Get information for reading input data */
996 ioDataCtl.code = IODATA_CTL_GET_INPBUFFINFO;
997 ioDataControl(pInp->hIoData, &ioDataCtl);
999 buffBase = ioDataCtl.param.dataReadInfo.buffBase;
1000 buffSize = ioDataCtl.param.dataReadInfo.buffSize;
1001 dataStartAddress = ioDataCtl.param.dataReadInfo.startAddress;
1002 frameSize = ioDataCtl.param.dataReadInfo.frameSize;
1004 // Copy PCM data to output buffer
1005 if(((size_t)dataStartAddress+frameSize) <= ((size_t)buffBase+buffSize)) {
1006 // Input buffer doesn't wrap around
1007 Cache_inv(dataStartAddress, frameSize, Cache_Type_ALL, TRUE);
1008 memcpy((void *)&pcmbuf[0], dataStartAddress, frameSize);
1009 }
1010 else {
1011 // Input buffer wraps around
1012 size1 = (size_t)buffBase + buffSize - (size_t)dataStartAddress;
1013 size2 = frameSize - size1;
1014 Cache_inv(dataStartAddress, size1, Cache_Type_ALL, TRUE);
1015 memcpy((void *)&pcmbuf[0], dataStartAddress, size1);
1017 Cache_inv(buffBase, size2, Cache_Type_ALL, TRUE);
1018 memcpy((void *)&pcmbuf[size1], buffBase, size2);
1019 }
1022 return ASIP_NO_ERR;
1023 }
1025 Int rxDecodeBitStream(PAF_AST_IoInp *pInp)
1026 {
1027 return ASIP_NO_ERR;
1028 }
1031 Int rxDecodePlayZero(PAF_AST_IoInp *pInp)
1032 {
1033 return ASIP_NO_ERR;
1034 }
1035 #endif
1037 void asipErrorHandling(PAF_AST_Config *pAstCfg, int asipErrno)
1038 {
1040 }
1042 /* Nothing past this line */