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.c117
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
42struct ucb1x00_ts { 45struct 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
57static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y) 60static 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
65static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts) 68static 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 */
86static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts) 89static 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 */
102static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts) 116static 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 */
125static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts) 143static 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
189static 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)
370static void ucb1x00_ts_remove(struct ucb1x00_dev *dev) 406static 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