hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
kernel/drivers/media/platform/s5p-g2d/g2d.c
....@@ -1,13 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Samsung S5P G2D - 2D Graphics Accelerator Driver
34 *
45 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
56 * Kamil Debski, <k.debski@samsung.com>
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by the
9
- * Free Software Foundation; either version 2 of the
10
- * License, or (at your option) any later version
117 */
128
139 #include <linux/module.h>
....@@ -33,31 +29,26 @@
3329
3430 static struct g2d_fmt formats[] = {
3531 {
36
- .name = "XRGB_8888",
3732 .fourcc = V4L2_PIX_FMT_RGB32,
3833 .depth = 32,
3934 .hw = COLOR_MODE(ORDER_XRGB, MODE_XRGB_8888),
4035 },
4136 {
42
- .name = "RGB_565",
4337 .fourcc = V4L2_PIX_FMT_RGB565X,
4438 .depth = 16,
4539 .hw = COLOR_MODE(ORDER_XRGB, MODE_RGB_565),
4640 },
4741 {
48
- .name = "XRGB_1555",
4942 .fourcc = V4L2_PIX_FMT_RGB555X,
5043 .depth = 16,
5144 .hw = COLOR_MODE(ORDER_XRGB, MODE_XRGB_1555),
5245 },
5346 {
54
- .name = "XRGB_4444",
5547 .fourcc = V4L2_PIX_FMT_RGB444,
5648 .depth = 16,
5749 .hw = COLOR_MODE(ORDER_XRGB, MODE_XRGB_4444),
5850 },
5951 {
60
- .name = "PACKED_RGB_888",
6152 .fourcc = V4L2_PIX_FMT_RGB24,
6253 .depth = 24,
6354 .hw = COLOR_MODE(ORDER_XRGB, MODE_PACKED_RGB_888),
....@@ -89,7 +80,7 @@
8980
9081
9182 static struct g2d_frame *get_frame(struct g2d_ctx *ctx,
92
- enum v4l2_buf_type type)
83
+ enum v4l2_buf_type type)
9384 {
9485 switch (type) {
9586 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
....@@ -300,22 +291,17 @@
300291 static int vidioc_querycap(struct file *file, void *priv,
301292 struct v4l2_capability *cap)
302293 {
303
- strncpy(cap->driver, G2D_NAME, sizeof(cap->driver) - 1);
304
- strncpy(cap->card, G2D_NAME, sizeof(cap->card) - 1);
294
+ strscpy(cap->driver, G2D_NAME, sizeof(cap->driver));
295
+ strscpy(cap->card, G2D_NAME, sizeof(cap->card));
305296 cap->bus_info[0] = 0;
306
- cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
307
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
308297 return 0;
309298 }
310299
311300 static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f)
312301 {
313
- struct g2d_fmt *fmt;
314302 if (f->index >= NUM_FORMATS)
315303 return -EINVAL;
316
- fmt = &formats[f->index];
317
- f->pixelformat = fmt->fourcc;
318
- strncpy(f->description, fmt->name, sizeof(f->description) - 1);
304
+ f->pixelformat = formats[f->index].fourcc;
319305 return 0;
320306 }
321307
....@@ -411,51 +397,76 @@
411397 return 0;
412398 }
413399
414
-static int vidioc_cropcap(struct file *file, void *priv,
415
- struct v4l2_cropcap *cr)
416
-{
417
- struct g2d_ctx *ctx = priv;
418
- struct g2d_frame *f;
419
-
420
- f = get_frame(ctx, cr->type);
421
- if (IS_ERR(f))
422
- return PTR_ERR(f);
423
-
424
- cr->bounds.left = 0;
425
- cr->bounds.top = 0;
426
- cr->bounds.width = f->width;
427
- cr->bounds.height = f->height;
428
- cr->defrect = cr->bounds;
429
- return 0;
430
-}
431
-
432
-static int vidioc_g_crop(struct file *file, void *prv, struct v4l2_crop *cr)
400
+static int vidioc_g_selection(struct file *file, void *prv,
401
+ struct v4l2_selection *s)
433402 {
434403 struct g2d_ctx *ctx = prv;
435404 struct g2d_frame *f;
436405
437
- f = get_frame(ctx, cr->type);
406
+ f = get_frame(ctx, s->type);
438407 if (IS_ERR(f))
439408 return PTR_ERR(f);
440409
441
- cr->c.left = f->o_height;
442
- cr->c.top = f->o_width;
443
- cr->c.width = f->c_width;
444
- cr->c.height = f->c_height;
410
+ switch (s->target) {
411
+ case V4L2_SEL_TGT_CROP:
412
+ case V4L2_SEL_TGT_CROP_DEFAULT:
413
+ case V4L2_SEL_TGT_CROP_BOUNDS:
414
+ if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
415
+ return -EINVAL;
416
+ break;
417
+ case V4L2_SEL_TGT_COMPOSE:
418
+ case V4L2_SEL_TGT_COMPOSE_DEFAULT:
419
+ case V4L2_SEL_TGT_COMPOSE_BOUNDS:
420
+ if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
421
+ return -EINVAL;
422
+ break;
423
+ default:
424
+ return -EINVAL;
425
+ }
426
+
427
+ switch (s->target) {
428
+ case V4L2_SEL_TGT_CROP:
429
+ case V4L2_SEL_TGT_COMPOSE:
430
+ s->r.left = f->o_height;
431
+ s->r.top = f->o_width;
432
+ s->r.width = f->c_width;
433
+ s->r.height = f->c_height;
434
+ break;
435
+ case V4L2_SEL_TGT_CROP_DEFAULT:
436
+ case V4L2_SEL_TGT_CROP_BOUNDS:
437
+ case V4L2_SEL_TGT_COMPOSE_DEFAULT:
438
+ case V4L2_SEL_TGT_COMPOSE_BOUNDS:
439
+ s->r.left = 0;
440
+ s->r.top = 0;
441
+ s->r.width = f->width;
442
+ s->r.height = f->height;
443
+ break;
444
+ default:
445
+ return -EINVAL;
446
+ }
445447 return 0;
446448 }
447449
448
-static int vidioc_try_crop(struct file *file, void *prv, const struct v4l2_crop *cr)
450
+static int vidioc_try_selection(struct file *file, void *prv,
451
+ const struct v4l2_selection *s)
449452 {
450453 struct g2d_ctx *ctx = prv;
451454 struct g2d_dev *dev = ctx->dev;
452455 struct g2d_frame *f;
453456
454
- f = get_frame(ctx, cr->type);
457
+ f = get_frame(ctx, s->type);
455458 if (IS_ERR(f))
456459 return PTR_ERR(f);
457460
458
- if (cr->c.top < 0 || cr->c.left < 0) {
461
+ if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
462
+ if (s->target != V4L2_SEL_TGT_COMPOSE)
463
+ return -EINVAL;
464
+ } else if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
465
+ if (s->target != V4L2_SEL_TGT_CROP)
466
+ return -EINVAL;
467
+ }
468
+
469
+ if (s->r.top < 0 || s->r.left < 0) {
459470 v4l2_err(&dev->v4l2_dev,
460471 "doesn't support negative values for top & left\n");
461472 return -EINVAL;
....@@ -464,23 +475,24 @@
464475 return 0;
465476 }
466477
467
-static int vidioc_s_crop(struct file *file, void *prv, const struct v4l2_crop *cr)
478
+static int vidioc_s_selection(struct file *file, void *prv,
479
+ struct v4l2_selection *s)
468480 {
469481 struct g2d_ctx *ctx = prv;
470482 struct g2d_frame *f;
471483 int ret;
472484
473
- ret = vidioc_try_crop(file, prv, cr);
485
+ ret = vidioc_try_selection(file, prv, s);
474486 if (ret)
475487 return ret;
476
- f = get_frame(ctx, cr->type);
488
+ f = get_frame(ctx, s->type);
477489 if (IS_ERR(f))
478490 return PTR_ERR(f);
479491
480
- f->c_width = cr->c.width;
481
- f->c_height = cr->c.height;
482
- f->o_width = cr->c.left;
483
- f->o_height = cr->c.top;
492
+ f->c_width = s->r.width;
493
+ f->c_height = s->r.height;
494
+ f->o_width = s->r.left;
495
+ f->o_height = s->r.top;
484496 f->bottom = f->o_height + f->c_height;
485497 f->right = f->o_width + f->c_width;
486498 return 0;
....@@ -588,9 +600,8 @@
588600 .vidioc_streamon = v4l2_m2m_ioctl_streamon,
589601 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
590602
591
- .vidioc_g_crop = vidioc_g_crop,
592
- .vidioc_s_crop = vidioc_s_crop,
593
- .vidioc_cropcap = vidioc_cropcap,
603
+ .vidioc_g_selection = vidioc_g_selection,
604
+ .vidioc_s_selection = vidioc_s_selection,
594605 };
595606
596607 static const struct video_device g2d_videodev = {
....@@ -683,23 +694,17 @@
683694 goto unreg_v4l2_dev;
684695 }
685696 *vfd = g2d_videodev;
697
+ set_bit(V4L2_FL_QUIRK_INVERTED_CROP, &vfd->flags);
686698 vfd->lock = &dev->mutex;
687699 vfd->v4l2_dev = &dev->v4l2_dev;
688
- ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
689
- if (ret) {
690
- v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
691
- goto rel_vdev;
692
- }
693
- video_set_drvdata(vfd, dev);
694
- dev->vfd = vfd;
695
- v4l2_info(&dev->v4l2_dev, "device registered as /dev/video%d\n",
696
- vfd->num);
700
+ vfd->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
701
+
697702 platform_set_drvdata(pdev, dev);
698703 dev->m2m_dev = v4l2_m2m_init(&g2d_m2m_ops);
699704 if (IS_ERR(dev->m2m_dev)) {
700705 v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
701706 ret = PTR_ERR(dev->m2m_dev);
702
- goto unreg_video_dev;
707
+ goto rel_vdev;
703708 }
704709
705710 def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
....@@ -707,14 +712,24 @@
707712 of_id = of_match_node(exynos_g2d_match, pdev->dev.of_node);
708713 if (!of_id) {
709714 ret = -ENODEV;
710
- goto unreg_video_dev;
715
+ goto free_m2m;
711716 }
712717 dev->variant = (struct g2d_variant *)of_id->data;
713718
719
+ ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
720
+ if (ret) {
721
+ v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
722
+ goto free_m2m;
723
+ }
724
+ video_set_drvdata(vfd, dev);
725
+ dev->vfd = vfd;
726
+ v4l2_info(&dev->v4l2_dev, "device registered as /dev/video%d\n",
727
+ vfd->num);
728
+
714729 return 0;
715730
716
-unreg_video_dev:
717
- video_unregister_device(dev->vfd);
731
+free_m2m:
732
+ v4l2_m2m_release(dev->m2m_dev);
718733 rel_vdev:
719734 video_device_release(vfd);
720735 unreg_v4l2_dev: