1bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee#include "fw_pvt.h" 2bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee#include "viddec_fw_parser_ipclib_config.h" 3bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee#include "viddec_fw_common_defs.h" 4bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee#include "viddec_fw_parser.h" 5bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee#include "viddec_fw_debug.h" 6bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 7bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/* This define makes sure that the structure is stored in Local memory. 8bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee This is shared memory between host and FW.*/ 9bd8388b4555645b3d29abc6a94c303638064d69awonjong.leevolatile dmem_t _dmem __attribute__ ((section (".exchange"))); 10bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/* Debug index should be disbaled for Production FW */ 11bd8388b4555645b3d29abc6a94c303638064d69awonjong.leeuint32_t dump_ptr=0; 12bd8388b4555645b3d29abc6a94c303638064d69awonjong.leeuint32_t timer=0; 13bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 14bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/* Auto Api definitions */ 15bd8388b4555645b3d29abc6a94c303638064d69awonjong.leeismd_api_group viddec_fw_api_array[2]; 16bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 17bd8388b4555645b3d29abc6a94c303638064d69awonjong.leeextern void viddec_fw_parser_register_callbacks(void); 18bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 19bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------ 20bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function: initialize firmware SVEN TX Output 21bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------ 22bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */ 23bd8388b4555645b3d29abc6a94c303638064d69awonjong.leeint SMDEXPORT viddec_fw_parser_sven_init(struct SVEN_FW_Globals *sven_fw_globals ) 24bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{ 25bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee extern int sven_fw_set_globals(struct SVEN_FW_Globals *fw_globals ); 26bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee return(sven_fw_set_globals(sven_fw_globals)); 27bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee} 28bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 29bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------ 30bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function: viddec_fw_check_watermark_boundary 31bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This function figures out if we crossesd watermark boundary on input data. 32bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * before represents the ES Queue data when we started and current represents ES Queue data 33bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * when we are ready to swap.Threshold is the amount of data specified by the driver to trigger an 34bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * interrupt. 35bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * We return true if threshold is between before and current. 36bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------ 37bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */ 38bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline uint32_t viddec_fw_check_watermark_boundary(uint32_t before, uint32_t current, uint32_t threshold) 39bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{ 40bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee return ((before >= threshold) && (current < threshold)); 41bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee} 42bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 43bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------ 44bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function: viddec_fw_get_total_input_Q_data 45bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This function figures out how much data is available in input queue of the FW 46bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------ 47bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */ 48bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic uint32_t viddec_fw_get_total_input_Q_data(uint32_t indx) 49bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{ 50bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee FW_IPC_Handle *fwipc = GET_IPC_HANDLE(_dmem); 51bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee uint32_t ret; 52bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee int32_t pos=0; 53bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee FW_IPC_ReceiveQue *rcv_q; 54bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 55bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee rcv_q = &fwipc->rcv_q[indx]; 56bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* count the cubby buffer which we already read if present */ 57bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee ret = (_dmem.stream_info[indx].buffered_data) ? CONFIG_IPC_MESSAGE_MAX_SIZE:0; 58bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee ret += ipc_mq_read_avail(&rcv_q->mq, (int32_t *)&pos); 59bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee return ret; 60bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee} 61bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 62bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------ 63bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function: mfd_round_robin 64bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Params: 65bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * [in] pri: Priority of the stream 66bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * [in] indx: stream id number of the last stream that was scheduled. 67bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * [out] qnum: Stream id of priority(pri) which has data. 68bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This function is responsible for figuring out which stream needs to be scheduled next. 69bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * It starts after the last scheduled stream and walks through all streams until it finds 70bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * a stream which is of required priority, in start state, has space on output and data in 71bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * input. 72bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * If no such stream is found qnum is not updated and return value is 0. 73bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * If a stream is found then qnum is updated with that id and function returns 1. 74bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------ 75bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */ 76bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 77bd8388b4555645b3d29abc6a94c303638064d69awonjong.leeuint32_t mfd_round_robin(uint32_t pri, int32_t *qnum, int32_t indx) 78bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{ 79bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee FW_IPC_Handle *fwipc = GET_IPC_HANDLE(_dmem); 80bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee int32_t i = CONFIG_IPC_FW_MAX_RX_QUEUES; 81bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee uint32_t ret = 0; 82bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* Go through all queues until we find a valid queue of reqd priority */ 83bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee while(i>0) 84bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 85bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee indx++; 86bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if(indx >= CONFIG_IPC_FW_MAX_RX_QUEUES) indx = 0; 87bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 88bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* We should look only at queues which match priority and 89bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee in running state */ 90bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if( (_dmem.stream_info[indx].state == 1) 91bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee && (_dmem.stream_info[indx].priority == pri)) 92bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 93bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee uint32_t inpt_avail=0, output_avail=0, wklds_avail =0 , pos; 94bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee FW_IPC_ReceiveQue *rcv_q; 95bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee rcv_q = &fwipc->rcv_q[indx]; 96bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee inpt_avail = (_dmem.stream_info[indx].buffered_data > 0) || (ipc_mq_read_avail(&rcv_q->mq, (int32_t *)&pos) > 0); 97bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* we have to check for two workloads to protect against error cases where we might have to push both current and next workloads */ 98bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee output_avail = FwIPC_SpaceAvailForMessage(fwipc, &fwipc->snd_q[indx], CONFIG_IPC_MESSAGE_MAX_SIZE, &pos) >= 2; 99bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee pos = 0; 100bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* Need at least current and next to proceed */ 101bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee wklds_avail = (ipc_mq_read_avail(&fwipc->wkld_q[indx].mq, (int32_t *)&pos) >= (CONFIG_IPC_MESSAGE_MAX_SIZE << 1)); 102bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if(inpt_avail && output_avail && wklds_avail) 103bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee {/* Success condition: we have some data on input and enough space on output queue */ 104bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *qnum = indx; 105bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee ret =1; 106bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee break; 107bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 108bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 109bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee i--; 110bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 111bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee return ret; 112bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee} 113bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline void mfd_setup_emitter(FW_IPC_Handle *fwipc, FW_IPC_ReceiveQue *rcv_q, mfd_pk_strm_cxt *cxt) 114bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{ 115bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee int32_t ret1=0,ret=0; 116bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* We don't check return values for the peek as round robin guarantee's that we have required free workloads */ 117bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee ret = FwIPC_PeekReadMessage(fwipc, rcv_q, (char *)&(cxt->wkld1), sizeof(ipc_msg_data), 0); 118bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee ret1 = FwIPC_PeekReadMessage(fwipc, rcv_q, (char *)&(cxt->wkld2), sizeof(ipc_msg_data), 1); 119bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee viddec_emit_update(&(cxt->pm.emitter), cxt->wkld1.phys, cxt->wkld2.phys, cxt->wkld1.len, cxt->wkld2.len); 120bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee} 121bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 122bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline void mfd_init_swap_memory(viddec_pm_cxt_t *pm, uint32_t codec_type, uint32_t start_addr, uint32_t clean) 123bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{ 124bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee uint32_t *persist_mem; 125bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee persist_mem = (uint32_t *)(start_addr | GV_DDR_MEM_MASK); 126bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee viddec_pm_init_context(pm,codec_type, persist_mem, clean); 127bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee pm->sc_prefix_info.first_sc_detect = 1; 128bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee viddec_emit_init(&(pm->emitter)); 129bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee} 130bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 131bd8388b4555645b3d29abc6a94c303638064d69awonjong.leevoid output_omar_wires( unsigned int value ) 132bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{ 133bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee#ifdef RTL_SIMULATION 134bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee reg_write(CONFIG_IPC_ROFF_HOST_DOORBELL, value ); 135bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee#endif 136bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee} 137bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 138bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------ 139bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function: viddec_fw_init_swap_memory 140bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This function is responsible for seeting the swap memory to a good state for current stream. 141bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * The swap parameter tells us whether we need to dma the context to local memory. 142bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * We call init on emitter and parser manager which inturn calls init of the codec we are opening the stream for. 143bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------ 144bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */ 145bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 146bd8388b4555645b3d29abc6a94c303638064d69awonjong.leevoid viddec_fw_init_swap_memory(unsigned int stream_id, unsigned int swap, unsigned int clean) 147bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{ 148bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee mfd_pk_strm_cxt *cxt; 149bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee mfd_stream_info *cxt_swap; 150bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee cxt = (mfd_pk_strm_cxt *)&(_dmem.srm_cxt); 151bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee cxt_swap = (mfd_stream_info *)&(_dmem.stream_info[stream_id]); 152bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 153bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if(swap) 154bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee {/* Swap context into local memory */ 155bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee cp_using_dma(cxt_swap->ddr_cxt, (uint32_t) &(cxt->pm), sizeof(viddec_pm_cxt_t), false, false); 156bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 157bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 158bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 159bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee mfd_init_swap_memory(&(cxt->pm), cxt_swap->strm_type, cxt_swap->ddr_cxt+cxt_swap->cxt_size, clean); 160bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee cxt_swap->wl_time = 0; 161bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee cxt_swap->es_time = 0; 162bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 163bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if(swap) 164bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee {/* Swap context into DDR */ 165bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee cp_using_dma(cxt_swap->ddr_cxt, (uint32_t) &(cxt->pm), sizeof(viddec_pm_cxt_t), true, false); 166bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 167bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee} 168bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 169bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------ 170bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function: viddec_fw_push_current_frame_to_output 171bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This is a helper function to read a workload from input queue and push to output queue. 172bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This is called when are done with a frame. 173bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------ 174bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */ 175bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline void viddec_fw_push_current_frame_to_output(FW_IPC_Handle *fwipc, uint32_t cur) 176bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{ 177bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee ipc_msg_data wkld_to_push; 178bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee FwIPC_ReadMessage(fwipc, &fwipc->wkld_q[cur], (char *)&(wkld_to_push), sizeof(ipc_msg_data)); 179bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee FwIPC_SendMessage(fwipc, cur, (char *)&(wkld_to_push), sizeof(ipc_msg_data)); 180bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee} 181bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 182bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------ 183bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function: viddec_fw_get_next_stream_to_schedule 184bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This is a helper function to figure out which active stream needs to be scheduled next. 185bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * If none of the streams are active it returns -1. 186bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------ 187bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */ 188bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline int viddec_fw_get_next_stream_to_schedule(void) 189bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{ 190bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee int32_t cur = -1; 191bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 192bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if(mfd_round_robin(viddec_stream_priority_REALTIME, &cur, _dmem.g_pk_data.high_id)) 193bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 194bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* On success store the stream id */ 195bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee _dmem.g_pk_data.high_id = cur; 196bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 197bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee else 198bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 199bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* Check Low priority Queues, Since we couldn't find a valid realtime stream */ 200bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if(mfd_round_robin(viddec_stream_priority_BACKGROUND, &cur, _dmem.g_pk_data.low_id)) 201bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 202bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee _dmem.g_pk_data.low_id = cur; 203bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 204bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 205bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 206bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee return cur; 207bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee} 208bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 209bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------ 210bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function: viddec_fw_update_pending_interrupt_flag 211bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This is a helper function to figure out if we need to mark an interrupt pending for this stream. 212bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * We update status value here if we find any of the interrupt conditions are true. 213bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * If this stream has a interrupt pending which we could not send to host, we don't overwrite past status info. 214bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------ 215bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */ 216bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline void viddec_fw_update_pending_interrupt_flag(int32_t cur, mfd_stream_info *cxt_swap, uint8_t pushed_a_workload, 217bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee uint32_t es_Q_data_at_start) 218bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{ 219bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if(_dmem.int_status[cur].mask) 220bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 221bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if(!cxt_swap->pending_interrupt) 222bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 223bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee uint32_t es_Q_data_now; 224bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee uint8_t wmark_boundary_reached=false; 225bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee es_Q_data_now = viddec_fw_get_total_input_Q_data((uint32_t)cur); 226bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee wmark_boundary_reached = viddec_fw_check_watermark_boundary(es_Q_data_at_start, es_Q_data_now, cxt_swap->low_watermark); 227bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee _dmem.int_status[cur].status = 0; 228bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if(pushed_a_workload) 229bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 230bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee _dmem.int_status[cur].status |= VIDDEC_FW_WKLD_DATA_AVAIL; 231bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 232bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if(wmark_boundary_reached) 233bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 234bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee _dmem.int_status[cur].status |= VIDDEC_FW_INPUT_WATERMARK_REACHED; 235bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 236bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee cxt_swap->pending_interrupt = ( _dmem.int_status[cur].status != 0); 237bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 238bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 239bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee else 240bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 241bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee cxt_swap->pending_interrupt = false; 242bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 243bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee} 244bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 245bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline void viddec_fw_handle_error_and_inband_messages(int32_t cur, uint32_t pm_ret) 246bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{ 247bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee FW_IPC_Handle *fwipc = GET_IPC_HANDLE(_dmem); 248bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 249bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee viddec_fw_push_current_frame_to_output(fwipc, cur); 250bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee switch(pm_ret) 251bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 252bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee case PM_EOS: 253bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee case PM_OVERFLOW: 254bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 255bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee viddec_fw_init_swap_memory(cur, false, true); 256bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 257bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee break; 258bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee case PM_DISCONTINUITY: 259bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 260bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee viddec_fw_init_swap_memory(cur, false, false); 261bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 262bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee break; 263bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee default: 264bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee break; 265bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 266bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee} 267bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 268bd8388b4555645b3d29abc6a94c303638064d69awonjong.leevoid viddec_fw_debug_scheduled_stream_state(int32_t indx, int32_t start) 269bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{ 270bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee FW_IPC_Handle *fwipc = GET_IPC_HANDLE(_dmem); 271bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee uint32_t inpt_avail=0, output_avail=0, wklds_avail =0 , pos; 272bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee FW_IPC_ReceiveQue *rcv_q; 273bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee uint32_t message; 274bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 275bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee message = (start) ? SVEN_MODULE_EVENT_GV_FW_PK_SCHDL_STRM_START: SVEN_MODULE_EVENT_GV_FW_PK_SCHDL_STRM_END; 276bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee rcv_q = &fwipc->rcv_q[indx]; 277bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee inpt_avail = ipc_mq_read_avail(&rcv_q->mq, (int32_t *)&pos); 278bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee inpt_avail += ((_dmem.stream_info[indx].buffered_data > 0) ? CONFIG_IPC_MESSAGE_MAX_SIZE: 0); 279bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee inpt_avail = inpt_avail >> 4; 280bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee pos = 0; 281bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee output_avail = ipc_mq_read_avail(&fwipc->snd_q[indx].mq, (int32_t *)&pos); 282bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee output_avail = output_avail >> 4; 283bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee pos = 0; 284bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee wklds_avail = ipc_mq_read_avail(&fwipc->wkld_q[indx].mq, (int32_t *)&pos); 285bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee wklds_avail = wklds_avail >> 4; 286bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee WRITE_SVEN(message, (int)indx, (int)inpt_avail, (int)output_avail, 287bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee (int)wklds_avail, 0, 0); 288bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee} 289bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 290bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------ 291bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function: viddec_fw_process_async_queues(A.K.A -> Parser Kernel) 292bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This function is responsible for handling the asynchronous queues. 293bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * 294bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * The first step is to figure out which stream to run. The current algorithm 295bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * will go through all high priority queues for a valid stream, if not found we 296bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * go through lower priority queues. 297bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * 298bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * If a valid stream is found we swap the required context from DDR to DMEM and do all necessary 299bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * things to setup the stream. 300bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Once a stream is setup we call the parser manager and wait until a wrkld is created or no more input 301bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * data left. 302bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Once we find a wkld we push it to host and save the current context to DDR. 303bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------ 304bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */ 305bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 306bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline int32_t viddec_fw_process_async_queues() 307bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{ 308bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee int32_t cur = -1; 309bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 310bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee cur = viddec_fw_get_next_stream_to_schedule(); 311bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 312bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if(cur != -1) 313bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 314bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee FW_IPC_Handle *fwipc = GET_IPC_HANDLE(_dmem); 315bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee FW_IPC_ReceiveQue *rcv_q; 316bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* bits captured by OMAR */ 317bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee output_omar_wires( 0x0 ); 318bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee rcv_q = &fwipc->rcv_q[cur]; 319bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 320bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee mfd_pk_strm_cxt *cxt; 321bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee mfd_stream_info *cxt_swap; 322bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee cxt = (mfd_pk_strm_cxt *)&(_dmem.srm_cxt); 323bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee cxt_swap = (mfd_stream_info *)&(_dmem.stream_info[cur]); 324bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 325bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* Step 1: Swap rodata to local memory. Not doing this currently as all the rodata fits in local memory. */ 326bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee {/* Step 2: Swap context into local memory */ 327bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee cp_using_dma(cxt_swap->ddr_cxt, (uint32_t) &(cxt->pm), sizeof(viddec_pm_cxt_t), false, false); 328bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 329bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* Step 3:setup emitter by reading input data and workloads and initialising it */ 330bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee mfd_setup_emitter(fwipc, &fwipc->wkld_q[cur], cxt); 331bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee viddec_fw_debug_scheduled_stream_state(cur, true); 332bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* Step 4: Call Parser Manager until workload done or No more ES buffers */ 333bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 334bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee ipc_msg_data *data = 0; 335bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee uint8_t stream_active = true, pushed_a_workload=false; 336bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee uint32_t pm_ret = PM_SUCCESS, es_Q_data_at_start; 337bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee uint32_t start_time, time=0; 338bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 339bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee start_time = set_wdog(VIDDEC_WATCHDOG_COUNTER_MAX); 340bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee timer=0; 341bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee es_Q_data_at_start = viddec_fw_get_total_input_Q_data((uint32_t)cur); 342bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee do 343bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 344bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee output_omar_wires( 0x1 ); 345bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 346bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee uint32_t es_t0,es_t1; 347bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee get_wdog(&es_t0); 348bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee pm_ret = viddec_pm_parse_es_buffer(&(cxt->pm), cxt_swap->strm_type, data); 349bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee get_wdog(&es_t1); 350bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee cxt_swap->es_time += get_total_ticks(es_t0, es_t1); 351bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 352bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee switch(pm_ret) 353bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 354bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee case PM_EOS: 355bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee case PM_WKLD_DONE: 356bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee case PM_OVERFLOW: 357bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee case PM_DISCONTINUITY: 358bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee {/* Finished a frame worth of data or encountered fatal error*/ 359bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee stream_active = false; 360bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 361bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee break; 362bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee case PM_NO_DATA: 363bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 364bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee uint32_t next_ret=0; 365bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if ( (NULL != data) && (0 != cxt_swap->es_time) ) 366bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 367bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* print performance info for this buffer */ 368bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee WRITE_SVEN(SVEN_MODULE_EVENT_GV_FW_PK_ES_DONE, (int)cur, (int)cxt_swap->es_time, (int)cxt->input.phys, 369bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee (int)cxt->input.len, (int)cxt->input.id, (int)cxt->input.flags ); 370bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee cxt_swap->es_time = 0; 371bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 372bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 373bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee next_ret = FwIPC_ReadMessage(fwipc, rcv_q, (char *)&(cxt->input), sizeof(ipc_msg_data)); 374bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if(next_ret != 0) 375bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 376bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee data = &(cxt->input); 377bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee WRITE_SVEN(SVEN_MODULE_EVENT_GV_FW_PK_ES_START, (int)cur, (int)cxt_swap->wl_time, 378bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee (int)cxt->input.phys, (int)cxt->input.len, (int)cxt->input.id, (int)cxt->input.flags ); 379bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 380bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee else 381bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee {/* No data on input queue */ 382bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee cxt_swap->buffered_data = 0; 383bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee stream_active = false; 384bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 385bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 386bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee break; 387bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee default: 388bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee {/* Not done with current buffer */ 389bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee data = NULL; 390bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 391bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee break; 392bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 393bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee }while(stream_active); 394bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee get_wdog(&time); 395bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee cxt_swap->wl_time += get_total_ticks(start_time, time); 396bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* Step 5: If workload done push workload out */ 397bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee switch(pm_ret) 398bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 399bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee case PM_EOS: 400bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee case PM_WKLD_DONE: 401bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee case PM_OVERFLOW: 402bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee case PM_DISCONTINUITY: 403bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee {/* Push current workload as we are done with the frame */ 404bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee cxt_swap->buffered_data = (PM_WKLD_DONE == pm_ret) ? true: false; 405bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee viddec_pm_update_time(&(cxt->pm), cxt_swap->wl_time); 406bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 407bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* xmit performance info for this workload output */ 408bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee WRITE_SVEN( SVEN_MODULE_EVENT_GV_FW_PK_WL_DONE, (int)cur, (int)cxt_swap->wl_time, (int)cxt->wkld1.phys, 409bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee (int)cxt->wkld1.len, (int)cxt->wkld1.id, (int)cxt->wkld1.flags ); 410bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee cxt_swap->wl_time = 0; 411bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 412bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee viddec_fw_push_current_frame_to_output(fwipc, cur); 413bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if(pm_ret != PM_WKLD_DONE) 414bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 415bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee viddec_fw_handle_error_and_inband_messages(cur, pm_ret); 416bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 417bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee pushed_a_workload = true; 418bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 419bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee break; 420bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee default: 421bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee break; 422bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 423bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* Update information on whether we have active interrupt for this stream */ 424bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee viddec_fw_update_pending_interrupt_flag(cur, cxt_swap, pushed_a_workload, es_Q_data_at_start); 425bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 426bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee viddec_fw_debug_scheduled_stream_state(cur, false); 427bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* Step 6: swap context into DDR */ 428bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 429bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee cp_using_dma(cxt_swap->ddr_cxt, (uint32_t) &(cxt->pm), sizeof(viddec_pm_cxt_t), true, false); 430bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 431bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 432bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 433bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 434bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee return cur; 435bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee} 436bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 437bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 438bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------ 439bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function: process_command 440bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This magic function figures out which function to excute based on autoapi. 441bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------ 442bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */ 443bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 444bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline void process_command(uint32_t cmd_id, unsigned char *command) 445bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{ 446bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee int32_t groupid = ((cmd_id >> 24) - 13) & 0xff; 447bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee int32_t funcid = cmd_id & 0xffffff; 448bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* writing func pointer to hsot doorbell */ 449bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee output_omar_wires( (int) viddec_fw_api_array[groupid].unmarshal[funcid] ); 450bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee WRITE_SVEN( SVEN_MODULE_EVENT_GV_FW_AUTOAPI_CMD,(int) cmd_id, (int) command, ((int *)command)[0], 451bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee ((int *)command)[1], ((int *)command)[2], ((int *)command)[3] ); 452bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 453bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee viddec_fw_api_array[groupid].unmarshal[funcid](0, command); 454bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 455bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee} 456bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 457bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------ 458bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function: viddec_fw_process_sync_queues(A.K.A auto api) 459bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Params: 460bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * [in] msg: common sync structure where all required parameters are present for autoapi. 461bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * 462bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This function is responsible for handling synchronous messages. All synchronous messages 463bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * are handled through auto api. 464bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * what are synchronous messages? Anything releated to teardown or opening a stream Ex: open, close, flush etc. 465bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * 466bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Only once synchronous message at a time. When a synchronous message its id is usually in cp doorbell. Once 467bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * we are done handling synchronous message through auto api we release doorbell to let the host write next 468bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * message. 469bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------ 470bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */ 471bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 472bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline int32_t viddec_fw_process_sync_queues(unsigned char *msg) 473bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{ 474bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee int32_t ret = -1; 475bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 476bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if(0 == reg_read(CONFIG_IPC_ROFF_RISC_DOORBELL_STATUS)) 477bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 478bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee uint32_t command1=0; 479bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee command1 = reg_read(CONFIG_IPC_ROFF_RISC_RX_DOORBELL); 480bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee process_command(command1, msg); 481bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee reg_write(CONFIG_IPC_ROFF_RISC_DOORBELL_STATUS, 0x2); /* Inform Host we are done with this message */ 482bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee ret = 0; 483bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 484bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee return ret; 485bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee} 486bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 487bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------ 488bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function: viddec_fw_check_for_pending_int 489bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This function walks through all active streams to see if atleast one stream has a pending interrupt 490bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * and returns true if it finds one. 491bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------ 492bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */ 493bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline uint32_t viddec_fw_check_for_pending_int(void) 494bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{ 495bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee uint32_t i=0, ret=false; 496bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* start from 0 to max streams that fw can handle*/ 497bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee while(i < FW_SUPPORTED_STREAMS) 498bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 499bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if(_dmem.stream_info[i].state == 1) 500bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 501bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if((_dmem.stream_info[i].pending_interrupt) && _dmem.int_status[i].mask) 502bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 503bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee ret = true; 504bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 505bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee else 506bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee {/* If this is not in INT state clear the status before sending it to host */ 507bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee _dmem.int_status[i].status = 0; 508bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 509bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 510bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee i++; 511bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 512bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee return ret; 513bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee} 514bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 515bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------ 516bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function: viddec_fw_clear_processed_int 517bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This function walks through all active streams to clear pending interrupt state.This is 518bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * called after a INT was issued. 519bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------ 520bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */ 521bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline void viddec_fw_clear_processed_int(void) 522bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{ 523bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee uint32_t i=0; 524bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* start from 0 to max streams that fw can handle*/ 525bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee while(i < FW_SUPPORTED_STREAMS) 526bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 527bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee //if(_dmem.stream_info[i].state == 1) 528bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee _dmem.stream_info[i].pending_interrupt = false; 529bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee i++; 530bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 531bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee return; 532bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee} 533bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 534bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------ 535bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function: viddec_fw_int_host 536bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This function interrupts host if data is available for host or any other status 537bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * is valid which the host configures the FW to. 538bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * There is only one interrupt line so this is a shared Int for all streams, Host should 539bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * look at status of all streams when it receives a Int. 540bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * The FW will interrupt the host only if host doorbell is free, in other words the host 541bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * should always make the doorbell free at the End of its ISR. 542bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------ 543bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */ 544bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 545bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline int32_t viddec_fw_int_host() 546bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{ 547bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* We Interrupt the host only if host is ready to receive an interrupt */ 548bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if((reg_read(CONFIG_IPC_ROFF_HOST_DOORBELL_STATUS) & GV_DOORBELL_STATS) == GV_DOORBELL_STATS) 549bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 550bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if(viddec_fw_check_for_pending_int()) 551bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 552bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* If a pending interrupt is found trigger INT */ 553bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee reg_write(CONFIG_IPC_ROFF_HOST_DOORBELL, VIDDEC_FW_PARSER_IPC_HOST_INT); 554bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* Clear all stream's pending Interrupt info since we use a global INT for all streams */ 555bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee viddec_fw_clear_processed_int(); 556bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 557bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 558bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee return 1; 559bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee} 560bd8388b4555645b3d29abc6a94c303638064d69awonjong.leevolatile unsigned int stack_corrupted __attribute__ ((section (".stckovrflwchk"))); 561bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------ 562bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function: main 563bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This function is the main firmware function. Its a infinite loop where it polls 564bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * for messages and processes them if they are available. Currently we ping pong between 565bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * synchronous and asynchronous messages one at a time. If we have multiple aysnchronous 566bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * queues we always process only one between synchronous messages. 567bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * 568bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * For multiple asynchronous queues we round robin through the high priorities first and pick 569bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * the first one available. Next time when we come around for asynchronous message we start 570bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * from the next stream onwards so this guarantees that we give equal time slices for same 571bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * priority queues. If no high priority queues are active we go to low priority queues and repeat 572bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * the same process. 573bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------ 574bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */ 575bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 576bd8388b4555645b3d29abc6a94c303638064d69awonjong.leeint main(void) 577bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{ 578bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee unsigned char *msg = (uint8_t *)&(_dmem.buf.data[0]); 579bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 580bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* We wait until host reads sync message */ 581bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee reg_write(CONFIG_IPC_ROFF_HOST_RX_DOORBELL, GV_FW_IPC_HOST_SYNC); 582bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee 583bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee while ( GV_DOORBELL_STATS != reg_read(CONFIG_IPC_ROFF_HOST_DOORBELL_STATUS) ) 584bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { /*poll register until done bit is set */ 585bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* Host re-writes Vsparc DRAM (BSS) in this loop and will hit the DONE bit when complete */ 586bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 587bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee enable_intr(); 588bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee /* Initialize State for queues */ 589bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee viddec_fw_parser_register_callbacks(); 590bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee FwIPC_Initialize(GET_IPC_HANDLE(_dmem), (volatile char *)msg); 591bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee _dmem.g_pk_data.high_id = _dmem.g_pk_data.low_id = -1; 592bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee viddec_pm_init_ops(); 593bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee stack_corrupted = 0xDEADBEEF; 594bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee while(1) 595bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 596bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee viddec_fw_process_sync_queues(msg); 597bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee viddec_fw_process_async_queues(); 598bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee viddec_fw_int_host(); 599bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee#if 0 600bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee if(stack_corrupted != 0xDEADBEEF) 601bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee { 602bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee WRITE_SVEN(SVEN_MODULE_EVENT_GV_FW_FATAL_STACK_CORRPON, 0, 0, 0, 0, 0, 0); 603bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee while(1); 604bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 605bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee#endif 606bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee } 607bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee return 1; 608bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee} 609