5460aeefc307996d3dd4d82ae946d7624387b7d2
[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 "aud.h"
53 #include "aud_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 DEBUG_SKIP_DECODING
65 #define SYNC_PC_MASK         0x1F
66 #define SYNC_SUBTYPE_MASK    0x700
67 #define SYNC_SUBTYPE_SHIFT   8
68 #define SYNC_SUBTYPE_DTSHD   0x11
69 #define SYNC_DDP             0x15
70 #define SYNC_THD             0x16
72 #define IEC_HEADER_LENGTH    4
74 #define INPUT_SWITCH_HANGOVER 8
76 //table needed until PAF_SOURCE is reordered to match IEC numbering
77 const SmUns IECpafSource[23] =
78 {
79     PAF_SOURCE_UNKNOWN,  // 0: IEC NULL Type
80     PAF_SOURCE_AC3,      // 1: Comments on 1-15 match IEC 61937 part 2.
81     PAF_SOURCE_UNKNOWN,  // 2: IEC reserved
82     PAF_SOURCE_UNKNOWN,  // 3: IEC pause
83     PAF_SOURCE_UNKNOWN,  // 4: MPEG 1 layer 1
84     PAF_SOURCE_MP3,      // 5: MPEG layer 2 or 3
85     PAF_SOURCE_UNKNOWN,  // 6: MPEG 2 data with extension
86     PAF_SOURCE_AAC,      // 7: MPEG-2 AAC ADTS
87     PAF_SOURCE_UNKNOWN,  // 8: MPEG 2 layer 1 low sampling frequency
88     PAF_SOURCE_UNKNOWN,  // 9: MPEG 2 layer 2 or 3 low sampling frequency
89     PAF_SOURCE_UNKNOWN,  // 10: reserved
90     PAF_SOURCE_DTS,      // 11: DTS type 1 (11 bit: 512 sample repeat period)
91     PAF_SOURCE_DTS12,    // 12: DTS type 2 (12 bit: 1024 sample repeat period)
92     PAF_SOURCE_DTS13,    // 13: DTS type 3 (13 bit: 2048 sample repeat period)
93     PAF_SOURCE_DTS14,    // 14: ATRAC
94     PAF_SOURCE_UNKNOWN,  // 15: ATRAC 2/3
95     PAF_SOURCE_THD,      // 16
96     PAF_SOURCE_DTSHD,    // 17
97     PAF_SOURCE_WMA9PRO,  // 18
98     PAF_SOURCE_UNKNOWN,  // 19
99     PAF_SOURCE_UNKNOWN,  // 20
100     PAF_SOURCE_DDP,      // 21
101     PAF_SOURCE_THD,      // 22
102 };
104 /*
105  * Functions defined in other files and to be put into proper header files
106  */
107 extern Void taskAsipFxnInit(const PAF_ASIT_Params *pP,const PAF_ASIT_Patchs *pQ);
110 // avoid including sap_d10.h, which would cause symbol redefinition
111 // warning (MCASP_PFUNC_XXX)
112 extern XDAS_Int32 D10_init(void * pD10Params);
114 extern XDAS_Int32 D10_RxControl(const void *pD10RxParams,
115                                 XDAS_Int32 code, XDAS_Int32 arg);
117 /*
118  * Functions only used in this file
119  */
120 int asitPrepareProcessing();
121 int asitIoCompsInit(PAF_AST_InpBuf * pInpBuf, PAF_AST_IoInp * pInpIo);
122 void asitProcInit(PAF_AST_IoInp  *pInp, asipDecProc_t *pDec);
123 void asitIoPhyPrime(PAF_AST_IoInp *pInpIo);
124 void asitPhyTransferComplete(PAF_AST_IoInp * pInpIo);
125 void asitPhyTransferStart(PAF_AST_IoInp *pInpIo);
126 Int asitRecfgPhyXfer(PAF_AST_IoInp *pInp, size_t xferSize);
127 Int asitSelectDevices(const PAF_ASIT_Patchs *pQ, PAF_AST_Config *pAstCfg, PAF_AST_IoInp *pInp);
128 Int asitUpdateInputStatus(const void *pRxParams, PAF_InpBufStatus *pStatus,
129                           PAF_InpBufConfig *pInpBuf);
131 Int asitSourceDetection(const PAF_ASIT_Params *pP,
132                         const PAF_ASIT_Patchs *pQ,
133                         PAF_ASIT_Config       *pAsitCfg);
135 Int asitDecideSource(PAF_AST_Config *pAstCfg, PAF_AST_IoInp  *pInp,
136                      ioDataAutoDetStat_t *autoDetStatus);
137 Int asitUpdateIoComps(const PAF_ASIT_Params *pP, PAF_AST_Config *pAstCfg,
138                       PAF_AST_IoInp  *pInp, ioDataAutoDetStat_t *autoDetStatus);
139 Int asitBypassIoData(PAF_AST_IoInp *pInp);
140 Int asitPcmTransition(PAF_ASIT_Config *pAsitCfg);
142 void asitUpdateInpBufConfig(PAF_AST_Config *pAstCfg, PAF_AST_IoInp  *pInp);
143 Int asitInputDataProcess(PAF_AST_IoInp *pInp, ioDataAutoDetStat_t *pAutoDetStats);
145 UInt asitEventsToDecMsg(UInt asitEvents);
146 void asitErrorHandling(PAF_ASIT_Config *pAsitCfg, Int asitErr);
147 Int asitEvtErrCheck(UInt actualEvents, UInt expectedEvents);
149 void asitPostInfoEvent();
150 void asitPostDecEvent();
152 /*
153  * variables/structures to be put into proper global structures
154  */
155 extern PAF_ASIT_Config gPAF_ASIT_config;
156 extern const MdUns iecFrameLength[23];
157 extern Ptr hMcaspRxChan;
159 // temp for simulation
160 //#define ASIT_ALL_EVENTS (  ASIT_EVTMSK_INPDATA \
161 //                         + ASIT_EVTMSK_INFOACK \
162 //                         + ASIT_EVTMSK_DECACK )
163 #define ASIT_ALL_EVENTS (  ASIT_EVTMSK_INPDATA \
164                          + ASIT_EVTMSK_RXACK )
166 // temp for simulation
167 //#define ASIT_DEC_EVENTS (  ASIT_EVTMSK_INPDATA \
168 //                         + ASIT_EVTMSK_INFOACK \
169 //                         + ASIT_EVTMSK_DECACK )
170 #define ASIT_DEC_EVENTS (  ASIT_EVTMSK_INPDATA \
171                          + ASIT_EVTMSK_RXACK )
173 #define ASIP_DEBUG
175 #ifdef ASIP_DEBUG
176 /* define the following as global variables for easy debugging */
177 int asipLoopCount1, asipLoopCount2;
178 Int asipErrno;
179 Int inputReadyForProcessing;
181 // debug
182 #include "evmc66x_gpio_dbg.h"
183 #endif
185 Event_Handle gAsitEvtHandle;            // ASIT event handle
186 Int eventsOn;                           // flag indicating whether to process events
188 SyncEvent_Handle gAsitSyncEvtHandle;    // ASIT Sync event handle
190 /*
191  *  ======== taskAsipFxn ========
192  *  Audio Stream Input Processing task function
193  */
194 #ifndef PASDK_SIO_DEV
195 #ifndef IO_LOOPBACK_TEST
196 Void taskAsipFxn(                  // ASIP task function for new I/O
197 #else
198 Void taskAsipFxn_NewIO_Not_Used(   // not used for loopback test
199 #endif
200 #else
201 Void taskAsipFxn_NewIO_Not_USED(   // not used for SIO/DEV based I/O
202 #endif
203     const PAF_ASIT_Params *pP,
204         const PAF_ASIT_Patchs *pQ)
206     PAF_ASIT_Config *pAsitCfg;      /* ASIT configuration pointer */
207     PAF_AST_Config  *pAstCfg;       /* AST Common (shared) configuration pointer */
208     PAF_AST_IoInp *pInp;            /* Input I/O components */
209     Int as;                         /* Audio Stream Number (1, 2, etc.) */
210     Int z;                          /* input/encode/stream/decode/output counter */
211     Int zMI;
212 #ifndef ASIP_DEBUG
213 int asipLoopCount1, asipLoopCount2;
214 Int asipErrno;
215 Int inputReadyForProcessing;
216 #endif
217     Int asitErr;
218     UInt events;
219 //    Int eventsOn;
220 //    Error_Block  eb;
222     Log_info0("Enter taskAsipFxn()");
224     taskAsipFxnInit(pP, pQ);  // initialization of input task
225     
226     //
227     // Audio Stream Input Task Configuration (*pAsitCfg):
228     //
229     pAsitCfg = &gPAF_ASIT_config;       // initialize pointer to task configuration
230     pAstCfg  = pAsitCfg->pAstCfg;       // pointer to AST common (shared) configuration
232     /* Set Audio Stream Number (1, 2, etc.) */
233     as = pAstCfg->as;
235     //
236     // Determine decoder and stream indices associated with the master input
237     //
238     zMI  = pP->zone.master;
239     pInp = &pAsitCfg->pIoInp[zMI];        // pointer to input I/O components
241     for (z=STREAM1; z < STREAMN; z++)
242     {
243         TRACE_VERBOSE1("TaskAsip: AS%d: running", as+z);
244     }
246     Log_info0("TaskAsip: Entering Main Loop.");
248     //
249     // Main processing loop
250     //
251     asipLoopCount1 = 0;
252     asipLoopCount2 = 0;
253     asitErr = ASIT_NO_ERR;
255     // The events_on flag will be removed if the RESTART state is changed to
256     // event-based scheduling instead of polling
257     eventsOn = FALSE;
259     for (;;)
260     {
261         asipLoopCount1++;
263         if(eventsOn) {
264             events = Event_pend(gAsitEvtHandle, ASIT_EVTMSK_NONE, ASIT_ALL_EVENTS,
265                                 BIOS_WAIT_FOREVER);
266         }
267         switch (pInp->asipState)
268         {
269         case ASIT_RESET:    // No events pending in this state
270             // Indicate decoder no decoding yet
271             pP->fxns->sourceDecode(pP, pQ, pAsitCfg, PAF_SOURCE_NONE);
273             // 5 system tick, or 5 msec. Should remove this later when implementing
274             // event based scheduling.
275             Task_sleep(5);
277             inputReadyForProcessing = asitPrepareProcessing(pP, pQ, pAsitCfg, &asipErrno);
278             if (inputReadyForProcessing) {
279                 TRACE_VERBOSE0("TaskAsip: Input is ready. Initialize I/O components.");
280                 // Input is ready for processing, so we initialize the I/O components.
281                 // Note that the I/O components init. and I/O PHY prime are performed only
282                 // at the first time. This should be changed later - init. and prime
283                 // should be done whenever input interface has changed.
284                 asitErr = asitIoCompsInit(&pAstCfg->xInp[zMI], pInp);
286                 // Initialize ASIT processing
287                 asitProcInit(pInp, &pAsitCfg->inpDec);
288                 pInp->asipState = ASIT_SOURCE_DETECTION;
289                 eventsOn = TRUE;   // turn on events pending
290                 TRACE_VERBOSE0("TaskAsip: turn on events and go to source detection.");
291             }
292             break;
294         case ASIT_SOURCE_DETECTION:
295             // Source unknown - to detect & identify source
296             if(events == ASIT_EVTMSK_INPDATA) {  
297                 // Only this event is expected. If any other event, it's error.
298                 // Input data is ready - perform source detection.
299                 // New state will be decided inside the function
300                 asitErr = asitSourceDetection(pP, pQ, pAsitCfg);
301             }
302             else {
303                 //Error checking & debug
304                 asitErr = asitEvtErrCheck(events, ASIT_EVTMSK_INPDATA);
305             }
307             break;
309         case ASIT_PCM_TRANSITION:
310             // Source is PCM - transition to PCM decoding
311             if(events == ASIT_EVTMSK_INPDATA) {
312                 // Only this event is expected. If any other event, it's error.
313                 // Input data is ready - transition to PCM decoding
314                 // New state will be decided inside the function
315                 asitErr = asitPcmTransition(pAsitCfg);
316             }
317             else {
318                 //Error checking & debug
319                 asitErr = asitEvtErrCheck(events, ASIT_EVTMSK_INPDATA);
320             }
321             break;
323         case ASIT_DECODE_PROCESSING:
324             if(events & ASIT_DEC_EVENTS) {
325                 
326 #if 1 // debug 
327                 if (events & ASIT_EVTMSK_INPDATA)
328                 {
329                     // shows timing of Input (Rx McASP EDMA)
330                     // ADC B5
331                     {
332                         static Uint8 toggleState = 0;
333                         if (toggleState == 0)
334                             GPIOSetOutput(GPIO_PORT_0, GPIO_PIN_99);
335                         else
336                             GPIOClearOutput(GPIO_PORT_0, GPIO_PIN_99);
337                         toggleState = ~(toggleState);
338                     }
339                 }
340 #endif           
341                 
342                 // Decode processing for either PCM or bitstream
343                 // New state will be decided inside the function
344                 asitErr = asitDecodeProcessing(pP, pQ, pAsitCfg, events);
345             }
346             else {
347                 //Error checking & debug
348                 asitErr = asitEvtErrCheck(events, ASIT_DEC_EVENTS);
349             }
350             break;
352         default:
353             break;
354         }
356         if(asitErr) {
357             asitErrorHandling(pAsitCfg, asitErr);
359             if(pInp->asipState == ASIT_RESET) {
360                 eventsOn = FALSE;
361             }
363             asitErr = ASIT_NO_ERR;
364         }
366     }  // for (;;)
368 }  /* taskAsipFxn */
371 /*===========================================================================
372  * ASIT Processing Preparation
373  * Output:
374  *        - return        TRUE (input is ready) or FALSE (input is not ready)
375  *        - *asipErrno    Error number
376 ============================================================================*/
377 Int asitPrepareProcessing(const PAF_ASIT_Params *pP,
378                           const PAF_ASIT_Patchs *pQ,
379                           PAF_ASIT_Config       *pC,
380                           Int                   *asipErrno)
382     Int as, zMS, zMI, zMD;
383     Int sourceConfig, mode;
384     PAF_AST_Config  *pAstCfg;
385     PAF_AST_IoInp *pInp;            /* I/O components for input */
387     pAstCfg  = pC->pAstCfg;         // pointer to AST common (shared) configuration
388     as  = pAstCfg->as;
389     zMI = pP->zone.master;
390     zMD = pAstCfg->masterDec;
391     zMS = pAstCfg->masterStr;
392     pInp = pC->pIoInp;              // pointer to input I/O components
394     *asipErrno = 0;
396     // Select source and initialize physical layer / HW interface
397     *asipErrno = asitSelectDevices(pQ, pAstCfg, pInp);
398     if (*asipErrno) {
399         TRACE_TERSE2("asitSelectDevices returned asipErrno = 0x%04x at line %d. AS%d",
400                      *asipErrno, as+zMS);
401         return FALSE;    // Input is not ready for processing due to error
402     }
404     // If no master input selected then we don't know what may be at the input,
405     // so set to unknown and skip any remaining processing
406     if (!pInp[zMI].pRxParams) {
407         sharedMemWriteInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceProgram),
408                            (Int8)PAF_SOURCE_UNKNOWN, GATEMP_INDEX_DEC);
410         TRACE_VERBOSE1("TaskAsip: AS%d: No input selected...", as+zMS);
411         return FALSE;    // No error, but input is not ready for processing
412     }
414     // If here then we have a valid input so query its status
415     *asipErrno = asitUpdateInputStatus(pInp[zMI].pRxParams,
416                                    &pAstCfg->xInp[zMI].inpBufStatus,
417                                    &pAstCfg->xInp[zMI].inpBufConfig);
418     if(*asipErrno) {
419         TRACE_VERBOSE1("TaskAsip: updateInputStatus returns 0x%x", *asipErrno);
420         return FALSE;   // Input is not ready for processing due to error
421     }
423     // If master decoder is not enabled, or the input is unlocked, then do nothing
424     mode = (Int)sharedMemReadInt8(&(pAstCfg->xDec[zMD].decodeStatus.mode),
425                                   GATEMP_INDEX_DEC);
426     if (!mode || !pAstCfg->xInp[zMI].inpBufStatus.lock)
427     {
428         TRACE_VERBOSE0("TaskAsip: Not locked, continue");
429         return FALSE;  // No error, but input is not ready for processing
430     }
432     // Check selected source: sourceSelect is set by another task, AIP or AFP
433     sourceConfig = (Int)sharedMemReadInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceSelect),
434                                           GATEMP_INDEX_DEC);
435     // If no source selected then do nothing
436     if(sourceConfig == PAF_SOURCE_NONE) {
437         sharedMemWriteInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceProgram),
438                            (Int8)PAF_SOURCE_NONE, GATEMP_INDEX_DEC);
439         TRACE_VERBOSE1("TaskAsip: AS%d: no source selected, continue", as+zMS);
440         return FALSE;  // No error, but input is not ready for processing
441     }
443     // If we want pass processing then proceed directly
444     if (sourceConfig == PAF_SOURCE_PASS)
445     {
446         TRACE_VERBOSE1("TaskAsip: AS%d: Pass processing ...", as+zMS);
447         sharedMemWriteInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceProgram),
448                            (Int8)PAF_SOURCE_PASS, GATEMP_INDEX_DEC);
450         pP->fxns->sourceDecode(pP, pQ, pC, PAF_SOURCE_PASS);
451         if (pP->fxns->passProcessing) {
452             *asipErrno = pP->fxns->passProcessing(pP, pQ, pC, NULL);
453         }
454         else {
455             TRACE_TERSE2("TaskAsip: AS%d: Pass Processing not supported, asipErrno 0x%x",
456                          as+zMS, ASPERR_PASS);
457             *asipErrno = ASPERR_PASS;
458         }
460         TRACE_VERBOSE0("TaskAsip: continue");
461         return FALSE;  // Error or not, input is not ready for processing
462     }
464     // No error and input processing is ready
465     return TRUE;
466 } /* asitPrepareProcessing */
469 /*===========================================================================
470  * ASIT Source Detection:
471  *     ASIT processing for input source identification:
472  *     - mark I/O PHY transfer completion
473  *     - run auto-detection via I/O DATA in asitInputDataProcess
474  *     - mark I/O DATA read completion
475  *     - check auto-detection status and take corresponding actions if either
476  *       PCM or bitstream is identified:
477  *       - decide input source
478  *       - update I/O components
479  *       - reconfigure McASP LLD if it is PCM
480  *     - start next I/O PHY transfer
481 ============================================================================*/
482 Int asitSourceDetection(const PAF_ASIT_Params *pP,
483                         const PAF_ASIT_Patchs *pQ,
484                         PAF_ASIT_Config       *pAsitCfg)
486     PAF_AST_Config  *pAstCfg;
487     PAF_AST_IoInp *pInp;                // I/O components for input
488     Int zMD, mcaspErr, asitErr;
489     ioDataAutoDetStat_t autoDetStatus;
491     pAstCfg  = pAsitCfg->pAstCfg;               // pointer to AST common (shared) configuration
492     zMD = pAstCfg->masterDec;
493     pInp = &pAsitCfg->pIoInp[zMD];              // pointer to input I/O components
495     // Marks I/O PHY transfer and I/O BUFF write complete
496     asitPhyTransferComplete(pInp);
498     // Process input data - either searching SYNC for PCM or checking SYNC for bitstream
499     asitErr = asitInputDataProcess(pInp, &autoDetStatus);
500     if(asitErr != ASIT_NO_ERR) {
501         // Even though there is error, still need to start next transfer to
502         // maintain McASP transfer.
503         asitPhyTransferStart(pInp);
505         return asitErr;
506     }
508     // Mark input data read complete
509     ioDataReadComplete(pInp->hIoData);
511     // Check if bitstream or PCM is detected
512     if(   autoDetStatus.syncState == IODATA_SYNC_BITSTREAM
513        || autoDetStatus.syncState == IODATA_SYNC_PCM) {
514         // Decide input source and inform decoder
515         asitErr = asitDecideSource(pAstCfg, pInp, &autoDetStatus);
516         if(asitErr != ASIT_NO_ERR) {
517             return asitErr;
518         }
519         else {
520             // Update I/O components and input buffer config
521             asitUpdateIoComps(pP, pAstCfg, pInp, &autoDetStatus);
523             // set to unknown so that we can ensure, for IOS purposes, that
524             // sourceDecode = NONE iff we are in this top level state machine
525             // and specifically not in decodeProcessing
526 #ifndef DEBUG_SKIP_DECODING
527             pP->fxns->sourceDecode(pP, pQ, pAsitCfg, PAF_SOURCE_UNKNOWN);
528 #endif
530             if(autoDetStatus.syncState == IODATA_SYNC_BITSTREAM) {
531                 // Input is bit stream: go to decoding
532                 pInp->asipState = ASIT_DECODE_PROCESSING;
533             }
534             else  {
535                 // Input is PCM: stop swapping data
536                 pInp->swapData = FALSE;
538                 // Reconfigure McASP LLD to transfer 32-bit unpacked data
539                 mcaspErr = mcaspRecfgWordWidth(pInp->hMcaspChan, Mcasp_WordLength_32);
540                 if(mcaspErr != Aud_EOK) {
541                     return ASIT_ERR_MCASP_CFG;
542                 }
544                 // Adjust I/O BUFF delay and read pointer - to make sure read pointers
545                 // always point to PCM data from 1st I2S (out of 4 for HDMI 4xI2S)
546                 ioBuffAdjustDelay(pInp->hIoBuff, pInp->phyXferSize);
548                 // Go to transition state to switch to PCM
549                 pInp->asipState = ASIT_PCM_TRANSITION;
550             }
551         }
552     }
554     // Start next transfer
555     asitPhyTransferStart(pInp);
557     return (ASIT_NO_ERR);
558 }  /* asitSourceDetection */
561 /*===========================================================================
562     //
563     // which will cause all 0's in one McASP LLD transfer. This will
564     // be detected as loss of SYNC by auto detection. To prevent that,
565     // skip I/O DATA process for hangover period so that this all 0's
566     // frame will not be seen by auto-detection. Also, playing out PCM
567     // needs to be skipped as well, to prevent from playing out garbage
568     // (16-bit packed data).
569  *
570  * ASIT Transition to PCM decoding.
571  *     When PCM is detected, McASP LLD will be reconfigured to transmit 32-bit
572  *     words, which will modify the RFMT register. This will cause all 0's in
573  *     one McASP LLD transfer, which would be detected as loss of SYNC by auto
574  *     detection (performed by I/O DATA). To prevent that, skip I/O DATA process
575  *     for hangover period so that this all-0's frame will not be seen by the
576  *     auto-detection.
577  *
578  *     In addition, playing out PCM should be skipped as well to prevent from
579  *     playing out the 16-bit packed data that's still in the input buffer.
580  *
581  *     This function does the following:
582  *     - mark I/O PHY transfer completion
583  *     - bypass I/O DATA
584  *     - start next I/O PHY transfer
585 ============================================================================*/
586 Int asitPcmTransition(PAF_ASIT_Config *pAsitCfg)
588     Int asitErr;
589     PAF_AST_IoInp *pInp;                  // I/O components for input
590     Int zMD;
592     zMD = pAsitCfg->pAstCfg->masterDec;   // pointer to AST common (shared) configuration
593     pInp = &pAsitCfg->pIoInp[zMD];        // pointer to input I/O components
595     // Marks I/O PHY transfer and I/O BUFF write complete
596     asitPhyTransferComplete(pInp);
598     // Bypass I/O data processing due to McASP LLD work around
599     // (refer to comments inside the function)
600     asitErr = asitBypassIoData(pInp);
602     pInp->pcmSwitchHangOver--;
603     if(pInp->pcmSwitchHangOver == 0) {
604         pInp->asipState = ASIT_DECODE_PROCESSING;
605     }
606     else {
607         ; // stay in this state
608     }
610     // Start next transfer
611     asitPhyTransferStart(pInp);
613     return asitErr;
615 } /* asitPcmTransition */
617 /*============================================================================
618  * ASIT Bypass I/O DATA Processing
619  *     This function bypasses the I/O DATA processing. It maintains the read
620  *     operation of I/O BUFF by directly calling I/O BUFF APIs. When I/O DATA
621  *     is not bypassed, I/O BUFF read operation is invoked by I/O DATA.
622  *
623 ============================================================================*/
624 Int asitBypassIoData(PAF_AST_IoInp *pInp)
626     void *buff1, *buff2;
627     size_t size1, size2;
629     // Get read pointers (or sub-buffers) of the input buffer
630     if (ioBuffGetReadPtrs(pInp->hIoBuff, pInp->phyXferSize,
631                           &buff1, &size1, &buff2, &size2)
632         == IOBUFF_ERR_UNDERFLOW) {
633         pInp->numUnderflow += 1;
635         // Return since there is no enough data to process
636         return ASIT_ERR_INPBUF_UNDERFLOW;
637     }
639     ioBuffReadComplete(pInp->hIoBuff, buff1, size1);
641     if(buff2 != NULL) {
642         ioBuffReadComplete(pInp->hIoBuff, buff2, size2);
643     }
645     return ASIT_NO_ERR;
646 } /* asitBypassIoData */
649 /*============================================================================
650  * ASIT Decode Processing
651  *     This function performs the decode processing and does the following based
652  *     on the ASIT events:
653  *     - initialize the decode processing if it is the first time
654  *     - if there is ASIT INPUT DATA event (ASIT_EVTMSK_INPDATA):
655  *        - mark I/O PHY transfer completion
656  *        - run auto-detection via I/O DATA in asitInputDataProcess
657  *        - check auto-detection status and take corresponding actions if SYNC
658  *          is lost.
659  *        - start next I/O PHY transfer
660  *     - map ASIT events to decoding messages
661  *     - invoke decDecodeFsm() and pass the mapped decoding messages
662  *     - if there is ASIT DECODE ACK event (ASIT_EVTMSK_DECACK)
663  *        - mark I/O DATA read completion
664  *     - error handling
665 ============================================================================*/
666 Int asitDecodeProcessing(const PAF_ASIT_Params *pP,
667                          const PAF_ASIT_Patchs *pQ,
668                          PAF_ASIT_Config       *pAsitCfg,
669                          UInt asitEvents)
671     Int asitErr, decErr;
672     PAF_AST_IoInp *pInp;                  // I/O components for input
673     AspMsgMaster_Handle hAspMsgMaster;    // ASIT message master handle
674     asipDecProc_t *pDec;
675     ioDataAutoDetStat_t autoDetStatus;
676     Int zMD;
677     UInt decMsg;
678     Int status;
680     zMD = pAsitCfg->pAstCfg->masterDec;         // pointer to AST common (shared) configuration
681     pInp = &pAsitCfg->pIoInp[zMD];              // pointer to input I/O components
682     hAspMsgMaster = pAsitCfg->hAspMsgMaster;    // get ASIT message master handle
683     pDec = &pAsitCfg->inpDec;
685     // Initialization for decode processing when this function is called the first time
686 #ifndef DEBUG_SKIP_DECODING
687     if(!pDec->initDone) {
688         // Initialize decoder
689         decDecodeInit(pP, pAsitCfg, pInp->sourceSelect);
691         pDec->initDone = TRUE;
692     }
693 #endif
695     // Process input data if this is a data ready message
696     if(asitEvents & ASIT_EVTMSK_INPDATA) {
697         TRACE_TERSE0("asitDecodeProcessing: process input data.");
699         // Marks I/O PHY transfer and I/O BUFF write complete
700         asitPhyTransferComplete(pInp);
702         // Process input data - either search SYNC for PCM or check SYNC for bitstream
703         asitErr = asitInputDataProcess(pInp, &autoDetStatus);
705         if(asitErr == ASIT_NO_ERR) {
706             ioDataReadComplete(pInp->hIoData);
708             // Check if SYNC is maintained or lost (stream stops or format changes)
709             if(autoDetStatus.syncState == IODATA_SYNC_NONE) {
710                 // SYNC lost: change I/O PHY transfer size to default for auto-detection
711                 //asitErr = asitRecfgPhyXfer(pInp, INPUT_FRAME_SIZE_DEF);
712                 //if(asitErr != ASIT_NO_ERR) {
713                 //    return asitErr;
714                 //}
716                 // Inform decoder to complete the decoding of previous frame - is this good?
717                 pInp->sourceSelect = PAF_SOURCE_NONE;
718                 pInp->numFrameReceived = 0;    // for debugging
719                 TRACE_TERSE0("asitDecodeProcessing: SYNC lost.");
721 #ifdef DEBUG_SKIP_DECODING
722                 asitErr = ASIT_ERR_DECODE_QUIT;
723 #endif
724             }
725             else {
726                 pInp->numFrameReceived += 1;    // for debugging
728                 // Communicate input stream information to decoder through input
729                 // buffer configuration
730                 asitUpdateInpBufConfig(pAsitCfg->pAstCfg, pInp);
732                 // Start next transfer
733                 asitPhyTransferStart(pInp);
734             }
736             // Start next transfer
737             //asitPhyTransferStart(pInp);
739 #ifdef DEBUG_SKIP_DECODING
740             return asitErr;
741 #endif
742         }
743         else if(asitErr == ASIT_ERR_INPBUF_UNDERFLOW) {
744             TRACE_TERSE0("asitDecodeProcessing: Input buffer underflows.");
746             // When input buffer underflows, it is not an error but decoding needs
747             // to be skipped as there is not enough data in the buffer.
748             asitPhyTransferStart(pInp);
750             return asitErr;
751         }
752         else {
753             // Inform decoder to complete the decoding of previous frame - is this good?
754             pInp->sourceSelect = PAF_SOURCE_NONE;
755             pInp->numFrameReceived = 0;    // for debugging
756             TRACE_TERSE1("asitDecodeProcessing: asitInputDataProcess error: %d", asitErr);
758 #ifdef DEBUG_SKIP_DECODING
759             return ASIT_ERR_DECODE_QUIT;
760 #endif
761         }
762     } /* ASIT_EVTMSK_INPDATA */
763 #ifdef DEBUG_SKIP_DECODING
764     else {
765         TRACE_TERSE0("asitDecodeProcessing: events error.");
766         return ASIT_ERR_EVENTS;
767     }
768 #endif
770 #ifndef DEBUG_SKIP_DECODING
771     // Map ASIT events to decode messages
772     decMsg = asitEventsToDecMsg(asitEvents);
774     // Pass messages (corresponding to events) to decode FSM
775     decErr = decDecodeFsm(pP, pQ, pAsitCfg, pInp->sourceSelect, decMsg);
777     // Mark I/O DATA read complete if decoder indicates decoding is done.
778     if((asitEvents & ASIT_EVTMSK_DECACK)) {  // DECACK -> decoding done
779         //ioDataReadComplete(pInp->hIoData);
780     }
782     if(decErr != DEC_NO_ERR) {
783         TRACE_VERBOSE0("TaskAsip: send DEC_EXIT message to slave decoder.");
785         // Send dec exit message to slave decoder
786         status = AspMsgSnd(hAspMsgMaster, ASP_SLAVE_DEC_EXIT, NULL);
787         if (status != ASP_MSG_NO_ERR)
788         {
789             TRACE_VERBOSE0("TaskAsip: error in sending DEC_EXIT message");
790             SW_BREAKPOINT;
791         }
792         status = AspMsgRcvAck(hAspMsgMaster, ASP_MASTER_DEC_EXIT_DONE, NULL, TRUE);
793         if (status != ASP_MSG_NO_ERR) 
794         {
795             TRACE_VERBOSE0("TaskAsip: error in sending DEC_EXIT message");
796             SW_BREAKPOINT;
797         }
799         return ASIT_ERR_DECODE_QUIT;  // This is not necessarily an error
800     }
801     else {
802         return ASIT_NO_ERR;
803     }
804 #endif
805 }  /* asitDecodeProcessing */
808 /*============================================================================
809  * ASIT Input Data Processing:
810  *    - invoke ioDataProcess() to inspect input data for
811  *       - initial auto-detection,  or
812  *       - background scanning for PCM data, or
813  *       - SYNC check for bitstream
814  *    - return auto-detection status (SYNC detected, SYNC loss, etc)
815 ============================================================================*/
816 Int asitInputDataProcess(PAF_AST_IoInp *pInp, ioDataAutoDetStat_t *pAutoDetStats)
818     Int ioDataErr, retVal;
819     ioDataCtl_t ioDataCtl;
821     // Perform auto-detection inside I/O DATA component
822     ioDataErr = ioDataProcess(pInp->hIoData);
824     if(ioDataErr == IODATA_NO_ERR) {
825         // Normal operation - check auto-detection status
826         ioDataCtl.code = IODATA_CTL_GET_AUTODET_STATUS;
827         ioDataControl(pInp->hIoData, &ioDataCtl);
829         *pAutoDetStats = ioDataCtl.param.autoDetStats;
831         retVal = ASIT_NO_ERR;
832     }
833     else if(ioDataErr == IODATA_ERR_IOBUF_UNDERFLOW) {
834         // Input buffer underflows - there is no enough data to process.
835         // This is not error and no action is needed.
836         pInp->numUnderflow += 1; // debug
838         retVal = ASIT_ERR_INPBUF_UNDERFLOW;
839     }
840     else {
841         // Something is wrong: print error log and return
842         //printf("IODATA processing error!\n");
843         retVal = ASIT_ERR_INPDATA_PROC;
844     }
846     return retVal;
847 } /* asitInputDataProcess */
849 /*============================================================================
850  * Mapping ASIT Events to Decoding Messages
851 ============================================================================*/
852 UInt asitEventsToDecMsg(UInt asitEvents)
854     UInt decMsg = 0;
856     if (asitEvents & ASIT_EVTMSK_INPDATA) {
857         // Input data event
858         decMsg |= DEC_MSGMSK_INPDATA;
859     }
861     // temp, simulation
862     //if(asitEvents & ASIT_EVTMSK_INFOACK) {
863     //    decMsg |= DEC_MSGMSK_INFOACK;
864     //}
866     // temp, simulation
867     //if(asitEvents & ASIT_EVTMSK_DECACK) {
868     //    decMsg |= DEC_MSGMSK_DECACK;
869     //}
871     if (asitEvents & ASIT_EVTMSK_RXACK)
872     {
873        // Receive acknowledge message event
874         decMsg |= DEC_MSGMSK_RXACK;
875     }
876     
877     return decMsg;
878 } /* asitEventsToDecMsg */
880 /*===========================================================================
881  * Initialize I/O components for input processing
882 ============================================================================*/
883 int asitIoCompsInit(PAF_AST_InpBuf * pInpBuf, PAF_AST_IoInp * pInpIo)
885     ioBuffParams_t ioBuffParams;
886     ioPhyParams_t  ioPhyParams;
887     ioDataParam_t  ioDataCfg;
888     ioPhyCtl_t     ioPhyCtl;
890     //pInpIo->phyXferSize = INPUT_FRAME_SIZE_DEF;
891     pInpIo->phyXferSize = pInpIo->stride * NUM_CYCLE_PER_FRAME_DEF * WORD_SIZE_BITSTREAM;
893     if(pInpIo->firstTimeInit) {
894         TRACE_VERBOSE0("Initialize I/O BUFF and I/O PHY.");
895         ioBuffParams.base         = pInpBuf->inpBufConfig.base.pVoid;
896         ioBuffParams.size         = pInpBuf->inpBufConfig.allocation / STRIDE_WORST_CASE
897                                                                      * STRIDE_WORST_CASE;
898         ioBuffParams.sync         = IOBUFF_WRITE_SYNC;
899         ioBuffParams.nominalDelay = INPUT_FRAME_SIZE_DEF;
900         if(ioBuffInit(pInpIo->hIoBuff, &ioBuffParams) != IOBUFF_NOERR) {
901             return (ASIT_ERR_IOBUFF_INIT);   // to remove magic number
902         }
904         ioPhyParams.ioBuffHandle    = pInpIo->hIoBuff;
905         ioPhyParams.xferFrameSize   = pInpIo->phyXferSize;
906         ioPhyParams.mcaspChanHandle = pInpIo->hMcaspChan;
907         ioPhyParams.ioBuffOp        = IOPHY_IOBUFFOP_WRITE;
908         if(ioPhyInit(pInpIo->hIoPhy, &ioPhyParams) != IOPHY_NOERR) {
909             return (ASIT_ERR_IOPYH_INIT);   // to remove magic number
910         }
912         pInpIo->numPrimeXfers = NUM_PRIME_XFERS;
913     }
915     /* Reinitialize I/O DATA every time when ASIT restarts */
916     TRACE_VERBOSE0("Initialize I/O DATA.");
917     ioDataCfg.ioBuffHandle         = pInpIo->hIoBuff;
918     ioDataCfg.unknownSourceTimeOut = pInpBuf->inpBufConfig.pBufStatus->unknownTimeout;
919     ioDataCfg.frameLengthsIEC      = (uint_least16_t *)&iecFrameLength[0];
920     ioDataCfg.frameLengthPCM       = INPUT_FRAME_SIZE_PCM / WORD_SIZE_PCM;
921     ioDataCfg.frameLengthDef       = INPUT_FRAME_SIZE_DEF / WORD_SIZE_BITSTREAM;
922     ioDataCfg.ibMode               = pInpBuf->inpBufConfig.pBufStatus->mode;
923     ioDataCfg.zeroRunRestart       = pInpBuf->inpBufConfig.pBufStatus->zeroRunRestart;
924     ioDataCfg.zeroRunTrigger       = pInpBuf->inpBufConfig.pBufStatus->zeroRunTrigger;
926     if(ioDataInit(pInpIo->hIoData, &ioDataCfg) != IODATA_NO_ERR) {
927         return (ASIT_ERR_IODATA_INIT);   // to remove magic number
928     }
930     if(pInpIo->firstTimeInit) {
931         /* Initialize I/O BUFF and I/O PHY only when input interface changes. */
932         TRACE_VERBOSE0("Prime I/O PHY.");
934         // Start I/O physical layer by priming McASP LLD for input
935         asitIoPhyPrime(pInpIo);
937         pInpIo->firstTimeInit = FALSE;
938     }
939     else {
940         // Reconfigure I/O PHY transfer size
941         ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
942         ioPhyCtl.params.xferFrameSize = pInpIo->phyXferSize;
943         ioPhyControl(pInpIo->hIoPhy, &ioPhyCtl);
944 #if 0
945         // If previous stream before reset was PCM, reconfigure McASP LLD to receive 16-bit packed bits
946         if(!pInpIo->swapData) {
947             Int mcaspErr;
948             mcaspErr = mcaspRecfgWordWidth(pInpIo->hMcaspChan, Mcasp_WordLength_16);
949             if(mcaspErr != Aud_EOK) {
950                 return ASIT_ERR_MCASP_CFG;
951             }
953             // Start swapping data
954             pInpIo->swapData = TRUE;
955             TRACE_VERBOSE0("Reconfigure McASP word length and start swapping data.");
956         }
957 #endif
958         // Start PHY transfer
959         TRACE_VERBOSE0("Start I/O PHY transfer.");
960         asitPhyTransferStart(pInpIo);
961     }
963     return 0;
964 } /* asitIoCompsInit */
966 /*======================================================================================
967  *  This function initializes ASIT processing
968  *====================================================================================*/
969 void asitProcInit(PAF_AST_IoInp  *pInp, asipDecProc_t *pDec)
971 //    pInp->swapData = TRUE;
972     pInp->pcmSwitchHangOver = INPUT_SWITCH_HANGOVER;
973     pDec->initDone = FALSE;
974     pInp->numFrameReceived = 0;
977 /*======================================================================================
978  *  I/O physical layer prime operation required by McASP LLD
979  *====================================================================================*/
980 void asitIoPhyPrime(PAF_AST_IoInp *pInp)
982     Int32        count;
984     for(count = 0; count < pInp->numPrimeXfers; count++)
985     {
986         ioPhyXferSubmit(pInp->hIoPhy);
987 #ifdef ASIP_DEBUG
988         //pInp->numXferStart++;
989 #endif
990     }
991 } /* asitIoPhyPrime */
994 /*======================================================================================
995  *  This function marks the I/O PHY transfer as complete
996  *====================================================================================*/
997 void asitPhyTransferComplete(PAF_AST_IoInp * pInpIo)
999     // Mark underlining I/O BUFF write complete and swap data if needed
1000     ioPhyXferComplete(pInpIo->hIoPhy, pInpIo->swapData);
1001 } /* asitPhyTransferComplete */
1003 #if 0
1004 Int asitRecfgPhyXfer(PAF_AST_IoInp *pInp, size_t xferSize)
1006     ioPhyCtl_t ioPhyCtl;
1007     Int mcaspErr;
1009     ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
1010     ioPhyCtl.params.xferFrameSize = xferSize;
1011     ioPhyControl(pInp->hIoPhy, &ioPhyCtl);
1013     pInp->phyXferSize  = ioPhyCtl.params.xferFrameSize;
1015     if(!pInp->swapData) {
1016         // If it was PCM, reconfigure McASP LLD to receive 16-bit packed bits
1017         mcaspErr = mcaspRecfgWordWidth(pInp->hMcaspChan, Mcasp_WordLength_16);
1018         if(mcaspErr != Aud_EOK) {
1019             return ASIT_ERR_MCASP_CFG;
1020         }
1022         // Start swapping data
1023         pInp->swapData = TRUE;
1024     }
1026     return ASIT_NO_ERR;
1028 } /* asitRecfgPhyXfer */
1029 #endif
1031 /*======================================================================================
1032  *  McASP LLD call back function
1033  *====================================================================================*/
1034 void asipMcaspCallback(void* arg, MCASP_Packet *mcasp_packet)
1036     /* post semaphore */
1037     if(mcasp_packet->arg == IOPHY_XFER_FINAL) {
1038         //Semaphore_post(asipSemRx);
1039         Event_post(gAsitEvtHandle, ASIT_EVTMSK_INPDATA);
1040     } else {
1041         ;    // intermediate packet due to buffer wrapping around
1042     }
1045 /*======================================================================================
1046  *  This function checks if McASP Rx for input overruns
1047  *====================================================================================*/
1048 int asipCheckMcaspRxOverrun(Ptr mcaspChanHandle)
1050     Mcasp_errCbStatus mcaspErrStat;
1052     mcaspControlChan(mcaspChanHandle, Mcasp_IOCTL_CHAN_QUERY_ERROR_STATS, &mcaspErrStat);
1054     return (mcaspErrStat.isRcvOvrRunOrTxUndRunErr);
1057 #if 0
1058 /*======================================================================================
1059  *  This function restarts McASP LLD channel for input
1060  *====================================================================================*/
1061 void asipMcaspRxRestart(PAF_AST_IoInp *pInpIo)
1063     mcaspRxReset();
1064     mcaspRxCreate();
1066 #endif
1068 /*======================================================================================
1069  *  This function starts an I/O PHY transfer
1070  *====================================================================================*/
1071 void asitPhyTransferStart(PAF_AST_IoInp *pInpIo)
1073     Int ioPhyErr;
1075     if(asipCheckMcaspRxOverrun(pInpIo->hMcaspChan)) {
1076 #ifdef ASIP_DEBUG
1077         pInpIo->numInputOverrun++;
1078 #endif
1079         //asipMcaspRxRestart(pInpIo);
1080         System_abort("\nMcASP for input overruns! %d!\n");
1081     }
1082     else {
1083         ioPhyErr = ioPhyXferSubmit(pInpIo->hIoPhy);
1084         //if(ioPhyXferSubmit(pInpIo->hIoPhy)==IOPHY_ERR_BUFF_OVERFLOW) {
1085         if(ioPhyErr!=IOPHY_NOERR){
1086             printf("\n I/O PHY ioPhyXferSubmit fails with error %d!\n", ioPhyErr);
1087             // Input buffer overflows!
1088             //printf("\nInput buffer overflows!\n");
1089             exit(0);
1090         }
1091         else {
1092             // Input buffer operates normally
1093             ;
1094         }
1095 #ifdef ASIP_DEBUG
1096         //pInpIo->numXferStart++;
1097 #endif
1098     }
1101 Int d10Initialized = 0;
1102 //extern Aud_STATUS mcaspAudioConfig(void);
1103 extern void McaspDevice_init(void);
1105 /*======================================================================================
1106  *  This function initializes HW interface and selects the right device for input
1107  *====================================================================================*/
1108 Int asitSelectDevices(const PAF_ASIT_Patchs *pQ, PAF_AST_Config *pAstCfg, PAF_AST_IoInp *pInp)
1110     Aud_STATUS status;
1111     mcaspLLDconfig *lldCfg;
1112     Ptr mcaspChanHandle;
1113     Int zMD, interface;
1115     zMD = pAstCfg->masterDec;
1117     interface = pAstCfg->xInp[zMD].inpBufStatus.sioSelect; // obtain SIO select for input
1119     if (interface <= 0) {
1120         pInp->pRxParams = NULL;
1122         return ASIT_NO_ERR;
1123     }
1125     // Initialize D10
1126     if(!d10Initialized) {
1127         void * pD10Params = (void *)pQ->devinp->x[interface];
1129         /* Initialize McASP HW details */
1130         McaspDevice_init();
1132         D10_init(pD10Params);
1134         d10Initialized = 1;
1135     }
1137     /* Get the McASP LLD channel for this interface. Create one if not yet created. */
1138     lldCfg = (mcaspLLDconfig *)pQ->devinp->x[interface]->sio.pConfig;
1139     if(lldCfg->hMcaspChan == NULL) {
1140         mcaspChanHandle = NULL;
1141         status = mcasplldChanCreate(lldCfg, &mcaspChanHandle);
1142         if(status != Aud_EOK) {
1143             Log_info0("McASP channel creation failed!\n");
1144             return ASIT_ERR_MCASP_CFG;
1145         }
1147         lldCfg->hMcaspChan = mcaspChanHandle;
1148     }
1149     else {
1150         /* Configure McASP to receive 16/32-bit data according to default configuration */
1151         status = mcaspRecfgWordWidth(pInp->hMcaspChan, lldCfg->mcaspChanParams->wordWidth);
1152         if(status != Audk2g_EOK) {
1153             return ASIT_ERR_MCASP_CFG;
1154         }
1155     }
1157     pInp->pRxParams = pQ->devinp->x[interface];
1158     pInp->hMcaspChan = lldCfg->hMcaspChan;
1159     pInp->stride     = lldCfg->mcaspChanParams->noOfSerRequested * 2;  // 2 for stereo
1161     /* Set flag to swap HDMI data if it is 4xI2S and word length is 16 */
1162     if(   (lldCfg->mcaspChanParams->wordWidth == Mcasp_WordLength_16)
1163         &&(lldCfg->mcaspChanParams->noOfSerRequested == 4)
1164       ) {
1165         pInp->swapData = TRUE;
1166     }
1167     else {
1168         pInp->swapData = FALSE;
1169     }
1171     return ASIT_NO_ERR;
1172 }  /* asitSelectDevices */
1174 /*======================================================================================
1175  *  This function updates input status
1176  *====================================================================================*/
1177 Int asitUpdateInputStatus(const void *pRxParams, PAF_InpBufStatus *pStatus,
1178                           PAF_InpBufConfig *pInpBuf)
1180     Int asipErrno;
1182     PAF_SIO_InputStatus inputStatus;
1184     // initialize all values to unknown so that device specific
1185     //   driver layer need only fill in those entries that it is aware of.
1186     //   This allows extensibility of the structure without requiring users
1187     //   to re-code.
1188     inputStatus.lock = 0;
1189     inputStatus.sampleRateData = PAF_SAMPLERATE_UNKNOWN;
1190     inputStatus.sampleRateMeasured = PAF_SAMPLERATE_UNKNOWN;
1191     inputStatus.nonaudio = PAF_IEC_AUDIOMODE_UNKNOWN;
1192     inputStatus.emphasis = PAF_IEC_PREEMPHASIS_UNKNOWN;
1194     //more configuration is needed to abstract out D10
1195     asipErrno = D10_RxControl(pRxParams,
1196                           (Uns)PAF_SIO_CONTROL_GET_INPUT_STATUS,
1197                           (Arg) &inputStatus);
1198     if (asipErrno) {
1199         return asipErrno;
1200     }
1201     pStatus->sampleRateData = inputStatus.sampleRateData;
1202     pStatus->sampleRateMeasured = inputStatus.sampleRateMeasured;
1203     pStatus->nonaudio = inputStatus.nonaudio;
1204     pStatus->emphasisData = inputStatus.emphasis;
1206     // if MSB of override clear then use as reported lock
1207     // if = 0x80 then use default [0x81]
1208     // if = 0x81 then use measured (from device)
1209     // others not defined or implemented
1210     if ((pStatus->lockOverride & (XDAS_Int8)0x80) == 0)
1211         pStatus->lock = pStatus->lockOverride;
1212     else if (pStatus->lockOverride == (XDAS_Int8)0x80)
1213         pStatus->lock = inputStatus.lock;
1214     else if (pStatus->lockOverride == (XDAS_Int8)0x81)
1215         pStatus->lock = inputStatus.lock;
1217     // if MSB of override clear then use it as sample rate for system,
1218     // if = 0x80 then use default [0x82]
1219     // if = 0x81 then use data
1220     // if = 0x82 then use measured
1221     // others not defined or implemented
1222     if ((pStatus->sampleRateOverride & (XDAS_Int8)0x80) == 0)
1223         pStatus->sampleRateStatus = pStatus->sampleRateOverride;
1224     else if (pStatus->sampleRateOverride == (XDAS_Int8)0x80)
1225         pStatus->sampleRateStatus = pStatus->sampleRateMeasured;
1226     else if (pStatus->sampleRateOverride == (XDAS_Int8)0x81)
1227         pStatus->sampleRateStatus = pStatus->sampleRateData;
1228     else if (pStatus->sampleRateOverride == (XDAS_Int8)0x82)
1229         pStatus->sampleRateStatus = pStatus->sampleRateMeasured;
1231     // Update emphasis status:
1232     if ((pStatus->emphasisOverride & (XDAS_Int8)0x80) == 0) {
1233         if (pStatus->emphasisData == PAF_IEC_PREEMPHASIS_YES)
1234             pStatus->emphasisStatus = PAF_IEC_PREEMPHASIS_YES;
1235         else
1236             pStatus->emphasisStatus = PAF_IEC_PREEMPHASIS_NO;
1237     }
1238     else if (pStatus->emphasisOverride ==
1239              (XDAS_Int8 )(0x80+PAF_IEC_PREEMPHASIS_YES))
1240         pStatus->emphasisStatus = PAF_IEC_PREEMPHASIS_YES;
1241     else /* IBEmphasisOverrideNo or other */
1242         pStatus->emphasisStatus = PAF_IEC_PREEMPHASIS_NO;
1244     // Update precision control
1245     pInpBuf->precision = pStatus->precisionInput =
1246         pStatus->precisionOverride < 0
1247         ? pStatus->precisionDefault
1248         : pStatus->precisionOverride > 0
1249         ? pStatus->precisionOverride
1250         : pStatus->precisionDetect > 0
1251         ? pStatus->precisionDetect
1252         : pStatus->precisionDefault;
1254     return 0;
1258 /*==============================================================================
1259  * This function updates input buffer config based on frame information provided
1260  * by I/O DATA.
1261  ==============================================================================*/
1262 void asitUpdateInpBufConfig(PAF_AST_Config *pAstCfg, PAF_AST_IoInp  *pInp)
1264     PAF_InpBufConfig *pBufConfig;
1265     ioDataCtl_t ioDataCtl;
1267     /* Get information for reading input data */
1268     ioDataCtl.code = IODATA_CTL_GET_INPBUFFINFO;
1269     ioDataControl(pInp->hIoData, &ioDataCtl);
1271     if(ioDataCtl.param.dataReadInfo.frameSize != pInp->phyXferSize) {
1272         // Fatal error!
1273         TRACE_VERBOSE0("TaskAsip: error in updating I/O");
1274         SW_BREAKPOINT;
1275     }
1277     pBufConfig = &(pAstCfg->xInp[pAstCfg->masterDec].inpBufConfig);
1279     //JXTODO: do we need to gate here?
1280     //key = GateMP_enter(gateHandle);
1282     pBufConfig->base.pVoid   = ioDataCtl.param.dataReadInfo.buffBase;
1283     pBufConfig->sizeofBuffer = ioDataCtl.param.dataReadInfo.buffSize;
1284     pBufConfig->pntr.pSmInt  = ioDataCtl.param.dataReadInfo.startAddress;
1286     // Leave the gate
1287     //GateMP_leave(gateHandle, key);
1289     TRACE_TERSE2("Frame start address: 0x%x., preamble: 0x%x",
1290                  (UInt)ioDataCtl.param.dataReadInfo.startAddress,
1291                  *(UInt *)ioDataCtl.param.dataReadInfo.startAddress);
1294 /*==============================================================================
1295  * Decide source after SYNC is found, i.e. either bitstream preamble is detected
1296  * or it times out to PCM.
1297  ==============================================================================*/
1298 Int asitDecideSource(PAF_AST_Config *pAstCfg, PAF_AST_IoInp  *pInp, 
1299                      ioDataAutoDetStat_t *autoDetStatus)
1301     Int sourceConfig, sourceSelect, sourceProgram;
1302     Int zMD;
1303     char asipMsgBuf[ASP_MSG_BUF_LEN];
1304     Int status;
1306     // Get the configured source
1307     zMD = pAstCfg->masterDec;
1308     sourceConfig = (Int)sharedMemReadInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceSelect),
1309                                           GATEMP_INDEX_DEC);
1311     if(autoDetStatus->syncState == IODATA_SYNC_PCM) {
1312         if (sourceConfig == PAF_SOURCE_DSD1 || sourceConfig == PAF_SOURCE_DSD2 ||
1313             sourceConfig == PAF_SOURCE_DSD3) {
1314             sourceProgram = sourceConfig;
1315         }
1316         else {
1317             sourceProgram = PAF_SOURCE_PCM;
1318         }
1319     }
1321     if(autoDetStatus->syncState == IODATA_SYNC_BITSTREAM) {
1322         uint_least16_t pc = autoDetStatus->bitStreamInfo & SYNC_PC_MASK; //0x001F
1323         sourceProgram = IECpafSource[pc];
1324     }
1326     // write the decided source program to memory
1327     sharedMemWriteInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceProgram), sourceProgram,
1328                        GATEMP_INDEX_DEC);
1330     // now that we have some input classification, and possibly an outstanding
1331     // input frame, we determine whether or not to call decodeProcessing and with
1332     // what decAlg.
1333     sourceSelect = PAF_SOURCE_NONE;
1335     switch (sourceConfig)
1336     {
1337         // If autodetecting, decoding everything, and input is something
1338         // (i.e. bitstream or PCM) then decode.
1339         case PAF_SOURCE_AUTO:
1340             if (sourceProgram >= PAF_SOURCE_PCM)  {
1341                 sourceSelect = sourceProgram; // use whatever from autodet
1342             }
1343             break;
1345         // If autodetecting, decoding only PCM, and input is PCM then decode.
1346         case PAF_SOURCE_PCMAUTO:
1347             if (sourceProgram == PAF_SOURCE_PCM) {
1348                 // only expect autodet to give PAF_SOURCE_PCM, otherwise set to NONE
1349                 sourceSelect = sourceProgram;
1350             }
1351             break;
1353         // If autodetecting, decoding only bitstreams, and input is a bitstream then decode.
1354         case PAF_SOURCE_BITSTREAM:
1355             if (sourceProgram >= PAF_SOURCE_AC3) {
1356                 sourceSelect = sourceProgram;
1357             }
1358             break;
1360         // If autodetecting, decoding only DTS, and input is DTS then decode.
1361         case PAF_SOURCE_DTSALL:
1362             switch (sourceProgram)
1363             {
1364                 case PAF_SOURCE_DTS11:
1365                 case PAF_SOURCE_DTS12:
1366                 case PAF_SOURCE_DTS13:
1367                 case PAF_SOURCE_DTS14:
1368                 case PAF_SOURCE_DTS16:
1369                 case PAF_SOURCE_DTSHD:
1370                     sourceSelect = sourceProgram;
1371                     break;
1372             }
1373             break;
1375         // All others, e.g., force modes, fall through to here.
1376         // If user made specific selection then program must match select.
1377         // (NB: this compare relies on ordering of PAF_SOURCE)
1378         default:
1379             sourceSelect = sourceConfig;
1380             if ((sourceSelect >= PAF_SOURCE_PCM) && (sourceSelect <= PAF_SOURCE_N)) {
1381                 if (sourceProgram != sourceSelect) {
1382                     sourceSelect = PAF_SOURCE_NONE;
1383                 }
1384             }
1385             break;
1386     }
1388     // if we didn't find any matches then skip
1389     if (sourceSelect == PAF_SOURCE_NONE) {
1390         TRACE_VERBOSE0("TaskAsip: no matching source type, continue");
1391         return ASIT_ERR_NO_MATCHING_SOURCE;
1392     }
1394 #ifndef DEBUG_SKIP_DECODING
1395     // send source select message to slave
1396     *(Int32 *)&asipMsgBuf[0] = sourceSelect;
1397     status = AspMsgSnd(gPAF_ASIT_config.hAspMsgMaster, ASP_SLAVE_DEC_SOURCE_SELECT, asipMsgBuf);
1398     if (status != ASP_MSG_NO_ERR) 
1399     {
1400         TRACE_VERBOSE0("TaskAsip: error in sending SOURCE_SELECT message");
1401         SW_BREAKPOINT;
1402     }
1403     status = AspMsgRcvAck(gPAF_ASIT_config.hAspMsgMaster, ASP_MASTER_DEC_SOURCE_SELECT_DONE, NULL, TRUE);
1404     if (status != ASP_MSG_NO_ERR)
1405     {
1406         TRACE_VERBOSE0("TaskAsip: error in receiving SOURCE_SELECT ack message");
1407         SW_BREAKPOINT;
1408     }
1409 #endif
1411     pInp->sourceSelect  = sourceSelect;
1412     pInp->sourceProgram = sourceProgram;
1414     return ASIT_NO_ERR;
1415 } /* asitDecideSource */
1417 /*==============================================================================
1418  * After SYNC is found, i.e. either bitstream preamble is detected or it times
1419  * out to PCM, update input buffer config and I/o components accordingly.
1420  ==============================================================================*/
1421 Int asitUpdateIoComps(const PAF_ASIT_Params *pP, PAF_AST_Config *pAstCfg,
1422                       PAF_AST_IoInp  *pInp, ioDataAutoDetStat_t *autoDetStatus)
1424     Int sourceConfig;
1425     Int zMD, deliverZeros;
1426     int ioFrameLength, decFrameLength;
1427     PAF_InpBufConfig *pBufConfig;
1428     ioPhyCtl_t  ioPhyCtl;
1429     ioDataCtl_t ioDataCtl;
1431     zMD = pAstCfg->masterDec;
1432     pBufConfig = &pAstCfg->xInp[zMD].inpBufConfig;
1434     // Compute decoder frame length based on source selection
1435     decFrameLength = getFrameLengthSourceSel(pP, pInp->sourceSelect);
1437     pAstCfg->xDec[zMD].decodeControl.frameLength  = decFrameLength;
1438     pAstCfg->xDec[zMD].decodeInStruct.sampleCount = decFrameLength;
1439     pAstCfg->xDec[zMD].decodeControl.sampleRate   = PAF_SAMPLERATE_UNKNOWN;
1441     // Decide frame length for I/O DATA and I/O PHY
1442     if(autoDetStatus->syncState == IODATA_SYNC_PCM) {
1443         // For PCM, I/O frame length is decode frame length multiplied by stride
1444         ioFrameLength = decFrameLength * pInp->stride;
1446         pBufConfig->sizeofElement = WORD_SIZE_PCM;
1447         pBufConfig->frameLength   = pBufConfig->lengthofData = ioFrameLength;
1449         // Configure I/O DATA PCM frame length
1450         ioDataCtl.code = IODATA_CTL_SET_PCM_FRAME_LENGTH;
1451         ioDataCtl.param.frameLengthPcm = ioFrameLength;
1452         ioDataControl(pInp->hIoData, &ioDataCtl);
1454         // Change I/O PHY transfer size to PCM frame size
1455         pInp->phyXferSize = ioFrameLength*(WORD_SIZE_PCM);
1457         // Adjust I/O BUFF delay and read pointer - to make sure read pointers always point to
1458         // PCM data from 1st I2S (out of 4 for HDMI 4xI2S)
1459         // Adjust delay and don't mark input buffer as read complete
1460         //ioBuffAdjustDelay(pInp->hIoBuff, pInp->phyXferSize);
1462         // Stop swapping data
1463         //pInp->swapData = FALSE;
1464     }
1465     else {
1466         // For bitstream, I/O frame length is the frame length of the bitstream
1467         uint_least16_t pc = autoDetStatus->bitStreamInfo & SYNC_PC_MASK; //0x001F
1468         ioFrameLength = iecFrameLength[pc];
1470 /*
1471         if(   (pc == 0x11) && (DTSHDSubType == 3)
1472            && (PAF_ASP_sampleRateHzTable[pBufConfig->pBufStatus->sampleRateStatus][PAF_SAMPLERATEHZ_STD] <=48000.0))
1473             pDevExt->sourceProgram = PAF_SOURCE_DXP;    // LBR is 23
1475         if (pc == 1)
1476             pDevExt->elementSize = 4288;
1477         else if (pc == 0x11) {
1478             pDevExt->frameLength = (pDevExt->pIECFrameLength[pc] << DTSHDSubType);
1479             pDevExt->lengthofData = pDevExt->frameLength;
1480         }
1481 */
1483         pBufConfig->sizeofElement = WORD_SIZE_BITSTREAM;
1484         pBufConfig->frameLength   = ioFrameLength;
1485         pBufConfig->lengthofData  = ioFrameLength - IEC_HEADER_LENGTH;
1487         // Change I/O PHY transfer size to bitstream frame size
1488         pInp->phyXferSize = ioFrameLength*WORD_SIZE_BITSTREAM;
1489     }
1491     pBufConfig->stride = pInp->stride;   // common for PCM and bitstream
1493     // Configure I/O PHY transfer size
1494     ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
1495     ioPhyCtl.params.xferFrameSize = pInp->phyXferSize;
1496     ioPhyControl(pInp->hIoPhy, &ioPhyCtl);
1498     // Decide if zeros should be delivered based on the configured source
1499     sourceConfig = (Int)sharedMemReadInt8(&(pAstCfg->xDec[zMD].decodeStatus.sourceSelect),
1500                                           GATEMP_INDEX_DEC);
1502     if(autoDetStatus->syncState == IODATA_SYNC_PCM) {
1503         // Bitstream preamble is not found and it times out -> assume this is PCM
1504         deliverZeros = autoDetStatus->deliverZeros;
1505         if (sourceConfig == PAF_SOURCE_PCM || sourceConfig == PAF_SOURCE_DSD1 ||
1506             sourceConfig == PAF_SOURCE_DSD2 || sourceConfig == PAF_SOURCE_DSD3) {
1507             // set to one -- ensures that PCM decode calls made before data is
1508             // available will result in zero output.
1509             // (mostly needed for PA15 since, currently, all other frameworks
1510             // require a frame of data before the first decode call.
1511             deliverZeros = TRUE;  // override deliverZeros returned by ioDataControl
1512         }
1514         // update input buffer config structure
1515         pBufConfig->deliverZeros  = deliverZeros;
1516     }
1518     //JXTODO: decide what to do with hRxSio
1519     //temporary - does ARM use hRxSio or just check if it is not NULL?
1520     pAstCfg->xInp[zMD].hRxSio = pInp->hIoData;
1521     pAstCfg->xInp[zMD].pInpBuf = &(pAstCfg->xInp[zMD].inpBufConfig);
1523     return ASIT_NO_ERR;
1524 } /* asitUpdateIoComps */
1527 #ifndef IO_LOOPBACK_TEST
1528 #if OUTPUT_FRAME_LENGTH == INPUT_FRAME_LENGTH
1529 U8 pcmbuf[OUTPUT_FRAME_SIZE];
1530 #else
1531 #error Input frame length is not equal to output frame length!
1532 #endif
1534 Int rxDecodePcm(PAF_AST_IoInp  *pInp)
1536     ioDataCtl_t ioDataCtl;
1537     void *buffBase;
1538     void *dataStartAddress;
1539     size_t buffSize, frameSize, size1, size2;
1541     /* Get information for reading input data */
1542     ioDataCtl.code = IODATA_CTL_GET_INPBUFFINFO;
1543     ioDataControl(pInp->hIoData, &ioDataCtl);
1545     buffBase = ioDataCtl.param.dataReadInfo.buffBase;
1546     buffSize = ioDataCtl.param.dataReadInfo.buffSize;
1547     dataStartAddress = ioDataCtl.param.dataReadInfo.startAddress;
1548     frameSize        = ioDataCtl.param.dataReadInfo.frameSize;
1550     // Copy PCM data to output buffer
1551     if(((size_t)dataStartAddress+frameSize) <= ((size_t)buffBase+buffSize)) {
1552         // Input buffer doesn't wrap around
1553         Cache_inv(dataStartAddress, frameSize, Cache_Type_ALL, TRUE);
1554         memcpy((void *)&pcmbuf[0], dataStartAddress, frameSize);
1555     }
1556     else {
1557         // Input buffer wraps around
1558         size1 = (size_t)buffBase + buffSize - (size_t)dataStartAddress;
1559         size2 = frameSize - size1;
1560         Cache_inv(dataStartAddress, size1, Cache_Type_ALL, TRUE);
1561         memcpy((void *)&pcmbuf[0], dataStartAddress, size1);
1563         Cache_inv(buffBase, size2, Cache_Type_ALL, TRUE);
1564         memcpy((void *)&pcmbuf[size1], buffBase, size2);
1565     }
1568     return ASIT_NO_ERR;
1572 Int rxDecodePlayZero(PAF_AST_IoInp  *pInp)
1574     return ASIT_NO_ERR;
1576 #endif
1578 Int asitEvtErrCheck(UInt actualEvents, UInt expectedEvents)
1580     TRACE_VERBOSE2("ASIT events error: actual events are: %d, expected events are: %d.",
1581                    actualEvents, expectedEvents);
1583     return ASIT_ERR_EVENTS;
1586 void asitErrorHandling(PAF_ASIT_Config *pAsitCfg, Int asitErr)
1588     //UInt events;
1590     if(asitErr == ASIT_ERR_INPBUF_UNDERFLOW) {
1591         TRACE_VERBOSE0("ASIT error handling: input buffer underflows. No actions needed.");
1592     }
1594     if(asitErr == ASIT_ERR_DECODE_QUIT) {
1595         TRACE_VERBOSE0("ASIT error handling: DECODE_QUIT - clear INPDATA event.");
1596 #if 0
1597         // Pend on INPTDATA event that should have been posted before decoding quits.
1598         events = Event_pend(asitEvent, ASIT_EVTMSK_NONE, ASIT_EVTMSK_INPDATA,
1599                             BIOS_WAIT_FOREVER);
1601         // Marks I/O PHY transfer and I/O BUFF write complete
1602         asitPhyTransferComplete(&pAsitCfg->pIoInp[0]);
1604         // Keep I/O BUFF read pointers going
1605         asitBypassIoData(&pAsitCfg->pIoInp[0]);
1606 #endif
1607         pAsitCfg->pIoInp[0].asipState = ASIT_RESET;
1608         pAsitCfg->pIoInp[0].numAsitRestart++;
1609         TRACE_VERBOSE0("ASIT error handling finished. Go to state ASIT_RESET.");
1610     }
1612     if(asitErr == ASIT_ERR_EVENTS) {
1613         pAsitCfg->pIoInp[0].asipState = ASIT_RESET;
1614         pAsitCfg->pIoInp[0].numAsitRestart++;
1615         TRACE_VERBOSE0("ASIT error handling: events error. Go to state ASIT_RESET.");
1616     }
1618     return;
1619 }  /* asitErrorHandling */
1622 //////////////////////////////////////////////////////////////////////////////
1623 void asitPostInfoEvent()
1625     Event_post(gAsitEvtHandle, ASIT_EVTMSK_INFOACK);
1628 void asitPostDecEvent()
1630     Event_post(gAsitEvtHandle, ASIT_EVTMSK_DECACK);
1632 //////////////////////////////////////////////////////////////////////////////
1634 /* Nothing past this line */