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