1 // SPDX-License-Identifier: GPL-2.0
3 * Hantro VPU HEVC codec driver
5 * Copyright (C) 2020 Safran Passenger Innovations LLC
8 #include <linux/types.h>
9 #include <media/v4l2-mem2mem.h>
12 #include "hantro_hw.h"
14 #define VERT_FILTER_RAM_SIZE 8 /* bytes per pixel row */
16 * BSD control data of current picture at tile border
17 * 128 bits per 4x4 tile = 128/(8*4) bytes per row
19 #define BSD_CTRL_RAM_SIZE 4 /* bytes per pixel row */
20 /* tile border coefficients of filter */
21 #define VERT_SAO_RAM_SIZE 48 /* bytes per pixel */
23 #define SCALING_LIST_SIZE (16 * 64)
25 #define MAX_TILE_COLS 20
26 #define MAX_TILE_ROWS 22
28 static bool hevc_use_compression
= IS_ENABLED(CONFIG_VIDEO_HANTRO_HEVC_RFC
);
29 module_param_named(hevc_use_compression
, hevc_use_compression
, bool, 0644);
30 MODULE_PARM_DESC(hevc_use_compression
,
31 "Use reference frame compression for HEVC");
33 void hantro_hevc_ref_init(struct hantro_ctx
*ctx
)
35 struct hantro_hevc_dec_hw_ctx
*hevc_dec
= &ctx
->hevc_dec
;
37 hevc_dec
->ref_bufs_used
= 0;
40 dma_addr_t
hantro_hevc_get_ref_buf(struct hantro_ctx
*ctx
,
43 struct hantro_hevc_dec_hw_ctx
*hevc_dec
= &ctx
->hevc_dec
;
46 /* Find the reference buffer in already known ones */
47 for (i
= 0; i
< NUM_REF_PICTURES
; i
++) {
48 if (hevc_dec
->ref_bufs_poc
[i
] == poc
) {
49 hevc_dec
->ref_bufs_used
|= 1 << i
;
50 return hevc_dec
->ref_bufs
[i
].dma
;
57 int hantro_hevc_add_ref_buf(struct hantro_ctx
*ctx
, int poc
, dma_addr_t addr
)
59 struct hantro_hevc_dec_hw_ctx
*hevc_dec
= &ctx
->hevc_dec
;
62 /* Add a new reference buffer */
63 for (i
= 0; i
< NUM_REF_PICTURES
; i
++) {
64 if (!(hevc_dec
->ref_bufs_used
& 1 << i
)) {
65 hevc_dec
->ref_bufs_used
|= 1 << i
;
66 hevc_dec
->ref_bufs_poc
[i
] = poc
;
67 hevc_dec
->ref_bufs
[i
].dma
= addr
;
75 static int tile_buffer_reallocate(struct hantro_ctx
*ctx
)
77 struct hantro_dev
*vpu
= ctx
->dev
;
78 struct hantro_hevc_dec_hw_ctx
*hevc_dec
= &ctx
->hevc_dec
;
79 const struct hantro_hevc_dec_ctrls
*ctrls
= &ctx
->hevc_dec
.ctrls
;
80 const struct v4l2_ctrl_hevc_pps
*pps
= ctrls
->pps
;
81 const struct v4l2_ctrl_hevc_sps
*sps
= ctrls
->sps
;
82 unsigned int num_tile_cols
= pps
->num_tile_columns_minus1
+ 1;
83 unsigned int height64
= (sps
->pic_height_in_luma_samples
+ 63) & ~63;
86 if (num_tile_cols
<= 1 ||
87 num_tile_cols
<= hevc_dec
->num_tile_cols_allocated
)
90 /* Need to reallocate due to tiles passed via PPS */
91 if (hevc_dec
->tile_filter
.cpu
) {
92 dma_free_coherent(vpu
->dev
, hevc_dec
->tile_filter
.size
,
93 hevc_dec
->tile_filter
.cpu
,
94 hevc_dec
->tile_filter
.dma
);
95 hevc_dec
->tile_filter
.cpu
= NULL
;
98 if (hevc_dec
->tile_sao
.cpu
) {
99 dma_free_coherent(vpu
->dev
, hevc_dec
->tile_sao
.size
,
100 hevc_dec
->tile_sao
.cpu
,
101 hevc_dec
->tile_sao
.dma
);
102 hevc_dec
->tile_sao
.cpu
= NULL
;
105 if (hevc_dec
->tile_bsd
.cpu
) {
106 dma_free_coherent(vpu
->dev
, hevc_dec
->tile_bsd
.size
,
107 hevc_dec
->tile_bsd
.cpu
,
108 hevc_dec
->tile_bsd
.dma
);
109 hevc_dec
->tile_bsd
.cpu
= NULL
;
112 size
= (VERT_FILTER_RAM_SIZE
* height64
* (num_tile_cols
- 1) * ctx
->bit_depth
) / 8;
113 hevc_dec
->tile_filter
.cpu
= dma_alloc_coherent(vpu
->dev
, size
,
114 &hevc_dec
->tile_filter
.dma
,
116 if (!hevc_dec
->tile_filter
.cpu
)
118 hevc_dec
->tile_filter
.size
= size
;
120 size
= (VERT_SAO_RAM_SIZE
* height64
* (num_tile_cols
- 1) * ctx
->bit_depth
) / 8;
121 hevc_dec
->tile_sao
.cpu
= dma_alloc_coherent(vpu
->dev
, size
,
122 &hevc_dec
->tile_sao
.dma
,
124 if (!hevc_dec
->tile_sao
.cpu
)
125 goto err_free_tile_buffers
;
126 hevc_dec
->tile_sao
.size
= size
;
128 size
= BSD_CTRL_RAM_SIZE
* height64
* (num_tile_cols
- 1);
129 hevc_dec
->tile_bsd
.cpu
= dma_alloc_coherent(vpu
->dev
, size
,
130 &hevc_dec
->tile_bsd
.dma
,
132 if (!hevc_dec
->tile_bsd
.cpu
)
133 goto err_free_sao_buffers
;
134 hevc_dec
->tile_bsd
.size
= size
;
136 hevc_dec
->num_tile_cols_allocated
= num_tile_cols
;
140 err_free_sao_buffers
:
141 if (hevc_dec
->tile_sao
.cpu
)
142 dma_free_coherent(vpu
->dev
, hevc_dec
->tile_sao
.size
,
143 hevc_dec
->tile_sao
.cpu
,
144 hevc_dec
->tile_sao
.dma
);
145 hevc_dec
->tile_sao
.cpu
= NULL
;
147 err_free_tile_buffers
:
148 if (hevc_dec
->tile_filter
.cpu
)
149 dma_free_coherent(vpu
->dev
, hevc_dec
->tile_filter
.size
,
150 hevc_dec
->tile_filter
.cpu
,
151 hevc_dec
->tile_filter
.dma
);
152 hevc_dec
->tile_filter
.cpu
= NULL
;
157 static int hantro_hevc_validate_sps(struct hantro_ctx
*ctx
, const struct v4l2_ctrl_hevc_sps
*sps
)
160 * for tile pixel format check if the width and height match
161 * hardware constraints
163 if (ctx
->vpu_dst_fmt
->fourcc
== V4L2_PIX_FMT_NV12_4L4
) {
164 if (ctx
->dst_fmt
.width
!=
165 ALIGN(sps
->pic_width_in_luma_samples
, ctx
->vpu_dst_fmt
->frmsize
.step_width
))
168 if (ctx
->dst_fmt
.height
!=
169 ALIGN(sps
->pic_height_in_luma_samples
, ctx
->vpu_dst_fmt
->frmsize
.step_height
))
176 int hantro_hevc_dec_prepare_run(struct hantro_ctx
*ctx
)
178 struct hantro_hevc_dec_hw_ctx
*hevc_ctx
= &ctx
->hevc_dec
;
179 struct hantro_hevc_dec_ctrls
*ctrls
= &hevc_ctx
->ctrls
;
182 hantro_start_prepare_run(ctx
);
184 ctrls
->decode_params
=
185 hantro_get_ctrl(ctx
, V4L2_CID_STATELESS_HEVC_DECODE_PARAMS
);
186 if (WARN_ON(!ctrls
->decode_params
))
190 hantro_get_ctrl(ctx
, V4L2_CID_STATELESS_HEVC_SCALING_MATRIX
);
191 if (WARN_ON(!ctrls
->scaling
))
195 hantro_get_ctrl(ctx
, V4L2_CID_STATELESS_HEVC_SPS
);
196 if (WARN_ON(!ctrls
->sps
))
199 ret
= hantro_hevc_validate_sps(ctx
, ctrls
->sps
);
204 hantro_get_ctrl(ctx
, V4L2_CID_STATELESS_HEVC_PPS
);
205 if (WARN_ON(!ctrls
->pps
))
208 ret
= tile_buffer_reallocate(ctx
);
215 void hantro_hevc_dec_exit(struct hantro_ctx
*ctx
)
217 struct hantro_dev
*vpu
= ctx
->dev
;
218 struct hantro_hevc_dec_hw_ctx
*hevc_dec
= &ctx
->hevc_dec
;
220 if (hevc_dec
->tile_sizes
.cpu
)
221 dma_free_coherent(vpu
->dev
, hevc_dec
->tile_sizes
.size
,
222 hevc_dec
->tile_sizes
.cpu
,
223 hevc_dec
->tile_sizes
.dma
);
224 hevc_dec
->tile_sizes
.cpu
= NULL
;
226 if (hevc_dec
->scaling_lists
.cpu
)
227 dma_free_coherent(vpu
->dev
, hevc_dec
->scaling_lists
.size
,
228 hevc_dec
->scaling_lists
.cpu
,
229 hevc_dec
->scaling_lists
.dma
);
230 hevc_dec
->scaling_lists
.cpu
= NULL
;
232 if (hevc_dec
->tile_filter
.cpu
)
233 dma_free_coherent(vpu
->dev
, hevc_dec
->tile_filter
.size
,
234 hevc_dec
->tile_filter
.cpu
,
235 hevc_dec
->tile_filter
.dma
);
236 hevc_dec
->tile_filter
.cpu
= NULL
;
238 if (hevc_dec
->tile_sao
.cpu
)
239 dma_free_coherent(vpu
->dev
, hevc_dec
->tile_sao
.size
,
240 hevc_dec
->tile_sao
.cpu
,
241 hevc_dec
->tile_sao
.dma
);
242 hevc_dec
->tile_sao
.cpu
= NULL
;
244 if (hevc_dec
->tile_bsd
.cpu
)
245 dma_free_coherent(vpu
->dev
, hevc_dec
->tile_bsd
.size
,
246 hevc_dec
->tile_bsd
.cpu
,
247 hevc_dec
->tile_bsd
.dma
);
248 hevc_dec
->tile_bsd
.cpu
= NULL
;
251 int hantro_hevc_dec_init(struct hantro_ctx
*ctx
)
253 struct hantro_dev
*vpu
= ctx
->dev
;
254 struct hantro_hevc_dec_hw_ctx
*hevc_dec
= &ctx
->hevc_dec
;
257 memset(hevc_dec
, 0, sizeof(*hevc_dec
));
260 * Maximum number of tiles times width and height (2 bytes each),
261 * rounding up to next 16 bytes boundary + one extra 16 byte
262 * chunk (HW guys wanted to have this).
264 size
= round_up(MAX_TILE_COLS
* MAX_TILE_ROWS
* 4 * sizeof(u16
) + 16, 16);
265 hevc_dec
->tile_sizes
.cpu
= dma_alloc_coherent(vpu
->dev
, size
,
266 &hevc_dec
->tile_sizes
.dma
,
268 if (!hevc_dec
->tile_sizes
.cpu
)
271 hevc_dec
->tile_sizes
.size
= size
;
273 hevc_dec
->scaling_lists
.cpu
= dma_alloc_coherent(vpu
->dev
, SCALING_LIST_SIZE
,
274 &hevc_dec
->scaling_lists
.dma
,
276 if (!hevc_dec
->scaling_lists
.cpu
)
279 hevc_dec
->scaling_lists
.size
= SCALING_LIST_SIZE
;
281 hantro_hevc_ref_init(ctx
);
283 hevc_dec
->use_compression
=
284 hevc_use_compression
& hantro_needs_postproc(ctx
, ctx
->vpu_dst_fmt
);