forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/drivers/input/misc/soc_button_array.c
....@@ -1,24 +1,26 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Supports for the button array on SoC tablets originally running
34 * Windows 8.
45 *
56 * (C) Copyright 2014 Intel Corporation
6
- *
7
- * This program is free software; you can redistribute it and/or
8
- * modify it under the terms of the GNU General Public License
9
- * as published by the Free Software Foundation; version 2
10
- * of the License.
117 */
128
139 #include <linux/module.h>
1410 #include <linux/input.h>
1511 #include <linux/init.h>
12
+#include <linux/irq.h>
1613 #include <linux/kernel.h>
1714 #include <linux/acpi.h>
15
+#include <linux/dmi.h>
1816 #include <linux/gpio/consumer.h>
1917 #include <linux/gpio_keys.h>
2018 #include <linux/gpio.h>
2119 #include <linux/platform_device.h>
20
+
21
+static bool use_low_level_irq;
22
+module_param(use_low_level_irq, bool, 0444);
23
+MODULE_PARM_DESC(use_low_level_irq, "Use low-level triggered IRQ instead of edge triggered");
2224
2325 struct soc_button_info {
2426 const char *name;
....@@ -27,6 +29,12 @@
2729 unsigned int event_code;
2830 bool autorepeat;
2931 bool wakeup;
32
+ bool active_low;
33
+};
34
+
35
+struct soc_device_data {
36
+ const struct soc_button_info *button_info;
37
+ int (*check)(struct device *dev);
3038 };
3139
3240 /*
....@@ -41,22 +49,83 @@
4149 };
4250
4351 /*
52
+ * Some 2-in-1s which use the soc_button_array driver have this ugly issue in
53
+ * their DSDT where the _LID method modifies the irq-type settings of the GPIOs
54
+ * used for the power and home buttons. The intend of this AML code is to
55
+ * disable these buttons when the lid is closed.
56
+ * The AML does this by directly poking the GPIO controllers registers. This is
57
+ * problematic because when re-enabling the irq, which happens whenever _LID
58
+ * gets called with the lid open (e.g. on boot and on resume), it sets the
59
+ * irq-type to IRQ_TYPE_LEVEL_LOW. Where as the gpio-keys driver programs the
60
+ * type to, and expects it to be, IRQ_TYPE_EDGE_BOTH.
61
+ * To work around this we don't set gpio_keys_button.gpio on these 2-in-1s,
62
+ * instead we get the irq for the GPIO ourselves, configure it as
63
+ * IRQ_TYPE_LEVEL_LOW (to match how the _LID AML code configures it) and pass
64
+ * the irq in gpio_keys_button.irq. Below is a list of affected devices.
65
+ */
66
+static const struct dmi_system_id dmi_use_low_level_irq[] = {
67
+ {
68
+ /*
69
+ * Acer Switch 10 SW5-012. _LID method messes with home- and
70
+ * power-button GPIO IRQ settings. When (re-)enabling the irq
71
+ * it ors in its own flags without clearing the previous set
72
+ * ones, leading to an irq-type of IRQ_TYPE_LEVEL_LOW |
73
+ * IRQ_TYPE_LEVEL_HIGH causing a continuous interrupt storm.
74
+ */
75
+ .matches = {
76
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
77
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"),
78
+ },
79
+ },
80
+ {
81
+ /* Acer Switch V 10 SW5-017, same issue as Acer Switch 10 SW5-012. */
82
+ .matches = {
83
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
84
+ DMI_MATCH(DMI_PRODUCT_NAME, "SW5-017"),
85
+ },
86
+ },
87
+ {
88
+ /*
89
+ * Acer One S1003. _LID method messes with power-button GPIO
90
+ * IRQ settings, leading to a non working power-button.
91
+ */
92
+ .matches = {
93
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
94
+ DMI_MATCH(DMI_PRODUCT_NAME, "One S1003"),
95
+ },
96
+ },
97
+ {
98
+ /*
99
+ * Lenovo Yoga Tab2 1051F/1051L, something messes with the home-button
100
+ * IRQ settings, leading to a non working home-button.
101
+ */
102
+ .matches = {
103
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
104
+ DMI_MATCH(DMI_PRODUCT_NAME, "60073"),
105
+ DMI_MATCH(DMI_PRODUCT_VERSION, "1051"),
106
+ },
107
+ },
108
+ {} /* Terminating entry */
109
+};
110
+
111
+/*
44112 * Get the Nth GPIO number from the ACPI object.
45113 */
46
-static int soc_button_lookup_gpio(struct device *dev, int acpi_index)
114
+static int soc_button_lookup_gpio(struct device *dev, int acpi_index,
115
+ int *gpio_ret, int *irq_ret)
47116 {
48117 struct gpio_desc *desc;
49
- int gpio;
50118
51119 desc = gpiod_get_index(dev, NULL, acpi_index, GPIOD_ASIS);
52120 if (IS_ERR(desc))
53121 return PTR_ERR(desc);
54122
55
- gpio = desc_to_gpio(desc);
123
+ *gpio_ret = desc_to_gpio(desc);
124
+ *irq_ret = gpiod_to_irq(desc);
56125
57126 gpiod_put(desc);
58127
59
- return gpio;
128
+ return 0;
60129 }
61130
62131 static struct platform_device *
....@@ -68,9 +137,8 @@
68137 struct platform_device *pd;
69138 struct gpio_keys_button *gpio_keys;
70139 struct gpio_keys_platform_data *gpio_keys_pdata;
140
+ int error, gpio, irq;
71141 int n_buttons = 0;
72
- int gpio;
73
- int error;
74142
75143 for (info = button_info; info->name; info++)
76144 if (info->autorepeat == autorepeat)
....@@ -90,14 +158,35 @@
90158 if (info->autorepeat != autorepeat)
91159 continue;
92160
93
- gpio = soc_button_lookup_gpio(&pdev->dev, info->acpi_index);
94
- if (!gpio_is_valid(gpio))
161
+ error = soc_button_lookup_gpio(&pdev->dev, info->acpi_index, &gpio, &irq);
162
+ if (error || irq < 0) {
163
+ /*
164
+ * Skip GPIO if not present. Note we deliberately
165
+ * ignore -EPROBE_DEFER errors here. On some devices
166
+ * Intel is using so called virtual GPIOs which are not
167
+ * GPIOs at all but some way for AML code to check some
168
+ * random status bits without need a custom opregion.
169
+ * In some cases the resources table we parse points to
170
+ * such a virtual GPIO, since these are not real GPIOs
171
+ * we do not have a driver for these so they will never
172
+ * show up, therefore we ignore -EPROBE_DEFER.
173
+ */
95174 continue;
175
+ }
176
+
177
+ /* See dmi_use_low_level_irq[] comment */
178
+ if (!autorepeat && (use_low_level_irq ||
179
+ dmi_check_system(dmi_use_low_level_irq))) {
180
+ irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW);
181
+ gpio_keys[n_buttons].irq = irq;
182
+ gpio_keys[n_buttons].gpio = -ENOENT;
183
+ } else {
184
+ gpio_keys[n_buttons].gpio = gpio;
185
+ }
96186
97187 gpio_keys[n_buttons].type = info->event_type;
98188 gpio_keys[n_buttons].code = info->event_code;
99
- gpio_keys[n_buttons].gpio = gpio;
100
- gpio_keys[n_buttons].active_low = 1;
189
+ gpio_keys[n_buttons].active_low = info->active_low;
101190 gpio_keys[n_buttons].desc = info->name;
102191 gpio_keys[n_buttons].wakeup = info->wakeup;
103192 /* These devices often use cheap buttons, use 50 ms debounce */
....@@ -114,25 +203,19 @@
114203 gpio_keys_pdata->nbuttons = n_buttons;
115204 gpio_keys_pdata->rep = autorepeat;
116205
117
- pd = platform_device_alloc("gpio-keys", PLATFORM_DEVID_AUTO);
118
- if (!pd) {
119
- error = -ENOMEM;
206
+ pd = platform_device_register_resndata(&pdev->dev, "gpio-keys",
207
+ PLATFORM_DEVID_AUTO, NULL, 0,
208
+ gpio_keys_pdata,
209
+ sizeof(*gpio_keys_pdata));
210
+ error = PTR_ERR_OR_ZERO(pd);
211
+ if (error) {
212
+ dev_err(&pdev->dev,
213
+ "failed registering gpio-keys: %d\n", error);
120214 goto err_free_mem;
121215 }
122216
123
- error = platform_device_add_data(pd, gpio_keys_pdata,
124
- sizeof(*gpio_keys_pdata));
125
- if (error)
126
- goto err_free_pdev;
127
-
128
- error = platform_device_add(pd);
129
- if (error)
130
- goto err_free_pdev;
131
-
132217 return pd;
133218
134
-err_free_pdev:
135
- platform_device_put(pd);
136219 err_free_mem:
137220 devm_kfree(&pdev->dev, gpio_keys_pdata);
138221 return ERR_PTR(error);
....@@ -166,6 +249,7 @@
166249 }
167250
168251 info->event_type = EV_KEY;
252
+ info->active_low = true;
169253 info->acpi_index =
170254 soc_button_get_acpi_object_int(&desc->package.elements[1]);
171255 upage = soc_button_get_acpi_object_int(&desc->package.elements[3]);
....@@ -185,6 +269,10 @@
185269 info->name = "power";
186270 info->event_code = KEY_POWER;
187271 info->wakeup = true;
272
+ } else if (upage == 0x01 && usage == 0xca) {
273
+ info->name = "rotation lock switch";
274
+ info->event_type = EV_SW;
275
+ info->event_code = SW_ROTATE_LOCK;
188276 } else if (upage == 0x07 && usage == 0xe3) {
189277 info->name = "home";
190278 info->event_code = KEY_LEFTMETA;
....@@ -309,23 +397,26 @@
309397 static int soc_button_probe(struct platform_device *pdev)
310398 {
311399 struct device *dev = &pdev->dev;
312
- const struct acpi_device_id *id;
313
- struct soc_button_info *button_info;
400
+ const struct soc_device_data *device_data;
401
+ const struct soc_button_info *button_info;
314402 struct soc_button_data *priv;
315403 struct platform_device *pd;
316404 int i;
317405 int error;
318406
319
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
320
- if (!id)
321
- return -ENODEV;
407
+ device_data = acpi_device_get_match_data(dev);
408
+ if (device_data && device_data->check) {
409
+ error = device_data->check(dev);
410
+ if (error)
411
+ return error;
412
+ }
322413
323
- if (!id->driver_data) {
414
+ if (device_data && device_data->button_info) {
415
+ button_info = device_data->button_info;
416
+ } else {
324417 button_info = soc_button_get_button_info(dev);
325418 if (IS_ERR(button_info))
326419 return PTR_ERR(button_info);
327
- } else {
328
- button_info = (struct soc_button_info *)id->driver_data;
329420 }
330421
331422 error = gpiod_count(dev, NULL);
....@@ -357,7 +448,7 @@
357448 if (!priv->children[0] && !priv->children[1])
358449 return -ENODEV;
359450
360
- if (!id->driver_data)
451
+ if (!device_data || !device_data->button_info)
361452 devm_kfree(dev, button_info);
362453
363454 return 0;
....@@ -368,18 +459,97 @@
368459 * is defined in section 2.8.7.2 of "Windows ACPI Design Guide for SoC
369460 * Platforms"
370461 */
371
-static struct soc_button_info soc_button_PNP0C40[] = {
372
- { "power", 0, EV_KEY, KEY_POWER, false, true },
373
- { "home", 1, EV_KEY, KEY_LEFTMETA, false, true },
374
- { "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false },
375
- { "volume_down", 3, EV_KEY, KEY_VOLUMEDOWN, true, false },
376
- { "rotation_lock", 4, EV_KEY, KEY_ROTATE_LOCK_TOGGLE, false, false },
462
+static const struct soc_button_info soc_button_PNP0C40[] = {
463
+ { "power", 0, EV_KEY, KEY_POWER, false, true, true },
464
+ { "home", 1, EV_KEY, KEY_LEFTMETA, false, true, true },
465
+ { "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false, true },
466
+ { "volume_down", 3, EV_KEY, KEY_VOLUMEDOWN, true, false, true },
467
+ { "rotation_lock", 4, EV_KEY, KEY_ROTATE_LOCK_TOGGLE, false, false, true },
377468 { }
378469 };
379470
471
+static const struct soc_device_data soc_device_PNP0C40 = {
472
+ .button_info = soc_button_PNP0C40,
473
+};
474
+
475
+static const struct soc_button_info soc_button_INT33D3[] = {
476
+ { "tablet_mode", 0, EV_SW, SW_TABLET_MODE, false, false, false },
477
+ { }
478
+};
479
+
480
+static const struct soc_device_data soc_device_INT33D3 = {
481
+ .button_info = soc_button_INT33D3,
482
+};
483
+
484
+/*
485
+ * Special device check for Surface Book 2 and Surface Pro (2017).
486
+ * Both, the Surface Pro 4 (surfacepro3_button.c) and the above mentioned
487
+ * devices use MSHW0040 for power and volume buttons, however the way they
488
+ * have to be addressed differs. Make sure that we only load this drivers
489
+ * for the correct devices by checking the OEM Platform Revision provided by
490
+ * the _DSM method.
491
+ */
492
+#define MSHW0040_DSM_REVISION 0x01
493
+#define MSHW0040_DSM_GET_OMPR 0x02 // get OEM Platform Revision
494
+static const guid_t MSHW0040_DSM_UUID =
495
+ GUID_INIT(0x6fd05c69, 0xcde3, 0x49f4, 0x95, 0xed, 0xab, 0x16, 0x65,
496
+ 0x49, 0x80, 0x35);
497
+
498
+static int soc_device_check_MSHW0040(struct device *dev)
499
+{
500
+ acpi_handle handle = ACPI_HANDLE(dev);
501
+ union acpi_object *result;
502
+ u64 oem_platform_rev = 0; // valid revisions are nonzero
503
+
504
+ // get OEM platform revision
505
+ result = acpi_evaluate_dsm_typed(handle, &MSHW0040_DSM_UUID,
506
+ MSHW0040_DSM_REVISION,
507
+ MSHW0040_DSM_GET_OMPR, NULL,
508
+ ACPI_TYPE_INTEGER);
509
+
510
+ if (result) {
511
+ oem_platform_rev = result->integer.value;
512
+ ACPI_FREE(result);
513
+ }
514
+
515
+ /*
516
+ * If the revision is zero here, the _DSM evaluation has failed. This
517
+ * indicates that we have a Pro 4 or Book 1 and this driver should not
518
+ * be used.
519
+ */
520
+ if (oem_platform_rev == 0)
521
+ return -ENODEV;
522
+
523
+ dev_dbg(dev, "OEM Platform Revision %llu\n", oem_platform_rev);
524
+
525
+ return 0;
526
+}
527
+
528
+/*
529
+ * Button infos for Microsoft Surface Book 2 and Surface Pro (2017).
530
+ * Obtained from DSDT/testing.
531
+ */
532
+static const struct soc_button_info soc_button_MSHW0040[] = {
533
+ { "power", 0, EV_KEY, KEY_POWER, false, true, true },
534
+ { "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false, true },
535
+ { "volume_down", 4, EV_KEY, KEY_VOLUMEDOWN, true, false, true },
536
+ { }
537
+};
538
+
539
+static const struct soc_device_data soc_device_MSHW0040 = {
540
+ .button_info = soc_button_MSHW0040,
541
+ .check = soc_device_check_MSHW0040,
542
+};
543
+
380544 static const struct acpi_device_id soc_button_acpi_match[] = {
381
- { "PNP0C40", (unsigned long)soc_button_PNP0C40 },
545
+ { "PNP0C40", (unsigned long)&soc_device_PNP0C40 },
546
+ { "INT33D3", (unsigned long)&soc_device_INT33D3 },
547
+ { "ID9001", (unsigned long)&soc_device_INT33D3 },
382548 { "ACPI0011", 0 },
549
+
550
+ /* Microsoft Surface Devices (5th and 6th generation) */
551
+ { "MSHW0040", (unsigned long)&soc_device_MSHW0040 },
552
+
383553 { }
384554 };
385555