diff options
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/touchscreen/tsc2007.c | 48 |
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 { | |||
70 | struct tsc2007 { | 68 | struct 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 | ||
182 | static int tsc2007_read_values(struct tsc2007 *tsc) | 176 | static 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 | ||
200 | static enum hrtimer_restart tsc2007_timer(struct hrtimer *handle) | 194 | static 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 | ||
231 | static irqreturn_t tsc2007_irq(int irq, void *handle) | 218 | static 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 | ||