summaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorGwendal Grignou <gwendal@chromium.org>2017-01-30 18:47:22 -0500
committerBenson Leung <bleung@chromium.org>2018-05-23 14:56:45 -0400
commitb418f74170d7e066bad802e8563cabdb1b6032c6 (patch)
tree1cffc92b0d868b6aa741037004f3b8ee874bddd4 /drivers/platform
parentb410b1226620b6c959f1e9c87529acd058e90caf (diff)
platform: chrome: Add Tablet Switch ACPI driver
Add a kernel driver for GOOG0006, an ACPI driver reporting an event when the tablet switch status changes. On an ACPI based convertible chromebook check evtest display tablet mode switch changes: Available devices: .. /dev/input/event3: Tablet Mode Switch .. Testing ... (interrupt to exit) Event: time 1484879712.604360, type 5 (EV_SW), code 1 (SW_TABLET_MODE), value 1 Event: time 1484879712.604360, -------------- SYN_REPORT ------------ Event: time 1484879715.132228, type 5 (EV_SW), code 1 (SW_TABLET_MODE), value 0 Event: time 1484879715.132228, -------------- SYN_REPORT ------------ ... Check state is updated at resume time when different from suspend time. Signed-off-by: Gwendal Grignou <gwendal@chromium.org> Signed-off-by: Benson Leung <bleung@chromium.org>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/chrome/Kconfig10
-rw-r--r--drivers/platform/chrome/Makefile1
-rw-r--r--drivers/platform/chrome/chromeos_tbmc.c128
3 files changed, 139 insertions, 0 deletions
diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index e728a96cabfd..57aabe6e94a3 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -38,6 +38,16 @@ config CHROMEOS_PSTORE
38 If you have a supported Chromebook, choose Y or M here. 38 If you have a supported Chromebook, choose Y or M here.
39 The module will be called chromeos_pstore. 39 The module will be called chromeos_pstore.
40 40
41config CHROMEOS_TBMC
42 tristate "ChromeOS Tablet Switch Controller"
43 depends on ACPI
44 help
45 This option adds a driver for the tablet switch on
46 select Chrome OS systems.
47
48 To compile this driver as a module, choose M here: the
49 module will be called chromeos_tbmc.
50
41config CROS_EC_CTL 51config CROS_EC_CTL
42 tristate 52 tristate
43 53
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index ff3b369911f0..e44c37a63fa9 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -2,6 +2,7 @@
2 2
3obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o 3obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o
4obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o 4obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o
5obj-$(CONFIG_CHROMEOS_TBMC) += chromeos_tbmc.o
5cros_ec_ctl-objs := cros_ec_sysfs.o cros_ec_lightbar.o \ 6cros_ec_ctl-objs := cros_ec_sysfs.o cros_ec_lightbar.o \
6 cros_ec_vbc.o cros_ec_debugfs.o 7 cros_ec_vbc.o cros_ec_debugfs.o
7obj-$(CONFIG_CROS_EC_CTL) += cros_ec_ctl.o 8obj-$(CONFIG_CROS_EC_CTL) += cros_ec_ctl.o
diff --git a/drivers/platform/chrome/chromeos_tbmc.c b/drivers/platform/chrome/chromeos_tbmc.c
new file mode 100644
index 000000000000..c87e53319dae
--- /dev/null
+++ b/drivers/platform/chrome/chromeos_tbmc.c
@@ -0,0 +1,128 @@
1/*
2 * chromeos_tbmc - Driver to detect Tablet Mode for ChromeOS convertible.
3 *
4 * Copyright 2017 Google, Inc
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * On Chromebook using ACPI, this device listens for notification
16 * from GOOG0006 and issue method TBMC to retrieve the status.
17 *
18 * GOOG0006 issues the notification when it receives EC_HOST_EVENT_MODE_CHANGE
19 * from the EC.
20 * Method TBMC reads EC_ACPI_MEM_DEVICE_ORIENTATION byte from the shared
21 * memory region.
22 */
23
24#include <linux/acpi.h>
25#include <linux/input.h>
26#include <linux/io.h>
27#include <linux/module.h>
28#include <linux/printk.h>
29
30#define DRV_NAME "chromeos_tbmc"
31#define ACPI_DRV_NAME "GOOG0006"
32
33static int chromeos_tbmc_query_switch(struct acpi_device *adev,
34 struct input_dev *idev)
35{
36 unsigned long long state;
37 acpi_status status;
38
39 status = acpi_evaluate_integer(adev->handle, "TBMC", NULL, &state);
40 if (ACPI_FAILURE(status))
41 return -ENODEV;
42
43 /* input layer checks if event is redundant */
44 input_report_switch(idev, SW_TABLET_MODE, state);
45 input_sync(idev);
46
47 return 0;
48}
49
50static __maybe_unused int chromeos_tbmc_resume(struct device *dev)
51{
52 struct acpi_device *adev = to_acpi_device(dev);
53
54 return chromeos_tbmc_query_switch(adev, adev->driver_data);
55}
56
57static void chromeos_tbmc_notify(struct acpi_device *adev, u32 event)
58{
59 switch (event) {
60 case 0x80:
61 chromeos_tbmc_query_switch(adev, adev->driver_data);
62 break;
63 default:
64 dev_err(&adev->dev, "Unexpected event: 0x%08X\n", event);
65 }
66}
67
68static int chromeos_tbmc_open(struct input_dev *idev)
69{
70 struct acpi_device *adev = input_get_drvdata(idev);
71
72 return chromeos_tbmc_query_switch(adev, idev);
73}
74
75static int chromeos_tbmc_add(struct acpi_device *adev)
76{
77 struct input_dev *idev;
78 struct device *dev = &adev->dev;
79 int ret;
80
81 idev = devm_input_allocate_device(dev);
82 if (!idev)
83 return -ENOMEM;
84
85 idev->name = "Tablet Mode Switch";
86 idev->phys = acpi_device_hid(adev);
87
88 idev->id.bustype = BUS_HOST;
89 idev->id.version = 1;
90 idev->id.product = 0;
91 idev->open = chromeos_tbmc_open;
92
93 input_set_drvdata(idev, adev);
94 adev->driver_data = idev;
95
96 input_set_capability(idev, EV_SW, SW_TABLET_MODE);
97 ret = input_register_device(idev);
98 if (ret) {
99 dev_err(dev, "cannot register input device\n");
100 return ret;
101 }
102 return 0;
103}
104
105static const struct acpi_device_id chromeos_tbmc_acpi_device_ids[] = {
106 { ACPI_DRV_NAME, 0 },
107 { }
108};
109MODULE_DEVICE_TABLE(acpi, chromeos_tbmc_acpi_device_ids);
110
111static const SIMPLE_DEV_PM_OPS(chromeos_tbmc_pm_ops, NULL,
112 chromeos_tbmc_resume);
113
114static struct acpi_driver chromeos_tbmc_driver = {
115 .name = DRV_NAME,
116 .class = DRV_NAME,
117 .ids = chromeos_tbmc_acpi_device_ids,
118 .ops = {
119 .add = chromeos_tbmc_add,
120 .notify = chromeos_tbmc_notify,
121 },
122 .drv.pm = &chromeos_tbmc_pm_ops,
123};
124
125module_acpi_driver(chromeos_tbmc_driver);
126
127MODULE_LICENSE("GPL v2");
128MODULE_DESCRIPTION("ChromeOS ACPI tablet switch driver");