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 (397 * 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 cedrus_h265_frame_info_write_single(ctx, i, dpb[i].field_pic,
151 pic_order_cnt,
152 buffer_index);
153 }
154 }
155
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)156 static void cedrus_h265_ref_pic_list_write(struct cedrus_dev *dev,
157 const struct v4l2_hevc_dpb_entry *dpb,
158 const u8 list[],
159 u8 num_ref_idx_active,
160 u32 sram_offset)
161 {
162 unsigned int i;
163 u32 word = 0;
164
165 cedrus_h265_sram_write_offset(dev, sram_offset);
166
167 for (i = 0; i < num_ref_idx_active; i++) {
168 unsigned int shift = (i % 4) * 8;
169 unsigned int index = list[i];
170 u8 value = list[i];
171
172 if (dpb[index].rps == V4L2_HEVC_DPB_ENTRY_RPS_LT_CURR)
173 value |= VE_DEC_H265_SRAM_REF_PIC_LIST_LT_REF;
174
175 /* Each SRAM word gathers up to 4 references. */
176 word |= value << shift;
177
178 /* Write the word to SRAM and clear it for the next batch. */
179 if ((i % 4) == 3 || i == (num_ref_idx_active - 1)) {
180 cedrus_h265_sram_write_data(dev, &word, sizeof(word));
181 word = 0;
182 }
183 }
184 }
185
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)186 static void cedrus_h265_pred_weight_write(struct cedrus_dev *dev,
187 const s8 delta_luma_weight[],
188 const s8 luma_offset[],
189 const s8 delta_chroma_weight[][2],
190 const s8 chroma_offset[][2],
191 u8 num_ref_idx_active,
192 u32 sram_luma_offset,
193 u32 sram_chroma_offset)
194 {
195 struct cedrus_h265_sram_pred_weight pred_weight[2] = { { 0 } };
196 unsigned int i, j;
197
198 cedrus_h265_sram_write_offset(dev, sram_luma_offset);
199
200 for (i = 0; i < num_ref_idx_active; i++) {
201 unsigned int index = i % 2;
202
203 pred_weight[index].delta_weight = delta_luma_weight[i];
204 pred_weight[index].offset = luma_offset[i];
205
206 if (index == 1 || i == (num_ref_idx_active - 1))
207 cedrus_h265_sram_write_data(dev, (u32 *)&pred_weight,
208 sizeof(pred_weight));
209 }
210
211 cedrus_h265_sram_write_offset(dev, sram_chroma_offset);
212
213 for (i = 0; i < num_ref_idx_active; i++) {
214 for (j = 0; j < 2; j++) {
215 pred_weight[j].delta_weight = delta_chroma_weight[i][j];
216 pred_weight[j].offset = chroma_offset[i][j];
217 }
218
219 cedrus_h265_sram_write_data(dev, &pred_weight,
220 sizeof(pred_weight));
221 }
222 }
223
cedrus_h265_skip_bits(struct cedrus_dev * dev,int num)224 static void cedrus_h265_skip_bits(struct cedrus_dev *dev, int num)
225 {
226 int count = 0;
227
228 while (count < num) {
229 int tmp = min(num - count, 32);
230
231 cedrus_write(dev, VE_DEC_H265_TRIGGER,
232 VE_DEC_H265_TRIGGER_FLUSH_BITS |
233 VE_DEC_H265_TRIGGER_TYPE_N_BITS(tmp));
234 while (cedrus_read(dev, VE_DEC_H265_STATUS) & VE_DEC_H265_STATUS_VLD_BUSY)
235 udelay(1);
236
237 count += tmp;
238 }
239 }
240
cedrus_h265_setup(struct cedrus_ctx * ctx,struct cedrus_run * run)241 static void cedrus_h265_setup(struct cedrus_ctx *ctx,
242 struct cedrus_run *run)
243 {
244 struct cedrus_dev *dev = ctx->dev;
245 const struct v4l2_ctrl_hevc_sps *sps;
246 const struct v4l2_ctrl_hevc_pps *pps;
247 const struct v4l2_ctrl_hevc_slice_params *slice_params;
248 const struct v4l2_hevc_pred_weight_table *pred_weight_table;
249 dma_addr_t src_buf_addr;
250 dma_addr_t src_buf_end_addr;
251 u32 chroma_log2_weight_denom;
252 u32 output_pic_list_index;
253 u32 pic_order_cnt[2];
254 u32 reg;
255
256 sps = run->h265.sps;
257 pps = run->h265.pps;
258 slice_params = run->h265.slice_params;
259 pred_weight_table = &slice_params->pred_weight_table;
260
261 /* MV column buffer size and allocation. */
262 if (!ctx->codec.h265.mv_col_buf_size) {
263 unsigned int num_buffers =
264 run->dst->vb2_buf.vb2_queue->num_buffers;
265 unsigned int log2_max_luma_coding_block_size =
266 sps->log2_min_luma_coding_block_size_minus3 + 3 +
267 sps->log2_diff_max_min_luma_coding_block_size;
268 unsigned int ctb_size_luma =
269 1UL << log2_max_luma_coding_block_size;
270
271 /*
272 * Each CTB requires a MV col buffer with a specific unit size.
273 * Since the address is given with missing lsb bits, 1 KiB is
274 * added to each buffer to ensure proper alignment.
275 */
276 ctx->codec.h265.mv_col_buf_unit_size =
277 DIV_ROUND_UP(ctx->src_fmt.width, ctb_size_luma) *
278 DIV_ROUND_UP(ctx->src_fmt.height, ctb_size_luma) *
279 CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE + SZ_1K;
280
281 ctx->codec.h265.mv_col_buf_size = num_buffers *
282 ctx->codec.h265.mv_col_buf_unit_size;
283
284 ctx->codec.h265.mv_col_buf =
285 dma_alloc_coherent(dev->dev,
286 ctx->codec.h265.mv_col_buf_size,
287 &ctx->codec.h265.mv_col_buf_addr,
288 GFP_KERNEL);
289 if (!ctx->codec.h265.mv_col_buf) {
290 ctx->codec.h265.mv_col_buf_size = 0;
291 // TODO: Abort the process here.
292 return;
293 }
294 }
295
296 /* Activate H265 engine. */
297 cedrus_engine_enable(ctx, CEDRUS_CODEC_H265);
298
299 /* Source offset and length in bits. */
300
301 cedrus_write(dev, VE_DEC_H265_BITS_OFFSET, 0);
302
303 reg = slice_params->bit_size;
304 cedrus_write(dev, VE_DEC_H265_BITS_LEN, reg);
305
306 /* Source beginning and end addresses. */
307
308 src_buf_addr = vb2_dma_contig_plane_dma_addr(&run->src->vb2_buf, 0);
309
310 reg = VE_DEC_H265_BITS_ADDR_BASE(src_buf_addr);
311 reg |= VE_DEC_H265_BITS_ADDR_VALID_SLICE_DATA;
312 reg |= VE_DEC_H265_BITS_ADDR_LAST_SLICE_DATA;
313 reg |= VE_DEC_H265_BITS_ADDR_FIRST_SLICE_DATA;
314
315 cedrus_write(dev, VE_DEC_H265_BITS_ADDR, reg);
316
317 src_buf_end_addr = src_buf_addr +
318 DIV_ROUND_UP(slice_params->bit_size, 8);
319
320 reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_end_addr);
321 cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg);
322
323 /* Coding tree block address: start at the beginning. */
324 reg = VE_DEC_H265_DEC_CTB_ADDR_X(0) | VE_DEC_H265_DEC_CTB_ADDR_Y(0);
325 cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg);
326
327 cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0);
328 cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0);
329
330 /* Clear the number of correctly-decoded coding tree blocks. */
331 cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0);
332
333 /* Initialize bitstream access. */
334 cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_INIT_SWDEC);
335
336 cedrus_h265_skip_bits(dev, slice_params->data_bit_offset);
337
338 /* Bitstream parameters. */
339
340 reg = VE_DEC_H265_DEC_NAL_HDR_NAL_UNIT_TYPE(slice_params->nal_unit_type) |
341 VE_DEC_H265_DEC_NAL_HDR_NUH_TEMPORAL_ID_PLUS1(slice_params->nuh_temporal_id_plus1);
342
343 cedrus_write(dev, VE_DEC_H265_DEC_NAL_HDR, reg);
344
345 /* SPS. */
346
347 reg = VE_DEC_H265_DEC_SPS_HDR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTRA(sps->max_transform_hierarchy_depth_intra) |
348 VE_DEC_H265_DEC_SPS_HDR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTER(sps->max_transform_hierarchy_depth_inter) |
349 VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_TRANSFORM_BLOCK_SIZE(sps->log2_diff_max_min_luma_transform_block_size) |
350 VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_TRANSFORM_BLOCK_SIZE_MINUS2(sps->log2_min_luma_transform_block_size_minus2) |
351 VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE(sps->log2_diff_max_min_luma_coding_block_size) |
352 VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_LUMA_CODING_BLOCK_SIZE_MINUS3(sps->log2_min_luma_coding_block_size_minus3) |
353 VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_CHROMA_MINUS8(sps->bit_depth_chroma_minus8) |
354 VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_LUMA_MINUS8(sps->bit_depth_luma_minus8) |
355 VE_DEC_H265_DEC_SPS_HDR_CHROMA_FORMAT_IDC(sps->chroma_format_idc);
356
357 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_STRONG_INTRA_SMOOTHING_ENABLE,
358 V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED,
359 sps->flags);
360
361 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_SPS_TEMPORAL_MVP_ENABLED,
362 V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED,
363 sps->flags);
364
365 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_SAMPLE_ADAPTIVE_OFFSET_ENABLED,
366 V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET,
367 sps->flags);
368
369 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_AMP_ENABLED,
370 V4L2_HEVC_SPS_FLAG_AMP_ENABLED, sps->flags);
371
372 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_SEPARATE_COLOUR_PLANE,
373 V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE,
374 sps->flags);
375
376 cedrus_write(dev, VE_DEC_H265_DEC_SPS_HDR, reg);
377
378 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) |
379 VE_DEC_H265_DEC_PCM_CTRL_LOG2_MIN_PCM_LUMA_CODING_BLOCK_SIZE_MINUS3(sps->log2_min_pcm_luma_coding_block_size_minus3) |
380 VE_DEC_H265_DEC_PCM_CTRL_PCM_SAMPLE_BIT_DEPTH_CHROMA_MINUS1(sps->pcm_sample_bit_depth_chroma_minus1) |
381 VE_DEC_H265_DEC_PCM_CTRL_PCM_SAMPLE_BIT_DEPTH_LUMA_MINUS1(sps->pcm_sample_bit_depth_luma_minus1);
382
383 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PCM_CTRL_FLAG_PCM_ENABLED,
384 V4L2_HEVC_SPS_FLAG_PCM_ENABLED, sps->flags);
385
386 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PCM_CTRL_FLAG_PCM_LOOP_FILTER_DISABLED,
387 V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED,
388 sps->flags);
389
390 cedrus_write(dev, VE_DEC_H265_DEC_PCM_CTRL, reg);
391
392 /* PPS. */
393
394 reg = VE_DEC_H265_DEC_PPS_CTRL0_PPS_CR_QP_OFFSET(pps->pps_cr_qp_offset) |
395 VE_DEC_H265_DEC_PPS_CTRL0_PPS_CB_QP_OFFSET(pps->pps_cb_qp_offset) |
396 VE_DEC_H265_DEC_PPS_CTRL0_INIT_QP_MINUS26(pps->init_qp_minus26) |
397 VE_DEC_H265_DEC_PPS_CTRL0_DIFF_CU_QP_DELTA_DEPTH(pps->diff_cu_qp_delta_depth);
398
399 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL0_FLAG_CU_QP_DELTA_ENABLED,
400 V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED,
401 pps->flags);
402
403 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL0_FLAG_TRANSFORM_SKIP_ENABLED,
404 V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED,
405 pps->flags);
406
407 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL0_FLAG_CONSTRAINED_INTRA_PRED,
408 V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED,
409 pps->flags);
410
411 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL0_FLAG_SIGN_DATA_HIDING_ENABLED,
412 V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED,
413 pps->flags);
414
415 cedrus_write(dev, VE_DEC_H265_DEC_PPS_CTRL0, reg);
416
417 reg = VE_DEC_H265_DEC_PPS_CTRL1_LOG2_PARALLEL_MERGE_LEVEL_MINUS2(pps->log2_parallel_merge_level_minus2);
418
419 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED,
420 V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED,
421 pps->flags);
422
423 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED,
424 V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED,
425 pps->flags);
426
427 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_ENTROPY_CODING_SYNC_ENABLED,
428 V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED,
429 pps->flags);
430
431 /* TODO: VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TILES_ENABLED */
432
433 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TRANSQUANT_BYPASS_ENABLED,
434 V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED,
435 pps->flags);
436
437 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_WEIGHTED_BIPRED,
438 V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED, pps->flags);
439
440 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_WEIGHTED_PRED,
441 V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED, pps->flags);
442
443 cedrus_write(dev, VE_DEC_H265_DEC_PPS_CTRL1, reg);
444
445 /* Slice Parameters. */
446
447 reg = VE_DEC_H265_DEC_SLICE_HDR_INFO0_PICTURE_TYPE(slice_params->pic_struct) |
448 VE_DEC_H265_DEC_SLICE_HDR_INFO0_FIVE_MINUS_MAX_NUM_MERGE_CAND(slice_params->five_minus_max_num_merge_cand) |
449 VE_DEC_H265_DEC_SLICE_HDR_INFO0_NUM_REF_IDX_L1_ACTIVE_MINUS1(slice_params->num_ref_idx_l1_active_minus1) |
450 VE_DEC_H265_DEC_SLICE_HDR_INFO0_NUM_REF_IDX_L0_ACTIVE_MINUS1(slice_params->num_ref_idx_l0_active_minus1) |
451 VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLLOCATED_REF_IDX(slice_params->collocated_ref_idx) |
452 VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLOUR_PLANE_ID(slice_params->colour_plane_id) |
453 VE_DEC_H265_DEC_SLICE_HDR_INFO0_SLICE_TYPE(slice_params->slice_type);
454
455 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_COLLOCATED_FROM_L0,
456 V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0,
457 slice_params->flags);
458
459 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_CABAC_INIT,
460 V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT,
461 slice_params->flags);
462
463 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_MVD_L1_ZERO,
464 V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO,
465 slice_params->flags);
466
467 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_SLICE_SAO_CHROMA,
468 V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA,
469 slice_params->flags);
470
471 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_SLICE_SAO_LUMA,
472 V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA,
473 slice_params->flags);
474
475 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_SLICE_TEMPORAL_MVP_ENABLE,
476 V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED,
477 slice_params->flags);
478
479 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_DEPENDENT_SLICE_SEGMENT,
480 V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT,
481 pps->flags);
482
483 /* FIXME: For multi-slice support. */
484 reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC;
485
486 cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO0, reg);
487
488 reg = VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_TC_OFFSET_DIV2(slice_params->slice_tc_offset_div2) |
489 VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_BETA_OFFSET_DIV2(slice_params->slice_beta_offset_div2) |
490 VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_POC_BIGEST_IN_RPS_ST(slice_params->num_rps_poc_st_curr_after == 0) |
491 VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CR_QP_OFFSET(slice_params->slice_cr_qp_offset) |
492 VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CB_QP_OFFSET(slice_params->slice_cb_qp_offset) |
493 VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_QP_DELTA(slice_params->slice_qp_delta);
494
495 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO1_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED,
496 V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED,
497 slice_params->flags);
498
499 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO1_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED,
500 V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED,
501 slice_params->flags);
502
503 cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO1, reg);
504
505 chroma_log2_weight_denom = pred_weight_table->luma_log2_weight_denom +
506 pred_weight_table->delta_chroma_log2_weight_denom;
507 reg = VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(0) |
508 VE_DEC_H265_DEC_SLICE_HDR_INFO2_CHROMA_LOG2_WEIGHT_DENOM(chroma_log2_weight_denom) |
509 VE_DEC_H265_DEC_SLICE_HDR_INFO2_LUMA_LOG2_WEIGHT_DENOM(pred_weight_table->luma_log2_weight_denom);
510
511 cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO2, reg);
512
513 /* Decoded picture size. */
514
515 reg = VE_DEC_H265_DEC_PIC_SIZE_WIDTH(ctx->src_fmt.width) |
516 VE_DEC_H265_DEC_PIC_SIZE_HEIGHT(ctx->src_fmt.height);
517
518 cedrus_write(dev, VE_DEC_H265_DEC_PIC_SIZE, reg);
519
520 /* Scaling list. */
521
522 reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT;
523 cedrus_write(dev, VE_DEC_H265_SCALING_LIST_CTRL0, reg);
524
525 /* Neightbor information address. */
526 reg = VE_DEC_H265_NEIGHBOR_INFO_ADDR_BASE(ctx->codec.h265.neighbor_info_buf_addr);
527 cedrus_write(dev, VE_DEC_H265_NEIGHBOR_INFO_ADDR, reg);
528
529 /* Write decoded picture buffer in pic list. */
530 cedrus_h265_frame_info_write_dpb(ctx, slice_params->dpb,
531 slice_params->num_active_dpb_entries);
532
533 /* Output frame. */
534
535 output_pic_list_index = V4L2_HEVC_DPB_ENTRIES_NUM_MAX;
536 pic_order_cnt[0] = slice_params->slice_pic_order_cnt;
537 pic_order_cnt[1] = slice_params->slice_pic_order_cnt;
538
539 cedrus_h265_frame_info_write_single(ctx, output_pic_list_index,
540 slice_params->pic_struct != 0,
541 pic_order_cnt,
542 run->dst->vb2_buf.index);
543
544 cedrus_write(dev, VE_DEC_H265_OUTPUT_FRAME_IDX, output_pic_list_index);
545
546 /* Reference picture list 0 (for P/B frames). */
547 if (slice_params->slice_type != V4L2_HEVC_SLICE_TYPE_I) {
548 cedrus_h265_ref_pic_list_write(dev, slice_params->dpb,
549 slice_params->ref_idx_l0,
550 slice_params->num_ref_idx_l0_active_minus1 + 1,
551 VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST0);
552
553 if ((pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED) ||
554 (pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED))
555 cedrus_h265_pred_weight_write(dev,
556 pred_weight_table->delta_luma_weight_l0,
557 pred_weight_table->luma_offset_l0,
558 pred_weight_table->delta_chroma_weight_l0,
559 pred_weight_table->chroma_offset_l0,
560 slice_params->num_ref_idx_l0_active_minus1 + 1,
561 VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L0,
562 VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L0);
563 }
564
565 /* Reference picture list 1 (for B frames). */
566 if (slice_params->slice_type == V4L2_HEVC_SLICE_TYPE_B) {
567 cedrus_h265_ref_pic_list_write(dev, slice_params->dpb,
568 slice_params->ref_idx_l1,
569 slice_params->num_ref_idx_l1_active_minus1 + 1,
570 VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST1);
571
572 if (pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED)
573 cedrus_h265_pred_weight_write(dev,
574 pred_weight_table->delta_luma_weight_l1,
575 pred_weight_table->luma_offset_l1,
576 pred_weight_table->delta_chroma_weight_l1,
577 pred_weight_table->chroma_offset_l1,
578 slice_params->num_ref_idx_l1_active_minus1 + 1,
579 VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L1,
580 VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L1);
581 }
582
583 /* Enable appropriate interruptions. */
584 cedrus_write(dev, VE_DEC_H265_CTRL, VE_DEC_H265_CTRL_IRQ_MASK);
585 }
586
cedrus_h265_start(struct cedrus_ctx * ctx)587 static int cedrus_h265_start(struct cedrus_ctx *ctx)
588 {
589 struct cedrus_dev *dev = ctx->dev;
590
591 /* The buffer size is calculated at setup time. */
592 ctx->codec.h265.mv_col_buf_size = 0;
593
594 ctx->codec.h265.neighbor_info_buf =
595 dma_alloc_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
596 &ctx->codec.h265.neighbor_info_buf_addr,
597 GFP_KERNEL);
598 if (!ctx->codec.h265.neighbor_info_buf)
599 return -ENOMEM;
600
601 return 0;
602 }
603
cedrus_h265_stop(struct cedrus_ctx * ctx)604 static void cedrus_h265_stop(struct cedrus_ctx *ctx)
605 {
606 struct cedrus_dev *dev = ctx->dev;
607
608 if (ctx->codec.h265.mv_col_buf_size > 0) {
609 dma_free_coherent(dev->dev, ctx->codec.h265.mv_col_buf_size,
610 ctx->codec.h265.mv_col_buf,
611 ctx->codec.h265.mv_col_buf_addr);
612
613 ctx->codec.h265.mv_col_buf_size = 0;
614 }
615
616 dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
617 ctx->codec.h265.neighbor_info_buf,
618 ctx->codec.h265.neighbor_info_buf_addr);
619 }
620
cedrus_h265_trigger(struct cedrus_ctx * ctx)621 static void cedrus_h265_trigger(struct cedrus_ctx *ctx)
622 {
623 struct cedrus_dev *dev = ctx->dev;
624
625 cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_DEC_SLICE);
626 }
627
628 struct cedrus_dec_ops cedrus_dec_ops_h265 = {
629 .irq_clear = cedrus_h265_irq_clear,
630 .irq_disable = cedrus_h265_irq_disable,
631 .irq_status = cedrus_h265_irq_status,
632 .setup = cedrus_h265_setup,
633 .start = cedrus_h265_start,
634 .stop = cedrus_h265_stop,
635 .trigger = cedrus_h265_trigger,
636 };
637