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