Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Side by Side Diff: drivers/input/keyboard/qci_kbd.c

Issue 723001: add keyboard driver in st1.5 (Closed)
Patch Set: error correction Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « drivers/input/keyboard/Makefile ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* Quanta I2C Keyboard Driver
2 *
3 * Copyright (C) 2009 Quanta Computer Inc.
4 * Author: Hsin Wu <hsin.wu@quantatw.com>
5 * Author: Austin Lai <austin.lai@quantatw.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18 /*
19 *
20 * The Driver with I/O communications via the I2C Interface for ON2 of AP BU.
21 * And it is only working on the nuvoTon WPCE775x Embedded Controller.
22 *
23 */
24
25 #include <linux/kernel.h>
26 #include <linux/init.h>
27 #include <linux/module.h>
28 #include <linux/slab.h>
29 #include <linux/jiffies.h>
30 #include <linux/i2c.h>
31 #include <linux/mutex.h>
32 #include <linux/interrupt.h>
33 #include <linux/input.h>
34 #include <linux/keyboard.h>
35 #include <linux/gpio.h>
36 #include <linux/delay.h>
37
38 /* Keyboard special scancode */
39 #define RC_KEY_FN 0x70
40 #define RC_KEY_BREAK 0x80
41 #define KEY_ACK_FA 0xFA
42
43 /* Keyboard keycodes */
44 #define NOKEY KEY_RESERVED
45 #define KEY_LEFTWIN KEY_LEFTMETA
46 #define KEY_RIGHTWIN KEY_RIGHTMETA
47 #define KEY_APPS KEY_COMPOSE
48 #define KEY_PRINTSCR KEY_SYSRQ
49
50 #define KEYBOARD_ID_NAME "qci-i2ckbd"
51 #define KEYBOARD_NAME "Quanta Keyboard"
52 #define KEYBOARD_DEVICE "/i2c/input0"
53 #define KEYBOARD_CMD_ENABLE 0xF4
54
55 /*-----------------------------------------------------------------------------
56 * Keyboard scancode to linux keycode translation table
57 *---------------------------------------------------------------------------*/
58
59 static const unsigned char on2_keycode[256] = {
60 [0] = NOKEY,
61 [1] = NOKEY,
62 [2] = NOKEY,
63 [3] = KEY_5,
64 [4] = KEY_7,
65 [5] = KEY_9,
66 [6] = KEY_MINUS,
67 [7] = NOKEY,
68 [8] = NOKEY,
69 [9] = NOKEY,
70 [10] = NOKEY,
71 [11] = KEY_LEFTBRACE,
72 [12] = KEY_F10,
73 [13] = KEY_INSERT,
74 [14] = KEY_F11,
75 [15] = KEY_ESC,
76 [16] = NOKEY,
77 [17] = NOKEY,
78 [18] = NOKEY,
79 [19] = KEY_4,
80 [20] = KEY_6,
81 [21] = KEY_8,
82 [22] = KEY_0,
83 [23] = KEY_EQUAL,
84 [24] = NOKEY,
85 [25] = NOKEY,
86 [26] = NOKEY,
87 [27] = KEY_P,
88 [28] = KEY_F9,
89 [29] = KEY_DELETE,
90 [30] = KEY_F12,
91 [31] = KEY_GRAVE,
92 [32] = KEY_W,
93 [33] = NOKEY,
94 [34] = NOKEY,
95 [35] = KEY_R,
96 [36] = KEY_T,
97 [37] = KEY_U,
98 [38] = KEY_O,
99 [39] = KEY_RIGHTBRACE,
100 [40] = NOKEY,
101 [41] = NOKEY,
102 [42] = NOKEY,
103 [43] = KEY_APOSTROPHE,
104 [44] = KEY_BACKSPACE,
105 [45] = NOKEY,
106 [46] = KEY_F8,
107 [47] = KEY_F5,
108 [48] = KEY_S,
109 [49] = NOKEY,
110 [50] = NOKEY,
111 [51] = KEY_E,
112 [52] = KEY_H,
113 [53] = KEY_Y,
114 [54] = KEY_I,
115 [55] = KEY_ENTER,
116 [56] = NOKEY,
117 [57] = NOKEY,
118 [58] = NOKEY,
119 [59] = KEY_SEMICOLON,
120 [60] = KEY_3,
121 [61] = KEY_PAGEUP,
122 [62] = KEY_Q,
123 [63] = KEY_TAB,
124 [64] = KEY_A,
125 [65] = NOKEY,
126 [66] = NOKEY,
127 [67] = KEY_F,
128 [68] = KEY_G,
129 [69] = KEY_J,
130 [70] = KEY_L,
131 [71] = NOKEY,
132 [72] = KEY_RIGHTSHIFT,
133 [73] = NOKEY,
134 [74] = NOKEY,
135 [75] = KEY_SLASH,
136 [76] = KEY_2,
137 [77] = KEY_PAGEDOWN,
138 [78] = KEY_F4,
139 [79] = KEY_F1,
140 [80] = KEY_Z,
141 [81] = NOKEY,
142 [82] = NOKEY,
143 [83] = KEY_D,
144 [84] = KEY_V,
145 [85] = KEY_N,
146 [86] = KEY_K,
147 [87] = NOKEY,
148 [88] = KEY_LEFTSHIFT,
149 [89] = KEY_RIGHTCTRL,
150 [90] = NOKEY,
151 [91] = KEY_DOT,
152 [92] = KEY_UP,
153 [93] = KEY_RIGHT,
154 [94] = KEY_F3,
155 [95] = KEY_F2,
156 [96] = NOKEY,
157 [97] = NOKEY,
158 [98] = KEY_RIGHTALT,
159 [99] = KEY_X,
160 [100] = KEY_C,
161 [101] = KEY_B,
162 [102] = KEY_COMMA,
163 [103] = NOKEY,
164 [104] = NOKEY,
165 [105] = NOKEY,
166 [106] = NOKEY,
167 [107] = NOKEY,
168 [108] = KEY_PRINTSCR,
169 [109] = KEY_DOWN,
170 [110] = KEY_1,
171 [111] = KEY_CAPSLOCK,
172 [112] = KEY_F24,
173 [113] = KEY_HOME,
174 [114] = KEY_LEFTALT,
175 [115] = NOKEY,
176 [116] = KEY_SPACE,
177 [117] = KEY_BACKSLASH,
178 [118] = KEY_M,
179 [119] = KEY_COMPOSE,
180 [120] = NOKEY,
181 [121] = KEY_LEFTCTRL,
182 [122] = NOKEY,
183 [123] = NOKEY,
184 [124] = KEY_PAUSE,
185 [125] = KEY_LEFT,
186 [126] = KEY_F7,
187 [127] = KEY_F6,
188 [128] = NOKEY,
189 [129] = NOKEY,
190 [130] = NOKEY,
191 [131] = NOKEY,
192 [132] = NOKEY,
193 [133] = NOKEY,
194 [134] = NOKEY,
195 [135] = NOKEY,
196 [136] = NOKEY,
197 [137] = NOKEY,
198 [138] = NOKEY,
199 [139] = NOKEY,
200 [140] = NOKEY,
201 [141] = NOKEY,
202 [142] = NOKEY,
203 [143] = NOKEY,
204 [144] = NOKEY,
205 [145] = NOKEY,
206 [146] = NOKEY,
207 [147] = NOKEY,
208 [148] = NOKEY,
209 [149] = NOKEY,
210 [150] = NOKEY,
211 [151] = NOKEY,
212 [152] = NOKEY,
213 [153] = NOKEY,
214 [154] = NOKEY,
215 [155] = NOKEY,
216 [156] = NOKEY,
217 [157] = NOKEY,
218 [158] = NOKEY,
219 [159] = NOKEY,
220 [160] = NOKEY,
221 [161] = NOKEY,
222 [162] = NOKEY,
223 [163] = NOKEY,
224 [164] = NOKEY,
225 [165] = NOKEY,
226 [166] = NOKEY,
227 [167] = NOKEY,
228 [168] = NOKEY,
229 [169] = NOKEY,
230 [170] = NOKEY,
231 [171] = NOKEY,
232 [172] = NOKEY,
233 [173] = NOKEY,
234 [174] = NOKEY,
235 [175] = NOKEY,
236 [176] = NOKEY,
237 [177] = NOKEY,
238 [178] = NOKEY,
239 [179] = NOKEY,
240 [180] = NOKEY,
241 [181] = NOKEY,
242 [182] = NOKEY,
243 [183] = NOKEY,
244 [184] = NOKEY,
245 [185] = NOKEY,
246 [186] = NOKEY,
247 [187] = NOKEY,
248 [188] = NOKEY,
249 [189] = KEY_HOME,
250 [190] = NOKEY,
251 [191] = NOKEY,
252 [192] = NOKEY,
253 [193] = NOKEY,
254 [194] = NOKEY,
255 [195] = NOKEY,
256 [196] = NOKEY,
257 [197] = NOKEY,
258 [198] = NOKEY,
259 [199] = NOKEY,
260 [200] = NOKEY,
261 [201] = NOKEY,
262 [202] = NOKEY,
263 [203] = NOKEY,
264 [204] = NOKEY,
265 [205] = KEY_END,
266 [206] = NOKEY,
267 [207] = NOKEY,
268 [208] = NOKEY,
269 [209] = NOKEY,
270 [210] = NOKEY,
271 [211] = NOKEY,
272 [212] = NOKEY,
273 [213] = NOKEY,
274 [214] = NOKEY,
275 [215] = NOKEY,
276 [216] = NOKEY,
277 [217] = NOKEY,
278 [218] = NOKEY,
279 [219] = NOKEY,
280 [220] = KEY_VOLUMEUP,
281 [221] = KEY_BRIGHTNESSUP,
282 [222] = NOKEY,
283 [223] = NOKEY,
284 [224] = NOKEY,
285 [225] = NOKEY,
286 [226] = NOKEY,
287 [227] = NOKEY,
288 [228] = NOKEY,
289 [229] = NOKEY,
290 [230] = NOKEY,
291 [231] = NOKEY,
292 [232] = NOKEY,
293 [233] = NOKEY,
294 [234] = NOKEY,
295 [235] = NOKEY,
296 [236] = NOKEY,
297 [237] = KEY_VOLUMEDOWN,
298 [238] = NOKEY,
299 [239] = NOKEY,
300 [240] = NOKEY,
301 [241] = NOKEY,
302 [242] = NOKEY,
303 [243] = NOKEY,
304 [244] = NOKEY,
305 [245] = NOKEY,
306 [246] = NOKEY,
307 [247] = NOKEY,
308 [248] = NOKEY,
309 [249] = NOKEY,
310 [250] = NOKEY,
311 [251] = NOKEY,
312 [252] = NOKEY,
313 [253] = KEY_BRIGHTNESSDOWN,
314 [254] = NOKEY,
315 [255] = NOKEY,
316 };
317 /*-----------------------------------------------------------------------------
318 * Global variables
319 *---------------------------------------------------------------------------*/
320
321 struct input_dev *g_qci_keyboard_dev;
322
323 /* General structure to hold the driver data */
324 struct i2ckbd_drv_data {
325 struct i2c_client *ki2c_client;
326 struct work_struct work;
327 struct input_dev *qcikbd_dev;
328 unsigned int qcikbd_gpio; /* GPIO used for interrupt */
329 unsigned int qcikbd_irq;
330 unsigned int key_down;
331 unsigned int escape;
332 unsigned int pause_seq;
333 unsigned int fn;
334 };
335 #ifdef CONFIG_PM
336 static int qcikbd_suspend(struct device *dev)
337 {
338 return 0;
339 }
340
341 static int qcikbd_resume(struct device *dev)
342 {
343 return 0;
344 }
345 #endif
346 static int __devinit qcikbd_probe(struct i2c_client *client,
347 const struct i2c_device_id *id);
348 static int __devexit qcikbd_remove(struct i2c_client *kbd);
349
350 static const struct i2c_device_id qcikbd_idtable[] = {
351 { KEYBOARD_ID_NAME, 0 },
352 { }
353 };
354
355 MODULE_DEVICE_TABLE(i2c, qcikbd_idtable);
356
357 #ifdef CONFIG_PM
358 static struct dev_pm_ops qcikbd_pm_ops = {
359 .suspend = qcikbd_suspend,
360 .resume = qcikbd_resume,
361 };
362 #endif
363 static struct i2c_driver i2ckbd_driver = {
364 .driver = {
365 .owner = THIS_MODULE,
366 .name = KEYBOARD_ID_NAME,
367 #ifdef CONFIG_PM
368 .pm = &qcikbd_pm_ops,
369 #endif
370 },
371 .probe = qcikbd_probe,
372 .remove = __devexit_p(qcikbd_remove),
373 .id_table = qcikbd_idtable,
374 };
375
376 /*-----------------------------------------------------------------------------
377 * Driver functions
378 *---------------------------------------------------------------------------*/
379
380 static irqreturn_t qcikbd_interrupt(int irq, void *dev_id)
381 {
382 struct i2ckbd_drv_data *ikbd_drv_data = dev_id;
383 schedule_work(&ikbd_drv_data->work);
384 return IRQ_HANDLED;
385 }
386
387 static void qcikbd_work_handler(struct work_struct *_work)
388 {
389 unsigned char scancode;
390 unsigned int keycode;
391
392 struct i2ckbd_drv_data *ikbd_drv_data =
393 container_of(_work, struct i2ckbd_drv_data, work);
394
395 struct i2c_client *ikbdclient = ikbd_drv_data->ki2c_client;
396 struct input_dev *ikbdev = ikbd_drv_data->qcikbd_dev;
397
398 scancode = i2c_smbus_read_byte(ikbdclient);
399
400 if (scancode == KEY_ACK_FA) {
401 return;
402 } else if (scancode == RC_KEY_FN) {
403 ikbd_drv_data->fn = 0x80; /* select keycode table > 0x7F */
404 } else {
405 ikbd_drv_data->key_down = 1;
406 if (scancode & RC_KEY_BREAK) {
407 ikbd_drv_data->key_down = 0;
408 if ((scancode & 0x7F) == RC_KEY_FN)
409 ikbd_drv_data->fn = 0;
410 }
411 keycode = on2_keycode[(scancode & 0x7F) | ikbd_drv_data->fn];
412 if (keycode != NOKEY) {
413 input_report_key(ikbdev,
414 keycode,
415 ikbd_drv_data->key_down);
416 input_sync(ikbdev);
417 }
418 }
419 }
420
421
422 static int qcikbd_open(struct input_dev *dev)
423 {
424 struct i2ckbd_drv_data *ikbd_drv_data = input_get_drvdata(dev);
425 struct i2c_client *ikbdclient = ikbd_drv_data->ki2c_client;
426
427 /* Send F4h - enable keyboard */
428 i2c_smbus_write_byte(ikbdclient, KEYBOARD_CMD_ENABLE);
429 return 0;
430 }
431
432 static int __devinit qcikbd_probe(struct i2c_client *client,
433 const struct i2c_device_id *id)
434 {
435 int err;
436 int i;
437 struct i2ckbd_drv_data *context;
438 context = kzalloc(sizeof(struct i2ckbd_drv_data), GFP_KERNEL);
439 if (!context)
440 return -ENOMEM;
441 i2c_set_clientdata(client, context);
442 context->ki2c_client = client;
443 context->qcikbd_gpio = client->irq;
444 client->driver = &i2ckbd_driver;
445
446 INIT_WORK(&context->work, qcikbd_work_handler);
447
448 err = gpio_request(context->qcikbd_gpio, "qci-kbd");
449 if (err) {
450 pr_err("[KBD] err gpio request\n");
451 goto gpio_request_fail;
452 }
453
454 context->qcikbd_irq = gpio_to_irq(context->qcikbd_gpio);
455 err = request_irq(context->qcikbd_irq,
456 qcikbd_interrupt,
457 IRQF_TRIGGER_FALLING,
458 KEYBOARD_ID_NAME,
459 context);
460 if (err) {
461 pr_err("[KBD] err unable to get IRQ\n");
462 goto request_irq_fail;
463 }
464
465 context->qcikbd_dev = input_allocate_device();
466 if (!context->qcikbd_dev) {
467 pr_err("[KBD]allocting memory err\n");
468 err = -ENOMEM;
469 goto allocate_fail;
470 }
471
472 context->qcikbd_dev->name = KEYBOARD_NAME;
473 context->qcikbd_dev->phys = KEYBOARD_DEVICE;
474 context->qcikbd_dev->id.bustype = BUS_I2C;
475 context->qcikbd_dev->id.vendor = 0x1050;
476 context->qcikbd_dev->id.product = 0x0006;
477 context->qcikbd_dev->id.version = 0x0004;
478 context->qcikbd_dev->open = qcikbd_open;
479 context->qcikbd_dev->evbit[0] = BIT_MASK(EV_KEY);
480
481 /* Enable all supported keys */
482 for (i = 1; i < ARRAY_SIZE(on2_keycode) ; i++)
483 set_bit(on2_keycode[i], context->qcikbd_dev->keybit);
484
485 set_bit(KEY_POWER, context->qcikbd_dev->keybit);
486 set_bit(KEY_END, context->qcikbd_dev->keybit);
487 set_bit(KEY_VOLUMEUP, context->qcikbd_dev->keybit);
488 set_bit(KEY_VOLUMEDOWN, context->qcikbd_dev->keybit);
489 set_bit(KEY_ZOOMIN, context->qcikbd_dev->keybit);
490 set_bit(KEY_ZOOMOUT, context->qcikbd_dev->keybit);
491
492 input_set_drvdata(context->qcikbd_dev, context);
493 err = input_register_device(context->qcikbd_dev);
494 if (err) {
495 pr_err("[KBD] err input register device\n");
496 goto register_fail;
497 }
498 g_qci_keyboard_dev = context->qcikbd_dev;
499 return 0;
500 register_fail:
501 input_free_device(context->qcikbd_dev);
502
503 allocate_fail:
504 free_irq(context->qcikbd_irq, context);
505
506 request_irq_fail:
507 gpio_free(context->qcikbd_gpio);
508
509 gpio_request_fail:
510 i2c_set_clientdata(client, NULL);
511 kfree(context);
512 return err;
513 }
514
515 static int __devexit qcikbd_remove(struct i2c_client *dev)
516 {
517 struct i2ckbd_drv_data *context = i2c_get_clientdata(dev);
518
519 free_irq(context->qcikbd_irq, context);
520 gpio_free(context->qcikbd_gpio);
521 input_free_device(context->qcikbd_dev);
522 input_unregister_device(context->qcikbd_dev);
523 kfree(context);
524
525 return 0;
526 }
527
528 static int __init qcikbd_init(void)
529 {
530 return i2c_add_driver(&i2ckbd_driver);
531 }
532
533 static void __exit qcikbd_exit(void)
534 {
535 i2c_del_driver(&i2ckbd_driver);
536 }
537
538 struct input_dev *nkbc_keypad_get_input_dev(void)
539 {
540 return g_qci_keyboard_dev;
541 }
542 EXPORT_SYMBOL(nkbc_keypad_get_input_dev);
543 module_init(qcikbd_init);
544 module_exit(qcikbd_exit);
545
546 MODULE_AUTHOR("Quanta Computer Inc.");
547 MODULE_DESCRIPTION("Quanta Embedded Controller I2C Keyboard Driver");
548 MODULE_LICENSE("GPL v2");
549
OLDNEW
« no previous file with comments | « drivers/input/keyboard/Makefile ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698