]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-client.git/commitdiff
platform/x86: int3472: Add support for GPIO type 0x02 (IR flood LED)
authorMarco Nenciarini <mnencia@kcore.it>
Wed, 1 Apr 2026 20:36:38 +0000 (22:36 +0200)
committerIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Mon, 13 Apr 2026 11:09:49 +0000 (14:09 +0300)
Add support for GPIO type 0x02, which controls an IR flood LED used
for face authentication on some laptops (e.g. Dell Pro Max 16 Premium).

Without this patch, the kernel logs "GPIO type 0x02 unknown; the sensor
may not work" and IR sensors paired with a flood LED cannot function.

The flood LED is registered through the LED subsystem like the existing
privacy LED, including a lookup entry to allow future consumer drivers
to find and control it via led_get().

To support multiple LEDs per INT3472 device, convert the single led
struct member to an array with a counter.

Signed-off-by: Marco Nenciarini <mnencia@kcore.it>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Link: https://patch.msgid.link/20260401203638.1601661-5-mnencia@kcore.it
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
drivers/platform/x86/intel/int3472/discrete.c
drivers/platform/x86/intel/int3472/led.c
include/linux/platform_data/x86/int3472.h

index 637e3821b4968609bc28819de9ca48b9795685d4..115bb37577a18dfffc9f0fcdb721c11db15cc5b9 100644 (file)
@@ -215,6 +215,10 @@ static void int3472_get_con_id_and_polarity(struct int3472_discrete_device *int3
                *con_id = "privacy";
                *gpio_flags = GPIO_ACTIVE_HIGH;
                break;
+       case INT3472_GPIO_TYPE_STROBE:
+               *con_id = "ir_flood";
+               *gpio_flags = GPIO_ACTIVE_HIGH;
+               break;
        case INT3472_GPIO_TYPE_HOTPLUG_DETECT:
                *con_id = "hpd";
                *gpio_flags = GPIO_ACTIVE_HIGH;
@@ -252,6 +256,7 @@ static void int3472_get_con_id_and_polarity(struct int3472_discrete_device *int3
  *
  * 0x00 Reset
  * 0x01 Power down
+ * 0x02 Strobe
  * 0x0b Power enable
  * 0x0c Clock enable
  * 0x0d Privacy LED
@@ -336,6 +341,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
                break;
        case INT3472_GPIO_TYPE_CLK_ENABLE:
        case INT3472_GPIO_TYPE_PRIVACY_LED:
+       case INT3472_GPIO_TYPE_STROBE:
        case INT3472_GPIO_TYPE_POWER_ENABLE:
        case INT3472_GPIO_TYPE_DOVDD:
        case INT3472_GPIO_TYPE_HANDSHAKE:
@@ -354,6 +360,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
 
                        break;
                case INT3472_GPIO_TYPE_PRIVACY_LED:
+               case INT3472_GPIO_TYPE_STROBE:
                        ret = skl_int3472_register_led(int3472, gpio, con_id);
                        if (ret)
                                err_msg = "Failed to register LED\n";
@@ -429,7 +436,7 @@ void int3472_discrete_cleanup(struct int3472_discrete_device *int3472)
        gpiod_remove_lookup_table(&int3472->gpios);
 
        skl_int3472_unregister_clock(int3472);
-       skl_int3472_unregister_led(int3472);
+       skl_int3472_unregister_leds(int3472);
        skl_int3472_unregister_regulator(int3472);
 }
 EXPORT_SYMBOL_NS_GPL(int3472_discrete_cleanup, "INTEL_INT3472_DISCRETE");
index 22d0d6c5e6ce6521c5bb23324075aa345146e80c..9b2573cc347b803ddc4d7eecd633c8ac363abc20 100644 (file)
@@ -17,13 +17,14 @@ static int int3472_led_set(struct led_classdev *led_cdev, enum led_brightness br
 int skl_int3472_register_led(struct int3472_discrete_device *int3472, struct gpio_desc *gpio,
                             const char *con_id)
 {
-       struct int3472_led *led = &int3472->led;
+       struct int3472_led *led;
        char *p;
        int ret;
 
-       if (led->classdev.dev)
-               return -EBUSY;
+       if (int3472->n_leds >= INT3472_MAX_LEDS)
+               return -ENOSPC;
 
+       led = &int3472->leds[int3472->n_leds];
        led->gpio = gpio;
 
        /* Generate the name, replacing the ':' in the ACPI devname with '_' */
@@ -46,17 +47,17 @@ int skl_int3472_register_led(struct int3472_discrete_device *int3472, struct gpi
        led->lookup.con_id = con_id;
        led_add_lookup(&led->lookup);
 
+       int3472->n_leds++;
        return 0;
 }
 
-void skl_int3472_unregister_led(struct int3472_discrete_device *int3472)
+void skl_int3472_unregister_leds(struct int3472_discrete_device *int3472)
 {
-       struct int3472_led *led = &int3472->led;
+       for (unsigned int i = 0; i < int3472->n_leds; i++) {
+               struct int3472_led *led = &int3472->leds[i];
 
-       if (IS_ERR_OR_NULL(led->classdev.dev))
-               return;
-
-       led_remove_lookup(&led->lookup);
-       led_classdev_unregister(&led->classdev);
-       gpiod_put(led->gpio);
+               led_remove_lookup(&led->lookup);
+               led_classdev_unregister(&led->classdev);
+               gpiod_put(led->gpio);
+       }
 }
index ebf4d063762440cc5e5b20c6dba99410da51f49b..93f1e1fe09b445690702c381c06c1b84d7d699cd 100644 (file)
@@ -23,6 +23,7 @@
 /* PMIC GPIO Types */
 #define INT3472_GPIO_TYPE_RESET                                        0x00
 #define INT3472_GPIO_TYPE_POWERDOWN                            0x01
+#define INT3472_GPIO_TYPE_STROBE                               0x02
 #define INT3472_GPIO_TYPE_POWER_ENABLE                         0x0b
 #define INT3472_GPIO_TYPE_CLK_ENABLE                           0x0c
 #define INT3472_GPIO_TYPE_PRIVACY_LED                          0x0d
@@ -32,6 +33,7 @@
 
 #define INT3472_PDEV_MAX_NAME_LEN                              23
 #define INT3472_MAX_SENSOR_GPIOS                               3
+#define INT3472_MAX_LEDS                                       2
 #define INT3472_MAX_REGULATORS                                 3
 
 /* E.g. "dovdd\0" */
@@ -127,11 +129,12 @@ struct int3472_discrete_device {
                struct led_lookup_data lookup;
                char name[INT3472_LED_MAX_NAME_LEN];
                struct gpio_desc *gpio;
-       } led;
+       } leds[INT3472_MAX_LEDS];
 
        struct int3472_discrete_quirks quirks;
 
        unsigned int ngpios; /* how many GPIOs have we seen */
+       unsigned int n_leds; /* how many LEDs have we registered */
        unsigned int n_sensor_gpios; /* how many have we mapped to sensor */
        unsigned int n_regulator_gpios; /* how many have we mapped to a regulator */
        struct gpiod_lookup_table gpios;
@@ -163,6 +166,6 @@ void skl_int3472_unregister_regulator(struct int3472_discrete_device *int3472);
 
 int skl_int3472_register_led(struct int3472_discrete_device *int3472, struct gpio_desc *gpio,
                             const char *con_id);
-void skl_int3472_unregister_led(struct int3472_discrete_device *int3472);
+void skl_int3472_unregister_leds(struct int3472_discrete_device *int3472);
 
 #endif