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