input: touchscreen: add touch screen of gslx680 for rk3399-firefly-edp
[firefly-linux-kernel-4.4.55.git] / drivers / input / touchscreen / ts_lib / variance.c
1 /*
2  *  tslib/variance.c
3  *
4  *  Copyright (C) 2001 Russell King.
5  *
6  * This file is placed under the LGPL.  Please see the file
7  * COPYING for more details.
8  *
9  *
10  * Variance filter for touchscreen values.
11  *
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.
17  *
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.
23  */
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>
36 #include <asm/io.h>
37 #include <asm/delay.h>
38 #include "tslib.h"
39
40 //#define DEBUG
41
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)
47 {
48         struct ts_sample cur;
49         struct tslib_variance *var = info->var;
50         
51         cur.pressure = 0;
52
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.
57          */
58         if (var->flags & VAR_PENDOWN) {
59                 var->flags |= VAR_SUBMITNOISE;
60                 var->noise = cur;
61         }
62         /* Reset the state machine on pen up events. */
63         var->flags &= ~(VAR_PENDOWN | VAR_NOISEVALID | VAR_LASTVALID);
64         var->noise = cur;
65         var->last = cur;
66
67         return;
68 }
69 int variance_read(struct tslib_info *info, struct ts_sample *samp, int nr)
70 {
71         struct tslib_variance *var = info->var;
72         struct ts_sample cur;
73         int count = 0, dist;
74
75         while (count < nr) {
76                 if (var->flags & VAR_SUBMITNOISE) {
77                         cur = var->noise;
78                         var->flags &= ~VAR_SUBMITNOISE;
79                 } else {
80                         if (info->raw_read(info, &cur, 1) < 1)
81                                 return count;
82                 }
83
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.
89                          */
90                         if (var->flags & VAR_PENDOWN) {
91                                 var->flags |= VAR_SUBMITNOISE;
92                                 var->noise = cur;
93                         }
94                         /* Reset the state machine on pen up events. */
95                         var->flags &= ~(VAR_PENDOWN | VAR_NOISEVALID | VAR_LASTVALID);
96                         goto acceptsample;
97                 } else
98                         var->flags |= VAR_PENDOWN;
99
100                 if (!(var->flags & VAR_LASTVALID)) {
101                         var->last = cur;
102                         var->flags |= VAR_LASTVALID;
103                         continue;
104                 }
105
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);
110
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) |
117                                                 VAR_SUBMITNOISE;
118                                 } else
119                                         var->flags |= VAR_NOISEVALID;
120
121                                 /* The pen jumped too far, maybe it's a noise ... */
122                                 var->noise = cur;
123                                 continue;
124                         } else
125                                 var->flags &= ~VAR_NOISEVALID;
126                 }
127
128 acceptsample:
129 #ifdef DEBUG
130                 printk("VARIANCE----------------> %d %d %d\n",
131                         var->last.x, var->last.y, var->last.pressure);
132 #endif
133                 samp [count++] = var->last;
134                 var->last = cur;
135         }
136
137         return count;
138 }