RE: [PATCH v5 1/3] media: pci: intel: ivsc: Add CSI submodule

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

 



Hi Sakari,

> -----Original Message-----
> From: Sakari Ailus <sakari.ailus@xxxxxxxxxxxxxxx>
> Sent: Monday, April 24, 2023 2:57 PM
> To: Wu, Wentong <wentong.wu@xxxxxxxxx>
>
> > > > +
> > > > +/* configure CSI-2 link between host and IVSC */ static int
> > > > +csi_set_link_cfg(struct mei_csi *csi) {
> > > > +	struct csi_cmd cmd = { 0 };
> > > > +	size_t cmd_size;
> > > > +	int ret;
> > > > +
> > > > +	cmd.cmd_id = CSI_SET_CONF;
> > > > +	cmd.param.conf.nr_of_lanes = csi->nr_of_lanes;
> > > > +	cmd.param.conf.link_freq = CSI_LINK_FREQ(csi->link_freq);
> > > > +	cmd_size = sizeof(cmd.cmd_id) + sizeof(cmd.param.conf);
> > >
> > > Could you initialise this in variable declaration as I requested earlier?
> > > The same for other similar cases.
> >
> > I believe we have discussed this on v3 patch set as below:
> >
> > 	> > > In some cases you're using memset and in others not. If you don't
> need memset,
> > 	> > > I'd prefer assigning the fields in variable declaration instead.
> > 	> >
> > 	> > The declaration will be like below, but it will break reverse x-mas
> tree style.
> > 	> >
> > 	> > struct csi_cmd cmd = { 0 };
> > 	> > size_t cmd_size = sizeof(cmd.cmd_id) + sizeof(cmd.param.param);
> > 	> > int ret;
> >
> > 	> It's not a problem if you have a dependency.
> 
> Yes, I meant the non-Christmas tree (reverse or not) ordering is not an issue.
> Dependencies of course are of higher priority.

Thanks, 

> 
> >
> > >
> > > > +
> > > > +	mutex_lock(&csi->lock);
> > > > +
> > > > +	ret = mei_csi_send(csi, (u8 *)&cmd, cmd_size);
> > > > +	/*
> > > > +	 * wait configuration ready if download success. placing
> > > > +	 * delay under mutex is to make sure current command flow
> > > > +	 * completed before starting a possible new one.
> > > > +	 */
> > > > +	if (!ret)
> > > > +		msleep(CSI_FW_READY_DELAY_MS);
> > > > +
> > > > +	mutex_unlock(&csi->lock);
> > > > +
> > > > +	return ret;
> > > > +}
> > > > +
> > > > +static int mei_csi_pre_streamon(struct v4l2_subdev *sd, u32 flags) {
> > > > +	struct v4l2_querymenu qm = { .id = V4L2_CID_LINK_FREQ, };
> > > > +	struct mei_csi *csi = sd_to_csi(sd);
> > > > +	struct v4l2_ctrl *ctrl;
> > > > +	int ret = 0;
> > >
> > > No need to initialise this, it is always set.
> >
> > ack, thanks
> >
> > >
> > > > +
> > > > +	if (!csi->remote)
> > > > +		return -ENODEV;
> > > > +
> > > > +	ctrl = v4l2_ctrl_find(csi->remote->ctrl_handler, V4L2_CID_LINK_FREQ);
> > > > +	if (!ctrl)
> > > > +		return -EINVAL;
> > > > +	qm.index = v4l2_ctrl_g_ctrl(ctrl);
> > > > +
> > > > +	ret = v4l2_querymenu(csi->remote->ctrl_handler, &qm);
> > > > +	if (ret)
> > > > +		return ret;
> > >
> > > Please use v4l2_get_link_freq() as already discussed.
> >
> > ack, thanks,
> >
> > >
> > > Didn't we also discuss that you could do this in the s_stream() callback?
> >
> > We don't need configure CSI2 link if call s_stream with enable = 0,
> >
> > But I'm ok to get this in s_stream, thanks
> 
> Yes, you should only query this if streaming is being enabled.

Can we just query the link freq in mei_csi_notify_bound and record it?

> 
> >
> > >
> > > > +
> > > > +	csi->link_freq = qm.value;
> > > > +
> > > > +	return ret;
> > > > +}
> > > > +
> > > > +
> > > > +static const struct v4l2_async_notifier_operations mei_csi_notify_ops = {
> > > > +	.bound = mei_csi_notify_bound,
> > > > +	.unbind = mei_csi_notify_unbind, };
> > > > +
> > > > +static int mei_csi_init_control(struct mei_csi *csi) {
> > > > +	v4l2_ctrl_handler_init(&csi->ctrl_handler, 1);
> > > > +	csi->ctrl_handler.lock = &csi->lock;
> > > > +
> > > > +	csi->privacy_ctrl = v4l2_ctrl_new_std(&csi->ctrl_handler, NULL,
> > > > +					      V4L2_CID_PRIVACY, 0, 1, 1, 0);
> > > > +	if (csi->ctrl_handler.error)
> > > > +		return csi->ctrl_handler.error;
> > > > +	csi->privacy_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
> > >
> > > You should also add the LINK_FREQUENCY control. Make it U64 and and
> > > VOLATILE, too. This way the driver's g_volatile_ctrl() gets called
> > > when the control value is read.
> >
> > ack, thanks
> >
> > >
> > > > +
> > > > +	csi->subdev.ctrl_handler = &csi->ctrl_handler;
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +static int mei_csi_parse_firmware(struct mei_csi *csi) {
> > > > +	struct v4l2_fwnode_endpoint v4l2_ep = {
> > > > +		.bus_type = V4L2_MBUS_CSI2_DPHY,
> > > > +	};
> > > > +	struct device *dev = &csi->cldev->dev;
> > > > +	struct v4l2_async_subdev *asd;
> > > > +	struct fwnode_handle *fwnode;
> > > > +	struct fwnode_handle *ep;
> > > > +	int ret;
> > > > +
> > > > +	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0, 0);
> > > > +	if (!ep) {
> > > > +		dev_err(dev, "not connected to subdevice\n");
> > > > +		return -EINVAL;
> > > > +	}
> > > > +
> > > > +	ret = v4l2_fwnode_endpoint_parse(ep, &v4l2_ep);
> > > > +	if (ret) {
> > > > +		dev_err(dev, "could not parse v4l2 endpoint\n");
> > > > +		fwnode_handle_put(ep);
> > > > +		return -EINVAL;
> > > > +	}
> > > > +
> > > > +	fwnode = fwnode_graph_get_remote_endpoint(ep);
> > > > +	fwnode_handle_put(ep);
> > > > +
> > > > +	v4l2_async_nf_init(&csi->notifier);
> > > > +	csi->notifier.ops = &mei_csi_notify_ops;
> > > > +
> > > > +	asd = v4l2_async_nf_add_fwnode(&csi->notifier, fwnode,
> > > > +				       struct v4l2_async_subdev);
> > > > +	if (IS_ERR(asd)) {
> > > > +		fwnode_handle_put(fwnode);
> > > > +		return PTR_ERR(asd);
> > > > +	}
> > > > +
> > > > +	ret = v4l2_fwnode_endpoint_alloc_parse(fwnode, &v4l2_ep);
> > >
> > > It seems you're parsing the remote endpoint properties here. This
> > > shouldn't be needed for any reason.
> >
> > We need sensor's lane number to configure IVSC's CSI2
> >
> > >
> > > > +	fwnode_handle_put(fwnode);
> > > > +	if (ret)
> > > > +		return ret;
> > > > +	csi->nr_of_lanes = v4l2_ep.bus.mipi_csi2.num_data_lanes;
> > >
> > > Instead the number of lanes comes from the local endpoint.
> >
> > The lane number of IVSC follows sensor's lane number, why local endpoint?
> 
> Because you shouldn't access other devices' endpoint properties in drivers.
> They are outside of the scope of the device's bindings.

Ok, in v3 patch set, it was trying to get the lane number as below:

	+	ret = v4l2_subdev_call(csi->remote, pad, get_mbus_config,
	+			       csi->remote_pad, &mbus_config);
	+	if (ret)
	+		return ret;
	+
	+	if (mbus_config.type != V4L2_MBUS_CSI2_DPHY)
	+		return -EINVAL;
	+
	+	csi->nr_of_lanes = mbus_config.bus.mipi_csi2.num_data_lanes;

Can we use above subdev_call in mei_csi_notify_bound to get lane number?

BR,
Wentong

> 
> >
> > >
> > > > +
> > > > +	ret = v4l2_async_subdev_nf_register(&csi->subdev, &csi->notifier);
> > > > +	if (ret)
> > > > +		v4l2_async_nf_cleanup(&csi->notifier);
> > > > +
> > > > +	v4l2_fwnode_endpoint_free(&v4l2_ep);
> > > > +
> > > > +	return ret;
> > > > +}
> > > > +
> > > > +static int mei_csi_probe(struct mei_cl_device *cldev,
> > > > +			 const struct mei_cl_device_id *id) {
> > > > +	struct device *dev = &cldev->dev;
> > > > +	struct mei_csi *csi;
> > > > +	int ret;
> > > > +
> > > > +	if (!dev_fwnode(dev))
> > > > +		return -EPROBE_DEFER;
> > > > +
> > > > +	csi = devm_kzalloc(dev, sizeof(struct mei_csi), GFP_KERNEL);
> > > > +	if (!csi)
> > > > +		return -ENOMEM;
> > > > +
> > > > +	csi->cldev = cldev;
> > > > +	mutex_init(&csi->lock);
> > > > +	init_completion(&csi->cmd_completion);
> > > > +
> > > > +	mei_cldev_set_drvdata(cldev, csi);
> > > > +
> > > > +	ret = mei_cldev_enable(cldev);
> > > > +	if (ret < 0) {
> > > > +		dev_err(dev, "mei_cldev_enable failed: %d\n", ret);
> > > > +		goto destroy_mutex;
> > > > +	}
> > > > +
> > > > +	ret = mei_cldev_register_rx_cb(cldev, mei_csi_rx);
> > > > +	if (ret) {
> > > > +		dev_err(dev, "event cb registration failed: %d\n", ret);
> > > > +		goto err_disable;
> > > > +	}
> > > > +
> > > > +	ret = mei_csi_parse_firmware(csi);
> > > > +	if (ret)
> > > > +		goto err_disable;
> > > > +
> > > > +	csi->subdev.dev = &cldev->dev;
> > > > +	v4l2_subdev_init(&csi->subdev, &mei_csi_subdev_ops);
> > > > +	v4l2_set_subdevdata(&csi->subdev, csi);
> > > > +	csi->subdev.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
> > >
> > > Please add V4L2_SUBDEV_FL_HAS_EVENTS for control events.
> >
> > ack, thanks
> 
> --
> Kind regards,
> 
> Sakari Ailus




[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