| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (c) 2015-2016 MediaTek Inc. |
|---|
| 3 | 4 | * Author: Houlong Wei <houlong.wei@mediatek.com> |
|---|
| 4 | 5 | * Ming Hsiu Tsai <minghsiu.tsai@mediatek.com> |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 7 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 8 | | - * published by the Free Software Foundation. |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 11 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 12 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 13 | | - * GNU General Public License for more details. |
|---|
| 14 | 6 | */ |
|---|
| 15 | 7 | |
|---|
| 16 | 8 | #include <linux/device.h> |
|---|
| .. | .. |
|---|
| 201 | 193 | |
|---|
| 202 | 194 | pix_mp->field = V4L2_FIELD_NONE; |
|---|
| 203 | 195 | pix_mp->pixelformat = fmt->pixelformat; |
|---|
| 204 | | - if (!V4L2_TYPE_IS_OUTPUT(f->type)) { |
|---|
| 196 | + if (V4L2_TYPE_IS_CAPTURE(f->type)) { |
|---|
| 205 | 197 | pix_mp->colorspace = ctx->colorspace; |
|---|
| 206 | 198 | pix_mp->xfer_func = ctx->xfer_func; |
|---|
| 207 | 199 | pix_mp->ycbcr_enc = ctx->ycbcr_enc; |
|---|
| .. | .. |
|---|
| 335 | 327 | mtk_mdp_bound_align_image(&new_w, min_w, max_w, align_w, |
|---|
| 336 | 328 | &new_h, min_h, max_h, align_h); |
|---|
| 337 | 329 | |
|---|
| 338 | | - if (!V4L2_TYPE_IS_OUTPUT(type) && |
|---|
| 339 | | - (ctx->ctrls.rotate->val == 90 || |
|---|
| 340 | | - ctx->ctrls.rotate->val == 270)) |
|---|
| 330 | + if (V4L2_TYPE_IS_CAPTURE(type) && |
|---|
| 331 | + (ctx->ctrls.rotate->val == 90 || ctx->ctrls.rotate->val == 270)) |
|---|
| 341 | 332 | mtk_mdp_check_crop_change(new_h, new_w, |
|---|
| 342 | 333 | &r->width, &r->height); |
|---|
| 343 | 334 | else |
|---|
| .. | .. |
|---|
| 377 | 368 | mutex_unlock(&ctx->slock); |
|---|
| 378 | 369 | } |
|---|
| 379 | 370 | |
|---|
| 380 | | -static void mtk_mdp_ctx_state_lock_clear(struct mtk_mdp_ctx *ctx, u32 state) |
|---|
| 381 | | -{ |
|---|
| 382 | | - mutex_lock(&ctx->slock); |
|---|
| 383 | | - ctx->state &= ~state; |
|---|
| 384 | | - mutex_unlock(&ctx->slock); |
|---|
| 385 | | -} |
|---|
| 386 | | - |
|---|
| 387 | 371 | static bool mtk_mdp_ctx_state_is_set(struct mtk_mdp_ctx *ctx, u32 mask) |
|---|
| 388 | 372 | { |
|---|
| 389 | 373 | bool ret; |
|---|
| .. | .. |
|---|
| 410 | 394 | struct mtk_mdp_ctx *ctx = q->drv_priv; |
|---|
| 411 | 395 | int ret; |
|---|
| 412 | 396 | |
|---|
| 413 | | - ret = pm_runtime_get_sync(&ctx->mdp_dev->pdev->dev); |
|---|
| 397 | + ret = pm_runtime_resume_and_get(&ctx->mdp_dev->pdev->dev); |
|---|
| 414 | 398 | if (ret < 0) |
|---|
| 415 | | - mtk_mdp_dbg(1, "[%d] pm_runtime_get_sync failed:%d", |
|---|
| 399 | + mtk_mdp_dbg(1, "[%d] pm_runtime_resume_and_get failed:%d", |
|---|
| 416 | 400 | ctx->id, ret); |
|---|
| 417 | 401 | |
|---|
| 418 | | - return 0; |
|---|
| 402 | + return ret; |
|---|
| 419 | 403 | } |
|---|
| 420 | 404 | |
|---|
| 421 | 405 | static void *mtk_mdp_m2m_buf_remove(struct mtk_mdp_ctx *ctx, |
|---|
| .. | .. |
|---|
| 473 | 457 | static void mtk_mdp_m2m_get_bufs(struct mtk_mdp_ctx *ctx) |
|---|
| 474 | 458 | { |
|---|
| 475 | 459 | struct mtk_mdp_frame *s_frame, *d_frame; |
|---|
| 476 | | - struct vb2_buffer *src_vb, *dst_vb; |
|---|
| 477 | 460 | struct vb2_v4l2_buffer *src_vbuf, *dst_vbuf; |
|---|
| 478 | 461 | |
|---|
| 479 | 462 | s_frame = &ctx->s_frame; |
|---|
| 480 | 463 | d_frame = &ctx->d_frame; |
|---|
| 481 | 464 | |
|---|
| 482 | | - src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx); |
|---|
| 483 | | - mtk_mdp_prepare_addr(ctx, src_vb, s_frame, &s_frame->addr); |
|---|
| 465 | + src_vbuf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); |
|---|
| 466 | + mtk_mdp_prepare_addr(ctx, &src_vbuf->vb2_buf, s_frame, &s_frame->addr); |
|---|
| 484 | 467 | |
|---|
| 485 | | - dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); |
|---|
| 486 | | - mtk_mdp_prepare_addr(ctx, dst_vb, d_frame, &d_frame->addr); |
|---|
| 468 | + dst_vbuf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); |
|---|
| 469 | + mtk_mdp_prepare_addr(ctx, &dst_vbuf->vb2_buf, d_frame, &d_frame->addr); |
|---|
| 487 | 470 | |
|---|
| 488 | | - src_vbuf = to_vb2_v4l2_buffer(src_vb); |
|---|
| 489 | | - dst_vbuf = to_vb2_v4l2_buffer(dst_vb); |
|---|
| 490 | 471 | dst_vbuf->vb2_buf.timestamp = src_vbuf->vb2_buf.timestamp; |
|---|
| 491 | 472 | } |
|---|
| 492 | 473 | |
|---|
| .. | .. |
|---|
| 494 | 475 | { |
|---|
| 495 | 476 | struct mtk_mdp_dev *mdp = priv; |
|---|
| 496 | 477 | struct mtk_mdp_ctx *ctx; |
|---|
| 497 | | - struct vb2_buffer *src_vb, *dst_vb; |
|---|
| 498 | | - struct vb2_v4l2_buffer *src_vbuf = NULL, *dst_vbuf = NULL; |
|---|
| 478 | + struct vb2_v4l2_buffer *src_vbuf, *dst_vbuf; |
|---|
| 499 | 479 | |
|---|
| 500 | 480 | ctx = v4l2_m2m_get_curr_priv(mdp->m2m_dev); |
|---|
| 501 | 481 | if (!ctx) |
|---|
| 502 | 482 | return; |
|---|
| 503 | 483 | |
|---|
| 504 | | - src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); |
|---|
| 505 | | - src_vbuf = to_vb2_v4l2_buffer(src_vb); |
|---|
| 506 | | - dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); |
|---|
| 507 | | - dst_vbuf = to_vb2_v4l2_buffer(dst_vb); |
|---|
| 484 | + src_vbuf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); |
|---|
| 485 | + dst_vbuf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); |
|---|
| 508 | 486 | |
|---|
| 509 | 487 | dst_vbuf->vb2_buf.timestamp = src_vbuf->vb2_buf.timestamp; |
|---|
| 510 | 488 | dst_vbuf->timecode = src_vbuf->timecode; |
|---|
| .. | .. |
|---|
| 619 | 597 | struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); |
|---|
| 620 | 598 | struct mtk_mdp_dev *mdp = ctx->mdp_dev; |
|---|
| 621 | 599 | |
|---|
| 622 | | - strlcpy(cap->driver, MTK_MDP_MODULE_NAME, sizeof(cap->driver)); |
|---|
| 623 | | - strlcpy(cap->card, mdp->pdev->name, sizeof(cap->card)); |
|---|
| 624 | | - strlcpy(cap->bus_info, "platform:mt8173", sizeof(cap->bus_info)); |
|---|
| 600 | + strscpy(cap->driver, MTK_MDP_MODULE_NAME, sizeof(cap->driver)); |
|---|
| 601 | + strscpy(cap->card, mdp->pdev->name, sizeof(cap->card)); |
|---|
| 602 | + strscpy(cap->bus_info, "platform:mt8173", sizeof(cap->bus_info)); |
|---|
| 625 | 603 | |
|---|
| 626 | 604 | return 0; |
|---|
| 627 | 605 | } |
|---|
| 628 | 606 | |
|---|
| 629 | | -static int mtk_mdp_enum_fmt_mplane(struct v4l2_fmtdesc *f, u32 type) |
|---|
| 607 | +static int mtk_mdp_enum_fmt(struct v4l2_fmtdesc *f, u32 type) |
|---|
| 630 | 608 | { |
|---|
| 631 | 609 | const struct mtk_mdp_fmt *fmt; |
|---|
| 632 | 610 | |
|---|
| .. | .. |
|---|
| 639 | 617 | return 0; |
|---|
| 640 | 618 | } |
|---|
| 641 | 619 | |
|---|
| 642 | | -static int mtk_mdp_m2m_enum_fmt_mplane_vid_cap(struct file *file, void *priv, |
|---|
| 643 | | - struct v4l2_fmtdesc *f) |
|---|
| 620 | +static int mtk_mdp_m2m_enum_fmt_vid_cap(struct file *file, void *priv, |
|---|
| 621 | + struct v4l2_fmtdesc *f) |
|---|
| 644 | 622 | { |
|---|
| 645 | | - return mtk_mdp_enum_fmt_mplane(f, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); |
|---|
| 623 | + return mtk_mdp_enum_fmt(f, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); |
|---|
| 646 | 624 | } |
|---|
| 647 | 625 | |
|---|
| 648 | | -static int mtk_mdp_m2m_enum_fmt_mplane_vid_out(struct file *file, void *priv, |
|---|
| 649 | | - struct v4l2_fmtdesc *f) |
|---|
| 626 | +static int mtk_mdp_m2m_enum_fmt_vid_out(struct file *file, void *priv, |
|---|
| 627 | + struct v4l2_fmtdesc *f) |
|---|
| 650 | 628 | { |
|---|
| 651 | | - return mtk_mdp_enum_fmt_mplane(f, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); |
|---|
| 629 | + return mtk_mdp_enum_fmt(f, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); |
|---|
| 652 | 630 | } |
|---|
| 653 | 631 | |
|---|
| 654 | 632 | static int mtk_mdp_m2m_g_fmt_mplane(struct file *file, void *fh, |
|---|
| .. | .. |
|---|
| 740 | 718 | ctx->quant = pix_mp->quantization; |
|---|
| 741 | 719 | } |
|---|
| 742 | 720 | |
|---|
| 743 | | - if (V4L2_TYPE_IS_OUTPUT(f->type)) |
|---|
| 744 | | - mtk_mdp_ctx_state_lock_set(ctx, MTK_MDP_SRC_FMT); |
|---|
| 745 | | - else |
|---|
| 746 | | - mtk_mdp_ctx_state_lock_set(ctx, MTK_MDP_DST_FMT); |
|---|
| 747 | | - |
|---|
| 748 | 721 | mtk_mdp_dbg(2, "[%d] type:%d, frame:%dx%d", ctx->id, f->type, |
|---|
| 749 | 722 | frame->width, frame->height); |
|---|
| 750 | 723 | |
|---|
| .. | .. |
|---|
| 756 | 729 | { |
|---|
| 757 | 730 | struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); |
|---|
| 758 | 731 | |
|---|
| 759 | | - if (reqbufs->count == 0) { |
|---|
| 760 | | - if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) |
|---|
| 761 | | - mtk_mdp_ctx_state_lock_clear(ctx, MTK_MDP_SRC_FMT); |
|---|
| 762 | | - else |
|---|
| 763 | | - mtk_mdp_ctx_state_lock_clear(ctx, MTK_MDP_DST_FMT); |
|---|
| 764 | | - } |
|---|
| 765 | | - |
|---|
| 766 | 732 | return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); |
|---|
| 767 | 733 | } |
|---|
| 768 | 734 | |
|---|
| .. | .. |
|---|
| 771 | 737 | { |
|---|
| 772 | 738 | struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); |
|---|
| 773 | 739 | int ret; |
|---|
| 774 | | - |
|---|
| 775 | | - /* The source and target color format need to be set */ |
|---|
| 776 | | - if (V4L2_TYPE_IS_OUTPUT(type)) { |
|---|
| 777 | | - if (!mtk_mdp_ctx_state_is_set(ctx, MTK_MDP_SRC_FMT)) |
|---|
| 778 | | - return -EINVAL; |
|---|
| 779 | | - } else if (!mtk_mdp_ctx_state_is_set(ctx, MTK_MDP_DST_FMT)) { |
|---|
| 780 | | - return -EINVAL; |
|---|
| 781 | | - } |
|---|
| 782 | 740 | |
|---|
| 783 | 741 | if (!mtk_mdp_ctx_state_is_set(ctx, MTK_MDP_VPU_INIT)) { |
|---|
| 784 | 742 | ret = mtk_mdp_vpu_init(&ctx->vpu); |
|---|
| .. | .. |
|---|
| 913 | 871 | frame = &ctx->d_frame; |
|---|
| 914 | 872 | |
|---|
| 915 | 873 | /* Check to see if scaling ratio is within supported range */ |
|---|
| 916 | | - if (mtk_mdp_ctx_state_is_set(ctx, MTK_MDP_DST_FMT | MTK_MDP_SRC_FMT)) { |
|---|
| 917 | | - if (V4L2_TYPE_IS_OUTPUT(s->type)) { |
|---|
| 918 | | - ret = mtk_mdp_check_scaler_ratio(variant, new_r.width, |
|---|
| 919 | | - new_r.height, ctx->d_frame.crop.width, |
|---|
| 920 | | - ctx->d_frame.crop.height, |
|---|
| 921 | | - ctx->ctrls.rotate->val); |
|---|
| 922 | | - } else { |
|---|
| 923 | | - ret = mtk_mdp_check_scaler_ratio(variant, |
|---|
| 924 | | - ctx->s_frame.crop.width, |
|---|
| 925 | | - ctx->s_frame.crop.height, new_r.width, |
|---|
| 926 | | - new_r.height, ctx->ctrls.rotate->val); |
|---|
| 927 | | - } |
|---|
| 874 | + if (V4L2_TYPE_IS_OUTPUT(s->type)) |
|---|
| 875 | + ret = mtk_mdp_check_scaler_ratio(variant, new_r.width, |
|---|
| 876 | + new_r.height, ctx->d_frame.crop.width, |
|---|
| 877 | + ctx->d_frame.crop.height, |
|---|
| 878 | + ctx->ctrls.rotate->val); |
|---|
| 879 | + else |
|---|
| 880 | + ret = mtk_mdp_check_scaler_ratio(variant, |
|---|
| 881 | + ctx->s_frame.crop.width, |
|---|
| 882 | + ctx->s_frame.crop.height, new_r.width, |
|---|
| 883 | + new_r.height, ctx->ctrls.rotate->val); |
|---|
| 928 | 884 | |
|---|
| 929 | | - if (ret) { |
|---|
| 930 | | - dev_info(&ctx->mdp_dev->pdev->dev, |
|---|
| 931 | | - "Out of scaler range"); |
|---|
| 932 | | - return -EINVAL; |
|---|
| 933 | | - } |
|---|
| 885 | + if (ret) { |
|---|
| 886 | + dev_info(&ctx->mdp_dev->pdev->dev, |
|---|
| 887 | + "Out of scaler range"); |
|---|
| 888 | + return -EINVAL; |
|---|
| 934 | 889 | } |
|---|
| 935 | 890 | |
|---|
| 936 | 891 | s->r = new_r; |
|---|
| .. | .. |
|---|
| 941 | 896 | |
|---|
| 942 | 897 | static const struct v4l2_ioctl_ops mtk_mdp_m2m_ioctl_ops = { |
|---|
| 943 | 898 | .vidioc_querycap = mtk_mdp_m2m_querycap, |
|---|
| 944 | | - .vidioc_enum_fmt_vid_cap_mplane = mtk_mdp_m2m_enum_fmt_mplane_vid_cap, |
|---|
| 945 | | - .vidioc_enum_fmt_vid_out_mplane = mtk_mdp_m2m_enum_fmt_mplane_vid_out, |
|---|
| 899 | + .vidioc_enum_fmt_vid_cap = mtk_mdp_m2m_enum_fmt_vid_cap, |
|---|
| 900 | + .vidioc_enum_fmt_vid_out = mtk_mdp_m2m_enum_fmt_vid_out, |
|---|
| 946 | 901 | .vidioc_g_fmt_vid_cap_mplane = mtk_mdp_m2m_g_fmt_mplane, |
|---|
| 947 | 902 | .vidioc_g_fmt_vid_out_mplane = mtk_mdp_m2m_g_fmt_mplane, |
|---|
| 948 | 903 | .vidioc_try_fmt_vid_cap_mplane = mtk_mdp_m2m_try_fmt_mplane, |
|---|
| .. | .. |
|---|
| 1003 | 958 | struct mtk_mdp_ctx *ctx = ctrl_to_ctx(ctrl); |
|---|
| 1004 | 959 | struct mtk_mdp_dev *mdp = ctx->mdp_dev; |
|---|
| 1005 | 960 | struct mtk_mdp_variant *variant = mdp->variant; |
|---|
| 1006 | | - u32 state = MTK_MDP_DST_FMT | MTK_MDP_SRC_FMT; |
|---|
| 1007 | 961 | int ret = 0; |
|---|
| 1008 | 962 | |
|---|
| 1009 | 963 | if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE) |
|---|
| .. | .. |
|---|
| 1017 | 971 | ctx->vflip = ctrl->val; |
|---|
| 1018 | 972 | break; |
|---|
| 1019 | 973 | case V4L2_CID_ROTATE: |
|---|
| 1020 | | - if (mtk_mdp_ctx_state_is_set(ctx, state)) { |
|---|
| 1021 | | - ret = mtk_mdp_check_scaler_ratio(variant, |
|---|
| 1022 | | - ctx->s_frame.crop.width, |
|---|
| 1023 | | - ctx->s_frame.crop.height, |
|---|
| 1024 | | - ctx->d_frame.crop.width, |
|---|
| 1025 | | - ctx->d_frame.crop.height, |
|---|
| 1026 | | - ctx->ctrls.rotate->val); |
|---|
| 974 | + ret = mtk_mdp_check_scaler_ratio(variant, |
|---|
| 975 | + ctx->s_frame.crop.width, |
|---|
| 976 | + ctx->s_frame.crop.height, |
|---|
| 977 | + ctx->d_frame.crop.width, |
|---|
| 978 | + ctx->d_frame.crop.height, |
|---|
| 979 | + ctx->ctrls.rotate->val); |
|---|
| 1027 | 980 | |
|---|
| 1028 | | - if (ret) |
|---|
| 1029 | | - return -EINVAL; |
|---|
| 1030 | | - } |
|---|
| 981 | + if (ret) |
|---|
| 982 | + return -EINVAL; |
|---|
| 1031 | 983 | |
|---|
| 1032 | 984 | ctx->rotation = ctrl->val; |
|---|
| 1033 | 985 | break; |
|---|
| .. | .. |
|---|
| 1104 | 1056 | struct video_device *vfd = video_devdata(file); |
|---|
| 1105 | 1057 | struct mtk_mdp_ctx *ctx = NULL; |
|---|
| 1106 | 1058 | int ret; |
|---|
| 1059 | + struct v4l2_format default_format; |
|---|
| 1107 | 1060 | |
|---|
| 1108 | 1061 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); |
|---|
| 1109 | 1062 | if (!ctx) |
|---|
| .. | .. |
|---|
| 1157 | 1110 | |
|---|
| 1158 | 1111 | list_add(&ctx->list, &mdp->ctx_list); |
|---|
| 1159 | 1112 | mutex_unlock(&mdp->lock); |
|---|
| 1113 | + |
|---|
| 1114 | + /* Default format */ |
|---|
| 1115 | + memset(&default_format, 0, sizeof(default_format)); |
|---|
| 1116 | + default_format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
|---|
| 1117 | + default_format.fmt.pix_mp.width = 32; |
|---|
| 1118 | + default_format.fmt.pix_mp.height = 32; |
|---|
| 1119 | + default_format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420M; |
|---|
| 1120 | + mtk_mdp_m2m_s_fmt_mplane(file, &ctx->fh, &default_format); |
|---|
| 1121 | + default_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
|---|
| 1122 | + mtk_mdp_m2m_s_fmt_mplane(file, &ctx->fh, &default_format); |
|---|
| 1160 | 1123 | |
|---|
| 1161 | 1124 | mtk_mdp_dbg(0, "%s [%d]", dev_name(&mdp->pdev->dev), ctx->id); |
|---|
| 1162 | 1125 | |
|---|
| .. | .. |
|---|
| 1243 | 1206 | goto err_m2m_init; |
|---|
| 1244 | 1207 | } |
|---|
| 1245 | 1208 | |
|---|
| 1246 | | - ret = video_register_device(mdp->vdev, VFL_TYPE_GRABBER, 2); |
|---|
| 1209 | + ret = video_register_device(mdp->vdev, VFL_TYPE_VIDEO, 2); |
|---|
| 1247 | 1210 | if (ret) { |
|---|
| 1248 | 1211 | dev_err(dev, "failed to register video device\n"); |
|---|
| 1249 | 1212 | goto err_vdev_register; |
|---|