summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-netbook-2.6.33.2/linux-2.6.34-cypress-touch-driver.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-kernel/linux/linux-netbook-2.6.33.2/linux-2.6.34-cypress-touch-driver.patch')
-rw-r--r--meta/recipes-kernel/linux/linux-netbook-2.6.33.2/linux-2.6.34-cypress-touch-driver.patch870
1 files changed, 870 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-netbook-2.6.33.2/linux-2.6.34-cypress-touch-driver.patch b/meta/recipes-kernel/linux/linux-netbook-2.6.33.2/linux-2.6.34-cypress-touch-driver.patch
new file mode 100644
index 0000000000..2dae9ed82d
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-netbook-2.6.33.2/linux-2.6.34-cypress-touch-driver.patch
@@ -0,0 +1,870 @@
1From 03e11a278286392dc20de57a24cadbc16d9aac3a Mon Sep 17 00:00:00 2001
2From: Priya Vijayan <priya.vijayan@intel.com>
3Date: Tue, 27 Apr 2010 11:23:00 -0700
4Subject: [PATCH] Touchscreen driver for Cypress panels
5
6This driver is from aava
7
8Signed-off-by: Priya Vijayan <priya.vijayan@intel.com>
9---
10 drivers/input/touchscreen/Kconfig | 8 +
11 drivers/input/touchscreen/Makefile | 1 +
12 drivers/input/touchscreen/cy8ctmg110_ts.c | 815 +++++++++++++++++++++++++++++
13 3 files changed, 824 insertions(+), 0 deletions(-)
14 create mode 100644 drivers/input/touchscreen/cy8ctmg110_ts.c
15
16diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
17index 6dd2674..5ecf00d 100644
18--- a/drivers/input/touchscreen/Kconfig
19+++ b/drivers/input/touchscreen/Kconfig
20@@ -103,6 +103,14 @@ config TOUCHSCREEN_CORGI
21 NOTE: this driver is deprecated, try enable SPI and generic
22 ADS7846-based touchscreen driver.
23
24+config TOUCHSCREEN_CY8CTMG110
25+ tristate "cy8ctmg110 touchscreen"
26+ depends on I2C
27+ default y
28+ help
29+ Say Y here if you have a cy8ctmg110 touchscreen capasitive touchscreen
30+ If unsure, say N.
31+
32 config TOUCHSCREEN_DA9034
33 tristate "Touchscreen support for Dialog Semiconductor DA9034"
34 depends on PMIC_DA903X
35diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
36index 15ad257..e5b5fae 100644
37--- a/drivers/input/touchscreen/Makefile
38+++ b/drivers/input/touchscreen/Makefile
39@@ -12,6 +12,7 @@ obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
40 obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o
41 obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
42 obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o
43+obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o
44 obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o
45 obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
46 obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o
47diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c
48new file mode 100644
49index 0000000..5587385
50--- /dev/null
51+++ b/drivers/input/touchscreen/cy8ctmg110_ts.c
52@@ -0,0 +1,815 @@
53+/*
54+ * cy8ctmg110_ts.c Driver for cypress touch screen controller
55+ * Copyright (c) 2009 Aava Mobile
56+ *
57+ * This program is free software; you can redistribute it and/or modify
58+ * it under the terms of the GNU General Public License version 2 as
59+ * published by the Free Software Foundation.
60+ *
61+ * This program is distributed in the hope that it will be useful,
62+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
63+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
64+ * GNU General Public License for more details.
65+ *
66+ * You should have received a copy of the GNU General Public License
67+ * along with this program; if not, write to the Free Software
68+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
69+ */
70+
71+#include <linux/module.h>
72+#include <linux/kernel.h>
73+#include <linux/input.h>
74+#include <linux/interrupt.h>
75+#include <asm/io.h>
76+#include <linux/i2c.h>
77+#include <linux/timer.h>
78+#include <linux/gpio.h>
79+#include <linux/hrtimer.h>
80+
81+#include <linux/platform_device.h>
82+#include <linux/delay.h>
83+#include <linux/fs.h>
84+#include <asm/ioctl.h>
85+#include <asm/ipc_defs.h>
86+#include <asm/uaccess.h>
87+#include <linux/device.h>
88+#include <linux/module.h>
89+#include <linux/platform_device.h>
90+#include <linux/delay.h>
91+#include <linux/fs.h>
92+#include <asm/ioctl.h>
93+#include <linux/fs.h>
94+#include <linux/init.h>
95+#include <linux/miscdevice.h>
96+#include <linux/module.h>
97+
98+
99+#define CY8CTMG110_DRIVER_NAME "cy8ctmg110"
100+#define CY8CTMG110_DRIVER_NAME_EXT "cy8ctmg110 ext"
101+/*#define MOORESTOWN_CDK*/
102+/*#define CY8CTMG110_DEBUG_INFO*/
103+/*#define POLL_TOUCH_EVENTS*/
104+
105+
106+
107+/*HW definations*/
108+
109+/*Main touch specific*/
110+#define CY8CTMG110_I2C_ADDR 0x38
111+#define CY8CTMG110_RESET_PIN_GPIO 43
112+#define CY8CTMG110_IRQ_PIN_GPIO 59
113+
114+/*Extended specific*/
115+#define CY8CTMG110_I2C_ADDR_EXT 0x39
116+#define CY8CTMG110_RESET_PIN_GPIO_EXT 39
117+#define CY8CTMG110_IRQ_PIN_GPIO_EXT 31
118+
119+
120+#define CY8CTMG110_TOUCH_LENGHT 9787
121+#define CY8CTMG110_SCREEN_LENGHT 8424
122+
123+
124+/*Main Touch coordinates*/
125+#define CY8CTMG110_X_MIN 0
126+#define CY8CTMG110_Y_MIN 0
127+#define CY8CTMG110_X_MAX 864
128+#define CY8CTMG110_Y_MAX 480
129+
130+
131+/*cy8ctmg110 registers defination*/
132+#define CY8CTMG110_TOUCH_WAKEUP_TIME 0
133+#define CY8CTMG110_TOUCH_SLEEP_TIME 2
134+#define CY8CTMG110_TOUCH_X1 3
135+#define CY8CTMG110_TOUCH_Y1 5
136+#define CY8CTMG110_TOUCH_X2 7
137+#define CY8CTMG110_TOUCH_Y2 9
138+#define CY8CTMG110_FINGERS 11
139+#define CY8CTMG110_GESTURE 12
140+#define CY8CTMG110_VERSIONID 13 //not supported in touchpanel FW
141+#define CY8CTMG110_REG_MAX 13
142+
143+#ifdef POLL_TOUCH_EVENTS
144+ #define CY8CTMG110_POLL_TIMER_DELAY 1000*1000*100
145+ #define TOUCH_MAX_I2C_FAILS 50
146+#endif
147+
148+#define CY8CTMG110_POLL_TIMER_DELAY 1000*1000*100
149+
150+/* Scale factors for coordinates */
151+#define X_SCALE_FACTOR 9387/8424
152+#define Y_SCALE_FACTOR 97/100
153+
154+/* For tracing */
155+static u16 g_y_trace_coord = 0;
156+
157+/*if soutcanyon*/
158+static bool isSc = false;
159+
160+
161+/*
162+ * Touchtype
163+ */
164+enum touch_type {
165+ TOUCH_KOSKI=1,
166+ TOUCH_SC,
167+ TOUCH_EXT,
168+};
169+
170+/*
171+ * The touch position structure.
172+ */
173+struct ts_event {
174+ int x1;
175+ int y1;
176+ int x2;
177+ int y2;
178+ bool event_sended;
179+};
180+
181+/*
182+ * The touch driver structure.
183+ */
184+struct cy8ctmg110 {
185+ struct input_dev *input;
186+ char phys[32];
187+ struct ts_event tc;
188+ struct i2c_client *client;
189+ bool pending;
190+ spinlock_t lock;
191+ bool initController;
192+ bool sleepmode;
193+ int irq_gpio;
194+ int reset_gpio;
195+ char driver_name[20];
196+ struct delayed_work work;
197+ enum touch_type version_id;
198+#ifdef POLL_TOUCH_EVENTS
199+ struct hrtimer timer;
200+ int i2c_fail_count;
201+#endif
202+};
203+
204+/*
205+ * cy8ctmg110_poweroff is the routine that is called when touch hardware
206+ * will powered off
207+ */
208+static void cy8ctmg110_power(struct cy8ctmg110 *ts,bool poweron)
209+{
210+#ifdef CY8CTMG110_DEBUG_INFO
211+ printk("%s power:%d\n",ts->driver_name,poweron);
212+#endif
213+ if (poweron)
214+ gpio_direction_output(ts->reset_gpio, 0);
215+ else
216+ gpio_direction_output(ts->reset_gpio, 1);
217+}
218+/*
219+ * cy8ctmg110_write_req write regs to the i2c devices
220+ *
221+ */
222+static int cy8ctmg110_write_req(struct cy8ctmg110 *tsc,unsigned char reg,unsigned char len,unsigned char *value)
223+{
224+ struct i2c_client *client = tsc->client;
225+ unsigned int ret;
226+ unsigned char i2c_data[]={0,0,0,0,0,0};
227+#ifdef CY8CTMG110_DEBUG_INFO
228+ printk("cy8ctmg110_init_req:\n");
229+#endif
230+
231+ i2c_data[0]=reg;
232+ memcpy(i2c_data+1,value,len);
233+
234+ {
235+ struct i2c_msg msg[] = {
236+ { client->addr, 0, len+1, i2c_data },
237+ };
238+
239+ ret = i2c_transfer(client->adapter, msg, 1);
240+
241+ if (ret != 1) {
242+ printk("cy8ctmg110 touch : i2c write data cmd failed \n");
243+ return ret;
244+ }
245+ }
246+
247+ return 0;
248+}
249+/*
250+ * get_time
251+ *
252+ */
253+#ifdef CY8CTMG110_DEBUG_INFO
254+static inline long cy8ctmg110_get_time(void)
255+{
256+ struct timeval t;
257+ do_gettimeofday(&t);
258+ return t.tv_usec;
259+}
260+#endif
261+/*
262+ * cy8ctmg110_read_req read regs from i2c devise
263+ *
264+ */
265+static int cy8ctmg110_read_req(struct cy8ctmg110 *tsc,unsigned char *i2c_data,unsigned char len ,unsigned char cmd)
266+{
267+ struct i2c_client *client = tsc->client;
268+ unsigned int ret;
269+ unsigned char regs_cmd[2]={0,0};
270+#ifdef CY8CTMG110_DEBUG_INFO
271+ long starttime = cy8ctmg110_get_time();
272+#endif
273+ regs_cmd[0]=cmd;
274+
275+
276+ /* first write slave position to i2c devices*/
277+ {
278+ struct i2c_msg msg1[] = {
279+ { client->addr, 0, 1, regs_cmd },
280+ };
281+
282+ ret = i2c_transfer(client->adapter, msg1, 1);
283+
284+ if (ret != 1) {
285+#ifdef POLL_TOUCH_EVENTS
286+ tsc->i2c_fail_count++;
287+#endif
288+ return ret;
289+ }
290+ }
291+
292+
293+ /* Second read data from position*/
294+ {
295+ struct i2c_msg msg2[] = {
296+ { client->addr, I2C_M_RD, len, i2c_data },
297+ };
298+
299+ ret = i2c_transfer(client->adapter, msg2, 1);
300+
301+
302+ if (ret != 1) {
303+#ifdef POLL_TOUCH_EVENTS
304+ tsc->i2c_fail_count++;
305+#endif
306+ return ret;
307+ }
308+ }
309+#ifdef CY8CTMG110_DEBUG_INFO
310+ printk("%s time to get data bytes read:%d time:%d\n",tsc->driver_name,len,(cy8ctmg110_get_time()-starttime));
311+#endif
312+ return 0;
313+}
314+/*
315+ * cy8ctmg110_send_event delevery touch event to the userpace
316+ * function use normal input interface
317+ */
318+static void cy8ctmg110_send_event(void *tsc,int x,int y)
319+{
320+ struct cy8ctmg110 *ts = tsc;
321+ struct input_dev *input = ts->input;
322+ u16 x2, y2;
323+#ifdef CY8CTMG110_DEBUG_INFO
324+ printk("cy8ctmg110_send_event\n");
325+#endif
326+
327+ if(ts->tc.event_sended == false){
328+
329+ if (ts->client->addr==CY8CTMG110_I2C_ADDR_EXT){
330+ /*Extended touchpanel*/
331+ input_report_key(input, BTN_TOUCH, 1);
332+
333+
334+ if ( ts->pending == true){
335+ input_report_rel(input, REL_Y, (ts->tc.x1-x)*2);
336+ input_report_rel(input, REL_X, (y - ts->tc.y1)*3);
337+ ts->tc.y1 = y;
338+ ts->tc.x1 = x;
339+ }
340+ else{
341+ ts->pending = true;
342+ ts->tc.y1 = y;
343+ ts->tc.x1 = x;
344+ }
345+
346+
347+ }
348+ else{
349+ /*Main touchpanel*/
350+ ts->tc.y1 = y;
351+ ts->tc.x1 = x;
352+ ts->pending = true;
353+ input_report_key(input, BTN_TOUCH, 1);
354+
355+ x2 = y;
356+ y2 = x;
357+
358+ if (isSc == false){
359+ /*Main touchpanel in koski*/
360+ x2 = (u16)(y*X_SCALE_FACTOR);
361+ y2 = (u16)(x*Y_SCALE_FACTOR);
362+ }
363+
364+ input_report_abs(input, ABS_X, x2);
365+ input_report_abs(input, ABS_Y, y2);
366+ }
367+
368+ input_sync(input);
369+ if(g_y_trace_coord)
370+ printk("%s touch position X:%d (was = %d) Y:%d (was = %d)\n",ts->driver_name, x2, y, y2, x);
371+ }
372+
373+}
374+
375+/*
376+ * cy8ctmg110_touch_pos check touch position from i2c devices
377+ *
378+ */
379+static int cy8ctmg110_touch_pos(struct cy8ctmg110 *tsc)
380+{
381+ unsigned char reg_p[CY8CTMG110_REG_MAX];
382+
383+ memset(reg_p,0,CY8CTMG110_REG_MAX);
384+
385+ /*Reading coordinates*/
386+ if (cy8ctmg110_read_req(tsc,reg_p,1,CY8CTMG110_FINGERS)==0){
387+
388+ /*number of touch*/
389+ if (reg_p[0]==0){
390+ if (tsc->pending == true){
391+ struct input_dev *input = tsc->input;
392+
393+ input_report_key(input, BTN_TOUCH, 0);
394+
395+ input_sync(input);
396+ tsc->tc.event_sended = true;
397+#ifdef CY8CTMG110_DEBUG_INFO
398+ printk("cy8ctmg110_send_event ts->pending = true;\n");
399+#endif
400+ tsc->pending = false;
401+ }
402+ }
403+ else {
404+
405+ if (cy8ctmg110_read_req(tsc,reg_p,4,CY8CTMG110_TOUCH_X1)==0){
406+ int x = 0,y = 0;
407+ y = reg_p[2]<<8 | reg_p[3];
408+ x = reg_p[0]<<8 | reg_p[1];
409+
410+ if (tsc->tc.x1 != x || tsc->tc.y1 != y){
411+ tsc->tc.event_sended = false;
412+ cy8ctmg110_send_event(tsc,x,y);
413+ }
414+ }
415+ }
416+ }
417+ else{
418+#ifdef CY8CTMG110_DEBUG_INFO
419+ printk("cy8ctmg110 i2c reading error\n");
420+#endif
421+ }
422+
423+ return 0;
424+}
425+/*
426+ * cy8ctmg110_read_versionid delevery touch event to the userpace
427+ * function use normal input interface
428+ */
429+static void cy8ctmg110_read_versionid(void *tsc)
430+{
431+ struct cy8ctmg110 *ts = tsc;
432+ unsigned char reg_p[2];
433+
434+
435+ if (cy8ctmg110_read_req(ts,reg_p,1,CY8CTMG110_VERSIONID)==0){
436+ printk("%s id 0x%x\n",ts->driver_name,reg_p[0]);
437+
438+ /*Ugly hack solution if SC
439+ */
440+
441+ if(ts->client->addr==CY8CTMG110_I2C_ADDR_EXT)
442+ isSc = true;
443+
444+ switch (reg_p[0]){
445+ case 0x01:
446+ ts->version_id = TOUCH_EXT;
447+ break;
448+ case 0x02:
449+ ts->version_id = TOUCH_SC;
450+ break;
451+ case 0x03:
452+ ts->version_id = TOUCH_KOSKI;
453+ break;
454+ default:
455+ ts->version_id = TOUCH_KOSKI;
456+ break;
457+ }
458+ }
459+}
460+
461+
462+#ifdef POLL_TOUCH_EVENTS
463+/*
464+ * if interup is'n in use the touch positions can reads by polling
465+ *
466+ */
467+static enum hrtimer_restart cy8ctmg110_timer(struct hrtimer *handle)
468+{
469+ struct cy8ctmg110 *ts = container_of(handle, struct cy8ctmg110, timer);
470+ unsigned long flags;
471+
472+ spin_lock_irqsave(&ts->lock, flags);
473+#ifdef CY8CTMG110_DEBUG_INFO
474+ printk("cy8ctmg110_timer\n");
475+#endif
476+
477+ cy8ctmg110_touch_pos(ts);
478+
479+ if (ts->i2c_fail_count<TOUCH_MAX_I2C_FAILS)
480+ hrtimer_start(&ts->timer, ktime_set(0, CY8CTMG110_POLL_TIMER_DELAY),
481+ HRTIMER_MODE_REL);
482+
483+ spin_unlock_irqrestore(&ts->lock, flags);
484+
485+ return HRTIMER_NORESTART;
486+}
487+#endif
488+/*
489+ * cy8ctmg110_init_controller set init value to touchcontroller
490+ *
491+ */
492+static bool cy8ctmg110_set_sleepmode(struct cy8ctmg110 *ts)
493+{
494+ unsigned char reg_p[3];
495+
496+ if(ts->sleepmode==true){
497+ reg_p[0] = 0x00; reg_p[1] =0xff; reg_p[2] =5;
498+ }else{
499+ reg_p[0] = 0x10;reg_p[1] =0xff;reg_p[2] =0;
500+ }
501+
502+ if (cy8ctmg110_write_req(ts,CY8CTMG110_TOUCH_WAKEUP_TIME,3,reg_p)){
503+ return false;
504+ }
505+ ts->initController = true;
506+
507+ return true;
508+}
509+
510+
511+
512+static void cy8ctmg110_work(struct work_struct *work)
513+{
514+ struct cy8ctmg110 *ts =
515+ container_of(to_delayed_work(work), struct cy8ctmg110, work);
516+
517+ cy8ctmg110_touch_pos(ts);
518+}
519+
520+
521+/*
522+ * cy8ctmg110_irq_handler irq handling function
523+ *
524+ */
525+static irqreturn_t cy8ctmg110_irq_handler(int irq, void *handle)
526+{
527+ struct cy8ctmg110 * tsc = (struct cy8ctmg110 *)handle;
528+
529+#ifdef CY8CTMG110_DEBUG_INFO
530+ printk("%s cy8ctmg110_irq_handler\n",tsc->driver_name);
531+#endif
532+ if (tsc->initController == false){
533+ if (cy8ctmg110_set_sleepmode(tsc) == true)
534+ tsc->initController = true;
535+ }
536+ else
537+ {
538+ schedule_delayed_work(&tsc->work,
539+ msecs_to_jiffies(1));
540+ }
541+
542+#ifdef POLL_TOUCH_EVENTS
543+ /*if interrupt supported in the touch controller
544+ timer polling need to stop*/
545+ tsc->i2c_fail_count = TOUCH_MAX_I2C_FAILS;
546+#endif
547+ return IRQ_HANDLED;
548+}
549+
550+
551+static int cy8ctmg110_probe(struct i2c_client *client,
552+ const struct i2c_device_id *id)
553+{
554+ struct cy8ctmg110 *ts;
555+ struct input_dev *input_dev;
556+ int err;
557+
558+ if (!i2c_check_functionality(client->adapter,
559+ I2C_FUNC_SMBUS_READ_WORD_DATA))
560+ return -EIO;
561+
562+ ts = kzalloc(sizeof(struct cy8ctmg110), GFP_KERNEL);
563+ input_dev = input_allocate_device();
564+
565+ if (!ts || !input_dev) {
566+ err = -ENOMEM;
567+ goto err_free_mem;
568+ }
569+
570+ ts->client = client;
571+ i2c_set_clientdata(client, ts);
572+
573+ ts->input = input_dev;
574+ ts->pending = false;
575+ ts->sleepmode = false;
576+
577+
578+ if(client->addr==CY8CTMG110_I2C_ADDR){
579+ ts->reset_gpio = CY8CTMG110_RESET_PIN_GPIO;
580+ input_dev->name = CY8CTMG110_DRIVER_NAME" Touchscreen";
581+ snprintf(ts->driver_name, sizeof(ts->driver_name),"%s", CY8CTMG110_DRIVER_NAME);
582+ }
583+ else if (client->addr==CY8CTMG110_I2C_ADDR_EXT){
584+ ts->reset_gpio = CY8CTMG110_RESET_PIN_GPIO_EXT;
585+ input_dev->name = CY8CTMG110_DRIVER_NAME_EXT" Touchscreen";
586+ snprintf(ts->driver_name, sizeof(ts->driver_name),"%s", CY8CTMG110_DRIVER_NAME_EXT);
587+ }
588+
589+ snprintf(ts->phys, sizeof(ts->phys),
590+ "%s/input0", dev_name(&client->dev));
591+
592+ INIT_DELAYED_WORK(&ts->work, cy8ctmg110_work);
593+
594+ input_dev->phys = ts->phys;
595+ input_dev->id.bustype = BUS_I2C;
596+
597+ spin_lock_init(&ts->lock);
598+
599+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
600+ BIT_MASK(EV_REL) | BIT_MASK(EV_ABS);
601+
602+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
603+
604+ input_set_capability(input_dev, EV_KEY, KEY_F);
605+
606+
607+ input_set_abs_params(input_dev, ABS_X, CY8CTMG110_X_MIN, CY8CTMG110_X_MAX, 0, 0);
608+ input_set_abs_params(input_dev, ABS_Y, CY8CTMG110_Y_MIN, CY8CTMG110_Y_MAX, 0, 0);
609+ input_dev->relbit[BIT_WORD(REL_X)] = BIT_MASK(REL_X)| BIT_MASK(REL_Y);
610+
611+ err = gpio_request(ts->reset_gpio, NULL);
612+
613+ if (err) {
614+ printk("GPIO pin %d failed to request.\n", ts->reset_gpio);
615+ goto err_free_thread;
616+ }
617+
618+ cy8ctmg110_power(ts,true);
619+
620+ ts->initController = false;
621+#ifdef POLL_TOUCH_EVENTS
622+ ts->i2c_fail_count = 0;
623+ hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
624+ ts->timer.function = cy8ctmg110_timer;
625+
626+ hrtimer_start(&ts->timer, ktime_set(10, 0),
627+ HRTIMER_MODE_REL);
628+#endif
629+ err = gpio_request(client->irq, "touch_irq_key");
630+
631+ if (err < 0) {
632+ printk("%s gpio-keys: failed to request GPIO %d,"
633+ " error %d\n",ts->driver_name,client->irq, err);
634+ goto err_free_thread;
635+ }
636+
637+ err= gpio_direction_input(client->irq);
638+
639+ if (err < 0) {
640+ pr_err("%s gpio-keys: failed to configure input"
641+ " direction for GPIO %d, error %d\n",ts->driver_name,client->irq, err);
642+ gpio_free(client->irq);
643+ goto err_free_thread;
644+ }
645+
646+ ts->irq_gpio = gpio_to_irq(client->irq);
647+
648+ if (ts->irq_gpio < 0) {
649+ err = ts->irq_gpio;
650+ pr_err("cy8ctmg110 gpio-keys: Unable to get irq number"
651+ " for GPIO %d, error %d\n",
652+ ts->irq_gpio, err);
653+ gpio_free(ts->irq_gpio);
654+ goto err_free_thread;
655+ }
656+
657+ if (client->addr!=CY8CTMG110_I2C_ADDR_EXT){
658+ err = request_irq(ts->irq_gpio, cy8ctmg110_irq_handler,
659+ IRQF_TRIGGER_RISING | IRQF_SHARED,
660+ "touch_reset_key",
661+ ts);
662+ }
663+
664+ if (err < 0) {
665+ dev_err(&client->dev, "cy8ctmg110 irq %d busy? error %d\n", ts->irq_gpio ,err);
666+ goto err_free_thread;
667+ }
668+
669+ err = input_register_device(input_dev);
670+ cy8ctmg110_read_versionid(ts);
671+
672+ if (err)
673+ goto err_free_irq;
674+
675+ return 0;
676+
677+ err_free_irq:
678+ printk("%s err_free_irq\n",ts->driver_name);
679+ free_irq(client->irq, ts);
680+ err_free_thread:
681+ printk("%s err_free_thread\n",ts->driver_name);
682+ err_free_mem:
683+ printk("%s err_free_mem\n",ts->driver_name);
684+ input_free_device(input_dev);
685+ kfree(ts);
686+
687+ return err;
688+}
689+/*
690+ * cy8ctmg110_suspend
691+ *
692+ */
693+static int cy8ctmg110_suspend(struct i2c_client *client, pm_message_t mesg)
694+{
695+ if (device_may_wakeup(&client->dev))
696+ enable_irq_wake(client->irq);
697+
698+ return 0;
699+}
700+/*
701+ * cy8ctmg110_resume
702+ *
703+ */
704+static int cy8ctmg110_resume(struct i2c_client *client)
705+{
706+ if (device_may_wakeup(&client->dev))
707+ disable_irq_wake(client->irq);
708+
709+ return 0;
710+}
711+/*
712+ * cy8ctmg110_remove
713+ *
714+ */
715+static int cy8ctmg110_remove(struct i2c_client *client)
716+{
717+ struct cy8ctmg110 *ts = i2c_get_clientdata(client);
718+
719+#ifdef CY8CTMG110_DEBUG_INFO
720+ printk("cy8ctmg110_remove\n");
721+#endif
722+
723+ cy8ctmg110_power(ts,false);
724+#ifdef POLL_TOUCH_EVENTS
725+ hrtimer_cancel(&ts->timer);
726+#endif
727+
728+ free_irq(client->irq, ts);
729+ input_unregister_device(ts->input);
730+ kfree(ts);
731+
732+ return 0;
733+}
734+
735+static struct i2c_device_id cy8ctmg110_idtable[] = {
736+ { CY8CTMG110_DRIVER_NAME, 1 },
737+ { CY8CTMG110_DRIVER_NAME_EXT, 1 },
738+ { }
739+};
740+
741+MODULE_DEVICE_TABLE(i2c, cy8ctmg110_idtable);
742+
743+static struct i2c_driver cy8ctmg110_driver = {
744+ .driver = {
745+ .owner = THIS_MODULE,
746+ .name = CY8CTMG110_DRIVER_NAME,
747+ .bus = &i2c_bus_type,
748+ },
749+ .id_table = cy8ctmg110_idtable,
750+ .probe = cy8ctmg110_probe,
751+ .remove = cy8ctmg110_remove,
752+ .suspend = cy8ctmg110_suspend,
753+ .resume = cy8ctmg110_resume,
754+};
755+
756+
757+static int __init cy8ctmg110_init(void)
758+{
759+ printk("cy8ctmg110_init\n");
760+
761+ return i2c_add_driver(&cy8ctmg110_driver);
762+}
763+
764+static void __exit cy8ctmg110_exit(void)
765+{
766+#ifdef CY8CTMG110_DEBUG_INFO
767+ printk("cy8ctmg110_exit\n");
768+#endif
769+ i2c_del_driver(&cy8ctmg110_driver);
770+}
771+
772+module_init(cy8ctmg110_init);
773+module_exit(cy8ctmg110_exit);
774+
775+
776+struct i2c_board_info __initdata koski_i2c_board_info2[] = {
777+ {
778+ I2C_BOARD_INFO(CY8CTMG110_DRIVER_NAME, CY8CTMG110_I2C_ADDR),
779+ .irq = CY8CTMG110_IRQ_PIN_GPIO
780+ },
781+ {
782+ I2C_BOARD_INFO(CY8CTMG110_DRIVER_NAME_EXT, CY8CTMG110_I2C_ADDR_EXT),
783+ .irq = CY8CTMG110_IRQ_PIN_GPIO_EXT
784+ },
785+};
786+
787+
788+static int __init koski_i2c_init(void)
789+{
790+ printk("init koski board\n");
791+
792+#ifdef MOORESTOWN_CDK
793+ /*init koski i2c*/
794+ i2c_register_board_info(1, koski_i2c_board_info2,
795+ ARRAY_SIZE(koski_i2c_board_info2));
796+#else
797+ /*init koski i2c*/
798+ i2c_register_board_info(0, koski_i2c_board_info2,
799+ ARRAY_SIZE(koski_i2c_board_info2));
800+#endif
801+ return 0;
802+}
803+
804+module_init(koski_i2c_init);
805+
806+MODULE_AUTHOR("Samuli Konttila <samuli.konttila@aavamobile.com>");
807+MODULE_DESCRIPTION("cy8ctmg110 TouchScreen Driver");
808+MODULE_LICENSE("GPL v2");
809+
810+
811+// Aava access from sysfs begin
812+static ssize_t aava_query_fw_info_func(struct class *class, char *buf)
813+{
814+ ssize_t status;
815+ int i = 0;
816+ unsigned char mrst_fw_ver_info[16];
817+
818+ printk("!!! aava_query_fw_info_func() ENTER\n");
819+
820+ status = mrst_get_firmware_version(mrst_fw_ver_info);
821+ for (i = 0; i < 16; i++){
822+ printk("%x\n", mrst_fw_ver_info[i]);
823+ buf[i] = mrst_fw_ver_info[i];
824+ }
825+
826+ return 16;
827+}
828+
829+static ssize_t aava_enable_touch_traces_func(struct class *class, \
830+ const char *buf, size_t len)
831+{
832+ ssize_t status;
833+ unsigned long value;
834+
835+ status = strict_strtoul(buf, 0, &value);
836+ printk("!!! aava_enable_touch_traces_func() = %d\n", (int)value);
837+
838+ g_y_trace_coord = value;
839+
840+ return len;
841+}
842+
843+static struct class_attribute aava_class_attrs[] = {
844+ __ATTR(aava_query_fw_info, 0444, aava_query_fw_info_func, NULL),
845+ __ATTR(aava_enable_touch_traces, 0200, NULL, aava_enable_touch_traces_func),
846+ __ATTR_NULL,
847+};
848+
849+static struct class aava_class = {
850+ .name = "aava",
851+ .owner = THIS_MODULE,
852+
853+ .class_attrs = aava_class_attrs,
854+};
855+
856+static int __init aava_sysfs_init(void)
857+{
858+ int status;
859+
860+ status = class_register(&aava_class);
861+ if (status < 0)
862+ return status;
863+
864+ return status;
865+}
866+postcore_initcall(aava_sysfs_init);
867+// Aava access from sysfs end
868--
8691.6.2.2
870