diff options
Diffstat (limited to 'drivers/mfd/ucb1x00-ts.c')
-rw-r--r-- | drivers/mfd/ucb1x00-ts.c | 117 |
1 files changed, 77 insertions, 40 deletions
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c index a260f83bcb02..a984c0efabf0 100644 --- a/drivers/mfd/ucb1x00-ts.c +++ b/drivers/mfd/ucb1x00-ts.c | |||
@@ -32,15 +32,18 @@ | |||
32 | #include <linux/suspend.h> | 32 | #include <linux/suspend.h> |
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/kthread.h> | 34 | #include <linux/kthread.h> |
35 | #include <linux/delay.h> | ||
35 | 36 | ||
36 | #include <asm/dma.h> | 37 | #include <asm/dma.h> |
37 | #include <asm/semaphore.h> | 38 | #include <asm/semaphore.h> |
39 | #include <asm/arch/collie.h> | ||
40 | #include <asm/mach-types.h> | ||
38 | 41 | ||
39 | #include "ucb1x00.h" | 42 | #include "ucb1x00.h" |
40 | 43 | ||
41 | 44 | ||
42 | struct ucb1x00_ts { | 45 | struct ucb1x00_ts { |
43 | struct input_dev idev; | 46 | struct input_dev *idev; |
44 | struct ucb1x00 *ucb; | 47 | struct ucb1x00 *ucb; |
45 | 48 | ||
46 | wait_queue_head_t irq_wait; | 49 | wait_queue_head_t irq_wait; |
@@ -56,16 +59,16 @@ static int adcsync; | |||
56 | 59 | ||
57 | static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y) | 60 | static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y) |
58 | { | 61 | { |
59 | input_report_abs(&ts->idev, ABS_X, x); | 62 | input_report_abs(ts->idev, ABS_X, x); |
60 | input_report_abs(&ts->idev, ABS_Y, y); | 63 | input_report_abs(ts->idev, ABS_Y, y); |
61 | input_report_abs(&ts->idev, ABS_PRESSURE, pressure); | 64 | input_report_abs(ts->idev, ABS_PRESSURE, pressure); |
62 | input_sync(&ts->idev); | 65 | input_sync(ts->idev); |
63 | } | 66 | } |
64 | 67 | ||
65 | static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts) | 68 | static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts) |
66 | { | 69 | { |
67 | input_report_abs(&ts->idev, ABS_PRESSURE, 0); | 70 | input_report_abs(ts->idev, ABS_PRESSURE, 0); |
68 | input_sync(&ts->idev); | 71 | input_sync(ts->idev); |
69 | } | 72 | } |
70 | 73 | ||
71 | /* | 74 | /* |
@@ -85,12 +88,23 @@ static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts) | |||
85 | */ | 88 | */ |
86 | static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts) | 89 | static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts) |
87 | { | 90 | { |
88 | ucb1x00_reg_write(ts->ucb, UCB_TS_CR, | 91 | if (machine_is_collie()) { |
89 | UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | | 92 | ucb1x00_io_write(ts->ucb, COLLIE_TC35143_GPIO_TBL_CHK, 0); |
90 | UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | | 93 | ucb1x00_reg_write(ts->ucb, UCB_TS_CR, |
91 | UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); | 94 | UCB_TS_CR_TSPX_POW | UCB_TS_CR_TSMX_POW | |
95 | UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); | ||
92 | 96 | ||
93 | return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync); | 97 | udelay(55); |
98 | |||
99 | return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_AD2, ts->adcsync); | ||
100 | } else { | ||
101 | ucb1x00_reg_write(ts->ucb, UCB_TS_CR, | ||
102 | UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | | ||
103 | UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | | ||
104 | UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); | ||
105 | |||
106 | return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync); | ||
107 | } | ||
94 | } | 108 | } |
95 | 109 | ||
96 | /* | 110 | /* |
@@ -101,12 +115,16 @@ static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts) | |||
101 | */ | 115 | */ |
102 | static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts) | 116 | static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts) |
103 | { | 117 | { |
104 | ucb1x00_reg_write(ts->ucb, UCB_TS_CR, | 118 | if (machine_is_collie()) |
105 | UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | | 119 | ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK); |
106 | UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); | 120 | else { |
107 | ucb1x00_reg_write(ts->ucb, UCB_TS_CR, | 121 | ucb1x00_reg_write(ts->ucb, UCB_TS_CR, |
108 | UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | | 122 | UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | |
109 | UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); | 123 | UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); |
124 | ucb1x00_reg_write(ts->ucb, UCB_TS_CR, | ||
125 | UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | | ||
126 | UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); | ||
127 | } | ||
110 | ucb1x00_reg_write(ts->ucb, UCB_TS_CR, | 128 | ucb1x00_reg_write(ts->ucb, UCB_TS_CR, |
111 | UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | | 129 | UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | |
112 | UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); | 130 | UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); |
@@ -124,12 +142,17 @@ static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts) | |||
124 | */ | 142 | */ |
125 | static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts) | 143 | static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts) |
126 | { | 144 | { |
127 | ucb1x00_reg_write(ts->ucb, UCB_TS_CR, | 145 | if (machine_is_collie()) |
128 | UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | | 146 | ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK); |
129 | UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); | 147 | else { |
130 | ucb1x00_reg_write(ts->ucb, UCB_TS_CR, | 148 | ucb1x00_reg_write(ts->ucb, UCB_TS_CR, |
131 | UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | | 149 | UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | |
132 | UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); | 150 | UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); |
151 | ucb1x00_reg_write(ts->ucb, UCB_TS_CR, | ||
152 | UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | | ||
153 | UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); | ||
154 | } | ||
155 | |||
133 | ucb1x00_reg_write(ts->ucb, UCB_TS_CR, | 156 | ucb1x00_reg_write(ts->ucb, UCB_TS_CR, |
134 | UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | | 157 | UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | |
135 | UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); | 158 | UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); |
@@ -163,6 +186,15 @@ static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts) | |||
163 | return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync); | 186 | return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync); |
164 | } | 187 | } |
165 | 188 | ||
189 | static inline int ucb1x00_ts_pen_down(struct ucb1x00_ts *ts) | ||
190 | { | ||
191 | unsigned int val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR); | ||
192 | if (machine_is_collie()) | ||
193 | return (!(val & (UCB_TS_CR_TSPX_LOW))); | ||
194 | else | ||
195 | return (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW)); | ||
196 | } | ||
197 | |||
166 | /* | 198 | /* |
167 | * This is a RT kernel thread that handles the ADC accesses | 199 | * This is a RT kernel thread that handles the ADC accesses |
168 | * (mainly so we can use semaphores in the UCB1200 core code | 200 | * (mainly so we can use semaphores in the UCB1200 core code |
@@ -186,7 +218,7 @@ static int ucb1x00_thread(void *_ts) | |||
186 | 218 | ||
187 | add_wait_queue(&ts->irq_wait, &wait); | 219 | add_wait_queue(&ts->irq_wait, &wait); |
188 | while (!kthread_should_stop()) { | 220 | while (!kthread_should_stop()) { |
189 | unsigned int x, y, p, val; | 221 | unsigned int x, y, p; |
190 | signed long timeout; | 222 | signed long timeout; |
191 | 223 | ||
192 | ts->restart = 0; | 224 | ts->restart = 0; |
@@ -206,12 +238,12 @@ static int ucb1x00_thread(void *_ts) | |||
206 | msleep(10); | 238 | msleep(10); |
207 | 239 | ||
208 | ucb1x00_enable(ts->ucb); | 240 | ucb1x00_enable(ts->ucb); |
209 | val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR); | ||
210 | 241 | ||
211 | if (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW)) { | 242 | |
243 | if (ucb1x00_ts_pen_down(ts)) { | ||
212 | set_task_state(tsk, TASK_INTERRUPTIBLE); | 244 | set_task_state(tsk, TASK_INTERRUPTIBLE); |
213 | 245 | ||
214 | ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING); | 246 | ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, machine_is_collie() ? UCB_RISING : UCB_FALLING); |
215 | ucb1x00_disable(ts->ucb); | 247 | ucb1x00_disable(ts->ucb); |
216 | 248 | ||
217 | /* | 249 | /* |
@@ -341,26 +373,30 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev) | |||
341 | { | 373 | { |
342 | struct ucb1x00_ts *ts; | 374 | struct ucb1x00_ts *ts; |
343 | 375 | ||
344 | ts = kmalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL); | 376 | ts = kzalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL); |
345 | if (!ts) | 377 | if (!ts) |
346 | return -ENOMEM; | 378 | return -ENOMEM; |
347 | 379 | ||
348 | memset(ts, 0, sizeof(struct ucb1x00_ts)); | 380 | ts->idev = input_allocate_device(); |
381 | if (!ts->idev) { | ||
382 | kfree(ts); | ||
383 | return -ENOMEM; | ||
384 | } | ||
349 | 385 | ||
350 | ts->ucb = dev->ucb; | 386 | ts->ucb = dev->ucb; |
351 | ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC; | 387 | ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC; |
352 | 388 | ||
353 | ts->idev.name = "Touchscreen panel"; | 389 | ts->idev->name = "Touchscreen panel"; |
354 | ts->idev.id.product = ts->ucb->id; | 390 | ts->idev->id.product = ts->ucb->id; |
355 | ts->idev.open = ucb1x00_ts_open; | 391 | ts->idev->open = ucb1x00_ts_open; |
356 | ts->idev.close = ucb1x00_ts_close; | 392 | ts->idev->close = ucb1x00_ts_close; |
357 | 393 | ||
358 | __set_bit(EV_ABS, ts->idev.evbit); | 394 | __set_bit(EV_ABS, ts->idev->evbit); |
359 | __set_bit(ABS_X, ts->idev.absbit); | 395 | __set_bit(ABS_X, ts->idev->absbit); |
360 | __set_bit(ABS_Y, ts->idev.absbit); | 396 | __set_bit(ABS_Y, ts->idev->absbit); |
361 | __set_bit(ABS_PRESSURE, ts->idev.absbit); | 397 | __set_bit(ABS_PRESSURE, ts->idev->absbit); |
362 | 398 | ||
363 | input_register_device(&ts->idev); | 399 | input_register_device(ts->idev); |
364 | 400 | ||
365 | dev->priv = ts; | 401 | dev->priv = ts; |
366 | 402 | ||
@@ -370,7 +406,8 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev) | |||
370 | static void ucb1x00_ts_remove(struct ucb1x00_dev *dev) | 406 | static void ucb1x00_ts_remove(struct ucb1x00_dev *dev) |
371 | { | 407 | { |
372 | struct ucb1x00_ts *ts = dev->priv; | 408 | struct ucb1x00_ts *ts = dev->priv; |
373 | input_unregister_device(&ts->idev); | 409 | |
410 | input_unregister_device(ts->idev); | ||
374 | kfree(ts); | 411 | kfree(ts); |
375 | } | 412 | } |
376 | 413 | ||