int32_t cmdq_rec_finalize_command(cmdqRecHandle handle, bool loop) { int32_t status = 0; uint32_t argB = 0; if (!handle->finalized) { if ((handle->prefetchCount > 0) && cmdq_core_should_enable_prefetch(handle->scenario)) { CMDQ_ERR("not insert prefetch disble marker when prefetch enabled, prefetchCount:%d\n", handle->prefetchCount); cmdqRecDumpCommand(handle); status = -EFAULT; return status; } /* insert EOF instruction */ argB = 0x1; /* generate IRQ for each command iteration */ status = cmdq_append_command(handle, CMDQ_CODE_EOC, 0, argB, 0, 0); if (0 != status) { return status; } /* insert JUMP to loop to beginning or as a scheduling mark(8) */ status = cmdq_append_command(handle, CMDQ_CODE_JUMP, 0, /* not absolute */ loop ? -handle->blockSize : 8, 0, 0); if (0 != status) { return status; } handle->finalized = true; } return status; }
static void _cmdq_build_trigger_loop(void) { int ret = 0; cmdqRecCreate(CMDQ_SCENARIO_TRIGGER_LOOP, &(pgc->cmdq_handle_trigger)); EXT_DISP_LOG("ext_disp path trigger thread cmd handle=%p\n", pgc->cmdq_handle_trigger); cmdqRecReset(pgc->cmdq_handle_trigger); if(ext_disp_is_video_mode()) { // wait and clear stream_done, HW will assert mutex enable automatically in frame done reset. // todo: should let dpmanager to decide wait which mutex's eof. ret = cmdqRecWait(pgc->cmdq_handle_trigger, dpmgr_path_get_mutex(pgc->dpmgr_handle) + CMDQ_EVENT_MUTEX0_STREAM_EOF); ///dpmgr_path_get_mutex(pgc->dpmgr_handle) // for some module(like COLOR) to read hw register to GPR after frame done dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger,CMDQ_AFTER_STREAM_EOF); } else { // DSI command mode doesn't have mutex_stream_eof, need use CMDQ token instead ret = cmdqRecWait(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_CONFIG_DIRTY); //ret = cmdqRecWait(pgc->cmdq_handle_trigger, CMDQ_EVENT_MDP_DSI0_TE_SOF); // for operations before frame transfer, such as waiting for DSI TE dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger,CMDQ_BEFORE_STREAM_SOF); // cleat frame done token, now the config thread will not allowed to config registers. // remember that config thread's priority is higher than trigger thread, so all the config queued before will be applied then STREAM_EOF token be cleared // this is what CMDQ did as "Merge" ret = cmdqRecClearEventToken(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_STREAM_EOF); // enable mutex, only cmd mode need this // this is what CMDQ did as "Trigger" dpmgr_path_trigger(pgc->dpmgr_handle, pgc->cmdq_handle_trigger, CMDQ_ENABLE); //ret = cmdqRecWrite(pgc->cmdq_handle_trigger, (unsigned int)(DISP_REG_CONFIG_MUTEX_EN(0))&0x1fffffff, 1, ~0); // waiting for frame done, because we can't use mutex stream eof here, so need to let dpmanager help to decide which event to wait // most time we wait rdmax frame done event. ret = cmdqRecWait(pgc->cmdq_handle_trigger, CMDQ_EVENT_DISP_RDMA1_EOF); dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger,CMDQ_WAIT_STREAM_EOF_EVENT); // dsi is not idle rightly after rdma frame done, so we need to polling about 1us for dsi returns to idle // do not polling dsi idle directly which will decrease CMDQ performance dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger,CMDQ_CHECK_IDLE_AFTER_STREAM_EOF); // for some module(like COLOR) to read hw register to GPR after frame done dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_trigger,CMDQ_AFTER_STREAM_EOF); // polling DSI idle //ret = cmdqRecPoll(pgc->cmdq_handle_trigger, 0x1401b00c, 0, 0x80000000); // polling wdma frame done //ret = cmdqRecPoll(pgc->cmdq_handle_trigger, 0x140060A0, 1, 0x1); // now frame done, config thread is allowed to config register now ret = cmdqRecSetEventToken(pgc->cmdq_handle_trigger, CMDQ_SYNC_TOKEN_STREAM_EOF); // RUN forever!!!! BUG_ON(ret < 0); } // dump trigger loop instructions to check whether dpmgr_path_build_cmdq works correctly cmdqRecDumpCommand(pgc->cmdq_handle_trigger); EXT_DISP_LOG("ext display BUILD cmdq trigger loop finished\n"); return; }