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 2000 /* msec - 2 sec */ 36 37 static 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 45 struct 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 54 struct qt2160_data { 55 struct i2c_client *client; 56 struct input_dev *input; 57 unsigned short keycodes[ARRAY_SIZE(qt2160_key2code)]; 58 u16 key_matrix; 59 #ifdef CONFIG_LEDS_CLASS 60 struct qt2160_led leds[QT2160_NUM_LEDS_X]; 61 #endif 62 }; 63 64 static int qt2160_read(struct i2c_client *client, u8 reg); 65 static int qt2160_write(struct i2c_client *client, u8 reg, u8 data); 66 67 #ifdef CONFIG_LEDS_CLASS 68 69 static int qt2160_led_set(struct led_classdev *cdev, 70 enum led_brightness value) 71 { 72 struct qt2160_led *led = container_of(cdev, struct qt2160_led, cdev); 73 struct qt2160_data *qt2160 = led->qt2160; 74 struct i2c_client *client = qt2160->client; 75 u32 drive, pwmen; 76 77 if (value != led->brightness) { 78 drive = qt2160_read(client, QT2160_CMD_DRIVE_X); 79 pwmen = qt2160_read(client, QT2160_CMD_PWMEN_X); 80 if (value != LED_OFF) { 81 drive |= BIT(led->id); 82 pwmen |= BIT(led->id); 83 84 } else { 85 drive &= ~BIT(led->id); 86 pwmen &= ~BIT(led->id); 87 } 88 qt2160_write(client, QT2160_CMD_DRIVE_X, drive); 89 qt2160_write(client, QT2160_CMD_PWMEN_X, pwmen); 90 91 /* 92 * Changing this register will change the brightness 93 * of every LED in the qt2160. It's a HW limitation. 94 */ 95 if (value != LED_OFF) 96 qt2160_write(client, QT2160_CMD_PWM_DUTY, value); 97 98 led->brightness = value; 99 } 100 101 return 0; 102 } 103 104 #endif /* CONFIG_LEDS_CLASS */ 105 106 static int qt2160_read_block(struct i2c_client *client, 107 u8 inireg, u8 *buffer, unsigned int count) 108 { 109 int error, idx = 0; 110 111 /* 112 * Can't use SMBus block data read. Check for I2C functionality to speed 113 * things up whenever possible. Otherwise we will be forced to read 114 * sequentially. 115 */ 116 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 117 118 error = i2c_smbus_write_byte(client, inireg + idx); 119 if (error) { 120 dev_err(&client->dev, 121 "couldn't send request. Returned %d\n", error); 122 return error; 123 } 124 125 error = i2c_master_recv(client, buffer, count); 126 if (error != count) { 127 dev_err(&client->dev, 128 "couldn't read registers. Returned %d bytes\n", error); 129 return error; 130 } 131 } else { 132 133 while (count--) { 134 int data; 135 136 error = i2c_smbus_write_byte(client, inireg + idx); 137 if (error) { 138 dev_err(&client->dev, 139 "couldn't send request. Returned %d\n", error); 140 return error; 141 } 142 143 data = i2c_smbus_read_byte(client); 144 if (data < 0) { 145 dev_err(&client->dev, 146 "couldn't read register. Returned %d\n", data); 147 return data; 148 } 149 150 buffer[idx++] = data; 151 } 152 } 153 154 return 0; 155 } 156 157 static void qt2160_get_key_matrix(struct input_dev *input) 158 { 159 struct qt2160_data *qt2160 = input_get_drvdata(input); 160 struct i2c_client *client = qt2160->client; 161 u8 regs[6]; 162 u16 old_matrix, new_matrix; 163 int ret, i, mask; 164 165 dev_dbg(&client->dev, "requesting keys...\n"); 166 167 /* 168 * Read all registers from General Status Register 169 * to GPIOs register 170 */ 171 ret = qt2160_read_block(client, QT2160_CMD_GSTAT, regs, 6); 172 if (ret) { 173 dev_err(&client->dev, 174 "could not perform chip read.\n"); 175 return; 176 } 177 178 old_matrix = qt2160->key_matrix; 179 qt2160->key_matrix = new_matrix = (regs[2] << 8) | regs[1]; 180 181 mask = 0x01; 182 for (i = 0; i < 16; ++i, mask <<= 1) { 183 int keyval = new_matrix & mask; 184 185 if ((old_matrix & mask) != keyval) { 186 input_report_key(input, qt2160->keycodes[i], keyval); 187 dev_dbg(&client->dev, "key %d %s\n", 188 i, keyval ? "pressed" : "released"); 189 } 190 } 191 192 input_sync(input); 193 } 194 195 static irqreturn_t qt2160_irq(int irq, void *data) 196 { 197 struct input_dev *input = data; 198 199 qt2160_get_key_matrix(input); 200 201 return IRQ_HANDLED; 202 } 203 204 static int qt2160_read(struct i2c_client *client, u8 reg) 205 { 206 int ret; 207 208 ret = i2c_smbus_write_byte(client, reg); 209 if (ret) { 210 dev_err(&client->dev, 211 "couldn't send request. Returned %d\n", ret); 212 return ret; 213 } 214 215 ret = i2c_smbus_read_byte(client); 216 if (ret < 0) { 217 dev_err(&client->dev, 218 "couldn't read register. Returned %d\n", ret); 219 return ret; 220 } 221 222 return ret; 223 } 224 225 static int qt2160_write(struct i2c_client *client, u8 reg, u8 data) 226 { 227 int ret; 228 229 ret = i2c_smbus_write_byte_data(client, reg, data); 230 if (ret < 0) 231 dev_err(&client->dev, 232 "couldn't write data. Returned %d\n", ret); 233 234 return ret; 235 } 236 237 #ifdef CONFIG_LEDS_CLASS 238 239 static int qt2160_register_leds(struct qt2160_data *qt2160) 240 { 241 struct i2c_client *client = qt2160->client; 242 int error; 243 int i; 244 245 for (i = 0; i < QT2160_NUM_LEDS_X; i++) { 246 struct qt2160_led *led = &qt2160->leds[i]; 247 248 snprintf(led->name, sizeof(led->name), "qt2160:x%d", i); 249 led->cdev.name = led->name; 250 led->cdev.brightness_set_blocking = qt2160_led_set; 251 led->cdev.brightness = LED_OFF; 252 led->id = i; 253 led->qt2160 = qt2160; 254 255 error = devm_led_classdev_register(&client->dev, &led->cdev); 256 if (error) 257 return error; 258 } 259 260 /* Tur off LEDs */ 261 qt2160_write(client, QT2160_CMD_DRIVE_X, 0); 262 qt2160_write(client, QT2160_CMD_PWMEN_X, 0); 263 qt2160_write(client, QT2160_CMD_PWM_DUTY, 0); 264 265 return 0; 266 } 267 268 #else 269 270 static inline int qt2160_register_leds(struct qt2160_data *qt2160) 271 { 272 return 0; 273 } 274 275 #endif 276 277 static bool qt2160_identify(struct i2c_client *client) 278 { 279 int id, ver, rev; 280 281 /* Read Chid ID to check if chip is valid */ 282 id = qt2160_read(client, QT2160_CMD_CHIPID); 283 if (id != QT2160_VALID_CHIPID) { 284 dev_err(&client->dev, "ID %d not supported\n", id); 285 return false; 286 } 287 288 /* Read chip firmware version */ 289 ver = qt2160_read(client, QT2160_CMD_CODEVER); 290 if (ver < 0) { 291 dev_err(&client->dev, "could not get firmware version\n"); 292 return false; 293 } 294 295 /* Read chip firmware revision */ 296 rev = qt2160_read(client, QT2160_CMD_SUBVER); 297 if (rev < 0) { 298 dev_err(&client->dev, "could not get firmware revision\n"); 299 return false; 300 } 301 302 dev_info(&client->dev, "AT42QT2160 firmware version %d.%d.%d\n", 303 ver >> 4, ver & 0xf, rev); 304 305 return true; 306 } 307 308 static int qt2160_probe(struct i2c_client *client) 309 { 310 struct qt2160_data *qt2160; 311 struct input_dev *input; 312 int i; 313 int error; 314 315 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) { 316 dev_err(&client->dev, "%s adapter not supported\n", 317 dev_driver_string(&client->adapter->dev)); 318 return -ENODEV; 319 } 320 321 if (!qt2160_identify(client)) 322 return -ENODEV; 323 324 /* Chip is valid and active. Allocate structure */ 325 qt2160 = devm_kzalloc(&client->dev, sizeof(*qt2160), GFP_KERNEL); 326 if (!qt2160) 327 return -ENOMEM; 328 329 input = devm_input_allocate_device(&client->dev); 330 if (!input) 331 return -ENOMEM; 332 333 qt2160->client = client; 334 qt2160->input = input; 335 336 input->name = "AT42QT2160 Touch Sense Keyboard"; 337 input->id.bustype = BUS_I2C; 338 339 input->keycode = qt2160->keycodes; 340 input->keycodesize = sizeof(qt2160->keycodes[0]); 341 input->keycodemax = ARRAY_SIZE(qt2160_key2code); 342 343 __set_bit(EV_KEY, input->evbit); 344 __clear_bit(EV_REP, input->evbit); 345 for (i = 0; i < ARRAY_SIZE(qt2160_key2code); i++) { 346 qt2160->keycodes[i] = qt2160_key2code[i]; 347 __set_bit(qt2160_key2code[i], input->keybit); 348 } 349 __clear_bit(KEY_RESERVED, input->keybit); 350 351 input_set_drvdata(input, qt2160); 352 353 /* Calibrate device */ 354 error = qt2160_write(client, QT2160_CMD_CALIBRATE, 1); 355 if (error) { 356 dev_err(&client->dev, "failed to calibrate device\n"); 357 return error; 358 } 359 360 if (client->irq) { 361 error = devm_request_threaded_irq(&client->dev, client->irq, 362 NULL, qt2160_irq, 363 IRQF_ONESHOT, 364 "qt2160", input); 365 if (error) { 366 dev_err(&client->dev, 367 "failed to allocate irq %d\n", client->irq); 368 return error; 369 } 370 } else { 371 error = input_setup_polling(input, qt2160_get_key_matrix); 372 if (error) { 373 dev_err(&client->dev, "Failed to setup polling\n"); 374 return error; 375 } 376 input_set_poll_interval(input, QT2160_CYCLE_INTERVAL); 377 } 378 379 error = qt2160_register_leds(qt2160); 380 if (error) { 381 dev_err(&client->dev, "Failed to register leds\n"); 382 return error; 383 } 384 385 error = input_register_device(qt2160->input); 386 if (error) { 387 dev_err(&client->dev, 388 "Failed to register input device\n"); 389 return error; 390 } 391 392 return 0; 393 } 394 395 static const struct i2c_device_id qt2160_idtable[] = { 396 { "qt2160", 0, }, 397 { } 398 }; 399 400 MODULE_DEVICE_TABLE(i2c, qt2160_idtable); 401 402 static struct i2c_driver qt2160_driver = { 403 .driver = { 404 .name = "qt2160", 405 }, 406 407 .id_table = qt2160_idtable, 408 .probe = qt2160_probe, 409 }; 410 411 module_i2c_driver(qt2160_driver); 412 413 MODULE_AUTHOR("Raphael Derosso Pereira <raphaelpereira@gmail.com>"); 414 MODULE_DESCRIPTION("Driver for AT42QT2160 Touch Sensor"); 415 MODULE_LICENSE("GPL"); 416