On Sat, Jun 20, 2020 at 3:37 PM Hans de Goede <hdegoede@xxxxxxxxxx> wrote: > > Many Bay Trail and Cherry Trail devices come with a camera attached to > Intel's Image Signal Processor. Linux currently does not have a driver for > these, so they do not work as a camera. > > Some of these camera's have a status LED which is controlled through a GPIO > in some cases, e.g. on the Asus T100TA and Asus T200TA, there is a firmware > issue where the LED gets turned on at boot. > > This commit adds a Linux LED driver for the camera LED on these devices. > This driver will turn the LED off at boot and also allows controlling the > LED (so the user can repurpose it) through the sysfs LED interface. > > Which GPIO is attached to the LED is usually not described in the ACPI > tables, so this driver contains per-system info about the GPIO inside the > driver. This means that this driver only works on systems the driver knows > about. > Pushed to my review and testing queue, thanks! > Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx> > --- > Changes in v2: > - Rebase on top of v5.8-rc1 > - Use PTR_ERR_OR_ZERO > --- > MAINTAINERS | 6 ++ > drivers/platform/x86/Kconfig | 21 ++++ > drivers/platform/x86/Makefile | 1 + > drivers/platform/x86/intel_atomisp2_led.c | 116 ++++++++++++++++++++++ > 4 files changed, 144 insertions(+) > create mode 100644 drivers/platform/x86/intel_atomisp2_led.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index 301330e02bca..5535761f2b54 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -8600,6 +8600,12 @@ L: platform-driver-x86@xxxxxxxxxxxxxxx > S: Maintained > F: drivers/platform/x86/intel_atomisp2_pm.c > > +INTEL ATOMISP2 LED DRIVER > +M: Hans de Goede <hdegoede@xxxxxxxxxx> > +L: platform-driver-x86@xxxxxxxxxxxxxxx > +S: Maintained > +F: drivers/platform/x86/intel_atomisp2_led.c > + > INTEL BROXTON PMC DRIVER > M: Mika Westerberg <mika.westerberg@xxxxxxxxxxxxxxx> > M: Zha Qipeng <qipeng.zha@xxxxxxxxx> > diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig > index 0581a54cf562..318e083f38b3 100644 > --- a/drivers/platform/x86/Kconfig > +++ b/drivers/platform/x86/Kconfig > @@ -761,6 +761,27 @@ config INTEL_ATOMISP2_PM > To compile this driver as a module, choose M here: the module > will be called intel_atomisp2_pm. > > +config INTEL_ATOMISP2_LED > + tristate "Intel AtomISP2 camera LED driver" > + depends on GPIOLIB && LEDS_GPIO > + help > + Many Bay Trail and Cherry Trail devices come with a camera attached > + to Intel's Image Signal Processor. Linux currently does not have a > + driver for these, so they do not work as a camera. Some of these > + camera's have a LED which is controlled through a GPIO. > + > + Some of these devices have a firmware issue where the LED gets turned > + on at boot. This driver will turn the LED off at boot and also allows > + controlling the LED (repurposing it) through the sysfs LED interface. > + > + Which GPIO is attached to the LED is usually not described in the > + ACPI tables, so this driver contains per-system info about the GPIO > + inside the driver, this means that this driver only works on systems > + the driver knows about. > + > + To compile this driver as a module, choose M here: the module > + will be called intel_atomisp2_led. > + > config INTEL_CHT_INT33FE > tristate "Intel Cherry Trail ACPI INT33FE Driver" > depends on X86 && ACPI && I2C && REGULATOR > diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile > index 2b85852a1a87..7a78cc0bb249 100644 > --- a/drivers/platform/x86/Makefile > +++ b/drivers/platform/x86/Makefile > @@ -70,6 +70,7 @@ obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o > > # Intel > obj-$(CONFIG_INTEL_ATOMISP2_PM) += intel_atomisp2_pm.o > +obj-$(CONFIG_INTEL_ATOMISP2_LED) += intel_atomisp2_led.o > obj-$(CONFIG_INTEL_CHT_INT33FE) += intel_cht_int33fe.o > intel_cht_int33fe-objs := intel_cht_int33fe_common.o \ > intel_cht_int33fe_typec.o \ > diff --git a/drivers/platform/x86/intel_atomisp2_led.c b/drivers/platform/x86/intel_atomisp2_led.c > new file mode 100644 > index 000000000000..5935dfca166f > --- /dev/null > +++ b/drivers/platform/x86/intel_atomisp2_led.c > @@ -0,0 +1,116 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Driver for controlling LEDs for cameras connected to the Intel atomisp2 > + * The main purpose of this driver is to turn off LEDs which are on at boot. > + * > + * Copyright (C) 2020 Hans de Goede <hdegoede@xxxxxxxxxx> > + */ > + > +#include <linux/dmi.h> > +#include <linux/gpio/consumer.h> > +#include <linux/gpio/machine.h> > +#include <linux/leds.h> > +#include <linux/module.h> > +#include <linux/mod_devicetable.h> > +#include <linux/platform_device.h> > +#include <linux/workqueue.h> > + > +/* This must be leds-gpio as the leds-gpio driver binds to the name */ > +#define DEV_NAME "leds-gpio" > + > +static const struct gpio_led atomisp2_leds[] = { > + { > + .name = "atomisp2::camera", > + .default_state = LEDS_GPIO_DEFSTATE_OFF, > + }, > +}; > + > +static const struct gpio_led_platform_data atomisp2_leds_pdata = { > + .num_leds = ARRAY_SIZE(atomisp2_leds), > + .leds = atomisp2_leds, > +}; > + > +static struct gpiod_lookup_table asus_t100ta_lookup = { > + .dev_id = DEV_NAME, > + .table = { > + GPIO_LOOKUP_IDX("INT33FC:02", 8, NULL, 0, GPIO_ACTIVE_HIGH), > + { } > + } > +}; > + > +static struct gpiod_lookup_table asus_t100chi_lookup = { > + .dev_id = DEV_NAME, > + .table = { > + GPIO_LOOKUP_IDX("INT33FC:01", 24, NULL, 0, GPIO_ACTIVE_HIGH), > + { } > + } > +}; > + > +static const struct dmi_system_id atomisp2_led_systems[] __initconst = { > + { > + .matches = { > + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), > + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"), > + }, > + .driver_data = &asus_t100ta_lookup, > + }, > + { > + .matches = { > + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), > + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T200TA"), > + }, > + .driver_data = &asus_t100ta_lookup, > + }, > + { > + .matches = { > + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), > + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100CHI"), > + }, > + .driver_data = &asus_t100chi_lookup, > + }, > + {} /* Terminating entry */ > +}; > +MODULE_DEVICE_TABLE(dmi, atomisp2_led_systems); > + > +static struct gpiod_lookup_table *gpio_lookup; > +static struct platform_device *pdev; > + > +static int __init atomisp2_led_init(void) > +{ > + const struct dmi_system_id *system; > + > + system = dmi_first_match(atomisp2_led_systems); > + if (!system) > + return -ENODEV; > + > + gpio_lookup = system->driver_data; > + gpiod_add_lookup_table(gpio_lookup); > + > + pdev = platform_device_register_resndata(NULL, > + DEV_NAME, PLATFORM_DEVID_NONE, > + NULL, 0, &atomisp2_leds_pdata, > + sizeof(atomisp2_leds_pdata)); > + if (IS_ERR(pdev)) > + gpiod_remove_lookup_table(gpio_lookup); > + > + return PTR_ERR_OR_ZERO(pdev); > +} > + > +static void __exit atomisp2_led_cleanup(void) > +{ > + platform_device_unregister(pdev); > + gpiod_remove_lookup_table(gpio_lookup); > +} > + > +module_init(atomisp2_led_init); > +module_exit(atomisp2_led_cleanup); > + > +/* > + * The ACPI INIT method from Asus WMI's code on the T100TA and T200TA turns the > + * LED on (without the WMI interface allowing further control over the LED). > + * Ensure we are loaded after asus-nb-wmi so that we turn the LED off again. > + */ > +MODULE_SOFTDEP("pre: asus_nb_wmi"); > +MODULE_AUTHOR("Hans de Goede <hdegoede@xxxxxxxxxx"); > +MODULE_DESCRIPTION("Intel atomisp2 camera LED driver"); > +MODULE_LICENSE("GPL"); > -- > 2.26.2 > -- With Best Regards, Andy Shevchenko