RE: [PATCH v5 3/3] intel-ipu3: cio2: Add new MIPI-CSI2 driver

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

 



Hi, Sakari,

> -----Original Message-----
> From: Sakari Ailus [mailto:sakari.ailus@xxxxxx]
> Sent: Wednesday, October 11, 2017 11:20 PM
> To: Zhi, Yong <yong.zhi@xxxxxxxxx>
> Cc: linux-media@xxxxxxxxxxxxxxx; sakari.ailus@xxxxxxxxxxxxxxx;
> hans.verkuil@xxxxxxxxx; Zheng, Jian Xu <jian.xu.zheng@xxxxxxxxx>;
> tfiga@xxxxxxxxxxxx; Mani, Rajmohan <rajmohan.mani@xxxxxxxxx>;
> Toivonen, Tuukka <tuukka.toivonen@xxxxxxxxx>; Yang, Hyungwoo
> <hyungwoo.yang@xxxxxxxxx>; Vijaykumar, Ramya
> <ramya.vijaykumar@xxxxxxxxx>; Rapolu, Chiranjeevi
> <chiranjeevi.rapolu@xxxxxxxxx>
> Subject: Re: [PATCH v5 3/3] intel-ipu3: cio2: Add new MIPI-CSI2 driver
> 
> Hi Yong,
> 
> One more comment below...
> 
> On Thu, Oct 12, 2017 at 01:02:54AM +0000, Zhi, Yong wrote:
> ...
> > > > +/******* V4L2 sub-device asynchronous registration
> > > callbacks***********/
> > > > +
> > > > +struct sensor_async_subdev {
> > > > +	struct v4l2_async_subdev asd;
> > > > +	struct csi2_bus_info csi2;
> > > > +};
> > > > +
> > > > +static struct cio2_queue *cio2_find_queue_by_sensor_node(struct
> > > cio2_queue *q,
> > > > +						struct fwnode_handle
> > > *fwnode)
> > > > +{
> > > > +	unsigned int i;
> > > > +
> > > > +	for (i = 0; i < CIO2_QUEUES; i++) {
> > > > +		if (q[i].sensor->fwnode == fwnode)
> > > > +			return &q[i];
> > > > +	}
> > > > +
> > > > +	return NULL;
> > > > +}
> > > > +
> > > > +/* The .bound() notifier callback when a match is found */ static
> > > > +int cio2_notifier_bound(struct v4l2_async_notifier *notifier,
> > > > +			       struct v4l2_subdev *sd,
> > > > +			       struct v4l2_async_subdev *asd) {
> > > > +	struct cio2_device *cio2 = container_of(notifier,
> > > > +					struct cio2_device, notifier);
> > > > +	struct sensor_async_subdev *s_asd = container_of(asd,
> > > > +					struct sensor_async_subdev, asd);
> > > > +	struct cio2_queue *q;
> > > > +	unsigned int i;
> > > > +
> > > > +
> > > > +	/* Find first free slot for the subdev */
> > > > +	for (i = 0; i < CIO2_QUEUES; i++)
> > > > +		if (!cio2->queue[i].sensor)
> > > > +			break;
> 
> The queues are related to sub-devices with the same number in the name,
> whereas the number of the CSI-2 receiver is q->csi2.port. The problem here
> is that the CSI-2 receiver that the sensor appears to be connected is a
> incrementing number from zero onwards, depending on the order in which
> the devices are bound rather than the real number of the receiver.
> 
> The easiest way to address this would be to create 1:1 mapping between the
> queues and CSI-2 receivers.
> 

Sure, will fix according your suggestion.

> > > > +
> > > > +	if (i >= CIO2_QUEUES) {
> > > > +		dev_err(&cio2->pci_dev->dev, "too many subdevs\n");
> > > > +		return -ENOSPC;
> > > > +	}
> > > > +	q = &cio2->queue[i];
> > > > +
> > > > +	q->csi2 = s_asd->csi2;
> > > > +	q->sensor = sd;
> > > > +	q->csi_rx_base = cio2->base + CIO2_REG_PIPE_BASE(q->csi2.port);
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +/* The .unbind callback */
> > > > +static void cio2_notifier_unbind(struct v4l2_async_notifier *notifier,
> > > > +				 struct v4l2_subdev *sd,
> > > > +				 struct v4l2_async_subdev *asd) {
> > > > +	struct cio2_device *cio2 = container_of(notifier,
> > > > +						struct cio2_device, notifier);
> > > > +	unsigned int i;
> > > > +
> > > > +	/* Note: sd may here point to unallocated memory. Do not access.
> > > > +*/
> > >
> > > That may be the case but the patchset that this driver depends on
> > > changes it. :-) So you can remove the comment.
> > >
> >
> > Ack, will remove.
> >
> > > > +	for (i = 0; i < CIO2_QUEUES; i++) {
> > > > +		if (cio2->queue[i].sensor == sd) {
> > > > +			cio2->queue[i].sensor = NULL;
> > > > +			return;
> > > > +		}
> > > > +	}
> > > > +}
> > > > +
> > > > +/* .complete() is called after all subdevices have been located
> > > > +*/ static int cio2_notifier_complete(struct v4l2_async_notifier
> > > > +*notifier) {
> > > > +	struct cio2_device *cio2 = container_of(notifier, struct cio2_device,
> > > > +						notifier);
> > > > +	struct sensor_async_subdev *s_asd;
> > > > +	struct cio2_queue *q;
> > > > +	unsigned int i, pad;
> > > > +	int ret;
> > > > +
> > > > +	for (i = 0; i < notifier->num_subdevs; i++) {
> > > > +		s_asd = container_of(cio2->notifier.subdevs[i],
> > > > +					struct sensor_async_subdev,
> > > > +					asd);
> > > > +
> > > > +		q = cio2_find_queue_by_sensor_node(
> > > > +						cio2->queue,
> > > > +						s_asd-
> > > >asd.match.fwnode.fwnode);
> > > > +		if (!q) {
> > > > +			dev_err(&cio2->pci_dev->dev,
> > > > +					"failed to find cio2 queue %d\n", ret);
> > > > +			return -ENXIO;
> > > > +		}
> > > > +
> > > > +		for (pad = 0; pad < q->sensor->entity.num_pads; pad++)
> > > > +			if (q->sensor->entity.pads[pad].flags &
> > > > +						MEDIA_PAD_FL_SOURCE)
> > > > +				break;
> > > > +
> > > > +		if (pad == q->sensor->entity.num_pads) {
> > > > +			dev_err(&cio2->pci_dev->dev,
> > > > +				"failed to find src pad for %s\n",
> > > > +				q->sensor->name);
> > > > +			return -ENXIO;
> > > > +		}
> > > > +
> > > > +		ret = media_create_pad_link(
> > > > +				&q->sensor->entity, pad,
> > > > +				&q->subdev.entity, CIO2_PAD_SINK,
> > > > +				0);
> > > > +		if (ret) {
> > > > +			dev_err(&cio2->pci_dev->dev,
> > > > +					"failed to create link for %s\n",
> > > > +					cio2->queue[i].sensor->name);
> > > > +			return ret;
> > > > +		}
> > > > +	}
> > > > +
> > > > +	return v4l2_device_register_subdev_nodes(&cio2->v4l2_dev);
> > > > +}
> > > > +
> > > > +static const struct v4l2_async_notifier_operations cio2_async_ops = {
> > > > +	.bound = cio2_notifier_bound,
> > > > +	.unbind = cio2_notifier_unbind,
> > > > +	.complete = cio2_notifier_complete, };
> > > > +
> > > > +static int cio2_fwnode_parse(struct device *dev,
> > > > +			     struct v4l2_fwnode_endpoint *vep,
> > > > +			     struct v4l2_async_subdev *asd) {
> > > > +	struct sensor_async_subdev *s_asd =
> > > > +			container_of(asd, struct sensor_async_subdev, asd);
> > > > +
> > > > +	if (vep->bus_type != V4L2_MBUS_CSI2) {
> > > > +		dev_err(dev, "endpoint bus type error\n");
> > > > +		return -EINVAL;
> > > > +	}
> > > > +
> > > > +	s_asd->csi2.port = vep->base.port;
> > > > +	s_asd->csi2.lanes = vep->bus.mipi_csi2.num_data_lanes;
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +static int cio2_notifier_init(struct cio2_device *cio2) {
> > > > +	int ret;
> > > > +
> > > > +	ret = v4l2_async_notifier_parse_fwnode_endpoints(
> > > > +		&cio2->pci_dev->dev, &cio2->notifier,
> > > > +		sizeof(struct sensor_async_subdev),
> > > > +		cio2_fwnode_parse);
> > > > +	if (ret < 0)
> > > > +		return ret;
> > > > +
> > > > +	if (!cio2->notifier.num_subdevs)
> > > > +		return 0;	/* no endpoint */
> > >
> > > You could make this an error as well: there device won't do anything
> > > in that case anyway. -ENODEV, perhaps.
> > >
> >
> > Ack.
> >
> > > > +
> > > > +	cio2->notifier.ops = &cio2_async_ops;
> > > > +	ret = v4l2_async_notifier_register(&cio2->v4l2_dev, &cio2->notifier);
> > > > +	if (ret) {
> > > > +		dev_err(&cio2->pci_dev->dev,
> > > > +			"failed to register async notifier : %d\n", ret);
> > > > +		goto error;
> > > > +	}
> > > > +
> > > > +	return 0;
> > > > +
> > > > +error:
> > > > +	v4l2_async_notifier_cleanup(&cio2->notifier);
> > > > +
> > > > +	return ret;
> > > > +}
> 
> --
> Sakari Ailus
> e-mail: sakari.ailus@xxxxxx



[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