123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722 |
- /* Quanta I2C Keyboard Driver
- *
- * Copyright (C) 2009 Quanta Computer Inc.
- * Copyright (c) 2010, The Linux Foundation. All rights reserved.
- * Author: Hsin Wu <hsin.wu@quantatw.com>
- * Author: Austin Lai <austin.lai@quantatw.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
- /*
- *
- * The Driver with I/O communications via the I2C Interface for ON2 of AP BU.
- * And it is only working on the nuvoTon WPCE775x Embedded Controller.
- *
- */
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/slab.h>
- #include <linux/jiffies.h>
- #include <linux/i2c.h>
- #include <linux/mutex.h>
- #include <linux/interrupt.h>
- #include <linux/input.h>
- #include <linux/keyboard.h>
- #include <linux/gpio.h>
- #include <linux/delay.h>
- #include <linux/input/qci_kbd.h>
- /* Keyboard special scancode */
- #define RC_KEY_FN 0x70
- #define RC_KEY_BREAK 0x80
- #define KEY_ACK_FA 0xFA
- #define SCAN_EMUL0 0xE0
- #define SCAN_EMUL1 0xE1
- #define SCAN_PAUSE1 0x1D
- #define SCAN_PAUSE2 0x45
- #define SCAN_LIDSW_OPEN 0x70
- #define SCAN_LIDSW_CLOSE 0x71
- /* Keyboard keycodes */
- #define NOKEY KEY_RESERVED
- #define KEY_LEFTWIN KEY_LEFTMETA
- #define KEY_RIGHTWIN KEY_RIGHTMETA
- #define KEY_APPS KEY_COMPOSE
- #define KEY_PRINTSCR KEY_SYSRQ
- #define KEYBOARD_ID_NAME "qci-i2ckbd"
- #define KEYBOARD_NAME "Quanta Keyboard"
- #define KEYBOARD_DEVICE "/i2c/input0"
- #define KEYBOARD_CMD_ENABLE 0xF4
- #define KEYBOARD_CMD_SET_LED 0xED
- /*-----------------------------------------------------------------------------
- * Keyboard scancode to linux keycode translation table
- *---------------------------------------------------------------------------*/
- static const unsigned char on2_keycode[256] = {
- [0] = NOKEY,
- [1] = NOKEY,
- [2] = NOKEY,
- [3] = KEY_5,
- [4] = KEY_7,
- [5] = KEY_9,
- [6] = KEY_MINUS,
- [7] = NOKEY,
- [8] = NOKEY,
- [9] = NOKEY,
- [10] = NOKEY,
- [11] = KEY_LEFTBRACE,
- [12] = KEY_F10,
- [13] = KEY_INSERT,
- [14] = KEY_F11,
- [15] = KEY_ESC,
- [16] = NOKEY,
- [17] = NOKEY,
- [18] = NOKEY,
- [19] = KEY_4,
- [20] = KEY_6,
- [21] = KEY_8,
- [22] = KEY_0,
- [23] = KEY_EQUAL,
- [24] = NOKEY,
- [25] = NOKEY,
- [26] = NOKEY,
- [27] = KEY_P,
- [28] = KEY_F9,
- [29] = KEY_DELETE,
- [30] = KEY_F12,
- [31] = KEY_GRAVE,
- [32] = KEY_W,
- [33] = NOKEY,
- [34] = NOKEY,
- [35] = KEY_R,
- [36] = KEY_T,
- [37] = KEY_U,
- [38] = KEY_O,
- [39] = KEY_RIGHTBRACE,
- [40] = NOKEY,
- [41] = NOKEY,
- [42] = NOKEY,
- [43] = KEY_APOSTROPHE,
- [44] = KEY_BACKSPACE,
- [45] = NOKEY,
- [46] = KEY_F8,
- [47] = KEY_F5,
- [48] = KEY_S,
- [49] = NOKEY,
- [50] = NOKEY,
- [51] = KEY_E,
- [52] = KEY_H,
- [53] = KEY_Y,
- [54] = KEY_I,
- [55] = KEY_ENTER,
- [56] = NOKEY,
- [57] = NOKEY,
- [58] = NOKEY,
- [59] = KEY_SEMICOLON,
- [60] = KEY_3,
- [61] = KEY_PAGEUP,
- [62] = KEY_Q,
- [63] = KEY_TAB,
- [64] = KEY_A,
- [65] = NOKEY,
- [66] = NOKEY,
- [67] = KEY_F,
- [68] = KEY_G,
- [69] = KEY_J,
- [70] = KEY_L,
- [71] = NOKEY,
- [72] = KEY_RIGHTSHIFT,
- [73] = NOKEY,
- [74] = NOKEY,
- [75] = KEY_SLASH,
- [76] = KEY_2,
- [77] = KEY_PAGEDOWN,
- [78] = KEY_F4,
- [79] = KEY_F1,
- [80] = KEY_Z,
- [81] = NOKEY,
- [82] = NOKEY,
- [83] = KEY_D,
- [84] = KEY_V,
- [85] = KEY_N,
- [86] = KEY_K,
- [87] = NOKEY,
- [88] = KEY_LEFTSHIFT,
- [89] = KEY_RIGHTCTRL,
- [90] = NOKEY,
- [91] = KEY_DOT,
- [92] = KEY_UP,
- [93] = KEY_RIGHT,
- [94] = KEY_F3,
- [95] = KEY_F2,
- [96] = NOKEY,
- [97] = NOKEY,
- [98] = KEY_RIGHTALT,
- [99] = KEY_X,
- [100] = KEY_C,
- [101] = KEY_B,
- [102] = KEY_COMMA,
- [103] = NOKEY,
- [104] = NOKEY,
- [105] = NOKEY,
- [106] = NOKEY,
- [107] = NOKEY,
- [108] = KEY_PRINTSCR,
- [109] = KEY_DOWN,
- [110] = KEY_1,
- [111] = KEY_CAPSLOCK,
- [112] = KEY_F24,
- [113] = KEY_HOME,
- [114] = KEY_LEFTALT,
- [115] = NOKEY,
- [116] = KEY_SPACE,
- [117] = KEY_BACKSLASH,
- [118] = KEY_M,
- [119] = KEY_COMPOSE,
- [120] = NOKEY,
- [121] = KEY_LEFTCTRL,
- [122] = NOKEY,
- [123] = NOKEY,
- [124] = KEY_PAUSE,
- [125] = KEY_LEFT,
- [126] = KEY_F7,
- [127] = KEY_F6,
- [128] = NOKEY,
- [129] = NOKEY,
- [130] = NOKEY,
- [131] = NOKEY,
- [132] = NOKEY,
- [133] = NOKEY,
- [134] = NOKEY,
- [135] = NOKEY,
- [136] = NOKEY,
- [137] = NOKEY,
- [138] = NOKEY,
- [139] = NOKEY,
- [140] = NOKEY,
- [141] = NOKEY,
- [142] = NOKEY,
- [143] = NOKEY,
- [144] = NOKEY,
- [145] = NOKEY,
- [146] = NOKEY,
- [147] = NOKEY,
- [148] = NOKEY,
- [149] = NOKEY,
- [150] = NOKEY,
- [151] = NOKEY,
- [152] = NOKEY,
- [153] = NOKEY,
- [154] = NOKEY,
- [155] = NOKEY,
- [156] = NOKEY,
- [157] = NOKEY,
- [158] = NOKEY,
- [159] = NOKEY,
- [160] = NOKEY,
- [161] = NOKEY,
- [162] = NOKEY,
- [163] = NOKEY,
- [164] = NOKEY,
- [165] = NOKEY,
- [166] = NOKEY,
- [167] = NOKEY,
- [168] = NOKEY,
- [169] = NOKEY,
- [170] = NOKEY,
- [171] = NOKEY,
- [172] = NOKEY,
- [173] = NOKEY,
- [174] = NOKEY,
- [175] = NOKEY,
- [176] = NOKEY,
- [177] = NOKEY,
- [178] = NOKEY,
- [179] = NOKEY,
- [180] = NOKEY,
- [181] = NOKEY,
- [182] = NOKEY,
- [183] = NOKEY,
- [184] = NOKEY,
- [185] = NOKEY,
- [186] = NOKEY,
- [187] = NOKEY,
- [188] = NOKEY,
- [189] = KEY_HOME,
- [190] = NOKEY,
- [191] = NOKEY,
- [192] = NOKEY,
- [193] = NOKEY,
- [194] = NOKEY,
- [195] = NOKEY,
- [196] = NOKEY,
- [197] = NOKEY,
- [198] = NOKEY,
- [199] = NOKEY,
- [200] = NOKEY,
- [201] = NOKEY,
- [202] = NOKEY,
- [203] = NOKEY,
- [204] = NOKEY,
- [205] = KEY_END,
- [206] = NOKEY,
- [207] = NOKEY,
- [208] = NOKEY,
- [209] = NOKEY,
- [210] = NOKEY,
- [211] = NOKEY,
- [212] = NOKEY,
- [213] = NOKEY,
- [214] = NOKEY,
- [215] = NOKEY,
- [216] = NOKEY,
- [217] = NOKEY,
- [218] = NOKEY,
- [219] = NOKEY,
- [220] = KEY_VOLUMEUP,
- [221] = KEY_BRIGHTNESSUP,
- [222] = NOKEY,
- [223] = NOKEY,
- [224] = NOKEY,
- [225] = NOKEY,
- [226] = NOKEY,
- [227] = NOKEY,
- [228] = NOKEY,
- [229] = NOKEY,
- [230] = NOKEY,
- [231] = NOKEY,
- [232] = NOKEY,
- [233] = NOKEY,
- [234] = NOKEY,
- [235] = NOKEY,
- [236] = NOKEY,
- [237] = KEY_VOLUMEDOWN,
- [238] = NOKEY,
- [239] = NOKEY,
- [240] = NOKEY,
- [241] = NOKEY,
- [242] = NOKEY,
- [243] = NOKEY,
- [244] = NOKEY,
- [245] = NOKEY,
- [246] = NOKEY,
- [247] = NOKEY,
- [248] = NOKEY,
- [249] = NOKEY,
- [250] = NOKEY,
- [251] = NOKEY,
- [252] = NOKEY,
- [253] = KEY_BRIGHTNESSDOWN,
- [254] = NOKEY,
- [255] = NOKEY,
- };
- static const u8 emul0_map[128] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 97, 0, 0,
- 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 0,
- 115, 0, 0, 0, 0, 98, 0, 99, 100, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 102, 103, 104, 0, 105, 0, 106, 0, 107,
- 108, 109, 110, 111, 0, 0, 0, 0, 0, 0, 0, 139, 0, 150, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- };
- /*-----------------------------------------------------------------------------
- * Global variables
- *---------------------------------------------------------------------------*/
- struct input_dev *g_qci_keyboard_dev;
- /* General structure to hold the driver data */
- struct i2ckbd_drv_data {
- struct i2c_client *ki2c_client;
- struct work_struct work;
- struct input_dev *qcikbd_dev;
- struct mutex kb_mutex;
- unsigned int qcikbd_gpio; /* GPIO used for interrupt */
- unsigned int qcikbd_irq;
- unsigned int key_down;
- unsigned int escape;
- unsigned int pause_seq;
- unsigned int fn;
- unsigned char led_status;
- bool standard_scancodes;
- bool kb_leds;
- bool event_led;
- bool emul0;
- bool emul1;
- bool pause1;
- };
- #ifdef CONFIG_PM
- static int qcikbd_suspend(struct device *dev)
- {
- struct i2ckbd_drv_data *context = input_get_drvdata(g_qci_keyboard_dev);
- enable_irq_wake(context->qcikbd_irq);
- return 0;
- }
- static int qcikbd_resume(struct device *dev)
- {
- struct i2ckbd_drv_data *context = input_get_drvdata(g_qci_keyboard_dev);
- struct i2c_client *ikbdclient = context->ki2c_client;
- disable_irq_wake(context->qcikbd_irq);
- /* consume any keypress generated while suspended */
- i2c_smbus_read_byte(ikbdclient);
- return 0;
- }
- #endif
- static int __devinit qcikbd_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
- static int __devexit qcikbd_remove(struct i2c_client *kbd);
- static const struct i2c_device_id qcikbd_idtable[] = {
- { KEYBOARD_ID_NAME, 0 },
- { }
- };
- MODULE_DEVICE_TABLE(i2c, qcikbd_idtable);
- #ifdef CONFIG_PM
- static struct dev_pm_ops qcikbd_pm_ops = {
- .suspend = qcikbd_suspend,
- .resume = qcikbd_resume,
- };
- #endif
- static struct i2c_driver i2ckbd_driver = {
- .driver = {
- .owner = THIS_MODULE,
- .name = KEYBOARD_ID_NAME,
- #ifdef CONFIG_PM
- .pm = &qcikbd_pm_ops,
- #endif
- },
- .probe = qcikbd_probe,
- .remove = __devexit_p(qcikbd_remove),
- .id_table = qcikbd_idtable,
- };
- /*-----------------------------------------------------------------------------
- * Driver functions
- *---------------------------------------------------------------------------*/
- #ifdef CONFIG_KEYBOARD_QCIKBD_LID
- static void process_lid(struct input_dev *ikbdev, unsigned char scancode)
- {
- if (scancode == SCAN_LIDSW_OPEN)
- input_report_switch(ikbdev, SW_LID, 0);
- else if (scancode == SCAN_LIDSW_CLOSE)
- input_report_switch(ikbdev, SW_LID, 1);
- else
- return;
- input_sync(ikbdev);
- }
- #endif
- static irqreturn_t qcikbd_interrupt(int irq, void *dev_id)
- {
- struct i2ckbd_drv_data *ikbd_drv_data = dev_id;
- schedule_work(&ikbd_drv_data->work);
- return IRQ_HANDLED;
- }
- static void qcikbd_work_handler(struct work_struct *_work)
- {
- unsigned char scancode;
- unsigned char scancode_only;
- unsigned int keycode;
- struct i2ckbd_drv_data *ikbd_drv_data =
- container_of(_work, struct i2ckbd_drv_data, work);
- struct i2c_client *ikbdclient = ikbd_drv_data->ki2c_client;
- struct input_dev *ikbdev = ikbd_drv_data->qcikbd_dev;
- mutex_lock(&ikbd_drv_data->kb_mutex);
- if ((ikbd_drv_data->kb_leds) && (ikbd_drv_data->event_led)) {
- i2c_smbus_write_byte(ikbdclient, KEYBOARD_CMD_SET_LED);
- i2c_smbus_write_byte(ikbdclient, ikbd_drv_data->led_status);
- ikbd_drv_data->event_led = 0;
- goto work_exit;
- }
- scancode = i2c_smbus_read_byte(ikbdclient);
- if (scancode == KEY_ACK_FA)
- goto work_exit;
- if (ikbd_drv_data->standard_scancodes) {
- /* pause key is E1 1D 45 */
- if (scancode == SCAN_EMUL1) {
- ikbd_drv_data->emul1 = 1;
- goto work_exit;
- }
- if (ikbd_drv_data->emul1) {
- ikbd_drv_data->emul1 = 0;
- if ((scancode & 0x7f) == SCAN_PAUSE1)
- ikbd_drv_data->pause1 = 1;
- goto work_exit;
- }
- if (ikbd_drv_data->pause1) {
- ikbd_drv_data->pause1 = 0;
- if ((scancode & 0x7f) == SCAN_PAUSE2) {
- input_report_key(ikbdev, KEY_PAUSE,
- !(scancode & 0x80));
- input_sync(ikbdev);
- }
- goto work_exit;
- }
- if (scancode == SCAN_EMUL0) {
- ikbd_drv_data->emul0 = 1;
- goto work_exit;
- }
- if (ikbd_drv_data->emul0) {
- ikbd_drv_data->emul0 = 0;
- scancode_only = scancode & 0x7f;
- #ifdef CONFIG_KEYBOARD_QCIKBD_LID
- if ((scancode_only == SCAN_LIDSW_OPEN) ||
- (scancode_only == SCAN_LIDSW_CLOSE)) {
- process_lid(ikbdev, scancode);
- goto work_exit;
- }
- #endif
- keycode = emul0_map[scancode_only];
- if (!keycode) {
- dev_err(&ikbdev->dev,
- "Unrecognized scancode %02x %02x\n",
- SCAN_EMUL0, scancode);
- goto work_exit;
- }
- } else {
- keycode = scancode & 0x7f;
- }
- /* MS bit of scancode indicates direction of keypress */
- ikbd_drv_data->key_down = !(scancode & 0x80);
- if (keycode) {
- input_event(ikbdev, EV_MSC, MSC_SCAN, scancode);
- input_report_key(ikbdev, keycode,
- ikbd_drv_data->key_down);
- input_sync(ikbdev);
- }
- goto work_exit;
- }
- mutex_unlock(&ikbd_drv_data->kb_mutex);
- if (scancode == RC_KEY_FN) {
- ikbd_drv_data->fn = 0x80; /* select keycode table > 0x7F */
- } else {
- ikbd_drv_data->key_down = 1;
- if (scancode & RC_KEY_BREAK) {
- ikbd_drv_data->key_down = 0;
- if ((scancode & 0x7F) == RC_KEY_FN)
- ikbd_drv_data->fn = 0;
- }
- keycode = on2_keycode[(scancode & 0x7F) | ikbd_drv_data->fn];
- if (keycode != NOKEY) {
- input_report_key(ikbdev,
- keycode,
- ikbd_drv_data->key_down);
- input_sync(ikbdev);
- }
- }
- return;
- work_exit:
- mutex_unlock(&ikbd_drv_data->kb_mutex);
- }
- static int qcikbd_input_event(struct input_dev *dev, unsigned int type,
- unsigned int code, int value)
- {
- struct i2ckbd_drv_data *ikbd_drv_data = input_get_drvdata(dev);
- struct input_dev *ikbdev = ikbd_drv_data->qcikbd_dev;
- if (type != EV_LED)
- return -EINVAL;
- ikbd_drv_data->led_status =
- (test_bit(LED_SCROLLL, ikbdev->led) ? 1 : 0) |
- (test_bit(LED_NUML, ikbdev->led) ? 2 : 0) |
- (test_bit(LED_CAPSL, ikbdev->led) ? 4 : 0);
- ikbd_drv_data->event_led = 1;
- schedule_work(&ikbd_drv_data->work);
- return 0;
- }
- static int qcikbd_open(struct input_dev *dev)
- {
- struct i2ckbd_drv_data *ikbd_drv_data = input_get_drvdata(dev);
- struct i2c_client *ikbdclient = ikbd_drv_data->ki2c_client;
- /* Send F4h - enable keyboard */
- i2c_smbus_write_byte(ikbdclient, KEYBOARD_CMD_ENABLE);
- return 0;
- }
- static int __devinit qcikbd_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
- {
- int err;
- int i;
- struct i2ckbd_drv_data *context;
- struct qci_kbd_platform_data *pdata = client->dev.platform_data;
- if (!pdata) {
- pr_err("[KBD] platform data not supplied\n");
- return -EINVAL;
- }
- context = kzalloc(sizeof(struct i2ckbd_drv_data), GFP_KERNEL);
- if (!context)
- return -ENOMEM;
- i2c_set_clientdata(client, context);
- context->ki2c_client = client;
- context->qcikbd_gpio = client->irq;
- client->driver = &i2ckbd_driver;
- INIT_WORK(&context->work, qcikbd_work_handler);
- mutex_init(&context->kb_mutex);
- err = gpio_request(context->qcikbd_gpio, "qci-kbd");
- if (err) {
- pr_err("[KBD] err gpio request\n");
- goto gpio_request_fail;
- }
- context->qcikbd_irq = gpio_to_irq(context->qcikbd_gpio);
- err = request_irq(context->qcikbd_irq,
- qcikbd_interrupt,
- IRQF_TRIGGER_FALLING,
- KEYBOARD_ID_NAME,
- context);
- if (err) {
- pr_err("[KBD] err unable to get IRQ\n");
- goto request_irq_fail;
- }
- context->standard_scancodes = pdata->standard_scancodes;
- context->kb_leds = pdata->kb_leds;
- context->qcikbd_dev = input_allocate_device();
- if (!context->qcikbd_dev) {
- pr_err("[KBD]allocting memory err\n");
- err = -ENOMEM;
- goto allocate_fail;
- }
- context->qcikbd_dev->name = KEYBOARD_NAME;
- context->qcikbd_dev->phys = KEYBOARD_DEVICE;
- context->qcikbd_dev->id.bustype = BUS_I2C;
- context->qcikbd_dev->id.vendor = 0x1050;
- context->qcikbd_dev->id.product = 0x0006;
- context->qcikbd_dev->id.version = 0x0004;
- context->qcikbd_dev->open = qcikbd_open;
- set_bit(EV_KEY, context->qcikbd_dev->evbit);
- __set_bit(MSC_SCAN, context->qcikbd_dev->mscbit);
- if (pdata->repeat)
- set_bit(EV_REP, context->qcikbd_dev->evbit);
- /* Enable all supported keys */
- for (i = 1; i < ARRAY_SIZE(on2_keycode) ; i++)
- set_bit(on2_keycode[i], context->qcikbd_dev->keybit);
- set_bit(KEY_POWER, context->qcikbd_dev->keybit);
- set_bit(KEY_END, context->qcikbd_dev->keybit);
- set_bit(KEY_VOLUMEUP, context->qcikbd_dev->keybit);
- set_bit(KEY_VOLUMEDOWN, context->qcikbd_dev->keybit);
- set_bit(KEY_ZOOMIN, context->qcikbd_dev->keybit);
- set_bit(KEY_ZOOMOUT, context->qcikbd_dev->keybit);
- #ifdef CONFIG_KEYBOARD_QCIKBD_LID
- set_bit(EV_SW, context->qcikbd_dev->evbit);
- set_bit(SW_LID, context->qcikbd_dev->swbit);
- #endif
- if (context->kb_leds) {
- context->qcikbd_dev->event = qcikbd_input_event;
- __set_bit(EV_LED, context->qcikbd_dev->evbit);
- __set_bit(LED_NUML, context->qcikbd_dev->ledbit);
- __set_bit(LED_CAPSL, context->qcikbd_dev->ledbit);
- __set_bit(LED_SCROLLL, context->qcikbd_dev->ledbit);
- }
- input_set_drvdata(context->qcikbd_dev, context);
- err = input_register_device(context->qcikbd_dev);
- if (err) {
- pr_err("[KBD] err input register device\n");
- goto register_fail;
- }
- g_qci_keyboard_dev = context->qcikbd_dev;
- return 0;
- register_fail:
- input_free_device(context->qcikbd_dev);
- allocate_fail:
- free_irq(context->qcikbd_irq, context);
- request_irq_fail:
- gpio_free(context->qcikbd_gpio);
- gpio_request_fail:
- i2c_set_clientdata(client, NULL);
- kfree(context);
- return err;
- }
- static int __devexit qcikbd_remove(struct i2c_client *dev)
- {
- struct i2ckbd_drv_data *context = i2c_get_clientdata(dev);
- free_irq(context->qcikbd_irq, context);
- gpio_free(context->qcikbd_gpio);
- input_free_device(context->qcikbd_dev);
- input_unregister_device(context->qcikbd_dev);
- kfree(context);
- return 0;
- }
- static int __init qcikbd_init(void)
- {
- return i2c_add_driver(&i2ckbd_driver);
- }
- static void __exit qcikbd_exit(void)
- {
- i2c_del_driver(&i2ckbd_driver);
- }
- struct input_dev *nkbc_keypad_get_input_dev(void)
- {
- return g_qci_keyboard_dev;
- }
- EXPORT_SYMBOL(nkbc_keypad_get_input_dev);
- module_init(qcikbd_init);
- module_exit(qcikbd_exit);
- MODULE_AUTHOR("Quanta Computer Inc.");
- MODULE_DESCRIPTION("Quanta Embedded Controller I2C Keyboard Driver");
- MODULE_LICENSE("GPL v2");
|