]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/performance-audio-sr.git/blob - pasdk/test_dsp/framework/audioStreamInpProcNewIO.c
Started refactoring input task. New code works up to auto-detection which detects
[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 "audioStreamInpProc.h"
43 #include "audioStreamProc_common.h"
44 #include "asperr.h"
46 #include "audk2g.h"
47 #include "audk2g_audio.h"
48 #include "mcasp_cfg.h"
49 #include "ioConfig.h"    //TODO: remove this header
50 #include "ioBuff.h"
51 #include "ioPhy.h"
52 #include "ioData.h"
56 #define SYNC_PC_MASK         0x1F
57 #define SYNC_SUBTYPE_MASK    0x700
58 #define SYNC_SUBTYPE_SHIFT   8
59 #define SYNC_SUBTYPE_DTSHD   0x11
60 #define SYNC_DDP             0x15
61 #define SYNC_THD             0x16
63 #define IEC_HEADER_LENGTH    4
66 //table needed until PAF_SOURCE is reordered to match IEC numbering
67 const SmUns IECpafSource[23] =
68 {
69     PAF_SOURCE_UNKNOWN,  // 0: IEC NULL Type
70     PAF_SOURCE_AC3,      // 1: Comments on 1-15 match IEC 61937 part 2.
71     PAF_SOURCE_UNKNOWN,  // 2: IEC reserved
72     PAF_SOURCE_UNKNOWN,  // 3: IEC pause
73     PAF_SOURCE_UNKNOWN,  // 4: MPEG 1 layer 1
74     PAF_SOURCE_MP3,      // 5: MPEG layer 2 or 3
75     PAF_SOURCE_UNKNOWN,  // 6: MPEG 2 data with extension
76     PAF_SOURCE_AAC,      // 7: MPEG-2 AAC ADTS
77     PAF_SOURCE_UNKNOWN,  // 8: MPEG 2 layer 1 low sampling frequency
78     PAF_SOURCE_UNKNOWN,  // 9: MPEG 2 layer 2 or 3 low sampling frequency
79     PAF_SOURCE_UNKNOWN,  // 10: reserved
80     PAF_SOURCE_DTS,      // 11: DTS type 1 (11 bit: 512 sample repeat period)
81     PAF_SOURCE_DTS12,    // 12: DTS type 2 (12 bit: 1024 sample repeat period)
82     PAF_SOURCE_DTS13,    // 13: DTS type 3 (13 bit: 2048 sample repeat period)
83     PAF_SOURCE_DTS14,    // 14: ATRAC
84     PAF_SOURCE_UNKNOWN,  // 15: ATRAC 2/3
85     PAF_SOURCE_THD,      // 16
86     PAF_SOURCE_DTSHD,    // 17
87     PAF_SOURCE_WMA9PRO,  // 18
88     PAF_SOURCE_UNKNOWN,  // 19
89     PAF_SOURCE_UNKNOWN,  // 20
90     PAF_SOURCE_DDP,      // 21
91     PAF_SOURCE_THD,      // 22
92 };
94 /*
95  * Functions defined in other files and to be put into proper header files
96  */
97 extern Void taskAsipFxnInit(const PAF_ASIT_Params *pP,const PAF_ASIT_Patchs *pQ);
100 // avoid including sap_d10.h, which would cause symbol redefinition
101 // warning (MCASP_PFUNC_XXX)
102 extern XDAS_Int32 D10_init();
103 extern XDAS_Int32 D10_RxControl(const void *pD10RxParams,
104                                 XDAS_Int32 code, XDAS_Int32 arg);
106 /*
107  * Functions only used in this file
108  */
109 int asipPrepareProcessing();
110 int asipIoCompsInit(PAF_AST_InpBuf * pInpBuf, PAF_AST_IoInp * pInpIo);
111 void asipProcInit(PAF_AST_IoInp  *pInp);
112 void asipIoPhyPrime(PAF_AST_IoInp *pInpIo);
113 void asipPhyTransferPend(void);
114 void asipPhyTransferComplete(PAF_AST_IoInp * pInpIo);
115 void asipPhyTransferStart(PAF_AST_IoInp *pInpIo);
116 Int asipSelectDevices(const PAF_ASIT_Patchs *pQ, PAF_AST_IoInp *pInp);
117 Int asipUpdateInputStatus(const void *pRxParams, PAF_InpBufStatus *pStatus,
118                           PAF_InpBufConfig *pInpBuf);
120 Int asipProcessing(PAF_AST_Config *pAstCfg, PAF_AST_IoInp  *pInp);
121 void asipErrorHandling(PAF_AST_Config *pAstCfg, int asipErrno);
123 /*
124  * variables/structures to be put into proper global structures
125  */
126 extern Semaphore_Handle asipSemRx;
127 extern PAF_ASIT_Config gPAF_ASIT_config;
129 enum
131     ASIP_SOURCE_DETECTION,
132     ASIP_DECODE_BITSTREAM,
133     ASIP_SWITCH_TO_PCM,
134     ASIP_DECODE_PCM
135 };
137 enum
139     ASIP_INPUT_PREPARATION,
140     ASIP_INPUT_PROCESSING
141 };
143 #define ASIP_DEBUG
145 #ifdef ASIP_DEBUG
146 /* define the following as global variables for easy debugging */
147 int asipLoopCount1, asipLoopCount2;
148 Int asipErrno;
149 Int inputReadyForProcessing;
150 #endif
152 /*
153  *  ======== taskAsipFxn ========
154  *  Audio Stream Input Processing task function
155  */
156 #ifndef PASDK_SIO_DEV
157 #ifndef IO_LOOPBACK_TEST
158 Void taskAsipFxn(                  // ASIP task function for new I/O
159 #else
160 Void taskAsipFxn_NewIO_Not_Used(   // not used for loopback test
161 #endif
162 #else
163 Void taskAsipFxn_NewIO_Not_USED(   // not used for SIO/DEV based I/O
164 #endif
165     const PAF_ASIT_Params *pP,
166         const PAF_ASIT_Patchs *pQ)
168     PAF_ASIT_Config *pAsitCfg;      /* ASIT configuration pointer */
169     PAF_AST_Config  *pAstCfg;       /* AST Common (shared) configuration pointer */
170     PAF_AST_IoInp *pInp;            /* Input I/O components */
171     Int as;                         /* Audio Stream Number (1, 2, etc.) */
172     Int z;                          /* input/encode/stream/decode/output counter */
173     Int zMI;
174 #ifndef ASIP_DEBUG
175 int asipLoopCount1, asipLoopCount2;
176 Int asipErrno;
177 Int inputReadyForProcessing;
178 #endif
180     Log_info0("Enter taskAsipFxn()");
182     taskAsipFxnInit(pP, pQ);  // initialization of input task
183     
184     //
185     // Audio Stream Input Task Configuration (*pAsitCfg):
186     //
187     pAsitCfg = &gPAF_ASIT_config;       // initialize pointer to task configuration
188     pAstCfg  = pAsitCfg->pAstCfg;       // pointer to AST common (shared) configuration
189     pInp     = pAsitCfg->pIoInp;        // pointer to input I/O components
191     /* Set Audio Stream Number (1, 2, etc.) */
192     as = pAstCfg->as;
194     //
195     // Determine decoder and stream indices associated with the master input
196     //
197     zMI = pP->zone.master;
199     pInp[zMI].numPrimeXfers = NUM_PRIME_XFERS;
200     //asipInitDebug(&pInp[zMI]);
202     for (z=STREAM1; z < STREAMN; z++)
203     {
204         TRACE_VERBOSE1("TaskAsip: AS%d: running", as+z);
205     }
207     TRACE_TERSE0("TaskAsip: Entering Main Loop.");
209 #if 0
210     // Wait until input device is ready - change this to event based scheduling
211     asipErrno = 0;
212     while (!inputReadyForProcessing)
213     {
214         // Indicate decoder no decoding yet
215         pP->fxns->sourceDecode(pP, pQ, pAsitCfg, PAF_SOURCE_NONE);
217         Task_sleep(5);  // 5 system tick, or 5 msec. Should remove this later when implementing event based scheduling.
219         inputReadyForProcessing = asipPrepareProcessing(pP, pQ, pAsitCfg, &asipErrno);
221         if(asipErrno) {
222             asipErrorHandling(pAstCfg, asipErrno);
223         }
224     }
226     // .....................................................................
227     // At this point we have an enabled input and want to decode something.
228     // If no decoder selected then do nothing. Need to reset the sourceProgram, since
229     // when no decoder is selected there are no calls to IB
230     asipErrno = asipIoCompsInit(&pAstCfg->xInp[zMI], &pInp[zMI]);
231     if(asipErrno) {
232         printf("ASIP IO components init error!\n");
233         exit(0);
234     }
236     asipProcInit(&pInp[zMI]);
238     // start I/O physical layer by priming McASP LLD for input
239     asipIoPhyPrime(&pInp[zMI]);
241     //
242     // Main processing loop
243     //
244     asipErrno = 0;
245     for (;;)
246     {
247         // Pending on I/O PHY transfer
248         asipPhyTransferPend();
250         // Marks I/O PHY transfer and I/O BUFF write complete
251         asipPhyTransferComplete(&pInp[zMI]);
253         // Main function to process input data
254         asipErrno = asipProcessing(pAstCfg, &pInp[zMI]);
256         // Start next transfer
257         asipPhyTransferStart(&pInp[zMI]);
259         if(asipErrno) {
260             asipErrorHandling(pAstCfg, asipErrno);
261         }
262     }
263 #endif
265 #if 0
266     //
267     // Main processing loop
268     //
269     asipLoopCount1 = 0;
270     asipLoopCount2 = 0;
271     asipErrno = 0;
272     inputReadyForProcessing = FALSE;
273     for (;;)
274     {
275         asipLoopCount1++;
277         if(asipErrno) {
278             asipErrorHandling(pAstCfg, asipErrno);
280             inputReadyForProcessing = FALSE;
281         }
283         // Wait until input device is ready - change this to event based scheduling
284         if(!inputReadyForProcessing) {
285             // Indicate decoder no decoding yet
286             pP->fxns->sourceDecode(pP, pQ, pAsitCfg, PAF_SOURCE_NONE);
288             // 5 system tick, or 5 msec. Should remove this later when implementing
289             // event based scheduling.
290             Task_sleep(5);
292             inputReadyForProcessing = asipPrepareProcessing(pP, pQ, pAsitCfg, &asipErrno);
294             if (inputReadyForProcessing) {
295                 // Input is ready for processing, so we initialize the I/O components
296                 asipIoCompsInit(&pAstCfg->xInp[zMI], &pInp[zMI]);
298                 // Initialize ASIP processing
299                 asipProcInit(&pInp[zMI]);
301                 // Start I/O physical layer by priming McASP LLD for input
302                 asipIoPhyPrime(&pInp[zMI]);
303             }
304             else {
305                 // Input is not ready, so go back to the beginning of the loop
306                 continue;
307             }
308         }  /* if(!inputReadyForProcessing) */
310         // Pending on I/O PHY transfer
311         asipPhyTransferPend();
313         // Marks I/O PHY transfer and I/O BUFF write complete
314         asipPhyTransferComplete(&pInp[zMI]);
316         // Main function to process input data
317         asipErrno = asipProcessing(pAstCfg, &pInp[zMI]);
319         // Start next transfer
320         asipPhyTransferStart(&pInp[zMI]);
322         asipLoopCount2++;
323     }  // for (;;)
324 #endif
326     //
327     // Main processing loop
328     //
329     asipLoopCount1 = 0;
330     asipLoopCount2 = 0;
331     asipErrno = 0;
332     inputReadyForProcessing = FALSE;
333     pInp->asipState = ASIP_INPUT_PREPARATION;
335     for (;;)
336     {
337         asipLoopCount1++;
339         switch (pInp->asipState)
340         {
341         case ASIP_INPUT_PREPARATION:
342             // Indicate decoder no decoding yet
343             pP->fxns->sourceDecode(pP, pQ, pAsitCfg, PAF_SOURCE_NONE);
345             // 5 system tick, or 5 msec. Should remove this later when implementing
346             // event based scheduling.
347             Task_sleep(5);
349             inputReadyForProcessing = asipPrepareProcessing(pP, pQ, pAsitCfg, &asipErrno);
351             if (inputReadyForProcessing) {
352                 // Input is ready for processing, so we initialize the I/O components
353                 asipIoCompsInit(&pAstCfg->xInp[zMI], &pInp[zMI]);
355                 // Initialize ASIP processing
356                 asipProcInit(&pInp[zMI]);
358                 // Start I/O physical layer by priming McASP LLD for input
359                 asipIoPhyPrime(&pInp[zMI]);
361                 pInp->asipState = ASIP_INPUT_PROCESSING;
362             }
363             break;
365         case ASIP_INPUT_PROCESSING:
366             // Pending on I/O PHY transfer
367             asipPhyTransferPend();
369             // Marks I/O PHY transfer and I/O BUFF write complete
370             asipPhyTransferComplete(&pInp[zMI]);
372             // Main function to process input data
373             asipErrno = asipProcessing(pAstCfg, &pInp[zMI]);
375             // Start next transfer
376             asipPhyTransferStart(&pInp[zMI]);
378             if(asipErrno) {
379                 asipErrorHandling(pAstCfg, asipErrno);
381                 pInp->asipState = ASIP_INPUT_PREPARATION;
382             }
384             break;
386         default:
387             break;
388         }
389     }  // for (;;)
391 }  /* taskAsipFxn */
393 extern const MdUns iecFrameLength[23];
394 extern Ptr hMcaspRxChan;
395 #define STRIDE_WORST_CASE 32  // 4-byte (32-bit) word, 2 slots, 4 serializers
398 /*===========================================================================
399  * ASIP processing preparation
400  * Output:
401  *        - return        TRUE (input is ready) or FALSE (input is not ready)
402  *        - *asipErrno        Error number
403 ============================================================================*/
404 Int asipPrepareProcessing(const PAF_ASIT_Params *pP,
405                           const PAF_ASIT_Patchs *pQ,
406                           PAF_ASIT_Config       *pC,
407                           Int                   *asipErrno)
409     Int as, zMS, zMI, zMD;
410     Int sourceConfig, mode;
411     PAF_AST_Config  *pAstCfg;
412     PAF_AST_IoInp *pInp;            /* I/O components for input */
414     pAstCfg  = pC->pAstCfg;         // pointer to AST common (shared) configuration
415     as  = pAstCfg->as;
416     zMI = pP->zone.master;
417     zMD = pAstCfg->masterDec;
418     zMS = pAstCfg->masterStr;
419     pInp = pC->pIoInp;              // pointer to input I/O components
421     *asipErrno = 0;
423     // Select source and initialize physical layer / HW interface
424     *asipErrno = asipSelectDevices(pQ, pInp);
425     if (*asipErrno) {
426         TRACE_TERSE2("TaskAsip: selectDevices returned asipErrno = 0x%04x at line %d. AS%d", *asipErrno, as+zMS);
427         return FALSE;    // Input is not ready for processing due to error
428     }
430     // If no master input selected then we don't know what may be at the input,
431     // so set to unknown and skip any remaining processing
432     if (!pInp[zMI].pRxParams) {
433         sharedMemWriteInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceProgram),
434                            (Int8)PAF_SOURCE_UNKNOWN, GATEMP_INDEX_DEC);
436         TRACE_VERBOSE1("TaskAsip: AS%d: No input selected...", as+zMS);
437         return FALSE;    // No error, but input is not ready for processing
438     }
440     // If here then we have a valid input so query its status
441     *asipErrno = asipUpdateInputStatus(pInp[zMI].pRxParams,
442                                    &pAstCfg->xInp[zMI].inpBufStatus,
443                                    &pAstCfg->xInp[zMI].inpBufConfig);
444     if(*asipErrno) {
445         TRACE_VERBOSE1("TaskAsip: updateInputStatus returns 0x%x", *asipErrno);
446         return FALSE;   // Input is not ready for processing due to error
447     }
449     // If master decoder is not enabled, or the input is unlocked, then do nothing
450     mode = (Int)sharedMemReadInt8(&(pAstCfg->xDec[zMD].decodeStatus.mode),
451                                   GATEMP_INDEX_DEC);
452     if (!mode || !pAstCfg->xInp[zMI].inpBufStatus.lock)
453     {
454         TRACE_VERBOSE0("TaskAsip: Not locked, continue");
455         return FALSE;  // No error, but input is not ready for processing
456     }
458     // Check selected source: sourceSelect is set by another task, AIP or AFP
459     sourceConfig = (Int)sharedMemReadInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceSelect),
460                                           GATEMP_INDEX_DEC);
461     // If no source selected then do nothing
462     if(sourceConfig == PAF_SOURCE_NONE) {
463         sharedMemWriteInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceProgram),
464                            (Int8)PAF_SOURCE_NONE, GATEMP_INDEX_DEC);
465         TRACE_VERBOSE1("TaskAsip: AS%d: no source selected, continue", as+zMS);
466         return FALSE;  // No error, but input is not ready for processing
467     }
469     // If we want pass processing then proceed directly
470     if (sourceConfig == PAF_SOURCE_PASS)
471     {
472         TRACE_VERBOSE1("TaskAsip: AS%d: Pass processing ...", as+zMS);
473         sharedMemWriteInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceProgram),
474                            (Int8)PAF_SOURCE_PASS, GATEMP_INDEX_DEC);
476         pP->fxns->sourceDecode(pP, pQ, pC, PAF_SOURCE_PASS);
477         if (pP->fxns->passProcessing) {
478             *asipErrno = pP->fxns->passProcessing(pP, pQ, pC, NULL);
479         }
480         else {
481             TRACE_TERSE2("TaskAsip: AS%d: Pass Processing not supported, asipErrno 0x%x", as+zMS, ASPERR_PASS);
482             *asipErrno = ASPERR_PASS;
483         }
485         TRACE_VERBOSE0("TaskAsip: continue");
486         return FALSE;  // Error or not, input is not ready for processing
487     }
489     // No error and input processing is ready
490     return TRUE;
491 } /* asipPrepareProcessing */
493 /*===========================================================================
494  * Initialize I/O components for input processing
495 ============================================================================*/
496 int asipIoCompsInit(PAF_AST_InpBuf * pInpBuf, PAF_AST_IoInp * pInpIo)
498     // Initialize I/O BUFF and I/O PHY components for input task
499     ioBuffParams_t ioBuffParams;
500     ioPhyParams_t  ioPhyParams;
501     ioDataParam_t  ioDataCfg;
503     ioBuffParams.base         = pInpBuf->inpBufConfig.base.pVoid;
504     ioBuffParams.size         = pInpBuf->inpBufConfig.allocation/STRIDE_WORST_CASE*STRIDE_WORST_CASE;
505     ioBuffParams.sync         = IOBUFF_WRITE_SYNC;
506     ioBuffParams.nominalDelay = INPUT_FRAME_SIZE_DEF;
507     if(ioBuffInit(pInpIo->hIoBuff, &ioBuffParams) != IOBUFF_NOERR) {
508         return (-1);   // to remove magic number
509     }
511     ioPhyParams.ioBuffHandle    = pInpIo->hIoBuff;
512     ioPhyParams.xferFrameSize   = INPUT_FRAME_SIZE_DEF;
513     ioPhyParams.mcaspChanHandle = hMcaspRxChan;
514     ioPhyParams.ioBuffOp        = IOPHY_IOBUFFOP_WRITE;
515     if(ioPhyInit(pInpIo->hIoPhy, &ioPhyParams) != IOPHY_NOERR) {
516         return (-1);   // to remove magic number
517     }
519     ioDataCfg.ioBuffHandle         = pInpIo->hIoBuff;
520     ioDataCfg.unknownSourceTimeOut = pInpBuf->inpBufConfig.pBufStatus->unknownTimeout;
521     ioDataCfg.frameLengthsIEC      = (uint_least16_t *)&iecFrameLength[0];
522     ioDataCfg.frameLengthPCM       = INPUT_FRAME_SIZE_PCM / WORD_SIZE_PCM;
523     ioDataCfg.frameLengthDef       = INPUT_FRAME_SIZE_DEF / WORD_SIZE_BITSTREAM;
524     ioDataCfg.ibMode               = pInpBuf->inpBufConfig.pBufStatus->mode;
525     ioDataCfg.zeroRunRestart       = pInpBuf->inpBufConfig.pBufStatus->zeroRunRestart;
526     ioDataCfg.zeroRunTrigger       = pInpBuf->inpBufConfig.pBufStatus->zeroRunTrigger;
528     if(ioDataInit(pInpIo->hIoData, &ioDataCfg) != IODATA_NO_ERR) {
529         return (-1);   // to remove magic number
530     }
532     pInpIo->phyXferSize    = ioPhyParams.xferFrameSize;
533     pInpIo->switchHangOver = 0;
534     pInpIo->syncState      = IODATA_SYNC_NONE;
536     return 0;
537 } /* asipIoCompsInit */
539 /*======================================================================================
540  *  This function initializes ASIP processing
541  *====================================================================================*/
542 void asipProcInit(PAF_AST_IoInp  *pInp)
544     pInp->swapData = SWAP_INPUT_DATA;
545     pInp->asipProcState = ASIP_SOURCE_DETECTION;
546     pInp->switchHangOver = 0;
549 /*======================================================================================
550  *  I/O physical layer prime operation required by McASP LLD
551  *====================================================================================*/
552 void asipIoPhyPrime(PAF_AST_IoInp *pInp)
554     Int32        count;
556     for(count = 0; count < pInp->numPrimeXfers; count++)
557     {
558         ioPhyXferSubmit(pInp->hIoPhy);
559 #ifdef ASIP_DEBUG
560         //pInp->numXferStart++;
561 #endif
562     }
563 } /* asipIoPhyPrime */
565 /*======================================================================================
566  *  This function pends on I/O PHY transfer for the input task
567  *====================================================================================*/
568 void asipPhyTransferPend()
570     // asipSemRx needs to be placed into some data structure
571     Semaphore_pend(asipSemRx, BIOS_WAIT_FOREVER);
572 } /* asipPhyTransferPend */
574 /*======================================================================================
575  *  This function marks the I/O PHY transfer as complete
576  *====================================================================================*/
577 void asipPhyTransferComplete(PAF_AST_IoInp * pInpIo)
579     // Mark underlining I/O BUFF write complete and swap data if needed
580     ioPhyXferComplete(pInpIo->hIoPhy, pInpIo->swapData);
581 } /* asipPhyTransferComplete */
584 /*======================================================================================
585  *  McASP LLD call back function
586  *====================================================================================*/
587 void asipMcaspCallback(void* arg, MCASP_Packet *mcasp_packet)
589     /* post semaphore */
590     if(mcasp_packet->arg == IOPHY_XFER_FINAL) {
591         Semaphore_post(asipSemRx);
592     } else {
593         ;    // intermediate packet due to buffer wrapping around
594     }
597 /*======================================================================================
598  *  This function checks if McASP Rx for input overruns
599  *====================================================================================*/
600 int asipCheckMcaspRxOverrun(void)
602     Mcasp_errCbStatus mcaspErrStat;
604     mcaspControlChan(hMcaspRxChan, Mcasp_IOCTL_CHAN_QUERY_ERROR_STATS, &mcaspErrStat);
606     return (mcaspErrStat.isRcvOvrRunOrTxUndRunErr);
609 /*======================================================================================
610  *  This function restarts McASP LLD channel for input
611  *====================================================================================*/
612 void asipMcaspRxRestart(void)
614     mcaspRxReset();
615     mcaspRxCreate();
618 /*======================================================================================
619  *  This function starts an I/O PHY transfer
620  *====================================================================================*/
621 void asipPhyTransferStart(PAF_AST_IoInp *pInpIo)
623     if(asipCheckMcaspRxOverrun()) {
624 #ifdef ASIP_DEBUG
625         pInpIo->numInputOverrun++;
626 #endif
627         asipMcaspRxRestart();
628     }
629     else {
630         if(ioPhyXferSubmit(pInpIo->hIoPhy)==IOPHY_ERR_BUFF_OVERFLOW) {
631             // Input buffer overflows!
632             printf("\nInput buffer overflows!\n");
633             exit(0);
634         }
635         else {
636             // Input buffer operates normally
637             ;
638         }
639 #ifdef ASIP_DEBUG
640         //pInpIo->numXferStart++;
641 #endif
642     }
645 Int d10Initialized = 0;
646 //extern Audk2g_STATUS mcaspAudioConfig(void);
647 extern void McaspDevice_init(void);
649 /*======================================================================================
650  *  This function initializes HW interface and selects the right device for input
651  *====================================================================================*/
652 Int asipSelectDevices(const PAF_ASIT_Patchs *pQ, PAF_AST_IoInp *pInp)
654     Audk2g_STATUS status;
656     //more configuration is needed to abstract out D10
657     if(!d10Initialized) {
658         /* Initialize McASP HW details */
659         McaspDevice_init();
661         D10_init();
663 #ifdef INPUT_SPDIF
664         // Input is DIR
665         status = audk2g_AudioSelectClkSrc(AUDK2G_AUDIO_CLK_SRC_DIR);
666 #else
667         // Input is HDMI
668         status = audk2g_AudioSelectClkSrc(AUDK2G_AUDIO_CLK_SRC_I2S);
669 #endif
670         if(status != Audk2g_EOK) {
671             Log_info0("audk2g_AudioSelectClkSrc Failed!\n");
672         }
673         audk2g_delay(50000); // Without delay between these 2 calls system aborts.
675         /* Initialize McASP module */
676         status = mcaspAudioConfig(); //defined in newio\fw\mcasp_cfg.c
677         if(status != Audk2g_EOK) {
678             TRACE_TERSE0("McASP Configuration Failed!\n");
679         }
681         d10Initialized = 1;
682     }
684     /////////////// TODO: HW interface selection and initialization //////////////
685 #ifdef IO_HW_INTERFACE
686     pInp->pRxParams = pQ->devinp->x[IO_HW_INTERFACE];
687 #else
688     pInp->pRxParams = NULL;
689 #endif
691     return 0;
692 }  /* asipSelectDevices */
694 /*======================================================================================
695  *  This function updates input status
696  *====================================================================================*/
697 Int asipUpdateInputStatus(const void *pRxParams, PAF_InpBufStatus *pStatus,
698                           PAF_InpBufConfig *pInpBuf)
700     Int asipErrno;
702     PAF_SIO_InputStatus inputStatus;
704     // initialize all values to unknown so that device specific
705     //   driver layer need only fill in those entries that it is aware of.
706     //   This allows extensibility of the structure without requiring users
707     //   to re-code.
708     inputStatus.lock = 0;
709     inputStatus.sampleRateData = PAF_SAMPLERATE_UNKNOWN;
710     inputStatus.sampleRateMeasured = PAF_SAMPLERATE_UNKNOWN;
711     inputStatus.nonaudio = PAF_IEC_AUDIOMODE_UNKNOWN;
712     inputStatus.emphasis = PAF_IEC_PREEMPHASIS_UNKNOWN;
714     //more configuration is needed to abstract out D10
715     asipErrno = D10_RxControl(pRxParams,
716                           (Uns)PAF_SIO_CONTROL_GET_INPUT_STATUS,
717                           (Arg) &inputStatus);
718     if (asipErrno)
719         return asipErrno;
720     pStatus->sampleRateData = inputStatus.sampleRateData;
721     pStatus->sampleRateMeasured = inputStatus.sampleRateMeasured;
722     pStatus->nonaudio = inputStatus.nonaudio;
723     pStatus->emphasisData = inputStatus.emphasis;
725     // if MSB of override clear then use as reported lock
726     // if = 0x80 then use default [0x81]
727     // if = 0x81 then use measured (from device)
728     // others not defined or implemented
729     if ((pStatus->lockOverride & (XDAS_Int8)0x80) == 0)
730         pStatus->lock = pStatus->lockOverride;
731     else if (pStatus->lockOverride == (XDAS_Int8)0x80)
732         pStatus->lock = inputStatus.lock;
733     else if (pStatus->lockOverride == (XDAS_Int8)0x81)
734         pStatus->lock = inputStatus.lock;
736     // if MSB of override clear then use it as sample rate for system,
737     // if = 0x80 then use default [0x82]
738     // if = 0x81 then use data
739     // if = 0x82 then use measured
740     // others not defined or implemented
741     if ((pStatus->sampleRateOverride & (XDAS_Int8)0x80) == 0)
742         pStatus->sampleRateStatus = pStatus->sampleRateOverride;
743     else if (pStatus->sampleRateOverride == (XDAS_Int8)0x80)
744         pStatus->sampleRateStatus = pStatus->sampleRateMeasured;
745     else if (pStatus->sampleRateOverride == (XDAS_Int8)0x81)
746         pStatus->sampleRateStatus = pStatus->sampleRateData;
747     else if (pStatus->sampleRateOverride == (XDAS_Int8)0x82)
748         pStatus->sampleRateStatus = pStatus->sampleRateMeasured;
750     // Update emphasis status:
751     if ((pStatus->emphasisOverride & (XDAS_Int8)0x80) == 0) {
752         if (pStatus->emphasisData == PAF_IEC_PREEMPHASIS_YES)
753             pStatus->emphasisStatus = PAF_IEC_PREEMPHASIS_YES;
754         else
755             pStatus->emphasisStatus = PAF_IEC_PREEMPHASIS_NO;
756     }
757     else if (pStatus->emphasisOverride ==
758              (XDAS_Int8 )(0x80+PAF_IEC_PREEMPHASIS_YES))
759         pStatus->emphasisStatus = PAF_IEC_PREEMPHASIS_YES;
760     else /* IBEmphasisOverrideNo or other */
761         pStatus->emphasisStatus = PAF_IEC_PREEMPHASIS_NO;
763     // Update precision control
764     pInpBuf->precision = pStatus->precisionInput =
765         pStatus->precisionOverride < 0
766         ? pStatus->precisionDefault
767         : pStatus->precisionOverride > 0
768         ? pStatus->precisionOverride
769         : pStatus->precisionDetect > 0
770         ? pStatus->precisionDetect
771         : pStatus->precisionDefault;
773     return 0;
777 /*=============================================================================
778  *  Main function of ASIP processing
779  *============================================================================*/
780 #define INPUT_SWITCH_HANGOVER 8
782 Int asipProcessing(PAF_AST_Config *pAstCfg, PAF_AST_IoInp  *pInp)
784     int autoDetstatus, syncState;
785     Audk2g_STATUS mcaspStatus;
787     ioDataCtl_t ioDataCtl;
788     ioPhyCtl_t  ioPhyCtl;
790     if(pInp->asipProcState == ASIP_SWITCH_TO_PCM) {
791         // When switching to PCM, McASP RFMT register will be modified,
792         // which will cause all 0's in one McASP LLD transfer. This will
793         // be detected as loss of SYNC by auto detection. To prevent that,
794         // skip I/O DATA process for hangover period so that this all 0's
795         // frame will not be seen by auto-detection. Also, playing out PCM
796         // needs to be skipped as well, to prevent from playing out garbage
797         // (16-bit packed data).
798         void *buff1, *buff2;
799         size_t size1, size2;
801         // Get read pointers (or sub-buffers) of the input buffer
802         if (ioBuffGetReadPtrs(pInp->hIoBuff, pInp->phyXferSize,
803                               &buff1, &size1, &buff2, &size2)
804             == IOBUFF_ERR_UNDERFLOW) {
805             //printf("Input buffer underflows during switch hangover!\n");
806             return ASIP_ERR_SWITCH_TO_PCM;
807         }
809         ioBuffReadComplete(pInp->hIoBuff, buff1, size1);
811         if(buff2 != NULL) {
812             ioBuffReadComplete(pInp->hIoBuff, buff2, size2);
813         }
814     }
815     else {
816         // Perform auto-detection when not switching
817         autoDetstatus = ioDataProcess(pInp->hIoData);
818         if(autoDetstatus == IODATA_ERR_IOBUF_UNDERFLOW) {
819             // Input buffer underflows - no action is needed
820             //printf("Input buffer underflows.\n");
821             pInp->numUnderflow += 1;
823             // Return since there is no enough data to process
824             return ASIP_NO_ERR;
825         }
826         else if(autoDetstatus != IODATA_NO_ERR) {
827             // Something run happens: print error log and return
828             //printf("IODATA processing error!\n");
829             return ASIP_ERR_AUTO_DETECION;
830         }
831         else {
832             // Normal operation - check auto-detection status
833             ioDataCtl.code = IODATA_CTL_GET_AUTODET_STATUS;
834             ioDataControl(pInp->hIoData, &ioDataCtl);
836             syncState = ioDataCtl.param.autoDetStats.syncState;
837         }
838     }
840     switch(pInp->asipProcState)
841     {
842     case ASIP_SOURCE_DETECTION:
843         // zero out the output buffer
844         rxDecodePlayZero(pInp);
846         ioDataReadComplete(pInp->hIoData);
848         if(syncState == IODATA_SYNC_BITSTREAM) {
849             // Change I/O PHY transfer size to be the same as the bitstream frame size
850             int frameSize;
851             uint_least16_t pc = ioDataCtl.param.autoDetStats.bitStreamInfo & SYNC_PC_MASK; //0x001F
852             frameSize = iecFrameLength[pc] * WORD_SIZE_BITSTREAM;
854             ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
855             ioPhyCtl.params.xferFrameSize = frameSize;
856             ioPhyControl(pInp->hIoPhy, &ioPhyCtl);
857             pInp->phyXferSize = ioPhyCtl.params.xferFrameSize;
859             pInp->asipProcState = ASIP_DECODE_BITSTREAM;
860             pInp->numFrameReceived = 1;
861         }
862         else if(syncState == IODATA_SYNC_PCM) {
863             // reconfigure McASP LLD to transfer 32-bit unpacked data
864             mcaspStatus = mcaspRecfgWordWidth(hMcaspRxChan, Mcasp_WordLength_32);
865             if(mcaspStatus != Audk2g_EOK) {
866                 return ASIP_ERR_MCASP_CFG;
867             }
869             // Change I/O PHY transfer size to PCM frame size
870             ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
871             ioPhyCtl.params.xferFrameSize = INPUT_FRAME_SIZE_PCM;
872             ioPhyControl(pInp->hIoPhy, &ioPhyCtl);
873             pInp->phyXferSize = ioPhyCtl.params.xferFrameSize;
875             // Adjust I/O BUFF delay and read pointer - to make sure read pointers always point to
876             // PCM data from 1st I2S (out of 4 for HDMI 4xI2S)
877             // Adjust delay and don't mark input buffer as read complete
878             ioBuffAdjustDelay(pInp->hIoBuff, pInp->phyXferSize);
880             // Stop swapping data
881             pInp->swapData = FALSE;
883             // Go to transition state to switch to PCM
884             pInp->asipProcState = ASIP_SWITCH_TO_PCM;
885             pInp->switchHangOver = INPUT_SWITCH_HANGOVER;
887             pInp->numPcmFrameReceived = 0;
888         }
889         else {
890             // Source is still unknown - take no action
891             ;
892         }
893         break;
895     case ASIP_DECODE_BITSTREAM:
896         if (syncState == IODATA_SYNC_NONE) {
897             // Change I/O PHY transfer size to default
898             ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
899             ioPhyCtl.params.xferFrameSize = INPUT_FRAME_SIZE_DEF;
900             ioPhyControl(pInp->hIoPhy, &ioPhyCtl);
901             pInp->phyXferSize  = ioPhyCtl.params.xferFrameSize;
903             pInp->numFrameReceived = 0;
904             pInp->asipProcState  = ASIP_SOURCE_DETECTION;
905         }
906         else {
907             pInp->numFrameReceived += 1;
909             rxDecodeBitStream(pInp);
911             ioDataReadComplete(pInp->hIoData);
912         }
913         break;
915     case ASIP_SWITCH_TO_PCM:
916         // zero out the output buffer
917         rxDecodePlayZero(pInp);
919         pInp->switchHangOver--;
920         if(pInp->switchHangOver == 0) {
921             pInp->asipProcState = ASIP_DECODE_PCM;
922             // send message to decoder
923         }
924         break;
926     case ASIP_DECODE_PCM:
927         if (syncState == IODATA_SYNC_NONE) {
928             // reconfigure McASP LLD to receive 16-bit packed bits
929             mcaspStatus = mcaspRecfgWordWidth(hMcaspRxChan, Mcasp_WordLength_16);
930             if(mcaspStatus != Audk2g_EOK) {
931                 return ASIP_ERR_MCASP_CFG;
932             }
934             // Change I/O PHY transfer size to default
935             ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
936             ioPhyCtl.params.xferFrameSize = INPUT_FRAME_SIZE_DEF;
937             ioPhyControl(pInp->hIoPhy, &ioPhyCtl);
938             pInp->phyXferSize  = ioPhyCtl.params.xferFrameSize;
940             // Start swapping data
941             pInp->swapData = TRUE;
942             pInp->numPcmFrameReceived = 0;
944             pInp->asipProcState = ASIP_SOURCE_DETECTION;
945         }
946         else {
947             pInp->numPcmFrameReceived += 1;
949             rxDecodePcm(pInp);
951             ioDataReadComplete(pInp->hIoData);
952         }
954         break;
956     default:
957         break;
958     }
960     return 0;
961 } /* asipProcessing */
963 #ifndef IO_LOOPBACK_TEST
964 Int rxDecodePcm(PAF_AST_IoInp  *pInp)
966     return ASIP_NO_ERR;
969 Int rxDecodeBitStream(PAF_AST_IoInp  *pInp)
971     return ASIP_NO_ERR;
974 Int rxDecodePlayZero(PAF_AST_IoInp  *pInp)
976     return ASIP_NO_ERR;
978 #endif
980 void asipErrorHandling(PAF_AST_Config *pAstCfg, int asipErrno)
985 /* Nothing past this line */