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