| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- #include <linux/delay.h>
- #include <linux/sched.h>
- #include <linux/semaphore.h>
- #include <linux/module.h>
- #include <linux/wait.h>
- #include <linux/kthread.h>
- #include <linux/mutex.h>
- #include "debug.h"
- #include "disp_drv_log.h"
- #include "disp_utils.h"
- #include "ddp_dump.h"
- #include "ddp_path.h"
- #include "ddp_drv.h"
- #include "ddp_ovl.h"
- #include "disp_session.h"
- #include "primary_display.h"
- #include "m4u.h"
- #include "cmdq_def.h"
- #include "cmdq_record.h"
- #include "cmdq_reg.h"
- #include "cmdq_core.h"
- #include "ddp_manager.h"
- #include "disp_drv_platform.h"
- #include "display_recorder.h"
- /* #include "ddp_mmp.h" */
- #include "mtk_ovl.h"
- #include "mtkfb_fence.h"
- #include <asm/atomic.h>
- static int ovl2mem_layer_num;
- int ovl2mem_use_m4u = 1;
- int ovl2mem_use_cmdq = CMDQ_ENABLE;
- typedef struct {
- int state;
- unsigned int session;
- unsigned int lcm_fps;
- int max_layer;
- int need_trigger_path;
- struct mutex lock;
- cmdqRecHandle cmdq_handle_config;
- cmdqRecHandle cmdq_handle_trigger;
- disp_path_handle dpmgr_handle;
- const char *mutex_locker;
- } ovl2mem_path_context;
- atomic_t g_trigger_ticket = ATOMIC_INIT(1);
- atomic_t g_release_ticket = ATOMIC_INIT(1);
- #define pgc _get_context()
- static ovl2mem_path_context *_get_context(void)
- {
- static int is_context_inited;
- static ovl2mem_path_context g_context;
- if (!is_context_inited) {
- memset((void *)&g_context, 0, sizeof(ovl2mem_path_context));
- is_context_inited = 1;
- }
- return &g_context;
- }
- CMDQ_SWITCH ovl2mem_cmdq_enabled(void)
- {
- return ovl2mem_use_cmdq;
- }
- static void _ovl2mem_path_lock(const char *caller)
- {
- dprec_logger_start(DPREC_LOGGER_PRIMARY_MUTEX, 0, 0);
- disp_sw_mutex_lock(&(pgc->lock));
- pgc->mutex_locker = caller;
- }
- static void _ovl2mem_path_unlock(const char *caller)
- {
- pgc->mutex_locker = NULL;
- disp_sw_mutex_unlock(&(pgc->lock));
- dprec_logger_done(DPREC_LOGGER_PRIMARY_MUTEX, 0, 0);
- }
- void ovl2mem_setlayernum(int layer_num)
- {
- ovl2mem_layer_num = layer_num;
- DISPERR("ovl2mem_setlayernum: %d\n", ovl2mem_layer_num);
- }
- int ovl2mem_get_info(void *info)
- {
- /* /DISPFUNC(); */
- disp_session_info *dispif_info = (disp_session_info *) info;
- memset((void *)dispif_info, 0, sizeof(disp_session_info));
- /* FIXME, for decouple mode, should dynamic return 4 or 8, please refer to primary_display_get_info() */
- dispif_info->maxLayerNum = ovl2mem_layer_num;
- dispif_info->displayType = DISP_IF_TYPE_DPI;
- dispif_info->displayMode = DISP_IF_MODE_VIDEO;
- dispif_info->isHwVsyncAvailable = 1;
- dispif_info->displayFormat = DISP_IF_FORMAT_RGB888;
- dispif_info->displayWidth = primary_display_get_width();
- dispif_info->displayHeight = primary_display_get_height();
- dispif_info->vsyncFPS = pgc->lcm_fps;
- if (dispif_info->displayWidth * dispif_info->displayHeight <= 240 * 432)
- dispif_info->physicalHeight = dispif_info->physicalWidth = 0;
- else if (dispif_info->displayWidth * dispif_info->displayHeight <= 320 * 480)
- dispif_info->physicalHeight = dispif_info->physicalWidth = 0;
- else if (dispif_info->displayWidth * dispif_info->displayHeight <= 480 * 854)
- dispif_info->physicalHeight = dispif_info->physicalWidth = 0;
- else
- dispif_info->physicalHeight = dispif_info->physicalWidth = 0;
- dispif_info->isConnected = 1;
- return 0;
- }
- static int _convert_disp_input_to_ovl(OVL_CONFIG_STRUCT *dst, primary_disp_input_config *src)
- {
- if (src && dst) {
- dst->layer = src->layer;
- dst->layer_en = src->layer_en;
- dst->source = src->buff_source;
- dst->fmt = src->fmt;
- dst->addr = src->addr;
- dst->vaddr = src->vaddr;
- dst->src_x = src->src_x;
- dst->src_y = src->src_y;
- dst->src_w = src->src_w;
- dst->src_h = src->src_h;
- dst->src_pitch = src->src_pitch;
- dst->dst_x = src->dst_x;
- dst->dst_y = src->dst_y;
- dst->dst_w = src->dst_w;
- dst->dst_h = src->dst_h;
- dst->keyEn = src->keyEn;
- dst->key = src->key;
- dst->aen = src->aen;
- dst->alpha = src->alpha;
- dst->sur_aen = src->sur_aen;
- dst->src_alpha = src->src_alpha;
- dst->dst_alpha = src->dst_alpha;
- dst->isDirty = src->isDirty;
- dst->buff_idx = src->buff_idx;
- dst->identity = src->identity;
- dst->connected_type = src->connected_type;
- dst->security = src->security;
- dst->yuv_range = src->yuv_range;
- return 0;
- }
- DISPERR("src(%p) or dst(%p) is null\n", src, dst);
- return -1;
- }
- static int ovl2mem_callback(unsigned int userdata)
- {
- int fence_idx = 0;
- int layid = 0;
- DISPMSG("ovl2mem_callback(%x), current tick=%d, release tick: %d\n", pgc->session,
- get_ovl2mem_ticket(), userdata);
- for (layid = 0; layid < (HW_OVERLAY_COUNT + 1); layid++) {
- fence_idx = mtkfb_query_idx_by_ticket(pgc->session, layid, userdata);
- if (fence_idx >= 0) {
- disp_ddp_path_config *data_config = dpmgr_path_get_last_config(pgc->dpmgr_handle);
- WDMA_CONFIG_STRUCT wdma_layer;
- wdma_layer.dstAddress = 0;
- if (data_config && (layid >= HW_OVERLAY_COUNT)) {
- wdma_layer.dstAddress = mtkfb_query_buf_mva(pgc->session, layid, fence_idx);
- wdma_layer.outputFormat = data_config->wdma_config.outputFormat;
- wdma_layer.srcWidth = data_config->wdma_config.srcWidth;
- wdma_layer.srcHeight = data_config->wdma_config.srcHeight;
- wdma_layer.dstPitch = data_config->wdma_config.dstPitch;
- DISPMSG("mem_seq %x-seq+ %d\n", pgc->session,
- mtkfb_query_frm_seq_by_addr(pgc->session, layid,
- wdma_layer.dstAddress));
- dprec_logger_frame_seq_end(pgc->session,
- mtkfb_query_frm_seq_by_addr(pgc->session,
- layid,
- wdma_layer.
- dstAddress));
- dprec_mmp_dump_wdma_layer(&wdma_layer, 1);
- }
- mtkfb_release_fence(pgc->session, layid, fence_idx);
- }
- }
- atomic_set(&g_release_ticket, userdata);
- return 0;
- }
- int get_ovl2mem_ticket(void)
- {
- return atomic_read(&g_trigger_ticket);
- }
- int ovl2mem_input_config(ovl2mem_in_config *input)
- {
- int ret = -1;
- int i = 0;
- disp_ddp_path_config *data_config;
- DISPFUNC();
- _ovl2mem_path_lock(__func__);
- /* all dirty should be cleared in dpmgr_path_get_last_config() */
- data_config = dpmgr_path_get_last_config(pgc->dpmgr_handle);
- data_config->dst_dirty = 0;
- data_config->ovl_dirty = 0;
- data_config->rdma_dirty = 0;
- if (pgc->state == 0) {
- DISPMSG("ovl2mem is already slept\n");
- _ovl2mem_path_unlock(__func__);
- return 0;
- }
- /* hope we can use only 1 input struct for input config, just set layer number */
- for (i = 0; i < HW_OVERLAY_COUNT; i++) {
- dprec_logger_start(DPREC_LOGGER_PRIMARY_CONFIG,
- input->layer | (input->layer_en << 16), input->addr);
- if (input[i].layer_en) {
- if (input[i].vaddr)
- /* / _debug_pattern(0x00000000, input[i].vaddr, input[i].dst_w, input[i].dst_h,
- input[i].src_pitch, 0x00000000, input[i].layer, input[i].buff_idx);
- */
- ;
- else
- /* /_debug_pattern(input[i].addr,0x00000000, input[i].dst_w, input[i].dst_h,
- input[i].src_pitch, 0x00000000, input[i].layer, input[i].buff_idx);
- */
- ;
- }
- /* /DISPMSG("[primary], i:%d, layer:%d, layer_en:%d, dirty:%d -0x%x\n",
- i, input[i].layer, input[i].layer_en, input[i].dirty, input[i].addr);
- */
- if (input[i].dirty)
- ret = _convert_disp_input_to_ovl(&(data_config->ovl_config[input[i].layer]),
- (primary_disp_input_config *)&input[i]);
- data_config->ovl_dirty = 1;
- dprec_logger_done(DPREC_LOGGER_PRIMARY_CONFIG, input->src_x, input->src_y);
- }
- if (dpmgr_path_is_busy(pgc->dpmgr_handle))
- dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_COMPLETE, HZ / 5);
- ret = dpmgr_path_config(pgc->dpmgr_handle, data_config, pgc->cmdq_handle_config);
- _ovl2mem_path_unlock(__func__);
- DISPMSG("ovl2mem_input_config done\n");
- return ret;
- }
- int ovl2mem_output_config(disp_mem_output_config *out)
- {
- int ret = -1;
- disp_ddp_path_config *data_config;
- _ovl2mem_path_lock(__func__);
- /* all dirty should be cleared in dpmgr_path_get_last_config() */
- data_config = dpmgr_path_get_last_config(pgc->dpmgr_handle);
- data_config->dst_dirty = 1;
- data_config->dst_h = out->h;
- data_config->dst_w = out->w;
- data_config->ovl_dirty = 0;
- data_config->rdma_dirty = 0;
- data_config->wdma_dirty = 1;
- data_config->wdma_config.dstAddress = out->addr;
- data_config->wdma_config.srcHeight = out->h;
- data_config->wdma_config.srcWidth = out->w;
- data_config->wdma_config.clipX = out->x;
- data_config->wdma_config.clipY = out->y;
- data_config->wdma_config.clipHeight = out->h;
- data_config->wdma_config.clipWidth = out->w;
- data_config->wdma_config.outputFormat = out->fmt;
- data_config->wdma_config.dstPitch = out->pitch;
- data_config->wdma_config.useSpecifiedAlpha = 1;
- data_config->wdma_config.alpha = 0xFF;
- data_config->wdma_config.security = out->security;
- if (pgc->state == 0) {
- DISPMSG("ovl2mem is already slept\n");
- _ovl2mem_path_unlock(__func__);
- return 0;
- }
- if (dpmgr_path_is_busy(pgc->dpmgr_handle))
- dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_DONE, HZ / 5);
- ret = dpmgr_path_config(pgc->dpmgr_handle, data_config, pgc->cmdq_handle_config);
- pgc->need_trigger_path = 1;
- _ovl2mem_path_unlock(__func__);
- /* /DISPMSG("ovl2mem_output_config done\n"); */
- return ret;
- }
- int ovl2mem_trigger(int blocking, void *callback, unsigned int userdata)
- {
- int ret = -1;
- int fence_idx = 0;
- int layid = 0;
- DISPFUNC();
- if (pgc->need_trigger_path == 0) {
- DISPMSG("ovl2mem_trigger do not trigger\n");
- if ((atomic_read(&g_trigger_ticket) - atomic_read(&g_release_ticket)) == 1) {
- DISPMSG("ovl2mem_trigger(%x), configue input, but does not config output!!\n", pgc->session);
- for (layid = 0; layid < (HW_OVERLAY_COUNT + 1); layid++) {
- fence_idx = mtkfb_query_idx_by_ticket(pgc->session, layid,
- atomic_read(&g_trigger_ticket));
- if (fence_idx >= 0)
- mtkfb_release_fence(pgc->session, layid, fence_idx);
- }
- }
- return ret;
- }
- _ovl2mem_path_lock(__func__);
- dpmgr_path_start(pgc->dpmgr_handle, ovl2mem_cmdq_enabled());
- dpmgr_path_trigger(pgc->dpmgr_handle, pgc->cmdq_handle_config, ovl2mem_cmdq_enabled());
- cmdqRecWait(pgc->cmdq_handle_config, CMDQ_EVENT_DISP_WDMA1_EOF);
- dpmgr_path_stop(pgc->dpmgr_handle, ovl2mem_cmdq_enabled());
- /* /cmdqRecDumpCommand(pgc->cmdq_handle_config); */
- cmdqRecFlushAsyncCallback(pgc->cmdq_handle_config, (CmdqAsyncFlushCB)ovl2mem_callback,
- atomic_read(&g_trigger_ticket));
- cmdqRecReset(pgc->cmdq_handle_config);
- pgc->need_trigger_path = 0;
- atomic_add(1, &g_trigger_ticket);
- _ovl2mem_path_unlock(__func__);
- dprec_logger_frame_seq_begin(pgc->session, mtkfb_query_frm_seq_by_addr(pgc->session, 0, 0));
- DISPMSG("ovl2mem_trigger ovl2mem_seq %d-seq %d\n", get_ovl2mem_ticket(),
- mtkfb_query_frm_seq_by_addr(pgc->session, 0, 0));
- return ret;
- }
- void ovl2mem_wait_done(void)
- {
- int loop_cnt = 0;
- if ((atomic_read(&g_trigger_ticket) - atomic_read(&g_release_ticket)) <= 1)
- return;
- DISPFUNC();
- while ((atomic_read(&g_trigger_ticket) - atomic_read(&g_release_ticket)) > 1) {
- dpmgr_wait_event_timeout(pgc->dpmgr_handle, DISP_PATH_EVENT_FRAME_COMPLETE,
- HZ / 30);
- if (loop_cnt > 5)
- break;
- loop_cnt++;
- }
- DISPMSG("ovl2mem_wait_done loop %d, trigger tick:%d, release tick:%d\n", loop_cnt,
- atomic_read(&g_trigger_ticket), atomic_read(&g_release_ticket));
- }
- int ovl2mem_deinit(void)
- {
- int ret = -1;
- DISPFUNC();
- _ovl2mem_path_lock(__func__);
- if (pgc->state == 0)
- goto Exit;
- ovl2mem_wait_done();
- dpmgr_path_stop(pgc->dpmgr_handle, CMDQ_DISABLE);
- dpmgr_path_reset(pgc->dpmgr_handle, CMDQ_DISABLE);
- dpmgr_path_deinit(pgc->dpmgr_handle, CMDQ_DISABLE);
- dpmgr_destroy_path(pgc->dpmgr_handle, NULL);
- cmdqRecDestroy(pgc->cmdq_handle_config);
- pgc->dpmgr_handle = NULL;
- pgc->cmdq_handle_config = NULL;
- pgc->state = 0;
- pgc->need_trigger_path = 0;
- atomic_set(&g_trigger_ticket, 1);
- atomic_set(&g_release_ticket, 1);
- ovl2mem_layer_num = 0;
- Exit:
- _ovl2mem_path_unlock(__func__);
- DISPMSG("ovl2mem_deinit done\n");
- return ret;
- }
|