msm: vidc: Enhance bus scaling algorithm

Enhance current bus scaling algorithm to make use of run time
UBWC stats of compression ratios(CR) and complexity factor(CF).

CRs-Fixed: 2012520
Change-Id: I3d2f61ab7e49b8fa9f953e3fb381261fde34c42a
Signed-off-by: Praneeth Paladugu <ppaladug@codeaurora.org>
diff --git a/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c b/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
index f7ce757..d329a8b 100644
--- a/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
+++ b/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
@@ -16,6 +16,7 @@
 #include "msm_vidc_internal.h"
 #include "msm_vidc_debug.h"
 #include "vidc_hfi_api.h"
+#define COMPRESSION_RATIO_MAX 5
 
 static bool debug;
 module_param(debug, bool, 0644);
@@ -30,13 +31,6 @@
 	struct devfreq_governor devfreq_gov;
 };
 
-enum scenario {
-	SCENARIO_WORST,
-	SCENARIO_SUSTAINED_WORST,
-	SCENARIO_AVERAGE,
-	SCENARIO_MAX,
-};
-
 /*
  * Minimum dimensions that the governor is willing to calculate
  * bandwidth for.  This means that anything bandwidth(0, 0) ==
@@ -62,15 +56,9 @@
 #define kbps(__mbps) ((__mbps) * 1000)
 #define bps(__mbps) (kbps(__mbps) * 1000)
 
-#define GENERATE_SCENARIO_PROFILE(__average, __worst) {                        \
-	[SCENARIO_AVERAGE] = (__average),                                      \
-	[SCENARIO_WORST] =  (__worst),                                         \
-	[SCENARIO_SUSTAINED_WORST] = (__worst),                                \
-}
-
-#define GENERATE_COMPRESSION_PROFILE(__bpp, __average, __worst) {              \
+#define GENERATE_COMPRESSION_PROFILE(__bpp, __worst) {              \
 	.bpp = __bpp,                                                          \
-	.ratio = GENERATE_SCENARIO_PROFILE(__average, __worst),                \
+	.ratio = __worst,                \
 }
 
 /*
@@ -85,109 +73,168 @@
  *  4096   2160|     44   88|     2.2       1.26      1.97        1.22|
  *  4096   2304|     48   96|     2.2       1.26      1.97        1.22|
  */
-#define COMPRESSION_RATIO_MAX 2
 static struct lut {
 	int frame_size; /* width x height */
-	unsigned long bitrate[SCENARIO_MAX];
+	int frame_rate;
+	unsigned long bitrate;
 	struct {
 		int bpp;
-		fp_t ratio[SCENARIO_MAX];
+		fp_t ratio;
 	} compression_ratio[COMPRESSION_RATIO_MAX];
 } const LUT[] = {
 	{
 		.frame_size = 1280 * 720,
-		.bitrate = GENERATE_SCENARIO_PROFILE(7, 14),
+		.frame_rate = 30,
+		.bitrate = 14,
 		.compression_ratio = {
 			GENERATE_COMPRESSION_PROFILE(8,
-					FP(1, 69, 100),
 					FP(1, 28, 100)),
 			GENERATE_COMPRESSION_PROFILE(10,
-					FP(1, 49, 100),
+					FP(1, 23, 100)),
+		}
+	},
+	{
+		.frame_size = 1280 * 720,
+		.frame_rate = 60,
+		.bitrate = 22,
+		.compression_ratio = {
+			GENERATE_COMPRESSION_PROFILE(8,
+					FP(1, 28, 100)),
+			GENERATE_COMPRESSION_PROFILE(10,
 					FP(1, 23, 100)),
 		}
 	},
 	{
 		.frame_size = 1920 * 1088,
-		.bitrate = GENERATE_SCENARIO_PROFILE(20, 40),
+		.frame_rate = 30,
+		.bitrate = 40,
 		.compression_ratio = {
 			GENERATE_COMPRESSION_PROFILE(8,
-					FP(1, 69, 100),
 					FP(1, 28, 100)),
 			GENERATE_COMPRESSION_PROFILE(10,
-					FP(1, 49, 100),
+					FP(1, 23, 100)),
+		}
+	},
+	{
+		.frame_size = 1920 * 1088,
+		.frame_rate = 60,
+		.bitrate = 64,
+		.compression_ratio = {
+			GENERATE_COMPRESSION_PROFILE(8,
+					FP(1, 28, 100)),
+			GENERATE_COMPRESSION_PROFILE(10,
 					FP(1, 23, 100)),
 		}
 	},
 	{
 		.frame_size = 2560 * 1440,
-		.bitrate = GENERATE_SCENARIO_PROFILE(32, 64),
+		.frame_rate = 30,
+		.bitrate = 64,
 		.compression_ratio = {
 			GENERATE_COMPRESSION_PROFILE(8,
-					FP(2, 20, 100),
 					FP(1, 26, 100)),
 			GENERATE_COMPRESSION_PROFILE(10,
-					FP(1, 97, 100),
+					FP(1, 22, 100)),
+		}
+	},
+	{
+		.frame_size = 2560 * 1440,
+		.frame_rate = 60,
+		.bitrate = 102,
+		.compression_ratio = {
+			GENERATE_COMPRESSION_PROFILE(8,
+					FP(1, 26, 100)),
+			GENERATE_COMPRESSION_PROFILE(10,
 					FP(1, 22, 100)),
 		}
 	},
 	{
 		.frame_size = 3840 * 2160,
-		.bitrate = GENERATE_SCENARIO_PROFILE(42, 84),
+		.frame_rate = 30,
+		.bitrate = 84,
 		.compression_ratio = {
 			GENERATE_COMPRESSION_PROFILE(8,
-					FP(2, 20, 100),
 					FP(1, 26, 100)),
 			GENERATE_COMPRESSION_PROFILE(10,
-					FP(1, 97, 100),
+					FP(1, 22, 100)),
+		}
+	},
+	{
+		.frame_size = 3840 * 2160,
+		.frame_rate = 60,
+		.bitrate = 134,
+		.compression_ratio = {
+			GENERATE_COMPRESSION_PROFILE(8,
+					FP(1, 26, 100)),
+			GENERATE_COMPRESSION_PROFILE(10,
 					FP(1, 22, 100)),
 		}
 	},
 	{
 		.frame_size = 4096 * 2160,
-		.bitrate = GENERATE_SCENARIO_PROFILE(44, 88),
+		.frame_rate = 30,
+		.bitrate = 88,
 		.compression_ratio = {
 			GENERATE_COMPRESSION_PROFILE(8,
-					FP(2, 20, 100),
 					FP(1, 26, 100)),
 			GENERATE_COMPRESSION_PROFILE(10,
-					FP(1, 97, 100),
+					FP(1, 22, 100)),
+		}
+	},
+	{
+		.frame_size = 4096 * 2160,
+		.frame_rate = 60,
+		.bitrate = 141,
+		.compression_ratio = {
+			GENERATE_COMPRESSION_PROFILE(8,
+					FP(1, 26, 100)),
+			GENERATE_COMPRESSION_PROFILE(10,
 					FP(1, 22, 100)),
 		}
 	},
 	{
 		.frame_size = 4096 * 2304,
-		.bitrate = GENERATE_SCENARIO_PROFILE(48, 96),
+		.frame_rate = 30,
+		.bitrate = 96,
 		.compression_ratio = {
 			GENERATE_COMPRESSION_PROFILE(8,
-					FP(2, 20, 100),
 					FP(1, 26, 100)),
 			GENERATE_COMPRESSION_PROFILE(10,
-					FP(1, 97, 100),
+					FP(1, 22, 100)),
+		}
+	},
+	{
+		.frame_size = 4096 * 2304,
+		.frame_rate = 60,
+		.bitrate = 154,
+		.compression_ratio = {
+			GENERATE_COMPRESSION_PROFILE(8,
+					FP(1, 26, 100)),
+			GENERATE_COMPRESSION_PROFILE(10,
 					FP(1, 22, 100)),
 		}
 	},
 };
 
-static struct lut const *__lut(int width, int height)
+static struct lut const *__lut(int width, int height, int fps)
 {
 	int frame_size = height * width, c = 0;
 
 	do {
-		if (LUT[c].frame_size >= frame_size)
+		if (LUT[c].frame_size >= frame_size && LUT[c].frame_rate >= fps)
 			return &LUT[c];
 	} while (++c < ARRAY_SIZE(LUT));
 
 	return &LUT[ARRAY_SIZE(LUT) - 1];
 }
 
-static fp_t __compression_ratio(struct lut const *entry, int bpp,
-		enum scenario s)
+static fp_t __compression_ratio(struct lut const *entry, int bpp)
 {
 	int c = 0;
 
 	for (c = 0; c < COMPRESSION_RATIO_MAX; ++c) {
 		if (entry->compression_ratio[c].bpp == bpp)
-			return entry->compression_ratio[c].ratio[s];
+			return entry->compression_ratio[c].ratio;
 	}
 
 	WARN(true, "Shouldn't be here, LUT possibly corrupted?\n");
@@ -282,23 +329,20 @@
 	 * measured heuristics and hardcoded numbers taken from the firmware.
 	 */
 	/* Decoder parameters */
-	enum scenario scenario;
-	int width, height, lcu_size, dpb_bpp, opb_bpp, fps;
+	int width, height, lcu_size, dpb_bpp, opb_bpp, fps, opb_factor;
 	bool unified_dpb_opb, dpb_compression_enabled, opb_compression_enabled;
-	fp_t dpb_opb_scaling_ratio, dpb_compression_factor,
-		opb_compression_factor, qsmmu_bw_overhead_factor;
-	int vmem_size; /* in kB */
+	fp_t dpb_opb_scaling_ratio, dpb_read_compression_factor,
+		dpb_write_compression_factor, opb_compression_factor,
+		qsmmu_bw_overhead_factor, height_ratio;
 
 	/* Derived parameters */
-	int lcu_per_frame, tnbr_per_lcu_10bpc, tnbr_per_lcu_8bpc, tnbr_per_lcu,
-		colocated_bytes_per_lcu, vmem_line_buffer, vmem_chroma_cache,
-		vmem_luma_cache, vmem_chroma_luma_cache;
+	int lcu_per_frame, tnbr_per_lcu, colocated_bytes_per_lcu;
 	unsigned long bitrate;
+
 	fp_t bins_to_bit_factor, dpb_write_factor, ten_bpc_packing_factor,
 		ten_bpc_bpp_factor, vsp_read_factor, vsp_write_factor,
-		ocmem_usage_lcu_factor, ref_ocmem_bw_factor_read,
-		ref_ocmem_bw_factor_write, bw_for_1x_8bpc, dpb_bw_for_1x,
-		motion_vector_complexity, row_cache_penalty, opb_bw;
+		bw_for_1x_8bpc, dpb_bw_for_1x,
+		motion_vector_complexity = 0, row_cache_penalty = 0, opb_bw = 0;
 
 	/* Output parameters */
 	struct {
@@ -306,17 +350,15 @@
 			line_buffer_read, line_buffer_write, recon_read,
 			recon_write, opb_read, opb_write, dpb_read, dpb_write,
 			total;
-	} ddr, vmem;
+	} ddr = {0};
 
 	unsigned long ret = 0;
+	unsigned int integer_part, frac_part;
 
-	/* Decoder parameters setup */
-	scenario = SCENARIO_WORST;
+	width = max(d->input_width, BASELINE_DIMENSIONS.width);
+	height = max(d->input_height, BASELINE_DIMENSIONS.height);
 
-	width = max(d->width, BASELINE_DIMENSIONS.width);
-	height = max(d->height, BASELINE_DIMENSIONS.height);
-
-	lcu_size = 32;
+	lcu_size = d->lcu_size;
 
 	dpb_bpp = d->num_formats >= 1 ? __bpp(d->color_formats[0]) : INT_MAX;
 	opb_bpp = d->num_formats >= 2 ?  __bpp(d->color_formats[1]) : dpb_bpp;
@@ -325,134 +367,61 @@
 
 	unified_dpb_opb = d->num_formats == 1;
 
-	dpb_opb_scaling_ratio = FP_ONE;
+	dpb_opb_scaling_ratio = fp_div(FP_INT(d->input_width * d->input_height),
+		FP_INT(d->output_width * d->output_height));
+	height_ratio = fp_div(d->input_height, d->output_height);
 
 	dpb_compression_enabled = d->num_formats >= 1 &&
 		__ubwc(d->color_formats[0]);
 	opb_compression_enabled = d->num_formats >= 2 &&
 		__ubwc(d->color_formats[1]);
 
-	dpb_compression_factor = !dpb_compression_enabled ? FP_ONE :
-		__compression_ratio(__lut(width, height), dpb_bpp, scenario);
+	/*
+	 * Convert Q16 number into Integer and Fractional part upto 2 places.
+	 * Ex : 105752 / 65536 = 1.61; 1.61 in Q16 = 105752;
+	 * Integer part =  105752 / 65536 = 1;
+	 * Reminder = 105752 - 1 * 65536 = 40216;
+	 * Fractional part = 40216 * 100 / 65536 = 61;
+	 * Now converto to FP(1, 61, 100) for below code.
+	 */
+
+	integer_part = d->compression_ratio >> 16;
+	frac_part =
+		((d->compression_ratio - (integer_part * 65536)) * 100) >> 16;
+
+	dpb_read_compression_factor = FP(integer_part, frac_part, 100);
+
+	dpb_write_compression_factor = !dpb_compression_enabled ? FP_ONE :
+		__compression_ratio(__lut(width, height, fps), opb_bpp);
 
 	opb_compression_factor = !opb_compression_enabled ? FP_ONE :
-		__compression_ratio(__lut(width, height), opb_bpp, scenario);
+		__compression_ratio(__lut(width, height, fps), opb_bpp);
 
-	vmem_size = 512; /* in kB */
 
 	/* Derived parameters setup */
 	lcu_per_frame = DIV_ROUND_UP(width, lcu_size) *
 		DIV_ROUND_UP(height, lcu_size);
 
-	bitrate = __lut(width, height)->bitrate[scenario];
+	bitrate = __lut(width, height, fps)->bitrate;
 
-	bins_to_bit_factor = FP(1, 60, 100);
+	bins_to_bit_factor = d->work_mode == VIDC_WORK_MODE_1 ?
+		FP_INT(0) : FP_INT(4);
 
-	dpb_write_factor = scenario == SCENARIO_AVERAGE ?
-		FP_ONE : FP(1, 5, 100);
+	vsp_read_factor = bins_to_bit_factor + FP_INT(2);
+
+	dpb_write_factor = FP(1, 5, 100);
 
 	ten_bpc_packing_factor = FP(1, 67, 1000);
 	ten_bpc_bpp_factor = FP(1, 1, 4);
 
-	vsp_read_factor = bins_to_bit_factor + FP_INT(2);
 	vsp_write_factor = bins_to_bit_factor;
 
-	tnbr_per_lcu_10bpc = lcu_size == 16 ? 384 + 192 :
-				lcu_size == 32 ? 640 + 256 :
-						1280 + 384;
-	tnbr_per_lcu_8bpc = lcu_size == 16 ? 256 + 192 :
-				lcu_size == 32 ? 512 + 256 :
-						1024 + 384;
-	tnbr_per_lcu = dpb_bpp == 10 ? tnbr_per_lcu_10bpc : tnbr_per_lcu_8bpc;
+	tnbr_per_lcu = lcu_size == 16 ? 128 :
+		lcu_size == 32 ? 64 : 128;
 
 	colocated_bytes_per_lcu = lcu_size == 16 ? 16 :
 				lcu_size == 32 ? 64 : 256;
 
-	ocmem_usage_lcu_factor = lcu_size == 16 ? FP(1, 8, 10) :
-				lcu_size == 32 ? FP(1, 2, 10) :
-						FP_ONE;
-	ref_ocmem_bw_factor_read = vmem_size < 296 ? FP_ZERO :
-				vmem_size < 648 ? FP(0, 1, 4) :
-						FP(0, 55, 100);
-	ref_ocmem_bw_factor_write = vmem_size < 296 ? FP_ZERO :
-				vmem_size < 648 ? FP(0, 7, 10) :
-						FP(1, 4, 10);
-
-	/* Prelim b/w calculation */
-	bw_for_1x_8bpc = fp_mult(FP_INT(width * height * fps),
-			fp_mult(FP(1, 50, 100), dpb_write_factor));
-	bw_for_1x_8bpc = fp_div(bw_for_1x_8bpc, FP_INT(bps(1)));
-
-	dpb_bw_for_1x = dpb_bpp == 8 ? bw_for_1x_8bpc :
-		fp_mult(bw_for_1x_8bpc, fp_mult(ten_bpc_packing_factor,
-					ten_bpc_bpp_factor));
-	/* VMEM adjustments */
-	vmem_line_buffer = tnbr_per_lcu * DIV_ROUND_UP(width, lcu_size) / 1024;
-	vmem_chroma_cache = dpb_bpp == 10 ? 176 : 128;
-	vmem_luma_cache = dpb_bpp == 10 ? 353 : 256;
-	vmem_chroma_luma_cache = vmem_chroma_cache + vmem_luma_cache;
-
-	motion_vector_complexity = scenario == SCENARIO_AVERAGE ?
-		FP(2, 66, 100) : FP_INT(4);
-
-	row_cache_penalty = FP_ZERO;
-	if (vmem_size < vmem_line_buffer + vmem_chroma_cache)
-		row_cache_penalty = fp_mult(FP(0, 5, 100),
-				motion_vector_complexity);
-	else if (vmem_size < vmem_line_buffer + vmem_luma_cache)
-		row_cache_penalty = fp_mult(FP(0, 7, 100),
-				motion_vector_complexity);
-	else if (vmem_size < vmem_line_buffer + vmem_chroma_cache
-			+ vmem_luma_cache)
-		row_cache_penalty = fp_mult(FP(0, 3, 100),
-				motion_vector_complexity);
-	else
-		row_cache_penalty = FP_ZERO;
-
-
-	opb_bw = unified_dpb_opb ? FP_ZERO :
-		fp_div(fp_div(bw_for_1x_8bpc, dpb_opb_scaling_ratio),
-				opb_compression_factor);
-
-	/* B/W breakdown on a per buffer type basis for VMEM */
-	vmem.vsp_read = FP_ZERO;
-	vmem.vsp_write = FP_ZERO;
-
-	vmem.collocated_read = FP_ZERO;
-	vmem.collocated_write = FP_ZERO;
-
-	vmem.line_buffer_read = FP_INT(tnbr_per_lcu *
-			lcu_per_frame * fps / bps(1));
-	vmem.line_buffer_write = vmem.line_buffer_read;
-
-	vmem.recon_read = FP_ZERO;
-	vmem.recon_write = FP_ZERO;
-
-	vmem.opb_read = FP_ZERO;
-	vmem.opb_write = FP_ZERO;
-
-	vmem.dpb_read = fp_mult(ocmem_usage_lcu_factor, fp_mult(
-					ref_ocmem_bw_factor_read,
-					dpb_bw_for_1x));
-	vmem.dpb_write = fp_mult(ocmem_usage_lcu_factor, fp_mult(
-					ref_ocmem_bw_factor_write,
-					dpb_bw_for_1x));
-
-	vmem.total = vmem.vsp_read + vmem.vsp_write +
-		vmem.collocated_read + vmem.collocated_write +
-		vmem.line_buffer_read + vmem.line_buffer_write +
-		vmem.recon_read + vmem.recon_write +
-		vmem.opb_read + vmem.opb_write +
-		vmem.dpb_read + vmem.dpb_write;
-
-	/*
-	 * Attempt to force VMEM to a certain frequency for 4K
-	 */
-	if (width * height * fps >= 3840 * 2160 * 60)
-		vmem.total = FP_INT(NOMINAL_BW_MBPS);
-	else if (width * height * fps >= 3840 * 2160 * 30)
-		vmem.total = FP_INT(SVS_BW_MBPS);
-
 	/* ........................................ for DDR */
 	ddr.vsp_read = fp_div(fp_mult(FP_INT(bitrate),
 				vsp_read_factor), FP_INT(8));
@@ -464,35 +433,51 @@
 	ddr.collocated_write = FP_INT(lcu_per_frame *
 			colocated_bytes_per_lcu * fps / bps(1));
 
-	ddr.line_buffer_read = vmem_size ? FP_ZERO : vmem.line_buffer_read;
-	ddr.line_buffer_write = vmem_size ? FP_ZERO : vmem.line_buffer_write;
+	ddr.line_buffer_read = FP_INT(tnbr_per_lcu *
+			lcu_per_frame * fps / bps(1));
+	ddr.line_buffer_write = ddr.line_buffer_read;
 
-	ddr.recon_read = FP_ZERO;
-	ddr.recon_write = fp_div(dpb_bw_for_1x, dpb_compression_factor);
+	motion_vector_complexity = FP_INT(4);
 
-	ddr.opb_read = FP_ZERO;
-	ddr.opb_write = opb_bw;
+	bw_for_1x_8bpc = fp_div(FP_INT(width * height), FP_INT(32 * 8));
 
-	ddr.dpb_read = fp_div(fp_mult(dpb_bw_for_1x,
-				motion_vector_complexity + row_cache_penalty),
-			dpb_compression_factor);
-	ddr.dpb_write = FP_ZERO;
+	bw_for_1x_8bpc = fp_mult(bw_for_1x_8bpc,
+		fp_div(FP_INT(256 * 30), FP_INT(1000 * 1000)));
+
+	dpb_bw_for_1x = dpb_bpp == 8 ? bw_for_1x_8bpc :
+		fp_mult(bw_for_1x_8bpc, fp_mult(ten_bpc_packing_factor,
+				ten_bpc_bpp_factor));
+
+	ddr.dpb_read = fp_div(fp_mult(fp_mult(dpb_bw_for_1x,
+			motion_vector_complexity), dpb_write_factor),
+			dpb_read_compression_factor);
+
+	ddr.dpb_write = fp_div(fp_mult(dpb_bw_for_1x, dpb_write_factor),
+		dpb_write_compression_factor);
+
+	opb_factor = dpb_bpp == 8 ? 8 : 4;
+
+	ddr.opb_read = unified_dpb_opb ? 0 : opb_compression_enabled ?
+		fp_div(fp_mult(fp_div(dpb_bw_for_1x, dpb_opb_scaling_ratio),
+		FP_INT(opb_factor)), height_ratio) : 0;
+	ddr.opb_write = unified_dpb_opb ? 0 : opb_compression_enabled ?
+		ddr.dpb_read : fp_div(fp_div(fp_mult(dpb_bw_for_1x,
+		FP(1, 50, 100)), dpb_opb_scaling_ratio),
+			opb_compression_factor);
 
 	ddr.total = ddr.vsp_read + ddr.vsp_write +
 		ddr.collocated_read + ddr.collocated_write +
-		ddr.line_buffer_read + ddr.line_buffer_write +
-		ddr.recon_read + ddr.recon_write +
 		ddr.opb_read + ddr.opb_write +
 		ddr.dpb_read + ddr.dpb_write;
 
 	qsmmu_bw_overhead_factor = FP(1, 3, 100);
+
 	ddr.total = fp_mult(ddr.total, qsmmu_bw_overhead_factor);
 
 	/* Dump all the variables for easier debugging */
 	if (debug) {
 		struct dump dump[] = {
 		{"DECODER PARAMETERS", "", DUMP_HEADER_MAGIC},
-		{"content", "%d", scenario},
 		{"LCU size", "%d", lcu_size},
 		{"DPB bitdepth", "%d", dpb_bpp},
 		{"frame rate", "%d", fps},
@@ -501,11 +486,12 @@
 			dpb_opb_scaling_ratio},
 		{"DPB compression", "%d", dpb_compression_enabled},
 		{"OPB compression", "%d", opb_compression_enabled},
-		{"DPB compression factor", DUMP_FP_FMT,
-			dpb_compression_factor},
+		{"DPB Read compression factor", DUMP_FP_FMT,
+			dpb_read_compression_factor},
+		{"DPB Write compression factor", DUMP_FP_FMT,
+			dpb_write_compression_factor},
 		{"OPB compression factor", DUMP_FP_FMT,
 			opb_compression_factor},
-		{"VMEM size", "%dkB", vmem_size},
 		{"frame width", "%d", width},
 		{"frame height", "%d", height},
 
@@ -519,25 +505,11 @@
 		{"10bpc,BPP factor", DUMP_FP_FMT, ten_bpc_bpp_factor},
 		{"VSP read factor", DUMP_FP_FMT, vsp_read_factor},
 		{"VSP write factor", DUMP_FP_FMT, vsp_write_factor},
-		{"TNBR/LCU_10bpc", "%d", tnbr_per_lcu_10bpc},
-		{"TNBR/LCU_8bpc", "%d", tnbr_per_lcu_8bpc},
 		{"TNBR/LCU", "%d", tnbr_per_lcu},
 		{"colocated bytes/LCU", "%d", colocated_bytes_per_lcu},
-		{"OCMEM usage LCU factor", DUMP_FP_FMT,
-			ocmem_usage_lcu_factor},
-		{"ref OCMEM b/w factor (read)", DUMP_FP_FMT,
-			ref_ocmem_bw_factor_read},
-		{"ref OCMEM b/w factor (write)", DUMP_FP_FMT,
-			ref_ocmem_bw_factor_write},
 		{"B/W for 1x (NV12 8bpc)", DUMP_FP_FMT, bw_for_1x_8bpc},
 		{"DPB B/W For 1x (NV12)", DUMP_FP_FMT, dpb_bw_for_1x},
 
-		{"VMEM", "", DUMP_HEADER_MAGIC},
-		{"line buffer", "%d", vmem_line_buffer},
-		{"chroma cache", "%d", vmem_chroma_cache},
-		{"luma cache", "%d", vmem_luma_cache},
-		{"luma & chroma cache", "%d", vmem_chroma_luma_cache},
-
 		{"DERIVED PARAMETERS (2)", "", DUMP_HEADER_MAGIC},
 		{"MV complexity", DUMP_FP_FMT, motion_vector_complexity},
 		{"row cache penalty", DUMP_FP_FMT, row_cache_penalty},
@@ -557,19 +529,6 @@
 		{"DPB read", DUMP_FP_FMT, ddr.dpb_read},
 		{"DPB write", DUMP_FP_FMT, ddr.dpb_write},
 
-		{"INTERMEDIATE VMEM B/W", "", DUMP_HEADER_MAGIC},
-		{"VSP read", "%d", vmem.vsp_read},
-		{"VSP write", DUMP_FP_FMT, vmem.vsp_write},
-		{"collocated read", DUMP_FP_FMT, vmem.collocated_read},
-		{"collocated write", DUMP_FP_FMT, vmem.collocated_write},
-		{"line buffer read", DUMP_FP_FMT, vmem.line_buffer_read},
-		{"line buffer write", DUMP_FP_FMT, vmem.line_buffer_write},
-		{"recon read", DUMP_FP_FMT, vmem.recon_read},
-		{"recon write", DUMP_FP_FMT, vmem.recon_write},
-		{"OPB read", DUMP_FP_FMT, vmem.opb_read},
-		{"OPB write", DUMP_FP_FMT, vmem.opb_write},
-		{"DPB read", DUMP_FP_FMT, vmem.dpb_read},
-		{"DPB write", DUMP_FP_FMT, vmem.dpb_write},
 		};
 		__dump(dump, ARRAY_SIZE(dump));
 	}
@@ -579,7 +538,7 @@
 		ret = kbps(fp_round(ddr.total));
 		break;
 	case GOVERNOR_LLCC:
-		ret = kbps(fp_round(vmem.total));
+		dprintk(VIDC_PROF, "LLCC Voting not supported yet\n");
 		break;
 	default:
 		dprintk(VIDC_ERR, "%s - Unknown governor\n", __func__);
@@ -597,9 +556,9 @@
 	 * measured heuristics and hardcoded numbers taken from the firmware.
 	 */
 	/* Encoder Parameters */
-	enum scenario scenario, bitrate_scenario;
+
 	enum hal_video_codec standard;
-	int width, height, fps, vmem_size;
+	int width, height, fps;
 	enum hal_uncompressed_format dpb_color_format;
 	enum hal_uncompressed_format original_color_format;
 	bool dpb_compression_enabled, original_compression_enabled,
@@ -618,35 +577,34 @@
 	fp_t bins_to_bit_factor, chroma_luma_factor_dpb, one_frame_bw_dpb,
 		 chroma_luma_factor_original, one_frame_bw_original,
 		 line_buffer_size_per_lcu, line_buffer_size, line_buffer_bw,
-		 original_vmem_requirement, bw_increase_p, bw_increase_b;
+		 bw_increase_p, bw_increase_b;
 	int collocated_mv_per_lcu, max_transaction_size,
 		search_window_size_vertical_p, search_window_factor_p,
-		search_window_factor_bw_p, vmem_size_p, available_vmem_p,
+		search_window_factor_bw_p,
 		search_window_size_vertical_b, search_window_factor_b,
-		search_window_factor_bw_b, vmem_size_b, available_vmem_b;
+		search_window_factor_bw_b;
 
 	/* Output paramaters */
 	struct {
 		fp_t vsp_read, vsp_write, collocated_read, collocated_write,
 			line_buffer_read, line_buffer_write, original_read,
 			original_write, dpb_read, dpb_write, total;
-	} ddr, vmem;
+	} ddr = {0};
 
 	unsigned long ret = 0;
+	fp_t integer_part, frac_part;
 
 	/* Encoder Parameters setup */
-	scenario = SCENARIO_WORST;
 
 	standard = d->codec;
-	width = max(d->width, BASELINE_DIMENSIONS.width);
-	height = max(d->height, BASELINE_DIMENSIONS.height);
+	width = max(d->input_width, BASELINE_DIMENSIONS.width);
+	height = max(d->input_height, BASELINE_DIMENSIONS.height);
 
 	dpb_color_format = HAL_COLOR_FORMAT_NV12_UBWC;
 	original_color_format = d->num_formats >= 1 ?
 		d->color_formats[0] : HAL_UNUSED_COLOR;
 
 	fps = d->fps;
-	bitrate_scenario = SCENARIO_WORST;
 
 	dpb_compression_enabled = __ubwc(dpb_color_format);
 	original_compression_enabled = __ubwc(original_color_format);
@@ -655,21 +613,30 @@
 	low_power = d->power_mode == VIDC_POWER_LOW;
 	b_frames_enabled = false;
 
-	dpb_compression_factor = !dpb_compression_enabled ? FP_ONE :
-		__compression_ratio(__lut(width, height),
-				__bpp(dpb_color_format), scenario);
-	original_compression_factor = !original_compression_enabled ? FP_ONE :
-		__compression_ratio(__lut(width, height),
-				__bpp(original_color_format), scenario);
+	/*
+	 * Convert Q16 number into Integer and Fractional part upto 2 places.
+	 * Ex : 105752 / 65536 = 1.61; 1.61 in Q16 = 105752;
+	 * Integer part =  105752 / 65536 = 1;
+	 * Reminder = 105752 - 1 * 65536 = 40216;
+	 * Fractional part = 40216 * 100 / 65536 = 61;
+	 * Now converto to FP(1, 61, 100) for below code.
+	 */
+
+	integer_part = d->compression_ratio >> 16;
+	frac_part =
+		((d->compression_ratio - (integer_part * 65536)) * 100) >> 16;
+
+	dpb_compression_factor = FP(integer_part, frac_part, 100);
+
+	original_compression_factor = dpb_compression_factor;
 
 	rotation = false;
 	cropping_or_scaling = false;
-	vmem_size = 512; /* in kB */
 
 	/* Derived Parameters */
 	lcu_size = 16;
 	gop = b_frames_enabled ? GOP_IBBP : GOP_IPPP;
-	bitrate = __lut(width, height)->bitrate[bitrate_scenario];
+	bitrate = __lut(width, height, fps)->bitrate;
 	bins_to_bit_factor = FP(1, 6, 10);
 
 	/*
@@ -713,16 +680,6 @@
 	collocated_mv_per_lcu = lcu_size == 16 ? 16 : 64;
 	max_transaction_size = 256;
 
-	original_vmem_requirement = FP_INT(3 *
-			(two_stage_encoding ? 2 : 1) * lcu_size);
-	original_vmem_requirement = fp_mult(original_vmem_requirement,
-			(FP_ONE + chroma_luma_factor_original));
-	original_vmem_requirement += FP_INT((cropping_or_scaling ? 3 : 0) * 2);
-	original_vmem_requirement = fp_mult(original_vmem_requirement,
-			FP_INT(max_transaction_size));
-	original_vmem_requirement = fp_div(original_vmem_requirement,
-			FP_INT(1024));
-
 	search_window_size_vertical_p = low_power ? 32 :
 					b_frames_enabled ? 80 :
 					width > 2048 ? 64 : 48;
@@ -730,24 +687,16 @@
 	search_window_factor_bw_p = !two_stage_encoding ?
 		search_window_size_vertical_p * 2 / lcu_size + 1 :
 		(search_window_size_vertical_p * 2 / lcu_size + 2) / 2;
-	vmem_size_p = (search_window_factor_p * width + 128 * 2) *
-		lcu_size / 2 / 1024; /* XXX: CF hack */
 	bw_increase_p = fp_mult(one_frame_bw_dpb,
 			FP_INT(search_window_factor_bw_p - 1) / 3);
-	available_vmem_p = min_t(int, 3, (vmem_size - fp_int(line_buffer_size) -
-			fp_int(original_vmem_requirement)) / vmem_size_p);
 
 	search_window_size_vertical_b = 48;
 	search_window_factor_b = search_window_size_vertical_b * 2 / lcu_size;
 	search_window_factor_bw_b = !two_stage_encoding ?
 		search_window_size_vertical_b * 2 / lcu_size + 1 :
 		(search_window_size_vertical_b * 2 / lcu_size + 2) / 2;
-	vmem_size_b = (search_window_factor_b * width + 128 * 2) * lcu_size /
-		2 / 1024;
 	bw_increase_b = fp_mult(one_frame_bw_dpb,
 			FP_INT((search_window_factor_bw_b - 1) / 3));
-	available_vmem_b = min_t(int, 6, (vmem_size - fp_int(line_buffer_size) -
-			fp_int(original_vmem_requirement)) / vmem_size_b);
 
 	/* Output parameters for DDR */
 	ddr.vsp_read = fp_mult(fp_div(FP_INT(bitrate), FP_INT(8)),
@@ -759,8 +708,6 @@
 			collocated_mv_per_lcu * fps), FP_INT(1000 * 1000));
 	ddr.collocated_write = ddr.collocated_read;
 
-	ddr.line_buffer_read = (FP_INT(vmem_size) >= line_buffer_size +
-		original_vmem_requirement) ? FP_ZERO : line_buffer_bw;
 	ddr.line_buffer_write = ddr.line_buffer_read;
 
 	ddr.original_read = fp_div(one_frame_bw_original,
@@ -768,27 +715,6 @@
 	ddr.original_write = FP_ZERO;
 
 	ddr.dpb_read = FP_ZERO;
-	if (gop == GOP_IPPP) {
-		ddr.dpb_read = one_frame_bw_dpb + fp_mult(bw_increase_p,
-			FP_INT(3 - available_vmem_p));
-	} else if (scenario == SCENARIO_WORST ||
-			scenario == SCENARIO_SUSTAINED_WORST) {
-		ddr.dpb_read = fp_mult(one_frame_bw_dpb, FP_INT(2));
-		ddr.dpb_read += fp_mult(FP_INT(6 - available_vmem_b),
-				bw_increase_b);
-	} else {
-		fp_t part_p, part_b;
-
-		part_p = one_frame_bw_dpb + fp_mult(bw_increase_p,
-				FP_INT(3 - available_vmem_p));
-		part_p = fp_div(part_p, FP_INT(3));
-
-		part_b = fp_mult(one_frame_bw_dpb, 2) +
-			fp_mult(FP_INT(6 - available_vmem_b), bw_increase_b);
-		part_b = fp_mult(part_b, FP(0, 2, 3));
-
-		ddr.dpb_read = part_p + part_b;
-	}
 
 	ddr.dpb_read = fp_div(ddr.dpb_read, dpb_compression_factor);
 	ddr.dpb_write = fp_div(one_frame_bw_dpb, dpb_compression_factor);
@@ -802,103 +728,15 @@
 	qsmmu_bw_overhead_factor = FP(1, 3, 100);
 	ddr.total = fp_mult(ddr.total, qsmmu_bw_overhead_factor);
 
-	/* ................. for VMEM */
-	vmem.vsp_read = FP_ZERO;
-	vmem.vsp_write = FP_ZERO;
-
-	vmem.collocated_read = FP_ZERO;
-	vmem.collocated_write = FP_ZERO;
-
-	vmem.line_buffer_read = line_buffer_bw - ddr.line_buffer_read;
-	vmem.line_buffer_write = vmem.line_buffer_read;
-
-	vmem.original_read = FP_INT(vmem_size) >= original_vmem_requirement ?
-		ddr.original_read : FP_ZERO;
-	vmem.original_write = vmem.original_read;
-
-	vmem.dpb_read = FP_ZERO;
-	if (gop == GOP_IPPP) {
-		fp_t temp = fp_mult(one_frame_bw_dpb,
-			FP_INT(search_window_factor_bw_p * available_vmem_p));
-		temp = fp_div(temp, FP_INT(3));
-
-		vmem.dpb_read = temp;
-	} else if (scenario != SCENARIO_AVERAGE) {
-		fp_t temp = fp_mult(one_frame_bw_dpb, FP_INT(2));
-
-		temp = fp_mult(temp, FP_INT(search_window_factor_bw_b *
-					available_vmem_b));
-		temp = fp_div(temp, FP_INT(6));
-
-		vmem.dpb_read = temp;
-	} else {
-		fp_t part_p, part_b;
-
-		part_p = fp_mult(one_frame_bw_dpb, FP_INT(
-					search_window_factor_bw_p *
-					available_vmem_p));
-		part_p = fp_div(part_p, FP_INT(3 * 3));
-
-		part_b = fp_mult(one_frame_bw_dpb, FP_INT(2 *
-					search_window_factor_bw_b *
-					available_vmem_b));
-		part_b = fp_div(part_b, FP_INT(6));
-		part_b = fp_mult(part_b, FP(0, 2, 3));
-
-		vmem.dpb_read = part_p + part_b;
-	}
-
-	vmem.dpb_write = FP_ZERO;
-	if (gop == GOP_IPPP) {
-		fp_t temp = fp_mult(one_frame_bw_dpb,
-				FP_INT(available_vmem_p));
-		temp = fp_div(temp, FP_INT(3));
-
-		vmem.dpb_write = temp;
-	} else if (scenario != SCENARIO_AVERAGE) {
-		fp_t temp = fp_mult(one_frame_bw_dpb,
-				FP_INT(2 * available_vmem_b));
-		temp = fp_div(temp, FP_INT(6));
-
-		vmem.dpb_write = temp;
-	} else {
-		fp_t part_b, part_p;
-
-		part_b = fp_mult(one_frame_bw_dpb, FP_INT(available_vmem_p));
-		part_b = fp_div(part_b, FP_INT(9));
-
-		part_p = fp_mult(one_frame_bw_dpb, FP_INT(
-					2 * available_vmem_b));
-		part_p = fp_div(part_p, FP_INT(6));
-		part_b = fp_mult(part_b, FP(0, 2, 3));
-
-		vmem.dpb_write = part_p + part_b;
-	}
-
-	vmem.total = vmem.vsp_read + vmem.vsp_write +
-		vmem.collocated_read + vmem.collocated_write +
-		vmem.line_buffer_read + vmem.line_buffer_write +
-		vmem.original_read + vmem.original_write +
-		vmem.dpb_read + vmem.dpb_write;
-
-	/*
-	 * When in low power mode, attempt to force the VMEM clocks a certain
-	 * frequency that DCVS would prefer
-	 */
-	if (width * height >= 3840 * 2160 && low_power)
-		vmem.total = FP_INT(NOMINAL_BW_MBPS);
-
 	if (debug) {
 		struct dump dump[] = {
 		{"ENCODER PARAMETERS", "", DUMP_HEADER_MAGIC},
-		{"scenario", "%d", scenario},
 		{"standard", "%#x", standard},
 		{"width", "%d", width},
 		{"height", "%d", height},
 		{"DPB format", "%#x", dpb_color_format},
 		{"original frame format", "%#x", original_color_format},
 		{"fps", "%d", fps},
-		{"target bitrate", "%d", bitrate_scenario},
 		{"DPB compression enable", "%d", dpb_compression_enabled},
 		{"original compression enable", "%d",
 			original_compression_enabled},
@@ -910,7 +748,6 @@
 			original_compression_factor},
 		{"rotation", "%d", rotation},
 		{"cropping or scaling", "%d", cropping_or_scaling},
-		{"VMEM size (KB)", "%d", vmem_size},
 
 		{"DERIVED PARAMETERS", "", DUMP_HEADER_MAGIC},
 		{"LCU size", "%d", lcu_size},
@@ -923,17 +760,13 @@
 		{"search window factor (B)", "%d", search_window_factor_b},
 		{"search window factor BW (B)", "%d",
 			search_window_factor_bw_b},
-		{"VMEM size (B)", "%d", vmem_size_b},
 		{"bw increase (MB/s) (B)", DUMP_FP_FMT, bw_increase_b},
-		{"available VMEM (B)", "%d", available_vmem_b},
 		{"search window size vertical (P)", "%d",
 			search_window_size_vertical_p},
 		{"search window factor (P)", "%d", search_window_factor_p},
 		{"search window factor BW (P)", "%d",
 			search_window_factor_bw_p},
-		{"VMEM size (P)", "%d", vmem_size_p},
 		{"bw increase (MB/s) (P)", DUMP_FP_FMT, bw_increase_p},
-		{"available VMEM (P)", "%d", available_vmem_p},
 		{"chroma/luma factor DPB", DUMP_FP_FMT,
 			chroma_luma_factor_dpb},
 		{"one frame BW DPB (MB/s)", DUMP_FP_FMT, one_frame_bw_dpb},
@@ -946,8 +779,6 @@
 		{"line buffer size (KB)", DUMP_FP_FMT, line_buffer_size},
 		{"line buffer BW (MB/s)", DUMP_FP_FMT, line_buffer_bw},
 		{"collocated MVs per LCU", "%d", collocated_mv_per_lcu},
-		{"original VMEM requirement (KB)", DUMP_FP_FMT,
-			original_vmem_requirement},
 
 		{"INTERMEDIATE B/W DDR", "", DUMP_HEADER_MAGIC},
 		{"VSP read", DUMP_FP_FMT, ddr.vsp_read},
@@ -960,18 +791,6 @@
 		{"original read", DUMP_FP_FMT, ddr.original_write},
 		{"DPB read", DUMP_FP_FMT, ddr.dpb_read},
 		{"DPB write", DUMP_FP_FMT, ddr.dpb_write},
-
-		{"INTERMEDIATE B/W VMEM", "", DUMP_HEADER_MAGIC},
-		{"VSP read", DUMP_FP_FMT, vmem.vsp_read},
-		{"VSP read", DUMP_FP_FMT, vmem.vsp_write},
-		{"collocated read", DUMP_FP_FMT, vmem.collocated_read},
-		{"collocated read", DUMP_FP_FMT, vmem.collocated_write},
-		{"line buffer read", DUMP_FP_FMT, vmem.line_buffer_read},
-		{"line buffer read", DUMP_FP_FMT, vmem.line_buffer_write},
-		{"original read", DUMP_FP_FMT, vmem.original_read},
-		{"original read", DUMP_FP_FMT, vmem.original_write},
-		{"DPB read", DUMP_FP_FMT, vmem.dpb_read},
-		{"DPB write", DUMP_FP_FMT, vmem.dpb_write},
 		};
 		__dump(dump, ARRAY_SIZE(dump));
 	}
@@ -981,7 +800,7 @@
 		ret = kbps(fp_round(ddr.total));
 		break;
 	case GOVERNOR_LLCC:
-		ret = kbps(fp_round(vmem.total));
+		dprintk(VIDC_PROF, "LLCC Voting not supported yet\n");
 		break;
 	default:
 		dprintk(VIDC_ERR, "%s - Unknown governor\n", __func__);
@@ -1023,18 +842,21 @@
 	dev->profile->get_dev_status(dev->dev.parent, &stats);
 	vidc_data = (struct msm_vidc_gov_data *)stats.private_data;
 
+	if (!vidc_data || !vidc_data->data_count)
+		goto exit;
+
 	for (c = 0; c < vidc_data->data_count; ++c) {
 		if (vidc_data->data->power_mode == VIDC_POWER_TURBO) {
-			*freq = INT_MAX;
 			goto exit;
 		}
 	}
 
+	ab_kbps = 0;
 	for (c = 0; c < vidc_data->data_count; ++c)
 		ab_kbps += __calculate(&vidc_data->data[c], gov->mode);
 
-	*freq = clamp(ab_kbps, dev->min_freq, dev->max_freq ?: UINT_MAX);
 exit:
+	*freq = clamp(ab_kbps, dev->min_freq, dev->max_freq ?: UINT_MAX);
 	return 0;
 }
 
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index f678f56..08cb055 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -1320,6 +1320,13 @@
 	data_done.status = hfi_map_err_status(pkt->error_type);
 	data_done.size = sizeof(struct msm_vidc_cb_data_done);
 	data_done.clnt_data = pkt->input_tag;
+	data_done.input_done.recon_stats.buffer_index =
+		pkt->ubwc_cr_stats.frame_index;
+	memcpy(&data_done.input_done.recon_stats.ubwc_stats_info,
+		&pkt->ubwc_cr_stats.ubwc_stats_info,
+		sizeof(data_done.input_done.recon_stats.ubwc_stats_info));
+	data_done.input_done.recon_stats.complexity_number =
+		pkt->ubwc_cr_stats.complexity_number;
 	data_done.input_done.offset = pkt->offset;
 	data_done.input_done.filled_len = pkt->filled_len;
 	data_done.input_done.packet_buffer =
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index 5c34f28..12a4e86 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -710,6 +710,7 @@
 	v4l2_device_unregister(&core->v4l2_dev);
 
 	msm_vidc_free_platform_resources(&core->resources);
+	kfree(core->vote_data);
 	sysfs_remove_group(&pdev->dev.kobj, &msm_vidc_core_attr_group);
 	dev_set_drvdata(&pdev->dev, NULL);
 	mutex_destroy(&core->lock);
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 053d748..f31c11b 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -513,6 +513,7 @@
 				msm_comm_get_hal_output_buffer(inst),
 				f->fmt.pix_mp.pixelformat);
 
+		inst->clk_data.opb_fourcc = f->fmt.pix_mp.pixelformat;
 		if (msm_comm_get_stream_output_mode(inst) ==
 			HAL_VIDEO_DECODER_SECONDARY) {
 			frame_sz.buffer_type = HAL_BUFFER_OUTPUT2;
@@ -1056,6 +1057,7 @@
 							"%s Failed to get buffer requirements : %d\n",
 							__func__, rc);
 				}
+				inst->clk_data.dpb_fourcc = fourcc;
 				break;
 			default:
 				dprintk(VIDC_ERR,
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 2e952a3..ede51b6 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -1482,6 +1482,13 @@
 		goto fail_start;
 	}
 
+	rc = msm_comm_set_recon_buffers(inst);
+	if (rc) {
+		dprintk(VIDC_ERR,
+				"Failed to set recon buffers: %d\n", rc);
+		goto fail_start;
+	}
+
 	if (msm_comm_get_stream_output_mode(inst) ==
 			HAL_VIDEO_DECODER_SECONDARY) {
 		rc = msm_comm_set_output_buffers(inst);
@@ -2085,6 +2092,7 @@
 	INIT_MSM_VIDC_LIST(&inst->pending_getpropq);
 	INIT_MSM_VIDC_LIST(&inst->outputbufs);
 	INIT_MSM_VIDC_LIST(&inst->registeredbufs);
+	INIT_MSM_VIDC_LIST(&inst->reconbufs);
 
 	kref_init(&inst->kref);
 
@@ -2219,6 +2227,11 @@
 				"Failed to release scratch buffers\n");
 		}
 
+		if (msm_comm_release_recon_buffers(inst)) {
+			dprintk(VIDC_ERR,
+				"Failed to release recon buffers\n");
+		}
+
 		if (msm_comm_release_persist_buffers(inst)) {
 			dprintk(VIDC_ERR,
 				"Failed to release persist buffers\n");
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
index 05af186..6935a76 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
@@ -16,6 +16,94 @@
 #include "msm_vidc_debug.h"
 #include "msm_vidc_clocks.h"
 
+static inline unsigned long int get_ubwc_compression_ratio(
+	struct ubwc_cr_stats_info_type ubwc_stats_info)
+{
+	unsigned long int sum = 0, weighted_sum = 0;
+	unsigned long int compression_ratio = 1 << 16;
+
+	weighted_sum =
+		32  * ubwc_stats_info.cr_stats_info0 +
+		64  * ubwc_stats_info.cr_stats_info1 +
+		96  * ubwc_stats_info.cr_stats_info2 +
+		128 * ubwc_stats_info.cr_stats_info3 +
+		160 * ubwc_stats_info.cr_stats_info4 +
+		192 * ubwc_stats_info.cr_stats_info5 +
+		256 * ubwc_stats_info.cr_stats_info6;
+
+	sum =
+		ubwc_stats_info.cr_stats_info0 +
+		ubwc_stats_info.cr_stats_info1 +
+		ubwc_stats_info.cr_stats_info2 +
+		ubwc_stats_info.cr_stats_info3 +
+		ubwc_stats_info.cr_stats_info4 +
+		ubwc_stats_info.cr_stats_info5 +
+		ubwc_stats_info.cr_stats_info6;
+
+	compression_ratio = (weighted_sum && sum) ?
+		((256 * sum) << 16) / weighted_sum : compression_ratio;
+
+	return compression_ratio;
+}
+
+static inline int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst *inst)
+{
+	int height, width;
+
+	if (!inst->in_reconfig) {
+		height = max(inst->prop.height[CAPTURE_PORT],
+			inst->prop.height[OUTPUT_PORT]);
+		width = max(inst->prop.width[CAPTURE_PORT],
+			inst->prop.width[OUTPUT_PORT]);
+	} else {
+		height = inst->reconfig_height;
+		width = inst->reconfig_width;
+	}
+
+	return NUM_MBS_PER_FRAME(height, width);
+}
+
+void update_recon_stats(struct msm_vidc_inst *inst,
+	struct recon_stats_type *recon_stats)
+{
+	struct recon_buf *binfo;
+	u32 CR = 0, CF = 0;
+	u32 frame_size;
+
+	CR = get_ubwc_compression_ratio(recon_stats->ubwc_stats_info);
+
+	frame_size = (msm_vidc_get_mbs_per_frame(inst) / (32 * 8) * 3) / 2;
+
+	CF = recon_stats->complexity_number / frame_size;
+
+	mutex_lock(&inst->reconbufs.lock);
+	list_for_each_entry(binfo, &inst->reconbufs.list, list) {
+		if (binfo->buffer_index ==
+				recon_stats->buffer_index) {
+			binfo->CR = CR;
+			binfo->CF = CF;
+		}
+	}
+	mutex_unlock(&inst->reconbufs.lock);
+}
+
+static int fill_recon_stats(struct msm_vidc_inst *inst,
+	struct vidc_bus_vote_data *vote_data)
+{
+	struct recon_buf *binfo;
+	u32 CR = 0, CF = 0;
+
+	mutex_lock(&inst->reconbufs.lock);
+	list_for_each_entry(binfo, &inst->reconbufs.list, list) {
+		CR = max(CR, binfo->CR);
+		CF = max(CF, binfo->CF);
+	}
+	mutex_unlock(&inst->reconbufs.lock);
+	vote_data->complexity_factor = CF;
+	vote_data->compression_ratio = CR;
+	return 0;
+}
+
 int msm_comm_vote_bus(struct msm_vidc_core *core)
 {
 	int rc = 0, vote_data_count = 0, i = 0;
@@ -30,35 +118,36 @@
 
 	hdev = core->device;
 
-	mutex_lock(&core->lock);
-	list_for_each_entry(inst, &core->instances, list)
-		++vote_data_count;
-
-	vote_data = kcalloc(vote_data_count, sizeof(*vote_data),
-			GFP_TEMPORARY);
+	vote_data = core->vote_data;
 	if (!vote_data) {
-		dprintk(VIDC_ERR, "%s: failed to allocate memory\n", __func__);
-		rc = -ENOMEM;
-		goto fail_alloc;
+		dprintk(VIDC_PROF,
+			"Failed to get vote_data for inst %pK\n",
+				inst);
+		return -EINVAL;
 	}
 
+	mutex_lock(&core->lock);
 	list_for_each_entry(inst, &core->instances, list) {
-		int codec = 0, yuv = 0;
+		int codec = 0;
+
+		++vote_data_count;
 
 		codec = inst->session_type == MSM_VIDC_DECODER ?
 			inst->fmts[OUTPUT_PORT].fourcc :
 			inst->fmts[CAPTURE_PORT].fourcc;
 
-		yuv = inst->session_type == MSM_VIDC_DECODER ?
-			inst->fmts[CAPTURE_PORT].fourcc :
-			inst->fmts[OUTPUT_PORT].fourcc;
-
 		vote_data[i].domain = get_hal_domain(inst->session_type);
 		vote_data[i].codec = get_hal_codec(codec);
-		vote_data[i].width =  max(inst->prop.width[CAPTURE_PORT],
+		vote_data[i].input_width =  max(inst->prop.width[OUTPUT_PORT],
 				inst->prop.width[OUTPUT_PORT]);
-		vote_data[i].height = max(inst->prop.height[CAPTURE_PORT],
+		vote_data[i].input_height = max(inst->prop.height[OUTPUT_PORT],
 				inst->prop.height[OUTPUT_PORT]);
+		vote_data[i].output_width =  max(inst->prop.width[CAPTURE_PORT],
+				inst->prop.width[OUTPUT_PORT]);
+		vote_data[i].output_height =
+				max(inst->prop.height[CAPTURE_PORT],
+				inst->prop.height[OUTPUT_PORT]);
+		vote_data[i].lcu_size = codec == V4L2_PIX_FMT_HEVC ? 32 : 16;
 
 		if (inst->clk_data.operating_rate)
 			vote_data[i].fps =
@@ -67,32 +156,35 @@
 		else
 			vote_data[i].fps = inst->prop.fps;
 
+		vote_data[i].power_mode = 0;
 		if (!msm_vidc_clock_scaling ||
 			inst->clk_data.buffer_counter < DCVS_FTB_WINDOW)
 			vote_data[i].power_mode = VIDC_POWER_TURBO;
 
-		/*
-		 * TODO: support for OBP-DBP split mode hasn't been yet
-		 * implemented, once it is, this part of code needs to be
-		 * revisited since passing in accurate information to the bus
-		 * governor will drastically reduce bandwidth
-		 */
-		//vote_data[i].color_formats[0] = get_hal_uncompressed(yuv);
-		vote_data[i].num_formats = 1;
+		if (msm_comm_get_stream_output_mode(inst) ==
+				HAL_VIDEO_DECODER_PRIMARY) {
+			vote_data[i].color_formats[0] =
+				msm_comm_get_hal_uncompressed(
+				inst->clk_data.opb_fourcc);
+			vote_data[i].num_formats = 1;
+		} else {
+			vote_data[i].color_formats[0] =
+				msm_comm_get_hal_uncompressed(
+				inst->clk_data.dpb_fourcc);
+			vote_data[i].color_formats[1] =
+				msm_comm_get_hal_uncompressed(
+				inst->clk_data.opb_fourcc);
+			vote_data[i].num_formats = 2;
+		}
+		vote_data[i].work_mode = inst->clk_data.work_mode;
+		fill_recon_stats(inst, &vote_data[i]);
 		i++;
 	}
 	mutex_unlock(&core->lock);
+	if (vote_data_count)
+		rc = call_hfi_op(hdev, vote_bus, hdev->hfi_device_data,
+			vote_data, vote_data_count);
 
-	rc = call_hfi_op(hdev, vote_bus, hdev->hfi_device_data, vote_data,
-			vote_data_count);
-	if (rc)
-		dprintk(VIDC_ERR, "Failed to scale bus: %d\n", rc);
-
-	kfree(vote_data);
-	return rc;
-
-fail_alloc:
-	mutex_unlock(&core->lock);
 	return rc;
 }
 
@@ -252,24 +344,6 @@
 	mutex_unlock(&inst->freqs.lock);
 }
 
-
-static inline int msm_dcvs_get_mbs_per_frame(struct msm_vidc_inst *inst)
-{
-	int height, width;
-
-	if (!inst->in_reconfig) {
-		height = max(inst->prop.height[CAPTURE_PORT],
-			inst->prop.height[OUTPUT_PORT]);
-		width = max(inst->prop.width[CAPTURE_PORT],
-			inst->prop.width[OUTPUT_PORT]);
-	} else {
-		height = inst->reconfig_height;
-		width = inst->reconfig_width;
-	}
-
-	return NUM_MBS_PER_FRAME(height, width);
-}
-
 static unsigned long msm_vidc_calc_freq(struct msm_vidc_inst *inst,
 	u32 filled_len)
 {
@@ -783,7 +857,7 @@
 				__func__);
 		return 0;
 	}
-	mbs_per_frame = msm_dcvs_get_mbs_per_frame(inst);
+	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) {
 		enable = true;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.h b/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
index fe4822b..db57647 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
@@ -43,5 +43,6 @@
 int msm_vidc_decide_core_and_power_mode(struct msm_vidc_inst *inst);
 void msm_vidc_clear_freq_entry(struct msm_vidc_inst *inst,
 	ion_phys_addr_t device_addr);
-
+void update_recon_stats(struct msm_vidc_inst *inst,
+	struct recon_stats_type *recon_stats);
 #endif
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index fe61e6f..45992a7 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -817,7 +817,7 @@
 	return codec;
 }
 
-static enum hal_uncompressed_format get_hal_uncompressed(int fourcc)
+enum hal_uncompressed_format msm_comm_get_hal_uncompressed(int fourcc)
 {
 	enum hal_uncompressed_format format = HAL_UNUSED_COLOR;
 
@@ -976,6 +976,11 @@
 		__func__, core->codec_count, core->enc_codec_supported,
 		core->dec_codec_supported);
 
+	core->vote_data = kcalloc(MAX_SUPPORTED_INSTANCES,
+		sizeof(core->vote_data), GFP_KERNEL);
+	if (!core->vote_data)
+		dprintk(VIDC_ERR, "%s: failed to allocate memory\n", __func__);
+
 	complete(&(core->completions[index]));
 }
 
@@ -2231,6 +2236,9 @@
 					V4L2_QCOM_BUF_FLAG_IDRFRAME |
 					V4L2_BUF_FLAG_KEYFRAME;
 		}
+
+		update_recon_stats(inst, &empty_buf_done->recon_stats);
+
 		dprintk(VIDC_DBG,
 			"Got ebd from hal: device_addr: %pa, alloc: %d, status: %#x, pic_type: %#x, flags: %#x\n",
 			&empty_buf_done->packet_buffer,
@@ -4504,6 +4512,27 @@
 	return rc;
 }
 
+int msm_comm_release_recon_buffers(struct msm_vidc_inst *inst)
+{
+	struct recon_buf *buf, *next;
+
+	if (!inst) {
+		dprintk(VIDC_ERR,
+			"Invalid instance pointer = %pK\n", inst);
+		return -EINVAL;
+	}
+
+	mutex_lock(&inst->reconbufs.lock);
+	list_for_each_entry_safe(buf, next, &inst->reconbufs.list, list) {
+		list_del(&buf->list);
+		kfree(buf);
+	}
+	INIT_LIST_HEAD(&inst->reconbufs.list);
+	mutex_unlock(&inst->reconbufs.lock);
+
+	return 0;
+}
+
 int msm_comm_release_persist_buffers(struct msm_vidc_inst *inst)
 {
 	struct msm_smem *handle;
@@ -4657,6 +4686,54 @@
 	return rc;
 }
 
+int msm_comm_set_recon_buffers(struct msm_vidc_inst *inst)
+{
+	int rc = 0, i = 0;
+	struct hal_buffer_requirements *internal_buf;
+	struct recon_buf *binfo;
+	struct msm_vidc_list *buf_list = &inst->reconbufs;
+
+	if (!inst) {
+		dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
+		return -EINVAL;
+	}
+
+	if (inst->session_type == MSM_VIDC_ENCODER)
+		internal_buf = get_buff_req_buffer(inst,
+			HAL_BUFFER_INTERNAL_RECON);
+	else if (inst->session_type == MSM_VIDC_DECODER)
+		internal_buf = get_buff_req_buffer(inst,
+			msm_comm_get_hal_output_buffer(inst));
+	else
+		return -EINVAL;
+
+	if (!internal_buf || !internal_buf->buffer_count_actual) {
+		dprintk(VIDC_DBG, "Inst : %pK Recon buffers not required\n",
+			inst);
+		return 0;
+	}
+
+	if (!list_empty(&inst->reconbufs.list))
+		msm_comm_release_recon_buffers(inst);
+
+	for (i = 0; i < internal_buf->buffer_count_actual; i++) {
+		binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
+		if (!binfo) {
+			dprintk(VIDC_ERR, "Out of memory\n");
+			rc = -ENOMEM;
+			goto fail_kzalloc;
+		}
+
+		binfo->buffer_index = i;
+		mutex_lock(&buf_list->lock);
+		list_add_tail(&binfo->list, &buf_list->list);
+		mutex_unlock(&buf_list->lock);
+	}
+
+fail_kzalloc:
+	return rc;
+}
+
 int msm_comm_set_persist_buffers(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
@@ -5395,7 +5472,7 @@
 
 	hdev = inst->core->device;
 
-	format = get_hal_uncompressed(fourcc);
+	format = msm_comm_get_hal_uncompressed(fourcc);
 	if (format == HAL_UNUSED_COLOR) {
 		dprintk(VIDC_ERR, "Using unsupported colorformat %#x\n",
 				fourcc);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h
index 7534593..52925eb 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h
@@ -41,6 +41,7 @@
 	enum hal_property ptype, void *pdata);
 int msm_comm_try_get_prop(struct msm_vidc_inst *inst,
 	enum hal_property ptype, union hal_get_property *hprop);
+int msm_comm_set_recon_buffers(struct msm_vidc_inst *inst);
 int msm_comm_set_scratch_buffers(struct msm_vidc_inst *inst);
 int msm_comm_set_persist_buffers(struct msm_vidc_inst *inst);
 int msm_comm_set_output_buffers(struct msm_vidc_inst *inst);
@@ -51,6 +52,7 @@
 int msm_comm_release_scratch_buffers(struct msm_vidc_inst *inst,
 					bool check_for_reuse);
 int msm_comm_release_persist_buffers(struct msm_vidc_inst *inst);
+int msm_comm_release_recon_buffers(struct msm_vidc_inst *inst);
 int msm_comm_release_output_buffers(struct msm_vidc_inst *inst,
 	bool force_release);
 void msm_comm_validate_output_buffers(struct msm_vidc_inst *inst);
@@ -98,6 +100,7 @@
 int msm_comm_v4l2_to_hal(int id, int value);
 int msm_comm_hal_to_v4l2(int id, int value);
 int msm_comm_session_continue(void *instance);
+enum hal_uncompressed_format msm_comm_get_hal_uncompressed(int fourcc);
 u32 get_frame_size_nv12(int plane, u32 height, u32 width);
 u32 get_frame_size_nv12_ubwc(int plane, u32 height, u32 width);
 u32 get_frame_size_rgba(int plane, u32 height, u32 width);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index 5edd3d5..769a94d 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -145,6 +145,13 @@
 	unsigned long freq;
 };
 
+struct recon_buf {
+	struct list_head list;
+	u32 buffer_index;
+	u32 CR;
+	u32 CF;
+};
+
 struct internal_buf {
 	struct list_head list;
 	enum hal_buffer buffer_type;
@@ -230,6 +237,8 @@
 	u32 operating_rate;
 	struct clock_profile_entry *entry;
 	u32 core_id;
+	u32 dpb_fourcc;
+	u32 opb_fourcc;
 	enum hal_work_mode work_mode;
 	bool low_latency_mode;
 };
@@ -278,6 +287,7 @@
 	bool smmu_fault_handled;
 	unsigned long min_freq;
 	unsigned long curr_freq;
+	struct vidc_bus_vote_data *vote_data;
 };
 
 struct msm_vidc_inst {
@@ -296,6 +306,7 @@
 	struct msm_vidc_list persistbufs;
 	struct msm_vidc_list pending_getpropq;
 	struct msm_vidc_list outputbufs;
+	struct msm_vidc_list reconbufs;
 	struct msm_vidc_list registeredbufs;
 	struct buffer_requirements buff_req;
 	void *mem_client;
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 86e4f42..695c563 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -1082,6 +1082,22 @@
 	HAL_RESPONSE_UNUSED = 0x10000000,
 };
 
+struct ubwc_cr_stats_info_type {
+	u32 cr_stats_info0;
+	u32 cr_stats_info1;
+	u32 cr_stats_info2;
+	u32 cr_stats_info3;
+	u32 cr_stats_info4;
+	u32 cr_stats_info5;
+	u32 cr_stats_info6;
+};
+
+struct recon_stats_type {
+	u32 buffer_index;
+	u32 complexity_number;
+	struct ubwc_cr_stats_info_type ubwc_stats_info;
+};
+
 struct vidc_hal_ebd {
 	u32 timestamp_hi;
 	u32 timestamp_lo;
@@ -1094,6 +1110,7 @@
 	u32 alloc_len;
 	u32 filled_len;
 	enum hal_picture picture_type;
+	struct recon_stats_type recon_stats;
 	ion_phys_addr_t packet_buffer;
 	ion_phys_addr_t extra_data_buffer;
 };
@@ -1315,8 +1332,16 @@
 	enum hal_video_codec codec;
 	enum hal_uncompressed_format color_formats[2];
 	int num_formats; /* 1 = DPB-OPB unified; 2 = split */
-	int height, width, fps;
+	int input_height, input_width, fps;
+	int output_height, output_width;
+	int compression_ratio;
+	int complexity_factor;
+	unsigned int lcu_size;
 	enum msm_vidc_power_mode power_mode;
+	struct imem_ab_table *imem_ab_tbl;
+	enum hal_work_mode work_mode;
+	unsigned long bitrate;
+	u32 imem_ab_tbl_size;
 };
 
 struct vidc_clk_scale_data {