1fde11323SRaphael Derosso Pereira /* 2fde11323SRaphael Derosso Pereira * qt2160.c - Atmel AT42QT2160 Touch Sense Controller 3fde11323SRaphael Derosso Pereira * 4fde11323SRaphael Derosso Pereira * Copyright (C) 2009 Raphael Derosso Pereira <raphaelpereira@gmail.com> 5fde11323SRaphael Derosso Pereira * 6fde11323SRaphael Derosso Pereira * This program is free software; you can redistribute it and/or modify 7fde11323SRaphael Derosso Pereira * it under the terms of the GNU General Public License as published by 8fde11323SRaphael Derosso Pereira * the Free Software Foundation; either version 2 of the License, or 9fde11323SRaphael Derosso Pereira * (at your option) any later version. 10fde11323SRaphael Derosso Pereira * 11fde11323SRaphael Derosso Pereira * This program is distributed in the hope that it will be useful, 12fde11323SRaphael Derosso Pereira * but WITHOUT ANY WARRANTY; without even the implied warranty of 13fde11323SRaphael Derosso Pereira * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14fde11323SRaphael Derosso Pereira * GNU General Public License for more details. 15fde11323SRaphael Derosso Pereira * 16fde11323SRaphael Derosso Pereira * You should have received a copy of the GNU General Public License 17fde11323SRaphael Derosso Pereira * along with this program; if not, write to the Free Software 18fde11323SRaphael Derosso Pereira * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19fde11323SRaphael Derosso Pereira */ 20fde11323SRaphael Derosso Pereira 21fde11323SRaphael Derosso Pereira #include <linux/kernel.h> 220e47e3dcSJavier Martin #include <linux/leds.h> 23fde11323SRaphael Derosso Pereira #include <linux/module.h> 24fde11323SRaphael Derosso Pereira #include <linux/slab.h> 25fde11323SRaphael Derosso Pereira #include <linux/jiffies.h> 26fde11323SRaphael Derosso Pereira #include <linux/i2c.h> 27fde11323SRaphael Derosso Pereira #include <linux/irq.h> 28fde11323SRaphael Derosso Pereira #include <linux/interrupt.h> 29fde11323SRaphael Derosso Pereira #include <linux/input.h> 30fde11323SRaphael Derosso Pereira 31fde11323SRaphael Derosso Pereira #define QT2160_VALID_CHIPID 0x11 32fde11323SRaphael Derosso Pereira 33fde11323SRaphael Derosso Pereira #define QT2160_CMD_CHIPID 0 34fde11323SRaphael Derosso Pereira #define QT2160_CMD_CODEVER 1 35fde11323SRaphael Derosso Pereira #define QT2160_CMD_GSTAT 2 36fde11323SRaphael Derosso Pereira #define QT2160_CMD_KEYS3 3 37fde11323SRaphael Derosso Pereira #define QT2160_CMD_KEYS4 4 38fde11323SRaphael Derosso Pereira #define QT2160_CMD_SLIDE 5 39fde11323SRaphael Derosso Pereira #define QT2160_CMD_GPIOS 6 40fde11323SRaphael Derosso Pereira #define QT2160_CMD_SUBVER 7 41fde11323SRaphael Derosso Pereira #define QT2160_CMD_CALIBRATE 10 420e47e3dcSJavier Martin #define QT2160_CMD_DRIVE_X 70 430e47e3dcSJavier Martin #define QT2160_CMD_PWMEN_X 74 440e47e3dcSJavier Martin #define QT2160_CMD_PWM_DUTY 76 450e47e3dcSJavier Martin 460e47e3dcSJavier Martin #define QT2160_NUM_LEDS_X 8 47fde11323SRaphael Derosso Pereira 48fde11323SRaphael Derosso Pereira #define QT2160_CYCLE_INTERVAL (2*HZ) 49fde11323SRaphael Derosso Pereira 50fde11323SRaphael Derosso Pereira static unsigned char qt2160_key2code[] = { 51fde11323SRaphael Derosso Pereira KEY_0, KEY_1, KEY_2, KEY_3, 52fde11323SRaphael Derosso Pereira KEY_4, KEY_5, KEY_6, KEY_7, 53fde11323SRaphael Derosso Pereira KEY_8, KEY_9, KEY_A, KEY_B, 54fde11323SRaphael Derosso Pereira KEY_C, KEY_D, KEY_E, KEY_F, 55fde11323SRaphael Derosso Pereira }; 56fde11323SRaphael Derosso Pereira 570e47e3dcSJavier Martin #ifdef CONFIG_LEDS_CLASS 580e47e3dcSJavier Martin struct qt2160_led { 590e47e3dcSJavier Martin struct qt2160_data *qt2160; 600e47e3dcSJavier Martin struct led_classdev cdev; 610e47e3dcSJavier Martin char name[32]; 620e47e3dcSJavier Martin int id; 63*83cd2030SDmitry Torokhov enum led_brightness brightness; 640e47e3dcSJavier Martin }; 650e47e3dcSJavier Martin #endif 660e47e3dcSJavier Martin 67fde11323SRaphael Derosso Pereira struct qt2160_data { 68fde11323SRaphael Derosso Pereira struct i2c_client *client; 69fde11323SRaphael Derosso Pereira struct input_dev *input; 70fde11323SRaphael Derosso Pereira struct delayed_work dwork; 71fde11323SRaphael Derosso Pereira spinlock_t lock; /* Protects canceling/rescheduling of dwork */ 72fde11323SRaphael Derosso Pereira unsigned short keycodes[ARRAY_SIZE(qt2160_key2code)]; 73fde11323SRaphael Derosso Pereira u16 key_matrix; 740e47e3dcSJavier Martin #ifdef CONFIG_LEDS_CLASS 750e47e3dcSJavier Martin struct qt2160_led leds[QT2160_NUM_LEDS_X]; 760e47e3dcSJavier Martin #endif 77fde11323SRaphael Derosso Pereira }; 78fde11323SRaphael Derosso Pereira 790e47e3dcSJavier Martin static int qt2160_read(struct i2c_client *client, u8 reg); 800e47e3dcSJavier Martin static int qt2160_write(struct i2c_client *client, u8 reg, u8 data); 810e47e3dcSJavier Martin 820e47e3dcSJavier Martin #ifdef CONFIG_LEDS_CLASS 830e47e3dcSJavier Martin 84*83cd2030SDmitry Torokhov static int qt2160_led_set(struct led_classdev *cdev, 85*83cd2030SDmitry Torokhov enum led_brightness value) 860e47e3dcSJavier Martin { 87*83cd2030SDmitry Torokhov struct qt2160_led *led = container_of(cdev, struct qt2160_led, cdev); 880e47e3dcSJavier Martin struct qt2160_data *qt2160 = led->qt2160; 890e47e3dcSJavier Martin struct i2c_client *client = qt2160->client; 900e47e3dcSJavier Martin u32 drive, pwmen; 910e47e3dcSJavier Martin 92*83cd2030SDmitry Torokhov if (value != led->brightness) { 930e47e3dcSJavier Martin drive = qt2160_read(client, QT2160_CMD_DRIVE_X); 940e47e3dcSJavier Martin pwmen = qt2160_read(client, QT2160_CMD_PWMEN_X); 950e47e3dcSJavier Martin if (value != LED_OFF) { 96*83cd2030SDmitry Torokhov drive |= BIT(led->id); 97*83cd2030SDmitry Torokhov pwmen |= BIT(led->id); 980e47e3dcSJavier Martin 990e47e3dcSJavier Martin } else { 100*83cd2030SDmitry Torokhov drive &= ~BIT(led->id); 101*83cd2030SDmitry Torokhov pwmen &= ~BIT(led->id); 1020e47e3dcSJavier Martin } 1030e47e3dcSJavier Martin qt2160_write(client, QT2160_CMD_DRIVE_X, drive); 1040e47e3dcSJavier Martin qt2160_write(client, QT2160_CMD_PWMEN_X, pwmen); 1050e47e3dcSJavier Martin 1060e47e3dcSJavier Martin /* 1070e47e3dcSJavier Martin * Changing this register will change the brightness 1080e47e3dcSJavier Martin * of every LED in the qt2160. It's a HW limitation. 1090e47e3dcSJavier Martin */ 1100e47e3dcSJavier Martin if (value != LED_OFF) 1110e47e3dcSJavier Martin qt2160_write(client, QT2160_CMD_PWM_DUTY, value); 1120e47e3dcSJavier Martin 113*83cd2030SDmitry Torokhov led->brightness = value; 1140e47e3dcSJavier Martin } 1150e47e3dcSJavier Martin 116*83cd2030SDmitry Torokhov return 0; 1170e47e3dcSJavier Martin } 1180e47e3dcSJavier Martin 1190e47e3dcSJavier Martin #endif /* CONFIG_LEDS_CLASS */ 1200e47e3dcSJavier Martin 121fde11323SRaphael Derosso Pereira static int qt2160_read_block(struct i2c_client *client, 122fde11323SRaphael Derosso Pereira u8 inireg, u8 *buffer, unsigned int count) 123fde11323SRaphael Derosso Pereira { 124fde11323SRaphael Derosso Pereira int error, idx = 0; 125fde11323SRaphael Derosso Pereira 126fde11323SRaphael Derosso Pereira /* 127fde11323SRaphael Derosso Pereira * Can't use SMBus block data read. Check for I2C functionality to speed 128fde11323SRaphael Derosso Pereira * things up whenever possible. Otherwise we will be forced to read 129fde11323SRaphael Derosso Pereira * sequentially. 130fde11323SRaphael Derosso Pereira */ 131fde11323SRaphael Derosso Pereira if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 132fde11323SRaphael Derosso Pereira 133fde11323SRaphael Derosso Pereira error = i2c_smbus_write_byte(client, inireg + idx); 134fde11323SRaphael Derosso Pereira if (error) { 135fde11323SRaphael Derosso Pereira dev_err(&client->dev, 136fde11323SRaphael Derosso Pereira "couldn't send request. Returned %d\n", error); 137fde11323SRaphael Derosso Pereira return error; 138fde11323SRaphael Derosso Pereira } 139fde11323SRaphael Derosso Pereira 140fde11323SRaphael Derosso Pereira error = i2c_master_recv(client, buffer, count); 141fde11323SRaphael Derosso Pereira if (error != count) { 142fde11323SRaphael Derosso Pereira dev_err(&client->dev, 143fde11323SRaphael Derosso Pereira "couldn't read registers. Returned %d bytes\n", error); 144fde11323SRaphael Derosso Pereira return error; 145fde11323SRaphael Derosso Pereira } 146fde11323SRaphael Derosso Pereira } else { 147fde11323SRaphael Derosso Pereira 148fde11323SRaphael Derosso Pereira while (count--) { 149fde11323SRaphael Derosso Pereira int data; 150fde11323SRaphael Derosso Pereira 151fde11323SRaphael Derosso Pereira error = i2c_smbus_write_byte(client, inireg + idx); 152fde11323SRaphael Derosso Pereira if (error) { 153fde11323SRaphael Derosso Pereira dev_err(&client->dev, 154fde11323SRaphael Derosso Pereira "couldn't send request. Returned %d\n", error); 155fde11323SRaphael Derosso Pereira return error; 156fde11323SRaphael Derosso Pereira } 157fde11323SRaphael Derosso Pereira 158fde11323SRaphael Derosso Pereira data = i2c_smbus_read_byte(client); 159fde11323SRaphael Derosso Pereira if (data < 0) { 160fde11323SRaphael Derosso Pereira dev_err(&client->dev, 161fde11323SRaphael Derosso Pereira "couldn't read register. Returned %d\n", data); 162fde11323SRaphael Derosso Pereira return data; 163fde11323SRaphael Derosso Pereira } 164fde11323SRaphael Derosso Pereira 165fde11323SRaphael Derosso Pereira buffer[idx++] = data; 166fde11323SRaphael Derosso Pereira } 167fde11323SRaphael Derosso Pereira } 168fde11323SRaphael Derosso Pereira 169fde11323SRaphael Derosso Pereira return 0; 170fde11323SRaphael Derosso Pereira } 171fde11323SRaphael Derosso Pereira 172fde11323SRaphael Derosso Pereira static int qt2160_get_key_matrix(struct qt2160_data *qt2160) 173fde11323SRaphael Derosso Pereira { 174fde11323SRaphael Derosso Pereira struct i2c_client *client = qt2160->client; 175fde11323SRaphael Derosso Pereira struct input_dev *input = qt2160->input; 176fde11323SRaphael Derosso Pereira u8 regs[6]; 177fde11323SRaphael Derosso Pereira u16 old_matrix, new_matrix; 178fde11323SRaphael Derosso Pereira int ret, i, mask; 179fde11323SRaphael Derosso Pereira 180fde11323SRaphael Derosso Pereira dev_dbg(&client->dev, "requesting keys...\n"); 181fde11323SRaphael Derosso Pereira 182fde11323SRaphael Derosso Pereira /* 183fde11323SRaphael Derosso Pereira * Read all registers from General Status Register 184fde11323SRaphael Derosso Pereira * to GPIOs register 185fde11323SRaphael Derosso Pereira */ 186fde11323SRaphael Derosso Pereira ret = qt2160_read_block(client, QT2160_CMD_GSTAT, regs, 6); 187fde11323SRaphael Derosso Pereira if (ret) { 188fde11323SRaphael Derosso Pereira dev_err(&client->dev, 189fde11323SRaphael Derosso Pereira "could not perform chip read.\n"); 190fde11323SRaphael Derosso Pereira return ret; 191fde11323SRaphael Derosso Pereira } 192fde11323SRaphael Derosso Pereira 193fde11323SRaphael Derosso Pereira old_matrix = qt2160->key_matrix; 194fde11323SRaphael Derosso Pereira qt2160->key_matrix = new_matrix = (regs[2] << 8) | regs[1]; 195fde11323SRaphael Derosso Pereira 196fde11323SRaphael Derosso Pereira mask = 0x01; 197fde11323SRaphael Derosso Pereira for (i = 0; i < 16; ++i, mask <<= 1) { 198fde11323SRaphael Derosso Pereira int keyval = new_matrix & mask; 199fde11323SRaphael Derosso Pereira 200fde11323SRaphael Derosso Pereira if ((old_matrix & mask) != keyval) { 201fde11323SRaphael Derosso Pereira input_report_key(input, qt2160->keycodes[i], keyval); 202fde11323SRaphael Derosso Pereira dev_dbg(&client->dev, "key %d %s\n", 203fde11323SRaphael Derosso Pereira i, keyval ? "pressed" : "released"); 204fde11323SRaphael Derosso Pereira } 205fde11323SRaphael Derosso Pereira } 206fde11323SRaphael Derosso Pereira 207fde11323SRaphael Derosso Pereira input_sync(input); 208fde11323SRaphael Derosso Pereira 209fde11323SRaphael Derosso Pereira return 0; 210fde11323SRaphael Derosso Pereira } 211fde11323SRaphael Derosso Pereira 212fde11323SRaphael Derosso Pereira static irqreturn_t qt2160_irq(int irq, void *_qt2160) 213fde11323SRaphael Derosso Pereira { 214fde11323SRaphael Derosso Pereira struct qt2160_data *qt2160 = _qt2160; 215fde11323SRaphael Derosso Pereira unsigned long flags; 216fde11323SRaphael Derosso Pereira 217fde11323SRaphael Derosso Pereira spin_lock_irqsave(&qt2160->lock, flags); 218fde11323SRaphael Derosso Pereira 219e7c2f967STejun Heo mod_delayed_work(system_wq, &qt2160->dwork, 0); 220fde11323SRaphael Derosso Pereira 221fde11323SRaphael Derosso Pereira spin_unlock_irqrestore(&qt2160->lock, flags); 222fde11323SRaphael Derosso Pereira 223fde11323SRaphael Derosso Pereira return IRQ_HANDLED; 224fde11323SRaphael Derosso Pereira } 225fde11323SRaphael Derosso Pereira 226fde11323SRaphael Derosso Pereira static void qt2160_schedule_read(struct qt2160_data *qt2160) 227fde11323SRaphael Derosso Pereira { 228fde11323SRaphael Derosso Pereira spin_lock_irq(&qt2160->lock); 229fde11323SRaphael Derosso Pereira schedule_delayed_work(&qt2160->dwork, QT2160_CYCLE_INTERVAL); 230fde11323SRaphael Derosso Pereira spin_unlock_irq(&qt2160->lock); 231fde11323SRaphael Derosso Pereira } 232fde11323SRaphael Derosso Pereira 233fde11323SRaphael Derosso Pereira static void qt2160_worker(struct work_struct *work) 234fde11323SRaphael Derosso Pereira { 235fde11323SRaphael Derosso Pereira struct qt2160_data *qt2160 = 236fde11323SRaphael Derosso Pereira container_of(work, struct qt2160_data, dwork.work); 237fde11323SRaphael Derosso Pereira 238fde11323SRaphael Derosso Pereira dev_dbg(&qt2160->client->dev, "worker\n"); 239fde11323SRaphael Derosso Pereira 240fde11323SRaphael Derosso Pereira qt2160_get_key_matrix(qt2160); 241fde11323SRaphael Derosso Pereira 242fde11323SRaphael Derosso Pereira /* Avoid device lock up by checking every so often */ 243fde11323SRaphael Derosso Pereira qt2160_schedule_read(qt2160); 244fde11323SRaphael Derosso Pereira } 245fde11323SRaphael Derosso Pereira 2465298cc4cSBill Pemberton static int qt2160_read(struct i2c_client *client, u8 reg) 247fde11323SRaphael Derosso Pereira { 248fde11323SRaphael Derosso Pereira int ret; 249fde11323SRaphael Derosso Pereira 250fde11323SRaphael Derosso Pereira ret = i2c_smbus_write_byte(client, reg); 251fde11323SRaphael Derosso Pereira if (ret) { 252fde11323SRaphael Derosso Pereira dev_err(&client->dev, 253fde11323SRaphael Derosso Pereira "couldn't send request. Returned %d\n", ret); 254fde11323SRaphael Derosso Pereira return ret; 255fde11323SRaphael Derosso Pereira } 256fde11323SRaphael Derosso Pereira 257fde11323SRaphael Derosso Pereira ret = i2c_smbus_read_byte(client); 258fde11323SRaphael Derosso Pereira if (ret < 0) { 259fde11323SRaphael Derosso Pereira dev_err(&client->dev, 260fde11323SRaphael Derosso Pereira "couldn't read register. Returned %d\n", ret); 261fde11323SRaphael Derosso Pereira return ret; 262fde11323SRaphael Derosso Pereira } 263fde11323SRaphael Derosso Pereira 264fde11323SRaphael Derosso Pereira return ret; 265fde11323SRaphael Derosso Pereira } 266fde11323SRaphael Derosso Pereira 2675298cc4cSBill Pemberton static int qt2160_write(struct i2c_client *client, u8 reg, u8 data) 268fde11323SRaphael Derosso Pereira { 269a6e8c0a2SJavier Martin int ret; 270fde11323SRaphael Derosso Pereira 271a6e8c0a2SJavier Martin ret = i2c_smbus_write_byte_data(client, reg, data); 272a6e8c0a2SJavier Martin if (ret < 0) 273fde11323SRaphael Derosso Pereira dev_err(&client->dev, 274a6e8c0a2SJavier Martin "couldn't write data. Returned %d\n", ret); 275fde11323SRaphael Derosso Pereira 276a6e8c0a2SJavier Martin return ret; 277fde11323SRaphael Derosso Pereira } 278fde11323SRaphael Derosso Pereira 2790e47e3dcSJavier Martin #ifdef CONFIG_LEDS_CLASS 2800e47e3dcSJavier Martin 2810e47e3dcSJavier Martin static int qt2160_register_leds(struct qt2160_data *qt2160) 2820e47e3dcSJavier Martin { 2830e47e3dcSJavier Martin struct i2c_client *client = qt2160->client; 2840e47e3dcSJavier Martin int ret; 2850e47e3dcSJavier Martin int i; 2860e47e3dcSJavier Martin 2870e47e3dcSJavier Martin for (i = 0; i < QT2160_NUM_LEDS_X; i++) { 2880e47e3dcSJavier Martin struct qt2160_led *led = &qt2160->leds[i]; 2890e47e3dcSJavier Martin 2900e47e3dcSJavier Martin snprintf(led->name, sizeof(led->name), "qt2160:x%d", i); 2910e47e3dcSJavier Martin led->cdev.name = led->name; 292*83cd2030SDmitry Torokhov led->cdev.brightness_set_blocking = qt2160_led_set; 2930e47e3dcSJavier Martin led->cdev.brightness = LED_OFF; 2940e47e3dcSJavier Martin led->id = i; 2950e47e3dcSJavier Martin led->qt2160 = qt2160; 2960e47e3dcSJavier Martin 2970e47e3dcSJavier Martin ret = led_classdev_register(&client->dev, &led->cdev); 2980e47e3dcSJavier Martin if (ret < 0) 2990e47e3dcSJavier Martin return ret; 3000e47e3dcSJavier Martin } 3010e47e3dcSJavier Martin 3020e47e3dcSJavier Martin /* Tur off LEDs */ 3030e47e3dcSJavier Martin qt2160_write(client, QT2160_CMD_DRIVE_X, 0); 3040e47e3dcSJavier Martin qt2160_write(client, QT2160_CMD_PWMEN_X, 0); 3050e47e3dcSJavier Martin qt2160_write(client, QT2160_CMD_PWM_DUTY, 0); 3060e47e3dcSJavier Martin 3070e47e3dcSJavier Martin return 0; 3080e47e3dcSJavier Martin } 3090e47e3dcSJavier Martin 3100e47e3dcSJavier Martin static void qt2160_unregister_leds(struct qt2160_data *qt2160) 3110e47e3dcSJavier Martin { 3120e47e3dcSJavier Martin int i; 3130e47e3dcSJavier Martin 314*83cd2030SDmitry Torokhov for (i = 0; i < QT2160_NUM_LEDS_X; i++) 3150e47e3dcSJavier Martin led_classdev_unregister(&qt2160->leds[i].cdev); 3160e47e3dcSJavier Martin } 3170e47e3dcSJavier Martin 3180e47e3dcSJavier Martin #else 3190e47e3dcSJavier Martin 3200e47e3dcSJavier Martin static inline int qt2160_register_leds(struct qt2160_data *qt2160) 3210e47e3dcSJavier Martin { 3220e47e3dcSJavier Martin return 0; 3230e47e3dcSJavier Martin } 3240e47e3dcSJavier Martin 3250e47e3dcSJavier Martin static inline void qt2160_unregister_leds(struct qt2160_data *qt2160) 3260e47e3dcSJavier Martin { 3270e47e3dcSJavier Martin } 3280e47e3dcSJavier Martin 3290e47e3dcSJavier Martin #endif 330fde11323SRaphael Derosso Pereira 3315298cc4cSBill Pemberton static bool qt2160_identify(struct i2c_client *client) 332fde11323SRaphael Derosso Pereira { 333fde11323SRaphael Derosso Pereira int id, ver, rev; 334fde11323SRaphael Derosso Pereira 335fde11323SRaphael Derosso Pereira /* Read Chid ID to check if chip is valid */ 336fde11323SRaphael Derosso Pereira id = qt2160_read(client, QT2160_CMD_CHIPID); 337fde11323SRaphael Derosso Pereira if (id != QT2160_VALID_CHIPID) { 338fde11323SRaphael Derosso Pereira dev_err(&client->dev, "ID %d not supported\n", id); 339fde11323SRaphael Derosso Pereira return false; 340fde11323SRaphael Derosso Pereira } 341fde11323SRaphael Derosso Pereira 342fde11323SRaphael Derosso Pereira /* Read chip firmware version */ 343fde11323SRaphael Derosso Pereira ver = qt2160_read(client, QT2160_CMD_CODEVER); 344fde11323SRaphael Derosso Pereira if (ver < 0) { 345fde11323SRaphael Derosso Pereira dev_err(&client->dev, "could not get firmware version\n"); 346fde11323SRaphael Derosso Pereira return false; 347fde11323SRaphael Derosso Pereira } 348fde11323SRaphael Derosso Pereira 349fde11323SRaphael Derosso Pereira /* Read chip firmware revision */ 350fde11323SRaphael Derosso Pereira rev = qt2160_read(client, QT2160_CMD_SUBVER); 351fde11323SRaphael Derosso Pereira if (rev < 0) { 352fde11323SRaphael Derosso Pereira dev_err(&client->dev, "could not get firmware revision\n"); 353fde11323SRaphael Derosso Pereira return false; 354fde11323SRaphael Derosso Pereira } 355fde11323SRaphael Derosso Pereira 356fde11323SRaphael Derosso Pereira dev_info(&client->dev, "AT42QT2160 firmware version %d.%d.%d\n", 357fde11323SRaphael Derosso Pereira ver >> 4, ver & 0xf, rev); 358fde11323SRaphael Derosso Pereira 359fde11323SRaphael Derosso Pereira return true; 360fde11323SRaphael Derosso Pereira } 361fde11323SRaphael Derosso Pereira 3625298cc4cSBill Pemberton static int qt2160_probe(struct i2c_client *client, 363fde11323SRaphael Derosso Pereira const struct i2c_device_id *id) 364fde11323SRaphael Derosso Pereira { 365fde11323SRaphael Derosso Pereira struct qt2160_data *qt2160; 366fde11323SRaphael Derosso Pereira struct input_dev *input; 367fde11323SRaphael Derosso Pereira int i; 368fde11323SRaphael Derosso Pereira int error; 369fde11323SRaphael Derosso Pereira 370fde11323SRaphael Derosso Pereira /* Check functionality */ 371fde11323SRaphael Derosso Pereira error = i2c_check_functionality(client->adapter, 372fde11323SRaphael Derosso Pereira I2C_FUNC_SMBUS_BYTE); 373fde11323SRaphael Derosso Pereira if (!error) { 374fde11323SRaphael Derosso Pereira dev_err(&client->dev, "%s adapter not supported\n", 375fde11323SRaphael Derosso Pereira dev_driver_string(&client->adapter->dev)); 376fde11323SRaphael Derosso Pereira return -ENODEV; 377fde11323SRaphael Derosso Pereira } 378fde11323SRaphael Derosso Pereira 379fde11323SRaphael Derosso Pereira if (!qt2160_identify(client)) 380fde11323SRaphael Derosso Pereira return -ENODEV; 381fde11323SRaphael Derosso Pereira 382fde11323SRaphael Derosso Pereira /* Chip is valid and active. Allocate structure */ 383fde11323SRaphael Derosso Pereira qt2160 = kzalloc(sizeof(struct qt2160_data), GFP_KERNEL); 384fde11323SRaphael Derosso Pereira input = input_allocate_device(); 385fde11323SRaphael Derosso Pereira if (!qt2160 || !input) { 386fde11323SRaphael Derosso Pereira dev_err(&client->dev, "insufficient memory\n"); 387fde11323SRaphael Derosso Pereira error = -ENOMEM; 388fde11323SRaphael Derosso Pereira goto err_free_mem; 389fde11323SRaphael Derosso Pereira } 390fde11323SRaphael Derosso Pereira 391fde11323SRaphael Derosso Pereira qt2160->client = client; 392fde11323SRaphael Derosso Pereira qt2160->input = input; 393fde11323SRaphael Derosso Pereira INIT_DELAYED_WORK(&qt2160->dwork, qt2160_worker); 394fde11323SRaphael Derosso Pereira spin_lock_init(&qt2160->lock); 395fde11323SRaphael Derosso Pereira 396fde11323SRaphael Derosso Pereira input->name = "AT42QT2160 Touch Sense Keyboard"; 397fde11323SRaphael Derosso Pereira input->id.bustype = BUS_I2C; 398fde11323SRaphael Derosso Pereira 399fde11323SRaphael Derosso Pereira input->keycode = qt2160->keycodes; 400fde11323SRaphael Derosso Pereira input->keycodesize = sizeof(qt2160->keycodes[0]); 401fde11323SRaphael Derosso Pereira input->keycodemax = ARRAY_SIZE(qt2160_key2code); 402fde11323SRaphael Derosso Pereira 403fde11323SRaphael Derosso Pereira __set_bit(EV_KEY, input->evbit); 404fde11323SRaphael Derosso Pereira __clear_bit(EV_REP, input->evbit); 405fde11323SRaphael Derosso Pereira for (i = 0; i < ARRAY_SIZE(qt2160_key2code); i++) { 406fde11323SRaphael Derosso Pereira qt2160->keycodes[i] = qt2160_key2code[i]; 407fde11323SRaphael Derosso Pereira __set_bit(qt2160_key2code[i], input->keybit); 408fde11323SRaphael Derosso Pereira } 409fde11323SRaphael Derosso Pereira __clear_bit(KEY_RESERVED, input->keybit); 410fde11323SRaphael Derosso Pereira 411fde11323SRaphael Derosso Pereira /* Calibrate device */ 412fde11323SRaphael Derosso Pereira error = qt2160_write(client, QT2160_CMD_CALIBRATE, 1); 413fde11323SRaphael Derosso Pereira if (error) { 414fde11323SRaphael Derosso Pereira dev_err(&client->dev, "failed to calibrate device\n"); 415fde11323SRaphael Derosso Pereira goto err_free_mem; 416fde11323SRaphael Derosso Pereira } 417fde11323SRaphael Derosso Pereira 418fde11323SRaphael Derosso Pereira if (client->irq) { 419fde11323SRaphael Derosso Pereira error = request_irq(client->irq, qt2160_irq, 420fde11323SRaphael Derosso Pereira IRQF_TRIGGER_FALLING, "qt2160", qt2160); 421fde11323SRaphael Derosso Pereira if (error) { 422fde11323SRaphael Derosso Pereira dev_err(&client->dev, 423fde11323SRaphael Derosso Pereira "failed to allocate irq %d\n", client->irq); 424fde11323SRaphael Derosso Pereira goto err_free_mem; 425fde11323SRaphael Derosso Pereira } 426fde11323SRaphael Derosso Pereira } 427fde11323SRaphael Derosso Pereira 4280e47e3dcSJavier Martin error = qt2160_register_leds(qt2160); 4290e47e3dcSJavier Martin if (error) { 4300e47e3dcSJavier Martin dev_err(&client->dev, "Failed to register leds\n"); 4310e47e3dcSJavier Martin goto err_free_irq; 4320e47e3dcSJavier Martin } 4330e47e3dcSJavier Martin 434fde11323SRaphael Derosso Pereira error = input_register_device(qt2160->input); 435fde11323SRaphael Derosso Pereira if (error) { 436fde11323SRaphael Derosso Pereira dev_err(&client->dev, 437fde11323SRaphael Derosso Pereira "Failed to register input device\n"); 4380e47e3dcSJavier Martin goto err_unregister_leds; 439fde11323SRaphael Derosso Pereira } 440fde11323SRaphael Derosso Pereira 441fde11323SRaphael Derosso Pereira i2c_set_clientdata(client, qt2160); 442fde11323SRaphael Derosso Pereira qt2160_schedule_read(qt2160); 443fde11323SRaphael Derosso Pereira 444fde11323SRaphael Derosso Pereira return 0; 445fde11323SRaphael Derosso Pereira 4460e47e3dcSJavier Martin err_unregister_leds: 4470e47e3dcSJavier Martin qt2160_unregister_leds(qt2160); 448fde11323SRaphael Derosso Pereira err_free_irq: 449fde11323SRaphael Derosso Pereira if (client->irq) 450fde11323SRaphael Derosso Pereira free_irq(client->irq, qt2160); 451fde11323SRaphael Derosso Pereira err_free_mem: 452fde11323SRaphael Derosso Pereira input_free_device(input); 453fde11323SRaphael Derosso Pereira kfree(qt2160); 454fde11323SRaphael Derosso Pereira return error; 455fde11323SRaphael Derosso Pereira } 456fde11323SRaphael Derosso Pereira 457e2619cf7SBill Pemberton static int qt2160_remove(struct i2c_client *client) 458fde11323SRaphael Derosso Pereira { 459fde11323SRaphael Derosso Pereira struct qt2160_data *qt2160 = i2c_get_clientdata(client); 460fde11323SRaphael Derosso Pereira 4610e47e3dcSJavier Martin qt2160_unregister_leds(qt2160); 4620e47e3dcSJavier Martin 463fde11323SRaphael Derosso Pereira /* Release IRQ so no queue will be scheduled */ 464fde11323SRaphael Derosso Pereira if (client->irq) 465fde11323SRaphael Derosso Pereira free_irq(client->irq, qt2160); 466fde11323SRaphael Derosso Pereira 467fde11323SRaphael Derosso Pereira cancel_delayed_work_sync(&qt2160->dwork); 468fde11323SRaphael Derosso Pereira 469fde11323SRaphael Derosso Pereira input_unregister_device(qt2160->input); 470fde11323SRaphael Derosso Pereira kfree(qt2160); 471fde11323SRaphael Derosso Pereira 472fde11323SRaphael Derosso Pereira return 0; 473fde11323SRaphael Derosso Pereira } 474fde11323SRaphael Derosso Pereira 475ce7b39a1SMárton Németh static const struct i2c_device_id qt2160_idtable[] = { 476fde11323SRaphael Derosso Pereira { "qt2160", 0, }, 477fde11323SRaphael Derosso Pereira { } 478fde11323SRaphael Derosso Pereira }; 479fde11323SRaphael Derosso Pereira 480fde11323SRaphael Derosso Pereira MODULE_DEVICE_TABLE(i2c, qt2160_idtable); 481fde11323SRaphael Derosso Pereira 482fde11323SRaphael Derosso Pereira static struct i2c_driver qt2160_driver = { 483fde11323SRaphael Derosso Pereira .driver = { 484fde11323SRaphael Derosso Pereira .name = "qt2160", 485fde11323SRaphael Derosso Pereira }, 486fde11323SRaphael Derosso Pereira 487fde11323SRaphael Derosso Pereira .id_table = qt2160_idtable, 488fde11323SRaphael Derosso Pereira .probe = qt2160_probe, 4891cb0aa88SBill Pemberton .remove = qt2160_remove, 490fde11323SRaphael Derosso Pereira }; 491fde11323SRaphael Derosso Pereira 4921b92c1cfSAxel Lin module_i2c_driver(qt2160_driver); 493fde11323SRaphael Derosso Pereira 494fde11323SRaphael Derosso Pereira MODULE_AUTHOR("Raphael Derosso Pereira <raphaelpereira@gmail.com>"); 495fde11323SRaphael Derosso Pereira MODULE_DESCRIPTION("Driver for AT42QT2160 Touch Sensor"); 496fde11323SRaphael Derosso Pereira MODULE_LICENSE("GPL"); 497