video: driver: limit max number of sessions based on resolution

add checks to limit max number of sessions supported based on
resolution.
max number of 720P sessions: 16
max number of 1080P sessions: 8
max number of 4K sessions: 4
max number of 8K sessions: 2

Change-Id: I2a784a0d28ba050923bdc7f42a21ee9801d01d86
Signed-off-by: Darshana Patil <darshana@codeaurora.org>
This commit is contained in:
Darshana Patil
2021-08-23 15:50:33 -07:00
committed by Gerrit - the friendly Code Review server
parent 8e1ba950f0
commit e17abd45c1
4 changed files with 170 additions and 50 deletions

View File

@@ -53,6 +53,10 @@ static struct msm_platform_core_capability core_data_waipio[] = {
{ENC_CODECS, H264|HEVC|HEIC},
{DEC_CODECS, H264|HEVC|VP9|HEIC},
{MAX_SESSION_COUNT, 16},
{MAX_NUM_720P_SESSIONS, 16},
{MAX_NUM_1080P_SESSIONS, 8},
{MAX_NUM_4K_SESSIONS, 4},
{MAX_NUM_8K_SESSIONS, 2},
{MAX_SECURE_SESSION_COUNT, 3},
{MAX_MBPF, 173056}, /* (8192x4320)/256 + (4096x2176)/256*/
{MAX_MBPS, 7833600}, /* max_load

View File

@@ -428,6 +428,8 @@ void msm_vidc_free_capabililty_list(struct msm_vidc_inst *inst,
enum msm_vidc_ctrl_list_type list_type);
bool res_is_greater_than(u32 width, u32 height,
u32 ref_width, u32 ref_height);
bool res_is_greater_than_or_equal_to(u32 width, u32 height,
u32 ref_width, u32 ref_height);
bool res_is_less_than(u32 width, u32 height,
u32 ref_width, u32 ref_height);
bool res_is_less_than_or_equal_to(u32 width, u32 height,

View File

@@ -304,6 +304,10 @@ enum msm_vidc_core_capability_type {
ENC_CODECS,
DEC_CODECS,
MAX_SESSION_COUNT,
MAX_NUM_720P_SESSIONS,
MAX_NUM_1080P_SESSIONS,
MAX_NUM_4K_SESSIONS,
MAX_NUM_8K_SESSIONS,
MAX_SECURE_SESSION_COUNT,
MAX_LOAD,
MAX_MBPF,

View File

@@ -1104,6 +1104,20 @@ bool res_is_greater_than(u32 width, u32 height,
return false;
}
bool res_is_greater_than_or_equal_to(u32 width, u32 height,
u32 ref_width, u32 ref_height)
{
u32 num_mbs = NUM_MBS_PER_FRAME(height, width);
u32 max_side = max(ref_width, ref_height);
if (num_mbs >= NUM_MBS_PER_FRAME(ref_height, ref_width) ||
width >= max_side ||
height >= max_side)
return true;
else
return false;
}
bool res_is_less_than(u32 width, u32 height,
u32 ref_width, u32 ref_height)
{
@@ -5334,13 +5348,12 @@ exit:
return allow;
}
int msm_vidc_check_session_supported(struct msm_vidc_inst *inst)
static int msm_vidc_check_resolution_supported(struct msm_vidc_inst *inst)
{
struct msm_vidc_inst_capability *capability;
u32 width = 0, height = 0, min_width, min_height,
max_width, max_height;
bool allow = false, is_interlaced = false;
int rc = 0;
bool is_interlaced = false;
if (!inst || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
@@ -5348,24 +5361,6 @@ int msm_vidc_check_session_supported(struct msm_vidc_inst *inst)
}
capability = inst->capabilities;
if (is_image_session(inst) && is_secure_session(inst)) {
i_vpr_e(inst, "%s: secure image session not supported\n", __func__);
rc = -EINVAL;
goto exit;
}
rc = msm_vidc_check_core_mbps(inst);
if (rc)
goto exit;
rc = msm_vidc_check_core_mbpf(inst);
if (rc)
goto exit;
rc = msm_vidc_check_inst_mbpf(inst);
if (rc)
goto exit;
if (is_decode_session(inst)) {
width = inst->fmts[INPUT_PORT].fmt.pix_mp.width;
height = inst->fmts[INPUT_PORT].fmt.pix_mp.height;
@@ -5399,56 +5394,171 @@ int msm_vidc_check_session_supported(struct msm_vidc_inst *inst)
i_vpr_e(inst, "%s: resolution is not even. wxh [%u x %u], compose [%u x %u]\n",
__func__, width, height, inst->compose.width,
inst->compose.height);
rc = -EINVAL;
goto exit;
return -EINVAL;
}
/* check decoder input width and height is in supported range */
if (is_decode_session(inst)) {
/* check if input width and height is in supported range */
if (is_decode_session(inst) || is_encode_session(inst)) {
if (!in_range(width, min_width, max_width) ||
!in_range(height, min_height, max_height)) {
i_vpr_e(inst,
"%s: unsupported input wxh [%u x %u], allowed range: [%u x %u] to [%u x %u]\n",
__func__, width, height, min_width,
min_height, max_width, max_height);
rc = -EINVAL;
goto exit;
return -EINVAL;
}
}
/* check encoder crop width and height is in supported range */
if (is_encode_session(inst)) {
if (!in_range(width, min_width, max_width) ||
!in_range(height, min_height, max_height)) {
i_vpr_e(inst,
"%s: unsupported wxh [%u x %u], allowed range: [%u x %u] to [%u x %u]\n",
__func__, width, height, min_width,
min_height, max_width, max_height);
rc = -EINVAL;
goto exit;
}
}
/* check image capabilities */
if (is_image_encode_session(inst)) {
allow = msm_vidc_allow_image_encode_session(inst);
if (!allow) {
rc = -EINVAL;
goto exit;
}
return 0;
}
/* check interlace supported resolution */
is_interlaced = capability->cap[CODED_FRAMES].value == CODED_FRAMES_INTERLACE;
if (is_interlaced && (width > INTERLACE_WIDTH_MAX || height > INTERLACE_HEIGHT_MAX ||
NUM_MBS_PER_FRAME(width, height) > INTERLACE_MB_PER_FRAME_MAX)) {
i_vpr_e(inst, "%s: unsupported interlace wxh [%u x %u], max [%u x %u]\n",
__func__, width, height, INTERLACE_WIDTH_MAX, INTERLACE_HEIGHT_MAX);
return -EINVAL;
}
return 0;
}
static int msm_vidc_check_max_sessions(struct msm_vidc_inst *inst)
{
u32 width = 0, height = 0;
u32 num_720p_sessions = 0, num_1080p_sessions = 0;
u32 num_4k_sessions = 0, num_8k_sessions = 0;
struct msm_vidc_inst *i;
struct msm_vidc_core *core;
if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
core = inst->core;
if (!core->capabilities) {
i_vpr_e(inst, "%s: invalid params\n", __func__);
return -EINVAL;
}
core_lock(core, __func__);
list_for_each_entry(i, &core->instances, list) {
/* skip image sessions count */
if (is_image_session(inst))
continue;
if (is_decode_session(i)) {
width = i->fmts[INPUT_PORT].fmt.pix_mp.width;
height = i->fmts[INPUT_PORT].fmt.pix_mp.height;
} else if (is_encode_session(i)) {
width = i->crop.width;
height = i->crop.height;
}
/*
* one 8k session equals to 64 720p sessions in reality.
* So for one 8k session the number of 720p sessions will
* exceed max supported session count(16), hence one 8k session
* will be rejected as well.
* Therefore, treat one 8k session equal to two 4k sessions and
* one 4k session equal to two 1080p sessions and
* one 1080p session equal to two 720p sessions. This equation
* will make one 8k session equal to eight 720p sessions
* which looks good.
*/
if (res_is_greater_than(width, height, 4096, 2176)) {
num_8k_sessions += 1;
num_4k_sessions += 2;
num_1080p_sessions += 4;
num_720p_sessions += 8;
} else if (res_is_greater_than(width, height, 1920, 1088)) {
num_4k_sessions += 1;
num_1080p_sessions += 2;
num_720p_sessions += 4;
} else if (res_is_greater_than(width, height, 1280, 736)) {
num_1080p_sessions += 1;
num_720p_sessions += 2;
} else {
num_720p_sessions += 1;
}
}
core_unlock(core, __func__);
if (num_8k_sessions > core->capabilities[MAX_NUM_8K_SESSIONS].value) {
i_vpr_e(inst, "%s: total 8k sessions %d, exceeded max limit %d\n",
__func__, num_8k_sessions,
core->capabilities[MAX_NUM_8K_SESSIONS].value);
return -ENOMEM;
}
if (num_4k_sessions > core->capabilities[MAX_NUM_4K_SESSIONS].value) {
i_vpr_e(inst, "%s: total 4K sessions %d, exceeded max limit %d\n",
__func__, num_4k_sessions,
core->capabilities[MAX_NUM_4K_SESSIONS].value);
return -ENOMEM;
}
if (num_1080p_sessions > core->capabilities[MAX_NUM_1080P_SESSIONS].value) {
i_vpr_e(inst, "%s: total 1080p sessions %d, exceeded max limit %d\n",
__func__, num_1080p_sessions,
core->capabilities[MAX_NUM_1080P_SESSIONS].value);
return -ENOMEM;
}
if (num_720p_sessions > core->capabilities[MAX_NUM_720P_SESSIONS].value) {
i_vpr_e(inst, "%s: total sessions(<=720p) %d, exceeded max limit %d\n",
__func__, num_720p_sessions,
core->capabilities[MAX_NUM_720P_SESSIONS].value);
return -ENOMEM;
}
return 0;
}
int msm_vidc_check_session_supported(struct msm_vidc_inst *inst)
{
bool allow = false;
int rc = 0;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
if (is_image_session(inst) && is_secure_session(inst)) {
i_vpr_e(inst, "%s: secure image session not supported\n", __func__);
rc = -EINVAL;
goto exit;
}
rc = msm_vidc_check_core_mbps(inst);
if (rc)
goto exit;
rc = msm_vidc_check_core_mbpf(inst);
if (rc)
goto exit;
rc = msm_vidc_check_inst_mbpf(inst);
if (rc)
goto exit;
rc = msm_vidc_check_resolution_supported(inst);
if (rc)
goto exit;
/* check image capabilities */
if (is_image_encode_session(inst)) {
allow = msm_vidc_allow_image_encode_session(inst);
if (!allow) {
rc = -EINVAL;
goto exit;
}
}
rc = msm_vidc_check_max_sessions(inst);
if (rc)
goto exit;
exit:
if (rc) {
i_vpr_e(inst, "%s: current session not supported\n", __func__);