From patchwork Tue Mar 19 14:52:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 10859741 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D2FC313B5 for ; Tue, 19 Mar 2019 14:52:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B8AB229698 for ; Tue, 19 Mar 2019 14:52:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AD13C2944D; Tue, 19 Mar 2019 14:52:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0108F2972F for ; Tue, 19 Mar 2019 14:52:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727270AbfCSOww (ORCPT ); Tue, 19 Mar 2019 10:52:52 -0400 Received: from bhuna.collabora.co.uk ([46.235.227.227]:37464 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726763AbfCSOww (ORCPT ); Tue, 19 Mar 2019 10:52:52 -0400 Received: from localhost.localdomain (unknown [IPv6:2a01:e0a:2c:6930:5cf4:84a1:2763:fe0d]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: bbrezillon) by bhuna.collabora.co.uk (Postfix) with ESMTPSA id 37B1B28139A; Tue, 19 Mar 2019 14:52:49 +0000 (GMT) From: Boris Brezillon To: Mauro Carvalho Chehab , Hans Verkuil , Laurent Pinchart , Sakari Ailus , linux-media@vger.kernel.org Cc: Tomasz Figa , Hirokazu Honda , Nicolas Dufresne , Boris Brezillon Subject: [RFC PATCH 1/3] media: v4l2: Get rid of ->vidioc_enum_fmt_vid_{cap,out}_mplane Date: Tue, 19 Mar 2019 15:52:41 +0100 Message-Id: <20190319145243.25047-2-boris.brezillon@collabora.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190319145243.25047-1-boris.brezillon@collabora.com> References: <20190319145243.25047-1-boris.brezillon@collabora.com> MIME-Version: 1.0 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Support for multiplanar and singleplanar formats is mutually exclusive, at least in practice. In our attempt to unify support for support for mplane and !mplane in v4l, let's get rid of the ->vidioc_enum_fmt_{vid,out}_cap_mplane() hooks and call ->vidioc_enum_fmt_{vid,out}_cap() instead. Signed-off-by: Boris Brezillon --- drivers/media/pci/intel/ipu3/ipu3-cio2.c | 2 +- drivers/media/platform/exynos-gsc/gsc-m2m.c | 4 ++-- .../media/platform/exynos4-is/fimc-capture.c | 2 +- .../platform/exynos4-is/fimc-isp-video.c | 2 +- drivers/media/platform/exynos4-is/fimc-lite.c | 2 +- drivers/media/platform/exynos4-is/fimc-m2m.c | 4 ++-- .../media/platform/mtk-jpeg/mtk_jpeg_core.c | 4 ++-- drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c | 4 ++-- .../platform/mtk-vcodec/mtk_vcodec_dec.c | 4 ++-- .../platform/mtk-vcodec/mtk_vcodec_enc.c | 4 ++-- .../media/platform/qcom/camss/camss-video.c | 2 +- drivers/media/platform/qcom/venus/vdec.c | 4 ++-- drivers/media/platform/qcom/venus/venc.c | 4 ++-- drivers/media/platform/rcar_fdp1.c | 4 ++-- drivers/media/platform/rcar_jpu.c | 4 ++-- drivers/media/platform/renesas-ceu.c | 2 +- drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 4 ++-- drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 4 ++-- drivers/media/platform/ti-vpe/vpe.c | 4 ++-- drivers/media/platform/vicodec/vicodec-core.c | 2 -- drivers/media/platform/vivid/vivid-core.c | 6 ++---- .../media/platform/vivid/vivid-vid-common.c | 20 ------------------- .../media/platform/vivid/vivid-vid-common.h | 2 -- drivers/media/v4l2-core/v4l2-dev.c | 2 -- drivers/media/v4l2-core/v4l2-ioctl.c | 12 ++--------- drivers/staging/media/ipu3/ipu3-v4l2.c | 4 ++-- .../media/rockchip/vpu/rockchip_vpu_enc.c | 4 ++-- include/media/v4l2-ioctl.h | 14 ++----------- 28 files changed, 42 insertions(+), 88 deletions(-) diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c index cdb79ae2d8dc..1f6907852bd3 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -1174,7 +1174,7 @@ static const struct v4l2_file_operations cio2_v4l2_fops = { static const struct v4l2_ioctl_ops cio2_v4l2_ioctl_ops = { .vidioc_querycap = cio2_v4l2_querycap, - .vidioc_enum_fmt_vid_cap_mplane = cio2_v4l2_enum_fmt, + .vidioc_enum_fmt_vid_cap = cio2_v4l2_enum_fmt, .vidioc_g_fmt_vid_cap_mplane = cio2_v4l2_g_fmt, .vidioc_s_fmt_vid_cap_mplane = cio2_v4l2_s_fmt, .vidioc_try_fmt_vid_cap_mplane = cio2_v4l2_try_fmt, diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c index c757f5d98bcc..9e2914d3d8f9 100644 --- a/drivers/media/platform/exynos-gsc/gsc-m2m.c +++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c @@ -562,8 +562,8 @@ static int gsc_m2m_s_selection(struct file *file, void *fh, static const struct v4l2_ioctl_ops gsc_m2m_ioctl_ops = { .vidioc_querycap = gsc_m2m_querycap, - .vidioc_enum_fmt_vid_cap_mplane = gsc_m2m_enum_fmt_mplane, - .vidioc_enum_fmt_vid_out_mplane = gsc_m2m_enum_fmt_mplane, + .vidioc_enum_fmt_vid_cap = gsc_m2m_enum_fmt_mplane, + .vidioc_enum_fmt_vid_out = gsc_m2m_enum_fmt_mplane, .vidioc_g_fmt_vid_cap_mplane = gsc_m2m_g_fmt_mplane, .vidioc_g_fmt_vid_out_mplane = gsc_m2m_g_fmt_mplane, .vidioc_try_fmt_vid_cap_mplane = gsc_m2m_try_fmt_mplane, diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index 3e9fcf4f8a13..649c3a5b4d03 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c @@ -1361,7 +1361,7 @@ static int fimc_cap_s_selection(struct file *file, void *fh, static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = { .vidioc_querycap = fimc_cap_querycap, - .vidioc_enum_fmt_vid_cap_mplane = fimc_cap_enum_fmt_mplane, + .vidioc_enum_fmt_vid_cap = fimc_cap_enum_fmt_mplane, .vidioc_try_fmt_vid_cap_mplane = fimc_cap_try_fmt_mplane, .vidioc_s_fmt_vid_cap_mplane = fimc_cap_s_fmt_mplane, .vidioc_g_fmt_vid_cap_mplane = fimc_cap_g_fmt_mplane, diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c index de6bd28f7e31..ede50eec3925 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp-video.c +++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c @@ -551,7 +551,7 @@ static int isp_video_reqbufs(struct file *file, void *priv, static const struct v4l2_ioctl_ops isp_video_ioctl_ops = { .vidioc_querycap = isp_video_querycap, - .vidioc_enum_fmt_vid_cap_mplane = isp_video_enum_fmt_mplane, + .vidioc_enum_fmt_vid_cap = isp_video_enum_fmt_mplane, .vidioc_try_fmt_vid_cap_mplane = isp_video_try_fmt_mplane, .vidioc_s_fmt_vid_cap_mplane = isp_video_s_fmt_mplane, .vidioc_g_fmt_vid_cap_mplane = isp_video_g_fmt_mplane, diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index 96f0a8a0dcae..b9c537d38a45 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -954,7 +954,7 @@ static int fimc_lite_s_selection(struct file *file, void *fh, static const struct v4l2_ioctl_ops fimc_lite_ioctl_ops = { .vidioc_querycap = fimc_lite_querycap, - .vidioc_enum_fmt_vid_cap_mplane = fimc_lite_enum_fmt_mplane, + .vidioc_enum_fmt_vid_cap = fimc_lite_enum_fmt_mplane, .vidioc_try_fmt_vid_cap_mplane = fimc_lite_try_fmt_mplane, .vidioc_s_fmt_vid_cap_mplane = fimc_lite_s_fmt_mplane, .vidioc_g_fmt_vid_cap_mplane = fimc_lite_g_fmt_mplane, diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c index 61c8177409cf..278ab067e30f 100644 --- a/drivers/media/platform/exynos4-is/fimc-m2m.c +++ b/drivers/media/platform/exynos4-is/fimc-m2m.c @@ -533,8 +533,8 @@ static int fimc_m2m_s_selection(struct file *file, void *fh, static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = { .vidioc_querycap = fimc_m2m_querycap, - .vidioc_enum_fmt_vid_cap_mplane = fimc_m2m_enum_fmt_mplane, - .vidioc_enum_fmt_vid_out_mplane = fimc_m2m_enum_fmt_mplane, + .vidioc_enum_fmt_vid_cap = fimc_m2m_enum_fmt_mplane, + .vidioc_enum_fmt_vid_out = fimc_m2m_enum_fmt_mplane, .vidioc_g_fmt_vid_cap_mplane = fimc_m2m_g_fmt_mplane, .vidioc_g_fmt_vid_out_mplane = fimc_m2m_g_fmt_mplane, .vidioc_try_fmt_vid_cap_mplane = fimc_m2m_try_fmt_mplane, diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c index 2a5d5002c27e..04d27dae3490 100644 --- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c +++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c @@ -536,8 +536,8 @@ static int mtk_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) static const struct v4l2_ioctl_ops mtk_jpeg_ioctl_ops = { .vidioc_querycap = mtk_jpeg_querycap, - .vidioc_enum_fmt_vid_cap_mplane = mtk_jpeg_enum_fmt_vid_cap, - .vidioc_enum_fmt_vid_out_mplane = mtk_jpeg_enum_fmt_vid_out, + .vidioc_enum_fmt_vid_cap = mtk_jpeg_enum_fmt_vid_cap, + .vidioc_enum_fmt_vid_out = mtk_jpeg_enum_fmt_vid_out, .vidioc_try_fmt_vid_cap_mplane = mtk_jpeg_try_fmt_vid_cap_mplane, .vidioc_try_fmt_vid_out_mplane = mtk_jpeg_try_fmt_vid_out_mplane, .vidioc_g_fmt_vid_cap_mplane = mtk_jpeg_g_fmt_vid_mplane, diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c index 51a13466261e..1ba1b2254149 100644 --- a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c +++ b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c @@ -941,8 +941,8 @@ static int mtk_mdp_m2m_s_selection(struct file *file, void *fh, static const struct v4l2_ioctl_ops mtk_mdp_m2m_ioctl_ops = { .vidioc_querycap = mtk_mdp_m2m_querycap, - .vidioc_enum_fmt_vid_cap_mplane = mtk_mdp_m2m_enum_fmt_mplane_vid_cap, - .vidioc_enum_fmt_vid_out_mplane = mtk_mdp_m2m_enum_fmt_mplane_vid_out, + .vidioc_enum_fmt_vid_cap = mtk_mdp_m2m_enum_fmt_mplane_vid_cap, + .vidioc_enum_fmt_vid_out = mtk_mdp_m2m_enum_fmt_mplane_vid_out, .vidioc_g_fmt_vid_cap_mplane = mtk_mdp_m2m_g_fmt_mplane, .vidioc_g_fmt_vid_out_mplane = mtk_mdp_m2m_g_fmt_mplane, .vidioc_try_fmt_vid_cap_mplane = mtk_mdp_m2m_try_fmt_mplane, diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c index ba619647bc10..4362c0607455 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c @@ -1454,8 +1454,8 @@ const struct v4l2_ioctl_ops mtk_vdec_ioctl_ops = { .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, - .vidioc_enum_fmt_vid_cap_mplane = vidioc_vdec_enum_fmt_vid_cap_mplane, - .vidioc_enum_fmt_vid_out_mplane = vidioc_vdec_enum_fmt_vid_out_mplane, + .vidioc_enum_fmt_vid_cap = vidioc_vdec_enum_fmt_vid_cap_mplane, + .vidioc_enum_fmt_vid_out = vidioc_vdec_enum_fmt_vid_out_mplane, .vidioc_enum_framesizes = vidioc_enum_framesizes, .vidioc_querycap = vidioc_vdec_querycap, diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c index d1f12257bf66..351a28f3d24f 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c @@ -725,8 +725,8 @@ const struct v4l2_ioctl_ops mtk_venc_ioctl_ops = { .vidioc_dqbuf = vidioc_venc_dqbuf, .vidioc_querycap = vidioc_venc_querycap, - .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane, - .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap_mplane, + .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out_mplane, .vidioc_enum_framesizes = vidioc_enum_framesizes, .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap_mplane, diff --git a/drivers/media/platform/qcom/camss/camss-video.c b/drivers/media/platform/qcom/camss/camss-video.c index 58aebe7114cd..1d50dfbbb762 100644 --- a/drivers/media/platform/qcom/camss/camss-video.c +++ b/drivers/media/platform/qcom/camss/camss-video.c @@ -703,7 +703,7 @@ static int video_s_input(struct file *file, void *fh, unsigned int input) static const struct v4l2_ioctl_ops msm_vid_ioctl_ops = { .vidioc_querycap = video_querycap, - .vidioc_enum_fmt_vid_cap_mplane = video_enum_fmt, + .vidioc_enum_fmt_vid_cap = video_enum_fmt, .vidioc_g_fmt_vid_cap_mplane = video_g_fmt, .vidioc_s_fmt_vid_cap_mplane = video_s_fmt, .vidioc_try_fmt_vid_cap_mplane = video_try_fmt, diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 282de21cf2e1..2a47b9b8c5bc 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -491,8 +491,8 @@ vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd) static const struct v4l2_ioctl_ops vdec_ioctl_ops = { .vidioc_querycap = vdec_querycap, - .vidioc_enum_fmt_vid_cap_mplane = vdec_enum_fmt, - .vidioc_enum_fmt_vid_out_mplane = vdec_enum_fmt, + .vidioc_enum_fmt_vid_cap = vdec_enum_fmt, + .vidioc_enum_fmt_vid_out = vdec_enum_fmt, .vidioc_s_fmt_vid_cap_mplane = vdec_s_fmt, .vidioc_s_fmt_vid_out_mplane = vdec_s_fmt, .vidioc_g_fmt_vid_cap_mplane = vdec_g_fmt, diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index 32cff294582f..406a47923996 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -616,8 +616,8 @@ static int venc_enum_frameintervals(struct file *file, void *fh, static const struct v4l2_ioctl_ops venc_ioctl_ops = { .vidioc_querycap = venc_querycap, - .vidioc_enum_fmt_vid_cap_mplane = venc_enum_fmt, - .vidioc_enum_fmt_vid_out_mplane = venc_enum_fmt, + .vidioc_enum_fmt_vid_cap = venc_enum_fmt, + .vidioc_enum_fmt_vid_out = venc_enum_fmt, .vidioc_s_fmt_vid_cap_mplane = venc_s_fmt, .vidioc_s_fmt_vid_out_mplane = venc_s_fmt, .vidioc_g_fmt_vid_cap_mplane = venc_g_fmt, diff --git a/drivers/media/platform/rcar_fdp1.c b/drivers/media/platform/rcar_fdp1.c index 6bda1eee9170..6e6471c37984 100644 --- a/drivers/media/platform/rcar_fdp1.c +++ b/drivers/media/platform/rcar_fdp1.c @@ -1730,8 +1730,8 @@ static const char * const fdp1_ctrl_deint_menu[] = { static const struct v4l2_ioctl_ops fdp1_ioctl_ops = { .vidioc_querycap = fdp1_vidioc_querycap, - .vidioc_enum_fmt_vid_cap_mplane = fdp1_enum_fmt_vid_cap, - .vidioc_enum_fmt_vid_out_mplane = fdp1_enum_fmt_vid_out, + .vidioc_enum_fmt_vid_cap = fdp1_enum_fmt_vid_cap, + .vidioc_enum_fmt_vid_out = fdp1_enum_fmt_vid_out, .vidioc_g_fmt_vid_cap_mplane = fdp1_g_fmt, .vidioc_g_fmt_vid_out_mplane = fdp1_g_fmt, .vidioc_try_fmt_vid_cap_mplane = fdp1_try_fmt, diff --git a/drivers/media/platform/rcar_jpu.c b/drivers/media/platform/rcar_jpu.c index 1dfd2eb65920..a34f4e6b2f98 100644 --- a/drivers/media/platform/rcar_jpu.c +++ b/drivers/media/platform/rcar_jpu.c @@ -948,8 +948,8 @@ static int jpu_streamon(struct file *file, void *priv, enum v4l2_buf_type type) static const struct v4l2_ioctl_ops jpu_ioctl_ops = { .vidioc_querycap = jpu_querycap, - .vidioc_enum_fmt_vid_cap_mplane = jpu_enum_fmt_cap, - .vidioc_enum_fmt_vid_out_mplane = jpu_enum_fmt_out, + .vidioc_enum_fmt_vid_cap = jpu_enum_fmt_cap, + .vidioc_enum_fmt_vid_out = jpu_enum_fmt_out, .vidioc_g_fmt_vid_cap_mplane = jpu_g_fmt, .vidioc_g_fmt_vid_out_mplane = jpu_g_fmt, .vidioc_try_fmt_vid_cap_mplane = jpu_try_fmt, diff --git a/drivers/media/platform/renesas-ceu.c b/drivers/media/platform/renesas-ceu.c index 150196f7cf96..57d0c0f9fa4b 100644 --- a/drivers/media/platform/renesas-ceu.c +++ b/drivers/media/platform/renesas-ceu.c @@ -1339,7 +1339,7 @@ static int ceu_enum_frameintervals(struct file *file, void *fh, static const struct v4l2_ioctl_ops ceu_ioctl_ops = { .vidioc_querycap = ceu_querycap, - .vidioc_enum_fmt_vid_cap_mplane = ceu_enum_fmt_vid_cap, + .vidioc_enum_fmt_vid_cap = ceu_enum_fmt_vid_cap, .vidioc_try_fmt_vid_cap_mplane = ceu_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap_mplane = ceu_s_fmt_vid_cap, .vidioc_g_fmt_vid_cap_mplane = ceu_g_fmt_vid_cap, diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index f4c0e3a8f27d..15ad74089958 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c @@ -887,8 +887,8 @@ static int vidioc_subscribe_event(struct v4l2_fh *fh, /* v4l2_ioctl_ops */ static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = { .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane, - .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap_mplane, + .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out_mplane, .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt, .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt, .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt, diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index 8fcf627dedfb..2fa16ee9c7b0 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c @@ -2343,8 +2343,8 @@ static int vidioc_subscribe_event(struct v4l2_fh *fh, static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = { .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane, - .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap_mplane, + .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out_mplane, .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt, .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt, .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt, diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c index d70871d0ad2d..0b55de9354ab 100644 --- a/drivers/media/platform/ti-vpe/vpe.c +++ b/drivers/media/platform/ti-vpe/vpe.c @@ -1973,12 +1973,12 @@ static const struct v4l2_ctrl_ops vpe_ctrl_ops = { static const struct v4l2_ioctl_ops vpe_ioctl_ops = { .vidioc_querycap = vpe_querycap, - .vidioc_enum_fmt_vid_cap_mplane = vpe_enum_fmt, + .vidioc_enum_fmt_vid_cap = vpe_enum_fmt, .vidioc_g_fmt_vid_cap_mplane = vpe_g_fmt, .vidioc_try_fmt_vid_cap_mplane = vpe_try_fmt, .vidioc_s_fmt_vid_cap_mplane = vpe_s_fmt, - .vidioc_enum_fmt_vid_out_mplane = vpe_enum_fmt, + .vidioc_enum_fmt_vid_out = vpe_enum_fmt, .vidioc_g_fmt_vid_out_mplane = vpe_g_fmt, .vidioc_try_fmt_vid_out_mplane = vpe_try_fmt, .vidioc_s_fmt_vid_out_mplane = vpe_s_fmt, diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index 0d7876f5acf0..3d922f848887 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -869,7 +869,6 @@ static const struct v4l2_ioctl_ops vicodec_ioctl_ops = { .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap, .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt_vid_cap, .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_vid_cap, @@ -879,7 +878,6 @@ static const struct v4l2_ioctl_ops vicodec_ioctl_ops = { .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, - .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out, .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt_vid_out, .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_vid_out, .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt_vid_out, diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c index c931f007e5b0..eedc8ea8c8fc 100644 --- a/drivers/media/platform/vivid/vivid-core.c +++ b/drivers/media/platform/vivid/vivid-core.c @@ -500,20 +500,18 @@ static const struct v4l2_file_operations vivid_radio_fops = { static const struct v4l2_ioctl_ops vivid_ioctl_ops = { .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid, + .vidioc_enum_fmt_vid_cap = vivid_enum_fmt_vid, .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_mplane, .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt_vid_cap_mplane, .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap_mplane, .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_vid_cap_mplane, - .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid, + .vidioc_enum_fmt_vid_out = vivid_enum_fmt_vid, .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out, .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, - .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_mplane, .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt_vid_out_mplane, .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_vid_out_mplane, .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt_vid_out_mplane, diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c index 661f4015fba1..3769f76e04b3 100644 --- a/drivers/media/platform/vivid/vivid-vid-common.c +++ b/drivers/media/platform/vivid/vivid-vid-common.c @@ -767,26 +767,6 @@ int vivid_enum_fmt_vid(struct file *file, void *priv, return 0; } -int vidioc_enum_fmt_vid_mplane(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - struct vivid_dev *dev = video_drvdata(file); - - if (!dev->multiplanar) - return -ENOTTY; - return vivid_enum_fmt_vid(file, priv, f); -} - -int vidioc_enum_fmt_vid(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - struct vivid_dev *dev = video_drvdata(file); - - if (dev->multiplanar) - return -ENOTTY; - return vivid_enum_fmt_vid(file, priv, f); -} - int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) { struct vivid_dev *dev = video_drvdata(file); diff --git a/drivers/media/platform/vivid/vivid-vid-common.h b/drivers/media/platform/vivid/vivid-vid-common.h index 29b6c0b40a1b..d908d9725283 100644 --- a/drivers/media/platform/vivid/vivid-vid-common.h +++ b/drivers/media/platform/vivid/vivid-vid-common.h @@ -28,8 +28,6 @@ void vivid_send_source_change(struct vivid_dev *dev, unsigned type); int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r); int vivid_enum_fmt_vid(struct file *file, void *priv, struct v4l2_fmtdesc *f); -int vidioc_enum_fmt_vid_mplane(struct file *file, void *priv, struct v4l2_fmtdesc *f); -int vidioc_enum_fmt_vid(struct file *file, void *priv, struct v4l2_fmtdesc *f); int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id); int vidioc_g_dv_timings(struct file *file, void *_fh, struct v4l2_dv_timings *timings); int vidioc_enum_dv_timings(struct file *file, void *_fh, struct v4l2_enum_dv_timings *timings); diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index d7528f82a66a..29946a2b2752 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -593,11 +593,9 @@ static void determine_valid_ioctls(struct video_device *vdev) if (is_vid || is_tch) { /* video and metadata specific ioctls */ if ((is_rx && (ops->vidioc_enum_fmt_vid_cap || - ops->vidioc_enum_fmt_vid_cap_mplane || ops->vidioc_enum_fmt_vid_overlay || ops->vidioc_enum_fmt_meta_cap)) || (is_tx && (ops->vidioc_enum_fmt_vid_out || - ops->vidioc_enum_fmt_vid_out_mplane || ops->vidioc_enum_fmt_meta_out))) set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls); if ((is_rx && (ops->vidioc_g_fmt_vid_cap || diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 90aad465f9ed..f1696717ab32 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1379,30 +1379,22 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops, switch (p->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: if (unlikely(!ops->vidioc_enum_fmt_vid_cap)) break; ret = ops->vidioc_enum_fmt_vid_cap(file, fh, arg); break; - case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - if (unlikely(!ops->vidioc_enum_fmt_vid_cap_mplane)) - break; - ret = ops->vidioc_enum_fmt_vid_cap_mplane(file, fh, arg); - break; case V4L2_BUF_TYPE_VIDEO_OVERLAY: if (unlikely(!ops->vidioc_enum_fmt_vid_overlay)) break; ret = ops->vidioc_enum_fmt_vid_overlay(file, fh, arg); break; case V4L2_BUF_TYPE_VIDEO_OUTPUT: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: if (unlikely(!ops->vidioc_enum_fmt_vid_out)) break; ret = ops->vidioc_enum_fmt_vid_out(file, fh, arg); break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - if (unlikely(!ops->vidioc_enum_fmt_vid_out_mplane)) - break; - ret = ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg); - break; case V4L2_BUF_TYPE_SDR_CAPTURE: if (unlikely(!ops->vidioc_enum_fmt_sdr_cap)) break; diff --git a/drivers/staging/media/ipu3/ipu3-v4l2.c b/drivers/staging/media/ipu3/ipu3-v4l2.c index c7936032beb9..33b999486073 100644 --- a/drivers/staging/media/ipu3/ipu3-v4l2.c +++ b/drivers/staging/media/ipu3/ipu3-v4l2.c @@ -956,12 +956,12 @@ static const struct v4l2_file_operations ipu3_v4l2_fops = { static const struct v4l2_ioctl_ops ipu3_v4l2_ioctl_ops = { .vidioc_querycap = ipu3_vidioc_querycap, - .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, .vidioc_g_fmt_vid_cap_mplane = ipu3_vidioc_g_fmt, .vidioc_s_fmt_vid_cap_mplane = ipu3_vidioc_s_fmt, .vidioc_try_fmt_vid_cap_mplane = ipu3_vidioc_try_fmt, - .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out, + .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out, .vidioc_g_fmt_vid_out_mplane = ipu3_vidioc_g_fmt, .vidioc_s_fmt_vid_out_mplane = ipu3_vidioc_s_fmt, .vidioc_try_fmt_vid_out_mplane = ipu3_vidioc_try_fmt, diff --git a/drivers/staging/media/rockchip/vpu/rockchip_vpu_enc.c b/drivers/staging/media/rockchip/vpu/rockchip_vpu_enc.c index ab0fb2053620..f42d8325fd33 100644 --- a/drivers/staging/media/rockchip/vpu/rockchip_vpu_enc.c +++ b/drivers/staging/media/rockchip/vpu/rockchip_vpu_enc.c @@ -493,8 +493,8 @@ const struct v4l2_ioctl_ops rockchip_vpu_enc_ioctl_ops = { .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_cap_mplane, .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt_out_mplane, .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt_cap_mplane, - .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane, - .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane, + .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out_mplane, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap_mplane, .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index 8533ece5026e..400f2e46c108 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -26,19 +26,13 @@ struct v4l2_fh; * :ref:`VIDIOC_QUERYCAP ` ioctl * @vidioc_enum_fmt_vid_cap: pointer to the function that implements * :ref:`VIDIOC_ENUM_FMT ` ioctl logic - * for video capture in single plane mode + * for video capture in single and multi plane mode * @vidioc_enum_fmt_vid_overlay: pointer to the function that implements * :ref:`VIDIOC_ENUM_FMT ` ioctl logic * for video overlay * @vidioc_enum_fmt_vid_out: pointer to the function that implements * :ref:`VIDIOC_ENUM_FMT ` ioctl logic - * for video output in single plane mode - * @vidioc_enum_fmt_vid_cap_mplane: pointer to the function that implements - * :ref:`VIDIOC_ENUM_FMT ` ioctl logic - * for video capture in multiplane mode - * @vidioc_enum_fmt_vid_out_mplane: pointer to the function that implements - * :ref:`VIDIOC_ENUM_FMT ` ioctl logic - * for video output in multiplane mode + * for video output in single and multi plane mode * @vidioc_enum_fmt_sdr_cap: pointer to the function that implements * :ref:`VIDIOC_ENUM_FMT ` ioctl logic * for Software Defined Radio capture @@ -313,10 +307,6 @@ struct v4l2_ioctl_ops { struct v4l2_fmtdesc *f); int (*vidioc_enum_fmt_vid_out)(struct file *file, void *fh, struct v4l2_fmtdesc *f); - int (*vidioc_enum_fmt_vid_cap_mplane)(struct file *file, void *fh, - struct v4l2_fmtdesc *f); - int (*vidioc_enum_fmt_vid_out_mplane)(struct file *file, void *fh, - struct v4l2_fmtdesc *f); int (*vidioc_enum_fmt_sdr_cap)(struct file *file, void *fh, struct v4l2_fmtdesc *f); int (*vidioc_enum_fmt_sdr_out)(struct file *file, void *fh, From patchwork Tue Mar 19 14:52:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 10859743 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8113E13B5 for ; Tue, 19 Mar 2019 14:52:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 63DF7284B9 for ; Tue, 19 Mar 2019 14:52:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 615EF2972C; Tue, 19 Mar 2019 14:52:56 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2F488284B9 for ; Tue, 19 Mar 2019 14:52:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727755AbfCSOwx (ORCPT ); Tue, 19 Mar 2019 10:52:53 -0400 Received: from bhuna.collabora.co.uk ([46.235.227.227]:37486 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726926AbfCSOwx (ORCPT ); Tue, 19 Mar 2019 10:52:53 -0400 Received: from localhost.localdomain (unknown [IPv6:2a01:e0a:2c:6930:5cf4:84a1:2763:fe0d]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: bbrezillon) by bhuna.collabora.co.uk (Postfix) with ESMTPSA id AB0F228139B; Tue, 19 Mar 2019 14:52:49 +0000 (GMT) From: Boris Brezillon To: Mauro Carvalho Chehab , Hans Verkuil , Laurent Pinchart , Sakari Ailus , linux-media@vger.kernel.org Cc: Tomasz Figa , Hirokazu Honda , Nicolas Dufresne , Boris Brezillon Subject: [RFC PATCH 2/3] media: v4l2: Extend pixel formats to unify single/multi-planar handling (and more) Date: Tue, 19 Mar 2019 15:52:42 +0100 Message-Id: <20190319145243.25047-3-boris.brezillon@collabora.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190319145243.25047-1-boris.brezillon@collabora.com> References: <20190319145243.25047-1-boris.brezillon@collabora.com> MIME-Version: 1.0 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This is part of the multiplanar and singleplanar unification process. v4l2_ext_pix_format is supposed to work for both cases. We also add the concept of modifiers already employed in DRM to expose HW-specific formats (like tiled or compressed formats) and allow exchanging this information with the DRM subsystem in a consistent way. Note that V4L2_BUF_TYPE_VIDEO[_OUTPUT]_OVERLAY and V4L2_BUF_TYPE_VIDEO_{CAPTURE,OUTPUT}_MPLANE types are no longer accepted in v4l2_ext_format and will be rejected if you use the {G,S,TRY}EXT_FMT ioctls. V4L2_BUF_TYPE_VIDEO_{CAPTURE,OUTPUT}_MPLANE is dropped as part of the multiplanar/singleplanar unification. V4L2_BUF_TYPE_VIDEO[_OUTPUT]_OVERLAY seems to be used mostly on old drivers and supporting it would require some extra rework. New hooks have been added to v4l2_ioctl_ops to support those new ioctls in drivers, but, in the meantime, the core takes care of converting {S,G,TRY}_EXT_FMT requests into {S,G,TRY}_FMT so that old drivers can still work if the userspace app/lib uses the new ioctls. The conversion is also done the other around to allow userspace apps/libs using {S,G,TRY}_FMT to work with drivers implementing the _ext_ hooks. Signed-off-by: Boris Brezillon --- drivers/media/v4l2-core/v4l2-common.c | 189 ++++++++++ drivers/media/v4l2-core/v4l2-dev.c | 24 +- drivers/media/v4l2-core/v4l2-ioctl.c | 504 +++++++++++++++++++++----- include/media/v4l2-common.h | 6 + include/media/v4l2-ioctl.h | 27 ++ include/uapi/linux/videodev2.h | 82 +++++ 6 files changed, 743 insertions(+), 89 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c index 50763fb42a1b..fb6ba89564d1 100644 --- a/drivers/media/v4l2-core/v4l2-common.c +++ b/drivers/media/v4l2-core/v4l2-common.c @@ -455,3 +455,192 @@ int v4l2_s_parm_cap(struct video_device *vdev, return ret; } EXPORT_SYMBOL_GPL(v4l2_s_parm_cap); + +int v4l2_ext_format_to_format(const struct v4l2_ext_format *e, + struct v4l2_format *f, bool mplane_cap) +{ + const struct v4l2_plane_ext_pix_format *pe; + struct v4l2_plane_pix_format *p; + unsigned int i; + + if (e->fmt.pix.num_planes > VIDEO_MAX_PLANES) + return -EINVAL; + + memset(f, 0, sizeof(*f)); + + switch (e->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + /* + * Make sure no modifier is required before doing the + * conversion. + */ + for (i = 0; i < e->fmt.pix.num_planes; i++) { + if (WARN_ON(e->fmt.pix.plane_fmt[i].modifier)) + return -ENOTSUPP; + } + + if (e->fmt.pix.num_planes > 1 && !mplane_cap) + return -EINVAL; + + if (!mplane_cap) { + f->fmt.pix.width = e->fmt.pix.width; + f->fmt.pix.width = e->fmt.pix.height; + f->fmt.pix.pixelformat = e->fmt.pix.pixelformat; + f->fmt.pix.field = e->fmt.pix.field; + f->fmt.pix.colorspace = e->fmt.pix.colorspace; + f->fmt.pix.flags = e->fmt.pix.flags; + f->fmt.pix.ycbcr_enc = e->fmt.pix.ycbcr_enc; + f->fmt.pix.quantization = e->fmt.pix.quantization; + pe = &e->fmt.pix.plane_fmt[0]; + f->fmt.pix.bytesperline = pe->bytesperline; + f->fmt.pix.sizeimage = pe->sizeimage; + f->type = e->type; + break; + } + + f->fmt.pix_mp.width = e->fmt.pix.width; + f->fmt.pix_mp.width = e->fmt.pix.height; + f->fmt.pix_mp.pixelformat = e->fmt.pix.pixelformat; + f->fmt.pix_mp.field = e->fmt.pix.field; + f->fmt.pix_mp.colorspace = e->fmt.pix.colorspace; + f->fmt.pix_mp.flags = e->fmt.pix.flags; + f->fmt.pix_mp.ycbcr_enc = e->fmt.pix.ycbcr_enc; + f->fmt.pix_mp.quantization = e->fmt.pix.quantization; + if (e->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + else + f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + + for (i = 0; i < e->fmt.pix.num_planes; i++) { + pe = &e->fmt.pix.plane_fmt[i]; + p = &f->fmt.pix_mp.plane_fmt[i]; + p->bytesperline = pe->bytesperline; + p->sizeimage = pe->sizeimage; + } + break; + + case V4L2_BUF_TYPE_VBI_CAPTURE: + case V4L2_BUF_TYPE_VBI_OUTPUT: + f->type = e->type; + f->fmt.vbi = e->fmt.vbi; + break; + + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + f->type = e->type; + f->fmt.sliced = e->fmt.sliced; + break; + + case V4L2_BUF_TYPE_SDR_CAPTURE: + case V4L2_BUF_TYPE_SDR_OUTPUT: + f->type = e->type; + f->fmt.sdr = e->fmt.sdr; + break; + + case V4L2_BUF_TYPE_META_CAPTURE: + case V4L2_BUF_TYPE_META_OUTPUT: + f->type = e->type; + f->fmt.meta = e->fmt.meta; + break; + + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_ext_format_to_format); + +int v4l2_format_to_ext_format(const struct v4l2_format *f, + struct v4l2_ext_format *e) +{ + const struct v4l2_plane_pix_format *p; + struct v4l2_plane_ext_pix_format *pe; + unsigned int i; + + memset(e, 0, sizeof(*e)); + + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + e->fmt.pix.width = f->fmt.pix.width; + e->fmt.pix.width = f->fmt.pix.height; + e->fmt.pix.pixelformat = f->fmt.pix.pixelformat; + e->fmt.pix.field = f->fmt.pix.field; + e->fmt.pix.colorspace = f->fmt.pix.colorspace; + e->fmt.pix.flags = f->fmt.pix.flags; + e->fmt.pix.ycbcr_enc = f->fmt.pix.ycbcr_enc; + e->fmt.pix.quantization = f->fmt.pix.quantization; + e->fmt.pix.num_planes = 1; + e->fmt.pix.plane_fmt[0].bytesperline = f->fmt.pix.bytesperline; + e->fmt.pix.plane_fmt[0].sizeimage = f->fmt.pix.sizeimage; + e->type = f->type; + break; + + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + if (f->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES) + return -EINVAL; + + e->fmt.pix.width = f->fmt.pix_mp.width; + e->fmt.pix.width = f->fmt.pix_mp.height; + e->fmt.pix.pixelformat = f->fmt.pix_mp.pixelformat; + e->fmt.pix.field = f->fmt.pix_mp.field; + e->fmt.pix.colorspace = f->fmt.pix_mp.colorspace; + e->fmt.pix.flags = f->fmt.pix_mp.flags; + e->fmt.pix.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; + e->fmt.pix.quantization = f->fmt.pix_mp.quantization; + e->fmt.pix.num_planes = f->fmt.pix_mp.num_planes; + if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) + e->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + else + e->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + + for (i = 0; i < e->fmt.pix.num_planes; i++) { + pe = &e->fmt.pix.plane_fmt[i]; + p = &f->fmt.pix_mp.plane_fmt[i]; + pe->bytesperline = p->bytesperline; + pe->sizeimage = p->sizeimage; + } + break; + + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + /* + * OVERLAY formats are not supported by the _EXT_FMT + * ioctl()s. + */ + return -ENOTSUPP; + + case V4L2_BUF_TYPE_VBI_CAPTURE: + case V4L2_BUF_TYPE_VBI_OUTPUT: + e->type = f->type; + e->fmt.vbi = f->fmt.vbi; + break; + + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + e->type = f->type; + e->fmt.sliced = f->fmt.sliced; + break; + + case V4L2_BUF_TYPE_SDR_CAPTURE: + case V4L2_BUF_TYPE_SDR_OUTPUT: + e->type = f->type; + e->fmt.sdr = f->fmt.sdr; + break; + + case V4L2_BUF_TYPE_META_CAPTURE: + case V4L2_BUF_TYPE_META_OUTPUT: + e->type = f->type; + e->fmt.meta = f->fmt.meta; + break; + + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_format_to_ext_format); diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index 29946a2b2752..a233e0924ed3 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -599,32 +599,44 @@ static void determine_valid_ioctls(struct video_device *vdev) ops->vidioc_enum_fmt_meta_out))) set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls); if ((is_rx && (ops->vidioc_g_fmt_vid_cap || + ops->vidioc_g_ext_fmt_vid_cap || ops->vidioc_g_fmt_vid_cap_mplane || ops->vidioc_g_fmt_vid_overlay || ops->vidioc_g_fmt_meta_cap)) || (is_tx && (ops->vidioc_g_fmt_vid_out || + ops->vidioc_g_ext_fmt_vid_out || ops->vidioc_g_fmt_vid_out_mplane || ops->vidioc_g_fmt_vid_out_overlay || - ops->vidioc_g_fmt_meta_out))) - set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls); + ops->vidioc_g_fmt_meta_out))) { + set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls); + set_bit(_IOC_NR(VIDIOC_G_EXT_FMT), valid_ioctls); + } if ((is_rx && (ops->vidioc_s_fmt_vid_cap || + ops->vidioc_s_ext_fmt_vid_cap || ops->vidioc_s_fmt_vid_cap_mplane || ops->vidioc_s_fmt_vid_overlay || ops->vidioc_s_fmt_meta_cap)) || (is_tx && (ops->vidioc_s_fmt_vid_out || + ops->vidioc_s_ext_fmt_vid_out || ops->vidioc_s_fmt_vid_out_mplane || ops->vidioc_s_fmt_vid_out_overlay || - ops->vidioc_s_fmt_meta_out))) - set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls); + ops->vidioc_s_fmt_meta_out))) { + set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls); + set_bit(_IOC_NR(VIDIOC_S_EXT_FMT), valid_ioctls); + } if ((is_rx && (ops->vidioc_try_fmt_vid_cap || + ops->vidioc_try_ext_fmt_vid_cap || ops->vidioc_try_fmt_vid_cap_mplane || ops->vidioc_try_fmt_vid_overlay || ops->vidioc_try_fmt_meta_cap)) || (is_tx && (ops->vidioc_try_fmt_vid_out || + ops->vidioc_try_ext_fmt_vid_out || ops->vidioc_try_fmt_vid_out_mplane || ops->vidioc_try_fmt_vid_out_overlay || - ops->vidioc_try_fmt_meta_out))) - set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls); + ops->vidioc_try_fmt_meta_out))) { + set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls); + set_bit(_IOC_NR(VIDIOC_TRY_EXT_FMT), valid_ioctls); + } SET_VALID_IOCTL(ops, VIDIOC_OVERLAY, vidioc_overlay); SET_VALID_IOCTL(ops, VIDIOC_G_FBUF, vidioc_g_fbuf); SET_VALID_IOCTL(ops, VIDIOC_S_FBUF, vidioc_s_fbuf); diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index f1696717ab32..e995eb6e09a4 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -381,6 +381,83 @@ static void v4l_print_format(const void *arg, bool write_only) } } +static void v4l_print_ext_format(const void *arg, bool write_only) +{ + const struct v4l2_ext_format *p = arg; + const struct v4l2_ext_pix_format *pix; + const struct v4l2_vbi_format *vbi; + const struct v4l2_sliced_vbi_format *sliced; + const struct v4l2_sdr_format *sdr; + const struct v4l2_meta_format *meta; + unsigned int i; + u32 planes; + + pr_cont("type=%s", prt_names(p->type, v4l2_type_names)); + switch (p->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + pix = &p->fmt.pix; + pr_cont(", width=%u, height=%u, format=%c%c%c%c, field=%s, colorspace=%d, num_planes=%u, flags=0x%x, ycbcr_enc=%u, quantization=%u, xfer_func=%u\n", + pix->width, pix->height, + (pix->pixelformat & 0xff), + (pix->pixelformat >> 8) & 0xff, + (pix->pixelformat >> 16) & 0xff, + (pix->pixelformat >> 24) & 0xff, + prt_names(pix->field, v4l2_field_names), + pix->colorspace, pix->num_planes, pix->flags, + pix->ycbcr_enc, pix->quantization, pix->xfer_func); + planes = min_t(u32, pix->num_planes, VIDEO_MAX_PLANES); + for (i = 0; i < planes; i++) + pr_debug("plane %u: modifier %llx bytesperline=%u sizeimage=%u\n", + i, pix->plane_fmt[i].modifier, + pix->plane_fmt[i].bytesperline, + pix->plane_fmt[i].sizeimage); + break; + case V4L2_BUF_TYPE_VBI_CAPTURE: + case V4L2_BUF_TYPE_VBI_OUTPUT: + vbi = &p->fmt.vbi; + pr_cont(", sampling_rate=%u, offset=%u, samples_per_line=%u, sample_format=%c%c%c%c, start=%u,%u, count=%u,%u\n", + vbi->sampling_rate, vbi->offset, + vbi->samples_per_line, + (vbi->sample_format & 0xff), + (vbi->sample_format >> 8) & 0xff, + (vbi->sample_format >> 16) & 0xff, + (vbi->sample_format >> 24) & 0xff, + vbi->start[0], vbi->start[1], + vbi->count[0], vbi->count[1]); + break; + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + sliced = &p->fmt.sliced; + pr_cont(", service_set=0x%08x, io_size=%d\n", + sliced->service_set, sliced->io_size); + for (i = 0; i < 24; i++) + pr_debug("line[%02u]=0x%04x, 0x%04x\n", i, + sliced->service_lines[0][i], + sliced->service_lines[1][i]); + break; + case V4L2_BUF_TYPE_SDR_CAPTURE: + case V4L2_BUF_TYPE_SDR_OUTPUT: + sdr = &p->fmt.sdr; + pr_cont(", pixelformat=%c%c%c%c\n", + (sdr->pixelformat >> 0) & 0xff, + (sdr->pixelformat >> 8) & 0xff, + (sdr->pixelformat >> 16) & 0xff, + (sdr->pixelformat >> 24) & 0xff); + break; + case V4L2_BUF_TYPE_META_CAPTURE: + case V4L2_BUF_TYPE_META_OUTPUT: + meta = &p->fmt.meta; + pr_cont(", dataformat=%c%c%c%c, buffersize=%u\n", + (meta->dataformat >> 0) & 0xff, + (meta->dataformat >> 8) & 0xff, + (meta->dataformat >> 16) & 0xff, + (meta->dataformat >> 24) & 0xff, + meta->buffersize); + break; + } +} + static void v4l_print_framebuffer(const void *arg, bool write_only) { const struct v4l2_framebuffer *p = arg; @@ -951,11 +1028,15 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type) switch (type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: if ((is_vid || is_tch) && is_rx && - (ops->vidioc_g_fmt_vid_cap || ops->vidioc_g_fmt_vid_cap_mplane)) + (ops->vidioc_g_fmt_vid_cap || + ops->vidioc_g_ext_fmt_vid_cap || + ops->vidioc_g_fmt_vid_cap_mplane)) return 0; break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - if (is_vid && is_rx && ops->vidioc_g_fmt_vid_cap_mplane) + if (is_vid && is_rx && + (ops->vidioc_g_fmt_vid_cap_mplane || + ops->vidioc_g_ext_fmt_vid_cap)) return 0; break; case V4L2_BUF_TYPE_VIDEO_OVERLAY: @@ -964,11 +1045,15 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type) break; case V4L2_BUF_TYPE_VIDEO_OUTPUT: if (is_vid && is_tx && - (ops->vidioc_g_fmt_vid_out || ops->vidioc_g_fmt_vid_out_mplane)) + (ops->vidioc_g_fmt_vid_out || + ops->vidioc_g_ext_fmt_vid_out || + ops->vidioc_g_fmt_vid_out_mplane)) return 0; break; case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - if (is_vid && is_tx && ops->vidioc_g_fmt_vid_out_mplane) + if (is_vid && is_tx && + (ops->vidioc_g_ext_fmt_vid_out || + ops->vidioc_g_fmt_vid_out_mplane)) return 0; break; case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: @@ -1421,6 +1506,36 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops, return ret; } +static int v4l_g_fmt_ext_pix(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, + struct v4l2_format *f) +{ + struct v4l2_ext_format ef = { }; + int ret; + + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + ret = ops->vidioc_g_ext_fmt_vid_cap(file, fh, &ef.fmt.pix); + break; + + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + ret = ops->vidioc_g_ext_fmt_vid_out(file, fh, &ef.fmt.pix); + break; + + default: + return -EINVAL; + } + + if (ret) + return ret; + + ef.type = f->type; + return v4l2_ext_format_to_format(&ef, f, + V4L2_TYPE_IS_MULTIPLANAR(f->type)); +} + static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { @@ -1456,15 +1571,22 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, switch (p->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (unlikely(!ops->vidioc_g_fmt_vid_cap)) - break; - p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; - ret = ops->vidioc_g_fmt_vid_cap(file, fh, arg); - /* just in case the driver zeroed it again */ - p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; - return ret; + if (ops->vidioc_g_fmt_vid_cap) { + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + ret = ops->vidioc_g_fmt_vid_cap(file, fh, arg); + /* just in case the driver zeroed it again */ + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + return ret; + } else if (ops->vidioc_g_ext_fmt_vid_cap) { + return v4l_g_fmt_ext_pix(ops, file, fh, p); + } + break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - return ops->vidioc_g_fmt_vid_cap_mplane(file, fh, arg); + if (ops->vidioc_g_fmt_vid_cap_mplane) + return ops->vidioc_g_fmt_vid_cap_mplane(file, fh, arg); + else if (ops->vidioc_g_ext_fmt_vid_cap) + return v4l_g_fmt_ext_pix(ops, file, fh, p); + break; case V4L2_BUF_TYPE_VIDEO_OVERLAY: return ops->vidioc_g_fmt_vid_overlay(file, fh, arg); case V4L2_BUF_TYPE_VBI_CAPTURE: @@ -1472,15 +1594,22 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: return ops->vidioc_g_fmt_sliced_vbi_cap(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT: - if (unlikely(!ops->vidioc_g_fmt_vid_out)) - break; - p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; - ret = ops->vidioc_g_fmt_vid_out(file, fh, arg); - /* just in case the driver zeroed it again */ - p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; - return ret; + if (ops->vidioc_g_fmt_vid_out) { + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + ret = ops->vidioc_g_fmt_vid_out(file, fh, arg); + /* just in case the driver zeroed it again */ + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + return ret; + } else if (ops->vidioc_g_ext_fmt_vid_out) { + return v4l_g_fmt_ext_pix(ops, file, fh, p); + } + break; case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - return ops->vidioc_g_fmt_vid_out_mplane(file, fh, arg); + if (ops->vidioc_g_fmt_vid_out_mplane) + return ops->vidioc_g_fmt_vid_out_mplane(file, fh, arg); + else if (ops->vidioc_g_ext_fmt_vid_out) + return v4l_g_fmt_ext_pix(ops, file, fh, p); + break; case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: return ops->vidioc_g_fmt_vid_out_overlay(file, fh, arg); case V4L2_BUF_TYPE_VBI_OUTPUT: @@ -1499,6 +1628,45 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, return -EINVAL; } +static int v4l_g_ext_fmt(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_ext_format *ef = arg; + struct v4l2_format f; + int ret; + + ret = check_fmt(file, ef->type); + if (ret) + return ret; + + switch (ef->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (ops->vidioc_g_ext_fmt_vid_cap) + return ops->vidioc_g_ext_fmt_vid_cap(file, fh, + &ef->fmt.pix); + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + if (ops->vidioc_g_ext_fmt_vid_out) + return ops->vidioc_g_ext_fmt_vid_cap(file, fh, + &ef->fmt.pix); + break; + default: + break; + } + + ret = v4l2_ext_format_to_format(ef, &f, + ops->vidioc_g_fmt_vid_cap_mplane || + ops->vidioc_g_fmt_vid_out_mplane); + if (ret) + return ret; + + ret = v4l_g_fmt(ops, file, fh, &f); + if (ret) + return ret; + + return v4l2_format_to_ext_format(&f, ef); +} + static void v4l_pix_format_touch(struct v4l2_pix_format *p) { /* @@ -1514,6 +1682,39 @@ static void v4l_pix_format_touch(struct v4l2_pix_format *p) p->xfer_func = 0; } +static int v4l_s_fmt_ext_pix(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, + struct v4l2_format *f) +{ + struct v4l2_ext_format ef; + int ret; + + ret = v4l2_format_to_ext_format(f, &ef); + if (ret) + return ret; + + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + ret = ops->vidioc_s_ext_fmt_vid_cap(file, fh, &ef.fmt.pix); + break; + + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + ret = ops->vidioc_s_ext_fmt_vid_out(file, fh, &ef.fmt.pix); + break; + + default: + return -EINVAL; + } + + if (ret) + return ret; + + return v4l2_ext_format_to_format(&ef, f, + V4L2_TYPE_IS_MULTIPLANAR(f->type)); +} + static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { @@ -1532,25 +1733,33 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, switch (p->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (unlikely(!ops->vidioc_s_fmt_vid_cap)) - break; - CLEAR_AFTER_FIELD(p, fmt.pix); - ret = ops->vidioc_s_fmt_vid_cap(file, fh, arg); - /* just in case the driver zeroed it again */ - p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + if (ops->vidioc_s_fmt_vid_cap) { + CLEAR_AFTER_FIELD(p, fmt.pix); + ret = ops->vidioc_s_fmt_vid_cap(file, fh, arg); + /* just in case the driver zeroed it again */ + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + } else if (ops->vidioc_s_ext_fmt_vid_cap) { + ret = v4l_s_fmt_ext_pix(ops, file, fh, arg); + } else { + ret = -EINVAL; + } + if (vfd->vfl_type == VFL_TYPE_TOUCH) v4l_pix_format_touch(&p->fmt.pix); return ret; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - if (unlikely(!ops->vidioc_s_fmt_vid_cap_mplane)) - break; - CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); - if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES) - break; - for (i = 0; i < p->fmt.pix_mp.num_planes; i++) - CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i], - bytesperline); - return ops->vidioc_s_fmt_vid_cap_mplane(file, fh, arg); + if (ops->vidioc_s_fmt_vid_cap_mplane) { + CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); + if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES) + break; + for (i = 0; i < p->fmt.pix_mp.num_planes; i++) + CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i], + bytesperline); + return ops->vidioc_s_fmt_vid_cap_mplane(file, fh, arg); + } else if (ops->vidioc_s_ext_fmt_vid_cap) { + return v4l_s_fmt_ext_pix(ops, file, fh, arg); + } + break; case V4L2_BUF_TYPE_VIDEO_OVERLAY: if (unlikely(!ops->vidioc_s_fmt_vid_overlay)) break; @@ -1567,23 +1776,29 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, CLEAR_AFTER_FIELD(p, fmt.sliced); return ops->vidioc_s_fmt_sliced_vbi_cap(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT: - if (unlikely(!ops->vidioc_s_fmt_vid_out)) - break; - CLEAR_AFTER_FIELD(p, fmt.pix); - ret = ops->vidioc_s_fmt_vid_out(file, fh, arg); - /* just in case the driver zeroed it again */ - p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; - return ret; + if (ops->vidioc_s_fmt_vid_out) { + CLEAR_AFTER_FIELD(p, fmt.pix); + ret = ops->vidioc_s_fmt_vid_out(file, fh, arg); + /* just in case the driver zeroed it again */ + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + return ret; + } else if (ops->vidioc_s_ext_fmt_vid_out) { + return v4l_s_fmt_ext_pix(ops, file, fh, arg); + } + break; case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - if (unlikely(!ops->vidioc_s_fmt_vid_out_mplane)) - break; - CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); - if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES) - break; - for (i = 0; i < p->fmt.pix_mp.num_planes; i++) - CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i], - bytesperline); - return ops->vidioc_s_fmt_vid_out_mplane(file, fh, arg); + if (ops->vidioc_s_fmt_vid_out_mplane) { + CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); + if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES) + break; + for (i = 0; i < p->fmt.pix_mp.num_planes; i++) + CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i], + bytesperline); + return ops->vidioc_s_fmt_vid_out_mplane(file, fh, arg); + } else if (ops->vidioc_s_ext_fmt_vid_out) { + return v4l_s_fmt_ext_pix(ops, file, fh, arg); + } + break; case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: if (unlikely(!ops->vidioc_s_fmt_vid_out_overlay)) break; @@ -1623,6 +1838,78 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, return -EINVAL; } +static int v4l_s_ext_fmt(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_ext_format *ef = arg; + struct v4l2_format f; + int ret; + + ret = check_fmt(file, ef->type); + if (ret) + return ret; + + switch (ef->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (ops->vidioc_s_ext_fmt_vid_cap) + return ops->vidioc_s_ext_fmt_vid_cap(file, fh, + &ef->fmt.pix); + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + if (ops->vidioc_s_ext_fmt_vid_out) + return ops->vidioc_s_ext_fmt_vid_out(file, fh, + &ef->fmt.pix); + break; + default: + break; + } + + ret = v4l2_ext_format_to_format(ef, &f, + ops->vidioc_s_fmt_vid_cap_mplane || + ops->vidioc_s_fmt_vid_out_mplane); + if (ret) + return ret; + + ret = v4l_s_ext_fmt(ops, file, fh, &f); + if (ret) + return ret; + + return v4l2_format_to_ext_format(&f, ef); +} + +static int v4l_try_fmt_ext_pix(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, + struct v4l2_format *f) +{ + struct v4l2_ext_format ef; + int ret; + + ret = v4l2_format_to_ext_format(f, &ef); + if (ret) + return ret; + + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + ret = ops->vidioc_try_ext_fmt_vid_cap(file, fh, &ef.fmt.pix); + break; + + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + ret = ops->vidioc_try_ext_fmt_vid_out(file, fh, &ef.fmt.pix); + break; + + default: + return -EINVAL; + } + + if (ret) + return ret; + + return v4l2_ext_format_to_format(&ef, f, + V4L2_TYPE_IS_MULTIPLANAR(f->type)); +} + static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { @@ -1637,23 +1924,29 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, switch (p->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (unlikely(!ops->vidioc_try_fmt_vid_cap)) - break; - CLEAR_AFTER_FIELD(p, fmt.pix); - ret = ops->vidioc_try_fmt_vid_cap(file, fh, arg); - /* just in case the driver zeroed it again */ - p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; - return ret; + if (ops->vidioc_try_fmt_vid_cap) { + CLEAR_AFTER_FIELD(p, fmt.pix); + ret = ops->vidioc_try_fmt_vid_cap(file, fh, arg); + /* just in case the driver zeroed it again */ + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + return ret; + } else if (ops->vidioc_try_ext_fmt_vid_cap) { + return v4l_try_fmt_ext_pix(ops, file, fh, p); + } + break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - if (unlikely(!ops->vidioc_try_fmt_vid_cap_mplane)) - break; - CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); - if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES) - break; - for (i = 0; i < p->fmt.pix_mp.num_planes; i++) - CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i], - bytesperline); - return ops->vidioc_try_fmt_vid_cap_mplane(file, fh, arg); + if (ops->vidioc_try_fmt_vid_cap_mplane) { + CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); + if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES) + break; + for (i = 0; i < p->fmt.pix_mp.num_planes; i++) + CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i], + bytesperline); + return ops->vidioc_try_fmt_vid_cap_mplane(file, fh, p); + } else if (ops->vidioc_try_ext_fmt_vid_cap) { + return v4l_try_fmt_ext_pix(ops, file, fh, p); + } + break; case V4L2_BUF_TYPE_VIDEO_OVERLAY: if (unlikely(!ops->vidioc_try_fmt_vid_overlay)) break; @@ -1670,23 +1963,29 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, CLEAR_AFTER_FIELD(p, fmt.sliced); return ops->vidioc_try_fmt_sliced_vbi_cap(file, fh, arg); case V4L2_BUF_TYPE_VIDEO_OUTPUT: - if (unlikely(!ops->vidioc_try_fmt_vid_out)) - break; - CLEAR_AFTER_FIELD(p, fmt.pix); - ret = ops->vidioc_try_fmt_vid_out(file, fh, arg); - /* just in case the driver zeroed it again */ - p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; - return ret; + if (ops->vidioc_try_fmt_vid_out) { + CLEAR_AFTER_FIELD(p, fmt.pix); + ret = ops->vidioc_try_fmt_vid_out(file, fh, arg); + /* just in case the driver zeroed it again */ + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + return ret; + } else if (ops->vidioc_try_ext_fmt_vid_cap) { + return v4l_try_fmt_ext_pix(ops, file, fh, p); + } + break; case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - if (unlikely(!ops->vidioc_try_fmt_vid_out_mplane)) - break; - CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); - if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES) - break; - for (i = 0; i < p->fmt.pix_mp.num_planes; i++) - CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i], - bytesperline); - return ops->vidioc_try_fmt_vid_out_mplane(file, fh, arg); + if (ops->vidioc_try_fmt_vid_out_mplane) { + CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); + if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES) + break; + for (i = 0; i < p->fmt.pix_mp.num_planes; i++) + CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i], + bytesperline); + return ops->vidioc_try_fmt_vid_out_mplane(file, fh, p); + } else if (ops->vidioc_try_ext_fmt_vid_cap) { + return v4l_try_fmt_ext_pix(ops, file, fh, p); + } + break; case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: if (unlikely(!ops->vidioc_try_fmt_vid_out_overlay)) break; @@ -1726,6 +2025,45 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, return -EINVAL; } +static int v4l_try_ext_fmt(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_ext_format *ef = arg; + struct v4l2_format f; + int ret; + + ret = check_fmt(file, ef->type); + if (ret) + return ret; + + switch (ef->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (ops->vidioc_try_ext_fmt_vid_cap) + return ops->vidioc_try_ext_fmt_vid_cap(file, fh, + &ef->fmt.pix); + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + if (ops->vidioc_try_ext_fmt_vid_out) + return ops->vidioc_try_ext_fmt_vid_out(file, fh, + &ef->fmt.pix); + break; + default: + break; + } + + ret = v4l2_ext_format_to_format(ef, &f, + ops->vidioc_try_fmt_vid_cap_mplane || + ops->vidioc_try_fmt_vid_out_mplane); + if (ret) + return ret; + + ret = v4l_try_ext_fmt(ops, file, fh, &f); + if (ret) + return ret; + + return v4l2_format_to_ext_format(&f, ef); +} + static int v4l_streamon(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 0c511ed8ffb0..6cc88f672405 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -401,4 +401,10 @@ int v4l2_s_parm_cap(struct video_device *vdev, ((u64)(a).numerator * (b).denominator OP \ (u64)(b).numerator * (a).denominator) +int v4l2_format_to_ext_format(const struct v4l2_format *f, + struct v4l2_ext_format *e); +int v4l2_ext_format_to_format(const struct v4l2_ext_format *e, + struct v4l2_format *f, + bool mplane_cap); + #endif /* V4L2_COMMON_H_ */ diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index 400f2e46c108..5cbc3df2a396 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -48,11 +48,16 @@ struct v4l2_fh; * @vidioc_g_fmt_vid_cap: pointer to the function that implements * :ref:`VIDIOC_G_FMT ` ioctl logic for video capture * in single plane mode + * @vidioc_g_ext_fmt_vid_cap: pointer to the function that implements + * :ref:`VIDIOC_G_EXT_FMT ` ioctl logic for video + * capture * @vidioc_g_fmt_vid_overlay: pointer to the function that implements * :ref:`VIDIOC_G_FMT ` ioctl logic for video overlay * @vidioc_g_fmt_vid_out: pointer to the function that implements * :ref:`VIDIOC_G_FMT ` ioctl logic for video out * in single plane mode + * @vidioc_g_ext_fmt_vid_out: pointer to the function that implements + * :ref:`VIDIOC_G_EXT_FMT ` ioctl logic for video out * @vidioc_g_fmt_vid_out_overlay: pointer to the function that implements * :ref:`VIDIOC_G_FMT ` ioctl logic for video overlay output * @vidioc_g_fmt_vbi_cap: pointer to the function that implements @@ -82,11 +87,16 @@ struct v4l2_fh; * @vidioc_s_fmt_vid_cap: pointer to the function that implements * :ref:`VIDIOC_S_FMT ` ioctl logic for video capture * in single plane mode + * @vidioc_s_ext_fmt_vid_cap: pointer to the function that implements + * :ref:`VIDIOC_S_EXT_FMT ` ioctl logic for video + * capture * @vidioc_s_fmt_vid_overlay: pointer to the function that implements * :ref:`VIDIOC_S_FMT ` ioctl logic for video overlay * @vidioc_s_fmt_vid_out: pointer to the function that implements * :ref:`VIDIOC_S_FMT ` ioctl logic for video out * in single plane mode + * @vidioc_s_ext_fmt_vid_out: pointer to the function that implements + * :ref:`VIDIOC_S_EXT_FMT ` ioctl logic for video out * @vidioc_s_fmt_vid_out_overlay: pointer to the function that implements * :ref:`VIDIOC_S_FMT ` ioctl logic for video overlay output * @vidioc_s_fmt_vbi_cap: pointer to the function that implements @@ -116,11 +126,16 @@ struct v4l2_fh; * @vidioc_try_fmt_vid_cap: pointer to the function that implements * :ref:`VIDIOC_TRY_FMT ` ioctl logic for video capture * in single plane mode + * @vidioc_try_ext_fmt_vid_cap: pointer to the function that implements + * :ref:`VIDIOC_TRY_EXT_FMT ` ioctl logic for video + capture * @vidioc_try_fmt_vid_overlay: pointer to the function that implements * :ref:`VIDIOC_TRY_FMT ` ioctl logic for video overlay * @vidioc_try_fmt_vid_out: pointer to the function that implements * :ref:`VIDIOC_TRY_FMT ` ioctl logic for video out * in single plane mode + * @vidioc_try_ext_fmt_vid_out: pointer to the function that implements + * :ref:`VIDIOC_TRY_EXT_FMT ` ioctl logic for video out * @vidioc_try_fmt_vid_out_overlay: pointer to the function that implements * :ref:`VIDIOC_TRY_FMT ` ioctl logic for video overlay * output @@ -319,10 +334,14 @@ struct v4l2_ioctl_ops { /* VIDIOC_G_FMT handlers */ int (*vidioc_g_fmt_vid_cap)(struct file *file, void *fh, struct v4l2_format *f); + int (*vidioc_g_ext_fmt_vid_cap)(struct file *file, void *fh, + struct v4l2_ext_pix_format *f); int (*vidioc_g_fmt_vid_overlay)(struct file *file, void *fh, struct v4l2_format *f); int (*vidioc_g_fmt_vid_out)(struct file *file, void *fh, struct v4l2_format *f); + int (*vidioc_g_ext_fmt_vid_out)(struct file *file, void *fh, + struct v4l2_ext_pix_format *f); int (*vidioc_g_fmt_vid_out_overlay)(struct file *file, void *fh, struct v4l2_format *f); int (*vidioc_g_fmt_vbi_cap)(struct file *file, void *fh, @@ -349,10 +368,14 @@ struct v4l2_ioctl_ops { /* VIDIOC_S_FMT handlers */ int (*vidioc_s_fmt_vid_cap)(struct file *file, void *fh, struct v4l2_format *f); + int (*vidioc_s_ext_fmt_vid_cap)(struct file *file, void *fh, + struct v4l2_ext_pix_format *f); int (*vidioc_s_fmt_vid_overlay)(struct file *file, void *fh, struct v4l2_format *f); int (*vidioc_s_fmt_vid_out)(struct file *file, void *fh, struct v4l2_format *f); + int (*vidioc_s_ext_fmt_vid_out)(struct file *file, void *fh, + struct v4l2_ext_pix_format *f); int (*vidioc_s_fmt_vid_out_overlay)(struct file *file, void *fh, struct v4l2_format *f); int (*vidioc_s_fmt_vbi_cap)(struct file *file, void *fh, @@ -379,10 +402,14 @@ struct v4l2_ioctl_ops { /* VIDIOC_TRY_FMT handlers */ int (*vidioc_try_fmt_vid_cap)(struct file *file, void *fh, struct v4l2_format *f); + int (*vidioc_try_ext_fmt_vid_cap)(struct file *file, void *fh, + struct v4l2_ext_pix_format *f); int (*vidioc_try_fmt_vid_overlay)(struct file *file, void *fh, struct v4l2_format *f); int (*vidioc_try_fmt_vid_out)(struct file *file, void *fh, struct v4l2_format *f); + int (*vidioc_try_ext_fmt_vid_out)(struct file *file, void *fh, + struct v4l2_ext_pix_format *f); int (*vidioc_try_fmt_vid_out_overlay)(struct file *file, void *fh, struct v4l2_format *f); int (*vidioc_try_fmt_vbi_cap)(struct file *file, void *fh, diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index b5671ce2724f..3dbeb83176bf 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -2147,6 +2147,56 @@ struct v4l2_pix_format_mplane { __u8 reserved[7]; } __attribute__ ((packed)); +/** + * struct v4l2_plane_ext_pix_format - additional, per-plane format definition + * @modifier: modifier applied to the format (used for tiled formats + * and other kind of HW-specific formats, like compressed + * formats) + * @sizeimage: maximum size in bytes required for data, for which + * this plane will be used + * @bytesperline: distance in bytes between the leftmost pixels in two + * adjacent lines + */ +struct v4l2_plane_ext_pix_format { + __u64 modifier; + __u32 sizeimage; + __u32 bytesperline; +}; + +/** + * struct v4l2_ext_pix_format - extended single/multiplanar format definition + * @width: image width in pixels + * @height: image height in pixels + * @pixelformat: little endian four character code (fourcc) + * @field: enum v4l2_field; field order (for interlaced video) + * @colorspace: enum v4l2_colorspace; supplemental to pixelformat + * @num_planes: number of planes for this format. Should be equal to 1 + * for single-planar formats and greater than 1 for + * multiplanar ones + * @plane_fmt: per-plane information + * @flags: format flags (V4L2_PIX_FMT_FLAG_*) + * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding + * @hsv_enc: enum v4l2_hsv_encoding, HSV encoding + * @quantization: enum v4l2_quantization, colorspace quantization + * @xfer_func: enum v4l2_xfer_func, colorspace transfer function + */ +struct v4l2_ext_pix_format { + __u32 width; + __u32 height; + __u32 pixelformat; + __u32 field; + __u32 colorspace; + __u32 num_planes; + struct v4l2_plane_ext_pix_format plane_fmt[VIDEO_MAX_PLANES]; + __u8 flags; + union { + __u8 ycbcr_enc; + __u8 hsv_enc; + }; + __u8 quantization; + __u8 xfer_func; +}; + /** * struct v4l2_sdr_format - SDR format definition * @pixelformat: little endian four character code (fourcc) @@ -2192,6 +2242,35 @@ struct v4l2_format { } fmt; }; +/** + * struct v4l2_ext_format - extended stream data format + * @type: enum v4l2_buf_type; type of the data stream. + * V4L2_BUF_TYPE_VIDEO[_OUTPUT]_OVERLAY and + * V4L2_BUF_TYPE_VIDEO_{CAPTURE,OUTPUT}_MPLANE are not supported + * @pix: definition of an image format. Used for + * V4L2_BUF_TYPE_VIDEO_{CAPTURE,OUTPUT} types + * @vbi: raw VBI capture or output parameters. Used for + * V4L2_BUF_TYPE_VBI_{CAPTURE,OUTPUT} types + * @sliced: sliced VBI capture or output parameters. Used for + * V4L2_BUF_TYPE_SLICED_VBI_{CAPTURE,OUTPUT} types. + * @sdr: SDR capture or output parameters. Used for + * V4L2_BUF_TYPE_SDR_{CAPTURE,OUTPUT} types + * @meta: meta capture or output parameters. Used for + * V4L2_BUF_TYPE_META_{CAPTURE,OUTPUT} types + * @raw_data: placeholder for future extensions and custom formats + */ +struct v4l2_ext_format { + __u32 type; + union { + struct v4l2_ext_pix_format pix; + struct v4l2_vbi_format vbi; + struct v4l2_sliced_vbi_format sliced; + struct v4l2_sdr_format sdr; + struct v4l2_meta_format meta; + __u8 raw_data[200]; + } fmt; +}; + /* Stream type-dependent parameters */ struct v4l2_streamparm { @@ -2456,6 +2535,9 @@ struct v4l2_create_buffers { #define VIDIOC_QUERY_EXT_CTRL _IOWR('V', 103, struct v4l2_query_ext_ctrl) +#define VIDIOC_G_EXT_FMT _IOWR('V', 104, struct v4l2_ext_format) +#define VIDIOC_S_EXT_FMT _IOWR('V', 105, struct v4l2_ext_format) +#define VIDIOC_TRY_EXT_FMT _IOWR('V', 106, struct v4l2_ext_format) /* Reminder: when adding new ioctls please add support for them to drivers/media/v4l2-core/v4l2-compat-ioctl32.c as well! */ From patchwork Tue Mar 19 14:52:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 10859745 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D6FDD13B5 for ; Tue, 19 Mar 2019 14:52:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B5567286F7 for ; Tue, 19 Mar 2019 14:52:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B2EC729711; Tue, 19 Mar 2019 14:52:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AE998286F7 for ; Tue, 19 Mar 2019 14:52:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727756AbfCSOwx (ORCPT ); Tue, 19 Mar 2019 10:52:53 -0400 Received: from bhuna.collabora.co.uk ([46.235.227.227]:37500 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726466AbfCSOwx (ORCPT ); Tue, 19 Mar 2019 10:52:53 -0400 Received: from localhost.localdomain (unknown [IPv6:2a01:e0a:2c:6930:5cf4:84a1:2763:fe0d]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: bbrezillon) by bhuna.collabora.co.uk (Postfix) with ESMTPSA id 42F8228139C; Tue, 19 Mar 2019 14:52:50 +0000 (GMT) From: Boris Brezillon To: Mauro Carvalho Chehab , Hans Verkuil , Laurent Pinchart , Sakari Ailus , linux-media@vger.kernel.org Cc: Tomasz Figa , Hirokazu Honda , Nicolas Dufresne , Boris Brezillon Subject: [RFC PATCH 3/3] media: v4l2: Add extended buffer operations Date: Tue, 19 Mar 2019 15:52:43 +0100 Message-Id: <20190319145243.25047-4-boris.brezillon@collabora.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190319145243.25047-1-boris.brezillon@collabora.com> References: <20190319145243.25047-1-boris.brezillon@collabora.com> MIME-Version: 1.0 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Hans Verkuil Those extended buffer ops have several purpose: 1/ Fix y2038 issues by converting the timestamp into an u64 counting the number of ns elapsed since 1970 2/ Unify single/multiplanar handling 3/ Add a new start offset field to each v4l2 plane buffer info struct to support the case where a single buffer object is storing all planes data, each one being placed at a different offset New hooks are created in v4l2_ioctl_ops so that drivers can start using these new objects. The core takes care of converting new ioctls requests to old ones if the driver does not support the new hooks, and vice versa. Signed-off-by: Hans Verkuil Signed-off-by: Boris Brezillon --- Hans, I kept initial autorship as this patch is heavily based on your initial proposal [1]. Please let me know if you want me to change it. Regards, Boris [1]https://git.linuxtv.org/hverkuil/media_tree.git/commit/?h=v4l2-buffer&id=a95549df06d9900f3559afdbb9da06bd4b22d1f3 --- drivers/media/v4l2-core/v4l2-common.c | 92 ++++++++ drivers/media/v4l2-core/v4l2-dev.c | 6 + drivers/media/v4l2-core/v4l2-ioctl.c | 315 ++++++++++++++++++++++++-- include/media/v4l2-common.h | 6 + include/media/v4l2-ioctl.h | 24 ++ include/uapi/linux/videodev2.h | 125 ++++++++++ 6 files changed, 547 insertions(+), 21 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c index fb6ba89564d1..2c9c539158c3 100644 --- a/drivers/media/v4l2-core/v4l2-common.c +++ b/drivers/media/v4l2-core/v4l2-common.c @@ -644,3 +644,95 @@ int v4l2_format_to_ext_format(const struct v4l2_format *f, return 0; } EXPORT_SYMBOL_GPL(v4l2_format_to_ext_format); + +int v4l2_ext_buffer_to_buffer(const struct v4l2_ext_buffer *e, + struct v4l2_buffer *b, bool mplane_cap) +{ + u64 nsecs; + + if (!mplane_cap && e->num_planes > 1) + return -EINVAL; + + memset(b, 0, sizeof(*b)); + + b->index = e->index; + b->flags = e->flags; + b->field = e->field; + b->sequence = e->sequence; + b->memory = e->memory; + b->request_fd = e->request_fd; + b->timestamp.tv_sec = div64_u64_rem(e->timestamp, NSEC_PER_SEC, &nsecs); + b->timestamp.tv_usec = (u32)nsecs / NSEC_PER_USEC; + if (mplane_cap) { + unsigned int i; + + if (e->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + b->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + else + b->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + + b->length = e->num_planes; + for (i = 0; i < e->num_planes; i++) { + b->m.planes[i].length = e->planes[i].length; + b->m.planes[i].bytesused = e->planes[i].bytesused; + b->m.planes[i].m.userptr = e->planes[i].m.userptr; + b->m.planes[i].data_offset = e->planes[i].data_offset; + memset(b->m.planes[i].reserved, 0, + sizeof(b->m.planes[i].reserved)); + } + } else { + b->type = e->type; + b->bytesused = e->planes[0].bytesused; + b->length = e->planes[0].length; + b->m.userptr = e->planes[0].m.userptr; + } + + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_ext_buffer_to_buffer); + +int v4l2_buffer_to_ext_buffer(const struct v4l2_buffer *b, + struct v4l2_ext_buffer *e) +{ + memset(e, 0, sizeof(*e)); + + e->index = b->index; + e->flags = b->flags; + e->field = b->field; + e->sequence = b->sequence; + e->memory = b->memory; + e->request_fd = b->request_fd; + e->timestamp = b->timestamp.tv_sec * NSEC_PER_SEC + + b->timestamp.tv_usec * NSEC_PER_USEC; + if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { + unsigned int i; + + if (!b->m.planes) + return -EINVAL; + + if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) + e->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + else + e->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + + e->num_planes = b->length; + for (i = 0; i < e->num_planes; i++) { + e->planes[i].length = b->m.planes[i].length; + e->planes[i].bytesused = b->m.planes[i].bytesused; + e->planes[i].m.userptr = b->m.planes[i].m.userptr; + e->planes[i].data_offset = b->m.planes[i].data_offset; + memset(e->planes[i].reserved, 0, + sizeof(e->planes[i].reserved)); + } + } else { + e->type = b->type; + e->num_planes = 1; + e->planes[0].bytesused = b->bytesused; + e->planes[0].length = b->length; + e->planes[0].m.userptr = b->m.userptr; + e->planes[0].data_offset = 0; + } + + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_buffer_to_ext_buffer); diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index a233e0924ed3..ecff3de494ff 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -701,10 +701,16 @@ static void determine_valid_ioctls(struct video_device *vdev) /* ioctls valid for video, metadata, vbi or sdr */ SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs); SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf); + SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_ext_querybuf); SET_VALID_IOCTL(ops, VIDIOC_QBUF, vidioc_qbuf); + SET_VALID_IOCTL(ops, VIDIOC_EXT_QBUF, vidioc_ext_qbuf); SET_VALID_IOCTL(ops, VIDIOC_EXPBUF, vidioc_expbuf); + SET_VALID_IOCTL(ops, VIDIOC_EXPBUF, vidioc_ext_expbuf); SET_VALID_IOCTL(ops, VIDIOC_DQBUF, vidioc_dqbuf); + SET_VALID_IOCTL(ops, VIDIOC_EXT_DQBUF, vidioc_ext_dqbuf); SET_VALID_IOCTL(ops, VIDIOC_CREATE_BUFS, vidioc_create_bufs); + SET_VALID_IOCTL(ops, VIDIOC_EXT_CREATE_BUFS, + vidioc_ext_create_bufs); SET_VALID_IOCTL(ops, VIDIOC_PREPARE_BUF, vidioc_prepare_buf); SET_VALID_IOCTL(ops, VIDIOC_STREAMON, vidioc_streamon); SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff); diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index e995eb6e09a4..31eb7c0a01a2 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -584,6 +584,26 @@ static void v4l_print_buffer(const void *arg, bool write_only) tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits); } +static void v4l_print_ext_buffer(const void *arg, bool write_only) +{ + const struct v4l2_ext_buffer *p = arg; + const struct v4l2_ext_plane *plane; + int i; + + pr_cont("%lld index=%d, type=%s, flags=0x%08x, field=%s, sequence=%d, memory=%s\n", + p->timestamp, p->index, prt_names(p->type, v4l2_type_names), + p->flags, prt_names(p->field, v4l2_field_names), + p->sequence, prt_names(p->memory, v4l2_memory_names)); + + for (i = 0; i < p->num_planes; ++i) { + plane = &p->planes[i]; + pr_debug("plane %d: bytesused=%d, start_offset=0x%08x, data_offset=0x%08x, offset/userptr=0x%llx, length=%d\n", + i, plane->bytesused, plane->start_offset, + plane->data_offset, plane->m.userptr, + plane->length); + } +} + static void v4l_print_exportbuffer(const void *arg, bool write_only) { const struct v4l2_exportbuffer *p = arg; @@ -593,6 +613,18 @@ static void v4l_print_exportbuffer(const void *arg, bool write_only) p->index, p->plane, p->flags); } +static void v4l_print_ext_exportbuffer(const void *arg, bool write_only) +{ + const struct v4l2_ext_exportbuffer *p = arg; + unsigned int i; + + pr_cont("type=%s, index=%u, first_plane=%u num_planes=%u, flags=%08x\n", + prt_names(p->type, v4l2_type_names), p->index, p->first_plane, + p->num_planes, p->flags); + for (i = p->first_plane; i < p->first_plane + p->num_planes; ++i) + pr_debug("plane %u: fd=%d\n", i, p->fds[i]); +} + static void v4l_print_create_buffers(const void *arg, bool write_only) { const struct v4l2_create_buffers *p = arg; @@ -603,6 +635,15 @@ static void v4l_print_create_buffers(const void *arg, bool write_only) v4l_print_format(&p->format, write_only); } +static void v4l_print_ext_create_buffers(const void *arg, bool write_only) +{ + const struct v4l2_ext_create_buffers *p = arg; + + pr_cont("index=%d, count=%d, memory=%s, ", p->index, p->count, + prt_names(p->memory, v4l2_memory_names)); + v4l_print_ext_format(&p->format, write_only); +} + static void v4l_print_streamparm(const void *arg, bool write_only) { const struct v4l2_streamparm *p = arg; @@ -2262,31 +2303,109 @@ static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops, return ops->vidioc_reqbufs(file, fh, p); } -static int v4l_querybuf(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_do_buf_op(int (*op)(struct file *, void *, + struct v4l2_buffer *), + int (*ext_op)(struct file *, void *, + struct v4l2_ext_buffer *), + struct file *file, void *fh, struct v4l2_buffer *b) { - struct v4l2_buffer *p = arg; - int ret = check_fmt(file, p->type); + struct v4l2_ext_buffer eb; + int ret; - return ret ? ret : ops->vidioc_querybuf(file, fh, p); + ret = check_fmt(file, b->type); + if (ret) + return ret; + + if (op) + return op(file, fh, b); + + ret = v4l2_buffer_to_ext_buffer(b, &eb); + if (ret) + return ret; + + ret = ext_op(file, fh, &eb); + if (ret) + return ret; + + v4l2_ext_buffer_to_buffer(&eb, b, V4L2_TYPE_IS_MULTIPLANAR(b->type)); + return 0; +} + +static int v4l_do_ext_buf_op(int (*op)(struct file *, void *, + struct v4l2_buffer *), + int (*ext_op)(struct file *, void *, + struct v4l2_ext_buffer *), + struct file *file, void *fh, + struct v4l2_ext_buffer *eb) +{ + struct video_device *vdev = video_devdata(file); + struct v4l2_buffer b; + bool mplane_cap; + int ret; + + ret = check_fmt(file, eb->type); + if (ret) + return ret; + + if (ext_op) + return ext_op(file, fh, eb); + + mplane_cap = !!(vdev->device_caps & + (V4L2_CAP_VIDEO_CAPTURE_MPLANE | + V4L2_CAP_VIDEO_OUTPUT_MPLANE | + V4L2_CAP_VIDEO_M2M_MPLANE)); + ret = v4l2_ext_buffer_to_buffer(eb, &b, mplane_cap); + if (ret) + return ret; + + ret = op(file, fh, &b); + if (ret) + return ret; + + v4l2_buffer_to_ext_buffer(&b, eb); + return 0; +} + +static int v4l_querybuf(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + return v4l_do_buf_op(ops->vidioc_querybuf, ops->vidioc_ext_querybuf, + file, fh, arg); +} + +static int v4l_ext_querybuf(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + return v4l_do_ext_buf_op(ops->vidioc_querybuf, + ops->vidioc_ext_querybuf, file, fh, arg); } static int v4l_qbuf(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *fh, void *arg) { - struct v4l2_buffer *p = arg; - int ret = check_fmt(file, p->type); + return v4l_do_buf_op(ops->vidioc_qbuf, ops->vidioc_ext_qbuf, + file, fh, arg); +} - return ret ? ret : ops->vidioc_qbuf(file, fh, p); +static int v4l_ext_qbuf(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + return v4l_do_ext_buf_op(ops->vidioc_qbuf, ops->vidioc_ext_qbuf, + file, fh, arg); } static int v4l_dqbuf(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) + struct file *file, void *fh, void *arg) { - struct v4l2_buffer *p = arg; - int ret = check_fmt(file, p->type); + return v4l_do_buf_op(ops->vidioc_dqbuf, ops->vidioc_ext_dqbuf, + file, fh, arg); +} - return ret ? ret : ops->vidioc_dqbuf(file, fh, p); +static int v4l_ext_dqbuf(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + return v4l_do_ext_buf_op(ops->vidioc_dqbuf, ops->vidioc_ext_dqbuf, + file, fh, arg); } static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops, @@ -2302,7 +2421,27 @@ static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops, v4l_sanitize_format(&create->format); - ret = ops->vidioc_create_bufs(file, fh, create); + if (ops->vidioc_create_bufs) { + ret = ops->vidioc_create_bufs(file, fh, create); + } else { + struct v4l2_ext_create_buffers ecreate = { + .count = create->count, + .memory = create->memory, + }; + + ret = v4l2_format_to_ext_format(&create->format, + &ecreate.format); + if (ret) + return ret; + + ret = ops->vidioc_ext_create_bufs(file, fh, &ecreate); + if (ret) + return ret; + + create->index = ecreate.index; + create->count = ecreate.count; + create->capabilities = ecreate.capabilities; + } if (create->format.type == V4L2_BUF_TYPE_VIDEO_CAPTURE || create->format.type == V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -2311,13 +2450,59 @@ static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops, return ret; } -static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) +static int v4l_ext_create_bufs(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) { - struct v4l2_buffer *b = arg; - int ret = check_fmt(file, b->type); + struct v4l2_ext_create_buffers *ecreate = arg; + struct video_device *vdev = video_devdata(file); + struct v4l2_create_buffers create = { + .count = ecreate->count, + .memory = ecreate->memory, + }; + bool mplane_cap; + int ret; - return ret ? ret : ops->vidioc_prepare_buf(file, fh, b); + ret = check_fmt(file, ecreate->format.type); + if (ret) + return ret; + + if (ops->vidioc_ext_create_bufs) + return ops->vidioc_ext_create_bufs(file, fh, ecreate); + + mplane_cap = !!(vdev->device_caps & + (V4L2_CAP_VIDEO_CAPTURE_MPLANE | + V4L2_CAP_VIDEO_OUTPUT_MPLANE | + V4L2_CAP_VIDEO_M2M_MPLANE)); + ret = v4l2_ext_format_to_format(&ecreate->format, + &create.format, mplane_cap); + if (ret) + return ret; + + ret = v4l_create_bufs(ops, file, fh, &create); + if (ret) + return ret; + + ecreate->index = create.index; + ecreate->count = create.count; + ecreate->capabilities = create.capabilities; + + return 0; +} + +static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + return v4l_do_buf_op(ops->vidioc_prepare_buf, + ops->vidioc_ext_prepare_buf, + file, fh, arg); +} + +static int v4l_ext_prepare_buf(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + return v4l_do_ext_buf_op(ops->vidioc_prepare_buf, + ops->vidioc_ext_prepare_buf, + file, fh, arg); } static int v4l_g_parm(const struct v4l2_ioctl_ops *ops, @@ -2909,6 +3094,86 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops, return -ENOTTY; } +static int v4l_expbuf(const struct v4l2_ioctl_ops *ops, struct file *file, + void *fh, void *arg) +{ + struct v4l2_exportbuffer *b = arg; + struct v4l2_ext_exportbuffer eb = { + .type = b->type, + .index = b->index, + .first_plane = b->plane, + .num_planes = 1, + .flags = b->flags, + }; + int ret; + + if (ops->vidioc_expbuf) + return ops->vidioc_expbuf(file, fh, b); + + if (b->plane >= VIDEO_MAX_PLANES) + return -EINVAL; + + ret = ops->vidioc_ext_expbuf(file, fh, &eb); + if (ret) + return ret; + + b->fd = eb.fds[b->plane]; + return 0; +} + +static int v4l_ext_expbuf(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_ext_exportbuffer *eb = arg; + unsigned int i; + int ret; + + if (eb->first_plane >= VIDEO_MAX_PLANES || + eb->num_planes > VIDEO_MAX_PLANES || + eb->first_plane + eb->num_planes > VIDEO_MAX_PLANES) + return -EINVAL; + + if (ops->vidioc_ext_expbuf) + return ops->vidioc_ext_expbuf(file, fh, eb); + + for (i = eb->first_plane; i < eb->first_plane + eb->num_planes; i++) { + struct v4l2_exportbuffer b = { + .type = eb->type, + .index = eb->index, + .plane = i, + .flags = eb->flags, + }; + + ret = ops->vidioc_expbuf(file, fh, &b); + if (ret) + goto err_put_dmabufs; + + eb->fds[i] = b.fd; + } + + return 0; + +err_put_dmabufs: + for (i = eb->first_plane; i < eb->first_plane + eb->num_planes; i++) { + struct dma_buf *dmabuf; + + if (eb->fds[i] <= 0) + break; + + /* + * We must call dma_buf_put() twice because we got one + * reference taken at dmabuf creation time one taken when + * calling dma_buf_get(). + * FIXME: not entirely sure this works correctly. + */ + dmabuf = dma_buf_get(eb->fds[i]); + dma_buf_put(dmabuf); + dma_buf_put(dmabuf); + } + + return ret; +} + struct v4l2_ioctl_info { unsigned int ioctl; u32 flags; @@ -2951,7 +3216,6 @@ struct v4l2_ioctl_info { DEFINE_V4L_STUB_FUNC(g_fbuf) DEFINE_V4L_STUB_FUNC(s_fbuf) -DEFINE_V4L_STUB_FUNC(expbuf) DEFINE_V4L_STUB_FUNC(g_std) DEFINE_V4L_STUB_FUNC(g_audio) DEFINE_V4L_STUB_FUNC(s_audio) @@ -2989,7 +3253,7 @@ static const struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO(VIDIOC_S_FBUF, v4l_stub_s_fbuf, v4l_print_framebuffer, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_OVERLAY, v4l_overlay, v4l_print_u32, INFO_FL_PRIO), IOCTL_INFO(VIDIOC_QBUF, v4l_qbuf, v4l_print_buffer, INFO_FL_QUEUE), - IOCTL_INFO(VIDIOC_EXPBUF, v4l_stub_expbuf, v4l_print_exportbuffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_exportbuffer, flags)), + IOCTL_INFO(VIDIOC_EXPBUF, v4l_expbuf, v4l_print_exportbuffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_exportbuffer, flags)), IOCTL_INFO(VIDIOC_DQBUF, v4l_dqbuf, v4l_print_buffer, INFO_FL_QUEUE), IOCTL_INFO(VIDIOC_STREAMON, v4l_streamon, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE), IOCTL_INFO(VIDIOC_STREAMOFF, v4l_streamoff, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE), @@ -3061,6 +3325,15 @@ static const struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0), IOCTL_INFO(VIDIOC_DBG_G_CHIP_INFO, v4l_dbg_g_chip_info, v4l_print_dbg_chip_info, INFO_FL_CLEAR(v4l2_dbg_chip_info, match)), IOCTL_INFO(VIDIOC_QUERY_EXT_CTRL, v4l_query_ext_ctrl, v4l_print_query_ext_ctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_query_ext_ctrl, id)), + IOCTL_INFO(VIDIOC_G_EXT_FMT, v4l_g_ext_fmt, v4l_print_ext_format, 0), + IOCTL_INFO(VIDIOC_S_EXT_FMT, v4l_s_ext_fmt, v4l_print_ext_format, INFO_FL_PRIO), + IOCTL_INFO(VIDIOC_TRY_EXT_FMT, v4l_try_ext_fmt, v4l_print_ext_format, 0), + IOCTL_INFO(VIDIOC_EXT_CREATE_BUFS, v4l_ext_create_bufs, v4l_print_ext_create_buffers, INFO_FL_PRIO | INFO_FL_QUEUE), + IOCTL_INFO(VIDIOC_EXT_QUERYBUF, v4l_ext_querybuf, v4l_print_ext_buffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_buffer, length)), + IOCTL_INFO(VIDIOC_EXT_QBUF, v4l_ext_qbuf, v4l_print_ext_buffer, INFO_FL_QUEUE), + IOCTL_INFO(VIDIOC_EXT_DQBUF, v4l_ext_dqbuf, v4l_print_ext_buffer, INFO_FL_QUEUE), + IOCTL_INFO(VIDIOC_EXT_PREPARE_BUF, v4l_ext_prepare_buf, v4l_print_ext_buffer, INFO_FL_QUEUE), + IOCTL_INFO(VIDIOC_EXT_EXPBUF, v4l_ext_expbuf, v4l_print_ext_exportbuffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_exportbuffer, flags)), }; #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 6cc88f672405..f8371bb7b3e2 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -407,4 +407,10 @@ int v4l2_ext_format_to_format(const struct v4l2_ext_format *e, struct v4l2_format *f, bool mplane_cap); +int v4l2_ext_buffer_to_buffer(const struct v4l2_ext_buffer *e, + struct v4l2_buffer *b, + bool mplane_cap); +int v4l2_buffer_to_ext_buffer(const struct v4l2_buffer *b, + struct v4l2_ext_buffer *e); + #endif /* V4L2_COMMON_H_ */ diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index 5cbc3df2a396..1f3c66220946 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -168,16 +168,28 @@ struct v4l2_fh; * :ref:`VIDIOC_REQBUFS ` ioctl * @vidioc_querybuf: pointer to the function that implements * :ref:`VIDIOC_QUERYBUF ` ioctl + * @vidioc_ext_querybuf: pointer to the function that implements + * :ref:`VIDIOC_EXT_QUERYBUF ` ioctl * @vidioc_qbuf: pointer to the function that implements * :ref:`VIDIOC_QBUF ` ioctl + * @vidioc_ext_qbuf: pointer to the function that implements + * :ref:`VIDIOC_EXT_QBUF ` ioctl * @vidioc_expbuf: pointer to the function that implements * :ref:`VIDIOC_EXPBUF ` ioctl + * @vidioc_ext_expbuf: pointer to the function that implements + * :ref:`VIDIOC_EXT_EXPBUF ` ioctl * @vidioc_dqbuf: pointer to the function that implements * :ref:`VIDIOC_DQBUF ` ioctl + * @vidioc_ext_dqbuf: pointer to the function that implements + * :ref:`VIDIOC_EXT_DQBUF ` ioctl * @vidioc_create_bufs: pointer to the function that implements * :ref:`VIDIOC_CREATE_BUFS ` ioctl + * @vidioc_ext_create_bufs: pointer to the function that implements + * :ref:`VIDIOC_EXT_CREATE_BUFS ` ioctl * @vidioc_prepare_buf: pointer to the function that implements * :ref:`VIDIOC_PREPARE_BUF ` ioctl + * @vidioc_ext_prepare_buf: pointer to the function that implements + * :ref:`VIDIOC_EXT_PREPARE_BUF ` ioctl * @vidioc_overlay: pointer to the function that implements * :ref:`VIDIOC_OVERLAY ` ioctl * @vidioc_g_fbuf: pointer to the function that implements @@ -438,17 +450,29 @@ struct v4l2_ioctl_ops { struct v4l2_requestbuffers *b); int (*vidioc_querybuf)(struct file *file, void *fh, struct v4l2_buffer *b); + int (*vidioc_ext_querybuf)(struct file *file, void *fh, + struct v4l2_ext_buffer *b); int (*vidioc_qbuf)(struct file *file, void *fh, struct v4l2_buffer *b); + int (*vidioc_ext_qbuf)(struct file *file, void *fh, + struct v4l2_ext_buffer *b); int (*vidioc_expbuf)(struct file *file, void *fh, struct v4l2_exportbuffer *e); + int (*vidioc_ext_expbuf)(struct file *file, void *fh, + struct v4l2_ext_exportbuffer *e); int (*vidioc_dqbuf)(struct file *file, void *fh, struct v4l2_buffer *b); + int (*vidioc_ext_dqbuf)(struct file *file, void *fh, + struct v4l2_ext_buffer *b); int (*vidioc_create_bufs)(struct file *file, void *fh, struct v4l2_create_buffers *b); + int (*vidioc_ext_create_bufs)(struct file *file, void *fh, + struct v4l2_ext_create_buffers *b); int (*vidioc_prepare_buf)(struct file *file, void *fh, struct v4l2_buffer *b); + int (*vidioc_ext_prepare_buf)(struct file *file, void *fh, + struct v4l2_ext_buffer *b); int (*vidioc_overlay)(struct file *file, void *fh, unsigned int i); int (*vidioc_g_fbuf)(struct file *file, void *fh, diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 3dbeb83176bf..290b7f430927 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -916,6 +916,47 @@ struct v4l2_plane { __u32 reserved[11]; }; +/** + * struct v4l2_ext_plane - extended plane buffer info + * @bytesused: number of bytes occupied by data in the plane (payload) + * @length: size of this plane (NOT the payload) in bytes + * @mem_offset: when memory in the associated struct v4l2_ext_buffer is + * V4L2_MEMORY_MMAP, equals the offset from the start of the + * device memory for this plane (or is a "cookie" that should be + * passed to mmap() called on the video node) + * @userptr: when memory is V4L2_MEMORY_USERPTR, a userspace pointer pointing + * to this plane + * @fd: when memory is V4L2_MEMORY_DMABUF, a userspace file descriptor + * associated with this plane + * @start_offset: where the plane starts inside a buffer. All planes might + * share the same buffer object. In this case we need to know + * where the plane start inside this buffer. + * @data_offset: offset in the plane to the start of data; usually 0, unless + * there is a header in front of the data. data_offset is + * relative to start_offset, so absolute data_offset is actually + * start_offset + data_offset + * + * + * Multi-planar buffers consist of one or more planes, e.g. an YCbCr buffer + * with two planes can have one plane for Y, and another for interleaved CbCr + * components. Each plane can reside in a separate memory buffer, or even in + * a completely separate memory node (e.g. in embedded devices). + * Note that this struct is also used for uni-planar buffers, but in that case + * you'll only have one plane defined. + */ +struct v4l2_ext_plane { + __u32 bytesused; + __u32 length; + union { + __u32 mem_offset; + __u64 userptr; + __s32 fd; + } m; + __u32 start_offset; + __u32 data_offset; + __u32 reserved[10]; +}; + /** * struct v4l2_buffer - video buffer info * @index: id number of the buffer @@ -973,6 +1014,37 @@ struct v4l2_buffer { }; }; +/** + * struct v4l2_ext_buffer - extended video buffer info + * @index: id number of the buffer + * @type: enum v4l2_buf_type; buffer type. _MPLANE and _OVERLAY formats are + * invalid + * @flags: buffer informational flags + * @field: enum v4l2_field; field order of the image in the buffer + * @timestamp: frame timestamp + * @sequence: sequence count of this frame + * @memory: enum v4l2_memory; the method, in which the actual video data is + * passed + * @planes: per-plane buffer information + * @num_planes: number of plane buffers + * + * Contains data exchanged by application and driver using one of the Streaming + * I/O methods. + */ +struct v4l2_ext_buffer { + __u32 index; + __u32 type; + __u32 flags; + __u32 field; + __u64 timestamp; + __u32 sequence; + __u32 memory; + struct v4l2_ext_plane planes[VIDEO_MAX_PLANES]; + __u32 num_planes; + __u32 request_fd; + __u32 reserved[10]; +}; + /* Flags for 'flags' field */ /* Buffer is mapped (flag) */ #define V4L2_BUF_FLAG_MAPPED 0x00000001 @@ -1038,6 +1110,35 @@ struct v4l2_exportbuffer { __u32 reserved[11]; }; +/** + * struct v4l2_ext_exportbuffer - export of video buffer as DMABUF file + * descriptor using extended format + * + * @index: id number of the buffer + * @type: enum v4l2_buf_type; buffer type + * @flags: flags for newly created file(s), currently only O_CLOEXEC is + * supported, refer to manual of open syscall for more details + * @first_plane: first plane to export. Most likely set to 0 + * @num_planes: number of planes to export. Most set to the number of planes + * attached to the buffer + * @fds: file descriptors associated with DMABUF (set by driver). Note that all + * planes might share the same buffer and then be returned the same FD + * + * Contains data used for exporting a video buffer as DMABUF file descriptor. + * The buffer is identified by a 'cookie' returned by VIDIOC_QUERYBUF + * (identical to the cookie used to mmap() the buffer to userspace). All + * reserved fields must be set to zero. + */ +struct v4l2_ext_exportbuffer { + __u32 type; /* enum v4l2_buf_type */ + __u32 index; + __u32 flags; + __u32 first_plane; + __u32 num_planes; + __s32 fds[VIDEO_MAX_PLANES]; + __u32 reserved; +}; + /* * O V E R L A Y P R E V I E W */ @@ -2435,6 +2536,23 @@ struct v4l2_create_buffers { __u32 reserved[7]; }; +/** + * struct v4l2_ext_create_buffers - VIDIOC_EXT_CREATE_BUFS argument + * @index: on return, index of the first created buffer + * @count: entry: number of requested buffers, + * return: number of created buffers + * @memory: enum v4l2_memory; buffer memory type + * @capabilities: capabilities of this buffer type. + * @format: frame format, for which buffers are requested + */ +struct v4l2_ext_create_buffers { + __u32 index; + __u32 count; + __u32 memory; + __u32 capabilities; + struct v4l2_ext_format format; +}; + /* * I O C T L C O D E S F O R V I D E O D E V I C E S * @@ -2538,6 +2656,13 @@ struct v4l2_create_buffers { #define VIDIOC_G_EXT_FMT _IOWR('V', 104, struct v4l2_ext_format) #define VIDIOC_S_EXT_FMT _IOWR('V', 105, struct v4l2_ext_format) #define VIDIOC_TRY_EXT_FMT _IOWR('V', 106, struct v4l2_ext_format) +#define VIDIOC_EXT_CREATE_BUFS _IOWR('V', 107, struct v4l2_ext_create_buffers) +#define VIDIOC_EXT_QUERYBUF _IOWR('V', 108, struct v4l2_ext_buffer) +#define VIDIOC_EXT_QBUF _IOWR('V', 109, struct v4l2_ext_buffer) +#define VIDIOC_EXT_DQBUF _IOWR('V', 110, struct v4l2_ext_buffer) +#define VIDIOC_EXT_PREPARE_BUF _IOWR('V', 111, struct v4l2_ext_buffer) +#define VIDIOC_EXT_EXPBUF _IOWR('V', 112, struct v4l2_ext_exportbuffer) + /* Reminder: when adding new ioctls please add support for them to drivers/media/v4l2-core/v4l2-compat-ioctl32.c as well! */