Browse Source

waipio: driver: Add support for work mode and route

Iris2 specific calculations for Work Mode and Route.
Also add quality mode support.

Change-Id: I7a1e2fa27236aa749978d146d85fd0af6177084c
Signed-off-by: Chinmay Sawarkar <[email protected]>
Chinmay Sawarkar 4 years ago
parent
commit
dca32dc984

+ 1 - 1
driver/platform/waipio/src/msm_vidc_waipio.c

@@ -959,7 +959,7 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
 	{QUALITY_MODE, ENC, CODECS_ALL,
 	{QUALITY_MODE, ENC, CODECS_ALL,
 		MSM_VIDC_MAX_QUALITY_MODE,
 		MSM_VIDC_MAX_QUALITY_MODE,
 		MSM_VIDC_POWER_SAVE_MODE, 1,
 		MSM_VIDC_POWER_SAVE_MODE, 1,
-		MSM_VIDC_MAX_QUALITY_MODE},
+		MSM_VIDC_POWER_SAVE_MODE},
 
 
 	{CODED_FRAMES, DEC, CODECS_ALL,
 	{CODED_FRAMES, DEC, CODECS_ALL,
 		CODED_FRAMES_MBS_ONLY, CODED_FRAMES_ADAPTIVE_FIELDS,
 		CODED_FRAMES_MBS_ONLY, CODED_FRAMES_ADAPTIVE_FIELDS,

+ 167 - 4
driver/variant/iris2/src/msm_vidc_iris2.c

@@ -17,7 +17,6 @@
 #include "msm_vidc_buffer.h"
 #include "msm_vidc_buffer.h"
 #include "msm_vidc_debug.h"
 #include "msm_vidc_debug.h"
 
 
-
 #define VBIF_BASE_OFFS_IRIS2                   0x00080000
 #define VBIF_BASE_OFFS_IRIS2                   0x00080000
 #define CPU_BASE_OFFS_IRIS2                    0x000A0000
 #define CPU_BASE_OFFS_IRIS2                    0x000A0000
 #define AON_BASE_OFFS			               0x000E0000
 #define AON_BASE_OFFS			               0x000E0000
@@ -484,6 +483,170 @@ static int __boot_firmware_iris2(struct msm_vidc_core *vidc_core)
 	return rc;
 	return rc;
 }
 }
 
 
+bool res_is_greater_than(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_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;
+}
+
+int msm_vidc_decide_work_mode_iris2(struct msm_vidc_inst* inst)
+{
+	u32 work_mode;
+	struct v4l2_format* out_f;
+	struct v4l2_format* inp_f;
+	u32 width, height;
+	bool res_ok = false;
+	bool lowlatency = false;
+
+	if (!inst || !inst->capabilities) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	work_mode = MSM_VIDC_STAGE_2;
+	out_f = &inst->fmts[OUTPUT_PORT];
+	inp_f = &inst->fmts[INPUT_PORT];
+
+	if (is_decode_session(inst)) {
+		height = out_f->fmt.pix_mp.height;
+		width = out_f->fmt.pix_mp.width;
+		res_ok = res_is_less_than_or_equal_to(width, height, 1280, 720);
+		if (inst->capabilities->cap[CODED_FRAMES].value ==
+				CODED_FRAMES_ADAPTIVE_FIELDS ||
+			inst->capabilities->cap[LOWLATENCY_MODE].value ||
+			res_ok) {
+			work_mode = MSM_VIDC_STAGE_1;
+		}
+	} else if (is_encode_session(inst)) {
+		height = inp_f->fmt.pix_mp.height;
+		width = inp_f->fmt.pix_mp.width;
+		res_ok = !res_is_greater_than(width, height, 4096, 2160);
+		if (res_ok &&
+			(inst->capabilities->cap[LOWLATENCY_MODE].value)) {
+			work_mode = MSM_VIDC_STAGE_1;
+			/* For WORK_MODE_1, set Low Latency mode by default */
+			lowlatency = true;
+		}
+		if (inst->capabilities->cap[LOSSLESS].value) {
+			/*TODO Set 2 stage in case of ALL INTRA */
+			work_mode = MSM_VIDC_STAGE_2;
+			lowlatency = false;
+		}
+	}
+	else {
+		d_vpr_e("%s: invalid session type\n", __func__);
+		return -EINVAL;
+	}
+
+	s_vpr_h(inst->sid, "Configuring work mode = %u low latency = %u",
+		work_mode, lowlatency);
+	inst->capabilities->cap[STAGE].value = work_mode;
+
+	/* TODO If Encode then Set Low Latency (Enable/Disable)
+	 * and Update internal cap struct
+	*/
+
+	return 0;
+}
+
+int msm_vidc_decide_work_route_iris2(struct msm_vidc_inst* inst)
+{
+	u32 work_route;
+	struct msm_vidc_core* core;
+
+	if (!inst || !inst->core) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	core = inst->core;
+	work_route = core->capabilities[NUM_VPP_PIPE].value;
+
+	if (is_decode_session(inst)) {
+		if (inst->capabilities->cap[CODED_FRAMES].value ==
+				CODED_FRAMES_ADAPTIVE_FIELDS)
+			work_route = MSM_VIDC_PIPE_1;
+	} else if (is_encode_session(inst)) {
+		u32 slice_mode, width, height;
+		struct v4l2_format* f;
+
+		f = &inst->fmts[INPUT_PORT];
+		height = f->fmt.pix_mp.height;
+		width = f->fmt.pix_mp.width;
+		slice_mode = inst->capabilities->cap[SLICE_MODE].value;
+
+		/*TODO Pipe=1 for legacy CBR*/
+		if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES)
+			work_route = MSM_VIDC_PIPE_1;
+
+	} else {
+		d_vpr_e("%s: invalid session type\n", __func__);
+		return -EINVAL;
+	}
+
+	s_vpr_h(inst->sid, "Configuring work route = %u", work_route);
+	inst->capabilities->cap[PIPE].value = work_route;
+
+	return 0;
+}
+
+int msm_vidc_decide_quality_mode_iris2(struct msm_vidc_inst* inst)
+{
+	struct msm_vidc_inst_capability* capability = inst->capabilities;
+	struct msm_vidc_core *core;
+	u32 mbpf, mbps, max_hq_mbpf, max_hq_mbps;
+	u32 mode;
+
+	if (!inst || !inst->capabilities) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!is_encode_session(inst))
+		return 0;
+
+	mode = MSM_VIDC_POWER_SAVE_MODE;
+	mbpf = msm_vidc_get_mbs_per_frame(inst);
+	mbps = mbpf * msm_vidc_get_fps(inst);
+	core = inst->core;
+	max_hq_mbpf = core->capabilities[MAX_MBPF_HQ].value;;
+	max_hq_mbps = core->capabilities[MAX_MBPS_HQ].value;;
+
+	/* Power saving always disabled for CQ and LOSSLESS RC modes. */
+	if (inst->capabilities->cap[LOSSLESS].value ||
+		(mbpf <= max_hq_mbpf && mbps <= max_hq_mbps))
+		mode = MSM_VIDC_MAX_QUALITY_MODE;
+
+	inst->flags = mode == MSM_VIDC_POWER_SAVE_MODE ?
+		inst->flags | VIDC_LOW_POWER :
+		inst->flags & ~VIDC_LOW_POWER;
+	capability->cap[QUALITY_MODE].value = mode;
+
+	return 0;
+}
+
 static struct msm_vidc_venus_ops iris2_ops = {
 static struct msm_vidc_venus_ops iris2_ops = {
 	.boot_firmware = __boot_firmware_iris2,
 	.boot_firmware = __boot_firmware_iris2,
 	.interrupt_init = __interrupt_init_iris2,
 	.interrupt_init = __interrupt_init_iris2,
@@ -504,9 +667,9 @@ static struct msm_vidc_session_ops msm_session_ops = {
 	.extra_count = msm_buffer_extra_count_iris2,
 	.extra_count = msm_buffer_extra_count_iris2,
 	.calc_freq = msm_vidc_calc_freq_iris2,
 	.calc_freq = msm_vidc_calc_freq_iris2,
 	.calc_bw = msm_vidc_calc_bw_iris2,
 	.calc_bw = msm_vidc_calc_bw_iris2,
-	.decide_work_route = NULL,
-	.decide_work_mode = NULL,
-	.decide_core_and_power_mode = NULL,
+	.decide_work_route = msm_vidc_decide_work_route_iris2,
+	.decide_work_mode = msm_vidc_decide_work_mode_iris2,
+	.decide_quality_mode = msm_vidc_decide_quality_mode_iris2,
 };
 };
 
 
 int msm_vidc_init_iris2(struct msm_vidc_core *core)
 int msm_vidc_init_iris2(struct msm_vidc_core *core)

+ 1 - 1
driver/vidc/inc/msm_vidc_inst.h

@@ -21,7 +21,7 @@ struct msm_vidc_session_ops {
 		struct vidc_bus_vote_data* vote_data);
 		struct vidc_bus_vote_data* vote_data);
 	int (*decide_work_route)(struct msm_vidc_inst *inst);
 	int (*decide_work_route)(struct msm_vidc_inst *inst);
 	int (*decide_work_mode)(struct msm_vidc_inst *inst);
 	int (*decide_work_mode)(struct msm_vidc_inst *inst);
-	int (*decide_core_and_power_mode)(struct msm_vidc_inst *inst);
+	int (*decide_quality_mode)(struct msm_vidc_inst *inst);
 	int (*buffer_size)(struct msm_vidc_inst *inst, enum msm_vidc_buffer_type type);
 	int (*buffer_size)(struct msm_vidc_inst *inst, enum msm_vidc_buffer_type type);
 	int (*min_count)(struct msm_vidc_inst *inst, enum msm_vidc_buffer_type type);
 	int (*min_count)(struct msm_vidc_inst *inst, enum msm_vidc_buffer_type type);
 	int (*extra_count)(struct msm_vidc_inst *inst, enum msm_vidc_buffer_type type);
 	int (*extra_count)(struct msm_vidc_inst *inst, enum msm_vidc_buffer_type type);

+ 8 - 0
driver/vidc/src/msm_venc.c

@@ -327,9 +327,17 @@ static int msm_venc_set_pipe(struct msm_vidc_inst *inst)
 static int msm_venc_set_quality_mode(struct msm_vidc_inst *inst)
 static int msm_venc_set_quality_mode(struct msm_vidc_inst *inst)
 {
 {
 	int rc = 0;
 	int rc = 0;
+	struct msm_vidc_core* core = inst->core;
 	struct msm_vidc_inst_capability *capability = inst->capabilities;
 	struct msm_vidc_inst_capability *capability = inst->capabilities;
 	u32 mode;
 	u32 mode;
 
 
+	rc = call_session_op(core, decide_quality_mode, inst);
+	if (rc) {
+		s_vpr_e(inst->sid, "%s: decide_work_route failed\n",
+			__func__);
+		return -EINVAL;
+	}
+
 	mode = capability->cap[QUALITY_MODE].value;
 	mode = capability->cap[QUALITY_MODE].value;
 	s_vpr_h(inst->sid, "%s: quality_mode: %u\n", __func__, mode);
 	s_vpr_h(inst->sid, "%s: quality_mode: %u\n", __func__, mode);
 	rc = venus_hfi_session_property(inst,
 	rc = venus_hfi_session_property(inst,