xref: /linux/drivers/media/platform/rockchip/rkvdec/rkvdec-h264-common.c (revision f4b369c6fe0ceaba2da2daff8c9eb415f85926dd)
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