Эх сурвалжийг харах

video: driver: enable dcvs - power feature

Enable/disable dcvs based on below settings.

- core supports dcvs
- core_clock_voting is set: disable
- encode_batching(superframe): disable
- decode_batching: disable
- thumbnail session: disable
- image session: disable

Handle below items as part of dcvs enablement.

- skip clock scaling for inactive session.
- reset dcvs flags to 0, for encoder at dcvs_window.

Change-Id: I84e6710946bca3fa8c83178f29745d4b9afd4697
Signed-off-by: Govindaraj Rajagopal <[email protected]>
Govindaraj Rajagopal 4 жил өмнө
parent
commit
78b1491ee1

+ 1 - 1
driver/platform/waipio/src/msm_vidc_waipio.c

@@ -241,7 +241,7 @@ static struct msm_platform_inst_capability instance_data_waipio[] = {
 		CAP_FLAG_ROOT | CAP_FLAG_OUTPUT_PORT},
 
 	{SUPER_FRAME, ENC, H264|HEVC,
-		0, 16, 1, 0,
+		0, 32, 1, 0,
 		V4L2_CID_MPEG_VIDC_SUPERFRAME,
 		0},
 

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

@@ -351,6 +351,7 @@ int msm_vidc_init_instance_caps(struct msm_vidc_core* core);
 int msm_vidc_deinit_core_caps(struct msm_vidc_core* core);
 int msm_vidc_deinit_instance_caps(struct msm_vidc_core* core);
 int msm_vidc_update_debug_str(struct msm_vidc_inst *inst);
+void msm_vidc_allow_dcvs(struct msm_vidc_inst *inst);
 bool msm_vidc_allow_decode_batch(struct msm_vidc_inst *inst);
 int msm_vidc_check_session_supported(struct msm_vidc_inst *inst);
 int msm_vidc_check_mbps_supported(struct msm_vidc_inst *inst);

+ 1 - 6
driver/vidc/inc/msm_vidc_internal.h

@@ -57,12 +57,7 @@
 #define MAX_AVC_ENH_LAYER_HYBRID_HP           5
 #define PERCENT_PEAK_BITRATE_INCREASED       10
 
-/* TODO
- * #define MAX_SUPERFRAME_COUNT     32
-*/
-
-/* Maintains the number of FTB's between each FBD over a window */
-#define DCVS_FTB_WINDOW 16
+#define DCVS_WINDOW 16
 /* Superframe can have maximum of 32 frames */
 #define VIDC_SUPERFRAME_MAX 32
 #define COLOR_RANGE_UNSPECIFIED (-1)

+ 1 - 1
driver/vidc/inc/msm_vidc_power.h

@@ -249,5 +249,5 @@ static inline int __bpp(enum msm_vidc_colorformat_type f)
 u64 msm_vidc_max_freq(struct msm_vidc_inst* inst);
 int msm_vidc_get_inst_load(struct msm_vidc_inst *inst);
 int msm_vidc_scale_power(struct msm_vidc_inst *inst, bool scale_buses);
-
+void msm_vidc_power_data_reset(struct msm_vidc_inst *inst);
 #endif

+ 7 - 6
driver/vidc/src/msm_vdec.c

@@ -15,6 +15,7 @@
 #include "msm_vidc_platform.h"
 #include "msm_vidc_control.h"
 #include "msm_vidc_debug.h"
+#include "msm_vidc_power.h"
 #include "msm_vidc_control.h"
 #include "venus_hfi.h"
 #include "hfi_packet.h"
@@ -1322,8 +1323,6 @@ static int msm_vdec_read_input_subcr_params(struct msm_vidc_inst *inst)
 	else
 		msm_vidc_update_cap_value(inst, CODED_FRAMES, CODED_FRAMES_INTERLACE, __func__);
 
-	inst->decode_batch.enable = msm_vidc_allow_decode_batch(inst);
-
 	return 0;
 }
 
@@ -1463,8 +1462,6 @@ int msm_vdec_streamon_input(struct msm_vidc_inst *inst)
 	if (rc)
 		goto error;
 
-	inst->decode_batch.enable = msm_vidc_allow_decode_batch(inst);
-
 	return 0;
 
 error:
@@ -1705,8 +1702,6 @@ int msm_vdec_streamon_output(struct msm_vidc_inst *inst)
 	if (rc)
 		goto error;
 
-	inst->decode_batch.enable = msm_vidc_allow_decode_batch(inst);
-
 	return 0;
 
 error:
@@ -1813,6 +1808,12 @@ int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
 		port = (inst->state == MSM_VIDC_DRAIN_LAST_FLAG) ? INPUT_PORT : OUTPUT_PORT;
 		vb2_clear_last_buffer_dequeued(&inst->vb2q[OUTPUT_META_PORT]);
 		vb2_clear_last_buffer_dequeued(&inst->vb2q[OUTPUT_PORT]);
+
+		/* tune power features */
+		inst->decode_batch.enable = msm_vidc_allow_decode_batch(inst);
+		msm_vidc_allow_dcvs(inst);
+		msm_vidc_power_data_reset(inst);
+
 		rc = msm_vidc_state_change_start(inst);
 		if (rc)
 			return rc;

+ 6 - 0
driver/vidc/src/msm_venc.c

@@ -14,6 +14,7 @@
 #include "msm_vidc_platform.h"
 #include "msm_vidc_control.h"
 #include "msm_vidc_debug.h"
+#include "msm_vidc_power.h"
 #include "venus_hfi.h"
 #include "hfi_packet.h"
 
@@ -971,6 +972,11 @@ int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
 			return -EBUSY;
 		vb2_clear_last_buffer_dequeued(&inst->vb2q[OUTPUT_META_PORT]);
 		vb2_clear_last_buffer_dequeued(&inst->vb2q[OUTPUT_PORT]);
+
+		/* tune power features */
+		msm_vidc_allow_dcvs(inst);
+		msm_vidc_power_data_reset(inst);
+
 		rc = msm_vidc_state_change_start(inst);
 		if (rc)
 			return rc;

+ 2 - 0
driver/vidc/src/msm_vidc.c

@@ -453,6 +453,8 @@ int msm_vidc_qbuf(void *instance, struct media_device *mdev,
 		goto unlock;
 	}
 
+	inst->last_qbuf_time_ns = ktime_get_ns();
+
 	rc = vb2_qbuf(q, mdev, b);
 	if (rc)
 		i_vpr_e(inst, "%s: failed with %d\n", __func__, rc);

+ 58 - 3
driver/vidc/src/msm_vidc_driver.c

@@ -1995,6 +1995,60 @@ static bool is_single_session(struct msm_vidc_inst *inst)
 	return count == 1;
 }
 
+void msm_vidc_allow_dcvs(struct msm_vidc_inst *inst)
+{
+	bool allow = false;
+	struct msm_vidc_core *core;
+
+	if (!inst || !inst->core) {
+		d_vpr_e("%s: Invalid args: %pK\n", __func__, inst);
+		return;
+	}
+	core = inst->core;
+
+	allow = !msm_vidc_clock_voting;
+	if (!allow) {
+		i_vpr_h(inst, "%s: core_clock_voting is set\n", __func__);
+		goto exit;
+	}
+
+	allow = core->capabilities[DCVS].value;
+	if (!allow) {
+		i_vpr_h(inst, "%s: core doesn't support dcvs\n", __func__);
+		goto exit;
+	}
+
+	allow = !inst->decode_batch.enable;
+	if (!allow) {
+		i_vpr_h(inst, "%s: decode_batching enabled\n", __func__);
+		goto exit;
+	}
+
+	allow = !msm_vidc_is_super_buffer(inst);
+	if (!allow) {
+		i_vpr_h(inst, "%s: encode_batching(super_buffer) enabled\n", __func__);
+		goto exit;
+	}
+
+	allow = !is_thumbnail_session(inst);
+	if (!allow) {
+		i_vpr_h(inst, "%s: thumbnail session\n", __func__);
+		goto exit;
+	}
+
+	allow = !is_image_session(inst);
+	if (!allow) {
+		i_vpr_h(inst, "%s: image session\n", __func__);
+		goto exit;
+	}
+
+exit:
+	i_vpr_h(inst, "%s: dcvs: %s\n", __func__, allow ? "enabled" : "disabled");
+
+	inst->power.dcvs_flags = 0;
+	inst->power.dcvs_mode = allow;
+}
+
 bool msm_vidc_allow_decode_batch(struct msm_vidc_inst *inst)
 {
 	struct msm_vidc_core *core;
@@ -2002,7 +2056,7 @@ bool msm_vidc_allow_decode_batch(struct msm_vidc_inst *inst)
 
 	if (!inst || !inst->core) {
 		d_vpr_e("%s: invalid params\n", __func__);
-		return -EINVAL;
+		return false;
 	}
 	core = inst->core;
 
@@ -2055,7 +2109,7 @@ bool msm_vidc_allow_decode_batch(struct msm_vidc_inst *inst)
 	}
 
 exit:
-	i_vpr_h(inst, "%s: batching %s\n", __func__, allow ? "enabled" : "disabled");
+	i_vpr_h(inst, "%s: batching: %s\n", __func__, allow ? "enabled" : "disabled");
 
 	return allow;
 }
@@ -2203,9 +2257,10 @@ int msm_vidc_queue_buffer_single(struct msm_vidc_inst *inst, struct vb2_buffer *
 			inst->capabilities->cap[ENC_IP_CR].value = 0;
 		}
 		inst->power.buffer_counter++;
-		msm_vidc_scale_power(inst, true);
 	}
 
+	msm_vidc_scale_power(inst, is_input_buffer(buf->type));
+
 	rc = msm_vidc_queue_buffer(inst, buf);
 	if (rc)
 		return rc;

+ 37 - 36
driver/vidc/src/msm_vidc_power.c

@@ -227,7 +227,7 @@ int msm_vidc_scale_buses(struct msm_vidc_inst *inst)
 		return 0;
 
 	vote_data->power_mode = VIDC_POWER_NORMAL;
-	if (inst->power.buffer_counter < DCVS_FTB_WINDOW || is_image_session(inst))
+	if (inst->power.buffer_counter < DCVS_WINDOW || is_image_session(inst))
 		vote_data->power_mode = VIDC_POWER_TURBO;
 	if (msm_vidc_clock_voting)
 		vote_data->power_mode = VIDC_POWER_TURBO;
@@ -422,17 +422,15 @@ static int msm_vidc_apply_dcvs(struct msm_vidc_inst *inst)
 	int bufs_with_fw = 0;
 	struct msm_vidc_power *power;
 
-	if (!inst || !inst->core) {
+	if (!inst) {
 		d_vpr_e("%s: invalid params %pK\n", __func__, inst);
 		return -EINVAL;
 	}
 
-	if (!inst->power.dcvs_mode || inst->decode_batch.enable || is_image_session(inst)) {
-		i_vpr_l(inst, "Skip DCVS (dcvs %d, batching %d)\n",
-			inst->power.dcvs_mode, inst->decode_batch.enable);
-		inst->power.dcvs_flags = 0;
+	/* skip dcvs */
+	if (!inst->power.dcvs_mode)
 		return 0;
-	}
+
 	power = &inst->power;
 
 	if (is_decode_session(inst)) {
@@ -458,22 +456,36 @@ static int msm_vidc_apply_dcvs(struct msm_vidc_inst *inst)
 	 *    FW is slow and will impact pipeline, Increase clock.
 	 * 2) When pending buffers with FW are less than FW requested,
 	 *    pipeline has cushion to absorb FW slowness, Decrease clocks.
-	 * 3) When DCVS has engaged(Inc or Dec) and pending buffers with FW
-	 *    transitions past the nom_threshold, switch to calculated load.
-	 *    This smoothens the clock transitions.
+	 * 3) When DCVS has engaged(Inc or Dec):
+	 *    For decode:
+	 *        - Pending buffers with FW transitions past the nom_threshold,
+	 *        switch to calculated load, this smoothens the clock transitions.
+	 *    For encode:
+	 *        - Always switch to calculated load.
 	 * 4) Otherwise maintain previous Load config.
 	 */
 	if (bufs_with_fw >= power->max_threshold) {
 		power->dcvs_flags = MSM_VIDC_DCVS_INCR;
+		goto exit;
 	} else if (bufs_with_fw < power->min_threshold) {
 		power->dcvs_flags = MSM_VIDC_DCVS_DECR;
-	} else if ((power->dcvs_flags & MSM_VIDC_DCVS_DECR &&
-			   bufs_with_fw >= power->nom_threshold) ||
-			   (power->dcvs_flags & MSM_VIDC_DCVS_INCR &&
-			   bufs_with_fw <= power->nom_threshold))
+		goto exit;
+	}
+
+	/* encoder: dcvs window handling */
+	if (is_encode_session(inst)) {
 		power->dcvs_flags = 0;
+		goto exit;
+	}
 
-	i_vpr_p(inst, "DCVS: bufs_with_fw %d th[%d %d %d] flags %#x\n",
+	/* decoder: dcvs window handling */
+	if ((power->dcvs_flags & MSM_VIDC_DCVS_DECR && bufs_with_fw >= power->nom_threshold) ||
+		(power->dcvs_flags & MSM_VIDC_DCVS_INCR && bufs_with_fw <= power->nom_threshold)) {
+		power->dcvs_flags = 0;
+	}
+
+exit:
+	i_vpr_p(inst, "dcvs: bufs_with_fw %d th[%d %d %d] flags %#x\n",
 		bufs_with_fw, power->min_threshold,
 		power->nom_threshold, power->max_threshold,
 		power->dcvs_flags);
@@ -498,8 +510,7 @@ int msm_vidc_scale_clocks(struct msm_vidc_inst *inst)
 	if (!data_size)
 		return 0;
 
-	//todo: add turbo session check
-	if (inst->power.buffer_counter < DCVS_FTB_WINDOW || is_image_session(inst)) {
+	if (inst->power.buffer_counter < DCVS_WINDOW || is_image_session(inst)) {
 		inst->power.min_freq = msm_vidc_max_freq(inst);
 		inst->power.dcvs_flags = 0;
 	} else if (msm_vidc_clock_voting) {
@@ -524,7 +535,6 @@ int msm_vidc_scale_power(struct msm_vidc_inst *inst, bool scale_buses)
 		d_vpr_e("%s: invalid params %pK\n", __func__, inst);
 		return -EINVAL;
 	}
-
 	core = inst->core;
 
 	if (!inst->active) {
@@ -553,7 +563,7 @@ int msm_vidc_scale_power(struct msm_vidc_inst *inst, bool scale_buses)
 void msm_vidc_dcvs_data_reset(struct msm_vidc_inst *inst)
 {
 	struct msm_vidc_power *dcvs;
-	u32 min_count, actual_count;
+	u32 min_count, actual_count, max_count;
 
 	if (!inst) {
 		d_vpr_e("%s: invalid params\n", __func__);
@@ -561,12 +571,14 @@ void msm_vidc_dcvs_data_reset(struct msm_vidc_inst *inst)
 	}
 
 	dcvs = &inst->power;
-	if (inst->domain == MSM_VIDC_ENCODER) {
+	if (is_encode_session(inst)) {
 		min_count = inst->buffers.input.min_count;
 		actual_count = inst->buffers.input.actual_count;
-	} else if (inst->domain == MSM_VIDC_DECODER) {
+		max_count = min((min_count + DCVS_ENC_EXTRA_INPUT_BUFFERS), actual_count);
+	} else if (is_decode_session(inst)) {
 		min_count = inst->buffers.output.min_count;
 		actual_count = inst->buffers.output.actual_count;
+		max_count = min((min_count + DCVS_DEC_EXTRA_OUTPUT_BUFFERS), actual_count);
 	} else {
 		i_vpr_e(inst, "%s: invalid domain type %d\n",
 			__func__, inst->domain);
@@ -574,23 +586,12 @@ void msm_vidc_dcvs_data_reset(struct msm_vidc_inst *inst)
 	}
 
 	dcvs->min_threshold = min_count;
-	if (inst->domain == MSM_VIDC_ENCODER)
-		dcvs->max_threshold = min((min_count + DCVS_ENC_EXTRA_INPUT_BUFFERS),
-								  actual_count);
-	else
-		dcvs->max_threshold = min((min_count + DCVS_DEC_EXTRA_OUTPUT_BUFFERS),
-								  actual_count);
-
-	dcvs->dcvs_window =
-		dcvs->max_threshold < dcvs->min_threshold ? 0 :
-		dcvs->max_threshold - dcvs->min_threshold;
-	dcvs->nom_threshold = dcvs->min_threshold +
-		(dcvs->dcvs_window ?
-		(dcvs->dcvs_window / 2) : 0);
-
+	dcvs->max_threshold = max_count;
+	dcvs->dcvs_window = min_count < max_count ? max_count - min_count : 0;
+	dcvs->nom_threshold = dcvs->min_threshold + (dcvs->dcvs_window / 2);
 	dcvs->dcvs_flags = 0;
 
-	i_vpr_p(inst, "%s: DCVS: thresholds [%d %d %d] flags %#x\n",
+	i_vpr_p(inst, "%s: dcvs: thresholds [%d %d %d] flags %#x\n",
 		__func__, dcvs->min_threshold,
 		dcvs->nom_threshold, dcvs->max_threshold,
 		dcvs->dcvs_flags);

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

@@ -8,6 +8,7 @@
 #include "msm_vidc_inst.h"
 #include "msm_vidc_internal.h"
 #include "msm_vidc_driver.h"
+#include "msm_vidc_power.h"
 #include "msm_vdec.h"
 #include "msm_venc.h"
 #include "msm_vidc_debug.h"
@@ -204,6 +205,12 @@ int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count)
 		}
 	}
 
+	if (is_decode_session(inst))
+		inst->decode_batch.enable = msm_vidc_allow_decode_batch(inst);
+
+	msm_vidc_allow_dcvs(inst);
+	msm_vidc_power_data_reset(inst);
+
 	if (q->type == INPUT_MPLANE) {
 		if (is_decode_session(inst))
 			rc = msm_vdec_streamon_input(inst);
@@ -222,9 +229,9 @@ int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count)
 		i_vpr_e(inst, "%s: invalid type %d\n", q->type);
 		goto error;
 	}
-
 	if (!rc)
 		i_vpr_h(inst, "Streamon: %d successful\n", q->type);
+
 	return rc;
 
 error: