blob: 8c6679994648e6aa04b70bbec59103ff537480f2 [file] [log] [blame]
Gary Kinge550e3f2009-12-11 10:58:20 -08001/*
2 * drivers/input/keyboard/tegra-nvec.c
3 *
4 * Keyboard class input driver for keyboards connected to an NvEc compliant
5 * embedded controller
6 *
7 * Copyright (c) 2009, NVIDIA Corporation.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 */
23
24#include <linux/module.h>
25#include <linux/input.h>
26#include <linux/platform_device.h>
27#include <linux/kthread.h>
Gary King1147a072009-12-15 17:42:32 -080028#include <linux/tegra_devices.h>
Ninad Malwadec1418ca2010-02-03 13:35:28 +053029#include <linux/freezer.h>
Gary Kinge550e3f2009-12-11 10:58:20 -080030
31#include "nvos.h"
32#include "nvec.h"
33#include "nvodm_services.h"
34#include "nvodm_keyboard.h"
35
36#define DRIVER_DESC "NvEc keyboard driver"
37#define DRIVER_LICENSE "GPL"
38
39MODULE_DESCRIPTION(DRIVER_DESC);
40MODULE_LICENSE(DRIVER_LICENSE);
41
42#define NVEC_PAYLOAD 32
43
44/* The total number of scan codes will be (first - last) */
45#define EC_FIRST_CODE 0x00
46#define EC_LAST_CODE 0x58
47#define EC_TOTAL_CODES (EC_LAST_CODE - EC_FIRST_CODE + 1)
48
49/**
50 * @brief This is the actual Scan-code-to-VKey mapping table. For new layouts
51 * this is the only structure which needs to be modified to return the
52 * proper vkey depending on the scan code.
53 */
54NvU8 code_tab_102us[EC_TOTAL_CODES] = {
55 KEY_GRAVE, // 0x00
56 KEY_BACK,
57 KEY_1,
58 KEY_2,
59 KEY_3,
60 KEY_4,
61 KEY_5,
62 KEY_6,
63 KEY_7,
64 KEY_8,
65 KEY_9,
66 KEY_0,
67 KEY_MINUS,
68 KEY_EQUAL,
69 KEY_BACKSPACE,
70 KEY_TAB,
71 KEY_Q, // 0x10
72 KEY_W,
73 KEY_E,
74 KEY_R,
75 KEY_T,
76 KEY_Y,
77 KEY_U,
78 KEY_I,
79 KEY_O,
80 KEY_P,
81 KEY_LEFTBRACE,
82 KEY_RIGHTBRACE,
83 KEY_ENTER,
84 KEY_LEFTCTRL,
85 KEY_A,
86 KEY_S,
87 KEY_D, // 0x20
88 KEY_F,
89 KEY_G,
90 KEY_H,
91 KEY_J,
92 KEY_K,
93 KEY_L,
94 KEY_SEMICOLON,
95 KEY_APOSTROPHE,
96 KEY_GRAVE,
97 KEY_LEFTSHIFT,
98 KEY_BACKSLASH,
99 KEY_Z,
100 KEY_X,
101 KEY_C,
102 KEY_V,
103 KEY_B, // 0x30
104 KEY_N,
105 KEY_M,
106 KEY_COMMA,
107 KEY_DOT,
108 KEY_SLASH,
109 KEY_RIGHTSHIFT,
110 KEY_KPASTERISK,
111 KEY_LEFTALT,
112 KEY_SPACE,
113 KEY_CAPSLOCK,
114 KEY_F1,
115 KEY_F2,
116 KEY_F3,
117 KEY_F4,
118 KEY_F5,
119 KEY_F6, // 0x40
120 KEY_F7,
121 KEY_F8,
122 KEY_F9,
123 KEY_F10,
124 KEY_NUMLOCK,
125 0, //VK_SCROLL
126 KEY_KP7,
127 KEY_KP8,
128 KEY_KP9,
129 KEY_KPMINUS,
130 KEY_KP4,
131 KEY_KP5,
132 KEY_KP6,
133 KEY_KPPLUS,
134 KEY_KP1,
135 KEY_KP2, // 0x50
136 KEY_KP3,
137 KEY_KP0,
Gary King1147a072009-12-15 17:42:32 -0800138 KEY_KPDOT,
Gary Kinge550e3f2009-12-11 10:58:20 -0800139 0, //VK_SNAPSHOT
140 0,
141 0, //VK_OEM_102
142 0, //VK_F11
143 0, //VK_F12
144};
145
146/* The total number of scan codes will be (first - last) */
147#define EC_EXT_CODE_FIRST 0xE010
148#define EC_EXT_CODE_LAST 0xE06D
149#define EC_EXT_TOTAL_CODES (EC_EXT_CODE_LAST - EC_EXT_CODE_FIRST + 1)
150
151/**
152 * @brief This table consists of the scan codes which were added after the
153 * original scan codes were designed.
154 * To avoid moving the already designed buttons to accomodate these
155 * new buttons, the new scan codes are preceded by 'E0'.
156 */
157NvU8 extcode_tab_us102[EC_EXT_TOTAL_CODES] = {
158 0, // 0xE0 0x10
159 0,
160 0,
161 0,
162 0,
163 0,
164 0,
165 0,
166 0,
167 0, //VK_MEDIA_NEXT_TRACK,
168 0,
169 0,
170 0, //VK_RETURN,
171 0, //VK_RCONTROL,
172 0,
173 0,
174 KEY_MUTE, // 0xE0 0x20
175 0, //VK_LAUNCH_APP1
176 0, //VK_MEDIA_PLAY_PAUSE
177 0,
178 0, //VK_MEDIA_STOP
179 0,
180 0,
181 0,
182 0,
183 0,
184 0,
185 0,
186 0,
187 0,
188 KEY_VOLUMEDOWN,
189 0,
190 KEY_VOLUMEUP, // 0xE0 0x30
191 0,
192 0, //VK_BROWSER_HOME
193 0,
194 0,
195 KEY_KPSLASH, //VK_DIVIDE
196 0,
197 0, //VK_SNAPSHOT
198 0, //VK_RMENU
199 0, //VK_OEM_NV_BACKLIGHT_UP
200 0, //VK_OEM_NV_BACKLIGHT_DN
201 0, //VK_OEM_NV_BACKLIGHT_AUTOTOGGLE
202 0, //VK_OEM_NV_POWER_INFO
203 0, //VK_OEM_NV_WIFI_TOGGLE
204 0, //VK_OEM_NV_DISPLAY_SELECT
205 0, //VK_OEM_NV_AIRPLANE_TOGGLE
206 0, //0xE0 0x40
207 0, //VK_OEM_NV_RESERVED
208 0, //VK_OEM_NV_RESERVED
209 0, //VK_OEM_NV_RESERVED
210 0, //VK_OEM_NV_RESERVED
211 0, //VK_OEM_NV_RESERVED
212 KEY_CANCEL,
213 KEY_HOME,
214 KEY_UP,
215 0, //VK_PRIOR
216 0,
217 KEY_LEFT,
218 0,
219 KEY_RIGHT,
220 0,
221 KEY_END,
222 KEY_DOWN, // 0xE0 0x50
223 0, //VK_NEXT
224 KEY_INSERT,
225 KEY_DELETE,
226 0,
227 0,
228 0,
229 0,
230 0,
231 0,
232 0,
233 KEY_MENU, //VK_LWIN
234 0, //VK_RWIN
235 KEY_BACK, //VK_APPS
236 0,
237 0,
238 0, // 0xE0 0x60
239 0,
240 0,
241 0,
242 0,
243 0, //VK_BROWSER_SEARCH
244 0, //VK_BROWSER_FAVORITES
245 0, //VK_BROWSER_REFRESH
246 0, //VK_BROWSER_STOP
247 0, //VK_BROWSER_FORWARD
248 0, //VK_BROWSER_BACK
249 0, //VK_LAUNCH_APP2
250 0, //VK_LAUNCH_MAIL
251 0, //VK_LAUNCH_MEDIA_SELECT
252};
253
254struct nvec_keyboard
255{
256 struct input_dev *input_dev;
257 struct task_struct *task;
258 char name[128];
Ninad Malwadea531df92010-01-28 20:42:39 +0530259 int shutdown;
Gary Kinge550e3f2009-12-11 10:58:20 -0800260 unsigned short keycode[512];
261 NvEcHandle hNvec;
262 NvEcEventRegistrationHandle hEvent;
263};
264
265static struct platform_device *nvec_keyboard_device;
266
267static int nvec_keyboard_recv(void *arg)
268{
269 struct input_dev *input_dev = (struct input_dev *)arg;
270 struct nvec_keyboard *keyboard = input_get_drvdata(input_dev);
271
Ninad Malwadec1418ca2010-02-03 13:35:28 +0530272 /* keyboard event thread should be frozen before suspending the
273 * keyboard and NVEC drivers */
274 set_freezable_with_signal();
275
Ninad Malwadea531df92010-01-28 20:42:39 +0530276 while (!keyboard->shutdown) {
Gary Kinge550e3f2009-12-11 10:58:20 -0800277 unsigned int pressed;
278 NvU32 code;
279 NvU8 flags;
280
281 if (!NvOdmKeyboardGetKeyData(&code, &flags, 0)) {
282 printk(KERN_INFO "nvec_keyboard: unhandled "
283 "scancode %x\n", code);
284 continue;
285 }
286
Ninad Malwadea531df92010-01-28 20:42:39 +0530287 if (keyboard->shutdown)
288 break;
Gary Kinge550e3f2009-12-11 10:58:20 -0800289
290 pressed = (flags & NV_ODM_SCAN_CODE_FLAG_MAKE);
291
292
293 if ((code >= EC_FIRST_CODE) && (code <= EC_LAST_CODE)) {
294 code -= EC_FIRST_CODE;
295 code = code_tab_102us[code];
296 input_report_key(keyboard->input_dev, code, pressed);
297 }
298 else if ((code >= EC_EXT_CODE_FIRST) &&
299 (code <= EC_EXT_CODE_LAST)) {
300
301 code -= EC_EXT_CODE_FIRST;
302 code = extcode_tab_us102[code];
303 input_report_key(keyboard->input_dev, code, pressed);
304 }
305 }
306
307 return 0;
308}
309
310static int nvec_keyboard_open(struct input_dev *dev)
311{
312 return 0;
313}
314
315static void nvec_keyboard_close(struct input_dev *dev)
316{
317 return;
318}
319
Gary Kinge550e3f2009-12-11 10:58:20 -0800320static int __devinit nvec_keyboard_probe(struct platform_device *pdev)
321{
322 int error;
323 NvError nverr;
324 struct nvec_keyboard *keyboard;
325 struct input_dev *input_dev;
326 int i;
327
328 keyboard = kzalloc(sizeof(struct nvec_keyboard), GFP_KERNEL);
329 input_dev = input_allocate_device();
330 if (!keyboard || !input_dev) {
331 error = -ENOMEM;
332 goto fail;
333 }
334
335 keyboard->input_dev = input_dev;
336 input_set_drvdata(input_dev, keyboard);
337 platform_set_drvdata(pdev, input_dev);
338
339 if (!NvOdmKeyboardInit()) {
340 error = -ENODEV;
341 pr_err("tegra_keyboard_probe: no keyboard\n");
342 goto fail_keyboard_init;
343 }
344
345 keyboard->task = kthread_create(nvec_keyboard_recv, input_dev,
346 "nvec_keyboard_thread");
347 if (keyboard->task == NULL) {
348 error = -ENOMEM;
349 goto fail_thread_create;
350 }
351 wake_up_process(keyboard->task);
352
353 if (!strlen(keyboard->name))
354 snprintf(keyboard->name, sizeof(keyboard->name),
355 "nvec keyboard");
356
357 input_dev->name = keyboard->name;
358 input_dev->open = nvec_keyboard_open;
359 input_dev->close = nvec_keyboard_close;
360
361 __set_bit(EV_KEY, input_dev->evbit);
362 for (i=1; i<EC_TOTAL_CODES; i++) {
363 __set_bit(code_tab_102us[i], input_dev->keybit);
364 }
365 for (i=1; i<EC_EXT_TOTAL_CODES; i++) {
366 __set_bit(extcode_tab_us102[i], input_dev->keybit);
367 }
368
Varun Wadekar87826b72010-01-21 20:53:04 +0530369 /* get EC handle */
370 nverr = NvEcOpen(&keyboard->hNvec, 0 /* instance */);
371 if (nverr != NvError_Success) {
372 goto fail_input_register;
373 }
374
Gary Kinge550e3f2009-12-11 10:58:20 -0800375 error = input_register_device(keyboard->input_dev);
376 if (error)
377 goto fail_input_register;
378
379 return 0;
380
381fail_input_register:
382 (void)kthread_stop(keyboard->task);
383fail_thread_create:
384 NvOdmKeyboardDeInit();
385fail_keyboard_init:
386fail:
Varun Wadekar87826b72010-01-21 20:53:04 +0530387 NvEcClose(keyboard->hNvec);
388 keyboard->hNvec = NULL;
Gary Kinge550e3f2009-12-11 10:58:20 -0800389 input_free_device(input_dev);
390 kfree(keyboard);
391
392 return error;
393}
394
395static int __devexit nvec_keyboard_remove(struct platform_device *dev)
396{
397 struct input_dev *input_dev = platform_get_drvdata(dev);
Varun Wadekar87826b72010-01-21 20:53:04 +0530398 struct nvec_keyboard *keyboard = input_get_drvdata(input_dev);
Gary Kinge550e3f2009-12-11 10:58:20 -0800399
400 (void)kthread_stop(keyboard->task);
401 NvOdmKeyboardDeInit();
Varun Wadekar87826b72010-01-21 20:53:04 +0530402 NvEcClose(keyboard->hNvec);
403 keyboard->hNvec = NULL;
Ninad Malwadea531df92010-01-28 20:42:39 +0530404 keyboard->shutdown = 1;
Gary Kinge550e3f2009-12-11 10:58:20 -0800405 input_free_device(input_dev);
406 kfree(keyboard);
407
408 return 0;
409}
410
Varun Wadekar87826b72010-01-21 20:53:04 +0530411static int nvec_keyboard_suspend(struct platform_device *pdev, pm_message_t state)
412{
413 NvEcRequest Request = {0};
414 NvEcResponse Response = {0};
415 struct input_dev *input_dev = platform_get_drvdata(pdev);
416 struct nvec_keyboard *keyboard = input_get_drvdata(input_dev);
417 NvError err = NvError_Success;
418
419 if (!keyboard) {
420 printk("%s: device handle is NULL\n", __func__);
421 return -1;
422 }
423
424 /* disable keyboard scanning */
425 Request.PacketType = NvEcPacketType_Request;
426 Request.RequestType = NvEcRequestResponseType_Keyboard;
427 Request.RequestSubtype =
428 (NvEcRequestResponseSubtype)NvEcKeyboardSubtype_Disable;
429 Request.NumPayloadBytes = 0;
430
431 err = NvEcSendRequest(
432 keyboard->hNvec,
433 &Request,
434 &Response,
435 sizeof(Request),
436 sizeof(Response));
437 if (err != NvError_Success) {
438 printk("%s: scanning disable request send fail\n", __func__);
439 return -1;
440 }
441
442 if (Response.Status != NvEcStatus_Success) {
443 printk("%s: scanning could not be disabled\n", __func__);
444 return -1;
445 }
446
447 /* power down hardware */
448 if (!NvOdmKeyboardPowerHandler(NV_TRUE)) {
449 printk("%s: hardware power down fail\n", __func__);
450 return -1;
451 }
452
453 return 0;
454}
455
456static int nvec_keyboard_resume(struct platform_device *pdev)
457{
458 NvEcRequest Request = {0};
459 NvEcResponse Response = {0};
460 struct input_dev *input_dev = platform_get_drvdata(pdev);
461 struct nvec_keyboard *keyboard = input_get_drvdata(input_dev);
462 NvError err = NvError_Success;
463
464 if (!keyboard) {
465 printk("%s: device handle is NULL\n", __func__);
466 return -1;
467 }
468
469 /* power up hardware */
470 if (!NvOdmKeyboardPowerHandler(NV_FALSE)) {
471 printk("%s: hardware power up fail\n", __func__);
472 return -1;
473 }
474
475 /* re-enable keyboard scanning */
476 Request.PacketType = NvEcPacketType_Request;
477 Request.RequestType = NvEcRequestResponseType_Keyboard;
478 Request.RequestSubtype =
479 (NvEcRequestResponseSubtype)NvEcKeyboardSubtype_Enable;
480 Request.NumPayloadBytes = 0;
481
482 err = NvEcSendRequest(
483 keyboard->hNvec,
484 &Request,
485 &Response,
486 sizeof(Request),
487 sizeof(Response));
488 if (err != NvError_Success) {
489 printk("%s: scanning enable request send fail\n", __func__);
490 return -1;
491 }
492
493 if (Response.Status != NvEcStatus_Success) {
494 printk("%s: scanning could not be enabled\n", __func__);
495 return -1;
496 }
497
498 return 0;
499}
500
Gary Kinge550e3f2009-12-11 10:58:20 -0800501static struct platform_driver nvec_keyboard_driver = {
502 .driver = {
503 .name = "nvec_keyboard",
504 .owner = THIS_MODULE,
505 },
506 .probe = nvec_keyboard_probe,
507 .remove = __devexit_p(nvec_keyboard_remove),
Varun Wadekar87826b72010-01-21 20:53:04 +0530508 .suspend = nvec_keyboard_suspend,
509 .resume = nvec_keyboard_resume,
Gary Kinge550e3f2009-12-11 10:58:20 -0800510};
511
Gary Kinge550e3f2009-12-11 10:58:20 -0800512static int __init nvec_keyboard_init(void)
513{
514 int err;
515
516 err = platform_driver_register(&nvec_keyboard_driver);
517 if (err) {
518 goto error;
519 }
520
521 nvec_keyboard_device = platform_device_alloc("nvec_keyboard", -1);
522 if (!nvec_keyboard_device) {
523 err = -ENOMEM;
524 goto error_unregister_driver;
525 }
526
527 err = platform_device_add(nvec_keyboard_device);
528 if (err)
529 goto error_free_device;
530
531 return 0;
532
533error_free_device:
534 platform_device_put(nvec_keyboard_device);
535error_unregister_driver:
536 platform_driver_unregister(&nvec_keyboard_driver);
537error:
538 return err;
539}
540
541static void __exit nvec_keyboard_exit(void)
542{
543 platform_device_unregister(nvec_keyboard_device);
544 platform_driver_unregister(&nvec_keyboard_driver);
545}
546
547module_init(nvec_keyboard_init);
548module_exit(nvec_keyboard_exit);
549