| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd. |
|---|
| 3 | 4 | * http://www.samsung.com |
|---|
| 4 | 5 | * |
|---|
| 5 | 6 | * Samsung EXYNOS5 SoC series G-Scaler driver |
|---|
| 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 |
|---|
| 9 | | - * by the Free Software Foundation, either version 2 of the License, |
|---|
| 10 | | - * or (at your option) any later version. |
|---|
| 11 | 7 | */ |
|---|
| 12 | 8 | |
|---|
| 13 | 9 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 60 | 56 | static int gsc_m2m_start_streaming(struct vb2_queue *q, unsigned int count) |
|---|
| 61 | 57 | { |
|---|
| 62 | 58 | struct gsc_ctx *ctx = q->drv_priv; |
|---|
| 63 | | - int ret; |
|---|
| 64 | 59 | |
|---|
| 65 | | - ret = pm_runtime_get_sync(&ctx->gsc_dev->pdev->dev); |
|---|
| 66 | | - return ret > 0 ? 0 : ret; |
|---|
| 60 | + return pm_runtime_resume_and_get(&ctx->gsc_dev->pdev->dev); |
|---|
| 67 | 61 | } |
|---|
| 68 | 62 | |
|---|
| 69 | 63 | static void __gsc_m2m_cleanup_queue(struct gsc_ctx *ctx) |
|---|
| .. | .. |
|---|
| 259 | 253 | if (IS_ERR(frame)) |
|---|
| 260 | 254 | return PTR_ERR(frame); |
|---|
| 261 | 255 | |
|---|
| 262 | | - if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { |
|---|
| 256 | + if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type)) { |
|---|
| 263 | 257 | for (i = 0; i < frame->fmt->num_planes; i++) |
|---|
| 264 | 258 | vb2_set_plane_payload(vb, i, frame->payload[i]); |
|---|
| 265 | 259 | } |
|---|
| .. | .. |
|---|
| 294 | 288 | struct gsc_ctx *ctx = fh_to_ctx(fh); |
|---|
| 295 | 289 | struct gsc_dev *gsc = ctx->gsc_dev; |
|---|
| 296 | 290 | |
|---|
| 297 | | - strlcpy(cap->driver, GSC_MODULE_NAME, sizeof(cap->driver)); |
|---|
| 298 | | - strlcpy(cap->card, GSC_MODULE_NAME " gscaler", sizeof(cap->card)); |
|---|
| 291 | + strscpy(cap->driver, GSC_MODULE_NAME, sizeof(cap->driver)); |
|---|
| 292 | + strscpy(cap->card, GSC_MODULE_NAME " gscaler", sizeof(cap->card)); |
|---|
| 299 | 293 | snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", |
|---|
| 300 | 294 | dev_name(&gsc->pdev->dev)); |
|---|
| 301 | | - cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE; |
|---|
| 302 | | - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; |
|---|
| 303 | 295 | return 0; |
|---|
| 304 | 296 | } |
|---|
| 305 | 297 | |
|---|
| 306 | | -static int gsc_m2m_enum_fmt_mplane(struct file *file, void *priv, |
|---|
| 307 | | - struct v4l2_fmtdesc *f) |
|---|
| 298 | +static int gsc_m2m_enum_fmt(struct file *file, void *priv, |
|---|
| 299 | + struct v4l2_fmtdesc *f) |
|---|
| 308 | 300 | { |
|---|
| 309 | | - return gsc_enum_fmt_mplane(f); |
|---|
| 301 | + return gsc_enum_fmt(f); |
|---|
| 310 | 302 | } |
|---|
| 311 | 303 | |
|---|
| 312 | 304 | static int gsc_m2m_g_fmt_mplane(struct file *file, void *fh, |
|---|
| .. | .. |
|---|
| 494 | 486 | { |
|---|
| 495 | 487 | struct gsc_frame *frame; |
|---|
| 496 | 488 | struct gsc_ctx *ctx = fh_to_ctx(fh); |
|---|
| 497 | | - struct v4l2_crop cr; |
|---|
| 498 | 489 | struct gsc_variant *variant = ctx->gsc_dev->variant; |
|---|
| 490 | + struct v4l2_selection sel = *s; |
|---|
| 499 | 491 | int ret; |
|---|
| 500 | | - |
|---|
| 501 | | - cr.type = s->type; |
|---|
| 502 | | - cr.c = s->r; |
|---|
| 503 | 492 | |
|---|
| 504 | 493 | if ((s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && |
|---|
| 505 | 494 | (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)) |
|---|
| 506 | 495 | return -EINVAL; |
|---|
| 507 | 496 | |
|---|
| 508 | | - ret = gsc_try_crop(ctx, &cr); |
|---|
| 497 | + ret = gsc_try_selection(ctx, &sel); |
|---|
| 509 | 498 | if (ret) |
|---|
| 510 | 499 | return ret; |
|---|
| 511 | 500 | |
|---|
| 512 | 501 | if (s->flags & V4L2_SEL_FLAG_LE && |
|---|
| 513 | | - !is_rectangle_enclosed(&cr.c, &s->r)) |
|---|
| 502 | + !is_rectangle_enclosed(&sel.r, &s->r)) |
|---|
| 514 | 503 | return -ERANGE; |
|---|
| 515 | 504 | |
|---|
| 516 | 505 | if (s->flags & V4L2_SEL_FLAG_GE && |
|---|
| 517 | | - !is_rectangle_enclosed(&s->r, &cr.c)) |
|---|
| 506 | + !is_rectangle_enclosed(&s->r, &sel.r)) |
|---|
| 518 | 507 | return -ERANGE; |
|---|
| 519 | 508 | |
|---|
| 520 | | - s->r = cr.c; |
|---|
| 509 | + s->r = sel.r; |
|---|
| 521 | 510 | |
|---|
| 522 | 511 | switch (s->target) { |
|---|
| 523 | 512 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: |
|---|
| .. | .. |
|---|
| 539 | 528 | /* Check to see if scaling ratio is within supported range */ |
|---|
| 540 | 529 | if (gsc_ctx_state_is_set(GSC_DST_FMT | GSC_SRC_FMT, ctx)) { |
|---|
| 541 | 530 | if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
|---|
| 542 | | - ret = gsc_check_scaler_ratio(variant, cr.c.width, |
|---|
| 543 | | - cr.c.height, ctx->d_frame.crop.width, |
|---|
| 531 | + ret = gsc_check_scaler_ratio(variant, sel.r.width, |
|---|
| 532 | + sel.r.height, ctx->d_frame.crop.width, |
|---|
| 544 | 533 | ctx->d_frame.crop.height, |
|---|
| 545 | 534 | ctx->gsc_ctrls.rotate->val, ctx->out_path); |
|---|
| 546 | 535 | } else { |
|---|
| 547 | 536 | ret = gsc_check_scaler_ratio(variant, |
|---|
| 548 | 537 | ctx->s_frame.crop.width, |
|---|
| 549 | | - ctx->s_frame.crop.height, cr.c.width, |
|---|
| 550 | | - cr.c.height, ctx->gsc_ctrls.rotate->val, |
|---|
| 538 | + ctx->s_frame.crop.height, sel.r.width, |
|---|
| 539 | + sel.r.height, ctx->gsc_ctrls.rotate->val, |
|---|
| 551 | 540 | ctx->out_path); |
|---|
| 552 | 541 | } |
|---|
| 553 | 542 | |
|---|
| .. | .. |
|---|
| 557 | 546 | } |
|---|
| 558 | 547 | } |
|---|
| 559 | 548 | |
|---|
| 560 | | - frame->crop = cr.c; |
|---|
| 549 | + frame->crop = sel.r; |
|---|
| 561 | 550 | |
|---|
| 562 | 551 | gsc_ctx_state_lock_set(GSC_PARAMS, ctx); |
|---|
| 563 | 552 | return 0; |
|---|
| .. | .. |
|---|
| 565 | 554 | |
|---|
| 566 | 555 | static const struct v4l2_ioctl_ops gsc_m2m_ioctl_ops = { |
|---|
| 567 | 556 | .vidioc_querycap = gsc_m2m_querycap, |
|---|
| 568 | | - .vidioc_enum_fmt_vid_cap_mplane = gsc_m2m_enum_fmt_mplane, |
|---|
| 569 | | - .vidioc_enum_fmt_vid_out_mplane = gsc_m2m_enum_fmt_mplane, |
|---|
| 557 | + .vidioc_enum_fmt_vid_cap = gsc_m2m_enum_fmt, |
|---|
| 558 | + .vidioc_enum_fmt_vid_out = gsc_m2m_enum_fmt, |
|---|
| 570 | 559 | .vidioc_g_fmt_vid_cap_mplane = gsc_m2m_g_fmt_mplane, |
|---|
| 571 | 560 | .vidioc_g_fmt_vid_out_mplane = gsc_m2m_g_fmt_mplane, |
|---|
| 572 | 561 | .vidioc_try_fmt_vid_cap_mplane = gsc_m2m_try_fmt_mplane, |
|---|
| .. | .. |
|---|
| 766 | 755 | gsc->vdev.lock = &gsc->lock; |
|---|
| 767 | 756 | gsc->vdev.vfl_dir = VFL_DIR_M2M; |
|---|
| 768 | 757 | gsc->vdev.v4l2_dev = &gsc->v4l2_dev; |
|---|
| 758 | + gsc->vdev.device_caps = V4L2_CAP_STREAMING | |
|---|
| 759 | + V4L2_CAP_VIDEO_M2M_MPLANE; |
|---|
| 769 | 760 | snprintf(gsc->vdev.name, sizeof(gsc->vdev.name), "%s.%d:m2m", |
|---|
| 770 | 761 | GSC_MODULE_NAME, gsc->id); |
|---|
| 771 | 762 | |
|---|
| .. | .. |
|---|
| 778 | 769 | return PTR_ERR(gsc->m2m.m2m_dev); |
|---|
| 779 | 770 | } |
|---|
| 780 | 771 | |
|---|
| 781 | | - ret = video_register_device(&gsc->vdev, VFL_TYPE_GRABBER, -1); |
|---|
| 772 | + ret = video_register_device(&gsc->vdev, VFL_TYPE_VIDEO, -1); |
|---|
| 782 | 773 | if (ret) { |
|---|
| 783 | 774 | dev_err(&pdev->dev, |
|---|
| 784 | 775 | "%s(): failed to register video device\n", __func__); |
|---|