]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/performance-audio-sr.git/blobdiff - pasdk/test_dsp/framework/audioStreamOutIo.c
PASDK-577:Add "proof of concept" code for McASP LLD to setCheckRateX
[processor-sdk/performance-audio-sr.git] / pasdk / test_dsp / framework / audioStreamOutIo.c
index c70438c9c7860528d7599f8726f7054bdb733e1d..a655af2675ac0b7681a8cceeee8678bdd57435fb 100644 (file)
@@ -58,36 +58,106 @@ All rights reserved.
 #define DEC_OUTNUMBUF_MAP(X) \
       pP->poutNumBufMap[z]->map[(X) >= pP->poutNumBufMap[z]->length ? 0 : (X)]
 
-#define STRIDE_WORST_CASE 32  // 4-byte (32-bit) word, 2 slots, 4 serializers
+//#define STRIDE_WORST_CASE 32  // 4-byte (32-bit) word, 2 slots, 4 serializers
 
 extern Ptr hMcaspTxChan;
 extern Int d10Initialized;
 
 
-// FL, New IO: this function is currently a stub
-// FL, New IO: need to McASP/EDMA configuration using SAP configuration from Output shortcut
 // Select Output devices
-Int asopSelectDevices(void *pConfig, PAF_AST_IoOut *pOut)
+Int asopSelectDevices(
+    const PAF_SIO_Params *pOutCfg, 
+    PAF_AST_IoOut *pOut
+)
 {
-    if((pOut->hIoBuff == NULL) || (pOut->hIoPhy == NULL) || (!d10Initialized)) {
-        return -1;
-    }
+    mcaspLLDconfig *pReqLldCfg;
+    Ptr mcaspChanHandle;
+    Int32 status;
+    Aud_STATUS audStatus;
+    UInt postedEvents;    
 
-    if(pOut->hMcaspChan == NULL) {
-        Audk2g_STATUS status;
-        mcaspLLDconfig * lldCfg;
-        Ptr mcaspChanHandle;
+    if ((pOut->hIoBuff == NULL) || (pOut->hIoPhy == NULL) || (!d10Initialized)) 
+    {
+        return ASOP_IO_ERR_IO_UNINIT;
+    }
 
-        lldCfg = (mcaspLLDconfig *)pConfig;
-        status = mcasplldChanCreate(lldCfg, &mcaspChanHandle);
-        if(status != Audk2g_EOK) {
-            return -1;
+    // Deactivate currently active Output device
+    if (pOut->hMcaspChan != NULL)
+    {
+        // Reset channel
+        status = mcaspControlChan(pOut->hMcaspChan, MCASP_CHAN_RESET, NULL);
+        if (status != MCASP_COMPLETED)
+        {
+            Log_info0("asopSelectDevices(): McASP channel reset failed!\n");
+            return ASOP_IO_ERR_MCASP_CFG;            
         }
+        
+        // Delete McASP LLD channel
+        status = mcaspDeleteChan(pOut->hMcaspChan);
+        if (status != MCASP_COMPLETED)
+        {
+            Log_info0("asopSelectDevices(): McASP channel deletion failed!\n");
+            return ASOP_IO_ERR_MCASP_CFG;
+        }
+        
+        // Clear (drop) already posted Output data events
+        postedEvents = Event_getPostedEvents(gAsotEvtHandle);
+        while ((postedEvents & Evt_Id_AsotTxMcaspEdma) != 0)
+        {
+            Event_pend(gAsotEvtHandle, Event_Id_NONE, Evt_Id_AsotTxMcaspEdma, 0);
+            postedEvents = Event_getPostedEvents(gAsotEvtHandle);
+        }        
+        
+        pOut->hMcaspChan = NULL;            // reset active McASP LLD handle
+        pOut->pLldCfg->hMcaspChan = NULL;   // reset McASP LLD handle for active McASP LLD configuration
+        pOut->pLldCfg = NULL;               // reset pointer to active McASP LLD configuration
+    }
 
-        pOut->hMcaspChan = mcaspChanHandle;
+    // Activate requested device
+    if (pOutCfg != NULL)
+    {
+        //
+        // Device other than OutNone selected
+        //
+        
+        pReqLldCfg = (mcaspLLDconfig *)pOutCfg->sio.pConfig;
+        if (pReqLldCfg->hMcaspChan == NULL) 
+        {
+            // Create McASP LLD channel
+            mcaspChanHandle = NULL;
+            audStatus = mcasplldChanCreate(pReqLldCfg, &mcaspChanHandle);
+            if (audStatus != Aud_EOK) 
+            {
+                Log_info0("asopSelectDevices(): McASP channel creation failed!\n");
+                return ASOP_IO_ERR_MCASP_CFG;
+            }
+
+            pReqLldCfg->hMcaspChan = mcaspChanHandle;   // set McASP LLD handle for requested McASP LLD configuration
+            pOut->pLldCfg = pReqLldCfg;                 // set pointer to active McASP LLD configuration
+            pOut->hMcaspChan = pReqLldCfg->hMcaspChan;  // set active McASP LLD handle
+            
+            // configure stride according to selected McASP LLD configuration
+            pOut->stride = pReqLldCfg->mcaspChanParams->noOfSerRequested * 
+                pReqLldCfg->mcaspChanParams->noOfChannels;
+                
+            pOut->rateX = 1.; // intialize rateX
+        }
+        else
+        {
+            return ASOP_IO_ERR_INV_STATE;
+        }
+    }
+    else
+    {
+        //
+        // OutNone device selected
+        //
+        
+        pOut->hMcaspChan = NULL;    // reset active McASP LLD handle
+        pOut->pLldCfg = NULL;       // reset pointer to active McASP LLD configuration
     }
 
-    return 0;
+    return ASOP_IO_SOK;
 }
 
 // Check if Output device SIO selection changed
@@ -105,12 +175,12 @@ Int checkOutDevSioSelUpdate(
     if ((z < OUTPUT1) || (z >= OUTPUTN))
     {
         *pOutDevSelUpdate = FALSE;
-        return -1;
+        return ASOP_IO_ERR_INV_PARAMS;
     }
     
     *pOutDevSelUpdate = (Bool)(pAstCfg->xOut[z].outBufStatus.sioSelect >= 0);
 
-    return 0;
+    return ASOP_IO_SOK;
 }
 
 // Check if any Output device SIO selection changed
@@ -138,7 +208,7 @@ Int checkAnyOutDevSioSelUpdate(
     
     *pOutDevSelUpdate = outDevSelUpdate;
 
-    return 0;
+    return ASOP_IO_SOK;
 }
 
 // -----------------------------------------------------------------------------
@@ -174,6 +244,10 @@ Int asopSetCheckRateX(
     Int zMI;
     Int zMS;
     Int zE, zX;
+    // "proof of concept" for McASP LLD API
+    Uint32 divider;
+    Mcasp_HwSetupData mcaspSetup;
+    Int32 status;
 
     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
     pOut = pAsotCfg->pIoOut; // get pointer to ASOT IO configuration
@@ -242,10 +316,60 @@ Int asopSetCheckRateX(
                 return ((getVal & 0xff) | ASPERR_RATE_CHECK);
             }
 #endif // FL, New IO
+            if (pOut->rateX != rateX)
+            {
+                UInt32 regVal;
+                
+                //
+                // "Proof on concept" code for McASP LLD API to change bit clock divider.
+                //
+
+                // Initialize divider value.
+                // This works for AHCLKX input from HDMI & sample rate = 44.1,48,88.2,96,192 kHz.
+                divider = 2;
+                
+                // Update divider based on calculated rateX
+                divider /= rateX;
+
+#if 0 // debug
+                // Experimental code: directly write CLKXDIV
+                regVal = *(volatile UInt32 *)0x23400B0; // read MCASP_ACLKXCTL
+                regVal &= ~0x1F; // mask off CLKXDIV bits
+                //regVal |= 7; // set CLKXDIV for 48 kHz
+                //regVal |= 3; // set CLKXDIV for 96 kHz
+                //regVal |= 1; // set CLKXDIV for 192 kHz
+                regVal |= (divider-1); // set CLKXDIV
+                *(volatile UInt32 *)0x23400B0 = regVal; // write MCASP_ACLKXCTL
+#endif                
+
+#if 1
+                // get existing McASP HW setup
+                status = mcaspControlChan(pOut->hMcaspChan, Mcasp_IOCTL_CNTRL_GET_FORMAT_CHAN, &mcaspSetup);
+                if (status != MCASP_COMPLETED)
+                {
+                    Log_info0("asopSetCheckRateX(): McASP get channel format failed!\n");
+                    return ASOP_IO_ERR_MCASP_CFG;
+                }
+                
+                // update CLKXDIV based on rateX
+                mcaspSetup.clk.clkSetupClk &= ~CSL_MCASP_ACLKXCTL_CLKXDIV_MASK;
+                mcaspSetup.clk.clkSetupClk |= (divider-1);
+                
+                // update McASP HW setup
+                status = mcaspControlChan(pOut->hMcaspChan, Mcasp_IOCTL_CNTRL_SET_FORMAT_CHAN, &mcaspSetup);
+                if (status != MCASP_COMPLETED)
+                {
+                    Log_info0("asopSetCheckRateX(): McASP set channel format failed!\n");
+                    return ASOP_IO_ERR_MCASP_CFG;
+                }
+#endif            
+                
+                pOut->rateX = rateX;
+            }
         }
     }
 
-    return 0;
+    return ASOP_IO_SOK;
 } //asopSetCheckRateX
 
 // -----------------------------------------------------------------------------
@@ -305,21 +429,21 @@ Int asopStartOutput(
 // Need to Revisit: Starting Clocks here seems logical & also manages the McASP without spurious underruns .
 #if 0
             // if device selected and valid then enable stat tracking if
-                       // required and start clocking
-                       if ((pAstCfg->xOut[z].outBufStatus.sioSelect < 0) && (pAstCfg->xOut[z].hTxSio))
-                       {
-                               TRACE_VERBOSE0("PAF_ASOT_startOutput: start SIO clocks");
-                               errme = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_OUTPUT_START_CLOCKS, 0);
-                               if (errno)
-                               {
-                                       TRACE_VERBOSE2("PAF_ASOT_startOutput: errme 0x%x, errno 0x%x", errme, errno);
-                                       SIO_idle(pAstCfg->xOut[z].hTxSio);
-                                       if (!errno)
-                                       {
-                                               errno = ASPERR_DEVOUT + errme;
-                                       }
-                               }
-                       }
+            // required and start clocking
+            if ((pAstCfg->xOut[z].outBufStatus.sioSelect < 0) && (pAstCfg->xOut[z].hTxSio))
+            {
+                TRACE_VERBOSE0("PAF_ASOT_startOutput: start SIO clocks");
+                errme = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_OUTPUT_START_CLOCKS, 0);
+                if (errno)
+                {
+                    TRACE_VERBOSE2("PAF_ASOT_startOutput: errme 0x%x, errno 0x%x", errme, errno);
+                    SIO_idle(pAstCfg->xOut[z].hTxSio);
+                    if (!errno)
+                    {
+                        errno = ASPERR_DEVOUT + errme;
+                    }
+                }
+            }
 #endif            
 
             // Set sample count so that DOB knows how much data to send
@@ -328,14 +452,14 @@ Int asopStartOutput(
 
 #if 1 // FL, New IO: add similar thing to be figured out
             // Update framework Phy transfer size
-            pOut[z].phyXferSize = pAstCfg->xOut[z].outBufConfig.lengthofFrame * OUTPUT_STRIDE * WORD_SIZE_PCM;
-            // Update IO Phy transfer size            
+            pOut[z].phyXferSize = pAstCfg->xOut[z].outBufConfig.lengthofFrame * pOut[z].stride * WORD_SIZE_PCM;
+            // Update IO Phy transfer size
             ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
             ioPhyCtl.params.xferFrameSize = pOut[z].phyXferSize;
             ioPhyControl(pOut[z].hIoPhy, &ioPhyCtl);
             // Update IO Buff delay to match Phy transfer size
             ioBuffAdjustDelay(pOut[z].hIoBuff, pOut[z].phyXferSize * (NUM_PRIME_XFERS+1));
-#endif            
+#endif
 
             if (pAstCfg->xOut[z].outBufStatus.markerMode == PAF_OB_MARKER_ENABLED)
             {
@@ -385,7 +509,7 @@ Int asopStartOutput(
         }
     }
 
-    return 0;
+    return ASOP_IO_SOK;
 } /* asopStartOutput */
 
 // -----------------------------------------------------------------------------
@@ -411,7 +535,7 @@ Int asopStopOutput(
     PAF_AST_IoOut  *pOut;
     Int as;                     /* Audio Stream Number (1, 2, etc.) */
     Int z;                      /* output counter */
-    Int errno = 0, getVal;
+    Int errno, getVal;
     Int zS, zX;
     PAF_SIO_IALG_Obj    *pObj;
     PAF_SIO_IALG_Config *pAlgConfig;
@@ -421,6 +545,7 @@ Int asopStopOutput(
     as = pAstCfg->as;
     (void)as;  // clear compiler warning in case not used with tracing disabled
 
+    errno = ASOP_IO_SOK;
     for (z=OUTPUT1; z < OUTPUTN; z++) 
     {
         if (pOut[z].hIoPhy) 
@@ -519,39 +644,46 @@ Int asopStopOutput(
  * Initialize I/O components for output processing
 ============================================================================*/
 Int asopIoCompsInit(
-    PAF_AST_OutBuf *pOutBuf, 
-    PAF_AST_IoOut *pOutIo
+    Int16 strAfSampleCount,     // stream audio frame sample count
+    PAF_AST_OutBuf *pOutBuf,    // pointer to Output Buffer
+    PAF_AST_IoOut *pOutIo       // pointer to Output IO
 )
 {
-    // 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) 
+    if (pOutIo->hMcaspChan != NULL)
     {
-        return -1;   // to remove magic number
-    }
+        // Initialize I/O BUFF and I/O PHY components for output task
+        ioBuffParams.base         = pOutBuf->outBufConfig.base.pVoid;
+        // Set IO buffer size to multiple of audio frame sample count x stride x size of element.
+        // This ensures no split buffers will be allocated on Output buffer wrap.
+        ioBuffParams.size         = pOutBuf->outBufConfig.allocation/(strAfSampleCount * pOutIo->stride * WORD_SIZE_PCM)*
+            (strAfSampleCount * pOutIo->stride * WORD_SIZE_PCM);
+        ioBuffParams.sync         = IOBUff_READ_SYNC;
+        ioBuffParams.nominalDelay = strAfSampleCount * pOutIo->stride * WORD_SIZE_PCM * (NUM_PRIME_XFERS+1);
+        if (ioBuffInit(pOutIo->hIoBuff, &ioBuffParams) != IOBUFF_NOERR) 
+        {
+            return ASOP_IO_ERR_IOBUFF_INIT;   // to remove magic number
+        }
 
-    ioPhyParams.ioBuffHandle    = pOutIo->hIoBuff;
-    ioPhyParams.xferFrameSize   = OUTPUT_FRAME_SIZE;
-    ioPhyParams.mcaspChanHandle = pOutIo->hMcaspChan;
-    ioPhyParams.ioBuffOp        = IOPHY_IOBUFFOP_READ;
-    if(ioPhyInit(pOutIo->hIoPhy, &ioPhyParams) != IOPHY_NOERR) 
-    {
-        return -1;   // to remove magic number
-    }
+        ioPhyParams.ioBuffHandle    = pOutIo->hIoBuff;
+        ioPhyParams.xferFrameSize   = strAfSampleCount * pOutIo->stride * WORD_SIZE_PCM;
+        ioPhyParams.mcaspChanHandle = pOutIo->hMcaspChan;
+        ioPhyParams.ioBuffOp        = IOPHY_IOBUFFOP_READ;
+        if (ioPhyInit(pOutIo->hIoPhy, &ioPhyParams) != IOPHY_NOERR) 
+        {
+            return ASOP_IO_ERR_IOPHY_INIT;   // to remove magic number
+        }
 
-    pOutIo->phyXferSize = ioPhyParams.xferFrameSize;
+        pOutIo->phyXferSize = ioPhyParams.xferFrameSize;
+        
+        pOutIo->ioBuffBuf2AllocCnt = 0; // initialize buffer2 alloc count (indicates Output buffer wrap)
+        pOutIo->errIoBuffOvrCnt = 0;    // initialize IO buff overflow count
+        pOutIo->errIoBuffUndCnt = 0;    // initialize IO buff underflow count
+    }
     
-    pOutIo->ioBuffBuf2AllocCnt = 0; // initialize buffer2 alloc count (indicates Output buffer wrap)
-    pOutIo->errIoBuffOvrCnt = 0; // initialize IO buff overflow count
-    pOutIo->errIoBuffUndCnt = 0; // initialize IO buff underflow count
-
-    return 0;
+    return ASOP_IO_SOK;
 } /* asopIoCompsInit */
 
 /*======================================================================================
@@ -595,19 +727,62 @@ Int asopInitOutBufConfig(
     pOutBufCfg = &pOutBuf->outBufConfig;
     hIoBuff = pOutIo->hIoBuff;
     
-    pOutBufCfg->stride = OUTPUT_STRIDE;
+    pOutBufCfg->stride = pOutIo->stride;
     pOutBufCfg->sizeofElement = WORD_SIZE_PCM;
     pOutBufCfg->precision = 24;
     
     ioBuffGetInfo(hIoBuff, &outBuffInfo);
-       pOutBufCfg->base.pLgInt = outBuffInfo.base;
-       pOutBufCfg->sizeofBuffer = outBuffInfo.size;
+    pOutBufCfg->base.pLgInt = outBuffInfo.base;
+    pOutBufCfg->sizeofBuffer = outBuffInfo.size;
+    
+    pOutBuf->pOutBuf = &(pOutBuf->outBufConfig);
     
-       pOutBuf->pOutBuf = &(pOutBuf->outBufConfig);
+    return ASOP_IO_SOK;
+}
+
+Int asopGetOutBufPtrs(
+    PAF_AST_IoOut *pOutIo,
+    size_t writeSize
+)
+{
+    void *buff1, *buff2;
+    size_t size1, size2;
+    Int status;
+
+    status = ioBuffGetWritePtrs(pOutIo->hIoBuff, writeSize,
+                                &buff1, &size1, &buff2, &size2);
+    if (status == IOBUFF_ERR_OVERFLOW)
+    {
+        pOutIo->errIoBuffOvrCnt++;
+        //System_printf ("asopGetOutBufPtrs: output buff overflow\n"); // debug
+
+        // skip processing since output buffer overflows
+        return ASOP_IO_ERR_OUTBUF_OVERFLOW;
+    }
+    else if (status == IOBUFF_ERR_UNDERFLOW)
+    {
+        pOutIo->errIoBuffUndCnt++;
+        //System_printf ("asopGetOutBufPtrs: output buff underflow\n"); // debug
+
+        // already underflows and remain in underflow
+    }
     
-    return 0;
+    if ((buff2 != NULL) || (size2 != 0))
+    {
+        // Two buffers allocated indicates split buffer allocation on buffer wrap.
+        pOutIo->ioBuffBuf2AllocCnt++; // increment count of allocated buffer2
+    }
+
+    // save buffer pointers & sizes for later write complete
+    pOutIo->buff1 = buff1;
+    pOutIo->size1 = size1;
+    pOutIo->buff2 = buff2;
+    pOutIo->size2 = size2;
+
+    return ASOP_IO_SOK;
 }
 
+#if 0
 // Update Output buffer configuration.
 // This is needed for proper operation of PCM encoder.
 Int asopUpdateOutBufConfig(
@@ -627,13 +802,13 @@ Int asopUpdateOutBufConfig(
 
     // FL, New IO: original code can change these values in every DOB issue
     //  Need to determine if this is required or not.
-    pOutBufCfg->stride = OUTPUT_STRIDE;
+    pOutBufCfg->stride = pOutIo->stride;
     pOutBufCfg->sizeofElement = WORD_SIZE_PCM;
     pOutBufCfg->precision = 24;
     
     //JXTODO: to replace hard coded write size
     // Get write pointers of output memory pool
-       total_write_size = pOutBufCfg->lengthofFrame * pOutBufCfg->stride * pOutBufCfg->sizeofElement;
+    total_write_size = pOutBufCfg->lengthofFrame * pOutBufCfg->stride * pOutBufCfg->sizeofElement;
     status = ioBuffGetWritePtrs(hIoBuff, total_write_size,
         &buff1, &size1, &buff2, &size2);
     if (status == IOBUFF_ERR_OVERFLOW) 
@@ -642,7 +817,7 @@ Int asopUpdateOutBufConfig(
         //System_printf ("asopUpdateOutBufConfig: output buff overflow\n"); // debug
 
         // skip processing since output buffer overflows        
-        return -1;
+        return ASOP_IO_ERR_OUTBUF_OVERFLOW;
     }
     else if (status == IOBUFF_ERR_UNDERFLOW) 
     {
@@ -651,24 +826,25 @@ Int asopUpdateOutBufConfig(
         
         // already underflows and remain in underflow
     }
-
+#if 0
     // Update Output buffer pointer for Encoder
-       pOutBufCfg->pntr.pLgInt = buff1;
+    pOutBufCfg->pntr.pLgInt = buff1;
     if ((buff2 != NULL) || (size2 != 0))
     {
         // buff2 should always be NULL for Output & size2 should always be 0 for Output.
         // Track this here.
         pOutIo->ioBuffBuf2AllocCnt++; // debug
     }
-    
+#endif
     // save buffer pointers & sizes for later write complete
     pOutIo->buff1 = buff1;
     pOutIo->size1 = size1;
     pOutIo->buff2 = buff2;
     pOutIo->size2 = size2;
     
-    return 0;
+    return ASOP_IO_SOK;
 }
+#endif
 
 // Mark Output buffers write complete
 Int asopMarkOutBuffsWriteComplete(
@@ -695,7 +871,7 @@ Int asopMarkOutBuffsWriteComplete(
         ioBuffWriteComplete(hIoBuff, buff2, size2);
     }
     
-    return 0;
+    return ASOP_IO_SOK;
 }
 
 /*======================================================================================