Switch to Streams API with a single hardcoded route. This breaks any
existing userspace which depended on the custom rcar streams
implementation, but a single camera use case should continue to work.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
---
drivers/media/platform/renesas/rcar-csi2.c | 47 +++++++++++++++++++++---------
1 file changed, 33 insertions(+), 14 deletions(-)
diff --git a/drivers/media/platform/renesas/rcar-csi2.c b/drivers/media/platform/renesas/rcar-csi2.c
index e0a0fd96459b..20bd44274bd2 100644
--- a/drivers/media/platform/renesas/rcar-csi2.c
+++ b/drivers/media/platform/renesas/rcar-csi2.c
@@ -1028,7 +1028,7 @@ static int rcsi2_calc_mbps(struct rcar_csi2 *priv,
if (ret)
return ret;
- fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK);
+ fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK, 0);
if (!fmt)
return -EINVAL;
@@ -1069,7 +1069,7 @@ static int rcsi2_start_receiver_gen3(struct rcar_csi2 *priv,
int mbps, ret;
/* Use the format on the sink pad to compute the receiver config. */
- fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK);
+ fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK, 0);
dev_dbg(priv->dev, "Input size (%ux%u%c)\n",
fmt->width, fmt->height,
@@ -1650,8 +1650,7 @@ static int rcsi2_set_pad_format(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state,
struct v4l2_subdev_format *format)
{
- struct rcar_csi2 *priv = sd_to_csi2(sd);
- unsigned int num_pads = rcsi2_num_pads(priv);
+ struct v4l2_mbus_framefmt *fmt;
if (format->pad > RCAR_CSI2_SINK)
return v4l2_subdev_get_fmt(sd, state, format);
@@ -1659,11 +1658,20 @@ static int rcsi2_set_pad_format(struct v4l2_subdev *sd,
if (!rcsi2_code_to_fmt(format->format.code))
format->format.code = rcar_csi2_formats[0].code;
- *v4l2_subdev_state_get_format(state, format->pad) = format->format;
+ /* Set sink format */
+ fmt = v4l2_subdev_state_get_format(state, format->pad, format->stream);
+ if (!fmt)
+ return -EINVAL;
+
+ *fmt = format->format;
+
+ /* Propagate to source format */
+ fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
+ format->stream);
+ if (!fmt)
+ return -EINVAL;
- /* Propagate the format to the source pads. */
- for (unsigned int i = RCAR_CSI2_SOURCE_VC0; i < num_pads; i++)
- *v4l2_subdev_state_get_format(state, i) = format->format;
+ *fmt = format->format;
return 0;
}
@@ -1683,8 +1691,15 @@ static const struct v4l2_subdev_ops rcar_csi2_subdev_ops = {
static int rcsi2_init_state(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state)
{
- struct rcar_csi2 *priv = sd_to_csi2(sd);
- unsigned int num_pads = rcsi2_num_pads(priv);
+ static 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,
+ },
+ };
static const struct v4l2_mbus_framefmt rcar_csi2_default_fmt = {
.width = 1920,
@@ -1697,10 +1712,13 @@ static int rcsi2_init_state(struct v4l2_subdev *sd,
.xfer_func = V4L2_XFER_FUNC_DEFAULT,
};
- for (unsigned int i = RCAR_CSI2_SINK; i < num_pads; i++)
- *v4l2_subdev_state_get_format(state, i) = rcar_csi2_default_fmt;
+ static const struct v4l2_subdev_krouting routing = {
+ .num_routes = ARRAY_SIZE(routes),
+ .routes = routes,
+ };
- return 0;
+ return v4l2_subdev_set_routing_with_fmt(sd, state, &routing,
+ &rcar_csi2_default_fmt);
}
static const struct v4l2_subdev_internal_ops rcar_csi2_internal_ops = {
@@ -2356,7 +2374,8 @@ static int rcsi2_probe(struct platform_device *pdev)
v4l2_set_subdevdata(&priv->subdev, &pdev->dev);
snprintf(priv->subdev.name, sizeof(priv->subdev.name), "%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_STREAMS;
priv->subdev.entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
priv->subdev.entity.ops = &rcar_csi2_entity_ops;
--
2.43.0
Hi Tomi,
Thanks for your patch.
On 2025-05-30 16:50:37 +0300, Tomi Valkeinen wrote:
> Switch to Streams API with a single hardcoded route. This breaks any
> existing userspace which depended on the custom rcar streams
> implementation, but a single camera use case should continue to work.
>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> ---
> drivers/media/platform/renesas/rcar-csi2.c | 47 +++++++++++++++++++++---------
> 1 file changed, 33 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/media/platform/renesas/rcar-csi2.c b/drivers/media/platform/renesas/rcar-csi2.c
> index e0a0fd96459b..20bd44274bd2 100644
> --- a/drivers/media/platform/renesas/rcar-csi2.c
> +++ b/drivers/media/platform/renesas/rcar-csi2.c
> @@ -1028,7 +1028,7 @@ static int rcsi2_calc_mbps(struct rcar_csi2 *priv,
> if (ret)
> return ret;
>
> - fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK);
> + fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK, 0);
> if (!fmt)
> return -EINVAL;
>
> @@ -1069,7 +1069,7 @@ static int rcsi2_start_receiver_gen3(struct rcar_csi2 *priv,
> int mbps, ret;
>
> /* Use the format on the sink pad to compute the receiver config. */
> - fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK);
> + fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK, 0);
>
> dev_dbg(priv->dev, "Input size (%ux%u%c)\n",
> fmt->width, fmt->height,
> @@ -1650,8 +1650,7 @@ static int rcsi2_set_pad_format(struct v4l2_subdev *sd,
> struct v4l2_subdev_state *state,
> struct v4l2_subdev_format *format)
> {
> - struct rcar_csi2 *priv = sd_to_csi2(sd);
> - unsigned int num_pads = rcsi2_num_pads(priv);
> + struct v4l2_mbus_framefmt *fmt;
>
> if (format->pad > RCAR_CSI2_SINK)
> return v4l2_subdev_get_fmt(sd, state, format);
> @@ -1659,11 +1658,20 @@ static int rcsi2_set_pad_format(struct v4l2_subdev *sd,
> if (!rcsi2_code_to_fmt(format->format.code))
> format->format.code = rcar_csi2_formats[0].code;
>
> - *v4l2_subdev_state_get_format(state, format->pad) = format->format;
> + /* Set sink format */
> + fmt = v4l2_subdev_state_get_format(state, format->pad, format->stream);
> + if (!fmt)
> + return -EINVAL;
> +
> + *fmt = format->format;
> +
> + /* Propagate to source format */
> + fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
> + format->stream);
> + if (!fmt)
> + return -EINVAL;
>
> - /* Propagate the format to the source pads. */
> - for (unsigned int i = RCAR_CSI2_SOURCE_VC0; i < num_pads; i++)
> - *v4l2_subdev_state_get_format(state, i) = format->format;
> + *fmt = format->format;
>
> return 0;
> }
> @@ -1683,8 +1691,15 @@ static const struct v4l2_subdev_ops rcar_csi2_subdev_ops = {
> static int rcsi2_init_state(struct v4l2_subdev *sd,
> struct v4l2_subdev_state *state)
> {
> - struct rcar_csi2 *priv = sd_to_csi2(sd);
> - unsigned int num_pads = rcsi2_num_pads(priv);
> + static 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,
> + },
> + };
>
> static const struct v4l2_mbus_framefmt rcar_csi2_default_fmt = {
> .width = 1920,
> @@ -1697,10 +1712,13 @@ static int rcsi2_init_state(struct v4l2_subdev *sd,
> .xfer_func = V4L2_XFER_FUNC_DEFAULT,
> };
>
> - for (unsigned int i = RCAR_CSI2_SINK; i < num_pads; i++)
> - *v4l2_subdev_state_get_format(state, i) = rcar_csi2_default_fmt;
> + static const struct v4l2_subdev_krouting routing = {
> + .num_routes = ARRAY_SIZE(routes),
> + .routes = routes,
> + };
>
> - return 0;
> + return v4l2_subdev_set_routing_with_fmt(sd, state, &routing,
> + &rcar_csi2_default_fmt);
> }
>
> static const struct v4l2_subdev_internal_ops rcar_csi2_internal_ops = {
> @@ -2356,7 +2374,8 @@ static int rcsi2_probe(struct platform_device *pdev)
> v4l2_set_subdevdata(&priv->subdev, &pdev->dev);
> snprintf(priv->subdev.name, sizeof(priv->subdev.name), "%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_STREAMS;
>
> priv->subdev.entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
> priv->subdev.entity.ops = &rcar_csi2_entity_ops;
>
> --
> 2.43.0
>
--
Kind Regards,
Niklas Söderlund
Hi Tomi,
Thank you for the patch.
On Fri, May 30, 2025 at 04:50:37PM +0300, Tomi Valkeinen wrote:
> Switch to Streams API with a single hardcoded route. This breaks any
> existing userspace which depended on the custom rcar streams
> implementation, but a single camera use case should continue to work.
>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
> ---
> drivers/media/platform/renesas/rcar-csi2.c | 47 +++++++++++++++++++++---------
> 1 file changed, 33 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/media/platform/renesas/rcar-csi2.c b/drivers/media/platform/renesas/rcar-csi2.c
> index e0a0fd96459b..20bd44274bd2 100644
> --- a/drivers/media/platform/renesas/rcar-csi2.c
> +++ b/drivers/media/platform/renesas/rcar-csi2.c
> @@ -1028,7 +1028,7 @@ static int rcsi2_calc_mbps(struct rcar_csi2 *priv,
> if (ret)
> return ret;
>
> - fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK);
> + fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK, 0);
> if (!fmt)
> return -EINVAL;
>
> @@ -1069,7 +1069,7 @@ static int rcsi2_start_receiver_gen3(struct rcar_csi2 *priv,
> int mbps, ret;
>
> /* Use the format on the sink pad to compute the receiver config. */
> - fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK);
> + fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK, 0);
>
> dev_dbg(priv->dev, "Input size (%ux%u%c)\n",
> fmt->width, fmt->height,
> @@ -1650,8 +1650,7 @@ static int rcsi2_set_pad_format(struct v4l2_subdev *sd,
> struct v4l2_subdev_state *state,
> struct v4l2_subdev_format *format)
> {
> - struct rcar_csi2 *priv = sd_to_csi2(sd);
> - unsigned int num_pads = rcsi2_num_pads(priv);
> + struct v4l2_mbus_framefmt *fmt;
>
> if (format->pad > RCAR_CSI2_SINK)
> return v4l2_subdev_get_fmt(sd, state, format);
> @@ -1659,11 +1658,20 @@ static int rcsi2_set_pad_format(struct v4l2_subdev *sd,
> if (!rcsi2_code_to_fmt(format->format.code))
> format->format.code = rcar_csi2_formats[0].code;
>
> - *v4l2_subdev_state_get_format(state, format->pad) = format->format;
> + /* Set sink format */
s/format/format./
> + fmt = v4l2_subdev_state_get_format(state, format->pad, format->stream);
> + if (!fmt)
> + return -EINVAL;
> +
> + *fmt = format->format;
> +
> + /* Propagate to source format */
Same here. Although I'd write
/* Propagate the format to the source pad. */
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> + fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
> + format->stream);
> + if (!fmt)
> + return -EINVAL;
>
> - /* Propagate the format to the source pads. */
> - for (unsigned int i = RCAR_CSI2_SOURCE_VC0; i < num_pads; i++)
> - *v4l2_subdev_state_get_format(state, i) = format->format;
> + *fmt = format->format;
>
> return 0;
> }
> @@ -1683,8 +1691,15 @@ static const struct v4l2_subdev_ops rcar_csi2_subdev_ops = {
> static int rcsi2_init_state(struct v4l2_subdev *sd,
> struct v4l2_subdev_state *state)
> {
> - struct rcar_csi2 *priv = sd_to_csi2(sd);
> - unsigned int num_pads = rcsi2_num_pads(priv);
> + static 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,
> + },
> + };
>
> static const struct v4l2_mbus_framefmt rcar_csi2_default_fmt = {
> .width = 1920,
> @@ -1697,10 +1712,13 @@ static int rcsi2_init_state(struct v4l2_subdev *sd,
> .xfer_func = V4L2_XFER_FUNC_DEFAULT,
> };
>
> - for (unsigned int i = RCAR_CSI2_SINK; i < num_pads; i++)
> - *v4l2_subdev_state_get_format(state, i) = rcar_csi2_default_fmt;
> + static const struct v4l2_subdev_krouting routing = {
> + .num_routes = ARRAY_SIZE(routes),
> + .routes = routes,
> + };
>
> - return 0;
> + return v4l2_subdev_set_routing_with_fmt(sd, state, &routing,
> + &rcar_csi2_default_fmt);
> }
>
> static const struct v4l2_subdev_internal_ops rcar_csi2_internal_ops = {
> @@ -2356,7 +2374,8 @@ static int rcsi2_probe(struct platform_device *pdev)
> v4l2_set_subdevdata(&priv->subdev, &pdev->dev);
> snprintf(priv->subdev.name, sizeof(priv->subdev.name), "%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_STREAMS;
>
> priv->subdev.entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
> priv->subdev.entity.ops = &rcar_csi2_entity_ops;
--
Regards,
Laurent Pinchart
Hi,
On 02/06/2025 17:06, Laurent Pinchart wrote:
> Hi Tomi,
>
> Thank you for the patch.
>
> On Fri, May 30, 2025 at 04:50:37PM +0300, Tomi Valkeinen wrote:
>> Switch to Streams API with a single hardcoded route. This breaks any
>> existing userspace which depended on the custom rcar streams
>> implementation, but a single camera use case should continue to work.
>>
>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
>> ---
>> drivers/media/platform/renesas/rcar-csi2.c | 47 +++++++++++++++++++++---------
>> 1 file changed, 33 insertions(+), 14 deletions(-)
>>
>> diff --git a/drivers/media/platform/renesas/rcar-csi2.c b/drivers/media/platform/renesas/rcar-csi2.c
>> index e0a0fd96459b..20bd44274bd2 100644
>> --- a/drivers/media/platform/renesas/rcar-csi2.c
>> +++ b/drivers/media/platform/renesas/rcar-csi2.c
>> @@ -1028,7 +1028,7 @@ static int rcsi2_calc_mbps(struct rcar_csi2 *priv,
>> if (ret)
>> return ret;
>>
>> - fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK);
>> + fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK, 0);
>> if (!fmt)
>> return -EINVAL;
>>
>> @@ -1069,7 +1069,7 @@ static int rcsi2_start_receiver_gen3(struct rcar_csi2 *priv,
>> int mbps, ret;
>>
>> /* Use the format on the sink pad to compute the receiver config. */
>> - fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK);
>> + fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK, 0);
>>
>> dev_dbg(priv->dev, "Input size (%ux%u%c)\n",
>> fmt->width, fmt->height,
>> @@ -1650,8 +1650,7 @@ static int rcsi2_set_pad_format(struct v4l2_subdev *sd,
>> struct v4l2_subdev_state *state,
>> struct v4l2_subdev_format *format)
>> {
>> - struct rcar_csi2 *priv = sd_to_csi2(sd);
>> - unsigned int num_pads = rcsi2_num_pads(priv);
>> + struct v4l2_mbus_framefmt *fmt;
>>
>> if (format->pad > RCAR_CSI2_SINK)
>> return v4l2_subdev_get_fmt(sd, state, format);
>> @@ -1659,11 +1658,20 @@ static int rcsi2_set_pad_format(struct v4l2_subdev *sd,
>> if (!rcsi2_code_to_fmt(format->format.code))
>> format->format.code = rcar_csi2_formats[0].code;
>>
>> - *v4l2_subdev_state_get_format(state, format->pad) = format->format;
>> + /* Set sink format */
>
> s/format/format./
Ok.
>> + fmt = v4l2_subdev_state_get_format(state, format->pad, format->stream);
>> + if (!fmt)
>> + return -EINVAL;
>> +
>> + *fmt = format->format;
>> +
>> + /* Propagate to source format */
>
> Same here. Although I'd write
>
> /* Propagate the format to the source pad. */
Ok. Although maybe "source stream" would be better. Then again, that's
on a source pad, so... =)
Tomi
> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
>
>> + fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
>> + format->stream);
>> + if (!fmt)
>> + return -EINVAL;
>>
>> - /* Propagate the format to the source pads. */
>> - for (unsigned int i = RCAR_CSI2_SOURCE_VC0; i < num_pads; i++)
>> - *v4l2_subdev_state_get_format(state, i) = format->format;
>> + *fmt = format->format;
>>
>> return 0;
>> }
>> @@ -1683,8 +1691,15 @@ static const struct v4l2_subdev_ops rcar_csi2_subdev_ops = {
>> static int rcsi2_init_state(struct v4l2_subdev *sd,
>> struct v4l2_subdev_state *state)
>> {
>> - struct rcar_csi2 *priv = sd_to_csi2(sd);
>> - unsigned int num_pads = rcsi2_num_pads(priv);
>> + static 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,
>> + },
>> + };
>>
>> static const struct v4l2_mbus_framefmt rcar_csi2_default_fmt = {
>> .width = 1920,
>> @@ -1697,10 +1712,13 @@ static int rcsi2_init_state(struct v4l2_subdev *sd,
>> .xfer_func = V4L2_XFER_FUNC_DEFAULT,
>> };
>>
>> - for (unsigned int i = RCAR_CSI2_SINK; i < num_pads; i++)
>> - *v4l2_subdev_state_get_format(state, i) = rcar_csi2_default_fmt;
>> + static const struct v4l2_subdev_krouting routing = {
>> + .num_routes = ARRAY_SIZE(routes),
>> + .routes = routes,
>> + };
>>
>> - return 0;
>> + return v4l2_subdev_set_routing_with_fmt(sd, state, &routing,
>> + &rcar_csi2_default_fmt);
>> }
>>
>> static const struct v4l2_subdev_internal_ops rcar_csi2_internal_ops = {
>> @@ -2356,7 +2374,8 @@ static int rcsi2_probe(struct platform_device *pdev)
>> v4l2_set_subdevdata(&priv->subdev, &pdev->dev);
>> snprintf(priv->subdev.name, sizeof(priv->subdev.name), "%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_STREAMS;
>>
>> priv->subdev.entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
>> priv->subdev.entity.ops = &rcar_csi2_entity_ops;
>
© 2016 - 2025 Red Hat, Inc.