01805dcf665b614a3770703aa0742fcb2b290b31
2 //#include "analog_test.h"
3 #include "frame_work.h"
4 #include "ioBuff.h"
5 #include "ioData.h"
6 #include "ioPhy.h"
7 #include <mcasp_drv.h>
8 #include "mcasp_cfg.h"
9 #include "ioConfig.h"
11 //#define TEST_OVERFLOW_UNDERFLOW
12 //#define TEST_OVERFLOW_OVERFLOW
13 #define NUM_BUFS_USED 8
15 #define INPUT_SWITCH_HANGOVER 8
17 /* Frame index for Rx and Tx buffers */
18 uint8_t rxFrameIndex = 0;
19 uint8_t txFrameIndex = 0;
20 uint32_t rxBufIndex = 0;
21 uint32_t txBufIndex = 0;
23 /* McASP Tx and Rx frame buffers */
24 MCASP_Packet rxFrame[NUM_BUFS];
25 MCASP_Packet txFrame[NUM_BUFS];
27 /* McASP Tx and Rx frame buffer pointers */
28 Ptr txBuf[NUM_BUFS];
29 Ptr rxBuf[NUM_BUFS];
30 Ptr procBuf;
32 /* Flags for counting Rx and Tx interrupts */
33 volatile uint32_t rxFlag = 0;
34 volatile uint32_t txFlag = 0;
36 int dataFrameIndex=0;
37 int RxTSKcnt = 0, TxTSKcnt = 0;
38 volatile int RxFlag=0, RxFlag1=0, RxFlag2=0, TxFlag=0, TxFlag1=0, TxFlag2=0;
40 /* Semaphore handle for Tx and Rx */
41 Semaphore_Handle semR;
42 Semaphore_Handle semT;
43 Semaphore_Params SemParams;
45 uint32_t mcaspRxChanArg = 1;
46 uint32_t mcaspTxChanArg = 2;
47 int num_gbl_err = 0;
48 int txCount = 0;
49 int rxCount = 0;
50 int resetCount = 0;
52 extern Mcasp_ChanParams mcaspRxChanParam;
54 /* McASP channel handles */
55 extern Ptr hMcaspTxChan;
56 extern Ptr hMcaspRxChan;
58 /* McASP device handles */
59 extern Ptr hMcaspDevTx;
60 extern Ptr hMcaspDevRx;
62 extern uint32_t gblErrFlag;
65 fwInst_t fwInst;
66 extern Ptr databuf[NUM_BUFS];
68 extern signed char* getGlobalAddr(signed char* addr);
70 void inputXferStart();
71 void outputXferStart();
73 int check_mcasp_rx_overrun(void);
74 void mcasp_rx_restart(void);
75 int check_mcasp_tx_underrun(void);
76 void mcasp_tx_restart(void);
77 void ioRecfgRxPhyForPcm(void);
78 void ioRecfgRxPhyForBitStream();
80 extern void ioCompsInitInput();
81 extern void ioCompsInitOutput();
84 #ifndef USE_IO_COMPONENTS
85 /**
86 * \brief McASP callback function called up on the data transfer completion
87 *
88 * \param arg [IN] - Application specific callback argument
89 * \param ioBuf [IN] - McASP IO buffer
90 *
91 * \return None
92 */
93 void mcaspAppCallbackRx(void *arg, MCASP_Packet *ioBuf)
94 {
95 /* Callback is triggered by Rx completion */
97 rxFlag++;
99 /* Post semaphore */
100 Semaphore_post(semR);
101 }
103 void mcaspAppCallbackTx(void *arg, MCASP_Packet *ioBuf)
104 {
105 /* Callback is triggered by Tx completion */
107 txFlag++;
109 /* Post semaphore */
110 Semaphore_post(semT);
111 }
113 #else
115 void *mcaspRxBuf1;
116 void *mcaspRxBuf2;
117 uint32_t mcaspRxSize1;
118 uint32_t mcaspRxSize2;
119 int mcaspRxtwoXfers = 0;
121 void mcaspAppCallbackRx(void* arg, MCASP_Packet *mcasp_packet)
122 {
123 RxFlag++;
125 /* post semaphore */
126 if(mcasp_packet->arg == IOPHY_XFER_FINAL) {
127 RxFlag1++;
129 Semaphore_post(semR);
130 } else {
131 RxFlag2++;
132 }
133 }
135 void mcaspAppCallbackTx(void* arg, MCASP_Packet *mcasp_packet)
136 {
137 TxFlag++;
139 /* post semaphore */
140 if(mcasp_packet->arg == IOPHY_XFER_FINAL) {
141 TxFlag1++;
143 Semaphore_post(semT);
144 } else {
145 TxFlag2++;
146 }
147 }
148 #endif
151 #ifdef IO_LOOPBACK_TEST
153 #ifndef USE_IO_COMPONENTS
155 /**
156 * \brief Task to echo the input data to output
157 *
158 * Waits for the McASP data transfer completion and copies the
159 * Rx data to Tx buffers
160 *
161 * \return Audk2g_EOK on Success or error code
162 */
163 Void taskAsipFxn(
164 const PAF_ASIT_Params *pP, //JX: asip_params_PAi defined in itopo/params.c
165 const PAF_ASIT_Patchs *pQ //JX: asop_patchs_PAi defined in itopo/patchs.c
166 )
167 {
168 int32_t count;
169 Int status;
171 inputXferStart();
173 /* Forever loop to continuously receive and transmit audio data */
174 count = 0;
175 while (1)
176 {
177 if(gblErrFlag)
178 {
179 break;
180 }
182 //Log_info0("Pending Rx semaphore");
184 /* Reclaim full buffer from the input stream */
185 Semaphore_pend(semR, BIOS_WAIT_FOREVER);
187 /* Copy the receive information to the transmit buffer */
188 Cache_inv(rxBuf[rxFrameIndex], INPUT_FRAME_SIZE, Cache_Type_ALL, TRUE);
189 memcpy(procBuf, rxBuf[rxFrameIndex], INPUT_FRAME_SIZE);
191 /* Issue an empty buffer to the input stream */
192 rxFrame[rxFrameIndex].cmd = MCASP_READ;
193 rxFrame[rxFrameIndex].addr = (void*)(getGlobalAddr(rxBuf[rxFrameIndex]));
194 rxFrame[rxFrameIndex].size = INPUT_FRAME_SIZE;
195 rxFrame[rxFrameIndex].arg = (uint32_t) mcaspRxChanArg;
196 rxFrame[rxFrameIndex].status = 0;
197 rxFrame[rxFrameIndex].misc = 1; /* reserved - used in callback to indicate asynch packet */
199 status = mcaspSubmitChan(hMcaspRxChan, &rxFrame[rxFrameIndex]);
200 if((status != MCASP_COMPLETED) && (status != MCASP_PENDING))
201 {
202 Log_info0("mcaspSubmitChan for Rx Failed\n");
203 }
205 rxFrameIndex++;
206 if(rxFrameIndex==NUM_BUFS_USED) {
207 rxFrameIndex = 0;
208 }
210 // test McASP LLD reset
211 count += 1;
212 if(count == 1000) {
213 mcaspRxReset();
214 mcaspRxChanParam.wordWidth = Mcasp_WordLength_32;
215 mcaspRxCreate();
216 inputXferStart();
218 count = 0;
219 resetCount += 1;
220 }
221 }
222 } /* taskAsipFxn */
224 Void taskAsopFxn(
225 const PAF_ASOT_Params *pP,
226 const PAF_ASOT_Patchs *pQ
227 )
228 {
229 Int status;
231 outputXferStart();
232 //Semaphore_Params_init(¶ms);
234 /* Forever loop to continuously receive and transmit audio data */
235 while (1)
236 {
237 if(gblErrFlag)
238 {
239 break;
240 }
242 //Log_info0("Pending Tx semaphore");
244 /* Reclaim full buffer from the input stream */
245 Semaphore_pend(semT, BIOS_WAIT_FOREVER);
247 memcpy(txBuf[txFrameIndex], procBuf, OUTPUT_FRAME_SIZE);
248 Cache_wbInv(txBuf[txFrameIndex], OUTPUT_FRAME_SIZE, Cache_Type_ALL,TRUE);
250 /* Issue full buffer to the output stream */
251 /* TX frame processing */
252 txFrame[txFrameIndex].cmd = MCASP_WRITE;
253 txFrame[txFrameIndex].addr = (void*)(getGlobalAddr(txBuf[txFrameIndex]));
254 txFrame[txFrameIndex].size = OUTPUT_FRAME_SIZE;
255 txFrame[txFrameIndex].arg = (uint32_t) mcaspTxChanArg;
256 txFrame[txFrameIndex].status = 0;
257 txFrame[txFrameIndex].misc = 1; /* reserved - used in callback to indicate asynch packet */
259 status = mcaspSubmitChan(hMcaspTxChan, &txFrame[txFrameIndex]);
260 if((status != MCASP_COMPLETED) && (status != MCASP_PENDING))
261 {
262 Log_info0("mcaspSubmitChan for Tx Failed\n");
263 }
264 else {
265 txCount++;
266 }
268 txFrameIndex++;
269 if(txFrameIndex==NUM_BUFS_USED) {
270 txFrameIndex = 0;
271 }
273 }
275 //testRet(0);
276 }
279 /* put input and output in the same task */
280 Void taskAsipFxn_1tsk(
281 const PAF_ASIT_Params *pP, //JX: asip_params_PAi defined in itopo/params.c
282 const PAF_ASIT_Patchs *pQ //JX: asop_patchs_PAi defined in itopo/patchs.c
283 )
284 {
285 Int status;
287 // mcaspRxCfgPCM();
289 inputXferStart();
290 outputXferStart();
292 /* Forever loop to continuously receive and transmit audio data */
293 while (1)
294 {
295 if(gblErrFlag)
296 {
297 break;
298 }
300 /* pending on both Rx and Tx semaphore */
301 Semaphore_pend(semR, BIOS_WAIT_FOREVER);
302 Semaphore_pend(semT, BIOS_WAIT_FOREVER);
304 /* Copy the receive information to the transmit buffer */
305 Cache_inv(rxBuf[rxFrameIndex], INPUT_FRAME_SIZE, Cache_Type_ALL, TRUE);
306 memcpy(procBuf, rxBuf[rxFrameIndex], INPUT_FRAME_SIZE);
308 memcpy(txBuf[txFrameIndex], procBuf, INPUT_FRAME_SIZE);
309 Cache_wbInv(txBuf[txFrameIndex], OUTPUT_FRAME_SIZE, Cache_Type_ALL,TRUE);
311 /* Issue an empty buffer to the input stream */
312 rxFrame[rxFrameIndex].cmd = MCASP_READ;
313 rxFrame[rxFrameIndex].addr = (void*)(getGlobalAddr(rxBuf[rxFrameIndex]));
314 rxFrame[rxFrameIndex].size = INPUT_FRAME_SIZE;
315 rxFrame[rxFrameIndex].arg = (uint32_t) mcaspRxChanArg;
316 rxFrame[rxFrameIndex].status = 0;
317 rxFrame[rxFrameIndex].misc = 1; /* reserved - used in callback to indicate asynch packet */
319 status = mcaspSubmitChan(hMcaspRxChan, &rxFrame[rxFrameIndex]);
320 if((status != MCASP_COMPLETED) && (status != MCASP_PENDING))
321 {
322 Log_info0("mcaspSubmitChan for Rx Failed\n");
323 }
325 rxFrameIndex++;
326 if(rxFrameIndex==NUM_BUFS_USED) {
327 rxFrameIndex = 0;
328 }
330 /* Issue full buffer to the output stream */
331 /* TX frame processing */
332 txFrame[txFrameIndex].cmd = MCASP_WRITE;
333 txFrame[txFrameIndex].addr = (void*)(getGlobalAddr(txBuf[txFrameIndex]));
334 txFrame[txFrameIndex].size = OUTPUT_FRAME_SIZE;
335 txFrame[txFrameIndex].arg = (uint32_t) mcaspTxChanArg;
336 txFrame[txFrameIndex].status = 0;
337 txFrame[txFrameIndex].misc = 1; /* reserved - used in callback to indicate asynch packet */
339 status = mcaspSubmitChan(hMcaspTxChan, &txFrame[txFrameIndex]);
340 if((status != MCASP_COMPLETED) && (status != MCASP_PENDING))
341 {
342 Log_info0("mcaspSubmitChan for Tx Failed\n");
343 }
344 else {
345 txCount++;
346 }
348 txFrameIndex++;
349 if(txFrameIndex==NUM_BUFS_USED) {
350 txFrameIndex = 0;
351 }
352 /*
353 if(txCount == 3000) {
354 mcaspRxReset();
355 mcaspRxCreate();
356 inputXferStart();
358 txCount = 0;
359 resetCount += 1;
360 }
361 */
362 }
364 //testRet(0);
365 }
367 Void taskAsopFxn_1tsk(
368 const PAF_ASOT_Params *pP,
369 const PAF_ASOT_Patchs *pQ
370 )
371 {
373 }
375 #else // else of #ifndef USE_IO_COMPONENTS
377 void audio_rx_proc()
378 {
379 void *buff1, *buff2;
380 size_t size1, size2;
382 /* Get read pointers of input memory pool */
383 if (ioBuffGetReadPtrs(fwInst.ioInp.hIoBuff, INPUT_FRAME_SIZE_PCM,
384 &buff1, &size1, &buff2, &size2)
385 == IOBUFF_ERR_UNDERFLOW) {
386 fwInst.buf_status_in = FW_IOBUF_UNDERFLOW;
387 //System_printf ("Debug: input buff underflows!\n");
389 /* skip processing since there is no enough data to process */
390 return;
391 } else {
392 fwInst.buf_status_in = FW_IOBUF_NORMAL;
393 }
395 /* copy the input data to data buffer */
396 Cache_inv(buff1, size1, Cache_Type_ALL, TRUE);
397 memcpy(databuf[0],buff1,size1);
398 ioBuffReadComplete(fwInst.ioInp.hIoBuff, buff1, size1);
400 if(buff2 != NULL) {
401 Cache_inv(buff2, size2, Cache_Type_ALL, TRUE);
402 memcpy((void *)((size_t)databuf[0]+size1),buff2,size2);
403 ioBuffReadComplete(fwInst.ioInp.hIoBuff, buff2, size2);
404 }
406 //Cache_wbInv(databuf[dataFrameIndex], INPUT_FRAME_SIZE, Cache_Type_ALL,TRUE);
407 } /* audio_rx_proc */
409 void audio_tx_proc()
410 {
411 void *buff1, *buff2;
412 size_t size1, size2;
413 int status;
414 /*
415 dataFrameIndex++;
416 if(dataFrameIndex==NUM_BUFS) {
417 dataFrameIndex = 0;
418 }
419 */
420 // Get write pointers of output memory pool
421 status = ioBuffGetWritePtrs(fwInst.ioOut.hIoBuff, OUTPUT_FRAME_SIZE,
422 &buff1, &size1, &buff2, &size2);
423 if (status == IOBUFF_ERR_OVERFLOW) {
424 fwInst.buf_status_out = FW_IOBUF_OVERFLOW;
425 //System_printf ("Debug: output buff overflows in Tx proc!\n");
427 /* skip processing since output buffer overflows */
428 return;
429 }
430 else if (status == IOBUFF_ERR_UNDERFLOW) {
431 /* already underflows and remain in underflow */
432 fwInst.buf_status_out = FW_IOBUF_UNDERFLOW;
433 }
434 else {
435 fwInst.buf_status_out = FW_IOBUF_NORMAL;
436 }
438 /* copy the output data from data buffer to output memory pool */
439 memcpy(buff1, databuf[0], size1);
440 Cache_wbInv(buff1, size1, Cache_Type_ALL,TRUE);
442 ioBuffWriteComplete(fwInst.ioOut.hIoBuff, buff1, size1);
444 if(buff2 != NULL) {
445 memcpy(buff2,(void *)((size_t)databuf[0]+size1),size2);
446 Cache_wbInv(buff2, size2, Cache_Type_ALL,TRUE);
448 ioBuffWriteComplete(fwInst.ioOut.hIoBuff, buff2, size2);
449 }
450 } /* audio_tx_proc */
452 void rxDecodeProcess()
453 {
454 ioDataCtl_t ioDataCtl;
455 void *buffBase;
456 void *dataStartAddress;
457 size_t buffSize, frameSize, size1, size2;
459 /* Get information for reading input data */
460 ioDataCtl.code = IODATA_CTL_GET_INPBUFFINFO;
461 ioDataControl(fwInst.ioInp.hIoData, &ioDataCtl);
463 buffBase = ioDataCtl.param.dataReadInfo.buffBase;
464 buffSize = ioDataCtl.param.dataReadInfo.buffSize;
465 dataStartAddress = ioDataCtl.param.dataReadInfo.startAddress;
466 frameSize = ioDataCtl.param.dataReadInfo.frameSize;
468 /* Depending on source information, either decode bit stream or simply
469 * copy PCM data to output buffer.
470 */
471 if(fwInst.syncState == IODATA_SYNC_PCM) {
472 // Copy PCM data to output buffer
473 if(((size_t)dataStartAddress+frameSize) <= ((size_t)buffBase+buffSize)) {
474 // Input buffer doesn't wrap around
475 Cache_inv(dataStartAddress, frameSize, Cache_Type_ALL, TRUE);
476 memcpy(databuf[0], dataStartAddress, frameSize);
477 }
478 else {
479 // Input buffer wraps around
480 size1 = (size_t)buffBase + buffSize - (size_t)dataStartAddress;
481 size2 = frameSize - size1;
482 Cache_inv(dataStartAddress, size1, Cache_Type_ALL, TRUE);
483 memcpy(databuf[0], dataStartAddress, size1);
485 Cache_inv(buffBase, size2, Cache_Type_ALL, TRUE);
486 memcpy((void *)((size_t)databuf[0]+size1), buffBase, size2);
487 }
488 }
489 else if(fwInst.syncState == IODATA_SYNC_BITSTREAM) {
490 // Do nothing - there is no decoder
491 }
492 } /* rxDecodeProcess */
494 int numFrameReceived, numPcmFrameReceived, numSyncLost, numUnderflow;
495 extern const MdUns iecFrameLength[23];
497 #define SYNC_PC_MASK 0x001F
499 Void taskAsipFxn(
500 const PAF_ASIT_Params *pP, //JX: asip_params_PAi defined in itopo/params.c
501 const PAF_ASIT_Patchs *pQ //JX: asop_patchs_PAi defined in itopo/patchs.c
502 )
503 {
504 int autoDetstatus;
505 ioDataCtl_t ioDataCtl;
506 ioPhyCtl_t ioPhyCtl;
508 /* Initialize I/O components for input */
509 ioCompsInitInput();
511 #ifdef INPUT_HDMI_4xI2S // HDMI 4xI2S, bit stream or PCM
512 #ifdef INPUT_PCM_ONLY
513 fwInst.ioInp.swapData = FALSE; // initialized to receive PCM
514 #else
515 fwInst.ioInp.swapData = TRUE; // initialized to receive bit stream
516 #endif
517 #else
518 fwInst.ioInp.swapData = FALSE; // initialized to receive PCM
519 #endif
521 fwInst.syncState = IODATA_SYNC_NONE;
522 fwInst.syncStatePrev = IODATA_SYNC_NONE;
523 fwInst.switchHangOver = 0;
524 fwInst.ioDelayAdjust = FALSE;
526 /* Start McASP LLD for input transfer */
527 inputXferStart();
529 numFrameReceived = 0;
530 numPcmFrameReceived = 0;
531 numSyncLost = 0;
533 /* Forever loop to continously receviec and transmit audio data */
534 while (1)
535 {
536 if(gblErrFlag) {
537 num_gbl_err++;
538 break;
539 }
541 Semaphore_pend(semR, BIOS_WAIT_FOREVER);
543 RxTSKcnt++;
545 ioPhyXferComplete(fwInst.ioInp.hIoPhy, fwInst.ioInp.swapData);
547 #ifndef INPUT_PCM_ONLY
548 if(fwInst.switchHangOver)
549 {
550 void *buff1, *buff2;
551 size_t size1, size2;
553 // Get read pointers (or sub-buffers) of the input buffer
554 if (ioBuffGetReadPtrs(fwInst.ioInp.hIoBuff, fwInst.phyXferSize,
555 &buff1, &size1, &buff2, &size2)
556 == IOBUFF_ERR_UNDERFLOW) {
557 printf("Input buffer underflows during switch hangover!\n");
558 exit(0);
559 }
561 ioBuffReadComplete(fwInst.ioInp.hIoBuff, buff1, size1);
563 if(buff2 != NULL) {
564 ioBuffReadComplete(fwInst.ioInp.hIoBuff, buff2, size2);
565 }
567 memset(databuf[0], 0, OUTPUT_FRAME_SIZE);
568 fwInst.switchHangOver--;
569 }
570 else {
571 // Input format is unknown, perform auto-detection
572 autoDetstatus = ioDataProcess(fwInst.ioInp.hIoData);
573 if(autoDetstatus == IODATA_ERR_IOBUF_UNDERFLOW) {
574 // Input buffer underflows - no action is needed
575 //printf("Input buffer underflows.\n");
576 numUnderflow += 1;
577 }
578 else if(autoDetstatus != IODATA_NO_ERR) {
579 // print error log and return
580 printf("IODATA processing error!\n");
581 exit(0);
582 }
583 else {
584 // Check auto-detection status
585 ioDataCtl.code = IODATA_CTL_GET_AUTODET_STATUS;
586 ioDataControl(fwInst.ioInp.hIoData, &ioDataCtl);
588 fwInst.syncState = ioDataCtl.param.autoDetStats.syncState;
590 if(fwInst.syncState == IODATA_SYNC_BITSTREAM) {
591 if(fwInst.syncStatePrev != IODATA_SYNC_BITSTREAM) {
592 // Change I/O PHY transfer size
593 int frameSize;
594 uint_least16_t pc = ioDataCtl.param.autoDetStats.bitStreamInfo & SYNC_PC_MASK; //0x001F
595 frameSize = iecFrameLength[pc] * WORD_SIZE_BITSTREAM;
597 ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
598 ioPhyCtl.params.xferFrameSize = frameSize;
599 ioPhyControl(fwInst.ioInp.hIoPhy, &ioPhyCtl);
600 fwInst.phyXferSize = ioPhyCtl.params.xferFrameSize;
601 }
603 numFrameReceived += 1;
604 }
605 else if(fwInst.syncState == IODATA_SYNC_PCM) {
606 // reconfigure McASP LLD if necessary
607 if(fwInst.syncStatePrev != IODATA_SYNC_PCM) {
608 ioRecfgRxPhyForPcm();
610 // Change I/O PHY transfer size
611 ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
612 ioPhyCtl.params.xferFrameSize = INPUT_FRAME_SIZE_PCM;
613 ioPhyControl(fwInst.ioInp.hIoPhy, &ioPhyCtl);
615 // Adjust I/O BUFF delay and read pointer - to make sure read pointers always point to
616 // PCM data from 1st I2S (out of 4 for HDMI 4xI2S)
617 //ioBuffAdjustDelay(fwInst.ioInp.hIoBuff, INPUT_FRAME_SIZE*2);
618 fwInst.ioInp.swapData = FALSE;
619 fwInst.phyXferSize = ioPhyCtl.params.xferFrameSize;
621 fwInst.switchHangOver = INPUT_SWITCH_HANGOVER;
622 fwInst.ioDelayAdjust = TRUE;
623 }
625 numPcmFrameReceived += 1;
626 }
627 else if (fwInst.syncState == IODATA_SYNC_NONE) {
629 if(fwInst.syncStatePrev != IODATA_SYNC_NONE) {
630 numSyncLost += 1;
631 numUnderflow = 0;
632 }
634 if(fwInst.syncStatePrev == IODATA_SYNC_PCM) {
635 // reconfigure McASP LLD to 16-bit packed bits
636 ioRecfgRxPhyForBitStream();
638 // Change I/O PHY transfer size
639 ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
640 ioPhyCtl.params.xferFrameSize = INPUT_FRAME_SIZE_DEF;
641 ioPhyControl(fwInst.ioInp.hIoPhy, &ioPhyCtl);
643 // Adjust I/O BUFF delay and read pointer - to make sure read pointers always point to
644 // PCM data from 1st I2S (out of 4 for HDMI 4xI2S)
645 //ioBuffAdjustDelay(fwInst.ioInp.hIoBuff, INPUT_FRAME_SIZE*2);
647 fwInst.ioInp.swapData = TRUE;
648 fwInst.phyXferSize = ioPhyCtl.params.xferFrameSize;
649 numPcmFrameReceived = 0;
651 fwInst.switchHangOver = INPUT_SWITCH_HANGOVER; // don't need hangover, since data is all 0's anyway
652 fwInst.ioDelayAdjust = TRUE; // no need to adjust delay since read size doesn't change during PCM
653 }
654 else if(fwInst.syncStatePrev == IODATA_SYNC_BITSTREAM) {
655 numFrameReceived = 0;
657 // Change I/O PHY transfer size
658 ioPhyCtl.code = IOPHY_CTL_FRAME_SIZE;
659 ioPhyCtl.params.xferFrameSize = INPUT_FRAME_SIZE_DEF;
660 ioPhyControl(fwInst.ioInp.hIoPhy, &ioPhyCtl);
661 }
662 else {
663 // SYNC has not been detected
664 ;
665 }
666 }
668 fwInst.syncStatePrev = ioDataCtl.param.autoDetStats.syncState;
670 // Receive processing: decoding bitstream or simply passing PCM to output
671 // To add proper processing for HDMI 4xlane interface: bitstream or PCM
672 /*if ((fwInst.syncState != IODATA_SYNC_NONE) && (fwInst.switchHangOver == 0)) {
673 rxDecodeProcess();
674 }
675 else {
676 if(fwInst.switchHangOver > 0) {
677 fwInst.switchHangOver--;
678 }
679 memset(databuf[0], 0, OUTPUT_FRAME_SIZE);
680 }*/
682 if(fwInst.syncState == IODATA_SYNC_NONE) {
683 memset(databuf[0], 0, OUTPUT_FRAME_SIZE);
684 }
685 else {
686 if(fwInst.switchHangOver) {
687 memset(databuf[0], 0, OUTPUT_FRAME_SIZE);
688 fwInst.switchHangOver--;
689 }
690 else {
691 rxDecodeProcess();
692 }
693 }
695 // Mark the input as read complete
696 if(fwInst.ioDelayAdjust) {
697 // don't mark input buffer as read complete
698 ioBuffAdjustDelay(fwInst.ioInp.hIoBuff, fwInst.phyXferSize);
699 fwInst.ioDelayAdjust = FALSE;
700 }
701 else {
702 ioDataReadComplete(fwInst.ioInp.hIoData);
703 }
704 }
705 }
706 #else
707 // Input is configured to PCM data
708 audio_rx_proc();
710 rxCount++;
711 if(rxCount == 2000) {
712 ioRecfgRxPhyForPcm();
713 }
715 if(rxCount == 4000) {
716 ioRecfgRxPhyForBitStream();
717 rxCount = 0;
718 }
720 #if 0
721 // test McASP LLD reset
722 count += 1;
723 if(count == 1000) {
724 mcaspRxReset();
725 mcaspRxChanParam.wordWidth = Mcasp_WordLength_32;
726 mcaspRxCreate();
727 status = ioPhyXferErrRecover(fwInst.ioInp.hIoPhy);
728 if(status != IOPHY_NOERR) {
729 printf("ioPhyXferErrRecover fails with error code %d!\n.", status);
730 exit(0);
731 }
733 count = 0;
734 resetCount += 1;
735 }
736 #endif
737 #endif
739 if(check_mcasp_rx_overrun()) {
740 mcasp_rx_restart();
741 ioPhyXferErrRecover(fwInst.ioInp.hIoPhy);
742 }
743 else {
744 if(ioPhyXferSubmit(fwInst.ioInp.hIoPhy) == IOPHY_ERR_BUFF_OVERFLOW) {
745 fwInst.buf_status_in = FW_IOBUF_OVERFLOW;
746 printf("Input buffer overflows in Rx task!\n");
747 exit(0);
748 } else {
749 fwInst.buf_status_in = FW_IOBUF_NORMAL;
750 }
751 }
752 } /* while (1) */
754 } /* taskAsipFxn */
756 Void taskAsopFxn(const PAF_ASOT_Params *pP, const PAF_ASOT_Patchs *pQ)
757 {
758 /* Initialize I/O components for output */
759 ioCompsInitOutput();
761 /* Start McASP LLD for output transfer */
762 outputXferStart();
764 /* Forever loop to continously receviec and transmit audio data */
765 //for (i32Count = 0; i32Count >= 0; i32Count++)
766 while (1)
767 {
768 if(gblErrFlag) {
769 num_gbl_err++;
770 break;
771 }
773 Semaphore_pend(semT, BIOS_WAIT_FOREVER);
775 TxTSKcnt++;
777 ioPhyXferComplete(fwInst.ioOut.hIoPhy, FALSE);
779 #ifdef TEST_OVERFLOW_UNDERFLOW
780 if(TxTSKcnt == 200) {
781 while(fwInst.buf_status_out != FW_IOBUF_OVERFLOW) {
782 audio_tx_proc(); // create output buffer overflow situation
783 }
784 }
786 if( (TxTSKcnt < 250) || (TxTSKcnt > 260)
787 || (fwInst.buf_status_out == FW_IOBUF_UNDERFLOW)) {
788 audio_tx_proc(); // create output buffer underflow situation
789 // between 250 and 260
790 }
792 if(fwInst.buf_status_out == FW_IOBUF_UNDERFLOW) {
793 audio_tx_proc(); // process one more frame during underflow
794 }
796 if(TxTSKcnt == 500) {
797 TxTSKcnt = 0;
798 TxFlag = 0;
799 TxFlag1 = 0;
800 TxFlag2 = 0;
801 }
802 #else
803 audio_tx_proc(); // process one more frame during underflow
804 #endif
806 if(check_mcasp_tx_underrun()) {
807 mcasp_tx_restart();
808 }
809 else {
810 if(ioPhyXferSubmit(fwInst.ioOut.hIoPhy)==IOPHY_ERR_BUFF_UNDERFLOW) {
811 fwInst.buf_status_out = FW_IOBUF_UNDERFLOW;
812 //System_printf("Debug: output buffer underflows in Tx task!\n");
813 }
814 else {
815 fwInst.buf_status_out = FW_IOBUF_NORMAL;
816 }
817 }
818 } /* while (1) */
819 } /* taskAsopFxn */
821 #endif // end of #ifndef USE_IO_COMPONENTS
823 #endif // end of #ifdef IO_LOOPBACK_TEST
826 extern const uint_least16_t IECframeLength[23];
828 void inputXferStart(void)
829 {
830 Int32 count;
832 #ifdef USE_IO_COMPONENTS
833 for(count = 0; count < NUM_PRIME_XFERS; count++)
834 {
835 ioPhyXferSubmit(fwInst.ioInp.hIoPhy);
836 }
837 #else
838 int status;
840 for(count = 0; count < NUM_PRIME_XFERS; count++)
841 {
842 /* Issue the first & second empty buffers to the input stream */
843 memset((uint8_t *)rxBuf[count], 0x0, INPUT_FRAME_SIZE);
845 /* RX frame processing */
846 rxFrame[count].cmd = MCASP_READ;
847 rxFrame[count].addr = (void*)(getGlobalAddr(rxBuf[count]));
848 rxFrame[count].size = INPUT_FRAME_SIZE;
849 rxFrame[count].arg = (uint32_t) mcaspRxChanArg;
850 rxFrame[count].status = 0;
851 rxFrame[count].misc = 1; /* reserved - used in callback to indicate asynch packet */
853 /* Submit McASP packet for Rx */
854 status = mcaspSubmitChan(hMcaspRxChan, &rxFrame[count]);
855 if((status != MCASP_COMPLETED) && (status != MCASP_PENDING))
856 {
857 IFPRINT(platform_write("mcaspSubmitChan for Rx Failed\n"));
858 exit(0);
859 }
860 }
862 // rxFrameIndex = count;
863 #endif
864 } /* inputXferStart */
866 void outputXferStart(void)
867 {
868 Int32 count;
870 /* Create semaphores to wait for buffer reclaiming */
871 // semT = Semaphore_create(0, &SemParams, &eb);
872 // semT = Semaphore_create(0, NULL, NULL);
874 #ifdef USE_IO_COMPONENTS
875 for(count = 0; count < NUM_PRIME_XFERS; count++)
876 {
877 if(ioPhyXferSubmit(fwInst.ioOut.hIoPhy)==IOPHY_ERR_BUFF_UNDERFLOW) {
878 fwInst.buf_status_out = FW_IOBUF_UNDERFLOW;
879 //System_printf("Debug, output buffer underflows in prime!\n");
880 } else {
881 fwInst.buf_status_out = FW_IOBUF_NORMAL;
882 }
883 }
884 #else
885 int status;
887 for(count = 0; count < NUM_PRIME_XFERS; count++)
888 {
889 memset((uint8_t *)txBuf[count], 0x0, OUTPUT_FRAME_SIZE);
891 /* TX frame processing */
892 txFrame[count].cmd = MCASP_WRITE;
893 txFrame[count].addr = (void*)(getGlobalAddr(txBuf[count]));
894 txFrame[count].size = OUTPUT_FRAME_SIZE;
895 txFrame[count].arg = (uint32_t) mcaspTxChanArg;
896 txFrame[count].status = 0;
897 txFrame[count].misc = 1; /* reserved - used in callback to indicate asynch packet */
899 /* Submit McASP packet for Tx */
900 status = mcaspSubmitChan(hMcaspTxChan, &txFrame[count]);
901 if((status != MCASP_COMPLETED) && (status != MCASP_PENDING))
902 {
903 IFPRINT(platform_write("mcaspSubmitChan for Tx Failed\n"));
904 exit(0);
905 }
906 }
908 // txFrameIndex = count;
909 #endif
910 } /* outputXferStart */
912 int check_mcasp_rx_overrun(void)
913 {
914 Mcasp_errCbStatus mcaspErrStat;
916 mcaspControlChan(hMcaspRxChan, Mcasp_IOCTL_CHAN_QUERY_ERROR_STATS, &mcaspErrStat);
918 return (mcaspErrStat.isRcvOvrRunOrTxUndRunErr);
919 }
921 void mcasp_rx_restart(void)
922 {
923 mcaspRxReset();
924 mcaspRxCreate();
925 }
927 int check_mcasp_tx_underrun(void)
928 {
929 Mcasp_errCbStatus mcaspErrStat;
931 mcaspControlChan(hMcaspTxChan, Mcasp_IOCTL_CHAN_QUERY_ERROR_STATS, &mcaspErrStat);
933 return (mcaspErrStat.isRcvOvrRunOrTxUndRunErr);
934 }
936 void mcasp_tx_restart(void)
937 {
938 mcaspTxReset();
939 mcaspTxCreate();
940 ioPhyXferErrRecover(fwInst.ioOut.hIoPhy);
941 }
943 void ioSemaphoreCreate(void)
944 {
945 Semaphore_Params_init(&SemParams);
947 semR = Semaphore_create(0, &SemParams, NULL);
948 semT = Semaphore_create(0, &SemParams, NULL);
949 }
951 void ioRecfgRxPhyForBitStream()
952 {
953 Int status = Audk2g_EOK;
955 if(mcaspRxChanParam.wordWidth != Mcasp_WordLength_16) {
956 //mcaspRxReset();
958 mcaspRxChanParam.wordWidth = Mcasp_WordLength_16;
959 status = mcaspControlChan(hMcaspRxChan, Mcasp_IOCTL_CHAN_PARAMS_WORD_WIDTH, &mcaspRxChanParam);
961 //status = mcaspRxCreate();
963 if(status != Audk2g_EOK) {
964 printf("McASP LLD reconfiguration for bitstream fails!\n");
965 exit(0);
966 }
968 //ioPhyXferErrRecover(fwInst.ioInp.hIoPhy);
969 }
970 } /* ioRecfgRxPhyForBitStream */
972 void ioRecfgRxPhyForPcm(void)
973 {
974 Int status = Audk2g_EOK;
976 if(mcaspRxChanParam.wordWidth != Mcasp_WordLength_32) {
977 //mcaspRxReset();
979 mcaspRxChanParam.wordWidth = Mcasp_WordLength_32;
981 status = mcaspControlChan(hMcaspRxChan, Mcasp_IOCTL_CHAN_PARAMS_WORD_WIDTH, &mcaspRxChanParam);
982 //status = mcaspRxCreate();
983 if(status != Audk2g_EOK) {
984 printf("McASP LLD reconfiguration for PCM fails!\n");
985 exit(0);
986 }
988 //ioPhyXferErrRecover(fwInst.ioInp.hIoPhy);
989 }
990 } /* ioRecfgRxPhyForPcm */