diff -Nu linux-2.6.8-rc1.orig/drivers/input/touchscreen/h1940ts.c linux-2.6.8-rc1/drivers/input/touchscreen/h1940ts.c
--- linux-2.6.8-rc1.orig/drivers/input/touchscreen/h1940ts.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.8-rc1/drivers/input/touchscreen/h1940ts.c	2004-07-21 23:51:23.000000000 +0200
@@ -0,0 +1,200 @@
+/*
+ *  Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
+ *  iPAQ H1940 touchscreen support
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/init.h>
+#include <linux/serio.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "asm/arch/regs-adc.h"
+
+MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
+MODULE_DESCRIPTION("h1940 touchscreen driver");
+MODULE_LICENSE("GPL");
+
+/*
+ * Definitions & global arrays.
+ */
+
+
+static char *h1940ts_name = "h1940 TouchScreen";
+
+/*
+ * Per-touchscreen data.
+ */
+
+struct h1940ts {
+	struct input_dev dev;
+	long xp;
+	long yp;
+	char phys[32];
+};
+
+static struct h1940ts ts;
+
+static irqreturn_t stylus_down(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned long adctsc;
+	unsigned long adccon;
+	unsigned long data0;
+	unsigned long data1;
+	disable_irq(IRQ_TC);
+	
+	adccon = __raw_readl(S3C2410_ADCCON);
+	adctsc = __raw_readl(S3C2410_ADCTSC);
+	data0  = __raw_readl(S3C2410_ADCDAT0);
+	data1  = __raw_readl(S3C2410_ADCDAT1);
+
+
+	printk(KERN_DEBUG "stylus down\n");
+	/* start X conversion */
+	adctsc &= ~0x07;
+	adctsc |= 1;
+	__raw_writel(adctsc,S3C2410_ADCTSC);
+	__raw_writel(adccon|1,S3C2410_ADCCON);
+
+	enable_irq(IRQ_TC);
+	return IRQ_HANDLED;
+}
+
+
+static irqreturn_t stylus_action(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned long adccon;
+	unsigned long data0;
+	unsigned long data1;
+	unsigned long adctsc;
+	
+	disable_irq(IRQ_ADC);
+
+	adccon = __raw_readl(S3C2410_ADCCON);
+	adctsc = __raw_readl(S3C2410_ADCTSC);
+
+	switch(adctsc & 3)
+	{
+		case 1: /* X conversion ended, starts Y conversion */
+			adctsc &= ~0x07;
+			adctsc |= 2;
+			__raw_writel(adctsc,S3C2410_ADCTSC);
+			data0  = __raw_readl(S3C2410_ADCDAT0);
+			ts.xp=data0&0x3FF;
+			printk(KERN_DEBUG "X : %ld, U/D: %ld\n",data0&0x3FF,data0>>15);
+			__raw_writel(adccon|1,S3C2410_ADCCON);
+			break;
+		default:
+			break;
+		case 2:
+			adctsc &= ~0x07;
+			adctsc |= 3;
+			__raw_writel(adctsc,S3C2410_ADCTSC);
+			data1  = __raw_readl(S3C2410_ADCDAT1);
+			ts.yp = data1&0x3FF;
+			printk(KERN_DEBUG "Y : %ld, U/D: %ld\n",data1&0x3FF,data1>>15);
+			input_report_abs(&ts.dev, ABS_X, ts.xp);
+			input_report_abs(&ts.dev, ABS_Y, ts.yp);
+			input_report_key(&ts.dev, BTN_TOUCH, 1);
+			input_sync(&ts.dev);
+
+			/* if stylus down, starts X conversion */
+			if (!(data1>>15))
+			{
+				adctsc &= ~0x07;
+				adctsc |= 1;
+				__raw_writel(adctsc,S3C2410_ADCTSC);
+				__raw_writel(adccon|1,S3C2410_ADCCON);
+			}
+			break;
+	}
+
+	enable_irq(IRQ_ADC);
+	return IRQ_HANDLED;
+}
+
+/*
+ * The functions for inserting/removing us as a module.
+ */
+
+int __init h1940ts_init(void)
+{
+	
+	printk(KERN_DEBUG "Entering h1940ts_connect\n");
+
+
+	/* Initialise registers */
+	__raw_writel(0xcc78,  S3C2410_ADCCON);
+	__raw_writel(  0xD3,  S3C2410_ADCTSC);
+	__raw_writel(0x2710,  S3C2410_ADCDLY);
+	__raw_writel(0xb1b4, S3C2410_ADCDAT0);
+	__raw_writel(0xb24c, S3C2410_ADCDAT1);
+
+	
+	memset(&ts, 0, sizeof(struct h1940ts));
+
+	init_input_dev(&ts.dev);
+	ts.dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	ts.dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+/*	input_set_abs_params(&ts.dev, ABS_X, 0, 0x3FF, 0, 0);
+	input_set_abs_params(&ts.dev, ABS_Y, 0, 0x3FF, 0, 0);*/
+
+	sprintf(ts.phys, "ts0");
+
+	ts.dev.private = &ts;
+	ts.dev.name = h1940ts_name;
+	ts.dev.phys = ts.phys;
+	ts.dev.id.bustype = BUS_RS232;
+	ts.dev.id.vendor = 0xDEAD;
+	ts.dev.id.product = 0xBEEF;
+	ts.dev.id.version = 0x0100;
+
+        if (request_irq(IRQ_ADC, stylus_action, SA_SAMPLE_RANDOM,
+			"h1940_action", &ts.dev)) {
+		printk(KERN_ERR "h1940ts.c: Could not allocate ts IRQ_ADC !\n");
+		return -EIO;
+	}
+        if (request_irq(IRQ_TC, stylus_down, SA_SAMPLE_RANDOM,
+			"h1940_action", &ts.dev)) {
+		printk(KERN_ERR "h1940ts.c: Could not allocate ts IRQ_TC !\n");
+		return -EIO;
+	}
+
+	printk(KERN_DEBUG "input: %s on ts0\n", h1940ts_name);
+
+	input_register_device(&ts.dev);
+	return 0;
+}
+
+void __exit h1940ts_exit(void)
+{
+	disable_irq(IRQ_ADC);
+	disable_irq(IRQ_TC);
+	free_irq(IRQ_TC,&ts.dev);
+	free_irq(IRQ_ADC,&ts.dev);
+	
+	input_unregister_device(&ts.dev);
+}
+
+module_init(h1940ts_init);
+module_exit(h1940ts_exit);
diff -Nu linux-2.6.8-rc1.orig/drivers/input/touchscreen/Kconfig linux-2.6.8-rc1/drivers/input/touchscreen/Kconfig
--- linux-2.6.8-rc1.orig/drivers/input/touchscreen/Kconfig	2004-07-18 02:13:05.000000000 +0200
+++ linux-2.6.8-rc1/drivers/input/touchscreen/Kconfig	2004-07-20 02:04:35.000000000 +0200
@@ -22,6 +22,19 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called h3600_ts_input.
 
+config TOUCHSCREEN_H1940
+	tristate "Compaq iPAQ H1940 touchscreen input driver"
+	depends on ARCH_H1940 && INPUT && INPUT_TOUCHSCREEN
+	select SERIO
+	help
+	  Say Y here if you have the h1940 touchscreen.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called h1940ts_input.
+
+
 config TOUCHSCREEN_GUNZE
 	tristate "Gunze AHL-51S touchscreen"
 	depends on INPUT && INPUT_TOUCHSCREEN
diff -Nu linux-2.6.8-rc1.orig/drivers/input/touchscreen/Makefile linux-2.6.8-rc1/drivers/input/touchscreen/Makefile
--- linux-2.6.8-rc1.orig/drivers/input/touchscreen/Makefile	2004-07-18 02:13:05.000000000 +0200
+++ linux-2.6.8-rc1/drivers/input/touchscreen/Makefile	2004-07-20 02:05:11.000000000 +0200
@@ -4,5 +4,7 @@
 
 # Each configuration option enables a list of files.
 
+
 obj-$(CONFIG_TOUCHSCREEN_BITSY)	+= h3600_ts_input.o
+obj-$(CONFIG_TOUCHSCREEN_H1940)	+= h1940ts.o
 obj-$(CONFIG_TOUCHSCREEN_GUNZE)	+= gunze.o
diff -Nu linux-2.6.8-rc1.orig/arch/arm/mach-s3c2410/irq.c linux-2.6.8-rc1/arch/arm/mach-s3c2410/irq.c
--- linux-2.6.8-rc1.orig/arch/arm/mach-s3c2410/irq.c	2004-07-18 02:12:56.000000000 +0200
+++ linux-2.6.8-rc1/arch/arm/mach-s3c2410/irq.c	2004-07-20 21:55:42.000000000 +0200
@@ -397,6 +397,36 @@
 #endif
 
 /* irq demux */
+static void s3c_irq_demux_adc(unsigned int irq,
+		    struct irqdesc *desc,
+		    struct pt_regs *regs)
+{
+	unsigned int subsrc, submsk;
+	unsigned int offset = 9;
+	struct irqdesc *mydesc;
+
+	/* read the current pending interrupts, and the mask
+	 * for what it is available */
+
+	subsrc = __raw_readl(S3C2410_SUBSRCPND);
+	submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+	subsrc &= ~submsk;
+	subsrc >>= offset;
+	subsrc &= 3;
+
+	if (subsrc != 0) {
+		if (subsrc & 1) {
+			mydesc = irq_desc + IRQ_TC;
+			mydesc->handle( IRQ_TC, mydesc, regs);
+		}
+ 		if (subsrc & 2) {
+			mydesc = irq_desc + IRQ_ADC;
+			mydesc->handle(IRQ_ADC, mydesc, regs);
+		}
+	}
+}
+
 
 
 static void s3c_irq_demux_uart(unsigned int start,
@@ -509,7 +539,7 @@
 
 	irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
 
-	for (irqno = IRQ_EINT0; irqno < IRQ_ADCPARENT; irqno++) {
+	for (irqno = IRQ_EINT0; irqno <= IRQ_ADCPARENT; irqno++) {
 		/* set all the s3c2410 internal irqs */
 
 		switch (irqno) {
@@ -550,7 +580,7 @@
 	set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
 	set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
 	//set_irq_chained_handler(IRQ_LCD, s3c_irq_demux_);
-	//set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_);
+	set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
 
 
 	/* external interrupts */
@@ -589,6 +619,7 @@
 
 	for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) {
 		irqdbf("registering irq %d (s3c adc irq)\n", irqno);
+		printk(KERN_INFO "registering irq %d (s3c adc irq)\n", irqno);
 		set_irq_chip(irqno, &s3c_irq_adc);
 		set_irq_handler(irqno, do_edge_IRQ);
 		set_irq_flags(irqno, IRQF_VALID);
diff -Nu linux-2.6.8-rc1.orig/include/asm-arm/arch-s3c2410/regs-adc.h linux-2.6.8-rc1/include/asm-arm/arch-s3c2410/regs-adc.h
--- linux-2.6.8-rc1.orig/include/asm-arm/arch-s3c2410/regs-adc.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.8-rc1/include/asm-arm/arch-s3c2410/regs-adc.h	2004-07-20 01:37:54.000000000 +0200
@@ -0,0 +1,36 @@
+#ifndef __ASM_ARCH_REGS_ADC_H
+#define __ASM_ARCH_REGS_ADC_H 
+
+#define S3C2410_ADCREG(x) ((x) + S3C2410_VA_ADC)
+
+#define S3C2410_ADCCON		S3C2410_ADCREG(0x00)
+#define S3C2410_ECFLG		(1<<15)
+#define S3C2410_PRSCEN		(1<<14)
+#define S3C2410_PRSCVL(x)	((x)<<6)
+#define S3C2410_SEL_MUX(x)	((x)<<3)
+#define S3C2410_STDBM		(1<<2)
+#define S3C2410_READ_START	(1<<1)
+#define S3C2410_ENABLE_START	(1<<0)
+
+#define S3C2410_ADCTSC		S3C2410_ADCREG(0x04)
+#define S3C2410_YM_SEN		(1<<7)
+#define S3C2410_YP_SEN		(1<<6)
+#define S3C2410_XM_SEN		(1<<5)
+#define S3C2410_XP_SEN		(1<<4)
+#define S3C2410_PULL_UP		(1<<3)
+#define S3C2410_AUTO_PST	(1<<2)
+#define S3C2410_XY_PST(x)	(x)
+
+#define S3C2410_ADCDLY	   	S3C2410_ADCREG(0x08)
+#define S3C2410_DELAY(x)	(x)
+
+#define S3C2410_ADCDAT0	   	S3C2410_ADCREG(0x0C)
+#define S3C2410_ADCDAT1	   	S3C2410_ADCREG(0x10)
+#define S3C2410_DAT_UPDOWN	(1<<15)
+#define S3C2410_DAT_AUTO_PST	(1<<14)
+#define S3C2410_DAT_XY_PST(x)	((x)<<12)
+
+
+#endif 
+
+
