commit 4760e6b7a7a495ab5c152ca46004f4f26b1dfb15
Author: I-Fan, Chen <tick@openmoko.com>
Date:   Tue Oct 28 22:02:23 2008 +0800

    S3C24XX touchscreen: To palliate the data jitter from touchpanel
    	Thanks to Dima Kogan patch eff39cde0d3cdd2afd5e1b4be5a8eb6cf195543e,
    	in which try to balence the up/down events, and inspired this patch.
    	We can observe a serious up/down jitter phenomenon when touching the touchscreen lightly.
    	This only happens when the press  pressure is pretty light:
    		eg. large scale light touch,
    		starting to touch,
    		or going to move finger from touch panel.
    	This will make user space library think it got extra click events.
    	In order to palliate with this phenomenon, we delayed the up event for a while,
    	and see if it is a jitter or not.
    	The threshold is crucial. If it is too long, multiple clicks will be filtered out.
    	If it is too short we did not filter anything out.
    	From the log and some survey we can see that the interval of two clicks is generally over 0.1 sec.
    	And Most jitter events happens in 0.3 sec.
    	And the longest duration of vision is about 1/16 sec, and it's not easy for human to notice.
    	So I choose 1/16 sec as the threshold.
    	This filters out most (not all) jitter events, and preserves the normal behavior we expected.

diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
index fc1c500..95672ff 100644
--- a/drivers/input/touchscreen/s3c2410_ts.c
+++ b/drivers/input/touchscreen/s3c2410_ts.c
@@ -78,6 +78,12 @@
 
 #define DEBUG_LVL    KERN_DEBUG
 
+#define TOUCH_STANDBY_FLAG 0
+#define TOUCH_PRESSED_FLAG 1
+#define TOUCH_RELEASE_FLAG 2
+
+#define TOUCH_RELEASE_TIMEOUT (HZ >> 4)
+
 MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
 MODULE_DESCRIPTION("s3c2410 touchscreen driver");
 MODULE_LICENSE("GPL");
@@ -131,7 +137,7 @@ static void clear_raw_fifo(void)
 	ts.raw_running_avg.x = 0;
 	ts.raw_running_avg.y = 0;
 	ts.flag_previous_exceeded_threshold = 0;
-	ts.flag_first_touch_sent = 0;
+	ts.flag_first_touch_sent = TOUCH_STANDBY_FLAG;
 }
 
 
@@ -143,6 +149,10 @@ static inline void s3c2410_ts_connect(void)
 	s3c2410_gpio_cfgpin(S3C2410_GPG15, S3C2410_GPG15_nYPON);
 }
 
+static void touch_timer_fire(unsigned long data);
+static struct timer_list touch_timer =
+		TIMER_INITIALIZER(touch_timer_fire, 0, 0);
+
 static void touch_timer_fire(unsigned long data)
 {
   	unsigned long data0;
@@ -155,18 +165,9 @@ static void touch_timer_fire(unsigned long data)
 	updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) &&
 					    (!(data1 & S3C2410_ADCDAT0_UPDOWN));
 
-	// if we need to send an untouch event, but we haven't yet sent the
-	// touch event (this happens if the touchscreen was tapped lightly),
-	// send the touch event first
-	if (!updown && !ts.flag_first_touch_sent && ts.count != 0) {
-		input_report_abs(ts.dev, ABS_X, ts.xp >> ts.shift);
-		input_report_abs(ts.dev, ABS_Y, ts.yp >> ts.shift);
-
-		input_report_key(ts.dev, BTN_TOUCH, 1);
-		input_report_abs(ts.dev, ABS_PRESSURE, 1);
-		input_sync(ts.dev);
-		ts.flag_first_touch_sent = 1;
-	}
+        if ( updown && ts.flag_first_touch_sent == TOUCH_RELEASE_FLAG ) {
+        	ts.flag_first_touch_sent = TOUCH_PRESSED_FLAG;
+        }
 
 	if (updown) {
 		if (ts.count != 0) {
@@ -189,7 +190,7 @@ static void touch_timer_fire(unsigned long data)
 			input_report_key(ts.dev, BTN_TOUCH, 1);
 			input_report_abs(ts.dev, ABS_PRESSURE, 1);
 			input_sync(ts.dev);
-			ts.flag_first_touch_sent = 1;
+			ts.flag_first_touch_sent = TOUCH_PRESSED_FLAG;
 		}
 
 		ts.xp = 0;
@@ -202,19 +203,21 @@ static void touch_timer_fire(unsigned long data)
 			 S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
 	} else {
 		ts.count = 0;
-
-		input_report_key(ts.dev, BTN_TOUCH, 0);
-		input_report_abs(ts.dev, ABS_PRESSURE, 0);
-		input_sync(ts.dev);
-		ts.flag_first_touch_sent = 0;
+                
+                if ( ts.flag_first_touch_sent == TOUCH_RELEASE_FLAG ) {
+			input_report_key(ts.dev, BTN_TOUCH, 0);
+			input_report_abs(ts.dev, ABS_PRESSURE, 0);
+			input_sync(ts.dev);
+			ts.flag_first_touch_sent = TOUCH_STANDBY_FLAG;
+                } if ( ts.flag_first_touch_sent == TOUCH_PRESSED_FLAG ) {
+                	ts.flag_first_touch_sent = TOUCH_RELEASE_FLAG;
+                	mod_timer(&touch_timer, jiffies + TOUCH_RELEASE_TIMEOUT);
+                }
 
 		writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
 	}
 }
 
-static struct timer_list touch_timer =
-		TIMER_INITIALIZER(touch_timer_fire, 0, 0);
-
 static irqreturn_t stylus_updown(int irq, void *dev_id)
 {
 	unsigned long data0;
