aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen/tsc2007.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen/tsc2007.c')
-rw-r--r--drivers/input/touchscreen/tsc2007.c200
1 files changed, 109 insertions, 91 deletions
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c
index fadc11545b1..1f674cb6c55 100644
--- a/drivers/input/touchscreen/tsc2007.c
+++ b/drivers/input/touchscreen/tsc2007.c
@@ -66,7 +66,6 @@ struct ts_event {
66struct tsc2007 { 66struct tsc2007 {
67 struct input_dev *input; 67 struct input_dev *input;
68 char phys[32]; 68 char phys[32];
69 struct delayed_work work;
70 69
71 struct i2c_client *client; 70 struct i2c_client *client;
72 71
@@ -76,9 +75,11 @@ struct tsc2007 {
76 unsigned long poll_delay; 75 unsigned long poll_delay;
77 unsigned long poll_period; 76 unsigned long poll_period;
78 77
79 bool pendown;
80 int irq; 78 int irq;
81 79
80 wait_queue_head_t wait;
81 bool stopped;
82
82 int (*get_pendown_state)(void); 83 int (*get_pendown_state)(void);
83 void (*clear_penirq)(void); 84 void (*clear_penirq)(void);
84}; 85};
@@ -141,25 +142,8 @@ static u32 tsc2007_calculate_pressure(struct tsc2007 *tsc, struct ts_event *tc)
141 return rt; 142 return rt;
142} 143}
143 144
144static void tsc2007_send_up_event(struct tsc2007 *tsc) 145static bool tsc2007_is_pen_down(struct tsc2007 *ts)
145{ 146{
146 struct input_dev *input = tsc->input;
147
148 dev_dbg(&tsc->client->dev, "UP\n");
149
150 input_report_key(input, BTN_TOUCH, 0);
151 input_report_abs(input, ABS_PRESSURE, 0);
152 input_sync(input);
153}
154
155static void tsc2007_work(struct work_struct *work)
156{
157 struct tsc2007 *ts =
158 container_of(to_delayed_work(work), struct tsc2007, work);
159 bool debounced = false;
160 struct ts_event tc;
161 u32 rt;
162
163 /* 147 /*
164 * NOTE: We can't rely on the pressure to determine the pen down 148 * NOTE: We can't rely on the pressure to determine the pen down
165 * state, even though this controller has a pressure sensor. 149 * state, even though this controller has a pressure sensor.
@@ -170,79 +154,82 @@ static void tsc2007_work(struct work_struct *work)
170 * The only safe way to check for the pen up condition is in the 154 * The only safe way to check for the pen up condition is in the
171 * work function by reading the pen signal state (it's a GPIO 155 * work function by reading the pen signal state (it's a GPIO
172 * and IRQ). Unfortunately such callback is not always available, 156 * and IRQ). Unfortunately such callback is not always available,
173 * in that case we have rely on the pressure anyway. 157 * in that case we assume that the pen is down and expect caller
158 * to fall back on the pressure reading.
174 */ 159 */
175 if (ts->get_pendown_state) {
176 if (unlikely(!ts->get_pendown_state())) {
177 tsc2007_send_up_event(ts);
178 ts->pendown = false;
179 goto out;
180 }
181 160
182 dev_dbg(&ts->client->dev, "pen is still down\n"); 161 if (!ts->get_pendown_state)
183 } 162 return true;
163
164 return ts->get_pendown_state();
165}
166
167static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
168{
169 struct tsc2007 *ts = handle;
170 struct input_dev *input = ts->input;
171 struct ts_event tc;
172 u32 rt;
184 173
185 tsc2007_read_values(ts, &tc); 174 while (!ts->stopped && tsc2007_is_pen_down(ts)) {
186 175
187 rt = tsc2007_calculate_pressure(ts, &tc); 176 /* pen is down, continue with the measurement */
188 if (rt > ts->max_rt) { 177 tsc2007_read_values(ts, &tc);
189 /*
190 * Sample found inconsistent by debouncing or pressure is
191 * beyond the maximum. Don't report it to user space,
192 * repeat at least once more the measurement.
193 */
194 dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);
195 debounced = true;
196 goto out;
197 178
198 } 179 rt = tsc2007_calculate_pressure(ts, &tc);
199 180
200 if (rt) { 181 if (rt == 0 && !ts->get_pendown_state) {
201 struct input_dev *input = ts->input; 182 /*
183 * If pressure reported is 0 and we don't have
184 * callback to check pendown state, we have to
185 * assume that pen was lifted up.
186 */
187 break;
188 }
202 189
203 if (!ts->pendown) { 190 if (rt <= ts->max_rt) {
204 dev_dbg(&ts->client->dev, "DOWN\n"); 191 dev_dbg(&ts->client->dev,
192 "DOWN point(%4d,%4d), pressure (%4u)\n",
193 tc.x, tc.y, rt);
205 194
206 input_report_key(input, BTN_TOUCH, 1); 195 input_report_key(input, BTN_TOUCH, 1);
207 ts->pendown = true; 196 input_report_abs(input, ABS_X, tc.x);
197 input_report_abs(input, ABS_Y, tc.y);
198 input_report_abs(input, ABS_PRESSURE, rt);
199
200 input_sync(input);
201
202 } else {
203 /*
204 * Sample found inconsistent by debouncing or pressure is
205 * beyond the maximum. Don't report it to user space,
206 * repeat at least once more the measurement.
207 */
208 dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);
208 } 209 }
209 210
210 input_report_abs(input, ABS_X, tc.x); 211 wait_event_timeout(ts->wait, ts->stopped,
211 input_report_abs(input, ABS_Y, tc.y); 212 msecs_to_jiffies(ts->poll_period));
212 input_report_abs(input, ABS_PRESSURE, rt); 213 }
213 214
214 input_sync(input); 215 dev_dbg(&ts->client->dev, "UP\n");
215 216
216 dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure (%4u)\n", 217 input_report_key(input, BTN_TOUCH, 0);
217 tc.x, tc.y, rt); 218 input_report_abs(input, ABS_PRESSURE, 0);
219 input_sync(input);
218 220
219 } else if (!ts->get_pendown_state && ts->pendown) { 221 if (ts->clear_penirq)
220 /* 222 ts->clear_penirq();
221 * We don't have callback to check pendown state, so we
222 * have to assume that since pressure reported is 0 the
223 * pen was lifted up.
224 */
225 tsc2007_send_up_event(ts);
226 ts->pendown = false;
227 }
228 223
229 out: 224 return IRQ_HANDLED;
230 if (ts->pendown || debounced)
231 schedule_delayed_work(&ts->work,
232 msecs_to_jiffies(ts->poll_period));
233 else
234 enable_irq(ts->irq);
235} 225}
236 226
237static irqreturn_t tsc2007_irq(int irq, void *handle) 227static irqreturn_t tsc2007_hard_irq(int irq, void *handle)
238{ 228{
239 struct tsc2007 *ts = handle; 229 struct tsc2007 *ts = handle;
240 230
241 if (!ts->get_pendown_state || likely(ts->get_pendown_state())) { 231 if (!ts->get_pendown_state || likely(ts->get_pendown_state()))
242 disable_irq_nosync(ts->irq); 232 return IRQ_WAKE_THREAD;
243 schedule_delayed_work(&ts->work,
244 msecs_to_jiffies(ts->poll_delay));
245 }
246 233
247 if (ts->clear_penirq) 234 if (ts->clear_penirq)
248 ts->clear_penirq(); 235 ts->clear_penirq();
@@ -250,17 +237,40 @@ static irqreturn_t tsc2007_irq(int irq, void *handle)
250 return IRQ_HANDLED; 237 return IRQ_HANDLED;
251} 238}
252 239
253static void tsc2007_free_irq(struct tsc2007 *ts) 240static void tsc2007_stop(struct tsc2007 *ts)
254{ 241{
255 free_irq(ts->irq, ts); 242 ts->stopped = true;
256 if (cancel_delayed_work_sync(&ts->work)) { 243 mb();
257 /* 244 wake_up(&ts->wait);
258 * Work was pending, therefore we need to enable 245
259 * IRQ here to balance the disable_irq() done in the 246 disable_irq(ts->irq);
260 * interrupt handler. 247}
261 */ 248
262 enable_irq(ts->irq); 249static int tsc2007_open(struct input_dev *input_dev)
250{
251 struct tsc2007 *ts = input_get_drvdata(input_dev);
252 int err;
253
254 ts->stopped = false;
255 mb();
256
257 enable_irq(ts->irq);
258
259 /* Prepare for touch readings - power down ADC and enable PENIRQ */
260 err = tsc2007_xfer(ts, PWRDOWN);
261 if (err < 0) {
262 tsc2007_stop(ts);
263 return err;
263 } 264 }
265
266 return 0;
267}
268
269static void tsc2007_close(struct input_dev *input_dev)
270{
271 struct tsc2007 *ts = input_get_drvdata(input_dev);
272
273 tsc2007_stop(ts);
264} 274}
265 275
266static int __devinit tsc2007_probe(struct i2c_client *client, 276static int __devinit tsc2007_probe(struct i2c_client *client,
@@ -290,7 +300,7 @@ static int __devinit tsc2007_probe(struct i2c_client *client,
290 ts->client = client; 300 ts->client = client;
291 ts->irq = client->irq; 301 ts->irq = client->irq;
292 ts->input = input_dev; 302 ts->input = input_dev;
293 INIT_DELAYED_WORK(&ts->work, tsc2007_work); 303 init_waitqueue_head(&ts->wait);
294 304
295 ts->model = pdata->model; 305 ts->model = pdata->model;
296 ts->x_plate_ohms = pdata->x_plate_ohms; 306 ts->x_plate_ohms = pdata->x_plate_ohms;
@@ -300,6 +310,12 @@ static int __devinit tsc2007_probe(struct i2c_client *client,
300 ts->get_pendown_state = pdata->get_pendown_state; 310 ts->get_pendown_state = pdata->get_pendown_state;
301 ts->clear_penirq = pdata->clear_penirq; 311 ts->clear_penirq = pdata->clear_penirq;
302 312
313 if (pdata->x_plate_ohms == 0) {
314 dev_err(&client->dev, "x_plate_ohms is not set up in platform data");
315 err = -EINVAL;
316 goto err_free_mem;
317 }
318
303 snprintf(ts->phys, sizeof(ts->phys), 319 snprintf(ts->phys, sizeof(ts->phys),
304 "%s/input0", dev_name(&client->dev)); 320 "%s/input0", dev_name(&client->dev));
305 321
@@ -307,6 +323,11 @@ static int __devinit tsc2007_probe(struct i2c_client *client,
307 input_dev->phys = ts->phys; 323 input_dev->phys = ts->phys;
308 input_dev->id.bustype = BUS_I2C; 324 input_dev->id.bustype = BUS_I2C;
309 325
326 input_dev->open = tsc2007_open;
327 input_dev->close = tsc2007_close;
328
329 input_set_drvdata(input_dev, ts);
330
310 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 331 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
311 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 332 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
312 333
@@ -318,17 +339,14 @@ static int __devinit tsc2007_probe(struct i2c_client *client,
318 if (pdata->init_platform_hw) 339 if (pdata->init_platform_hw)
319 pdata->init_platform_hw(); 340 pdata->init_platform_hw();
320 341
321 err = request_irq(ts->irq, tsc2007_irq, 0, 342 err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq,
322 client->dev.driver->name, ts); 343 IRQF_ONESHOT, client->dev.driver->name, ts);
323 if (err < 0) { 344 if (err < 0) {
324 dev_err(&client->dev, "irq %d busy?\n", ts->irq); 345 dev_err(&client->dev, "irq %d busy?\n", ts->irq);
325 goto err_free_mem; 346 goto err_free_mem;
326 } 347 }
327 348
328 /* Prepare for touch readings - power down ADC and enable PENIRQ */ 349 tsc2007_stop(ts);
329 err = tsc2007_xfer(ts, PWRDOWN);
330 if (err < 0)
331 goto err_free_irq;
332 350
333 err = input_register_device(input_dev); 351 err = input_register_device(input_dev);
334 if (err) 352 if (err)
@@ -339,7 +357,7 @@ static int __devinit tsc2007_probe(struct i2c_client *client,
339 return 0; 357 return 0;
340 358
341 err_free_irq: 359 err_free_irq:
342 tsc2007_free_irq(ts); 360 free_irq(ts->irq, ts);
343 if (pdata->exit_platform_hw) 361 if (pdata->exit_platform_hw)
344 pdata->exit_platform_hw(); 362 pdata->exit_platform_hw();
345 err_free_mem: 363 err_free_mem:
@@ -353,7 +371,7 @@ static int __devexit tsc2007_remove(struct i2c_client *client)
353 struct tsc2007 *ts = i2c_get_clientdata(client); 371 struct tsc2007 *ts = i2c_get_clientdata(client);
354 struct tsc2007_platform_data *pdata = client->dev.platform_data; 372 struct tsc2007_platform_data *pdata = client->dev.platform_data;
355 373
356 tsc2007_free_irq(ts); 374 free_irq(ts->irq, ts);
357 375
358 if (pdata->exit_platform_hw) 376 if (pdata->exit_platform_hw)
359 pdata->exit_platform_hw(); 377 pdata->exit_platform_hw();