>From beedbe850eacedbee25e39ff68cf59e42402ba4e Mon Sep 17 00:00:00 2001 From: Jekyll Lai <[email protected]> Date: Tue, 4 Jan 2011 14:15:11 +0800 Subject: [PATCH 3/3] mid_keypad: support multiple keypad matrixes
Add DMI scan to distinguish which keypad will be used. Signed-off-by: Jekyll Lai <[email protected]> --- drivers/input/keyboard/intel_mid_keypad.c | 170 ++++++++++++++++++++++++----- 1 files changed, 142 insertions(+), 28 deletions(-) diff --git a/drivers/input/keyboard/intel_mid_keypad.c b/drivers/input/keyboard/intel_mid_keypad.c index 8886158..48e0755 100644 --- a/drivers/input/keyboard/intel_mid_keypad.c +++ b/drivers/input/keyboard/intel_mid_keypad.c @@ -6,6 +6,7 @@ * Copyright (c) 2009 Intel Corporation. * Created: Sep 18, 2008 * Updated: May 14, 2010 + * Copyright (C) 2010 Jekyll Lai, Wistron <[email protected]> * * Based on pxa27x_keypad.c by Rodolfo Giometti <[email protected]> * pxa27x_keypad.c is based on a previous implementation by Kevin O'Connor @@ -28,7 +29,7 @@ */ #define DRV_NAME "mrst_keypad" -#define DRV_VERSION "0.0.1" +#define DRV_VERSION "1.2" #define MRST_KEYPAD_DRIVER_NAME DRV_NAME " " DRV_VERSION #include <linux/kernel.h> @@ -38,6 +39,7 @@ #include <linux/interrupt.h> #include <linux/input.h> #include <linux/device.h> +#include <linux/dmi.h> #include <linux/err.h> #include <linux/gpio.h> @@ -118,6 +120,51 @@ #define KEY_HALFSHUTTER KEY_PROG1 #define KEY_FULLSHUTTER KEY_CAMERA +#define SHIFT_NEEDED (0x1000) +#define ALTGR_NEEDED (0x2000) + +#define KEY_EXCLAM (KEY_1 + SHIFT_NEEDED) /* '!' -> shift+1 */ +#define KEY_AT (KEY_2 + SHIFT_NEEDED) /* '@' -> shift+2 */ +#define KEY_NUMBER_SIGN (KEY_3 + SHIFT_NEEDED) /* '#' -> shift+3 */ +#define KEY_DOLLAR_SIGN (KEY_4 + SHIFT_NEEDED) /* '$' -> shift+4 */ +#define KEY_PERCENT (KEY_5 + SHIFT_NEEDED) /* '%' -> shift+5 */ +#define KEY_NOR (KEY_6 + SHIFT_NEEDED) /* '^' -> shift+6 */ +#define KEY_AMPERSAND (KEY_7 + SHIFT_NEEDED) /* '&' -> shift+7 */ +#define KEY_PPARENL (KEY_9 + SHIFT_NEEDED) /* '(' -> shift+9 */ +#define KEY_PPARENR (KEY_0 + SHIFT_NEEDED) /* ')' -> shift+0 */ + +#define KEY_UNDERSCORE (KEY_MINUS + SHIFT_NEEDED) /* '_' -> shift+- */ +#define KEY_COLON (KEY_SEMICOLON + SHIFT_NEEDED) /* ':' -> shift+; */ +#define KEY_QUOTE_DBL (KEY_APOSTROPHE + SHIFT_NEEDED) /* '"' -> shift+' */ +#define KEY_TILDE (KEY_GRAVE + SHIFT_NEEDED) /* '~' -> shift+` */ +#define KEY_QUEST_SIGN (KEY_SLASH + SHIFT_NEEDED) /* '?' -> shift+/ */ + +#define KEY_EURO_SIGN (KEY_2 + ALTGR_NEEDED) /* AltGr+2 */ +#define KEY_POUND_SIGN (KEY_3 + ALTGR_NEEDED) /* AltGr+3 */ + +static unsigned int mrst_mm_keycode[MAX_MATRIX_KEY_NUM] = { + KEY_1, KEY_8, KEY_T, KEY_S, KEY_L, KEY_N, 0, KEY_MINUS, + KEY_2, KEY_9, KEY_Y, KEY_D, KEY_BACKSPACE, KEY_M, 0, KEY_RIGHTALT, + KEY_3, KEY_0, KEY_U, KEY_F, KEY_Z, KEY_AT, 0, KEY_RIGHTSHIFT, + KEY_4, KEY_Q, KEY_I, KEY_G, KEY_X, KEY_UNDERSCORE, 0, 0, + KEY_5, KEY_W, KEY_O, KEY_H, KEY_C, KEY_COMMA, 0, 0, + KEY_6, KEY_E, KEY_P, KEY_J, KEY_V, KEY_DOT, 0, 0, + KEY_7, KEY_R, KEY_A, KEY_K, KEY_B, KEY_SPACE, 0, 0, + KEY_LEFTSHIFT, KEY_FN, KEY_ENTER, 0, 0, 0, 0, 0 +}; + +/* Fn key mapping */ +static unsigned int mrst_mm_keycode_fn[MAX_MATRIX_KEY_NUM] = { + KEY_NUMBER_SIGN, KEY_KPASTERISK, 0, 0, KEY_GRAVE, KEY_SEMICOLON, 0, 0, + KEY_EURO_SIGN, KEY_KPPLUS, 0, 0, 0, KEY_COLON, 0, 0, + KEY_POUND_SIGN, KEY_EQUAL, KEY_PPARENL, 0, 0, 0, 0, 0, + KEY_DOLLAR_SIGN, 0, KEY_PPARENR, 0, 0, KEY_KPMINUS, 0, 0, + KEY_PERCENT, 0, KEY_TILDE, 0, 0, KEY_EXCLAM, 0, 0, + KEY_NOR, 0, KEY_SLASH, KEY_APOSTROPHE, 0, KEY_QUEST_SIGN, 0, 0, + KEY_AMPERSAND, 0, 0, KEY_QUOTE_DBL, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + static unsigned int mrst_keycode[MAX_MATRIX_KEY_NUM] = { KEY_F, KEY_D, KEY_E, KEY_GRAVE, KEY_C, KEY_R, KEY_4, KEY_V, KEY_NUMLOCK, KEY_LEFTCTRL, KEY_Z, KEY_W, KEY_2, KEY_X, KEY_S, KEY_3, @@ -218,6 +265,31 @@ struct mrst_keypad { int count; }; +enum keymap_type { + DEFAULT_KEYMAP, + MM_KEYMAP, +}; + +/* To determine different keypad matrix */ +static int keymap_mode; + +static int __init dmi_matched(const struct dmi_system_id *dmi) +{ + keymap_mode = (int)dmi->driver_data; + return 1; +} + +static const struct dmi_system_id __initconst dmi_ids[] = { + { + .callback = dmi_matched, + .matches = { + DMI_MATCH(DMI_BOARD_VERSION, "MM-A2.0-07-1G-4pcs"), + }, + .driver_data = (void *)MM_KEYMAP + }, + { NULL, } +}; + static void mrst_keypad_build_keycode(struct mrst_keypad *keypad) { struct input_dev *input_dev = keypad->input_dev; @@ -226,23 +298,40 @@ static void mrst_keypad_build_keycode(struct mrst_keypad *keypad) keypad->matrix_key_rows = MAX_MATRIX_KEY_ROWS; keypad->matrix_key_cols = MAX_MATRIX_KEY_COLS; - keypad->direct_key_num = MAX_DIRECT_KEY_NUM; keypad->matrix_key_map_size = MAX_MATRIX_KEY_NUM; keypad->debounce_interval = DEBOUNCE_INTERVAL; - /* three sets of keycode here */ - if (keypad->fn) - memcpy(keypad->matrix_keycodes, mrst_keycode_fn, - sizeof(keypad->matrix_keycodes)); - else if (keypad->numlck) - memcpy(keypad->matrix_keycodes, mrst_keycode_numlck, - sizeof(keypad->matrix_keycodes)); - else - memcpy(keypad->matrix_keycodes, mrst_keycode, - sizeof(keypad->matrix_keycodes)); - - memcpy(keypad->direct_key_map, mrst_direct_keycode, - sizeof(keypad->direct_key_map)); + if (keymap_mode == MM_KEYMAP) { + keypad->direct_key_num = 0; + /* three sets of keycode here */ + if (keypad->fn) + memcpy(keypad->matrix_keycodes, mrst_mm_keycode_fn, + sizeof(keypad->matrix_keycodes)); + else + memcpy(keypad->matrix_keycodes, mrst_mm_keycode, + sizeof(keypad->matrix_keycodes)); + } else { + keypad->direct_key_num = MAX_DIRECT_KEY_NUM; + /* three sets of keycode here */ + if (keypad->fn) + memcpy(keypad->matrix_keycodes, mrst_keycode_fn, + sizeof(keypad->matrix_keycodes)); + else if (keypad->numlck) + memcpy(keypad->matrix_keycodes, mrst_keycode_numlck, + sizeof(keypad->matrix_keycodes)); + else + memcpy(keypad->matrix_keycodes, mrst_keycode, + sizeof(keypad->matrix_keycodes)); + + memcpy(keypad->direct_key_map, mrst_direct_keycode, + sizeof(keypad->direct_key_map)); + + key = &keypad->direct_key_map[0]; + for (i = 0; i < keypad->direct_key_num; i++, key++) { + code = (*key) & 0xffffff; + set_bit(code, input_dev->keybit); + } + } key = &keypad->matrix_keycodes[0]; for (i = 0; i < MAX_MATRIX_KEY_NUM; i++, key++) { @@ -250,12 +339,6 @@ static void mrst_keypad_build_keycode(struct mrst_keypad *keypad) set_bit(code, input_dev->keybit); } - key = &keypad->direct_key_map[0]; - for (i = 0; i < keypad->direct_key_num; i++, key++) { - code = (*key) & 0xffffff; - set_bit(code, input_dev->keybit); - } - keypad->enable_rotary0 = 0; keypad->enable_rotary1 = 0; } @@ -266,6 +349,21 @@ static inline unsigned int lookup_matrix_keycode( return keypad->matrix_keycodes[(row << 3) + col]; } +/* translate the non-exist keycode keys */ +static void translate_keycode(struct mrst_keypad *keypad, + unsigned int keycode, int isdown) +{ + if (keycode & SHIFT_NEEDED) { + keycode = keycode & ~(SHIFT_NEEDED); + input_report_key(keypad->input_dev, KEY_RIGHTSHIFT, isdown); + } else if (keycode & ALTGR_NEEDED) { + keycode = keycode & ~(ALTGR_NEEDED); + input_report_key(keypad->input_dev, KEY_RIGHTALT, isdown); + } + + input_report_key(keypad->input_dev, keycode, isdown); +} + static void handle_constant_keypress(struct mrst_keypad *keypad, int num, int col, int row, int state) @@ -294,6 +392,10 @@ static void handle_constant_keypress(struct mrst_keypad *keypad, case 1: /* if Fn pressed */ + if (keymap_mode == MM_KEYMAP) { + if (col == 1 && row == 7) + keypad->fn = 1; + } else { if (col == 6 && row == 6) keypad->fn = 1; /* key '[' */ @@ -320,6 +422,7 @@ static void handle_constant_keypress(struct mrst_keypad *keypad, set_bit(KEY_DOT, dev->key); dev->repeat_key = KEY_DOT; } + } return; default: @@ -332,7 +435,8 @@ static void mrst_keypad_scan_matrix(struct mrst_keypad *keypad) int row, col, num_keys_pressed = 0; uint32_t new_state[MAX_MATRIX_KEY_COLS]; uint32_t kpas = keypad_readl(KPAS); - int status; + int status, isdown; + unsigned int keycode; num_keys_pressed = KPAS_MUKP(kpas); @@ -382,6 +486,10 @@ static void mrst_keypad_scan_matrix(struct mrst_keypad *keypad) new_state[6] = kpasmkp3 & KPASMKP_MKC_MASK; new_state[7] = (kpasmkp3 >> 16) & KPASMKP_MKC_MASK; + if (keymap_mode == MM_KEYMAP) { + if (new_state[1] & 0x80) + keypad->fn = 1; + } else { /* if Fn is pressed, all SHIFT is ignored, except when { * or } is pressed */ if (new_state[6] & 0x40) { @@ -404,8 +512,7 @@ static void mrst_keypad_scan_matrix(struct mrst_keypad *keypad) new_state[6] &= ~0x40; } } - - + } scan: /* re-build keycode */ mrst_keypad_build_keycode(keypad); @@ -421,9 +528,14 @@ scan: if ((bits_changed & (1 << row)) == 0) continue; - input_report_key(keypad->input_dev, - lookup_matrix_keycode(keypad, row, col), - new_state[col] & (1 << row)); + keycode = lookup_matrix_keycode(keypad, row, col); + isdown = new_state[col] & (1 << row); + + if (keymap_mode == MM_KEYMAP) + translate_keycode(keypad, keycode, isdown); + else + input_report_key(keypad->input_dev, keycode, + isdown); } } input_sync(keypad->input_dev); @@ -546,7 +658,6 @@ static void mrst_keypad_set_alt_func(void) iounmap(mem); } - static int mrst_keypad_gpio_init(struct mrst_keypad *keypad) { int i, err, cnt = 0; @@ -695,6 +806,9 @@ static int __devinit mrst_keypad_probe(struct pci_dev *pdev, goto failed_free_io; } + keymap_mode = DEFAULT_KEYMAP; + dmi_check_system(dmi_ids); + input_dev->name = pci_name(pdev); input_dev->id.bustype = BUS_PCI; input_dev->open = mrst_keypad_open; -- 1.7.0.4 _______________________________________________ MeeGo-kernel mailing list [email protected] http://lists.meego.com/listinfo/meego-kernel
