cbaa4c2d24a9ebccc29591b77191bcf2fe2f6618
[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>
41 #include <xdc/runtime/Error.h>
42 #include <ti/sysbios/knl/Event.h>
44 #include "procsdk_audio_typ.h"
45 #include "audioStreamInpProc.h"
46 #include "audioStreamProc_common.h"
47 #include "aspMsg_common.h"
48 #include "aspMsg_master.h"
49 #include "asperr.h"
50 #include "common.h"
52 #include "audk2g.h"
53 #include "audk2g_audio.h"
54 #include "mcasp_cfg.h"
55 #include "ioConfig.h"    //TODO: remove this header
56 #include "ioBuff.h"
57 #include "ioPhy.h"
58 #include "ioData.h"
61 #define STRIDE_WORST_CASE 32  // 4-byte (32-bit) word, 2 slots, 4 serializers
63 #define SYNC_PC_MASK         0x1F
64 #define SYNC_SUBTYPE_MASK    0x700
65 #define SYNC_SUBTYPE_SHIFT   8
66 #define SYNC_SUBTYPE_DTSHD   0x11
67 #define SYNC_DDP             0x15
68 #define SYNC_THD             0x16
70 #define IEC_HEADER_LENGTH    4
72 #define INPUT_SWITCH_HANGOVER 8
74 //table needed until PAF_SOURCE is reordered to match IEC numbering
75 const SmUns IECpafSource[23] =
76 {
77     PAF_SOURCE_UNKNOWN,  // 0: IEC NULL Type
78     PAF_SOURCE_AC3,      // 1: Comments on 1-15 match IEC 61937 part 2.
79     PAF_SOURCE_UNKNOWN,  // 2: IEC reserved
80     PAF_SOURCE_UNKNOWN,  // 3: IEC pause
81     PAF_SOURCE_UNKNOWN,  // 4: MPEG 1 layer 1
82     PAF_SOURCE_MP3,      // 5: MPEG layer 2 or 3
83     PAF_SOURCE_UNKNOWN,  // 6: MPEG 2 data with extension
84     PAF_SOURCE_AAC,      // 7: MPEG-2 AAC ADTS
85     PAF_SOURCE_UNKNOWN,  // 8: MPEG 2 layer 1 low sampling frequency
86     PAF_SOURCE_UNKNOWN,  // 9: MPEG 2 layer 2 or 3 low sampling frequency
87     PAF_SOURCE_UNKNOWN,  // 10: reserved
88     PAF_SOURCE_DTS,      // 11: DTS type 1 (11 bit: 512 sample repeat period)
89     PAF_SOURCE_DTS12,    // 12: DTS type 2 (12 bit: 1024 sample repeat period)
90     PAF_SOURCE_DTS13,    // 13: DTS type 3 (13 bit: 2048 sample repeat period)
91     PAF_SOURCE_DTS14,    // 14: ATRAC
92     PAF_SOURCE_UNKNOWN,  // 15: ATRAC 2/3
93     PAF_SOURCE_THD,      // 16
94     PAF_SOURCE_DTSHD,    // 17
95     PAF_SOURCE_WMA9PRO,  // 18
96     PAF_SOURCE_UNKNOWN,  // 19
97     PAF_SOURCE_UNKNOWN,  // 20
98     PAF_SOURCE_DDP,      // 21
99     PAF_SOURCE_THD,      // 22
100 };
102 /*
103  * Functions defined in other files and to be put into proper header files
104  */
105 extern Void taskAsipFxnInit(const PAF_ASIT_Params *pP,const PAF_ASIT_Patchs *pQ);
108 // avoid including sap_d10.h, which would cause symbol redefinition
109 // warning (MCASP_PFUNC_XXX)
110 extern XDAS_Int32 D10_init();
111 extern XDAS_Int32 D10_RxControl(const void *pD10RxParams,
112                                 XDAS_Int32 code, XDAS_Int32 arg);
114 /*
115  * Functions only used in this file
116  */
117 int asitPrepareProcessing();
118 int asitIoCompsInit(PAF_AST_InpBuf * pInpBuf, PAF_AST_IoInp * pInpIo);
119 void asitProcInit(PAF_AST_IoInp  *pInp, asipDecProc_t *pDec);
120 void asitIoPhyPrime(PAF_AST_IoInp *pInpIo);
121 void asitPhyTransferComplete(PAF_AST_IoInp * pInpIo);
122 void asitPhyTransferStart(PAF_AST_IoInp *pInpIo);
123 Int asitRecfgPhyXfer(PAF_AST_IoInp *pInp, size_t xferSize);
124 Int asitSelectDevices(const PAF_ASIT_Patchs *pQ, PAF_AST_IoInp *pInp);
125 Int asitUpdateInputStatus(const void *pRxParams, PAF_InpBufStatus *pStatus,
126                           PAF_InpBufConfig *pInpBuf);
128 Int asitSourceDetection(const PAF_ASIT_Params *pP,
129                         const PAF_ASIT_Patchs *pQ,
130                         PAF_ASIT_Config       *pAsitCfg);
132 Int asitDecideSource(PAF_AST_Config *pAstCfg, PAF_AST_IoInp  *pInp,
133                      ioDataAutoDetStat_t *autoDetStatus);
134 Int asitUpdateIoComps(const PAF_ASIT_Params *pP, PAF_AST_Config *pAstCfg,
135                       PAF_AST_IoInp  *pInp, ioDataAutoDetStat_t *autoDetStatus);
136 Int asitBypassIoData(PAF_AST_IoInp *pInp);
137 Int asitPcmTransition(PAF_ASIT_Config *pAsitCfg);
139 void asitUpdateInpBufConfig(PAF_AST_Config *pAstCfg, PAF_AST_IoInp  *pInp);
140 Int asitInputDataProcess(PAF_AST_IoInp *pInp, ioDataAutoDetStat_t *pAutoDetStats);
142 UInt asitEventsToDecMsg(UInt asitEvents);
143 void asitErrorHandling(PAF_ASIT_Config *pAsitCfg, Int asitErr);
144 Int asitEvtErrCheck(UInt actualEvents, UInt expectedEvents);
146 void asitPostInfoEvent();
147 void asitPostDecEvent();
149 /*
150  * variables/structures to be put into proper global structures
151  */
152 extern PAF_ASIT_Config gPAF_ASIT_config;
153 extern const MdUns iecFrameLength[23];
154 extern Ptr hMcaspRxChan;
156 enum {
157     ASIT_RESET,
158     ASIT_SOURCE_DETECTION,
159     ASIT_PCM_TRANSITION,
160     ASIT_DECODE_PROCESSING
161 };
163 #define ASIT_EVTMSK_NONE        0x0
164 #define ASIT_EVTMSK_INPDATA     0x1
165 #define ASIT_EVTMSK_INFOACK     0x2
166 #define ASIT_EVTMSK_DECACK      0x4
168 #define ASIT_ALL_EVENTS (  ASIT_EVTMSK_INPDATA \
169                          + ASIT_EVTMSK_INFOACK \
170                          + ASIT_EVTMSK_DECACK )
172 #define ASIT_DEC_EVENTS (  ASIT_EVTMSK_INPDATA \
173                          + ASIT_EVTMSK_INFOACK \
174                          + ASIT_EVTMSK_DECACK )
176 #define ASIP_DEBUG
178 #ifdef ASIP_DEBUG
179 /* define the following as global variables for easy debugging */
180 int asipLoopCount1, asipLoopCount2;
181 Int asipErrno;
182 Int inputReadyForProcessing;
183 #endif
185 Event_Handle asitEvent;
186 Int eventsOn;
188 /*
189  *  ======== taskAsipFxn ========
190  *  Audio Stream Input Processing task function
191  */
192 #ifndef PASDK_SIO_DEV
193 #ifndef IO_LOOPBACK_TEST
194 Void taskAsipFxn(                  // ASIP task function for new I/O
195 #else
196 Void taskAsipFxn_NewIO_Not_Used(   // not used for loopback test
197 #endif
198 #else
199 Void taskAsipFxn_NewIO_Not_USED(   // not used for SIO/DEV based I/O
200 #endif
201     const PAF_ASIT_Params *pP,
202         const PAF_ASIT_Patchs *pQ)
204     PAF_ASIT_Config *pAsitCfg;      /* ASIT configuration pointer */
205     PAF_AST_Config  *pAstCfg;       /* AST Common (shared) configuration pointer */
206     PAF_AST_IoInp *pInp;            /* Input I/O components */
207     Int as;                         /* Audio Stream Number (1, 2, etc.) */
208     Int z;                          /* input/encode/stream/decode/output counter */
209     Int zMI;
210 #ifndef ASIP_DEBUG
211 int asipLoopCount1, asipLoopCount2;
212 Int asipErrno;
213 Int inputReadyForProcessing;
214 #endif
215     Int asitErr;
216     UInt events;
217 //    Int eventsOn;
218     Error_Block  eb;
220     Log_info0("Enter taskAsipFxn()");
222     taskAsipFxnInit(pP, pQ);  // initialization of input task
223     
224     Error_init(&eb);          // initialize error block
226     asitEvent = Event_create(NULL, &eb);
227     if (asitEvent == NULL) {
228         System_abort("Event create failed");
229     }
230     //
231     // Audio Stream Input Task Configuration (*pAsitCfg):
232     //
233     pAsitCfg = &gPAF_ASIT_config;       // initialize pointer to task configuration
234     pAstCfg  = pAsitCfg->pAstCfg;       // pointer to AST common (shared) configuration
236     /* Set Audio Stream Number (1, 2, etc.) */
237     as = pAstCfg->as;
239     //
240     // Determine decoder and stream indices associated with the master input
241     //
242     zMI  = pP->zone.master;
243     pInp = &pAsitCfg->pIoInp[zMI];        // pointer to input I/O components
245     for (z=STREAM1; z < STREAMN; z++)
246     {
247         TRACE_VERBOSE1("TaskAsip: AS%d: running", as+z);
248     }
250     Log_info0("TaskAsip: Entering Main Loop.");
252     //
253     // Main processing loop
254     //
255     asipLoopCount1 = 0;
256     asipLoopCount2 = 0;
257     asitErr = ASIT_NO_ERR;
258     pInp->asipState = ASIT_RESET;
259     pInp->firstTimeInit = TRUE;
260     pInp->numAsitRestart = 0;
262     // The events_on flag will be removed if the RESTART state is changed to
263     // event-based scheduling instead of polling
264     eventsOn = FALSE;
266     for (;;)
267     {
268         asipLoopCount1++;
270         if(eventsOn) {
271             events = Event_pend(asitEvent, ASIT_EVTMSK_NONE, ASIT_ALL_EVENTS,
272                                 BIOS_WAIT_FOREVER);
273         }
274         switch (pInp->asipState)
275         {
276         case ASIT_RESET:    // No events pending in this state
277             // Indicate decoder no decoding yet
278             pP->fxns->sourceDecode(pP, pQ, pAsitCfg, PAF_SOURCE_NONE);
280             // 5 system tick, or 5 msec. Should remove this later when implementing
281             // event based scheduling.
282             Task_sleep(5);
284             inputReadyForProcessing = asitPrepareProcessing(pP, pQ, pAsitCfg, &asipErrno);
285             if (inputReadyForProcessing) {
286                 TRACE_VERBOSE0("TaskAsip: Input is ready. Initialize I/O components.");
287                 // Input is ready for processing, so we initialize the I/O components.
288                 // Note that the I/O components init. and I/O PHY prime are performed only
289                 // at the first time. This should be changed later - init. and prime
290                 // should be done whenever input interface has changed.
291                 asitErr = asitIoCompsInit(&pAstCfg->xInp[zMI], pInp);
293                 // Initialize ASIT processing
294                 asitProcInit(pInp, &pAsitCfg->inpDec);
295                 pInp->asipState = ASIT_SOURCE_DETECTION;
296                 eventsOn = TRUE;   // turn on events pending
297                 TRACE_VERBOSE0("TaskAsip: turn on events and go to source detection.");
298             }
299             break;
301         case ASIT_SOURCE_DETECTION:
302             // Source unknown - to detect & identify source
303             if(events == ASIT_EVTMSK_INPDATA) {  
304                 // Only this event is expected. If any other event, it's error.
305                 // Input data is ready - perform source detection.
306                 // New state will be decided inside the function
307                 asitErr = asitSourceDetection(pP, pQ, pAsitCfg);
308             }
309             else {
310                 //Error checking & debug
311                 asitErr = asitEvtErrCheck(events, ASIT_EVTMSK_INPDATA);
312             }
314             break;
316         case ASIT_PCM_TRANSITION:
317             // Source is PCM - transition to PCM decoding
318             if(events == ASIT_EVTMSK_INPDATA) {
319                 // Only this event is expected. If any other event, it's error.
320                 // Input data is ready - transition to PCM decoding
321                 // New state will be decided inside the function
322                 asitErr = asitPcmTransition(pAsitCfg);
323             }
324             else {
325                 //Error checking & debug
326                 asitErr = asitEvtErrCheck(events, ASIT_EVTMSK_INPDATA);
327             }
328             break;
330         case ASIT_DECODE_PROCESSING:
331             if(events & ASIT_DEC_EVENTS) {
332                 // Decode processing for either PCM or bitstream
333                 // New state will be decided inside the function
334                 asitErr = asitDecodeProcessing(pP, pQ, pAsitCfg, events);
335             }
336             else {
337                 //Error checking & debug
338                 asitErr = asitEvtErrCheck(events, ASIT_DEC_EVENTS);
339             }
340             break;
342         default:
343             break;
344         }
346         if(asitErr) {
347             asitErrorHandling(pAsitCfg, asitErr);
349             if(pInp->asipState == ASIT_RESET) {
350                 eventsOn = FALSE;
351             }
353             asitErr = ASIT_NO_ERR;
354         }
356     }  // for (;;)
358 }  /* taskAsipFxn */
361 /*===========================================================================
362  * ASIT Processing Preparation
363  * Output:
364  *        - return        TRUE (input is ready) or FALSE (input is not ready)
365  *        - *asipErrno    Error number
366 ============================================================================*/
367 Int asitPrepareProcessing(const PAF_ASIT_Params *pP,
368                           const PAF_ASIT_Patchs *pQ,
369                           PAF_ASIT_Config       *pC,
370                           Int                   *asipErrno)
372     Int as, zMS, zMI, zMD;
373     Int sourceConfig, mode;
374     PAF_AST_Config  *pAstCfg;
375     PAF_AST_IoInp *pInp;            /* I/O components for input */
377     pAstCfg  = pC->pAstCfg;         // pointer to AST common (shared) configuration
378     as  = pAstCfg->as;
379     zMI = pP->zone.master;
380     zMD = pAstCfg->masterDec;
381     zMS = pAstCfg->masterStr;
382     pInp = pC->pIoInp;              // pointer to input I/O components
384     *asipErrno = 0;
386     // Select source and initialize physical layer / HW interface
387     *asipErrno = asitSelectDevices(pQ, pInp);
388     if (*asipErrno) {
389         TRACE_TERSE2("asitSelectDevices returned asipErrno = 0x%04x at line %d. AS%d",
390                      *asipErrno, as+zMS);
391         return FALSE;    // Input is not ready for processing due to error
392     }
394     // If no master input selected then we don't know what may be at the input,
395     // so set to unknown and skip any remaining processing
396     if (!pInp[zMI].pRxParams) {
397         sharedMemWriteInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceProgram),
398                            (Int8)PAF_SOURCE_UNKNOWN, GATEMP_INDEX_DEC);
400         TRACE_VERBOSE1("TaskAsip: AS%d: No input selected...", as+zMS);
401         return FALSE;    // No error, but input is not ready for processing
402     }
404     // If here then we have a valid input so query its status
405     *asipErrno = asitUpdateInputStatus(pInp[zMI].pRxParams,
406                                    &pAstCfg->xInp[zMI].inpBufStatus,
407                                    &pAstCfg->xInp[zMI].inpBufConfig);
408     if(*asipErrno) {
409         TRACE_VERBOSE1("TaskAsip: updateInputStatus returns 0x%x", *asipErrno);
410         return FALSE;   // Input is not ready for processing due to error
411     }
413     // If master decoder is not enabled, or the input is unlocked, then do nothing
414     mode = (Int)sharedMemReadInt8(&(pAstCfg->xDec[zMD].decodeStatus.mode),
415                                   GATEMP_INDEX_DEC);
416     if (!mode || !pAstCfg->xInp[zMI].inpBufStatus.lock)
417     {
418         TRACE_VERBOSE0("TaskAsip: Not locked, continue");
419         return FALSE;  // No error, but input is not ready for processing
420     }
422     // Check selected source: sourceSelect is set by another task, AIP or AFP
423     sourceConfig = (Int)sharedMemReadInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceSelect),
424                                           GATEMP_INDEX_DEC);
425     // If no source selected then do nothing
426     if(sourceConfig == PAF_SOURCE_NONE) {
427         sharedMemWriteInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceProgram),
428                            (Int8)PAF_SOURCE_NONE, GATEMP_INDEX_DEC);
429         TRACE_VERBOSE1("TaskAsip: AS%d: no source selected, continue", as+zMS);
430         return FALSE;  // No error, but input is not ready for processing
431     }
433     // If we want pass processing then proceed directly
434     if (sourceConfig == PAF_SOURCE_PASS)
435     {
436         TRACE_VERBOSE1("TaskAsip: AS%d: Pass processing ...", as+zMS);
437         sharedMemWriteInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceProgram),
438                            (Int8)PAF_SOURCE_PASS, GATEMP_INDEX_DEC);
440         pP->fxns->sourceDecode(pP, pQ, pC, PAF_SOURCE_PASS);
441         if (pP->fxns->passProcessing) {
442             *asipErrno = pP->fxns->passProcessing(pP, pQ, pC, NULL);
443         }
444         else {
445             TRACE_TERSE2("TaskAsip: AS%d: Pass Processing not supported, asipErrno 0x%x",
446                          as+zMS, ASPERR_PASS);
447             *asipErrno = ASPERR_PASS;
448         }
450         TRACE_VERBOSE0("TaskAsip: continue");
451         return FALSE;  // Error or not, input is not ready for processing
452     }
454     // No error and input processing is ready
455     return TRUE;
456 } /* asitPrepareProcessing */
458 /*===========================================================================
459  * ASIT Source Detection:
460  *     ASIT processing for input source identification:
461  *     - mark I/O PHY transfer completion
462  *     - run auto-detection via I/O DATA in asitInputDataProcess
463  *     - mark I/O DATA read completion
464  *     - check auto-detection status and take corresponding actions if either
465  *       PCM or bitstream is identified:
466  *       - decide input source
467  *       - update I/O components
468  *       - reconfigure McASP LLD if it is PCM
469  *     - start next I/O PHY transfer
470 ============================================================================*/
471 Int asitSourceDetection(const PAF_ASIT_Params *pP,
472                         const PAF_ASIT_Patchs *pQ,
473                         PAF_ASIT_Config       *pAsitCfg)
475     PAF_AST_Config  *pAstCfg;
476     PAF_AST_IoInp *pInp;            /* I/O components for input */
477     Int zMD, mcaspErr, asitErr;
478     ioDataAutoDetStat_t autoDetStatus;
480     pAstCfg  = pAsitCfg->pAstCfg;         // pointer to AST common (shared) configuration
481     zMD = pAstCfg->masterDec;
482     pInp = &pAsitCfg->pIoInp[zMD];        // pointer to input I/O components
484     // Marks I/O PHY transfer and I/O BUFF write complete
485     asitPhyTransferComplete(pInp);
487     // Process input data - either searching SYNC for PCM or checking SYNC for bitstream
488     asitErr = asitInputDataProcess(pInp, &autoDetStatus);
489     if(asitErr != ASIT_NO_ERR) {
490         // Even though there is error, still need to start next transfer to
491         // maintain McASP transfer.
492         asitPhyTransferStart(pInp);
494         return asitErr;
495     }
497     // Mark input data read complete
498     ioDataReadComplete(pInp->hIoData);
500     // Check if bitstream or PCM is detected
501     if(   autoDetStatus.syncState == IODATA_SYNC_BITSTREAM
502        || autoDetStatus.syncState == IODATA_SYNC_PCM) {
503         // Decide input source and inform decoder
504         asitErr = asitDecideSource(pAstCfg, pInp, &autoDetStatus);
505         if(asitErr != ASIT_NO_ERR) {
506             return asitErr;
507         }
508         else {
509             // Update I/O components and input buffer config
510             asitUpdateIoComps(pP, pAstCfg, pInp, &autoDetStatus);
512             // set to unknown so that we can ensure, for IOS purposes, that
513             // sourceDecode = NONE iff we are in this top level state machine
514             // and specifically not in decodeProcessing
515 #ifndef PCM_LOOPBACK_TEST
516             pP->fxns->sourceDecode(pP, pQ, pAsitCfg, PAF_SOURCE_UNKNOWN);
517 #endif
519             if(autoDetStatus.syncState == IODATA_SYNC_BITSTREAM) {
520                 // Input is bit stream: go to decoding
521                 pInp->asipState = ASIT_DECODE_PROCESSING;
522             }
523             else  {
524                 // Input is PCM: stop swapping data
525                 pInp->swapData = FALSE;
527                 // Reconfigure McASP LLD to transfer 32-bit unpacked data
528                 mcaspErr = mcaspRecfgWordWidth(pInp->hMcaspChan, Mcasp_WordLength_32);
529                 if(mcaspErr != Audk2g_EOK) {
530                     return ASIT_ERR_MCASP_CFG;
531                 }
533                 // Adjust I/O BUFF delay and read pointer - to make sure read pointers
534                 // always point to PCM data from 1st I2S (out of 4 for HDMI 4xI2S)
535                 ioBuffAdjustDelay(pInp->hIoBuff, pInp->phyXferSize);
537                 // Go to transition state to switch to PCM
538                 pInp->asipState = ASIT_PCM_TRANSITION;
539             }
540         }
541     }
543     // Start next transfer
544     asitPhyTransferStart(pInp);
546     return (ASIT_NO_ERR);
547 }  /* asitSourceDetection */
550 /*===========================================================================
551     //
552     // which will cause all 0's in one McASP LLD transfer. This will
553     // be detected as loss of SYNC by auto detection. To prevent that,
554     // skip I/O DATA process for hangover period so that this all 0's
555     // frame will not be seen by auto-detection. Also, playing out PCM
556     // needs to be skipped as well, to prevent from playing out garbage
557     // (16-bit packed data).
558  *
559  * ASIT Transition to PCM decoding.
560  *     When PCM is detected, McASP LLD will be reconfigured to transmit 32-bit
561  *     words, which will modify the RFMT register. This will cause all 0's in
562  *     one McASP LLD transfer, which would be detected as loss of SYNC by auto
563  *     detection (performed by I/O DATA). To prevent that, skip I/O DATA process
564  *     for hangover period so that this all-0's frame will not be seen by the
565  *     auto-detection.
566  *
567  *     In addition, playing out PCM should be skipped as well to prevent from
568  *     playing out the 16-bit packed data that's still in the input buffer.
569  *
570  *     This function does the following:
571  *     - mark I/O PHY transfer completion
572  *     - bypass I/O DATA
573  *     - start next I/O PHY transfer
574 ============================================================================*/
575 Int asitPcmTransition(PAF_ASIT_Config *pAsitCfg)
577     Int asitErr;
578     PAF_AST_IoInp *pInp;                  // I/O components for input
579     Int zMD;
581     zMD = pAsitCfg->pAstCfg->masterDec;   // pointer to AST common (shared) configuration
582     pInp = &pAsitCfg->pIoInp[zMD];        // pointer to input I/O components
584     // Marks I/O PHY transfer and I/O BUFF write complete
585     asitPhyTransferComplete(pInp);
587     // Bypass I/O data processing due to McASP LLD work around
588     // (refer to comments inside the function)
589     asitErr = asitBypassIoData(pInp);
591     pInp->pcmSwitchHangOver--;
592     if(pInp->pcmSwitchHangOver == 0) {
593         pInp->asipState = ASIT_DECODE_PROCESSING;
594     }
595     else {
596         ; // stay in this state
597     }
599     // Start next transfer
600     asitPhyTransferStart(pInp);
602     return asitErr;
604 } /* asitPcmTransition */
606 /*============================================================================
607  * ASIT Bypass I/O DATA Processing
608  *     This function bypasses the I/O DATA processing. It maintains the read
609  *     operation of I/O BUFF by directly calling I/O BUFF APIs. When I/O DATA
610  *     is not bypassed, I/O BUFF read operation is invoked by I/O DATA.
611  *
612 ============================================================================*/
613 Int asitBypassIoData(PAF_AST_IoInp *pInp)
615     void *buff1, *buff2;
616     size_t size1, size2;
618     // Get read pointers (or sub-buffers) of the input buffer
619     if (ioBuffGetReadPtrs(pInp->hIoBuff, pInp->phyXferSize,
620                           &buff1, &size1, &buff2, &size2)
621         == IOBUFF_ERR_UNDERFLOW) {
622         pInp->numUnderflow += 1;
624         // Return since there is no enough data to process
625         return ASIT_ERR_INPBUF_UNDERFLOW;
626     }
628     ioBuffReadComplete(pInp->hIoBuff, buff1, size1);
630     if(buff2 != NULL) {
631         ioBuffReadComplete(pInp->hIoBuff, buff2, size2);
632     }
634     return ASIP_NO_ERR;
635 } /* asitBypassIoData */
638 /*============================================================================
639  * ASIT Decode Processing
640  *     This function performs the decode processing and does the following based
641  *     on the ASIT events:
642  *     - initialize the decode processing if it is the first time
643  *     - if there is ASIT INPUT DATA event (ASIT_EVTMSK_INPDATA):
644  *        - mark I/O PHY transfer completion
645  *        - run auto-detection via I/O DATA in asitInputDataProcess
646  *        - check auto-detection status and take corresponding actions if SYNC
647  *          is lost.
648  *        - start next I/O PHY transfer
649  *     - map ASIT events to decoding messages
650  *     - invoke decDecodeFsm() and pass the mapped decoding messages
651  *     - if there is ASIT DECODE ACK event (ASIT_EVTMSK_DECACK)
652  *        - mark I/O DATA read completion
653  *     - error handling
654 ============================================================================*/
655 Int asitDecodeProcessing(const PAF_ASIT_Params *pP,
656                          const PAF_ASIT_Patchs *pQ,
657                          PAF_ASIT_Config       *pAsitCfg,
658                          UInt asitEvents)
660     Int asitErr, decErr;
661     PAF_AST_IoInp *pInp;                  // I/O components for input
662     asipDecProc_t *pDec;
663     ioDataAutoDetStat_t autoDetStatus;
664     Int zMD;
665     UInt decMsg;
667     zMD = pAsitCfg->pAstCfg->masterDec;   // pointer to AST common (shared) configuration
668     pInp = &pAsitCfg->pIoInp[zMD];        // pointer to input I/O components
669     pDec = &pAsitCfg->inpDec;
671     // Initialization for decode processing when this function is called the first time
672     if(!pDec->initDone) {
673         // Initialize decoder
674         decDecodeInit(pP, pAsitCfg, pInp->sourceSelect);
676         pDec->initDone = TRUE;
677     }
679     // Process input data if this is a data ready message
680     if(asitEvents & ASIT_EVTMSK_INPDATA) {
681         // Marks I/O PHY transfer and I/O BUFF write complete
682         asitPhyTransferComplete(pInp);
684         // Process input data - either search SYNC for PCM or check SYNC for bitstream
685         asitErr = asitInputDataProcess(pInp, &autoDetStatus);
687         if(asitErr == ASIT_NO_ERR) {
688             ioDataReadComplete(pInp->hIoData);
690             // Check if SYNC is maintained or lost (stream stops or format changes)
691             if(autoDetStatus.syncState == IODATA_SYNC_NONE) {
692                 // SYNC lost: change I/O PHY transfer size to default for auto-detection
693                 //asitErr = asitRecfgPhyXfer(pInp, INPUT_FRAME_SIZE_DEF);
694                 //if(asitErr != ASIT_NO_ERR) {
695                 //    return asitErr;
696                 //}
698                 // Inform decoder to complete the decoding of previous frame - is this good?
699                 pInp->sourceSelect = PAF_SOURCE_NONE;
700                 pInp->numFrameReceived = 0;    // for debugging
701                 TRACE_TERSE0("asitDecodeProcessing: SYNC lost.");
702             }
703             else {
704                 pInp->numFrameReceived += 1;    // for debugging
706                 // Communicate input stream information to decoder through input
707                 // buffer configuration
708                 asitUpdateInpBufConfig(pAsitCfg->pAstCfg, pInp);
709             }
711             // Start next transfer
712             asitPhyTransferStart(pInp);
713         }
714         else {
715             // Even though there is error, still need to start next transfer to
716             // maintain McASP transfer.
717             asitPhyTransferStart(pInp);
719             return asitErr;
720         }
722     } /* ASIT_EVTMSK_INPDATA */
724     // Map ASIT events to decode messages
725     decMsg = asitEventsToDecMsg(asitEvents);
727     // Pass messages (corresponding to events) to decode FSM
728     decErr = decDecodeFsm(pP, pQ, pAsitCfg, pInp->sourceSelect, decMsg);
730     // Mark I/O DATA read complete if decoder indicates decoding is done.
731     if((asitEvents & ASIT_EVTMSK_DECACK)) {  // DECACK -> decoding done
732         //ioDataReadComplete(pInp->hIoData);
733     }
735     if(decErr != DEC_NO_ERR) {
736         TRACE_VERBOSE0("TaskAsip: send DEC_EXIT message to slave decoder.");
738         // Send dec exit message to slave decoder
739         if( AspMsgSend(ASP_SLAVE_DEC_EXIT, ASP_MASTER_DEC_EXIT_DONE, NULL, NULL)
740             != ASP_MSG_NO_ERR) {
741             TRACE_VERBOSE0("TaskAsip: error in sending DEC_EXIT message");
742             SW_BREAKPOINT;
743         }
745         return ASIT_ERR_DECODE_QUIT;  // This is not necessarily an error
746     }
747     else {
748         return ASIT_NO_ERR;
749     }
751 }  /* asitDecodeProcessing */
754 /*============================================================================
755  * ASIT Input Data Processing:
756  *    - invoke ioDataProcess() to inspect input data for
757  *       - initial auto-detection,  or
758  *       - background scanning for PCM data, or
759  *       - SYNC check for bitstream
760  *    - return auto-detection status (SYNC detected, SYNC loss, etc)
761 ============================================================================*/
762 Int asitInputDataProcess(PAF_AST_IoInp *pInp, ioDataAutoDetStat_t *pAutoDetStats)
764     Int ioDataErr, retVal;
765     ioDataCtl_t ioDataCtl;
767     // Perform auto-detection inside I/O DATA component
768     ioDataErr = ioDataProcess(pInp->hIoData);
770     if(ioDataErr == IODATA_NO_ERR) {
771         // Normal operation - check auto-detection status
772         ioDataCtl.code = IODATA_CTL_GET_AUTODET_STATUS;
773         ioDataControl(pInp->hIoData, &ioDataCtl);
775         *pAutoDetStats = ioDataCtl.param.autoDetStats;
777         retVal = ASIT_NO_ERR;
778     }
779     else if(ioDataErr == IODATA_ERR_IOBUF_UNDERFLOW) {
780         // Input buffer underflows - there is no enough data to process.
781         // This is not error and no action is needed.
782         pInp->numUnderflow += 1; // debug
784         retVal = ASIT_ERR_INPBUF_UNDERFLOW;
785     }
786     else {
787         // Something is wrong: print error log and return
788         //printf("IODATA processing error!\n");
789         retVal = ASIT_ERR_INPDATA_PROC;
790     }
792     return retVal;
793 } /* asitInputDataProcess */
795 /*============================================================================
796  * Mapping ASIT Events to Decoding Messages
797 ============================================================================*/
798 UInt asitEventsToDecMsg(UInt asitEvents)
800     UInt decMsg = 0;
802     if(asitEvents & ASIT_EVTMSK_INPDATA) {
803         decMsg |= DEC_MSGMSK_INPDATA;
804     }
806     if(asitEvents & ASIT_EVTMSK_INFOACK) {
807         decMsg |= DEC_MSGMSK_INFOACK;
808     }
810     if(asitEvents & ASIT_EVTMSK_DECACK) {
811         decMsg |= DEC_MSGMSK_DECACK;
812     }
814     return decMsg;
815 } /* asitEventsToDecMsg */
817 /*===========================================================================
818  * Initialize I/O components for input processing
819 ============================================================================*/
820 int asitIoCompsInit(PAF_AST_InpBuf * pInpBuf, PAF_AST_IoInp * pInpIo)
822     ioBuffParams_t ioBuffParams;
823     ioPhyParams_t  ioPhyParams;
824     ioDataParam_t  ioDataCfg;
825     ioPhyCtl_t     ioPhyCtl;
827     TRACE_VERBOSE0("Initialize I/O DATA.");
828 /*    ioBuffParams.base         = pInpBuf->inpBufConfig.base.pVoid;
829     ioBuffParams.size         = pInpBuf->inpBufConfig.allocation / STRIDE_WORST_CASE
830                                                                  * STRIDE_WORST_CASE;
831     ioBuffParams.sync         = IOBUFF_WRITE_SYNC;
832     ioBuffParams.nominalDelay = INPUT_FRAME_SIZE_DEF;
833     if(ioBuffInit(pInpIo->hIoBuff, &ioBuffParams) != IOBUFF_NOERR) {
834         return (ASIT_ERR_IOBUFF_INIT);   // to remove magic number
835     }
836 */
837     /* Reinitialize I/O DATA every time when ASIT restarts */
838     ioDataCfg.ioBuffHandle         = pInpIo->hIoBuff;
839     ioDataCfg.unknownSourceTimeOut = pInpBuf->inpBufConfig.pBufStatus->unknownTimeout;
840     ioDataCfg.frameLengthsIEC      = (uint_least16_t *)&iecFrameLength[0];
841     ioDataCfg.frameLengthPCM       = INPUT_FRAME_SIZE_PCM / WORD_SIZE_PCM;
842     ioDataCfg.frameLengthDef       = INPUT_FRAME_SIZE_DEF / WORD_SIZE_BITSTREAM;
843     ioDataCfg.ibMode               = pInpBuf->inpBufConfig.pBufStatus->mode;
844     ioDataCfg.zeroRunRestart       = pInpBuf->inpBufConfig.pBufStatus->zeroRunRestart;
845     ioDataCfg.zeroRunTrigger       = pInpBuf->inpBufConfig.pBufStatus->zeroRunTrigger;
847     if(ioDataInit(pInpIo->hIoData, &ioDataCfg) != IODATA_NO_ERR) {
848         return (ASIT_ERR_IODATA_INIT);   // to remove magic number
849     }
851     pInpIo->numPrimeXfers  = NUM_PRIME_XFERS;
852     pInpIo->phyXferSize    = INPUT_FRAME_SIZE_DEF;
854     if(pInpIo->firstTimeInit) {
855         /* Initialize I/O BUFF and I/O PHY only when input interface changes. */
856         TRACE_VERBOSE0("Initialize I/O PHY, and prime I/O PHY.");
857         ioBuffParams.base         = pInpBuf->inpBufConfig.base.pVoid;
858         ioBuffParams.size         = pInpBuf->inpBufConfig.allocation / STRIDE_WORST_CASE
859                                                                      * STRIDE_WORST_CASE;
860         ioBuffParams.sync         = IOBUFF_WRITE_SYNC;
861         ioBuffParams.nominalDelay = INPUT_FRAME_SIZE_DEF;
862         if(ioBuffInit(pInpIo->hIoBuff, &ioBuffParams) != IOBUFF_NOERR) {
863             return (ASIT_ERR_IOBUFF_INIT);   // to remove magic number
864         }
866         ioPhyParams.ioBuffHandle    = pInpIo->hIoBuff;
867         ioPhyParams.xferFrameSize   = pInpIo->phyXferSize;
868         ioPhyParams.mcaspChanHandle = pInpIo->hMcaspChan;
869         ioPhyParams.ioBuffOp        = IOPHY_IOBUFFOP_WRITE;
870         if(ioPhyInit(pInpIo->hIoPhy, &ioPhyParams) != IOPHY_NOERR) {
871             return (ASIT_ERR_IOPYH_INIT);   // to remove magic number
872         }
874         // Start I/O physical layer by priming McASP LLD for input
875         asitIoPhyPrime(pInpIo);
877         pInpIo->firstTimeInit = FALSE;
878     }
879     else {
880         // Reconfigure I/O PHY transfer size
881         ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
882         ioPhyCtl.params.xferFrameSize = pInpIo->phyXferSize;
883         ioPhyControl(pInpIo->hIoPhy, &ioPhyCtl);
885         // If previous stream before reset was PCM, reconfigure McASP LLD to receive 16-bit packed bits
886         if(!pInpIo->swapData) {
887             Int mcaspErr;
888             mcaspErr = mcaspRecfgWordWidth(pInpIo->hMcaspChan, Mcasp_WordLength_16);
889             if(mcaspErr != Audk2g_EOK) {
890                 return ASIT_ERR_MCASP_CFG;
891             }
893             // Start swapping data
894             pInpIo->swapData = TRUE;
895             TRACE_VERBOSE0("Reconfigure McASP word length and start swapping data.");
896         }
898         // Start PHY transfer
899         TRACE_VERBOSE0("Start I/O PHY transfer.");
900         asitPhyTransferStart(pInpIo);
901     }
903     return 0;
904 } /* asitIoCompsInit */
906 /*======================================================================================
907  *  This function initializes ASIT processing
908  *====================================================================================*/
909 void asitProcInit(PAF_AST_IoInp  *pInp, asipDecProc_t *pDec)
911     pInp->swapData = TRUE;
912     pInp->pcmSwitchHangOver = INPUT_SWITCH_HANGOVER;
913     pDec->initDone = FALSE;
914     pInp->numFrameReceived = 0;
917 /*======================================================================================
918  *  I/O physical layer prime operation required by McASP LLD
919  *====================================================================================*/
920 void asitIoPhyPrime(PAF_AST_IoInp *pInp)
922     Int32        count;
924     for(count = 0; count < pInp->numPrimeXfers; count++)
925     {
926         ioPhyXferSubmit(pInp->hIoPhy);
927 #ifdef ASIP_DEBUG
928         //pInp->numXferStart++;
929 #endif
930     }
931 } /* asitIoPhyPrime */
934 /*======================================================================================
935  *  This function marks the I/O PHY transfer as complete
936  *====================================================================================*/
937 void asitPhyTransferComplete(PAF_AST_IoInp * pInpIo)
939     // Mark underlining I/O BUFF write complete and swap data if needed
940     ioPhyXferComplete(pInpIo->hIoPhy, pInpIo->swapData);
941 } /* asitPhyTransferComplete */
943 Int asitRecfgPhyXfer(PAF_AST_IoInp *pInp, size_t xferSize)
945     ioPhyCtl_t ioPhyCtl;
946     Int mcaspErr;
948     ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
949     ioPhyCtl.params.xferFrameSize = xferSize;
950     ioPhyControl(pInp->hIoPhy, &ioPhyCtl);
952     pInp->phyXferSize  = ioPhyCtl.params.xferFrameSize;
954     if(!pInp->swapData) {
955         // If it was PCM, reconfigure McASP LLD to receive 16-bit packed bits
956         mcaspErr = mcaspRecfgWordWidth(pInp->hMcaspChan, Mcasp_WordLength_16);
957         if(mcaspErr != Audk2g_EOK) {
958             return ASIT_ERR_MCASP_CFG;
959         }
961         // Start swapping data
962         pInp->swapData = TRUE;
963     }
965     return ASIT_NO_ERR;
967 } /* asitRecfgPhyXfer */
969 /*======================================================================================
970  *  McASP LLD call back function
971  *====================================================================================*/
972 void asipMcaspCallback(void* arg, MCASP_Packet *mcasp_packet)
974     /* post semaphore */
975     if(mcasp_packet->arg == IOPHY_XFER_FINAL) {
976         //Semaphore_post(asipSemRx);
977         Event_post(asitEvent, ASIT_EVTMSK_INPDATA);
978     } else {
979         ;    // intermediate packet due to buffer wrapping around
980     }
983 /*======================================================================================
984  *  This function checks if McASP Rx for input overruns
985  *====================================================================================*/
986 int asipCheckMcaspRxOverrun(Ptr mcaspChanHandle)
988     Mcasp_errCbStatus mcaspErrStat;
990     mcaspControlChan(mcaspChanHandle, Mcasp_IOCTL_CHAN_QUERY_ERROR_STATS, &mcaspErrStat);
992     return (mcaspErrStat.isRcvOvrRunOrTxUndRunErr);
995 /*======================================================================================
996  *  This function restarts McASP LLD channel for input
997  *====================================================================================*/
998 void asipMcaspRxRestart(void)
1000     mcaspRxReset();
1001     mcaspRxCreate();
1004 /*======================================================================================
1005  *  This function starts an I/O PHY transfer
1006  *====================================================================================*/
1007 void asitPhyTransferStart(PAF_AST_IoInp *pInpIo)
1009     Int ioPhyErr;
1011     if(asipCheckMcaspRxOverrun(pInpIo->hMcaspChan)) {
1012 #ifdef ASIP_DEBUG
1013         pInpIo->numInputOverrun++;
1014 #endif
1015         asipMcaspRxRestart();
1016     }
1017     else {
1018         ioPhyErr = ioPhyXferSubmit(pInpIo->hIoPhy);
1019         //if(ioPhyXferSubmit(pInpIo->hIoPhy)==IOPHY_ERR_BUFF_OVERFLOW) {
1020         if(ioPhyErr!=IOPHY_NOERR){
1021             printf("\n I/O PHY ioPhyXferSubmit fails with error %d!\n", ioPhyErr);
1022             // Input buffer overflows!
1023             //printf("\nInput buffer overflows!\n");
1024             exit(0);
1025         }
1026         else {
1027             // Input buffer operates normally
1028             ;
1029         }
1030 #ifdef ASIP_DEBUG
1031         //pInpIo->numXferStart++;
1032 #endif
1033     }
1036 Int d10Initialized = 0;
1037 //extern Audk2g_STATUS mcaspAudioConfig(void);
1038 extern void McaspDevice_init(void);
1040 /*======================================================================================
1041  *  This function initializes HW interface and selects the right device for input
1042  *====================================================================================*/
1043 Int asitSelectDevices(const PAF_ASIT_Patchs *pQ, PAF_AST_IoInp *pInp)
1045     Audk2g_STATUS status;
1047     //more configuration is needed to abstract out D10
1048     if(!d10Initialized) {
1049         /* Initialize McASP HW details */
1050         McaspDevice_init();
1052         D10_init();
1054 #ifdef INPUT_SPDIF
1055         // Input is DIR
1056         status = audk2g_AudioSelectClkSrc(AUDK2G_AUDIO_CLK_SRC_DIR);
1057 #else
1058         // Input is HDMI
1059         status = audk2g_AudioSelectClkSrc(AUDK2G_AUDIO_CLK_SRC_I2S);
1060 #endif
1061         if(status != Audk2g_EOK) {
1062             Log_info0("audk2g_AudioSelectClkSrc Failed!\n");
1063             return ASIT_ERR_D10_CFG;
1064         }
1065         audk2g_delay(50000); // Without delay between these 2 calls system aborts.
1067         /* Initialize McASP module */
1068         status = mcaspAudioConfig(); //defined in newio\fw\mcasp_cfg.c
1069         if(status != Audk2g_EOK) {
1070             Log_info0("McASP Configuration Failed!\n");
1071             return ASIT_ERR_MCASP_CFG;
1072         }
1074         pInp->hMcaspChan = hMcaspRxChan;
1075         d10Initialized = 1;
1076     }
1078     /////////////// TODO: HW interface selection and initialization //////////////
1079     ////// to add what PAF_ASIT_selectDevices() does /////////
1080 #ifdef IO_HW_INTERFACE
1081     pInp->pRxParams = pQ->devinp->x[IO_HW_INTERFACE];
1082 #else
1083     pInp->pRxParams = NULL;
1084 #endif
1086     return 0;
1087 }  /* asitSelectDevices */
1089 /*======================================================================================
1090  *  This function updates input status
1091  *====================================================================================*/
1092 Int asitUpdateInputStatus(const void *pRxParams, PAF_InpBufStatus *pStatus,
1093                           PAF_InpBufConfig *pInpBuf)
1095     Int asipErrno;
1097     PAF_SIO_InputStatus inputStatus;
1099     // initialize all values to unknown so that device specific
1100     //   driver layer need only fill in those entries that it is aware of.
1101     //   This allows extensibility of the structure without requiring users
1102     //   to re-code.
1103     inputStatus.lock = 0;
1104     inputStatus.sampleRateData = PAF_SAMPLERATE_UNKNOWN;
1105     inputStatus.sampleRateMeasured = PAF_SAMPLERATE_UNKNOWN;
1106     inputStatus.nonaudio = PAF_IEC_AUDIOMODE_UNKNOWN;
1107     inputStatus.emphasis = PAF_IEC_PREEMPHASIS_UNKNOWN;
1109     //more configuration is needed to abstract out D10
1110     asipErrno = D10_RxControl(pRxParams,
1111                           (Uns)PAF_SIO_CONTROL_GET_INPUT_STATUS,
1112                           (Arg) &inputStatus);
1113     if (asipErrno) {
1114         return asipErrno;
1115     }
1116     pStatus->sampleRateData = inputStatus.sampleRateData;
1117     pStatus->sampleRateMeasured = inputStatus.sampleRateMeasured;
1118     pStatus->nonaudio = inputStatus.nonaudio;
1119     pStatus->emphasisData = inputStatus.emphasis;
1121     // if MSB of override clear then use as reported lock
1122     // if = 0x80 then use default [0x81]
1123     // if = 0x81 then use measured (from device)
1124     // others not defined or implemented
1125     if ((pStatus->lockOverride & (XDAS_Int8)0x80) == 0)
1126         pStatus->lock = pStatus->lockOverride;
1127     else if (pStatus->lockOverride == (XDAS_Int8)0x80)
1128         pStatus->lock = inputStatus.lock;
1129     else if (pStatus->lockOverride == (XDAS_Int8)0x81)
1130         pStatus->lock = inputStatus.lock;
1132     // if MSB of override clear then use it as sample rate for system,
1133     // if = 0x80 then use default [0x82]
1134     // if = 0x81 then use data
1135     // if = 0x82 then use measured
1136     // others not defined or implemented
1137     if ((pStatus->sampleRateOverride & (XDAS_Int8)0x80) == 0)
1138         pStatus->sampleRateStatus = pStatus->sampleRateOverride;
1139     else if (pStatus->sampleRateOverride == (XDAS_Int8)0x80)
1140         pStatus->sampleRateStatus = pStatus->sampleRateMeasured;
1141     else if (pStatus->sampleRateOverride == (XDAS_Int8)0x81)
1142         pStatus->sampleRateStatus = pStatus->sampleRateData;
1143     else if (pStatus->sampleRateOverride == (XDAS_Int8)0x82)
1144         pStatus->sampleRateStatus = pStatus->sampleRateMeasured;
1146     // Update emphasis status:
1147     if ((pStatus->emphasisOverride & (XDAS_Int8)0x80) == 0) {
1148         if (pStatus->emphasisData == PAF_IEC_PREEMPHASIS_YES)
1149             pStatus->emphasisStatus = PAF_IEC_PREEMPHASIS_YES;
1150         else
1151             pStatus->emphasisStatus = PAF_IEC_PREEMPHASIS_NO;
1152     }
1153     else if (pStatus->emphasisOverride ==
1154              (XDAS_Int8 )(0x80+PAF_IEC_PREEMPHASIS_YES))
1155         pStatus->emphasisStatus = PAF_IEC_PREEMPHASIS_YES;
1156     else /* IBEmphasisOverrideNo or other */
1157         pStatus->emphasisStatus = PAF_IEC_PREEMPHASIS_NO;
1159     // Update precision control
1160     pInpBuf->precision = pStatus->precisionInput =
1161         pStatus->precisionOverride < 0
1162         ? pStatus->precisionDefault
1163         : pStatus->precisionOverride > 0
1164         ? pStatus->precisionOverride
1165         : pStatus->precisionDetect > 0
1166         ? pStatus->precisionDetect
1167         : pStatus->precisionDefault;
1169     return 0;
1173 /*==============================================================================
1174  * This function updates input buffer config based on frame information provided
1175  * by I/O DATA.
1176  ==============================================================================*/
1177 void asitUpdateInpBufConfig(PAF_AST_Config *pAstCfg, PAF_AST_IoInp  *pInp)
1179     PAF_InpBufConfig *pBufConfig;
1180     ioDataCtl_t ioDataCtl;
1182     /* Get information for reading input data */
1183     ioDataCtl.code = IODATA_CTL_GET_INPBUFFINFO;
1184     ioDataControl(pInp->hIoData, &ioDataCtl);
1186     if(ioDataCtl.param.dataReadInfo.frameSize != pInp->phyXferSize) {
1187         // Fatal error!
1188         TRACE_VERBOSE0("TaskAsip: error in updating I/O");
1189         SW_BREAKPOINT;
1190     }
1192     pBufConfig = &(pAstCfg->xInp[pAstCfg->masterDec].inpBufConfig);
1194     //JXTODO: do we need to gate here?
1195     //key = GateMP_enter(gateHandle);
1197     pBufConfig->base.pVoid   = ioDataCtl.param.dataReadInfo.buffBase;
1198     pBufConfig->sizeofBuffer = ioDataCtl.param.dataReadInfo.buffSize;
1199     pBufConfig->pntr.pSmInt  = ioDataCtl.param.dataReadInfo.startAddress;
1201     // Leave the gate
1202     //GateMP_leave(gateHandle, key);
1204     TRACE_TERSE2("Frame start address: 0x%x., preamble: 0x%x",
1205                  (UInt)ioDataCtl.param.dataReadInfo.startAddress,
1206                  *(UInt *)ioDataCtl.param.dataReadInfo.startAddress);
1209 /*==============================================================================
1210  * Decide source after SYNC is found, i.e. either bitstream preamble is detected
1211  * or it times out to PCM.
1212  ==============================================================================*/
1213 Int asitDecideSource(PAF_AST_Config *pAstCfg, PAF_AST_IoInp  *pInp,
1214                      ioDataAutoDetStat_t *autoDetStatus)
1216     Int sourceConfig, sourceSelect, sourceProgram;
1217     Int zMD;
1218     char asipMsgBuf[ASP_MSG_BUF_LEN];
1220     // Get the configured source
1221     zMD = pAstCfg->masterDec;
1222     sourceConfig = (Int)sharedMemReadInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceSelect),
1223                                           GATEMP_INDEX_DEC);
1225     if(autoDetStatus->syncState == IODATA_SYNC_PCM) {
1226         if (sourceConfig == PAF_SOURCE_DSD1 || sourceConfig == PAF_SOURCE_DSD2 ||
1227             sourceConfig == PAF_SOURCE_DSD3) {
1228             sourceProgram = sourceConfig;
1229         }
1230         else {
1231             sourceProgram = PAF_SOURCE_PCM;
1232         }
1233     }
1235     if(autoDetStatus->syncState == IODATA_SYNC_BITSTREAM) {
1236         uint_least16_t pc = autoDetStatus->bitStreamInfo & SYNC_PC_MASK; //0x001F
1237         sourceProgram = IECpafSource[pc];
1238     }
1240     // write the decided source program to memory
1241     sharedMemWriteInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceProgram), sourceProgram,
1242                        GATEMP_INDEX_DEC);
1244     // now that we have some input classification, and possibly an outstanding
1245     // input frame, we determine whether or not to call decodeProcessing and with
1246     // what decAlg.
1247     sourceSelect = PAF_SOURCE_NONE;
1249     switch (sourceConfig)
1250     {
1251         // If autodetecting, decoding everything, and input is something
1252         // (i.e. bitstream or PCM) then decode.
1253         case PAF_SOURCE_AUTO:
1254             if (sourceProgram >= PAF_SOURCE_PCM)  {
1255                 sourceSelect = sourceProgram; // use whatever from autodet
1256             }
1257             break;
1259         // If autodetecting, decoding only PCM, and input is PCM then decode.
1260         case PAF_SOURCE_PCMAUTO:
1261             if (sourceProgram == PAF_SOURCE_PCM) {
1262                 // only expect autodet to give PAF_SOURCE_PCM, otherwise set to NONE
1263                 sourceSelect = sourceProgram;
1264             }
1265             break;
1267         // If autodetecting, decoding only bitstreams, and input is a bitstream then decode.
1268         case PAF_SOURCE_BITSTREAM:
1269             if (sourceProgram >= PAF_SOURCE_AC3) {
1270                 sourceSelect = sourceProgram;
1271             }
1272             break;
1274         // If autodetecting, decoding only DTS, and input is DTS then decode.
1275         case PAF_SOURCE_DTSALL:
1276             switch (sourceProgram)
1277             {
1278                 case PAF_SOURCE_DTS11:
1279                 case PAF_SOURCE_DTS12:
1280                 case PAF_SOURCE_DTS13:
1281                 case PAF_SOURCE_DTS14:
1282                 case PAF_SOURCE_DTS16:
1283                 case PAF_SOURCE_DTSHD:
1284                     sourceSelect = sourceProgram;
1285                     break;
1286             }
1287             break;
1289         // All others, e.g., force modes, fall through to here.
1290         // If user made specific selection then program must match select.
1291         // (NB: this compare relies on ordering of PAF_SOURCE)
1292         default:
1293             sourceSelect = sourceConfig;
1294             if ((sourceSelect >= PAF_SOURCE_PCM) && (sourceSelect <= PAF_SOURCE_N)) {
1295                 if (sourceProgram != sourceSelect) {
1296                     sourceSelect = PAF_SOURCE_NONE;
1297                 }
1298             }
1299             break;
1300     }
1302     // if we didn't find any matches then skip
1303     if (sourceSelect == PAF_SOURCE_NONE) {
1304         TRACE_VERBOSE0("TaskAsip: no matching source type, continue");
1305         return ASIT_ERR_NO_MATCHING_SOURCE;
1306     }
1308 #ifndef PCM_LOOPBACK_TEST
1309     // send source select message to slave
1310     *(Int32 *)&asipMsgBuf[0] = sourceSelect;
1311     if(AspMsgSend(ASP_SLAVE_DEC_SOURCE_SELECT, ASP_MASTER_DEC_SOURCE_SELECT_DONE,
1312                   asipMsgBuf, NULL) != ASP_MSG_NO_ERR) {
1313         TRACE_VERBOSE0("TaskAsip: error in sending SOURCE_SELECT message");
1314         SW_BREAKPOINT;
1315     }
1316 #endif
1318     pInp->sourceSelect  = sourceSelect;
1319     pInp->sourceProgram = sourceProgram;
1321     return ASIT_NO_ERR;
1322 } /* asitDecideSource */
1324 /*==============================================================================
1325  * After SYNC is found, i.e. either bitstream preamble is detected or it times
1326  * out to PCM, update input buffer config and I/o components accordingly.
1327  ==============================================================================*/
1328 Int asitUpdateIoComps(const PAF_ASIT_Params *pP, PAF_AST_Config *pAstCfg,
1329                       PAF_AST_IoInp  *pInp, ioDataAutoDetStat_t *autoDetStatus)
1331     Int sourceConfig;
1332     Int zMD, deliverZeros;
1333     int ioFrameLength, decFrameLength;
1334     PAF_InpBufConfig *pBufConfig;
1335     ioPhyCtl_t  ioPhyCtl;
1336     ioDataCtl_t ioDataCtl;
1338     zMD = pAstCfg->masterDec;
1339     pBufConfig = &pAstCfg->xInp[zMD].inpBufConfig;
1341     // Compute decoder frame length based on source selection
1342     decFrameLength = getFrameLengthSourceSel(pP, pInp->sourceSelect);
1344     pAstCfg->xDec[zMD].decodeControl.frameLength  = decFrameLength;
1345     pAstCfg->xDec[zMD].decodeInStruct.sampleCount = decFrameLength;
1346     pAstCfg->xDec[zMD].decodeControl.sampleRate   = PAF_SAMPLERATE_UNKNOWN;
1348     // Decide frame length for I/O DATA and I/O PHY
1349     if(autoDetStatus->syncState == IODATA_SYNC_PCM) {
1350         // For PCM, I/O frame length is decode frame length multiplied by stride
1351         ioFrameLength = decFrameLength * INPUT_STRIDE;
1353         pBufConfig->sizeofElement = WORD_SIZE_PCM;
1354         pBufConfig->frameLength   = pBufConfig->lengthofData = ioFrameLength;
1356         // Configure I/O DATA PCM frame length
1357         ioDataCtl.code = IODATA_CTL_SET_PCM_FRAME_LENGTH;
1358         ioDataCtl.param.frameLengthPcm = ioFrameLength;
1359         ioDataControl(pInp->hIoData, &ioDataCtl);
1361         // Change I/O PHY transfer size to PCM frame size
1362         pInp->phyXferSize = ioFrameLength*(WORD_SIZE_PCM);
1364         // Adjust I/O BUFF delay and read pointer - to make sure read pointers always point to
1365         // PCM data from 1st I2S (out of 4 for HDMI 4xI2S)
1366         // Adjust delay and don't mark input buffer as read complete
1367         //ioBuffAdjustDelay(pInp->hIoBuff, pInp->phyXferSize);
1369         // Stop swapping data
1370         //pInp->swapData = FALSE;
1371     }
1372     else {
1373         // For bitstream, I/O frame length is the frame length of the bitstream
1374         uint_least16_t pc = autoDetStatus->bitStreamInfo & SYNC_PC_MASK; //0x001F
1375         ioFrameLength = iecFrameLength[pc];
1377 /*
1378         if(   (pc == 0x11) && (DTSHDSubType == 3)
1379            && (PAF_ASP_sampleRateHzTable[pBufConfig->pBufStatus->sampleRateStatus][PAF_SAMPLERATEHZ_STD] <=48000.0))
1380             pDevExt->sourceProgram = PAF_SOURCE_DXP;    // LBR is 23
1382         if (pc == 1)
1383             pDevExt->elementSize = 4288;
1384         else if (pc == 0x11) {
1385             pDevExt->frameLength = (pDevExt->pIECFrameLength[pc] << DTSHDSubType);
1386             pDevExt->lengthofData = pDevExt->frameLength;
1387         }
1388 */
1390         pBufConfig->sizeofElement = WORD_SIZE_BITSTREAM;
1391         pBufConfig->frameLength   = ioFrameLength;
1392         pBufConfig->lengthofData  = ioFrameLength - IEC_HEADER_LENGTH;
1394         // Change I/O PHY transfer size to bitstream frame size
1395         pInp->phyXferSize = ioFrameLength*WORD_SIZE_BITSTREAM;
1396     }
1398     pBufConfig->stride = INPUT_STRIDE;   // common for PCM and bitstream
1400     // Configure I/O PHY transfer size
1401     ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
1402     ioPhyCtl.params.xferFrameSize = pInp->phyXferSize;
1403     ioPhyControl(pInp->hIoPhy, &ioPhyCtl);
1405     // Decide if zeros should be delivered based on the configured source
1406     sourceConfig = (Int)sharedMemReadInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceSelect),
1407                                           GATEMP_INDEX_DEC);
1409     if(autoDetStatus->syncState == IODATA_SYNC_PCM) {
1410         // Bitstream preamble is not found and it times out -> assume this is PCM
1411         deliverZeros = autoDetStatus->deliverZeros;
1412         if (sourceConfig == PAF_SOURCE_PCM || sourceConfig == PAF_SOURCE_DSD1 ||
1413             sourceConfig == PAF_SOURCE_DSD2 || sourceConfig == PAF_SOURCE_DSD3) {
1414             // set to one -- ensures that PCM decode calls made before data is
1415             // available will result in zero output.
1416             // (mostly needed for PA15 since, currently, all other frameworks
1417             // require a frame of data before the first decode call.
1418             deliverZeros = TRUE;  // override deliverZeros returned by ioDataControl
1419         }
1421         // update input buffer config structure
1422         pBufConfig->deliverZeros  = deliverZeros;
1423     }
1425     //JXTODO: decide what to do with hRxSio
1426     //temporary - does ARM use hRxSio or just check if it is not NULL?
1427     pAstCfg->xInp[zMD].hRxSio = pInp->hIoData;
1428     pAstCfg->xInp[zMD].pInpBuf = &(pAstCfg->xInp[zMD].inpBufConfig);
1430     return ASIT_NO_ERR;
1431 } /* asitUpdateIoComps */
1434 #ifndef IO_LOOPBACK_TEST
1435 #if OUTPUT_FRAME_LENGTH == INPUT_FRAME_LENGTH
1436 U8 pcmbuf[OUTPUT_FRAME_SIZE];
1437 #else
1438 #error Input frame length is not equal to output frame length!
1439 #endif
1441 Int rxDecodePcm(PAF_AST_IoInp  *pInp)
1443     ioDataCtl_t ioDataCtl;
1444     void *buffBase;
1445     void *dataStartAddress;
1446     size_t buffSize, frameSize, size1, size2;
1448     /* Get information for reading input data */
1449     ioDataCtl.code = IODATA_CTL_GET_INPBUFFINFO;
1450     ioDataControl(pInp->hIoData, &ioDataCtl);
1452     buffBase = ioDataCtl.param.dataReadInfo.buffBase;
1453     buffSize = ioDataCtl.param.dataReadInfo.buffSize;
1454     dataStartAddress = ioDataCtl.param.dataReadInfo.startAddress;
1455     frameSize        = ioDataCtl.param.dataReadInfo.frameSize;
1457     // Copy PCM data to output buffer
1458     if(((size_t)dataStartAddress+frameSize) <= ((size_t)buffBase+buffSize)) {
1459         // Input buffer doesn't wrap around
1460         Cache_inv(dataStartAddress, frameSize, Cache_Type_ALL, TRUE);
1461         memcpy((void *)&pcmbuf[0], dataStartAddress, frameSize);
1462     }
1463     else {
1464         // Input buffer wraps around
1465         size1 = (size_t)buffBase + buffSize - (size_t)dataStartAddress;
1466         size2 = frameSize - size1;
1467         Cache_inv(dataStartAddress, size1, Cache_Type_ALL, TRUE);
1468         memcpy((void *)&pcmbuf[0], dataStartAddress, size1);
1470         Cache_inv(buffBase, size2, Cache_Type_ALL, TRUE);
1471         memcpy((void *)&pcmbuf[size1], buffBase, size2);
1472     }
1475     return ASIT_NO_ERR;
1479 Int rxDecodePlayZero(PAF_AST_IoInp  *pInp)
1481     return ASIT_NO_ERR;
1483 #endif
1485 Int asitEvtErrCheck(UInt actualEvents, UInt expectedEvents)
1487     TRACE_VERBOSE2("ASIT events error: actual events are: %d, expected events are: %d.",
1488                    actualEvents, expectedEvents);
1490     return ASIT_ERR_EVENTS;
1493 void asitErrorHandling(PAF_ASIT_Config *pAsitCfg, Int asitErr)
1495     UInt events;
1497     if(asitErr == ASIT_ERR_INPBUF_UNDERFLOW) {
1498         TRACE_VERBOSE0("ASIT error handling: input buffer underflows. No actions needed.");
1499     }
1501     if(asitErr == ASIT_ERR_DECODE_QUIT) {
1502         TRACE_VERBOSE0("ASIT error handling: DECODE_QUIT - clear INPDATA event.");
1504         // Pend on INPTDATA event that should have been posted before decoding quits.
1505         events = Event_pend(asitEvent, ASIT_EVTMSK_NONE, ASIT_EVTMSK_INPDATA,
1506                             BIOS_WAIT_FOREVER);
1508         // Marks I/O PHY transfer and I/O BUFF write complete
1509         asitPhyTransferComplete(&pAsitCfg->pIoInp[0]);
1511         pAsitCfg->pIoInp[0].asipState = ASIT_RESET;
1512         pAsitCfg->pIoInp[0].numAsitRestart++;
1513         TRACE_VERBOSE0("ASIT error handling finished. Go to state ASIT_RESET.");
1514     }
1516     if(asitErr == ASIT_ERR_EVENTS) {
1517         pAsitCfg->pIoInp[0].asipState = ASIT_RESET;
1518         pAsitCfg->pIoInp[0].numAsitRestart++;
1519         TRACE_VERBOSE0("ASIT error handling: events error. Go to state ASIT_RESET.");
1520     }
1522     return;
1523 }  /* asitErrorHandling */
1526 //////////////////////////////////////////////////////////////////////////////
1527 void asitPostInfoEvent()
1529     Event_post(asitEvent, ASIT_EVTMSK_INFOACK);
1532 void asitPostDecEvent()
1534     Event_post(asitEvent, ASIT_EVTMSK_DECACK);
1536 //////////////////////////////////////////////////////////////////////////////
1538 /* Nothing past this line */