blob: f2c0ae18e24a1ab54e8de73575901d9643be3541 [file] [log] [blame]
Jianchun Bian36a281e2011-12-30 15:16:21 -08001/*
2 * Driver for Pixcir I2C touchscreen controllers.
3 *
4 * Copyright (C) 2010-2011 Pixcir, Inc.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
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
16 * License along with this library; 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/delay.h>
21#include <linux/module.h>
22#include <linux/interrupt.h>
23#include <linux/slab.h>
24#include <linux/i2c.h>
25#include <linux/input.h>
26#include <linux/input/pixcir_ts.h>
Roger Quadros0dfc8d42014-05-18 22:46:43 -070027#include <linux/gpio.h>
Jianchun Bian36a281e2011-12-30 15:16:21 -080028
29struct pixcir_i2c_ts_data {
30 struct i2c_client *client;
31 struct input_dev *input;
32 const struct pixcir_ts_platform_data *chip;
Roger Quadros3b36fbb2014-05-18 22:44:35 -070033 bool running;
Jianchun Bian36a281e2011-12-30 15:16:21 -080034};
35
36static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data)
37{
38 struct pixcir_i2c_ts_data *tsdata = data;
39 u8 rdbuf[10], wrbuf[1] = { 0 };
40 u8 touch;
41 int ret;
42
43 ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf));
44 if (ret != sizeof(wrbuf)) {
45 dev_err(&tsdata->client->dev,
46 "%s: i2c_master_send failed(), ret=%d\n",
47 __func__, ret);
48 return;
49 }
50
51 ret = i2c_master_recv(tsdata->client, rdbuf, sizeof(rdbuf));
52 if (ret != sizeof(rdbuf)) {
53 dev_err(&tsdata->client->dev,
54 "%s: i2c_master_recv failed(), ret=%d\n",
55 __func__, ret);
56 return;
57 }
58
59 touch = rdbuf[0];
60 if (touch) {
61 u16 posx1 = (rdbuf[3] << 8) | rdbuf[2];
62 u16 posy1 = (rdbuf[5] << 8) | rdbuf[4];
63 u16 posx2 = (rdbuf[7] << 8) | rdbuf[6];
64 u16 posy2 = (rdbuf[9] << 8) | rdbuf[8];
65
66 input_report_key(tsdata->input, BTN_TOUCH, 1);
67 input_report_abs(tsdata->input, ABS_X, posx1);
68 input_report_abs(tsdata->input, ABS_Y, posy1);
69
70 input_report_abs(tsdata->input, ABS_MT_POSITION_X, posx1);
71 input_report_abs(tsdata->input, ABS_MT_POSITION_Y, posy1);
72 input_mt_sync(tsdata->input);
73
74 if (touch == 2) {
75 input_report_abs(tsdata->input,
76 ABS_MT_POSITION_X, posx2);
77 input_report_abs(tsdata->input,
78 ABS_MT_POSITION_Y, posy2);
79 input_mt_sync(tsdata->input);
80 }
81 } else {
82 input_report_key(tsdata->input, BTN_TOUCH, 0);
83 }
84
85 input_sync(tsdata->input);
86}
87
88static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
89{
90 struct pixcir_i2c_ts_data *tsdata = dev_id;
Roger Quadros0dfc8d42014-05-18 22:46:43 -070091 const struct pixcir_ts_platform_data *pdata = tsdata->chip;
Jianchun Bian36a281e2011-12-30 15:16:21 -080092
Roger Quadros3b36fbb2014-05-18 22:44:35 -070093 while (tsdata->running) {
Jianchun Bian36a281e2011-12-30 15:16:21 -080094 pixcir_ts_poscheck(tsdata);
95
Roger Quadros0dfc8d42014-05-18 22:46:43 -070096 if (gpio_get_value(pdata->gpio_attb))
Jianchun Bian36a281e2011-12-30 15:16:21 -080097 break;
98
99 msleep(20);
100 }
101
102 return IRQ_HANDLED;
103}
104
Roger Quadros3b36fbb2014-05-18 22:44:35 -0700105static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
106 enum pixcir_power_mode mode)
107{
108 struct device *dev = &ts->client->dev;
109 int ret;
110
111 ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_POWER_MODE);
112 if (ret < 0) {
113 dev_err(dev, "%s: can't read reg 0x%x : %d\n",
114 __func__, PIXCIR_REG_POWER_MODE, ret);
115 return ret;
116 }
117
118 ret &= ~PIXCIR_POWER_MODE_MASK;
119 ret |= mode;
120
121 /* Always AUTO_IDLE */
122 ret |= PIXCIR_POWER_ALLOW_IDLE;
123
124 ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_POWER_MODE, ret);
125 if (ret < 0) {
126 dev_err(dev, "%s: can't write reg 0x%x : %d\n",
127 __func__, PIXCIR_REG_POWER_MODE, ret);
128 return ret;
129 }
130
131 return 0;
132}
133
134/*
135 * Set the interrupt mode for the device i.e. ATTB line behaviour
136 *
137 * @polarity : 1 for active high, 0 for active low.
138 */
139static int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts,
140 enum pixcir_int_mode mode, bool polarity)
141{
142 struct device *dev = &ts->client->dev;
143 int ret;
144
145 ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
146 if (ret < 0) {
147 dev_err(dev, "%s: can't read reg 0x%x : %d\n",
148 __func__, PIXCIR_REG_INT_MODE, ret);
149 return ret;
150 }
151
152 ret &= ~PIXCIR_INT_MODE_MASK;
153 ret |= mode;
154
155 if (polarity)
156 ret |= PIXCIR_INT_POL_HIGH;
157 else
158 ret &= ~PIXCIR_INT_POL_HIGH;
159
160 ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
161 if (ret < 0) {
162 dev_err(dev, "%s: can't write reg 0x%x : %d\n",
163 __func__, PIXCIR_REG_INT_MODE, ret);
164 return ret;
165 }
166
167 return 0;
168}
169
170/*
171 * Enable/disable interrupt generation
172 */
173static int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable)
174{
175 struct device *dev = &ts->client->dev;
176 int ret;
177
178 ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
179 if (ret < 0) {
180 dev_err(dev, "%s: can't read reg 0x%x : %d\n",
181 __func__, PIXCIR_REG_INT_MODE, ret);
182 return ret;
183 }
184
185 if (enable)
186 ret |= PIXCIR_INT_ENABLE;
187 else
188 ret &= ~PIXCIR_INT_ENABLE;
189
190 ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
191 if (ret < 0) {
192 dev_err(dev, "%s: can't write reg 0x%x : %d\n",
193 __func__, PIXCIR_REG_INT_MODE, ret);
194 return ret;
195 }
196
197 return 0;
198}
199
200static int pixcir_start(struct pixcir_i2c_ts_data *ts)
201{
202 struct device *dev = &ts->client->dev;
203 int error;
204
205 /* LEVEL_TOUCH interrupt with active low polarity */
206 error = pixcir_set_int_mode(ts, PIXCIR_INT_LEVEL_TOUCH, 0);
207 if (error) {
208 dev_err(dev, "Failed to set interrupt mode: %d\n", error);
209 return error;
210 }
211
212 ts->running = true;
213 mb(); /* Update status before IRQ can fire */
214
215 /* enable interrupt generation */
216 error = pixcir_int_enable(ts, true);
217 if (error) {
218 dev_err(dev, "Failed to enable interrupt generation: %d\n",
219 error);
220 return error;
221 }
222
223 return 0;
224}
225
226static int pixcir_stop(struct pixcir_i2c_ts_data *ts)
227{
228 int error;
229
230 /* Disable interrupt generation */
231 error = pixcir_int_enable(ts, false);
232 if (error) {
233 dev_err(&ts->client->dev,
234 "Failed to disable interrupt generation: %d\n",
235 error);
236 return error;
237 }
238
239 /* Exit ISR if running, no more report parsing */
240 ts->running = false;
241 mb(); /* update status before we synchronize irq */
242
243 /* Wait till running ISR is complete */
244 synchronize_irq(ts->client->irq);
245
246 return 0;
247}
248
249static int pixcir_input_open(struct input_dev *dev)
250{
251 struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev);
252
253 return pixcir_start(ts);
254}
255
256static void pixcir_input_close(struct input_dev *dev)
257{
258 struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev);
259
260 pixcir_stop(ts);
261}
262
Jianchun Bian36a281e2011-12-30 15:16:21 -0800263#ifdef CONFIG_PM_SLEEP
264static int pixcir_i2c_ts_suspend(struct device *dev)
265{
266 struct i2c_client *client = to_i2c_client(dev);
267
268 if (device_may_wakeup(&client->dev))
269 enable_irq_wake(client->irq);
270
271 return 0;
272}
273
274static int pixcir_i2c_ts_resume(struct device *dev)
275{
276 struct i2c_client *client = to_i2c_client(dev);
277
278 if (device_may_wakeup(&client->dev))
279 disable_irq_wake(client->irq);
280
281 return 0;
282}
283#endif
284
285static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
286 pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume);
287
Bill Pemberton5298cc42012-11-23 21:38:25 -0800288static int pixcir_i2c_ts_probe(struct i2c_client *client,
Jianchun Bian36a281e2011-12-30 15:16:21 -0800289 const struct i2c_device_id *id)
290{
Jingoo Hanc838cb32013-12-05 19:21:10 -0800291 const struct pixcir_ts_platform_data *pdata =
292 dev_get_platdata(&client->dev);
Roger Quadrose9d47182014-05-18 22:43:42 -0700293 struct device *dev = &client->dev;
Jianchun Bian36a281e2011-12-30 15:16:21 -0800294 struct pixcir_i2c_ts_data *tsdata;
295 struct input_dev *input;
296 int error;
297
298 if (!pdata) {
299 dev_err(&client->dev, "platform data not defined\n");
300 return -EINVAL;
301 }
302
Roger Quadros0dfc8d42014-05-18 22:46:43 -0700303 if (!gpio_is_valid(pdata->gpio_attb)) {
304 dev_err(dev, "Invalid gpio_attb in pdata\n");
305 return -EINVAL;
306 }
307
Roger Quadrose9d47182014-05-18 22:43:42 -0700308 tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL);
309 if (!tsdata)
310 return -ENOMEM;
311
312 input = devm_input_allocate_device(dev);
313 if (!input) {
314 dev_err(dev, "Failed to allocate input device\n");
315 return -ENOMEM;
Jianchun Bian36a281e2011-12-30 15:16:21 -0800316 }
317
318 tsdata->client = client;
319 tsdata->input = input;
320 tsdata->chip = pdata;
321
322 input->name = client->name;
323 input->id.bustype = BUS_I2C;
Roger Quadros3b36fbb2014-05-18 22:44:35 -0700324 input->open = pixcir_input_open;
325 input->close = pixcir_input_close;
Jianchun Bian36a281e2011-12-30 15:16:21 -0800326 input->dev.parent = &client->dev;
327
328 __set_bit(EV_KEY, input->evbit);
329 __set_bit(EV_ABS, input->evbit);
330 __set_bit(BTN_TOUCH, input->keybit);
331 input_set_abs_params(input, ABS_X, 0, pdata->x_max, 0, 0);
332 input_set_abs_params(input, ABS_Y, 0, pdata->y_max, 0, 0);
333 input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0);
334 input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0);
335
336 input_set_drvdata(input, tsdata);
337
Roger Quadros0dfc8d42014-05-18 22:46:43 -0700338 error = devm_gpio_request_one(dev, pdata->gpio_attb,
339 GPIOF_DIR_IN, "pixcir_i2c_attb");
340 if (error) {
341 dev_err(dev, "Failed to request ATTB gpio\n");
342 return error;
343 }
344
Roger Quadrose9d47182014-05-18 22:43:42 -0700345 error = devm_request_threaded_irq(dev, client->irq, NULL, pixcir_ts_isr,
346 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
347 client->name, tsdata);
Jianchun Bian36a281e2011-12-30 15:16:21 -0800348 if (error) {
Roger Quadrose9d47182014-05-18 22:43:42 -0700349 dev_err(dev, "failed to request irq %d\n", client->irq);
350 return error;
Jianchun Bian36a281e2011-12-30 15:16:21 -0800351 }
352
Roger Quadros3b36fbb2014-05-18 22:44:35 -0700353 /* Always be in IDLE mode to save power, device supports auto wake */
354 error = pixcir_set_power_mode(tsdata, PIXCIR_POWER_IDLE);
355 if (error) {
356 dev_err(dev, "Failed to set IDLE mode\n");
357 return error;
358 }
359
360 /* Stop device till opened */
361 error = pixcir_stop(tsdata);
362 if (error)
363 return error;
364
Jianchun Bian36a281e2011-12-30 15:16:21 -0800365 error = input_register_device(input);
366 if (error)
Roger Quadrose9d47182014-05-18 22:43:42 -0700367 return error;
Jianchun Bian36a281e2011-12-30 15:16:21 -0800368
Jianchun Bian36a281e2011-12-30 15:16:21 -0800369 device_init_wakeup(&client->dev, 1);
370
371 return 0;
Jianchun Bian36a281e2011-12-30 15:16:21 -0800372}
373
Bill Pembertone2619cf2012-11-23 21:50:47 -0800374static int pixcir_i2c_ts_remove(struct i2c_client *client)
Jianchun Bian36a281e2011-12-30 15:16:21 -0800375{
Jianchun Bian36a281e2011-12-30 15:16:21 -0800376 device_init_wakeup(&client->dev, 0);
377
Jianchun Bian36a281e2011-12-30 15:16:21 -0800378 return 0;
379}
380
381static const struct i2c_device_id pixcir_i2c_ts_id[] = {
382 { "pixcir_ts", 0 },
383 { }
384};
385MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
386
387static struct i2c_driver pixcir_i2c_ts_driver = {
388 .driver = {
389 .owner = THIS_MODULE,
390 .name = "pixcir_ts",
391 .pm = &pixcir_dev_pm_ops,
392 },
393 .probe = pixcir_i2c_ts_probe,
Bill Pemberton1cb0aa82012-11-23 21:27:39 -0800394 .remove = pixcir_i2c_ts_remove,
Jianchun Bian36a281e2011-12-30 15:16:21 -0800395 .id_table = pixcir_i2c_ts_id,
396};
397
Dmitry Torokhov4a533832012-03-16 23:05:44 -0700398module_i2c_driver(pixcir_i2c_ts_driver);
Jianchun Bian36a281e2011-12-30 15:16:21 -0800399
400MODULE_AUTHOR("Jianchun Bian <jcbian@pixcir.com.cn>, Dequan Meng <dqmeng@pixcir.com.cn>");
401MODULE_DESCRIPTION("Pixcir I2C Touchscreen Driver");
402MODULE_LICENSE("GPL");