
#
# Patch managed by http://www.holgerschurig.de/patcher.html
#

--- /dev/null
+++ linux-2.6.10/drivers/input/touchscreen/ads7846_ts.c
@@ -0,0 +1,719 @@
+/*
+ * linux/drivers/char/ads7846_ts.c
+ *
+ * Copyright (c) 2001 Lineo Japan, Inc.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Based on:
+ *   cotulla_ts.c
+ *
+ */
+
+/***************************************************************************/
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/delay.h>
+#include <linux/ioctl.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+
+#include <asm/irq.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/corgi.h>
+
+#include "ads7846_ts.h"
+
+//#include <asm/sharp_apm.h>
+
+#define PMPD_MODE_ACTIVE  0
+#define PMPD_MODE_SUSPEND 1
+static char PowerDownMode = PMPD_MODE_ACTIVE;
+
+extern unsigned long corgi_ssp_ads7846_putget(unsigned long);
+extern unsigned long corgi_ssp_ads7846_put(ulong data);
+extern unsigned long corgi_ssp_ads7846_get(void);
+extern void corgi_ssp_ads7846_lock(void);
+extern void corgi_ssp_ads7846_unlock(void);
+
+static irqreturn_t ts_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void ts_interrupt_main(int irq, int isTimer);
+static struct timer_list tp_main_timer;
+
+#define BUFSIZE 128
+static int raw_max_x, raw_max_y, res_x, res_y, raw_min_x, raw_min_y, xyswap;
+static int cal_ok, x_rev, y_rev;
+struct fasync_struct *fasync;
+int ts_type = 0;
+static char ispass = 1;
+ 
+typedef struct {
+   short pressure;
+   short x;
+   short y;
+   short millisecs;
+} TS_EVENT;
+
+static TS_EVENT tbuf[BUFSIZE], tc, samples[3];
+static DECLARE_WAIT_QUEUE_HEAD(queue);
+static int head, tail;
+static char pendown = 0;
+static unsigned long Pressure;
+
+static long wait_after_sync_hs = 0;
+static unsigned long wait_time = 0;
+#define WAIT_AFTER_SYNC_HS wait_after_sync_hs
+#define SyncHS()	while((GPLR(CORGI_GPIO_HSYNC) & GPIO_bit(CORGI_GPIO_HSYNC)) == 0);\
+while((GPLR(CORGI_GPIO_HSYNC) & GPIO_bit(CORGI_GPIO_HSYNC)) != 0);
+#define CCNT(a)		asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a))
+#define CCNT_ON()	{int pmnc = 1; asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(pmnc));}
+#define CCNT_OFF()	{int pmnc = 0; asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(pmnc));}
+
+/*
+#define WAIT_HS_333_VGA					5791	// 17.995us
+#define WAIT_HS_400_VGA					7013	// 17.615us
+#define WAIT_HS_471_VGA					8257	// 17.615us
+#define WAIT_HS_400_VGA_FASTSYSCLK		5260	// 17.615us
+#define WAIT_HS_471_VGA_FASTSYSCLK		6192	// 17.615us
+
+#define WAIT_HS_400_VGA640				21376	// 17.615us
+#define WAIT_HS_471_VGA640				25170	// 17.615us
+#define WAIT_HS_400_VGA640_FASTSYSCLK	16032	// 17.615us
+#define WAIT_HS_471_VGA640_FASTSYSCLK	18878	// 17.615us
+
+#define WAIT_HS_333_QVGA	13969	// 42.100us
+#define WAIT_HS_400_QVGA	16621	// 41.750us
+#define WAIT_HS_471_QVGA	19571	// 41.750us
+*/
+
+#define WAIT_HS_333_VGA					5970	// 17.995us
+#define WAIT_HS_400_VGA					7013	// 17.615us
+#define WAIT_HS_471_VGA					8312	// 17.615us
+#define WAIT_HS_400_VGA_FASTSYSCLK		5260	// 13.211us
+#define WAIT_HS_471_VGA_FASTSYSCLK		6234	// 13.211us
+
+#define WAIT_HS_400_VGA640				21276	// 53.440us
+#define WAIT_HS_471_VGA640				25216	// 53.440us
+#define WAIT_HS_400_VGA640_FASTSYSCLK	15957	// 40.080us
+#define WAIT_HS_471_VGA640_FASTSYSCLK	18912	// 40.080us
+
+#define WAIT_HS_333_QVGA	13968	// 42.100us
+#define WAIT_HS_400_QVGA	16622	// 41.750us
+#define WAIT_HS_471_QVGA	19700	// 41.750us
+
+//extern unsigned long cccr_reg;
+
+extern int w100fb_get_xres(void);
+extern int w100fb_get_blanking(void);
+extern int w100fb_get_fastsysclk(void);
+
+static void calc_waittime(void) 
+{
+	int w100fb_xres = w100fb_get_xres();
+	//	if (cccr_reg == 0x145) {
+//		// 332MHz
+//		if (w100fb_xres == 480) {
+//			wait_time = WAIT_HS_333_VGA - wait_after_sync_hs;
+//		}else {
+//			wait_time = WAIT_HS_333_QVGA - wait_after_sync_hs;
+//		}
+//	}else if(cccr_reg == 0x242 || cccr_reg == 0x162) {
+//
+//		// 471MHz
+//		if (w100fb_get_fastsysclk() == 100 ){
+//			if (w100fb_xres == 480) {
+//				wait_time = WAIT_HS_471_VGA_FASTSYSCLK - wait_after_sync_hs;
+//			}else if(w100fb_xres == 640){
+//				wait_time = WAIT_HS_471_VGA640_FASTSYSCLK - wait_after_sync_hs;
+//			}else {
+//				wait_time = WAIT_HS_471_QVGA - wait_after_sync_hs;
+//			}
+//		}else {
+//			if (w100fb_xres == 480) {
+//				wait_time = WAIT_HS_471_VGA - wait_after_sync_hs;
+//			}else if(w100fb_xres == 640){
+//				wait_time = WAIT_HS_471_VGA640 - wait_after_sync_hs;
+//			}else {
+//				wait_time = WAIT_HS_471_QVGA - wait_after_sync_hs;
+//			}
+//		}
+//
+//	}else {
+
+		// 400MHz
+		if (w100fb_get_fastsysclk() == 100 ){
+			if (w100fb_xres == 480) {
+				wait_time = WAIT_HS_400_VGA_FASTSYSCLK - wait_after_sync_hs;
+			}else if(w100fb_xres == 640){
+				wait_time = WAIT_HS_400_VGA640_FASTSYSCLK - wait_after_sync_hs;
+			}else {
+				wait_time = WAIT_HS_400_QVGA - wait_after_sync_hs;
+			}
+		}else {
+			if (w100fb_xres == 480) {
+				wait_time = WAIT_HS_400_VGA - wait_after_sync_hs;
+			}else if(w100fb_xres == 640){
+				wait_time = WAIT_HS_400_VGA640 - wait_after_sync_hs;
+			}else {
+				wait_time = WAIT_HS_400_QVGA - wait_after_sync_hs;
+			}
+		}
+//	}
+}
+
+static int sync_receive_data_send_cmd(int doRecive,int doSend,unsigned int address)
+{
+	int pos = 0;
+	unsigned long timer1=0,timer2;
+	int sCmd;
+
+	sCmd = (1u << ADSCTRL_PD0_SH) | (1u << ADSCTRL_PD1_SH) |
+			(address << ADSCTRL_ADR_SH) | (1u << ADSCTRL_STS_SH);
+
+	if (w100fb_get_blanking()) {
+		if(doRecive){
+			pos = corgi_ssp_ads7846_get();
+		}
+		if(doSend) {
+			/* dummy command */
+			corgi_ssp_ads7846_put(sCmd);
+			corgi_ssp_ads7846_get();
+			corgi_ssp_ads7846_put(sCmd);
+		}
+		return pos;
+	}
+
+	if(doSend) {
+		CCNT_ON();
+		/* polling HSync */
+		SyncHS();
+		/* get CCNT */
+		CCNT(timer1);
+	}		
+
+	if(doRecive){
+		pos = corgi_ssp_ads7846_get();
+	}
+
+	if(doSend) {
+		/* dummy command */
+		corgi_ssp_ads7846_put(sCmd);
+		corgi_ssp_ads7846_get();
+
+		/* Wait after HSync */
+		CCNT(timer2);
+		if ((timer2-timer1) > wait_time) 
+		{
+			/* timeout */
+			SyncHS();
+			/* get OSCR */
+			CCNT(timer1);
+			/* Wait after HSync */
+			CCNT(timer2);
+		}
+		while((timer2-timer1) < wait_time){
+			CCNT(timer2);
+		}
+		corgi_ssp_ads7846_put(sCmd);
+		CCNT_OFF();
+	}
+	return pos;
+}
+
+
+#define TOUCH_PANEL_AVERAGE 1
+
+void read_xydata(ts_pos_t *tp)
+{
+	unsigned int z1,z2;
+	unsigned int x,y,tx,ty;
+	unsigned long flags;
+	int i, fail;
+
+	GPDR(CORGI_GPIO_HSYNC) &= ~GPIO_bit(CORGI_GPIO_HSYNC);
+
+	tx = 0;
+	ty = 0;
+	fail = 0;
+
+	/* critical section */
+	local_irq_save(flags);
+	corgi_ssp_ads7846_lock();
+	calc_waittime();
+
+	for (i = 0; i < TOUCH_PANEL_AVERAGE; i++) {
+
+		/* Y-axis */
+		sync_receive_data_send_cmd(0, 1, 1u);
+
+		/* Y-axis */
+		sync_receive_data_send_cmd(1, 1, 1u);
+
+		/* X-axis */
+		y = sync_receive_data_send_cmd(1, 1, 5u);
+
+		/* Z1 */
+		x = sync_receive_data_send_cmd(1, 1, 3u);
+
+		/* Z2 */
+		z1 = sync_receive_data_send_cmd(1, 1, 4u);
+		z2 = sync_receive_data_send_cmd(1, 0, 4u);
+
+		if ((z1 == 0) || ((x * (z2 -z1) / z1) >= 15000)) {
+			fail++;
+		}
+		else {
+			tx += x;
+			ty += y;
+		}
+	}
+
+	/* Power-Down Enable */
+	corgi_ssp_ads7846_put((1u << ADSCTRL_ADR_SH) | (1u << ADSCTRL_STS_SH));
+	corgi_ssp_ads7846_get();
+	
+	corgi_ssp_ads7846_unlock();
+	local_irq_restore(flags);
+
+	printk("fail %d\n", fail); //rpdebug
+
+	if (fail == TOUCH_PANEL_AVERAGE) {
+		Pressure = 0;
+		printk("pen up\n");//rpdebug
+	}
+	else {
+		Pressure = 1;
+		tp->xd = tx / (TOUCH_PANEL_AVERAGE - fail);
+		tp->yd = ty / (TOUCH_PANEL_AVERAGE - fail);
+		printk("pen position (%d,%d)\n", tx, ty); //rpdebug
+	}
+}
+
+static void print_par(void)
+{
+	 printk(" Kernel ==> cal_ok = %d\n",cal_ok);
+	 printk(" Kernel ==> raw_max_x = %d\n",raw_max_x);
+	 printk(" Kernel ==> raw_max_y = %d\n",raw_max_y);
+	 printk(" Kernel ==> res_x = %d\n",res_x);
+	 printk(" Kernel ==> res_y = %d\n",res_y);
+	 printk(" Kernel ==> raw_min_x = %d\n",raw_min_x);
+	 printk(" Kernel ==> raw_min_y = %d\n",raw_min_y);
+	 printk(" Kernel ==> xyswap = %d\n",xyswap);
+	 printk(" Kernel ==> x_rev = %d\n",x_rev);
+	 printk(" Kernel ==> y_rev = %d\n",y_rev);
+}
+
+void ts_clear(void)
+{
+	int i;
+	
+	for (i =0; i < BUFSIZE; i++) {
+		tbuf[i].pressure = 0;
+		tbuf[i].x = 0;
+		tbuf[i].y = 0;
+		tbuf[i].millisecs = 0;
+	}
+	head = tail = pendown = 0;
+}
+
+static TS_EVENT get_data(void)
+{
+   int last = tail;
+   if (++tail == BUFSIZE) { tail = 0; }
+   return tbuf[last];
+}
+
+static void new_data(void)
+{
+
+	if( PowerDownMode != PMPD_MODE_ACTIVE )
+		return;
+
+	if (tc.x > X_AXIS_MAX || tc.x < X_AXIS_MIN ||
+			tc.y > Y_AXIS_MAX || tc.y < Y_AXIS_MIN) {
+		printk("over range (%d,%d)\n",tc.x,tc.y); //rpdebug
+		return;
+	}
+	if (tc.pressure) {
+	} else
+		if (pendown == 0) {
+			return;
+		}
+
+	tc.millisecs = jiffies;
+
+	if (tc.pressure == 0) {
+		if (ispass == 0) {
+			samples[0].pressure = 0;
+			tbuf[head++] = samples[0];
+			if (head >= BUFSIZE) { head = 0; }
+			if (head == tail && ++tail >= BUFSIZE) { tail = 0; }
+		}
+		ispass = 1;
+	}
+	else {
+		if (ispass == 0) {
+			tbuf[head++] = samples[0];
+			samples[0] = tc;
+			if (head >= BUFSIZE) { head = 0; }
+			if (head == tail && ++tail >= BUFSIZE) { tail = 0; }
+		}
+		else if (ispass == 1) {
+			ispass = 2;
+		}
+		else {
+			ispass = 0;
+			samples[0] = tc;
+		}
+	}
+	if (fasync)	kill_fasync(&fasync, SIGIO, POLL_IN);
+	wake_up_interruptible(&queue);
+}
+
+
+static void cotulla_main_ts_timer(unsigned long irq)
+{
+	ts_interrupt_main(irq, 1);
+}
+
+static irqreturn_t ts_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	ts_interrupt_main(irq, 0);
+	return IRQ_HANDLED;
+}
+
+static void ts_interrupt_main(int irq, int isTimer)
+{
+	ts_pos_t pos_dt;
+	static TS_EVENT before_data = { pressure: 0 };
+	
+	if (isTimer) printk("Timer called\n");
+	else printk("TS Interrupt\n");
+	if ((GPLR(CORGI_GPIO_TP_INT) & GPIO_bit(CORGI_GPIO_TP_INT)) == 0) {
+
+		/* Disable Falling Edge */
+		set_irq_type(CORGI_IRQ_GPIO_TP_INT,IRQT_NOEDGE);
+		
+		read_xydata(&pos_dt);
+
+		tc.x = pos_dt.xd;
+		tc.y = pos_dt.yd;
+
+		if( pos_dt.xd && pos_dt.yd && Pressure ) {
+
+			tc.pressure = 500;
+
+			before_data = tc;
+			pendown = 1;
+			new_data();
+		}
+
+		mod_timer(&tp_main_timer, jiffies + HZ / 100);
+	} else {
+
+		if( pendown == 1 || pendown == 2 ){
+			mod_timer(&tp_main_timer, jiffies + HZ / 100);
+			pendown ++;
+			return;
+		}
+
+		if (pendown) {
+			tc = before_data;
+			tc.pressure = 0;
+			new_data();
+		}
+
+		/* Enable Falling Edge */
+		set_irq_type(CORGI_IRQ_GPIO_TP_INT,IRQT_FALLING);
+		pendown = 0;
+
+		PowerDownMode = PMPD_MODE_ACTIVE;
+	}
+}
+
+static void ts_hardware_init(void)
+{
+	/* Initiaize ADS7846 Difference Reference mode */
+	corgi_ssp_ads7846_putget(1u << ADSCTRL_PD0_SH) | (1u << ADSCTRL_PD1_SH) |
+			(1u << ADSCTRL_ADR_SH) | (1u << ADSCTRL_STS_SH);
+
+
+	/* Enable Falling Edge */
+	set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+}
+
+
+static int ts_open(struct inode *, struct file *);
+static int ts_release(struct inode *, struct file *);
+static int ts_fasync(int fd, struct file *filp, int on);
+static ssize_t ts_read(struct file *, char *, size_t, loff_t *);
+static ssize_t ts_write(struct file *, const char *, size_t, loff_t *);
+static unsigned int ts_poll(struct file *, poll_table *);
+static int ts_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+
+struct file_operations ts_fops = {
+	open:		ts_open,
+	release:	ts_release,
+	fasync:		ts_fasync,
+	read:		ts_read,
+	write:		ts_write,
+	poll:		ts_poll,
+	ioctl:		ts_ioctl,
+};
+
+static int corgits_remove(struct device *dev) 
+{
+	unregister_chrdev(TS_MAJOR, "ts");
+	free_irq(CORGI_IRQ_GPIO_TP_INT, NULL);
+	return 0;
+}
+
+static int __init corgits_probe(struct device *dev) 
+{
+	if ( register_chrdev(TS_MAJOR,"ts",&ts_fops) )
+				printk("unable to get major %d for touch screen\n", TS_MAJOR);
+
+	ts_clear();
+	raw_max_x = X_AXIS_MAX;
+	raw_max_y = Y_AXIS_MAX;
+	raw_min_x = X_AXIS_MIN;
+	raw_min_y = Y_AXIS_MIN;
+
+	res_x = 640;
+	res_y = 480;
+
+	cal_ok = 1;
+	x_rev = 0;
+	y_rev = 0;
+	xyswap = 0;
+
+	ts_hardware_init();
+	init_timer(&tp_main_timer);
+	tp_main_timer.data = CORGI_IRQ_GPIO_TP_INT;	
+	tp_main_timer.function = cotulla_main_ts_timer;
+
+	if (request_irq(CORGI_IRQ_GPIO_TP_INT, ts_interrupt, SA_INTERRUPT, "ts", NULL)) {
+		return -EBUSY;
+	}
+
+	printk("ADS7846 Touch Screen driver initialized\n");
+
+	return 0;
+}
+
+
+static int ts_open(struct inode *inode, struct file *file)
+{
+	if( iminor (inode) == 1 )
+		ts_type = 0;
+	else 	
+		ts_type = 1;
+
+	return 0;
+}
+
+
+static int ts_release(struct inode *inode, struct file *file)
+{
+	ts_fasync(-1, file, 0);
+	return 0;
+}
+
+static int ts_fasync(int fd, struct file *filp, int on)
+{
+	int retval;
+
+	retval = fasync_helper(fd, filp, on, &fasync);
+	if (retval < 0)
+		return retval;
+	return 0;
+}
+
+static ssize_t ts_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	TS_EVENT t, r;
+	int i;
+	
+	if (head == tail) {
+		if (file->f_flags & O_NONBLOCK) {
+			return -EAGAIN;
+		}
+		add_wait_queue(&queue, &wait);
+		current->state = TASK_INTERRUPTIBLE;
+		while ((head == tail)&& !signal_pending(current)) {
+			schedule();
+			current->state = TASK_INTERRUPTIBLE;
+		}
+		current->state = TASK_RUNNING;
+		remove_wait_queue(&queue, &wait);
+	}
+	
+	for (i = count ; i >= sizeof(TS_EVENT);
+			i -= sizeof(TS_EVENT), buffer += sizeof(TS_EVENT)) {
+		if (head == tail)
+			break;
+		t = get_data();
+
+		if (xyswap) {
+			short tmp = t.x;
+			t.x = t.y;
+			t.y = tmp;
+		}
+		if (cal_ok) {
+			r.x = (x_rev) ? ((raw_max_x - t.x) * res_x) / (raw_max_x - raw_min_x)
+		 		: ((t.x - raw_min_x) * res_x) / (raw_max_x - raw_min_x);
+			r.y = (y_rev) ? ((raw_max_y - t.y) * res_y) / (raw_max_y - raw_min_y)
+				: ((t.y - raw_min_y) * res_y) / (raw_max_y - raw_min_y);
+		} else {
+			r.x = t.x;
+			r.y = t.y;
+		}
+
+		r.pressure = t.pressure;
+		r.millisecs = t.millisecs;
+
+		copy_to_user(buffer,&r,sizeof(TS_EVENT));
+	}
+	return count - i;
+}
+
+static ssize_t	ts_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+{
+	char *endp;
+
+	wait_after_sync_hs = simple_strtol(buffer, &endp, 0);
+	printk("Wait_after_sync_hs: %d\n",(int) wait_after_sync_hs);
+	return count+endp-buffer;
+
+}
+
+static unsigned int ts_poll(struct file *filp, poll_table *wait)
+{
+	poll_wait(filp, &queue, wait);
+	if (head != tail)
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
+static int ts_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	switch(cmd){
+
+	case 3:
+		raw_max_x = arg;
+		break;
+	case 4:
+		raw_max_y = arg;
+		break;
+	case 5:
+		res_x = arg;
+		break;
+	case 6:
+		res_y = arg;
+		break;
+	case 10:
+		raw_min_x = arg;
+		break;
+	case 11:
+		raw_min_y = arg;
+		break;
+	case 12:			/* New attribute for portrait modes */
+		xyswap = arg;
+	case 13:		 /* 0 = Enable calibration ; 1 = Calibration OK */
+		cal_ok = arg;
+	case 14:		 /* Clear all buffer data */
+		ts_clear();
+		break;	
+	case 15:		 /* X axis reversed setting */
+		x_rev = arg;
+		break;
+	case 16:		 /* Y axis reversed setting */
+			y_rev = arg;
+		break;
+	case 17:		 /* Clear all buffer data */
+		print_par();
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int corgits_suspend(struct device *dev, uint32_t state, uint32_t level)
+{
+	if (level == SUSPEND_POWER_DOWN) {
+		unsigned long cmd;
+
+		//set_irq_type(CORGI_IRQ_GPIO_TP_INT,IRQT_NOEDGE);
+		if( pendown ){
+			del_timer(&tp_main_timer);
+			tc.pressure = 0;
+			new_data();
+			pendown = 0;
+		}
+		PowerDownMode = PMPD_MODE_SUSPEND;	
+
+		cmd = (1u << ADSCTRL_ADR_SH) | (1u << ADSCTRL_STS_SH);
+
+		corgi_ssp_ads7846_putget(cmd);
+	}
+	return 0;
+}
+
+static int corgits_resume(struct device *dev, uint32_t level)
+{
+	if (level == RESUME_POWER_ON) 
+	{
+		unsigned long cmd;
+		
+		cmd =   (1u << ADSCTRL_PD0_SH) | (1u << ADSCTRL_PD1_SH) |
+			(1u << ADSCTRL_ADR_SH) | (1u << ADSCTRL_STS_SH);
+		corgi_ssp_ads7846_putget(cmd);
+
+		/* Enable Falling Edge */
+		set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+
+		PowerDownMode = PMPD_MODE_ACTIVE;
+	}
+	return 0;
+}
+#else
+#define corgits_suspend		NULL
+#define corgits_resume		NULL
+#endif
+
+static struct device_driver corgits_driver = {
+	.name		= "corgi-ts",
+	.bus		= &platform_bus_type,
+	.probe		= corgits_probe,
+	.remove		= corgits_remove,
+	.suspend	= corgits_suspend,
+	.resume		= corgits_resume,
+};
+
+int __devinit corgits_init(void)
+{
+	return driver_register(&corgits_driver);
+}
+
+void __exit corgits_exit(void)
+{
+ 	driver_unregister(&corgits_driver);
+}
+
+module_init(corgits_init);
+module_exit(corgits_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
+MODULE_DESCRIPTION("Corgi TouchScreen Driver");
+MODULE_LICENSE("GPL");
--- linux-2.6.10/drivers/input/touchscreen/Kconfig~corgi_ts-r1.patch
+++ linux-2.6.10/drivers/input/touchscreen/Kconfig
@@ -22,6 +22,17 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called h3600_ts_input.
 
+config TOUCHSCREEN_ADS7846
+	tristate "ADS7846 touchscreen input driver (for Sharp SL-C7xx)"
+	depends on PXA_SHARPSL && INPUT && INPUT_TOUCHSCREEN
+	help
+	  Say Y here if you have the Sharp SL-C7xx touchscreen.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ads7846_ts.
+
 config TOUCHSCREEN_GUNZE
 	tristate "Gunze AHL-51S touchscreen"
 	depends on INPUT && INPUT_TOUCHSCREEN
--- linux-2.6.10/drivers/input/touchscreen/Makefile~corgi_ts-r1.patch
+++ linux-2.6.10/drivers/input/touchscreen/Makefile
@@ -6,3 +6,4 @@
 
 obj-$(CONFIG_TOUCHSCREEN_BITSY)	+= h3600_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_GUNZE)	+= gunze.o
+obj-$(CONFIG_TOUCHSCREEN_ADS7846)	+= ads7846_ts.o
\ No newline at end of file
--- /dev/null
+++ linux-2.6.10/drivers/input/touchscreen/ads7846_ts.h
@@ -0,0 +1,39 @@
+/*
+ * linux/include/asm-arm/arch-pxa/ads7846_ts.h
+ *
+ * Copyright (C) 2001 Lineo Japan, Inc.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ */
+
+
+/*#define TS_MAJOR		55*/		/* default device major */
+#define TS_MAJOR		11		/* for sharp_ts */
+
+#define X_AXIS_MAX		3830
+#define X_AXIS_MIN		150
+#define Y_AXIS_MAX		3830
+#define Y_AXIS_MIN		190
+
+
+/* ADS7846 Touch Screen Controller bit shift constants */
+
+#define ADSCTRL_PD0_SH		0	// PD0 bit
+#define ADSCTRL_PD1_SH		1	// PD1 bit
+#define ADSCTRL_DFR_SH		2	// SER/DFR bit
+#define ADSCTRL_MOD_SH		3	// Mode bit
+#define ADSCTRL_ADR_SH		4	// Address setting
+#define ADSCTRL_STS_SH		7	// Start bit
+
+
+/* ADS7846 Touch Screen Controller bit mask constants */
+
+#define ADSCTRL_PD0_MSK			(1u << ADSCTRL_PD0_SH)
+#define ADSCTRL_PD1_MSK			(1u << ADSCTRL_PD0_SH)
+
+typedef struct ts_pos_s {
+	unsigned long xd;
+	unsigned long yd;
+} ts_pos_t;

