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)
205 {
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
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) {
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
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)
381 {
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)
485 {
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)
587 {
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)
625 {
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)
670 {
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)
817 {
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)
853 {
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 }
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)
884 {
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 = pInpIo->stride * NUM_CYCLE_PER_FRAME_DEF;
921 ioDataCfg.frameLengthDef = pInpIo->stride * NUM_CYCLE_PER_FRAME_DEF;
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)
970 {
971 // pInp->swapData = TRUE;
972 pInp->pcmSwitchHangOver = INPUT_SWITCH_HANGOVER;
973 pDec->initDone = FALSE;
974 pInp->numFrameReceived = 0;
975 }
977 /*======================================================================================
978 * I/O physical layer prime operation required by McASP LLD
979 *====================================================================================*/
980 void asitIoPhyPrime(PAF_AST_IoInp *pInp)
981 {
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)
998 {
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)
1005 {
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)
1035 {
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 }
1043 }
1045 /*======================================================================================
1046 * This function checks if McASP Rx for input overruns
1047 *====================================================================================*/
1048 int asipCheckMcaspRxOverrun(Ptr mcaspChanHandle)
1049 {
1050 Mcasp_errCbStatus mcaspErrStat;
1052 mcaspControlChan(mcaspChanHandle, Mcasp_IOCTL_CHAN_QUERY_ERROR_STATS, &mcaspErrStat);
1054 return (mcaspErrStat.isRcvOvrRunOrTxUndRunErr);
1055 }
1057 #if 0
1058 /*======================================================================================
1059 * This function restarts McASP LLD channel for input
1060 *====================================================================================*/
1061 void asipMcaspRxRestart(PAF_AST_IoInp *pInpIo)
1062 {
1063 mcaspRxReset();
1064 mcaspRxCreate();
1065 }
1066 #endif
1068 /*======================================================================================
1069 * This function starts an I/O PHY transfer
1070 *====================================================================================*/
1071 void asitPhyTransferStart(PAF_AST_IoInp *pInpIo)
1072 {
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 }
1099 }
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)
1109 {
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 != Aud_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 * lldCfg->mcaspChanParams->noOfChannels;
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)
1179 {
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;
1255 }
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)
1263 {
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);
1292 }
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)
1300 {
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)
1423 {
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 */
1526 #if 0
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)
1535 {
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;
1569 }
1572 Int rxDecodePlayZero(PAF_AST_IoInp *pInp)
1573 {
1574 return ASIT_NO_ERR;
1575 }
1576 #endif
1578 #endif
1580 Int asitEvtErrCheck(UInt actualEvents, UInt expectedEvents)
1581 {
1582 TRACE_VERBOSE2("ASIT events error: actual events are: %d, expected events are: %d.",
1583 actualEvents, expectedEvents);
1585 return ASIT_ERR_EVENTS;
1586 }
1588 void asitErrorHandling(PAF_ASIT_Config *pAsitCfg, Int asitErr)
1589 {
1590 //UInt events;
1592 if(asitErr == ASIT_ERR_INPBUF_UNDERFLOW) {
1593 TRACE_VERBOSE0("ASIT error handling: input buffer underflows. No actions needed.");
1594 }
1596 if(asitErr == ASIT_ERR_DECODE_QUIT) {
1597 TRACE_VERBOSE0("ASIT error handling: DECODE_QUIT - clear INPDATA event.");
1598 #if 0
1599 // Pend on INPTDATA event that should have been posted before decoding quits.
1600 events = Event_pend(asitEvent, ASIT_EVTMSK_NONE, ASIT_EVTMSK_INPDATA,
1601 BIOS_WAIT_FOREVER);
1603 // Marks I/O PHY transfer and I/O BUFF write complete
1604 asitPhyTransferComplete(&pAsitCfg->pIoInp[0]);
1606 // Keep I/O BUFF read pointers going
1607 asitBypassIoData(&pAsitCfg->pIoInp[0]);
1608 #endif
1609 pAsitCfg->pIoInp[0].asipState = ASIT_RESET;
1610 pAsitCfg->pIoInp[0].numAsitRestart++;
1611 TRACE_VERBOSE0("ASIT error handling finished. Go to state ASIT_RESET.");
1612 }
1614 if(asitErr == ASIT_ERR_EVENTS) {
1615 pAsitCfg->pIoInp[0].asipState = ASIT_RESET;
1616 pAsitCfg->pIoInp[0].numAsitRestart++;
1617 TRACE_VERBOSE0("ASIT error handling: events error. Go to state ASIT_RESET.");
1618 }
1620 return;
1621 } /* asitErrorHandling */
1624 //////////////////////////////////////////////////////////////////////////////
1625 void asitPostInfoEvent()
1626 {
1627 Event_post(gAsitEvtHandle, ASIT_EVTMSK_INFOACK);
1628 }
1630 void asitPostDecEvent()
1631 {
1632 Event_post(gAsitEvtHandle, ASIT_EVTMSK_DECACK);
1633 }
1634 //////////////////////////////////////////////////////////////////////////////
1636 /* Nothing past this line */