/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2019 MediaTek Inc. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "layering_rule.h" static struct layering_rule_ops l_rule_ops; static struct layering_rule_info_t l_rule_info; int emi_bound_table[HRT_BOUND_NUM][HRT_LEVEL_NUM] = { /* HRT_BOUND_TYPE_LP4 */ {0, 0, 300, 400}, /* HRT_BOUND_TYPE_LP3 */ {0, 0, 300, 400}, /* HRT_BOUND_TYPE_LP4_1CH */ {0, 300, 600, 800}, /* HRT_BOUND_TYPE_LP4_HYBRID */ {0, 0, 300, 400}, /* HRT_BOUND_TYPE_LP3_PLUSP */ {0, 0, 200, 400}, }; int larb_bound_table[HRT_BOUND_NUM][HRT_LEVEL_NUM] = { /* HRT_BOUND_TYPE_LP4 */ {1200, 1200, 1200, 1200}, /* */ {1200, 1200, 1200, 1200}, /* HRT_BOUND_TYPE_LP4_1CH */ {1200, 1200, 1200, 1200}, /* HRT_BOUND_TYPE_LP4_HYBRID */ {1200, 1200, 1200, 1200}, }; /** * The layer mapping table define ovl layer dispatch rule for both * primary and secondary display.Each table has 16 elements which * represent the layer mapping rule by the number of input layers. */ #ifndef CONFIG_MTK_ROUND_CORNER_SUPPORT static int layer_mapping_table[HRT_TB_NUM][MAX_PHY_OVL_CNT] = { /* HRT_TB_TYPE_GENERAL */ {0x00000001, 0x00000003, 0x00000007, 0x0000000F, 0x0000000F, 0x0000000F, 0x0000000F}, }; #else static int layer_mapping_table[HRT_TB_NUM][MAX_PHY_OVL_CNT] = { {0x00000001, 0x00000003, 0x00000007, 0x00000007, 0x00000007}, }; #endif /** * The larb mapping table represent the relation between LARB and OVL. */ static int larb_mapping_table[HRT_TB_NUM] = { 0x00000001, }; /** * The OVL mapping table is used to get the OVL index of correcponding layer. * The bit value 1 means the position of the last layer in OVL engine. */ static int ovl_mapping_table[HRT_TB_NUM] = { 0x00000008, }; #define GET_SYS_STATE(sys_state) \ ((l_rule_info.hrt_sys_state >> sys_state) & 0x1) static void layering_rule_senario_decision(struct disp_layer_info *disp_info) { mmprofile_log_ex(ddp_mmp_get_events()->hrt, MMPROFILE_FLAG_START, l_rule_info.disp_path, l_rule_info.layer_tb_idx | (l_rule_info.bound_tb_idx << 16)); if (GET_SYS_STATE(DISP_HRT_MULTI_TUI_ON)) { l_rule_info.disp_path = HRT_PATH_GENERAL; /* layer_tb_idx = HRT_TB_TYPE_MULTI_WINDOW_TUI;*/ l_rule_info.layer_tb_idx = HRT_TB_TYPE_GENERAL; } else { l_rule_info.layer_tb_idx = HRT_TB_TYPE_GENERAL; l_rule_info.disp_path = HRT_PATH_GENERAL; } l_rule_info.primary_fps = 60; if (primary_display_get_height() <= 1440) l_rule_info.bound_tb_idx = HRT_BOUND_TYPE_LP4; else l_rule_info.bound_tb_idx = HRT_BOUND_TYPE_LP3_PLUSP; mmprofile_log_ex(ddp_mmp_get_events()->hrt, MMPROFILE_FLAG_END, l_rule_info.disp_path, l_rule_info.layer_tb_idx | (l_rule_info.bound_tb_idx << 16)); } static bool filter_by_hw_limitation(struct disp_layer_info *disp_info) { bool flag = false; unsigned int i = 0; struct layer_config *info; unsigned int disp_idx = 0; unsigned int layer_cnt = 0; for (disp_idx = 0 ; disp_idx < 2; ++disp_idx) { if (disp_info->layer_num[disp_idx] < 1) continue; /* display not support RGBA1010102 & RGBA_FP16 */ for (i = 0; i < disp_info->layer_num[disp_idx]; i++) { info = &(disp_info->input_config[disp_idx][i]); if (info->src_fmt != DISP_FORMAT_RGBA1010102 && info->src_fmt != DISP_FORMAT_RGBA_FP16) continue; /* push to GPU */ if (disp_info->gles_head[disp_idx] == -1 || i < disp_info->gles_head[disp_idx]) disp_info->gles_head[disp_idx] = i; if (disp_info->gles_tail[disp_idx] == -1 || i > disp_info->gles_tail[disp_idx]) disp_info->gles_tail[disp_idx] = i; } } disp_idx = 1; for (i = 0; i < disp_info->layer_num[disp_idx]; i++) { info = &(disp_info->input_config[disp_idx][i]); if (is_gles_layer(disp_info, disp_idx, i)) continue; layer_cnt++; if (layer_cnt > SECONDARY_OVL_LAYER_NUM) { /* push to GPU */ if (disp_info->gles_head[disp_idx] == -1 || i < disp_info->gles_head[disp_idx]) disp_info->gles_head[disp_idx] = i; if (disp_info->gles_tail[disp_idx] == -1 || i > disp_info->gles_tail[disp_idx]) disp_info->gles_tail[disp_idx] = i; flag = false; } } return flag; } static void clear_layer(struct disp_layer_info *disp_info) { int di = 0; int i = 0; struct layer_config *c; for (di = 0; di < 2; di++) { int g_head = disp_info->gles_head[di]; int top = -1; if (disp_info->layer_num[di] <= 0) continue; if (g_head == -1) continue; for (i = disp_info->layer_num[di] - 1; i >= g_head; i--) { c = &disp_info->input_config[di][i]; if (has_layer_cap(c, LAYERING_OVL_ONLY) && has_layer_cap(c, CLIENT_CLEAR_LAYER)) { top = i; break; } } if (top == -1) continue; if (!is_gles_layer(disp_info, di, top)) continue; c = &disp_info->input_config[di][top]; c->layer_caps |= DISP_CLIENT_CLEAR_LAYER; DISPMSG("%s:D%d:L%d\n", __func__, di, top); disp_info->gles_head[di] = 0; disp_info->gles_tail[di] = disp_info->layer_num[di] - 1; for (i = 0; i < disp_info->layer_num[di]; i++) { c = &disp_info->input_config[di][i]; c->ext_sel_layer = -1; if (i == top) c->ovl_id = 0; else c->ovl_id = 1; } } } static int get_hrt_bound(int is_larb, int hrt_level) { if (is_larb) return larb_bound_table[l_rule_info.bound_tb_idx][hrt_level]; else return emi_bound_table[l_rule_info.bound_tb_idx][hrt_level]; } static int *get_bound_table(enum DISP_HW_MAPPING_TB_TYPE tb_type) { switch (tb_type) { case DISP_HW_EMI_BOUND_TB: return emi_bound_table[l_rule_info.bound_tb_idx]; case DISP_HW_LARB_BOUND_TB: return larb_bound_table[l_rule_info.bound_tb_idx]; default: return NULL; } } static int get_mapping_table(enum DISP_HW_MAPPING_TB_TYPE tb_type, int param) { int layer_tb_idx = l_rule_info.layer_tb_idx; switch (tb_type) { case DISP_HW_OVL_TB: return ovl_mapping_table[layer_tb_idx]; case DISP_HW_LARB_TB: return larb_mapping_table[layer_tb_idx]; case DISP_HW_LAYER_TB: if (param < MAX_PHY_OVL_CNT && param >= 0) return layer_mapping_table[layer_tb_idx][param]; else return -1; default: return -1; } } void layering_rule_init(void) { l_rule_info.primary_fps = 60; register_layering_rule_ops(&l_rule_ops, &l_rule_info); } static struct layering_rule_ops l_rule_ops = { .scenario_decision = layering_rule_senario_decision, .get_bound_table = get_bound_table, .get_hrt_bound = get_hrt_bound, .get_mapping_table = get_mapping_table, .rollback_to_gpu_by_hw_limitation = filter_by_hw_limitation, .clear_layer = clear_layer, };