aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-09-18 12:22:36 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-18 12:22:36 -0400
commit6f130478e24d810078c3f0ee292bcc4ec034dcce (patch)
tree1c782ccceaf998e9e23862094588c125ee6f38af /drivers/input
parent6f128fa344833bf8bf076a51d14401661c146470 (diff)
parent75f2ba8f0006440e720e47ae14c917e07c452d72 (diff)
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: (55 commits) regulator: Voltage count for AB3100 mfd: Convert WM8350 to use request_threaded_irq() mfd: Update MAINTAINERS patterns for WM831x mfd: Fix twl4030-power warnings regulator: AB3100 support rtc: AB3100 RTC support mfd: Fix ab3100-otp build failure mfd: OMAP: Board-specifc twl4030 DPS scripts for RX51 board mfd: Print warning for twl4030 out-of-order script loading mfd: Add support for TWL4030/5030 dynamic power switching mfd: AB3100 OTP readout regulator: Add Freescale MC13783 driver mfd: Add Freescale MC13783 driver mfd: AB3100 disable irq nosync mfd: AB3100 alter default setting mfd: AB3100 propagate error mfd: AB3100 accessor function cleanups rtc: Add support for RTCs on Wolfson WM831x devices regulator: get pcap data from the parent device input: PCAP2 misc input driver ...
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/misc/Kconfig20
-rw-r--r--drivers/input/misc/Makefile3
-rw-r--r--drivers/input/misc/pcap_keys.c144
-rw-r--r--drivers/input/misc/wm831x-on.c163
-rw-r--r--drivers/input/touchscreen/Kconfig9
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/pcap_ts.c271
7 files changed, 611 insertions, 0 deletions
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index cbe21bc96b5..1a50be379cb 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -279,4 +279,24 @@ config INPUT_BFIN_ROTARY
279 To compile this driver as a module, choose M here: the 279 To compile this driver as a module, choose M here: the
280 module will be called bfin-rotary. 280 module will be called bfin-rotary.
281 281
282config INPUT_WM831X_ON
283 tristate "WM831X ON pin"
284 depends on MFD_WM831X
285 help
286 Support the ON pin of WM831X PMICs as an input device
287 reporting power button status.
288
289 To compile this driver as a module, choose M here: the module
290 will be called wm831x_on.
291
292config INPUT_PCAP
293 tristate "Motorola EZX PCAP misc input events"
294 depends on EZX_PCAP
295 help
296 Say Y here if you want to use Power key and Headphone button
297 on Motorola EZX phones.
298
299 To compile this driver as a module, choose M here: the
300 module will be called pcap_keys.
301
282endif 302endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 79c1e9a5ea3..bf4db626c31 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
16obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o 16obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o
17obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o 17obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o
18obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o 18obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
19obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o
19obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o 20obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o
20obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o 21obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
21obj-$(CONFIG_INPUT_POWERMATE) += powermate.o 22obj-$(CONFIG_INPUT_POWERMATE) += powermate.o
@@ -26,4 +27,6 @@ obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
26obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o 27obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o
27obj-$(CONFIG_INPUT_UINPUT) += uinput.o 28obj-$(CONFIG_INPUT_UINPUT) += uinput.o
28obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o 29obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o
30obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
29obj-$(CONFIG_INPUT_YEALINK) += yealink.o 31obj-$(CONFIG_INPUT_YEALINK) += yealink.o
32
diff --git a/drivers/input/misc/pcap_keys.c b/drivers/input/misc/pcap_keys.c
new file mode 100644
index 00000000000..7ea969347ca
--- /dev/null
+++ b/drivers/input/misc/pcap_keys.c
@@ -0,0 +1,144 @@
1/*
2 * Input driver for PCAP events:
3 * * Power key
4 * * Headphone button
5 *
6 * Copyright (c) 2008,2009 Ilya Petrov <ilya.muromec@gmail.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/interrupt.h>
17#include <linux/platform_device.h>
18#include <linux/input.h>
19#include <linux/mfd/ezx-pcap.h>
20
21struct pcap_keys {
22 struct pcap_chip *pcap;
23 struct input_dev *input;
24};
25
26/* PCAP2 interrupts us on keypress */
27static irqreturn_t pcap_keys_handler(int irq, void *_pcap_keys)
28{
29 struct pcap_keys *pcap_keys = _pcap_keys;
30 int pirq = irq_to_pcap(pcap_keys->pcap, irq);
31 u32 pstat;
32
33 ezx_pcap_read(pcap_keys->pcap, PCAP_REG_PSTAT, &pstat);
34 pstat &= 1 << pirq;
35
36 switch (pirq) {
37 case PCAP_IRQ_ONOFF:
38 input_report_key(pcap_keys->input, KEY_POWER, !pstat);
39 break;
40 case PCAP_IRQ_MIC:
41 input_report_key(pcap_keys->input, KEY_HP, !pstat);
42 break;
43 }
44
45 input_sync(pcap_keys->input);
46
47 return IRQ_HANDLED;
48}
49
50static int __devinit pcap_keys_probe(struct platform_device *pdev)
51{
52 int err = -ENOMEM;
53 struct pcap_keys *pcap_keys;
54 struct input_dev *input_dev;
55
56 pcap_keys = kmalloc(sizeof(struct pcap_keys), GFP_KERNEL);
57 if (!pcap_keys)
58 return err;
59
60 pcap_keys->pcap = dev_get_drvdata(pdev->dev.parent);
61
62 input_dev = input_allocate_device();
63 if (!input_dev)
64 goto fail;
65
66 pcap_keys->input = input_dev;
67
68 platform_set_drvdata(pdev, pcap_keys);
69 input_dev->name = pdev->name;
70 input_dev->phys = "pcap-keys/input0";
71 input_dev->id.bustype = BUS_HOST;
72 input_dev->dev.parent = &pdev->dev;
73
74 __set_bit(EV_KEY, input_dev->evbit);
75 __set_bit(KEY_POWER, input_dev->keybit);
76 __set_bit(KEY_HP, input_dev->keybit);
77
78 err = input_register_device(input_dev);
79 if (err)
80 goto fail_allocate;
81
82 err = request_irq(pcap_to_irq(pcap_keys->pcap, PCAP_IRQ_ONOFF),
83 pcap_keys_handler, 0, "Power key", pcap_keys);
84 if (err)
85 goto fail_register;
86
87 err = request_irq(pcap_to_irq(pcap_keys->pcap, PCAP_IRQ_MIC),
88 pcap_keys_handler, 0, "Headphone button", pcap_keys);
89 if (err)
90 goto fail_pwrkey;
91
92 return 0;
93
94fail_pwrkey:
95 free_irq(pcap_to_irq(pcap_keys->pcap, PCAP_IRQ_ONOFF), pcap_keys);
96fail_register:
97 input_unregister_device(input_dev);
98 goto fail;
99fail_allocate:
100 input_free_device(input_dev);
101fail:
102 kfree(pcap_keys);
103 return err;
104}
105
106static int __devexit pcap_keys_remove(struct platform_device *pdev)
107{
108 struct pcap_keys *pcap_keys = platform_get_drvdata(pdev);
109
110 free_irq(pcap_to_irq(pcap_keys->pcap, PCAP_IRQ_ONOFF), pcap_keys);
111 free_irq(pcap_to_irq(pcap_keys->pcap, PCAP_IRQ_MIC), pcap_keys);
112
113 input_unregister_device(pcap_keys->input);
114 kfree(pcap_keys);
115
116 return 0;
117}
118
119static struct platform_driver pcap_keys_device_driver = {
120 .probe = pcap_keys_probe,
121 .remove = __devexit_p(pcap_keys_remove),
122 .driver = {
123 .name = "pcap-keys",
124 .owner = THIS_MODULE,
125 }
126};
127
128static int __init pcap_keys_init(void)
129{
130 return platform_driver_register(&pcap_keys_device_driver);
131};
132
133static void __exit pcap_keys_exit(void)
134{
135 platform_driver_unregister(&pcap_keys_device_driver);
136};
137
138module_init(pcap_keys_init);
139module_exit(pcap_keys_exit);
140
141MODULE_DESCRIPTION("Motorola PCAP2 input events driver");
142MODULE_AUTHOR("Ilya Petrov <ilya.muromec@gmail.com>");
143MODULE_LICENSE("GPL");
144MODULE_ALIAS("platform:pcap_keys");
diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c
new file mode 100644
index 00000000000..ba4f5dd7c60
--- /dev/null
+++ b/drivers/input/misc/wm831x-on.c
@@ -0,0 +1,163 @@
1/**
2 * wm831x-on.c - WM831X ON pin driver
3 *
4 * Copyright (C) 2009 Wolfson Microelectronics plc
5 *
6 * This file is subject to the terms and conditions of the GNU General
7 * Public License. See the file "COPYING" in the main directory of this
8 * archive for more details.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include <linux/module.h>
21#include <linux/init.h>
22#include <linux/kernel.h>
23#include <linux/errno.h>
24#include <linux/input.h>
25#include <linux/interrupt.h>
26#include <linux/platform_device.h>
27#include <linux/workqueue.h>
28#include <linux/mfd/wm831x/core.h>
29
30struct wm831x_on {
31 struct input_dev *dev;
32 struct delayed_work work;
33 struct wm831x *wm831x;
34};
35
36/*
37 * The chip gives us an interrupt when the ON pin is asserted but we
38 * then need to poll to see when the pin is deasserted.
39 */
40static void wm831x_poll_on(struct work_struct *work)
41{
42 struct wm831x_on *wm831x_on = container_of(work, struct wm831x_on,
43 work.work);
44 struct wm831x *wm831x = wm831x_on->wm831x;
45 int poll, ret;
46
47 ret = wm831x_reg_read(wm831x, WM831X_ON_PIN_CONTROL);
48 if (ret >= 0) {
49 poll = !(ret & WM831X_ON_PIN_STS);
50
51 input_report_key(wm831x_on->dev, KEY_POWER, poll);
52 input_sync(wm831x_on->dev);
53 } else {
54 dev_err(wm831x->dev, "Failed to read ON status: %d\n", ret);
55 poll = 1;
56 }
57
58 if (poll)
59 schedule_delayed_work(&wm831x_on->work, 100);
60}
61
62static irqreturn_t wm831x_on_irq(int irq, void *data)
63{
64 struct wm831x_on *wm831x_on = data;
65
66 schedule_delayed_work(&wm831x_on->work, 0);
67
68 return IRQ_HANDLED;
69}
70
71static int __devinit wm831x_on_probe(struct platform_device *pdev)
72{
73 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
74 struct wm831x_on *wm831x_on;
75 int irq = platform_get_irq(pdev, 0);
76 int ret;
77
78 wm831x_on = kzalloc(sizeof(struct wm831x_on), GFP_KERNEL);
79 if (!wm831x_on) {
80 dev_err(&pdev->dev, "Can't allocate data\n");
81 return -ENOMEM;
82 }
83
84 wm831x_on->wm831x = wm831x;
85 INIT_DELAYED_WORK(&wm831x_on->work, wm831x_poll_on);
86
87 wm831x_on->dev = input_allocate_device();
88 if (!wm831x_on->dev) {
89 dev_err(&pdev->dev, "Can't allocate input dev\n");
90 ret = -ENOMEM;
91 goto err;
92 }
93
94 wm831x_on->dev->evbit[0] = BIT_MASK(EV_KEY);
95 wm831x_on->dev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER);
96 wm831x_on->dev->name = "wm831x_on";
97 wm831x_on->dev->phys = "wm831x_on/input0";
98 wm831x_on->dev->dev.parent = &pdev->dev;
99
100 ret = wm831x_request_irq(wm831x, irq, wm831x_on_irq,
101 IRQF_TRIGGER_RISING, "wm831x_on", wm831x_on);
102 if (ret < 0) {
103 dev_err(&pdev->dev, "Unable to request IRQ: %d\n", ret);
104 goto err_input_dev;
105 }
106 ret = input_register_device(wm831x_on->dev);
107 if (ret) {
108 dev_dbg(&pdev->dev, "Can't register input device: %d\n", ret);
109 goto err_irq;
110 }
111
112 platform_set_drvdata(pdev, wm831x_on);
113
114 return 0;
115
116err_irq:
117 wm831x_free_irq(wm831x, irq, NULL);
118err_input_dev:
119 input_free_device(wm831x_on->dev);
120err:
121 kfree(wm831x_on);
122 return ret;
123}
124
125static int __devexit wm831x_on_remove(struct platform_device *pdev)
126{
127 struct wm831x_on *wm831x_on = platform_get_drvdata(pdev);
128 int irq = platform_get_irq(pdev, 0);
129
130 wm831x_free_irq(wm831x_on->wm831x, irq, wm831x_on);
131 cancel_delayed_work_sync(&wm831x_on->work);
132 input_unregister_device(wm831x_on->dev);
133 kfree(wm831x_on);
134
135 return 0;
136}
137
138static struct platform_driver wm831x_on_driver = {
139 .probe = wm831x_on_probe,
140 .remove = __devexit_p(wm831x_on_remove),
141 .driver = {
142 .name = "wm831x-on",
143 .owner = THIS_MODULE,
144 },
145};
146
147static int __init wm831x_on_init(void)
148{
149 return platform_driver_register(&wm831x_on_driver);
150}
151module_init(wm831x_on_init);
152
153static void __exit wm831x_on_exit(void)
154{
155 platform_driver_unregister(&wm831x_on_driver);
156}
157module_exit(wm831x_on_exit);
158
159MODULE_ALIAS("platform:wm831x-on");
160MODULE_DESCRIPTION("WM831x ON pin");
161MODULE_LICENSE("GPL");
162MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
163
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 87a1ae63bcc..ab02d72afbf 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -510,4 +510,13 @@ config TOUCHSCREEN_W90X900
510 To compile this driver as a module, choose M here: the 510 To compile this driver as a module, choose M here: the
511 module will be called w90p910_ts. 511 module will be called w90p910_ts.
512 512
513config TOUCHSCREEN_PCAP
514 tristate "Motorola PCAP touchscreen"
515 depends on EZX_PCAP
516 help
517 Say Y here if you have a Motorola EZX telephone and
518 want to enable support for the built-in touchscreen.
519
520 To compile this driver as a module, choose M here: the
521 module will be called pcap_ts.
513endif 522endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 3e1c5e0b952..4599bf7ad81 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -40,3 +40,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o
40obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o 40obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
41obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o 41obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
42obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o 42obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
43obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o
diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c
new file mode 100644
index 00000000000..67fcd33595d
--- /dev/null
+++ b/drivers/input/touchscreen/pcap_ts.c
@@ -0,0 +1,271 @@
1/*
2 * Driver for Motorola PCAP2 touchscreen as found in the EZX phone platform.
3 *
4 * Copyright (C) 2006 Harald Welte <laforge@openezx.org>
5 * Copyright (C) 2009 Daniel Ribeiro <drwyrm@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 */
12
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/fs.h>
16#include <linux/string.h>
17#include <linux/pm.h>
18#include <linux/timer.h>
19#include <linux/interrupt.h>
20#include <linux/platform_device.h>
21#include <linux/input.h>
22#include <linux/mfd/ezx-pcap.h>
23
24struct pcap_ts {
25 struct pcap_chip *pcap;
26 struct input_dev *input;
27 struct delayed_work work;
28 u16 x, y;
29 u16 pressure;
30 u8 read_state;
31};
32
33#define SAMPLE_DELAY 20 /* msecs */
34
35#define X_AXIS_MIN 0
36#define X_AXIS_MAX 1023
37#define Y_AXIS_MAX X_AXIS_MAX
38#define Y_AXIS_MIN X_AXIS_MIN
39#define PRESSURE_MAX X_AXIS_MAX
40#define PRESSURE_MIN X_AXIS_MIN
41
42static void pcap_ts_read_xy(void *data, u16 res[2])
43{
44 struct pcap_ts *pcap_ts = data;
45
46 switch (pcap_ts->read_state) {
47 case PCAP_ADC_TS_M_PRESSURE:
48 /* pressure reading is unreliable */
49 if (res[0] > PRESSURE_MIN && res[0] < PRESSURE_MAX)
50 pcap_ts->pressure = res[0];
51 pcap_ts->read_state = PCAP_ADC_TS_M_XY;
52 schedule_delayed_work(&pcap_ts->work, 0);
53 break;
54 case PCAP_ADC_TS_M_XY:
55 pcap_ts->y = res[0];
56 pcap_ts->x = res[1];
57 if (pcap_ts->x <= X_AXIS_MIN || pcap_ts->x >= X_AXIS_MAX ||
58 pcap_ts->y <= Y_AXIS_MIN || pcap_ts->y >= Y_AXIS_MAX) {
59 /* pen has been released */
60 input_report_abs(pcap_ts->input, ABS_PRESSURE, 0);
61 input_report_key(pcap_ts->input, BTN_TOUCH, 0);
62
63 pcap_ts->read_state = PCAP_ADC_TS_M_STANDBY;
64 schedule_delayed_work(&pcap_ts->work, 0);
65 } else {
66 /* pen is touching the screen */
67 input_report_abs(pcap_ts->input, ABS_X, pcap_ts->x);
68 input_report_abs(pcap_ts->input, ABS_Y, pcap_ts->y);
69 input_report_key(pcap_ts->input, BTN_TOUCH, 1);
70 input_report_abs(pcap_ts->input, ABS_PRESSURE,
71 pcap_ts->pressure);
72
73 /* switch back to pressure read mode */
74 pcap_ts->read_state = PCAP_ADC_TS_M_PRESSURE;
75 schedule_delayed_work(&pcap_ts->work,
76 msecs_to_jiffies(SAMPLE_DELAY));
77 }
78 input_sync(pcap_ts->input);
79 break;
80 default:
81 dev_warn(&pcap_ts->input->dev,
82 "pcap_ts: Warning, unhandled read_state %d\n",
83 pcap_ts->read_state);
84 break;
85 }
86}
87
88static void pcap_ts_work(struct work_struct *work)
89{
90 struct delayed_work *dw = container_of(work, struct delayed_work, work);
91 struct pcap_ts *pcap_ts = container_of(dw, struct pcap_ts, work);
92 u8 ch[2];
93
94 pcap_set_ts_bits(pcap_ts->pcap,
95 pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT);
96
97 if (pcap_ts->read_state == PCAP_ADC_TS_M_STANDBY)
98 return;
99
100 /* start adc conversion */
101 ch[0] = PCAP_ADC_CH_TS_X1;
102 ch[1] = PCAP_ADC_CH_TS_Y1;
103 pcap_adc_async(pcap_ts->pcap, PCAP_ADC_BANK_1, 0, ch,
104 pcap_ts_read_xy, pcap_ts);
105}
106
107static irqreturn_t pcap_ts_event_touch(int pirq, void *data)
108{
109 struct pcap_ts *pcap_ts = data;
110
111 if (pcap_ts->read_state == PCAP_ADC_TS_M_STANDBY) {
112 pcap_ts->read_state = PCAP_ADC_TS_M_PRESSURE;
113 schedule_delayed_work(&pcap_ts->work, 0);
114 }
115 return IRQ_HANDLED;
116}
117
118static int pcap_ts_open(struct input_dev *dev)
119{
120 struct pcap_ts *pcap_ts = input_get_drvdata(dev);
121
122 pcap_ts->read_state = PCAP_ADC_TS_M_STANDBY;
123 schedule_delayed_work(&pcap_ts->work, 0);
124
125 return 0;
126}
127
128static void pcap_ts_close(struct input_dev *dev)
129{
130 struct pcap_ts *pcap_ts = input_get_drvdata(dev);
131
132 cancel_delayed_work_sync(&pcap_ts->work);
133
134 pcap_ts->read_state = PCAP_ADC_TS_M_NONTS;
135 pcap_set_ts_bits(pcap_ts->pcap,
136 pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT);
137}
138
139static int __devinit pcap_ts_probe(struct platform_device *pdev)
140{
141 struct input_dev *input_dev;
142 struct pcap_ts *pcap_ts;
143 int err = -ENOMEM;
144
145 pcap_ts = kzalloc(sizeof(*pcap_ts), GFP_KERNEL);
146 if (!pcap_ts)
147 return err;
148
149 pcap_ts->pcap = dev_get_drvdata(pdev->dev.parent);
150 platform_set_drvdata(pdev, pcap_ts);
151
152 input_dev = input_allocate_device();
153 if (!input_dev)
154 goto fail;
155
156 INIT_DELAYED_WORK(&pcap_ts->work, pcap_ts_work);
157
158 pcap_ts->read_state = PCAP_ADC_TS_M_NONTS;
159 pcap_set_ts_bits(pcap_ts->pcap,
160 pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT);
161
162 pcap_ts->input = input_dev;
163 input_set_drvdata(input_dev, pcap_ts);
164
165 input_dev->name = "pcap-touchscreen";
166 input_dev->phys = "pcap_ts/input0";
167 input_dev->id.bustype = BUS_HOST;
168 input_dev->id.vendor = 0x0001;
169 input_dev->id.product = 0x0002;
170 input_dev->id.version = 0x0100;
171 input_dev->dev.parent = &pdev->dev;
172 input_dev->open = pcap_ts_open;
173 input_dev->close = pcap_ts_close;
174
175 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
176 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
177 input_set_abs_params(input_dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0);
178 input_set_abs_params(input_dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0);
179 input_set_abs_params(input_dev, ABS_PRESSURE, PRESSURE_MIN,
180 PRESSURE_MAX, 0, 0);
181
182 err = input_register_device(pcap_ts->input);
183 if (err)
184 goto fail_allocate;
185
186 err = request_irq(pcap_to_irq(pcap_ts->pcap, PCAP_IRQ_TS),
187 pcap_ts_event_touch, 0, "Touch Screen", pcap_ts);
188 if (err)
189 goto fail_register;
190
191 return 0;
192
193fail_register:
194 input_unregister_device(input_dev);
195 goto fail;
196fail_allocate:
197 input_free_device(input_dev);
198fail:
199 kfree(pcap_ts);
200
201 return err;
202}
203
204static int __devexit pcap_ts_remove(struct platform_device *pdev)
205{
206 struct pcap_ts *pcap_ts = platform_get_drvdata(pdev);
207
208 free_irq(pcap_to_irq(pcap_ts->pcap, PCAP_IRQ_TS), pcap_ts);
209 cancel_delayed_work_sync(&pcap_ts->work);
210
211 input_unregister_device(pcap_ts->input);
212
213 kfree(pcap_ts);
214
215 return 0;
216}
217
218#ifdef CONFIG_PM
219static int pcap_ts_suspend(struct device *dev)
220{
221 struct pcap_ts *pcap_ts = dev_get_drvdata(dev);
222
223 pcap_set_ts_bits(pcap_ts->pcap, PCAP_ADC_TS_REF_LOWPWR);
224 return 0;
225}
226
227static int pcap_ts_resume(struct device *dev)
228{
229 struct pcap_ts *pcap_ts = dev_get_drvdata(dev);
230
231 pcap_set_ts_bits(pcap_ts->pcap,
232 pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT);
233 return 0;
234}
235
236static struct dev_pm_ops pcap_ts_pm_ops = {
237 .suspend = pcap_ts_suspend,
238 .resume = pcap_ts_resume,
239};
240#define PCAP_TS_PM_OPS (&pcap_ts_pm_ops)
241#else
242#define PCAP_TS_PM_OPS NULL
243#endif
244
245static struct platform_driver pcap_ts_driver = {
246 .probe = pcap_ts_probe,
247 .remove = __devexit_p(pcap_ts_remove),
248 .driver = {
249 .name = "pcap-ts",
250 .owner = THIS_MODULE,
251 .pm = PCAP_TS_PM_OPS,
252 },
253};
254
255static int __init pcap_ts_init(void)
256{
257 return platform_driver_register(&pcap_ts_driver);
258}
259
260static void __exit pcap_ts_exit(void)
261{
262 platform_driver_unregister(&pcap_ts_driver);
263}
264
265module_init(pcap_ts_init);
266module_exit(pcap_ts_exit);
267
268MODULE_DESCRIPTION("Motorola PCAP2 touchscreen driver");
269MODULE_AUTHOR("Daniel Ribeiro / Harald Welte");
270MODULE_LICENSE("GPL");
271MODULE_ALIAS("platform:pcap_ts");