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 // -----------------------------------------------------------------------------
68 // ASOT Decoding Function Helper - SIO Driver Change
69 //
70 // Name: PAF_ASOT_setCheckRateX
71 // Purpose: Decoding Function for reinitiating output.
72 // From: AST Parameter Function -> decodeInfo1
73 // AST Parameter Function -> decodeInfo2
74 // Uses: See code.
75 // States: x
76 // Return: Error number in standard form (0 on success).
77 // Trace: None.
78 //
80 /* 0: set, 1: check, unused for now. --Kurt */
81 Int asopSetCheckRateX(
82 const PAF_ASOT_Params *pP,
83 const PAF_ASOT_Patchs *pQ,
84 PAF_ASOT_Config *pAsotCfg,
85 Int check
86 )
87 {
88 PAF_AST_Config *pAstCfg;
89 PAF_AST_IoOut *pOut;
90 float rateX;
91 PAF_SampleRateHz rateO /* std */, rateI /* inv */;
92 Int z; /* output counter */
93 Int zx; /* output re-counter */
94 Int getVal;
95 int inputRate, inputCount, outputRate, outputCount;
96 Int zMD;
97 Int zMI;
98 Int zMS;
99 Int zE, zX;
101 pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
102 pOut = pAsotCfg->pIoOut; // get pointer to ASOT IO configuration
104 zMD = pAstCfg->masterDec;
105 zMS = pAstCfg->masterStr;
106 zMI = pP->zone.master;
108 inputRate = pAstCfg->xInp[zMI].inpBufStatus.sampleRateStatus;
109 inputCount = pAstCfg->xDec[zMD].decodeStatus.frameLength;
110 rateI = pAstCfg->xStr[zMS].pAudioFrame->fxns->sampleRateHz(pAstCfg->xStr[zMS].pAudioFrame,
111 inputRate, PAF_SAMPLERATEHZ_INV);
113 for (z=OUTPUT1; z < OUTPUTN; z++)
114 {
115 if (pOut[z].hIoPhy && (pAstCfg->xOut[z].outBufStatus.clock & 0x01))
116 {
117 // determine associated encoder
118 zE = z;
119 for (zX = ENCODE1; zX < ENCODEN; zX++)
120 {
121 if (pP->outputsFromEncodes[zX] == z)
122 {
123 zE = zX;
124 break;
125 }
126 }
128 outputRate = pAstCfg->xEnc[zE].encodeStatus.sampleRate;
129 outputCount = pAstCfg->xEnc[zE].encodeStatus.frameLength;
130 rateO = pAstCfg->xStr[zMS].pAudioFrame->fxns->sampleRateHz(pAstCfg->xStr[zMS].pAudioFrame,
131 outputRate, PAF_SAMPLERATEHZ_STD);
132 if ((rateI > 0) && (rateO > 0))
133 {
134 rateX = rateO /* std */ * rateI /* inv */;
135 }
136 else if (inputCount != 0)
137 {
138 rateX = (float)outputCount / inputCount;
139 }
140 else
141 {
142 return ASPERR_INFO_RATERATIO;
143 }
145 #if 0 // FL, New IO: add similar thing to be figured out
146 getVal = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_SET_RATEX, (Arg)&rateX);
147 if (getVal == DOBERR_RATECHANGE)
148 {
149 for (zx=OUTPUT1; zx < OUTPUTN; zx++)
150 {
151 if (pAstCfg->xOut[zx].hTxSio)
152 {
153 SIO_idle(pAstCfg->xOut[zx].hTxSio);
154 }
155 }
157 // this forces an exit from the calling state machine which will
158 // eventually call startOutput which calls setCheckRateX for all outputs
159 // and so it is ok, in the presence of a rate change on any output, to
160 // exit this loop /function early.
161 return ASPERR_INFO_RATECHANGE;
162 }
163 else if (getVal != SYS_OK)
164 {
165 return ((getVal & 0xff) | ASPERR_RATE_CHECK);
166 }
167 #endif // FL, New IO
168 }
169 }
171 return 0;
172 } //asopSetCheckRateX
174 // -----------------------------------------------------------------------------
175 // ASOT Decoding Function Helper - SIO Driver Start
176 //
177 // Name: PAF_ASOT_startOutput
178 // Purpose: Decoding Function for initiating output.
179 // From: AST Parameter Function -> decodeInfo1
180 // Uses: See code.
181 // States: x
182 // Return: Error number in standard or SIO form (0 on success).
183 // Trace: Message Log "trace" in Debug Project Configuration reports:
184 // * State information as per parent.
185 // * SIO control errors.
186 //
187 Int asopStartOutput(
188 const PAF_ASOT_Params *pP,
189 const PAF_ASOT_Patchs *pQ,
190 PAF_ASOT_Config *pAsotCfg
191 )
192 {
193 PAF_AST_Config *pAstCfg;
194 PAF_AST_IoOut *pOut;
195 Int as; /* Audio Stream Number (1, 2, etc.) */
196 Int z; /* output counter */
197 Int nbufs;
198 Int zE, zS, zX;
199 Int zMD;
200 PAF_SIO_IALG_Obj *pObj;
201 PAF_SIO_IALG_Config *pAlgConfig;
202 ioPhyCtl_t ioPhyCtl;
205 pAstCfg = pAsotCfg->pAstCfg; // get pointer to common (shared) configuration
206 pOut = pAsotCfg->pIoOut; // get pointer to ASOT IO configuration
207 as = pAstCfg->as;
208 zMD = pAstCfg->masterDec;
210 for (z=OUTPUT1; z < OUTPUTN; z++)
211 {
212 if (pOut[z].hIoPhy)
213 {
214 // determine associated encoder and stream
215 zE = z;
216 zS = z;
217 for (zX = ENCODE1; zX < ENCODEN; zX++)
218 {
219 if (pP->outputsFromEncodes[zX] == z)
220 {
221 zE = zX;
222 zS = pP->streamsFromEncodes[zE];
223 break;
224 }
225 }
227 // FL, New IO: add similar thing to be figured out
228 // Need to Revisit: Starting Clocks here seems logical & also manages the McASP without spurious underruns .
229 #if 0
230 // if device selected and valid then enable stat tracking if
231 // required and start clocking
232 if ((pAstCfg->xOut[z].outBufStatus.sioSelect < 0) && (pAstCfg->xOut[z].hTxSio))
233 {
234 TRACE_VERBOSE0("PAF_ASOT_startOutput: start SIO clocks");
235 errme = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_OUTPUT_START_CLOCKS, 0);
236 if (errno)
237 {
238 TRACE_VERBOSE2("PAF_ASOT_startOutput: errme 0x%x, errno 0x%x", errme, errno);
239 SIO_idle(pAstCfg->xOut[z].hTxSio);
240 if (!errno)
241 {
242 errno = ASPERR_DEVOUT + errme;
243 }
244 }
245 }
246 #endif
248 // Set sample count so that DOB knows how much data to send
249 pAstCfg->xOut[z].outBufConfig.lengthofFrame =
250 pAstCfg->xEnc[zE].encodeInStruct.pAudioFrame->sampleCount;
252 #if 1 // FL New IO: add similar thing to be figured out
253 ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
254 ioPhyCtl.params.xferFrameSize = pAstCfg->xOut[z].outBufConfig.lengthofFrame
255 * OUTPUT_STRIDE * WORD_SIZE_PCM;
256 ioPhyControl(pOut[z].hIoPhy, &ioPhyCtl);
257 // Update framework transfer size to IO Phy transfer size
258 pOut[z].phyXferSize = ioPhyCtl.params.xferFrameSize;
259 // Update IO Buff delay to match IO Phy transfer size
260 ioBuffAdjustDelay(pOut[z].hIoBuff, ioPhyCtl.params.xferFrameSize * (NUM_PRIME_XFERS+1));
261 #endif
263 if (pAstCfg->xOut[z].outBufStatus.markerMode == PAF_OB_MARKER_ENABLED)
264 {
265 pObj = (PAF_SIO_IALG_Obj *) pAstCfg->xOut[z].outChainData.head->alg;
266 pAlgConfig = &pObj->config;
267 memset(pAstCfg->xOut[z].outBufConfig.base.pVoid, 0xAA,
268 pAlgConfig->pMemRec[0].size);
269 }
271 // The index to DEC_OUTNUMBUF_MAP will always come from the primary/master
272 // decoder. How should we handle the sourceProgram for multiple decoders?
273 // Override as needed
274 nbufs = DEC_OUTNUMBUF_MAP(pAstCfg->xDec[zMD].decodeStatus.sourceProgram);
275 if (pAstCfg->xOut[z].outBufStatus.numBufOverride[pAstCfg->xDec[zMD].decodeStatus.sourceProgram] > 0)
276 {
277 nbufs = pAstCfg->xOut[z].outBufStatus.numBufOverride[pAstCfg->xDec[zMD].decodeStatus.sourceProgram];
278 }
279 //JXTODO: add similar thing to be figured out
280 //SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_SET_NUMBUF, nbufs);
282 //JXTODO: data transfer start to be moved to output task state machine
283 /*if (errno = SIO_issue(pAstCfg->xOut[z].hTxSio,
284 &pAstCfg->xOut[z].outBufConfig, sizeof(pAstCfg->xOut[z].outBufConfig), 0))
285 {
286 SIO_idle(pAstCfg->xOut[z].hTxSio);
287 TRACE_TERSE2("PAF_ASOT_startOutput: AS%d: SIO_issue failed (0x%x)", as+zS, errno);
288 return errno;
289 } */
291 //JXTODO: add similar thing to be figured out
292 #if 0
293 if (!(pAstCfg->xOut[z].outBufStatus.audio & 0xf0) &&
294 (errno = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_UNMUTE, 0)))
295 {
296 errno = (errno & 0xff) | ASPERR_MUTE;
297 /* convert to sensical errno */
298 TRACE_TERSE2("as1-f2: PAF_ASOT_startOutput: AS%d: SIO control failed (unmute) 0x%x", as+zS, errno);
299 return errno;
300 }
301 else
302 {
303 pAstCfg->xOut[z].outBufStatus.audio
304 = (pAstCfg->xOut[z].outBufStatus.audio & 0xf0) | PAF_OB_AUDIO_SOUND;
305 }
306 #endif
307 TRACE_VERBOSE1("PAF_ASOT_startOutput: AS%d: output started", as+zS);
308 }
309 }
311 return 0;
312 } /* asopStartOutput */
314 // -----------------------------------------------------------------------------
315 // ASOT Decoding Function Helper - SIO Driver Stop
316 //
317 // Name: PAF_ASOT_stopOutput
318 // Purpose: Decoding Function for terminating output.
319 // From: AST Parameter Function -> decodeProcessing
320 // AST Parameter Function -> decodeComplete
321 // Uses: See code.
322 // States: x
323 // Return: Error number in standard or SIO form (0 on success).
324 // Trace: Message Log "trace" in Debug Project Configuration reports:
325 // * SIO control errors.
326 //
327 Int asopStopOutput(
328 const PAF_ASOT_Params *pP,
329 const PAF_ASOT_Patchs *pQ,
330 PAF_ASOT_Config *pAsotCfg
331 )
332 {
333 PAF_AST_Config *pAstCfg;
334 PAF_AST_IoOut *pOut;
335 Int as; /* Audio Stream Number (1, 2, etc.) */
336 Int z; /* output counter */
337 Int errno = 0, getVal;
338 Int zS, zX;
339 PAF_SIO_IALG_Obj *pObj;
340 PAF_SIO_IALG_Config *pAlgConfig;
342 pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
343 pOut = pAsotCfg->pIoOut; // get pointer to ASOT IO configuration
344 as = pAstCfg->as;
345 (void)as; // clear compiler warning in case not used with tracing disabled
347 for (z=OUTPUT1; z < OUTPUTN; z++)
348 {
349 if (pOut[z].hIoPhy)
350 {
351 // determine associated encoder and stream
352 zS = z;
353 (void)zS;
354 for (zX = ENCODE1; zX < ENCODEN; zX++)
355 {
356 if (pP->outputsFromEncodes[zX] == z)
357 {
358 zS = pP->streamsFromEncodes[zX];
359 break;
360 }
361 }
363 #if 0 // FL, New IO: add similar thing to be figured out
364 // Mute output before audio data termination in the usual case,
365 // where such termination is due to decode error or user command.
366 // Identification of this as the usual case is provided by the
367 // "decode processing" state machine.
368 if (!(pAstCfg->xOut[z].outBufStatus.audio & 0xf0) &&
369 ((pAstCfg->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_SOUND) &&
370 (getVal = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_MUTE, 0)))
371 {
372 if (!errno)
373 {
374 errno = (getVal & 0xff) | ASPERR_MUTE;
375 /* convert to sensical errno */
376 }
377 TRACE_VERBOSE1("asopStopOutput: AS%d: SIO control failed (mute)", as+zS);
378 }
380 TRACE_TIME((&TIME_MOD, "... + %d = %d (stopOutput -- begin PAF_SIO_CONTROL_IDLE)", dtime(), TSK_time()));
382 // Terminate audio data output, truncating (ignore) or flushing
383 // (play out) final samples as per (1) control register set by
384 // the user and (2) the type of audio data termination:
386 #if 0
387 // This form is not used because driver support for truncating
388 // data is not supported for internal clocks, although it is
389 // for external clocks.
390 getVal = SIO_ctrl(pC->xOut[z].hTxSio, PAF_SIO_CONTROL_IDLE,
391 pC->xOut[z].outBufStatus.flush
392 & (pC->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_FLUSH
393 ? 1 : 0);
394 /* UNTESTED */
395 #else
396 // This form should be used when driver support for truncating
397 // data is supported for both internal and external clocks.
398 getVal = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_IDLE,
399 pAstCfg->xOut[z].outBufStatus.flush ? 1 :
400 (pAstCfg->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_FLUSH
401 ? 1 : 0);
402 /* TESTED */
403 #endif
405 TRACE_TIME((&TIME_MOD, "... + %d = %d (stopOutput -- after PAF_SIO_CONTROL_IDLE)", dtime(), TSK_time()));
407 if (!errno)
408 {
409 errno = getVal;
410 }
412 // Mute output after audio data termination in a special case,
413 // where such termination is due to processing of a final frame
414 // or user command. Identification of this as a special case is
415 // provided by the "decode processing" state machine.
416 if (!(pAstCfg->xOut[z].outBufStatus.audio & 0xf0) &&
417 ((pAstCfg->xOut[z].outBufStatus.audio & 0x0f) == PAF_OB_AUDIO_FLUSH) &&
418 (getVal = SIO_ctrl(pAstCfg->xOut[z].hTxSio, PAF_SIO_CONTROL_MUTE, 0)))
419 {
420 if (!errno)
421 {
422 errno = (getVal & 0xff) | ASPERR_MUTE;
423 /* convert to sensical errno */
424 }
425 TRACE_VERBOSE1("as1-f2: asopStopOutput: AS%d: SIO control failed (mute)", as+zS);
426 }
428 pAstCfg->xOut[z].outBufStatus.audio &= ~0x0f;
429 #endif // FL, New IO
431 // zero output buffers
432 pObj = (PAF_SIO_IALG_Obj *) pAstCfg->xOut[z].outChainData.head->alg;
433 pAlgConfig = &pObj->config;
434 memset (pAstCfg->xOut[z].outBufConfig.base.pVoid, 0, pAlgConfig->pMemRec[0].size);
435 } //pAstCfg->xOut[z].hTxSio
436 }//OUTPUT
438 return errno;
439 } //asopStopOutput
441 // FL, New IO: this function is currently a stub
442 // FL, New IO: need to McASP/EDMA configuration using SAP configuration from Output shortcut
443 // Select Output devices
444 Int asopSelectDevices(PAF_AST_IoOut *pOut)
445 {
446 if((pOut->hIoBuff == NULL) || (pOut->hIoPhy == NULL) || (!d10Initialized)) {
447 return -1;
448 }
450 pOut->hMcaspChan = hMcaspTxChan;
452 return 0;
453 }
455 /*===========================================================================
456 * Initialize I/O components for output processing
457 ============================================================================*/
458 Int asopIoCompsInit(
459 PAF_AST_OutBuf *pOutBuf,
460 PAF_AST_IoOut *pOutIo
461 )
462 {
463 // Initialize I/O BUFF and I/O PHY components for output task
464 ioBuffParams_t ioBuffParams;
465 ioPhyParams_t ioPhyParams;
467 ioBuffParams.base = pOutBuf->outBufConfig.base.pVoid;
468 ioBuffParams.size = pOutBuf->outBufConfig.allocation/STRIDE_WORST_CASE*STRIDE_WORST_CASE;
469 ioBuffParams.sync = IOBUff_READ_SYNC;
470 ioBuffParams.nominalDelay = OUTPUT_FRAME_SIZE * (NUM_PRIME_XFERS+1);
471 if(ioBuffInit(pOutIo->hIoBuff, &ioBuffParams) != IOBUFF_NOERR)
472 {
473 return -1; // to remove magic number
474 }
476 ioPhyParams.ioBuffHandle = pOutIo->hIoBuff;
477 ioPhyParams.xferFrameSize = OUTPUT_FRAME_SIZE;
478 ioPhyParams.mcaspChanHandle = hMcaspTxChan;
479 ioPhyParams.ioBuffOp = IOPHY_IOBUFFOP_READ;
480 if(ioPhyInit(pOutIo->hIoPhy, &ioPhyParams) != IOPHY_NOERR)
481 {
482 return -1; // to remove magic number
483 }
485 pOutIo->phyXferSize = ioPhyParams.xferFrameSize;
487 return 0;
488 } /* asopIoCompsInit */
491 /*======================================================================================
492 * I/O physical layer prime operation required by McASP LLD
493 *====================================================================================*/
494 Void asopIoPhyPrime(
495 PAF_AST_IoOut *pOut
496 )
497 {
498 Int32 count;
500 pOut->numPrimeXfers = NUM_PRIME_XFERS;
502 for (count = 0; count < pOut->numPrimeXfers; count++)
503 {
504 ioPhyXferSubmit(pOut->hIoPhy);
505 }
506 } /* asipIoPhyPrime */
509 /*======================================================================================
510 * This function checks whether the I/O physical layer has been initialized
511 *====================================================================================*/
512 Bool asopIoPhyCheckInit(Void)
513 {
514 if (!d10Initialized)
515 return FALSE;
516 else
517 return TRUE;
518 }
520 /*======================================================================================
521 * This function starts an I/O PHY transfer for output
522 *====================================================================================*/
523 Void asopPhyTransferStart(
524 PAF_AST_IoOut *pOut
525 )
526 {
527 if(mcaspCheckOverUnderRun(pOut->hMcaspChan))
528 {
529 mcaspTxReset();
530 mcaspTxCreate();
531 pOut->hMcaspChan = hMcaspTxChan;
532 }
533 else
534 {
535 if(ioPhyXferSubmit(pOut->hIoPhy) == IOPHY_ERR_BUFF_UNDERFLOW)
536 {
537 // Output buffer underflows!
538 System_abort("\nOutput buffer underflows!\n");
539 }
540 else {
541 // Output buffer operates normally
542 ;
543 }
544 }
545 }
547 // Write output buffers with encoded data
548 Int asopWriteOpBuffers(
549 PAF_OutBufConfig *pOpBufCfg,
550 PAF_AST_IoOut *pOut
551 )
552 {
553 PAF_UnionPointer pntr;
554 void *buff1, *buff2;
555 size_t size1, size2;
556 int status;
558 pntr = pOpBufCfg->pntr; // get output buffer pointer
560 status = ioBuffGetWritePtrs(pOut->hIoBuff, pOut->phyXferSize,
561 &buff1, &size1, &buff2, &size2);
562 if (status == IOBUFF_ERR_OVERFLOW)
563 {
564 /* skip processing since output buffer overflows */
565 return IOBUFF_ERR_OVERFLOW; // to use a different error code
566 }
568 // Copy data to output buffer to be transmitted by McASP
569 memcpy(buff1, &pntr.pSmInt[0], size1);
570 Cache_wbInv(buff1, size1, Cache_Type_ALL,TRUE);
572 ioBuffWriteComplete(pOut->hIoBuff, buff1, size1);
574 if (buff2 != NULL)
575 {
576 memcpy(buff2, &pntr.pSmInt[size1], size2);
577 Cache_wbInv(buff2, size2, Cache_Type_ALL,TRUE);
579 ioBuffWriteComplete(pOut->hIoBuff, buff2, size2);
580 }
582 return 0;
583 }
585 // Check if Output device SIO selection changed
586 Int checkOutDevSioSelUpdate(
587 const PAF_ASOT_Params *pP,
588 PAF_ASOT_Config *pAsotCfg,
589 Int z,
590 Bool *pOutDevSelUpdate
591 )
592 {
593 PAF_AST_Config *pAstCfg;
595 pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
597 if ((z < OUTPUT1) || (z >= OUTPUTN))
598 {
599 *pOutDevSelUpdate = FALSE;
600 return -1;
601 }
603 *pOutDevSelUpdate = (Bool)(pAstCfg->xOut[z].outBufStatus.sioSelect >= 0);
605 return 0;
606 }
608 // Check if any Output device SIO selection changed
609 Int checkAnyOutDevSioSelUpdate(
610 const PAF_ASOT_Params *pP,
611 PAF_ASOT_Config *pAsotCfg,
612 Bool *pOutDevSelUpdate
613 )
614 {
615 PAF_AST_Config *pAstCfg;
616 Int outDevSelUpdate;
617 Int z;
619 pAstCfg = pAsotCfg->pAstCfg; // get pointer to AST common (shared) configuration
621 outDevSelUpdate = FALSE;
622 for (z=OUTPUT1; z < OUTPUTN; z++)
623 {
624 if (pAstCfg->xOut[z].outBufStatus.sioSelect >= 0)
625 {
626 outDevSelUpdate = TRUE;
627 break;
628 }
629 }
631 *pOutDevSelUpdate = outDevSelUpdate;
633 return 0;
634 }
636 /* nothing past this point */