linux/drivers/input/misc/cma3000_d0x.c
<<
>>
Prefs
   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#include <linux/module.h>
  27
  28#include "cma3000_d0x.h"
  29
  30#define CMA3000_WHOAMI      0x00
  31#define CMA3000_REVID       0x01
  32#define CMA3000_CTRL        0x02
  33#define CMA3000_STATUS      0x03
  34#define CMA3000_RSTR        0x04
  35#define CMA3000_INTSTATUS   0x05
  36#define CMA3000_DOUTX       0x06
  37#define CMA3000_DOUTY       0x07
  38#define CMA3000_DOUTZ       0x08
  39#define CMA3000_MDTHR       0x09
  40#define CMA3000_MDFFTMR     0x0A
  41#define CMA3000_FFTHR       0x0B
  42
  43#define CMA3000_RANGE2G    (1 << 7)
  44#define CMA3000_RANGE8G    (0 << 7)
  45#define CMA3000_BUSI2C     (0 << 4)
  46#define CMA3000_MODEMASK   (7 << 1)
  47#define CMA3000_GRANGEMASK (1 << 7)
  48
  49#define CMA3000_STATUS_PERR    1
  50#define CMA3000_INTSTATUS_FFDET (1 << 2)
  51
  52/* Settling time delay in ms */
  53#define CMA3000_SETDELAY    30
  54
  55/* Delay for clearing interrupt in us */
  56#define CMA3000_INTDELAY    44
  57
  58
  59/*
  60 * Bit weights in mg for bit 0, other bits need
  61 * multiply factor 2^n. Eight bit is the sign bit.
  62 */
  63#define BIT_TO_2G  18
  64#define BIT_TO_8G  71
  65
  66struct cma3000_accl_data {
  67        const struct cma3000_bus_ops *bus_ops;
  68        const struct cma3000_platform_data *pdata;
  69
  70        struct device *dev;
  71        struct input_dev *input_dev;
  72
  73        int bit_to_mg;
  74        int irq;
  75
  76        int g_range;
  77        u8 mode;
  78
  79        struct mutex mutex;
  80        bool opened;
  81        bool suspended;
  82};
  83
  84#define CMA3000_READ(data, reg, msg) \
  85        (data->bus_ops->read(data->dev, reg, msg))
  86#define CMA3000_SET(data, reg, val, msg) \
  87        ((data)->bus_ops->write(data->dev, reg, val, msg))
  88
  89/*
  90 * Conversion for each of the eight modes to g, depending
  91 * on G range i.e 2G or 8G. Some modes always operate in
  92 * 8G.
  93 */
  94
  95static int mode_to_mg[8][2] = {
  96        { 0, 0 },
  97        { BIT_TO_8G, BIT_TO_2G },
  98        { BIT_TO_8G, BIT_TO_2G },
  99        { BIT_TO_8G, BIT_TO_8G },
 100        { BIT_TO_8G, BIT_TO_8G },
 101        { BIT_TO_8G, BIT_TO_2G },
 102        { BIT_TO_8G, BIT_TO_2G },
 103        { 0, 0},
 104};
 105
 106static void decode_mg(struct cma3000_accl_data *data, int *datax,
 107                                int *datay, int *dataz)
 108{
 109        /* Data in 2's complement, convert to mg */
 110        *datax = ((s8)*datax) * data->bit_to_mg;
 111        *datay = ((s8)*datay) * data->bit_to_mg;
 112        *dataz = ((s8)*dataz) * data->bit_to_mg;
 113}
 114
 115static irqreturn_t cma3000_thread_irq(int irq, void *dev_id)
 116{
 117        struct cma3000_accl_data *data = dev_id;
 118        int datax, datay, dataz, intr_status;
 119        u8 ctrl, mode, range;
 120
 121        intr_status = CMA3000_READ(data, CMA3000_INTSTATUS, "interrupt status");
 122        if (intr_status < 0)
 123                return IRQ_NONE;
 124
 125        /* Check if free fall is detected, report immediately */
 126        if (intr_status & CMA3000_INTSTATUS_FFDET) {
 127                input_report_abs(data->input_dev, ABS_MISC, 1);
 128                input_sync(data->input_dev);
 129        } else {
 130                input_report_abs(data->input_dev, ABS_MISC, 0);
 131        }
 132
 133        datax = CMA3000_READ(data, CMA3000_DOUTX, "X");
 134        datay = CMA3000_READ(data, CMA3000_DOUTY, "Y");
 135        dataz = CMA3000_READ(data, CMA3000_DOUTZ, "Z");
 136
 137        ctrl = CMA3000_READ(data, CMA3000_CTRL, "ctrl");
 138        mode = (ctrl & CMA3000_MODEMASK) >> 1;
 139        range = (ctrl & CMA3000_GRANGEMASK) >> 7;
 140
 141        data->bit_to_mg = mode_to_mg[mode][range];
 142
 143        /* Interrupt not for this device */
 144        if (data->bit_to_mg == 0)
 145                return IRQ_NONE;
 146
 147        /* Decode register values to milli g */
 148        decode_mg(data, &datax, &datay, &dataz);
 149
 150        input_report_abs(data->input_dev, ABS_X, datax);
 151        input_report_abs(data->input_dev, ABS_Y, datay);
 152        input_report_abs(data->input_dev, ABS_Z, dataz);
 153        input_sync(data->input_dev);
 154
 155        return IRQ_HANDLED;
 156}
 157
 158static int cma3000_reset(struct cma3000_accl_data *data)
 159{
 160        int val;
 161
 162        /* Reset sequence */
 163        CMA3000_SET(data, CMA3000_RSTR, 0x02, "Reset");
 164        CMA3000_SET(data, CMA3000_RSTR, 0x0A, "Reset");
 165        CMA3000_SET(data, CMA3000_RSTR, 0x04, "Reset");
 166
 167        /* Settling time delay */
 168        mdelay(10);
 169
 170        val = CMA3000_READ(data, CMA3000_STATUS, "Status");
 171        if (val < 0) {
 172                dev_err(data->dev, "Reset failed\n");
 173                return val;
 174        }
 175
 176        if (val & CMA3000_STATUS_PERR) {
 177                dev_err(data->dev, "Parity Error\n");
 178                return -EIO;
 179        }
 180
 181        return 0;
 182}
 183
 184static int cma3000_poweron(struct cma3000_accl_data *data)
 185{
 186        const struct cma3000_platform_data *pdata = data->pdata;
 187        u8 ctrl = 0;
 188        int ret;
 189
 190        if (data->g_range == CMARANGE_2G) {
 191                ctrl = (data->mode << 1) | CMA3000_RANGE2G;
 192        } else if (data->g_range == CMARANGE_8G) {
 193                ctrl = (data->mode << 1) | CMA3000_RANGE8G;
 194        } else {
 195                dev_info(data->dev,
 196                         "Invalid G range specified, assuming 8G\n");
 197                ctrl = (data->mode << 1) | CMA3000_RANGE8G;
 198        }
 199
 200        ctrl |= data->bus_ops->ctrl_mod;
 201
 202        CMA3000_SET(data, CMA3000_MDTHR, pdata->mdthr,
 203                    "Motion Detect Threshold");
 204        CMA3000_SET(data, CMA3000_MDFFTMR, pdata->mdfftmr,
 205                    "Time register");
 206        CMA3000_SET(data, CMA3000_FFTHR, pdata->ffthr,
 207                    "Free fall threshold");
 208        ret = CMA3000_SET(data, CMA3000_CTRL, ctrl, "Mode setting");
 209        if (ret < 0)
 210                return -EIO;
 211
 212        msleep(CMA3000_SETDELAY);
 213
 214        return 0;
 215}
 216
 217static int cma3000_poweroff(struct cma3000_accl_data *data)
 218{
 219        int ret;
 220
 221        ret = CMA3000_SET(data, CMA3000_CTRL, CMAMODE_POFF, "Mode setting");
 222        msleep(CMA3000_SETDELAY);
 223
 224        return ret;
 225}
 226
 227static int cma3000_open(struct input_dev *input_dev)
 228{
 229        struct cma3000_accl_data *data = input_get_drvdata(input_dev);
 230
 231        mutex_lock(&data->mutex);
 232
 233        if (!data->suspended)
 234                cma3000_poweron(data);
 235
 236        data->opened = true;
 237
 238        mutex_unlock(&data->mutex);
 239
 240        return 0;
 241}
 242
 243static void cma3000_close(struct input_dev *input_dev)
 244{
 245        struct cma3000_accl_data *data = input_get_drvdata(input_dev);
 246
 247        mutex_lock(&data->mutex);
 248
 249        if (!data->suspended)
 250                cma3000_poweroff(data);
 251
 252        data->opened = false;
 253
 254        mutex_unlock(&data->mutex);
 255}
 256
 257void cma3000_suspend(struct cma3000_accl_data *data)
 258{
 259        mutex_lock(&data->mutex);
 260
 261        if (!data->suspended && data->opened)
 262                cma3000_poweroff(data);
 263
 264        data->suspended = true;
 265
 266        mutex_unlock(&data->mutex);
 267}
 268EXPORT_SYMBOL(cma3000_suspend);
 269
 270
 271void cma3000_resume(struct cma3000_accl_data *data)
 272{
 273        mutex_lock(&data->mutex);
 274
 275        if (data->suspended && data->opened)
 276                cma3000_poweron(data);
 277
 278        data->suspended = false;
 279
 280        mutex_unlock(&data->mutex);
 281}
 282EXPORT_SYMBOL(cma3000_resume);
 283
 284struct cma3000_accl_data *cma3000_init(struct device *dev, int irq,
 285                                       const struct cma3000_bus_ops *bops)
 286{
 287        const struct cma3000_platform_data *pdata = dev_get_platdata(dev);
 288        struct cma3000_accl_data *data;
 289        struct input_dev *input_dev;
 290        int rev;
 291        int error;
 292
 293        if (!pdata) {
 294                dev_err(dev, "platform data not found\n");
 295                error = -EINVAL;
 296                goto err_out;
 297        }
 298
 299
 300        /* if no IRQ return error */
 301        if (irq == 0) {
 302                error = -EINVAL;
 303                goto err_out;
 304        }
 305
 306        data = kzalloc(sizeof(struct cma3000_accl_data), GFP_KERNEL);
 307        input_dev = input_allocate_device();
 308        if (!data || !input_dev) {
 309                error = -ENOMEM;
 310                goto err_free_mem;
 311        }
 312
 313        data->dev = dev;
 314        data->input_dev = input_dev;
 315        data->bus_ops = bops;
 316        data->pdata = pdata;
 317        data->irq = irq;
 318        mutex_init(&data->mutex);
 319
 320        data->mode = pdata->mode;
 321        if (data->mode > CMAMODE_POFF) {
 322                data->mode = CMAMODE_MOTDET;
 323                dev_warn(dev,
 324                         "Invalid mode specified, assuming Motion Detect\n");
 325        }
 326
 327        data->g_range = pdata->g_range;
 328        if (data->g_range != CMARANGE_2G && data->g_range != CMARANGE_8G) {
 329                dev_info(dev,
 330                         "Invalid G range specified, assuming 8G\n");
 331                data->g_range = CMARANGE_8G;
 332        }
 333
 334        input_dev->name = "cma3000-accelerometer";
 335        input_dev->id.bustype = bops->bustype;
 336        input_dev->open = cma3000_open;
 337        input_dev->close = cma3000_close;
 338
 339         __set_bit(EV_ABS, input_dev->evbit);
 340
 341        input_set_abs_params(input_dev, ABS_X,
 342                        -data->g_range, data->g_range, pdata->fuzz_x, 0);
 343        input_set_abs_params(input_dev, ABS_Y,
 344                        -data->g_range, data->g_range, pdata->fuzz_y, 0);
 345        input_set_abs_params(input_dev, ABS_Z,
 346                        -data->g_range, data->g_range, pdata->fuzz_z, 0);
 347        input_set_abs_params(input_dev, ABS_MISC, 0, 1, 0, 0);
 348
 349        input_set_drvdata(input_dev, data);
 350
 351        error = cma3000_reset(data);
 352        if (error)
 353                goto err_free_mem;
 354
 355        rev = CMA3000_READ(data, CMA3000_REVID, "Revid");
 356        if (rev < 0) {
 357                error = rev;
 358                goto err_free_mem;
 359        }
 360
 361        pr_info("CMA3000 Accelerometer: Revision %x\n", rev);
 362
 363        error = request_threaded_irq(irq, NULL, cma3000_thread_irq,
 364                                     pdata->irqflags | IRQF_ONESHOT,
 365                                     "cma3000_d0x", data);
 366        if (error) {
 367                dev_err(dev, "request_threaded_irq failed\n");
 368                goto err_free_mem;
 369        }
 370
 371        error = input_register_device(data->input_dev);
 372        if (error) {
 373                dev_err(dev, "Unable to register input device\n");
 374                goto err_free_irq;
 375        }
 376
 377        return data;
 378
 379err_free_irq:
 380        free_irq(irq, data);
 381err_free_mem:
 382        input_free_device(input_dev);
 383        kfree(data);
 384err_out:
 385        return ERR_PTR(error);
 386}
 387EXPORT_SYMBOL(cma3000_init);
 388
 389void cma3000_exit(struct cma3000_accl_data *data)
 390{
 391        free_irq(data->irq, data);
 392        input_unregister_device(data->input_dev);
 393        kfree(data);
 394}
 395EXPORT_SYMBOL(cma3000_exit);
 396
 397MODULE_DESCRIPTION("CMA3000-D0x Accelerometer Driver");
 398MODULE_LICENSE("GPL");
 399MODULE_AUTHOR("Hemanth V <hemanthv@ti.com>");
 400