aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2010-06-30 17:50:51 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2010-07-03 16:13:14 -0400
commit14fbbc36d126d7ec7717144def386b9fc4c7fba2 (patch)
tree425be4f1742e0f9de874573d4f10e9831f3ca27d /drivers/input
parent4397c98a8a60ba029f2d0051d0cbafe600f05d8c (diff)
Input: ad7879 - add open and close methods
Tested-by: Michael Hennerich <michael.hennerich@analog.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/touchscreen/ad7879-i2c.c4
-rw-r--r--drivers/input/touchscreen/ad7879-spi.c4
-rw-r--r--drivers/input/touchscreen/ad7879.c113
-rw-r--r--drivers/input/touchscreen/ad7879.h4
4 files changed, 86 insertions, 39 deletions
diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c
index 85dfdd27df5a..81937b21e9d2 100644
--- a/drivers/input/touchscreen/ad7879-i2c.c
+++ b/drivers/input/touchscreen/ad7879-i2c.c
@@ -20,7 +20,7 @@ static int ad7879_i2c_suspend(struct i2c_client *client, pm_message_t message)
20{ 20{
21 struct ad7879 *ts = i2c_get_clientdata(client); 21 struct ad7879 *ts = i2c_get_clientdata(client);
22 22
23 ad7879_disable(ts); 23 ad7879_suspend(ts);
24 24
25 return 0; 25 return 0;
26} 26}
@@ -29,7 +29,7 @@ static int ad7879_i2c_resume(struct i2c_client *client)
29{ 29{
30 struct ad7879 *ts = i2c_get_clientdata(client); 30 struct ad7879 *ts = i2c_get_clientdata(client);
31 31
32 ad7879_enable(ts); 32 ad7879_resume(ts);
33 33
34 return 0; 34 return 0;
35} 35}
diff --git a/drivers/input/touchscreen/ad7879-spi.c b/drivers/input/touchscreen/ad7879-spi.c
index 5d1e5a050332..9fa8e5de5ff9 100644
--- a/drivers/input/touchscreen/ad7879-spi.c
+++ b/drivers/input/touchscreen/ad7879-spi.c
@@ -25,7 +25,7 @@ static int ad7879_spi_suspend(struct spi_device *spi, pm_message_t message)
25{ 25{
26 struct ad7879 *ts = spi_get_drvdata(spi); 26 struct ad7879 *ts = spi_get_drvdata(spi);
27 27
28 ad7879_disable(ts); 28 ad7879_suspend(ts);
29 29
30 return 0; 30 return 0;
31} 31}
@@ -34,7 +34,7 @@ static int ad7879_spi_resume(struct spi_device *spi)
34{ 34{
35 struct ad7879 *ts = spi_get_drvdata(spi); 35 struct ad7879 *ts = spi_get_drvdata(spi);
36 36
37 ad7879_enable(ts); 37 ad7879_resume(ts);
38 38
39 return 0; 39 return 0;
40} 40}
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c
index 1de19691c4a3..fad65969cc72 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);
diff --git a/drivers/input/touchscreen/ad7879.h b/drivers/input/touchscreen/ad7879.h
index 169f155db3b9..6b45a27236c7 100644
--- a/drivers/input/touchscreen/ad7879.h
+++ b/drivers/input/touchscreen/ad7879.h
@@ -21,8 +21,8 @@ struct ad7879_bus_ops {
21 int (*write)(struct device *dev, u8 reg, u16 val); 21 int (*write)(struct device *dev, u8 reg, u16 val);
22}; 22};
23 23
24void ad7879_disable(struct ad7879 *); 24void ad7879_suspend(struct ad7879 *);
25void ad7879_enable(struct ad7879 *); 25void ad7879_resume(struct ad7879 *);
26struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned irq, 26struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned irq,
27 const struct ad7879_bus_ops *bops); 27 const struct ad7879_bus_ops *bops);
28void ad7879_remove(struct ad7879 *); 28void ad7879_remove(struct ad7879 *);