// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2023 MediaTek Inc. * Author: Xiaoyong Lu <[email protected]> */ #include <linux/module.h> #include <linux/slab.h> #include <media/videobuf2-dma-contig.h> #include "../mtk_vcodec_dec.h" #include "../../common/mtk_vcodec_intr.h" #include "../vdec_drv_base.h" #include "../vdec_drv_if.h" #include "../vdec_vpu_if.h" #define AV1_MAX_FRAME_BUF_COUNT … #define AV1_TILE_BUF_SIZE … #define AV1_SCALE_SUBPEL_BITS … #define AV1_REF_SCALE_SHIFT … #define AV1_REF_NO_SCALE … #define AV1_REF_INVALID_SCALE … #define AV1_CDF_TABLE_BUFFER_SIZE … #define AV1_PRIMARY_REF_NONE … #define AV1_INVALID_IDX … #define AV1_DIV_ROUND_UP_POW2(value, n) … #define AV1_DIV_ROUND_UP_POW2_SIGNED(value, n) … #define BIT_FLAG(x, bit) … #define SEGMENTATION_FLAG(x, name) … #define QUANT_FLAG(x, name) … #define SEQUENCE_FLAG(x, name) … #define FH_FLAG(x, name) … #define MINQ … #define MAXQ … #define DIV_LUT_PREC_BITS … #define DIV_LUT_BITS … #define DIV_LUT_NUM … #define WARP_PARAM_REDUCE_BITS … #define WARPEDMODEL_PREC_BITS … #define SEG_LVL_ALT_Q … #define SECONDARY_FILTER_STRENGTH_NUM_BITS … static const short div_lut[DIV_LUT_NUM + 1] = …; /** * struct vdec_av1_slice_init_vsi - VSI used to initialize instance * @architecture: architecture type * @reserved: reserved * @core_vsi: for core vsi * @cdf_table_addr: cdf table addr * @cdf_table_size: cdf table size * @iq_table_addr: iq table addr * @iq_table_size: iq table size * @vsi_size: share vsi structure size */ struct vdec_av1_slice_init_vsi { … }; /** * struct vdec_av1_slice_mem - memory address and size * @buf: dma_addr padding * @dma_addr: buffer address * @size: buffer size * @dma_addr_end: buffer end address * @padding: for padding */ struct vdec_av1_slice_mem { … }; /** * struct vdec_av1_slice_state - decoding state * @err : err type for decode * @full : transcoded buffer is full or not * @timeout : decode timeout or not * @perf : performance enable * @crc : hw checksum * @out_size : hw output size */ struct vdec_av1_slice_state { … }; /* * enum vdec_av1_slice_resolution_level - resolution level */ enum vdec_av1_slice_resolution_level { … }; /* * enum vdec_av1_slice_frame_type - av1 frame type */ enum vdec_av1_slice_frame_type { … }; /* * enum vdec_av1_slice_reference_mode - reference mode type */ enum vdec_av1_slice_reference_mode { … }; /** * struct vdec_av1_slice_tile_group - info for each tile * @num_tiles: tile number * @tile_size: input size for each tile * @tile_start_offset: tile offset to input buffer */ struct vdec_av1_slice_tile_group { … }; /** * struct vdec_av1_slice_scale_factors - scale info for each ref frame * @is_scaled: frame is scaled or not * @x_scale: frame width scale coefficient * @y_scale: frame height scale coefficient * @x_step: width step for x_scale * @y_step: height step for y_scale */ struct vdec_av1_slice_scale_factors { … }; /** * struct vdec_av1_slice_frame_refs - ref frame info * @ref_fb_idx: ref slot index * @ref_map_idx: ref frame index * @scale_factors: scale factors for each ref frame */ struct vdec_av1_slice_frame_refs { … }; /** * struct vdec_av1_slice_gm - AV1 Global Motion parameters * @wmtype: The type of global motion transform used * @wmmat: gm_params * @alpha: alpha info * @beta: beta info * @gamma: gamma info * @delta: delta info * @invalid: is invalid or not */ struct vdec_av1_slice_gm { … }; /** * struct vdec_av1_slice_sm - AV1 Skip Mode parameters * @skip_mode_allowed: Skip Mode is allowed or not * @skip_mode_present: specified that the skip_mode will be present or not * @skip_mode_frame: specifies the frames to use for compound prediction */ struct vdec_av1_slice_sm { … }; /** * struct vdec_av1_slice_seg - AV1 Segmentation params * @segmentation_enabled: this frame makes use of the segmentation tool or not * @segmentation_update_map: segmentation map are updated during the decoding frame * @segmentation_temporal_update:segmentation map are coded relative the existing segmentaion map * @segmentation_update_data: new parameters are about to be specified for each segment * @feature_data: specifies the feature data for a segment feature * @feature_enabled_mask: the corresponding feature value is coded or not. * @segid_preskip: segment id will be read before the skip syntax element. * @last_active_segid: the highest numbered segment id that has some enabled feature */ struct vdec_av1_slice_seg { … }; /** * struct vdec_av1_slice_delta_q_lf - AV1 Loop Filter delta parameters * @delta_q_present: specified whether quantizer index delta values are present * @delta_q_res: specifies the left shift which should be applied to decoded quantizer index * @delta_lf_present: specifies whether loop filter delta values are present * @delta_lf_res: specifies the left shift which should be applied to decoded * loop filter delta values * @delta_lf_multi: specifies that separate loop filter deltas are sent for horizontal * luma edges,vertical luma edges,the u edges, and the v edges. */ struct vdec_av1_slice_delta_q_lf { … }; /** * struct vdec_av1_slice_quantization - AV1 Quantization params * @base_q_idx: indicates the base frame qindex. This is used for Y AC * coefficients and as the base value for the other quantizers. * @qindex: qindex * @delta_qydc: indicates the Y DC quantizer relative to base_q_idx * @delta_qudc: indicates the U DC quantizer relative to base_q_idx. * @delta_quac: indicates the U AC quantizer relative to base_q_idx * @delta_qvdc: indicates the V DC quantizer relative to base_q_idx * @delta_qvac: indicates the V AC quantizer relative to base_q_idx * @using_qmatrix: specifies that the quantizer matrix will be used to * compute quantizers * @qm_y: specifies the level in the quantizer matrix that should * be used for luma plane decoding * @qm_u: specifies the level in the quantizer matrix that should * be used for chroma U plane decoding. * @qm_v: specifies the level in the quantizer matrix that should be * used for chroma V plane decoding */ struct vdec_av1_slice_quantization { … }; /** * struct vdec_av1_slice_lr - AV1 Loop Restauration parameters * @use_lr: whether to use loop restoration * @use_chroma_lr: whether to use chroma loop restoration * @frame_restoration_type: specifies the type of restoration used for each plane * @loop_restoration_size: specifies the size of loop restoration units in units * of samples in the current plane */ struct vdec_av1_slice_lr { … }; /** * struct vdec_av1_slice_loop_filter - AV1 Loop filter parameters * @loop_filter_level: an array containing loop filter strength values. * @loop_filter_ref_deltas: contains the adjustment needed for the filter * level based on the chosen reference frame * @loop_filter_mode_deltas: contains the adjustment needed for the filter * level based on the chosen mode * @loop_filter_sharpness: indicates the sharpness level. The loop_filter_level * and loop_filter_sharpness together determine when * a block edge is filtered, and by how much the * filtering can change the sample values * @loop_filter_delta_enabled: filter level depends on the mode and reference * frame used to predict a block */ struct vdec_av1_slice_loop_filter { … }; /** * struct vdec_av1_slice_cdef - AV1 CDEF parameters * @cdef_damping: controls the amount of damping in the deringing filter * @cdef_y_strength: specifies the strength of the primary filter and secondary filter * @cdef_uv_strength: specifies the strength of the primary filter and secondary filter * @cdef_bits: specifies the number of bits needed to specify which * CDEF filter to apply */ struct vdec_av1_slice_cdef { … }; /** * struct vdec_av1_slice_mfmv - AV1 mfmv parameters * @mfmv_valid_ref: mfmv_valid_ref * @mfmv_dir: mfmv_dir * @mfmv_ref_to_cur: mfmv_ref_to_cur * @mfmv_ref_frame_idx: mfmv_ref_frame_idx * @mfmv_count: mfmv_count */ struct vdec_av1_slice_mfmv { … }; /** * struct vdec_av1_slice_tile - AV1 Tile info * @tile_cols: specifies the number of tiles across the frame * @tile_rows: specifies the number of tiles down the frame * @mi_col_starts: an array specifying the start column * @mi_row_starts: an array specifying the start row * @context_update_tile_id: specifies which tile to use for the CDF update * @uniform_tile_spacing_flag: tiles are uniformly spaced across the frame * or the tile sizes are coded */ struct vdec_av1_slice_tile { … }; /** * struct vdec_av1_slice_uncompressed_header - Represents an AV1 Frame Header OBU * @use_ref_frame_mvs: use_ref_frame_mvs flag * @order_hint: specifies OrderHintBits least significant bits of the expected * @gm: global motion param * @upscaled_width: the upscaled width * @frame_width: frame's width * @frame_height: frame's height * @reduced_tx_set: frame is restricted to a reduced subset of the full * set of transform types * @tx_mode: specifies how the transform size is determined * @uniform_tile_spacing_flag: tiles are uniformly spaced across the frame * or the tile sizes are coded * @interpolation_filter: specifies the filter selection used for performing inter prediction * @allow_warped_motion: motion_mode may be present or not * @is_motion_mode_switchable : equal to 0 specifies that only the SIMPLE motion mode will be used * @reference_mode : frame reference mode selected * @allow_high_precision_mv: specifies that motion vectors are specified to * quarter pel precision or to eighth pel precision * @allow_intra_bc: allows that intra block copy may be used in this frame * @force_integer_mv: specifies motion vectors will always be integers or * can contain fractional bits * @allow_screen_content_tools: intra blocks may use palette encoding * @error_resilient_mode: error resilient mode is enable/disable * @frame_type: specifies the AV1 frame type * @primary_ref_frame: specifies which reference frame contains the CDF values * and other state that should be loaded at the start of the frame * slots will be updated with the current frame after it is decoded * @disable_frame_end_update_cdf:indicates the end of frame CDF update is disable or enable * @disable_cdf_update: specified whether the CDF update in the symbol * decoding process should be disables * @skip_mode: av1 skip mode parameters * @seg: av1 segmentation parameters * @delta_q_lf: av1 delta loop filter * @quant: av1 Quantization params * @lr: av1 Loop Restauration parameters * @superres_denom: the denominator for the upscaling ratio * @loop_filter: av1 Loop filter parameters * @cdef: av1 CDEF parameters * @mfmv: av1 mfmv parameters * @tile: av1 Tile info * @frame_is_intra: intra frame * @loss_less_array: lossless array * @coded_loss_less: coded lossless * @mi_rows: size of mi unit in rows * @mi_cols: size of mi unit in cols */ struct vdec_av1_slice_uncompressed_header { … }; /** * struct vdec_av1_slice_seq_header - Represents an AV1 Sequence OBU * @bitdepth: the bitdepth to use for the sequence * @enable_superres: specifies whether the use_superres syntax element may be present * @enable_filter_intra: specifies the use_filter_intra syntax element may be present * @enable_intra_edge_filter: whether the intra edge filtering process should be enabled * @enable_interintra_compound: specifies the mode info fo rinter blocks may * contain the syntax element interintra * @enable_masked_compound: specifies the mode info fo rinter blocks may * contain the syntax element compound_type * @enable_dual_filter: the inter prediction filter type may be specified independently * @enable_jnt_comp: distance weights process may be used for inter prediction * @mono_chrome: indicates the video does not contain U and V color planes * @enable_order_hint: tools based on the values of order hints may be used * @order_hint_bits: the number of bits used for the order_hint field at each frame * @use_128x128_superblock: indicates superblocks contain 128*128 luma samples * @subsampling_x: the chroma subsamling format * @subsampling_y: the chroma subsamling format * @max_frame_width: the maximum frame width for the frames represented by sequence * @max_frame_height: the maximum frame height for the frames represented by sequence */ struct vdec_av1_slice_seq_header { … }; /** * struct vdec_av1_slice_frame - Represents current Frame info * @uh: uncompressed header info * @seq: sequence header info * @large_scale_tile: is large scale mode * @cur_ts: current frame timestamp * @prev_fb_idx: prev slot id * @ref_frame_sign_bias: arrays for ref_frame sign bias * @order_hints: arrays for ref_frame order hint * @ref_frame_valid: arrays for valid ref_frame * @ref_frame_map: map to slot frame info * @frame_refs: ref_frame info */ struct vdec_av1_slice_frame { … }; /** * struct vdec_av1_slice_work_buffer - work buffer for lat * @mv_addr: mv buffer memory info * @cdf_addr: cdf buffer memory info * @segid_addr: segid buffer memory info */ struct vdec_av1_slice_work_buffer { … }; /** * struct vdec_av1_slice_frame_info - frame info for each slot * @frame_type: frame type * @frame_is_intra: is intra frame * @order_hint: order hint * @order_hints: referece frame order hint * @upscaled_width: upscale width * @pic_pitch: buffer pitch * @frame_width: frane width * @frame_height: frame height * @mi_rows: rows in mode info * @mi_cols: cols in mode info * @ref_count: mark to reference frame counts */ struct vdec_av1_slice_frame_info { … }; /** * struct vdec_av1_slice_slot - slot info that needs to be saved in the global instance * @frame_info: frame info for each slot * @timestamp: time stamp info */ struct vdec_av1_slice_slot { … }; /** * struct vdec_av1_slice_fb - frame buffer for decoding * @y: current y buffer address info * @c: current c buffer address info */ struct vdec_av1_slice_fb { … }; /** * struct vdec_av1_slice_vsi - exchange frame information between Main CPU and MicroP * @bs: input buffer info * @work_buffer: working buffe for hw * @cdf_table: cdf_table buffer * @cdf_tmp: cdf temp buffer * @rd_mv: mv buffer for lat output , core input * @ube: ube buffer * @trans: transcoded buffer * @err_map: err map buffer * @row_info: row info buffer * @fb: current y/c buffer * @ref: ref y/c buffer * @iq_table: iq table buffer * @tile: tile buffer * @slots: slots info for each frame * @slot_id: current frame slot id * @frame: current frame info * @state: status after decode done * @cur_lst_tile_id: tile id for large scale */ struct vdec_av1_slice_vsi { … }; /** * struct vdec_av1_slice_pfc - per-frame context that contains a local vsi. * pass it from lat to core * @vsi: local vsi. copy to/from remote vsi before/after decoding * @ref_idx: reference buffer timestamp * @seq: picture sequence */ struct vdec_av1_slice_pfc { … }; /** * struct vdec_av1_slice_instance - represent one av1 instance * @ctx: pointer to codec's context * @vpu: VPU instance * @iq_table: iq table buffer * @cdf_table: cdf table buffer * @mv: mv working buffer * @cdf: cdf working buffer * @seg: segmentation working buffer * @cdf_temp: cdf temp buffer * @tile: tile buffer * @slots: slots info * @tile_group: tile_group entry * @level: level of current resolution * @width: width of last picture * @height: height of last picture * @frame_type: frame_type of last picture * @irq_enabled: irq to Main CPU or MicroP * @inneracing_mode: is inneracing mode * @init_vsi: vsi used for initialized AV1 instance * @vsi: vsi used for decoding/flush ... * @core_vsi: vsi used for Core stage * @seq: global picture sequence */ struct vdec_av1_slice_instance { … }; static int vdec_av1_slice_core_decode(struct vdec_lat_buf *lat_buf); static inline int vdec_av1_slice_get_msb(u32 n) { … } static inline bool vdec_av1_slice_need_scale(u32 ref_width, u32 ref_height, u32 this_width, u32 this_height) { … } static void *vdec_av1_get_ctrl_ptr(struct mtk_vcodec_dec_ctx *ctx, int id) { … } static int vdec_av1_slice_init_cdf_table(struct vdec_av1_slice_instance *instance) { … } static int vdec_av1_slice_init_iq_table(struct vdec_av1_slice_instance *instance) { … } static int vdec_av1_slice_get_new_slot(struct vdec_av1_slice_vsi *vsi) { … } static inline void vdec_av1_slice_clear_fb(struct vdec_av1_slice_frame_info *frame_info) { … } static void vdec_av1_slice_decrease_ref_count(struct vdec_av1_slice_slot *slots, int fb_idx) { … } static void vdec_av1_slice_cleanup_slots(struct vdec_av1_slice_slot *slots, struct vdec_av1_slice_frame *frame, struct v4l2_ctrl_av1_frame *ctrl_fh) { … } static void vdec_av1_slice_setup_slot(struct vdec_av1_slice_instance *instance, struct vdec_av1_slice_vsi *vsi, struct v4l2_ctrl_av1_frame *ctrl_fh) { … } static int vdec_av1_slice_alloc_working_buffer(struct vdec_av1_slice_instance *instance, struct vdec_av1_slice_vsi *vsi) { … } static void vdec_av1_slice_free_working_buffer(struct vdec_av1_slice_instance *instance) { … } static inline void vdec_av1_slice_vsi_from_remote(struct vdec_av1_slice_vsi *vsi, struct vdec_av1_slice_vsi *remote_vsi) { … } static inline void vdec_av1_slice_vsi_to_remote(struct vdec_av1_slice_vsi *vsi, struct vdec_av1_slice_vsi *remote_vsi) { … } static int vdec_av1_slice_setup_lat_from_src_buf(struct vdec_av1_slice_instance *instance, struct vdec_av1_slice_vsi *vsi, struct vdec_lat_buf *lat_buf) { … } static short vdec_av1_slice_resolve_divisor_32(u32 D, short *shift) { … } static void vdec_av1_slice_get_shear_params(struct vdec_av1_slice_gm *gm_params) { … } static void vdec_av1_slice_setup_gm(struct vdec_av1_slice_gm *gm, struct v4l2_av1_global_motion *ctrl_gm) { … } static void vdec_av1_slice_setup_seg(struct vdec_av1_slice_seg *seg, struct v4l2_av1_segmentation *ctrl_seg) { … } static void vdec_av1_slice_setup_quant(struct vdec_av1_slice_quantization *quant, struct v4l2_av1_quantization *ctrl_quant) { … } static int vdec_av1_slice_get_qindex(struct vdec_av1_slice_uncompressed_header *uh, int segmentation_id) { … } static void vdec_av1_slice_setup_lr(struct vdec_av1_slice_lr *lr, struct v4l2_av1_loop_restoration *ctrl_lr) { … } static void vdec_av1_slice_setup_lf(struct vdec_av1_slice_loop_filter *lf, struct v4l2_av1_loop_filter *ctrl_lf) { … } static void vdec_av1_slice_setup_cdef(struct vdec_av1_slice_cdef *cdef, struct v4l2_av1_cdef *ctrl_cdef) { … } static void vdec_av1_slice_setup_seq(struct vdec_av1_slice_seq_header *seq, struct v4l2_ctrl_av1_sequence *ctrl_seq) { … } static void vdec_av1_slice_setup_tile(struct vdec_av1_slice_frame *frame, struct v4l2_av1_tile_info *ctrl_tile) { … } static void vdec_av1_slice_setup_uh(struct vdec_av1_slice_instance *instance, struct vdec_av1_slice_frame *frame, struct v4l2_ctrl_av1_frame *ctrl_fh) { … } static int vdec_av1_slice_setup_tile_group(struct vdec_av1_slice_instance *instance, struct vdec_av1_slice_vsi *vsi) { … } static inline void vdec_av1_slice_setup_state(struct vdec_av1_slice_vsi *vsi) { … } static void vdec_av1_slice_setup_scale_factors(struct vdec_av1_slice_frame_refs *frame_ref, struct vdec_av1_slice_frame_info *ref_frame_info, struct vdec_av1_slice_uncompressed_header *uh) { … } static unsigned char vdec_av1_slice_get_sign_bias(int a, int b, u8 enable_order_hint, u8 order_hint_bits) { … } static void vdec_av1_slice_setup_ref(struct vdec_av1_slice_pfc *pfc, struct v4l2_ctrl_av1_frame *ctrl_fh) { … } static void vdec_av1_slice_get_previous(struct vdec_av1_slice_vsi *vsi) { … } static inline void vdec_av1_slice_setup_operating_mode(struct vdec_av1_slice_instance *instance, struct vdec_av1_slice_frame *frame) { … } static int vdec_av1_slice_setup_pfc(struct vdec_av1_slice_instance *instance, struct vdec_av1_slice_pfc *pfc) { … } static void vdec_av1_slice_setup_lat_buffer(struct vdec_av1_slice_instance *instance, struct vdec_av1_slice_vsi *vsi, struct mtk_vcodec_mem *bs, struct vdec_lat_buf *lat_buf) { … } static void vdec_av1_slice_setup_seg_buffer(struct vdec_av1_slice_instance *instance, struct vdec_av1_slice_vsi *vsi) { … } static void vdec_av1_slice_setup_tile_buffer(struct vdec_av1_slice_instance *instance, struct vdec_av1_slice_vsi *vsi, struct mtk_vcodec_mem *bs) { … } static int vdec_av1_slice_setup_lat(struct vdec_av1_slice_instance *instance, struct mtk_vcodec_mem *bs, struct vdec_lat_buf *lat_buf, struct vdec_av1_slice_pfc *pfc) { … } static int vdec_av1_slice_update_lat(struct vdec_av1_slice_instance *instance, struct vdec_lat_buf *lat_buf, struct vdec_av1_slice_pfc *pfc) { … } static int vdec_av1_slice_setup_core_to_dst_buf(struct vdec_av1_slice_instance *instance, struct vdec_lat_buf *lat_buf) { … } static int vdec_av1_slice_setup_core_buffer(struct vdec_av1_slice_instance *instance, struct vdec_av1_slice_pfc *pfc, struct vdec_av1_slice_vsi *vsi, struct vdec_fb *fb, struct vdec_lat_buf *lat_buf) { … } static int vdec_av1_slice_setup_core(struct vdec_av1_slice_instance *instance, struct vdec_fb *fb, struct vdec_lat_buf *lat_buf, struct vdec_av1_slice_pfc *pfc) { … } static int vdec_av1_slice_update_core(struct vdec_av1_slice_instance *instance, struct vdec_lat_buf *lat_buf, struct vdec_av1_slice_pfc *pfc) { … } static int vdec_av1_slice_init(struct mtk_vcodec_dec_ctx *ctx) { … } static void vdec_av1_slice_deinit(void *h_vdec) { … } static int vdec_av1_slice_flush(void *h_vdec, struct mtk_vcodec_mem *bs, struct vdec_fb *fb, bool *res_chg) { … } static void vdec_av1_slice_get_pic_info(struct vdec_av1_slice_instance *instance) { … } static inline void vdec_av1_slice_get_dpb_size(struct vdec_av1_slice_instance *instance, u32 *dpb_sz) { … } static void vdec_av1_slice_get_crop_info(struct vdec_av1_slice_instance *instance, struct v4l2_rect *cr) { … } static int vdec_av1_slice_get_param(void *h_vdec, enum vdec_get_param_type type, void *out) { … } static int vdec_av1_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, struct vdec_fb *fb, bool *res_chg) { … } static int vdec_av1_slice_core_decode(struct vdec_lat_buf *lat_buf) { … } const struct vdec_common_if vdec_av1_slice_lat_if = …;