4 * Copyright (C) 2001 Russell King.
6 * This file is placed under the LGPL. Please see the file
7 * COPYING for more details.
10 * Variance filter for touchscreen values.
12 * Problem: some touchscreens are sampled very roughly, thus even if
13 * you hold the pen still, the samples can differ, sometimes substantially.
14 * The worst happens when electric noise during sampling causes the result
15 * to be substantially different from the real pen position; this causes
16 * the mouse cursor to suddenly "jump" and then return back.
18 * Solution: delay sampled data by one timeslot. If we see that the last
19 * sample read differs too much, we mark it as "suspicious". If next sample
20 * read is close to the sample before the "suspicious", the suspicious sample
21 * is dropped, otherwise we consider that a quick pen movement is in progress
22 * and pass through both the "suspicious" sample and the sample after it.
24 #include <linux/module.h>
25 #include <linux/init.h>
26 #include <linux/interrupt.h>
27 #include <linux/kernel.h>
28 #include <linux/slab.h>
29 #include <linux/fcntl.h>
30 #include <linux/delay.h>
31 #include <linux/device.h>
32 //#include <asm/typedef.h>
33 #include <mach/iomux.h>
34 #include <asm/uaccess.h>
35 #include <asm/types.h>
37 #include <asm/delay.h>
42 #define VAR_PENDOWN 0x00000001
43 #define VAR_LASTVALID 0x00000002
44 #define VAR_NOISEVALID 0x00000004
45 #define VAR_SUBMITNOISE 0x00000008
46 void variance_clear(struct tslib_info *info)
49 struct tslib_variance *var = info->var;
53 /* Flush the queue immediately when the pen is just
54 * released, otherwise the previous layer will
55 * get the pen up notification too late. This
56 * will happen if info->next->ops->read() blocks.
58 if (var->flags & VAR_PENDOWN) {
59 var->flags |= VAR_SUBMITNOISE;
62 /* Reset the state machine on pen up events. */
63 var->flags &= ~(VAR_PENDOWN | VAR_NOISEVALID | VAR_LASTVALID);
69 int variance_read(struct tslib_info *info, struct ts_sample *samp, int nr)
71 struct tslib_variance *var = info->var;
76 if (var->flags & VAR_SUBMITNOISE) {
78 var->flags &= ~VAR_SUBMITNOISE;
80 if (info->raw_read(info, &cur, 1) < 1)
84 if (cur.pressure == 0) {
85 /* Flush the queue immediately when the pen is just
86 * released, otherwise the previous layer will
87 * get the pen up notification too late. This
88 * will happen if info->next->ops->read() blocks.
90 if (var->flags & VAR_PENDOWN) {
91 var->flags |= VAR_SUBMITNOISE;
94 /* Reset the state machine on pen up events. */
95 var->flags &= ~(VAR_PENDOWN | VAR_NOISEVALID | VAR_LASTVALID);
98 var->flags |= VAR_PENDOWN;
100 if (!(var->flags & VAR_LASTVALID)) {
102 var->flags |= VAR_LASTVALID;
106 if (var->flags & VAR_PENDOWN) {
107 /* Compute the distance between last sample and current */
108 dist = sqr(cur.x - var->last.x) +
109 sqr(cur.y - var->last.y);
111 if (dist > var->delta) {
112 /* Do we suspect the previous sample was a noise? */
113 if (var->flags & VAR_NOISEVALID) {
114 /* Two "noises": it's just a quick pen movement */
115 samp [count++] = var->last = var->noise;
116 var->flags = (var->flags & ~VAR_NOISEVALID) |
119 var->flags |= VAR_NOISEVALID;
121 /* The pen jumped too far, maybe it's a noise ... */
125 var->flags &= ~VAR_NOISEVALID;
130 printk("VARIANCE----------------> %d %d %d\n",
131 var->last.x, var->last.y, var->last.pressure);
133 samp [count++] = var->last;