]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/staging/dream/synaptics_i2c_rmi.c
Staging: HTC Dream: touchscreen: more cleanups
[mv-sheeva.git] / drivers / staging / dream / synaptics_i2c_rmi.c
1 /*
2  * Support for synaptics touchscreen.
3  *
4  * Copyright (C) 2007 Google, Inc.
5  * Author: Arve Hjønnevåg <arve@android.com>
6  *
7  * This software is licensed under the terms of the GNU General Public
8  * License version 2, as published by the Free Software Foundation, and
9  * may be copied, distributed, and modified under those terms.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  */
17
18 #include <linux/module.h>
19 #include <linux/delay.h>
20 #ifdef CONFIG_HAS_EARLYSUSPEND
21 #include <linux/earlysuspend.h>
22 #endif
23 #include <linux/hrtimer.h>
24 #include <linux/i2c.h>
25 #include <linux/input.h>
26 #include <linux/interrupt.h>
27 #include <linux/io.h>
28 #include <linux/platform_device.h>
29 #include "synaptics_i2c_rmi.h"
30
31 static struct workqueue_struct *synaptics_wq;
32
33 struct synaptics_ts_data {
34         u16 addr;
35         struct i2c_client *client;
36         struct input_dev *input_dev;
37         int use_irq;
38         struct hrtimer timer;
39         struct work_struct  work;
40         u16 max[2];
41         int snap_state[2][2];
42         int snap_down_on[2];
43         int snap_down_off[2];
44         int snap_up_on[2];
45         int snap_up_off[2];
46         int snap_down[2];
47         int snap_up[2];
48         u32 flags;
49         int (*power)(int on);
50 #ifdef CONFIG_HAS_EARLYSUSPEND
51         struct early_suspend early_suspend;
52 #endif
53 };
54
55 static int i2c_set(struct synaptics_ts_data *ts, u8 reg, u8 val, char *msg)
56 {
57         int ret = i2c_smbus_write_byte_data(ts->client, reg, val);
58         if (ret < 0)
59                 pr_err("i2c_smbus_write_byte_data failed (%s)\n", msg);
60         return ret;
61 }
62
63 static int i2c_read(struct synaptics_ts_data *ts, u8 reg, char *msg)
64 {
65         int ret = i2c_smbus_read_byte_data(ts->client, reg);
66         if (ret < 0)
67                 pr_err("i2c_smbus_read_byte_data failed (%s)\n", msg);
68         return ret;
69 }
70 #ifdef CONFIG_HAS_EARLYSUSPEND
71 static void synaptics_ts_early_suspend(struct early_suspend *h);
72 static void synaptics_ts_late_resume(struct early_suspend *h);
73 #endif
74
75 static int synaptics_init_panel(struct synaptics_ts_data *ts)
76 {
77         int ret;
78
79         ret = i2c_set(ts, 0xff, 0x10, "set page select");
80         if (ret == 0)
81                 ret = i2c_set(ts, 0x41, 0x04, "set No Clip Z");
82
83         ret = i2c_set(ts, 0xff, 0x04, "fallback page select");
84         ret = i2c_set(ts, 0xf0, 0x81, "select 80 reports per second");
85         return ret;
86 }
87
88 static void decode_report(struct synaptics_ts_data *ts, u8 *buf)
89 {
90         int pos[2][2];
91         int f, a;
92         int base = 2;
93         int z = buf[1];
94         int w = buf[0] >> 4;
95         int finger = buf[0] & 7;
96         int finger2_pressed;
97
98         for (f = 0; f < 2; f++) {
99                 u32 flip_flag = SYNAPTICS_FLIP_X;
100                 for (a = 0; a < 2; a++) {
101                         int p = buf[base + 1];
102                         p |= (u16)(buf[base] & 0x1f) << 8;
103                         if (ts->flags & flip_flag)
104                                 p = ts->max[a] - p;
105                         if (ts->flags & SYNAPTICS_SNAP_TO_INACTIVE_EDGE) {
106                                 if (ts->snap_state[f][a]) {
107                                         if (p <= ts->snap_down_off[a])
108                                                 p = ts->snap_down[a];
109                                         else if (p >= ts->snap_up_off[a])
110                                                 p = ts->snap_up[a];
111                                         else
112                                                 ts->snap_state[f][a] = 0;
113                                 } else {
114                                         if (p <= ts->snap_down_on[a]) {
115                                                 p = ts->snap_down[a];
116                                                 ts->snap_state[f][a] = 1;
117                                         } else if (p >= ts->snap_up_on[a]) {
118                                                 p = ts->snap_up[a];
119                                                 ts->snap_state[f][a] = 1;
120                                         }
121                                 }
122                         }
123                         pos[f][a] = p;
124                         base += 2;
125                         flip_flag <<= 1;
126                 }
127                 base += 2;
128                 if (ts->flags & SYNAPTICS_SWAP_XY)
129                         swap(pos[f][0], pos[f][1]);
130         }
131         if (z) {
132                 input_report_abs(ts->input_dev, ABS_X, pos[0][0]);
133                 input_report_abs(ts->input_dev, ABS_Y, pos[0][1]);
134         }
135         input_report_abs(ts->input_dev, ABS_PRESSURE, z);
136         input_report_abs(ts->input_dev, ABS_TOOL_WIDTH, w);
137         input_report_key(ts->input_dev, BTN_TOUCH, finger);
138         finger2_pressed = finger > 1 && finger != 7;
139         input_report_key(ts->input_dev, BTN_2, finger2_pressed);
140         if (finger2_pressed) {
141                 input_report_abs(ts->input_dev, ABS_HAT0X, pos[1][0]);
142                 input_report_abs(ts->input_dev, ABS_HAT0Y, pos[1][1]);
143         }
144         input_sync(ts->input_dev);
145 }
146
147 static void synaptics_ts_work_func(struct work_struct *work)
148 {
149         int i;
150         int ret;
151         int bad_data = 0;
152         struct i2c_msg msg[2];
153         u8 start_reg = 0;
154         u8 buf[15];
155         struct synaptics_ts_data *ts =
156                 container_of(work, struct synaptics_ts_data, work);
157
158         msg[0].addr = ts->client->addr;
159         msg[0].flags = 0;
160         msg[0].len = 1;
161         msg[0].buf = &start_reg;
162         msg[1].addr = ts->client->addr;
163         msg[1].flags = I2C_M_RD;
164         msg[1].len = sizeof(buf);
165         msg[1].buf = buf;
166
167         for (i = 0; i < ((ts->use_irq && !bad_data) ? 1 : 10); i++) {
168                 ret = i2c_transfer(ts->client->adapter, msg, 2);
169                 if (ret < 0) {
170                         pr_err("ts_work: i2c_transfer failed\n");
171                         bad_data = 1;
172                         continue;
173                 }
174                 if ((buf[14] & 0xc0) != 0x40) {
175                         pr_warning("synaptics_ts_work_func:"
176                                " bad read %x %x %x %x %x %x %x %x %x"
177                                " %x %x %x %x %x %x, ret %d\n",
178                                buf[0], buf[1], buf[2], buf[3],
179                                buf[4], buf[5], buf[6], buf[7],
180                                buf[8], buf[9], buf[10], buf[11],
181                                buf[12], buf[13], buf[14], ret);
182                         if (bad_data)
183                                 synaptics_init_panel(ts);
184                         bad_data = 1;
185                         continue;
186                 }
187                 bad_data = 0;
188                 if ((buf[14] & 1) == 0)
189                         break;
190
191                 decode_report(ts, buf);
192         }
193         if (ts->use_irq)
194                 enable_irq(ts->client->irq);
195 }
196
197 static enum hrtimer_restart synaptics_ts_timer_func(struct hrtimer *timer)
198 {
199         struct synaptics_ts_data *ts =
200                 container_of(timer, struct synaptics_ts_data, timer);
201
202         queue_work(synaptics_wq, &ts->work);
203
204         hrtimer_start(&ts->timer, ktime_set(0, 12500000), HRTIMER_MODE_REL);
205         return HRTIMER_NORESTART;
206 }
207
208 static irqreturn_t synaptics_ts_irq_handler(int irq, void *dev_id)
209 {
210         struct synaptics_ts_data *ts = dev_id;
211
212         disable_irq_nosync(ts->client->irq);
213         queue_work(synaptics_wq, &ts->work);
214         return IRQ_HANDLED;
215 }
216
217 static int detect(struct synaptics_ts_data *ts, u32 *panel_version)
218 {
219         int ret;
220         int retry = 10;
221
222         ret = i2c_set(ts, 0xf4, 0x01, "reset device");
223
224         while (retry-- > 0) {
225                 ret = i2c_smbus_read_byte_data(ts->client, 0xe4);
226                 if (ret >= 0)
227                         break;
228                 msleep(100);
229         }
230         if (ret < 0) {
231                 pr_err("i2c_smbus_read_byte_data failed\n");
232                 return ret;
233         }
234
235         *panel_version = ret << 8;
236         ret = i2c_read(ts, 0xe5, "product minor");
237         if (ret < 0)
238                 return ret;
239         *panel_version |= ret;
240
241         ret = i2c_read(ts, 0xe3, "property");
242         if (ret < 0)
243                 return ret;
244
245         pr_info("synaptics: version %x, product property %x\n",
246                 *panel_version, ret);
247         return 0;
248 }
249
250 static void compute_areas(struct synaptics_ts_data *ts,
251                           struct synaptics_i2c_rmi_platform_data *pdata,
252                           u16 max_x, u16 max_y)
253 {
254         int inactive_area_left;
255         int inactive_area_right;
256         int inactive_area_top;
257         int inactive_area_bottom;
258         int snap_left_on;
259         int snap_left_off;
260         int snap_right_on;
261         int snap_right_off;
262         int snap_top_on;
263         int snap_top_off;
264         int snap_bottom_on;
265         int snap_bottom_off;
266         int fuzz_x;
267         int fuzz_y;
268         int fuzz_p;
269         int fuzz_w;
270         int swapped = !!(ts->flags & SYNAPTICS_SWAP_XY);
271
272         inactive_area_left = pdata->inactive_left;
273         inactive_area_right = pdata->inactive_right;
274         inactive_area_top = pdata->inactive_top;
275         inactive_area_bottom = pdata->inactive_bottom;
276         snap_left_on = pdata->snap_left_on;
277         snap_left_off = pdata->snap_left_off;
278         snap_right_on = pdata->snap_right_on;
279         snap_right_off = pdata->snap_right_off;
280         snap_top_on = pdata->snap_top_on;
281         snap_top_off = pdata->snap_top_off;
282         snap_bottom_on = pdata->snap_bottom_on;
283         snap_bottom_off = pdata->snap_bottom_off;
284         fuzz_x = pdata->fuzz_x;
285         fuzz_y = pdata->fuzz_y;
286         fuzz_p = pdata->fuzz_p;
287         fuzz_w = pdata->fuzz_w;
288
289         inactive_area_left = inactive_area_left * max_x / 0x10000;
290         inactive_area_right = inactive_area_right * max_x / 0x10000;
291         inactive_area_top = inactive_area_top * max_y / 0x10000;
292         inactive_area_bottom = inactive_area_bottom * max_y / 0x10000;
293         snap_left_on = snap_left_on * max_x / 0x10000;
294         snap_left_off = snap_left_off * max_x / 0x10000;
295         snap_right_on = snap_right_on * max_x / 0x10000;
296         snap_right_off = snap_right_off * max_x / 0x10000;
297         snap_top_on = snap_top_on * max_y / 0x10000;
298         snap_top_off = snap_top_off * max_y / 0x10000;
299         snap_bottom_on = snap_bottom_on * max_y / 0x10000;
300         snap_bottom_off = snap_bottom_off * max_y / 0x10000;
301         fuzz_x = fuzz_x * max_x / 0x10000;
302         fuzz_y = fuzz_y * max_y / 0x10000;
303
304
305         ts->snap_down[swapped] = -inactive_area_left;
306         ts->snap_up[swapped] = max_x + inactive_area_right;
307         ts->snap_down[!swapped] = -inactive_area_top;
308         ts->snap_up[!swapped] = max_y + inactive_area_bottom;
309         ts->snap_down_on[swapped] = snap_left_on;
310         ts->snap_down_off[swapped] = snap_left_off;
311         ts->snap_up_on[swapped] = max_x - snap_right_on;
312         ts->snap_up_off[swapped] = max_x - snap_right_off;
313         ts->snap_down_on[!swapped] = snap_top_on;
314         ts->snap_down_off[!swapped] = snap_top_off;
315         ts->snap_up_on[!swapped] = max_y - snap_bottom_on;
316         ts->snap_up_off[!swapped] = max_y - snap_bottom_off;
317         pr_info("synaptics_ts_probe: max_x %d, max_y %d\n", max_x, max_y);
318         pr_info("synaptics_ts_probe: inactive_x %d %d, inactive_y %d %d\n",
319                inactive_area_left, inactive_area_right,
320                inactive_area_top, inactive_area_bottom);
321         pr_info("synaptics_ts_probe: snap_x %d-%d %d-%d, snap_y %d-%d %d-%d\n",
322                snap_left_on, snap_left_off, snap_right_on, snap_right_off,
323                snap_top_on, snap_top_off, snap_bottom_on, snap_bottom_off);
324
325         input_set_abs_params(ts->input_dev, ABS_X,
326                              -inactive_area_left, max_x + inactive_area_right,
327                              fuzz_x, 0);
328         input_set_abs_params(ts->input_dev, ABS_Y,
329                              -inactive_area_top, max_y + inactive_area_bottom,
330                              fuzz_y, 0);
331         input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 255, fuzz_p, 0);
332         input_set_abs_params(ts->input_dev, ABS_TOOL_WIDTH, 0, 15, fuzz_w, 0);
333         input_set_abs_params(ts->input_dev, ABS_HAT0X, -inactive_area_left,
334                              max_x + inactive_area_right, fuzz_x, 0);
335         input_set_abs_params(ts->input_dev, ABS_HAT0Y, -inactive_area_top,
336                              max_y + inactive_area_bottom, fuzz_y, 0);
337 }
338
339 static struct synaptics_i2c_rmi_platform_data fake_pdata;
340
341 static int __devinit synaptics_ts_probe(
342         struct i2c_client *client, const struct i2c_device_id *id)
343 {
344         struct synaptics_ts_data *ts;
345         u8 buf0[4];
346         u8 buf1[8];
347         struct i2c_msg msg[2];
348         int ret = 0;
349         struct synaptics_i2c_rmi_platform_data *pdata;
350         u32 panel_version = 0;
351         u16 max_x, max_y;
352
353         if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
354                 pr_err("synaptics_ts_probe: need I2C_FUNC_I2C\n");
355                 ret = -ENODEV;
356                 goto err_check_functionality_failed;
357         }
358
359         ts = kzalloc(sizeof(*ts), GFP_KERNEL);
360         if (ts == NULL) {
361                 ret = -ENOMEM;
362                 goto err_alloc_data_failed;
363         }
364         INIT_WORK(&ts->work, synaptics_ts_work_func);
365         ts->client = client;
366         i2c_set_clientdata(client, ts);
367         pdata = client->dev.platform_data;
368         if (pdata)
369                 ts->power = pdata->power;
370         else
371                 pdata = &fake_pdata;
372
373         if (ts->power) {
374                 ret = ts->power(1);
375                 if (ret < 0) {
376                         pr_err("synaptics_ts_probe power on failed\n");
377                         goto err_power_failed;
378                 }
379         }
380
381         ret = detect(ts, &panel_version);
382         if (ret)
383                 goto err_detect_failed;
384
385         while (pdata->version > panel_version)
386                 pdata++;
387         ts->flags = pdata->flags;
388
389         ret = i2c_read(ts, 0xf0, "device control");
390         if (ret < 0)
391                 goto err_detect_failed;
392         pr_info("synaptics: device control %x\n", ret);
393
394         ret = i2c_read(ts, 0xf1, "interrupt enable");
395         if (ret < 0)
396                 goto err_detect_failed;
397         pr_info("synaptics_ts_probe: interrupt enable %x\n", ret);
398
399         ret = i2c_set(ts, 0xf1, 0, "disable interrupt");
400         if (ret < 0)
401                 goto err_detect_failed;
402
403         msg[0].addr = ts->client->addr;
404         msg[0].flags = 0;
405         msg[0].len = 1;
406         msg[0].buf = buf0;
407         buf0[0] = 0xe0;
408         msg[1].addr = ts->client->addr;
409         msg[1].flags = I2C_M_RD;
410         msg[1].len = 8;
411         msg[1].buf = buf1;
412         ret = i2c_transfer(ts->client->adapter, msg, 2);
413         if (ret < 0) {
414                 pr_err("i2c_transfer failed\n");
415                 goto err_detect_failed;
416         }
417         pr_info("synaptics_ts_probe: 0xe0: %x %x %x %x %x %x %x %x\n",
418                buf1[0], buf1[1], buf1[2], buf1[3],
419                buf1[4], buf1[5], buf1[6], buf1[7]);
420
421         ret = i2c_set(ts, 0xff, 0x10, "page select = 0x10");
422         if (ret < 0)
423                 goto err_detect_failed;
424
425         ret = i2c_smbus_read_word_data(ts->client, 0x04);
426         if (ret < 0) {
427                 pr_err("i2c_smbus_read_word_data failed\n");
428                 goto err_detect_failed;
429         }
430         ts->max[0] = max_x = (ret >> 8 & 0xff) | ((ret & 0x1f) << 8);
431         ret = i2c_smbus_read_word_data(ts->client, 0x06);
432         if (ret < 0) {
433                 pr_err("i2c_smbus_read_word_data failed\n");
434                 goto err_detect_failed;
435         }
436         ts->max[1] = max_y = (ret >> 8 & 0xff) | ((ret & 0x1f) << 8);
437         if (ts->flags & SYNAPTICS_SWAP_XY)
438                 swap(max_x, max_y);
439
440         /* will also switch back to page 0x04 */
441         ret = synaptics_init_panel(ts);
442         if (ret < 0) {
443                 pr_err("synaptics_init_panel failed\n");
444                 goto err_detect_failed;
445         }
446
447         ts->input_dev = input_allocate_device();
448         if (ts->input_dev == NULL) {
449                 ret = -ENOMEM;
450                 pr_err("synaptics: Failed to allocate input device\n");
451                 goto err_input_dev_alloc_failed;
452         }
453         ts->input_dev->name = "synaptics-rmi-touchscreen";
454         ts->input_dev->phys = "msm/input0";
455         ts->input_dev->id.bustype = BUS_I2C;
456
457         __set_bit(EV_SYN, ts->input_dev->evbit);
458         __set_bit(EV_KEY, ts->input_dev->evbit);
459         __set_bit(BTN_TOUCH, ts->input_dev->keybit);
460         __set_bit(BTN_2, ts->input_dev->keybit);
461         __set_bit(EV_ABS, ts->input_dev->evbit);
462
463         compute_areas(ts, pdata, max_x, max_y);
464
465
466         ret = input_register_device(ts->input_dev);
467         if (ret) {
468                 pr_err("synaptics: Unable to register %s input device\n",
469                        ts->input_dev->name);
470                 goto err_input_register_device_failed;
471         }
472         if (client->irq) {
473                 ret = request_irq(client->irq, synaptics_ts_irq_handler,
474                                   0, client->name, ts);
475                 if (ret == 0) {
476                         ret = i2c_set(ts, 0xf1, 0x01, "enable abs int");
477                         if (ret)
478                                 free_irq(client->irq, ts);
479                 }
480                 if (ret == 0)
481                         ts->use_irq = 1;
482                 else
483                         dev_err(&client->dev, "request_irq failed\n");
484         }
485         if (!ts->use_irq) {
486                 hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
487                 ts->timer.function = synaptics_ts_timer_func;
488                 hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
489         }
490 #ifdef CONFIG_HAS_EARLYSUSPEND
491         ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
492         ts->early_suspend.suspend = synaptics_ts_early_suspend;
493         ts->early_suspend.resume = synaptics_ts_late_resume;
494         register_early_suspend(&ts->early_suspend);
495 #endif
496
497         pr_info("synaptics: Start touchscreen %s in %s mode\n",
498                 ts->input_dev->name, ts->use_irq ? "interrupt" : "polling");
499
500         return 0;
501
502 err_input_register_device_failed:
503         input_free_device(ts->input_dev);
504
505 err_input_dev_alloc_failed:
506 err_detect_failed:
507 err_power_failed:
508         kfree(ts);
509 err_alloc_data_failed:
510 err_check_functionality_failed:
511         return ret;
512 }
513
514 static int synaptics_ts_remove(struct i2c_client *client)
515 {
516         struct synaptics_ts_data *ts = i2c_get_clientdata(client);
517 #ifdef CONFIG_HAS_EARLYSUSPEND
518         unregister_early_suspend(&ts->early_suspend);
519 #endif
520         if (ts->use_irq)
521                 free_irq(client->irq, ts);
522         else
523                 hrtimer_cancel(&ts->timer);
524         input_unregister_device(ts->input_dev);
525         kfree(ts);
526         return 0;
527 }
528
529 #ifdef CONFIG_PM
530 static int synaptics_ts_suspend(struct i2c_client *client, pm_message_t mesg)
531 {
532         int ret;
533         struct synaptics_ts_data *ts = i2c_get_clientdata(client);
534
535         if (ts->use_irq)
536                 disable_irq(client->irq);
537         else
538                 hrtimer_cancel(&ts->timer);
539         ret = cancel_work_sync(&ts->work);
540         if (ret && ts->use_irq) /* if work was pending disable-count is now 2 */
541                 enable_irq(client->irq);
542         i2c_set(ts, 0xf1, 0, "disable interrupt");
543         i2c_set(ts, 0xf0, 0x86, "deep sleep");
544
545         if (ts->power) {
546                 ret = ts->power(0);
547                 if (ret < 0)
548                         pr_err("synaptics_ts_suspend power off failed\n");
549         }
550         return 0;
551 }
552
553 static int synaptics_ts_resume(struct i2c_client *client)
554 {
555         int ret;
556         struct synaptics_ts_data *ts = i2c_get_clientdata(client);
557
558         if (ts->power) {
559                 ret = ts->power(1);
560                 if (ret < 0)
561                         pr_err("synaptics_ts_resume power on failed\n");
562         }
563
564         synaptics_init_panel(ts);
565
566         if (ts->use_irq) {
567                 enable_irq(client->irq);
568                 i2c_set(ts, 0xf1, 0x01, "enable abs int");
569         } else
570                 hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
571
572         return 0;
573 }
574
575 #ifdef CONFIG_HAS_EARLYSUSPEND
576 static void synaptics_ts_early_suspend(struct early_suspend *h)
577 {
578         struct synaptics_ts_data *ts;
579         ts = container_of(h, struct synaptics_ts_data, early_suspend);
580         synaptics_ts_suspend(ts->client, PMSG_SUSPEND);
581 }
582
583 static void synaptics_ts_late_resume(struct early_suspend *h)
584 {
585         struct synaptics_ts_data *ts;
586         ts = container_of(h, struct synaptics_ts_data, early_suspend);
587         synaptics_ts_resume(ts->client);
588 }
589 #endif
590 #else
591 #define synaptics_ts_suspend NULL
592 #define synaptics_ts_resume NULL
593 #endif
594
595
596
597 static const struct i2c_device_id synaptics_ts_id[] = {
598         { SYNAPTICS_I2C_RMI_NAME, 0 },
599         { }
600 };
601
602 static struct i2c_driver synaptics_ts_driver = {
603         .probe          = synaptics_ts_probe,
604         .remove         = synaptics_ts_remove,
605 #ifndef CONFIG_HAS_EARLYSUSPEND
606         .suspend        = synaptics_ts_suspend,
607         .resume         = synaptics_ts_resume,
608 #endif
609         .id_table       = synaptics_ts_id,
610         .driver = {
611                 .name   = SYNAPTICS_I2C_RMI_NAME,
612         },
613 };
614
615 static int __devinit synaptics_ts_init(void)
616 {
617         synaptics_wq = create_singlethread_workqueue("synaptics_wq");
618         if (!synaptics_wq)
619                 return -ENOMEM;
620         return i2c_add_driver(&synaptics_ts_driver);
621 }
622
623 static void __exit synaptics_ts_exit(void)
624 {
625         i2c_del_driver(&synaptics_ts_driver);
626         if (synaptics_wq)
627                 destroy_workqueue(synaptics_wq);
628 }
629
630 module_init(synaptics_ts_init);
631 module_exit(synaptics_ts_exit);
632
633 MODULE_DESCRIPTION("Synaptics Touchscreen Driver");
634 MODULE_LICENSE("GPL");
635 MODULE_AUTHOR("Arve Hjønnevåg <arve@android.com>");