linux/drivers/input/keyboard/qt2160.c
<<
>>
Prefs
   1/*
   2 *  qt2160.c - Atmel AT42QT2160 Touch Sense Controller
   3 *
   4 *  Copyright (C) 2009 Raphael Derosso Pereira <raphaelpereira@gmail.com>
   5 *
   6 *  This program is free software; you can redistribute it and/or modify
   7 *  it under the terms of the GNU General Public License as published by
   8 *  the Free Software Foundation; either version 2 of the License, or
   9 *  (at your option) any later version.
  10 *
  11 *  This program is distributed in the hope that it will be useful,
  12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *  GNU General Public License for more details.
  15 *
  16 *  You should have received a copy of the GNU General Public License
  17 *  along with this program; if not, write to the Free Software
  18 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19 */
  20
  21#include <linux/kernel.h>
  22#include <linux/init.h>
  23#include <linux/module.h>
  24#include <linux/slab.h>
  25#include <linux/jiffies.h>
  26#include <linux/i2c.h>
  27#include <linux/irq.h>
  28#include <linux/interrupt.h>
  29#include <linux/input.h>
  30
  31#define QT2160_VALID_CHIPID  0x11
  32
  33#define QT2160_CMD_CHIPID     0
  34#define QT2160_CMD_CODEVER    1
  35#define QT2160_CMD_GSTAT      2
  36#define QT2160_CMD_KEYS3      3
  37#define QT2160_CMD_KEYS4      4
  38#define QT2160_CMD_SLIDE      5
  39#define QT2160_CMD_GPIOS      6
  40#define QT2160_CMD_SUBVER     7
  41#define QT2160_CMD_CALIBRATE  10
  42
  43#define QT2160_CYCLE_INTERVAL   (2*HZ)
  44
  45static unsigned char qt2160_key2code[] = {
  46        KEY_0, KEY_1, KEY_2, KEY_3,
  47        KEY_4, KEY_5, KEY_6, KEY_7,
  48        KEY_8, KEY_9, KEY_A, KEY_B,
  49        KEY_C, KEY_D, KEY_E, KEY_F,
  50};
  51
  52struct qt2160_data {
  53        struct i2c_client *client;
  54        struct input_dev *input;
  55        struct delayed_work dwork;
  56        spinlock_t lock;        /* Protects canceling/rescheduling of dwork */
  57        unsigned short keycodes[ARRAY_SIZE(qt2160_key2code)];
  58        u16 key_matrix;
  59};
  60
  61static int qt2160_read_block(struct i2c_client *client,
  62                             u8 inireg, u8 *buffer, unsigned int count)
  63{
  64        int error, idx = 0;
  65
  66        /*
  67         * Can't use SMBus block data read. Check for I2C functionality to speed
  68         * things up whenever possible. Otherwise we will be forced to read
  69         * sequentially.
  70         */
  71        if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C))     {
  72
  73                error = i2c_smbus_write_byte(client, inireg + idx);
  74                if (error) {
  75                        dev_err(&client->dev,
  76                                "couldn't send request. Returned %d\n", error);
  77                        return error;
  78                }
  79
  80                error = i2c_master_recv(client, buffer, count);
  81                if (error != count) {
  82                        dev_err(&client->dev,
  83                                "couldn't read registers. Returned %d bytes\n", error);
  84                        return error;
  85                }
  86        } else {
  87
  88                while (count--) {
  89                        int data;
  90
  91                        error = i2c_smbus_write_byte(client, inireg + idx);
  92                        if (error) {
  93                                dev_err(&client->dev,
  94                                        "couldn't send request. Returned %d\n", error);
  95                                return error;
  96                        }
  97
  98                        data = i2c_smbus_read_byte(client);
  99                        if (data < 0) {
 100                                dev_err(&client->dev,
 101                                        "couldn't read register. Returned %d\n", data);
 102                                return data;
 103                        }
 104
 105                        buffer[idx++] = data;
 106                }
 107        }
 108
 109        return 0;
 110}
 111
 112static int qt2160_get_key_matrix(struct qt2160_data *qt2160)
 113{
 114        struct i2c_client *client = qt2160->client;
 115        struct input_dev *input = qt2160->input;
 116        u8 regs[6];
 117        u16 old_matrix, new_matrix;
 118        int ret, i, mask;
 119
 120        dev_dbg(&client->dev, "requesting keys...\n");
 121
 122        /*
 123         * Read all registers from General Status Register
 124         * to GPIOs register
 125         */
 126        ret = qt2160_read_block(client, QT2160_CMD_GSTAT, regs, 6);
 127        if (ret) {
 128                dev_err(&client->dev,
 129                        "could not perform chip read.\n");
 130                return ret;
 131        }
 132
 133        old_matrix = qt2160->key_matrix;
 134        qt2160->key_matrix = new_matrix = (regs[2] << 8) | regs[1];
 135
 136        mask = 0x01;
 137        for (i = 0; i < 16; ++i, mask <<= 1) {
 138                int keyval = new_matrix & mask;
 139
 140                if ((old_matrix & mask) != keyval) {
 141                        input_report_key(input, qt2160->keycodes[i], keyval);
 142                        dev_dbg(&client->dev, "key %d %s\n",
 143                                i, keyval ? "pressed" : "released");
 144                }
 145        }
 146
 147        input_sync(input);
 148
 149        return 0;
 150}
 151
 152static irqreturn_t qt2160_irq(int irq, void *_qt2160)
 153{
 154        struct qt2160_data *qt2160 = _qt2160;
 155        unsigned long flags;
 156
 157        spin_lock_irqsave(&qt2160->lock, flags);
 158
 159        mod_delayed_work(system_wq, &qt2160->dwork, 0);
 160
 161        spin_unlock_irqrestore(&qt2160->lock, flags);
 162
 163        return IRQ_HANDLED;
 164}
 165
 166static void qt2160_schedule_read(struct qt2160_data *qt2160)
 167{
 168        spin_lock_irq(&qt2160->lock);
 169        schedule_delayed_work(&qt2160->dwork, QT2160_CYCLE_INTERVAL);
 170        spin_unlock_irq(&qt2160->lock);
 171}
 172
 173static void qt2160_worker(struct work_struct *work)
 174{
 175        struct qt2160_data *qt2160 =
 176                container_of(work, struct qt2160_data, dwork.work);
 177
 178        dev_dbg(&qt2160->client->dev, "worker\n");
 179
 180        qt2160_get_key_matrix(qt2160);
 181
 182        /* Avoid device lock up by checking every so often */
 183        qt2160_schedule_read(qt2160);
 184}
 185
 186static int __devinit qt2160_read(struct i2c_client *client, u8 reg)
 187{
 188        int ret;
 189
 190        ret = i2c_smbus_write_byte(client, reg);
 191        if (ret) {
 192                dev_err(&client->dev,
 193                        "couldn't send request. Returned %d\n", ret);
 194                return ret;
 195        }
 196
 197        ret = i2c_smbus_read_byte(client);
 198        if (ret < 0) {
 199                dev_err(&client->dev,
 200                        "couldn't read register. Returned %d\n", ret);
 201                return ret;
 202        }
 203
 204        return ret;
 205}
 206
 207static int __devinit qt2160_write(struct i2c_client *client, u8 reg, u8 data)
 208{
 209        int error;
 210
 211        error = i2c_smbus_write_byte(client, reg);
 212        if (error) {
 213                dev_err(&client->dev,
 214                        "couldn't send request. Returned %d\n", error);
 215                return error;
 216        }
 217
 218        error = i2c_smbus_write_byte(client, data);
 219        if (error) {
 220                dev_err(&client->dev,
 221                        "couldn't write data. Returned %d\n", error);
 222                return error;
 223        }
 224
 225        return error;
 226}
 227
 228
 229static bool __devinit qt2160_identify(struct i2c_client *client)
 230{
 231        int id, ver, rev;
 232
 233        /* Read Chid ID to check if chip is valid */
 234        id = qt2160_read(client, QT2160_CMD_CHIPID);
 235        if (id != QT2160_VALID_CHIPID) {
 236                dev_err(&client->dev, "ID %d not supported\n", id);
 237                return false;
 238        }
 239
 240        /* Read chip firmware version */
 241        ver = qt2160_read(client, QT2160_CMD_CODEVER);
 242        if (ver < 0) {
 243                dev_err(&client->dev, "could not get firmware version\n");
 244                return false;
 245        }
 246
 247        /* Read chip firmware revision */
 248        rev = qt2160_read(client, QT2160_CMD_SUBVER);
 249        if (rev < 0) {
 250                dev_err(&client->dev, "could not get firmware revision\n");
 251                return false;
 252        }
 253
 254        dev_info(&client->dev, "AT42QT2160 firmware version %d.%d.%d\n",
 255                        ver >> 4, ver & 0xf, rev);
 256
 257        return true;
 258}
 259
 260static int __devinit qt2160_probe(struct i2c_client *client,
 261                                  const struct i2c_device_id *id)
 262{
 263        struct qt2160_data *qt2160;
 264        struct input_dev *input;
 265        int i;
 266        int error;
 267
 268        /* Check functionality */
 269        error = i2c_check_functionality(client->adapter,
 270                        I2C_FUNC_SMBUS_BYTE);
 271        if (!error) {
 272                dev_err(&client->dev, "%s adapter not supported\n",
 273                                dev_driver_string(&client->adapter->dev));
 274                return -ENODEV;
 275        }
 276
 277        if (!qt2160_identify(client))
 278                return -ENODEV;
 279
 280        /* Chip is valid and active. Allocate structure */
 281        qt2160 = kzalloc(sizeof(struct qt2160_data), GFP_KERNEL);
 282        input = input_allocate_device();
 283        if (!qt2160 || !input) {
 284                dev_err(&client->dev, "insufficient memory\n");
 285                error = -ENOMEM;
 286                goto err_free_mem;
 287        }
 288
 289        qt2160->client = client;
 290        qt2160->input = input;
 291        INIT_DELAYED_WORK(&qt2160->dwork, qt2160_worker);
 292        spin_lock_init(&qt2160->lock);
 293
 294        input->name = "AT42QT2160 Touch Sense Keyboard";
 295        input->id.bustype = BUS_I2C;
 296
 297        input->keycode = qt2160->keycodes;
 298        input->keycodesize = sizeof(qt2160->keycodes[0]);
 299        input->keycodemax = ARRAY_SIZE(qt2160_key2code);
 300
 301        __set_bit(EV_KEY, input->evbit);
 302        __clear_bit(EV_REP, input->evbit);
 303        for (i = 0; i < ARRAY_SIZE(qt2160_key2code); i++) {
 304                qt2160->keycodes[i] = qt2160_key2code[i];
 305                __set_bit(qt2160_key2code[i], input->keybit);
 306        }
 307        __clear_bit(KEY_RESERVED, input->keybit);
 308
 309        /* Calibrate device */
 310        error = qt2160_write(client, QT2160_CMD_CALIBRATE, 1);
 311        if (error) {
 312                dev_err(&client->dev, "failed to calibrate device\n");
 313                goto err_free_mem;
 314        }
 315
 316        if (client->irq) {
 317                error = request_irq(client->irq, qt2160_irq,
 318                                    IRQF_TRIGGER_FALLING, "qt2160", qt2160);
 319                if (error) {
 320                        dev_err(&client->dev,
 321                                "failed to allocate irq %d\n", client->irq);
 322                        goto err_free_mem;
 323                }
 324        }
 325
 326        error = input_register_device(qt2160->input);
 327        if (error) {
 328                dev_err(&client->dev,
 329                        "Failed to register input device\n");
 330                goto err_free_irq;
 331        }
 332
 333        i2c_set_clientdata(client, qt2160);
 334        qt2160_schedule_read(qt2160);
 335
 336        return 0;
 337
 338err_free_irq:
 339        if (client->irq)
 340                free_irq(client->irq, qt2160);
 341err_free_mem:
 342        input_free_device(input);
 343        kfree(qt2160);
 344        return error;
 345}
 346
 347static int __devexit qt2160_remove(struct i2c_client *client)
 348{
 349        struct qt2160_data *qt2160 = i2c_get_clientdata(client);
 350
 351        /* Release IRQ so no queue will be scheduled */
 352        if (client->irq)
 353                free_irq(client->irq, qt2160);
 354
 355        cancel_delayed_work_sync(&qt2160->dwork);
 356
 357        input_unregister_device(qt2160->input);
 358        kfree(qt2160);
 359
 360        return 0;
 361}
 362
 363static const struct i2c_device_id qt2160_idtable[] = {
 364        { "qt2160", 0, },
 365        { }
 366};
 367
 368MODULE_DEVICE_TABLE(i2c, qt2160_idtable);
 369
 370static struct i2c_driver qt2160_driver = {
 371        .driver = {
 372                .name   = "qt2160",
 373                .owner  = THIS_MODULE,
 374        },
 375
 376        .id_table       = qt2160_idtable,
 377        .probe          = qt2160_probe,
 378        .remove         = __devexit_p(qt2160_remove),
 379};
 380
 381module_i2c_driver(qt2160_driver);
 382
 383MODULE_AUTHOR("Raphael Derosso Pereira <raphaelpereira@gmail.com>");
 384MODULE_DESCRIPTION("Driver for AT42QT2160 Touch Sensor");
 385MODULE_LICENSE("GPL");
 386