aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorChristian Gmeiner <christian.gmeiner@gmail.com>2014-10-08 12:22:54 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2014-10-09 18:27:42 -0400
commitdd4cae8bf16611053ee7b00e20aa4fa945b92b99 (patch)
tree2703e38a67c5b4a3d97cbf57db6cd6544a70d70e /drivers/input
parent3f1fe73b92c4e5cd614f628621048c0c120e2620 (diff)
Input: Add Microchip AR1021 i2c touchscreen
This patch adds support for the ar1021 i2c based touchscreen. The driver is quite simple and only supports the Touch Reporting Protocol. This is the final version for an RFC patch send a while ago. http://www.spinics.net/lists/linux-input/msg29419.html Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/touchscreen/Kconfig12
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/ar1021_i2c.c181
3 files changed, 194 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 6bb9a7dd23b6..e1d8003d01f8 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -90,6 +90,18 @@ config TOUCHSCREEN_AD7879_SPI
90 To compile this driver as a module, choose M here: the 90 To compile this driver as a module, choose M here: the
91 module will be called ad7879-spi. 91 module will be called ad7879-spi.
92 92
93config TOUCHSCREEN_AR1021_I2C
94 tristate "Microchip AR1021 i2c touchscreen"
95 depends on I2C && OF
96 help
97 Say Y here if you have the Microchip AR1021 touchscreen controller
98 chip in your system.
99
100 If unsure, say N.
101
102 To compile this driver as a module, choose M here: the
103 module will be called ar1021_i2c.
104
93config TOUCHSCREEN_ATMEL_MXT 105config TOUCHSCREEN_ATMEL_MXT
94 tristate "Atmel mXT I2C Touchscreen" 106 tristate "Atmel mXT I2C Touchscreen"
95 depends on I2C 107 depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 4be94fce41af..090e61cc9171 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o
13obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C) += ad7879-i2c.o 13obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C) += ad7879-i2c.o
14obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o 14obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o
15obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o 15obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
16obj-$(CONFIG_TOUCHSCREEN_AR1021_I2C) += ar1021_i2c.o
16obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o 17obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o
17obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o 18obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o
18obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o 19obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
diff --git a/drivers/input/touchscreen/ar1021_i2c.c b/drivers/input/touchscreen/ar1021_i2c.c
new file mode 100644
index 000000000000..ba30578e296e
--- /dev/null
+++ b/drivers/input/touchscreen/ar1021_i2c.c
@@ -0,0 +1,181 @@
1/*
2 * Microchip AR1021 driver for I2C
3 *
4 * Author: Christian Gmeiner <christian.gmeiner@gmail.com>
5 *
6 * License: GPLv2 as published by the FSF.
7 */
8
9#include <linux/module.h>
10#include <linux/input.h>
11#include <linux/of.h>
12#include <linux/i2c.h>
13#include <linux/irq.h>
14#include <linux/interrupt.h>
15
16#define AR1021_TOCUH_PKG_SIZE 5
17
18#define AR1021_MAX_X 4095
19#define AR1021_MAX_Y 4095
20
21struct ar1021_i2c {
22 struct i2c_client *client;
23 struct input_dev *input;
24 u8 data[AR1021_TOCUH_PKG_SIZE];
25};
26
27static irqreturn_t ar1021_i2c_irq(int irq, void *dev_id)
28{
29 struct ar1021_i2c *ar1021 = dev_id;
30 struct input_dev *input = ar1021->input;
31 u8 *data = ar1021->data;
32 unsigned int x, y, button;
33 int retval;
34
35 retval = i2c_master_recv(ar1021->client,
36 ar1021->data, sizeof(ar1021->data));
37 if (retval != sizeof(ar1021->data))
38 goto out;
39
40 /* sync bit set ? */
41 if ((data[0] & 0x80) == 0)
42 goto out;
43
44 button = data[0] & BIT(0);
45 x = ((data[2] & 0x1f) << 7) | (data[1] & 0x7f);
46 y = ((data[4] & 0x1f) << 7) | (data[3] & 0x7f);
47
48 input_report_abs(input, ABS_X, x);
49 input_report_abs(input, ABS_Y, y);
50 input_report_key(input, BTN_TOUCH, button);
51 input_sync(input);
52
53out:
54 return IRQ_HANDLED;
55}
56
57static int ar1021_i2c_open(struct input_dev *dev)
58{
59 struct ar1021_i2c *ar1021 = input_get_drvdata(dev);
60 struct i2c_client *client = ar1021->client;
61
62 enable_irq(client->irq);
63
64 return 0;
65}
66
67static void ar1021_i2c_close(struct input_dev *dev)
68{
69 struct ar1021_i2c *ar1021 = input_get_drvdata(dev);
70 struct i2c_client *client = ar1021->client;
71
72 disable_irq(client->irq);
73}
74
75static int ar1021_i2c_probe(struct i2c_client *client,
76 const struct i2c_device_id *id)
77{
78 struct ar1021_i2c *ar1021;
79 struct input_dev *input;
80 int error;
81
82 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
83 dev_err(&client->dev, "i2c_check_functionality error\n");
84 return -ENXIO;
85 }
86
87 ar1021 = devm_kzalloc(&client->dev, sizeof(*ar1021), GFP_KERNEL);
88 if (!ar1021)
89 return -ENOMEM;
90
91 input = devm_input_allocate_device(&client->dev);
92 if (!input)
93 return -ENOMEM;
94
95 ar1021->client = client;
96 ar1021->input = input;
97
98 input->name = "ar1021 I2C Touchscreen";
99 input->id.bustype = BUS_I2C;
100 input->dev.parent = &client->dev;
101 input->open = ar1021_i2c_open;
102 input->close = ar1021_i2c_close;
103
104 input_set_capability(input, EV_KEY, BTN_TOUCH);
105 input_set_abs_params(input, ABS_X, 0, AR1021_MAX_X, 0, 0);
106 input_set_abs_params(input, ABS_Y, 0, AR1021_MAX_Y, 0, 0);
107
108 input_set_drvdata(input, ar1021);
109
110 error = devm_request_threaded_irq(&client->dev, client->irq,
111 NULL, ar1021_i2c_irq,
112 IRQF_TRIGGER_RISING | IRQF_ONESHOT,
113 "ar1021_i2c", ar1021);
114 if (error) {
115 dev_err(&client->dev,
116 "Failed to enable IRQ, error: %d\n", error);
117 return error;
118 }
119
120 /* Disable the IRQ, we'll enable it in ar1021_i2c_open() */
121 disable_irq(client->irq);
122
123 error = input_register_device(ar1021->input);
124 if (error) {
125 dev_err(&client->dev,
126 "Failed to register input device, error: %d\n", error);
127 return error;
128 }
129
130 i2c_set_clientdata(client, ar1021);
131 return 0;
132}
133
134static int __maybe_unused ar1021_i2c_suspend(struct device *dev)
135{
136 struct i2c_client *client = to_i2c_client(dev);
137
138 disable_irq(client->irq);
139
140 return 0;
141}
142
143static int __maybe_unused ar1021_i2c_resume(struct device *dev)
144{
145 struct i2c_client *client = to_i2c_client(dev);
146
147 enable_irq(client->irq);
148
149 return 0;
150}
151
152static SIMPLE_DEV_PM_OPS(ar1021_i2c_pm, ar1021_i2c_suspend, ar1021_i2c_resume);
153
154static const struct i2c_device_id ar1021_i2c_id[] = {
155 { "MICROCHIP_AR1021_I2C", 0 },
156 { },
157};
158MODULE_DEVICE_TABLE(i2c, ar1021_i2c_id);
159
160static struct of_device_id ar1021_i2c_of_match[] = {
161 { .compatible = "microchip,ar1021-i2c", },
162 { }
163};
164MODULE_DEVICE_TABLE(of, ar1021_i2c_of_match);
165
166static struct i2c_driver ar1021_i2c_driver = {
167 .driver = {
168 .name = "ar1021_i2c",
169 .owner = THIS_MODULE,
170 .pm = &ar1021_i2c_pm,
171 .of_match_table = ar1021_i2c_of_match,
172 },
173
174 .probe = ar1021_i2c_probe,
175 .id_table = ar1021_i2c_id,
176};
177module_i2c_driver(ar1021_i2c_driver);
178
179MODULE_AUTHOR("Christian Gmeiner <christian.gmeiner@gmail.com>");
180MODULE_DESCRIPTION("Microchip AR1021 I2C Driver");
181MODULE_LICENSE("GPL");