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/leds.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#define QT2160_CMD_DRIVE_X    70
  43#define QT2160_CMD_PWMEN_X    74
  44#define QT2160_CMD_PWM_DUTY   76
  45
  46#define QT2160_NUM_LEDS_X       8
  47
  48#define QT2160_CYCLE_INTERVAL   (2*HZ)
  49
  50static unsigned char qt2160_key2code[] = {
  51        KEY_0, KEY_1, KEY_2, KEY_3,
  52        KEY_4, KEY_5, KEY_6, KEY_7,
  53        KEY_8, KEY_9, KEY_A, KEY_B,
  54        KEY_C, KEY_D, KEY_E, KEY_F,
  55};
  56
  57#ifdef CONFIG_LEDS_CLASS
  58struct qt2160_led {
  59        struct qt2160_data *qt2160;
  60        struct led_classdev cdev;
  61        struct work_struct work;
  62        char name[32];
  63        int id;
  64        enum led_brightness new_brightness;
  65};
  66#endif
  67
  68struct qt2160_data {
  69        struct i2c_client *client;
  70        struct input_dev *input;
  71        struct delayed_work dwork;
  72        spinlock_t lock;        /* Protects canceling/rescheduling of dwork */
  73        unsigned short keycodes[ARRAY_SIZE(qt2160_key2code)];
  74        u16 key_matrix;
  75#ifdef CONFIG_LEDS_CLASS
  76        struct qt2160_led leds[QT2160_NUM_LEDS_X];
  77        struct mutex led_lock;
  78#endif
  79};
  80
  81static int qt2160_read(struct i2c_client *client, u8 reg);
  82static int qt2160_write(struct i2c_client *client, u8 reg, u8 data);
  83
  84#ifdef CONFIG_LEDS_CLASS
  85
  86static void qt2160_led_work(struct work_struct *work)
  87{
  88        struct qt2160_led *led = container_of(work, struct qt2160_led, work);
  89        struct qt2160_data *qt2160 = led->qt2160;
  90        struct i2c_client *client = qt2160->client;
  91        int value = led->new_brightness;
  92        u32 drive, pwmen;
  93
  94        mutex_lock(&qt2160->led_lock);
  95
  96        drive = qt2160_read(client, QT2160_CMD_DRIVE_X);
  97        pwmen = qt2160_read(client, QT2160_CMD_PWMEN_X);
  98        if (value != LED_OFF) {
  99                drive |= (1 << led->id);
 100                pwmen |= (1 << led->id);
 101
 102        } else {
 103                drive &= ~(1 << led->id);
 104                pwmen &= ~(1 << led->id);
 105        }
 106        qt2160_write(client, QT2160_CMD_DRIVE_X, drive);
 107        qt2160_write(client, QT2160_CMD_PWMEN_X, pwmen);
 108
 109        /*
 110         * Changing this register will change the brightness
 111         * of every LED in the qt2160. It's a HW limitation.
 112         */
 113        if (value != LED_OFF)
 114                qt2160_write(client, QT2160_CMD_PWM_DUTY, value);
 115
 116        mutex_unlock(&qt2160->led_lock);
 117}
 118
 119static void qt2160_led_set(struct led_classdev *cdev,
 120                           enum led_brightness value)
 121{
 122        struct qt2160_led *led = container_of(cdev, struct qt2160_led, cdev);
 123
 124        led->new_brightness = value;
 125        schedule_work(&led->work);
 126}
 127
 128#endif /* CONFIG_LEDS_CLASS */
 129
 130static int qt2160_read_block(struct i2c_client *client,
 131                             u8 inireg, u8 *buffer, unsigned int count)
 132{
 133        int error, idx = 0;
 134
 135        /*
 136         * Can't use SMBus block data read. Check for I2C functionality to speed
 137         * things up whenever possible. Otherwise we will be forced to read
 138         * sequentially.
 139         */
 140        if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C))     {
 141
 142                error = i2c_smbus_write_byte(client, inireg + idx);
 143                if (error) {
 144                        dev_err(&client->dev,
 145                                "couldn't send request. Returned %d\n", error);
 146                        return error;
 147                }
 148
 149                error = i2c_master_recv(client, buffer, count);
 150                if (error != count) {
 151                        dev_err(&client->dev,
 152                                "couldn't read registers. Returned %d bytes\n", error);
 153                        return error;
 154                }
 155        } else {
 156
 157                while (count--) {
 158                        int data;
 159
 160                        error = i2c_smbus_write_byte(client, inireg + idx);
 161                        if (error) {
 162                                dev_err(&client->dev,
 163                                        "couldn't send request. Returned %d\n", error);
 164                                return error;
 165                        }
 166
 167                        data = i2c_smbus_read_byte(client);
 168                        if (data < 0) {
 169                                dev_err(&client->dev,
 170                                        "couldn't read register. Returned %d\n", data);
 171                                return data;
 172                        }
 173
 174                        buffer[idx++] = data;
 175                }
 176        }
 177
 178        return 0;
 179}
 180
 181static int qt2160_get_key_matrix(struct qt2160_data *qt2160)
 182{
 183        struct i2c_client *client = qt2160->client;
 184        struct input_dev *input = qt2160->input;
 185        u8 regs[6];
 186        u16 old_matrix, new_matrix;
 187        int ret, i, mask;
 188
 189        dev_dbg(&client->dev, "requesting keys...\n");
 190
 191        /*
 192         * Read all registers from General Status Register
 193         * to GPIOs register
 194         */
 195        ret = qt2160_read_block(client, QT2160_CMD_GSTAT, regs, 6);
 196        if (ret) {
 197                dev_err(&client->dev,
 198                        "could not perform chip read.\n");
 199                return ret;
 200        }
 201
 202        old_matrix = qt2160->key_matrix;
 203        qt2160->key_matrix = new_matrix = (regs[2] << 8) | regs[1];
 204
 205        mask = 0x01;
 206        for (i = 0; i < 16; ++i, mask <<= 1) {
 207                int keyval = new_matrix & mask;
 208
 209                if ((old_matrix & mask) != keyval) {
 210                        input_report_key(input, qt2160->keycodes[i], keyval);
 211                        dev_dbg(&client->dev, "key %d %s\n",
 212                                i, keyval ? "pressed" : "released");
 213                }
 214        }
 215
 216        input_sync(input);
 217
 218        return 0;
 219}
 220
 221static irqreturn_t qt2160_irq(int irq, void *_qt2160)
 222{
 223        struct qt2160_data *qt2160 = _qt2160;
 224        unsigned long flags;
 225
 226        spin_lock_irqsave(&qt2160->lock, flags);
 227
 228        mod_delayed_work(system_wq, &qt2160->dwork, 0);
 229
 230        spin_unlock_irqrestore(&qt2160->lock, flags);
 231
 232        return IRQ_HANDLED;
 233}
 234
 235static void qt2160_schedule_read(struct qt2160_data *qt2160)
 236{
 237        spin_lock_irq(&qt2160->lock);
 238        schedule_delayed_work(&qt2160->dwork, QT2160_CYCLE_INTERVAL);
 239        spin_unlock_irq(&qt2160->lock);
 240}
 241
 242static void qt2160_worker(struct work_struct *work)
 243{
 244        struct qt2160_data *qt2160 =
 245                container_of(work, struct qt2160_data, dwork.work);
 246
 247        dev_dbg(&qt2160->client->dev, "worker\n");
 248
 249        qt2160_get_key_matrix(qt2160);
 250
 251        /* Avoid device lock up by checking every so often */
 252        qt2160_schedule_read(qt2160);
 253}
 254
 255static int qt2160_read(struct i2c_client *client, u8 reg)
 256{
 257        int ret;
 258
 259        ret = i2c_smbus_write_byte(client, reg);
 260        if (ret) {
 261                dev_err(&client->dev,
 262                        "couldn't send request. Returned %d\n", ret);
 263                return ret;
 264        }
 265
 266        ret = i2c_smbus_read_byte(client);
 267        if (ret < 0) {
 268                dev_err(&client->dev,
 269                        "couldn't read register. Returned %d\n", ret);
 270                return ret;
 271        }
 272
 273        return ret;
 274}
 275
 276static int qt2160_write(struct i2c_client *client, u8 reg, u8 data)
 277{
 278        int ret;
 279
 280        ret = i2c_smbus_write_byte_data(client, reg, data);
 281        if (ret < 0)
 282                dev_err(&client->dev,
 283                        "couldn't write data. Returned %d\n", ret);
 284
 285        return ret;
 286}
 287
 288#ifdef CONFIG_LEDS_CLASS
 289
 290static int qt2160_register_leds(struct qt2160_data *qt2160)
 291{
 292        struct i2c_client *client = qt2160->client;
 293        int ret;
 294        int i;
 295
 296        mutex_init(&qt2160->led_lock);
 297
 298        for (i = 0; i < QT2160_NUM_LEDS_X; i++) {
 299                struct qt2160_led *led = &qt2160->leds[i];
 300
 301                snprintf(led->name, sizeof(led->name), "qt2160:x%d", i);
 302                led->cdev.name = led->name;
 303                led->cdev.brightness_set = qt2160_led_set;
 304                led->cdev.brightness = LED_OFF;
 305                led->id = i;
 306                led->qt2160 = qt2160;
 307
 308                INIT_WORK(&led->work, qt2160_led_work);
 309
 310                ret = led_classdev_register(&client->dev, &led->cdev);
 311                if (ret < 0)
 312                        return ret;
 313        }
 314
 315        /* Tur off LEDs */
 316        qt2160_write(client, QT2160_CMD_DRIVE_X, 0);
 317        qt2160_write(client, QT2160_CMD_PWMEN_X, 0);
 318        qt2160_write(client, QT2160_CMD_PWM_DUTY, 0);
 319
 320        return 0;
 321}
 322
 323static void qt2160_unregister_leds(struct qt2160_data *qt2160)
 324{
 325        int i;
 326
 327        for (i = 0; i < QT2160_NUM_LEDS_X; i++) {
 328                led_classdev_unregister(&qt2160->leds[i].cdev);
 329                cancel_work_sync(&qt2160->leds[i].work);
 330        }
 331}
 332
 333#else
 334
 335static inline int qt2160_register_leds(struct qt2160_data *qt2160)
 336{
 337        return 0;
 338}
 339
 340static inline void qt2160_unregister_leds(struct qt2160_data *qt2160)
 341{
 342}
 343
 344#endif
 345
 346static bool qt2160_identify(struct i2c_client *client)
 347{
 348        int id, ver, rev;
 349
 350        /* Read Chid ID to check if chip is valid */
 351        id = qt2160_read(client, QT2160_CMD_CHIPID);
 352        if (id != QT2160_VALID_CHIPID) {
 353                dev_err(&client->dev, "ID %d not supported\n", id);
 354                return false;
 355        }
 356
 357        /* Read chip firmware version */
 358        ver = qt2160_read(client, QT2160_CMD_CODEVER);
 359        if (ver < 0) {
 360                dev_err(&client->dev, "could not get firmware version\n");
 361                return false;
 362        }
 363
 364        /* Read chip firmware revision */
 365        rev = qt2160_read(client, QT2160_CMD_SUBVER);
 366        if (rev < 0) {
 367                dev_err(&client->dev, "could not get firmware revision\n");
 368                return false;
 369        }
 370
 371        dev_info(&client->dev, "AT42QT2160 firmware version %d.%d.%d\n",
 372                        ver >> 4, ver & 0xf, rev);
 373
 374        return true;
 375}
 376
 377static int qt2160_probe(struct i2c_client *client,
 378                        const struct i2c_device_id *id)
 379{
 380        struct qt2160_data *qt2160;
 381        struct input_dev *input;
 382        int i;
 383        int error;
 384
 385        /* Check functionality */
 386        error = i2c_check_functionality(client->adapter,
 387                        I2C_FUNC_SMBUS_BYTE);
 388        if (!error) {
 389                dev_err(&client->dev, "%s adapter not supported\n",
 390                                dev_driver_string(&client->adapter->dev));
 391                return -ENODEV;
 392        }
 393
 394        if (!qt2160_identify(client))
 395                return -ENODEV;
 396
 397        /* Chip is valid and active. Allocate structure */
 398        qt2160 = kzalloc(sizeof(struct qt2160_data), GFP_KERNEL);
 399        input = input_allocate_device();
 400        if (!qt2160 || !input) {
 401                dev_err(&client->dev, "insufficient memory\n");
 402                error = -ENOMEM;
 403                goto err_free_mem;
 404        }
 405
 406        qt2160->client = client;
 407        qt2160->input = input;
 408        INIT_DELAYED_WORK(&qt2160->dwork, qt2160_worker);
 409        spin_lock_init(&qt2160->lock);
 410
 411        input->name = "AT42QT2160 Touch Sense Keyboard";
 412        input->id.bustype = BUS_I2C;
 413
 414        input->keycode = qt2160->keycodes;
 415        input->keycodesize = sizeof(qt2160->keycodes[0]);
 416        input->keycodemax = ARRAY_SIZE(qt2160_key2code);
 417
 418        __set_bit(EV_KEY, input->evbit);
 419        __clear_bit(EV_REP, input->evbit);
 420        for (i = 0; i < ARRAY_SIZE(qt2160_key2code); i++) {
 421                qt2160->keycodes[i] = qt2160_key2code[i];
 422                __set_bit(qt2160_key2code[i], input->keybit);
 423        }
 424        __clear_bit(KEY_RESERVED, input->keybit);
 425
 426        /* Calibrate device */
 427        error = qt2160_write(client, QT2160_CMD_CALIBRATE, 1);
 428        if (error) {
 429                dev_err(&client->dev, "failed to calibrate device\n");
 430                goto err_free_mem;
 431        }
 432
 433        if (client->irq) {
 434                error = request_irq(client->irq, qt2160_irq,
 435                                    IRQF_TRIGGER_FALLING, "qt2160", qt2160);
 436                if (error) {
 437                        dev_err(&client->dev,
 438                                "failed to allocate irq %d\n", client->irq);
 439                        goto err_free_mem;
 440                }
 441        }
 442
 443        error = qt2160_register_leds(qt2160);
 444        if (error) {
 445                dev_err(&client->dev, "Failed to register leds\n");
 446                goto err_free_irq;
 447        }
 448
 449        error = input_register_device(qt2160->input);
 450        if (error) {
 451                dev_err(&client->dev,
 452                        "Failed to register input device\n");
 453                goto err_unregister_leds;
 454        }
 455
 456        i2c_set_clientdata(client, qt2160);
 457        qt2160_schedule_read(qt2160);
 458
 459        return 0;
 460
 461err_unregister_leds:
 462        qt2160_unregister_leds(qt2160);
 463err_free_irq:
 464        if (client->irq)
 465                free_irq(client->irq, qt2160);
 466err_free_mem:
 467        input_free_device(input);
 468        kfree(qt2160);
 469        return error;
 470}
 471
 472static int qt2160_remove(struct i2c_client *client)
 473{
 474        struct qt2160_data *qt2160 = i2c_get_clientdata(client);
 475
 476        qt2160_unregister_leds(qt2160);
 477
 478        /* Release IRQ so no queue will be scheduled */
 479        if (client->irq)
 480                free_irq(client->irq, qt2160);
 481
 482        cancel_delayed_work_sync(&qt2160->dwork);
 483
 484        input_unregister_device(qt2160->input);
 485        kfree(qt2160);
 486
 487        return 0;
 488}
 489
 490static const struct i2c_device_id qt2160_idtable[] = {
 491        { "qt2160", 0, },
 492        { }
 493};
 494
 495MODULE_DEVICE_TABLE(i2c, qt2160_idtable);
 496
 497static struct i2c_driver qt2160_driver = {
 498        .driver = {
 499                .name   = "qt2160",
 500        },
 501
 502        .id_table       = qt2160_idtable,
 503        .probe          = qt2160_probe,
 504        .remove         = qt2160_remove,
 505};
 506
 507module_i2c_driver(qt2160_driver);
 508
 509MODULE_AUTHOR("Raphael Derosso Pereira <raphaelpereira@gmail.com>");
 510MODULE_DESCRIPTION("Driver for AT42QT2160 Touch Sensor");
 511MODULE_LICENSE("GPL");
 512