linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
To: Pratyush Yadav <p.yadav@ti.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
	Lokesh Vutla <lokeshvutla@ti.com>,
	linux-media@vger.kernel.org
Subject: Re: [PATCH v3 38/38] media: ti-vpe: cal: add multiplexed streams support
Date: Tue, 3 Aug 2021 17:51:08 +0300	[thread overview]
Message-ID: <a31cd6fd-a037-b1d8-0d14-7c86bd89aa5f@ideasonboard.com> (raw)
In-Reply-To: <20210803102153.zwdydnrhyhclstb4@ti.com>

Hi,

On 03/08/2021 13:21, Pratyush Yadav wrote:
> Hi Tomi,
> 
> Thanks for your work on this. I have used your patches to add
> multiplexed stream support on J721E. A few thoughts below that came to
> my mind when implementing it.

That's great to hear!

> On 24/05/21 02:09PM, Tomi Valkeinen wrote:
>> Add routing and stream_config support to CAL driver.
>>
>> Add multiplexed streams support. CAL has 8 dma-engines and can capture 8
>> separate streams at the same time.
>>
>> Add 8 video device nodes, each representing a single dma-engine, and set
>> the number of source pads on camerarx to 8. Each video node can be
>> connected to any of the source pads on either of the camerarx instances
>> using media links. Camerarx internal routing is used to route the
>> incoming CSI-2 streams to one of the 8 source pads.
>>
>> CAL doesn't support transcoding, so the driver currently allows changes
>> only on the camerarx sink side, and then copies the sink pad config to
>> the source pad. This becomes slighly more complex with 8 source pads and
>> multiple streams on the sink pad. A helper,
>> cal_camerarx_get_opposite_stream_format(), is added, which uses the
>> routing table to get the format from the "opposite" side.
>>
>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
>> ---
>>   drivers/media/platform/ti-vpe/cal-camerarx.c | 303 ++++++++++++++++---
>>   drivers/media/platform/ti-vpe/cal-video.c    | 103 ++++++-
>>   drivers/media/platform/ti-vpe/cal.c          |  34 ++-
>>   drivers/media/platform/ti-vpe/cal.h          |  12 +-
>>   4 files changed, 385 insertions(+), 67 deletions(-)
>>
>> diff --git a/drivers/media/platform/ti-vpe/cal-camerarx.c b/drivers/media/platform/ti-vpe/cal-camerarx.c
>> index cb6a37f47432..d09b06780b15 100644
>> --- a/drivers/media/platform/ti-vpe/cal-camerarx.c
>> +++ b/drivers/media/platform/ti-vpe/cal-camerarx.c
>> @@ -49,15 +49,33 @@ static s64 cal_camerarx_get_ext_link_freq(struct cal_camerarx *phy)
>>   {
>>   	struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 = &phy->endpoint.bus.mipi_csi2;
>>   	u32 num_lanes = mipi_csi2->num_data_lanes;
>> -	const struct cal_format_info *fmtinfo;
>>   	u32 bpp;
>>   	s64 freq;
>>   
>> -	fmtinfo = cal_format_by_code(phy->formats[CAL_CAMERARX_PAD_SINK].code);
>> -	if (!fmtinfo)
>> +	/*
>> +	 * With multistream input we don't have bpp, and cannot use
>> +	 * V4L2_CID_PIXEL_RATE. Passing 0 as bpp causes v4l2_get_link_freq()
>> +	 * to return an error if it falls back to V4L2_CID_PIXEL_RATE.
>> +	 */
>> +
>> +	if (phy->stream_configs.num_configs == 0)
>>   		return -EINVAL;
>>   
>> -	bpp = fmtinfo->bpp;
>> +	if (phy->stream_configs.num_configs > 2) {
>> +		bpp = 0;
>> +	} else {
>> +		const struct cal_format_info *fmtinfo;
>> +		struct v4l2_mbus_framefmt *fmt;
>> +
>> +		/* The first format is for the sink */
>> +		fmt = &phy->stream_configs.configs[0].fmt;
>> +
>> +		fmtinfo = cal_format_by_code(fmt->code);
>> +		if (!fmtinfo)
>> +			return -EINVAL;
>> +
>> +		bpp = fmtinfo->bpp;
>> +	}
>>   
>>   	freq = v4l2_get_link_freq(phy->source->ctrl_handler, bpp, 2 * num_lanes);
>>   	if (freq < 0) {
>> @@ -619,19 +637,104 @@ static inline struct cal_camerarx *to_cal_camerarx(struct v4l2_subdev *sd)
>>   	return container_of(sd, struct cal_camerarx, subdev);
>>   }
>>   
>> -static struct v4l2_mbus_framefmt *
>> -cal_camerarx_get_pad_format(struct cal_camerarx *phy,
>> -			    struct v4l2_subdev_state *sd_state,
>> -			    unsigned int pad, u32 which)
>> -{
>> -	switch (which) {
>> -	case V4L2_SUBDEV_FORMAT_TRY:
>> -		return v4l2_subdev_get_try_format(&phy->subdev, sd_state, pad);
>> -	case V4L2_SUBDEV_FORMAT_ACTIVE:
>> -		return &phy->formats[pad];
>> -	default:
>> +struct cal_camerarx *
>> +cal_camerarx_get_phy_from_entity(struct media_entity *entity)
>> +{
>> +	struct v4l2_subdev *sd;
>> +
>> +	sd = media_entity_to_v4l2_subdev(entity);
>> +	if (!sd)
>>   		return NULL;
>> +
>> +	return to_cal_camerarx(sd);
>> +}
>> +
>> +static struct v4l2_subdev_krouting *
>> +cal_camerarx_get_routing_table(struct cal_camerarx *phy,
>> +			       struct v4l2_subdev_state *sd_state, u32 which)
>> +{
>> +	if (which == V4L2_SUBDEV_FORMAT_ACTIVE)
>> +		return &phy->routing;
>> +	else
>> +		return &sd_state->routing;
>> +}
>> +
>> +static struct v4l2_subdev_stream_configs *
>> +cal_camerarx_get_stream_configs(struct cal_camerarx *phy,
>> +				struct v4l2_subdev_state *sd_state, u32 which)
>> +{
>> +	if (which == V4L2_SUBDEV_FORMAT_ACTIVE)
>> +		return &phy->stream_configs;
>> +	else
>> +		return &sd_state->stream_configs;
>> +}
>> +
>> +struct v4l2_mbus_framefmt *
>> +cal_camerarx_get_stream_format(struct cal_camerarx *phy,
>> +			       struct v4l2_subdev_state *sd_state,
>> +			       unsigned int pad, u32 stream, u32 which)
>> +{
>> +	struct v4l2_subdev_stream_configs *stream_configs;
>> +	unsigned int i;
>> +
>> +	stream_configs = cal_camerarx_get_stream_configs(phy, sd_state, which);
>> +
>> +	for (i = 0; i < stream_configs->num_configs; ++i) {
>> +		if (stream_configs->configs[i].pad == pad &&
>> +		    stream_configs->configs[i].stream == stream)
>> +			return &stream_configs->configs[i].fmt;
>> +	}
>> +
>> +	return NULL;
>> +}
>> +
>> +static int cal_camerarx_find_opposite_end(struct v4l2_subdev_krouting *routing,
>> +					  u32 pad, u32 stream, u32 *other_pad,
>> +					  u32 *other_stream)
>> +{
>> +	unsigned int i;
>> +
>> +	for (i = 0; i < routing->num_routes; ++i) {
>> +		struct v4l2_subdev_route *route = &routing->routes[i];
>> +
>> +		if (cal_rx_pad_is_source(pad)) {
>> +			if (route->source_pad == pad &&
>> +			    route->source_stream == stream) {
>> +				*other_pad = route->sink_pad;
>> +				*other_stream = route->sink_stream;
>> +				return 0;
>> +			}
>> +		} else {
>> +			if (route->sink_pad == pad &&
>> +			    route->sink_stream == stream) {
>> +				*other_pad = route->source_pad;
>> +				*other_stream = route->source_stream;
>> +				return 0;
>> +			}
>> +		}
>>   	}
>> +
>> +	return -EINVAL;
>> +}
>> +
>> +static struct v4l2_mbus_framefmt *
>> +cal_camerarx_get_opposite_stream_format(struct cal_camerarx *phy,
>> +					struct v4l2_subdev_state *sd_state,
>> +					u32 pad, u32 stream, u32 which)
>> +{
>> +	struct v4l2_subdev_krouting *routing;
>> +	u32 other_pad, other_stream;
>> +	int ret;
>> +
>> +	routing = cal_camerarx_get_routing_table(phy, sd_state, which);
>> +
>> +	ret = cal_camerarx_find_opposite_end(routing, pad, stream, &other_pad,
>> +					     &other_stream);
>> +	if (ret)
>> +		return NULL;
>> +
>> +	return cal_camerarx_get_stream_format(phy, sd_state, other_pad,
>> +					      other_stream, which);
>>   }
> 
> Would it make sense to move these functions to v4l2 core to reduce
> boilerplate in drivers? Are they generic enough?

Yes, I have moved all these to the core in my WIP branch.

>>   static int cal_camerarx_sd_s_stream(struct v4l2_subdev *sd, int enable)
>> @@ -669,9 +772,15 @@ static int cal_camerarx_sd_enum_mbus_code(struct v4l2_subdev *sd,
>>   			goto out;
>>   		}
>>   
>> -		fmt = cal_camerarx_get_pad_format(phy, sd_state,
>> -						  CAL_CAMERARX_PAD_SINK,
>> -						  code->which);
>> +		fmt = cal_camerarx_get_opposite_stream_format(phy, sd_state,
>> +					code->pad, code->stream,
>> +					code->which);
>> +
>> +		if (!fmt) {
>> +			r = -EINVAL;
>> +			goto out;
>> +		}
>> +
>>   		code->code = fmt->code;
>>   	} else {
>>   		if (code->index >= cal_num_formats) {
>> @@ -705,9 +814,14 @@ static int cal_camerarx_sd_enum_frame_size(struct v4l2_subdev *sd,
>>   	if (cal_rx_pad_is_source(fse->pad)) {
>>   		struct v4l2_mbus_framefmt *fmt;
>>   
>> -		fmt = cal_camerarx_get_pad_format(phy, sd_state,
>> -						  CAL_CAMERARX_PAD_SINK,
>> -						  fse->which);
>> +		fmt = cal_camerarx_get_opposite_stream_format(
>> +			phy, sd_state, fse->pad, fse->stream, fse->which);
>> +
>> +		if (!fmt) {
>> +			r = -EINVAL;
>> +			goto out;
>> +		}
>> +
>>   		if (fse->code != fmt->code) {
>>   			r = -EINVAL;
>>   			goto out;
>> @@ -747,8 +861,14 @@ static int cal_camerarx_sd_get_fmt(struct v4l2_subdev *sd,
>>   
>>   	mutex_lock(&phy->mutex);
>>   
>> -	fmt = cal_camerarx_get_pad_format(phy, sd_state, format->pad,
>> -					  format->which);
>> +	fmt = cal_camerarx_get_stream_format(phy, sd_state, format->pad,
>> +					     format->stream, format->which);
>> +
>> +	if (!fmt) {
>> +		mutex_unlock(&phy->mutex);
>> +		return -EINVAL;
>> +	}
>> +
>>   	format->format = *fmt;
>>   
>>   	mutex_unlock(&phy->mutex);
>> @@ -764,6 +884,7 @@ static int cal_camerarx_sd_set_fmt(struct v4l2_subdev *sd,
>>   	const struct cal_format_info *fmtinfo;
>>   	struct v4l2_mbus_framefmt *fmt;
>>   	unsigned int bpp;
>> +	int ret = 0;
>>   
>>   	/* No transcoding, source and sink formats must match. */
> 
> If the bridge can't transcode, does it need {get,set}_fmt ops at all?

I don't know what is the official rule here (if any). But I think the 
code that verifies the media pipeline before the start won't be able to 
verify (just skips the verification) if the subdev doesn't support get_fmt.

> What does it do with this information?

Well, CAL driver has the ops because they were there for non-multiplexed 
case too. I can't say right away if CAL could do without those for 
multiplexed use.

> For example, on the cdns-csi2rx bridge driver used on J721E, I did not
> implement these ops at all. You can simply program the hardware to let
> everything through. The only time the bridge needs to know the format is
> when it needs to convert pixel rate to link frequency, but that can be
> done by asking the source.

What happens if the source is also pass-through, and doesn't implement 
these ops? You need a function to traverse the graph and find a subdev 
that has the format.

>>   	if (cal_rx_pad_is_source(format->pad))
>> @@ -792,40 +913,117 @@ static int cal_camerarx_sd_set_fmt(struct v4l2_subdev *sd,
>>   	/* Store the format and propagate it to the source pad. */
>>   	mutex_lock(&phy->mutex);
>>   
>> -	fmt = cal_camerarx_get_pad_format(phy, sd_state,
>> -					  CAL_CAMERARX_PAD_SINK,
>> -					  format->which);
>> +	fmt = cal_camerarx_get_stream_format(phy, sd_state, format->pad,
>> +					     format->stream, format->which);
>> +	if (!fmt) {
>> +		ret = -EINVAL;
>> +		goto out;
>> +	}
>> +
>>   	*fmt = format->format;
>>   
>> -	fmt = cal_camerarx_get_pad_format(phy, sd_state, CAL_CAMERARX_PAD_FIRST_SOURCE,
>> -					  format->which);
>> +	fmt = cal_camerarx_get_opposite_stream_format(phy, sd_state, format->pad,
>> +						      format->stream,
>> +						      format->which);
>> +	if (!fmt) {
>> +		ret = -EINVAL;
>> +		goto out;
>> +	}
>> +
>>   	*fmt = format->format;
>>   
>> +out:
>>   	mutex_unlock(&phy->mutex);
>>   
>> +	return ret;
>> +}
>> +
>> +static int cal_camerarx_sd_get_routing(struct v4l2_subdev *sd,
>> +				       struct v4l2_subdev_state *sd_state,
>> +				       struct v4l2_subdev_krouting *routing)
>> +{
>> +	struct cal_camerarx *phy = to_cal_camerarx(sd);
>> +	struct v4l2_subdev_krouting *src;
>> +
>> +	src = cal_camerarx_get_routing_table(phy, sd_state, routing->which);
>> +
>> +	return v4l2_subdev_cpy_routing(routing, src);
>> +}
>> +
>> +static void cal_camerarx_init_formats(struct v4l2_subdev *sd,
>> +				      struct v4l2_subdev_state *sd_state,
>> +				      u32 which)
>> +{
>> +	struct cal_camerarx *phy = to_cal_camerarx(sd);
>> +
>> +	static const struct v4l2_mbus_framefmt format = {
>> +		.width = 640,
>> +		.height = 480,
>> +		.code = MEDIA_BUS_FMT_UYVY8_2X8,
>> +		.field = V4L2_FIELD_NONE,
>> +		.colorspace = V4L2_COLORSPACE_SRGB,
>> +		.ycbcr_enc = V4L2_YCBCR_ENC_601,
>> +		.quantization = V4L2_QUANTIZATION_LIM_RANGE,
>> +		.xfer_func = V4L2_XFER_FUNC_SRGB,
>> +	};
>> +
>> +	struct v4l2_subdev_stream_configs *stream_configs;
>> +	unsigned int i;
>> +
>> +	stream_configs = cal_camerarx_get_stream_configs(phy, sd_state, which);
>> +
>> +	for (i = 0; i < stream_configs->num_configs; ++i)
>> +		stream_configs->configs[i].fmt = format;
>> +}
>> +
>> +static int cal_camerarx_sd_set_routing(struct v4l2_subdev *sd,
>> +				       struct v4l2_subdev_state *sd_state,
>> +				       struct v4l2_subdev_krouting *routing)
>> +{
>> +	struct cal_camerarx *phy = to_cal_camerarx(sd);
>> +	int ret;
>> +	struct v4l2_subdev_krouting *dst;
>> +	struct v4l2_subdev_stream_configs *stream_configs;
>> +
>> +	dst = cal_camerarx_get_routing_table(phy, sd_state, routing->which);
>> +	stream_configs =
>> +		cal_camerarx_get_stream_configs(phy, sd_state, routing->which);
>> +
>> +	ret = v4l2_subdev_dup_routing(dst, routing);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = v4l2_init_stream_configs(stream_configs, dst);
>> +	if (ret)
>> +		return ret;
>> +
>> +	/* Initialize stream formats */
>> +	cal_camerarx_init_formats(sd, sd_state, routing->which);
> 
> What if an application calls this when one or more of the contexts are
> streaming? I don't see you prevent that. Can it lead to any
> undefined/unexpected behaviour?

Yes, I think changing routing needs to be prevented when streaming is 
enabled.

>> +
>>   	return 0;
>>   }
>>   
>>   static int cal_camerarx_sd_init_cfg(struct v4l2_subdev *sd,
>>   				    struct v4l2_subdev_state *sd_state)
>>   {
>> -	struct v4l2_subdev_format format = {
>> -		.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY
>> -		: V4L2_SUBDEV_FORMAT_ACTIVE,
>> -		.pad = CAL_CAMERARX_PAD_SINK,
>> -		.format = {
>> -			.width = 640,
>> -			.height = 480,
>> -			.code = MEDIA_BUS_FMT_UYVY8_2X8,
>> -			.field = V4L2_FIELD_NONE,
>> -			.colorspace = V4L2_COLORSPACE_SRGB,
>> -			.ycbcr_enc = V4L2_YCBCR_ENC_601,
>> -			.quantization = V4L2_QUANTIZATION_LIM_RANGE,
>> -			.xfer_func = V4L2_XFER_FUNC_SRGB,
>> -		},
>> +	u32 which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
>> +
>> +	struct v4l2_subdev_route routes[] = { {
>> +		.sink_pad = 0,
>> +		.sink_stream = 0,
>> +		.source_pad = 1,
>> +		.source_stream = 0,
>> +		.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
>> +	} };
>> +
>> +	struct v4l2_subdev_krouting routing = {
>> +		.which = which,
>> +		.num_routes = 1,
>> +		.routes = routes,
>>   	};
>>   
>> -	return cal_camerarx_sd_set_fmt(sd, sd_state, &format);
>> +	/* Initialize routing to single route to the fist source pad */
>> +	return cal_camerarx_sd_set_routing(sd, sd_state, &routing);
>>   }
>>   
>>   static const struct v4l2_subdev_video_ops cal_camerarx_video_ops = {
>> @@ -838,6 +1036,8 @@ static const struct v4l2_subdev_pad_ops cal_camerarx_pad_ops = {
>>   	.enum_frame_size = cal_camerarx_sd_enum_frame_size,
>>   	.get_fmt = cal_camerarx_sd_get_fmt,
>>   	.set_fmt = cal_camerarx_sd_set_fmt,
>> +	.get_routing = cal_camerarx_sd_get_routing,
>> +	.set_routing = cal_camerarx_sd_set_routing,
>>   };
>>   
>>   static const struct v4l2_subdev_ops cal_camerarx_subdev_ops = {
>> @@ -845,8 +1045,18 @@ static const struct v4l2_subdev_ops cal_camerarx_subdev_ops = {
>>   	.pad = &cal_camerarx_pad_ops,
>>   };
>>   
>> +static bool cal_camerarx_has_route(struct media_entity *entity, unsigned int pad0,
>> +			  unsigned int pad1)
>> +{
>> +	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
>> +	struct cal_camerarx *phy = to_cal_camerarx(sd);
>> +
>> +	return v4l2_subdev_has_route(&phy->routing, pad0, pad1);
>> +}
>> +
>>   static struct media_entity_operations cal_camerarx_media_ops = {
>>   	.link_validate = v4l2_subdev_link_validate,
>> +	.has_route = cal_camerarx_has_route,
>>   };
>>   
>>   /* ------------------------------------------------------------------
>> @@ -898,11 +1108,12 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
>>   	sd = &phy->subdev;
>>   	v4l2_subdev_init(sd, &cal_camerarx_subdev_ops);
>>   	sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
>> -	sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
>> +	sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_MULTIPLEXED;
>>   	snprintf(sd->name, sizeof(sd->name), "CAMERARX%u", instance);
>>   	sd->dev = cal->dev;
>>   
>>   	phy->pads[CAL_CAMERARX_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
>> +
>>   	for (i = CAL_CAMERARX_PAD_FIRST_SOURCE; i < CAL_CAMERARX_NUM_PADS; ++i)
>>   		phy->pads[i].flags = MEDIA_PAD_FL_SOURCE;
>>   	sd->entity.ops = &cal_camerarx_media_ops;
>> @@ -922,6 +1133,8 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
>>   	return phy;
>>   
>>   error:
>> +	v4l2_subdev_free_routing(&phy->routing);
>> +	v4l2_uninit_stream_configs(&phy->stream_configs);
>>   	media_entity_cleanup(&phy->subdev.entity);
>>   	kfree(phy);
>>   	return ERR_PTR(ret);
>> @@ -933,6 +1146,8 @@ void cal_camerarx_destroy(struct cal_camerarx *phy)
>>   		return;
>>   
>>   	v4l2_device_unregister_subdev(&phy->subdev);
>> +	v4l2_subdev_free_routing(&phy->routing);
>> +	v4l2_uninit_stream_configs(&phy->stream_configs);
>>   	media_entity_cleanup(&phy->subdev.entity);
>>   	of_node_put(phy->source_ep_node);
>>   	of_node_put(phy->source_node);
>> diff --git a/drivers/media/platform/ti-vpe/cal-video.c b/drivers/media/platform/ti-vpe/cal-video.c
>> index 8ecae7dc2774..234af40a24fa 100644
>> --- a/drivers/media/platform/ti-vpe/cal-video.c
>> +++ b/drivers/media/platform/ti-vpe/cal-video.c
>> @@ -693,7 +693,11 @@ static int cal_video_check_format(struct cal_ctx *ctx)
>>   	if (!remote_pad)
>>   		return -ENODEV;
>>   
>> -	format = &ctx->phy->formats[remote_pad->index];
>> +	format = cal_camerarx_get_stream_format(ctx->phy, NULL,
>> +						remote_pad->index, 0,
>> +						V4L2_SUBDEV_FORMAT_ACTIVE);
>> +	if (!format)
>> +		return -EINVAL;
>>   
>>   	if (ctx->fmtinfo->code != format->code ||
>>   	    ctx->v_fmt.fmt.pix.height != format->height ||
>> @@ -711,6 +715,48 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
>>   	dma_addr_t addr;
>>   	int ret;
>>   
>> +	if (cal_mc_api) {
>> +		struct v4l2_subdev_route *route = NULL;
>> +		struct media_pad *remote_pad;
>> +		unsigned int i;
>> +
>> +		/* Find the PHY connected to this video device */
>> +
>> +		remote_pad = media_entity_remote_pad(&ctx->pad);
>> +		if (!remote_pad) {
>> +			ctx_err(ctx, "Context not connected\n");
>> +			ret = -ENODEV;
>> +			goto error_release_buffers;
>> +		}
>> +
>> +		ctx->phy = cal_camerarx_get_phy_from_entity(remote_pad->entity);
>> +
>> +		/* Find the stream */
>> +
>> +		for (i = 0; i < ctx->phy->routing.num_routes; ++i) {
>> +			struct v4l2_subdev_route *r =
>> +				&ctx->phy->routing.routes[i];
>> +
>> +			if (!(r->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE))
>> +				continue;
>> +
>> +			if (r->source_pad != remote_pad->index)
>> +				continue;
>> +
>> +			route = r;
>> +
>> +			break;
>> +		}
>> +
>> +		if (!route) {
>> +			ctx_err(ctx, "Failed to find route\n");
>> +			ret = -ENODEV;
>> +			goto error_release_buffers;
>> +		}
> 
> Is it possible to generalize this boilerplate so every driver does not
> have to repeat it? Do you think it is generic enough?

Hmm, what's the boilerplate here? Isn't the above quite cal specific? 
How does the J7 code look like?

> 
>> +
>> +		ctx->stream = route->sink_stream;
>> +	}
>> +
> 
> Applications lose a bit of control over the cameras here. Say you only
> want to use 1 camera and don't care about the rest right now. With the
> current implementation, you propagate the s_stream(1) call to the
> FPD-Link/GMSL/whatever serializer subdev as soon any of the contexts
> start streaming, and don't send s_stream(0) until all contexts stop
> streaming.
> 
> We have an all or nothing policy here. Either all cameras are streaming,
> or none are. Would it make sense to add a way to control individual
> cameras? How much more complexity would it add?

It would make sense, but I haven't seriously considered it because it's 
just an optimization afaics. Probably adding stream based 
start/stop-streaming ops would do it, but if I have realized one thing 
with this work it is that nothing is simple here =).

> On J721E, when you start all cameras but capture only one, the buffer
> for pixel data overflows very quickly and all streams are affected. The
> ability to select the exact cameras to stream could be useful, though I
> am not sure how often anyone would want to do that in a real use case.

This sounds a bit odd. The CSI-2 RX hardware has rx buffers that will be 
filled no matter what the SW says?

We may also have a piece of HW that always sends multiple streams. What 
if you attach a sensor that always sends pixel data and metadata. Does 
that mean that the SW has to capture both, otherwise the buffers will 
overflow?

  Tomi

  reply	other threads:[~2021-08-03 14:51 UTC|newest]

Thread overview: 80+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-24 11:08 [PATCH v3 00/38] media: ti-vpe: cal: multistream & embedded data support Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 01/38] media: ti-vpe: cal: add g/s_parm for legacy API Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 02/38] media: ti-vpe: cal: fix error handling in cal_camerarx_create Tomi Valkeinen
2021-06-04 12:12   ` Laurent Pinchart
2021-05-24 11:08 ` [PATCH v3 03/38] media: ti-vpe: cal: remove unused cal_camerarx->dev field Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 04/38] media: ti-vpe: cal: rename "sensor" to "source" Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 05/38] media: ti-vpe: cal: move global config from cal_ctx_wr_dma_config to runtime resume Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 06/38] media: ti-vpe: cal: use v4l2_get_link_freq Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 07/38] media: ti-vpe: cal: add cal_ctx_prepare/unprepare Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 08/38] media: ti-vpe: cal: change index and cport to u8 Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 09/38] media: ti-vpe: cal: Add CSI2 context Tomi Valkeinen
2021-06-04 13:40   ` Laurent Pinchart
2021-05-24 11:08 ` [PATCH v3 10/38] media: ti-vpe: cal: Add pixel processing context Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 11/38] media: ti-vpe: cal: rename cal_ctx->index to dma_ctx Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 12/38] media: ti-vpe: cal: rename CAL_HL_IRQ_MASK Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 13/38] media: ti-vpe: cal: clean up CAL_CSI2_VC_IRQ_* macros Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 14/38] media: ti-vpe: cal: catch VC errors Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 15/38] media: ti-vpe: cal: remove wait when stopping camerarx Tomi Valkeinen
2021-06-04 13:43   ` Laurent Pinchart
2021-05-24 11:08 ` [PATCH v3 16/38] media: ti-vpe: cal: disable csi2 ctx and pix proc at ctx_stop Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 17/38] media: ti-vpe: cal: allocate pix proc dynamically Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 18/38] media: ti-vpe: cal: add 'use_pix_proc' field Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 19/38] media: ti-vpe: cal: add cal_ctx_wr_dma_enable and fix a race Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 20/38] media: ti-vpe: cal: add vc and datatype fields to cal_ctx Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 21/38] media: ti-vpe: cal: handle cal_ctx_v4l2_register error Tomi Valkeinen
2021-06-04 13:47   ` Laurent Pinchart
2021-06-07  7:44     ` Tomi Valkeinen
2021-06-07  8:00       ` Laurent Pinchart
2021-06-07  8:53         ` Tomi Valkeinen
2021-06-09 12:36           ` Laurent Pinchart
2021-06-09 14:07             ` Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 22/38] media: ti-vpe: cal: set field always to V4L2_FIELD_NONE Tomi Valkeinen
2021-06-04 13:48   ` Laurent Pinchart
2021-05-24 11:08 ` [PATCH v3 23/38] media: ti-vpe: cal: fix typo in a comment Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 24/38] media: ti-vpe: cal: add mbus_code support to cal_mc_enum_fmt_vid_cap Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 25/38] media: ti-vpe: cal: rename non-MC funcs to cal_legacy_* Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 26/38] media: ti-vpe: cal: init ctx->v_fmt correctly in MC mode Tomi Valkeinen
2021-06-04 13:51   ` Laurent Pinchart
2021-05-24 11:08 ` [PATCH v3 27/38] media: ti-vpe: cal: remove cal_camerarx->fmtinfo Tomi Valkeinen
2021-05-24 11:08 ` [PATCH v3 28/38] media: ti-vpe: cal: support 8 DMA contexts Tomi Valkeinen
2021-05-24 11:09 ` [PATCH v3 29/38] media: ti-vpe: cal: cleanup phy iteration in cal_remove Tomi Valkeinen
2021-06-04 13:52   ` Laurent Pinchart
2021-05-24 11:09 ` [PATCH v3 30/38] media: ti-vpe: cal: fix ctx uninitialization Tomi Valkeinen
2021-06-04 13:55   ` Laurent Pinchart
2021-05-24 11:09 ` [PATCH v3 31/38] media: ti-vpe: cal: fix queuing of the initial buffer Tomi Valkeinen
2021-06-04 13:57   ` Laurent Pinchart
2021-05-24 11:09 ` [PATCH v3 32/38] media: ti-vpe: cal: use CSI-2 frame number Tomi Valkeinen
2021-06-04 14:04   ` Laurent Pinchart
2021-06-07 12:39     ` Tomi Valkeinen
2021-06-07 13:42       ` Laurent Pinchart
2021-06-07 14:55         ` Tomi Valkeinen
2021-06-07 16:51           ` Laurent Pinchart
2021-06-08  7:38             ` Tomi Valkeinen
2021-06-08 12:46               ` Tomi Valkeinen
2021-06-09 12:47                 ` Laurent Pinchart
2021-06-09 14:02                   ` Tomi Valkeinen
2021-05-24 11:09 ` [PATCH v3 33/38] media: ti-vpe: cal: add camerarx locking Tomi Valkeinen
2021-06-04 14:14   ` Laurent Pinchart
2021-06-07 11:55     ` Tomi Valkeinen
2021-06-07 12:21       ` Laurent Pinchart
2021-05-24 11:09 ` [PATCH v3 34/38] media: ti-vpe: cal: add camerarx enable/disable refcounting Tomi Valkeinen
2021-06-04 14:16   ` Laurent Pinchart
2021-05-24 11:09 ` [PATCH v3 35/38] media: ti-vpe: cal: allow more than 1 source pads Tomi Valkeinen
2021-06-04 14:18   ` Laurent Pinchart
2021-05-24 11:09 ` [PATCH v3 36/38] media: ti-vpe: cal: add embedded data support Tomi Valkeinen
2021-05-24 11:09 ` [PATCH v3 37/38] media: ti-vpe: cal: use frame desc to get vc and dt Tomi Valkeinen
2021-06-04 14:25   ` Laurent Pinchart
2021-06-07 12:07     ` Tomi Valkeinen
2021-06-07 12:23       ` Laurent Pinchart
2021-05-24 11:09 ` [PATCH v3 38/38] media: ti-vpe: cal: add multiplexed streams support Tomi Valkeinen
2021-05-27 16:06   ` Pratyush Yadav
2021-05-27 16:10     ` Tomi Valkeinen
2021-05-27 16:30       ` Laurent Pinchart
2021-05-27 16:33         ` Tomi Valkeinen
2021-06-04 11:57           ` Laurent Pinchart
2021-06-06 16:14   ` Laurent Pinchart
2021-06-29  9:12     ` Tomi Valkeinen
2021-08-03 10:21   ` Pratyush Yadav
2021-08-03 14:51     ` Tomi Valkeinen [this message]
2021-08-03 16:27       ` Pratyush Yadav

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=a31cd6fd-a037-b1d8-0d14-7c86bd89aa5f@ideasonboard.com \
    --to=tomi.valkeinen@ideasonboard.com \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-media@vger.kernel.org \
    --cc=lokeshvutla@ti.com \
    --cc=p.yadav@ti.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).