Re: [PATCH/RFC v2 06/15] rcar-csi2: use frame description information when propagating .s_stream()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Sakari,

Thanks for your comments.

On 2017-12-15 15:19:36 +0200, Sakari Ailus wrote:
> Hi Niklas,
> 
> On Thu, Dec 14, 2017 at 08:08:26PM +0100, Niklas Söderlund wrote:
> > Use the frame description from the remote subdevice of the rcar-csi2's
> > sink pad to get the remote pad and stream pad needed to propagate the
> > .s_stream() operation.
> > 
> > The CSI-2 virtual channel which should be acted upon can be determined
> > by looking at which of the rcar-csi2 source pad the .s_stream() was
> > called on. This is because the rcar-csi2 acts as a demultiplexer for the
> > CSI-2 link on the one sink pad and outputs each virtual channel on a
> > distinct and known source pad.
> > 
> > Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@xxxxxxxxxxxx>
> > ---
> >  drivers/media/platform/rcar-vin/rcar-csi2.c | 58 ++++++++++++++++++++---------
> >  1 file changed, 41 insertions(+), 17 deletions(-)
> > 
> > diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c
> > index e0f56cc3d25179a9..6b607b2e31e26063 100644
> > --- a/drivers/media/platform/rcar-vin/rcar-csi2.c
> > +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c
> > @@ -614,20 +614,31 @@ static void rcar_csi2_stop(struct rcar_csi2 *priv)
> >  	rcar_csi2_reset(priv);
> >  }
> >  
> > -static int rcar_csi2_sd_info(struct rcar_csi2 *priv, struct v4l2_subdev **sd)
> > +static int rcar_csi2_get_source_info(struct rcar_csi2 *priv,
> > +				     struct v4l2_subdev **subdev,
> 
> I wonder if using struct media_pad for this would be cleaner.

I can give it a try and see how it works out, thanks for the suggestion.

> 
> > +				     unsigned int *pad,
> > +				     struct v4l2_mbus_frame_desc *fd)
> >  {
> > -	struct media_pad *pad;
> > +	struct media_pad *remote_pad;
> >  
> > -	pad = media_entity_remote_pad(&priv->pads[RCAR_CSI2_SINK]);
> > -	if (!pad) {
> > -		dev_err(priv->dev, "Could not find remote pad\n");
> > +	/* Get source subdevice and pad */
> > +	remote_pad = media_entity_remote_pad(&priv->pads[RCAR_CSI2_SINK]);
> > +	if (!remote_pad) {
> > +		dev_err(priv->dev, "Could not find remote source pad\n");
> >  		return -ENODEV;
> >  	}
> > +	*subdev = media_entity_to_v4l2_subdev(remote_pad->entity);
> > +	*pad = remote_pad->index;
> >  
> > -	*sd = media_entity_to_v4l2_subdev(pad->entity);
> > -	if (!*sd) {
> > -		dev_err(priv->dev, "Could not find remote subdevice\n");
> > -		return -ENODEV;
> > +	/* Get frame descriptor */
> > +	if (v4l2_subdev_call(*subdev, pad, get_frame_desc, *pad, fd)) {
> > +		dev_err(priv->dev, "Could not read frame desc\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (fd->type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) {
> > +		dev_err(priv->dev, "Frame desc do not describe CSI-2 link");
> > +		return -EINVAL;
> 
> I think this should also work with drivers that do not support frame
> descriptors.
> 
> Alternatively support could be added for all drivers. In practice this
> would mean having a few bus specific implementations of get_frame_desc op
> that would dig the information from the frame format.
> 
> Perhaps the former option would make sense here, for now.

I will try to give it some thought when I rework this series. At the 
moment I'm not sure what is the best idea :-)

> 
> >  	}
> >  
> >  	return 0;
> > @@ -637,9 +648,10 @@ static int rcar_csi2_s_stream(struct v4l2_subdev *sd, unsigned int pad,
> >  			      unsigned int stream, int enable)
> >  {
> >  	struct rcar_csi2 *priv = sd_to_csi2(sd);
> > +	struct v4l2_mbus_frame_desc fd;
> >  	struct v4l2_subdev *nextsd;
> > -	unsigned int i, count = 0;
> > -	int ret, vc;
> > +	unsigned int i, rpad, count = 0;
> > +	int ret, vc, rstream = -1;
> >  
> >  	/* Only allow stream control on source pads and valid vc */
> >  	vc = rcar_csi2_pad_to_vc(pad);
> > @@ -650,11 +662,23 @@ static int rcar_csi2_s_stream(struct v4l2_subdev *sd, unsigned int pad,
> >  	if (stream != 0)
> >  		return -EINVAL;
> >  
> > -	mutex_lock(&priv->lock);
> > -
> > -	ret = rcar_csi2_sd_info(priv, &nextsd);
> > +	/* Get information about multiplexed link */
> > +	ret = rcar_csi2_get_source_info(priv, &nextsd, &rpad, &fd);
> >  	if (ret)
> > -		goto out;
> > +		return ret;
> > +
> > +	/* Get stream on multiplexed link */
> > +	for (i = 0; i < fd.num_entries; i++)
> > +		if (fd.entry[i].bus.csi2.channel == vc)
> > +			rstream = fd.entry[i].stream;
> 
> Virtual channel does not equate to the stream. You'll need the data type,
> too.
> 
> You should actually obtain this from the configured routes instead.

You are correct, will fix.

> 
> How does this work btw. if you have several streams on the same virtual
> channel that only have different data types?

I have not been able to test this but I think the hardware should be 
able to handle it. From other part of this driver:

tmp = VCDT_SEL_VC(entry->bus.csi2.channel) | VCDT_VCDTN_EN |
		    VCDT_SEL_DTN_ON |
		    VCDT_SEL_DT(entry->bus.csi2.data_type);

So it looks like selection is based on both virtual channel and data 
type. Unfortunately I'm not aware of hardware setup I can use to verify 
this for the R-Car CSI-2. Maybe I can create a data type mismatch in the 
driver and verify that no stream is outputted, but I would not say that 
would prove it would work with to streams with same VC but different 
data types.

> 
> > +
> > +	if (rstream < 0) {
> > +		dev_err(priv->dev, "Could not find stream for vc %u\n", vc);
> > +		return -EINVAL;
> > +	}
> > +
> > +	/* Start or stop the requested stream */
> > +	mutex_lock(&priv->lock);
> >  
> >  	for (i = 0; i < 4; i++)
> >  		count += priv->stream_count[i];
> > @@ -673,14 +697,14 @@ static int rcar_csi2_s_stream(struct v4l2_subdev *sd, unsigned int pad,
> >  	}
> >  
> >  	if (enable && priv->stream_count[vc] == 0) {
> > -		ret = v4l2_subdev_call(nextsd, video, s_stream, 1);
> > +		ret = v4l2_subdev_call(nextsd, pad, s_stream, rpad, rstream, 1);
> >  		if (ret) {
> >  			rcar_csi2_stop(priv);
> >  			pm_runtime_put(priv->dev);
> >  			goto out;
> >  		}
> >  	} else if (!enable && priv->stream_count[vc] == 1) {
> > -		ret = v4l2_subdev_call(nextsd, video, s_stream, 0);
> > +		ret = v4l2_subdev_call(nextsd, pad, s_stream, rpad, rstream, 0);
> >  	}
> >  
> >  	priv->stream_count[vc] += enable ? 1 : -1;
> > -- 
> > 2.15.1
> > 
> 
> -- 
> Sakari Ailus
> sakari.ailus@xxxxxxxxxxxxxxx

-- 
Regards,
Niklas Söderlund



[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux