]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/performance-audio-sr.git/blob - pasdk/test_dsp/framework/audioStreamOutIo.c
fbc05c0d78720a5b21f68ec10578d708b3c3b1ab
[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;
76     UInt postedEvents;    
78     if ((pOut->hIoBuff == NULL) || (pOut->hIoPhy == NULL) || (!d10Initialized)) 
79     {
80         return ASOP_IO_ERR_IO_UNINIT;
81     }
83     // Deactivate currently active Output device
84     if (pOut->hMcaspChan != NULL)
85     {
86         // check McASP LLD control API
87         mcaspControlChan(pOut->hMcaspChan, MCASP_CHAN_RESET, NULL);
88         // Delete McASP LLD channel
89         status = mcaspDeleteChan(pOut->hMcaspChan);
90         if (status != Aud_EOK)
91         {
92             Log_info0("asopSelectDevices(): McASP channel deletion failed!\n");
93             return ASOP_IO_ERR_MCASP_CFG;
94         }
95         
96         // Clear (drop) already posted Output data events
97         postedEvents = Event_getPostedEvents(gAsotEvtHandle);
98         while ((postedEvents & Evt_Id_AsotTxMcaspEdma) != 0)
99         {
100             Event_pend(gAsotEvtHandle, Event_Id_NONE, Evt_Id_AsotTxMcaspEdma, 0);
101             postedEvents = Event_getPostedEvents(gAsotEvtHandle);
102         }        
103         
104         pOut->hMcaspChan = NULL;            // reset active McASP LLD handle
105         pOut->pLldCfg->hMcaspChan = NULL;   // reset McASP LLD handle for active McASP LLD configuration
106         pOut->pLldCfg = NULL;               // reset pointer to active McASP LLD configuration
107     }
109     // Activate requested device
110     if (pOutCfg != NULL)
111     {
112         //
113         // Device other than OutNone selected
114         //
115         
116         pReqLldCfg = (mcaspLLDconfig *)pOutCfg->sio.pConfig;
117         if (pReqLldCfg->hMcaspChan == NULL) 
118         {
119             // Create McASP LLD channel
120             mcaspChanHandle = NULL;
121             status = mcasplldChanCreate(pReqLldCfg, &mcaspChanHandle);
122             if (status != Aud_EOK) {
123                 Log_info0("asopSelectDevices(): McASP channel creation failed!\n");
124                 return ASOP_IO_ERR_MCASP_CFG;
125             }
127             pReqLldCfg->hMcaspChan = mcaspChanHandle;   // set McASP LLD handle for requested McASP LLD configuration
128             pOut->pLldCfg = pReqLldCfg;                 // set pointer to active McASP LLD configuration
129             pOut->hMcaspChan = pReqLldCfg->hMcaspChan;  // set active McASP LLD handle
130             
131             // configure stride according to selected McASP LLD configuration
132             pOut->stride = pReqLldCfg->mcaspChanParams->noOfSerRequested * 
133                 pReqLldCfg->mcaspChanParams->noOfChannels;
134         }
135         else
136         {
137             return ASOP_IO_ERR_INV_STATE;
138         }
139     }
140     else
141     {
142         //
143         // OutNone device selected
144         //
145         
146         pOut->hMcaspChan = NULL;    // reset active McASP LLD handle
147         pOut->pLldCfg = NULL;       // reset pointer to active McASP LLD configuration
148     }
150     return ASOP_IO_SOK;
153 // Check if Output device SIO selection changed
154 Int checkOutDevSioSelUpdate(
155     const PAF_ASOT_Params *pP, 
156     PAF_ASOT_Config *pAsotCfg,
157     Int z, 
158     Bool *pOutDevSelUpdate
161     PAF_AST_Config *pAstCfg;
162     
163     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
165     if ((z < OUTPUT1) || (z >= OUTPUTN))
166     {
167         *pOutDevSelUpdate = FALSE;
168         return ASOP_IO_ERR_INV_PARAMS;
169     }
170     
171     *pOutDevSelUpdate = (Bool)(pAstCfg->xOut[z].outBufStatus.sioSelect >= 0);
173     return ASOP_IO_SOK;
176 // Check if any Output device SIO selection changed
177 Int checkAnyOutDevSioSelUpdate(
178     const PAF_ASOT_Params *pP, 
179     PAF_ASOT_Config *pAsotCfg,
180     Bool *pOutDevSelUpdate
183     PAF_AST_Config *pAstCfg;
184     Int outDevSelUpdate;
185     Int z;
186     
187     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
189     outDevSelUpdate = FALSE;
190     for (z=OUTPUT1; z < OUTPUTN; z++) 
191     {
192         if (pAstCfg->xOut[z].outBufStatus.sioSelect >= 0)
193         {
194             outDevSelUpdate = TRUE;
195             break;
196         }
197     }
198     
199     *pOutDevSelUpdate = outDevSelUpdate;
201     return ASOP_IO_SOK;
204 // -----------------------------------------------------------------------------
205 // ASOT Decoding Function Helper - SIO Driver Change
206 //
207 //   Name:      PAF_ASOT_setCheckRateX
208 //   Purpose:   Decoding Function for reinitiating output.
209 //   From:      AST Parameter Function -> decodeInfo1
210 //              AST Parameter Function -> decodeInfo2
211 //   Uses:      See code.
212 //   States:    x
213 //   Return:    Error number in standard form (0 on success).
214 //   Trace:     None.
215 //
217 /* 0: set, 1: check, unused for now. --Kurt */
218 Int asopSetCheckRateX(
219     const PAF_ASOT_Params *pP, 
220     const PAF_ASOT_Patchs *pQ, 
221     PAF_ASOT_Config *pAsotCfg, 
222     Int check
225     PAF_AST_Config *pAstCfg;
226     PAF_AST_IoOut  *pOut;
227     float rateX;
228     PAF_SampleRateHz rateO /* std */, rateI /* inv */;
229     Int z;                              /* output counter */
230     Int zx;                             /* output re-counter */
231     Int getVal;
232     int inputRate, inputCount, outputRate, outputCount;
233     Int zMD;
234     Int zMI;
235     Int zMS;
236     Int zE, zX;
238     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
239     pOut = pAsotCfg->pIoOut; // get pointer to ASOT IO configuration
240     
241     zMD = pAstCfg->masterDec;
242     zMS = pAstCfg->masterStr;
243     zMI = pP->zone.master;
245     inputRate = pAstCfg->xInp[zMI].inpBufStatus.sampleRateStatus;
246     inputCount = pAstCfg->xDec[zMD].decodeStatus.frameLength;
247     rateI = pAstCfg->xStr[zMS].pAudioFrame->fxns->sampleRateHz(pAstCfg->xStr[zMS].pAudioFrame, 
248         inputRate, PAF_SAMPLERATEHZ_INV);
250     for (z=OUTPUT1; z < OUTPUTN; z++) 
251     {
252         if (pOut[z].hIoPhy && (pAstCfg->xOut[z].outBufStatus.clock & 0x01)) 
253         {
254             // determine associated encoder
255             zE = z;
256             for (zX = ENCODE1; zX < ENCODEN; zX++) 
257             {
258                 if (pP->outputsFromEncodes[zX] == z) 
259                 {
260                     zE = zX;
261                     break;
262                 }
263             }
265             outputRate = pAstCfg->xEnc[zE].encodeStatus.sampleRate;
266             outputCount = pAstCfg->xEnc[zE].encodeStatus.frameLength;
267             rateO = pAstCfg->xStr[zMS].pAudioFrame->fxns->sampleRateHz(pAstCfg->xStr[zMS].pAudioFrame, 
268                 outputRate, PAF_SAMPLERATEHZ_STD);
269             if ((rateI > 0) && (rateO > 0))
270             {
271                 rateX = rateO /* std */ * rateI /* inv */;
272             }
273             else if (inputCount != 0)
274             {
275                 rateX = (float)outputCount / inputCount;
276             }
277             else
278             {
279                 return ASPERR_INFO_RATERATIO;
280             }
282 #if 0 // FL, New IO: add similar thing to be figured out     
283             getVal = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_SET_RATEX, (Arg)&rateX);
284             if (getVal == DOBERR_RATECHANGE) 
285             {
286                 for (zx=OUTPUT1; zx < OUTPUTN; zx++)
287                 {
288                     if (pAstCfg->xOut[zx].hTxSio)
289                     {
290                         SIO_idle(pAstCfg->xOut[zx].hTxSio);
291                     }
292                 }
294                 // this forces an exit from the calling state machine which will
295                 // eventually call startOutput which calls setCheckRateX for all outputs
296                 // and so it is ok, in the presence of a rate change on any output, to
297                 // exit this loop /function early.
298                 return ASPERR_INFO_RATECHANGE;
299             }
300             else if (getVal != SYS_OK)
301             {
302                 return ((getVal & 0xff) | ASPERR_RATE_CHECK);
303             }
304 #endif // FL, New IO
305             // FL: ugly little experiment
306             //*(volatile UInt32 *)0x23400B0 |= 7; // set CLKXDIV to 7
307         }
308     }
310     return ASOP_IO_SOK;
311 } //asopSetCheckRateX
313 // -----------------------------------------------------------------------------
314 // ASOT Decoding Function Helper - SIO Driver Start
315 //
316 //   Name:      PAF_ASOT_startOutput
317 //   Purpose:   Decoding Function for initiating output.
318 //   From:      AST Parameter Function -> decodeInfo1
319 //   Uses:      See code.
320 //   States:    x
321 //   Return:    Error number in standard or SIO form (0 on success).
322 //   Trace:     Message Log "trace" in Debug Project Configuration reports:
323 //              * State information as per parent.
324 //              * SIO control errors.
325 //
326 Int asopStartOutput(
327     const PAF_ASOT_Params *pP,
328     const PAF_ASOT_Patchs *pQ,
329     PAF_ASOT_Config *pAsotCfg
332     PAF_AST_Config *pAstCfg;
333     PAF_AST_IoOut  *pOut;
334     Int as;                     /* Audio Stream Number (1, 2, etc.) */
335     Int z;                      /* output counter */
336     Int nbufs;
337     Int zE, zS, zX;
338     Int zMD;
339     PAF_SIO_IALG_Obj    *pObj;
340     PAF_SIO_IALG_Config *pAlgConfig;
341     ioPhyCtl_t ioPhyCtl;
344     pAstCfg = pAsotCfg->pAstCfg; // get pointer to common (shared) configuration
345     pOut = pAsotCfg->pIoOut; // get pointer to ASOT IO configuration
346     as = pAstCfg->as;
347     zMD = pAstCfg->masterDec;
349     for (z=OUTPUT1; z < OUTPUTN; z++)
350     {
351         if (pOut[z].hIoPhy)
352         {
353             // determine associated encoder and stream
354             zE = z;
355             zS = z;
356             for (zX = ENCODE1; zX < ENCODEN; zX++)
357             {
358                 if (pP->outputsFromEncodes[zX] == z)
359                 {
360                     zE = zX;
361                     zS = pP->streamsFromEncodes[zE];
362                     break;
363                 }
364             }
366             // FL, New IO: add similar thing to be figured out
367 // Need to Revisit: Starting Clocks here seems logical & also manages the McASP without spurious underruns .
368 #if 0
369             // if device selected and valid then enable stat tracking if
370             // required and start clocking
371             if ((pAstCfg->xOut[z].outBufStatus.sioSelect < 0) && (pAstCfg->xOut[z].hTxSio))
372             {
373                 TRACE_VERBOSE0("PAF_ASOT_startOutput: start SIO clocks");
374                 errme = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_OUTPUT_START_CLOCKS, 0);
375                 if (errno)
376                 {
377                     TRACE_VERBOSE2("PAF_ASOT_startOutput: errme 0x%x, errno 0x%x", errme, errno);
378                     SIO_idle(pAstCfg->xOut[z].hTxSio);
379                     if (!errno)
380                     {
381                         errno = ASPERR_DEVOUT + errme;
382                     }
383                 }
384             }
385 #endif            
387             // Set sample count so that DOB knows how much data to send
388             pAstCfg->xOut[z].outBufConfig.lengthofFrame =
389                 pAstCfg->xEnc[zE].encodeInStruct.pAudioFrame->sampleCount;
391 #if 1 // FL, New IO: add similar thing to be figured out
392             // Update framework Phy transfer size
393             pOut[z].phyXferSize = pAstCfg->xOut[z].outBufConfig.lengthofFrame * pOut[z].stride * WORD_SIZE_PCM;
394             // Update IO Phy transfer size
395             ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
396             ioPhyCtl.params.xferFrameSize = pOut[z].phyXferSize;
397             ioPhyControl(pOut[z].hIoPhy, &ioPhyCtl);
398             // Update IO Buff delay to match Phy transfer size
399             ioBuffAdjustDelay(pOut[z].hIoBuff, pOut[z].phyXferSize * (NUM_PRIME_XFERS+1));
400 #endif
402             if (pAstCfg->xOut[z].outBufStatus.markerMode == PAF_OB_MARKER_ENABLED)
403             {
404                 pObj = (PAF_SIO_IALG_Obj *) pAstCfg->xOut[z].outChainData.head->alg;
405                 pAlgConfig = &pObj->config;
406                 memset(pAstCfg->xOut[z].outBufConfig.base.pVoid, 0xAA,
407                     pAlgConfig->pMemRec[0].size);
408             }
410             // The index to DEC_OUTNUMBUF_MAP will always come from the primary/master
411             // decoder. How should we handle the sourceProgram for multiple decoders?
412             // Override as needed
413             nbufs = DEC_OUTNUMBUF_MAP(pAstCfg->xDec[zMD].decodeStatus.sourceProgram);
414             if (pAstCfg->xOut[z].outBufStatus.numBufOverride[pAstCfg->xDec[zMD].decodeStatus.sourceProgram] > 0)
415             {
416                 nbufs = pAstCfg->xOut[z].outBufStatus.numBufOverride[pAstCfg->xDec[zMD].decodeStatus.sourceProgram];
417             }
418             //JXTODO: add similar thing to be figured out
419             //SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_SET_NUMBUF, nbufs);
421             //JXTODO: data transfer start to be moved to output task state machine
422             /*if (errno = SIO_issue(pAstCfg->xOut[z].hTxSio,
423                 &pAstCfg->xOut[z].outBufConfig, sizeof(pAstCfg->xOut[z].outBufConfig), 0))
424             {
425                 SIO_idle(pAstCfg->xOut[z].hTxSio);
426                 TRACE_TERSE2("PAF_ASOT_startOutput: AS%d: SIO_issue failed (0x%x)", as+zS, errno);
427                 return errno;
428             } */
430             //JXTODO: add similar thing to be figured out
431 #if 0
432             if (!(pAstCfg->xOut[z].outBufStatus.audio & 0xf0) &&
433                 (errno =  SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_UNMUTE, 0)))
434             {
435                 errno = (errno & 0xff) | ASPERR_MUTE;
436                 /* convert to sensical errno */
437                 TRACE_TERSE2("as1-f2: PAF_ASOT_startOutput: AS%d: SIO control failed (unmute) 0x%x", as+zS, errno);
438                 return errno;
439             }
440             else
441             {
442                 pAstCfg->xOut[z].outBufStatus.audio
443                     = (pAstCfg->xOut[z].outBufStatus.audio & 0xf0) | PAF_OB_AUDIO_SOUND;
444             }
445 #endif
446             TRACE_VERBOSE1("PAF_ASOT_startOutput: AS%d: output started", as+zS);
447         }
448     }
450     return ASOP_IO_SOK;
451 } /* asopStartOutput */
453 // -----------------------------------------------------------------------------
454 // ASOT Decoding Function Helper - SIO Driver Stop
455 //
456 //   Name:      PAF_ASOT_stopOutput
457 //   Purpose:   Decoding Function for terminating output.
458 //   From:      AST Parameter Function -> decodeProcessing
459 //              AST Parameter Function -> decodeComplete
460 //   Uses:      See code.
461 //   States:    x
462 //   Return:    Error number in standard or SIO form (0 on success).
463 //   Trace:     Message Log "trace" in Debug Project Configuration reports:
464 //              * SIO control errors.
465 //
466 Int asopStopOutput(
467     const PAF_ASOT_Params *pP, 
468     const PAF_ASOT_Patchs *pQ, 
469     PAF_ASOT_Config *pAsotCfg
472     PAF_AST_Config *pAstCfg;
473     PAF_AST_IoOut  *pOut;
474     Int as;                     /* Audio Stream Number (1, 2, etc.) */
475     Int z;                      /* output counter */
476     Int errno, getVal;
477     Int zS, zX;
478     PAF_SIO_IALG_Obj    *pObj;
479     PAF_SIO_IALG_Config *pAlgConfig;
481     pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
482     pOut = pAsotCfg->pIoOut; // get pointer to ASOT IO configuration
483     as = pAstCfg->as;
484     (void)as;  // clear compiler warning in case not used with tracing disabled
486     errno = ASOP_IO_SOK;
487     for (z=OUTPUT1; z < OUTPUTN; z++) 
488     {
489         if (pOut[z].hIoPhy) 
490         {
491             // determine associated encoder and stream
492             zS = z;
493             (void)zS;
494             for (zX = ENCODE1; zX < ENCODEN; zX++) 
495             {
496                 if (pP->outputsFromEncodes[zX] == z) 
497                 {
498                     zS = pP->streamsFromEncodes[zX];
499                     break;
500                 }
501             }
503 #if 0 // FL, New IO: add similar thing to be figured out            
504             // Mute output before audio data termination in the usual case,
505             // where such termination is due to decode error or user command.
506             // Identification of this as the usual case is provided by the
507             // "decode processing" state machine.
508             if (!(pAstCfg->xOut[z].outBufStatus.audio & 0xf0) &&
509                 ((pAstCfg->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_SOUND) &&
510                 (getVal = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_MUTE, 0))) 
511             {
512                 if (!errno) 
513                 {
514                     errno = (getVal & 0xff) | ASPERR_MUTE;
515                     /* convert to sensical errno */
516                 }
517                 TRACE_VERBOSE1("asopStopOutput:  AS%d: SIO control failed (mute)", as+zS);
518             }
520             TRACE_TIME((&TIME_MOD, "... + %d = %d (stopOutput -- begin PAF_SIO_CONTROL_IDLE)", dtime(), TSK_time()));
521             
522             // Terminate audio data output, truncating (ignore) or flushing
523             // (play out) final samples as per (1) control register set by
524             // the user and (2) the type of audio data termination:
526 #if 0
527             // This form is not used because driver support for truncating
528             // data is not supported for internal clocks, although it is
529             // for external clocks.
530             getVal = SIO_ctrl(pC->xOut[z].hTxSio, PAF_SIO_CONTROL_IDLE,
531                 pC->xOut[z].outBufStatus.flush
532                 & (pC->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_FLUSH
533                 ? 1 : 0);
534             /* UNTESTED */
535 #else
536             // This form should be used when driver support for truncating
537             // data is supported for both internal and external clocks.
538             getVal = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_IDLE,
539                 pAstCfg->xOut[z].outBufStatus.flush ? 1 :
540                 (pAstCfg->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_FLUSH
541                 ? 1 : 0);
542             /* TESTED */
543 #endif
545             TRACE_TIME((&TIME_MOD, "... + %d = %d (stopOutput -- after PAF_SIO_CONTROL_IDLE)", dtime(), TSK_time()));
547             if (!errno)
548             {
549                 errno = getVal;
550             }
552             // Mute output after audio data termination in a special case,
553             // where such termination is due to processing of a final frame
554             // or user command. Identification of this as a special case is
555             // provided by the "decode processing" state machine.
556             if (!(pAstCfg->xOut[z].outBufStatus.audio & 0xf0) &&
557                 ((pAstCfg->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_FLUSH) &&
558                 (getVal = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_MUTE, 0)))
559             {
560                 if (!errno) 
561                 {
562                     errno = (getVal & 0xff) | ASPERR_MUTE;
563                     /* convert to sensical errno */
564                 }
565                 TRACE_VERBOSE1("as1-f2: asopStopOutput:  AS%d: SIO control failed (mute)", as+zS);
566             }
568             pAstCfg->xOut[z].outBufStatus.audio &= ~0x0f;
569 #endif // FL, New IO
571             // zero output buffers
572             pObj = (PAF_SIO_IALG_Obj *) pAstCfg->xOut[z].outChainData.head->alg;
573             pAlgConfig = &pObj->config;
574             memset (pAstCfg->xOut[z].outBufConfig.base.pVoid, 0, pAlgConfig->pMemRec[0].size);
575         } //pAstCfg->xOut[z].hTxSio
576     }//OUTPUT
578     return errno;
579 } //asopStopOutput
581 /*===========================================================================
582  * Initialize I/O components for output processing
583 ============================================================================*/
584 Int asopIoCompsInit(
585     Int16 strAfSampleCount,     // stream audio frame sample count
586     PAF_AST_OutBuf *pOutBuf,    // pointer to Output Buffer
587     PAF_AST_IoOut *pOutIo       // pointer to Output IO
590     ioBuffParams_t ioBuffParams;
591     ioPhyParams_t  ioPhyParams;
593     if (pOutIo->hMcaspChan != NULL)
594     {
595         // Initialize I/O BUFF and I/O PHY components for output task
596         ioBuffParams.base         = pOutBuf->outBufConfig.base.pVoid;
597         // Set IO buffer size to multiple of audio frame sample count x stride x size of element.
598         // This ensures no split buffers will be allocated on Output buffer wrap.
599         ioBuffParams.size         = pOutBuf->outBufConfig.allocation/(strAfSampleCount * pOutIo->stride * WORD_SIZE_PCM)*
600             (strAfSampleCount * pOutIo->stride * WORD_SIZE_PCM);
601         ioBuffParams.sync         = IOBUff_READ_SYNC;
602         ioBuffParams.nominalDelay = strAfSampleCount * pOutIo->stride * WORD_SIZE_PCM * (NUM_PRIME_XFERS+1);
603         if (ioBuffInit(pOutIo->hIoBuff, &ioBuffParams) != IOBUFF_NOERR) 
604         {
605             return ASOP_IO_ERR_IOBUFF_INIT;   // to remove magic number
606         }
608         ioPhyParams.ioBuffHandle    = pOutIo->hIoBuff;
609         ioPhyParams.xferFrameSize   = strAfSampleCount * pOutIo->stride * WORD_SIZE_PCM;
610         ioPhyParams.mcaspChanHandle = pOutIo->hMcaspChan;
611         ioPhyParams.ioBuffOp        = IOPHY_IOBUFFOP_READ;
612         if (ioPhyInit(pOutIo->hIoPhy, &ioPhyParams) != IOPHY_NOERR) 
613         {
614             return ASOP_IO_ERR_IOPHY_INIT;   // to remove magic number
615         }
617         pOutIo->phyXferSize = ioPhyParams.xferFrameSize;
618         
619         pOutIo->ioBuffBuf2AllocCnt = 0; // initialize buffer2 alloc count (indicates Output buffer wrap)
620         pOutIo->errIoBuffOvrCnt = 0;    // initialize IO buff overflow count
621         pOutIo->errIoBuffUndCnt = 0;    // initialize IO buff underflow count
622     }
623     
624     return ASOP_IO_SOK;
625 } /* asopIoCompsInit */
627 /*======================================================================================
628  *  This function checks whether the I/O physical layer has been initialized
629  *====================================================================================*/
630 Bool asopIoPhyCheckInit(Void)
632     if (!d10Initialized)
633         return FALSE;
634     else 
635         return TRUE;
638 /*======================================================================================
639  *  I/O physical layer prime operation required by McASP LLD
640  *====================================================================================*/
641 Void asopIoPhyPrime(
642     PAF_AST_IoOut *pOut
645     Int32        count;
647     pOut->numPrimeXfers = NUM_PRIME_XFERS;
649     for (count = 0; count < pOut->numPrimeXfers; count++)
650     {
651         ioPhyXferSubmit(pOut->hIoPhy);
652     }
653 } /* asipIoPhyPrime */
655 // Initialize Output buffer configuration
656 Int asopInitOutBufConfig(
657     PAF_AST_OutBuf *pOutBuf, 
658     PAF_AST_IoOut *pOutIo
661     PAF_OutBufConfig *pOutBufCfg;
662     ioBuffHandle_t hIoBuff;
663     ioBuffInfo_t outBuffInfo;
664     
665     pOutBufCfg = &pOutBuf->outBufConfig;
666     hIoBuff = pOutIo->hIoBuff;
667     
668     pOutBufCfg->stride = pOutIo->stride;
669     pOutBufCfg->sizeofElement = WORD_SIZE_PCM;
670     pOutBufCfg->precision = 24;
671     
672     ioBuffGetInfo(hIoBuff, &outBuffInfo);
673     pOutBufCfg->base.pLgInt = outBuffInfo.base;
674     pOutBufCfg->sizeofBuffer = outBuffInfo.size;
675     
676     pOutBuf->pOutBuf = &(pOutBuf->outBufConfig);
677     
678     return ASOP_IO_SOK;
681 Int asopGetOutBufPtrs(
682     PAF_AST_IoOut *pOutIo,
683     size_t writeSize
686     void *buff1, *buff2;
687     size_t size1, size2;
688     Int status;
690     status = ioBuffGetWritePtrs(pOutIo->hIoBuff, writeSize,
691                                 &buff1, &size1, &buff2, &size2);
692     if (status == IOBUFF_ERR_OVERFLOW)
693     {
694         pOutIo->errIoBuffOvrCnt++;
695         //System_printf ("asopGetOutBufPtrs: output buff overflow\n"); // debug
697         // skip processing since output buffer overflows
698         return ASOP_IO_ERR_OUTBUF_OVERFLOW;
699     }
700     else if (status == IOBUFF_ERR_UNDERFLOW)
701     {
702         pOutIo->errIoBuffUndCnt++;
703         //System_printf ("asopGetOutBufPtrs: output buff underflow\n"); // debug
705         // already underflows and remain in underflow
706     }
707     
708     if ((buff2 != NULL) || (size2 != 0))
709     {
710         // Two buffers allocated indicates split buffer allocation on buffer wrap.
711         pOutIo->ioBuffBuf2AllocCnt++; // increment count of allocated buffer2
712     }
714     // save buffer pointers & sizes for later write complete
715     pOutIo->buff1 = buff1;
716     pOutIo->size1 = size1;
717     pOutIo->buff2 = buff2;
718     pOutIo->size2 = size2;
720     return ASOP_IO_SOK;
723 #if 0
724 // Update Output buffer configuration.
725 // This is needed for proper operation of PCM encoder.
726 Int asopUpdateOutBufConfig(
727     PAF_AST_OutBuf *pOutBuf, 
728     PAF_AST_IoOut *pOutIo
731     PAF_OutBufConfig *pOutBufCfg;
732     ioBuffHandle_t hIoBuff;
733     ioBuffInfo_t outBuffInfo;
734     void *buff1, *buff2;
735     size_t size1, size2, total_write_size;
736     Int status;
738     pOutBufCfg = &pOutBuf->outBufConfig;
739     hIoBuff = pOutIo->hIoBuff;
741     // FL, New IO: original code can change these values in every DOB issue
742     //  Need to determine if this is required or not.
743     pOutBufCfg->stride = pOutIo->stride;
744     pOutBufCfg->sizeofElement = WORD_SIZE_PCM;
745     pOutBufCfg->precision = 24;
746     
747     //JXTODO: to replace hard coded write size
748     // Get write pointers of output memory pool
749     total_write_size = pOutBufCfg->lengthofFrame * pOutBufCfg->stride * pOutBufCfg->sizeofElement;
750     status = ioBuffGetWritePtrs(hIoBuff, total_write_size,
751         &buff1, &size1, &buff2, &size2);
752     if (status == IOBUFF_ERR_OVERFLOW) 
753     {
754         pOutIo->errIoBuffOvrCnt++;
755         //System_printf ("asopUpdateOutBufConfig: output buff overflow\n"); // debug
757         // skip processing since output buffer overflows        
758         return ASOP_IO_ERR_OUTBUF_OVERFLOW;
759     }
760     else if (status == IOBUFF_ERR_UNDERFLOW) 
761     {
762         pOutIo->errIoBuffUndCnt++;
763         //System_printf ("asopUpdateOutBufConfig: output buff underflow\n"); // debug
764         
765         // already underflows and remain in underflow
766     }
767 #if 0
768     // Update Output buffer pointer for Encoder
769     pOutBufCfg->pntr.pLgInt = buff1;
770     if ((buff2 != NULL) || (size2 != 0))
771     {
772         // buff2 should always be NULL for Output & size2 should always be 0 for Output.
773         // Track this here.
774         pOutIo->ioBuffBuf2AllocCnt++; // debug
775     }
776 #endif
777     // save buffer pointers & sizes for later write complete
778     pOutIo->buff1 = buff1;
779     pOutIo->size1 = size1;
780     pOutIo->buff2 = buff2;
781     pOutIo->size2 = size2;
782     
783     return ASOP_IO_SOK;
785 #endif
787 // Mark Output buffers write complete
788 Int asopMarkOutBuffsWriteComplete(
789     PAF_AST_OutBuf *pOutBuf, 
790     PAF_AST_IoOut *pOutIo
793     ioBuffHandle_t hIoBuff;
794     void *buff1, *buff2;
795     size_t size1, size2;
796     
797     // get buffer pointers & sizes from previous IO Buff write allocation
798     buff1 = pOutIo->buff1;
799     size1 = pOutIo->size1;
800     buff2 = pOutIo->buff2; // this should always be NULL for Output
801     size2 = pOutIo->size2; // this should always be 0 for Output
802     
803     hIoBuff = pOutIo->hIoBuff;
804     
805     ioBuffWriteComplete(hIoBuff, buff1, size1);
807     if (buff2 != NULL) 
808     {
809         ioBuffWriteComplete(hIoBuff, buff2, size2);
810     }
811     
812     return ASOP_IO_SOK;
815 /*======================================================================================
816  *  This function starts an I/O PHY transfer for output
817  *====================================================================================*/
818 Void asopPhyTransferStart(
819     PAF_AST_IoOut *pOut
822     if(mcaspCheckOverUnderRun(pOut->hMcaspChan)) 
823     {
824         //mcaspTxReset();
825         //mcaspTxCreate();
826         //pOut->hMcaspChan = hMcaspTxChan;
827         System_abort("\nMcASP for output underruns! %d!\n");
828     }
829     else 
830     {
831         if(ioPhyXferSubmit(pOut->hIoPhy) == IOPHY_ERR_BUFF_UNDERFLOW) 
832         {
833             // Output buffer underflows!
834             System_abort("\nOutput buffer underflows!\n");
835         }
836         else {
837             // Output buffer operates normally
838             ;
839         }
840     }
843 /* nothing past this point */