--- /dev/null
+From fc359f9dd7efd346c070950320dda62ae671519f Mon Sep 17 00:00:00 2001
+From: Grazvydas Ignotas <notasas@gmail.com>
+Date: Thu, 5 Nov 2009 12:52:23 +0200
+Subject: [PATCH 7/7] some hackish Fn handling for testing
+
+---
+ arch/arm/mach-omap2/board-omap3pandora-input.c | 47 ++++++++++++++++++++++++
+ drivers/input/keyboard/twl4030_keypad.c | 39 +++++++++++++++++---
+ 2 files changed, 81 insertions(+), 5 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3pandora-input.c b/arch/arm/mach-omap2/board-omap3pandora-input.c
+index ce9df0e..3d530cf 100644
+--- a/arch/arm/mach-omap2/board-omap3pandora-input.c
++++ b/arch/arm/mach-omap2/board-omap3pandora-input.c
+@@ -31,6 +31,9 @@
+ /* hardware debounce, (value + 1) * 31us */
+ #define GPIO_DEBOUNCE_TIME 0x7f
+
++/* HACK: this requires patched twl4030_keypad driver */
++#define FNKEY(row, col, code) KEY((row + 8), col, code)
++
+ static int omap3pandora_keymap[] = {
+ /* row, col, code */
+ KEY(0, 0, KEY_9),
+@@ -76,6 +79,50 @@ static int omap3pandora_keymap[] = {
+ KEY(7, 2, KEY_Q),
+ KEY(7, 3, KEY_LEFTSHIFT),
+ KEY(7, 4, KEY_COMMA),
++ /* Fn keys */
++ FNKEY(0, 0, KEY_F9),
++ FNKEY(0, 1, KEY_F8),
++ FNKEY(0, 2, KEY_BRIGHTNESSUP),
++ FNKEY(0, 3, KEY_F13), /* apostrophe, differs from Fn-A? */
++ FNKEY(0, 4, KEY_DOLLAR),
++ FNKEY(0, 5, KEY_EURO),
++ FNKEY(1, 0, KEY_F10),
++ FNKEY(1, 1, KEY_F7),
++ FNKEY(1, 2, KEY_BRIGHTNESSDOWN),
++ FNKEY(1, 3, KEY_GRAVE),
++ FNKEY(1, 4, KEY_F14), /* pipe/bar */
++ FNKEY(1, 5, KEY_TAB),
++ FNKEY(2, 0, KEY_INSERT),
++ FNKEY(2, 1, KEY_F6),
++ FNKEY(2, 2, KEY_F15), /* dash */
++ FNKEY(2, 3, KEY_EQUAL),
++ FNKEY(2, 4, KEY_F16), /* # (pound/hash) */
++ FNKEY(2, 5, KEY_FN),
++ FNKEY(3, 0, KEY_F11),
++ FNKEY(3, 1, KEY_F5),
++ FNKEY(3, 2, KEY_F17), /* ! */
++ FNKEY(3, 3, KEY_KPPLUS),
++ FNKEY(3, 4, KEY_BACKSLASH),
++ FNKEY(4, 0, KEY_F12),
++ FNKEY(4, 1, KEY_F4),
++ FNKEY(4, 2, KEY_RIGHTBRACE),
++ FNKEY(4, 3, KEY_KPMINUS),
++ FNKEY(4, 4, KEY_QUESTION),
++ FNKEY(5, 0, KEY_F18), /* £ (pound) */
++ FNKEY(5, 1, KEY_F3),
++ FNKEY(5, 2, KEY_LEFTBRACE),
++ FNKEY(5, 3, KEY_F19), /* " */
++ FNKEY(5, 4, KEY_SLASH),
++ FNKEY(6, 0, KEY_YEN),
++ FNKEY(6, 1, KEY_F2),
++ FNKEY(6, 2, KEY_F20), /* @ */
++ FNKEY(6, 3, KEY_APOSTROPHE),
++ FNKEY(6, 4, KEY_F21), /* : */
++ FNKEY(7, 0, KEY_ENTER),
++ FNKEY(7, 1, KEY_F1),
++ FNKEY(7, 2, KEY_ESC),
++ FNKEY(7, 3, KEY_CAPSLOCK),
++ FNKEY(7, 4, KEY_SEMICOLON),
+ };
+
+ static struct matrix_keymap_data board_map_data = {
+diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c
+index 99bb58d..74485d6 100644
+--- a/drivers/input/keyboard/twl4030_keypad.c
++++ b/drivers/input/keyboard/twl4030_keypad.c
+@@ -52,7 +52,7 @@
+ #define TWL4030_MAX_ROWS 8 /* TWL4030 hard limit */
+ #define TWL4030_MAX_COLS 8
+ #define TWL4030_ROW_SHIFT 3
+-#define TWL4030_KEYMAP_SIZE (TWL4030_MAX_ROWS * TWL4030_MAX_COLS)
++#define TWL4030_KEYMAP_SIZE (TWL4030_MAX_ROWS * 2 * TWL4030_MAX_COLS)
+
+ struct twl4030_keypad {
+ unsigned short keymap[TWL4030_KEYMAP_SIZE];
+@@ -61,6 +61,9 @@ struct twl4030_keypad {
+ unsigned n_cols;
+ unsigned irq;
+
++ unsigned fn_down:1;
++ unsigned fn_sticked:1;
++
+ struct device *dbg_dev;
+ struct input_dev *input;
+ };
+@@ -226,7 +229,8 @@ static void twl4030_kp_scan(struct twl4030_keypad *kp, bool release_all)
+ continue;
+
+ for (col = 0; col < kp->n_cols; col++) {
+- int code;
++ int code, kcode, is_down;
++ int code2;
+
+ if (!(changed & (1 << col)))
+ continue;
+@@ -236,9 +240,34 @@ static void twl4030_kp_scan(struct twl4030_keypad *kp, bool release_all)
+ "press" : "release");
+
+ code = MATRIX_SCAN_CODE(row, col, TWL4030_ROW_SHIFT);
++ kcode = kp->keymap[code];
++ is_down = (new_state[row] & (1 << col)) ? 1 : 0;
++
++ dev_dbg(kp->dbg_dev, "code: %d %d\n", code, kcode);
++ /* Fn handling */
++ if (kcode == KEY_FN) {
++ kp->fn_down = is_down;
++ kp->fn_sticked |= is_down;
++ } else if (kp->fn_down || kp->fn_sticked) {
++ /* make sure other function is up */
++ input_event(input, EV_MSC, MSC_SCAN, code);
++ input_report_key(input, kcode, 0);
++
++ code = MATRIX_SCAN_CODE(row + TWL4030_MAX_ROWS,
++ col, TWL4030_ROW_SHIFT);
++ kcode = kp->keymap[code];
++
++ kp->fn_sticked = 0;
++ } else {
++ code2 = MATRIX_SCAN_CODE(row + TWL4030_MAX_ROWS,
++ col, TWL4030_ROW_SHIFT);
++ input_event(input, EV_MSC, MSC_SCAN, code2);
++ input_report_key(input, kp->keymap[code2], 0);
++ }
++
++ dev_dbg(kp->dbg_dev, "code(fn): %d %d\n", code, kcode);
+ input_event(input, EV_MSC, MSC_SCAN, code);
+- input_report_key(input, kp->keymap[code],
+- new_state[row] & (1 << col));
++ input_report_key(input, kcode, is_down);
+ }
+ kp->kp_state[row] = new_state[row];
+ }
+@@ -371,7 +400,7 @@ static int __devinit twl4030_kp_probe(struct platform_device *pdev)
+
+ input_set_capability(input, EV_MSC, MSC_SCAN);
+
+- input->name = "TWL4030 Keypad";
++ input->name = "omap_twl4030keypad";
+ input->phys = "twl4030_keypad/input0";
+ input->dev.parent = &pdev->dev;
+
+--
+1.6.3.1
+