Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: add driver for FT5x06 based EDT displays

This is a driver for the EDT "Polytouch" family of touch controllers
based on the FocalTech FT5x06 line of chips.

Signed-off-by: Simon Budig <simon.budig@kernelconcepts.de>
Reviewed-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Simon Budig and committed by
Dmitry Torokhov
43c4d13e 07b8481d

+990
+54
Documentation/input/edt-ft5x06.txt
··· 1 + EDT ft5x06 based Polytouch devices 2 + ---------------------------------- 3 + 4 + The edt-ft5x06 driver is useful for the EDT "Polytouch" family of capacitive 5 + touch screens. Note that it is *not* suitable for other devices based on the 6 + focaltec ft5x06 devices, since they contain vendor-specific firmware. In 7 + particular this driver is not suitable for the Nook tablet. 8 + 9 + It has been tested with the following devices: 10 + * EP0350M06 11 + * EP0430M06 12 + * EP0570M06 13 + * EP0700M06 14 + 15 + The driver allows configuration of the touch screen via a set of sysfs files: 16 + 17 + /sys/class/input/eventX/device/device/threshold: 18 + allows setting the "click"-threshold in the range from 20 to 80. 19 + 20 + /sys/class/input/eventX/device/device/gain: 21 + allows setting the sensitivity in the range from 0 to 31. Note that 22 + lower values indicate higher sensitivity. 23 + 24 + /sys/class/input/eventX/device/device/offset: 25 + allows setting the edge compensation in the range from 0 to 31. 26 + 27 + /sys/class/input/eventX/device/device/report_rate: 28 + allows setting the report rate in the range from 3 to 14. 29 + 30 + 31 + For debugging purposes the driver provides a few files in the debug 32 + filesystem (if available in the kernel). In /sys/kernel/debug/edt_ft5x06 33 + you'll find the following files: 34 + 35 + num_x, num_y: 36 + (readonly) contains the number of sensor fields in X- and 37 + Y-direction. 38 + 39 + mode: 40 + allows switching the sensor between "factory mode" and "operation 41 + mode" by writing "1" or "0" to it. In factory mode (1) it is 42 + possible to get the raw data from the sensor. Note that in factory 43 + mode regular events don't get delivered and the options described 44 + above are unavailable. 45 + 46 + raw_data: 47 + contains num_x * num_y big endian 16 bit values describing the raw 48 + values for each sensor field. Note that each read() call on this 49 + files triggers a new readout. It is recommended to provide a buffer 50 + big enough to contain num_x * num_y * 2 bytes. 51 + 52 + Note that reading raw_data gives a I/O error when the device is not in factory 53 + mode. The same happens when reading/writing to the parameter files when the 54 + device is not in regular operation mode.
+13
drivers/input/touchscreen/Kconfig
··· 472 472 To compile this driver as a module, choose M here: the 473 473 module will be called penmount. 474 474 475 + config TOUCHSCREEN_EDT_FT5X06 476 + tristate "EDT FocalTech FT5x06 I2C Touchscreen support" 477 + depends on I2C 478 + help 479 + Say Y here if you have an EDT "Polytouch" touchscreen based 480 + on the FocalTech FT5x06 family of controllers connected to 481 + your system. 482 + 483 + If unsure, say N. 484 + 485 + To compile this driver as a module, choose M here: the 486 + module will be called edt-ft5x06. 487 + 475 488 config TOUCHSCREEN_MIGOR 476 489 tristate "Renesas MIGO-R touchscreen" 477 490 depends on SH_MIGOR && I2C
+1
drivers/input/touchscreen/Makefile
··· 24 24 obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o 25 25 obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o 26 26 obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o 27 + obj-$(CONFIG_TOUCHSCREEN_EDT_FT5X06) += edt-ft5x06.o 27 28 obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o 28 29 obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o 29 30 obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o
+898
drivers/input/touchscreen/edt-ft5x06.c
··· 1 + /* 2 + * Copyright (C) 2012 Simon Budig, <simon.budig@kernelconcepts.de> 3 + * 4 + * This software is licensed under the terms of the GNU General Public 5 + * License version 2, as published by the Free Software Foundation, and 6 + * may be copied, distributed, and modified under those terms. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + * 13 + * You should have received a copy of the GNU General Public 14 + * License along with this library; if not, write to the Free Software 15 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 + */ 17 + 18 + /* 19 + * This is a driver for the EDT "Polytouch" family of touch controllers 20 + * based on the FocalTech FT5x06 line of chips. 21 + * 22 + * Development of this driver has been sponsored by Glyn: 23 + * http://www.glyn.com/Products/Displays 24 + */ 25 + 26 + #include <linux/module.h> 27 + #include <linux/ratelimit.h> 28 + #include <linux/interrupt.h> 29 + #include <linux/input.h> 30 + #include <linux/i2c.h> 31 + #include <linux/uaccess.h> 32 + #include <linux/delay.h> 33 + #include <linux/debugfs.h> 34 + #include <linux/slab.h> 35 + #include <linux/gpio.h> 36 + #include <linux/input/mt.h> 37 + #include <linux/input/edt-ft5x06.h> 38 + 39 + #define MAX_SUPPORT_POINTS 5 40 + 41 + #define WORK_REGISTER_THRESHOLD 0x00 42 + #define WORK_REGISTER_REPORT_RATE 0x08 43 + #define WORK_REGISTER_GAIN 0x30 44 + #define WORK_REGISTER_OFFSET 0x31 45 + #define WORK_REGISTER_NUM_X 0x33 46 + #define WORK_REGISTER_NUM_Y 0x34 47 + 48 + #define WORK_REGISTER_OPMODE 0x3c 49 + #define FACTORY_REGISTER_OPMODE 0x01 50 + 51 + #define TOUCH_EVENT_DOWN 0x00 52 + #define TOUCH_EVENT_UP 0x01 53 + #define TOUCH_EVENT_ON 0x02 54 + #define TOUCH_EVENT_RESERVED 0x03 55 + 56 + #define EDT_NAME_LEN 23 57 + #define EDT_SWITCH_MODE_RETRIES 10 58 + #define EDT_SWITCH_MODE_DELAY 5 /* msec */ 59 + #define EDT_RAW_DATA_RETRIES 100 60 + #define EDT_RAW_DATA_DELAY 1 /* msec */ 61 + 62 + struct edt_ft5x06_ts_data { 63 + struct i2c_client *client; 64 + struct input_dev *input; 65 + u16 num_x; 66 + u16 num_y; 67 + 68 + #if defined(CONFIG_DEBUG_FS) 69 + struct dentry *debug_dir; 70 + u8 *raw_buffer; 71 + size_t raw_bufsize; 72 + #endif 73 + 74 + struct mutex mutex; 75 + bool factory_mode; 76 + int threshold; 77 + int gain; 78 + int offset; 79 + int report_rate; 80 + 81 + char name[EDT_NAME_LEN]; 82 + }; 83 + 84 + static int edt_ft5x06_ts_readwrite(struct i2c_client *client, 85 + u16 wr_len, u8 *wr_buf, 86 + u16 rd_len, u8 *rd_buf) 87 + { 88 + struct i2c_msg wrmsg[2]; 89 + int i = 0; 90 + int ret; 91 + 92 + if (wr_len) { 93 + wrmsg[i].addr = client->addr; 94 + wrmsg[i].flags = 0; 95 + wrmsg[i].len = wr_len; 96 + wrmsg[i].buf = wr_buf; 97 + i++; 98 + } 99 + if (rd_len) { 100 + wrmsg[i].addr = client->addr; 101 + wrmsg[i].flags = I2C_M_RD; 102 + wrmsg[i].len = rd_len; 103 + wrmsg[i].buf = rd_buf; 104 + i++; 105 + } 106 + 107 + ret = i2c_transfer(client->adapter, wrmsg, i); 108 + if (ret < 0) 109 + return ret; 110 + if (ret != i) 111 + return -EIO; 112 + 113 + return 0; 114 + } 115 + 116 + static bool edt_ft5x06_ts_check_crc(struct edt_ft5x06_ts_data *tsdata, 117 + u8 *buf, int buflen) 118 + { 119 + int i; 120 + u8 crc = 0; 121 + 122 + for (i = 0; i < buflen - 1; i++) 123 + crc ^= buf[i]; 124 + 125 + if (crc != buf[buflen-1]) { 126 + dev_err_ratelimited(&tsdata->client->dev, 127 + "crc error: 0x%02x expected, got 0x%02x\n", 128 + crc, buf[buflen-1]); 129 + return false; 130 + } 131 + 132 + return true; 133 + } 134 + 135 + static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) 136 + { 137 + struct edt_ft5x06_ts_data *tsdata = dev_id; 138 + struct device *dev = &tsdata->client->dev; 139 + u8 cmd = 0xf9; 140 + u8 rdbuf[26]; 141 + int i, type, x, y, id; 142 + int error; 143 + 144 + memset(rdbuf, 0, sizeof(rdbuf)); 145 + 146 + error = edt_ft5x06_ts_readwrite(tsdata->client, 147 + sizeof(cmd), &cmd, 148 + sizeof(rdbuf), rdbuf); 149 + if (error) { 150 + dev_err_ratelimited(dev, "Unable to fetch data, error: %d\n", 151 + error); 152 + goto out; 153 + } 154 + 155 + if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa || rdbuf[2] != 26) { 156 + dev_err_ratelimited(dev, "Unexpected header: %02x%02x%02x!\n", 157 + rdbuf[0], rdbuf[1], rdbuf[2]); 158 + goto out; 159 + } 160 + 161 + if (!edt_ft5x06_ts_check_crc(tsdata, rdbuf, 26)) 162 + goto out; 163 + 164 + for (i = 0; i < MAX_SUPPORT_POINTS; i++) { 165 + u8 *buf = &rdbuf[i * 4 + 5]; 166 + bool down; 167 + 168 + type = buf[0] >> 6; 169 + /* ignore Reserved events */ 170 + if (type == TOUCH_EVENT_RESERVED) 171 + continue; 172 + 173 + x = ((buf[0] << 8) | buf[1]) & 0x0fff; 174 + y = ((buf[2] << 8) | buf[3]) & 0x0fff; 175 + id = (buf[2] >> 4) & 0x0f; 176 + down = (type != TOUCH_EVENT_UP); 177 + 178 + input_mt_slot(tsdata->input, id); 179 + input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER, down); 180 + 181 + if (!down) 182 + continue; 183 + 184 + input_report_abs(tsdata->input, ABS_MT_POSITION_X, x); 185 + input_report_abs(tsdata->input, ABS_MT_POSITION_Y, y); 186 + } 187 + 188 + input_mt_report_pointer_emulation(tsdata->input, true); 189 + input_sync(tsdata->input); 190 + 191 + out: 192 + return IRQ_HANDLED; 193 + } 194 + 195 + static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata, 196 + u8 addr, u8 value) 197 + { 198 + u8 wrbuf[4]; 199 + 200 + wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; 201 + wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; 202 + wrbuf[2] = value; 203 + wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2]; 204 + 205 + return edt_ft5x06_ts_readwrite(tsdata->client, 4, wrbuf, 0, NULL); 206 + } 207 + 208 + static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata, 209 + u8 addr) 210 + { 211 + u8 wrbuf[2], rdbuf[2]; 212 + int error; 213 + 214 + wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; 215 + wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; 216 + wrbuf[1] |= tsdata->factory_mode ? 0x80 : 0x40; 217 + 218 + error = edt_ft5x06_ts_readwrite(tsdata->client, 2, wrbuf, 2, rdbuf); 219 + if (error) 220 + return error; 221 + 222 + if ((wrbuf[0] ^ wrbuf[1] ^ rdbuf[0]) != rdbuf[1]) { 223 + dev_err(&tsdata->client->dev, 224 + "crc error: 0x%02x expected, got 0x%02x\n", 225 + wrbuf[0] ^ wrbuf[1] ^ rdbuf[0], rdbuf[1]); 226 + return -EIO; 227 + } 228 + 229 + return rdbuf[0]; 230 + } 231 + 232 + struct edt_ft5x06_attribute { 233 + struct device_attribute dattr; 234 + size_t field_offset; 235 + u8 limit_low; 236 + u8 limit_high; 237 + u8 addr; 238 + }; 239 + 240 + #define EDT_ATTR(_field, _mode, _addr, _limit_low, _limit_high) \ 241 + struct edt_ft5x06_attribute edt_ft5x06_attr_##_field = { \ 242 + .dattr = __ATTR(_field, _mode, \ 243 + edt_ft5x06_setting_show, \ 244 + edt_ft5x06_setting_store), \ 245 + .field_offset = \ 246 + offsetof(struct edt_ft5x06_ts_data, _field), \ 247 + .limit_low = _limit_low, \ 248 + .limit_high = _limit_high, \ 249 + .addr = _addr, \ 250 + } 251 + 252 + static ssize_t edt_ft5x06_setting_show(struct device *dev, 253 + struct device_attribute *dattr, 254 + char *buf) 255 + { 256 + struct i2c_client *client = to_i2c_client(dev); 257 + struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); 258 + struct edt_ft5x06_attribute *attr = 259 + container_of(dattr, struct edt_ft5x06_attribute, dattr); 260 + u8 *field = (u8 *)((char *)tsdata + attr->field_offset); 261 + int val; 262 + size_t count = 0; 263 + int error = 0; 264 + 265 + mutex_lock(&tsdata->mutex); 266 + 267 + if (tsdata->factory_mode) { 268 + error = -EIO; 269 + goto out; 270 + } 271 + 272 + val = edt_ft5x06_register_read(tsdata, attr->addr); 273 + if (val < 0) { 274 + error = val; 275 + dev_err(&tsdata->client->dev, 276 + "Failed to fetch attribute %s, error %d\n", 277 + dattr->attr.name, error); 278 + goto out; 279 + } 280 + 281 + if (val != *field) { 282 + dev_warn(&tsdata->client->dev, 283 + "%s: read (%d) and stored value (%d) differ\n", 284 + dattr->attr.name, val, *field); 285 + *field = val; 286 + } 287 + 288 + count = scnprintf(buf, PAGE_SIZE, "%d\n", val); 289 + out: 290 + mutex_unlock(&tsdata->mutex); 291 + return error ?: count; 292 + } 293 + 294 + static ssize_t edt_ft5x06_setting_store(struct device *dev, 295 + struct device_attribute *dattr, 296 + const char *buf, size_t count) 297 + { 298 + struct i2c_client *client = to_i2c_client(dev); 299 + struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); 300 + struct edt_ft5x06_attribute *attr = 301 + container_of(dattr, struct edt_ft5x06_attribute, dattr); 302 + u8 *field = (u8 *)((char *)tsdata + attr->field_offset); 303 + unsigned int val; 304 + int error; 305 + 306 + mutex_lock(&tsdata->mutex); 307 + 308 + if (tsdata->factory_mode) { 309 + error = -EIO; 310 + goto out; 311 + } 312 + 313 + error = kstrtouint(buf, 0, &val); 314 + if (error) 315 + goto out; 316 + 317 + if (val < attr->limit_low || val > attr->limit_high) { 318 + error = -ERANGE; 319 + goto out; 320 + } 321 + 322 + error = edt_ft5x06_register_write(tsdata, attr->addr, val); 323 + if (error) { 324 + dev_err(&tsdata->client->dev, 325 + "Failed to update attribute %s, error: %d\n", 326 + dattr->attr.name, error); 327 + goto out; 328 + } 329 + 330 + *field = val; 331 + 332 + out: 333 + mutex_unlock(&tsdata->mutex); 334 + return error ?: count; 335 + } 336 + 337 + static EDT_ATTR(gain, S_IWUSR | S_IRUGO, WORK_REGISTER_GAIN, 0, 31); 338 + static EDT_ATTR(offset, S_IWUSR | S_IRUGO, WORK_REGISTER_OFFSET, 0, 31); 339 + static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, 340 + WORK_REGISTER_THRESHOLD, 20, 80); 341 + static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, 342 + WORK_REGISTER_REPORT_RATE, 3, 14); 343 + 344 + static struct attribute *edt_ft5x06_attrs[] = { 345 + &edt_ft5x06_attr_gain.dattr.attr, 346 + &edt_ft5x06_attr_offset.dattr.attr, 347 + &edt_ft5x06_attr_threshold.dattr.attr, 348 + &edt_ft5x06_attr_report_rate.dattr.attr, 349 + NULL 350 + }; 351 + 352 + static const struct attribute_group edt_ft5x06_attr_group = { 353 + .attrs = edt_ft5x06_attrs, 354 + }; 355 + 356 + #ifdef CONFIG_DEBUG_FS 357 + static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata) 358 + { 359 + struct i2c_client *client = tsdata->client; 360 + int retries = EDT_SWITCH_MODE_RETRIES; 361 + int ret; 362 + int error; 363 + 364 + disable_irq(client->irq); 365 + 366 + if (!tsdata->raw_buffer) { 367 + tsdata->raw_bufsize = tsdata->num_x * tsdata->num_y * 368 + sizeof(u16); 369 + tsdata->raw_buffer = kzalloc(tsdata->raw_bufsize, GFP_KERNEL); 370 + if (!tsdata->raw_buffer) { 371 + error = -ENOMEM; 372 + goto err_out; 373 + } 374 + } 375 + 376 + /* mode register is 0x3c when in the work mode */ 377 + error = edt_ft5x06_register_write(tsdata, WORK_REGISTER_OPMODE, 0x03); 378 + if (error) { 379 + dev_err(&client->dev, 380 + "failed to switch to factory mode, error %d\n", error); 381 + goto err_out; 382 + } 383 + 384 + tsdata->factory_mode = true; 385 + do { 386 + mdelay(EDT_SWITCH_MODE_DELAY); 387 + /* mode register is 0x01 when in factory mode */ 388 + ret = edt_ft5x06_register_read(tsdata, FACTORY_REGISTER_OPMODE); 389 + if (ret == 0x03) 390 + break; 391 + } while (--retries > 0); 392 + 393 + if (retries == 0) { 394 + dev_err(&client->dev, "not in factory mode after %dms.\n", 395 + EDT_SWITCH_MODE_RETRIES * EDT_SWITCH_MODE_DELAY); 396 + error = -EIO; 397 + goto err_out; 398 + } 399 + 400 + return 0; 401 + 402 + err_out: 403 + kfree(tsdata->raw_buffer); 404 + tsdata->raw_buffer = NULL; 405 + tsdata->factory_mode = false; 406 + enable_irq(client->irq); 407 + 408 + return error; 409 + } 410 + 411 + static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata) 412 + { 413 + struct i2c_client *client = tsdata->client; 414 + int retries = EDT_SWITCH_MODE_RETRIES; 415 + int ret; 416 + int error; 417 + 418 + /* mode register is 0x01 when in the factory mode */ 419 + error = edt_ft5x06_register_write(tsdata, FACTORY_REGISTER_OPMODE, 0x1); 420 + if (error) { 421 + dev_err(&client->dev, 422 + "failed to switch to work mode, error: %d\n", error); 423 + return error; 424 + } 425 + 426 + tsdata->factory_mode = false; 427 + 428 + do { 429 + mdelay(EDT_SWITCH_MODE_DELAY); 430 + /* mode register is 0x01 when in factory mode */ 431 + ret = edt_ft5x06_register_read(tsdata, WORK_REGISTER_OPMODE); 432 + if (ret == 0x01) 433 + break; 434 + } while (--retries > 0); 435 + 436 + if (retries == 0) { 437 + dev_err(&client->dev, "not in work mode after %dms.\n", 438 + EDT_SWITCH_MODE_RETRIES * EDT_SWITCH_MODE_DELAY); 439 + tsdata->factory_mode = true; 440 + return -EIO; 441 + } 442 + 443 + if (tsdata->raw_buffer) 444 + kfree(tsdata->raw_buffer); 445 + tsdata->raw_buffer = NULL; 446 + 447 + /* restore parameters */ 448 + edt_ft5x06_register_write(tsdata, WORK_REGISTER_THRESHOLD, 449 + tsdata->threshold); 450 + edt_ft5x06_register_write(tsdata, WORK_REGISTER_GAIN, 451 + tsdata->gain); 452 + edt_ft5x06_register_write(tsdata, WORK_REGISTER_OFFSET, 453 + tsdata->offset); 454 + edt_ft5x06_register_write(tsdata, WORK_REGISTER_REPORT_RATE, 455 + tsdata->report_rate); 456 + 457 + enable_irq(client->irq); 458 + 459 + return 0; 460 + } 461 + 462 + static int edt_ft5x06_debugfs_mode_get(void *data, u64 *mode) 463 + { 464 + struct edt_ft5x06_ts_data *tsdata = data; 465 + 466 + *mode = tsdata->factory_mode; 467 + 468 + return 0; 469 + }; 470 + 471 + static int edt_ft5x06_debugfs_mode_set(void *data, u64 mode) 472 + { 473 + struct edt_ft5x06_ts_data *tsdata = data; 474 + int retval = 0; 475 + 476 + if (mode > 1) 477 + return -ERANGE; 478 + 479 + mutex_lock(&tsdata->mutex); 480 + 481 + if (mode != tsdata->factory_mode) { 482 + retval = mode ? edt_ft5x06_factory_mode(tsdata) : 483 + edt_ft5x06_work_mode(tsdata); 484 + } 485 + 486 + mutex_unlock(&tsdata->mutex); 487 + 488 + return retval; 489 + }; 490 + 491 + DEFINE_SIMPLE_ATTRIBUTE(debugfs_mode_fops, edt_ft5x06_debugfs_mode_get, 492 + edt_ft5x06_debugfs_mode_set, "%llu\n"); 493 + 494 + static int edt_ft5x06_debugfs_raw_data_open(struct inode *inode, 495 + struct file *file) 496 + { 497 + file->private_data = inode->i_private; 498 + 499 + return 0; 500 + } 501 + 502 + static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file, 503 + char __user *buf, size_t count, loff_t *off) 504 + { 505 + struct edt_ft5x06_ts_data *tsdata = file->private_data; 506 + struct i2c_client *client = tsdata->client; 507 + int retries = EDT_RAW_DATA_RETRIES; 508 + int val, i, error; 509 + size_t read = 0; 510 + int colbytes; 511 + char wrbuf[3]; 512 + u8 *rdbuf; 513 + 514 + if (*off < 0 || *off >= tsdata->raw_bufsize) 515 + return 0; 516 + 517 + mutex_lock(&tsdata->mutex); 518 + 519 + if (!tsdata->factory_mode || !tsdata->raw_buffer) { 520 + error = -EIO; 521 + goto out; 522 + } 523 + 524 + error = edt_ft5x06_register_write(tsdata, 0x08, 0x01); 525 + if (error) { 526 + dev_dbg(&client->dev, 527 + "failed to write 0x08 register, error %d\n", error); 528 + goto out; 529 + } 530 + 531 + do { 532 + msleep(EDT_RAW_DATA_DELAY); 533 + val = edt_ft5x06_register_read(tsdata, 0x08); 534 + if (val < 1) 535 + break; 536 + } while (--retries > 0); 537 + 538 + if (val < 0) { 539 + error = val; 540 + dev_dbg(&client->dev, 541 + "failed to read 0x08 register, error %d\n", error); 542 + goto out; 543 + } 544 + 545 + if (retries == 0) { 546 + dev_dbg(&client->dev, 547 + "timed out waiting for register to settle\n"); 548 + error = -ETIMEDOUT; 549 + goto out; 550 + } 551 + 552 + rdbuf = tsdata->raw_buffer; 553 + colbytes = tsdata->num_y * sizeof(u16); 554 + 555 + wrbuf[0] = 0xf5; 556 + wrbuf[1] = 0x0e; 557 + for (i = 0; i < tsdata->num_x; i++) { 558 + wrbuf[2] = i; /* column index */ 559 + error = edt_ft5x06_ts_readwrite(tsdata->client, 560 + sizeof(wrbuf), wrbuf, 561 + colbytes, rdbuf); 562 + if (error) 563 + goto out; 564 + 565 + rdbuf += colbytes; 566 + } 567 + 568 + read = min_t(size_t, count, tsdata->raw_bufsize - *off); 569 + error = copy_to_user(buf, tsdata->raw_buffer + *off, read); 570 + if (!error) 571 + *off += read; 572 + out: 573 + mutex_unlock(&tsdata->mutex); 574 + return error ?: read; 575 + }; 576 + 577 + 578 + static const struct file_operations debugfs_raw_data_fops = { 579 + .open = edt_ft5x06_debugfs_raw_data_open, 580 + .read = edt_ft5x06_debugfs_raw_data_read, 581 + }; 582 + 583 + static void __devinit 584 + edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata, 585 + const char *debugfs_name) 586 + { 587 + tsdata->debug_dir = debugfs_create_dir(debugfs_name, NULL); 588 + if (!tsdata->debug_dir) 589 + return; 590 + 591 + debugfs_create_u16("num_x", S_IRUSR, tsdata->debug_dir, &tsdata->num_x); 592 + debugfs_create_u16("num_y", S_IRUSR, tsdata->debug_dir, &tsdata->num_y); 593 + 594 + debugfs_create_file("mode", S_IRUSR | S_IWUSR, 595 + tsdata->debug_dir, tsdata, &debugfs_mode_fops); 596 + debugfs_create_file("raw_data", S_IRUSR, 597 + tsdata->debug_dir, tsdata, &debugfs_raw_data_fops); 598 + } 599 + 600 + static void __devexit 601 + edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata) 602 + { 603 + if (tsdata->debug_dir) 604 + debugfs_remove_recursive(tsdata->debug_dir); 605 + } 606 + 607 + #else 608 + 609 + static inline void 610 + edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata, 611 + const char *debugfs_name) 612 + { 613 + } 614 + 615 + static inline void 616 + edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata) 617 + { 618 + } 619 + 620 + #endif /* CONFIG_DEBUGFS */ 621 + 622 + 623 + 624 + static int __devinit edt_ft5x06_ts_reset(struct i2c_client *client, 625 + int reset_pin) 626 + { 627 + int error; 628 + 629 + if (gpio_is_valid(reset_pin)) { 630 + /* this pulls reset down, enabling the low active reset */ 631 + error = gpio_request_one(reset_pin, GPIOF_OUT_INIT_LOW, 632 + "edt-ft5x06 reset"); 633 + if (error) { 634 + dev_err(&client->dev, 635 + "Failed to request GPIO %d as reset pin, error %d\n", 636 + reset_pin, error); 637 + return error; 638 + } 639 + 640 + mdelay(50); 641 + gpio_set_value(reset_pin, 1); 642 + mdelay(100); 643 + } 644 + 645 + return 0; 646 + } 647 + 648 + static int __devinit edt_ft5x06_ts_identify(struct i2c_client *client, 649 + char *model_name, 650 + char *fw_version) 651 + { 652 + u8 rdbuf[EDT_NAME_LEN]; 653 + char *p; 654 + int error; 655 + 656 + error = edt_ft5x06_ts_readwrite(client, 1, "\xbb", 657 + EDT_NAME_LEN - 1, rdbuf); 658 + if (error) 659 + return error; 660 + 661 + /* remove last '$' end marker */ 662 + rdbuf[EDT_NAME_LEN - 1] = '\0'; 663 + if (rdbuf[EDT_NAME_LEN - 2] == '$') 664 + rdbuf[EDT_NAME_LEN - 2] = '\0'; 665 + 666 + /* look for Model/Version separator */ 667 + p = strchr(rdbuf, '*'); 668 + if (p) 669 + *p++ = '\0'; 670 + 671 + strlcpy(model_name, rdbuf + 1, EDT_NAME_LEN); 672 + strlcpy(fw_version, p ? p : "", EDT_NAME_LEN); 673 + 674 + return 0; 675 + } 676 + 677 + #define EDT_ATTR_CHECKSET(name, reg) \ 678 + if (pdata->name >= edt_ft5x06_attr_##name.limit_low && \ 679 + pdata->name <= edt_ft5x06_attr_##name.limit_high) \ 680 + edt_ft5x06_register_write(tsdata, reg, pdata->name) 681 + 682 + static void __devinit 683 + edt_ft5x06_ts_get_defaults(struct edt_ft5x06_ts_data *tsdata, 684 + const struct edt_ft5x06_platform_data *pdata) 685 + { 686 + if (!pdata->use_parameters) 687 + return; 688 + 689 + /* pick up defaults from the platform data */ 690 + EDT_ATTR_CHECKSET(threshold, WORK_REGISTER_THRESHOLD); 691 + EDT_ATTR_CHECKSET(gain, WORK_REGISTER_GAIN); 692 + EDT_ATTR_CHECKSET(offset, WORK_REGISTER_OFFSET); 693 + EDT_ATTR_CHECKSET(report_rate, WORK_REGISTER_REPORT_RATE); 694 + } 695 + 696 + static void __devinit 697 + edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata) 698 + { 699 + tsdata->threshold = edt_ft5x06_register_read(tsdata, 700 + WORK_REGISTER_THRESHOLD); 701 + tsdata->gain = edt_ft5x06_register_read(tsdata, WORK_REGISTER_GAIN); 702 + tsdata->offset = edt_ft5x06_register_read(tsdata, WORK_REGISTER_OFFSET); 703 + tsdata->report_rate = edt_ft5x06_register_read(tsdata, 704 + WORK_REGISTER_REPORT_RATE); 705 + tsdata->num_x = edt_ft5x06_register_read(tsdata, WORK_REGISTER_NUM_X); 706 + tsdata->num_y = edt_ft5x06_register_read(tsdata, WORK_REGISTER_NUM_Y); 707 + } 708 + 709 + static int __devinit edt_ft5x06_ts_probe(struct i2c_client *client, 710 + const struct i2c_device_id *id) 711 + { 712 + const struct edt_ft5x06_platform_data *pdata = 713 + client->dev.platform_data; 714 + struct edt_ft5x06_ts_data *tsdata; 715 + struct input_dev *input; 716 + int error; 717 + char fw_version[EDT_NAME_LEN]; 718 + 719 + dev_dbg(&client->dev, "probing for EDT FT5x06 I2C\n"); 720 + 721 + if (!pdata) { 722 + dev_err(&client->dev, "no platform data?\n"); 723 + return -EINVAL; 724 + } 725 + 726 + error = edt_ft5x06_ts_reset(client, pdata->reset_pin); 727 + if (error) 728 + return error; 729 + 730 + if (gpio_is_valid(pdata->irq_pin)) { 731 + error = gpio_request_one(pdata->irq_pin, 732 + GPIOF_IN, "edt-ft5x06 irq"); 733 + if (error) { 734 + dev_err(&client->dev, 735 + "Failed to request GPIO %d, error %d\n", 736 + pdata->irq_pin, error); 737 + return error; 738 + } 739 + } 740 + 741 + tsdata = kzalloc(sizeof(*tsdata), GFP_KERNEL); 742 + input = input_allocate_device(); 743 + if (!tsdata || !input) { 744 + dev_err(&client->dev, "failed to allocate driver data.\n"); 745 + error = -ENOMEM; 746 + goto err_free_mem; 747 + } 748 + 749 + mutex_init(&tsdata->mutex); 750 + tsdata->client = client; 751 + tsdata->input = input; 752 + tsdata->factory_mode = false; 753 + 754 + error = edt_ft5x06_ts_identify(client, tsdata->name, fw_version); 755 + if (error) { 756 + dev_err(&client->dev, "touchscreen probe failed\n"); 757 + goto err_free_mem; 758 + } 759 + 760 + edt_ft5x06_ts_get_defaults(tsdata, pdata); 761 + edt_ft5x06_ts_get_parameters(tsdata); 762 + 763 + dev_dbg(&client->dev, 764 + "Model \"%s\", Rev. \"%s\", %dx%d sensors\n", 765 + tsdata->name, fw_version, tsdata->num_x, tsdata->num_y); 766 + 767 + input->name = tsdata->name; 768 + input->id.bustype = BUS_I2C; 769 + input->dev.parent = &client->dev; 770 + 771 + __set_bit(EV_SYN, input->evbit); 772 + __set_bit(EV_KEY, input->evbit); 773 + __set_bit(EV_ABS, input->evbit); 774 + __set_bit(BTN_TOUCH, input->keybit); 775 + input_set_abs_params(input, ABS_X, 0, tsdata->num_x * 64 - 1, 0, 0); 776 + input_set_abs_params(input, ABS_Y, 0, tsdata->num_y * 64 - 1, 0, 0); 777 + input_set_abs_params(input, ABS_MT_POSITION_X, 778 + 0, tsdata->num_x * 64 - 1, 0, 0); 779 + input_set_abs_params(input, ABS_MT_POSITION_Y, 780 + 0, tsdata->num_y * 64 - 1, 0, 0); 781 + error = input_mt_init_slots(input, MAX_SUPPORT_POINTS); 782 + if (error) { 783 + dev_err(&client->dev, "Unable to init MT slots.\n"); 784 + goto err_free_mem; 785 + } 786 + 787 + input_set_drvdata(input, tsdata); 788 + i2c_set_clientdata(client, tsdata); 789 + 790 + error = request_threaded_irq(client->irq, NULL, edt_ft5x06_ts_isr, 791 + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 792 + client->name, tsdata); 793 + if (error) { 794 + dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); 795 + goto err_free_mem; 796 + } 797 + 798 + error = sysfs_create_group(&client->dev.kobj, &edt_ft5x06_attr_group); 799 + if (error) 800 + goto err_free_irq; 801 + 802 + error = input_register_device(input); 803 + if (error) 804 + goto err_remove_attrs; 805 + 806 + edt_ft5x06_ts_prepare_debugfs(tsdata, dev_driver_string(&client->dev)); 807 + device_init_wakeup(&client->dev, 1); 808 + 809 + dev_dbg(&client->dev, 810 + "EDT FT5x06 initialized: IRQ pin %d, Reset pin %d.\n", 811 + pdata->irq_pin, pdata->reset_pin); 812 + 813 + return 0; 814 + 815 + err_remove_attrs: 816 + sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group); 817 + err_free_irq: 818 + free_irq(client->irq, tsdata); 819 + err_free_mem: 820 + input_free_device(input); 821 + kfree(tsdata); 822 + 823 + if (gpio_is_valid(pdata->irq_pin)) 824 + gpio_free(pdata->irq_pin); 825 + 826 + return error; 827 + } 828 + 829 + static int __devexit edt_ft5x06_ts_remove(struct i2c_client *client) 830 + { 831 + const struct edt_ft5x06_platform_data *pdata = 832 + dev_get_platdata(&client->dev); 833 + struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); 834 + 835 + edt_ft5x06_ts_teardown_debugfs(tsdata); 836 + sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group); 837 + 838 + free_irq(client->irq, tsdata); 839 + input_unregister_device(tsdata->input); 840 + 841 + if (gpio_is_valid(pdata->irq_pin)) 842 + gpio_free(pdata->irq_pin); 843 + if (gpio_is_valid(pdata->reset_pin)) 844 + gpio_free(pdata->reset_pin); 845 + 846 + kfree(tsdata->raw_buffer); 847 + kfree(tsdata); 848 + 849 + return 0; 850 + } 851 + 852 + #ifdef CONFIG_PM_SLEEP 853 + static int edt_ft5x06_ts_suspend(struct device *dev) 854 + { 855 + struct i2c_client *client = to_i2c_client(dev); 856 + 857 + if (device_may_wakeup(dev)) 858 + enable_irq_wake(client->irq); 859 + 860 + return 0; 861 + } 862 + 863 + static int edt_ft5x06_ts_resume(struct device *dev) 864 + { 865 + struct i2c_client *client = to_i2c_client(dev); 866 + 867 + if (device_may_wakeup(dev)) 868 + disable_irq_wake(client->irq); 869 + 870 + return 0; 871 + } 872 + #endif 873 + 874 + static SIMPLE_DEV_PM_OPS(edt_ft5x06_ts_pm_ops, 875 + edt_ft5x06_ts_suspend, edt_ft5x06_ts_resume); 876 + 877 + static const struct i2c_device_id edt_ft5x06_ts_id[] = { 878 + { "edt-ft5x06", 0 }, 879 + { } 880 + }; 881 + MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id); 882 + 883 + static struct i2c_driver edt_ft5x06_ts_driver = { 884 + .driver = { 885 + .owner = THIS_MODULE, 886 + .name = "edt_ft5x06", 887 + .pm = &edt_ft5x06_ts_pm_ops, 888 + }, 889 + .id_table = edt_ft5x06_ts_id, 890 + .probe = edt_ft5x06_ts_probe, 891 + .remove = __devexit_p(edt_ft5x06_ts_remove), 892 + }; 893 + 894 + module_i2c_driver(edt_ft5x06_ts_driver); 895 + 896 + MODULE_AUTHOR("Simon Budig <simon.budig@kernelconcepts.de>"); 897 + MODULE_DESCRIPTION("EDT FT5x06 I2C Touchscreen Driver"); 898 + MODULE_LICENSE("GPL");
+24
include/linux/input/edt-ft5x06.h
··· 1 + #ifndef _EDT_FT5X06_H 2 + #define _EDT_FT5X06_H 3 + 4 + /* 5 + * Copyright (c) 2012 Simon Budig, <simon.budig@kernelconcepts.de> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published by 9 + * the Free Software Foundation. 10 + */ 11 + 12 + struct edt_ft5x06_platform_data { 13 + int irq_pin; 14 + int reset_pin; 15 + 16 + /* startup defaults for operational parameters */ 17 + bool use_parameters; 18 + u8 gain; 19 + u8 threshold; 20 + u8 offset; 21 + u8 report_rate; 22 + }; 23 + 24 + #endif /* _EDT_FT5X06_H */