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;
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 }
99 *pOutDevSelUpdate = (Bool)(pAstCfg->xOut[z].outBufStatus.sioSelect >= 0);
101 return 0;
102 }
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
109 )
110 {
111 PAF_AST_Config *pAstCfg;
112 Int outDevSelUpdate;
113 Int z;
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 }
127 *pOutDevSelUpdate = outDevSelUpdate;
129 return 0;
130 }
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
151 )
152 {
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
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
256 )
257 {
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
396 )
397 {
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()));
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
512 )
513 {
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;
538 pOutIo->ioBuffNumOvr = 0; // initialize number of IO buff overflows
539 pOutIo->ioBuffNumUnd = 0; // initialize number of IO buff underflows
541 return 0;
542 } /* asopIoCompsInit */
544 /*======================================================================================
545 * This function checks whether the I/O physical layer has been initialized
546 *====================================================================================*/
547 Bool asopIoPhyCheckInit(Void)
548 {
549 if (!d10Initialized)
550 return FALSE;
551 else
552 return TRUE;
553 }
555 /*======================================================================================
556 * I/O physical layer prime operation required by McASP LLD
557 *====================================================================================*/
558 Void asopIoPhyPrime(
559 PAF_AST_IoOut *pOut
560 )
561 {
562 Int32 count;
564 pOut->numPrimeXfers = NUM_PRIME_XFERS;
566 for (count = 0; count < pOut->numPrimeXfers; count++)
567 {
568 ioPhyXferSubmit(pOut->hIoPhy);
569 }
570 } /* asipIoPhyPrime */
572 // Initialize Output buffer configuration
573 Int asopInitOutBufConfig(
574 PAF_AST_OutBuf *pOutBuf,
575 PAF_AST_IoOut *pOutIo
576 )
577 {
578 PAF_OutBufConfig *pOutBufCfg;
579 ioBuffHandle_t hIoBuff;
580 ioBuffInfo_t outBuffInfo;
582 pOutBufCfg = &pOutBuf->outBufConfig;
583 hIoBuff = pOutIo->hIoBuff;
585 pOutBufCfg->stride = OUTPUT_STRIDE;
586 pOutBufCfg->sizeofElement = WORD_SIZE_PCM;
587 pOutBufCfg->precision = 24;
589 ioBuffGetInfo(hIoBuff, &outBuffInfo);
590 pOutBufCfg->base.pLgInt = outBuffInfo.base;
591 pOutBufCfg->sizeofBuffer = outBuffInfo.size;
593 pOutBuf->pOutBuf = &(pOutBuf->outBufConfig);
595 return 0;
596 }
598 // Update Output buffer configuration.
599 // This is needed for proper operation of PCM encoder.
600 Int asopUpdateOutBufConfig(
601 PAF_AST_OutBuf *pOutBuf,
602 PAF_AST_IoOut *pOutIo
603 )
604 {
605 PAF_OutBufConfig *pOutBufCfg;
606 ioBuffHandle_t hIoBuff;
607 ioBuffInfo_t outBuffInfo;
608 void *buff1, *buff2;
609 size_t size1, size2, total_write_size;
610 Int status;
612 pOutBufCfg = &pOutBuf->outBufConfig;
613 hIoBuff = pOutIo->hIoBuff;
615 // FL, New IO: original code can change these values in every DOB issue
616 // Need to determine if this is required or not.
617 pOutBufCfg->stride = OUTPUT_STRIDE;
618 pOutBufCfg->sizeofElement = WORD_SIZE_PCM;
619 pOutBufCfg->precision = 24;
621 //JXTODO: to replace hard coded write size
622 // Get write pointers of output memory pool
623 total_write_size = pOutBufCfg->lengthofFrame * pOutBufCfg->stride * pOutBufCfg->sizeofElement;
624 status = ioBuffGetWritePtrs(hIoBuff, total_write_size,
625 &buff1, &size1, &buff2, &size2);
626 if (status == IOBUFF_ERR_OVERFLOW)
627 {
628 pOutIo->ioBuffNumOvr++;
629 //System_printf ("asopUpdateOutBufConfig: output buff overflow\n"); // debug
631 // skip processing since output buffer overflows
632 return -1;
633 }
634 else if (status == IOBUFF_ERR_UNDERFLOW)
635 {
636 pOutIo->ioBuffNumUnd++;
637 //System_printf ("asopUpdateOutBufConfig: output buff underflow\n"); // debug
639 // already underflows and remain in underflow
640 }
642 // Update Output buffer pointer for Encoder
643 pOutBufCfg->pntr.pLgInt = buff1;
645 // save buffer pointers & sizes for later write complete
646 pOutIo->buff1 = buff1;
647 pOutIo->size1 = size1;
648 pOutIo->buff2 = buff2; // this should always be NULL for Output
649 pOutIo->size2 = size2; // this should always be 0 for Output
651 return 0;
652 }
654 // Mark Output buffers write complete
655 Int asopMarkOutBuffsWriteComplete(
656 PAF_AST_OutBuf *pOutBuf,
657 PAF_AST_IoOut *pOutIo
658 )
659 {
660 ioBuffHandle_t hIoBuff;
661 void *buff1, *buff2;
662 size_t size1, size2;
664 // get buffer pointers & sizes from previous IO Buff write allocation
665 buff1 = pOutIo->buff1;
666 size1 = pOutIo->size1;
667 buff2 = pOutIo->buff2; // this should always be NULL for Output
668 size2 = pOutIo->size2; // this should always be 0 for Output
670 hIoBuff = pOutIo->hIoBuff;
672 ioBuffWriteComplete(hIoBuff, buff1, size1);
674 if (buff2 != NULL)
675 {
676 ioBuffWriteComplete(hIoBuff, buff2, size2);
677 }
679 return 0;
680 }
682 /*======================================================================================
683 * This function starts an I/O PHY transfer for output
684 *====================================================================================*/
685 Void asopPhyTransferStart(
686 PAF_AST_IoOut *pOut
687 )
688 {
689 if(mcaspCheckOverUnderRun(pOut->hMcaspChan))
690 {
691 mcaspTxReset();
692 mcaspTxCreate();
693 pOut->hMcaspChan = hMcaspTxChan;
694 }
695 else
696 {
697 if(ioPhyXferSubmit(pOut->hIoPhy) == IOPHY_ERR_BUFF_UNDERFLOW)
698 {
699 // Output buffer underflows!
700 System_abort("\nOutput buffer underflows!\n");
701 }
702 else {
703 // Output buffer operates normally
704 ;
705 }
706 }
707 }
709 /* nothing past this point */