Skip to content

Commit eab541a

Browse files
committed
Merge remote-tracking branch 'pdx86/platform-drivers-x86-android-tablets' into review-hans
2 parents 4106a70 + eee9cd5 commit eab541a

6 files changed

Lines changed: 133 additions & 77 deletions

File tree

drivers/gpio/gpiolib-acpi.c

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,11 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
437437
if (!handler)
438438
return AE_OK;
439439

440+
if (acpi_gpio_in_ignore_list(ignore_interrupt, dev_name(chip->parent), pin)) {
441+
dev_info(chip->parent, "Ignoring interrupt on pin %u\n", pin);
442+
return AE_OK;
443+
}
444+
440445
desc = acpi_request_own_gpiod(chip, agpio, 0, "ACPI:Event");
441446
if (IS_ERR(desc)) {
442447
dev_err(chip->parent,
@@ -461,11 +466,6 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
461466
goto fail_unlock_irq;
462467
}
463468

464-
if (acpi_gpio_in_ignore_list(ignore_interrupt, dev_name(chip->parent), pin)) {
465-
dev_info(chip->parent, "Ignoring interrupt on pin %u\n", pin);
466-
return AE_OK;
467-
}
468-
469469
event = kzalloc(sizeof(*event), GFP_KERNEL);
470470
if (!event)
471471
goto fail_unlock_irq;
@@ -1654,6 +1654,26 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = {
16541654
.ignore_wake = "SYNA1202:00@16",
16551655
},
16561656
},
1657+
{
1658+
/*
1659+
* On the Peaq C1010 2-in-1 INT33FC:00 pin 3 is connected to
1660+
* a "dolby" button. At the ACPI level an _AEI event-handler
1661+
* is connected which sets an ACPI variable to 1 on both
1662+
* edges. This variable can be polled + cleared to 0 using
1663+
* WMI. But since the variable is set on both edges the WMI
1664+
* interface is pretty useless even when polling.
1665+
* So instead the x86-android-tablets code instantiates
1666+
* a gpio-keys platform device for it.
1667+
* Ignore the _AEI handler for the pin, so that it is not busy.
1668+
*/
1669+
.matches = {
1670+
DMI_MATCH(DMI_SYS_VENDOR, "PEAQ"),
1671+
DMI_MATCH(DMI_PRODUCT_NAME, "PEAQ PMM C1010 MD99187"),
1672+
},
1673+
.driver_data = &(struct acpi_gpiolib_dmi_quirk) {
1674+
.ignore_interrupt = "INT33FC:00@3",
1675+
},
1676+
},
16571677
{} /* Terminating entry */
16581678
};
16591679

drivers/platform/x86/x86-android-tablets/asus.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ static const struct x86_i2c_client_info asus_tf103c_i2c_clients[] __initconst =
303303
.index = 28,
304304
.trigger = ACPI_EDGE_SENSITIVE,
305305
.polarity = ACPI_ACTIVE_LOW,
306+
.con_id = "atmel_mxt_ts_irq",
306307
},
307308
},
308309
};

drivers/platform/x86/x86-android-tablets/core.c

Lines changed: 83 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
#include <linux/acpi.h>
1414
#include <linux/dmi.h>
15-
#include <linux/gpio/driver.h>
15+
#include <linux/gpio/consumer.h>
1616
#include <linux/gpio/machine.h>
1717
#include <linux/irq.h>
1818
#include <linux/module.h>
@@ -21,33 +21,54 @@
2121
#include <linux/string.h>
2222

2323
#include "x86-android-tablets.h"
24-
/* For gpiochip_get_desc() which is EXPORT_SYMBOL_GPL() */
25-
#include "../../../gpio/gpiolib.h"
26-
#include "../../../gpio/gpiolib-acpi.h"
2724

28-
static int gpiochip_find_match_label(struct gpio_chip *gc, void *data)
29-
{
30-
return gc->label && !strcmp(gc->label, data);
31-
}
25+
static struct platform_device *x86_android_tablet_device;
3226

33-
int x86_android_tablet_get_gpiod(const char *label, int pin, struct gpio_desc **desc)
27+
/*
28+
* This helper allows getting a gpio_desc *before* the actual device consuming
29+
* the GPIO has been instantiated. This function _must_ only be used to handle
30+
* this special case such as e.g. :
31+
*
32+
* 1. Getting an IRQ from a GPIO for i2c_board_info.irq which is passed to
33+
* i2c_client_new() to instantiate i2c_client-s; or
34+
* 2. Calling desc_to_gpio() to get an old style GPIO number for gpio_keys
35+
* platform_data which still uses old style GPIO numbers.
36+
*
37+
* Since the consuming device has not been instatiated yet a dynamic lookup
38+
* is generated using the special x86_android_tablet dev for dev_id.
39+
*
40+
* For normal GPIO lookups a standard static gpiod_lookup_table _must_ be used.
41+
*/
42+
int x86_android_tablet_get_gpiod(const char *chip, int pin, const char *con_id,
43+
bool active_low, enum gpiod_flags dflags,
44+
struct gpio_desc **desc)
3445
{
46+
struct gpiod_lookup_table *lookup;
3547
struct gpio_desc *gpiod;
36-
struct gpio_chip *chip;
3748

38-
chip = gpiochip_find((void *)label, gpiochip_find_match_label);
39-
if (!chip) {
40-
pr_err("error cannot find GPIO chip %s\n", label);
41-
return -ENODEV;
42-
}
49+
lookup = kzalloc(struct_size(lookup, table, 2), GFP_KERNEL);
50+
if (!lookup)
51+
return -ENOMEM;
52+
53+
lookup->dev_id = KBUILD_MODNAME;
54+
lookup->table[0].key = chip;
55+
lookup->table[0].chip_hwnum = pin;
56+
lookup->table[0].con_id = con_id;
57+
lookup->table[0].flags = active_low ? GPIO_ACTIVE_LOW : GPIO_ACTIVE_HIGH;
58+
59+
gpiod_add_lookup_table(lookup);
60+
gpiod = devm_gpiod_get(&x86_android_tablet_device->dev, con_id, dflags);
61+
gpiod_remove_lookup_table(lookup);
62+
kfree(lookup);
4363

44-
gpiod = gpiochip_get_desc(chip, pin);
4564
if (IS_ERR(gpiod)) {
46-
pr_err("error %ld getting GPIO %s %d\n", PTR_ERR(gpiod), label, pin);
65+
pr_err("error %ld getting GPIO %s %d\n", PTR_ERR(gpiod), chip, pin);
4766
return PTR_ERR(gpiod);
4867
}
4968

50-
*desc = gpiod;
69+
if (desc)
70+
*desc = gpiod;
71+
5172
return 0;
5273
}
5374

@@ -77,7 +98,8 @@ int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data)
7798
return irq;
7899
case X86_ACPI_IRQ_TYPE_GPIOINT:
79100
/* Like acpi_dev_gpio_irq_get(), but without parsing ACPI resources */
80-
ret = x86_android_tablet_get_gpiod(data->chip, data->index, &gpiod);
101+
ret = x86_android_tablet_get_gpiod(data->chip, data->index, data->con_id,
102+
false, GPIOD_ASIS, &gpiod);
81103
if (ret)
82104
return ret;
83105

@@ -224,7 +246,7 @@ static __init int x86_instantiate_serdev(const struct x86_serdev_info *info, int
224246
return ret;
225247
}
226248

227-
static void x86_android_tablet_cleanup(void)
249+
static void x86_android_tablet_remove(struct platform_device *pdev)
228250
{
229251
int i;
230252

@@ -255,32 +277,19 @@ static void x86_android_tablet_cleanup(void)
255277
software_node_unregister(bat_swnode);
256278
}
257279

258-
static __init int x86_android_tablet_init(void)
280+
static __init int x86_android_tablet_probe(struct platform_device *pdev)
259281
{
260282
const struct x86_dev_info *dev_info;
261283
const struct dmi_system_id *id;
262-
struct gpio_chip *chip;
263284
int i, ret = 0;
264285

265286
id = dmi_first_match(x86_android_tablet_ids);
266287
if (!id)
267288
return -ENODEV;
268289

269290
dev_info = id->driver_data;
270-
271-
/*
272-
* The broken DSDTs on these devices often also include broken
273-
* _AEI (ACPI Event Interrupt) handlers, disable these.
274-
*/
275-
if (dev_info->invalid_aei_gpiochip) {
276-
chip = gpiochip_find(dev_info->invalid_aei_gpiochip,
277-
gpiochip_find_match_label);
278-
if (!chip) {
279-
pr_err("error cannot find GPIO chip %s\n", dev_info->invalid_aei_gpiochip);
280-
return -ENODEV;
281-
}
282-
acpi_gpiochip_free_interrupts(chip);
283-
}
291+
/* Allow x86_android_tablet_device use before probe() exits */
292+
x86_android_tablet_device = pdev;
284293

285294
/*
286295
* Since this runs from module_init() it cannot use -EPROBE_DEFER,
@@ -303,54 +312,54 @@ static __init int x86_android_tablet_init(void)
303312
if (dev_info->init) {
304313
ret = dev_info->init();
305314
if (ret < 0) {
306-
x86_android_tablet_cleanup();
315+
x86_android_tablet_remove(pdev);
307316
return ret;
308317
}
309318
exit_handler = dev_info->exit;
310319
}
311320

312321
i2c_clients = kcalloc(dev_info->i2c_client_count, sizeof(*i2c_clients), GFP_KERNEL);
313322
if (!i2c_clients) {
314-
x86_android_tablet_cleanup();
323+
x86_android_tablet_remove(pdev);
315324
return -ENOMEM;
316325
}
317326

318327
i2c_client_count = dev_info->i2c_client_count;
319328
for (i = 0; i < i2c_client_count; i++) {
320329
ret = x86_instantiate_i2c_client(dev_info, i);
321330
if (ret < 0) {
322-
x86_android_tablet_cleanup();
331+
x86_android_tablet_remove(pdev);
323332
return ret;
324333
}
325334
}
326335

327336
/* + 1 to make space for (optional) gpio_keys_button pdev */
328337
pdevs = kcalloc(dev_info->pdev_count + 1, sizeof(*pdevs), GFP_KERNEL);
329338
if (!pdevs) {
330-
x86_android_tablet_cleanup();
339+
x86_android_tablet_remove(pdev);
331340
return -ENOMEM;
332341
}
333342

334343
pdev_count = dev_info->pdev_count;
335344
for (i = 0; i < pdev_count; i++) {
336345
pdevs[i] = platform_device_register_full(&dev_info->pdev_info[i]);
337346
if (IS_ERR(pdevs[i])) {
338-
x86_android_tablet_cleanup();
347+
x86_android_tablet_remove(pdev);
339348
return PTR_ERR(pdevs[i]);
340349
}
341350
}
342351

343352
serdevs = kcalloc(dev_info->serdev_count, sizeof(*serdevs), GFP_KERNEL);
344353
if (!serdevs) {
345-
x86_android_tablet_cleanup();
354+
x86_android_tablet_remove(pdev);
346355
return -ENOMEM;
347356
}
348357

349358
serdev_count = dev_info->serdev_count;
350359
for (i = 0; i < serdev_count; i++) {
351360
ret = x86_instantiate_serdev(&dev_info->serdev_info[i], i);
352361
if (ret < 0) {
353-
x86_android_tablet_cleanup();
362+
x86_android_tablet_remove(pdev);
354363
return ret;
355364
}
356365
}
@@ -361,30 +370,34 @@ static __init int x86_android_tablet_init(void)
361370

362371
buttons = kcalloc(dev_info->gpio_button_count, sizeof(*buttons), GFP_KERNEL);
363372
if (!buttons) {
364-
x86_android_tablet_cleanup();
373+
x86_android_tablet_remove(pdev);
365374
return -ENOMEM;
366375
}
367376

368377
for (i = 0; i < dev_info->gpio_button_count; i++) {
369378
ret = x86_android_tablet_get_gpiod(dev_info->gpio_button[i].chip,
370-
dev_info->gpio_button[i].pin, &gpiod);
379+
dev_info->gpio_button[i].pin,
380+
dev_info->gpio_button[i].button.desc,
381+
false, GPIOD_IN, &gpiod);
371382
if (ret < 0) {
372-
x86_android_tablet_cleanup();
383+
x86_android_tablet_remove(pdev);
373384
return ret;
374385
}
375386

376387
buttons[i] = dev_info->gpio_button[i].button;
377388
buttons[i].gpio = desc_to_gpio(gpiod);
389+
/* Release gpiod so that gpio-keys can request it */
390+
devm_gpiod_put(&x86_android_tablet_device->dev, gpiod);
378391
}
379392

380393
pdata.buttons = buttons;
381394
pdata.nbuttons = dev_info->gpio_button_count;
382395

383-
pdevs[pdev_count] = platform_device_register_data(NULL, "gpio-keys",
396+
pdevs[pdev_count] = platform_device_register_data(&pdev->dev, "gpio-keys",
384397
PLATFORM_DEVID_AUTO,
385398
&pdata, sizeof(pdata));
386399
if (IS_ERR(pdevs[pdev_count])) {
387-
x86_android_tablet_cleanup();
400+
x86_android_tablet_remove(pdev);
388401
return PTR_ERR(pdevs[pdev_count]);
389402
}
390403
pdev_count++;
@@ -393,8 +406,29 @@ static __init int x86_android_tablet_init(void)
393406
return 0;
394407
}
395408

409+
static struct platform_driver x86_android_tablet_driver = {
410+
.driver = {
411+
.name = KBUILD_MODNAME,
412+
},
413+
.remove_new = x86_android_tablet_remove,
414+
};
415+
416+
static int __init x86_android_tablet_init(void)
417+
{
418+
x86_android_tablet_device = platform_create_bundle(&x86_android_tablet_driver,
419+
x86_android_tablet_probe,
420+
NULL, 0, NULL, 0);
421+
422+
return PTR_ERR_OR_ZERO(x86_android_tablet_device);
423+
}
396424
module_init(x86_android_tablet_init);
397-
module_exit(x86_android_tablet_cleanup);
425+
426+
static void __exit x86_android_tablet_exit(void)
427+
{
428+
platform_device_unregister(x86_android_tablet_device);
429+
platform_driver_unregister(&x86_android_tablet_driver);
430+
}
431+
module_exit(x86_android_tablet_exit);
398432

399433
MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
400434
MODULE_DESCRIPTION("X86 Android tablets DSDT fixups driver");

0 commit comments

Comments
 (0)