0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/acpi.h>
0016 #include <linux/input.h>
0017 #include <linux/io.h>
0018 #include <linux/module.h>
0019 #include <linux/printk.h>
0020
0021 #define DRV_NAME "chromeos_tbmc"
0022 #define ACPI_DRV_NAME "GOOG0006"
0023
0024 static int chromeos_tbmc_query_switch(struct acpi_device *adev,
0025 struct input_dev *idev)
0026 {
0027 unsigned long long state;
0028 acpi_status status;
0029
0030 status = acpi_evaluate_integer(adev->handle, "TBMC", NULL, &state);
0031 if (ACPI_FAILURE(status))
0032 return -ENODEV;
0033
0034
0035 input_report_switch(idev, SW_TABLET_MODE, state);
0036 input_sync(idev);
0037
0038 return 0;
0039 }
0040
0041 static __maybe_unused int chromeos_tbmc_resume(struct device *dev)
0042 {
0043 struct acpi_device *adev = to_acpi_device(dev);
0044
0045 return chromeos_tbmc_query_switch(adev, adev->driver_data);
0046 }
0047
0048 static void chromeos_tbmc_notify(struct acpi_device *adev, u32 event)
0049 {
0050 acpi_pm_wakeup_event(&adev->dev);
0051 switch (event) {
0052 case 0x80:
0053 chromeos_tbmc_query_switch(adev, adev->driver_data);
0054 break;
0055 default:
0056 dev_err(&adev->dev, "Unexpected event: 0x%08X\n", event);
0057 }
0058 }
0059
0060 static int chromeos_tbmc_open(struct input_dev *idev)
0061 {
0062 struct acpi_device *adev = input_get_drvdata(idev);
0063
0064 return chromeos_tbmc_query_switch(adev, idev);
0065 }
0066
0067 static int chromeos_tbmc_add(struct acpi_device *adev)
0068 {
0069 struct input_dev *idev;
0070 struct device *dev = &adev->dev;
0071 int ret;
0072
0073 idev = devm_input_allocate_device(dev);
0074 if (!idev)
0075 return -ENOMEM;
0076
0077 idev->name = "Tablet Mode Switch";
0078 idev->phys = acpi_device_hid(adev);
0079
0080 idev->id.bustype = BUS_HOST;
0081 idev->id.version = 1;
0082 idev->id.product = 0;
0083 idev->open = chromeos_tbmc_open;
0084
0085 input_set_drvdata(idev, adev);
0086 adev->driver_data = idev;
0087
0088 input_set_capability(idev, EV_SW, SW_TABLET_MODE);
0089 ret = input_register_device(idev);
0090 if (ret) {
0091 dev_err(dev, "cannot register input device\n");
0092 return ret;
0093 }
0094 device_init_wakeup(dev, true);
0095 return 0;
0096 }
0097
0098 static const struct acpi_device_id chromeos_tbmc_acpi_device_ids[] = {
0099 { ACPI_DRV_NAME, 0 },
0100 { }
0101 };
0102 MODULE_DEVICE_TABLE(acpi, chromeos_tbmc_acpi_device_ids);
0103
0104 static SIMPLE_DEV_PM_OPS(chromeos_tbmc_pm_ops, NULL,
0105 chromeos_tbmc_resume);
0106
0107 static struct acpi_driver chromeos_tbmc_driver = {
0108 .name = DRV_NAME,
0109 .class = DRV_NAME,
0110 .ids = chromeos_tbmc_acpi_device_ids,
0111 .ops = {
0112 .add = chromeos_tbmc_add,
0113 .notify = chromeos_tbmc_notify,
0114 },
0115 .drv.pm = &chromeos_tbmc_pm_ops,
0116 };
0117
0118 module_acpi_driver(chromeos_tbmc_driver);
0119
0120 MODULE_LICENSE("GPL v2");
0121 MODULE_DESCRIPTION("ChromeOS ACPI tablet switch driver");