[PATCH 41/55] media: rkisp1: csi: Plumb the CSI RX subdev

Laurent Pinchart laurent.pinchart at ideasonboard.com
Sat Jun 25 09:07:29 PDT 2022


Hi Dafna,

On Sat, Jun 25, 2022 at 10:45:59AM +0300, Dafna Hirschfeld wrote:
> On 15.06.2022 04:11, Paul Elder wrote:
> > From: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> > 
> > Connect the CSI receiver subdevice into the rest of the driver. This
> > includes:
> 
> To make it clear where you put the csi, i'll add here
> 'Connect the CSI subdevice between the source
> and the isp' or something like that.
> 
> Also the sketch 'Media Topology' in rkisp1-dev.c should be updated.

Good point, I'll do that.

> I'd also wonder if we should ignore src configuration of the isp entity
> since it must be identical to the sink of the csi.

What do you mean exactly by ignoring it ?

> > - calling the subdevice via the v4l2 subdev API
> > - moving the async notifier for the sensor from the ISP to the CSI
> >   receiver
> > - in the ISP, create a media link to the CSI receiver, and remove the
> >   media link creation to the sensor
> > - in the CSI receiver, create a media link to the sensor
> > 
> > Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
> > Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> > ---
> >  .../platform/rockchip/rkisp1/rkisp1-csi.c     | 34 ++++++++++++++++--
> >  .../platform/rockchip/rkisp1/rkisp1-csi.h     |  6 ++--
> >  .../platform/rockchip/rkisp1/rkisp1-dev.c     | 36 +++++++++----------
> >  .../platform/rockchip/rkisp1/rkisp1-isp.c     | 21 ++---------
> >  4 files changed, 53 insertions(+), 44 deletions(-)
> > 
> > diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c
> > index 8182694a6fe0..96712b467dde 100644
> > --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c
> > +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c
> > @@ -43,6 +43,34 @@ rkisp1_csi_get_pad_fmt(struct rkisp1_csi *csi,
> >  		return v4l2_subdev_get_try_format(&csi->sd, &state, pad);
> >  }
> > 
> > +int rkisp1_csi_link_sensor(struct rkisp1_device *rkisp1, struct v4l2_subdev *sd,
> > +			   struct rkisp1_sensor_async *s_asd,
> > +			   unsigned int source_pad)
> > +{
> > +	struct rkisp1_csi *csi = &rkisp1->csi;
> > +	int ret;		
> 
> extra space after 'ret;' ?

Oh.

Paul, did you get so used to the fact that checkstyle.py is integrated
in git hooks in libcamera that you forgot that checkpatch.pl has to be
run manually ? :-)

> > +
> > +	s_asd->pixel_rate_ctrl = v4l2_ctrl_find(sd->ctrl_handler,
> > +						V4L2_CID_PIXEL_RATE);
> > +	if (!s_asd->pixel_rate_ctrl) {
> > +		dev_err(rkisp1->dev, "No pixel rate control in subdev %s\n",
> > +			sd->name);
> > +		return -EINVAL;
> > +	}
> > +
> > +	/* Create the link from the sensor to the CSI receiver. */
> > +	ret = media_create_pad_link(&sd->entity, source_pad,
> > +				    &csi->sd.entity, RKISP1_CSI_PAD_SINK,
> > +				    !s_asd->index ? MEDIA_LNK_FL_ENABLED : 0);
> > +	if (ret) {
> > +		dev_err(csi->rkisp1->dev, "failed to link src pad of %s\n",
> > +			sd->name);
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  static int rkisp1_csi_config(struct rkisp1_csi *csi,
> >  			     const struct rkisp1_sensor_async *sensor)
> >  {
> > @@ -118,8 +146,8 @@ static void rkisp1_csi_disable(struct rkisp1_csi *csi)
> >  		     val & (~RKISP1_CIF_MIPI_CTRL_OUTPUT_ENA));
> >  }
> > 
> > -int rkisp1_csi_start(struct rkisp1_csi *csi,
> > -		     const struct rkisp1_sensor_async *sensor)
> > +static int rkisp1_csi_start(struct rkisp1_csi *csi,
> > +			    const struct rkisp1_sensor_async *sensor)
> >  {
> >  	struct rkisp1_device *rkisp1 = csi->rkisp1;
> >  	union phy_configure_opts opts;
> > @@ -155,7 +183,7 @@ int rkisp1_csi_start(struct rkisp1_csi *csi,
> >  	return 0;
> >  }
> > 
> > -void rkisp1_csi_stop(struct rkisp1_csi *csi)
> > +static void rkisp1_csi_stop(struct rkisp1_csi *csi)
> >  {
> >  	rkisp1_csi_disable(csi);
> > 
> > diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.h
> > index ddf8e5e08f55..eadcd24f65fb 100644
> > --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.h
> > +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.h
> > @@ -21,8 +21,8 @@ void rkisp1_csi_cleanup(struct rkisp1_device *rkisp1);
> >  int rkisp1_csi_register(struct rkisp1_device *rkisp1);
> >  void rkisp1_csi_unregister(struct rkisp1_device *rkisp1);
> > 
> > -int rkisp1_csi_start(struct rkisp1_csi *csi,
> > -		     const struct rkisp1_sensor_async *sensor);
> > -void rkisp1_csi_stop(struct rkisp1_csi *csi);
> > +int rkisp1_csi_link_sensor(struct rkisp1_device *rkisp1, struct v4l2_subdev *sd,
> > +			   struct rkisp1_sensor_async *s_asd,
> > +			   unsigned int source_pad);
> > 
> >  #endif /* _RKISP1_CSI_H */
> > diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> > index faf2cd4c8149..a3e182c86bdd 100644
> > --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> > +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> > @@ -17,6 +17,7 @@
> >  #include <linux/pinctrl/consumer.h>
> >  #include <linux/pm_runtime.h>
> >  #include <media/v4l2-fwnode.h>
> > +#include <media/v4l2-mc.h>
> > 
> >  #include "rkisp1-common.h"
> >  #include "rkisp1-csi.h"
> > @@ -119,17 +120,8 @@ static int rkisp1_subdev_notifier_bound(struct v4l2_async_notifier *notifier,
> >  		container_of(asd, struct rkisp1_sensor_async, asd);
> >  	int source_pad;
> > 
> > -	s_asd->pixel_rate_ctrl = v4l2_ctrl_find(sd->ctrl_handler,
> > -						V4L2_CID_PIXEL_RATE);
> > -	if (!s_asd->pixel_rate_ctrl) {
> > -		dev_err(rkisp1->dev, "No pixel rate control in subdev %s\n",
> > -			sd->name);
> > -		return -EINVAL;
> > -	}
> > -
> >  	s_asd->sd = sd;
> > 
> > -	/* Create the link to the sensor. */
> >  	source_pad = media_entity_get_fwnode_pad(&sd->entity, s_asd->source_ep,
> >  						 MEDIA_PAD_FL_SOURCE);
> >  	if (source_pad < 0) {
> > @@ -138,10 +130,7 @@ static int rkisp1_subdev_notifier_bound(struct v4l2_async_notifier *notifier,
> >  		return source_pad;
> >  	}
> > 
> > -	return media_create_pad_link(&sd->entity, source_pad,
> > -				     &rkisp1->isp.sd.entity,
> > -				     RKISP1_ISP_PAD_SINK_VIDEO,
> > -				     !s_asd->index ? MEDIA_LNK_FL_ENABLED : 0);
> > +	return rkisp1_csi_link_sensor(rkisp1, sd, s_asd, source_pad);
> >  }
> > 
> >  static int rkisp1_subdev_notifier_complete(struct v4l2_async_notifier *notifier)
> > @@ -283,6 +272,14 @@ static int rkisp1_create_links(struct rkisp1_device *rkisp1)
> >  	unsigned int i;
> >  	int ret;
> > 
> > +	/* Link the CSI receiver to the ISP. */
> > +	ret = media_create_pad_link(&rkisp1->csi.sd.entity, RKISP1_CSI_PAD_SRC,
> > +				    &rkisp1->isp.sd.entity,
> > +				    RKISP1_ISP_PAD_SINK_VIDEO,
> > +				    MEDIA_LNK_FL_ENABLED);
> 
> should this also be immutable?

I don't think so, because one could connect a parallel sensor directly
to the ISP parallel input. This isn't well supported in the driver today
though, probably because nobody has cared much about upstreaming support
for such a setup, but I think it's a valid hardware option.

> > +	if (ret)
> > +		return ret;
> > +
> >  	/* create ISP->RSZ->CAP links */
> >  	for (i = 0; i < 2; i++) {
> >  		struct media_entity *resizer =
> > @@ -364,13 +361,6 @@ static int rkisp1_entities_register(struct rkisp1_device *rkisp1)
> >  	if (ret)
> >  		goto error;
> > 
> > -	ret = rkisp1_subdev_notifier_register(rkisp1);
> > -	if (ret) {
> > -		dev_err(rkisp1->dev,
> > -			"Failed to register subdev notifier(%d)\n", ret);
> > -		goto error;
> > -	}
> > -
> >  	return 0;
> > 
> >  error:
> > @@ -534,10 +524,16 @@ static int rkisp1_probe(struct platform_device *pdev)
> >  	if (ret)
> >  		goto err_cleanup_csi;
> > 
> > +	ret = rkisp1_subdev_notifier_register(rkisp1);
> > +	if (ret)
> > +		goto err_unreg_entities;
> > +
> >  	rkisp1_debug_init(rkisp1);
> > 
> >  	return 0;
> > 
> > +err_unreg_entities:
> > +	rkisp1_entities_unregister(rkisp1);
> >  err_cleanup_csi:
> >  	rkisp1_csi_cleanup(rkisp1);
> >  err_unreg_media_dev:
> > diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
> > index 5afb8be311c7..260c9ce0dca4 100644
> > --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
> > +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
> > @@ -16,7 +16,6 @@
> >  #include <media/v4l2-event.h>
> > 
> >  #include "rkisp1-common.h"
> > -#include "rkisp1-csi.h"
> > 
> >  #define RKISP1_DEF_SINK_PAD_FMT MEDIA_BUS_FMT_SRGGB10_1X10
> >  #define RKISP1_DEF_SRC_PAD_FMT MEDIA_BUS_FMT_YUYV8_2X8
> > @@ -728,16 +727,12 @@ static int rkisp1_isp_s_stream(struct v4l2_subdev *sd, int enable)
> >  {
> >  	struct rkisp1_isp *isp = to_rkisp1_isp(sd);
> >  	struct rkisp1_device *rkisp1 = isp->rkisp1;
> > -	const struct rkisp1_sensor_async *asd;
> >  	struct media_pad *source_pad;
> >  	int ret;
> > 
> >  	if (!enable) {
> >  		v4l2_subdev_call(rkisp1->source, video, s_stream, false);
> > -
> > -		rkisp1_csi_stop(&rkisp1->csi);
> >  		rkisp1_isp_stop(isp);
> > -
> >  		return 0;
> >  	}
> > 
> > @@ -754,30 +749,20 @@ static int rkisp1_isp_s_stream(struct v4l2_subdev *sd, int enable)
> >  		return -EPIPE;
> >  	}
> > 
> > -	asd = container_of(rkisp1->source->asd, struct rkisp1_sensor_async,
> > -			   asd);
> > -
> > -	if (asd->mbus_type != V4L2_MBUS_CSI2_DPHY)
> > -		return -EINVAL;
> > +	if (rkisp1->source != &rkisp1->csi.sd)
> > +		return -EPIPE;
> 
> This is not very clear, 'source' should point to the remote source (the one outside this driver)
> so why should it be 'csi.sd' ?
> Or is it that now 'rkips1->source' might be either the remote source or csi? if so I think it is a bit confusing.

rkisp1->source is the source of the ISP. it can be the CSI-2 receiver,
or if a parallel sensor is connected directly to the ISP, the sensor
itself. The check here is meant to catch bugs in the implementation
while transitioning, as in this patch external CSI-2 receivers or
parallel sensors are not supported yet. Patch "media: rkisp1: Support
the ISP parallel input" then changes this code.

> > 
> >  	isp->frame_sequence = -1;
> >  	mutex_lock(&isp->ops_lock);
> > -	ret = rkisp1_config_cif(isp, asd->mbus_type, asd->mbus_flags);
> > +	ret = rkisp1_config_cif(isp, V4L2_MBUS_CSI2_DPHY, 0);
> >  	if (ret)
> >  		goto mutex_unlock;
> > 
> >  	rkisp1_isp_start(isp);
> > 
> > -	ret = rkisp1_csi_start(&rkisp1->csi, asd);
> > -	if (ret) {
> > -		rkisp1_isp_stop(isp);
> > -		goto mutex_unlock;
> > -	}
> > -
> >  	ret = v4l2_subdev_call(rkisp1->source, video, s_stream, true);
> 
> Now that isp should call 's_stream' for 'rkisp1->csi->sd' and not 'rkisp1->source'.

As explained above, I think source is correct here, as rkisp1->csi is
the internal CSI-2 receiver, which may or may not be the source of the
ISP, depending on link configuration.

> >  	if (ret) {
> >  		rkisp1_isp_stop(isp);
> > -		rkisp1_csi_stop(&rkisp1->csi);
> >  		goto mutex_unlock;
> >  	}
> > 

-- 
Regards,

Laurent Pinchart



More information about the Linux-rockchip mailing list