From patchwork Sun Oct 17 18:24:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12564547 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AF40BC433FE for ; Sun, 17 Oct 2021 18:24:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8A18A61040 for ; Sun, 17 Oct 2021 18:24:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344098AbhJQS00 (ORCPT ); Sun, 17 Oct 2021 14:26:26 -0400 Received: from relay12.mail.gandi.net ([217.70.178.232]:34937 "EHLO relay12.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344076AbhJQS0Y (ORCPT ); Sun, 17 Oct 2021 14:26:24 -0400 Received: (Authenticated sender: jacopo@jmondi.org) by relay12.mail.gandi.net (Postfix) with ESMTPSA id B61D7200004; Sun, 17 Oct 2021 18:24:11 +0000 (UTC) From: Jacopo Mondi To: tomi.valkeinen@ideasonboard.com, sakari.ailus@linux.intel.com, laurent.pinchart@ideasonboard.com, niklas.soderlund@ragnatech.se, kieran.bingham@ideasonboard.com Cc: Jacopo Mondi , Mauro Carvalho Chehab , Hans Verkuil , linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH v2 01/13] media: max9286: Add support for v4l2_subdev_state Date: Sun, 17 Oct 2021 20:24:37 +0200 Message-Id: <20211017182449.64192-2-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211017182449.64192-1-jacopo+renesas@jmondi.org> References: <20211017182449.64192-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Create and initialize the v4l2_subdev_state for the max9286 driver in order to prepare to support routing operations and multiplexed streams. 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 device format. Remove the max9286_open() subdev internal operation as the format of the file-handle state is now initialized by init_cfg(). Signed-off-by: Jacopo Mondi --- drivers/media/i2c/max9286.c | 90 +++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 33 deletions(-) diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c index 1b92d18a1f94..5997fe40509f 100644 --- a/drivers/media/i2c/max9286.c +++ b/drivers/media/i2c/max9286.c @@ -215,6 +215,17 @@ static inline struct max9286_priv *sd_to_max9286(struct v4l2_subdev *sd) return container_of(sd, struct max9286_priv, sd); } +static const struct v4l2_mbus_framefmt max9286_default_format = { + .width = 1280, + .height = 800, + .code = MEDIA_BUS_FMT_UYVY8_1X16, + .colorspace = V4L2_COLORSPACE_SRGB, + .field = V4L2_FIELD_NONE, + .ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT, + .quantization = V4L2_QUANTIZATION_DEFAULT, + .xfer_func = V4L2_XFER_FUNC_DEFAULT, +}; + /* ----------------------------------------------------------------------------- * I2C IO */ @@ -822,11 +833,45 @@ static int max9286_get_fmt(struct v4l2_subdev *sd, return 0; } +static int max9286_init_cfg(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state) +{ + struct v4l2_subdev_route routes[MAX9286_NUM_GMSL]; + struct max9286_priv *priv = sd_to_max9286(sd); + struct v4l2_subdev_krouting routing; + struct max9286_source *source; + unsigned int num_routes = 0; + int ret; + + /* Create a route for each enable source. */ + for_each_source(priv, source) { + struct v4l2_subdev_route *route = &routes[num_routes++]; + unsigned int idx = to_index(priv, source); + + route->sink_pad = idx; + route->sink_stream = 0; + route->source_pad = MAX9286_SRC_PAD; + route->source_stream = idx; + route->flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE; + } + + routing.num_routes = num_routes; + routing.routes = routes; + + state = v4l2_subdev_validate_and_lock_state(sd, state); + ret = v4l2_subdev_set_routing_with_fmt(sd, state, &routing, + &max9286_default_format); + v4l2_subdev_unlock_state(state); + + return ret; +} + static const struct v4l2_subdev_video_ops max9286_video_ops = { .s_stream = max9286_s_stream, }; static const struct v4l2_subdev_pad_ops max9286_pad_ops = { + .init_cfg = max9286_init_cfg, .enum_mbus_code = max9286_enum_mbus_code, .get_fmt = max9286_get_fmt, .set_fmt = max9286_set_fmt, @@ -837,35 +882,6 @@ static const struct v4l2_subdev_ops max9286_subdev_ops = { .pad = &max9286_pad_ops, }; -static void max9286_init_format(struct v4l2_mbus_framefmt *fmt) -{ - fmt->width = 1280; - fmt->height = 800; - fmt->code = MEDIA_BUS_FMT_UYVY8_1X16; - fmt->colorspace = V4L2_COLORSPACE_SRGB; - fmt->field = V4L2_FIELD_NONE; - fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; - fmt->quantization = V4L2_QUANTIZATION_DEFAULT; - fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT; -} - -static int max9286_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) -{ - struct v4l2_mbus_framefmt *format; - unsigned int i; - - for (i = 0; i < MAX9286_N_SINKS; i++) { - format = v4l2_subdev_get_try_format(subdev, fh->state, i); - max9286_init_format(format); - } - - return 0; -} - -static const struct v4l2_subdev_internal_ops max9286_subdev_internal_ops = { - .open = max9286_open, -}; - static int max9286_s_ctrl(struct v4l2_ctrl *ctrl) { switch (ctrl->id) { @@ -897,11 +913,11 @@ static int max9286_v4l2_register(struct max9286_priv *priv) /* Configure V4L2 for the MAX9286 itself */ for (i = 0; i < MAX9286_N_SINKS; i++) - max9286_init_format(&priv->fmt[i]); + priv->fmt[i] = max9286_default_format; v4l2_i2c_subdev_init(&priv->sd, priv->client, &max9286_subdev_ops); - priv->sd.internal_ops = &max9286_subdev_internal_ops; - priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | + V4L2_SUBDEV_FL_MULTIPLEXED; v4l2_ctrl_handler_init(&priv->ctrls, 1); priv->pixelrate = v4l2_ctrl_new_std(&priv->ctrls, @@ -933,14 +949,21 @@ static int max9286_v4l2_register(struct max9286_priv *priv) } priv->sd.fwnode = ep; + ret = v4l2_subdev_init_finalize(&priv->sd); + if (ret) + goto err_put_node; + ret = v4l2_async_register_subdev(&priv->sd); if (ret < 0) { dev_err(dev, "Unable to register subdevice\n"); - goto err_put_node; + goto err_free_state; } return 0; +err_free_state: + v4l2_subdev_cleanup(&priv->sd); + err_put_node: fwnode_handle_put(ep); err_async: @@ -953,6 +976,7 @@ static void max9286_v4l2_unregister(struct max9286_priv *priv) { fwnode_handle_put(priv->sd.fwnode); v4l2_async_unregister_subdev(&priv->sd); + v4l2_subdev_cleanup(&priv->sd); max9286_v4l2_notifier_unregister(priv); } From patchwork Sun Oct 17 18:24:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12564549 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AE2CFC433F5 for ; Sun, 17 Oct 2021 18:24:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 89A1C61052 for ; Sun, 17 Oct 2021 18:24:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344134AbhJQS02 (ORCPT ); Sun, 17 Oct 2021 14:26:28 -0400 Received: from relay12.mail.gandi.net ([217.70.178.232]:52575 "EHLO relay12.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344093AbhJQS0Z (ORCPT ); Sun, 17 Oct 2021 14:26:25 -0400 Received: (Authenticated sender: jacopo@jmondi.org) by relay12.mail.gandi.net (Postfix) with ESMTPSA id 64800200007; Sun, 17 Oct 2021 18:24:13 +0000 (UTC) From: Jacopo Mondi To: tomi.valkeinen@ideasonboard.com, sakari.ailus@linux.intel.com, laurent.pinchart@ideasonboard.com, niklas.soderlund@ragnatech.se, kieran.bingham@ideasonboard.com Cc: Jacopo Mondi , Mauro Carvalho Chehab , Hans Verkuil , linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH v2 02/13] media: max9286: Implement set_routing Date: Sun, 17 Oct 2021 20:24:38 +0200 Message-Id: <20211017182449.64192-3-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211017182449.64192-1-jacopo+renesas@jmondi.org> References: <20211017182449.64192-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add the set_routing() subdev operation to allow userspace to configure routing on the max9286 deserializer. Implement route verification but do not take routing into consideration when configuring the CSI-2 output and pixel rate yet. Signed-off-by: Jacopo Mondi --- drivers/media/i2c/max9286.c | 88 ++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c index 5997fe40509f..54b4067168df 100644 --- a/drivers/media/i2c/max9286.c +++ b/drivers/media/i2c/max9286.c @@ -833,6 +833,90 @@ static int max9286_get_fmt(struct v4l2_subdev *sd, return 0; } +static int max9286_routing_verify(struct max9286_priv *priv, + struct v4l2_subdev_krouting *routing) +{ + unsigned int i; + int ret; + + ret = v4l2_routing_simple_verify(routing); + if (ret) + return ret; + + /* + * Make sure all routes points to the single source pad which can have + * up to 4 streams. All routes shall start from a sink pad and shall not + * have more than one sink stream. The GMSL link for the sink has to be + * enabled. + */ + for (i = 0; i < routing->num_routes; ++i) { + const struct v4l2_subdev_route *route = &routing->routes[i]; + struct max9286_source *source = &priv->sources[i]; + + if (route->source_pad != MAX9286_SRC_PAD || + route->source_stream > 4) { + dev_err(&priv->client->dev, + "Invalid (%u,%u) source in route %u\n", + route->source_pad, route->source_stream, i); + return -EINVAL; + } + + if (route->sink_pad >= MAX9286_N_SINKS || + route->sink_stream != 0) { + dev_err(&priv->client->dev, + "Invalid (%u,%u) sink in route %u\n", + route->sink_pad, route->sink_stream, i); + return -EINVAL; + } + + source = &priv->sources[route->sink_pad]; + if (!source->fwnode) { + dev_err(&priv->client->dev, + "Cannot set route for non-active source %u\n", + route->sink_pad); + return -EINVAL; + } + } + + return 0; +} + +static int _max9286_set_routing(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_krouting *routing) +{ + struct max9286_priv *priv = sd_to_max9286(sd); + int ret; + + ret = max9286_routing_verify(priv, routing); + if (ret) + return ret; + + /* Re-initialize the format on a routing change. */ + ret = v4l2_subdev_set_routing_with_fmt(sd, state, routing, + &max9286_default_format); + if (ret) + return ret; + + return 0; +} + +static int max9286_set_routing(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + enum v4l2_subdev_format_whence which, + struct v4l2_subdev_krouting *routing) +{ + struct max9286_priv *priv = sd_to_max9286(sd); + unsigned int i; + int ret; + + state = v4l2_subdev_validate_and_lock_state(sd, state); + ret = _max9286_set_routing(sd, state, routing); + v4l2_subdev_unlock_state(state); + + return ret; +} + static int max9286_init_cfg(struct v4l2_subdev *sd, struct v4l2_subdev_state *state) { @@ -859,8 +943,7 @@ static int max9286_init_cfg(struct v4l2_subdev *sd, routing.routes = routes; state = v4l2_subdev_validate_and_lock_state(sd, state); - ret = v4l2_subdev_set_routing_with_fmt(sd, state, &routing, - &max9286_default_format); + ret = _max9286_set_routing(sd, state, &routing); v4l2_subdev_unlock_state(state); return ret; @@ -875,6 +958,7 @@ static const struct v4l2_subdev_pad_ops max9286_pad_ops = { .enum_mbus_code = max9286_enum_mbus_code, .get_fmt = max9286_get_fmt, .set_fmt = max9286_set_fmt, + .set_routing = max9286_set_routing, }; static const struct v4l2_subdev_ops max9286_subdev_ops = { From patchwork Sun Oct 17 18:24:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12564551 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7779BC43219 for ; Sun, 17 Oct 2021 18:24:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5292D61040 for ; Sun, 17 Oct 2021 18:24:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344158AbhJQS02 (ORCPT ); Sun, 17 Oct 2021 14:26:28 -0400 Received: from relay12.mail.gandi.net ([217.70.178.232]:47135 "EHLO relay12.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344099AbhJQS01 (ORCPT ); Sun, 17 Oct 2021 14:26:27 -0400 Received: (Authenticated sender: jacopo@jmondi.org) by relay12.mail.gandi.net (Postfix) with ESMTPSA id 0C8B3200006; Sun, 17 Oct 2021 18:24:14 +0000 (UTC) From: Jacopo Mondi To: tomi.valkeinen@ideasonboard.com, sakari.ailus@linux.intel.com, laurent.pinchart@ideasonboard.com, niklas.soderlund@ragnatech.se, kieran.bingham@ideasonboard.com Cc: Jacopo Mondi , Mauro Carvalho Chehab , Hans Verkuil , linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH v2 03/13] media: max9286: Use enabled routes to calculate pixelrate Date: Sun, 17 Oct 2021 20:24:39 +0200 Message-Id: <20211017182449.64192-4-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211017182449.64192-1-jacopo+renesas@jmondi.org> References: <20211017182449.64192-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Now that the device supports routing, use the enabled routes instead of the connected sources to compute the output pixel rate. To do so, update the route_mask after a set_routing() call with the ACTIVE format, and re-calculate the pixel rate just after. At the same time, start and stop only the enabled routes at s_stream() time. Signed-off-by: Jacopo Mondi --- drivers/media/i2c/max9286.c | 63 ++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 12 deletions(-) diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c index 54b4067168df..2e635179aec0 100644 --- a/drivers/media/i2c/max9286.c +++ b/drivers/media/i2c/max9286.c @@ -189,8 +189,11 @@ struct max9286_priv { struct v4l2_async_notifier notifier; }; +#define to_index(priv, source) ((source) - &(priv)->sources[0]) + static struct max9286_source *next_source(struct max9286_priv *priv, - struct max9286_source *source) + struct max9286_source *source, + bool routed) { if (!source) source = &priv->sources[0]; @@ -198,17 +201,27 @@ static struct max9286_source *next_source(struct max9286_priv *priv, source++; for (; source < &priv->sources[MAX9286_NUM_GMSL]; source++) { - if (source->fwnode) + unsigned int index = to_index(priv, source); + + if (!source->fwnode) + continue; + + /* + * Careful here! A very unfortunate call to set_routing() can + * change priv->route_mask behind our back! + */ + if (!routed || priv->route_mask & BIT(index)) return source; } return NULL; } -#define for_each_source(priv, source) \ - for ((source) = NULL; ((source) = next_source((priv), (source))); ) +#define for_each_route(priv, source) \ + for ((source) = NULL; ((source) = next_source((priv), (source), true)); ) -#define to_index(priv, source) ((source) - &(priv)->sources[0]) +#define for_each_source(priv, source) \ + for ((source) = NULL; ((source) = next_source((priv), (source), false)); ) static inline struct max9286_priv *sd_to_max9286(struct v4l2_subdev *sd) { @@ -410,7 +423,7 @@ static int max9286_check_video_links(struct max9286_priv *priv) if (ret < 0) return -EIO; - if ((ret & MAX9286_VIDEO_DETECT_MASK) == priv->source_mask) + if ((ret & MAX9286_VIDEO_DETECT_MASK) == priv->route_mask) break; usleep_range(350, 500); @@ -494,9 +507,10 @@ static int max9286_check_config_link(struct max9286_priv *priv, static int max9286_set_pixelrate(struct max9286_priv *priv) { struct max9286_source *source = NULL; + unsigned int num_routes = 0; u64 pixelrate = 0; - for_each_source(priv, source) { + for_each_route(priv, source) { struct v4l2_ctrl *ctrl; u64 source_rate = 0; @@ -517,6 +531,8 @@ static int max9286_set_pixelrate(struct max9286_priv *priv) "Unable to calculate pixel rate\n"); return -EINVAL; } + + num_routes++; } if (!pixelrate) { @@ -530,7 +546,7 @@ static int max9286_set_pixelrate(struct max9286_priv *priv) * by the number of available sources. */ return v4l2_ctrl_s_ctrl_int64(priv->pixelrate, - pixelrate * priv->nsources); + pixelrate * num_routes); } static int max9286_notify_bound(struct v4l2_async_notifier *notifier, @@ -692,8 +708,8 @@ static int max9286_s_stream(struct v4l2_subdev *sd, int enable) */ max9286_i2c_mux_open(priv); - /* Start all cameras. */ - for_each_source(priv, source) { + /* Start cameras. */ + for_each_route(priv, source) { ret = v4l2_subdev_call(source->sd, video, s_stream, 1); if (ret) return ret; @@ -734,8 +750,8 @@ static int max9286_s_stream(struct v4l2_subdev *sd, int enable) } else { max9286_write(priv, 0x15, MAX9286_VCTYPE | MAX9286_0X15_RESV); - /* Stop all cameras. */ - for_each_source(priv, source) + /* Stop cameras. */ + for_each_route(priv, source) v4l2_subdev_call(source->sd, video, s_stream, 0); max9286_i2c_mux_close(priv); @@ -912,6 +928,29 @@ static int max9286_set_routing(struct v4l2_subdev *sd, state = v4l2_subdev_validate_and_lock_state(sd, state); ret = _max9286_set_routing(sd, state, routing); + if (ret) + goto out; + + if (which == V4L2_SUBDEV_FORMAT_TRY) + goto out; + + /* + * Update the active routes mask and the pixel rate according to the + * routed sources. + */ + priv->route_mask = 0; + for (i = 0; i < routing->num_routes; ++i) { + struct v4l2_subdev_route *route = &routing->routes[i]; + + if (!(route->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) + continue; + + priv->route_mask |= BIT(route->sink_pad); + } + + max9286_set_pixelrate(priv); + +out: v4l2_subdev_unlock_state(state); return ret; From patchwork Sun Oct 17 18:24:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12564553 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A0947C4321E for ; Sun, 17 Oct 2021 18:24:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7E6D561040 for ; Sun, 17 Oct 2021 18:24:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344182AbhJQS03 (ORCPT ); Sun, 17 Oct 2021 14:26:29 -0400 Received: from relay12.mail.gandi.net ([217.70.178.232]:53361 "EHLO relay12.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344139AbhJQS02 (ORCPT ); Sun, 17 Oct 2021 14:26:28 -0400 Received: (Authenticated sender: jacopo@jmondi.org) by relay12.mail.gandi.net (Postfix) with ESMTPSA id 9E06F200009; Sun, 17 Oct 2021 18:24:16 +0000 (UTC) From: Jacopo Mondi To: tomi.valkeinen@ideasonboard.com, sakari.ailus@linux.intel.com, laurent.pinchart@ideasonboard.com, niklas.soderlund@ragnatech.se, kieran.bingham@ideasonboard.com Cc: Jacopo Mondi , Mauro Carvalho Chehab , Hans Verkuil , linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH v2 04/13] media: max9286: Use routes to configure link order Date: Sun, 17 Oct 2021 20:24:40 +0200 Message-Id: <20211017182449.64192-5-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211017182449.64192-1-jacopo+renesas@jmondi.org> References: <20211017182449.64192-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Use the routing table to configure the link output order and link masking. The link output order defines the CSI-2 virtual channel a GSML stream is output on. Configure ordering at stream start time and at chip setup time. This last step requires to move the chip initialization function after the V4L2 setup phase as it requires the subdev state from where the routing table is retrieved from to be initialized. Signed-off-by: Jacopo Mondi --- drivers/media/i2c/max9286.c | 103 ++++++++++++++++++++++-------------- 1 file changed, 64 insertions(+), 39 deletions(-) diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c index 2e635179aec0..3485478f08a5 100644 --- a/drivers/media/i2c/max9286.c +++ b/drivers/media/i2c/max9286.c @@ -500,6 +500,61 @@ static int max9286_check_config_link(struct max9286_priv *priv, return 0; } +/* + * Configure the links output order (which defines on which CSI-2 VC a + * link is output on) and configure link masking. + */ +static void max9286_config_links(struct max9286_priv *priv) +{ + const struct v4l2_subdev_krouting *routing; + struct v4l2_subdev_state *state; + u8 link_order = 0; + u8 vc_mask = 0xf; + unsigned int i; + + state = v4l2_subdev_lock_active_state(&priv->sd); + routing = &state->routing; + + for (i = 0; i < routing->num_routes; ++i) { + struct v4l2_subdev_route *route = &routing->routes[i]; + + if (!(priv->route_mask & BIT(i))) + continue; + + /* Assign the CSI-2 VC using the source stream number. */ + link_order |= route->source_stream << (2 * route->sink_pad); + vc_mask &= ~BIT(route->source_stream); + } + + /* + * This might look rather silly, but now that we have assigned a + * VC to the enabled routes, we have to assign one to the disabled + * routes as well, as there cannot be two sources with the same VC. + */ + for (i = 0; i < MAX9286_NUM_GMSL; ++i) { + unsigned int vc; + + if (priv->route_mask & BIT(i)) + continue; + + /* ffs() counts from 1. */ + vc = ffs(vc_mask) - 1; + link_order |= vc << (2 * i); + vc_mask &= ~BIT(vc); + } + + /* + * Use the enabled routes to enable GMSL links, configure the CSI-2 + * output order, mask unused links and autodetect link used as CSI + * clock source. + */ + max9286_write(priv, 0x00, MAX9286_MSTLINKSEL_AUTO | priv->route_mask); + max9286_write(priv, 0x0b, link_order); + max9286_write(priv, 0x69, 0xf & ~priv->route_mask); + + v4l2_subdev_unlock_state(state); +} + /* ----------------------------------------------------------------------------- * V4L2 Subdev */ @@ -701,6 +756,8 @@ static int max9286_s_stream(struct v4l2_subdev *sd, int enable) int ret; if (enable) { + max9286_config_links(priv); + /* * The frame sync between cameras is transmitted across the * reverse channel as GPIO. We must open all channels while @@ -1109,32 +1166,6 @@ static void max9286_v4l2_unregister(struct max9286_priv *priv) static int max9286_setup(struct max9286_priv *priv) { - /* - * Link ordering values for all enabled links combinations. Orders must - * be assigned sequentially from 0 to the number of enabled links - * without leaving any hole for disabled links. We thus assign orders to - * enabled links first, and use the remaining order values for disabled - * links are all links must have a different order value; - */ - static const u8 link_order[] = { - (3 << 6) | (2 << 4) | (1 << 2) | (0 << 0), /* xxxx */ - (3 << 6) | (2 << 4) | (1 << 2) | (0 << 0), /* xxx0 */ - (3 << 6) | (2 << 4) | (0 << 2) | (1 << 0), /* xx0x */ - (3 << 6) | (2 << 4) | (1 << 2) | (0 << 0), /* xx10 */ - (3 << 6) | (0 << 4) | (2 << 2) | (1 << 0), /* x0xx */ - (3 << 6) | (1 << 4) | (2 << 2) | (0 << 0), /* x1x0 */ - (3 << 6) | (1 << 4) | (0 << 2) | (2 << 0), /* x10x */ - (3 << 6) | (1 << 4) | (1 << 2) | (0 << 0), /* x210 */ - (0 << 6) | (3 << 4) | (2 << 2) | (1 << 0), /* 0xxx */ - (1 << 6) | (3 << 4) | (2 << 2) | (0 << 0), /* 1xx0 */ - (1 << 6) | (3 << 4) | (0 << 2) | (2 << 0), /* 1x0x */ - (2 << 6) | (3 << 4) | (1 << 2) | (0 << 0), /* 2x10 */ - (1 << 6) | (0 << 4) | (3 << 2) | (2 << 0), /* 10xx */ - (2 << 6) | (1 << 4) | (3 << 2) | (0 << 0), /* 21x0 */ - (2 << 6) | (1 << 4) | (0 << 2) | (3 << 0), /* 210x */ - (3 << 6) | (2 << 4) | (1 << 2) | (0 << 0), /* 3210 */ - }; - /* * Set the I2C bus speed. * @@ -1144,13 +1175,7 @@ static int max9286_setup(struct max9286_priv *priv) max9286_configure_i2c(priv, true); max9286_reverse_channel_setup(priv, priv->init_rev_chan_mv); - /* - * Enable GMSL links, mask unused ones and autodetect link - * used as CSI clock source. - */ - max9286_write(priv, 0x00, MAX9286_MSTLINKSEL_AUTO | priv->route_mask); - max9286_write(priv, 0x0b, link_order[priv->route_mask]); - max9286_write(priv, 0x69, (0xf & ~priv->route_mask)); + max9286_config_links(priv); /* * Video format setup: @@ -1324,12 +1349,6 @@ static int max9286_init(struct device *dev) if (ret) return ret; - ret = max9286_setup(priv); - if (ret) { - dev_err(dev, "Unable to setup max9286\n"); - goto err_poc_disable; - } - /* * Register all V4L2 interactions for the MAX9286 and notifiers for * any subdevices connected. @@ -1340,6 +1359,12 @@ static int max9286_init(struct device *dev) goto err_poc_disable; } + ret = max9286_setup(priv); + if (ret) { + dev_err(dev, "Unable to setup max9286\n"); + goto err_poc_disable; + } + ret = max9286_i2c_mux_init(priv); if (ret) { dev_err(dev, "Unable to initialize I2C multiplexer\n"); From patchwork Sun Oct 17 18:24:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12564555 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 595CDC433F5 for ; Sun, 17 Oct 2021 18:24:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 40BDE61039 for ; Sun, 17 Oct 2021 18:24:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344206AbhJQS0b (ORCPT ); Sun, 17 Oct 2021 14:26:31 -0400 Received: from relay12.mail.gandi.net ([217.70.178.232]:46385 "EHLO relay12.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344139AbhJQS0a (ORCPT ); Sun, 17 Oct 2021 14:26:30 -0400 Received: (Authenticated sender: jacopo@jmondi.org) by relay12.mail.gandi.net (Postfix) with ESMTPSA id 50A8920000B; Sun, 17 Oct 2021 18:24:18 +0000 (UTC) From: Jacopo Mondi To: tomi.valkeinen@ideasonboard.com, sakari.ailus@linux.intel.com, laurent.pinchart@ideasonboard.com, niklas.soderlund@ragnatech.se, kieran.bingham@ideasonboard.com Cc: Jacopo Mondi , Mauro Carvalho Chehab , Hans Verkuil , linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH v2 05/13] media: max9286: Move format to subdev state Date: Sun, 17 Oct 2021 20:24:41 +0200 Message-Id: <20211017182449.64192-6-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211017182449.64192-1-jacopo+renesas@jmondi.org> References: <20211017182449.64192-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@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/max9286.c | 85 ++++++++++++------------------------- 1 file changed, 27 insertions(+), 58 deletions(-) diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c index 3485478f08a5..e51771d99437 100644 --- a/drivers/media/i2c/max9286.c +++ b/drivers/media/i2c/max9286.c @@ -175,8 +175,6 @@ struct max9286_priv { struct v4l2_ctrl_handler ctrls; struct v4l2_ctrl *pixelrate; - struct v4l2_mbus_framefmt fmt[MAX9286_N_SINKS]; - /* Protects controls and fmt structures */ struct mutex mutex; @@ -829,28 +827,18 @@ static int max9286_enum_mbus_code(struct v4l2_subdev *sd, return 0; } -static struct v4l2_mbus_framefmt * -max9286_get_pad_format(struct max9286_priv *priv, - struct v4l2_subdev_state *sd_state, - unsigned int pad, u32 which) -{ - switch (which) { - case V4L2_SUBDEV_FORMAT_TRY: - return v4l2_subdev_get_try_format(&priv->sd, sd_state, pad); - case V4L2_SUBDEV_FORMAT_ACTIVE: - return &priv->fmt[pad]; - default: - return NULL; - } -} - static int max9286_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *format) { - struct max9286_priv *priv = sd_to_max9286(sd); - struct v4l2_mbus_framefmt *cfg_fmt; + struct v4l2_mbus_framefmt *fmt; + struct v4l2_subdev_state *state; + int ret = 0; + /* + * Refuse to set format on the multiplexed source pad. + * Format is propagated from sinks streams to source streams. + */ if (format->pad == MAX9286_SRC_PAD) return -EINVAL; @@ -866,44 +854,28 @@ static int max9286_set_fmt(struct v4l2_subdev *sd, break; } - cfg_fmt = max9286_get_pad_format(priv, sd_state, format->pad, - format->which); - if (!cfg_fmt) - return -EINVAL; - - mutex_lock(&priv->mutex); - *cfg_fmt = format->format; - mutex_unlock(&priv->mutex); - - return 0; -} - -static int max9286_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *format) -{ - struct max9286_priv *priv = sd_to_max9286(sd); - struct v4l2_mbus_framefmt *cfg_fmt; - unsigned int pad = format->pad; - - /* - * Multiplexed Stream Support: Support link validation by returning the - * format of the first bound link. All links must have the same format, - * as we do not support mixing and matching of cameras connected to the - * max9286. - */ - if (pad == MAX9286_SRC_PAD) - pad = __ffs(priv->bound_sources); + state = v4l2_subdev_validate_and_lock_state(sd, sd_state); + fmt = v4l2_state_get_stream_format(state, format->pad, + format->stream); + if (!fmt) { + ret = -EINVAL; + goto out; + } + *fmt = format->format; - cfg_fmt = max9286_get_pad_format(priv, sd_state, pad, format->which); - if (!cfg_fmt) - return -EINVAL; + /* Propagate format to the other end of the route. */ + fmt = v4l2_state_get_opposite_stream_format(state, format->pad, + format->stream); + if (!fmt) { + ret = -EINVAL; + goto out; + } + *fmt = format->format; - mutex_lock(&priv->mutex); - format->format = *cfg_fmt; - mutex_unlock(&priv->mutex); +out: + v4l2_subdev_unlock_state(state); - return 0; + return ret; } static int max9286_routing_verify(struct max9286_priv *priv, @@ -1052,7 +1024,7 @@ static const struct v4l2_subdev_video_ops max9286_video_ops = { static const struct v4l2_subdev_pad_ops max9286_pad_ops = { .init_cfg = max9286_init_cfg, .enum_mbus_code = max9286_enum_mbus_code, - .get_fmt = max9286_get_fmt, + .get_fmt = v4l2_subdev_get_fmt, .set_fmt = max9286_set_fmt, .set_routing = max9286_set_routing, }; @@ -1092,9 +1064,6 @@ static int max9286_v4l2_register(struct max9286_priv *priv) /* Configure V4L2 for the MAX9286 itself */ - for (i = 0; i < MAX9286_N_SINKS; i++) - priv->fmt[i] = max9286_default_format; - v4l2_i2c_subdev_init(&priv->sd, priv->client, &max9286_subdev_ops); priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_MULTIPLEXED; From patchwork Sun Oct 17 18:24:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12564557 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 007AEC4332F for ; Sun, 17 Oct 2021 18:24:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E013B61052 for ; Sun, 17 Oct 2021 18:24:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344231AbhJQS0c (ORCPT ); Sun, 17 Oct 2021 14:26:32 -0400 Received: from relay12.mail.gandi.net ([217.70.178.232]:38141 "EHLO relay12.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344139AbhJQS0c (ORCPT ); Sun, 17 Oct 2021 14:26:32 -0400 Received: (Authenticated sender: jacopo@jmondi.org) by relay12.mail.gandi.net (Postfix) with ESMTPSA id E597C200004; Sun, 17 Oct 2021 18:24:19 +0000 (UTC) From: Jacopo Mondi To: tomi.valkeinen@ideasonboard.com, sakari.ailus@linux.intel.com, laurent.pinchart@ideasonboard.com, niklas.soderlund@ragnatech.se, kieran.bingham@ideasonboard.com Cc: Jacopo Mondi , Mauro Carvalho Chehab , Hans Verkuil , linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH v2 06/13] media: subdev: Add for_each_active_route() macro Date: Sun, 17 Oct 2021 20:24:42 +0200 Message-Id: <20211017182449.64192-7-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211017182449.64192-1-jacopo+renesas@jmondi.org> References: <20211017182449.64192-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add a for_each_active_route() macro to replace the repeated pattern of iterating on the active routes of a routing table. Replace the existing occurrences of such pattern in the codebase. Signed-off-by: Jacopo Mondi --- drivers/media/i2c/ds90ub913.c | 8 ++------ drivers/media/i2c/ds90ub953.c | 7 ++----- drivers/media/i2c/ds90ub960.c | 8 ++------ drivers/media/i2c/max9286.c | 10 ++-------- drivers/media/platform/ti-vpe/cal-video.c | 9 ++------- drivers/media/v4l2-core/v4l2-subdev.c | 18 ++++++++++++++++++ include/media/v4l2-subdev.h | 11 +++++++++++ 7 files changed, 39 insertions(+), 32 deletions(-) diff --git a/drivers/media/i2c/ds90ub913.c b/drivers/media/i2c/ds90ub913.c index d675faa2c571..478717e05480 100644 --- a/drivers/media/i2c/ds90ub913.c +++ b/drivers/media/i2c/ds90ub913.c @@ -342,8 +342,8 @@ static int ub913_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, struct ub913_data *priv = sd_to_ub913(sd); const struct v4l2_subdev_krouting *routing; struct v4l2_mbus_frame_desc source_fd; + struct v4l2_subdev_route *route; struct v4l2_subdev_state *state; - unsigned int i; int ret = 0; if (pad != 1) /* first tx pad */ @@ -361,13 +361,9 @@ static int ub913_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, fd->type = V4L2_MBUS_FRAME_DESC_TYPE_PARALLEL; - for (i = 0; i < routing->num_routes; ++i) { - const struct v4l2_subdev_route *route = &routing->routes[i]; + for_each_active_route(routing, route) { unsigned int j; - if (!(route->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) - continue; - if (route->source_pad != pad) continue; diff --git a/drivers/media/i2c/ds90ub953.c b/drivers/media/i2c/ds90ub953.c index d0b47e31be90..8615d8e996ee 100644 --- a/drivers/media/i2c/ds90ub953.c +++ b/drivers/media/i2c/ds90ub953.c @@ -383,6 +383,7 @@ static int ub953_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, struct ub953_data *priv = sd_to_ub953(sd); const struct v4l2_subdev_krouting *routing; struct v4l2_mbus_frame_desc source_fd; + struct v4l2_subdev_route *route; struct v4l2_subdev_state *state; unsigned int i; int ret = 0; @@ -402,14 +403,10 @@ static int ub953_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2; - for (i = 0; i < routing->num_routes; ++i) { - const struct v4l2_subdev_route *route = &routing->routes[i]; + for_each_active_route(routing, route) { struct v4l2_mbus_frame_desc_entry *source_entry = NULL; unsigned int j; - if (!(route->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) - continue; - if (route->source_pad != pad) continue; diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c index c655cb3e1ad6..9f79efddb138 100644 --- a/drivers/media/i2c/ds90ub960.c +++ b/drivers/media/i2c/ds90ub960.c @@ -1521,9 +1521,9 @@ static int ub960_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, { struct ub960_data *priv = sd_to_ub960(sd); const struct v4l2_subdev_krouting *routing; + struct v4l2_subdev_route *route; struct v4l2_subdev_state *state; int ret = 0; - unsigned int i; struct device *dev = &priv->client->dev; dev_dbg(dev, "%s for pad %d\n", __func__, pad); @@ -1539,15 +1539,11 @@ static int ub960_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2; - for (i = 0; i < routing->num_routes; ++i) { - const struct v4l2_subdev_route *route = &routing->routes[i]; + for_each_active_route(routing, route) { struct v4l2_mbus_frame_desc_entry *source_entry = NULL; struct v4l2_mbus_frame_desc source_fd; unsigned int j; - if (!(route->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) - continue; - if (route->source_pad != pad) continue; diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c index e51771d99437..8bfb88db9976 100644 --- a/drivers/media/i2c/max9286.c +++ b/drivers/media/i2c/max9286.c @@ -952,7 +952,7 @@ static int max9286_set_routing(struct v4l2_subdev *sd, struct v4l2_subdev_krouting *routing) { struct max9286_priv *priv = sd_to_max9286(sd); - unsigned int i; + struct v4l2_subdev_route *route; int ret; state = v4l2_subdev_validate_and_lock_state(sd, state); @@ -968,14 +968,8 @@ static int max9286_set_routing(struct v4l2_subdev *sd, * routed sources. */ priv->route_mask = 0; - for (i = 0; i < routing->num_routes; ++i) { - struct v4l2_subdev_route *route = &routing->routes[i]; - - if (!(route->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) - continue; - + for_each_active_route(routing, route) priv->route_mask |= BIT(route->sink_pad); - } max9286_set_pixelrate(priv); diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c index f945d737c5e5..cdd279a32beb 100644 --- a/drivers/media/platform/ti-vpe/cal-video.c +++ b/drivers/media/platform/ti-vpe/cal-video.c @@ -771,6 +771,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count) if (cal_mc_api) { struct v4l2_subdev_route *route = NULL; + struct v4l2_subdev_route *r; struct media_pad *remote_pad; unsigned int i; struct v4l2_subdev_state *state; @@ -790,13 +791,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count) /* Find the stream */ - for (i = 0; i < state->routing.num_routes; ++i) { - struct v4l2_subdev_route *r = - &state->routing.routes[i]; - - if (!(r->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) - continue; - + for_each_active_route(routing, r) { if (r->source_pad != remote_pad->index) continue; diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 2a64ff003e4b..7dde44467c9a 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -1593,3 +1593,21 @@ int v4l2_routing_simple_verify(const struct v4l2_subdev_krouting *routing) return 0; } EXPORT_SYMBOL_GPL(v4l2_routing_simple_verify); + +struct v4l2_subdev_route *next_active_route(const struct v4l2_subdev_krouting *routing, + struct v4l2_subdev_route *route) +{ + if (route) + ++route; + else + route = &routing->routes[0]; + + for (; route < routing->routes + routing->num_routes; ++route) { + if (!(route->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) + continue; + + return route; + } + + return NULL; +} diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index d0354e507970..ffce66e88952 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -1582,4 +1582,15 @@ int v4l2_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, */ int v4l2_routing_simple_verify(const struct v4l2_subdev_krouting *routing); +struct v4l2_subdev_route *next_active_route(const struct v4l2_subdev_krouting *routing, + struct v4l2_subdev_route *route); +/** + * for_each_active_route - iterate on all active routes of a routing table + * @routing: The routing table + * @route: The route iterator + */ +#define for_each_active_route(routing, route) \ + for ((route) = NULL; \ + ((route) = next_active_route((routing), (route)));) + #endif From patchwork Sun Oct 17 18:24:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12564559 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C3FD4C433F5 for ; Sun, 17 Oct 2021 18:24:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AA86860FED for ; Sun, 17 Oct 2021 18:24:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344257AbhJQS0e (ORCPT ); Sun, 17 Oct 2021 14:26:34 -0400 Received: from relay12.mail.gandi.net ([217.70.178.232]:49567 "EHLO relay12.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344139AbhJQS0d (ORCPT ); Sun, 17 Oct 2021 14:26:33 -0400 Received: (Authenticated sender: jacopo@jmondi.org) by relay12.mail.gandi.net (Postfix) with ESMTPSA id 96AFA200007; Sun, 17 Oct 2021 18:24:21 +0000 (UTC) From: Jacopo Mondi To: tomi.valkeinen@ideasonboard.com, sakari.ailus@linux.intel.com, laurent.pinchart@ideasonboard.com, niklas.soderlund@ragnatech.se, kieran.bingham@ideasonboard.com Cc: Jacopo Mondi , Mauro Carvalho Chehab , Hans Verkuil , linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH v2 07/13] media: max9286: Implement get_frame_desc() Date: Sun, 17 Oct 2021 20:24:43 +0200 Message-Id: <20211017182449.64192-8-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211017182449.64192-1-jacopo+renesas@jmondi.org> References: <20211017182449.64192-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Implement the get_frame_desc pad operation to allow retrieving the stream configuration of the max9286 subdevice. Signed-off-by: Jacopo Mondi --- drivers/media/i2c/max9286.c | 53 +++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c index 8bfb88db9976..aca8455d6d56 100644 --- a/drivers/media/i2c/max9286.c +++ b/drivers/media/i2c/max9286.c @@ -878,6 +878,58 @@ static int max9286_set_fmt(struct v4l2_subdev *sd, return ret; } +static int max9286_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, + struct v4l2_mbus_frame_desc *fd) +{ + struct v4l2_subdev_route *route; + struct v4l2_subdev_state *state; + int ret = 0; + + if (pad != MAX9286_SRC_PAD) + return -EINVAL; + + state = v4l2_subdev_lock_active_state(sd); + + memset(fd, 0, sizeof(*fd)); + + /* One stream entry per each connected route. */ + for_each_active_route(&state->routing, route) { + struct v4l2_mbus_frame_desc_entry *entry = + &fd->entry[fd->num_entries]; + struct v4l2_mbus_framefmt *fmt; + + fmt = v4l2_state_get_stream_format(state, pad, + route->source_stream); + if (!fmt) { + ret = -EINVAL; + goto out; + } + + /* + * Assume a YUYV format (0x1e DT) and 16 bpp: we only support + * these formats at the moment. + */ + entry->stream = fd->num_entries++; + entry->flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX; + entry->length = fmt->width * fmt->height * 16 / 8; + entry->pixelcode = fmt->code; + + /* + * The source stream id corresponds to the virtual channel a + * stream is output on. + */ + entry->bus.csi2.vc = route->source_stream; + entry->bus.csi2.dt = 0x1e; + } + + fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2; + +out: + v4l2_subdev_unlock_state(state); + + return ret; +} + static int max9286_routing_verify(struct max9286_priv *priv, struct v4l2_subdev_krouting *routing) { @@ -1020,6 +1072,7 @@ static const struct v4l2_subdev_pad_ops max9286_pad_ops = { .enum_mbus_code = max9286_enum_mbus_code, .get_fmt = v4l2_subdev_get_fmt, .set_fmt = max9286_set_fmt, + .get_frame_desc = max9286_get_frame_desc, .set_routing = max9286_set_routing, }; From patchwork Sun Oct 17 18:24:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12564561 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F2DDBC433FE for ; Sun, 17 Oct 2021 18:24:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D9C2960FED for ; Sun, 17 Oct 2021 18:24:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344280AbhJQS0g (ORCPT ); Sun, 17 Oct 2021 14:26:36 -0400 Received: from relay12.mail.gandi.net ([217.70.178.232]:42113 "EHLO relay12.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344139AbhJQS0f (ORCPT ); Sun, 17 Oct 2021 14:26:35 -0400 Received: (Authenticated sender: jacopo@jmondi.org) by relay12.mail.gandi.net (Postfix) with ESMTPSA id 479E9200003; Sun, 17 Oct 2021 18:24:23 +0000 (UTC) From: Jacopo Mondi To: tomi.valkeinen@ideasonboard.com, sakari.ailus@linux.intel.com, laurent.pinchart@ideasonboard.com, niklas.soderlund@ragnatech.se, kieran.bingham@ideasonboard.com Cc: Jacopo Mondi , Mauro Carvalho Chehab , Hans Verkuil , linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH v2 08/13] media: rcar-csi2: Add support for v4l2_subdev_state Date: Sun, 17 Oct 2021 20:24:44 +0200 Message-Id: <20211017182449.64192-9-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211017182449.64192-1-jacopo+renesas@jmondi.org> References: <20211017182449.64192-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Create and initialize the v4l2_subdev_state for the R-Car CSI-2 receiver rder to prepare to support routing operations and multiplexed streams. 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 Reviewed-by: Laurent Pinchart --- drivers/media/platform/rcar-vin/rcar-csi2.c | 68 ++++++++++++++++++++- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index e28eff039688..a74087b49e71 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -752,11 +752,65 @@ 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) +{ + /* Initialize 4 routes from each source pad to the single sink pad. */ + 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_routing_simple_verify(&routing); + if (ret) + return ret; + + state = v4l2_subdev_validate_and_lock_state(sd, 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, }; @@ -1260,7 +1314,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; @@ -1276,14 +1331,22 @@ static int rcsi2_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); + ret = v4l2_subdev_init_finalize(&priv->subdev); + if (ret) + goto error_pm; + ret = v4l2_async_register_subdev(&priv->subdev); if (ret < 0) - goto error; + goto error_subdev; dev_info(priv->dev, "%d lanes found\n", priv->lanes); return 0; +error_subdev: + v4l2_subdev_cleanup(&priv->subdev); +error_pm: + pm_runtime_disable(&pdev->dev); error: v4l2_async_notifier_unregister(&priv->notifier); v4l2_async_notifier_cleanup(&priv->notifier); @@ -1298,6 +1361,7 @@ static int rcsi2_remove(struct platform_device *pdev) v4l2_async_notifier_unregister(&priv->notifier); v4l2_async_notifier_cleanup(&priv->notifier); v4l2_async_unregister_subdev(&priv->subdev); + v4l2_subdev_cleanup(&priv->subdev); pm_runtime_disable(&pdev->dev); From patchwork Sun Oct 17 18:24:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12564563 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9D0DBC433EF for ; Sun, 17 Oct 2021 18:24:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 86BBE60FED for ; Sun, 17 Oct 2021 18:24:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344320AbhJQS0h (ORCPT ); Sun, 17 Oct 2021 14:26:37 -0400 Received: from relay12.mail.gandi.net ([217.70.178.232]:57661 "EHLO relay12.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344139AbhJQS0g (ORCPT ); Sun, 17 Oct 2021 14:26:36 -0400 Received: (Authenticated sender: jacopo@jmondi.org) by relay12.mail.gandi.net (Postfix) with ESMTPSA id E440F200004; Sun, 17 Oct 2021 18:24:24 +0000 (UTC) From: Jacopo Mondi To: tomi.valkeinen@ideasonboard.com, sakari.ailus@linux.intel.com, laurent.pinchart@ideasonboard.com, niklas.soderlund@ragnatech.se, kieran.bingham@ideasonboard.com Cc: Jacopo Mondi , Mauro Carvalho Chehab , Hans Verkuil , linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH v2 09/13] media: rcar-csi2: Implement set_routing Date: Sun, 17 Oct 2021 20:24:45 +0200 Message-Id: <20211017182449.64192-10-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211017182449.64192-1-jacopo+renesas@jmondi.org> References: <20211017182449.64192-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add the set_routing() subdev operation to allow userspace to configure routing on the R-Car CSI-2 receiver. Signed-off-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- drivers/media/platform/rcar-vin/rcar-csi2.c | 40 +++++++++++++++------ 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index a74087b49e71..451a6da26e03 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -752,6 +752,33 @@ static int rcsi2_get_pad_format(struct v4l2_subdev *sd, return 0; } +static int _rcsi2_set_routing(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_krouting *routing) +{ + int ret; + + ret = v4l2_routing_simple_verify(routing); + if (ret) + return ret; + + state = v4l2_subdev_validate_and_lock_state(sd, state); + + ret = v4l2_subdev_set_routing(sd, state, routing); + + 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) { @@ -792,17 +819,7 @@ static int rcsi2_init_cfg(struct v4l2_subdev *sd, .routes = routes, }; - int ret = v4l2_routing_simple_verify(&routing); - if (ret) - return ret; - - state = v4l2_subdev_validate_and_lock_state(sd, 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 = { @@ -813,6 +830,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 = rcsi2_get_pad_format, + .set_routing = rcsi2_set_routing, }; static const struct v4l2_subdev_ops rcar_csi2_subdev_ops = { From patchwork Sun Oct 17 18:24:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12564565 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 03F0FC433F5 for ; Sun, 17 Oct 2021 18:24:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DE88D60F8F for ; Sun, 17 Oct 2021 18:24:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344343AbhJQS0j (ORCPT ); Sun, 17 Oct 2021 14:26:39 -0400 Received: from relay12.mail.gandi.net ([217.70.178.232]:44199 "EHLO relay12.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344139AbhJQS0i (ORCPT ); Sun, 17 Oct 2021 14:26:38 -0400 Received: (Authenticated sender: jacopo@jmondi.org) by relay12.mail.gandi.net (Postfix) with ESMTPSA id 8AAC4200005; Sun, 17 Oct 2021 18:24:26 +0000 (UTC) From: Jacopo Mondi To: tomi.valkeinen@ideasonboard.com, sakari.ailus@linux.intel.com, laurent.pinchart@ideasonboard.com, niklas.soderlund@ragnatech.se, kieran.bingham@ideasonboard.com Cc: Jacopo Mondi , Mauro Carvalho Chehab , Hans Verkuil , linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH v2 10/13] media: rcar-csi2: Move format to subdev state Date: Sun, 17 Oct 2021 20:24:46 +0200 Message-Id: <20211017182449.64192-11-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211017182449.64192-1-jacopo+renesas@jmondi.org> References: <20211017182449.64192-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@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 Reviewed-by: Laurent Pinchart --- drivers/media/platform/rcar-vin/rcar-csi2.c | 50 ++++++++++++--------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index 451a6da26e03..b60845b1e563 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -722,34 +722,42 @@ static int rcsi2_set_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); - struct v4l2_mbus_framefmt *framefmt; + struct v4l2_mbus_framefmt *fmt; + struct v4l2_subdev_state *state; + int ret = 0; 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; - } + /* + * 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; - return 0; -} + state = v4l2_subdev_validate_and_lock_state(sd, sd_state); + fmt = v4l2_state_get_stream_format(state, format->pad, + format->stream); + if (!fmt) { + ret = -EINVAL; + goto out; + } + *fmt = format->format; -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); + /* Propagate format to the other end of the route. */ + fmt = v4l2_state_get_opposite_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); +out: + v4l2_subdev_unlock_state(state); - return 0; + return ret; } static int _rcsi2_set_routing(struct v4l2_subdev *sd, @@ -829,7 +837,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, .set_routing = rcsi2_set_routing, }; From patchwork Sun Oct 17 18:24:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12564567 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3A989C433EF for ; Sun, 17 Oct 2021 18:24:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 245396103B for ; Sun, 17 Oct 2021 18:24:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344366AbhJQS0l (ORCPT ); Sun, 17 Oct 2021 14:26:41 -0400 Received: from relay12.mail.gandi.net ([217.70.178.232]:59439 "EHLO relay12.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344139AbhJQS0k (ORCPT ); Sun, 17 Oct 2021 14:26:40 -0400 Received: (Authenticated sender: jacopo@jmondi.org) by relay12.mail.gandi.net (Postfix) with ESMTPSA id 260DF200006; Sun, 17 Oct 2021 18:24:28 +0000 (UTC) From: Jacopo Mondi To: tomi.valkeinen@ideasonboard.com, sakari.ailus@linux.intel.com, laurent.pinchart@ideasonboard.com, niklas.soderlund@ragnatech.se, kieran.bingham@ideasonboard.com Cc: Jacopo Mondi , Mauro Carvalho Chehab , Hans Verkuil , linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org, =?utf-8?q?Niklas_S=C3=B6derlund?= Subject: [PATCH v2 11/13] media: rcar-csi2: Config by using the remote frame_desc Date: Sun, 17 Oct 2021 20:24:47 +0200 Message-Id: <20211017182449.64192-12-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211017182449.64192-1-jacopo+renesas@jmondi.org> References: <20211017182449.64192-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@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 | 145 +++++++++++++++----- 1 file changed, 110 insertions(+), 35 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index b60845b1e563..4ef7b9cb1ab7 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 @@ -339,6 +336,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, @@ -370,8 +378,6 @@ struct rcar_csi2 { struct v4l2_subdev *remote; unsigned int remote_pad; - struct v4l2_mbus_framefmt mf; - struct mutex lock; int stream_count; @@ -421,6 +427,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) { @@ -460,11 +492,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) @@ -480,12 +515,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; @@ -541,49 +594,64 @@ 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); + /* 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; - vcdt_part = VCDT_SEL_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 @@ -596,7 +664,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; @@ -894,6 +962,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 Sun Oct 17 18:24:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12564569 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3FF86C433F5 for ; Sun, 17 Oct 2021 18:24:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 273D660F8F for ; Sun, 17 Oct 2021 18:24:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344398AbhJQS0o (ORCPT ); Sun, 17 Oct 2021 14:26:44 -0400 Received: from relay12.mail.gandi.net ([217.70.178.232]:51111 "EHLO relay12.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344139AbhJQS0m (ORCPT ); Sun, 17 Oct 2021 14:26:42 -0400 Received: (Authenticated sender: jacopo@jmondi.org) by relay12.mail.gandi.net (Postfix) with ESMTPSA id F0CCE200004; Sun, 17 Oct 2021 18:24:29 +0000 (UTC) From: Jacopo Mondi To: tomi.valkeinen@ideasonboard.com, sakari.ailus@linux.intel.com, laurent.pinchart@ideasonboard.com, niklas.soderlund@ragnatech.se, kieran.bingham@ideasonboard.com Cc: Jacopo Mondi , Mauro Carvalho Chehab , Hans Verkuil , linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH v2 12/13] media: rcar-csi2: Implement .get_frame_desc() Date: Sun, 17 Oct 2021 20:24:48 +0200 Message-Id: <20211017182449.64192-13-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211017182449.64192-1-jacopo+renesas@jmondi.org> References: <20211017182449.64192-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Implement the get_frame_desc subdev pad operation. The operation informs the VIN entity to which the CSI-2 output channel is routed to about the CSI-2 Virtual Channel and the Datatype the transported stream is tagged with. Signed-off-by: Jacopo Mondi --- drivers/media/platform/rcar-vin/rcar-csi2.c | 63 +++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index 4ef7b9cb1ab7..7084ee06e99e 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -828,6 +828,68 @@ static int rcsi2_set_pad_format(struct v4l2_subdev *sd, return ret; } +/* + * The R-Car CSI-2 receivers are connected to the VINs (or ISP) by 'channels' + * not to be confused with CSI-2 Virtual Channels. + * + * Inform the VIN instance, to which the channel identified by the source pad is + * routed to, about the CSI-2 Virtual Channel and CSI-2 Datatype of the + * transported data stream. + */ +static int rcsi2_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, + struct v4l2_mbus_frame_desc *fd) +{ + struct v4l2_subdev_state *state; + struct v4l2_subdev_route *route; + int ret; + + if (pad < RCAR_CSI2_SOURCE_VC0 || pad > RCAR_CSI2_SOURCE_VC3) + return -EINVAL; + + state = v4l2_subdev_validate_and_lock_state(sd, state); + + memset(fd, 0, sizeof(*fd)); + + for_each_active_route(&state->routing, route) { + const struct rcar_csi2_format *rcsi2_fmt; + struct v4l2_mbus_framefmt *fmt; + + if (route->source_pad != pad) + continue; + + fmt = v4l2_state_get_stream_format(state, pad, + route->source_stream); + if (!fmt) { + ret = -EINVAL; + goto out; + } + + rcsi2_fmt = rcsi2_code_to_fmt(fmt->code); + + /* Only one stream per 'channel' is allowed. */ + fd->entry[0].pixelcode = fmt->code; + fd->entry[0].length = fmt->width * fmt->height * rcsi2_fmt->bpp / 8; + fd->entry[0].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX; + + /* + * The sink stream id corresponds to the CSI-2 Virtual Channel + * which is output on the channel identified by the current + * source pad. + */ + fd->entry[0].bus.csi2.vc = route->source_stream; + fd->entry[0].bus.csi2.dt = rcsi2_fmt->datatype; + + break; + } + fd->num_entries = 1; + fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2; + +out: + v4l2_subdev_unlock_state(state); + + return ret; +} + static int _rcsi2_set_routing(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, struct v4l2_subdev_krouting *routing) @@ -906,6 +968,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, + .get_frame_desc = rcsi2_get_frame_desc, .set_routing = rcsi2_set_routing, }; From patchwork Sun Oct 17 18:24:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 12564571 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 64BECC433EF for ; Sun, 17 Oct 2021 18:24:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4B93661039 for ; Sun, 17 Oct 2021 18:24:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344415AbhJQS0r (ORCPT ); Sun, 17 Oct 2021 14:26:47 -0400 Received: from relay12.mail.gandi.net ([217.70.178.232]:60629 "EHLO relay12.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344382AbhJQS0o (ORCPT ); Sun, 17 Oct 2021 14:26:44 -0400 Received: (Authenticated sender: jacopo@jmondi.org) by relay12.mail.gandi.net (Postfix) with ESMTPSA id A4407200005; Sun, 17 Oct 2021 18:24:31 +0000 (UTC) From: Jacopo Mondi To: tomi.valkeinen@ideasonboard.com, sakari.ailus@linux.intel.com, laurent.pinchart@ideasonboard.com, niklas.soderlund@ragnatech.se, kieran.bingham@ideasonboard.com Cc: Jacopo Mondi , Mauro Carvalho Chehab , Hans Verkuil , linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org Subject: [PATCH v2 13/13] media: rcar-vin: Support multiplexed CSI-2 receiver Date: Sun, 17 Oct 2021 20:24:49 +0200 Message-Id: <20211017182449.64192-14-jacopo+renesas@jmondi.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211017182449.64192-1-jacopo+renesas@jmondi.org> References: <20211017182449.64192-1-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The R-Car CSI-2 receiver supports multiplexed streams. The VIN driver inspects the CSI-2 subdevice format with the intent of validating formats at stream start time. Each VIN instance is connected to a CSI-2 receiver which exposes a single stream and since it has acquired support for multiplexed streams maintains the format information in its v4l2_subdev_state per-stream. Instrument the VIN driver to fetch the CSI-2 receiver format from the streams configuration by setting the stream identifier to 0 and pass to the subdevice its own state where to retrieve format information from. 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 83b2f923cf98..a6f3701f3f3f 100644 --- a/drivers/media/platform/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/rcar-vin/rcar-dma.c @@ -1119,7 +1119,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)) + fmt.stream = 0; + if (v4l2_subdev_call(sd, pad, get_fmt, sd->state, &fmt)) return -EPIPE; switch (fmt.format.code) {