PASDK-577:Move local var declarations outside if()
[processor-sdk/performance-audio-sr.git] / pasdk / test_dsp / framework / audioStreamOutIo.c
2 /*
3 Copyright (c) 2018, 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 */
35 /*
36  *  ======== audioStreamOutIo.c ========
37  */
39 #include <string.h> // for memset
40 #include <xdc/runtime/Log.h>
41 #include <xdc/runtime/System.h>
42 #include <xdc/std.h>
44 #include "mcasp_cfg.h"
45 #include "ioConfig.h"    //TODO: remove this header
46 #include "ioBuff.h"
47 #include "ioPhy.h"
48 #include "ioData.h"
50 #include "pafsio_ialg.h"
51 #include "stdasp.h"
52 #include "asperr.h"
54 #include "audioStreamProc_common.h"
55 #include "audioStreamOutProc.h"
56 #include "audioStreamOutIo.h"
58 #define DEC_OUTNUMBUF_MAP(X) \
59       pP->poutNumBufMap[z]->map[(X) >= pP->poutNumBufMap[z]->length ? 0 : (X)]
61 #define STRIDE_WORST_CASE 32  // 4-byte (32-bit) word, 2 slots, 4 serializers
63 extern Ptr hMcaspTxChan;
64 extern Int d10Initialized;
67 // Select Output devices
68 Int asopSelectDevices(
69     const PAF_SIO_Params *pOutCfg, 
70     PAF_AST_IoOut *pOut
71 )
72 {
73     mcaspLLDconfig *pReqLldCfg;
74     Ptr mcaspChanHandle;
75     Aud_STATUS status;
77     if ((pOut->hIoBuff == NULL) || (pOut->hIoPhy == NULL) || (!d10Initialized)) 
78     {
79         return ASOP_IO_ERR_IO_UNINIT;
80     }
82     // Deactivate currently active Output device
83     if (pOut->hMcaspChan != NULL)
84     {
85         // Delete McASP LLD channel
86         status = mcaspDeleteChan(pOut->hMcaspChan);
87         if (status != Aud_EOK)
88         {
89             Log_info0("asopSelectDevices(): McASP channel deletion failed!\n");
90             return ASOP_IO_ERR_MCASP_CFG;
91         }
92         
93         pOut->hMcaspChan = NULL;            // reset active McASP LLD handle
94         pOut->pLldCfg->hMcaspChan = NULL;   // reset McASP LLD handle for active McASP LLD configuration
95         pOut->pLldCfg = NULL;               // reset pointer to active McASP LLD configuration
96     }
98     // Activate requested device
99     if (pOutCfg != NULL)
100     {
101         //
102         // Device other than OutNone selected
103         //
104         
105         pReqLldCfg = (mcaspLLDconfig *)pOutCfg->sio.pConfig;
106         if (pReqLldCfg->hMcaspChan == NULL) 
107         {
108             // Create McASP LLD channel
109             mcaspChanHandle = NULL;
110             status = mcasplldChanCreate(pReqLldCfg, &mcaspChanHandle);
111             if (status != Aud_EOK) {
112                 Log_info0("asopSelectDevices(): McASP channel creation failed!\n");
113                 return ASOP_IO_ERR_MCASP_CFG;
114             }
116             pReqLldCfg->hMcaspChan = mcaspChanHandle;   // set McASP LLD handle for requested McASP LLD configuration
117             pOut->pLldCfg = pReqLldCfg;                 // set pointer to active McASP LLD configuration
118             pOut->hMcaspChan = pReqLldCfg->hMcaspChan;  // set active McASP LLD handle
119             
120             // configure stride according to selected McASP LLD configuration
121             pOut->stride = pReqLldCfg->mcaspChanParams->noOfSerRequested * 
122                 pReqLldCfg->mcaspChanParams->noOfChannels;
123         }
124     }
125     else
126     {
127         //
128         // OutNone device selected
129         //
130         
131         pOut->hMcaspChan = NULL;    // reset active McASP LLD handle
132         pOut->pLldCfg = NULL;       // reset pointer to active McASP LLD configuration
133     }
135     return ASOP_IO_SOK;
138 // Check if Output device SIO selection changed
139 Int checkOutDevSioSelUpdate(
140     const PAF_ASOT_Params *pP, 
141     PAF_ASOT_Config *pAsotCfg,
142     Int z, 
143     Bool *pOutDevSelUpdate
146     PAF_AST_Config *pAstCfg;
147     
148     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
150     if ((z < OUTPUT1) || (z >= OUTPUTN))
151     {
152         *pOutDevSelUpdate = FALSE;
153         return ASOP_IO_ERR_INV_PARAMS;
154     }
155     
156     *pOutDevSelUpdate = (Bool)(pAstCfg->xOut[z].outBufStatus.sioSelect >= 0);
158     return ASOP_IO_SOK;
161 // Check if any Output device SIO selection changed
162 Int checkAnyOutDevSioSelUpdate(
163     const PAF_ASOT_Params *pP, 
164     PAF_ASOT_Config *pAsotCfg,
165     Bool *pOutDevSelUpdate
168     PAF_AST_Config *pAstCfg;
169     Int outDevSelUpdate;
170     Int z;
171     
172     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
174     outDevSelUpdate = FALSE;
175     for (z=OUTPUT1; z < OUTPUTN; z++) 
176     {
177         if (pAstCfg->xOut[z].outBufStatus.sioSelect >= 0)
178         {
179             outDevSelUpdate = TRUE;
180             break;
181         }
182     }
183     
184     *pOutDevSelUpdate = outDevSelUpdate;
186     return ASOP_IO_SOK;
189 // -----------------------------------------------------------------------------
190 // ASOT Decoding Function Helper - SIO Driver Change
191 //
192 //   Name:      PAF_ASOT_setCheckRateX
193 //   Purpose:   Decoding Function for reinitiating output.
194 //   From:      AST Parameter Function -> decodeInfo1
195 //              AST Parameter Function -> decodeInfo2
196 //   Uses:      See code.
197 //   States:    x
198 //   Return:    Error number in standard form (0 on success).
199 //   Trace:     None.
200 //
202 /* 0: set, 1: check, unused for now. --Kurt */
203 Int asopSetCheckRateX(
204     const PAF_ASOT_Params *pP, 
205     const PAF_ASOT_Patchs *pQ, 
206     PAF_ASOT_Config *pAsotCfg, 
207     Int check
210     PAF_AST_Config *pAstCfg;
211     PAF_AST_IoOut  *pOut;
212     float rateX;
213     PAF_SampleRateHz rateO /* std */, rateI /* inv */;
214     Int z;                              /* output counter */
215     Int zx;                             /* output re-counter */
216     Int getVal;
217     int inputRate, inputCount, outputRate, outputCount;
218     Int zMD;
219     Int zMI;
220     Int zMS;
221     Int zE, zX;
223     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
224     pOut = pAsotCfg->pIoOut; // get pointer to ASOT IO configuration
225     
226     zMD = pAstCfg->masterDec;
227     zMS = pAstCfg->masterStr;
228     zMI = pP->zone.master;
230     inputRate = pAstCfg->xInp[zMI].inpBufStatus.sampleRateStatus;
231     inputCount = pAstCfg->xDec[zMD].decodeStatus.frameLength;
232     rateI = pAstCfg->xStr[zMS].pAudioFrame->fxns->sampleRateHz(pAstCfg->xStr[zMS].pAudioFrame, 
233         inputRate, PAF_SAMPLERATEHZ_INV);
235     for (z=OUTPUT1; z < OUTPUTN; z++) 
236     {
237         if (pOut[z].hIoPhy && (pAstCfg->xOut[z].outBufStatus.clock & 0x01)) 
238         {
239             // determine associated encoder
240             zE = z;
241             for (zX = ENCODE1; zX < ENCODEN; zX++) 
242             {
243                 if (pP->outputsFromEncodes[zX] == z) 
244                 {
245                     zE = zX;
246                     break;
247                 }
248             }
250             outputRate = pAstCfg->xEnc[zE].encodeStatus.sampleRate;
251             outputCount = pAstCfg->xEnc[zE].encodeStatus.frameLength;
252             rateO = pAstCfg->xStr[zMS].pAudioFrame->fxns->sampleRateHz(pAstCfg->xStr[zMS].pAudioFrame, 
253                 outputRate, PAF_SAMPLERATEHZ_STD);
254             if ((rateI > 0) && (rateO > 0))
255             {
256                 rateX = rateO /* std */ * rateI /* inv */;
257             }
258             else if (inputCount != 0)
259             {
260                 rateX = (float)outputCount / inputCount;
261             }
262             else
263             {
264                 return ASPERR_INFO_RATERATIO;
265             }
267 #if 0 // FL, New IO: add similar thing to be figured out     
268             getVal = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_SET_RATEX, (Arg)&rateX);
269             if (getVal == DOBERR_RATECHANGE) 
270             {
271                 for (zx=OUTPUT1; zx < OUTPUTN; zx++)
272                 {
273                     if (pAstCfg->xOut[zx].hTxSio)
274                     {
275                         SIO_idle(pAstCfg->xOut[zx].hTxSio);
276                     }
277                 }
279                 // this forces an exit from the calling state machine which will
280                 // eventually call startOutput which calls setCheckRateX for all outputs
281                 // and so it is ok, in the presence of a rate change on any output, to
282                 // exit this loop /function early.
283                 return ASPERR_INFO_RATECHANGE;
284             }
285             else if (getVal != SYS_OK)
286             {
287                 return ((getVal & 0xff) | ASPERR_RATE_CHECK);
288             }
289 #endif // FL, New IO
290             // FL: ugly little experiment
291             //*(volatile UInt32 *)0x23400B0 |= 7;
292         }
293     }
295     return ASOP_IO_SOK;
296 } //asopSetCheckRateX
298 // -----------------------------------------------------------------------------
299 // ASOT Decoding Function Helper - SIO Driver Start
300 //
301 //   Name:      PAF_ASOT_startOutput
302 //   Purpose:   Decoding Function for initiating output.
303 //   From:      AST Parameter Function -> decodeInfo1
304 //   Uses:      See code.
305 //   States:    x
306 //   Return:    Error number in standard or SIO form (0 on success).
307 //   Trace:     Message Log "trace" in Debug Project Configuration reports:
308 //              * State information as per parent.
309 //              * SIO control errors.
310 //
311 Int asopStartOutput(
312     const PAF_ASOT_Params *pP,
313     const PAF_ASOT_Patchs *pQ,
314     PAF_ASOT_Config *pAsotCfg
317     PAF_AST_Config *pAstCfg;
318     PAF_AST_IoOut  *pOut;
319     Int as;                     /* Audio Stream Number (1, 2, etc.) */
320     Int z;                      /* output counter */
321     Int nbufs;
322     Int zE, zS, zX;
323     Int zMD;
324     PAF_SIO_IALG_Obj    *pObj;
325     PAF_SIO_IALG_Config *pAlgConfig;
326     ioPhyCtl_t ioPhyCtl;
329     pAstCfg = pAsotCfg->pAstCfg; // get pointer to common (shared) configuration
330     pOut = pAsotCfg->pIoOut; // get pointer to ASOT IO configuration
331     as = pAstCfg->as;
332     zMD = pAstCfg->masterDec;
334     for (z=OUTPUT1; z < OUTPUTN; z++)
335     {
336         if (pOut[z].hIoPhy)
337         {
338             // determine associated encoder and stream
339             zE = z;
340             zS = z;
341             for (zX = ENCODE1; zX < ENCODEN; zX++)
342             {
343                 if (pP->outputsFromEncodes[zX] == z)
344                 {
345                     zE = zX;
346                     zS = pP->streamsFromEncodes[zE];
347                     break;
348                 }
349             }
351             // FL, New IO: add similar thing to be figured out
352 // Need to Revisit: Starting Clocks here seems logical & also manages the McASP without spurious underruns .
353 #if 0
354             // if device selected and valid then enable stat tracking if
355             // required and start clocking
356             if ((pAstCfg->xOut[z].outBufStatus.sioSelect < 0) && (pAstCfg->xOut[z].hTxSio))
357             {
358                 TRACE_VERBOSE0("PAF_ASOT_startOutput: start SIO clocks");
359                 errme = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_OUTPUT_START_CLOCKS, 0);
360                 if (errno)
361                 {
362                     TRACE_VERBOSE2("PAF_ASOT_startOutput: errme 0x%x, errno 0x%x", errme, errno);
363                     SIO_idle(pAstCfg->xOut[z].hTxSio);
364                     if (!errno)
365                     {
366                         errno = ASPERR_DEVOUT + errme;
367                     }
368                 }
369             }
370 #endif            
372             // Set sample count so that DOB knows how much data to send
373             pAstCfg->xOut[z].outBufConfig.lengthofFrame =
374                 pAstCfg->xEnc[zE].encodeInStruct.pAudioFrame->sampleCount;
376 #if 1 // FL, New IO: add similar thing to be figured out
377             // Update framework Phy transfer size
378             pOut[z].phyXferSize = pAstCfg->xOut[z].outBufConfig.lengthofFrame * pOut[z].stride * WORD_SIZE_PCM;
379             // Update IO Phy transfer size
380             ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
381             ioPhyCtl.params.xferFrameSize = pOut[z].phyXferSize;
382             ioPhyControl(pOut[z].hIoPhy, &ioPhyCtl);
383             // Update IO Buff delay to match Phy transfer size
384             ioBuffAdjustDelay(pOut[z].hIoBuff, pOut[z].phyXferSize * (NUM_PRIME_XFERS+1));
385 #endif
387             if (pAstCfg->xOut[z].outBufStatus.markerMode == PAF_OB_MARKER_ENABLED)
388             {
389                 pObj = (PAF_SIO_IALG_Obj *) pAstCfg->xOut[z].outChainData.head->alg;
390                 pAlgConfig = &pObj->config;
391                 memset(pAstCfg->xOut[z].outBufConfig.base.pVoid, 0xAA,
392                     pAlgConfig->pMemRec[0].size);
393             }
395             // The index to DEC_OUTNUMBUF_MAP will always come from the primary/master
396             // decoder. How should we handle the sourceProgram for multiple decoders?
397             // Override as needed
398             nbufs = DEC_OUTNUMBUF_MAP(pAstCfg->xDec[zMD].decodeStatus.sourceProgram);
399             if (pAstCfg->xOut[z].outBufStatus.numBufOverride[pAstCfg->xDec[zMD].decodeStatus.sourceProgram] > 0)
400             {
401                 nbufs = pAstCfg->xOut[z].outBufStatus.numBufOverride[pAstCfg->xDec[zMD].decodeStatus.sourceProgram];
402             }
403             //JXTODO: add similar thing to be figured out
404             //SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_SET_NUMBUF, nbufs);
406             //JXTODO: data transfer start to be moved to output task state machine
407             /*if (errno = SIO_issue(pAstCfg->xOut[z].hTxSio,
408                 &pAstCfg->xOut[z].outBufConfig, sizeof(pAstCfg->xOut[z].outBufConfig), 0))
409             {
410                 SIO_idle(pAstCfg->xOut[z].hTxSio);
411                 TRACE_TERSE2("PAF_ASOT_startOutput: AS%d: SIO_issue failed (0x%x)", as+zS, errno);
412                 return errno;
413             } */
415             //JXTODO: add similar thing to be figured out
416 #if 0
417             if (!(pAstCfg->xOut[z].outBufStatus.audio & 0xf0) &&
418                 (errno =  SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_UNMUTE, 0)))
419             {
420                 errno = (errno & 0xff) | ASPERR_MUTE;
421                 /* convert to sensical errno */
422                 TRACE_TERSE2("as1-f2: PAF_ASOT_startOutput: AS%d: SIO control failed (unmute) 0x%x", as+zS, errno);
423                 return errno;
424             }
425             else
426             {
427                 pAstCfg->xOut[z].outBufStatus.audio
428                     = (pAstCfg->xOut[z].outBufStatus.audio & 0xf0) | PAF_OB_AUDIO_SOUND;
429             }
430 #endif
431             TRACE_VERBOSE1("PAF_ASOT_startOutput: AS%d: output started", as+zS);
432         }
433     }
435     return ASOP_IO_SOK;
436 } /* asopStartOutput */
438 // -----------------------------------------------------------------------------
439 // ASOT Decoding Function Helper - SIO Driver Stop
440 //
441 //   Name:      PAF_ASOT_stopOutput
442 //   Purpose:   Decoding Function for terminating output.
443 //   From:      AST Parameter Function -> decodeProcessing
444 //              AST Parameter Function -> decodeComplete
445 //   Uses:      See code.
446 //   States:    x
447 //   Return:    Error number in standard or SIO form (0 on success).
448 //   Trace:     Message Log "trace" in Debug Project Configuration reports:
449 //              * SIO control errors.
450 //
451 Int asopStopOutput(
452     const PAF_ASOT_Params *pP, 
453     const PAF_ASOT_Patchs *pQ, 
454     PAF_ASOT_Config *pAsotCfg
457     PAF_AST_Config *pAstCfg;
458     PAF_AST_IoOut  *pOut;
459     Int as;                     /* Audio Stream Number (1, 2, etc.) */
460     Int z;                      /* output counter */
461     Int errno, getVal;
462     Int zS, zX;
463     PAF_SIO_IALG_Obj    *pObj;
464     PAF_SIO_IALG_Config *pAlgConfig;
466     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
467     pOut = pAsotCfg->pIoOut; // get pointer to ASOT IO configuration
468     as = pAstCfg->as;
469     (void)as;  // clear compiler warning in case not used with tracing disabled
471     errno = ASOP_IO_SOK;
472     for (z=OUTPUT1; z < OUTPUTN; z++) 
473     {
474         if (pOut[z].hIoPhy) 
475         {
476             // determine associated encoder and stream
477             zS = z;
478             (void)zS;
479             for (zX = ENCODE1; zX < ENCODEN; zX++) 
480             {
481                 if (pP->outputsFromEncodes[zX] == z) 
482                 {
483                     zS = pP->streamsFromEncodes[zX];
484                     break;
485                 }
486             }
488 #if 0 // FL, New IO: add similar thing to be figured out            
489             // Mute output before audio data termination in the usual case,
490             // where such termination is due to decode error or user command.
491             // Identification of this as the usual case is provided by the
492             // "decode processing" state machine.
493             if (!(pAstCfg->xOut[z].outBufStatus.audio & 0xf0) &&
494                 ((pAstCfg->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_SOUND) &&
495                 (getVal = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_MUTE, 0))) 
496             {
497                 if (!errno) 
498                 {
499                     errno = (getVal & 0xff) | ASPERR_MUTE;
500                     /* convert to sensical errno */
501                 }
502                 TRACE_VERBOSE1("asopStopOutput:  AS%d: SIO control failed (mute)", as+zS);
503             }
505             TRACE_TIME((&TIME_MOD, "... + %d = %d (stopOutput -- begin PAF_SIO_CONTROL_IDLE)", dtime(), TSK_time()));
506             
507             // Terminate audio data output, truncating (ignore) or flushing
508             // (play out) final samples as per (1) control register set by
509             // the user and (2) the type of audio data termination:
511 #if 0
512             // This form is not used because driver support for truncating
513             // data is not supported for internal clocks, although it is
514             // for external clocks.
515             getVal = SIO_ctrl(pC->xOut[z].hTxSio, PAF_SIO_CONTROL_IDLE,
516                 pC->xOut[z].outBufStatus.flush
517                 & (pC->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_FLUSH
518                 ? 1 : 0);
519             /* UNTESTED */
520 #else
521             // This form should be used when driver support for truncating
522             // data is supported for both internal and external clocks.
523             getVal = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_IDLE,
524                 pAstCfg->xOut[z].outBufStatus.flush ? 1 :
525                 (pAstCfg->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_FLUSH
526                 ? 1 : 0);
527             /* TESTED */
528 #endif
530             TRACE_TIME((&TIME_MOD, "... + %d = %d (stopOutput -- after PAF_SIO_CONTROL_IDLE)", dtime(), TSK_time()));
532             if (!errno)
533             {
534                 errno = getVal;
535             }
537             // Mute output after audio data termination in a special case,
538             // where such termination is due to processing of a final frame
539             // or user command. Identification of this as a special case is
540             // provided by the "decode processing" state machine.
541             if (!(pAstCfg->xOut[z].outBufStatus.audio & 0xf0) &&
542                 ((pAstCfg->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_FLUSH) &&
543                 (getVal = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_MUTE, 0)))
544             {
545                 if (!errno) 
546                 {
547                     errno = (getVal & 0xff) | ASPERR_MUTE;
548                     /* convert to sensical errno */
549                 }
550                 TRACE_VERBOSE1("as1-f2: asopStopOutput:  AS%d: SIO control failed (mute)", as+zS);
551             }
553             pAstCfg->xOut[z].outBufStatus.audio &= ~0x0f;
554 #endif // FL, New IO
556             // zero output buffers
557             pObj = (PAF_SIO_IALG_Obj *) pAstCfg->xOut[z].outChainData.head->alg;
558             pAlgConfig = &pObj->config;
559             memset (pAstCfg->xOut[z].outBufConfig.base.pVoid, 0, pAlgConfig->pMemRec[0].size);
560         } //pAstCfg->xOut[z].hTxSio
561     }//OUTPUT
563     return errno;
564 } //asopStopOutput
566 /*===========================================================================
567  * Initialize I/O components for output processing
568 ============================================================================*/
569 Int asopIoCompsInit(
570     PAF_AST_OutBuf *pOutBuf, 
571     PAF_AST_IoOut *pOutIo
574     ioBuffParams_t ioBuffParams;
575     ioPhyParams_t  ioPhyParams;
577     if (pOutIo->hMcaspChan != NULL)
578     {
579         // Initialize I/O BUFF and I/O PHY components for output task
580         ioBuffParams.base         = pOutBuf->outBufConfig.base.pVoid;
581         ioBuffParams.size         = pOutBuf->outBufConfig.allocation/STRIDE_WORST_CASE*STRIDE_WORST_CASE;
582         ioBuffParams.sync         = IOBUff_READ_SYNC;
583         ioBuffParams.nominalDelay = NUM_CYCLE_PER_OUTPUT_FRAME_DEF * pOutIo->stride * WORD_SIZE_PCM * (NUM_PRIME_XFERS+1);
584         if(ioBuffInit(pOutIo->hIoBuff, &ioBuffParams) != IOBUFF_NOERR) 
585         {
586             return ASOP_IO_ERR_IOBUFF_INIT;   // to remove magic number
587         }
589         ioPhyParams.ioBuffHandle    = pOutIo->hIoBuff;
590         ioPhyParams.xferFrameSize   = NUM_CYCLE_PER_FRAME_DEF * pOutIo->stride * WORD_SIZE_PCM;
591         ioPhyParams.mcaspChanHandle = pOutIo->hMcaspChan;
592         ioPhyParams.ioBuffOp        = IOPHY_IOBUFFOP_READ;
593         if(ioPhyInit(pOutIo->hIoPhy, &ioPhyParams) != IOPHY_NOERR) 
594         {
595             return ASOP_IO_ERR_IOPHY_INIT;   // to remove magic number
596         }
598         pOutIo->phyXferSize = ioPhyParams.xferFrameSize;
599         
600         pOutIo->ioBuffBuf2AllocCnt = 0; // initialize buffer2 alloc count (indicates Output buffer wrap)
601         pOutIo->errIoBuffOvrCnt = 0; // initialize IO buff overflow count
602         pOutIo->errIoBuffUndCnt = 0; // initialize IO buff underflow count
603     }
604     
605     return ASOP_IO_SOK;
606 } /* asopIoCompsInit */
608 /*======================================================================================
609  *  This function checks whether the I/O physical layer has been initialized
610  *====================================================================================*/
611 Bool asopIoPhyCheckInit(Void)
613     if (!d10Initialized)
614         return FALSE;
615     else 
616         return TRUE;
619 /*======================================================================================
620  *  I/O physical layer prime operation required by McASP LLD
621  *====================================================================================*/
622 Void asopIoPhyPrime(
623     PAF_AST_IoOut *pOut
626     Int32        count;
628     pOut->numPrimeXfers = NUM_PRIME_XFERS;
630     for (count = 0; count < pOut->numPrimeXfers; count++)
631     {
632         ioPhyXferSubmit(pOut->hIoPhy);
633     }
634 } /* asipIoPhyPrime */
636 // Initialize Output buffer configuration
637 Int asopInitOutBufConfig(
638     PAF_AST_OutBuf *pOutBuf, 
639     PAF_AST_IoOut *pOutIo
642     PAF_OutBufConfig *pOutBufCfg;
643     ioBuffHandle_t hIoBuff;
644     ioBuffInfo_t outBuffInfo;
645     
646     pOutBufCfg = &pOutBuf->outBufConfig;
647     hIoBuff = pOutIo->hIoBuff;
648     
649     pOutBufCfg->stride = pOutIo->stride;
650     pOutBufCfg->sizeofElement = WORD_SIZE_PCM;
651     pOutBufCfg->precision = 24;
652     
653     ioBuffGetInfo(hIoBuff, &outBuffInfo);
654     pOutBufCfg->base.pLgInt = outBuffInfo.base;
655     pOutBufCfg->sizeofBuffer = outBuffInfo.size;
656     
657     pOutBuf->pOutBuf = &(pOutBuf->outBufConfig);
658     
659     return ASOP_IO_SOK;
662 Int asopGetOutBufPtrs(
663     PAF_AST_IoOut *pOutIo,
664     size_t writeSize
667     void *buff1, *buff2;
668     size_t size1, size2;
669     Int status;
671     status = ioBuffGetWritePtrs(pOutIo->hIoBuff, writeSize,
672                                 &buff1, &size1, &buff2, &size2);
673     if (status == IOBUFF_ERR_OVERFLOW)
674     {
675         pOutIo->errIoBuffOvrCnt++;
676         //System_printf ("asopGetOutBufPtrs: output buff overflow\n"); // debug
678         // skip processing since output buffer overflows
679         return ASOP_IO_ERR_OUTBUF_OVERFLOW;
680     }
681     else if (status == IOBUFF_ERR_UNDERFLOW)
682     {
683         pOutIo->errIoBuffUndCnt++;
684         //System_printf ("asopGetOutBufPtrs: output buff underflow\n"); // debug
686         // already underflows and remain in underflow
687     }
689     // save buffer pointers & sizes for later write complete
690     pOutIo->buff1 = buff1;
691     pOutIo->size1 = size1;
692     pOutIo->buff2 = buff2;
693     pOutIo->size2 = size2;
695     return ASOP_IO_SOK;
698 #if 0
699 // Update Output buffer configuration.
700 // This is needed for proper operation of PCM encoder.
701 Int asopUpdateOutBufConfig(
702     PAF_AST_OutBuf *pOutBuf, 
703     PAF_AST_IoOut *pOutIo
706     PAF_OutBufConfig *pOutBufCfg;
707     ioBuffHandle_t hIoBuff;
708     ioBuffInfo_t outBuffInfo;
709     void *buff1, *buff2;
710     size_t size1, size2, total_write_size;
711     Int status;
713     pOutBufCfg = &pOutBuf->outBufConfig;
714     hIoBuff = pOutIo->hIoBuff;
716     // FL, New IO: original code can change these values in every DOB issue
717     //  Need to determine if this is required or not.
718     pOutBufCfg->stride = pOutIo->stride;
719     pOutBufCfg->sizeofElement = WORD_SIZE_PCM;
720     pOutBufCfg->precision = 24;
721     
722     //JXTODO: to replace hard coded write size
723     // Get write pointers of output memory pool
724     total_write_size = pOutBufCfg->lengthofFrame * pOutBufCfg->stride * pOutBufCfg->sizeofElement;
725     status = ioBuffGetWritePtrs(hIoBuff, total_write_size,
726         &buff1, &size1, &buff2, &size2);
727     if (status == IOBUFF_ERR_OVERFLOW) 
728     {
729         pOutIo->errIoBuffOvrCnt++;
730         //System_printf ("asopUpdateOutBufConfig: output buff overflow\n"); // debug
732         // skip processing since output buffer overflows        
733         return ASOP_IO_ERR_OUTBUF_OVERFLOW;
734     }
735     else if (status == IOBUFF_ERR_UNDERFLOW) 
736     {
737         pOutIo->errIoBuffUndCnt++;
738         //System_printf ("asopUpdateOutBufConfig: output buff underflow\n"); // debug
739         
740         // already underflows and remain in underflow
741     }
742 #if 0
743     // Update Output buffer pointer for Encoder
744     pOutBufCfg->pntr.pLgInt = buff1;
745     if ((buff2 != NULL) || (size2 != 0))
746     {
747         // buff2 should always be NULL for Output & size2 should always be 0 for Output.
748         // Track this here.
749         pOutIo->ioBuffBuf2AllocCnt++; // debug
750     }
751 #endif
752     // save buffer pointers & sizes for later write complete
753     pOutIo->buff1 = buff1;
754     pOutIo->size1 = size1;
755     pOutIo->buff2 = buff2;
756     pOutIo->size2 = size2;
757     
758     return ASOP_IO_SOK;
760 #endif
762 // Mark Output buffers write complete
763 Int asopMarkOutBuffsWriteComplete(
764     PAF_AST_OutBuf *pOutBuf, 
765     PAF_AST_IoOut *pOutIo
768     ioBuffHandle_t hIoBuff;
769     void *buff1, *buff2;
770     size_t size1, size2;
771     
772     // get buffer pointers & sizes from previous IO Buff write allocation
773     buff1 = pOutIo->buff1;
774     size1 = pOutIo->size1;
775     buff2 = pOutIo->buff2; // this should always be NULL for Output
776     size2 = pOutIo->size2; // this should always be 0 for Output
777     
778     hIoBuff = pOutIo->hIoBuff;
779     
780     ioBuffWriteComplete(hIoBuff, buff1, size1);
782     if (buff2 != NULL) 
783     {
784         ioBuffWriteComplete(hIoBuff, buff2, size2);
785     }
786     
787     return ASOP_IO_SOK;
790 /*======================================================================================
791  *  This function starts an I/O PHY transfer for output
792  *====================================================================================*/
793 Void asopPhyTransferStart(
794     PAF_AST_IoOut *pOut
797     if(mcaspCheckOverUnderRun(pOut->hMcaspChan)) 
798     {
799         //mcaspTxReset();
800         //mcaspTxCreate();
801         //pOut->hMcaspChan = hMcaspTxChan;
802         System_abort("\nMcASP for output underruns! %d!\n");
803     }
804     else 
805     {
806         if(ioPhyXferSubmit(pOut->hIoPhy) == IOPHY_ERR_BUFF_UNDERFLOW) 
807         {
808             // Output buffer underflows!
809             System_abort("\nOutput buffer underflows!\n");
810         }
811         else {
812             // Output buffer operates normally
813             ;
814         }
815     }
818 /* nothing past this point */