506 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Diff
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			506 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Diff
		
	
	
		
			Executable File
		
	
	
	
	
| From 76d6ab9228efca87d3e6db46e918c7bbf19f6540 Mon Sep 17 00:00:00 2001
 | |
| From: Andy Green <andy@openmoko.com>
 | |
| Date: Fri, 25 Jul 2008 23:06:16 +0100
 | |
| Subject: [PATCH] touchscreen-meddling.patch
 | |
| 
 | |
| Touchscreen on GTA01-02 experiences noise on the channel that serves the
 | |
| "tall axis" of the LCM.  The sample quality of the other axis is good.
 | |
| The bad samples have a characteristic of one shot excursions that can
 | |
| reach +/- 20% or more of the sample average.
 | |
| 
 | |
| Previously, we had a simple averaging scheme going in the touchscreen
 | |
| driver that summed up 32 x and ys and then divided it by 32.  This patch
 | |
| first tidies up the existing code for style, then adds a new "running
 | |
| average" concept with a FIFO.  The running average is separate from the
 | |
| summing average mentioned above, and is accurate for the last n samples
 | |
| sample-by-sample, where n is set by 1 << excursion_filter_len_bits in the
 | |
| machine / platform stuff.
 | |
| 
 | |
| The heuristic the patch implements for the filtering is to accept all
 | |
| samples, but tag the *previous* sample with a flag if it differed from
 | |
| the running average by more than reject_threshold_vs_avg in either
 | |
| axis.  The next sample time, a beauty contest is held if the flag was
 | |
| set to decide if we think the previous sample was a one-shot excursion
 | |
| (detected by the new sample being closer to the average than to the
 | |
| flagged previous sample), or if we believe we are moving (detected by
 | |
| the new sample being closer to the flagged previous sample than the
 | |
| average.  In the case that we believe the previous sample was an
 | |
| excursion, we simply overwrite it with the new data and adjust the
 | |
| summing average to use the new data instead of the excursion data.
 | |
| 
 | |
| I only tested this by eyeballing the output of ts_print_raw, but it
 | |
| seemed to be quite a bit better.  Gross movement appeared to be
 | |
| tracked fine too.  If folks want to try different heuristics on top
 | |
| of this patch, be my guest; either way feedback on what it looks like
 | |
| with a graphical app would be good.
 | |
| 
 | |
| Signed-off-by: Andy Green <andy@openmoko.com>
 | |
| ---
 | |
|  arch/arm/mach-s3c2440/mach-gta02.c     |   10 +-
 | |
|  drivers/input/touchscreen/s3c2410_ts.c |  256 ++++++++++++++++++++++++--------
 | |
|  include/asm-arm/arch-s3c2410/ts.h      |    8 +-
 | |
|  3 files changed, 205 insertions(+), 69 deletions(-)
 | |
| 
 | |
| diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
 | |
| index c32bb2a..afe8039 100644
 | |
| --- a/arch/arm/mach-s3c2440/mach-gta02.c
 | |
| +++ b/arch/arm/mach-s3c2440/mach-gta02.c
 | |
| @@ -897,10 +897,18 @@ static struct s3c2410_udc_mach_info gta02_udc_cfg = {
 | |
|  
 | |
|  static struct s3c2410_ts_mach_info gta02_ts_cfg = {
 | |
|  	.delay = 10000,
 | |
| -	.presc = 65,
 | |
| +	.presc = 50000000 / 1000000, /* 50 MHz PCLK / 1MHz */
 | |
| +	/* simple averaging, 2^n samples */
 | |
|  	.oversampling_shift = 5,
 | |
| +	 /* averaging filter length, 2^n */
 | |
| +	.excursion_filter_len_bits = 5,
 | |
| +	/* flagged for beauty contest on next sample if differs from
 | |
| +	 * average more than this
 | |
| +	 */
 | |
| +	.reject_threshold_vs_avg = 2,
 | |
|  };
 | |
|  
 | |
| +
 | |
|  /* SPI: LCM control interface attached to Glamo3362 */
 | |
|  
 | |
|  static void gta02_jbt6k74_reset(int devidx, int level)
 | |
| diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
 | |
| index 1251454..b1ba73d 100644
 | |
| --- a/drivers/input/touchscreen/s3c2410_ts.c
 | |
| +++ b/drivers/input/touchscreen/s3c2410_ts.c
 | |
| @@ -36,6 +36,9 @@
 | |
|   *
 | |
|   * 2007-05-23: Harald Welte <laforge@openmoko.org>
 | |
|   * 	- Add proper support for S32440
 | |
| + *
 | |
| + * 2008-06-18: Andy Green <andy@openmoko.com>
 | |
| + *      - Outlier removal
 | |
|   */
 | |
|  
 | |
|  #include <linux/errno.h>
 | |
| @@ -62,11 +65,16 @@
 | |
|  #define TSC_SLEEP  (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0))
 | |
|  
 | |
|  #define WAIT4INT(x)  (((x)<<8) | \
 | |
| -		     S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
 | |
| +		     S3C2410_ADCTSC_YM_SEN | \
 | |
| +		     S3C2410_ADCTSC_YP_SEN | \
 | |
| +		     S3C2410_ADCTSC_XP_SEN | \
 | |
|  		     S3C2410_ADCTSC_XY_PST(3))
 | |
|  
 | |
| -#define AUTOPST	     (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
 | |
| -		     S3C2410_ADCTSC_AUTO_PST | S3C2410_ADCTSC_XY_PST(0))
 | |
| +#define AUTOPST	     (S3C2410_ADCTSC_YM_SEN | \
 | |
| +		      S3C2410_ADCTSC_YP_SEN | \
 | |
| +		      S3C2410_ADCTSC_XP_SEN | \
 | |
| +		      S3C2410_ADCTSC_AUTO_PST | \
 | |
| +		      S3C2410_ADCTSC_XY_PST(0))
 | |
|  
 | |
|  #define DEBUG_LVL    KERN_DEBUG
 | |
|  
 | |
| @@ -85,17 +93,46 @@ static char *s3c2410ts_name = "s3c2410 TouchScreen";
 | |
|   * Per-touchscreen data.
 | |
|   */
 | |
|  
 | |
| +struct s3c2410ts_sample {
 | |
| +	int x;
 | |
| +	int y;
 | |
| +};
 | |
| +
 | |
|  struct s3c2410ts {
 | |
|  	struct input_dev *dev;
 | |
|  	long xp;
 | |
|  	long yp;
 | |
|  	int count;
 | |
|  	int shift;
 | |
| +	int extent;  /* 1 << shift */
 | |
| +
 | |
| +	/* the raw sample fifo is a lightweight way to track a running average
 | |
| +	 * of all taken samples.  "running average" here means that it gives
 | |
| +	 * correct average for each sample, not only at the end of block of
 | |
| +	 * samples
 | |
| +	 */
 | |
| +	int excursion_filter_len;
 | |
| +	struct s3c2410ts_sample *raw_sample_fifo;
 | |
| +	int head_raw_fifo;
 | |
| +	int tail_raw_fifo;
 | |
| +	struct s3c2410ts_sample raw_running_avg;
 | |
| +	int reject_threshold_vs_avg;
 | |
| +	int flag_previous_exceeded_threshold;
 | |
|  };
 | |
|  
 | |
|  static struct s3c2410ts ts;
 | |
|  static void __iomem *base_addr;
 | |
|  
 | |
| +static void clear_raw_fifo(void)
 | |
| +{
 | |
| +	ts.head_raw_fifo = 0;
 | |
| +	ts.tail_raw_fifo = 0;
 | |
| +	ts.raw_running_avg.x = 0;
 | |
| +	ts.raw_running_avg.y = 0;
 | |
| +	ts.flag_previous_exceeded_threshold = 0;
 | |
| +}
 | |
| +
 | |
| +
 | |
|  static inline void s3c2410_ts_connect(void)
 | |
|  {
 | |
|  	s3c2410_gpio_cfgpin(S3C2410_GPG12, S3C2410_GPG12_XMON);
 | |
| @@ -110,47 +147,52 @@ static void touch_timer_fire(unsigned long data)
 | |
|    	unsigned long data1;
 | |
|  	int updown;
 | |
|  
 | |
| -  	data0 = readl(base_addr+S3C2410_ADCDAT0);
 | |
| -  	data1 = readl(base_addr+S3C2410_ADCDAT1);
 | |
| +	data0 = readl(base_addr + S3C2410_ADCDAT0);
 | |
| +	data1 = readl(base_addr + S3C2410_ADCDAT1);
 | |
|  
 | |
| - 	updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));
 | |
| +	updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) &&
 | |
| +					    (!(data1 & S3C2410_ADCDAT0_UPDOWN));
 | |
|  
 | |
| - 	if (updown) {
 | |
| - 		if (ts.count != 0) {
 | |
| - 			ts.xp >>= ts.shift;
 | |
| - 			ts.yp >>= ts.shift;
 | |
| +	if (updown) {
 | |
| +		if (ts.count != 0) {
 | |
| +			ts.xp >>= ts.shift;
 | |
| +			ts.yp >>= ts.shift;
 | |
|  
 | |
|  #ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
 | |
| - 			{
 | |
| - 				struct timeval tv;
 | |
| - 				do_gettimeofday(&tv);
 | |
| - 				printk(DEBUG_LVL "T: %06d, X: %03ld, Y: %03ld\n", (int)tv.tv_usec, ts.xp, ts.yp);
 | |
| - 			}
 | |
| +			{
 | |
| +				struct timeval tv;
 | |
| +
 | |
| +				do_gettimeofday(&tv);
 | |
| +				printk(DEBUG_LVL "T:%06d, X:%03ld, Y:%03ld\n",
 | |
| +						 (int)tv.tv_usec, ts.xp, ts.yp);
 | |
| +			}
 | |
|  #endif
 | |
|  
 | |
| - 			input_report_abs(ts.dev, ABS_X, ts.xp);
 | |
| - 			input_report_abs(ts.dev, ABS_Y, ts.yp);
 | |
| +			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_report_abs(ts.dev, ABS_PRESSURE, 1);
 | |
| - 			input_sync(ts.dev);
 | |
| - 		}
 | |
| +			input_report_key(ts.dev, BTN_TOUCH, 1);
 | |
| +			input_report_abs(ts.dev, ABS_PRESSURE, 1);
 | |
| +			input_sync(ts.dev);
 | |
| +		}
 | |
|  
 | |
| - 		ts.xp = 0;
 | |
| - 		ts.yp = 0;
 | |
| - 		ts.count = 0;
 | |
| +		ts.xp = 0;
 | |
| +		ts.yp = 0;
 | |
| +		ts.count = 0;
 | |
|  
 | |
| - 		writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
 | |
| - 		writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
 | |
| - 	} else {
 | |
| - 		ts.count = 0;
 | |
| +		writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST,
 | |
| +						      base_addr+S3C2410_ADCTSC);
 | |
| +		writel(readl(base_addr+S3C2410_ADCCON) |
 | |
| +			 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);
 | |
| +		input_report_key(ts.dev, BTN_TOUCH, 0);
 | |
| +		input_report_abs(ts.dev, ABS_PRESSURE, 0);
 | |
| +		input_sync(ts.dev);
 | |
|  
 | |
| - 		writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
 | |
| - 	}
 | |
| +		writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
 | |
| +	}
 | |
|  }
 | |
|  
 | |
|  static struct timer_list touch_timer =
 | |
| @@ -165,7 +207,8 @@ static irqreturn_t stylus_updown(int irq, void *dev_id)
 | |
|  	data0 = readl(base_addr+S3C2410_ADCDAT0);
 | |
|  	data1 = readl(base_addr+S3C2410_ADCDAT1);
 | |
|  
 | |
| -	updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));
 | |
| +	updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) &&
 | |
| +					    (!(data1 & S3C2410_ADCDAT0_UPDOWN));
 | |
|  
 | |
|  	/* TODO we should never get an interrupt with updown set while
 | |
|  	 * the timer is running, but maybe we ought to verify that the
 | |
| @@ -180,24 +223,94 @@ static irqreturn_t stylus_updown(int irq, void *dev_id)
 | |
|  
 | |
|  static irqreturn_t stylus_action(int irq, void *dev_id)
 | |
|  {
 | |
| -	unsigned long data0;
 | |
| -	unsigned long data1;
 | |
| -
 | |
| -	data0 = readl(base_addr+S3C2410_ADCDAT0);
 | |
| -	data1 = readl(base_addr+S3C2410_ADCDAT1);
 | |
| +	unsigned long x;
 | |
| +	unsigned long y;
 | |
| +	int length = (ts.head_raw_fifo - ts.tail_raw_fifo) & (ts.extent - 1);
 | |
| +	int scaled_avg_x = ts.raw_running_avg.x / length;
 | |
| +	int scaled_avg_y = ts.raw_running_avg.y / length;
 | |
| +
 | |
| +	x = readl(base_addr + S3C2410_ADCDAT0) & S3C2410_ADCDAT0_XPDATA_MASK;
 | |
| +	y = readl(base_addr + S3C2410_ADCDAT1) & S3C2410_ADCDAT1_YPDATA_MASK;
 | |
| +
 | |
| +	/* we appear to accept every sample into both the running average FIFO
 | |
| +	 * and the summing average.  BUT, if the last sample crossed a
 | |
| +	 * machine-set threshold, each time we do a beauty contest
 | |
| +	 * on the new sample comparing if it is closer to the running
 | |
| +	 * average and the previous sample.  If it is closer to the previous
 | |
| +	 * suspicious sample, we assume the change is real and accept both
 | |
| +	 * if the new sample has returned to being closer to the average than
 | |
| +	 * the previous sample, we take the previous sample as an excursion
 | |
| +	 * and overwrite it in both the running average and summing average.
 | |
| +	 */
 | |
| +
 | |
| +	if (ts.flag_previous_exceeded_threshold)
 | |
| +		/* new one closer to "nonconformist" previous, or average?
 | |
| +		 * Pythagoras?  Who?  Don't need it because large excursion
 | |
| +		 * will be accounted for correctly this way
 | |
| +		 */
 | |
| +		if ((abs(x - scaled_avg_x) + abs(y - scaled_avg_y)) <
 | |
| +		    (abs(x - ts.raw_sample_fifo[(ts.head_raw_fifo - 1) &
 | |
| +							  (ts.extent - 1)].x) +
 | |
| +		     abs(y - ts.raw_sample_fifo[(ts.head_raw_fifo - 1) &
 | |
| +							 (ts.extent - 1)].y))) {
 | |
| +			/* it's closer to average, reject previous as a one-
 | |
| +			 * shot excursion, by overwriting it
 | |
| +			 */
 | |
| +			ts.xp += x - ts.raw_sample_fifo[(ts.head_raw_fifo - 1) &
 | |
| +							     (ts.extent - 1)].x;
 | |
| +			ts.yp += y - ts.raw_sample_fifo[(ts.head_raw_fifo - 1) &
 | |
| +							     (ts.extent - 1)].y;
 | |
| +			ts.raw_sample_fifo[(ts.head_raw_fifo - 1) &
 | |
| +							 (ts.extent - 1)].x = x;
 | |
| +			ts.raw_sample_fifo[(ts.head_raw_fifo - 1) &
 | |
| +							 (ts.extent - 1)].y = y;
 | |
| +			/* no new sample: replaced previous, so we are done */
 | |
| +			goto completed;
 | |
| +		}
 | |
| +		/* else it was closer to nonconformist previous: it's likely
 | |
| +		 * a genuine consistent move then.
 | |
| +		 * Keep previous and add new guy.
 | |
| +		 */
 | |
| +
 | |
| +	if ((x >= scaled_avg_x - ts.reject_threshold_vs_avg) &&
 | |
| +	    (x <= scaled_avg_x + ts.reject_threshold_vs_avg) &&
 | |
| +	    (y >= scaled_avg_y - ts.reject_threshold_vs_avg) &&
 | |
| +	    (y <= scaled_avg_y + ts.reject_threshold_vs_avg))
 | |
| +		ts.flag_previous_exceeded_threshold = 0;
 | |
| +	else
 | |
| +		ts.flag_previous_exceeded_threshold = 1;
 | |
|  
 | |
| -	ts.xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK;
 | |
| -	ts.yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK;
 | |
| +	/* accepted */
 | |
| +	ts.xp += x;
 | |
| +	ts.yp += y;
 | |
|  	ts.count++;
 | |
|  
 | |
| -        if (ts.count < (1<<ts.shift)) {
 | |
| -		writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
 | |
| -		writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
 | |
| -	} else {
 | |
| -		mod_timer(&touch_timer, jiffies+1);
 | |
| +	/* remove oldest sample from avg when we have full pipeline */
 | |
| +	if (((ts.head_raw_fifo + 1) & (ts.extent - 1)) == ts.tail_raw_fifo) {
 | |
| +		ts.raw_running_avg.x -= ts.raw_sample_fifo[ts.tail_raw_fifo].x;
 | |
| +		ts.raw_running_avg.y -= ts.raw_sample_fifo[ts.tail_raw_fifo].y;
 | |
| +		ts.tail_raw_fifo = (ts.tail_raw_fifo + 1) & (ts.extent - 1);
 | |
| +	}
 | |
| +	/* always add current sample to fifo and average */
 | |
| +	ts.raw_sample_fifo[ts.head_raw_fifo].x = x;
 | |
| +	ts.raw_sample_fifo[ts.head_raw_fifo].y = y;
 | |
| +	ts.raw_running_avg.x += x;
 | |
| +	ts.raw_running_avg.y += y;
 | |
| +	ts.head_raw_fifo = (ts.head_raw_fifo + 1) & (ts.extent - 1);
 | |
| +
 | |
| +completed:
 | |
| +	if (ts.count >= (1 << ts.shift)) {
 | |
| +		mod_timer(&touch_timer, jiffies + 1);
 | |
|  		writel(WAIT4INT(1), base_addr+S3C2410_ADCTSC);
 | |
| +		goto bail;
 | |
|  	}
 | |
|  
 | |
| +	writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST,
 | |
| +						      base_addr+S3C2410_ADCTSC);
 | |
| +	writel(readl(base_addr+S3C2410_ADCCON) |
 | |
| +			 S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
 | |
| +
 | |
| +bail:
 | |
|  	return IRQ_HANDLED;
 | |
|  }
 | |
|  
 | |
| @@ -213,11 +326,11 @@ static int __init s3c2410ts_probe(struct platform_device *pdev)
 | |
|  	struct s3c2410_ts_mach_info *info;
 | |
|  	struct input_dev *input_dev;
 | |
|  
 | |
| -	info = ( struct s3c2410_ts_mach_info *)pdev->dev.platform_data;
 | |
| +	info = (struct s3c2410_ts_mach_info *)pdev->dev.platform_data;
 | |
|  
 | |
|  	if (!info)
 | |
|  	{
 | |
| -		printk(KERN_ERR "Hm... too bad : no platform data for ts\n");
 | |
| +		dev_err(&pdev->dev, "Hm... too bad: no platform data for ts\n");
 | |
|  		return -EINVAL;
 | |
|  	}
 | |
|  
 | |
| @@ -227,7 +340,7 @@ static int __init s3c2410ts_probe(struct platform_device *pdev)
 | |
|  
 | |
|  	adc_clock = clk_get(NULL, "adc");
 | |
|  	if (!adc_clock) {
 | |
| -		printk(KERN_ERR "failed to get adc clock source\n");
 | |
| +		dev_err(&pdev->dev, "failed to get adc clock source\n");
 | |
|  		return -ENOENT;
 | |
|  	}
 | |
|  	clk_enable(adc_clock);
 | |
| @@ -238,7 +351,7 @@ static int __init s3c2410ts_probe(struct platform_device *pdev)
 | |
|  
 | |
|  	base_addr = ioremap(S3C2410_PA_ADC,0x20);
 | |
|  	if (base_addr == NULL) {
 | |
| -		printk(KERN_ERR "Failed to remap register block\n");
 | |
| +		dev_err(&pdev->dev, "Failed to remap register block\n");
 | |
|  		return -ENOMEM;
 | |
|  	}
 | |
|  
 | |
| @@ -247,25 +360,26 @@ static int __init s3c2410ts_probe(struct platform_device *pdev)
 | |
|  	if (!strcmp(pdev->name, "s3c2410-ts"))
 | |
|  		s3c2410_ts_connect();
 | |
|  
 | |
| -	if ((info->presc&0xff) > 0)
 | |
| -		writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(info->presc&0xFF),\
 | |
| -			     base_addr+S3C2410_ADCCON);
 | |
| +	if ((info->presc & 0xff) > 0)
 | |
| +		writel(S3C2410_ADCCON_PRSCEN |
 | |
| +		       S3C2410_ADCCON_PRSCVL(info->presc&0xFF),
 | |
| +						    base_addr + S3C2410_ADCCON);
 | |
|  	else
 | |
| -		writel(0,base_addr+S3C2410_ADCCON);
 | |
| +		writel(0, base_addr+S3C2410_ADCCON);
 | |
|  
 | |
|  
 | |
|  	/* Initialise registers */
 | |
| -	if ((info->delay&0xffff) > 0)
 | |
| -		writel(info->delay & 0xffff,  base_addr+S3C2410_ADCDLY);
 | |
| +	if ((info->delay & 0xffff) > 0)
 | |
| +		writel(info->delay & 0xffff,  base_addr + S3C2410_ADCDLY);
 | |
|  
 | |
| -	writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
 | |
| +	writel(WAIT4INT(0), base_addr + S3C2410_ADCTSC);
 | |
|  
 | |
|  	/* Initialise input stuff */
 | |
|  	memset(&ts, 0, sizeof(struct s3c2410ts));
 | |
|  	input_dev = input_allocate_device();
 | |
|  
 | |
|  	if (!input_dev) {
 | |
| -		printk(KERN_ERR "Unable to allocate the input device !!\n");
 | |
| +		dev_err(&pdev->dev, "Unable to allocate the input device\n");
 | |
|  		return -ENOMEM;
 | |
|  	}
 | |
|  
 | |
| @@ -284,23 +398,30 @@ static int __init s3c2410ts_probe(struct platform_device *pdev)
 | |
|  	ts.dev->id.version = S3C2410TSVERSION;
 | |
|  
 | |
|  	ts.shift = info->oversampling_shift;
 | |
| +	ts.extent = 1 << info->oversampling_shift;
 | |
| +	ts.reject_threshold_vs_avg = info->reject_threshold_vs_avg;
 | |
| +	ts.excursion_filter_len = 1 << info->excursion_filter_len_bits;
 | |
| +
 | |
| +	ts.raw_sample_fifo = kmalloc(sizeof(struct s3c2410ts_sample) *
 | |
| +					   ts.excursion_filter_len, GFP_KERNEL);
 | |
| +	clear_raw_fifo();
 | |
|  
 | |
|  	/* Get irqs */
 | |
|  	if (request_irq(IRQ_ADC, stylus_action, IRQF_SAMPLE_RANDOM,
 | |
| -		"s3c2410_action", ts.dev)) {
 | |
| -		printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_ADC !\n");
 | |
| +						    "s3c2410_action", ts.dev)) {
 | |
| +		dev_err(&pdev->dev, "Could not allocate ts IRQ_ADC !\n");
 | |
|  		iounmap(base_addr);
 | |
|  		return -EIO;
 | |
|  	}
 | |
|  	if (request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM,
 | |
|  			"s3c2410_action", ts.dev)) {
 | |
| -		printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_TC !\n");
 | |
| +		dev_err(&pdev->dev, "Could not allocate ts IRQ_TC !\n");
 | |
|  		free_irq(IRQ_ADC, ts.dev);
 | |
|  		iounmap(base_addr);
 | |
|  		return -EIO;
 | |
|  	}
 | |
|  
 | |
| -	printk(KERN_INFO "%s successfully loaded\n", s3c2410ts_name);
 | |
| +	dev_info(&pdev->dev, "successfully loaded\n");
 | |
|  
 | |
|  	/* All went ok, so register to the input system */
 | |
|  	rc = input_register_device(ts.dev);
 | |
| @@ -328,6 +449,8 @@ static int s3c2410ts_remove(struct platform_device *pdev)
 | |
|  		adc_clock = NULL;
 | |
|  	}
 | |
|  
 | |
| +	kfree(ts.raw_sample_fifo);
 | |
| +
 | |
|  	input_unregister_device(ts.dev);
 | |
|  	iounmap(base_addr);
 | |
|  
 | |
| @@ -357,17 +480,20 @@ static int s3c2410ts_resume(struct platform_device *pdev)
 | |
|  	clk_enable(adc_clock);
 | |
|  	mdelay(1);
 | |
|  
 | |
| +	clear_raw_fifo();
 | |
| +
 | |
|  	enable_irq(IRQ_ADC);
 | |
|  	enable_irq(IRQ_TC);
 | |
|  
 | |
|  	if ((info->presc&0xff) > 0)
 | |
| -		writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(info->presc&0xFF),\
 | |
| -			     base_addr+S3C2410_ADCCON);
 | |
| +		writel(S3C2410_ADCCON_PRSCEN |
 | |
| +		       S3C2410_ADCCON_PRSCVL(info->presc&0xFF),
 | |
| +						      base_addr+S3C2410_ADCCON);
 | |
|  	else
 | |
|  		writel(0,base_addr+S3C2410_ADCCON);
 | |
|  
 | |
|  	/* Initialise registers */
 | |
| -	if ((info->delay&0xffff) > 0)
 | |
| +	if ((info->delay & 0xffff) > 0)
 | |
|  		writel(info->delay & 0xffff,  base_addr+S3C2410_ADCDLY);
 | |
|  
 | |
|  	writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
 | |
| diff --git a/include/asm-arm/arch-s3c2410/ts.h b/include/asm-arm/arch-s3c2410/ts.h
 | |
| index 593632a..44c1e4b 100644
 | |
| --- a/include/asm-arm/arch-s3c2410/ts.h
 | |
| +++ b/include/asm-arm/arch-s3c2410/ts.h
 | |
| @@ -17,9 +17,11 @@
 | |
|  #define __ASM_ARM_TS_H
 | |
|  
 | |
|  struct s3c2410_ts_mach_info {
 | |
| -       int             delay;
 | |
| -       int             presc;
 | |
| -       int             oversampling_shift;
 | |
| +	int             delay;
 | |
| +	int             presc;
 | |
| +	int             oversampling_shift;
 | |
| +	int		excursion_filter_len_bits;
 | |
| +	int		reject_threshold_vs_avg;
 | |
|  };
 | |
|  
 | |
|  void set_s3c2410ts_info(struct s3c2410_ts_mach_info *hard_s3c2410ts_info);
 | |
| -- 
 | |
| 1.5.6.3
 | |
| 
 |