From patchwork Mon Mar 26 21:44:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 10308875 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id A2DE0600CC for ; Mon, 26 Mar 2018 21:47:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 99B1C29833 for ; Mon, 26 Mar 2018 21:47:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8E830298F0; Mon, 26 Mar 2018 21:47:19 +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=-6.9 required=2.0 tests=BAYES_00,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 BF95129833 for ; Mon, 26 Mar 2018 21:47:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752346AbeCZVq6 (ORCPT ); Mon, 26 Mar 2018 17:46:58 -0400 Received: from bin-mail-out-05.binero.net ([195.74.38.228]:32495 "EHLO bin-mail-out-05.binero.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752479AbeCZVqy (ORCPT ); Mon, 26 Mar 2018 17:46:54 -0400 X-Halon-ID: 3183230d-313f-11e8-93de-005056917a89 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-01.atm.binero.net (Halon) with ESMTPA id 3183230d-313f-11e8-93de-005056917a89; Mon, 26 Mar 2018 23:46:52 +0200 (CEST) From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= To: Laurent Pinchart , Hans Verkuil , linux-media@vger.kernel.org Cc: linux-renesas-soc@vger.kernel.org, tomoharu.fukawa.eb@renesas.com, Kieran Bingham , =?UTF-8?q?Niklas=20S=C3=B6derlund?= Subject: [PATCH v13 22/33] rcar-vin: use different v4l2 operations in media controller mode Date: Mon, 26 Mar 2018 23:44:45 +0200 Message-Id: <20180326214456.6655-23-niklas.soderlund+renesas@ragnatech.se> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180326214456.6655-1-niklas.soderlund+renesas@ragnatech.se> References: <20180326214456.6655-1-niklas.soderlund+renesas@ragnatech.se> 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 When the driver runs in media controller mode it should not directly control the subdevice instead userspace will be responsible for configuring the pipeline. To be able to run in this mode a different set of v4l2 operations needs to be used. Add a new set of v4l2 operations to support operation without directly interacting with the source subdevice. Signed-off-by: Niklas Söderlund Reviewed-by: Hans Verkuil Reviewed-by: Laurent Pinchart --- * Changes since v11 - Fixed error labels name in rvin_mc_open(). --- drivers/media/platform/rcar-vin/rcar-dma.c | 2 +- drivers/media/platform/rcar-vin/rcar-v4l2.c | 161 +++++++++++++++++++++++++++- 2 files changed, 159 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c index 1809f5c0190eafb6..a93772c10baaa003 100644 --- a/drivers/media/platform/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/rcar-vin/rcar-dma.c @@ -627,7 +627,7 @@ static int rvin_setup(struct rvin_dev *vin) /* Default to TB */ vnmc = VNMC_IM_FULL; /* Use BT if video standard can be read and is 60 Hz format */ - if (vin->std & V4L2_STD_525_60) + if (!vin->info->use_mc && vin->std & V4L2_STD_525_60) vnmc = VNMC_IM_FULL | VNMC_FOC; break; case V4L2_FIELD_INTERLACED_TB: diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c index dd835be0f9cbcc05..2280535ca981993f 100644 --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c @@ -18,12 +18,16 @@ #include #include +#include #include #include "rcar-vin.h" #define RVIN_DEFAULT_FORMAT V4L2_PIX_FMT_YUYV +#define RVIN_DEFAULT_WIDTH 800 +#define RVIN_DEFAULT_HEIGHT 600 #define RVIN_DEFAULT_FIELD V4L2_FIELD_NONE +#define RVIN_DEFAULT_COLORSPACE V4L2_COLORSPACE_SRGB /* ----------------------------------------------------------------------------- * Format Conversions @@ -656,6 +660,74 @@ static const struct v4l2_ioctl_ops rvin_ioctl_ops = { .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; +/* ----------------------------------------------------------------------------- + * V4L2 Media Controller + */ + +static int rvin_mc_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct rvin_dev *vin = video_drvdata(file); + + return rvin_format_align(vin, &f->fmt.pix); +} + +static int rvin_mc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct rvin_dev *vin = video_drvdata(file); + int ret; + + if (vb2_is_busy(&vin->queue)) + return -EBUSY; + + ret = rvin_format_align(vin, &f->fmt.pix); + if (ret) + return ret; + + vin->format = f->fmt.pix; + + return 0; +} + +static int rvin_mc_enum_input(struct file *file, void *priv, + struct v4l2_input *i) +{ + if (i->index != 0) + return -EINVAL; + + i->type = V4L2_INPUT_TYPE_CAMERA; + strlcpy(i->name, "Camera", sizeof(i->name)); + + return 0; +} + +static const struct v4l2_ioctl_ops rvin_mc_ioctl_ops = { + .vidioc_querycap = rvin_querycap, + .vidioc_try_fmt_vid_cap = rvin_mc_try_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = rvin_g_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = rvin_mc_s_fmt_vid_cap, + .vidioc_enum_fmt_vid_cap = rvin_enum_fmt_vid_cap, + + .vidioc_enum_input = rvin_mc_enum_input, + .vidioc_g_input = rvin_g_input, + .vidioc_s_input = rvin_s_input, + + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_expbuf = vb2_ioctl_expbuf, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = rvin_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + /* ----------------------------------------------------------------------------- * File Operations */ @@ -799,6 +871,74 @@ static const struct v4l2_file_operations rvin_fops = { .read = vb2_fop_read, }; +/* ----------------------------------------------------------------------------- + * Media controller file operations + */ + +static int rvin_mc_open(struct file *file) +{ + struct rvin_dev *vin = video_drvdata(file); + int ret; + + ret = mutex_lock_interruptible(&vin->lock); + if (ret) + return ret; + + ret = pm_runtime_get_sync(vin->dev); + if (ret < 0) + goto err_unlock; + + ret = v4l2_pipeline_pm_use(&vin->vdev.entity, 1); + if (ret < 0) + goto err_pm; + + file->private_data = vin; + + ret = v4l2_fh_open(file); + if (ret) + goto err_v4l2pm; + + mutex_unlock(&vin->lock); + + return 0; +err_v4l2pm: + v4l2_pipeline_pm_use(&vin->vdev.entity, 0); +err_pm: + pm_runtime_put(vin->dev); +err_unlock: + mutex_unlock(&vin->lock); + + return ret; +} + +static int rvin_mc_release(struct file *file) +{ + struct rvin_dev *vin = video_drvdata(file); + int ret; + + mutex_lock(&vin->lock); + + /* the release helper will cleanup any on-going streaming. */ + ret = _vb2_fop_release(file, NULL); + + v4l2_pipeline_pm_use(&vin->vdev.entity, 0); + pm_runtime_put(vin->dev); + + mutex_unlock(&vin->lock); + + return ret; +} + +static const struct v4l2_file_operations rvin_mc_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = video_ioctl2, + .open = rvin_mc_open, + .release = rvin_mc_release, + .poll = vb2_fop_poll, + .mmap = vb2_fop_mmap, + .read = vb2_fop_read, +}; + void rvin_v4l2_unregister(struct rvin_dev *vin) { if (!video_is_registered(&vin->vdev)) @@ -834,18 +974,33 @@ int rvin_v4l2_register(struct rvin_dev *vin) vin->v4l2_dev.notify = rvin_notify; /* video node */ - vdev->fops = &rvin_fops; vdev->v4l2_dev = &vin->v4l2_dev; vdev->queue = &vin->queue; strlcpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name)); vdev->release = video_device_release_empty; - vdev->ioctl_ops = &rvin_ioctl_ops; vdev->lock = &vin->lock; vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; + /* Set a default format */ vin->format.pixelformat = RVIN_DEFAULT_FORMAT; - rvin_reset_format(vin); + vin->format.width = RVIN_DEFAULT_WIDTH; + vin->format.height = RVIN_DEFAULT_HEIGHT; + vin->format.field = RVIN_DEFAULT_FIELD; + vin->format.colorspace = RVIN_DEFAULT_COLORSPACE; + + if (vin->info->use_mc) { + vdev->fops = &rvin_mc_fops; + vdev->ioctl_ops = &rvin_mc_ioctl_ops; + } else { + vdev->fops = &rvin_fops; + vdev->ioctl_ops = &rvin_ioctl_ops; + rvin_reset_format(vin); + } + + ret = rvin_format_align(vin, &vin->format); + if (ret) + return ret; ret = video_register_device(&vin->vdev, VFL_TYPE_GRABBER, -1); if (ret) {