Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

platform/x86: int3472: Add support for GPIO type 0x02 (IR flood LED)

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>

authored by

Marco Nenciarini and committed by
Ilpo Järvinen
0ec7f158 218d3c44

+25 -14
+8 -1
drivers/platform/x86/intel/int3472/discrete.c
··· 215 215 *con_id = "privacy"; 216 216 *gpio_flags = GPIO_ACTIVE_HIGH; 217 217 break; 218 + case INT3472_GPIO_TYPE_STROBE: 219 + *con_id = "ir_flood"; 220 + *gpio_flags = GPIO_ACTIVE_HIGH; 221 + break; 218 222 case INT3472_GPIO_TYPE_HOTPLUG_DETECT: 219 223 *con_id = "hpd"; 220 224 *gpio_flags = GPIO_ACTIVE_HIGH; ··· 256 252 * 257 253 * 0x00 Reset 258 254 * 0x01 Power down 255 + * 0x02 Strobe 259 256 * 0x0b Power enable 260 257 * 0x0c Clock enable 261 258 * 0x0d Privacy LED ··· 341 336 break; 342 337 case INT3472_GPIO_TYPE_CLK_ENABLE: 343 338 case INT3472_GPIO_TYPE_PRIVACY_LED: 339 + case INT3472_GPIO_TYPE_STROBE: 344 340 case INT3472_GPIO_TYPE_POWER_ENABLE: 345 341 case INT3472_GPIO_TYPE_DOVDD: 346 342 case INT3472_GPIO_TYPE_HANDSHAKE: ··· 360 354 361 355 break; 362 356 case INT3472_GPIO_TYPE_PRIVACY_LED: 357 + case INT3472_GPIO_TYPE_STROBE: 363 358 ret = skl_int3472_register_led(int3472, gpio, con_id); 364 359 if (ret) 365 360 err_msg = "Failed to register LED\n"; ··· 436 429 gpiod_remove_lookup_table(&int3472->gpios); 437 430 438 431 skl_int3472_unregister_clock(int3472); 439 - skl_int3472_unregister_led(int3472); 432 + skl_int3472_unregister_leds(int3472); 440 433 skl_int3472_unregister_regulator(int3472); 441 434 } 442 435 EXPORT_SYMBOL_NS_GPL(int3472_discrete_cleanup, "INTEL_INT3472_DISCRETE");
+12 -11
drivers/platform/x86/intel/int3472/led.c
··· 17 17 int skl_int3472_register_led(struct int3472_discrete_device *int3472, struct gpio_desc *gpio, 18 18 const char *con_id) 19 19 { 20 - struct int3472_led *led = &int3472->led; 20 + struct int3472_led *led; 21 21 char *p; 22 22 int ret; 23 23 24 - if (led->classdev.dev) 25 - return -EBUSY; 24 + if (int3472->n_leds >= INT3472_MAX_LEDS) 25 + return -ENOSPC; 26 26 27 + led = &int3472->leds[int3472->n_leds]; 27 28 led->gpio = gpio; 28 29 29 30 /* Generate the name, replacing the ':' in the ACPI devname with '_' */ ··· 47 46 led->lookup.con_id = con_id; 48 47 led_add_lookup(&led->lookup); 49 48 49 + int3472->n_leds++; 50 50 return 0; 51 51 } 52 52 53 - void skl_int3472_unregister_led(struct int3472_discrete_device *int3472) 53 + void skl_int3472_unregister_leds(struct int3472_discrete_device *int3472) 54 54 { 55 - struct int3472_led *led = &int3472->led; 55 + for (unsigned int i = 0; i < int3472->n_leds; i++) { 56 + struct int3472_led *led = &int3472->leds[i]; 56 57 57 - if (IS_ERR_OR_NULL(led->classdev.dev)) 58 - return; 59 - 60 - led_remove_lookup(&led->lookup); 61 - led_classdev_unregister(&led->classdev); 62 - gpiod_put(led->gpio); 58 + led_remove_lookup(&led->lookup); 59 + led_classdev_unregister(&led->classdev); 60 + gpiod_put(led->gpio); 61 + } 63 62 }
+5 -2
include/linux/platform_data/x86/int3472.h
··· 23 23 /* PMIC GPIO Types */ 24 24 #define INT3472_GPIO_TYPE_RESET 0x00 25 25 #define INT3472_GPIO_TYPE_POWERDOWN 0x01 26 + #define INT3472_GPIO_TYPE_STROBE 0x02 26 27 #define INT3472_GPIO_TYPE_POWER_ENABLE 0x0b 27 28 #define INT3472_GPIO_TYPE_CLK_ENABLE 0x0c 28 29 #define INT3472_GPIO_TYPE_PRIVACY_LED 0x0d ··· 33 32 34 33 #define INT3472_PDEV_MAX_NAME_LEN 23 35 34 #define INT3472_MAX_SENSOR_GPIOS 3 35 + #define INT3472_MAX_LEDS 2 36 36 #define INT3472_MAX_REGULATORS 3 37 37 38 38 /* E.g. "dovdd\0" */ ··· 129 127 struct led_lookup_data lookup; 130 128 char name[INT3472_LED_MAX_NAME_LEN]; 131 129 struct gpio_desc *gpio; 132 - } led; 130 + } leds[INT3472_MAX_LEDS]; 133 131 134 132 struct int3472_discrete_quirks quirks; 135 133 136 134 unsigned int ngpios; /* how many GPIOs have we seen */ 135 + unsigned int n_leds; /* how many LEDs have we registered */ 137 136 unsigned int n_sensor_gpios; /* how many have we mapped to sensor */ 138 137 unsigned int n_regulator_gpios; /* how many have we mapped to a regulator */ 139 138 struct gpiod_lookup_table gpios; ··· 166 163 167 164 int skl_int3472_register_led(struct int3472_discrete_device *int3472, struct gpio_desc *gpio, 168 165 const char *con_id); 169 - void skl_int3472_unregister_led(struct int3472_discrete_device *int3472); 166 + void skl_int3472_unregister_leds(struct int3472_discrete_device *int3472); 170 167 171 168 #endif