diff -ur linux-2.6.27-pandora-r1/arch/arm/mach-omap2/board-omap3pandora-input.c linux-2.6.27-pandora-r1.patched/arch/arm/mach-omap2/board-omap3pandora-input.c
--- linux-2.6.27-pandora-r1/arch/arm/mach-omap2/board-omap3pandora-input.c	2010-10-20 22:58:21.000000000 +0400
+++ linux-2.6.27-pandora-r1.patched/arch/arm/mach-omap2/board-omap3pandora-input.c	2010-10-20 23:27:52.000000000 +0400
@@ -57,7 +57,7 @@
 	KEY(2, 2, KEY_Y),
 	KEY(2, 3, KEY_G),
 	KEY(2, 4, KEY_V),
-	KEY(2, 5, KEY_FN),
+	KEY(2, 5, KEY_RIGHTCTRL),
 	KEY(3, 0, KEY_O),
 	KEY(3, 1, KEY_5),
 	KEY(3, 2, KEY_T),
@@ -81,7 +81,7 @@
 	KEY(7, 0, KEY_ENTER),
 	KEY(7, 1, KEY_1),
 	KEY(7, 2, KEY_Q),
-	KEY(7, 3, KEY_LEFTSHIFT),
+	KEY(7, 3, KEY_TAB),
 	KEY(7, 4, KEY_COMMA),
 	/* Fn keys */
 	FNKEY(0, 0, KEY_F9),
@@ -95,13 +95,13 @@
 	FNKEY(1, 2, KEY_BRIGHTNESSDOWN),
 	FNKEY(1, 3, KEY_GRAVE),
 	FNKEY(1, 4, KEY_F14),		/* pipe/bar */
-	FNKEY(1, 5, KEY_TAB),
+	FNKEY(1, 5, KEY_SPACE),
 	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(2, 5, KEY_RIGHTCTRL),
 	FNKEY(3, 0, KEY_F11),
 	FNKEY(3, 1, KEY_F5),
 	FNKEY(3, 2, KEY_F17),		/* ! */
@@ -125,7 +125,7 @@
 	FNKEY(7, 0, KEY_ENTER),
 	FNKEY(7, 1, KEY_F1),
 	FNKEY(7, 2, KEY_ESC),
-	FNKEY(7, 3, KEY_CAPSLOCK),
+	FNKEY(7, 3, KEY_TAB),
 	FNKEY(7, 4, KEY_SEMICOLON),
 };
 
@@ -141,50 +141,79 @@
 	.rep		= 1,
 };
 
-#define GPIO_BUTTON(gpio_num, ev_type, ev_code, act_low, descr)	\
+#define GPIO_BUTTON(gpio_num, ev_type, ev_code, ev_code_fn, act_low, descr) \
 {								\
 	.gpio		= gpio_num,				\
 	.type		= ev_type,				\
 	.code		= ev_code,				\
+	.code_fn	= ev_code_fn,				\
 	.active_low	= act_low,				\
 	.desc		= "btn " descr,				\
 }
 
-#define GPIO_BUTTON_LOW(gpio_num, event_code, description)	\
-	GPIO_BUTTON(gpio_num, EV_KEY, event_code, 1, description)
+#define GPIO_BUTTON_KEY_LOW(gpio_num, description) \
+	GPIO_BUTTON(gpio_num, EV_KEY, 0, 0, 1, description)
 
 static struct gpio_keys_button gpio_buttons[] = {
-	GPIO_BUTTON_LOW(110,	KEY_UP,		"up"),
-	GPIO_BUTTON_LOW(103,	KEY_DOWN,	"down"),
-	GPIO_BUTTON_LOW(96,	KEY_LEFT,	"left"),
-	GPIO_BUTTON_LOW(98,	KEY_RIGHT,	"right"),
-	GPIO_BUTTON_LOW(109,	KEY_PAGEUP,	"game 1"),
-	GPIO_BUTTON_LOW(111,	KEY_END,	"game 2"),
-	GPIO_BUTTON_LOW(106,	KEY_PAGEDOWN,	"game 3"),
-	GPIO_BUTTON_LOW(101,	KEY_HOME,	"game 4"),
-	GPIO_BUTTON_LOW(102,	KEY_RIGHTSHIFT,	"l"),
-	GPIO_BUTTON_LOW(97,	KEY_KPPLUS,	"l2"),
-	GPIO_BUTTON_LOW(105,	KEY_RIGHTCTRL,	"r"),
-	GPIO_BUTTON_LOW(107,	KEY_KPMINUS,	"r2"),
-	GPIO_BUTTON_LOW(104,	KEY_LEFTCTRL,	"ctrl"),
-	GPIO_BUTTON(100, EV_KEY, KEY_LEFTALT, 0, "alt"),
-	GPIO_BUTTON_LOW(99,	KEY_MENU,	"menu"),
-	GPIO_BUTTON_LOW(176,	KEY_COFFEE,	"hold"),
-	GPIO_BUTTON(108, EV_SW, SW_LID, 1, "lid"),
-};
-
-static const unsigned short buttons_kbd[] = {
-	KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT,
-	KEY_PAGEUP, KEY_END, KEY_PAGEDOWN, KEY_HOME,
-	KEY_RIGHTSHIFT, KEY_KPPLUS, KEY_RIGHTCTRL, KEY_KPMINUS,
-	KEY_LEFTCTRL, KEY_LEFTALT,
-};
-
-static const unsigned short buttons_joy[] = {
-	BTN_0, BTN_1, BTN_2, BTN_3,
-	BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4,
-	BTN_TL, BTN_TL2, BTN_TR, BTN_TR2,
-	BTN_SELECT, BTN_START,
+	GPIO_BUTTON_KEY_LOW(110, "up"),
+	GPIO_BUTTON_KEY_LOW(103, "down"),
+	GPIO_BUTTON_KEY_LOW(96,  "left"),
+	GPIO_BUTTON_KEY_LOW(98,  "right"),
+	GPIO_BUTTON_KEY_LOW(109, "game 1"),
+	GPIO_BUTTON_KEY_LOW(111, "game 2"),
+	GPIO_BUTTON_KEY_LOW(106, "game 3"),
+	GPIO_BUTTON_KEY_LOW(101, "game 4"),
+	GPIO_BUTTON_KEY_LOW(102, "l"),
+	GPIO_BUTTON_KEY_LOW(97,  "l2"),
+	GPIO_BUTTON_KEY_LOW(105, "r"),
+	GPIO_BUTTON_KEY_LOW(107, "r2"),
+	GPIO_BUTTON_KEY_LOW(104, "ctrl"),
+	GPIO_BUTTON(100, EV_KEY, 0,          0, 0, "alt"),
+	GPIO_BUTTON(99,  EV_KEY, KEY_MENU,   KEY_HELP, 1, "menu"),
+	GPIO_BUTTON(176, EV_KEY, KEY_COFFEE, 0, 1, "hold"),
+	GPIO_BUTTON(108, EV_SW,  SW_LID,     0, 1, "lid"),
+};
+
+#define GPIO_BUTTON_CODES(ev_code, ev_code_fn) \
+{						\
+	.code		= ev_code,		\
+	.code_fn	= ev_code_fn,		\
+}
+
+#define  GPIO_ORD_BUTTON_CODES(ev_code) GPIO_BUTTON_CODES(ev_code, 0)
+
+static const struct gpio_button_codes  buttons_kbd[] = {
+	GPIO_BUTTON_CODES(KEY_UP,    KEY_PAGEUP),
+	GPIO_BUTTON_CODES(KEY_DOWN,  KEY_PAGEDOWN),
+	GPIO_BUTTON_CODES(KEY_LEFT,  KEY_HOME),
+	GPIO_BUTTON_CODES(KEY_RIGHT, KEY_END),
+	GPIO_ORD_BUTTON_CODES(KEY_PROG2),
+	GPIO_ORD_BUTTON_CODES(KEY_PROG3),
+	GPIO_ORD_BUTTON_CODES(KEY_PROG4),
+	GPIO_ORD_BUTTON_CODES(KEY_PROG1),
+	GPIO_ORD_BUTTON_CODES(KEY_RIGHTSHIFT),
+	GPIO_ORD_BUTTON_CODES(KEY_KPPLUS),
+	GPIO_ORD_BUTTON_CODES(KEY_FN),
+	GPIO_ORD_BUTTON_CODES(KEY_KPMINUS),
+	GPIO_ORD_BUTTON_CODES(KEY_LEFTCTRL),
+	GPIO_ORD_BUTTON_CODES(KEY_LEFTALT),
+};
+
+static const struct gpio_button_codes buttons_joy[] = {
+	GPIO_ORD_BUTTON_CODES(BTN_0),
+	GPIO_ORD_BUTTON_CODES(BTN_1),
+	GPIO_ORD_BUTTON_CODES(BTN_2),
+	GPIO_ORD_BUTTON_CODES(BTN_3),
+	GPIO_ORD_BUTTON_CODES(BTN_BASE),
+	GPIO_ORD_BUTTON_CODES(BTN_BASE2),
+	GPIO_ORD_BUTTON_CODES(BTN_BASE3),
+	GPIO_ORD_BUTTON_CODES(BTN_BASE4),
+	GPIO_ORD_BUTTON_CODES(BTN_TL),
+	GPIO_ORD_BUTTON_CODES(BTN_TL2),
+	GPIO_ORD_BUTTON_CODES(BTN_TR),
+	GPIO_ORD_BUTTON_CODES(BTN_TR2),
+	GPIO_ORD_BUTTON_CODES(BTN_SELECT),
+	GPIO_ORD_BUTTON_CODES(BTN_START),
 };
 
 static struct gpio_keys_platform_data gpio_key_info = {
@@ -212,11 +241,21 @@
 	return sprintf(page, "%d\n", pandora_keys_gpio_mode);
 }
 
+static void set_goip_button_codes(const struct gpio_button_codes *button_codes,
+		int button_count)
+{
+	int i;
+	for (i = 0; i < button_count; i++) {
+		gpio_buttons[i].code = button_codes[i].code;
+		gpio_buttons[i].code_fn = button_codes[i].code_fn;
+	}
+}
+
 static int pandora_input_proc_write(struct file *file,
 		const char __user *buffer, unsigned long count, void *data)
 {
-	const unsigned short *buttons;
-	int i, val, button_count;
+	const struct gpio_button_codes *button_codes;
+	int val, button_count;
 	char s[32];
 
 	if (!count)
@@ -230,16 +269,15 @@
 		return -EINVAL;
 
 	if (val == 1) {
-		buttons = buttons_kbd;
+		button_codes = buttons_kbd;
 		button_count = ARRAY_SIZE(buttons_kbd);
 	} else if (val == 2) {
-		buttons = buttons_joy;
+		button_codes = buttons_joy;
 		button_count = ARRAY_SIZE(buttons_joy);
 	} else
 		return -EINVAL;
 
-	for (i = 0; i < button_count; i++)
-		gpio_buttons[i].code = buttons[i];
+	set_goip_button_codes(button_codes, button_count);
 
 	pandora_keys_gpio_mode = val;
 	return count;
@@ -277,6 +315,7 @@
 	}
 
 	/* kbd mode by default */
+	set_goip_button_codes(buttons_kbd, ARRAY_SIZE(buttons_kbd));
 	pandora_keys_gpio_mode = 1;
 }
 
diff -ur linux-2.6.27-pandora-r1/arch/arm/plat-omap/include/mach/board-omap3pandora.h linux-2.6.27-pandora-r1.patched/arch/arm/plat-omap/include/mach/board-omap3pandora.h
--- linux-2.6.27-pandora-r1/arch/arm/plat-omap/include/mach/board-omap3pandora.h	2010-10-20 22:58:24.000000000 +0400
+++ linux-2.6.27-pandora-r1.patched/arch/arm/plat-omap/include/mach/board-omap3pandora.h	2010-10-20 23:27:16.000000000 +0400
@@ -28,5 +28,6 @@
 void __init omap3pandora_input_init(void);
 
 #define	OMAP3_PANDORA_TS_GPIO		94
+#define	OMAP3_PANDORA_FN_GPIO		105
 
 #endif /* __ASM_ARCH_OMAP3_PANDORA_H */
diff -ur linux-2.6.27-pandora-r1/drivers/input/keyboard/gpio_keys.c linux-2.6.27-pandora-r1.patched/drivers/input/keyboard/gpio_keys.c
--- linux-2.6.27-pandora-r1/drivers/input/keyboard/gpio_keys.c	2010-10-20 22:59:33.000000000 +0400
+++ linux-2.6.27-pandora-r1.patched/drivers/input/keyboard/gpio_keys.c	2010-10-20 23:27:16.000000000 +0400
@@ -24,6 +24,7 @@
 #include <linux/gpio_keys.h>
 
 #include <asm/gpio.h>
+#include <mach/gpio.h>
 
 struct gpio_button_data {
 	struct gpio_keys_button *button;
@@ -39,10 +40,28 @@
 static void gpio_keys_report_event(struct gpio_keys_button *button,
 				   struct input_dev *input)
 {
+	int code;
 	unsigned int type = button->type ?: EV_KEY;
 	int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low;
 
-	input_event(input, type, button->code, !!state);
+	if (state) {
+		if (button->code_fn &&
+		    !omap_get_gpio_datain(OMAP3_PANDORA_FN_GPIO)) {
+			code = button->code_fn;
+			button->fnized = 1;
+		} else {
+			code = button->code;
+		}
+	} else {
+		if (button->fnized) {
+			code = button->code_fn;
+			button->fnized = 0;
+		} else {
+			code = button->code;
+		}
+	}
+
+	input_event(input, type, code, !!state);
 	input_sync(input);
 }
 
@@ -167,10 +186,17 @@
 			wakeup = 1;
 
 		input_set_capability(input, type, button->code);
+		if (button->code_fn)
+			input_set_capability(input, type, button->code_fn);
 	}
 
-	for (i = 0; i < pdata->nbuttons_reserved; i++)
-		input_set_capability(input, EV_KEY, pdata->buttons_reserved[i]);
+	for (i = 0; i < pdata->nbuttons_reserved; i++) {
+		input_set_capability(input, EV_KEY,
+				     pdata->buttons_reserved[i].code);
+		if (pdata->buttons_reserved[i].code_fn)
+			input_set_capability(input, EV_KEY,
+					pdata->buttons_reserved[i].code_fn);
+	}
 
 	error = input_register_device(input);
 	if (error) {
diff -ur linux-2.6.27-pandora-r1/drivers/input/keyboard/twl4030_keypad.c linux-2.6.27-pandora-r1.patched/drivers/input/keyboard/twl4030_keypad.c
--- linux-2.6.27-pandora-r1/drivers/input/keyboard/twl4030_keypad.c	2010-10-20 22:59:33.000000000 +0400
+++ linux-2.6.27-pandora-r1.patched/drivers/input/keyboard/twl4030_keypad.c	2010-10-20 23:27:16.000000000 +0400
@@ -34,6 +34,7 @@
 #include <linux/i2c/twl4030.h>
 #include <linux/input/matrix_keypad.h>
 
+#include <mach/gpio.h>
 
 /*
  * The TWL4030 family chips include a keypad controller that supports
@@ -61,8 +62,7 @@
 	unsigned	n_cols;
 	unsigned	irq;
 
-	unsigned	fn_down:1;
-	unsigned	fn_sticked:1;
+	unsigned short	fnized[TWL4030_KEYMAP_SIZE];
 
 	struct device *dbg_dev;
 	struct input_dev *input;
@@ -245,26 +245,22 @@
 
 			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);
+			if (is_down) {
+				if (!omap_get_gpio_datain(OMAP3_PANDORA_FN_GPIO)) {
+					kp->fnized[code] = 1;
+					code = MATRIX_SCAN_CODE(row + TWL4030_MAX_ROWS,
+							col, TWL4030_ROW_SHIFT);
+				}
+			}	 
+			else {
+				if (kp->fnized[code]) {
+					kp->fnized[code] = 0;
+					code = MATRIX_SCAN_CODE(row + TWL4030_MAX_ROWS,
+							col, TWL4030_ROW_SHIFT);
+				}
 			}
 
+			kcode = kp->keymap[code];
 			dev_dbg(kp->dbg_dev, "code(fn): %d %d\n", code, kcode);
 			input_event(input, EV_MSC, MSC_SCAN, code);
 			input_report_key(input, kcode, is_down);
diff -ur linux-2.6.27-pandora-r1/include/linux/gpio_keys.h linux-2.6.27-pandora-r1.patched/include/linux/gpio_keys.h
--- linux-2.6.27-pandora-r1/include/linux/gpio_keys.h	2010-10-20 23:01:12.000000000 +0400
+++ linux-2.6.27-pandora-r1.patched/include/linux/gpio_keys.h	2010-10-20 23:27:16.000000000 +0400
@@ -4,6 +4,9 @@
 struct gpio_keys_button {
 	/* Configuration parameters */
 	int code;		/* input event code (KEY_*, SW_*) */
+	int code_fn;		/* 0 if key is ordinary */
+	int fnized;		/* release as code_fn even if fn is no longer 
+				   pressed */
 	int gpio;
 	int active_low;
 	char *desc;
@@ -12,11 +15,16 @@
 	int debounce_interval;	/* debounce ticks interval in msecs */
 };
 
+struct gpio_button_codes {
+	int code;
+	int code_fn;
+};
+
 struct gpio_keys_platform_data {
 	struct gpio_keys_button *buttons;
 	int nbuttons;
 	unsigned int rep:1;		/* enable input subsystem auto repeat */
-	const unsigned short *buttons_reserved;
+	struct gpio_button_codes *buttons_reserved;
 	int nbuttons_reserved;
 };
 
