Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b7e6001c authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: vidc: Reorganize work mode, route and latency selection"

parents ef3ed353 edfb03a6
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -878,7 +878,7 @@ int msm_vdec_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
		}
		break;
	case V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_MODE:
		inst->clk_data.low_latency_mode = (bool)ctrl->val;
		inst->clk_data.low_latency_mode = !!ctrl->val;
		break;
	default:
		dprintk(VIDC_ERR,
+1 −35
Original line number Diff line number Diff line
@@ -1444,7 +1444,7 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
		}
		break;
	case V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_MODE:
		inst->clk_data.low_latency_mode = (bool)ctrl->val;
		inst->clk_data.low_latency_mode = !!ctrl->val;
		break;
	case V4L2_CID_MPEG_VIDC_VENC_HDR_INFO: {
		u32 info_type = (ctrl->val >> 28);
@@ -2857,37 +2857,6 @@ int msm_venc_set_video_csc(struct msm_vidc_inst *inst)
	return rc;
}

int msm_venc_set_low_latency_mode(struct msm_vidc_inst *inst)
{
	int rc = 0;
	struct hfi_device *hdev;
	struct v4l2_ctrl *ctrl;
	struct hal_enable enable;

	if (!inst || !inst->core) {
		dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
		return -EINVAL;
	}
	hdev = inst->core->device;

	ctrl = msm_venc_get_ctrl(inst,
			V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_MODE);
	if (!ctrl) {
		dprintk(VIDC_ERR,
			"%s: get lowlatency mode failed\n", __func__);
		return -EINVAL;
	}
	enable.enable = !!ctrl->val;

	dprintk(VIDC_DBG, "%s: %d\n", __func__, enable.enable);
	rc = call_hfi_op(hdev, session_set_property, inst->session,
			HAL_PARAM_VENC_LOW_LATENCY, &enable);
	if (rc)
		dprintk(VIDC_ERR, "%s: set property failed\n", __func__);

	return rc;
}

int msm_venc_set_8x8_transform(struct msm_vidc_inst *inst)
{
	int rc = 0;
@@ -3382,9 +3351,6 @@ int msm_venc_set_properties(struct msm_vidc_inst *inst)
	if (rc)
		goto exit;
	rc = msm_venc_set_vpx_error_resilience(inst);
	if (rc)
		goto exit;
	rc = msm_venc_set_low_latency_mode(inst);
	if (rc)
		goto exit;
	rc = msm_venc_set_video_signal_info(inst);
+9 −19
Original line number Diff line number Diff line
@@ -943,13 +943,7 @@ int msm_vidc_set_internal_config(struct msm_vidc_inst *inst)
		rc = call_hfi_op(hdev, session_set_property,
			(void *)inst->session, HAL_CONFIG_VENC_VBV_HRD_BUF_SIZE,
			(void *)&hrd_buf_size);

		latency.enable = true;
		rc = call_hfi_op(hdev, session_set_property,
			(void *)inst->session, HAL_PARAM_VENC_LOW_LATENCY,
			(void *)&latency);

		inst->clk_data.low_latency_mode = latency.enable;
		inst->clk_data.low_latency_mode = true;
	}

	/* Update Slice Config */
@@ -1144,19 +1138,20 @@ static inline int start_streaming(struct msm_vidc_inst *inst)
		goto fail_start;
	}

	/* Decide work route for current session */
	rc = call_core_op(inst->core, decide_work_route, inst);

	/* Decide work mode for current session */
	rc = call_core_op(inst->core, decide_work_mode, inst);
	if (rc) {
		dprintk(VIDC_ERR,
			"Failed to decide work route for session %pK\n", inst);
			"Failed to decide work mode for session %pK\n", inst);
		goto fail_start;
	}

	/* Decide work mode for current session */
	rc = call_core_op(inst->core, decide_work_mode, inst);
	/* Decide work route for current session */
	rc = call_core_op(inst->core, decide_work_route, inst);
	if (rc) {
		dprintk(VIDC_ERR,
			"Failed to decide work mode for session %pK\n", inst);
			"Failed to decide work route for session %pK\n", inst);
		goto fail_start;
	}

@@ -1898,17 +1893,12 @@ void *msm_vidc_open(int core_id, int session_type)
	inst->session_type = session_type;
	inst->state = MSM_VIDC_CORE_UNINIT_DONE;
	inst->core = core;
	inst->clk_data.min_freq = 0;
	inst->clk_data.curr_freq = 0;
	inst->clk_data.ddr_bw = 0;
	inst->clk_data.sys_cache_bw = 0;
	inst->clk_data.bitrate = 0;
	inst->clk_data.core_id = VIDC_CORE_ID_DEFAULT;
	inst->bit_depth = MSM_VIDC_BIT_DEPTH_8;
	inst->pic_struct = MSM_VIDC_PIC_STRUCT_PROGRESSIVE;
	inst->colour_space = MSM_VIDC_BT601_6_525;
	inst->profile = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
	inst->level = V4L2_MPEG_VIDEO_H264_LEVEL_1_0;
	inst->level = V4L2_MPEG_VIDEO_H264_LEVEL_UNKNOWN;
	inst->entropy_mode = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC;
	inst->smem_ops = &msm_vidc_smem_ops;

+237 −13
Original line number Diff line number Diff line
@@ -14,22 +14,30 @@
#define MSM_VIDC_MIN_UBWC_COMPRESSION_RATIO (1 << 16)
#define MSM_VIDC_MAX_UBWC_COMPRESSION_RATIO (5 << 16)

static int msm_vidc_decide_work_mode_ar50(struct msm_vidc_inst *inst);
static unsigned long msm_vidc_calc_freq_ar50(struct msm_vidc_inst *inst,
	u32 filled_len);
static int msm_vidc_decide_work_mode_ar50(struct msm_vidc_inst *inst);
static unsigned long msm_vidc_calc_freq(struct msm_vidc_inst *inst,
static unsigned long msm_vidc_calc_freq_iris1(struct msm_vidc_inst *inst,
	u32 filled_len);
static unsigned long msm_vidc_calc_freq_iris2(struct msm_vidc_inst *inst,
	u32 filled_len);

struct msm_vidc_core_ops core_ops_vpu4 = {
struct msm_vidc_core_ops core_ops_ar50 = {
	.calc_freq = msm_vidc_calc_freq_ar50,
	.decide_work_route = NULL,
	.decide_work_mode = msm_vidc_decide_work_mode_ar50,
};

struct msm_vidc_core_ops core_ops_vpu5 = {
	.calc_freq = msm_vidc_calc_freq,
	.decide_work_route = msm_vidc_decide_work_route,
	.decide_work_mode = msm_vidc_decide_work_mode,
struct msm_vidc_core_ops core_ops_iris1 = {
	.calc_freq = msm_vidc_calc_freq_iris1,
	.decide_work_route = msm_vidc_decide_work_route_iris1,
	.decide_work_mode = msm_vidc_decide_work_mode_iris1,
};

struct msm_vidc_core_ops core_ops_iris2 = {
	.calc_freq = msm_vidc_calc_freq_iris2,
	.decide_work_route = msm_vidc_decide_work_route_iris2,
	.decide_work_mode = msm_vidc_decide_work_mode_iris2,
};

static inline void msm_dcvs_print_dcvs_stats(struct clock_data *dcvs)
@@ -609,7 +617,99 @@ static unsigned long msm_vidc_calc_freq_ar50(struct msm_vidc_inst *inst,
	return (unsigned long) freq;
}

static unsigned long msm_vidc_calc_freq(struct msm_vidc_inst *inst,
static unsigned long msm_vidc_calc_freq_iris1(struct msm_vidc_inst *inst,
	u32 filled_len)
{
	u64 vsp_cycles = 0, vpp_cycles = 0, fw_cycles = 0, freq = 0;
	u32 vpp_cycles_per_mb;
	u32 mbs_per_second;
	struct msm_vidc_core *core = NULL;
	int i = 0;
	struct allowed_clock_rates_table *allowed_clks_tbl = NULL;
	u64 rate = 0, fps;
	struct clock_data *dcvs = NULL;
	u32 operating_rate, vsp_factor_num = 10, vsp_factor_den = 5;

	core = inst->core;
	dcvs = &inst->clk_data;

	mbs_per_second = msm_comm_get_inst_load_per_core(inst,
		LOAD_CALC_NO_QUIRKS);

	fps = msm_vidc_get_fps(inst);

	/*
	 * Calculate vpp, vsp, fw cycles separately for encoder and decoder.
	 * Even though, most part is common now, in future it may change
	 * between them.
	 */

	if (inst->session_type == MSM_VIDC_ENCODER) {
		vpp_cycles_per_mb = inst->flags & VIDC_LOW_POWER ?
			inst->clk_data.entry->low_power_cycles :
			inst->clk_data.entry->vpp_cycles;

		vpp_cycles = mbs_per_second * vpp_cycles_per_mb;
		/* 21 / 20 is overhead factor */
		vpp_cycles = (vpp_cycles * 21)/
				(inst->clk_data.work_route * 20);

		vsp_cycles = mbs_per_second * inst->clk_data.entry->vsp_cycles;

		/* bitrate is based on fps, scale it using operating rate */
		operating_rate = inst->clk_data.operating_rate >> 16;
		if (operating_rate > inst->prop.fps && inst->prop.fps) {
			vsp_factor_num *= operating_rate;
			vsp_factor_den *= inst->prop.fps;
		}
		vsp_cycles += ((u64)inst->clk_data.bitrate * vsp_factor_num) /
				vsp_factor_den;

		fw_cycles = fps * inst->core->resources.fw_cycles;

	} else if (inst->session_type == MSM_VIDC_DECODER) {
		vpp_cycles = mbs_per_second * inst->clk_data.entry->vpp_cycles;
		/* 21 / 20 is overhead factor */
		vpp_cycles = (vpp_cycles * 21)/
				(inst->clk_data.work_route * 20);

		vsp_cycles = mbs_per_second * inst->clk_data.entry->vsp_cycles;

		/* vsp perf is about 0.5 bits/cycle */
		vsp_cycles += ((fps * filled_len * 8) * 10) / 5;

		fw_cycles = fps * inst->core->resources.fw_cycles;

	} else {
		dprintk(VIDC_ERR, "Unknown session type = %s\n", __func__);
		return msm_vidc_max_freq(inst->core);
	}

	freq = max(vpp_cycles, vsp_cycles);
	freq = max(freq, fw_cycles);

	allowed_clks_tbl = core->resources.allowed_clks_tbl;
	for (i = core->resources.allowed_clks_tbl_size - 1; i >= 0; i--) {
		rate = allowed_clks_tbl[i].clock_rate;
		if (rate >= freq)
			break;
	}

	dcvs->load_norm = rate;
	dcvs->load_low = i < (int) (core->resources.allowed_clks_tbl_size - 1) ?
		allowed_clks_tbl[i+1].clock_rate : dcvs->load_norm;
	dcvs->load_high = i > 0 ? allowed_clks_tbl[i-1].clock_rate :
		dcvs->load_norm;

	dprintk(VIDC_PROF,
		"%s: inst %pK: %x : filled len %d required freq %lu load_norm %lu\n",
		__func__, inst, hash32_ptr(inst->session),
		filled_len, freq, dcvs->load_norm);

	return (unsigned long) freq;
}

static unsigned long msm_vidc_calc_freq_iris2(struct msm_vidc_inst *inst,
	u32 filled_len)
{
	u64 vsp_cycles = 0, vpp_cycles = 0, fw_cycles = 0, freq = 0;
@@ -1131,7 +1231,7 @@ int msm_vidc_get_extra_buff_count(struct msm_vidc_inst *inst,
	return count;
}

int msm_vidc_decide_work_route(struct msm_vidc_inst *inst)
int msm_vidc_decide_work_route_iris1(struct msm_vidc_inst *inst)
{
	int rc = 0;
	struct hfi_device *hdev;
@@ -1209,6 +1309,71 @@ int msm_vidc_decide_work_route(struct msm_vidc_inst *inst)
	return rc;
}

int msm_vidc_decide_work_route_iris2(struct msm_vidc_inst *inst)
{
	int rc = 0;
	struct hfi_device *hdev;
	struct hal_video_work_route pdata;

	if (!inst || !inst->core || !inst->core->device) {
		dprintk(VIDC_ERR,
			"%s Invalid args: Inst = %pK\n",
			__func__, inst);
		return -EINVAL;
	}

	hdev = inst->core->device;

	pdata.video_work_route = 4;
	if (inst->session_type == MSM_VIDC_DECODER) {
		if (inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_MPEG2 ||
			inst->pic_struct != MSM_VIDC_PIC_STRUCT_PROGRESSIVE)
			pdata.video_work_route = 1;
	} else if (inst->session_type == MSM_VIDC_ENCODER) {
		u32 slice_mode, rc_mode;
		u32 output_width, output_height, fps, mbps;
		bool cbr_plus;

		if (inst->fmts[CAPTURE_PORT].fourcc == V4L2_PIX_FMT_VP8) {
			pdata.video_work_route = 1;
			goto decision_done;
		}

		rc_mode = msm_comm_g_ctrl_for_id(inst,
			V4L2_CID_MPEG_VIDEO_BITRATE_MODE);
		slice_mode =  msm_comm_g_ctrl_for_id(inst,
				V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE);
		output_height = inst->prop.height[CAPTURE_PORT];
		output_width = inst->prop.width[CAPTURE_PORT];
		fps = inst->prop.fps;
		mbps = NUM_MBS_PER_SEC(output_height, output_width, fps);
		cbr_plus = ((rc_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR &&
			mbps > CBR_MB_LIMIT) ||
			(rc_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR &&
			mbps > CBR_VFR_MB_LIMIT));
		if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES ||
			((mbps <= NUM_MBS_PER_SEC(1920, 1088, 60)) && !cbr_plus)
			) {
			pdata.video_work_route = 1;
			dprintk(VIDC_DBG, "Configured work route = 1");
		}
	} else {
		return -EINVAL;
	}

decision_done:

	inst->clk_data.work_route = pdata.video_work_route;
	rc = call_hfi_op(hdev, session_set_property,
			(void *)inst->session, HAL_PARAM_VIDEO_WORK_ROUTE,
			(void *)&pdata);
	if (rc)
		dprintk(VIDC_WARN,
			" Failed to configure work route %pK\n", inst);

	return rc;
}

static int msm_vidc_decide_work_mode_ar50(struct msm_vidc_inst *inst)
{
	int rc = 0;
@@ -1274,7 +1439,7 @@ static int msm_vidc_decide_work_mode_ar50(struct msm_vidc_inst *inst)
	return rc;
}

int msm_vidc_decide_work_mode(struct msm_vidc_inst *inst)
int msm_vidc_decide_work_mode_iris1(struct msm_vidc_inst *inst)
{
	int rc = 0;
	struct hfi_device *hdev;
@@ -1354,6 +1519,63 @@ int msm_vidc_decide_work_mode(struct msm_vidc_inst *inst)
	return rc;
}

int msm_vidc_decide_work_mode_iris2(struct msm_vidc_inst *inst)
{
	int rc = 0;
	struct hfi_device *hdev;
	struct hal_video_work_mode pdata;
	struct hal_enable latency;
	u32 num_mbs = 0;

	if (!inst || !inst->core || !inst->core->device) {
		dprintk(VIDC_ERR,
			"%s Invalid args: Inst = %pK\n",
			__func__, inst);
		return -EINVAL;
	}

	hdev = inst->core->device;
	pdata.video_work_mode = VIDC_WORK_MODE_2;

	if (inst->clk_data.low_latency_mode) {
		pdata.video_work_mode = VIDC_WORK_MODE_1;
		dprintk(VIDC_DBG, "Configured work mode = 1");
	} else if (inst->session_type == MSM_VIDC_DECODER) {
		num_mbs = NUM_MBS_PER_FRAME(
					inst->prop.height[OUTPUT_PORT],
					inst->prop.width[OUTPUT_PORT]);
		if (inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_MPEG2 ||
			(inst->pic_struct != MSM_VIDC_PIC_STRUCT_PROGRESSIVE) ||
			(num_mbs < NUM_MBS_PER_FRAME(720, 1280)))
			pdata.video_work_mode = VIDC_WORK_MODE_1;
	} else if (inst->session_type == MSM_VIDC_ENCODER &&
			inst->fmts[CAPTURE_PORT].fourcc == V4L2_PIX_FMT_VP8) {
		pdata.video_work_mode = VIDC_WORK_MODE_1;
		/* For WORK_MODE_1, set Low Latency mode by default to HW. */
		inst->clk_data.low_latency_mode = true;
	} else {
		return -EINVAL;
	}

	inst->clk_data.work_mode = pdata.video_work_mode;
	rc = call_hfi_op(hdev, session_set_property,
			(void *)inst->session, HAL_PARAM_VIDEO_WORK_MODE,
			(void *)&pdata);
	if (rc)
		dprintk(VIDC_WARN,
			" Failed to configure Work Mode %pK\n", inst);

	if (inst->clk_data.low_latency_mode &&
		inst->session_type == MSM_VIDC_ENCODER){
		latency.enable = true;
		rc = call_hfi_op(hdev, session_set_property,
			(void *)inst->session, HAL_PARAM_VENC_LOW_LATENCY,
			(void *)&latency);
	}

	return rc;
}

static inline int msm_vidc_power_save_mode_enable(struct msm_vidc_inst *inst,
	bool enable)
{
@@ -1608,10 +1830,12 @@ void msm_vidc_init_core_clk_ops(struct msm_vidc_core *core)
	if (!core)
		return;

	if (core->platform_data->vpu_ver == VPU_VERSION_4)
		core->core_ops = &core_ops_vpu4;
	if (core->platform_data->vpu_ver == VPU_VERSION_AR50)
		core->core_ops = &core_ops_ar50;
	else if (core->platform_data->vpu_ver == VPU_VERSION_IRIS1)
		core->core_ops = &core_ops_iris1;
	else
		core->core_ops = &core_ops_vpu5;
		core->core_ops = &core_ops_iris2;
}

void msm_print_core_status(struct msm_vidc_core *core, u32 core_id)
+4 −2
Original line number Diff line number Diff line
@@ -25,8 +25,10 @@ int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst *inst);
int msm_comm_scale_clocks_and_bus(struct msm_vidc_inst *inst);
int msm_comm_init_clocks_and_bus_data(struct msm_vidc_inst *inst);
void msm_comm_free_freq_table(struct msm_vidc_inst *inst);
int msm_vidc_decide_work_route(struct msm_vidc_inst *inst);
int msm_vidc_decide_work_mode(struct msm_vidc_inst *inst);
int msm_vidc_decide_work_route_iris1(struct msm_vidc_inst *inst);
int msm_vidc_decide_work_mode_iris1(struct msm_vidc_inst *inst);
int msm_vidc_decide_work_route_iris2(struct msm_vidc_inst *inst);
int msm_vidc_decide_work_mode_iris2(struct msm_vidc_inst *inst);
int msm_vidc_decide_core_and_power_mode(struct msm_vidc_inst *inst);
void msm_print_core_status(struct msm_vidc_core *core, u32 core_id);
void msm_vidc_clear_freq_entry(struct msm_vidc_inst *inst,
Loading