public inbox for linux-omap@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] Make N810 keyboard work with console
@ 2008-05-15  4:01 Tony Lindgren
  2008-05-15  4:01 ` [PATCH 1/2] Input: Fix lm8323 probe and module unloading Tony Lindgren
  2008-05-15  8:58 ` [PATCH 0/2] Make N810 keyboard work with console Daniel Stone
  0 siblings, 2 replies; 14+ messages in thread
From: Tony Lindgren @ 2008-05-15  4:01 UTC (permalink / raw)
  To: linux-omap; +Cc: daniel.stone, Tony Lindgren

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


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/2] Input: Fix lm8323 probe and module unloading
  2008-05-15  4:01 [PATCH 0/2] Make N810 keyboard work with console Tony Lindgren
@ 2008-05-15  4:01 ` Tony Lindgren
  2008-05-15  4:01   ` [PATCH 2/2] Input: Make lm8323 sticky key to work with console Tony Lindgren
  2008-05-15  8:01   ` [PATCH 1/2] Input: Fix lm8323 probe and module unloading Felipe Balbi
  2008-05-15  8:58 ` [PATCH 0/2] Make N810 keyboard work with console Daniel Stone
  1 sibling, 2 replies; 14+ messages in thread
From: Tony Lindgren @ 2008-05-15  4:01 UTC (permalink / raw)
  To: linux-omap; +Cc: daniel.stone, 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

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 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(-)

diff --git a/arch/arm/mach-omap2/board-n800.c b/arch/arm/mach-omap2/board-n800.c
index efcb25d..ae85c2c 100644
--- a/arch/arm/mach-omap2/board-n800.c
+++ b/arch/arm/mach-omap2/board-n800.c
@@ -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),
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
index e793ae7..d472da0 100644
--- a/drivers/input/keyboard/lm8323.c
+++ b/drivers/input/keyboard/lm8323.c
@@ -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;
 }
diff --git a/include/linux/i2c/lm8323.h b/include/linux/i2c/lm8323.h
index 5cb09ab..17d6b33 100644
--- a/include/linux/i2c/lm8323.h
+++ b/include/linux/i2c/lm8323.h
@@ -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. */
 
-- 
1.5.3.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/2] Input: Make lm8323 sticky key to work with console
  2008-05-15  4:01 ` [PATCH 1/2] Input: Fix lm8323 probe and module unloading Tony Lindgren
@ 2008-05-15  4:01   ` Tony Lindgren
  2008-05-15  8:03     ` Felipe Balbi
  2008-05-15  8:01   ` [PATCH 1/2] Input: Fix lm8323 probe and module unloading Felipe Balbi
  1 sibling, 1 reply; 14+ messages in thread
From: Tony Lindgren @ 2008-05-15  4:01 UTC (permalink / raw)
  To: linux-omap; +Cc: daniel.stone, 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

Works also with xserver-xorg-video-fbdev.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 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(-)

diff --git a/arch/arm/mach-omap2/board-n800.c b/arch/arm/mach-omap2/board-n800.c
index ae85c2c..a654886 100644
--- a/arch/arm/mach-omap2/board-n800.c
+++ b/arch/arm/mach-omap2/board-n800.c
@@ -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
 
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
index d472da0..485c19f 100644
--- a/drivers/input/keyboard/lm8323.c
+++ b/drivers/input/keyboard/lm8323.c
@@ -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)
diff --git a/include/linux/i2c/lm8323.h b/include/linux/i2c/lm8323.h
index 17d6b33..5ea6cef 100644
--- a/include/linux/i2c/lm8323.h
+++ b/include/linux/i2c/lm8323.h
@@ -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. */
-- 
1.5.3.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] Input: Fix lm8323 probe and module unloading
  2008-05-15  4:01 ` [PATCH 1/2] Input: Fix lm8323 probe and module unloading Tony Lindgren
  2008-05-15  4:01   ` [PATCH 2/2] Input: Make lm8323 sticky key to work with console Tony Lindgren
@ 2008-05-15  8:01   ` Felipe Balbi
  2008-05-15 18:18     ` [PATCH 1/2] Input: Fix lm8323 probe and module unloading, take #2 Tony Lindgren
  1 sibling, 1 reply; 14+ messages in thread
From: Felipe Balbi @ 2008-05-15  8:01 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-omap, daniel.stone

On Wed, May 14, 2008 at 09:01:18PM -0700, Tony Lindgren wrote:
> 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
> 
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
>  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(-)
> 
> diff --git a/arch/arm/mach-omap2/board-n800.c b/arch/arm/mach-omap2/board-n800.c
> index efcb25d..ae85c2c 100644
> --- a/arch/arm/mach-omap2/board-n800.c
> +++ b/arch/arm/mach-omap2/board-n800.c
> @@ -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),
> diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
> index e793ae7..d472da0 100644
> --- a/drivers/input/keyboard/lm8323.c
> +++ b/drivers/input/keyboard/lm8323.c
> @@ -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,

instead, you could just remove lm->irq field from structure and keep
using client->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;
>  }
> diff --git a/include/linux/i2c/lm8323.h b/include/linux/i2c/lm8323.h
> index 5cb09ab..17d6b33 100644
> --- a/include/linux/i2c/lm8323.h
> +++ b/include/linux/i2c/lm8323.h
> @@ -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. */
>  
> -- 
> 1.5.3.6
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Best Regards,

Felipe Balbi
me@felipebalbi.com
http://blog.felipebalbi.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/2] Input: Make lm8323 sticky key to work with console
  2008-05-15  4:01   ` [PATCH 2/2] Input: Make lm8323 sticky key to work with console Tony Lindgren
@ 2008-05-15  8:03     ` Felipe Balbi
  2008-05-15  8:14       ` andrzej zaborowski
  0 siblings, 1 reply; 14+ messages in thread
From: Felipe Balbi @ 2008-05-15  8:03 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-omap, daniel.stone

On Wed, May 14, 2008 at 09:01:19PM -0700, Tony Lindgren wrote:
> 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

> 
> Works also with xserver-xorg-video-fbdev.
> 
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
>  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(-)
> 
> diff --git a/arch/arm/mach-omap2/board-n800.c b/arch/arm/mach-omap2/board-n800.c
> index ae85c2c..a654886 100644
> --- a/arch/arm/mach-omap2/board-n800.c
> +++ b/arch/arm/mach-omap2/board-n800.c
> @@ -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
>  
> diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
> index d472da0..485c19f 100644
> --- a/drivers/input/keyboard/lm8323.c
> +++ b/drivers/input/keyboard/lm8323.c
> @@ -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)
> diff --git a/include/linux/i2c/lm8323.h b/include/linux/i2c/lm8323.h
> index 17d6b33..5ea6cef 100644
> --- a/include/linux/i2c/lm8323.h
> +++ b/include/linux/i2c/lm8323.h
> @@ -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. */
> -- 
> 1.5.3.6
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Best Regards,

Felipe Balbi
me@felipebalbi.com
http://blog.felipebalbi.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/2] Input: Make lm8323 sticky key to work with console
  2008-05-15  8:03     ` Felipe Balbi
@ 2008-05-15  8:14       ` andrzej zaborowski
  2008-05-15  8:20         ` Felipe Balbi
  0 siblings, 1 reply; 14+ messages in thread
From: andrzej zaborowski @ 2008-05-15  8:14 UTC (permalink / raw)
  To: me; +Cc: Tony Lindgren, linux-omap, daniel.stone

On 15/05/2008, Felipe Balbi <me@felipebalbi.com> wrote:
> On Wed, May 14, 2008 at 09:01:19PM -0700, Tony Lindgren wrote:
>  > 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

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
-- 
Please do not print this email unless absolutely necessary. Spread
environmental awareness.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/2] Input: Make lm8323 sticky key to work with console
  2008-05-15  8:14       ` andrzej zaborowski
@ 2008-05-15  8:20         ` Felipe Balbi
  2008-05-15  8:29           ` Tony Lindgren
  0 siblings, 1 reply; 14+ messages in thread
From: Felipe Balbi @ 2008-05-15  8:20 UTC (permalink / raw)
  To: andrzej zaborowski; +Cc: me, Tony Lindgren, linux-omap, daniel.stone

On Thu, May 15, 2008 at 10:14:24AM +0200, andrzej zaborowski wrote:
> On 15/05/2008, Felipe Balbi <me@felipebalbi.com> wrote:
> > On Wed, May 14, 2008 at 09:01:19PM -0700, Tony Lindgren wrote:
> >  > 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
> 
> 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.

-- 
Best Regards,

Felipe Balbi
me@felipebalbi.com
http://blog.felipebalbi.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/2] Input: Make lm8323 sticky key to work with console
  2008-05-15  8:20         ` Felipe Balbi
@ 2008-05-15  8:29           ` Tony Lindgren
  2008-05-15  8:31             ` Tony Lindgren
  0 siblings, 1 reply; 14+ messages in thread
From: Tony Lindgren @ 2008-05-15  8:29 UTC (permalink / raw)
  To: Felipe Balbi; +Cc: andrzej zaborowski, linux-omap, daniel.stone

* Felipe Balbi <me@felipebalbi.com> [080515 01:19]:
> On Thu, May 15, 2008 at 10:14:24AM +0200, andrzej zaborowski wrote:
> > On 15/05/2008, Felipe Balbi <me@felipebalbi.com> wrote:
> > > On Wed, May 14, 2008 at 09:01:19PM -0700, Tony Lindgren wrote:
> > >  > 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
> > 
> > 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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/2] Input: Make lm8323 sticky key to work with console
  2008-05-15  8:29           ` Tony Lindgren
@ 2008-05-15  8:31             ` Tony Lindgren
  0 siblings, 0 replies; 14+ messages in thread
From: Tony Lindgren @ 2008-05-15  8:31 UTC (permalink / raw)
  To: Felipe Balbi; +Cc: andrzej zaborowski, linux-omap, daniel.stone

* Tony Lindgren <tony@atomide.com> [080515 01:30]:
> * Felipe Balbi <me@felipebalbi.com> [080515 01:19]:
> > On Thu, May 15, 2008 at 10:14:24AM +0200, andrzej zaborowski wrote:
> > > On 15/05/2008, Felipe Balbi <me@felipebalbi.com> wrote:
> > > > On Wed, May 14, 2008 at 09:01:19PM -0700, Tony Lindgren wrote:
> > > >  > 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
> > > 
> > > 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.

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

Tony

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/2] Make N810 keyboard work with console
  2008-05-15  4:01 [PATCH 0/2] Make N810 keyboard work with console Tony Lindgren
  2008-05-15  4:01 ` [PATCH 1/2] Input: Fix lm8323 probe and module unloading Tony Lindgren
@ 2008-05-15  8:58 ` Daniel Stone
  2008-05-15 17:22   ` Tony Lindgren
  1 sibling, 1 reply; 14+ messages in thread
From: Daniel Stone @ 2008-05-15  8:58 UTC (permalink / raw)
  To: ext Tony Lindgren; +Cc: linux-omap

[-- Attachment #1: Type: text/plain, Size: 627 bytes --]

On Wed, May 14, 2008 at 09:01:17PM -0700, ext Tony Lindgren wrote:
> 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

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/2] Make N810 keyboard work with console
  2008-05-15  8:58 ` [PATCH 0/2] Make N810 keyboard work with console Daniel Stone
@ 2008-05-15 17:22   ` Tony Lindgren
  2008-05-15 18:19     ` [PATCH 0/2] Make N810 keyboard work with console, take #2 Tony Lindgren
  0 siblings, 1 reply; 14+ messages in thread
From: Tony Lindgren @ 2008-05-15 17:22 UTC (permalink / raw)
  To: Daniel Stone; +Cc: linux-omap

* Daniel Stone <daniel.stone@nokia.com> [080515 01:57]:
> On Wed, May 14, 2008 at 09:01:17PM -0700, ext Tony Lindgren wrote:
> > 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.

> 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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] Input: Fix lm8323 probe and module unloading, take #2
  2008-05-15  8:01   ` [PATCH 1/2] Input: Fix lm8323 probe and module unloading Felipe Balbi
@ 2008-05-15 18:18     ` Tony Lindgren
  2008-05-15 22:54       ` Tony Lindgren
  0 siblings, 1 reply; 14+ messages in thread
From: Tony Lindgren @ 2008-05-15 18:18 UTC (permalink / raw)
  To: Felipe Balbi; +Cc: linux-omap, daniel.stone

[-- Attachment #1: Type: text/plain, Size: 2255 bytes --]

* Felipe Balbi <me@felipebalbi.com> [080515 01:00]:
> On Wed, May 14, 2008 at 09:01:18PM -0700, Tony Lindgren wrote:
> > 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
> > 
> > Signed-off-by: Tony Lindgren <tony@atomide.com>
> > ---
> >  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(-)
> > 
> > diff --git a/arch/arm/mach-omap2/board-n800.c b/arch/arm/mach-omap2/board-n800.c
> > index efcb25d..ae85c2c 100644
> > --- a/arch/arm/mach-omap2/board-n800.c
> > +++ b/arch/arm/mach-omap2/board-n800.c
> > @@ -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),
> > diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
> > index e793ae7..d472da0 100644
> > --- a/drivers/input/keyboard/lm8323.c
> > +++ b/drivers/input/keyboard/lm8323.c
> > @@ -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,
> 
> instead, you could just remove lm->irq field from structure and keep
> using client->irq.

Good idea, here's an updated patch.

Tony


[-- Attachment #2: 0006-Input-Fix-lm8323-probe-and-module-unloading.patch --]
[-- Type: text/x-diff, Size: 4708 bytes --]

>From aa1c7706df6f99df31322d297e7142267e237819 Mon Sep 17 00:00:00 2001
From: Tony Lindgren <tony@atomide.com>
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

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 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(-)

diff --git a/arch/arm/mach-omap2/board-n800.c b/arch/arm/mach-omap2/board-n800.c
index efcb25d..ae85c2c 100644
--- a/arch/arm/mach-omap2/board-n800.c
+++ b/arch/arm/mach-omap2/board-n800.c
@@ -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),
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
index e793ae7..72bb587 100644
--- a/drivers/input/keyboard/lm8323.c
+++ b/drivers/input/keyboard/lm8323.c
@@ -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;
 }
diff --git a/include/linux/i2c/lm8323.h b/include/linux/i2c/lm8323.h
index 5cb09ab..17d6b33 100644
--- a/include/linux/i2c/lm8323.h
+++ b/include/linux/i2c/lm8323.h
@@ -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. */
 
-- 
1.5.3.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/2] Make N810 keyboard work with console, take #2
  2008-05-15 17:22   ` Tony Lindgren
@ 2008-05-15 18:19     ` Tony Lindgren
  0 siblings, 0 replies; 14+ messages in thread
From: Tony Lindgren @ 2008-05-15 18:19 UTC (permalink / raw)
  To: Daniel Stone; +Cc: linux-omap

[-- Attachment #1: Type: text/plain, Size: 1276 bytes --]

* Tony Lindgren <tony@atomide.com> [080515 10:22]:
> * Daniel Stone <daniel.stone@nokia.com> [080515 01:57]:
> > On Wed, May 14, 2008 at 09:01:17PM -0700, ext Tony Lindgren wrote:
> > > 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.
> 
> > 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

[-- Attachment #2: 0007-Input-Make-lm8323-sticky-key-to-work-with-console.patch --]
[-- Type: text/x-diff, Size: 9871 bytes --]

>From f30e4dc44b563eb3b1dc1207c2099cb345f0752d Mon Sep 17 00:00:00 2001
From: Tony Lindgren <tony@atomide.com>
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.

Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 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(-)

diff --git a/arch/arm/mach-omap2/board-n800.c b/arch/arm/mach-omap2/board-n800.c
index ae85c2c..0d73c29 100644
--- a/arch/arm/mach-omap2/board-n800.c
+++ b/arch/arm/mach-omap2/board-n800.c
@@ -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
 
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
index 72bb587..929edbe 100644
--- a/drivers/input/keyboard/lm8323.c
+++ b/drivers/input/keyboard/lm8323.c
@@ -154,7 +154,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;
@@ -278,6 +290,45 @@ static inline int lm8323_ispress(u8 event)
 	return (event & 0x80) ? 1 : 0;
 }
 
+/*
+ * REVISIT: The sticky handling should be done in more generic ways in
+ * the input layer
+ */
+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;
@@ -299,10 +350,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");
@@ -706,8 +776,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. */
@@ -787,12 +861,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)
 		set_bit(EV_REP, idev->evbit);
diff --git a/include/linux/i2c/lm8323.h b/include/linux/i2c/lm8323.h
index 17d6b33..5ea6cef 100644
--- a/include/linux/i2c/lm8323.h
+++ b/include/linux/i2c/lm8323.h
@@ -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. */
-- 
1.5.3.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] Input: Fix lm8323 probe and module unloading, take #2
  2008-05-15 18:18     ` [PATCH 1/2] Input: Fix lm8323 probe and module unloading, take #2 Tony Lindgren
@ 2008-05-15 22:54       ` Tony Lindgren
  0 siblings, 0 replies; 14+ messages in thread
From: Tony Lindgren @ 2008-05-15 22:54 UTC (permalink / raw)
  To: Felipe Balbi; +Cc: linux-omap, daniel.stone

* Tony Lindgren <tony@atomide.com> [080515 11:20]:
> * Felipe Balbi <me@felipebalbi.com> [080515 01:00]:
> > On Wed, May 14, 2008 at 09:01:18PM -0700, Tony Lindgren wrote:
> > > 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
> > > 
> > > Signed-off-by: Tony Lindgren <tony@atomide.com>
> > > ---
> > >  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(-)
> > > 
> > > diff --git a/arch/arm/mach-omap2/board-n800.c b/arch/arm/mach-omap2/board-n800.c
> > > index efcb25d..ae85c2c 100644
> > > --- a/arch/arm/mach-omap2/board-n800.c
> > > +++ b/arch/arm/mach-omap2/board-n800.c
> > > @@ -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),
> > > diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
> > > index e793ae7..d472da0 100644
> > > --- a/drivers/input/keyboard/lm8323.c
> > > +++ b/drivers/input/keyboard/lm8323.c
> > > @@ -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,
> > 
> > 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.

> 
> Tony
> 

> From aa1c7706df6f99df31322d297e7142267e237819 Mon Sep 17 00:00:00 2001
> From: Tony Lindgren <tony@atomide.com>
> 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
> 
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> ---
>  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(-)
> 
> diff --git a/arch/arm/mach-omap2/board-n800.c b/arch/arm/mach-omap2/board-n800.c
> index efcb25d..ae85c2c 100644
> --- a/arch/arm/mach-omap2/board-n800.c
> +++ b/arch/arm/mach-omap2/board-n800.c
> @@ -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),
> diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
> index e793ae7..72bb587 100644
> --- a/drivers/input/keyboard/lm8323.c
> +++ b/drivers/input/keyboard/lm8323.c
> @@ -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;
>  }
> diff --git a/include/linux/i2c/lm8323.h b/include/linux/i2c/lm8323.h
> index 5cb09ab..17d6b33 100644
> --- a/include/linux/i2c/lm8323.h
> +++ b/include/linux/i2c/lm8323.h
> @@ -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. */
>  
> -- 
> 1.5.3.6
> 


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2008-05-15 22:54 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-05-15  4:01 [PATCH 0/2] Make N810 keyboard work with console Tony Lindgren
2008-05-15  4:01 ` [PATCH 1/2] Input: Fix lm8323 probe and module unloading Tony Lindgren
2008-05-15  4:01   ` [PATCH 2/2] Input: Make lm8323 sticky key to work with console Tony Lindgren
2008-05-15  8:03     ` Felipe Balbi
2008-05-15  8:14       ` andrzej zaborowski
2008-05-15  8:20         ` Felipe Balbi
2008-05-15  8:29           ` Tony Lindgren
2008-05-15  8:31             ` Tony Lindgren
2008-05-15  8:01   ` [PATCH 1/2] Input: Fix lm8323 probe and module unloading Felipe Balbi
2008-05-15 18:18     ` [PATCH 1/2] Input: Fix lm8323 probe and module unloading, take #2 Tony Lindgren
2008-05-15 22:54       ` Tony Lindgren
2008-05-15  8:58 ` [PATCH 0/2] Make N810 keyboard work with console Daniel Stone
2008-05-15 17:22   ` Tony Lindgren
2008-05-15 18:19     ` [PATCH 0/2] Make N810 keyboard work with console, take #2 Tony Lindgren

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox