On Wed Sep 2 16:23:20 2026 +0200, Fernando Rimoli wrote:
> Some sensors need different treatment depending on which IPU they are
> connected to, so the ACPI HID alone is not enough.
> 
> Match on an optional list of IPU PCI product IDs. Entries for one HID
> must be adjacent, IPU-specific ones first, so the generic entry is
> skipped once a specific one has matched.
> 
> Signed-off-by: Fernando Rimoli <[email protected]>
> Tested-by: Jakob Berg Jespersen <[email protected]> # Surface Pro 7+, IPU6 Tiger 
> Lake
> Tested-by: Fil Dunsky <[email protected]> # Surface Pro 8, IPU6 Tiger 
> Lake (8086:9a19)
> Tested-by: Lucas Lis <[email protected]> # Surface Pro 7+, IPU6 Tiger 
> Lake (0x9a19)
> Tested-by: Kengo Oki <[email protected]> # Surface Go 4, IPU6 
> Alder Lake-N 8086:462e
> Signed-off-by: Sakari Ailus <[email protected]>

Patch committed.

Thanks,
Sakari Ailus

 drivers/media/pci/intel/ipu-bridge.c | 35 +++++++++++++++++++++++++++++++++++
 include/media/ipu-bridge.h           | 26 +++++++++++++++++++++-----
 2 files changed, 56 insertions(+), 5 deletions(-)

---

diff --git a/drivers/media/pci/intel/ipu-bridge.c 
b/drivers/media/pci/intel/ipu-bridge.c
index 9cd864bcce34..3d4de959c890 100644
--- a/drivers/media/pci/intel/ipu-bridge.c
+++ b/drivers/media/pci/intel/ipu-bridge.c
@@ -8,6 +8,7 @@
 #include <linux/dmi.h>
 #include <linux/i2c.h>
 #include <linux/mei_cl_bus.h>
+#include <linux/pci.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/property.h>
@@ -893,8 +894,28 @@ err_put_adev:
        return ret;
 }
 
+/*
+ * Whether a sensor config applies to the IPU this bridge sits on. A config
+ * listing PCI product IDs only applies to those IPUs.
+ */
+static bool ipu_bridge_config_matches(const struct ipu_sensor_config *cfg,
+                                     struct ipu_bridge *bridge)
+{
+       const u16 *id;
+
+       if (!cfg->pci_ids)
+               return true;
+
+       for (id = cfg->pci_ids; *id; id++)
+               if (*id == bridge->pci_id)
+                       return true;
+
+       return false;
+}
+
 static int ipu_bridge_connect_sensors(struct ipu_bridge *bridge)
 {
+       const char *done_hid = NULL;
        unsigned int i;
        int ret;
 
@@ -902,9 +923,22 @@ static int ipu_bridge_connect_sensors(struct ipu_bridge 
*bridge)
                const struct ipu_sensor_config *cfg =
                        &ipu_supported_sensors[i];
 
+               /*
+                * Entries for one HID are adjacent, IPU-specific ones first,
+                * so the generic entry is skipped once a specific one has
+                * matched and the sensor is not connected twice.
+                */
+               if (done_hid && !strcmp(cfg->hid, done_hid))
+                       continue;
+
+               if (!ipu_bridge_config_matches(cfg, bridge))
+                       continue;
+
                ret = ipu_bridge_connect_sensor(cfg, bridge);
                if (ret)
                        goto err_unregister_sensors;
+
+               done_hid = cfg->hid;
        }
 
        return 0;
@@ -1000,6 +1034,7 @@ int ipu_bridge_init(struct device *dev,
                sizeof(bridge->ipu_node_name));
        bridge->ipu_hid_node.name = bridge->ipu_node_name;
        bridge->dev = dev;
+       bridge->pci_id = dev_is_pci(dev) ? to_pci_dev(dev)->device : 0;
        bridge->parse_sensor_fwnode = parse_sensor_fwnode;
 
        ret = software_node_register(&bridge->ipu_hid_node);
diff --git a/include/media/ipu-bridge.h b/include/media/ipu-bridge.h
index e8aeb23dc5a2..c562db794ca8 100644
--- a/include/media/ipu-bridge.h
+++ b/include/media/ipu-bridge.h
@@ -17,13 +17,24 @@
 #define IPU_SENSOR_ROTATION_NORMAL             0
 #define IPU_SENSOR_ROTATION_INVERTED           1
 
-#define IPU_SENSOR_CONFIG(_HID, _NR, ...)      \
-       (const struct ipu_sensor_config) {      \
-               .hid = _HID,                    \
-               .nr_link_freqs = _NR,           \
-               .link_freqs = { __VA_ARGS__ }   \
+/*
+ * Sensor config specific to one or more IPUs, identified by their PCI product
+ * IDs, with flags describing what the sensor needs there. Entries for one HID
+ * must be adjacent in ipu_supported_sensors[], with the IPU-specific ones
+ * before the generic one.
+ */
+#define IPU_SENSOR_CONFIG_MATCH_FL(_HID, _IDS, _FLAGS, _NR, ...)       \
+       (const struct ipu_sensor_config) {                              \
+               .hid = _HID,                                            \
+               .pci_ids = _IDS,                                        \
+               .flags = _FLAGS,                                        \
+               .nr_link_freqs = _NR,                                   \
+               .link_freqs = { __VA_ARGS__ }                           \
        }
 
+#define IPU_SENSOR_CONFIG(_HID, _NR, ...)                              \
+       IPU_SENSOR_CONFIG_MATCH_FL(_HID, NULL, 0, _NR, __VA_ARGS__)
+
 #define NODE_SENSOR(_HID, _PROPS)              \
        (const struct software_node) {          \
                .name = _HID,                   \
@@ -132,6 +143,9 @@ struct ipu_node_names {
 
 struct ipu_sensor_config {
        const char *hid;
+       /* Zero-terminated list of IPU PCI product IDs, NULL for any IPU */
+       const u16 *pci_ids;
+       const u32 flags;
        const u8 nr_link_freqs;
        const u64 link_freqs[MAX_NUM_LINK_FREQS];
 };
@@ -177,6 +191,8 @@ typedef int (*ipu_parse_sensor_fwnode_t)(struct acpi_device 
*adev,
 
 struct ipu_bridge {
        struct device *dev;
+       /* PCI product ID of the IPU, 0 if it is not a PCI device */
+       u16 pci_id;
        ipu_parse_sensor_fwnode_t parse_sensor_fwnode;
        char ipu_node_name[ACPI_ID_LEN];
        struct software_node ipu_hid_node;
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to