From: Dikshita Agarwal Date: Mon, 25 Aug 2025 07:00:40 +0000 (+0530) Subject: media: iris: Add support for ENUM_FRAMESIZES/FRAMEINTERVALS for encoder X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a6882431a138ac352a6e20ec3b85f97f84501329;p=thirdparty%2Fkernel%2Fstable.git media: iris: Add support for ENUM_FRAMESIZES/FRAMEINTERVALS for encoder Add support for frame size and frame interval enumeration by implementing ENUM_FRAMESIZES/FRAMEINTERVALS V4L2 ioctls for encoder video device with necessary hooks. This allows userspace application to query encoder capabilities and adapt encoding configurations accordingly. Tested-by: Vikash Garodia # X1E80100 Reviewed-by: Vikash Garodia Tested-by: Neil Armstrong # on SM8550-HDK Tested-by: Neil Armstrong # on SM8650-HDK Signed-off-by: Dikshita Agarwal Tested-by: Bryan O'Donoghue # x1e80100-crd Signed-off-by: Bryan O'Donoghue Signed-off-by: Hans Verkuil --- diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index fd5a6e69e01c..b555542c870f 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -21,7 +21,8 @@ struct iris_inst; #define DEFAULT_MAX_HOST_BUF_COUNT 64 #define DEFAULT_MAX_HOST_BURST_BUF_COUNT 256 #define DEFAULT_FPS 30 -#define NUM_MBS_8K ((8192 * 4352) / 256) +#define MAXIMUM_FPS 480 +#define NUM_MBS_8K ((8192 * 4352) / 256) enum stage_type { STAGE_1 = 1, @@ -183,6 +184,8 @@ struct iris_platform_data { u32 max_session_count; /* max number of macroblocks per frame supported */ u32 max_core_mbpf; + /* max number of macroblocks per second supported */ + u32 max_core_mbps; const u32 *input_config_params_default; unsigned int input_config_params_default_size; const u32 *input_config_params_hevc; diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c index c7c384fce233..39c46c8b972f 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c +++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c @@ -356,6 +356,7 @@ struct iris_platform_data sm8550_data = { .num_vpp_pipe = 4, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K * 2, + .max_core_mbps = ((7680 * 4320) / 256) * 60, .input_config_params_default = sm8550_vdec_input_config_params_default, .input_config_params_default_size = @@ -431,6 +432,7 @@ struct iris_platform_data sm8650_data = { .num_vpp_pipe = 4, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K * 2, + .max_core_mbps = ((7680 * 4320) / 256) * 60, .input_config_params_default = sm8550_vdec_input_config_params_default, .input_config_params_default_size = @@ -568,6 +570,7 @@ struct iris_platform_data qcs8300_data = { .num_vpp_pipe = 2, .max_session_count = 16, .max_core_mbpf = ((4096 * 2176) / 256) * 4, + .max_core_mbps = (((3840 * 2176) / 256) * 120), .input_config_params_default = sm8550_vdec_input_config_params_default, .input_config_params_default_size = diff --git a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c index 8d0816a67ae0..2a3cbe1f2d4b 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_sm8250.c +++ b/drivers/media/platform/qcom/iris/iris_platform_sm8250.c @@ -128,6 +128,7 @@ struct iris_platform_data sm8250_data = { .num_vpp_pipe = 4, .max_session_count = 16, .max_core_mbpf = NUM_MBS_8K, + .max_core_mbps = ((7680 * 4320) / 256) * 60, .input_config_params_default = sm8250_vdec_input_config_param_default, .input_config_params_default_size = diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c index b4ad5df62bcd..f1bc928043ac 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.c +++ b/drivers/media/platform/qcom/iris/iris_vdec.c @@ -263,6 +263,19 @@ int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f) return 0; } +int iris_vdec_validate_format(struct iris_inst *inst, u32 pixelformat) +{ + const struct iris_fmt *fmt = NULL; + + if (pixelformat != V4L2_PIX_FMT_NV12) { + fmt = find_format(inst, pixelformat, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (!fmt) + return -EINVAL; + } + + return 0; +} + int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub) { int ret = 0; diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h index b24932dc511a..097e02bfa72b 100644 --- a/drivers/media/platform/qcom/iris/iris_vdec.h +++ b/drivers/media/platform/qcom/iris/iris_vdec.h @@ -13,6 +13,7 @@ void iris_vdec_inst_deinit(struct iris_inst *inst); int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f); int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f); int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f); +int iris_vdec_validate_format(struct iris_inst *inst, u32 pixelformat); int iris_vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub); void iris_vdec_src_change(struct iris_inst *inst); int iris_vdec_streamon_input(struct iris_inst *inst); diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c index 40f7990cd162..55938050249f 100644 --- a/drivers/media/platform/qcom/iris/iris_venc.c +++ b/drivers/media/platform/qcom/iris/iris_venc.c @@ -273,3 +273,16 @@ int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f) return -EINVAL; } } + +int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat) +{ + const struct iris_fmt *fmt = NULL; + + if (pixelformat != V4L2_PIX_FMT_NV12) { + fmt = find_format(inst, pixelformat, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (!fmt) + return -EINVAL; + } + + return 0; +} diff --git a/drivers/media/platform/qcom/iris/iris_venc.h b/drivers/media/platform/qcom/iris/iris_venc.h index eb26a3ecbd98..04fd41275547 100644 --- a/drivers/media/platform/qcom/iris/iris_venc.h +++ b/drivers/media/platform/qcom/iris/iris_venc.h @@ -13,5 +13,6 @@ void iris_venc_inst_deinit(struct iris_inst *inst); int iris_venc_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f); int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f); int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f); +int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat); #endif diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index 7adb82186cac..3f641782e932 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -371,13 +371,18 @@ static int iris_enum_framesizes(struct file *filp, void *fh, { struct iris_inst *inst = iris_get_inst(filp); struct platform_inst_caps *caps; + int ret = 0; if (fsize->index) return -EINVAL; - if (fsize->pixel_format != V4L2_PIX_FMT_H264 && - fsize->pixel_format != V4L2_PIX_FMT_NV12) - return -EINVAL; + if (inst->domain == DECODER) + ret = iris_vdec_validate_format(inst, fsize->pixel_format); + else + ret = iris_venc_validate_format(inst, fsize->pixel_format); + + if (ret) + return ret; caps = inst->core->iris_platform_data->inst_caps; @@ -389,6 +394,51 @@ static int iris_enum_framesizes(struct file *filp, void *fh, fsize->stepwise.max_height = caps->max_frame_height; fsize->stepwise.step_height = STEP_HEIGHT; + return ret; +} + +static int iris_enum_frameintervals(struct file *filp, void *fh, + struct v4l2_frmivalenum *fival) + +{ + struct iris_inst *inst = iris_get_inst(filp); + struct iris_core *core = inst->core; + struct platform_inst_caps *caps; + u32 fps, mbpf; + int ret = 0; + + if (inst->domain == DECODER) + return -ENOTTY; + + if (fival->index) + return -EINVAL; + + ret = iris_venc_validate_format(inst, fival->pixel_format); + if (ret) + return ret; + + if (!fival->width || !fival->height) + return -EINVAL; + + caps = inst->core->iris_platform_data->inst_caps; + if (fival->width > caps->max_frame_width || + fival->width < caps->min_frame_width || + fival->height > caps->max_frame_height || + fival->height < caps->min_frame_height) + return -EINVAL; + + mbpf = NUM_MBS_PER_FRAME(fival->height, fival->width); + fps = DIV_ROUND_UP(core->iris_platform_data->max_core_mbps, mbpf); + + fival->type = V4L2_FRMIVAL_TYPE_STEPWISE; + fival->stepwise.min.numerator = 1; + fival->stepwise.min.denominator = + min_t(u32, fps, MAXIMUM_FPS); + fival->stepwise.max.numerator = 1; + fival->stepwise.max.denominator = 1; + fival->stepwise.step.numerator = 1; + fival->stepwise.step.denominator = MAXIMUM_FPS; + return 0; } @@ -523,6 +573,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = { .vidioc_s_fmt_vid_out_mplane = iris_s_fmt_vid_mplane, .vidioc_g_fmt_vid_cap_mplane = iris_g_fmt_vid_mplane, .vidioc_g_fmt_vid_out_mplane = iris_g_fmt_vid_mplane, + .vidioc_enum_framesizes = iris_enum_framesizes, + .vidioc_enum_frameintervals = iris_enum_frameintervals, }; void iris_init_ops(struct iris_core *core)