Skip to contentSkip to conversation

Make N810 keyboard work with console

PATCH In review Tony Lindgren 4 participants 14 messages May 15, 2008 1 message not in the archive

Subsystems (4)
lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): n810-keyboard

Tony Lindgren

author maintainer
#1 lore raw

cover Make N810 keyboard work with console

Hi all,

Here are few fun patches for N810 hackers to make the integrated keyboard work with console :) This should be done in a generic way and the old behaviour is preserved if optional sticky keys are not passed from platform_data.

Seems to also work nicely with xserver-xorg-video-fbdev.

Regards,

Tony

author maintainer
#2 lore raw

PATCH 1/2 Input: Fix lm8323 probe and module unloading

Make module unloading and reloading behave:

- Driver probe could fail if input_register_device fails as no error was returned from probe

- Driver interrupt was using unused platform_data field, change to use i2c platform data interrupt instead

- Free resources on unloading module

- Mark platform data as __init_or_module

---
 arch/arm/mach-omap2/board-n800.c |    2 +-
 drivers/input/keyboard/lm8323.c  |   18 +++++++++++++-----
 include/linux/i2c/lm8323.h       |    2 --
 3 files changed, 14 insertions(+), 8 deletions(-)
arch/arm/mach-omap2/board-n800.c +1 -1
index efcb25d..ae85c2c 100644
@@ -642,7 +642,7 @@ static struct i2c_board_info __initdata n800_i2c_board_info_1[] = {
 
 extern struct tcm825x_platform_data n800_tcm825x_platform_data;
 
-static struct i2c_board_info __initdata n800_i2c_board_info_2[] = {
+static struct i2c_board_info __initdata_or_module n800_i2c_board_info_2[] = {
 #if defined (CONFIG_VIDEO_TCM825X) || defined (CONFIG_VIDEO_TCM825X_MODULE)
 	{
 		I2C_BOARD_INFO(TCM825X_NAME, TCM825X_I2C_ADDR),
drivers/input/keyboard/lm8323.c +13 -5
index e793ae7..d472da0 100644
@@ -755,13 +755,11 @@ static int lm8323_probe(struct i2c_client *client,
 	if (init_pwm(lm, 3, &client->dev, lm8323_pdata->pwm3_name) < 0)
 		goto fail5;
 
-	lm->irq = lm8323_pdata->irq_gpio;
-	debug(&c->dev, "IRQ: %d\n", lm->irq);
-
+	lm->irq = client->irq;
 	mutex_init(&lm->lock);
 	INIT_WORK(&lm->work, lm8323_work);
 
-	err = request_irq(client->irq, lm8323_irq,
+	err = request_irq(lm->irq, lm8323_irq,
 			  IRQF_TRIGGER_FALLING | IRQF_DISABLED |
 			  IRQF_SAMPLE_RANDOM, DRIVER_NAME, lm);
 	if (err) {
@@ -802,7 +800,8 @@ static int lm8323_probe(struct i2c_client *client,
 		set_bit(EV_REP, idev->evbit);
 
 	lm->idev = idev;
-	if (input_register_device(idev)) {
+	err = input_register_device(idev);
+	if (err) {
 		dev_dbg(&client->dev, "error registering input device\n");
 		goto fail8;
 	}
@@ -833,7 +832,16 @@ static int lm8323_remove(struct i2c_client *client)
 	struct lm8323_chip *lm = i2c_get_clientdata(client);
 
 	free_irq(lm->irq, lm);
+	cancel_work_sync(&lm->work);
+	input_unregister_device(lm->idev);
 	device_remove_file(&lm->client->dev, &dev_attr_disable_kp);
+	if (lm->pwm3.enabled)
+		led_classdev_unregister(&lm->pwm3.cdev);
+	if (lm->pwm2.enabled)
+		led_classdev_unregister(&lm->pwm2.cdev);
+	if (lm->pwm1.enabled)
+		led_classdev_unregister(&lm->pwm1.cdev);
+	kfree(lm);
 
 	return 0;
 }
include/linux/i2c/lm8323.h +0 -2
index 5cb09ab..17d6b33 100644
@@ -17,8 +17,6 @@
 #define LM8323_KEYMAP_SIZE (0x7f + 1)
 
 struct lm8323_platform_data {
-	u16 irq_gpio;
-
 	int debounce_time; /* Time to watch for key bouncing, in ms. */
 	int active_time; /* Idle time until sleep, in ms. */
 
Signature · 1 line
1.5.3.6
author maintainer
#3 lore raw

PATCH 2/2 Input: Make lm8323 sticky key to work with console

This allows using N810 keyboard from console by adding optional Fn and shift sticky key handling by passing them from platform_data.

Currently some not so obvious mappings are:

- Pipe is Fn + Enter
- Delete is Fn + Backspace
- Escape is Fn + Ctrl

Works also with xserver-xorg-video-fbdev.

---
 arch/arm/mach-omap2/board-n800.c |   87 ++++++++++++++++++++++++++++++++++----
 drivers/input/keyboard/lm8323.c  |   84 +++++++++++++++++++++++++++++++++----
 include/linux/i2c/lm8323.h       |   12 ++----
 3 files changed, 159 insertions(+), 24 deletions(-)
arch/arm/mach-omap2/board-n800.c +79 -8
index ae85c2c..a654886 100644
@@ -51,7 +51,16 @@
 #define N800_TSC2301_RESET_GPIO		118
 
 #ifdef CONFIG_MACH_NOKIA_N810
-static s16 rx44_keymap[LM8323_KEYMAP_SIZE] = {
+
+/*
+ * Largest keycode that the chip can send, plus one,
+ * so keys can be mapped directly at the index of the
+ * LM8323 keycode instead of subtracting one.
+ */
+#define N810_HWKEY_SZ			(0x7f + 1)
+
+/* Keymap for lm8323. Negative value means Shift + KEY */
+static s16 rx44_keymap[N810_HWKEY_SZ * 2] = {
 	[0x01] = KEY_Q,
 	[0x02] = KEY_K,
 	[0x03] = KEY_O,
@@ -81,7 +90,7 @@ static s16 rx44_keymap[LM8323_KEYMAP_SIZE] = {
 	[0x21] = KEY_E,
 	[0x22] = KEY_SEMICOLON,
 	[0x23] = KEY_MINUS,
-	[0x24] = KEY_EQUAL,
+	[0x24] = -KEY_EQUAL,
 	[0x2b] = KEY_FN,
 	[0x2c] = KEY_M,
 	[0x2f] = KEY_F8,
@@ -108,15 +117,77 @@ static s16 rx44_keymap[LM8323_KEYMAP_SIZE] = {
 
 	[0x71] = KEY_I,
 	[0x75] = KEY_KPENTER,
+
+	/* End of hardware key map, Fn + key values below */
+
+	[0x01 + N810_HWKEY_SZ] = KEY_1,		/* Fn + KEY_Q */
+	[0x02 + N810_HWKEY_SZ] = -KEY_0,		/* Fn + KEY_K */
+	[0x03 + N810_HWKEY_SZ] = KEY_9,		/* Fn + KEY_O */
+	[0x04 + N810_HWKEY_SZ] = KEY_0,		/* Fn + KEY_P */
+	[0x05 + N810_HWKEY_SZ] = KEY_DELETE,	/* Fn + KEY_BACKSPACE */
+	[0x06 + N810_HWKEY_SZ] = -KEY_1,		/* Fn + KEY_A */
+	[0x07 + N810_HWKEY_SZ] = -KEY_APOSTROPHE,	/* Fn + KEY_S */
+	[0x08 + N810_HWKEY_SZ] = -KEY_2,		/* Fn + KEY_D */
+	[0x09 + N810_HWKEY_SZ] = -KEY_3,		/* Fn + KEY_F */
+	[0x0a + N810_HWKEY_SZ] = KEY_BACKSLASH,	/* Fn + KEY_G */
+	[0x0b + N810_HWKEY_SZ] = KEY_SLASH,	/* Fn + KEY_H */
+	[0x0c + N810_HWKEY_SZ] = -KEY_9,		/* Fn + KEY_J */
+
+	[0x11 + N810_HWKEY_SZ] = KEY_2,		/* Fn + KEY_W */
+	[0x12 + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_F4 */
+	[0x13 + N810_HWKEY_SZ] = -KEY_8,		/* Fn + KEY_L */
+	[0x14 + N810_HWKEY_SZ] = -KEY_SLASH,	/* Fn + KEY_APOSTROPHE */
+	[0x16 + N810_HWKEY_SZ] = KEY_YEN,		/* Fn + KEY_Z */
+	[0x17 + N810_HWKEY_SZ] = -KEY_6,		/* Fn + KEY_X */
+	[0x18 + N810_HWKEY_SZ] = -KEY_GRAVE,	/* Fn + KEY_C */
+	[0x19 + N810_HWKEY_SZ] = -KEY_5,		/* Fn + KEY_V */
+	[0x1a + N810_HWKEY_SZ] = -KEY_7,		/* Fn + KEY_B */
+	[0x1b + N810_HWKEY_SZ] = -KEY_4,		/* Fn + KEY_N */
+	[0x1c + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_LEFTSHIFT */
+	[0x1f + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_F7 */
+
+	[0x21 + N810_HWKEY_SZ] = KEY_3,		/* Fn + KEY_E */
+	[0x22 + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_SEMICOLON */
+	[0x23 + N810_HWKEY_SZ] = -KEY_MINUS,	/* Fn + KEY_MINUS */
+	[0x24 + N810_HWKEY_SZ] = KEY_EQUAL,	/* Fn + -KEY_EQUAL */
+	[0x2b + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_FN */
+	[0x2c + N810_HWKEY_SZ] = KEY_EURO,		/* Fn + KEY_M */
+	[0x2f + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_F8 */
+
+	[0x31 + N810_HWKEY_SZ] = KEY_4,		/* Fn + KEY_R */
+	[0x32 + N810_HWKEY_SZ] = KEY_ESC,		/* Fn + KEY_RIGHTCTRL */
+	[0x34 + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_SPACE */
+	[0x35 + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_COMMA */
+	[0x37 + N810_HWKEY_SZ] = KEY_PAGEUP,	/* Fn + KEY_UP */
+	[0x3c + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_COMPOSE */
+	[0x3f + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_F6 */
+
+	[0x41 + N810_HWKEY_SZ] = KEY_5,		/* Fn + KEY_T */
+	[0x44 + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_DOT */
+	[0x46 + N810_HWKEY_SZ] = KEY_TAB,		/* Fn + KEY_RIGHT */
+	[0x4f + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_F5 */
+	[0x51 + N810_HWKEY_SZ] = KEY_6,		/* Fn + KEY_Y */
+	[0x53 + N810_HWKEY_SZ] = KEY_PAGEDOWN,	/* Fn + KEY_DOWN */
+	[0x55 + N810_HWKEY_SZ] = -KEY_BACKSLASH,	/* Fn + KEY_ENTER */
+	[0x5f + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_ESC */
+
+	[0x61 + N810_HWKEY_SZ] = KEY_7,		/* Fn + KEY_U */
+	[0x64 + N810_HWKEY_SZ] = KEY_ESC,		/* Fn + KEY_LEFT */
+
+	[0x71 + N810_HWKEY_SZ] = KEY_8,		/* Fn + KEY_I */
+	[0x75 + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_KPENTER */
 };
 
 static struct lm8323_platform_data lm8323_pdata = {
-	.repeat = 0, /* Repeat is handled in userspace for now. */
-	.keymap = rx44_keymap,
-
-	.name = "Internal keyboard",
-	.pwm1_name = "keyboard",
-	.pwm2_name = "cover",
+	.repeat		= 1, /* Change to 0 if handled in userspace */
+	.keymap		= rx44_keymap,
+	.keymap_sz	= ARRAY_SIZE(rx44_keymap),
+	.fn_key		= KEY_FN,
+	.shift_key	= KEY_LEFTSHIFT,
+
+	.name		= "Internal keyboard",
+	.pwm1_name	= "keyboard",
+	.pwm2_name	= "cover",
 };
 #endif
 
drivers/input/keyboard/lm8323.c +76 -8

118 lines not on this page · raw message

include/linux/i2c/lm8323.h +4 -8
index 17d6b33..5ea6cef 100644
@@ -9,13 +9,6 @@
 
 #include <linux/types.h>
 
-/*
- * Largest keycode that the chip can send, plus one,
- * so keys can be mapped directly at the index of the
- * LM8323 keycode instead of subtracting one.
- */
-#define LM8323_KEYMAP_SIZE (0x7f + 1)
-
 struct lm8323_platform_data {
 	int debounce_time; /* Time to watch for key bouncing, in ms. */
 	int active_time; /* Idle time until sleep, in ms. */
@@ -23,7 +16,10 @@ struct lm8323_platform_data {
 	int size_x;
 	int size_y;
 	int repeat : 1;
-	const s16 *keymap;
+	s16 *keymap;
+	u16 keymap_sz;
+	u16 fn_key;
+	u16 shift_key;
 
 	char *pwm1_name; /* Device name for PWM1. */
 	char *pwm2_name; /* Device name for PWM2. */
Signature · 1 line
1.5.3.6
#4 lore raw

Re: [PATCH 2/2] Input: Make lm8323 sticky key to work with console

Quoted 8 lines · Tony Lindgren

This allows using N810 keyboard from console by adding optional Fn and shift sticky key handling by passing them from platform_data.

Currently some not so obvious mappings are:

- Pipe is Fn + Enter
- Delete is Fn + Backspace
- Escape is Fn + Ctrl

no tab? :-(

Fn + space maybe?? :-p

Quoted 289 lines

Works also with xserver-xorg-video-fbdev.

---
 arch/arm/mach-omap2/board-n800.c |   87 ++++++++++++++++++++++++++++++++++----
 drivers/input/keyboard/lm8323.c  |   84 +++++++++++++++++++++++++++++++++----
 include/linux/i2c/lm8323.h       |   12 ++----
 3 files changed, 159 insertions(+), 24 deletions(-)
arch/arm/mach-omap2/board-n800.c +79 -8
index ae85c2c..a654886 100644
@@ -51,7 +51,16 @@
 #define N800_TSC2301_RESET_GPIO		118
 
 #ifdef CONFIG_MACH_NOKIA_N810
-static s16 rx44_keymap[LM8323_KEYMAP_SIZE] = {
+
+/*
+ * Largest keycode that the chip can send, plus one,
+ * so keys can be mapped directly at the index of the
+ * LM8323 keycode instead of subtracting one.
+ */
+#define N810_HWKEY_SZ			(0x7f + 1)
+
+/* Keymap for lm8323. Negative value means Shift + KEY */
+static s16 rx44_keymap[N810_HWKEY_SZ * 2] = {
 	[0x01] = KEY_Q,
 	[0x02] = KEY_K,
 	[0x03] = KEY_O,
@@ -81,7 +90,7 @@ static s16 rx44_keymap[LM8323_KEYMAP_SIZE] = {
 	[0x21] = KEY_E,
 	[0x22] = KEY_SEMICOLON,
 	[0x23] = KEY_MINUS,
-	[0x24] = KEY_EQUAL,
+	[0x24] = -KEY_EQUAL,
 	[0x2b] = KEY_FN,
 	[0x2c] = KEY_M,
 	[0x2f] = KEY_F8,
@@ -108,15 +117,77 @@ static s16 rx44_keymap[LM8323_KEYMAP_SIZE] = {
 
 	[0x71] = KEY_I,
 	[0x75] = KEY_KPENTER,
+
+	/* End of hardware key map, Fn + key values below */
+
+	[0x01 + N810_HWKEY_SZ] = KEY_1,		/* Fn + KEY_Q */
+	[0x02 + N810_HWKEY_SZ] = -KEY_0,		/* Fn + KEY_K */
+	[0x03 + N810_HWKEY_SZ] = KEY_9,		/* Fn + KEY_O */
+	[0x04 + N810_HWKEY_SZ] = KEY_0,		/* Fn + KEY_P */
+	[0x05 + N810_HWKEY_SZ] = KEY_DELETE,	/* Fn + KEY_BACKSPACE */
+	[0x06 + N810_HWKEY_SZ] = -KEY_1,		/* Fn + KEY_A */
+	[0x07 + N810_HWKEY_SZ] = -KEY_APOSTROPHE,	/* Fn + KEY_S */
+	[0x08 + N810_HWKEY_SZ] = -KEY_2,		/* Fn + KEY_D */
+	[0x09 + N810_HWKEY_SZ] = -KEY_3,		/* Fn + KEY_F */
+	[0x0a + N810_HWKEY_SZ] = KEY_BACKSLASH,	/* Fn + KEY_G */
+	[0x0b + N810_HWKEY_SZ] = KEY_SLASH,	/* Fn + KEY_H */
+	[0x0c + N810_HWKEY_SZ] = -KEY_9,		/* Fn + KEY_J */
+
+	[0x11 + N810_HWKEY_SZ] = KEY_2,		/* Fn + KEY_W */
+	[0x12 + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_F4 */
+	[0x13 + N810_HWKEY_SZ] = -KEY_8,		/* Fn + KEY_L */
+	[0x14 + N810_HWKEY_SZ] = -KEY_SLASH,	/* Fn + KEY_APOSTROPHE */
+	[0x16 + N810_HWKEY_SZ] = KEY_YEN,		/* Fn + KEY_Z */
+	[0x17 + N810_HWKEY_SZ] = -KEY_6,		/* Fn + KEY_X */
+	[0x18 + N810_HWKEY_SZ] = -KEY_GRAVE,	/* Fn + KEY_C */
+	[0x19 + N810_HWKEY_SZ] = -KEY_5,		/* Fn + KEY_V */
+	[0x1a + N810_HWKEY_SZ] = -KEY_7,		/* Fn + KEY_B */
+	[0x1b + N810_HWKEY_SZ] = -KEY_4,		/* Fn + KEY_N */
+	[0x1c + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_LEFTSHIFT */
+	[0x1f + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_F7 */
+
+	[0x21 + N810_HWKEY_SZ] = KEY_3,		/* Fn + KEY_E */
+	[0x22 + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_SEMICOLON */
+	[0x23 + N810_HWKEY_SZ] = -KEY_MINUS,	/* Fn + KEY_MINUS */
+	[0x24 + N810_HWKEY_SZ] = KEY_EQUAL,	/* Fn + -KEY_EQUAL */
+	[0x2b + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_FN */
+	[0x2c + N810_HWKEY_SZ] = KEY_EURO,		/* Fn + KEY_M */
+	[0x2f + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_F8 */
+
+	[0x31 + N810_HWKEY_SZ] = KEY_4,		/* Fn + KEY_R */
+	[0x32 + N810_HWKEY_SZ] = KEY_ESC,		/* Fn + KEY_RIGHTCTRL */
+	[0x34 + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_SPACE */
+	[0x35 + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_COMMA */
+	[0x37 + N810_HWKEY_SZ] = KEY_PAGEUP,	/* Fn + KEY_UP */
+	[0x3c + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_COMPOSE */
+	[0x3f + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_F6 */
+
+	[0x41 + N810_HWKEY_SZ] = KEY_5,		/* Fn + KEY_T */
+	[0x44 + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_DOT */
+	[0x46 + N810_HWKEY_SZ] = KEY_TAB,		/* Fn + KEY_RIGHT */
+	[0x4f + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_F5 */
+	[0x51 + N810_HWKEY_SZ] = KEY_6,		/* Fn + KEY_Y */
+	[0x53 + N810_HWKEY_SZ] = KEY_PAGEDOWN,	/* Fn + KEY_DOWN */
+	[0x55 + N810_HWKEY_SZ] = -KEY_BACKSLASH,	/* Fn + KEY_ENTER */
+	[0x5f + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_ESC */
+
+	[0x61 + N810_HWKEY_SZ] = KEY_7,		/* Fn + KEY_U */
+	[0x64 + N810_HWKEY_SZ] = KEY_ESC,		/* Fn + KEY_LEFT */
+
+	[0x71 + N810_HWKEY_SZ] = KEY_8,		/* Fn + KEY_I */
+	[0x75 + N810_HWKEY_SZ] = KEY_RESERVED,	/* Fn + KEY_KPENTER */
 };
 
 static struct lm8323_platform_data lm8323_pdata = {
-	.repeat = 0, /* Repeat is handled in userspace for now. */
-	.keymap = rx44_keymap,
-
-	.name = "Internal keyboard",
-	.pwm1_name = "keyboard",
-	.pwm2_name = "cover",
+	.repeat		= 1, /* Change to 0 if handled in userspace */
+	.keymap		= rx44_keymap,
+	.keymap_sz	= ARRAY_SIZE(rx44_keymap),
+	.fn_key		= KEY_FN,
+	.shift_key	= KEY_LEFTSHIFT,
+
+	.name		= "Internal keyboard",
+	.pwm1_name	= "keyboard",
+	.pwm2_name	= "cover",
 };
 #endif
 
drivers/input/keyboard/lm8323.c +76 -8
index d472da0..485c19f 100644
@@ -155,7 +155,19 @@ struct lm8323_chip {
 	unsigned		pm_suspend : 1;
 	unsigned		keys_down;
 	char			phys[32];
-	s16			keymap[LM8323_KEYMAP_SIZE];
+
+#define SHIFT_LOCKED		(1 << 5)
+#define SHIFT_HELD		(1 << 4)
+#define SHIFT_ONE		(1 << 3)
+#define FN_LOCKED		(1 << 2)
+#define FN_HELD			(1 << 1)
+#define FN_ONE			(1 << 0)
+	u8			sticky;
+
+	s16			*keymap;
+	u16			keymap_sz;
+	u16			fn_key;
+	u16			shift_key;
 	int			size_x;
 	int			size_y;
 	int			debounce_time;
@@ -279,6 +291,41 @@ static inline int lm8323_ispress(u8 event)
 	return (event & 0x80) ? 1 : 0;
 }
 
+static inline u8 is_sticky(struct lm8323_chip *lm, s16 keycode, int isdown)
+{
+	if (isdown) {
+		if (lm->fn_key && keycode == lm->fn_key) {
+			if (lm->sticky & FN_LOCKED)
+				lm->sticky = 0;
+			else if (lm->sticky & FN_ONE)
+				lm->sticky = FN_LOCKED;
+			else
+				lm->sticky = FN_HELD | FN_ONE;
+			return 1;
+		}
+		if (lm->shift_key && keycode == lm->shift_key) {
+			if (lm->sticky & SHIFT_LOCKED)
+				lm->sticky = 0;
+			else if (lm->sticky & SHIFT_ONE)
+				lm->sticky = SHIFT_LOCKED;
+			else
+				lm->sticky = SHIFT_HELD | SHIFT_ONE;
+			return 1;
+		}
+	} else {
+		if (lm->fn_key && keycode == lm->fn_key) {
+			lm->sticky &= ~FN_HELD;
+			return 1;
+		}
+		if (lm->shift_key && keycode == lm->shift_key) {
+			lm->sticky &= ~SHIFT_HELD;
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
 static void process_keys(struct lm8323_chip *lm)
 {
 	u8 event;
@@ -300,10 +347,29 @@ static void process_keys(struct lm8323_chip *lm)
 	key_fifo[ret] = 0;
 
 	while ((event = key_fifo[i])) {
-		u8 key = lm8323_whichkey(event);
+		u16 key = lm8323_whichkey(event);
 		int isdown = lm8323_ispress(event);
 		s16 keycode = lm->keymap[key];
 
+		if (is_sticky(lm, keycode, isdown)) {
+			i++;
+			continue;
+		}
+
+		if (lm->sticky & (FN_LOCKED | FN_HELD | FN_ONE)) {
+			keycode = lm->keymap[key + (lm->keymap_sz / 2)];
+			if (keycode < 0) {
+				lm->sticky |= SHIFT_ONE;
+				keycode = abs(keycode);
+			}
+		}
+
+		if (lm->sticky & (SHIFT_LOCKED | SHIFT_HELD | SHIFT_ONE))
+			input_report_key(lm->idev, KEY_LEFTSHIFT, isdown);
+
+		if (lm->sticky && !isdown)
+			lm->sticky &= ~(SHIFT_ONE | FN_ONE);
+
 		if (likely(keycode > 0)) {
 			debug(&lm->client->dev, "key 0x%02x %s\n", key,
 			      isdown ? "down" : "up");
@@ -707,8 +773,12 @@ static int lm8323_probe(struct i2c_client *client,
 				lm->size_y);
 		lm->size_x = 12;
 	}
+	debug(&client->dev, "Keypad size: %d x %d\n", lm->size_x, lm->size_y);
 
-	debug(&c->dev, "Keypad size: %d x %d\n", lm->size_x, lm->size_y);
+	lm->keymap = lm8323_pdata->keymap;
+	lm->keymap_sz = lm8323_pdata->keymap_sz;
+	lm->fn_key = lm8323_pdata->fn_key;
+	lm->shift_key = lm8323_pdata->shift_key;
 
 	lm->debounce_time = lm8323_pdata->debounce_time;
 	if (lm->debounce_time == 0) /* Default. */
@@ -789,11 +859,9 @@ static int lm8323_probe(struct i2c_client *client,
 
 	lm->keys_down = 0;
 	idev->evbit[0] = BIT(EV_KEY);
-	for (i = 0; i < LM8323_KEYMAP_SIZE; i++) {
-		if (lm8323_pdata->keymap[i] > 0)
-			set_bit(lm8323_pdata->keymap[i], idev->keybit);
-
-		lm->keymap[i] = lm8323_pdata->keymap[i];
+	for (i = 0; i < lm->keymap_sz; i++) {
+		if (lm->keymap[i] != 0)
+			set_bit(abs(lm->keymap[i]), idev->keybit);
 	}
 
 	if (lm8323_pdata->repeat)
include/linux/i2c/lm8323.h +4 -8
index 17d6b33..5ea6cef 100644
@@ -9,13 +9,6 @@
 
 #include <linux/types.h>
 
-/*
- * Largest keycode that the chip can send, plus one,
- * so keys can be mapped directly at the index of the
- * LM8323 keycode instead of subtracting one.
- */
-#define LM8323_KEYMAP_SIZE (0x7f + 1)
-
 struct lm8323_platform_data {
 	int debounce_time; /* Time to watch for key bouncing, in ms. */
 	int active_time; /* Idle time until sleep, in ms. */
@@ -23,7 +16,10 @@ struct lm8323_platform_data {
 	int size_x;
 	int size_y;
 	int repeat : 1;
-	const s16 *keymap;
+	s16 *keymap;
+	u16 keymap_sz;
+	u16 fn_key;
+	u16 shift_key;
 
 	char *pwm1_name; /* Device name for PWM1. */
 	char *pwm2_name; /* Device name for PWM2. */
Signature · 6 lines
1.5.3.6

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Signature · 5 lines
Best Regards,

Felipe Balbi
[email protected]
http://blog.felipebalbi.com
#5 lore raw

Re: [PATCH 2/2] Input: Make lm8323 sticky key to work with console

Quoted 6 lines · Felipe Balbi
Quoted 5 lines · Tony Lindgren

This allows using N810 keyboard from console by adding optional Fn and shift sticky key handling by passing them from platform_data.

Currently some not so obvious mappings are:

Quoted 7 lines
Quoted 3 lines

- Pipe is Fn + Enter
- Delete is Fn + Backspace
- Escape is Fn + Ctrl

no tab? :-(

Fn + space maybe?? :-p

Fn + Right is assigned in the patch (I check too :) ). But I'm not sure whther that should be done in the lm8323 driver or elsewhere. The existence of keys like Fn and Shift is N810-specific and lm8323 is just a gpio matrix keypad chip.

Regards

Signature · 2 lines
Please do not print this email unless absolutely necessary. Spread
environmental awareness.
#6 lore raw

Re: [PATCH 2/2] Input: Make lm8323 sticky key to work with console

Quoted 11 lines · andrzej zaborowski
Quoted 10 lines · Felipe Balbi
Quoted 8 lines · Tony Lindgren

This allows using N810 keyboard from console by adding optional Fn and shift sticky key handling by passing them from platform_data.

Currently some not so obvious mappings are:

- Pipe is Fn + Enter
- Delete is Fn + Backspace
- Escape is Fn + Ctrl

Quoted 8 lines
Quoted 3 lines

no tab? :-(

Fn + space maybe?? :-p

Fn + Right is assigned in the patch (I check too :) ). But I'm not sure whther that should be done in the lm8323 driver or elsewhere. The existence of keys like Fn and Shift is N810-specific and lm8323 is just a gpio matrix keypad chip.

but that's coming from board file. It should be ok.

Signature · 5 lines
Best Regards,

Felipe Balbi
[email protected]
http://blog.felipebalbi.com
author maintainer
#7 lore raw

Re: [PATCH 2/2] Input: Make lm8323 sticky key to work with console

Quoted 14 lines · Felipe Balbi
Quoted 13 lines · andrzej zaborowski
Quoted 12 lines · Felipe Balbi
Quoted 8 lines · Tony Lindgren

This allows using N810 keyboard from console by adding optional Fn and shift sticky key handling by passing them from platform_data.

Currently some not so obvious mappings are:

- Pipe is Fn + Enter
- Delete is Fn + Backspace
- Escape is Fn + Ctrl

no tab? :-(

Quoted 8 lines
Quoted 6 lines
Quoted 1 line

Fn + space maybe?? :-p

Fn + Right is assigned in the patch (I check too :) ). But I'm not sure whther that should be done in the lm8323 driver or elsewhere. The existence of keys like Fn and Shift is N810-specific and lm8323 is just a gpio matrix keypad chip.

but that's coming from board file. It should be ok.

Yeah I think it should be OK too as nothing happens if platform_data does not pass fn or shift keys. So the driver should work with any keyboard layout.

Tony

author maintainer
#8 lore raw

Re: [PATCH 2/2] Input: Make lm8323 sticky key to work with console

Quoted 22 lines · Tony Lindgren
Quoted 21 lines · Felipe Balbi
Quoted 19 lines · andrzej zaborowski
Quoted 6 lines · Felipe Balbi
Quoted 5 lines · Tony Lindgren

This allows using N810 keyboard from console by adding optional Fn and shift sticky key handling by passing them from platform_data.

Currently some not so obvious mappings are:

Quoted 7 lines
Quoted 3 lines

- Pipe is Fn + Enter
- Delete is Fn + Backspace
- Escape is Fn + Ctrl

no tab? :-(

Fn + space maybe?? :-p

Fn + Right is assigned in the patch (I check too :) ). But I'm not sure whther that should be done in the lm8323 driver or elsewhere. The existence of keys like Fn and Shift is N810-specific and lm8323 is just a gpio matrix keypad chip.

Quoted 5 lines
Quoted 1 line

but that's coming from board file. It should be ok.

Yeah I think it should be OK too as nothing happens if platform_data does not pass fn or shift keys. So the driver should work with any keyboard layout.

BTW, I like the idea for FN + space for tab key, easier to use than FN + Right :)

Tony

#9 lore raw

Re: [PATCH 1/2] Input: Fix lm8323 probe and module unloading

In reply to Tony Lindgren
Quoted 39 lines · Tony Lindgren

Make module unloading and reloading behave:

- Driver probe could fail if input_register_device fails as no error was returned from probe

- Driver interrupt was using unused platform_data field, change to use i2c platform data interrupt instead

- Free resources on unloading module

- Mark platform data as __init_or_module

---
 arch/arm/mach-omap2/board-n800.c |    2 +-
 drivers/input/keyboard/lm8323.c  |   18 +++++++++++++-----
 include/linux/i2c/lm8323.h       |    2 --
 3 files changed, 14 insertions(+), 8 deletions(-)
arch/arm/mach-omap2/board-n800.c +1 -1
index efcb25d..ae85c2c 100644
@@ -642,7 +642,7 @@ static struct i2c_board_info __initdata n800_i2c_board_info_1[] = {
 
 extern struct tcm825x_platform_data n800_tcm825x_platform_data;
 
-static struct i2c_board_info __initdata n800_i2c_board_info_2[] = {
+static struct i2c_board_info __initdata_or_module n800_i2c_board_info_2[] = {
 #if defined (CONFIG_VIDEO_TCM825X) || defined (CONFIG_VIDEO_TCM825X_MODULE)
 	{
 		I2C_BOARD_INFO(TCM825X_NAME, TCM825X_I2C_ADDR),
drivers/input/keyboard/lm8323.c +0 -0
index e793ae7..d472da0 100644
@@ -755,13 +755,11 @@ static int lm8323_probe(struct i2c_client *client,
 	if (init_pwm(lm, 3, &client->dev, lm8323_pdata->pwm3_name) < 0)
 		goto fail5;

drivers/input/keyboard/lm8323.c static int lm8323_probe(struct i2c_client *client, · line 762

Quoted 10 lines
drivers/input/keyboard/lm8323.c +2 -4
 
-	lm->irq = lm8323_pdata->irq_gpio;
-	debug(&c->dev, "IRQ: %d\n", lm->irq);
-
+	lm->irq = client->irq;
 	mutex_init(&lm->lock);
 	INIT_WORK(&lm->work, lm8323_work);
 
-	err = request_irq(client->irq, lm8323_irq,
+	err = request_irq(lm->irq, lm8323_irq,

instead, you could just remove lm->irq field from structure and keep using client->irq.

Quoted 50 lines
drivers/input/keyboard/lm8323.c +11 -1
 			  IRQF_TRIGGER_FALLING | IRQF_DISABLED |
 			  IRQF_SAMPLE_RANDOM, DRIVER_NAME, lm);
 	if (err) {
@@ -802,7 +800,8 @@ static int lm8323_probe(struct i2c_client *client,
 		set_bit(EV_REP, idev->evbit);
 
 	lm->idev = idev;
-	if (input_register_device(idev)) {
+	err = input_register_device(idev);
+	if (err) {
 		dev_dbg(&client->dev, "error registering input device\n");
 		goto fail8;
 	}
@@ -833,7 +832,16 @@ static int lm8323_remove(struct i2c_client *client)
 	struct lm8323_chip *lm = i2c_get_clientdata(client);
 
 	free_irq(lm->irq, lm);
+	cancel_work_sync(&lm->work);
+	input_unregister_device(lm->idev);
 	device_remove_file(&lm->client->dev, &dev_attr_disable_kp);
+	if (lm->pwm3.enabled)
+		led_classdev_unregister(&lm->pwm3.cdev);
+	if (lm->pwm2.enabled)
+		led_classdev_unregister(&lm->pwm2.cdev);
+	if (lm->pwm1.enabled)
+		led_classdev_unregister(&lm->pwm1.cdev);
+	kfree(lm);
 
 	return 0;
 }
include/linux/i2c/lm8323.h +0 -2
index 5cb09ab..17d6b33 100644
@@ -17,8 +17,6 @@
 #define LM8323_KEYMAP_SIZE (0x7f + 1)
 
 struct lm8323_platform_data {
-	u16 irq_gpio;
-
 	int debounce_time; /* Time to watch for key bouncing, in ms. */
 	int active_time; /* Idle time until sleep, in ms. */
 
Signature · 6 lines
1.5.3.6

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Signature · 5 lines
Best Regards,

Felipe Balbi
[email protected]
http://blog.felipebalbi.com
author maintainer
#10 lore raw

Re: [PATCH 1/2] Input: Fix lm8323 probe and module unloading, take #2

Quoted 48 lines · Felipe Balbi
Quoted 47 lines · Tony Lindgren

Make module unloading and reloading behave:

- Driver probe could fail if input_register_device fails as no error was returned from probe

- Driver interrupt was using unused platform_data field, change to use i2c platform data interrupt instead

- Free resources on unloading module

- Mark platform data as __init_or_module

---
 arch/arm/mach-omap2/board-n800.c |    2 +-
 drivers/input/keyboard/lm8323.c  |   18 +++++++++++++-----
 include/linux/i2c/lm8323.h       |    2 --
 3 files changed, 14 insertions(+), 8 deletions(-)
arch/arm/mach-omap2/board-n800.c +1 -1
index efcb25d..ae85c2c 100644
@@ -642,7 +642,7 @@ static struct i2c_board_info __initdata n800_i2c_board_info_1[] = {
 
 extern struct tcm825x_platform_data n800_tcm825x_platform_data;
 
-static struct i2c_board_info __initdata n800_i2c_board_info_2[] = {
+static struct i2c_board_info __initdata_or_module n800_i2c_board_info_2[] = {
 #if defined (CONFIG_VIDEO_TCM825X) || defined (CONFIG_VIDEO_TCM825X_MODULE)
 	{
 		I2C_BOARD_INFO(TCM825X_NAME, TCM825X_I2C_ADDR),
drivers/input/keyboard/lm8323.c +1 -3
index e793ae7..d472da0 100644
@@ -755,13 +755,11 @@ static int lm8323_probe(struct i2c_client *client,
 	if (init_pwm(lm, 3, &client->dev, lm8323_pdata->pwm3_name) < 0)
 		goto fail5;
 
-	lm->irq = lm8323_pdata->irq_gpio;
-	debug(&c->dev, "IRQ: %d\n", lm->irq);
-
+	lm->irq = client->irq;
 	mutex_init(&lm->lock);
 	INIT_WORK(&lm->work, lm8323_work);
 
Quoted 5 lines

drivers/input/keyboard/lm8323.c static int lm8323_probe(struct i2c_client *client, · line 762

Quoted 2 lines
drivers/input/keyboard/lm8323.c +1 -1
-	err = request_irq(client->irq, lm8323_irq,
+	err = request_irq(lm->irq, lm8323_irq,

instead, you could just remove lm->irq field from structure and keep using client->irq.

Good idea, here's an updated patch.

Tony

Quoted 1 line

From aa1c7706df6f99df31322d297e7142267e237819 Mon Sep 17 00:00:00 2001

From: Tony Lindgren <[email protected]>
Date: Mon, 12 May 2008 22:53:07 -0700
Subject: [PATCH] Input: Fix lm8323 probe and module unloading

Make module unloading and reloading behave:

- Driver probe could fail if input_register_device fails as no error was returned from probe

- Driver interrupt was using unused platform_data field, change to use i2c platform data interrupt instead

- Free resources on unloading module

- Mark platform data as __init_or_module

---
 arch/arm/mach-omap2/board-n800.c |    2 +-
 drivers/input/keyboard/lm8323.c  |   32 +++++++++++++++++++-------------
 include/linux/i2c/lm8323.h       |    2 --
 3 files changed, 20 insertions(+), 16 deletions(-)
arch/arm/mach-omap2/board-n800.c +1 -1
index efcb25d..ae85c2c 100644
@@ -642,7 +642,7 @@ static struct i2c_board_info __initdata n800_i2c_board_info_1[] = {
 
 extern struct tcm825x_platform_data n800_tcm825x_platform_data;
 
-static struct i2c_board_info __initdata n800_i2c_board_info_2[] = {
+static struct i2c_board_info __initdata_or_module n800_i2c_board_info_2[] = {
 #if defined (CONFIG_VIDEO_TCM825X) || defined (CONFIG_VIDEO_TCM825X_MODULE)
 	{
 		I2C_BOARD_INFO(TCM825X_NAME, TCM825X_I2C_ADDR),
drivers/input/keyboard/lm8323.c +19 -13
index e793ae7..72bb587 100644
@@ -150,7 +150,6 @@ struct lm8323_chip {
 	struct i2c_client	*client;
 	struct work_struct	work;
 	struct input_dev	*idev;
-	int			irq;
 	unsigned		kp_enabled : 1;
 	unsigned		pm_suspend : 1;
 	unsigned		keys_down;
@@ -755,9 +754,6 @@ static int lm8323_probe(struct i2c_client *client,
 	if (init_pwm(lm, 3, &client->dev, lm8323_pdata->pwm3_name) < 0)
 		goto fail5;
 
-	lm->irq = lm8323_pdata->irq_gpio;
-	debug(&c->dev, "IRQ: %d\n", lm->irq);
-
 	mutex_init(&lm->lock);
 	INIT_WORK(&lm->work, lm8323_work);
 
@@ -765,11 +761,11 @@ static int lm8323_probe(struct i2c_client *client,
 			  IRQF_TRIGGER_FALLING | IRQF_DISABLED |
 			  IRQF_SAMPLE_RANDOM, DRIVER_NAME, lm);
 	if (err) {
-		dev_err(&client->dev, "could not get IRQ %d\n", lm->irq);
+		dev_err(&client->dev, "could not get IRQ %d\n", client->irq);
 		goto fail6;
 	}
 
-	set_irq_wake(lm->irq, 1);
+	set_irq_wake(client->irq, 1);
 
 	lm->kp_enabled = 1;
 	err = device_create_file(&client->dev, &dev_attr_disable_kp);
@@ -802,7 +798,8 @@ static int lm8323_probe(struct i2c_client *client,
 		set_bit(EV_REP, idev->evbit);
 
 	lm->idev = idev;
-	if (input_register_device(idev)) {
+	err = input_register_device(idev);
+	if (err) {
 		dev_dbg(&client->dev, "error registering input device\n");
 		goto fail8;
 	}
@@ -812,7 +809,7 @@ static int lm8323_probe(struct i2c_client *client,
 fail8:
 	device_remove_file(&client->dev, &dev_attr_disable_kp);
 fail7:
-	free_irq(lm->irq, lm);
+	free_irq(client->irq, lm);
 fail6:
 	if (lm->pwm3.enabled)
 		led_classdev_unregister(&lm->pwm3.cdev);
@@ -832,8 +829,17 @@ static int lm8323_remove(struct i2c_client *client)
 {
 	struct lm8323_chip *lm = i2c_get_clientdata(client);
 
-	free_irq(lm->irq, lm);
+	free_irq(client->irq, lm);
+	cancel_work_sync(&lm->work);
+	input_unregister_device(lm->idev);
 	device_remove_file(&lm->client->dev, &dev_attr_disable_kp);
+	if (lm->pwm3.enabled)
+		led_classdev_unregister(&lm->pwm3.cdev);
+	if (lm->pwm2.enabled)
+		led_classdev_unregister(&lm->pwm2.cdev);
+	if (lm->pwm1.enabled)
+		led_classdev_unregister(&lm->pwm1.cdev);
+	kfree(lm);
 
 	return 0;
 }
@@ -846,8 +852,8 @@ static int lm8323_suspend(struct i2c_client *client, pm_message_t mesg)
 {
 	struct lm8323_chip *lm = i2c_get_clientdata(client);
 
-	set_irq_wake(lm->irq, 0);
-	disable_irq(lm->irq);
+	set_irq_wake(client->irq, 0);
+	disable_irq(client->irq);
 
 	mutex_lock(&lm->lock);
 	lm->pm_suspend = 1;
@@ -878,8 +884,8 @@ static int lm8323_resume(struct i2c_client *client)
 	if (lm->pwm3.enabled)
 		led_classdev_resume(&lm->pwm3.cdev);
 
-	enable_irq(lm->irq);
-	set_irq_wake(lm->irq, 1);
+	enable_irq(client->irq);
+	set_irq_wake(client->irq, 1);
 
 	return 0;
 }
include/linux/i2c/lm8323.h +0 -2
index 5cb09ab..17d6b33 100644
@@ -17,8 +17,6 @@
 #define LM8323_KEYMAP_SIZE (0x7f + 1)
 
 struct lm8323_platform_data {
-	u16 irq_gpio;
-
 	int debounce_time; /* Time to watch for key bouncing, in ms. */
 	int active_time; /* Idle time until sleep, in ms. */
 
Signature · 1 line
1.5.3.6
author maintainer
#11 lore raw

Re: [PATCH 1/2] Input: Fix lm8323 probe and module unloading, take #2

Quoted 49 lines · Tony Lindgren
Quoted 48 lines · Felipe Balbi
Quoted 47 lines · Tony Lindgren

Make module unloading and reloading behave:

- Driver probe could fail if input_register_device fails as no error was returned from probe

- Driver interrupt was using unused platform_data field, change to use i2c platform data interrupt instead

- Free resources on unloading module

- Mark platform data as __init_or_module

---
 arch/arm/mach-omap2/board-n800.c |    2 +-
 drivers/input/keyboard/lm8323.c  |   18 +++++++++++++-----
 include/linux/i2c/lm8323.h       |    2 --
 3 files changed, 14 insertions(+), 8 deletions(-)
arch/arm/mach-omap2/board-n800.c +1 -1
index efcb25d..ae85c2c 100644
@@ -642,7 +642,7 @@ static struct i2c_board_info __initdata n800_i2c_board_info_1[] = {
 
 extern struct tcm825x_platform_data n800_tcm825x_platform_data;
 
-static struct i2c_board_info __initdata n800_i2c_board_info_2[] = {
+static struct i2c_board_info __initdata_or_module n800_i2c_board_info_2[] = {
 #if defined (CONFIG_VIDEO_TCM825X) || defined (CONFIG_VIDEO_TCM825X_MODULE)
 	{
 		I2C_BOARD_INFO(TCM825X_NAME, TCM825X_I2C_ADDR),
drivers/input/keyboard/lm8323.c +1 -3
index e793ae7..d472da0 100644
@@ -755,13 +755,11 @@ static int lm8323_probe(struct i2c_client *client,
 	if (init_pwm(lm, 3, &client->dev, lm8323_pdata->pwm3_name) < 0)
 		goto fail5;
 
-	lm->irq = lm8323_pdata->irq_gpio;
-	debug(&c->dev, "IRQ: %d\n", lm->irq);
-
+	lm->irq = client->irq;
 	mutex_init(&lm->lock);
 	INIT_WORK(&lm->work, lm8323_work);
 
Quoted 7 lines
Quoted 5 lines

drivers/input/keyboard/lm8323.c static int lm8323_probe(struct i2c_client *client, · line 762

Quoted 2 lines
drivers/input/keyboard/lm8323.c +1 -1
-	err = request_irq(client->irq, lm8323_irq,
+	err = request_irq(lm->irq, lm8323_irq,

instead, you could just remove lm->irq field from structure and keep using client->irq.

Good idea, here's an updated patch.

I'll push this first patch only today, the second one still needs more work.

Quoted 153 lines

Tony

From aa1c7706df6f99df31322d297e7142267e237819 Mon Sep 17 00:00:00 2001
From: Tony Lindgren <[email protected]>
Date: Mon, 12 May 2008 22:53:07 -0700
Subject: [PATCH] Input: Fix lm8323 probe and module unloading

Make module unloading and reloading behave:

- Driver probe could fail if input_register_device fails as no error was returned from probe

- Driver interrupt was using unused platform_data field, change to use i2c platform data interrupt instead

- Free resources on unloading module

- Mark platform data as __init_or_module

---
 arch/arm/mach-omap2/board-n800.c |    2 +-
 drivers/input/keyboard/lm8323.c  |   32 +++++++++++++++++++-------------
 include/linux/i2c/lm8323.h       |    2 --
 3 files changed, 20 insertions(+), 16 deletions(-)
arch/arm/mach-omap2/board-n800.c +1 -1
index efcb25d..ae85c2c 100644
@@ -642,7 +642,7 @@ static struct i2c_board_info __initdata n800_i2c_board_info_1[] = {
 
 extern struct tcm825x_platform_data n800_tcm825x_platform_data;
 
-static struct i2c_board_info __initdata n800_i2c_board_info_2[] = {
+static struct i2c_board_info __initdata_or_module n800_i2c_board_info_2[] = {
 #if defined (CONFIG_VIDEO_TCM825X) || defined (CONFIG_VIDEO_TCM825X_MODULE)
 	{
 		I2C_BOARD_INFO(TCM825X_NAME, TCM825X_I2C_ADDR),
drivers/input/keyboard/lm8323.c +19 -13
index e793ae7..72bb587 100644
@@ -150,7 +150,6 @@ struct lm8323_chip {
 	struct i2c_client	*client;
 	struct work_struct	work;
 	struct input_dev	*idev;
-	int			irq;
 	unsigned		kp_enabled : 1;
 	unsigned		pm_suspend : 1;
 	unsigned		keys_down;
@@ -755,9 +754,6 @@ static int lm8323_probe(struct i2c_client *client,
 	if (init_pwm(lm, 3, &client->dev, lm8323_pdata->pwm3_name) < 0)
 		goto fail5;
 
-	lm->irq = lm8323_pdata->irq_gpio;
-	debug(&c->dev, "IRQ: %d\n", lm->irq);
-
 	mutex_init(&lm->lock);
 	INIT_WORK(&lm->work, lm8323_work);
 
@@ -765,11 +761,11 @@ static int lm8323_probe(struct i2c_client *client,
 			  IRQF_TRIGGER_FALLING | IRQF_DISABLED |
 			  IRQF_SAMPLE_RANDOM, DRIVER_NAME, lm);
 	if (err) {
-		dev_err(&client->dev, "could not get IRQ %d\n", lm->irq);
+		dev_err(&client->dev, "could not get IRQ %d\n", client->irq);
 		goto fail6;
 	}
 
-	set_irq_wake(lm->irq, 1);
+	set_irq_wake(client->irq, 1);
 
 	lm->kp_enabled = 1;
 	err = device_create_file(&client->dev, &dev_attr_disable_kp);
@@ -802,7 +798,8 @@ static int lm8323_probe(struct i2c_client *client,
 		set_bit(EV_REP, idev->evbit);
 
 	lm->idev = idev;
-	if (input_register_device(idev)) {
+	err = input_register_device(idev);
+	if (err) {
 		dev_dbg(&client->dev, "error registering input device\n");
 		goto fail8;
 	}
@@ -812,7 +809,7 @@ static int lm8323_probe(struct i2c_client *client,
 fail8:
 	device_remove_file(&client->dev, &dev_attr_disable_kp);
 fail7:
-	free_irq(lm->irq, lm);
+	free_irq(client->irq, lm);
 fail6:
 	if (lm->pwm3.enabled)
 		led_classdev_unregister(&lm->pwm3.cdev);
@@ -832,8 +829,17 @@ static int lm8323_remove(struct i2c_client *client)
 {
 	struct lm8323_chip *lm = i2c_get_clientdata(client);
 
-	free_irq(lm->irq, lm);
+	free_irq(client->irq, lm);
+	cancel_work_sync(&lm->work);
+	input_unregister_device(lm->idev);
 	device_remove_file(&lm->client->dev, &dev_attr_disable_kp);
+	if (lm->pwm3.enabled)
+		led_classdev_unregister(&lm->pwm3.cdev);
+	if (lm->pwm2.enabled)
+		led_classdev_unregister(&lm->pwm2.cdev);
+	if (lm->pwm1.enabled)
+		led_classdev_unregister(&lm->pwm1.cdev);
+	kfree(lm);
 
 	return 0;
 }
@@ -846,8 +852,8 @@ static int lm8323_suspend(struct i2c_client *client, pm_message_t mesg)
 {
 	struct lm8323_chip *lm = i2c_get_clientdata(client);
 
-	set_irq_wake(lm->irq, 0);
-	disable_irq(lm->irq);
+	set_irq_wake(client->irq, 0);
+	disable_irq(client->irq);
 
 	mutex_lock(&lm->lock);
 	lm->pm_suspend = 1;
@@ -878,8 +884,8 @@ static int lm8323_resume(struct i2c_client *client)
 	if (lm->pwm3.enabled)
 		led_classdev_resume(&lm->pwm3.cdev);
 
-	enable_irq(lm->irq);
-	set_irq_wake(lm->irq, 1);
+	enable_irq(client->irq);
+	set_irq_wake(client->irq, 1);
 
 	return 0;
 }
include/linux/i2c/lm8323.h +0 -2
index 5cb09ab..17d6b33 100644
@@ -17,8 +17,6 @@
 #define LM8323_KEYMAP_SIZE (0x7f + 1)
 
 struct lm8323_platform_data {
-	u16 irq_gpio;
-
 	int debounce_time; /* Time to watch for key bouncing, in ms. */
 	int active_time; /* Idle time until sleep, in ms. */
 
Signature · 1 line
1.5.3.6
#12 lore raw
In reply to Tony Lindgren
Quoted 4 lines · ext Tony Lindgren

Here are few fun patches for N810 hackers to make the integrated keyboard work with console :) This should be done in a generic way and the old behaviour is preserved if optional sticky keys are not passed from platform_data.

Uhm. If you're going to implement latching/locking keys, surely it'd be better to do this in the generic input layer than the keyboard driver?

NAK from myself (for what little that means) simply due to the sheer horror of seeing what should, by all rights, be a tiny driver, explode into non-triviality. :)

Cheers,
Daniel

author maintainer
#13 lore raw
Quoted 8 lines · Daniel Stone
Quoted 4 lines · ext Tony Lindgren

Here are few fun patches for N810 hackers to make the integrated keyboard work with console :) This should be done in a generic way and the old behaviour is preserved if optional sticky keys are not passed from platform_data.

Uhm. If you're going to implement latching/locking keys, surely it'd be better to do this in the generic input layer than the keyboard driver?

Yeah I agree it would be best to have the sticky keys handled in the input layer in generic way in the long run. Doing it in a generic ways would just require passing the flags with selected keys to input layer.

Quoted 3 lines

NAK from myself (for what little that means) simply due to the sheer horror of seeing what should, by all rights, be a tiny driver, explode into non-triviality. :)

Well I'll take a look at some point how to move the is_sticky handling to input layer. Meanwhile people can use this patch to have something usable.

Tony

author maintainer
#14 lore raw

Re: [PATCH 0/2] Make N810 keyboard work with console, take #2

Quoted 14 lines · Tony Lindgren
Quoted 8 lines · Daniel Stone
Quoted 4 lines · ext Tony Lindgren

Here are few fun patches for N810 hackers to make the integrated keyboard work with console :) This should be done in a generic way and the old behaviour is preserved if optional sticky keys are not passed from platform_data.

Uhm. If you're going to implement latching/locking keys, surely it'd be better to do this in the generic input layer than the keyboard driver?

Yeah I agree it would be best to have the sticky keys handled in the input layer in generic way in the long run. Doing it in a generic ways would just require passing the flags with selected keys to input layer.

Quoted 7 lines
Quoted 3 lines

NAK from myself (for what little that means) simply due to the sheer horror of seeing what should, by all rights, be a tiny driver, explode into non-triviality. :)

Well I'll take a look at some point how to move the is_sticky handling to input layer. Meanwhile people can use this patch to have something usable.

Here's slightly updated version with Fn + space for tab key. Also added some comments on handling stuff in the input layer.

Tony

Quoted 1 line

From f30e4dc44b563eb3b1dc1207c2099cb345f0752d Mon Sep 17 00:00:00 2001

From: Tony Lindgren <[email protected]>
Date: Wed, 14 May 2008 20:41:44 -0700
Subject: [PATCH] Input: Make lm8323 sticky key to work with console

This allows using N810 keyboard from console by adding optional Fn and shift sticky key handling by passing them from platform_data.

Currently some not so obvious mappings are:

- Pipe is Fn + Enter
- Delete is Fn + Backspace
- Escape is Fn + Ctrl and Fn + Left
- Tab is Fn + Space and Fn + Right

Works also with xserver-xorg-video-fbdev.

Note that the sticky key handling should be moved to the input layer.

---
 arch/arm/mach-omap2/board-n800.c |   87 +++++++++++++++++++++++++++++++++---
 drivers/input/keyboard/lm8323.c  |   89 ++++++++++++++++++++++++++++++++++----
 include/linux/i2c/lm8323.h       |   12 ++---
 3 files changed, 163 insertions(+), 25 deletions(-)
arch/arm/mach-omap2/board-n800.c +79 -8
index ae85c2c..0d73c29 100644
@@ -51,7 +51,16 @@
 #define N800_TSC2301_RESET_GPIO		118
 
 #ifdef CONFIG_MACH_NOKIA_N810
-static s16 rx44_keymap[LM8323_KEYMAP_SIZE] = {
+
+/*
+ * Largest keycode that the chip can send, plus one,
+ * so keys can be mapped directly at the index of the
+ * LM8323 keycode instead of subtracting one.
+ */
+#define N810_HWKEY_SZ			(0x7f + 1)
+
+/* Keymap for lm8323. Negative value means Shift + KEY */
+static s16 rx44_keymap[N810_HWKEY_SZ * 2] = {
 	[0x01] = KEY_Q,
 	[0x02] = KEY_K,
 	[0x03] = KEY_O,
@@ -81,7 +90,7 @@ static s16 rx44_keymap[LM8323_KEYMAP_SIZE] = {
 	[0x21] = KEY_E,
 	[0x22] = KEY_SEMICOLON,
 	[0x23] = KEY_MINUS,
-	[0x24] = KEY_EQUAL,
+	[0x24] = -KEY_EQUAL,
 	[0x2b] = KEY_FN,
 	[0x2c] = KEY_M,
 	[0x2f] = KEY_F8,
@@ -108,15 +117,77 @@ static s16 rx44_keymap[LM8323_KEYMAP_SIZE] = {
 
 	[0x71] = KEY_I,
 	[0x75] = KEY_KPENTER,
+
+	/* End of hardware key map, Fn + key values below */
+
+	[0x01 + N810_HWKEY_SZ] = KEY_1,			/* Fn + KEY_Q */
+	[0x02 + N810_HWKEY_SZ] = -KEY_0,		/* Fn + KEY_K */
+	[0x03 + N810_HWKEY_SZ] = KEY_9,			/* Fn + KEY_O */
+	[0x04 + N810_HWKEY_SZ] = KEY_0,			/* Fn + KEY_P */
+	[0x05 + N810_HWKEY_SZ] = KEY_DELETE,		/* Fn + KEY_BACKSPACE */
+	[0x06 + N810_HWKEY_SZ] = -KEY_1,		/* Fn + KEY_A */
+	[0x07 + N810_HWKEY_SZ] = -KEY_APOSTROPHE,	/* Fn + KEY_S */
+	[0x08 + N810_HWKEY_SZ] = -KEY_2,		/* Fn + KEY_D */
+	[0x09 + N810_HWKEY_SZ] = -KEY_3,		/* Fn + KEY_F */
+	[0x0a + N810_HWKEY_SZ] = KEY_BACKSLASH,		/* Fn + KEY_G */
+	[0x0b + N810_HWKEY_SZ] = KEY_SLASH,		/* Fn + KEY_H */
+	[0x0c + N810_HWKEY_SZ] = -KEY_9,		/* Fn + KEY_J */
+
+	[0x11 + N810_HWKEY_SZ] = KEY_2,			/* Fn + KEY_W */
+	[0x12 + N810_HWKEY_SZ] = KEY_RESERVED,		/* Fn + KEY_F4 */
+	[0x13 + N810_HWKEY_SZ] = -KEY_8,		/* Fn + KEY_L */
+	[0x14 + N810_HWKEY_SZ] = -KEY_SLASH,		/* Fn + KEY_APOSTROPHE */
+	[0x16 + N810_HWKEY_SZ] = KEY_YEN,		/* Fn + KEY_Z */
+	[0x17 + N810_HWKEY_SZ] = -KEY_6,		/* Fn + KEY_X */
+	[0x18 + N810_HWKEY_SZ] = -KEY_GRAVE,		/* Fn + KEY_C */
+	[0x19 + N810_HWKEY_SZ] = -KEY_5,		/* Fn + KEY_V */
+	[0x1a + N810_HWKEY_SZ] = -KEY_7,		/* Fn + KEY_B */
+	[0x1b + N810_HWKEY_SZ] = -KEY_4,		/* Fn + KEY_N */
+	[0x1c + N810_HWKEY_SZ] = KEY_RESERVED,		/* Fn + KEY_LEFTSHIFT */
+	[0x1f + N810_HWKEY_SZ] = KEY_RESERVED,		/* Fn + KEY_F7 */
+
+	[0x21 + N810_HWKEY_SZ] = KEY_3,			/* Fn + KEY_E */
+	[0x22 + N810_HWKEY_SZ] = KEY_RESERVED,		/* Fn + KEY_SEMICOLON */
+	[0x23 + N810_HWKEY_SZ] = -KEY_MINUS,		/* Fn + KEY_MINUS */
+	[0x24 + N810_HWKEY_SZ] = KEY_EQUAL,		/* Fn + -KEY_EQUAL */
+	[0x2b + N810_HWKEY_SZ] = KEY_RESERVED,		/* Fn + KEY_FN */
+	[0x2c + N810_HWKEY_SZ] = KEY_EURO,		/* Fn + KEY_M */
+	[0x2f + N810_HWKEY_SZ] = KEY_RESERVED,		/* Fn + KEY_F8 */
+
+	[0x31 + N810_HWKEY_SZ] = KEY_4,			/* Fn + KEY_R */
+	[0x32 + N810_HWKEY_SZ] = KEY_ESC,		/* Fn + KEY_RIGHTCTRL */
+	[0x34 + N810_HWKEY_SZ] = KEY_TAB,		/* Fn + KEY_SPACE */
+	[0x35 + N810_HWKEY_SZ] = KEY_RESERVED,		/* Fn + KEY_COMMA */
+	[0x37 + N810_HWKEY_SZ] = KEY_PAGEUP,		/* Fn + KEY_UP */
+	[0x3c + N810_HWKEY_SZ] = KEY_RESERVED,		/* Fn + KEY_COMPOSE */
+	[0x3f + N810_HWKEY_SZ] = KEY_RESERVED,		/* Fn + KEY_F6 */
+
+	[0x41 + N810_HWKEY_SZ] = KEY_5,			/* Fn + KEY_T */
+	[0x44 + N810_HWKEY_SZ] = KEY_RESERVED,		/* Fn + KEY_DOT */
+	[0x46 + N810_HWKEY_SZ] = KEY_TAB,		/* Fn + KEY_RIGHT */
+	[0x4f + N810_HWKEY_SZ] = KEY_RESERVED,		/* Fn + KEY_F5 */
+	[0x51 + N810_HWKEY_SZ] = KEY_6,			/* Fn + KEY_Y */
+	[0x53 + N810_HWKEY_SZ] = KEY_PAGEDOWN,		/* Fn + KEY_DOWN */
+	[0x55 + N810_HWKEY_SZ] = -KEY_BACKSLASH,	/* Fn + KEY_ENTER */
+	[0x5f + N810_HWKEY_SZ] = KEY_RESERVED,		/* Fn + KEY_ESC */
+
+	[0x61 + N810_HWKEY_SZ] = KEY_7,			/* Fn + KEY_U */
+	[0x64 + N810_HWKEY_SZ] = KEY_ESC,		/* Fn + KEY_LEFT */
+
+	[0x71 + N810_HWKEY_SZ] = KEY_8,			/* Fn + KEY_I */
+	[0x75 + N810_HWKEY_SZ] = KEY_RESERVED,		/* Fn + KEY_KPENTER */
 };
 
 static struct lm8323_platform_data lm8323_pdata = {
-	.repeat = 0, /* Repeat is handled in userspace for now. */
-	.keymap = rx44_keymap,
-
-	.name = "Internal keyboard",
-	.pwm1_name = "keyboard",
-	.pwm2_name = "cover",
+	.repeat		= 1, /* Change to 0 if handled in userspace */
+	.keymap		= rx44_keymap,
+	.keymap_sz	= ARRAY_SIZE(rx44_keymap),
+	.fn_key		= KEY_FN,
+	.shift_key	= KEY_LEFTSHIFT,
+
+	.name		= "Internal keyboard",
+	.pwm1_name	= "keyboard",
+	.pwm2_name	= "cover",
 };
 #endif
 
drivers/input/keyboard/lm8323.c +80 -9

123 lines not on this page · raw message

include/linux/i2c/lm8323.h +4 -8
index 17d6b33..5ea6cef 100644
@@ -9,13 +9,6 @@
 
 #include <linux/types.h>
 
-/*
- * Largest keycode that the chip can send, plus one,
- * so keys can be mapped directly at the index of the
- * LM8323 keycode instead of subtracting one.
- */
-#define LM8323_KEYMAP_SIZE (0x7f + 1)
-
 struct lm8323_platform_data {
 	int debounce_time; /* Time to watch for key bouncing, in ms. */
 	int active_time; /* Idle time until sleep, in ms. */
@@ -23,7 +16,10 @@ struct lm8323_platform_data {
 	int size_x;
 	int size_y;
 	int repeat : 1;
-	const s16 *keymap;
+	s16 *keymap;
+	u16 keymap_sz;
+	u16 fn_key;
+	u16 shift_key;
 
 	char *pwm1_name; /* Device name for PWM1. */
 	char *pwm2_name; /* Device name for PWM2. */
Signature · 1 line
1.5.3.6