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