upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / input / keyboard / cypress_touchkey.c
1 /*
2  *  For CYPRESS CY8C20236-24LKX1 TouchSensor driver
3  *
4  * Copyright (C) 2010 Samsung Electronics Co.Ltd
5  * Author: Junkyeong Kim <jk0430.kim@samsung.com>
6  *
7  *  This program is free software; you can redistribute  it and/or modify it
8  *  under  the terms of  the GNU General  Public License as published by the
9  *  Free Software Foundation.
10  *
11  */
12
13 #include <linux/module.h>
14 #include <linux/firmware.h>
15 #include <linux/init.h>
16 #include <linux/i2c.h>
17 #include <linux/i2c/cypress_touchkey.h>
18 #include <linux/interrupt.h>
19 #include <linux/input.h>
20 #include <linux/irq.h>
21 #include <linux/workqueue.h>
22 #include <linux/delay.h>
23 #include <linux/gpio.h>
24 #include <linux/slab.h>
25 #include <linux/pm_runtime.h>
26 #include <linux/fb.h>
27 #include <plat/gpio-cfg.h>
28
29 /* for i2c */
30 #define I2C_M_WR 0
31
32 /* register */
33 #define CYPRESS_TK_CONTROL_REG                  0x00
34 #define CYPRESS_TK_KEYCODE_REG                  0x00
35 #define CYPRESS_TK_FW_VERSION                   0x01
36 #define CYPRESS_TK_MD_VERSION                   0x02
37
38 /* read value bit */
39 #define KEYCODE_VALUE           0x07
40 #define UPDOWN_EVENT            0x08
41 #define ESD_STATE_BIT           0x10
42
43 /* LED time */
44 #define PRESS_LED_TIME                  500
45 #define WAKEUP_LED_TIME                 5000
46
47 struct cypress_data {
48         struct i2c_client *client;
49         struct input_dev *input_dev;
50         struct work_struct event_work;
51         struct cypress_platform_data *pdata;
52
53         unsigned int type;
54         unsigned int irq;
55         unsigned char last_key;
56
57         /* The framebuffer notifier block */
58         struct notifier_block fb_notif;
59 };
60
61 static struct i2c_driver cypress_tk_driver;
62 struct cypress_data *global_cypress_data;
63
64 static struct timer_list cypress_led_off_timer;
65 struct work_struct cypress_led_onoff_work;
66
67 int cypress_key_onoff;
68 int cypress_key_debug;
69 int cypress_irq_flag;
70 int cypress_led_onoff;
71 int cypress_led_timer_start;
72 u8 cypress_fw_ver, cypress_md_ver;
73
74 static void cypress_hardware_reset(struct i2c_client *client)
75 {
76         struct cypress_data *data = i2c_get_clientdata(client);
77
78         if (cypress_key_onoff == 0)
79                 return;
80
81         disable_irq(client->irq);
82
83         s3c_gpio_cfgpin(data->pdata->pin->gpio_sda, S3C_GPIO_OUTPUT);
84         s3c_gpio_cfgpin(data->pdata->pin->gpio_scl, S3C_GPIO_OUTPUT);
85         s3c_gpio_cfgpin(data->pdata->pin->gpio_int, S3C_GPIO_OUTPUT);
86
87         s3c_gpio_setpull(data->pdata->pin->gpio_sda, S3C_GPIO_PULL_NONE);
88         s3c_gpio_setpull(data->pdata->pin->gpio_scl, S3C_GPIO_PULL_NONE);
89         s3c_gpio_setpull(data->pdata->pin->gpio_int, S3C_GPIO_PULL_NONE);
90
91         gpio_direction_output(data->pdata->pin->gpio_sda, 0);
92         gpio_direction_output(data->pdata->pin->gpio_scl, 0);
93         gpio_direction_output(data->pdata->pin->gpio_int, 0);
94
95         data->pdata->power_pin(0);
96
97         /* i2c pin pull up controled by touch chip */
98         s3c_gpio_setpull(data->pdata->pin->gpio_int, S3C_GPIO_PULL_UP);
99
100         s3c_gpio_cfgpin(data->pdata->pin->gpio_sda, S3C_GPIO_SFN(2));
101         s3c_gpio_cfgpin(data->pdata->pin->gpio_scl, S3C_GPIO_SFN(2));
102         s3c_gpio_cfgpin(data->pdata->pin->gpio_int, S3C_GPIO_SFN(0xf));
103         msleep(1);
104
105         data->pdata->power_pin(1);
106
107         enable_irq(client->irq);
108
109         printk(KERN_INFO "[TK] %s excute\n", __func__);
110 }
111
112 static int cypress_i2c_read(struct i2c_client *client, u8 reg, u8 *val, int len)
113 {
114         struct i2c_msg msg[1];
115         int ret;
116
117         msg->addr = client->addr;
118         msg->flags = client->flags | I2C_M_RD;
119         msg->len = len;
120         msg->buf = (char *)val;
121
122         ret = i2c_transfer(client->adapter, msg, 1);
123         if (ret != 1) {
124                 dev_err(&client->dev, "[TK][R] i2c transfer failed. ret:%d, reg:%02x, val:%02x\n",
125                         ret, reg, *val);
126                 msleep(5);
127                 /* if failed, try one moer time */
128                 ret = i2c_transfer(client->adapter, msg, 1);
129                 if (ret != 1) {
130                         dev_err(&client->dev, "[TK][R] i2c transfer failed 2. ret:%d, reg:%02x, val:%02x\n",
131                                 ret, reg, *val);
132                         /* hardware reset */
133                         cypress_hardware_reset(client);
134                         return ret;
135                 }
136         }
137         return 0;
138 }
139
140 static int cypress_i2c_write(struct i2c_client *client, u8 reg, u8 *val, int len)
141 {
142         struct i2c_msg msg[1];
143         int ret;
144
145         msg->addr = client->addr;
146         msg->flags = I2C_M_WR;
147         msg->len = len;
148         msg->buf = (char *)val;
149
150         ret = i2c_transfer(client->adapter, msg, 1);
151         if (ret != 1) {
152                 dev_err(&client->dev, "[TK][W] i2c transfer failed. ret:%d, reg:%02x, val:%02x\n",
153                         ret, reg, *val);
154                 msleep(5);
155                 /* if failed, try one moer time */
156                 ret = i2c_transfer(client->adapter, msg, 1);
157                 if (ret != 1) {
158                         dev_err(&client->dev, "[TK][W] i2c transfer failed 2. ret:%d, reg:%02x, val:%02x\n",
159                                 ret, reg, *val);
160                         /* hardware reset */
161                         cypress_hardware_reset(client);
162                         return ret;
163                 }
164         }
165         return 0;
166 }
167
168 int cypress_debug_on(struct i2c_client *client)
169 {
170         int ret;
171         unsigned char buf = 0x40;
172
173         ret = cypress_i2c_write(client, CYPRESS_TK_CONTROL_REG, &buf, 1);
174         if (ret != 0) {
175                 dev_err(&client->dev, "[TK] %s: error\n", __func__);
176                 return ret;
177         }
178         return 0;
179 }
180
181 void cypress_tk_led_on(struct i2c_client *client)
182 {
183         int ret;
184         unsigned char buf = 0x1;
185
186         ret = cypress_i2c_write(client, CYPRESS_TK_CONTROL_REG, &buf, 1);
187         if (ret != 0)
188                 dev_err(&client->dev, "[TK] %s: error\n", __func__);
189 }
190
191 void cypress_tk_led_off(struct i2c_client *client)
192 {
193         int ret;
194         unsigned char buf = 0x2;
195
196         ret = cypress_i2c_write(client, CYPRESS_TK_CONTROL_REG, &buf, 1);
197         if (ret != 0)
198                 dev_err(&client->dev, "[TK] %s: error\n", __func__);
199 }
200
201
202 static void cypress_led_onoff_worker(struct work_struct *work)
203 {
204         struct i2c_client *client = global_cypress_data->client;
205
206         local_irq_disable();
207         if (cypress_led_onoff == 1) {
208                 local_irq_enable();
209                 cypress_tk_led_on(client);
210                 if (cypress_led_timer_start != 1) {
211                         cypress_led_off_timer.expires = (jiffies + (400)); /* 2sec */
212                         add_timer(&cypress_led_off_timer);
213                         cypress_led_timer_start = 1;
214                 }
215         } else {
216                 local_irq_enable();
217                 cypress_tk_led_off(client);
218         }
219 }
220
221 static void cypress_led_off_timer_handler(unsigned long timer_data)
222 {
223         if ((cypress_key_onoff == 1) && (cypress_led_onoff == 1)) {
224                 cypress_led_onoff = 0;
225                 if (!work_pending(&cypress_led_onoff_work))
226                         schedule_work(&cypress_led_onoff_work);
227         }
228         cypress_led_timer_start = 0;
229 }
230
231 void cypress_tk_led_onoff_function(int flag)
232 {
233         struct i2c_client *client;
234
235         if (global_cypress_data == NULL)
236                 return;
237
238         client = global_cypress_data->client;
239
240         if (cypress_key_onoff == 0)
241                 return;
242
243         if (cypress_irq_flag == 0)
244                 return;
245
246         if (cypress_led_onoff == 0) {
247                 if (flag == 1) {
248                         cypress_led_onoff = 1;
249                         if (!work_pending(&cypress_led_onoff_work))
250                                 schedule_work(&cypress_led_onoff_work);
251                 }
252         } else if (cypress_led_onoff == 1) {
253                 if (flag == 1) {
254                         if (cypress_led_timer_start == 1) {
255                                 del_timer(&cypress_led_off_timer);
256                                 cypress_led_off_timer.expires = (jiffies + (400)); /* 2sec */
257                                 add_timer(&cypress_led_off_timer);
258                         }
259                 } else if (flag == 0) {
260                         cypress_led_onoff = 0;
261                         del_timer(&cypress_led_off_timer);
262                         cypress_led_timer_start = 0;
263                         if (!work_pending(&cypress_led_onoff_work))
264                                 schedule_work(&cypress_led_onoff_work);
265                 }
266         }
267 }
268 EXPORT_SYMBOL(cypress_tk_led_onoff_function);
269
270 void cypress_touchkey_irq_flag_function(int flag)
271 {
272         if (global_cypress_data == NULL)
273                 return;
274
275         if (flag == 0) {
276                 if (global_cypress_data->pdata->led_pin)
277                         global_cypress_data->pdata->led_pin(0);
278                 cypress_tk_led_onoff_function(0);
279                 cypress_irq_flag = 0;
280         } else if (flag == 1) {
281                 cypress_irq_flag = 1;
282                 if (global_cypress_data->pdata->led_pin)
283                         global_cypress_data->pdata->led_pin(1);
284                 cypress_tk_led_onoff_function(1);
285
286         }
287 }
288 EXPORT_SYMBOL(cypress_touchkey_irq_flag_function);
289
290 static void cypress_tk_input_read(struct cypress_data *data)
291 {
292         struct i2c_client *client = data->client;
293         const struct cypress_platform_data *pdata = data->pdata;
294         struct input_dev *input = data->input_dev;
295         unsigned int value, updown;
296         unsigned int key;
297         int pushed;
298         u8 buffer;
299         int ret;
300
301         ret = cypress_i2c_read(client, CYPRESS_TK_KEYCODE_REG, &buffer, 1);
302         if (ret != 0) {
303                 dev_err(&client->dev, "[TK] %s: error\n", __func__);
304                 return;
305         }
306
307         if (cypress_irq_flag == 0) {
308                 if (cypress_key_debug) {
309                         printk(KERN_INFO "[TK] %s excute. But do not report (cypress_irq_flag = %d)\n",
310                                 __func__, cypress_irq_flag);
311                 }
312                 return;
313         }
314
315         if (buffer & ESD_STATE_BIT) {
316                 if (cypress_key_debug)
317                         printk(KERN_INFO "[TK] ESD_STATE_BIT setting.(buffer = 0x%x)\n", buffer);
318                 /* release if pressed */
319                 cypress_hardware_reset(client);
320                 /* read and confirm it's good or bad - jk */
321                 return;
322         }
323
324         value = buffer & KEYCODE_VALUE;
325         updown = (buffer & UPDOWN_EVENT) >> 3; /* 0 = press, 1 = release */
326         key = pdata->keycode[value];
327
328         if (updown) { /* release */
329                 pushed = 0;
330                 key = data->last_key;
331         } else { /* press */
332                 pushed = 1;
333                 data->last_key = key;
334         }
335
336         input_report_key(input, key, pushed);
337         input_sync(input);
338
339         cypress_tk_led_onoff_function(1);
340
341         if (cypress_key_debug) {
342                 printk(KERN_INFO "[TK] value:%02x, key:%d, updown:%02x,pushed:%d\n",
343                         value, key, updown, pushed);
344         }
345 }
346
347 static void cypress_tk_irq_worker(struct work_struct *work)
348 {
349         struct cypress_data *data = container_of(work, struct cypress_data, event_work);
350
351         cypress_tk_input_read(data);
352 }
353
354 static irqreturn_t cypress_tk_interrupt(int irq, void *dev_id)
355 {
356         struct cypress_data *data = dev_id;
357
358         if (!work_pending(&data->event_work))
359                 schedule_work(&data->event_work);
360
361         return IRQ_HANDLED;
362 }
363
364 void cypress_tk_on(struct cypress_data *data)
365 {
366
367         cypress_key_onoff = 1;
368
369         s3c_gpio_setpull(data->pdata->pin->gpio_int, S3C_GPIO_PULL_UP);
370
371         s3c_gpio_cfgpin(data->pdata->pin->gpio_sda, S3C_GPIO_SFN(2));
372         s3c_gpio_cfgpin(data->pdata->pin->gpio_scl, S3C_GPIO_SFN(2));
373         s3c_gpio_cfgpin(data->pdata->pin->gpio_int, S3C_GPIO_SFN(0xf));
374         msleep(1);
375
376         data->pdata->power_pin(1);
377 }
378
379 void cypress_tk_off(struct cypress_data *data)
380 {
381
382         cypress_key_onoff = 0;
383
384         s3c_gpio_cfgpin(data->pdata->pin->gpio_sda, S3C_GPIO_OUTPUT);
385         s3c_gpio_cfgpin(data->pdata->pin->gpio_scl, S3C_GPIO_OUTPUT);
386         s3c_gpio_cfgpin(data->pdata->pin->gpio_int, S3C_GPIO_OUTPUT);
387
388         s3c_gpio_setpull(data->pdata->pin->gpio_sda, S3C_GPIO_PULL_NONE);
389         s3c_gpio_setpull(data->pdata->pin->gpio_scl, S3C_GPIO_PULL_NONE);
390         s3c_gpio_setpull(data->pdata->pin->gpio_int, S3C_GPIO_PULL_NONE);
391
392         gpio_direction_output(data->pdata->pin->gpio_sda, 0);
393         gpio_direction_output(data->pdata->pin->gpio_scl, 0);
394         gpio_direction_output(data->pdata->pin->gpio_int, 0);
395         data->pdata->power_pin(0);
396
397 }
398
399 static void cypress_tk_power_up(struct cypress_data *data)
400 {
401         if (data->pdata->power_pin)
402                 data->pdata->power_pin(0);
403
404         /* setting pin */
405         if (data->pdata->cfg_pin)
406                 data->pdata->cfg_pin();
407
408         mdelay(1);
409
410         /* powerup pin */
411         if (data->pdata->power_pin)
412                 data->pdata->power_pin(1);
413
414         if (data->pdata->led_pin)
415                 data->pdata->led_pin(1);
416
417         /* setting state */
418         cypress_key_onoff = 1;
419 }
420
421 static ssize_t cypress_firmware_show(struct device *dev,
422                 struct device_attribute *attr, char *buf)
423 {
424         struct cypress_data *data = dev_get_drvdata(dev);
425         struct i2c_client *client = data->client;
426         u8 buffer[3];
427         int err = 0;
428
429         err = cypress_i2c_read(client, CYPRESS_TK_KEYCODE_REG, buffer, 3);
430         if (err < 0) {
431                 dev_err(&client->dev, "%s: error\n", __func__);
432         } else {
433                 printk(KERN_INFO "[TK] MCS-5080 TK Firmware version = 0x%x, Module version = 0x%x\n",
434                         buffer[CYPRESS_TK_FW_VERSION], buffer[CYPRESS_TK_MD_VERSION]);
435         }
436
437         return 0;
438 }
439
440 void cypress_tk_fw_pin_setting(struct cypress_data *data, int flag)
441 {
442         struct i2c_client *client = data->client;
443
444         struct cypress_platform_data *pdata = data->pdata;
445
446         int gpio_intr = pdata->pin->gpio_int;
447         int gpio_sda = pdata->pin->gpio_sda;
448         int gpio_scl = pdata->pin->gpio_scl;
449
450         if (flag == 1) {
451                 s3c_gpio_cfgpin(gpio_sda, S3C_GPIO_OUTPUT);
452                 s3c_gpio_cfgpin(gpio_scl, S3C_GPIO_OUTPUT);
453                 s3c_gpio_cfgpin(gpio_intr, S3C_GPIO_OUTPUT);
454
455                 s3c_gpio_setpull(gpio_sda, S3C_GPIO_PULL_NONE);
456                 s3c_gpio_setpull(gpio_scl, S3C_GPIO_PULL_NONE);
457                 s3c_gpio_setpull(gpio_intr, S3C_GPIO_PULL_NONE);
458
459                 data->pdata->power_pin(0);
460
461                 gpio_direction_output(gpio_sda, 0);
462                 gpio_direction_output(gpio_scl, 0);
463                 gpio_direction_output(gpio_intr, 0);
464         } else {
465                 s3c_gpio_cfgpin(gpio_sda, S3C_GPIO_OUTPUT);
466                 s3c_gpio_cfgpin(gpio_scl, S3C_GPIO_OUTPUT);
467                 s3c_gpio_cfgpin(gpio_intr, S3C_GPIO_OUTPUT);
468
469                 s3c_gpio_setpull(gpio_sda, S3C_GPIO_PULL_NONE);
470                 s3c_gpio_setpull(gpio_scl, S3C_GPIO_PULL_NONE);
471                 s3c_gpio_setpull(gpio_intr, S3C_GPIO_PULL_NONE);
472
473                 data->pdata->power_pin(0);
474
475                 gpio_direction_output(gpio_sda, 0);
476                 gpio_direction_output(gpio_scl, 0);
477                 gpio_direction_output(gpio_intr, 0);
478
479                 mdelay(200);
480
481                 /* on */
482                 s3c_gpio_setpull(gpio_sda, S3C_GPIO_PULL_UP);
483                 s3c_gpio_setpull(gpio_scl, S3C_GPIO_PULL_UP);
484                 s3c_gpio_setpull(gpio_intr, S3C_GPIO_PULL_UP);
485
486                 s3c_gpio_cfgpin(gpio_sda, S3C_GPIO_SFN(2));
487                 s3c_gpio_cfgpin(gpio_scl, S3C_GPIO_SFN(2));
488                 s3c_gpio_cfgpin(gpio_intr, S3C_GPIO_SFN(0xf));
489                 msleep(1);
490
491                 client->addr = 0x20;
492                 data->pdata->power_pin(1);
493         }
494 }
495
496 static ssize_t cypress_firmware_store(struct device *dev,
497                 struct device_attribute *attr, const char *buf, size_t count)
498 {
499         struct cypress_data *data = dev_get_drvdata(dev);
500         struct i2c_client *client = data->client;
501         int ret = 0;
502
503         unsigned int type;
504
505         sscanf(buf, "%d", &type);
506
507         if (type == 1) {
508                 printk(KERN_INFO "[TK] cypress touch key firmware update start\n");
509                 disable_irq(client->irq);
510                 cypress_key_onoff = 0;
511                 cypress_tk_fw_pin_setting(data, 1);
512
513                 cypress_tk_fw_pin_setting(data, 0);
514                 cypress_key_onoff = 1;
515                 enable_irq(client->irq);
516                 if (ret == 0)
517                         printk(KERN_INFO "[TK] cypress touch key firmware update success\n");
518                 else
519                         printk(KERN_INFO "[TK] cypress touch key firmware update fail(ret = %d)\n", ret);
520         } else {
521                 printk(KERN_INFO "[TK] wrong command\n");
522         }
523         return count;
524 }
525
526 static ssize_t sysfs_cypress_test_show(struct device *dev,
527                 struct device_attribute *attr, char *buf)
528 {
529         printk(KERN_INFO "[TK] cypress_key_onoff = %d\n", cypress_key_onoff);
530         printk(KERN_INFO "[TK] cypress_led_onoff = %d\n", cypress_led_onoff);
531         printk(KERN_INFO "[TK] cypress_key_debug = %d\n", cypress_key_debug);
532         printk(KERN_INFO "[TK] cypress_irq_flag = %d\n", cypress_irq_flag);
533         printk(KERN_INFO "[TK] fw_ver = %d, md_ver = %d\n", cypress_fw_ver, cypress_md_ver);
534         return 0;
535 }
536
537 static ssize_t sysfs_cypress_test(struct device *dev,
538                 struct device_attribute *attr, const char *buf, size_t count)
539 {
540         struct cypress_data *data = dev_get_drvdata(dev);
541         struct i2c_client *client = data->client;
542         unsigned int type;
543
544         sscanf(buf, "%d", &type);
545
546         if (type == 0) { /* touch_key off */
547                 printk(KERN_INFO "[TK] touch key off\n");
548                 local_irq_disable();
549                 data->pdata->power_pin(0);
550                 cypress_key_onoff = 0;
551                 local_irq_enable();
552         } else if (type == 1) { /* touch_key on */
553                 printk(KERN_INFO "[TK] touch key on\n");
554                 local_irq_disable();
555                 data->pdata->power_pin(1);
556                 cypress_key_onoff = 1;
557                 local_irq_enable();
558         } else if (type == 2) { /* key led_off */
559                 printk(KERN_INFO "[TK] key led off\n");
560                 local_irq_disable();
561                 if (cypress_led_onoff == 1) {
562                         cypress_tk_led_off(client);
563                         cypress_led_onoff = 0;
564                 } else
565                         printk(KERN_INFO "[TK] key led already off\n");
566                 local_irq_enable();
567         } else if (type == 3) { /* key led_on */
568                 printk(KERN_INFO "[TK] key led on\n");
569                 local_irq_disable();
570                 if (cypress_led_onoff == 0) {
571                         cypress_tk_led_on(client);
572                         cypress_led_onoff = 1;
573                 } else
574                         printk(KERN_INFO "[TK] key led already on\n");
575                 local_irq_enable();
576         } else if (type == 4) { /* key led_off by workqueue */
577                 printk(KERN_INFO "[TK] key led off\n");
578                 local_irq_disable();
579                 if (cypress_led_onoff == 1) {
580                         cypress_led_onoff = 0;
581                         if (!work_pending(&cypress_led_onoff_work))
582                                 schedule_work(&cypress_led_onoff_work);
583                 } else
584                         printk(KERN_INFO "[TK] key led already off\n");
585                 local_irq_enable();
586         } else if (type == 5) { /* key led_on by workqueue */
587                 printk(KERN_INFO "[TK] key led on\n");
588                 local_irq_disable();
589                 if (cypress_led_onoff == 0) {
590                         cypress_led_onoff = 1;
591                         if (!work_pending(&cypress_led_onoff_work))
592                                 schedule_work(&cypress_led_onoff_work);
593                 } else
594                         printk(KERN_INFO "[TK] key led already on\n");
595                 local_irq_enable();
596         } else if (type == 6) { /* key led_power off */
597                 printk(KERN_INFO "[TK] key led power off\n");
598                 if (data->pdata->led_pin)
599                         data->pdata->led_pin(0);
600         } else if (type == 7) { /* key led_power on */
601                 printk(KERN_INFO "[TK] key led power on\n");
602                 if (data->pdata->led_pin)
603                         data->pdata->led_pin(1);
604         } else {
605                 printk(KERN_INFO "[TSP] sysfs_qt602240_debug wrong command\n");
606         }
607         return count;
608 }
609
610 static ssize_t cypress_debug_store(struct device *dev,
611                 struct device_attribute *attr, const char *buf, size_t count)
612 {
613         unsigned int type;
614
615         sscanf(buf, "%d", &type);
616
617         if (type == 0) {
618                 printk(KERN_INFO "[TK] cypress_key_debug off\n");
619                 cypress_key_debug = 0;
620         } else if (type == 1) {
621                 printk(KERN_INFO "[TK] cypress_key_debug on\n");
622                 cypress_key_debug = 1;
623         }
624         return count;
625 }
626
627 static ssize_t cypress_debug_show(struct device *dev,
628                 struct device_attribute *attr, char *buf)
629 {
630         printk(KERN_INFO "[TK] cypress_key_debug = %d\n", cypress_key_debug);
631
632         return 0;
633 }
634
635 static DEVICE_ATTR(fw_update, 0664, cypress_firmware_show, cypress_firmware_store);
636 static DEVICE_ATTR(test, 0664, sysfs_cypress_test_show, sysfs_cypress_test);
637 static DEVICE_ATTR(debug, 0664, cypress_debug_show, cypress_debug_store);
638
639 static struct attribute *cypress_attrs[] = {
640         &dev_attr_fw_update.attr,
641         &dev_attr_test.attr,
642         &dev_attr_debug.attr,
643         NULL
644 };
645
646 static const struct attribute_group cypress_attr_group = {
647         .attrs = cypress_attrs,
648 };
649
650 static void cypress_tk_enable(struct i2c_client *client)
651 {
652         struct cypress_data *data = i2c_get_clientdata(client);
653
654         if (cypress_key_onoff == 1)
655                 return;
656
657         /* Enable the device first */
658         if (data->pdata->power_pin)
659                 data->pdata->power_pin(1);
660
661         /* Enable irq again */
662         enable_irq(client->irq);
663
664         /* Set touchkey state as enable */
665         cypress_key_onoff = 1;
666
667         /* LED On with power */
668         cypress_touchkey_irq_flag_function(1);
669
670 }
671
672 static void cypress_tk_disable(struct i2c_client *client)
673 {
674         struct cypress_data *data = i2c_get_clientdata(client);
675
676         if (cypress_key_onoff == 0)
677                 return;
678
679         /* LED Off with power */
680         cypress_touchkey_irq_flag_function(0);
681
682         /* Disable irq */
683         disable_irq(client->irq);
684
685         /* Disable the work */
686         cancel_work_sync(&data->event_work);
687         cancel_work_sync(&cypress_led_onoff_work);
688         if (cypress_led_onoff == 1)
689                 del_timer(&cypress_led_off_timer);
690         cypress_led_onoff = 0;
691
692         /* Finally turn off the power */
693         if (data->pdata->power_pin)
694                 data->pdata->power_pin(0);
695
696         /* Set touchkey state as diable */
697         cypress_key_onoff = 0;
698
699 }
700
701 static int cypress_tk_fb_notifier_callback(struct notifier_block *self,
702                 unsigned long event, void *fb_evdata)
703 {
704         struct cypress_data *data = container_of(self, struct cypress_data, fb_notif);
705         struct i2c_client *client = data->client;
706         struct fb_event *evdata = fb_evdata;
707         int blank;
708
709         /* If we aren't interested in this event, skip it immediately ... */
710         if (event != FB_EVENT_BLANK)
711                 return 0;
712
713         blank = *(int *)evdata->data;
714
715         switch (blank) {
716         case 0:
717                 cypress_tk_enable(client);
718                 break;
719         case 4:
720                 cypress_tk_disable(client);
721                 break;
722         default:
723                 break;
724         }
725
726         return 0;
727 }
728
729 static int __devinit cypress_tk_probe(struct i2c_client *client, const struct i2c_device_id *id)
730 {
731         struct cypress_data *data;
732         struct cypress_platform_data *pdata = client->dev.platform_data;
733         struct input_dev *input_dev;
734         int i, ret;
735
736         if (!client->dev.platform_data)
737                 return -EINVAL;
738
739         data = kzalloc(sizeof(struct cypress_data), GFP_KERNEL);
740         global_cypress_data = data;
741
742         input_dev = input_allocate_device();
743         if (!data || !input_dev) {
744                 dev_err(&client->dev, "[TK] Failed to allocate memory\n");
745                 ret = -ENOMEM;
746                 goto err_free_mem;
747         }
748
749         INIT_WORK(&data->event_work, cypress_tk_irq_worker);
750         data->client = client;
751         data->input_dev = input_dev;
752         data->pdata = pdata;
753         data->irq = client->irq;
754         data->type = id->driver_data;
755
756         INIT_WORK(&cypress_led_onoff_work, cypress_led_onoff_worker);
757
758         /* set up input device driver configuration */
759         __set_bit(EV_ABS, input_dev->evbit);
760         __set_bit(EV_KEY, input_dev->evbit);
761         for (i = 0; i < pdata->keycode_size; i++) {
762                 if (pdata->keycode_setbit[i] == 1)
763                         __set_bit(pdata->keycode[i], input_dev->keybit);
764         }
765
766         input_dev->name = "CYPRESS Touchkey"; /* CY8C20236-24LKX1 */
767         input_dev->id.bustype = BUS_I2C;
768         input_dev->dev.parent = &client->dev;
769         input_set_drvdata(input_dev, data);
770
771         /* register IRQ */
772         ret = request_irq(client->irq, cypress_tk_interrupt, IRQF_TRIGGER_FALLING,
773                 "cypress_tk_input", data);
774         if (ret < 0) {
775                 dev_err(&client->dev, "[TK] Failed to register interrupt\n");
776                 goto err_free_mem;
777         }
778
779         /* register input device driver */
780         ret = input_register_device(data->input_dev);
781         if (ret < 0) {
782                 dev_err(&client->dev, "[TK] Failed to input_register_device\n");
783                 goto err_free_irq;
784         }
785         /* set i2c client driver data */
786         i2c_set_clientdata(client, data);
787
788         /* set up physical characteristics */
789         cypress_tk_power_up(data);
790
791         cypress_key_onoff = 1;
792         cypress_tk_disable(client);
793         /* To turn off touchkey when LCD turns off */
794         data->fb_notif.notifier_call = cypress_tk_fb_notifier_callback;
795         fb_register_client(&data->fb_notif);
796
797         init_timer(&cypress_led_off_timer);
798         cypress_led_off_timer.function = cypress_led_off_timer_handler;
799
800         ret = sysfs_create_group(&client->dev.kobj, &cypress_attr_group);
801         if (ret < 0)
802                 printk(KERN_INFO "[TK] make sysfs_create_group error\n");
803
804         cypress_irq_flag = 1;
805 /*
806         mdelay(120);
807
808         ret = cypress_i2c_read(client, CYPRESS_TK_KEYCODE_REG, buffer, 3);
809         if (ret < 0)
810                 dev_err(&client->dev, "%s: error\n", __func__);
811         else {
812                 printk(KERN_INFO "[TK] CYPRESS TK Firmware version = 0x%x, Module version = 0x%x\n",\
813                         buffer[CYPRESS_TK_FW_VERSION], buffer[CYPRESS_TK_MD_VERSION]);
814                 cypress_fw_ver = buffer[CYPRESS_TK_FW_VERSION];
815                 cypress_md_ver = buffer[CYPRESS_TK_MD_VERSION];
816         }
817 */
818
819         return 0;
820
821 err_free_irq:
822         free_irq(client->irq, data);
823 err_free_mem:
824         input_free_device(input_dev);
825         kfree(data);
826         return ret;
827 }
828
829 static int __devexit cypress_tk_remove(struct i2c_client *client)
830 {
831         struct cypress_data *data = i2c_get_clientdata(client);
832
833         free_irq(data->irq, data);
834         cancel_work_sync(&data->event_work);
835
836         input_unregister_device(data->input_dev);
837         kfree(data);
838
839         i2c_set_clientdata(client, NULL);
840
841         return 0;
842 }
843
844 static const struct i2c_device_id cypress_tk_id[] = {
845         { "cypress_tk", 0 },
846         { }
847 };
848 MODULE_DEVICE_TABLE(i2c, cypress_tk_id);
849
850 static struct i2c_driver cypress_tk_driver = {
851         .driver = {
852                 .name = "cypress_tk",
853         },
854         .probe          = cypress_tk_probe,
855         .remove         = __devexit_p(cypress_tk_remove),
856         .id_table       = cypress_tk_id,
857 };
858
859 static int __init cypress_tk_init(void)
860 {
861         return i2c_add_driver(&cypress_tk_driver);
862 }
863
864 static void __exit cypress_tk_exit(void)
865 {
866         i2c_del_driver(&cypress_tk_driver);
867 }
868
869 module_init(cypress_tk_init);
870 module_exit(cypress_tk_exit);
871
872 /* Module information */
873 MODULE_AUTHOR("Samsung Electronics");
874 MODULE_DESCRIPTION("touch key driver for CYPRESS CY8C20236-24LKX1");
875 MODULE_LICENSE("GPL");
876