]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/performance-audio-sr.git/blob - pasdk/test_dsp/framework/audioStreamOutIo.c
Replaced hard coded OUTPUT_STRIDE with configured stride = num_serializer*num_channel.
[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 // FL, New IO: this function is currently a stub
68 // FL, New IO: need to McASP/EDMA configuration using SAP configuration from Output shortcut
69 // Select Output devices
70 Int asopSelectDevices(void *pConfig, PAF_AST_IoOut *pOut)
71 {
72     if((pOut->hIoBuff == NULL) || (pOut->hIoPhy == NULL) || (!d10Initialized)) {
73         return -1;
74     }
76     if(pOut->hMcaspChan == NULL) {
77         Audk2g_STATUS status;
78         mcaspLLDconfig * lldCfg;
79         Ptr mcaspChanHandle;
81         lldCfg = (mcaspLLDconfig *)pConfig;
82         status = mcasplldChanCreate(lldCfg, &mcaspChanHandle);
83         if(status != Audk2g_EOK) {
84             return -1;
85         }
87         pOut->hMcaspChan = mcaspChanHandle;
88         pOut->stride = lldCfg->mcaspChanParams->noOfSerRequested * lldCfg->mcaspChanParams->noOfChannels;
89     }
91     return 0;
92 }
94 // Check if Output device SIO selection changed
95 Int checkOutDevSioSelUpdate(
96     const PAF_ASOT_Params *pP, 
97     PAF_ASOT_Config *pAsotCfg,
98     Int z, 
99     Bool *pOutDevSelUpdate
102     PAF_AST_Config *pAstCfg;
103     
104     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
106     if ((z < OUTPUT1) || (z >= OUTPUTN))
107     {
108         *pOutDevSelUpdate = FALSE;
109         return -1;
110     }
111     
112     *pOutDevSelUpdate = (Bool)(pAstCfg->xOut[z].outBufStatus.sioSelect >= 0);
114     return 0;
117 // Check if any Output device SIO selection changed
118 Int checkAnyOutDevSioSelUpdate(
119     const PAF_ASOT_Params *pP, 
120     PAF_ASOT_Config *pAsotCfg,
121     Bool *pOutDevSelUpdate
124     PAF_AST_Config *pAstCfg;
125     Int outDevSelUpdate;
126     Int z;
127     
128     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
130     outDevSelUpdate = FALSE;
131     for (z=OUTPUT1; z < OUTPUTN; z++) 
132     {
133         if (pAstCfg->xOut[z].outBufStatus.sioSelect >= 0)
134         {
135             outDevSelUpdate = TRUE;
136             break;
137         }
138     }
139     
140     *pOutDevSelUpdate = outDevSelUpdate;
142     return 0;
145 // -----------------------------------------------------------------------------
146 // ASOT Decoding Function Helper - SIO Driver Change
147 //
148 //   Name:      PAF_ASOT_setCheckRateX
149 //   Purpose:   Decoding Function for reinitiating output.
150 //   From:      AST Parameter Function -> decodeInfo1
151 //              AST Parameter Function -> decodeInfo2
152 //   Uses:      See code.
153 //   States:    x
154 //   Return:    Error number in standard form (0 on success).
155 //   Trace:     None.
156 //
158 /* 0: set, 1: check, unused for now. --Kurt */
159 Int asopSetCheckRateX(
160     const PAF_ASOT_Params *pP, 
161     const PAF_ASOT_Patchs *pQ, 
162     PAF_ASOT_Config *pAsotCfg, 
163     Int check
166     PAF_AST_Config *pAstCfg;
167     PAF_AST_IoOut  *pOut;
168     float rateX;
169     PAF_SampleRateHz rateO /* std */, rateI /* inv */;
170     Int z;                              /* output counter */
171     Int zx;                             /* output re-counter */
172     Int getVal;
173     int inputRate, inputCount, outputRate, outputCount;
174     Int zMD;
175     Int zMI;
176     Int zMS;
177     Int zE, zX;
179     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
180     pOut = pAsotCfg->pIoOut; // get pointer to ASOT IO configuration
181     
182     zMD = pAstCfg->masterDec;
183     zMS = pAstCfg->masterStr;
184     zMI = pP->zone.master;
186     inputRate = pAstCfg->xInp[zMI].inpBufStatus.sampleRateStatus;
187     inputCount = pAstCfg->xDec[zMD].decodeStatus.frameLength;
188     rateI = pAstCfg->xStr[zMS].pAudioFrame->fxns->sampleRateHz(pAstCfg->xStr[zMS].pAudioFrame, 
189         inputRate, PAF_SAMPLERATEHZ_INV);
191     for (z=OUTPUT1; z < OUTPUTN; z++) 
192     {
193         if (pOut[z].hIoPhy && (pAstCfg->xOut[z].outBufStatus.clock & 0x01)) 
194         {
195             // determine associated encoder
196             zE = z;
197             for (zX = ENCODE1; zX < ENCODEN; zX++) 
198             {
199                 if (pP->outputsFromEncodes[zX] == z) 
200                 {
201                     zE = zX;
202                     break;
203                 }
204             }
206             outputRate = pAstCfg->xEnc[zE].encodeStatus.sampleRate;
207             outputCount = pAstCfg->xEnc[zE].encodeStatus.frameLength;
208             rateO = pAstCfg->xStr[zMS].pAudioFrame->fxns->sampleRateHz(pAstCfg->xStr[zMS].pAudioFrame, 
209                 outputRate, PAF_SAMPLERATEHZ_STD);
210             if ((rateI > 0) && (rateO > 0))
211             {
212                 rateX = rateO /* std */ * rateI /* inv */;
213             }
214             else if (inputCount != 0)
215             {
216                 rateX = (float)outputCount / inputCount;
217             }
218             else
219             {
220                 return ASPERR_INFO_RATERATIO;
221             }
223 #if 0 // FL, New IO: add similar thing to be figured out     
224             getVal = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_SET_RATEX, (Arg)&rateX);
225             if (getVal == DOBERR_RATECHANGE) 
226             {
227                 for (zx=OUTPUT1; zx < OUTPUTN; zx++)
228                 {
229                     if (pAstCfg->xOut[zx].hTxSio)
230                     {
231                         SIO_idle(pAstCfg->xOut[zx].hTxSio);
232                     }
233                 }
235                 // this forces an exit from the calling state machine which will
236                 // eventually call startOutput which calls setCheckRateX for all outputs
237                 // and so it is ok, in the presence of a rate change on any output, to
238                 // exit this loop /function early.
239                 return ASPERR_INFO_RATECHANGE;
240             }
241             else if (getVal != SYS_OK)
242             {
243                 return ((getVal & 0xff) | ASPERR_RATE_CHECK);
244             }
245 #endif // FL, New IO
246         }
247     }
249     return 0;
250 } //asopSetCheckRateX
252 // -----------------------------------------------------------------------------
253 // ASOT Decoding Function Helper - SIO Driver Start
254 //
255 //   Name:      PAF_ASOT_startOutput
256 //   Purpose:   Decoding Function for initiating output.
257 //   From:      AST Parameter Function -> decodeInfo1
258 //   Uses:      See code.
259 //   States:    x
260 //   Return:    Error number in standard or SIO form (0 on success).
261 //   Trace:     Message Log "trace" in Debug Project Configuration reports:
262 //              * State information as per parent.
263 //              * SIO control errors.
264 //
265 Int asopStartOutput(
266     const PAF_ASOT_Params *pP,
267     const PAF_ASOT_Patchs *pQ,
268     PAF_ASOT_Config *pAsotCfg
271     PAF_AST_Config *pAstCfg;
272     PAF_AST_IoOut  *pOut;
273     Int as;                     /* Audio Stream Number (1, 2, etc.) */
274     Int z;                      /* output counter */
275     Int nbufs;
276     Int zE, zS, zX;
277     Int zMD;
278     PAF_SIO_IALG_Obj    *pObj;
279     PAF_SIO_IALG_Config *pAlgConfig;
280     ioPhyCtl_t ioPhyCtl;
283     pAstCfg = pAsotCfg->pAstCfg; // get pointer to common (shared) configuration
284     pOut = pAsotCfg->pIoOut; // get pointer to ASOT IO configuration
285     as = pAstCfg->as;
286     zMD = pAstCfg->masterDec;
288     for (z=OUTPUT1; z < OUTPUTN; z++)
289     {
290         if (pOut[z].hIoPhy)
291         {
292             // determine associated encoder and stream
293             zE = z;
294             zS = z;
295             for (zX = ENCODE1; zX < ENCODEN; zX++)
296             {
297                 if (pP->outputsFromEncodes[zX] == z)
298                 {
299                     zE = zX;
300                     zS = pP->streamsFromEncodes[zE];
301                     break;
302                 }
303             }
305             // FL, New IO: add similar thing to be figured out
306 // Need to Revisit: Starting Clocks here seems logical & also manages the McASP without spurious underruns .
307 #if 0
308             // if device selected and valid then enable stat tracking if
309                         // required and start clocking
310                         if ((pAstCfg->xOut[z].outBufStatus.sioSelect < 0) && (pAstCfg->xOut[z].hTxSio))
311                         {
312                                 TRACE_VERBOSE0("PAF_ASOT_startOutput: start SIO clocks");
313                                 errme = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_OUTPUT_START_CLOCKS, 0);
314                                 if (errno)
315                                 {
316                                         TRACE_VERBOSE2("PAF_ASOT_startOutput: errme 0x%x, errno 0x%x", errme, errno);
317                                         SIO_idle(pAstCfg->xOut[z].hTxSio);
318                                         if (!errno)
319                                         {
320                                                 errno = ASPERR_DEVOUT + errme;
321                                         }
322                                 }
323                         }
324 #endif            
326             // Set sample count so that DOB knows how much data to send
327             pAstCfg->xOut[z].outBufConfig.lengthofFrame =
328                 pAstCfg->xEnc[zE].encodeInStruct.pAudioFrame->sampleCount;
330 #if 1 // FL, New IO: add similar thing to be figured out
331             // Update framework Phy transfer size
332             pOut[z].phyXferSize = pAstCfg->xOut[z].outBufConfig.lengthofFrame * pOut[z].stride * WORD_SIZE_PCM;
333             // Update IO Phy transfer size            
334             ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
335             ioPhyCtl.params.xferFrameSize = pOut[z].phyXferSize;
336             ioPhyControl(pOut[z].hIoPhy, &ioPhyCtl);
337             // Update IO Buff delay to match Phy transfer size
338             ioBuffAdjustDelay(pOut[z].hIoBuff, pOut[z].phyXferSize * (NUM_PRIME_XFERS+1));
339 #endif            
341             if (pAstCfg->xOut[z].outBufStatus.markerMode == PAF_OB_MARKER_ENABLED)
342             {
343                 pObj = (PAF_SIO_IALG_Obj *) pAstCfg->xOut[z].outChainData.head->alg;
344                 pAlgConfig = &pObj->config;
345                 memset(pAstCfg->xOut[z].outBufConfig.base.pVoid, 0xAA,
346                     pAlgConfig->pMemRec[0].size);
347             }
349             // The index to DEC_OUTNUMBUF_MAP will always come from the primary/master
350             // decoder. How should we handle the sourceProgram for multiple decoders?
351             // Override as needed
352             nbufs = DEC_OUTNUMBUF_MAP(pAstCfg->xDec[zMD].decodeStatus.sourceProgram);
353             if (pAstCfg->xOut[z].outBufStatus.numBufOverride[pAstCfg->xDec[zMD].decodeStatus.sourceProgram] > 0)
354             {
355                 nbufs = pAstCfg->xOut[z].outBufStatus.numBufOverride[pAstCfg->xDec[zMD].decodeStatus.sourceProgram];
356             }
357             //JXTODO: add similar thing to be figured out
358             //SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_SET_NUMBUF, nbufs);
360             //JXTODO: data transfer start to be moved to output task state machine
361             /*if (errno = SIO_issue(pAstCfg->xOut[z].hTxSio,
362                 &pAstCfg->xOut[z].outBufConfig, sizeof(pAstCfg->xOut[z].outBufConfig), 0))
363             {
364                 SIO_idle(pAstCfg->xOut[z].hTxSio);
365                 TRACE_TERSE2("PAF_ASOT_startOutput: AS%d: SIO_issue failed (0x%x)", as+zS, errno);
366                 return errno;
367             } */
369             //JXTODO: add similar thing to be figured out
370 #if 0
371             if (!(pAstCfg->xOut[z].outBufStatus.audio & 0xf0) &&
372                 (errno =  SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_UNMUTE, 0)))
373             {
374                 errno = (errno & 0xff) | ASPERR_MUTE;
375                 /* convert to sensical errno */
376                 TRACE_TERSE2("as1-f2: PAF_ASOT_startOutput: AS%d: SIO control failed (unmute) 0x%x", as+zS, errno);
377                 return errno;
378             }
379             else
380             {
381                 pAstCfg->xOut[z].outBufStatus.audio
382                     = (pAstCfg->xOut[z].outBufStatus.audio & 0xf0) | PAF_OB_AUDIO_SOUND;
383             }
384 #endif
385             TRACE_VERBOSE1("PAF_ASOT_startOutput: AS%d: output started", as+zS);
386         }
387     }
389     return 0;
390 } /* asopStartOutput */
392 // -----------------------------------------------------------------------------
393 // ASOT Decoding Function Helper - SIO Driver Stop
394 //
395 //   Name:      PAF_ASOT_stopOutput
396 //   Purpose:   Decoding Function for terminating output.
397 //   From:      AST Parameter Function -> decodeProcessing
398 //              AST Parameter Function -> decodeComplete
399 //   Uses:      See code.
400 //   States:    x
401 //   Return:    Error number in standard or SIO form (0 on success).
402 //   Trace:     Message Log "trace" in Debug Project Configuration reports:
403 //              * SIO control errors.
404 //
405 Int asopStopOutput(
406     const PAF_ASOT_Params *pP, 
407     const PAF_ASOT_Patchs *pQ, 
408     PAF_ASOT_Config *pAsotCfg
411     PAF_AST_Config *pAstCfg;
412     PAF_AST_IoOut  *pOut;
413     Int as;                     /* Audio Stream Number (1, 2, etc.) */
414     Int z;                      /* output counter */
415     Int errno = 0, getVal;
416     Int zS, zX;
417     PAF_SIO_IALG_Obj    *pObj;
418     PAF_SIO_IALG_Config *pAlgConfig;
420     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
421     pOut = pAsotCfg->pIoOut; // get pointer to ASOT IO configuration
422     as = pAstCfg->as;
423     (void)as;  // clear compiler warning in case not used with tracing disabled
425     for (z=OUTPUT1; z < OUTPUTN; z++) 
426     {
427         if (pOut[z].hIoPhy) 
428         {
429             // determine associated encoder and stream
430             zS = z;
431             (void)zS;
432             for (zX = ENCODE1; zX < ENCODEN; zX++) 
433             {
434                 if (pP->outputsFromEncodes[zX] == z) 
435                 {
436                     zS = pP->streamsFromEncodes[zX];
437                     break;
438                 }
439             }
441 #if 0 // FL, New IO: add similar thing to be figured out            
442             // Mute output before audio data termination in the usual case,
443             // where such termination is due to decode error or user command.
444             // Identification of this as the usual case is provided by the
445             // "decode processing" state machine.
446             if (!(pAstCfg->xOut[z].outBufStatus.audio & 0xf0) &&
447                 ((pAstCfg->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_SOUND) &&
448                 (getVal = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_MUTE, 0))) 
449             {
450                 if (!errno) 
451                 {
452                     errno = (getVal & 0xff) | ASPERR_MUTE;
453                     /* convert to sensical errno */
454                 }
455                 TRACE_VERBOSE1("asopStopOutput:  AS%d: SIO control failed (mute)", as+zS);
456             }
458             TRACE_TIME((&TIME_MOD, "... + %d = %d (stopOutput -- begin PAF_SIO_CONTROL_IDLE)", dtime(), TSK_time()));
459             
460             // Terminate audio data output, truncating (ignore) or flushing
461             // (play out) final samples as per (1) control register set by
462             // the user and (2) the type of audio data termination:
464 #if 0
465             // This form is not used because driver support for truncating
466             // data is not supported for internal clocks, although it is
467             // for external clocks.
468             getVal = SIO_ctrl(pC->xOut[z].hTxSio, PAF_SIO_CONTROL_IDLE,
469                 pC->xOut[z].outBufStatus.flush
470                 & (pC->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_FLUSH
471                 ? 1 : 0);
472             /* UNTESTED */
473 #else
474             // This form should be used when driver support for truncating
475             // data is supported for both internal and external clocks.
476             getVal = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_IDLE,
477                 pAstCfg->xOut[z].outBufStatus.flush ? 1 :
478                 (pAstCfg->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_FLUSH
479                 ? 1 : 0);
480             /* TESTED */
481 #endif
483             TRACE_TIME((&TIME_MOD, "... + %d = %d (stopOutput -- after PAF_SIO_CONTROL_IDLE)", dtime(), TSK_time()));
485             if (!errno)
486             {
487                 errno = getVal;
488             }
490             // Mute output after audio data termination in a special case,
491             // where such termination is due to processing of a final frame
492             // or user command. Identification of this as a special case is
493             // provided by the "decode processing" state machine.
494             if (!(pAstCfg->xOut[z].outBufStatus.audio & 0xf0) &&
495                 ((pAstCfg->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_FLUSH) &&
496                 (getVal = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_MUTE, 0)))
497             {
498                 if (!errno) 
499                 {
500                     errno = (getVal & 0xff) | ASPERR_MUTE;
501                     /* convert to sensical errno */
502                 }
503                 TRACE_VERBOSE1("as1-f2: asopStopOutput:  AS%d: SIO control failed (mute)", as+zS);
504             }
506             pAstCfg->xOut[z].outBufStatus.audio &= ~0x0f;
507 #endif // FL, New IO
509             // zero output buffers
510             pObj = (PAF_SIO_IALG_Obj *) pAstCfg->xOut[z].outChainData.head->alg;
511             pAlgConfig = &pObj->config;
512             memset (pAstCfg->xOut[z].outBufConfig.base.pVoid, 0, pAlgConfig->pMemRec[0].size);
513         } //pAstCfg->xOut[z].hTxSio
514     }//OUTPUT
516     return errno;
517 } //asopStopOutput
519 /*===========================================================================
520  * Initialize I/O components for output processing
521 ============================================================================*/
522 Int asopIoCompsInit(
523     PAF_AST_OutBuf *pOutBuf, 
524     PAF_AST_IoOut *pOutIo
527     // Initialize I/O BUFF and I/O PHY components for output task
528     ioBuffParams_t ioBuffParams;
529     ioPhyParams_t  ioPhyParams;
531     ioBuffParams.base         = pOutBuf->outBufConfig.base.pVoid;
532     ioBuffParams.size         = pOutBuf->outBufConfig.allocation/STRIDE_WORST_CASE*STRIDE_WORST_CASE;
533     ioBuffParams.sync         = IOBUff_READ_SYNC;
534     ioBuffParams.nominalDelay = NUM_CYCLE_PER_FRAME_DEF * pOutIo->stride * WORD_SIZE_PCM * (NUM_PRIME_XFERS+1);
535     if(ioBuffInit(pOutIo->hIoBuff, &ioBuffParams) != IOBUFF_NOERR) 
536     {
537         return -1;   // to remove magic number
538     }
540     ioPhyParams.ioBuffHandle    = pOutIo->hIoBuff;
541     ioPhyParams.xferFrameSize   = NUM_CYCLE_PER_FRAME_DEF * pOutIo->stride * WORD_SIZE_PCM;
542     ioPhyParams.mcaspChanHandle = pOutIo->hMcaspChan;
543     ioPhyParams.ioBuffOp        = IOPHY_IOBUFFOP_READ;
544     if(ioPhyInit(pOutIo->hIoPhy, &ioPhyParams) != IOPHY_NOERR) 
545     {
546         return -1;   // to remove magic number
547     }
549     pOutIo->phyXferSize = ioPhyParams.xferFrameSize;
550     
551     pOutIo->ioBuffBuf2AllocCnt = 0; // initialize buffer2 alloc count (indicates Output buffer wrap)
552     pOutIo->errIoBuffOvrCnt = 0; // initialize IO buff overflow count
553     pOutIo->errIoBuffUndCnt = 0; // initialize IO buff underflow count
555     return 0;
556 } /* asopIoCompsInit */
558 /*======================================================================================
559  *  This function checks whether the I/O physical layer has been initialized
560  *====================================================================================*/
561 Bool asopIoPhyCheckInit(Void)
563     if (!d10Initialized)
564         return FALSE;
565     else 
566         return TRUE;
569 /*======================================================================================
570  *  I/O physical layer prime operation required by McASP LLD
571  *====================================================================================*/
572 Void asopIoPhyPrime(
573     PAF_AST_IoOut *pOut
576     Int32        count;
578     pOut->numPrimeXfers = NUM_PRIME_XFERS;
580     for (count = 0; count < pOut->numPrimeXfers; count++)
581     {
582         ioPhyXferSubmit(pOut->hIoPhy);
583     }
584 } /* asipIoPhyPrime */
586 // Initialize Output buffer configuration
587 Int asopInitOutBufConfig(
588     PAF_AST_OutBuf *pOutBuf, 
589     PAF_AST_IoOut *pOutIo
592     PAF_OutBufConfig *pOutBufCfg;
593     ioBuffHandle_t hIoBuff;
594     ioBuffInfo_t outBuffInfo;
595     
596     pOutBufCfg = &pOutBuf->outBufConfig;
597     hIoBuff = pOutIo->hIoBuff;
598     
599     pOutBufCfg->stride = pOutIo->stride;
600     pOutBufCfg->sizeofElement = WORD_SIZE_PCM;
601     pOutBufCfg->precision = 24;
602     
603     ioBuffGetInfo(hIoBuff, &outBuffInfo);
604         pOutBufCfg->base.pLgInt = outBuffInfo.base;
605         pOutBufCfg->sizeofBuffer = outBuffInfo.size;
606     
607         pOutBuf->pOutBuf = &(pOutBuf->outBufConfig);
608     
609     return 0;
612 // Update Output buffer configuration.
613 // This is needed for proper operation of PCM encoder.
614 Int asopUpdateOutBufConfig(
615     PAF_AST_OutBuf *pOutBuf, 
616     PAF_AST_IoOut *pOutIo
619     PAF_OutBufConfig *pOutBufCfg;
620     ioBuffHandle_t hIoBuff;
621     ioBuffInfo_t outBuffInfo;
622     void *buff1, *buff2;
623     size_t size1, size2, total_write_size;
624     Int status;
626     pOutBufCfg = &pOutBuf->outBufConfig;
627     hIoBuff = pOutIo->hIoBuff;
629     // FL, New IO: original code can change these values in every DOB issue
630     //  Need to determine if this is required or not.
631     pOutBufCfg->stride = pOutIo->stride;
632     pOutBufCfg->sizeofElement = WORD_SIZE_PCM;
633     pOutBufCfg->precision = 24;
634     
635     //JXTODO: to replace hard coded write size
636     // Get write pointers of output memory pool
637         total_write_size = pOutBufCfg->lengthofFrame * pOutBufCfg->stride * pOutBufCfg->sizeofElement;
638     status = ioBuffGetWritePtrs(hIoBuff, total_write_size,
639         &buff1, &size1, &buff2, &size2);
640     if (status == IOBUFF_ERR_OVERFLOW) 
641     {
642         pOutIo->errIoBuffOvrCnt++;
643         //System_printf ("asopUpdateOutBufConfig: output buff overflow\n"); // debug
645         // skip processing since output buffer overflows        
646         return -1;
647     }
648     else if (status == IOBUFF_ERR_UNDERFLOW) 
649     {
650         pOutIo->errIoBuffUndCnt++;
651         //System_printf ("asopUpdateOutBufConfig: output buff underflow\n"); // debug
652         
653         // already underflows and remain in underflow
654     }
656     // Update Output buffer pointer for Encoder
657         pOutBufCfg->pntr.pLgInt = buff1;
658     if ((buff2 != NULL) || (size2 != 0))
659     {
660         // buff2 should always be NULL for Output & size2 should always be 0 for Output.
661         // Track this here.
662         pOutIo->ioBuffBuf2AllocCnt++; // debug
663     }
664     
665     // save buffer pointers & sizes for later write complete
666     pOutIo->buff1 = buff1;
667     pOutIo->size1 = size1;
668     pOutIo->buff2 = buff2;
669     pOutIo->size2 = size2;
670     
671     return 0;
674 // Mark Output buffers write complete
675 Int asopMarkOutBuffsWriteComplete(
676     PAF_AST_OutBuf *pOutBuf, 
677     PAF_AST_IoOut *pOutIo
680     ioBuffHandle_t hIoBuff;
681     void *buff1, *buff2;
682     size_t size1, size2;
683     
684     // get buffer pointers & sizes from previous IO Buff write allocation
685     buff1 = pOutIo->buff1;
686     size1 = pOutIo->size1;
687     buff2 = pOutIo->buff2; // this should always be NULL for Output
688     size2 = pOutIo->size2; // this should always be 0 for Output
689     
690     hIoBuff = pOutIo->hIoBuff;
691     
692     ioBuffWriteComplete(hIoBuff, buff1, size1);
694     if (buff2 != NULL) 
695     {
696         ioBuffWriteComplete(hIoBuff, buff2, size2);
697     }
698     
699     return 0;
702 /*======================================================================================
703  *  This function starts an I/O PHY transfer for output
704  *====================================================================================*/
705 Void asopPhyTransferStart(
706     PAF_AST_IoOut *pOut
709     if(mcaspCheckOverUnderRun(pOut->hMcaspChan)) 
710     {
711         //mcaspTxReset();
712         //mcaspTxCreate();
713         //pOut->hMcaspChan = hMcaspTxChan;
714         System_abort("\nMcASP for output underruns! %d!\n");
715     }
716     else 
717     {
718         if(ioPhyXferSubmit(pOut->hIoPhy) == IOPHY_ERR_BUFF_UNDERFLOW) 
719         {
720             // Output buffer underflows!
721             System_abort("\nOutput buffer underflows!\n");
722         }
723         else {
724             // Output buffer operates normally
725             ;
726         }
727     }
730 /* nothing past this point */