diff options
Diffstat (limited to 'drivers/input/touchscreen/atmel_tsadcc.c')
-rw-r--r-- | drivers/input/touchscreen/atmel_tsadcc.c | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index eee126b19e8b..a89a6a8f05e6 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c | |||
@@ -91,6 +91,9 @@ struct atmel_tsadcc { | |||
91 | char phys[32]; | 91 | char phys[32]; |
92 | struct clk *clk; | 92 | struct clk *clk; |
93 | int irq; | 93 | int irq; |
94 | unsigned int prev_absx; | ||
95 | unsigned int prev_absy; | ||
96 | unsigned char bufferedmeasure; | ||
94 | }; | 97 | }; |
95 | 98 | ||
96 | static void __iomem *tsc_base; | 99 | static void __iomem *tsc_base; |
@@ -100,10 +103,9 @@ static void __iomem *tsc_base; | |||
100 | 103 | ||
101 | static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) | 104 | static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) |
102 | { | 105 | { |
103 | struct input_dev *input_dev = ((struct atmel_tsadcc *)dev)->input; | 106 | struct atmel_tsadcc *ts_dev = (struct atmel_tsadcc *)dev; |
107 | struct input_dev *input_dev = ts_dev->input; | ||
104 | 108 | ||
105 | unsigned int absx; | ||
106 | unsigned int absy; | ||
107 | unsigned int status; | 109 | unsigned int status; |
108 | unsigned int reg; | 110 | unsigned int reg; |
109 | 111 | ||
@@ -121,6 +123,7 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) | |||
121 | atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT); | 123 | atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT); |
122 | 124 | ||
123 | input_report_key(input_dev, BTN_TOUCH, 0); | 125 | input_report_key(input_dev, BTN_TOUCH, 0); |
126 | ts_dev->bufferedmeasure = 0; | ||
124 | input_sync(input_dev); | 127 | input_sync(input_dev); |
125 | 128 | ||
126 | } else if (status & ATMEL_TSADCC_PENCNT) { | 129 | } else if (status & ATMEL_TSADCC_PENCNT) { |
@@ -138,16 +141,23 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) | |||
138 | } else if (status & ATMEL_TSADCC_EOC(3)) { | 141 | } else if (status & ATMEL_TSADCC_EOC(3)) { |
139 | /* Conversion finished */ | 142 | /* Conversion finished */ |
140 | 143 | ||
141 | absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10; | 144 | if (ts_dev->bufferedmeasure) { |
142 | absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2); | 145 | /* Last measurement is always discarded, since it can |
143 | 146 | * be erroneous. | |
144 | absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10; | 147 | * Always report previous measurement */ |
145 | absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0); | 148 | input_report_abs(input_dev, ABS_X, ts_dev->prev_absx); |
146 | 149 | input_report_abs(input_dev, ABS_Y, ts_dev->prev_absy); | |
147 | input_report_abs(input_dev, ABS_X, absx); | 150 | input_report_key(input_dev, BTN_TOUCH, 1); |
148 | input_report_abs(input_dev, ABS_Y, absy); | 151 | input_sync(input_dev); |
149 | input_report_key(input_dev, BTN_TOUCH, 1); | 152 | } else |
150 | input_sync(input_dev); | 153 | ts_dev->bufferedmeasure = 1; |
154 | |||
155 | /* Now make new measurement */ | ||
156 | ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10; | ||
157 | ts_dev->prev_absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2); | ||
158 | |||
159 | ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10; | ||
160 | ts_dev->prev_absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0); | ||
151 | } | 161 | } |
152 | 162 | ||
153 | return IRQ_HANDLED; | 163 | return IRQ_HANDLED; |
@@ -223,6 +233,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) | |||
223 | } | 233 | } |
224 | 234 | ||
225 | ts_dev->input = input_dev; | 235 | ts_dev->input = input_dev; |
236 | ts_dev->bufferedmeasure = 0; | ||
226 | 237 | ||
227 | snprintf(ts_dev->phys, sizeof(ts_dev->phys), | 238 | snprintf(ts_dev->phys, sizeof(ts_dev->phys), |
228 | "%s/input0", pdev->dev.bus_id); | 239 | "%s/input0", pdev->dev.bus_id); |