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_2bit_size(unsigned int width,unsigned int height)44 static unsigned int cedrus_h265_2bit_size(unsigned int width,
45 unsigned int height)
46 {
47 /*
48 * Vendor library additionally aligns width and height to 16,
49 * but all capture formats are already aligned to that anyway,
50 * so we can skip that here. All formats are also one form of
51 * YUV 4:2:0 or another, so we can safely assume multiplication
52 * factor of 1.5.
53 */
54 return ALIGN(width / 4, 32) * height * 3 / 2;
55 }
56
cedrus_h265_irq_status(struct cedrus_ctx * ctx)57 static enum cedrus_irq_status cedrus_h265_irq_status(struct cedrus_ctx *ctx)
58 {
59 struct cedrus_dev *dev = ctx->dev;
60 u32 reg;
61
62 reg = cedrus_read(dev, VE_DEC_H265_STATUS);
63 reg &= VE_DEC_H265_STATUS_CHECK_MASK;
64
65 if (reg & VE_DEC_H265_STATUS_CHECK_ERROR ||
66 !(reg & VE_DEC_H265_STATUS_SUCCESS))
67 return CEDRUS_IRQ_ERROR;
68
69 return CEDRUS_IRQ_OK;
70 }
71
cedrus_h265_irq_clear(struct cedrus_ctx * ctx)72 static void cedrus_h265_irq_clear(struct cedrus_ctx *ctx)
73 {
74 struct cedrus_dev *dev = ctx->dev;
75
76 cedrus_write(dev, VE_DEC_H265_STATUS, VE_DEC_H265_STATUS_CHECK_MASK);
77 }
78
cedrus_h265_irq_disable(struct cedrus_ctx * ctx)79 static void cedrus_h265_irq_disable(struct cedrus_ctx *ctx)
80 {
81 struct cedrus_dev *dev = ctx->dev;
82 u32 reg = cedrus_read(dev, VE_DEC_H265_CTRL);
83
84 reg &= ~VE_DEC_H265_CTRL_IRQ_MASK;
85
86 cedrus_write(dev, VE_DEC_H265_CTRL, reg);
87 }
88
cedrus_h265_sram_write_offset(struct cedrus_dev * dev,u32 offset)89 static void cedrus_h265_sram_write_offset(struct cedrus_dev *dev, u32 offset)
90 {
91 cedrus_write(dev, VE_DEC_H265_SRAM_OFFSET, offset);
92 }
93
cedrus_h265_sram_write_data(struct cedrus_dev * dev,void * data,unsigned int size)94 static void cedrus_h265_sram_write_data(struct cedrus_dev *dev, void *data,
95 unsigned int size)
96 {
97 u32 *word = data;
98
99 while (size >= sizeof(u32)) {
100 cedrus_write(dev, VE_DEC_H265_SRAM_DATA, *word++);
101 size -= sizeof(u32);
102 }
103 }
104
105 static inline dma_addr_t
cedrus_h265_frame_info_mv_col_buf_addr(struct vb2_buffer * buf,unsigned int field)106 cedrus_h265_frame_info_mv_col_buf_addr(struct vb2_buffer *buf,
107 unsigned int field)
108 {
109 struct cedrus_buffer *cedrus_buf = vb2_to_cedrus_buffer(buf);
110
111 return cedrus_buf->codec.h265.mv_col_buf_dma +
112 field * cedrus_buf->codec.h265.mv_col_buf_size / 2;
113 }
114
cedrus_h265_frame_info_write_single(struct cedrus_ctx * ctx,unsigned int index,bool field_pic,u32 pic_order_cnt[],struct vb2_buffer * buf)115 static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx,
116 unsigned int index,
117 bool field_pic,
118 u32 pic_order_cnt[],
119 struct vb2_buffer *buf)
120 {
121 struct cedrus_dev *dev = ctx->dev;
122 dma_addr_t dst_luma_addr = cedrus_dst_buf_addr(ctx, buf, 0);
123 dma_addr_t dst_chroma_addr = cedrus_dst_buf_addr(ctx, buf, 1);
124 dma_addr_t mv_col_buf_addr[2] = {
125 cedrus_h265_frame_info_mv_col_buf_addr(buf, 0),
126 cedrus_h265_frame_info_mv_col_buf_addr(buf, field_pic ? 1 : 0)
127 };
128 u32 offset = VE_DEC_H265_SRAM_OFFSET_FRAME_INFO +
129 VE_DEC_H265_SRAM_OFFSET_FRAME_INFO_UNIT * index;
130 struct cedrus_h265_sram_frame_info frame_info = {
131 .top_pic_order_cnt = cpu_to_le32(pic_order_cnt[0]),
132 .bottom_pic_order_cnt = cpu_to_le32(field_pic ?
133 pic_order_cnt[1] :
134 pic_order_cnt[0]),
135 .top_mv_col_buf_addr =
136 cpu_to_le32(VE_DEC_H265_SRAM_DATA_ADDR_BASE(mv_col_buf_addr[0])),
137 .bottom_mv_col_buf_addr = cpu_to_le32(field_pic ?
138 VE_DEC_H265_SRAM_DATA_ADDR_BASE(mv_col_buf_addr[1]) :
139 VE_DEC_H265_SRAM_DATA_ADDR_BASE(mv_col_buf_addr[0])),
140 .luma_addr = cpu_to_le32(VE_DEC_H265_SRAM_DATA_ADDR_BASE(dst_luma_addr)),
141 .chroma_addr = cpu_to_le32(VE_DEC_H265_SRAM_DATA_ADDR_BASE(dst_chroma_addr)),
142 };
143
144 cedrus_h265_sram_write_offset(dev, offset);
145 cedrus_h265_sram_write_data(dev, &frame_info, sizeof(frame_info));
146 }
147
cedrus_h265_frame_info_write_dpb(struct cedrus_ctx * ctx,const struct v4l2_hevc_dpb_entry * dpb,u8 num_active_dpb_entries)148 static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx,
149 const struct v4l2_hevc_dpb_entry *dpb,
150 u8 num_active_dpb_entries)
151 {
152 struct vb2_queue *vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
153 V4L2_BUF_TYPE_VIDEO_CAPTURE);
154 unsigned int i;
155
156 for (i = 0; i < num_active_dpb_entries; i++) {
157 struct vb2_buffer *buf = vb2_find_buffer(vq, dpb[i].timestamp);
158 u32 pic_order_cnt[2] = {
159 dpb[i].pic_order_cnt_val,
160 dpb[i].pic_order_cnt_val
161 };
162
163 if (!buf)
164 continue;
165
166 cedrus_h265_frame_info_write_single(ctx, i, dpb[i].field_pic,
167 pic_order_cnt,
168 buf);
169 }
170 }
171
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)172 static void cedrus_h265_ref_pic_list_write(struct cedrus_dev *dev,
173 const struct v4l2_hevc_dpb_entry *dpb,
174 const u8 list[],
175 u8 num_ref_idx_active,
176 u32 sram_offset)
177 {
178 unsigned int i;
179 u32 word = 0;
180
181 cedrus_h265_sram_write_offset(dev, sram_offset);
182
183 for (i = 0; i < num_ref_idx_active; i++) {
184 unsigned int shift = (i % 4) * 8;
185 unsigned int index = list[i];
186 u8 value = list[i];
187
188 if (dpb[index].flags & V4L2_HEVC_DPB_ENTRY_LONG_TERM_REFERENCE)
189 value |= VE_DEC_H265_SRAM_REF_PIC_LIST_LT_REF;
190
191 /* Each SRAM word gathers up to 4 references. */
192 word |= value << shift;
193
194 /* Write the word to SRAM and clear it for the next batch. */
195 if ((i % 4) == 3 || i == (num_ref_idx_active - 1)) {
196 cedrus_h265_sram_write_data(dev, &word, sizeof(word));
197 word = 0;
198 }
199 }
200 }
201
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)202 static void cedrus_h265_pred_weight_write(struct cedrus_dev *dev,
203 const s8 delta_luma_weight[],
204 const s8 luma_offset[],
205 const s8 delta_chroma_weight[][2],
206 const s8 chroma_offset[][2],
207 u8 num_ref_idx_active,
208 u32 sram_luma_offset,
209 u32 sram_chroma_offset)
210 {
211 struct cedrus_h265_sram_pred_weight pred_weight[2] = { { 0 } };
212 unsigned int i, j;
213
214 cedrus_h265_sram_write_offset(dev, sram_luma_offset);
215
216 for (i = 0; i < num_ref_idx_active; i++) {
217 unsigned int index = i % 2;
218
219 pred_weight[index].delta_weight = delta_luma_weight[i];
220 pred_weight[index].offset = luma_offset[i];
221
222 if (index == 1 || i == (num_ref_idx_active - 1))
223 cedrus_h265_sram_write_data(dev, (u32 *)&pred_weight,
224 sizeof(pred_weight));
225 }
226
227 cedrus_h265_sram_write_offset(dev, sram_chroma_offset);
228
229 for (i = 0; i < num_ref_idx_active; i++) {
230 for (j = 0; j < 2; j++) {
231 pred_weight[j].delta_weight = delta_chroma_weight[i][j];
232 pred_weight[j].offset = chroma_offset[i][j];
233 }
234
235 cedrus_h265_sram_write_data(dev, &pred_weight,
236 sizeof(pred_weight));
237 }
238 }
239
cedrus_h265_skip_bits(struct cedrus_dev * dev,int num)240 static void cedrus_h265_skip_bits(struct cedrus_dev *dev, int num)
241 {
242 int count = 0;
243
244 while (count < num) {
245 int tmp = min(num - count, 32);
246
247 cedrus_write(dev, VE_DEC_H265_TRIGGER,
248 VE_DEC_H265_TRIGGER_FLUSH_BITS |
249 VE_DEC_H265_TRIGGER_TYPE_N_BITS(tmp));
250
251 if (cedrus_wait_for(dev, VE_DEC_H265_STATUS, VE_DEC_H265_STATUS_VLD_BUSY))
252 dev_err_ratelimited(dev->dev, "timed out waiting to skip bits\n");
253
254 count += tmp;
255 }
256 }
257
cedrus_h265_show_bits(struct cedrus_dev * dev,int num)258 static u32 cedrus_h265_show_bits(struct cedrus_dev *dev, int num)
259 {
260 cedrus_write(dev, VE_DEC_H265_TRIGGER,
261 VE_DEC_H265_TRIGGER_SHOW_BITS |
262 VE_DEC_H265_TRIGGER_TYPE_N_BITS(num));
263
264 cedrus_wait_for(dev, VE_DEC_H265_STATUS,
265 VE_DEC_H265_STATUS_VLD_BUSY);
266
267 return cedrus_read(dev, VE_DEC_H265_BITS_READ);
268 }
269
cedrus_h265_write_scaling_list(struct cedrus_ctx * ctx,struct cedrus_run * run)270 static void cedrus_h265_write_scaling_list(struct cedrus_ctx *ctx,
271 struct cedrus_run *run)
272 {
273 const struct v4l2_ctrl_hevc_scaling_matrix *scaling;
274 struct cedrus_dev *dev = ctx->dev;
275 u32 i, j, k, val;
276
277 scaling = run->h265.scaling_matrix;
278
279 cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF0,
280 (scaling->scaling_list_dc_coef_32x32[1] << 24) |
281 (scaling->scaling_list_dc_coef_32x32[0] << 16) |
282 (scaling->scaling_list_dc_coef_16x16[1] << 8) |
283 (scaling->scaling_list_dc_coef_16x16[0] << 0));
284
285 cedrus_write(dev, VE_DEC_H265_SCALING_LIST_DC_COEF1,
286 (scaling->scaling_list_dc_coef_16x16[5] << 24) |
287 (scaling->scaling_list_dc_coef_16x16[4] << 16) |
288 (scaling->scaling_list_dc_coef_16x16[3] << 8) |
289 (scaling->scaling_list_dc_coef_16x16[2] << 0));
290
291 cedrus_h265_sram_write_offset(dev, VE_DEC_H265_SRAM_OFFSET_SCALING_LISTS);
292
293 for (i = 0; i < 6; i++)
294 for (j = 0; j < 8; j++)
295 for (k = 0; k < 8; k += 4) {
296 val = ((u32)scaling->scaling_list_8x8[i][j + (k + 3) * 8] << 24) |
297 ((u32)scaling->scaling_list_8x8[i][j + (k + 2) * 8] << 16) |
298 ((u32)scaling->scaling_list_8x8[i][j + (k + 1) * 8] << 8) |
299 scaling->scaling_list_8x8[i][j + k * 8];
300 cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val);
301 }
302
303 for (i = 0; i < 2; i++)
304 for (j = 0; j < 8; j++)
305 for (k = 0; k < 8; k += 4) {
306 val = ((u32)scaling->scaling_list_32x32[i][j + (k + 3) * 8] << 24) |
307 ((u32)scaling->scaling_list_32x32[i][j + (k + 2) * 8] << 16) |
308 ((u32)scaling->scaling_list_32x32[i][j + (k + 1) * 8] << 8) |
309 scaling->scaling_list_32x32[i][j + k * 8];
310 cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val);
311 }
312
313 for (i = 0; i < 6; i++)
314 for (j = 0; j < 8; j++)
315 for (k = 0; k < 8; k += 4) {
316 val = ((u32)scaling->scaling_list_16x16[i][j + (k + 3) * 8] << 24) |
317 ((u32)scaling->scaling_list_16x16[i][j + (k + 2) * 8] << 16) |
318 ((u32)scaling->scaling_list_16x16[i][j + (k + 1) * 8] << 8) |
319 scaling->scaling_list_16x16[i][j + k * 8];
320 cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val);
321 }
322
323 for (i = 0; i < 6; i++)
324 for (j = 0; j < 4; j++) {
325 val = ((u32)scaling->scaling_list_4x4[i][j + 12] << 24) |
326 ((u32)scaling->scaling_list_4x4[i][j + 8] << 16) |
327 ((u32)scaling->scaling_list_4x4[i][j + 4] << 8) |
328 scaling->scaling_list_4x4[i][j];
329 cedrus_write(dev, VE_DEC_H265_SRAM_DATA, val);
330 }
331 }
332
cedrus_h265_is_low_delay(struct cedrus_run * run)333 static int cedrus_h265_is_low_delay(struct cedrus_run *run)
334 {
335 const struct v4l2_ctrl_hevc_slice_params *slice_params;
336 const struct v4l2_hevc_dpb_entry *dpb;
337 s32 poc;
338 int i;
339
340 slice_params = run->h265.slice_params;
341 poc = run->h265.decode_params->pic_order_cnt_val;
342 dpb = run->h265.decode_params->dpb;
343
344 for (i = 0; i < slice_params->num_ref_idx_l0_active_minus1 + 1; i++)
345 if (dpb[slice_params->ref_idx_l0[i]].pic_order_cnt_val > poc)
346 return 1;
347
348 if (slice_params->slice_type != V4L2_HEVC_SLICE_TYPE_B)
349 return 0;
350
351 for (i = 0; i < slice_params->num_ref_idx_l1_active_minus1 + 1; i++)
352 if (dpb[slice_params->ref_idx_l1[i]].pic_order_cnt_val > poc)
353 return 1;
354
355 return 0;
356 }
357
cedrus_h265_write_tiles(struct cedrus_ctx * ctx,struct cedrus_run * run,unsigned int ctb_addr_x,unsigned int ctb_addr_y)358 static void cedrus_h265_write_tiles(struct cedrus_ctx *ctx,
359 struct cedrus_run *run,
360 unsigned int ctb_addr_x,
361 unsigned int ctb_addr_y)
362 {
363 const struct v4l2_ctrl_hevc_slice_params *slice_params;
364 const struct v4l2_ctrl_hevc_pps *pps;
365 struct cedrus_dev *dev = ctx->dev;
366 const u32 *entry_points;
367 u32 *entry_points_buf;
368 int i, x, tx, y, ty;
369
370 pps = run->h265.pps;
371 slice_params = run->h265.slice_params;
372 entry_points = run->h265.entry_points;
373 entry_points_buf = ctx->codec.h265.entry_points_buf;
374
375 for (x = 0, tx = 0; tx < pps->num_tile_columns_minus1 + 1; tx++) {
376 if (x + pps->column_width_minus1[tx] + 1 > ctb_addr_x)
377 break;
378
379 x += pps->column_width_minus1[tx] + 1;
380 }
381
382 for (y = 0, ty = 0; ty < pps->num_tile_rows_minus1 + 1; ty++) {
383 if (y + pps->row_height_minus1[ty] + 1 > ctb_addr_y)
384 break;
385
386 y += pps->row_height_minus1[ty] + 1;
387 }
388
389 cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, (y << 16) | (x << 0));
390 cedrus_write(dev, VE_DEC_H265_TILE_END_CTB,
391 ((y + pps->row_height_minus1[ty]) << 16) |
392 ((x + pps->column_width_minus1[tx]) << 0));
393
394 if (pps->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED) {
395 for (i = 0; i < slice_params->num_entry_point_offsets; i++)
396 entry_points_buf[i] = entry_points[i];
397 } else {
398 for (i = 0; i < slice_params->num_entry_point_offsets; i++) {
399 if (tx + 1 >= pps->num_tile_columns_minus1 + 1) {
400 x = 0;
401 tx = 0;
402 y += pps->row_height_minus1[ty++] + 1;
403 } else {
404 x += pps->column_width_minus1[tx++] + 1;
405 }
406
407 entry_points_buf[i * 4 + 0] = entry_points[i];
408 entry_points_buf[i * 4 + 1] = 0x0;
409 entry_points_buf[i * 4 + 2] = (y << 16) | (x << 0);
410 entry_points_buf[i * 4 + 3] =
411 ((y + pps->row_height_minus1[ty]) << 16) |
412 ((x + pps->column_width_minus1[tx]) << 0);
413 }
414 }
415 }
416
cedrus_h265_setup(struct cedrus_ctx * ctx,struct cedrus_run * run)417 static int cedrus_h265_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
418 {
419 struct cedrus_dev *dev = ctx->dev;
420 const struct v4l2_ctrl_hevc_sps *sps;
421 const struct v4l2_ctrl_hevc_pps *pps;
422 const struct v4l2_ctrl_hevc_slice_params *slice_params;
423 const struct v4l2_ctrl_hevc_decode_params *decode_params;
424 const struct v4l2_hevc_pred_weight_table *pred_weight_table;
425 unsigned int width_in_ctb_luma, ctb_size_luma;
426 unsigned int log2_max_luma_coding_block_size;
427 unsigned int ctb_addr_x, ctb_addr_y;
428 struct cedrus_buffer *cedrus_buf;
429 dma_addr_t src_buf_addr;
430 dma_addr_t src_buf_end_addr;
431 u32 chroma_log2_weight_denom;
432 u32 num_entry_point_offsets;
433 u32 output_pic_list_index;
434 u32 pic_order_cnt[2];
435 u8 padding;
436 int count;
437 u32 reg;
438
439 sps = run->h265.sps;
440 pps = run->h265.pps;
441 slice_params = run->h265.slice_params;
442 decode_params = run->h265.decode_params;
443 pred_weight_table = &slice_params->pred_weight_table;
444 num_entry_point_offsets = slice_params->num_entry_point_offsets;
445 cedrus_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf);
446
447 /*
448 * If entry points offsets are present, we should get them
449 * exactly the right amount.
450 */
451 if (num_entry_point_offsets &&
452 num_entry_point_offsets != run->h265.entry_points_count)
453 return -ERANGE;
454
455 log2_max_luma_coding_block_size =
456 sps->log2_min_luma_coding_block_size_minus3 + 3 +
457 sps->log2_diff_max_min_luma_coding_block_size;
458 ctb_size_luma = 1UL << log2_max_luma_coding_block_size;
459 width_in_ctb_luma =
460 DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma);
461
462 /* MV column buffer size and allocation. */
463 if (!cedrus_buf->codec.h265.mv_col_buf_size) {
464 /*
465 * Each CTB requires a MV col buffer with a specific unit size.
466 * Since the address is given with missing lsb bits, 1 KiB is
467 * added to each buffer to ensure proper alignment.
468 */
469 cedrus_buf->codec.h265.mv_col_buf_size =
470 DIV_ROUND_UP(ctx->src_fmt.width, ctb_size_luma) *
471 DIV_ROUND_UP(ctx->src_fmt.height, ctb_size_luma) *
472 CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE + SZ_1K;
473
474 /* Buffer is never accessed by CPU, so we can skip kernel mapping. */
475 cedrus_buf->codec.h265.mv_col_buf =
476 dma_alloc_attrs(dev->dev,
477 cedrus_buf->codec.h265.mv_col_buf_size,
478 &cedrus_buf->codec.h265.mv_col_buf_dma,
479 GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING);
480 if (!cedrus_buf->codec.h265.mv_col_buf) {
481 cedrus_buf->codec.h265.mv_col_buf_size = 0;
482 return -ENOMEM;
483 }
484 }
485
486 /* Activate H265 engine. */
487 cedrus_engine_enable(ctx);
488
489 /* Source offset and length in bits. */
490
491 cedrus_write(dev, VE_DEC_H265_BITS_OFFSET, 0);
492
493 reg = slice_params->bit_size;
494 cedrus_write(dev, VE_DEC_H265_BITS_LEN, reg);
495
496 /* Source beginning and end addresses. */
497
498 src_buf_addr = vb2_dma_contig_plane_dma_addr(&run->src->vb2_buf, 0);
499
500 reg = VE_DEC_H265_BITS_ADDR_BASE(src_buf_addr);
501 reg |= VE_DEC_H265_BITS_ADDR_VALID_SLICE_DATA;
502 reg |= VE_DEC_H265_BITS_ADDR_LAST_SLICE_DATA;
503 reg |= VE_DEC_H265_BITS_ADDR_FIRST_SLICE_DATA;
504
505 cedrus_write(dev, VE_DEC_H265_BITS_ADDR, reg);
506
507 src_buf_end_addr = src_buf_addr +
508 DIV_ROUND_UP(slice_params->bit_size, 8);
509
510 reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_end_addr);
511 cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg);
512
513 /* Coding tree block address */
514 ctb_addr_x = slice_params->slice_segment_addr % width_in_ctb_luma;
515 ctb_addr_y = slice_params->slice_segment_addr / width_in_ctb_luma;
516 reg = VE_DEC_H265_DEC_CTB_ADDR_X(ctb_addr_x);
517 reg |= VE_DEC_H265_DEC_CTB_ADDR_Y(ctb_addr_y);
518 cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg);
519
520 if ((pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED) ||
521 (pps->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED)) {
522 cedrus_h265_write_tiles(ctx, run, ctb_addr_x, ctb_addr_y);
523 } else {
524 cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0);
525 cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0);
526 }
527
528 /* Clear the number of correctly-decoded coding tree blocks. */
529 if (ctx->fh.m2m_ctx->new_frame)
530 cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0);
531
532 /* Initialize bitstream access. */
533 cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_INIT_SWDEC);
534
535 /*
536 * Cedrus expects that bitstream pointer is actually at the end of the slice header
537 * instead of start of slice data. Padding is 8 bits at most (one bit set to 1 and
538 * at most seven bits set to 0), so we have to inspect only one byte before slice data.
539 */
540
541 if (slice_params->data_byte_offset == 0)
542 return -EOPNOTSUPP;
543
544 cedrus_h265_skip_bits(dev, (slice_params->data_byte_offset - 1) * 8);
545
546 padding = cedrus_h265_show_bits(dev, 8);
547
548 /* at least one bit must be set in that byte */
549 if (padding == 0)
550 return -EINVAL;
551
552 for (count = 0; count < 8; count++)
553 if (padding & (1 << count))
554 break;
555
556 /* Include the one bit. */
557 count++;
558
559 cedrus_h265_skip_bits(dev, 8 - count);
560
561 /* Bitstream parameters. */
562
563 reg = VE_DEC_H265_DEC_NAL_HDR_NAL_UNIT_TYPE(slice_params->nal_unit_type) |
564 VE_DEC_H265_DEC_NAL_HDR_NUH_TEMPORAL_ID_PLUS1(slice_params->nuh_temporal_id_plus1);
565
566 cedrus_write(dev, VE_DEC_H265_DEC_NAL_HDR, reg);
567
568 /* SPS. */
569
570 reg = VE_DEC_H265_DEC_SPS_HDR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTRA(sps->max_transform_hierarchy_depth_intra) |
571 VE_DEC_H265_DEC_SPS_HDR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTER(sps->max_transform_hierarchy_depth_inter) |
572 VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_TRANSFORM_BLOCK_SIZE(sps->log2_diff_max_min_luma_transform_block_size) |
573 VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_TRANSFORM_BLOCK_SIZE_MINUS2(sps->log2_min_luma_transform_block_size_minus2) |
574 VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE(sps->log2_diff_max_min_luma_coding_block_size) |
575 VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_LUMA_CODING_BLOCK_SIZE_MINUS3(sps->log2_min_luma_coding_block_size_minus3) |
576 VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_CHROMA_MINUS8(sps->bit_depth_chroma_minus8) |
577 VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_LUMA_MINUS8(sps->bit_depth_luma_minus8) |
578 VE_DEC_H265_DEC_SPS_HDR_CHROMA_FORMAT_IDC(sps->chroma_format_idc);
579
580 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_STRONG_INTRA_SMOOTHING_ENABLE,
581 V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED,
582 sps->flags);
583
584 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_SPS_TEMPORAL_MVP_ENABLED,
585 V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED,
586 sps->flags);
587
588 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_SAMPLE_ADAPTIVE_OFFSET_ENABLED,
589 V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET,
590 sps->flags);
591
592 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_AMP_ENABLED,
593 V4L2_HEVC_SPS_FLAG_AMP_ENABLED, sps->flags);
594
595 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_SEPARATE_COLOUR_PLANE,
596 V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE,
597 sps->flags);
598
599 cedrus_write(dev, VE_DEC_H265_DEC_SPS_HDR, reg);
600
601 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) |
602 VE_DEC_H265_DEC_PCM_CTRL_LOG2_MIN_PCM_LUMA_CODING_BLOCK_SIZE_MINUS3(sps->log2_min_pcm_luma_coding_block_size_minus3) |
603 VE_DEC_H265_DEC_PCM_CTRL_PCM_SAMPLE_BIT_DEPTH_CHROMA_MINUS1(sps->pcm_sample_bit_depth_chroma_minus1) |
604 VE_DEC_H265_DEC_PCM_CTRL_PCM_SAMPLE_BIT_DEPTH_LUMA_MINUS1(sps->pcm_sample_bit_depth_luma_minus1);
605
606 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PCM_CTRL_FLAG_PCM_ENABLED,
607 V4L2_HEVC_SPS_FLAG_PCM_ENABLED, sps->flags);
608
609 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PCM_CTRL_FLAG_PCM_LOOP_FILTER_DISABLED,
610 V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED,
611 sps->flags);
612
613 cedrus_write(dev, VE_DEC_H265_DEC_PCM_CTRL, reg);
614
615 /* PPS. */
616
617 reg = VE_DEC_H265_DEC_PPS_CTRL0_PPS_CR_QP_OFFSET(pps->pps_cr_qp_offset) |
618 VE_DEC_H265_DEC_PPS_CTRL0_PPS_CB_QP_OFFSET(pps->pps_cb_qp_offset) |
619 VE_DEC_H265_DEC_PPS_CTRL0_INIT_QP_MINUS26(pps->init_qp_minus26) |
620 VE_DEC_H265_DEC_PPS_CTRL0_DIFF_CU_QP_DELTA_DEPTH(pps->diff_cu_qp_delta_depth);
621
622 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL0_FLAG_CU_QP_DELTA_ENABLED,
623 V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED,
624 pps->flags);
625
626 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL0_FLAG_TRANSFORM_SKIP_ENABLED,
627 V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED,
628 pps->flags);
629
630 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL0_FLAG_CONSTRAINED_INTRA_PRED,
631 V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED,
632 pps->flags);
633
634 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL0_FLAG_SIGN_DATA_HIDING_ENABLED,
635 V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED,
636 pps->flags);
637
638 cedrus_write(dev, VE_DEC_H265_DEC_PPS_CTRL0, reg);
639
640 reg = VE_DEC_H265_DEC_PPS_CTRL1_LOG2_PARALLEL_MERGE_LEVEL_MINUS2(pps->log2_parallel_merge_level_minus2);
641
642 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED,
643 V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED,
644 pps->flags);
645
646 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED,
647 V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED,
648 pps->flags);
649
650 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_ENTROPY_CODING_SYNC_ENABLED,
651 V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED,
652 pps->flags);
653
654 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TILES_ENABLED,
655 V4L2_HEVC_PPS_FLAG_TILES_ENABLED,
656 pps->flags);
657
658 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TRANSQUANT_BYPASS_ENABLED,
659 V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED,
660 pps->flags);
661
662 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_WEIGHTED_BIPRED,
663 V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED, pps->flags);
664
665 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_WEIGHTED_PRED,
666 V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED, pps->flags);
667
668 cedrus_write(dev, VE_DEC_H265_DEC_PPS_CTRL1, reg);
669
670 /* Slice Parameters. */
671
672 reg = VE_DEC_H265_DEC_SLICE_HDR_INFO0_PICTURE_TYPE(slice_params->pic_struct) |
673 VE_DEC_H265_DEC_SLICE_HDR_INFO0_FIVE_MINUS_MAX_NUM_MERGE_CAND(slice_params->five_minus_max_num_merge_cand) |
674 VE_DEC_H265_DEC_SLICE_HDR_INFO0_NUM_REF_IDX_L1_ACTIVE_MINUS1(slice_params->num_ref_idx_l1_active_minus1) |
675 VE_DEC_H265_DEC_SLICE_HDR_INFO0_NUM_REF_IDX_L0_ACTIVE_MINUS1(slice_params->num_ref_idx_l0_active_minus1) |
676 VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLLOCATED_REF_IDX(slice_params->collocated_ref_idx) |
677 VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLOUR_PLANE_ID(slice_params->colour_plane_id) |
678 VE_DEC_H265_DEC_SLICE_HDR_INFO0_SLICE_TYPE(slice_params->slice_type);
679
680 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_COLLOCATED_FROM_L0,
681 V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0,
682 slice_params->flags);
683
684 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_CABAC_INIT,
685 V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT,
686 slice_params->flags);
687
688 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_MVD_L1_ZERO,
689 V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO,
690 slice_params->flags);
691
692 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_SLICE_SAO_CHROMA,
693 V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA,
694 slice_params->flags);
695
696 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_SLICE_SAO_LUMA,
697 V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA,
698 slice_params->flags);
699
700 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_SLICE_TEMPORAL_MVP_ENABLE,
701 V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED,
702 slice_params->flags);
703
704 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_DEPENDENT_SLICE_SEGMENT,
705 V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT,
706 slice_params->flags);
707
708 if (ctx->fh.m2m_ctx->new_frame)
709 reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC;
710
711 cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO0, reg);
712
713 reg = VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_TC_OFFSET_DIV2(slice_params->slice_tc_offset_div2) |
714 VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_BETA_OFFSET_DIV2(slice_params->slice_beta_offset_div2) |
715 VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CR_QP_OFFSET(slice_params->slice_cr_qp_offset) |
716 VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CB_QP_OFFSET(slice_params->slice_cb_qp_offset) |
717 VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_QP_DELTA(slice_params->slice_qp_delta);
718
719 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO1_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED,
720 V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED,
721 slice_params->flags);
722
723 reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO1_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED,
724 V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED,
725 slice_params->flags);
726
727 if (slice_params->slice_type != V4L2_HEVC_SLICE_TYPE_I && !cedrus_h265_is_low_delay(run))
728 reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO1_FLAG_SLICE_NOT_LOW_DELAY;
729
730 cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO1, reg);
731
732 chroma_log2_weight_denom = pred_weight_table->luma_log2_weight_denom +
733 pred_weight_table->delta_chroma_log2_weight_denom;
734 reg = VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(num_entry_point_offsets) |
735 VE_DEC_H265_DEC_SLICE_HDR_INFO2_CHROMA_LOG2_WEIGHT_DENOM(chroma_log2_weight_denom) |
736 VE_DEC_H265_DEC_SLICE_HDR_INFO2_LUMA_LOG2_WEIGHT_DENOM(pred_weight_table->luma_log2_weight_denom);
737
738 cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO2, reg);
739
740 cedrus_write(dev, VE_DEC_H265_ENTRY_POINT_OFFSET_ADDR,
741 ctx->codec.h265.entry_points_buf_addr >> 8);
742
743 /* Decoded picture size. */
744
745 reg = VE_DEC_H265_DEC_PIC_SIZE_WIDTH(ctx->src_fmt.width) |
746 VE_DEC_H265_DEC_PIC_SIZE_HEIGHT(ctx->src_fmt.height);
747
748 cedrus_write(dev, VE_DEC_H265_DEC_PIC_SIZE, reg);
749
750 /* Scaling list. */
751
752 if (sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED) {
753 cedrus_h265_write_scaling_list(ctx, run);
754 reg = VE_DEC_H265_SCALING_LIST_CTRL0_FLAG_ENABLED;
755 } else {
756 reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT;
757 }
758 cedrus_write(dev, VE_DEC_H265_SCALING_LIST_CTRL0, reg);
759
760 /* Neightbor information address. */
761 reg = VE_DEC_H265_NEIGHBOR_INFO_ADDR_BASE(ctx->codec.h265.neighbor_info_buf_addr);
762 cedrus_write(dev, VE_DEC_H265_NEIGHBOR_INFO_ADDR, reg);
763
764 /* Write decoded picture buffer in pic list. */
765 cedrus_h265_frame_info_write_dpb(ctx, decode_params->dpb,
766 decode_params->num_active_dpb_entries);
767
768 /* Output frame. */
769
770 output_pic_list_index = V4L2_HEVC_DPB_ENTRIES_NUM_MAX;
771 pic_order_cnt[0] = slice_params->slice_pic_order_cnt;
772 pic_order_cnt[1] = slice_params->slice_pic_order_cnt;
773
774 cedrus_h265_frame_info_write_single(ctx, output_pic_list_index,
775 slice_params->pic_struct != 0,
776 pic_order_cnt,
777 &run->dst->vb2_buf);
778
779 cedrus_write(dev, VE_DEC_H265_OUTPUT_FRAME_IDX, output_pic_list_index);
780
781 /* Reference picture list 0 (for P/B frames). */
782 if (slice_params->slice_type != V4L2_HEVC_SLICE_TYPE_I) {
783 cedrus_h265_ref_pic_list_write(dev, decode_params->dpb,
784 slice_params->ref_idx_l0,
785 slice_params->num_ref_idx_l0_active_minus1 + 1,
786 VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST0);
787
788 if ((pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED) ||
789 (pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED))
790 cedrus_h265_pred_weight_write(dev,
791 pred_weight_table->delta_luma_weight_l0,
792 pred_weight_table->luma_offset_l0,
793 pred_weight_table->delta_chroma_weight_l0,
794 pred_weight_table->chroma_offset_l0,
795 slice_params->num_ref_idx_l0_active_minus1 + 1,
796 VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L0,
797 VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L0);
798 }
799
800 /* Reference picture list 1 (for B frames). */
801 if (slice_params->slice_type == V4L2_HEVC_SLICE_TYPE_B) {
802 cedrus_h265_ref_pic_list_write(dev, decode_params->dpb,
803 slice_params->ref_idx_l1,
804 slice_params->num_ref_idx_l1_active_minus1 + 1,
805 VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST1);
806
807 if (pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED)
808 cedrus_h265_pred_weight_write(dev,
809 pred_weight_table->delta_luma_weight_l1,
810 pred_weight_table->luma_offset_l1,
811 pred_weight_table->delta_chroma_weight_l1,
812 pred_weight_table->chroma_offset_l1,
813 slice_params->num_ref_idx_l1_active_minus1 + 1,
814 VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L1,
815 VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L1);
816 }
817
818 if (ctx->bit_depth > 8) {
819 unsigned int stride = ALIGN(ctx->dst_fmt.width / 4, 32);
820
821 reg = ctx->dst_fmt.sizeimage -
822 cedrus_h265_2bit_size(ctx->dst_fmt.width,
823 ctx->dst_fmt.height);
824 cedrus_write(dev, VE_DEC_H265_OFFSET_ADDR_FIRST_OUT, reg);
825
826 reg = VE_DEC_H265_10BIT_CONFIGURE_FIRST_2BIT_STRIDE(stride);
827 cedrus_write(dev, VE_DEC_H265_10BIT_CONFIGURE, reg);
828 }
829
830 /* Enable appropriate interruptions. */
831 cedrus_write(dev, VE_DEC_H265_CTRL, VE_DEC_H265_CTRL_IRQ_MASK);
832
833 return 0;
834 }
835
cedrus_h265_start(struct cedrus_ctx * ctx)836 static int cedrus_h265_start(struct cedrus_ctx *ctx)
837 {
838 struct cedrus_dev *dev = ctx->dev;
839
840 /* Buffer is never accessed by CPU, so we can skip kernel mapping. */
841 ctx->codec.h265.neighbor_info_buf =
842 dma_alloc_attrs(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
843 &ctx->codec.h265.neighbor_info_buf_addr,
844 GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING);
845 if (!ctx->codec.h265.neighbor_info_buf)
846 return -ENOMEM;
847
848 ctx->codec.h265.entry_points_buf =
849 dma_alloc_coherent(dev->dev, CEDRUS_H265_ENTRY_POINTS_BUF_SIZE,
850 &ctx->codec.h265.entry_points_buf_addr,
851 GFP_KERNEL);
852 if (!ctx->codec.h265.entry_points_buf) {
853 dma_free_attrs(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
854 ctx->codec.h265.neighbor_info_buf,
855 ctx->codec.h265.neighbor_info_buf_addr,
856 DMA_ATTR_NO_KERNEL_MAPPING);
857 return -ENOMEM;
858 }
859
860 return 0;
861 }
862
cedrus_h265_stop(struct cedrus_ctx * ctx)863 static void cedrus_h265_stop(struct cedrus_ctx *ctx)
864 {
865 struct cedrus_dev *dev = ctx->dev;
866 struct cedrus_buffer *buf;
867 struct vb2_queue *vq;
868 unsigned int i;
869
870 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
871
872 for (i = 0; i < vq->num_buffers; i++) {
873 buf = vb2_to_cedrus_buffer(vb2_get_buffer(vq, i));
874
875 if (buf->codec.h265.mv_col_buf_size > 0) {
876 dma_free_attrs(dev->dev,
877 buf->codec.h265.mv_col_buf_size,
878 buf->codec.h265.mv_col_buf,
879 buf->codec.h265.mv_col_buf_dma,
880 DMA_ATTR_NO_KERNEL_MAPPING);
881
882 buf->codec.h265.mv_col_buf_size = 0;
883 }
884 }
885
886 dma_free_attrs(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
887 ctx->codec.h265.neighbor_info_buf,
888 ctx->codec.h265.neighbor_info_buf_addr,
889 DMA_ATTR_NO_KERNEL_MAPPING);
890 dma_free_coherent(dev->dev, CEDRUS_H265_ENTRY_POINTS_BUF_SIZE,
891 ctx->codec.h265.entry_points_buf,
892 ctx->codec.h265.entry_points_buf_addr);
893 }
894
cedrus_h265_trigger(struct cedrus_ctx * ctx)895 static void cedrus_h265_trigger(struct cedrus_ctx *ctx)
896 {
897 struct cedrus_dev *dev = ctx->dev;
898
899 cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_DEC_SLICE);
900 }
901
cedrus_h265_extra_cap_size(struct cedrus_ctx * ctx,struct v4l2_pix_format * pix_fmt)902 static unsigned int cedrus_h265_extra_cap_size(struct cedrus_ctx *ctx,
903 struct v4l2_pix_format *pix_fmt)
904 {
905 if (ctx->bit_depth > 8)
906 return cedrus_h265_2bit_size(pix_fmt->width, pix_fmt->height);
907
908 return 0;
909 }
910
911 struct cedrus_dec_ops cedrus_dec_ops_h265 = {
912 .irq_clear = cedrus_h265_irq_clear,
913 .irq_disable = cedrus_h265_irq_disable,
914 .irq_status = cedrus_h265_irq_status,
915 .setup = cedrus_h265_setup,
916 .start = cedrus_h265_start,
917 .stop = cedrus_h265_stop,
918 .trigger = cedrus_h265_trigger,
919 .extra_cap_size = cedrus_h265_extra_cap_size,
920 };
921