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

Commit ac263b32 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: vidc: Update Venus DCVS algorithm for 8994V2"

parents 4d4e4d04 697c976b
Loading
Loading
Loading
Loading
+95 −178
Original line number Diff line number Diff line
@@ -59,7 +59,7 @@ struct getprop_buf {
static void msm_comm_generate_session_error(struct msm_vidc_inst *inst);
static void msm_comm_generate_sys_error(struct msm_vidc_inst *inst);
static void handle_session_error(enum command_response cmd, void *data);
static void msm_comm_monitor_ftb(struct msm_vidc_inst *inst);
static void msm_comm_dcvs_monitor_buffer(struct msm_vidc_inst *inst);
static int msm_comm_scale_clocks_dcvs(struct msm_vidc_inst *inst, bool fbd);
static int msm_comm_check_dcvs_supported(struct msm_vidc_inst *inst);

@@ -1491,7 +1491,6 @@ static void handle_fbd(enum command_response cmd, void *data)
	enum hal_buffer buffer_type;
	int extra_idx = 0;
	int64_t time_usec = 0;
	int rc = 0;

	if (!response) {
		dprintk(VIDC_ERR, "Invalid response from vidc_hal\n");
@@ -1607,15 +1606,6 @@ static void handle_fbd(enum command_response cmd, void *data)
		default:
			break;
		}
		if (msm_vidc_dcvs_mode && inst->dcvs_mode &&
			fill_buf_done->filled_len1) {
			msm_comm_monitor_ftb(inst);
			rc = msm_comm_scale_clocks_dcvs(inst, true);
			if (rc)
				dprintk(VIDC_WARN,
					"%s: Failed to scale clocks in DCVS: %d\n",
					__func__, rc);
		}
		inst->count.fbd++;
		if (fill_buf_done->filled_len1)
			msm_vidc_debugfs_update(inst,
@@ -1813,46 +1803,17 @@ void msm_comm_init_dcvs_load(struct msm_vidc_inst *inst)
		return;
	}

	dcvs->transition_turbo = false;

	/* calculating the min and max threshold */
	if (output_buf_req->buffer_count_actual) {
		dcvs->min_threshold = DCVS_MIN_DRAIN_RATE;
		dcvs->max_threshold =
			output_buf_req->buffer_count_actual -
			(DCVS_BUFFER_WITH_DEC + DCVS_BUFFER_SAFEGUARD +
			DCVS_BUFFER_RELEASED_DEC);

	if (dcvs->max_threshold - dcvs->min_threshold <
		DCVS_BUFFER_SAFEGUARD)
		dcvs->min_threshold = DCVS_MIN_DISPLAY_BUFF;
		dcvs->max_threshold = output_buf_req->buffer_count_actual;
		if (dcvs->max_threshold <= dcvs->min_threshold)
			dcvs->max_threshold =
				dcvs->min_threshold + DCVS_BUFFER_SAFEGUARD;

	dcvs->threshold_disp_buf_low =
		clamp(dcvs->threshold_disp_buf_low,
				dcvs->min_threshold,
				dcvs->max_threshold);

	dcvs->threshold_disp_buf_high =
		clamp(dcvs->threshold_disp_buf_high,
				dcvs->min_threshold,
				dcvs->max_threshold);
	}

	if (dcvs->threshold_disp_buf_high - dcvs->threshold_disp_buf_low
		< DCVS_MIN_THRESHOLD_DIFF) {
		if (dcvs->max_threshold - dcvs->min_threshold <=
			DCVS_MIN_THRESHOLD_DIFF) {
		dcvs->threshold_disp_buf_low = dcvs->min_threshold;
		dcvs->threshold_disp_buf_high = dcvs->max_threshold;
		} else if (dcvs->threshold_disp_buf_low ==
			dcvs->min_threshold) {
			dcvs->threshold_disp_buf_high =
				dcvs->threshold_disp_buf_low +
				DCVS_MIN_THRESHOLD_DIFF;
		} else {
			dcvs->threshold_disp_buf_high = dcvs->max_threshold;
			dcvs->threshold_disp_buf_low =
				dcvs->max_threshold - DCVS_MIN_THRESHOLD_DIFF;
		}
	}
	msm_comm_print_dcvs_stats(dcvs);
}
@@ -1871,12 +1832,12 @@ void msm_comm_init_dcvs(struct msm_vidc_inst *inst)
	inst->dcvs.threshold_disp_buf_low = DCVS_TURBO_THRESHOLD;
}

static void msm_comm_monitor_ftb(struct msm_vidc_inst *inst)
static void msm_comm_dcvs_monitor_buffer(struct msm_vidc_inst *inst)
{
	int new_ftb = 0;
	int new_ftb_temp = 0;
	int i;
	int new_ftb, i, prev_buf_count;
	int fw_pending_bufs, total_output_buf, buffers_outside_fw;
	struct dcvs_stats *dcvs;
	struct hal_buffer_requirements *output_buf_req;

	if (!inst) {
		dprintk(VIDC_ERR, "%s Invalid args: %p\n", __func__, inst);
@@ -1884,90 +1845,67 @@ static void msm_comm_monitor_ftb(struct msm_vidc_inst *inst)
	}

	dcvs = &inst->dcvs;
	/* update FTB stats only in nominal mode */
	if (dcvs->load == dcvs->load_low) {
		dcvs->num_ftb[dcvs->ftb_index] =
			inst->count.ftb - dcvs->prev_ftb_count;
		dcvs->ftb_index =
			(dcvs->ftb_index + 1) % DCVS_FTB_WINDOW;
		if (dcvs->ftb_counter < DCVS_FTB_WINDOW)
			dcvs->ftb_counter++;
	}
	dcvs->prev_ftb_count = inst->count.ftb;

	if (dcvs->load == dcvs->load_low
		&& dcvs->change_initial_freq
		&& dcvs->ftb_counter == DCVS_FTB_WINDOW) {
	mutex_lock(&inst->lock);
	output_buf_req = get_buff_req_buffer(inst,
	msm_comm_get_hal_output_buffer(inst));

		/*
		* Low threshold =
		* min( max(avg of 4 FTB in stats window), max threshold)
		*/
		for (i = 0; i <= dcvs->ftb_counter - DCVS_FTB_STAT_SAMPLES;
			i++) {
			new_ftb_temp = SUM_ARRAY(dcvs->num_ftb, i,
				i + DCVS_FTB_STAT_SAMPLES - 1);
			new_ftb_temp = DIV_ROUND_UP(new_ftb_temp,
				DCVS_FTB_STAT_SAMPLES);
			new_ftb = max(new_ftb_temp, new_ftb);
	if (!output_buf_req) {
		dprintk(VIDC_ERR, "%s : Get output buffer req failed %p\n",
			__func__, inst);
		mutex_unlock(&inst->lock);
		return;
	}
		dprintk(VIDC_PROF,
			"DCVS: Max FTB_count for Low_thr %d\n", new_ftb);

		new_ftb = min(new_ftb, dcvs->max_threshold);
		dcvs->threshold_disp_buf_low = new_ftb;
	total_output_buf = output_buf_req->buffer_count_actual;
	fw_pending_bufs = get_pending_bufs_fw(inst) + 1;
	mutex_unlock(&inst->lock);
	buffers_outside_fw = total_output_buf - fw_pending_bufs;
	dcvs->num_ftb[dcvs->ftb_index] = buffers_outside_fw;
	dcvs->ftb_index = (dcvs->ftb_index + 1) % DCVS_FTB_WINDOW;

		/*
		* High Threshold =
		* max(max(8, Low threshold + 4),
		* round( (sumof(num_ftb[])*8)/DCVS_FTB_WINDOW)
		*/
		new_ftb = 0;
		for (i = 0; i < dcvs->ftb_counter; i++)
			new_ftb += dcvs->num_ftb[i];
	if (dcvs->ftb_counter < DCVS_FTB_WINDOW)
		dcvs->ftb_counter++;

		new_ftb = ((new_ftb * DCVS_EMP_THRESHOLD_HIGH) /
			DCVS_FTB_WINDOW);
	dprintk(VIDC_PROF,
			"DCVS: Avg FTB_count for High_Thr %d\n",
			new_ftb);
		"DCVS: ftb_counter %d\n", dcvs->ftb_counter);

		if (dcvs->threshold_disp_buf_low +
			DCVS_TURBO_THRESHOLD > DCVS_NOMINAL_THRESHOLD) {
	if (dcvs->ftb_counter == DCVS_FTB_WINDOW) {
		new_ftb = 0;
		for (i = 0; i < dcvs->ftb_counter; i++) {
			if (dcvs->num_ftb[i] > new_ftb)
				new_ftb = dcvs->num_ftb[i];
		}
		dcvs->threshold_disp_buf_high = new_ftb;
		if (dcvs->threshold_disp_buf_high <=
			dcvs->threshold_disp_buf_low) {
			dcvs->threshold_disp_buf_high =
				dcvs->threshold_disp_buf_low +
				DCVS_TURBO_THRESHOLD;
		} else {
			dcvs->threshold_disp_buf_high =
				DCVS_NOMINAL_THRESHOLD;
				DCVS_BUFFER_SAFEGUARD;
		}

		if (new_ftb > dcvs->threshold_disp_buf_high)
			dcvs->threshold_disp_buf_high = new_ftb;

		dcvs->threshold_disp_buf_high =
			clamp(dcvs->threshold_disp_buf_high,
				dcvs->min_threshold,
				dcvs->max_threshold);

		/*
		* Ensure that high threshold is
		* always greater than low threshold
		*/

		if (dcvs->threshold_disp_buf_high <
				dcvs->threshold_disp_buf_low) {
			dcvs->threshold_disp_buf_high =
				dcvs->threshold_disp_buf_low +
				DCVS_BUFFER_SAFEGUARD;
	}
	if (dcvs->ftb_counter == DCVS_FTB_WINDOW &&
			dcvs->load == dcvs->load_low) {
		prev_buf_count =
			dcvs->num_ftb[((dcvs->ftb_index - 2 +
				DCVS_FTB_WINDOW) % DCVS_FTB_WINDOW)];
		if (prev_buf_count == DCVS_MIN_DISPLAY_BUFF &&
			buffers_outside_fw == DCVS_MIN_DISPLAY_BUFF) {
			dcvs->transition_turbo = true;
		} else if (buffers_outside_fw > DCVS_MIN_DISPLAY_BUFF &&
			(buffers_outside_fw -
			 (prev_buf_count - buffers_outside_fw))
			< DCVS_MIN_DISPLAY_BUFF){
			dcvs->transition_turbo = true;
		}

	dprintk(VIDC_DBG,
		"DCVS: threshold_low %d, threshold_high %d, load %d\n",
		dcvs->threshold_disp_buf_low,
		dcvs->threshold_disp_buf_high,
		dcvs->load);
	}
	dprintk(VIDC_PROF,
		"DCVS: total_output_buf %d buffers_outside_fw %d load %d transition_turbo %d\n",
		total_output_buf, buffers_outside_fw, dcvs->load_low,
		dcvs->transition_turbo);
}

/*
@@ -1976,6 +1914,7 @@ static void msm_comm_monitor_ftb(struct msm_vidc_inst *inst)
* 0 indicates call made from qbuf that increases clock
* based on DCVS algorithm
*/

static int msm_comm_scale_clocks_dcvs(struct msm_vidc_inst *inst, bool fbd)
{
	int rc = 0;
@@ -1995,12 +1934,13 @@ static int msm_comm_scale_clocks_dcvs(struct msm_vidc_inst *inst, bool fbd)
	core = inst->core;
	hdev = core->device;
	dcvs = &inst->dcvs;
	mutex_lock(&inst->lock);
	fw_pending_bufs = get_pending_bufs_fw(inst) +
		(fbd ? 0 : 1);

	output_buf_req = get_buff_req_buffer(inst,
		msm_comm_get_hal_output_buffer(inst));

	mutex_unlock(&inst->lock);
	if (!output_buf_req) {
		dprintk(VIDC_ERR,
			"%s: No buffer requirement for buffer type %x\n",
@@ -2018,29 +1958,30 @@ static int msm_comm_scale_clocks_dcvs(struct msm_vidc_inst *inst, bool fbd)
	/* Buffers outside FW are with display */
	buffers_outside_fw = total_output_buf - fw_pending_bufs;

	if (fbd) {
		/*
		* scale clock only after display has buffers
		* more than high threshold
		*/
		if (!dcvs->change_initial_freq &&
			buffers_outside_fw >= dcvs->threshold_disp_buf_high)
			dcvs->change_initial_freq = true;

	if (buffers_outside_fw >= dcvs->threshold_disp_buf_high &&
			!dcvs->prev_freq_increased) {
			!dcvs->prev_freq_increased &&
			dcvs->load > dcvs->load_low) {
			dcvs->load = dcvs->load_low;
			dcvs->prev_freq_lowered = true;
		} else
			dcvs->prev_freq_increased = false;
	} else if (dcvs->transition_turbo && dcvs->load == dcvs->load_low) {
			dcvs->load = dcvs->load_high;
			dcvs->prev_freq_increased = true;
			dcvs->prev_freq_lowered = false;
			dcvs->transition_turbo = false;
	} else {
			dcvs->prev_freq_increased = false;
			dcvs->prev_freq_lowered = false;
	}

		if (dcvs->prev_freq_lowered) {
	if (dcvs->prev_freq_lowered || dcvs->prev_freq_increased) {
		dprintk(VIDC_PROF,
				"DCVS: fbd clock set = %d tot_output_buf = %d buffers_outside_fw %d threshold_high %d\n",
			"DCVS: clock set = %d tot_output_buf = %d buffers_outside_fw %d threshold_high %d transition_turbo %d\n",
			dcvs->load,
			total_output_buf,
			buffers_outside_fw,
				dcvs->threshold_disp_buf_high);
			dcvs->threshold_disp_buf_high,
			dcvs->transition_turbo);

		/* HFI call to scale clock */
		rc = call_hfi_op(hdev, scale_clocks,
@@ -2050,33 +1991,11 @@ static int msm_comm_scale_clocks_dcvs(struct msm_vidc_inst *inst, bool fbd)
			dprintk(VIDC_ERR,
				"Failed to set clock rate in FBD: %d\n",
				rc);
		}
	} else {
		if (buffers_outside_fw <= dcvs->threshold_disp_buf_low &&
			!dcvs->prev_freq_lowered) {
			dcvs->load = dcvs->load_high;
			dcvs->prev_freq_increased = true;
	} else
			dcvs->prev_freq_increased = false;

		if (dcvs->prev_freq_increased) {
		dprintk(VIDC_PROF,
				"DCVS: ftb clock set = %d tot_output_buf = %d buffers_outside_fw %d, threshold_low %d\n",
				dcvs->load,
				total_output_buf,
				buffers_outside_fw,
				dcvs->threshold_disp_buf_low);

			/* HFI call to scale clock */
			rc = call_hfi_op(hdev, scale_clocks,
				hdev->hfi_device_data, dcvs->load,
				codecs_enabled);
			if (rc)
				dprintk(VIDC_ERR,
				"Failed to set clock rate in FTB %d\n",
				rc);
		}
	}
			"DCVS: clock old = %d tot_output_buf = %d buffers_outside_fw %d threshold_high %d transition_turbo %d\n",
			dcvs->load, total_output_buf, buffers_outside_fw,
			dcvs->threshold_disp_buf_high, dcvs->transition_turbo);
	return rc;
}

@@ -3481,6 +3400,7 @@ int msm_comm_qbuf(struct vb2_buffer *vb)
						__func__, inst->dcvs_mode);
				}
				if (msm_vidc_dcvs_mode && inst->dcvs_mode) {
					msm_comm_dcvs_monitor_buffer(inst);
					rc = msm_comm_scale_clocks_dcvs(
							inst, false);
					if (rc)
@@ -4505,9 +4425,6 @@ static int msm_comm_check_dcvs_supported(struct msm_vidc_inst *inst)
				__func__, HAL_BUFFER_OUTPUT);
			return -EINVAL;
		}
		if (inst->count.ftb - dcvs->prev_ftb_count >
			output_buf_req->buffer_count_actual)
				dcvs->prev_ftb_count = inst->count.ftb;
	} else {
		rc = -ENOTSUPP;
		/*
+1 −1
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@ int msm_fw_low_power_mode = 0x1;
int msm_vidc_hw_rsp_timeout = 1000;
u32 msm_fw_coverage = 0x0;
int msm_vidc_vpe_csc_601_to_709 = 0x0;
int msm_vidc_dcvs_mode = 0x0;
int msm_vidc_dcvs_mode = 0x1;
int msm_vidc_sys_idle_indicator = 0x0;
u32 msm_vidc_firmware_unload_delay = 15000;

+4 −15
Original line number Diff line number Diff line
@@ -64,30 +64,20 @@
#define NUM_MBS_PER_FRAME(__height, __width) \
	((ALIGN(__height, 16) / 16) * (ALIGN(__width, 16) / 16))

/* Minimum number of display buffers */
#define DCVS_MIN_DISPLAY_BUFF 4
/* Default threshold to reduce the core frequency */
#define DCVS_NOMINAL_THRESHOLD 8
/* Default threshold to increase the core frequency */
#define DCVS_TURBO_THRESHOLD 4
/* Instance max load above which DCVS kicks in */
#define DCVS_NOMINAL_LOAD NUM_MBS_PER_SEC(1088, 1920, 60)
/* Considering one output buffer with core */
#define DCVS_BUFFER_WITH_DEC 1
/* Considering one safeguard buffer */
#define DCVS_BUFFER_SAFEGUARD 1
/* Considering one output buffer in transition after decode */
#define DCVS_BUFFER_RELEASED_DEC 1
/* Considering at least two FTB's between each FBD */
#define DCVS_MIN_DRAIN_RATE 2
/* Ensures difference of 4 between min and max threshold always*/
#define DCVS_MIN_THRESHOLD_DIFF 4
/* Maintains the number of FTB's between each FBD over a window */
#define DCVS_FTB_WINDOW 16
/* Empirical number arrived at to calculate the high threshold*/
#define DCVS_EMP_THRESHOLD_HIGH 8
#define DCVS_FTB_WINDOW 32
/* Supported DCVS MBs per frame */
#define DCVS_MIN_SUPPORTED_MBPERFRAME NUM_MBS_PER_FRAME(2160, 3840)
/* Window size used to calculate the low threshold */
#define DCVS_FTB_STAT_SAMPLES 4

enum vidc_ports {
	OUTPUT_PORT,
@@ -207,12 +197,11 @@ struct buf_count {

struct dcvs_stats {
	int num_ftb[DCVS_FTB_WINDOW];
	bool transition_turbo;
	int ftb_index;
	int ftb_counter;
	int prev_ftb_count;
	bool prev_freq_lowered;
	bool prev_freq_increased;
	bool change_initial_freq;
	int threshold_disp_buf_high;
	int threshold_disp_buf_low;
	int load;