Penmount LPC driver for Dialogue Flybook tablet PC. Original version by Heikki Linnakangas. Initialization sequence and other improvements by Elmar Hanlhofer. Further fixes by Cristoph Pittracher. diff -c -N -r linux-2.6.15.1/drivers/input/touchscreen/Kconfig linux-2.6.15.1-penmountlpc/drivers/input/touchscreen/Kconfig *** linux-2.6.15.1/drivers/input/touchscreen/Kconfig Sun Jan 15 08:16:02 2006 --- linux-2.6.15.1-penmountlpc/drivers/input/touchscreen/Kconfig Sat Jan 21 12:37:04 2006 *************** *** 95,98 **** --- 95,109 ---- To compile this driver as a module, choose M here: the module will be called hp680_ts_input. + config TOUCHSCREEN_PENMOUNTLPC + tristate "Penmount LPC touchscreen" + help + Say Y here if you have the Penmount LPC touchscreen connected to + your system. For example, a Dialogue Flybook. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called penmountlpc. + endif diff -c -N -r linux-2.6.15.1/drivers/input/touchscreen/Makefile linux-2.6.15.1-penmountlpc/drivers/input/touchscreen/Makefile *** linux-2.6.15.1/drivers/input/touchscreen/Makefile Sun Jan 15 08:16:02 2006 --- linux-2.6.15.1-penmountlpc/drivers/input/touchscreen/Makefile Sat Jan 21 12:37:04 2006 *************** *** 11,13 **** --- 11,14 ---- obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o + obj-$(CONFIG_TOUCHSCREEN_PENMOUNTLPC) += penmountlpc.o diff -c -N -r linux-2.6.15.1/drivers/input/touchscreen/penmountlpc.c linux-2.6.15.1-penmountlpc/drivers/input/touchscreen/penmountlpc.c *** linux-2.6.15.1/drivers/input/touchscreen/penmountlpc.c Thu Jan 1 02:00:00 1970 --- linux-2.6.15.1-penmountlpc/drivers/input/touchscreen/penmountlpc.c Sat Jan 21 12:40:02 2006 *************** *** 0 **** --- 1,126 ---- + //========================================================================== + // eventdevice driver for penmount touchscreen + // Licence GPL + // + // Driver written by Heikki Linnakangas + // Driver modified by Elmar Hanlhofer development@plop.at http://www.plop.at + // Driver modified by Christoph Pittracher + // + // Changelog: + // + // 20060113 fixed small 2.6.15 issues by Christoph Pittracher + // 20050902 cleanup, irq data check by Christoph Pittracher + // 20050624 init sequence and timeout optimized by Elmar Hanlhofer + // 20050622 some evbit fixes by Christoph Pittracher + // 20050617 added init sequence and more debug messages by Elmar Hanlhofer + // + //========================================================================== + + #include + #include + #include + #include + #include + + #include + #include + + MODULE_AUTHOR("Heikki Linnakangas "); + MODULE_DESCRIPTION("Penmount LPC touchscreen driver"); + MODULE_LICENSE("GPL"); + + #define PENMOUNT_PORT 0x0338 + #define PENMOUNT_IRQ 6 + #define PENMOUNT_INITMAX 5 + #define TIMEOUT 25000 + + struct input_dev* penmount_dev; + + static void poll_penmount(void) { + unsigned short xa, xb, ya, yb; + unsigned char touch, flag; + + flag = inb_p(PENMOUNT_PORT + 4); + if (flag) { + touch = inb_p(PENMOUNT_PORT); + xa = inb_p(PENMOUNT_PORT); + inb_p(PENMOUNT_PORT + 4); + xb = inb_p(PENMOUNT_PORT); + inb_p(PENMOUNT_PORT + 4); + ya = inb_p(PENMOUNT_PORT); + inb_p(PENMOUNT_PORT + 4); + yb = inb_p(PENMOUNT_PORT); + + if ((touch | 0x40) != 0xFF || (xa & 0xF8) != 0 || (ya & 0xF8) != 0 || (xb & 0x80) != 0 || (yb & 0x80) != 0) + return; + + input_report_abs(penmount_dev, ABS_X, xa * 128 + xb); + input_report_abs(penmount_dev, ABS_Y, ya * 128 + yb); + input_report_key(penmount_dev, BTN_LEFT, (touch & 0x40) != 0); + input_sync(penmount_dev); + // printk(KERN_INFO "penmount (%d|%d) %s\n", xa*128+xb, ya*128+yb, (touch & 0x40) ? "press" : "release"); + } + } + + static irqreturn_t penmount_interrupt(int irq, void *dummy, struct pt_regs *fp) { + poll_penmount(); + return IRQ_HANDLED; + } + + static int __init penmount_init(void) { + unsigned short initPorts[] = { PENMOUNT_PORT+4, PENMOUNT_PORT+4, PENMOUNT_PORT+4, PENMOUNT_PORT, PENMOUNT_PORT+4, PENMOUNT_PORT+4 }; + unsigned char initWData[] = { 0xf8, 0xfb, 0xf0, 0xf2, 0xf1, 0xf9 }; + unsigned char initRData[] = { 0x09, 0x09, 0x09, 0xf0, 0x09 }; + int initDataCount = 0; + int timeout; + + for (initDataCount = 0; initDataCount < PENMOUNT_INITMAX; initDataCount++) { + outb_p(initWData[initDataCount], initPorts[initDataCount]); + timeout = TIMEOUT; + while (timeout-- && initRData[initDataCount] != inb_p(initPorts[initDataCount])) + udelay(10); + + if (timeout == 0) { + printk(KERN_ERR "penmountlpc.c: timeout\n"); + return -EPERM; + } + } + + outb_p(initWData[PENMOUNT_INITMAX], initPorts[PENMOUNT_INITMAX]); + + if (request_irq(PENMOUNT_IRQ, penmount_interrupt, 0, "penmountlpc", NULL)) + return -EBUSY; + + penmount_dev = input_allocate_device(); + if (!penmount_dev) + return -ENOMEM; + + penmount_dev->name = "PenmountLPC TouchScreen"; + penmount_dev->id.bustype = BUS_ISA; + penmount_dev->id.vendor = 0; + penmount_dev->id.product = 0; + penmount_dev->id.version = 0; + + input_set_abs_params(penmount_dev, ABS_X, 0, 128 * 7, 4, 0); + input_set_abs_params(penmount_dev, ABS_Y, 0, 128 * 7, 4, 0); + + penmount_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY); + penmount_dev->absbit[LONG(ABS_X)] = BIT(ABS_X); + penmount_dev->absbit[LONG(ABS_Y)] |= BIT(ABS_Y); + penmount_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT); + + input_register_device(penmount_dev); + printk(KERN_ERR "penmountlpc.c: init finished\n"); + + return 0; + } + + static void __exit penmount_exit(void) { + input_unregister_device(penmount_dev); + free_irq(PENMOUNT_IRQ, NULL); + printk(KERN_ERR "penmountlpc.c: driver removed\n"); + } + + module_init(penmount_init); + module_exit(penmount_exit); +