diff options
| author | Benson Leung <bleung@chromium.org> | 2012-10-25 17:21:21 -0400 |
|---|---|---|
| committer | Matthew Garrett <matthew.garrett@nebula.com> | 2013-02-24 17:49:57 -0500 |
| commit | d1381f45ad54e0bb40ef19f99e87187ff3458bdb (patch) | |
| tree | db199e11fc1fb1f41144797aac59f803aea4ba65 /drivers/platform | |
| parent | 16a3d9f5aa1c9e0ecddd48bdfcf44445c9dbb601 (diff) | |
Platform: x86: Add Chrome OS Laptop driver
This adds the chromeos_laptop driver. It supports
the Cypress APA SMBUS touchpad as well as the isl29018 i2c ambient
light sensor on the Samsung Series 5 550 Chromebook.
Signed-off-by: Benson Leung <bleung@chromium.org>
Reviewed-by: Olof Johansson <olof@lixom.net>
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
Diffstat (limited to 'drivers/platform')
| -rw-r--r-- | drivers/platform/x86/Kconfig | 11 | ||||
| -rw-r--r-- | drivers/platform/x86/Makefile | 1 | ||||
| -rw-r--r-- | drivers/platform/x86/chromeos_laptop.c | 205 |
3 files changed, 217 insertions, 0 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 7ab0b2fba503..585db6fa64b8 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
| @@ -79,6 +79,17 @@ config ASUS_LAPTOP | |||
| 79 | 79 | ||
| 80 | If you have an ACPI-compatible ASUS laptop, say Y or M here. | 80 | If you have an ACPI-compatible ASUS laptop, say Y or M here. |
| 81 | 81 | ||
| 82 | config CHROMEOS_LAPTOP | ||
| 83 | tristate "Chrome OS Laptop" | ||
| 84 | depends on I2C | ||
| 85 | depends on DMI | ||
| 86 | ---help--- | ||
| 87 | This driver instantiates i2c and smbus devices such as | ||
| 88 | light sensors and touchpads. | ||
| 89 | |||
| 90 | If you have a supported Chromebook, choose Y or M here. | ||
| 91 | The module will be called chromeos_laptop. | ||
| 92 | |||
| 82 | config DELL_LAPTOP | 93 | config DELL_LAPTOP |
| 83 | tristate "Dell Laptop Extras" | 94 | tristate "Dell Laptop Extras" |
| 84 | depends on X86 | 95 | depends on X86 |
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index bf7e4f935b17..ace2b38942fe 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile | |||
| @@ -50,3 +50,4 @@ obj-$(CONFIG_INTEL_MID_POWER_BUTTON) += intel_mid_powerbtn.o | |||
| 50 | obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o | 50 | obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o |
| 51 | obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o | 51 | obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o |
| 52 | obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o | 52 | obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o |
| 53 | obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o | ||
diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c new file mode 100644 index 000000000000..a8329c3a9d0d --- /dev/null +++ b/drivers/platform/x86/chromeos_laptop.c | |||
| @@ -0,0 +1,205 @@ | |||
| 1 | /* | ||
| 2 | * chromeos_laptop.c - Driver to instantiate Chromebook i2c/smbus devices. | ||
| 3 | * | ||
| 4 | * Author : Benson Leung <bleung@chromium.org> | ||
| 5 | * | ||
| 6 | * Copyright (C) 2012 Google, Inc. | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 21 | * | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/dmi.h> | ||
| 25 | #include <linux/i2c.h> | ||
| 26 | #include <linux/module.h> | ||
| 27 | |||
| 28 | #define CYAPA_TP_I2C_ADDR 0x67 | ||
| 29 | #define ISL_ALS_I2C_ADDR 0x44 | ||
| 30 | |||
| 31 | static struct i2c_client *als; | ||
| 32 | static struct i2c_client *tp; | ||
| 33 | |||
| 34 | const char *i2c_adapter_names[] = { | ||
| 35 | "SMBus I801 adapter", | ||
| 36 | }; | ||
| 37 | |||
| 38 | /* Keep this enum consistent with i2c_adapter_names */ | ||
| 39 | enum i2c_adapter_type { | ||
| 40 | I2C_ADAPTER_SMBUS = 0, | ||
| 41 | }; | ||
| 42 | |||
| 43 | static struct i2c_board_info __initdata cyapa_device = { | ||
| 44 | I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), | ||
| 45 | .flags = I2C_CLIENT_WAKE, | ||
| 46 | }; | ||
| 47 | |||
| 48 | static struct i2c_board_info __initdata isl_als_device = { | ||
| 49 | I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR), | ||
| 50 | }; | ||
| 51 | |||
| 52 | static struct i2c_client __init *__add_probed_i2c_device( | ||
| 53 | const char *name, | ||
| 54 | int bus, | ||
| 55 | struct i2c_board_info *info, | ||
| 56 | const unsigned short *addrs) | ||
| 57 | { | ||
| 58 | const struct dmi_device *dmi_dev; | ||
| 59 | const struct dmi_dev_onboard *dev_data; | ||
| 60 | struct i2c_adapter *adapter; | ||
| 61 | struct i2c_client *client; | ||
| 62 | |||
| 63 | if (bus < 0) | ||
| 64 | return NULL; | ||
| 65 | /* | ||
| 66 | * If a name is specified, look for irq platform information stashed | ||
| 67 | * in DMI_DEV_TYPE_DEV_ONBOARD by the Chrome OS custom system firmware. | ||
| 68 | */ | ||
| 69 | if (name) { | ||
| 70 | dmi_dev = dmi_find_device(DMI_DEV_TYPE_DEV_ONBOARD, name, NULL); | ||
| 71 | if (!dmi_dev) { | ||
| 72 | pr_err("%s failed to dmi find device %s.\n", | ||
| 73 | __func__, | ||
| 74 | name); | ||
| 75 | return NULL; | ||
| 76 | } | ||
| 77 | dev_data = (struct dmi_dev_onboard *)dmi_dev->device_data; | ||
| 78 | if (!dev_data) { | ||
| 79 | pr_err("%s failed to get data from dmi for %s.\n", | ||
| 80 | __func__, name); | ||
| 81 | return NULL; | ||
| 82 | } | ||
| 83 | info->irq = dev_data->instance; | ||
| 84 | } | ||
| 85 | |||
| 86 | adapter = i2c_get_adapter(bus); | ||
| 87 | if (!adapter) { | ||
| 88 | pr_err("%s failed to get i2c adapter %d.\n", __func__, bus); | ||
| 89 | return NULL; | ||
| 90 | } | ||
| 91 | |||
| 92 | /* add the i2c device */ | ||
| 93 | client = i2c_new_probed_device(adapter, info, addrs, NULL); | ||
| 94 | if (!client) | ||
| 95 | pr_err("%s failed to register device %d-%02x\n", | ||
| 96 | __func__, bus, info->addr); | ||
| 97 | else | ||
| 98 | pr_debug("%s added i2c device %d-%02x\n", | ||
| 99 | __func__, bus, info->addr); | ||
| 100 | |||
| 101 | i2c_put_adapter(adapter); | ||
| 102 | return client; | ||
| 103 | } | ||
| 104 | |||
| 105 | static int __init __find_i2c_adap(struct device *dev, void *data) | ||
| 106 | { | ||
| 107 | const char *name = data; | ||
| 108 | static const char *prefix = "i2c-"; | ||
| 109 | struct i2c_adapter *adapter; | ||
| 110 | if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0) | ||
| 111 | return 0; | ||
| 112 | adapter = to_i2c_adapter(dev); | ||
| 113 | return (strncmp(adapter->name, name, strlen(name)) == 0); | ||
| 114 | } | ||
| 115 | |||
| 116 | static int __init find_i2c_adapter_num(enum i2c_adapter_type type) | ||
| 117 | { | ||
| 118 | struct device *dev = NULL; | ||
| 119 | struct i2c_adapter *adapter; | ||
| 120 | const char *name = i2c_adapter_names[type]; | ||
| 121 | /* find the adapter by name */ | ||
| 122 | dev = bus_find_device(&i2c_bus_type, NULL, (void *)name, | ||
| 123 | __find_i2c_adap); | ||
| 124 | if (!dev) { | ||
| 125 | pr_err("%s: i2c adapter %s not found on system.\n", __func__, | ||
| 126 | name); | ||
| 127 | return -ENODEV; | ||
| 128 | } | ||
| 129 | adapter = to_i2c_adapter(dev); | ||
| 130 | return adapter->nr; | ||
| 131 | } | ||
| 132 | |||
| 133 | /* | ||
| 134 | * Probes for a device at a single address, the one provided by | ||
| 135 | * info->addr. | ||
| 136 | * Returns NULL if no device found. | ||
| 137 | */ | ||
| 138 | static struct i2c_client __init *add_smbus_device(const char *name, | ||
| 139 | struct i2c_board_info *info) | ||
| 140 | { | ||
| 141 | const unsigned short addr_list[] = { info->addr, I2C_CLIENT_END }; | ||
| 142 | return __add_probed_i2c_device(name, | ||
| 143 | find_i2c_adapter_num(I2C_ADAPTER_SMBUS), | ||
| 144 | info, | ||
| 145 | addr_list); | ||
| 146 | } | ||
| 147 | |||
| 148 | static int __init setup_lumpy_tp(const struct dmi_system_id *id) | ||
| 149 | { | ||
| 150 | /* add cyapa touchpad on smbus */ | ||
| 151 | tp = add_smbus_device("trackpad", &cyapa_device); | ||
| 152 | return 0; | ||
| 153 | } | ||
