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