Hi Datlev, Some small and quick feedback below. On 2024-06-20 16:19, Detlev Casanova wrote: > This driver supports the second generation of the Rockchip Video > decoder, also known as vdpu34x. > It is currently only used on the RK3588(s) SoC. > > There are 2 decoders on the RK3588 SoC that can work in pair to decode > 8K video at 30 FPS but currently, only using one core at a time is > supported. > > Scheduling requests between the two cores will be implemented later. > > The core supports H264, HEVC, VP9 and AVS2 decoding but this driver > currently only supports H264. > > The driver is based on rkvdec and they may share some code in the > future. > The decision to make a different driver is mainly because rkvdec2 has > more features and can work with multiple cores. > > The registers are mapped in a struct in RAM using bitfields. It is IO > copied to the HW when all values are configured. > The decision to use such a struct instead of writing buffers one by one > is based on the following reasons: > - Rockchip cores are known to misbehave when registers are not written > in address order, > - Those cores also need the software to write all registers, even if > they are written their default values or are not related to the task > (this core will not start decoding some H264 frames if some VP9 > registers are not written to 0) > - In the future, to support multiple cores, the scheduler could be > optimized by storing the precomputed registers values and copy them > to the HW as soos as a core becomes available. > > This makes the code more readable and may bring performance improvements > in future features. > > Signed-off-by: Detlev Casanova <detlev.casanova@xxxxxxxxxxxxx> > --- > drivers/staging/media/Kconfig | 1 + > drivers/staging/media/Makefile | 1 + > drivers/staging/media/rkvdec2/Kconfig | 15 + > drivers/staging/media/rkvdec2/Makefile | 3 + > drivers/staging/media/rkvdec2/TODO | 9 + > drivers/staging/media/rkvdec2/rkvdec2-h264.c | 739 +++++++++++ > drivers/staging/media/rkvdec2/rkvdec2-regs.h | 345 +++++ > drivers/staging/media/rkvdec2/rkvdec2.c | 1253 ++++++++++++++++++ > drivers/staging/media/rkvdec2/rkvdec2.h | 130 ++ > 9 files changed, 2496 insertions(+) > create mode 100644 drivers/staging/media/rkvdec2/Kconfig > create mode 100644 drivers/staging/media/rkvdec2/Makefile > create mode 100644 drivers/staging/media/rkvdec2/TODO > create mode 100644 drivers/staging/media/rkvdec2/rkvdec2-h264.c > create mode 100644 drivers/staging/media/rkvdec2/rkvdec2-regs.h > create mode 100644 drivers/staging/media/rkvdec2/rkvdec2.c > create mode 100644 drivers/staging/media/rkvdec2/rkvdec2.h > > diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig > index 554c2e475ce3..7f377d37e670 100644 > --- a/drivers/staging/media/Kconfig > +++ b/drivers/staging/media/Kconfig > @@ -35,6 +35,7 @@ source "drivers/staging/media/meson/vdec/Kconfig" > source "drivers/staging/media/omap4iss/Kconfig" > > source "drivers/staging/media/rkvdec/Kconfig" > +source "drivers/staging/media/rkvdec2/Kconfig" > > source "drivers/staging/media/starfive/Kconfig" > > diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile > index dcaeeca0ee6d..0a2d89db32b2 100644 > --- a/drivers/staging/media/Makefile > +++ b/drivers/staging/media/Makefile > @@ -6,6 +6,7 @@ obj-$(CONFIG_VIDEO_MAX96712) += max96712/ > obj-$(CONFIG_VIDEO_MESON_VDEC) += meson/vdec/ > obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ > obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rkvdec/ > +obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC2) += rkvdec2/ > obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive/ > obj-$(CONFIG_VIDEO_SUNXI) += sunxi/ > obj-$(CONFIG_VIDEO_TEGRA) += tegra-video/ > diff --git a/drivers/staging/media/rkvdec2/Kconfig b/drivers/staging/media/rkvdec2/Kconfig > new file mode 100644 > index 000000000000..fd505cb7aff9 > --- /dev/null > +++ b/drivers/staging/media/rkvdec2/Kconfig > @@ -0,0 +1,15 @@ > +# SPDX-License-Identifier: GPL-2.0 > +config VIDEO_ROCKCHIP_VDEC2 > + tristate "Rockchip Video Decoder driver 2" > + depends on ARCH_ROCKCHIP || COMPILE_TEST > + depends on VIDEO_DEV > + select MEDIA_CONTROLLER > + select VIDEOBUF2_DMA_CONTIG > + select VIDEOBUF2_VMALLOC > + select V4L2_MEM2MEM_DEV > + select V4L2_H264 > + help > + Support for the Rockchip Video Decoder 2 IP present on Rockchip SoCs, > + which accelerates video decoding. > + To compile this driver as a module, choose M here: the module > + will be called rockchip-vdec2. > diff --git a/drivers/staging/media/rkvdec2/Makefile b/drivers/staging/media/rkvdec2/Makefile > new file mode 100644 > index 000000000000..b5a6ac701970 > --- /dev/null > +++ b/drivers/staging/media/rkvdec2/Makefile > @@ -0,0 +1,3 @@ > +obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC2) += rockchip-vdec2.o > + > +rockchip-vdec2-y += rkvdec2.o rkvdec2-h264.o > diff --git a/drivers/staging/media/rkvdec2/TODO b/drivers/staging/media/rkvdec2/TODO > new file mode 100644 > index 000000000000..9f64270e789e > --- /dev/null > +++ b/drivers/staging/media/rkvdec2/TODO > @@ -0,0 +1,9 @@ > +* Support for 4:2:2 and 10 bits > +* Support for rockchip IOMMU > +* Support for HEVC and VP9 are planned for this driver. > + > + First, the h264 backend needs to be stabilized. > + > +* Evaluate sharing code with rkvdec > + > + As rkvdec is still in staging, this driver stays there as well. > diff --git a/drivers/staging/media/rkvdec2/rkvdec2-h264.c b/drivers/staging/media/rkvdec2/rkvdec2-h264.c > new file mode 100644 > index 000000000000..37606f6833a1 > --- /dev/null > +++ b/drivers/staging/media/rkvdec2/rkvdec2-h264.c > @@ -0,0 +1,739 @@ [snip] > + > +/* Data structure describing auxiliary buffer format. */ > +struct rkvdec2_h264_priv_tbl { > + u32 cabac_table[928]; This should probably now match rkvdec, i.e. s8 cabac_table[4][464][2]; > + struct rkvdec2_h264_scaling_list scaling_list; > + struct rkvdec2_sps_pps param_set[256]; > + struct rkvdec2_rps rps; > +}; > + > +struct rkvdec2_h264_reflists { > + struct v4l2_h264_reference p[V4L2_H264_REF_LIST_LEN]; > + struct v4l2_h264_reference b0[V4L2_H264_REF_LIST_LEN]; > + struct v4l2_h264_reference b1[V4L2_H264_REF_LIST_LEN]; > +}; > + > +struct rkvdec2_h264_run { > + struct rkvdec2_run base; > + const struct v4l2_ctrl_h264_decode_params *decode_params; > + const struct v4l2_ctrl_h264_sps *sps; > + const struct v4l2_ctrl_h264_pps *pps; > + const struct v4l2_ctrl_h264_scaling_matrix *scaling_matrix; These are aligned, others are not, please be consistent. > + struct vb2_buffer *ref_buf[V4L2_H264_NUM_DPB_ENTRIES]; > +}; > + > +struct rkvdec2_h264_ctx { > + struct rkvdec2_aux_buf priv_tbl; > + struct rkvdec2_h264_reflists reflists; > + struct rkvdec2_regs_h264 regs; Same as above, please be consistent for all structs. > +}; > + > +static void assemble_hw_pps(struct rkvdec2_ctx *ctx, > + struct rkvdec2_h264_run *run) > +{ > + struct rkvdec2_h264_ctx *h264_ctx = ctx->priv; > + const struct v4l2_ctrl_h264_sps *sps = run->sps; > + const struct v4l2_ctrl_h264_pps *pps = run->pps; > + const struct v4l2_ctrl_h264_decode_params *dec_params = run->decode_params; > + const struct v4l2_h264_dpb_entry *dpb = dec_params->dpb; > + struct rkvdec2_h264_priv_tbl *priv_tbl = h264_ctx->priv_tbl.cpu; > + struct rkvdec2_sps_pps *hw_ps; > + dma_addr_t scaling_list_address; > + u32 scaling_distance; > + u32 i; > + > + /* > + * HW read the SPS/PPS information from PPS packet index by PPS id. > + * offset from the base can be calculated by PPS_id * 32 (size per PPS > + * packet unit). so the driver copy SPS/PPS information to the exact PPS > + * packet unit for HW accessing. > + */ > + hw_ps = &priv_tbl->param_set[pps->pic_parameter_set_id]; > + memset(hw_ps, 0, sizeof(*hw_ps)); > + > + /* write sps */ > + hw_ps->sps.seq_parameter_set_id = 0xf; This should use sps->seq_parameter_set_id > + hw_ps->sps.profile_idc = 0xff; This shold use sps->profile_idc > + hw_ps->sps.constraint_set3_flag = 1; This should use !!(sps->constraint_set_flags & (1 << 3)) > + hw_ps->sps.chroma_format_idc = sps->chroma_format_idc; > + hw_ps->sps.bit_depth_luma = sps->bit_depth_luma_minus8; > + hw_ps->sps.bit_depth_chroma = sps->bit_depth_chroma_minus8; > + hw_ps->sps.qpprime_y_zero_transform_bypass_flag = 0; This should use !!(sps->flags & V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS) > + hw_ps->sps.log2_max_frame_num_minus4 = sps->log2_max_frame_num_minus4; > + hw_ps->sps.max_num_ref_frames = sps->max_num_ref_frames; > + hw_ps->sps.pic_order_cnt_type = sps->pic_order_cnt_type; > + hw_ps->sps.log2_max_pic_order_cnt_lsb_minus4 = > + sps->log2_max_pic_order_cnt_lsb_minus4; > + hw_ps->sps.delta_pic_order_always_zero_flag = > + !!(sps->flags & V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO); > + hw_ps->sps.mvc_extension_enable = 1; > + hw_ps->sps.num_views = 1; > + > + /* > + * Use the SPS values since they are already in macroblocks > + * dimensions, height can be field height (halved) if > + * V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY is not set and also it allows > + * decoding smaller images into larger allocation which can be used > + * to implementing SVC spatial layer support. > + */ > + hw_ps->sps.pic_width_in_mbs = sps->pic_width_in_mbs_minus1 + 1; > + hw_ps->sps.pic_height_in_mbs = sps->pic_height_in_map_units_minus1 + 1; > + hw_ps->sps.frame_mbs_only_flag = > + !!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY); > + hw_ps->sps.mb_adaptive_frame_field_flag = > + !!(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD); > + hw_ps->sps.direct_8x8_inference_flag = > + !!(sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE); > + > + /* write pps */ > + hw_ps->pps.pic_parameter_set_id = 0xff; This should use pps->pic_parameter_set_id > + hw_ps->pps.pps_seq_parameter_set_id = 0x1f; This should use pps->seq_parameter_set_id Fluster score is not affected by these changes and follow https://lore.kernel.org/linux-media/20240618194647.742037-5-jonas@xxxxxxxxx/ > + hw_ps->pps.entropy_coding_mode_flag = > + !!(pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE); > + hw_ps->pps.bottom_field_pic_order_in_frame_present_flag = > + !!(pps->flags & V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT); > + hw_ps->pps.num_ref_idx_l0_default_active_minus1 = > + pps->num_ref_idx_l0_default_active_minus1; > + hw_ps->pps.num_ref_idx_l1_default_active_minus1 = > + pps->num_ref_idx_l1_default_active_minus1; > + hw_ps->pps.weighted_pred_flag = > + !!(pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED); > + hw_ps->pps.weighted_bipred_idc = pps->weighted_bipred_idc; > + hw_ps->pps.pic_init_qp_minus26 = pps->pic_init_qp_minus26; > + hw_ps->pps.pic_init_qs_minus26 = pps->pic_init_qs_minus26; > + hw_ps->pps.chroma_qp_index_offset = pps->chroma_qp_index_offset; > + hw_ps->pps.deblocking_filter_control_present_flag = > + !!(pps->flags & V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT); > + hw_ps->pps.constrained_intra_pred_flag = > + !!(pps->flags & V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED); > + hw_ps->pps.redundant_pic_cnt_present = > + !!(pps->flags & V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT); > + hw_ps->pps.transform_8x8_mode_flag = > + !!(pps->flags & V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE); > + hw_ps->pps.second_chroma_qp_index_offset = pps->second_chroma_qp_index_offset; > + hw_ps->pps.scaling_list_enable_flag = > + !!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT); > + > + /* > + * To be on the safe side, program the scaling matrix address > + * > + * With this set here, > + * RKVDEC_SWREG12_SENCODARY_EN:sw_scanlist_addr_valid_en > + * can stay at 0 > + */ > + scaling_distance = offsetof(struct rkvdec2_h264_priv_tbl, scaling_list); > + scaling_list_address = h264_ctx->priv_tbl.dma + scaling_distance; > + hw_ps->pps.scaling_list_address = scaling_list_address; > + > + for (i = 0; i < ARRAY_SIZE(dec_params->dpb); i++) { > + if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) > + hw_ps->pps.is_longterm |= (1 << i); > + } > +} > + [snip] > diff --git a/drivers/staging/media/rkvdec2/rkvdec2.c b/drivers/staging/media/rkvdec2/rkvdec2.c > new file mode 100644 > index 000000000000..464eec67521b > --- /dev/null > +++ b/drivers/staging/media/rkvdec2/rkvdec2.c > @@ -0,0 +1,1253 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Rockchip Video Decoder 2 driver > + * > + * Copyright (C) 2024 Collabora, Ltd. > + * Detlev Casanova <detlev.casanova@xxxxxxxxxxxxx> > + * > + * Based on rkvdec driver by Boris Brezillon <boris.brezillon@xxxxxxxxxxxxx> > + */ > + > +#include <linux/clk.h> > +#include <linux/genalloc.h> > +#include <linux/interrupt.h> > +#include <linux/module.h> > +#include <linux/of.h> > +#include <linux/platform_device.h> > +#include <linux/pm.h> > +#include <linux/pm_runtime.h> > +#include <linux/slab.h> > +#include <linux/videodev2.h> > +#include <linux/workqueue.h> > +#include <media/v4l2-event.h> > +#include <media/v4l2-mem2mem.h> > +#include <media/videobuf2-core.h> > +#include <media/videobuf2-vmalloc.h> > + > +#include "rkvdec2.h" > + > +static int rkvdec2_try_ctrl(struct v4l2_ctrl *ctrl) > +{ > + struct rkvdec2_ctx *ctx = container_of(ctrl->handler, struct rkvdec2_ctx, ctrl_hdl); > + const struct rkvdec2_coded_fmt_desc *desc = ctx->coded_fmt_desc; > + > + if (desc->ops->try_ctrl) > + return desc->ops->try_ctrl(ctx, ctrl); > + > + return 0; > +} > + > +static const struct v4l2_ctrl_ops rkvdec2_ctrl_ops = { > + .try_ctrl = rkvdec2_try_ctrl, > +}; > + > +static const struct rkvdec2_ctrl_desc rkvdec2_h264_ctrl_descs[] = { > + { > + .cfg.id = V4L2_CID_STATELESS_H264_DECODE_PARAMS, > + }, > + { > + .cfg.id = V4L2_CID_STATELESS_H264_SPS, > + .cfg.ops = &rkvdec2_ctrl_ops, > + }, > + { > + .cfg.id = V4L2_CID_STATELESS_H264_PPS, > + }, > + { > + .cfg.id = V4L2_CID_STATELESS_H264_SCALING_MATRIX, > + }, > + { > + .cfg.id = V4L2_CID_STATELESS_H264_DECODE_MODE, > + .cfg.min = V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED, > + .cfg.max = V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED, > + .cfg.def = V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED, > + }, > + { > + .cfg.id = V4L2_CID_STATELESS_H264_START_CODE, > + .cfg.min = V4L2_STATELESS_H264_START_CODE_ANNEX_B, > + .cfg.def = V4L2_STATELESS_H264_START_CODE_ANNEX_B, > + .cfg.max = V4L2_STATELESS_H264_START_CODE_ANNEX_B, > + }, > + { > + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE, > + .cfg.min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, Should be V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE > + .cfg.max = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, > + .cfg.menu_skip_mask = > + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED), > + .cfg.def = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN, > + }, > + { > + .cfg.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL, > + .cfg.min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0, > + .cfg.max = V4L2_MPEG_VIDEO_H264_LEVEL_6_1, > + }, > +}; > + > +static const struct rkvdec2_ctrls rkvdec2_h264_ctrls = { > + .ctrls = rkvdec2_h264_ctrl_descs, > + .num_ctrls = ARRAY_SIZE(rkvdec2_h264_ctrl_descs), > +}; > + > +static const u32 rkvdec2_h264_decoded_fmts[] = { > + V4L2_PIX_FMT_NV12 > +}; > + > +static const struct rkvdec2_coded_fmt_desc rkvdec2_coded_fmts[] = { > + { > + .fourcc = V4L2_PIX_FMT_H264_SLICE, > + .frmsize = { > + .min_width = 16, > + .max_width = 65520, > + .step_width = 16, > + .min_height = 16, > + .max_height = 65520, > + .step_height = 16, > + }, > + .ctrls = &rkvdec2_h264_ctrls, > + .ops = &rkvdec2_h264_fmt_ops, > + .num_decoded_fmts = ARRAY_SIZE(rkvdec2_h264_decoded_fmts), > + .decoded_fmts = rkvdec2_h264_decoded_fmts, > + .subsystem_flags = VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF, > + }, > +}; > + > +enum rcb_axis { > + PIC_WIDTH = 0, > + PIC_HEIGHT = 1 > +}; > + > +struct rcb_size_info { > + u8 multiplier; > + enum rcb_axis axis; > +}; > + > +static struct rcb_size_info rcb_sizes[] = { > + {6, PIC_WIDTH}, // intrar > + {1, PIC_WIDTH}, // transdr (Is actually 0.4*pic_width) > + {1, PIC_HEIGHT}, // transdc (Is actually 0.1*pic_height) > + {3, PIC_WIDTH}, // streamdr > + {6, PIC_WIDTH}, // interr > + {3, PIC_HEIGHT}, // interc > + {22, PIC_WIDTH}, // dblkr > + {6, PIC_WIDTH}, // saor > + {11, PIC_WIDTH}, // fbcr > + {67, PIC_HEIGHT}, // filtc col > +}; > + > +#define RCB_SIZE(n) (rcb_sizes[(n)].multiplier * (rcb_sizes[(n)].axis ? height : width)) This should probably take width and height, e.g.: RCB_SIZE(n,w,h) (rcb_sizes[(n)].multiplier * (rcb_sizes[(n)].axis ? (h) : (w))) > + > +static const struct rkvdec2_coded_fmt_desc * > +rkvdec2_find_coded_fmt_desc(u32 fourcc) > +{ > + unsigned int i; > + > + for (i = 0; i < ARRAY_SIZE(rkvdec2_coded_fmts); i++) { > + if (rkvdec2_coded_fmts[i].fourcc == fourcc) > + return &rkvdec2_coded_fmts[i]; > + } > + > + return NULL; > +} > + > +static void rkvdec2_reset_fmt(struct rkvdec2_ctx *ctx, struct v4l2_format *f, > + u32 fourcc) > +{ > + memset(f, 0, sizeof(*f)); > + f->fmt.pix_mp.pixelformat = fourcc; > + f->fmt.pix_mp.field = V4L2_FIELD_NONE; > + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_REC709; > + f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; > + f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT; > + f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT; > +} > + > +static void rkvdec2_reset_coded_fmt(struct rkvdec2_ctx *ctx) > +{ > + struct v4l2_format *f = &ctx->coded_fmt; > + > + ctx->coded_fmt_desc = &rkvdec2_coded_fmts[0]; > + rkvdec2_reset_fmt(ctx, f, ctx->coded_fmt_desc->fourcc); > + > + f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; > + f->fmt.pix_mp.width = ctx->coded_fmt_desc->frmsize.min_width; > + f->fmt.pix_mp.height = ctx->coded_fmt_desc->frmsize.min_height; > + > + if (ctx->coded_fmt_desc->ops->adjust_fmt) > + ctx->coded_fmt_desc->ops->adjust_fmt(ctx, f); > +} > + > +static void rkvdec2_reset_decoded_fmt(struct rkvdec2_ctx *ctx) > +{ > + struct v4l2_format *f = &ctx->decoded_fmt; > + > + rkvdec2_reset_fmt(ctx, f, ctx->coded_fmt_desc->decoded_fmts[0]); > + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; > + v4l2_fill_pixfmt_mp(&f->fmt.pix_mp, > + ctx->coded_fmt_desc->decoded_fmts[0], > + ctx->coded_fmt.fmt.pix_mp.width, > + ctx->coded_fmt.fmt.pix_mp.height); > + > + ctx->colmv_offset = f->fmt.pix_mp.plane_fmt[0].sizeimage; > + > + f->fmt.pix_mp.plane_fmt[0].sizeimage += 128 * > + DIV_ROUND_UP(f->fmt.pix_mp.width, 16) * > + DIV_ROUND_UP(f->fmt.pix_mp.height, 16); > +} > + > +static int rkvdec2_enum_framesizes(struct file *file, void *priv, > + struct v4l2_frmsizeenum *fsize) > +{ > + const struct rkvdec2_coded_fmt_desc *fmt; This should probably be named desc to match other uses. Regards, Jonas > + > + if (fsize->index != 0) > + return -EINVAL; > + > + fmt = rkvdec2_find_coded_fmt_desc(fsize->pixel_format); > + if (!fmt) > + return -EINVAL; > + > + fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; > + fsize->stepwise = fmt->frmsize; > + return 0; > +} > + [snip]