linux/drivers/input/keyboard/mpr121_touchkey.c
<<
>>
Prefs
   1/*
   2 * Touchkey driver for Freescale MPR121 Controllor
   3 *
   4 * Copyright (C) 2011 Freescale Semiconductor, Inc.
   5 * Author: Zhang Jiejing <jiejing.zhang@freescale.com>
   6 *
   7 * Based on mcs_touchkey.c
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License version 2 as
  11 * published by the Free Software Foundation.
  12 *
  13 */
  14
  15#include <linux/module.h>
  16#include <linux/init.h>
  17#include <linux/input.h>
  18#include <linux/i2c.h>
  19#include <linux/slab.h>
  20#include <linux/delay.h>
  21#include <linux/bitops.h>
  22#include <linux/interrupt.h>
  23#include <linux/i2c/mpr121_touchkey.h>
  24
  25/* Register definitions */
  26#define ELE_TOUCH_STATUS_0_ADDR 0x0
  27#define ELE_TOUCH_STATUS_1_ADDR 0X1
  28#define MHD_RISING_ADDR         0x2b
  29#define NHD_RISING_ADDR         0x2c
  30#define NCL_RISING_ADDR         0x2d
  31#define FDL_RISING_ADDR         0x2e
  32#define MHD_FALLING_ADDR        0x2f
  33#define NHD_FALLING_ADDR        0x30
  34#define NCL_FALLING_ADDR        0x31
  35#define FDL_FALLING_ADDR        0x32
  36#define ELE0_TOUCH_THRESHOLD_ADDR       0x41
  37#define ELE0_RELEASE_THRESHOLD_ADDR     0x42
  38#define AFE_CONF_ADDR                   0x5c
  39#define FILTER_CONF_ADDR                0x5d
  40
  41/*
  42 * ELECTRODE_CONF_ADDR: This register configures the number of
  43 * enabled capacitance sensing inputs and its run/suspend mode.
  44 */
  45#define ELECTRODE_CONF_ADDR             0x5e
  46#define AUTO_CONFIG_CTRL_ADDR           0x7b
  47#define AUTO_CONFIG_USL_ADDR            0x7d
  48#define AUTO_CONFIG_LSL_ADDR            0x7e
  49#define AUTO_CONFIG_TL_ADDR             0x7f
  50
  51/* Threshold of touch/release trigger */
  52#define TOUCH_THRESHOLD                 0x0f
  53#define RELEASE_THRESHOLD               0x0a
  54/* Masks for touch and release triggers */
  55#define TOUCH_STATUS_MASK               0xfff
  56/* MPR121 has 12 keys */
  57#define MPR121_MAX_KEY_COUNT            12
  58
  59struct mpr121_touchkey {
  60        struct i2c_client       *client;
  61        struct input_dev        *input_dev;
  62        unsigned int            key_val;
  63        unsigned int            statusbits;
  64        unsigned int            keycount;
  65        u16                     keycodes[MPR121_MAX_KEY_COUNT];
  66};
  67
  68struct mpr121_init_register {
  69        int addr;
  70        u8 val;
  71};
  72
  73static const struct mpr121_init_register init_reg_table[] __devinitconst = {
  74        { MHD_RISING_ADDR,      0x1 },
  75        { NHD_RISING_ADDR,      0x1 },
  76        { MHD_FALLING_ADDR,     0x1 },
  77        { NHD_FALLING_ADDR,     0x1 },
  78        { NCL_FALLING_ADDR,     0xff },
  79        { FDL_FALLING_ADDR,     0x02 },
  80        { FILTER_CONF_ADDR,     0x04 },
  81        { AFE_CONF_ADDR,        0x0b },
  82        { AUTO_CONFIG_CTRL_ADDR, 0x0b },
  83};
  84
  85static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
  86{
  87        struct mpr121_touchkey *mpr121 = dev_id;
  88        struct i2c_client *client = mpr121->client;
  89        struct input_dev *input = mpr121->input_dev;
  90        unsigned int key_num, key_val, pressed;
  91        int reg;
  92
  93        reg = i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_1_ADDR);
  94        if (reg < 0) {
  95                dev_err(&client->dev, "i2c read error [%d]\n", reg);
  96                goto out;
  97        }
  98
  99        reg <<= 8;
 100        reg |= i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_0_ADDR);
 101        if (reg < 0) {
 102                dev_err(&client->dev, "i2c read error [%d]\n", reg);
 103                goto out;
 104        }
 105
 106        reg &= TOUCH_STATUS_MASK;
 107        /* use old press bit to figure out which bit changed */
 108        key_num = ffs(reg ^ mpr121->statusbits) - 1;
 109        pressed = reg & (1 << key_num);
 110        mpr121->statusbits = reg;
 111
 112        key_val = mpr121->keycodes[key_num];
 113
 114        input_event(input, EV_MSC, MSC_SCAN, key_num);
 115        input_report_key(input, key_val, pressed);
 116        input_sync(input);
 117
 118        dev_dbg(&client->dev, "key %d %d %s\n", key_num, key_val,
 119                pressed ? "pressed" : "released");
 120
 121out:
 122        return IRQ_HANDLED;
 123}
 124
 125static int __devinit mpr121_phys_init(const struct mpr121_platform_data *pdata,
 126                                      struct mpr121_touchkey *mpr121,
 127                                      struct i2c_client *client)
 128{
 129        const struct mpr121_init_register *reg;
 130        unsigned char usl, lsl, tl;
 131        int i, t, vdd, ret;
 132
 133        /* Set up touch/release threshold for ele0-ele11 */
 134        for (i = 0; i <= MPR121_MAX_KEY_COUNT; i++) {
 135                t = ELE0_TOUCH_THRESHOLD_ADDR + (i * 2);
 136                ret = i2c_smbus_write_byte_data(client, t, TOUCH_THRESHOLD);
 137                if (ret < 0)
 138                        goto err_i2c_write;
 139                ret = i2c_smbus_write_byte_data(client, t + 1,
 140                                                RELEASE_THRESHOLD);
 141                if (ret < 0)
 142                        goto err_i2c_write;
 143        }
 144
 145        /* Set up init register */
 146        for (i = 0; i < ARRAY_SIZE(init_reg_table); i++) {
 147                reg = &init_reg_table[i];
 148                ret = i2c_smbus_write_byte_data(client, reg->addr, reg->val);
 149                if (ret < 0)
 150                        goto err_i2c_write;
 151        }
 152
 153
 154        /*
 155         * Capacitance on sensing input varies and needs to be compensated.
 156         * The internal MPR121-auto-configuration can do this if it's
 157         * registers are set properly (based on pdata->vdd_uv).
 158         */
 159        vdd = pdata->vdd_uv / 1000;
 160        usl = ((vdd - 700) * 256) / vdd;
 161        lsl = (usl * 65) / 100;
 162        tl = (usl * 90) / 100;
 163        ret = i2c_smbus_write_byte_data(client, AUTO_CONFIG_USL_ADDR, usl);
 164        ret |= i2c_smbus_write_byte_data(client, AUTO_CONFIG_LSL_ADDR, lsl);
 165        ret |= i2c_smbus_write_byte_data(client, AUTO_CONFIG_TL_ADDR, tl);
 166        ret |= i2c_smbus_write_byte_data(client, ELECTRODE_CONF_ADDR,
 167                                         mpr121->keycount);
 168        if (ret != 0)
 169                goto err_i2c_write;
 170
 171        dev_dbg(&client->dev, "set up with %x keys.\n", mpr121->keycount);
 172
 173        return 0;
 174
 175err_i2c_write:
 176        dev_err(&client->dev, "i2c write error: %d\n", ret);
 177        return ret;
 178}
 179
 180static int __devinit mpr_touchkey_probe(struct i2c_client *client,
 181                                        const struct i2c_device_id *id)
 182{
 183        const struct mpr121_platform_data *pdata = client->dev.platform_data;
 184        struct mpr121_touchkey *mpr121;
 185        struct input_dev *input_dev;
 186        int error;
 187        int i;
 188
 189        if (!pdata) {
 190                dev_err(&client->dev, "no platform data defined\n");
 191                return -EINVAL;
 192        }
 193
 194        if (!pdata->keymap || !pdata->keymap_size) {
 195                dev_err(&client->dev, "missing keymap data\n");
 196                return -EINVAL;
 197        }
 198
 199        if (pdata->keymap_size > MPR121_MAX_KEY_COUNT) {
 200                dev_err(&client->dev, "too many keys defined\n");
 201                return -EINVAL;
 202        }
 203
 204        if (!client->irq) {
 205                dev_err(&client->dev, "irq number should not be zero\n");
 206                return -EINVAL;
 207        }
 208
 209        mpr121 = kzalloc(sizeof(struct mpr121_touchkey), GFP_KERNEL);
 210        input_dev = input_allocate_device();
 211        if (!mpr121 || !input_dev) {
 212                dev_err(&client->dev, "Failed to allocate memory\n");
 213                error = -ENOMEM;
 214                goto err_free_mem;
 215        }
 216
 217        mpr121->client = client;
 218        mpr121->input_dev = input_dev;
 219        mpr121->keycount = pdata->keymap_size;
 220
 221        input_dev->name = "Freescale MPR121 Touchkey";
 222        input_dev->id.bustype = BUS_I2C;
 223        input_dev->dev.parent = &client->dev;
 224        input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
 225
 226        input_dev->keycode = mpr121->keycodes;
 227        input_dev->keycodesize = sizeof(mpr121->keycodes[0]);
 228        input_dev->keycodemax = mpr121->keycount;
 229
 230        for (i = 0; i < pdata->keymap_size; i++) {
 231                input_set_capability(input_dev, EV_KEY, pdata->keymap[i]);
 232                mpr121->keycodes[i] = pdata->keymap[i];
 233        }
 234
 235        error = mpr121_phys_init(pdata, mpr121, client);
 236        if (error) {
 237                dev_err(&client->dev, "Failed to init register\n");
 238                goto err_free_mem;
 239        }
 240
 241        error = request_threaded_irq(client->irq, NULL,
 242                                     mpr_touchkey_interrupt,
 243                                     IRQF_TRIGGER_FALLING,
 244                                     client->dev.driver->name, mpr121);
 245        if (error) {
 246                dev_err(&client->dev, "Failed to register interrupt\n");
 247                goto err_free_mem;
 248        }
 249
 250        error = input_register_device(input_dev);
 251        if (error)
 252                goto err_free_irq;
 253
 254        i2c_set_clientdata(client, mpr121);
 255        device_init_wakeup(&client->dev, pdata->wakeup);
 256
 257        return 0;
 258
 259err_free_irq:
 260        free_irq(client->irq, mpr121);
 261err_free_mem:
 262        input_free_device(input_dev);
 263        kfree(mpr121);
 264        return error;
 265}
 266
 267static int __devexit mpr_touchkey_remove(struct i2c_client *client)
 268{
 269        struct mpr121_touchkey *mpr121 = i2c_get_clientdata(client);
 270
 271        free_irq(client->irq, mpr121);
 272        input_unregister_device(mpr121->input_dev);
 273        kfree(mpr121);
 274
 275        return 0;
 276}
 277
 278#ifdef CONFIG_PM_SLEEP
 279static int mpr_suspend(struct device *dev)
 280{
 281        struct i2c_client *client = to_i2c_client(dev);
 282
 283        if (device_may_wakeup(&client->dev))
 284                enable_irq_wake(client->irq);
 285
 286        i2c_smbus_write_byte_data(client, ELECTRODE_CONF_ADDR, 0x00);
 287
 288        return 0;
 289}
 290
 291static int mpr_resume(struct device *dev)
 292{
 293        struct i2c_client *client = to_i2c_client(dev);
 294        struct mpr121_touchkey *mpr121 = i2c_get_clientdata(client);
 295
 296        if (device_may_wakeup(&client->dev))
 297                disable_irq_wake(client->irq);
 298
 299        i2c_smbus_write_byte_data(client, ELECTRODE_CONF_ADDR,
 300                                  mpr121->keycount);
 301
 302        return 0;
 303}
 304#endif
 305
 306static SIMPLE_DEV_PM_OPS(mpr121_touchkey_pm_ops, mpr_suspend, mpr_resume);
 307
 308static const struct i2c_device_id mpr121_id[] = {
 309        { "mpr121_touchkey", 0 },
 310        { }
 311};
 312MODULE_DEVICE_TABLE(i2c, mpr121_id);
 313
 314static struct i2c_driver mpr_touchkey_driver = {
 315        .driver = {
 316                .name   = "mpr121",
 317                .owner  = THIS_MODULE,
 318                .pm     = &mpr121_touchkey_pm_ops,
 319        },
 320        .id_table       = mpr121_id,
 321        .probe          = mpr_touchkey_probe,
 322        .remove         = __devexit_p(mpr_touchkey_remove),
 323};
 324
 325static int __init mpr_touchkey_init(void)
 326{
 327        return i2c_add_driver(&mpr_touchkey_driver);
 328}
 329module_init(mpr_touchkey_init);
 330
 331static void __exit mpr_touchkey_exit(void)
 332{
 333        i2c_del_driver(&mpr_touchkey_driver);
 334}
 335module_exit(mpr_touchkey_exit);
 336
 337MODULE_LICENSE("GPL");
 338MODULE_AUTHOR("Zhang Jiejing <jiejing.zhang@freescale.com>");
 339MODULE_DESCRIPTION("Touch Key driver for Freescale MPR121 Chip");
 340