diff options
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/mouse/Kconfig | 18 | ||||
-rw-r--r-- | drivers/input/mouse/Makefile | 1 | ||||
-rw-r--r-- | drivers/input/mouse/synaptics_i2c.c | 676 |
3 files changed, 695 insertions, 0 deletions
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index c66cc3d08c2f..8a2c5b14c8d8 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
@@ -303,4 +303,22 @@ config MOUSE_MAPLE | |||
303 | To compile this driver as a module choose M here: the module will be | 303 | To compile this driver as a module choose M here: the module will be |
304 | called maplemouse. | 304 | called maplemouse. |
305 | 305 | ||
306 | config MOUSE_SYNAPTICS_I2C | ||
307 | tristate "Synaptics I2C Touchpad support" | ||
308 | depends on I2C | ||
309 | help | ||
310 | This driver supports Synaptics I2C touchpad controller on eXeda | ||
311 | mobile device. | ||
312 | The device will not work the synaptics X11 driver because | ||
313 | (i) it reports only relative coordinates and has no capabilities | ||
314 | to report absolute coordinates | ||
315 | (ii) the eXeda device itself uses Xfbdev as X Server and it does | ||
316 | not allow using xf86-input-* drivers. | ||
317 | |||
318 | Say y here if you have eXeda device and want to use a Synaptics | ||
319 | I2C Touchpad. | ||
320 | |||
321 | To compile this driver as a module, choose M here: the | ||
322 | module will be called synaptics_i2c. | ||
323 | |||
306 | endif | 324 | endif |
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 472189468d67..010f265ec152 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile | |||
@@ -18,6 +18,7 @@ obj-$(CONFIG_MOUSE_PS2) += psmouse.o | |||
18 | obj-$(CONFIG_MOUSE_PXA930_TRKBALL) += pxa930_trkball.o | 18 | obj-$(CONFIG_MOUSE_PXA930_TRKBALL) += pxa930_trkball.o |
19 | obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o | 19 | obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o |
20 | obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o | 20 | obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o |
21 | obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o | ||
21 | obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o | 22 | obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o |
22 | 23 | ||
23 | psmouse-objs := psmouse-base.o synaptics.o | 24 | psmouse-objs := psmouse-base.o synaptics.o |
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c new file mode 100644 index 000000000000..eac9fdde7ee9 --- /dev/null +++ b/drivers/input/mouse/synaptics_i2c.c | |||
@@ -0,0 +1,676 @@ | |||
1 | /* | ||
2 | * Synaptics touchpad with I2C interface | ||
3 | * | ||
4 | * Copyright (C) 2009 Compulab, Ltd. | ||
5 | * Mike Rapoport <mike@compulab.co.il> | ||
6 | * Igor Grinberg <grinberg@compulab.co.il> | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License. See the file COPYING in the main directory of this archive for | ||
10 | * more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/i2c.h> | ||
15 | #include <linux/irq.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/input.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/workqueue.h> | ||
20 | |||
21 | #define DRIVER_NAME "synaptics_i2c" | ||
22 | /* maximum product id is 15 characters */ | ||
23 | #define PRODUCT_ID_LENGTH 15 | ||
24 | #define REGISTER_LENGTH 8 | ||
25 | |||
26 | /* | ||
27 | * after soft reset, we should wait for 1 ms | ||
28 | * before the device becomes operational | ||
29 | */ | ||
30 | #define SOFT_RESET_DELAY_MS 3 | ||
31 | /* and after hard reset, we should wait for max 500ms */ | ||
32 | #define HARD_RESET_DELAY_MS 500 | ||
33 | |||
34 | /* Registers by SMBus address */ | ||
35 | #define PAGE_SEL_REG 0xff | ||
36 | #define DEVICE_STATUS_REG 0x09 | ||
37 | |||
38 | /* Registers by RMI address */ | ||
39 | #define DEV_CONTROL_REG 0x0000 | ||
40 | #define INTERRUPT_EN_REG 0x0001 | ||
41 | #define ERR_STAT_REG 0x0002 | ||
42 | #define INT_REQ_STAT_REG 0x0003 | ||
43 | #define DEV_COMMAND_REG 0x0004 | ||
44 | |||
45 | #define RMI_PROT_VER_REG 0x0200 | ||
46 | #define MANUFACT_ID_REG 0x0201 | ||
47 | #define PHYS_INT_VER_REG 0x0202 | ||
48 | #define PROD_PROPERTY_REG 0x0203 | ||
49 | #define INFO_QUERY_REG0 0x0204 | ||
50 | #define INFO_QUERY_REG1 (INFO_QUERY_REG0 + 1) | ||
51 | #define INFO_QUERY_REG2 (INFO_QUERY_REG0 + 2) | ||
52 | #define INFO_QUERY_REG3 (INFO_QUERY_REG0 + 3) | ||
53 | |||
54 | #define PRODUCT_ID_REG0 0x0210 | ||
55 | #define PRODUCT_ID_REG1 (PRODUCT_ID_REG0 + 1) | ||
56 | #define PRODUCT_ID_REG2 (PRODUCT_ID_REG0 + 2) | ||
57 | #define PRODUCT_ID_REG3 (PRODUCT_ID_REG0 + 3) | ||
58 | #define PRODUCT_ID_REG4 (PRODUCT_ID_REG0 + 4) | ||
59 | #define PRODUCT_ID_REG5 (PRODUCT_ID_REG0 + 5) | ||
60 | #define PRODUCT_ID_REG6 (PRODUCT_ID_REG0 + 6) | ||
61 | #define PRODUCT_ID_REG7 (PRODUCT_ID_REG0 + 7) | ||
62 | #define PRODUCT_ID_REG8 (PRODUCT_ID_REG0 + 8) | ||
63 | #define PRODUCT_ID_REG9 (PRODUCT_ID_REG0 + 9) | ||
64 | #define PRODUCT_ID_REG10 (PRODUCT_ID_REG0 + 10) | ||
65 | #define PRODUCT_ID_REG11 (PRODUCT_ID_REG0 + 11) | ||
66 | #define PRODUCT_ID_REG12 (PRODUCT_ID_REG0 + 12) | ||
67 | #define PRODUCT_ID_REG13 (PRODUCT_ID_REG0 + 13) | ||
68 | #define PRODUCT_ID_REG14 (PRODUCT_ID_REG0 + 14) | ||
69 | #define PRODUCT_ID_REG15 (PRODUCT_ID_REG0 + 15) | ||
70 | |||
71 | #define DATA_REG0 0x0400 | ||
72 | #define ABS_PRESSURE_REG 0x0401 | ||
73 | #define ABS_MSB_X_REG 0x0402 | ||
74 | #define ABS_LSB_X_REG (ABS_MSB_X_REG + 1) | ||
75 | #define ABS_MSB_Y_REG 0x0404 | ||
76 | #define ABS_LSB_Y_REG (ABS_MSB_Y_REG + 1) | ||
77 | #define REL_X_REG 0x0406 | ||
78 | #define REL_Y_REG 0x0407 | ||
79 | |||
80 | #define DEV_QUERY_REG0 0x1000 | ||
81 | #define DEV_QUERY_REG1 (DEV_QUERY_REG0 + 1) | ||
82 | #define DEV_QUERY_REG2 (DEV_QUERY_REG0 + 2) | ||
83 | #define DEV_QUERY_REG3 (DEV_QUERY_REG0 + 3) | ||
84 | #define DEV_QUERY_REG4 (DEV_QUERY_REG0 + 4) | ||
85 | #define DEV_QUERY_REG5 (DEV_QUERY_REG0 + 5) | ||
86 | #define DEV_QUERY_REG6 (DEV_QUERY_REG0 + 6) | ||
87 | #define DEV_QUERY_REG7 (DEV_QUERY_REG0 + 7) | ||
88 | #define DEV_QUERY_REG8 (DEV_QUERY_REG0 + 8) | ||
89 | |||
90 | #define GENERAL_2D_CONTROL_REG 0x1041 | ||
91 | #define SENSOR_SENSITIVITY_REG 0x1044 | ||
92 | #define SENS_MAX_POS_MSB_REG 0x1046 | ||
93 | #define SENS_MAX_POS_LSB_REG (SENS_MAX_POS_UPPER_REG + 1) | ||
94 | |||
95 | /* Register bits */ | ||
96 | /* Device Control Register Bits */ | ||
97 | #define REPORT_RATE_1ST_BIT 6 | ||
98 | |||
99 | /* Interrupt Enable Register Bits (INTERRUPT_EN_REG) */ | ||
100 | #define F10_ABS_INT_ENA 0 | ||
101 | #define F10_REL_INT_ENA 1 | ||
102 | #define F20_INT_ENA 2 | ||
103 | |||
104 | /* Interrupt Request Register Bits (INT_REQ_STAT_REG | DEVICE_STATUS_REG) */ | ||
105 | #define F10_ABS_INT_REQ 0 | ||
106 | #define F10_REL_INT_REQ 1 | ||
107 | #define F20_INT_REQ 2 | ||
108 | /* Device Status Register Bits (DEVICE_STATUS_REG) */ | ||
109 | #define STAT_CONFIGURED 6 | ||
110 | #define STAT_ERROR 7 | ||
111 | |||
112 | /* Device Command Register Bits (DEV_COMMAND_REG) */ | ||
113 | #define RESET_COMMAND 0x01 | ||
114 | #define REZERO_COMMAND 0x02 | ||
115 | |||
116 | /* Data Register 0 Bits (DATA_REG0) */ | ||
117 | #define GESTURE 3 | ||
118 | |||
119 | /* Device Query Registers Bits */ | ||
120 | /* DEV_QUERY_REG3 */ | ||
121 | #define HAS_PALM_DETECT 1 | ||
122 | #define HAS_MULTI_FING 2 | ||
123 | #define HAS_SCROLLER 4 | ||
124 | #define HAS_2D_SCROLL 5 | ||
125 | |||
126 | /* General 2D Control Register Bits (GENERAL_2D_CONTROL_REG) */ | ||
127 | #define NO_DECELERATION 1 | ||
128 | #define REDUCE_REPORTING 3 | ||
129 | #define NO_FILTER 5 | ||
130 | |||
131 | /* Function Masks */ | ||
132 | /* Device Control Register Masks (DEV_CONTROL_REG) */ | ||
133 | #define REPORT_RATE_MSK 0xc0 | ||
134 | #define SLEEP_MODE_MSK 0x07 | ||
135 | |||
136 | /* Device Sleep Modes */ | ||
137 | #define FULL_AWAKE 0x0 | ||
138 | #define NORMAL_OP 0x1 | ||
139 | #define LOW_PWR_OP 0x2 | ||
140 | #define VERY_LOW_PWR_OP 0x3 | ||
141 | #define SENS_SLEEP 0x4 | ||
142 | #define SLEEP_MOD 0x5 | ||
143 | #define DEEP_SLEEP 0x6 | ||
144 | #define HIBERNATE 0x7 | ||
145 | |||
146 | /* Interrupt Register Mask */ | ||
147 | /* (INT_REQ_STAT_REG | DEVICE_STATUS_REG | INTERRUPT_EN_REG) */ | ||
148 | #define INT_ENA_REQ_MSK 0x07 | ||
149 | #define INT_ENA_ABS_MSK 0x01 | ||
150 | #define INT_ENA_REL_MSK 0x02 | ||
151 | #define INT_ENA_F20_MSK 0x04 | ||
152 | |||
153 | /* Device Status Register Masks (DEVICE_STATUS_REG) */ | ||
154 | #define CONFIGURED_MSK 0x40 | ||
155 | #define ERROR_MSK 0x80 | ||
156 | |||
157 | /* Data Register 0 Masks */ | ||
158 | #define FINGER_WIDTH_MSK 0xf0 | ||
159 | #define GESTURE_MSK 0x08 | ||
160 | #define SENSOR_STATUS_MSK 0x07 | ||
161 | |||
162 | /* | ||
163 | * MSB Position Register Masks | ||
164 | * ABS_MSB_X_REG | ABS_MSB_Y_REG | SENS_MAX_POS_MSB_REG | | ||
165 | * DEV_QUERY_REG3 | DEV_QUERY_REG5 | ||
166 | */ | ||
167 | #define MSB_POSITION_MSK 0x1f | ||
168 | |||
169 | /* Device Query Registers Masks */ | ||
170 | |||
171 | /* DEV_QUERY_REG2 */ | ||
172 | #define NUM_EXTRA_POS_MSK 0x07 | ||
173 | |||
174 | /* When in IRQ mode read the device every THREAD_IRQ_SLEEP_SECS */ | ||
175 | #define THREAD_IRQ_SLEEP_SECS 2 | ||
176 | #define THREAD_IRQ_SLEEP_MSECS (THREAD_IRQ_SLEEP_SECS * MSEC_PER_SEC) | ||
177 | |||
178 | /* | ||
179 | * When in Polling mode and no data received for NO_DATA_THRES msecs | ||
180 | * reduce the polling rate to NO_DATA_SLEEP_MSECS | ||
181 | */ | ||
182 | #define NO_DATA_THRES (MSEC_PER_SEC) | ||
183 | #define NO_DATA_SLEEP_MSECS (MSEC_PER_SEC / 4) | ||
184 | |||
185 | /* Control touchpad's No Deceleration option */ | ||
186 | static int no_decel = 1; | ||
187 | module_param(no_decel, bool, 0644); | ||
188 | MODULE_PARM_DESC(no_decel, "No Deceleration. Default = 1 (on)"); | ||
189 | |||
190 | /* Control touchpad's Reduced Reporting option */ | ||
191 | static int reduce_report; | ||
192 | module_param(reduce_report, bool, 0644); | ||
193 | MODULE_PARM_DESC(reduce_report, "Reduced Reporting. Default = 0 (off)"); | ||
194 | |||
195 | /* Control touchpad's No Filter option */ | ||
196 | static int no_filter; | ||
197 | module_param(no_filter, bool, 0644); | ||
198 | MODULE_PARM_DESC(no_filter, "No Filter. Default = 0 (off)"); | ||
199 | |||
200 | /* | ||
201 | * touchpad Attention line is Active Low and Open Drain, | ||
202 | * therefore should be connected to pulled up line | ||
203 | * and the irq configuration should be set to Falling Edge Trigger | ||
204 | */ | ||
205 | /* Control IRQ / Polling option */ | ||
206 | static int polling_req; | ||
207 | module_param(polling_req, bool, 0444); | ||
208 | MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)"); | ||
209 | |||
210 | /* Control Polling Rate */ | ||
211 | static int scan_rate = 80; | ||
212 | module_param(scan_rate, int, 0644); | ||
213 | MODULE_PARM_DESC(scan_rate, "Polling rate in times/sec. Default = 80"); | ||
214 | |||
215 | /* The main device structure */ | ||
216 | struct synaptics_i2c { | ||
217 | struct i2c_client *client; | ||
218 | struct input_dev *input; | ||
219 | struct delayed_work dwork; | ||
220 | int no_data_count; | ||
221 | int no_decel_param; | ||
222 | int reduce_report_param; | ||
223 | int no_filter_param; | ||
224 | int scan_rate_param; | ||
225 | int scan_ms; | ||
226 | }; | ||
227 | |||
228 | static inline void set_scan_rate(struct synaptics_i2c *touch, int scan_rate) | ||
229 | { | ||
230 | touch->scan_ms = MSEC_PER_SEC / scan_rate; | ||
231 | touch->scan_rate_param = scan_rate; | ||
232 | } | ||
233 | |||
234 | /* | ||
235 | * Driver's initial design makes no race condition possible on i2c bus, | ||
236 | * so there is no need in any locking. | ||
237 | * Keep it in mind, while playing with the code. | ||
238 | */ | ||
239 | static s32 synaptics_i2c_reg_get(struct i2c_client *client, u16 reg) | ||
240 | { | ||
241 | int ret; | ||
242 | |||
243 | ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); | ||
244 | if (ret == 0) | ||
245 | ret = i2c_smbus_read_byte_data(client, reg & 0xff); | ||
246 | |||
247 | return ret; | ||
248 | } | ||
249 | |||
250 | static s32 synaptics_i2c_reg_set(struct i2c_client *client, u16 reg, u8 val) | ||
251 | { | ||
252 | int ret; | ||
253 | |||
254 | ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); | ||
255 | if (ret == 0) | ||
256 | ret = i2c_smbus_write_byte_data(client, reg & 0xff, val); | ||
257 | |||
258 | return ret; | ||
259 | } | ||
260 | |||
261 | static s32 synaptics_i2c_word_get(struct i2c_client *client, u16 reg) | ||
262 | { | ||
263 | int ret; | ||
264 | |||
265 | ret = i2c_smbus_write_byte_data(client, PAGE_SEL_REG, reg >> 8); | ||
266 | if (ret == 0) | ||
267 | ret = i2c_smbus_read_word_data(client, reg & 0xff); | ||
268 | |||
269 | return ret; | ||
270 | } | ||
271 | |||
272 | static int synaptics_i2c_config(struct i2c_client *client) | ||
273 | { | ||
274 | int ret, control; | ||
275 | u8 int_en; | ||
276 | |||
277 | /* set Report Rate to Device Highest (>=80) and Sleep to normal */ | ||
278 | ret = synaptics_i2c_reg_set(client, DEV_CONTROL_REG, 0xc1); | ||
279 | if (ret) | ||
280 | return ret; | ||
281 | |||
282 | /* set Interrupt Disable to Func20 / Enable to Func10) */ | ||
283 | int_en = (polling_req) ? 0 : INT_ENA_ABS_MSK | INT_ENA_REL_MSK; | ||
284 | ret = synaptics_i2c_reg_set(client, INTERRUPT_EN_REG, int_en); | ||
285 | if (ret) | ||
286 | return ret; | ||
287 | |||
288 | control = synaptics_i2c_reg_get(client, GENERAL_2D_CONTROL_REG); | ||
289 | /* No Deceleration */ | ||
290 | control |= no_decel ? 1 << NO_DECELERATION : 0; | ||
291 | /* Reduced Reporting */ | ||
292 | control |= reduce_report ? 1 << REDUCE_REPORTING : 0; | ||
293 | /* No Filter */ | ||
294 | control |= no_filter ? 1 << NO_FILTER : 0; | ||
295 | ret = synaptics_i2c_reg_set(client, GENERAL_2D_CONTROL_REG, control); | ||
296 | if (ret) | ||
297 | return ret; | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | static int synaptics_i2c_reset_config(struct i2c_client *client) | ||
303 | { | ||
304 | int ret; | ||
305 | |||
306 | /* Reset the Touchpad */ | ||
307 | ret = synaptics_i2c_reg_set(client, DEV_COMMAND_REG, RESET_COMMAND); | ||
308 | if (ret) { | ||
309 | dev_err(&client->dev, "Unable to reset device\n"); | ||
310 | } else { | ||
311 | msleep(SOFT_RESET_DELAY_MS); | ||
312 | ret = synaptics_i2c_config(client); | ||
313 | if (ret) | ||
314 | dev_err(&client->dev, "Unable to config device\n"); | ||
315 | } | ||
316 | |||
317 | return ret; | ||
318 | } | ||
319 | |||
320 | static int synaptics_i2c_check_error(struct i2c_client *client) | ||
321 | { | ||
322 | int status, ret = 0; | ||
323 | |||
324 | status = i2c_smbus_read_byte_data(client, DEVICE_STATUS_REG) & | ||
325 | (CONFIGURED_MSK | ERROR_MSK); | ||
326 | |||
327 | if (status != CONFIGURED_MSK) | ||
328 | ret = synaptics_i2c_reset_config(client); | ||
329 | |||
330 | return ret; | ||
331 | } | ||
332 | |||
333 | static bool synaptics_i2c_get_input(struct synaptics_i2c *touch) | ||
334 | { | ||
335 | struct input_dev *input = touch->input; | ||
336 | int xy_delta, gesture; | ||
337 | s32 data; | ||
338 | s8 x_delta, y_delta; | ||
339 | |||
340 | /* Deal with spontanious resets and errors */ | ||
341 | if (synaptics_i2c_check_error(touch->client)) | ||
342 | return 0; | ||
343 | |||
344 | /* Get Gesture Bit */ | ||
345 | data = synaptics_i2c_reg_get(touch->client, DATA_REG0); | ||
346 | gesture = (data >> GESTURE) & 0x1; | ||
347 | |||
348 | /* | ||
349 | * Get Relative axes. we have to get them in one shot, | ||
350 | * so we get 2 bytes starting from REL_X_REG. | ||
351 | */ | ||
352 | xy_delta = synaptics_i2c_word_get(touch->client, REL_X_REG) & 0xffff; | ||
353 | |||
354 | /* Separate X from Y */ | ||
355 | x_delta = xy_delta & 0xff; | ||
356 | y_delta = (xy_delta >> REGISTER_LENGTH) & 0xff; | ||
357 | |||
358 | /* Report the button event */ | ||
359 | input_report_key(input, BTN_LEFT, gesture); | ||
360 | |||
361 | /* Report the deltas */ | ||
362 | input_report_rel(input, REL_X, x_delta); | ||
363 | input_report_rel(input, REL_Y, -y_delta); | ||
364 | input_sync(input); | ||
365 | |||
366 | return xy_delta || gesture; | ||
367 | } | ||
368 | |||
369 | static irqreturn_t synaptics_i2c_irq(int irq, void *dev_id) | ||
370 | { | ||
371 | struct synaptics_i2c *touch = dev_id; | ||
372 | |||
373 | /* | ||
374 | * We want to have the work run immediately but it might have | ||
375 | * already been scheduled with a delay, that's why we have to | ||
376 | * cancel it first. | ||
377 | */ | ||
378 | cancel_delayed_work(&touch->dwork); | ||
379 | schedule_delayed_work(&touch->dwork, 0); | ||
380 | |||
381 | return IRQ_HANDLED; | ||
382 | } | ||
383 | |||
384 | static void synaptics_i2c_check_params(struct synaptics_i2c *touch) | ||
385 | { | ||
386 | bool reset = false; | ||
387 | |||
388 | if (scan_rate != touch->scan_rate_param) | ||
389 | set_scan_rate(touch, scan_rate); | ||
390 | |||
391 | if (no_decel != touch->no_decel_param) { | ||
392 | touch->no_decel_param = no_decel; | ||
393 | reset = true; | ||
394 | } | ||
395 | |||
396 | if (no_filter != touch->no_filter_param) { | ||
397 | touch->no_filter_param = no_filter; | ||
398 | reset = true; | ||
399 | } | ||
400 | |||
401 | if (reduce_report != touch->reduce_report_param) { | ||
402 | touch->reduce_report_param = reduce_report; | ||
403 | reset = true; | ||
404 | } | ||
405 | |||
406 | if (reset) | ||
407 | synaptics_i2c_reset_config(touch->client); | ||
408 | } | ||
409 | |||
410 | /* Control the Device polling rate / Work Handler sleep time */ | ||
411 | unsigned long synaptics_i2c_adjust_delay(struct synaptics_i2c *touch, | ||
412 | bool have_data) | ||
413 | { | ||
414 | unsigned long delay, nodata_count_thres; | ||
415 | |||
416 | if (polling_req) { | ||
417 | delay = touch->scan_ms; | ||
418 | if (have_data) { | ||
419 | touch->no_data_count = 0; | ||
420 | } else { | ||
421 | nodata_count_thres = NO_DATA_THRES / touch->scan_ms; | ||
422 | if (touch->no_data_count < nodata_count_thres) | ||
423 | touch->no_data_count++; | ||
424 | else | ||
425 | delay = NO_DATA_SLEEP_MSECS; | ||
426 | } | ||
427 | return msecs_to_jiffies(delay); | ||
428 | } else { | ||
429 | delay = msecs_to_jiffies(THREAD_IRQ_SLEEP_MSECS); | ||
430 | return round_jiffies_relative(delay); | ||
431 | } | ||
432 | } | ||
433 | |||
434 | /* Work Handler */ | ||
435 | static void synaptics_i2c_work_handler(struct work_struct *work) | ||
436 | { | ||
437 | bool have_data; | ||
438 | struct synaptics_i2c *touch = | ||
439 | container_of(work, struct synaptics_i2c, dwork.work); | ||
440 | unsigned long delay; | ||
441 | |||
442 | synaptics_i2c_check_params(touch); | ||
443 | |||
444 | have_data = synaptics_i2c_get_input(touch); | ||
445 | delay = synaptics_i2c_adjust_delay(touch, have_data); | ||
446 | |||
447 | /* | ||
448 | * While interrupt driven, there is no real need to poll the device. | ||
449 | * But touchpads are very sensitive, so there could be errors | ||
450 | * related to physical environment and the attention line isn't | ||
451 | * neccesarily asserted. In such case we can lose the touchpad. | ||
452 | * We poll the device once in THREAD_IRQ_SLEEP_SECS and | ||
453 | * if error is detected, we try to reset and reconfigure the touchpad. | ||
454 | */ | ||
455 | schedule_delayed_work(&touch->dwork, delay); | ||
456 | } | ||
457 | |||
458 | static int synaptics_i2c_open(struct input_dev *input) | ||
459 | { | ||
460 | struct synaptics_i2c *touch = input_get_drvdata(input); | ||
461 | int ret; | ||
462 | |||
463 | ret = synaptics_i2c_reset_config(touch->client); | ||
464 | if (ret) | ||
465 | return ret; | ||
466 | |||
467 | if (polling_req) | ||
468 | schedule_delayed_work(&touch->dwork, | ||
469 | msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); | ||
470 | |||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | static void synaptics_i2c_close(struct input_dev *input) | ||
475 | { | ||
476 | struct synaptics_i2c *touch = input_get_drvdata(input); | ||
477 | |||
478 | if (!polling_req) | ||
479 | synaptics_i2c_reg_set(touch->client, INTERRUPT_EN_REG, 0); | ||
480 | |||
481 | cancel_delayed_work_sync(&touch->dwork); | ||
482 | |||
483 | /* Save some power */ | ||
484 | synaptics_i2c_reg_set(touch->client, DEV_CONTROL_REG, DEEP_SLEEP); | ||
485 | } | ||
486 | |||
487 | static void synaptics_i2c_set_input_params(struct synaptics_i2c *touch) | ||
488 | { | ||
489 | struct input_dev *input = touch->input; | ||
490 | |||
491 | input->name = touch->client->name; | ||
492 | input->phys = touch->client->adapter->name; | ||
493 | input->id.bustype = BUS_I2C; | ||
494 | input->id.version = synaptics_i2c_word_get(touch->client, | ||
495 | INFO_QUERY_REG0); | ||
496 | input->dev.parent = &touch->client->dev; | ||
497 | input->open = synaptics_i2c_open; | ||
498 | input->close = synaptics_i2c_close; | ||
499 | input_set_drvdata(input, touch); | ||
500 | |||
501 | /* Register the device as mouse */ | ||
502 | __set_bit(EV_REL, input->evbit); | ||
503 | __set_bit(REL_X, input->relbit); | ||
504 | __set_bit(REL_Y, input->relbit); | ||
505 | |||
506 | /* Register device's buttons and keys */ | ||
507 | __set_bit(EV_KEY, input->evbit); | ||
508 | __set_bit(BTN_LEFT, input->keybit); | ||
509 | } | ||
510 | |||
511 | struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *client) | ||
512 | { | ||
513 | struct synaptics_i2c *touch; | ||
514 | |||
515 | touch = kzalloc(sizeof(struct synaptics_i2c), GFP_KERNEL); | ||
516 | if (!touch) | ||
517 | return NULL; | ||
518 | |||
519 | touch->client = client; | ||
520 | touch->no_decel_param = no_decel; | ||
521 | touch->scan_rate_param = scan_rate; | ||
522 | set_scan_rate(touch, scan_rate); | ||
523 | INIT_DELAYED_WORK(&touch->dwork, synaptics_i2c_work_handler); | ||
524 | |||
525 | return touch; | ||
526 | } | ||
527 | |||
528 | static int __devinit synaptics_i2c_probe(struct i2c_client *client, | ||
529 | const struct i2c_device_id *dev_id) | ||
530 | { | ||
531 | int ret; | ||
532 | struct synaptics_i2c *touch; | ||
533 | |||
534 | touch = synaptics_i2c_touch_create(client); | ||
535 | if (!touch) | ||
536 | return -ENOMEM; | ||
537 | |||
538 | i2c_set_clientdata(client, touch); | ||
539 | |||
540 | ret = synaptics_i2c_reset_config(client); | ||
541 | if (ret) | ||
542 | goto err_mem_free; | ||
543 | |||
544 | if (client->irq < 1) | ||
545 | polling_req = 1; | ||
546 | |||
547 | touch->input = input_allocate_device(); | ||
548 | if (!touch->input) { | ||
549 | ret = -ENOMEM; | ||
550 | goto err_mem_free; | ||
551 | } | ||
552 | |||
553 | synaptics_i2c_set_input_params(touch); | ||
554 | |||
555 | if (!polling_req) { | ||
556 | dev_dbg(&touch->client->dev, | ||
557 | "Requesting IRQ: %d\n", touch->client->irq); | ||
558 | |||
559 | ret = request_irq(touch->client->irq, synaptics_i2c_irq, | ||
560 | IRQF_DISABLED|IRQ_TYPE_EDGE_FALLING, | ||
561 | DRIVER_NAME, touch); | ||
562 | if (ret) { | ||
563 | dev_warn(&touch->client->dev, | ||
564 | "IRQ request failed: %d, " | ||
565 | "falling back to polling\n", ret); | ||
566 | polling_req = 1; | ||
567 | synaptics_i2c_reg_set(touch->client, | ||
568 | INTERRUPT_EN_REG, 0); | ||
569 | } | ||
570 | } | ||
571 | |||
572 | if (polling_req) | ||
573 | dev_dbg(&touch->client->dev, | ||
574 | "Using polling at rate: %d times/sec\n", scan_rate); | ||
575 | |||
576 | /* Register the device in input subsystem */ | ||
577 | ret = input_register_device(touch->input); | ||
578 | if (ret) { | ||
579 | dev_err(&client->dev, | ||
580 | "Input device register failed: %d\n", ret); | ||
581 | goto err_input_free; | ||
582 | } | ||
583 | return 0; | ||
584 | |||
585 | err_input_free: | ||
586 | input_free_device(touch->input); | ||
587 | err_mem_free: | ||
588 | i2c_set_clientdata(client, NULL); | ||
589 | kfree(touch); | ||
590 | |||
591 | return ret; | ||
592 | } | ||
593 | |||
594 | static int __devexit synaptics_i2c_remove(struct i2c_client *client) | ||
595 | { | ||
596 | struct synaptics_i2c *touch = i2c_get_clientdata(client); | ||
597 | |||
598 | if (!polling_req) | ||
599 | free_irq(touch->client->irq, touch); | ||
600 | |||
601 | input_unregister_device(touch->input); | ||
602 | i2c_set_clientdata(client, NULL); | ||
603 | kfree(touch); | ||
604 | |||
605 | return 0; | ||
606 | } | ||
607 | |||
608 | #ifdef CONFIG_PM | ||
609 | static int synaptics_i2c_suspend(struct i2c_client *client, pm_message_t mesg) | ||
610 | { | ||
611 | struct synaptics_i2c *touch = i2c_get_clientdata(client); | ||
612 | |||
613 | cancel_delayed_work_sync(&touch->dwork); | ||
614 | |||
615 | /* Save some power */ | ||
616 | synaptics_i2c_reg_set(touch->client, DEV_CONTROL_REG, DEEP_SLEEP); | ||
617 | |||
618 | return 0; | ||
619 | } | ||
620 | |||
621 | static int synaptics_i2c_resume(struct i2c_client *client) | ||
622 | { | ||
623 | int ret; | ||
624 | struct synaptics_i2c *touch = i2c_get_clientdata(client); | ||
625 | |||
626 | ret = synaptics_i2c_reset_config(client); | ||
627 | if (ret) | ||
628 | return ret; | ||
629 | |||
630 | schedule_delayed_work(&touch->dwork, | ||
631 | msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); | ||
632 | |||
633 | return 0; | ||
634 | } | ||
635 | #else | ||
636 | #define synaptics_i2c_suspend NULL | ||
637 | #define synaptics_i2c_resume NULL | ||
638 | #endif | ||
639 | |||
640 | static const struct i2c_device_id synaptics_i2c_id_table[] = { | ||
641 | { "synaptics_i2c", 0 }, | ||
642 | { }, | ||
643 | }; | ||
644 | MODULE_DEVICE_TABLE(i2c, synaptics_i2c_id_table); | ||
645 | |||
646 | static struct i2c_driver synaptics_i2c_driver = { | ||
647 | .driver = { | ||
648 | .name = DRIVER_NAME, | ||
649 | .owner = THIS_MODULE, | ||
650 | }, | ||
651 | |||
652 | .probe = synaptics_i2c_probe, | ||
653 | .remove = __devexit_p(synaptics_i2c_remove), | ||
654 | |||
655 | .suspend = synaptics_i2c_suspend, | ||
656 | .resume = synaptics_i2c_resume, | ||
657 | .id_table = synaptics_i2c_id_table, | ||
658 | }; | ||
659 | |||
660 | static int __init synaptics_i2c_init(void) | ||
661 | { | ||
662 | return i2c_add_driver(&synaptics_i2c_driver); | ||
663 | } | ||
664 | |||
665 | static void __exit synaptics_i2c_exit(void) | ||
666 | { | ||
667 | i2c_del_driver(&synaptics_i2c_driver); | ||
668 | } | ||
669 | |||
670 | module_init(synaptics_i2c_init); | ||
671 | module_exit(synaptics_i2c_exit); | ||
672 | |||
673 | MODULE_DESCRIPTION("Synaptics I2C touchpad driver"); | ||
674 | MODULE_AUTHOR("Mike Rapoport, Igor Grinberg, Compulab"); | ||
675 | MODULE_LICENSE("GPL"); | ||
676 | |||