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