From patchwork Wed Feb 16 21:04:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12749051 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 E18A4C433F5 for ; Wed, 16 Feb 2022 21:04:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233705AbiBPVEL (ORCPT ); Wed, 16 Feb 2022 16:04:11 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:52406 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234064AbiBPVEI (ORCPT ); Wed, 16 Feb 2022 16:04:08 -0500 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::228]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E82742B0B23; Wed, 16 Feb 2022 13:03:47 -0800 (PST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id C478E1BF209; Wed, 16 Feb 2022 21:03:44 +0000 (UTC) From: Jacopo Mondi To: niklas.soderlund@ragnatech.se, laurent.pinchart@ideasonboard.com Cc: Jacopo Mondi , tomi.valkeinen@ideasonboard.com, linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH 01/10] media: adv748x: Add flags to adv748x_subdev_init() Date: Wed, 16 Feb 2022 22:04:38 +0100 Message-Id: <20220216210447.481006-2-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.35.0 In-Reply-To: <20220216210447.481006-1-jacopo+renesas@jmondi.org> References: <20220216210447.481006-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org Add a flags parameter to the adv748x_subdev_init() function that allows to pass additional flags to the v4l2_subdevice. This will be used to identify the CSI-2 subdevices as multiplexed. Signed-off-by: Jacopo Mondi --- drivers/media/i2c/adv748x/adv748x-afe.c | 2 +- drivers/media/i2c/adv748x/adv748x-core.c | 4 ++-- drivers/media/i2c/adv748x/adv748x-csi2.c | 2 +- drivers/media/i2c/adv748x/adv748x-hdmi.c | 2 +- drivers/media/i2c/adv748x/adv748x.h | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/i2c/adv748x/adv748x-afe.c b/drivers/media/i2c/adv748x/adv748x-afe.c index 02eabe10ab97..0d05e8a8887f 100644 --- a/drivers/media/i2c/adv748x/adv748x-afe.c +++ b/drivers/media/i2c/adv748x/adv748x-afe.c @@ -510,7 +510,7 @@ int adv748x_afe_init(struct adv748x_afe *afe) afe->curr_norm = V4L2_STD_NTSC_M; adv748x_subdev_init(&afe->sd, state, &adv748x_afe_ops, - MEDIA_ENT_F_ATV_DECODER, "afe"); + MEDIA_ENT_F_ATV_DECODER, 0, "afe"); /* Identify the first connector found as a default input if set */ for (i = ADV748X_PORT_AIN0; i <= ADV748X_PORT_AIN7; i++) { diff --git a/drivers/media/i2c/adv748x/adv748x-core.c b/drivers/media/i2c/adv748x/adv748x-core.c index 4e54148147b9..0961b1468465 100644 --- a/drivers/media/i2c/adv748x/adv748x-core.c +++ b/drivers/media/i2c/adv748x/adv748x-core.c @@ -583,10 +583,10 @@ static int __maybe_unused adv748x_resume_early(struct device *dev) void adv748x_subdev_init(struct v4l2_subdev *sd, struct adv748x_state *state, const struct v4l2_subdev_ops *ops, u32 function, - const char *ident) + u32 flags, const char *ident) { v4l2_subdev_init(sd, ops); - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | flags; /* the owner is the same as the i2c_client's driver owner */ sd->owner = state->dev->driver->owner; diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c b/drivers/media/i2c/adv748x/adv748x-csi2.c index 589e9644fcdc..6cbb47a715ab 100644 --- a/drivers/media/i2c/adv748x/adv748x-csi2.c +++ b/drivers/media/i2c/adv748x/adv748x-csi2.c @@ -313,7 +313,7 @@ int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx) return 0; adv748x_subdev_init(&tx->sd, state, &adv748x_csi2_ops, - MEDIA_ENT_F_VID_IF_BRIDGE, + MEDIA_ENT_F_VID_IF_BRIDGE, 0, is_txa(tx) ? "txa" : "txb"); /* Ensure that matching is based upon the endpoint fwnodes */ diff --git a/drivers/media/i2c/adv748x/adv748x-hdmi.c b/drivers/media/i2c/adv748x/adv748x-hdmi.c index 52fa7bd75660..535a21b3c350 100644 --- a/drivers/media/i2c/adv748x/adv748x-hdmi.c +++ b/drivers/media/i2c/adv748x/adv748x-hdmi.c @@ -732,7 +732,7 @@ int adv748x_hdmi_init(struct adv748x_hdmi *hdmi) hdmi->aspect_ratio.denominator = 9; adv748x_subdev_init(&hdmi->sd, state, &adv748x_ops_hdmi, - MEDIA_ENT_F_IO_DTV, "hdmi"); + MEDIA_ENT_F_IO_DTV, 0, "hdmi"); hdmi->pads[ADV748X_HDMI_SINK].flags = MEDIA_PAD_FL_SINK; hdmi->pads[ADV748X_HDMI_SOURCE].flags = MEDIA_PAD_FL_SOURCE; diff --git a/drivers/media/i2c/adv748x/adv748x.h b/drivers/media/i2c/adv748x/adv748x.h index 31bac06d46b5..92c8caee6a42 100644 --- a/drivers/media/i2c/adv748x/adv748x.h +++ b/drivers/media/i2c/adv748x/adv748x.h @@ -426,7 +426,7 @@ static inline struct v4l2_subdev *adv748x_get_remote_sd(struct media_pad *pad) void adv748x_subdev_init(struct v4l2_subdev *sd, struct adv748x_state *state, const struct v4l2_subdev_ops *ops, u32 function, - const char *ident); + u32 flags, const char *ident); int adv748x_register_subdevs(struct adv748x_state *state, struct v4l2_device *v4l2_dev); From patchwork Wed Feb 16 21:04:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12749053 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 E22A5C433EF for ; Wed, 16 Feb 2022 21:04:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233504AbiBPVES (ORCPT ); Wed, 16 Feb 2022 16:04:18 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:53002 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234096AbiBPVEI (ORCPT ); Wed, 16 Feb 2022 16:04:08 -0500 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3761E2221BC; Wed, 16 Feb 2022 13:03:48 -0800 (PST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 8754D1BF204; Wed, 16 Feb 2022 21:03:46 +0000 (UTC) From: Jacopo Mondi To: niklas.soderlund@ragnatech.se, laurent.pinchart@ideasonboard.com Cc: Jacopo Mondi , tomi.valkeinen@ideasonboard.com, linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH 02/10] media: adv748x: Add support for v4l2_subdev_state Date: Wed, 16 Feb 2022 22:04:39 +0100 Message-Id: <20220216210447.481006-3-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.35.0 In-Reply-To: <20220216210447.481006-1-jacopo+renesas@jmondi.org> References: <20220216210447.481006-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org Create and initialize the v4l2_subdev_state for the adv748x CSI-2 subdevice in order to prepare to support routing of the video stream. Create the subdevice state with v4l2_subdev_init_finalize() and implement the init_cfg() operation to guarantee the state is initialized correctly with the default routing set. Signed-off-by: Jacopo Mondi --- drivers/media/i2c/adv748x/adv748x-csi2.c | 57 +++++++++++++++++++++++- drivers/media/i2c/adv748x/adv748x.h | 3 ++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c b/drivers/media/i2c/adv748x/adv748x-csi2.c index 6cbb47a715ab..9061c34ba561 100644 --- a/drivers/media/i2c/adv748x/adv748x-csi2.c +++ b/drivers/media/i2c/adv748x/adv748x-csi2.c @@ -139,6 +139,50 @@ static const struct v4l2_subdev_video_ops adv748x_csi2_video_ops = { * But we must support setting the pad formats for format propagation. */ +static int adv748x_csi2_init_cfg(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state) +{ + /* One route for each virtual channel. Route 0 enabled by default. */ + struct v4l2_subdev_route routes[ADV748X_CSI2_STREAMS] = { + { + .sink_pad = ADV748X_CSI2_SINK, + .sink_stream = 0, + .source_pad = ADV748X_CSI2_SOURCE, + .source_stream = 0, + .flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE, + }, + { + .sink_pad = ADV748X_CSI2_SINK, + .sink_stream = 0, + .source_pad = ADV748X_CSI2_SOURCE, + .source_stream = 1, + }, + { + .sink_pad = ADV748X_CSI2_SINK, + .sink_stream = 0, + .source_pad = ADV748X_CSI2_SOURCE, + .source_stream = 2, + }, + { + .sink_pad = ADV748X_CSI2_SINK, + .sink_stream = 0, + .source_pad = ADV748X_CSI2_SOURCE, + .source_stream = 3, + }, + }; + struct v4l2_subdev_krouting routing; + int ret; + + routing.num_routes = ADV748X_CSI2_STREAMS; + routing.routes = routes; + + v4l2_subdev_lock_state(state); + ret = v4l2_subdev_set_routing(sd, state, &routing); + v4l2_subdev_unlock_state(state); + + return ret; +} + static struct v4l2_mbus_framefmt * adv748x_csi2_get_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, @@ -244,6 +288,7 @@ static int adv748x_csi2_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad } static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = { + .init_cfg = adv748x_csi2_init_cfg, .get_fmt = adv748x_csi2_get_format, .set_fmt = adv748x_csi2_set_format, .get_mbus_config = adv748x_csi2_get_mbus_config, @@ -313,7 +358,8 @@ int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx) return 0; adv748x_subdev_init(&tx->sd, state, &adv748x_csi2_ops, - MEDIA_ENT_F_VID_IF_BRIDGE, 0, + MEDIA_ENT_F_VID_IF_BRIDGE, + V4L2_SUBDEV_FL_MULTIPLEXED, is_txa(tx) ? "txa" : "txb"); /* Ensure that matching is based upon the endpoint fwnodes */ @@ -330,10 +376,14 @@ int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx) if (ret) return ret; - ret = adv748x_csi2_init_controls(tx); + ret = v4l2_subdev_init_finalize(&tx->sd); if (ret) goto err_free_media; + ret = adv748x_csi2_init_controls(tx); + if (ret) + goto err_free_state; + ret = v4l2_async_register_subdev(&tx->sd); if (ret) goto err_free_ctrl; @@ -342,6 +392,8 @@ int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx) err_free_ctrl: v4l2_ctrl_handler_free(&tx->ctrl_hdl); +err_free_state: + v4l2_subdev_cleanup(&tx->sd); err_free_media: media_entity_cleanup(&tx->sd.entity); @@ -354,6 +406,7 @@ void adv748x_csi2_cleanup(struct adv748x_csi2 *tx) return; v4l2_async_unregister_subdev(&tx->sd); + v4l2_subdev_cleanup(&tx->sd); media_entity_cleanup(&tx->sd.entity); v4l2_ctrl_handler_free(&tx->ctrl_hdl); } diff --git a/drivers/media/i2c/adv748x/adv748x.h b/drivers/media/i2c/adv748x/adv748x.h index 92c8caee6a42..d651c8390e6f 100644 --- a/drivers/media/i2c/adv748x/adv748x.h +++ b/drivers/media/i2c/adv748x/adv748x.h @@ -73,6 +73,9 @@ enum adv748x_csi2_pads { /* CSI2 transmitters can have 2 internal connections, HDMI/AFE */ #define ADV748X_CSI2_MAX_SUBDEVS 2 +/* CSI2 number of streams: 1 for each CSI-2 Virtual channel output. */ +#define ADV748X_CSI2_STREAMS 4 + struct adv748x_csi2 { struct adv748x_state *state; struct v4l2_mbus_framefmt format; From patchwork Wed Feb 16 21:04:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12749054 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 E161EC433EF for ; Wed, 16 Feb 2022 21:04:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234599AbiBPVEc (ORCPT ); Wed, 16 Feb 2022 16:04:32 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:53012 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234149AbiBPVEI (ORCPT ); Wed, 16 Feb 2022 16:04:08 -0500 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::228]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 979AF2B0B26; Wed, 16 Feb 2022 13:03:50 -0800 (PST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id EF3BC1BF20C; Wed, 16 Feb 2022 21:03:47 +0000 (UTC) From: Jacopo Mondi To: niklas.soderlund@ragnatech.se, laurent.pinchart@ideasonboard.com Cc: Jacopo Mondi , tomi.valkeinen@ideasonboard.com, linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH 03/10] media: adv748x: Move format to subdev state Date: Wed, 16 Feb 2022 22:04:40 +0100 Message-Id: <20220216210447.481006-4-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.35.0 In-Reply-To: <20220216210447.481006-1-jacopo+renesas@jmondi.org> References: <20220216210447.481006-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org Move format handling to the v4l2_subdev state and store it per (pad, stream) combination. Now that the image format is stored in the subdev state, it can be accessed through v4l2_subdev_get_fmt() instead of open-coding it. Signed-off-by: Jacopo Mondi --- drivers/media/i2c/adv748x/adv748x-csi2.c | 83 +++++++----------------- drivers/media/i2c/adv748x/adv748x.h | 1 - 2 files changed, 22 insertions(+), 62 deletions(-) diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c b/drivers/media/i2c/adv748x/adv748x-csi2.c index 9061c34ba561..549c3cd96006 100644 --- a/drivers/media/i2c/adv748x/adv748x-csi2.c +++ b/drivers/media/i2c/adv748x/adv748x-csi2.c @@ -183,76 +183,37 @@ static int adv748x_csi2_init_cfg(struct v4l2_subdev *sd, return ret; } -static struct v4l2_mbus_framefmt * -adv748x_csi2_get_pad_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - unsigned int pad, u32 which) -{ - struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); - - if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_format(sd, sd_state, pad); - - return &tx->format; -} - -static int adv748x_csi2_get_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *sdformat) -{ - struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); - struct adv748x_state *state = tx->state; - struct v4l2_mbus_framefmt *mbusformat; - - mbusformat = adv748x_csi2_get_pad_format(sd, sd_state, sdformat->pad, - sdformat->which); - if (!mbusformat) - return -EINVAL; - - mutex_lock(&state->mutex); - - sdformat->format = *mbusformat; - - mutex_unlock(&state->mutex); - - return 0; -} - static int adv748x_csi2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *sdformat) { - struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); - struct adv748x_state *state = tx->state; - struct v4l2_mbus_framefmt *mbusformat; + struct v4l2_mbus_framefmt *fmt; int ret = 0; - mbusformat = adv748x_csi2_get_pad_format(sd, sd_state, sdformat->pad, - sdformat->which); - if (!mbusformat) + /* Do not allow to set format on the multiplexed source pad. */ + if (sdformat->pad == ADV748X_CSI2_SOURCE) return -EINVAL; - mutex_lock(&state->mutex); - - if (sdformat->pad == ADV748X_CSI2_SOURCE) { - const struct v4l2_mbus_framefmt *sink_fmt; - - sink_fmt = adv748x_csi2_get_pad_format(sd, sd_state, - ADV748X_CSI2_SINK, - sdformat->which); - - if (!sink_fmt) { - ret = -EINVAL; - goto unlock; - } - - sdformat->format = *sink_fmt; + v4l2_subdev_lock_state(sd_state); + fmt = v4l2_state_get_stream_format(sd_state, sdformat->pad, + sdformat->stream); + if (!fmt) { + ret = -EINVAL; + goto out; + }; + *fmt = sdformat->format; + + /* Propagate format to the other end of the route. */ + fmt = v4l2_subdev_state_get_opposite_stream_format(sd_state, sdformat->pad, + sdformat->stream); + if (!fmt) { + ret = -EINVAL; + goto out; } + *fmt = sdformat->format; - *mbusformat = sdformat->format; - -unlock: - mutex_unlock(&state->mutex); +out: + v4l2_subdev_unlock_state(sd_state); return ret; } @@ -289,7 +250,7 @@ static int adv748x_csi2_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = { .init_cfg = adv748x_csi2_init_cfg, - .get_fmt = adv748x_csi2_get_format, + .get_fmt = v4l2_subdev_get_fmt, .set_fmt = adv748x_csi2_set_format, .get_mbus_config = adv748x_csi2_get_mbus_config, }; diff --git a/drivers/media/i2c/adv748x/adv748x.h b/drivers/media/i2c/adv748x/adv748x.h index d651c8390e6f..98a3b3e0642a 100644 --- a/drivers/media/i2c/adv748x/adv748x.h +++ b/drivers/media/i2c/adv748x/adv748x.h @@ -78,7 +78,6 @@ enum adv748x_csi2_pads { struct adv748x_csi2 { struct adv748x_state *state; - struct v4l2_mbus_framefmt format; unsigned int page; unsigned int port; unsigned int num_lanes; From patchwork Wed Feb 16 21:04:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12749061 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 939A7C433F5 for ; Wed, 16 Feb 2022 21:04:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234296AbiBPVFD (ORCPT ); Wed, 16 Feb 2022 16:05:03 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:53016 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234157AbiBPVEI (ORCPT ); Wed, 16 Feb 2022 16:04:08 -0500 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DF2A52B0B2E; Wed, 16 Feb 2022 13:03:51 -0800 (PST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 69F071BF208; Wed, 16 Feb 2022 21:03:49 +0000 (UTC) From: Jacopo Mondi To: niklas.soderlund@ragnatech.se, laurent.pinchart@ideasonboard.com Cc: Jacopo Mondi , tomi.valkeinen@ideasonboard.com, linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH 04/10] media: adv748x: Implement .get_frame_desc() Date: Wed, 16 Feb 2022 22:04:41 +0100 Message-Id: <20220216210447.481006-5-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.35.0 In-Reply-To: <20220216210447.481006-1-jacopo+renesas@jmondi.org> References: <20220216210447.481006-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org Implement the get_frame_desc subdev pad operation. Implement the get_frame_desc pad operation to allow retrieving the stream configuration of the adv748x csi2 subdevice. Signed-off-by: Jacopo Mondi --- drivers/media/i2c/adv748x/adv748x-csi2.c | 93 ++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c b/drivers/media/i2c/adv748x/adv748x-csi2.c index 549c3cd96006..9824ebe44eb1 100644 --- a/drivers/media/i2c/adv748x/adv748x-csi2.c +++ b/drivers/media/i2c/adv748x/adv748x-csi2.c @@ -14,6 +14,50 @@ #include "adv748x.h" +/* Describes a format bit depth and CSI-2 defined Data Type. */ +struct adv748x_csi2_format_info { + u8 dt; + u8 bpp; +}; + +static int adv748x_csi2_get_format_info(struct adv748x_csi2 *tx, + u32 mbus_code, + struct adv748x_csi2_format_info *fmt) +{ + switch (mbus_code) { + case MEDIA_BUS_FMT_YUYV8_1X16: + case MEDIA_BUS_FMT_YUYV8_2X8: + fmt->dt = 0x1e; + fmt->bpp = 16; + break; + case MEDIA_BUS_FMT_YUYV10_2X10: + case MEDIA_BUS_FMT_YUYV10_1X20: + fmt->dt = 0x1f; + fmt->bpp = 20; + break; + case MEDIA_BUS_FMT_RGB565_1X16: + case MEDIA_BUS_FMT_RGB565_2X8_LE: + case MEDIA_BUS_FMT_RGB565_2X8_BE: + fmt->dt = 0x22; + fmt->bpp = 16; + break; + case MEDIA_BUS_FMT_RGB666_1X18: + fmt->dt = 0x23; + fmt->bpp = 18; + break; + case MEDIA_BUS_FMT_RGB888_1X24: + fmt->dt = 0x24; + fmt->bpp = 24; + break; + default: + dev_err(tx->state->dev, + "Unsupported media bus code: %u\n", mbus_code); + return -EINVAL; + } + + return 0; +} + int adv748x_csi2_set_virtual_channel(struct adv748x_csi2 *tx, unsigned int vc) { return tx_write(tx, ADV748X_CSI_VC_REF, vc << ADV748X_CSI_VC_REF_SHIFT); @@ -248,11 +292,60 @@ static int adv748x_csi2_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad return 0; } +static int adv748x_csi2_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, + struct v4l2_mbus_frame_desc *fd) +{ + struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); + struct adv748x_csi2_format_info info = {}; + struct v4l2_mbus_frame_desc_entry *entry; + struct v4l2_subdev_route *route; + struct v4l2_subdev_state *state; + struct v4l2_mbus_framefmt *fmt; + int ret; + + if (pad != ADV748X_CSI2_SOURCE) + return -EINVAL; + + state = v4l2_subdev_lock_active_state(sd); + + /* A single route is available. */ + route = &state->routing.routes[0]; + fmt = v4l2_state_get_stream_format(state, pad, route->source_stream); + if (!fmt) { + ret = -EINVAL; + goto out; + } + + ret = adv748x_csi2_get_format_info(tx, fmt->code, &info); + if (ret) + goto out; + + memset(fd, 0, sizeof(*fd)); + + /* A single stream is available. */ + fd->num_entries = 1; + fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2; + + entry = &fd->entry[0]; + entry->stream = 0; + entry->flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX; + entry->length = fmt->width * fmt->height * info.bpp / 8; + entry->pixelcode = fmt->code; + entry->bus.csi2.vc = route->source_stream; + entry->bus.csi2.dt = info.dt; + +out: + v4l2_subdev_unlock_state(state); + + return ret; +} + static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = { .init_cfg = adv748x_csi2_init_cfg, .get_fmt = v4l2_subdev_get_fmt, .set_fmt = adv748x_csi2_set_format, .get_mbus_config = adv748x_csi2_get_mbus_config, + .get_frame_desc = adv748x_csi2_get_frame_desc, }; /* ----------------------------------------------------------------------------- From patchwork Wed Feb 16 21:04:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12749055 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 12FF6C433FE for ; Wed, 16 Feb 2022 21:04:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234135AbiBPVEd (ORCPT ); Wed, 16 Feb 2022 16:04:33 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:52898 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234183AbiBPVEI (ORCPT ); Wed, 16 Feb 2022 16:04:08 -0500 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::228]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8A3992B1005; Wed, 16 Feb 2022 13:03:53 -0800 (PST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id DDEB81BF206; Wed, 16 Feb 2022 21:03:50 +0000 (UTC) From: Jacopo Mondi To: niklas.soderlund@ragnatech.se, laurent.pinchart@ideasonboard.com Cc: Jacopo Mondi , tomi.valkeinen@ideasonboard.com, linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH 05/10] media: adv748x: Implement set_routing Date: Wed, 16 Feb 2022 22:04:42 +0100 Message-Id: <20220216210447.481006-6-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.35.0 In-Reply-To: <20220216210447.481006-1-jacopo+renesas@jmondi.org> References: <20220216210447.481006-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org Add the set_routing() subdev operation to allow userspace to configure the CSI-2 virtual channel. Signed-off-by: Jacopo Mondi --- drivers/media/i2c/adv748x/adv748x-csi2.c | 73 ++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c b/drivers/media/i2c/adv748x/adv748x-csi2.c index 9824ebe44eb1..bf927898b918 100644 --- a/drivers/media/i2c/adv748x/adv748x-csi2.c +++ b/drivers/media/i2c/adv748x/adv748x-csi2.c @@ -340,12 +340,85 @@ static int adv748x_csi2_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, return ret; } +static int adv748x_csi2_routing_validate(struct adv748x_csi2 *tx, + struct v4l2_subdev_krouting *routing) +{ + struct v4l2_subdev_route *route; + + if (routing->num_routes != 1) { + dev_err(tx->state->dev, "Unsupported number of routes %u", + routing->num_routes); + return -EINVAL; + } + + route = &routing->routes[0]; + + if (route->sink_pad != ADV748X_CSI2_SINK || + route->source_pad != ADV748X_CSI2_SOURCE) { + dev_err(tx->state->dev, + "Routes should go from the sink to the source pads.\n"); + return -EINVAL; + } + + if (route->source_stream > 4) { + dev_err(tx->state->dev, "Unsupported source stream %u\n", + route->source_stream); + return -EINVAL; + } + + if (route->sink_stream != 0) { + dev_err(tx->state->dev, "Unsupported sink stream %u\n", + route->sink_stream); + return -EINVAL; + } + + return 0; +} + +static int adv748x_csi2_set_vc_with_routing(struct adv748x_csi2 *tx, + struct v4l2_subdev_krouting *routing) +{ + struct v4l2_subdev_route *route = &routing->routes[0]; + + return adv748x_csi2_set_virtual_channel(tx, route->source_stream); +} + +static int adv748x_csi2_set_routing(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + enum v4l2_subdev_format_whence which, + struct v4l2_subdev_krouting *routing) +{ + struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); + int ret; + + v4l2_subdev_lock_state(state); + + ret = adv748x_csi2_routing_validate(tx, routing); + if (ret) + goto out; + + ret = v4l2_subdev_set_routing(sd, state, routing); + if (ret) + goto out; + + if (which == V4L2_SUBDEV_FORMAT_TRY) + goto out; + + ret = adv748x_csi2_set_vc_with_routing(tx, routing); + +out: + v4l2_subdev_unlock_state(state); + + return ret; +} + static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = { .init_cfg = adv748x_csi2_init_cfg, .get_fmt = v4l2_subdev_get_fmt, .set_fmt = adv748x_csi2_set_format, .get_mbus_config = adv748x_csi2_get_mbus_config, .get_frame_desc = adv748x_csi2_get_frame_desc, + .set_routing = adv748x_csi2_set_routing, }; /* ----------------------------------------------------------------------------- From patchwork Wed Feb 16 21:04:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12749060 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 15122C3526C for ; Wed, 16 Feb 2022 21:04:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233717AbiBPVEg (ORCPT ); Wed, 16 Feb 2022 16:04:36 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:51234 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234189AbiBPVEI (ORCPT ); Wed, 16 Feb 2022 16:04:08 -0500 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::228]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E52DF2AFE9D; Wed, 16 Feb 2022 13:03:54 -0800 (PST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 567B81BF204; Wed, 16 Feb 2022 21:03:52 +0000 (UTC) From: Jacopo Mondi To: niklas.soderlund@ragnatech.se, laurent.pinchart@ideasonboard.com Cc: Jacopo Mondi , tomi.valkeinen@ideasonboard.com, linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH 06/10] media: rcar-csi2: Add support for multiplexed streams Date: Wed, 16 Feb 2022 22:04:43 +0100 Message-Id: <20220216210447.481006-7-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.35.0 In-Reply-To: <20220216210447.481006-1-jacopo+renesas@jmondi.org> References: <20220216210447.481006-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org Create and initialize the v4l2_subdev_state for the R-Car CSI-2 receiver in order to prepare to support multiplexed transmitters. Create the subdevice state with v4l2_subdev_init_finalize() and implement the init_cfg() operation to guarantee the state is initialized correctly with a set of default routes. Signed-off-by: Jacopo Mondi --- drivers/media/platform/rcar-vin/rcar-csi2.c | 74 ++++++++++++++++++++- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index b8c56d248454..e8a79a30cc49 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -875,11 +875,73 @@ static int rcsi2_get_pad_format(struct v4l2_subdev *sd, return 0; } +static int rcsi2_init_cfg(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state) +{ + /* + * Routing is fixed for this device: which stream goes to the next + * processing block (VIN) is controlled by link enablement between the + * CSI-2 and the VIN itself. + * + * In example, to route VC 3 to VIN1, as an example: "csi2:3 -> vin1:0" + * + * The routing table is then fixed as streams transmitted on VC x will + * be directed to csi:0/x and will be transmitted to VINs on media link + * csi2:x->vin:0. + */ + struct v4l2_subdev_route routes[] = { + { + .sink_pad = RCAR_CSI2_SINK, + .sink_stream = 0, + .source_pad = RCAR_CSI2_SOURCE_VC0, + .source_stream = 0, + .flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE, + }, + { + .sink_pad = RCAR_CSI2_SINK, + .sink_stream = 1, + .source_pad = RCAR_CSI2_SOURCE_VC1, + .source_stream = 0, + .flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE, + }, + { + .sink_pad = RCAR_CSI2_SINK, + .sink_stream = 2, + .source_pad = RCAR_CSI2_SOURCE_VC2, + .source_stream = 0, + .flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE, + }, + { + .sink_pad = RCAR_CSI2_SINK, + .sink_stream = 3, + .source_pad = RCAR_CSI2_SOURCE_VC3, + .source_stream = 0, + .flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE, + }, + }; + + struct v4l2_subdev_krouting routing = { + .num_routes = ARRAY_SIZE(routes), + .routes = routes, + }; + + int ret = v4l2_subdev_routing_validate_1_to_1(&routing); + if (ret) + return ret; + + v4l2_subdev_lock_state(state); + ret = v4l2_subdev_set_routing(sd, state, &routing); + v4l2_subdev_unlock_state(state); + + return ret; +} + static const struct v4l2_subdev_video_ops rcar_csi2_video_ops = { .s_stream = rcsi2_s_stream, }; static const struct v4l2_subdev_pad_ops rcar_csi2_pad_ops = { + .init_cfg = rcsi2_init_cfg, .set_fmt = rcsi2_set_pad_format, .get_fmt = rcsi2_get_pad_format, }; @@ -1494,7 +1556,8 @@ static int rcsi2_probe(struct platform_device *pdev) v4l2_set_subdevdata(&priv->subdev, &pdev->dev); snprintf(priv->subdev.name, V4L2_SUBDEV_NAME_SIZE, "%s %s", KBUILD_MODNAME, dev_name(&pdev->dev)); - priv->subdev.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; + priv->subdev.flags = V4L2_SUBDEV_FL_HAS_DEVNODE | + V4L2_SUBDEV_FL_MULTIPLEXED; priv->subdev.entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER; priv->subdev.entity.ops = &rcar_csi2_entity_ops; @@ -1515,14 +1578,20 @@ static int rcsi2_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); + ret = v4l2_subdev_init_finalize(&priv->subdev); + if (ret) + goto error_async; + ret = v4l2_async_register_subdev(&priv->subdev); if (ret < 0) - goto error_async; + goto error_subdev; dev_info(priv->dev, "%d lanes found\n", priv->lanes); return 0; +error_subdev: + v4l2_subdev_cleanup(&priv->subdev); error_async: v4l2_async_nf_unregister(&priv->notifier); v4l2_async_nf_cleanup(&priv->notifier); @@ -1539,6 +1608,7 @@ static int rcsi2_remove(struct platform_device *pdev) v4l2_async_nf_unregister(&priv->notifier); v4l2_async_nf_cleanup(&priv->notifier); v4l2_async_unregister_subdev(&priv->subdev); + v4l2_subdev_cleanup(&priv->subdev); pm_runtime_disable(&pdev->dev); From patchwork Wed Feb 16 21:04:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12749056 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 5A268C43217 for ; Wed, 16 Feb 2022 21:04:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234839AbiBPVEe (ORCPT ); Wed, 16 Feb 2022 16:04:34 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:52388 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233855AbiBPVEJ (ORCPT ); Wed, 16 Feb 2022 16:04:09 -0500 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::228]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 657872AFE9F; Wed, 16 Feb 2022 13:03:56 -0800 (PST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id D37181BF205; Wed, 16 Feb 2022 21:03:53 +0000 (UTC) From: Jacopo Mondi To: niklas.soderlund@ragnatech.se, laurent.pinchart@ideasonboard.com Cc: Jacopo Mondi , tomi.valkeinen@ideasonboard.com, linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH 07/10] media: rcar-csi2: Move format to subdev state Date: Wed, 16 Feb 2022 22:04:44 +0100 Message-Id: <20220216210447.481006-8-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.35.0 In-Reply-To: <20220216210447.481006-1-jacopo+renesas@jmondi.org> References: <20220216210447.481006-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org Move format handling to the v4l2_subdev state and store it per (pad, stream) combination. Now that the image format is stored in the subdev state, it can be accessed through v4l2_subdev_get_fmt() instead of open-coding it. Signed-off-by: Jacopo Mondi --- drivers/media/platform/rcar-vin/rcar-csi2.c | 58 ++++++++++----------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index e8a79a30cc49..a0642cafd70b 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -834,45 +834,45 @@ static int rcsi2_s_stream(struct v4l2_subdev *sd, int enable) } static int rcsi2_set_pad_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_state *state, struct v4l2_subdev_format *format) { - struct rcar_csi2 *priv = sd_to_csi2(sd); - struct v4l2_mbus_framefmt *framefmt; + struct v4l2_mbus_framefmt *fmt; + int ret = 0; - mutex_lock(&priv->lock); + /* + * Format is propagated from sink streams to source streams, so + * disallow setting format on the source pads. + */ + if (format->pad > RCAR_CSI2_SINK) + return -EINVAL; if (!rcsi2_code_to_fmt(format->format.code)) format->format.code = rcar_csi2_formats[0].code; - if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) { - priv->mf = format->format; - } else { - framefmt = v4l2_subdev_get_try_format(sd, sd_state, 0); - *framefmt = format->format; - } - - mutex_unlock(&priv->lock); - - return 0; -} - -static int rcsi2_get_pad_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *format) -{ - struct rcar_csi2 *priv = sd_to_csi2(sd); + v4l2_subdev_lock_state(state); - mutex_lock(&priv->lock); + fmt = v4l2_state_get_stream_format(state, format->pad, + format->stream); + if (!fmt) { + ret = -EINVAL; + goto out; + } + *fmt = format->format; - if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) - format->format = priv->mf; - else - format->format = *v4l2_subdev_get_try_format(sd, sd_state, 0); + /* Propagate format to the other end of the route. */ + fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad, + format->stream); + if (!fmt) { + ret = -EINVAL; + goto out; + } + *fmt = format->format; - mutex_unlock(&priv->lock); +out: + v4l2_subdev_unlock_state(state); - return 0; + return ret; } static int rcsi2_init_cfg(struct v4l2_subdev *sd, @@ -943,7 +943,7 @@ static const struct v4l2_subdev_video_ops rcar_csi2_video_ops = { static const struct v4l2_subdev_pad_ops rcar_csi2_pad_ops = { .init_cfg = rcsi2_init_cfg, .set_fmt = rcsi2_set_pad_format, - .get_fmt = rcsi2_get_pad_format, + .get_fmt = v4l2_subdev_get_fmt, }; static const struct v4l2_subdev_ops rcar_csi2_subdev_ops = { From patchwork Wed Feb 16 21:04:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12749057 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 6494DC433F5 for ; Wed, 16 Feb 2022 21:04:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234846AbiBPVEf (ORCPT ); Wed, 16 Feb 2022 16:04:35 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:53244 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234266AbiBPVEL (ORCPT ); Wed, 16 Feb 2022 16:04:11 -0500 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0678922219E; Wed, 16 Feb 2022 13:03:57 -0800 (PST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 536011BF206; Wed, 16 Feb 2022 21:03:55 +0000 (UTC) From: Jacopo Mondi To: niklas.soderlund@ragnatech.se, laurent.pinchart@ideasonboard.com Cc: Jacopo Mondi , tomi.valkeinen@ideasonboard.com, linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org, =?utf-8?q?N?= =?utf-8?q?iklas_S=C3=B6derlund?= Subject: [PATCH 08/10] media: rcar-csi2: Config by using the remote frame_desc Date: Wed, 16 Feb 2022 22:04:45 +0100 Message-Id: <20220216210447.481006-9-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.35.0 In-Reply-To: <20220216210447.481006-1-jacopo+renesas@jmondi.org> References: <20220216210447.481006-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org Configure the CSI-2 receiver by inspecting the remote subdev frame_desc. Configure the link clock rate, field handling and CSI-2 Virtual Channel and DT filtering using the frame descriptor retrieved from the transmitter. This change also makes mandatory for any subdevice that operates with the R-Car CSI-2 receiver to implement the .get_frame_desc() operation. [based on a patch from] Signed-off-by: Niklas Söderlund [rework based on lates multistream support] Signed-off-by: Jacopo Mondi --- drivers/media/platform/rcar-vin/rcar-csi2.c | 146 +++++++++++++++----- 1 file changed, 110 insertions(+), 36 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index a0642cafd70b..793a4d6e5a27 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -69,10 +69,7 @@ struct rcar_csi2; #define FLD_REG 0x1c #define FLD_FLD_NUM(n) (((n) & 0xff) << 16) #define FLD_DET_SEL(n) (((n) & 0x3) << 4) -#define FLD_FLD_EN4 BIT(3) -#define FLD_FLD_EN3 BIT(2) -#define FLD_FLD_EN2 BIT(1) -#define FLD_FLD_EN BIT(0) +#define FLD_FLD_EN(n) BIT((n) & 0xf) /* Automatic Standby Control */ #define ASTBY_REG 0x20 @@ -436,6 +433,17 @@ static const struct rcar_csi2_format *rcsi2_code_to_fmt(unsigned int code) return NULL; } +static const struct rcar_csi2_format *rcsi2_datatype_to_fmt(unsigned int dt) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(rcar_csi2_formats); i++) + if (rcar_csi2_formats[i].datatype == dt) + return &rcar_csi2_formats[i]; + + return NULL; +} + enum rcar_csi2_pads { RCAR_CSI2_SINK, RCAR_CSI2_SOURCE_VC0, @@ -471,7 +479,6 @@ struct rcar_csi2 { int channel_vc[4]; struct mutex lock; /* Protects mf and stream_count. */ - struct v4l2_mbus_framefmt mf; int stream_count; unsigned short lanes; @@ -520,6 +527,32 @@ static int rcsi2_exit_standby(struct rcar_csi2 *priv) return 0; } +static int rcsi2_get_remote_frame_desc(struct rcar_csi2 *priv, + struct v4l2_mbus_frame_desc *fd) +{ + struct media_pad *pad; + int ret; + + if (!priv->remote) + return -ENODEV; + + pad = media_entity_remote_pad(&priv->pads[RCAR_CSI2_SINK]); + if (!pad) + return -ENODEV; + + ret = v4l2_subdev_call(priv->remote, pad, get_frame_desc, + pad->index, fd); + if (ret) + return ret; + + if (fd->type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) { + dev_err(priv->dev, "Frame desc do not describe CSI-2 link"); + return -EINVAL; + } + + return 0; +} + static int rcsi2_wait_phy_start(struct rcar_csi2 *priv, unsigned int lanes) { @@ -559,11 +592,14 @@ static int rcsi2_set_phypll(struct rcar_csi2 *priv, unsigned int mbps) return 0; } -static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp, - unsigned int lanes) +static int rcsi2_calc_mbps(struct rcar_csi2 *priv, + struct v4l2_mbus_frame_desc *fd, unsigned int lanes) { + const struct v4l2_mbus_frame_desc_entry_csi2 *csi2_desc; + const struct rcar_csi2_format *format; struct v4l2_subdev *source; struct v4l2_ctrl *ctrl; + unsigned int i; u64 mbps; if (!priv->remote) @@ -579,12 +615,30 @@ static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp, return -EINVAL; } + /* Verify that all remote streams send the same datatype. */ + csi2_desc = NULL; + for (i = 0; i < fd->num_entries; i++) { + struct v4l2_mbus_frame_desc_entry_csi2 *stream_desc; + + stream_desc = &fd->entry[i].bus.csi2; + if (!csi2_desc) + csi2_desc = stream_desc; + + if (csi2_desc->dt != stream_desc->dt) { + dev_err(priv->dev, + "Remote streams with different DT: %u - %u\n", + csi2_desc->dt, stream_desc->dt); + return -EINVAL; + } + } + format = rcsi2_datatype_to_fmt(csi2_desc->dt); + /* * Calculate the phypll in mbps. * link_freq = (pixel_rate * bits_per_sample) / (2 * nr_of_lanes) * bps = link_freq * 2 */ - mbps = v4l2_ctrl_g_ctrl_int64(ctrl) * bpp; + mbps = v4l2_ctrl_g_ctrl_int64(ctrl) * format->bpp; do_div(mbps, lanes * 1000000); return mbps; @@ -640,54 +694,67 @@ static int rcsi2_get_active_lanes(struct rcar_csi2 *priv, static int rcsi2_start_receiver(struct rcar_csi2 *priv) { - const struct rcar_csi2_format *format; + const struct v4l2_subdev_stream_configs *configs; + struct v4l2_subdev_state *state; u32 phycnt, vcdt = 0, vcdt2 = 0, fld = 0; + struct v4l2_mbus_frame_desc fd; unsigned int lanes; unsigned int i; int mbps, ret; - dev_dbg(priv->dev, "Input size (%ux%u%c)\n", - priv->mf.width, priv->mf.height, - priv->mf.field == V4L2_FIELD_NONE ? 'p' : 'i'); - - /* Code is validated in set_fmt. */ - format = rcsi2_code_to_fmt(priv->mf.code); - if (!format) - return -EINVAL; + /* Get information about multiplexed link. */ + ret = rcsi2_get_remote_frame_desc(priv, &fd); + if (ret) + return ret; - /* - * Enable all supported CSI-2 channels with virtual channel and - * data type matching. - * - * NOTE: It's not possible to get individual datatype for each - * source virtual channel. Once this is possible in V4L2 - * it should be used here. - */ - for (i = 0; i < priv->info->num_channels; i++) { + for (i = 0; i < fd.num_entries; i++) { + struct v4l2_mbus_frame_desc_entry *entry = &fd.entry[i]; u32 vcdt_part; 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); + vcdt_part = VCDT_SEL_VC(entry->bus.csi2.vc) | + VCDT_VCDTN_EN | VCDT_SEL_DTN_ON | + VCDT_SEL_DT(entry->bus.csi2.dt); /* Store in correct reg and offset. */ - if (i < 2) - vcdt |= vcdt_part << ((i % 2) * 16); + if (entry->bus.csi2.vc < 2) + vcdt |= vcdt_part << + ((entry->bus.csi2.vc % 2) * 16); else - vcdt2 |= vcdt_part << ((i % 2) * 16); + vcdt2 |= vcdt_part << + ((entry->bus.csi2.vc % 2) * 16); + + dev_dbg(priv->dev, "VC: %d datatype: 0x%x\n", + entry->bus.csi2.vc, entry->bus.csi2.dt); } - if (priv->mf.field == V4L2_FIELD_ALTERNATE) { - fld = FLD_DET_SEL(1) | FLD_FLD_EN4 | FLD_FLD_EN3 | FLD_FLD_EN2 - | FLD_FLD_EN; + /* + * Configure field handling inspecting the formats of the + * sink pad streams. + */ + state = v4l2_subdev_lock_active_state(&priv->subdev); + configs = &state->stream_configs; + for (i = 0; i < configs->num_configs; ++i) { + const struct v4l2_subdev_stream_config *config = configs->configs; + + if (config->pad != RCAR_CSI2_SINK) + continue; + + if (config->fmt.field != V4L2_FIELD_ALTERNATE) + continue; - if (priv->mf.height == 240) + fld |= FLD_DET_SEL(1); + fld |= FLD_FLD_EN(config->stream); + + /* PAL vs NTSC. */ + if (config->fmt.height == 240) fld |= FLD_FLD_NUM(0); else fld |= FLD_FLD_NUM(1); } + v4l2_subdev_unlock_state(state); /* * Get the number of active data lanes inspecting the remote mbus @@ -700,7 +767,7 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv) phycnt = PHYCNT_ENABLECLK; phycnt |= (1 << lanes) - 1; - mbps = rcsi2_calc_mbps(priv, format->bpp, lanes); + mbps = rcsi2_calc_mbps(priv, &fd, lanes); if (mbps < 0) return mbps; @@ -999,6 +1066,13 @@ static int rcsi2_notify_bound(struct v4l2_async_notifier *notifier, struct rcar_csi2 *priv = notifier_to_csi2(notifier); int pad; + if (!v4l2_subdev_has_op(subdev, pad, get_frame_desc)) { + dev_err(priv->dev, + "Subdev %s bound failed: missing get_frame_desc()\n", + subdev->name); + return -EINVAL; + } + pad = media_entity_get_fwnode_pad(&subdev->entity, asd->match.fwnode, MEDIA_PAD_FL_SOURCE); if (pad < 0) { From patchwork Wed Feb 16 21:04:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12749058 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 2675EC433EF for ; Wed, 16 Feb 2022 21:04:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233969AbiBPVEf (ORCPT ); Wed, 16 Feb 2022 16:04:35 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:53330 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233940AbiBPVEM (ORCPT ); Wed, 16 Feb 2022 16:04:12 -0500 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 931C22AFEA6; Wed, 16 Feb 2022 13:03:59 -0800 (PST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id EB6601BF209; Wed, 16 Feb 2022 21:03:56 +0000 (UTC) From: Jacopo Mondi To: niklas.soderlund@ragnatech.se, laurent.pinchart@ideasonboard.com Cc: Jacopo Mondi , tomi.valkeinen@ideasonboard.com, linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH 09/10] media: rcar-csi2: Implement set_routing Date: Wed, 16 Feb 2022 22:04:46 +0100 Message-Id: <20220216210447.481006-10-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.35.0 In-Reply-To: <20220216210447.481006-1-jacopo+renesas@jmondi.org> References: <20220216210447.481006-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org Add the set_routing() subdev operation to allow userspace to activate routes on the R-Car CSI-2 receiver. Routing for this device is fixed. Validate that the provided route respects it. Signed-off-by: Jacopo Mondi --- drivers/media/platform/rcar-vin/rcar-csi2.c | 64 ++++++++++++++++++--- 1 file changed, 55 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index 793a4d6e5a27..3ceb7bcfe8d1 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -942,6 +942,59 @@ static int rcsi2_set_pad_format(struct v4l2_subdev *sd, return ret; } +static int __rcsi2_set_routing(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_krouting *routing) +{ + unsigned int i; + int ret = 0; + + ret = v4l2_subdev_routing_validate_1_to_1(routing); + if (ret) + return ret; + + v4l2_subdev_lock_state(state); + + /* + * Routing is fixed for this device. + * + * Only routes in the form of CSI2:0/x->CSI2:x+1/0 are allowed. + * + * We have anyway to implement set_routing to mark the route as active. + */ + for (i = 0; i < routing->num_routes; ++i) { + const struct v4l2_subdev_route *route = &routing->routes[i]; + unsigned int vc = route->sink_stream; + unsigned int pad = vc + 1; + + if (route->sink_pad != 0) { + ret = -EINVAL; + goto out; + } + + if (route->source_pad != pad || + route->source_stream != 0) { + ret = -EINVAL; + goto out; + } + } + + ret = v4l2_subdev_set_routing(sd, state, routing); + +out: + v4l2_subdev_unlock_state(state); + + return ret; +} + +static int rcsi2_set_routing(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + enum v4l2_subdev_format_whence which, + struct v4l2_subdev_krouting *routing) +{ + return __rcsi2_set_routing(sd, state, routing); +} + static int rcsi2_init_cfg(struct v4l2_subdev *sd, struct v4l2_subdev_state *state) { @@ -992,15 +1045,7 @@ static int rcsi2_init_cfg(struct v4l2_subdev *sd, .routes = routes, }; - int ret = v4l2_subdev_routing_validate_1_to_1(&routing); - if (ret) - return ret; - - v4l2_subdev_lock_state(state); - ret = v4l2_subdev_set_routing(sd, state, &routing); - v4l2_subdev_unlock_state(state); - - return ret; + return __rcsi2_set_routing(sd, state, &routing); } static const struct v4l2_subdev_video_ops rcar_csi2_video_ops = { @@ -1011,6 +1056,7 @@ static const struct v4l2_subdev_pad_ops rcar_csi2_pad_ops = { .init_cfg = rcsi2_init_cfg, .set_fmt = rcsi2_set_pad_format, .get_fmt = v4l2_subdev_get_fmt, + .set_routing = rcsi2_set_routing, }; static const struct v4l2_subdev_ops rcar_csi2_subdev_ops = { From patchwork Wed Feb 16 21:04:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12749059 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 7B43CC433FE for ; Wed, 16 Feb 2022 21:04:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234987AbiBPVEh (ORCPT ); Wed, 16 Feb 2022 16:04:37 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:53590 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233619AbiBPVEQ (ORCPT ); Wed, 16 Feb 2022 16:04:16 -0500 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::228]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DB0C32B048C; Wed, 16 Feb 2022 13:04:01 -0800 (PST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 7EE8A1BF204; Wed, 16 Feb 2022 21:03:58 +0000 (UTC) From: Jacopo Mondi To: niklas.soderlund@ragnatech.se, laurent.pinchart@ideasonboard.com Cc: Jacopo Mondi , tomi.valkeinen@ideasonboard.com, linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH 10/10] media: rcar-vin: Support multiplexed transmitters Date: Wed, 16 Feb 2022 22:04:47 +0100 Message-Id: <20220216210447.481006-11-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.35.0 In-Reply-To: <20220216210447.481006-1-jacopo+renesas@jmondi.org> References: <20220216210447.481006-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org The VIN driver calls get_fmt() on the remove subdev to validate its format. Now that the R-Car CSI-2 driver supports multiplexed streams pass it the active state when calling the operation. Signed-off-by: Jacopo Mondi --- drivers/media/platform/rcar-vin/rcar-dma.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c index 3575be1387e3..1e181eede8e1 100644 --- a/drivers/media/platform/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/rcar-vin/rcar-dma.c @@ -1133,7 +1133,8 @@ static int rvin_mc_validate_format(struct rvin_dev *vin, struct v4l2_subdev *sd, }; fmt.pad = pad->index; - if (v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt)) + if (v4l2_subdev_call(sd, pad, get_fmt, + v4l2_subdev_get_active_state(sd), &fmt)) return -EPIPE; switch (fmt.format.code) {