From patchwork Sat Nov 12 13:12:11 2016 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: 9424135 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 02ED260484 for ; Sat, 12 Nov 2016 13:14:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EB63C296DC for ; Sat, 12 Nov 2016 13:14:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E094A298C0; Sat, 12 Nov 2016 13:14:00 +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=unavailable 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 89A81296DC for ; Sat, 12 Nov 2016 13:14:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S966161AbcKLNN5 (ORCPT ); Sat, 12 Nov 2016 08:13:57 -0500 Received: from smtp-4.sys.kth.se ([130.237.48.193]:33623 "EHLO smtp-4.sys.kth.se" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S966087AbcKLNNy (ORCPT ); Sat, 12 Nov 2016 08:13:54 -0500 Received: from smtp-4.sys.kth.se (localhost.localdomain [127.0.0.1]) by smtp-4.sys.kth.se (Postfix) with ESMTP id 8D97E32C2; Sat, 12 Nov 2016 14:13:51 +0100 (CET) X-Virus-Scanned: by amavisd-new at kth.se Received: from smtp-4.sys.kth.se ([127.0.0.1]) by smtp-4.sys.kth.se (smtp-4.sys.kth.se [127.0.0.1]) (amavisd-new, port 10024) with LMTP id BbGGPtOTPRIa; Sat, 12 Nov 2016 14:13:50 +0100 (CET) X-KTH-Auth: niso [89.233.230.99] X-KTH-mail-from: niklas.soderlund+renesas@ragnatech.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by smtp-4.sys.kth.se (Postfix) with ESMTPSA id 0DEDC32CC; Sat, 12 Nov 2016 14:13:50 +0100 (CET) From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= To: Laurent Pinchart , Hans Verkuil Cc: linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org, tomoharu.fukawa.eb@renesas.com, Sakari Ailus , Geert Uytterhoeven , =?UTF-8?q?Niklas=20S=C3=B6derlund?= Subject: [PATCHv2 27/32] media: rcar-vin: start/stop the CSI2 bridge stream Date: Sat, 12 Nov 2016 14:12:11 +0100 Message-Id: <20161112131216.22635-28-niklas.soderlund+renesas@ragnatech.se> X-Mailer: git-send-email 2.10.2 In-Reply-To: <20161112131216.22635-1-niklas.soderlund+renesas@ragnatech.se> References: <20161112131216.22635-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 On Gen3 the CSI2 bridge stream needs to be start/stop in conjunction with the video source. Create helpers to deal with both the Gen2 single subdevice case and the Gen3 CSI2 group case. In the Gen3 case there might be other simultaneous users of the bridge and source devices so examine each entity stream_count before acting on any particular device. Signed-off-by: Niklas Söderlund --- drivers/media/platform/rcar-vin/rcar-dma.c | 84 +++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 7 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c index 322e4c1..872f138 100644 --- a/drivers/media/platform/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/rcar-vin/rcar-dma.c @@ -1089,15 +1089,87 @@ static void rvin_buffer_queue(struct vb2_buffer *vb) spin_unlock_irqrestore(&vin->qlock, flags); } +static int __rvin_start_streaming(struct rvin_dev *vin) +{ + struct v4l2_subdev *source, *bridge = NULL; + struct media_pipeline *pipe; + int ret; + + source = vin_to_source(vin); + if (!source) + return -EINVAL; + + if (vin_have_bridge(vin)) { + bridge = vin_to_bridge(vin); + + if (!bridge) + return -EINVAL; + + mutex_lock(&vin->group->lock); + + pipe = bridge->entity.pipe ? bridge->entity.pipe : + &vin->vdev.pipe; + ret = media_entity_pipeline_start(&vin->vdev.entity, pipe); + if (ret) { + mutex_unlock(&vin->group->lock); + return ret; + } + + /* Only need to start stream if it's not running */ + if (bridge->entity.stream_count <= 1) + v4l2_subdev_call(bridge, video, s_stream, 1); + if (source->entity.stream_count <= 1) + v4l2_subdev_call(source, video, s_stream, 1); + + mutex_unlock(&vin->group->lock); + } else { + v4l2_subdev_call(source, video, s_stream, 1); + } + + return 0; +} + +static int __rvin_stop_streaming(struct rvin_dev *vin) +{ + struct v4l2_subdev *source, *bridge = NULL; + + source = vin_to_source(vin); + if (!source) + return -EINVAL; + + if (vin_have_bridge(vin)) { + bridge = vin_to_bridge(vin); + + if (!bridge) + return -EINVAL; + + mutex_lock(&vin->group->lock); + + media_entity_pipeline_stop(&vin->vdev.entity); + + /* Only need to stop stream if there are no other users */ + if (bridge->entity.stream_count <= 0) + v4l2_subdev_call(bridge, video, s_stream, 0); + if (source->entity.stream_count <= 0) + v4l2_subdev_call(source, video, s_stream, 0); + + mutex_unlock(&vin->group->lock); + } else { + v4l2_subdev_call(source, video, s_stream, 0); + } + + return 0; +} + static int rvin_start_streaming(struct vb2_queue *vq, unsigned int count) { struct rvin_dev *vin = vb2_get_drv_priv(vq); - struct v4l2_subdev *sd; unsigned long flags; int ret; - sd = vin_to_source(vin); - v4l2_subdev_call(sd, video, s_stream, 1); + ret = __rvin_start_streaming(vin); + if (ret) + return ret; spin_lock_irqsave(&vin->qlock, flags); @@ -1122,7 +1194,7 @@ static int rvin_start_streaming(struct vb2_queue *vq, unsigned int count) /* Return all buffers if something went wrong */ if (ret) { return_all_buffers(vin, VB2_BUF_STATE_QUEUED); - v4l2_subdev_call(sd, video, s_stream, 0); + __rvin_stop_streaming(vin); } spin_unlock_irqrestore(&vin->qlock, flags); @@ -1133,7 +1205,6 @@ static int rvin_start_streaming(struct vb2_queue *vq, unsigned int count) static void rvin_stop_streaming(struct vb2_queue *vq) { struct rvin_dev *vin = vb2_get_drv_priv(vq); - struct v4l2_subdev *sd; unsigned long flags; int retries = 0; @@ -1172,8 +1243,7 @@ static void rvin_stop_streaming(struct vb2_queue *vq) spin_unlock_irqrestore(&vin->qlock, flags); - sd = vin_to_source(vin); - v4l2_subdev_call(sd, video, s_stream, 0); + __rvin_stop_streaming(vin); /* disable interrupts */ rvin_disable_interrupts(vin);