aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen/ad7879.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen/ad7879.c')
-rw-r--r--drivers/input/touchscreen/ad7879.c113
1 files changed, 80 insertions, 33 deletions
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c
index 1de19691c4a..fad65969cc7 100644
--- a/drivers/input/touchscreen/ad7879.c
+++ b/drivers/input/touchscreen/ad7879.c
@@ -112,10 +112,11 @@ struct ad7879 {
112 struct timer_list timer; 112 struct timer_list timer;
113#ifdef CONFIG_GPIOLIB 113#ifdef CONFIG_GPIOLIB
114 struct gpio_chip gc; 114 struct gpio_chip gc;
115 struct mutex mutex;
115#endif 116#endif
116 unsigned int irq; 117 unsigned int irq;
117 struct mutex mutex; 118 bool disabled; /* P: input->mutex */
118 bool disabled; /* P: mutex */ 119 bool suspended; /* P: input->mutex */
119 u16 conversion_data[AD7879_NR_SENSE]; 120 u16 conversion_data[AD7879_NR_SENSE];
120 char phys[32]; 121 char phys[32];
121 u8 first_conversion_delay; 122 u8 first_conversion_delay;
@@ -208,46 +209,91 @@ static irqreturn_t ad7879_irq(int irq, void *handle)
208 return IRQ_HANDLED; 209 return IRQ_HANDLED;
209} 210}
210 211
211static void ad7879_setup(struct ad7879 *ts) 212static void __ad7879_enable(struct ad7879 *ts)
212{ 213{
213 ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2); 214 ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);
214 ad7879_write(ts, AD7879_REG_CTRL3, ts->cmd_crtl3); 215 ad7879_write(ts, AD7879_REG_CTRL3, ts->cmd_crtl3);
215 ad7879_write(ts, AD7879_REG_CTRL1, ts->cmd_crtl1); 216 ad7879_write(ts, AD7879_REG_CTRL1, ts->cmd_crtl1);
217
218 enable_irq(ts->irq);
216} 219}
217 220
218void ad7879_disable(struct ad7879 *ts) 221static void __ad7879_disable(struct ad7879 *ts)
219{ 222{
220 mutex_lock(&ts->mutex); 223 disable_irq(ts->irq);
221 224
222 if (!ts->disabled) { 225 if (del_timer_sync(&ts->timer))
226 ad7879_ts_event_release(ts);
223 227
224 ts->disabled = true; 228 ad7879_write(ts, AD7879_REG_CTRL2, AD7879_PM(AD7879_PM_SHUTDOWN));
225 disable_irq(ts->irq); 229}
226 230
227 if (del_timer_sync(&ts->timer))
228 ad7879_ts_event_release(ts);
229 231
230 ad7879_write(ts, AD7879_REG_CTRL2, 232static int ad7879_open(struct input_dev *input)
231 AD7879_PM(AD7879_PM_SHUTDOWN)); 233{
232 } 234 struct ad7879 *ts = input_get_drvdata(input);
233 235
234 mutex_unlock(&ts->mutex); 236 /* protected by input->mutex */
237 if (!ts->disabled && !ts->suspended)
238 __ad7879_enable(ts);
239
240 return 0;
235} 241}
236EXPORT_SYMBOL(ad7879_disable);
237 242
238void ad7879_enable(struct ad7879 *ts) 243static void ad7879_close(struct input_dev* input)
239{ 244{
240 mutex_lock(&ts->mutex); 245 struct ad7879 *ts = input_get_drvdata(input);
246
247 /* protected by input->mutex */
248 if (!ts->disabled && !ts->suspended)
249 __ad7879_disable(ts);
250}
251
252void ad7879_suspend(struct ad7879 *ts)
253{
254 mutex_lock(&ts->input->mutex);
255
256 if (!ts->suspended && !ts->disabled && ts->input->users)
257 __ad7879_disable(ts);
258
259 ts->suspended = true;
260
261 mutex_unlock(&ts->input->mutex);
262}
263EXPORT_SYMBOL(ad7879_suspend);
264
265void ad7879_resume(struct ad7879 *ts)
266{
267 mutex_lock(&ts->input->mutex);
241 268
242 if (ts->disabled) { 269 if (ts->suspended && !ts->disabled && ts->input->users)
243 ad7879_setup(ts); 270 __ad7879_enable(ts);
244 ts->disabled = false; 271
245 enable_irq(ts->irq); 272 ts->suspended = false;
273
274 mutex_unlock(&ts->input->mutex);
275}
276EXPORT_SYMBOL(ad7879_resume);
277
278static void ad7879_toggle(struct ad7879 *ts, bool disable)
279{
280 mutex_lock(&ts->input->mutex);
281
282 if (!ts->suspended && ts->input->users != 0) {
283
284 if (disable) {
285 if (ts->disabled)
286 __ad7879_enable(ts);
287 } else {
288 if (!ts->disabled)
289 __ad7879_disable(ts);
290 }
246 } 291 }
247 292
248 mutex_unlock(&ts->mutex); 293 ts->disabled = disable;
294
295 mutex_unlock(&ts->input->mutex);
249} 296}
250EXPORT_SYMBOL(ad7879_enable);
251 297
252static ssize_t ad7879_disable_show(struct device *dev, 298static ssize_t ad7879_disable_show(struct device *dev,
253 struct device_attribute *attr, char *buf) 299 struct device_attribute *attr, char *buf)
@@ -269,10 +315,7 @@ static ssize_t ad7879_disable_store(struct device *dev,
269 if (error) 315 if (error)
270 return error; 316 return error;
271 317
272 if (val) 318 ad7879_toggle(ts, val);
273 ad7879_disable(ts);
274 else
275 ad7879_enable(ts);
276 319
277 return count; 320 return count;
278} 321}
@@ -355,6 +398,8 @@ static int ad7879_gpio_add(struct ad7879 *ts,
355{ 398{
356 int ret = 0; 399 int ret = 0;
357 400
401 mutex_init(&ts->mutex);
402
358 if (pdata->gpio_export) { 403 if (pdata->gpio_export) {
359 ts->gc.direction_input = ad7879_gpio_direction_input; 404 ts->gc.direction_input = ad7879_gpio_direction_input;
360 ts->gc.direction_output = ad7879_gpio_direction_output; 405 ts->gc.direction_output = ad7879_gpio_direction_output;
@@ -431,11 +476,9 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq,
431 ts->bops = bops; 476 ts->bops = bops;
432 ts->dev = dev; 477 ts->dev = dev;
433 ts->input = input_dev; 478 ts->input = input_dev;
479 ts->irq = irq;
434 480
435 setup_timer(&ts->timer, ad7879_timer, (unsigned long) ts); 481 setup_timer(&ts->timer, ad7879_timer, (unsigned long) ts);
436 mutex_init(&ts->mutex);
437
438 ts->irq = irq;
439 482
440 ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; 483 ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
441 ts->pressure_max = pdata->pressure_max ? : ~0; 484 ts->pressure_max = pdata->pressure_max ? : ~0;
@@ -453,6 +496,11 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq,
453 input_dev->dev.parent = dev; 496 input_dev->dev.parent = dev;
454 input_dev->id.bustype = bops->bustype; 497 input_dev->id.bustype = bops->bustype;
455 498
499 input_dev->open = ad7879_open;
500 input_dev->close = ad7879_close;
501
502 input_set_drvdata(input_dev, ts);
503
456 __set_bit(EV_ABS, input_dev->evbit); 504 __set_bit(EV_ABS, input_dev->evbit);
457 __set_bit(ABS_X, input_dev->absbit); 505 __set_bit(ABS_X, input_dev->absbit);
458 __set_bit(ABS_Y, input_dev->absbit); 506 __set_bit(ABS_Y, input_dev->absbit);
@@ -502,8 +550,6 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq,
502 AD7879_ACQ(ts->acquisition_time) | 550 AD7879_ACQ(ts->acquisition_time) |
503 AD7879_TMR(ts->pen_down_acc_interval); 551 AD7879_TMR(ts->pen_down_acc_interval);
504 552
505 ad7879_setup(ts);
506
507 err = request_threaded_irq(ts->irq, NULL, ad7879_irq, 553 err = request_threaded_irq(ts->irq, NULL, ad7879_irq,
508 IRQF_TRIGGER_FALLING, 554 IRQF_TRIGGER_FALLING,
509 dev_name(dev), ts); 555 dev_name(dev), ts);
@@ -512,6 +558,8 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq,
512 goto err_free_mem; 558 goto err_free_mem;
513 } 559 }
514 560
561 __ad7879_disable(ts);
562
515 err = sysfs_create_group(&dev->kobj, &ad7879_attr_group); 563 err = sysfs_create_group(&dev->kobj, &ad7879_attr_group);
516 if (err) 564 if (err)
517 goto err_free_irq; 565 goto err_free_irq;
@@ -543,7 +591,6 @@ EXPORT_SYMBOL(ad7879_probe);
543void ad7879_remove(struct ad7879 *ts) 591void ad7879_remove(struct ad7879 *ts)
544{ 592{
545 ad7879_gpio_remove(ts); 593 ad7879_gpio_remove(ts);
546 ad7879_disable(ts);
547 sysfs_remove_group(&ts->dev->kobj, &ad7879_attr_group); 594 sysfs_remove_group(&ts->dev->kobj, &ad7879_attr_group);
548 free_irq(ts->irq, ts); 595 free_irq(ts->irq, ts);
549 input_unregister_device(ts->input); 596 input_unregister_device(ts->input);