From patchwork Fri Nov 3 08:11:24 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 117857 Delivered-To: patch@linaro.org Received: by 10.140.22.164 with SMTP id 33csp3162195qgn; Fri, 3 Nov 2017 01:11:43 -0700 (PDT) X-Google-Smtp-Source: ABhQp+SXAtKG6i6WNT+rfx4e/5FBk/Y83skFqW7rMWTqA5nem67VNSmHai1zIuvUgX5C5IZMO1Ss X-Received: by 10.101.88.203 with SMTP id e11mr6393476pgu.173.1509696703543; Fri, 03 Nov 2017 01:11:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1509696703; cv=none; d=google.com; s=arc-20160816; b=P1XJ+pyXdW3ouAf3YUtaNY62qOowxgPJ5zjeTtc5ewMBPRv44zzgrkBHVMtCvN0OmR dLhdcFH0v4K5HMILQB1hx8uXQDxG+sIDDZMMcLTbStUR1MfFVx+y5ak4T9t+72lompCy p4AoBf+i/BQqc1c2wuTcGx3l6Kq/Te64dsdL3scXSYsaJsSQD1Qv2rZ1+IJ+sRWCG03Z NT9zzsj3Ae7lnfrayNFsQ37i5DbxMMuYTNyVUcRZZrmUMp989LvAVR7noKRRw2Y4F6eC f2YdG6f9PH+IIbP2OdEClOgw5psNkBdSFDp71i5Htq1ecaQOzfQAfzrd/MhYZMh+kl6y R23g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:cms-type:message-id:date :subject:cc:to:from:dkim-signature:dkim-filter :arc-authentication-results; bh=QInLlCZ8oq2p0uEDEL/QSCBAJbtB2LzMLHpnEVewWMk=; b=JiC4eZrGo7ISEGjX+Uy7fzkWNFOhg2LEh57vBEzpvYLJ3R1/l/z+N475uD102Qjuty PdU9jHpBQWLXTe24xYZyPlFcgCgeFzahgdaQvgz5gnQJFGFR5LhIgOStrdaBUyjOwtAe CYIvdOvGGqQxcbyNBXf+UlrUhGIbv0pskKNx8iQoW79nv2JC/08q7yHCsWrIah9VOS50 3aC5sbhQ18cyohE+687CWOtTwKa1pwoerYtfUFjrrkkAkGAk9P9UXExo8N1LWXghRWcL JsJtqJ2bZaN7lvAbGUVx8nn9F9Y8mgOJZlkxbomfrlw15FIq5c0fXTQgSqK6ZAr8HR5K 8eCA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@samsung.com header.s=mail20170921 header.b=YF/XP9VC; spf=pass (google.com: best guess record for domain of linux-samsung-soc-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-samsung-soc-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=samsung.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v68si6033411pfj.359.2017.11.03.01.11.43; Fri, 03 Nov 2017 01:11:43 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-samsung-soc-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@samsung.com header.s=mail20170921 header.b=YF/XP9VC; spf=pass (google.com: best guess record for domain of linux-samsung-soc-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-samsung-soc-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=samsung.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751960AbdKCILm (ORCPT + 3 others); Fri, 3 Nov 2017 04:11:42 -0400 Received: from mailout2.w1.samsung.com ([210.118.77.12]:55278 "EHLO mailout2.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754080AbdKCILg (ORCPT ); Fri, 3 Nov 2017 04:11:36 -0400 Received: from eucas1p1.samsung.com (unknown [182.198.249.206]) by mailout2.w1.samsung.com (KnoxPortal) with ESMTP id 20171103081134euoutp02fd6142516512b19560457934daec77c2~zhSUD4vSx0442504425euoutp02u; Fri, 3 Nov 2017 08:11:34 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout2.w1.samsung.com 20171103081134euoutp02fd6142516512b19560457934daec77c2~zhSUD4vSx0442504425euoutp02u DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1509696694; bh=XXDTnAXvkLBuIEyzbme/TfOhCRBHfl5Ac/r1ZfwEIVg=; h=From:To:Cc:Subject:Date:References:From; b=YF/XP9VCAIO/p4kcxm6h4MKHn21oTaPoglnBhKynvnjiVR6EiKDPCfWc2QuOvUykO k5M/g955FMtOrqeYoXgDjjW8Iu/koitkZNJVoTA+9436I3Ke720wEjnKnVfoNHQTOW 0f3VG2FdINf1EVzyTkDvRuvgMjRnEifuVILl8d9g= Received: from eusmges4.samsung.com (unknown [203.254.199.244]) by eucas1p1.samsung.com (KnoxPortal) with ESMTP id 20171103081133eucas1p137b23bdd05fc77557f76c12dce97075e~zhSTbcf7O0109901099eucas1p1q; Fri, 3 Nov 2017 08:11:33 +0000 (GMT) Received: from eucas1p1.samsung.com ( [182.198.249.206]) by eusmges4.samsung.com (EUCPMTA) with SMTP id 56.8B.12944.5B42CF95; Fri, 3 Nov 2017 08:11:33 +0000 (GMT) Received: from eusmgms2.samsung.com (unknown [182.198.249.180]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20171103081132eucas1p2212e32d26e7921340336d78d0d92cb1b~zhSSxMZsD0093200932eucas1p2k; Fri, 3 Nov 2017 08:11:32 +0000 (GMT) X-AuditID: cbfec7f4-f79ab6d000003290-b4-59fc24b5d835 Received: from eusync3.samsung.com ( [203.254.199.213]) by eusmgms2.samsung.com (EUCPMTA) with SMTP id BF.E0.20118.4B42CF95; Fri, 3 Nov 2017 08:11:32 +0000 (GMT) Received: from AMDC2765.digital.local ([106.116.147.25]) by eusync3.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0OYU0088O1F45W30@eusync3.samsung.com>; Fri, 03 Nov 2017 08:11:32 +0000 (GMT) From: Marek Szyprowski To: linux-media@vger.kernel.org, linux-samsung-soc@vger.kernel.org Cc: Marek Szyprowski , Sylwester Nawrocki , Andrzej Hajda , Marian Mihailescu , Chanwoo Choi , JaeChul Lee , Krzysztof Kozlowski , Seung-Woo Kim Subject: [PATCH v2] media: s5p-mfc: Add support for V4L2_MEMORY_DMABUF type Date: Fri, 03 Nov 2017 09:11:24 +0100 Message-id: <20171103081124.30119-1-m.szyprowski@samsung.com> X-Mailer: git-send-email 2.14.2 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrDIsWRmVeSWpSXmKPExsWy7djPc7pbVf5EGnw7ymVxa905VovrX56z Wrzd381scf78BnaLng1bWS1mnN/HZLH2yF12i/XTfrJaHH7TDhSb/JLNgctj56y77B6bVnWy efRtWcXo8XmTXABLFJdNSmpOZllqkb5dAlfGmfYmpoK1TYwVn/5/ZGpg3J/ZxcjJISFgIrGn 9x8jhC0mceHeerYuRi4OIYGljBJX1nxihHA+M0pcPLaIDabj145DUFXLGCXub37LAuE0MEm8 f3kZbBabgKFE19susA4RASeJhbP+soMUMQtcYJJY0fOLFSQhLOAtMaXnKQuIzSKgKnHj9GYw m1fAVuJ49wyoo+Ql3i+4D3aHhMBfVok7D08zQyRcJPY9+c8CYQtLvDq+hR3ClpG4PLkbKt7P KNHUqg1hz2CUOPeWF8K2ljh8/CLYEcwCfBKTtk0HmskBFOeV6GgTgijxkLiw+CULRNhR4tbM LJCwkECsxLYFO9gnMEotYGRYxSiSWlqcm55abKJXnJhbXJqXrpecn7uJERinp/8d/7KDcfEx q0OMAhyMSjy8Gyb8jhRiTSwrrsw9xCjBwawkwvs4BijEm5JYWZValB9fVJqTWnyIUZqDRUmc 1zaqLVJIID2xJDU7NbUgtQgmy8TBKdXAOMdgR0+lkKHbi9SoPHOPzRUtr/98vXJPVfjyY2a1 rRvTtuVft97pujfIeErF0y0smfsFHuh11rBpRZ3/+9/ffO9jjSTnacvs5+bViswSq/7zKCzE kXlr3a6cC1y7Zy+VuDahzf25f/39zocr9Vo+Mzz+XF484Yt60rkDEWdKYo9cFOaqec3tocRS nJFoqMVcVJwIAHdl7NnPAgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFmpjluLIzCtJLcpLzFFi42I5/e/4Vd0tKn8iDbZ0a1vcWneO1eL6l+es Fm/3dzNbnD+/gd2iZ8NWVosZ5/cxWaw9cpfdYv20n6wWh9+0A8Umv2Rz4PLYOesuu8emVZ1s Hn1bVjF6fN4kF8ASxWWTkpqTWZZapG+XwJVxpr2JqWBtE2PFp/8fmRoY92d2MXJySAiYSPza cYgNwhaTuHBvPZDNxSEksIRRYuL0R0wQThOTxMEJb9hBqtgEDCW63naBdYgIOEksnPUXLM4s cIlJ4tpEbxBbWMBbYkrPUxYQm0VAVeLG6c1gNq+ArcTx7hmMENvkJd4vuM84gZF7ASPDKkaR 1NLi3PTcYiO94sTc4tK8dL3k/NxNjMDQ2Xbs55YdjF3vgg8xCnAwKvHwckz+HSnEmlhWXJl7 iFGCg1lJhPdxDFCINyWxsiq1KD++qDQntfgQozQHi5I4b++e1ZFCAumJJanZqakFqUUwWSYO TqkGxs0bSuaYVh3z17L4zefYtMUt/ctmb9dXLMFxK4+xcF1qurUpO5znYSVH5+7D+7Nz/ooL JXMV6jfHFgvd/K72fUv5xFOWtVahamvX5Os6nAlb71Oh5LQ/RD/DNmj2jv87nXI1xV/vcCr8 VVR6brPw3KXpK7evy/giF5VwJfjZxs33dtx79vnQFyWW4oxEQy3mouJEAJXHV9MZAgAA X-CMS-MailID: 20171103081132eucas1p2212e32d26e7921340336d78d0d92cb1b X-Msg-Generator: CA CMS-TYPE: 201P X-CMS-RootMailID: 20171103081132eucas1p2212e32d26e7921340336d78d0d92cb1b X-RootMTR: 20171103081132eucas1p2212e32d26e7921340336d78d0d92cb1b References: Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org MFC driver supports only MMAP operation mode mainly due to the hardware restrictions of the addresses of the DMA buffers (MFC v5 hardware can access buffers only in 128MiB memory region starting from the base address of its firmware). When IOMMU is available, this requirement is easily fulfilled even for the buffers located anywhere in the memory - typically by mapping them in the DMA address space as close as possible to the firmware. Later hardware revisions don't have this limitations at all. The second limitation of the MFC hardware related to the memory buffers is constant buffer address. Once the hardware has been initialized for operation on given buffer set, the addresses of the buffers cannot be changed. With the above assumptions, a limited support for USERPTR and DMABUF operation modes can be added. The main requirement is to have all buffers known when starting hardware. This has been achieved by postponing hardware initialization once all the DMABUF or USERPTR buffers have been queued for the first time. Once then, buffers cannot be modified to point to other memory area. This patch also removes unconditional USERPTR operation mode from encoder video node, because it doesn't work with v5 MFC hardware without IOMMU being enabled. In case of MFC v5 a bidirectional queue flag has to be enabled as a workaround of the strange hardware behavior - MFC performs a few writes to source data during the operation. Signed-off-by: Seung-Woo Kim [mszyprow: adapted to v4.14 code base, rewrote and extended commit message, added checks for changing buffer addresses, added bidirectional queue flags and comments] Signed-off-by: Marek Szyprowski --- v2: - fixed copy/paste bug, which broke encoding support (thanks to Marian Mihailescu for reporting it) - added checks for changing buffers DMA addresses - added bidirectional queue flags v1: - inital version --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 23 +++++- drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 111 +++++++++++++++++++-------- drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 64 +++++++++++---- 3 files changed, 147 insertions(+), 51 deletions(-) -- 2.14.2 -- To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 1839a86cc2a5..f1ab8d198158 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -754,6 +754,7 @@ static int s5p_mfc_open(struct file *file) struct s5p_mfc_dev *dev = video_drvdata(file); struct s5p_mfc_ctx *ctx = NULL; struct vb2_queue *q; + unsigned int io_modes; int ret = 0; mfc_debug_enter(); @@ -839,16 +840,25 @@ static int s5p_mfc_open(struct file *file) if (ret) goto err_init_hw; } + + io_modes = VB2_MMAP; + if (exynos_is_iommu_available(&dev->plat_dev->dev) || !IS_TWOPORT(dev)) + io_modes |= VB2_USERPTR | VB2_DMABUF; + /* Init videobuf2 queue for CAPTURE */ q = &ctx->vq_dst; q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + q->io_modes = io_modes; + /* + * Destination buffers are always bidirectional, they use used as + * reference data, which require READ access + */ + q->bidirectional = true; q->drv_priv = &ctx->fh; q->lock = &dev->mfc_mutex; if (vdev == dev->vfd_dec) { - q->io_modes = VB2_MMAP; q->ops = get_dec_queue_ops(); } else if (vdev == dev->vfd_enc) { - q->io_modes = VB2_MMAP | VB2_USERPTR; q->ops = get_enc_queue_ops(); } else { ret = -ENOENT; @@ -869,13 +879,18 @@ static int s5p_mfc_open(struct file *file) /* Init videobuf2 queue for OUTPUT */ q = &ctx->vq_src; q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + q->io_modes = io_modes; + /* + * MFV v5 performs write operations on source data, so make queue + * bidirectional to avoid IOMMU protection fault. + */ + if (!IS_MFCV6_PLUS(dev)) + q->bidirectional = true; q->drv_priv = &ctx->fh; q->lock = &dev->mfc_mutex; if (vdev == dev->vfd_dec) { - q->io_modes = VB2_MMAP; q->ops = get_dec_queue_ops(); } else if (vdev == dev->vfd_enc) { - q->io_modes = VB2_MMAP | VB2_USERPTR; q->ops = get_enc_queue_ops(); } else { ret = -ENOENT; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index e3e5c442902a..26ee8315e2cf 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c @@ -551,14 +551,27 @@ static int reqbufs_capture(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx, goto out; } - WARN_ON(ctx->dst_bufs_cnt != ctx->total_dpb_count); - ctx->capture_state = QUEUE_BUFS_MMAPED; + if (reqbufs->memory == V4L2_MEMORY_MMAP) { + if (ctx->dst_bufs_cnt == ctx->total_dpb_count) { + ctx->capture_state = QUEUE_BUFS_MMAPED; + } else { + mfc_err("Not all buffers passed to buf_init\n"); + reqbufs->count = 0; + ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); + s5p_mfc_hw_call(dev->mfc_ops, + release_codec_buffers, ctx); + ret = -ENOMEM; + goto out; + } + } if (s5p_mfc_ctx_ready(ctx)) set_work_bit_irqsave(ctx); s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); - s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, - 0); + if (reqbufs->memory == V4L2_MEMORY_MMAP) { + s5p_mfc_wait_for_done_ctx(ctx, + S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, 0); + } } else { mfc_err("Buffers have already been requested\n"); ret = -EINVAL; @@ -576,15 +589,19 @@ static int vidioc_reqbufs(struct file *file, void *priv, { struct s5p_mfc_dev *dev = video_drvdata(file); struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); - - if (reqbufs->memory != V4L2_MEMORY_MMAP) { - mfc_debug(2, "Only V4L2_MEMORY_MMAP is supported\n"); - return -EINVAL; - } + int ret; if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + ret = vb2_verify_memory_type(&ctx->vq_src, reqbufs->memory, + reqbufs->type); + if (ret) + return ret; return reqbufs_output(dev, ctx, reqbufs); } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + ret = vb2_verify_memory_type(&ctx->vq_dst, reqbufs->memory, + reqbufs->type); + if (ret) + return ret; return reqbufs_capture(dev, ctx, reqbufs); } else { mfc_err("Invalid type requested\n"); @@ -600,16 +617,20 @@ static int vidioc_querybuf(struct file *file, void *priv, int ret; int i; - if (buf->memory != V4L2_MEMORY_MMAP) { - mfc_err("Only mmaped buffers can be used\n"); - return -EINVAL; - } mfc_debug(2, "State: %d, buf->type: %d\n", ctx->state, buf->type); if (ctx->state == MFCINST_GOT_INST && buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + ret = vb2_verify_memory_type(&ctx->vq_src, buf->memory, + buf->type); + if (ret) + return ret; ret = vb2_querybuf(&ctx->vq_src, buf); } else if (ctx->state == MFCINST_RUNNING && buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + ret = vb2_verify_memory_type(&ctx->vq_dst, buf->memory, + buf->type); + if (ret) + return ret; ret = vb2_querybuf(&ctx->vq_dst, buf); for (i = 0; i < buf->length; i++) buf->m.planes[i].m.mem_offset += DST_QUEUE_OFF_BASE; @@ -940,10 +961,12 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, else alloc_devs[0] = ctx->dev->mem_dev[BANK_R_CTX]; alloc_devs[1] = ctx->dev->mem_dev[BANK_L_CTX]; + memset(ctx->dst_bufs, 0, sizeof(ctx->dst_bufs)); } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && ctx->state == MFCINST_INIT) { psize[0] = ctx->dec_src_buf_size; alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX]; + memset(ctx->src_bufs, 0, sizeof(ctx->src_bufs)); } else { mfc_err("This video node is dedicated to decoding. Decoding not initialized\n"); return -EINVAL; @@ -959,30 +982,35 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb) unsigned int i; if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + dma_addr_t luma, chroma; + if (ctx->capture_state == QUEUE_BUFS_MMAPED) return 0; - for (i = 0; i < ctx->dst_fmt->num_planes; i++) { - if (IS_ERR_OR_NULL(ERR_PTR( - vb2_dma_contig_plane_dma_addr(vb, i)))) { - mfc_err("Plane mem not allocated\n"); - return -EINVAL; - } - } - if (vb2_plane_size(vb, 0) < ctx->luma_size || - vb2_plane_size(vb, 1) < ctx->chroma_size) { - mfc_err("Plane buffer (CAPTURE) is too small\n"); + + luma = vb2_dma_contig_plane_dma_addr(vb, 0); + chroma = vb2_dma_contig_plane_dma_addr(vb, 1); + if (!luma || !chroma) { + mfc_err("Plane mem not allocated\n"); return -EINVAL; } + i = vb->index; + if ((ctx->dst_bufs[i].cookie.raw.luma && + ctx->dst_bufs[i].cookie.raw.luma != luma) || + (ctx->dst_bufs[i].cookie.raw.chroma && + ctx->dst_bufs[i].cookie.raw.chroma != chroma)) { + mfc_err("Changing CAPTURE buffer address during straming is not possible\n"); + return -EINVAL; + } + ctx->dst_bufs[i].b = vbuf; - ctx->dst_bufs[i].cookie.raw.luma = - vb2_dma_contig_plane_dma_addr(vb, 0); - ctx->dst_bufs[i].cookie.raw.chroma = - vb2_dma_contig_plane_dma_addr(vb, 1); + ctx->dst_bufs[i].cookie.raw.luma = luma; + ctx->dst_bufs[i].cookie.raw.chroma = chroma; ctx->dst_bufs_cnt++; } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - if (IS_ERR_OR_NULL(ERR_PTR( - vb2_dma_contig_plane_dma_addr(vb, 0)))) { + dma_addr_t stream = vb2_dma_contig_plane_dma_addr(vb, 0); + + if (!stream) { mfc_err("Plane memory not allocated\n"); return -EINVAL; } @@ -992,9 +1020,14 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb) } i = vb->index; + if (ctx->src_bufs[i].cookie.stream && + ctx->src_bufs[i].cookie.stream != stream) { + mfc_err("Changing OUTPUT buffer address during straming is not possible\n"); + return -EINVAL; + } + ctx->src_bufs[i].b = vbuf; - ctx->src_bufs[i].cookie.stream = - vb2_dma_contig_plane_dma_addr(vb, 0); + ctx->src_bufs[i].cookie.stream = stream; ctx->src_bufs_cnt++; } else { mfc_err("s5p_mfc_buf_init: unknown queue type\n"); @@ -1071,6 +1104,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb) struct s5p_mfc_dev *dev = ctx->dev; unsigned long flags; struct s5p_mfc_buf *mfc_buf; + int wait_flag = 0; if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { mfc_buf = &ctx->src_bufs[vb->index]; @@ -1088,12 +1122,25 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb) list_add_tail(&mfc_buf->list, &ctx->dst_queue); ctx->dst_queue_cnt++; spin_unlock_irqrestore(&dev->irqlock, flags); + if ((vq->memory == V4L2_MEMORY_USERPTR || + vq->memory == V4L2_MEMORY_DMABUF) && + ctx->dst_queue_cnt == ctx->total_dpb_count) + ctx->capture_state = QUEUE_BUFS_MMAPED; } else { mfc_err("Unsupported buffer type (%d)\n", vq->type); } - if (s5p_mfc_ctx_ready(ctx)) + if (s5p_mfc_ctx_ready(ctx)) { set_work_bit_irqsave(ctx); + if ((vq->memory == V4L2_MEMORY_USERPTR || + vq->memory == V4L2_MEMORY_DMABUF) && + ctx->state == MFCINST_HEAD_PARSED && + ctx->capture_state == QUEUE_BUFS_MMAPED) + wait_flag = 1; + } s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); + if (wait_flag) + s5p_mfc_wait_for_done_ctx(ctx, + S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, 0); } static struct vb2_ops s5p_mfc_dec_qops = { diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index 7b041e5ee4be..33fc3f3ef48a 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c @@ -1125,11 +1125,11 @@ static int vidioc_reqbufs(struct file *file, void *priv, struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); int ret = 0; - /* if memory is not mmp or userptr return error */ - if ((reqbufs->memory != V4L2_MEMORY_MMAP) && - (reqbufs->memory != V4L2_MEMORY_USERPTR)) - return -EINVAL; if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + ret = vb2_verify_memory_type(&ctx->vq_dst, reqbufs->memory, + reqbufs->type); + if (ret) + return ret; if (reqbufs->count == 0) { mfc_debug(2, "Freeing buffers\n"); ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); @@ -1159,6 +1159,10 @@ static int vidioc_reqbufs(struct file *file, void *priv, return -ENOMEM; } } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + ret = vb2_verify_memory_type(&ctx->vq_src, reqbufs->memory, + reqbufs->type); + if (ret) + return ret; if (reqbufs->count == 0) { mfc_debug(2, "Freeing buffers\n"); ret = vb2_reqbufs(&ctx->vq_src, reqbufs); @@ -1190,6 +1194,8 @@ static int vidioc_reqbufs(struct file *file, void *priv, mfc_err("error in vb2_reqbufs() for E(S)\n"); return ret; } + if (reqbufs->memory != V4L2_MEMORY_MMAP) + ctx->src_bufs_cnt = reqbufs->count; ctx->output_state = QUEUE_BUFS_REQUESTED; } else { mfc_err("invalid buf type\n"); @@ -1204,11 +1210,11 @@ static int vidioc_querybuf(struct file *file, void *priv, struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); int ret = 0; - /* if memory is not mmp or userptr return error */ - if ((buf->memory != V4L2_MEMORY_MMAP) && - (buf->memory != V4L2_MEMORY_USERPTR)) - return -EINVAL; if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + ret = vb2_verify_memory_type(&ctx->vq_dst, buf->memory, + buf->type); + if (ret) + return ret; if (ctx->state != MFCINST_GOT_INST) { mfc_err("invalid context state: %d\n", ctx->state); return -EINVAL; @@ -1220,6 +1226,10 @@ static int vidioc_querybuf(struct file *file, void *priv, } buf->m.planes[0].m.mem_offset += DST_QUEUE_OFF_BASE; } else if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + ret = vb2_verify_memory_type(&ctx->vq_src, buf->memory, + buf->type); + if (ret) + return ret; ret = vb2_querybuf(&ctx->vq_src, buf); if (ret != 0) { mfc_err("error in vb2_querybuf() for E(S)\n"); @@ -1828,6 +1838,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, *buf_count = MFC_MAX_BUFFERS; psize[0] = ctx->enc_dst_buf_size; alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX]; + memset(ctx->dst_bufs, 0, sizeof(ctx->dst_bufs)); } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { if (ctx->src_fmt) *plane_count = ctx->src_fmt->num_planes; @@ -1849,6 +1860,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, alloc_devs[0] = ctx->dev->mem_dev[BANK_R_CTX]; alloc_devs[1] = ctx->dev->mem_dev[BANK_R_CTX]; } + memset(ctx->src_bufs, 0, sizeof(ctx->src_bufs)); } else { mfc_err("invalid queue type: %d\n", vq->type); return -EINVAL; @@ -1865,25 +1877,47 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb) int ret; if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + dma_addr_t stream; + ret = check_vb_with_fmt(ctx->dst_fmt, vb); if (ret < 0) return ret; + + stream = vb2_dma_contig_plane_dma_addr(vb, 0); i = vb->index; + if (ctx->dst_bufs[i].cookie.stream && + ctx->src_bufs[i].cookie.stream != stream) { + mfc_err("Changing CAPTURE buffer address during straming is not possible\n"); + return -EINVAL; + } + ctx->dst_bufs[i].b = vbuf; - ctx->dst_bufs[i].cookie.stream = - vb2_dma_contig_plane_dma_addr(vb, 0); + ctx->dst_bufs[i].cookie.stream = stream; ctx->dst_bufs_cnt++; } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + dma_addr_t luma, chroma; + ret = check_vb_with_fmt(ctx->src_fmt, vb); if (ret < 0) return ret; + + luma = vb2_dma_contig_plane_dma_addr(vb, 0); + chroma = vb2_dma_contig_plane_dma_addr(vb, 1); + i = vb->index; + if ((ctx->src_bufs[i].cookie.raw.luma && + ctx->src_bufs[i].cookie.raw.luma != luma) || + (ctx->src_bufs[i].cookie.raw.chroma && + ctx->src_bufs[i].cookie.raw.chroma != chroma)) { + mfc_err("Changing OUTPUT buffer address during straming is not possible\n"); + return -EINVAL; + } + ctx->src_bufs[i].b = vbuf; - ctx->src_bufs[i].cookie.raw.luma = - vb2_dma_contig_plane_dma_addr(vb, 0); - ctx->src_bufs[i].cookie.raw.chroma = - vb2_dma_contig_plane_dma_addr(vb, 1); - ctx->src_bufs_cnt++; + ctx->src_bufs[i].cookie.raw.luma = luma; + ctx->src_bufs[i].cookie.raw.chroma = chroma; + if (vb->memory == V4L2_MEMORY_MMAP) + ctx->src_bufs_cnt++; } else { mfc_err("invalid queue type: %d\n", vq->type); return -EINVAL;