aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/ucb1x00-ts.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/ucb1x00-ts.c')
-rw-r--r--drivers/mfd/ucb1x00-ts.c39
1 files changed, 31 insertions, 8 deletions
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
index 63a3cbdfa3f3..1e0e20c0e082 100644
--- a/drivers/mfd/ucb1x00-ts.c
+++ b/drivers/mfd/ucb1x00-ts.c
@@ -20,8 +20,9 @@
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/moduleparam.h> 21#include <linux/moduleparam.h>
22#include <linux/init.h> 22#include <linux/init.h>
23#include <linux/smp.h> 23#include <linux/interrupt.h>
24#include <linux/sched.h> 24#include <linux/sched.h>
25#include <linux/spinlock.h>
25#include <linux/completion.h> 26#include <linux/completion.h>
26#include <linux/delay.h> 27#include <linux/delay.h>
27#include <linux/string.h> 28#include <linux/string.h>
@@ -32,7 +33,6 @@
32#include <linux/kthread.h> 33#include <linux/kthread.h>
33#include <linux/mfd/ucb1x00.h> 34#include <linux/mfd/ucb1x00.h>
34 35
35#include <mach/dma.h>
36#include <mach/collie.h> 36#include <mach/collie.h>
37#include <asm/mach-types.h> 37#include <asm/mach-types.h>
38 38
@@ -42,6 +42,8 @@ struct ucb1x00_ts {
42 struct input_dev *idev; 42 struct input_dev *idev;
43 struct ucb1x00 *ucb; 43 struct ucb1x00 *ucb;
44 44
45 spinlock_t irq_lock;
46 unsigned irq_disabled;
45 wait_queue_head_t irq_wait; 47 wait_queue_head_t irq_wait;
46 struct task_struct *rtask; 48 struct task_struct *rtask;
47 u16 x_res; 49 u16 x_res;
@@ -238,7 +240,12 @@ static int ucb1x00_thread(void *_ts)
238 if (ucb1x00_ts_pen_down(ts)) { 240 if (ucb1x00_ts_pen_down(ts)) {
239 set_current_state(TASK_INTERRUPTIBLE); 241 set_current_state(TASK_INTERRUPTIBLE);
240 242
241 ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, machine_is_collie() ? UCB_RISING : UCB_FALLING); 243 spin_lock_irq(&ts->irq_lock);
244 if (ts->irq_disabled) {
245 ts->irq_disabled = 0;
246 enable_irq(ts->ucb->irq_base + UCB_IRQ_TSPX);
247 }
248 spin_unlock_irq(&ts->irq_lock);
242 ucb1x00_disable(ts->ucb); 249 ucb1x00_disable(ts->ucb);
243 250
244 /* 251 /*
@@ -281,23 +288,37 @@ static int ucb1x00_thread(void *_ts)
281 * We only detect touch screen _touches_ with this interrupt 288 * We only detect touch screen _touches_ with this interrupt
282 * handler, and even then we just schedule our task. 289 * handler, and even then we just schedule our task.
283 */ 290 */
284static void ucb1x00_ts_irq(int idx, void *id) 291static irqreturn_t ucb1x00_ts_irq(int irq, void *id)
285{ 292{
286 struct ucb1x00_ts *ts = id; 293 struct ucb1x00_ts *ts = id;
287 294
288 ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING); 295 spin_lock(&ts->irq_lock);
296 ts->irq_disabled = 1;
297 disable_irq_nosync(ts->ucb->irq_base + UCB_IRQ_TSPX);
298 spin_unlock(&ts->irq_lock);
289 wake_up(&ts->irq_wait); 299 wake_up(&ts->irq_wait);
300
301 return IRQ_HANDLED;
290} 302}
291 303
292static int ucb1x00_ts_open(struct input_dev *idev) 304static int ucb1x00_ts_open(struct input_dev *idev)
293{ 305{
294 struct ucb1x00_ts *ts = input_get_drvdata(idev); 306 struct ucb1x00_ts *ts = input_get_drvdata(idev);
307 unsigned long flags = 0;
295 int ret = 0; 308 int ret = 0;
296 309
297 BUG_ON(ts->rtask); 310 BUG_ON(ts->rtask);
298 311
312 if (machine_is_collie())
313 flags = IRQF_TRIGGER_RISING;
314 else
315 flags = IRQF_TRIGGER_FALLING;
316
317 ts->irq_disabled = 0;
318
299 init_waitqueue_head(&ts->irq_wait); 319 init_waitqueue_head(&ts->irq_wait);
300 ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts); 320 ret = request_irq(ts->ucb->irq_base + UCB_IRQ_TSPX, ucb1x00_ts_irq,
321 flags, "ucb1x00-ts", ts);
301 if (ret < 0) 322 if (ret < 0)
302 goto out; 323 goto out;
303 324
@@ -314,7 +335,7 @@ static int ucb1x00_ts_open(struct input_dev *idev)
314 if (!IS_ERR(ts->rtask)) { 335 if (!IS_ERR(ts->rtask)) {
315 ret = 0; 336 ret = 0;
316 } else { 337 } else {
317 ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts); 338 free_irq(ts->ucb->irq_base + UCB_IRQ_TSPX, ts);
318 ts->rtask = NULL; 339 ts->rtask = NULL;
319 ret = -EFAULT; 340 ret = -EFAULT;
320 } 341 }
@@ -334,7 +355,7 @@ static void ucb1x00_ts_close(struct input_dev *idev)
334 kthread_stop(ts->rtask); 355 kthread_stop(ts->rtask);
335 356
336 ucb1x00_enable(ts->ucb); 357 ucb1x00_enable(ts->ucb);
337 ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts); 358 free_irq(ts->ucb->irq_base + UCB_IRQ_TSPX, ts);
338 ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0); 359 ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0);
339 ucb1x00_disable(ts->ucb); 360 ucb1x00_disable(ts->ucb);
340} 361}
@@ -359,11 +380,13 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
359 ts->ucb = dev->ucb; 380 ts->ucb = dev->ucb;
360 ts->idev = idev; 381 ts->idev = idev;
361 ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC; 382 ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
383 spin_lock_init(&ts->irq_lock);
362 384
363 idev->name = "Touchscreen panel"; 385 idev->name = "Touchscreen panel";
364 idev->id.product = ts->ucb->id; 386 idev->id.product = ts->ucb->id;
365 idev->open = ucb1x00_ts_open; 387 idev->open = ucb1x00_ts_open;
366 idev->close = ucb1x00_ts_close; 388 idev->close = ucb1x00_ts_close;
389 idev->dev.parent = &ts->ucb->dev;
367 390
368 idev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY); 391 idev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
369 idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 392 idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);