1*74ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2fde11323SRaphael Derosso Pereira /* 3fde11323SRaphael Derosso Pereira * qt2160.c - Atmel AT42QT2160 Touch Sense Controller 4fde11323SRaphael Derosso Pereira * 5fde11323SRaphael Derosso Pereira * Copyright (C) 2009 Raphael Derosso Pereira <raphaelpereira@gmail.com> 6fde11323SRaphael Derosso Pereira */ 7fde11323SRaphael Derosso Pereira 8fde11323SRaphael Derosso Pereira #include <linux/kernel.h> 90e47e3dcSJavier Martin #include <linux/leds.h> 10fde11323SRaphael Derosso Pereira #include <linux/module.h> 11fde11323SRaphael Derosso Pereira #include <linux/slab.h> 12fde11323SRaphael Derosso Pereira #include <linux/jiffies.h> 13fde11323SRaphael Derosso Pereira #include <linux/i2c.h> 14fde11323SRaphael Derosso Pereira #include <linux/irq.h> 15fde11323SRaphael Derosso Pereira #include <linux/interrupt.h> 16fde11323SRaphael Derosso Pereira #include <linux/input.h> 17fde11323SRaphael Derosso Pereira 18fde11323SRaphael Derosso Pereira #define QT2160_VALID_CHIPID 0x11 19fde11323SRaphael Derosso Pereira 20fde11323SRaphael Derosso Pereira #define QT2160_CMD_CHIPID 0 21fde11323SRaphael Derosso Pereira #define QT2160_CMD_CODEVER 1 22fde11323SRaphael Derosso Pereira #define QT2160_CMD_GSTAT 2 23fde11323SRaphael Derosso Pereira #define QT2160_CMD_KEYS3 3 24fde11323SRaphael Derosso Pereira #define QT2160_CMD_KEYS4 4 25fde11323SRaphael Derosso Pereira #define QT2160_CMD_SLIDE 5 26fde11323SRaphael Derosso Pereira #define QT2160_CMD_GPIOS 6 27fde11323SRaphael Derosso Pereira #define QT2160_CMD_SUBVER 7 28fde11323SRaphael Derosso Pereira #define QT2160_CMD_CALIBRATE 10 290e47e3dcSJavier Martin #define QT2160_CMD_DRIVE_X 70 300e47e3dcSJavier Martin #define QT2160_CMD_PWMEN_X 74 310e47e3dcSJavier Martin #define QT2160_CMD_PWM_DUTY 76 320e47e3dcSJavier Martin 330e47e3dcSJavier Martin #define QT2160_NUM_LEDS_X 8 34fde11323SRaphael Derosso Pereira 35fde11323SRaphael Derosso Pereira #define QT2160_CYCLE_INTERVAL (2*HZ) 36fde11323SRaphael Derosso Pereira 37fde11323SRaphael Derosso Pereira static unsigned char qt2160_key2code[] = { 38fde11323SRaphael Derosso Pereira KEY_0, KEY_1, KEY_2, KEY_3, 39fde11323SRaphael Derosso Pereira KEY_4, KEY_5, KEY_6, KEY_7, 40fde11323SRaphael Derosso Pereira KEY_8, KEY_9, KEY_A, KEY_B, 41fde11323SRaphael Derosso Pereira KEY_C, KEY_D, KEY_E, KEY_F, 42fde11323SRaphael Derosso Pereira }; 43fde11323SRaphael Derosso Pereira 440e47e3dcSJavier Martin #ifdef CONFIG_LEDS_CLASS 450e47e3dcSJavier Martin struct qt2160_led { 460e47e3dcSJavier Martin struct qt2160_data *qt2160; 470e47e3dcSJavier Martin struct led_classdev cdev; 480e47e3dcSJavier Martin char name[32]; 490e47e3dcSJavier Martin int id; 5083cd2030SDmitry Torokhov enum led_brightness brightness; 510e47e3dcSJavier Martin }; 520e47e3dcSJavier Martin #endif 530e47e3dcSJavier Martin 54fde11323SRaphael Derosso Pereira struct qt2160_data { 55fde11323SRaphael Derosso Pereira struct i2c_client *client; 56fde11323SRaphael Derosso Pereira struct input_dev *input; 57fde11323SRaphael Derosso Pereira struct delayed_work dwork; 58fde11323SRaphael Derosso Pereira unsigned short keycodes[ARRAY_SIZE(qt2160_key2code)]; 59fde11323SRaphael Derosso Pereira u16 key_matrix; 600e47e3dcSJavier Martin #ifdef CONFIG_LEDS_CLASS 610e47e3dcSJavier Martin struct qt2160_led leds[QT2160_NUM_LEDS_X]; 620e47e3dcSJavier Martin #endif 63fde11323SRaphael Derosso Pereira }; 64fde11323SRaphael Derosso Pereira 650e47e3dcSJavier Martin static int qt2160_read(struct i2c_client *client, u8 reg); 660e47e3dcSJavier Martin static int qt2160_write(struct i2c_client *client, u8 reg, u8 data); 670e47e3dcSJavier Martin 680e47e3dcSJavier Martin #ifdef CONFIG_LEDS_CLASS 690e47e3dcSJavier Martin 7083cd2030SDmitry Torokhov static int qt2160_led_set(struct led_classdev *cdev, 7183cd2030SDmitry Torokhov enum led_brightness value) 720e47e3dcSJavier Martin { 7383cd2030SDmitry Torokhov struct qt2160_led *led = container_of(cdev, struct qt2160_led, cdev); 740e47e3dcSJavier Martin struct qt2160_data *qt2160 = led->qt2160; 750e47e3dcSJavier Martin struct i2c_client *client = qt2160->client; 760e47e3dcSJavier Martin u32 drive, pwmen; 770e47e3dcSJavier Martin 7883cd2030SDmitry Torokhov if (value != led->brightness) { 790e47e3dcSJavier Martin drive = qt2160_read(client, QT2160_CMD_DRIVE_X); 800e47e3dcSJavier Martin pwmen = qt2160_read(client, QT2160_CMD_PWMEN_X); 810e47e3dcSJavier Martin if (value != LED_OFF) { 8283cd2030SDmitry Torokhov drive |= BIT(led->id); 8383cd2030SDmitry Torokhov pwmen |= BIT(led->id); 840e47e3dcSJavier Martin 850e47e3dcSJavier Martin } else { 8683cd2030SDmitry Torokhov drive &= ~BIT(led->id); 8783cd2030SDmitry Torokhov pwmen &= ~BIT(led->id); 880e47e3dcSJavier Martin } 890e47e3dcSJavier Martin qt2160_write(client, QT2160_CMD_DRIVE_X, drive); 900e47e3dcSJavier Martin qt2160_write(client, QT2160_CMD_PWMEN_X, pwmen); 910e47e3dcSJavier Martin 920e47e3dcSJavier Martin /* 930e47e3dcSJavier Martin * Changing this register will change the brightness 940e47e3dcSJavier Martin * of every LED in the qt2160. It's a HW limitation. 950e47e3dcSJavier Martin */ 960e47e3dcSJavier Martin if (value != LED_OFF) 970e47e3dcSJavier Martin qt2160_write(client, QT2160_CMD_PWM_DUTY, value); 980e47e3dcSJavier Martin 9983cd2030SDmitry Torokhov led->brightness = value; 1000e47e3dcSJavier Martin } 1010e47e3dcSJavier Martin 10283cd2030SDmitry Torokhov return 0; 1030e47e3dcSJavier Martin } 1040e47e3dcSJavier Martin 1050e47e3dcSJavier Martin #endif /* CONFIG_LEDS_CLASS */ 1060e47e3dcSJavier Martin 107fde11323SRaphael Derosso Pereira static int qt2160_read_block(struct i2c_client *client, 108fde11323SRaphael Derosso Pereira u8 inireg, u8 *buffer, unsigned int count) 109fde11323SRaphael Derosso Pereira { 110fde11323SRaphael Derosso Pereira int error, idx = 0; 111fde11323SRaphael Derosso Pereira 112fde11323SRaphael Derosso Pereira /* 113fde11323SRaphael Derosso Pereira * Can't use SMBus block data read. Check for I2C functionality to speed 114fde11323SRaphael Derosso Pereira * things up whenever possible. Otherwise we will be forced to read 115fde11323SRaphael Derosso Pereira * sequentially. 116fde11323SRaphael Derosso Pereira */ 117fde11323SRaphael Derosso Pereira if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 118fde11323SRaphael Derosso Pereira 119fde11323SRaphael Derosso Pereira error = i2c_smbus_write_byte(client, inireg + idx); 120fde11323SRaphael Derosso Pereira if (error) { 121fde11323SRaphael Derosso Pereira dev_err(&client->dev, 122fde11323SRaphael Derosso Pereira "couldn't send request. Returned %d\n", error); 123fde11323SRaphael Derosso Pereira return error; 124fde11323SRaphael Derosso Pereira } 125fde11323SRaphael Derosso Pereira 126fde11323SRaphael Derosso Pereira error = i2c_master_recv(client, buffer, count); 127fde11323SRaphael Derosso Pereira if (error != count) { 128fde11323SRaphael Derosso Pereira dev_err(&client->dev, 129fde11323SRaphael Derosso Pereira "couldn't read registers. Returned %d bytes\n", error); 130fde11323SRaphael Derosso Pereira return error; 131fde11323SRaphael Derosso Pereira } 132fde11323SRaphael Derosso Pereira } else { 133fde11323SRaphael Derosso Pereira 134fde11323SRaphael Derosso Pereira while (count--) { 135fde11323SRaphael Derosso Pereira int data; 136fde11323SRaphael Derosso Pereira 137fde11323SRaphael Derosso Pereira error = i2c_smbus_write_byte(client, inireg + idx); 138fde11323SRaphael Derosso Pereira if (error) { 139fde11323SRaphael Derosso Pereira dev_err(&client->dev, 140fde11323SRaphael Derosso Pereira "couldn't send request. Returned %d\n", error); 141fde11323SRaphael Derosso Pereira return error; 142fde11323SRaphael Derosso Pereira } 143fde11323SRaphael Derosso Pereira 144fde11323SRaphael Derosso Pereira data = i2c_smbus_read_byte(client); 145fde11323SRaphael Derosso Pereira if (data < 0) { 146fde11323SRaphael Derosso Pereira dev_err(&client->dev, 147fde11323SRaphael Derosso Pereira "couldn't read register. Returned %d\n", data); 148fde11323SRaphael Derosso Pereira return data; 149fde11323SRaphael Derosso Pereira } 150fde11323SRaphael Derosso Pereira 151fde11323SRaphael Derosso Pereira buffer[idx++] = data; 152fde11323SRaphael Derosso Pereira } 153fde11323SRaphael Derosso Pereira } 154fde11323SRaphael Derosso Pereira 155fde11323SRaphael Derosso Pereira return 0; 156fde11323SRaphael Derosso Pereira } 157fde11323SRaphael Derosso Pereira 158fde11323SRaphael Derosso Pereira static int qt2160_get_key_matrix(struct qt2160_data *qt2160) 159fde11323SRaphael Derosso Pereira { 160fde11323SRaphael Derosso Pereira struct i2c_client *client = qt2160->client; 161fde11323SRaphael Derosso Pereira struct input_dev *input = qt2160->input; 162fde11323SRaphael Derosso Pereira u8 regs[6]; 163fde11323SRaphael Derosso Pereira u16 old_matrix, new_matrix; 164fde11323SRaphael Derosso Pereira int ret, i, mask; 165fde11323SRaphael Derosso Pereira 166fde11323SRaphael Derosso Pereira dev_dbg(&client->dev, "requesting keys...\n"); 167fde11323SRaphael Derosso Pereira 168fde11323SRaphael Derosso Pereira /* 169fde11323SRaphael Derosso Pereira * Read all registers from General Status Register 170fde11323SRaphael Derosso Pereira * to GPIOs register 171fde11323SRaphael Derosso Pereira */ 172fde11323SRaphael Derosso Pereira ret = qt2160_read_block(client, QT2160_CMD_GSTAT, regs, 6); 173fde11323SRaphael Derosso Pereira if (ret) { 174fde11323SRaphael Derosso Pereira dev_err(&client->dev, 175fde11323SRaphael Derosso Pereira "could not perform chip read.\n"); 176fde11323SRaphael Derosso Pereira return ret; 177fde11323SRaphael Derosso Pereira } 178fde11323SRaphael Derosso Pereira 179fde11323SRaphael Derosso Pereira old_matrix = qt2160->key_matrix; 180fde11323SRaphael Derosso Pereira qt2160->key_matrix = new_matrix = (regs[2] << 8) | regs[1]; 181fde11323SRaphael Derosso Pereira 182fde11323SRaphael Derosso Pereira mask = 0x01; 183fde11323SRaphael Derosso Pereira for (i = 0; i < 16; ++i, mask <<= 1) { 184fde11323SRaphael Derosso Pereira int keyval = new_matrix & mask; 185fde11323SRaphael Derosso Pereira 186fde11323SRaphael Derosso Pereira if ((old_matrix & mask) != keyval) { 187fde11323SRaphael Derosso Pereira input_report_key(input, qt2160->keycodes[i], keyval); 188fde11323SRaphael Derosso Pereira dev_dbg(&client->dev, "key %d %s\n", 189fde11323SRaphael Derosso Pereira i, keyval ? "pressed" : "released"); 190fde11323SRaphael Derosso Pereira } 191fde11323SRaphael Derosso Pereira } 192fde11323SRaphael Derosso Pereira 193fde11323SRaphael Derosso Pereira input_sync(input); 194fde11323SRaphael Derosso Pereira 195fde11323SRaphael Derosso Pereira return 0; 196fde11323SRaphael Derosso Pereira } 197fde11323SRaphael Derosso Pereira 198fde11323SRaphael Derosso Pereira static irqreturn_t qt2160_irq(int irq, void *_qt2160) 199fde11323SRaphael Derosso Pereira { 200fde11323SRaphael Derosso Pereira struct qt2160_data *qt2160 = _qt2160; 201fde11323SRaphael Derosso Pereira 202e7c2f967STejun Heo mod_delayed_work(system_wq, &qt2160->dwork, 0); 203fde11323SRaphael Derosso Pereira 204fde11323SRaphael Derosso Pereira return IRQ_HANDLED; 205fde11323SRaphael Derosso Pereira } 206fde11323SRaphael Derosso Pereira 207fde11323SRaphael Derosso Pereira static void qt2160_schedule_read(struct qt2160_data *qt2160) 208fde11323SRaphael Derosso Pereira { 209fde11323SRaphael Derosso Pereira schedule_delayed_work(&qt2160->dwork, QT2160_CYCLE_INTERVAL); 210fde11323SRaphael Derosso Pereira } 211fde11323SRaphael Derosso Pereira 212fde11323SRaphael Derosso Pereira static void qt2160_worker(struct work_struct *work) 213fde11323SRaphael Derosso Pereira { 214fde11323SRaphael Derosso Pereira struct qt2160_data *qt2160 = 215fde11323SRaphael Derosso Pereira container_of(work, struct qt2160_data, dwork.work); 216fde11323SRaphael Derosso Pereira 217fde11323SRaphael Derosso Pereira dev_dbg(&qt2160->client->dev, "worker\n"); 218fde11323SRaphael Derosso Pereira 219fde11323SRaphael Derosso Pereira qt2160_get_key_matrix(qt2160); 220fde11323SRaphael Derosso Pereira 221fde11323SRaphael Derosso Pereira /* Avoid device lock up by checking every so often */ 222fde11323SRaphael Derosso Pereira qt2160_schedule_read(qt2160); 223fde11323SRaphael Derosso Pereira } 224fde11323SRaphael Derosso Pereira 2255298cc4cSBill Pemberton static int qt2160_read(struct i2c_client *client, u8 reg) 226fde11323SRaphael Derosso Pereira { 227fde11323SRaphael Derosso Pereira int ret; 228fde11323SRaphael Derosso Pereira 229fde11323SRaphael Derosso Pereira ret = i2c_smbus_write_byte(client, reg); 230fde11323SRaphael Derosso Pereira if (ret) { 231fde11323SRaphael Derosso Pereira dev_err(&client->dev, 232fde11323SRaphael Derosso Pereira "couldn't send request. Returned %d\n", ret); 233fde11323SRaphael Derosso Pereira return ret; 234fde11323SRaphael Derosso Pereira } 235fde11323SRaphael Derosso Pereira 236fde11323SRaphael Derosso Pereira ret = i2c_smbus_read_byte(client); 237fde11323SRaphael Derosso Pereira if (ret < 0) { 238fde11323SRaphael Derosso Pereira dev_err(&client->dev, 239fde11323SRaphael Derosso Pereira "couldn't read register. Returned %d\n", ret); 240fde11323SRaphael Derosso Pereira return ret; 241fde11323SRaphael Derosso Pereira } 242fde11323SRaphael Derosso Pereira 243fde11323SRaphael Derosso Pereira return ret; 244fde11323SRaphael Derosso Pereira } 245fde11323SRaphael Derosso Pereira 2465298cc4cSBill Pemberton static int qt2160_write(struct i2c_client *client, u8 reg, u8 data) 247fde11323SRaphael Derosso Pereira { 248a6e8c0a2SJavier Martin int ret; 249fde11323SRaphael Derosso Pereira 250a6e8c0a2SJavier Martin ret = i2c_smbus_write_byte_data(client, reg, data); 251a6e8c0a2SJavier Martin if (ret < 0) 252fde11323SRaphael Derosso Pereira dev_err(&client->dev, 253a6e8c0a2SJavier Martin "couldn't write data. Returned %d\n", ret); 254fde11323SRaphael Derosso Pereira 255a6e8c0a2SJavier Martin return ret; 256fde11323SRaphael Derosso Pereira } 257fde11323SRaphael Derosso Pereira 2580e47e3dcSJavier Martin #ifdef CONFIG_LEDS_CLASS 2590e47e3dcSJavier Martin 2600e47e3dcSJavier Martin static int qt2160_register_leds(struct qt2160_data *qt2160) 2610e47e3dcSJavier Martin { 2620e47e3dcSJavier Martin struct i2c_client *client = qt2160->client; 2630e47e3dcSJavier Martin int ret; 2640e47e3dcSJavier Martin int i; 2650e47e3dcSJavier Martin 2660e47e3dcSJavier Martin for (i = 0; i < QT2160_NUM_LEDS_X; i++) { 2670e47e3dcSJavier Martin struct qt2160_led *led = &qt2160->leds[i]; 2680e47e3dcSJavier Martin 2690e47e3dcSJavier Martin snprintf(led->name, sizeof(led->name), "qt2160:x%d", i); 2700e47e3dcSJavier Martin led->cdev.name = led->name; 27183cd2030SDmitry Torokhov led->cdev.brightness_set_blocking = qt2160_led_set; 2720e47e3dcSJavier Martin led->cdev.brightness = LED_OFF; 2730e47e3dcSJavier Martin led->id = i; 2740e47e3dcSJavier Martin led->qt2160 = qt2160; 2750e47e3dcSJavier Martin 2760e47e3dcSJavier Martin ret = led_classdev_register(&client->dev, &led->cdev); 2770e47e3dcSJavier Martin if (ret < 0) 2780e47e3dcSJavier Martin return ret; 2790e47e3dcSJavier Martin } 2800e47e3dcSJavier Martin 2810e47e3dcSJavier Martin /* Tur off LEDs */ 2820e47e3dcSJavier Martin qt2160_write(client, QT2160_CMD_DRIVE_X, 0); 2830e47e3dcSJavier Martin qt2160_write(client, QT2160_CMD_PWMEN_X, 0); 2840e47e3dcSJavier Martin qt2160_write(client, QT2160_CMD_PWM_DUTY, 0); 2850e47e3dcSJavier Martin 2860e47e3dcSJavier Martin return 0; 2870e47e3dcSJavier Martin } 2880e47e3dcSJavier Martin 2890e47e3dcSJavier Martin static void qt2160_unregister_leds(struct qt2160_data *qt2160) 2900e47e3dcSJavier Martin { 2910e47e3dcSJavier Martin int i; 2920e47e3dcSJavier Martin 29383cd2030SDmitry Torokhov for (i = 0; i < QT2160_NUM_LEDS_X; i++) 2940e47e3dcSJavier Martin led_classdev_unregister(&qt2160->leds[i].cdev); 2950e47e3dcSJavier Martin } 2960e47e3dcSJavier Martin 2970e47e3dcSJavier Martin #else 2980e47e3dcSJavier Martin 2990e47e3dcSJavier Martin static inline int qt2160_register_leds(struct qt2160_data *qt2160) 3000e47e3dcSJavier Martin { 3010e47e3dcSJavier Martin return 0; 3020e47e3dcSJavier Martin } 3030e47e3dcSJavier Martin 3040e47e3dcSJavier Martin static inline void qt2160_unregister_leds(struct qt2160_data *qt2160) 3050e47e3dcSJavier Martin { 3060e47e3dcSJavier Martin } 3070e47e3dcSJavier Martin 3080e47e3dcSJavier Martin #endif 309fde11323SRaphael Derosso Pereira 3105298cc4cSBill Pemberton static bool qt2160_identify(struct i2c_client *client) 311fde11323SRaphael Derosso Pereira { 312fde11323SRaphael Derosso Pereira int id, ver, rev; 313fde11323SRaphael Derosso Pereira 314fde11323SRaphael Derosso Pereira /* Read Chid ID to check if chip is valid */ 315fde11323SRaphael Derosso Pereira id = qt2160_read(client, QT2160_CMD_CHIPID); 316fde11323SRaphael Derosso Pereira if (id != QT2160_VALID_CHIPID) { 317fde11323SRaphael Derosso Pereira dev_err(&client->dev, "ID %d not supported\n", id); 318fde11323SRaphael Derosso Pereira return false; 319fde11323SRaphael Derosso Pereira } 320fde11323SRaphael Derosso Pereira 321fde11323SRaphael Derosso Pereira /* Read chip firmware version */ 322fde11323SRaphael Derosso Pereira ver = qt2160_read(client, QT2160_CMD_CODEVER); 323fde11323SRaphael Derosso Pereira if (ver < 0) { 324fde11323SRaphael Derosso Pereira dev_err(&client->dev, "could not get firmware version\n"); 325fde11323SRaphael Derosso Pereira return false; 326fde11323SRaphael Derosso Pereira } 327fde11323SRaphael Derosso Pereira 328fde11323SRaphael Derosso Pereira /* Read chip firmware revision */ 329fde11323SRaphael Derosso Pereira rev = qt2160_read(client, QT2160_CMD_SUBVER); 330fde11323SRaphael Derosso Pereira if (rev < 0) { 331fde11323SRaphael Derosso Pereira dev_err(&client->dev, "could not get firmware revision\n"); 332fde11323SRaphael Derosso Pereira return false; 333fde11323SRaphael Derosso Pereira } 334fde11323SRaphael Derosso Pereira 335fde11323SRaphael Derosso Pereira dev_info(&client->dev, "AT42QT2160 firmware version %d.%d.%d\n", 336fde11323SRaphael Derosso Pereira ver >> 4, ver & 0xf, rev); 337fde11323SRaphael Derosso Pereira 338fde11323SRaphael Derosso Pereira return true; 339fde11323SRaphael Derosso Pereira } 340fde11323SRaphael Derosso Pereira 3415298cc4cSBill Pemberton static int qt2160_probe(struct i2c_client *client, 342fde11323SRaphael Derosso Pereira const struct i2c_device_id *id) 343fde11323SRaphael Derosso Pereira { 344fde11323SRaphael Derosso Pereira struct qt2160_data *qt2160; 345fde11323SRaphael Derosso Pereira struct input_dev *input; 346fde11323SRaphael Derosso Pereira int i; 347fde11323SRaphael Derosso Pereira int error; 348fde11323SRaphael Derosso Pereira 349fde11323SRaphael Derosso Pereira /* Check functionality */ 350fde11323SRaphael Derosso Pereira error = i2c_check_functionality(client->adapter, 351fde11323SRaphael Derosso Pereira I2C_FUNC_SMBUS_BYTE); 352fde11323SRaphael Derosso Pereira if (!error) { 353fde11323SRaphael Derosso Pereira dev_err(&client->dev, "%s adapter not supported\n", 354fde11323SRaphael Derosso Pereira dev_driver_string(&client->adapter->dev)); 355fde11323SRaphael Derosso Pereira return -ENODEV; 356fde11323SRaphael Derosso Pereira } 357fde11323SRaphael Derosso Pereira 358fde11323SRaphael Derosso Pereira if (!qt2160_identify(client)) 359fde11323SRaphael Derosso Pereira return -ENODEV; 360fde11323SRaphael Derosso Pereira 361fde11323SRaphael Derosso Pereira /* Chip is valid and active. Allocate structure */ 362fde11323SRaphael Derosso Pereira qt2160 = kzalloc(sizeof(struct qt2160_data), GFP_KERNEL); 363fde11323SRaphael Derosso Pereira input = input_allocate_device(); 364fde11323SRaphael Derosso Pereira if (!qt2160 || !input) { 365fde11323SRaphael Derosso Pereira dev_err(&client->dev, "insufficient memory\n"); 366fde11323SRaphael Derosso Pereira error = -ENOMEM; 367fde11323SRaphael Derosso Pereira goto err_free_mem; 368fde11323SRaphael Derosso Pereira } 369fde11323SRaphael Derosso Pereira 370fde11323SRaphael Derosso Pereira qt2160->client = client; 371fde11323SRaphael Derosso Pereira qt2160->input = input; 372fde11323SRaphael Derosso Pereira INIT_DELAYED_WORK(&qt2160->dwork, qt2160_worker); 373fde11323SRaphael Derosso Pereira 374fde11323SRaphael Derosso Pereira input->name = "AT42QT2160 Touch Sense Keyboard"; 375fde11323SRaphael Derosso Pereira input->id.bustype = BUS_I2C; 376fde11323SRaphael Derosso Pereira 377fde11323SRaphael Derosso Pereira input->keycode = qt2160->keycodes; 378fde11323SRaphael Derosso Pereira input->keycodesize = sizeof(qt2160->keycodes[0]); 379fde11323SRaphael Derosso Pereira input->keycodemax = ARRAY_SIZE(qt2160_key2code); 380fde11323SRaphael Derosso Pereira 381fde11323SRaphael Derosso Pereira __set_bit(EV_KEY, input->evbit); 382fde11323SRaphael Derosso Pereira __clear_bit(EV_REP, input->evbit); 383fde11323SRaphael Derosso Pereira for (i = 0; i < ARRAY_SIZE(qt2160_key2code); i++) { 384fde11323SRaphael Derosso Pereira qt2160->keycodes[i] = qt2160_key2code[i]; 385fde11323SRaphael Derosso Pereira __set_bit(qt2160_key2code[i], input->keybit); 386fde11323SRaphael Derosso Pereira } 387fde11323SRaphael Derosso Pereira __clear_bit(KEY_RESERVED, input->keybit); 388fde11323SRaphael Derosso Pereira 389fde11323SRaphael Derosso Pereira /* Calibrate device */ 390fde11323SRaphael Derosso Pereira error = qt2160_write(client, QT2160_CMD_CALIBRATE, 1); 391fde11323SRaphael Derosso Pereira if (error) { 392fde11323SRaphael Derosso Pereira dev_err(&client->dev, "failed to calibrate device\n"); 393fde11323SRaphael Derosso Pereira goto err_free_mem; 394fde11323SRaphael Derosso Pereira } 395fde11323SRaphael Derosso Pereira 396fde11323SRaphael Derosso Pereira if (client->irq) { 397fde11323SRaphael Derosso Pereira error = request_irq(client->irq, qt2160_irq, 398fde11323SRaphael Derosso Pereira IRQF_TRIGGER_FALLING, "qt2160", qt2160); 399fde11323SRaphael Derosso Pereira if (error) { 400fde11323SRaphael Derosso Pereira dev_err(&client->dev, 401fde11323SRaphael Derosso Pereira "failed to allocate irq %d\n", client->irq); 402fde11323SRaphael Derosso Pereira goto err_free_mem; 403fde11323SRaphael Derosso Pereira } 404fde11323SRaphael Derosso Pereira } 405fde11323SRaphael Derosso Pereira 4060e47e3dcSJavier Martin error = qt2160_register_leds(qt2160); 4070e47e3dcSJavier Martin if (error) { 4080e47e3dcSJavier Martin dev_err(&client->dev, "Failed to register leds\n"); 4090e47e3dcSJavier Martin goto err_free_irq; 4100e47e3dcSJavier Martin } 4110e47e3dcSJavier Martin 412fde11323SRaphael Derosso Pereira error = input_register_device(qt2160->input); 413fde11323SRaphael Derosso Pereira if (error) { 414fde11323SRaphael Derosso Pereira dev_err(&client->dev, 415fde11323SRaphael Derosso Pereira "Failed to register input device\n"); 4160e47e3dcSJavier Martin goto err_unregister_leds; 417fde11323SRaphael Derosso Pereira } 418fde11323SRaphael Derosso Pereira 419fde11323SRaphael Derosso Pereira i2c_set_clientdata(client, qt2160); 420fde11323SRaphael Derosso Pereira qt2160_schedule_read(qt2160); 421fde11323SRaphael Derosso Pereira 422fde11323SRaphael Derosso Pereira return 0; 423fde11323SRaphael Derosso Pereira 4240e47e3dcSJavier Martin err_unregister_leds: 4250e47e3dcSJavier Martin qt2160_unregister_leds(qt2160); 426fde11323SRaphael Derosso Pereira err_free_irq: 427fde11323SRaphael Derosso Pereira if (client->irq) 428fde11323SRaphael Derosso Pereira free_irq(client->irq, qt2160); 429fde11323SRaphael Derosso Pereira err_free_mem: 430fde11323SRaphael Derosso Pereira input_free_device(input); 431fde11323SRaphael Derosso Pereira kfree(qt2160); 432fde11323SRaphael Derosso Pereira return error; 433fde11323SRaphael Derosso Pereira } 434fde11323SRaphael Derosso Pereira 435e2619cf7SBill Pemberton static int qt2160_remove(struct i2c_client *client) 436fde11323SRaphael Derosso Pereira { 437fde11323SRaphael Derosso Pereira struct qt2160_data *qt2160 = i2c_get_clientdata(client); 438fde11323SRaphael Derosso Pereira 4390e47e3dcSJavier Martin qt2160_unregister_leds(qt2160); 4400e47e3dcSJavier Martin 441fde11323SRaphael Derosso Pereira /* Release IRQ so no queue will be scheduled */ 442fde11323SRaphael Derosso Pereira if (client->irq) 443fde11323SRaphael Derosso Pereira free_irq(client->irq, qt2160); 444fde11323SRaphael Derosso Pereira 445fde11323SRaphael Derosso Pereira cancel_delayed_work_sync(&qt2160->dwork); 446fde11323SRaphael Derosso Pereira 447fde11323SRaphael Derosso Pereira input_unregister_device(qt2160->input); 448fde11323SRaphael Derosso Pereira kfree(qt2160); 449fde11323SRaphael Derosso Pereira 450fde11323SRaphael Derosso Pereira return 0; 451fde11323SRaphael Derosso Pereira } 452fde11323SRaphael Derosso Pereira 453ce7b39a1SMárton Németh static const struct i2c_device_id qt2160_idtable[] = { 454fde11323SRaphael Derosso Pereira { "qt2160", 0, }, 455fde11323SRaphael Derosso Pereira { } 456fde11323SRaphael Derosso Pereira }; 457fde11323SRaphael Derosso Pereira 458fde11323SRaphael Derosso Pereira MODULE_DEVICE_TABLE(i2c, qt2160_idtable); 459fde11323SRaphael Derosso Pereira 460fde11323SRaphael Derosso Pereira static struct i2c_driver qt2160_driver = { 461fde11323SRaphael Derosso Pereira .driver = { 462fde11323SRaphael Derosso Pereira .name = "qt2160", 463fde11323SRaphael Derosso Pereira }, 464fde11323SRaphael Derosso Pereira 465fde11323SRaphael Derosso Pereira .id_table = qt2160_idtable, 466fde11323SRaphael Derosso Pereira .probe = qt2160_probe, 4671cb0aa88SBill Pemberton .remove = qt2160_remove, 468fde11323SRaphael Derosso Pereira }; 469fde11323SRaphael Derosso Pereira 4701b92c1cfSAxel Lin module_i2c_driver(qt2160_driver); 471fde11323SRaphael Derosso Pereira 472fde11323SRaphael Derosso Pereira MODULE_AUTHOR("Raphael Derosso Pereira <raphaelpereira@gmail.com>"); 473fde11323SRaphael Derosso Pereira MODULE_DESCRIPTION("Driver for AT42QT2160 Touch Sensor"); 474fde11323SRaphael Derosso Pereira MODULE_LICENSE("GPL"); 475