xref: /linux/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c (revision 546b928da0427b0d6c663cbb992bd7bfa9ac7971)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Rockchip video decoder hevc common functions
4  *
5  * Copyright (C) 2025 Collabora, Ltd.
6  *      Detlev Casanova <detlev.casanova@collabora.com>
7  *
8  * Copyright (C) 2023 Collabora, Ltd.
9  *      Sebastian Fricke <sebastian.fricke@collabora.com>
10  *
11  * Copyright (C) 2019 Collabora, Ltd.
12  *	Boris Brezillon <boris.brezillon@collabora.com>
13  *
14  * Copyright (C) 2016 Rockchip Electronics Co., Ltd.
15  *	Jeffy Chen <jeffy.chen@rock-chips.com>
16  */
17 
18 #include <linux/v4l2-common.h>
19 #include <media/v4l2-hevc.h>
20 #include <media/v4l2-mem2mem.h>
21 
22 #include "rkvdec.h"
23 #include "rkvdec-hevc-common.h"
24 
25 /* Store the Short term ref pic set calculated values */
26 struct calculated_rps_st_set {
27 	u8 num_delta_pocs;
28 	u8 num_negative_pics;
29 	u8 num_positive_pics;
30 	u8 used_by_curr_pic_s0[16];
31 	u8 used_by_curr_pic_s1[16];
32 	s32 delta_poc_s0[16];
33 	s32 delta_poc_s1[16];
34 };
35 
compute_tiles_uniform(struct rkvdec_hevc_run * run,u16 log2_min_cb_size,u16 width,u16 height,s32 pic_in_cts_width,s32 pic_in_cts_height,u16 * column_width,u16 * row_height)36 void compute_tiles_uniform(struct rkvdec_hevc_run *run, u16 log2_min_cb_size,
37 			   u16 width, u16 height, s32 pic_in_cts_width,
38 			   s32 pic_in_cts_height, u16 *column_width, u16 *row_height)
39 {
40 	const struct v4l2_ctrl_hevc_pps *pps = run->pps;
41 	unsigned int num_cols = v4l2_hevc_pps_num_tile_columns(pps);
42 	unsigned int num_rows = v4l2_hevc_pps_num_tile_rows(pps);
43 	int i;
44 
45 	for (i = 0; i < num_cols; i++)
46 		column_width[i] = ((i + 1) * pic_in_cts_width) /
47 				  (pps->num_tile_columns_minus1 + 1) -
48 				  (i * pic_in_cts_width) /
49 				  (pps->num_tile_columns_minus1 + 1);
50 
51 	for (i = 0; i < num_rows; i++)
52 		row_height[i] = ((i + 1) * pic_in_cts_height) /
53 				(pps->num_tile_rows_minus1 + 1) -
54 				(i * pic_in_cts_height) /
55 				(pps->num_tile_rows_minus1 + 1);
56 }
57 
compute_tiles_non_uniform(struct rkvdec_hevc_run * run,u16 log2_min_cb_size,u16 width,u16 height,s32 pic_in_cts_width,s32 pic_in_cts_height,u16 * column_width,u16 * row_height)58 void compute_tiles_non_uniform(struct rkvdec_hevc_run *run, u16 log2_min_cb_size,
59 			       u16 width, u16 height, s32 pic_in_cts_width,
60 			       s32 pic_in_cts_height, u16 *column_width, u16 *row_height)
61 {
62 	const struct v4l2_ctrl_hevc_pps *pps = run->pps;
63 	unsigned int num_cols = v4l2_hevc_pps_num_tile_columns(pps);
64 	unsigned int num_rows = v4l2_hevc_pps_num_tile_rows(pps);
65 	s32 sum = 0;
66 	int i;
67 
68 	/* The last tile entry is written after the loop, so iterate one less. */
69 	for (i = 0; i < num_cols - 1; i++) {
70 		column_width[i] = pps->column_width_minus1[i] + 1;
71 		sum += column_width[i];
72 	}
73 	column_width[i] = pic_in_cts_width - sum;
74 
75 	sum = 0;
76 	for (i = 0; i < num_rows - 1; i++) {
77 		row_height[i] = pps->row_height_minus1[i] + 1;
78 		sum += row_height[i];
79 	}
80 	row_height[i] = pic_in_cts_height - sum;
81 }
82 
assemble_scalingfactor0(struct rkvdec_ctx * ctx,u8 * output,const struct v4l2_ctrl_hevc_scaling_matrix * input)83 static void assemble_scalingfactor0(struct rkvdec_ctx *ctx, u8 *output,
84 				    const struct v4l2_ctrl_hevc_scaling_matrix *input)
85 {
86 	const struct rkvdec_variant *variant = ctx->dev->variant;
87 	int offset = 0;
88 
89 	variant->ops->flatten_matrices(output, (const u8 *)input->scaling_list_4x4, 6, 4);
90 	offset = 6 * 16 * sizeof(u8);
91 	variant->ops->flatten_matrices(output + offset, (const u8 *)input->scaling_list_8x8, 6, 8);
92 	offset += 6 * 64 * sizeof(u8);
93 	variant->ops->flatten_matrices(output + offset, (const u8 *)input->scaling_list_16x16,
94 				       6, 8);
95 	offset += 6 * 64 * sizeof(u8);
96 	/* Add a 128 byte padding with 0s between the two 32x32 matrices */
97 	variant->ops->flatten_matrices(output + offset, (const u8 *)input->scaling_list_32x32,
98 				       1, 8);
99 	offset += 64 * sizeof(u8);
100 	memset(output + offset, 0, 128);
101 	offset += 128 * sizeof(u8);
102 	variant->ops->flatten_matrices(output + offset,
103 				       (const u8 *)input->scaling_list_32x32 + (64 * sizeof(u8)),
104 				       1, 8);
105 	offset += 64 * sizeof(u8);
106 	memset(output + offset, 0, 128);
107 }
108 
109 /*
110  * Required layout:
111  * A = scaling_list_dc_coef_16x16
112  * B = scaling_list_dc_coef_32x32
113  * 0 = Padding
114  *
115  * A, A, A, A, A, A, B, 0, 0, B, 0, 0
116  */
assemble_scalingdc(u8 * output,const struct v4l2_ctrl_hevc_scaling_matrix * input)117 static void assemble_scalingdc(u8 *output, const struct v4l2_ctrl_hevc_scaling_matrix *input)
118 {
119 	u8 list_32x32[6] = {0};
120 
121 	memcpy(output, input->scaling_list_dc_coef_16x16, 6 * sizeof(u8));
122 	list_32x32[0] = input->scaling_list_dc_coef_32x32[0];
123 	list_32x32[3] = input->scaling_list_dc_coef_32x32[1];
124 	memcpy(output + 6 * sizeof(u8), list_32x32, 6 * sizeof(u8));
125 }
126 
translate_scaling_list(struct rkvdec_ctx * ctx,struct scaling_factor * output,const struct v4l2_ctrl_hevc_scaling_matrix * input)127 static void translate_scaling_list(struct rkvdec_ctx *ctx, struct scaling_factor *output,
128 				   const struct v4l2_ctrl_hevc_scaling_matrix *input)
129 {
130 	assemble_scalingfactor0(ctx, output->scalingfactor0, input);
131 	memcpy(output->scalingfactor1, (const u8 *)input->scaling_list_4x4, 96);
132 	assemble_scalingdc(output->scalingdc, input);
133 	memset(output->reserved, 0, 4 * sizeof(u8));
134 }
135 
rkvdec_hevc_assemble_hw_scaling_list(struct rkvdec_ctx * ctx,struct rkvdec_hevc_run * run,struct scaling_factor * scaling_factor,struct v4l2_ctrl_hevc_scaling_matrix * cache)136 void rkvdec_hevc_assemble_hw_scaling_list(struct rkvdec_ctx *ctx,
137 					  struct rkvdec_hevc_run *run,
138 					  struct scaling_factor *scaling_factor,
139 					  struct v4l2_ctrl_hevc_scaling_matrix *cache)
140 {
141 	const struct v4l2_ctrl_hevc_scaling_matrix *scaling = run->scaling_matrix;
142 
143 	if (!memcmp(cache, scaling,
144 		    sizeof(struct v4l2_ctrl_hevc_scaling_matrix)))
145 		return;
146 
147 	translate_scaling_list(ctx, scaling_factor, scaling);
148 
149 	memcpy(cache, scaling,
150 	       sizeof(struct v4l2_ctrl_hevc_scaling_matrix));
151 }
152 
rkvdec_hevc_assemble_hw_lt_rps(struct rkvdec_hevc_run * run,struct rkvdec_rps * rps)153 static void rkvdec_hevc_assemble_hw_lt_rps(struct rkvdec_hevc_run *run, struct rkvdec_rps *rps)
154 {
155 	const struct v4l2_ctrl_hevc_sps *sps = run->sps;
156 
157 	if (!run->ext_sps_lt_rps)
158 		return;
159 
160 	for (int i = 0; i < sps->num_long_term_ref_pics_sps; i++) {
161 		rkvdec_set_bw_field(rps->info, RPS_LT_REF_PIC_POC_LSB(i),
162 				    run->ext_sps_lt_rps[i].lt_ref_pic_poc_lsb_sps);
163 		rkvdec_set_bw_field(rps->info, RPS_LT_REF_USED_BY_CURR_PIC(i),
164 				    !!(run->ext_sps_lt_rps[i].flags &
165 				       V4L2_HEVC_EXT_SPS_LT_RPS_FLAG_USED_LT));
166 	}
167 }
168 
rkvdec_hevc_assemble_hw_st_rps(struct rkvdec_hevc_run * run,struct rkvdec_rps * rps,struct calculated_rps_st_set * calculated_rps_st_sets)169 static void rkvdec_hevc_assemble_hw_st_rps(struct rkvdec_hevc_run *run, struct rkvdec_rps *rps,
170 					   struct calculated_rps_st_set *calculated_rps_st_sets)
171 {
172 	const struct v4l2_ctrl_hevc_sps *sps = run->sps;
173 
174 	for (int i = 0; i < sps->num_short_term_ref_pic_sets; i++) {
175 		int poc = 0;
176 		int j = 0;
177 		const struct calculated_rps_st_set *set = &calculated_rps_st_sets[i];
178 
179 		rkvdec_set_bw_field(rps->info, RPS_ST_REF_SET_NUM_NEGATIVE(i),
180 				    set->num_negative_pics);
181 		rkvdec_set_bw_field(rps->info, RPS_ST_REF_SET_NUM_POSITIVE(i),
182 				    set->num_positive_pics);
183 
184 		for (; j < set->num_negative_pics; j++) {
185 			rkvdec_set_bw_field(rps->info, RPS_ST_REF_SET_DELTA_POC(i, j),
186 					    set->delta_poc_s0[j]);
187 			rkvdec_set_bw_field(rps->info, RPS_ST_REF_SET_USED(i, j),
188 					    set->used_by_curr_pic_s0[j]);
189 		}
190 		poc = j;
191 
192 		for (j = 0; j < set->num_positive_pics; j++) {
193 			rkvdec_set_bw_field(rps->info, RPS_ST_REF_SET_DELTA_POC(i, poc + j),
194 					    set->delta_poc_s1[j]);
195 			rkvdec_set_bw_field(rps->info, RPS_ST_REF_SET_USED(i, poc + j),
196 					    set->used_by_curr_pic_s1[j]);
197 		}
198 	}
199 }
200 
201 /*
202  * Compute the short term ref pic set parameters based on its reference short term ref pic
203  */
st_ref_pic_set_prediction(struct rkvdec_hevc_run * run,int idx,struct calculated_rps_st_set * calculated_rps_st_sets)204 static void st_ref_pic_set_prediction(struct rkvdec_hevc_run *run, int idx,
205 				      struct calculated_rps_st_set *calculated_rps_st_sets)
206 {
207 	const struct v4l2_ctrl_hevc_ext_sps_st_rps *rps_data = &run->ext_sps_st_rps[idx];
208 	struct calculated_rps_st_set *st_rps = &calculated_rps_st_sets[idx];
209 	struct calculated_rps_st_set *ref_rps;
210 	u8 st_rps_idx = idx;
211 	u8 ref_rps_idx = 0;
212 	s16 delta_rps = 0;
213 	u8 use_delta_flag[16] = { 0 };
214 	u8 used_by_curr_pic_flag[16] = { 0 };
215 	int i, j;
216 	int dPoc;
217 
218 	if ((unsigned int)rps_data->delta_idx_minus1 + 1 > idx)
219 		return;
220 
221 	ref_rps_idx = st_rps_idx - (rps_data->delta_idx_minus1 + 1); /* 7-59 */
222 	delta_rps = (1 - 2 * rps_data->delta_rps_sign) *
223 		   (rps_data->abs_delta_rps_minus1 + 1); /* 7-60 */
224 
225 	ref_rps = &calculated_rps_st_sets[ref_rps_idx];
226 
227 	for (j = 0; j <= ref_rps->num_delta_pocs; j++) {
228 		used_by_curr_pic_flag[j] = !!(rps_data->used_by_curr_pic & (1 << j));
229 		use_delta_flag[j] = !!(rps_data->use_delta_flag & (1 << j));
230 	}
231 
232 	/* 7-61: calculate num_negative_pics, delta_poc_s0 and used_by_curr_pic_s0 */
233 	i = 0;
234 	for (j = (ref_rps->num_positive_pics - 1); j >= 0; j--) {
235 		dPoc = ref_rps->delta_poc_s1[j] + delta_rps;
236 		if (dPoc < 0 && use_delta_flag[ref_rps->num_negative_pics + j]) {
237 			st_rps->delta_poc_s0[i] = dPoc;
238 			st_rps->used_by_curr_pic_s0[i++] =
239 				used_by_curr_pic_flag[ref_rps->num_negative_pics + j];
240 		}
241 	}
242 	if (delta_rps < 0 && use_delta_flag[ref_rps->num_delta_pocs]) {
243 		st_rps->delta_poc_s0[i] = delta_rps;
244 		st_rps->used_by_curr_pic_s0[i++] = used_by_curr_pic_flag[ref_rps->num_delta_pocs];
245 	}
246 	for (j = 0; j < ref_rps->num_negative_pics; j++) {
247 		dPoc = ref_rps->delta_poc_s0[j] + delta_rps;
248 		if (dPoc < 0 && use_delta_flag[j]) {
249 			st_rps->delta_poc_s0[i] = dPoc;
250 			st_rps->used_by_curr_pic_s0[i++] = used_by_curr_pic_flag[j];
251 		}
252 	}
253 	st_rps->num_negative_pics = i;
254 
255 	/* 7-62: calculate num_positive_pics, delta_poc_s1 and used_by_curr_pic_s1 */
256 	i = 0;
257 	for (j = (ref_rps->num_negative_pics - 1); j >= 0; j--) {
258 		dPoc = ref_rps->delta_poc_s0[j] + delta_rps;
259 		if (dPoc > 0 && use_delta_flag[j]) {
260 			st_rps->delta_poc_s1[i] = dPoc;
261 			st_rps->used_by_curr_pic_s1[i++] = used_by_curr_pic_flag[j];
262 		}
263 	}
264 	if (delta_rps > 0 && use_delta_flag[ref_rps->num_delta_pocs]) {
265 		st_rps->delta_poc_s1[i] = delta_rps;
266 		st_rps->used_by_curr_pic_s1[i++] = used_by_curr_pic_flag[ref_rps->num_delta_pocs];
267 	}
268 	for (j = 0; j < ref_rps->num_positive_pics; j++) {
269 		dPoc = ref_rps->delta_poc_s1[j] + delta_rps;
270 		if (dPoc > 0 && use_delta_flag[ref_rps->num_negative_pics + j]) {
271 			st_rps->delta_poc_s1[i] = dPoc;
272 			st_rps->used_by_curr_pic_s1[i++] =
273 				used_by_curr_pic_flag[ref_rps->num_negative_pics + j];
274 		}
275 	}
276 	st_rps->num_positive_pics = i;
277 
278 	st_rps->num_delta_pocs = st_rps->num_positive_pics + st_rps->num_negative_pics;
279 }
280 
281 /*
282  * Compute the short term ref pic set parameters based on the control's data.
283  */
st_ref_pic_set_calculate(struct rkvdec_hevc_run * run,int idx,struct calculated_rps_st_set * calculated_rps_st_sets)284 static void st_ref_pic_set_calculate(struct rkvdec_hevc_run *run, int idx,
285 				     struct calculated_rps_st_set *calculated_rps_st_sets)
286 {
287 	const struct v4l2_ctrl_hevc_ext_sps_st_rps *rps_data = &run->ext_sps_st_rps[idx];
288 	struct calculated_rps_st_set *st_rps = &calculated_rps_st_sets[idx];
289 	int j, i = 0;
290 
291 	/* 7-63 */
292 	st_rps->num_negative_pics = rps_data->num_negative_pics;
293 	/* 7-64 */
294 	st_rps->num_positive_pics = rps_data->num_positive_pics;
295 
296 	for (i = 0; i < st_rps->num_negative_pics; i++) {
297 		/* 7-65 */
298 		st_rps->used_by_curr_pic_s0[i] = !!(rps_data->used_by_curr_pic & (1 << i));
299 
300 		if (i == 0) {
301 			/* 7-67 */
302 			st_rps->delta_poc_s0[i] = -(rps_data->delta_poc_s0_minus1[i] + 1);
303 		} else {
304 			/* 7-69 */
305 			st_rps->delta_poc_s0[i] =
306 				st_rps->delta_poc_s0[i - 1] -
307 				(rps_data->delta_poc_s0_minus1[i] + 1);
308 		}
309 	}
310 
311 	for (j = 0; j < st_rps->num_positive_pics; j++) {
312 		/* 7-66 */
313 		st_rps->used_by_curr_pic_s1[j] = !!(rps_data->used_by_curr_pic & (1 << (i + j)));
314 
315 		if (j == 0) {
316 			/* 7-68 */
317 			st_rps->delta_poc_s1[j] = rps_data->delta_poc_s1_minus1[j] + 1;
318 		} else {
319 			/* 7-70 */
320 			st_rps->delta_poc_s1[j] =
321 				st_rps->delta_poc_s1[j - 1] +
322 				(rps_data->delta_poc_s1_minus1[j] + 1);
323 		}
324 	}
325 
326 	/* 7-71 */
327 	st_rps->num_delta_pocs = st_rps->num_positive_pics + st_rps->num_negative_pics;
328 }
329 
rkvdec_hevc_prepare_hw_st_rps(struct rkvdec_hevc_run * run,struct rkvdec_rps * rps,struct v4l2_ctrl_hevc_ext_sps_st_rps * cache)330 static void rkvdec_hevc_prepare_hw_st_rps(struct rkvdec_hevc_run *run, struct rkvdec_rps *rps,
331 					  struct v4l2_ctrl_hevc_ext_sps_st_rps *cache)
332 {
333 	int idx;
334 
335 	if (!run->ext_sps_st_rps)
336 		return;
337 
338 	if (!memcmp(cache, run->ext_sps_st_rps, sizeof(struct v4l2_ctrl_hevc_ext_sps_st_rps)))
339 		return;
340 
341 	struct calculated_rps_st_set *calculated_rps_st_sets =
342 		kzalloc(sizeof(struct calculated_rps_st_set) *
343 			run->sps->num_short_term_ref_pic_sets, GFP_KERNEL);
344 
345 	for (idx = 0; idx < run->sps->num_short_term_ref_pic_sets; idx++) {
346 		const struct v4l2_ctrl_hevc_ext_sps_st_rps *rps_data = &run->ext_sps_st_rps[idx];
347 
348 		if (rps_data->flags & V4L2_HEVC_EXT_SPS_ST_RPS_FLAG_INTER_REF_PIC_SET_PRED)
349 			st_ref_pic_set_prediction(run, idx, calculated_rps_st_sets);
350 		else
351 			st_ref_pic_set_calculate(run, idx, calculated_rps_st_sets);
352 	}
353 
354 	rkvdec_hevc_assemble_hw_st_rps(run, rps, calculated_rps_st_sets);
355 
356 	kfree(calculated_rps_st_sets);
357 
358 	memcpy(cache, run->ext_sps_st_rps, sizeof(struct v4l2_ctrl_hevc_ext_sps_st_rps));
359 }
360 
rkvdec_hevc_assemble_hw_rps(struct rkvdec_hevc_run * run,struct rkvdec_rps * rps,struct v4l2_ctrl_hevc_ext_sps_st_rps * st_cache)361 void rkvdec_hevc_assemble_hw_rps(struct rkvdec_hevc_run *run, struct rkvdec_rps *rps,
362 				 struct v4l2_ctrl_hevc_ext_sps_st_rps *st_cache)
363 {
364 	rkvdec_hevc_prepare_hw_st_rps(run, rps, st_cache);
365 	rkvdec_hevc_assemble_hw_lt_rps(run, rps);
366 }
367 
368 struct vb2_buffer *
get_ref_buf(struct rkvdec_ctx * ctx,struct rkvdec_hevc_run * run,unsigned int dpb_idx)369 get_ref_buf(struct rkvdec_ctx *ctx, struct rkvdec_hevc_run *run,
370 	    unsigned int dpb_idx)
371 {
372 	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
373 	const struct v4l2_ctrl_hevc_decode_params *decode_params = run->decode_params;
374 	const struct v4l2_hevc_dpb_entry *dpb = decode_params->dpb;
375 	struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q;
376 	struct vb2_buffer *buf = NULL;
377 
378 	if (dpb_idx < decode_params->num_active_dpb_entries)
379 		buf = vb2_find_buffer(cap_q, dpb[dpb_idx].timestamp);
380 
381 	/*
382 	 * If a DPB entry is unused or invalid, the address of current destination
383 	 * buffer is returned.
384 	 */
385 	if (!buf)
386 		return &run->base.bufs.dst->vb2_buf;
387 
388 	return buf;
389 }
390 
391 #define RKVDEC_HEVC_MAX_DEPTH_IN_BYTES		2
392 
rkvdec_hevc_adjust_fmt(struct rkvdec_ctx * ctx,struct v4l2_format * f)393 int rkvdec_hevc_adjust_fmt(struct rkvdec_ctx *ctx, struct v4l2_format *f)
394 {
395 	struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp;
396 
397 	fmt->num_planes = 1;
398 	if (!fmt->plane_fmt[0].sizeimage)
399 		fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height *
400 					      RKVDEC_HEVC_MAX_DEPTH_IN_BYTES;
401 	return 0;
402 }
403 
rkvdec_hevc_get_image_fmt(struct rkvdec_ctx * ctx,struct v4l2_ctrl * ctrl)404 enum rkvdec_image_fmt rkvdec_hevc_get_image_fmt(struct rkvdec_ctx *ctx,
405 						struct v4l2_ctrl *ctrl)
406 {
407 	const struct v4l2_ctrl_hevc_sps *sps = ctrl->p_new.p_hevc_sps;
408 
409 	if (ctrl->id != V4L2_CID_STATELESS_HEVC_SPS)
410 		return RKVDEC_IMG_FMT_ANY;
411 
412 	if (sps->bit_depth_luma_minus8 == 0) {
413 		if (sps->chroma_format_idc == 2)
414 			return RKVDEC_IMG_FMT_422_8BIT;
415 		else
416 			return RKVDEC_IMG_FMT_420_8BIT;
417 	} else if (sps->bit_depth_luma_minus8 == 2) {
418 		if (sps->chroma_format_idc == 2)
419 			return RKVDEC_IMG_FMT_422_10BIT;
420 		else
421 			return RKVDEC_IMG_FMT_420_10BIT;
422 	}
423 
424 	return RKVDEC_IMG_FMT_ANY;
425 }
426 
rkvdec_hevc_run_preamble(struct rkvdec_ctx * ctx,struct rkvdec_hevc_run * run)427 void rkvdec_hevc_run_preamble(struct rkvdec_ctx *ctx,
428 			      struct rkvdec_hevc_run *run)
429 {
430 	struct v4l2_ctrl *ctrl;
431 
432 	ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
433 			      V4L2_CID_STATELESS_HEVC_DECODE_PARAMS);
434 	run->decode_params = ctrl ? ctrl->p_cur.p : NULL;
435 	ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
436 			      V4L2_CID_STATELESS_HEVC_SLICE_PARAMS);
437 	run->slices_params = ctrl ? ctrl->p_cur.p : NULL;
438 	run->num_slices = ctrl ? ctrl->new_elems : 0;
439 	ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
440 			      V4L2_CID_STATELESS_HEVC_SPS);
441 	run->sps = ctrl ? ctrl->p_cur.p : NULL;
442 	ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
443 			      V4L2_CID_STATELESS_HEVC_PPS);
444 	run->pps = ctrl ? ctrl->p_cur.p : NULL;
445 	ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
446 			      V4L2_CID_STATELESS_HEVC_SCALING_MATRIX);
447 	run->scaling_matrix = ctrl ? ctrl->p_cur.p : NULL;
448 
449 	if (ctx->has_sps_st_rps) {
450 		ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
451 				      V4L2_CID_STATELESS_HEVC_EXT_SPS_ST_RPS);
452 		run->ext_sps_st_rps = ctrl ? ctrl->p_cur.p : NULL;
453 	} else {
454 		run->ext_sps_st_rps = NULL;
455 	}
456 	if (ctx->has_sps_lt_rps) {
457 		ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
458 				      V4L2_CID_STATELESS_HEVC_EXT_SPS_LT_RPS);
459 		run->ext_sps_lt_rps = ctrl ? ctrl->p_cur.p : NULL;
460 	} else {
461 		run->ext_sps_lt_rps = NULL;
462 	}
463 
464 	rkvdec_run_preamble(ctx, &run->base);
465 }
466