From patchwork Sat Nov 27 16:41:33 2021 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: 12642417 X-Patchwork-Delegate: kieran@bingham.xyz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 35F76C433F5 for ; Sat, 27 Nov 2021 16:44:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234670AbhK0Qre (ORCPT ); Sat, 27 Nov 2021 11:47:34 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37626 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233268AbhK0Qpc (ORCPT ); Sat, 27 Nov 2021 11:45:32 -0500 Received: from mail-wm1-x330.google.com (mail-wm1-x330.google.com [IPv6:2a00:1450:4864:20::330]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A4886C061746 for ; Sat, 27 Nov 2021 08:42:15 -0800 (PST) Received: by mail-wm1-x330.google.com with SMTP id r9-20020a7bc089000000b00332f4abf43fso8959113wmh.0 for ; Sat, 27 Nov 2021 08:42:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ragnatech-se.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Jp77MKE/U4T9c+FwNAWUTuF78plz492lxF0sUt5DL5w=; b=LXPH7JjwQXdBgbG0YwR/1WEauHe52AyQ6DmrBqulBAn9Lf3dVVAALwslKjA7COT6yB MULBlrE4UFbm7mwaZ6/Y7xznJPOhvyUNmF/V4/s3dH66tTgLcNujubcTEmgvDRbQUMRT uKa88/SnPBY3KqfLxdHDWiI6GkXTCX9XVG/ku0crNdbblSNj69jB8fwhVk/HWrr2Eoo4 rx4Q5oN44Hh18Kw0GQlNiTWRaj9cxFywVMdLTU+onWnhmZbC3TzFOscEk+yGnU0oDnvC eUKEL1r9q2c6J+CuyGKr/Lm0nZ2cEjokemVJzBAZOFXvDhg2S0B0nvf3S/TmDSm4me06 pozw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Jp77MKE/U4T9c+FwNAWUTuF78plz492lxF0sUt5DL5w=; b=COAVNWhp5S/0rfrPst7W/xUz9jwp5XOldS6u6/DEtOnCBemTT5G/fs/ZJ9t69r3MnY FvQu6ZBNv2lMbdtY0aakD0oU98/78eL3xtaLVLKDn1Tt2uyqKAdBjcyGDQrZSyyc2KeJ 9H4idtsDiwZj9ZjfPQ/p08obea1SHHSx2h2N/bftVoyXyUzyUB4H8Kn9JMXFqHqDiz34 Io00b0AbVBZufyMhz8QvnZ4f9n/3XJcJLg60MQFyH0yQmoHKcQWbLkwB7b9LNPDQU6/6 0mnVTRi0yZ4TQxH6Kig4muzV7ynL7mh7GMPbxjlwTAH2kR+XPGXLAp9HF7pZWgpFNyMR Rz/g== X-Gm-Message-State: AOAM532eYKZFC7y1hXnXJr9T9wAnmk0P/1qpT4T1Os2LiBWnRFtubPv1 VjxEJZAQZcxwI3l0B01L4RZklQ== X-Google-Smtp-Source: ABdhPJzDXEZznePExCfd/hxbrc9D9+67a6gSP54xWkC5SS/EPwpk/jj1yLB40pjECT+5K7xqDNYTxg== X-Received: by 2002:a1c:f20e:: with SMTP id s14mr24320938wmc.186.1638031334197; Sat, 27 Nov 2021 08:42:14 -0800 (PST) Received: from bismarck.berto.se (p54ac5892.dip0.t-ipconnect.de. [84.172.88.146]) by smtp.googlemail.com with ESMTPSA id u13sm2900104wmq.14.2021.11.27.08.42.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 27 Nov 2021 08:42:13 -0800 (PST) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: Hans Verkuil , Jacopo Mondi , Laurent Pinchart , linux-media@vger.kernel.org Cc: linux-renesas-soc@vger.kernel.org, =?utf-8?q?Niklas_S=C3=B6derlund?= Subject: [PATCH v2 1/3] media: rcar-vin: Refactor link notify Date: Sat, 27 Nov 2021 17:41:33 +0100 Message-Id: <20211127164135.2617686-2-niklas.soderlund+renesas@ragnatech.se> X-Mailer: git-send-email 2.34.0 In-Reply-To: <20211127164135.2617686-1-niklas.soderlund+renesas@ragnatech.se> References: <20211127164135.2617686-1-niklas.soderlund+renesas@ragnatech.se> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org The code has grown organically and a lot of checks are performed for the CSI-2 use-case even if the link notify is for a subdevice connected to the parallel interface. Before reworking the CSI-2 routing logic split the CSI-2 and parallel link notify code in two separate blocks to make it clearer. There is no functional change. Signed-off-by: Niklas Söderlund Tested-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- * Changers since v1 - Fix spelling in commit message. - Removed extra blank line in rvin_csi2_link_notify(). - Move vdev and vin lookup outside the mutex. --- drivers/media/platform/rcar-vin/rcar-core.c | 90 +++++++++++---------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c index 1d92cc8ede8f8a3e..4c3c092a7cb9476b 100644 --- a/drivers/media/platform/rcar-vin/rcar-core.c +++ b/drivers/media/platform/rcar-vin/rcar-core.c @@ -795,12 +795,10 @@ static int rvin_csi2_link_notify(struct media_link *link, u32 flags, { struct rvin_group *group = container_of(link->graph_obj.mdev, struct rvin_group, mdev); - unsigned int master_id, channel, mask_new, i; - unsigned int mask = ~0; struct media_entity *entity; struct video_device *vdev; - struct media_pad *csi_pad; - struct rvin_dev *vin = NULL; + struct rvin_dev *vin; + unsigned int i; int csi_id, ret; ret = v4l2_pipeline_link_notify(link, flags, notification); @@ -821,38 +819,13 @@ static int rvin_csi2_link_notify(struct media_link *link, u32 flags, if (entity->stream_count) return -EBUSY; - mutex_lock(&group->lock); - /* Find the master VIN that controls the routes. */ vdev = media_entity_to_video_device(link->sink->entity); vin = container_of(vdev, struct rvin_dev, vdev); - master_id = rvin_group_id_to_master(vin->id); - if (WARN_ON(!group->vin[master_id])) { - ret = -ENODEV; - goto out; - } + mutex_lock(&group->lock); - /* Build a mask for already enabled links. */ - for (i = master_id; i < master_id + 4; i++) { - if (!group->vin[i]) - continue; - - /* Get remote CSI-2, if any. */ - csi_pad = media_entity_remote_pad( - &group->vin[i]->vdev.entity.pads[0]); - if (!csi_pad) - continue; - - csi_id = rvin_group_entity_to_remote_id(group, csi_pad->entity); - channel = rvin_group_csi_pad_to_channel(csi_pad->index); - - mask &= rvin_csi2_get_mask(group->vin[i], csi_id, channel); - } - - /* Add the new link to the existing mask and check if it works. */ csi_id = rvin_group_entity_to_remote_id(group, link->source->entity); - if (csi_id == -ENODEV) { struct v4l2_subdev *sd; @@ -877,25 +850,54 @@ static int rvin_csi2_link_notify(struct media_link *link, u32 flags, vin_err(vin, "Subdevice %s not registered to any VIN\n", link->source->entity->name); ret = -ENODEV; - goto out; - } + } else { + unsigned int master_id, channel, mask_new; + unsigned int mask = ~0; + struct media_pad *csi_pad; - channel = rvin_group_csi_pad_to_channel(link->source->index); - mask_new = mask & rvin_csi2_get_mask(vin, csi_id, channel); - vin_dbg(vin, "Try link change mask: 0x%x new: 0x%x\n", mask, mask_new); + master_id = rvin_group_id_to_master(vin->id); - if (!mask_new) { - ret = -EMLINK; - goto out; - } + if (WARN_ON(!group->vin[master_id])) { + ret = -ENODEV; + goto out; + } + + /* Build a mask for already enabled links. */ + for (i = master_id; i < master_id + 4; i++) { + if (!group->vin[i]) + continue; + + /* Get remote CSI-2, if any. */ + csi_pad = media_entity_remote_pad( + &group->vin[i]->vdev.entity.pads[0]); + if (!csi_pad) + continue; - /* New valid CHSEL found, set the new value. */ - ret = rvin_set_channel_routing(group->vin[master_id], __ffs(mask_new)); - if (ret) - goto out; + csi_id = rvin_group_entity_to_remote_id(group, + csi_pad->entity); + channel = rvin_group_csi_pad_to_channel(csi_pad->index); - vin->is_csi = true; + mask &= rvin_csi2_get_mask(group->vin[i], csi_id, channel); + } + channel = rvin_group_csi_pad_to_channel(link->source->index); + mask_new = mask & rvin_csi2_get_mask(vin, csi_id, channel); + vin_dbg(vin, "Try link change mask: 0x%x new: 0x%x\n", mask, + mask_new); + + if (!mask_new) { + ret = -EMLINK; + goto out; + } + + /* New valid CHSEL found, set the new value. */ + ret = rvin_set_channel_routing(group->vin[master_id], + __ffs(mask_new)); + if (ret) + goto out; + + vin->is_csi = true; + } out: mutex_unlock(&group->lock); From patchwork Sat Nov 27 16:41:34 2021 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: 12642421 X-Patchwork-Delegate: kieran@bingham.xyz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2E0CCC433F5 for ; Sat, 27 Nov 2021 16:44:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235754AbhK0Qrf (ORCPT ); Sat, 27 Nov 2021 11:47:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37632 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233999AbhK0Qpc (ORCPT ); Sat, 27 Nov 2021 11:45:32 -0500 Received: from mail-wr1-x433.google.com (mail-wr1-x433.google.com [IPv6:2a00:1450:4864:20::433]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3B7C7C06174A for ; Sat, 27 Nov 2021 08:42:16 -0800 (PST) Received: by mail-wr1-x433.google.com with SMTP id j3so25920162wrp.1 for ; Sat, 27 Nov 2021 08:42:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ragnatech-se.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=R3gkSM1pd5VakS31lqAU7GttEgDzPEtgx9VPbpSRfs4=; b=z/zRZQH4M05YWZ4wApL6+tp31PtKtv/WLoCF16aEnEgtfaHHYzq9WjG+ZMRQ8qsF5G lIqcxnuc7a5l5MXBGdartx2LgQarLwYWsilHqp3Ur7fvjUAYDXBJl1I2J2wjm0R55TX+ Znnta+U6bSq2PkpQapdo6TW+suXQGtsdSF6TiVds6eine2PNJZLEgFvpSVGvmWvaG0KI zb3II74B96eikXPg+OGe/L4kHM2lgY61pUVZX2OxnbM4ETNV2Trt/dtG1qaJOjPMwGM0 nKyrRx9fDlO+BSeZrk6UR8X9rF87QHWPcasTE3Fl5kG8Nt9hqoo5zCkN2kRrnnhcmmSI +i2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=R3gkSM1pd5VakS31lqAU7GttEgDzPEtgx9VPbpSRfs4=; b=Zf21XnRII64qdGDrkiaXAVEmC2V+DfjB7OBhMyRNbFIoLPhCmsd8qPZ1/impoTQH4D Wb0DK/ZOPFvRG+rPelnIgUSSgJH8Mq1sjVC8RkyEX9llMC6ZZZzREy4fPoBhcg+BsCvC eSsDGhtnIlPjrgS64KhgdHQCReFUL4ApaGvipT6SYmCaXNuVZSFjPFAmPxYQ46Fqnk6C kwGsdX+jmeZzVytH6CoVL3k3qi3BFv9AFnAq6zWByt44P6///t1BoXMla8bGQY3fhe3x QPuzZc3wVDOnJEtp2yqRd9BlbmemCvXRfh46w2FRMSA2gHjAOXbhhglzTZx+vlt1eXmi 0m6A== X-Gm-Message-State: AOAM530xnm+9QZRXFk1elZU9EqgkRanul8Y6Z0Z7IGac7bqB5ktHk8kK 8q9Dv1IiHq9Y6JbiC0ce6w35Xw== X-Google-Smtp-Source: ABdhPJxaNqjUSV9aUPHbIMoYC506awgl56soNYUIMbuS2YqlBVofCibbAvDc+rKAJPbcxLDjLcRx6Q== X-Received: by 2002:a5d:648f:: with SMTP id o15mr21037223wri.381.1638031334784; Sat, 27 Nov 2021 08:42:14 -0800 (PST) Received: from bismarck.berto.se (p54ac5892.dip0.t-ipconnect.de. [84.172.88.146]) by smtp.googlemail.com with ESMTPSA id u13sm2900104wmq.14.2021.11.27.08.42.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 27 Nov 2021 08:42:14 -0800 (PST) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: Hans Verkuil , Jacopo Mondi , Laurent Pinchart , linux-media@vger.kernel.org Cc: linux-renesas-soc@vger.kernel.org, =?utf-8?q?Niklas_S=C3=B6derlund?= Subject: [PATCH v2 2/3] media: rcar-vin: Breakout media link creation Date: Sat, 27 Nov 2021 17:41:34 +0100 Message-Id: <20211127164135.2617686-3-niklas.soderlund+renesas@ragnatech.se> X-Mailer: git-send-email 2.34.0 In-Reply-To: <20211127164135.2617686-1-niklas.soderlund+renesas@ragnatech.se> References: <20211127164135.2617686-1-niklas.soderlund+renesas@ragnatech.se> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org In preparation of creating more links to allow for full Virtual Channel routing within the CSI-2 block break out the link creation logic to a helper function as the logic will grow in future work. There is no functional change. Signed-off-by: Niklas Söderlund Tested-by: Jacopo Mondi Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- * Changers since v1 - Rename rvin_csi2_add_route() to rvin_csi2_create_link(). - Restored comment about skipping links aready created. --- drivers/media/platform/rcar-vin/rcar-core.c | 39 ++++++++++----------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c index 4c3c092a7cb9476b..278e55f6ff3da933 100644 --- a/drivers/media/platform/rcar-vin/rcar-core.c +++ b/drivers/media/platform/rcar-vin/rcar-core.c @@ -908,6 +908,23 @@ static const struct media_device_ops rvin_csi2_media_ops = { .link_notify = rvin_csi2_link_notify, }; +static int rvin_csi2_create_link(struct rvin_group *group, + const struct rvin_group_route *route) + +{ + struct media_entity *source = &group->remotes[route->csi].subdev->entity; + unsigned int source_idx = rvin_group_csi_channel_to_pad(route->channel); + struct media_entity *sink = &group->vin[route->vin]->vdev.entity; + struct media_pad *source_pad = &source->pads[source_idx]; + struct media_pad *sink_pad = &sink->pads[0]; + + /* Skip if link already exists. */ + if (media_entity_find_link(source_pad, sink_pad)) + return 0; + + return media_create_pad_link(source, source_idx, sink, 0, 0); +} + static int rvin_csi2_setup_links(struct rvin_dev *vin) { const struct rvin_group_route *route; @@ -916,10 +933,6 @@ static int rvin_csi2_setup_links(struct rvin_dev *vin) /* Create all media device links between VINs and CSI-2's. */ mutex_lock(&vin->group->lock); for (route = vin->info->routes; route->mask; route++) { - struct media_pad *source_pad, *sink_pad; - struct media_entity *source, *sink; - unsigned int source_idx; - /* Check that VIN is part of the group. */ if (!vin->group->vin[route->vin]) continue; @@ -932,23 +945,9 @@ static int rvin_csi2_setup_links(struct rvin_dev *vin) if (!vin->group->remotes[route->csi].subdev) continue; - source = &vin->group->remotes[route->csi].subdev->entity; - source_idx = rvin_group_csi_channel_to_pad(route->channel); - source_pad = &source->pads[source_idx]; - - sink = &vin->group->vin[route->vin]->vdev.entity; - sink_pad = &sink->pads[0]; - - /* Skip if link already exists. */ - if (media_entity_find_link(source_pad, sink_pad)) - continue; - - ret = media_create_pad_link(source, source_idx, sink, 0, 0); - if (ret) { - vin_err(vin, "Error adding link from %s to %s\n", - source->name, sink->name); + ret = rvin_csi2_create_link(vin->group, route); + if (ret) break; - } } mutex_unlock(&vin->group->lock); From patchwork Sat Nov 27 16:41:35 2021 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: 12642419 X-Patchwork-Delegate: kieran@bingham.xyz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DCC7CC433EF for ; Sat, 27 Nov 2021 16:44:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233268AbhK0Qrf (ORCPT ); Sat, 27 Nov 2021 11:47:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37638 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234077AbhK0Qpc (ORCPT ); Sat, 27 Nov 2021 11:45:32 -0500 Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 37B54C061757 for ; Sat, 27 Nov 2021 08:42:17 -0800 (PST) Received: by mail-wr1-x434.google.com with SMTP id a18so25894513wrn.6 for ; Sat, 27 Nov 2021 08:42:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ragnatech-se.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=x015oE0uc9DfjhhIKBVJ+S2qbKlSUmepCqgjG87yYA8=; b=wHbNwYvZ8RX214xKGmhQq3PSqb0O0t1XRRMfJHdYcHq8OiwMaaNCX7x0rrriDCaV7s HRTLqHjYCDM6P8E/8J1sZw0kWOKS7VcOuBuiazJzAE4dqMqT7ilaYV0SoRSNrGtZCNz3 WxaO/GX9oxC4KF/L7gwkcVr3Y1b2qJZJnS88Rmp4r0SrKtTgb+dWwvbYtn5LMXfGsnSH D0YXL0RG78tqlXGBWr3jkLGQ04+ztNEHSsHP4upN3/ue/87sOu0vEkRPuYJAr2nFypXd UYryjOCUdofC6sCwXsHboVlvVRI+8SSwzQFZbl2cq5yBIS2o2kGRATRvIfkKhcmqdhzt HHNQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=x015oE0uc9DfjhhIKBVJ+S2qbKlSUmepCqgjG87yYA8=; b=ApPdpixk/nQOpLWb3aNJ71F9uH8ooQdbzCxtFaZjtJRsEMocbawGPaIJyDPGA8Pf0n XwtYmrpXTadBbNJFZbknXAIjqNnMOVFVZwlsW49OJYaNTMT7FqM3MVBRKfuxCRC8dCa7 TUqnjAhJKLUuo53+3lI/0e1tmwv3RglBuu+rEUsdSaHnOifHoqbDvDC9KmpuCTNE0eCr ldKg14kTPZfjsaYVKG1/fDiQoQ0qVeI8JvBstrvdfav27xVocM+5vJ3IdIchQOr1lSSd ykL880y2HVmjV9b2ii6rmLVW3F3OWAUFOsBqT9VnB2dU6NAFinCVoXPet9yr4OP5tabQ QY5w== X-Gm-Message-State: AOAM53352hJa5hUc7fs9QWvUatGclLlTaEDp3wOdRbttcfGCPqrtQWR8 uL5/kf8PhbdldWm4bVE9CIiVEQ== X-Google-Smtp-Source: ABdhPJzUPbzVe0j+l+CBh36hhBYutvZVBWtOYV0a5o0Eq1/i9JfvsCXOP9qPJ6Xq/t1UXa6SuT3qOw== X-Received: by 2002:a5d:568c:: with SMTP id f12mr21525260wrv.240.1638031335461; Sat, 27 Nov 2021 08:42:15 -0800 (PST) Received: from bismarck.berto.se (p54ac5892.dip0.t-ipconnect.de. [84.172.88.146]) by smtp.googlemail.com with ESMTPSA id u13sm2900104wmq.14.2021.11.27.08.42.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 27 Nov 2021 08:42:15 -0800 (PST) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: Hans Verkuil , Jacopo Mondi , Laurent Pinchart , linux-media@vger.kernel.org Cc: linux-renesas-soc@vger.kernel.org, =?utf-8?q?Niklas_S=C3=B6derlund?= Subject: [PATCH v2 3/3] media: rcar-{csi2,vin}: Move to full Virtual Channel routing per CSI-2 IP Date: Sat, 27 Nov 2021 17:41:35 +0100 Message-Id: <20211127164135.2617686-4-niklas.soderlund+renesas@ragnatech.se> X-Mailer: git-send-email 2.34.0 In-Reply-To: <20211127164135.2617686-1-niklas.soderlund+renesas@ragnatech.se> References: <20211127164135.2617686-1-niklas.soderlund+renesas@ragnatech.se> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org When Gen3 support was first added to this R-Car VIN and CSI-2 driver the routing was centred around the CHSEL register which multiplexes the different parallel buses that sit between the CSI-2 receivers source side and the VIN dma engines. This was a bad design as the multiplexing do allow for only a few combinations and do not play nice with many video streams in the system. For example it's only possible for CSI-2 Virtual Channels 0 and 1 of any given CSI-2 receiver to be used together with the scaler. Later datasheets have expanded the documentation and it is now possible to improve on this design by allowing any Virtual Channel to be routed to any R-Car VIN instance, provided that there exists a parallel bus between them. This increases the flexibility as all Virtual Channels can now be used together with the scaler for example. The redesign is not however perfect. While the new design allows for many more routes, two constrains limit a small portion of routes that was possible in the old design but are no more. - It is no longer possible to route the same CSI-2 and VC to more then one VIN at a time. This was theoretically possible before if the specific SoC allowed for the same CSI-2 and VC to be routed to two different VIN capture groups. - It is no longer possible to simultaneously mix links from two CSI-2 IP blocks to the same VIN capture group. For example if VIN2 is capturing from CSI40 then VIN{0,1,3} must also capture from CSI40. While VIN{4,5,6,7} is still free to capture from any other CSI-2 IP in the system. Once all VIN{0,1,2,3} links to CSI40 are disabled that VIN capture group is free again to capture from any other CSI-2 IP it is connected to. At the core of the redesign is greater cooperator of the R-Car VIN and CSI-2 drivers in configuring the routing. The VIN driver is after this change only responsible to configure the full VIN capture groups parallel buses to be to a particular CSI-2 IP. While the configuration of which CSI-2 Virtual Channel is outputted on which of the R-Car CSI-2 IP output ports is handled by the CSI-2 driver. Before this change the CSI-2 Virtual Channel to output port was static in the CSI-2 driver and the different links only manipulated the VIN capture groups CHSEL register. With this change both the CHSEl register and the CSI-2 routing VCDT registers are modified for greater flexibility. This change touches both the R-Car VIN and R-Car CSI-2 drivers in the same commit as both drivers cooperate closely and one change without the other would more or less break video capture. Signed-off-by: Niklas Söderlund Tested-by: Jacopo Mondi --- * Changers since v1 - Fix spelling in commit message. - Fix incorrect routing table for r8a7795es1. - Remove usage of BUG_ON() and recover instead. --- drivers/media/platform/rcar-vin/rcar-core.c | 320 +++++--------------- drivers/media/platform/rcar-vin/rcar-csi2.c | 58 +++- drivers/media/platform/rcar-vin/rcar-dma.c | 2 +- drivers/media/platform/rcar-vin/rcar-vin.h | 18 +- 4 files changed, 139 insertions(+), 259 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c index 278e55f6ff3da933..c910a4c6d07ede83 100644 --- a/drivers/media/platform/rcar-vin/rcar-core.c +++ b/drivers/media/platform/rcar-vin/rcar-core.c @@ -745,27 +745,6 @@ static int rvin_parallel_init(struct rvin_dev *vin) * CSI-2 */ -static unsigned int rvin_csi2_get_mask(struct rvin_dev *vin, - enum rvin_csi_id csi_id, - unsigned char channel) -{ - const struct rvin_group_route *route; - unsigned int mask = 0; - - for (route = vin->info->routes; route->mask; route++) { - if (route->vin == vin->id && - route->csi == csi_id && - route->channel == channel) { - vin_dbg(vin, - "Adding route: vin: %d csi: %d channel: %d\n", - route->vin, route->csi, route->channel); - mask |= route->mask; - } - } - - return mask; -} - /* * Link setup for the links between a VIN and a CSI-2 receiver is a bit * complex. The reason for this is that the register controlling routing @@ -851,9 +830,9 @@ static int rvin_csi2_link_notify(struct media_link *link, u32 flags, link->source->entity->name); ret = -ENODEV; } else { - unsigned int master_id, channel, mask_new; - unsigned int mask = ~0; - struct media_pad *csi_pad; + const struct rvin_group_route *route; + unsigned int chsel = UINT_MAX; + unsigned int master_id; master_id = rvin_group_id_to_master(vin->id); @@ -862,8 +841,10 @@ static int rvin_csi2_link_notify(struct media_link *link, u32 flags, goto out; } - /* Build a mask for already enabled links. */ + /* Make sure group is connected to same CSI-2 */ for (i = master_id; i < master_id + 4; i++) { + struct media_pad *csi_pad; + if (!group->vin[i]) continue; @@ -873,26 +854,28 @@ static int rvin_csi2_link_notify(struct media_link *link, u32 flags, if (!csi_pad) continue; - csi_id = rvin_group_entity_to_remote_id(group, - csi_pad->entity); - channel = rvin_group_csi_pad_to_channel(csi_pad->index); - - mask &= rvin_csi2_get_mask(group->vin[i], csi_id, channel); + if (csi_pad->entity != link->source->entity) { + vin_dbg(vin, "Already attached to %s\n", + csi_pad->entity->name); + ret = -EBUSY; + goto out; + } } - channel = rvin_group_csi_pad_to_channel(link->source->index); - mask_new = mask & rvin_csi2_get_mask(vin, csi_id, channel); - vin_dbg(vin, "Try link change mask: 0x%x new: 0x%x\n", mask, - mask_new); + for (route = vin->info->routes; route->chsel; route++) { + if (route->master == master_id && route->csi == csi_id) { + chsel = route->chsel; + break; + } + } - if (!mask_new) { - ret = -EMLINK; + if (chsel == UINT_MAX) { + vin_err(vin, "No CHSEL value found\n"); + ret = -EINVAL; goto out; } - /* New valid CHSEL found, set the new value. */ - ret = rvin_set_channel_routing(group->vin[master_id], - __ffs(mask_new)); + ret = rvin_set_channel_routing(group->vin[master_id], chsel); if (ret) goto out; @@ -908,47 +891,60 @@ static const struct media_device_ops rvin_csi2_media_ops = { .link_notify = rvin_csi2_link_notify, }; -static int rvin_csi2_create_link(struct rvin_group *group, - const struct rvin_group_route *route) +static int rvin_csi2_create_link(struct rvin_group *group, unsigned int id, + const struct rvin_group_route *route) { struct media_entity *source = &group->remotes[route->csi].subdev->entity; - unsigned int source_idx = rvin_group_csi_channel_to_pad(route->channel); - struct media_entity *sink = &group->vin[route->vin]->vdev.entity; - struct media_pad *source_pad = &source->pads[source_idx]; + struct media_entity *sink = &group->vin[id]->vdev.entity; struct media_pad *sink_pad = &sink->pads[0]; + unsigned int channel; + int ret; - /* Skip if link already exists. */ - if (media_entity_find_link(source_pad, sink_pad)) - return 0; + for (channel = 0; channel < 4; channel++) { + unsigned int source_idx = rvin_group_csi_channel_to_pad(channel); + struct media_pad *source_pad = &source->pads[source_idx]; - return media_create_pad_link(source, source_idx, sink, 0, 0); + /* Skip if link already exists. */ + if (media_entity_find_link(source_pad, sink_pad)) + continue; + + ret = media_create_pad_link(source, source_idx, sink, 0, 0); + if (ret) + return ret; + } + + return 0; } static int rvin_csi2_setup_links(struct rvin_dev *vin) { const struct rvin_group_route *route; + unsigned int id; int ret = -EINVAL; /* Create all media device links between VINs and CSI-2's. */ mutex_lock(&vin->group->lock); - for (route = vin->info->routes; route->mask; route++) { - /* Check that VIN is part of the group. */ - if (!vin->group->vin[route->vin]) - continue; - + for (route = vin->info->routes; route->chsel; route++) { /* Check that VIN' master is part of the group. */ - if (!vin->group->vin[rvin_group_id_to_master(route->vin)]) + if (!vin->group->vin[route->master]) continue; /* Check that CSI-2 is part of the group. */ if (!vin->group->remotes[route->csi].subdev) continue; - ret = rvin_csi2_create_link(vin->group, route); - if (ret) - break; + for (id = route->master; id < route->master + 4; id++) { + /* Check that VIN is part of the group. */ + if (!vin->group->vin[id]) + continue; + + ret = rvin_csi2_create_link(vin->group, id, route); + if (ret) + goto out; + } } +out: mutex_unlock(&vin->group->lock); return ret; @@ -1158,30 +1154,9 @@ static const struct rvin_info rcar_info_gen2 = { }; static const struct rvin_group_route rcar_info_r8a774e1_routes[] = { - { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 2, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) | BIT(2) }, - { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 6, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) | BIT(2) }, - { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) }, + { .master = 0, .csi = RVIN_CSI20, .chsel = 0x04 }, + { .master = 0, .csi = RVIN_CSI40, .chsel = 0x03 }, + { .master = 4, .csi = RVIN_CSI20, .chsel = 0x04 }, { /* Sentinel */ } }; @@ -1194,38 +1169,10 @@ static const struct rvin_info rcar_info_r8a774e1 = { }; static const struct rvin_group_route rcar_info_r8a7795_routes[] = { - { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 2, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) | BIT(2) }, - { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) }, - { .csi = RVIN_CSI41, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) }, - { .csi = RVIN_CSI41, .channel = 1, .vin = 4, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) }, - { .csi = RVIN_CSI41, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) }, - { .csi = RVIN_CSI41, .channel = 0, .vin = 5, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 6, .mask = BIT(0) }, - { .csi = RVIN_CSI41, .channel = 0, .vin = 6, .mask = BIT(1) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) }, - { .csi = RVIN_CSI41, .channel = 2, .vin = 6, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) }, - { .csi = RVIN_CSI41, .channel = 1, .vin = 7, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) | BIT(2) }, - { .csi = RVIN_CSI41, .channel = 3, .vin = 7, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) }, + { .master = 0, .csi = RVIN_CSI20, .chsel = 0x04 }, + { .master = 0, .csi = RVIN_CSI40, .chsel = 0x03 }, + { .master = 4, .csi = RVIN_CSI20, .chsel = 0x04 }, + { .master = 4, .csi = RVIN_CSI41, .chsel = 0x03 }, { /* Sentinel */ } }; @@ -1239,48 +1186,12 @@ static const struct rvin_info rcar_info_r8a7795 = { }; static const struct rvin_group_route rcar_info_r8a7795es1_routes[] = { - { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) }, - { .csi = RVIN_CSI21, .channel = 0, .vin = 0, .mask = BIT(2) | BIT(5) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) }, - { .csi = RVIN_CSI21, .channel = 0, .vin = 1, .mask = BIT(1) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) }, - { .csi = RVIN_CSI21, .channel = 1, .vin = 1, .mask = BIT(5) }, - { .csi = RVIN_CSI21, .channel = 0, .vin = 2, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) }, - { .csi = RVIN_CSI21, .channel = 2, .vin = 2, .mask = BIT(5) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) }, - { .csi = RVIN_CSI21, .channel = 1, .vin = 3, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) }, - { .csi = RVIN_CSI21, .channel = 3, .vin = 3, .mask = BIT(5) }, - { .csi = RVIN_CSI41, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) }, - { .csi = RVIN_CSI21, .channel = 0, .vin = 4, .mask = BIT(2) | BIT(5) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) }, - { .csi = RVIN_CSI21, .channel = 0, .vin = 5, .mask = BIT(1) }, - { .csi = RVIN_CSI41, .channel = 0, .vin = 5, .mask = BIT(2) }, - { .csi = RVIN_CSI41, .channel = 1, .vin = 5, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) }, - { .csi = RVIN_CSI21, .channel = 1, .vin = 5, .mask = BIT(5) }, - { .csi = RVIN_CSI21, .channel = 0, .vin = 6, .mask = BIT(0) }, - { .csi = RVIN_CSI41, .channel = 0, .vin = 6, .mask = BIT(1) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) }, - { .csi = RVIN_CSI41, .channel = 2, .vin = 6, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) }, - { .csi = RVIN_CSI21, .channel = 2, .vin = 6, .mask = BIT(5) }, - { .csi = RVIN_CSI41, .channel = 1, .vin = 7, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) }, - { .csi = RVIN_CSI21, .channel = 1, .vin = 7, .mask = BIT(2) }, - { .csi = RVIN_CSI41, .channel = 3, .vin = 7, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) }, - { .csi = RVIN_CSI21, .channel = 3, .vin = 7, .mask = BIT(5) }, + { .master = 0, .csi = RVIN_CSI20, .chsel = 0x04 }, + { .master = 0, .csi = RVIN_CSI21, .chsel = 0x05 }, + { .master = 0, .csi = RVIN_CSI40, .chsel = 0x03 }, + { .master = 4, .csi = RVIN_CSI20, .chsel = 0x04 }, + { .master = 4, .csi = RVIN_CSI21, .chsel = 0x05 }, + { .master = 4, .csi = RVIN_CSI41, .chsel = 0x03 }, { /* Sentinel */ } }; @@ -1293,34 +1204,10 @@ static const struct rvin_info rcar_info_r8a7795es1 = { }; static const struct rvin_group_route rcar_info_r8a7796_routes[] = { - { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) }, - { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 5, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 5, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 6, .mask = BIT(1) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 2, .vin = 6, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 7, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) }, - { .csi = RVIN_CSI40, .channel = 3, .vin = 7, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) }, + { .master = 0, .csi = RVIN_CSI20, .chsel = 0x04 }, + { .master = 0, .csi = RVIN_CSI40, .chsel = 0x03 }, + { .master = 4, .csi = RVIN_CSI20, .chsel = 0x04 }, + { .master = 4, .csi = RVIN_CSI40, .chsel = 0x03 }, { /* Sentinel */ } }; @@ -1334,38 +1221,10 @@ static const struct rvin_info rcar_info_r8a7796 = { }; static const struct rvin_group_route rcar_info_r8a77965_routes[] = { - { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 2, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) | BIT(2) }, - { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 4, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 5, .mask = BIT(2) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 6, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 6, .mask = BIT(1) }, - { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 2, .vin = 6, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 7, .mask = BIT(0) }, - { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) | BIT(2) }, - { .csi = RVIN_CSI40, .channel = 3, .vin = 7, .mask = BIT(3) }, - { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) }, + { .master = 0, .csi = RVIN_CSI20, .chsel = 0x04 }, + { .master = 0, .csi = RVIN_CSI40, .chsel = 0x03 }, + { .master = 4, .csi = RVIN_CSI20, .chsel = 0x04 }, + { .master = 4, .csi = RVIN_CSI40, .chsel = 0x03 }, { /* Sentinel */ } }; @@ -1379,13 +1238,7 @@ static const struct rvin_info rcar_info_r8a77965 = { }; static const struct rvin_group_route rcar_info_r8a77970_routes[] = { - { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(3) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) }, - { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) }, + { .master = 0, .csi = RVIN_CSI40, .chsel = 0x03 }, { /* Sentinel */ } }; @@ -1398,22 +1251,8 @@ static const struct rvin_info rcar_info_r8a77970 = { }; static const struct rvin_group_route rcar_info_r8a77980_routes[] = { - { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) }, - { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) }, - { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) }, - { .csi = RVIN_CSI41, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI41, .channel = 1, .vin = 4, .mask = BIT(2) }, - { .csi = RVIN_CSI41, .channel = 0, .vin = 5, .mask = BIT(2) }, - { .csi = RVIN_CSI41, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) }, - { .csi = RVIN_CSI41, .channel = 0, .vin = 6, .mask = BIT(1) }, - { .csi = RVIN_CSI41, .channel = 2, .vin = 6, .mask = BIT(3) }, - { .csi = RVIN_CSI41, .channel = 1, .vin = 7, .mask = BIT(0) }, - { .csi = RVIN_CSI41, .channel = 3, .vin = 7, .mask = BIT(3) }, + { .master = 0, .csi = RVIN_CSI40, .chsel = 0x03 }, + { .master = 4, .csi = RVIN_CSI41, .chsel = 0x03 }, { /* Sentinel */ } }; @@ -1427,10 +1266,7 @@ static const struct rvin_info rcar_info_r8a77980 = { }; static const struct rvin_group_route rcar_info_r8a77990_routes[] = { - { .csi = RVIN_CSI40, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) }, - { .csi = RVIN_CSI40, .channel = 0, .vin = 5, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 4, .mask = BIT(2) }, - { .csi = RVIN_CSI40, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) }, + { .master = 0, .csi = RVIN_CSI40, .chsel = 0x03 }, { /* Sentinel */ } }; diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index 11848d0c4a55cb4c..b8c56d248454efbf 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -468,6 +468,8 @@ struct rcar_csi2 { struct v4l2_subdev *remote; unsigned int remote_pad; + int channel_vc[4]; + struct mutex lock; /* Protects mf and stream_count. */ struct v4l2_mbus_framefmt mf; int stream_count; @@ -664,8 +666,11 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv) for (i = 0; i < priv->info->num_channels; i++) { u32 vcdt_part; - vcdt_part = VCDT_SEL_VC(i) | VCDT_VCDTN_EN | VCDT_SEL_DTN_ON | - VCDT_SEL_DT(format->datatype); + if (priv->channel_vc[i] < 0) + continue; + + vcdt_part = VCDT_SEL_VC(priv->channel_vc[i]) | VCDT_VCDTN_EN | + VCDT_SEL_DTN_ON | VCDT_SEL_DT(format->datatype); /* Store in correct reg and offset. */ if (i < 2) @@ -1240,7 +1245,53 @@ static int rcsi2_init_phtw_v3u(struct rcar_csi2 *priv, * Platform Device Driver. */ +static int rcsi2_link_setup(struct media_entity *entity, + const struct media_pad *local, + const struct media_pad *remote, u32 flags) +{ + struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); + struct rcar_csi2 *priv = sd_to_csi2(sd); + struct video_device *vdev; + int channel, vc; + u32 id; + + if (!is_media_entity_v4l2_video_device(remote->entity)) { + dev_err(priv->dev, "Remote is not a video device\n"); + return -EINVAL; + } + + vdev = media_entity_to_video_device(remote->entity); + + if (of_property_read_u32(vdev->dev_parent->of_node, "renesas,id", &id)) { + dev_err(priv->dev, "No renesas,id, can't configure routing\n"); + return -EINVAL; + } + + channel = id % 4; + + if (flags & MEDIA_LNK_FL_ENABLED) { + if (media_entity_remote_pad(local)) { + dev_dbg(priv->dev, + "Each VC can only be routed to one output channel\n"); + return -EINVAL; + } + + vc = local->index - 1; + + dev_dbg(priv->dev, "Route VC%d to VIN%u on output channel %d\n", + vc, id, channel); + } else { + vc = -1; + } + + priv->channel_vc[channel] = vc; + + return 0; +} + + static const struct media_entity_operations rcar_csi2_entity_ops = { + .link_setup = rcsi2_link_setup, .link_validate = v4l2_subdev_link_validate, }; @@ -1459,6 +1510,9 @@ static int rcsi2_probe(struct platform_device *pdev) if (ret) goto error_async; + for (i = 0; i < ARRAY_SIZE(priv->channel_vc); i++) + priv->channel_vc[i] = -1; + pm_runtime_enable(&pdev->dev); ret = v4l2_async_register_subdev(&priv->subdev); diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c index 25ead9333d0046e7..b72ae27a407dc96c 100644 --- a/drivers/media/platform/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/rcar-vin/rcar-dma.c @@ -1490,7 +1490,7 @@ int rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel) * register. IFMD_DES1 controls data expansion mode for CSI20/21, * IFMD_DES0 controls data expansion mode for CSI40/41. */ - for (route = vin->info->routes; route->mask; route++) { + for (route = vin->info->routes; route->chsel; route++) { if (route->csi == RVIN_CSI20 || route->csi == RVIN_CSI21) ifmd |= VNCSI_IFMD_DES1; else diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h index 6c06320174a2ed96..ddc1830be9a5d6c3 100644 --- a/drivers/media/platform/rcar-vin/rcar-vin.h +++ b/drivers/media/platform/rcar-vin/rcar-vin.h @@ -128,11 +128,9 @@ struct rvin_parallel_entity { * struct rvin_group_route - describes a route from a channel of a * CSI-2 receiver to a VIN * + * @master: VIN group master ID. * @csi: CSI-2 receiver ID. - * @channel: Output channel of the CSI-2 receiver. - * @vin: VIN ID. - * @mask: Bitmask of the different CHSEL register values that - * allow for a route from @csi + @chan to @vin. + * @chsel: CHSEL register values that connects VIN group to CSI-2. * * .. note:: * Each R-Car CSI-2 receiver has four output channels facing the VIN @@ -140,19 +138,11 @@ struct rvin_parallel_entity { * There is no correlation between channel number and CSI-2 VC. It's * up to the CSI-2 receiver driver to configure which VC is output * on which channel, the VIN devices only care about output channels. - * - * There are in some cases multiple CHSEL register settings which would - * allow for the same route from @csi + @channel to @vin. For example - * on R-Car H3 both the CHSEL values 0 and 3 allow for a route from - * CSI40/VC0 to VIN0. All possible CHSEL values for a route need to be - * recorded as a bitmask in @mask, in this example bit 0 and 3 should - * be set. */ struct rvin_group_route { + unsigned int master; enum rvin_csi_id csi; - unsigned int channel; - unsigned int vin; - unsigned int mask; + unsigned int chsel; }; /**