upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / input / keyboard / mcs_touchkey.c
1 /*
2  * mcs_touchkey.c - Touchkey driver for MELFAS MCS5000/5080 controller
3  *
4  * Copyright (C) 2010 Samsung Electronics Co.Ltd
5  * Author: HeungJun Kim <riverful.kim@samsung.com>
6  * Author: Joonyoung Shim <jy0922.shim@samsung.com>
7  *
8  * This program is free software; you can redistribute  it and/or modify it
9  * under  the terms of  the GNU General  Public License as published by the
10  * Free Software Foundation;  either version 2 of the  License, or (at your
11  * option) any later version.
12  */
13
14 #include <linux/module.h>
15 #include <linux/init.h>
16 #include <linux/i2c.h>
17 #include <linux/i2c/mcs.h>
18 #include <linux/interrupt.h>
19 #include <linux/input.h>
20 #include <linux/irq.h>
21 #include <linux/slab.h>
22 #include <linux/workqueue.h>
23 #include <linux/delay.h>
24 #include <linux/gpio.h>
25 #include <linux/pm_runtime.h>
26 #include <linux/fb.h>
27 #include <plat/gpio-cfg.h>
28
29 /* MCS5000 Touchkey */
30 #define MCS5000_TOUCHKEY_STATUS         0x04
31 #define MCS5000_TOUCHKEY_STATUS_PRESS   7
32 #define MCS5000_TOUCHKEY_FW             0x0a
33 #define MCS5000_TOUCHKEY_BASE_VAL       0x61
34
35 /* MCS5080 Touchkey */
36 #define MCS5080_TOUCHKEY_STATUS         0x00
37 #define MCS5080_TOUCHKEY_STATUS_PRESS   3
38 #define MCS5080_TOUCHKEY_FW             0x01
39 #define MCS5080_TOUCHKEY_BASE_VAL       0x1
40
41 #define PRESS_LED_TIME                  500
42 #define WAKEUP_LED_TIME                 5000
43
44 enum mcs_touchkey_type {
45         MCS5000_TOUCHKEY,
46         MCS5080_TOUCHKEY,
47 };
48
49 struct mcs_touchkey_chip {
50         unsigned int status_reg;
51         unsigned int pressbit;
52         unsigned int press_invert;
53         unsigned int baseval;
54 };
55
56 struct mcs_touchkey_data {
57         struct i2c_client *client;
58         struct input_dev *input_dev;
59         struct mcs_touchkey_chip chip;
60         struct delayed_work work;
61         void (*poweron)(bool);
62         void (*cfg_pin_fw)(int);
63         unsigned int touchkey_enable;
64         unsigned int key_code;
65         unsigned int key_val;
66
67         /* The framebuffer notifier block */
68         struct notifier_block fb_notif;
69
70         unsigned short keycodes[];
71 };
72
73 static void mcs_touchkey_led(struct mcs_touchkey_data *data, int on)
74 {
75         unsigned char buf;
76
77         if (!data->touchkey_enable)
78                 return;
79
80         if (on)
81                 buf = 0x1;
82         else
83                 buf = 0x2;
84         i2c_master_send(data->client, &buf, 1);
85 }
86
87 static void mcs_touchkey_work(struct work_struct *work)
88 {
89         struct delayed_work *dw = to_delayed_work(work);
90         struct mcs_touchkey_data *data;
91
92         data = container_of(dw, struct mcs_touchkey_data, work);
93
94         mcs_touchkey_led(data, 0);
95 }
96
97 static irqreturn_t mcs_touchkey_interrupt(int irq, void *dev_id)
98 {
99         struct mcs_touchkey_data *data = dev_id;
100         struct mcs_touchkey_chip *chip = &data->chip;
101         struct i2c_client *client = data->client;
102         struct input_dev *input = data->input_dev;
103         unsigned int key_val;
104         unsigned int pressed;
105         int val;
106
107         val = i2c_smbus_read_byte_data(client, chip->status_reg);
108         if (val < 0) {
109                 dev_err(&client->dev, "i2c read error [%d]\n", val);
110                 return IRQ_HANDLED;
111         }
112
113         pressed = (val & (1 << chip->pressbit)) >> chip->pressbit;
114         if (chip->press_invert)
115                 pressed ^= chip->press_invert;
116
117         /* key_val is 0 when released, so we should use key_val of press. */
118         if (pressed) {
119                 key_val = val & (0xff >> (8 - chip->pressbit));
120                 if (!key_val)
121                         return IRQ_HANDLED;
122                 key_val -= chip->baseval;
123                 data->key_code = data->keycodes[key_val];
124                 data->key_val = key_val;
125         }
126
127         input_event(input, EV_MSC, MSC_SCAN, data->key_val);
128         input_report_key(input, data->key_code, pressed);
129         input_sync(input);
130
131         if (pressed) {
132                 cancel_work_sync(&data->work.work);
133                 mcs_touchkey_led(data, 1);
134         } else {
135                 if (!delayed_work_pending(&data->work))
136                         schedule_delayed_work(&data->work,
137                                         msecs_to_jiffies(PRESS_LED_TIME));
138         }
139
140         dev_dbg(&client->dev, "key %d %d %s\n", data->key_val, data->key_code,
141                 pressed ? "pressed" : "released");
142
143         return IRQ_HANDLED;
144 }
145
146 static u8 mcs_i2c_read(struct i2c_client *client, u8 cmd, u8 *rval, int size)
147 {
148         struct i2c_msg msg[2];
149         int ret, wret;
150
151         msg[0].addr = client->addr;
152         msg[0].flags = client->flags | I2C_M_RD;
153         msg[0].len = size;
154         msg[0].buf = (char *)rval;
155
156         wret = 1;
157
158         ret = i2c_transfer(client->adapter, msg, wret);
159         if (ret != wret)
160                 dev_err(&client->dev, "failed i2c transfer ret %d, "
161                                 "cmd %02x, rval %02x\n", ret, cmd, *rval);
162         return ret;
163 }
164
165 static int mcs_fw_update(struct mcs_touchkey_data *data, const char *fn)
166 {
167         struct i2c_client *client = data->client;
168         int ret = 0;
169
170         dev_info(&client->dev, "[TK] firmware file : %s\n", fn);
171
172         /* set mode FW download */
173         disable_irq(client->irq);
174         data->cfg_pin_fw(1);
175         ret = mcsdl_download_binary_data();
176         if (ret < 0)
177                 dev_info(&client->dev, "[TK] failed to update.\n");
178         else
179                 dev_info(&client->dev, "[TK] succeeded to update.\n");
180         data->cfg_pin_fw(0);
181
182         /* set mode touchkey mode */
183         enable_irq(client->irq);
184         client->addr = 0x20;
185         data->poweron(0);
186         mdelay(100);
187         data->poweron(1);
188
189         return ret;
190 }
191
192 static ssize_t mcs_firmware_store(struct device *dev,
193                 struct device_attribute *attr, const char *buf, size_t count)
194 {
195         struct mcs_touchkey_data *data = dev_get_drvdata(dev);
196         struct i2c_client *client = data->client;
197         int ret = 0;
198
199         unsigned int type;
200
201         sscanf(buf, "%d", &type);
202
203         if (type == 1) {
204                 dev_info(&client->dev, "[TK] firmware update\n");
205
206                 /* set mode FW download */
207                 disable_irq(client->irq);
208                 data->cfg_pin_fw(1);
209                 ret = mcsdl_download_binary_data();
210                 if (ret < 0)
211                         dev_info(&client->dev, "[TK] failed to update.\n");
212                 else
213                         dev_info(&client->dev, "[TK] succeeded to update.\n");
214                 data->cfg_pin_fw(0);
215
216                 /* set mode touchkey mode */
217                 enable_irq(client->irq);
218                 client->addr = 0x20;
219                 data->poweron(0);
220                 mdelay(100);
221                 data->poweron(1);
222
223         } else if (type == 2) {
224                 ret = mcs_fw_update(data, "MTH-KESSLER-R01_V82.bin");
225                 if (ret < 0)
226                         dev_info(&client->dev, "[TK] failed to update.\n");
227                 else
228                         dev_info(&client->dev, "[TK] succeeded to update.\n");
229
230         } else {
231                 dev_info(&client->dev, "[TK] wrong command\n");
232         }
233
234         return count;
235 }
236
237 static ssize_t mcs_firmware_show(struct device *dev,
238                 struct device_attribute *attr, char *buf)
239 {
240         struct mcs_touchkey_data *data = dev_get_drvdata(dev);
241         struct i2c_client *client = data->client;
242         u8 buffer[3];
243         int err = 0;
244
245         err = mcs_i2c_read(client, MCS5080_TOUCHKEY_STATUS, buffer, 3);
246         if (err < 0) {
247                 dev_err(&client->dev, "%s: error\n", __func__);
248         } else
249                 dev_info(&client->dev, "[TK] firmware version = 0x%x, "
250                                 "Module version = 0x%x\n",
251                 buffer[1], buffer[2]);
252         return 0;
253 }
254
255 static DEVICE_ATTR(fw_update, 0664, mcs_firmware_show, mcs_firmware_store);
256
257 static struct attribute *mcs_attrs[] = {
258         &dev_attr_fw_update.attr,
259         NULL
260 };
261
262 static const struct attribute_group mcs_attr_group = {
263         .attrs = mcs_attrs,
264 };
265
266 static void mcs_touchkey_enable(struct mcs_touchkey_data *data)
267 {
268         struct i2c_client *client = data->client;
269
270         if (data->touchkey_enable == 1)
271                 return;
272
273         /* Enable the device first */
274         if (data->poweron)
275                 data->poweron(1);
276
277         /* Enable irq again */
278         enable_irq(client->irq);
279
280         if (!delayed_work_pending(&data->work))
281                 schedule_delayed_work(&data->work,
282                                 msecs_to_jiffies(WAKEUP_LED_TIME));
283
284         /* Set touchkey state as enable */
285         data->touchkey_enable = 1;
286 }
287
288 static void mcs_touchkey_disable(struct mcs_touchkey_data *data)
289 {
290         struct i2c_client *client = data->client;
291
292         if (data->touchkey_enable == 0)
293                 return;
294
295         /* Turn off LED */
296         mcs_touchkey_led(data, 0);
297
298         /* Disable the work */
299         disable_irq(client->irq);
300         cancel_delayed_work_sync(&data->work);
301
302         /* Finally turn off the power */
303         if (data->poweron)
304                 data->poweron(0);
305
306         /* Set touchkey state as disable */
307         data->touchkey_enable = 0;
308 }
309
310 static int mcs_touchkey_fb_notifier_callback(struct notifier_block *self,
311                 unsigned long event, void *fb_evdata)
312 {
313         struct mcs_touchkey_data *data;
314         struct fb_event *evdata = fb_evdata;
315         int blank;
316
317         /* If we aren't interested in this event, skip it immediately ... */
318         if (event != FB_EVENT_BLANK)
319                 return 0;
320
321         data = container_of(self, struct mcs_touchkey_data, fb_notif);
322         blank = *(int *)evdata->data;
323
324         switch (blank) {
325         case 0:
326                 mcs_touchkey_enable(data);
327                 break;
328         case 4:
329                 mcs_touchkey_disable(data);
330                 break;
331         default:
332                 break;
333         }
334
335         return 0;
336 }
337
338 static int __devinit mcs_touchkey_probe(struct i2c_client *client,
339                 const struct i2c_device_id *id)
340 {
341         const struct mcs_platform_data *pdata;
342         struct mcs_touchkey_data *data;
343         struct input_dev *input_dev;
344         struct device *dev = &client->dev;
345         unsigned int fw_reg;
346 #if 0
347         int fw_ver;
348 #endif
349         int error;
350         int i;
351         u8 buffer[3];
352
353         pdata = client->dev.platform_data;
354         if (!pdata) {
355                 dev_err(&client->dev, "no platform data defined\n");
356                 return -EINVAL;
357         }
358
359         data = kzalloc(sizeof(struct mcs_touchkey_data) +
360                         sizeof(data->keycodes[0]) * (pdata->key_maxval + 1),
361                         GFP_KERNEL);
362         input_dev = input_allocate_device();
363         if (!data || !input_dev) {
364                 dev_err(dev, "Failed to allocate memory\n");
365                 error = -ENOMEM;
366                 goto err_free_mem;
367         }
368
369         data->client = client;
370         data->input_dev = input_dev;
371
372         data->poweron = pdata->poweron;
373         data->cfg_pin_fw = pdata->cfg_pin_fw;
374
375         if (data->poweron)
376                 data->poweron(1);
377
378         if (id->driver_data == MCS5000_TOUCHKEY) {
379                 data->chip.status_reg = MCS5000_TOUCHKEY_STATUS;
380                 data->chip.pressbit = MCS5000_TOUCHKEY_STATUS_PRESS;
381                 data->chip.baseval = MCS5000_TOUCHKEY_BASE_VAL;
382                 fw_reg = MCS5000_TOUCHKEY_FW;
383         } else {
384                 data->chip.status_reg = MCS5080_TOUCHKEY_STATUS;
385                 data->chip.pressbit = MCS5080_TOUCHKEY_STATUS_PRESS;
386                 data->chip.press_invert = 1;
387                 data->chip.baseval = MCS5080_TOUCHKEY_BASE_VAL;
388                 fw_reg = MCS5080_TOUCHKEY_FW;
389         }
390 #if 0
391         fw_ver = i2c_smbus_read_byte_data(client, fw_reg);
392         if (fw_ver < 0) {
393                 error = fw_ver;
394                 dev_err(dev, "i2c read error[%d]\n", error);
395                 goto err_free_mem;
396         }
397         dev_info(dev, "Firmware version: %d\n", fw_ver);
398 #endif
399         input_dev->name = "MELFAS MCS Touchkey";
400         input_dev->id.bustype = BUS_I2C;
401         input_dev->dev.parent = &client->dev;
402         input_dev->evbit[0] = BIT_MASK(EV_KEY);
403         if (!pdata->no_autorepeat)
404                 input_dev->evbit[0] |= BIT_MASK(EV_REP);
405         input_dev->keycode = data->keycodes;
406         input_dev->keycodesize = sizeof(data->keycodes[0]);
407         input_dev->keycodemax = pdata->key_maxval + 1;
408
409         for (i = 0; i < pdata->keymap_size; i++) {
410                 unsigned int val = MCS_KEY_VAL(pdata->keymap[i]);
411                 unsigned int code = MCS_KEY_CODE(pdata->keymap[i]);
412
413                 data->keycodes[val] = code;
414                 __set_bit(code, input_dev->keybit);
415         }
416
417         input_set_capability(input_dev, EV_MSC, MSC_SCAN);
418         input_set_drvdata(input_dev, data);
419
420         INIT_DELAYED_WORK(&data->work, mcs_touchkey_work);
421
422         error = input_register_device(input_dev);
423         if (error)
424                 goto err_free_irq;
425
426         i2c_set_clientdata(client, data);
427
428         error = sysfs_create_group(&client->dev.kobj, &mcs_attr_group);
429         if (error < 0)
430                 dev_err(dev, "[TK] make sysfs_create_group error\n");
431
432         /* After all, set the firmware setting */
433         error = mcsdl_set_i2c_client(client);
434         if (error)
435                 goto out;
436         if (id->driver_data != MCS5080_TOUCHKEY)
437                 goto out;
438
439         error = mcs_i2c_read(client, MCS5080_TOUCHKEY_STATUS, buffer, 3);
440         if (error < 0) {
441                 dev_err(dev, "%s: error\n", __func__);
442                 goto out;
443         }
444         dev_info(dev, "[TK] FW ver = 0x%x, " "MD(Module) ver = 0x%x\n",
445                 buffer[1], buffer[2]);
446
447         error = request_threaded_irq(client->irq, NULL, mcs_touchkey_interrupt,
448                         IRQF_TRIGGER_FALLING, client->dev.driver->name, data);
449         if (error) {
450                 dev_err(dev, "Failed to register interrupt\n");
451                 goto err_free_mem;
452         }
453
454         data->touchkey_enable = 1;
455         mcs_touchkey_disable(data);
456         /* To turn off touchkey when LCD turns off */
457         data->fb_notif.notifier_call = mcs_touchkey_fb_notifier_callback;
458         fb_register_client(&data->fb_notif);
459
460 /* TODO: Touchkey power change from GPIO to PMIC */
461 /*
462         if ((buffer[2] != pdata->md_ver) || ((buffer[2] == pdata->md_ver) &&
463             (buffer[1] < pdata->fw_ver))) {
464                 dev_info(dev, "[TK] FW auto update!\n");
465                 dev_info(dev, "[TK] MTH-KESSLER-R%x_V%x.bin ->"
466                                 "MTH-KESSLER-R%x_V%x.bin\n",
467                         buffer[2], buffer[1], pdata->md_ver, pdata->fw_ver);
468                 error = mcs_fw_update(data, "MTH-KESSLER-R01_V02.bin");
469                 if (error < 0)
470                         dev_info(dev, "[TK] failed to FW update.\n");
471                 else
472                         dev_info(dev, "[TK] succeeded to FW update.\n");
473         }
474 */
475 out:
476         /* enable runtime pm */
477         pm_runtime_set_active(dev);
478
479         return 0;
480
481 err_free_irq:
482         free_irq(client->irq, data);
483 err_free_mem:
484         input_free_device(input_dev);
485         kfree(data);
486         return error;
487 }
488
489 static int __devexit mcs_touchkey_remove(struct i2c_client *client)
490 {
491         struct mcs_touchkey_data *data = i2c_get_clientdata(client);
492
493         free_irq(client->irq, data);
494         input_unregister_device(data->input_dev);
495         kfree(data);
496
497         return 0;
498 }
499
500 static void mcs_touchkey_shutdown(struct i2c_client *client)
501 {
502         struct mcs_touchkey_data *data = i2c_get_clientdata(client);
503
504         if (data->poweron)
505                 data->poweron(0);
506 }
507
508 static const struct i2c_device_id mcs_touchkey_id[] = {
509         { "mcs5000_touchkey", MCS5000_TOUCHKEY },
510         { "mcs5080_touchkey", MCS5080_TOUCHKEY },
511         { }
512 };
513 MODULE_DEVICE_TABLE(i2c, mcs_touchkey_id);
514
515 static struct i2c_driver mcs_touchkey_driver = {
516         .driver = {
517                 .name   = "mcs_touchkey",
518                 .owner  = THIS_MODULE,
519         },
520         .probe          = mcs_touchkey_probe,
521         .remove         = __devexit_p(mcs_touchkey_remove),
522         .shutdown       = mcs_touchkey_shutdown,
523         .id_table       = mcs_touchkey_id,
524 };
525
526 static int __init mcs_touchkey_init(void)
527 {
528         return i2c_add_driver(&mcs_touchkey_driver);
529 }
530
531 static void __exit mcs_touchkey_exit(void)
532 {
533         i2c_del_driver(&mcs_touchkey_driver);
534 }
535
536 module_init(mcs_touchkey_init);
537 module_exit(mcs_touchkey_exit);
538
539 /* Module information */
540 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
541 MODULE_AUTHOR("HeungJun Kim <riverful.kim@samsung.com>");
542 MODULE_DESCRIPTION("Touchkey driver for MELFAS MCS5000/5080 controller");
543 MODULE_LICENSE("GPL");