PASDK-516:Add ASOT wake timer, update existing ASOT SM to use events
[processor-sdk/performance-audio-sr.git] / pasdk / test_dsp / framework / audioStreamOutProcNewIO.c
index 205d64b93648636984b6eed8bd5587a79addfe20..13276593c2736e3f72b51b904e21d4902e65285e 100644 (file)
@@ -37,23 +37,130 @@ All rights reserved.
  *  ======== audioStreamOutProc.c ========
  */
 
  *  ======== audioStreamOutProc.c ========
  */
 
+#include <xdc/runtime/Log.h>
+#include <ti/sysbios/BIOS.h>
+#include <ti/sysbios/knl/Event.h>
+#include <stdio.h>
+
+#include "mcasp_cfg.h"
+#include "audioStreamProc_common.h"
 #include "audioStreamOutProc.h"
 #include "audioStreamOutProc.h"
+
 #include "ioConfig.h"    //TODO: remove this header
 #include "ioBuff.h"
 #include "ioPhy.h"
 #include "ioData.h"
 
 #include "ioConfig.h"    //TODO: remove this header
 #include "ioBuff.h"
 #include "ioPhy.h"
 #include "ioData.h"
 
+extern Ptr hMcaspTxChan;
 extern Semaphore_Handle asopSemTx;
 extern Semaphore_Handle asopSemTx;
+extern PAF_ASOT_Config gPAF_ASOT_config;
+extern volatile UInt32 gCommandOutputTask_SYNC;
+extern volatile UInt32 gCommandOutputTask_ACK;
+extern Int d10Initialized;
+
+static Int asopSelectDevices(PAF_AST_IoOut *pOut);
+static int asopIoCompsInit(PAF_AST_OutBuf * pOutBuf, PAF_AST_IoOut * pOutIo);
+static void asopIoPhyPrime(PAF_AST_IoOut *pOut);
+static void asopPhyTransferStart(PAF_AST_IoOut *pOut);
+static Int asopDecodePcm(PAF_AST_IoOut *pOut);
+
+// Initialize Output Processing state function
+extern Int PAF_ASOT_initOutProc(
+    const PAF_ASOT_Params *pP,
+    PAF_AST_Stream *xStr);
+
+extern Int PAF_ASOT_initSyncDecReset(
+        const PAF_ASOT_Params *pP,
+        const PAF_ASOT_Patchs *pQ,
+        PAF_ASOT_Config *pAsotCfg,
+        PAF_AudioFrame *pDecResetAf);
+
+static Int checkOutSel(
+    const PAF_ASOT_Params *pP,
+    PAF_ASOT_Config *pAsotCfg,
+    Int *pOutSel);
+
+extern Int PAF_ASOT_initSyncDecDecode1(
+    const PAF_ASOT_Params *pP,
+    const PAF_ASOT_Patchs *pQ,
+    PAF_ASOT_Config *pAsotCfg);
+
+extern Int PAF_ASOT_initSyncDecInfo1(
+    const PAF_ASOT_Params *pP,
+    const PAF_ASOT_Patchs *pQ,
+    PAF_ASOT_Config *pAsotCfg,
+    PAF_AudioFrame *pDecInfo1Af);
+
+extern Int PAF_ASOT_initSyncResync(
+    const PAF_ASOT_Params *pP,
+    const PAF_ASOT_Patchs *pQ,
+    PAF_ASOT_Config *pAsotCfg,
+    PAF_AudioFrame *pDecResetAf,
+    PAF_AudioFrame *pDecInfo1Af);
 
 extern Void taskAsopFxnInit(const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ);
 
 
 extern Void taskAsopFxnInit(const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ);
 
+//
+// Audio Stream Output Task definitions
+//
+
+// status codes
+// Output FSM
+#define ASOP_INITSYNC_NOTREADY      (  1 )  // ok, init-sync not ready
+#define ASOP_SOK                    (  0 )  // ok
+#define ASOP_FORWARD_ERR            ( -1 )  // forward (ASIT) error
+#define ASOP_ENCRESET_ERR           ( -2 )  // enc reset error
+#define ASOP_DECINFO1_ERR           ( -3 )  // dec info1 error
+// Decode Processing
+#define ASOP_DP_OUT_SIO_UPDATE      (  3 )  // new output selected
+#define ASOP_DP_CB_DRAINED          (  2 )  // circular buffer drained
+#define ASOP_DP_SOK                 (  0 )  // ok
+#define ASOP_DP_FORWARD_ERR         ( -1 )  // forward (ASIT) error
+#define ASOP_DP_DECINIT_ERR         ( -2 )  // decode init error
+#define ASOP_DP_DECSTREAM_ERR       ( -3 )  // decode stream error
+#define ASOP_DP_DECENC_ERR          ( -4 )  // decode encode error
+#define ASOP_DP_DECINFO2_ERR        ( -5 )  // decode encode error
+#define ASOP_DP_DECFINALTEST_ERR    ( -6 )  // decode final error
+
+// Output FSM states 
+enum 
+{ 
+    INIT_OUT_PROC_STATE,
+    INITSYNC_DEC_RESET_STATE, 
+    INITSYNC_DEC_INFO1_STATE, 
+    INITSYNC_DEC_DECODE1_STATE,
+    INITSYNC_RESYNC_STATE,
+    OUT_PROC_STATE 
+};
+
+// Global debug counters */
+extern UInt32 gAsopTxSioReclaimCnt      ;
+extern UInt32 gAsopInitOutProcCnt       ;
+extern UInt32 gAsopInitSyncDecResetCnt  ;
+extern UInt32 gAsopInitSyncDecInfo1Cnt  ;
+extern UInt32 gAsopInitSyncDecDecode1Cnt;
+extern UInt32 gAsopInitSyncResyncCnt    ;
+extern UInt32 gAsopOutProcCnt           ;
+extern UInt32 gAsopInitCnt              ;
+extern UInt32 gAsopStreamCnt            ;
+extern UInt32 gAsopEncodeCnt            ;
+extern UInt32 gAsopFinalCnt             ;
+extern UInt32 gAsopOutSioUpdateCnt      ;
+extern UInt32 gAsopQuitCnt              ;
+
+#define ASOP_DEBUG
+#ifdef ASOP_DEBUG
+Int asopLoopCount;
+#endif
+
+
 /*
  *  ======== taskAsopFxn ========
  *  Audio Stream Output Processing task function
  */
 #ifndef PASDK_SIO_DEV
 #ifndef IO_LOOPBACK_TEST
 /*
  *  ======== taskAsopFxn ========
  *  Audio Stream Output Processing task function
  */
 #ifndef PASDK_SIO_DEV
 #ifndef IO_LOOPBACK_TEST
-Void taskAsopFxn_Not_Used(                 // ASOP task function for new I/O
+Void taskAsopFxn(                 // ASOP task function for new I/O
 #else
 Void taskAsopFxn_NewIO_Not_Used(  // not used for loopback test
 #endif
 #else
 Void taskAsopFxn_NewIO_Not_Used(  // not used for loopback test
 #endif
@@ -64,21 +171,578 @@ Void taskAsopFxn_NewIO_Not_Used(  // not used for SIO_DEV I/O
     const PAF_ASOT_Patchs *pQ
 )
 {
     const PAF_ASOT_Patchs *pQ
 )
 {
-//    Log_info0("Enter taskAsopFxn()");
+    PAF_ASOT_Config *pAsotCfg;      // ASOT configuration pointer
+    PAF_AST_Config *pAstCfg;        // Common (shared) configuration pointer
+    Int as;                         // Audio Stream Number (1, 2, etc.)
+    Int z;                          // input/encode/stream/decode/output counter
+    Int zMS;
+    Int errno;                      // error number
+    Int8 procSleep;                 // whether to sleep: 0: No, 1: Yes
+    Int8 procOutDevSel;             // whether to perform output device selection: 0: No, 1:Yes
+    Int outSel;                     // whether output device selected
+    PAF_AudioFrame decResetAf;
+    PAF_AudioFrame decInfo1Af;
+#ifndef ASOP_DEBUG
+    Int asopLoopCount;              // debug, ASOT loop counter
+#endif    
+
+    Log_info0("Enter taskAsopFxn()");
 
     taskAsopFxnInit(pP, pQ);    // initialization of output task
 
     taskAsopFxnInit(pP, pQ);    // initialization of output task
+    
+    //
+    // Audio Stream Output Task Configuration (*pAsotCfg):
+    //
+    pAsotCfg = &gPAF_ASOT_config;       // initialize pointer to task configuration
+    pAstCfg = pAsotCfg->pAstCfg;        // get pointer to AST common (shared) configuration
+
+    /* Obtain Audio Stream Number (1, 2, etc.) */
+    as = pAstCfg->as;
+
+    zMS = pAstCfg->masterStr;
+
+    //
+    // Main processing loop
+    //
+    for (z=STREAM1; z < STREAMN; z++)
+    {
+        TRACE_VERBOSE1("TaskAsop: AS%d: running", as+z);
+    }
+
+    errno = 0;                              // init error indicator -- no error
+    procSleep = 1;                          // init sleep flag -- sleep
+    procOutDevSel = 1;                      // init device output selection flag -- perform output device selection
+    pAsotCfg->state = INIT_OUT_PROC_STATE;  // init state
+    asopLoopCount = 0;                      // loop counter
+    for (;;)
+    {
+        asopLoopCount++;
+        TRACE_GEN2("TaskAsop (begin Main loop %d) (errno 0x%x)", asopLoopCount, errno);
+
+        //
+        // Check forward (ASIT) error here, TBD
+        //
+
+        // Even if we are not in error state, we check if writeDECCommandRestar issued or not
+        if (gCommandOutputTask_SYNC) {
+            TRACE_TERSE0("TaskAsop: ack for writeDECCommandRestart ... Wait for the command deasserted");
+            gCommandOutputTask_ACK = 1;
+            while (gCommandOutputTask_SYNC) {
+                //Task_sleep(1);
+                Event_pend(asotEvt, Event_Id_NONE, Evt_Id_AsotWakeTimer, BIOS_WAIT_FOREVER);
+            }
+            TRACE_TERSE0("TaskAsop: ack for writeDECCommandRestart ... Sync-ed! Startover the process");
+            procSleep = 1;                          // init sleep flag -- sleep
+            procOutDevSel = 1;                      // init device output selection flag -- perform output device selection
+            pAsotCfg->state = INIT_OUT_PROC_STATE;  // init state -- start over
+            errno = ASOP_DP_FORWARD_ERR;            // Override the error -- for flushing SIO output device
+        }
+
+        // any error forces idling of output
+        if (errno)
+        {
+            for (z=OUTPUT1; z < OUTPUTN; z++)
+            {
+                if (pAstCfg->xOut[z].hTxSio)
+                {
+                    //SIO_idle(pAstCfg->xOut[z].hTxSio);  TO DO: implement proper error handling
+                }
+            }
+
+            TRACE_TERSE1("TaskAsop: Trace stopped at loop %d.", asopLoopCount);
+            //ERRNO_RPRT(TaskAsop, errno);
+        }
+
+        if (procSleep == 1)
+        {
+            TRACE_VERBOSE1("TaskAsop: AS%d: ... sleeping ...", as+zMS);
+            //Task_sleep(1);
+            Event_pend(asotEvt, Event_Id_NONE, Evt_Id_AsotWakeTimer, BIOS_WAIT_FOREVER);
+        }
+
+        if (procOutDevSel == 1)
+        {
+            // select output devices
+            TRACE_GEN1("TaskAsop: AS%d: Output device selection ...", as+zMS);
+            //errno = pP->fxns->selectDevices(pP, pQ, pAsotCfg);
+            errno = asopSelectDevices(&pAsotCfg->pIoOut[0]);   // Do we need to do  for (z=OUTPUT1; z < OUTPUTN; z++)
+            if (errno)
+            {
+                TRACE_TERSE2("TaskAsop: AS%d: selectDevices returned errno = 0x%04x", as+zMS, errno);
+
+                procSleep = 1;
+                procOutDevSel = 1;
+
+                continue;
+            }
+
+            // if no output selected skip remaining processing
+            errno = checkOutSel(pP, pAsotCfg, &outSel);
+            if (errno < 0)
+            {
+                TRACE_TERSE2("TaskAsop: AS%d: checkOutSel returned errno = 0x%04x", as+zMS, errno);
+
+                procSleep = 1;
+                procOutDevSel = 1;
+
+                continue;
+            }
+            else if (!outSel)
+            {
+                TRACE_VERBOSE1("TaskAsop: AS%d: No output selected...", as+zMS);
+
+                procSleep = 1;
+                procOutDevSel = 1;
+
+                continue;
+            }
+        } /* if (procOutDevSel == 1) */
+
+        switch (pAsotCfg->state)
+        {
+            case INIT_OUT_PROC_STATE:
+                gAsopInitOutProcCnt++;
+                Log_info0("TaskAsop: state=INIT_OUT_PROC_STATE");
+
+                //
+                // Output Processing initialization.
+                //
+                errno = PAF_ASOT_initOutProc(pP, pAstCfg->xStr);
+                if (errno < 0)
+                {
+                    pAsotCfg->state = INIT_OUT_PROC_STATE;
+                    procSleep = 1;
+                    procOutDevSel = 1;
+                }
+                else
+                {
+                    //pAsotCfg->state = INITSYNC_DEC_RESET_STATE;
+                    procSleep = 0;
+                    procOutDevSel = 0;
+                    for (z=OUTPUT1; z < OUTPUTN; z++)
+                    {
+                        asopIoCompsInit(&pAstCfg->xOut[z], &pAsotCfg->pIoOut[z]);
+                    }
+
+                    // Start I/O physical layer by priming McASP LLD for output
+                    asopIoPhyPrime(&pAsotCfg->pIoOut[0]);
+
+                    pAsotCfg->state = OUT_PROC_STATE;
+                }
+
+                break;
+
+            case OUT_PROC_STATE:
+                //Semaphore_pend(asopSemTx, BIOS_WAIT_FOREVER);
+                Event_pend(asotEvt, Event_Id_NONE, Evt_Id_AsotTxMcaspEdma, BIOS_WAIT_FOREVER);
+                
+                ioPhyXferComplete(pAsotCfg->pIoOut[0].hIoPhy, FALSE);
+
+                asopDecodePcm(&pAsotCfg->pIoOut[0]);
+
+                asopPhyTransferStart(&pAsotCfg->pIoOut[0]);
+                break;
+
+#if 0
+            case INITSYNC_DEC_RESET_STATE:
+                gAsopInitSyncDecResetCnt++;
+                Log_info0("TaskAsop: state=INITSYNC_DEC_RESET_STATE");
+
+                //
+                // Dec Reset Init-Sync.
+                //
+
+                // Perform Dec Reset init-sync.
+                // Latch Dec Reset AF.
+                errno = PAF_ASOT_initSyncDecReset(pP, pQ, pAsotCfg, &decResetAf);
+                if (errno < 0)
+                {
+                    Log_info1("TaskAsop: state=INITSYNC_DEC_RESET_STATE errno=%d", errno);
+
+                    // sync error -- start over
+                    pAsotCfg->state = INIT_OUT_PROC_STATE;
+                    procSleep = 1;
+                    procOutDevSel = 1;
+                }
+                else if (errno == ASOP_INITSYNC_NOTREADY)
+                {
+                    Log_info1("TaskAsop: state=INITSYNC_DEC_RESET_STATE not sync'd errno=%d", errno);
+
+                    // sync not ready -- try again
+                    pAsotCfg->state = INITSYNC_DEC_RESET_STATE;
+                    errno=0; // FL: temp hack
+                    procSleep = 1;
+                    procOutDevSel = 1;
+                }
+                else // errno==0
+                {
+                    Log_info1("TaskAsop: state=INITSYNC_DEC_RESET_STATE sync'd, errno=%d", errno);
+
+                    // sync'd -- move on
+                    pAsotCfg->state = INITSYNC_DEC_INFO1_STATE;
+                    procSleep = 0;
+                    procOutDevSel = 0;
+                }
+
+                break;
+
+            case INITSYNC_DEC_INFO1_STATE:
+                gAsopInitSyncDecInfo1Cnt++;
+                Log_info0("TaskAsop: state=INITSYNC_DEC_INFO1_STATE");
+
+                //
+                // Dec Info1 Init-Sync.
+                //
+
+                // Perform Dec Info1 init-sync.
+                // Latch Dec Info1 AF.
+                errno = PAF_ASOT_initSyncDecInfo1(pP, pQ, pAsotCfg, &decInfo1Af);
+                if (errno < 0)
+                {
+                    Log_info1("TaskAsop: state=INITSYNC_DEC_INFO1_STATE errno=%d", errno);
+
+                    // sync error -- start over
+                    pAsotCfg->state = INIT_OUT_PROC_STATE;
+                    procSleep = 1;
+                    procOutDevSel = 1;
+                }
+                else if (errno == ASOP_INITSYNC_NOTREADY)
+                {
+                    Log_info1("TaskAsop: state=INITSYNC_DEC_INFO1_STATE not sync'd errno=%d", errno);
+
+                    // sync not ready -- try again
+                    pAsotCfg->state = INITSYNC_DEC_INFO1_STATE;
+                    errno=0; // FL: temp hack
+                    procSleep = 1;
+                    procOutDevSel = 0;
+                }
+                else // errno = 0
+                {
+                    Log_info1("TaskAsop: state=INITSYNC_DEC_INFO1_STATE sync'd errno=%d", errno);
+
+                    // sync'd -- move on
+                    pAsotCfg->state = INITSYNC_DEC_DECODE1_STATE;
+                    procSleep = 0;
+                    procOutDevSel = 0;
+                }
+
+                break;
+
+            case INITSYNC_DEC_DECODE1_STATE:
+                gAsopInitSyncDecDecode1Cnt++;
+                Log_info0("TaskAsop: state=INITSYNC_DEC_DECODE1_STATE");
+
+                //
+                // Dec Info1 Init-Sync.
+                //
+
+                // Perform Dec Info1 init-sync.
+                // Latch Dec Info1 AF.
+                errno = PAF_ASOT_initSyncDecDecode1(pP, pQ, pAsotCfg);
+                if (errno < 0)
+                {
+                    Log_info1("TaskAsop: state=INITSYNC_DEC_DECODE1_STATE errno=%d", errno);
+
+                    // sync error -- start over
+                    pAsotCfg->state = INIT_OUT_PROC_STATE;
+                    procSleep = 1;
+                    procOutDevSel = 1;
+                }
+                else if (errno == ASOP_INITSYNC_NOTREADY)
+                {
+                    Log_info1("TaskAsop: state=INITSYNC_DEC_DECODE1_STATE not sync'd errno=%d", errno);
+
+                    // sync not ready -- try again
+                    pAsotCfg->state = INITSYNC_DEC_DECODE1_STATE;
+                    errno=0; // FL: temp hack
+                    procSleep = 1;
+                    procOutDevSel = 0;
+                }
+                else // errno = 0
+                {
+                    Log_info1("TaskAsop: state=INITSYNC_DEC_DECODE1_STATE sync'd errno=%d", errno);
+
+                    // sync'd -- move on
+                    pAsotCfg->state = OUT_PROC_STATE;
+                    procSleep = 0;
+                    procOutDevSel = 0;
+                }
+
+                break;
+
+            case INITSYNC_RESYNC_STATE:
+                gAsopInitSyncResyncCnt++;
+                Log_info0("TaskAsop: state=INITSYNC_RESYNC_STATE");
+
+                //
+                // Re-Sync.
+                // Use stored AF info from init-sync.
+                // This is done in case of local error.
+                //
+
+                // Perform Dec Info1 init-sync.
+                errno = PAF_ASOT_initSyncResync(pP, pQ, pAsotCfg, &decResetAf,
+                    &decInfo1Af);
+                if (errno < 0)
+                {
+                    Log_info1("TaskAsop: state=INITSYNC_RESYNC_STATE errno=%d", errno);
+
+                    // sync error -- start over
+                    pAsotCfg->state = INIT_OUT_PROC_STATE;
+                    procSleep = 1;
+                    procOutDevSel = 1;
+                }
+                else
+                {
+                    Log_info1("TaskAsop: state=INITSYNC_RESYNC_STATE sync'd errno=%d", errno);
+
+                    // re-sync'd -- move on
+                    pAsotCfg->state = OUT_PROC_STATE;
+                    procSleep = 0;
+                    procOutDevSel = 0;
+                }
+
+                break;
+
+            case OUT_PROC_STATE:
+                gAsopOutProcCnt++;
+                Log_info0("TaskAsop: state=OUT_PROC_STATE");
+
+                //
+                // Output Processing.
+                //
+
+                TRACE_VERBOSE0("TaskAsop: calling decodeProcessing.");
+                errno = pP->fxns->decodeProcessing(pP, pQ, pAsotCfg);
+                if (errno < 0)
+                {
+                    Log_info1("TaskAsop: state=OUT_PROC_STATE errno=%d", errno);
+
+                    //
+                    // Output Processing exit, due to error
+                    //
+
+                    TRACE_TERSE1("TaskAsop: decodeProcessing returns 0x%x, continue", errno);
+                    if (errno == ASOP_DP_FORWARD_ERR)
+                    {
+                        // forward (ASIT) error -- start over
+                        pAsotCfg->state = INIT_OUT_PROC_STATE;
+                        procSleep = 1;
+                        procOutDevSel = 1;
+                    }
+                    else
+                    {
+                        // local (ASOT) error
+                        pAsotCfg->state = INITSYNC_RESYNC_STATE;
+                        procSleep = 1;
+                        procOutDevSel = 0; // disallow device re-select if local error during output processing
+                    }
+                }
+                else if (errno > 0)
+                {
+                    Log_info1("TaskAsop: state=OUT_PROC_STATE errno=%d", errno);
+
+                    //
+                    // Output Processing exit, not due to error
+                    //
+
+                    TRACE_TERSE1("TaskAsop: decodeProcessing returns 0x%x, continue", errno);
+                    if (errno == ASOP_DP_OUT_SIO_UPDATE)
+                    {
+                        // skip re-sync
+                        // resume output processing after new output selected
+                        pAsotCfg->state = OUT_PROC_STATE;
+                        procSleep = 1;
+                        procOutDevSel = 1;
+                    }
+                }
+                else
+                {
+                    Log_info1("TaskAsop: state=OUT_PROC_STATE errno=%d", errno);
+
+                    //
+                    // Output Processing exit, normal
+                    //
+
+                    TRACE_VERBOSE0("TaskAsop: outputProcessing complete with no error.");
+
+                    // no error returned if CB drained
+                    // (i.e. CB drained is normal behavior)
+                    pAsotCfg->state = INIT_OUT_PROC_STATE;
+                    procSleep = 1;
+                    procOutDevSel = 1;
+                }
+
+                break;
+#endif
+            default: // unknown state
+                TRACE_TERSE2("TaskAsop: AS%d: state: unknown, 0x%x", as+zMS, pAsotCfg->state);
+                break;
+        } // End of switch
+
+    } // End of main processing loop for (;;)
+
+
 
 } /* taskAsopFxn */
 
 
 } /* taskAsopFxn */
 
+// ASOT wake timer (clock) function
+Void clkAsotFxn(Void)
+{
+    Event_post(asotEvt, Evt_Id_AsotWakeTimer);
+}
 
 void asopMcaspCallback(void* arg, MCASP_Packet *mcasp_packet)
 {
     /* post semaphore */
     if(mcasp_packet->arg == IOPHY_XFER_FINAL) {
 
 void asopMcaspCallback(void* arg, MCASP_Packet *mcasp_packet)
 {
     /* post semaphore */
     if(mcasp_packet->arg == IOPHY_XFER_FINAL) {
-        Semaphore_post(asopSemTx);
+        //Semaphore_post(asopSemTx);
+        Event_post(asotEvt, Evt_Id_AsotTxMcaspEdma);
     } else {
         ;    // intermediate packet due to buffer wrapping around
     }
 }
 
     } else {
         ;    // intermediate packet due to buffer wrapping around
     }
 }
 
+Int asopSelectDevices(PAF_AST_IoOut *pOut)
+{
+    if((pOut->hIoBuff == NULL) || (pOut->hIoPhy == NULL) || (!d10Initialized)) {
+        return -1;
+    }
+
+    pOut->hMcaspChan = hMcaspTxChan;
+
+    return 0;
+}
+
+/* Check if at least one output selected */
+static Int checkOutSel(
+    const PAF_ASOT_Params *pP,
+    PAF_ASOT_Config *pAsotCfg,
+    Int *pOutSel
+)
+{
+    PAF_AST_IoOut  *pOut;
+    Int outSel;
+    Int z;
+
+    pOut= pAsotCfg->pIoOut; // get pointer to AST common (shared) configuration
+
+    outSel = 0;
+    for (z=OUTPUT1; z < OUTPUTN; z++)
+    {
+        if (pOut[z].hIoPhy)
+        {
+            outSel = 1;
+            break;
+        }
+    }
+
+    *pOutSel = outSel;
+
+    return ASOP_SOK;
+}
+
+#define STRIDE_WORST_CASE 32  // 4-byte (32-bit) word, 2 slots, 4 serializers
+
+/*===========================================================================
+ * Initialize I/O components for output processing
+============================================================================*/
+int asopIoCompsInit(PAF_AST_OutBuf * pOutBuf, PAF_AST_IoOut * pOutIo)
+{
+    // Initialize I/O BUFF and I/O PHY components for output task
+    ioBuffParams_t ioBuffParams;
+    ioPhyParams_t  ioPhyParams;
+
+    ioBuffParams.base         = pOutBuf->outBufConfig.base.pVoid;
+    ioBuffParams.size         = pOutBuf->outBufConfig.allocation/STRIDE_WORST_CASE*STRIDE_WORST_CASE;
+    ioBuffParams.sync         = IOBUff_READ_SYNC;
+    ioBuffParams.nominalDelay = OUTPUT_FRAME_SIZE * (NUM_PRIME_XFERS+1);
+    if(ioBuffInit(pOutIo->hIoBuff, &ioBuffParams) != IOBUFF_NOERR) {
+        return (-1);   // to remove magic number
+    }
+
+    ioPhyParams.ioBuffHandle    = pOutIo->hIoBuff;
+    ioPhyParams.xferFrameSize   = OUTPUT_FRAME_SIZE;
+    ioPhyParams.mcaspChanHandle = hMcaspTxChan;
+    ioPhyParams.ioBuffOp        = IOPHY_IOBUFFOP_READ;
+    if(ioPhyInit(pOutIo->hIoPhy, &ioPhyParams) != IOPHY_NOERR) {
+        return (-1);   // to remove magic number
+    }
+
+    pOutIo->phyXferSize = ioPhyParams.xferFrameSize;
+
+    return 0;
+} /* asopIoCompsInit */
+
+
+/*======================================================================================
+ *  I/O physical layer prime operation required by McASP LLD
+ *====================================================================================*/
+void asopIoPhyPrime(PAF_AST_IoOut *pOut)
+{
+    Int32        count;
+
+    pOut->numPrimeXfers = NUM_PRIME_XFERS;
+
+    for(count = 0; count < pOut->numPrimeXfers; count++)
+    {
+        ioPhyXferSubmit(pOut->hIoPhy);
+    }
+} /* asipIoPhyPrime */
+
+
+/*======================================================================================
+ *  This function starts an I/O PHY transfer for output
+ *====================================================================================*/
+void asopPhyTransferStart(PAF_AST_IoOut *pOut)
+{
+    if(mcaspCheckOverUnderRun(pOut->hMcaspChan)) {
+        mcaspTxReset();
+        mcaspTxCreate();
+        pOut->hMcaspChan = hMcaspTxChan;
+    }
+    else {
+        if(ioPhyXferSubmit(pOut->hIoPhy) == IOPHY_ERR_BUFF_UNDERFLOW) {
+            // Output buffer underflows!
+            printf("\nOutput buffer underflows!\n");
+            exit(0);
+        }
+        else {
+            // Output buffer operates normally
+            ;
+        }
+    }
+}
+
+extern U8 pcmbuf[OUTPUT_FRAME_SIZE];
+
+Int asopDecodePcm(PAF_AST_IoOut *pOut)
+{
+    void *buff1, *buff2;
+    size_t size1, size2;
+    int status;
+
+    status = ioBuffGetWritePtrs(pOut->hIoBuff, pOut->phyXferSize,
+                                &buff1, &size1, &buff2, &size2);
+    if (status == IOBUFF_ERR_OVERFLOW) {
+        /* skip processing since output buffer overflows */
+        return IOBUFF_ERR_OVERFLOW;   // to use a different error code
+    }
+
+    // Copy PCM data to output buffer to be transmitted by McASP
+    memcpy(buff1, &pcmbuf[0], size1);
+    Cache_wbInv(buff1, size1, Cache_Type_ALL,TRUE);
+
+    ioBuffWriteComplete(pOut->hIoBuff, buff1, size1);
+
+    if(buff2 != NULL) {
+      memcpy(buff2, &pcmbuf[size1], size2);
+      Cache_wbInv(buff2, size2, Cache_Type_ALL,TRUE);
+
+      ioBuffWriteComplete(pOut->hIoBuff, buff2, size2);
+    }
+
+    return 0;
+}
+
 /* Nothing past this line */
 /* Nothing past this line */