Started refactoring output task and integrating new I/O into output
[processor-sdk/performance-audio-sr.git] / pasdk / test_dsp / framework / audioStreamInpProcNewIO.c
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
133     ASIP_SOURCE_DETECTION,
134     ASIP_DECODE_BITSTREAM,
135     ASIP_SWITCH_TO_PCM,
136     ASIP_DECODE_PCM
137 };
139 enum
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)
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
185     
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)
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)
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)
546     pInp->swapData = SWAP_INPUT_DATA;
547     pInp->asipProcState = ASIP_SOURCE_DETECTION;
548     pInp->switchHangOver = 0;
551 /*======================================================================================
552  *  I/O physical layer prime operation required by McASP LLD
553  *====================================================================================*/
554 void asipIoPhyPrime(PAF_AST_IoInp *pInp)
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()
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)
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)
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     }
599 /*======================================================================================
600  *  This function checks if McASP Rx for input overruns
601  *====================================================================================*/
602 int asipCheckMcaspRxOverrun(void)
604     Mcasp_errCbStatus mcaspErrStat;
606     mcaspControlChan(hMcaspRxChan, Mcasp_IOCTL_CHAN_QUERY_ERROR_STATS, &mcaspErrStat);
608     return (mcaspErrStat.isRcvOvrRunOrTxUndRunErr);
611 /*======================================================================================
612  *  This function restarts McASP LLD channel for input
613  *====================================================================================*/
614 void asipMcaspRxRestart(void)
616     mcaspRxReset();
617     mcaspRxCreate();
620 /*======================================================================================
621  *  This function starts an I/O PHY transfer
622  *====================================================================================*/
623 void asipPhyTransferStart(PAF_AST_IoInp *pInpIo)
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     }
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)
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)
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;
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)
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)
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;
1025 Int rxDecodeBitStream(PAF_AST_IoInp  *pInp)
1027     return ASIP_NO_ERR;
1031 Int rxDecodePlayZero(PAF_AST_IoInp  *pInp)
1033     return ASIP_NO_ERR;
1035 #endif
1037 void asipErrorHandling(PAF_AST_Config *pAstCfg, int asipErrno)
1042 /* Nothing past this line */