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

Commit 501be798 authored by Saurabh Kothawade's avatar Saurabh Kothawade
Browse files

msm: vidc: Update operating rate handling



Validate incoming operating rate setting and
consider special value of operating rate indicating
client's intention to set turbo mode. Vote for the
highest frequency if one of the instance sets
operating rate as INT_MAX.

Change-Id: I4803ed419cee0e327d96b81d7bf372cee82a2e8d
Signed-off-by: default avatarSaurabh Kothawade <skothawa@codeaurora.org>
parent 1d9aee75
Loading
Loading
Loading
Loading
+31 −6
Original line number Diff line number Diff line
@@ -413,7 +413,16 @@ static struct msm_vidc_ctrl msm_vdec_ctrls[] = {
		.minimum = 0,
		.maximum = INT_MAX,
		.default_value = 0,
		.step = OPERATING_FRAME_RATE_STEP,
		.step = 1,
	},
	{
		.id = V4L2_CID_MPEG_VIDC_VIDEO_FRAME_RATE,
		.name = "Set Decoder Frame rate",
		.type = V4L2_CTRL_TYPE_INTEGER,
		.minimum = 0,
		.maximum = INT_MAX,
		.default_value = 0,
		.step = 1,
	},
	{
		.id = V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_MODE,
@@ -1107,11 +1116,27 @@ int msm_vdec_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
		}
		break;
	case V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE:
		if (((ctrl->val >> 16) < inst->capability.frame_rate.min ||
			(ctrl->val >> 16) > inst->capability.frame_rate.max) &&
			ctrl->val != INT_MAX) {
			dprintk(VIDC_ERR, "Invalid operating rate %u\n",
				(ctrl->val >> 16));
			rc = -ENOTSUPP;
		} else if (ctrl->val == INT_MAX) {
			dprintk(VIDC_DBG,
				"inst(%pK) Request for turbo mode\n", inst);
			inst->clk_data.turbo_mode = true;
		} else if (msm_vidc_validate_operating_rate(inst, ctrl->val)) {
			dprintk(VIDC_ERR, "Failed to set operating rate\n");
			rc = -ENOTSUPP;
		} else {
			dprintk(VIDC_DBG,
				"inst(%pK) operating rate changed from %d to %d\n",
				inst, inst->clk_data.operating_rate >> 16,
					ctrl->val >> 16);
			inst->clk_data.operating_rate = ctrl->val;
			inst->clk_data.turbo_mode = false;
		}
		break;
	case V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_MODE:
		if (ctrl->val ==
+30 −6
Original line number Diff line number Diff line
@@ -909,7 +909,16 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = {
		.minimum = 0,
		.maximum = INT_MAX,
		.default_value = 0,
		.step = OPERATING_FRAME_RATE_STEP,
		.step = 1,
	},
	{
		.id = V4L2_CID_MPEG_VIDC_VIDEO_FRAME_RATE,
		.name = "Set Encoder Frame rate",
		.type = V4L2_CTRL_TYPE_INTEGER,
		.minimum = 0,
		.maximum = INT_MAX,
		.default_value = 0,
		.step = 1,
	},
	{
		.id = V4L2_CID_MPEG_VIDC_VIDEO_VENC_BITRATE_TYPE,
@@ -1817,12 +1826,27 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
		}
		break;
	case V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE:
		if (((ctrl->val >> 16) < inst->capability.frame_rate.min ||
			 (ctrl->val >> 16) > inst->capability.frame_rate.max) &&
			  ctrl->val != INT_MAX) {
			dprintk(VIDC_ERR, "Invalid operating rate %u\n",
				(ctrl->val >> 16));
			rc = -ENOTSUPP;
		} else if (ctrl->val == INT_MAX) {
			dprintk(VIDC_DBG, "inst(%pK) Request for turbo mode\n",
				inst);
			inst->clk_data.turbo_mode = true;
		} else if (msm_vidc_validate_operating_rate(inst, ctrl->val)) {
			dprintk(VIDC_ERR, "Failed to set operating rate\n");
			rc = -ENOTSUPP;
		} else {
			dprintk(VIDC_DBG,
				"inst(%pK) operating rate changed from %d to %d\n",
				inst, inst->clk_data.operating_rate >> 16,
				ctrl->val >> 16);
			inst->clk_data.operating_rate = ctrl->val;

			inst->clk_data.turbo_mode = false;
		}
		break;
	case V4L2_CID_MPEG_VIDC_VIDEO_VENC_BITRATE_TYPE:
	{
+4 −0
Original line number Diff line number Diff line
@@ -179,6 +179,10 @@ int msm_vidc_query_ctrl(void *instance, struct v4l2_queryctrl *ctrl)
	case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
		msm_vidc_ctrl_get_range(ctrl, &inst->capability.slice_bytes);
		break;
	case V4L2_CID_MPEG_VIDC_VIDEO_FRAME_RATE:
	case V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE:
		msm_vidc_ctrl_get_range(ctrl, &inst->capability.frame_rate);
		break;
	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
	case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE:
	case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_PROFILE:
+66 −43
Original line number Diff line number Diff line
@@ -569,6 +569,12 @@ static int msm_vidc_set_clocks(struct msm_vidc_core *core)
	mutex_lock(&core->lock);
	list_for_each_entry(temp, &core->instances, list) {
		freq += temp->clk_data.curr_freq;
		if (temp->clk_data.turbo_mode) {
			dprintk(VIDC_PROF,
				"Found an instance with Turbo request\n");
			freq = msm_vidc_max_freq(core);
			break;
		}
	}
	for (i = core->resources.allowed_clks_tbl_size - 1; i >= 0; i--) {
		rate = allowed_clks_tbl[i].clock_rate;
@@ -587,19 +593,22 @@ static int msm_vidc_set_clocks(struct msm_vidc_core *core)
	return rc;
}

int msm_vidc_update_operating_rate(struct msm_vidc_inst *inst)
int msm_vidc_validate_operating_rate(struct msm_vidc_inst *inst,
	u32 operating_rate)
{
	struct v4l2_ctrl *ctrl = NULL;
	struct msm_vidc_inst *temp;
	struct msm_vidc_core *core;
	unsigned long max_freq, freq_left, ops_left, load, cycles, freq = 0;
	unsigned long mbs_per_second;
	int rc = 0;
	u32 curr_operating_rate = 0;

	if (!inst || !inst->core) {
		dprintk(VIDC_ERR, "%s Invalid args\n", __func__);
		return -EINVAL;
	}
	core = inst->core;
	curr_operating_rate = inst->clk_data.operating_rate >> 16;

	mutex_lock(&core->lock);
	max_freq = msm_vidc_max_freq(core);
@@ -614,51 +623,35 @@ int msm_vidc_update_operating_rate(struct msm_vidc_inst *inst)

	freq_left = max_freq - freq;

	list_for_each_entry(temp, &core->instances, list) {

		if (!temp ||
				temp->state < MSM_VIDC_START_DONE ||
				temp->state >= MSM_VIDC_RELEASE_RESOURCES_DONE)
			continue;

		mbs_per_second = msm_comm_get_inst_load_per_core(temp,
	mbs_per_second = msm_comm_get_inst_load_per_core(inst,
		LOAD_CALC_NO_QUIRKS);

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

	load = cycles * mbs_per_second;

	ops_left = load ? (freq_left / load) : 0;
		/* Convert remaining operating rate to Q16 format */
		ops_left = ops_left << 16;

		ctrl = v4l2_ctrl_find(&temp->ctrl_handler,
			V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE);
		if (ctrl) {
			dprintk(VIDC_DBG,
				"%s: Before Range = %lld --> %lld\n",
				ctrl->name, ctrl->minimum, ctrl->maximum);
			dprintk(VIDC_DBG,
				"%s: Before Def value = %lld Cur val = %d\n",
				ctrl->name, ctrl->default_value, ctrl->val);
			v4l2_ctrl_modify_range(ctrl, ctrl->minimum,
				ctrl->val + ops_left, ctrl->step,
				ctrl->default_value);
	operating_rate = operating_rate >> 16;

	if ((curr_operating_rate + ops_left) >= operating_rate) {
		dprintk(VIDC_DBG,
				"%s: Updated Range = %lld --> %lld\n",
				ctrl->name, ctrl->minimum, ctrl->maximum);
			"Requestd operating rate is valid %u\n",
			operating_rate);
		rc = 0;
	} else {
		dprintk(VIDC_DBG,
				"%s: Updated Def value = %lld Cur val = %d\n",
				ctrl->name, ctrl->default_value, ctrl->val);
		}
			"Current load is high for requested settings. Cannot set operating rate to %u\n",
			operating_rate);
		rc = -EINVAL;
	}
	mutex_unlock(&core->lock);

	return 0;
	return rc;
}

int msm_comm_scale_clocks(struct msm_vidc_inst *inst)
@@ -980,8 +973,8 @@ static inline int msm_vidc_power_save_mode_enable(struct msm_vidc_inst *inst,
		return 0;
	}
	mbs_per_frame = msm_vidc_get_mbs_per_frame(inst);
	if (mbs_per_frame >= inst->core->resources.max_hq_mbs_per_frame ||
		inst->prop.fps >= inst->core->resources.max_hq_fps) {
	if (mbs_per_frame > inst->core->resources.max_hq_mbs_per_frame ||
		inst->prop.fps > inst->core->resources.max_hq_fps) {
		enable = true;
	}

@@ -1184,7 +1177,37 @@ int msm_vidc_decide_core_and_power_mode(struct msm_vidc_inst *inst)

	rc = msm_comm_scale_clocks_and_bus(inst);

	msm_print_core_status(core, VIDC_CORE_ID_1);
	msm_print_core_status(core, VIDC_CORE_ID_2);

	return rc;
}

void msm_print_core_status(struct msm_vidc_core *core, u32 core_id)
{
	struct msm_vidc_inst *inst = NULL;

	dprintk(VIDC_PROF, "Instances running on core %u", core_id);
	mutex_lock(&core->lock);
	list_for_each_entry(inst, &core->instances, list) {

		if (!((inst->clk_data.core_id & core_id) ||
			  (inst->clk_data.core_id & VIDC_CORE_ID_3)))
			continue;

		dprintk(VIDC_PROF,
			"inst %pK (%4ux%4u) to (%4ux%4u) %3u %s %s %s %s\n",
			inst,
			inst->prop.width[OUTPUT_PORT],
			inst->prop.height[OUTPUT_PORT],
			inst->prop.width[CAPTURE_PORT],
			inst->prop.height[CAPTURE_PORT],
			inst->prop.fps,
			inst->session_type == MSM_VIDC_ENCODER ? "ENC" : "DEC",
			inst->clk_data.work_mode == VIDC_WORK_MODE_1 ?
				"WORK_MODE_1" : "WORK_MODE_2",
			inst->flags & VIDC_LOW_POWER ? "LP" : "HQ",
			inst->flags & VIDC_REALTIME ? "RealTime" : "NonRTime");
	}
	mutex_unlock(&core->lock);
}
+3 −1
Original line number Diff line number Diff line
@@ -22,7 +22,8 @@
#define DCVS_DEC_EXTRA_OUTPUT_BUFFERS 4

void msm_clock_data_reset(struct msm_vidc_inst *inst);
int msm_vidc_update_operating_rate(struct msm_vidc_inst *inst);
int msm_vidc_validate_operating_rate(struct msm_vidc_inst *inst,
	u32 operating_rate);
int msm_vidc_get_extra_buff_count(struct msm_vidc_inst *inst,
	enum hal_buffer buffer_type);
int msm_dcvs_try_enable(struct msm_vidc_inst *inst);
@@ -31,6 +32,7 @@ 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_mode(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,
	u32 device_addr);
void msm_comm_free_input_cr_table(struct msm_vidc_inst *inst);
Loading