root/drivers/platform/chrome/chromeos_tbmc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. chromeos_tbmc_query_switch
  2. chromeos_tbmc_resume
  3. chromeos_tbmc_notify
  4. chromeos_tbmc_open
  5. chromeos_tbmc_add

   1 // SPDX-License-Identifier: GPL-2.0
   2 // Driver to detect Tablet Mode for ChromeOS convertible.
   3 //
   4 // Copyright (C) 2017 Google, Inc.
   5 // Author: Gwendal Grignou <gwendal@chromium.org>
   6 //
   7 // On Chromebook using ACPI, this device listens for notification
   8 // from GOOG0006 and issue method TBMC to retrieve the status.
   9 //
  10 // GOOG0006 issues the notification when it receives EC_HOST_EVENT_MODE_CHANGE
  11 // from the EC.
  12 // Method TBMC reads EC_ACPI_MEM_DEVICE_ORIENTATION byte from the shared
  13 // memory region.
  14 
  15 #include <linux/acpi.h>
  16 #include <linux/input.h>
  17 #include <linux/io.h>
  18 #include <linux/module.h>
  19 #include <linux/printk.h>
  20 
  21 #define DRV_NAME "chromeos_tbmc"
  22 #define ACPI_DRV_NAME "GOOG0006"
  23 
  24 static int chromeos_tbmc_query_switch(struct acpi_device *adev,
  25                                      struct input_dev *idev)
  26 {
  27         unsigned long long state;
  28         acpi_status status;
  29 
  30         status = acpi_evaluate_integer(adev->handle, "TBMC", NULL, &state);
  31         if (ACPI_FAILURE(status))
  32                 return -ENODEV;
  33 
  34         /* input layer checks if event is redundant */
  35         input_report_switch(idev, SW_TABLET_MODE, state);
  36         input_sync(idev);
  37 
  38         return 0;
  39 }
  40 
  41 static __maybe_unused int chromeos_tbmc_resume(struct device *dev)
  42 {
  43         struct acpi_device *adev = to_acpi_device(dev);
  44 
  45         return chromeos_tbmc_query_switch(adev, adev->driver_data);
  46 }
  47 
  48 static void chromeos_tbmc_notify(struct acpi_device *adev, u32 event)
  49 {
  50         acpi_pm_wakeup_event(&adev->dev);
  51         switch (event) {
  52         case 0x80:
  53                 chromeos_tbmc_query_switch(adev, adev->driver_data);
  54                 break;
  55         default:
  56                 dev_err(&adev->dev, "Unexpected event: 0x%08X\n", event);
  57         }
  58 }
  59 
  60 static int chromeos_tbmc_open(struct input_dev *idev)
  61 {
  62         struct acpi_device *adev = input_get_drvdata(idev);
  63 
  64         return chromeos_tbmc_query_switch(adev, idev);
  65 }
  66 
  67 static int chromeos_tbmc_add(struct acpi_device *adev)
  68 {
  69         struct input_dev *idev;
  70         struct device *dev = &adev->dev;
  71         int ret;
  72 
  73         idev = devm_input_allocate_device(dev);
  74         if (!idev)
  75                 return -ENOMEM;
  76 
  77         idev->name = "Tablet Mode Switch";
  78         idev->phys = acpi_device_hid(adev);
  79 
  80         idev->id.bustype = BUS_HOST;
  81         idev->id.version = 1;
  82         idev->id.product = 0;
  83         idev->open = chromeos_tbmc_open;
  84 
  85         input_set_drvdata(idev, adev);
  86         adev->driver_data = idev;
  87 
  88         input_set_capability(idev, EV_SW, SW_TABLET_MODE);
  89         ret = input_register_device(idev);
  90         if (ret) {
  91                 dev_err(dev, "cannot register input device\n");
  92                 return ret;
  93         }
  94         device_init_wakeup(dev, true);
  95         return 0;
  96 }
  97 
  98 static const struct acpi_device_id chromeos_tbmc_acpi_device_ids[] = {
  99         { ACPI_DRV_NAME, 0 },
 100         { }
 101 };
 102 MODULE_DEVICE_TABLE(acpi, chromeos_tbmc_acpi_device_ids);
 103 
 104 static SIMPLE_DEV_PM_OPS(chromeos_tbmc_pm_ops, NULL,
 105                 chromeos_tbmc_resume);
 106 
 107 static struct acpi_driver chromeos_tbmc_driver = {
 108         .name = DRV_NAME,
 109         .class = DRV_NAME,
 110         .ids = chromeos_tbmc_acpi_device_ids,
 111         .ops = {
 112                 .add = chromeos_tbmc_add,
 113                 .notify = chromeos_tbmc_notify,
 114         },
 115         .drv.pm = &chromeos_tbmc_pm_ops,
 116 };
 117 
 118 module_acpi_driver(chromeos_tbmc_driver);
 119 
 120 MODULE_LICENSE("GPL v2");
 121 MODULE_DESCRIPTION("ChromeOS ACPI tablet switch driver");

/* [<][>][^][v][top][bottom][index][help] */