]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
ARM: OMAP: Update OMAP keypad driver
authorHiroshi DOYU <hiroshi.doyu@nokia.com>
Sun, 12 Feb 2006 10:50:18 +0000 (12:50 +0200)
committerJuha Yrjola <juha.yrjola@nokia.com>
Sun, 12 Feb 2006 10:50:18 +0000 (12:50 +0200)
- Prevent ghost key presses on OMAP1
- Add sysfs attribute for enabling/disabling the keypad IRQ

Signed-off-by: Hiroshi DOYU <hiroshi.doyu@nokia.com>
Signed-off-by: Juha Yrjölä <juha.yrjola@nokia.com>
arch/arm/mach-omap1/board-nokia770.c
drivers/input/keyboard/omap-keypad.c
include/asm-arm/arch-omap/keypad.h

index 90f794e7c461f5d51b39c5abf2bd8b595155a18a..2c583d1949a40df8feb05fbc621570b52c2cd942 100644 (file)
@@ -35,17 +35,17 @@ static void __init omap_nokia770_init_irq(void)
 }
 
 static int nokia770_keymap[] = {
-       KEY(0, 1, KEY_UP),
-       KEY(0, 2, KEY_F5),
-       KEY(1, 0, KEY_LEFT),
-       KEY(1, 1, KEY_ENTER),
-       KEY(1, 2, KEY_RIGHT),
-       KEY(2, 0, KEY_ESC),
-       KEY(2, 1, KEY_DOWN),
-       KEY(2, 2, KEY_F4),
-       KEY(3, 0, KEY_F7),
-       KEY(3, 1, KEY_F8),
-       KEY(3, 2, KEY_F6),
+       KEY(0, 1, GROUP_0 | KEY_UP),
+       KEY(0, 2, GROUP_1 | KEY_F5),
+       KEY(1, 0, GROUP_0 | KEY_LEFT),
+       KEY(1, 1, GROUP_0 | KEY_ENTER),
+       KEY(1, 2, GROUP_0 | KEY_RIGHT),
+       KEY(2, 0, GROUP_1 | KEY_ESC),
+       KEY(2, 1, GROUP_0 | KEY_DOWN),
+       KEY(2, 2, GROUP_1 | KEY_F4),
+       KEY(3, 0, GROUP_2 | KEY_F7),
+       KEY(3, 1, GROUP_2 | KEY_F8),
+       KEY(3, 2, GROUP_2 | KEY_F6),
        0
 };
 
index 66ee31f277c524f32ec33d5849e9980a44d5ca58..1ad96b706cbf82524ee20613d160308ae815325c 100644 (file)
@@ -48,6 +48,9 @@ static void omap_kp_tasklet(unsigned long);
 static void omap_kp_timer(unsigned long);
 
 static unsigned char keypad_state[8];
+static DECLARE_MUTEX(kp_enable_mutex);
+static int kp_enable = 1;
+static int kp_cur_group = -1;
 
 struct omap_kp {
        struct input_dev *input;
@@ -213,6 +216,11 @@ static void omap_kp_tasklet(unsigned long data)
                                continue;
                        }
 
+                       if (!(kp_cur_group == (key & GROUP_MASK) ||
+                             kp_cur_group == -1))
+                               continue;
+
+                       kp_cur_group = key & GROUP_MASK;
                        input_report_key(omap_kp_data->input, key,
                                         new_state[col] & (1 << row));
 #endif
@@ -235,10 +243,43 @@ static void omap_kp_tasklet(unsigned long data)
                                enable_irq(OMAP_GPIO_IRQ(row_gpios[i]));
                } else {
                        omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+                       kp_cur_group = -1;
                }
        }
 }
 
+static ssize_t omap_kp_enable_show(struct device *dev, 
+                                  struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%u\n", kp_enable);
+}
+
+static ssize_t omap_kp_enable_store(struct device *dev, struct device_attribute *attr,
+                                   const char *buf, size_t count)
+{
+       int state;
+
+       if (sscanf(buf, "%u", &state) != 1)
+               return -EINVAL;
+
+       if ((state != 1) && (state != 0))
+               return -EINVAL;
+
+       down(&kp_enable_mutex);
+       if (state != kp_enable) {
+               if (state)
+                       enable_irq(INT_KEYBOARD);
+               else
+                       disable_irq(INT_KEYBOARD);
+               kp_enable = state;
+       }
+       up(&kp_enable_mutex);
+
+       return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, omap_kp_enable_show, omap_kp_enable_store);
+
 #ifdef CONFIG_PM
 static int omap_kp_suspend(struct platform_device *dev, pm_message_t state)
 {
@@ -299,12 +340,6 @@ static int __init omap_kp_probe(struct platform_device *pdev)
                col_gpios = pdata->col_gpios;
        }
 
-       if (cpu_is_omap24xx() && omap_has_menelaus()) {
-               row_gpios[5] = 0;
-               col_gpios[2] = 15;
-               col_gpios[6] = 18;
-       }
-
        omap_kp->rows = pdata->rows;
        omap_kp->cols = pdata->cols;
 
@@ -313,8 +348,8 @@ static int __init omap_kp_probe(struct platform_device *pdev)
                for (i = 0; i < omap_kp->cols; i++) {
                        if (omap_request_gpio(col_gpios[i]) < 0) {
                                printk(KERN_ERR "Failed to request"
-          "GPIO%d for keypad\n",
-          col_gpios[i]);
+                                      "GPIO%d for keypad\n",
+                                      col_gpios[i]);
                                return -EINVAL;
                        }
                        omap_set_gpio_direction(col_gpios[i], 0);
@@ -323,8 +358,8 @@ static int __init omap_kp_probe(struct platform_device *pdev)
                for (i = 0; i < omap_kp->rows; i++) {
                        if (omap_request_gpio(row_gpios[i]) < 0) {
                                printk(KERN_ERR "Failed to request"
-          "GPIO%d for keypad\n",
-          row_gpios[i]);
+                                      "GPIO%d for keypad\n",
+                                      row_gpios[i]);
                                return -EINVAL;
                        }
                        omap_set_gpio_direction(row_gpios[i], 1);
@@ -346,6 +381,8 @@ static int __init omap_kp_probe(struct platform_device *pdev)
                        return -EINVAL;
        }
 
+       device_create_file(&pdev->dev, &dev_attr_enable);
+
        /* setup input device */
        set_bit(EV_KEY, input_dev->evbit);
        for (i = 0; keymap[i] != 0; i++)
index 0d90b4f11ab0a73dbd31b28992068284f2c5a391..548515d503e8eaf97ea2f5e368bd006ce871cf85 100644 (file)
@@ -20,6 +20,16 @@ struct omap_kp_platform_data {
        unsigned int *col_gpios;
 };
 
+/* Group (0..3) -- when multiple keys are pressed, only the
+ * keys pressed in the same group are considered as pressed. This is
+ * in order to workaround certain crappy HW designs that produce ghost
+ * keypresses. */
+#define GROUP_0                (0 << 10)
+#define GROUP_1                (1 << 10)
+#define GROUP_2                (2 << 10)
+#define GROUP_3                (3 << 10)
+#define GROUP_MASK     GROUP_3
+
 #define KEY(col, row, val) (((col) << 28) | ((row) << 24) | (val))
 
 #endif