Commit 43c4d13e901a8f37d9abbd410f093ebe885b5322

Authored by Simon Budig
Committed by Dmitry Torokhov
1 parent 07b8481d4a

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>

Showing 5 changed files with 990 additions and 0 deletions Side-by-side Diff

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.
drivers/input/touchscreen/Kconfig
... ... @@ -472,6 +472,19 @@
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
drivers/input/touchscreen/Makefile
... ... @@ -24,6 +24,7 @@
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
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");
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 */