Prechádzať zdrojové kódy

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 <[email protected]>
Darshana Patil 3 rokov pred
rodič
commit
e17abd45c1

+ 4 - 0
driver/platform/waipio/src/msm_vidc_waipio.c

@@ -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

+ 2 - 0
driver/vidc/inc/msm_vidc_driver.h

@@ -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,

+ 4 - 0
driver/vidc/inc/msm_vidc_internal.h

@@ -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,

+ 156 - 46
driver/vidc/src/msm_vidc_driver.c

@@ -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,36 +5394,158 @@ 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 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);
@@ -5436,18 +5553,11 @@ int msm_vidc_check_session_supported(struct msm_vidc_inst *inst)
 			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);
-		rc = -EINVAL;
+	rc = msm_vidc_check_max_sessions(inst);
+	if (rc)
 		goto exit;
-	}
 
 exit:
 	if (rc) {