qt2160.c (10766B)
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");