diff options
| author | Hemanth V <hemanthv@ti.com> | 2010-12-01 02:03:54 -0500 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-12-01 02:05:21 -0500 |
| commit | b029ffafe89cf4b97cf39e0225a5205cbbf9e02f (patch) | |
| tree | 3f5b9074c4b9b4cf35d930f057ed6a73559e1e0c /drivers/input | |
| parent | 33e808c383477e821163f133c2e3e671879c28b6 (diff) | |
Input: add CMA3000 accelerometer driver
Add support for CMA3000 Tri-axis accelerometer, which supports Motion
detect, Measurement and Free fall modes. CMA3000 supports both I2C/SPI
bus for communication, currently the driver supports I2C based
communication.
Signed-off-by: Hemanth V <hemanthv@ti.com>
Reviewed-by: Jonathan Cameron <jic23@cam.ac.uk>
Reviewed-by: Sergio Aguirre <saaguirre@ti.com>
Reviewed-by: Shubhrajyoti <Shubhrajyoti@ti.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
| -rw-r--r-- | drivers/input/misc/Kconfig | 24 | ||||
| -rw-r--r-- | drivers/input/misc/Makefile | 2 | ||||
| -rw-r--r-- | drivers/input/misc/cma3000_d0x.c | 398 | ||||
| -rw-r--r-- | drivers/input/misc/cma3000_d0x.h | 42 | ||||
| -rw-r--r-- | drivers/input/misc/cma3000_d0x_i2c.c | 141 |
5 files changed, 607 insertions, 0 deletions
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index b99b8cbde02f..f0d90172a65f 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
| @@ -448,4 +448,28 @@ config INPUT_ADXL34X_SPI | |||
| 448 | To compile this driver as a module, choose M here: the | 448 | To compile this driver as a module, choose M here: the |
| 449 | module will be called adxl34x-spi. | 449 | module will be called adxl34x-spi. |
| 450 | 450 | ||
| 451 | config INPUT_CMA3000 | ||
| 452 | tristate "VTI CMA3000 Tri-axis accelerometer" | ||
| 453 | help | ||
| 454 | Say Y here if you want to use VTI CMA3000_D0x Accelerometer | ||
| 455 | driver | ||
| 456 | |||
| 457 | This driver currently only supports I2C interface to the | ||
| 458 | controller. Also select the I2C method. | ||
| 459 | |||
| 460 | If unsure, say N | ||
| 461 | |||
| 462 | To compile this driver as a module, choose M here: the | ||
| 463 | module will be called cma3000_d0x. | ||
| 464 | |||
| 465 | config INPUT_CMA3000_I2C | ||
| 466 | tristate "Support I2C bus connection" | ||
| 467 | depends on INPUT_CMA3000 && I2C | ||
| 468 | help | ||
| 469 | Say Y here if you want to use VTI CMA3000_D0x Accelerometer | ||
| 470 | through I2C interface. | ||
| 471 | |||
| 472 | To compile this driver as a module, choose M here: the | ||
| 473 | module will be called cma3000_d0x_i2c. | ||
| 474 | |||
| 451 | endif | 475 | endif |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 1fe1f6c8b737..35bcfe46555e 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
| @@ -18,6 +18,8 @@ obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o | |||
| 18 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o | 18 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o |
| 19 | obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o | 19 | obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o |
| 20 | obj-$(CONFIG_INPUT_CM109) += cm109.o | 20 | obj-$(CONFIG_INPUT_CM109) += cm109.o |
| 21 | obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o | ||
| 22 | obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o | ||
| 21 | obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o | 23 | obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o |
| 22 | obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o | 24 | obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o |
| 23 | obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o | 25 | obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o |
diff --git a/drivers/input/misc/cma3000_d0x.c b/drivers/input/misc/cma3000_d0x.c new file mode 100644 index 000000000000..1633b6342267 --- /dev/null +++ b/drivers/input/misc/cma3000_d0x.c | |||
| @@ -0,0 +1,398 @@ | |||
| 1 | /* | ||
| 2 | * VTI CMA3000_D0x Accelerometer driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Texas Instruments | ||
| 5 | * Author: Hemanth V <hemanthv@ti.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License version 2 as published by | ||
| 9 | * the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 14 | * more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along with | ||
| 17 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/types.h> | ||
| 21 | #include <linux/interrupt.h> | ||
| 22 | #include <linux/delay.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <linux/input.h> | ||
| 25 | #include <linux/input/cma3000.h> | ||
| 26 | |||
| 27 | #include "cma3000_d0x.h" | ||
| 28 | |||
| 29 | #define CMA3000_WHOAMI 0x00 | ||
| 30 | #define CMA3000_REVID 0x01 | ||
| 31 | #define CMA3000_CTRL 0x02 | ||
| 32 | #define CMA3000_STATUS 0x03 | ||
| 33 | #define CMA3000_RSTR 0x04 | ||
| 34 | #define CMA3000_INTSTATUS 0x05 | ||
| 35 | #define CMA3000_DOUTX 0x06 | ||
| 36 | #define CMA3000_DOUTY 0x07 | ||
| 37 | #define CMA3000_DOUTZ 0x08 | ||
| 38 | #define CMA3000_MDTHR 0x09 | ||
| 39 | #define CMA3000_MDFFTMR 0x0A | ||
| 40 | #define CMA3000_FFTHR 0x0B | ||
| 41 | |||
| 42 | #define CMA3000_RANGE2G (1 << 7) | ||
| 43 | #define CMA3000_RANGE8G (0 << 7) | ||
| 44 | #define CMA3000_BUSI2C (0 << 4) | ||
| 45 | #define CMA3000_MODEMASK (7 << 1) | ||
| 46 | #define CMA3000_GRANGEMASK (1 << 7) | ||
| 47 | |||
| 48 | #define CMA3000_STATUS_PERR 1 | ||
| 49 | #define CMA3000_INTSTATUS_FFDET (1 << 2) | ||
| 50 | |||
| 51 | /* Settling time delay in ms */ | ||
| 52 | #define CMA3000_SETDELAY 30 | ||
| 53 | |||
| 54 | /* Delay for clearing interrupt in us */ | ||
| 55 | #define CMA3000_INTDELAY 44 | ||
| 56 | |||
| 57 | |||
| 58 | /* | ||
| 59 | * Bit weights in mg for bit 0, other bits need | ||
| 60 | * multipy factor 2^n. Eight bit is the sign bit. | ||
| 61 | */ | ||
| 62 | #define BIT_TO_2G 18 | ||
| 63 | #define BIT_TO_8G 71 | ||
| 64 | |||
| 65 | struct cma3000_accl_data { | ||
| 66 | const struct cma3000_bus_ops *bus_ops; | ||
| 67 | const struct cma3000_platform_data *pdata; | ||
| 68 | |||
| 69 | struct device *dev; | ||
| 70 | struct input_dev *input_dev; | ||
| 71 | |||
| 72 | int bit_to_mg; | ||
| 73 | int irq; | ||
| 74 | |||
| 75 | int g_range; | ||
| 76 | u8 mode; | ||
| 77 | |||
| 78 | struct mutex mutex; | ||
| 79 | bool opened; | ||
| 80 | bool suspended; | ||
| 81 | }; | ||
| 82 | |||
| 83 | #define CMA3000_READ(data, reg, msg) \ | ||
| 84 | (data->bus_ops->read(data->dev, reg, msg)) | ||
| 85 | #define CMA3000_SET(data, reg, val, msg) \ | ||
| 86 | ((data)->bus_ops->write(data->dev, reg, val, msg)) | ||
| 87 | |||
| 88 | /* | ||
| 89 | * Conversion for each of the eight modes to g, depending | ||
| 90 | * on G range i.e 2G or 8G. Some modes always operate in | ||
| 91 | * 8G. | ||
| 92 | */ | ||
| 93 | |||
| 94 | static int mode_to_mg[8][2] = { | ||
| 95 | { 0, 0 }, | ||
| 96 | { BIT_TO_8G, BIT_TO_2G }, | ||
| 97 | { BIT_TO_8G, BIT_TO_2G }, | ||
| 98 | { BIT_TO_8G, BIT_TO_8G }, | ||
| 99 | { BIT_TO_8G, BIT_TO_8G }, | ||
| 100 | { BIT_TO_8G, BIT_TO_2G }, | ||
| 101 | { BIT_TO_8G, BIT_TO_2G }, | ||
| 102 | { 0, 0}, | ||
| 103 | }; | ||
| 104 | |||
| 105 | static void decode_mg(struct cma3000_accl_data *data, int *datax, | ||
| 106 | int *datay, int *dataz) | ||
| 107 | { | ||
| 108 | /* Data in 2's complement, convert to mg */ | ||
| 109 | *datax = ((s8)*datax) * data->bit_to_mg; | ||
| 110 | *datay = ((s8)*datay) * data->bit_to_mg; | ||
| 111 | *dataz = ((s8)*dataz) * data->bit_to_mg; | ||
| 112 | } | ||
| 113 | |||
| 114 | static irqreturn_t cma3000_thread_irq(int irq, void *dev_id) | ||
| 115 | { | ||
| 116 | struct cma3000_accl_data *data = dev_id; | ||
| 117 | int datax, datay, dataz; | ||
| 118 | u8 ctrl, mode, range, intr_status; | ||
| 119 | |||
| 120 | intr_status = CMA3000_READ(data, CMA3000_INTSTATUS, "interrupt status"); | ||
| 121 | if (intr_status < 0) | ||
| 122 | return IRQ_NONE; | ||
| 123 | |||
| 124 | /* Check if free fall is detected, report immediately */ | ||
| 125 | if (intr_status & CMA3000_INTSTATUS_FFDET) { | ||
| 126 | input_report_abs(data->input_dev, ABS_MISC, 1); | ||
| 127 | input_sync(data->input_dev); | ||
| 128 | } else { | ||
| 129 | input_report_abs(data->input_dev, ABS_MISC, 0); | ||
| 130 | } | ||
| 131 | |||
| 132 | datax = CMA3000_READ(data, CMA3000_DOUTX, "X"); | ||
| 133 | datay = CMA3000_READ(data, CMA3000_DOUTY, "Y"); | ||
| 134 | dataz = CMA3000_READ(data, CMA3000_DOUTZ, "Z"); | ||
| 135 | |||
| 136 | ctrl = CMA3000_READ(data, CMA3000_CTRL, "ctrl"); | ||
| 137 | mode = (ctrl & CMA3000_MODEMASK) >> 1; | ||
| 138 | |||
