Skip to content

Commit 34e2b14

Browse files
cazouHans Verkuil
authored andcommitted
media: rkvdec: Move hevc functions to common file
This is a preparation commit to add support for new variants of the decoder. The functions will later be shared with vdpu381 (rk3588) and vdpu383 (rk3576). Tested-by: Diederik de Haas <didi.debian@cknow.org> # Rock 5B Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com> Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com> Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com> Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
1 parent 560438e commit 34e2b14

4 files changed

Lines changed: 260 additions & 207 deletions

File tree

drivers/media/platform/rockchip/rkvdec/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ rockchip-vdec-y += \
66
rkvdec-h264.o \
77
rkvdec-h264-common.o \
88
rkvdec-hevc.o \
9+
rkvdec-hevc-common.o \
910
rkvdec-vp9.o
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
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-mem2mem.h>
20+
21+
#include "rkvdec.h"
22+
#include "rkvdec-hevc-common.h"
23+
24+
/*
25+
* Flip one or more matrices along their main diagonal and flatten them
26+
* before writing it to the memory.
27+
* Convert:
28+
* ABCD AEIM
29+
* EFGH => BFJN => AEIMBFJNCGKODHLP
30+
* IJKL CGKO
31+
* MNOP DHLP
32+
*/
33+
static void transpose_and_flatten_matrices(u8 *output, const u8 *input,
34+
int matrices, int row_length)
35+
{
36+
int i, j, row, x_offset, matrix_offset, rot_index, y_offset, matrix_size, new_value;
37+
38+
matrix_size = row_length * row_length;
39+
for (i = 0; i < matrices; i++) {
40+
row = 0;
41+
x_offset = 0;
42+
matrix_offset = i * matrix_size;
43+
for (j = 0; j < matrix_size; j++) {
44+
y_offset = j - (row * row_length);
45+
rot_index = y_offset * row_length + x_offset;
46+
new_value = *(input + i * matrix_size + j);
47+
output[matrix_offset + rot_index] = new_value;
48+
if ((j + 1) % row_length == 0) {
49+
row += 1;
50+
x_offset += 1;
51+
}
52+
}
53+
}
54+
}
55+
56+
static void assemble_scalingfactor0(u8 *output, const struct v4l2_ctrl_hevc_scaling_matrix *input)
57+
{
58+
int offset = 0;
59+
60+
transpose_and_flatten_matrices(output, (const u8 *)input->scaling_list_4x4, 6, 4);
61+
offset = 6 * 16 * sizeof(u8);
62+
transpose_and_flatten_matrices(output + offset, (const u8 *)input->scaling_list_8x8, 6, 8);
63+
offset += 6 * 64 * sizeof(u8);
64+
transpose_and_flatten_matrices(output + offset,
65+
(const u8 *)input->scaling_list_16x16, 6, 8);
66+
offset += 6 * 64 * sizeof(u8);
67+
/* Add a 128 byte padding with 0s between the two 32x32 matrices */
68+
transpose_and_flatten_matrices(output + offset,
69+
(const u8 *)input->scaling_list_32x32, 1, 8);
70+
offset += 64 * sizeof(u8);
71+
memset(output + offset, 0, 128);
72+
offset += 128 * sizeof(u8);
73+
transpose_and_flatten_matrices(output + offset,
74+
(const u8 *)input->scaling_list_32x32 + (64 * sizeof(u8)),
75+
1, 8);
76+
offset += 64 * sizeof(u8);
77+
memset(output + offset, 0, 128);
78+
}
79+
80+
/*
81+
* Required layout:
82+
* A = scaling_list_dc_coef_16x16
83+
* B = scaling_list_dc_coef_32x32
84+
* 0 = Padding
85+
*
86+
* A, A, A, A, A, A, B, 0, 0, B, 0, 0
87+
*/
88+
static void assemble_scalingdc(u8 *output, const struct v4l2_ctrl_hevc_scaling_matrix *input)
89+
{
90+
u8 list_32x32[6] = {0};
91+
92+
memcpy(output, input->scaling_list_dc_coef_16x16, 6 * sizeof(u8));
93+
list_32x32[0] = input->scaling_list_dc_coef_32x32[0];
94+
list_32x32[3] = input->scaling_list_dc_coef_32x32[1];
95+
memcpy(output + 6 * sizeof(u8), list_32x32, 6 * sizeof(u8));
96+
}
97+
98+
static void translate_scaling_list(struct scaling_factor *output,
99+
const struct v4l2_ctrl_hevc_scaling_matrix *input)
100+
{
101+
assemble_scalingfactor0(output->scalingfactor0, input);
102+
memcpy(output->scalingfactor1, (const u8 *)input->scaling_list_4x4, 96);
103+
assemble_scalingdc(output->scalingdc, input);
104+
memset(output->reserved, 0, 4 * sizeof(u8));
105+
}
106+
107+
void rkvdec_hevc_assemble_hw_scaling_list(struct rkvdec_hevc_run *run,
108+
struct scaling_factor *scaling_factor,
109+
struct v4l2_ctrl_hevc_scaling_matrix *cache)
110+
{
111+
const struct v4l2_ctrl_hevc_scaling_matrix *scaling = run->scaling_matrix;
112+
113+
if (!memcmp(cache, scaling,
114+
sizeof(struct v4l2_ctrl_hevc_scaling_matrix)))
115+
return;
116+
117+
translate_scaling_list(scaling_factor, scaling);
118+
119+
memcpy(cache, scaling,
120+
sizeof(struct v4l2_ctrl_hevc_scaling_matrix));
121+
}
122+
123+
struct vb2_buffer *
124+
get_ref_buf(struct rkvdec_ctx *ctx, struct rkvdec_hevc_run *run,
125+
unsigned int dpb_idx)
126+
{
127+
struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
128+
const struct v4l2_ctrl_hevc_decode_params *decode_params = run->decode_params;
129+
const struct v4l2_hevc_dpb_entry *dpb = decode_params->dpb;
130+
struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q;
131+
struct vb2_buffer *buf = NULL;
132+
133+
if (dpb_idx < decode_params->num_active_dpb_entries)
134+
buf = vb2_find_buffer(cap_q, dpb[dpb_idx].timestamp);
135+
136+
/*
137+
* If a DPB entry is unused or invalid, the address of current destination
138+
* buffer is returned.
139+
*/
140+
if (!buf)
141+
return &run->base.bufs.dst->vb2_buf;
142+
143+
return buf;
144+
}
145+
146+
#define RKVDEC_HEVC_MAX_DEPTH_IN_BYTES 2
147+
148+
int rkvdec_hevc_adjust_fmt(struct rkvdec_ctx *ctx, struct v4l2_format *f)
149+
{
150+
struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp;
151+
152+
fmt->num_planes = 1;
153+
if (!fmt->plane_fmt[0].sizeimage)
154+
fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height *
155+
RKVDEC_HEVC_MAX_DEPTH_IN_BYTES;
156+
return 0;
157+
}
158+
159+
enum rkvdec_image_fmt rkvdec_hevc_get_image_fmt(struct rkvdec_ctx *ctx,
160+
struct v4l2_ctrl *ctrl)
161+
{
162+
const struct v4l2_ctrl_hevc_sps *sps = ctrl->p_new.p_hevc_sps;
163+
164+
if (ctrl->id != V4L2_CID_STATELESS_HEVC_SPS)
165+
return RKVDEC_IMG_FMT_ANY;
166+
167+
if (sps->bit_depth_luma_minus8 == 0) {
168+
if (sps->chroma_format_idc == 2)
169+
return RKVDEC_IMG_FMT_422_8BIT;
170+
else
171+
return RKVDEC_IMG_FMT_420_8BIT;
172+
} else if (sps->bit_depth_luma_minus8 == 2) {
173+
if (sps->chroma_format_idc == 2)
174+
return RKVDEC_IMG_FMT_422_10BIT;
175+
else
176+
return RKVDEC_IMG_FMT_420_10BIT;
177+
}
178+
179+
return RKVDEC_IMG_FMT_ANY;
180+
}
181+
182+
void rkvdec_hevc_run_preamble(struct rkvdec_ctx *ctx,
183+
struct rkvdec_hevc_run *run)
184+
{
185+
struct v4l2_ctrl *ctrl;
186+
187+
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
188+
V4L2_CID_STATELESS_HEVC_DECODE_PARAMS);
189+
run->decode_params = ctrl ? ctrl->p_cur.p : NULL;
190+
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
191+
V4L2_CID_STATELESS_HEVC_SLICE_PARAMS);
192+
run->slices_params = ctrl ? ctrl->p_cur.p : NULL;
193+
run->num_slices = ctrl ? ctrl->new_elems : 0;
194+
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
195+
V4L2_CID_STATELESS_HEVC_SPS);
196+
run->sps = ctrl ? ctrl->p_cur.p : NULL;
197+
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
198+
V4L2_CID_STATELESS_HEVC_PPS);
199+
run->pps = ctrl ? ctrl->p_cur.p : NULL;
200+
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
201+
V4L2_CID_STATELESS_HEVC_SCALING_MATRIX);
202+
run->scaling_matrix = ctrl ? ctrl->p_cur.p : NULL;
203+
204+
rkvdec_run_preamble(ctx, &run->base);
205+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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 <media/v4l2-mem2mem.h>
19+
20+
#include "rkvdec.h"
21+
22+
struct rkvdec_hevc_run {
23+
struct rkvdec_run base;
24+
const struct v4l2_ctrl_hevc_slice_params *slices_params;
25+
const struct v4l2_ctrl_hevc_decode_params *decode_params;
26+
const struct v4l2_ctrl_hevc_sps *sps;
27+
const struct v4l2_ctrl_hevc_pps *pps;
28+
const struct v4l2_ctrl_hevc_scaling_matrix *scaling_matrix;
29+
int num_slices;
30+
};
31+
32+
struct scaling_factor {
33+
u8 scalingfactor0[1248];
34+
u8 scalingfactor1[96]; /*4X4 TU Rotate, total 16X4*/
35+
u8 scalingdc[12]; /*N1005 Vienna Meeting*/
36+
u8 reserved[4]; /*16Bytes align*/
37+
};
38+
39+
void rkvdec_hevc_assemble_hw_scaling_list(struct rkvdec_hevc_run *run,
40+
struct scaling_factor *scaling_factor,
41+
struct v4l2_ctrl_hevc_scaling_matrix *cache);
42+
struct vb2_buffer *get_ref_buf(struct rkvdec_ctx *ctx,
43+
struct rkvdec_hevc_run *run,
44+
unsigned int dpb_idx);
45+
int rkvdec_hevc_adjust_fmt(struct rkvdec_ctx *ctx, struct v4l2_format *f);
46+
enum rkvdec_image_fmt rkvdec_hevc_get_image_fmt(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl);
47+
void rkvdec_hevc_run_preamble(struct rkvdec_ctx *ctx, struct rkvdec_hevc_run *run);

0 commit comments

Comments
 (0)