blob: 1deb2a3c065cdeb7c1aaee8fd2c8133e3b81db0d [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
Praveena Pachipulusu8b621e42011-08-10 18:17:07 +0530199static DEVICE_ATTR(irq_enable, 0664, cyttsp_irq_status, cyttsp_irq_enable);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700200
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
Praveena Pachipulusu8b621e42011-08-10 18:17:07 +0530208static DEVICE_ATTR(cyttsp_fw_ver, 0664, cyttsp_fw_show, NULL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700209
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
Praveena Pachipulusu8b621e42011-08-10 18:17:07 +0530851static DEVICE_ATTR(cyttsp_force_update_fw, 0664, cyttsp_update_fw_show,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700852 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
Praveena Pachipulusu8b621e42011-08-10 18:17:07 +0530880static DEVICE_ATTR(cyttsp_update_fw, 0664, cyttsp_update_fw_show,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700881 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
Praveena Pachipulusu8b621e42011-08-10 18:17:07 +0530906static DEVICE_ATTR(cyttsp_fw_name, 0664, cyttsp_fw_name_show,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700907 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");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002176 tries = 0;
2177 do {
Anirudh Ghayalab2754e2011-08-22 12:39:31 +05302178 msleep(100);
2179 retval = i2c_smbus_write_i2c_block_data(ts->client,
2180 CY_REG_BASE, sizeof(bl_cmd), bl_cmd);
2181 if (retval == CY_OK)
2182 break;
2183 } while (tries++ < 5);
2184
2185 if (retval == CY_OK) {
2186 tries = 0;
2187 do {
2188 msleep(100);
2189 cyttsp_putbl(ts, 4, true, false, false);
2190 cyttsp_info("BL%d: f=%02X s=%02X err=%02X" \
2191 "bl=%02X%02X bld=%02X%02X\n", 104, \
2192 g_bl_data.bl_file, \
2193 g_bl_data.bl_status, \
2194 g_bl_data.bl_error, \
2195 g_bl_data.blver_hi, \
2196 g_bl_data.blver_lo, \
2197 g_bl_data.bld_blver_hi, \
2198 g_bl_data.bld_blver_lo);
2199 } while (GET_BOOTLOADERMODE(g_bl_data.bl_status) &&
2200 tries++ < 5);
2201 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002202 }
2203
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002204 if (!(retval < CY_OK) &&
2205 cyttsp_app_load()) {
2206 if (CY_DIFF(g_bl_data.ttspver_hi, cyttsp_tts_verh()) ||
2207 CY_DIFF(g_bl_data.ttspver_lo, cyttsp_tts_verl()) ||
2208 CY_DIFF(g_bl_data.appid_hi, cyttsp_app_idh()) ||
2209 CY_DIFF(g_bl_data.appid_lo, cyttsp_app_idl()) ||
2210 CY_DIFF(g_bl_data.appver_hi, cyttsp_app_verh()) ||
2211 CY_DIFF(g_bl_data.appver_lo, cyttsp_app_verl()) ||
2212 CY_DIFF(g_bl_data.cid_0, cyttsp_cid_0()) ||
2213 CY_DIFF(g_bl_data.cid_1, cyttsp_cid_1()) ||
2214 CY_DIFF(g_bl_data.cid_2, cyttsp_cid_2()) ||
2215 cyttsp_force_fw_load()) {
2216 cyttsp_debug("blttsp=0x%02X%02X flttsp=0x%02X%02X force=%d\n", \
2217 g_bl_data.ttspver_hi, g_bl_data.ttspver_lo, \
2218 cyttsp_tts_verh(), cyttsp_tts_verl(), \
2219 cyttsp_force_fw_load());
2220 cyttsp_debug("blappid=0x%02X%02X flappid=0x%02X%02X\n", \
2221 g_bl_data.appid_hi, g_bl_data.appid_lo, \
2222 cyttsp_app_idh(), cyttsp_app_idl());
2223 cyttsp_debug("blappver=0x%02X%02X flappver=0x%02X%02X\n", \
2224 g_bl_data.appver_hi, g_bl_data.appver_lo, \
2225 cyttsp_app_verh(), cyttsp_app_verl());
2226 cyttsp_debug("blcid=0x%02X%02X%02X flcid=0x%02X%02X%02X\n", \
2227 g_bl_data.cid_0, \
2228 g_bl_data.cid_1, \
2229 g_bl_data.cid_2, \
2230 cyttsp_cid_0(), \
2231 cyttsp_cid_1(), \
2232 cyttsp_cid_2());
2233 /* enter bootloader to load new app into TTSP Device */
2234 retval = cyttsp_bootload_app(ts);
2235 /* take TTSP device out of bootloader mode;
2236 * switch back to TrueTouch operational mode */
2237 if (!(retval < CY_OK)) {
2238 retval = i2c_smbus_write_i2c_block_data(ts->client,
2239 CY_REG_BASE,
2240 sizeof(bl_cmd), bl_cmd);
2241 /* wait for TTSP Device to complete
2242 * switch to Operational mode */
2243 tries = 0;
2244 do {
2245 mdelay(100);
2246 cyttsp_putbl(ts, 9, false, false, false);
2247 } while (GET_BOOTLOADERMODE(g_bl_data.bl_status) &&
2248 tries++ < 100);
2249 cyttsp_putbl(ts, 9, true, false, false);
2250 }
2251 }
2252 }
2253
2254bypass:
2255 /* switch to System Information mode to read versions
2256 * and set interval registers */
2257 if (!(retval < CY_OK)) {
2258 cyttsp_debug("switch to sysinfo mode \n");
2259 host_reg = CY_SYSINFO_MODE;
2260 retval = i2c_smbus_write_i2c_block_data(ts->client,
2261 CY_REG_BASE, sizeof(host_reg), &host_reg);
2262 /* wait for TTSP Device to complete switch to SysInfo mode */
2263 mdelay(100);
2264 if (!(retval < CY_OK)) {
2265 retval = i2c_smbus_read_i2c_block_data(ts->client,
2266 CY_REG_BASE,
2267 sizeof(struct cyttsp_sysinfo_data_t),
2268 (u8 *)&g_sysinfo_data);
2269 cyttsp_debug("SI2: hst_mode=0x%02X mfg_cmd=0x%02X mfg_stat=0x%02X\n", \
2270 g_sysinfo_data.hst_mode, \
2271 g_sysinfo_data.mfg_cmd, \
2272 g_sysinfo_data.mfg_stat);
2273 cyttsp_debug("SI2: bl_ver=0x%02X%02X\n", \
2274 g_sysinfo_data.bl_verh, \
2275 g_sysinfo_data.bl_verl);
2276 cyttsp_debug("SI2: sysinfo act_int=0x%02X tch_tmout=0x%02X lp_int=0x%02X\n", \
2277 g_sysinfo_data.act_intrvl, \
2278 g_sysinfo_data.tch_tmout, \
2279 g_sysinfo_data.lp_intrvl);
2280 cyttsp_info("SI%d: tver=%02X%02X a_id=%02X%02X aver=%02X%02X\n", \
2281 102, \
2282 g_sysinfo_data.tts_verh, \
2283 g_sysinfo_data.tts_verl, \
2284 g_sysinfo_data.app_idh, \
2285 g_sysinfo_data.app_idl, \
2286 g_sysinfo_data.app_verh, \
2287 g_sysinfo_data.app_verl);
2288 cyttsp_info("SI%d: c_id=%02X%02X%02X\n", \
2289 103, \
2290 g_sysinfo_data.cid[0], \
2291 g_sysinfo_data.cid[1], \
2292 g_sysinfo_data.cid[2]);
2293 if (!(retval < CY_OK) &&
2294 (CY_DIFF(ts->platform_data->act_intrvl,
2295 CY_ACT_INTRVL_DFLT) ||
2296 CY_DIFF(ts->platform_data->tch_tmout,
2297 CY_TCH_TMOUT_DFLT) ||
2298 CY_DIFF(ts->platform_data->lp_intrvl,
2299 CY_LP_INTRVL_DFLT))) {
2300 if (!(retval < CY_OK)) {
2301 u8 intrvl_ray[sizeof(ts->platform_data->act_intrvl) +
2302 sizeof(ts->platform_data->tch_tmout) +
2303 sizeof(ts->platform_data->lp_intrvl)];
2304 u8 i = 0;
2305
2306 intrvl_ray[i++] =
2307 ts->platform_data->act_intrvl;
2308 intrvl_ray[i++] =
2309 ts->platform_data->tch_tmout;
2310 intrvl_ray[i++] =
2311 ts->platform_data->lp_intrvl;
2312
2313 cyttsp_debug("SI2: platinfo act_intrvl=0x%02X tch_tmout=0x%02X lp_intrvl=0x%02X\n", \
2314 ts->platform_data->act_intrvl, \
2315 ts->platform_data->tch_tmout, \
2316 ts->platform_data->lp_intrvl);
2317 /* set intrvl registers */
2318 retval = i2c_smbus_write_i2c_block_data(
2319 ts->client,
2320 CY_REG_ACT_INTRVL,
2321 sizeof(intrvl_ray), intrvl_ray);
2322 mdelay(CY_DLY_SYSINFO);
2323 }
2324 }
2325 }
2326 /* switch back to Operational mode */
2327 cyttsp_debug("switch back to operational mode \n");
2328 if (!(retval < CY_OK)) {
2329 host_reg = CY_OP_MODE/* + CY_LOW_PWR_MODE*/;
2330 retval = i2c_smbus_write_i2c_block_data(ts->client,
2331 CY_REG_BASE,
2332 sizeof(host_reg), &host_reg);
2333 /* wait for TTSP Device to complete
2334 * switch to Operational mode */
2335 mdelay(100);
2336 }
2337 }
2338 /* init gesture setup;
2339 * this is required even if not using gestures
2340 * in order to set the active distance */
2341 if (!(retval < CY_OK)) {
2342 u8 gesture_setup;
2343 cyttsp_debug("init gesture setup \n");
2344 gesture_setup = ts->platform_data->gest_set;
2345 retval = i2c_smbus_write_i2c_block_data(ts->client,
2346 CY_REG_GEST_SET,
2347 sizeof(gesture_setup), &gesture_setup);
2348 mdelay(CY_DLY_DFLT);
2349 }
2350
2351 if (!(retval < CY_OK))
2352 ts->platform_data->power_state = CY_ACTIVE_STATE;
2353 else
2354 ts->platform_data->power_state = CY_IDLE_STATE;
2355
2356 cyttsp_debug("Retval=%d Power state is %s\n", \
2357 retval, \
2358 ts->platform_data->power_state == CY_ACTIVE_STATE ? \
2359 "ACTIVE" : "IDLE");
2360
2361 return retval;
2362}
2363
2364static int cyttsp_power_device(struct cyttsp *ts, bool on)
2365{
2366 int rc = 0, i;
2367 const struct cyttsp_regulator *reg_info =
2368 ts->platform_data->regulator_info;
2369 u8 num_reg = ts->platform_data->num_regulators;
2370
2371 if (!reg_info) {
2372 pr_err("regulator pdata not specified\n");
2373 return -EINVAL;
2374 }
2375
2376 if (on == false) /* Turn off the regulators */
2377 goto ts_reg_disable;
2378
2379 ts->vdd = kzalloc(num_reg * sizeof(struct regulator *), GFP_KERNEL);
2380 if (!ts->vdd) {
2381 pr_err("unable to allocate memory\n");
2382 return -ENOMEM;
2383 }
2384
2385 for (i = 0; i < num_reg; i++) {
2386 ts->vdd[i] = regulator_get(&ts->client->dev, reg_info[i].name);
2387 if (IS_ERR(ts->vdd[i])) {
2388 rc = PTR_ERR(ts->vdd[i]);
2389 pr_err("%s:regulator get failed rc=%d\n",
2390 __func__, rc);
2391 goto error_vdd;
2392 }
2393
2394 if (regulator_count_voltages(ts->vdd[i]) > 0) {
2395 rc = regulator_set_voltage(ts->vdd[i],
2396 reg_info[i].min_uV, reg_info[i].max_uV);
2397 if (rc) {
2398 pr_err("%s: regulator_set_voltage"
2399 "failed rc =%d\n", __func__, rc);
2400 regulator_put(ts->vdd[i]);
2401 goto error_vdd;
2402 }
2403 }
2404
2405 rc = regulator_set_optimum_mode(ts->vdd[i],
2406 reg_info[i].load_uA);
2407 if (rc < 0) {
2408 pr_err("%s: regulator_set_optimum_mode failed rc=%d\n",
2409 __func__, rc);
2410
2411 regulator_set_voltage(ts->vdd[i], 0,
2412 reg_info[i].max_uV);
2413 regulator_put(ts->vdd[i]);
2414 goto error_vdd;
2415 }
2416
2417 rc = regulator_enable(ts->vdd[i]);
2418 if (rc) {
2419 pr_err("%s: regulator_enable failed rc =%d\n",
2420 __func__, rc);
2421 regulator_set_optimum_mode(ts->vdd[i], 0);
2422 regulator_set_voltage(ts->vdd[i], 0,
2423 reg_info[i].max_uV);
2424 regulator_put(ts->vdd[i]);
2425 goto error_vdd;
2426 }
2427 }
2428
2429 return rc;
2430
2431ts_reg_disable:
2432 i = ts->platform_data->num_regulators;
2433error_vdd:
2434 while (--i >= 0) {
2435 if (regulator_count_voltages(ts->vdd[i]) > 0)
2436 regulator_set_voltage(ts->vdd[i], 0,
2437 reg_info[i].max_uV);
2438 regulator_set_optimum_mode(ts->vdd[i], 0);
2439 regulator_disable(ts->vdd[i]);
2440 regulator_put(ts->vdd[i]);
2441 }
2442 kfree(ts->vdd);
2443 return rc;
2444}
2445
2446/* cyttsp_initialize: Driver Initialization. This function takes
2447 * care of the following tasks:
2448 * 1. Create and register an input device with input layer
2449 * 2. Take CYTTSP device out of bootloader mode; go operational
2450 * 3. Start any timers/Work queues. */
2451static int cyttsp_initialize(struct i2c_client *client, struct cyttsp *ts)
2452{
2453 struct input_dev *input_device;
2454 int error = 0;
2455 int retval = CY_OK;
2456 u8 id;
2457
2458 /* Create the input device and register it. */
2459 input_device = input_allocate_device();
2460 if (!input_device) {
2461 error = -ENOMEM;
2462 cyttsp_xdebug1("err input allocate device\n");
2463 goto error_free_device;
2464 }
2465
2466 if (!client) {
2467 error = ~ENODEV;
2468 cyttsp_xdebug1("err client is Null\n");
2469 goto error_free_device;
2470 }
2471
2472 if (!ts) {
2473 error = ~ENODEV;
2474 cyttsp_xdebug1("err context is Null\n");
2475 goto error_free_device;
2476 }
2477
2478 ts->input = input_device;
2479 input_device->name = CY_I2C_NAME;
2480 input_device->phys = ts->phys;
2481 input_device->dev.parent = &client->dev;
2482
2483 /* init the touch structures */
2484 ts->num_prv_st_tch = CY_NTCH;
2485 for (id = 0; id < CY_NUM_TRK_ID; id++) {
2486 ts->act_trk[id] = CY_NTCH;
2487 ts->prv_mt_pos[id][CY_XPOS] = 0;
2488 ts->prv_mt_pos[id][CY_YPOS] = 0;
2489 }
2490
2491 for (id = 0; id < CY_NUM_MT_TCH_ID; id++)
2492 ts->prv_mt_tch[id] = CY_IGNR_TCH;
2493
2494 for (id = 0; id < CY_NUM_ST_TCH_ID; id++)
2495 ts->prv_st_tch[id] = CY_IGNR_TCH;
2496
2497 set_bit(EV_SYN, input_device->evbit);
2498 set_bit(EV_KEY, input_device->evbit);
2499 set_bit(EV_ABS, input_device->evbit);
2500 set_bit(BTN_TOUCH, input_device->keybit);
2501 set_bit(BTN_2, input_device->keybit);
2502 if (ts->platform_data->use_gestures)
2503 set_bit(BTN_3, input_device->keybit);
2504
2505 input_set_abs_params(input_device, ABS_X, ts->platform_data->disp_minx,
2506 ts->platform_data->disp_maxx, 0, 0);
2507 input_set_abs_params(input_device, ABS_Y, ts->platform_data->disp_miny,
2508 ts->platform_data->disp_maxy, 0, 0);
2509 input_set_abs_params(input_device,
2510 ABS_TOOL_WIDTH, 0, CY_LARGE_TOOL_WIDTH, 0 , 0);
2511 input_set_abs_params(input_device,
2512 ABS_PRESSURE, 0, CY_MAXZ, 0, 0);
2513 input_set_abs_params(input_device,
2514 ABS_HAT0X, 0, ts->platform_data->panel_maxx, 0, 0);
2515 input_set_abs_params(input_device,
2516 ABS_HAT0Y, 0, ts->platform_data->panel_maxy, 0, 0);
2517 if (ts->platform_data->use_gestures) {
2518 input_set_abs_params(input_device,
2519 ABS_HAT1X, 0, CY_MAXZ, 0, 0);
2520 input_set_abs_params(input_device,
2521 ABS_HAT1Y, 0, CY_MAXZ, 0, 0);
2522 }
2523 if (ts->platform_data->use_mt) {
2524 input_set_abs_params(input_device, ABS_MT_POSITION_X,
2525 ts->platform_data->disp_minx,
2526 ts->platform_data->disp_maxx, 0, 0);
2527 input_set_abs_params(input_device, ABS_MT_POSITION_Y,
2528 ts->platform_data->disp_miny,
2529 ts->platform_data->disp_maxy, 0, 0);
2530 input_set_abs_params(input_device,
2531 ABS_MT_TOUCH_MAJOR, 0, CY_MAXZ, 0, 0);
2532 input_set_abs_params(input_device,
2533 ABS_MT_WIDTH_MAJOR, 0, CY_LARGE_TOOL_WIDTH, 0, 0);
2534 if (ts->platform_data->use_trk_id) {
2535 input_set_abs_params(input_device,
2536 ABS_MT_TRACKING_ID, 0, CY_NUM_TRK_ID, 0, 0);
2537 }
2538 }
2539
2540 /* set dummy key to make driver work with virtual keys */
2541 input_set_capability(input_device, EV_KEY, KEY_PROG1);
2542
2543 cyttsp_info("%s: Register input device\n", CY_I2C_NAME);
2544 error = input_register_device(input_device);
2545 if (error) {
2546 cyttsp_alert("%s: Failed to register input device\n", \
2547 CY_I2C_NAME);
2548 retval = error;
2549 goto error_free_device;
2550 }
2551
2552 /* Prepare our worker structure prior to setting up the timer/ISR */
2553 INIT_WORK(&ts->work, cyttsp_xy_worker);
2554
2555 if (gpio_is_valid(ts->platform_data->resout_gpio)) {
2556 /* configure touchscreen reset out gpio */
2557 retval = gpio_request(ts->platform_data->resout_gpio,
2558 "cyttsp_resout_gpio");
2559 if (retval) {
2560 pr_err("%s: unable to request reset gpio %d\n",
2561 __func__, ts->platform_data->resout_gpio);
2562 goto error_free_device;
2563 }
2564
2565 retval = gpio_direction_output(
2566 ts->platform_data->resout_gpio, 1);
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_resout_gpio_dir;
2571 }
2572 }
2573
2574 if (gpio_is_valid(ts->platform_data->sleep_gpio)) {
2575 /* configure touchscreen reset out gpio */
2576 retval = gpio_request(ts->platform_data->sleep_gpio,
2577 "cy8c_sleep_gpio");
2578 if (retval) {
2579 pr_err("%s: unable to request sleep gpio %d\n",
2580 __func__, ts->platform_data->sleep_gpio);
2581 goto error_sleep_gpio_req;
2582 }
2583
2584 retval = gpio_direction_output(
2585 ts->platform_data->sleep_gpio, 0);
2586 if (retval) {
2587 pr_err("%s: unable to set direction for gpio %d\n",
2588 __func__, ts->platform_data->resout_gpio);
2589 goto error_sleep_gpio_dir;
2590 }
2591 }
2592
2593 if (gpio_is_valid(ts->platform_data->irq_gpio)) {
2594 /* configure touchscreen irq gpio */
2595 retval = gpio_request(ts->platform_data->irq_gpio,
2596 "ts_irq_gpio");
2597 if (retval) {
2598 pr_err("%s: unable to request gpio [%d]\n", __func__,
2599 ts->platform_data->irq_gpio);
2600 goto error_irq_gpio_req;
2601 }
2602 retval = gpio_direction_input(ts->platform_data->irq_gpio);
2603 if (retval) {
2604 pr_err("%s: unable to set_direction for gpio [%d]\n",
2605 __func__, ts->platform_data->irq_gpio);
2606 goto error_irq_gpio_dir;
2607 }
2608 }
2609
2610 if (ts->platform_data->regulator_info) {
2611 retval = cyttsp_power_device(ts, true);
2612 if (retval) {
2613 pr_err("%s: Unable to power device %d\n",
2614 __func__, retval);
2615 goto error_irq_gpio_dir;
2616 }
2617 }
2618
2619 /* Power on the chip and make sure that I/Os are set as specified
2620 * in the platform */
2621 if (ts->platform_data->init) {
2622 retval = ts->platform_data->init(client);
2623 if (retval) {
2624 pr_err("%s: ts init failed\n", __func__);
2625 goto error_power_device;
2626 }
2627 }
2628
2629 msleep(100);
2630
2631 /* check this device active by reading first byte/register */
2632 retval = i2c_smbus_read_byte_data(ts->client, 0x01);
2633 if (retval < 0) {
2634 pr_err("%s: i2c sanity check failed\n", __func__);
2635 goto error_power_device;
2636 }
2637
2638 retval = cyttsp_power_on(ts);
2639 if (retval < 0) {
2640 pr_err("%s: cyttsp_power_on failed\n", __func__);
2641 goto error_power_device;
2642 }
2643
2644 /* Timer or Interrupt setup */
2645 if (ts->client->irq == 0) {
2646 cyttsp_info("Setting up timer\n");
2647 setup_timer(&ts->timer, cyttsp_timer, (unsigned long) ts);
2648 mod_timer(&ts->timer, jiffies + TOUCHSCREEN_TIMEOUT);
2649 } else {
2650 cyttsp_info("Setting up interrupt\n");
2651 /* request_irq() will also call enable_irq() */
2652 error = request_irq(client->irq, cyttsp_irq,
2653 IRQF_TRIGGER_FALLING,
2654 client->dev.driver->name, ts);
2655 if (error) {
2656 cyttsp_alert("error: could not request irq\n");
2657 retval = error;
2658 goto error_power_device;
2659 }
2660 }
2661
2662 irq_cnt = 0;
2663 irq_cnt_total = 0;
2664 irq_err_cnt = 0;
2665
2666 atomic_set(&ts->irq_enabled, 1);
2667 retval = device_create_file(&ts->client->dev, &dev_attr_irq_enable);
2668 if (retval < CY_OK) {
2669 cyttsp_alert("File device creation failed: %d\n", retval);
2670 retval = -ENODEV;
2671 goto error_free_irq;
2672 }
2673
2674 retval = device_create_file(&client->dev, &dev_attr_cyttsp_fw_ver);
2675 if (retval) {
2676 cyttsp_alert("sysfs entry for firmware version failed\n");
2677 goto error_rm_dev_file_irq_en;
2678 }
2679
2680 ts->cyttsp_fwloader_mode = 0;
2681 retval = device_create_file(&client->dev, &dev_attr_cyttsp_update_fw);
2682 if (retval) {
2683 cyttsp_alert("sysfs entry for firmware update failed\n");
2684 goto error_rm_dev_file_fw_ver;
2685 }
2686
2687 retval = device_create_file(&client->dev,
2688 &dev_attr_cyttsp_force_update_fw);
2689 if (retval) {
2690 cyttsp_alert("sysfs entry for force firmware update failed\n");
2691 goto error_rm_dev_file_update_fw;
2692 }
2693 if (ts->platform_data->correct_fw_ver) {
2694 if (g_bl_data.appid_lo != ts->platform_data->correct_fw_ver)
Mohan Pallaka1cef4a02011-08-01 11:48:42 +05302695 pr_warn("%s: Invalid firmware version detected;"
2696 " Please update.\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002697 }
2698
2699 retval = device_create_file(&client->dev,
2700 &dev_attr_cyttsp_fw_name);
2701 if (retval) {
2702 cyttsp_alert("sysfs entry for file name selection failed\n");
2703 goto error_rm_dev_file_fupdate_fw;
2704 }
2705
2706 cyttsp_info("%s: Successful registration\n", CY_I2C_NAME);
2707
2708 goto success;
2709
2710error_rm_dev_file_fupdate_fw:
2711 device_remove_file(&client->dev, &dev_attr_cyttsp_force_update_fw);
2712error_rm_dev_file_update_fw:
2713 device_remove_file(&client->dev, &dev_attr_cyttsp_update_fw);
2714error_rm_dev_file_fw_ver:
2715 device_remove_file(&client->dev, &dev_attr_cyttsp_fw_ver);
2716error_rm_dev_file_irq_en:
2717 device_remove_file(&client->dev, &dev_attr_irq_enable);
2718error_free_irq:
2719 if (ts->client->irq)
2720 free_irq(client->irq, ts);
2721error_power_device:
2722 if (ts->platform_data->regulator_info)
2723 cyttsp_power_device(ts, false);
2724error_irq_gpio_dir:
2725 if (gpio_is_valid(ts->platform_data->irq_gpio))
2726 gpio_free(ts->platform_data->irq_gpio);
2727error_irq_gpio_req:
2728 if (gpio_is_valid(ts->platform_data->sleep_gpio))
2729 gpio_direction_output(ts->platform_data->sleep_gpio, 1);
2730error_sleep_gpio_dir:
2731 if (gpio_is_valid(ts->platform_data->sleep_gpio))
2732 gpio_free(ts->platform_data->sleep_gpio);
2733error_sleep_gpio_req:
2734 if (gpio_is_valid(ts->platform_data->resout_gpio))
2735 gpio_direction_output(ts->platform_data->resout_gpio, 0);
2736error_resout_gpio_dir:
2737 if (gpio_is_valid(ts->platform_data->resout_gpio))
2738 gpio_free(ts->platform_data->resout_gpio);
2739error_free_device:
2740 if (input_device)
2741 input_free_device(input_device);
2742
2743success:
2744 return retval;
2745}
2746
2747/* I2C driver probe function */
2748static int __devinit cyttsp_probe(struct i2c_client *client,
2749 const struct i2c_device_id *id)
2750{
2751 struct cyttsp *ts;
2752 int error;
2753 int retval = CY_OK;
2754
2755 cyttsp_info("Start Probe 1.2\n");
2756
2757 /* allocate and clear memory */
2758 ts = kzalloc(sizeof(struct cyttsp), GFP_KERNEL);
2759 if (ts == NULL) {
2760 cyttsp_xdebug1("err kzalloc for cyttsp\n");
2761 retval = -ENOMEM;
2762 }
2763
2764 /* Enable runtime PM ops, start in ACTIVE mode */
2765 error = pm_runtime_set_active(&client->dev);
2766 if (error < 0)
2767 dev_dbg(&client->dev, "unable to set runtime pm state\n");
2768 pm_runtime_enable(&client->dev);
2769
2770 if (!(retval < CY_OK)) {
2771 /* register driver_data */
2772 ts->client = client;
2773 ts->platform_data = client->dev.platform_data;
2774
2775 if (ts->platform_data->fw_fname)
2776 strncpy(ts->fw_fname, ts->platform_data->fw_fname,
2777 FW_FNAME_LEN - 1);
2778 else
2779 strncpy(ts->fw_fname, "cyttsp.hex", FW_FNAME_LEN - 1);
2780
Amy Malocheedd5fd72011-06-22 18:50:21 -07002781 if (ts->platform_data->gen == CY_GEN3) {
2782 ts->fw_start_addr = 0x0b00;
2783 } else if (ts->platform_data->gen == CY_GEN2) {
2784 ts->fw_start_addr = 0x0880;
2785 } else {
2786 pr_err("%s: unsupported cypress chip\n", __func__);
2787 kfree(ts);
2788 return -EINVAL;
2789 }
2790
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002791 i2c_set_clientdata(client, ts);
2792
2793 error = cyttsp_initialize(client, ts);
2794 if (error) {
2795 cyttsp_xdebug1("err cyttsp_initialize\n");
2796 if (ts != NULL) {
2797 /* deallocate memory */
2798 kfree(ts);
2799 }
2800/*
2801 i2c_del_driver(&cyttsp_driver);
2802*/
2803 retval = -ENODEV;
2804 } else
2805 cyttsp_openlog();
2806 }
2807
2808#ifdef CONFIG_HAS_EARLYSUSPEND
2809 if (!(retval < CY_OK)) {
2810 ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
2811 ts->early_suspend.suspend = cyttsp_early_suspend;
2812 ts->early_suspend.resume = cyttsp_late_resume;
2813 register_early_suspend(&ts->early_suspend);
2814 }
2815#endif /* CONFIG_HAS_EARLYSUSPEND */
2816 device_init_wakeup(&client->dev, ts->platform_data->wakeup);
2817 mutex_init(&ts->mutex);
2818
2819 cyttsp_info("Start Probe %s\n", \
2820 (retval < CY_OK) ? "FAIL" : "PASS");
2821
2822 return retval;
2823}
2824
2825/* Function to manage power-on resume */
2826static int cyttsp_resume(struct device *dev)
2827{
2828 struct cyttsp *ts = dev_get_drvdata(dev);
2829 int retval = CY_OK;
2830
2831 cyttsp_debug("Wake Up\n");
2832
2833 if (ts->is_suspended == false) {
2834 pr_err("%s: in wakeup state\n", __func__);
2835 return 0;
2836 }
2837
2838 if (device_may_wakeup(dev)) {
2839 if (ts->client->irq)
2840 disable_irq_wake(ts->client->irq);
2841 return 0;
2842 }
2843
2844 /* re-enable the interrupt prior to wake device */
2845 if (ts->client->irq)
2846 enable_irq(ts->client->irq);
2847
2848 if (ts->platform_data->use_sleep &&
2849 (ts->platform_data->power_state != CY_ACTIVE_STATE)) {
2850 if (ts->platform_data->resume)
2851 retval = ts->platform_data->resume(ts->client);
Amy Maloche13dcf552011-08-22 15:38:44 -07002852 /* take TTSP device out of bootloader mode;
2853 * switch back to TrueTouch operational mode */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002854 if (!(retval < CY_OK)) {
Amy Maloche13dcf552011-08-22 15:38:44 -07002855 int tries = 0;
2856 do {
2857 msleep(100);
2858 retval = i2c_smbus_write_i2c_block_data(
2859 ts->client, CY_REG_BASE,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002860 sizeof(bl_cmd), bl_cmd);
Amy Maloche13dcf552011-08-22 15:38:44 -07002861 if (retval == CY_OK)
2862 break;
2863 } while (tries++ < 2);
2864 /* wait for TTSP Device to complete
2865 * switch to Operational mode */
2866 tries = 0;
2867 do {
2868 msleep(100);
2869 cyttsp_putbl(ts, 16, false, false, false);
2870 } while (GET_BOOTLOADERMODE(g_bl_data.bl_status) &&
2871 tries++ < 2);
2872 cyttsp_putbl(ts, 16, true, false, false);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002873 }
2874 }
2875
2876 if (!(retval < CY_OK) &&
2877 (GET_HSTMODE(g_bl_data.bl_file) == CY_OK)) {
2878 ts->platform_data->power_state = CY_ACTIVE_STATE;
2879
2880 /* re-enable the timer after resuming */
2881 if (ts->client->irq == 0)
2882 mod_timer(&ts->timer, jiffies + TOUCHSCREEN_TIMEOUT);
2883 } else
2884 retval = -ENODEV;
2885
2886 ts->is_suspended = false;
2887 cyttsp_debug("Wake Up %s\n", \
2888 (retval < CY_OK) ? "FAIL" : "PASS");
2889
2890 return retval;
2891}
2892
2893
2894/* Function to manage low power suspend */
2895static int cyttsp_suspend(struct device *dev)
2896{
2897 struct cyttsp *ts = dev_get_drvdata(dev);
2898 u8 sleep_mode = CY_OK;
2899 int retval = CY_OK;
2900
2901 cyttsp_debug("Enter Sleep\n");
2902
2903 if (ts->is_suspended == true) {
2904 pr_err("%s: in sleep state\n", __func__);
2905 return 0;
2906 }
2907
2908 mutex_lock(&ts->mutex);
2909 if (ts->cyttsp_fwloader_mode) {
2910 pr_err("%s:firmware upgrade mode:"
2911 "suspend not allowed\n", __func__);
2912 mutex_unlock(&ts->mutex);
2913 return -EBUSY;
2914 }
2915 mutex_unlock(&ts->mutex);
2916
2917 if (device_may_wakeup(dev)) {
2918 if (ts->client->irq)
2919 enable_irq_wake(ts->client->irq);
2920 return 0;
2921 }
2922
2923 /* disable worker */
2924 if (ts->client->irq == 0)
2925 del_timer(&ts->timer);
2926 else
2927 disable_irq_nosync(ts->client->irq);
2928 retval = cancel_work_sync(&ts->work);
2929
2930 if (retval)
2931 enable_irq(ts->client->irq);
2932
2933 if (!(retval < CY_OK)) {
2934 if (ts->platform_data->use_sleep &&
2935 (ts->platform_data->power_state == CY_ACTIVE_STATE)) {
2936 if (ts->platform_data->use_sleep & CY_USE_DEEP_SLEEP_SEL)
2937 sleep_mode = CY_DEEP_SLEEP_MODE;
2938 else
2939 sleep_mode = CY_LOW_PWR_MODE;
2940
2941 retval = i2c_smbus_write_i2c_block_data(ts->client,
2942 CY_REG_BASE,
2943 sizeof(sleep_mode), &sleep_mode);
2944 }
2945 }
2946
2947 if (!(retval < CY_OK)) {
2948 if (sleep_mode == CY_DEEP_SLEEP_MODE)
2949 ts->platform_data->power_state = CY_SLEEP_STATE;
2950 else if (sleep_mode == CY_LOW_PWR_MODE)
2951 ts->platform_data->power_state = CY_LOW_PWR_STATE;
2952 }
2953
2954 ts->is_suspended = true;
2955 cyttsp_debug("Sleep Power state is %s\n", \
2956 (ts->platform_data->power_state == CY_ACTIVE_STATE) ? \
2957 "ACTIVE" : \
2958 ((ts->platform_data->power_state == CY_SLEEP_STATE) ? \
2959 "SLEEP" : "LOW POWER"));
2960
2961 return retval;
2962}
2963
2964/* registered in driver struct */
2965static int __devexit cyttsp_remove(struct i2c_client *client)
2966{
2967 /* clientdata registered on probe */
2968 struct cyttsp *ts = i2c_get_clientdata(client);
2969 int err;
2970
2971 cyttsp_alert("Unregister\n");
2972
2973 pm_runtime_set_suspended(&client->dev);
2974 pm_runtime_disable(&client->dev);
2975
2976 device_init_wakeup(&client->dev, 0);
2977 device_remove_file(&ts->client->dev, &dev_attr_irq_enable);
2978 device_remove_file(&client->dev, &dev_attr_cyttsp_fw_ver);
2979 device_remove_file(&client->dev, &dev_attr_cyttsp_update_fw);
2980 device_remove_file(&client->dev, &dev_attr_cyttsp_force_update_fw);
2981 device_remove_file(&client->dev, &dev_attr_cyttsp_fw_name);
2982
2983 /* Start cleaning up by removing any delayed work and the timer */
2984 if (cancel_delayed_work((struct delayed_work *)&ts->work) < CY_OK)
2985 cyttsp_alert("error: could not remove work from workqueue\n");
2986
2987 /* free up timer or irq */
2988 if (ts->client->irq == 0) {
2989 err = del_timer(&ts->timer);
2990 if (err < CY_OK)
2991 cyttsp_alert("error: failed to delete timer\n");
2992 } else
2993 free_irq(client->irq, ts);
2994
2995 if (ts->platform_data->regulator_info)
2996 cyttsp_power_device(ts, false);
2997
2998#ifdef CONFIG_HAS_EARLYSUSPEND
2999 unregister_early_suspend(&ts->early_suspend);
3000#endif /* CONFIG_HAS_EARLYSUSPEND */
3001
3002 mutex_destroy(&ts->mutex);
3003
3004 if (gpio_is_valid(ts->platform_data->sleep_gpio)) {
3005 gpio_direction_output(ts->platform_data->sleep_gpio, 1);
3006 gpio_free(ts->platform_data->sleep_gpio);
3007 }
3008
3009 if (gpio_is_valid(ts->platform_data->resout_gpio)) {
3010 gpio_direction_output(ts->platform_data->resout_gpio, 0);
3011 gpio_free(ts->platform_data->resout_gpio);
3012 }
3013
3014 if (gpio_is_valid(ts->platform_data->irq_gpio))
3015 gpio_free(ts->platform_data->irq_gpio);
3016
3017 /* housekeeping */
3018 if (ts != NULL)
3019 kfree(ts);
3020
3021 cyttsp_alert("Leaving\n");
3022
3023 return 0;
3024}
3025
3026#ifdef CONFIG_HAS_EARLYSUSPEND
3027static void cyttsp_early_suspend(struct early_suspend *handler)
3028{
3029 struct cyttsp *ts;
3030
3031 ts = container_of(handler, struct cyttsp, early_suspend);
3032 cyttsp_suspend(&ts->client->dev);
3033}
3034
3035static void cyttsp_late_resume(struct early_suspend *handler)
3036{
3037 struct cyttsp *ts;
3038
3039 ts = container_of(handler, struct cyttsp, early_suspend);
3040 cyttsp_resume(&ts->client->dev);
3041}
3042#endif /* CONFIG_HAS_EARLYSUSPEND */
3043
3044static int cyttsp_init(void)
3045{
3046 int ret;
3047
3048 cyttsp_info("Cypress TrueTouch(R) Standard Product\n");
3049 cyttsp_info("I2C Touchscreen Driver (Built %s @ %s)\n", \
3050 __DATE__, __TIME__);
3051
3052 cyttsp_ts_wq = create_singlethread_workqueue("cyttsp_ts_wq");
3053 if (cyttsp_ts_wq == NULL) {
3054 cyttsp_debug("No memory for cyttsp_ts_wq\n");
3055 return -ENOMEM;
3056 }
3057
3058 ret = i2c_add_driver(&cyttsp_driver);
3059
3060 return ret;
3061}
3062
3063static void cyttsp_exit(void)
3064{
3065 if (cyttsp_ts_wq)
3066 destroy_workqueue(cyttsp_ts_wq);
3067 return i2c_del_driver(&cyttsp_driver);
3068}
3069
3070module_init(cyttsp_init);
3071module_exit(cyttsp_exit);
3072MODULE_FIRMWARE("cyttsp.fw");
3073