1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Cedrus VPU driver
4 *
5 * Copyright (C) 2013 Jens Kuske <jenskuske@gmail.com>
6 * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
7 * Copyright (C) 2018 Bootlin
8 */
9
10 #include <linux/delay.h>
11 #include <linux/types.h>
12
13 #include <media/videobuf2-dma-contig.h>
14
15 #include "cedrus.h"
16 #include "cedrus_hw.h"
17 #include "cedrus_regs.h"
18
19 /*
20 * These are the sizes for side buffers required by the hardware for storing
21 * internal decoding metadata. They match the values used by the early BSP
22 * implementations, that were initially exposed in libvdpau-sunxi.
23 * Subsequent BSP implementations seem to double the neighbor info buffer size
24 * for the H6 SoC, which may be related to 10 bit H265 support.
25 */
26 #define CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE (794 * SZ_1K)
27 #define CEDRUS_H265_ENTRY_POINTS_BUF_SIZE (4 * SZ_1K)
28 #define CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE 160
29
30 struct cedrus_h265_sram_frame_info {
31 __le32 top_pic_order_cnt;
32 __le32 bottom_pic_order_cnt;
33 __le32 top_mv_col_buf_addr;
34 __le32 bottom_mv_col_buf_addr;
35 __le32 luma_addr;
36 __le32 chroma_addr;
37 } __packed;
38
39 struct cedrus_h265_sram_pred_weight {
40 __s8 delta_weight;
41 __s8 offset;
42 } __packed;
43
cedrus_h265_irq_status(struct cedrus_ctx * ctx)44 static enum cedrus_irq_status cedrus_h265_irq_status(struct cedrus_ctx *ctx)
45 {
46 struct cedrus_dev *dev = ctx->dev;
47 u32 reg;
48
49 reg = cedrus_read(dev, VE_DEC_H265_STATUS);
50 reg &= VE_DEC_H265_STATUS_CHECK_MASK;
51
52 if (reg & VE_DEC_H265_STATUS_CHECK_ERROR ||
53 !(reg & VE_DEC_H265_STATUS_SUCCESS))
54 return CEDRUS_IRQ_ERROR;
55
56 return CEDRUS_IRQ_OK;
57 }
58
cedrus_h265_irq_clear(struct cedrus_ctx * ctx)59 static void cedrus_h265_irq_clear(struct cedrus_ctx *ctx)
60 {
61 struct cedrus_dev *dev = ctx->dev;
62
63 cedrus_write(dev, VE_DEC_H265_STATUS, VE_DEC_H265_STATUS_CHECK_MASK);
64 }
65
cedrus_h265_irq_disable(struct cedrus_ctx * ctx)66 static void cedrus_h265_irq_disable(struct cedrus_ctx *ctx)
67 {
68 struct cedrus_dev *dev = ctx->dev;
69 u32 reg = cedrus_read(dev, VE_DEC_H265_CTRL);
70
71 reg &= ~VE_DEC_H265_CTRL_IRQ_MASK;
72
73 cedrus_write(dev, VE_DEC_H265_CTRL, reg);
74 }
75
cedrus_h265_sram_write_offset(struct cedrus_dev * dev,u32 offset)76 static void cedrus_h265_sram_write_offset(struct cedrus_dev *dev, u32 offset)
77 {
78 cedrus_write(dev, VE_DEC_H265_SRAM_OFFSET, offset);
79 }
80
cedrus_h265_sram_write_data(struct cedrus_dev * dev,void * data,unsigned int size)81 static void cedrus_h265_sram_write_data(struct cedrus_dev *dev, void *data,
82 unsigned int size)
83 {
84 u32 *word = data;
85
86 while (size >= sizeof(u32)) {
87 cedrus_write(dev, VE_DEC_H265_SRAM_DATA, *word++);
88 size -= sizeof(u32);
89 }
90 }
91
92 static inline dma_addr_t
cedrus_h265_frame_info_mv_col_buf_addr(struct cedrus_ctx * ctx,unsigned int index,unsigned int field)93 cedrus_h265_frame_info_mv_col_buf_addr(struct cedrus_ctx *ctx,
94 unsigned int index, unsigned int field)
95 {
96 return ctx->codec.h265.mv_col_buf_addr + index *
97 ctx->codec.h265.mv_col_buf_unit_size +
98 field * ctx->codec.h265.mv_col_buf_unit_size / 2;
99 }
100
cedrus_h265_frame_info_write_single(struct cedrus_ctx * ctx,unsigned int index,bool field_pic,u32 pic_order_cnt[],int buffer_index)101 static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx,
102 unsigned int index,
103 bool field_pic,
104 u32 pic_order_cnt[],
105 int buffer_index)
106 {
107 struct cedrus_dev *dev = ctx->dev;
108 dma_addr_t dst_luma_addr = cedrus_dst_buf_addr(ctx, buffer_index, 0);
109 dma_addr_t dst_chroma_addr = cedrus_dst_buf_addr(ctx, buffer_index, 1);
110 dma_addr_t mv_col_buf_addr[2] = {
111 cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index, 0),
112 cedrus_h265_frame_info_mv_col_buf_addr(ctx, buffer_index,
113 field_pic ? 1 : 0)
114 };
115 u32 offset = VE_DEC_H265_SRAM_OFFSET_FRAME_INFO +
116 VE_DEC_H265_SRAM_OFFSET_FRAME_INFO_UNIT * index;
117 struct cedrus_h265_sram_frame_info frame_info = {
118 .top_pic_order_cnt = cpu_to_le32(pic_order_cnt[0]),
119 .bottom_pic_order_cnt = cpu_to_le32(field_pic ?
120 pic_order_cnt[1] :
121 pic_order_cnt[0]),
122 .top_mv_col_buf_addr =
123 cpu_to_le32(VE_DEC_H265_SRAM_DATA_ADDR_BASE(mv_col_buf_addr[0])),
124 .bottom_mv_col_buf_addr = cpu_to_le32(field_pic ?
125 VE_DEC_H265_SRAM_DATA_ADDR_BASE(mv_col_buf_addr[1]) :
126 VE_DEC_H265_SRAM_DATA_ADDR_BASE(mv_col_buf_addr[0])),
127 .luma_addr = cpu_to_le32(VE_DEC_H265_SRAM_DATA_ADDR_BASE(dst_luma_addr)),
128 .chroma_addr = cpu_to_le32(VE_DEC_H265_SRAM_DATA_ADDR_BASE(dst_chroma_addr)),
129 };
130
131 cedrus_h265_sram_write_offset(dev, offset);
132 cedrus_h265_sram_write_data(dev, &frame_info, sizeof(frame_info));
133 }
134
cedrus_h265_frame_info_write_dpb(struct cedrus_ctx * ctx,const struct v4l2_hevc_dpb_entry * dpb,u8 num_active_dpb_entries)135 static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx,
136 const struct v4l2_hevc_dpb_entry *dpb,
137 u8 num_active_dpb_entries)
138 {
139 struct vb2_queue *vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
140 V4L2_BUF_TYPE_VIDEO_CAPTURE);
141 unsigned int i;
142
143 for (i = 0; i < num_active_dpb_entries; i++) {
144 int buffer_index = vb2_find_timestamp(vq, dpb[i].timestamp, 0);
145 u32 pic_order_cnt[2] = {
146 dpb[i].pic_order_cnt[0],
147 dpb[i].pic_order_cnt[1]
148 };
149
150 if (buffer_index < 0)
151 continue;
152
153 cedrus_h265_frame_info_write_single(ctx, i, dpb[i].field_pic,
154 pic_order_cnt,
155 buffer_index);
156 }
157 }
158
cedrus_h265_ref_pic_list_write(struct cedrus_dev * dev,const struct v4l2_hevc_dpb_entry * dpb,const u8 list[],u8 num_ref_idx_active,u32 sram_offset)159 static void cedrus_h265_ref_pic_list_write(struct cedrus_dev *dev,
160 const struct v4l2_hevc_dpb_entry *dpb,
161 const u8 list[],
162 u8 num_ref_idx_active,
163 u32 sram_offset)
164 {
165 unsigned int i;
166 u32 word = 0;
167
168 cedrus_h265_sram_write_offset(dev, sram_offset);
169
170 for (i = 0; i < num_ref_idx_active; i++) {
171 unsigned int shift = (i % 4) * 8;
172 unsigned int index = list[i];
173 u8 value = list[i];
174
175 if (dpb[index].rps == V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR)
176 value |= VE_DEC_H265_SRAM_REF_PIC_LIST_LT_REF;
177
178 /* Each SRAM word gathers up to 4 references. */
179 word |= value << shift;
180
181 /* Write the word to SRAM and clear it for the next batch. */
182 if ((i % 4) == 3 || i == (num_ref_idx_active - 1)) {
183 cedrus_h265_sram_write_data(dev, &word, sizeof(word));
184 word = 0;
185 }
186 }
187 }
188
cedrus_h265_pred_weight_write(struct cedrus_dev * dev,const s8 delta_luma_weight[],const s8 luma_offset[],const s8 delta_chroma_weight[][2],const s8 chroma_offset[][2],u8 num_ref_idx_active,u32 sram_luma_offset,u32 sram_chroma_offset)189 static void cedrus_h265_pred_weight_write(struct cedrus_dev *dev,
190 const s8 delta_luma_weight[],
191 const s8 luma_offset[],
192 const s8 delta_chroma_weight[][2],
193 const s8 chroma_offset[][2],
194 u8 num_ref_idx_active,
195 u32 sram_luma_offset,
196 u32 sram_chroma_offset)
197 {
198 struct cedrus_h265_sram_pred_weight pred_weight[2] = { { 0 } };
199 unsigned int i, j;
200
201 cedrus_h265_sram_write_offset(dev, sram_luma_offset);
202
203 for (i = 0; i < num_ref_idx_active; i++) {
204 unsigned int index = i % 2;
205
206 pred_weight[index].delta_weight = delta_luma_weight[i];
207 pred_weight[index].offset = luma_offset[i];
208
209 if (index == 1 || i == (num_ref_idx_active - 1))
210 cedrus_h265_sram_write_data(dev, (u32 *)&pred_weight,
211 sizeof(pred_weight));
212 }
213
214 cedrus_h265_sram_write_offset(dev, sram_chroma_offset);
215
216 for (i = 0; i < num_ref_idx_active; i++) {
217 for (j = 0; j < 2; j++) {
218 pred_weight[j].delta_weight = delta_chroma_weight[i][j];
219 pred_weight[j].offset = chroma_offset[i][j];
220 }
221
222 cedrus_h265_sram_write_data(dev, &pred_weight,
223 sizeof(pred_weight));
224 }
225 }
226
cedrus_h265_skip_bits(struct cedrus_dev * dev,int num)227 static void cedrus_h265_skip_bits(struct cedrus_dev *dev, int num)
228 {
229 int count = 0;
230
231 while (count < num) {
232 int tmp = min(num - count, 32);
233
234 cedrus_write(dev, VE_DEC_H265_TRIGGER,
235 VE_DEC_H265_TRIGGER_FLUSH_BITS |
236 VE_DEC_H265_TRIGGER_TYPE_N_BITS(tmp));
237 while (cedrus_read(dev, VE_DEC_H265_STATUS) & VE_DEC_H265_STATUS_VLD_BUSY)
238 udelay(1);
239
240 count += tmp;
241 }
242 }
243
cedrus_h265_setup(struct cedrus_ctx * ctx,struct cedrus_run * run)244 static void cedrus_h265_setup(struct cedrus_ctx *ctx,
245 struct cedrus_run *run)
246 {
247 struct cedrus_dev *dev = ctx->dev;
248 const struct v4l2_ctrl_hevc_sps *sps;
249 const struct v4l2_ctrl_hevc_pps *pps;
250 const struct v4l2_ctrl_hevc_slice_params *slice_params;
251 const struct v4l2_hevc_pred_weight_table *pred_weight_table;
252 dma_addr_t src_buf_addr;
253 dma_addr_t src_buf_end_addr;
254 u32 chroma_log2_weight_denom;
255 u32 output_pic_list_index;
256 u32 pic_order_cnt[2];
257 u32 reg;
258
259 sps = run->h265.sps;
260 pps = run->h265.pps;
261 slice_params = run->h265.slice_params;
262 pred_weight_table = &slice_params->pred_weight_table;
263
264 /* MV column buffer size and allocation. */
265 if (!ctx->codec.h265.mv_col_buf_size) {
266 unsigned int num_buffers =
267 run->dst->vb2_buf.vb2_queue->num_buffers;
268 unsigned int log2_max_luma_coding_block_size =
269 sps->log2_min_luma_coding_block_size_minus3 + 3 +
270 sps->log2_diff_max_min_luma_coding_block_size;
271 unsigned int ctb_size_luma =
272 1UL << log2_max_luma_coding_block_size;
273
274 /*
275 * Each CTB requires a MV col buffer with a specific unit size.
276 * Since the address is given with missing lsb bits, 1 KiB is
277 * added to each buffer to ensure proper alignment.
278 */
279 ctx->codec.h265.mv_col_buf_unit_size =
280 DIV_ROUND_UP(ctx->src_fmt.width, ctb_size_luma) *
281 DIV_ROUND_UP(ctx->src_fmt.height, ctb_size_luma) *
282 CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE + SZ_1K;
283
284 ctx->codec.h265.mv_col_buf_size = num_buffers *
285 ctx->codec.h265.mv_col_buf_unit_size;
286
287 ctx->codec.h265.mv_col_buf =
288 dma_alloc_coherent(dev->dev,
289 ctx->codec.h265.mv_col_buf_size,
290 &ctx->codec.h265.mv_col_buf_addr,
291 GFP_KERNEL);
292 if (!ctx->codec.h265.mv_col_buf) {
293 ctx->codec.h265.mv_col_buf_size = 0;
294 // TODO: Abort the process here.
295 return;
296 }
297 }
298
299 /* Activate H265 engine. */
300 cedrus_engine_enable(ctx, CEDRUS_CODEC_H265);
301
302 /* Source offset and length in bits. */
303
304 cedrus_write(dev, VE_DEC_H265_BITS_OFFSET, 0);
305
306 reg = slice_params->bit_size;
307 cedrus_write(dev, VE_DEC_H265_BITS_LEN, reg);
308
309 /* Source beginning and end addresses. */
310
311 src_buf_addr = vb2_dma_contig_plane_dma_addr(&run->src->vb2_buf, 0);
312
313 reg = VE_DEC_H265_BITS_ADDR_BASE(src_buf_addr);
314 reg |= VE_DEC_H265_BITS_ADDR_VALID_SLICE_DATA;
315 reg |= VE_DEC_H265_BITS_ADDR_LAST_SLICE_DATA;
316 reg |= VE_DEC_H265_BITS_ADDR_FIRST_SLICE_DATA;
317
318 cedrus_write(dev, VE_DEC_H265_BITS_ADDR, reg);
319
320 src_buf_end_addr = src_buf_addr +
321 DIV_ROUND_UP(slice_params->bit_size, 8);
322
323 reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_end_addr);
324 cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg);
325
326 /* Coding tree block address: start at the beginning. */
327 reg = VE_DEC_H265_DEC_CTB_ADDR_X(0) | VE_DEC_H265_DEC_CTB_ADDR_Y(0);
328 cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg);
329
330 cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0);
331 cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0);
332
333 /* Clear the number of correctly-decoded coding tree blocks. */
334 cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0);
335
336 /* Initialize bitstream access. */
337 cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_INIT_SWDEC);
338
339 cedrus_h265_skip_bits(dev, slice_params->data_bit_offset);
340
341 /* Bitstream parameters. */
342
343 reg = VE_DEC_H265_DEC_NAL_HDR_NAL_UNIT_TYPE(slice_params->nal_unit_type) |
344 VE_DEC_H265_DEC_NAL_HDR_NUH_TEMPORAL_ID_PLUS1(slice_params->nuh_temporal_id_plus1);
345
346 cedrus_write(dev, VE_DEC_H265_DEC_NAL_HDR, reg);
347
348 /* SPS. */
349
350 reg = VE_DEC_H265_DEC_SPS_HDR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTRA(sps->max_transform_hierarchy_depth_intra) |
351 VE_DEC_H265_DEC_SPS_HDR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTER(sps->max_transform_hierarchy_depth_inter) |
352 VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_TRANSFORM_BLOCK_SIZE(sps->log2_diff_max_min_luma_transform_block_size) |
353 VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_TRANSFORM_BLOCK_SIZE_MINUS2(sps->log2_min_luma_transform_block_size_minus2) |
354 VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE(sps->log2_diff_max_min_luma_coding_block_size) |
355 VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_LUMA_CODING_BLOCK_SIZE_MINUS3(sps->log2_min_luma_coding_block_size_minus3) |
356 VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_CHROMA_MINUS8(sps->bit_depth_chroma_minus8) |
357 VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_LUMA_MINUS8(sps->bit_depth_luma_minus8) |
358 VE_DEC_H265_DEC_SPS_HDR_CHROMA_FORMAT_IDC(sps->chroma_format_idc);
359
360 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_STRONG_INTRA_SMOOTHING_ENABLE,
361 V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED,
362 sps->flags);
363
364 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_SPS_TEMPORAL_MVP_ENABLED,
365 V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED,
366 sps->flags);
367
368 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_SAMPLE_ADAPTIVE_OFFSET_ENABLED,
369 V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET,
370 sps->flags);
371
372 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_AMP_ENABLED,
373 V4L2_HEVC_SPS_FLAG_AMP_ENABLED, sps->flags);
374
375 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_SEPARATE_COLOUR_PLANE,
376 V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE,
377 sps->flags);
378
379 cedrus_write(dev, VE_DEC_H265_DEC_SPS_HDR, reg);
380
381 reg = VE_DEC_H265_DEC_PCM_CTRL_LOG2_DIFF_MAX_MIN_PCM_LUMA_CODING_BLOCK_SIZE(sps->log2_diff_max_min_pcm_luma_coding_block_size) |
382 VE_DEC_H265_DEC_PCM_CTRL_LOG2_MIN_PCM_LUMA_CODING_BLOCK_SIZE_MINUS3(sps->log2_min_pcm_luma_coding_block_size_minus3) |
383 VE_DEC_H265_DEC_PCM_CTRL_PCM_SAMPLE_BIT_DEPTH_CHROMA_MINUS1(sps->pcm_sample_bit_depth_chroma_minus1) |
384 VE_DEC_H265_DEC_PCM_CTRL_PCM_SAMPLE_BIT_DEPTH_LUMA_MINUS1(sps->pcm_sample_bit_depth_luma_minus1);
385
386 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PCM_CTRL_FLAG_PCM_ENABLED,
387 V4L2_HEVC_SPS_FLAG_PCM_ENABLED, sps->flags);
388
389 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PCM_CTRL_FLAG_PCM_LOOP_FILTER_DISABLED,
390 V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED,
391 sps->flags);
392
393 cedrus_write(dev, VE_DEC_H265_DEC_PCM_CTRL, reg);
394
395 /* PPS. */
396
397 reg = VE_DEC_H265_DEC_PPS_CTRL0_PPS_CR_QP_OFFSET(pps->pps_cr_qp_offset) |
398 VE_DEC_H265_DEC_PPS_CTRL0_PPS_CB_QP_OFFSET(pps->pps_cb_qp_offset) |
399 VE_DEC_H265_DEC_PPS_CTRL0_INIT_QP_MINUS26(pps->init_qp_minus26) |
400 VE_DEC_H265_DEC_PPS_CTRL0_DIFF_CU_QP_DELTA_DEPTH(pps->diff_cu_qp_delta_depth);
401
402 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL0_FLAG_CU_QP_DELTA_ENABLED,
403 V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED,
404 pps->flags);
405
406 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL0_FLAG_TRANSFORM_SKIP_ENABLED,
407 V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED,
408 pps->flags);
409
410 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL0_FLAG_CONSTRAINED_INTRA_PRED,
411 V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED,
412 pps->flags);
413
414 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL0_FLAG_SIGN_DATA_HIDING_ENABLED,
415 V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED,
416 pps->flags);
417
418 cedrus_write(dev, VE_DEC_H265_DEC_PPS_CTRL0, reg);
419
420 reg = VE_DEC_H265_DEC_PPS_CTRL1_LOG2_PARALLEL_MERGE_LEVEL_MINUS2(pps->log2_parallel_merge_level_minus2);
421
422 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED,
423 V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED,
424 pps->flags);
425
426 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED,
427 V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED,
428 pps->flags);
429
430 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_ENTROPY_CODING_SYNC_ENABLED,
431 V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED,
432 pps->flags);
433
434 /* TODO: VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TILES_ENABLED */
435
436 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TRANSQUANT_BYPASS_ENABLED,
437 V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED,
438 pps->flags);
439
440 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_WEIGHTED_BIPRED,
441 V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED, pps->flags);
442
443 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_WEIGHTED_PRED,
444 V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED, pps->flags);
445
446 cedrus_write(dev, VE_DEC_H265_DEC_PPS_CTRL1, reg);
447
448 /* Slice Parameters. */
449
450 reg = VE_DEC_H265_DEC_SLICE_HDR_INFO0_PICTURE_TYPE(slice_params->pic_struct) |
451 VE_DEC_H265_DEC_SLICE_HDR_INFO0_FIVE_MINUS_MAX_NUM_MERGE_CAND(slice_params->five_minus_max_num_merge_cand) |
452 VE_DEC_H265_DEC_SLICE_HDR_INFO0_NUM_REF_IDX_L1_ACTIVE_MINUS1(slice_params->num_ref_idx_l1_active_minus1) |
453 VE_DEC_H265_DEC_SLICE_HDR_INFO0_NUM_REF_IDX_L0_ACTIVE_MINUS1(slice_params->num_ref_idx_l0_active_minus1) |
454 VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLLOCATED_REF_IDX(slice_params->collocated_ref_idx) |
455 VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLOUR_PLANE_ID(slice_params->colour_plane_id) |
456 VE_DEC_H265_DEC_SLICE_HDR_INFO0_SLICE_TYPE(slice_params->slice_type);
457
458 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_COLLOCATED_FROM_L0,
459 V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0,
460 slice_params->flags);
461
462 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_CABAC_INIT,
463 V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT,
464 slice_params->flags);
465
466 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_MVD_L1_ZERO,
467 V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO,
468 slice_params->flags);
469
470 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_SLICE_SAO_CHROMA,
471 V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA,
472 slice_params->flags);
473
474 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_SLICE_SAO_LUMA,
475 V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA,
476 slice_params->flags);
477
478 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_SLICE_TEMPORAL_MVP_ENABLE,
479 V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED,
480 slice_params->flags);
481
482 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_DEPENDENT_SLICE_SEGMENT,
483 V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT,
484 slice_params->flags);
485
486 /* FIXME: For multi-slice support. */
487 reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC;
488
489 cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO0, reg);
490
491 reg = VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_TC_OFFSET_DIV2(slice_params->slice_tc_offset_div2) |
492 VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_BETA_OFFSET_DIV2(slice_params->slice_beta_offset_div2) |
493 VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_POC_BIGEST_IN_RPS_ST(slice_params->num_rps_poc_st_curr_after == 0) |
494 VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CR_QP_OFFSET(slice_params->slice_cr_qp_offset) |
495 VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CB_QP_OFFSET(slice_params->slice_cb_qp_offset) |
496 VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_QP_DELTA(slice_params->slice_qp_delta);
497
498 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO1_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED,
499 V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED,
500 slice_params->flags);
501
502 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO1_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED,
503 V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED,
504 slice_params->flags);
505
506 cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO1, reg);
507
508 chroma_log2_weight_denom = pred_weight_table->luma_log2_weight_denom +
509 pred_weight_table->delta_chroma_log2_weight_denom;
510 reg = VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(0) |
511 VE_DEC_H265_DEC_SLICE_HDR_INFO2_CHROMA_LOG2_WEIGHT_DENOM(chroma_log2_weight_denom) |
512 VE_DEC_H265_DEC_SLICE_HDR_INFO2_LUMA_LOG2_WEIGHT_DENOM(pred_weight_table->luma_log2_weight_denom);
513
514 cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO2, reg);
515
516 /* Decoded picture size. */
517
518 reg = VE_DEC_H265_DEC_PIC_SIZE_WIDTH(ctx->src_fmt.width) |
519 VE_DEC_H265_DEC_PIC_SIZE_HEIGHT(ctx->src_fmt.height);
520
521 cedrus_write(dev, VE_DEC_H265_DEC_PIC_SIZE, reg);
522
523 /* Scaling list. */
524
525 reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT;
526 cedrus_write(dev, VE_DEC_H265_SCALING_LIST_CTRL0, reg);
527
528 /* Neightbor information address. */
529 reg = VE_DEC_H265_NEIGHBOR_INFO_ADDR_BASE(ctx->codec.h265.neighbor_info_buf_addr);
530 cedrus_write(dev, VE_DEC_H265_NEIGHBOR_INFO_ADDR, reg);
531
532 /* Write decoded picture buffer in pic list. */
533 cedrus_h265_frame_info_write_dpb(ctx, slice_params->dpb,
534 slice_params->num_active_dpb_entries);
535
536 /* Output frame. */
537
538 output_pic_list_index = V4L2_HEVC_DPB_ENTRIES_NUM_MAX;
539 pic_order_cnt[0] = slice_params->slice_pic_order_cnt;
540 pic_order_cnt[1] = slice_params->slice_pic_order_cnt;
541
542 cedrus_h265_frame_info_write_single(ctx, output_pic_list_index,
543 slice_params->pic_struct != 0,
544 pic_order_cnt,
545 run->dst->vb2_buf.index);
546
547 cedrus_write(dev, VE_DEC_H265_OUTPUT_FRAME_IDX, output_pic_list_index);
548
549 /* Reference picture list 0 (for P/B frames). */
550 if (slice_params->slice_type != V4L2_HEVC_SLICE_TYPE_I) {
551 cedrus_h265_ref_pic_list_write(dev, slice_params->dpb,
552 slice_params->ref_idx_l0,
553 slice_params->num_ref_idx_l0_active_minus1 + 1,
554 VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST0);
555
556 if ((pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED) ||
557 (pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED))
558 cedrus_h265_pred_weight_write(dev,
559 pred_weight_table->delta_luma_weight_l0,
560 pred_weight_table->luma_offset_l0,
561 pred_weight_table->delta_chroma_weight_l0,
562 pred_weight_table->chroma_offset_l0,
563 slice_params->num_ref_idx_l0_active_minus1 + 1,
564 VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L0,
565 VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L0);
566 }
567
568 /* Reference picture list 1 (for B frames). */
569 if (slice_params->slice_type == V4L2_HEVC_SLICE_TYPE_B) {
570 cedrus_h265_ref_pic_list_write(dev, slice_params->dpb,
571 slice_params->ref_idx_l1,
572 slice_params->num_ref_idx_l1_active_minus1 + 1,
573 VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST1);
574
575 if (pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED)
576 cedrus_h265_pred_weight_write(dev,
577 pred_weight_table->delta_luma_weight_l1,
578 pred_weight_table->luma_offset_l1,
579 pred_weight_table->delta_chroma_weight_l1,
580 pred_weight_table->chroma_offset_l1,
581 slice_params->num_ref_idx_l1_active_minus1 + 1,
582 VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L1,
583 VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L1);
584 }
585
586 /* Enable appropriate interruptions. */
587 cedrus_write(dev, VE_DEC_H265_CTRL, VE_DEC_H265_CTRL_IRQ_MASK);
588 }
589
cedrus_h265_start(struct cedrus_ctx * ctx)590 static int cedrus_h265_start(struct cedrus_ctx *ctx)
591 {
592 struct cedrus_dev *dev = ctx->dev;
593
594 /* The buffer size is calculated at setup time. */
595 ctx->codec.h265.mv_col_buf_size = 0;
596
597 ctx->codec.h265.neighbor_info_buf =
598 dma_alloc_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
599 &ctx->codec.h265.neighbor_info_buf_addr,
600 GFP_KERNEL);
601 if (!ctx->codec.h265.neighbor_info_buf)
602 return -ENOMEM;
603
604 return 0;
605 }
606
cedrus_h265_stop(struct cedrus_ctx * ctx)607 static void cedrus_h265_stop(struct cedrus_ctx *ctx)
608 {
609 struct cedrus_dev *dev = ctx->dev;
610
611 if (ctx->codec.h265.mv_col_buf_size > 0) {
612 dma_free_coherent(dev->dev, ctx->codec.h265.mv_col_buf_size,
613 ctx->codec.h265.mv_col_buf,
614 ctx->codec.h265.mv_col_buf_addr);
615
616 ctx->codec.h265.mv_col_buf_size = 0;
617 }
618
619 dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
620 ctx->codec.h265.neighbor_info_buf,
621 ctx->codec.h265.neighbor_info_buf_addr);
622 }
623
cedrus_h265_trigger(struct cedrus_ctx * ctx)624 static void cedrus_h265_trigger(struct cedrus_ctx *ctx)
625 {
626 struct cedrus_dev *dev = ctx->dev;
627
628 cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_DEC_SLICE);
629 }
630
631 struct cedrus_dec_ops cedrus_dec_ops_h265 = {
632 .irq_clear = cedrus_h265_irq_clear,
633 .irq_disable = cedrus_h265_irq_disable,
634 .irq_status = cedrus_h265_irq_status,
635 .setup = cedrus_h265_setup,
636 .start = cedrus_h265_start,
637 .stop = cedrus_h265_stop,
638 .trigger = cedrus_h265_trigger,
639 };
640