Skip to content

Commit 0ec7f15

Browse files
mnenciaij-intel
authored andcommitted
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>
1 parent 218d3c4 commit 0ec7f15

3 files changed

Lines changed: 25 additions & 14 deletions

File tree

drivers/platform/x86/intel/int3472/discrete.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,10 @@ static void int3472_get_con_id_and_polarity(struct int3472_discrete_device *int3
215215
*con_id = "privacy";
216216
*gpio_flags = GPIO_ACTIVE_HIGH;
217217
break;
218+
case INT3472_GPIO_TYPE_STROBE:
219+
*con_id = "ir_flood";
220+
*gpio_flags = GPIO_ACTIVE_HIGH;
221+
break;
218222
case INT3472_GPIO_TYPE_HOTPLUG_DETECT:
219223
*con_id = "hpd";
220224
*gpio_flags = GPIO_ACTIVE_HIGH;
@@ -252,6 +256,7 @@ static void int3472_get_con_id_and_polarity(struct int3472_discrete_device *int3
252256
*
253257
* 0x00 Reset
254258
* 0x01 Power down
259+
* 0x02 Strobe
255260
* 0x0b Power enable
256261
* 0x0c Clock enable
257262
* 0x0d Privacy LED
@@ -336,6 +341,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
336341
break;
337342
case INT3472_GPIO_TYPE_CLK_ENABLE:
338343
case INT3472_GPIO_TYPE_PRIVACY_LED:
344+
case INT3472_GPIO_TYPE_STROBE:
339345
case INT3472_GPIO_TYPE_POWER_ENABLE:
340346
case INT3472_GPIO_TYPE_DOVDD:
341347
case INT3472_GPIO_TYPE_HANDSHAKE:
@@ -354,6 +360,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
354360

355361
break;
356362
case INT3472_GPIO_TYPE_PRIVACY_LED:
363+
case INT3472_GPIO_TYPE_STROBE:
357364
ret = skl_int3472_register_led(int3472, gpio, con_id);
358365
if (ret)
359366
err_msg = "Failed to register LED\n";
@@ -429,7 +436,7 @@ void int3472_discrete_cleanup(struct int3472_discrete_device *int3472)
429436
gpiod_remove_lookup_table(&int3472->gpios);
430437

431438
skl_int3472_unregister_clock(int3472);
432-
skl_int3472_unregister_led(int3472);
439+
skl_int3472_unregister_leds(int3472);
433440
skl_int3472_unregister_regulator(int3472);
434441
}
435442
EXPORT_SYMBOL_NS_GPL(int3472_discrete_cleanup, "INTEL_INT3472_DISCRETE");

drivers/platform/x86/intel/int3472/led.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,14 @@ static int int3472_led_set(struct led_classdev *led_cdev, enum led_brightness br
1717
int skl_int3472_register_led(struct int3472_discrete_device *int3472, struct gpio_desc *gpio,
1818
const char *con_id)
1919
{
20-
struct int3472_led *led = &int3472->led;
20+
struct int3472_led *led;
2121
char *p;
2222
int ret;
2323

24-
if (led->classdev.dev)
25-
return -EBUSY;
24+
if (int3472->n_leds >= INT3472_MAX_LEDS)
25+
return -ENOSPC;
2626

27+
led = &int3472->leds[int3472->n_leds];
2728
led->gpio = gpio;
2829

2930
/* 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
4647
led->lookup.con_id = con_id;
4748
led_add_lookup(&led->lookup);
4849

50+
int3472->n_leds++;
4951
return 0;
5052
}
5153

52-
void skl_int3472_unregister_led(struct int3472_discrete_device *int3472)
54+
void skl_int3472_unregister_leds(struct int3472_discrete_device *int3472)
5355
{
54-
struct int3472_led *led = &int3472->led;
56+
for (unsigned int i = 0; i < int3472->n_leds; i++) {
57+
struct int3472_led *led = &int3472->leds[i];
5558

56-
if (IS_ERR_OR_NULL(led->classdev.dev))
57-
return;
58-
59-
led_remove_lookup(&led->lookup);
60-
led_classdev_unregister(&led->classdev);
61-
gpiod_put(led->gpio);
59+
led_remove_lookup(&led->lookup);
60+
led_classdev_unregister(&led->classdev);
61+
gpiod_put(led->gpio);
62+
}
6263
}

include/linux/platform_data/x86/int3472.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
/* PMIC GPIO Types */
2424
#define INT3472_GPIO_TYPE_RESET 0x00
2525
#define INT3472_GPIO_TYPE_POWERDOWN 0x01
26+
#define INT3472_GPIO_TYPE_STROBE 0x02
2627
#define INT3472_GPIO_TYPE_POWER_ENABLE 0x0b
2728
#define INT3472_GPIO_TYPE_CLK_ENABLE 0x0c
2829
#define INT3472_GPIO_TYPE_PRIVACY_LED 0x0d
@@ -32,6 +33,7 @@
3233

3334
#define INT3472_PDEV_MAX_NAME_LEN 23
3435
#define INT3472_MAX_SENSOR_GPIOS 3
36+
#define INT3472_MAX_LEDS 2
3537
#define INT3472_MAX_REGULATORS 3
3638

3739
/* E.g. "dovdd\0" */
@@ -127,11 +129,12 @@ struct int3472_discrete_device {
127129
struct led_lookup_data lookup;
128130
char name[INT3472_LED_MAX_NAME_LEN];
129131
struct gpio_desc *gpio;
130-
} led;
132+
} leds[INT3472_MAX_LEDS];
131133

132134
struct int3472_discrete_quirks quirks;
133135

134136
unsigned int ngpios; /* how many GPIOs have we seen */
137+
unsigned int n_leds; /* how many LEDs have we registered */
135138
unsigned int n_sensor_gpios; /* how many have we mapped to sensor */
136139
unsigned int n_regulator_gpios; /* how many have we mapped to a regulator */
137140
struct gpiod_lookup_table gpios;
@@ -163,6 +166,6 @@ void skl_int3472_unregister_regulator(struct int3472_discrete_device *int3472);
163166

164167
int skl_int3472_register_led(struct int3472_discrete_device *int3472, struct gpio_desc *gpio,
165168
const char *con_id);
166-
void skl_int3472_unregister_led(struct int3472_discrete_device *int3472);
169+
void skl_int3472_unregister_leds(struct int3472_discrete_device *int3472);
167170

168171
#endif

0 commit comments

Comments
 (0)