Loading drivers/gpio/gpiolib-acpi.c +25 −5 Original line number Diff line number Diff line Loading @@ -437,6 +437,11 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares, if (!handler) return AE_OK; if (acpi_gpio_in_ignore_list(ignore_interrupt, dev_name(chip->parent), pin)) { dev_info(chip->parent, "Ignoring interrupt on pin %u\n", pin); return AE_OK; } desc = acpi_request_own_gpiod(chip, agpio, 0, "ACPI:Event"); if (IS_ERR(desc)) { dev_err(chip->parent, Loading @@ -461,11 +466,6 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares, goto fail_unlock_irq; } if (acpi_gpio_in_ignore_list(ignore_interrupt, dev_name(chip->parent), pin)) { dev_info(chip->parent, "Ignoring interrupt on pin %u\n", pin); return AE_OK; } event = kzalloc(sizeof(*event), GFP_KERNEL); if (!event) goto fail_unlock_irq; Loading Loading @@ -1654,6 +1654,26 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = { .ignore_wake = "SYNA1202:00@16", }, }, { /* * On the Peaq C1010 2-in-1 INT33FC:00 pin 3 is connected to * a "dolby" button. At the ACPI level an _AEI event-handler * is connected which sets an ACPI variable to 1 on both * edges. This variable can be polled + cleared to 0 using * WMI. But since the variable is set on both edges the WMI * interface is pretty useless even when polling. * So instead the x86-android-tablets code instantiates * a gpio-keys platform device for it. * Ignore the _AEI handler for the pin, so that it is not busy. */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "PEAQ"), DMI_MATCH(DMI_PRODUCT_NAME, "PEAQ PMM C1010 MD99187"), }, .driver_data = &(struct acpi_gpiolib_dmi_quirk) { .ignore_interrupt = "INT33FC:00@3", }, }, {} /* Terminating entry */ }; Loading drivers/platform/x86/x86-android-tablets/asus.c +1 −0 Original line number Diff line number Diff line Loading @@ -303,6 +303,7 @@ static const struct x86_i2c_client_info asus_tf103c_i2c_clients[] __initconst = .index = 28, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, .con_id = "atmel_mxt_ts_irq", }, }, }; Loading drivers/platform/x86/x86-android-tablets/core.c +83 −49 Original line number Diff line number Diff line Loading @@ -12,7 +12,7 @@ #include <linux/acpi.h> #include <linux/dmi.h> #include <linux/gpio/driver.h> #include <linux/gpio/consumer.h> #include <linux/gpio/machine.h> #include <linux/irq.h> #include <linux/module.h> Loading @@ -21,33 +21,54 @@ #include <linux/string.h> #include "x86-android-tablets.h" /* For gpiochip_get_desc() which is EXPORT_SYMBOL_GPL() */ #include "../../../gpio/gpiolib.h" #include "../../../gpio/gpiolib-acpi.h" static int gpiochip_find_match_label(struct gpio_chip *gc, void *data) { return gc->label && !strcmp(gc->label, data); } static struct platform_device *x86_android_tablet_device; int x86_android_tablet_get_gpiod(const char *label, int pin, struct gpio_desc **desc) /* * This helper allows getting a gpio_desc *before* the actual device consuming * the GPIO has been instantiated. This function _must_ only be used to handle * this special case such as e.g. : * * 1. Getting an IRQ from a GPIO for i2c_board_info.irq which is passed to * i2c_client_new() to instantiate i2c_client-s; or * 2. Calling desc_to_gpio() to get an old style GPIO number for gpio_keys * platform_data which still uses old style GPIO numbers. * * Since the consuming device has not been instatiated yet a dynamic lookup * is generated using the special x86_android_tablet dev for dev_id. * * For normal GPIO lookups a standard static gpiod_lookup_table _must_ be used. */ int x86_android_tablet_get_gpiod(const char *chip, int pin, const char *con_id, bool active_low, enum gpiod_flags dflags, struct gpio_desc **desc) { struct gpiod_lookup_table *lookup; struct gpio_desc *gpiod; struct gpio_chip *chip; chip = gpiochip_find((void *)label, gpiochip_find_match_label); if (!chip) { pr_err("error cannot find GPIO chip %s\n", label); return -ENODEV; } lookup = kzalloc(struct_size(lookup, table, 2), GFP_KERNEL); if (!lookup) return -ENOMEM; lookup->dev_id = KBUILD_MODNAME; lookup->table[0].key = chip; lookup->table[0].chip_hwnum = pin; lookup->table[0].con_id = con_id; lookup->table[0].flags = active_low ? GPIO_ACTIVE_LOW : GPIO_ACTIVE_HIGH; gpiod_add_lookup_table(lookup); gpiod = devm_gpiod_get(&x86_android_tablet_device->dev, con_id, dflags); gpiod_remove_lookup_table(lookup); kfree(lookup); gpiod = gpiochip_get_desc(chip, pin); if (IS_ERR(gpiod)) { pr_err("error %ld getting GPIO %s %d\n", PTR_ERR(gpiod), label, pin); pr_err("error %ld getting GPIO %s %d\n", PTR_ERR(gpiod), chip, pin); return PTR_ERR(gpiod); } if (desc) *desc = gpiod; return 0; } Loading Loading @@ -77,7 +98,8 @@ int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data) return irq; case X86_ACPI_IRQ_TYPE_GPIOINT: /* Like acpi_dev_gpio_irq_get(), but without parsing ACPI resources */ ret = x86_android_tablet_get_gpiod(data->chip, data->index, &gpiod); ret = x86_android_tablet_get_gpiod(data->chip, data->index, data->con_id, false, GPIOD_ASIS, &gpiod); if (ret) return ret; Loading Loading @@ -224,7 +246,7 @@ static __init int x86_instantiate_serdev(const struct x86_serdev_info *info, int return ret; } static void x86_android_tablet_cleanup(void) static void x86_android_tablet_remove(struct platform_device *pdev) { int i; Loading Loading @@ -255,11 +277,10 @@ static void x86_android_tablet_cleanup(void) software_node_unregister(bat_swnode); } static __init int x86_android_tablet_init(void) static __init int x86_android_tablet_probe(struct platform_device *pdev) { const struct x86_dev_info *dev_info; const struct dmi_system_id *id; struct gpio_chip *chip; int i, ret = 0; id = dmi_first_match(x86_android_tablet_ids); Loading @@ -267,20 +288,8 @@ static __init int x86_android_tablet_init(void) return -ENODEV; dev_info = id->driver_data; /* * The broken DSDTs on these devices often also include broken * _AEI (ACPI Event Interrupt) handlers, disable these. */ if (dev_info->invalid_aei_gpiochip) { chip = gpiochip_find(dev_info->invalid_aei_gpiochip, gpiochip_find_match_label); if (!chip) { pr_err("error cannot find GPIO chip %s\n", dev_info->invalid_aei_gpiochip); return -ENODEV; } acpi_gpiochip_free_interrupts(chip); } /* Allow x86_android_tablet_device use before probe() exits */ x86_android_tablet_device = pdev; /* * Since this runs from module_init() it cannot use -EPROBE_DEFER, Loading @@ -303,7 +312,7 @@ static __init int x86_android_tablet_init(void) if (dev_info->init) { ret = dev_info->init(); if (ret < 0) { x86_android_tablet_cleanup(); x86_android_tablet_remove(pdev); return ret; } exit_handler = dev_info->exit; Loading @@ -311,7 +320,7 @@ static __init int x86_android_tablet_init(void) i2c_clients = kcalloc(dev_info->i2c_client_count, sizeof(*i2c_clients), GFP_KERNEL); if (!i2c_clients) { x86_android_tablet_cleanup(); x86_android_tablet_remove(pdev); return -ENOMEM; } Loading @@ -319,7 +328,7 @@ static __init int x86_android_tablet_init(void) for (i = 0; i < i2c_client_count; i++) { ret = x86_instantiate_i2c_client(dev_info, i); if (ret < 0) { x86_android_tablet_cleanup(); x86_android_tablet_remove(pdev); return ret; } } Loading @@ -327,7 +336,7 @@ static __init int x86_android_tablet_init(void) /* + 1 to make space for (optional) gpio_keys_button pdev */ pdevs = kcalloc(dev_info->pdev_count + 1, sizeof(*pdevs), GFP_KERNEL); if (!pdevs) { x86_android_tablet_cleanup(); x86_android_tablet_remove(pdev); return -ENOMEM; } Loading @@ -335,14 +344,14 @@ static __init int x86_android_tablet_init(void) for (i = 0; i < pdev_count; i++) { pdevs[i] = platform_device_register_full(&dev_info->pdev_info[i]); if (IS_ERR(pdevs[i])) { x86_android_tablet_cleanup(); x86_android_tablet_remove(pdev); return PTR_ERR(pdevs[i]); } } serdevs = kcalloc(dev_info->serdev_count, sizeof(*serdevs), GFP_KERNEL); if (!serdevs) { x86_android_tablet_cleanup(); x86_android_tablet_remove(pdev); return -ENOMEM; } Loading @@ -350,7 +359,7 @@ static __init int x86_android_tablet_init(void) for (i = 0; i < serdev_count; i++) { ret = x86_instantiate_serdev(&dev_info->serdev_info[i], i); if (ret < 0) { x86_android_tablet_cleanup(); x86_android_tablet_remove(pdev); return ret; } } Loading @@ -361,30 +370,34 @@ static __init int x86_android_tablet_init(void) buttons = kcalloc(dev_info->gpio_button_count, sizeof(*buttons), GFP_KERNEL); if (!buttons) { x86_android_tablet_cleanup(); x86_android_tablet_remove(pdev); return -ENOMEM; } for (i = 0; i < dev_info->gpio_button_count; i++) { ret = x86_android_tablet_get_gpiod(dev_info->gpio_button[i].chip, dev_info->gpio_button[i].pin, &gpiod); dev_info->gpio_button[i].pin, dev_info->gpio_button[i].button.desc, false, GPIOD_IN, &gpiod); if (ret < 0) { x86_android_tablet_cleanup(); x86_android_tablet_remove(pdev); return ret; } buttons[i] = dev_info->gpio_button[i].button; buttons[i].gpio = desc_to_gpio(gpiod); /* Release gpiod so that gpio-keys can request it */ devm_gpiod_put(&x86_android_tablet_device->dev, gpiod); } pdata.buttons = buttons; pdata.nbuttons = dev_info->gpio_button_count; pdevs[pdev_count] = platform_device_register_data(NULL, "gpio-keys", pdevs[pdev_count] = platform_device_register_data(&pdev->dev, "gpio-keys", PLATFORM_DEVID_AUTO, &pdata, sizeof(pdata)); if (IS_ERR(pdevs[pdev_count])) { x86_android_tablet_cleanup(); x86_android_tablet_remove(pdev); return PTR_ERR(pdevs[pdev_count]); } pdev_count++; Loading @@ -393,8 +406,29 @@ static __init int x86_android_tablet_init(void) return 0; } static struct platform_driver x86_android_tablet_driver = { .driver = { .name = KBUILD_MODNAME, }, .remove_new = x86_android_tablet_remove, }; static int __init x86_android_tablet_init(void) { x86_android_tablet_device = platform_create_bundle(&x86_android_tablet_driver, x86_android_tablet_probe, NULL, 0, NULL, 0); return PTR_ERR_OR_ZERO(x86_android_tablet_device); } module_init(x86_android_tablet_init); module_exit(x86_android_tablet_cleanup); static void __exit x86_android_tablet_exit(void) { platform_device_unregister(x86_android_tablet_device); platform_driver_unregister(&x86_android_tablet_driver); } module_exit(x86_android_tablet_exit); MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); MODULE_DESCRIPTION("X86 Android tablets DSDT fixups driver"); Loading drivers/platform/x86/x86-android-tablets/lenovo.c +13 −16 Original line number Diff line number Diff line Loading @@ -95,6 +95,7 @@ static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst .index = 56, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, .con_id = "goodix_ts_irq", }, }, { /* Wacom Digitizer in keyboard half */ Loading @@ -111,6 +112,7 @@ static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst .index = 49, .trigger = ACPI_LEVEL_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, .con_id = "wacom_irq", }, }, { /* LP8557 Backlight controller */ Loading @@ -136,6 +138,7 @@ static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst .index = 77, .trigger = ACPI_LEVEL_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, .con_id = "hideep_ts_irq", }, }, }; Loading Loading @@ -321,6 +324,7 @@ static struct x86_i2c_client_info lenovo_yoga_tab2_830_1050_i2c_clients[] __init .index = 2, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_HIGH, .con_id = "bq24292i_irq", }, }, { /* BQ27541 fuel-gauge */ Loading Loading @@ -431,7 +435,8 @@ static int __init lenovo_yoga_tab2_830_1050_init_touchscreen(void) int ret; /* Use PMIC GPIO 10 bootstrap pin to differentiate 830 vs 1050 */ ret = x86_android_tablet_get_gpiod("gpio_crystalcove", 10, &gpiod); ret = x86_android_tablet_get_gpiod("gpio_crystalcove", 10, "yoga_bootstrap", false, GPIOD_IN, &gpiod); if (ret) return ret; Loading Loading @@ -560,7 +565,6 @@ static const struct software_node fg_bq25890_1_supply_node = { /* bq25892 charger settings for the flat lipo battery behind the screen */ static const struct property_entry lenovo_yt3_bq25892_0_props[] = { PROPERTY_ENTRY_STRING_ARRAY("supplied-from", lenovo_yt3_bq25892_0_suppliers), PROPERTY_ENTRY_STRING("linux,power-supply-name", "bq25892-second-chrg"), PROPERTY_ENTRY_U32("linux,iinlim-percentage", 40), PROPERTY_ENTRY_BOOL("linux,skip-reset"), /* Values taken from Android Factory Image */ Loading Loading @@ -615,6 +619,7 @@ static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = { .index = 5, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, .con_id = "bq25892_0_irq", }, }, { /* bq27500 fuel-gauge for the round li-ion cells in the hinge */ Loading @@ -640,6 +645,7 @@ static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = { .index = 77, .trigger = ACPI_LEVEL_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, .con_id = "hideep_ts_irq", }, }, { /* LP8557 Backlight controller */ Loading @@ -655,7 +661,6 @@ static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = { static int __init lenovo_yt3_init(void) { struct gpio_desc *gpiod; int ret; /* Loading @@ -665,31 +670,23 @@ static int __init lenovo_yt3_init(void) * * The bq25890_charger driver controls these through I2C, but this only * works if not overridden by the pins. Set these pins here: * 1. Set /CE to 0 to allow charging. * 1. Set /CE to 1 to allow charging. * 2. Set OTG to 0 disable V5 boost output since the 5V boost output of * the main "bq25892_1" charger is used when necessary. */ /* /CE pin */ ret = x86_android_tablet_get_gpiod("INT33FF:02", 22, &gpiod); ret = x86_android_tablet_get_gpiod("INT33FF:02", 22, "bq25892_0_ce", true, GPIOD_OUT_HIGH, NULL); if (ret < 0) return ret; /* * The gpio_desc returned by x86_android_tablet_get_gpiod() is a "raw" * gpio_desc, that is there is no way to pass lookup-flags like * GPIO_ACTIVE_LOW. Set the GPIO to 0 here to enable charging since * the /CE pin is active-low, but not marked as such in the gpio_desc. */ gpiod_set_value(gpiod, 0); /* OTG pin */ ret = x86_android_tablet_get_gpiod("INT33FF:03", 19, &gpiod); ret = x86_android_tablet_get_gpiod("INT33FF:03", 19, "bq25892_0_otg", false, GPIOD_OUT_LOW, NULL); if (ret < 0) return ret; gpiod_set_value(gpiod, 0); /* Enable the regulators used by the touchscreen */ intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9b, 0x02, 0xff); intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa0, 0x02, 0xff); Loading drivers/platform/x86/x86-android-tablets/other.c +6 −5 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ static const struct x86_i2c_client_info acer_b1_750_i2c_clients[] __initconst = .index = 3, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, .con_id = "NVT-ts_irq", }, }, { /* BMA250E accelerometer */ Loading @@ -62,6 +63,7 @@ static const struct x86_i2c_client_info acer_b1_750_i2c_clients[] __initconst = .index = 25, .trigger = ACPI_LEVEL_SENSITIVE, .polarity = ACPI_ACTIVE_HIGH, .con_id = "bma250e_irq", }, }, }; Loading Loading @@ -174,6 +176,7 @@ static const struct x86_i2c_client_info chuwi_hi8_i2c_clients[] __initconst = { .index = 23, .trigger = ACPI_LEVEL_SENSITIVE, .polarity = ACPI_ACTIVE_HIGH, .con_id = "bma250e_irq", }, }, }; Loading Loading @@ -312,6 +315,7 @@ static const struct x86_i2c_client_info medion_lifetab_s10346_i2c_clients[] __in .index = 23, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_HIGH, .con_id = "kxtj21009_irq", }, }, { /* goodix touchscreen */ Loading Loading @@ -402,6 +406,7 @@ static const struct x86_i2c_client_info nextbook_ares8_i2c_clients[] __initconst .index = 3, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, .con_id = "ft5416_irq", }, }, }; Loading Loading @@ -460,6 +465,7 @@ static const struct x86_i2c_client_info nextbook_ares8a_i2c_clients[] __initcons .index = 17, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, .con_id = "ft5416_irq", }, }, }; Loading Loading @@ -505,11 +511,6 @@ static const struct x86_gpio_button peaq_c1010_button __initconst = { const struct x86_dev_info peaq_c1010_info __initconst = { .gpio_button = &peaq_c1010_button, .gpio_button_count = 1, /* * Move the ACPI event handler used by the broken WMI interface out of * the way. This is the only event handler on INT33FC:00. */ .invalid_aei_gpiochip = "INT33FC:00", }; /* Loading Loading
drivers/gpio/gpiolib-acpi.c +25 −5 Original line number Diff line number Diff line Loading @@ -437,6 +437,11 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares, if (!handler) return AE_OK; if (acpi_gpio_in_ignore_list(ignore_interrupt, dev_name(chip->parent), pin)) { dev_info(chip->parent, "Ignoring interrupt on pin %u\n", pin); return AE_OK; } desc = acpi_request_own_gpiod(chip, agpio, 0, "ACPI:Event"); if (IS_ERR(desc)) { dev_err(chip->parent, Loading @@ -461,11 +466,6 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares, goto fail_unlock_irq; } if (acpi_gpio_in_ignore_list(ignore_interrupt, dev_name(chip->parent), pin)) { dev_info(chip->parent, "Ignoring interrupt on pin %u\n", pin); return AE_OK; } event = kzalloc(sizeof(*event), GFP_KERNEL); if (!event) goto fail_unlock_irq; Loading Loading @@ -1654,6 +1654,26 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = { .ignore_wake = "SYNA1202:00@16", }, }, { /* * On the Peaq C1010 2-in-1 INT33FC:00 pin 3 is connected to * a "dolby" button. At the ACPI level an _AEI event-handler * is connected which sets an ACPI variable to 1 on both * edges. This variable can be polled + cleared to 0 using * WMI. But since the variable is set on both edges the WMI * interface is pretty useless even when polling. * So instead the x86-android-tablets code instantiates * a gpio-keys platform device for it. * Ignore the _AEI handler for the pin, so that it is not busy. */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "PEAQ"), DMI_MATCH(DMI_PRODUCT_NAME, "PEAQ PMM C1010 MD99187"), }, .driver_data = &(struct acpi_gpiolib_dmi_quirk) { .ignore_interrupt = "INT33FC:00@3", }, }, {} /* Terminating entry */ }; Loading
drivers/platform/x86/x86-android-tablets/asus.c +1 −0 Original line number Diff line number Diff line Loading @@ -303,6 +303,7 @@ static const struct x86_i2c_client_info asus_tf103c_i2c_clients[] __initconst = .index = 28, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, .con_id = "atmel_mxt_ts_irq", }, }, }; Loading
drivers/platform/x86/x86-android-tablets/core.c +83 −49 Original line number Diff line number Diff line Loading @@ -12,7 +12,7 @@ #include <linux/acpi.h> #include <linux/dmi.h> #include <linux/gpio/driver.h> #include <linux/gpio/consumer.h> #include <linux/gpio/machine.h> #include <linux/irq.h> #include <linux/module.h> Loading @@ -21,33 +21,54 @@ #include <linux/string.h> #include "x86-android-tablets.h" /* For gpiochip_get_desc() which is EXPORT_SYMBOL_GPL() */ #include "../../../gpio/gpiolib.h" #include "../../../gpio/gpiolib-acpi.h" static int gpiochip_find_match_label(struct gpio_chip *gc, void *data) { return gc->label && !strcmp(gc->label, data); } static struct platform_device *x86_android_tablet_device; int x86_android_tablet_get_gpiod(const char *label, int pin, struct gpio_desc **desc) /* * This helper allows getting a gpio_desc *before* the actual device consuming * the GPIO has been instantiated. This function _must_ only be used to handle * this special case such as e.g. : * * 1. Getting an IRQ from a GPIO for i2c_board_info.irq which is passed to * i2c_client_new() to instantiate i2c_client-s; or * 2. Calling desc_to_gpio() to get an old style GPIO number for gpio_keys * platform_data which still uses old style GPIO numbers. * * Since the consuming device has not been instatiated yet a dynamic lookup * is generated using the special x86_android_tablet dev for dev_id. * * For normal GPIO lookups a standard static gpiod_lookup_table _must_ be used. */ int x86_android_tablet_get_gpiod(const char *chip, int pin, const char *con_id, bool active_low, enum gpiod_flags dflags, struct gpio_desc **desc) { struct gpiod_lookup_table *lookup; struct gpio_desc *gpiod; struct gpio_chip *chip; chip = gpiochip_find((void *)label, gpiochip_find_match_label); if (!chip) { pr_err("error cannot find GPIO chip %s\n", label); return -ENODEV; } lookup = kzalloc(struct_size(lookup, table, 2), GFP_KERNEL); if (!lookup) return -ENOMEM; lookup->dev_id = KBUILD_MODNAME; lookup->table[0].key = chip; lookup->table[0].chip_hwnum = pin; lookup->table[0].con_id = con_id; lookup->table[0].flags = active_low ? GPIO_ACTIVE_LOW : GPIO_ACTIVE_HIGH; gpiod_add_lookup_table(lookup); gpiod = devm_gpiod_get(&x86_android_tablet_device->dev, con_id, dflags); gpiod_remove_lookup_table(lookup); kfree(lookup); gpiod = gpiochip_get_desc(chip, pin); if (IS_ERR(gpiod)) { pr_err("error %ld getting GPIO %s %d\n", PTR_ERR(gpiod), label, pin); pr_err("error %ld getting GPIO %s %d\n", PTR_ERR(gpiod), chip, pin); return PTR_ERR(gpiod); } if (desc) *desc = gpiod; return 0; } Loading Loading @@ -77,7 +98,8 @@ int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data) return irq; case X86_ACPI_IRQ_TYPE_GPIOINT: /* Like acpi_dev_gpio_irq_get(), but without parsing ACPI resources */ ret = x86_android_tablet_get_gpiod(data->chip, data->index, &gpiod); ret = x86_android_tablet_get_gpiod(data->chip, data->index, data->con_id, false, GPIOD_ASIS, &gpiod); if (ret) return ret; Loading Loading @@ -224,7 +246,7 @@ static __init int x86_instantiate_serdev(const struct x86_serdev_info *info, int return ret; } static void x86_android_tablet_cleanup(void) static void x86_android_tablet_remove(struct platform_device *pdev) { int i; Loading Loading @@ -255,11 +277,10 @@ static void x86_android_tablet_cleanup(void) software_node_unregister(bat_swnode); } static __init int x86_android_tablet_init(void) static __init int x86_android_tablet_probe(struct platform_device *pdev) { const struct x86_dev_info *dev_info; const struct dmi_system_id *id; struct gpio_chip *chip; int i, ret = 0; id = dmi_first_match(x86_android_tablet_ids); Loading @@ -267,20 +288,8 @@ static __init int x86_android_tablet_init(void) return -ENODEV; dev_info = id->driver_data; /* * The broken DSDTs on these devices often also include broken * _AEI (ACPI Event Interrupt) handlers, disable these. */ if (dev_info->invalid_aei_gpiochip) { chip = gpiochip_find(dev_info->invalid_aei_gpiochip, gpiochip_find_match_label); if (!chip) { pr_err("error cannot find GPIO chip %s\n", dev_info->invalid_aei_gpiochip); return -ENODEV; } acpi_gpiochip_free_interrupts(chip); } /* Allow x86_android_tablet_device use before probe() exits */ x86_android_tablet_device = pdev; /* * Since this runs from module_init() it cannot use -EPROBE_DEFER, Loading @@ -303,7 +312,7 @@ static __init int x86_android_tablet_init(void) if (dev_info->init) { ret = dev_info->init(); if (ret < 0) { x86_android_tablet_cleanup(); x86_android_tablet_remove(pdev); return ret; } exit_handler = dev_info->exit; Loading @@ -311,7 +320,7 @@ static __init int x86_android_tablet_init(void) i2c_clients = kcalloc(dev_info->i2c_client_count, sizeof(*i2c_clients), GFP_KERNEL); if (!i2c_clients) { x86_android_tablet_cleanup(); x86_android_tablet_remove(pdev); return -ENOMEM; } Loading @@ -319,7 +328,7 @@ static __init int x86_android_tablet_init(void) for (i = 0; i < i2c_client_count; i++) { ret = x86_instantiate_i2c_client(dev_info, i); if (ret < 0) { x86_android_tablet_cleanup(); x86_android_tablet_remove(pdev); return ret; } } Loading @@ -327,7 +336,7 @@ static __init int x86_android_tablet_init(void) /* + 1 to make space for (optional) gpio_keys_button pdev */ pdevs = kcalloc(dev_info->pdev_count + 1, sizeof(*pdevs), GFP_KERNEL); if (!pdevs) { x86_android_tablet_cleanup(); x86_android_tablet_remove(pdev); return -ENOMEM; } Loading @@ -335,14 +344,14 @@ static __init int x86_android_tablet_init(void) for (i = 0; i < pdev_count; i++) { pdevs[i] = platform_device_register_full(&dev_info->pdev_info[i]); if (IS_ERR(pdevs[i])) { x86_android_tablet_cleanup(); x86_android_tablet_remove(pdev); return PTR_ERR(pdevs[i]); } } serdevs = kcalloc(dev_info->serdev_count, sizeof(*serdevs), GFP_KERNEL); if (!serdevs) { x86_android_tablet_cleanup(); x86_android_tablet_remove(pdev); return -ENOMEM; } Loading @@ -350,7 +359,7 @@ static __init int x86_android_tablet_init(void) for (i = 0; i < serdev_count; i++) { ret = x86_instantiate_serdev(&dev_info->serdev_info[i], i); if (ret < 0) { x86_android_tablet_cleanup(); x86_android_tablet_remove(pdev); return ret; } } Loading @@ -361,30 +370,34 @@ static __init int x86_android_tablet_init(void) buttons = kcalloc(dev_info->gpio_button_count, sizeof(*buttons), GFP_KERNEL); if (!buttons) { x86_android_tablet_cleanup(); x86_android_tablet_remove(pdev); return -ENOMEM; } for (i = 0; i < dev_info->gpio_button_count; i++) { ret = x86_android_tablet_get_gpiod(dev_info->gpio_button[i].chip, dev_info->gpio_button[i].pin, &gpiod); dev_info->gpio_button[i].pin, dev_info->gpio_button[i].button.desc, false, GPIOD_IN, &gpiod); if (ret < 0) { x86_android_tablet_cleanup(); x86_android_tablet_remove(pdev); return ret; } buttons[i] = dev_info->gpio_button[i].button; buttons[i].gpio = desc_to_gpio(gpiod); /* Release gpiod so that gpio-keys can request it */ devm_gpiod_put(&x86_android_tablet_device->dev, gpiod); } pdata.buttons = buttons; pdata.nbuttons = dev_info->gpio_button_count; pdevs[pdev_count] = platform_device_register_data(NULL, "gpio-keys", pdevs[pdev_count] = platform_device_register_data(&pdev->dev, "gpio-keys", PLATFORM_DEVID_AUTO, &pdata, sizeof(pdata)); if (IS_ERR(pdevs[pdev_count])) { x86_android_tablet_cleanup(); x86_android_tablet_remove(pdev); return PTR_ERR(pdevs[pdev_count]); } pdev_count++; Loading @@ -393,8 +406,29 @@ static __init int x86_android_tablet_init(void) return 0; } static struct platform_driver x86_android_tablet_driver = { .driver = { .name = KBUILD_MODNAME, }, .remove_new = x86_android_tablet_remove, }; static int __init x86_android_tablet_init(void) { x86_android_tablet_device = platform_create_bundle(&x86_android_tablet_driver, x86_android_tablet_probe, NULL, 0, NULL, 0); return PTR_ERR_OR_ZERO(x86_android_tablet_device); } module_init(x86_android_tablet_init); module_exit(x86_android_tablet_cleanup); static void __exit x86_android_tablet_exit(void) { platform_device_unregister(x86_android_tablet_device); platform_driver_unregister(&x86_android_tablet_driver); } module_exit(x86_android_tablet_exit); MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); MODULE_DESCRIPTION("X86 Android tablets DSDT fixups driver"); Loading
drivers/platform/x86/x86-android-tablets/lenovo.c +13 −16 Original line number Diff line number Diff line Loading @@ -95,6 +95,7 @@ static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst .index = 56, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, .con_id = "goodix_ts_irq", }, }, { /* Wacom Digitizer in keyboard half */ Loading @@ -111,6 +112,7 @@ static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst .index = 49, .trigger = ACPI_LEVEL_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, .con_id = "wacom_irq", }, }, { /* LP8557 Backlight controller */ Loading @@ -136,6 +138,7 @@ static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst .index = 77, .trigger = ACPI_LEVEL_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, .con_id = "hideep_ts_irq", }, }, }; Loading Loading @@ -321,6 +324,7 @@ static struct x86_i2c_client_info lenovo_yoga_tab2_830_1050_i2c_clients[] __init .index = 2, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_HIGH, .con_id = "bq24292i_irq", }, }, { /* BQ27541 fuel-gauge */ Loading Loading @@ -431,7 +435,8 @@ static int __init lenovo_yoga_tab2_830_1050_init_touchscreen(void) int ret; /* Use PMIC GPIO 10 bootstrap pin to differentiate 830 vs 1050 */ ret = x86_android_tablet_get_gpiod("gpio_crystalcove", 10, &gpiod); ret = x86_android_tablet_get_gpiod("gpio_crystalcove", 10, "yoga_bootstrap", false, GPIOD_IN, &gpiod); if (ret) return ret; Loading Loading @@ -560,7 +565,6 @@ static const struct software_node fg_bq25890_1_supply_node = { /* bq25892 charger settings for the flat lipo battery behind the screen */ static const struct property_entry lenovo_yt3_bq25892_0_props[] = { PROPERTY_ENTRY_STRING_ARRAY("supplied-from", lenovo_yt3_bq25892_0_suppliers), PROPERTY_ENTRY_STRING("linux,power-supply-name", "bq25892-second-chrg"), PROPERTY_ENTRY_U32("linux,iinlim-percentage", 40), PROPERTY_ENTRY_BOOL("linux,skip-reset"), /* Values taken from Android Factory Image */ Loading Loading @@ -615,6 +619,7 @@ static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = { .index = 5, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, .con_id = "bq25892_0_irq", }, }, { /* bq27500 fuel-gauge for the round li-ion cells in the hinge */ Loading @@ -640,6 +645,7 @@ static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = { .index = 77, .trigger = ACPI_LEVEL_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, .con_id = "hideep_ts_irq", }, }, { /* LP8557 Backlight controller */ Loading @@ -655,7 +661,6 @@ static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = { static int __init lenovo_yt3_init(void) { struct gpio_desc *gpiod; int ret; /* Loading @@ -665,31 +670,23 @@ static int __init lenovo_yt3_init(void) * * The bq25890_charger driver controls these through I2C, but this only * works if not overridden by the pins. Set these pins here: * 1. Set /CE to 0 to allow charging. * 1. Set /CE to 1 to allow charging. * 2. Set OTG to 0 disable V5 boost output since the 5V boost output of * the main "bq25892_1" charger is used when necessary. */ /* /CE pin */ ret = x86_android_tablet_get_gpiod("INT33FF:02", 22, &gpiod); ret = x86_android_tablet_get_gpiod("INT33FF:02", 22, "bq25892_0_ce", true, GPIOD_OUT_HIGH, NULL); if (ret < 0) return ret; /* * The gpio_desc returned by x86_android_tablet_get_gpiod() is a "raw" * gpio_desc, that is there is no way to pass lookup-flags like * GPIO_ACTIVE_LOW. Set the GPIO to 0 here to enable charging since * the /CE pin is active-low, but not marked as such in the gpio_desc. */ gpiod_set_value(gpiod, 0); /* OTG pin */ ret = x86_android_tablet_get_gpiod("INT33FF:03", 19, &gpiod); ret = x86_android_tablet_get_gpiod("INT33FF:03", 19, "bq25892_0_otg", false, GPIOD_OUT_LOW, NULL); if (ret < 0) return ret; gpiod_set_value(gpiod, 0); /* Enable the regulators used by the touchscreen */ intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9b, 0x02, 0xff); intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa0, 0x02, 0xff); Loading
drivers/platform/x86/x86-android-tablets/other.c +6 −5 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ static const struct x86_i2c_client_info acer_b1_750_i2c_clients[] __initconst = .index = 3, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, .con_id = "NVT-ts_irq", }, }, { /* BMA250E accelerometer */ Loading @@ -62,6 +63,7 @@ static const struct x86_i2c_client_info acer_b1_750_i2c_clients[] __initconst = .index = 25, .trigger = ACPI_LEVEL_SENSITIVE, .polarity = ACPI_ACTIVE_HIGH, .con_id = "bma250e_irq", }, }, }; Loading Loading @@ -174,6 +176,7 @@ static const struct x86_i2c_client_info chuwi_hi8_i2c_clients[] __initconst = { .index = 23, .trigger = ACPI_LEVEL_SENSITIVE, .polarity = ACPI_ACTIVE_HIGH, .con_id = "bma250e_irq", }, }, }; Loading Loading @@ -312,6 +315,7 @@ static const struct x86_i2c_client_info medion_lifetab_s10346_i2c_clients[] __in .index = 23, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_HIGH, .con_id = "kxtj21009_irq", }, }, { /* goodix touchscreen */ Loading Loading @@ -402,6 +406,7 @@ static const struct x86_i2c_client_info nextbook_ares8_i2c_clients[] __initconst .index = 3, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, .con_id = "ft5416_irq", }, }, }; Loading Loading @@ -460,6 +465,7 @@ static const struct x86_i2c_client_info nextbook_ares8a_i2c_clients[] __initcons .index = 17, .trigger = ACPI_EDGE_SENSITIVE, .polarity = ACPI_ACTIVE_LOW, .con_id = "ft5416_irq", }, }, }; Loading Loading @@ -505,11 +511,6 @@ static const struct x86_gpio_button peaq_c1010_button __initconst = { const struct x86_dev_info peaq_c1010_info __initconst = { .gpio_button = &peaq_c1010_button, .gpio_button_count = 1, /* * Move the ACPI event handler used by the broken WMI interface out of * the way. This is the only event handler on INT33FC:00. */ .invalid_aei_gpiochip = "INT33FC:00", }; /* Loading