diff options
Diffstat (limited to 'drivers/input/touchscreen/ads7846.c')
-rw-r--r-- | drivers/input/touchscreen/ads7846.c | 73 |
1 files changed, 55 insertions, 18 deletions
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 09c810999b92..532279cda0e4 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
@@ -27,15 +27,16 @@ | |||
27 | #include <linux/gpio.h> | 27 | #include <linux/gpio.h> |
28 | #include <linux/spi/spi.h> | 28 | #include <linux/spi/spi.h> |
29 | #include <linux/spi/ads7846.h> | 29 | #include <linux/spi/ads7846.h> |
30 | #include <linux/regulator/consumer.h> | ||
30 | #include <asm/irq.h> | 31 | #include <asm/irq.h> |
31 | 32 | ||
32 | |||
33 | /* | 33 | /* |
34 | * This code has been heavily tested on a Nokia 770, and lightly | 34 | * This code has been heavily tested on a Nokia 770, and lightly |
35 | * tested on other ads7846 devices (OSK/Mistral, Lubbock). | 35 | * tested on other ads7846 devices (OSK/Mistral, Lubbock, Spitz). |
36 | * TSC2046 is just newer ads7846 silicon. | 36 | * TSC2046 is just newer ads7846 silicon. |
37 | * Support for ads7843 tested on Atmel at91sam926x-EK. | 37 | * Support for ads7843 tested on Atmel at91sam926x-EK. |
38 | * Support for ads7845 has only been stubbed in. | 38 | * Support for ads7845 has only been stubbed in. |
39 | * Support for Analog Devices AD7873 and AD7843 tested. | ||
39 | * | 40 | * |
40 | * IRQ handling needs a workaround because of a shortcoming in handling | 41 | * IRQ handling needs a workaround because of a shortcoming in handling |
41 | * edge triggered IRQs on some platforms like the OMAP1/2. These | 42 | * edge triggered IRQs on some platforms like the OMAP1/2. These |
@@ -43,7 +44,7 @@ | |||
43 | * have to maintain our own SW IRQ disabled status. This should be | 44 | * have to maintain our own SW IRQ disabled status. This should be |
44 | * removed as soon as the affected platform's IRQ handling is fixed. | 45 | * removed as soon as the affected platform's IRQ handling is fixed. |
45 | * | 46 | * |
46 | * app note sbaa036 talks in more detail about accurate sampling... | 47 | * App note sbaa036 talks in more detail about accurate sampling... |
47 | * that ought to help in situations like LCDs inducing noise (which | 48 | * that ought to help in situations like LCDs inducing noise (which |
48 | * can also be helped by using synch signals) and more generally. | 49 | * can also be helped by using synch signals) and more generally. |
49 | * This driver tries to utilize the measures described in the app | 50 | * This driver tries to utilize the measures described in the app |
@@ -86,6 +87,7 @@ struct ads7846 { | |||
86 | char name[32]; | 87 | char name[32]; |
87 | 88 | ||
88 | struct spi_device *spi; | 89 | struct spi_device *spi; |
90 | struct regulator *reg; | ||
89 | 91 | ||
90 | #if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE) | 92 | #if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE) |
91 | struct attribute_group *attr_group; | 93 | struct attribute_group *attr_group; |
@@ -566,10 +568,8 @@ static void ads7846_rx(void *ads) | |||
566 | * once more the measurement | 568 | * once more the measurement |
567 | */ | 569 | */ |
568 | if (packet->tc.ignore || Rt > ts->pressure_max) { | 570 | if (packet->tc.ignore || Rt > ts->pressure_max) { |
569 | #ifdef VERBOSE | 571 | dev_vdbg(&ts->spi->dev, "ignored %d pressure %d\n", |
570 | pr_debug("%s: ignored %d pressure %d\n", | 572 | packet->tc.ignore, Rt); |
571 | dev_name(&ts->spi->dev), packet->tc.ignore, Rt); | ||
572 | #endif | ||
573 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), | 573 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), |
574 | HRTIMER_MODE_REL); | 574 | HRTIMER_MODE_REL); |
575 | return; | 575 | return; |
@@ -598,9 +598,7 @@ static void ads7846_rx(void *ads) | |||
598 | if (!ts->pendown) { | 598 | if (!ts->pendown) { |
599 | input_report_key(input, BTN_TOUCH, 1); | 599 | input_report_key(input, BTN_TOUCH, 1); |
600 | ts->pendown = 1; | 600 | ts->pendown = 1; |
601 | #ifdef VERBOSE | 601 | dev_vdbg(&ts->spi->dev, "DOWN\n"); |
602 | dev_dbg(&ts->spi->dev, "DOWN\n"); | ||
603 | #endif | ||
604 | } | 602 | } |
605 | 603 | ||
606 | if (ts->swap_xy) | 604 | if (ts->swap_xy) |
@@ -608,12 +606,10 @@ static void ads7846_rx(void *ads) | |||
608 | 606 | ||
609 | input_report_abs(input, ABS_X, x); | 607 | input_report_abs(input, ABS_X, x); |
610 | input_report_abs(input, ABS_Y, y); | 608 | input_report_abs(input, ABS_Y, y); |
611 | input_report_abs(input, ABS_PRESSURE, Rt); | 609 | input_report_abs(input, ABS_PRESSURE, ts->pressure_max - Rt); |
612 | 610 | ||
613 | input_sync(input); | 611 | input_sync(input); |
614 | #ifdef VERBOSE | 612 | dev_vdbg(&ts->spi->dev, "%4d/%4d/%4d\n", x, y, Rt); |
615 | dev_dbg(&ts->spi->dev, "%4d/%4d/%4d\n", x, y, Rt); | ||
616 | #endif | ||
617 | } | 613 | } |
618 | 614 | ||
619 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), | 615 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), |
@@ -723,9 +719,7 @@ static enum hrtimer_restart ads7846_timer(struct hrtimer *handle) | |||
723 | input_sync(input); | 719 | input_sync(input); |
724 | 720 | ||
725 | ts->pendown = 0; | 721 | ts->pendown = 0; |
726 | #ifdef VERBOSE | 722 | dev_vdbg(&ts->spi->dev, "UP\n"); |
727 | dev_dbg(&ts->spi->dev, "UP\n"); | ||
728 | #endif | ||
729 | } | 723 | } |
730 | 724 | ||
731 | /* measurement cycle ended */ | 725 | /* measurement cycle ended */ |
@@ -797,6 +791,8 @@ static void ads7846_disable(struct ads7846 *ts) | |||
797 | } | 791 | } |
798 | } | 792 | } |
799 | 793 | ||
794 | regulator_disable(ts->reg); | ||
795 | |||
800 | /* we know the chip's in lowpower mode since we always | 796 | /* we know the chip's in lowpower mode since we always |
801 | * leave it that way after every request | 797 | * leave it that way after every request |
802 | */ | 798 | */ |
@@ -808,6 +804,8 @@ static void ads7846_enable(struct ads7846 *ts) | |||
808 | if (!ts->disabled) | 804 | if (!ts->disabled) |
809 | return; | 805 | return; |
810 | 806 | ||
807 | regulator_enable(ts->reg); | ||
808 | |||
811 | ts->disabled = 0; | 809 | ts->disabled = 0; |
812 | ts->irq_disabled = 0; | 810 | ts->irq_disabled = 0; |
813 | enable_irq(ts->spi->irq); | 811 | enable_irq(ts->spi->irq); |
@@ -824,6 +822,9 @@ static int ads7846_suspend(struct spi_device *spi, pm_message_t message) | |||
824 | 822 | ||
825 | spin_unlock_irq(&ts->lock); | 823 | spin_unlock_irq(&ts->lock); |
826 | 824 | ||
825 | if (device_may_wakeup(&ts->spi->dev)) | ||
826 | enable_irq_wake(ts->spi->irq); | ||
827 | |||
827 | return 0; | 828 | return 0; |
828 | 829 | ||
829 | } | 830 | } |
@@ -832,6 +833,9 @@ static int ads7846_resume(struct spi_device *spi) | |||
832 | { | 833 | { |
833 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | 834 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); |
834 | 835 | ||
836 | if (device_may_wakeup(&ts->spi->dev)) | ||
837 | disable_irq_wake(ts->spi->irq); | ||
838 | |||
835 | spin_lock_irq(&ts->lock); | 839 | spin_lock_irq(&ts->lock); |
836 | 840 | ||
837 | ts->is_suspended = 0; | 841 | ts->is_suspended = 0; |
@@ -987,6 +991,15 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
987 | 991 | ||
988 | vref = pdata->keep_vref_on; | 992 | vref = pdata->keep_vref_on; |
989 | 993 | ||
994 | if (ts->model == 7873) { | ||
995 | /* The AD7873 is almost identical to the ADS7846 | ||
996 | * keep VREF off during differential/ratiometric | ||
997 | * conversion modes | ||
998 | */ | ||
999 | ts->model = 7846; | ||
1000 | vref = 0; | ||
1001 | } | ||
1002 | |||
990 | /* set up the transfers to read touchscreen state; this assumes we | 1003 | /* set up the transfers to read touchscreen state; this assumes we |
991 | * use formula #2 for pressure, not #3. | 1004 | * use formula #2 for pressure, not #3. |
992 | */ | 1005 | */ |
@@ -1148,6 +1161,19 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1148 | 1161 | ||
1149 | ts->last_msg = m; | 1162 | ts->last_msg = m; |
1150 | 1163 | ||
1164 | ts->reg = regulator_get(&spi->dev, "vcc"); | ||
1165 | if (IS_ERR(ts->reg)) { | ||
1166 | dev_err(&spi->dev, "unable to get regulator: %ld\n", | ||
1167 | PTR_ERR(ts->reg)); | ||
1168 | goto err_free_gpio; | ||
1169 | } | ||
1170 | |||
1171 | err = regulator_enable(ts->reg); | ||
1172 | if (err) { | ||
1173 | dev_err(&spi->dev, "unable to enable regulator: %d\n", err); | ||
1174 | goto err_put_regulator; | ||
1175 | } | ||
1176 | |||
1151 | if (request_irq(spi->irq, ads7846_irq, IRQF_TRIGGER_FALLING, | 1177 | if (request_irq(spi->irq, ads7846_irq, IRQF_TRIGGER_FALLING, |
1152 | spi->dev.driver->name, ts)) { | 1178 | spi->dev.driver->name, ts)) { |
1153 | dev_info(&spi->dev, | 1179 | dev_info(&spi->dev, |
@@ -1157,7 +1183,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1157 | spi->dev.driver->name, ts); | 1183 | spi->dev.driver->name, ts); |
1158 | if (err) { | 1184 | if (err) { |
1159 | dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); | 1185 | dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); |
1160 | goto err_free_gpio; | 1186 | goto err_disable_regulator; |
1161 | } | 1187 | } |
1162 | } | 1188 | } |
1163 | 1189 | ||
@@ -1181,6 +1207,8 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1181 | if (err) | 1207 | if (err) |
1182 | goto err_remove_attr_group; | 1208 | goto err_remove_attr_group; |
1183 | 1209 | ||
1210 | device_init_wakeup(&spi->dev, pdata->wakeup); | ||
1211 | |||
1184 | return 0; | 1212 | return 0; |
1185 | 1213 | ||
1186 | err_remove_attr_group: | 1214 | err_remove_attr_group: |
@@ -1189,6 +1217,10 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1189 | ads784x_hwmon_unregister(spi, ts); | 1217 | ads784x_hwmon_unregister(spi, ts); |
1190 | err_free_irq: | 1218 | err_free_irq: |
1191 | free_irq(spi->irq, ts); | 1219 | free_irq(spi->irq, ts); |
1220 | err_disable_regulator: | ||
1221 | regulator_disable(ts->reg); | ||
1222 | err_put_regulator: | ||
1223 | regulator_put(ts->reg); | ||
1192 | err_free_gpio: | 1224 | err_free_gpio: |
1193 | if (ts->gpio_pendown != -1) | 1225 | if (ts->gpio_pendown != -1) |
1194 | gpio_free(ts->gpio_pendown); | 1226 | gpio_free(ts->gpio_pendown); |
@@ -1206,6 +1238,8 @@ static int __devexit ads7846_remove(struct spi_device *spi) | |||
1206 | { | 1238 | { |
1207 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | 1239 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); |
1208 | 1240 | ||
1241 | device_init_wakeup(&spi->dev, false); | ||
1242 | |||
1209 | ads784x_hwmon_unregister(spi, ts); | 1243 | ads784x_hwmon_unregister(spi, ts); |
1210 | input_unregister_device(ts->input); | 1244 | input_unregister_device(ts->input); |
1211 | 1245 | ||
@@ -1217,6 +1251,9 @@ static int __devexit ads7846_remove(struct spi_device *spi) | |||
1217 | /* suspend left the IRQ disabled */ | 1251 | /* suspend left the IRQ disabled */ |
1218 | enable_irq(ts->spi->irq); | 1252 | enable_irq(ts->spi->irq); |
1219 | 1253 | ||
1254 | regulator_disable(ts->reg); | ||
1255 | regulator_put(ts->reg); | ||
1256 | |||
1220 | if (ts->gpio_pendown != -1) | 1257 | if (ts->gpio_pendown != -1) |
1221 | gpio_free(ts->gpio_pendown); | 1258 | gpio_free(ts->gpio_pendown); |
1222 | 1259 | ||