diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-06-08 02:24:07 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-06-08 02:24:07 -0400 |
commit | a292241cccb7e20e8b997a9a44177e7c98141859 (patch) | |
tree | a0b0bb95e7dce3233a2d8b203f9e326cdec7a00e /drivers/input/touchscreen/tsc2005.c | |
parent | d49cb7aeebb974713f9f7ab2991352d3050b095b (diff) | |
parent | 68807a0c2015cb40df4869e16651f0ce5cc14d52 (diff) |
Merge branch 'next' into for-linus
Prepare input updates for 3.16.
Diffstat (limited to 'drivers/input/touchscreen/tsc2005.c')
-rw-r--r-- | drivers/input/touchscreen/tsc2005.c | 157 |
1 files changed, 116 insertions, 41 deletions
diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 550adcbbfc23..52380b68ebdf 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c | |||
@@ -25,11 +25,15 @@ | |||
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/input.h> | 27 | #include <linux/input.h> |
28 | #include <linux/input/touchscreen.h> | ||
28 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
29 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
30 | #include <linux/pm.h> | 31 | #include <linux/pm.h> |
32 | #include <linux/of.h> | ||
33 | #include <linux/of_gpio.h> | ||
31 | #include <linux/spi/spi.h> | 34 | #include <linux/spi/spi.h> |
32 | #include <linux/spi/tsc2005.h> | 35 | #include <linux/spi/tsc2005.h> |
36 | #include <linux/regulator/consumer.h> | ||
33 | 37 | ||
34 | /* | 38 | /* |
35 | * The touchscreen interface operates as follows: | 39 | * The touchscreen interface operates as follows: |
@@ -100,6 +104,11 @@ | |||
100 | TSC2005_CFR2_AVG_7) | 104 | TSC2005_CFR2_AVG_7) |
101 | 105 | ||
102 | #define MAX_12BIT 0xfff | 106 | #define MAX_12BIT 0xfff |
107 | #define TSC2005_DEF_X_FUZZ 4 | ||
108 | #define TSC2005_DEF_Y_FUZZ 8 | ||
109 | #define TSC2005_DEF_P_FUZZ 2 | ||
110 | #define TSC2005_DEF_RESISTOR 280 | ||
111 | |||
103 | #define TSC2005_SPI_MAX_SPEED_HZ 10000000 | 112 | #define TSC2005_SPI_MAX_SPEED_HZ 10000000 |
104 | #define TSC2005_PENUP_TIME_MS 40 | 113 | #define TSC2005_PENUP_TIME_MS 40 |
105 | 114 | ||
@@ -143,6 +152,9 @@ struct tsc2005 { | |||
143 | 152 | ||
144 | bool pen_down; | 153 | bool pen_down; |
145 | 154 | ||
155 | struct regulator *vio; | ||
156 | |||
157 | int reset_gpio; | ||
146 | void (*set_reset)(bool enable); | 158 | void (*set_reset)(bool enable); |
147 | }; | 159 | }; |
148 | 160 | ||
@@ -337,6 +349,14 @@ static void tsc2005_stop_scan(struct tsc2005 *ts) | |||
337 | tsc2005_cmd(ts, TSC2005_CMD_STOP); | 349 | tsc2005_cmd(ts, TSC2005_CMD_STOP); |
338 | } | 350 | } |
339 | 351 | ||
352 | static void tsc2005_set_reset(struct tsc2005 *ts, bool enable) | ||
353 | { | ||
354 | if (ts->reset_gpio >= 0) | ||
355 | gpio_set_value(ts->reset_gpio, enable); | ||
356 | else if (ts->set_reset) | ||
357 | ts->set_reset(enable); | ||
358 | } | ||
359 | |||
340 | /* must be called with ts->mutex held */ | 360 | /* must be called with ts->mutex held */ |
341 | static void __tsc2005_disable(struct tsc2005 *ts) | 361 | static void __tsc2005_disable(struct tsc2005 *ts) |
342 | { | 362 | { |
@@ -355,7 +375,7 @@ static void __tsc2005_enable(struct tsc2005 *ts) | |||
355 | { | 375 | { |
356 | tsc2005_start_scan(ts); | 376 | tsc2005_start_scan(ts); |
357 | 377 | ||
358 | if (ts->esd_timeout && ts->set_reset) { | 378 | if (ts->esd_timeout && (ts->set_reset || ts->reset_gpio)) { |
359 | ts->last_valid_interrupt = jiffies; | 379 | ts->last_valid_interrupt = jiffies; |
360 | schedule_delayed_work(&ts->esd_work, | 380 | schedule_delayed_work(&ts->esd_work, |
361 | round_jiffies_relative( | 381 | round_jiffies_relative( |
@@ -414,9 +434,9 @@ static ssize_t tsc2005_selftest_show(struct device *dev, | |||
414 | } | 434 | } |
415 | 435 | ||
416 | /* hardware reset */ | 436 | /* hardware reset */ |
417 | ts->set_reset(false); | 437 | tsc2005_set_reset(ts, false); |
418 | usleep_range(100, 500); /* only 10us required */ | 438 | usleep_range(100, 500); /* only 10us required */ |
419 | ts->set_reset(true); | 439 | tsc2005_set_reset(ts, true); |
420 | 440 | ||
421 | if (!success) | 441 | if (!success) |
422 | goto out; | 442 | goto out; |
@@ -459,7 +479,7 @@ static umode_t tsc2005_attr_is_visible(struct kobject *kobj, | |||
459 | umode_t mode = attr->mode; | 479 | umode_t mode = attr->mode; |
460 | 480 | ||
461 | if (attr == &dev_attr_selftest.attr) { | 481 | if (attr == &dev_attr_selftest.attr) { |
462 | if (!ts->set_reset) | 482 | if (!ts->set_reset && !ts->reset_gpio) |
463 | mode = 0; | 483 | mode = 0; |
464 | } | 484 | } |
465 | 485 | ||
@@ -509,9 +529,9 @@ static void tsc2005_esd_work(struct work_struct *work) | |||
509 | 529 | ||
510 | tsc2005_update_pen_state(ts, 0, 0, 0); | 530 | tsc2005_update_pen_state(ts, 0, 0, 0); |
511 | 531 | ||
512 | ts->set_reset(false); | 532 | tsc2005_set_reset(ts, false); |
513 | usleep_range(100, 500); /* only 10us required */ | 533 | usleep_range(100, 500); /* only 10us required */ |
514 | ts->set_reset(true); | 534 | tsc2005_set_reset(ts, true); |
515 | 535 | ||
516 | enable_irq(ts->spi->irq); | 536 | enable_irq(ts->spi->irq); |
517 | tsc2005_start_scan(ts); | 537 | tsc2005_start_scan(ts); |
@@ -572,29 +592,47 @@ static void tsc2005_setup_spi_xfer(struct tsc2005 *ts) | |||
572 | static int tsc2005_probe(struct spi_device *spi) | 592 | static int tsc2005_probe(struct spi_device *spi) |
573 | { | 593 | { |
574 | const struct tsc2005_platform_data *pdata = dev_get_platdata(&spi->dev); | 594 | const struct tsc2005_platform_data *pdata = dev_get_platdata(&spi->dev); |
595 | struct device_node *np = spi->dev.of_node; | ||
596 | |||
575 | struct tsc2005 *ts; | 597 | struct tsc2005 *ts; |
576 | struct input_dev *input_dev; | 598 | struct input_dev *input_dev; |
577 | unsigned int max_x, max_y, max_p; | 599 | unsigned int max_x = MAX_12BIT; |
578 | unsigned int fudge_x, fudge_y, fudge_p; | 600 | unsigned int max_y = MAX_12BIT; |
601 | unsigned int max_p = MAX_12BIT; | ||
602 | unsigned int fudge_x = TSC2005_DEF_X_FUZZ; | ||
603 | unsigned int fudge_y = TSC2005_DEF_Y_FUZZ; | ||
604 | unsigned int fudge_p = TSC2005_DEF_P_FUZZ; | ||
605 | unsigned int x_plate_ohm = TSC2005_DEF_RESISTOR; | ||
606 | unsigned int esd_timeout; | ||
579 | int error; | 607 | int error; |
580 | 608 | ||
581 | if (!pdata) { | 609 | if (!np && !pdata) { |
582 | dev_dbg(&spi->dev, "no platform data\n"); | 610 | dev_err(&spi->dev, "no platform data\n"); |
583 | return -ENODEV; | 611 | return -ENODEV; |
584 | } | 612 | } |
585 | 613 | ||
586 | fudge_x = pdata->ts_x_fudge ? : 4; | ||
587 | fudge_y = pdata->ts_y_fudge ? : 8; | ||
588 | fudge_p = pdata->ts_pressure_fudge ? : 2; | ||
589 | max_x = pdata->ts_x_max ? : MAX_12BIT; | ||
590 | max_y = pdata->ts_y_max ? : MAX_12BIT; | ||
591 | max_p = pdata->ts_pressure_max ? : MAX_12BIT; | ||
592 | |||
593 | if (spi->irq <= 0) { | 614 | if (spi->irq <= 0) { |
594 | dev_dbg(&spi->dev, "no irq\n"); | 615 | dev_err(&spi->dev, "no irq\n"); |
595 | return -ENODEV; | 616 | return -ENODEV; |
596 | } | 617 | } |
597 | 618 | ||
619 | if (pdata) { | ||
620 | fudge_x = pdata->ts_x_fudge; | ||
621 | fudge_y = pdata->ts_y_fudge; | ||
622 | fudge_p = pdata->ts_pressure_fudge; | ||
623 | max_x = pdata->ts_x_max; | ||
624 | max_y = pdata->ts_y_max; | ||
625 | max_p = pdata->ts_pressure_max; | ||
626 | x_plate_ohm = pdata->ts_x_plate_ohm; | ||
627 | esd_timeout = pdata->esd_timeout_ms; | ||
628 | } else { | ||
629 | x_plate_ohm = TSC2005_DEF_RESISTOR; | ||
630 | of_property_read_u32(np, "ti,x-plate-ohms", &x_plate_ohm); | ||
631 | esd_timeout = 0; | ||
632 | of_property_read_u32(np, "ti,esd-recovery-timeout-ms", | ||
633 | &esd_timeout); | ||
634 | } | ||
635 | |||
598 | spi->mode = SPI_MODE_0; | 636 | spi->mode = SPI_MODE_0; |
599 | spi->bits_per_word = 8; | 637 | spi->bits_per_word = 8; |
600 | if (!spi->max_speed_hz) | 638 | if (!spi->max_speed_hz) |
@@ -604,19 +642,48 @@ static int tsc2005_probe(struct spi_device *spi) | |||
604 | if (error) | 642 | if (error) |
605 | return error; | 643 | return error; |
606 | 644 | ||
607 | ts = kzalloc(sizeof(*ts), GFP_KERNEL); | 645 | ts = devm_kzalloc(&spi->dev, sizeof(*ts), GFP_KERNEL); |
608 | input_dev = input_allocate_device(); | 646 | if (!ts) |
609 | if (!ts || !input_dev) { | 647 | return -ENOMEM; |
610 | error = -ENOMEM; | 648 | |
611 | goto err_free_mem; | 649 | input_dev = devm_input_allocate_device(&spi->dev); |
612 | } | 650 | if (!input_dev) |
651 | return -ENOMEM; | ||
613 | 652 | ||
614 | ts->spi = spi; | 653 | ts->spi = spi; |
615 | ts->idev = input_dev; | 654 | ts->idev = input_dev; |
616 | 655 | ||
617 | ts->x_plate_ohm = pdata->ts_x_plate_ohm ? : 280; | 656 | ts->x_plate_ohm = x_plate_ohm; |
618 | ts->esd_timeout = pdata->esd_timeout_ms; | 657 | ts->esd_timeout = esd_timeout; |
619 | ts->set_reset = pdata->set_reset; | 658 | |
659 | if (np) { | ||
660 | ts->reset_gpio = of_get_named_gpio(np, "reset-gpios", 0); | ||
661 | if (ts->reset_gpio == -EPROBE_DEFER) | ||
662 | return ts->reset_gpio; | ||
663 | if (ts->reset_gpio < 0) { | ||
664 | dev_err(&spi->dev, "error acquiring reset gpio: %d\n", | ||
665 | ts->reset_gpio); | ||
666 | return ts->reset_gpio; | ||
667 | } | ||
668 | |||
669 | error = devm_gpio_request_one(&spi->dev, ts->reset_gpio, 0, | ||
670 | "reset-gpios"); | ||
671 | if (error) { | ||
672 | dev_err(&spi->dev, "error requesting reset gpio: %d\n", | ||
673 | error); | ||
674 | return error; | ||
675 | } | ||
676 | |||
677 | ts->vio = devm_regulator_get(&spi->dev, "vio"); | ||
678 | if (IS_ERR(ts->vio)) { | ||
679 | error = PTR_ERR(ts->vio); | ||
680 | dev_err(&spi->dev, "vio regulator missing (%d)", error); | ||
681 | return error; | ||
682 | } | ||
683 | } else { | ||
684 | ts->reset_gpio = -1; | ||
685 | ts->set_reset = pdata->set_reset; | ||
686 | } | ||
620 | 687 | ||
621 | mutex_init(&ts->mutex); | 688 | mutex_init(&ts->mutex); |
622 | 689 | ||
@@ -641,6 +708,9 @@ static int tsc2005_probe(struct spi_device *spi) | |||
641 | input_set_abs_params(input_dev, ABS_Y, 0, max_y, fudge_y, 0); | 708 | input_set_abs_params(input_dev, ABS_Y, 0, max_y, fudge_y, 0); |
642 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0); | 709 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0); |
643 | 710 | ||
711 | if (np) | ||
712 | touchscreen_parse_of_params(input_dev); | ||
713 | |||
644 | input_dev->open = tsc2005_open; | 714 | input_dev->open = tsc2005_open; |
645 | input_dev->close = tsc2005_close; | 715 | input_dev->close = tsc2005_close; |
646 | 716 | ||
@@ -649,12 +719,20 @@ static int tsc2005_probe(struct spi_device *spi) | |||
649 | /* Ensure the touchscreen is off */ | 719 | /* Ensure the touchscreen is off */ |
650 | tsc2005_stop_scan(ts); | 720 | tsc2005_stop_scan(ts); |
651 | 721 | ||
652 | error = request_threaded_irq(spi->irq, NULL, tsc2005_irq_thread, | 722 | error = devm_request_threaded_irq(&spi->dev, spi->irq, NULL, |
653 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | 723 | tsc2005_irq_thread, |
654 | "tsc2005", ts); | 724 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, |
725 | "tsc2005", ts); | ||
655 | if (error) { | 726 | if (error) { |
656 | dev_err(&spi->dev, "Failed to request irq, err: %d\n", error); | 727 | dev_err(&spi->dev, "Failed to request irq, err: %d\n", error); |
657 | goto err_free_mem; | 728 | return error; |
729 | } | ||
730 | |||
731 | /* enable regulator for DT */ | ||
732 | if (ts->vio) { | ||
733 | error = regulator_enable(ts->vio); | ||
734 | if (error) | ||
735 | return error; | ||
658 | } | 736 | } |
659 | 737 | ||
660 | spi_set_drvdata(spi, ts); | 738 | spi_set_drvdata(spi, ts); |
@@ -662,7 +740,7 @@ static int tsc2005_probe(struct spi_device *spi) | |||
662 | if (error) { | 740 | if (error) { |
663 | dev_err(&spi->dev, | 741 | dev_err(&spi->dev, |
664 | "Failed to create sysfs attributes, err: %d\n", error); | 742 | "Failed to create sysfs attributes, err: %d\n", error); |
665 | goto err_clear_drvdata; | 743 | goto disable_regulator; |
666 | } | 744 | } |
667 | 745 | ||
668 | error = input_register_device(ts->idev); | 746 | error = input_register_device(ts->idev); |
@@ -677,11 +755,9 @@ static int tsc2005_probe(struct spi_device *spi) | |||
677 | 755 | ||
678 | err_remove_sysfs: | 756 | err_remove_sysfs: |
679 | sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group); | 757 | sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group); |
680 | err_clear_drvdata: | 758 | disable_regulator: |
681 | free_irq(spi->irq, ts); | 759 | if (ts->vio) |
682 | err_free_mem: | 760 | regulator_disable(ts->vio); |
683 | input_free_device(input_dev); | ||
684 | kfree(ts); | ||
685 | return error; | 761 | return error; |
686 | } | 762 | } |
687 | 763 | ||
@@ -689,11 +765,10 @@ static int tsc2005_remove(struct spi_device *spi) | |||
689 | { | 765 | { |
690 | struct tsc2005 *ts = spi_get_drvdata(spi); | 766 | struct tsc2005 *ts = spi_get_drvdata(spi); |
691 | 767 | ||
692 | sysfs_remove_group(&ts->spi->dev.kobj, &tsc2005_attr_group); | 768 | sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group); |
693 | 769 | ||
694 | free_irq(ts->spi->irq, ts); | 770 | if (ts->vio) |
695 | input_unregister_device(ts->idev); | 771 | regulator_disable(ts->vio); |
696 | kfree(ts); | ||
697 | 772 | ||
698 | return 0; | 773 | return 0; |
699 | } | 774 | } |