aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTai-hwa Liang <avatar@sentelic.com>2009-05-10 21:15:39 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2009-08-20 00:46:09 -0400
commitfc69f4a6af49ee69475dc4217924d9edf77760e0 (patch)
tree2b200846dc0848e8fa85f439d9a1c98652356348
parent3b72094409ab673d096b3852f4636be540780faf (diff)
Input: add new driver for Sentelic Finger Sensing Pad
This is the driver for Sentelic Finger Sensing Pad which can be found on MSI WIND Netbook. Signed-off-by: Tai-hwa Liang <avatar@sentelic.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-rw-r--r--Documentation/input/sentelic.txt475
-rw-r--r--drivers/input/mouse/Kconfig8
-rw-r--r--drivers/input/mouse/Makefile1
-rw-r--r--drivers/input/mouse/psmouse-base.c26
-rw-r--r--drivers/input/mouse/psmouse.h1
-rw-r--r--drivers/input/mouse/sentelic.c867
-rw-r--r--drivers/input/mouse/sentelic.h98
-rw-r--r--drivers/input/serio/libps2.c15
-rw-r--r--include/linux/libps2.h1
9 files changed, 1488 insertions, 4 deletions
diff --git a/Documentation/input/sentelic.txt b/Documentation/input/sentelic.txt
new file mode 100644
index 000000000000..f7160a2fb6a2
--- /dev/null
+++ b/Documentation/input/sentelic.txt
@@ -0,0 +1,475 @@
1Copyright (C) 2002-2008 Sentelic Corporation.
2Last update: Oct-31-2008
3
4==============================================================================
5* Finger Sensing Pad Intellimouse Mode(scrolling wheel, 4th and 5th buttons)
6==============================================================================
7A) MSID 4: Scrolling wheel mode plus Forward page(4th button) and Backward
8 page (5th button)
9@1. Set sample rate to 200;
10@2. Set sample rate to 200;
11@3. Set sample rate to 80;
12@4. Issuing the "Get device ID" command (0xF2) and waits for the response;
13@5. FSP will respond 0x04.
14
15Packet 1
16 Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
17BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
18 1 |Y|X|y|x|1|M|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 | | |B|F|W|W|W|W|
19 |---------------| |---------------| |---------------| |---------------|
20
21Byte 1: Bit7 => Y overflow
22 Bit6 => X overflow
23 Bit5 => Y sign bit
24 Bit4 => X sign bit
25 Bit3 => 1
26 Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
27 Bit1 => Right Button, 1 is pressed, 0 is not pressed.
28 Bit0 => Left Button, 1 is pressed, 0 is not pressed.
29Byte 2: X Movement(9-bit 2's complement integers)
30Byte 3: Y Movement(9-bit 2's complement integers)
31Byte 4: Bit3~Bit0 => the scrolling wheel's movement since the last data report.
32 valid values, -8 ~ +7
33 Bit4 => 1 = 4th mouse button is pressed, Forward one page.
34 0 = 4th mouse button is not pressed.
35 Bit5 => 1 = 5th mouse button is pressed, Backward one page.
36 0 = 5th mouse button is not pressed.
37
38B) MSID 6: Horizontal and Vertical scrolling.
39@ Set bit 1 in register 0x40 to 1
40
41# FSP replaces scrolling wheel's movement as 4 bits to show horizontal and
42 vertical scrolling.
43
44Packet 1
45 Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
46BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
47 1 |Y|X|y|x|1|M|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 | | |B|F|l|r|u|d|
48 |---------------| |---------------| |---------------| |---------------|
49
50Byte 1: Bit7 => Y overflow
51 Bit6 => X overflow
52 Bit5 => Y sign bit
53 Bit4 => X sign bit
54 Bit3 => 1
55 Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
56 Bit1 => Right Button, 1 is pressed, 0 is not pressed.
57 Bit0 => Left Button, 1 is pressed, 0 is not pressed.
58Byte 2: X Movement(9-bit 2's complement integers)
59Byte 3: Y Movement(9-bit 2's complement integers)
60Byte 4: Bit0 => the Vertical scrolling movement downward.
61 Bit1 => the Vertical scrolling movement upward.
62 Bit2 => the Vertical scrolling movement rightward.
63 Bit3 => the Vertical scrolling movement leftward.
64 Bit4 => 1 = 4th mouse button is pressed, Forward one page.
65 0 = 4th mouse button is not pressed.
66 Bit5 => 1 = 5th mouse button is pressed, Backward one page.
67 0 = 5th mouse button is not pressed.
68
69C) MSID 7:
70# FSP uses 2 packets(8 Bytes) data to represent Absolute Position
71 so we have PACKET NUMBER to identify packets.
72 If PACKET NUMBER is 0, the packet is Packet 1.
73 If PACKET NUMBER is 1, the packet is Packet 2.
74 Please count this number in program.
75
76# MSID6 special packet will be enable at the same time when enable MSID 7.
77
78==============================================================================
79* Absolute position for STL3886-G0.
80==============================================================================
81@ Set bit 2 or 3 in register 0x40 to 1
82@ Set bit 6 in register 0x40 to 1
83
84Packet 1 (ABSOLUTE POSITION)
85 Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
86BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
87 1 |0|1|V|1|1|M|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 |r|l|d|u|X|X|Y|Y|
88 |---------------| |---------------| |---------------| |---------------|
89
90Byte 1: Bit7~Bit6 => 00, Normal data packet
91 => 01, Absolute coordination packet
92 => 10, Notify packet
93 Bit5 => valid bit
94 Bit4 => 1
95 Bit3 => 1
96 Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
97 Bit1 => Right Button, 1 is pressed, 0 is not pressed.
98 Bit0 => Left Button, 1 is pressed, 0 is not pressed.
99Byte 2: X coordinate (xpos[9:2])
100Byte 3: Y coordinate (ypos[9:2])
101Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
102 Bit3~Bit2 => X coordinate (ypos[1:0])
103 Bit4 => scroll up
104 Bit5 => scroll down
105 Bit6 => scroll left
106 Bit7 => scroll right
107
108Notify Packet for G0
109 Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
110BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
111 1 |1|0|0|1|1|M|R|L| 2 |C|C|C|C|C|C|C|C| 3 |M|M|M|M|M|M|M|M| 4 |0|0|0|0|0|0|0|0|
112 |---------------| |---------------| |---------------| |---------------|
113
114Byte 1: Bit7~Bit6 => 00, Normal data packet
115 => 01, Absolute coordination packet
116 => 10, Notify packet
117 Bit5 => 0
118 Bit4 => 1
119 Bit3 => 1
120 Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
121 Bit1 => Right Button, 1 is pressed, 0 is not pressed.
122 Bit0 => Left Button, 1 is pressed, 0 is not pressed.
123Byte 2: Message Type => 0x5A (Enable/Disable status packet)
124 Mode Type => 0xA5 (Normal/Icon mode status)
125Byte 3: Message Type => 0x00 (Disabled)
126 => 0x01 (Enabled)
127 Mode Type => 0x00 (Normal)
128 => 0x01 (Icon)
129Byte 4: Bit7~Bit0 => Don't Care
130
131==============================================================================
132* Absolute position for STL3888-A0.
133==============================================================================
134Packet 1 (ABSOLUTE POSITION)
135 Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
136BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
137 1 |0|1|V|A|1|L|0|1| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 |x|x|y|y|X|X|Y|Y|
138 |---------------| |---------------| |---------------| |---------------|
139
140Byte 1: Bit7~Bit6 => 00, Normal data packet
141 => 01, Absolute coordination packet
142 => 10, Notify packet
143 Bit5 => Valid bit, 0 means that the coordinate is invalid or finger up.
144 When both fingers are up, the last two reports have zero valid
145 bit.
146 Bit4 => arc
147 Bit3 => 1
148 Bit2 => Left Button, 1 is pressed, 0 is released.
149 Bit1 => 0
150 Bit0 => 1
151Byte 2: X coordinate (xpos[9:2])
152Byte 3: Y coordinate (ypos[9:2])
153Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
154 Bit3~Bit2 => X coordinate (ypos[1:0])
155 Bit5~Bit4 => y1_g
156 Bit7~Bit6 => x1_g
157
158Packet 2 (ABSOLUTE POSITION)
159 Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
160BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
161 1 |0|1|V|A|1|R|1|0| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 |x|x|y|y|X|X|Y|Y|
162 |---------------| |---------------| |---------------| |---------------|
163
164Byte 1: Bit7~Bit6 => 00, Normal data packet
165 => 01, Absolute coordinates packet
166 => 10, Notify packet
167 Bit5 => Valid bit, 0 means that the coordinate is invalid or finger up.
168 When both fingers are up, the last two reports have zero valid
169 bit.
170 Bit4 => arc
171 Bit3 => 1
172 Bit2 => Right Button, 1 is pressed, 0 is released.
173 Bit1 => 1
174 Bit0 => 0
175Byte 2: X coordinate (xpos[9:2])
176Byte 3: Y coordinate (ypos[9:2])
177Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
178 Bit3~Bit2 => X coordinate (ypos[1:0])
179 Bit5~Bit4 => y2_g
180 Bit7~Bit6 => x2_g
181
182Notify Packet for STL3888-A0
183 Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
184BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
185 1 |1|0|1|P|1|M|R|L| 2 |C|C|C|C|C|C|C|C| 3 |0|0|F|F|0|0|0|i| 4 |r|l|d|u|0|0|0|0|
186 |---------------| |---------------| |---------------| |---------------|
187
188Byte 1: Bit7~Bit6 => 00, Normal data packet
189 => 01, Absolute coordination packet
190 => 10, Notify packet
191 Bit5 => 1
192 Bit4 => when in absolute coordinates mode (valid when EN_PKT_GO is 1):
193 0: left button is generated by the on-pad command
194 1: left button is generated by the external button
195 Bit3 => 1
196 Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
197 Bit1 => Right Button, 1 is pressed, 0 is not pressed.
198 Bit0 => Left Button, 1 is pressed, 0 is not pressed.
199Byte 2: Message Type => 0xB7 (Multi Finger, Multi Coordinate mode)
200Byte 3: Bit7~Bit6 => Don't care
201 Bit5~Bit4 => Number of fingers
202 Bit3~Bit1 => Reserved
203 Bit0 => 1: enter gesture mode; 0: leaving gesture mode
204Byte 4: Bit7 => scroll right button
205 Bit6 => scroll left button
206 Bit5 => scroll down button
207 Bit4 => scroll up button
208 * Note that if gesture and additional button (Bit4~Bit7)
209 happen at the same time, the button information will not
210 be sent.
211 Bit3~Bit0 => Reserved
212
213Sample sequence of Multi-finger, Multi-coordinate mode:
214
215 notify packet (valid bit == 1), abs pkt 1, abs pkt 2, abs pkt 1,
216 abs pkt 2, ..., notify packet(valid bit == 0)
217
218==============================================================================
219* FSP Enable/Disable packet
220==============================================================================
221 Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
222BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
223 1 |Y|X|0|0|1|M|R|L| 2 |0|1|0|1|1|0|1|E| 3 | | | | | | | | | 4 | | | | | | | | |
224 |---------------| |---------------| |---------------| |---------------|
225
226FSP will send out enable/disable packet when FSP receive PS/2 enable/disable
227command. Host will receive the packet which Middle, Right, Left button will
228be set. The packet only use byte 0 and byte 1 as a pattern of original packet.
229Ignore the other bytes of the packet.
230
231Byte 1: Bit7 => 0, Y overflow
232 Bit6 => 0, X overflow
233 Bit5 => 0, Y sign bit
234 Bit4 => 0, X sign bit
235 Bit3 => 1
236 Bit2 => 1, Middle Button
237 Bit1 => 1, Right Button
238 Bit0 => 1, Left Button
239Byte 2: Bit7~1 => (0101101b)
240 Bit0 => 1 = Enable
241 0 = Disable
242Byte 3: Don't care
243Byte 4: Don't care (MOUSE ID 3, 4)
244Byte 5~8: Don't care (Absolute packet)
245
246==============================================================================
247* PS/2 Command Set
248==============================================================================
249
250FSP supports basic PS/2 commanding set and modes, refer to following URL for
251details about PS/2 commands:
252
253http://www.computer-engineering.org/index.php?title=PS/2_Mouse_Interface
254
255==============================================================================
256* Programming Sequence for Determining Packet Parsing Flow
257==============================================================================
2581. Identify FSP by reading device ID(0x00) and version(0x01) register
259
2602. Determine number of buttons by reading status2 (0x0b) register
261
262 buttons = reg[0x0b] & 0x30
263
264 if buttons == 0x30 or buttons == 0x20:
265 # two/four buttons
266 Refer to 'Finger Sensing Pad PS/2 Mouse Intellimouse'
267 section A for packet parsing detail(ignore byte 4, bit ~ 7)
268 elif buttons == 0x10:
269 # 6 buttons
270 Refer to 'Finger Sensing Pad PS/2 Mouse Intellimouse'
271 section B for packet parsing detail
272 elif buttons == 0x00:
273 # 6 buttons
274 Refer to 'Finger Sensing Pad PS/2 Mouse Intellimouse'
275 section A for packet parsing detail
276
277==============================================================================
278* Programming Sequence for Register Reading/Writing
279==============================================================================
280
281Register inversion requirement:
282
283 Following values needed to be inverted(the '~' operator in C) before being
284sent to FSP:
285
286 0xe9, 0xee, 0xf2 and 0xff.
287
288Register swapping requirement:
289
290 Following values needed to have their higher 4 bits and lower 4 bits being
291swapped before being sent to FSP:
292
293 10, 20, 40, 60, 80, 100 and 200.
294
295Register reading sequence:
296
297 1. send 0xf3 PS/2 command to FSP;
298
299 2. send 0x66 PS/2 command to FSP;
300
301 3. send 0x88 PS/2 command to FSP;
302
303 4. send 0xf3 PS/2 command to FSP;
304
305 5. if the register address being to read is not required to be
306 inverted(refer to the 'Register inversion requirement' section),
307 goto step 6
308
309 5a. send 0x68 PS/2 command to FSP;
310
311 5b. send the inverted register address to FSP and goto step 8;
312
313 6. if the register address being to read is not required to be
314 swapped(refer to the 'Register swapping requirement' section),
315 goto step 7
316
317 6a. send 0xcc PS/2 command to FSP;
318
319 6b. send the swapped register address to FSP and goto step 8;
320
321 7. send 0x66 PS/2 command to FSP;
322
323 7a. send the original register address to FSP and goto step 8;
324
325 8. send 0xe9(status request) PS/2 command to FSP;
326
327 9. the response read from FSP should be the requested register value.
328
329Register writing sequence:
330
331 1. send 0xf3 PS/2 command to FSP;
332
333 2. if the register address being to write is not required to be
334 inverted(refer to the 'Register inversion requirement' section),
335 goto step 3
336
337 2a. send 0x74 PS/2 command to FSP;
338
339 2b. send the inverted register address to FSP and goto step 5;
340
341 3. if the register address being to write is not required to be
342 swapped(refer to the 'Register swapping requirement' section),
343 goto step 4
344
345 3a. send 0x77 PS/2 command to FSP;
346
347 3b. send the swapped register address to FSP and goto step 5;
348
349 4. send 0x55 PS/2 command to FSP;
350
351 4a. send the register address to FSP and goto step 5;
352
353 5. send 0xf3 PS/2 command to FSP;
354
355 6. if the register value being to write is not required to be
356 inverted(refer to the 'Register inversion requirement' section),
357 goto step 7
358
359 6a. send 0x47 PS/2 command to FSP;
360
361 6b. send the inverted register value to FSP and goto step 9;
362
363 7. if the register value being to write is not required to be
364 swapped(refer to the 'Register swapping requirement' section),
365 goto step 8
366
367 7a. send 0x44 PS/2 command to FSP;
368
369 7b. send the swapped register value to FSP and goto step 9;
370
371 8. send 0x33 PS/2 command to FSP;
372
373 8a. send the register value to FSP;
374
375 9. the register writing sequence is completed.
376
377==============================================================================
378* Register Listing
379==============================================================================
380
381offset width default r/w name
3820x00 bit7~bit0 0x01 RO device ID
383
3840x01 bit7~bit0 0xc0 RW version ID
385
3860x02 bit7~bit0 0x01 RO vendor ID
387
3880x03 bit7~bit0 0x01 RO product ID
389
3900x04 bit3~bit0 0x01 RW revision ID
391
3920x0b RO test mode status 1
393 bit3 1 RO 0: rotate 180 degree, 1: no rotation
394
395 bit5~bit4 RO number of buttons
396 11 => 2, lbtn/rbtn
397 10 => 4, lbtn/rbtn/scru/scrd
398 01 => 6, lbtn/rbtn/scru/scrd/scrl/scrr
399 00 => 6, lbtn/rbtn/scru/scrd/fbtn/bbtn
400
4010x0f RW register file page control
402 bit0 0 RW 1 to enable page 1 register files
403
4040x10 RW system control 1
405 bit0 1 RW Reserved, must be 1
406 bit1 0 RW Reserved, must be 0
407 bit4 1 RW Reserved, must be 0
408 bit5 0 RW register clock gating enable
409 0: read only, 1: read/write enable
410 (Note that following registers does not require clock gating being
411 enabled prior to write: 05 06 07 08 09 0c 0f 10 11 12 16 17 18 23 2e
412 40 41 42 43.)
413
4140x31 RW on-pad command detection
415 bit7 0 RW on-pad command left button down tag
416 enable
417 0: disable, 1: enable
418
4190x34 RW on-pad command control 5
420 bit4~bit0 0x05 RW XLO in 0s/4/1, so 03h = 0010.1b = 2.5
421 (Note that position unit is in 0.5 scanline)
422
423 bit7 0 RW on-pad tap zone enable
424 0: disable, 1: enable
425
4260x35 RW on-pad command control 6
427 bit4~bit0 0x1d RW XHI in 0s/4/1, so 19h = 1100.1b = 12.5
428 (Note that position unit is in 0.5 scanline)
429
4300x36 RW on-pad command control 7
431 bit4~bit0 0x04 RW YLO in 0s/4/1, so 03h = 0010.1b = 2.5
432 (Note that position unit is in 0.5 scanline)
433
4340x37 RW on-pad command control 8
435 bit4~bit0 0x13 RW YHI in 0s/4/1, so 11h = 1000.1b = 8.5
436 (Note that position unit is in 0.5 scanline)
437
4380x40 RW system control 5
439 bit1 0 RW FSP Intellimouse mode enable
440 0: disable, 1: enable
441
442 bit2 0 RW movement + abs. coordinate mode enable
443 0: disable, 1: enable
444 (Note that this function has the functionality of bit 1 even when
445 bit 1 is not set. However, the format is different from that of bit 1.
446 In addition, when bit 1 and bit 2 are set at the same time, bit 2 will
447 override bit 1.)
448
449 bit3 0 RW abs. coordinate only mode enable
450 0: disable, 1: enable
451 (Note that this function has the functionality of bit 1 even when
452 bit 1 is not set. However, the format is different from that of bit 1.
453 In addition, when bit 1, bit 2 and bit 3 are set at the same time,
454 bit 3 will override bit 1 and 2.)
455
456 bit5 0 RW auto switch enable
457 0: disable, 1: enable
458
459 bit6 0 RW G0 abs. + notify packet format enable
460 0: disable, 1: enable
461 (Note that the absolute/relative coordinate output still depends on
462 bit 2 and 3. That is, if any of those bit is 1, host will receive
463 absolute coordinates; otherwise, host only receives packets with
464 relative coordinate.)
465
4660x43 RW on-pad control
467 bit0 0 RW on-pad control enable
468 0: disable, 1: enable
469 (Note that if this bit is cleared, bit 3/5 will be ineffective)
470
471 bit3 0 RW on-pad fix vertical scrolling enable
472 0: disable, 1: enable
473
474 bit5 0 RW on-pad fix horizontal scrolling enable
475 0: disable, 1: enable
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 90bef5d498f0..3feeb3af8abd 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -107,6 +107,14 @@ config MOUSE_PS2_ELANTECH
107 entries. For further information, 107 entries. For further information,
108 see <file:Documentation/input/elantech.txt>. 108 see <file:Documentation/input/elantech.txt>.
109 109
110config MOUSE_PS2_SENTELIC
111 bool "Sentelic Finger Sensing Pad PS/2 protocol extension"
112 depends on MOUSE_PS2
113 help
114 Say Y here if you have a laptop (such as MSI WIND Netbook)
115 with Sentelic Finger Sensing Pad touchpad.
116
117 If unsure, say N.
110 118
111config MOUSE_PS2_TOUCHKIT 119config MOUSE_PS2_TOUCHKIT
112 bool "eGalax TouchKit PS/2 protocol extension" 120 bool "eGalax TouchKit PS/2 protocol extension"
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index ea58c9a372b6..570c84a4a654 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -27,5 +27,6 @@ psmouse-$(CONFIG_MOUSE_PS2_ELANTECH) += elantech.o
27psmouse-$(CONFIG_MOUSE_PS2_OLPC) += hgpk.o 27psmouse-$(CONFIG_MOUSE_PS2_OLPC) += hgpk.o
28psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o 28psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o
29psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o 29psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o
30psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o
30psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o 31psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o
31psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o 32psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index b407b355dceb..df318887ca09 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -30,6 +30,7 @@
30#include "trackpoint.h" 30#include "trackpoint.h"
31#include "touchkit_ps2.h" 31#include "touchkit_ps2.h"
32#include "elantech.h" 32#include "elantech.h"
33#include "sentelic.h"
33 34
34#define DRIVER_DESC "PS/2 mouse driver" 35#define DRIVER_DESC "PS/2 mouse driver"
35 36
@@ -666,6 +667,20 @@ static int psmouse_extensions(struct psmouse *psmouse,
666 max_proto = PSMOUSE_IMEX; 667 max_proto = PSMOUSE_IMEX;
667 } 668 }
668 669
670/*
671 * Try Finger Sensing Pad
672 */
673 if (max_proto > PSMOUSE_IMEX) {
674 if (fsp_detect(psmouse, set_properties) == 0) {
675 if (!set_properties || fsp_init(psmouse) == 0)
676 return PSMOUSE_FSP;
677/*
678 * Init failed, try basic relative protocols
679 */
680 max_proto = PSMOUSE_IMEX;
681 }
682 }
683
669 if (max_proto > PSMOUSE_IMEX) { 684 if (max_proto > PSMOUSE_IMEX) {
670 if (genius_detect(psmouse, set_properties) == 0) 685 if (genius_detect(psmouse, set_properties) == 0)
671 return PSMOUSE_GENPS; 686 return PSMOUSE_GENPS;
@@ -813,7 +828,16 @@ static const struct psmouse_protocol psmouse_protocols[] = {
813 .detect = elantech_detect, 828 .detect = elantech_detect,
814 .init = elantech_init, 829 .init = elantech_init,
815 }, 830 },
816 #endif 831#endif
832#ifdef CONFIG_MOUSE_PS2_SENTELIC
833 {
834 .type = PSMOUSE_FSP,
835 .name = "FSPPS/2",
836 .alias = "fsp",
837 .detect = fsp_detect,
838 .init = fsp_init,
839 },
840#endif
817 { 841 {
818 .type = PSMOUSE_CORTRON, 842 .type = PSMOUSE_CORTRON,
819 .name = "CortronPS/2", 843 .name = "CortronPS/2",
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index e3562daeb2ed..cca1744c2a08 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -91,6 +91,7 @@ enum psmouse_type {
91 PSMOUSE_CORTRON, 91 PSMOUSE_CORTRON,
92 PSMOUSE_HGPK, 92 PSMOUSE_HGPK,
93 PSMOUSE_ELANTECH, 93 PSMOUSE_ELANTECH,
94 PSMOUSE_FSP,
94 PSMOUSE_AUTO /* This one should always be last */ 95 PSMOUSE_AUTO /* This one should always be last */
95}; 96};
96 97
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c
new file mode 100644
index 000000000000..97b1e72855a0
--- /dev/null
+++ b/drivers/input/mouse/sentelic.c
@@ -0,0 +1,867 @@
1/*-
2 * Finger Sensing Pad PS/2 mouse driver.
3 *
4 * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd.
5 * Copyright (C) 2005-2009 Tai-hwa Liang, Sentelic Corporation.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include <linux/module.h>
23#include <linux/version.h>
24#include <linux/input.h>
25#include <linux/ctype.h>
26#include <linux/libps2.h>
27#include <linux/serio.h>
28#include <linux/jiffies.h>
29
30#include "psmouse.h"
31#include "sentelic.h"
32
33/*
34 * Timeout for FSP PS/2 command only (in milliseconds).
35 */
36#define FSP_CMD_TIMEOUT 200
37#define FSP_CMD_TIMEOUT2 30
38
39/** Driver version. */
40static const char fsp_drv_ver[] = "1.0.0-K";
41
42/*
43 * Make sure that the value being sent to FSP will not conflict with
44 * possible sample rate values.
45 */
46static unsigned char fsp_test_swap_cmd(unsigned char reg_val)
47{
48 switch (reg_val) {
49 case 10: case 20: case 40: case 60: case 80: case 100: case 200:
50 /*
51 * The requested value being sent to FSP matched to possible
52 * sample rates, swap the given value such that the hardware
53 * wouldn't get confused.
54 */
55 return (reg_val >> 4) | (reg_val << 4);
56 default:
57 return reg_val; /* swap isn't necessary */
58 }
59}
60
61/*
62 * Make sure that the value being sent to FSP will not conflict with certain
63 * commands.
64 */
65static unsigned char fsp_test_invert_cmd(unsigned char reg_val)
66{
67 switch (reg_val) {
68 case 0xe9: case 0xee: case 0xf2: case 0xff:
69 /*
70 * The requested value being sent to FSP matched to certain
71 * commands, inverse the given value such that the hardware
72 * wouldn't get confused.
73 */
74 return ~reg_val;
75 default:
76 return reg_val; /* inversion isn't necessary */
77 }
78}
79
80static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val)
81{
82 struct ps2dev *ps2dev = &psmouse->ps2dev;
83 unsigned char param[3];
84 unsigned char addr;
85 int rc = -1;
86
87 /*
88 * We need to shut off the device and switch it into command
89 * mode so we don't confuse our protocol handler. We don't need
90 * to do that for writes because sysfs set helper does this for
91 * us.
92 */
93 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE);
94 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
95 mutex_lock(&ps2dev->cmd_mutex);
96
97 if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
98 goto out;
99
100 /* should return 0xfe(request for resending) */
101 ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2);
102 /* should return 0xfc(failed) */
103 ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2);
104
105 if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
106 goto out;
107
108 if ((addr = fsp_test_invert_cmd(reg_addr)) != reg_addr) {
109 ps2_sendbyte(ps2dev, 0x68, FSP_CMD_TIMEOUT2);
110 } else if ((addr = fsp_test_swap_cmd(reg_addr)) != reg_addr) {
111 /* swapping is required */
112 ps2_sendbyte(ps2dev, 0xcc, FSP_CMD_TIMEOUT2);
113 /* expect 0xfe */
114 } else {
115 /* swapping isn't necessary */
116 ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2);
117 /* expect 0xfe */
118 }
119 /* should return 0xfc(failed) */
120 ps2_sendbyte(ps2dev, addr, FSP_CMD_TIMEOUT);
121
122 if (__ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO) < 0)
123 goto out;
124
125 *reg_val = param[2];
126 rc = 0;
127
128 out:
129 mutex_unlock(&ps2dev->cmd_mutex);
130 ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
131 psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
132 dev_dbg(&ps2dev->serio->dev, "READ REG: 0x%02x is 0x%02x (rc = %d)\n",
133 reg_addr, *reg_val, rc);
134 return rc;
135}
136
137static int fsp_reg_write(struct psmouse *psmouse, int reg_addr, int reg_val)
138{
139 struct ps2dev *ps2dev = &psmouse->ps2dev;
140 unsigned char v;
141 int rc = -1;
142
143 mutex_lock(&ps2dev->cmd_mutex);
144
145 if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
146 goto out;
147
148 if ((v = fsp_test_invert_cmd(reg_addr)) != reg_addr) {
149 /* inversion is required */
150 ps2_sendbyte(ps2dev, 0x74, FSP_CMD_TIMEOUT2);
151 } else {
152 if ((v = fsp_test_swap_cmd(reg_addr)) != reg_addr) {
153 /* swapping is required */
154 ps2_sendbyte(ps2dev, 0x77, FSP_CMD_TIMEOUT2);
155 } else {
156 /* swapping isn't necessary */
157 ps2_sendbyte(ps2dev, 0x55, FSP_CMD_TIMEOUT2);
158 }
159 }
160 /* write the register address in correct order */
161 ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2);
162
163 if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
164 return -1;
165
166 if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) {
167 /* inversion is required */
168 ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2);
169 } else if ((v = fsp_test_swap_cmd(reg_val)) != reg_val) {
170 /* swapping is required */
171 ps2_sendbyte(ps2dev, 0x44, FSP_CMD_TIMEOUT2);
172 } else {
173 /* swapping isn't necessary */
174 ps2_sendbyte(ps2dev, 0x33, FSP_CMD_TIMEOUT2);
175 }
176
177 /* write the register value in correct order */
178 ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2);
179 rc = 0;
180
181 out:
182 mutex_unlock(&ps2dev->cmd_mutex);
183 dev_dbg(&ps2dev->serio->dev, "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n",
184 reg_addr, reg_val, rc);
185 return rc;
186}
187
188/* Enable register clock gating for writing certain registers */
189static int fsp_reg_write_enable(struct psmouse *psmouse, bool enable)
190{
191 int v, nv;
192
193 if (fsp_reg_read(psmouse, FSP_REG_SYSCTL1, &v) == -1)
194 return -1;
195
196 if (enable)
197 nv = v | FSP_BIT_EN_REG_CLK;
198 else
199 nv = v & ~FSP_BIT_EN_REG_CLK;
200
201 /* only write if necessary */
202 if (nv != v)
203 if (fsp_reg_write(psmouse, FSP_REG_SYSCTL1, nv) == -1)
204 return -1;
205
206 return 0;
207}
208
209static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val)
210{
211 struct ps2dev *ps2dev = &psmouse->ps2dev;
212 unsigned char param[3];
213 int rc = -1;
214
215 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE);
216 psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
217 mutex_lock(&ps2dev->cmd_mutex);
218
219 if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
220 goto out;
221
222 ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2);
223 ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2);
224
225 if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
226 goto out;
227
228 ps2_sendbyte(ps2dev, 0x83, FSP_CMD_TIMEOUT2);
229 ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2);
230
231 /* get the returned result */
232 if (__ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
233 goto out;
234
235 *reg_val = param[2];
236 rc = 0;
237
238 out:
239 mutex_unlock(&ps2dev->cmd_mutex);
240 ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
241 psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
242 dev_dbg(&ps2dev->serio->dev, "READ PAGE REG: 0x%02x (rc = %d)\n",
243 *reg_val, rc);
244 return rc;
245}
246
247static int fsp_page_reg_write(struct psmouse *psmouse, int reg_val)
248{
249 struct ps2dev *ps2dev = &psmouse->ps2dev;
250 unsigned char v;
251 int rc = -1;
252
253 mutex_lock(&ps2dev->cmd_mutex);
254
255 if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
256 goto out;
257
258 ps2_sendbyte(ps2dev, 0x38, FSP_CMD_TIMEOUT2);
259 ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2);
260
261 if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
262 return -1;
263
264 if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) {
265 ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2);
266 } else if ((v = fsp_test_swap_cmd(reg_val)) != reg_val) {
267 /* swapping is required */
268 ps2_sendbyte(ps2dev, 0x44, FSP_CMD_TIMEOUT2);
269 } else {
270 /* swapping isn't necessary */
271 ps2_sendbyte(ps2dev, 0x33, FSP_CMD_TIMEOUT2);
272 }
273
274 ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2);
275 rc = 0;
276
277 out:
278 mutex_unlock(&ps2dev->cmd_mutex);
279 dev_dbg(&ps2dev->serio->dev, "WRITE PAGE REG: to 0x%02x (rc = %d)\n",
280 reg_val, rc);
281 return rc;
282}
283
284static int fsp_get_version(struct psmouse *psmouse, int *version)
285{
286 if (fsp_reg_read(psmouse, FSP_REG_VERSION, version))
287 return -EIO;
288
289 return 0;
290}
291
292static int fsp_get_revision(struct psmouse *psmouse, int *rev)
293{
294 if (fsp_reg_read(psmouse, FSP_REG_REVISION, rev))
295 return -EIO;
296
297 return 0;
298}
299
300static int fsp_get_buttons(struct psmouse *psmouse, int *btn)
301{
302 static const int buttons[] = {
303 0x16, /* Left/Middle/Right/Forward/Backward & Scroll Up/Down */
304 0x06, /* Left/Middle/Right & Scroll Up/Down/Right/Left */
305 0x04, /* Left/Middle/Right & Scroll Up/Down */
306 0x02, /* Left/Middle/Right */
307 };
308 int val;
309
310 if (fsp_reg_read(psmouse, FSP_REG_TMOD_STATUS1, &val) == -1)
311 return -EIO;
312
313 *btn = buttons[(val & 0x30) >> 4];
314 return 0;
315}
316
317/* Enable on-pad command tag output */
318static int fsp_opc_tag_enable(struct psmouse *psmouse, bool enable)
319{
320 int v, nv;
321 int res = 0;
322
323 if (fsp_reg_read(psmouse, FSP_REG_OPC_QDOWN, &v) == -1) {
324 dev_err(&psmouse->ps2dev.serio->dev, "Unable get OPC state.\n");
325 return -EIO;
326 }
327
328 if (enable)
329 nv = v | FSP_BIT_EN_OPC_TAG;
330 else
331 nv = v & ~FSP_BIT_EN_OPC_TAG;
332
333 /* only write if necessary */
334 if (nv != v) {
335 fsp_reg_write_enable(psmouse, true);
336 res = fsp_reg_write(psmouse, FSP_REG_OPC_QDOWN, nv);
337 fsp_reg_write_enable(psmouse, false);
338 }
339
340 if (res != 0) {
341 dev_err(&psmouse->ps2dev.serio->dev,
342 "Unable to enable OPC tag.\n");
343 res = -EIO;
344 }
345
346 return res;
347}
348
349static int fsp_onpad_vscr(struct psmouse *psmouse, bool enable)
350{
351 struct fsp_data *pad = psmouse->private;
352 int val;
353
354 if (fsp_reg_read(psmouse, FSP_REG_ONPAD_CTL, &val))
355 return -EIO;
356
357 pad->vscroll = enable;
358
359 if (enable)
360 val |= (FSP_BIT_FIX_VSCR | FSP_BIT_ONPAD_ENABLE);
361 else
362 val &= ~FSP_BIT_FIX_VSCR;
363
364 if (fsp_reg_write(psmouse, FSP_REG_ONPAD_CTL, val))
365 return -EIO;
366
367 return 0;
368}
369
370static int fsp_onpad_hscr(struct psmouse *psmouse, bool enable)
371{
372 struct fsp_data *pad = psmouse->private;
373 int val, v2;
374
375 if (fsp_reg_read(psmouse, FSP_REG_ONPAD_CTL, &val))
376 return -EIO;
377
378 if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &v2))
379 return -EIO;
380
381 pad->hscroll = enable;
382
383 if (enable) {
384 val |= (FSP_BIT_FIX_HSCR | FSP_BIT_ONPAD_ENABLE);
385 v2 |= FSP_BIT_EN_MSID6;
386 } else {
387 val &= ~FSP_BIT_FIX_HSCR;
388 v2 &= ~(FSP_BIT_EN_MSID6 | FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8);
389 }
390
391 if (fsp_reg_write(psmouse, FSP_REG_ONPAD_CTL, val))
392 return -EIO;
393
394 /* reconfigure horizontal scrolling packet output */
395 if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, v2))
396 return -EIO;
397
398 return 0;
399}
400
401/*
402 * Write device specific initial parameters.
403 *
404 * ex: 0xab 0xcd - write oxcd into register 0xab
405 */
406static ssize_t fsp_attr_set_setreg(struct psmouse *psmouse, void *data,
407 const char *buf, size_t count)
408{
409 unsigned long reg, val;
410 char *rest;
411 ssize_t retval;
412
413 reg = simple_strtoul(buf, &rest, 16);
414 if (rest == buf || *rest != ' ' || reg > 0xff)
415 return -EINVAL;
416
417 if (strict_strtoul(rest + 1, 16, &val) || val > 0xff)
418 return -EINVAL;
419
420 if (fsp_reg_write_enable(psmouse, true))
421 return -EIO;
422
423 retval = fsp_reg_write(psmouse, reg, val) < 0 ? -EIO : count;
424
425 fsp_reg_write_enable(psmouse, false);
426
427 return count;
428}
429
430PSMOUSE_DEFINE_WO_ATTR(setreg, S_IWUSR, NULL, fsp_attr_set_setreg);
431
432static ssize_t fsp_attr_show_getreg(struct psmouse *psmouse,
433 void *data, char *buf)
434{
435 struct fsp_data *pad = psmouse->private;
436
437 return sprintf(buf, "%02x%02x\n", pad->last_reg, pad->last_val);
438}
439
440/*
441 * Read a register from device.
442 *
443 * ex: 0xab -- read content from register 0xab
444 */
445static ssize_t fsp_attr_set_getreg(struct psmouse *psmouse, void *data,
446 const char *buf, size_t count)
447{
448 struct fsp_data *pad = psmouse->private;
449 unsigned long reg;
450 int val;
451
452 if (strict_strtoul(buf, 16, &reg) || reg > 0xff)
453 return -EINVAL;
454
455 if (fsp_reg_read(psmouse, reg, &val))
456 return -EIO;
457
458 pad->last_reg = reg;
459 pad->last_val = val;
460
461 return count;
462}
463
464PSMOUSE_DEFINE_ATTR(getreg, S_IWUSR | S_IRUGO, NULL,
465 fsp_attr_show_getreg, fsp_attr_set_getreg);
466
467static ssize_t fsp_attr_show_pagereg(struct psmouse *psmouse,
468 void *data, char *buf)
469{
470 int val = 0;
471
472 if (fsp_page_reg_read(psmouse, &val))
473 return -EIO;
474
475 return sprintf(buf, "%02x\n", val);
476}
477
478static ssize_t fsp_attr_set_pagereg(struct psmouse *psmouse, void *data,
479 const char *buf, size_t count)
480{
481 unsigned long val;
482
483 if (strict_strtoul(buf, 16, &val) || val > 0xff)
484 return -EINVAL;
485
486 if (fsp_page_reg_write(psmouse, val))
487 return -EIO;
488
489 return count;
490}
491
492PSMOUSE_DEFINE_ATTR(page, S_IWUSR | S_IRUGO, NULL,
493 fsp_attr_show_pagereg, fsp_attr_set_pagereg);
494
495static ssize_t fsp_attr_show_vscroll(struct psmouse *psmouse,
496 void *data, char *buf)
497{
498 struct fsp_data *pad = psmouse->private;
499
500 return sprintf(buf, "%d\n", pad->vscroll);
501}
502
503static ssize_t fsp_attr_set_vscroll(struct psmouse *psmouse, void *data,
504 const char *buf, size_t count)
505{
506 unsigned long val;
507
508 if (strict_strtoul(buf, 10, &val) || val > 1)
509 return -EINVAL;
510
511 fsp_onpad_vscr(psmouse, val);
512
513 return count;
514}
515
516PSMOUSE_DEFINE_ATTR(vscroll, S_IWUSR | S_IRUGO, NULL,
517 fsp_attr_show_vscroll, fsp_attr_set_vscroll);
518
519static ssize_t fsp_attr_show_hscroll(struct psmouse *psmouse,
520 void *data, char *buf)
521{
522 struct fsp_data *pad = psmouse->private;
523
524 return sprintf(buf, "%d\n", pad->hscroll);
525}
526
527static ssize_t fsp_attr_set_hscroll(struct psmouse *psmouse, void *data,
528 const char *buf, size_t count)
529{
530 unsigned long val;
531
532 if (strict_strtoul(buf, 10, &val) || val > 1)
533 return -EINVAL;
534
535 fsp_onpad_hscr(psmouse, val);
536
537 return count;
538}
539
540PSMOUSE_DEFINE_ATTR(hscroll, S_IWUSR | S_IRUGO, NULL,
541 fsp_attr_show_hscroll, fsp_attr_set_hscroll);
542
543static ssize_t fsp_attr_show_flags(struct psmouse *psmouse,
544 void *data, char *buf)
545{
546 struct fsp_data *pad = psmouse->private;
547
548 return sprintf(buf, "%c\n",
549 pad->flags & FSPDRV_FLAG_EN_OPC ? 'C' : 'c');
550}
551
552static ssize_t fsp_attr_set_flags(struct psmouse *psmouse, void *data,
553 const char *buf, size_t count)
554{
555 struct fsp_data *pad = psmouse->private;
556 size_t i;
557
558 for (i = 0; i < count; i++) {
559 switch (buf[i]) {
560 case 'C':
561 pad->flags |= FSPDRV_FLAG_EN_OPC;
562 break;
563 case 'c':
564 pad->flags &= ~FSPDRV_FLAG_EN_OPC;
565 break;
566 default:
567 return -EINVAL;
568 }
569 }
570 return count;
571}
572
573PSMOUSE_DEFINE_ATTR(flags, S_IWUSR | S_IRUGO, NULL,
574 fsp_attr_show_flags, fsp_attr_set_flags);
575
576static ssize_t fsp_attr_show_ver(struct psmouse *psmouse,
577 void *data, char *buf)
578{
579 return sprintf(buf, "Sentelic FSP kernel module %s\n", fsp_drv_ver);
580}
581
582PSMOUSE_DEFINE_RO_ATTR(ver, S_IRUGO, NULL, fsp_attr_show_ver);
583
584static struct attribute *fsp_attributes[] = {
585 &psmouse_attr_setreg.dattr.attr,
586 &psmouse_attr_getreg.dattr.attr,
587 &psmouse_attr_page.dattr.attr,
588 &psmouse_attr_vscroll.dattr.attr,
589 &psmouse_attr_hscroll.dattr.attr,
590 &psmouse_attr_flags.dattr.attr,
591 &psmouse_attr_ver.dattr.attr,
592 NULL
593};
594
595static struct attribute_group fsp_attribute_group = {
596 .attrs = fsp_attributes,
597};
598
599#ifdef FSP_DEBUG
600static void fsp_packet_debug(unsigned char packet[])
601{
602 static unsigned int ps2_packet_cnt;
603 static unsigned int ps2_last_second;
604 unsigned int jiffies_msec;
605
606 ps2_packet_cnt++;
607 jiffies_msec = jiffies_to_msecs(jiffies);
608 printk(KERN_DEBUG "%08dms PS/2 packets: %02x, %02x, %02x, %02x\n",
609 jiffies_msec, packet[0], packet[1], packet[2], packet[3]);
610
611 if (jiffies_msec - ps2_last_second > 1000) {
612 printk(KERN_DEBUG "PS/2 packets/sec = %d\n", ps2_packet_cnt);
613 ps2_packet_cnt = 0;
614 ps2_last_second = jiffies_msec;
615 }
616}
617#else
618static void fsp_packet_debug(unsigned char packet[])
619{
620}
621#endif
622
623static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse)
624{
625 struct input_dev *dev = psmouse->dev;
626 struct fsp_data *ad = psmouse->private;
627 unsigned char *packet = psmouse->packet;
628 unsigned char button_status = 0, lscroll = 0, rscroll = 0;
629 int rel_x, rel_y;
630
631 if (psmouse->pktcnt < 4)
632 return PSMOUSE_GOOD_DATA;
633
634 /*
635 * Full packet accumulated, process it
636 */
637
638 switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) {
639 case FSP_PKT_TYPE_ABS:
640 dev_warn(&psmouse->ps2dev.serio->dev,
641 "Unexpected absolute mode packet, ignored.\n");
642 break;
643
644 case FSP_PKT_TYPE_NORMAL_OPC:
645 /* on-pad click, filter it if necessary */
646 if ((ad->flags & FSPDRV_FLAG_EN_OPC) != FSPDRV_FLAG_EN_OPC)
647 packet[0] &= ~BIT(0);
648 /* fall through */
649
650 case FSP_PKT_TYPE_NORMAL:
651 /* normal packet */
652 /* special packet data translation from on-pad packets */
653 if (packet[3] != 0) {
654 if (packet[3] & BIT(0))
655 button_status |= 0x01; /* wheel down */
656 if (packet[3] & BIT(1))
657 button_status |= 0x0f; /* wheel up */
658 if (packet[3] & BIT(2))
659 button_status |= BIT(5);/* horizontal left */
660 if (packet[3] & BIT(3))
661 button_status |= BIT(4);/* horizontal right */
662 /* push back to packet queue */
663 if (button_status != 0)
664 packet[3] = button_status;
665 rscroll = (packet[3] >> 4) & 1;
666 lscroll = (packet[3] >> 5) & 1;
667 }
668 /*
669 * Processing wheel up/down and extra button events
670 */
671 input_report_rel(dev, REL_WHEEL,
672 (int)(packet[3] & 8) - (int)(packet[3] & 7));
673 input_report_rel(dev, REL_HWHEEL, lscroll - rscroll);
674 input_report_key(dev, BTN_BACK, lscroll);
675 input_report_key(dev, BTN_FORWARD, rscroll);
676
677 /*
678 * Standard PS/2 Mouse
679 */
680 input_report_key(dev, BTN_LEFT, packet[0] & 1);
681 input_report_key(dev, BTN_MIDDLE, (packet[0] >> 2) & 1);
682 input_report_key(dev, BTN_RIGHT, (packet[0] >> 1) & 1);
683
684 rel_x = packet[1] ? (int)packet[1] - (int)((packet[0] << 4) & 0x100) : 0;
685 rel_y = packet[2] ? (int)((packet[0] << 3) & 0x100) - (int)packet[2] : 0;
686
687 input_report_rel(dev, REL_X, rel_x);
688 input_report_rel(dev, REL_Y, rel_y);
689 break;
690 }
691
692 input_sync(dev);
693
694 fsp_packet_debug(packet);
695
696 return PSMOUSE_FULL_PACKET;
697}
698
699static int fsp_activate_protocol(struct psmouse *psmouse)
700{
701 struct fsp_data *pad = psmouse->private;
702 struct ps2dev *ps2dev = &psmouse->ps2dev;
703 unsigned char param[2];
704 int val;
705
706 /*
707 * Standard procedure to enter FSP Intellimouse mode
708 * (scrolling wheel, 4th and 5th buttons)
709 */
710 param[0] = 200;
711 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
712 param[0] = 200;
713 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
714 param[0] = 80;
715 ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
716
717 ps2_command(ps2dev, param, PSMOUSE_CMD_GETID);
718 if (param[0] != 0x04) {
719 dev_err(&psmouse->ps2dev.serio->dev,
720 "Unable to enable 4 bytes packet format.\n");
721 return -EIO;
722 }
723
724 if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &val)) {
725 dev_err(&psmouse->ps2dev.serio->dev,
726 "Unable to read SYSCTL5 register.\n");
727 return -EIO;
728 }
729
730 val &= ~(FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8 | FSP_BIT_EN_AUTO_MSID8);
731 /* Ensure we are not in absolute mode */
732 val &= ~FSP_BIT_EN_PKT_G0;
733 if (pad->buttons == 0x06) {
734 /* Left/Middle/Right & Scroll Up/Down/Right/Left */
735 val |= FSP_BIT_EN_MSID6;
736 }
737
738 if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, val)) {
739 dev_err(&psmouse->ps2dev.serio->dev,
740 "Unable to set up required mode bits.\n");
741 return -EIO;
742 }
743
744 /*
745 * Enable OPC tags such that driver can tell the difference between
746 * on-pad and real button click
747 */
748 if (fsp_opc_tag_enable(psmouse, true))
749 dev_warn(&psmouse->ps2dev.serio->dev,
750 "Failed to enable OPC tag mode.\n");
751
752 /* Enable on-pad vertical and horizontal scrolling */
753 fsp_onpad_vscr(psmouse, true);
754 fsp_onpad_hscr(psmouse, true);
755
756 return 0;
757}
758
759int fsp_detect(struct psmouse *psmouse, int set_properties)
760{
761 int id;
762
763 if (fsp_reg_read(psmouse, FSP_REG_DEVICE_ID, &id))
764 return -EIO;
765
766 if (id != 0x01)
767 return -ENODEV;
768
769 if (set_properties) {
770 psmouse->vendor = "Sentelic";
771 psmouse->name = "FingerSensingPad";
772 }
773
774 return 0;
775}
776
777static void fsp_reset(struct psmouse *psmouse)
778{
779 fsp_opc_tag_enable(psmouse, false);
780 fsp_onpad_vscr(psmouse, false);
781 fsp_onpad_hscr(psmouse, false);
782}
783
784static void fsp_disconnect(struct psmouse *psmouse)
785{
786 sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj,
787 &fsp_attribute_group);
788
789 fsp_reset(psmouse);
790 kfree(psmouse->private);
791}
792
793static int fsp_reconnect(struct psmouse *psmouse)
794{
795 int version;
796
797 if (fsp_detect(psmouse, 0))
798 return -ENODEV;
799
800 if (fsp_get_version(psmouse, &version))
801 return -ENODEV;
802
803 if (fsp_activate_protocol(psmouse))
804 return -EIO;
805
806 return 0;
807}
808
809int fsp_init(struct psmouse *psmouse)
810{
811 struct fsp_data *priv;
812 int ver, rev, buttons;
813 int error;
814
815 if (fsp_get_version(psmouse, &ver) ||
816 fsp_get_revision(psmouse, &rev) ||
817 fsp_get_buttons(psmouse, &buttons)) {
818 return -ENODEV;
819 }
820
821 printk(KERN_INFO
822 "Finger Sensing Pad, hw: %d.%d.%d, sw: %s, buttons: %d\n",
823 ver >> 4, ver & 0x0F, rev, fsp_drv_ver, buttons & 7);
824
825 psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL);
826 if (!priv)
827 return -ENOMEM;
828
829 priv->ver = ver;
830 priv->rev = rev;
831 priv->buttons = buttons;
832
833 /* enable on-pad click by default */
834 priv->flags |= FSPDRV_FLAG_EN_OPC;
835
836 /* Set up various supported input event bits */
837 __set_bit(BTN_BACK, psmouse->dev->keybit);
838 __set_bit(BTN_FORWARD, psmouse->dev->keybit);
839 __set_bit(REL_WHEEL, psmouse->dev->relbit);
840 __set_bit(REL_HWHEEL, psmouse->dev->relbit);
841
842 psmouse->protocol_handler = fsp_process_byte;
843 psmouse->disconnect = fsp_disconnect;
844 psmouse->reconnect = fsp_reconnect;
845 psmouse->cleanup = fsp_reset;
846 psmouse->pktsize = 4;
847
848 /* set default packet output based on number of buttons we found */
849 error = fsp_activate_protocol(psmouse);
850 if (error)
851 goto err_out;
852
853 error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj,
854 &fsp_attribute_group);
855 if (error) {
856 dev_err(&psmouse->ps2dev.serio->dev,
857 "Failed to create sysfs attributes (%d)", error);
858 goto err_out;
859 }
860
861 return 0;
862
863 err_out:
864 kfree(psmouse->private);
865 psmouse->private = NULL;
866 return error;
867}
diff --git a/drivers/input/mouse/sentelic.h b/drivers/input/mouse/sentelic.h
new file mode 100644
index 000000000000..083559c7282b
--- /dev/null
+++ b/drivers/input/mouse/sentelic.h
@@ -0,0 +1,98 @@
1/*-
2 * Finger Sensing Pad PS/2 mouse driver.
3 *
4 * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd.
5 * Copyright (C) 2005-2009 Tai-hwa Liang, Sentelic Corporation.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#ifndef __SENTELIC_H
23#define __SENTELIC_H
24
25/* Finger-sensing Pad information registers */
26#define FSP_REG_DEVICE_ID 0x00
27#define FSP_REG_VERSION 0x01
28#define FSP_REG_REVISION 0x04
29#define FSP_REG_TMOD_STATUS1 0x0B
30#define FSP_BIT_NO_ROTATION BIT(3)
31#define FSP_REG_PAGE_CTRL 0x0F
32
33/* Finger-sensing Pad control registers */
34#define FSP_REG_SYSCTL1 0x10
35#define FSP_BIT_EN_REG_CLK BIT(5)
36#define FSP_REG_OPC_QDOWN 0x31
37#define FSP_BIT_EN_OPC_TAG BIT(7)
38#define FSP_REG_OPTZ_XLO 0x34
39#define FSP_REG_OPTZ_XHI 0x35
40#define FSP_REG_OPTZ_YLO 0x36
41#define FSP_REG_OPTZ_YHI 0x37
42#define FSP_REG_SYSCTL5 0x40
43#define FSP_BIT_90_DEGREE BIT(0)
44#define FSP_BIT_EN_MSID6 BIT(1)
45#define FSP_BIT_EN_MSID7 BIT(2)
46#define FSP_BIT_EN_MSID8 BIT(3)
47#define FSP_BIT_EN_AUTO_MSID8 BIT(5)
48#define FSP_BIT_EN_PKT_G0 BIT(6)
49
50#define FSP_REG_ONPAD_CTL 0x43
51#define FSP_BIT_ONPAD_ENABLE BIT(0)
52#define FSP_BIT_ONPAD_FBBB BIT(1)
53#define FSP_BIT_FIX_VSCR BIT(3)
54#define FSP_BIT_FIX_HSCR BIT(5)
55#define FSP_BIT_DRAG_LOCK BIT(6)
56
57/* Finger-sensing Pad packet formating related definitions */
58
59/* absolute packet type */
60#define FSP_PKT_TYPE_NORMAL (0x00)
61#define FSP_PKT_TYPE_ABS (0x01)
62#define FSP_PKT_TYPE_NOTIFY (0x02)
63#define FSP_PKT_TYPE_NORMAL_OPC (0x03)
64#define FSP_PKT_TYPE_SHIFT (6)
65
66#ifdef __KERNEL__
67
68struct fsp_data {
69 unsigned char ver; /* hardware version */
70 unsigned char rev; /* hardware revison */
71 unsigned char buttons; /* Number of buttons */
72 unsigned int flags;
73#define FSPDRV_FLAG_EN_OPC (0x001) /* enable on-pad clicking */
74
75 bool vscroll; /* Vertical scroll zone enabled */
76 bool hscroll; /* Horizontal scroll zone enabled */
77
78 unsigned char last_reg; /* Last register we requested read from */
79 unsigned char last_val;
80};
81
82#ifdef CONFIG_MOUSE_PS2_SENTELIC
83extern int fsp_detect(struct psmouse *psmouse, int set_properties);
84extern int fsp_init(struct psmouse *psmouse);
85#else
86inline int fsp_detect(struct psmouse *psmouse, int set_properties)
87{
88 return -ENOSYS;
89}
90inline int fsp_init(struct psmouse *psmouse)
91{
92 return -ENOSYS;
93}
94#endif
95
96#endif /* __KERNEL__ */
97
98#endif /* !__SENTELIC_H */
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index be5bbbb8ae4e..3a95b508bf27 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -161,7 +161,7 @@ static int ps2_adjust_timeout(struct ps2dev *ps2dev, int command, int timeout)
161 * ps2_command() can only be called from a process context 161 * ps2_command() can only be called from a process context
162 */ 162 */
163 163
164int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) 164int __ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
165{ 165{
166 int timeout; 166 int timeout;
167 int send = (command >> 12) & 0xf; 167 int send = (command >> 12) & 0xf;
@@ -179,8 +179,6 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
179 return -1; 179 return -1;
180 } 180 }
181 181
182 mutex_lock(&ps2dev->cmd_mutex);
183
184 serio_pause_rx(ps2dev->serio); 182 serio_pause_rx(ps2dev->serio);
185 ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0; 183 ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0;
186 ps2dev->cmdcnt = receive; 184 ps2dev->cmdcnt = receive;
@@ -231,7 +229,18 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
231 ps2dev->flags = 0; 229 ps2dev->flags = 0;
232 serio_continue_rx(ps2dev->serio); 230 serio_continue_rx(ps2dev->serio);
233 231
232 return rc;
233}
234EXPORT_SYMBOL(__ps2_command);
235
236int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
237{
238 int rc;
239
240 mutex_lock(&ps2dev->cmd_mutex);
241 rc = __ps2_command(ps2dev, param, command);
234 mutex_unlock(&ps2dev->cmd_mutex); 242 mutex_unlock(&ps2dev->cmd_mutex);
243
235 return rc; 244 return rc;
236} 245}
237EXPORT_SYMBOL(ps2_command); 246EXPORT_SYMBOL(ps2_command);
diff --git a/include/linux/libps2.h b/include/linux/libps2.h
index b94534b7e266..fcf5fbe6a50c 100644
--- a/include/linux/libps2.h
+++ b/include/linux/libps2.h
@@ -44,6 +44,7 @@ struct ps2dev {
44void ps2_init(struct ps2dev *ps2dev, struct serio *serio); 44void ps2_init(struct ps2dev *ps2dev, struct serio *serio);
45int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout); 45int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout);
46void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout); 46void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout);
47int __ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command);
47int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command); 48int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command);
48int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data); 49int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data);
49int ps2_handle_response(struct ps2dev *ps2dev, unsigned char data); 50int ps2_handle_response(struct ps2dev *ps2dev, unsigned char data);