diff options
Diffstat (limited to 'packages/linux/linux-rp-2.6.23/tosa-keyboard-r19.patch')
-rw-r--r-- | packages/linux/linux-rp-2.6.23/tosa-keyboard-r19.patch | 514 |
1 files changed, 0 insertions, 514 deletions
diff --git a/packages/linux/linux-rp-2.6.23/tosa-keyboard-r19.patch b/packages/linux/linux-rp-2.6.23/tosa-keyboard-r19.patch index 5d94f25527..948c27fdce 100644 --- a/packages/linux/linux-rp-2.6.23/tosa-keyboard-r19.patch +++ b/packages/linux/linux-rp-2.6.23/tosa-keyboard-r19.patch @@ -512,517 +512,3 @@ Index: git/drivers/input/keyboard/tosakbd.c +MODULE_AUTHOR("Dirk Opfer <Dirk@Opfer-Online.de>"); +MODULE_DESCRIPTION("Tosa Keyboard Driver"); +MODULE_LICENSE("GPLv2"); - drivers/input/keyboard/Kconfig | 12 - - drivers/input/keyboard/Makefile | 1 - drivers/input/keyboard/tosakbd.c | 467 +++++++++++++++++++++++++++++++++++++++ - 3 files changed, 479 insertions(+), 1 deletion(-) - -Index: git/drivers/input/keyboard/Kconfig -=================================================================== ---- git.orig/drivers/input/keyboard/Kconfig 2006-10-31 16:08:57.000000000 +0000 -+++ git/drivers/input/keyboard/Kconfig 2006-11-07 22:13:10.000000000 +0000 -@@ -148,12 +148,22 @@ config KEYBOARD_SPITZ - depends on PXA_SHARPSL - default y - help -- Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, -+ Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, - SL-C3000 and Sl-C3100 series of PDAs. - - To compile this driver as a module, choose M here: the - module will be called spitzkbd. - -+config KEYBOARD_TOSA -+ tristate "Tosa keyboard" -+ depends on PXA_SHARPSL -+ default y -+ help -+ Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) -+ -+ To compile this driver as a module, choose M here: the -+ module will be called tosakbd. -+ - config KEYBOARD_AMIGA - tristate "Amiga keyboard" - depends on AMIGA -Index: git/drivers/input/keyboard/Makefile -=================================================================== ---- git.orig/drivers/input/keyboard/Makefile 2006-10-31 16:08:57.000000000 +0000 -+++ git/drivers/input/keyboard/Makefile 2006-11-07 22:13:10.000000000 +0000 -@@ -17,3 +17,4 @@ obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkb - obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o - obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o - obj-$(CONFIG_KEYBOARD_ASIC3) += asic3_keys.o -+obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o -Index: git/drivers/input/keyboard/tosakbd.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ git/drivers/input/keyboard/tosakbd.c 2006-11-07 23:27:19.000000000 +0000 -@@ -0,0 +1,467 @@ -+/* -+ * Keyboard driver for Sharp Tosa models (SL-6000x) -+ * -+ * Copyright (c) 2005 Dirk Opfer -+ * -+ * Based on xtkbd.c/locomkbd.c/corgikbd.c -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/delay.h> -+#include <linux/platform_device.h> -+#include <linux/init.h> -+#include <linux/input.h> -+#include <linux/interrupt.h> -+#include <linux/jiffies.h> -+#include <linux/module.h> -+#include <linux/slab.h> -+ -+#include <asm/arch/tosa.h> -+#include <asm/arch/hardware.h> -+#include <asm/arch/pxa-regs.h> -+ -+ -+#define TOSA_KEY_STROBE_NUM (11) -+#define TOSA_KEY_SENSE_NUM (7) -+ -+#define KEYMASK_ON (0x1<<0) -+#define KEYMASK_REC (0x1<<1) -+#define KEYMASK_SYNC (0x1<<2) -+ -+#define KB_ROWS 7 -+#define KB_COLS 11 -+#define KB_ROWMASK(r) (1 << (r)) -+#define SCANCODE(r,c) ( ((r)<<4) + (c) + 1 ) -+#define NR_SCANCODES (SCANCODE(KB_ROWS-1,KB_COLS)+1+1) -+ -+#define SCAN_INTERVAL (HZ/10) -+#define HP_SCAN_INTERVAL (150) /* ms */ -+#define HP_STABLE_COUNT 2 -+ -+#define TOSA_KEY_CALENDER KEY_F1 -+#define TOSA_KEY_ADDRESS KEY_F2 -+#define TOSA_KEY_FN KEY_F3 -+#define TOSA_KEY_CANCEL KEY_F4 -+#define TOSA_KEY_OFF KEY_SUSPEND -+#define TOSA_KEY_CENTER KEY_F5 -+#define TOSA_KEY_REC KEY_F6 -+#define TOSA_KEY_LIGHT KEY_F7 -+#define TOSA_KEY_RECORD KEY_F8 -+#define TOSA_KEY_HOME KEY_F9 -+#define TOSA_KEY_MAIL KEY_F10 -+#define TOSA_KEY_OK KEY_F11 -+#define TOSA_KEY_MENU KEY_F12 -+#define TOSA_KEY_SYNC KEY_F13 -+ -+#define GET_ROWS_STATUS(c) ((GPLR2 & TOSA_GPIO_ALL_SENSE_BIT) >> TOSA_GPIO_ALL_SENSE_RSHIFT) -+#define KB_DISCHARGE_DELAY 10 -+#define KB_ACTIVATE_DELAY 10 -+ -+ -+static unsigned char tosakbd_keycode[NR_SCANCODES] = { -+ 0, /* 0 */ -+ 0, KEY_W, 0, 0, 0, KEY_K, KEY_BACKSPACE, KEY_P, 0, 0, 0, TOSA_KEY_OFF, 0, 0, 0, 0, /*1 - 16*/ -+ KEY_Q, KEY_E, KEY_T, KEY_Y, 0, KEY_O, KEY_I, KEY_COMMA, 0, 0, 0, TOSA_KEY_RECORD, 0, 0, 0, 0, /*17 - 32*/ -+ KEY_A, KEY_D, KEY_G, KEY_U, 0, KEY_L, KEY_ENTER, KEY_DOT, 0, 0, 0, TOSA_KEY_SYNC, 0, 0, 0, 0, /*33 - 48*/ -+ KEY_Z, KEY_C, KEY_V, KEY_J, TOSA_KEY_ADDRESS, TOSA_KEY_CANCEL, TOSA_KEY_CENTER, TOSA_KEY_OK, KEY_LEFTSHIFT, 0 , 0,0 , 0, 0, 0, 0, /*49 - 64*/ -+ KEY_S, KEY_R, KEY_B, KEY_N, TOSA_KEY_CALENDER, TOSA_KEY_HOME, TOSA_KEY_REC, TOSA_KEY_LIGHT, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /*65 - 80*/ -+ KEY_TAB, KEY_SLASH, KEY_H, KEY_M, TOSA_KEY_MENU, 0, KEY_UP, 0, 0, 0, TOSA_KEY_FN, 0, 0, 0, 0, 0, /*81 - 96*/ -+ KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, /*97 - 109*/ -+}; -+ -+struct tosakbd { -+ unsigned char keycode[ARRAY_SIZE(tosakbd_keycode)]; -+ struct input_dev *input; -+ -+ spinlock_t lock; -+ struct timer_list timer; -+ struct timer_list hptimer; -+ -+ int hp_state; -+ int hp_count; -+ -+ unsigned int suspended; -+ unsigned long suspend_jiffies; -+}; -+ -+/* Helper functions for reading the keyboard matrix -+ * Note: We should really be using pxa_gpio_mode to alter GPDR but it -+ * requires a function call per GPIO bit which is excessive -+ * when we need to access 12 bits at once, multiple times. -+ * These functions must be called within local_irq_save()/local_irq_restore() -+ * or similar. -+ */ -+static inline void tosakbd_discharge_all(void) -+{ -+ /* STROBE All HiZ */ -+ GPCR1 = TOSA_GPIO_HIGH_STROBE_BIT; -+ GPDR1 &= ~TOSA_GPIO_HIGH_STROBE_BIT; -+ GPCR2 = TOSA_GPIO_LOW_STROBE_BIT; -+ GPDR2 &= ~TOSA_GPIO_LOW_STROBE_BIT; -+} -+ -+static inline void tosakbd_activate_all(void) -+{ -+ /* STROBE ALL -> High */ -+ GPSR1 = TOSA_GPIO_HIGH_STROBE_BIT; -+ GPDR1 |= TOSA_GPIO_HIGH_STROBE_BIT; -+ GPSR2 = TOSA_GPIO_LOW_STROBE_BIT; -+ GPDR2 |= TOSA_GPIO_LOW_STROBE_BIT; -+ -+ udelay(KB_DISCHARGE_DELAY); -+ -+ /* STATE CLEAR */ -+ GEDR2 |= TOSA_GPIO_ALL_SENSE_BIT; -+} -+ -+static inline void tosakbd_activate_col(int col) -+{ -+ if (col<=5) { -+ /* STROBE col -> High, not col -> HiZ */ -+ GPSR1 = TOSA_GPIO_STROBE_BIT(col); -+ GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); -+ } else { -+ /* STROBE col -> High, not col -> HiZ */ -+ GPSR2 = TOSA_GPIO_STROBE_BIT(col); -+ GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); -+ } -+} -+ -+static inline void tosakbd_reset_col(int col) -+{ -+ if (col<=5) { -+ /* STROBE col -> Low */ -+ GPCR1 = TOSA_GPIO_STROBE_BIT(col); -+ /* STROBE col -> out, not col -> HiZ */ -+ GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); -+ } else { -+ /* STROBE col -> Low */ -+ GPCR2 = TOSA_GPIO_STROBE_BIT(col); -+ /* STROBE col -> out, not col -> HiZ */ -+ GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); -+ } -+} -+ -+/* -+ * Read the GPIOs for POWER, RECORD and SYNC -+ */ -+static int read_port_key_status_raw(void) -+{ -+ int val=0; -+ -+ /* Power key */ -+ if ((GPLR0 & GPIO_bit(TOSA_GPIO_ON_KEY))==0) -+ val |= KEYMASK_ON; -+ /* Record key */ -+ if ((GPLR0 & GPIO_bit(TOSA_GPIO_RECORD_BTN))==0) -+ val |= KEYMASK_REC; -+ /* Sync key */ -+ if ((GPLR0 & GPIO_bit(TOSA_GPIO_SYNC))==0) -+ val |= KEYMASK_SYNC; -+ return val; -+} -+ -+ -+/* -+ * The tosa keyboard only generates interrupts when a key is pressed. -+ * So when a key is pressed, we enable a timer. This timer scans the -+ * keyboard, and this is how we detect when the key is released. -+ */ -+ -+/* Scan the hardware keyboard and push any changes up through the input layer */ -+static void tosakbd_scankeyboard(struct tosakbd *tosakbd_data) -+{ -+ unsigned int row, col, rowd; -+ unsigned long flags; -+ unsigned int num_pressed = 0; -+ -+ if (tosakbd_data->suspended) -+ return; -+ -+ spin_lock_irqsave(&tosakbd_data->lock, flags); -+ -+ for (col = 0; col < KB_COLS; col++) { -+ /* -+ * Discharge the output driver capacitatance -+ * in the keyboard matrix. (Yes it is significant..) -+ */ -+ tosakbd_discharge_all(); -+ udelay(KB_DISCHARGE_DELAY); -+ -+ tosakbd_activate_col( col); -+ udelay(KB_ACTIVATE_DELAY); -+ -+ rowd = GET_ROWS_STATUS(col); -+ -+ for (row = 0; row < KB_ROWS; row++) { -+ unsigned int scancode, pressed; -+ scancode = SCANCODE(row, col); -+ pressed = rowd & KB_ROWMASK(row); -+ input_report_key(tosakbd_data->input, tosakbd_data->keycode[scancode], pressed); -+ if (pressed) -+ num_pressed++; -+ } -+ -+ tosakbd_reset_col(col); -+ } -+ -+ tosakbd_activate_all(); -+ -+ rowd = read_port_key_status_raw(); -+ -+ for (row = 0; row < 3; row++ ) { -+ unsigned int scancode, pressed; -+ scancode = SCANCODE(row, KB_COLS); -+ pressed = rowd & KB_ROWMASK(row); -+ input_report_key(tosakbd_data->input, tosakbd_data->keycode[scancode], pressed); -+ if (pressed) -+ num_pressed++; -+ -+ if (pressed && (tosakbd_data->keycode[scancode] == TOSA_KEY_OFF) -+ && time_after(jiffies, tosakbd_data->suspend_jiffies + msecs_to_jiffies(1000))) { -+ input_event(tosakbd_data->input, EV_PWR, TOSA_KEY_OFF, 1); -+ tosakbd_data->suspend_jiffies = jiffies; -+ } -+ } -+ -+ input_sync(tosakbd_data->input); -+ -+ /* if any keys are pressed, enable the timer */ -+ if (num_pressed) -+ mod_timer(&tosakbd_data->timer, jiffies + SCAN_INTERVAL); -+ -+ spin_unlock_irqrestore(&tosakbd_data->lock, flags); -+} -+ -+/* -+ * tosa keyboard interrupt handler. -+ */ -+static irqreturn_t tosakbd_interrupt(int irq, void *dev_id) -+{ -+ struct tosakbd *tosakbd_data = dev_id; -+ -+ if (!timer_pending(&tosakbd_data->timer)) -+ { -+ /** wait chattering delay **/ -+ udelay(20); -+ tosakbd_scankeyboard(tosakbd_data); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+/* -+ * tosa timer checking for released keys -+ */ -+static void tosakbd_timer_callback(unsigned long data) -+{ -+ struct tosakbd *tosakbd_data = (struct tosakbd *) data; -+ tosakbd_scankeyboard(tosakbd_data); -+} -+ -+/* -+ * The headphone generates an interrupt. -+ * We debounce the switche and pass them to the input system. -+ */ -+ -+static irqreturn_t tosakbd_hp_isr(int irq, void *dev_id) -+{ -+ struct tosakbd *tosakbd_data = dev_id; -+ -+ if (!timer_pending(&tosakbd_data->hptimer)) -+ mod_timer(&tosakbd_data->hptimer, jiffies + msecs_to_jiffies(HP_SCAN_INTERVAL)); -+ -+ return IRQ_HANDLED; -+} -+ -+static void tosakbd_hp_timer(unsigned long data) -+{ -+ struct tosakbd *tosakbd_data = (struct tosakbd *) data; -+ unsigned long state; -+ unsigned long flags; -+ -+ state = (GPLR(TOSA_GPIO_EAR_IN) & GPIO_bit(TOSA_GPIO_EAR_IN)); -+ if (state != tosakbd_data->hp_state) { -+ tosakbd_data->hp_count = 0; -+ tosakbd_data->hp_state = state; -+ } else if (tosakbd_data->hp_count < HP_STABLE_COUNT) { -+ tosakbd_data->hp_count++; -+ } -+ -+ if (tosakbd_data->hp_count >= HP_STABLE_COUNT) { -+ spin_lock_irqsave(&tosakbd_data->lock, flags); -+ -+ input_report_switch(tosakbd_data->input, SW_HEADPHONE_INSERT, ((GPLR(TOSA_GPIO_EAR_IN) & GPIO_bit(TOSA_GPIO_EAR_IN)) == 0)); -+ input_sync(tosakbd_data->input); -+ -+ spin_unlock_irqrestore(&tosakbd_data->lock, flags); -+ } else { -+ mod_timer(&tosakbd_data->hptimer, jiffies + msecs_to_jiffies(HP_SCAN_INTERVAL)); -+ } -+} -+ -+#ifdef CONFIG_PM -+static int tosakbd_suspend(struct platform_device *dev, pm_message_t state) -+{ -+ struct tosakbd *tosakbd = platform_get_drvdata(dev); -+ -+ tosakbd->suspended = 1; -+ -+ return 0; -+} -+ -+static int tosakbd_resume(struct platform_device *dev) -+{ -+ struct tosakbd *tosakbd = platform_get_drvdata(dev); -+ -+ /* Upon resume, ignore the suspend key for a short while */ -+ tosakbd->suspend_jiffies = jiffies; -+ tosakbd->suspended = 0; -+ -+ return 0; -+} -+#else -+#define tosakbd_suspend NULL -+#define tosakbd_resume NULL -+#endif -+ -+static int __init tosakbd_probe(struct platform_device *pdev) { -+ -+ int i; -+ struct tosakbd *tosakbd; -+ struct input_dev *input_dev; -+ -+ tosakbd = kzalloc(sizeof(struct tosakbd), GFP_KERNEL); -+ if (!tosakbd) -+ return -ENOMEM; -+ -+ input_dev = input_allocate_device(); -+ if (!input_dev) { -+ kfree(tosakbd); -+ return -ENOMEM; -+ } -+ -+ platform_set_drvdata(pdev,tosakbd); -+ -+ spin_lock_init(&tosakbd->lock); -+ -+ /* Init Keyboard rescan timer */ -+ init_timer(&tosakbd->timer); -+ tosakbd->timer.function = tosakbd_timer_callback; -+ tosakbd->timer.data = (unsigned long) tosakbd; -+ -+ /* Init Headphone Timer */ -+ init_timer(&tosakbd->hptimer); -+ tosakbd->hptimer.function = tosakbd_hp_timer; -+ tosakbd->hptimer.data = (unsigned long) tosakbd; -+ -+ tosakbd->suspend_jiffies = jiffies; -+ -+ tosakbd->input = input_dev; -+ -+ input_dev->private = tosakbd; -+ input_dev->name = "Tosa Keyboard"; -+ input_dev->phys = "tosakbd/input0"; -+ input_dev->cdev.dev = &pdev->dev; -+ -+ input_dev->id.bustype = BUS_HOST; -+ input_dev->id.vendor = 0x0001; -+ input_dev->id.product = 0x0001; -+ input_dev->id.version = 0x0100; -+ -+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW); -+ input_dev->keycode = tosakbd->keycode; -+ input_dev->keycodesize = sizeof(unsigned char); -+ input_dev->keycodemax = ARRAY_SIZE(tosakbd_keycode); -+ -+ memcpy(tosakbd->keycode, tosakbd_keycode, sizeof(tosakbd->keycode)); -+ for (i = 0; i < ARRAY_SIZE(tosakbd_keycode); i++) -+ set_bit(tosakbd->keycode[i], input_dev->keybit); -+ clear_bit(0, input_dev->keybit); -+ set_bit(SW_HEADPHONE_INSERT, input_dev->swbit); -+ -+ input_register_device(tosakbd->input); -+ -+ /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ -+ for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { -+ pxa_gpio_mode( TOSA_GPIO_KEY_SENSE(i) | GPIO_IN); -+ if (request_irq(TOSA_IRQ_GPIO_KEY_SENSE(i), tosakbd_interrupt, -+ IRQF_DISABLED | IRQF_TRIGGER_RISING, "tosakbd", tosakbd)) { -+ printk("tosakbd: Can't get IRQ: %d !\n", i); -+ } -+ } -+ -+ /* Set Strobe lines as outputs - set high */ -+ for (i = 0; i < TOSA_KEY_STROBE_NUM; i++) { -+ pxa_gpio_mode( TOSA_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH); -+ } -+ -+ // Power&Rec Button -+ pxa_gpio_mode( TOSA_GPIO_ON_KEY | GPIO_IN); -+ pxa_gpio_mode( TOSA_GPIO_RECORD_BTN | GPIO_IN); -+ pxa_gpio_mode( TOSA_GPIO_SYNC | GPIO_IN); -+ pxa_gpio_mode( TOSA_GPIO_EAR_IN | GPIO_IN); -+ -+ if (request_irq(TOSA_IRQ_GPIO_ON_KEY, tosakbd_interrupt, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "On key", tosakbd) || -+ request_irq(TOSA_IRQ_GPIO_RECORD_BTN, tosakbd_interrupt, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Record key", tosakbd) || -+ request_irq(TOSA_IRQ_GPIO_SYNC, tosakbd_interrupt, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Sync key", tosakbd) || -+ request_irq(TOSA_IRQ_GPIO_EAR_IN, tosakbd_hp_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "HP in", tosakbd)) { -+ printk("Could not allocate KEYBD IRQ!\n"); -+ } -+ -+ printk(KERN_INFO "input: Tosa Keyboard Registered\n"); -+ -+ return 0; -+} -+ -+static int tosakbd_remove(struct platform_device *dev) { -+ -+ int i; -+ struct tosakbd *tosakbd = platform_get_drvdata(dev); -+ -+ for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) -+ free_irq(TOSA_IRQ_GPIO_KEY_SENSE(i),tosakbd); -+ -+ free_irq(TOSA_IRQ_GPIO_ON_KEY,tosakbd); -+ free_irq(TOSA_IRQ_GPIO_RECORD_BTN,tosakbd); -+ free_irq(TOSA_IRQ_GPIO_SYNC,tosakbd); -+ -+ del_timer_sync(&tosakbd->timer); -+ -+ input_unregister_device(tosakbd->input); -+ -+ kfree(tosakbd); -+ -+ return 0; -+} -+ -+static struct platform_driver tosakbd_driver = { -+ .probe = tosakbd_probe, -+ .remove = tosakbd_remove, -+ .suspend = tosakbd_suspend, -+ .resume = tosakbd_resume, -+ .driver = { -+ .name = "tosa-keyboard", -+ }, -+}; -+ -+static int __devinit tosakbd_init(void) -+{ -+ return platform_driver_register(&tosakbd_driver); -+} -+ -+static void __exit tosakbd_exit(void) -+{ -+ platform_driver_unregister(&tosakbd_driver); -+} -+ -+module_init(tosakbd_init); -+module_exit(tosakbd_exit); -+ -+MODULE_AUTHOR("Dirk Opfer <Dirk@Opfer-Online.de>"); -+MODULE_DESCRIPTION("Tosa Keyboard Driver"); -+MODULE_LICENSE("GPLv2"); |