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 <quic_vgarodia@quicinc.com> # X1E80100
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-HDK
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8650-HDK
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # x1e80100-crd
Signed-off-by: Bryan O'Donoghue <bod@kernel.org>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
This commit is contained in:
Dikshita Agarwal
2025-08-25 12:30:40 +05:30
committed by Hans Verkuil
parent 63357cf8a9
commit a6882431a1
8 changed files with 91 additions and 4 deletions

View File

@@ -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;

View File

@@ -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 =

View File

@@ -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 =

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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)