#define LOG_TAG "ddp_path" #include "ddp_log.h" #include #include #include #include "ddp_reg.h" #include "disp_drv_platform.h" #include "ddp_debug.h" #include "ddp_path.h" #include "primary_display.h" #include "ddp_hal.h" #include "m4u.h" #pragma GCC optimize("O0") int ddp_path_init() { // mout mout_map[0].reg = DISP_REG_CONFIG_DISP_OVL0_MOUT_EN; #if defined(MTK_FB_OVL1_SUPPORT) mout_map[1].reg = DISP_REG_CONFIG_DISP_OVL1_MOUT_EN; #endif mout_map[2].reg = DISP_REG_CONFIG_DISP_DITHER_MOUT_EN; mout_map[3].reg = DISP_REG_CONFIG_DISP_UFOE_MOUT_EN; // sel_out sel_out_map[0].reg = DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN; sel_out_map[1].reg = DISP_REG_CONFIG_DISP_RDMA1_SOUT_SEL_IN; // sel_in sel_in_map[0].reg = DISP_REG_CONFIG_DISP_COLOR0_SEL_IN; // COLOR_SEL sel_in_map[1].reg = DISP_REG_CONFIG_DISP_UFOE_SEL_IN; //UFOE_SEL sel_in_map[2].reg = DISP_REG_CONFIG_DSI0_SEL_IN; //DSI0_SEL sel_in_map[3].reg = DISP_REG_CONFIG_DPI0_SEL_IN; //DPI0_SEL sel_in_map[4].reg = DISP_REG_CONFIG_DISP_WDMA0_SEL_IN; // WDMA_SEL } char* ddp_get_scenario_name(DDP_SCENARIO_ENUM scenario) { switch(scenario) { case DDP_SCENARIO_PRIMARY_DISP: return "primary_disp"; case DDP_SCENARIO_PRIMARY_RDMA0_COLOR0_DISP: return "primary_rdma0_color0_disp"; case DDP_SCENARIO_PRIMARY_RDMA0_DISP: return "primary_rdma0_disp"; case DDP_SCENARIO_PRIMARY_BYPASS_RDMA: return "primary_bypass_rdma"; case DDP_SCENARIO_PRIMARY_OVL_MEMOUT: return "primary_ovl_memout"; case DDP_SCENARIO_PRIMARY_DITHER_MEMOUT: return "primary_dither_memout"; case DDP_SCENARIO_PRIMARY_UFOE_MEMOUT: return "primary_ufoe_memout"; case DDP_SCENARIO_SUB_DISP: return "sub_disp"; case DDP_SCENARIO_SUB_RDMA1_DISP: return "sub_rdma1_disp"; case DDP_SCENARIO_SUB_OVL_MEMOUT: return "sub_ovl_memout"; case DDP_SCENARIO_PRIMARY_ALL: return "primary_all"; case DDP_SCENARIO_SUB_ALL: return "sub_all"; case DDP_SCENARIO_MULTIPLE_OVL: return "multi_ovl"; default: DDPMSG("invalid scenario id=%d\n", scenario); return "unknown"; } } int ddp_is_scenario_on_primary(DDP_SCENARIO_ENUM scenario) { int on_primary = 0; switch(scenario) { case DDP_SCENARIO_PRIMARY_DISP: case DDP_SCENARIO_PRIMARY_RDMA0_COLOR0_DISP: case DDP_SCENARIO_PRIMARY_RDMA0_DISP: case DDP_SCENARIO_PRIMARY_BYPASS_RDMA: case DDP_SCENARIO_PRIMARY_OVL_MEMOUT: case DDP_SCENARIO_PRIMARY_DITHER_MEMOUT: case DDP_SCENARIO_PRIMARY_UFOE_MEMOUT: case DDP_SCENARIO_PRIMARY_ALL: case DDP_SCENARIO_MULTIPLE_OVL: on_primary = 1; break; case DDP_SCENARIO_SUB_DISP: case DDP_SCENARIO_SUB_RDMA1_DISP: case DDP_SCENARIO_SUB_OVL_MEMOUT: case DDP_SCENARIO_SUB_ALL: on_primary = 0; break; default: DDPMSG("invalid scenario id=%d\n", scenario); } return on_primary; } char* ddp_get_mutex_sof_name(MUTEX_SOF mode) { switch(mode) { case SOF_SINGLE : return "single"; case SOF_DSI0 : return "dsi0"; case SOF_DSI1 : return "dsi1"; case SOF_DPI0 : return "dpi0"; default: DDPMSG("invalid sof =%d\n", mode); return "unknown"; } } char* ddp_get_mode_name(DDP_MODE ddp_mode) { switch(ddp_mode) { case DDP_VIDEO_MODE : return "vido_mode"; case DDP_CMD_MODE : return "cmd_mode"; default: DDPMSG("invalid ddp mode =%d\n", ddp_mode); return "unknown"; } } static int ddp_get_module_num_l(int* module_list) { unsigned int num = 0; while(*(module_list+num)!=-1) { num++; if(num==DDP_ENING_NUM) break; } return num; } // config mout/msel to creat a compelte path static void ddp_connect_path_l(int *module_list, void * handle) { unsigned int i, j, k; int step=0; unsigned int mout=0; unsigned int reg_mout = 0; unsigned int mout_idx = 0; unsigned int module_num = ddp_get_module_num_l(module_list); DDPDBG("connect_path: %s to %s\n",ddp_get_module_name(module_list[0]), ddp_get_module_name(module_list[module_num-1])); // connect mout for(i = 0 ; i < module_num - 1 ; i++) { for(j = 0 ; j < DDP_MOUT_NUM ; j++) { if(module_list[i] == mout_map[j].id) { //find next module which can be connected step = i+1; while(module_can_connect[module_list[step]].bit==0 && step0) { step--; } ASSERT(step>=0); for(k = 0 ; k < 4 ; k++) { if(sel_in_map[j].id_bit_map[k] == -1) break; if(sel_in_map[j].id_bit_map[k] == module_list[step]) { DDPDBG("connect in_s %s to %s, bits=0x%x\n", ddp_get_module_name(module_list[step]), ddp_get_module_name(module_list[i]), k); DISP_REG_SET(handle,sel_in_map[j].reg, (kal_uint16)k); break; } } } } } } static void ddp_check_path_l(int *module_list) { unsigned int i, j, k; int step = 0; int valid =0; unsigned int mout; unsigned int path_error = 0; unsigned int module_num = ddp_get_module_num_l(module_list); DDPDUMP("check_path: %s to %s\n",ddp_get_module_name(module_list[0]) ,ddp_get_module_name(module_list[module_num-1])); // check mout for(i = 0 ; i < module_num - 1 ; i++) { for(j = 0 ; j < DDP_MOUT_NUM ; j++) { if(module_list[i] == mout_map[j].id) { mout = 0; //find next module which can be connected step = i+1; while(module_can_connect[module_list[step]].bit==0 && step0) { step--; } ASSERT(step>=0); for(k = 0 ; k < 4 ; k++) { if(sel_in_map[j].id_bit_map[k] == -1) break; if(sel_in_map[j].id_bit_map[k] == module_list[step]) { if(DISP_REG_GET(sel_in_map[j].reg) != k) { path_error += 1; DDPDUMP("error:in_s %s not connect to %s, expect=0x%x, real=0x%x \n", ddp_get_module_name(module_list[step]),ddp_get_module_name(module_list[i]), k, DISP_REG_GET(sel_in_map[j].reg)); } break; } } } } } if(path_error == 0) { DDPDUMP("path: %s to %s is connected\n",ddp_get_module_name(module_list[0]), ddp_get_module_name(module_list[module_num - 1])); } else { DDPDUMP("path: %s to %s not connected!!!\n",ddp_get_module_name(module_list[0]), ddp_get_module_name(module_list[module_num - 1])); } } static void ddp_disconnect_path_l(int *module_list,void * handle) { unsigned int i, j, k; int step = 0; unsigned int mout = 0; unsigned int reg_mout = 0; unsigned int mout_idx = 0; unsigned int module_num = ddp_get_module_num_l(module_list); DDPDBG("disconnect_path: %s to %s\n",ddp_get_module_name(module_list[0]), ddp_get_module_name(module_list[module_num-1])); for(i = 0 ; i < module_num - 1 ; i++) { for(j = 0 ; j < DDP_MOUT_NUM ; j++) { if(module_list[i] == mout_map[j].id) { //find next module which can be connected step = i+1; while(module_can_connect[module_list[step]].bit==0 && step DISP_MUTEX_DDP_LAST) { DDPERR("exceed mutex max (0 ~ %d)\n",DISP_MUTEX_DDP_LAST); return -1; } for(i = 0 ; i < module_num ; i++) { if(module_mutex_map[module_list[i]].bit != -1) { DDPDBG("module %s added to mutex %d\n",ddp_get_module_name(module_list[i]),mutex_id); value |= (1 << module_mutex_map[module_list[i]].bit); } else { DDPDBG("module %s not added to mutex %d\n",ddp_get_module_name(module_list[i]),mutex_id); } } DISP_REG_SET(handle,DISP_REG_CONFIG_MUTEX_MOD(mutex_id),value); DISP_REG_SET(handle,DISP_REG_CONFIG_MUTEX_SOF(mutex_id),mode); // for primary config thread, save more time for register config if(gEnableMutexRisingEdge==1 && primary_display_is_video_mode()==1 && mutex_id==0) { DISP_REG_SET_FIELD(handle, SOF_FLD_MUTEX0_SOF_TIMING, DISP_REG_CONFIG_MUTEX0_SOF, 1); } if(gEnableSWTrigger==1 && primary_display_is_video_mode()==1 && mutex_id==0) { // set OVL0/OVL1 to separate mutex DISP_REG_SET(handle,DISP_REG_CONFIG_MUTEX_MOD(DISP_OVL_SEPARATE_MUTEX_ID),value&((1 << module_mutex_map[DISP_MODULE_OVL0].bit)|(1 << module_mutex_map[DISP_MODULE_OVL1].bit))); DISP_REG_SET(handle,DISP_REG_CONFIG_MUTEX_SOF(DISP_OVL_SEPARATE_MUTEX_ID), SOF_SINGLE); // move OVL0/OVL1 out from primary path DISP_REG_SET(handle,DISP_REG_CONFIG_MUTEX_MOD(mutex_id),value&(~((1 << module_mutex_map[DISP_MODULE_OVL0].bit)|(1 << module_mutex_map[DISP_MODULE_OVL1].bit)))); } DDPDBG("mutex %d value=0x%x, sof=%s\n",mutex_id, value, ddp_get_mutex_sof_name(mode)); return 0; } static void ddp_check_mutex_l(int mutex_id, int* module_list, DDP_MODE ddp_mode) { int i=0; kal_uint32 real_value = 0; kal_uint32 expect_value = 0; kal_uint32 real_sof = 0; MUTEX_SOF expect_sof = SOF_SINGLE; int module_num = ddp_get_module_num_l(module_list); if(mutex_id < DISP_MUTEX_DDP_FIRST || mutex_id > DISP_MUTEX_DDP_LAST) { DDPDUMP("error:check mutex fail:exceed mutex max (0 ~ %d)\n",DISP_MUTEX_DDP_LAST); return; } real_value = DISP_REG_GET(DISP_REG_CONFIG_MUTEX_MOD(mutex_id)); for(i = 0 ; i < module_num ; i++) { if(module_mutex_map[module_list[i]].bit != -1) expect_value |= (1 << module_mutex_map[module_list[i]].bit); } if( expect_value != real_value ) { DDPDUMP("error:mutex %d error: expect 0x%x, real 0x%x\n",mutex_id,expect_value,real_value); } real_sof = DISP_REG_GET(DISP_REG_CONFIG_MUTEX_SOF(mutex_id)); expect_sof = ddp_get_mutex_sof(module_list[module_num-1],ddp_mode); if((kal_uint32)expect_sof != real_sof) { DDPDUMP("error:mutex %d sof error: expect %s, real %s\n", mutex_id, ddp_get_mutex_sof_name(expect_sof), ddp_get_mutex_sof_name((MUTEX_SOF)real_sof)); } } static int ddp_mutex_enable_l(int mutex_idx,void * handle) { DDPDBG("mutex %d enable\n", mutex_idx); DISP_REG_SET(handle,DISP_REG_CONFIG_MUTEX_EN(mutex_idx),1); return 0; } int ddp_mutex_hw_dcm_on(int mutex_idx,void * handle) { if(gMutexFreeRun==1 && primary_display_is_video_mode()==0 && mutex_idx==0) { DISP_REG_SET(handle,DISP_REG_CONFIG_MUTEX_HW_DCM,1); } DDPDBG("mutex %d hw_dcm 0x%x \n", mutex_idx, DISP_REG_GET(DISP_REG_CONFIG_MUTEX_HW_DCM)); return 0; } int ddp_mutex_hw_dcm_off(int mutex_idx,void * handle) { if(gMutexFreeRun==1 && primary_display_is_video_mode()==0 && mutex_idx==0) { DISP_REG_SET(handle,DISP_REG_CONFIG_MUTEX_HW_DCM,0); } DDPDBG("mutex %d hw_dcm 0x%x \n", mutex_idx, DISP_REG_GET(DISP_REG_CONFIG_MUTEX_HW_DCM)); return 0; } int ddp_get_module_num(DDP_SCENARIO_ENUM scenario) { return ddp_get_module_num_l(module_list_scenario[scenario]); } static void ddp_print_scenario(DDP_SCENARIO_ENUM scenario) { int i =0; char path[512]={'\0'}; int num = ddp_get_module_num(scenario); for(i=0; i< num; i++) { strcat(path,ddp_get_module_name(module_list_scenario[scenario][i])); } DDPMSG("scenario %s have modules: %s\n",ddp_get_scenario_name(scenario),path); } static int ddp_find_module_index(DDP_SCENARIO_ENUM ddp_scenario, DISP_MODULE_ENUM module) { int i=0; for(i=0; i< DDP_ENING_NUM; i++) { if(module_list_scenario[ddp_scenario][i] == module) { return i; } } DDPDBG("find module: can not find module %s on scenario %s\n",ddp_get_module_name(module), ddp_get_scenario_name(ddp_scenario)); return -1; } // set display interface when kernel init int ddp_set_dst_module(DDP_SCENARIO_ENUM scenario, DISP_MODULE_ENUM dst_module) { int i = 0; DDPMSG("ddp_set_dst_module, scenario=%s, dst_module=%s \n", ddp_get_scenario_name(scenario), ddp_get_module_name(dst_module)); if (ddp_find_module_index(scenario,dst_module) > 0) { DDPDBG("%s is already on path\n",ddp_get_module_name(dst_module)); return 0; } i = ddp_get_module_num_l(module_list_scenario[scenario])-1; ASSERT(i>=0); if (dst_module == DISP_MODULE_DSIDUAL) { if (i < (DDP_ENING_NUM -1)) { module_list_scenario[scenario][i++] = DISP_MODULE_SPLIT1; }else{ DDPERR("set dst module over up bound\n"); return -1; } } else { if(ddp_get_dst_module(scenario)==DISP_MODULE_DSIDUAL) { if (i >= 1) { module_list_scenario[scenario][i--] = -1; }else{ DDPERR("set dst module over low bound\n"); return -1; } } } module_list_scenario[scenario][i] = dst_module; if (scenario == DDP_SCENARIO_PRIMARY_ALL) { ddp_set_dst_module(DDP_SCENARIO_PRIMARY_DISP,dst_module); }else if(scenario==DDP_SCENARIO_SUB_ALL) { ddp_set_dst_module(DDP_SCENARIO_SUB_DISP,dst_module); } ddp_print_scenario(scenario); return 0; } DISP_MODULE_ENUM ddp_get_dst_module(DDP_SCENARIO_ENUM ddp_scenario) { DISP_MODULE_ENUM module_name = DISP_MODULE_UNKNOWN; int module_num = ddp_get_module_num_l(module_list_scenario[ddp_scenario])-1; if(module_num >=0 ) module_name = module_list_scenario[ddp_scenario][module_num]; //DDPMSG("ddp_get_dst_module, scneario=%s, dst_module=%s\n", // ddp_get_scenario_name(ddp_scenario), // ddp_get_module_name(module_name)); return module_name; } int * ddp_get_scenario_list(DDP_SCENARIO_ENUM ddp_scenario) { return module_list_scenario[ddp_scenario]; } int ddp_is_module_in_scenario(DDP_SCENARIO_ENUM ddp_scenario, DISP_MODULE_ENUM module) { int i=0; for(i=0; i< DDP_ENING_NUM; i++) { if(module_list_scenario[ddp_scenario][i] == module) { return 1; } } return 0; } int ddp_insert_module(DDP_SCENARIO_ENUM ddp_scenario, DISP_MODULE_ENUM place, DISP_MODULE_ENUM module) { int i = DDP_ENING_NUM-1; int idx = ddp_find_module_index(ddp_scenario,place); if( idx < 0) { DDPERR("error: ddp_insert_module , place=%s is not in scenario %s!\n", ddp_get_module_name(place), ddp_get_scenario_name(ddp_scenario)); return -1; } for(i=0; i=idx; i--) { module_list_scenario[ddp_scenario][i+1] = module_list_scenario[ddp_scenario][i]; } module_list_scenario[ddp_scenario][idx] = module; if(0) { int * modules = ddp_get_scenario_list(ddp_scenario); int module_num = ddp_get_module_num(ddp_scenario); DDPMSG("after insert module, module list is: \n"); for(i=0;i