On Wed Apr 1 19:19:29 2026 +0530, Vishnu Reddy wrote:
> The driver was using a fixed default FPS value when calculating the VPU
> frequency. This caused wrong frequency requests for highâframeârate
> streams, for example 4K at 240 FPS. Because of this, the hardware was
> running at a lower frequency than needed.
>
> Add the FPS measurement based on the decoder input buffer arrival rate.
> The measured FPS is stored per instance and used in frequency calculation
> instead of the fixed default FPS. The value is clamped so that it does
> not exceed platform limits. Add a VPP firmware overhead when running in
> STAGE_2.
>
> Reviewed-by: Vikash Garodia <[email protected]>
> Signed-off-by: Vishnu Reddy <[email protected]>
> Signed-off-by: Bryan O'Donoghue <[email protected]>
Patch committed.
Thanks,
Bryan O'Donoghue
drivers/media/platform/qcom/iris/iris_instance.h | 4 ++++
drivers/media/platform/qcom/iris/iris_vdec.c | 20 ++++++++++++++++++++
drivers/media/platform/qcom/iris/iris_vpu2.c | 2 +-
drivers/media/platform/qcom/iris/iris_vpu_common.c | 6 +++++-
4 files changed, 30 insertions(+), 2 deletions(-)
---
diff --git a/drivers/media/platform/qcom/iris/iris_instance.h
b/drivers/media/platform/qcom/iris/iris_instance.h
index 0041b0cc4001..1d8a22ea4809 100644
--- a/drivers/media/platform/qcom/iris/iris_instance.h
+++ b/drivers/media/platform/qcom/iris/iris_instance.h
@@ -70,6 +70,8 @@ struct iris_fmt {
* @metadata_idx: index for metadata buffer
* @codec: codec type
* @last_buffer_dequeued: a flag to indicate that last buffer is sent by driver
+ * @last_buf_ns: start time of received input buffer for current one second
FPS window
+ * @frame_counter: input buffer counter for current one second FPS window
* @frame_rate: frame rate of current instance
* @operating_rate: operating rate of current instance
* @hfi_rc_type: rate control type
@@ -115,6 +117,8 @@ struct iris_inst {
u32 metadata_idx;
u32 codec;
bool last_buffer_dequeued;
+ u64 last_buf_ns;
+ u32 frame_counter;
u32 frame_rate;
u32 operating_rate;
u32 hfi_rc_type;
diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c
b/drivers/media/platform/qcom/iris/iris_vdec.c
index ccda3b9fb845..1d34c7bcf8f8 100644
--- a/drivers/media/platform/qcom/iris/iris_vdec.c
+++ b/drivers/media/platform/qcom/iris/iris_vdec.c
@@ -54,6 +54,7 @@ int iris_vdec_inst_init(struct iris_inst *inst)
f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;
inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst,
BUF_OUTPUT);
inst->buffers[BUF_OUTPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage;
+ inst->frame_rate = MAXIMUM_FPS;
memcpy(&inst->fw_caps[0], &core->inst_fw_caps_dec[0],
INST_FW_CAP_MAX * sizeof(struct platform_inst_fw_cap));
@@ -369,6 +370,8 @@ int iris_vdec_streamon_input(struct iris_inst *inst)
if (ret)
return ret;
+ inst->frame_counter = 0;
+
return iris_process_streamon_input(inst);
}
@@ -411,6 +414,7 @@ int iris_vdec_qbuf(struct iris_inst *inst, struct
vb2_v4l2_buffer *vbuf)
{
struct iris_buffer *buf = to_iris_buffer(vbuf);
struct vb2_buffer *vb2 = &vbuf->vb2_buf;
+ u64 cur_buf_ns, delta_ns;
struct vb2_queue *q;
int ret;
@@ -427,6 +431,22 @@ int iris_vdec_qbuf(struct iris_inst *inst, struct
vb2_v4l2_buffer *vbuf)
return 0;
}
+ if (buf->type == BUF_INPUT) {
+ cur_buf_ns = ktime_get_ns();
+
+ if (!inst->frame_counter)
+ inst->last_buf_ns = cur_buf_ns;
+
+ inst->frame_counter++;
+ delta_ns = cur_buf_ns - inst->last_buf_ns;
+
+ if (delta_ns >= NSEC_PER_SEC) {
+ inst->frame_rate = clamp_t(u32, inst->frame_counter,
DEFAULT_FPS,
+ MAXIMUM_FPS);
+ inst->frame_counter = 0;
+ }
+ }
+
iris_scale_power(inst);
return iris_queue_buffer(inst, buf);
diff --git a/drivers/media/platform/qcom/iris/iris_vpu2.c
b/drivers/media/platform/qcom/iris/iris_vpu2.c
index 9c103a2e4e4e..73c201f4f338 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu2.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu2.c
@@ -18,7 +18,7 @@ static u64 iris_vpu2_calc_freq(struct iris_inst *inst, size_t
data_size)
struct v4l2_format *inp_f = inst->fmt_src;
u32 mbs_per_second, mbpf, height, width;
unsigned long vpp_freq, vsp_freq;
- u32 fps = DEFAULT_FPS;
+ u32 fps = inst->frame_rate;
width = max(inp_f->fmt.pix_mp.width, inst->crop.width);
height = max(inp_f->fmt.pix_mp.height, inst->crop.height);
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c
b/drivers/media/platform/qcom/iris/iris_vpu_common.c
index c6cfc1d9fd9e..3872c4f37987 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_common.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c
@@ -416,7 +416,7 @@ u64 iris_vpu3x_vpu4x_calculate_frequency(struct iris_inst
*inst, size_t data_siz
u32 height, width, mbs_per_second, mbpf;
u64 fw_cycles, fw_vpp_cycles;
u64 vsp_cycles, vpp_cycles;
- u32 fps = DEFAULT_FPS;
+ u32 fps = inst->frame_rate;
width = max(inp_f->fmt.pix_mp.width, inst->crop.width);
height = max(inp_f->fmt.pix_mp.height, inst->crop.height);
@@ -435,6 +435,10 @@ u64 iris_vpu3x_vpu4x_calculate_frequency(struct iris_inst
*inst, size_t data_siz
if (inst->fw_caps[PIPE].value > 1)
vpp_cycles += div_u64(vpp_cycles * 59, 1000);
+ /* 1.05 is VPP FW overhead */
+ if (inst->fw_caps[STAGE].value == STAGE_2)
+ vpp_cycles += mult_frac(vpp_cycles, 5, 100);
+
vsp_cycles = fps * data_size * 8;
vsp_cycles = div_u64(vsp_cycles, 2);
/* VSP FW overhead 1.05 */
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]