Browse Source

Merge "video driver: calculate power based on max rate"

qctecmdr 3 years ago
parent
commit
f1918f5314

+ 8 - 0
driver/platform/kalama/src/msm_vidc_kalama.c

@@ -240,6 +240,10 @@ static struct msm_platform_inst_capability instance_data_kalama[] = {
 	{MBPS, DEC, VP9, 36, 4423680, 1, 4423680},
 	{MBPS, DEC, VP9, 36, 4423680, 1, 4423680},
 	/* ((4096 * 2304) / 256) * 60 fps */
 	/* ((4096 * 2304) / 256) * 60 fps */
 	{POWER_SAVE_MBPS, ENC, CODECS_ALL, 0, 2211840, 1, 2211840},
 	{POWER_SAVE_MBPS, ENC, CODECS_ALL, 0, 2211840, 1, 2211840},
+	/* Enable check mbps for encoder */
+	{CHECK_MBPS, ENC, CODECS_ALL, 0, 1, 1, 1},
+	/* Disable check mbps for encoder */
+	{CHECK_MBPS, DEC, CODECS_ALL, 0, 1, 1, 0},
 
 
 	{FRAME_RATE, ENC, CODECS_ALL,
 	{FRAME_RATE, ENC, CODECS_ALL,
 		(MINIMUM_FPS << 16), (MAXIMUM_FPS << 16),
 		(MINIMUM_FPS << 16), (MAXIMUM_FPS << 16),
@@ -298,6 +302,10 @@ static struct msm_platform_inst_capability instance_data_kalama[] = {
 		(MINIMUM_FPS << 16), INT_MAX,
 		(MINIMUM_FPS << 16), INT_MAX,
 		1, (DEFAULT_FPS << 16)},
 		1, (DEFAULT_FPS << 16)},
 
 
+	{TIMESTAMP_RATE, ENC|DEC, CODECS_ALL,
+		(MINIMUM_FPS << 16), INT_MAX,
+		1, (DEFAULT_FPS << 16)},
+
 	{SCALE_FACTOR, ENC, H264|HEVC, 1, 8, 1, 8},
 	{SCALE_FACTOR, ENC, H264|HEVC, 1, 8, 1, 8},
 
 
 	{MB_CYCLES_VSP, ENC, CODECS_ALL, 25, 25, 1, 25},
 	{MB_CYCLES_VSP, ENC, CODECS_ALL, 25, 25, 1, 25},

+ 8 - 0
driver/platform/waipio/src/msm_vidc_waipio.c

@@ -225,6 +225,10 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
 	{MBPS, DEC, VP9, 36, 4423680, 1, 4423680},
 	{MBPS, DEC, VP9, 36, 4423680, 1, 4423680},
 	/* ((4096 * 2304) / 256) * 60 fps */
 	/* ((4096 * 2304) / 256) * 60 fps */
 	{POWER_SAVE_MBPS, ENC, CODECS_ALL, 0, 2211840, 1, 2211840},
 	{POWER_SAVE_MBPS, ENC, CODECS_ALL, 0, 2211840, 1, 2211840},
+	/* Enable check mbps for encoder */
+	{CHECK_MBPS, ENC, CODECS_ALL, 0, 1, 1, 1},
+	/* Disable check mbps for encoder */
+	{CHECK_MBPS, DEC, CODECS_ALL, 0, 1, 1, 0},
 
 
 	{FRAME_RATE, ENC, CODECS_ALL,
 	{FRAME_RATE, ENC, CODECS_ALL,
 		(MINIMUM_FPS << 16), (MAXIMUM_FPS << 16),
 		(MINIMUM_FPS << 16), (MAXIMUM_FPS << 16),
@@ -283,6 +287,10 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
 		(MINIMUM_FPS << 16), INT_MAX,
 		(MINIMUM_FPS << 16), INT_MAX,
 		1, (DEFAULT_FPS << 16)},
 		1, (DEFAULT_FPS << 16)},
 
 
+	{TIMESTAMP_RATE, ENC|DEC, CODECS_ALL,
+		(MINIMUM_FPS << 16), INT_MAX,
+		1, (DEFAULT_FPS << 16)},
+
 	{SCALE_FACTOR, ENC, H264|HEVC, 1, 8, 1, 8},
 	{SCALE_FACTOR, ENC, H264|HEVC, 1, 8, 1, 8},
 
 
 	{MB_CYCLES_VSP, ENC, CODECS_ALL, 25, 25, 1, 25},
 	{MB_CYCLES_VSP, ENC, CODECS_ALL, 25, 25, 1, 25},

+ 2 - 25
driver/variant/iris2/src/msm_vidc_power_iris2.c

@@ -20,8 +20,7 @@ u64 msm_vidc_calc_freq_iris2(struct msm_vidc_inst *inst, u32 data_size)
 	u32 mbs_per_second;
 	u32 mbs_per_second;
 	u32 operating_rate, vsp_factor_num = 1, vsp_factor_den = 1;
 	u32 operating_rate, vsp_factor_num = 1, vsp_factor_den = 1;
 	u32 base_cycles = 0;
 	u32 base_cycles = 0;
-	u32 fps;
-	u32 buf_timetamps_fps, mbpf, input_rate;
+	u32 fps, mbpf;
 
 
 	if (!inst || !inst->core || !inst->capabilities) {
 	if (!inst || !inst->core || !inst->capabilities) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		d_vpr_e("%s: invalid params\n", __func__);
@@ -35,29 +34,7 @@ u64 msm_vidc_calc_freq_iris2(struct msm_vidc_inst *inst, u32 data_size)
 	}
 	}
 
 
 	mbpf = msm_vidc_get_mbs_per_frame(inst);
 	mbpf = msm_vidc_get_mbs_per_frame(inst);
-	fps = msm_vidc_get_fps(inst);
-
-	buf_timetamps_fps = msm_vidc_calc_window_avg_framerate(inst);
-
-	/*
-	 * when buffer detected fps is more than client set value by 10%,
-	 * utilize buffer detected fps to scale clock.
-	 */
-	if (div_u64(fps * 11, 10) < buf_timetamps_fps) {
-		fps = buf_timetamps_fps;
-		inst->priority_level = MSM_VIDC_PRIORITY_LOW;
-	}
-	if (!is_realtime_session(inst)) {
-		input_rate = msm_vidc_get_input_rate(inst);
-		if (input_rate > fps) {
-			fps = input_rate;
-			/*
-			 * add 12.5% more fps to increase power to make firmware
-			 * processing little faster than client queuing rate
-			 */
-			fps = fps + fps / 8;
-		}
-	}
+	fps = inst->max_rate;
 	mbs_per_second = mbpf * fps;
 	mbs_per_second = mbpf * fps;
 
 
 	/*
 	/*

+ 2 - 25
driver/variant/iris3/src/msm_vidc_power_iris3.c

@@ -21,8 +21,7 @@ u64 msm_vidc_calc_freq_iris3(struct msm_vidc_inst *inst, u32 data_size)
 	u32 mbs_per_second;
 	u32 mbs_per_second;
 	u32 operating_rate, vsp_factor_num = 1, vsp_factor_den = 1;
 	u32 operating_rate, vsp_factor_num = 1, vsp_factor_den = 1;
 	u32 base_cycles = 0;
 	u32 base_cycles = 0;
-	u32 fps;
-	u32 buf_timetamps_fps, mbpf, input_rate;
+	u32 fps, mbpf;
 
 
 	if (!inst || !inst->core || !inst->capabilities) {
 	if (!inst || !inst->core || !inst->capabilities) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		d_vpr_e("%s: invalid params\n", __func__);
@@ -36,29 +35,7 @@ u64 msm_vidc_calc_freq_iris3(struct msm_vidc_inst *inst, u32 data_size)
 	}
 	}
 
 
 	mbpf = msm_vidc_get_mbs_per_frame(inst);
 	mbpf = msm_vidc_get_mbs_per_frame(inst);
-	fps = msm_vidc_get_fps(inst);
-
-	buf_timetamps_fps = msm_vidc_calc_window_avg_framerate(inst);
-
-	/*
-	 * when buffer detected fps is more than client set value by 10%,
-	 * utilize buffer detected fps to scale clock.
-	 */
-	if (div_u64(fps * 11, 10) < buf_timetamps_fps) {
-		fps = buf_timetamps_fps;
-		inst->priority_level = MSM_VIDC_PRIORITY_LOW;
-	}
-	if (!is_realtime_session(inst)) {
-		input_rate = msm_vidc_get_input_rate(inst);
-		if (input_rate > fps) {
-			fps = input_rate;
-			/*
-			 * add 12.5% more fps to increase power to make firmware
-			 * processing little faster than client queuing rate
-			 */
-			fps = fps + fps / 8;
-		}
-	}
+	fps = inst->max_rate;
 	mbs_per_second = mbpf * fps;
 	mbs_per_second = mbpf * fps;
 
 
 	/*
 	/*

+ 4 - 2
driver/vidc/inc/msm_vidc_driver.h

@@ -480,9 +480,9 @@ int msm_vidc_check_session_supported(struct msm_vidc_inst *inst);
 int msm_vidc_check_core_mbps(struct msm_vidc_inst *inst);
 int msm_vidc_check_core_mbps(struct msm_vidc_inst *inst);
 int msm_vidc_check_core_mbpf(struct msm_vidc_inst *inst);
 int msm_vidc_check_core_mbpf(struct msm_vidc_inst *inst);
 int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst);
 int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst);
-int msm_vidc_update_timestamp(struct msm_vidc_inst *inst, u64 timestamp);
+int msm_vidc_update_timestamp_rate(struct msm_vidc_inst *inst, u64 timestamp);
 int msm_vidc_set_auto_framerate(struct msm_vidc_inst *inst, u64 timestamp);
 int msm_vidc_set_auto_framerate(struct msm_vidc_inst *inst, u64 timestamp);
-int msm_vidc_calc_window_avg_framerate(struct msm_vidc_inst *inst);
+int msm_vidc_get_timestamp_rate(struct msm_vidc_inst *inst);
 int msm_vidc_flush_ts(struct msm_vidc_inst *inst);
 int msm_vidc_flush_ts(struct msm_vidc_inst *inst);
 int msm_vidc_ts_reorder_insert_timestamp(struct msm_vidc_inst *inst, u64 timestamp);
 int msm_vidc_ts_reorder_insert_timestamp(struct msm_vidc_inst *inst, u64 timestamp);
 int msm_vidc_ts_reorder_remove_timestamp(struct msm_vidc_inst *inst, u64 timestamp);
 int msm_vidc_ts_reorder_remove_timestamp(struct msm_vidc_inst *inst, u64 timestamp);
@@ -502,5 +502,7 @@ int msm_vidc_create_input_metadata_buffer(struct msm_vidc_inst *inst, int buf_fd
 int msm_vidc_update_input_meta_buffer_index(struct msm_vidc_inst *inst, struct vb2_buffer *vb2);
 int msm_vidc_update_input_meta_buffer_index(struct msm_vidc_inst *inst, struct vb2_buffer *vb2);
 int msm_vidc_update_input_rate(struct msm_vidc_inst *inst, u64 time_us);
 int msm_vidc_update_input_rate(struct msm_vidc_inst *inst, u64 time_us);
 int msm_vidc_get_input_rate(struct msm_vidc_inst *inst);
 int msm_vidc_get_input_rate(struct msm_vidc_inst *inst);
+int msm_vidc_get_frame_rate(struct msm_vidc_inst *inst);
+int msm_vidc_get_operating_rate(struct msm_vidc_inst *inst);
 #endif // _MSM_VIDC_DRIVER_H_
 #endif // _MSM_VIDC_DRIVER_H_
 
 

+ 1 - 0
driver/vidc/inc/msm_vidc_inst.h

@@ -170,6 +170,7 @@ struct msm_vidc_inst {
 	u32                                dpb_list_payload[MAX_DPB_LIST_ARRAY_SIZE];
 	u32                                dpb_list_payload[MAX_DPB_LIST_ARRAY_SIZE];
 	u32                                max_map_output_count;
 	u32                                max_map_output_count;
 	u32                                auto_framerate;
 	u32                                auto_framerate;
+	u32                                max_rate;
 	bool                               has_bframe;
 	bool                               has_bframe;
 };
 };
 #endif // _MSM_VIDC_INST_H_
 #endif // _MSM_VIDC_INST_H_

+ 2 - 0
driver/vidc/inc/msm_vidc_internal.h

@@ -398,9 +398,11 @@ enum msm_vidc_inst_capability_type {
 	SECURE_MBPF,
 	SECURE_MBPF,
 	MBPS,
 	MBPS,
 	POWER_SAVE_MBPS,
 	POWER_SAVE_MBPS,
+	CHECK_MBPS,
 	FRAME_RATE,
 	FRAME_RATE,
 	OPERATING_RATE,
 	OPERATING_RATE,
 	INPUT_RATE,
 	INPUT_RATE,
+	TIMESTAMP_RATE,
 	SCALE_FACTOR,
 	SCALE_FACTOR,
 	MB_CYCLES_VSP,
 	MB_CYCLES_VSP,
 	MB_CYCLES_VPP,
 	MB_CYCLES_VPP,

+ 64 - 35
driver/vidc/src/msm_vidc_driver.c

@@ -97,9 +97,11 @@ static const struct msm_vidc_cap_name cap_name_arr[] = {
 	{SECURE_MBPF,                    "SECURE_MBPF"                },
 	{SECURE_MBPF,                    "SECURE_MBPF"                },
 	{MBPS,                           "MBPS"                       },
 	{MBPS,                           "MBPS"                       },
 	{POWER_SAVE_MBPS,                "POWER_SAVE_MBPS"            },
 	{POWER_SAVE_MBPS,                "POWER_SAVE_MBPS"            },
+	{CHECK_MBPS,                     "CHECK_MPBS"                 },
 	{FRAME_RATE,                     "FRAME_RATE"                 },
 	{FRAME_RATE,                     "FRAME_RATE"                 },
 	{OPERATING_RATE,                 "OPERATING_RATE"             },
 	{OPERATING_RATE,                 "OPERATING_RATE"             },
 	{INPUT_RATE,                     "INPUT_RATE"                 },
 	{INPUT_RATE,                     "INPUT_RATE"                 },
+	{TIMESTAMP_RATE,                 "TIMESTAMP_RATE"             },
 	{SCALE_FACTOR,                   "SCALE_FACTOR"               },
 	{SCALE_FACTOR,                   "SCALE_FACTOR"               },
 	{MB_CYCLES_VSP,                  "MB_CYCLES_VSP"              },
 	{MB_CYCLES_VSP,                  "MB_CYCLES_VSP"              },
 	{MB_CYCLES_VPP,                  "MB_CYCLES_VPP"              },
 	{MB_CYCLES_VPP,                  "MB_CYCLES_VPP"              },
@@ -2181,14 +2183,13 @@ int msm_vidc_get_fps(struct msm_vidc_inst *inst)
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	frame_rate = inst->capabilities->cap[FRAME_RATE].value;
-	operating_rate = inst->capabilities->cap[OPERATING_RATE].value;
+	frame_rate = msm_vidc_get_frame_rate(inst);
+	operating_rate = msm_vidc_get_operating_rate(inst);
 
 
 	if (operating_rate > frame_rate)
 	if (operating_rate > frame_rate)
-		fps = (operating_rate >> 16) ?
-			(operating_rate >> 16) : 1;
+		fps = operating_rate ? operating_rate : 1;
 	else
 	else
-		fps = frame_rate >> 16;
+		fps = frame_rate;
 
 
 	return fps;
 	return fps;
 }
 }
@@ -2331,7 +2332,7 @@ int msm_vidc_set_auto_framerate(struct msm_vidc_inst *inst, u64 timestamp)
 			!inst->capabilities->cap[TIME_DELTA_BASED_RC].value)
 			!inst->capabilities->cap[TIME_DELTA_BASED_RC].value)
 		goto exit;
 		goto exit;
 
 
-	rc = msm_vidc_update_timestamp(inst, timestamp);
+	rc = msm_vidc_update_timestamp_rate(inst, timestamp);
 	if (rc)
 	if (rc)
 		goto exit;
 		goto exit;
 
 
@@ -2373,32 +2374,6 @@ exit:
 	return rc;
 	return rc;
 }
 }
 
 
-int msm_vidc_calc_window_avg_framerate(struct msm_vidc_inst *inst)
-{
-	struct msm_vidc_timestamp *ts;
-	struct msm_vidc_timestamp *prev = NULL;
-	u32 counter = 0;
-	u64 ts_ms = 0;
-
-	if (!inst) {
-		d_vpr_e("%s: invalid params\n", __func__);
-		return -EINVAL;
-	}
-
-	list_for_each_entry(ts, &inst->timestamps.list, sort.list) {
-		if (prev) {
-			if (ts->sort.val == prev->sort.val)
-				continue;
-
-			ts_ms += div_u64(ts->sort.val - prev->sort.val, 1000000);
-			counter++;
-		}
-		prev = ts;
-	}
-
-	return ts_ms ? (1000 * counter) / ts_ms : 0;
-}
-
 int msm_vidc_update_input_rate(struct msm_vidc_inst *inst, u64 time_us)
 int msm_vidc_update_input_rate(struct msm_vidc_inst *inst, u64 time_us)
 {
 {
 	struct msm_vidc_input_timer *input_timer;
 	struct msm_vidc_input_timer *input_timer;
@@ -2452,6 +2427,36 @@ int msm_vidc_get_input_rate(struct msm_vidc_inst *inst)
 	return inst->capabilities->cap[INPUT_RATE].value >> 16;
 	return inst->capabilities->cap[INPUT_RATE].value >> 16;
 }
 }
 
 
+int msm_vidc_get_timestamp_rate(struct msm_vidc_inst *inst)
+{
+	if (!inst || !inst->capabilities) {
+		d_vpr_e("%s: Invalid params\n", __func__);
+		return 0;
+	}
+
+	return inst->capabilities->cap[TIMESTAMP_RATE].value >> 16;
+}
+
+int msm_vidc_get_frame_rate(struct msm_vidc_inst *inst)
+{
+	if (!inst || !inst->capabilities) {
+		d_vpr_e("%s: Invalid params\n", __func__);
+		return 0;
+	}
+
+	return inst->capabilities->cap[FRAME_RATE].value >> 16;
+}
+
+int msm_vidc_get_operating_rate(struct msm_vidc_inst *inst)
+{
+	if (!inst || !inst->capabilities) {
+		d_vpr_e("%s: Invalid params\n", __func__);
+		return 0;
+	}
+
+	return inst->capabilities->cap[OPERATING_RATE].value >> 16;
+}
+
 static int msm_vidc_insert_sort(struct list_head *head,
 static int msm_vidc_insert_sort(struct list_head *head,
 	struct msm_vidc_sort *entry)
 	struct msm_vidc_sort *entry)
 {
 {
@@ -2532,11 +2537,14 @@ int msm_vidc_flush_ts(struct msm_vidc_inst *inst)
 	return 0;
 	return 0;
 }
 }
 
 
-int msm_vidc_update_timestamp(struct msm_vidc_inst *inst, u64 timestamp)
+int msm_vidc_update_timestamp_rate(struct msm_vidc_inst *inst, u64 timestamp)
 {
 {
-	struct msm_vidc_timestamp *ts;
+	struct msm_vidc_timestamp *ts, *prev;
 	int rc = 0;
 	int rc = 0;
 	u32 window_size = 0;
 	u32 window_size = 0;
+	u32 timestamp_rate = 0;
+	u64 ts_ms = 0;
+	u32 counter = 0;
 
 
 	if (!inst) {
 	if (!inst) {
 		d_vpr_e("%s: Invalid params\n", __func__);
 		d_vpr_e("%s: Invalid params\n", __func__);
@@ -2574,6 +2582,21 @@ int msm_vidc_update_timestamp(struct msm_vidc_inst *inst, u64 timestamp)
 		msm_memory_pool_free(inst, ts);
 		msm_memory_pool_free(inst, ts);
 	}
 	}
 
 
+	/* Calculate timestamp rate */
+	list_for_each_entry(ts, &inst->timestamps.list, sort.list) {
+		if (prev) {
+			if (ts->sort.val == prev->sort.val)
+				continue;
+			ts_ms += div_u64(ts->sort.val - prev->sort.val, 1000000);
+			counter++;
+		}
+		prev = ts;
+	}
+	if (ts_ms)
+		timestamp_rate = (u32)div_u64((u64)counter * 1000, ts_ms);
+
+	msm_vidc_update_cap_value(inst, TIMESTAMP_RATE, timestamp_rate << 16, __func__);
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -5825,11 +5848,17 @@ int msm_vidc_check_core_mbps(struct msm_vidc_inst *inst)
 	u64 curr_time_ns;
 	u64 curr_time_ns;
 	int rc = 0;
 	int rc = 0;
 
 
-	if (!inst || !inst->core) {
+	if (!inst || !inst->core || !inst->capabilities) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 	core = inst->core;
 	core = inst->core;
+
+	if (!inst->capabilities->cap[CHECK_MBPS].value) {
+		i_vpr_h(inst, "%s: skip mbps check\n", __func__);
+		return 0;
+	}
+
 	curr_time_ns = ktime_get_ns();
 	curr_time_ns = ktime_get_ns();
 
 
 	core_lock(core, __func__);
 	core_lock(core, __func__);

+ 62 - 41
driver/vidc/src/msm_vidc_power.c

@@ -45,34 +45,44 @@ u64 msm_vidc_max_freq(struct msm_vidc_inst *inst)
 
 
 int msm_vidc_get_mbps(struct msm_vidc_inst *inst)
 int msm_vidc_get_mbps(struct msm_vidc_inst *inst)
 {
 {
-	u32 mbpf, fps;
+	u32 mbpf, fps, input_rate;
 
 
 	mbpf = msm_vidc_get_mbs_per_frame(inst);
 	mbpf = msm_vidc_get_mbs_per_frame(inst);
 	fps = msm_vidc_get_fps(inst);
 	fps = msm_vidc_get_fps(inst);
+	input_rate = msm_vidc_get_input_rate(inst);
 
 
-	return mbpf * fps;
+	return mbpf * max(fps, input_rate);
 }
 }
 
 
 int msm_vidc_get_inst_load(struct msm_vidc_inst *inst)
 int msm_vidc_get_inst_load(struct msm_vidc_inst *inst)
 {
 {
 	int load = 0;
 	int load = 0;
+	u32 mbpf, fps;
+	u32 frame_rate, operating_rate, input_rate, timestamp_rate;
 
 
 	if (!inst || !inst->capabilities) {
 	if (!inst || !inst->capabilities) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	/*
-	 * NRT sessions - clock scaling is based on OPP table.
-	 *              - No load based rejection.
-	 * RT sessions  - clock scaling and session admission based on load.
-	 */
+	/* return zero load for thumbnail and NRT session */
 	if (is_thumbnail_session(inst) || !is_realtime_session(inst))
 	if (is_thumbnail_session(inst) || !is_realtime_session(inst))
-		load = 0;
-	else
-		load = msm_vidc_get_mbps(inst);
+		return load;
 
 
-	return load;
+	/* calculate load for RT session */
+	mbpf = msm_vidc_get_mbs_per_frame(inst);
+	frame_rate = msm_vidc_get_frame_rate(inst);
+	operating_rate = msm_vidc_get_operating_rate(inst);
+	fps = max(frame_rate, operating_rate);
+
+	if (is_decode_session(inst)) {
+		input_rate = msm_vidc_get_input_rate(inst);
+		timestamp_rate = msm_vidc_get_timestamp_rate(inst);
+		fps = max(fps, input_rate);
+		fps = max(fps, timestamp_rate);
+	}
+
+	return load = mbpf * fps;
 }
 }
 
 
 static int fill_dynamic_stats(struct msm_vidc_inst *inst,
 static int fill_dynamic_stats(struct msm_vidc_inst *inst,
@@ -178,7 +188,8 @@ int msm_vidc_scale_buses(struct msm_vidc_inst *inst)
 	struct vidc_bus_vote_data *vote_data;
 	struct vidc_bus_vote_data *vote_data;
 	struct v4l2_format *out_f;
 	struct v4l2_format *out_f;
 	struct v4l2_format *inp_f;
 	struct v4l2_format *inp_f;
-	int codec = 0, frame_rate, buf_ts_fps, input_rate;
+	int codec = 0;
+	u32 operating_rate, frame_rate;
 
 
 	if (!inst || !inst->core || !inst->capabilities) {
 	if (!inst || !inst->core || !inst->capabilities) {
 		d_vpr_e("%s: invalid params: %pK\n", __func__, inst);
 		d_vpr_e("%s: invalid params: %pK\n", __func__, inst);
@@ -213,7 +224,6 @@ int msm_vidc_scale_buses(struct msm_vidc_inst *inst)
 		break;
 		break;
 	}
 	}
 
 
-	frame_rate = inst->capabilities->cap[FRAME_RATE].value;
 	vote_data->codec = inst->codec;
 	vote_data->codec = inst->codec;
 	vote_data->input_width = inp_f->fmt.pix_mp.width;
 	vote_data->input_width = inp_f->fmt.pix_mp.width;
 	vote_data->input_height = inp_f->fmt.pix_mp.height;
 	vote_data->input_height = inp_f->fmt.pix_mp.height;
@@ -221,38 +231,21 @@ int msm_vidc_scale_buses(struct msm_vidc_inst *inst)
 	vote_data->output_height = out_f->fmt.pix_mp.height;
 	vote_data->output_height = out_f->fmt.pix_mp.height;
 	vote_data->lcu_size = (codec == V4L2_PIX_FMT_HEVC ||
 	vote_data->lcu_size = (codec == V4L2_PIX_FMT_HEVC ||
 			codec == V4L2_PIX_FMT_VP9) ? 32 : 16;
 			codec == V4L2_PIX_FMT_VP9) ? 32 : 16;
-	vote_data->fps = msm_vidc_get_fps(inst);
-	buf_ts_fps = msm_vidc_calc_window_avg_framerate(inst);
-	if (buf_ts_fps > vote_data->fps) {
-		i_vpr_l(inst, "%s: bitstream: fps %d, client rate %u\n", __func__,
-			buf_ts_fps, vote_data->fps);
-		vote_data->fps = buf_ts_fps;
-	}
-	if (!is_realtime_session(inst)) {
-		input_rate = msm_vidc_get_input_rate(inst);
-		if (input_rate > vote_data->fps) {
-			i_vpr_h(inst, "%s: use input rate %d for fps (%u)\n", __func__,
-				input_rate, vote_data->fps);
-			vote_data->fps = input_rate;
-			/*
-			 * add 12.5% more fps to increase power to make firmware
-			 * processing little faster than client queuing rate
-			 */
-			vote_data->fps = vote_data->fps + vote_data->fps / 8;
-		}
-	}
+	vote_data->fps = inst->max_rate;
+
 	if (inst->domain == MSM_VIDC_ENCODER) {
 	if (inst->domain == MSM_VIDC_ENCODER) {
 		vote_data->domain = MSM_VIDC_ENCODER;
 		vote_data->domain = MSM_VIDC_ENCODER;
 		vote_data->bitrate = inst->capabilities->cap[BIT_RATE].value;
 		vote_data->bitrate = inst->capabilities->cap[BIT_RATE].value;
 		vote_data->rotation = inst->capabilities->cap[ROTATION].value;
 		vote_data->rotation = inst->capabilities->cap[ROTATION].value;
 		vote_data->b_frames_enabled =
 		vote_data->b_frames_enabled =
 			inst->capabilities->cap[B_FRAME].value > 0;
 			inst->capabilities->cap[B_FRAME].value > 0;
-		/* scale bitrate if operating rate is larger than fps */
-		if (vote_data->fps > (frame_rate >> 16) &&
-			(frame_rate >> 16)) {
-			vote_data->bitrate = vote_data->bitrate /
-				(frame_rate >> 16) * vote_data->fps;
-		}
+
+		/* scale bitrate if operating rate is larger than frame rate */
+		frame_rate = msm_vidc_get_frame_rate(inst);
+		operating_rate = msm_vidc_get_frame_rate(inst);
+		if (frame_rate && operating_rate && operating_rate > frame_rate)
+			vote_data->bitrate = (vote_data->bitrate / frame_rate) * operating_rate;
+
 		vote_data->num_formats = 1;
 		vote_data->num_formats = 1;
 		vote_data->color_formats[0] = v4l2_colorformat_to_driver(
 		vote_data->color_formats[0] = v4l2_colorformat_to_driver(
 			inst->fmts[INPUT_PORT].fmt.pix_mp.pixelformat, __func__);
 			inst->fmts[INPUT_PORT].fmt.pix_mp.pixelformat, __func__);
@@ -488,6 +481,8 @@ int msm_vidc_scale_power(struct msm_vidc_inst *inst, bool scale_buses)
 	struct msm_vidc_core *core;
 	struct msm_vidc_core *core;
 	struct msm_vidc_buffer *vbuf;
 	struct msm_vidc_buffer *vbuf;
 	u32 data_size = 0;
 	u32 data_size = 0;
+	u32 fps;
+	u32 frame_rate, operating_rate, timestamp_rate, input_rate;
 
 
 	if (!inst || !inst->core) {
 	if (!inst || !inst->core) {
 		d_vpr_e("%s: invalid params %pK\n", __func__, inst);
 		d_vpr_e("%s: invalid params %pK\n", __func__, inst);
@@ -505,6 +500,31 @@ int msm_vidc_scale_power(struct msm_vidc_inst *inst, bool scale_buses)
 		data_size = max(data_size, vbuf->data_size);
 		data_size = max(data_size, vbuf->data_size);
 	inst->max_input_data_size = data_size;
 	inst->max_input_data_size = data_size;
 
 
+	frame_rate = msm_vidc_get_frame_rate(inst);
+	operating_rate = msm_vidc_get_operating_rate(inst);
+	fps = max(frame_rate, operating_rate);
+	if (is_decode_session(inst)) {
+		/*
+		 * when buffer detected fps is more than client set value by 12.5%,
+		 * utilize buffer detected fps to scale clock.
+		 */
+		timestamp_rate = msm_vidc_get_timestamp_rate(inst);
+		input_rate = msm_vidc_get_input_rate(inst);
+		if (timestamp_rate > (fps + fps / 8)) {
+			fps = timestamp_rate;
+			inst->priority_level = MSM_VIDC_PRIORITY_LOW;
+		}
+		if (input_rate > fps) {
+			fps = input_rate;
+			/*
+			 * add 6.25% more fps to increase power to make firmware
+			 * processing little faster than client queuing rate
+			 */
+			fps = fps + fps / 16;
+		}
+	}
+	inst->max_rate = fps;
+
 	/* no pending inputs - skip scale power */
 	/* no pending inputs - skip scale power */
 	if (!inst->max_input_data_size)
 	if (!inst->max_input_data_size)
 		return 0;
 		return 0;
@@ -518,10 +538,11 @@ int msm_vidc_scale_power(struct msm_vidc_inst *inst, bool scale_buses)
 	}
 	}
 
 
 	i_vpr_hp(inst,
 	i_vpr_hp(inst,
-		"power: inst: clk %lld ddr %d llcc %d dcvs flags %#x, core: clk %lld ddr %lld llcc %lld\n",
+		"power: inst: clk %lld ddr %d llcc %d dcvs flags %#x fps %u (%u %u %u %u) core: clk %lld ddr %lld llcc %lld\n",
 		inst->power.curr_freq, inst->power.ddr_bw,
 		inst->power.curr_freq, inst->power.ddr_bw,
 		inst->power.sys_cache_bw, inst->power.dcvs_flags,
 		inst->power.sys_cache_bw, inst->power.dcvs_flags,
-		core->power.clk_freq, core->power.bw_ddr,
+		inst->max_rate, frame_rate, operating_rate, timestamp_rate,
+		input_rate, core->power.clk_freq, core->power.bw_ddr,
 		core->power.bw_llcc);
 		core->power.bw_llcc);
 
 
 	trace_msm_vidc_perf_power_scale(inst, core->power.clk_freq,
 	trace_msm_vidc_perf_power_scale(inst, core->power.clk_freq,

+ 1 - 1
driver/vidc/src/msm_vidc_vb2.c

@@ -464,7 +464,7 @@ void msm_vidc_buf_queue(struct vb2_buffer *vb2)
 	}
 	}
 	inst->last_qbuf_time_ns = ktime_ns;
 	inst->last_qbuf_time_ns = ktime_ns;
 
 
-	if (!is_realtime_session(inst) && vb2->type == INPUT_MPLANE) {
+	if (is_decode_session(inst) && vb2->type == INPUT_MPLANE) {
 		rc = msm_vidc_update_input_rate(inst, div_u64(ktime_ns, 1000));
 		rc = msm_vidc_update_input_rate(inst, div_u64(ktime_ns, 1000));
 		if (rc)
 		if (rc)
 			goto unlock;
 			goto unlock;

+ 1 - 1
driver/vidc/src/venus_hfi_response.c

@@ -904,7 +904,7 @@ static int handle_output_buffer(struct msm_vidc_inst *inst,
 	}
 	}
 
 
 	if (!is_image_session(inst) && is_decode_session(inst) && buf->data_size)
 	if (!is_image_session(inst) && is_decode_session(inst) && buf->data_size)
-		msm_vidc_update_timestamp(inst, buf->timestamp);
+		msm_vidc_update_timestamp_rate(inst, buf->timestamp);
 
 
 	/* update output buffer timestamp, if ts_reorder is enabled */
 	/* update output buffer timestamp, if ts_reorder is enabled */
 	if (is_ts_reorder_allowed(inst) && buf->data_size)
 	if (is_ts_reorder_allowed(inst) && buf->data_size)