Merge tag 'gpio-updates-for-v6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / drivers / gpio / gpiolib-acpi.c
index 51e41676de0b8df597a7d9afd493165863e5b053..88066826d8e5b629697136b8bb2431b543544977 100644 (file)
@@ -143,7 +143,6 @@ static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)
  */
 static struct gpio_desc *acpi_get_gpiod(char *path, unsigned int pin)
 {
-       struct gpio_chip *chip;
        acpi_handle handle;
        acpi_status status;
 
@@ -151,40 +150,17 @@ static struct gpio_desc *acpi_get_gpiod(char *path, unsigned int pin)
        if (ACPI_FAILURE(status))
                return ERR_PTR(-ENODEV);
 
-       chip = gpiochip_find(handle, acpi_gpiochip_find);
-       if (!chip)
+       struct gpio_device *gdev __free(gpio_device_put) =
+                               gpio_device_find(handle, acpi_gpiochip_find);
+       if (!gdev)
                return ERR_PTR(-EPROBE_DEFER);
 
-       return gpiochip_get_desc(chip, pin);
-}
-
-/**
- * acpi_get_and_request_gpiod - Translate ACPI GPIO pin to GPIO descriptor and
- *                              hold a refcount to the GPIO device.
- * @path:      ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1")
- * @pin:       ACPI GPIO pin number (0-based, controller-relative)
- * @label:     Label to pass to gpiod_request()
- *
- * This function is a simple pass-through to acpi_get_gpiod(), except that
- * as it is intended for use outside of the GPIO layer (in a similar fashion to
- * gpiod_get_index() for example) it also holds a reference to the GPIO device.
- */
-struct gpio_desc *acpi_get_and_request_gpiod(char *path, unsigned int pin, char *label)
-{
-       struct gpio_desc *gpio;
-       int ret;
-
-       gpio = acpi_get_gpiod(path, pin);
-       if (IS_ERR(gpio))
-               return gpio;
-
-       ret = gpiod_request(gpio, label);
-       if (ret)
-               return ERR_PTR(ret);
-
-       return gpio;
+       /*
+        * FIXME: keep track of the reference to the GPIO device somehow
+        * instead of putting it here.
+        */
+       return gpio_device_get_desc(gdev, pin);
 }
-EXPORT_SYMBOL_GPL(acpi_get_and_request_gpiod);
 
 static irqreturn_t acpi_gpio_irq_handler(int irq, void *data)
 {
@@ -437,6 +413,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,
@@ -461,11 +442,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;
@@ -1655,6 +1631,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 */
 };