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