blob: 7c7518a59a04bd6e789b1cf11bd94a3c644240f7 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Source for:
2 * Cypress TrueTouch(TM) Standard Product I2C touchscreen driver.
3 * drivers/input/touchscreen/cyttsp-i2c.c
4 *
5 * Copyright (C) 2009, 2010 Cypress Semiconductor, Inc.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2, and only version 2, as published by the
10 * Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 * Cypress reserves the right to make changes without further notice
22 * to the materials described herein. Cypress does not assume any
23 * liability arising out of the application described herein.
24 *
25 * Contact Cypress Semiconductor at www.cypress.com
26 *
27 */
28
29#include <linux/delay.h>
30#include <linux/init.h>
31#include <linux/module.h>
32#include <linux/i2c.h>
33#include <linux/input.h>
34#include <linux/slab.h>
35#include <linux/gpio.h>
36#include <linux/irq.h>
37#include <linux/interrupt.h>
38#include <linux/timer.h>
39#include <linux/workqueue.h>
40#include <linux/byteorder/generic.h>
41#include <linux/bitops.h>
42#include <linux/pm_runtime.h>
43#include <linux/firmware.h>
44#include <linux/mutex.h>
45#include <linux/regulator/consumer.h>
46#ifdef CONFIG_HAS_EARLYSUSPEND
47#include <linux/earlysuspend.h>
48#endif /* CONFIG_HAS_EARLYSUSPEND */
49
50#define CY_DECLARE_GLOBALS
51
52#include <linux/cyttsp.h>
53
54uint32_t cyttsp_tsdebug1 = 0xff;
55module_param_named(tsdebug1, cyttsp_tsdebug1, uint, 0664);
56
57#define FW_FNAME_LEN 40
58
59/* CY TTSP I2C Driver private data */
60struct cyttsp {
61 struct i2c_client *client;
62 struct input_dev *input;
63 struct work_struct work;
64 struct timer_list timer;
65 struct mutex mutex;
66 char phys[32];
67 struct cyttsp_platform_data *platform_data;
68 u8 num_prv_st_tch;
69 u16 act_trk[CY_NUM_TRK_ID];
70 u16 prv_st_tch[CY_NUM_ST_TCH_ID];
71 u16 prv_mt_tch[CY_NUM_MT_TCH_ID];
72 u16 prv_mt_pos[CY_NUM_TRK_ID][2];
73 atomic_t irq_enabled;
74 bool cyttsp_update_fw;
75 bool cyttsp_fwloader_mode;
76 bool is_suspended;
77 struct regulator **vdd;
78 char fw_fname[FW_FNAME_LEN];
79#ifdef CONFIG_HAS_EARLYSUSPEND
80 struct early_suspend early_suspend;
81#endif /* CONFIG_HAS_EARLYSUSPEND */
82};
83static u8 irq_cnt; /* comparison counter with register valuw */
84static u32 irq_cnt_total; /* total interrupts */
85static u32 irq_err_cnt; /* count number of touch interrupts with err */
86#define CY_IRQ_CNT_MASK 0x000000FF /* mapped for sizeof count in reg */
87#define CY_IRQ_CNT_REG 0x00 /* tt_undef[0]=reg 0x1B - Gen3 only */
88
89#ifdef CONFIG_HAS_EARLYSUSPEND
90static void cyttsp_early_suspend(struct early_suspend *handler);
91static void cyttsp_late_resume(struct early_suspend *handler);
92#endif /* CONFIG_HAS_EARLYSUSPEND */
93
94static struct workqueue_struct *cyttsp_ts_wq;
95
96
97/* ****************************************************************************
98 * Prototypes for static functions
99 * ************************************************************************** */
100static void cyttsp_xy_worker(struct work_struct *work);
101static irqreturn_t cyttsp_irq(int irq, void *handle);
102static int cyttsp_inlist(u16 prev_track[],
103 u8 cur_trk_id, u8 *prev_loc, u8 num_touches);
104static int cyttsp_next_avail_inlist(u16 cur_trk[],
105 u8 *new_loc, u8 num_touches);
106static int cyttsp_putbl(struct cyttsp *ts, int show,
107 int show_status, int show_version, int show_cid);
108static int __devinit cyttsp_probe(struct i2c_client *client,
109 const struct i2c_device_id *id);
110static int __devexit cyttsp_remove(struct i2c_client *client);
111static int cyttsp_resume(struct device *dev);
112static int cyttsp_suspend(struct device *dev);
113
114/* Static variables */
115static struct cyttsp_gen3_xydata_t g_xy_data;
116static struct cyttsp_bootloader_data_t g_bl_data;
117static struct cyttsp_sysinfo_data_t g_sysinfo_data;
118static const struct i2c_device_id cyttsp_id[] = {
119 { CY_I2C_NAME, 0 }, { }
120};
121static u8 bl_cmd[] = {
122 CY_BL_FILE0, CY_BL_CMD, CY_BL_EXIT,
123 CY_BL_KEY0, CY_BL_KEY1, CY_BL_KEY2,
124 CY_BL_KEY3, CY_BL_KEY4, CY_BL_KEY5,
125 CY_BL_KEY6, CY_BL_KEY7};
126
127MODULE_DEVICE_TABLE(i2c, cyttsp_id);
128
129static const struct dev_pm_ops cyttsp_pm_ops = {
130 .suspend = cyttsp_suspend,
131 .resume = cyttsp_resume,
132};
133
134static struct i2c_driver cyttsp_driver = {
135 .driver = {
136 .name = CY_I2C_NAME,
137 .owner = THIS_MODULE,
138 .pm = &cyttsp_pm_ops,
139 },
140 .probe = cyttsp_probe,
141 .remove = __devexit_p(cyttsp_remove),
142 .id_table = cyttsp_id,
143};
144
145MODULE_LICENSE("GPL");
146MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard touchscreen driver");
147MODULE_AUTHOR("Cypress");
148
149static ssize_t cyttsp_irq_status(struct device *dev,
150 struct device_attribute *attr, char *buf)
151{
152 struct i2c_client *client = container_of(dev, struct i2c_client, dev);
153 struct cyttsp *ts = i2c_get_clientdata(client);
154 return sprintf(buf, "%u\n", atomic_read(&ts->irq_enabled));
155}
156
157static ssize_t cyttsp_irq_enable(struct device *dev,
158 struct device_attribute *attr,
159 const char *buf, size_t size)
160{
161 struct i2c_client *client = container_of(dev, struct i2c_client, dev);
162 struct cyttsp *ts = i2c_get_clientdata(client);
163 int err = 0;
164 unsigned long value;
165
166 if (size > 2)
167 return -EINVAL;
168
169 err = strict_strtoul(buf, 10, &value);
170 if (err != 0)
171 return err;
172
173 switch (value) {
174 case 0:
175 if (atomic_cmpxchg(&ts->irq_enabled, 1, 0)) {
176 pr_info("touch irq disabled!\n");
177 disable_irq_nosync(ts->client->irq);
178 }
179 err = size;
180 break;
181 case 1:
182 if (!atomic_cmpxchg(&ts->irq_enabled, 0, 1)) {
183 pr_info("touch irq enabled!\n");
184 enable_irq(ts->client->irq);
185 }
186 err = size;
187 break;
188 default:
189 pr_info("cyttsp_irq_enable failed -> irq_enabled = %d\n",
190 atomic_read(&ts->irq_enabled));
191 err = -EINVAL;
192 break;
193 }
194
195 return err;
196}
197
198static DEVICE_ATTR(irq_enable, 0777, cyttsp_irq_status, cyttsp_irq_enable);
199
200static ssize_t cyttsp_fw_show(struct device *dev,
201 struct device_attribute *attr, char *buf)
202{
203 return sprintf(buf, "%d.%d.%d\n", g_bl_data.appid_lo,
204 g_bl_data.appver_hi, g_bl_data.appver_lo);
205}
206
207static DEVICE_ATTR(cyttsp_fw_ver, 0777, cyttsp_fw_show, NULL);
208
209/* firmware flashing block */
210#define BLK_SIZE 16
211#define DATA_REC_LEN 64
212#define START_ADDR 0x0b00
213#define BLK_SEED 0xff
214#define RECAL_REG 0x1b
215
216enum bl_commands {
217 BL_CMD_WRBLK = 0x39,
218 BL_CMD_INIT = 0x38,
219 BL_CMD_TERMINATE = 0x3b,
220};
221/* TODO: Add key as part of platform data */
222#define KEY_CS (0 + 1 + 2 + 3 + 4 + 5 + 6 + 7)
223#define KEY {0, 1, 2, 3, 4, 5, 6, 7}
224
225static const char _key[] = KEY;
226#define KEY_LEN sizeof(_key)
227
228static int rec_cnt;
229struct fw_record {
230 u8 seed;
231 u8 cmd;
232 u8 key[KEY_LEN];
233 u8 blk_hi;
234 u8 blk_lo;
235 u8 data[DATA_REC_LEN];
236 u8 data_cs;
237 u8 rec_cs;
238};
239#define fw_rec_size (sizeof(struct fw_record))
240
241struct cmd_record {
242 u8 reg;
243 u8 seed;
244 u8 cmd;
245 u8 key[KEY_LEN];
246};
247#define cmd_rec_size (sizeof(struct cmd_record))
248
249static struct fw_record data_record = {
250 .seed = BLK_SEED,
251 .cmd = BL_CMD_WRBLK,
252 .key = KEY,
253};
254
255static const struct cmd_record terminate_rec = {
256 .reg = 0,
257 .seed = BLK_SEED,
258 .cmd = BL_CMD_TERMINATE,
259 .key = KEY,
260};
261static const struct cmd_record initiate_rec = {
262 .reg = 0,
263 .seed = BLK_SEED,
264 .cmd = BL_CMD_INIT,
265 .key = KEY,
266};
267
268#define BL_REC1_ADDR 0x0780
269#define BL_REC2_ADDR 0x07c0
270
271#define ID_INFO_REC ":40078000"
272#define ID_INFO_OFFSET_IN_REC 77
273
274#define REC_START_CHR ':'
275#define REC_LEN_OFFSET 1
276#define REC_ADDR_HI_OFFSET 3
277#define REC_ADDR_LO_OFFSET 5
278#define REC_TYPE_OFFSET 7
279#define REC_DATA_OFFSET 9
280#define REC_LINE_SIZE 141
281
282static int cyttsp_soft_reset(struct cyttsp *ts)
283{
284 int retval = 0, tries = 0;
285 u8 host_reg = CY_SOFT_RESET_MODE;
286
287 do {
288 retval = i2c_smbus_write_i2c_block_data(ts->client,
289 CY_REG_BASE, sizeof(host_reg), &host_reg);
290 if (retval < 0)
291 msleep(20);
292 } while (tries++ < 10 && (retval < 0));
293
294 if (retval < 0) {
295 pr_err("%s: failed\n", __func__);
296 return retval;
297 }
298
299 tries = 0;
300 do {
301 msleep(20);
302 cyttsp_putbl(ts, 1, true, true, false);
303 } while (g_bl_data.bl_status != 0x10 &&
304 g_bl_data.bl_status != 0x11 &&
305 tries++ < 100);
306
307 if (g_bl_data.bl_status != 0x11 && g_bl_data.bl_status != 0x10)
308 return -EINVAL;
309
310 return 0;
311}
312
313static void cyttsp_exit_bl_mode(struct cyttsp *ts)
314{
315 int retval, tries = 0;
316
317 do {
318 retval = i2c_smbus_write_i2c_block_data(ts->client,
319 CY_REG_BASE, sizeof(bl_cmd), bl_cmd);
320 if (retval < 0)
321 msleep(20);
322 } while (tries++ < 10 && (retval < 0));
323}
324
325static void cyttsp_set_sysinfo_mode(struct cyttsp *ts)
326{
327 int retval, tries = 0;
328 u8 host_reg = CY_SYSINFO_MODE;
329
330 do {
331 retval = i2c_smbus_write_i2c_block_data(ts->client,
332 CY_REG_BASE, sizeof(host_reg), &host_reg);
333 if (retval < 0)
334 msleep(20);
335 } while (tries++ < 10 && (retval < 0));
336
337 /* wait for TTSP Device to complete switch to SysInfo mode */
338 if (!(retval < 0)) {
339 retval = i2c_smbus_read_i2c_block_data(ts->client,
340 CY_REG_BASE,
341 sizeof(struct cyttsp_sysinfo_data_t),
342 (u8 *)&g_sysinfo_data);
343 } else
344 pr_err("%s: failed\n", __func__);
345}
346
347static void cyttsp_set_opmode(struct cyttsp *ts)
348{
349 int retval, tries = 0;
350 u8 host_reg = CY_OP_MODE;
351
352 do {
353 retval = i2c_smbus_write_i2c_block_data(ts->client,
354 CY_REG_BASE, sizeof(host_reg), &host_reg);
355 if (retval < 0)
356 msleep(20);
357 } while (tries++ < 10 && (retval < 0));
358}
359
360static int str2uc(char *str, u8 *val)
361{
362 char substr[3];
363 unsigned long ulval;
364 int rc;
365
366 if (!str && strlen(str) < 2)
367 return -EINVAL;
368
369 substr[0] = str[0];
370 substr[1] = str[1];
371 substr[2] = '\0';
372
373 rc = strict_strtoul(substr, 16, &ulval);
374 if (rc != 0)
375 return rc;
376
377 *val = (u8) ulval;
378
379 return 0;
380}
381
382static int flash_block(struct cyttsp *ts, u8 *blk, int len)
383{
384 int retval, i, tries = 0;
385 char buf[(2 * (BLK_SIZE + 1)) + 1];
386 char *p = buf;
387
388 for (i = 0; i < len; i++, p += 2)
389 sprintf(p, "%02x", blk[i]);
390 pr_debug("%s: size %d, pos %ld payload %s\n",
391 __func__, len, (long)0, buf);
392
393 do {
394 retval = i2c_smbus_write_i2c_block_data(ts->client,
395 CY_REG_BASE, len, blk);
396 if (retval < 0)
397 msleep(20);
398 } while (tries++ < 20 && (retval < 0));
399
400 if (retval < 0) {
401 pr_err("%s: failed\n", __func__);
402 return retval;
403 }
404
405 return 0;
406}
407
408static int flash_command(struct cyttsp *ts, const struct cmd_record *record)
409{
410 return flash_block(ts, (u8 *)record, cmd_rec_size);
411}
412
413static void init_data_record(struct fw_record *rec, unsigned short addr)
414{
415 addr >>= 6;
416 rec->blk_hi = (addr >> 8) & 0xff;
417 rec->blk_lo = addr & 0xff;
418 rec->rec_cs = rec->blk_hi + rec->blk_lo +
419 (unsigned char)(BLK_SEED + BL_CMD_WRBLK + KEY_CS);
420 rec->data_cs = 0;
421}
422
423static int check_record(u8 *rec)
424{
425 int rc;
426 u16 addr;
427 u8 r_len, type, hi_off, lo_off;
428
429 rc = str2uc(rec + REC_LEN_OFFSET, &r_len);
430 if (rc < 0)
431 return rc;
432
433 rc = str2uc(rec + REC_TYPE_OFFSET, &type);
434 if (rc < 0)
435 return rc;
436
437 if (*rec != REC_START_CHR || r_len != DATA_REC_LEN || type != 0)
438 return -EINVAL;
439
440 rc = str2uc(rec + REC_ADDR_HI_OFFSET, &hi_off);
441 if (rc < 0)
442 return rc;
443
444 rc = str2uc(rec + REC_ADDR_LO_OFFSET, &lo_off);
445 if (rc < 0)
446 return rc;
447
448 addr = (hi_off << 8) | lo_off;
449
450 if (addr >= START_ADDR || addr == BL_REC1_ADDR || addr == BL_REC2_ADDR)
451 return 0;
452
453 return -EINVAL;
454}
455
456static struct fw_record *prepare_record(u8 *rec)
457{
458 int i, rc;
459 u16 addr;
460 u8 hi_off, lo_off;
461 u8 *p;
462
463 rc = str2uc(rec + REC_ADDR_HI_OFFSET, &hi_off);
464 if (rc < 0)
465 return ERR_PTR((long) rc);
466
467 rc = str2uc(rec + REC_ADDR_LO_OFFSET, &lo_off);
468 if (rc < 0)
469 return ERR_PTR((long) rc);
470
471 addr = (hi_off << 8) | lo_off;
472
473 init_data_record(&data_record, addr);
474 p = rec + REC_DATA_OFFSET;
475 for (i = 0; i < DATA_REC_LEN; i++) {
476 rc = str2uc(p, &data_record.data[i]);
477 if (rc < 0)
478 return ERR_PTR((long) rc);
479 data_record.data_cs += data_record.data[i];
480 data_record.rec_cs += data_record.data[i];
481 p += 2;
482 }
483 data_record.rec_cs += data_record.data_cs;
484
485 return &data_record;
486}
487
488static int flash_record(struct cyttsp *ts, const struct fw_record *record)
489{
490 int len = fw_rec_size;
491 int blk_len, rc;
492 u8 *rec = (u8 *)record;
493 u8 data[BLK_SIZE + 1];
494 u8 blk_offset;
495
496 for (blk_offset = 0; len; len -= blk_len) {
497 data[0] = blk_offset;
498 blk_len = len > BLK_SIZE ? BLK_SIZE : len;
499 memcpy(data + 1, rec, blk_len);
500 rec += blk_len;
501 rc = flash_block(ts, data, blk_len + 1);
502 if (rc < 0)
503 return rc;
504 blk_offset += blk_len;
505 }
506 return 0;
507}
508
509static int flash_data_rec(struct cyttsp *ts, u8 *buf)
510{
511 struct fw_record *rec;
512 int rc, tries;
513
514 if (!buf)
515 return -EINVAL;
516
517 rc = check_record(buf);
518
519 if (rc < 0) {
520 pr_debug("%s: record ignored %s", __func__, buf);
521 return 0;
522 }
523
524 rec = prepare_record(buf);
525 if (IS_ERR_OR_NULL(rec))
526 return PTR_ERR(rec);
527
528 rc = flash_record(ts, rec);
529 if (rc < 0)
530 return rc;
531
532 tries = 0;
533 do {
534 if (rec_cnt%2)
535 msleep(20);
536 cyttsp_putbl(ts, 4, true, false, false);
537 } while (g_bl_data.bl_status != 0x10 &&
538 g_bl_data.bl_status != 0x11 &&
539 tries++ < 100);
540 rec_cnt++;
541 return rc;
542}
543
544static int cyttspfw_flash_firmware(struct cyttsp *ts, const u8 *data,
545 int data_len)
546{
547 u8 *buf;
548 int i, j;
549 int rc, tries = 0;
550
551 /* initiate bootload: this will erase all the existing data */
552 rc = flash_command(ts, &initiate_rec);
553 if (rc < 0)
554 return rc;
555
556 do {
557 msleep(100);
558 cyttsp_putbl(ts, 4, true, false, false);
559 } while (g_bl_data.bl_status != 0x10 &&
560 g_bl_data.bl_status != 0x11 &&
561 tries++ < 100);
562
563 buf = kzalloc(REC_LINE_SIZE + 1, GFP_KERNEL);
564 if (!buf) {
565 pr_err("%s: no memory\n", __func__);
566 return -ENOMEM;
567 }
568
569 rec_cnt = 0;
570 /* flash data records */
571 for (i = 0, j = 0; i < data_len; i++, j++) {
572 if ((data[i] == REC_START_CHR) && j) {
573 buf[j] = 0;
574 rc = flash_data_rec(ts, buf);
575 if (rc < 0)
576 return rc;
577 j = 0;
578 }
579 buf[j] = data[i];
580 }
581
582 /* flash last data record */
583 if (j) {
584 buf[j] = 0;
585 rc = flash_data_rec(ts, buf);
586 if (rc < 0)
587 return rc;
588 }
589
590 kfree(buf);
591
592 /* termiate bootload */
593 tries = 0;
594 rc = flash_command(ts, &terminate_rec);
595 do {
596 msleep(100);
597 cyttsp_putbl(ts, 4, true, false, false);
598 } while (g_bl_data.bl_status != 0x10 &&
599 g_bl_data.bl_status != 0x11 &&
600 tries++ < 100);
601
602 return rc;
603}
604
605static int get_hex_fw_ver(u8 *p, u8 *ttspver_hi, u8 *ttspver_lo,
606 u8 *appid_hi, u8 *appid_lo, u8 *appver_hi,
607 u8 *appver_lo, u8 *cid_0, u8 *cid_1, u8 *cid_2)
608{
609 int rc;
610
611 p = p + ID_INFO_OFFSET_IN_REC;
612 rc = str2uc(p, ttspver_hi);
613 if (rc < 0)
614 return rc;
615 p += 2;
616 rc = str2uc(p, ttspver_lo);
617 if (rc < 0)
618 return rc;
619 p += 2;
620 rc = str2uc(p, appid_hi);
621 if (rc < 0)
622 return rc;
623 p += 2;
624 rc = str2uc(p, appid_lo);
625 if (rc < 0)
626 return rc;
627 p += 2;
628 rc = str2uc(p, appver_hi);
629 if (rc < 0)
630 return rc;
631 p += 2;
632 rc = str2uc(p, appver_lo);
633 if (rc < 0)
634 return rc;
635 p += 2;
636 rc = str2uc(p, cid_0);
637 if (rc < 0)
638 return rc;
639 p += 2;
640 rc = str2uc(p, cid_1);
641 if (rc < 0)
642 return rc;
643 p += 2;
644 rc = str2uc(p, cid_2);
645 if (rc < 0)
646 return rc;
647
648 return 0;
649}
650
651static void cyttspfw_flash_start(struct cyttsp *ts, const u8 *data,
652 int data_len, u8 *buf, bool force)
653{
654 int rc;
655 u8 ttspver_hi = 0, ttspver_lo = 0, fw_upgrade = 0;
656 u8 appid_hi = 0, appid_lo = 0;
657 u8 appver_hi = 0, appver_lo = 0;
658 u8 cid_0 = 0, cid_1 = 0, cid_2 = 0;
659 char *p = buf;
660
661 /* get hex firmware version */
662 rc = get_hex_fw_ver(p, &ttspver_hi, &ttspver_lo,
663 &appid_hi, &appid_lo, &appver_hi,
664 &appver_lo, &cid_0, &cid_1, &cid_2);
665
666 if (rc < 0) {
667 pr_err("%s: unable to get hex firmware version\n", __func__);
668 return;
669 }
670
671 /* disable interrupts before flashing */
672 if (ts->client->irq == 0)
673 del_timer(&ts->timer);
674 else
675 disable_irq(ts->client->irq);
676
677 rc = cancel_work_sync(&ts->work);
678
679 if (rc && ts->client->irq)
680 enable_irq(ts->client->irq);
681
682 /* enter bootloader idle mode */
683 rc = cyttsp_soft_reset(ts);
684
685 if (rc < 0) {
686 pr_err("%s: try entering into idle mode"
687 " second time\n", __func__);
688 msleep(1000);
689 rc = cyttsp_soft_reset(ts);
690 }
691
692 if (rc < 0) {
693 pr_err("%s: try again later\n", __func__);
694 return;
695 }
696
697
698 pr_info("Current firmware: %d.%d.%d", g_bl_data.appid_lo,
699 g_bl_data.appver_hi, g_bl_data.appver_lo);
700 pr_info("New firmware: %d.%d.%d", appid_lo, appver_hi, appver_lo);
701
702 if (force)
703 fw_upgrade = 1;
704 else
705 if ((appid_hi == g_bl_data.appid_hi) &&
706 (appid_lo == g_bl_data.appid_lo)) {
707 if (appver_hi > g_bl_data.appver_hi) {
708 fw_upgrade = 1;
709 } else if ((appver_hi == g_bl_data.appver_hi) &&
710 (appver_lo > g_bl_data.appver_lo)) {
711 fw_upgrade = 1;
712 } else {
713 fw_upgrade = 0;
714 pr_info("%s: Firmware version "
715 "lesser/equal to existing firmware, "
716 "upgrade not needed\n", __func__);
717 }
718 } else {
719 fw_upgrade = 0;
720 pr_info("%s: Firware versions do not match, "
721 "cannot upgrade\n", __func__);
722 }
723
724 if (fw_upgrade) {
725 pr_info("%s: Starting firmware upgrade\n", __func__);
726 rc = cyttspfw_flash_firmware(ts, data, data_len);
727 if (rc < 0)
728 pr_err("%s: firmware upgrade failed\n", __func__);
729 else
730 pr_info("%s: firmware upgrade success\n", __func__);
731 }
732
733 /* enter bootloader idle mode */
734 cyttsp_soft_reset(ts);
735 /* exit bootloader mode */
736 cyttsp_exit_bl_mode(ts);
737 msleep(100);
738 /* set sysinfo details */
739 cyttsp_set_sysinfo_mode(ts);
740 /* enter application mode */
741 cyttsp_set_opmode(ts);
742
743 /* enable interrupts */
744 if (ts->client->irq == 0)
745 mod_timer(&ts->timer, jiffies + TOUCHSCREEN_TIMEOUT);
746 else
747 enable_irq(ts->client->irq);
748}
749
750static void cyttspfw_upgrade_start(struct cyttsp *ts, const u8 *data,
751 int data_len, bool force)
752{
753 int i, j;
754 u8 *buf;
755
756 buf = kzalloc(REC_LINE_SIZE + 1, GFP_KERNEL);
757 if (!buf) {
758 pr_err("%s: no memory\n", __func__);
759 return;
760 }
761
762 for (i = 0, j = 0; i < data_len; i++, j++) {
763 if ((data[i] == REC_START_CHR) && j) {
764 buf[j] = 0;
765 j = 0;
766 if (!strncmp(buf, ID_INFO_REC, strlen(ID_INFO_REC))) {
767 cyttspfw_flash_start(ts, data, data_len,
768 buf, force);
769 break;
770 }
771 }
772 buf[j] = data[i];
773 }
774
775 /* check in the last record of firmware */
776 if (j) {
777 buf[j] = 0;
778 if (!strncmp(buf, ID_INFO_REC, strlen(ID_INFO_REC))) {
779 cyttspfw_flash_start(ts, data, data_len,
780 buf, force);
781 }
782 }
783
784 kfree(buf);
785}
786
787static void cyttspfw_upgrade(struct device *dev, bool force)
788{
789 struct cyttsp *ts = dev_get_drvdata(dev);
790 const struct firmware *cyttsp_fw;
791 int retval = 0;
792
793 if (ts->is_suspended == true) {
794 pr_err("%s: in suspend state, resume it\n", __func__);
795 retval = cyttsp_resume(dev);
796 if (retval < 0) {
797 pr_err("%s: unable to resume\n", __func__);
798 return;
799 }
800 }
801
802 retval = request_firmware(&cyttsp_fw, ts->fw_fname, dev);
803 if (retval < 0) {
804 pr_err("%s: %s request failed(%d)\n", __func__,
805 ts->fw_fname, retval);
806 } else {
807 /* check and start upgrade */
808 cyttspfw_upgrade_start(ts, cyttsp_fw->data,
809 cyttsp_fw->size, force);
810 release_firmware(cyttsp_fw);
811 }
812}
813
814static ssize_t cyttsp_update_fw_show(struct device *dev,
815 struct device_attribute *attr, char *buf)
816{
817 struct cyttsp *ts = dev_get_drvdata(dev);
818 return snprintf(buf, 2, "%d\n", ts->cyttsp_fwloader_mode);
819}
820
821static ssize_t cyttsp_force_update_fw_store(struct device *dev,
822 struct device_attribute *attr,
823 const char *buf, size_t size)
824{
825 struct cyttsp *ts = dev_get_drvdata(dev);
826 unsigned long val;
827 int rc;
828
829 if (size > 2)
830 return -EINVAL;
831
832 rc = strict_strtoul(buf, 10, &val);
833 if (rc != 0)
834 return rc;
835
836 mutex_lock(&ts->mutex);
837 if (!ts->cyttsp_fwloader_mode && val) {
838 ts->cyttsp_fwloader_mode = 1;
839 cyttspfw_upgrade(dev, true);
840 ts->cyttsp_fwloader_mode = 0;
841 }
842 mutex_unlock(&ts->mutex);
843 return size;
844}
845
846static DEVICE_ATTR(cyttsp_force_update_fw, 0777, cyttsp_update_fw_show,
847 cyttsp_force_update_fw_store);
848
849static ssize_t cyttsp_update_fw_store(struct device *dev,
850 struct device_attribute *attr,
851 const char *buf, size_t size)
852{
853 struct cyttsp *ts = dev_get_drvdata(dev);
854 unsigned long val;
855 int rc;
856
857 if (size > 2)
858 return -EINVAL;
859
860 rc = strict_strtoul(buf, 10, &val);
861 if (rc != 0)
862 return rc;
863
864 mutex_lock(&ts->mutex);
865 if (!ts->cyttsp_fwloader_mode && val) {
866 ts->cyttsp_fwloader_mode = 1;
867 cyttspfw_upgrade(dev, false);
868 ts->cyttsp_fwloader_mode = 0;
869 }
870 mutex_unlock(&ts->mutex);
871
872 return size;
873}
874
875static DEVICE_ATTR(cyttsp_update_fw, 0777, cyttsp_update_fw_show,
876 cyttsp_update_fw_store);
877
878static ssize_t cyttsp_fw_name_show(struct device *dev,
879 struct device_attribute *attr, char *buf)
880{
881 struct cyttsp *ts = dev_get_drvdata(dev);
882 return snprintf(buf, FW_FNAME_LEN - 1, "%s\n", ts->fw_fname);
883}
884
885static ssize_t cyttsp_fw_name_store(struct device *dev,
886 struct device_attribute *attr,
887 const char *buf, size_t size)
888{
889 struct cyttsp *ts = dev_get_drvdata(dev);
890
891 if (size > FW_FNAME_LEN - 1)
892 return -EINVAL;
893
894 strncpy(ts->fw_fname, buf, size);
895 if (ts->fw_fname[size-1] == '\n')
896 ts->fw_fname[size-1] = 0;
897
898 return size;
899}
900
901static DEVICE_ATTR(cyttsp_fw_name, 0777, cyttsp_fw_name_show,
902 cyttsp_fw_name_store);
903
904/* The cyttsp_xy_worker function reads the XY coordinates and sends them to
905 * the input layer. It is scheduled from the interrupt (or timer).
906 */
907void cyttsp_xy_worker(struct work_struct *work)
908{
909 struct cyttsp *ts = container_of(work, struct cyttsp, work);
910 u8 id, tilt, rev_x, rev_y;
911 u8 i, loc;
912 u8 prv_tch; /* number of previous touches */
913 u8 cur_tch; /* number of current touches */
914 u16 tmp_trk[CY_NUM_MT_TCH_ID];
915 u16 snd_trk[CY_NUM_MT_TCH_ID];
916 u16 cur_trk[CY_NUM_TRK_ID];
917 u16 cur_st_tch[CY_NUM_ST_TCH_ID];
918 u16 cur_mt_tch[CY_NUM_MT_TCH_ID];
919 /* if NOT CY_USE_TRACKING_ID then
920 * only uses CY_NUM_MT_TCH_ID positions */
921 u16 cur_mt_pos[CY_NUM_TRK_ID][2];
922 /* if NOT CY_USE_TRACKING_ID then
923 * only uses CY_NUM_MT_TCH_ID positions */
924 u8 cur_mt_z[CY_NUM_TRK_ID];
925 u8 curr_tool_width;
926 u16 st_x1, st_y1;
927 u8 st_z1;
928 u16 st_x2, st_y2;
929 u8 st_z2;
930 s32 retval;
931
932 cyttsp_xdebug("TTSP worker start 1:\n");
933
934 /* get event data from CYTTSP device */
935 i = CY_NUM_RETRY;
936 do {
937 retval = i2c_smbus_read_i2c_block_data(ts->client,
938 CY_REG_BASE,
939 sizeof(struct cyttsp_gen3_xydata_t), (u8 *)&g_xy_data);
940 } while ((retval < CY_OK) && --i);
941
942 if (retval < CY_OK) {
943 /* return immediately on
944 * failure to read device on the i2c bus */
945 goto exit_xy_worker;
946 }
947
948 cyttsp_xdebug("TTSP worker start 2:\n");
949
950 /* compare own irq counter with the device irq counter */
951 if (ts->client->irq) {
952 u8 host_reg;
953 u8 cur_cnt;
954 if (ts->platform_data->use_hndshk) {
955
956 host_reg = g_xy_data.hst_mode & CY_HNDSHK_BIT ?
957 g_xy_data.hst_mode & ~CY_HNDSHK_BIT :
958 g_xy_data.hst_mode | CY_HNDSHK_BIT;
959 retval = i2c_smbus_write_i2c_block_data(ts->client,
960 CY_REG_BASE, sizeof(host_reg), &host_reg);
961 }
962 cur_cnt = g_xy_data.tt_undef[CY_IRQ_CNT_REG];
963 irq_cnt_total++;
964 irq_cnt++;
965 if (irq_cnt != cur_cnt) {
966 irq_err_cnt++;
967 cyttsp_debug("i_c_ER: dv=%d fw=%d hm=%02X t=%lu te=%lu\n", \
968 irq_cnt, \
969 cur_cnt, g_xy_data.hst_mode, \
970 (unsigned long)irq_cnt_total, \
971 (unsigned long)irq_err_cnt);
972 } else {
973 cyttsp_debug("i_c_ok: dv=%d fw=%d hm=%02X t=%lu te=%lu\n", \
974 irq_cnt, \
975 cur_cnt, g_xy_data.hst_mode, \
976 (unsigned long)irq_cnt_total, \
977 (unsigned long)irq_err_cnt);
978 }
979 irq_cnt = cur_cnt;
980 }
981
982 /* Get the current num touches and return if there are no touches */
983 if ((GET_BOOTLOADERMODE(g_xy_data.tt_mode) == 1) ||
984 (GET_HSTMODE(g_xy_data.hst_mode) != CY_OK)) {
985 u8 host_reg, tries;
986 /* the TTSP device has suffered spurious reset or mode switch */
987 cyttsp_debug( \
988 "Spurious err opmode (tt_mode=%02X hst_mode=%02X)\n", \
989 g_xy_data.tt_mode, g_xy_data.hst_mode);
990 cyttsp_debug("Reset TTSP Device; Terminating active tracks\n");
991 /* terminate all active tracks */
992 cur_tch = CY_NTCH;
993 /* reset TTSP part and take it back out of Bootloader mode */
994 /* reset TTSP Device back to bootloader mode */
995 host_reg = CY_SOFT_RESET_MODE;
996 retval = i2c_smbus_write_i2c_block_data(ts->client, CY_REG_BASE,
997 sizeof(host_reg), &host_reg);
998 /* wait for TTSP Device to complete reset back to bootloader */
999 tries = 0;
1000 do {
1001 mdelay(1);
1002 cyttsp_putbl(ts, 1, false, false, false);
1003 } while (g_bl_data.bl_status != 0x10 &&
1004 g_bl_data.bl_status != 0x11 &&
1005 tries++ < 100);
1006 retval = cyttsp_putbl(ts, 1, true, true, true);
1007 /* switch back to operational mode */
1008 /* take TTSP device out of bootloader mode;
1009 * switch back to TrueTouch operational mode */
1010 if (!(retval < CY_OK)) {
1011 int tries;
1012 retval = i2c_smbus_write_i2c_block_data(ts->client,
1013 CY_REG_BASE,
1014 sizeof(bl_cmd), bl_cmd);
1015 /* wait for TTSP Device to complete
1016 * switch to Operational mode */
1017 tries = 0;
1018 do {
1019 mdelay(100);
1020 cyttsp_putbl(ts, 2, false, false, false);
1021 } while (GET_BOOTLOADERMODE(g_bl_data.bl_status) &&
1022 tries++ < 100);
1023 cyttsp_putbl(ts, 2, true, false, false);
1024 }
1025 goto exit_xy_worker;
1026 } else {
1027 cur_tch = GET_NUM_TOUCHES(g_xy_data.tt_stat);
1028 if (IS_LARGE_AREA(g_xy_data.tt_stat)) {
1029 /* terminate all active tracks */
1030 cur_tch = CY_NTCH;
1031 cyttsp_debug("Large obj detect (tt_stat=0x%02X). Terminate act trks\n", \
1032 g_xy_data.tt_stat);
1033 } else if (cur_tch > CY_NUM_MT_TCH_ID) {
1034 /* if the number of fingers on the touch surface
1035 * is more than the maximum then
1036 * there will be no new track information
1037 * even for the original touches.
1038 * Therefore, terminate all active tracks.
1039 */
1040 cur_tch = CY_NTCH;
1041 cyttsp_debug("Num touch err (tt_stat=0x%02X). Terminate act trks\n", \
1042 g_xy_data.tt_stat);
1043 }
1044 }
1045
1046 /* set tool size */
1047 curr_tool_width = CY_SMALL_TOOL_WIDTH;
1048
1049 /* translate Gen2 interface data into comparable Gen3 data */
1050 if (ts->platform_data->gen == CY_GEN2) {
1051 struct cyttsp_gen2_xydata_t *pxy_gen2_data;
1052 pxy_gen2_data = (struct cyttsp_gen2_xydata_t *)(&g_xy_data);
1053
1054 /* use test data? */
1055 cyttsp_testdat(&g_xy_data, &tt_gen2_testray, \
1056 sizeof(struct cyttsp_gen3_xydata_t));
1057
1058 if (pxy_gen2_data->evnt_idx == CY_GEN2_NOTOUCH) {
1059 cur_tch = 0;
1060 } else if (cur_tch == CY_GEN2_GHOST) {
1061 cur_tch = 0;
1062 } else if (cur_tch == CY_GEN2_2TOUCH) {
1063 /* stuff artificial track ID1 and ID2 */
1064 g_xy_data.touch12_id = 0x12;
1065 g_xy_data.z1 = CY_MAXZ;
1066 g_xy_data.z2 = CY_MAXZ;
1067 cur_tch--; /* 2 touches */
1068 } else if (cur_tch == CY_GEN2_1TOUCH) {
1069 /* stuff artificial track ID1 and ID2 */
1070 g_xy_data.touch12_id = 0x12;
1071 g_xy_data.z1 = CY_MAXZ;
1072 g_xy_data.z2 = CY_NTCH;
1073 if (pxy_gen2_data->evnt_idx == CY_GEN2_TOUCH2) {
1074 /* push touch 2 data into touch1
1075 * (first finger up; second finger down) */
1076 /* stuff artificial track ID1 for touch2 info */
1077 g_xy_data.touch12_id = 0x20;
1078 /* stuff touch 1 with touch 2 coordinate data */
1079 g_xy_data.x1 = g_xy_data.x2;
1080 g_xy_data.y1 = g_xy_data.y2;
1081 }
1082 } else {
1083 cur_tch = 0;
1084 }
1085 } else {
1086 /* use test data? */
1087 cyttsp_testdat(&g_xy_data, &tt_gen3_testray, \
1088 sizeof(struct cyttsp_gen3_xydata_t));
1089 }
1090
1091
1092
1093 /* clear current active track ID array and count previous touches */
1094 for (id = 0, prv_tch = CY_NTCH;
1095 id < CY_NUM_TRK_ID; id++) {
1096 cur_trk[id] = CY_NTCH;
1097 prv_tch += ts->act_trk[id];
1098 }
1099
1100 /* send no events if no previous touches and no new touches */
1101 if ((prv_tch == CY_NTCH) &&
1102 ((cur_tch == CY_NTCH) ||
1103 (cur_tch > CY_NUM_MT_TCH_ID))) {
1104 goto exit_xy_worker;
1105 }
1106
1107 cyttsp_debug("prev=%d curr=%d\n", prv_tch, cur_tch);
1108
1109 for (id = 0; id < CY_NUM_ST_TCH_ID; id++) {
1110 /* clear current single touches array */
1111 cur_st_tch[id] = CY_IGNR_TCH;
1112 }
1113
1114 /* clear single touch positions */
1115 st_x1 = CY_NTCH;
1116 st_y1 = CY_NTCH;
1117 st_z1 = CY_NTCH;
1118 st_x2 = CY_NTCH;
1119 st_y2 = CY_NTCH;
1120 st_z2 = CY_NTCH;
1121
1122 for (id = 0; id < CY_NUM_MT_TCH_ID; id++) {
1123 /* clear current multi-touches array and
1124 * multi-touch positions/z */
1125 cur_mt_tch[id] = CY_IGNR_TCH;
1126 }
1127
1128 if (ts->platform_data->use_trk_id) {
1129 for (id = 0; id < CY_NUM_MT_TCH_ID; id++) {
1130 cur_mt_pos[id][CY_XPOS] = 0;
1131 cur_mt_pos[id][CY_YPOS] = 0;
1132 cur_mt_z[id] = 0;
1133 }
1134 } else {
1135 for (id = 0; id < CY_NUM_TRK_ID; id++) {
1136 cur_mt_pos[id][CY_XPOS] = 0;
1137 cur_mt_pos[id][CY_YPOS] = 0;
1138 cur_mt_z[id] = 0;
1139 }
1140 }
1141
1142 /* Determine if display is tilted */
1143 if (FLIP_DATA(ts->platform_data->flags))
1144 tilt = true;
1145 else
1146 tilt = false;
1147
1148 /* Check for switch in origin */
1149 if (REVERSE_X(ts->platform_data->flags))
1150 rev_x = true;
1151 else
1152 rev_x = false;
1153
1154 if (REVERSE_Y(ts->platform_data->flags))
1155 rev_y = true;
1156 else
1157 rev_y = false;
1158
1159 if (cur_tch) {
1160 struct cyttsp_gen2_xydata_t *pxy_gen2_data;
1161 struct cyttsp_gen3_xydata_t *pxy_gen3_data;
1162 switch (ts->platform_data->gen) {
1163 case CY_GEN2: {
1164 pxy_gen2_data =
1165 (struct cyttsp_gen2_xydata_t *)(&g_xy_data);
1166 cyttsp_xdebug("TTSP Gen2 report:\n");
1167 cyttsp_xdebug("%02X %02X %02X\n", \
1168 pxy_gen2_data->hst_mode, \
1169 pxy_gen2_data->tt_mode, \
1170 pxy_gen2_data->tt_stat);
1171 cyttsp_xdebug("%04X %04X %02X %02X\n", \
1172 pxy_gen2_data->x1, \
1173 pxy_gen2_data->y1, \
1174 pxy_gen2_data->z1, \
1175 pxy_gen2_data->evnt_idx);
1176 cyttsp_xdebug("%04X %04X %02X\n", \
1177 pxy_gen2_data->x2, \
1178 pxy_gen2_data->y2, \
1179 pxy_gen2_data->tt_undef1);
1180 cyttsp_xdebug("%02X %02X %02X\n", \
1181 pxy_gen2_data->gest_cnt, \
1182 pxy_gen2_data->gest_id, \
1183 pxy_gen2_data->gest_set);
1184 break;
1185 }
1186 case CY_GEN3:
1187 default: {
1188 pxy_gen3_data =
1189 (struct cyttsp_gen3_xydata_t *)(&g_xy_data);
1190 cyttsp_xdebug("TTSP Gen3 report:\n");
1191 cyttsp_xdebug("%02X %02X %02X\n", \
1192 pxy_gen3_data->hst_mode,
1193 pxy_gen3_data->tt_mode,
1194 pxy_gen3_data->tt_stat);
1195 cyttsp_xdebug("%04X %04X %02X %02X", \
1196 pxy_gen3_data->x1,
1197 pxy_gen3_data->y1,
1198 pxy_gen3_data->z1, \
1199 pxy_gen3_data->touch12_id);
1200 cyttsp_xdebug("%04X %04X %02X\n", \
1201 pxy_gen3_data->x2, \
1202 pxy_gen3_data->y2, \
1203 pxy_gen3_data->z2);
1204 cyttsp_xdebug("%02X %02X %02X\n", \
1205 pxy_gen3_data->gest_cnt, \
1206 pxy_gen3_data->gest_id, \
1207 pxy_gen3_data->gest_set);
1208 cyttsp_xdebug("%04X %04X %02X %02X\n", \
1209 pxy_gen3_data->x3, \
1210 pxy_gen3_data->y3, \
1211 pxy_gen3_data->z3, \
1212 pxy_gen3_data->touch34_id);
1213 cyttsp_xdebug("%04X %04X %02X\n", \
1214 pxy_gen3_data->x4, \
1215 pxy_gen3_data->y4, \
1216 pxy_gen3_data->z4);
1217 break;
1218 }
1219 }
1220 }
1221
1222 /* process the touches */
1223 switch (cur_tch) {
1224 case 4: {
1225 g_xy_data.x4 = be16_to_cpu(g_xy_data.x4);
1226 g_xy_data.y4 = be16_to_cpu(g_xy_data.y4);
1227 if (tilt)
1228 FLIP_XY(g_xy_data.x4, g_xy_data.y4);
1229
1230 if (rev_x) {
1231 g_xy_data.x4 = INVERT_X(g_xy_data.x4,
1232 ts->platform_data->panel_maxx);
1233 if (g_xy_data.x4 < 0)
1234 pr_debug("X value is negative. Please configure"
1235 " maxx in platform data structure\n");
1236 }
1237 if (rev_y) {
1238 g_xy_data.y4 = INVERT_X(g_xy_data.y4,
1239 ts->platform_data->panel_maxy);
1240 if (g_xy_data.y4 < 0)
1241 pr_debug("Y value is negative. Please configure"
1242 " maxy in platform data structure\n");
1243
1244 }
1245 id = GET_TOUCH4_ID(g_xy_data.touch34_id);
1246 if (ts->platform_data->use_trk_id) {
1247 cur_mt_pos[CY_MT_TCH4_IDX][CY_XPOS] =
1248 g_xy_data.x4;
1249 cur_mt_pos[CY_MT_TCH4_IDX][CY_YPOS] =
1250 g_xy_data.y4;
1251 cur_mt_z[CY_MT_TCH4_IDX] = g_xy_data.z4;
1252 } else {
1253 cur_mt_pos[id][CY_XPOS] = g_xy_data.x4;
1254 cur_mt_pos[id][CY_YPOS] = g_xy_data.y4;
1255 cur_mt_z[id] = g_xy_data.z4;
1256 }
1257 cur_mt_tch[CY_MT_TCH4_IDX] = id;
1258 cur_trk[id] = CY_TCH;
1259 if (ts->prv_st_tch[CY_ST_FNGR1_IDX] <
1260 CY_NUM_TRK_ID) {
1261 if (ts->prv_st_tch[CY_ST_FNGR1_IDX] == id) {
1262 st_x1 = g_xy_data.x4;
1263 st_y1 = g_xy_data.y4;
1264 st_z1 = g_xy_data.z4;
1265 cur_st_tch[CY_ST_FNGR1_IDX] = id;
1266 } else if (ts->prv_st_tch[CY_ST_FNGR2_IDX] == id) {
1267 st_x2 = g_xy_data.x4;
1268 st_y2 = g_xy_data.y4;
1269 st_z2 = g_xy_data.z4;
1270 cur_st_tch[CY_ST_FNGR2_IDX] = id;
1271 }
1272 }
1273 cyttsp_xdebug("4th XYZ:% 3d,% 3d,% 3d ID:% 2d\n\n", \
1274 g_xy_data.x4, g_xy_data.y4, g_xy_data.z4, \
1275 (g_xy_data.touch34_id & 0x0F));
1276 /* do not break */
1277 }
1278 case 3: {
1279 g_xy_data.x3 = be16_to_cpu(g_xy_data.x3);
1280 g_xy_data.y3 = be16_to_cpu(g_xy_data.y3);
1281 if (tilt)
1282 FLIP_XY(g_xy_data.x3, g_xy_data.y3);
1283
1284 if (rev_x) {
1285 g_xy_data.x3 = INVERT_X(g_xy_data.x3,
1286 ts->platform_data->panel_maxx);
1287 if (g_xy_data.x3 < 0)
1288 pr_debug("X value is negative. Please configure"
1289 " maxx in platform data structure\n");
1290
1291 }
1292 if (rev_y) {
1293 g_xy_data.y3 = INVERT_X(g_xy_data.y3,
1294 ts->platform_data->panel_maxy);
1295 if (g_xy_data.y3 < 0)
1296 pr_debug("Y value is negative. Please configure"
1297 " maxy in platform data structure\n");
1298
1299 }
1300 id = GET_TOUCH3_ID(g_xy_data.touch34_id);
1301 if (ts->platform_data->use_trk_id) {
1302 cur_mt_pos[CY_MT_TCH3_IDX][CY_XPOS] =
1303 g_xy_data.x3;
1304 cur_mt_pos[CY_MT_TCH3_IDX][CY_YPOS] =
1305 g_xy_data.y3;
1306 cur_mt_z[CY_MT_TCH3_IDX] = g_xy_data.z3;
1307 } else {
1308 cur_mt_pos[id][CY_XPOS] = g_xy_data.x3;
1309 cur_mt_pos[id][CY_YPOS] = g_xy_data.y3;
1310 cur_mt_z[id] = g_xy_data.z3;
1311 }
1312 cur_mt_tch[CY_MT_TCH3_IDX] = id;
1313 cur_trk[id] = CY_TCH;
1314 if (ts->prv_st_tch[CY_ST_FNGR1_IDX] <
1315 CY_NUM_TRK_ID) {
1316 if (ts->prv_st_tch[CY_ST_FNGR1_IDX] == id) {
1317 st_x1 = g_xy_data.x3;
1318 st_y1 = g_xy_data.y3;
1319 st_z1 = g_xy_data.z3;
1320 cur_st_tch[CY_ST_FNGR1_IDX] = id;
1321 } else if (ts->prv_st_tch[CY_ST_FNGR2_IDX] == id) {
1322 st_x2 = g_xy_data.x3;
1323 st_y2 = g_xy_data.y3;
1324 st_z2 = g_xy_data.z3;
1325 cur_st_tch[CY_ST_FNGR2_IDX] = id;
1326 }
1327 }
1328 cyttsp_xdebug("3rd XYZ:% 3d,% 3d,% 3d ID:% 2d\n", \
1329 g_xy_data.x3, g_xy_data.y3, g_xy_data.z3, \
1330 ((g_xy_data.touch34_id >> 4) & 0x0F));
1331 /* do not break */
1332 }
1333 case 2: {
1334 g_xy_data.x2 = be16_to_cpu(g_xy_data.x2);
1335 g_xy_data.y2 = be16_to_cpu(g_xy_data.y2);
1336 if (tilt)
1337 FLIP_XY(g_xy_data.x2, g_xy_data.y2);
1338
1339 if (rev_x) {
1340 g_xy_data.x2 = INVERT_X(g_xy_data.x2,
1341 ts->platform_data->panel_maxx);
1342 if (g_xy_data.x2 < 0)
1343 pr_debug("X value is negative. Please configure"
1344 " maxx in platform data structure\n");
1345 }
1346 if (rev_y) {
1347 g_xy_data.y2 = INVERT_X(g_xy_data.y2,
1348 ts->platform_data->panel_maxy);
1349 if (g_xy_data.y2 < 0)
1350 pr_debug("Y value is negative. Please configure"
1351 " maxy in platform data structure\n");
1352 }
1353 id = GET_TOUCH2_ID(g_xy_data.touch12_id);
1354 if (ts->platform_data->use_trk_id) {
1355 cur_mt_pos[CY_MT_TCH2_IDX][CY_XPOS] =
1356 g_xy_data.x2;
1357 cur_mt_pos[CY_MT_TCH2_IDX][CY_YPOS] =
1358 g_xy_data.y2;
1359 cur_mt_z[CY_MT_TCH2_IDX] = g_xy_data.z2;
1360 } else {
1361 cur_mt_pos[id][CY_XPOS] = g_xy_data.x2;
1362 cur_mt_pos[id][CY_YPOS] = g_xy_data.y2;
1363 cur_mt_z[id] = g_xy_data.z2;
1364 }
1365 cur_mt_tch[CY_MT_TCH2_IDX] = id;
1366 cur_trk[id] = CY_TCH;
1367 if (ts->prv_st_tch[CY_ST_FNGR1_IDX] <
1368 CY_NUM_TRK_ID) {
1369 if (ts->prv_st_tch[CY_ST_FNGR1_IDX] == id) {
1370 st_x1 = g_xy_data.x2;
1371 st_y1 = g_xy_data.y2;
1372 st_z1 = g_xy_data.z2;
1373 cur_st_tch[CY_ST_FNGR1_IDX] = id;
1374 } else if (ts->prv_st_tch[CY_ST_FNGR2_IDX] == id) {
1375 st_x2 = g_xy_data.x2;
1376 st_y2 = g_xy_data.y2;
1377 st_z2 = g_xy_data.z2;
1378 cur_st_tch[CY_ST_FNGR2_IDX] = id;
1379 }
1380 }
1381 cyttsp_xdebug("2nd XYZ:% 3d,% 3d,% 3d ID:% 2d\n", \
1382 g_xy_data.x2, g_xy_data.y2, g_xy_data.z2, \
1383 (g_xy_data.touch12_id & 0x0F));
1384 /* do not break */
1385 }
1386 case 1: {
1387 g_xy_data.x1 = be16_to_cpu(g_xy_data.x1);
1388 g_xy_data.y1 = be16_to_cpu(g_xy_data.y1);
1389 if (tilt)
1390 FLIP_XY(g_xy_data.x1, g_xy_data.y1);
1391
1392 if (rev_x) {
1393 g_xy_data.x1 = INVERT_X(g_xy_data.x1,
1394 ts->platform_data->panel_maxx);
1395 if (g_xy_data.x1 < 0)
1396 pr_debug("X value is negative. Please configure"
1397 " maxx in platform data structure\n");
1398 }
1399 if (rev_y) {
1400 g_xy_data.y1 = INVERT_X(g_xy_data.y1,
1401 ts->platform_data->panel_maxy);
1402 if (g_xy_data.y1 < 0)
1403 pr_debug("Y value is negative. Please configure"
1404 " maxy in platform data structure");
1405 }
1406 id = GET_TOUCH1_ID(g_xy_data.touch12_id);
1407 if (ts->platform_data->use_trk_id) {
1408 cur_mt_pos[CY_MT_TCH1_IDX][CY_XPOS] =
1409 g_xy_data.x1;
1410 cur_mt_pos[CY_MT_TCH1_IDX][CY_YPOS] =
1411 g_xy_data.y1;
1412 cur_mt_z[CY_MT_TCH1_IDX] = g_xy_data.z1;
1413 } else {
1414 cur_mt_pos[id][CY_XPOS] = g_xy_data.x1;
1415 cur_mt_pos[id][CY_YPOS] = g_xy_data.y1;
1416 cur_mt_z[id] = g_xy_data.z1;
1417 }
1418 cur_mt_tch[CY_MT_TCH1_IDX] = id;
1419 cur_trk[id] = CY_TCH;
1420 if (ts->prv_st_tch[CY_ST_FNGR1_IDX] <
1421 CY_NUM_TRK_ID) {
1422 if (ts->prv_st_tch[CY_ST_FNGR1_IDX] == id) {
1423 st_x1 = g_xy_data.x1;
1424 st_y1 = g_xy_data.y1;
1425 st_z1 = g_xy_data.z1;
1426 cur_st_tch[CY_ST_FNGR1_IDX] = id;
1427 } else if (ts->prv_st_tch[CY_ST_FNGR2_IDX] == id) {
1428 st_x2 = g_xy_data.x1;
1429 st_y2 = g_xy_data.y1;
1430 st_z2 = g_xy_data.z1;
1431 cur_st_tch[CY_ST_FNGR2_IDX] = id;
1432 }
1433 }
1434 cyttsp_xdebug("1st XYZ:% 3d,% 3d,% 3d ID:% 2d\n", \
1435 g_xy_data.x1, g_xy_data.y1, g_xy_data.z1, \
1436 ((g_xy_data.touch12_id >> 4) & 0x0F));
1437 break;
1438 }
1439 case 0:
1440 default:{
1441 break;
1442 }
1443 }
1444
1445 /* handle Single Touch signals */
1446 if (ts->platform_data->use_st) {
1447 cyttsp_xdebug("ST STEP 0 - ST1 ID=%d ST2 ID=%d\n", \
1448 cur_st_tch[CY_ST_FNGR1_IDX], \
1449 cur_st_tch[CY_ST_FNGR2_IDX]);
1450 if (cur_st_tch[CY_ST_FNGR1_IDX] > CY_NUM_TRK_ID) {
1451 /* reassign finger 1 and 2 positions to new tracks */
1452 if (cur_tch > 0) {
1453 /* reassign st finger1 */
1454 if (ts->platform_data->use_trk_id) {
1455 id = CY_MT_TCH1_IDX;
1456 cur_st_tch[CY_ST_FNGR1_IDX] = cur_mt_tch[id];
1457 } else {
1458 id = GET_TOUCH1_ID(g_xy_data.touch12_id);
1459 cur_st_tch[CY_ST_FNGR1_IDX] = id;
1460 }
1461 st_x1 = cur_mt_pos[id][CY_XPOS];
1462 st_y1 = cur_mt_pos[id][CY_YPOS];
1463 st_z1 = cur_mt_z[id];
1464 cyttsp_xdebug("ST STEP 1 - ST1 ID=%3d\n", \
1465 cur_st_tch[CY_ST_FNGR1_IDX]);
1466 if ((cur_tch > 1) &&
1467 (cur_st_tch[CY_ST_FNGR2_IDX] >
1468 CY_NUM_TRK_ID)) {
1469 /* reassign st finger2 */
1470 if (cur_tch > 1) {
1471 if (ts->platform_data->use_trk_id) {
1472 id = CY_MT_TCH2_IDX;
1473 cur_st_tch[CY_ST_FNGR2_IDX] = cur_mt_tch[id];
1474 } else {
1475 id = GET_TOUCH2_ID(g_xy_data.touch12_id);
1476 cur_st_tch[CY_ST_FNGR2_IDX] = id;
1477 }
1478 st_x2 = cur_mt_pos[id][CY_XPOS];
1479 st_y2 = cur_mt_pos[id][CY_YPOS];
1480 st_z2 = cur_mt_z[id];
1481 cyttsp_xdebug("ST STEP 2 - ST2 ID=%3d\n", \
1482 cur_st_tch[CY_ST_FNGR2_IDX]);
1483 }
1484 }
1485 }
1486 } else if (cur_st_tch[CY_ST_FNGR2_IDX] > CY_NUM_TRK_ID) {
1487 if (cur_tch > 1) {
1488 /* reassign st finger2 */
1489 if (ts->platform_data->use_trk_id) {
1490 /* reassign st finger2 */
1491 id = CY_MT_TCH2_IDX;
1492 cur_st_tch[CY_ST_FNGR2_IDX] =
1493 cur_mt_tch[id];
1494 } else {
1495 /* reassign st finger2 */
1496 id = GET_TOUCH2_ID(g_xy_data.touch12_id);
1497 cur_st_tch[CY_ST_FNGR2_IDX] = id;
1498 }
1499 st_x2 = cur_mt_pos[id][CY_XPOS];
1500 st_y2 = cur_mt_pos[id][CY_YPOS];
1501 st_z2 = cur_mt_z[id];
1502 cyttsp_xdebug("ST STEP 3 - ST2 ID=%3d\n", \
1503 cur_st_tch[CY_ST_FNGR2_IDX]);
1504 }
1505 }
1506 /* if the 1st touch is missing and there is a 2nd touch,
1507 * then set the 1st touch to 2nd touch and terminate 2nd touch
1508 */
1509 if ((cur_st_tch[CY_ST_FNGR1_IDX] > CY_NUM_TRK_ID) &&
1510 (cur_st_tch[CY_ST_FNGR2_IDX] < CY_NUM_TRK_ID)) {
1511 st_x1 = st_x2;
1512 st_y1 = st_y2;
1513 st_z1 = st_z2;
1514 cur_st_tch[CY_ST_FNGR1_IDX] =
1515 cur_st_tch[CY_ST_FNGR2_IDX];
1516 cur_st_tch[CY_ST_FNGR2_IDX] =
1517 CY_IGNR_TCH;
1518 }
1519 /* if the 2nd touch ends up equal to the 1st touch,
1520 * then just report a single touch */
1521 if (cur_st_tch[CY_ST_FNGR1_IDX] ==
1522 cur_st_tch[CY_ST_FNGR2_IDX]) {
1523 cur_st_tch[CY_ST_FNGR2_IDX] =
1524 CY_IGNR_TCH;
1525 }
1526 /* set Single Touch current event signals */
1527 if (cur_st_tch[CY_ST_FNGR1_IDX] < CY_NUM_TRK_ID) {
1528 input_report_abs(ts->input,
1529 ABS_X, st_x1);
1530 input_report_abs(ts->input,
1531 ABS_Y, st_y1);
1532 input_report_abs(ts->input,
1533 ABS_PRESSURE, st_z1);
1534 input_report_key(ts->input,
1535 BTN_TOUCH,
1536 CY_TCH);
1537 input_report_abs(ts->input,
1538 ABS_TOOL_WIDTH,
1539 curr_tool_width);
1540 cyttsp_debug("ST->F1:%3d X:%3d Y:%3d Z:%3d\n", \
1541 cur_st_tch[CY_ST_FNGR1_IDX], \
1542 st_x1, st_y1, st_z1);
1543 if (cur_st_tch[CY_ST_FNGR2_IDX] < CY_NUM_TRK_ID) {
1544 input_report_key(ts->input, BTN_2, CY_TCH);
1545 input_report_abs(ts->input, ABS_HAT0X, st_x2);
1546 input_report_abs(ts->input, ABS_HAT0Y, st_y2);
1547 cyttsp_debug("ST->F2:%3d X:%3d Y:%3d Z:%3d\n", \
1548 cur_st_tch[CY_ST_FNGR2_IDX],
1549 st_x2, st_y2, st_z2);
1550 } else {
1551 input_report_key(ts->input,
1552 BTN_2,
1553 CY_NTCH);
1554 }
1555 } else {
1556 input_report_abs(ts->input, ABS_PRESSURE, CY_NTCH);
1557 input_report_key(ts->input, BTN_TOUCH, CY_NTCH);
1558 input_report_key(ts->input, BTN_2, CY_NTCH);
1559 }
1560 /* update platform data for the current single touch info */
1561 ts->prv_st_tch[CY_ST_FNGR1_IDX] = cur_st_tch[CY_ST_FNGR1_IDX];
1562 ts->prv_st_tch[CY_ST_FNGR2_IDX] = cur_st_tch[CY_ST_FNGR2_IDX];
1563
1564 }
1565
1566 /* handle Multi-touch signals */
1567 if (ts->platform_data->use_mt) {
1568 if (ts->platform_data->use_trk_id) {
1569 /* terminate any previous touch where the track
1570 * is missing from the current event */
1571 for (id = 0; id < CY_NUM_TRK_ID; id++) {
1572 if ((ts->act_trk[id] != CY_NTCH) &&
1573 (cur_trk[id] == CY_NTCH)) {
1574 input_report_abs(ts->input,
1575 ABS_MT_TRACKING_ID,
1576 id);
1577 input_report_abs(ts->input,
1578 ABS_MT_TOUCH_MAJOR,
1579 CY_NTCH);
1580 input_report_abs(ts->input,
1581 ABS_MT_WIDTH_MAJOR,
1582 curr_tool_width);
1583 input_report_abs(ts->input,
1584 ABS_MT_POSITION_X,
1585 ts->prv_mt_pos[id][CY_XPOS]);
1586 input_report_abs(ts->input,
1587 ABS_MT_POSITION_Y,
1588 ts->prv_mt_pos[id][CY_YPOS]);
1589 CY_MT_SYNC(ts->input);
1590 ts->act_trk[id] = CY_NTCH;
1591 ts->prv_mt_pos[id][CY_XPOS] = 0;
1592 ts->prv_mt_pos[id][CY_YPOS] = 0;
1593 }
1594 }
1595 /* set Multi-Touch current event signals */
1596 for (id = 0; id < CY_NUM_MT_TCH_ID; id++) {
1597 if (cur_mt_tch[id] < CY_NUM_TRK_ID) {
1598 input_report_abs(ts->input,
1599 ABS_MT_TRACKING_ID,
1600 cur_mt_tch[id]);
1601 input_report_abs(ts->input,
1602 ABS_MT_TOUCH_MAJOR,
1603 cur_mt_z[id]);
1604 input_report_abs(ts->input,
1605 ABS_MT_WIDTH_MAJOR,
1606 curr_tool_width);
1607 input_report_abs(ts->input,
1608 ABS_MT_POSITION_X,
1609 cur_mt_pos[id][CY_XPOS]);
1610 input_report_abs(ts->input,
1611 ABS_MT_POSITION_Y,
1612 cur_mt_pos[id][CY_YPOS]);
1613 CY_MT_SYNC(ts->input);
1614 ts->act_trk[id] = CY_TCH;
1615 ts->prv_mt_pos[id][CY_XPOS] =
1616 cur_mt_pos[id][CY_XPOS];
1617 ts->prv_mt_pos[id][CY_YPOS] =
1618 cur_mt_pos[id][CY_YPOS];
1619 }
1620 }
1621 } else {
1622 /* set temporary track array elements to voids */
1623 for (id = 0; id < CY_NUM_MT_TCH_ID; id++) {
1624 tmp_trk[id] = CY_IGNR_TCH;
1625 snd_trk[id] = CY_IGNR_TCH;
1626 }
1627
1628 /* get what is currently active */
1629 for (i = 0, id = 0;
1630 id < CY_NUM_TRK_ID && i < CY_NUM_MT_TCH_ID;
1631 id++) {
1632 if (cur_trk[id] == CY_TCH) {
1633 /* only incr counter if track found */
1634 tmp_trk[i] = id;
1635 i++;
1636 }
1637 }
1638 cyttsp_xdebug("T1: t0=%d, t1=%d, t2=%d, t3=%d\n", \
1639 tmp_trk[0], tmp_trk[1], tmp_trk[2], \
1640 tmp_trk[3]);
1641 cyttsp_xdebug("T1: p0=%d, p1=%d, p2=%d, p3=%d\n", \
1642 ts->prv_mt_tch[0], ts->prv_mt_tch[1], \
1643 ts->prv_mt_tch[2], ts->prv_mt_tch[3]);
1644
1645 /* pack in still active previous touches */
1646 for (id = 0, prv_tch = 0;
1647 id < CY_NUM_MT_TCH_ID; id++) {
1648 if (tmp_trk[id] < CY_NUM_TRK_ID) {
1649 if (cyttsp_inlist(ts->prv_mt_tch,
1650 tmp_trk[id], &loc,
1651 CY_NUM_MT_TCH_ID)) {
1652 loc &= CY_NUM_MT_TCH_ID - 1;
1653 snd_trk[loc] = tmp_trk[id];
1654 prv_tch++;
1655 cyttsp_xdebug("inlist s[%d]=%d t[%d]=%d l=%d p=%d\n", \
1656 loc, snd_trk[loc], \
1657 id, tmp_trk[id], \
1658 loc, prv_tch);
1659 } else {
1660 cyttsp_xdebug("not inlist s[%d]=%d t[%d]=%d l=%d \n", \
1661 id, snd_trk[id], \
1662 id, tmp_trk[id], \
1663 loc);
1664 }
1665 }
1666 }
1667 cyttsp_xdebug("S1: s0=%d, s1=%d, s2=%d, s3=%d p=%d\n", \
1668 snd_trk[0], snd_trk[1], snd_trk[2], \
1669 snd_trk[3], prv_tch);
1670
1671 /* pack in new touches */
1672 for (id = 0; id < CY_NUM_MT_TCH_ID; id++) {
1673 if (tmp_trk[id] < CY_NUM_TRK_ID) {
1674 if (!cyttsp_inlist(snd_trk, tmp_trk[id], &loc, CY_NUM_MT_TCH_ID)) {
1675 cyttsp_xdebug("not inlist t[%d]=%d l=%d\n", \
1676 id, tmp_trk[id], loc);
1677 if (cyttsp_next_avail_inlist(snd_trk, &loc, CY_NUM_MT_TCH_ID)) {
1678 loc &= CY_NUM_MT_TCH_ID - 1;
1679 snd_trk[loc] = tmp_trk[id];
1680 cyttsp_xdebug("put inlist s[%d]=%d t[%d]=%d\n",
1681 loc, snd_trk[loc], id, tmp_trk[id]);
1682 }
1683 } else {
1684 cyttsp_xdebug("is in list s[%d]=%d t[%d]=%d loc=%d\n", \
1685 id, snd_trk[id], id, tmp_trk[id], loc);
1686 }
1687 }
1688 }
1689 cyttsp_xdebug("S2: s0=%d, s1=%d, s2=%d, s3=%d\n", \
1690 snd_trk[0], snd_trk[1],
1691 snd_trk[2], snd_trk[3]);
1692
1693 /* sync motion event signals for each current touch */
1694 for (id = 0; id < CY_NUM_MT_TCH_ID; id++) {
1695 /* z will either be 0 (NOTOUCH) or
1696 * some pressure (TOUCH) */
1697 cyttsp_xdebug("MT0 prev[%d]=%d temp[%d]=%d send[%d]=%d\n", \
1698 id, ts->prv_mt_tch[id], \
1699 id, tmp_trk[id], \
1700 id, snd_trk[id]);
1701 if (snd_trk[id] < CY_NUM_TRK_ID) {
1702 input_report_abs(ts->input,
1703 ABS_MT_TOUCH_MAJOR,
1704 cur_mt_z[snd_trk[id]]);
1705 input_report_abs(ts->input,
1706 ABS_MT_WIDTH_MAJOR,
1707 curr_tool_width);
1708 input_report_abs(ts->input,
1709 ABS_MT_POSITION_X,
1710 cur_mt_pos[snd_trk[id]][CY_XPOS]);
1711 input_report_abs(ts->input,
1712 ABS_MT_POSITION_Y,
1713 cur_mt_pos[snd_trk[id]][CY_YPOS]);
1714 CY_MT_SYNC(ts->input);
1715 cyttsp_debug("MT1->TID:%2d X:%3d Y:%3d Z:%3d touch-sent\n", \
1716 snd_trk[id], \
1717 cur_mt_pos[snd_trk[id]][CY_XPOS], \
1718 cur_mt_pos[snd_trk[id]][CY_YPOS], \
1719 cur_mt_z[snd_trk[id]]);
1720 } else if (ts->prv_mt_tch[id] < CY_NUM_TRK_ID) {
1721 /* void out this touch */
1722 input_report_abs(ts->input,
1723 ABS_MT_TOUCH_MAJOR,
1724 CY_NTCH);
1725 input_report_abs(ts->input,
1726 ABS_MT_WIDTH_MAJOR,
1727 curr_tool_width);
1728 input_report_abs(ts->input,
1729 ABS_MT_POSITION_X,
1730 ts->prv_mt_pos[ts->prv_mt_tch[id]][CY_XPOS]);
1731 input_report_abs(ts->input,
1732 ABS_MT_POSITION_Y,
1733 ts->prv_mt_pos[ts->prv_mt_tch[id]][CY_YPOS]);
1734 CY_MT_SYNC(ts->input);
1735 cyttsp_debug("MT2->TID:%2d X:%3d Y:%3d Z:%3d lift off-sent\n", \
1736 ts->prv_mt_tch[id], \
1737 ts->prv_mt_pos[ts->prv_mt_tch[id]][CY_XPOS], \
1738 ts->prv_mt_pos[ts->prv_mt_tch[id]][CY_YPOS], \
1739 CY_NTCH);
1740 } else {
1741 /* do not stuff any signals for this
1742 * previously and currently
1743 * void touches */
1744 cyttsp_xdebug("MT3->send[%d]=%d - No touch - NOT sent\n", \
1745 id, snd_trk[id]);
1746 }
1747 }
1748
1749 /* save current posted tracks to
1750 * previous track memory */
1751 for (id = 0; id < CY_NUM_MT_TCH_ID; id++) {
1752 ts->prv_mt_tch[id] = snd_trk[id];
1753 if (snd_trk[id] < CY_NUM_TRK_ID) {
1754 ts->prv_mt_pos[snd_trk[id]][CY_XPOS] =
1755 cur_mt_pos[snd_trk[id]][CY_XPOS];
1756 ts->prv_mt_pos[snd_trk[id]][CY_YPOS] =
1757 cur_mt_pos[snd_trk[id]][CY_YPOS];
1758 cyttsp_xdebug("MT4->TID:%2d X:%3d Y:%3d Z:%3d save for previous\n", \
1759 snd_trk[id], \
1760 ts->prv_mt_pos[snd_trk[id]][CY_XPOS], \
1761 ts->prv_mt_pos[snd_trk[id]][CY_YPOS], \
1762 CY_NTCH);
1763 }
1764 }
1765 for (id = 0; id < CY_NUM_TRK_ID; id++)
1766 ts->act_trk[id] = CY_NTCH;
1767 for (id = 0; id < CY_NUM_MT_TCH_ID; id++) {
1768 if (snd_trk[id] < CY_NUM_TRK_ID)
1769 ts->act_trk[snd_trk[id]] = CY_TCH;
1770 }
1771 }
1772 }
1773
1774 /* handle gestures */
1775 if (ts->platform_data->use_gestures) {
1776 if (g_xy_data.gest_id) {
1777 input_report_key(ts->input,
1778 BTN_3, CY_TCH);
1779 input_report_abs(ts->input,
1780 ABS_HAT1X, g_xy_data.gest_id);
1781 input_report_abs(ts->input,
1782 ABS_HAT2Y, g_xy_data.gest_cnt);
1783 }
1784 }
1785
1786 /* signal the view motion event */
1787 input_sync(ts->input);
1788
1789 for (id = 0; id < CY_NUM_TRK_ID; id++) {
1790 /* update platform data for the current MT information */
1791 ts->act_trk[id] = cur_trk[id];
1792 }
1793
1794exit_xy_worker:
1795 if (cyttsp_disable_touch) {
1796 /* Turn off the touch interrupts */
1797 cyttsp_debug("Not enabling touch\n");
1798 } else {
1799 if (ts->client->irq == 0) {
1800 /* restart event timer */
1801 mod_timer(&ts->timer, jiffies + TOUCHSCREEN_TIMEOUT);
1802 } else {
1803 /* re-enable the interrupt after processing */
1804 enable_irq(ts->client->irq);
1805 }
1806 }
1807 return;
1808}
1809
1810static int cyttsp_inlist(u16 prev_track[], u8 cur_trk_id,
1811 u8 *prev_loc, u8 num_touches)
1812{
1813 u8 id = 0;
1814
1815 *prev_loc = CY_IGNR_TCH;
1816
1817 cyttsp_xdebug("IN p[%d]=%d c=%d n=%d loc=%d\n", \
1818 id, prev_track[id], cur_trk_id, \
1819 num_touches, *prev_loc);
1820 for (id = 0, *prev_loc = CY_IGNR_TCH;
1821 (id < num_touches); id++) {
1822 cyttsp_xdebug("p[%d]=%d c=%d n=%d loc=%d\n", \
1823 id, prev_track[id], cur_trk_id, \
1824 num_touches, *prev_loc);
1825 if (prev_track[id] == cur_trk_id) {
1826 *prev_loc = id;
1827 break;
1828 }
1829 }
1830 cyttsp_xdebug("OUT p[%d]=%d c=%d n=%d loc=%d\n", \
1831 id, prev_track[id], cur_trk_id, num_touches, *prev_loc);
1832
1833 return ((*prev_loc < CY_NUM_TRK_ID) ? true : false);
1834}
1835
1836static int cyttsp_next_avail_inlist(u16 cur_trk[],
1837 u8 *new_loc, u8 num_touches)
1838{
1839 u8 id;
1840
1841 for (id = 0, *new_loc = CY_IGNR_TCH;
1842 (id < num_touches); id++) {
1843 if (cur_trk[id] > CY_NUM_TRK_ID) {
1844 *new_loc = id;
1845 break;
1846 }
1847 }
1848
1849 return ((*new_loc < CY_NUM_TRK_ID) ? true : false);
1850}
1851
1852/* Timer function used as dummy interrupt driver */
1853static void cyttsp_timer(unsigned long handle)
1854{
1855 struct cyttsp *ts = (struct cyttsp *) handle;
1856
1857 cyttsp_xdebug("TTSP Device timer event\n");
1858
1859 /* schedule motion signal handling */
1860 queue_work(cyttsp_ts_wq, &ts->work);
1861
1862 return;
1863}
1864
1865
1866
1867/* ************************************************************************
1868 * ISR function. This function is general, initialized in drivers init
1869 * function
1870 * ************************************************************************ */
1871static irqreturn_t cyttsp_irq(int irq, void *handle)
1872{
1873 struct cyttsp *ts = (struct cyttsp *) handle;
1874
1875 cyttsp_xdebug("%s: Got IRQ\n", CY_I2C_NAME);
1876
1877 /* disable further interrupts until this interrupt is processed */
1878 disable_irq_nosync(ts->client->irq);
1879
1880 /* schedule motion signal handling */
1881 queue_work(cyttsp_ts_wq, &ts->work);
1882 return IRQ_HANDLED;
1883}
1884
1885/* ************************************************************************
1886 * Probe initialization functions
1887 * ************************************************************************ */
1888static int cyttsp_putbl(struct cyttsp *ts, int show,
1889 int show_status, int show_version, int show_cid)
1890{
1891 int retval = CY_OK;
1892
1893 int num_bytes = (show_status * 3) + (show_version * 6) + (show_cid * 3);
1894
1895 if (show_cid)
1896 num_bytes = sizeof(struct cyttsp_bootloader_data_t);
1897 else if (show_version)
1898 num_bytes = sizeof(struct cyttsp_bootloader_data_t) - 3;
1899 else
1900 num_bytes = sizeof(struct cyttsp_bootloader_data_t) - 9;
1901
1902 if (show) {
1903 retval = i2c_smbus_read_i2c_block_data(ts->client,
1904 CY_REG_BASE, num_bytes, (u8 *)&g_bl_data);
1905 if (show_status) {
1906 cyttsp_debug("BL%d: f=%02X s=%02X err=%02X bl=%02X%02X bld=%02X%02X\n", \
1907 show, \
1908 g_bl_data.bl_file, \
1909 g_bl_data.bl_status, \
1910 g_bl_data.bl_error, \
1911 g_bl_data.blver_hi, g_bl_data.blver_lo, \
1912 g_bl_data.bld_blver_hi, g_bl_data.bld_blver_lo);
1913 }
1914 if (show_version) {
1915 cyttsp_debug("BL%d: ttspver=0x%02X%02X appid=0x%02X%02X appver=0x%02X%02X\n", \
1916 show, \
1917 g_bl_data.ttspver_hi, g_bl_data.ttspver_lo, \
1918 g_bl_data.appid_hi, g_bl_data.appid_lo, \
1919 g_bl_data.appver_hi, g_bl_data.appver_lo);
1920 }
1921 if (show_cid) {
1922 cyttsp_debug("BL%d: cid=0x%02X%02X%02X\n", \
1923 show, \
1924 g_bl_data.cid_0, \
1925 g_bl_data.cid_1, \
1926 g_bl_data.cid_2);
1927 }
1928 }
1929
1930 return retval;
1931}
1932
1933#ifdef CY_INCLUDE_LOAD_FILE
1934#define CY_MAX_I2C_LEN 256
1935#define CY_MAX_TRY 10
1936#define CY_BL_PAGE_SIZE 16
1937#define CY_BL_NUM_PAGES 5
1938static int cyttsp_i2c_wr_blk_chunks(struct cyttsp *ts, u8 command,
1939 u8 length, const u8 *values)
1940{
1941 int retval = CY_OK;
1942 int block = 1;
1943
1944 u8 dataray[CY_MAX_I2C_LEN];
1945
1946 /* first page already includes the bl page offset */
1947 retval = i2c_smbus_write_i2c_block_data(ts->client, CY_REG_BASE,
1948 CY_BL_PAGE_SIZE+1, values);
1949 values += CY_BL_PAGE_SIZE+1;
1950 length -= CY_BL_PAGE_SIZE+1;
1951
1952 /* rem blocks require bl page offset stuffing */
1953 while (length &&
1954 (block < CY_BL_NUM_PAGES) &&
1955 !(retval < CY_OK)) {
1956 udelay(43*2); /* TRM * 2 */
1957 dataray[0] = CY_BL_PAGE_SIZE*block;
1958 memcpy(&dataray[1], values,
1959 length >= CY_BL_PAGE_SIZE ?
1960 CY_BL_PAGE_SIZE : length);
1961 retval = i2c_smbus_write_i2c_block_data(ts->client,
1962 CY_REG_BASE,
1963 length >= CY_BL_PAGE_SIZE ?
1964 CY_BL_PAGE_SIZE + 1 : length+1, dataray);
1965 values += CY_BL_PAGE_SIZE;
1966 length = length >= CY_BL_PAGE_SIZE ?
1967 length - CY_BL_PAGE_SIZE : 0;
1968 block++;
1969 }
1970
1971 return retval;
1972}
1973
1974static int cyttsp_bootload_app(struct cyttsp *ts)
1975{
1976 int retval = CY_OK;
1977 int i, tries;
1978 u8 host_reg;
1979
1980 cyttsp_debug("load new firmware \n");
1981 /* reset TTSP Device back to bootloader mode */
1982 host_reg = CY_SOFT_RESET_MODE;
1983 retval = i2c_smbus_write_i2c_block_data(ts->client, CY_REG_BASE,
1984 sizeof(host_reg), &host_reg);
1985 /* wait for TTSP Device to complete reset back to bootloader */
1986 tries = 0;
1987 do {
1988 mdelay(1);
1989 cyttsp_putbl(ts, 3, false, false, false);
1990 } while (g_bl_data.bl_status != 0x10 &&
1991 g_bl_data.bl_status != 0x11 &&
1992 tries++ < 100);
1993 cyttsp_debug("load file - tver=0x%02X%02X a_id=0x%02X%02X aver=0x%02X%02X\n", \
1994 cyttsp_fw_tts_verh, cyttsp_fw_tts_verl, \
1995 cyttsp_fw_app_idh, cyttsp_fw_app_idl, \
1996 cyttsp_fw_app_verh, cyttsp_fw_app_verl);
1997
1998 /* download new TTSP Application to the Bootloader */
1999 if (!(retval < CY_OK)) {
2000 i = 0;
2001 /* send bootload initiation command */
2002 if (cyttsp_fw[i].Command == CY_BL_INIT_LOAD) {
2003 g_bl_data.bl_file = 0;
2004 g_bl_data.bl_status = 0;
2005 g_bl_data.bl_error = 0;
2006 retval = i2c_smbus_write_i2c_block_data(ts->client,
2007 CY_REG_BASE,
2008 cyttsp_fw[i].Length, cyttsp_fw[i].Block);
2009 /* delay to allow bl to get ready for block writes */
2010 i++;
2011 tries = 0;
2012 do {
2013 mdelay(100);
2014 cyttsp_putbl(ts, 4, false, false, false);
2015 } while (g_bl_data.bl_status != 0x10 &&
2016 g_bl_data.bl_status != 0x11 &&
2017 tries++ < 100);
2018 cyttsp_debug("wait init f=%02X, s=%02X, e=%02X t=%d\n", \
2019 g_bl_data.bl_file, g_bl_data.bl_status, \
2020 g_bl_data.bl_error, tries);
2021 /* send bootload firmware load blocks */
2022 if (!(retval < CY_OK)) {
2023 while (cyttsp_fw[i].Command == CY_BL_WRITE_BLK) {
2024 retval = cyttsp_i2c_wr_blk_chunks(ts,
2025 CY_REG_BASE,
2026 cyttsp_fw[i].Length,
2027 cyttsp_fw[i].Block);
2028 cyttsp_xdebug("BL DNLD Rec=% 3d Len=% 3d Addr=%04X\n", \
2029 cyttsp_fw[i].Record, \
2030 cyttsp_fw[i].Length, \
2031 cyttsp_fw[i].Address);
2032 i++;
2033 if (retval < CY_OK) {
2034 cyttsp_debug("BL fail Rec=%3d retval=%d\n", \
2035 cyttsp_fw[i-1].Record, \
2036 retval);
2037 break;
2038 } else {
2039 tries = 0;
2040 cyttsp_putbl(ts, 5, false, false, false);
2041 while (!((g_bl_data.bl_status == 0x10) &&
2042 (g_bl_data.bl_error == 0x20)) &&
2043 !((g_bl_data.bl_status == 0x11) &&
2044 (g_bl_data.bl_error == 0x20)) &&
2045 (tries++ < 100)) {
2046 mdelay(1);
2047 cyttsp_putbl(ts, 5, false, false, false);
2048 }
2049 }
2050 }
2051
2052 if (!(retval < CY_OK)) {
2053 while (i < cyttsp_fw_records) {
2054 retval = i2c_smbus_write_i2c_block_data(ts->client, CY_REG_BASE,
2055 cyttsp_fw[i].Length,
2056 cyttsp_fw[i].Block);
2057 i++;
2058 tries = 0;
2059 do {
2060 mdelay(100);
2061 cyttsp_putbl(ts, 6, true, false, false);
2062 } while (g_bl_data.bl_status != 0x10 &&
2063 g_bl_data.bl_status != 0x11 &&
2064 tries++ < 100);
2065 cyttsp_debug("wait term f=%02X, s=%02X, e=%02X t=%d\n", \
2066 g_bl_data.bl_file, \
2067 g_bl_data.bl_status, \
2068 g_bl_data.bl_error, \
2069 tries);
2070 if (retval < CY_OK)
2071 break;
2072 }
2073 }
2074 }
2075 }
2076 }
2077
2078 /* reset TTSP Device back to bootloader mode */
2079 host_reg = CY_SOFT_RESET_MODE;
2080 retval = i2c_smbus_write_i2c_block_data(ts->client, CY_REG_BASE,
2081 sizeof(host_reg), &host_reg);
2082 /* wait for TTSP Device to complete reset back to bootloader */
2083 tries = 0;
2084 do {
2085 mdelay(1);
2086 cyttsp_putbl(ts, 3, false, false, false);
2087 } while (g_bl_data.bl_status != 0x10 &&
2088 g_bl_data.bl_status != 0x11 &&
2089 tries++ < 100);
2090
2091 /* set arg2 to non-0 to activate */
2092 retval = cyttsp_putbl(ts, 8, true, true, true);
2093
2094 return retval;
2095}
2096#else
2097static int cyttsp_bootload_app(struct cyttsp *ts)
2098{
2099 cyttsp_debug("no-load new firmware \n");
2100 return CY_OK;
2101}
2102#endif /* CY_INCLUDE_LOAD_FILE */
2103
2104
2105static int cyttsp_power_on(struct cyttsp *ts)
2106{
2107 int retval = CY_OK;
2108 u8 host_reg;
2109 int tries;
2110
2111 cyttsp_debug("Power up \n");
2112
2113 /* check if the TTSP device has a bootloader installed */
2114 host_reg = CY_SOFT_RESET_MODE;
2115 retval = i2c_smbus_write_i2c_block_data(ts->client, CY_REG_BASE,
2116 sizeof(host_reg), &host_reg);
2117 tries = 0;
2118 do {
2119 mdelay(1);
2120
2121 /* set arg2 to non-0 to activate */
2122 retval = cyttsp_putbl(ts, 1, true, true, true);
2123 cyttsp_info("BL%d: f=%02X s=%02X err=%02X bl=%02X%02X bld=%02X%02X R=%d\n", \
2124 101, \
2125 g_bl_data.bl_file, g_bl_data.bl_status, \
2126 g_bl_data.bl_error, \
2127 g_bl_data.blver_hi, g_bl_data.blver_lo, \
2128 g_bl_data.bld_blver_hi, g_bl_data.bld_blver_lo,
2129 retval);
2130 cyttsp_info("BL%d: tver=%02X%02X a_id=%02X%02X aver=%02X%02X\n", \
2131 102, \
2132 g_bl_data.ttspver_hi, g_bl_data.ttspver_lo, \
2133 g_bl_data.appid_hi, g_bl_data.appid_lo, \
2134 g_bl_data.appver_hi, g_bl_data.appver_lo);
2135 cyttsp_info("BL%d: c_id=%02X%02X%02X\n", \
2136 103, \
2137 g_bl_data.cid_0, g_bl_data.cid_1, g_bl_data.cid_2);
2138 } while (!(retval < CY_OK) &&
2139 !GET_BOOTLOADERMODE(g_bl_data.bl_status) &&
2140 !(g_bl_data.bl_file == CY_OP_MODE + CY_LOW_PWR_MODE) &&
2141 tries++ < 100);
2142
2143 /* is bootloader missing? */
2144 if (!(retval < CY_OK)) {
2145 cyttsp_xdebug("Ret=%d Check if bootloader is missing...\n", \
2146 retval);
2147 if (!GET_BOOTLOADERMODE(g_bl_data.bl_status)) {
2148 /* skip all bl and sys info and go to op mode */
2149 if (!(retval < CY_OK)) {
2150 cyttsp_xdebug("Bl is missing (ret=%d)\n", \
2151 retval);
2152 host_reg = CY_OP_MODE/* + CY_LOW_PWR_MODE*/;
2153 retval = i2c_smbus_write_i2c_block_data(ts->client, CY_REG_BASE,
2154 sizeof(host_reg), &host_reg);
2155 /* wait for TTSP Device to complete switch to
2156 * Operational mode */
2157 mdelay(1000);
2158 goto bypass;
2159 }
2160 }
2161 }
2162
2163
2164 /* take TTSP out of bootloader mode; go to TrueTouch operational mode */
2165 if (!(retval < CY_OK)) {
2166 cyttsp_xdebug1("exit bootloader; go operational\n");
2167 retval = i2c_smbus_write_i2c_block_data(ts->client,
2168 CY_REG_BASE, sizeof(bl_cmd), bl_cmd);
2169 tries = 0;
2170 do {
2171 mdelay(100);
2172 cyttsp_putbl(ts, 4, true, false, false);
2173 cyttsp_info("BL%d: f=%02X s=%02X err=%02X bl=%02X%02X bld=%02X%02X\n", \
2174 104, \
2175 g_bl_data.bl_file, g_bl_data.bl_status, \
2176 g_bl_data.bl_error, \
2177 g_bl_data.blver_hi, g_bl_data.blver_lo, \
2178 g_bl_data.bld_blver_hi, g_bl_data.bld_blver_lo);
2179 } while (GET_BOOTLOADERMODE(g_bl_data.bl_status) &&
2180 tries++ < 100);
2181 }
2182
2183
2184
2185 if (!(retval < CY_OK) &&
2186 cyttsp_app_load()) {
2187 if (CY_DIFF(g_bl_data.ttspver_hi, cyttsp_tts_verh()) ||
2188 CY_DIFF(g_bl_data.ttspver_lo, cyttsp_tts_verl()) ||
2189 CY_DIFF(g_bl_data.appid_hi, cyttsp_app_idh()) ||
2190 CY_DIFF(g_bl_data.appid_lo, cyttsp_app_idl()) ||
2191 CY_DIFF(g_bl_data.appver_hi, cyttsp_app_verh()) ||
2192 CY_DIFF(g_bl_data.appver_lo, cyttsp_app_verl()) ||
2193 CY_DIFF(g_bl_data.cid_0, cyttsp_cid_0()) ||
2194 CY_DIFF(g_bl_data.cid_1, cyttsp_cid_1()) ||
2195 CY_DIFF(g_bl_data.cid_2, cyttsp_cid_2()) ||
2196 cyttsp_force_fw_load()) {
2197 cyttsp_debug("blttsp=0x%02X%02X flttsp=0x%02X%02X force=%d\n", \
2198 g_bl_data.ttspver_hi, g_bl_data.ttspver_lo, \
2199 cyttsp_tts_verh(), cyttsp_tts_verl(), \
2200 cyttsp_force_fw_load());
2201 cyttsp_debug("blappid=0x%02X%02X flappid=0x%02X%02X\n", \
2202 g_bl_data.appid_hi, g_bl_data.appid_lo, \
2203 cyttsp_app_idh(), cyttsp_app_idl());
2204 cyttsp_debug("blappver=0x%02X%02X flappver=0x%02X%02X\n", \
2205 g_bl_data.appver_hi, g_bl_data.appver_lo, \
2206 cyttsp_app_verh(), cyttsp_app_verl());
2207 cyttsp_debug("blcid=0x%02X%02X%02X flcid=0x%02X%02X%02X\n", \
2208 g_bl_data.cid_0, \
2209 g_bl_data.cid_1, \
2210 g_bl_data.cid_2, \
2211 cyttsp_cid_0(), \
2212 cyttsp_cid_1(), \
2213 cyttsp_cid_2());
2214 /* enter bootloader to load new app into TTSP Device */
2215 retval = cyttsp_bootload_app(ts);
2216 /* take TTSP device out of bootloader mode;
2217 * switch back to TrueTouch operational mode */
2218 if (!(retval < CY_OK)) {
2219 retval = i2c_smbus_write_i2c_block_data(ts->client,
2220 CY_REG_BASE,
2221 sizeof(bl_cmd), bl_cmd);
2222 /* wait for TTSP Device to complete
2223 * switch to Operational mode */
2224 tries = 0;
2225 do {
2226 mdelay(100);
2227 cyttsp_putbl(ts, 9, false, false, false);
2228 } while (GET_BOOTLOADERMODE(g_bl_data.bl_status) &&
2229 tries++ < 100);
2230 cyttsp_putbl(ts, 9, true, false, false);
2231 }
2232 }
2233 }
2234
2235bypass:
2236 /* switch to System Information mode to read versions
2237 * and set interval registers */
2238 if (!(retval < CY_OK)) {
2239 cyttsp_debug("switch to sysinfo mode \n");
2240 host_reg = CY_SYSINFO_MODE;
2241 retval = i2c_smbus_write_i2c_block_data(ts->client,
2242 CY_REG_BASE, sizeof(host_reg), &host_reg);
2243 /* wait for TTSP Device to complete switch to SysInfo mode */
2244 mdelay(100);
2245 if (!(retval < CY_OK)) {
2246 retval = i2c_smbus_read_i2c_block_data(ts->client,
2247 CY_REG_BASE,
2248 sizeof(struct cyttsp_sysinfo_data_t),
2249 (u8 *)&g_sysinfo_data);
2250 cyttsp_debug("SI2: hst_mode=0x%02X mfg_cmd=0x%02X mfg_stat=0x%02X\n", \
2251 g_sysinfo_data.hst_mode, \
2252 g_sysinfo_data.mfg_cmd, \
2253 g_sysinfo_data.mfg_stat);
2254 cyttsp_debug("SI2: bl_ver=0x%02X%02X\n", \
2255 g_sysinfo_data.bl_verh, \
2256 g_sysinfo_data.bl_verl);
2257 cyttsp_debug("SI2: sysinfo act_int=0x%02X tch_tmout=0x%02X lp_int=0x%02X\n", \
2258 g_sysinfo_data.act_intrvl, \
2259 g_sysinfo_data.tch_tmout, \
2260 g_sysinfo_data.lp_intrvl);
2261 cyttsp_info("SI%d: tver=%02X%02X a_id=%02X%02X aver=%02X%02X\n", \
2262 102, \
2263 g_sysinfo_data.tts_verh, \
2264 g_sysinfo_data.tts_verl, \
2265 g_sysinfo_data.app_idh, \
2266 g_sysinfo_data.app_idl, \
2267 g_sysinfo_data.app_verh, \
2268 g_sysinfo_data.app_verl);
2269 cyttsp_info("SI%d: c_id=%02X%02X%02X\n", \
2270 103, \
2271 g_sysinfo_data.cid[0], \
2272 g_sysinfo_data.cid[1], \
2273 g_sysinfo_data.cid[2]);
2274 if (!(retval < CY_OK) &&
2275 (CY_DIFF(ts->platform_data->act_intrvl,
2276 CY_ACT_INTRVL_DFLT) ||
2277 CY_DIFF(ts->platform_data->tch_tmout,
2278 CY_TCH_TMOUT_DFLT) ||
2279 CY_DIFF(ts->platform_data->lp_intrvl,
2280 CY_LP_INTRVL_DFLT))) {
2281 if (!(retval < CY_OK)) {
2282 u8 intrvl_ray[sizeof(ts->platform_data->act_intrvl) +
2283 sizeof(ts->platform_data->tch_tmout) +
2284 sizeof(ts->platform_data->lp_intrvl)];
2285 u8 i = 0;
2286
2287 intrvl_ray[i++] =
2288 ts->platform_data->act_intrvl;
2289 intrvl_ray[i++] =
2290 ts->platform_data->tch_tmout;
2291 intrvl_ray[i++] =
2292 ts->platform_data->lp_intrvl;
2293
2294 cyttsp_debug("SI2: platinfo act_intrvl=0x%02X tch_tmout=0x%02X lp_intrvl=0x%02X\n", \
2295 ts->platform_data->act_intrvl, \
2296 ts->platform_data->tch_tmout, \
2297 ts->platform_data->lp_intrvl);
2298 /* set intrvl registers */
2299 retval = i2c_smbus_write_i2c_block_data(
2300 ts->client,
2301 CY_REG_ACT_INTRVL,
2302 sizeof(intrvl_ray), intrvl_ray);
2303 mdelay(CY_DLY_SYSINFO);
2304 }
2305 }
2306 }
2307 /* switch back to Operational mode */
2308 cyttsp_debug("switch back to operational mode \n");
2309 if (!(retval < CY_OK)) {
2310 host_reg = CY_OP_MODE/* + CY_LOW_PWR_MODE*/;
2311 retval = i2c_smbus_write_i2c_block_data(ts->client,
2312 CY_REG_BASE,
2313 sizeof(host_reg), &host_reg);
2314 /* wait for TTSP Device to complete
2315 * switch to Operational mode */
2316 mdelay(100);
2317 }
2318 }
2319 /* init gesture setup;
2320 * this is required even if not using gestures
2321 * in order to set the active distance */
2322 if (!(retval < CY_OK)) {
2323 u8 gesture_setup;
2324 cyttsp_debug("init gesture setup \n");
2325 gesture_setup = ts->platform_data->gest_set;
2326 retval = i2c_smbus_write_i2c_block_data(ts->client,
2327 CY_REG_GEST_SET,
2328 sizeof(gesture_setup), &gesture_setup);
2329 mdelay(CY_DLY_DFLT);
2330 }
2331
2332 if (!(retval < CY_OK))
2333 ts->platform_data->power_state = CY_ACTIVE_STATE;
2334 else
2335 ts->platform_data->power_state = CY_IDLE_STATE;
2336
2337 cyttsp_debug("Retval=%d Power state is %s\n", \
2338 retval, \
2339 ts->platform_data->power_state == CY_ACTIVE_STATE ? \
2340 "ACTIVE" : "IDLE");
2341
2342 return retval;
2343}
2344
2345static int cyttsp_power_device(struct cyttsp *ts, bool on)
2346{
2347 int rc = 0, i;
2348 const struct cyttsp_regulator *reg_info =
2349 ts->platform_data->regulator_info;
2350 u8 num_reg = ts->platform_data->num_regulators;
2351
2352 if (!reg_info) {
2353 pr_err("regulator pdata not specified\n");
2354 return -EINVAL;
2355 }
2356
2357 if (on == false) /* Turn off the regulators */
2358 goto ts_reg_disable;
2359
2360 ts->vdd = kzalloc(num_reg * sizeof(struct regulator *), GFP_KERNEL);
2361 if (!ts->vdd) {
2362 pr_err("unable to allocate memory\n");
2363 return -ENOMEM;
2364 }
2365
2366 for (i = 0; i < num_reg; i++) {
2367 ts->vdd[i] = regulator_get(&ts->client->dev, reg_info[i].name);
2368 if (IS_ERR(ts->vdd[i])) {
2369 rc = PTR_ERR(ts->vdd[i]);
2370 pr_err("%s:regulator get failed rc=%d\n",
2371 __func__, rc);
2372 goto error_vdd;
2373 }
2374
2375 if (regulator_count_voltages(ts->vdd[i]) > 0) {
2376 rc = regulator_set_voltage(ts->vdd[i],
2377 reg_info[i].min_uV, reg_info[i].max_uV);
2378 if (rc) {
2379 pr_err("%s: regulator_set_voltage"
2380 "failed rc =%d\n", __func__, rc);
2381 regulator_put(ts->vdd[i]);
2382 goto error_vdd;
2383 }
2384 }
2385
2386 rc = regulator_set_optimum_mode(ts->vdd[i],
2387 reg_info[i].load_uA);
2388 if (rc < 0) {
2389 pr_err("%s: regulator_set_optimum_mode failed rc=%d\n",
2390 __func__, rc);
2391
2392 regulator_set_voltage(ts->vdd[i], 0,
2393 reg_info[i].max_uV);
2394 regulator_put(ts->vdd[i]);
2395 goto error_vdd;
2396 }
2397
2398 rc = regulator_enable(ts->vdd[i]);
2399 if (rc) {
2400 pr_err("%s: regulator_enable failed rc =%d\n",
2401 __func__, rc);
2402 regulator_set_optimum_mode(ts->vdd[i], 0);
2403 regulator_set_voltage(ts->vdd[i], 0,
2404 reg_info[i].max_uV);
2405 regulator_put(ts->vdd[i]);
2406 goto error_vdd;
2407 }
2408 }
2409
2410 return rc;
2411
2412ts_reg_disable:
2413 i = ts->platform_data->num_regulators;
2414error_vdd:
2415 while (--i >= 0) {
2416 if (regulator_count_voltages(ts->vdd[i]) > 0)
2417 regulator_set_voltage(ts->vdd[i], 0,
2418 reg_info[i].max_uV);
2419 regulator_set_optimum_mode(ts->vdd[i], 0);
2420 regulator_disable(ts->vdd[i]);
2421 regulator_put(ts->vdd[i]);
2422 }
2423 kfree(ts->vdd);
2424 return rc;
2425}
2426
2427/* cyttsp_initialize: Driver Initialization. This function takes
2428 * care of the following tasks:
2429 * 1. Create and register an input device with input layer
2430 * 2. Take CYTTSP device out of bootloader mode; go operational
2431 * 3. Start any timers/Work queues. */
2432static int cyttsp_initialize(struct i2c_client *client, struct cyttsp *ts)
2433{
2434 struct input_dev *input_device;
2435 int error = 0;
2436 int retval = CY_OK;
2437 u8 id;
2438
2439 /* Create the input device and register it. */
2440 input_device = input_allocate_device();
2441 if (!input_device) {
2442 error = -ENOMEM;
2443 cyttsp_xdebug1("err input allocate device\n");
2444 goto error_free_device;
2445 }
2446
2447 if (!client) {
2448 error = ~ENODEV;
2449 cyttsp_xdebug1("err client is Null\n");
2450 goto error_free_device;
2451 }
2452
2453 if (!ts) {
2454 error = ~ENODEV;
2455 cyttsp_xdebug1("err context is Null\n");
2456 goto error_free_device;
2457 }
2458
2459 ts->input = input_device;
2460 input_device->name = CY_I2C_NAME;
2461 input_device->phys = ts->phys;
2462 input_device->dev.parent = &client->dev;
2463
2464 /* init the touch structures */
2465 ts->num_prv_st_tch = CY_NTCH;
2466 for (id = 0; id < CY_NUM_TRK_ID; id++) {
2467 ts->act_trk[id] = CY_NTCH;
2468 ts->prv_mt_pos[id][CY_XPOS] = 0;
2469 ts->prv_mt_pos[id][CY_YPOS] = 0;
2470 }
2471
2472 for (id = 0; id < CY_NUM_MT_TCH_ID; id++)
2473 ts->prv_mt_tch[id] = CY_IGNR_TCH;
2474
2475 for (id = 0; id < CY_NUM_ST_TCH_ID; id++)
2476 ts->prv_st_tch[id] = CY_IGNR_TCH;
2477
2478 set_bit(EV_SYN, input_device->evbit);
2479 set_bit(EV_KEY, input_device->evbit);
2480 set_bit(EV_ABS, input_device->evbit);
2481 set_bit(BTN_TOUCH, input_device->keybit);
2482 set_bit(BTN_2, input_device->keybit);
2483 if (ts->platform_data->use_gestures)
2484 set_bit(BTN_3, input_device->keybit);
2485
2486 input_set_abs_params(input_device, ABS_X, ts->platform_data->disp_minx,
2487 ts->platform_data->disp_maxx, 0, 0);
2488 input_set_abs_params(input_device, ABS_Y, ts->platform_data->disp_miny,
2489 ts->platform_data->disp_maxy, 0, 0);
2490 input_set_abs_params(input_device,
2491 ABS_TOOL_WIDTH, 0, CY_LARGE_TOOL_WIDTH, 0 , 0);
2492 input_set_abs_params(input_device,
2493 ABS_PRESSURE, 0, CY_MAXZ, 0, 0);
2494 input_set_abs_params(input_device,
2495 ABS_HAT0X, 0, ts->platform_data->panel_maxx, 0, 0);
2496 input_set_abs_params(input_device,
2497 ABS_HAT0Y, 0, ts->platform_data->panel_maxy, 0, 0);
2498 if (ts->platform_data->use_gestures) {
2499 input_set_abs_params(input_device,
2500 ABS_HAT1X, 0, CY_MAXZ, 0, 0);
2501 input_set_abs_params(input_device,
2502 ABS_HAT1Y, 0, CY_MAXZ, 0, 0);
2503 }
2504 if (ts->platform_data->use_mt) {
2505 input_set_abs_params(input_device, ABS_MT_POSITION_X,
2506 ts->platform_data->disp_minx,
2507 ts->platform_data->disp_maxx, 0, 0);
2508 input_set_abs_params(input_device, ABS_MT_POSITION_Y,
2509 ts->platform_data->disp_miny,
2510 ts->platform_data->disp_maxy, 0, 0);
2511 input_set_abs_params(input_device,
2512 ABS_MT_TOUCH_MAJOR, 0, CY_MAXZ, 0, 0);
2513 input_set_abs_params(input_device,
2514 ABS_MT_WIDTH_MAJOR, 0, CY_LARGE_TOOL_WIDTH, 0, 0);
2515 if (ts->platform_data->use_trk_id) {
2516 input_set_abs_params(input_device,
2517 ABS_MT_TRACKING_ID, 0, CY_NUM_TRK_ID, 0, 0);
2518 }
2519 }
2520
2521 /* set dummy key to make driver work with virtual keys */
2522 input_set_capability(input_device, EV_KEY, KEY_PROG1);
2523
2524 cyttsp_info("%s: Register input device\n", CY_I2C_NAME);
2525 error = input_register_device(input_device);
2526 if (error) {
2527 cyttsp_alert("%s: Failed to register input device\n", \
2528 CY_I2C_NAME);
2529 retval = error;
2530 goto error_free_device;
2531 }
2532
2533 /* Prepare our worker structure prior to setting up the timer/ISR */
2534 INIT_WORK(&ts->work, cyttsp_xy_worker);
2535
2536 if (gpio_is_valid(ts->platform_data->resout_gpio)) {
2537 /* configure touchscreen reset out gpio */
2538 retval = gpio_request(ts->platform_data->resout_gpio,
2539 "cyttsp_resout_gpio");
2540 if (retval) {
2541 pr_err("%s: unable to request reset gpio %d\n",
2542 __func__, ts->platform_data->resout_gpio);
2543 goto error_free_device;
2544 }
2545
2546 retval = gpio_direction_output(
2547 ts->platform_data->resout_gpio, 1);
2548 if (retval) {
2549 pr_err("%s: unable to set direction for gpio %d\n",
2550 __func__, ts->platform_data->resout_gpio);
2551 goto error_resout_gpio_dir;
2552 }
2553 }
2554
2555 if (gpio_is_valid(ts->platform_data->sleep_gpio)) {
2556 /* configure touchscreen reset out gpio */
2557 retval = gpio_request(ts->platform_data->sleep_gpio,
2558 "cy8c_sleep_gpio");
2559 if (retval) {
2560 pr_err("%s: unable to request sleep gpio %d\n",
2561 __func__, ts->platform_data->sleep_gpio);
2562 goto error_sleep_gpio_req;
2563 }
2564
2565 retval = gpio_direction_output(
2566 ts->platform_data->sleep_gpio, 0);
2567 if (retval) {
2568 pr_err("%s: unable to set direction for gpio %d\n",
2569 __func__, ts->platform_data->resout_gpio);
2570 goto error_sleep_gpio_dir;
2571 }
2572 }
2573
2574 if (gpio_is_valid(ts->platform_data->irq_gpio)) {
2575 /* configure touchscreen irq gpio */
2576 retval = gpio_request(ts->platform_data->irq_gpio,
2577 "ts_irq_gpio");
2578 if (retval) {
2579 pr_err("%s: unable to request gpio [%d]\n", __func__,
2580 ts->platform_data->irq_gpio);
2581 goto error_irq_gpio_req;
2582 }
2583 retval = gpio_direction_input(ts->platform_data->irq_gpio);
2584 if (retval) {
2585 pr_err("%s: unable to set_direction for gpio [%d]\n",
2586 __func__, ts->platform_data->irq_gpio);
2587 goto error_irq_gpio_dir;
2588 }
2589 }
2590
2591 if (ts->platform_data->regulator_info) {
2592 retval = cyttsp_power_device(ts, true);
2593 if (retval) {
2594 pr_err("%s: Unable to power device %d\n",
2595 __func__, retval);
2596 goto error_irq_gpio_dir;
2597 }
2598 }
2599
2600 /* Power on the chip and make sure that I/Os are set as specified
2601 * in the platform */
2602 if (ts->platform_data->init) {
2603 retval = ts->platform_data->init(client);
2604 if (retval) {
2605 pr_err("%s: ts init failed\n", __func__);
2606 goto error_power_device;
2607 }
2608 }
2609
2610 msleep(100);
2611
2612 /* check this device active by reading first byte/register */
2613 retval = i2c_smbus_read_byte_data(ts->client, 0x01);
2614 if (retval < 0) {
2615 pr_err("%s: i2c sanity check failed\n", __func__);
2616 goto error_power_device;
2617 }
2618
2619 retval = cyttsp_power_on(ts);
2620 if (retval < 0) {
2621 pr_err("%s: cyttsp_power_on failed\n", __func__);
2622 goto error_power_device;
2623 }
2624
2625 /* Timer or Interrupt setup */
2626 if (ts->client->irq == 0) {
2627 cyttsp_info("Setting up timer\n");
2628 setup_timer(&ts->timer, cyttsp_timer, (unsigned long) ts);
2629 mod_timer(&ts->timer, jiffies + TOUCHSCREEN_TIMEOUT);
2630 } else {
2631 cyttsp_info("Setting up interrupt\n");
2632 /* request_irq() will also call enable_irq() */
2633 error = request_irq(client->irq, cyttsp_irq,
2634 IRQF_TRIGGER_FALLING,
2635 client->dev.driver->name, ts);
2636 if (error) {
2637 cyttsp_alert("error: could not request irq\n");
2638 retval = error;
2639 goto error_power_device;
2640 }
2641 }
2642
2643 irq_cnt = 0;
2644 irq_cnt_total = 0;
2645 irq_err_cnt = 0;
2646
2647 atomic_set(&ts->irq_enabled, 1);
2648 retval = device_create_file(&ts->client->dev, &dev_attr_irq_enable);
2649 if (retval < CY_OK) {
2650 cyttsp_alert("File device creation failed: %d\n", retval);
2651 retval = -ENODEV;
2652 goto error_free_irq;
2653 }
2654
2655 retval = device_create_file(&client->dev, &dev_attr_cyttsp_fw_ver);
2656 if (retval) {
2657 cyttsp_alert("sysfs entry for firmware version failed\n");
2658 goto error_rm_dev_file_irq_en;
2659 }
2660
2661 ts->cyttsp_fwloader_mode = 0;
2662 retval = device_create_file(&client->dev, &dev_attr_cyttsp_update_fw);
2663 if (retval) {
2664 cyttsp_alert("sysfs entry for firmware update failed\n");
2665 goto error_rm_dev_file_fw_ver;
2666 }
2667
2668 retval = device_create_file(&client->dev,
2669 &dev_attr_cyttsp_force_update_fw);
2670 if (retval) {
2671 cyttsp_alert("sysfs entry for force firmware update failed\n");
2672 goto error_rm_dev_file_update_fw;
2673 }
2674 if (ts->platform_data->correct_fw_ver) {
2675 if (g_bl_data.appid_lo != ts->platform_data->correct_fw_ver)
2676 printk(KERN_INFO "Please update touchscreen firmware\n");
2677 }
2678
2679 retval = device_create_file(&client->dev,
2680 &dev_attr_cyttsp_fw_name);
2681 if (retval) {
2682 cyttsp_alert("sysfs entry for file name selection failed\n");
2683 goto error_rm_dev_file_fupdate_fw;
2684 }
2685
2686 cyttsp_info("%s: Successful registration\n", CY_I2C_NAME);
2687
2688 goto success;
2689
2690error_rm_dev_file_fupdate_fw:
2691 device_remove_file(&client->dev, &dev_attr_cyttsp_force_update_fw);
2692error_rm_dev_file_update_fw:
2693 device_remove_file(&client->dev, &dev_attr_cyttsp_update_fw);
2694error_rm_dev_file_fw_ver:
2695 device_remove_file(&client->dev, &dev_attr_cyttsp_fw_ver);
2696error_rm_dev_file_irq_en:
2697 device_remove_file(&client->dev, &dev_attr_irq_enable);
2698error_free_irq:
2699 if (ts->client->irq)
2700 free_irq(client->irq, ts);
2701error_power_device:
2702 if (ts->platform_data->regulator_info)
2703 cyttsp_power_device(ts, false);
2704error_irq_gpio_dir:
2705 if (gpio_is_valid(ts->platform_data->irq_gpio))
2706 gpio_free(ts->platform_data->irq_gpio);
2707error_irq_gpio_req:
2708 if (gpio_is_valid(ts->platform_data->sleep_gpio))
2709 gpio_direction_output(ts->platform_data->sleep_gpio, 1);
2710error_sleep_gpio_dir:
2711 if (gpio_is_valid(ts->platform_data->sleep_gpio))
2712 gpio_free(ts->platform_data->sleep_gpio);
2713error_sleep_gpio_req:
2714 if (gpio_is_valid(ts->platform_data->resout_gpio))
2715 gpio_direction_output(ts->platform_data->resout_gpio, 0);
2716error_resout_gpio_dir:
2717 if (gpio_is_valid(ts->platform_data->resout_gpio))
2718 gpio_free(ts->platform_data->resout_gpio);
2719error_free_device:
2720 if (input_device)
2721 input_free_device(input_device);
2722
2723success:
2724 return retval;
2725}
2726
2727/* I2C driver probe function */
2728static int __devinit cyttsp_probe(struct i2c_client *client,
2729 const struct i2c_device_id *id)
2730{
2731 struct cyttsp *ts;
2732 int error;
2733 int retval = CY_OK;
2734
2735 cyttsp_info("Start Probe 1.2\n");
2736
2737 /* allocate and clear memory */
2738 ts = kzalloc(sizeof(struct cyttsp), GFP_KERNEL);
2739 if (ts == NULL) {
2740 cyttsp_xdebug1("err kzalloc for cyttsp\n");
2741 retval = -ENOMEM;
2742 }
2743
2744 /* Enable runtime PM ops, start in ACTIVE mode */
2745 error = pm_runtime_set_active(&client->dev);
2746 if (error < 0)
2747 dev_dbg(&client->dev, "unable to set runtime pm state\n");
2748 pm_runtime_enable(&client->dev);
2749
2750 if (!(retval < CY_OK)) {
2751 /* register driver_data */
2752 ts->client = client;
2753 ts->platform_data = client->dev.platform_data;
2754
2755 if (ts->platform_data->fw_fname)
2756 strncpy(ts->fw_fname, ts->platform_data->fw_fname,
2757 FW_FNAME_LEN - 1);
2758 else
2759 strncpy(ts->fw_fname, "cyttsp.hex", FW_FNAME_LEN - 1);
2760
2761 i2c_set_clientdata(client, ts);
2762
2763 error = cyttsp_initialize(client, ts);
2764 if (error) {
2765 cyttsp_xdebug1("err cyttsp_initialize\n");
2766 if (ts != NULL) {
2767 /* deallocate memory */
2768 kfree(ts);
2769 }
2770/*
2771 i2c_del_driver(&cyttsp_driver);
2772*/
2773 retval = -ENODEV;
2774 } else
2775 cyttsp_openlog();
2776 }
2777
2778#ifdef CONFIG_HAS_EARLYSUSPEND
2779 if (!(retval < CY_OK)) {
2780 ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
2781 ts->early_suspend.suspend = cyttsp_early_suspend;
2782 ts->early_suspend.resume = cyttsp_late_resume;
2783 register_early_suspend(&ts->early_suspend);
2784 }
2785#endif /* CONFIG_HAS_EARLYSUSPEND */
2786 device_init_wakeup(&client->dev, ts->platform_data->wakeup);
2787 mutex_init(&ts->mutex);
2788
2789 cyttsp_info("Start Probe %s\n", \
2790 (retval < CY_OK) ? "FAIL" : "PASS");
2791
2792 return retval;
2793}
2794
2795/* Function to manage power-on resume */
2796static int cyttsp_resume(struct device *dev)
2797{
2798 struct cyttsp *ts = dev_get_drvdata(dev);
2799 int retval = CY_OK;
2800
2801 cyttsp_debug("Wake Up\n");
2802
2803 if (ts->is_suspended == false) {
2804 pr_err("%s: in wakeup state\n", __func__);
2805 return 0;
2806 }
2807
2808 if (device_may_wakeup(dev)) {
2809 if (ts->client->irq)
2810 disable_irq_wake(ts->client->irq);
2811 return 0;
2812 }
2813
2814 /* re-enable the interrupt prior to wake device */
2815 if (ts->client->irq)
2816 enable_irq(ts->client->irq);
2817
2818 if (ts->platform_data->use_sleep &&
2819 (ts->platform_data->power_state != CY_ACTIVE_STATE)) {
2820 if (ts->platform_data->resume)
2821 retval = ts->platform_data->resume(ts->client);
2822 if (!(retval < CY_OK)) {
2823 /* take TTSP device out of bootloader mode;
2824 * switch back to TrueTouch operational mode */
2825 if (!(retval < CY_OK)) {
2826 int tries;
2827 retval = i2c_smbus_write_i2c_block_data(ts->client,
2828 CY_REG_BASE,
2829 sizeof(bl_cmd), bl_cmd);
2830 /* wait for TTSP Device to complete
2831 * switch to Operational mode */
2832 tries = 0;
2833 do {
2834 mdelay(100);
2835 cyttsp_putbl(ts, 16, false, false, false);
2836 } while (GET_BOOTLOADERMODE(g_bl_data.bl_status) &&
2837 tries++ < 100);
2838 cyttsp_putbl(ts, 16, true, false, false);
2839 }
2840 }
2841 }
2842
2843 if (!(retval < CY_OK) &&
2844 (GET_HSTMODE(g_bl_data.bl_file) == CY_OK)) {
2845 ts->platform_data->power_state = CY_ACTIVE_STATE;
2846
2847 /* re-enable the timer after resuming */
2848 if (ts->client->irq == 0)
2849 mod_timer(&ts->timer, jiffies + TOUCHSCREEN_TIMEOUT);
2850 } else
2851 retval = -ENODEV;
2852
2853 ts->is_suspended = false;
2854 cyttsp_debug("Wake Up %s\n", \
2855 (retval < CY_OK) ? "FAIL" : "PASS");
2856
2857 return retval;
2858}
2859
2860
2861/* Function to manage low power suspend */
2862static int cyttsp_suspend(struct device *dev)
2863{
2864 struct cyttsp *ts = dev_get_drvdata(dev);
2865 u8 sleep_mode = CY_OK;
2866 int retval = CY_OK;
2867
2868 cyttsp_debug("Enter Sleep\n");
2869
2870 if (ts->is_suspended == true) {
2871 pr_err("%s: in sleep state\n", __func__);
2872 return 0;
2873 }
2874
2875 mutex_lock(&ts->mutex);
2876 if (ts->cyttsp_fwloader_mode) {
2877 pr_err("%s:firmware upgrade mode:"
2878 "suspend not allowed\n", __func__);
2879 mutex_unlock(&ts->mutex);
2880 return -EBUSY;
2881 }
2882 mutex_unlock(&ts->mutex);
2883
2884 if (device_may_wakeup(dev)) {
2885 if (ts->client->irq)
2886 enable_irq_wake(ts->client->irq);
2887 return 0;
2888 }
2889
2890 /* disable worker */
2891 if (ts->client->irq == 0)
2892 del_timer(&ts->timer);
2893 else
2894 disable_irq_nosync(ts->client->irq);
2895 retval = cancel_work_sync(&ts->work);
2896
2897 if (retval)
2898 enable_irq(ts->client->irq);
2899
2900 if (!(retval < CY_OK)) {
2901 if (ts->platform_data->use_sleep &&
2902 (ts->platform_data->power_state == CY_ACTIVE_STATE)) {
2903 if (ts->platform_data->use_sleep & CY_USE_DEEP_SLEEP_SEL)
2904 sleep_mode = CY_DEEP_SLEEP_MODE;
2905 else
2906 sleep_mode = CY_LOW_PWR_MODE;
2907
2908 retval = i2c_smbus_write_i2c_block_data(ts->client,
2909 CY_REG_BASE,
2910 sizeof(sleep_mode), &sleep_mode);
2911 }
2912 }
2913
2914 if (!(retval < CY_OK)) {
2915 if (sleep_mode == CY_DEEP_SLEEP_MODE)
2916 ts->platform_data->power_state = CY_SLEEP_STATE;
2917 else if (sleep_mode == CY_LOW_PWR_MODE)
2918 ts->platform_data->power_state = CY_LOW_PWR_STATE;
2919 }
2920
2921 ts->is_suspended = true;
2922 cyttsp_debug("Sleep Power state is %s\n", \
2923 (ts->platform_data->power_state == CY_ACTIVE_STATE) ? \
2924 "ACTIVE" : \
2925 ((ts->platform_data->power_state == CY_SLEEP_STATE) ? \
2926 "SLEEP" : "LOW POWER"));
2927
2928 return retval;
2929}
2930
2931/* registered in driver struct */
2932static int __devexit cyttsp_remove(struct i2c_client *client)
2933{
2934 /* clientdata registered on probe */
2935 struct cyttsp *ts = i2c_get_clientdata(client);
2936 int err;
2937
2938 cyttsp_alert("Unregister\n");
2939
2940 pm_runtime_set_suspended(&client->dev);
2941 pm_runtime_disable(&client->dev);
2942
2943 device_init_wakeup(&client->dev, 0);
2944 device_remove_file(&ts->client->dev, &dev_attr_irq_enable);
2945 device_remove_file(&client->dev, &dev_attr_cyttsp_fw_ver);
2946 device_remove_file(&client->dev, &dev_attr_cyttsp_update_fw);
2947 device_remove_file(&client->dev, &dev_attr_cyttsp_force_update_fw);
2948 device_remove_file(&client->dev, &dev_attr_cyttsp_fw_name);
2949
2950 /* Start cleaning up by removing any delayed work and the timer */
2951 if (cancel_delayed_work((struct delayed_work *)&ts->work) < CY_OK)
2952 cyttsp_alert("error: could not remove work from workqueue\n");
2953
2954 /* free up timer or irq */
2955 if (ts->client->irq == 0) {
2956 err = del_timer(&ts->timer);
2957 if (err < CY_OK)
2958 cyttsp_alert("error: failed to delete timer\n");
2959 } else
2960 free_irq(client->irq, ts);
2961
2962 if (ts->platform_data->regulator_info)
2963 cyttsp_power_device(ts, false);
2964
2965#ifdef CONFIG_HAS_EARLYSUSPEND
2966 unregister_early_suspend(&ts->early_suspend);
2967#endif /* CONFIG_HAS_EARLYSUSPEND */
2968
2969 mutex_destroy(&ts->mutex);
2970
2971 if (gpio_is_valid(ts->platform_data->sleep_gpio)) {
2972 gpio_direction_output(ts->platform_data->sleep_gpio, 1);
2973 gpio_free(ts->platform_data->sleep_gpio);
2974 }
2975
2976 if (gpio_is_valid(ts->platform_data->resout_gpio)) {
2977 gpio_direction_output(ts->platform_data->resout_gpio, 0);
2978 gpio_free(ts->platform_data->resout_gpio);
2979 }
2980
2981 if (gpio_is_valid(ts->platform_data->irq_gpio))
2982 gpio_free(ts->platform_data->irq_gpio);
2983
2984 /* housekeeping */
2985 if (ts != NULL)
2986 kfree(ts);
2987
2988 cyttsp_alert("Leaving\n");
2989
2990 return 0;
2991}
2992
2993#ifdef CONFIG_HAS_EARLYSUSPEND
2994static void cyttsp_early_suspend(struct early_suspend *handler)
2995{
2996 struct cyttsp *ts;
2997
2998 ts = container_of(handler, struct cyttsp, early_suspend);
2999 cyttsp_suspend(&ts->client->dev);
3000}
3001
3002static void cyttsp_late_resume(struct early_suspend *handler)
3003{
3004 struct cyttsp *ts;
3005
3006 ts = container_of(handler, struct cyttsp, early_suspend);
3007 cyttsp_resume(&ts->client->dev);
3008}
3009#endif /* CONFIG_HAS_EARLYSUSPEND */
3010
3011static int cyttsp_init(void)
3012{
3013 int ret;
3014
3015 cyttsp_info("Cypress TrueTouch(R) Standard Product\n");
3016 cyttsp_info("I2C Touchscreen Driver (Built %s @ %s)\n", \
3017 __DATE__, __TIME__);
3018
3019 cyttsp_ts_wq = create_singlethread_workqueue("cyttsp_ts_wq");
3020 if (cyttsp_ts_wq == NULL) {
3021 cyttsp_debug("No memory for cyttsp_ts_wq\n");
3022 return -ENOMEM;
3023 }
3024
3025 ret = i2c_add_driver(&cyttsp_driver);
3026
3027 return ret;
3028}
3029
3030static void cyttsp_exit(void)
3031{
3032 if (cyttsp_ts_wq)
3033 destroy_workqueue(cyttsp_ts_wq);
3034 return i2c_del_driver(&cyttsp_driver);
3035}
3036
3037module_init(cyttsp_init);
3038module_exit(cyttsp_exit);
3039MODULE_FIRMWARE("cyttsp.fw");
3040