1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Cedrus VPU driver
4  *
5  * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
6  * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
7  * Copyright (C) 2018 Bootlin
8  *
9  * Based on the vim2m driver, that is:
10  *
11  * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
12  * Pawel Osciak, <pawel@osciak.com>
13  * Marek Szyprowski, <m.szyprowski@samsung.com>
14  */
15 
16 #include <linux/pm_runtime.h>
17 
18 #include <media/videobuf2-dma-contig.h>
19 #include <media/v4l2-device.h>
20 #include <media/v4l2-ioctl.h>
21 #include <media/v4l2-event.h>
22 #include <media/v4l2-mem2mem.h>
23 
24 #include "cedrus.h"
25 #include "cedrus_video.h"
26 #include "cedrus_dec.h"
27 #include "cedrus_hw.h"
28 
29 #define CEDRUS_DECODE_SRC	BIT(0)
30 #define CEDRUS_DECODE_DST	BIT(1)
31 
32 #define CEDRUS_MIN_WIDTH	16U
33 #define CEDRUS_MIN_HEIGHT	16U
34 #define CEDRUS_MAX_WIDTH	4096U
35 #define CEDRUS_MAX_HEIGHT	2304U
36 
37 static struct cedrus_format cedrus_formats[] = {
38 	{
39 		.pixelformat	= V4L2_PIX_FMT_MPEG2_SLICE,
40 		.directions	= CEDRUS_DECODE_SRC,
41 	},
42 	{
43 		.pixelformat	= V4L2_PIX_FMT_H264_SLICE,
44 		.directions	= CEDRUS_DECODE_SRC,
45 	},
46 	{
47 		.pixelformat	= V4L2_PIX_FMT_HEVC_SLICE,
48 		.directions	= CEDRUS_DECODE_SRC,
49 		.capabilities	= CEDRUS_CAPABILITY_H265_DEC,
50 	},
51 	{
52 		.pixelformat	= V4L2_PIX_FMT_SUNXI_TILED_NV12,
53 		.directions	= CEDRUS_DECODE_DST,
54 	},
55 	{
56 		.pixelformat	= V4L2_PIX_FMT_NV12,
57 		.directions	= CEDRUS_DECODE_DST,
58 		.capabilities	= CEDRUS_CAPABILITY_UNTILED,
59 	},
60 };
61 
62 #define CEDRUS_FORMATS_COUNT	ARRAY_SIZE(cedrus_formats)
63 
64 static inline struct cedrus_ctx *cedrus_file2ctx(struct file *file)
65 {
66 	return container_of(file->private_data, struct cedrus_ctx, fh);
67 }
68 
69 static struct cedrus_format *cedrus_find_format(u32 pixelformat, u32 directions,
70 						unsigned int capabilities)
71 {
72 	struct cedrus_format *first_valid_fmt = NULL;
73 	struct cedrus_format *fmt;
74 	unsigned int i;
75 
76 	for (i = 0; i < CEDRUS_FORMATS_COUNT; i++) {
77 		fmt = &cedrus_formats[i];
78 
79 		if ((fmt->capabilities & capabilities) != fmt->capabilities ||
80 		    !(fmt->directions & directions))
81 			continue;
82 
83 		if (fmt->pixelformat == pixelformat)
84 			break;
85 
86 		if (!first_valid_fmt)
87 			first_valid_fmt = fmt;
88 	}
89 
90 	if (i == CEDRUS_FORMATS_COUNT)
91 		return first_valid_fmt;
92 
93 	return &cedrus_formats[i];
94 }
95 
96 void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt)
97 {
98 	unsigned int width = pix_fmt->width;
99 	unsigned int height = pix_fmt->height;
100 	unsigned int sizeimage = pix_fmt->sizeimage;
101 	unsigned int bytesperline = pix_fmt->bytesperline;
102 
103 	pix_fmt->field = V4L2_FIELD_NONE;
104 
105 	/* Limit to hardware min/max. */
106 	width = clamp(width, CEDRUS_MIN_WIDTH, CEDRUS_MAX_WIDTH);
107 	height = clamp(height, CEDRUS_MIN_HEIGHT, CEDRUS_MAX_HEIGHT);
108 
109 	switch (pix_fmt->pixelformat) {
110 	case V4L2_PIX_FMT_MPEG2_SLICE:
111 	case V4L2_PIX_FMT_H264_SLICE:
112 	case V4L2_PIX_FMT_HEVC_SLICE:
113 		/* Zero bytes per line for encoded source. */
114 		bytesperline = 0;
115 		/* Choose some minimum size since this can't be 0 */
116 		sizeimage = max_t(u32, SZ_1K, sizeimage);
117 		break;
118 
119 	case V4L2_PIX_FMT_SUNXI_TILED_NV12:
120 		/* 32-aligned stride. */
121 		bytesperline = ALIGN(width, 32);
122 
123 		/* 32-aligned height. */
124 		height = ALIGN(height, 32);
125 
126 		/* Luma plane size. */
127 		sizeimage = bytesperline * height;
128 
129 		/* Chroma plane size. */
130 		sizeimage += bytesperline * height / 2;
131 
132 		break;
133 
134 	case V4L2_PIX_FMT_NV12:
135 		/* 16-aligned stride. */
136 		bytesperline = ALIGN(width, 16);
137 
138 		/* 16-aligned height. */
139 		height = ALIGN(height, 16);
140 
141 		/* Luma plane size. */
142 		sizeimage = bytesperline * height;
143 
144 		/* Chroma plane size. */
145 		sizeimage += bytesperline * height / 2;
146 
147 		break;
148 	}
149 
150 	pix_fmt->width = width;
151 	pix_fmt->height = height;
152 
153 	pix_fmt->bytesperline = bytesperline;
154 	pix_fmt->sizeimage = sizeimage;
155 }
156 
157 static int cedrus_querycap(struct file *file, void *priv,
158 			   struct v4l2_capability *cap)
159 {
160 	strscpy(cap->driver, CEDRUS_NAME, sizeof(cap->driver));
161 	strscpy(cap->card, CEDRUS_NAME, sizeof(cap->card));
162 	snprintf(cap->bus_info, sizeof(cap->bus_info),
163 		 "platform:%s", CEDRUS_NAME);
164 
165 	return 0;
166 }
167 
168 static int cedrus_enum_fmt(struct file *file, struct v4l2_fmtdesc *f,
169 			   u32 direction)
170 {
171 	struct cedrus_ctx *ctx = cedrus_file2ctx(file);
172 	struct cedrus_dev *dev = ctx->dev;
173 	unsigned int capabilities = dev->capabilities;
174 	struct cedrus_format *fmt;
175 	unsigned int i, index;
176 
177 	/* Index among formats that match the requested direction. */
178 	index = 0;
179 
180 	for (i = 0; i < CEDRUS_FORMATS_COUNT; i++) {
181 		fmt = &cedrus_formats[i];
182 
183 		if (fmt->capabilities && (fmt->capabilities & capabilities) !=
184 		    fmt->capabilities)
185 			continue;
186 
187 		if (!(cedrus_formats[i].directions & direction))
188 			continue;
189 
190 		if (index == f->index)
191 			break;
192 
193 		index++;
194 	}
195 
196 	/* Matched format. */
197 	if (i < CEDRUS_FORMATS_COUNT) {
198 		f->pixelformat = cedrus_formats[i].pixelformat;
199 
200 		return 0;
201 	}
202 
203 	return -EINVAL;
204 }
205 
206 static int cedrus_enum_fmt_vid_cap(struct file *file, void *priv,
207 				   struct v4l2_fmtdesc *f)
208 {
209 	return cedrus_enum_fmt(file, f, CEDRUS_DECODE_DST);
210 }
211 
212 static int cedrus_enum_fmt_vid_out(struct file *file, void *priv,
213 				   struct v4l2_fmtdesc *f)
214 {
215 	return cedrus_enum_fmt(file, f, CEDRUS_DECODE_SRC);
216 }
217 
218 static int cedrus_g_fmt_vid_cap(struct file *file, void *priv,
219 				struct v4l2_format *f)
220 {
221 	struct cedrus_ctx *ctx = cedrus_file2ctx(file);
222 
223 	f->fmt.pix = ctx->dst_fmt;
224 	return 0;
225 }
226 
227 static int cedrus_g_fmt_vid_out(struct file *file, void *priv,
228 				struct v4l2_format *f)
229 {
230 	struct cedrus_ctx *ctx = cedrus_file2ctx(file);
231 
232 	f->fmt.pix = ctx->src_fmt;
233 	return 0;
234 }
235 
236 static int cedrus_try_fmt_vid_cap(struct file *file, void *priv,
237 				  struct v4l2_format *f)
238 {
239 	struct cedrus_ctx *ctx = cedrus_file2ctx(file);
240 	struct cedrus_dev *dev = ctx->dev;
241 	struct v4l2_pix_format *pix_fmt = &f->fmt.pix;
242 	struct cedrus_format *fmt =
243 		cedrus_find_format(pix_fmt->pixelformat, CEDRUS_DECODE_DST,
244 				   dev->capabilities);
245 
246 	if (!fmt)
247 		return -EINVAL;
248 
249 	pix_fmt->pixelformat = fmt->pixelformat;
250 	pix_fmt->width = ctx->src_fmt.width;
251 	pix_fmt->height = ctx->src_fmt.height;
252 	cedrus_prepare_format(pix_fmt);
253 
254 	return 0;
255 }
256 
257 static int cedrus_try_fmt_vid_out(struct file *file, void *priv,
258 				  struct v4l2_format *f)
259 {
260 	struct cedrus_ctx *ctx = cedrus_file2ctx(file);
261 	struct cedrus_dev *dev = ctx->dev;
262 	struct v4l2_pix_format *pix_fmt = &f->fmt.pix;
263 	struct cedrus_format *fmt =
264 		cedrus_find_format(pix_fmt->pixelformat, CEDRUS_DECODE_SRC,
265 				   dev->capabilities);
266 
267 	if (!fmt)
268 		return -EINVAL;
269 
270 	pix_fmt->pixelformat = fmt->pixelformat;
271 	cedrus_prepare_format(pix_fmt);
272 
273 	return 0;
274 }
275 
276 static int cedrus_s_fmt_vid_cap(struct file *file, void *priv,
277 				struct v4l2_format *f)
278 {
279 	struct cedrus_ctx *ctx = cedrus_file2ctx(file);
280 	struct vb2_queue *vq;
281 	int ret;
282 
283 	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
284 	if (vb2_is_busy(vq))
285 		return -EBUSY;
286 
287 	ret = cedrus_try_fmt_vid_cap(file, priv, f);
288 	if (ret)
289 		return ret;
290 
291 	ctx->dst_fmt = f->fmt.pix;
292 
293 	return 0;
294 }
295 
296 static int cedrus_s_fmt_vid_out(struct file *file, void *priv,
297 				struct v4l2_format *f)
298 {
299 	struct cedrus_ctx *ctx = cedrus_file2ctx(file);
300 	struct vb2_queue *vq;
301 	struct vb2_queue *peer_vq;
302 	int ret;
303 
304 	ret = cedrus_try_fmt_vid_out(file, priv, f);
305 	if (ret)
306 		return ret;
307 
308 	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
309 	/*
310 	 * In order to support dynamic resolution change,
311 	 * the decoder admits a resolution change, as long
312 	 * as the pixelformat remains. Can't be done if streaming.
313 	 */
314 	if (vb2_is_streaming(vq) || (vb2_is_busy(vq) &&
315 	    f->fmt.pix.pixelformat != ctx->src_fmt.pixelformat))
316 		return -EBUSY;
317 	/*
318 	 * Since format change on the OUTPUT queue will reset
319 	 * the CAPTURE queue, we can't allow doing so
320 	 * when the CAPTURE queue has buffers allocated.
321 	 */
322 	peer_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
323 				  V4L2_BUF_TYPE_VIDEO_CAPTURE);
324 	if (vb2_is_busy(peer_vq))
325 		return -EBUSY;
326 
327 	ret = cedrus_try_fmt_vid_out(file, priv, f);
328 	if (ret)
329 		return ret;
330 
331 	ctx->src_fmt = f->fmt.pix;
332 
333 	switch (ctx->src_fmt.pixelformat) {
334 	case V4L2_PIX_FMT_H264_SLICE:
335 		vq->subsystem_flags |=
336 			VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
337 		break;
338 	default:
339 		vq->subsystem_flags &=
340 			~VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
341 		break;
342 	}
343 
344 	/* Propagate format information to capture. */
345 	ctx->dst_fmt.colorspace = f->fmt.pix.colorspace;
346 	ctx->dst_fmt.xfer_func = f->fmt.pix.xfer_func;
347 	ctx->dst_fmt.ycbcr_enc = f->fmt.pix.ycbcr_enc;
348 	ctx->dst_fmt.quantization = f->fmt.pix.quantization;
349 	ctx->dst_fmt.width = ctx->src_fmt.width;
350 	ctx->dst_fmt.height = ctx->src_fmt.height;
351 	cedrus_prepare_format(&ctx->dst_fmt);
352 
353 	return 0;
354 }
355 
356 const struct v4l2_ioctl_ops cedrus_ioctl_ops = {
357 	.vidioc_querycap		= cedrus_querycap,
358 
359 	.vidioc_enum_fmt_vid_cap	= cedrus_enum_fmt_vid_cap,
360 	.vidioc_g_fmt_vid_cap		= cedrus_g_fmt_vid_cap,
361 	.vidioc_try_fmt_vid_cap		= cedrus_try_fmt_vid_cap,
362 	.vidioc_s_fmt_vid_cap		= cedrus_s_fmt_vid_cap,
363 
364 	.vidioc_enum_fmt_vid_out	= cedrus_enum_fmt_vid_out,
365 	.vidioc_g_fmt_vid_out		= cedrus_g_fmt_vid_out,
366 	.vidioc_try_fmt_vid_out		= cedrus_try_fmt_vid_out,
367 	.vidioc_s_fmt_vid_out		= cedrus_s_fmt_vid_out,
368 
369 	.vidioc_reqbufs			= v4l2_m2m_ioctl_reqbufs,
370 	.vidioc_querybuf		= v4l2_m2m_ioctl_querybuf,
371 	.vidioc_qbuf			= v4l2_m2m_ioctl_qbuf,
372 	.vidioc_dqbuf			= v4l2_m2m_ioctl_dqbuf,
373 	.vidioc_prepare_buf		= v4l2_m2m_ioctl_prepare_buf,
374 	.vidioc_create_bufs		= v4l2_m2m_ioctl_create_bufs,
375 	.vidioc_expbuf			= v4l2_m2m_ioctl_expbuf,
376 
377 	.vidioc_streamon		= v4l2_m2m_ioctl_streamon,
378 	.vidioc_streamoff		= v4l2_m2m_ioctl_streamoff,
379 
380 	.vidioc_try_decoder_cmd		= v4l2_m2m_ioctl_stateless_try_decoder_cmd,
381 	.vidioc_decoder_cmd		= v4l2_m2m_ioctl_stateless_decoder_cmd,
382 
383 	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
384 	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
385 };
386 
387 static int cedrus_queue_setup(struct vb2_queue *vq, unsigned int *nbufs,
388 			      unsigned int *nplanes, unsigned int sizes[],
389 			      struct device *alloc_devs[])
390 {
391 	struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
392 	struct v4l2_pix_format *pix_fmt;
393 
394 	if (V4L2_TYPE_IS_OUTPUT(vq->type))
395 		pix_fmt = &ctx->src_fmt;
396 	else
397 		pix_fmt = &ctx->dst_fmt;
398 
399 	if (*nplanes) {
400 		if (sizes[0] < pix_fmt->sizeimage)
401 			return -EINVAL;
402 	} else {
403 		sizes[0] = pix_fmt->sizeimage;
404 		*nplanes = 1;
405 	}
406 
407 	return 0;
408 }
409 
410 static void cedrus_queue_cleanup(struct vb2_queue *vq, u32 state)
411 {
412 	struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
413 	struct vb2_v4l2_buffer *vbuf;
414 
415 	for (;;) {
416 		if (V4L2_TYPE_IS_OUTPUT(vq->type))
417 			vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
418 		else
419 			vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
420 
421 		if (!vbuf)
422 			return;
423 
424 		v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
425 					   &ctx->hdl);
426 		v4l2_m2m_buf_done(vbuf, state);
427 	}
428 }
429 
430 static int cedrus_buf_out_validate(struct vb2_buffer *vb)
431 {
432 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
433 
434 	vbuf->field = V4L2_FIELD_NONE;
435 	return 0;
436 }
437 
438 static int cedrus_buf_prepare(struct vb2_buffer *vb)
439 {
440 	struct vb2_queue *vq = vb->vb2_queue;
441 	struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
442 	struct v4l2_pix_format *pix_fmt;
443 
444 	if (V4L2_TYPE_IS_OUTPUT(vq->type))
445 		pix_fmt = &ctx->src_fmt;
446 	else
447 		pix_fmt = &ctx->dst_fmt;
448 
449 	if (vb2_plane_size(vb, 0) < pix_fmt->sizeimage)
450 		return -EINVAL;
451 
452 	vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage);
453 
454 	return 0;
455 }
456 
457 static int cedrus_start_streaming(struct vb2_queue *vq, unsigned int count)
458 {
459 	struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
460 	struct cedrus_dev *dev = ctx->dev;
461 	int ret = 0;
462 
463 	switch (ctx->src_fmt.pixelformat) {
464 	case V4L2_PIX_FMT_MPEG2_SLICE:
465 		ctx->current_codec = CEDRUS_CODEC_MPEG2;
466 		break;
467 
468 	case V4L2_PIX_FMT_H264_SLICE:
469 		ctx->current_codec = CEDRUS_CODEC_H264;
470 		break;
471 
472 	case V4L2_PIX_FMT_HEVC_SLICE:
473 		ctx->current_codec = CEDRUS_CODEC_H265;
474 		break;
475 
476 	default:
477 		return -EINVAL;
478 	}
479 
480 	if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
481 		ret = pm_runtime_get_sync(dev->dev);
482 		if (ret < 0)
483 			goto err_cleanup;
484 
485 		if (dev->dec_ops[ctx->current_codec]->start) {
486 			ret = dev->dec_ops[ctx->current_codec]->start(ctx);
487 			if (ret)
488 				goto err_pm;
489 		}
490 	}
491 
492 	return 0;
493 
494 err_pm:
495 	pm_runtime_put(dev->dev);
496 err_cleanup:
497 	cedrus_queue_cleanup(vq, VB2_BUF_STATE_QUEUED);
498 
499 	return ret;
500 }
501 
502 static void cedrus_stop_streaming(struct vb2_queue *vq)
503 {
504 	struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
505 	struct cedrus_dev *dev = ctx->dev;
506 
507 	if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
508 		if (dev->dec_ops[ctx->current_codec]->stop)
509 			dev->dec_ops[ctx->current_codec]->stop(ctx);
510 
511 		pm_runtime_put(dev->dev);
512 	}
513 
514 	cedrus_queue_cleanup(vq, VB2_BUF_STATE_ERROR);
515 }
516 
517 static void cedrus_buf_queue(struct vb2_buffer *vb)
518 {
519 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
520 	struct cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
521 
522 	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
523 }
524 
525 static void cedrus_buf_request_complete(struct vb2_buffer *vb)
526 {
527 	struct cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
528 
529 	v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl);
530 }
531 
532 static struct vb2_ops cedrus_qops = {
533 	.queue_setup		= cedrus_queue_setup,
534 	.buf_prepare		= cedrus_buf_prepare,
535 	.buf_queue		= cedrus_buf_queue,
536 	.buf_out_validate	= cedrus_buf_out_validate,
537 	.buf_request_complete	= cedrus_buf_request_complete,
538 	.start_streaming	= cedrus_start_streaming,
539 	.stop_streaming		= cedrus_stop_streaming,
540 	.wait_prepare		= vb2_ops_wait_prepare,
541 	.wait_finish		= vb2_ops_wait_finish,
542 };
543 
544 int cedrus_queue_init(void *priv, struct vb2_queue *src_vq,
545 		      struct vb2_queue *dst_vq)
546 {
547 	struct cedrus_ctx *ctx = priv;
548 	int ret;
549 
550 	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
551 	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
552 	src_vq->drv_priv = ctx;
553 	src_vq->buf_struct_size = sizeof(struct cedrus_buffer);
554 	src_vq->min_buffers_needed = 1;
555 	src_vq->ops = &cedrus_qops;
556 	src_vq->mem_ops = &vb2_dma_contig_memops;
557 	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
558 	src_vq->lock = &ctx->dev->dev_mutex;
559 	src_vq->dev = ctx->dev->dev;
560 	src_vq->supports_requests = true;
561 	src_vq->requires_requests = true;
562 
563 	ret = vb2_queue_init(src_vq);
564 	if (ret)
565 		return ret;
566 
567 	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
568 	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
569 	dst_vq->drv_priv = ctx;
570 	dst_vq->buf_struct_size = sizeof(struct cedrus_buffer);
571 	dst_vq->min_buffers_needed = 1;
572 	dst_vq->ops = &cedrus_qops;
573 	dst_vq->mem_ops = &vb2_dma_contig_memops;
574 	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
575 	dst_vq->lock = &ctx->dev->dev_mutex;
576 	dst_vq->dev = ctx->dev->dev;
577 
578 	return vb2_queue_init(dst_vq);
579 }
580