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/input.h>
  17#include <linux/i2c.h>
  18#include <linux/slab.h>
  19#include <linux/delay.h>
  20#include <linux/bitops.h>
  21#include <linux/interrupt.h>
  22#include <linux/i2c/mpr121_touchkey.h>
  23
  24/* Register definitions */
  25#define ELE_TOUCH_STATUS_0_ADDR 0x0
  26#define ELE_TOUCH_STATUS_1_ADDR 0X1
  27#define MHD_RISING_ADDR         0x2b
  28#define NHD_RISING_ADDR         0x2c
  29#define NCL_RISING_ADDR         0x2d
  30#define FDL_RISING_ADDR         0x2e
  31#define MHD_FALLING_ADDR        0x2f
  32#define NHD_FALLING_ADDR        0x30
  33#define NCL_FALLING_ADDR        0x31
  34#define FDL_FALLING_ADDR        0x32
  35#define ELE0_TOUCH_THRESHOLD_ADDR       0x41
  36#define ELE0_RELEASE_THRESHOLD_ADDR     0x42
  37#define AFE_CONF_ADDR                   0x5c
  38#define FILTER_CONF_ADDR                0x5d
  39
  40/*
  41 * ELECTRODE_CONF_ADDR: This register configures the number of
  42 * enabled capacitance sensing inputs and its run/suspend mode.
  43 */
  44#define ELECTRODE_CONF_ADDR             0x5e
  45#define ELECTRODE_CONF_QUICK_CHARGE     0x80
  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                 0x08
  53#define RELEASE_THRESHOLD               0x05
  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[] = {
  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 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, eleconf;
 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
 167        /*
 168         * Quick charge bit will let the capacitive charge to ready
 169         * state quickly, or the buttons may not function after system
 170         * boot.
 171         */
 172        eleconf = mpr121->keycount | ELECTRODE_CONF_QUICK_CHARGE;
 173        ret |= i2c_smbus_write_byte_data(client, ELECTRODE_CONF_ADDR,
 174                                         eleconf);
 175        if (ret != 0)
 176                goto err_i2c_write;
 177
 178        dev_dbg(&client->dev, "set up with %x keys.\n", mpr121->keycount);
 179
 180        return 0;
 181
 182err_i2c_write:
 183        dev_err(&client->dev, "i2c write error: %d\n", ret);
 184        return ret;
 185}
 186
 187static int mpr_touchkey_probe(struct i2c_client *client,
 188                              const struct i2c_device_id *id)
 189{
 190        const struct mpr121_platform_data *pdata =
 191                        dev_get_platdata(&client->dev);
 192        struct mpr121_touchkey *mpr121;
 193        struct input_dev *input_dev;
 194        int error;
 195        int i;
 196
 197        if (!pdata) {
 198                dev_err(&client->dev, "no platform data defined\n");
 199                return -EINVAL;
 200        }
 201
 202        if (!pdata->keymap || !pdata->keymap_size) {
 203                dev_err(&client->dev, "missing keymap data\n");
 204                return -EINVAL;
 205        }
 206
 207        if (pdata->keymap_size > MPR121_MAX_KEY_COUNT) {
 208                dev_err(&client->dev, "too many keys defined\n");
 209                return -EINVAL;
 210        }
 211
 212        if (!client->irq) {
 213                dev_err(&client->dev, "irq number should not be zero\n");
 214                return -EINVAL;
 215        }
 216
 217        mpr121 = devm_kzalloc(&client->dev, sizeof(*mpr121),
 218                              GFP_KERNEL);
 219        if (!mpr121)
 220                return -ENOMEM;
 221
 222        input_dev = devm_input_allocate_device(&client->dev);
 223        if (!input_dev)
 224                return -ENOMEM;
 225
 226        mpr121->client = client;
 227        mpr121->input_dev = input_dev;
 228        mpr121->keycount = pdata->keymap_size;
 229
 230        input_dev->name = "Freescale MPR121 Touchkey";
 231        input_dev->id.bustype = BUS_I2C;
 232        input_dev->dev.parent = &client->dev;
 233        input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
 234
 235        input_dev->keycode = mpr121->keycodes;
 236        input_dev->keycodesize = sizeof(mpr121->keycodes[0]);
 237        input_dev->keycodemax = mpr121->keycount;
 238
 239        for (i = 0; i < pdata->keymap_size; i++) {
 240                input_set_capability(input_dev, EV_KEY, pdata->keymap[i]);
 241                mpr121->keycodes[i] = pdata->keymap[i];
 242        }
 243
 244        error = mpr121_phys_init(pdata, mpr121, client);
 245        if (error) {
 246                dev_err(&client->dev, "Failed to init register\n");
 247                return error;
 248        }
 249
 250        error = devm_request_threaded_irq(&client->dev, client->irq, NULL,
 251                                     mpr_touchkey_interrupt,
 252                                     IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 253                                     client->dev.driver->name, mpr121);
 254        if (error) {
 255                dev_err(&client->dev, "Failed to register interrupt\n");
 256                return error;
 257        }
 258
 259        error = input_register_device(input_dev);
 260        if (error)
 261                return error;
 262
 263        i2c_set_clientdata(client, mpr121);
 264        device_init_wakeup(&client->dev, pdata->wakeup);
 265
 266        return 0;
 267}
 268
 269#ifdef CONFIG_PM_SLEEP
 270static int mpr_suspend(struct device *dev)
 271{
 272        struct i2c_client *client = to_i2c_client(dev);
 273
 274        if (device_may_wakeup(&client->dev))
 275                enable_irq_wake(client->irq);
 276
 277        i2c_smbus_write_byte_data(client, ELECTRODE_CONF_ADDR, 0x00);
 278
 279        return 0;
 280}
 281
 282static int mpr_resume(struct device *dev)
 283{
 284        struct i2c_client *client = to_i2c_client(dev);
 285        struct mpr121_touchkey *mpr121 = i2c_get_clientdata(client);
 286
 287        if (device_may_wakeup(&client->dev))
 288                disable_irq_wake(client->irq);
 289
 290        i2c_smbus_write_byte_data(client, ELECTRODE_CONF_ADDR,
 291                                  mpr121->keycount);
 292
 293        return 0;
 294}
 295#endif
 296
 297static SIMPLE_DEV_PM_OPS(mpr121_touchkey_pm_ops, mpr_suspend, mpr_resume);
 298
 299static const struct i2c_device_id mpr121_id[] = {
 300        { "mpr121_touchkey", 0 },
 301        { }
 302};
 303MODULE_DEVICE_TABLE(i2c, mpr121_id);
 304
 305static struct i2c_driver mpr_touchkey_driver = {
 306        .driver = {
 307                .name   = "mpr121",
 308                .pm     = &mpr121_touchkey_pm_ops,
 309        },
 310        .id_table       = mpr121_id,
 311        .probe          = mpr_touchkey_probe,
 312};
 313
 314module_i2c_driver(mpr_touchkey_driver);
 315
 316MODULE_LICENSE("GPL");
 317MODULE_AUTHOR("Zhang Jiejing <jiejing.zhang@freescale.com>");
 318MODULE_DESCRIPTION("Touch Key driver for Freescale MPR121 Chip");
 319