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
100 )
101 {
102 PAF_AST_Config *pAstCfg;
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 }
112 *pOutDevSelUpdate = (Bool)(pAstCfg->xOut[z].outBufStatus.sioSelect >= 0);
114 return 0;
115 }
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
122 )
123 {
124 PAF_AST_Config *pAstCfg;
125 Int outDevSelUpdate;
126 Int z;
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 }
140 *pOutDevSelUpdate = outDevSelUpdate;
142 return 0;
143 }
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
164 )
165 {
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
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
269 )
270 {
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
409 )
410 {
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()));
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
525 )
526 {
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;
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)
562 {
563 if (!d10Initialized)
564 return FALSE;
565 else
566 return TRUE;
567 }
569 /*======================================================================================
570 * I/O physical layer prime operation required by McASP LLD
571 *====================================================================================*/
572 Void asopIoPhyPrime(
573 PAF_AST_IoOut *pOut
574 )
575 {
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
590 )
591 {
592 PAF_OutBufConfig *pOutBufCfg;
593 ioBuffHandle_t hIoBuff;
594 ioBuffInfo_t outBuffInfo;
596 pOutBufCfg = &pOutBuf->outBufConfig;
597 hIoBuff = pOutIo->hIoBuff;
599 pOutBufCfg->stride = pOutIo->stride;
600 pOutBufCfg->sizeofElement = WORD_SIZE_PCM;
601 pOutBufCfg->precision = 24;
603 ioBuffGetInfo(hIoBuff, &outBuffInfo);
604 pOutBufCfg->base.pLgInt = outBuffInfo.base;
605 pOutBufCfg->sizeofBuffer = outBuffInfo.size;
607 pOutBuf->pOutBuf = &(pOutBuf->outBufConfig);
609 return 0;
610 }
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
617 )
618 {
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;
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
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 }
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;
671 return 0;
672 }
674 // Mark Output buffers write complete
675 Int asopMarkOutBuffsWriteComplete(
676 PAF_AST_OutBuf *pOutBuf,
677 PAF_AST_IoOut *pOutIo
678 )
679 {
680 ioBuffHandle_t hIoBuff;
681 void *buff1, *buff2;
682 size_t size1, size2;
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
690 hIoBuff = pOutIo->hIoBuff;
692 ioBuffWriteComplete(hIoBuff, buff1, size1);
694 if (buff2 != NULL)
695 {
696 ioBuffWriteComplete(hIoBuff, buff2, size2);
697 }
699 return 0;
700 }
702 /*======================================================================================
703 * This function starts an I/O PHY transfer for output
704 *====================================================================================*/
705 Void asopPhyTransferStart(
706 PAF_AST_IoOut *pOut
707 )
708 {
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 }
728 }
730 /* nothing past this point */