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