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
  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
  65struct 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
  94static 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
 105static 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
 114static 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        range = (ctrl & CMA3000_GRANGEMASK) >> 7;
 139
 140        data->bit_to_mg = mode_to_mg[mode][range];
 141
 142        /* Interrupt not for this device */
 143        if (data->bit_to_mg == 0)
 144                return IRQ_NONE;
 145
 146        /* Decode register values to milli g */
 147        decode_mg(data, &datax, &datay, &dataz);
 148
 149        input_report_abs(data->input_dev, ABS_X, datax);
 150        input_report_abs(data->input_dev, ABS_Y, datay);
 151        input_report_abs(data->input_dev, ABS_Z, dataz);
 152        input_sync(data->input_dev);
 153
 154        return IRQ_HANDLED;
 155}
 156
 157static int cma3000_reset(struct cma3000_accl_data *data)
 158{
 159        int val;
 160
 161        /* Reset sequence */
 162        CMA3000_SET(data, CMA3000_RSTR, 0x02, "Reset");
 163        CMA3000_SET(data, CMA3000_RSTR, 0x0A, "Reset");
 164        CMA3000_SET(data, CMA3000_RSTR, 0x04, "Reset");
 165
 166        /* Settling time delay */
 167        mdelay(10);
 168
 169        val = CMA3000_READ(data, CMA3000_STATUS, "Status");
 170        if (val < 0) {
 171                dev_err(data->dev, "Reset failed\n");
 172                return val;
 173        }
 174
 175        if (val & CMA3000_STATUS_PERR) {
 176                dev_err(data->dev, "Parity Error\n");
 177                return -EIO;
 178        }
 179
 180        return 0;
 181}
 182
 183static int cma3000_poweron(struct cma3000_accl_data *data)
 184{
 185        const struct cma3000_platform_data *pdata = data->pdata;
 186        u8 ctrl = 0;
 187        int ret;
 188
 189        if (data->g_range == CMARANGE_2G) {
 190                ctrl = (data->mode << 1) | CMA3000_RANGE2G;
 191        } else if (data->g_range == CMARANGE_8G) {
 192                ctrl = (data->mode << 1) | CMA3000_RANGE8G;
 193        } else {
 194                dev_info(data->dev,
 195                         "Invalid G range specified, assuming 8G\n");
 196                ctrl = (data->mode << 1) | CMA3000_RANGE8G;
 197        }
 198
 199        ctrl |= data->bus_ops->ctrl_mod;
 200
 201        CMA3000_SET(data, CMA3000_MDTHR, pdata->mdthr,
 202                    "Motion Detect Threshold");
 203        CMA3000_SET(data, CMA3000_MDFFTMR, pdata->mdfftmr,
 204                    "Time register");
 205        CMA3000_SET(data, CMA3000_FFTHR, pdata->ffthr,
 206                    "Free fall threshold");
 207        ret = CMA3000_SET(data, CMA3000_CTRL, ctrl, "Mode setting");
 208        if (ret < 0)
 209                return -EIO;
 210
 211        msleep(CMA3000_SETDELAY);
 212
 213        return 0;
 214}
 215
 216static int cma3000_poweroff(struct cma3000_accl_data *data)
 217{
 218        int ret;
 219
 220        ret = CMA3000_SET(data, CMA3000_CTRL, CMAMODE_POFF, "Mode setting");
 221        msleep(CMA3000_SETDELAY);
 222
 223        return ret;
 224}
 225
 226static int cma3000_open(struct input_dev *input_dev)
 227{
 228        struct cma3000_accl_data *data = input_get_drvdata(input_dev);
 229
 230        mutex_lock(&data->mutex);
 231
 232        if (!data->suspended)
 233                cma3000_poweron(data);
 234
 235        data->opened = true;
 236
 237        mutex_unlock(&data->mutex);
 238
 239        return 0;
 240}
 241
 242static void cma3000_close(struct input_dev *input_dev)
 243{
 244        struct cma3000_accl_data *data = input_get_drvdata(input_dev);
 245
 246        mutex_lock(&data->mutex);
 247
 248        if (!data->suspended)
 249                cma3000_poweroff(data);
 250
 251        data->opened = false;
 252
 253        mutex_unlock(&data->mutex);
 254}
 255
 256void cma3000_suspend(struct cma3000_accl_data *data)
 257{
 258        mutex_lock(&data->mutex);
 259
 260        if (!data->suspended && data->opened)
 261                cma3000_poweroff(data);
 262
 263        data->suspended = true;
 264
 265        mutex_unlock(&data->mutex);
 266}
 267EXPORT_SYMBOL(cma3000_suspend);
 268
 269
 270void cma3000_resume(struct cma3000_accl_data *data)
 271{
 272        mutex_lock(&data->mutex);
 273
 274        if (data->suspended && data->opened)
 275                cma3000_poweron(data);
 276
 277        data->suspended = false;
 278
 279        mutex_unlock(&data->mutex);
 280}
 281EXPORT_SYMBOL(cma3000_resume);
 282
 283struct cma3000_accl_data *cma3000_init(struct device *dev, int irq,
 284                                       const struct cma3000_bus_ops *bops)
 285{
 286        const struct cma3000_platform_data *pdata = dev->platform_data;
 287        struct cma3000_accl_data *data;
 288        struct input_dev *input_dev;
 289        int rev;
 290        int error;
 291
 292        if (!pdata) {
 293                dev_err(dev, "platform data not found\n");
 294                error = -EINVAL;
 295                goto err_out;
 296        }
 297
 298
 299        /* if no IRQ return error */
 300        if (irq == 0) {
 301                error = -EINVAL;
 302                goto err_out;
 303        }
 304
 305        data = kzalloc(sizeof(struct cma3000_accl_data), GFP_KERNEL);
 306        input_dev = input_allocate_device();
 307        if (!data || !input_dev) {
 308                error = -ENOMEM;
 309                goto err_free_mem;
 310        }
 311
 312        data->dev = dev;
 313        data->input_dev = input_dev;
 314        data->bus_ops = bops;
 315        data->pdata = pdata;
 316        data->irq = irq;
 317        mutex_init(&data->mutex);
 318
 319        data->mode = pdata->mode;
 320        if (data->mode < CMAMODE_DEFAULT || data->mode > CMAMODE_POFF) {
 321                data->mode = CMAMODE_MOTDET;
 322                dev_warn(dev,
 323                         "Invalid mode specified, assuming Motion Detect\n");
 324        }
 325
 326        data->g_range = pdata->g_range;
 327        if (data->g_range != CMARANGE_2G && data->g_range != CMARANGE_8G) {
 328                dev_info(dev,
 329                         "Invalid G range specified, assuming 8G\n");
 330                data->g_range = CMARANGE_8G;
 331        }
 332
 333        input_dev->name = "cma3000-accelerometer";
 334        input_dev->id.bustype = bops->bustype;
 335        input_dev->open = cma3000_open;
 336        input_dev->close = cma3000_close;
 337
 338         __set_bit(EV_ABS, input_dev->evbit);
 339
 340        input_set_abs_params(input_dev, ABS_X,
 341                        -data->g_range, data->g_range, pdata->fuzz_x, 0);
 342        input_set_abs_params(input_dev, ABS_Y,
 343                        -data->g_range, data->g_range, pdata->fuzz_y, 0);
 344        input_set_abs_params(input_dev, ABS_Z,
 345                        -data->g_range, data->g_range, pdata->fuzz_z, 0);
 346        input_set_abs_params(input_dev, ABS_MISC, 0, 1, 0, 0);
 347
 348        input_set_drvdata(input_dev, data);
 349
 350        error = cma3000_reset(data);
 351        if (error)
 352                goto err_free_mem;
 353
 354        rev = CMA3000_READ(data, CMA3000_REVID, "Revid");
 355        if (rev < 0) {
 356                error = rev;
 357                goto err_free_mem;
 358        }
 359
 360        pr_info("CMA3000 Accelerometer: Revision %x\n", rev);
 361
 362        error = request_threaded_irq(irq, NULL, cma3000_thread_irq,
 363                                     pdata->irqflags | IRQF_ONESHOT,
 364                                     "cma3000_d0x", data);
 365        if (error) {
 366                dev_err(dev, "request_threaded_irq failed\n");
 367                goto err_free_mem;
 368        }
 369
 370        error = input_register_device(data->input_dev);
 371        if (error) {
 372                dev_err(dev, "Unable to register input device\n");
 373                goto err_free_irq;
 374        }
 375
 376        return data;
 377
 378err_free_irq:
 379        free_irq(irq, data);
 380err_free_mem:
 381        input_free_device(input_dev);
 382        kfree(data);
 383err_out:
 384        return ERR_PTR(error);
 385}
 386EXPORT_SYMBOL(cma3000_init);
 387
 388void cma3000_exit(struct cma3000_accl_data *data)
 389{
 390        free_irq(data->irq, data);
 391        input_unregister_device(data->input_dev);
 392        kfree(data);
 393}
 394EXPORT_SYMBOL(cma3000_exit);
 395
 396MODULE_DESCRIPTION("CMA3000-D0x Accelerometer Driver");
 397MODULE_LICENSE("GPL");
 398MODULE_AUTHOR("Hemanth V <hemanthv@ti.com>");
 399