#include "ioPhy.h" #include "ioPhy_loc.h" #include "libarch.h" #include "mcasp_drv.h" #include #include // for System_printf #include #define NUM_MCASP_PRIME_PACKETS 3 // should be provided by McASP driver /****************************************************************************** * Implementation of I/O Physical Layer Component ******************************************************************************/ #define IOPHY_NUM_MEM_ALLOCS 1 #define IOPHY_INST_ALIGN 3 //C:\ti\edma3_lld_2_12_01_24\packages\ti\sdo\edma3\drv\sample\src\platforms\sample_tci66ak2g02_cfg.c extern signed char* getGlobalAddr(signed char* addr); // to be replaced by lib_getGlobalAddr /******************************************************************************* * API function: ioPhyNumAlloc * Returns the maximum number of memory allocation requests that ioPhyAlloc() * requires. *******************************************************************************/ int ioPhyNumAlloc(void) { return (IOPHY_NUM_MEM_ALLOCS); } /******************************************************************************* * API function: ioPhyAlloc * Returns a table of memory records that describe the size, alignment, type * and memory space of all buffers required by I/O PHY component. *******************************************************************************/ int ioPhyAlloc(lib_mem_rec_t *mem_tbl) { mem_tbl[0].size = sizeof(ioPhyInst_t); mem_tbl[0].alignment = IOPHY_INST_ALIGN; mem_tbl[0].type = LIB_PMEM_SLOW; mem_tbl[0].base = NULL; return (IOPHY_NOERR); } /****************************************************************************** * API function: * I/O physical layer creation. ******************************************************************************/ int ioPhyCreate(ioPhyHandle_t *handle, const lib_mem_rec_t *mem_tbl) { ioPhyInst_t *io_phy_inst; if( (mem_tbl[0].size < sizeof(ioPhyInst_t)) ||libChkAlign(mem_tbl[0].base, IOPHY_INST_ALIGN) ) { return (IOPHY_ERR_MEMORY); } io_phy_inst = (ioPhyInst_t *)mem_tbl[0].base; /* return I/O PHY instance */ *handle = (ioPhyHandle_t *)io_phy_inst; return (IOPHY_NOERR); } /****************************************************************************** * API function: * I/O physical layer initialization. ******************************************************************************/ int ioPhyInit(ioPhyHandle_t handle, const ioPhyParams_t *params) { ioPhyInst_t *io_phy_inst; Mcasp_IOcmd_e mcasp_cmd; int i; io_phy_inst = (ioPhyInst_t *)handle; if(params == NULL) { return (IOPHY_ERR_BAD_PARAMS); } /* attach I/O buffer manangement handle */ io_phy_inst->io_buff_handle = params->ioBuffHandle; /* set transfer frame size - interrupt generated when the frame is transfered */ io_phy_inst->xfer_frame_size = params->xferFrameSize; /* attach McASP driver channel handle */ io_phy_inst->mcasp_chan_handle = params->mcaspChanHandle; /* set the operation that I/O PHY will perform to I/O buffer - read or write */ io_phy_inst->ioBuffOp = params->ioBuffOp; /* attach ioBuff functions based on buffer operation */ if(params->ioBuffOp == IOPHY_IOBUFFOP_READ) { io_phy_inst->ioBuffMarkComplete = ioBuffReadComplete; io_phy_inst->ioBuffGetPtrs = ioBuffGetReadPtrs; mcasp_cmd = MCASP_WRITE; } else { io_phy_inst->ioBuffMarkComplete = ioBuffWriteComplete; io_phy_inst->ioBuffGetPtrs = ioBuffGetWritePtrs; mcasp_cmd = MCASP_READ; } for(i=0; ixfered_packets[i].cmd = mcasp_cmd; } io_phy_inst->mcasp_cmd = mcasp_cmd; /* initialize status variables */ io_phy_inst->sync_cntr = 0; /* to keep track xfer submit and complete */ io_phy_inst->submit_ind = 0; /* index to submited McASP packets */ io_phy_inst->complete_ind = 0; /* index to completed McASP packets */ return (IOPHY_NOERR); } /* ioPhyInit */ /****************************************************************************** * I/O PHY internal function: * Calculate transfer size in bytes based on encoding frame size passed * through ioPhyControl. ******************************************************************************/ static size_t ioPhy_calc_xfer_size(ioPhyInst_t *io_phy_inst) { /* calc. xfer size based on io_phy_inst->frame_size */ return (io_phy_inst->xfer_frame_size); } /****************************************************************************** * API function: * Submit transfer to underlining driver. * * - Called by audio processing task. ******************************************************************************/ int ioPhyXferSubmit(ioPhyHandle_t handle) { int submit_ind, err_code, ret_value; void *buff1, *buff2; size_t size1, size2, xfer_size; ioPhyInst_t *io_phy_inst = (ioPhyInst_t *)handle; /* Figure out the transfer size in bytes */ xfer_size = ioPhy_calc_xfer_size(io_phy_inst); // internal function ret_value = IOPHY_NOERR; /* Get one or two buffers from I/O buffer management for write */ err_code = io_phy_inst->ioBuffGetPtrs(io_phy_inst->io_buff_handle, xfer_size, &buff1, &size1, &buff2, &size2); /* Don't return from here even if ioBuff overflows or underflows, since McASP needs to be running and generating interrupts all the time. */ if(err_code == IOBUFF_ERR_UNDERFLOW) { ret_value = IOPHY_ERR_BUFF_UNDERFLOW; } if(err_code == IOBUFF_ERR_OVERFLOW) { ret_value = IOPHY_ERR_BUFF_OVERFLOW; } /* ioBuff needs to provide buffer to read/write even if it underflows/overflows */ if(buff1 == NULL) { return (IOPHY_ERR_BUFF_BADPTRS); } /* Submit 1 or 2 transfers depending on whether I/O buffer wraps around */ submit_ind = io_phy_inst->submit_ind; /* Compose McASP packet and save in the instance - McASP driver requires the packet to be in permanent memory so that it can provide the packet to the callback function. */ // io_phy_inst->xfered_packets[submit_ind].cmd = 0; io_phy_inst->xfered_packets[submit_ind].addr = (void*)(getGlobalAddr(buff1)); io_phy_inst->xfered_packets[submit_ind].size = size1; io_phy_inst->xfered_packets[submit_ind].status = 0; io_phy_inst->xfer_rec[submit_ind].base = buff1; io_phy_inst->xfer_rec[submit_ind].size = size1; if(buff2 == NULL) { /* There is no wrap around in I/O buffer - submit one transfer */ /* indicate that this is the final transfer of a frame */ io_phy_inst->xfered_packets[submit_ind].arg = IOPHY_XFER_FINAL; io_phy_inst->xfer_rec[submit_ind].packet_status = IOPHY_XFER_FINAL; } else { /* There is wrap around in I/O buffer - submit two tranfers */ /* indicate that this is the intermediate transfer of a frame */ io_phy_inst->xfered_packets[submit_ind].arg = IOPHY_XFER_INTER; io_phy_inst->xfer_rec[submit_ind].packet_status = IOPHY_XFER_INTER; } /* make a transfer request */ if((err_code = mcaspSubmitChan(io_phy_inst->mcasp_chan_handle, &io_phy_inst->xfered_packets[submit_ind])) != 1) { //System_printf("mcaspSubmitChan failed with handle 0x%x and error code %d!\n", // (unsigned int)io_phy_inst->mcasp_chan_handle, err_code); return(IOPHY_ERR_MCASP_FAIL); } /* update submit index */ submit_ind++; if(submit_ind == IOPHY_NUM_XFER_RECORD) { submit_ind = 0; } io_phy_inst->submit_ind = submit_ind; /* make another transfer request if ioBuff wraps around */ if(buff2 != NULL) { /* Compose McASP packets and save in the instance */ //io_phy_inst->xfered_packets[submit_ind].cmd = 0; io_phy_inst->xfered_packets[submit_ind].addr = (void*)(getGlobalAddr(buff2)); io_phy_inst->xfered_packets[submit_ind].size = size2; io_phy_inst->xfered_packets[submit_ind].status = 0; /* indicate that this is the final transfer of a frame */ io_phy_inst->xfered_packets[submit_ind].arg = IOPHY_XFER_FINAL; io_phy_inst->xfer_rec[submit_ind].base = buff2; io_phy_inst->xfer_rec[submit_ind].size = size2; io_phy_inst->xfer_rec[submit_ind].packet_status = IOPHY_XFER_FINAL; if((err_code = mcaspSubmitChan(io_phy_inst->mcasp_chan_handle, &io_phy_inst->xfered_packets[submit_ind])) != 1) { //System_printf("mcaspSubmitChan failed with handle 0x%x and error code %d!\n", // (unsigned int)io_phy_inst->mcasp_chan_handle, err_code); return(IOPHY_ERR_MCASP_FAIL); } submit_ind++; if(submit_ind == IOPHY_NUM_XFER_RECORD) { submit_ind = 0; } io_phy_inst->submit_ind = submit_ind; } return (ret_value); } /* ioPhyXferSubmit() */ void swapData(void *buff, uint_least32_t size) { int i; int_least16_t L0, L1, L2, L3, R0, R1, R2, R3 = 0; int_least16_t *p1, *p2; int_least16_t *dataPtr = (int_least16_t *)buff; /* for (i=0; icomplete_ind; buff = io_phy_inst->xfer_rec[complete_ind].base; size = io_phy_inst->xfer_rec[complete_ind].size; if(dataSwap) { hdmiDataSwap(buff, size); } io_phy_inst->ioBuffMarkComplete(io_phy_inst->io_buff_handle, buff, size); /* Check if this is a single McASP transfer or batch transfer */ if(io_phy_inst->xfer_rec[complete_ind].packet_status == IOPHY_XFER_INTER) { /* This is a batch transfer, so also mark next packet as complete. */ complete_ind++; if(complete_ind == IOPHY_NUM_XFER_RECORD) { complete_ind = 0; } if(io_phy_inst->xfer_rec[complete_ind].packet_status == IOPHY_XFER_FINAL) { buff = io_phy_inst->xfer_rec[complete_ind].base; size = io_phy_inst->xfer_rec[complete_ind].size; if(dataSwap) { hdmiDataSwap(buff, size); } io_phy_inst->ioBuffMarkComplete(io_phy_inst->io_buff_handle, buff, size); } else { // error! } } /* increment index to point to next completed packet */ io_phy_inst->complete_ind = complete_ind+1; if(io_phy_inst->complete_ind == IOPHY_NUM_XFER_RECORD) { io_phy_inst->complete_ind = 0; } return (IOPHY_NOERR); } /* ioPhyXferComplete() */ // TODO: add error check and recovery mechanism int ioPhyCheckXferStatus(ioPhyHandle_t handle, MCASP_Packet *mcasp_packet) { int complete_ind, temp_ind; ioPhyInst_t *io_phy_inst = (ioPhyInst_t *)handle; // complete_ind points to the packet to be marked as complete complete_ind = io_phy_inst->complete_ind; temp_ind = complete_ind + 1; if(temp_ind == IOPHY_NUM_XFER_RECORD) { temp_ind = 0; } // check if next completed packet is part of two-packet transfer or not: // - if two-packet transfer, it points to the first packet // - if one-packet transfer, it points to the only packet if(io_phy_inst->xfer_rec[complete_ind].packet_status == IOPHY_XFER_INTER) { // this is a two-packet transfer and this function may be called after either the // first or the second packet has been transfered. if( (mcasp_packet->arg == IOPHY_XFER_INTER) // first packet && (mcasp_packet->addr == io_phy_inst->xfer_rec[complete_ind].base) ) { // this is the first packet return (IOPHY_XFER_INTER); } else if( (mcasp_packet->arg == IOPHY_XFER_FINAL) // second packet && (mcasp_packet->addr == io_phy_inst->xfer_rec[temp_ind].base) ) { // this is the second packet return (IOPHY_XFER_FINAL); } else { return (IOPHY_XFER_ERROR); } } else { // this is a one-packet transfer if( (mcasp_packet->arg == IOPHY_XFER_FINAL) &&(mcasp_packet->addr == io_phy_inst->xfer_rec[complete_ind].base) ) { return (IOPHY_XFER_FINAL); } else { return (IOPHY_XFER_ERROR); } } #if 0 if(mcasp_packet->addr != io_phy_inst->xfer_rec[io_phy_inst->complete_ind].base) { return (IOPHY_XFER_ERROR); } if(mcasp_packet->arg == IOPHY_XFER_FINAL) { return (IOPHY_XFER_FINAL); } else if (mcasp_packet->arg == IOPHY_XFER_INTER) { return (IOPHY_XFER_INTER); } else { return (IOPHY_XFER_ERROR); } #endif } /* ioPhyCheckXferStatus */ /****************************************************************************** * API function: run-time control of IO Configuration component ******************************************************************************/ int ioPhyControl(ioPhyHandle_t handle, ioPhyCtl_t *ctl) { ioPhyInst_t *io_phy_inst = (ioPhyInst_t *)handle; switch(ctl->code) { case IOPHY_CTL_FRAME_SIZE: /* pass data frame size */ io_phy_inst->xfer_frame_size = ctl->params.xferFrameSize; break; case IOPHY_CTL_INPUT_CHANGE: //ioPhyInit(handle, ctl->ioPhyRxParams); break; default: break; } return (IOPHY_NOERR); } /* ioPhyControl */ // change this API to something like ioPhyXferReSubmit(ioPhyHandle_t handle, int numXfer) int ioPhyXferErrRecover(ioPhyHandle_t handle) { int submit_ind, i; ioPhyInst_t *io_phy_inst = (ioPhyInst_t *)handle; /* resend the latest #NUM_MCASP_PRIME_PACKETS packets */ submit_ind = io_phy_inst->submit_ind - NUM_MCASP_PRIME_PACKETS; //submit_ind = io_phy_inst->submit_ind - (NUM_MCASP_PRIME_PACKETS-1); if(submit_ind < 0) { submit_ind += IOPHY_NUM_XFER_RECORD; } for(i=0; imcasp_chan_handle, &io_phy_inst->xfered_packets[submit_ind])) != 1) { return(IOPHY_ERR_MCASP_FAIL); } submit_ind++; if(submit_ind == IOPHY_NUM_XFER_RECORD) { submit_ind = 0; } } io_phy_inst->submit_ind = submit_ind; return (IOPHY_NOERR); } /* ioPhyXferErrRecover */