From: Neil Armstrong Date: Tue, 2 Sep 2025 08:43:49 +0000 (+0200) Subject: media: iris: add VPU33 specific encoding buffer calculation X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a5925a2ce0775374dcbbaf19826b539c2e9eec84;p=thirdparty%2Fkernel%2Fstable.git media: iris: add VPU33 specific encoding buffer calculation The VPU33 found in the SM8650 Platform requires some slighly different buffer calculation for encoding to allow working with the latest firwware uploaded on linux-firmware at [1]. [1] https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/commit/?id=ece445af91bbee49bf0d8b23c2b99b596ae6eac7 Suggested-by: Vikash Garodia Signed-off-by: Neil Armstrong Reviewed-by: Vikash Garodia Signed-off-by: Bryan O'Donoghue Signed-off-by: Hans Verkuil --- diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c index 8891a297d384..c0900038e7de 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_buffer.c @@ -284,7 +284,7 @@ static void iris_fill_internal_buf_info(struct iris_inst *inst, { struct iris_buffers *buffers = &inst->buffers[buffer_type]; - buffers->size = iris_vpu_buf_size(inst, buffer_type); + buffers->size = inst->core->iris_platform_data->get_vpu_buffer_size(inst, buffer_type); buffers->min_count = iris_vpu_buf_count(inst, buffer_type); } diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c index 29cf392ca256..e1788c266bb1 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c @@ -911,7 +911,7 @@ static int iris_hfi_gen1_set_bufsize(struct iris_inst *inst, u32 plane) if (iris_split_mode_enabled(inst)) { bufsz.type = HFI_BUFFER_OUTPUT; - bufsz.size = iris_vpu_buf_size(inst, BUF_DPB); + bufsz.size = inst->core->iris_platform_data->get_vpu_buffer_size(inst, BUF_DPB); ret = hfi_gen1_set_property(inst, ptype, &bufsz, sizeof(bufsz)); if (ret) diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 7fbbea38c78a..58d05e0a112e 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -7,6 +7,7 @@ #define __IRIS_PLATFORM_COMMON_H__ #include +#include "iris_buffer.h" struct iris_core; struct iris_inst; @@ -193,6 +194,7 @@ struct iris_platform_data { void (*init_hfi_command_ops)(struct iris_core *core); void (*init_hfi_response_ops)(struct iris_core *core); struct iris_inst *(*get_instance)(void); + u32 (*get_vpu_buffer_size)(struct iris_inst *inst, enum iris_buffer_type buffer_type); const struct vpu_ops *vpu_ops; void (*set_preset_registers)(struct iris_core *core); const struct icc_info *icc_tbl; diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c index d8c167c6f62c..36d69cc73986 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c +++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c @@ -9,6 +9,7 @@ #include "iris_hfi_gen2.h" #include "iris_hfi_gen2_defines.h" #include "iris_platform_common.h" +#include "iris_vpu_buffer.h" #include "iris_vpu_common.h" #include "iris_platform_qcs8300.h" @@ -740,6 +741,7 @@ struct iris_platform_data sm8550_data = { .get_instance = iris_hfi_gen2_get_instance, .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, .init_hfi_response_ops = iris_hfi_gen2_response_ops_init, + .get_vpu_buffer_size = iris_vpu_buf_size, .vpu_ops = &iris_vpu3_ops, .set_preset_registers = iris_set_sm8550_preset_registers, .icc_tbl = sm8550_icc_table, @@ -829,6 +831,7 @@ struct iris_platform_data sm8650_data = { .get_instance = iris_hfi_gen2_get_instance, .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, .init_hfi_response_ops = iris_hfi_gen2_response_ops_init, + .get_vpu_buffer_size = iris_vpu33_buf_size, .vpu_ops = &iris_vpu33_ops, .set_preset_registers = iris_set_sm8550_preset_registers, .icc_tbl = sm8550_icc_table, @@ -999,6 +1002,7 @@ struct iris_platform_data qcs8300_data = { .get_instance = iris_hfi_gen2_get_instance, .init_hfi_command_ops = iris_hfi_gen2_command_ops_init, .init_hfi_response_ops = iris_hfi_gen2_response_ops_init, + .get_vpu_buffer_size = iris_vpu_buf_size, .vpu_ops = &iris_vpu3_ops, .set_preset_registers = iris_set_sm8550_preset_registers, .icc_tbl = sm8550_icc_table, diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c index 978d0130d43b..16486284f8ac 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c @@ -9,6 +9,7 @@ #include "iris_resources.h" #include "iris_hfi_gen1.h" #include "iris_hfi_gen1_defines.h" +#include "iris_vpu_buffer.h" #include "iris_vpu_common.h" #define BITRATE_MIN 32000 @@ -317,6 +318,7 @@ struct iris_platform_data sm8250_data = { .get_instance = iris_hfi_gen1_get_instance, .init_hfi_command_ops = &iris_hfi_gen1_command_ops_init, .init_hfi_response_ops = iris_hfi_gen1_response_ops_init, + .get_vpu_buffer_size = iris_vpu_buf_size, .vpu_ops = &iris_vpu2_ops, .set_preset_registers = iris_set_sm8250_preset_registers, .icc_tbl = sm8250_icc_table, diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c index 570b6415dff9..4463be05ce16 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c @@ -844,6 +844,27 @@ u32 size_vpss_line_buf(u32 num_vpp_pipes_enc, u32 frame_height_coded, (((((max_t(u32, (frame_width_coded), (frame_height_coded)) + 3) >> 2) << 5) + 256) * 16)), 256); } +static inline +u32 size_vpss_line_buf_vpu33(u32 num_vpp_pipes_enc, u32 frame_height_coded, + u32 frame_width_coded) +{ + u32 vpss_4tap_top, vpss_4tap_left, vpss_div2_top; + u32 vpss_div2_left, vpss_top_lb, vpss_left_lb; + u32 size_left, size_top; + u32 max_width_height; + + max_width_height = max_t(u32, frame_width_coded, frame_height_coded); + vpss_4tap_top = ((((max_width_height * 2) + 3) >> 2) << 4) + 256; + vpss_4tap_left = (((8192 + 3) >> 2) << 5) + 64; + vpss_div2_top = (((max_width_height + 3) >> 2) << 4) + 256; + vpss_div2_left = ((((max_width_height * 2) + 3) >> 2) << 5) + 64; + vpss_top_lb = (frame_width_coded + 1) << 3; + vpss_left_lb = (frame_height_coded << 3) * num_vpp_pipes_enc; + size_left = (vpss_4tap_left + vpss_div2_left) * 2 * num_vpp_pipes_enc; + size_top = (vpss_4tap_top + vpss_div2_top) * 2; + + return ALIGN(size_left + size_top + vpss_top_lb + vpss_left_lb, DMA_ALIGNMENT); +} static inline u32 size_top_line_buf_first_stg_sao(u32 frame_width_coded) @@ -954,8 +975,8 @@ static u32 iris_vpu_enc_non_comv_size(struct iris_inst *inst) } static inline -u32 hfi_buffer_line_enc(u32 frame_width, u32 frame_height, bool is_ten_bit, - u32 num_vpp_pipes_enc, u32 lcu_size, u32 standard) +u32 hfi_buffer_line_enc_base(u32 frame_width, u32 frame_height, bool is_ten_bit, + u32 num_vpp_pipes_enc, u32 lcu_size, u32 standard) { u32 width_in_lcus = ((frame_width) + (lcu_size) - 1) / (lcu_size); u32 height_in_lcus = ((frame_height) + (lcu_size) - 1) / (lcu_size); @@ -995,10 +1016,38 @@ u32 hfi_buffer_line_enc(u32 frame_width, u32 frame_height, bool is_ten_bit, line_buff_recon_pix_size + size_left_linebuff_ctrl_fe(frame_height_coded, num_vpp_pipes_enc) + size_line_buf_sde(frame_width_coded) + - size_vpss_line_buf(num_vpp_pipes_enc, frame_height_coded, frame_width_coded) + size_top_line_buf_first_stg_sao(frame_width_coded); } +static inline +u32 hfi_buffer_line_enc(u32 frame_width, u32 frame_height, bool is_ten_bit, + u32 num_vpp_pipes_enc, u32 lcu_size, u32 standard) +{ + u32 width_in_lcus = ((frame_width) + (lcu_size) - 1) / (lcu_size); + u32 height_in_lcus = ((frame_height) + (lcu_size) - 1) / (lcu_size); + u32 frame_height_coded = height_in_lcus * (lcu_size); + u32 frame_width_coded = width_in_lcus * (lcu_size); + + return hfi_buffer_line_enc_base(frame_width, frame_height, is_ten_bit, + num_vpp_pipes_enc, lcu_size, standard) + + size_vpss_line_buf(num_vpp_pipes_enc, frame_height_coded, frame_width_coded); +} + +static inline +u32 hfi_buffer_line_enc_vpu33(u32 frame_width, u32 frame_height, bool is_ten_bit, + u32 num_vpp_pipes_enc, u32 lcu_size, u32 standard) +{ + u32 width_in_lcus = ((frame_width) + (lcu_size) - 1) / (lcu_size); + u32 height_in_lcus = ((frame_height) + (lcu_size) - 1) / (lcu_size); + u32 frame_height_coded = height_in_lcus * (lcu_size); + u32 frame_width_coded = width_in_lcus * (lcu_size); + + return hfi_buffer_line_enc_base(frame_width, frame_height, is_ten_bit, + num_vpp_pipes_enc, lcu_size, standard) + + size_vpss_line_buf_vpu33(num_vpp_pipes_enc, frame_height_coded, + frame_width_coded); +} + static u32 iris_vpu_enc_line_size(struct iris_inst *inst) { u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; @@ -1017,6 +1066,24 @@ static u32 iris_vpu_enc_line_size(struct iris_inst *inst) lcu_size, HFI_CODEC_ENCODE_AVC); } +static u32 iris_vpu33_enc_line_size(struct iris_inst *inst) +{ + u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe; + struct v4l2_format *f = inst->fmt_dst; + u32 height = f->fmt.pix_mp.height; + u32 width = f->fmt.pix_mp.width; + u32 lcu_size = 16; + + if (inst->codec == V4L2_PIX_FMT_HEVC) { + lcu_size = 32; + return hfi_buffer_line_enc_vpu33(width, height, 0, num_vpp_pipes, + lcu_size, HFI_CODEC_ENCODE_HEVC); + } + + return hfi_buffer_line_enc_vpu33(width, height, 0, num_vpp_pipes, + lcu_size, HFI_CODEC_ENCODE_AVC); +} + static inline u32 hfi_buffer_dpb_enc(u32 frame_width, u32 frame_height, bool is_ten_bit) { @@ -1364,7 +1431,7 @@ struct iris_vpu_buf_type_handle { u32 (*handle)(struct iris_inst *inst); }; -int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) +u32 iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) { const struct iris_vpu_buf_type_handle *buf_type_handle_arr = NULL; u32 size = 0, buf_type_handle_size = 0, i; @@ -1408,6 +1475,34 @@ int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) return size; } +u32 iris_vpu33_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type) +{ + u32 size = 0, i; + + static const struct iris_vpu_buf_type_handle enc_internal_buf_type_handle[] = { + {BUF_BIN, iris_vpu_enc_bin_size }, + {BUF_COMV, iris_vpu_enc_comv_size }, + {BUF_NON_COMV, iris_vpu_enc_non_comv_size }, + {BUF_LINE, iris_vpu33_enc_line_size }, + {BUF_ARP, iris_vpu_enc_arp_size }, + {BUF_VPSS, iris_vpu_enc_vpss_size }, + {BUF_SCRATCH_1, iris_vpu_enc_scratch1_size }, + {BUF_SCRATCH_2, iris_vpu_enc_scratch2_size }, + }; + + if (inst->domain == DECODER) + return iris_vpu_buf_size(inst, buffer_type); + + for (i = 0; i < ARRAY_SIZE(enc_internal_buf_type_handle); i++) { + if (enc_internal_buf_type_handle[i].type == buffer_type) { + size = enc_internal_buf_type_handle[i].handle(inst); + break; + } + } + + return size; +} + static u32 internal_buffer_count(struct iris_inst *inst, enum iris_buffer_type buffer_type) { diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h index 94668c5b3d15..04f0b7400a1e 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h @@ -146,7 +146,8 @@ static inline u32 size_h264d_qp(u32 frame_width, u32 frame_height) return DIV_ROUND_UP(frame_width, 64) * DIV_ROUND_UP(frame_height, 64) * 128; } -int iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); +u32 iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); +u32 iris_vpu33_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type); int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type); #endif