msm: vidc: Simplify DCVS algorithm

Unify Encoder and Decoder DCVS by removing complex buffer
tracking logic. DCVS is based on simple logic now.

    - More YUV buffers with Venus --> Venus is Late -->
          Increase Venus clock.
    - Less YUV buffers with Venus --> Venus is not late -->
          Decrease Venus clock.

CRs-Fixed: 2012520
Change-Id: I47870747dd73e20e1be1fd156ed8ae89ca4b824a
Signed-off-by: Praneeth Paladugu <ppaladug@codeaurora.org>
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index fd6e681..abc6cc8 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -883,6 +883,7 @@
 		property_id = HAL_PARAM_VDEC_SYNC_FRAME_DECODE;
 		hal_property.enable = ctrl->val;
 		pdata = &hal_property;
+		msm_dcvs_try_enable(inst);
 		break;
 	case V4L2_CID_MPEG_VIDC_VIDEO_SECURE:
 		inst->flags |= VIDC_SECURE;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 475b696..2d803bb 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -1390,7 +1390,7 @@
 			"Failed to move inst: %pK to start done state\n", inst);
 		goto fail_start;
 	}
-	msm_dcvs_init_load(inst);
+	msm_dcvs_init(inst);
 	if (msm_comm_get_stream_output_mode(inst) ==
 			HAL_VIDEO_DECODER_SECONDARY) {
 		rc = msm_comm_queue_output_buffers(inst);
@@ -1953,7 +1953,6 @@
 	if (rc)
 		goto fail_bufq_capture;
 
-	msm_dcvs_init(inst);
 	rc = vb2_bufq_init(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
 			session_type);
 	if (rc) {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
index 73a3967..70427d3 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
@@ -16,13 +16,6 @@
 #include "msm_vidc_debug.h"
 #include "msm_vidc_clocks.h"
 
-#define IS_VALID_DCVS_SESSION(__cur_mbpf, __min_mbpf) \
-		((__cur_mbpf) >= (__min_mbpf))
-
-static bool msm_dcvs_check_supported(struct msm_vidc_inst *inst);
-static int msm_dcvs_enc_scale_clocks(struct msm_vidc_inst *inst);
-static int msm_dcvs_dec_scale_clocks(struct msm_vidc_inst *inst, bool fbd);
-
 int msm_comm_vote_bus(struct msm_vidc_core *core)
 {
 	int rc = 0, vote_data_count = 0, i = 0;
@@ -103,6 +96,82 @@
 	return rc;
 }
 
+static inline int get_pending_bufs_fw(struct msm_vidc_inst *inst)
+{
+	int fw_out_qsize = 0, buffers_in_driver = 0;
+
+	/*
+	 * DCVS always operates on Uncompressed buffers.
+	 * For Decoders, FTB and Encoders, ETB.
+	 */
+
+	if (inst->state >= MSM_VIDC_OPEN_DONE &&
+			inst->state < MSM_VIDC_STOP_DONE) {
+		if (inst->session_type == MSM_VIDC_DECODER)
+			fw_out_qsize = inst->count.ftb - inst->count.fbd;
+		else
+			fw_out_qsize = inst->count.etb - inst->count.ebd;
+
+		buffers_in_driver = inst->buffers_held_in_driver;
+	}
+
+	return fw_out_qsize + buffers_in_driver;
+}
+
+static int msm_dcvs_scale_clocks(struct msm_vidc_inst *inst)
+{
+	int rc = 0;
+	int fw_pending_bufs = 0;
+	int total_output_buf = 0;
+	int buffers_outside_fw = 0;
+	struct msm_vidc_core *core;
+	struct hal_buffer_requirements *output_buf_req;
+	struct dcvs_stats *dcvs;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s Invalid params\n", __func__);
+		return -EINVAL;
+	}
+	if (!inst->dcvs_mode) {
+		dprintk(VIDC_DBG, "DCVS is not enabled\n");
+		return 0;
+	}
+
+	dcvs = &inst->dcvs;
+
+	core = inst->core;
+	mutex_lock(&inst->lock);
+	fw_pending_bufs = get_pending_bufs_fw(inst);
+
+	output_buf_req = get_buff_req_buffer(inst,
+			dcvs->buffer_type);
+	mutex_unlock(&inst->lock);
+	if (!output_buf_req) {
+		dprintk(VIDC_ERR,
+				"%s: No buffer requirement for buffer type %x\n",
+				__func__, dcvs->buffer_type);
+		return -EINVAL;
+	}
+
+	/* Total number of output buffers */
+	total_output_buf = output_buf_req->buffer_count_actual;
+
+	/* Buffers outside FW are with display */
+	buffers_outside_fw = total_output_buf - fw_pending_bufs;
+	dprintk(VIDC_DBG,
+		"Counts : total_output_buf = %d fw_pending_bufs = %d buffers_outside_fw = %d\n",
+		total_output_buf, fw_pending_bufs, buffers_outside_fw);
+
+	if (buffers_outside_fw >=  dcvs->min_threshold &&
+			dcvs->load > dcvs->load_low) {
+		dcvs->load = dcvs->load_low;
+	} else if (buffers_outside_fw < dcvs->min_threshold &&
+			dcvs->load == dcvs->load_low) {
+		dcvs->load = dcvs->load_high;
+	}
+	return rc;
+}
+
 static void msm_vidc_update_freq_entry(struct msm_vidc_inst *inst,
 	unsigned long freq, ion_phys_addr_t device_addr)
 {
@@ -140,10 +209,12 @@
 			temp->freq = 0;
 	}
 	mutex_unlock(&inst->freqs.lock);
+
+	inst->dcvs.buffer_counter++;
 }
 
 
-static unsigned long msm_vidc_get_highest_freq(struct msm_vidc_inst *inst)
+static unsigned long msm_vidc_adjust_freq(struct msm_vidc_inst *inst)
 {
 	struct vidc_freq_data *temp;
 	unsigned long freq = 0;
@@ -154,6 +225,15 @@
 	}
 	mutex_unlock(&inst->freqs.lock);
 
+	/* If current requirement is within DCVS limits, try DCVS. */
+
+	if (freq < inst->dcvs.load_high) {
+		dprintk(VIDC_DBG, "Calling DCVS now\n");
+		// TODO calling DCVS here may reduce the residency. Re-visit.
+		msm_dcvs_scale_clocks(inst);
+		freq = inst->dcvs.load;
+	}
+
 	return freq;
 }
 
@@ -285,7 +365,7 @@
 	u32 filled_len = 0;
 	ion_phys_addr_t device_addr = 0;
 
-	if (inst->count.fbd < DCVS_FTB_WINDOW) {
+	if (inst->dcvs.buffer_counter < DCVS_FTB_WINDOW) {
 		freq = msm_vidc_max_freq(inst);
 		goto decision_done;
 	}
@@ -309,7 +389,7 @@
 
 	msm_vidc_update_freq_entry(inst, freq, device_addr);
 
-	freq = msm_vidc_get_highest_freq(inst);
+	freq = msm_vidc_adjust_freq(inst);
 
 decision_done:
 	inst->freq = freq;
@@ -346,35 +426,16 @@
 		dprintk(VIDC_ERR, "%s: Invalid args: %p\n", __func__, inst);
 		return -EINVAL;
 	}
-	inst->dcvs_mode = msm_dcvs_check_supported(inst);
-	return 0;
-}
-
-static inline int msm_dcvs_count_active_instances(struct msm_vidc_core *core,
-	enum session_type session_type)
-{
-	int active_instances = 0;
-	struct msm_vidc_inst *temp = NULL;
-
-	if (!core) {
-		dprintk(VIDC_ERR, "%s: Invalid args: %pK\n", __func__, core);
-		return -EINVAL;
+	if (inst->flags & VIDC_THUMBNAIL) {
+		dprintk(VIDC_PROF, "Thumbnail sessions don't need DCVS : %pK\n",
+			inst);
+		return false;
 	}
+	inst->dcvs_mode = true;
 
-	/* DCVS condition is as following
-	 * Decoder DCVS : Only for ONE decoder session.
-	 * Encoder DCVS : Only for ONE encoder session + ONE decoder session
-	 */
-	mutex_lock(&core->lock);
-	list_for_each_entry(temp, &core->instances, list) {
-		if (temp->state >= MSM_VIDC_OPEN_DONE &&
-			temp->state < MSM_VIDC_STOP_DONE &&
-			(temp->session_type == session_type ||
-			 temp->session_type == MSM_VIDC_ENCODER))
-			active_instances++;
-	}
-	mutex_unlock(&core->lock);
-	return active_instances;
+	// TODO : Update with proper number based on on-target tuning.
+	inst->dcvs.extra_buffer_count = DCVS_DEC_EXTRA_OUTPUT_BUFFERS;
+	return true;
 }
 
 static bool msm_dcvs_check_codec_supported(int fourcc,
@@ -406,7 +467,6 @@
 
 int msm_comm_init_clocks_and_bus_data(struct msm_vidc_inst *inst)
 {
-
 	int rc = 0, j = 0;
 	struct clock_freq_table *clk_freq_tbl = NULL;
 	struct clock_profile_entry *entry = NULL;
@@ -442,92 +502,6 @@
 	return rc;
 }
 
-static void msm_dcvs_update_dcvs_params(int idx, struct msm_vidc_inst *inst)
-{
-	struct dcvs_stats *dcvs = NULL;
-	struct msm_vidc_platform_resources *res = NULL;
-	struct dcvs_table *table = NULL;
-
-	if (!inst || !inst->core) {
-		dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, inst);
-		return;
-	}
-
-	dcvs = &inst->dcvs;
-	res = &inst->core->resources;
-	table = res->dcvs_tbl;
-
-	dcvs->load_low = table[idx].load_low;
-	dcvs->load_high = table[idx].load_high;
-	dcvs->supported_codecs = table[idx].supported_codecs;
-}
-
-static void msm_dcvs_enc_check_and_scale_clocks(struct msm_vidc_inst *inst)
-{
-	int rc = 0;
-
-	if (inst->session_type == MSM_VIDC_ENCODER &&
-		msm_vidc_enc_dcvs_mode) {
-		rc = msm_dcvs_enc_scale_clocks(inst);
-		if (rc) {
-			dprintk(VIDC_DBG,
-				"ENC_DCVS: error while scaling clocks\n");
-		}
-	}
-}
-
-static void msm_dcvs_dec_check_and_scale_clocks(struct msm_vidc_inst *inst)
-{
-	int rc = 0;
-
-	if (inst->session_type == MSM_VIDC_DECODER &&
-		msm_vidc_dec_dcvs_mode) {
-		msm_dcvs_monitor_buffer(inst);
-		rc = msm_dcvs_dec_scale_clocks(inst, false);
-		if (rc) {
-			dprintk(VIDC_ERR,
-					"%s: Failed to scale clocks in DCVS: %d\n",
-					__func__, rc);
-		}
-	}
-}
-
-void msm_dcvs_check_and_scale_clocks(struct msm_vidc_inst *inst, bool is_etb)
-{
-	if (!inst) {
-		dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, inst);
-		return;
-	}
-	msm_dcvs_try_enable(inst);
-	if (!inst->dcvs_mode) {
-		dprintk(VIDC_DBG, "DCVS is not enabled\n");
-		return;
-	}
-
-	if (is_etb)
-		msm_dcvs_enc_check_and_scale_clocks(inst);
-	else
-		msm_dcvs_dec_check_and_scale_clocks(inst);
-}
-
-static inline int get_pending_bufs_fw(struct msm_vidc_inst *inst)
-{
-	int fw_out_qsize = 0, buffers_in_driver = 0;
-
-	if (!inst) {
-		dprintk(VIDC_ERR, "%s Invalid args\n", __func__);
-		return -EINVAL;
-	}
-
-	if (inst->state >= MSM_VIDC_OPEN_DONE &&
-		inst->state < MSM_VIDC_STOP_DONE) {
-		fw_out_qsize = inst->count.ftb - inst->count.fbd;
-		buffers_in_driver = inst->buffers_held_in_driver;
-	}
-
-	return fw_out_qsize + buffers_in_driver;
-}
-
 static inline void msm_dcvs_print_dcvs_stats(struct dcvs_stats *dcvs)
 {
 	dprintk(VIDC_DBG,
@@ -536,23 +510,18 @@
 		dcvs->load_high);
 
 	dprintk(VIDC_DBG,
-		"DCVS: ThrDispBufLow %d, ThrDispBufHigh %d\n",
-		dcvs->threshold_disp_buf_low,
-		dcvs->threshold_disp_buf_high);
-
-	dprintk(VIDC_DBG,
 		"DCVS: min_threshold %d, max_threshold %d\n",
 		dcvs->min_threshold, dcvs->max_threshold);
 }
 
-void msm_dcvs_init_load(struct msm_vidc_inst *inst)
+void msm_dcvs_init(struct msm_vidc_inst *inst)
 {
 	struct msm_vidc_core *core;
-	struct hal_buffer_requirements *output_buf_req;
+	int i = 0;
+	struct allowed_clock_rates_table *allowed_clks_tbl = NULL;
+	u64 total_freq = 0, rate = 0, load;
+	int cycles;
 	struct dcvs_stats *dcvs;
-	struct dcvs_table *table;
-	struct msm_vidc_platform_resources *res = NULL;
-	int i, num_rows, fourcc;
 
 	dprintk(VIDC_DBG, "Init DCVS Load\n");
 
@@ -563,410 +532,38 @@
 
 	core = inst->core;
 	dcvs = &inst->dcvs;
-	res = &core->resources;
-	dcvs->load = msm_comm_get_inst_load(inst, LOAD_CALC_NO_QUIRKS);
-
-	num_rows = res->dcvs_tbl_size;
-	table = res->dcvs_tbl;
-
-	if (!num_rows || !table) {
-		dprintk(VIDC_ERR,
-				"%s: Dcvs table entry not found.\n", __func__);
-		return;
-	}
-
-	fourcc = inst->session_type == MSM_VIDC_DECODER ?
-				inst->fmts[OUTPUT_PORT].fourcc :
-				inst->fmts[CAPTURE_PORT].fourcc;
-
-	for (i = 0; i < num_rows; i++) {
-		bool matches = msm_dcvs_check_codec_supported(
-					fourcc,
-					table[i].supported_codecs,
-					inst->session_type);
-		if (!matches)
-			continue;
-
-		if (dcvs->load > table[i].load) {
-			msm_dcvs_update_dcvs_params(i, inst);
-			break;
-		}
-	}
-
-	if (inst->session_type == MSM_VIDC_ENCODER)
-		goto print_stats;
-
-	output_buf_req = get_buff_req_buffer(inst,
-		msm_comm_get_hal_output_buffer(inst));
-
-	if (!output_buf_req) {
-		dprintk(VIDC_ERR,
-			"%s: No buffer requirement for buffer type %x\n",
-			__func__, HAL_BUFFER_OUTPUT);
-		return;
-	}
-
-	dcvs->transition_turbo = false;
-
-	/* calculating the min and max threshold */
-	if (output_buf_req->buffer_count_actual) {
-		dcvs->min_threshold = output_buf_req->buffer_count_actual -
-			output_buf_req->buffer_count_min -
-			msm_dcvs_get_extra_buff_count(inst) + 1;
-		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 = dcvs->min_threshold;
-		dcvs->threshold_disp_buf_high = dcvs->max_threshold;
-	}
-
-print_stats:
-	msm_dcvs_print_dcvs_stats(dcvs);
-}
-
-void msm_dcvs_init(struct msm_vidc_inst *inst)
-{
-	dprintk(VIDC_DBG, "Init DCVS Struct\n");
-
-	if (!inst) {
-		dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, inst);
-		return;
-	}
-
-	inst->dcvs = (struct dcvs_stats){ {0} };
-	inst->dcvs.threshold_disp_buf_high = DCVS_NOMINAL_THRESHOLD;
-	inst->dcvs.threshold_disp_buf_low = DCVS_TURBO_THRESHOLD;
-}
-
-void msm_dcvs_monitor_buffer(struct msm_vidc_inst *inst)
-{
-	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: %pK\n", __func__, inst);
-		return;
-	}
-	dcvs = &inst->dcvs;
-
-	mutex_lock(&inst->lock);
-	output_buf_req = get_buff_req_buffer(inst,
-				msm_comm_get_hal_output_buffer(inst));
-	if (!output_buf_req) {
-		dprintk(VIDC_ERR, "%s : Get output buffer req failed %pK\n",
-			__func__, inst);
-		mutex_unlock(&inst->lock);
-		return;
-	}
-
-	total_output_buf = output_buf_req->buffer_count_actual;
-	fw_pending_bufs = get_pending_bufs_fw(inst);
-	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;
-
-	if (dcvs->ftb_counter < DCVS_FTB_WINDOW)
-		dcvs->ftb_counter++;
-
-	dprintk(VIDC_PROF,
-		"DCVS: ftb_counter %d\n", dcvs->ftb_counter);
-
-	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_BUFFER_SAFEGUARD) {
-			dcvs->threshold_disp_buf_high =
-				dcvs->threshold_disp_buf_low +
-				DCVS_BUFFER_SAFEGUARD
-				+ (DCVS_BUFFER_SAFEGUARD == 0);
-		}
-
-		dcvs->threshold_disp_buf_high =
-			clamp(dcvs->threshold_disp_buf_high,
-				dcvs->min_threshold,
-				dcvs->max_threshold);
-	}
-
-	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->threshold_disp_buf_low &&
-			buffers_outside_fw <= dcvs->threshold_disp_buf_low) {
-			dcvs->transition_turbo = true;
-		} else if (buffers_outside_fw > dcvs->threshold_disp_buf_low &&
-			(buffers_outside_fw -
-			 (prev_buf_count - buffers_outside_fw))
-			< dcvs->threshold_disp_buf_low){
-			dcvs->transition_turbo = true;
-		}
-	}
-
-	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);
-}
-
-static int msm_dcvs_enc_scale_clocks(struct msm_vidc_inst *inst)
-{
-	int rc = 0, fw_pending_bufs = 0, total_input_buf = 0;
-	struct msm_vidc_core *core;
-	struct dcvs_stats *dcvs;
-
-	if (!inst || !inst->core || !inst->core->device) {
-		dprintk(VIDC_ERR, "%s Invalid params\n", __func__);
-		return -EINVAL;
-	}
-
-	core = inst->core;
-	dcvs = &inst->dcvs;
-
-	mutex_lock(&inst->lock);
-	total_input_buf = inst->buff_req.buffer[0].buffer_count_actual;
-	fw_pending_bufs = (inst->count.etb - inst->count.ebd);
-	mutex_unlock(&inst->lock);
-
-	dprintk(VIDC_PROF,
-		"DCVS: total_input_buf %d, fw_pending_bufs %d\n",
-		total_input_buf, fw_pending_bufs);
-
-	if (dcvs->etb_counter < total_input_buf) {
-		dcvs->etb_counter++;
-		if (dcvs->etb_counter != total_input_buf)
-			return rc;
-	}
-
-	dprintk(VIDC_PROF,
-		"DCVS: total_input_buf %d, fw_pending_bufs %d etb_counter %d  dcvs->load %d\n",
-		total_input_buf, fw_pending_bufs,
-		dcvs->etb_counter, dcvs->load);
-
-	if (fw_pending_bufs <= DCVS_ENC_LOW_THR &&
-		dcvs->load > dcvs->load_low) {
-		dcvs->load = dcvs->load_low;
-		dcvs->prev_freq_lowered = true;
-	} else {
-		dcvs->prev_freq_lowered = false;
-	}
-
-	if (fw_pending_bufs >= DCVS_ENC_HIGH_THR &&
-		dcvs->load <= dcvs->load_low) {
-		dcvs->load = dcvs->load_high;
-		dcvs->prev_freq_increased = true;
-	} else {
-		dcvs->prev_freq_increased = false;
-	}
-
-	if (dcvs->prev_freq_lowered || dcvs->prev_freq_increased) {
-		dprintk(VIDC_PROF,
-			"DCVS: (Scaling Clock %s)  etb clock set = %d total_input_buf = %d fw_pending_bufs %d\n",
-			dcvs->prev_freq_lowered ? "Lower" : "Higher",
-			dcvs->load, total_input_buf, fw_pending_bufs);
-
-		if (rc) {
-			dprintk(VIDC_PROF,
-				"Failed to set clock rate in FBD: %d\n", rc);
-		}
-	} else {
-		dprintk(VIDC_PROF,
-			"DCVS: etb clock load_old = %d total_input_buf = %d fw_pending_bufs %d\n",
-			dcvs->load, total_input_buf, fw_pending_bufs);
-	}
-
-	return rc;
-}
-
-
-/*
- * In DCVS scale_clocks will be done both in qbuf and FBD
- * 1 indicates call made from fbd that lowers clock
- * 0 indicates call made from qbuf that increases clock
- * based on DCVS algorithm
- */
-
-static int msm_dcvs_dec_scale_clocks(struct msm_vidc_inst *inst, bool fbd)
-{
-	int rc = 0;
-	int fw_pending_bufs = 0;
-	int total_output_buf = 0;
-	int buffers_outside_fw = 0;
-	struct msm_vidc_core *core;
-	struct hal_buffer_requirements *output_buf_req;
-	struct dcvs_stats *dcvs;
-
-	if (!inst || !inst->core || !inst->core->device) {
-		dprintk(VIDC_ERR, "%s Invalid params\n", __func__);
-		return -EINVAL;
-	}
-	core = inst->core;
-	dcvs = &inst->dcvs;
-	mutex_lock(&inst->lock);
-	fw_pending_bufs = get_pending_bufs_fw(inst);
-
-	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",
-			__func__, HAL_BUFFER_OUTPUT);
-		return -EINVAL;
-	}
-
-	/* Total number of output buffers */
-	total_output_buf = output_buf_req->buffer_count_actual;
-
-	/* Buffers outside FW are with display */
-	buffers_outside_fw = total_output_buf - fw_pending_bufs;
-
-	if (buffers_outside_fw >= dcvs->threshold_disp_buf_high &&
-		!dcvs->prev_freq_increased &&
-		dcvs->load > dcvs->load_low) {
-		dcvs->load = dcvs->load_low;
-		dcvs->prev_freq_lowered = true;
-		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 || dcvs->prev_freq_increased) {
-		dprintk(VIDC_PROF,
-			"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->transition_turbo);
-
-		if (rc) {
-			dprintk(VIDC_ERR,
-				"Failed to set clock rate in FBD: %d\n", rc);
-		}
-	} else {
-		dprintk(VIDC_PROF,
-			"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;
-}
-
-static bool msm_dcvs_check_supported(struct msm_vidc_inst *inst)
-{
-	int num_mbs_per_frame = 0, instance_count = 0;
-	long int instance_load = 0;
-	long int dcvs_limit = 0;
-	struct msm_vidc_inst *temp = NULL;
-	struct msm_vidc_core *core;
-	struct hal_buffer_requirements *output_buf_req;
-	struct dcvs_stats *dcvs;
-	bool is_codec_supported = false;
-	bool is_dcvs_supported = true;
-	struct msm_vidc_platform_resources *res = NULL;
-
-	if (!inst || !inst->core || !inst->core->device) {
-		dprintk(VIDC_WARN, "%s: Invalid parameter\n", __func__);
-		return -EINVAL;
-	}
-
-	core = inst->core;
-	dcvs = &inst->dcvs;
-	res = &core->resources;
-
-	if (!res->dcvs_limit) {
-		dprintk(VIDC_WARN,
-				"%s: dcvs limit table not found\n", __func__);
-		return false;
-	}
-	instance_count = msm_dcvs_count_active_instances(core,
-		inst->session_type);
-	num_mbs_per_frame = msm_dcvs_get_mbs_per_frame(inst);
-	instance_load = msm_comm_get_inst_load(inst, LOAD_CALC_NO_QUIRKS);
-	dcvs_limit =
-		(long int)res->dcvs_limit[inst->session_type].min_mbpf *
-		res->dcvs_limit[inst->session_type].fps;
-	inst->dcvs.extra_buffer_count = 0;
-
-	if (!IS_VALID_DCVS_SESSION(num_mbs_per_frame,
-				res->dcvs_limit[inst->session_type].min_mbpf)) {
-		inst->dcvs.extra_buffer_count = 0;
-		is_dcvs_supported = false;
-		goto dcvs_decision_done;
-
-	}
-
-	if (inst->session_type == MSM_VIDC_DECODER) {
-		inst->dcvs.extra_buffer_count = DCVS_DEC_EXTRA_OUTPUT_BUFFERS;
-		output_buf_req = get_buff_req_buffer(inst,
-				msm_comm_get_hal_output_buffer(inst));
-		if (!output_buf_req) {
-			dprintk(VIDC_ERR,
-					"%s: No buffer requirement for buffer type %x\n",
-					__func__, HAL_BUFFER_OUTPUT);
-			return false;
-		}
-		is_codec_supported =
-			msm_dcvs_check_codec_supported(
-				inst->fmts[OUTPUT_PORT].fourcc,
-				inst->dcvs.supported_codecs,
-				inst->session_type);
-		if (!is_codec_supported ||
-				!msm_vidc_dec_dcvs_mode) {
-			inst->dcvs.extra_buffer_count = 0;
-			is_dcvs_supported = false;
-			goto dcvs_decision_done;
-		}
-		if (msm_comm_turbo_session(inst) ||
-			!IS_VALID_DCVS_SESSION(instance_load, dcvs_limit) ||
-			instance_count > 1)
-			is_dcvs_supported = false;
-	}
+	inst->dcvs = (struct dcvs_stats){0};
+	load = msm_comm_get_inst_load(inst, LOAD_CALC_NO_QUIRKS);
+	cycles = inst->entry->vpp_cycles;
+	allowed_clks_tbl = core->resources.allowed_clks_tbl;
 	if (inst->session_type == MSM_VIDC_ENCODER) {
-		inst->dcvs.extra_buffer_count = DCVS_ENC_EXTRA_OUTPUT_BUFFERS;
-		is_codec_supported =
-			msm_dcvs_check_codec_supported(
-				inst->fmts[CAPTURE_PORT].fourcc,
-				inst->dcvs.supported_codecs,
-				inst->session_type);
-		if (!is_codec_supported ||
-				!msm_vidc_enc_dcvs_mode) {
-			inst->dcvs.extra_buffer_count = 0;
-			is_dcvs_supported = false;
-			goto dcvs_decision_done;
-		}
-		if (msm_comm_turbo_session(inst) ||
-			!IS_VALID_DCVS_SESSION(instance_load, dcvs_limit) ||
-				instance_count > 1)
-			is_dcvs_supported = false;
+		cycles = inst->flags & VIDC_LOW_POWER ?
+			inst->entry->low_power_cycles :
+			cycles;
+
+		dcvs->buffer_type = HAL_BUFFER_INPUT;
+		// TODO : Update with proper no based on Buffer counts change.
+		dcvs->min_threshold = 7;
+	} else if (inst->session_type == MSM_VIDC_DECODER) {
+		dcvs->buffer_type = msm_comm_get_hal_output_buffer(inst);
+		// TODO : Update with proper no based on Buffer counts change.
+		dcvs->min_threshold = 4;
+	} else {
+		return;
 	}
-dcvs_decision_done:
-	if (!is_dcvs_supported) {
-		msm_comm_scale_clocks(inst);
-		if (instance_count > 1) {
-			mutex_lock(&core->lock);
-			list_for_each_entry(temp, &core->instances, list)
-				temp->dcvs_mode = false;
-			mutex_unlock(&core->lock);
-		}
+
+	total_freq = cycles * load;
+
+	for (i = core->resources.allowed_clks_tbl_size - 1; i >= 0; i--) {
+		rate = allowed_clks_tbl[i].clock_rate;
+		if (rate >= total_freq)
+			break;
 	}
-	return is_dcvs_supported;
+
+	dcvs->load = dcvs->load_high = rate;
+	dcvs->load_low = allowed_clks_tbl[i+1].clock_rate;
+
+	msm_dcvs_print_dcvs_stats(dcvs);
 }
 
 int msm_dcvs_get_extra_buff_count(struct msm_vidc_inst *inst)
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.h b/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
index 665aca8..0229ccbb 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
@@ -32,10 +32,7 @@
 #define DCVS_BUFFER_SAFEGUARD (DCVS_DEC_EXTRA_OUTPUT_BUFFERS - 1)
 
 void msm_dcvs_init(struct msm_vidc_inst *inst);
-void msm_dcvs_init_load(struct msm_vidc_inst *inst);
-void msm_dcvs_monitor_buffer(struct msm_vidc_inst *inst);
 int  msm_dcvs_get_extra_buff_count(struct msm_vidc_inst *inst);
-void msm_dcvs_check_and_scale_clocks(struct msm_vidc_inst *inst, bool is_etb);
 int msm_dcvs_try_enable(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);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 3a79f9a..4aaa525 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -1525,9 +1525,6 @@
 		inst->prop.width[OUTPUT_PORT] = event_notify->width;
 	}
 
-	if (inst->session_type == MSM_VIDC_DECODER)
-		msm_dcvs_init_load(inst);
-
 	rc = msm_vidc_check_session_supported(inst);
 	if (!rc) {
 		seq_changed_event.type = event;
@@ -3850,7 +3847,6 @@
 			data->timestamp, data->flags);
 		msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_FTB);
 	}
-
 }
 
 /*
@@ -4723,6 +4719,10 @@
 		return 0;
 	}
 
+	// Finish FLUSH As Soon As Possible.
+	inst->dcvs.buffer_counter = 0;
+	msm_comm_scale_clocks_and_bus(inst);
+
 	msm_comm_flush_dynamic_buffers(inst);
 
 	if (inst->state == MSM_VIDC_CORE_INVALID ||
@@ -5058,9 +5058,6 @@
 		return -ENOTSUPP;
 	}
 
-	if (!rc)
-		msm_dcvs_try_enable(inst);
-
 	if (!rc) {
 		if (inst->prop.width[CAPTURE_PORT] < capability->width.min ||
 			inst->prop.height[CAPTURE_PORT] <
@@ -5377,10 +5374,7 @@
 			if (rc)
 				dprintk(VIDC_WARN,
 					"Failed to set frame rate %d\n", rc);
-		} else {
-			msm_dcvs_init_load(inst);
 		}
-		msm_dcvs_try_enable(inst);
 	}
 exit:
 	return rc;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index 28612e3..8562e8f 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -206,23 +206,14 @@
 };
 
 struct dcvs_stats {
-	int num_ftb[DCVS_FTB_WINDOW];
-	bool transition_turbo;
-	int ftb_index;
-	int ftb_counter;
-	bool prev_freq_lowered;
-	bool prev_freq_increased;
-	int threshold_disp_buf_high;
-	int threshold_disp_buf_low;
+	int buffer_counter;
 	int load;
 	int load_low;
 	int load_high;
 	int min_threshold;
 	int max_threshold;
-	int etb_counter;
-	bool is_power_save_mode;
 	unsigned int extra_buffer_count;
-	u32 supported_codecs;
+	enum hal_buffer buffer_type;
 };
 
 struct profile_data {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
index fbf4474..8b9018c 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
@@ -90,18 +90,6 @@
 	res->pf_ver_tbl = NULL;
 }
 
-static inline void msm_vidc_free_dcvs_table(
-		struct msm_vidc_platform_resources *res)
-{
-	res->dcvs_tbl = NULL;
-}
-
-static inline void msm_vidc_free_dcvs_limit(
-		struct msm_vidc_platform_resources *res)
-{
-	res->dcvs_limit = NULL;
-}
-
 static inline void msm_vidc_free_imem_ab_table(
 		struct msm_vidc_platform_resources *res)
 {
@@ -163,8 +151,6 @@
 	msm_vidc_free_clock_table(res);
 	msm_vidc_free_regulator_table(res);
 	msm_vidc_free_platform_version_table(res);
-	msm_vidc_free_dcvs_table(res);
-	msm_vidc_free_dcvs_limit(res);
 	msm_vidc_free_cycles_per_mb_table(res);
 	msm_vidc_free_allowed_clocks_table(res);
 	msm_vidc_free_reg_table(res);
@@ -547,94 +533,6 @@
 	return rc;
 }
 
-static int msm_vidc_load_dcvs_table(struct msm_vidc_platform_resources *res)
-{
-	int rc = 0;
-	int num_elements = 0;
-	struct platform_device *pdev = res->pdev;
-
-	if (!of_find_property(pdev->dev.of_node, "qcom,dcvs-tbl", NULL)) {
-		/*
-		 * qcom,dcvs-tbl is an optional property. Incase qcom,dcvs-limit
-		 * property is present, it becomes mandatory. It likely won't
-		 * be present on targets that does not support the feature
-		 */
-		dprintk(VIDC_DBG, "qcom,dcvs-tbl not found\n");
-		return 0;
-	}
-
-	num_elements = get_u32_array_num_elements(pdev->dev.of_node,
-			"qcom,dcvs-tbl");
-	num_elements /= sizeof(*res->dcvs_tbl) / sizeof(u32);
-	if (!num_elements) {
-		dprintk(VIDC_ERR, "no elements in dcvs table\n");
-		return rc;
-	}
-
-	res->dcvs_tbl = devm_kzalloc(&pdev->dev, num_elements *
-			sizeof(*res->dcvs_tbl), GFP_KERNEL);
-	if (!res->dcvs_tbl) {
-		dprintk(VIDC_ERR,
-				"%s Failed to alloc dcvs_tbl\n",
-				__func__);
-		return -ENOMEM;
-	}
-
-	if (of_property_read_u32_array(pdev->dev.of_node,
-		"qcom,dcvs-tbl", (u32 *)res->dcvs_tbl,
-		num_elements * sizeof(*res->dcvs_tbl) / sizeof(u32))) {
-		dprintk(VIDC_ERR, "Failed to read dcvs table\n");
-		msm_vidc_free_dcvs_table(res);
-		return -EINVAL;
-	}
-	res->dcvs_tbl_size = num_elements;
-
-	return rc;
-}
-
-static int msm_vidc_load_dcvs_limit(struct msm_vidc_platform_resources *res)
-{
-	int rc = 0;
-	int num_elements = 0;
-	struct platform_device *pdev = res->pdev;
-
-	if (!of_find_property(pdev->dev.of_node, "qcom,dcvs-limit", NULL)) {
-		/*
-		 * qcom,dcvs-limit is an optional property. Incase qcom,dcvs-tbl
-		 * property is present, it becomes mandatory. It likely won't
-		 * be present on targets that does not support the feature
-		 */
-		dprintk(VIDC_DBG, "qcom,dcvs-limit not found\n");
-		return 0;
-	}
-
-	num_elements = get_u32_array_num_elements(pdev->dev.of_node,
-			"qcom,dcvs-limit");
-	num_elements /= sizeof(*res->dcvs_limit) / sizeof(u32);
-	if (!num_elements) {
-		dprintk(VIDC_ERR, "no elements in dcvs limit\n");
-		res->dcvs_limit = NULL;
-		return rc;
-	}
-
-	res->dcvs_limit = devm_kzalloc(&pdev->dev, num_elements *
-			sizeof(*res->dcvs_limit), GFP_KERNEL);
-	if (!res->dcvs_limit) {
-		dprintk(VIDC_ERR,
-				"%s Failed to alloc dcvs_limit\n",
-				__func__);
-		return -ENOMEM;
-	}
-	if (of_property_read_u32_array(pdev->dev.of_node,
-		"qcom,dcvs-limit", (u32 *)res->dcvs_limit,
-		num_elements * sizeof(*res->dcvs_limit) / sizeof(u32))) {
-		dprintk(VIDC_ERR, "Failed to read dcvs limit\n");
-		msm_vidc_free_dcvs_limit(res);
-		return -EINVAL;
-	}
-	return rc;
-}
-
 static int msm_vidc_populate_bus(struct device *dev,
 		struct msm_vidc_platform_resources *res)
 {
@@ -986,14 +884,6 @@
 	if (rc)
 		dprintk(VIDC_ERR, "Failed to load pf version table: %d\n", rc);
 
-	rc = msm_vidc_load_dcvs_table(res);
-	if (rc)
-		dprintk(VIDC_WARN, "Failed to load dcvs table: %d\n", rc);
-
-	rc = msm_vidc_load_dcvs_limit(res);
-	if (rc)
-		dprintk(VIDC_WARN, "Failed to load dcvs limit: %d\n", rc);
-
 	rc = msm_vidc_load_imem_ab_table(res);
 	if (rc)
 		dprintk(VIDC_WARN, "Failed to load freq table: %d\n", rc);