]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/input/touchscreen/pixcir_i2c_ts.c
arm: imx6: defconfig: update tx6 defconfigs
[karo-tx-linux.git] / drivers / input / touchscreen / pixcir_i2c_ts.c
1 /*
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>
27
28 struct pixcir_i2c_ts_data {
29         struct i2c_client *client;
30         struct input_dev *input;
31         const struct pixcir_ts_platform_data *chip;
32         bool exiting;
33 };
34
35 static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data)
36 {
37         struct pixcir_i2c_ts_data *tsdata = data;
38         u8 rdbuf[10], wrbuf[1] = { 0 };
39         u8 touch;
40         int ret;
41
42         ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf));
43         if (ret != sizeof(wrbuf)) {
44                 dev_err(&tsdata->client->dev,
45                         "%s: i2c_master_send failed(), ret=%d\n",
46                         __func__, ret);
47                 return;
48         }
49
50         ret = i2c_master_recv(tsdata->client, rdbuf, sizeof(rdbuf));
51         if (ret != sizeof(rdbuf)) {
52                 dev_err(&tsdata->client->dev,
53                         "%s: i2c_master_recv failed(), ret=%d\n",
54                         __func__, ret);
55                 return;
56         }
57
58         touch = rdbuf[0];
59         if (touch) {
60                 u16 posx1 = (rdbuf[3] << 8) | rdbuf[2];
61                 u16 posy1 = (rdbuf[5] << 8) | rdbuf[4];
62                 u16 posx2 = (rdbuf[7] << 8) | rdbuf[6];
63                 u16 posy2 = (rdbuf[9] << 8) | rdbuf[8];
64
65                 input_report_key(tsdata->input, BTN_TOUCH, 1);
66                 input_report_abs(tsdata->input, ABS_X, posx1);
67                 input_report_abs(tsdata->input, ABS_Y, posy1);
68
69                 input_report_abs(tsdata->input, ABS_MT_POSITION_X, posx1);
70                 input_report_abs(tsdata->input, ABS_MT_POSITION_Y, posy1);
71                 input_mt_sync(tsdata->input);
72
73                 if (touch == 2) {
74                         input_report_abs(tsdata->input,
75                                          ABS_MT_POSITION_X, posx2);
76                         input_report_abs(tsdata->input,
77                                          ABS_MT_POSITION_Y, posy2);
78                         input_mt_sync(tsdata->input);
79                 }
80         } else {
81                 input_report_key(tsdata->input, BTN_TOUCH, 0);
82         }
83
84         input_sync(tsdata->input);
85 }
86
87 static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
88 {
89         struct pixcir_i2c_ts_data *tsdata = dev_id;
90
91         while (!tsdata->exiting) {
92                 pixcir_ts_poscheck(tsdata);
93
94                 if (tsdata->chip->attb_read_val())
95                         break;
96
97                 msleep(20);
98         }
99
100         return IRQ_HANDLED;
101 }
102
103 #ifdef CONFIG_PM_SLEEP
104 static int pixcir_i2c_ts_suspend(struct device *dev)
105 {
106         struct i2c_client *client = to_i2c_client(dev);
107
108         if (device_may_wakeup(&client->dev))
109                 enable_irq_wake(client->irq);
110
111         return 0;
112 }
113
114 static int pixcir_i2c_ts_resume(struct device *dev)
115 {
116         struct i2c_client *client = to_i2c_client(dev);
117
118         if (device_may_wakeup(&client->dev))
119                 disable_irq_wake(client->irq);
120
121         return 0;
122 }
123 #endif
124
125 static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
126                          pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume);
127
128 static int pixcir_i2c_ts_probe(struct i2c_client *client,
129                                          const struct i2c_device_id *id)
130 {
131         const struct pixcir_ts_platform_data *pdata = client->dev.platform_data;
132         struct pixcir_i2c_ts_data *tsdata;
133         struct input_dev *input;
134         int error;
135
136         if (!pdata) {
137                 dev_err(&client->dev, "platform data not defined\n");
138                 return -EINVAL;
139         }
140
141         tsdata = kzalloc(sizeof(*tsdata), GFP_KERNEL);
142         input = input_allocate_device();
143         if (!tsdata || !input) {
144                 dev_err(&client->dev, "Failed to allocate driver data!\n");
145                 error = -ENOMEM;
146                 goto err_free_mem;
147         }
148
149         tsdata->client = client;
150         tsdata->input = input;
151         tsdata->chip = pdata;
152
153         input->name = client->name;
154         input->id.bustype = BUS_I2C;
155         input->dev.parent = &client->dev;
156
157         __set_bit(EV_KEY, input->evbit);
158         __set_bit(EV_ABS, input->evbit);
159         __set_bit(BTN_TOUCH, input->keybit);
160         input_set_abs_params(input, ABS_X, 0, pdata->x_max, 0, 0);
161         input_set_abs_params(input, ABS_Y, 0, pdata->y_max, 0, 0);
162         input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0);
163         input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0);
164
165         input_set_drvdata(input, tsdata);
166
167         error = request_threaded_irq(client->irq, NULL, pixcir_ts_isr,
168                                      IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
169                                      client->name, tsdata);
170         if (error) {
171                 dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
172                 goto err_free_mem;
173         }
174
175         error = input_register_device(input);
176         if (error)
177                 goto err_free_irq;
178
179         i2c_set_clientdata(client, tsdata);
180         device_init_wakeup(&client->dev, 1);
181
182         return 0;
183
184 err_free_irq:
185         free_irq(client->irq, tsdata);
186 err_free_mem:
187         input_free_device(input);
188         kfree(tsdata);
189         return error;
190 }
191
192 static int pixcir_i2c_ts_remove(struct i2c_client *client)
193 {
194         struct pixcir_i2c_ts_data *tsdata = i2c_get_clientdata(client);
195
196         device_init_wakeup(&client->dev, 0);
197
198         tsdata->exiting = true;
199         mb();
200         free_irq(client->irq, tsdata);
201
202         input_unregister_device(tsdata->input);
203         kfree(tsdata);
204
205         return 0;
206 }
207
208 static const struct i2c_device_id pixcir_i2c_ts_id[] = {
209         { "pixcir_ts", 0 },
210         { }
211 };
212 MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
213
214 static struct i2c_driver pixcir_i2c_ts_driver = {
215         .driver = {
216                 .owner  = THIS_MODULE,
217                 .name   = "pixcir_ts",
218                 .pm     = &pixcir_dev_pm_ops,
219         },
220         .probe          = pixcir_i2c_ts_probe,
221         .remove         = pixcir_i2c_ts_remove,
222         .id_table       = pixcir_i2c_ts_id,
223 };
224
225 module_i2c_driver(pixcir_i2c_ts_driver);
226
227 MODULE_AUTHOR("Jianchun Bian <jcbian@pixcir.com.cn>, Dequan Meng <dqmeng@pixcir.com.cn>");
228 MODULE_DESCRIPTION("Pixcir I2C Touchscreen Driver");
229 MODULE_LICENSE("GPL");