Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/input/touchscreen/st1232.c
15111 views
1
/*
2
* ST1232 Touchscreen Controller Driver
3
*
4
* Copyright (C) 2010 Renesas Solutions Corp.
5
* Tony SIM <[email protected]>
6
*
7
* Using code from:
8
* - android.git.kernel.org: projects/kernel/common.git: synaptics_i2c_rmi.c
9
* Copyright (C) 2007 Google, Inc.
10
*
11
* This software is licensed under the terms of the GNU General Public
12
* License version 2, as published by the Free Software Foundation, and
13
* may be copied, distributed, and modified under those terms.
14
*
15
* This program is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
19
*/
20
21
#include <linux/delay.h>
22
#include <linux/i2c.h>
23
#include <linux/input.h>
24
#include <linux/interrupt.h>
25
#include <linux/module.h>
26
#include <linux/slab.h>
27
#include <linux/types.h>
28
29
#define ST1232_TS_NAME "st1232-ts"
30
31
#define MIN_X 0x00
32
#define MIN_Y 0x00
33
#define MAX_X 0x31f /* (800 - 1) */
34
#define MAX_Y 0x1df /* (480 - 1) */
35
#define MAX_AREA 0xff
36
#define MAX_FINGERS 2
37
38
struct st1232_ts_finger {
39
u16 x;
40
u16 y;
41
u8 t;
42
bool is_valid;
43
};
44
45
struct st1232_ts_data {
46
struct i2c_client *client;
47
struct input_dev *input_dev;
48
struct st1232_ts_finger finger[MAX_FINGERS];
49
};
50
51
static int st1232_ts_read_data(struct st1232_ts_data *ts)
52
{
53
struct st1232_ts_finger *finger = ts->finger;
54
struct i2c_client *client = ts->client;
55
struct i2c_msg msg[2];
56
int error;
57
u8 start_reg;
58
u8 buf[10];
59
60
/* read touchscreen data from ST1232 */
61
msg[0].addr = client->addr;
62
msg[0].flags = 0;
63
msg[0].len = 1;
64
msg[0].buf = &start_reg;
65
start_reg = 0x10;
66
67
msg[1].addr = ts->client->addr;
68
msg[1].flags = I2C_M_RD;
69
msg[1].len = sizeof(buf);
70
msg[1].buf = buf;
71
72
error = i2c_transfer(client->adapter, msg, 2);
73
if (error < 0)
74
return error;
75
76
/* get "valid" bits */
77
finger[0].is_valid = buf[2] >> 7;
78
finger[1].is_valid = buf[5] >> 7;
79
80
/* get xy coordinate */
81
if (finger[0].is_valid) {
82
finger[0].x = ((buf[2] & 0x0070) << 4) | buf[3];
83
finger[0].y = ((buf[2] & 0x0007) << 8) | buf[4];
84
finger[0].t = buf[8];
85
}
86
87
if (finger[1].is_valid) {
88
finger[1].x = ((buf[5] & 0x0070) << 4) | buf[6];
89
finger[1].y = ((buf[5] & 0x0007) << 8) | buf[7];
90
finger[1].t = buf[9];
91
}
92
93
return 0;
94
}
95
96
static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id)
97
{
98
struct st1232_ts_data *ts = dev_id;
99
struct st1232_ts_finger *finger = ts->finger;
100
struct input_dev *input_dev = ts->input_dev;
101
int count = 0;
102
int i, ret;
103
104
ret = st1232_ts_read_data(ts);
105
if (ret < 0)
106
goto end;
107
108
/* multi touch protocol */
109
for (i = 0; i < MAX_FINGERS; i++) {
110
if (!finger[i].is_valid)
111
continue;
112
113
input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, finger[i].t);
114
input_report_abs(input_dev, ABS_MT_POSITION_X, finger[i].x);
115
input_report_abs(input_dev, ABS_MT_POSITION_Y, finger[i].y);
116
input_mt_sync(input_dev);
117
count++;
118
}
119
120
/* SYN_MT_REPORT only if no contact */
121
if (!count)
122
input_mt_sync(input_dev);
123
124
/* SYN_REPORT */
125
input_sync(input_dev);
126
127
end:
128
return IRQ_HANDLED;
129
}
130
131
static int __devinit st1232_ts_probe(struct i2c_client *client,
132
const struct i2c_device_id *id)
133
{
134
struct st1232_ts_data *ts;
135
struct input_dev *input_dev;
136
int error;
137
138
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
139
dev_err(&client->dev, "need I2C_FUNC_I2C\n");
140
return -EIO;
141
}
142
143
if (!client->irq) {
144
dev_err(&client->dev, "no IRQ?\n");
145
return -EINVAL;
146
}
147
148
149
ts = kzalloc(sizeof(struct st1232_ts_data), GFP_KERNEL);
150
input_dev = input_allocate_device();
151
if (!ts || !input_dev) {
152
error = -ENOMEM;
153
goto err_free_mem;
154
}
155
156
ts->client = client;
157
ts->input_dev = input_dev;
158
159
input_dev->name = "st1232-touchscreen";
160
input_dev->id.bustype = BUS_I2C;
161
input_dev->dev.parent = &client->dev;
162
163
__set_bit(EV_SYN, input_dev->evbit);
164
__set_bit(EV_KEY, input_dev->evbit);
165
__set_bit(EV_ABS, input_dev->evbit);
166
167
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, MAX_AREA, 0, 0);
168
input_set_abs_params(input_dev, ABS_MT_POSITION_X, MIN_X, MAX_X, 0, 0);
169
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, MIN_Y, MAX_Y, 0, 0);
170
171
error = request_threaded_irq(client->irq, NULL, st1232_ts_irq_handler,
172
IRQF_ONESHOT, client->name, ts);
173
if (error) {
174
dev_err(&client->dev, "Failed to register interrupt\n");
175
goto err_free_mem;
176
}
177
178
error = input_register_device(ts->input_dev);
179
if (error) {
180
dev_err(&client->dev, "Unable to register %s input device\n",
181
input_dev->name);
182
goto err_free_irq;
183
}
184
185
i2c_set_clientdata(client, ts);
186
device_init_wakeup(&client->dev, 1);
187
188
return 0;
189
190
err_free_irq:
191
free_irq(client->irq, ts);
192
err_free_mem:
193
input_free_device(input_dev);
194
kfree(ts);
195
return error;
196
}
197
198
static int __devexit st1232_ts_remove(struct i2c_client *client)
199
{
200
struct st1232_ts_data *ts = i2c_get_clientdata(client);
201
202
device_init_wakeup(&client->dev, 0);
203
free_irq(client->irq, ts);
204
input_unregister_device(ts->input_dev);
205
kfree(ts);
206
207
return 0;
208
}
209
210
#ifdef CONFIG_PM
211
static int st1232_ts_suspend(struct device *dev)
212
{
213
struct i2c_client *client = to_i2c_client(dev);
214
215
if (device_may_wakeup(&client->dev))
216
enable_irq_wake(client->irq);
217
else
218
disable_irq(client->irq);
219
220
return 0;
221
}
222
223
static int st1232_ts_resume(struct device *dev)
224
{
225
struct i2c_client *client = to_i2c_client(dev);
226
227
if (device_may_wakeup(&client->dev))
228
disable_irq_wake(client->irq);
229
else
230
enable_irq(client->irq);
231
232
return 0;
233
}
234
235
static const struct dev_pm_ops st1232_ts_pm_ops = {
236
.suspend = st1232_ts_suspend,
237
.resume = st1232_ts_resume,
238
};
239
#endif
240
241
static const struct i2c_device_id st1232_ts_id[] = {
242
{ ST1232_TS_NAME, 0 },
243
{ }
244
};
245
MODULE_DEVICE_TABLE(i2c, st1232_ts_id);
246
247
static struct i2c_driver st1232_ts_driver = {
248
.probe = st1232_ts_probe,
249
.remove = __devexit_p(st1232_ts_remove),
250
.id_table = st1232_ts_id,
251
.driver = {
252
.name = ST1232_TS_NAME,
253
.owner = THIS_MODULE,
254
#ifdef CONFIG_PM
255
.pm = &st1232_ts_pm_ops,
256
#endif
257
},
258
};
259
260
static int __init st1232_ts_init(void)
261
{
262
return i2c_add_driver(&st1232_ts_driver);
263
}
264
module_init(st1232_ts_init);
265
266
static void __exit st1232_ts_exit(void)
267
{
268
i2c_del_driver(&st1232_ts_driver);
269
}
270
module_exit(st1232_ts_exit);
271
272
MODULE_AUTHOR("Tony SIM <[email protected]>");
273
MODULE_DESCRIPTION("SITRONIX ST1232 Touchscreen Controller Driver");
274
MODULE_LICENSE("GPL");
275
276