From: <mar...@us...> - 2006-10-14 07:15:54
|
Revision: 625 http://svn.sourceforge.net/hackndev/?rev=625&view=rev Author: marex_z71 Date: 2006-10-14 00:15:41 -0700 (Sat, 14 Oct 2006) Log Message: ----------- New PalmTC keyboard driver by Holger Bocklet Modified Paths: -------------- linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/Kconfig linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/Makefile linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/palmtc.c Added Paths: ----------- linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/palmtc_keyboard.c Removed Paths: ------------- linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/palmtc_buttons.c linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/palmtc_fbkeyb.c linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/palmtc_tsc2101.c linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/tsc2101.h Modified: linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/Kconfig =================================================================== --- linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/Kconfig 2006-10-13 19:51:42 UTC (rev 624) +++ linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/Kconfig 2006-10-14 07:15:41 UTC (rev 625) @@ -6,23 +6,10 @@ Palm Tungsten C. Currently there is only basic support for this PDA. -config PALMTC_BUTTONS - tristate "Palm Tungsten C buttons driver" +config PALMTC_KEYBOARD + tristate "Palm Tungsten C keyboard driver" depends on MACH_OMAP_PALMTC help This driver translates button presses on a Palm - Tungsten C to Linux input subsystem events, still non - functional. + Tungsten C to Linux input subsystem events -config PALMTC_TSC2101 - tristate "Support for TSC2101 touchscreen and audio" - depends on MACH_OMAP_PALMTC - help - Adds support for TSC2101 touchscreen and audio controller. This - code is hearly the same as soc/tsc2101 so is obsolete. - -config PALMTC_FBKEYBOARD - bool "On-screen keyboard (BROKEN)" - depends on PALMTC_TSC2101 - help - On-screen framebuffer keyboard Modified: linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/Makefile =================================================================== --- linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/Makefile 2006-10-13 19:51:42 UTC (rev 624) +++ linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/Makefile 2006-10-14 07:15:41 UTC (rev 625) @@ -3,5 +3,4 @@ # obj-$(CONFIG_MACH_OMAP_PALMTC) += palmtc.o -obj-$(CONFIG_PALMTC_BUTTONS) += palmtc_buttons.o -obj-$(CONFIG_PALMTC_TSC2101) += palmtc_tsc2101.o +obj-$(CONFIG_PALMTC_KEYBOARD) += palmtc_keyboard.o Modified: linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/palmtc.c =================================================================== --- linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/palmtc.c 2006-10-13 19:51:42 UTC (rev 624) +++ linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/palmtc.c 2006-10-14 07:15:41 UTC (rev 625) @@ -7,6 +7,7 @@ #include <linux/kernel.h> #include <linux/init.h> +#include <asm/arch/audio.h> #include <asm/mach/arch.h> #include <asm/mach-types.h> #include <asm/arch/hardware.h> @@ -14,6 +15,7 @@ #include <asm/domain.h> #include <linux/device.h> +#include <linux/platform_device.h> #include <linux/fb.h> #include <asm/arch/pxa-dmabounce.h> @@ -54,9 +56,29 @@ .pxafb_backlight_power = palm_backlight_power, }; -static void __init palm_init(void) + + +static struct platform_device palmtc_audio_device = { + .name = "pxa2xx-ac97", + .id = -1, +}; + +static struct platform_device palmtc_keyboard_device = { + .name = "palmtc-kbd", + .id = -1, +}; + + +static struct platform_device *devices[] __initdata = { + &palmtc_audio_device, + &palmtc_keyboard_device, +}; + +static void __init palmtc_init(void) { set_pxa_fb_info(&palmtclcd); + GCR &= ~GCR_PRIRDY_IEN; + platform_add_devices (devices, ARRAY_SIZE (devices)); } MACHINE_START(OMAP_PALMTC, "Palm Tungsten C") @@ -67,6 +89,6 @@ .map_io = pxa_map_io, .init_irq = pxa_init_irq, .timer = &pxa_timer, - .init_machine = palm_init + .init_machine = palmtc_init MACHINE_END Deleted: linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/palmtc_buttons.c =================================================================== --- linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/palmtc_buttons.c 2006-10-13 19:51:42 UTC (rev 624) +++ linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/palmtc_buttons.c 2006-10-14 07:15:41 UTC (rev 625) @@ -1,113 +0,0 @@ -/* - * Palm TC hardware buttons - * - * Author: Chetan Kumar S<shi...@gm...> - * Based on Palm T3 hardware buttons - * - */ -#include <linux/module.h> -#include <linux/config.h> - -#include <linux/input.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <asm/irq.h> -#include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include <asm/mach-types.h> -#include <asm/hardware.h> -#include <asm/arch/pxa-regs.h> -#include <asm/arch/irqs.h> -#include <linux/sched.h> -#include <linux/workqueue.h> - - - -#define GET_GPIO(gpio) (GPLR(gpio) & GPIO_bit(gpio)) - - -#define MY_WORK_QUEUE_NAME "WQsched.c" - -#define CURRGPIO 18 - -static struct workqueue_struct *my_workqueue; - -static void handle_gpio(void* irq) -{ - int gpn = (int)irq; - printk(KERN_ERR "palmtc: GPIO[%d] = %d\n", gpn, GET_GPIO(gpn)); -} - -irqreturn_t gpio_irq(int irq, void *dev_id, struct pt_regs *regs) -{ - static int initialised = 0; - static struct work_struct task; - -printk(KERN_INFO "gpio_irq.\n"); - -//Not very optimized, need to check this sometime -Chetan - if (initialised == 0) { - INIT_WORK(&task, handle_gpio, dev_id); - initialised = 1; - } else { - PREPARE_WORK(&task, handle_gpio, dev_id); - } - - queue_work(my_workqueue, &task); - - return IRQ_HANDLED; -} - - -#define REG_GPIO(x) \ - ret = request_irq (IRQ_GPIO(x), gpio_irq, SA_SAMPLE_RANDOM, "Palmtc Buttons", (void*)x); \ - set_irq_type (IRQ_GPIO(x), IRQT_BOTHEDGE); \ - if(ret!=0) { \ - printk(KERN_INFO "Request GPIO: %d failed\n", x); \ - return 1; \ - } else { \ - printk(KERN_INFO "Registered GPIO %d\n", x); \ - } - -#define UNREG_GPIO(x) \ - free_irq(IRQ_GPIO(x),(void*)x); - -static int __init palmtc_btn_init(void) -{ - int ret; - printk(KERN_INFO "palmtc: init\n"); - printk(KERN_INFO "GPDR Dump:\n0: %X\n1: %X\n2: %X\n", GPDR0, GPDR1, GPDR2); - - - my_workqueue = create_workqueue(MY_WORK_QUEUE_NAME); - - REG_GPIO(0); - REG_GPIO(9); - REG_GPIO(10); - REG_GPIO(11); - - printk(KERN_INFO "palmtc: registered for irqs %d, %d, %d, %d\n", IRQ_GPIO(0), IRQ_GPIO(9), IRQ_GPIO(10), IRQ_GPIO(11)); - - -printk("Keypad register set done.........\n"); - - return 0; -} - -static void __exit palmtc_btn_cleanup(void) -{ - printk(KERN_INFO "tc buttons: unloading...\n"); - printk(KERN_INFO "Releasing irq\n"); - UNREG_GPIO(0); - UNREG_GPIO(9); - UNREG_GPIO(10); - UNREG_GPIO(11); - -} - -module_init(palmtc_btn_init); -module_exit(palmtc_btn_cleanup); - -MODULE_AUTHOR ("Chetan Kumar S <shi...@gm...>"); -MODULE_DESCRIPTION ("Button support for Palm Tungsten C"); -MODULE_LICENSE("GPL"); Deleted: linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/palmtc_fbkeyb.c =================================================================== --- linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/palmtc_fbkeyb.c 2006-10-13 19:51:42 UTC (rev 624) +++ linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/palmtc_fbkeyb.c 2006-10-14 07:15:41 UTC (rev 625) @@ -1,72 +0,0 @@ -/* - * On-screen keyboard in kernel space - * - * Author: Vladimir "Farcaller" Pouzanov <far...@gm...> - * - */ -#include <linux/module.h> -#include <linux/config.h> - -#include <linux/input.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <asm/irq.h> -#include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include <asm/mach-types.h> -#include <asm/hardware.h> -#include <asm/arch/pxa-regs.h> -#include <asm/arch/irqs.h> -#include <linux/sched.h> -#include <linux/workqueue.h> - -#include <linux/fb.h> -#include <linux/vt_kern.h> - -static int resized; - -void drawkeyb(void) -{ - /* - struct fb_info *p; - struct vc_data *vc; - struct fb_fillrect rect; - int i; - unsigned long fg; - - if(resized<2) { - resized++; - vc = vc_cons[0].d; - vc_resize(vc, 40, 41); - } - p = registered_fb[0]; - - rect.dx = 0; - rect.width = 320; - rect.height = 2; - rect.color = 0x00FF00FF; - rect.rop = ROP_COPY; - for(i = 150; i < 320; i+=10) { - rect.dy = i; - cfb_fillrect(p, &rect); - } - if (p->fix.visual == FB_VISUAL_TRUECOLOR || p->fix.visual == FB_VISUAL_DIRECTCOLOR ) { - fg = ((u32 *) (p->pseudo_palette))[rect.color]; - printk(KERN_INFO "Direct col %lu\n", fg); - } else { - fg = rect.color; - printk(KERN_INFO "Indir col %lu\n", fg); - } - */ -} - -static int __init palmt3_fbk_init(void) -{ - printk(KERN_INFO "fbkeyb: init\n"); - resized = 0; - - return 0; -} - -module_init(palmt3_fbk_init); - Added: linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/palmtc_keyboard.c =================================================================== --- linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/palmtc_keyboard.c (rev 0) +++ linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/palmtc_keyboard.c 2006-10-14 07:15:41 UTC (rev 625) @@ -0,0 +1,402 @@ +/* + * Palm TC hardware buttons + * + * Author: Holger Bocklet, Bit...@gm..., + * based on research by Chetan Kumar S<shi...@gm...> + * with bits and pieces from + * htcuniversal_kbd.c, (Milan Votava) + * palmt3_buttons.c, (Vladimir "Farcaller" Pouzanov <far...@gm...>, Martin Kupec) + * palmte2_keyboard, (Carlos Eduardo Medaglia Dyonisio <ca...@ne...>) + * + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/input.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/jiffies.h> +#include <linux/platform_device.h> +#include <linux/workqueue.h> +#include <linux/delay.h> + +#include <asm/mach/arch.h> +#include <asm/mach-types.h> +#include <asm/hardware.h> +#include <asm/arch/pxa-regs.h> +#include <asm/arch/irqs.h> + +#define USE_RELEASE_TIMER +#define USE_DOUBLECLICK + +#define PALMTC_KEYBOARD_DEBUG + +#ifdef PALMTC_KEYBOARD_DEBUG +#define DBG(x...) \ + printk(KERN_INFO "Palmtc keyboard: " x) +#else +#define DBG(x...) do { } while (0) +#endif + +#define TRUE 1 +#define FALSE 0 +#define PERMANENT 2 + +#define MAX_ROW 12 +#define MAX_COL 4 + +#define SHIFT_BIT 0x80 +#define PRESSED_BIT 1 + +#define PALMTC_BLUEKEY -17 + +#define RELEASE_CHECK_TIME_MS 50 +#define DOUBLECLICK_TIME_MS 250 + +#define GET_GPIO(gpio) (GPLR(gpio) & GPIO_bit(gpio)) + +#define GET_KEY_BIT(vkey, bit) ((vkey >> (bit) ) & 0x01) +#define SET_KEY_BIT(vkey, bit) (vkey |= (1 << (bit)) ) +#define CLEAR_KEY_BIT(vkey, bit) (vkey &= ~(1 << (bit)) ) + +#ifdef USE_RELEASE_TIMER +static void release_timer_went_off (unsigned long); +static struct timer_list key_release_timer; +#endif + +/********************************************************** + * Key-matrix map german + * GPIO 0 9 10 11 + * 18 CALEND CONTACT MAIL WEB + * 19 x DOWN OPT OK + * 20 POWER + * 21 TAB d h . + * 22 a c z l + * 23 q f n o + * 24 SHIFT r j EXIT + * 25 y SPACE u CR + * 26 s v m BS + * 27 w g k p + * 79 e t i b + * 80 UP LEFT RIGHT BLUE + **********************************************************/ + +static u8 alternate_key=FALSE; +static int col_gpio[MAX_COL] = { 0, 9, 10, 11 }; +static u8 row_gpio[MAX_ROW] = {18,19,20,21,22,23,24,25,26,27,79,80}; + +static struct { // matrix for real buttons + int key; + int alt_key; + u8 flags; // for recording last status and shift_bit + unsigned long tstamp; // timestamp (jiffies) + char *desc; +} palmtc_buttons[MAX_ROW][MAX_COL] = { +// Gpio Column+IRQ +// german keymap +/*18*/{{KEY_F1,KEY_F5,FALSE,0,"CAL/F1"}, //0 + {KEY_F2,KEY_F6,FALSE,0,"CONTACT/F2"}, //9 + {KEY_F3,KEY_F7,FALSE,0,"MAIL/F3"}, //10 + {KEY_F4,KEY_F8,FALSE,0,"WEB/F4"} },//11 +/*19*/ {{KEY_X,KEY_9,SHIFT_BIT|FALSE,0,"X"}, + {KEY_DOWN,KEY_PAGEDOWN,FALSE,0,"down/pgdown"} , + {KEY_LEFTCTRL,KEY_F9,FALSE,0,"cmd/ctrl/f9"}, + {KEY_ENTER,-1,FALSE,0,"Select/enter/;"} }, //1 free +/*20*/ {{KEY_POWER,-1,FALSE,0,"power"}, //0 + {-1,-1,FALSE,0,"unused 9/20"}, //9 + {-1,-1,FALSE,0,"unused 10/20"}, //10 + {-1,-1,FALSE,0,"unused 11/20"} }, //11 +/*21*/ {{KEY_TAB,KEY_BACKSLASH,SHIFT_BIT|FALSE,0,"tab/|"}, + {KEY_D,KEY_KPPLUS,FALSE,0,"D"}, + {KEY_H,KEY_MINUS,SHIFT_BIT|FALSE,0,"H/_"}, + {KEY_DOT,KEY_SEMICOLON,SHIFT_BIT|FALSE,0,"./:"} }, +/*22*/ {{KEY_A,KEY_2,SHIFT_BIT|FALSE,0,"A/@"}, + {KEY_C,KEY_0,SHIFT_BIT|FALSE,0,"C/)"}, + {KEY_Z,KEY_6,FALSE,0,"de:Z us:Y"}, + {KEY_L,KEY_EQUAL,FALSE,0,"L/\xDF"} }, // Keyoard shows "\xDF" but better use "=" +/*23*/ {{KEY_Q,KEY_1,FALSE,0,"Q"}, //0 + {KEY_F,KEY_KPMINUS,FALSE,0,"F"}, //9 + {KEY_N,KEY_COMMA,FALSE,0,"N"}, //10 + {KEY_O,KEY_9,FALSE,0,"O"} },//11 +/*24*/ {{KEY_LEFTSHIFT,KEY_7,SHIFT_BIT|FALSE,0,"shift/&"}, + {KEY_R,KEY_4,FALSE,0,"R"}, + {KEY_J,KEY_SLASH,FALSE,0,"J"}, + {KEY_LEFTALT,KEY_F10,FALSE,0,"exit/alt"} }, +/*25*/ {{KEY_Y,KEY_4,SHIFT_BIT|FALSE,0,"de:Y us:Z / $"}, // dollar is more usefull + {KEY_SPACE,KEY_ESC,FALSE,0,"space/esc"}, + {KEY_U,KEY_7,FALSE,0,"U"}, + {KEY_ENTER,KEY_SEMICOLON,FALSE,0,"enter"} }, +/*26*/ {{KEY_S,KEY_APOSTROPHE,SHIFT_BIT|FALSE,0,"S"}, + {KEY_V,KEY_3,SHIFT_BIT|FALSE,0,"V/#"}, + {KEY_M,KEY_SLASH,SHIFT_BIT|FALSE,0,"M/?"}, + {KEY_BACKSPACE,KEY_GRAVE,SHIFT_BIT|FALSE,0,"bs/~"} }, +/*27*/ {{KEY_W,KEY_2,FALSE,0,"W"}, + {KEY_G,KEY_KPASTERISK,FALSE,0,"G"}, + {KEY_K,KEY_APOSTROPHE,FALSE,0,"K"}, + {KEY_P,KEY_0,FALSE,0,"P"} }, +/*79*/ {{KEY_E,KEY_3,FALSE,0,"E"}, + {KEY_T,KEY_5,FALSE,0,"T"}, + {KEY_I,KEY_8,FALSE,0,"I"}, + {KEY_B,KEY_1,SHIFT_BIT|FALSE,0,"B/!"} }, +/*80*/ {{KEY_UP,KEY_PAGEUP,FALSE,0,"up"}, + {KEY_LEFT,KEY_HOME,FALSE,0,"left"}, + {KEY_RIGHT,KEY_END,FALSE,0,"right"}, + {PALMTC_BLUEKEY,-1,FALSE,0,"blue"} } +}; + +struct input_dev *keyboard_dev; + +static struct workqueue_struct *palmtc_kbd_workqueue; +static struct work_struct palmtc_kbd_task; + +static spinlock_t kbd_lock = SPIN_LOCK_UNLOCKED; + +static irqreturn_t palmtc_kbd_irq_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + queue_work(palmtc_kbd_workqueue, &palmtc_kbd_task); + return IRQ_HANDLED; +} + +static void palmtc_kbd_queuework(void *data) +{ + unsigned long tdiff_msec, flags; + int gpio, row, col; + + // ignore irqs + for(col=0;col<MAX_COL;col++) { + set_irq_type (IRQ_GPIO(col_gpio[col]), IRQT_NOEDGE); + } + // set row-gpios high so we can pull them low later one-by-one in loop + spin_lock_irqsave(&kbd_lock, flags); + for (row=0; row<MAX_ROW;row++) { + GPSR(row_gpio[row]) = GPIO_bit(row_gpio[row]); + } + spin_unlock_irqrestore(&kbd_lock, flags); + + // run thru rows, pull row-gpio low and see if what gpio of the colums goes low with it + for(row = MAX_ROW-1; row >=0; row--) { // counting backwards, so we get BLUE first + spin_lock_irqsave(&kbd_lock, flags); + GPCR(row_gpio[row]) = GPIO_bit(row_gpio[row]); + spin_unlock_irqrestore(&kbd_lock, flags); + + udelay(50); + + for(col = MAX_COL-1; col >= 0; col--) { + spin_lock_irqsave(&kbd_lock, flags); + gpio = GET_GPIO(col_gpio[col]); + spin_unlock_irqrestore(&kbd_lock, flags); + + tdiff_msec = jiffies_to_msecs((unsigned long)((long)jiffies - + (long)palmtc_buttons[row][col].tstamp)); + + if(!gpio) { + if (! (palmtc_buttons[row][col].flags&PRESSED_BIT)) { //is not pressed at the moment + + palmtc_buttons[row][col].flags|=PRESSED_BIT; + palmtc_buttons[row][col].tstamp=jiffies; +#ifdef USE_DOUBLECLICK + if ( (tdiff_msec<DOUBLECLICK_TIME_MS) ) { + if(palmtc_buttons[row][col].alt_key >= 0) { // report "alternate" keys + input_report_key(keyboard_dev, KEY_BACKSPACE, 1); + input_report_key(keyboard_dev, KEY_BACKSPACE, 0); + if (palmtc_buttons[row][col].flags&SHIFT_BIT) + input_report_key(keyboard_dev,KEY_LEFTSHIFT,1); + input_report_key(keyboard_dev, palmtc_buttons[row][col].alt_key, 1); + input_sync(keyboard_dev); + alternate_key=FALSE; + } + } else { +#endif + if (palmtc_buttons[row][col].key==PALMTC_BLUEKEY) { + switch(alternate_key) { + case (PERMANENT): + alternate_key=FALSE; + break; + case (TRUE): + alternate_key=PERMANENT; + break; + case (FALSE): + alternate_key=TRUE; + break; + } + } else { + if (alternate_key) { + if(palmtc_buttons[row][col].alt_key >= 0) { + if (palmtc_buttons[row][col].flags&SHIFT_BIT) + input_report_key(keyboard_dev,KEY_LEFTSHIFT,1); + input_report_key(keyboard_dev, palmtc_buttons[row][col].alt_key, 1); + //DBG("alt: ms:%0lu char: %s\n",palmtc_buttons[row][col].tstamp,palmtc_buttons[row][col].desc); + input_sync(keyboard_dev); + } + if(! (alternate_key==PERMANENT)) { + alternate_key=FALSE; + } + } else { + if(palmtc_buttons[row][col].key >= 0) { + input_report_key(keyboard_dev, palmtc_buttons[row][col].key, 1); + input_sync(keyboard_dev); + } + } + } +#ifdef USE_DOUBLECLICK + } +#endif + } +#ifdef USE_RELEASE_TIMER + spin_lock_irqsave(&kbd_lock, flags); + if (timer_pending(&key_release_timer)) { + mod_timer (&key_release_timer,jiffies + msecs_to_jiffies(RELEASE_CHECK_TIME_MS)); + } else { + key_release_timer.expires = (jiffies + msecs_to_jiffies(RELEASE_CHECK_TIME_MS)); + add_timer (&key_release_timer); + } + spin_unlock_irqrestore(&kbd_lock, flags); +#endif + } else { // not pressed branch + if (palmtc_buttons[row][col].flags&PRESSED_BIT) { + + palmtc_buttons[row][col].flags ^= PRESSED_BIT; //xor bit to 0 + if (palmtc_buttons[row][col].key >= 0) { + input_report_key(keyboard_dev, palmtc_buttons[row][col].key, 0); + if ((palmtc_buttons[row][col].alt_key >= 0) && (palmtc_buttons[row][col].flags&SHIFT_BIT) ) + input_report_key(keyboard_dev,KEY_LEFTSHIFT,0); + input_report_key(keyboard_dev, palmtc_buttons[row][col].alt_key, 0); + //DBG("rel: %s i:%d\n",palmtc_buttons[row][col].desc,i); i=0; + input_sync(keyboard_dev); + } + } + } + } + // back to high for this row + spin_lock_irqsave(&kbd_lock, flags); + GPSR(row_gpio[row]) = GPIO_bit(row_gpio[row]); + spin_unlock_irqrestore(&kbd_lock, flags); + } + + // set row-gpios low again + spin_lock_irqsave(&kbd_lock, flags); + for (row=0; row<MAX_ROW;row++) { + GPCR(row_gpio[row]) = GPIO_bit(row_gpio[row]); + } + spin_unlock_irqrestore(&kbd_lock, flags); + + // restore irqs (cols) + for(col=0;col<MAX_COL;col++) { + set_irq_type (IRQ_GPIO(col_gpio[col]), IRQT_BOTHEDGE); + } +} + + +#ifdef USE_RELEASE_TIMER +/* + * This is called when the key release timer goes off. That's the + * only time it should be called. Check for changes in what keys + * are down. + */ +static void +release_timer_went_off(unsigned long unused) +{ +unsigned long flags; + + spin_lock_irqsave(&kbd_lock,flags); + + queue_work(palmtc_kbd_workqueue, &palmtc_kbd_task); + + spin_unlock_irqrestore(&kbd_lock, flags); +} +#endif + + +static int palmtc_kbd_probe(struct device *dev) +{ + int row, col; + unsigned long ret; + DBG("Probing device\n" ); + + keyboard_dev = input_allocate_device(); + + keyboard_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); + + keyboard_dev->name = "Palm Tungsten C Keyboard"; + keyboard_dev->id.bustype = BUS_HOST; + + for(row=0;row<MAX_ROW;row++) { + for(col=0;col<MAX_COL;col++) { + if(palmtc_buttons[row][col].key >= 0) { + keyboard_dev->keybit[LONG(palmtc_buttons[row][col].key)] |= + BIT(palmtc_buttons[row][col].key); + } + if (palmtc_buttons[row][col].alt_key >= 0) { + keyboard_dev->keybit[LONG(palmtc_buttons[row][col].alt_key)] |= + BIT(palmtc_buttons[row][col].alt_key); + } + } + } + input_register_device(keyboard_dev); + + palmtc_kbd_workqueue = create_workqueue("palmtckbdw"); + INIT_WORK(&palmtc_kbd_task, palmtc_kbd_queuework, NULL); + +#ifdef USE_RELEASE_TIMER + init_timer (&key_release_timer); + key_release_timer.function = release_timer_went_off; +#endif + + for(col=0;col<MAX_COL;col++) { + ret = request_irq(IRQ_GPIO(col_gpio[col]), palmtc_kbd_irq_handler, + SA_SAMPLE_RANDOM,"palmtc-kbd", (void*)col_gpio[col]); + set_irq_type(IRQ_GPIO(col_gpio[col]), IRQT_BOTHEDGE); + } + return 0; +} + +static int palmtc_kbd_remove (struct device *dev) +{ + int col; + + DBG("removing device...\n"); + destroy_workqueue(palmtc_kbd_workqueue); + input_unregister_device(keyboard_dev); + + /* free irqs */ + for(col=0;col<MAX_COL;col++) { + free_irq(IRQ_GPIO(col_gpio[col]), (void*) col_gpio[col]); + } + +#ifdef USE_RELEASE_TIMER + del_timer (&key_release_timer); +#endif + + return 0; +} + +static struct device_driver palmtc_keyboard_driver = { + .name = "palmtc-kbd", + .bus = &platform_bus_type, + .probe = palmtc_kbd_probe, + .remove = palmtc_kbd_remove, +#ifdef CONFIG_PM + .suspend = NULL, + .resume = NULL, +#endif +}; + +static int __init palmtc_kbd_init(void) +{ + DBG("init\n"); + + return driver_register(&palmtc_keyboard_driver); +} + +static void __exit palmtc_kbd_cleanup(void) +{ + DBG("unloading...\n"); + + driver_unregister(&palmtc_keyboard_driver); +} + +module_init(palmtc_kbd_init); +module_exit(palmtc_kbd_cleanup); + +MODULE_AUTHOR("Holger Bocklet"); +MODULE_DESCRIPTION("Support for Palm TC Keyboard"); +MODULE_LICENSE("GPL"); Deleted: linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/palmtc_tsc2101.c =================================================================== --- linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/palmtc_tsc2101.c 2006-10-13 19:51:42 UTC (rev 624) +++ linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/palmtc_tsc2101.c 2006-10-14 07:15:41 UTC (rev 625) @@ -1,236 +0,0 @@ -/* - * Support for TSC2101 - * - * Author: Vladimir Pouzanov <far...@gm...> - * - * Parts of the code from tsc2101 module by Richard Purdie <ri...@o-...> - * - * 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/init.h> -#include <linux/kernel.h> -#include <asm/mach-types.h> -#include <asm/mach/arch.h> -#include <linux/interrupt.h> -#include <asm/arch/pxa-regs.h> -#include <asm/arch/pxa_keys.h> -#include <asm/arch/ssp.h> -#include <asm/arch/irqs.h> -#include <linux/sched.h> -#include <linux/workqueue.h> -#include <asm/hardware.h> -#include "tsc2101.h" - -#define PALMT3_GPIO_TSC2101_SS 26 -#define PALMT3_GPIO_TOUCHSCREEN 37 - -#define X_AXIS_MAX 3830 -#define X_AXIS_MIN 150 -#define Y_AXIS_MAX 3830 -#define Y_AXIS_MIN 190 -#define PRESSURE_MIN 0 -#define PRESSURE_MAX 20000 - -static struct ssp_dev palmt3_ssp_dev; -static struct workqueue_struct *palmt3_touchscreen_wq; - -struct tsc2101_ts_data { - int x,y,p; -}; -struct tsc2101_ts_data palmt3_ts_data; - -/*** TSC2101 I/O ops ***/ -int palmt3_tsc2101_send(int read, int command, int *values, int numval) -{ - int i; - - GPCR0 = GPIO_bit(PALMT3_GPIO_TSC2101_SS); - - ssp_write_word(&palmt3_ssp_dev, command | read); - /* dummy read */ - ssp_read_word(&palmt3_ssp_dev); - - for (i=0; i < numval; i++) { - if (read) { - ssp_write_word(&palmt3_ssp_dev, 0); - values[i]=ssp_read_word(&palmt3_ssp_dev); - } else { - ssp_write_word(&palmt3_ssp_dev, values[i]); - ssp_read_word(&palmt3_ssp_dev); - } - } - - GPSR0 = GPIO_bit(PALMT3_GPIO_TSC2101_SS); - return 0; -} - -/* FIXME static or not? */ -void palmt3_tsc2101_readdata(void *ts_data) -{ - int vx,vy,vp,z1,z2;//,fixadc=0; - u32 values[4],status; - vx=0; vy=0; vp=0; - palmt3_tsc2101_send(TSC2101_READ, TSC2101_REG_STATUS, &status, 1); - - // printk("status: %x ", status); - - if (status & (TSC2101_STATUS_XSTAT | TSC2101_STATUS_YSTAT | TSC2101_STATUS_Z1STAT - | TSC2101_STATUS_Z2STAT)) { - - /* Read X, Y, Z1 and Z2 */ - palmt3_tsc2101_send(TSC2101_READ, TSC2101_REG_X, &values[0], 4); - - vx=values[0]; - vy=values[1]; - z1=values[2]; - z2=values[3]; - - /* Calculate Pressure */ - if ((z1 != 0) && (vx!=0) && (vy!=0)) - vp = ((vx * (z2 -z1) / z1)); - else - vp=0; - } - /*printk("Touch at %d:%d raw, pressure: %d\n", vx,vy,vp);*/ - palmt3_ts_data.x = vx; - palmt3_ts_data.y = vy; - palmt3_ts_data.p = vp; - - /* - if (status & TSC2101_STATUS_BSTAT) { - devdata->platform->send(TSC2101_READ, TSC2101_REG_BAT, &values[0], 1); - devdata->miscdata.bat=values[0]; - fixadc=1; - } - if (status & TSC2101_STATUS_AX1STAT) { - devdata->platform->send(TSC2101_READ, TSC2101_REG_AUX1, &values[0], 1); - devdata->miscdata.aux1=values[0]; - fixadc=1; - } - if (status & TSC2101_STATUS_AX2STAT) { - devdata->platform->send(TSC2101_READ, TSC2101_REG_AUX2, &values[0], 1); - devdata->miscdata.aux2=values[0]; - fixadc=1; - } - if (status & TSC2101_STATUS_T1STAT) { - devdata->platform->send(TSC2101_READ, TSC2101_REG_TEMP1, &values[0], 1); - devdata->miscdata.temp1=values[0]; - fixadc=1; - } - if (status & TSC2101_STATUS_T2STAT) { - devdata->platform->send(TSC2101_READ, TSC2101_REG_TEMP2, &values[0], 1); - devdata->miscdata.temp2=values[0]; - fixadc=1; - } - if (fixadc) { - // Switch back to touchscreen autoscan - tsc2101_regwrite(devdata, TSC2101_REG_ADC, TSC2101_ADC_DEFAULT | TSC2101_ADC_PSM | TSC2101_ADC_ADMODE(0x2)); - } - */ -} - -/*** IRQ handlers ***/ -static void palmt3_touchscreen_handle(void* unused) -{ - palmt3_tsc2101_readdata(0); - // printk(KERN_INFO "palmt3_touchscreen_handle: Screen touched...\n"); -} - -irqreturn_t palmt3_touchscreen_irq(int irq, void *dev_id, struct pt_regs *regs) -{ - static int initialised = 0; - static struct work_struct task; - - if (initialised == 0) { - INIT_WORK(&task, palmt3_touchscreen_handle, NULL); - initialised = 1; - } else { - PREPARE_WORK(&task, palmt3_touchscreen_handle, NULL); - } - - queue_work(palmt3_touchscreen_wq, &task); - - return IRQ_HANDLED; -} - -/*** INIT/CLEANUP stuff ***/ -#define TSC_REGWRITE(r, x) regval = x; palmt3_tsc2101_send(TSC2101_WRITE, r, ®val, 1); -#define TSC2101_ADC_DEFAULT (TSC2101_ADC_RES(TSC2101_ADC_RES_12BITP) | TSC2101_ADC_AVG(TSC2101_ADC_4AVG) | TSC2101_ADC_CL(TSC2101_ADC_CL_1MHZ_12BIT) | TSC2101_ADC_PV(TSC2101_ADC_PV_500us) | TSC2101_ADC_AVGFILT_MEAN) - -static int __init palmt3_tsc2101_init(void) -{ - int regval; - printk(KERN_INFO "palmt3_tsc2101: init\n"); - - printk(KERN_WARNING "FIXME: Resetting SSP, but that's bootloader job\n"); - SSCR0 &= ~SSCR0_SSE; - SSCR1 = SSCR1 & 0x3FFC; - - if (ssp_init(&palmt3_ssp_dev, 1, NULL)) - printk(KERN_ERR "palmt3_tsc2101: Unable to register SSP1 handler!\n"); - else { - // ssp_disable(&palmt3_ssp_dev); - // ssp_config(&palmt3_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x0f )), SSCR1_SPH, 0, 0); - ssp_enable(&palmt3_ssp_dev); - // hx2750_set_egpio(HX2750_EGPIO_TSC_PWR); - printk(KERN_INFO "palmt3_tsc2101: SSP initialized\n"); - } - - // reset TSC2101 - TSC_REGWRITE(TSC2101_REG_ADC, 0x4000); - printk(KERN_INFO "palmt3_tsc2101: re-enabling TSC2101\n"); - /* PINTDAV is data available only */ - TSC_REGWRITE(TSC2101_REG_STATUS, 0x4000); - - /* disable buffer mode */ - TSC_REGWRITE(TSC2101_REG_BUFMODE, 0x0); - - /* use internal reference, 100 usec power-up delay, - * power down between conversions, 1.25V internal reference */ - // TSC_REGWRITE(TSC2101_REG_REF, 0x16); - - /* enable touch detection, 84usec precharge time, 32 usec sense time */ - TSC_REGWRITE(TSC2101_REG_CONFIG, 0x08); - - /* 3 msec conversion delays */ - TSC_REGWRITE(TSC2101_REG_DELAY, 0x0900); - - /* - * TSC2101-controlled conversions - * 12-bit samples - * continuous X,Y,Z1,Z2 scan mode - * average (mean) 4 samples per coordinate - * 1 MHz internal conversion clock - * 500 usec panel voltage stabilization delay - */ - TSC_REGWRITE(TSC2101_REG_ADC, TSC2101_ADC_DEFAULT | TSC2101_ADC_PSM | TSC2101_ADC_ADMODE(0x2)); - -#if 0 - palmt3_touchscreen_wq = create_workqueue("T3 Touchscreen"); - if(request_irq(IRQ_GPIO(PALMT3_GPIO_TOUCHSCREEN), palmt3_touchscreen_irq, - SA_SAMPLE_RANDOM, "T3 Touchscreen GPIO", NULL)) { - printk(KERN_ERR "palmt3_tsc2101: Unable to register GPIO handler for %d\n", PALMT3_GPIO_TSC2101_SS); - } else { - set_irq_type (IRQ_GPIO(PALMT3_GPIO_TOUCHSCREEN), IRQT_BOTHEDGE); - /* FIXME is it really bothedge? Should check PalmOS */ - - printk(KERN_INFO "palmt3_tsc2101: Touchscreen GPIO registered\n"); - } -#endif - - return 0; -} - -static void __exit palmt3_tsc2101_cleanup(void) -{ - /* FIXME Unreg stuff */ - printk(KERN_INFO "palmt3_tsc2101: cleanup\n"); -} - -module_init(palmt3_tsc2101_init); -module_exit(palmt3_tsc2101_cleanup); - Deleted: linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/tsc2101.h =================================================================== --- linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/tsc2101.h 2006-10-13 19:51:42 UTC (rev 624) +++ linux4palm/linux/trunk/arch/arm/mach-pxa/palmtc/tsc2101.h 2006-10-14 07:15:41 UTC (rev 625) @@ -1,154 +0,0 @@ -/* - * TI TSC2101 Hardware definitions - * - * Copyright 2005 Openedhand Ltd. - * - * Author: Richard Purdie <ri...@o-...> - * - * 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. - * - */ - -/* Address constructs */ -#define TSC2101_READ (1 << 15) /* Read Register */ -#define TSC2101_WRITE (0 << 15) /* Write Register */ -#define TSC2101_PAGE(x) ((x & 0xf) << 11) /* Memory Page to access */ -#define TSC2101_ADDR(x) ((x & 0x3f) << 5) /* Memory Address to access */ - -#define TSC2101_P0_REG(x) (TSC2101_PAGE(0) | TSC2101_ADDR(x)) -#define TSC2101_P1_REG(x) (TSC2101_PAGE(1) | TSC2101_ADDR(x)) -#define TSC2101_P2_REG(x) (TSC2101_PAGE(2) | TSC2101_ADDR(x)) -#define TSC2101_P3_REG(x) (TSC2101_PAGE(3) | TSC2101_ADDR(x)) - -/* Page 0 Registers */ -#define TSC2101_REG_X TSC2101_P0_REG(0x0) -#define TSC2101_REG_Y TSC2101_P0_REG(0x1) -#define TSC2101_REG_Z1 TSC2101_P0_REG(0x2) -#define TSC2101_REG_Z2 TSC2101_P0_REG(0x3) -#define TSC2101_REG_BAT TSC2101_P0_REG(0x5) -#define TSC2101_REG_AUX1 TSC2101_P0_REG(0x7) -#define TSC2101_REG_AUX2 TSC2101_P0_REG(0x8) -#define TSC2101_REG_TEMP1 TSC2101_P0_REG(0x9) -#define TSC2101_REG_TEMP2 TSC2101_P0_REG(0xa) - -/* Page 1 Registers */ -#define TSC2101_REG_ADC TSC2101_P1_REG(0x0) -#define TSC2101_REG_STATUS TSC2101_P1_REG(0x1) -#define TSC2101_REG_BUFMODE TSC2101_P1_REG(0x2) -#define TSC2101_REG_REF TSC2101_P1_REG(0x3) -#define TSC2101_REG_RESETCTL TSC2101_P1_REG(0x4) -#define TSC2101_REG_CONFIG TSC2101_P1_REG(0x5) -#define TSC2101_REG_TEMPMAX TSC2101_P1_REG(0x6) -#define TSC2101_REG_TEMPMIN TSC2101_P1_REG(0x7) -#define TSC2101_REG_AUX1MAX TSC2101_P1_REG(0x8) -#define TSC2101_REG_AUX1MIN TSC2101_P1_REG(0x9) -#define TSC2101_REG_AUX2MAX TSC2101_P1_REG(0xa) -#define TSC2101_REG_AUX2MIN TSC2101_P1_REG(0xb) -#define TSC2101_REG_MEASURE TSC2101_P1_REG(0xc) -#define TSC2101_REG_DELAY TSC2101_P1_REG(0xd) - -/* Page 2 Registers */ -#define TSC2101_REG_AUDIOCON1 TSC2101_P2_REG(0x0) -#define TSC2101_REG_HEADSETPGA TSC2101_P2_REG(0x1) -#define TSC2101_REG_DACPGA TSC2101_P2_REG(0x2) -#define TSC2101_REG_MIXERPGA TSC2101_P2_REG(0x3) -#define TSC2101_REG_AUDIOCON2 TSC2101_P2_REG(0x4) -#define TSC2101_REG_PWRDOWN TSC2101_P2_REG(0x5) -#define TSC2101_REG_AUDIOCON3 TSC2101_P2_REG(0x6) -#define TSC2101_REG_DAEFC(x) TSC2101_P2_REG(0x7+x) -#define TSC2101_REG_PLL1 TSC2101_P2_REG(0x1b) -#define TSC2101_REG_PLL2 TSC2101_P2_REG(0x1c) -#define TSC2101_REG_AUDIOCON4 TSC2101_P2_REG(0x1d) -#define TSC2101_REG_HANDSETPGA TSC2101_P2_REG(0x1e) -#define TSC2101_REG_BUZZPGA TSC2101_P2_REG(0x1f) -#define TSC2101_REG_AUDIOCON5 TSC2101_P2_REG(0x20) -#define TSC2101_REG_AUDIOCON6 TSC2101_P2_REG(0x21) -#define TSC2101_REG_AUDIOCON7 TSC2101_P2_REG(0x22) -#define TSC2101_REG_GPIO TSC2101_P2_REG(0x23) -#define TSC2101_REG_AGCCON TSC2101_P2_REG(0x24) -#define TSC2101_REG_DRVPWRDWN TSC2101_P2_REG(0x25) -#define TSC2101_REG_MICAGC TSC2101_P2_REG(0x26) -#define TSC2101_REG_CELLAGC TSC2101_P2_REG(0x27) - -/* Page 2 Registers */ -#define TSC2101_REG_BUFLOC(x) TSC2101_P3_REG(x) - -/* Status Register Masks */ - -#define TSC2101_STATUS_T2STAT (1 << 1) -#define TSC2101_STATUS_T1STAT (1 << 2) -#define TSC2101_STATUS_AX2STAT (1 << 3) -#define TSC2101_STATUS_AX1STAT (1 << 4) -#define TSC2101_STATUS_BSTAT (1 << 6) -#define TSC2101_STATUS_Z2STAT (1 << 7) -#define TSC2101_STATUS_Z1STAT (1 << 8) -#define TSC2101_STATUS_YSTAT (1 << 9) -#define TSC2101_STATUS_XSTAT (1 << 10) -#define TSC2101_STATUS_DAVAIL (1 << 11) -#define TSC2101_STATUS_HCTLM (1 << 12) -#define TSC2101_STATUS_PWRDN (1 << 13) -#define TSC2101_STATUS_PINTDAV_SHIFT (14) -#define TSC2101_STATUS_PINTDAV_MASK (0x03) - - - - - - - -#define TSC2101_ADC_PSM (1<<15) // pen status mode on ctrlreg adc -#define TSC2101_ADC_STS (1<<14) // stop continuous scanning. -#define TSC2101_ADC_AD3 (1<<13) -#define TSC2101_ADC_AD2 (1<<12) -#define TSC2101_ADC_AD1 (1<<11) -#define TSC2101_ADC_AD0 (1<<10) -#define TSC2101_ADC_ADMODE(x) ((x<<10) & TSC2101_ADC_ADMODE_MASK) -#define TSC2101_ADC_ADMODE_MASK (0xf<<10) - -#define TSC2101_ADC_RES(x) ((x<<8) & TSC2101_ADC_RES_MASK ) -#define TSC2101_ADC_RES_MASK (0x3<<8) -#define TSC2101_ADC_RES_12BITP (0) // 12-bit ADC resolution (default) -#define TSC2101_ADC_RES_8BIT (1) // 8-bit ADC resolution -#define TSC2101_ADC_RES_10BIT (2) // 10-bit ADC resolution -#define TSC2101_ADC_RES_12BIT (3) // 12-bit ADC resolution - -#define TSC2101_ADC_AVG(x) ((x<<6) & TSC2101_ADC_AVG_MASK ) -#define TSC2101_ADC_AVG_MASK (0x3<<6) -#define TSC2101_ADC_NOAVG (0) // a-d does no averaging -#define TSC2101_ADC_4AVG (1) // a-d does averaging of 4 samples -#define TSC2101_ADC_8AVG (2) // a-d does averaging of 8 samples -#define TSC2101_ADC_16AVG (3) // a-d does averaging of 16 samples - -#define TSC2101_ADC_CL(x) ((x<<4) & TSC2101_ADC_CL_MASK ) -#define TSC2101_ADC_CL_MASK (0x3<<4) -#define TSC2101_ADC_CL_8MHZ_8BIT (0) -#define TSC2101_ADC_CL_4MHZ_10BIT (1) -#define TSC2101_ADC_CL_2MHZ_12BIT (2) -#define TSC2101_ADC_CL_1MHZ_12BIT (3) -#define TSC2101_ADC_CL0 (1<< 4) - -/* ADC - Panel Voltage Stabilisation Time */ -#define TSC2101_ADC_PV(x) ((x<<1) & TSC2101_ADC_PV_MASK ) -#define TSC2101_ADC_PV_MASK (0x7<<1) -#define TSC2101_ADC_PV_100ms (0x7) /* 100ms */ -#define TSC2101_ADC_PV_50ms (0x6) /* 50ms */ -#define TSC2101_ADC_PV_10ms (0x5) /* 10ms */ -#define TSC2101_ADC_PV_5ms (0x4) /* 5ms */ -#define TSC2101_ADC_PV_1ms (0x3) /* 1ms */ -#define TSC2101_ADC_PV_500us (0x2) /* 500us */ -#define TSC2101_ADC_PV_100us (0x1) /* 100us */ -#define TSC2101_ADC_PV_0s (0x0) /* 0s */ - -#define TSC2101_ADC_AVGFILT_MEAN (0<<0) /* Mean Average Filter */ -#define TSC2101_ADC_AVGFILT_MEDIAN (1<<0) /* Median Average Filter */ - -#define TSC2101_ADC_x (1<< 0) // don't care - -#define TSC2101_CONFIG_DAV (1<<6) - -#define TSC2101_KEY_STC (1<<15) // keypad status -#define TSC2101_KEY_SCS (1<<14) // keypad scan status - - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |