| OLD | NEW | 
|---|
| (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 | 
| OLD | NEW | 
|---|