media: ivsc: csi: Check number of lanes on source, too
authorSakari Ailus <sakari.ailus@linux.intel.com>
Mon, 16 Oct 2023 07:38:43 +0000 (10:38 +0300)
committerHans Verkuil <hverkuil-cisco@xs4all.nl>
Wed, 22 Nov 2023 09:56:34 +0000 (10:56 +0100)
The IVSC has two CSI-2 ports, one receiver and one transmitter, for
passing through the CSI-2 image data. Both have the same number of lanes
and this information should be also present in firmware. Check this.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Tested-by: Wentong Wu <wentong.wu@intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
drivers/media/pci/intel/ivsc/mei_csi.c

index 3f507d0..2ca5239 100644 (file)
@@ -645,27 +645,49 @@ static int mei_csi_parse_firmware(struct mei_csi *csi)
        };
        struct device *dev = &csi->cldev->dev;
        struct v4l2_async_connection *asd;
-       struct fwnode_handle *ep;
+       struct fwnode_handle *sink_ep, *source_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");
+       sink_ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0, 0);
+       if (!sink_ep) {
+               dev_err(dev, "can't obtain sink endpoint\n");
                return -EINVAL;
        }
 
        v4l2_async_subdev_nf_init(&csi->notifier, &csi->subdev);
        csi->notifier.ops = &mei_csi_notify_ops;
 
-       ret = v4l2_fwnode_endpoint_parse(ep, &v4l2_ep);
+       ret = v4l2_fwnode_endpoint_parse(sink_ep, &v4l2_ep);
        if (ret) {
-               dev_err(dev, "could not parse v4l2 endpoint\n");
+               dev_err(dev, "could not parse v4l2 sink endpoint\n");
                goto out_nf_cleanup;
        }
 
        csi->nr_of_lanes = v4l2_ep.bus.mipi_csi2.num_data_lanes;
 
-       asd = v4l2_async_nf_add_fwnode_remote(&csi->notifier, ep,
+       source_ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 1, 0, 0);
+       if (!source_ep) {
+               ret = -ENOTCONN;
+               dev_err(dev, "can't obtain source endpoint\n");
+               goto out_nf_cleanup;
+       }
+
+       ret = v4l2_fwnode_endpoint_parse(source_ep, &v4l2_ep);
+       fwnode_handle_put(source_ep);
+       if (ret) {
+               dev_err(dev, "could not parse v4l2 source endpoint\n");
+               goto out_nf_cleanup;
+       }
+
+       if (csi->nr_of_lanes != v4l2_ep.bus.mipi_csi2.num_data_lanes) {
+               ret = -EINVAL;
+               dev_err(dev,
+                       "the number of lanes does not match (%u vs. %u)\n",
+                       csi->nr_of_lanes, v4l2_ep.bus.mipi_csi2.num_data_lanes);
+               goto out_nf_cleanup;
+       }
+
+       asd = v4l2_async_nf_add_fwnode_remote(&csi->notifier, sink_ep,
                                              struct v4l2_async_connection);
        if (IS_ERR(asd)) {
                ret = PTR_ERR(asd);
@@ -676,13 +698,13 @@ static int mei_csi_parse_firmware(struct mei_csi *csi)
        if (ret)
                goto out_nf_cleanup;
 
-       fwnode_handle_put(ep);
+       fwnode_handle_put(sink_ep);
 
        return 0;
 
 out_nf_cleanup:
        v4l2_async_nf_cleanup(&csi->notifier);
-       fwnode_handle_put(ep);
+       fwnode_handle_put(sink_ep);
 
        return ret;
 }