Commit 3fea6026 authored by Dmitry Torokhov's avatar Dmitry Torokhov

Input: twl40300-keypad - fix handling of "all ground" rows

The Nokia RX51 board code (arch/arm/mach-omap2/board-rx51-peripherals.c)
defines a key map for the matrix keypad keyboard. The hardware seems to
use all of the 8 rows and 8 columns of the keypad, although not all
possible locations are used.

The TWL4030 supports keypads with at most 8 rows and 8 columns. Most keys
are defined with a row and column number between 0 and 7, except

        KEY(0xff, 2, KEY_F9),
        KEY(0xff, 4, KEY_F10),
        KEY(0xff, 5, KEY_F11),

which represent keycodes that should be emitted when entire row is
connected to the ground.  since the driver handles this case as if we
had an extra column in the key matrix. Unfortunately we do not allocate
enough space and end up owerwriting some random memory.
Reported-and-tested-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: stable@kernel.org
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent c25f7b76
...@@ -175,6 +175,10 @@ static void __init rx51_add_gpio_keys(void) ...@@ -175,6 +175,10 @@ static void __init rx51_add_gpio_keys(void)
#endif /* CONFIG_KEYBOARD_GPIO || CONFIG_KEYBOARD_GPIO_MODULE */ #endif /* CONFIG_KEYBOARD_GPIO || CONFIG_KEYBOARD_GPIO_MODULE */
static int board_keymap[] = { static int board_keymap[] = {
/*
* Note that KEY(x, 8, KEY_XXX) entries represent "entrire row
* connected to the ground" matrix state.
*/
KEY(0, 0, KEY_Q), KEY(0, 0, KEY_Q),
KEY(0, 1, KEY_O), KEY(0, 1, KEY_O),
KEY(0, 2, KEY_P), KEY(0, 2, KEY_P),
...@@ -182,6 +186,7 @@ static int board_keymap[] = { ...@@ -182,6 +186,7 @@ static int board_keymap[] = {
KEY(0, 4, KEY_BACKSPACE), KEY(0, 4, KEY_BACKSPACE),
KEY(0, 6, KEY_A), KEY(0, 6, KEY_A),
KEY(0, 7, KEY_S), KEY(0, 7, KEY_S),
KEY(1, 0, KEY_W), KEY(1, 0, KEY_W),
KEY(1, 1, KEY_D), KEY(1, 1, KEY_D),
KEY(1, 2, KEY_F), KEY(1, 2, KEY_F),
...@@ -190,6 +195,7 @@ static int board_keymap[] = { ...@@ -190,6 +195,7 @@ static int board_keymap[] = {
KEY(1, 5, KEY_J), KEY(1, 5, KEY_J),
KEY(1, 6, KEY_K), KEY(1, 6, KEY_K),
KEY(1, 7, KEY_L), KEY(1, 7, KEY_L),
KEY(2, 0, KEY_E), KEY(2, 0, KEY_E),
KEY(2, 1, KEY_DOT), KEY(2, 1, KEY_DOT),
KEY(2, 2, KEY_UP), KEY(2, 2, KEY_UP),
...@@ -197,6 +203,8 @@ static int board_keymap[] = { ...@@ -197,6 +203,8 @@ static int board_keymap[] = {
KEY(2, 5, KEY_Z), KEY(2, 5, KEY_Z),
KEY(2, 6, KEY_X), KEY(2, 6, KEY_X),
KEY(2, 7, KEY_C), KEY(2, 7, KEY_C),
KEY(2, 8, KEY_F9),
KEY(3, 0, KEY_R), KEY(3, 0, KEY_R),
KEY(3, 1, KEY_V), KEY(3, 1, KEY_V),
KEY(3, 2, KEY_B), KEY(3, 2, KEY_B),
...@@ -205,20 +213,23 @@ static int board_keymap[] = { ...@@ -205,20 +213,23 @@ static int board_keymap[] = {
KEY(3, 5, KEY_SPACE), KEY(3, 5, KEY_SPACE),
KEY(3, 6, KEY_SPACE), KEY(3, 6, KEY_SPACE),
KEY(3, 7, KEY_LEFT), KEY(3, 7, KEY_LEFT),
KEY(4, 0, KEY_T), KEY(4, 0, KEY_T),
KEY(4, 1, KEY_DOWN), KEY(4, 1, KEY_DOWN),
KEY(4, 2, KEY_RIGHT), KEY(4, 2, KEY_RIGHT),
KEY(4, 4, KEY_LEFTCTRL), KEY(4, 4, KEY_LEFTCTRL),
KEY(4, 5, KEY_RIGHTALT), KEY(4, 5, KEY_RIGHTALT),
KEY(4, 6, KEY_LEFTSHIFT), KEY(4, 6, KEY_LEFTSHIFT),
KEY(4, 8, KEY_10),
KEY(5, 0, KEY_Y), KEY(5, 0, KEY_Y),
KEY(5, 8, KEY_11),
KEY(6, 0, KEY_U), KEY(6, 0, KEY_U),
KEY(7, 0, KEY_I), KEY(7, 0, KEY_I),
KEY(7, 1, KEY_F7), KEY(7, 1, KEY_F7),
KEY(7, 2, KEY_F8), KEY(7, 2, KEY_F8),
KEY(0xff, 2, KEY_F9),
KEY(0xff, 4, KEY_F10),
KEY(0xff, 5, KEY_F11),
}; };
static struct matrix_keymap_data board_map_data = { static struct matrix_keymap_data board_map_data = {
......
...@@ -51,8 +51,12 @@ ...@@ -51,8 +51,12 @@
*/ */
#define TWL4030_MAX_ROWS 8 /* TWL4030 hard limit */ #define TWL4030_MAX_ROWS 8 /* TWL4030 hard limit */
#define TWL4030_MAX_COLS 8 #define TWL4030_MAX_COLS 8
#define TWL4030_ROW_SHIFT 3 /*
#define TWL4030_KEYMAP_SIZE (TWL4030_MAX_ROWS * TWL4030_MAX_COLS) * Note that we add space for an extra column so that we can handle
* row lines connected to the gnd (see twl4030_col_xlate()).
*/
#define TWL4030_ROW_SHIFT 4
#define TWL4030_KEYMAP_SIZE (TWL4030_MAX_ROWS << TWL4030_ROW_SHIFT)
struct twl4030_keypad { struct twl4030_keypad {
unsigned short keymap[TWL4030_KEYMAP_SIZE]; unsigned short keymap[TWL4030_KEYMAP_SIZE];
...@@ -182,7 +186,7 @@ static int twl4030_read_kp_matrix_state(struct twl4030_keypad *kp, u16 *state) ...@@ -182,7 +186,7 @@ static int twl4030_read_kp_matrix_state(struct twl4030_keypad *kp, u16 *state)
return ret; return ret;
} }
static int twl4030_is_in_ghost_state(struct twl4030_keypad *kp, u16 *key_state) static bool twl4030_is_in_ghost_state(struct twl4030_keypad *kp, u16 *key_state)
{ {
int i; int i;
u16 check = 0; u16 check = 0;
...@@ -191,12 +195,12 @@ static int twl4030_is_in_ghost_state(struct twl4030_keypad *kp, u16 *key_state) ...@@ -191,12 +195,12 @@ static int twl4030_is_in_ghost_state(struct twl4030_keypad *kp, u16 *key_state)
u16 col = key_state[i]; u16 col = key_state[i];
if ((col & check) && hweight16(col) > 1) if ((col & check) && hweight16(col) > 1)
return 1; return true;
check |= col; check |= col;
} }
return 0; return false;
} }
static void twl4030_kp_scan(struct twl4030_keypad *kp, bool release_all) static void twl4030_kp_scan(struct twl4030_keypad *kp, bool release_all)
...@@ -225,7 +229,8 @@ static void twl4030_kp_scan(struct twl4030_keypad *kp, bool release_all) ...@@ -225,7 +229,8 @@ static void twl4030_kp_scan(struct twl4030_keypad *kp, bool release_all)
if (!changed) if (!changed)
continue; continue;
for (col = 0; col < kp->n_cols; col++) { /* Extra column handles "all gnd" rows */
for (col = 0; col < kp->n_cols + 1; col++) {
int code; int code;
if (!(changed & (1 << col))) if (!(changed & (1 << col)))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment