File Index
Files and directories
Sign in
FILE

cedrus_h265.c

File preview with syntax highlighting.

linux-6.19.14/drivers/staging/media/sunxi/cedrus/cedrus_h265.c C
  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
 30struct 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
 39struct cedrus_h265_sram_pred_weight {
 40	__s8	delta_weight;
 41	__s8	offset;
 42} __packed;
 43
 44static 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
 57static 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
 72static 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
 79static 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
 89static 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
 94static 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
105static inline dma_addr_t
106cedrus_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
115static 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
148static 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
172static 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
202static 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
240static 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
258static 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
270static 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
333static 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
358static 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
417static 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	u32 chroma_log2_weight_denom;
431	u32 num_entry_point_offsets;
432	u32 output_pic_list_index;
433	u32 pic_order_cnt[2];
434	size_t slice_bytes;
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	slice_bytes = vb2_get_plane_payload(&run->src->vb2_buf, 0);
447
448	/*
449	 * If entry points offsets are present, we should get them
450	 * exactly the right amount.
451	 */
452	if (num_entry_point_offsets &&
453	    num_entry_point_offsets != run->h265.entry_points_count)
454		return -ERANGE;
455
456	log2_max_luma_coding_block_size =
457		sps->log2_min_luma_coding_block_size_minus3 + 3 +
458		sps->log2_diff_max_min_luma_coding_block_size;
459	ctb_size_luma = 1UL << log2_max_luma_coding_block_size;
460	width_in_ctb_luma =
461		DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma);
462
463	/* MV column buffer size and allocation. */
464	if (!cedrus_buf->codec.h265.mv_col_buf_size) {
465		/*
466		 * Each CTB requires a MV col buffer with a specific unit size.
467		 * Since the address is given with missing lsb bits, 1 KiB is
468		 * added to each buffer to ensure proper alignment.
469		 */
470		cedrus_buf->codec.h265.mv_col_buf_size =
471			DIV_ROUND_UP(ctx->src_fmt.width, ctb_size_luma) *
472			DIV_ROUND_UP(ctx->src_fmt.height, ctb_size_luma) *
473			CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE + SZ_1K;
474
475		/* Buffer is never accessed by CPU, so we can skip kernel mapping. */
476		cedrus_buf->codec.h265.mv_col_buf =
477			dma_alloc_attrs(dev->dev,
478					cedrus_buf->codec.h265.mv_col_buf_size,
479					&cedrus_buf->codec.h265.mv_col_buf_dma,
480					GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING);
481		if (!cedrus_buf->codec.h265.mv_col_buf) {
482			cedrus_buf->codec.h265.mv_col_buf_size = 0;
483			return -ENOMEM;
484		}
485	}
486
487	/* Activate H265 engine. */
488	cedrus_engine_enable(ctx);
489
490	/* Source offset and length in bits. */
491
492	cedrus_write(dev, VE_DEC_H265_BITS_OFFSET, 0);
493
494	reg = slice_bytes * 8;
495	cedrus_write(dev, VE_DEC_H265_BITS_LEN, reg);
496
497	/* Source beginning and end addresses. */
498
499	src_buf_addr = vb2_dma_contig_plane_dma_addr(&run->src->vb2_buf, 0);
500
501	reg = VE_DEC_H265_BITS_ADDR_BASE(src_buf_addr);
502	reg |= VE_DEC_H265_BITS_ADDR_VALID_SLICE_DATA;
503	reg |= VE_DEC_H265_BITS_ADDR_LAST_SLICE_DATA;
504	reg |= VE_DEC_H265_BITS_ADDR_FIRST_SLICE_DATA;
505
506	cedrus_write(dev, VE_DEC_H265_BITS_ADDR, reg);
507
508	reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_addr + slice_bytes);
509	cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg);
510
511	/* Coding tree block address */
512	ctb_addr_x = slice_params->slice_segment_addr % width_in_ctb_luma;
513	ctb_addr_y = slice_params->slice_segment_addr / width_in_ctb_luma;
514	reg = VE_DEC_H265_DEC_CTB_ADDR_X(ctb_addr_x);
515	reg |= VE_DEC_H265_DEC_CTB_ADDR_Y(ctb_addr_y);
516	cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg);
517
518	if ((pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED) ||
519	    (pps->flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED)) {
520		cedrus_h265_write_tiles(ctx, run, ctb_addr_x, ctb_addr_y);
521	} else {
522		cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0);
523		cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0);
524	}
525
526	/* Clear the number of correctly-decoded coding tree blocks. */
527	if (ctx->fh.m2m_ctx->new_frame)
528		cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0);
529
530	/* Initialize bitstream access. */
531	cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_INIT_SWDEC);
532
533	/*
534	 * Cedrus expects that bitstream pointer is actually at the end of the slice header
535	 * instead of start of slice data. Padding is 8 bits at most (one bit set to 1 and
536	 * at most seven bits set to 0), so we have to inspect only one byte before slice data.
537	 */
538
539	if (slice_params->data_byte_offset == 0)
540		return -EOPNOTSUPP;
541
542	cedrus_h265_skip_bits(dev, (slice_params->data_byte_offset - 1) * 8);
543
544	padding = cedrus_h265_show_bits(dev, 8);
545
546	/* at least one bit must be set in that byte */
547	if (padding == 0)
548		return -EINVAL;
549
550	for (count = 0; count < 8; count++)
551		if (padding & (1 << count))
552			break;
553
554	/* Include the one bit. */
555	count++;
556
557	cedrus_h265_skip_bits(dev, 8 - count);
558
559	/* Bitstream parameters. */
560
561	reg = VE_DEC_H265_DEC_NAL_HDR_NAL_UNIT_TYPE(slice_params->nal_unit_type) |
562	      VE_DEC_H265_DEC_NAL_HDR_NUH_TEMPORAL_ID_PLUS1(slice_params->nuh_temporal_id_plus1);
563
564	cedrus_write(dev, VE_DEC_H265_DEC_NAL_HDR, reg);
565
566	/* SPS. */
567
568	reg = VE_DEC_H265_DEC_SPS_HDR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTRA(sps->max_transform_hierarchy_depth_intra) |
569	      VE_DEC_H265_DEC_SPS_HDR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTER(sps->max_transform_hierarchy_depth_inter) |
570	      VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_TRANSFORM_BLOCK_SIZE(sps->log2_diff_max_min_luma_transform_block_size) |
571	      VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_TRANSFORM_BLOCK_SIZE_MINUS2(sps->log2_min_luma_transform_block_size_minus2) |
572	      VE_DEC_H265_DEC_SPS_HDR_LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE(sps->log2_diff_max_min_luma_coding_block_size) |
573	      VE_DEC_H265_DEC_SPS_HDR_LOG2_MIN_LUMA_CODING_BLOCK_SIZE_MINUS3(sps->log2_min_luma_coding_block_size_minus3) |
574	      VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_CHROMA_MINUS8(sps->bit_depth_chroma_minus8) |
575	      VE_DEC_H265_DEC_SPS_HDR_BIT_DEPTH_LUMA_MINUS8(sps->bit_depth_luma_minus8) |
576	      VE_DEC_H265_DEC_SPS_HDR_CHROMA_FORMAT_IDC(sps->chroma_format_idc);
577
578	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_STRONG_INTRA_SMOOTHING_ENABLE,
579				V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED,
580				sps->flags);
581
582	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_SPS_TEMPORAL_MVP_ENABLED,
583				V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED,
584				sps->flags);
585
586	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_SAMPLE_ADAPTIVE_OFFSET_ENABLED,
587				V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET,
588				sps->flags);
589
590	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_AMP_ENABLED,
591				V4L2_HEVC_SPS_FLAG_AMP_ENABLED, sps->flags);
592
593	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SPS_HDR_FLAG_SEPARATE_COLOUR_PLANE,
594				V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE,
595				sps->flags);
596
597	cedrus_write(dev, VE_DEC_H265_DEC_SPS_HDR, reg);
598
599	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) |
600	      VE_DEC_H265_DEC_PCM_CTRL_LOG2_MIN_PCM_LUMA_CODING_BLOCK_SIZE_MINUS3(sps->log2_min_pcm_luma_coding_block_size_minus3) |
601	      VE_DEC_H265_DEC_PCM_CTRL_PCM_SAMPLE_BIT_DEPTH_CHROMA_MINUS1(sps->pcm_sample_bit_depth_chroma_minus1) |
602	      VE_DEC_H265_DEC_PCM_CTRL_PCM_SAMPLE_BIT_DEPTH_LUMA_MINUS1(sps->pcm_sample_bit_depth_luma_minus1);
603
604	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PCM_CTRL_FLAG_PCM_ENABLED,
605				V4L2_HEVC_SPS_FLAG_PCM_ENABLED, sps->flags);
606
607	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PCM_CTRL_FLAG_PCM_LOOP_FILTER_DISABLED,
608				V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED,
609				sps->flags);
610
611	cedrus_write(dev, VE_DEC_H265_DEC_PCM_CTRL, reg);
612
613	/* PPS. */
614
615	reg = VE_DEC_H265_DEC_PPS_CTRL0_PPS_CR_QP_OFFSET(pps->pps_cr_qp_offset) |
616	      VE_DEC_H265_DEC_PPS_CTRL0_PPS_CB_QP_OFFSET(pps->pps_cb_qp_offset) |
617	      VE_DEC_H265_DEC_PPS_CTRL0_INIT_QP_MINUS26(pps->init_qp_minus26) |
618	      VE_DEC_H265_DEC_PPS_CTRL0_DIFF_CU_QP_DELTA_DEPTH(pps->diff_cu_qp_delta_depth);
619
620	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL0_FLAG_CU_QP_DELTA_ENABLED,
621				V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED,
622				pps->flags);
623
624	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL0_FLAG_TRANSFORM_SKIP_ENABLED,
625				V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED,
626				pps->flags);
627
628	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL0_FLAG_CONSTRAINED_INTRA_PRED,
629				V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED,
630				pps->flags);
631
632	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL0_FLAG_SIGN_DATA_HIDING_ENABLED,
633				V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED,
634				pps->flags);
635
636	cedrus_write(dev, VE_DEC_H265_DEC_PPS_CTRL0, reg);
637
638	reg = VE_DEC_H265_DEC_PPS_CTRL1_LOG2_PARALLEL_MERGE_LEVEL_MINUS2(pps->log2_parallel_merge_level_minus2);
639
640	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED,
641				V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED,
642				pps->flags);
643
644	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED,
645				V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED,
646				pps->flags);
647
648	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_ENTROPY_CODING_SYNC_ENABLED,
649				V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED,
650				pps->flags);
651
652	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TILES_ENABLED,
653				V4L2_HEVC_PPS_FLAG_TILES_ENABLED,
654				pps->flags);
655
656	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_TRANSQUANT_BYPASS_ENABLED,
657				V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED,
658				pps->flags);
659
660	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_WEIGHTED_BIPRED,
661				V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED, pps->flags);
662
663	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_PPS_CTRL1_FLAG_WEIGHTED_PRED,
664				V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED, pps->flags);
665
666	cedrus_write(dev, VE_DEC_H265_DEC_PPS_CTRL1, reg);
667
668	/* Slice Parameters. */
669
670	reg = VE_DEC_H265_DEC_SLICE_HDR_INFO0_PICTURE_TYPE(slice_params->pic_struct) |
671	      VE_DEC_H265_DEC_SLICE_HDR_INFO0_FIVE_MINUS_MAX_NUM_MERGE_CAND(slice_params->five_minus_max_num_merge_cand) |
672	      VE_DEC_H265_DEC_SLICE_HDR_INFO0_NUM_REF_IDX_L1_ACTIVE_MINUS1(slice_params->num_ref_idx_l1_active_minus1) |
673	      VE_DEC_H265_DEC_SLICE_HDR_INFO0_NUM_REF_IDX_L0_ACTIVE_MINUS1(slice_params->num_ref_idx_l0_active_minus1) |
674	      VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLLOCATED_REF_IDX(slice_params->collocated_ref_idx) |
675	      VE_DEC_H265_DEC_SLICE_HDR_INFO0_COLOUR_PLANE_ID(slice_params->colour_plane_id) |
676	      VE_DEC_H265_DEC_SLICE_HDR_INFO0_SLICE_TYPE(slice_params->slice_type);
677
678	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_COLLOCATED_FROM_L0,
679				V4L2_HEVC_SLICE_PARAMS_FLAG_COLLOCATED_FROM_L0,
680				slice_params->flags);
681
682	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_CABAC_INIT,
683				V4L2_HEVC_SLICE_PARAMS_FLAG_CABAC_INIT,
684				slice_params->flags);
685
686	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_MVD_L1_ZERO,
687				V4L2_HEVC_SLICE_PARAMS_FLAG_MVD_L1_ZERO,
688				slice_params->flags);
689
690	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_SLICE_SAO_CHROMA,
691				V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_CHROMA,
692				slice_params->flags);
693
694	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_SLICE_SAO_LUMA,
695				V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_SAO_LUMA,
696				slice_params->flags);
697
698	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_SLICE_TEMPORAL_MVP_ENABLE,
699				V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED,
700				slice_params->flags);
701
702	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_DEPENDENT_SLICE_SEGMENT,
703				V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT,
704				slice_params->flags);
705
706	if (ctx->fh.m2m_ctx->new_frame)
707		reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC;
708
709	cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO0, reg);
710
711	reg = VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_TC_OFFSET_DIV2(slice_params->slice_tc_offset_div2) |
712	      VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_BETA_OFFSET_DIV2(slice_params->slice_beta_offset_div2) |
713	      VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CR_QP_OFFSET(slice_params->slice_cr_qp_offset) |
714	      VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_CB_QP_OFFSET(slice_params->slice_cb_qp_offset) |
715	      VE_DEC_H265_DEC_SLICE_HDR_INFO1_SLICE_QP_DELTA(slice_params->slice_qp_delta);
716
717	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO1_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED,
718				V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED,
719				slice_params->flags);
720
721	reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO1_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED,
722				V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED,
723				slice_params->flags);
724
725	if (slice_params->slice_type != V4L2_HEVC_SLICE_TYPE_I && !cedrus_h265_is_low_delay(run))
726		reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO1_FLAG_SLICE_NOT_LOW_DELAY;
727
728	cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO1, reg);
729
730	chroma_log2_weight_denom = pred_weight_table->luma_log2_weight_denom +
731				   pred_weight_table->delta_chroma_log2_weight_denom;
732	reg = VE_DEC_H265_DEC_SLICE_HDR_INFO2_NUM_ENTRY_POINT_OFFSETS(num_entry_point_offsets) |
733	      VE_DEC_H265_DEC_SLICE_HDR_INFO2_CHROMA_LOG2_WEIGHT_DENOM(chroma_log2_weight_denom) |
734	      VE_DEC_H265_DEC_SLICE_HDR_INFO2_LUMA_LOG2_WEIGHT_DENOM(pred_weight_table->luma_log2_weight_denom);
735
736	cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO2, reg);
737
738	cedrus_write(dev, VE_DEC_H265_ENTRY_POINT_OFFSET_ADDR,
739		     ctx->codec.h265.entry_points_buf_addr >> 8);
740
741	/* Decoded picture size. */
742
743	reg = VE_DEC_H265_DEC_PIC_SIZE_WIDTH(ctx->src_fmt.width) |
744	      VE_DEC_H265_DEC_PIC_SIZE_HEIGHT(ctx->src_fmt.height);
745
746	cedrus_write(dev, VE_DEC_H265_DEC_PIC_SIZE, reg);
747
748	/* Scaling list. */
749
750	if (sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED) {
751		cedrus_h265_write_scaling_list(ctx, run);
752		reg = VE_DEC_H265_SCALING_LIST_CTRL0_FLAG_ENABLED;
753	} else {
754		reg = VE_DEC_H265_SCALING_LIST_CTRL0_DEFAULT;
755	}
756	cedrus_write(dev, VE_DEC_H265_SCALING_LIST_CTRL0, reg);
757
758	/* Neightbor information address. */
759	reg = VE_DEC_H265_NEIGHBOR_INFO_ADDR_BASE(ctx->codec.h265.neighbor_info_buf_addr);
760	cedrus_write(dev, VE_DEC_H265_NEIGHBOR_INFO_ADDR, reg);
761
762	/* Write decoded picture buffer in pic list. */
763	cedrus_h265_frame_info_write_dpb(ctx, decode_params->dpb,
764					 decode_params->num_active_dpb_entries);
765
766	/* Output frame. */
767
768	output_pic_list_index = V4L2_HEVC_DPB_ENTRIES_NUM_MAX;
769	pic_order_cnt[0] = slice_params->slice_pic_order_cnt;
770	pic_order_cnt[1] = slice_params->slice_pic_order_cnt;
771
772	cedrus_h265_frame_info_write_single(ctx, output_pic_list_index,
773					    slice_params->pic_struct != 0,
774					    pic_order_cnt,
775					    &run->dst->vb2_buf);
776
777	cedrus_write(dev, VE_DEC_H265_OUTPUT_FRAME_IDX, output_pic_list_index);
778
779	/* Reference picture list 0 (for P/B frames). */
780	if (slice_params->slice_type != V4L2_HEVC_SLICE_TYPE_I) {
781		cedrus_h265_ref_pic_list_write(dev, decode_params->dpb,
782					       slice_params->ref_idx_l0,
783					       slice_params->num_ref_idx_l0_active_minus1 + 1,
784					       VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST0);
785
786		if ((pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED) ||
787		    (pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED))
788			cedrus_h265_pred_weight_write(dev,
789						      pred_weight_table->delta_luma_weight_l0,
790						      pred_weight_table->luma_offset_l0,
791						      pred_weight_table->delta_chroma_weight_l0,
792						      pred_weight_table->chroma_offset_l0,
793						      slice_params->num_ref_idx_l0_active_minus1 + 1,
794						      VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L0,
795						      VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L0);
796	}
797
798	/* Reference picture list 1 (for B frames). */
799	if (slice_params->slice_type == V4L2_HEVC_SLICE_TYPE_B) {
800		cedrus_h265_ref_pic_list_write(dev, decode_params->dpb,
801					       slice_params->ref_idx_l1,
802					       slice_params->num_ref_idx_l1_active_minus1 + 1,
803					       VE_DEC_H265_SRAM_OFFSET_REF_PIC_LIST1);
804
805		if (pps->flags & V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED)
806			cedrus_h265_pred_weight_write(dev,
807						      pred_weight_table->delta_luma_weight_l1,
808						      pred_weight_table->luma_offset_l1,
809						      pred_weight_table->delta_chroma_weight_l1,
810						      pred_weight_table->chroma_offset_l1,
811						      slice_params->num_ref_idx_l1_active_minus1 + 1,
812						      VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_LUMA_L1,
813						      VE_DEC_H265_SRAM_OFFSET_PRED_WEIGHT_CHROMA_L1);
814	}
815
816	if (ctx->bit_depth > 8) {
817		unsigned int stride = ALIGN(ctx->dst_fmt.width / 4, 32);
818
819		reg = ctx->dst_fmt.sizeimage -
820		      cedrus_h265_2bit_size(ctx->dst_fmt.width,
821					    ctx->dst_fmt.height);
822		cedrus_write(dev, VE_DEC_H265_OFFSET_ADDR_FIRST_OUT, reg);
823
824		reg = VE_DEC_H265_10BIT_CONFIGURE_FIRST_2BIT_STRIDE(stride);
825		cedrus_write(dev, VE_DEC_H265_10BIT_CONFIGURE, reg);
826	}
827
828	/* Enable appropriate interruptions. */
829	cedrus_write(dev, VE_DEC_H265_CTRL, VE_DEC_H265_CTRL_IRQ_MASK);
830
831	return 0;
832}
833
834static int cedrus_h265_start(struct cedrus_ctx *ctx)
835{
836	struct cedrus_dev *dev = ctx->dev;
837
838	/* Buffer is never accessed by CPU, so we can skip kernel mapping. */
839	ctx->codec.h265.neighbor_info_buf =
840		dma_alloc_attrs(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
841				&ctx->codec.h265.neighbor_info_buf_addr,
842				GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING);
843	if (!ctx->codec.h265.neighbor_info_buf)
844		return -ENOMEM;
845
846	ctx->codec.h265.entry_points_buf =
847		dma_alloc_coherent(dev->dev, CEDRUS_H265_ENTRY_POINTS_BUF_SIZE,
848				   &ctx->codec.h265.entry_points_buf_addr,
849				   GFP_KERNEL);
850	if (!ctx->codec.h265.entry_points_buf) {
851		dma_free_attrs(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
852			       ctx->codec.h265.neighbor_info_buf,
853			       ctx->codec.h265.neighbor_info_buf_addr,
854			       DMA_ATTR_NO_KERNEL_MAPPING);
855		return -ENOMEM;
856	}
857
858	return 0;
859}
860
861static void cedrus_h265_stop(struct cedrus_ctx *ctx)
862{
863	struct cedrus_dev *dev = ctx->dev;
864	struct cedrus_buffer *buf;
865	struct vb2_queue *vq;
866	unsigned int i;
867
868	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
869
870	for (i = 0; i < vb2_get_num_buffers(vq); i++) {
871		struct vb2_buffer *vb = vb2_get_buffer(vq, i);
872
873		if (!vb)
874			continue;
875
876		buf = vb2_to_cedrus_buffer(vb);
877
878		if (buf->codec.h265.mv_col_buf_size > 0) {
879			dma_free_attrs(dev->dev,
880				       buf->codec.h265.mv_col_buf_size,
881				       buf->codec.h265.mv_col_buf,
882				       buf->codec.h265.mv_col_buf_dma,
883				       DMA_ATTR_NO_KERNEL_MAPPING);
884
885			buf->codec.h265.mv_col_buf_size = 0;
886		}
887	}
888
889	dma_free_attrs(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE,
890		       ctx->codec.h265.neighbor_info_buf,
891		       ctx->codec.h265.neighbor_info_buf_addr,
892		       DMA_ATTR_NO_KERNEL_MAPPING);
893	dma_free_coherent(dev->dev, CEDRUS_H265_ENTRY_POINTS_BUF_SIZE,
894			  ctx->codec.h265.entry_points_buf,
895			  ctx->codec.h265.entry_points_buf_addr);
896}
897
898static void cedrus_h265_trigger(struct cedrus_ctx *ctx)
899{
900	struct cedrus_dev *dev = ctx->dev;
901
902	cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_DEC_SLICE);
903}
904
905static unsigned int cedrus_h265_extra_cap_size(struct cedrus_ctx *ctx,
906					       struct v4l2_pix_format *pix_fmt)
907{
908	if (ctx->bit_depth > 8)
909		return cedrus_h265_2bit_size(pix_fmt->width, pix_fmt->height);
910
911	return 0;
912}
913
914struct cedrus_dec_ops cedrus_dec_ops_h265 = {
915	.irq_clear	= cedrus_h265_irq_clear,
916	.irq_disable	= cedrus_h265_irq_disable,
917	.irq_status	= cedrus_h265_irq_status,
918	.setup		= cedrus_h265_setup,
919	.start		= cedrus_h265_start,
920	.stop		= cedrus_h265_stop,
921	.trigger	= cedrus_h265_trigger,
922	.extra_cap_size	= cedrus_h265_extra_cap_size,
923};
~/ Read-only file preview.