On Fri Jul 4 11:24:02 2025 +0200, Hans de Goede wrote:
> Replace the duplicate code for calling the special Intel camera sensor GPIO
> type _DSM (79234640-9e10-4fea-a5c1-b5aa8b19756f) and mapping GPIOs to
> the sensor with a call to int3472_discrete_parse_crs() from the int3472
> driver.
> 
> Besides avoiding code duplication the int3472 version of the code also
> supports more features, like mapping the powerdown GPIO to a regulator on
> the mt9m114 which is necessary to make the camera on the Asus T100TA work.
> 
> Signed-off-by: Hans de Goede <ha...@kernel.org>
> Acked-by: Sakari Ailus <sakari.ai...@linux.intel.com>
> Link: https://lore.kernel.org/r/20250507184737.154747-7-hdego...@redhat.com
> Signed-off-by: Mauro Carvalho Chehab <mchehab+hua...@kernel.org>

Patch committed.

Thanks,
Mauro Carvalho Chehab

 drivers/staging/media/atomisp/Kconfig              |   1 +
 drivers/staging/media/atomisp/pci/atomisp_csi2.h   |  17 --
 .../media/atomisp/pci/atomisp_csi2_bridge.c        | 233 +++------------------
 drivers/staging/media/atomisp/pci/atomisp_v4l2.c   |   1 +
 4 files changed, 27 insertions(+), 225 deletions(-)

---

diff --git a/drivers/staging/media/atomisp/Kconfig 
b/drivers/staging/media/atomisp/Kconfig
index 1265fc58a232..fbe507ae6ec6 100644
--- a/drivers/staging/media/atomisp/Kconfig
+++ b/drivers/staging/media/atomisp/Kconfig
@@ -12,6 +12,7 @@ menuconfig INTEL_ATOMISP
 config VIDEO_ATOMISP
        tristate "Intel Atom Image Signal Processor Driver"
        depends on VIDEO_DEV && INTEL_ATOMISP
+       depends on INTEL_SKL_INT3472
        depends on IPU_BRIDGE
        depends on MEDIA_PCI_SUPPORT
        depends on PMIC_OPREGION
diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2.h 
b/drivers/staging/media/atomisp/pci/atomisp_csi2.h
index bb998c82a438..ec762f8fb922 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_csi2.h
+++ b/drivers/staging/media/atomisp/pci/atomisp_csi2.h
@@ -19,28 +19,11 @@
 #define CSI2_PAD_SOURCE                1
 #define CSI2_PADS_NUM          2
 
-#define CSI2_MAX_ACPI_GPIOS    2u
-
-struct acpi_device;
 struct v4l2_device;
 
 struct atomisp_device;
 struct atomisp_sub_device;
 
-struct atomisp_csi2_acpi_gpio_map {
-       struct acpi_gpio_params params[CSI2_MAX_ACPI_GPIOS];
-       struct acpi_gpio_mapping mapping[CSI2_MAX_ACPI_GPIOS + 1];
-};
-
-struct atomisp_csi2_acpi_gpio_parsing_data {
-       struct acpi_device *adev;
-       struct atomisp_csi2_acpi_gpio_map *map;
-       u32 settings[CSI2_MAX_ACPI_GPIOS];
-       unsigned int settings_count;
-       unsigned int res_count;
-       unsigned int map_count;
-};
-
 struct atomisp_mipi_csi2_device {
        struct v4l2_subdev subdev;
        struct media_pad pads[CSI2_PADS_NUM];
diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c 
b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c
index 6abda358a72f..2a90f86e515f 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c
@@ -13,6 +13,7 @@
 #include <linux/clk.h>
 #include <linux/device.h>
 #include <linux/dmi.h>
+#include <linux/platform_data/x86/int3472.h>
 #include <linux/property.h>
 
 #include <media/ipu-bridge.h>
@@ -24,39 +25,6 @@
 
 #define PMC_CLK_RATE_19_2MHZ                   19200000
 
-/*
- * 79234640-9e10-4fea-a5c1-b5aa8b19756f
- * This _DSM GUID returns information about the GPIO lines mapped to a sensor.
- * Function number 1 returns a count of the GPIO lines that are mapped.
- * Subsequent functions return 32 bit ints encoding information about the GPIO.
- */
-static const guid_t intel_sensor_gpio_info_guid =
-       GUID_INIT(0x79234640, 0x9e10, 0x4fea,
-                 0xa5, 0xc1, 0xb5, 0xaa, 0x8b, 0x19, 0x75, 0x6f);
-
-#define INTEL_GPIO_DSM_TYPE_SHIFT                      0
-#define INTEL_GPIO_DSM_TYPE_MASK                       GENMASK(7, 0)
-#define INTEL_GPIO_DSM_PIN_SHIFT                       8
-#define INTEL_GPIO_DSM_PIN_MASK                                GENMASK(15, 8)
-#define INTEL_GPIO_DSM_SENSOR_ON_VAL_SHIFT             24
-#define INTEL_GPIO_DSM_SENSOR_ON_VAL_MASK              GENMASK(31, 24)
-
-#define INTEL_GPIO_DSM_TYPE(x) \
-       (((x) & INTEL_GPIO_DSM_TYPE_MASK) >> INTEL_GPIO_DSM_TYPE_SHIFT)
-#define INTEL_GPIO_DSM_PIN(x) \
-       (((x) & INTEL_GPIO_DSM_PIN_MASK) >> INTEL_GPIO_DSM_PIN_SHIFT)
-#define INTEL_GPIO_DSM_SENSOR_ON_VAL(x) \
-       (((x) & INTEL_GPIO_DSM_SENSOR_ON_VAL_MASK) >> 
INTEL_GPIO_DSM_SENSOR_ON_VAL_SHIFT)
-
-/*
- * 822ace8f-2814-4174-a56b-5f029fe079ee
- * This _DSM GUID returns a string from the sensor device, which acts as a
- * module identifier.
- */
-static const guid_t intel_sensor_module_guid =
-       GUID_INIT(0x822ace8f, 0x2814, 0x4174,
-                 0xa5, 0x6b, 0x5f, 0x02, 0x9f, 0xe0, 0x79, 0xee);
-
 /*
  * dc2f6c4f-045b-4f1d-97b9-882a6860a4be
  * This _DSM GUID returns a package with n*2 strings, with each set of 2 
strings
@@ -323,196 +291,45 @@ static int atomisp_csi2_get_port(struct acpi_device 
*adev, int clock_num)
        return gmin_cfg_get_int(adev, "CsiPort", port);
 }
 
-/* Note this always returns 1 to continue looping so that res_count is 
accurate */
-static int atomisp_csi2_handle_acpi_gpio_res(struct acpi_resource *ares, void 
*_data)
-{
-       struct atomisp_csi2_acpi_gpio_parsing_data *data = _data;
-       struct acpi_resource_gpio *agpio;
-       const char *name;
-       bool active_low;
-       unsigned int i;
-       u32 settings = 0;
-       u16 pin;
-
-       if (!acpi_gpio_get_io_resource(ares, &agpio))
-               return 1; /* Not a GPIO, continue the loop */
-
-       data->res_count++;
-
-       pin = agpio->pin_table[0];
-       for (i = 0; i < data->settings_count; i++) {
-               if (INTEL_GPIO_DSM_PIN(data->settings[i]) == pin) {
-                       settings = data->settings[i];
-                       break;
-               }
-       }
-
-       if (i == data->settings_count) {
-               acpi_handle_warn(data->adev->handle,
-                                "%s: Could not find DSM GPIO settings for pin 
%u\n",
-                                dev_name(&data->adev->dev), pin);
-               return 1;
-       }
-
-       switch (INTEL_GPIO_DSM_TYPE(settings)) {
-       case 0:
-               name = "reset-gpios";
-               break;
-       case 1:
-               name = "powerdown-gpios";
-               break;
-       default:
-               acpi_handle_warn(data->adev->handle, "%s: Unknown GPIO type 
0x%02lx for pin %u\n",
-                                dev_name(&data->adev->dev),
-                                INTEL_GPIO_DSM_TYPE(settings), pin);
-               return 1;
-       }
-
-       /*
-        * Both reset and power-down need to be logical false when the sensor
-        * is on (sensor should not be in reset and not be powered-down). So
-        * when the sensor-on-value (which is the physical pin value) is high,
-        * then the signal is active-low.
-        */
-       active_low = INTEL_GPIO_DSM_SENSOR_ON_VAL(settings);
-
-       i = data->map_count;
-       if (i == CSI2_MAX_ACPI_GPIOS)
-               return 1;
-
-       /* res_count is already incremented */
-       data->map->params[i].crs_entry_index = data->res_count - 1;
-       data->map->params[i].active_low = active_low;
-       data->map->mapping[i].name = name;
-       data->map->mapping[i].data = &data->map->params[i];
-       data->map->mapping[i].size = 1;
-       data->map_count++;
-
-       acpi_handle_info(data->adev->handle, "%s: %s crs %d %s pin %u 
active-%s\n",
-                        dev_name(&data->adev->dev), name,
-                        data->res_count - 1, agpio->resource_source.string_ptr,
-                        pin, active_low ? "low" : "high");
-
-       return 1;
-}
-
 /*
- * Helper function to create an ACPI GPIO lookup table for sensor reset and
- * powerdown signals on Intel Bay Trail (BYT) and Cherry Trail (CHT) devices,
- * including setting the correct polarity for the GPIO.
- *
- * This uses the "79234640-9e10-4fea-a5c1-b5aa8b19756f" DSM method directly
- * on the sensor device's ACPI node. This is different from later Intel
- * hardware which has a separate INT3472 acpi_device with this info.
- *
- * This function must be called before creating the sw-noded describing
- * the fwnode graph endpoint. And sensor drivers used on these devices
- * must return -EPROBE_DEFER when there is no endpoint description yet.
- * Together this guarantees that the GPIO lookups are in place before
- * the sensor driver tries to get GPIOs with gpiod_get().
+ * Alloc and fill an int3472_discrete_device struct so that we can re-use
+ * the INT3472 sensor GPIO mapping code.
  *
- * Note this code uses the same DSM GUID as the int3472_gpio_guid in
- * the INT3472 discrete.c code and there is some overlap, but there are
- * enough differences that it is difficult to share the code.
+ * This gets called from ipu_bridge_init() which runs only once per boot,
+ * the created faux int3472 device is leaked on purpose to keep the created
+ * GPIO mappings around permanently.
  */
 static int atomisp_csi2_add_gpio_mappings(struct acpi_device *adev)
 {
-       struct atomisp_csi2_acpi_gpio_parsing_data data = { };
-       LIST_HEAD(resource_list);
-       union acpi_object *obj;
-       unsigned int i, j;
+       struct int3472_discrete_device *int3472;
        int ret;
 
-       obj = acpi_evaluate_dsm_typed(adev->handle, &intel_sensor_module_guid,
-                                     0x00, 1, NULL, ACPI_TYPE_STRING);
-       if (obj) {
-               acpi_handle_info(adev->handle, "%s: Sensor module id: '%s'\n",
-                                dev_name(&adev->dev), obj->string.pointer);
-               ACPI_FREE(obj);
-       }
+       /* Max num GPIOs we've seen plus a terminator */
+       int3472 = kzalloc(struct_size(int3472, gpios.table, 
INT3472_MAX_SENSOR_GPIOS + 1),
+                         GFP_KERNEL);
+       if (!int3472)
+               return -ENOMEM;
 
        /*
-        * First get the GPIO-settings count and then get count GPIO-settings
-        * values. Note the order of these may differ from the order in which
-        * the GPIOs are listed on the ACPI resources! So we first store them 
all
-        * and then enumerate the ACPI resources and match them up by pin 
number.
+        * On atomisp the _DSM to get the GPIO type must be made on the sensor
+        * adev, rather than on a separate INT3472 adev.
         */
-       obj = acpi_evaluate_dsm_typed(adev->handle,
-                                     &intel_sensor_gpio_info_guid, 0x00, 1,
-                                     NULL, ACPI_TYPE_INTEGER);
-       if (!obj) {
-               acpi_handle_err(adev->handle, "%s: No _DSM entry for GPIO pin 
count\n",
-                               dev_name(&adev->dev));
-               return -EIO;
-       }
-
-       data.settings_count = obj->integer.value;
-       ACPI_FREE(obj);
+       int3472->adev = adev;
+       int3472->dev = &adev->dev;
+       int3472->sensor = adev;
 
-       if (data.settings_count > CSI2_MAX_ACPI_GPIOS) {
-               acpi_handle_err(adev->handle, "%s: Too many GPIOs %u > %u\n",
-                               dev_name(&adev->dev), data.settings_count,
-                               CSI2_MAX_ACPI_GPIOS);
-               return -EOVERFLOW;
+       int3472->sensor_name = kasprintf(GFP_KERNEL, I2C_DEV_NAME_FORMAT, 
acpi_dev_name(adev));
+       if (!int3472->sensor_name) {
+               kfree(int3472);
+               return -ENOMEM;
        }
 
-       for (i = 0; i < data.settings_count; i++) {
-               /*
-                * i + 2 because the index of this _DSM function is 1-based
-                * and the first function is just a count.
-                */
-               obj = acpi_evaluate_dsm_typed(adev->handle,
-                                             &intel_sensor_gpio_info_guid,
-                                             0x00, i + 2,
-                                             NULL, ACPI_TYPE_INTEGER);
-               if (!obj) {
-                       acpi_handle_err(adev->handle, "%s: No _DSM entry for 
pin %u\n",
-                                       dev_name(&adev->dev), i);
-                       return -EIO;
-               }
-
-               data.settings[i] = obj->integer.value;
-               ACPI_FREE(obj);
+       ret = int3472_discrete_parse_crs(int3472);
+       if (ret) {
+               int3472_discrete_cleanup(int3472);
+               kfree(int3472);
        }
 
-       /* Since we match up by pin-number the pin-numbers must be unique */
-       for (i = 0; i < data.settings_count; i++) {
-               for (j = i + 1; j < data.settings_count; j++) {
-                       if (INTEL_GPIO_DSM_PIN(data.settings[i]) !=
-                           INTEL_GPIO_DSM_PIN(data.settings[j]))
-                               continue;
-
-                       acpi_handle_err(adev->handle, "%s: Duplicate pin number 
%lu\n",
-                                       dev_name(&adev->dev),
-                                       INTEL_GPIO_DSM_PIN(data.settings[i]));
-                       return -EIO;
-               }
-       }
-
-       data.map = kzalloc(sizeof(*data.map), GFP_KERNEL);
-       if (!data.map)
-               return -ENOMEM;
-
-       /* Now parse the ACPI resources and build the lookup table */
-       data.adev = adev;
-       ret = acpi_dev_get_resources(adev, &resource_list,
-                                    atomisp_csi2_handle_acpi_gpio_res, &data);
-       if (ret < 0)
-               return ret;
-
-       acpi_dev_free_resource_list(&resource_list);
-
-       if (data.map_count != data.settings_count ||
-           data.res_count != data.settings_count)
-               acpi_handle_warn(adev->handle, "%s: ACPI GPIO resources vs DSM 
GPIO-info count mismatch (dsm: %d res: %d map %d\n",
-                                dev_name(&adev->dev), data.settings_count,
-                                data.res_count, data.map_count);
-
-       ret = acpi_dev_add_driver_gpios(adev, data.map->mapping);
-       if (ret)
-               acpi_handle_err(adev->handle, "%s: Error adding driver GPIOs: 
%d\n",
-                               dev_name(&adev->dev), ret);
-
        return ret;
 }
 
diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c 
b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
index 0bd0bfded4af..3fdaa4b7bbaf 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
@@ -1513,3 +1513,4 @@ MODULE_AUTHOR("Xiaolin Zhang <xiaolin.zh...@intel.com>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Intel ATOM Platform ISP Driver");
 MODULE_IMPORT_NS("INTEL_IPU_BRIDGE");
+MODULE_IMPORT_NS("INTEL_INT3472_DISCRETE");

Reply via email to