unplugged-kernel/drivers/misc/mediatek/video/mt6739/videox/layering_rule.c

261 lines
6.7 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2019 MediaTek Inc.
*/
#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 <linux/types.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#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,
};