video: driver: Add support to enable enc ring buffer

Add support to enable ring buffer for enc intermediate
bin buffer to improve encoding performance.

Change-Id: Ifbf50cb48278c62c09a20bc7626a3b6288813830
Signed-off-by: Akshata Sahukar <quic_asahukar@quicinc.com>
This commit is contained in:
Akshata Sahukar
2023-03-02 17:44:47 -08:00
committed by Gerrit - the friendly Code Review server
parent fb2e2c5715
commit 9a5fea8ef3
9 changed files with 282 additions and 8 deletions

View File

@@ -12,6 +12,7 @@
#define ENABLE_LEGACY_POWER_CALCULATIONS 1
int msm_vidc_ring_buf_count_iris33(struct msm_vidc_inst *inst, u32 data_size);
u64 msm_vidc_calc_freq_iris33(struct msm_vidc_inst* inst, u32 data_size);
int msm_vidc_calc_bw_iris33(struct msm_vidc_inst* inst,
struct vidc_bus_vote_data* vote_data);

View File

@@ -338,7 +338,7 @@ static u32 msm_vidc_encoder_bin_size_iris33(struct msm_vidc_inst *inst)
{
struct msm_vidc_core *core;
u32 size = 0;
u32 width, height, num_vpp_pipes, stage, profile;
u32 width, height, num_vpp_pipes, stage, profile, ring_buf_count;
struct v4l2_format *f;
if (!inst || !inst->core || !inst->capabilities) {
@@ -356,13 +356,14 @@ static u32 msm_vidc_encoder_bin_size_iris33(struct msm_vidc_inst *inst)
width = f->fmt.pix_mp.width;
height = f->fmt.pix_mp.height;
profile = inst->capabilities->cap[PROFILE].value;
ring_buf_count = inst->capabilities->cap[ENC_RING_BUFFER_COUNT].value;
if (inst->codec == MSM_VIDC_H264)
HFI_BUFFER_BIN_H264E(size, inst->hfi_rc_type, width,
height, stage, num_vpp_pipes, profile);
height, stage, num_vpp_pipes, profile, ring_buf_count);
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
HFI_BUFFER_BIN_H265E(size, inst->hfi_rc_type, width,
height, stage, num_vpp_pipes, profile);
height, stage, num_vpp_pipes, profile, ring_buf_count);
i_vpr_l(inst, "%s: size %d\n", __func__, size);
return size;

View File

@@ -1231,6 +1231,7 @@ static struct msm_vidc_session_ops msm_session_ops = {
.buffer_size = msm_buffer_size_iris33,
.min_count = msm_buffer_min_count_iris33,
.extra_count = msm_buffer_extra_count_iris33,
.ring_buf_count = msm_vidc_ring_buf_count_iris33,
.calc_freq = msm_vidc_calc_freq_iris33,
.calc_bw = msm_vidc_calc_bw_iris33,
.decide_work_route = msm_vidc_decide_work_route_iris33,

View File

@@ -12,6 +12,8 @@
#include "perf_static_model.h"
#include "msm_vidc_power.h"
#define VPP_MIN_FREQ_MARGIN_PERCENT 5 /* to be tuned */
static u64 __calculate_decoder(struct vidc_bus_vote_data *d);
static u64 __calculate_encoder(struct vidc_bus_vote_data *d);
static u64 __calculate(struct msm_vidc_inst* inst, struct vidc_bus_vote_data *d);
@@ -284,6 +286,49 @@ static int msm_vidc_init_codec_input_bus(struct msm_vidc_inst *inst, struct vidc
return 0;
}
static bool is_vpp_cycles_close_to_freq_corner(struct msm_vidc_core *core,
u64 vpp_min_freq)
{
u64 margin_freq = 0;
u64 closest_freq_upper_corner = 0;
u32 margin_percent = 0;
int i = 0;
if (!core || !core->resource || !core->resource->freq_set.freq_tbl ||
!core->resource->freq_set.count) {
d_vpr_e("%s: invalid params\n", __func__);
return false;
}
vpp_min_freq = vpp_min_freq * 1000000; /* convert to hz */
closest_freq_upper_corner =
core->resource->freq_set.freq_tbl[0].freq;
if (vpp_min_freq > closest_freq_upper_corner)
return false;
/* get the closest freq corner for vpp_min_freq */
for (i = 0; i < core->resource->freq_set.count; i++) {
if (vpp_min_freq <=
core->resource->freq_set.freq_tbl[i].freq) {
closest_freq_upper_corner =
core->resource->freq_set.freq_tbl[i].freq;
} else {
break;
}
}
margin_freq = closest_freq_upper_corner - vpp_min_freq;
margin_percent = div_u64((margin_freq * 100), closest_freq_upper_corner);
/* check if margin is less than cutoff */
if (margin_percent < VPP_MIN_FREQ_MARGIN_PERCENT)
return true;
return false;
}
static u64 msm_vidc_calc_freq_iris33_new(struct msm_vidc_inst *inst, u32 data_size)
{
u64 freq = 0;
@@ -311,6 +356,25 @@ static u64 msm_vidc_calc_freq_iris33_new(struct msm_vidc_inst *inst, u32 data_si
ret = msm_vidc_calculate_frequency(codec_input, &codec_output);
if (ret)
return freq;
if (inst->domain == MSM_VIDC_ENCODER) {
if (!inst->capabilities->cap[ENC_RING_BUFFER_COUNT].value &&
is_vpp_cycles_close_to_freq_corner(core,
codec_output.vpp_min_freq)) {
/*
* if ring buffer not enabled and required vpp cycles
* is too close to the frequency corner then increase
* the vpp cycles by VPP_MIN_FREQ_MARGIN_PERCENT
*/
codec_output.vpp_min_freq += div_u64(
codec_output.vpp_min_freq *
VPP_MIN_FREQ_MARGIN_PERCENT, 100);
codec_output.hw_min_freq = max(
codec_output.hw_min_freq,
codec_output.vpp_min_freq);
}
}
freq = codec_output.hw_min_freq * 1000000; /* Convert to Hz */
i_vpr_p(inst, "%s: filled len %d, required freq %llu, fps %u, mbpf %u\n",
@@ -1173,4 +1237,47 @@ int msm_vidc_calc_bw_iris33(struct msm_vidc_inst *inst,
value = msm_vidc_calc_bw_iris33_new(inst, vidc_data);
return value;
}
}
int msm_vidc_ring_buf_count_iris33(struct msm_vidc_inst *inst, u32 data_size)
{
int rc = 0;
struct msm_vidc_core *core;
struct api_calculation_input codec_input;
struct api_calculation_freq_output codec_output;
if (!inst || !inst->core || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
core = inst->core;
if (!core->resource || !core->resource->freq_set.freq_tbl ||
!core->resource->freq_set.count) {
i_vpr_e(inst, "%s: invalid frequency table\n", __func__);
return -EINVAL;
}
if (ENABLE_LEGACY_POWER_CALCULATIONS)
return 0;
memset(&codec_input, 0, sizeof(struct api_calculation_input));
memset(&codec_output, 0, sizeof(struct api_calculation_freq_output));
rc = msm_vidc_init_codec_input_freq(inst, data_size, &codec_input);
if (rc)
return rc;
rc = msm_vidc_calculate_frequency(codec_input, &codec_output);
if (rc)
return rc;
/* check if vpp_min_freq is exceeding closest freq corner margin */
if (is_vpp_cycles_close_to_freq_corner(core,
codec_output.vpp_min_freq))
/* enables ring buffer */
inst->capabilities->cap[ENC_RING_BUFFER_COUNT].value =
MAX_ENC_RING_BUF_COUNT;
else
inst->capabilities->cap[ENC_RING_BUFFER_COUNT].value = 0;
return 0;
}