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