aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/touchscreen/Kconfig32
-rw-r--r--drivers/input/touchscreen/Makefile5
-rw-r--r--drivers/input/touchscreen/cyttsp_core.c625
-rw-r--r--drivers/input/touchscreen/cyttsp_core.h149
-rw-r--r--drivers/input/touchscreen/cyttsp_i2c.c146
-rw-r--r--drivers/input/touchscreen/cyttsp_spi.c210
-rw-r--r--include/linux/input/cyttsp.h58
7 files changed, 1223 insertions, 2 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 4af2a18eb3b..2b21a7066d3 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -139,7 +139,6 @@ config TOUCHSCREEN_CY8CTMG110
139 tristate "cy8ctmg110 touchscreen" 139 tristate "cy8ctmg110 touchscreen"
140 depends on I2C 140 depends on I2C
141 depends on GPIOLIB 141 depends on GPIOLIB
142
143 help 142 help
144 Say Y here if you have a cy8ctmg110 capacitive touchscreen on 143 Say Y here if you have a cy8ctmg110 capacitive touchscreen on
145 an AAVA device. 144 an AAVA device.
@@ -149,6 +148,37 @@ config TOUCHSCREEN_CY8CTMG110
149 To compile this driver as a module, choose M here: the 148 To compile this driver as a module, choose M here: the
150 module will be called cy8ctmg110_ts. 149 module will be called cy8ctmg110_ts.
151 150
151config TOUCHSCREEN_CYTTSP_CORE
152 tristate "Cypress TTSP touchscreen"
153 help
154 Say Y here if you have a touchscreen using controller from
155 the Cypress TrueTouch(tm) Standard Product family connected
156 to your system. You will also need to select appropriate
157 bus connection below.
158
159 If unsure, say N.
160
161 To compile this driver as a module, choose M here: the
162 module will be called cyttsp_core.
163
164config TOUCHSCREEN_CYTTSP_I2C
165 tristate "support I2C bus connection"
166 depends on TOUCHSCREEN_CYTTSP_CORE && I2C
167 help
168 Say Y here if the touchscreen is connected via I2C bus.
169
170 To compile this driver as a module, choose M here: the
171 module will be called cyttsp_i2c.
172
173config TOUCHSCREEN_CYTTSP_SPI
174 tristate "support SPI bus connection"
175 depends on TOUCHSCREEN_CYTTSP_CORE && SPI_MASTER
176 help
177 Say Y here if the touchscreen is connected via SPI bus.
178
179 To compile this driver as a module, choose M here: the
180 module will be called cyttsp_spi.
181
152config TOUCHSCREEN_DA9034 182config TOUCHSCREEN_DA9034
153 tristate "Touchscreen support for Dialog Semiconductor DA9034" 183 tristate "Touchscreen support for Dialog Semiconductor DA9034"
154 depends on PMIC_DA903X 184 depends on PMIC_DA903X
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 496091e8846..d9acbdcda3d 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -16,8 +16,11 @@ obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o
16obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o 16obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o
17obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o 17obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o
18obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o 18obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
19obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o 19obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
20obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o 20obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o
21obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o
22obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o
23obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o
21obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o 24obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o
22obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o 25obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o
23obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o 26obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o
diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c
new file mode 100644
index 00000000000..8be22479b41
--- /dev/null
+++ b/drivers/input/touchscreen/cyttsp_core.c
@@ -0,0 +1,625 @@
1/*
2 * Core Source for:
3 * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers.
4 * For use with Cypress Txx3xx parts.
5 * Supported parts include:
6 * CY8CTST341
7 * CY8CTMA340
8 *
9 * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
10 * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * version 2, and only version 2, as published by the
15 * Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 *
26 * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com>
27 *
28 */
29
30#include <linux/delay.h>
31#include <linux/input.h>
32#include <linux/input/mt.h>
33#include <linux/gpio.h>
34#include <linux/interrupt.h>
35#include <linux/slab.h>
36
37#include "cyttsp_core.h"
38
39/* Bootloader number of command keys */
40#define CY_NUM_BL_KEYS 8
41
42/* helpers */
43#define GET_NUM_TOUCHES(x) ((x) & 0x0F)
44#define IS_LARGE_AREA(x) (((x) & 0x10) >> 4)
45#define IS_BAD_PKT(x) ((x) & 0x20)
46#define IS_VALID_APP(x) ((x) & 0x01)
47#define IS_OPERATIONAL_ERR(x) ((x) & 0x3F)
48#define GET_HSTMODE(reg) (((reg) & 0x70) >> 4)
49#define GET_BOOTLOADERMODE(reg) (((reg) & 0x10) >> 4)
50
51#define CY_REG_BASE 0x00
52#define CY_REG_ACT_DIST 0x1E
53#define CY_REG_ACT_INTRVL 0x1D
54#define CY_REG_TCH_TMOUT (CY_REG_ACT_INTRVL + 1)
55#define CY_REG_LP_INTRVL (CY_REG_TCH_TMOUT + 1)
56#define CY_MAXZ 255
57#define CY_DELAY_DFLT 20 /* ms */
58#define CY_DELAY_MAX 500
59#define CY_ACT_DIST_DFLT 0xF8
60#define CY_HNDSHK_BIT 0x80
61/* device mode bits */
62#define CY_OPERATE_MODE 0x00
63#define CY_SYSINFO_MODE 0x10
64/* power mode select bits */
65#define CY_SOFT_RESET_MODE 0x01 /* return to Bootloader mode */
66#define CY_DEEP_SLEEP_MODE 0x02
67#define CY_LOW_POWER_MODE 0x04
68
69/* Slots management */
70#define CY_MAX_FINGER 4
71#define CY_MAX_ID 16
72
73static const u8 bl_command[] = {
74 0x00, /* file offset */
75 0xFF, /* command */
76 0xA5, /* exit bootloader command */
77 0, 1, 2, 3, 4, 5, 6, 7 /* default keys */
78};
79
80static int ttsp_read_block_data(struct cyttsp *ts, u8 command,
81 u8 length, void *buf)
82{
83 int error;
84 int tries;
85
86 for (tries = 0; tries < CY_NUM_RETRY; tries++) {
87 error = ts->bus_ops->read(ts, command, length, buf);
88 if (!error)
89 return 0;
90
91 msleep(CY_DELAY_DFLT);
92 }
93
94 return -EIO;
95}
96
97static int ttsp_write_block_data(struct cyttsp *ts, u8 command,
98 u8 length, void *buf)
99{
100 int error;
101 int tries;
102
103 for (tries = 0; tries < CY_NUM_RETRY; tries++) {
104 error = ts->bus_ops->write(ts, command, length, buf);
105 if (!error)
106 return 0;
107
108 msleep(CY_DELAY_DFLT);
109 }
110
111 return -EIO;
112}
113
114static int ttsp_send_command(struct cyttsp *ts, u8 cmd)
115{
116 return ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), &cmd);
117}
118
119static int cyttsp_load_bl_regs(struct cyttsp *ts)
120{
121 memset(&ts->bl_data, 0, sizeof(ts->bl_data));
122 ts->bl_data.bl_status = 0x10;
123
124 return ttsp_read_block_data(ts, CY_REG_BASE,
125 sizeof(ts->bl_data), &ts->bl_data);
126}
127
128static int cyttsp_exit_bl_mode(struct cyttsp *ts)
129{
130 int error;
131 u8 bl_cmd[sizeof(bl_command)];
132
133 memcpy(bl_cmd, bl_command, sizeof(bl_command));
134 if (ts->pdata->bl_keys)
135 memcpy(&bl_cmd[sizeof(bl_command) - CY_NUM_BL_KEYS],
136 ts->pdata->bl_keys, sizeof(bl_command));
137
138 error = ttsp_write_block_data(ts, CY_REG_BASE,
139 sizeof(bl_cmd), bl_cmd);
140 if (error)
141 return error;
142
143 /* wait for TTSP Device to complete the operation */
144 msleep(CY_DELAY_DFLT);
145
146 error = cyttsp_load_bl_regs(ts);
147 if (error)
148 return error;
149
150 if (GET_BOOTLOADERMODE(ts->bl_data.bl_status))
151 return -EIO;
152
153 return 0;
154}
155
156static int cyttsp_set_operational_mode(struct cyttsp *ts)
157{
158 int error;
159
160 error = ttsp_send_command(ts, CY_OPERATE_MODE);
161 if (error)
162 return error;
163
164 /* wait for TTSP Device to complete switch to Operational mode */
165 error = ttsp_read_block_data(ts, CY_REG_BASE,
166 sizeof(ts->xy_data), &ts->xy_data);
167 if (error)
168 return error;
169
170 return ts->xy_data.act_dist == CY_ACT_DIST_DFLT ? -EIO : 0;
171}
172
173static int cyttsp_set_sysinfo_mode(struct cyttsp *ts)
174{
175 int error;
176
177 memset(&ts->sysinfo_data, 0, sizeof(ts->sysinfo_data));
178
179 /* switch to sysinfo mode */
180 error = ttsp_send_command(ts, CY_SYSINFO_MODE);
181 if (error)
182 return error;
183
184 /* read sysinfo registers */
185 msleep(CY_DELAY_DFLT);
186 error = ttsp_read_block_data(ts, CY_REG_BASE, sizeof(ts->sysinfo_data),
187 &ts->sysinfo_data);
188 if (error)
189 return error;
190
191 if (!ts->sysinfo_data.tts_verh && !ts->sysinfo_data.tts_verl)
192 return -EIO;
193
194 return 0;
195}
196
197static int cyttsp_set_sysinfo_regs(struct cyttsp *ts)
198{
199 int retval = 0;
200
201 if (ts->pdata->act_intrvl != CY_ACT_INTRVL_DFLT ||
202 ts->pdata->tch_tmout != CY_TCH_TMOUT_DFLT ||
203 ts->pdata->lp_intrvl != CY_LP_INTRVL_DFLT) {
204
205 u8 intrvl_ray[] = {
206 ts->pdata->act_intrvl,
207 ts->pdata->tch_tmout,
208 ts->pdata->lp_intrvl
209 };
210
211 /* set intrvl registers */
212 retval = ttsp_write_block_data(ts, CY_REG_ACT_INTRVL,
213 sizeof(intrvl_ray), intrvl_ray);
214 msleep(CY_DELAY_DFLT);
215 }
216
217 return retval;
218}
219
220static int cyttsp_soft_reset(struct cyttsp *ts)
221{
222 unsigned long timeout;
223 int retval;
224
225 /* wait for interrupt to set ready completion */
226 INIT_COMPLETION(ts->bl_ready);
227 ts->state = CY_BL_STATE;
228
229 enable_irq(ts->irq);
230
231 retval = ttsp_send_command(ts, CY_SOFT_RESET_MODE);
232 if (retval)
233 goto out;
234
235 timeout = wait_for_completion_timeout(&ts->bl_ready,
236 msecs_to_jiffies(CY_DELAY_DFLT * CY_DELAY_MAX));
237 retval = timeout ? 0 : -EIO;
238
239out:
240 ts->state = CY_IDLE_STATE;
241 disable_irq(ts->irq);
242 return retval;
243}
244
245static int cyttsp_act_dist_setup(struct cyttsp *ts)
246{
247 u8 act_dist_setup = ts->pdata->act_dist;
248
249 /* Init gesture; active distance setup */
250 return ttsp_write_block_data(ts, CY_REG_ACT_DIST,
251 sizeof(act_dist_setup), &act_dist_setup);
252}
253
254static void cyttsp_extract_track_ids(struct cyttsp_xydata *xy_data, int *ids)
255{
256 ids[0] = xy_data->touch12_id >> 4;
257 ids[1] = xy_data->touch12_id & 0xF;
258 ids[2] = xy_data->touch34_id >> 4;
259 ids[3] = xy_data->touch34_id & 0xF;
260}
261
262static const struct cyttsp_tch *cyttsp_get_tch(struct cyttsp_xydata *xy_data,
263 int idx)
264{
265 switch (idx) {
266 case 0:
267 return &xy_data->tch1;
268 case 1:
269 return &xy_data->tch2;
270 case 2:
271 return &xy_data->tch3;
272 case 3:
273 return &xy_data->tch4;
274 default:
275 return NULL;
276 }
277}
278
279static void cyttsp_report_tchdata(struct cyttsp *ts)
280{
281 struct cyttsp_xydata *xy_data = &ts->xy_data;
282 struct input_dev *input = ts->input;
283 int num_tch = GET_NUM_TOUCHES(xy_data->tt_stat);
284 const struct cyttsp_tch *tch;
285 int ids[CY_MAX_ID];
286 int i;
287 DECLARE_BITMAP(used, CY_MAX_ID);
288
289 if (IS_LARGE_AREA(xy_data->tt_stat) == 1) {
290 /* terminate all active tracks */
291 num_tch = 0;
292 dev_dbg(ts->dev, "%s: Large area detected\n", __func__);
293 } else if (num_tch > CY_MAX_FINGER) {
294 /* terminate all active tracks */
295 num_tch = 0;
296 dev_dbg(ts->dev, "%s: Num touch error detected\n", __func__);
297 } else if (IS_BAD_PKT(xy_data->tt_mode)) {
298 /* terminate all active tracks */
299 num_tch = 0;
300 dev_dbg(ts->dev, "%s: Invalid buffer detected\n", __func__);
301 }
302
303 cyttsp_extract_track_ids(xy_data, ids);
304
305 bitmap_zero(used, CY_MAX_ID);
306
307 for (i = 0; i < num_tch; i++) {
308 tch = cyttsp_get_tch(xy_data, i);
309
310 input_mt_slot(input, ids[i]);
311 input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
312 input_report_abs(input, ABS_MT_POSITION_X, be16_to_cpu(tch->x));
313 input_report_abs(input, ABS_MT_POSITION_Y, be16_to_cpu(tch->y));
314 input_report_abs(input, ABS_MT_TOUCH_MAJOR, tch->z);
315
316 __set_bit(ids[i], used);
317 }
318
319 for (i = 0; i < CY_MAX_ID; i++) {
320 if (test_bit(i, used))
321 continue;
322
323 input_mt_slot(input, i);
324 input_mt_report_slot_state(input, MT_TOOL_FINGER, false);
325 }
326
327 input_sync(input);
328}
329
330static irqreturn_t cyttsp_irq(int irq, void *handle)
331{
332 struct cyttsp *ts = handle;
333 int error;
334
335 if (unlikely(ts->state == CY_BL_STATE)) {
336 complete(&ts->bl_ready);
337 goto out;
338 }
339
340 /* Get touch data from CYTTSP device */
341 error = ttsp_read_block_data(ts, CY_REG_BASE,
342 sizeof(struct cyttsp_xydata), &ts->xy_data);
343 if (error)
344 goto out;
345
346 /* provide flow control handshake */
347 if (ts->pdata->use_hndshk) {
348 error = ttsp_send_command(ts,
349 ts->xy_data.hst_mode ^ CY_HNDSHK_BIT);
350 if (error)
351 goto out;
352 }
353
354 if (unlikely(ts->state == CY_IDLE_STATE))
355 goto out;
356
357 if (GET_BOOTLOADERMODE(ts->xy_data.tt_mode)) {
358 /*
359 * TTSP device has reset back to bootloader mode.
360 * Restore to operational mode.
361 */
362 error = cyttsp_exit_bl_mode(ts);
363 if (error) {
364 dev_err(ts->dev,
365 "Could not return to operational mode, err: %d\n",
366 error);
367 ts->state = CY_IDLE_STATE;
368 }
369 } else {
370 cyttsp_report_tchdata(ts);
371 }
372
373out:
374 return IRQ_HANDLED;
375}
376
377static int cyttsp_power_on(struct cyttsp *ts)
378{
379 int error;
380
381 error = cyttsp_soft_reset(ts);
382 if (error)
383 return error;
384
385 error = cyttsp_load_bl_regs(ts);
386 if (error)
387 return error;
388
389 if (GET_BOOTLOADERMODE(ts->bl_data.bl_status) &&
390 IS_VALID_APP(ts->bl_data.bl_status)) {
391 error = cyttsp_exit_bl_mode(ts);
392 if (error)
393 return error;
394 }
395
396 if (GET_HSTMODE(ts->bl_data.bl_file) != CY_OPERATE_MODE ||
397 IS_OPERATIONAL_ERR(ts->bl_data.bl_status)) {
398 return -ENODEV;
399 }
400
401 error = cyttsp_set_sysinfo_mode(ts);
402 if (error)
403 return error;
404
405 error = cyttsp_set_sysinfo_regs(ts);
406 if (error)
407 return error;
408
409 error = cyttsp_set_operational_mode(ts);
410 if (error)
411 return error;
412
413 /* init active distance */
414 error = cyttsp_act_dist_setup(ts);
415 if (error)
416 return error;
417
418 ts->state = CY_ACTIVE_STATE;
419
420 return 0;
421}
422
423static int cyttsp_enable(struct cyttsp *ts)
424{
425 int error;
426
427 /*
428 * The device firmware can wake on an I2C or SPI memory slave
429 * address match. So just reading a register is sufficient to
430 * wake up the device. The first read attempt will fail but it
431 * will wake it up making the second read attempt successful.
432 */
433 error = ttsp_read_block_data(ts, CY_REG_BASE,
434 sizeof(ts->xy_data), &ts->xy_data);
435 if (error)
436 return error;
437
438 if (GET_HSTMODE(ts->xy_data.hst_mode))
439 return -EIO;
440
441 enable_irq(ts->irq);
442
443 return 0;
444}
445
446static int cyttsp_disable(struct cyttsp *ts)
447{
448 int error;
449
450 error = ttsp_send_command(ts, CY_LOW_POWER_MODE);
451 if (error)
452 return error;
453
454 disable_irq(ts->irq);
455
456 return 0;
457}
458
459#ifdef CONFIG_PM_SLEEP
460static int cyttsp_suspend(struct device *dev)
461{
462 struct cyttsp *ts = dev_get_drvdata(dev);
463 int retval = 0;
464
465 mutex_lock(&ts->input->mutex);
466
467 if (ts->input->users) {
468 retval = cyttsp_disable(ts);
469 if (retval == 0)
470 ts->suspended = true;
471 }
472
473 mutex_unlock(&ts->input->mutex);
474
475 return retval;
476}
477
478static int cyttsp_resume(struct device *dev)
479{
480 struct cyttsp *ts = dev_get_drvdata(dev);
481
482 mutex_lock(&ts->input->mutex);
483
484 if (ts->input->users)
485 cyttsp_enable(ts);
486
487 ts->suspended = false;
488
489 mutex_unlock(&ts->input->mutex);
490
491 return 0;
492}
493
494#endif
495
496SIMPLE_DEV_PM_OPS(cyttsp_pm_ops, cyttsp_suspend, cyttsp_resume);
497EXPORT_SYMBOL_GPL(cyttsp_pm_ops);
498
499static int cyttsp_open(struct input_dev *dev)
500{
501 struct cyttsp *ts = input_get_drvdata(dev);
502 int retval = 0;
503
504 if (!ts->suspended)
505 retval = cyttsp_enable(ts);
506
507 return retval;
508}
509
510static void cyttsp_close(struct input_dev *dev)
511{
512 struct cyttsp *ts = input_get_drvdata(dev);
513
514 if (!ts->suspended)
515 cyttsp_disable(ts);
516}
517
518struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
519 struct device *dev, int irq, size_t xfer_buf_size)
520{
521 const struct cyttsp_platform_data *pdata = dev->platform_data;
522 struct cyttsp *ts;
523 struct input_dev *input_dev;
524 int error;
525
526 if (!dev || !bus_ops || !pdata || !pdata->name || irq <= 0) {
527 error = -EINVAL;
528 goto err_out;
529 }
530
531 ts = kzalloc(sizeof(*ts) + xfer_buf_size, GFP_KERNEL);
532 input_dev = input_allocate_device();
533 if (!ts || !input_dev) {
534 error = -ENOMEM;
535 goto err_free_mem;
536 }
537
538 ts->dev = dev;
539 ts->input = input_dev;
540 ts->pdata = dev->platform_data;
541 ts->bus_ops = bus_ops;
542 ts->irq = irq;
543
544 init_completion(&ts->bl_ready);
545 snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev));
546
547 if (pdata->init) {
548 error = pdata->init();
549 if (error) {
550 dev_err(ts->dev, "platform init failed, err: %d\n",
551 error);
552 goto err_free_mem;
553 }
554 }
555
556 input_dev->name = pdata->name;
557 input_dev->phys = ts->phys;
558 input_dev->id.bustype = bus_ops->bustype;
559 input_dev->dev.parent = ts->dev;
560
561 input_dev->open = cyttsp_open;
562 input_dev->close = cyttsp_close;
563
564 input_set_drvdata(input_dev, ts);
565
566 __set_bit(EV_ABS, input_dev->evbit);
567 input_set_abs_params(input_dev, ABS_MT_POSITION_X,
568 0, pdata->maxx, 0, 0);
569 input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
570 0, pdata->maxy, 0, 0);
571 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
572 0, CY_MAXZ, 0, 0);
573
574 input_mt_init_slots(input_dev, CY_MAX_ID);
575
576 error = request_threaded_irq(ts->irq, NULL, cyttsp_irq,
577 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
578 pdata->name, ts);
579 if (error) {
580 dev_err(ts->dev, "failed to request IRQ %d, err: %d\n",
581 ts->irq, error);
582 goto err_platform_exit;
583 }
584
585 disable_irq(ts->irq);
586
587 error = cyttsp_power_on(ts);
588 if (error)
589 goto err_free_irq;
590
591 error = input_register_device(input_dev);
592 if (error) {
593 dev_err(ts->dev, "failed to register input device: %d\n",
594 error);
595 goto err_free_irq;
596 }
597
598 return ts;
599
600err_free_irq:
601 free_irq(ts->irq, ts);
602err_platform_exit:
603 if (pdata->exit)
604 pdata->exit();
605err_free_mem:
606 input_free_device(input_dev);
607 kfree(ts);
608err_out:
609 return ERR_PTR(error);
610}
611EXPORT_SYMBOL_GPL(cyttsp_probe);
612
613void cyttsp_remove(struct cyttsp *ts)
614{
615 free_irq(ts->irq, ts);
616 input_unregister_device(ts->input);
617 if (ts->pdata->exit)
618 ts->pdata->exit();
619 kfree(ts);
620}
621EXPORT_SYMBOL_GPL(cyttsp_remove);
622
623MODULE_LICENSE("GPL");
624MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard touchscreen driver core");
625MODULE_AUTHOR("Cypress");
diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h
new file mode 100644
index 00000000000..1aa3c6967e7
--- /dev/null
+++ b/drivers/input/touchscreen/cyttsp_core.h
@@ -0,0 +1,149 @@
1/*
2 * Header file for:
3 * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers.
4 * For use with Cypress Txx3xx parts.
5 * Supported parts include:
6 * CY8CTST341
7 * CY8CTMA340
8 *
9 * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
10 * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * version 2, and only version 2, as published by the
15 * Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 *
26 * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com>
27 *
28 */
29
30
31#ifndef __CYTTSP_CORE_H__
32#define __CYTTSP_CORE_H__
33
34#include <linux/kernel.h>
35#include <linux/err.h>
36#include <linux/module.h>
37#include <linux/types.h>
38#include <linux/device.h>
39#include <linux/input/cyttsp.h>
40
41#define CY_NUM_RETRY 16 /* max number of retries for read ops */
42
43struct cyttsp_tch {
44 __be16 x, y;
45 u8 z;
46} __packed;
47
48/* TrueTouch Standard Product Gen3 interface definition */
49struct cyttsp_xydata {
50 u8 hst_mode;
51 u8 tt_mode;
52 u8 tt_stat;
53 struct cyttsp_tch tch1;
54 u8 touch12_id;
55 struct cyttsp_tch tch2;
56 u8 gest_cnt;
57 u8 gest_id;
58 struct cyttsp_tch tch3;
59 u8 touch34_id;
60 struct cyttsp_tch tch4;
61 u8 tt_undef[3];
62 u8 act_dist;
63 u8 tt_reserved;
64} __packed;
65
66
67/* TTSP System Information interface definition */
68struct cyttsp_sysinfo_data {
69 u8 hst_mode;
70 u8 mfg_cmd;
71 u8 mfg_stat;
72 u8 cid[3];
73 u8 tt_undef1;
74 u8 uid[8];
75 u8 bl_verh;
76 u8 bl_verl;
77 u8 tts_verh;
78 u8 tts_verl;
79 u8 app_idh;
80 u8 app_idl;
81 u8 app_verh;
82 u8 app_verl;
83 u8 tt_undef[5];
84 u8 scn_typ;
85 u8 act_intrvl;
86 u8 tch_tmout;
87 u8 lp_intrvl;
88};
89
90/* TTSP Bootloader Register Map interface definition */
91#define CY_BL_CHKSUM_OK 0x01
92struct cyttsp_bootloader_data {
93 u8 bl_file;
94 u8 bl_status;
95 u8 bl_error;
96 u8 blver_hi;
97 u8 blver_lo;
98 u8 bld_blver_hi;
99 u8 bld_blver_lo;
100 u8 ttspver_hi;
101 u8 ttspver_lo;
102 u8 appid_hi;
103 u8 appid_lo;
104 u8 appver_hi;
105 u8 appver_lo;
106 u8 cid_0;
107 u8 cid_1;
108 u8 cid_2;
109};
110
111struct cyttsp;
112
113struct cyttsp_bus_ops {
114 u16 bustype;
115 int (*write)(struct cyttsp *ts,
116 u8 addr, u8 length, const void *values);
117 int (*read)(struct cyttsp *ts, u8 addr, u8 length, void *values);
118};
119
120enum cyttsp_state {
121 CY_IDLE_STATE,
122 CY_ACTIVE_STATE,
123 CY_BL_STATE,
124};
125
126struct cyttsp {
127 struct device *dev;
128 int irq;
129 struct input_dev *input;
130 char phys[32];
131 const struct cyttsp_platform_data *pdata;
132 const struct cyttsp_bus_ops *bus_ops;
133 struct cyttsp_bootloader_data bl_data;
134 struct cyttsp_sysinfo_data sysinfo_data;
135 struct cyttsp_xydata xy_data;
136 struct completion bl_ready;
137 enum cyttsp_state state;
138 bool suspended;
139
140 u8 xfer_buf[] ____cacheline_aligned;
141};
142
143struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
144 struct device *dev, int irq, size_t xfer_buf_size);
145void cyttsp_remove(struct cyttsp *ts);
146
147extern const struct dev_pm_ops cyttsp_pm_ops;
148
149#endif /* __CYTTSP_CORE_H__ */
diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c
new file mode 100644
index 00000000000..c7110cc06b9
--- /dev/null
+++ b/drivers/input/touchscreen/cyttsp_i2c.c
@@ -0,0 +1,146 @@
1/*
2 * Source for:
3 * Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver.
4 * For use with Cypress Txx3xx parts.
5 * Supported parts include:
6 * CY8CTST341
7 * CY8CTMA340
8 *
9 * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
10 * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * version 2, and only version 2, as published by the
15 * Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 *
26 * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com>
27 *
28 */
29
30#include "cyttsp_core.h"
31
32#include <linux/i2c.h>
33#include <linux/input.h>
34
35#define CY_I2C_DATA_SIZE 128
36
37static int cyttsp_i2c_read_block_data(struct cyttsp *ts,
38 u8 addr, u8 length, void *values)
39{
40 struct i2c_client *client = to_i2c_client(ts->dev);
41 struct i2c_msg msgs[] = {
42 {
43 .addr = client->addr,
44 .flags = 0,
45 .len = 1,
46 .buf = &addr,
47 },
48 {
49 .addr = client->addr,
50 .flags = I2C_M_RD,
51 .len = length,
52 .buf = values,
53 },
54 };
55 int retval;
56
57 retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
58 if (retval < 0)
59 return retval;
60
61 return retval != ARRAY_SIZE(msgs) ? -EIO : 0;
62}
63
64static int cyttsp_i2c_write_block_data(struct cyttsp *ts,
65 u8 addr, u8 length, const void *values)
66{
67 struct i2c_client *client = to_i2c_client(ts->dev);
68 int retval;
69
70 ts->xfer_buf[0] = addr;
71 memcpy(&ts->xfer_buf[1], values, length);
72
73 retval = i2c_master_send(client, ts->xfer_buf, length + 1);
74
75 return retval < 0 ? retval : 0;
76}
77
78static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = {
79 .bustype = BUS_I2C,
80 .write = cyttsp_i2c_write_block_data,
81 .read = cyttsp_i2c_read_block_data,
82};
83
84static int __devinit cyttsp_i2c_probe(struct i2c_client *client,
85 const struct i2c_device_id *id)
86{
87 struct cyttsp *ts;
88
89 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
90 dev_err(&client->dev, "I2C functionality not Supported\n");
91 return -EIO;
92 }
93
94 ts = cyttsp_probe(&cyttsp_i2c_bus_ops, &client->dev, client->irq,
95 CY_I2C_DATA_SIZE);
96
97 if (IS_ERR(ts))
98 return PTR_ERR(ts);
99
100 i2c_set_clientdata(client, ts);
101
102 return 0;
103}
104
105static int __devexit cyttsp_i2c_remove(struct i2c_client *client)
106{
107 struct cyttsp *ts = i2c_get_clientdata(client);
108
109 cyttsp_remove(ts);
110
111 return 0;
112}
113
114static const struct i2c_device_id cyttsp_i2c_id[] = {
115 { CY_I2C_NAME, 0 },
116 { }
117};
118MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id);
119
120static struct i2c_driver cyttsp_i2c_driver = {
121 .driver = {
122 .name = CY_I2C_NAME,
123 .owner = THIS_MODULE,
124 .pm = &cyttsp_pm_ops,
125 },
126 .probe = cyttsp_i2c_probe,
127 .remove = __devexit_p(cyttsp_i2c_remove),
128 .id_table = cyttsp_i2c_id,
129};
130
131static int __init cyttsp_i2c_init(void)
132{
133 return i2c_add_driver(&cyttsp_i2c_driver);
134}
135module_init(cyttsp_i2c_init);
136
137static void __exit cyttsp_i2c_exit(void)
138{
139 return i2c_del_driver(&cyttsp_i2c_driver);
140}
141module_exit(cyttsp_i2c_exit);
142
143MODULE_LICENSE("GPL");
144MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) I2C driver");
145MODULE_AUTHOR("Cypress");
146MODULE_ALIAS("i2c:cyttsp");
diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c
new file mode 100644
index 00000000000..9db5f8754d1
--- /dev/null
+++ b/drivers/input/touchscreen/cyttsp_spi.c
@@ -0,0 +1,210 @@
1/*
2 * Source for:
3 * Cypress TrueTouch(TM) Standard Product (TTSP) SPI touchscreen driver.
4 * For use with Cypress Txx3xx parts.
5 * Supported parts include:
6 * CY8CTST341
7 * CY8CTMA340
8 *
9 * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
10 * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * version 2, and only version 2, as published by the
15 * Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 *
26 * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com>
27 *
28 */
29
30#include "cyttsp_core.h"
31
32#include <linux/delay.h>
33#include <linux/input.h>
34#include <linux/spi/spi.h>
35
36#define CY_SPI_WR_OP 0x00 /* r/~w */
37#define CY_SPI_RD_OP 0x01
38#define CY_SPI_CMD_BYTES 4
39#define CY_SPI_SYNC_BYTE 2
40#define CY_SPI_SYNC_ACK1 0x62 /* from protocol v.2 */
41#define CY_SPI_SYNC_ACK2 0x9D /* from protocol v.2 */
42#define CY_SPI_DATA_SIZE 128
43#define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE)
44#define CY_SPI_BITS_PER_WORD 8
45
46static int cyttsp_spi_xfer(struct cyttsp *ts,
47 u8 op, u8 reg, u8 *buf, int length)
48{
49 struct spi_device *spi = to_spi_device(ts->dev);
50 struct spi_message msg;
51 struct spi_transfer xfer[2];
52 u8 *wr_buf = &ts->xfer_buf[0];
53 u8 *rd_buf = &ts->xfer_buf[CY_SPI_DATA_BUF_SIZE];
54 int retval;
55 int i;
56
57 if (length > CY_SPI_DATA_SIZE) {
58 dev_err(ts->dev, "%s: length %d is too big.\n",
59 __func__, length);
60 return -EINVAL;
61 }
62
63 memset(wr_buf, 0, CY_SPI_DATA_BUF_SIZE);
64 memset(rd_buf, 0, CY_SPI_DATA_BUF_SIZE);
65
66 wr_buf[0] = 0x00; /* header byte 0 */
67 wr_buf[1] = 0xFF; /* header byte 1 */
68 wr_buf[2] = reg; /* reg index */
69 wr_buf[3] = op; /* r/~w */
70 if (op == CY_SPI_WR_OP)
71 memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length);
72
73 memset(xfer, 0, sizeof(xfer));
74 spi_message_init(&msg);
75
76 /*
77 We set both TX and RX buffers because Cypress TTSP
78 requires full duplex operation.
79 */
80 xfer[0].tx_buf = wr_buf;
81 xfer[0].rx_buf = rd_buf;
82 switch (op) {
83 case CY_SPI_WR_OP:
84 xfer[0].len = length + CY_SPI_CMD_BYTES;
85 spi_message_add_tail(&xfer[0], &msg);
86 break;
87
88 case CY_SPI_RD_OP:
89 xfer[0].len = CY_SPI_CMD_BYTES;
90 spi_message_add_tail(&xfer[0], &msg);
91
92 xfer[1].rx_buf = buf;
93 xfer[1].len = length;
94 spi_message_add_tail(&xfer[1], &msg);
95 break;
96
97 default:
98 dev_err(ts->dev, "%s: bad operation code=%d\n", __func__, op);
99 return -EINVAL;
100 }
101
102 retval = spi_sync(spi, &msg);
103 if (retval < 0) {
104 dev_dbg(ts->dev, "%s: spi_sync() error %d, len=%d, op=%d\n",
105 __func__, retval, xfer[1].len, op);
106
107 /*
108 * do not return here since was a bad ACK sequence
109 * let the following ACK check handle any errors and
110 * allow silent retries
111 */
112 }
113
114 if (rd_buf[CY_SPI_SYNC_BYTE] != CY_SPI_SYNC_ACK1 ||
115 rd_buf[CY_SPI_SYNC_BYTE + 1] != CY_SPI_SYNC_ACK2) {
116
117 dev_dbg(ts->dev, "%s: operation %d failed\n", __func__, op);
118
119 for (i = 0; i < CY_SPI_CMD_BYTES; i++)
120 dev_dbg(ts->dev, "%s: test rd_buf[%d]:0x%02x\n",
121 __func__, i, rd_buf[i]);
122 for (i = 0; i < length; i++)
123 dev_dbg(ts->dev, "%s: test buf[%d]:0x%02x\n",
124 __func__, i, buf[i]);
125
126 return -EIO;
127 }
128
129 return 0;
130}
131
132static int cyttsp_spi_read_block_data(struct cyttsp *ts,
133 u8 addr, u8 length, void *data)
134{
135 return cyttsp_spi_xfer(ts, CY_SPI_RD_OP, addr, data, length);
136}
137
138static int cyttsp_spi_write_block_data(struct cyttsp *ts,
139 u8 addr, u8 length, const void *data)
140{
141 return cyttsp_spi_xfer(ts, CY_SPI_WR_OP, addr, (void *)data, length);
142}
143
144static const struct cyttsp_bus_ops cyttsp_spi_bus_ops = {
145 .bustype = BUS_SPI,
146 .write = cyttsp_spi_write_block_data,
147 .read = cyttsp_spi_read_block_data,
148};
149
150static int __devinit cyttsp_spi_probe(struct spi_device *spi)
151{
152 struct cyttsp *ts;
153 int error;
154
155 /* Set up SPI*/
156 spi->bits_per_word = CY_SPI_BITS_PER_WORD;
157 spi->mode = SPI_MODE_0;
158 error = spi_setup(spi);
159 if (error < 0) {
160 dev_err(&spi->dev, "%s: SPI setup error %d\n",
161 __func__, error);
162 return error;
163 }
164
165 ts = cyttsp_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq,
166 CY_SPI_DATA_BUF_SIZE * 2);
167 if (IS_ERR(ts))
168 return PTR_ERR(ts);
169
170 spi_set_drvdata(spi, ts);
171
172 return 0;
173}
174
175static int __devexit cyttsp_spi_remove(struct spi_device *spi)
176{
177 struct cyttsp *ts = spi_get_drvdata(spi);
178
179 cyttsp_remove(ts);
180
181 return 0;
182}
183
184static struct spi_driver cyttsp_spi_driver = {
185 .driver = {
186 .name = CY_SPI_NAME,
187 .owner = THIS_MODULE,
188 .pm = &cyttsp_pm_ops,
189 },
190 .probe = cyttsp_spi_probe,
191 .remove = __devexit_p(cyttsp_spi_remove),
192};
193
194static int __init cyttsp_spi_init(void)
195{
196 return spi_register_driver(&cyttsp_spi_driver);
197}
198module_init(cyttsp_spi_init);
199
200static void __exit cyttsp_spi_exit(void)
201{
202 spi_unregister_driver(&cyttsp_spi_driver);
203}
204module_exit(cyttsp_spi_exit);
205
206MODULE_ALIAS("spi:cyttsp");
207MODULE_LICENSE("GPL");
208MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver");
209MODULE_AUTHOR("Cypress");
210MODULE_ALIAS("spi:cyttsp");
diff --git a/include/linux/input/cyttsp.h b/include/linux/input/cyttsp.h
new file mode 100644
index 00000000000..5af7c66f1fc
--- /dev/null
+++ b/include/linux/input/cyttsp.h
@@ -0,0 +1,58 @@
1/*
2 * Header file for:
3 * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers.
4 * For use with Cypress Txx3xx parts.
5 * Supported parts include:
6 * CY8CTST341
7 * CY8CTMA340
8 *
9 * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
10 * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * version 2, and only version 2, as published by the
15 * Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 *
26 * Contact Cypress Semiconductor at www.cypress.com (kev@cypress.com)
27 *
28 */
29#ifndef _CYTTSP_H_
30#define _CYTTSP_H_
31
32#define CY_SPI_NAME "cyttsp-spi"
33#define CY_I2C_NAME "cyttsp-i2c"
34/* Active Power state scanning/processing refresh interval */
35#define CY_ACT_INTRVL_DFLT 0x00 /* ms */
36/* touch timeout for the Active power */
37#define CY_TCH_TMOUT_DFLT 0xFF /* ms */
38/* Low Power state scanning/processing refresh interval */
39#define CY_LP_INTRVL_DFLT 0x0A /* ms */
40/* Active distance in pixels for a gesture to be reported */
41#define CY_ACT_DIST_DFLT 0xF8 /* pixels */
42
43struct cyttsp_platform_data {
44 u32 maxx;
45 u32 maxy;
46 bool use_hndshk;
47 u8 act_dist; /* Active distance */
48 u8 act_intrvl; /* Active refresh interval; ms */
49 u8 tch_tmout; /* Active touch timeout; ms */
50 u8 lp_intrvl; /* Low power refresh interval; ms */
51 int (*init)(void);
52 void (*exit)(void);
53 char *name;
54 s16 irq_gpio;
55 u8 *bl_keys;
56};
57
58#endif /* _CYTTSP_H_ */