aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen/tsc2007.c
diff options
context:
space:
mode:
authorRichard Röjfors <richard.rojfors.ext@mocean-labs.com>2009-07-25 01:01:39 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2009-07-26 14:20:55 -0400
commit75fba3b05d6ed82b975c1f8df8f8e08d5d81dee5 (patch)
tree7ab10345d46834588983f90bc89e781171d58dd9 /drivers/input/touchscreen/tsc2007.c
parentb0010911d52dc7836a78c9f5c3b32ce4ac05b3c3 (diff)
Input: tsc2007 - remove HR timer
Since it's not allowed to do synchronous I2C in the HR timer callback context we have to switch to using the global workqueue. The work is scheduled every 1ms when polling rather than 5 us. Signed-off-by: Richard Röjfors <richard.rojfors.ext@mocean-labs.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/touchscreen/tsc2007.c')
-rw-r--r--drivers/input/touchscreen/tsc2007.c48
1 files changed, 13 insertions, 35 deletions
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c
index 880f58c6a7c..b512697b227 100644
--- a/drivers/input/touchscreen/tsc2007.c
+++ b/drivers/input/touchscreen/tsc2007.c
@@ -21,15 +21,13 @@
21 */ 21 */
22 22
23#include <linux/module.h> 23#include <linux/module.h>
24#include <linux/hrtimer.h>
25#include <linux/slab.h> 24#include <linux/slab.h>
26#include <linux/input.h> 25#include <linux/input.h>
27#include <linux/interrupt.h> 26#include <linux/interrupt.h>
28#include <linux/i2c.h> 27#include <linux/i2c.h>
29#include <linux/i2c/tsc2007.h> 28#include <linux/i2c/tsc2007.h>
30 29
31#define TS_POLL_DELAY (10 * 1000) /* ns delay before the first sample */ 30#define TS_POLL_PERIOD msecs_to_jiffies(1) /* ms delay between samples */
32#define TS_POLL_PERIOD (5 * 1000) /* ns delay between samples */
33 31
34#define TSC2007_MEASURE_TEMP0 (0x0 << 4) 32#define TSC2007_MEASURE_TEMP0 (0x0 << 4)
35#define TSC2007_MEASURE_AUX (0x2 << 4) 33#define TSC2007_MEASURE_AUX (0x2 << 4)
@@ -70,13 +68,11 @@ struct ts_event {
70struct tsc2007 { 68struct tsc2007 {
71 struct input_dev *input; 69 struct input_dev *input;
72 char phys[32]; 70 char phys[32];
73 struct hrtimer timer; 71 struct delayed_work work;
74 struct ts_event tc; 72 struct ts_event tc;
75 73
76 struct i2c_client *client; 74 struct i2c_client *client;
77 75
78 spinlock_t lock;
79
80 u16 model; 76 u16 model;
81 u16 x_plate_ohms; 77 u16 x_plate_ohms;
82 78
@@ -142,8 +138,7 @@ static void tsc2007_send_event(void *tsc)
142 if (rt > MAX_12BIT) { 138 if (rt > MAX_12BIT) {
143 dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt); 139 dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);
144 140
145 hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), 141 schedule_delayed_work(&ts->work, TS_POLL_PERIOD);
146 HRTIMER_MODE_REL);
147 return; 142 return;
148 } 143 }
149 144
@@ -153,7 +148,7 @@ static void tsc2007_send_event(void *tsc)
153 * in some cases may not even settle at the expected value. 148 * in some cases may not even settle at the expected value.
154 * 149 *
155 * The only safe way to check for the pen up condition is in the 150 * The only safe way to check for the pen up condition is in the
156 * timer by reading the pen signal state (it's a GPIO _and_ IRQ). 151 * work function by reading the pen signal state (it's a GPIO and IRQ).
157 */ 152 */
158 if (rt) { 153 if (rt) {
159 struct input_dev *input = ts->input; 154 struct input_dev *input = ts->input;
@@ -175,8 +170,7 @@ static void tsc2007_send_event(void *tsc)
175 x, y, rt); 170 x, y, rt);
176 } 171 }
177 172
178 hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), 173 schedule_delayed_work(&ts->work, TS_POLL_PERIOD);
179 HRTIMER_MODE_REL);
180} 174}
181 175
182static int tsc2007_read_values(struct tsc2007 *tsc) 176static int tsc2007_read_values(struct tsc2007 *tsc)
@@ -197,13 +191,10 @@ static int tsc2007_read_values(struct tsc2007 *tsc)
197 return 0; 191 return 0;
198} 192}
199 193
200static enum hrtimer_restart tsc2007_timer(struct hrtimer *handle) 194static void tsc2007_work(struct work_struct *work)
201{ 195{
202 struct tsc2007 *ts = container_of(handle, struct tsc2007, timer); 196 struct tsc2007 *ts =
203 unsigned long flags; 197 container_of(to_delayed_work(work), struct tsc2007, work);
204
205 spin_lock_irqsave(&ts->lock, flags);
206
207 if (unlikely(!ts->get_pendown_state() && ts->pendown)) { 198 if (unlikely(!ts->get_pendown_state() && ts->pendown)) {
208 struct input_dev *input = ts->input; 199 struct input_dev *input = ts->input;
209 200
@@ -222,30 +213,20 @@ static enum hrtimer_restart tsc2007_timer(struct hrtimer *handle)
222 tsc2007_read_values(ts); 213 tsc2007_read_values(ts);
223 tsc2007_send_event(ts); 214 tsc2007_send_event(ts);
224 } 215 }
225
226 spin_unlock_irqrestore(&ts->lock, flags);
227
228 return HRTIMER_NORESTART;
229} 216}
230 217
231static irqreturn_t tsc2007_irq(int irq, void *handle) 218static irqreturn_t tsc2007_irq(int irq, void *handle)
232{ 219{
233 struct tsc2007 *ts = handle; 220 struct tsc2007 *ts = handle;
234 unsigned long flags;
235
236 spin_lock_irqsave(&ts->lock, flags);
237 221
238 if (likely(ts->get_pendown_state())) { 222 if (likely(ts->get_pendown_state())) {
239 disable_irq_nosync(ts->irq); 223 disable_irq_nosync(ts->irq);
240 hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY), 224 schedule_delayed_work(&ts->work, 0);
241 HRTIMER_MODE_REL);
242 } 225 }
243 226
244 if (ts->clear_penirq) 227 if (ts->clear_penirq)
245 ts->clear_penirq(); 228 ts->clear_penirq();
246 229
247 spin_unlock_irqrestore(&ts->lock, flags);
248
249 return IRQ_HANDLED; 230 return IRQ_HANDLED;
250} 231}
251 232
@@ -278,11 +259,6 @@ static int tsc2007_probe(struct i2c_client *client,
278 259
279 ts->input = input_dev; 260 ts->input = input_dev;
280 261
281 hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
282 ts->timer.function = tsc2007_timer;
283
284 spin_lock_init(&ts->lock);
285
286 ts->model = pdata->model; 262 ts->model = pdata->model;
287 ts->x_plate_ohms = pdata->x_plate_ohms; 263 ts->x_plate_ohms = pdata->x_plate_ohms;
288 ts->get_pendown_state = pdata->get_pendown_state; 264 ts->get_pendown_state = pdata->get_pendown_state;
@@ -308,6 +284,8 @@ static int tsc2007_probe(struct i2c_client *client,
308 284
309 ts->irq = client->irq; 285 ts->irq = client->irq;
310 286
287 INIT_DELAYED_WORK(&ts->work, tsc2007_work);
288
311 err = request_irq(ts->irq, tsc2007_irq, 0, 289 err = request_irq(ts->irq, tsc2007_irq, 0,
312 client->dev.driver->name, ts); 290 client->dev.driver->name, ts);
313 if (err < 0) { 291 if (err < 0) {
@@ -325,7 +303,6 @@ static int tsc2007_probe(struct i2c_client *client,
325 303
326 err_free_irq: 304 err_free_irq:
327 free_irq(ts->irq, ts); 305 free_irq(ts->irq, ts);
328 hrtimer_cancel(&ts->timer);
329 err_free_mem: 306 err_free_mem:
330 input_free_device(input_dev); 307 input_free_device(input_dev);
331 kfree(ts); 308 kfree(ts);
@@ -337,11 +314,12 @@ static int tsc2007_remove(struct i2c_client *client)
337 struct tsc2007 *ts = i2c_get_clientdata(client); 314 struct tsc2007 *ts = i2c_get_clientdata(client);
338 struct tsc2007_platform_data *pdata; 315 struct tsc2007_platform_data *pdata;
339 316
317 cancel_delayed_work_sync(&ts->work);
318
340 pdata = client->dev.platform_data; 319 pdata = client->dev.platform_data;
341 pdata->exit_platform_hw(); 320 pdata->exit_platform_hw();
342 321
343 free_irq(ts->irq, ts); 322 free_irq(ts->irq, ts);
344 hrtimer_cancel(&ts->timer);
345 input_unregister_device(ts->input); 323 input_unregister_device(ts->input);
346 kfree(ts); 324 kfree(ts);
347 325