intel / ipu6-drivers

GNU General Public License v2.0
168 stars 52 forks source link

ipu6: Fix compilation with kernels >= 6.6.0 #175

Closed jwrdegoede closed 10 months ago

jwrdegoede commented 1 year ago

Kernel 6.6 has made some significant changes to how v4l2-async (sub)dev registration works. Adjust the code accordingly.

Note this is based on building against a recent verison of the media_staging/master git tree. Since 6.6 has not been released yet there is a small chance that there might be some more work needed, but this should at least make things work with 6.6-rc1 once released.

alvinpeters commented 1 year ago

This might need some updating lol. IVSC driver just merged for 6.6. https://lore.kernel.org/lkml/20230901142147.096c1b57@sal.lan/

jwrdegoede commented 12 months ago

New push:

  1. Rebased on latest master
  2. Also fix compilation errors in i2c sensor drivers
hao-yao commented 11 months ago

Thank you @jwrdegoede . Would you mind also change the ov02e10.c?

diff --git a/drivers/media/i2c/ov02e10.c b/drivers/media/i2c/ov02e10.c
index bfdff21d3..fb9150ab6 100644
--- a/drivers/media/i2c/ov02e10.c
+++ b/drivers/media/i2c/ov02e10.c
@@ -1023,7 +1023,11 @@ static struct i2c_driver ov02e10_i2c_driver = {
                   .pm = &ov02e10_pm_ops,
                   .acpi_match_table = ov02e10_acpi_ids,
                    },
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
        .probe_new = ov02e10_probe,
+#else
+       .probe = ov02e10_probe,
+#endif
        .remove = ov02e10_remove,
 };

Besides, we need to change some var/struct names in v6.6 so please let me sync internally.

jwrdegoede commented 11 months ago

Thank you @jwrdegoede . Would you mind also change the ov02e10.c?

Rebased to latest master and added the requested changes.

hao-yao commented 11 months ago

Hi Hans,

Internally we want to change align struct definitions with IPU6 in upstreaming, so I changed a bit more. Could you try this patch?

diff --git a/drivers/media/pci/intel/ipu-isys.c b/drivers/media/pci/intel/ipu-isys.c
index 8931934d9..3cc38d4c9 100644
--- a/drivers/media/pci/intel/ipu-isys.c
+++ b/drivers/media/pci/intel/ipu-isys.c
@@ -723,6 +723,7 @@ static int isys_iwake_watermark_cleanup(struct ipu_isys *isys)
 }

 /* The .bound() notifier callback when a match is found */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
 static int isys_notifier_bound(struct v4l2_async_notifier *notifier,
                   struct v4l2_subdev *sd,
                   struct v4l2_async_subdev *asd)
@@ -748,6 +749,33 @@ static void isys_notifier_unbind(struct v4l2_async_notifier *notifier,

    dev_info(&isys->adev->dev, "unbind %s\n", sd->name);
 }
+#else
+static int isys_notifier_bound(struct v4l2_async_notifier *notifier,
+                  struct v4l2_subdev *sd,
+                  struct v4l2_async_connection *asc)
+{
+   struct ipu_isys *isys = container_of(notifier,
+                   struct ipu_isys, notifier);
+   struct sensor_async_sd *s_asd = container_of(asc,
+                   struct sensor_async_sd, asc);
+
+   dev_info(&isys->adev->dev, "bind %s nlanes is %d port is %d\n",
+        sd->name, s_asd->csi2.nlanes, s_asd->csi2.port);
+   isys_complete_ext_device_registration(isys, sd, &s_asd->csi2);
+
+   return v4l2_device_register_subdev_nodes(&isys->v4l2_dev);
+}
+
+static void isys_notifier_unbind(struct v4l2_async_notifier *notifier,
+                struct v4l2_subdev *sd,
+                struct v4l2_async_connection *asc)
+{
+   struct ipu_isys *isys = container_of(notifier,
+                   struct ipu_isys, notifier);
+
+   dev_info(&isys->adev->dev, "unbind %s\n", sd->name);
+}
+#endif

 static int isys_notifier_complete(struct v4l2_async_notifier *notifier)
 {
@@ -765,6 +793,7 @@ static const struct v4l2_async_notifier_operations isys_async_ops = {
    .complete = isys_notifier_complete,
 };

+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
 static int isys_fwnode_parse(struct device *dev,
                 struct v4l2_fwnode_endpoint *vep,
                 struct v4l2_async_subdev *asd)
@@ -777,6 +806,7 @@ static int isys_fwnode_parse(struct device *dev,

    return 0;
 }
+#endif

 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) && LINUX_VERSION_CODE != KERNEL_VERSION(5, 15, 71)
 static int isys_notifier_init(struct ipu_isys *isys)
@@ -813,13 +843,7 @@ static int isys_notifier_init(struct ipu_isys *isys)

    return ret;
 }
-
-static void isys_notifier_cleanup(struct ipu_isys *isys)
-{
-   v4l2_async_notifier_unregister(&isys->notifier);
-   v4l2_async_notifier_cleanup(&isys->notifier);
-}
-#else
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
 static int isys_notifier_init(struct ipu_isys *isys)
 {
    struct ipu_device *isp = isys->adev->isp;
@@ -852,7 +876,79 @@ static int isys_notifier_init(struct ipu_isys *isys)

    return ret;
 }
+#else
+static int isys_notifier_init(struct ipu_isys *isys)
+{
+   const struct ipu_isys_internal_csi2_pdata *csi2 =
+       &isys->pdata->ipdata->csi2;
+   struct ipu_device *isp = isys->adev->isp;
+   struct device *dev = &isp->pdev->dev;
+   unsigned int i;
+   int ret;
+
+   v4l2_async_nf_init(&isys->notifier, &isys->v4l2_dev);
+
+   for (i = 0; i < csi2->nports; i++) {
+       struct v4l2_fwnode_endpoint vep = {
+           .bus_type = V4L2_MBUS_CSI2_DPHY
+       };
+       struct sensor_async_sd *s_asd;
+       struct fwnode_handle *ep;
+
+       ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), i, 0,
+                       FWNODE_GRAPH_ENDPOINT_NEXT);
+       if (!ep)
+           continue;
+
+       ret = v4l2_fwnode_endpoint_parse(ep, &vep);
+       if (ret)
+           goto err_parse;
+
+       s_asd = v4l2_async_nf_add_fwnode_remote(&isys->notifier, ep,
+                           struct
+                           sensor_async_sd);
+       if (IS_ERR(s_asd)) {
+           ret = PTR_ERR(s_asd);
+           goto err_parse;
+       }
+
+       s_asd->csi2.port = vep.base.port;
+       s_asd->csi2.nlanes = vep.bus.mipi_csi2.num_data_lanes;
+
+       fwnode_handle_put(ep);
+
+       continue;
+
+err_parse:
+       fwnode_handle_put(ep);
+       return ret;
+   }
+
+   if (list_empty(&isys->notifier.waiting_list)) {
+       /* isys probe could continue with async subdevs missing */
+       dev_warn(&isys->adev->dev, "no subdev found in graph\n");
+       return 0;
+   }
+
+   isys->notifier.ops = &isys_async_ops;
+   ret = v4l2_async_nf_register(&isys->notifier);
+   if (ret) {
+       dev_err(&isys->adev->dev,
+           "failed to register async notifier : %d\n", ret);
+       v4l2_async_nf_cleanup(&isys->notifier);
+   }
+
+   return ret;
+}
+#endif

+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) && LINUX_VERSION_CODE != KERNEL_VERSION(5, 15, 71)
+static void isys_notifier_cleanup(struct ipu_isys *isys)
+{
+   v4l2_async_notifier_unregister(&isys->notifier);
+   v4l2_async_notifier_cleanup(&isys->notifier);
+}
+#else
 static void isys_notifier_cleanup(struct ipu_isys *isys)
 {
    v4l2_async_nf_unregister(&isys->notifier);
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-phy.c b/drivers/media/pci/intel/ipu6/ipu6-isys-phy.c
index c26780106..bc4aafabf 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-phy.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-phy.c
@@ -504,12 +504,21 @@ int ipu6_isys_phy_common_init(struct ipu_isys *isys)
    struct ipu_bus_device *adev = to_ipu_bus_device(&isys->adev->dev);
    struct ipu_device *isp = adev->isp;
    void __iomem *isp_base = isp->base;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
    struct v4l2_async_subdev *asd;
    struct sensor_async_subdev *s_asd;
    unsigned int i;

    list_for_each_entry(asd, &isys->notifier.asd_list, asd_list) {
        s_asd = container_of(asd, struct sensor_async_subdev, asd);
+#else
+   struct v4l2_async_connection *asc;
+   struct sensor_async_sd *s_asd;
+   unsigned int i;
+
+   list_for_each_entry(asc, &isys->notifier.done_list, asc_entry) {
+       s_asd = container_of(asc, struct sensor_async_sd, asc);
+#endif
        phy_id = s_asd->csi2.port / 4;
        phy_base = isp_base + IPU6_ISYS_PHY_BASE(phy_id);

@@ -562,6 +571,7 @@ int ipu6_isys_phy_config(struct ipu_isys *isys)
    struct ipu_device *isp = adev->isp;
    void __iomem *isp_base = isp->base;
    const struct phy_reg **phy_config_regs;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
    struct v4l2_async_subdev *asd;
    struct sensor_async_subdev *s_asd;
    struct ipu_isys_csi2_config cfg;
@@ -569,6 +579,15 @@ int ipu6_isys_phy_config(struct ipu_isys *isys)

    list_for_each_entry(asd, &isys->notifier.asd_list, asd_list) {
        s_asd = container_of(asd, struct sensor_async_subdev, asd);
+#else
+   struct v4l2_async_connection *asc;
+   struct sensor_async_sd *s_asd;
+   struct ipu_isys_csi2_config cfg;
+   int i;
+
+   list_for_each_entry(asc, &isys->notifier.done_list, asc_entry) {
+       s_asd = container_of(asc, struct sensor_async_sd, asc);
+#endif
        cfg.port = s_asd->csi2.port;
        cfg.nlanes = s_asd->csi2.nlanes;
        phy_port = ipu6_isys_driver_port_to_phy_port(&cfg);
diff --git a/include/media/ipu-isys.h b/include/media/ipu-isys.h
index b75febf80..0788b1b40 100644
--- a/include/media/ipu-isys.h
+++ b/include/media/ipu-isys.h
@@ -6,6 +6,7 @@

 #include <linux/i2c.h>
 #include <linux/clkdev.h>
+#include <linux/version.h>
 #include <media/v4l2-async.h>

 #define IPU_ISYS_MAX_CSI2_LANES        4
@@ -36,9 +37,16 @@ struct ipu_isys_subdev_pdata {
    struct ipu_isys_clk_mapping *clk_map;
 };

+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
 struct sensor_async_subdev {
    struct v4l2_async_subdev asd;
    struct ipu_isys_csi2_config csi2;
 };

+#else
+struct sensor_async_sd {
+   struct v4l2_async_connection asc;
+   struct ipu_isys_csi2_config csi2;
+};
+#endif
 #endif /* MEDIA_IPU_H */
jwrdegoede commented 10 months ago

@hao-yao:

Internally we want to change align struct definitions with IPU6 in upstreaming, so I changed a bit more. Could you try this patch?

Sorry for being a bit slow. Yes that works and looks a bit cleaner too.

I've just pushed a new version (also rebased on the latest master) using this approach, thanks.

hao-yao commented 10 months ago

Thank you @jwrdegoede !