diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-06-30 17:50:51 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-07-03 16:13:14 -0400 |
commit | 14fbbc36d126d7ec7717144def386b9fc4c7fba2 (patch) | |
tree | 425be4f1742e0f9de874573d4f10e9831f3ca27d /drivers/input | |
parent | 4397c98a8a60ba029f2d0051d0cbafe600f05d8c (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.c | 4 | ||||
-rw-r--r-- | drivers/input/touchscreen/ad7879-spi.c | 4 | ||||
-rw-r--r-- | drivers/input/touchscreen/ad7879.c | 113 | ||||
-rw-r--r-- | drivers/input/touchscreen/ad7879.h | 4 |
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 | ||
211 | static void ad7879_setup(struct ad7879 *ts) | 212 | static 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 | ||
218 | void ad7879_disable(struct ad7879 *ts) | 221 | static 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, | 232 | static 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 | } |
236 | EXPORT_SYMBOL(ad7879_disable); | ||
237 | 242 | ||
238 | void ad7879_enable(struct ad7879 *ts) | 243 | static 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 | |||
252 | void 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 | } | ||
263 | EXPORT_SYMBOL(ad7879_suspend); | ||
264 | |||
265 | void 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 | } | ||
276 | EXPORT_SYMBOL(ad7879_resume); | ||
277 | |||
278 | static 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 | } |
250 | EXPORT_SYMBOL(ad7879_enable); | ||
251 | 297 | ||
252 | static ssize_t ad7879_disable_show(struct device *dev, | 298 | static 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); | |||
543 | void ad7879_remove(struct ad7879 *ts) | 591 | void 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 | ||
24 | void ad7879_disable(struct ad7879 *); | 24 | void ad7879_suspend(struct ad7879 *); |
25 | void ad7879_enable(struct ad7879 *); | 25 | void ad7879_resume(struct ad7879 *); |
26 | struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned irq, | 26 | struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned irq, |
27 | const struct ad7879_bus_ops *bops); | 27 | const struct ad7879_bus_ops *bops); |
28 | void ad7879_remove(struct ad7879 *); | 28 | void ad7879_remove(struct ad7879 *); |