1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Rockchip video decoder h264 common functions 4 * 5 * Copyright (C) 2025 Collabora, Ltd. 6 * Detlev Casanova <detlev.casanova@collabora.com> 7 * 8 * Copyright (C) 2019 Collabora, Ltd. 9 * Boris Brezillon <boris.brezillon@collabora.com> 10 * 11 * Copyright (C) 2016 Rockchip Electronics Co., Ltd. 12 * Jeffy Chen <jeffy.chen@rock-chips.com> 13 */ 14 15 #include <linux/v4l2-common.h> 16 #include <media/v4l2-h264.h> 17 #include <media/v4l2-mem2mem.h> 18 19 #include "rkvdec.h" 20 #include "rkvdec-h264-common.h" 21 22 #define RKVDEC_NUM_REFLIST 3 23 24 static void set_dpb_info(struct rkvdec_rps_entry *entries, 25 u8 reflist, 26 u8 refnum, 27 u8 info, 28 bool bottom) 29 { 30 struct rkvdec_rps_entry *entry = &entries[(reflist * 4) + refnum / 8]; 31 u8 idx = refnum % 8; 32 33 switch (idx) { 34 case 0: 35 entry->dpb_info0 = info; 36 entry->bottom_flag0 = bottom; 37 break; 38 case 1: 39 entry->dpb_info1 = info; 40 entry->bottom_flag1 = bottom; 41 break; 42 case 2: 43 entry->dpb_info2 = info; 44 entry->bottom_flag2 = bottom; 45 break; 46 case 3: 47 entry->dpb_info3 = info; 48 entry->bottom_flag3 = bottom; 49 break; 50 case 4: 51 entry->dpb_info4 = info; 52 entry->bottom_flag4 = bottom; 53 break; 54 case 5: 55 entry->dpb_info5 = info; 56 entry->bottom_flag5 = bottom; 57 break; 58 case 6: 59 entry->dpb_info6 = info; 60 entry->bottom_flag6 = bottom; 61 break; 62 case 7: 63 entry->dpb_info7 = info; 64 entry->bottom_flag7 = bottom; 65 break; 66 } 67 } 68 69 void lookup_ref_buf_idx(struct rkvdec_ctx *ctx, 70 struct rkvdec_h264_run *run) 71 { 72 const struct v4l2_ctrl_h264_decode_params *dec_params = run->decode_params; 73 u32 i; 74 75 for (i = 0; i < ARRAY_SIZE(dec_params->dpb); i++) { 76 struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; 77 const struct v4l2_h264_dpb_entry *dpb = run->decode_params->dpb; 78 struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q; 79 struct vb2_buffer *buf = NULL; 80 81 if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) { 82 buf = vb2_find_buffer(cap_q, dpb[i].reference_ts); 83 if (!buf) 84 pr_debug("No buffer for reference_ts %llu", 85 dpb[i].reference_ts); 86 } 87 88 run->ref_buf[i] = buf; 89 } 90 } 91 92 void assemble_hw_rps(struct v4l2_h264_reflist_builder *builder, 93 struct rkvdec_h264_run *run, 94 struct rkvdec_h264_reflists *reflists, 95 struct rkvdec_rps *hw_rps) 96 { 97 const struct v4l2_ctrl_h264_decode_params *dec_params = run->decode_params; 98 const struct v4l2_h264_dpb_entry *dpb = dec_params->dpb; 99 100 u32 i, j; 101 102 memset(hw_rps, 0, sizeof(*hw_rps)); 103 104 /* 105 * Assign an invalid pic_num if DPB entry at that position is inactive. 106 * If we assign 0 in that position hardware will treat that as a real 107 * reference picture with pic_num 0, triggering output picture 108 * corruption. 109 */ 110 for (i = 0; i < ARRAY_SIZE(dec_params->dpb); i++) { 111 if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) 112 continue; 113 114 hw_rps->frame_num[i] = builder->refs[i].frame_num; 115 } 116 117 for (j = 0; j < RKVDEC_NUM_REFLIST; j++) { 118 for (i = 0; i < builder->num_valid; i++) { 119 struct v4l2_h264_reference *ref; 120 bool dpb_valid; 121 bool bottom; 122 123 switch (j) { 124 case 0: 125 ref = &reflists->p[i]; 126 break; 127 case 1: 128 ref = &reflists->b0[i]; 129 break; 130 case 2: 131 ref = &reflists->b1[i]; 132 break; 133 } 134 135 if (WARN_ON(ref->index >= ARRAY_SIZE(dec_params->dpb))) 136 continue; 137 138 dpb_valid = !!(run->ref_buf[ref->index]); 139 bottom = ref->fields == V4L2_H264_BOTTOM_FIELD_REF; 140 141 set_dpb_info(hw_rps->entries, j, i, ref->index | (dpb_valid << 4), bottom); 142 } 143 } 144 } 145 146 void assemble_hw_scaling_list(struct rkvdec_h264_run *run, 147 struct rkvdec_h264_scaling_list *scaling_list) 148 { 149 const struct v4l2_ctrl_h264_scaling_matrix *scaling = run->scaling_matrix; 150 const struct v4l2_ctrl_h264_pps *pps = run->pps; 151 152 if (!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT)) 153 return; 154 155 BUILD_BUG_ON(sizeof(scaling_list->scaling_list_4x4) != 156 sizeof(scaling->scaling_list_4x4)); 157 BUILD_BUG_ON(sizeof(scaling_list->scaling_list_8x8) != 158 sizeof(scaling->scaling_list_8x8)); 159 160 memcpy(scaling_list->scaling_list_4x4, 161 scaling->scaling_list_4x4, 162 sizeof(scaling->scaling_list_4x4)); 163 164 memcpy(scaling_list->scaling_list_8x8, 165 scaling->scaling_list_8x8, 166 sizeof(scaling->scaling_list_8x8)); 167 } 168 169 #define RKVDEC_H264_MAX_DEPTH_IN_BYTES 2 170 171 int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx, 172 struct v4l2_format *f) 173 { 174 struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp; 175 176 fmt->num_planes = 1; 177 if (!fmt->plane_fmt[0].sizeimage) 178 fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * 179 RKVDEC_H264_MAX_DEPTH_IN_BYTES; 180 return 0; 181 } 182 183 enum rkvdec_image_fmt rkvdec_h264_get_image_fmt(struct rkvdec_ctx *ctx, 184 struct v4l2_ctrl *ctrl) 185 { 186 const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps; 187 188 if (ctrl->id != V4L2_CID_STATELESS_H264_SPS) 189 return RKVDEC_IMG_FMT_ANY; 190 191 if (sps->bit_depth_luma_minus8 == 0) { 192 if (sps->chroma_format_idc == 2) 193 return RKVDEC_IMG_FMT_422_8BIT; 194 else 195 return RKVDEC_IMG_FMT_420_8BIT; 196 } else if (sps->bit_depth_luma_minus8 == 2) { 197 if (sps->chroma_format_idc == 2) 198 return RKVDEC_IMG_FMT_422_10BIT; 199 else 200 return RKVDEC_IMG_FMT_420_10BIT; 201 } 202 203 return RKVDEC_IMG_FMT_ANY; 204 } 205 206 int rkvdec_h264_validate_sps(struct rkvdec_ctx *ctx, 207 const struct v4l2_ctrl_h264_sps *sps) 208 { 209 unsigned int width, height; 210 211 if (sps->chroma_format_idc > 2) 212 /* Only 4:0:0, 4:2:0 and 4:2:2 are supported */ 213 return -EINVAL; 214 if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8) 215 /* Luma and chroma bit depth mismatch */ 216 return -EINVAL; 217 if (sps->bit_depth_luma_minus8 != 0 && sps->bit_depth_luma_minus8 != 2) 218 /* Only 8-bit and 10-bit is supported */ 219 return -EINVAL; 220 221 width = (sps->pic_width_in_mbs_minus1 + 1) * 16; 222 height = (sps->pic_height_in_map_units_minus1 + 1) * 16; 223 224 /* 225 * When frame_mbs_only_flag is not set, this is field height, 226 * which is half the final height (see (7-18) in the 227 * specification) 228 */ 229 if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY)) 230 height *= 2; 231 232 if (width > ctx->coded_fmt.fmt.pix_mp.width || 233 height > ctx->coded_fmt.fmt.pix_mp.height) 234 return -EINVAL; 235 236 return 0; 237 } 238 239 void rkvdec_h264_run_preamble(struct rkvdec_ctx *ctx, 240 struct rkvdec_h264_run *run) 241 { 242 struct v4l2_ctrl *ctrl; 243 244 ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, 245 V4L2_CID_STATELESS_H264_DECODE_PARAMS); 246 run->decode_params = ctrl ? ctrl->p_cur.p : NULL; 247 ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, 248 V4L2_CID_STATELESS_H264_SPS); 249 run->sps = ctrl ? ctrl->p_cur.p : NULL; 250 ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, 251 V4L2_CID_STATELESS_H264_PPS); 252 run->pps = ctrl ? ctrl->p_cur.p : NULL; 253 ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, 254 V4L2_CID_STATELESS_H264_SCALING_MATRIX); 255 run->scaling_matrix = ctrl ? ctrl->p_cur.p : NULL; 256 257 rkvdec_run_preamble(ctx, &run->base); 258 } 259