diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-14 20:56:51 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-14 20:56:51 -0400 |
| commit | 133309a89e7430f907ebe85e78906ee12c311727 (patch) | |
| tree | daa96e6e82b63c0ef1538dcbb455d13595a1c83d | |
| parent | 5489375d481c8456c8259b48e107d03b05309d1d (diff) | |
| parent | fc8e1ead9314cf0e0f1922e661428b93d3a50d88 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (52 commits)
Input: bcm5974 - silence uninitialized variables warnings
Input: wistron_btns - add keymap for AOpen 1557
Input: psmouse - use boolean type
Input: i8042 - use platform_driver_probe
Input: i8042 - use boolean type where it makes sense
Input: i8042 - try disabling and re-enabling AUX port at close
Input: pxa27x_keypad - allow modifying keymap from userspace
Input: sunkbd - fix formatting
Input: i8042 - bypass AUX IRQ delivery test on laptops
Input: wacom_w8001 - simplify querying logic
Input: atkbd - allow setting force-release bitmap via sysfs
Input: w90p910_keypad - move a dereference below a NULL test
Input: add twl4030_keypad driver
Input: matrix-keypad - add function to build device keymap
Input: tosakbd - fix cleaning up KEY_STROBEs after error
Input: joydev - validate axis/button maps before clobbering current ones
Input: xpad - add USB ID for the drumkit controller from Rock Band
Input: w90p910_keypad - rename driver name to match platform
Input: add new driver for Sentelic Finger Sensing Pad
Input: psmouse - allow defining read-only attributes
...
77 files changed, 4347 insertions, 1572 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 @@ | |||
| 1 | Copyright (C) 2002-2008 Sentelic Corporation. | ||
| 2 | Last update: Oct-31-2008 | ||
| 3 | |||
| 4 | ============================================================================== | ||
| 5 | * Finger Sensing Pad Intellimouse Mode(scrolling wheel, 4th and 5th buttons) | ||
| 6 | ============================================================================== | ||
| 7 | A) 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 | |||
| 15 | Packet 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 | ||
| 17 | BYTE |---------------|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 | |||
| 21 | Byte 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. | ||
| 29 | Byte 2: X Movement(9-bit 2's complement integers) | ||
| 30 | Byte 3: Y Movement(9-bit 2's complement integers) | ||
| 31 | Byte 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 | |||
| 38 | B) 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 | |||
| 44 | Packet 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 | ||
| 46 | BYTE |---------------|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 | |||
| 50 | Byte 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. | ||
| 58 | Byte 2: X Movement(9-bit 2's complement integers) | ||
| 59 | Byte 3: Y Movement(9-bit 2's complement integers) | ||
| 60 | Byte 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 | |||
| 69 | C) 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 | |||
| 84 | Packet 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 | ||
| 86 | BYTE |---------------|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 | |||
| 90 | Byte 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. | ||
| 99 | Byte 2: X coordinate (xpos[9:2]) | ||
| 100 | Byte 3: Y coordinate (ypos[9:2]) | ||
| 101 | Byte 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 | |||
| 108 | Notify 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 | ||
| 110 | BYTE |---------------|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 | |||
| 114 | Byte 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. | ||
| 123 | Byte 2: Message Type => 0x5A (Enable/Disable status packet) | ||
| 124 | Mode Type => 0xA5 (Normal/Icon mode status) | ||
| 125 | Byte 3: Message Type => 0x00 (Disabled) | ||
| 126 | => 0x01 (Enabled) | ||
| 127 | Mode Type => 0x00 (Normal) | ||
| 128 | => 0x01 (Icon) | ||
| 129 | Byte 4: Bit7~Bit0 => Don't Care | ||
| 130 | |||
| 131 | ============================================================================== | ||
| 132 | * Absolute position for STL3888-A0. | ||
| 133 | ============================================================================== | ||
| 134 | Packet 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 | ||
| 136 | BYTE |---------------|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 | |||
| 140 | Byte 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 | ||
| 151 | Byte 2: X coordinate (xpos[9:2]) | ||
| 152 | Byte 3: Y coordinate (ypos[9:2]) | ||
| 153 | Byte 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 | |||
| 158 | Packet 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 | ||
| 160 | BYTE |---------------|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 | |||
| 164 | Byte 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 | ||
| 175 | Byte 2: X coordinate (xpos[9:2]) | ||
| 176 | Byte 3: Y coordinate (ypos[9:2]) | ||
| 177 | Byte 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 | |||
| 182 | Notify 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 | ||
| 184 | BYTE |---------------|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 | |||
| 188 | Byte 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. | ||
| 199 | Byte 2: Message Type => 0xB7 (Multi Finger, Multi Coordinate mode) | ||
| 200 | Byte 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 | ||
| 204 | Byte 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 | |||
| 213 | Sample 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 | ||
| 222 | BYTE |---------------|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 | |||
| 226 | FSP will send out enable/disable packet when FSP receive PS/2 enable/disable | ||
| 227 | command. Host will receive the packet which Middle, Right, Left button will | ||
| 228 | be set. The packet only use byte 0 and byte 1 as a pattern of original packet. | ||
| 229 | Ignore the other bytes of the packet. | ||
| 230 | |||
| 231 | Byte 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 | ||
| 239 | Byte 2: Bit7~1 => (0101101b) | ||
| 240 | Bit0 => 1 = Enable | ||
| 241 | 0 = Disable | ||
| 242 | Byte 3: Don't care | ||
| 243 | Byte 4: Don't care (MOUSE ID 3, 4) | ||
| 244 | Byte 5~8: Don't care (Absolute packet) | ||
| 245 | |||
| 246 | ============================================================================== | ||
| 247 | * PS/2 Command Set | ||
| 248 | ============================================================================== | ||
| 249 | |||
| 250 | FSP supports basic PS/2 commanding set and modes, refer to following URL for | ||
| 251 | details about PS/2 commands: | ||
| 252 | |||
| 253 | http://www.computer-engineering.org/index.php?title=PS/2_Mouse_Interface | ||
| 254 | |||
| 255 | ============================================================================== | ||
| 256 | * Programming Sequence for Determining Packet Parsing Flow | ||
| 257 | ============================================================================== | ||
| 258 | 1. Identify FSP by reading device ID(0x00) and version(0x01) register | ||
| 259 | |||
| 260 | 2. 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 | |||
| 281 | Register inversion requirement: | ||
| 282 | |||
| 283 | Following values needed to be inverted(the '~' operator in C) before being | ||
| 284 | sent to FSP: | ||
| 285 | |||
| 286 | 0xe9, 0xee, 0xf2 and 0xff. | ||
| 287 | |||
| 288 | Register swapping requirement: | ||
| 289 | |||
| 290 | Following values needed to have their higher 4 bits and lower 4 bits being | ||
| 291 | swapped before being sent to FSP: | ||
| 292 | |||
| 293 | 10, 20, 40, 60, 80, 100 and 200. | ||
| 294 | |||
| 295 | Register 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 | |||
| 329 | Register 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 | |||
| 381 | offset width default r/w name | ||
| 382 | 0x00 bit7~bit0 0x01 RO device ID | ||
| 383 | |||
| 384 | 0x01 bit7~bit0 0xc0 RW version ID | ||
| 385 | |||
| 386 | 0x02 bit7~bit0 0x01 RO vendor ID | ||
| 387 | |||
| 388 | 0x03 bit7~bit0 0x01 RO product ID | ||
| 389 | |||
| 390 | 0x04 bit3~bit0 0x01 RW revision ID | ||
| 391 | |||
| 392 | 0x0b 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 | |||
| 401 | 0x0f RW register file page control | ||
| 402 | bit0 0 RW 1 to enable page 1 register files | ||
| 403 | |||
| 404 | 0x10 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 | |||
| 414 | 0x31 RW on-pad command detection | ||
| 415 | bit7 0 RW on-pad command left button down tag | ||
| 416 | enable | ||
| 417 | 0: disable, 1: enable | ||
| 418 | |||
| 419 | 0x34 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 | |||
| 426 | 0x35 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 | |||
| 430 | 0x36 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 | |||
| 434 | 0x37 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 | |||
| 438 | 0x40 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 | |||
| 466 | 0x43 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/arch/arm/mach-pxa/include/mach/pxa27x_keypad.h b/arch/arm/mach-pxa/include/mach/pxa27x_keypad.h index d5a48a96dea7..7b4eadc6df3a 100644 --- a/arch/arm/mach-pxa/include/mach/pxa27x_keypad.h +++ b/arch/arm/mach-pxa/include/mach/pxa27x_keypad.h | |||
| @@ -2,9 +2,12 @@ | |||
| 2 | #define __ASM_ARCH_PXA27x_KEYPAD_H | 2 | #define __ASM_ARCH_PXA27x_KEYPAD_H |
| 3 | 3 | ||
| 4 | #include <linux/input.h> | 4 | #include <linux/input.h> |
| 5 | #include <linux/input/matrix_keypad.h> | ||
| 5 | 6 | ||
| 6 | #define MAX_MATRIX_KEY_ROWS (8) | 7 | #define MAX_MATRIX_KEY_ROWS (8) |
| 7 | #define MAX_MATRIX_KEY_COLS (8) | 8 | #define MAX_MATRIX_KEY_COLS (8) |
| 9 | #define MATRIX_ROW_SHIFT (3) | ||
| 10 | #define MAX_DIRECT_KEY_NUM (8) | ||
| 8 | 11 | ||
| 9 | /* pxa3xx keypad platform specific parameters | 12 | /* pxa3xx keypad platform specific parameters |
| 10 | * | 13 | * |
| @@ -33,7 +36,7 @@ struct pxa27x_keypad_platform_data { | |||
| 33 | 36 | ||
| 34 | /* direct keys */ | 37 | /* direct keys */ |
| 35 | int direct_key_num; | 38 | int direct_key_num; |
| 36 | unsigned int direct_key_map[8]; | 39 | unsigned int direct_key_map[MAX_DIRECT_KEY_NUM]; |
| 37 | 40 | ||
| 38 | /* rotary encoders 0 */ | 41 | /* rotary encoders 0 */ |
| 39 | int enable_rotary0; | 42 | int enable_rotary0; |
| @@ -51,8 +54,6 @@ struct pxa27x_keypad_platform_data { | |||
| 51 | unsigned int debounce_interval; | 54 | unsigned int debounce_interval; |
| 52 | }; | 55 | }; |
| 53 | 56 | ||
| 54 | #define KEY(row, col, val) (((row) << 28) | ((col) << 24) | (val)) | ||
| 55 | |||
| 56 | extern void pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info); | 57 | extern void pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info); |
| 57 | 58 | ||
| 58 | #endif /* __ASM_ARCH_PXA27x_KEYPAD_H */ | 59 | #endif /* __ASM_ARCH_PXA27x_KEYPAD_H */ |
diff --git a/arch/arm/mach-w90x900/include/mach/w90p910_keypad.h b/arch/arm/mach-w90x900/include/mach/w90p910_keypad.h new file mode 100644 index 000000000000..556778e8ddaa --- /dev/null +++ b/arch/arm/mach-w90x900/include/mach/w90p910_keypad.h | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | #ifndef __ASM_ARCH_W90P910_KEYPAD_H | ||
| 2 | #define __ASM_ARCH_W90P910_KEYPAD_H | ||
| 3 | |||
| 4 | #include <linux/input/matrix_keypad.h> | ||
| 5 | |||
| 6 | extern void mfp_set_groupi(struct device *dev); | ||
| 7 | |||
| 8 | struct w90p910_keypad_platform_data { | ||
| 9 | const struct matrix_keymap_data *keymap_data; | ||
| 10 | |||
| 11 | unsigned int prescale; | ||
| 12 | unsigned int debounce; | ||
| 13 | }; | ||
| 14 | |||
| 15 | #endif /* __ASM_ARCH_W90P910_KEYPAD_H */ | ||
diff --git a/arch/blackfin/include/asm/bfin_rotary.h b/arch/blackfin/include/asm/bfin_rotary.h new file mode 100644 index 000000000000..425ece64fd5e --- /dev/null +++ b/arch/blackfin/include/asm/bfin_rotary.h | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | /* | ||
| 2 | * board initialization should put one of these structures into platform_data | ||
| 3 | * and place the bfin-rotary onto platform_bus named "bfin-rotary". | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef _BFIN_ROTARY_H | ||
| 7 | #define _BFIN_ROTARY_H | ||
| 8 | |||
| 9 | /* mode bitmasks */ | ||
| 10 | #define ROT_QUAD_ENC CNTMODE_QUADENC /* quadrature/grey code encoder mode */ | ||
| 11 | #define ROT_BIN_ENC CNTMODE_BINENC /* binary encoder mode */ | ||
| 12 | #define ROT_UD_CNT CNTMODE_UDCNT /* rotary counter mode */ | ||
| 13 | #define ROT_DIR_CNT CNTMODE_DIRCNT /* direction counter mode */ | ||
| 14 | |||
| 15 | #define ROT_DEBE DEBE /* Debounce Enable */ | ||
| 16 | |||
| 17 | #define ROT_CDGINV CDGINV /* CDG Pin Polarity Invert */ | ||
| 18 | #define ROT_CUDINV CUDINV /* CUD Pin Polarity Invert */ | ||
| 19 | #define ROT_CZMINV CZMINV /* CZM Pin Polarity Invert */ | ||
| 20 | |||
| 21 | struct bfin_rotary_platform_data { | ||
| 22 | /* set rotary UP KEY_### or BTN_### in case you prefer | ||
| 23 | * bfin-rotary to send EV_KEY otherwise set 0 | ||
| 24 | */ | ||
| 25 | unsigned int rotary_up_key; | ||
| 26 | /* set rotary DOWN KEY_### or BTN_### in case you prefer | ||
| 27 | * bfin-rotary to send EV_KEY otherwise set 0 | ||
| 28 | */ | ||
| 29 | unsigned int rotary_down_key; | ||
| 30 | /* set rotary BUTTON KEY_### or BTN_### */ | ||
| 31 | unsigned int rotary_button_key; | ||
| 32 | /* set rotary Relative Axis REL_### in case you prefer | ||
| 33 | * bfin-rotary to send EV_REL otherwise set 0 | ||
| 34 | */ | ||
| 35 | unsigned int rotary_rel_code; | ||
| 36 | unsigned short debounce; /* 0..17 */ | ||
| 37 | unsigned short mode; | ||
| 38 | }; | ||
| 39 | #endif | ||
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 456594bd97bc..0b111e8e444f 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
| @@ -922,7 +922,7 @@ static int platform_pm_restore_noirq(struct device *dev) | |||
| 922 | 922 | ||
| 923 | #endif /* !CONFIG_HIBERNATION */ | 923 | #endif /* !CONFIG_HIBERNATION */ |
| 924 | 924 | ||
| 925 | static struct dev_pm_ops platform_dev_pm_ops = { | 925 | static const struct dev_pm_ops platform_dev_pm_ops = { |
| 926 | .prepare = platform_pm_prepare, | 926 | .prepare = platform_pm_prepare, |
| 927 | .complete = platform_pm_complete, | 927 | .complete = platform_pm_complete, |
| 928 | .suspend = platform_pm_suspend, | 928 | .suspend = platform_pm_suspend, |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 58a3e572f2c9..1b1a786b7dec 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
| @@ -157,8 +157,9 @@ void device_pm_move_last(struct device *dev) | |||
| 157 | * @ops: PM operations to choose from. | 157 | * @ops: PM operations to choose from. |
| 158 | * @state: PM transition of the system being carried out. | 158 | * @state: PM transition of the system being carried out. |
| 159 | */ | 159 | */ |
| 160 | static int pm_op(struct device *dev, struct dev_pm_ops *ops, | 160 | static int pm_op(struct device *dev, |
| 161 | pm_message_t state) | 161 | const struct dev_pm_ops *ops, |
| 162 | pm_message_t state) | ||
| 162 | { | 163 | { |
| 163 | int error = 0; | 164 | int error = 0; |
| 164 | 165 | ||
| @@ -220,7 +221,8 @@ static int pm_op(struct device *dev, struct dev_pm_ops *ops, | |||
| 220 | * The operation is executed with interrupts disabled by the only remaining | 221 | * The operation is executed with interrupts disabled by the only remaining |
| 221 | * functional CPU in the system. | 222 | * functional CPU in the system. |
| 222 | */ | 223 | */ |
| 223 | static int pm_noirq_op(struct device *dev, struct dev_pm_ops *ops, | 224 | static int pm_noirq_op(struct device *dev, |
| 225 | const struct dev_pm_ops *ops, | ||
| 224 | pm_message_t state) | 226 | pm_message_t state) |
| 225 | { | 227 | { |
| 226 | int error = 0; | 228 | int error = 0; |
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 9a1d55b74d7a..901b2525993e 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
| @@ -452,6 +452,76 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait) | |||
| 452 | (joydev->exist ? 0 : (POLLHUP | POLLERR)); | 452 | (joydev->exist ? 0 : (POLLHUP | POLLERR)); |
| 453 | } | 453 | } |
| 454 | 454 | ||
| 455 | static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev, | ||
| 456 | void __user *argp, size_t len) | ||
| 457 | { | ||
| 458 | __u8 *abspam; | ||
| 459 | int i; | ||
| 460 | int retval = 0; | ||
| 461 | |||
| 462 | len = min(len, sizeof(joydev->abspam)); | ||
| 463 | |||
| 464 | /* Validate the map. */ | ||
| 465 | abspam = kmalloc(len, GFP_KERNEL); | ||
| 466 | if (!abspam) | ||
| 467 | return -ENOMEM; | ||
| 468 | |||
| 469 | if (copy_from_user(abspam, argp, len)) { | ||
| 470 | retval = -EFAULT; | ||
| 471 | goto out; | ||
| 472 | } | ||
| 473 | |||
| 474 | for (i = 0; i < joydev->nabs; i++) { | ||
| 475 | if (abspam[i] > ABS_MAX) { | ||
| 476 | retval = -EINVAL; | ||
| 477 | goto out; | ||
| 478 | } | ||
| 479 | } | ||
| 480 | |||
| 481 | memcpy(joydev->abspam, abspam, len); | ||
| 482 | |||
| 483 | out: | ||
| 484 | kfree(abspam); | ||
| 485 | return retval; | ||
| 486 | } | ||
| 487 | |||
| 488 | static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev, | ||
| 489 | void __user *argp, size_t len) | ||
| 490 | { | ||
| 491 | __u16 *keypam; | ||
| 492 | int i; | ||
| 493 | int retval = 0; | ||
| 494 | |||
| 495 | len = min(len, sizeof(joydev->keypam)); | ||
| 496 | |||
| 497 | /* Validate the map. */ | ||
| 498 | keypam = kmalloc(len, GFP_KERNEL); | ||
| 499 | if (!keypam) | ||
| 500 | return -ENOMEM; | ||
| 501 | |||
| 502 | if (copy_from_user(keypam, argp, len)) { | ||
| 503 | retval = -EFAULT; | ||
| 504 | goto out; | ||
| 505 | } | ||
| 506 | |||
| 507 | for (i = 0; i < joydev->nkey; i++) { | ||
| 508 | if (keypam[i] > KEY_MAX || keypam[i] < BTN_MISC) { | ||
| 509 | retval = -EINVAL; | ||
| 510 | goto out; | ||
| 511 | } | ||
| 512 | } | ||
| 513 | |||
| 514 | memcpy(joydev->keypam, keypam, len); | ||
| 515 | |||
| 516 | for (i = 0; i < joydev->nkey; i++) | ||
| 517 | joydev->keymap[keypam[i] - BTN_MISC] = i; | ||
| 518 | |||
| 519 | out: | ||
| 520 | kfree(keypam); | ||
| 521 | return retval; | ||
| 522 | } | ||
| 523 | |||
| 524 | |||
| 455 | static int joydev_ioctl_common(struct joydev *joydev, | 525 | static int joydev_ioctl_common(struct joydev *joydev, |
| 456 | unsigned int cmd, void __user *argp) | 526 | unsigned int cmd, void __user *argp) |
| 457 | { | 527 | { |
| @@ -512,46 +582,18 @@ static int joydev_ioctl_common(struct joydev *joydev, | |||
| 512 | switch (cmd & ~IOCSIZE_MASK) { | 582 | switch (cmd & ~IOCSIZE_MASK) { |
| 513 | 583 | ||
| 514 | case (JSIOCSAXMAP & ~IOCSIZE_MASK): | 584 | case (JSIOCSAXMAP & ~IOCSIZE_MASK): |
| 515 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam)); | 585 | return joydev_handle_JSIOCSAXMAP(joydev, argp, _IOC_SIZE(cmd)); |
| 516 | /* | ||
| 517 | * FIXME: we should not copy into our axis map before | ||
| 518 | * validating the data. | ||
| 519 | */ | ||
| 520 | if (copy_from_user(joydev->abspam, argp, len)) | ||
| 521 | return -EFAULT; | ||
| 522 | |||
| 523 | for (i = 0; i < joydev->nabs; i++) { | ||
| 524 | if (joydev->abspam[i] > ABS_MAX) | ||
| 525 | return -EINVAL; | ||
| 526 | joydev->absmap[joydev->abspam[i]] = i; | ||
| 527 | } | ||
| 528 | return 0; | ||
| 529 | 586 | ||
| 530 | case (JSIOCGAXMAP & ~IOCSIZE_MASK): | 587 | case (JSIOCGAXMAP & ~IOCSIZE_MASK): |
| 531 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam)); | 588 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam)); |
| 532 | return copy_to_user(argp, joydev->abspam, len) ? -EFAULT : 0; | 589 | return copy_to_user(argp, joydev->abspam, len) ? -EFAULT : len; |
| 533 | 590 | ||
| 534 | case (JSIOCSBTNMAP & ~IOCSIZE_MASK): | 591 | case (JSIOCSBTNMAP & ~IOCSIZE_MASK): |
| 535 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam)); | 592 | return joydev_handle_JSIOCSBTNMAP(joydev, argp, _IOC_SIZE(cmd)); |
| 536 | /* | ||
| 537 | * FIXME: we should not copy into our keymap before | ||
| 538 | * validating the data. | ||
| 539 | */ | ||
| 540 | if (copy_from_user(joydev->keypam, argp, len)) | ||
| 541 | return -EFAULT; | ||
| 542 | |||
| 543 | for (i = 0; i < joydev->nkey; i++) { | ||
| 544 | if (joydev->keypam[i] > KEY_MAX || | ||
| 545 | joydev->keypam[i] < BTN_MISC) | ||
| 546 | return -EINVAL; | ||
| 547 | joydev->keymap[joydev->keypam[i] - BTN_MISC] = i; | ||
| 548 | } | ||
| 549 | |||
| 550 | return 0; | ||
| 551 | 593 | ||
| 552 | case (JSIOCGBTNMAP & ~IOCSIZE_MASK): | 594 | case (JSIOCGBTNMAP & ~IOCSIZE_MASK): |
| 553 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam)); | 595 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam)); |
| 554 | return copy_to_user(argp, joydev->keypam, len) ? -EFAULT : 0; | 596 | return copy_to_user(argp, joydev->keypam, len) ? -EFAULT : len; |
| 555 | 597 | ||
| 556 | case JSIOCGNAME(0): | 598 | case JSIOCGNAME(0): |
| 557 | name = dev->name; | 599 | name = dev->name; |
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index f155ad8cdae7..2388cf578a62 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
| @@ -144,6 +144,7 @@ static const struct xpad_device { | |||
| 144 | { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, | 144 | { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, |
| 145 | { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, | 145 | { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
| 146 | { 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, | 146 | { 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, |
| 147 | { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, | ||
| 147 | { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 148 | { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
| 148 | { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_UNKNOWN } | 149 | { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_UNKNOWN } |
| 149 | }; | 150 | }; |
| @@ -208,6 +209,7 @@ static struct usb_device_id xpad_table [] = { | |||
| 208 | XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */ | 209 | XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */ |
| 209 | XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */ | 210 | XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */ |
| 210 | XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ | 211 | XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ |
| 212 | XPAD_XBOX360_VENDOR(0x1bad), /* Rock Band Drums */ | ||
| 211 | { } | 213 | { } |
| 212 | }; | 214 | }; |
| 213 | 215 | ||
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index a6b989a9dc07..3525c19be428 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
| @@ -187,7 +187,7 @@ config KEYBOARD_HIL_OLD | |||
| 187 | submenu. | 187 | submenu. |
| 188 | 188 | ||
| 189 | config KEYBOARD_HIL | 189 | config KEYBOARD_HIL |
| 190 | tristate "HP HIL keyboard support" | 190 | tristate "HP HIL keyboard/pointer support" |
| 191 | depends on GSC || HP300 | 191 | depends on GSC || HP300 |
| 192 | default y | 192 | default y |
| 193 | select HP_SDC | 193 | select HP_SDC |
| @@ -196,7 +196,8 @@ config KEYBOARD_HIL | |||
| 196 | help | 196 | help |
| 197 | The "Human Interface Loop" is a older, 8-channel USB-like | 197 | The "Human Interface Loop" is a older, 8-channel USB-like |
| 198 | controller used in several Hewlett Packard models. | 198 | controller used in several Hewlett Packard models. |
| 199 | This driver implements support for HIL-keyboards attached | 199 | This driver implements support for HIL-keyboards and pointing |
| 200 | devices (mice, tablets, touchscreens) attached | ||
| 200 | to your machine, so normally you should say Y here. | 201 | to your machine, so normally you should say Y here. |
| 201 | 202 | ||
| 202 | config KEYBOARD_HP6XX | 203 | config KEYBOARD_HP6XX |
| @@ -329,6 +330,17 @@ config KEYBOARD_OMAP | |||
| 329 | To compile this driver as a module, choose M here: the | 330 | To compile this driver as a module, choose M here: the |
| 330 | module will be called omap-keypad. | 331 | module will be called omap-keypad. |
| 331 | 332 | ||
| 333 | config KEYBOARD_TWL4030 | ||
| 334 | tristate "TI TWL4030/TWL5030/TPS659x0 keypad support" | ||
| 335 | depends on TWL4030_CORE | ||
| 336 | help | ||
| 337 | Say Y here if your board use the keypad controller on | ||
| 338 | TWL4030 family chips. It's safe to say enable this | ||
| 339 | even on boards that don't use the keypad controller. | ||
| 340 | |||
| 341 | To compile this driver as a module, choose M here: the | ||
| 342 | module will be called twl4030_keypad. | ||
| 343 | |||
| 332 | config KEYBOARD_TOSA | 344 | config KEYBOARD_TOSA |
| 333 | tristate "Tosa keyboard" | 345 | tristate "Tosa keyboard" |
| 334 | depends on MACH_TOSA | 346 | depends on MACH_TOSA |
| @@ -361,4 +373,14 @@ config KEYBOARD_XTKBD | |||
| 361 | To compile this driver as a module, choose M here: the | 373 | To compile this driver as a module, choose M here: the |
| 362 | module will be called xtkbd. | 374 | module will be called xtkbd. |
| 363 | 375 | ||
| 376 | config KEYBOARD_W90P910 | ||
| 377 | tristate "W90P910 Matrix Keypad support" | ||
| 378 | depends on ARCH_W90X900 | ||
| 379 | help | ||
| 380 | Say Y here to enable the matrix keypad on evaluation board | ||
| 381 | based on W90P910. | ||
| 382 | |||
| 383 | To compile this driver as a module, choose M here: the | ||
| 384 | module will be called w90p910_keypad. | ||
| 385 | |||
| 364 | endif | 386 | endif |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index b5b5eae9724f..8a7a22b30266 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
| @@ -30,4 +30,6 @@ obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o | |||
| 30 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | 30 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o |
| 31 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o | 31 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o |
| 32 | obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o | 32 | obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o |
| 33 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o | ||
| 33 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o | 34 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o |
| 35 | obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o | ||
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 6c6a09b1c0fe..c9523e48c6ad 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
| @@ -68,7 +68,9 @@ MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and | |||
| 68 | * are loadable via a userland utility. | 68 | * are loadable via a userland utility. |
| 69 | */ | 69 | */ |
| 70 | 70 | ||
| 71 | static const unsigned short atkbd_set2_keycode[512] = { | 71 | #define ATKBD_KEYMAP_SIZE 512 |
| 72 | |||
| 73 | static const unsigned short atkbd_set2_keycode[ATKBD_KEYMAP_SIZE] = { | ||
| 72 | 74 | ||
| 73 | #ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES | 75 | #ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES |
| 74 | 76 | ||
| @@ -99,7 +101,7 @@ static const unsigned short atkbd_set2_keycode[512] = { | |||
| 99 | #endif | 101 | #endif |
| 100 | }; | 102 | }; |
| 101 | 103 | ||
| 102 | static const unsigned short atkbd_set3_keycode[512] = { | 104 | static const unsigned short atkbd_set3_keycode[ATKBD_KEYMAP_SIZE] = { |
| 103 | 105 | ||
| 104 | 0, 0, 0, 0, 0, 0, 0, 59, 1,138,128,129,130, 15, 41, 60, | 106 | 0, 0, 0, 0, 0, 0, 0, 59, 1,138,128,129,130, 15, 41, 60, |
| 105 | 131, 29, 42, 86, 58, 16, 2, 61,133, 56, 44, 31, 30, 17, 3, 62, | 107 | 131, 29, 42, 86, 58, 16, 2, 61,133, 56, 44, 31, 30, 17, 3, 62, |
| @@ -200,8 +202,8 @@ struct atkbd { | |||
| 200 | char phys[32]; | 202 | char phys[32]; |
| 201 | 203 | ||
| 202 | unsigned short id; | 204 | unsigned short id; |
| 203 | unsigned short keycode[512]; | 205 | unsigned short keycode[ATKBD_KEYMAP_SIZE]; |
| 204 | DECLARE_BITMAP(force_release_mask, 512); | 206 | DECLARE_BITMAP(force_release_mask, ATKBD_KEYMAP_SIZE); |
| 205 | unsigned char set; | 207 | unsigned char set; |
| 206 | unsigned char translated; | 208 | unsigned char translated; |
| 207 | unsigned char extra; | 209 | unsigned char extra; |
| @@ -253,6 +255,7 @@ static struct device_attribute atkbd_attr_##_name = \ | |||
| 253 | __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name); | 255 | __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name); |
| 254 | 256 | ||
| 255 | ATKBD_DEFINE_ATTR(extra); | 257 | ATKBD_DEFINE_ATTR(extra); |
| 258 | ATKBD_DEFINE_ATTR(force_release); | ||
| 256 | ATKBD_DEFINE_ATTR(scroll); | 259 | ATKBD_DEFINE_ATTR(scroll); |
| 257 | ATKBD_DEFINE_ATTR(set); | 260 | ATKBD_DEFINE_ATTR(set); |
| 258 | ATKBD_DEFINE_ATTR(softrepeat); | 261 | ATKBD_DEFINE_ATTR(softrepeat); |
| @@ -272,6 +275,7 @@ ATKBD_DEFINE_RO_ATTR(err_count); | |||
| 272 | 275 | ||
| 273 | static struct attribute *atkbd_attributes[] = { | 276 | static struct attribute *atkbd_attributes[] = { |
| 274 | &atkbd_attr_extra.attr, | 277 | &atkbd_attr_extra.attr, |
| 278 | &atkbd_attr_force_release.attr, | ||
| 275 | &atkbd_attr_scroll.attr, | 279 | &atkbd_attr_scroll.attr, |
| 276 | &atkbd_attr_set.attr, | 280 | &atkbd_attr_set.attr, |
| 277 | &atkbd_attr_softrepeat.attr, | 281 | &atkbd_attr_softrepeat.attr, |
| @@ -934,7 +938,7 @@ static void atkbd_set_keycode_table(struct atkbd *atkbd) | |||
| 934 | int i, j; | 938 | int i, j; |
| 935 | 939 | ||
| 936 | memset(atkbd->keycode, 0, sizeof(atkbd->keycode)); | 940 | memset(atkbd->keycode, 0, sizeof(atkbd->keycode)); |
| 937 | bitmap_zero(atkbd->force_release_mask, 512); | 941 | bitmap_zero(atkbd->force_release_mask, ATKBD_KEYMAP_SIZE); |
| 938 | 942 | ||
| 939 | if (atkbd->translated) { | 943 | if (atkbd->translated) { |
| 940 | for (i = 0; i < 128; i++) { | 944 | for (i = 0; i < 128; i++) { |
| @@ -1041,7 +1045,7 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd) | |||
| 1041 | input_dev->keycodesize = sizeof(unsigned short); | 1045 | input_dev->keycodesize = sizeof(unsigned short); |
| 1042 | input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode); | 1046 | input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode); |
| 1043 | 1047 | ||
| 1044 | for (i = 0; i < 512; i++) | 1048 | for (i = 0; i < ATKBD_KEYMAP_SIZE; i++) |
| 1045 | if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL) | 1049 | if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL) |
| 1046 | __set_bit(atkbd->keycode[i], input_dev->keybit); | 1050 | __set_bit(atkbd->keycode[i], input_dev->keybit); |
| 1047 | } | 1051 | } |
| @@ -1309,6 +1313,33 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun | |||
| 1309 | return count; | 1313 | return count; |
| 1310 | } | 1314 | } |
| 1311 | 1315 | ||
| 1316 | static ssize_t atkbd_show_force_release(struct atkbd *atkbd, char *buf) | ||
| 1317 | { | ||
| 1318 | size_t len = bitmap_scnlistprintf(buf, PAGE_SIZE - 2, | ||
| 1319 | atkbd->force_release_mask, ATKBD_KEYMAP_SIZE); | ||
| 1320 | |||
| 1321 | buf[len++] = '\n'; | ||
| 1322 | buf[len] = '\0'; | ||
| 1323 | |||
| 1324 | return len; | ||
| 1325 | } | ||
| 1326 | |||
| 1327 | static ssize_t atkbd_set_force_release(struct atkbd *atkbd, | ||
| 1328 | const char *buf, size_t count) | ||
| 1329 | { | ||
| 1330 | /* 64 bytes on stack should be acceptable */ | ||
| 1331 | DECLARE_BITMAP(new_mask, ATKBD_KEYMAP_SIZE); | ||
| 1332 | int err; | ||
| 1333 | |||
| 1334 | err = bitmap_parselist(buf, new_mask, ATKBD_KEYMAP_SIZE); | ||
| 1335 | if (err) | ||
| 1336 | return err; | ||
| 1337 | |||
| 1338 | memcpy(atkbd->force_release_mask, new_mask, sizeof(atkbd->force_release_mask)); | ||
| 1339 | return count; | ||
| 1340 | } | ||
| 1341 | |||
| 1342 | |||
| 1312 | static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf) | 1343 | static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf) |
| 1313 | { | 1344 | { |
| 1314 | return sprintf(buf, "%d\n", atkbd->scroll ? 1 : 0); | 1345 | return sprintf(buf, "%d\n", atkbd->scroll ? 1 : 0); |
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index d427f322e207..fe376a27fe57 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c | |||
| @@ -184,14 +184,13 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
| 184 | int i, error; | 184 | int i, error; |
| 185 | 185 | ||
| 186 | if (!pdata->rows || !pdata->cols || !pdata->keymap) { | 186 | if (!pdata->rows || !pdata->cols || !pdata->keymap) { |
| 187 | printk(KERN_ERR DRV_NAME | 187 | dev_err(&pdev->dev, "no rows, cols or keymap from pdata\n"); |
| 188 | ": No rows, cols or keymap from pdata\n"); | ||
| 189 | return -EINVAL; | 188 | return -EINVAL; |
| 190 | } | 189 | } |
| 191 | 190 | ||
| 192 | if (!pdata->keymapsize || | 191 | if (!pdata->keymapsize || |
| 193 | pdata->keymapsize > (pdata->rows * pdata->cols)) { | 192 | pdata->keymapsize > (pdata->rows * pdata->cols)) { |
| 194 | printk(KERN_ERR DRV_NAME ": Invalid keymapsize\n"); | 193 | dev_err(&pdev->dev, "invalid keymapsize\n"); |
| 195 | return -EINVAL; | 194 | return -EINVAL; |
| 196 | } | 195 | } |
| 197 | 196 | ||
| @@ -211,8 +210,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
| 211 | 210 | ||
| 212 | if (!pdata->debounce_time || pdata->debounce_time > MAX_MULT || | 211 | if (!pdata->debounce_time || pdata->debounce_time > MAX_MULT || |
| 213 | !pdata->coldrive_time || pdata->coldrive_time > MAX_MULT) { | 212 | !pdata->coldrive_time || pdata->coldrive_time > MAX_MULT) { |
| 214 | printk(KERN_WARNING DRV_NAME | 213 | dev_warn(&pdev->dev, |
| 215 | ": Invalid Debounce/Columndrive Time in platform data\n"); | 214 | "invalid platform debounce/columndrive time\n"); |
| 216 | bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ | 215 | bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ |
| 217 | } else { | 216 | } else { |
| 218 | bfin_write_KPAD_MSEL( | 217 | bfin_write_KPAD_MSEL( |
| @@ -231,16 +230,14 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
| 231 | 230 | ||
| 232 | if (peripheral_request_list((u16 *)&per_rows[MAX_RC - pdata->rows], | 231 | if (peripheral_request_list((u16 *)&per_rows[MAX_RC - pdata->rows], |
| 233 | DRV_NAME)) { | 232 | DRV_NAME)) { |
| 234 | printk(KERN_ERR DRV_NAME | 233 | dev_err(&pdev->dev, "requesting peripherals failed\n"); |
| 235 | ": Requesting Peripherals failed\n"); | ||
| 236 | error = -EFAULT; | 234 | error = -EFAULT; |
| 237 | goto out0; | 235 | goto out0; |
| 238 | } | 236 | } |
| 239 | 237 | ||
| 240 | if (peripheral_request_list((u16 *)&per_cols[MAX_RC - pdata->cols], | 238 | if (peripheral_request_list((u16 *)&per_cols[MAX_RC - pdata->cols], |
| 241 | DRV_NAME)) { | 239 | DRV_NAME)) { |
| 242 | printk(KERN_ERR DRV_NAME | 240 | dev_err(&pdev->dev, "requesting peripherals failed\n"); |
| 243 | ": Requesting Peripherals failed\n"); | ||
| 244 | error = -EFAULT; | 241 | error = -EFAULT; |
| 245 | goto out1; | 242 | goto out1; |
| 246 | } | 243 | } |
| @@ -254,9 +251,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
| 254 | error = request_irq(bf54x_kpad->irq, bfin_kpad_isr, | 251 | error = request_irq(bf54x_kpad->irq, bfin_kpad_isr, |
| 255 | 0, DRV_NAME, pdev); | 252 | 0, DRV_NAME, pdev); |
| 256 | if (error) { | 253 | if (error) { |
| 257 | printk(KERN_ERR DRV_NAME | 254 | dev_err(&pdev->dev, "unable to claim irq %d\n", |
| 258 | ": unable to claim irq %d; error %d\n", | 255 | bf54x_kpad->irq); |
| 259 | bf54x_kpad->irq, error); | ||
| 260 | goto out2; | 256 | goto out2; |
| 261 | } | 257 | } |
| 262 | 258 | ||
| @@ -297,8 +293,7 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
| 297 | 293 | ||
| 298 | error = input_register_device(input); | 294 | error = input_register_device(input); |
| 299 | if (error) { | 295 | if (error) { |
| 300 | printk(KERN_ERR DRV_NAME | 296 | dev_err(&pdev->dev, "unable to register input device\n"); |
| 301 | ": Unable to register input device (%d)\n", error); | ||
| 302 | goto out4; | 297 | goto out4; |
| 303 | } | 298 | } |
| 304 | 299 | ||
| @@ -316,9 +311,6 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
| 316 | 311 | ||
| 317 | device_init_wakeup(&pdev->dev, 1); | 312 | device_init_wakeup(&pdev->dev, 1); |
| 318 | 313 | ||
| 319 | printk(KERN_ERR DRV_NAME | ||
| 320 | ": Blackfin BF54x Keypad registered IRQ %d\n", bf54x_kpad->irq); | ||
| 321 | |||
| 322 | return 0; | 314 | return 0; |
| 323 | 315 | ||
| 324 | out4: | 316 | out4: |
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index efed0c9e242e..a88aff3816a0 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
| @@ -216,8 +216,9 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) | |||
| 216 | 216 | ||
| 217 | 217 | ||
| 218 | #ifdef CONFIG_PM | 218 | #ifdef CONFIG_PM |
| 219 | static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state) | 219 | static int gpio_keys_suspend(struct device *dev) |
| 220 | { | 220 | { |
| 221 | struct platform_device *pdev = to_platform_device(dev); | ||
| 221 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | 222 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; |
| 222 | int i; | 223 | int i; |
| 223 | 224 | ||
| @@ -234,8 +235,9 @@ static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state) | |||
| 234 | return 0; | 235 | return 0; |
| 235 | } | 236 | } |
| 236 | 237 | ||
| 237 | static int gpio_keys_resume(struct platform_device *pdev) | 238 | static int gpio_keys_resume(struct device *dev) |
| 238 | { | 239 | { |
| 240 | struct platform_device *pdev = to_platform_device(dev); | ||
| 239 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | 241 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; |
| 240 | int i; | 242 | int i; |
| 241 | 243 | ||
| @@ -251,19 +253,22 @@ static int gpio_keys_resume(struct platform_device *pdev) | |||
| 251 | 253 | ||
| 252 | return 0; | 254 | return 0; |
| 253 | } | 255 | } |
| 254 | #else | 256 | |
| 255 | #define gpio_keys_suspend NULL | 257 | static const struct dev_pm_ops gpio_keys_pm_ops = { |
| 256 | #define gpio_keys_resume NULL | 258 | .suspend = gpio_keys_suspend, |
| 259 | .resume = gpio_keys_resume, | ||
| 260 | }; | ||
| 257 | #endif | 261 | #endif |
| 258 | 262 | ||
| 259 | static struct platform_driver gpio_keys_device_driver = { | 263 | static struct platform_driver gpio_keys_device_driver = { |
| 260 | .probe = gpio_keys_probe, | 264 | .probe = gpio_keys_probe, |
| 261 | .remove = __devexit_p(gpio_keys_remove), | 265 | .remove = __devexit_p(gpio_keys_remove), |
| 262 | .suspend = gpio_keys_suspend, | ||
| 263 | .resume = gpio_keys_resume, | ||
| 264 | .driver = { | 266 | .driver = { |
| 265 | .name = "gpio-keys", | 267 | .name = "gpio-keys", |
| 266 | .owner = THIS_MODULE, | 268 | .owner = THIS_MODULE, |
| 269 | #ifdef CONFIG_PM | ||
| 270 | .pm = &gpio_keys_pm_ops, | ||
| 271 | #endif | ||
| 267 | } | 272 | } |
| 268 | }; | 273 | }; |
| 269 | 274 | ||
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index 6f356705ee3b..c83f4b2ec7d3 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c | |||
| @@ -37,19 +37,19 @@ | |||
| 37 | #include <linux/kernel.h> | 37 | #include <linux/kernel.h> |
| 38 | #include <linux/module.h> | 38 | #include <linux/module.h> |
| 39 | #include <linux/init.h> | 39 | #include <linux/init.h> |
| 40 | #include <linux/semaphore.h> | 40 | #include <linux/completion.h> |
| 41 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
| 42 | #include <linux/pci_ids.h> | 42 | #include <linux/pci_ids.h> |
| 43 | 43 | ||
| 44 | #define PREFIX "HIL KEYB: " | 44 | #define PREFIX "HIL: " |
| 45 | #define HIL_GENERIC_NAME "HIL keyboard" | ||
| 46 | 45 | ||
| 47 | MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>"); | 46 | MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>"); |
| 48 | MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver"); | 47 | MODULE_DESCRIPTION("HIL keyboard/mouse driver"); |
| 49 | MODULE_LICENSE("Dual BSD/GPL"); | 48 | MODULE_LICENSE("Dual BSD/GPL"); |
| 50 | MODULE_ALIAS("serio:ty03pr25id00ex*"); | 49 | MODULE_ALIAS("serio:ty03pr25id00ex*"); /* HIL keyboard */ |
| 50 | MODULE_ALIAS("serio:ty03pr25id0Fex*"); /* HIL mouse */ | ||
| 51 | 51 | ||
| 52 | #define HIL_KBD_MAX_LENGTH 16 | 52 | #define HIL_PACKET_MAX_LENGTH 16 |
| 53 | 53 | ||
| 54 | #define HIL_KBD_SET1_UPBIT 0x01 | 54 | #define HIL_KBD_SET1_UPBIT 0x01 |
| 55 | #define HIL_KBD_SET1_SHIFT 1 | 55 | #define HIL_KBD_SET1_SHIFT 1 |
| @@ -67,308 +67,497 @@ static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] __read_mostly = | |||
| 67 | 67 | ||
| 68 | static const char hil_language[][16] = { HIL_LOCALE_MAP }; | 68 | static const char hil_language[][16] = { HIL_LOCALE_MAP }; |
| 69 | 69 | ||
| 70 | struct hil_kbd { | 70 | struct hil_dev { |
| 71 | struct input_dev *dev; | 71 | struct input_dev *dev; |
| 72 | struct serio *serio; | 72 | struct serio *serio; |
| 73 | 73 | ||
| 74 | /* Input buffer and index for packets from HIL bus. */ | 74 | /* Input buffer and index for packets from HIL bus. */ |
| 75 | hil_packet data[HIL_KBD_MAX_LENGTH]; | 75 | hil_packet data[HIL_PACKET_MAX_LENGTH]; |
| 76 | int idx4; /* four counts per packet */ | 76 | int idx4; /* four counts per packet */ |
| 77 | 77 | ||
| 78 | /* Raw device info records from HIL bus, see hil.h for fields. */ | 78 | /* Raw device info records from HIL bus, see hil.h for fields. */ |
| 79 | char idd[HIL_KBD_MAX_LENGTH]; /* DID byte and IDD record */ | 79 | char idd[HIL_PACKET_MAX_LENGTH]; /* DID byte and IDD record */ |
| 80 | char rsc[HIL_KBD_MAX_LENGTH]; /* RSC record */ | 80 | char rsc[HIL_PACKET_MAX_LENGTH]; /* RSC record */ |
| 81 | char exd[HIL_KBD_MAX_LENGTH]; /* EXD record */ | 81 | char exd[HIL_PACKET_MAX_LENGTH]; /* EXD record */ |
| 82 | char rnm[HIL_KBD_MAX_LENGTH + 1]; /* RNM record + NULL term. */ | 82 | char rnm[HIL_PACKET_MAX_LENGTH + 1]; /* RNM record + NULL term. */ |
| 83 | 83 | ||
| 84 | /* Something to sleep around with. */ | 84 | struct completion cmd_done; |
| 85 | struct semaphore sem; | 85 | |
| 86 | bool is_pointer; | ||
| 87 | /* Extra device details needed for pointing devices. */ | ||
| 88 | unsigned int nbtn, naxes; | ||
| 89 | unsigned int btnmap[7]; | ||
| 86 | }; | 90 | }; |
| 87 | 91 | ||
| 88 | /* Process a complete packet after transfer from the HIL */ | 92 | static bool hil_dev_is_command_response(hil_packet p) |
| 89 | static void hil_kbd_process_record(struct hil_kbd *kbd) | ||
| 90 | { | 93 | { |
| 91 | struct input_dev *dev = kbd->dev; | 94 | if ((p & ~HIL_CMDCT_POL) == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) |
| 92 | hil_packet *data = kbd->data; | 95 | return false; |
| 93 | hil_packet p; | ||
| 94 | int idx, i, cnt; | ||
| 95 | 96 | ||
| 96 | idx = kbd->idx4/4; | 97 | if ((p & ~HIL_CMDCT_RPL) == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) |
| 97 | p = data[idx - 1]; | 98 | return false; |
| 98 | 99 | ||
| 99 | if ((p & ~HIL_CMDCT_POL) == | 100 | return true; |
| 100 | (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) | 101 | } |
| 101 | goto report; | 102 | |
| 102 | if ((p & ~HIL_CMDCT_RPL) == | 103 | static void hil_dev_handle_command_response(struct hil_dev *dev) |
| 103 | (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) | 104 | { |
| 104 | goto report; | 105 | hil_packet p; |
| 106 | char *buf; | ||
| 107 | int i, idx; | ||
| 108 | |||
| 109 | idx = dev->idx4 / 4; | ||
| 110 | p = dev->data[idx - 1]; | ||
| 105 | 111 | ||
| 106 | /* Not a poll response. See if we are loading config records. */ | ||
| 107 | switch (p & HIL_PKT_DATA_MASK) { | 112 | switch (p & HIL_PKT_DATA_MASK) { |
| 108 | case HIL_CMD_IDD: | 113 | case HIL_CMD_IDD: |
| 109 | for (i = 0; i < idx; i++) | 114 | buf = dev->idd; |
| 110 | kbd->idd[i] = kbd->data[i] & HIL_PKT_DATA_MASK; | ||
| 111 | for (; i < HIL_KBD_MAX_LENGTH; i++) | ||
| 112 | kbd->idd[i] = 0; | ||
| 113 | break; | 115 | break; |
| 114 | 116 | ||
| 115 | case HIL_CMD_RSC: | 117 | case HIL_CMD_RSC: |
| 116 | for (i = 0; i < idx; i++) | 118 | buf = dev->rsc; |
| 117 | kbd->rsc[i] = kbd->data[i] & HIL_PKT_DATA_MASK; | ||
| 118 | for (; i < HIL_KBD_MAX_LENGTH; i++) | ||
| 119 | kbd->rsc[i] = 0; | ||
| 120 | break; | 119 | break; |
| 121 | 120 | ||
| 122 | case HIL_CMD_EXD: | 121 | case HIL_CMD_EXD: |
| 123 | for (i = 0; i < idx; i++) | 122 | buf = dev->exd; |
| 124 | kbd->exd[i] = kbd->data[i] & HIL_PKT_DATA_MASK; | ||
| 125 | for (; i < HIL_KBD_MAX_LENGTH; i++) | ||
| 126 | kbd->exd[i] = 0; | ||
| 127 | break; | 123 | break; |
| 128 | 124 | ||
| 129 | case HIL_CMD_RNM: | 125 | case HIL_CMD_RNM: |
| 130 | for (i = 0; i < idx; i++) | 126 | dev->rnm[HIL_PACKET_MAX_LENGTH] = 0; |
| 131 | kbd->rnm[i] = kbd->data[i] & HIL_PKT_DATA_MASK; | 127 | buf = dev->rnm; |
| 132 | for (; i < HIL_KBD_MAX_LENGTH + 1; i++) | ||
| 133 | kbd->rnm[i] = '\0'; | ||
| 134 | break; | 128 | break; |
| 135 | 129 | ||
| 136 | default: | 130 | default: |
| 137 | /* These occur when device isn't present */ | 131 | /* These occur when device isn't present */ |
| 138 | if (p == (HIL_ERR_INT | HIL_PKT_CMD)) | 132 | if (p != (HIL_ERR_INT | HIL_PKT_CMD)) { |
| 139 | break; | 133 | /* Anything else we'd like to know about. */ |
| 140 | /* Anything else we'd like to know about. */ | 134 | printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p); |
| 141 | printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p); | 135 | } |
| 142 | break; | 136 | goto out; |
| 143 | } | 137 | } |
| 144 | goto out; | ||
| 145 | 138 | ||
| 146 | report: | 139 | for (i = 0; i < idx; i++) |
| 147 | cnt = 1; | 140 | buf[i] = dev->data[i] & HIL_PKT_DATA_MASK; |
| 141 | for (; i < HIL_PACKET_MAX_LENGTH; i++) | ||
| 142 | buf[i] = 0; | ||
| 143 | out: | ||
| 144 | complete(&dev->cmd_done); | ||
| 145 | } | ||
| 146 | |||
| 147 | static void hil_dev_handle_kbd_events(struct hil_dev *kbd) | ||
| 148 | { | ||
| 149 | struct input_dev *dev = kbd->dev; | ||
| 150 | int idx = kbd->idx4 / 4; | ||
| 151 | int i; | ||
| 152 | |||
| 148 | switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) { | 153 | switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) { |
| 149 | case HIL_POL_CHARTYPE_NONE: | 154 | case HIL_POL_CHARTYPE_NONE: |
| 150 | break; | 155 | return; |
| 151 | 156 | ||
| 152 | case HIL_POL_CHARTYPE_ASCII: | 157 | case HIL_POL_CHARTYPE_ASCII: |
| 153 | while (cnt < idx - 1) | 158 | for (i = 1; i < idx - 1; i++) |
| 154 | input_report_key(dev, kbd->data[cnt++] & 0x7f, 1); | 159 | input_report_key(dev, kbd->data[i] & 0x7f, 1); |
| 155 | break; | 160 | break; |
| 156 | 161 | ||
| 157 | case HIL_POL_CHARTYPE_RSVD1: | 162 | case HIL_POL_CHARTYPE_RSVD1: |
| 158 | case HIL_POL_CHARTYPE_RSVD2: | 163 | case HIL_POL_CHARTYPE_RSVD2: |
| 159 | case HIL_POL_CHARTYPE_BINARY: | 164 | case HIL_POL_CHARTYPE_BINARY: |
| 160 | while (cnt < idx - 1) | 165 | for (i = 1; i < idx - 1; i++) |
| 161 | input_report_key(dev, kbd->data[cnt++], 1); | 166 | input_report_key(dev, kbd->data[i], 1); |
| 162 | break; | 167 | break; |
| 163 | 168 | ||
| 164 | case HIL_POL_CHARTYPE_SET1: | 169 | case HIL_POL_CHARTYPE_SET1: |
| 165 | while (cnt < idx - 1) { | 170 | for (i = 1; i < idx - 1; i++) { |
| 166 | unsigned int key; | 171 | unsigned int key = kbd->data[i]; |
| 167 | int up; | 172 | int up = key & HIL_KBD_SET1_UPBIT; |
| 168 | key = kbd->data[cnt++]; | 173 | |
| 169 | up = key & HIL_KBD_SET1_UPBIT; | ||
| 170 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); | 174 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); |
| 171 | key = hil_kbd_set1[key >> HIL_KBD_SET1_SHIFT]; | 175 | key = hil_kbd_set1[key >> HIL_KBD_SET1_SHIFT]; |
| 172 | if (key != KEY_RESERVED) | 176 | input_report_key(dev, key, !up); |
| 173 | input_report_key(dev, key, !up); | ||
| 174 | } | 177 | } |
| 175 | break; | 178 | break; |
| 176 | 179 | ||
| 177 | case HIL_POL_CHARTYPE_SET2: | 180 | case HIL_POL_CHARTYPE_SET2: |
| 178 | while (cnt < idx - 1) { | 181 | for (i = 1; i < idx - 1; i++) { |
| 179 | unsigned int key; | 182 | unsigned int key = kbd->data[i]; |
| 180 | int up; | 183 | int up = key & HIL_KBD_SET2_UPBIT; |
| 181 | key = kbd->data[cnt++]; | 184 | |
| 182 | up = key & HIL_KBD_SET2_UPBIT; | ||
| 183 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); | 185 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); |
| 184 | key = key >> HIL_KBD_SET2_SHIFT; | 186 | key = key >> HIL_KBD_SET2_SHIFT; |
| 185 | if (key != KEY_RESERVED) | 187 | input_report_key(dev, key, !up); |
| 186 | input_report_key(dev, key, !up); | ||
| 187 | } | 188 | } |
| 188 | break; | 189 | break; |
| 189 | 190 | ||
| 190 | case HIL_POL_CHARTYPE_SET3: | 191 | case HIL_POL_CHARTYPE_SET3: |
| 191 | while (cnt < idx - 1) { | 192 | for (i = 1; i < idx - 1; i++) { |
| 192 | unsigned int key; | 193 | unsigned int key = kbd->data[i]; |
| 193 | int up; | 194 | int up = key & HIL_KBD_SET3_UPBIT; |
| 194 | key = kbd->data[cnt++]; | 195 | |
| 195 | up = key & HIL_KBD_SET3_UPBIT; | ||
| 196 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); | 196 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); |
| 197 | key = hil_kbd_set3[key >> HIL_KBD_SET3_SHIFT]; | 197 | key = hil_kbd_set3[key >> HIL_KBD_SET3_SHIFT]; |
| 198 | if (key != KEY_RESERVED) | 198 | input_report_key(dev, key, !up); |
| 199 | input_report_key(dev, key, !up); | ||
| 200 | } | 199 | } |
| 201 | break; | 200 | break; |
| 202 | } | 201 | } |
| 203 | out: | 202 | |
| 204 | kbd->idx4 = 0; | 203 | input_sync(dev); |
| 205 | up(&kbd->sem); | ||
| 206 | } | 204 | } |
| 207 | 205 | ||
| 208 | static void hil_kbd_process_err(struct hil_kbd *kbd) | 206 | static void hil_dev_handle_ptr_events(struct hil_dev *ptr) |
| 207 | { | ||
| 208 | struct input_dev *dev = ptr->dev; | ||
| 209 | int idx = ptr->idx4 / 4; | ||
| 210 | hil_packet p = ptr->data[idx - 1]; | ||
| 211 | int i, cnt, laxis; | ||
| 212 | bool absdev, ax16; | ||
| 213 | |||
| 214 | if ((p & HIL_CMDCT_POL) != idx - 1) { | ||
| 215 | printk(KERN_WARNING PREFIX | ||
| 216 | "Malformed poll packet %x (idx = %i)\n", p, idx); | ||
| 217 | return; | ||
| 218 | } | ||
| 219 | |||
| 220 | i = (p & HIL_POL_AXIS_ALT) ? 3 : 0; | ||
| 221 | laxis = (p & HIL_POL_NUM_AXES_MASK) + i; | ||
| 222 | |||
| 223 | ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */ | ||
| 224 | absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; | ||
| 225 | |||
| 226 | for (cnt = 1; i < laxis; i++) { | ||
| 227 | unsigned int lo, hi, val; | ||
| 228 | |||
| 229 | lo = ptr->data[cnt++] & HIL_PKT_DATA_MASK; | ||
| 230 | hi = ax16 ? (ptr->data[cnt++] & HIL_PKT_DATA_MASK) : 0; | ||
| 231 | |||
| 232 | if (absdev) { | ||
| 233 | val = lo + (hi << 8); | ||
| 234 | #ifdef TABLET_AUTOADJUST | ||
| 235 | if (val < dev->absmin[ABS_X + i]) | ||
| 236 | dev->absmin[ABS_X + i] = val; | ||
| 237 | if (val > dev->absmax[ABS_X + i]) | ||
| 238 | dev->absmax[ABS_X + i] = val; | ||
| 239 | #endif | ||
| 240 | if (i%3) val = dev->absmax[ABS_X + i] - val; | ||
| 241 | input_report_abs(dev, ABS_X + i, val); | ||
| 242 | } else { | ||
| 243 | val = (int) (((int8_t)lo) | ((int8_t)hi << 8)); | ||
| 244 | if (i % 3) | ||
| 245 | val *= -1; | ||
| 246 | input_report_rel(dev, REL_X + i, val); | ||
| 247 | } | ||
| 248 | } | ||
| 249 | |||
| 250 | while (cnt < idx - 1) { | ||
| 251 | unsigned int btn = ptr->data[cnt++]; | ||
| 252 | int up = btn & 1; | ||
| 253 | |||
| 254 | btn &= 0xfe; | ||
| 255 | if (btn == 0x8e) | ||
| 256 | continue; /* TODO: proximity == touch? */ | ||
| 257 | if (btn > 0x8c || btn < 0x80) | ||
| 258 | continue; | ||
| 259 | btn = (btn - 0x80) >> 1; | ||
| 260 | btn = ptr->btnmap[btn]; | ||
| 261 | input_report_key(dev, btn, !up); | ||
| 262 | } | ||
| 263 | |||
| 264 | input_sync(dev); | ||
| 265 | } | ||
| 266 | |||
| 267 | static void hil_dev_process_err(struct hil_dev *dev) | ||
| 209 | { | 268 | { |
| 210 | printk(KERN_WARNING PREFIX "errored HIL packet\n"); | 269 | printk(KERN_WARNING PREFIX "errored HIL packet\n"); |
| 211 | kbd->idx4 = 0; | 270 | dev->idx4 = 0; |
| 212 | up(&kbd->sem); | 271 | complete(&dev->cmd_done); /* just in case somebody is waiting */ |
| 213 | } | 272 | } |
| 214 | 273 | ||
| 215 | static irqreturn_t hil_kbd_interrupt(struct serio *serio, | 274 | static irqreturn_t hil_dev_interrupt(struct serio *serio, |
| 216 | unsigned char data, unsigned int flags) | 275 | unsigned char data, unsigned int flags) |
| 217 | { | 276 | { |
| 218 | struct hil_kbd *kbd; | 277 | struct hil_dev *dev; |
| 219 | hil_packet packet; | 278 | hil_packet packet; |
| 220 | int idx; | 279 | int idx; |
| 221 | 280 | ||
| 222 | kbd = serio_get_drvdata(serio); | 281 | dev = serio_get_drvdata(serio); |
| 223 | BUG_ON(kbd == NULL); | 282 | BUG_ON(dev == NULL); |
| 224 | 283 | ||
| 225 | if (kbd->idx4 >= (HIL_KBD_MAX_LENGTH * sizeof(hil_packet))) { | 284 | if (dev->idx4 >= HIL_PACKET_MAX_LENGTH * sizeof(hil_packet)) { |
| 226 | hil_kbd_process_err(kbd); | 285 | hil_dev_process_err(dev); |
| 227 | return IRQ_HANDLED; | 286 | goto out; |
| 228 | } | 287 | } |
| 229 | idx = kbd->idx4/4; | 288 | |
| 230 | if (!(kbd->idx4 % 4)) | 289 | idx = dev->idx4 / 4; |
| 231 | kbd->data[idx] = 0; | 290 | if (!(dev->idx4 % 4)) |
| 232 | packet = kbd->data[idx]; | 291 | dev->data[idx] = 0; |
| 233 | packet |= ((hil_packet)data) << ((3 - (kbd->idx4 % 4)) * 8); | 292 | packet = dev->data[idx]; |
| 234 | kbd->data[idx] = packet; | 293 | packet |= ((hil_packet)data) << ((3 - (dev->idx4 % 4)) * 8); |
| 294 | dev->data[idx] = packet; | ||
| 235 | 295 | ||
| 236 | /* Records of N 4-byte hil_packets must terminate with a command. */ | 296 | /* Records of N 4-byte hil_packets must terminate with a command. */ |
| 237 | if ((++(kbd->idx4)) % 4) | 297 | if ((++dev->idx4 % 4) == 0) { |
| 238 | return IRQ_HANDLED; | 298 | if ((packet & 0xffff0000) != HIL_ERR_INT) { |
| 239 | if ((packet & 0xffff0000) != HIL_ERR_INT) { | 299 | hil_dev_process_err(dev); |
| 240 | hil_kbd_process_err(kbd); | 300 | } else if (packet & HIL_PKT_CMD) { |
| 241 | return IRQ_HANDLED; | 301 | if (hil_dev_is_command_response(packet)) |
| 302 | hil_dev_handle_command_response(dev); | ||
| 303 | else if (dev->is_pointer) | ||
| 304 | hil_dev_handle_ptr_events(dev); | ||
| 305 | else | ||
| 306 | hil_dev_handle_kbd_events(dev); | ||
| 307 | dev->idx4 = 0; | ||
| 308 | } | ||
| 242 | } | 309 | } |
| 243 | if (packet & HIL_PKT_CMD) | 310 | out: |
| 244 | hil_kbd_process_record(kbd); | ||
| 245 | return IRQ_HANDLED; | 311 | return IRQ_HANDLED; |
| 246 | } | 312 | } |
| 247 | 313 | ||
| 248 | static void hil_kbd_disconnect(struct serio *serio) | 314 | static void hil_dev_disconnect(struct serio *serio) |
| 249 | { | 315 | { |
| 250 | struct hil_kbd *kbd; | 316 | struct hil_dev *dev = serio_get_drvdata(serio); |
| 251 | 317 | ||
| 252 | kbd = serio_get_drvdata(serio); | 318 | BUG_ON(dev == NULL); |
| 253 | BUG_ON(kbd == NULL); | ||
| 254 | 319 | ||
| 255 | serio_close(serio); | 320 | serio_close(serio); |
| 256 | input_unregister_device(kbd->dev); | 321 | input_unregister_device(dev->dev); |
| 257 | kfree(kbd); | 322 | serio_set_drvdata(serio, NULL); |
| 323 | kfree(dev); | ||
| 324 | } | ||
| 325 | |||
| 326 | static void hil_dev_keyboard_setup(struct hil_dev *kbd) | ||
| 327 | { | ||
| 328 | struct input_dev *input_dev = kbd->dev; | ||
| 329 | uint8_t did = kbd->idd[0]; | ||
| 330 | int i; | ||
| 331 | |||
| 332 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | ||
| 333 | input_dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) | | ||
| 334 | BIT_MASK(LED_SCROLLL); | ||
| 335 | |||
| 336 | for (i = 0; i < 128; i++) { | ||
| 337 | __set_bit(hil_kbd_set1[i], input_dev->keybit); | ||
| 338 | __set_bit(hil_kbd_set3[i], input_dev->keybit); | ||
| 339 | } | ||
| 340 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
| 341 | |||
| 342 | input_dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE; | ||
| 343 | input_dev->keycodesize = sizeof(hil_kbd_set1[0]); | ||
| 344 | input_dev->keycode = hil_kbd_set1; | ||
| 345 | |||
| 346 | input_dev->name = strlen(kbd->rnm) ? kbd->rnm : "HIL keyboard"; | ||
| 347 | input_dev->phys = "hpkbd/input0"; | ||
| 348 | |||
| 349 | printk(KERN_INFO PREFIX "HIL keyboard found (did = 0x%02x, lang = %s)\n", | ||
| 350 | did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]); | ||
| 258 | } | 351 | } |
| 259 | 352 | ||
| 260 | static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv) | 353 | static void hil_dev_pointer_setup(struct hil_dev *ptr) |
| 261 | { | 354 | { |
| 262 | struct hil_kbd *kbd; | 355 | struct input_dev *input_dev = ptr->dev; |
| 263 | uint8_t did, *idd; | 356 | uint8_t did = ptr->idd[0]; |
| 264 | int i; | 357 | uint8_t *idd = ptr->idd + 1; |
| 358 | unsigned int naxsets = HIL_IDD_NUM_AXSETS(*idd); | ||
| 359 | unsigned int i, btntype; | ||
| 360 | const char *txt; | ||
| 361 | |||
| 362 | ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd); | ||
| 363 | |||
| 364 | switch (did & HIL_IDD_DID_TYPE_MASK) { | ||
| 365 | case HIL_IDD_DID_TYPE_REL: | ||
| 366 | input_dev->evbit[0] = BIT_MASK(EV_REL); | ||
| 265 | 367 | ||
| 266 | kbd = kzalloc(sizeof(*kbd), GFP_KERNEL); | 368 | for (i = 0; i < ptr->naxes; i++) |
| 267 | if (!kbd) | 369 | __set_bit(REL_X + i, input_dev->relbit); |
| 268 | return -ENOMEM; | ||
| 269 | 370 | ||
| 270 | kbd->dev = input_allocate_device(); | 371 | for (i = 3; naxsets > 1 && i < ptr->naxes + 3; i++) |
| 271 | if (!kbd->dev) | 372 | __set_bit(REL_X + i, input_dev->relbit); |
| 373 | |||
| 374 | txt = "relative"; | ||
| 375 | break; | ||
| 376 | |||
| 377 | case HIL_IDD_DID_TYPE_ABS: | ||
| 378 | input_dev->evbit[0] = BIT_MASK(EV_ABS); | ||
| 379 | |||
| 380 | for (i = 0; i < ptr->naxes; i++) | ||
| 381 | input_set_abs_params(input_dev, ABS_X + i, | ||
| 382 | 0, HIL_IDD_AXIS_MAX(idd, i), 0, 0); | ||
| 383 | |||
| 384 | for (i = 3; naxsets > 1 && i < ptr->naxes + 3; i++) | ||
| 385 | input_set_abs_params(input_dev, ABS_X + i, | ||
| 386 | 0, HIL_IDD_AXIS_MAX(idd, i - 3), 0, 0); | ||
| 387 | |||
| 388 | #ifdef TABLET_AUTOADJUST | ||
| 389 | for (i = 0; i < ABS_MAX; i++) { | ||
| 390 | int diff = input_dev->absmax[ABS_X + i] / 10; | ||
| 391 | input_dev->absmin[ABS_X + i] += diff; | ||
| 392 | input_dev->absmax[ABS_X + i] -= diff; | ||
| 393 | } | ||
| 394 | #endif | ||
| 395 | |||
| 396 | txt = "absolute"; | ||
| 397 | break; | ||
| 398 | |||
| 399 | default: | ||
| 400 | BUG(); | ||
| 401 | } | ||
| 402 | |||
| 403 | ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd); | ||
| 404 | if (ptr->nbtn) | ||
| 405 | input_dev->evbit[0] |= BIT_MASK(EV_KEY); | ||
| 406 | |||
| 407 | btntype = BTN_MISC; | ||
| 408 | if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET) | ||
| 409 | #ifdef TABLET_SIMULATES_MOUSE | ||
| 410 | btntype = BTN_TOUCH; | ||
| 411 | #else | ||
| 412 | btntype = BTN_DIGI; | ||
| 413 | #endif | ||
| 414 | if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN) | ||
| 415 | btntype = BTN_TOUCH; | ||
| 416 | |||
| 417 | if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE) | ||
| 418 | btntype = BTN_MOUSE; | ||
| 419 | |||
| 420 | for (i = 0; i < ptr->nbtn; i++) { | ||
| 421 | __set_bit(btntype | i, input_dev->keybit); | ||
| 422 | ptr->btnmap[i] = btntype | i; | ||
| 423 | } | ||
| 424 | |||
| 425 | if (btntype == BTN_MOUSE) { | ||
| 426 | /* Swap buttons 2 and 3 */ | ||
| 427 | ptr->btnmap[1] = BTN_MIDDLE; | ||
| 428 | ptr->btnmap[2] = BTN_RIGHT; | ||
| 429 | } | ||
| 430 | |||
| 431 | input_dev->name = strlen(ptr->rnm) ? ptr->rnm : "HIL pointer device"; | ||
| 432 | |||
| 433 | printk(KERN_INFO PREFIX | ||
| 434 | "HIL pointer device found (did: 0x%02x, axis: %s)\n", | ||
| 435 | did, txt); | ||
| 436 | printk(KERN_INFO PREFIX | ||
| 437 | "HIL pointer has %i buttons and %i sets of %i axes\n", | ||
| 438 | ptr->nbtn, naxsets, ptr->naxes); | ||
| 439 | } | ||
| 440 | |||
| 441 | static int hil_dev_connect(struct serio *serio, struct serio_driver *drv) | ||
| 442 | { | ||
| 443 | struct hil_dev *dev; | ||
| 444 | struct input_dev *input_dev; | ||
| 445 | uint8_t did, *idd; | ||
| 446 | int error; | ||
| 447 | |||
| 448 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
| 449 | input_dev = input_allocate_device(); | ||
| 450 | if (!dev || !input_dev) { | ||
| 451 | error = -ENOMEM; | ||
| 272 | goto bail0; | 452 | goto bail0; |
| 453 | } | ||
| 273 | 454 | ||
| 274 | if (serio_open(serio, drv)) | 455 | dev->serio = serio; |
| 275 | goto bail1; | 456 | dev->dev = input_dev; |
| 276 | 457 | ||
| 277 | serio_set_drvdata(serio, kbd); | 458 | error = serio_open(serio, drv); |
| 278 | kbd->serio = serio; | 459 | if (error) |
| 460 | goto bail0; | ||
| 279 | 461 | ||
| 280 | init_MUTEX_LOCKED(&kbd->sem); | 462 | serio_set_drvdata(serio, dev); |
| 281 | 463 | ||
| 282 | /* Get device info. MLC driver supplies devid/status/etc. */ | 464 | /* Get device info. MLC driver supplies devid/status/etc. */ |
| 283 | serio->write(serio, 0); | 465 | init_completion(&dev->cmd_done); |
| 284 | serio->write(serio, 0); | 466 | serio_write(serio, 0); |
| 285 | serio->write(serio, HIL_PKT_CMD >> 8); | 467 | serio_write(serio, 0); |
| 286 | serio->write(serio, HIL_CMD_IDD); | 468 | serio_write(serio, HIL_PKT_CMD >> 8); |
| 287 | down(&kbd->sem); | 469 | serio_write(serio, HIL_CMD_IDD); |
| 288 | 470 | error = wait_for_completion_killable(&dev->cmd_done); | |
| 289 | serio->write(serio, 0); | 471 | if (error) |
| 290 | serio->write(serio, 0); | 472 | goto bail1; |
| 291 | serio->write(serio, HIL_PKT_CMD >> 8); | 473 | |
| 292 | serio->write(serio, HIL_CMD_RSC); | 474 | init_completion(&dev->cmd_done); |
| 293 | down(&kbd->sem); | 475 | serio_write(serio, 0); |
| 294 | 476 | serio_write(serio, 0); | |
| 295 | serio->write(serio, 0); | 477 | serio_write(serio, HIL_PKT_CMD >> 8); |
| 296 | serio->write(serio, 0); | 478 | serio_write(serio, HIL_CMD_RSC); |
| 297 | serio->write(serio, HIL_PKT_CMD >> 8); | 479 | error = wait_for_completion_killable(&dev->cmd_done); |
| 298 | serio->write(serio, HIL_CMD_RNM); | 480 | if (error) |
| 299 | down(&kbd->sem); | 481 | goto bail1; |
| 300 | 482 | ||
| 301 | serio->write(serio, 0); | 483 | init_completion(&dev->cmd_done); |
| 302 | serio->write(serio, 0); | 484 | serio_write(serio, 0); |
| 303 | serio->write(serio, HIL_PKT_CMD >> 8); | 485 | serio_write(serio, 0); |
| 304 | serio->write(serio, HIL_CMD_EXD); | 486 | serio_write(serio, HIL_PKT_CMD >> 8); |
| 305 | down(&kbd->sem); | 487 | serio_write(serio, HIL_CMD_RNM); |
| 306 | 488 | error = wait_for_completion_killable(&dev->cmd_done); | |
| 307 | up(&kbd->sem); | 489 | if (error) |
| 308 | 490 | goto bail1; | |
| 309 | did = kbd->idd[0]; | 491 | |
| 310 | idd = kbd->idd + 1; | 492 | init_completion(&dev->cmd_done); |
| 493 | serio_write(serio, 0); | ||
| 494 | serio_write(serio, 0); | ||
| 495 | serio_write(serio, HIL_PKT_CMD >> 8); | ||
| 496 | serio_write(serio, HIL_CMD_EXD); | ||
| 497 | error = wait_for_completion_killable(&dev->cmd_done); | ||
| 498 | if (error) | ||
| 499 | goto bail1; | ||
| 500 | |||
| 501 | did = dev->idd[0]; | ||
| 502 | idd = dev->idd + 1; | ||
| 503 | |||
| 311 | switch (did & HIL_IDD_DID_TYPE_MASK) { | 504 | switch (did & HIL_IDD_DID_TYPE_MASK) { |
| 312 | case HIL_IDD_DID_TYPE_KB_INTEGRAL: | 505 | case HIL_IDD_DID_TYPE_KB_INTEGRAL: |
| 313 | case HIL_IDD_DID_TYPE_KB_ITF: | 506 | case HIL_IDD_DID_TYPE_KB_ITF: |
| 314 | case HIL_IDD_DID_TYPE_KB_RSVD: | 507 | case HIL_IDD_DID_TYPE_KB_RSVD: |
| 315 | case HIL_IDD_DID_TYPE_CHAR: | 508 | case HIL_IDD_DID_TYPE_CHAR: |
| 316 | printk(KERN_INFO PREFIX "HIL keyboard found (did = 0x%02x, lang = %s)\n", | 509 | if (HIL_IDD_NUM_BUTTONS(idd) || |
| 317 | did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]); | 510 | HIL_IDD_NUM_AXES_PER_SET(*idd)) { |
| 318 | break; | 511 | printk(KERN_INFO PREFIX |
| 319 | default: | 512 | "combo devices are not supported.\n"); |
| 320 | goto bail2; | 513 | goto bail1; |
| 321 | } | 514 | } |
| 322 | 515 | ||
| 323 | if (HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) { | 516 | dev->is_pointer = false; |
| 324 | printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n"); | 517 | hil_dev_keyboard_setup(dev); |
| 325 | goto bail2; | 518 | break; |
| 326 | } | ||
| 327 | 519 | ||
| 328 | kbd->dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | 520 | case HIL_IDD_DID_TYPE_REL: |
| 329 | kbd->dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) | | 521 | case HIL_IDD_DID_TYPE_ABS: |
| 330 | BIT_MASK(LED_SCROLLL); | 522 | dev->is_pointer = true; |
| 331 | kbd->dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE; | 523 | hil_dev_pointer_setup(dev); |
| 332 | kbd->dev->keycodesize = sizeof(hil_kbd_set1[0]); | 524 | break; |
| 333 | kbd->dev->keycode = hil_kbd_set1; | ||
| 334 | kbd->dev->name = strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME; | ||
| 335 | kbd->dev->phys = "hpkbd/input0"; /* XXX */ | ||
| 336 | |||
| 337 | kbd->dev->id.bustype = BUS_HIL; | ||
| 338 | kbd->dev->id.vendor = PCI_VENDOR_ID_HP; | ||
| 339 | kbd->dev->id.product = 0x0001; /* TODO: get from kbd->rsc */ | ||
| 340 | kbd->dev->id.version = 0x0100; /* TODO: get from kbd->rsc */ | ||
| 341 | kbd->dev->dev.parent = &serio->dev; | ||
| 342 | 525 | ||
| 343 | for (i = 0; i < 128; i++) { | 526 | default: |
| 344 | set_bit(hil_kbd_set1[i], kbd->dev->keybit); | 527 | goto bail1; |
| 345 | set_bit(hil_kbd_set3[i], kbd->dev->keybit); | ||
| 346 | } | 528 | } |
| 347 | clear_bit(0, kbd->dev->keybit); | ||
| 348 | 529 | ||
| 349 | input_register_device(kbd->dev); | 530 | input_dev->id.bustype = BUS_HIL; |
| 350 | printk(KERN_INFO "input: %s, ID: %d\n", | 531 | input_dev->id.vendor = PCI_VENDOR_ID_HP; |
| 351 | kbd->dev->name, did); | 532 | input_dev->id.product = 0x0001; /* TODO: get from kbd->rsc */ |
| 533 | input_dev->id.version = 0x0100; /* TODO: get from kbd->rsc */ | ||
| 534 | input_dev->dev.parent = &serio->dev; | ||
| 535 | |||
| 536 | if (!dev->is_pointer) { | ||
| 537 | serio_write(serio, 0); | ||
| 538 | serio_write(serio, 0); | ||
| 539 | serio_write(serio, HIL_PKT_CMD >> 8); | ||
| 540 | /* Enable Keyswitch Autorepeat 1 */ | ||
| 541 | serio_write(serio, HIL_CMD_EK1); | ||
| 542 | /* No need to wait for completion */ | ||
| 543 | } | ||
| 352 | 544 | ||
| 353 | serio->write(serio, 0); | 545 | error = input_register_device(input_dev); |
| 354 | serio->write(serio, 0); | 546 | if (error) |
| 355 | serio->write(serio, HIL_PKT_CMD >> 8); | 547 | goto bail1; |
| 356 | serio->write(serio, HIL_CMD_EK1); /* Enable Keyswitch Autorepeat 1 */ | ||
| 357 | down(&kbd->sem); | ||
| 358 | up(&kbd->sem); | ||
| 359 | 548 | ||
| 360 | return 0; | 549 | return 0; |
| 361 | bail2: | 550 | |
| 551 | bail1: | ||
| 362 | serio_close(serio); | 552 | serio_close(serio); |
| 363 | serio_set_drvdata(serio, NULL); | 553 | serio_set_drvdata(serio, NULL); |
| 364 | bail1: | ||
| 365 | input_free_device(kbd->dev); | ||
| 366 | bail0: | 554 | bail0: |
| 367 | kfree(kbd); | 555 | input_free_device(input_dev); |
| 368 | return -EIO; | 556 | kfree(dev); |
| 557 | return error; | ||
| 369 | } | 558 | } |
| 370 | 559 | ||
| 371 | static struct serio_device_id hil_kbd_ids[] = { | 560 | static struct serio_device_id hil_dev_ids[] = { |
| 372 | { | 561 | { |
| 373 | .type = SERIO_HIL_MLC, | 562 | .type = SERIO_HIL_MLC, |
| 374 | .proto = SERIO_HIL, | 563 | .proto = SERIO_HIL, |
| @@ -378,26 +567,26 @@ static struct serio_device_id hil_kbd_ids[] = { | |||
| 378 | { 0 } | 567 | { 0 } |
| 379 | }; | 568 | }; |
| 380 | 569 | ||
| 381 | static struct serio_driver hil_kbd_serio_drv = { | 570 | static struct serio_driver hil_serio_drv = { |
| 382 | .driver = { | 571 | .driver = { |
| 383 | .name = "hil_kbd", | 572 | .name = "hil_dev", |
| 384 | }, | 573 | }, |
| 385 | .description = "HP HIL keyboard driver", | 574 | .description = "HP HIL keyboard/mouse/tablet driver", |
| 386 | .id_table = hil_kbd_ids, | 575 | .id_table = hil_dev_ids, |
| 387 | .connect = hil_kbd_connect, | 576 | .connect = hil_dev_connect, |
| 388 | .disconnect = hil_kbd_disconnect, | 577 | .disconnect = hil_dev_disconnect, |
| 389 | .interrupt = hil_kbd_interrupt | 578 | .interrupt = hil_dev_interrupt |
| 390 | }; | 579 | }; |
| 391 | 580 | ||
| 392 | static int __init hil_kbd_init(void) | 581 | static int __init hil_dev_init(void) |
| 393 | { | 582 | { |
| 394 | return serio_register_driver(&hil_kbd_serio_drv); | 583 | return serio_register_driver(&hil_serio_drv); |
| 395 | } | 584 | } |
| 396 | 585 | ||
| 397 | static void __exit hil_kbd_exit(void) | 586 | static void __exit hil_dev_exit(void) |
| 398 | { | 587 | { |
| 399 | serio_unregister_driver(&hil_kbd_serio_drv); | 588 | serio_unregister_driver(&hil_serio_drv); |
| 400 | } | 589 | } |
| 401 | 590 | ||
| 402 | module_init(hil_kbd_init); | 591 | module_init(hil_dev_init); |
| 403 | module_exit(hil_kbd_exit); | 592 | module_exit(hil_dev_exit); |
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 4730ef35c732..f9847e0fb553 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c | |||
| @@ -525,12 +525,12 @@ lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code, | |||
| 525 | CHECK_LED (lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); | 525 | CHECK_LED (lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); |
| 526 | CHECK_LED (lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); | 526 | CHECK_LED (lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); |
| 527 | if (leds_on != 0) { | 527 | if (leds_on != 0) { |
| 528 | lk->serio->write (lk->serio, LK_CMD_LED_ON); | 528 | serio_write (lk->serio, LK_CMD_LED_ON); |
| 529 | lk->serio->write (lk->serio, leds_on); | 529 | serio_write (lk->serio, leds_on); |
| 530 | } | 530 | } |
| 531 | if (leds_off != 0) { | 531 | if (leds_off != 0) { |
| 532 | lk->serio->write (lk->serio, LK_CMD_LED_OFF); | 532 | serio_write (lk->serio, LK_CMD_LED_OFF); |
| 533 | lk->serio->write (lk->serio, leds_off); | 533 | serio_write (lk->serio, leds_off); |
| 534 | } | 534 | } |
| 535 | return 0; | 535 | return 0; |
| 536 | 536 | ||
| @@ -539,20 +539,20 @@ lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code, | |||
| 539 | case SND_CLICK: | 539 | case SND_CLICK: |
| 540 | if (value == 0) { | 540 | if (value == 0) { |
| 541 | DBG ("%s: Deactivating key clicks\n", __func__); | 541 | DBG ("%s: Deactivating key clicks\n", __func__); |
| 542 | lk->serio->write (lk->serio, LK_CMD_DISABLE_KEYCLICK); | 542 | serio_write (lk->serio, LK_CMD_DISABLE_KEYCLICK); |
| 543 | lk->serio->write (lk->serio, LK_CMD_DISABLE_CTRCLICK); | 543 | serio_write (lk->serio, LK_CMD_DISABLE_CTRCLICK); |
| 544 | } else { | 544 | } else { |
| 545 | DBG ("%s: Activating key clicks\n", __func__); | 545 | DBG ("%s: Activating key clicks\n", __func__); |
| 546 | lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK); | 546 | serio_write (lk->serio, LK_CMD_ENABLE_KEYCLICK); |
| 547 | lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume)); | 547 | serio_write (lk->serio, volume_to_hw (lk->keyclick_volume)); |
| 548 | lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK); | 548 | serio_write (lk->serio, LK_CMD_ENABLE_CTRCLICK); |
| 549 | lk->serio->write (lk->serio, volume_to_hw (lk->ctrlclick_volume)); | 549 | serio_write (lk->serio, volume_to_hw (lk->ctrlclick_volume)); |
| 550 | } | 550 | } |
| 551 | return 0; | 551 | return 0; |
| 552 | 552 | ||
| 553 | case SND_BELL: | 553 | case SND_BELL: |
| 554 | if (value != 0) | 554 | if (value != 0) |
| 555 | lk->serio->write (lk->serio, LK_CMD_SOUND_BELL); | 555 | serio_write (lk->serio, LK_CMD_SOUND_BELL); |
| 556 | 556 | ||
| 557 | return 0; | 557 | return 0; |
| 558 | } | 558 | } |
| @@ -579,10 +579,10 @@ lkkbd_reinit (struct work_struct *work) | |||
| 579 | unsigned char leds_off = 0; | 579 | unsigned char leds_off = 0; |
| 580 | 580 | ||
| 581 | /* Ask for ID */ | 581 | /* Ask for ID */ |
| 582 | lk->serio->write (lk->serio, LK_CMD_REQUEST_ID); | 582 | serio_write (lk->serio, LK_CMD_REQUEST_ID); |
| 583 | 583 | ||
| 584 | /* Reset parameters */ | 584 | /* Reset parameters */ |
| 585 | lk->serio->write (lk->serio, LK_CMD_SET_DEFAULTS); | 585 | serio_write (lk->serio, LK_CMD_SET_DEFAULTS); |
| 586 | 586 | ||
| 587 | /* Set LEDs */ | 587 | /* Set LEDs */ |
| 588 | CHECK_LED (lk, leds_on, leds_off, LED_CAPSL, LK_LED_SHIFTLOCK); | 588 | CHECK_LED (lk, leds_on, leds_off, LED_CAPSL, LK_LED_SHIFTLOCK); |
| @@ -590,12 +590,12 @@ lkkbd_reinit (struct work_struct *work) | |||
| 590 | CHECK_LED (lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); | 590 | CHECK_LED (lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); |
| 591 | CHECK_LED (lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); | 591 | CHECK_LED (lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); |
| 592 | if (leds_on != 0) { | 592 | if (leds_on != 0) { |
| 593 | lk->serio->write (lk->serio, LK_CMD_LED_ON); | 593 | serio_write (lk->serio, LK_CMD_LED_ON); |
| 594 | lk->serio->write (lk->serio, leds_on); | 594 | serio_write (lk->serio, leds_on); |
| 595 | } | 595 | } |
| 596 | if (leds_off != 0) { | 596 | if (leds_off != 0) { |
| 597 | lk->serio->write (lk->serio, LK_CMD_LED_OFF); | 597 | serio_write (lk->serio, LK_CMD_LED_OFF); |
| 598 | lk->serio->write (lk->serio, leds_off); | 598 | serio_write (lk->serio, leds_off); |
| 599 | } | 599 | } |
| 600 | 600 | ||
| 601 | /* | 601 | /* |
| @@ -603,31 +603,31 @@ lkkbd_reinit (struct work_struct *work) | |||
| 603 | * only work with a LK401 keyboard and grants access to | 603 | * only work with a LK401 keyboard and grants access to |
| 604 | * LAlt, RAlt, RCompose and RShift. | 604 | * LAlt, RAlt, RCompose and RShift. |
| 605 | */ | 605 | */ |
| 606 | lk->serio->write (lk->serio, LK_CMD_ENABLE_LK401); | 606 | serio_write (lk->serio, LK_CMD_ENABLE_LK401); |
| 607 | 607 | ||
| 608 | /* Set all keys to UPDOWN mode */ | 608 | /* Set all keys to UPDOWN mode */ |
| 609 | for (division = 1; division <= 14; division++) | 609 | for (division = 1; division <= 14; division++) |
| 610 | lk->serio->write (lk->serio, LK_CMD_SET_MODE (LK_MODE_UPDOWN, | 610 | serio_write (lk->serio, LK_CMD_SET_MODE (LK_MODE_UPDOWN, |
| 611 | division)); | 611 | division)); |
| 612 | 612 | ||
| 613 | /* Enable bell and set volume */ | 613 | /* Enable bell and set volume */ |
| 614 | lk->serio->write (lk->serio, LK_CMD_ENABLE_BELL); | 614 | serio_write (lk->serio, LK_CMD_ENABLE_BELL); |
| 615 | lk->serio->write (lk->serio, volume_to_hw (lk->bell_volume)); | 615 | serio_write (lk->serio, volume_to_hw (lk->bell_volume)); |
| 616 | 616 | ||
| 617 | /* Enable/disable keyclick (and possibly set volume) */ | 617 | /* Enable/disable keyclick (and possibly set volume) */ |
| 618 | if (test_bit (SND_CLICK, lk->dev->snd)) { | 618 | if (test_bit (SND_CLICK, lk->dev->snd)) { |
| 619 | lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK); | 619 | serio_write (lk->serio, LK_CMD_ENABLE_KEYCLICK); |
| 620 | lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume)); | 620 | serio_write (lk->serio, volume_to_hw (lk->keyclick_volume)); |
| 621 | lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK); | 621 | serio_write (lk->serio, LK_CMD_ENABLE_CTRCLICK); |
| 622 | lk->serio->write (lk->serio, volume_to_hw (lk->ctrlclick_volume)); | 622 | serio_write (lk->serio, volume_to_hw (lk->ctrlclick_volume)); |
| 623 | } else { | 623 | } else { |
| 624 | lk->serio->write (lk->serio, LK_CMD_DISABLE_KEYCLICK); | 624 | serio_write (lk->serio, LK_CMD_DISABLE_KEYCLICK); |
| 625 | lk->serio->write (lk->serio, LK_CMD_DISABLE_CTRCLICK); | 625 | serio_write (lk->serio, LK_CMD_DISABLE_CTRCLICK); |
| 626 | } | 626 | } |
| 627 | 627 | ||
| 628 | /* Sound the bell if needed */ | 628 | /* Sound the bell if needed */ |
| 629 | if (test_bit (SND_BELL, lk->dev->snd)) | 629 | if (test_bit (SND_BELL, lk->dev->snd)) |
| 630 | lk->serio->write (lk->serio, LK_CMD_SOUND_BELL); | 630 | serio_write (lk->serio, LK_CMD_SOUND_BELL); |
| 631 | } | 631 | } |
| 632 | 632 | ||
| 633 | /* | 633 | /* |
| @@ -684,8 +684,10 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv) | |||
| 684 | input_dev->keycode = lk->keycode; | 684 | input_dev->keycode = lk->keycode; |
| 685 | input_dev->keycodesize = sizeof (lk_keycode_t); | 685 | input_dev->keycodesize = sizeof (lk_keycode_t); |
| 686 | input_dev->keycodemax = LK_NUM_KEYCODES; | 686 | input_dev->keycodemax = LK_NUM_KEYCODES; |
| 687 | |||
| 687 | for (i = 0; i < LK_NUM_KEYCODES; i++) | 688 | for (i = 0; i < LK_NUM_KEYCODES; i++) |
| 688 | set_bit (lk->keycode[i], input_dev->keybit); | 689 | __set_bit (lk->keycode[i], input_dev->keybit); |
| 690 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
| 689 | 691 | ||
| 690 | serio_set_drvdata (serio, lk); | 692 | serio_set_drvdata (serio, lk); |
| 691 | 693 | ||
| @@ -697,7 +699,7 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv) | |||
| 697 | if (err) | 699 | if (err) |
| 698 | goto fail3; | 700 | goto fail3; |
| 699 | 701 | ||
| 700 | lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET); | 702 | serio_write (lk->serio, LK_CMD_POWERCYCLE_RESET); |
| 701 | 703 | ||
| 702 | return 0; | 704 | return 0; |
| 703 | 705 | ||
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 541b981ff075..91cfe5170265 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c | |||
| @@ -319,7 +319,6 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev) | |||
| 319 | struct input_dev *input_dev; | 319 | struct input_dev *input_dev; |
| 320 | unsigned short *keycodes; | 320 | unsigned short *keycodes; |
| 321 | unsigned int row_shift; | 321 | unsigned int row_shift; |
| 322 | int i; | ||
| 323 | int err; | 322 | int err; |
| 324 | 323 | ||
| 325 | pdata = pdev->dev.platform_data; | 324 | pdata = pdev->dev.platform_data; |
| @@ -363,18 +362,10 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev) | |||
| 363 | 362 | ||
| 364 | input_dev->keycode = keycodes; | 363 | input_dev->keycode = keycodes; |
| 365 | input_dev->keycodesize = sizeof(*keycodes); | 364 | input_dev->keycodesize = sizeof(*keycodes); |
| 366 | input_dev->keycodemax = pdata->num_row_gpios << keypad->row_shift; | 365 | input_dev->keycodemax = pdata->num_row_gpios << row_shift; |
| 367 | |||
| 368 | for (i = 0; i < keymap_data->keymap_size; i++) { | ||
| 369 | unsigned int key = keymap_data->keymap[i]; | ||
| 370 | unsigned int row = KEY_ROW(key); | ||
| 371 | unsigned int col = KEY_COL(key); | ||
| 372 | unsigned short code = KEY_VAL(key); | ||
| 373 | 366 | ||
| 374 | keycodes[MATRIX_SCAN_CODE(row, col, row_shift)] = code; | 367 | matrix_keypad_build_keymap(keymap_data, row_shift, |
| 375 | __set_bit(code, input_dev->keybit); | 368 | input_dev->keycode, input_dev->keybit); |
| 376 | } | ||
| 377 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
| 378 | 369 | ||
| 379 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | 370 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); |
| 380 | input_set_drvdata(input_dev, keypad); | 371 | input_set_drvdata(input_dev, keypad); |
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 0d2fc64a5e1c..76f9668221a4 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c | |||
| @@ -25,13 +25,13 @@ | |||
| 25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
| 26 | #include <linux/clk.h> | 26 | #include <linux/clk.h> |
| 27 | #include <linux/err.h> | 27 | #include <linux/err.h> |
| 28 | #include <linux/input/matrix_keypad.h> | ||
| 28 | 29 | ||
| 29 | #include <asm/mach/arch.h> | 30 | #include <asm/mach/arch.h> |
| 30 | #include <asm/mach/map.h> | 31 | #include <asm/mach/map.h> |
| 31 | 32 | ||
| 32 | #include <mach/hardware.h> | 33 | #include <mach/hardware.h> |
| 33 | #include <mach/pxa27x_keypad.h> | 34 | #include <mach/pxa27x_keypad.h> |
| 34 | |||
| 35 | /* | 35 | /* |
| 36 | * Keypad Controller registers | 36 | * Keypad Controller registers |
| 37 | */ | 37 | */ |
| @@ -95,7 +95,8 @@ | |||
| 95 | #define keypad_readl(off) __raw_readl(keypad->mmio_base + (off)) | 95 | #define keypad_readl(off) __raw_readl(keypad->mmio_base + (off)) |
| 96 | #define keypad_writel(off, v) __raw_writel((v), keypad->mmio_base + (off)) | 96 | #define keypad_writel(off, v) __raw_writel((v), keypad->mmio_base + (off)) |
| 97 | 97 | ||
| 98 | #define MAX_MATRIX_KEY_NUM (8 * 8) | 98 | #define MAX_MATRIX_KEY_NUM (MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS) |
| 99 | #define MAX_KEYPAD_KEYS (MAX_MATRIX_KEY_NUM + MAX_DIRECT_KEY_NUM) | ||
| 99 | 100 | ||
| 100 | struct pxa27x_keypad { | 101 | struct pxa27x_keypad { |
| 101 | struct pxa27x_keypad_platform_data *pdata; | 102 | struct pxa27x_keypad_platform_data *pdata; |
| @@ -106,73 +107,82 @@ struct pxa27x_keypad { | |||
| 106 | 107 | ||
| 107 | int irq; | 108 | int irq; |
| 108 | 109 | ||
| 109 | /* matrix key code map */ | 110 | unsigned short keycodes[MAX_KEYPAD_KEYS]; |
| 110 | unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM]; | 111 | int rotary_rel_code[2]; |
| 111 | 112 | ||
| 112 | /* state row bits of each column scan */ | 113 | /* state row bits of each column scan */ |
| 113 | uint32_t matrix_key_state[MAX_MATRIX_KEY_COLS]; | 114 | uint32_t matrix_key_state[MAX_MATRIX_KEY_COLS]; |
| 114 | uint32_t direct_key_state; | 115 | uint32_t direct_key_state; |
| 115 | 116 | ||
| 116 | unsigned int direct_key_mask; | 117 | unsigned int direct_key_mask; |
| 117 | |||
| 118 | int rotary_rel_code[2]; | ||
| 119 | int rotary_up_key[2]; | ||
| 120 | int rotary_down_key[2]; | ||
| 121 | }; | 118 | }; |
| 122 | 119 | ||
| 123 | static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) | 120 | static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) |
| 124 | { | 121 | { |
| 125 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 122 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
| 126 | struct input_dev *input_dev = keypad->input_dev; | 123 | struct input_dev *input_dev = keypad->input_dev; |
| 127 | unsigned int *key; | 124 | unsigned short keycode; |
| 128 | int i; | 125 | int i; |
| 129 | 126 | ||
| 130 | key = &pdata->matrix_key_map[0]; | 127 | for (i = 0; i < pdata->matrix_key_map_size; i++) { |
| 131 | for (i = 0; i < pdata->matrix_key_map_size; i++, key++) { | 128 | unsigned int key = pdata->matrix_key_map[i]; |
| 132 | int row = ((*key) >> 28) & 0xf; | 129 | unsigned int row = KEY_ROW(key); |
| 133 | int col = ((*key) >> 24) & 0xf; | 130 | unsigned int col = KEY_COL(key); |
| 134 | int code = (*key) & 0xffffff; | 131 | unsigned int scancode = MATRIX_SCAN_CODE(row, col, |
| 132 | MATRIX_ROW_SHIFT); | ||
| 135 | 133 | ||
| 136 | keypad->matrix_keycodes[(row << 3) + col] = code; | 134 | keycode = KEY_VAL(key); |
| 137 | set_bit(code, input_dev->keybit); | 135 | keypad->keycodes[scancode] = keycode; |
| 136 | __set_bit(keycode, input_dev->keybit); | ||
| 138 | } | 137 | } |
| 139 | 138 | ||
| 140 | for (i = 0; i < pdata->direct_key_num; i++) | 139 | for (i = 0; i < pdata->direct_key_num; i++) { |
| 141 | set_bit(pdata->direct_key_map[i], input_dev->keybit); | 140 | keycode = pdata->direct_key_map[i]; |
| 142 | 141 | keypad->keycodes[MAX_MATRIX_KEY_NUM + i] = keycode; | |
| 143 | keypad->rotary_up_key[0] = pdata->rotary0_up_key; | 142 | __set_bit(keycode, input_dev->keybit); |
| 144 | keypad->rotary_up_key[1] = pdata->rotary1_up_key; | 143 | } |
| 145 | keypad->rotary_down_key[0] = pdata->rotary0_down_key; | ||
| 146 | keypad->rotary_down_key[1] = pdata->rotary1_down_key; | ||
| 147 | keypad->rotary_rel_code[0] = pdata->rotary0_rel_code; | ||
| 148 | keypad->rotary_rel_code[1] = pdata->rotary1_rel_code; | ||
| 149 | 144 | ||
| 150 | if (pdata->enable_rotary0) { | 145 | if (pdata->enable_rotary0) { |
| 151 | if (pdata->rotary0_up_key && pdata->rotary0_down_key) { | 146 | if (pdata->rotary0_up_key && pdata->rotary0_down_key) { |
| 152 | set_bit(pdata->rotary0_up_key, input_dev->keybit); | 147 | keycode = pdata->rotary0_up_key; |
| 153 | set_bit(pdata->rotary0_down_key, input_dev->keybit); | 148 | keypad->keycodes[MAX_MATRIX_KEY_NUM + 0] = keycode; |
| 154 | } else | 149 | __set_bit(keycode, input_dev->keybit); |
| 155 | set_bit(pdata->rotary0_rel_code, input_dev->relbit); | 150 | |
| 151 | keycode = pdata->rotary0_down_key; | ||
| 152 | keypad->keycodes[MAX_MATRIX_KEY_NUM + 1] = keycode; | ||
| 153 | __set_bit(keycode, input_dev->keybit); | ||
| 154 | |||
| 155 | keypad->rotary_rel_code[0] = -1; | ||
| 156 | } else { | ||
| 157 | keypad->rotary_rel_code[0] = pdata->rotary0_rel_code; | ||
| 158 | __set_bit(pdata->rotary0_rel_code, input_dev->relbit); | ||
| 159 | } | ||
| 156 | } | 160 | } |
| 157 | 161 | ||
| 158 | if (pdata->enable_rotary1) { | 162 | if (pdata->enable_rotary1) { |
| 159 | if (pdata->rotary1_up_key && pdata->rotary1_down_key) { | 163 | if (pdata->rotary1_up_key && pdata->rotary1_down_key) { |
| 160 | set_bit(pdata->rotary1_up_key, input_dev->keybit); | 164 | keycode = pdata->rotary1_up_key; |
| 161 | set_bit(pdata->rotary1_down_key, input_dev->keybit); | 165 | keypad->keycodes[MAX_MATRIX_KEY_NUM + 2] = keycode; |
| 162 | } else | 166 | __set_bit(keycode, input_dev->keybit); |
| 163 | set_bit(pdata->rotary1_rel_code, input_dev->relbit); | 167 | |
| 168 | keycode = pdata->rotary1_down_key; | ||
| 169 | keypad->keycodes[MAX_MATRIX_KEY_NUM + 3] = keycode; | ||
| 170 | __set_bit(keycode, input_dev->keybit); | ||
| 171 | |||
| 172 | keypad->rotary_rel_code[1] = -1; | ||
| 173 | } else { | ||
| 174 | keypad->rotary_rel_code[1] = pdata->rotary1_rel_code; | ||
| 175 | __set_bit(pdata->rotary1_rel_code, input_dev->relbit); | ||
| 176 | } | ||
| 164 | } | 177 | } |
| 165 | } | ||
| 166 | 178 | ||
| 167 | static inline unsigned int lookup_matrix_keycode( | 179 | __clear_bit(KEY_RESERVED, input_dev->keybit); |
| 168 | struct pxa27x_keypad *keypad, int row, int col) | ||
| 169 | { | ||
| 170 | return keypad->matrix_keycodes[(row << 3) + col]; | ||
| 171 | } | 180 | } |
| 172 | 181 | ||
| 173 | static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad) | 182 | static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad) |
| 174 | { | 183 | { |
| 175 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 184 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
| 185 | struct input_dev *input_dev = keypad->input_dev; | ||
| 176 | int row, col, num_keys_pressed = 0; | 186 | int row, col, num_keys_pressed = 0; |
| 177 | uint32_t new_state[MAX_MATRIX_KEY_COLS]; | 187 | uint32_t new_state[MAX_MATRIX_KEY_COLS]; |
| 178 | uint32_t kpas = keypad_readl(KPAS); | 188 | uint32_t kpas = keypad_readl(KPAS); |
| @@ -215,6 +225,7 @@ static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad) | |||
| 215 | scan: | 225 | scan: |
| 216 | for (col = 0; col < pdata->matrix_key_cols; col++) { | 226 | for (col = 0; col < pdata->matrix_key_cols; col++) { |
| 217 | uint32_t bits_changed; | 227 | uint32_t bits_changed; |
| 228 | int code; | ||
| 218 | 229 | ||
| 219 | bits_changed = keypad->matrix_key_state[col] ^ new_state[col]; | 230 | bits_changed = keypad->matrix_key_state[col] ^ new_state[col]; |
| 220 | if (bits_changed == 0) | 231 | if (bits_changed == 0) |
| @@ -224,12 +235,13 @@ scan: | |||
| 224 | if ((bits_changed & (1 << row)) == 0) | 235 | if ((bits_changed & (1 << row)) == 0) |
| 225 | continue; | 236 | continue; |
| 226 | 237 | ||
| 227 | input_report_key(keypad->input_dev, | 238 | code = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT); |
| 228 | lookup_matrix_keycode(keypad, row, col), | 239 | input_event(input_dev, EV_MSC, MSC_SCAN, code); |
| 229 | new_state[col] & (1 << row)); | 240 | input_report_key(input_dev, keypad->keycodes[code], |
| 241 | new_state[col] & (1 << row)); | ||
| 230 | } | 242 | } |
| 231 | } | 243 | } |
| 232 | input_sync(keypad->input_dev); | 244 | input_sync(input_dev); |
| 233 | memcpy(keypad->matrix_key_state, new_state, sizeof(new_state)); | 245 | memcpy(keypad->matrix_key_state, new_state, sizeof(new_state)); |
| 234 | } | 246 | } |
| 235 | 247 | ||
| @@ -252,13 +264,15 @@ static void report_rotary_event(struct pxa27x_keypad *keypad, int r, int delta) | |||
| 252 | if (delta == 0) | 264 | if (delta == 0) |
| 253 | return; | 265 | return; |
| 254 | 266 | ||
| 255 | if (keypad->rotary_up_key[r] && keypad->rotary_down_key[r]) { | 267 | if (keypad->rotary_rel_code[r] == -1) { |
| 256 | int keycode = (delta > 0) ? keypad->rotary_up_key[r] : | 268 | int code = MAX_MATRIX_KEY_NUM + 2 * r + (delta > 0 ? 0 : 1); |
| 257 | keypad->rotary_down_key[r]; | 269 | unsigned char keycode = keypad->keycodes[code]; |
| 258 | 270 | ||
| 259 | /* simulate a press-n-release */ | 271 | /* simulate a press-n-release */ |
| 272 | input_event(dev, EV_MSC, MSC_SCAN, code); | ||
| 260 | input_report_key(dev, keycode, 1); | 273 | input_report_key(dev, keycode, 1); |
| 261 | input_sync(dev); | 274 | input_sync(dev); |
| 275 | input_event(dev, EV_MSC, MSC_SCAN, code); | ||
| 262 | input_report_key(dev, keycode, 0); | 276 | input_report_key(dev, keycode, 0); |
| 263 | input_sync(dev); | 277 | input_sync(dev); |
| 264 | } else { | 278 | } else { |
| @@ -286,6 +300,7 @@ static void pxa27x_keypad_scan_rotary(struct pxa27x_keypad *keypad) | |||
| 286 | static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) | 300 | static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) |
| 287 | { | 301 | { |
| 288 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 302 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
| 303 | struct input_dev *input_dev = keypad->input_dev; | ||
| 289 | unsigned int new_state; | 304 | unsigned int new_state; |
| 290 | uint32_t kpdk, bits_changed; | 305 | uint32_t kpdk, bits_changed; |
| 291 | int i; | 306 | int i; |
| @@ -295,9 +310,6 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) | |||
| 295 | if (pdata->enable_rotary0 || pdata->enable_rotary1) | 310 | if (pdata->enable_rotary0 || pdata->enable_rotary1) |
| 296 | pxa27x_keypad_scan_rotary(keypad); | 311 | pxa27x_keypad_scan_rotary(keypad); |
| 297 | 312 | ||
| 298 | if (pdata->direct_key_map == NULL) | ||
| 299 | return; | ||
| 300 | |||
| 301 | new_state = KPDK_DK(kpdk) & keypad->direct_key_mask; | 313 | new_state = KPDK_DK(kpdk) & keypad->direct_key_mask; |
| 302 | bits_changed = keypad->direct_key_state ^ new_state; | 314 | bits_changed = keypad->direct_key_state ^ new_state; |
| 303 | 315 | ||
| @@ -305,12 +317,15 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) | |||
| 305 | return; | 317 | return; |
| 306 | 318 | ||
| 307 | for (i = 0; i < pdata->direct_key_num; i++) { | 319 | for (i = 0; i < pdata->direct_key_num; i++) { |
| 308 | if (bits_changed & (1 << i)) | 320 | if (bits_changed & (1 << i)) { |
| 309 | input_report_key(keypad->input_dev, | 321 | int code = MAX_MATRIX_KEY_NUM + i; |
| 310 | pdata->direct_key_map[i], | 322 | |
| 311 | (new_state & (1 << i))); | 323 | input_event(input_dev, EV_MSC, MSC_SCAN, code); |
| 324 | input_report_key(input_dev, keypad->keycodes[code], | ||
| 325 | new_state & (1 << i)); | ||
| 326 | } | ||
| 312 | } | 327 | } |
| 313 | input_sync(keypad->input_dev); | 328 | input_sync(input_dev); |
| 314 | keypad->direct_key_state = new_state; | 329 | keypad->direct_key_state = new_state; |
| 315 | } | 330 | } |
| 316 | 331 | ||
| @@ -388,8 +403,9 @@ static void pxa27x_keypad_close(struct input_dev *dev) | |||
| 388 | } | 403 | } |
| 389 | 404 | ||
| 390 | #ifdef CONFIG_PM | 405 | #ifdef CONFIG_PM |
| 391 | static int pxa27x_keypad_suspend(struct platform_device *pdev, pm_message_t state) | 406 | static int pxa27x_keypad_suspend(struct device *dev) |
| 392 | { | 407 | { |
| 408 | struct platform_device *pdev = to_platform_device(dev); | ||
| 393 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); | 409 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); |
| 394 | 410 | ||
| 395 | clk_disable(keypad->clk); | 411 | clk_disable(keypad->clk); |
| @@ -400,8 +416,9 @@ static int pxa27x_keypad_suspend(struct platform_device *pdev, pm_message_t stat | |||
| 400 | return 0; | 416 | return 0; |
| 401 | } | 417 | } |
| 402 | 418 | ||
| 403 | static int pxa27x_keypad_resume(struct platform_device *pdev) | 419 | static int pxa27x_keypad_resume(struct device *dev) |
| 404 | { | 420 | { |
| 421 | struct platform_device *pdev = to_platform_device(dev); | ||
| 405 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); | 422 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); |
| 406 | struct input_dev *input_dev = keypad->input_dev; | 423 | struct input_dev *input_dev = keypad->input_dev; |
| 407 | 424 | ||
| @@ -420,55 +437,58 @@ static int pxa27x_keypad_resume(struct platform_device *pdev) | |||
| 420 | 437 | ||
| 421 | return 0; | 438 | return 0; |
| 422 | } | 439 | } |
| 423 | #else | ||
| 424 | #define pxa27x_keypad_suspend NULL | ||
| 425 | #define pxa27x_keypad_resume NULL | ||
| 426 | #endif | ||
| 427 | 440 | ||
| 428 | #define res_size(res) ((res)->end - (res)->start + 1) | 441 | static const struct dev_pm_ops pxa27x_keypad_pm_ops = { |
| 442 | .suspend = pxa27x_keypad_suspend, | ||
| 443 | .resume = pxa27x_keypad_resume, | ||
| 444 | }; | ||
| 445 | #endif | ||
| 429 | 446 | ||
| 430 | static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) | 447 | static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) |
| 431 | { | 448 | { |
| 449 | struct pxa27x_keypad_platform_data *pdata = pdev->dev.platform_data; | ||
| 432 | struct pxa27x_keypad *keypad; | 450 | struct pxa27x_keypad *keypad; |
| 433 | struct input_dev *input_dev; | 451 | struct input_dev *input_dev; |
| 434 | struct resource *res; | 452 | struct resource *res; |
| 435 | int irq, error; | 453 | int irq, error; |
| 436 | 454 | ||
| 437 | keypad = kzalloc(sizeof(struct pxa27x_keypad), GFP_KERNEL); | 455 | if (pdata == NULL) { |
| 438 | if (keypad == NULL) { | ||
| 439 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
| 440 | return -ENOMEM; | ||
| 441 | } | ||
| 442 | |||
| 443 | keypad->pdata = pdev->dev.platform_data; | ||
| 444 | if (keypad->pdata == NULL) { | ||
| 445 | dev_err(&pdev->dev, "no platform data defined\n"); | 456 | dev_err(&pdev->dev, "no platform data defined\n"); |
| 446 | error = -EINVAL; | 457 | return -EINVAL; |
| 447 | goto failed_free; | ||
| 448 | } | 458 | } |
| 449 | 459 | ||
| 450 | irq = platform_get_irq(pdev, 0); | 460 | irq = platform_get_irq(pdev, 0); |
| 451 | if (irq < 0) { | 461 | if (irq < 0) { |
| 452 | dev_err(&pdev->dev, "failed to get keypad irq\n"); | 462 | dev_err(&pdev->dev, "failed to get keypad irq\n"); |
| 453 | error = -ENXIO; | 463 | return -ENXIO; |
| 454 | goto failed_free; | ||
| 455 | } | 464 | } |
| 456 | 465 | ||
| 457 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 466 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 458 | if (res == NULL) { | 467 | if (res == NULL) { |
| 459 | dev_err(&pdev->dev, "failed to get I/O memory\n"); | 468 | dev_err(&pdev->dev, "failed to get I/O memory\n"); |
| 460 | error = -ENXIO; | 469 | return -ENXIO; |
| 470 | } | ||
| 471 | |||
| 472 | keypad = kzalloc(sizeof(struct pxa27x_keypad), GFP_KERNEL); | ||
| 473 | input_dev = input_allocate_device(); | ||
| 474 | if (!keypad || !input_dev) { | ||
| 475 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
| 476 | error = -ENOMEM; | ||
| 461 | goto failed_free; | 477 | goto failed_free; |
| 462 | } | 478 | } |
| 463 | 479 | ||
| 464 | res = request_mem_region(res->start, res_size(res), pdev->name); | 480 | keypad->pdata = pdata; |
| 481 | keypad->input_dev = input_dev; | ||
| 482 | keypad->irq = irq; | ||
| 483 | |||
| 484 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
| 465 | if (res == NULL) { | 485 | if (res == NULL) { |
| 466 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | 486 | dev_err(&pdev->dev, "failed to request I/O memory\n"); |
| 467 | error = -EBUSY; | 487 | error = -EBUSY; |
| 468 | goto failed_free; | 488 | goto failed_free; |
| 469 | } | 489 | } |
| 470 | 490 | ||
| 471 | keypad->mmio_base = ioremap(res->start, res_size(res)); | 491 | keypad->mmio_base = ioremap(res->start, resource_size(res)); |
| 472 | if (keypad->mmio_base == NULL) { | 492 | if (keypad->mmio_base == NULL) { |
| 473 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | 493 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); |
| 474 | error = -ENXIO; | 494 | error = -ENXIO; |
| @@ -482,43 +502,35 @@ static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) | |||
| 482 | goto failed_free_io; | 502 | goto failed_free_io; |
| 483 | } | 503 | } |
| 484 | 504 | ||
| 485 | /* Create and register the input driver. */ | ||
| 486 | input_dev = input_allocate_device(); | ||
| 487 | if (!input_dev) { | ||
| 488 | dev_err(&pdev->dev, "failed to allocate input device\n"); | ||
| 489 | error = -ENOMEM; | ||
| 490 | goto failed_put_clk; | ||
| 491 | } | ||
| 492 | |||
| 493 | input_dev->name = pdev->name; | 505 | input_dev->name = pdev->name; |
| 494 | input_dev->id.bustype = BUS_HOST; | 506 | input_dev->id.bustype = BUS_HOST; |
| 495 | input_dev->open = pxa27x_keypad_open; | 507 | input_dev->open = pxa27x_keypad_open; |
| 496 | input_dev->close = pxa27x_keypad_close; | 508 | input_dev->close = pxa27x_keypad_close; |
| 497 | input_dev->dev.parent = &pdev->dev; | 509 | input_dev->dev.parent = &pdev->dev; |
| 498 | 510 | ||
| 499 | keypad->input_dev = input_dev; | 511 | input_dev->keycode = keypad->keycodes; |
| 512 | input_dev->keycodesize = sizeof(keypad->keycodes[0]); | ||
| 513 | input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes); | ||
| 514 | |||
| 500 | input_set_drvdata(input_dev, keypad); | 515 | input_set_drvdata(input_dev, keypad); |
| 501 | 516 | ||
| 502 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | 517 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); |
| 503 | if ((keypad->pdata->enable_rotary0 && | 518 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); |
| 504 | keypad->pdata->rotary0_rel_code) || | ||
| 505 | (keypad->pdata->enable_rotary1 && | ||
| 506 | keypad->pdata->rotary1_rel_code)) { | ||
| 507 | input_dev->evbit[0] |= BIT_MASK(EV_REL); | ||
| 508 | } | ||
| 509 | 519 | ||
| 510 | pxa27x_keypad_build_keycode(keypad); | 520 | pxa27x_keypad_build_keycode(keypad); |
| 511 | platform_set_drvdata(pdev, keypad); | 521 | |
| 522 | if ((pdata->enable_rotary0 && keypad->rotary_rel_code[0] != -1) || | ||
| 523 | (pdata->enable_rotary1 && keypad->rotary_rel_code[1] != -1)) { | ||
| 524 | input_dev->evbit[0] |= BIT_MASK(EV_REL); | ||
| 525 | } | ||
| 512 | 526 | ||
| 513 | error = request_irq(irq, pxa27x_keypad_irq_handler, IRQF_DISABLED, | 527 | error = request_irq(irq, pxa27x_keypad_irq_handler, IRQF_DISABLED, |
| 514 | pdev->name, keypad); | 528 | pdev->name, keypad); |
| 515 | if (error) { | 529 | if (error) { |
| 516 | dev_err(&pdev->dev, "failed to request IRQ\n"); | 530 | dev_err(&pdev->dev, "failed to request IRQ\n"); |
| 517 | goto failed_free_dev; | 531 | goto failed_put_clk; |
| 518 | } | 532 | } |
| 519 | 533 | ||
| 520 | keypad->irq = irq; | ||
| 521 | |||
| 522 | /* Register the input device */ | 534 | /* Register the input device */ |
| 523 | error = input_register_device(input_dev); | 535 | error = input_register_device(input_dev); |
| 524 | if (error) { | 536 | if (error) { |
| @@ -526,22 +538,21 @@ static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) | |||
| 526 | goto failed_free_irq; | 538 | goto failed_free_irq; |
| 527 | } | 539 | } |
| 528 | 540 | ||
| 541 | platform_set_drvdata(pdev, keypad); | ||
| 529 | device_init_wakeup(&pdev->dev, 1); | 542 | device_init_wakeup(&pdev->dev, 1); |
| 530 | 543 | ||
| 531 | return 0; | 544 | return 0; |
| 532 | 545 | ||
| 533 | failed_free_irq: | 546 | failed_free_irq: |
| 534 | free_irq(irq, pdev); | 547 | free_irq(irq, pdev); |
| 535 | platform_set_drvdata(pdev, NULL); | ||
| 536 | failed_free_dev: | ||
| 537 | input_free_device(input_dev); | ||
| 538 | failed_put_clk: | 548 | failed_put_clk: |
| 539 | clk_put(keypad->clk); | 549 | clk_put(keypad->clk); |
| 540 | failed_free_io: | 550 | failed_free_io: |
| 541 | iounmap(keypad->mmio_base); | 551 | iounmap(keypad->mmio_base); |
| 542 | failed_free_mem: | 552 | failed_free_mem: |
| 543 | release_mem_region(res->start, res_size(res)); | 553 | release_mem_region(res->start, resource_size(res)); |
| 544 | failed_free: | 554 | failed_free: |
| 555 | input_free_device(input_dev); | ||
| 545 | kfree(keypad); | 556 | kfree(keypad); |
| 546 | return error; | 557 | return error; |
| 547 | } | 558 | } |
| @@ -552,8 +563,6 @@ static int __devexit pxa27x_keypad_remove(struct platform_device *pdev) | |||
| 552 | struct resource *res; | 563 | struct resource *res; |
| 553 | 564 | ||
| 554 | free_irq(keypad->irq, pdev); | 565 | free_irq(keypad->irq, pdev); |
| 555 | |||
| 556 | clk_disable(keypad->clk); | ||
| 557 | clk_put(keypad->clk); | 566 | clk_put(keypad->clk); |
| 558 | 567 | ||
| 559 | input_unregister_device(keypad->input_dev); | 568 | input_unregister_device(keypad->input_dev); |
| @@ -562,10 +571,11 @@ static int __devexit pxa27x_keypad_remove(struct platform_device *pdev) | |||
| 562 | iounmap(keypad->mmio_base); | 571 | iounmap(keypad->mmio_base); |
| 563 | 572 | ||
| 564 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 573 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 565 | release_mem_region(res->start, res_size(res)); | 574 | release_mem_region(res->start, resource_size(res)); |
| 566 | 575 | ||
| 567 | platform_set_drvdata(pdev, NULL); | 576 | platform_set_drvdata(pdev, NULL); |
| 568 | kfree(keypad); | 577 | kfree(keypad); |
| 578 | |||
| 569 | return 0; | 579 | return 0; |
| 570 | } | 580 | } |
| 571 | 581 | ||
| @@ -575,11 +585,12 @@ MODULE_ALIAS("platform:pxa27x-keypad"); | |||
| 575 | static struct platform_driver pxa27x_keypad_driver = { | 585 | static struct platform_driver pxa27x_keypad_driver = { |
| 576 | .probe = pxa27x_keypad_probe, | 586 | .probe = pxa27x_keypad_probe, |
| 577 | .remove = __devexit_p(pxa27x_keypad_remove), | 587 | .remove = __devexit_p(pxa27x_keypad_remove), |
| 578 | .suspend = pxa27x_keypad_suspend, | ||
| 579 | .resume = pxa27x_keypad_resume, | ||
| 580 | .driver = { | 588 | .driver = { |
| 581 | .name = "pxa27x-keypad", | 589 | .name = "pxa27x-keypad", |
| 582 | .owner = THIS_MODULE, | 590 | .owner = THIS_MODULE, |
| 591 | #ifdef CONFIG_PM | ||
| 592 | .pm = &pxa27x_keypad_pm_ops, | ||
| 593 | #endif | ||
| 583 | }, | 594 | }, |
| 584 | }; | 595 | }; |
| 585 | 596 | ||
diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index cea70e6a1031..0714bf2c28fc 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c | |||
| @@ -128,7 +128,7 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) | |||
| 128 | struct resource *res; | 128 | struct resource *res; |
| 129 | struct input_dev *input; | 129 | struct input_dev *input; |
| 130 | char clk_name[8]; | 130 | char clk_name[8]; |
| 131 | int i, k; | 131 | int i; |
| 132 | int irq, error; | 132 | int irq, error; |
| 133 | 133 | ||
| 134 | if (!pdev->dev.platform_data) { | 134 | if (!pdev->dev.platform_data) { |
| @@ -195,17 +195,19 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) | |||
| 195 | input->id.product = 0x0001; | 195 | input->id.product = 0x0001; |
| 196 | input->id.version = 0x0100; | 196 | input->id.version = 0x0100; |
| 197 | 197 | ||
| 198 | input->keycode = pdata->keycodes; | ||
| 199 | input->keycodesize = sizeof(pdata->keycodes[0]); | ||
| 200 | input->keycodemax = ARRAY_SIZE(pdata->keycodes); | ||
| 201 | |||
| 198 | error = request_irq(irq, sh_keysc_isr, 0, pdev->name, pdev); | 202 | error = request_irq(irq, sh_keysc_isr, 0, pdev->name, pdev); |
| 199 | if (error) { | 203 | if (error) { |
| 200 | dev_err(&pdev->dev, "failed to request IRQ\n"); | 204 | dev_err(&pdev->dev, "failed to request IRQ\n"); |
| 201 | goto err4; | 205 | goto err4; |
| 202 | } | 206 | } |
| 203 | 207 | ||
| 204 | for (i = 0; i < SH_KEYSC_MAXKEYS; i++) { | 208 | for (i = 0; i < SH_KEYSC_MAXKEYS; i++) |
| 205 | k = pdata->keycodes[i]; | 209 | __set_bit(pdata->keycodes[i], input->keybit); |
| 206 | if (k) | 210 | __clear_bit(KEY_RESERVED, input->keybit); |
| 207 | input_set_capability(input, EV_KEY, k); | ||
| 208 | } | ||
| 209 | 211 | ||
| 210 | error = input_register_device(input); | 212 | error = input_register_device(input); |
| 211 | if (error) { | 213 | if (error) { |
| @@ -221,7 +223,9 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) | |||
| 221 | iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS); | 223 | iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS); |
| 222 | 224 | ||
| 223 | device_init_wakeup(&pdev->dev, 1); | 225 | device_init_wakeup(&pdev->dev, 1); |
| 226 | |||
| 224 | return 0; | 227 | return 0; |
| 228 | |||
| 225 | err5: | 229 | err5: |
| 226 | free_irq(irq, pdev); | 230 | free_irq(irq, pdev); |
| 227 | err4: | 231 | err4: |
| @@ -252,6 +256,7 @@ static int __devexit sh_keysc_remove(struct platform_device *pdev) | |||
| 252 | 256 | ||
| 253 | platform_set_drvdata(pdev, NULL); | 257 | platform_set_drvdata(pdev, NULL); |
| 254 | kfree(priv); | 258 | kfree(priv); |
| 259 | |||
| 255 | return 0; | 260 | return 0; |
| 256 | } | 261 | } |
| 257 | 262 | ||
| @@ -267,11 +272,12 @@ static int sh_keysc_suspend(struct device *dev) | |||
| 267 | if (device_may_wakeup(dev)) { | 272 | if (device_may_wakeup(dev)) { |
| 268 | value |= 0x80; | 273 | value |= 0x80; |
| 269 | enable_irq_wake(irq); | 274 | enable_irq_wake(irq); |
| 270 | } | 275 | } else { |
| 271 | else | ||
| 272 | value &= ~0x80; | 276 | value &= ~0x80; |
| 277 | } | ||
| 273 | 278 | ||
| 274 | iowrite16(value, priv->iomem_base + KYCR1_OFFS); | 279 | iowrite16(value, priv->iomem_base + KYCR1_OFFS); |
| 280 | |||
| 275 | return 0; | 281 | return 0; |
| 276 | } | 282 | } |
| 277 | 283 | ||
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c index 9fce6d1e29b2..472b56639cdb 100644 --- a/drivers/input/keyboard/sunkbd.c +++ b/drivers/input/keyboard/sunkbd.c | |||
| @@ -73,7 +73,7 @@ static unsigned char sunkbd_keycode[128] = { | |||
| 73 | */ | 73 | */ |
| 74 | 74 | ||
| 75 | struct sunkbd { | 75 | struct sunkbd { |
| 76 | unsigned char keycode[128]; | 76 | unsigned char keycode[ARRAY_SIZE(sunkbd_keycode)]; |
| 77 | struct input_dev *dev; | 77 | struct input_dev *dev; |
| 78 | struct serio *serio; | 78 | struct serio *serio; |
| 79 | struct work_struct tq; | 79 | struct work_struct tq; |
| @@ -81,7 +81,7 @@ struct sunkbd { | |||
| 81 | char name[64]; | 81 | char name[64]; |
| 82 | char phys[32]; | 82 | char phys[32]; |
| 83 | char type; | 83 | char type; |
| 84 | unsigned char enabled; | 84 | bool enabled; |
| 85 | volatile s8 reset; | 85 | volatile s8 reset; |
| 86 | volatile s8 layout; | 86 | volatile s8 layout; |
| 87 | }; | 87 | }; |
| @@ -94,10 +94,14 @@ struct sunkbd { | |||
| 94 | static irqreturn_t sunkbd_interrupt(struct serio *serio, | 94 | static irqreturn_t sunkbd_interrupt(struct serio *serio, |
| 95 | unsigned char data, unsigned int flags) | 95 | unsigned char data, unsigned int flags) |
| 96 | { | 96 | { |
| 97 | struct sunkbd* sunkbd = serio_get_drvdata(serio); | 97 | struct sunkbd *sunkbd = serio_get_drvdata(serio); |
| 98 | 98 | ||
| 99 | if (sunkbd->reset <= -1) { /* If cp[i] is 0xff, sunkbd->reset will stay -1. */ | 99 | if (sunkbd->reset <= -1) { |
| 100 | sunkbd->reset = data; /* The keyboard sends 0xff 0xff 0xID on powerup */ | 100 | /* |
| 101 | * If cp[i] is 0xff, sunkbd->reset will stay -1. | ||
| 102 | * The keyboard sends 0xff 0xff 0xID on powerup. | ||
| 103 | */ | ||
| 104 | sunkbd->reset = data; | ||
| 101 | wake_up_interruptible(&sunkbd->wait); | 105 | wake_up_interruptible(&sunkbd->wait); |
| 102 | goto out; | 106 | goto out; |
| 103 | } | 107 | } |
| @@ -110,29 +114,33 @@ static irqreturn_t sunkbd_interrupt(struct serio *serio, | |||
| 110 | 114 | ||
| 111 | switch (data) { | 115 | switch (data) { |
| 112 | 116 | ||
| 113 | case SUNKBD_RET_RESET: | 117 | case SUNKBD_RET_RESET: |
| 114 | schedule_work(&sunkbd->tq); | 118 | schedule_work(&sunkbd->tq); |
| 115 | sunkbd->reset = -1; | 119 | sunkbd->reset = -1; |
| 116 | break; | 120 | break; |
| 117 | 121 | ||
| 118 | case SUNKBD_RET_LAYOUT: | 122 | case SUNKBD_RET_LAYOUT: |
| 119 | sunkbd->layout = -1; | 123 | sunkbd->layout = -1; |
| 120 | break; | 124 | break; |
| 125 | |||
| 126 | case SUNKBD_RET_ALLUP: /* All keys released */ | ||
| 127 | break; | ||
| 121 | 128 | ||
| 122 | case SUNKBD_RET_ALLUP: /* All keys released */ | 129 | default: |
| 130 | if (!sunkbd->enabled) | ||
| 123 | break; | 131 | break; |
| 124 | 132 | ||
| 125 | default: | 133 | if (sunkbd->keycode[data & SUNKBD_KEY]) { |
| 126 | if (!sunkbd->enabled) | 134 | input_report_key(sunkbd->dev, |
| 127 | break; | 135 | sunkbd->keycode[data & SUNKBD_KEY], |
| 128 | 136 | !(data & SUNKBD_RELEASE)); | |
| 129 | if (sunkbd->keycode[data & SUNKBD_KEY]) { | 137 | input_sync(sunkbd->dev); |
| 130 | input_report_key(sunkbd->dev, sunkbd->keycode[data & SUNKBD_KEY], !(data & SUNKBD_RELEASE)); | 138 | } else { |
| 131 | input_sync(sunkbd->dev); | 139 | printk(KERN_WARNING |
| 132 | } else { | 140 | "sunkbd.c: Unknown key (scancode %#x) %s.\n", |
| 133 | printk(KERN_WARNING "sunkbd.c: Unknown key (scancode %#x) %s.\n", | 141 | data & SUNKBD_KEY, |
| 134 | data & SUNKBD_KEY, data & SUNKBD_RELEASE ? "released" : "pressed"); | 142 | data & SUNKBD_RELEASE ? "released" : "pressed"); |
| 135 | } | 143 | } |
| 136 | } | 144 | } |
| 137 | out: | 145 | out: |
| 138 | return IRQ_HANDLED; | 146 | return IRQ_HANDLED; |
| @@ -142,34 +150,37 @@ out: | |||
| 142 | * sunkbd_event() handles events from the input module. | 150 | * sunkbd_event() handles events from the input module. |
| 143 | */ | 151 | */ |
| 144 | 152 | ||
| 145 | static int sunkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | 153 | static int sunkbd_event(struct input_dev *dev, |
| 154 | unsigned int type, unsigned int code, int value) | ||
| 146 | { | 155 | { |
| 147 | struct sunkbd *sunkbd = input_get_drvdata(dev); | 156 | struct sunkbd *sunkbd = input_get_drvdata(dev); |
| 148 | 157 | ||
| 149 | switch (type) { | 158 | switch (type) { |
| 150 | 159 | ||
| 151 | case EV_LED: | 160 | case EV_LED: |
| 152 | 161 | ||
| 153 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED); | 162 | serio_write(sunkbd->serio, SUNKBD_CMD_SETLED); |
| 154 | sunkbd->serio->write(sunkbd->serio, | 163 | serio_write(sunkbd->serio, |
| 155 | (!!test_bit(LED_CAPSL, dev->led) << 3) | (!!test_bit(LED_SCROLLL, dev->led) << 2) | | 164 | (!!test_bit(LED_CAPSL, dev->led) << 3) | |
| 156 | (!!test_bit(LED_COMPOSE, dev->led) << 1) | !!test_bit(LED_NUML, dev->led)); | 165 | (!!test_bit(LED_SCROLLL, dev->led) << 2) | |
| 157 | return 0; | 166 | (!!test_bit(LED_COMPOSE, dev->led) << 1) | |
| 167 | !!test_bit(LED_NUML, dev->led)); | ||
| 168 | return 0; | ||
| 158 | 169 | ||
| 159 | case EV_SND: | 170 | case EV_SND: |
| 160 | 171 | ||
| 161 | switch (code) { | 172 | switch (code) { |
| 162 | 173 | ||
| 163 | case SND_CLICK: | 174 | case SND_CLICK: |
| 164 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - value); | 175 | serio_write(sunkbd->serio, SUNKBD_CMD_NOCLICK - value); |
| 165 | return 0; | 176 | return 0; |
| 166 | 177 | ||
| 167 | case SND_BELL: | 178 | case SND_BELL: |
| 168 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - value); | 179 | serio_write(sunkbd->serio, SUNKBD_CMD_BELLOFF - value); |
| 169 | return 0; | 180 | return 0; |
| 170 | } | 181 | } |
| 171 | 182 | ||
| 172 | break; | 183 | break; |
| 173 | } | 184 | } |
| 174 | 185 | ||
| 175 | return -1; | 186 | return -1; |
| @@ -183,7 +194,7 @@ static int sunkbd_event(struct input_dev *dev, unsigned int type, unsigned int c | |||
| 183 | static int sunkbd_initialize(struct sunkbd *sunkbd) | 194 | static int sunkbd_initialize(struct sunkbd *sunkbd) |
| 184 | { | 195 | { |
| 185 | sunkbd->reset = -2; | 196 | sunkbd->reset = -2; |
| 186 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_RESET); | 197 | serio_write(sunkbd->serio, SUNKBD_CMD_RESET); |
| 187 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); | 198 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); |
| 188 | if (sunkbd->reset < 0) | 199 | if (sunkbd->reset < 0) |
| 189 | return -1; | 200 | return -1; |
| @@ -192,10 +203,13 @@ static int sunkbd_initialize(struct sunkbd *sunkbd) | |||
| 192 | 203 | ||
| 193 | if (sunkbd->type == 4) { /* Type 4 keyboard */ | 204 | if (sunkbd->type == 4) { /* Type 4 keyboard */ |
| 194 | sunkbd->layout = -2; | 205 | sunkbd->layout = -2; |
| 195 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_LAYOUT); | 206 | serio_write(sunkbd->serio, SUNKBD_CMD_LAYOUT); |
| 196 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->layout >= 0, HZ/4); | 207 | wait_event_interruptible_timeout(sunkbd->wait, |
| 197 | if (sunkbd->layout < 0) return -1; | 208 | sunkbd->layout >= 0, HZ / 4); |
| 198 | if (sunkbd->layout & SUNKBD_LAYOUT_5_MASK) sunkbd->type = 5; | 209 | if (sunkbd->layout < 0) |
| 210 | return -1; | ||
| 211 | if (sunkbd->layout & SUNKBD_LAYOUT_5_MASK) | ||
| 212 | sunkbd->type = 5; | ||
| 199 | } | 213 | } |
| 200 | 214 | ||
| 201 | return 0; | 215 | return 0; |
| @@ -212,15 +226,19 @@ static void sunkbd_reinit(struct work_struct *work) | |||
| 212 | 226 | ||
| 213 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); | 227 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); |
| 214 | 228 | ||
| 215 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED); | 229 | serio_write(sunkbd->serio, SUNKBD_CMD_SETLED); |
| 216 | sunkbd->serio->write(sunkbd->serio, | 230 | serio_write(sunkbd->serio, |
| 217 | (!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) | (!!test_bit(LED_SCROLLL, sunkbd->dev->led) << 2) | | 231 | (!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) | |
| 218 | (!!test_bit(LED_COMPOSE, sunkbd->dev->led) << 1) | !!test_bit(LED_NUML, sunkbd->dev->led)); | 232 | (!!test_bit(LED_SCROLLL, sunkbd->dev->led) << 2) | |
| 219 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev->snd)); | 233 | (!!test_bit(LED_COMPOSE, sunkbd->dev->led) << 1) | |
| 220 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd)); | 234 | !!test_bit(LED_NUML, sunkbd->dev->led)); |
| 235 | serio_write(sunkbd->serio, | ||
| 236 | SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev->snd)); | ||
| 237 | serio_write(sunkbd->serio, | ||
| 238 | SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd)); | ||
| 221 | } | 239 | } |
| 222 | 240 | ||
| 223 | static void sunkbd_enable(struct sunkbd *sunkbd, int enable) | 241 | static void sunkbd_enable(struct sunkbd *sunkbd, bool enable) |
| 224 | { | 242 | { |
| 225 | serio_pause_rx(sunkbd->serio); | 243 | serio_pause_rx(sunkbd->serio); |
| 226 | sunkbd->enabled = enable; | 244 | sunkbd->enabled = enable; |
| @@ -228,7 +246,8 @@ static void sunkbd_enable(struct sunkbd *sunkbd, int enable) | |||
| 228 | } | 246 | } |
| 229 | 247 | ||
| 230 | /* | 248 | /* |
| 231 | * sunkbd_connect() probes for a Sun keyboard and fills the necessary structures. | 249 | * sunkbd_connect() probes for a Sun keyboard and fills the necessary |
| 250 | * structures. | ||
| 232 | */ | 251 | */ |
| 233 | 252 | ||
| 234 | static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) | 253 | static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) |
| @@ -260,7 +279,8 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) | |||
| 260 | goto fail3; | 279 | goto fail3; |
| 261 | } | 280 | } |
| 262 | 281 | ||
| 263 | snprintf(sunkbd->name, sizeof(sunkbd->name), "Sun Type %d keyboard", sunkbd->type); | 282 | snprintf(sunkbd->name, sizeof(sunkbd->name), |
| 283 | "Sun Type %d keyboard", sunkbd->type); | ||
| 264 | memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode)); | 284 | memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode)); |
| 265 | 285 | ||
| 266 | input_dev->name = sunkbd->name; | 286 | input_dev->name = sunkbd->name; |
| @@ -284,11 +304,11 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) | |||
| 284 | input_dev->keycode = sunkbd->keycode; | 304 | input_dev->keycode = sunkbd->keycode; |
| 285 | input_dev->keycodesize = sizeof(unsigned char); | 305 | input_dev->keycodesize = sizeof(unsigned char); |
| 286 | input_dev->keycodemax = ARRAY_SIZE(sunkbd_keycode); | 306 | input_dev->keycodemax = ARRAY_SIZE(sunkbd_keycode); |
| 287 | for (i = 0; i < 128; i++) | 307 | for (i = 0; i < ARRAY_SIZE(sunkbd_keycode); i++) |
| 288 | set_bit(sunkbd->keycode[i], input_dev->keybit); | 308 | __set_bit(sunkbd->keycode[i], input_dev->keybit); |
| 289 | clear_bit(0, input_dev->keybit); | 309 | __clear_bit(KEY_RESERVED, input_dev->keybit); |
| 290 | 310 | ||
| 291 | sunkbd_enable(sunkbd, 1); | 311 | sunkbd_enable(sunkbd, true); |
| 292 | 312 | ||
| 293 | err = input_register_device(sunkbd->dev); | 313 | err = input_register_device(sunkbd->dev); |
| 294 | if (err) | 314 | if (err) |
| @@ -296,7 +316,7 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) | |||
| 296 | 316 | ||
| 297 | return 0; | 317 | return 0; |
| 298 | 318 | ||
| 299 | fail4: sunkbd_enable(sunkbd, 0); | 319 | fail4: sunkbd_enable(sunkbd, false); |
| 300 | fail3: serio_close(serio); | 320 | fail3: serio_close(serio); |
| 301 | fail2: serio_set_drvdata(serio, NULL); | 321 | fail2: serio_set_drvdata(serio, NULL); |
| 302 | fail1: input_free_device(input_dev); | 322 | fail1: input_free_device(input_dev); |
| @@ -312,7 +332,7 @@ static void sunkbd_disconnect(struct serio *serio) | |||
| 312 | { | 332 | { |
| 313 | struct sunkbd *sunkbd = serio_get_drvdata(serio); | 333 | struct sunkbd *sunkbd = serio_get_drvdata(serio); |
| 314 | 334 | ||
| 315 | sunkbd_enable(sunkbd, 0); | 335 | sunkbd_enable(sunkbd, false); |
| 316 | input_unregister_device(sunkbd->dev); | 336 | input_unregister_device(sunkbd->dev); |
| 317 | serio_close(serio); | 337 | serio_close(serio); |
| 318 | serio_set_drvdata(serio, NULL); | 338 | serio_set_drvdata(serio, NULL); |
diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c index 677276b12020..42cb3faf7336 100644 --- a/drivers/input/keyboard/tosakbd.c +++ b/drivers/input/keyboard/tosakbd.c | |||
| @@ -31,7 +31,7 @@ | |||
| 31 | #define KB_DISCHARGE_DELAY 10 | 31 | #define KB_DISCHARGE_DELAY 10 |
| 32 | #define KB_ACTIVATE_DELAY 10 | 32 | #define KB_ACTIVATE_DELAY 10 |
| 33 | 33 | ||
| 34 | static unsigned int tosakbd_keycode[NR_SCANCODES] = { | 34 | static unsigned short tosakbd_keycode[NR_SCANCODES] = { |
| 35 | 0, | 35 | 0, |
| 36 | 0, KEY_W, 0, 0, 0, KEY_K, KEY_BACKSPACE, KEY_P, | 36 | 0, KEY_W, 0, 0, 0, KEY_K, KEY_BACKSPACE, KEY_P, |
| 37 | 0, 0, 0, 0, 0, 0, 0, 0, | 37 | 0, 0, 0, 0, 0, 0, 0, 0, |
| @@ -50,9 +50,9 @@ KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_ | |||
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| 52 | struct tosakbd { | 52 | struct tosakbd { |
| 53 | unsigned int keycode[ARRAY_SIZE(tosakbd_keycode)]; | 53 | unsigned short keycode[ARRAY_SIZE(tosakbd_keycode)]; |
| 54 | struct input_dev *input; | 54 | struct input_dev *input; |
| 55 | int suspended; | 55 | bool suspended; |
| 56 | spinlock_t lock; /* protect kbd scanning */ | 56 | spinlock_t lock; /* protect kbd scanning */ |
| 57 | struct timer_list timer; | 57 | struct timer_list timer; |
| 58 | }; | 58 | }; |
| @@ -215,7 +215,7 @@ static int tosakbd_suspend(struct platform_device *dev, pm_message_t state) | |||
| 215 | unsigned long flags; | 215 | unsigned long flags; |
| 216 | 216 | ||
| 217 | spin_lock_irqsave(&tosakbd->lock, flags); | 217 | spin_lock_irqsave(&tosakbd->lock, flags); |
| 218 | tosakbd->suspended = 1; | 218 | tosakbd->suspended = true; |
| 219 | spin_unlock_irqrestore(&tosakbd->lock, flags); | 219 | spin_unlock_irqrestore(&tosakbd->lock, flags); |
| 220 | 220 | ||
| 221 | del_timer_sync(&tosakbd->timer); | 221 | del_timer_sync(&tosakbd->timer); |
| @@ -227,7 +227,7 @@ static int tosakbd_resume(struct platform_device *dev) | |||
| 227 | { | 227 | { |
| 228 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | 228 | struct tosakbd *tosakbd = platform_get_drvdata(dev); |
| 229 | 229 | ||
| 230 | tosakbd->suspended = 0; | 230 | tosakbd->suspended = false; |
| 231 | tosakbd_scankeyboard(dev); | 231 | tosakbd_scankeyboard(dev); |
| 232 | 232 | ||
| 233 | return 0; | 233 | return 0; |
| @@ -277,14 +277,14 @@ static int __devinit tosakbd_probe(struct platform_device *pdev) { | |||
| 277 | 277 | ||
| 278 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | 278 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); |
| 279 | input_dev->keycode = tosakbd->keycode; | 279 | input_dev->keycode = tosakbd->keycode; |
| 280 | input_dev->keycodesize = sizeof(unsigned int); | 280 | input_dev->keycodesize = sizeof(tosakbd->keycode[0]); |
| 281 | input_dev->keycodemax = ARRAY_SIZE(tosakbd_keycode); | 281 | input_dev->keycodemax = ARRAY_SIZE(tosakbd_keycode); |
| 282 | 282 | ||
| 283 | memcpy(tosakbd->keycode, tosakbd_keycode, sizeof(tosakbd_keycode)); | 283 | memcpy(tosakbd->keycode, tosakbd_keycode, sizeof(tosakbd_keycode)); |
| 284 | 284 | ||
| 285 | for (i = 0; i < ARRAY_SIZE(tosakbd_keycode); i++) | 285 | for (i = 0; i < ARRAY_SIZE(tosakbd_keycode); i++) |
| 286 | __set_bit(tosakbd->keycode[i], input_dev->keybit); | 286 | __set_bit(tosakbd->keycode[i], input_dev->keybit); |
| 287 | clear_bit(0, input_dev->keybit); | 287 | __clear_bit(KEY_RESERVED, input_dev->keybit); |
| 288 | 288 | ||
| 289 | /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ | 289 | /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ |
| 290 | for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { | 290 | for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { |
| @@ -344,7 +344,7 @@ static int __devinit tosakbd_probe(struct platform_device *pdev) { | |||
| 344 | " direction for GPIO %d, error %d\n", | 344 | " direction for GPIO %d, error %d\n", |
| 345 | gpio, error); | 345 | gpio, error); |
| 346 | gpio_free(gpio); | 346 | gpio_free(gpio); |
| 347 | goto fail; | 347 | goto fail2; |
| 348 | } | 348 | } |
| 349 | 349 | ||
| 350 | } | 350 | } |
| @@ -353,7 +353,7 @@ static int __devinit tosakbd_probe(struct platform_device *pdev) { | |||
| 353 | if (error) { | 353 | if (error) { |
| 354 | printk(KERN_ERR "tosakbd: Unable to register input device, " | 354 | printk(KERN_ERR "tosakbd: Unable to register input device, " |
| 355 | "error: %d\n", error); | 355 | "error: %d\n", error); |
| 356 | goto fail; | 356 | goto fail2; |
| 357 | } | 357 | } |
| 358 | 358 | ||
| 359 | printk(KERN_INFO "input: Tosa Keyboard Registered\n"); | 359 | printk(KERN_INFO "input: Tosa Keyboard Registered\n"); |
diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c new file mode 100644 index 000000000000..9a2977c21696 --- /dev/null +++ b/drivers/input/keyboard/twl4030_keypad.c | |||
| @@ -0,0 +1,480 @@ | |||
| 1 | /* | ||
| 2 | * twl4030_keypad.c - driver for 8x8 keypad controller in twl4030 chips | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Texas Instruments, Inc. | ||
| 5 | * Copyright (C) 2008 Nokia Corporation | ||
| 6 | * | ||
| 7 | * Code re-written for 2430SDP by: | ||
| 8 | * Syed Mohammed Khasim <x0khasim@ti.com> | ||
| 9 | * | ||
| 10 | * Initial Code: | ||
| 11 | * Manjunatha G K <manjugk@ti.com> | ||
| 12 | * | ||
| 13 | * This program is free software; you can redistribute it and/or modify | ||
| 14 | * it under the terms of the GNU General Public License as published by | ||
| 15 | * the Free Software Foundation; either version 2 of the License, or | ||
| 16 | * (at your option) any later version. | ||
| 17 | * | ||
| 18 | * This program is distributed in the hope that it will be useful, | ||
| 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 21 | * GNU General Public License for more details. | ||
| 22 | * | ||
| 23 | * You should have received a copy of the GNU General Public License | ||
| 24 | * along with this program; if not, write to the Free Software | ||
| 25 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 26 | */ | ||
| 27 | |||
| 28 | #include <linux/kernel.h> | ||
| 29 | #include <linux/module.h> | ||
| 30 | #include <linux/init.h> | ||
| 31 | #include <linux/interrupt.h> | ||
| 32 | #include <linux/input.h> | ||
| 33 | #include <linux/platform_device.h> | ||
| 34 | #include <linux/i2c/twl4030.h> | ||
| 35 | |||
| 36 | |||
| 37 | /* | ||
| 38 | * The TWL4030 family chips include a keypad controller that supports | ||
| 39 | * up to an 8x8 switch matrix. The controller can issue system wakeup | ||
| 40 | * events, since it uses only the always-on 32KiHz oscillator, and has | ||
| 41 | * an internal state machine that decodes pressed keys, including | ||
| 42 | * multi-key combinations. | ||
| 43 | * | ||
| 44 | * This driver lets boards define what keycodes they wish to report for | ||
| 45 | * which scancodes, as part of the "struct twl4030_keypad_data" used in | ||
| 46 | * the probe() routine. | ||
| 47 | * | ||
| 48 | * See the TPS65950 documentation; that's the general availability | ||
| 49 | * version of the TWL5030 second generation part. | ||
| 50 | */ | ||
| 51 | #define TWL4030_MAX_ROWS 8 /* TWL4030 hard limit */ | ||
| 52 | #define TWL4030_MAX_COLS 8 | ||
| 53 | #define TWL4030_ROW_SHIFT 3 | ||
| 54 | #define TWL4030_KEYMAP_SIZE (TWL4030_MAX_ROWS * TWL4030_MAX_COLS) | ||
| 55 | |||
| 56 | struct twl4030_keypad { | ||
| 57 | unsigned short keymap[TWL4030_KEYMAP_SIZE]; | ||
| 58 | u16 kp_state[TWL4030_MAX_ROWS]; | ||
| 59 | unsigned n_rows; | ||
| 60 | unsigned n_cols; | ||
| 61 | unsigned irq; | ||
| 62 | |||
| 63 | struct device *dbg_dev; | ||
| 64 | struct input_dev *input; | ||
| 65 | }; | ||
| 66 | |||
| 67 | /*----------------------------------------------------------------------*/ | ||
| 68 | |||
| 69 | /* arbitrary prescaler value 0..7 */ | ||
| 70 | #define PTV_PRESCALER 4 | ||
| 71 | |||
| 72 | /* Register Offsets */ | ||
| 73 | #define KEYP_CTRL 0x00 | ||
| 74 | #define KEYP_DEB 0x01 | ||
| 75 | #define KEYP_LONG_KEY 0x02 | ||
| 76 | #define KEYP_LK_PTV 0x03 | ||
| 77 | #define KEYP_TIMEOUT_L 0x04 | ||
| 78 | #define KEYP_TIMEOUT_H 0x05 | ||
| 79 | #define KEYP_KBC 0x06 | ||
| 80 | #define KEYP_KBR 0x07 | ||
| 81 | #define KEYP_SMS 0x08 | ||
| 82 | #define KEYP_FULL_CODE_7_0 0x09 /* row 0 column status */ | ||
| 83 | #define KEYP_FULL_CODE_15_8 0x0a /* ... row 1 ... */ | ||
| 84 | #define KEYP_FULL_CODE_23_16 0x0b | ||
| 85 | #define KEYP_FULL_CODE_31_24 0x0c | ||
| 86 | #define KEYP_FULL_CODE_39_32 0x0d | ||
| 87 | #define KEYP_FULL_CODE_47_40 0x0e | ||
| 88 | #define KEYP_FULL_CODE_55_48 0x0f | ||
| 89 | #define KEYP_FULL_CODE_63_56 0x10 | ||
| 90 | #define KEYP_ISR1 0x11 | ||
| 91 | #define KEYP_IMR1 0x12 | ||
| 92 | #define KEYP_ISR2 0x13 | ||
| 93 | #define KEYP_IMR2 0x14 | ||
| 94 | #define KEYP_SIR 0x15 | ||
| 95 | #define KEYP_EDR 0x16 /* edge triggers */ | ||
| 96 | #define KEYP_SIH_CTRL 0x17 | ||
| 97 | |||
| 98 | /* KEYP_CTRL_REG Fields */ | ||
| 99 | #define KEYP_CTRL_SOFT_NRST BIT(0) | ||
| 100 | #define KEYP_CTRL_SOFTMODEN BIT(1) | ||
| 101 | #define KEYP_CTRL_LK_EN BIT(2) | ||
| 102 | #define KEYP_CTRL_TOE_EN BIT(3) | ||
| 103 | #define KEYP_CTRL_TOLE_EN BIT(4) | ||
| 104 | #define KEYP_CTRL_RP_EN BIT(5) | ||
| 105 | #define KEYP_CTRL_KBD_ON BIT(6) | ||
| 106 | |||
| 107 | /* KEYP_DEB, KEYP_LONG_KEY, KEYP_TIMEOUT_x*/ | ||
| 108 | #define KEYP_PERIOD_US(t, prescale) ((t) / (31 << (prescale + 1)) - 1) | ||
| 109 | |||
| 110 | /* KEYP_LK_PTV_REG Fields */ | ||
| 111 | #define KEYP_LK_PTV_PTV_SHIFT 5 | ||
| 112 | |||
| 113 | /* KEYP_{IMR,ISR,SIR} Fields */ | ||
| 114 | #define KEYP_IMR1_MIS BIT(3) | ||
| 115 | #define KEYP_IMR1_TO BIT(2) | ||
| 116 | #define KEYP_IMR1_LK BIT(1) | ||
| 117 | #define KEYP_IMR1_KP BIT(0) | ||
| 118 | |||
| 119 | /* KEYP_EDR Fields */ | ||
| 120 | #define KEYP_EDR_KP_FALLING 0x01 | ||
| 121 | #define KEYP_EDR_KP_RISING 0x02 | ||
| 122 | #define KEYP_EDR_KP_BOTH 0x03 | ||
| 123 | #define KEYP_EDR_LK_FALLING 0x04 | ||
| 124 | #define KEYP_EDR_LK_RISING 0x08 | ||
| 125 | #define KEYP_EDR_TO_FALLING 0x10 | ||
| 126 | #define KEYP_EDR_TO_RISING 0x20 | ||
| 127 | #define KEYP_EDR_MIS_FALLING 0x40 | ||
| 128 | #define KEYP_EDR_MIS_RISING 0x80 | ||
| 129 | |||
| 130 | |||
| 131 | /*----------------------------------------------------------------------*/ | ||
| 132 | |||
| 133 | static int twl4030_kpread(struct twl4030_keypad *kp, | ||
| 134 | u8 *data, u32 reg, u8 num_bytes) | ||
| 135 | { | ||
| 136 | int ret = twl4030_i2c_read(TWL4030_MODULE_KEYPAD, data, reg, num_bytes); | ||
| 137 | |||
| 138 | if (ret < 0) | ||
| 139 | dev_warn(kp->dbg_dev, | ||
| 140 | "Couldn't read TWL4030: %X - ret %d[%x]\n", | ||
| 141 | reg, ret, ret); | ||
| 142 | |||
| 143 | return ret; | ||
| 144 | } | ||
| 145 | |||
| 146 | static int twl4030_kpwrite_u8(struct twl4030_keypad *kp, u8 data, u32 reg) | ||
| 147 | { | ||
| 148 | int ret = twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, data, reg); | ||
| 149 | |||
| 150 | if (ret < 0) | ||
| 151 | dev_warn(kp->dbg_dev, | ||
| 152 | "Could not write TWL4030: %X - ret %d[%x]\n", | ||
| 153 | reg, ret, ret); | ||
| 154 | |||
| 155 | return ret; | ||
| 156 | } | ||
| 157 | |||
| 158 | static inline u16 twl4030_col_xlate(struct twl4030_keypad *kp, u8 col) | ||
| 159 | { | ||
| 160 | /* If all bits in a row are active for all coloumns then | ||
| 161 | * we have that row line connected to gnd. Mark this | ||
| 162 | * key on as if it was on matrix position n_cols (ie | ||
| 163 | * one higher than the size of the matrix). | ||
| 164 | */ | ||
| 165 | if (col == 0xFF) | ||
| 166 | return 1 << kp->n_cols; | ||
| 167 | else | ||
| 168 | return col & ((1 << kp->n_cols) - 1); | ||
| 169 | } | ||
| 170 | |||
| 171 | static int twl4030_read_kp_matrix_state(struct twl4030_keypad *kp, u16 *state) | ||
| 172 | { | ||
| 173 | u8 new_state[TWL4030_MAX_ROWS]; | ||
| 174 | int row; | ||
| 175 | int ret = twl4030_kpread(kp, new_state, | ||
| 176 | KEYP_FULL_CODE_7_0, kp->n_rows); | ||
| 177 | if (ret >= 0) | ||
| 178 | for (row = 0; row < kp->n_rows; row++) | ||
| 179 | state[row] = twl4030_col_xlate(kp, new_state[row]); | ||
| 180 | |||
| 181 | return ret; | ||
| 182 | } | ||
| 183 | |||
| 184 | static int twl4030_is_in_ghost_state(struct twl4030_keypad *kp, u16 *key_state) | ||
| 185 | { | ||
| 186 | int i; | ||
| 187 | u16 check = 0; | ||
| 188 | |||
| 189 | for (i = 0; i < kp->n_rows; i++) { | ||
| 190 | u16 col = key_state[i]; | ||
| 191 | |||
| 192 | if ((col & check) && hweight16(col) > 1) | ||
| 193 | return 1; | ||
| 194 | |||
| 195 | check |= col; | ||
| 196 | } | ||
| 197 | |||
| 198 | return 0; | ||
| 199 | } | ||
| 200 | |||
| 201 | static void twl4030_kp_scan(struct twl4030_keypad *kp, bool release_all) | ||
| 202 | { | ||
| 203 | struct input_dev *input = kp->input; | ||
| 204 | u16 new_state[TWL4030_MAX_ROWS]; | ||
| 205 | int col, row; | ||
| 206 | |||
| 207 | if (release_all) | ||
| 208 | memset(new_state, 0, sizeof(new_state)); | ||
| 209 | else { | ||
| 210 | /* check for any changes */ | ||
| 211 | int ret = twl4030_read_kp_matrix_state(kp, new_state); | ||
| 212 | |||
| 213 | if (ret < 0) /* panic ... */ | ||
| 214 | return; | ||
| 215 | |||
| 216 | if (twl4030_is_in_ghost_state(kp, new_state)) | ||
| 217 | return; | ||
| 218 | } | ||
| 219 | |||
| 220 | /* check for changes and print those */ | ||
| 221 | for (row = 0; row < kp->n_rows; row++) { | ||
| 222 | int changed = new_state[row] ^ kp->kp_state[row]; | ||
| 223 | |||
| 224 | if (!changed) | ||
| 225 | continue; | ||
| 226 | |||
| 227 | for (col = 0; col < kp->n_cols; col++) { | ||
| 228 | int code; | ||
| 229 | |||
| 230 | if (!(changed & (1 << col))) | ||
| 231 | continue; | ||
| 232 | |||
| 233 | dev_dbg(kp->dbg_dev, "key [%d:%d] %s\n", row, col, | ||
| 234 | (new_state[row] & (1 << col)) ? | ||
| 235 | "press" : "release"); | ||
| 236 | |||
| 237 | code = MATRIX_SCAN_CODE(row, col, TWL4030_ROW_SHIFT); | ||
| 238 | input_event(input, EV_MSC, MSC_SCAN, code); | ||
| 239 | input_report_key(input, kp->keymap[code], | ||
| 240 | new_state[row] & (1 << col)); | ||
| 241 | } | ||
| 242 | kp->kp_state[row] = new_state[row]; | ||
| 243 | } | ||
| 244 | input_sync(input); | ||
| 245 | } | ||
| 246 | |||
| 247 | /* | ||
| 248 | * Keypad interrupt handler | ||
| 249 | */ | ||
| 250 | static irqreturn_t do_kp_irq(int irq, void *_kp) | ||
| 251 | { | ||
| 252 | struct twl4030_keypad *kp = _kp; | ||
| 253 | u8 reg; | ||
| 254 | int ret; | ||
| 255 | |||
| 256 | #ifdef CONFIG_LOCKDEP | ||
| 257 | /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which | ||
| 258 | * we don't want and can't tolerate. Although it might be | ||
| 259 | * friendlier not to borrow this thread context... | ||
| 260 | */ | ||
| 261 | local_irq_enable(); | ||
| 262 | #endif | ||
| 263 | |||
| 264 | /* Read & Clear TWL4030 pending interrupt */ | ||
| 265 | ret = twl4030_kpread(kp, ®, KEYP_ISR1, 1); | ||
| 266 | |||
| 267 | /* Release all keys if I2C has gone bad or | ||
| 268 | * the KEYP has gone to idle state */ | ||
| 269 | if (ret >= 0 && (reg & KEYP_IMR1_KP)) | ||
| 270 | twl4030_kp_scan(kp, false); | ||
| 271 | else | ||
| 272 | twl4030_kp_scan(kp, true); | ||
| 273 | |||
| 274 | return IRQ_HANDLED; | ||
| 275 | } | ||
| 276 | |||
| 277 | static int __devinit twl4030_kp_program(struct twl4030_keypad *kp) | ||
| 278 | { | ||
| 279 | u8 reg; | ||
| 280 | int i; | ||
| 281 | |||
| 282 | /* Enable controller, with hardware decoding but not autorepeat */ | ||
| 283 | reg = KEYP_CTRL_SOFT_NRST | KEYP_CTRL_SOFTMODEN | ||
| 284 | | KEYP_CTRL_TOE_EN | KEYP_CTRL_KBD_ON; | ||
| 285 | if (twl4030_kpwrite_u8(kp, reg, KEYP_CTRL) < 0) | ||
| 286 | return -EIO; | ||
| 287 | |||
| 288 | /* NOTE: we could use sih_setup() here to package keypad | ||
| 289 | * event sources as four different IRQs ... but we don't. | ||
| 290 | */ | ||
| 291 | |||
| 292 | /* Enable TO rising and KP rising and falling edge detection */ | ||
| 293 | reg = KEYP_EDR_KP_BOTH | KEYP_EDR_TO_RISING; | ||
| 294 | if (twl4030_kpwrite_u8(kp, reg, KEYP_EDR) < 0) | ||
| 295 | return -EIO; | ||
| 296 | |||
| 297 | /* Set PTV prescaler Field */ | ||
| 298 | reg = (PTV_PRESCALER << KEYP_LK_PTV_PTV_SHIFT); | ||
| 299 | if (twl4030_kpwrite_u8(kp, reg, KEYP_LK_PTV) < 0) | ||
| 300 | return -EIO; | ||
| 301 | |||
| 302 | /* Set key debounce time to 20 ms */ | ||
| 303 | i = KEYP_PERIOD_US(20000, PTV_PRESCALER); | ||
| 304 | if (twl4030_kpwrite_u8(kp, i, KEYP_DEB) < 0) | ||
| 305 | return -EIO; | ||
| 306 | |||
| 307 | /* Set timeout period to 100 ms */ | ||
| 308 | i = KEYP_PERIOD_US(200000, PTV_PRESCALER); | ||
| 309 | if (twl4030_kpwrite_u8(kp, (i & 0xFF), KEYP_TIMEOUT_L) < 0) | ||
| 310 | return -EIO; | ||
| 311 | |||
| 312 | if (twl4030_kpwrite_u8(kp, (i >> 8), KEYP_TIMEOUT_H) < 0) | ||
| 313 | return -EIO; | ||
| 314 | |||
| 315 | /* | ||
| 316 | * Enable Clear-on-Read; disable remembering events that fire | ||
| 317 | * after the IRQ but before our handler acks (reads) them, | ||
| 318 | */ | ||
| 319 | reg = TWL4030_SIH_CTRL_COR_MASK | TWL4030_SIH_CTRL_PENDDIS_MASK; | ||
| 320 | if (twl4030_kpwrite_u8(kp, reg, KEYP_SIH_CTRL) < 0) | ||
| 321 | return -EIO; | ||
| 322 | |||
| 323 | /* initialize key state; irqs update it from here on */ | ||
| 324 | if (twl4030_read_kp_matrix_state(kp, kp->kp_state) < 0) | ||
| 325 | return -EIO; | ||
| 326 | |||
| 327 | return 0; | ||
| 328 | } | ||
| 329 | |||
| 330 | /* | ||
| 331 | * Registers keypad device with input subsystem | ||
| 332 | * and configures TWL4030 keypad registers | ||
| 333 | */ | ||
| 334 | static int __devinit twl4030_kp_probe(struct platform_device *pdev) | ||
| 335 | { | ||
| 336 | struct twl4030_keypad_data *pdata = pdev->dev.platform_data; | ||
| 337 | const struct matrix_keymap_data *keymap_data = pdata->keymap_data; | ||
| 338 | struct twl4030_keypad *kp; | ||
| 339 | struct input_dev *input; | ||
| 340 | u8 reg; | ||
| 341 | int error; | ||
| 342 | |||
| 343 | if (!pdata || !pdata->rows || !pdata->cols || | ||
| 344 | pdata->rows > TWL4030_MAX_ROWS || pdata->cols > TWL4030_MAX_COLS) { | ||
| 345 | dev_err(&pdev->dev, "Invalid platform_data\n"); | ||
| 346 | return -EINVAL; | ||
| 347 | } | ||
| 348 | |||
| 349 | kp = kzalloc(sizeof(*kp), GFP_KERNEL); | ||
| 350 | input = input_allocate_device(); | ||
| 351 | if (!kp || !input) { | ||
| 352 | error = -ENOMEM; | ||
| 353 | goto err1; | ||
| 354 | } | ||
| 355 | |||
| 356 | /* Get the debug Device */ | ||
| 357 | kp->dbg_dev = &pdev->dev; | ||
| 358 | kp->input = input; | ||
| 359 | |||
| 360 | kp->n_rows = pdata->rows; | ||
| 361 | kp->n_cols = pdata->cols; | ||
| 362 | kp->irq = platform_get_irq(pdev, 0); | ||
| 363 | |||
| 364 | /* setup input device */ | ||
| 365 | __set_bit(EV_KEY, input->evbit); | ||
| 366 | |||
| 367 | /* Enable auto repeat feature of Linux input subsystem */ | ||
| 368 | if (pdata->rep) | ||
| 369 | __set_bit(EV_REP, input->evbit); | ||
| 370 | |||
| 371 | input_set_capability(input, EV_MSC, MSC_SCAN); | ||
| 372 | |||
| 373 | input->name = "TWL4030 Keypad"; | ||
| 374 | input->phys = "twl4030_keypad/input0"; | ||
| 375 | input->dev.parent = &pdev->dev; | ||
| 376 | |||
| 377 | input->id.bustype = BUS_HOST; | ||
| 378 | input->id.vendor = 0x0001; | ||
| 379 | input->id.product = 0x0001; | ||
| 380 | input->id.version = 0x0003; | ||
| 381 | |||
| 382 | input->keycode = kp->keymap; | ||
| 383 | input->keycodesize = sizeof(kp->keymap[0]); | ||
| 384 | input->keycodemax = ARRAY_SIZE(kp->keymap); | ||
| 385 | |||
| 386 | matrix_keypad_build_keymap(keymap_data, TWL4030_ROW_SHIFT, | ||
| 387 | input->keycode, input->keybit); | ||
| 388 | |||
| 389 | error = input_register_device(input); | ||
| 390 | if (error) { | ||
| 391 | dev_err(kp->dbg_dev, | ||
| 392 | "Unable to register twl4030 keypad device\n"); | ||
| 393 | goto err1; | ||
| 394 | } | ||
| 395 | |||
| 396 | error = twl4030_kp_program(kp); | ||
| 397 | if (error) | ||
| 398 | goto err2; | ||
| 399 | |||
| 400 | /* | ||
| 401 | * This ISR will always execute in kernel thread context because of | ||
| 402 | * the need to access the TWL4030 over the I2C bus. | ||
| 403 | * | ||
| 404 | * NOTE: we assume this host is wired to TWL4040 INT1, not INT2 ... | ||
| 405 | */ | ||
| 406 | error = request_irq(kp->irq, do_kp_irq, 0, pdev->name, kp); | ||
| 407 | if (error) { | ||
| 408 | dev_info(kp->dbg_dev, "request_irq failed for irq no=%d\n", | ||
| 409 | kp->irq); | ||
| 410 | goto err3; | ||
| 411 | } | ||
| 412 | |||
| 413 | /* Enable KP and TO interrupts now. */ | ||
| 414 | reg = (u8) ~(KEYP_IMR1_KP | KEYP_IMR1_TO); | ||
| 415 | if (twl4030_kpwrite_u8(kp, reg, KEYP_IMR1)) { | ||
| 416 | error = -EIO; | ||
| 417 | goto err4; | ||
| 418 | } | ||
| 419 | |||
| 420 | platform_set_drvdata(pdev, kp); | ||
| 421 | return 0; | ||
| 422 | |||
| 423 | err4: | ||
| 424 | /* mask all events - we don't care about the result */ | ||
| 425 | (void) twl4030_kpwrite_u8(kp, 0xff, KEYP_IMR1); | ||
| 426 | err3: | ||
| 427 | free_irq(kp->irq, NULL); | ||
| 428 | err2: | ||
| 429 | input_unregister_device(input); | ||
| 430 | input = NULL; | ||
| 431 | err1: | ||
| 432 | input_free_device(input); | ||
| 433 | kfree(kp); | ||
| 434 | return error; | ||
| 435 | } | ||
| 436 | |||
| 437 | static int __devexit twl4030_kp_remove(struct platform_device *pdev) | ||
| 438 | { | ||
| 439 | struct twl4030_keypad *kp = platform_get_drvdata(pdev); | ||
| 440 | |||
| 441 | free_irq(kp->irq, kp); | ||
| 442 | input_unregister_device(kp->input); | ||
| 443 | platform_set_drvdata(pdev, NULL); | ||
| 444 | kfree(kp); | ||
| 445 | |||
| 446 | return 0; | ||
| 447 | } | ||
| 448 | |||
| 449 | /* | ||
| 450 | * NOTE: twl4030 are multi-function devices connected via I2C. | ||
| 451 | * So this device is a child of an I2C parent, thus it needs to | ||
| 452 | * support unplug/replug (which most platform devices don't). | ||
| 453 | */ | ||
| 454 | |||
| 455 | static struct platform_driver twl4030_kp_driver = { | ||
| 456 | .probe = twl4030_kp_probe, | ||
| 457 | .remove = __devexit_p(twl4030_kp_remove), | ||
| 458 | .driver = { | ||
| 459 | .name = "twl4030_keypad", | ||
| 460 | .owner = THIS_MODULE, | ||
| 461 | }, | ||
| 462 | }; | ||
| 463 | |||
| 464 | static int __init twl4030_kp_init(void) | ||
| 465 | { | ||
| 466 | return platform_driver_register(&twl4030_kp_driver); | ||
| 467 | } | ||
| 468 | module_init(twl4030_kp_init); | ||
| 469 | |||
| 470 | static void __exit twl4030_kp_exit(void) | ||
| 471 | { | ||
| 472 | platform_driver_unregister(&twl4030_kp_driver); | ||
| 473 | } | ||
| 474 | module_exit(twl4030_kp_exit); | ||
| 475 | |||
| 476 | MODULE_AUTHOR("Texas Instruments"); | ||
| 477 | MODULE_DESCRIPTION("TWL4030 Keypad Driver"); | ||
| 478 | MODULE_LICENSE("GPL"); | ||
| 479 | MODULE_ALIAS("platform:twl4030_keypad"); | ||
| 480 | |||
diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c new file mode 100644 index 000000000000..6032def03707 --- /dev/null +++ b/drivers/input/keyboard/w90p910_keypad.c | |||
| @@ -0,0 +1,281 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2008-2009 Nuvoton technology corporation. | ||
| 3 | * | ||
| 4 | * Wan ZongShun <mcuos.com@gmail.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation;version 2 of the License. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/init.h> | ||
| 15 | #include <linux/interrupt.h> | ||
| 16 | #include <linux/input.h> | ||
| 17 | #include <linux/device.h> | ||
| 18 | #include <linux/platform_device.h> | ||
| 19 | #include <linux/clk.h> | ||
| 20 | #include <linux/err.h> | ||
| 21 | #include <linux/io.h> | ||
| 22 | |||
| 23 | #include <mach/w90p910_keypad.h> | ||
| 24 | |||
| 25 | /* Keypad Interface Control Registers */ | ||
| 26 | #define KPI_CONF 0x00 | ||
| 27 | #define KPI_3KCONF 0x04 | ||
| 28 | #define KPI_LPCONF 0x08 | ||
| 29 | #define KPI_STATUS 0x0C | ||
| 30 | |||
| 31 | #define IS1KEY (0x01 << 16) | ||
| 32 | #define INTTR (0x01 << 21) | ||
| 33 | #define KEY0R (0x0f << 3) | ||
| 34 | #define KEY0C 0x07 | ||
| 35 | #define DEBOUNCE_BIT 0x08 | ||
| 36 | #define KSIZE0 (0x01 << 16) | ||
| 37 | #define KSIZE1 (0x01 << 17) | ||
| 38 | #define KPSEL (0x01 << 19) | ||
| 39 | #define ENKP (0x01 << 18) | ||
| 40 | |||
| 41 | #define KGET_RAW(n) (((n) & KEY0R) >> 3) | ||
| 42 | #define KGET_COLUMN(n) ((n) & KEY0C) | ||
| 43 | |||
| 44 | #define W90P910_MAX_KEY_NUM (8 * 8) | ||
| 45 | #define W90P910_ROW_SHIFT 3 | ||
| 46 | |||
| 47 | struct w90p910_keypad { | ||
| 48 | const struct w90p910_keypad_platform_data *pdata; | ||
| 49 | struct clk *clk; | ||
| 50 | struct input_dev *input_dev; | ||
| 51 | void __iomem *mmio_base; | ||
| 52 | int irq; | ||
| 53 | unsigned short keymap[W90P910_MAX_KEY_NUM]; | ||
| 54 | }; | ||
| 55 | |||
| 56 | static void w90p910_keypad_scan_matrix(struct w90p910_keypad *keypad, | ||
| 57 | unsigned int status) | ||
| 58 | { | ||
| 59 | struct input_dev *input_dev = keypad->input_dev; | ||
| 60 | unsigned int row = KGET_RAW(status); | ||
| 61 | unsigned int col = KGET_COLUMN(status); | ||
| 62 | unsigned int code = MATRIX_SCAN_CODE(row, col, W90P910_ROW_SHIFT); | ||
| 63 | unsigned int key = keypad->keymap[code]; | ||
| 64 | |||
| 65 | input_event(input_dev, EV_MSC, MSC_SCAN, code); | ||
| 66 | input_report_key(input_dev, key, 1); | ||
| 67 | input_sync(input_dev); | ||
| 68 | |||
| 69 | input_event(input_dev, EV_MSC, MSC_SCAN, code); | ||
| 70 | input_report_key(input_dev, key, 0); | ||
| 71 | input_sync(input_dev); | ||
| 72 | } | ||
| 73 | |||
| 74 | static irqreturn_t w90p910_keypad_irq_handler(int irq, void *dev_id) | ||
| 75 | { | ||
| 76 | struct w90p910_keypad *keypad = dev_id; | ||
| 77 | unsigned int kstatus, val; | ||
| 78 | |||
| 79 | kstatus = __raw_readl(keypad->mmio_base + KPI_STATUS); | ||
| 80 | |||
| 81 | val = INTTR | IS1KEY; | ||
| 82 | |||
| 83 | if (kstatus & val) | ||
| 84 | w90p910_keypad_scan_matrix(keypad, kstatus); | ||
| 85 | |||
| 86 | return IRQ_HANDLED; | ||
| 87 | } | ||
| 88 | |||
| 89 | static int w90p910_keypad_open(struct input_dev *dev) | ||
| 90 | { | ||
| 91 | struct w90p910_keypad *keypad = input_get_drvdata(dev); | ||
| 92 | const struct w90p910_keypad_platform_data *pdata = keypad->pdata; | ||
| 93 | unsigned int val, config; | ||
| 94 | |||
| 95 | /* Enable unit clock */ | ||
| 96 | clk_enable(keypad->clk); | ||
| 97 | |||
| 98 | val = __raw_readl(keypad->mmio_base + KPI_CONF); | ||
| 99 | val |= (KPSEL | ENKP); | ||
| 100 | val &= ~(KSIZE0 | KSIZE1); | ||
| 101 | |||
| 102 | config = pdata->prescale | (pdata->debounce << DEBOUNCE_BIT); | ||
| 103 | |||
| 104 | val |= config; | ||
| 105 | |||
| 106 | __raw_writel(val, keypad->mmio_base + KPI_CONF); | ||
| 107 | |||
| 108 | return 0; | ||
| 109 | } | ||
| 110 | |||
| 111 | static void w90p910_keypad_close(struct input_dev *dev) | ||
| 112 | { | ||
| 113 | struct w90p910_keypad *keypad = input_get_drvdata(dev); | ||
| 114 | |||
| 115 | /* Disable clock unit */ | ||
| 116 | clk_disable(keypad->clk); | ||
| 117 | } | ||
| 118 | |||
| 119 | static int __devinit w90p910_keypad_probe(struct platform_device *pdev) | ||
| 120 | { | ||
| 121 | const struct w90p910_keypad_platform_data *pdata = | ||
| 122 | pdev->dev.platform_data; | ||
| 123 | const struct matrix_keymap_data *keymap_data; | ||
| 124 | struct w90p910_keypad *keypad; | ||
| 125 | struct input_dev *input_dev; | ||
| 126 | struct resource *res; | ||
| 127 | int irq; | ||
| 128 | int error; | ||
| 129 | |||
| 130 | if (!pdata) { | ||
| 131 | dev_err(&pdev->dev, "no platform data defined\n"); | ||
| 132 | return -EINVAL; | ||
| 133 | } | ||
| 134 | |||
| 135 | keymap_data = pdata->keymap_data; | ||
| 136 | |||
| 137 | irq = platform_get_irq(pdev, 0); | ||
| 138 | if (irq < 0) { | ||
| 139 | dev_err(&pdev->dev, "failed to get keypad irq\n"); | ||
| 140 | return -ENXIO; | ||
| 141 | } | ||
| 142 | |||
| 143 | keypad = kzalloc(sizeof(struct w90p910_keypad), GFP_KERNEL); | ||
| 144 | input_dev = input_allocate_device(); | ||
| 145 | if (!keypad || !input_dev) { | ||
| 146 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
| 147 | error = -ENOMEM; | ||
| 148 | goto failed_free; | ||
| 149 | } | ||
| 150 | |||
| 151 | keypad->pdata = pdata; | ||
| 152 | keypad->input_dev = input_dev; | ||
| 153 | keypad->irq = irq; | ||
| 154 | |||
| 155 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 156 | if (res == NULL) { | ||
| 157 | dev_err(&pdev->dev, "failed to get I/O memory\n"); | ||
| 158 | error = -ENXIO; | ||
| 159 | goto failed_free; | ||
| 160 | } | ||
| 161 | |||
| 162 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
| 163 | if (res == NULL) { | ||
| 164 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | ||
| 165 | error = -EBUSY; | ||
| 166 | goto failed_free; | ||
| 167 | } | ||
| 168 | |||
| 169 | keypad->mmio_base = ioremap(res->start, resource_size(res)); | ||
| 170 | if (keypad->mmio_base == NULL) { | ||
| 171 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | ||
| 172 | error = -ENXIO; | ||
| 173 | goto failed_free_res; | ||
| 174 | } | ||
| 175 | |||
| 176 | keypad->clk = clk_get(&pdev->dev, NULL); | ||
| 177 | if (IS_ERR(keypad->clk)) { | ||
| 178 | dev_err(&pdev->dev, "failed to get keypad clock\n"); | ||
| 179 | error = PTR_ERR(keypad->clk); | ||
| 180 | goto failed_free_io; | ||
| 181 | } | ||
| 182 | |||
| 183 | /* set multi-function pin for w90p910 kpi. */ | ||
| 184 | mfp_set_groupi(&pdev->dev); | ||
| 185 | |||
| 186 | input_dev->name = pdev->name; | ||
| 187 | input_dev->id.bustype = BUS_HOST; | ||
| 188 | input_dev->open = w90p910_keypad_open; | ||
| 189 | input_dev->close = w90p910_keypad_close; | ||
| 190 | input_dev->dev.parent = &pdev->dev; | ||
| 191 | |||
| 192 | input_dev->keycode = keypad->keymap; | ||
| 193 | input_dev->keycodesize = sizeof(keypad->keymap[0]); | ||
| 194 | input_dev->keycodemax = ARRAY_SIZE(keypad->keymap); | ||
| 195 | |||
| 196 | input_set_drvdata(input_dev, keypad); | ||
| 197 | |||
| 198 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | ||
| 199 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | ||
| 200 | |||
| 201 | matrix_keypad_build_keymap(keymap_data, W90P910_ROW_SHIFT, | ||
| 202 | input_dev->keycode, input_dev->keybit); | ||
| 203 | |||
| 204 | error = request_irq(keypad->irq, w90p910_keypad_irq_handler, | ||
| 205 | IRQF_DISABLED, pdev->name, keypad); | ||
| 206 | if (error) { | ||
| 207 | dev_err(&pdev->dev, "failed to request IRQ\n"); | ||
| 208 | goto failed_put_clk; | ||
| 209 | } | ||
| 210 | |||
| 211 | /* Register the input device */ | ||
| 212 | error = input_register_device(input_dev); | ||
| 213 | if (error) { | ||
| 214 | dev_err(&pdev->dev, "failed to register input device\n"); | ||
| 215 | goto failed_free_irq; | ||
| 216 | } | ||
| 217 | |||
| 218 | platform_set_drvdata(pdev, keypad); | ||
| 219 | return 0; | ||
| 220 | |||
| 221 | failed_free_irq: | ||
| 222 | free_irq(irq, pdev); | ||
| 223 | failed_put_clk: | ||
| 224 | clk_put(keypad->clk); | ||
| 225 | failed_free_io: | ||
| 226 | iounmap(keypad->mmio_base); | ||
| 227 | failed_free_res: | ||
| 228 | release_mem_region(res->start, resource_size(res)); | ||
| 229 | failed_free: | ||
| 230 | input_free_device(input_dev); | ||
| 231 | kfree(keypad); | ||
| 232 | return error; | ||
| 233 | } | ||
| 234 | |||
| 235 | static int __devexit w90p910_keypad_remove(struct platform_device *pdev) | ||
| 236 | { | ||
| 237 | struct w90p910_keypad *keypad = platform_get_drvdata(pdev); | ||
| 238 | struct resource *res; | ||
| 239 | |||
| 240 | free_irq(keypad->irq, pdev); | ||
| 241 | |||
| 242 | clk_put(keypad->clk); | ||
| 243 | |||
| 244 | input_unregister_device(keypad->input_dev); | ||
| 245 | |||
| 246 | iounmap(keypad->mmio_base); | ||
| 247 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 248 | release_mem_region(res->start, resource_size(res)); | ||
| 249 | |||
| 250 | platform_set_drvdata(pdev, NULL); | ||
| 251 | kfree(keypad); | ||
| 252 | |||
| 253 | return 0; | ||
| 254 | } | ||
| 255 | |||
| 256 | static struct platform_driver w90p910_keypad_driver = { | ||
| 257 | .probe = w90p910_keypad_probe, | ||
| 258 | .remove = __devexit_p(w90p910_keypad_remove), | ||
| 259 | .driver = { | ||
| 260 | .name = "nuc900-keypad", | ||
| 261 | .owner = THIS_MODULE, | ||
| 262 | }, | ||
| 263 | }; | ||
| 264 | |||
| 265 | static int __init w90p910_keypad_init(void) | ||
| 266 | { | ||
| 267 | return platform_driver_register(&w90p910_keypad_driver); | ||
| 268 | } | ||
| 269 | |||
| 270 | static void __exit w90p910_keypad_exit(void) | ||
| 271 | { | ||
| 272 | platform_driver_unregister(&w90p910_keypad_driver); | ||
| 273 | } | ||
| 274 | |||
| 275 | module_init(w90p910_keypad_init); | ||
| 276 | module_exit(w90p910_keypad_exit); | ||
| 277 | |||
| 278 | MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); | ||
| 279 | MODULE_DESCRIPTION("w90p910 keypad driver"); | ||
| 280 | MODULE_LICENSE("GPL"); | ||
| 281 | MODULE_ALIAS("platform:nuc900-keypad"); | ||
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 1acfa3a05aad..cbe21bc96b52 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
| @@ -269,4 +269,14 @@ config INPUT_DM355EVM | |||
| 269 | 269 | ||
| 270 | To compile this driver as a module, choose M here: the | 270 | To compile this driver as a module, choose M here: the |
| 271 | module will be called dm355evm_keys. | 271 | module will be called dm355evm_keys. |
| 272 | |||
| 273 | config INPUT_BFIN_ROTARY | ||
| 274 | tristate "Blackfin Rotary support" | ||
| 275 | depends on BF54x || BF52x | ||
| 276 | help | ||
| 277 | Say Y here if you want to use the Blackfin Rotary. | ||
| 278 | |||
| 279 | To compile this driver as a module, choose M here: the | ||
| 280 | module will be called bfin-rotary. | ||
| 281 | |||
| 272 | endif | 282 | endif |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 0d979fd4cd57..79c1e9a5ea31 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
| @@ -8,6 +8,7 @@ obj-$(CONFIG_INPUT_APANEL) += apanel.o | |||
| 8 | obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o | 8 | obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o |
| 9 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o | 9 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o |
| 10 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o | 10 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o |
| 11 | obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o | ||
| 11 | obj-$(CONFIG_INPUT_CM109) += cm109.o | 12 | obj-$(CONFIG_INPUT_CM109) += cm109.o |
| 12 | obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o | 13 | obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o |
| 13 | obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o | 14 | obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o |
diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c new file mode 100644 index 000000000000..690f3fafa03b --- /dev/null +++ b/drivers/input/misc/bfin_rotary.c | |||
| @@ -0,0 +1,283 @@ | |||
| 1 | /* | ||
| 2 | * Rotary counter driver for Analog Devices Blackfin Processors | ||
| 3 | * | ||
| 4 | * Copyright 2008-2009 Analog Devices Inc. | ||
| 5 | * Licensed under the GPL-2 or later. | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/module.h> | ||
| 9 | #include <linux/version.h> | ||
| 10 | #include <linux/init.h> | ||
| 11 | #include <linux/interrupt.h> | ||
| 12 | #include <linux/irq.h> | ||
| 13 | #include <linux/pm.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/input.h> | ||
| 16 | |||
| 17 | #include <asm/portmux.h> | ||
| 18 | #include <asm/bfin_rotary.h> | ||
| 19 | |||
| 20 | static const u16 per_cnt[] = { | ||
| 21 | P_CNT_CUD, | ||
| 22 | P_CNT_CDG, | ||
| 23 | P_CNT_CZM, | ||
| 24 | 0 | ||
| 25 | }; | ||
| 26 | |||
| 27 | struct bfin_rot { | ||
| 28 | struct input_dev *input; | ||
| 29 | int irq; | ||
| 30 | unsigned int up_key; | ||
| 31 | unsigned int down_key; | ||
| 32 | unsigned int button_key; | ||
| 33 | unsigned int rel_code; | ||
| 34 | unsigned short cnt_config; | ||
| 35 | unsigned short cnt_imask; | ||
| 36 | unsigned short cnt_debounce; | ||
| 37 | }; | ||
| 38 | |||
| 39 | static void report_key_event(struct input_dev *input, int keycode) | ||
| 40 | { | ||
| 41 | /* simulate a press-n-release */ | ||
| 42 | input_report_key(input, keycode, 1); | ||
| 43 | input_sync(input); | ||
| 44 | input_report_key(input, keycode, 0); | ||
| 45 | input_sync(input); | ||
| 46 | } | ||
| 47 | |||
| 48 | static void report_rotary_event(struct bfin_rot *rotary, int delta) | ||
| 49 | { | ||
| 50 | struct input_dev *input = rotary->input; | ||
| 51 | |||
| 52 | if (rotary->up_key) { | ||
| 53 | report_key_event(input, | ||
| 54 | delta > 0 ? rotary->up_key : rotary->down_key); | ||
| 55 | } else { | ||
| 56 | input_report_rel(input, rotary->rel_code, delta); | ||
| 57 | input_sync(input); | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | static irqreturn_t bfin_rotary_isr(int irq, void *dev_id) | ||
| 62 | { | ||
| 63 | struct platform_device *pdev = dev_id; | ||
| 64 | struct bfin_rot *rotary = platform_get_drvdata(pdev); | ||
| 65 | int delta; | ||
| 66 | |||
| 67 | switch (bfin_read_CNT_STATUS()) { | ||
| 68 | |||
| 69 | case ICII: | ||
| 70 | break; | ||
| 71 | |||
| 72 | case UCII: | ||
| 73 | case DCII: | ||
| 74 | delta = bfin_read_CNT_COUNTER(); | ||
| 75 | if (delta) | ||
| 76 | report_rotary_event(rotary, delta); | ||
| 77 | break; | ||
| 78 | |||
| 79 | case CZMII: | ||
| 80 | report_key_event(rotary->input, rotary->button_key); | ||
| 81 | break; | ||
| 82 | |||
| 83 | default: | ||
| 84 | break; | ||
| 85 | } | ||
| 86 | |||
| 87 | bfin_write_CNT_COMMAND(W1LCNT_ZERO); /* Clear COUNTER */ | ||
| 88 | bfin_write_CNT_STATUS(-1); /* Clear STATUS */ | ||
| 89 | |||
| 90 | return IRQ_HANDLED; | ||
| 91 | } | ||
| 92 | |||
| 93 | static int __devinit bfin_rotary_probe(struct platform_device *pdev) | ||
| 94 | { | ||
| 95 | struct bfin_rotary_platform_data *pdata = pdev->dev.platform_data; | ||
| 96 | struct bfin_rot *rotary; | ||
| 97 | struct input_dev *input; | ||
| 98 | int error; | ||
| 99 | |||
| 100 | /* Basic validation */ | ||
| 101 | if ((pdata->rotary_up_key && !pdata->rotary_down_key) || | ||
| 102 | (!pdata->rotary_up_key && pdata->rotary_down_key)) { | ||
| 103 | return -EINVAL; | ||
| 104 | } | ||
| 105 | |||
| 106 | error = peripheral_request_list(per_cnt, dev_name(&pdev->dev)); | ||
| 107 | if (error) { | ||
| 108 | dev_err(&pdev->dev, "requesting peripherals failed\n"); | ||
| 109 | return error; | ||
| 110 | } | ||
| 111 | |||
| 112 | rotary = kzalloc(sizeof(struct bfin_rot), GFP_KERNEL); | ||
| 113 | input = input_allocate_device(); | ||
| 114 | if (!rotary || !input) { | ||
| 115 | error = -ENOMEM; | ||
| 116 | goto out1; | ||
| 117 | } | ||
| 118 | |||
| 119 | rotary->input = input; | ||
| 120 | |||
| 121 | rotary->up_key = pdata->rotary_up_key; | ||
| 122 | rotary->down_key = pdata->rotary_down_key; | ||
| 123 | rotary->button_key = pdata->rotary_button_key; | ||
| 124 | rotary->rel_code = pdata->rotary_rel_code; | ||
| 125 | |||
| 126 | error = rotary->irq = platform_get_irq(pdev, 0); | ||
| 127 | if (error < 0) | ||
| 128 | goto out1; | ||
| 129 | |||
| 130 | input->name = pdev->name; | ||
| 131 | input->phys = "bfin-rotary/input0"; | ||
| 132 | input->dev.parent = &pdev->dev; | ||
| 133 | |||
| 134 | input_set_drvdata(input, rotary); | ||
| 135 | |||
| 136 | input->id.bustype = BUS_HOST; | ||
| 137 | input->id.vendor = 0x0001; | ||
| 138 | input->id.product = 0x0001; | ||
| 139 | input->id.version = 0x0100; | ||
| 140 | |||
| 141 | if (rotary->up_key) { | ||
| 142 | __set_bit(EV_KEY, input->evbit); | ||
| 143 | __set_bit(rotary->up_key, input->keybit); | ||
| 144 | __set_bit(rotary->down_key, input->keybit); | ||
| 145 | } else { | ||
| 146 | __set_bit(EV_REL, input->evbit); | ||
| 147 | __set_bit(rotary->rel_code, input->relbit); | ||
| 148 | } | ||
| 149 | |||
| 150 | if (rotary->button_key) { | ||
| 151 | __set_bit(EV_KEY, input->evbit); | ||
| 152 | __set_bit(rotary->button_key, input->keybit); | ||
| 153 | } | ||
| 154 | |||
| 155 | error = request_irq(rotary->irq, bfin_rotary_isr, | ||
| 156 | 0, dev_name(&pdev->dev), pdev); | ||
| 157 | if (error) { | ||
| 158 | dev_err(&pdev->dev, | ||
| 159 | "unable to claim irq %d; error %d\n", | ||
| 160 | rotary->irq, error); | ||
| 161 | goto out1; | ||
| 162 | } | ||
| 163 | |||
| 164 | error = input_register_device(input); | ||
| 165 | if (error) { | ||
| 166 | dev_err(&pdev->dev, | ||
| 167 | "unable to register input device (%d)\n", error); | ||
| 168 | goto out2; | ||
| 169 | } | ||
| 170 | |||
| 171 | if (pdata->rotary_button_key) | ||
| 172 | bfin_write_CNT_IMASK(CZMIE); | ||
| 173 | |||
| 174 | if (pdata->mode & ROT_DEBE) | ||
| 175 | bfin_write_CNT_DEBOUNCE(pdata->debounce & DPRESCALE); | ||
| 176 | |||
| 177 | if (pdata->mode) | ||
| 178 | bfin_write_CNT_CONFIG(bfin_read_CNT_CONFIG() | | ||
| 179 | (pdata->mode & ~CNTE)); | ||
| 180 | |||
| 181 | bfin_write_CNT_IMASK(bfin_read_CNT_IMASK() | UCIE | DCIE); | ||
| 182 | bfin_write_CNT_CONFIG(bfin_read_CNT_CONFIG() | CNTE); | ||
| 183 | |||
| 184 | platform_set_drvdata(pdev, rotary); | ||
| 185 | device_init_wakeup(&pdev->dev, 1); | ||
| 186 | |||
| 187 | return 0; | ||
| 188 | |||
| 189 | out2: | ||
| 190 | free_irq(rotary->irq, pdev); | ||
| 191 | out1: | ||
| 192 | input_free_device(input); | ||
| 193 | kfree(rotary); | ||
| 194 | peripheral_free_list(per_cnt); | ||
| 195 | |||
| 196 | return error; | ||
| 197 | } | ||
| 198 | |||
| 199 | static int __devexit bfin_rotary_remove(struct platform_device *pdev) | ||
| 200 | { | ||
| 201 | struct bfin_rot *rotary = platform_get_drvdata(pdev); | ||
| 202 | |||
| 203 | bfin_write_CNT_CONFIG(0); | ||
| 204 | bfin_write_CNT_IMASK(0); | ||
| 205 | |||
| 206 | free_irq(rotary->irq, pdev); | ||
| 207 | input_unregister_device(rotary->input); | ||
| 208 | peripheral_free_list(per_cnt); | ||
| 209 | |||
| 210 | kfree(rotary); | ||
| 211 | platform_set_drvdata(pdev, NULL); | ||
| 212 | |||
| 213 | return 0; | ||
| 214 | } | ||
| 215 | |||
| 216 | #ifdef CONFIG_PM | ||
| 217 | static int bfin_rotary_suspend(struct device *dev) | ||
| 218 | { | ||
| 219 | struct platform_device *pdev = to_platform_device(dev); | ||
| 220 | struct bfin_rot *rotary = platform_get_drvdata(pdev); | ||
| 221 | |||
| 222 | rotary->cnt_config = bfin_read_CNT_CONFIG(); | ||
| 223 | rotary->cnt_imask = bfin_read_CNT_IMASK(); | ||
| 224 | rotary->cnt_debounce = bfin_read_CNT_DEBOUNCE(); | ||
| 225 | |||
| 226 | if (device_may_wakeup(&pdev->dev)) | ||
| 227 | enable_irq_wake(rotary->irq); | ||
| 228 | |||
| 229 | return 0; | ||
| 230 | } | ||
| 231 | |||
| 232 | static int bfin_rotary_resume(struct device *dev) | ||
| 233 | { | ||
| 234 | struct platform_device *pdev = to_platform_device(dev); | ||
| 235 | struct bfin_rot *rotary = platform_get_drvdata(pdev); | ||
| 236 | |||
| 237 | bfin_write_CNT_DEBOUNCE(rotary->cnt_debounce); | ||
| 238 | bfin_write_CNT_IMASK(rotary->cnt_imask); | ||
| 239 | bfin_write_CNT_CONFIG(rotary->cnt_config & ~CNTE); | ||
| 240 | |||
| 241 | if (device_may_wakeup(&pdev->dev)) | ||
| 242 | disable_irq_wake(rotary->irq); | ||
| 243 | |||
| 244 | if (rotary->cnt_config & CNTE) | ||
| 245 | bfin_write_CNT_CONFIG(rotary->cnt_config); | ||
| 246 | |||
| 247 | return 0; | ||
| 248 | } | ||
| 249 | |||
| 250 | static struct dev_pm_ops bfin_rotary_pm_ops = { | ||
| 251 | .suspend = bfin_rotary_suspend, | ||
| 252 | .resume = bfin_rotary_resume, | ||
| 253 | }; | ||
| 254 | #endif | ||
| 255 | |||
| 256 | static struct platform_driver bfin_rotary_device_driver = { | ||
| 257 | .probe = bfin_rotary_probe, | ||
| 258 | .remove = __devexit_p(bfin_rotary_remove), | ||
| 259 | .driver = { | ||
| 260 | .name = "bfin-rotary", | ||
| 261 | .owner = THIS_MODULE, | ||
| 262 | #ifdef CONFIG_PM | ||
| 263 | .pm = &bfin_rotary_pm_ops, | ||
| 264 | #endif | ||
| 265 | }, | ||
| 266 | }; | ||
| 267 | |||
| 268 | static int __init bfin_rotary_init(void) | ||
| 269 | { | ||
| 270 | return platform_driver_register(&bfin_rotary_device_driver); | ||
| 271 | } | ||
| 272 | module_init(bfin_rotary_init); | ||
| 273 | |||
| 274 | static void __exit bfin_rotary_exit(void) | ||
| 275 | { | ||
| 276 | platform_driver_unregister(&bfin_rotary_device_driver); | ||
| 277 | } | ||
| 278 | module_exit(bfin_rotary_exit); | ||
| 279 | |||
| 280 | MODULE_LICENSE("GPL"); | ||
| 281 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
| 282 | MODULE_DESCRIPTION("Rotary Counter driver for Blackfin Processors"); | ||
| 283 | MODULE_ALIAS("platform:bfin-rotary"); | ||
diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index d114d3a9e1e9..ee73d7219c92 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c | |||
| @@ -116,7 +116,7 @@ static int __devinit cobalt_buttons_probe(struct platform_device *pdev) | |||
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | bdev->poll_dev = poll_dev; | 118 | bdev->poll_dev = poll_dev; |
| 119 | bdev->reg = ioremap(res->start, res->end - res->start + 1); | 119 | bdev->reg = ioremap(res->start, resource_size(res)); |
| 120 | dev_set_drvdata(&pdev->dev, bdev); | 120 | dev_set_drvdata(&pdev->dev, bdev); |
| 121 | 121 | ||
| 122 | error = input_register_polled_device(poll_dev); | 122 | error = input_register_polled_device(poll_dev); |
diff --git a/drivers/input/misc/dm355evm_keys.c b/drivers/input/misc/dm355evm_keys.c index a63315ce4a6c..0918acae584a 100644 --- a/drivers/input/misc/dm355evm_keys.c +++ b/drivers/input/misc/dm355evm_keys.c | |||
| @@ -23,30 +23,16 @@ | |||
| 23 | * pressed, or its autorepeat kicks in, an event is sent. This driver | 23 | * pressed, or its autorepeat kicks in, an event is sent. This driver |
| 24 | * read those events from the small (32 event) queue and reports them. | 24 | * read those events from the small (32 event) queue and reports them. |
| 25 | * | 25 | * |
| 26 | * Because we communicate with the MSP430 using I2C, and all I2C calls | ||
| 27 | * in Linux sleep, we need to cons up a kind of threaded IRQ handler | ||
| 28 | * using a work_struct. The IRQ is active low, but we use it through | ||
| 29 | * the GPIO controller so we can trigger on falling edges. | ||
| 30 | * | ||
| 31 | * Note that physically there can only be one of these devices. | 26 | * Note that physically there can only be one of these devices. |
| 32 | * | 27 | * |
| 33 | * This driver was tested with firmware revision A4. | 28 | * This driver was tested with firmware revision A4. |
| 34 | */ | 29 | */ |
| 35 | struct dm355evm_keys { | 30 | struct dm355evm_keys { |
| 36 | struct work_struct work; | ||
| 37 | struct input_dev *input; | 31 | struct input_dev *input; |
| 38 | struct device *dev; | 32 | struct device *dev; |
| 39 | int irq; | 33 | int irq; |
| 40 | }; | 34 | }; |
| 41 | 35 | ||
| 42 | static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) | ||
| 43 | { | ||
| 44 | struct dm355evm_keys *keys = _keys; | ||
| 45 | |||
| 46 | schedule_work(&keys->work); | ||
| 47 | return IRQ_HANDLED; | ||
| 48 | } | ||
| 49 | |||
| 50 | /* These initial keycodes can be remapped by dm355evm_setkeycode(). */ | 36 | /* These initial keycodes can be remapped by dm355evm_setkeycode(). */ |
| 51 | static struct { | 37 | static struct { |
| 52 | u16 event; | 38 | u16 event; |
| @@ -110,13 +96,12 @@ static struct { | |||
| 110 | { 0x3169, KEY_PAUSE, }, | 96 | { 0x3169, KEY_PAUSE, }, |
| 111 | }; | 97 | }; |
| 112 | 98 | ||
| 113 | static void dm355evm_keys_work(struct work_struct *work) | 99 | /* runs in an IRQ thread -- can (and will!) sleep */ |
| 100 | static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) | ||
| 114 | { | 101 | { |
| 115 | struct dm355evm_keys *keys; | 102 | struct dm355evm_keys *keys = _keys; |
| 116 | int status; | 103 | int status; |
| 117 | 104 | ||
| 118 | keys = container_of(work, struct dm355evm_keys, work); | ||
| 119 | |||
| 120 | /* For simplicity we ignore INPUT_COUNT and just read | 105 | /* For simplicity we ignore INPUT_COUNT and just read |
| 121 | * events until we get the "queue empty" indicator. | 106 | * events until we get the "queue empty" indicator. |
| 122 | * Reading INPUT_LOW decrements the count. | 107 | * Reading INPUT_LOW decrements the count. |
| @@ -183,6 +168,19 @@ static void dm355evm_keys_work(struct work_struct *work) | |||
| 183 | input_report_key(keys->input, keycode, 0); | 168 | input_report_key(keys->input, keycode, 0); |
| 184 | input_sync(keys->input); | 169 | input_sync(keys->input); |
| 185 | } | 170 | } |
| 171 | return IRQ_HANDLED; | ||
| 172 | } | ||
| 173 | |||
| 174 | /* | ||
| 175 | * Because we communicate with the MSP430 using I2C, and all I2C calls | ||
| 176 | * in Linux sleep, we use a threaded IRQ handler. The IRQ itself is | ||
| 177 | * active low, but we go through the GPIO controller so we can trigger | ||
| 178 | * on falling edges and not worry about enabling/disabling the IRQ in | ||
| 179 | * the keypress handling path. | ||
| 180 | */ | ||
| 181 | static irqreturn_t dm355evm_keys_hardirq(int irq, void *_keys) | ||
| 182 | { | ||
| 183 | return IRQ_WAKE_THREAD; | ||
| 186 | } | 184 | } |
| 187 | 185 | ||
| 188 | static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode) | 186 | static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode) |
| @@ -233,7 +231,6 @@ static int __devinit dm355evm_keys_probe(struct platform_device *pdev) | |||
| 233 | 231 | ||
| 234 | keys->dev = &pdev->dev; | 232 | keys->dev = &pdev->dev; |
| 235 | keys->input = input; | 233 | keys->input = input; |
| 236 | INIT_WORK(&keys->work, dm355evm_keys_work); | ||
| 237 | 234 | ||
| 238 | /* set up "threaded IRQ handler" */ | 235 | /* set up "threaded IRQ handler" */ |
| 239 | status = platform_get_irq(pdev, 0); | 236 | status = platform_get_irq(pdev, 0); |
| @@ -260,9 +257,10 @@ static int __devinit dm355evm_keys_probe(struct platform_device *pdev) | |||
| 260 | 257 | ||
| 261 | /* REVISIT: flush the event queue? */ | 258 | /* REVISIT: flush the event queue? */ |
| 262 | 259 | ||
| 263 | status = request_irq(keys->irq, dm355evm_keys_irq, | 260 | status = request_threaded_irq(keys->irq, |
| 264 | IRQF_TRIGGER_FALLING, | 261 | dm355evm_keys_hardirq, dm355evm_keys_irq, |
| 265 | dev_name(&pdev->dev), keys); | 262 | IRQF_TRIGGER_FALLING, |
| 263 | dev_name(&pdev->dev), keys); | ||
| 266 | if (status < 0) | 264 | if (status < 0) |
| 267 | goto fail1; | 265 | goto fail1; |
| 268 | 266 | ||
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 27ee976eb54c..11fd038a078f 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
| @@ -243,9 +243,9 @@ enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH }; | |||
| 243 | #define FE_UNTESTED 0x80 | 243 | #define FE_UNTESTED 0x80 |
| 244 | 244 | ||
| 245 | static struct key_entry *keymap; /* = NULL; Current key map */ | 245 | static struct key_entry *keymap; /* = NULL; Current key map */ |
| 246 | static int have_wifi; | 246 | static bool have_wifi; |
| 247 | static int have_bluetooth; | 247 | static bool have_bluetooth; |
| 248 | static int have_leds; | 248 | static int leds_present; /* bitmask of leds present */ |
| 249 | 249 | ||
| 250 | static int __init dmi_matched(const struct dmi_system_id *dmi) | 250 | static int __init dmi_matched(const struct dmi_system_id *dmi) |
| 251 | { | 251 | { |
| @@ -254,11 +254,11 @@ static int __init dmi_matched(const struct dmi_system_id *dmi) | |||
| 254 | keymap = dmi->driver_data; | 254 | keymap = dmi->driver_data; |
| 255 | for (key = keymap; key->type != KE_END; key++) { | 255 | for (key = keymap; key->type != KE_END; key++) { |
| 256 | if (key->type == KE_WIFI) | 256 | if (key->type == KE_WIFI) |
| 257 | have_wifi = 1; | 257 | have_wifi = true; |
| 258 | else if (key->type == KE_BLUETOOTH) | 258 | else if (key->type == KE_BLUETOOTH) |
| 259 | have_bluetooth = 1; | 259 | have_bluetooth = true; |
| 260 | } | 260 | } |
| 261 | have_leds = key->code & (FE_MAIL_LED | FE_WIFI_LED); | 261 | leds_present = key->code & (FE_MAIL_LED | FE_WIFI_LED); |
| 262 | 262 | ||
| 263 | return 1; | 263 | return 1; |
| 264 | } | 264 | } |
| @@ -611,10 +611,24 @@ static struct key_entry keymap_wistron_generic[] __initdata = { | |||
| 611 | { KE_END, 0 } | 611 | { KE_END, 0 } |
| 612 | }; | 612 | }; |
| 613 | 613 | ||
| 614 | static struct key_entry keymap_aopen_1557[] __initdata = { | ||
| 615 | { KE_KEY, 0x01, {KEY_HELP} }, | ||
| 616 | { KE_KEY, 0x11, {KEY_PROG1} }, | ||
| 617 | { KE_KEY, 0x12, {KEY_PROG2} }, | ||
| 618 | { KE_WIFI, 0x30 }, | ||
| 619 | { KE_KEY, 0x22, {KEY_REWIND} }, | ||
| 620 | { KE_KEY, 0x23, {KEY_FORWARD} }, | ||
| 621 | { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, | ||
| 622 | { KE_KEY, 0x25, {KEY_STOPCD} }, | ||
| 623 | { KE_KEY, 0x31, {KEY_MAIL} }, | ||
| 624 | { KE_KEY, 0x36, {KEY_WWW} }, | ||
| 625 | { KE_END, 0 } | ||
| 626 | }; | ||
| 627 | |||
| 614 | static struct key_entry keymap_prestigio[] __initdata = { | 628 | static struct key_entry keymap_prestigio[] __initdata = { |
| 615 | { KE_KEY, 0x11, {KEY_PROG1} }, | 629 | { KE_KEY, 0x11, {KEY_PROG1} }, |
| 616 | { KE_KEY, 0x12, {KEY_PROG2} }, | 630 | { KE_KEY, 0x12, {KEY_PROG2} }, |
| 617 | { KE_WIFI, 0x30 }, | 631 | { KE_WIFI, 0x30 }, |
| 618 | { KE_KEY, 0x22, {KEY_REWIND} }, | 632 | { KE_KEY, 0x22, {KEY_REWIND} }, |
| 619 | { KE_KEY, 0x23, {KEY_FORWARD} }, | 633 | { KE_KEY, 0x23, {KEY_FORWARD} }, |
| 620 | { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, | 634 | { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, |
| @@ -985,6 +999,8 @@ static int __init select_keymap(void) | |||
| 985 | if (keymap_name != NULL) { | 999 | if (keymap_name != NULL) { |
| 986 | if (strcmp (keymap_name, "1557/MS2141") == 0) | 1000 | if (strcmp (keymap_name, "1557/MS2141") == 0) |
| 987 | keymap = keymap_wistron_ms2141; | 1001 | keymap = keymap_wistron_ms2141; |
| 1002 | else if (strcmp (keymap_name, "aopen1557") == 0) | ||
| 1003 | keymap = keymap_aopen_1557; | ||
| 988 | else if (strcmp (keymap_name, "prestigio") == 0) | 1004 | else if (strcmp (keymap_name, "prestigio") == 0) |
| 989 | keymap = keymap_prestigio; | 1005 | keymap = keymap_prestigio; |
| 990 | else if (strcmp (keymap_name, "generic") == 0) | 1006 | else if (strcmp (keymap_name, "generic") == 0) |
| @@ -1009,8 +1025,8 @@ static int __init select_keymap(void) | |||
| 1009 | 1025 | ||
| 1010 | static struct input_polled_dev *wistron_idev; | 1026 | static struct input_polled_dev *wistron_idev; |
| 1011 | static unsigned long jiffies_last_press; | 1027 | static unsigned long jiffies_last_press; |
| 1012 | static int wifi_enabled; | 1028 | static bool wifi_enabled; |
| 1013 | static int bluetooth_enabled; | 1029 | static bool bluetooth_enabled; |
| 1014 | 1030 | ||
| 1015 | static void report_key(struct input_dev *dev, unsigned int keycode) | 1031 | static void report_key(struct input_dev *dev, unsigned int keycode) |
| 1016 | { | 1032 | { |
| @@ -1053,24 +1069,24 @@ static struct led_classdev wistron_wifi_led = { | |||
| 1053 | 1069 | ||
| 1054 | static void __devinit wistron_led_init(struct device *parent) | 1070 | static void __devinit wistron_led_init(struct device *parent) |
| 1055 | { | 1071 | { |
| 1056 | if (have_leds & FE_WIFI_LED) { | 1072 | if (leds_present & FE_WIFI_LED) { |
| 1057 | u16 wifi = bios_get_default_setting(WIFI); | 1073 | u16 wifi = bios_get_default_setting(WIFI); |
| 1058 | if (wifi & 1) { | 1074 | if (wifi & 1) { |
| 1059 | wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF; | 1075 | wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF; |
| 1060 | if (led_classdev_register(parent, &wistron_wifi_led)) | 1076 | if (led_classdev_register(parent, &wistron_wifi_led)) |
| 1061 | have_leds &= ~FE_WIFI_LED; | 1077 | leds_present &= ~FE_WIFI_LED; |
| 1062 | else | 1078 | else |
| 1063 | bios_set_state(WIFI, wistron_wifi_led.brightness); | 1079 | bios_set_state(WIFI, wistron_wifi_led.brightness); |
| 1064 | 1080 | ||
| 1065 | } else | 1081 | } else |
| 1066 | have_leds &= ~FE_WIFI_LED; | 1082 | leds_present &= ~FE_WIFI_LED; |
| 1067 | } | 1083 | } |
| 1068 | 1084 | ||
| 1069 | if (have_leds & FE_MAIL_LED) { | 1085 | if (leds_present & FE_MAIL_LED) { |
| 1070 | /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */ | 1086 | /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */ |
| 1071 | wistron_mail_led.brightness = LED_OFF; | 1087 | wistron_mail_led.brightness = LED_OFF; |
| 1072 | if (led_classdev_register(parent, &wistron_mail_led)) | 1088 | if (led_classdev_register(parent, &wistron_mail_led)) |
| 1073 | have_leds &= ~FE_MAIL_LED; | 1089 | leds_present &= ~FE_MAIL_LED; |
| 1074 | else | 1090 | else |
| 1075 | bios_set_state(MAIL_LED, wistron_mail_led.brightness); | 1091 | bios_set_state(MAIL_LED, wistron_mail_led.brightness); |
| 1076 | } | 1092 | } |
| @@ -1078,28 +1094,28 @@ static void __devinit wistron_led_init(struct device *parent) | |||
| 1078 | 1094 | ||
| 1079 | static void __devexit wistron_led_remove(void) | 1095 | static void __devexit wistron_led_remove(void) |
| 1080 | { | 1096 | { |
| 1081 | if (have_leds & FE_MAIL_LED) | 1097 | if (leds_present & FE_MAIL_LED) |
| 1082 | led_classdev_unregister(&wistron_mail_led); | 1098 | led_classdev_unregister(&wistron_mail_led); |
| 1083 | 1099 | ||
| 1084 | if (have_leds & FE_WIFI_LED) | 1100 | if (leds_present & FE_WIFI_LED) |
| 1085 | led_classdev_unregister(&wistron_wifi_led); | 1101 | led_classdev_unregister(&wistron_wifi_led); |
| 1086 | } | 1102 | } |
| 1087 | 1103 | ||
| 1088 | static inline void wistron_led_suspend(void) | 1104 | static inline void wistron_led_suspend(void) |
| 1089 | { | 1105 | { |
| 1090 | if (have_leds & FE_MAIL_LED) | 1106 | if (leds_present & FE_MAIL_LED) |
| 1091 | led_classdev_suspend(&wistron_mail_led); | 1107 | led_classdev_suspend(&wistron_mail_led); |
| 1092 | 1108 | ||
| 1093 | if (have_leds & FE_WIFI_LED) | 1109 | if (leds_present & FE_WIFI_LED) |
| 1094 | led_classdev_suspend(&wistron_wifi_led); | 1110 | led_classdev_suspend(&wistron_wifi_led); |
| 1095 | } | 1111 | } |
| 1096 | 1112 | ||
| 1097 | static inline void wistron_led_resume(void) | 1113 | static inline void wistron_led_resume(void) |
| 1098 | { | 1114 | { |
| 1099 | if (have_leds & FE_MAIL_LED) | 1115 | if (leds_present & FE_MAIL_LED) |
| 1100 | led_classdev_resume(&wistron_mail_led); | 1116 | led_classdev_resume(&wistron_mail_led); |
| 1101 | 1117 | ||
| 1102 | if (have_leds & FE_WIFI_LED) | 1118 | if (leds_present & FE_WIFI_LED) |
| 1103 | led_classdev_resume(&wistron_wifi_led); | 1119 | led_classdev_resume(&wistron_wifi_led); |
| 1104 | } | 1120 | } |
| 1105 | 1121 | ||
| @@ -1312,7 +1328,7 @@ static int __devinit wistron_probe(struct platform_device *dev) | |||
| 1312 | if (have_wifi) { | 1328 | if (have_wifi) { |
| 1313 | u16 wifi = bios_get_default_setting(WIFI); | 1329 | u16 wifi = bios_get_default_setting(WIFI); |
| 1314 | if (wifi & 1) | 1330 | if (wifi & 1) |
| 1315 | wifi_enabled = (wifi & 2) ? 1 : 0; | 1331 | wifi_enabled = wifi & 2; |
| 1316 | else | 1332 | else |
| 1317 | have_wifi = 0; | 1333 | have_wifi = 0; |
| 1318 | 1334 | ||
| @@ -1323,15 +1339,16 @@ static int __devinit wistron_probe(struct platform_device *dev) | |||
| 1323 | if (have_bluetooth) { | 1339 | if (have_bluetooth) { |
| 1324 | u16 bt = bios_get_default_setting(BLUETOOTH); | 1340 | u16 bt = bios_get_default_setting(BLUETOOTH); |
| 1325 | if (bt & 1) | 1341 | if (bt & 1) |
| 1326 | bluetooth_enabled = (bt & 2) ? 1 : 0; | 1342 | bluetooth_enabled = bt & 2; |
| 1327 | else | 1343 | else |
| 1328 | have_bluetooth = 0; | 1344 | have_bluetooth = false; |
| 1329 | 1345 | ||
| 1330 | if (have_bluetooth) | 1346 | if (have_bluetooth) |
| 1331 | bios_set_state(BLUETOOTH, bluetooth_enabled); | 1347 | bios_set_state(BLUETOOTH, bluetooth_enabled); |
| 1332 | } | 1348 | } |
| 1333 | 1349 | ||
| 1334 | wistron_led_init(&dev->dev); | 1350 | wistron_led_init(&dev->dev); |
| 1351 | |||
| 1335 | err = setup_input_dev(); | 1352 | err = setup_input_dev(); |
| 1336 | if (err) { | 1353 | if (err) { |
| 1337 | bios_detach(); | 1354 | bios_detach(); |
| @@ -1352,7 +1369,7 @@ static int __devexit wistron_remove(struct platform_device *dev) | |||
| 1352 | } | 1369 | } |
| 1353 | 1370 | ||
| 1354 | #ifdef CONFIG_PM | 1371 | #ifdef CONFIG_PM |
| 1355 | static int wistron_suspend(struct platform_device *dev, pm_message_t state) | 1372 | static int wistron_suspend(struct device *dev) |
| 1356 | { | 1373 | { |
| 1357 | if (have_wifi) | 1374 | if (have_wifi) |
| 1358 | bios_set_state(WIFI, 0); | 1375 | bios_set_state(WIFI, 0); |
| @@ -1361,10 +1378,11 @@ static int wistron_suspend(struct platform_device *dev, pm_message_t state) | |||
| 1361 | bios_set_state(BLUETOOTH, 0); | 1378 | bios_set_state(BLUETOOTH, 0); |
| 1362 | 1379 | ||
| 1363 | wistron_led_suspend(); | 1380 | wistron_led_suspend(); |
| 1381 | |||
| 1364 | return 0; | 1382 | return 0; |
| 1365 | } | 1383 | } |
| 1366 | 1384 | ||
| 1367 | static int wistron_resume(struct platform_device *dev) | 1385 | static int wistron_resume(struct device *dev) |
| 1368 | { | 1386 | { |
| 1369 | if (have_wifi) | 1387 | if (have_wifi) |
| 1370 | bios_set_state(WIFI, wifi_enabled); | 1388 | bios_set_state(WIFI, wifi_enabled); |
| @@ -1373,24 +1391,30 @@ static int wistron_resume(struct platform_device *dev) | |||
| 1373 | bios_set_state(BLUETOOTH, bluetooth_enabled); | 1391 | bios_set_state(BLUETOOTH, bluetooth_enabled); |
| 1374 | 1392 | ||
| 1375 | wistron_led_resume(); | 1393 | wistron_led_resume(); |
| 1394 | |||
| 1376 | poll_bios(true); | 1395 | poll_bios(true); |
| 1377 | 1396 | ||
| 1378 | return 0; | 1397 | return 0; |
| 1379 | } | 1398 | } |
| 1380 | #else | 1399 | |
| 1381 | #define wistron_suspend NULL | 1400 | static const struct dev_pm_ops wistron_pm_ops = { |
| 1382 | #define wistron_resume NULL | 1401 | .suspend = wistron_suspend, |
| 1402 | .resume = wistron_resume, | ||
| 1403 | .poweroff = wistron_suspend, | ||
| 1404 | .restore = wistron_resume, | ||
| 1405 | }; | ||
| 1383 | #endif | 1406 | #endif |
| 1384 | 1407 | ||
| 1385 | static struct platform_driver wistron_driver = { | 1408 | static struct platform_driver wistron_driver = { |
| 1386 | .driver = { | 1409 | .driver = { |
| 1387 | .name = "wistron-bios", | 1410 | .name = "wistron-bios", |
| 1388 | .owner = THIS_MODULE, | 1411 | .owner = THIS_MODULE, |
| 1412 | #if CONFIG_PM | ||
| 1413 | .pm = &wistron_pm_ops, | ||
| 1414 | #endif | ||
| 1389 | }, | 1415 | }, |
| 1390 | .probe = wistron_probe, | 1416 | .probe = wistron_probe, |
| 1391 | .remove = __devexit_p(wistron_remove), | 1417 | .remove = __devexit_p(wistron_remove), |
| 1392 | .suspend = wistron_suspend, | ||
| 1393 | .resume = wistron_resume, | ||
| 1394 | }; | 1418 | }; |
| 1395 | 1419 | ||
| 1396 | static int __init wb_module_init(void) | 1420 | static int __init wb_module_init(void) |
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 8a2c5b14c8d8..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 | ||
| 110 | config 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 | ||
| 111 | config MOUSE_PS2_TOUCHKIT | 119 | config MOUSE_PS2_TOUCHKIT |
| 112 | bool "eGalax TouchKit PS/2 protocol extension" | 120 | bool "eGalax TouchKit PS/2 protocol extension" |
| @@ -262,14 +270,6 @@ config MOUSE_VSXXXAA | |||
| 262 | described in the source file). This driver also works with the | 270 | described in the source file). This driver also works with the |
| 263 | digitizer (VSXXX-AB) DEC produced. | 271 | digitizer (VSXXX-AB) DEC produced. |
| 264 | 272 | ||
| 265 | config MOUSE_HIL | ||
| 266 | tristate "HIL pointers (mice etc)." | ||
| 267 | depends on GSC || HP300 | ||
| 268 | select HP_SDC | ||
| 269 | select HIL_MLC | ||
| 270 | help | ||
| 271 | Say Y here to support HIL pointers. | ||
| 272 | |||
| 273 | config MOUSE_GPIO | 273 | config MOUSE_GPIO |
| 274 | tristate "GPIO mouse" | 274 | tristate "GPIO mouse" |
| 275 | depends on GENERIC_GPIO | 275 | depends on GENERIC_GPIO |
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 010f265ec152..570c84a4a654 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile | |||
| @@ -9,7 +9,6 @@ obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o | |||
| 9 | obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o | 9 | obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o |
| 10 | obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o | 10 | obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o |
| 11 | obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o | 11 | obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o |
| 12 | obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o | ||
| 13 | obj-$(CONFIG_MOUSE_INPORT) += inport.o | 12 | obj-$(CONFIG_MOUSE_INPORT) += inport.o |
| 14 | obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o | 13 | obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o |
| 15 | obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o | 14 | obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o |
| @@ -28,5 +27,6 @@ psmouse-$(CONFIG_MOUSE_PS2_ELANTECH) += elantech.o | |||
| 28 | psmouse-$(CONFIG_MOUSE_PS2_OLPC) += hgpk.o | 27 | psmouse-$(CONFIG_MOUSE_PS2_OLPC) += hgpk.o |
| 29 | psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o | 28 | psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o |
| 30 | psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o | 29 | psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o |
| 30 | psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o | ||
| 31 | psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o | 31 | psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o |
| 32 | psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o | 32 | psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 5547e2429fbe..f36110689aae 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
| @@ -279,7 +279,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int | |||
| 279 | * subsequent commands. It looks like glidepad is behind stickpointer, | 279 | * subsequent commands. It looks like glidepad is behind stickpointer, |
| 280 | * I'd thought it would be other way around... | 280 | * I'd thought it would be other way around... |
| 281 | */ | 281 | */ |
| 282 | static int alps_passthrough_mode(struct psmouse *psmouse, int enable) | 282 | static int alps_passthrough_mode(struct psmouse *psmouse, bool enable) |
| 283 | { | 283 | { |
| 284 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 284 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
| 285 | int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; | 285 | int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; |
| @@ -367,16 +367,16 @@ static int alps_poll(struct psmouse *psmouse) | |||
| 367 | { | 367 | { |
| 368 | struct alps_data *priv = psmouse->private; | 368 | struct alps_data *priv = psmouse->private; |
| 369 | unsigned char buf[6]; | 369 | unsigned char buf[6]; |
| 370 | int poll_failed; | 370 | bool poll_failed; |
| 371 | 371 | ||
| 372 | if (priv->i->flags & ALPS_PASS) | 372 | if (priv->i->flags & ALPS_PASS) |
| 373 | alps_passthrough_mode(psmouse, 1); | 373 | alps_passthrough_mode(psmouse, true); |
| 374 | 374 | ||
| 375 | poll_failed = ps2_command(&psmouse->ps2dev, buf, | 375 | poll_failed = ps2_command(&psmouse->ps2dev, buf, |
| 376 | PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; | 376 | PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; |
| 377 | 377 | ||
| 378 | if (priv->i->flags & ALPS_PASS) | 378 | if (priv->i->flags & ALPS_PASS) |
| 379 | alps_passthrough_mode(psmouse, 0); | 379 | alps_passthrough_mode(psmouse, false); |
| 380 | 380 | ||
| 381 | if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) | 381 | if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) |
| 382 | return -1; | 382 | return -1; |
| @@ -401,10 +401,12 @@ static int alps_hw_init(struct psmouse *psmouse, int *version) | |||
| 401 | if (!priv->i) | 401 | if (!priv->i) |
| 402 | return -1; | 402 | return -1; |
| 403 | 403 | ||
| 404 | if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 1)) | 404 | if ((priv->i->flags & ALPS_PASS) && |
| 405 | alps_passthrough_mode(psmouse, true)) { | ||
| 405 | return -1; | 406 | return -1; |
| 407 | } | ||
| 406 | 408 | ||
| 407 | if (alps_tap_mode(psmouse, 1)) { | 409 | if (alps_tap_mode(psmouse, true)) { |
| 408 | printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n"); | 410 | printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n"); |
| 409 | return -1; | 411 | return -1; |
| 410 | } | 412 | } |
| @@ -414,8 +416,10 @@ static int alps_hw_init(struct psmouse *psmouse, int *version) | |||
| 414 | return -1; | 416 | return -1; |
| 415 | } | 417 | } |
| 416 | 418 | ||
| 417 | if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 0)) | 419 | if ((priv->i->flags & ALPS_PASS) && |
| 420 | alps_passthrough_mode(psmouse, false)) { | ||
| 418 | return -1; | 421 | return -1; |
| 422 | } | ||
| 419 | 423 | ||
| 420 | /* ALPS needs stream mode, otherwise it won't report any data */ | 424 | /* ALPS needs stream mode, otherwise it won't report any data */ |
| 421 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) { | 425 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) { |
| @@ -519,7 +523,7 @@ init_fail: | |||
| 519 | return -1; | 523 | return -1; |
| 520 | } | 524 | } |
| 521 | 525 | ||
| 522 | int alps_detect(struct psmouse *psmouse, int set_properties) | 526 | int alps_detect(struct psmouse *psmouse, bool set_properties) |
| 523 | { | 527 | { |
| 524 | int version; | 528 | int version; |
| 525 | const struct alps_model_info *model; | 529 | const struct alps_model_info *model; |
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index 4bbddc99962b..bc87936fee1a 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h | |||
| @@ -26,10 +26,10 @@ struct alps_data { | |||
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | #ifdef CONFIG_MOUSE_PS2_ALPS | 28 | #ifdef CONFIG_MOUSE_PS2_ALPS |
| 29 | int alps_detect(struct psmouse *psmouse, int set_properties); | 29 | int alps_detect(struct psmouse *psmouse, bool set_properties); |
| 30 | int alps_init(struct psmouse *psmouse); | 30 | int alps_init(struct psmouse *psmouse); |
| 31 | #else | 31 | #else |
| 32 | inline int alps_detect(struct psmouse *psmouse, int set_properties) | 32 | inline int alps_detect(struct psmouse *psmouse, bool set_properties) |
| 33 | { | 33 | { |
| 34 | return -ENOSYS; | 34 | return -ENOSYS; |
| 35 | } | 35 | } |
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 2d8fc0bf6923..0d1d33468b43 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c | |||
| @@ -317,7 +317,7 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
| 317 | const struct tp_finger *f; | 317 | const struct tp_finger *f; |
| 318 | struct input_dev *input = dev->input; | 318 | struct input_dev *input = dev->input; |
| 319 | int raw_p, raw_w, raw_x, raw_y, raw_n; | 319 | int raw_p, raw_w, raw_x, raw_y, raw_n; |
| 320 | int ptest = 0, origin = 0, ibt = 0, nmin = 0, nmax = 0; | 320 | int ptest, origin, ibt = 0, nmin = 0, nmax = 0; |
| 321 | int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; | 321 | int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; |
| 322 | 322 | ||
| 323 | if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0) | 323 | if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0) |
| @@ -345,21 +345,22 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
| 345 | /* set the integrated button if applicable */ | 345 | /* set the integrated button if applicable */ |
| 346 | if (c->tp_type == TYPE2) | 346 | if (c->tp_type == TYPE2) |
| 347 | ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); | 347 | ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); |
| 348 | } | ||
| 349 | 348 | ||
| 350 | /* while tracking finger still valid, count all fingers */ | 349 | /* while tracking finger still valid, count all fingers */ |
| 351 | if (ptest > PRESSURE_LOW && origin) { | 350 | if (ptest > PRESSURE_LOW && origin) { |
| 352 | abs_p = ptest; | 351 | abs_p = ptest; |
| 353 | abs_w = int2bound(&c->w, raw_w); | 352 | abs_w = int2bound(&c->w, raw_w); |
| 354 | abs_x = int2bound(&c->x, raw_x - c->x.devmin); | 353 | abs_x = int2bound(&c->x, raw_x - c->x.devmin); |
| 355 | abs_y = int2bound(&c->y, c->y.devmax - raw_y); | 354 | abs_y = int2bound(&c->y, c->y.devmax - raw_y); |
| 356 | while (raw_n--) { | 355 | while (raw_n--) { |
| 357 | ptest = int2bound(&c->p, raw2int(f->force_major)); | 356 | ptest = int2bound(&c->p, |
| 358 | if (ptest > PRESSURE_LOW) | 357 | raw2int(f->force_major)); |
| 359 | nmax++; | 358 | if (ptest > PRESSURE_LOW) |
| 360 | if (ptest > PRESSURE_HIGH) | 359 | nmax++; |
| 361 | nmin++; | 360 | if (ptest > PRESSURE_HIGH) |
| 362 | f++; | 361 | nmin++; |
| 362 | f++; | ||
| 363 | } | ||
| 363 | } | 364 | } |
| 364 | } | 365 | } |
| 365 | 366 | ||
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 4bc78892ba91..fda35e615abf 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
| @@ -553,7 +553,7 @@ static struct attribute_group elantech_attr_group = { | |||
| 553 | /* | 553 | /* |
| 554 | * Use magic knock to detect Elantech touchpad | 554 | * Use magic knock to detect Elantech touchpad |
| 555 | */ | 555 | */ |
| 556 | int elantech_detect(struct psmouse *psmouse, int set_properties) | 556 | int elantech_detect(struct psmouse *psmouse, bool set_properties) |
| 557 | { | 557 | { |
| 558 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 558 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
| 559 | unsigned char param[3]; | 559 | unsigned char param[3]; |
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index ed848cc80814..feac5f7af966 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h | |||
| @@ -109,10 +109,10 @@ struct elantech_data { | |||
| 109 | }; | 109 | }; |
| 110 | 110 | ||
| 111 | #ifdef CONFIG_MOUSE_PS2_ELANTECH | 111 | #ifdef CONFIG_MOUSE_PS2_ELANTECH |
| 112 | int elantech_detect(struct psmouse *psmouse, int set_properties); | 112 | int elantech_detect(struct psmouse *psmouse, bool set_properties); |
| 113 | int elantech_init(struct psmouse *psmouse); | 113 | int elantech_init(struct psmouse *psmouse); |
| 114 | #else | 114 | #else |
| 115 | static inline int elantech_detect(struct psmouse *psmouse, int set_properties) | 115 | static inline int elantech_detect(struct psmouse *psmouse, bool set_properties) |
| 116 | { | 116 | { |
| 117 | return -ENOSYS; | 117 | return -ENOSYS; |
| 118 | } | 118 | } |
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index a1ad2f1a7bb3..de1e553028b7 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c | |||
| @@ -367,7 +367,36 @@ static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data, | |||
| 367 | } | 367 | } |
| 368 | 368 | ||
| 369 | __PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL, | 369 | __PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL, |
| 370 | hgpk_show_powered, hgpk_set_powered, 0); | 370 | hgpk_show_powered, hgpk_set_powered, false); |
| 371 | |||
| 372 | static ssize_t hgpk_trigger_recal_show(struct psmouse *psmouse, | ||
| 373 | void *data, char *buf) | ||
| 374 | { | ||
| 375 | return -EINVAL; | ||
| 376 | } | ||
| 377 | |||
| 378 | static ssize_t hgpk_trigger_recal(struct psmouse *psmouse, void *data, | ||
| 379 | const char *buf, size_t count) | ||
| 380 | { | ||
| 381 | struct hgpk_data *priv = psmouse->private; | ||
| 382 | unsigned long value; | ||
| 383 | int err; | ||
| 384 | |||
| 385 | err = strict_strtoul(buf, 10, &value); | ||
| 386 | if (err || value != 1) | ||
| 387 | return -EINVAL; | ||
| 388 | |||
| 389 | /* | ||
| 390 | * We queue work instead of doing recalibration right here | ||
| 391 | * to avoid adding locking to to hgpk_force_recalibrate() | ||
| 392 | * since workqueue provides serialization. | ||
| 393 | */ | ||
| 394 | psmouse_queue_work(psmouse, &priv->recalib_wq, 0); | ||
| 395 | return count; | ||
| 396 | } | ||
| 397 | |||
| 398 | __PSMOUSE_DEFINE_ATTR(recalibrate, S_IWUSR | S_IRUGO, NULL, | ||
| 399 | hgpk_trigger_recal_show, hgpk_trigger_recal, false); | ||
| 371 | 400 | ||
| 372 | static void hgpk_disconnect(struct psmouse *psmouse) | 401 | static void hgpk_disconnect(struct psmouse *psmouse) |
| 373 | { | 402 | { |
| @@ -375,6 +404,11 @@ static void hgpk_disconnect(struct psmouse *psmouse) | |||
| 375 | 404 | ||
| 376 | device_remove_file(&psmouse->ps2dev.serio->dev, | 405 | device_remove_file(&psmouse->ps2dev.serio->dev, |
| 377 | &psmouse_attr_powered.dattr); | 406 | &psmouse_attr_powered.dattr); |
| 407 | |||
| 408 | if (psmouse->model >= HGPK_MODEL_C) | ||
| 409 | device_remove_file(&psmouse->ps2dev.serio->dev, | ||
| 410 | &psmouse_attr_recalibrate.dattr); | ||
| 411 | |||
| 378 | psmouse_reset(psmouse); | 412 | psmouse_reset(psmouse); |
| 379 | kfree(priv); | 413 | kfree(priv); |
| 380 | } | 414 | } |
| @@ -423,10 +457,25 @@ static int hgpk_register(struct psmouse *psmouse) | |||
| 423 | 457 | ||
| 424 | err = device_create_file(&psmouse->ps2dev.serio->dev, | 458 | err = device_create_file(&psmouse->ps2dev.serio->dev, |
| 425 | &psmouse_attr_powered.dattr); | 459 | &psmouse_attr_powered.dattr); |
| 426 | if (err) | 460 | if (err) { |
| 427 | hgpk_err(psmouse, "Failed to create sysfs attribute\n"); | 461 | hgpk_err(psmouse, "Failed creating 'powered' sysfs node\n"); |
| 462 | return err; | ||
| 463 | } | ||
| 428 | 464 | ||
| 429 | return err; | 465 | /* C-series touchpads added the recalibrate command */ |
| 466 | if (psmouse->model >= HGPK_MODEL_C) { | ||
| 467 | err = device_create_file(&psmouse->ps2dev.serio->dev, | ||
| 468 | &psmouse_attr_recalibrate.dattr); | ||
| 469 | if (err) { | ||
| 470 | hgpk_err(psmouse, | ||
| 471 | "Failed creating 'recalibrate' sysfs node\n"); | ||
| 472 | device_remove_file(&psmouse->ps2dev.serio->dev, | ||
| 473 | &psmouse_attr_powered.dattr); | ||
| 474 | return err; | ||
| 475 | } | ||
| 476 | } | ||
| 477 | |||
| 478 | return 0; | ||
| 430 | } | 479 | } |
| 431 | 480 | ||
| 432 | int hgpk_init(struct psmouse *psmouse) | 481 | int hgpk_init(struct psmouse *psmouse) |
| @@ -440,7 +489,7 @@ int hgpk_init(struct psmouse *psmouse) | |||
| 440 | 489 | ||
| 441 | psmouse->private = priv; | 490 | psmouse->private = priv; |
| 442 | priv->psmouse = psmouse; | 491 | priv->psmouse = psmouse; |
| 443 | priv->powered = 1; | 492 | priv->powered = true; |
| 444 | INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work); | 493 | INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work); |
| 445 | 494 | ||
| 446 | err = psmouse_reset(psmouse); | 495 | err = psmouse_reset(psmouse); |
| @@ -483,7 +532,7 @@ static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse) | |||
| 483 | return param[2]; | 532 | return param[2]; |
| 484 | } | 533 | } |
| 485 | 534 | ||
| 486 | int hgpk_detect(struct psmouse *psmouse, int set_properties) | 535 | int hgpk_detect(struct psmouse *psmouse, bool set_properties) |
| 487 | { | 536 | { |
| 488 | int version; | 537 | int version; |
| 489 | 538 | ||
diff --git a/drivers/input/mouse/hgpk.h b/drivers/input/mouse/hgpk.h index a4b2a96f5f54..d61cfd3ee9cb 100644 --- a/drivers/input/mouse/hgpk.h +++ b/drivers/input/mouse/hgpk.h | |||
| @@ -15,7 +15,7 @@ enum hgpk_model_t { | |||
| 15 | 15 | ||
| 16 | struct hgpk_data { | 16 | struct hgpk_data { |
| 17 | struct psmouse *psmouse; | 17 | struct psmouse *psmouse; |
| 18 | int powered; | 18 | bool powered; |
| 19 | int count, x_tally, y_tally; /* hardware workaround stuff */ | 19 | int count, x_tally, y_tally; /* hardware workaround stuff */ |
| 20 | unsigned long recalib_window; | 20 | unsigned long recalib_window; |
| 21 | struct delayed_work recalib_wq; | 21 | struct delayed_work recalib_wq; |
| @@ -33,10 +33,10 @@ struct hgpk_data { | |||
| 33 | dev_notice(&(psmouse)->ps2dev.serio->dev, format, ## arg) | 33 | dev_notice(&(psmouse)->ps2dev.serio->dev, format, ## arg) |
| 34 | 34 | ||
| 35 | #ifdef CONFIG_MOUSE_PS2_OLPC | 35 | #ifdef CONFIG_MOUSE_PS2_OLPC |
| 36 | int hgpk_detect(struct psmouse *psmouse, int set_properties); | 36 | int hgpk_detect(struct psmouse *psmouse, bool set_properties); |
| 37 | int hgpk_init(struct psmouse *psmouse); | 37 | int hgpk_init(struct psmouse *psmouse); |
| 38 | #else | 38 | #else |
| 39 | static inline int hgpk_detect(struct psmouse *psmouse, int set_properties) | 39 | static inline int hgpk_detect(struct psmouse *psmouse, bool set_properties) |
| 40 | { | 40 | { |
| 41 | return -ENODEV; | 41 | return -ENODEV; |
| 42 | } | 42 | } |
diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c deleted file mode 100644 index 3263ce083bf0..000000000000 --- a/drivers/input/mouse/hil_ptr.c +++ /dev/null | |||
| @@ -1,447 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Generic linux-input device driver for axis-bearing devices | ||
| 3 | * | ||
| 4 | * Copyright (c) 2001 Brian S. Julin | ||
| 5 | * All rights reserved. | ||
| 6 | * | ||
| 7 | * Redistribution and use in source and binary forms, with or without | ||
| 8 | * modification, are permitted provided that the following conditions | ||
| 9 | * are met: | ||
| 10 | * 1. Redistributions of source code must retain the above copyright | ||
| 11 | * notice, this list of conditions, and the following disclaimer, | ||
| 12 | * without modification. | ||
| 13 | * 2. The name of the author may not be used to endorse or promote products | ||
| 14 | * derived from this software without specific prior written permission. | ||
| 15 | * | ||
| 16 | * Alternatively, this software may be distributed under the terms of the | ||
| 17 | * GNU General Public License ("GPL"). | ||
| 18 | * | ||
| 19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
| 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
| 23 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
| 28 | * | ||
| 29 | * References: | ||
| 30 | * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A | ||
| 31 | * | ||
| 32 | */ | ||
| 33 | |||
| 34 | #include <linux/hil.h> | ||
| 35 | #include <linux/input.h> | ||
| 36 | #include <linux/serio.h> | ||
| 37 | #include <linux/kernel.h> | ||
| 38 | #include <linux/module.h> | ||
| 39 | #include <linux/init.h> | ||
| 40 | #include <linux/slab.h> | ||
| 41 | #include <linux/pci_ids.h> | ||
| 42 | |||
| 43 | #define PREFIX "HIL PTR: " | ||
| 44 | #define HIL_GENERIC_NAME "HIL pointer device" | ||
| 45 | |||
| 46 | MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>"); | ||
| 47 | MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver"); | ||
| 48 | MODULE_LICENSE("Dual BSD/GPL"); | ||
| 49 | MODULE_ALIAS("serio:ty03pr25id0Fex*"); | ||
| 50 | |||
| 51 | #define TABLET_SIMULATES_MOUSE /* allow tablet to be used as mouse */ | ||
| 52 | #undef TABLET_AUTOADJUST /* auto-adjust valid tablet ranges */ | ||
| 53 | |||
| 54 | |||
| 55 | #define HIL_PTR_MAX_LENGTH 16 | ||
| 56 | |||
| 57 | struct hil_ptr { | ||
| 58 | struct input_dev *dev; | ||
| 59 | struct serio *serio; | ||
| 60 | |||
| 61 | /* Input buffer and index for packets from HIL bus. */ | ||
| 62 | hil_packet data[HIL_PTR_MAX_LENGTH]; | ||
| 63 | int idx4; /* four counts per packet */ | ||
| 64 | |||
| 65 | /* Raw device info records from HIL bus, see hil.h for fields. */ | ||
| 66 | char idd[HIL_PTR_MAX_LENGTH]; /* DID byte and IDD record */ | ||
| 67 | char rsc[HIL_PTR_MAX_LENGTH]; /* RSC record */ | ||
| 68 | char exd[HIL_PTR_MAX_LENGTH]; /* EXD record */ | ||
| 69 | char rnm[HIL_PTR_MAX_LENGTH + 1]; /* RNM record + NULL term. */ | ||
| 70 | |||
| 71 | /* Extra device details not contained in struct input_dev. */ | ||
| 72 | unsigned int nbtn, naxes; | ||
| 73 | unsigned int btnmap[7]; | ||
| 74 | |||
| 75 | /* Something to sleep around with. */ | ||
| 76 | struct semaphore sem; | ||
| 77 | }; | ||
| 78 | |||
| 79 | /* Process a complete packet after transfer from the HIL */ | ||
| 80 | static void hil_ptr_process_record(struct hil_ptr *ptr) | ||
| 81 | { | ||
| 82 | struct input_dev *dev = ptr->dev; | ||
| 83 | hil_packet *data = ptr->data; | ||
| 84 | hil_packet p; | ||
| 85 | int idx, i, cnt, laxis; | ||
| 86 | int ax16, absdev; | ||
| 87 | |||
| 88 | idx = ptr->idx4/4; | ||
| 89 | p = data[idx - 1]; | ||
| 90 | |||
| 91 | if ((p & ~HIL_CMDCT_POL) == | ||
| 92 | (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) | ||
| 93 | goto report; | ||
| 94 | if ((p & ~HIL_CMDCT_RPL) == | ||
| 95 | (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) | ||
| 96 | goto report; | ||
| 97 | |||
| 98 | /* Not a poll response. See if we are loading config records. */ | ||
| 99 | switch (p & HIL_PKT_DATA_MASK) { | ||
| 100 | case HIL_CMD_IDD: | ||
| 101 | for (i = 0; i < idx; i++) | ||
| 102 | ptr->idd[i] = ptr->data[i] & HIL_PKT_DATA_MASK; | ||
| 103 | for (; i < HIL_PTR_MAX_LENGTH; i++) | ||
| 104 | ptr->idd[i] = 0; | ||
| 105 | break; | ||
| 106 | |||
| 107 | case HIL_CMD_RSC: | ||
| 108 | for (i = 0; i < idx; i++) | ||
| 109 | ptr->rsc[i] = ptr->data[i] & HIL_PKT_DATA_MASK; | ||
| 110 | for (; i < HIL_PTR_MAX_LENGTH; i++) | ||
| 111 | ptr->rsc[i] = 0; | ||
| 112 | break; | ||
| 113 | |||
| 114 | case HIL_CMD_EXD: | ||
| 115 | for (i = 0; i < idx; i++) | ||
| 116 | ptr->exd[i] = ptr->data[i] & HIL_PKT_DATA_MASK; | ||
| 117 | for (; i < HIL_PTR_MAX_LENGTH; i++) | ||
| 118 | ptr->exd[i] = 0; | ||
| 119 | break; | ||
| 120 | |||
| 121 | case HIL_CMD_RNM: | ||
| 122 | for (i = 0; i < idx; i++) | ||
| 123 | ptr->rnm[i] = ptr->data[i] & HIL_PKT_DATA_MASK; | ||
| 124 | for (; i < HIL_PTR_MAX_LENGTH + 1; i++) | ||
| 125 | ptr->rnm[i] = 0; | ||
| 126 | break; | ||
| 127 | |||
| 128 | default: | ||
| 129 | /* These occur when device isn't present */ | ||
| 130 | if (p == (HIL_ERR_INT | HIL_PKT_CMD)) | ||
| 131 | break; | ||
| 132 | /* Anything else we'd like to know about. */ | ||
| 133 | printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p); | ||
| 134 | break; | ||
| 135 | } | ||
| 136 | goto out; | ||
| 137 | |||
| 138 | report: | ||
| 139 | if ((p & HIL_CMDCT_POL) != idx - 1) { | ||
| 140 | printk(KERN_WARNING PREFIX | ||
| 141 | "Malformed poll packet %x (idx = %i)\n", p, idx); | ||
| 142 | goto out; | ||
| 143 | } | ||
| 144 | |||
| 145 | i = (ptr->data[0] & HIL_POL_AXIS_ALT) ? 3 : 0; | ||
| 146 | laxis = ptr->data[0] & HIL_POL_NUM_AXES_MASK; | ||
| 147 | laxis += i; | ||
| 148 | |||
| 149 | ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */ | ||
| 150 | absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; | ||
| 151 | |||
| 152 | for (cnt = 1; i < laxis; i++) { | ||
| 153 | unsigned int lo,hi,val; | ||
| 154 | lo = ptr->data[cnt++] & HIL_PKT_DATA_MASK; | ||
| 155 | hi = ax16 ? (ptr->data[cnt++] & HIL_PKT_DATA_MASK) : 0; | ||
| 156 | if (absdev) { | ||
| 157 | val = lo + (hi<<8); | ||
| 158 | #ifdef TABLET_AUTOADJUST | ||
| 159 | if (val < dev->absmin[ABS_X + i]) | ||
| 160 | dev->absmin[ABS_X + i] = val; | ||
| 161 | if (val > dev->absmax[ABS_X + i]) | ||
| 162 | dev->absmax[ABS_X + i] = val; | ||
| 163 | #endif | ||
| 164 | if (i%3) val = dev->absmax[ABS_X + i] - val; | ||
| 165 | input_report_abs(dev, ABS_X + i, val); | ||
| 166 | } else { | ||
| 167 | val = (int) (((int8_t)lo) | ((int8_t)hi<<8)); | ||
| 168 | if (i%3) | ||
| 169 | val *= -1; | ||
| 170 | input_report_rel(dev, REL_X + i, val); | ||
| 171 | } | ||
| 172 | } | ||
| 173 | |||
| 174 | while (cnt < idx - 1) { | ||
| 175 | unsigned int btn; | ||
| 176 | int up; | ||
| 177 | btn = ptr->data[cnt++]; | ||
| 178 | up = btn & 1; | ||
| 179 | btn &= 0xfe; | ||
| 180 | if (btn == 0x8e) | ||
| 181 | continue; /* TODO: proximity == touch? */ | ||
| 182 | else | ||
| 183 | if ((btn > 0x8c) || (btn < 0x80)) | ||
| 184 | continue; | ||
| 185 | btn = (btn - 0x80) >> 1; | ||
| 186 | btn = ptr->btnmap[btn]; | ||
| 187 | input_report_key(dev, btn, !up); | ||
| 188 | } | ||
| 189 | input_sync(dev); | ||
| 190 | out: | ||
| 191 | ptr->idx4 = 0; | ||
| 192 | up(&ptr->sem); | ||
| 193 | } | ||
| 194 | |||
| 195 | static void hil_ptr_process_err(struct hil_ptr *ptr) | ||
| 196 | { | ||
| 197 | printk(KERN_WARNING PREFIX "errored HIL packet\n"); | ||
| 198 | ptr->idx4 = 0; | ||
| 199 | up(&ptr->sem); | ||
| 200 | } | ||
| 201 | |||
| 202 | static irqreturn_t hil_ptr_interrupt(struct serio *serio, | ||
| 203 | unsigned char data, unsigned int flags) | ||
| 204 | { | ||
| 205 | struct hil_ptr *ptr; | ||
| 206 | hil_packet packet; | ||
| 207 | int idx; | ||
| 208 | |||
| 209 | ptr = serio_get_drvdata(serio); | ||
| 210 | BUG_ON(ptr == NULL); | ||
| 211 | |||
| 212 | if (ptr->idx4 >= (HIL_PTR_MAX_LENGTH * sizeof(hil_packet))) { | ||
| 213 | hil_ptr_process_err(ptr); | ||
| 214 | return IRQ_HANDLED; | ||
| 215 | } | ||
| 216 | idx = ptr->idx4/4; | ||
| 217 | if (!(ptr->idx4 % 4)) | ||
| 218 | ptr->data[idx] = 0; | ||
| 219 | packet = ptr->data[idx]; | ||
| 220 | packet |= ((hil_packet)data) << ((3 - (ptr->idx4 % 4)) * 8); | ||
| 221 | ptr->data[idx] = packet; | ||
| 222 | |||
| 223 | /* Records of N 4-byte hil_packets must terminate with a command. */ | ||
| 224 | if ((++(ptr->idx4)) % 4) | ||
| 225 | return IRQ_HANDLED; | ||
| 226 | if ((packet & 0xffff0000) != HIL_ERR_INT) { | ||
| 227 | hil_ptr_process_err(ptr); | ||
| 228 | return IRQ_HANDLED; | ||
| 229 | } | ||
| 230 | if (packet & HIL_PKT_CMD) | ||
| 231 | hil_ptr_process_record(ptr); | ||
| 232 | |||
| 233 | return IRQ_HANDLED; | ||
| 234 | } | ||
| 235 | |||
| 236 | static void hil_ptr_disconnect(struct serio *serio) | ||
| 237 | { | ||
| 238 | struct hil_ptr *ptr; | ||
| 239 | |||
| 240 | ptr = serio_get_drvdata(serio); | ||
| 241 | BUG_ON(ptr == NULL); | ||
| 242 | |||
| 243 | serio_close(serio); | ||
| 244 | input_unregister_device(ptr->dev); | ||
| 245 | kfree(ptr); | ||
| 246 | } | ||
| 247 | |||
| 248 | static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) | ||
| 249 | { | ||
| 250 | struct hil_ptr *ptr; | ||
| 251 | const char *txt; | ||
| 252 | unsigned int i, naxsets, btntype; | ||
| 253 | uint8_t did, *idd; | ||
| 254 | int error; | ||
| 255 | |||
| 256 | ptr = kzalloc(sizeof(struct hil_ptr), GFP_KERNEL); | ||
| 257 | if (!ptr) | ||
| 258 | return -ENOMEM; | ||
| 259 | |||
| 260 | ptr->dev = input_allocate_device(); | ||
| 261 | if (!ptr->dev) { | ||
| 262 | error = -ENOMEM; | ||
| 263 | goto bail0; | ||
| 264 | } | ||
| 265 | |||
| 266 | error = serio_open(serio, driver); | ||
| 267 | if (error) | ||
| 268 | goto bail1; | ||
| 269 | |||
| 270 | serio_set_drvdata(serio, ptr); | ||
| 271 | ptr->serio = serio; | ||
| 272 | |||
| 273 | init_MUTEX_LOCKED(&ptr->sem); | ||
| 274 | |||
| 275 | /* Get device info. MLC driver supplies devid/status/etc. */ | ||
| 276 | serio->write(serio, 0); | ||
| 277 | serio->write(serio, 0); | ||
| 278 | serio->write(serio, HIL_PKT_CMD >> 8); | ||
| 279 | serio->write(serio, HIL_CMD_IDD); | ||
| 280 | down(&ptr->sem); | ||
| 281 | |||
| 282 | serio->write(serio, 0); | ||
| 283 | serio->write(serio, 0); | ||
| 284 | serio->write(serio, HIL_PKT_CMD >> 8); | ||
| 285 | serio->write(serio, HIL_CMD_RSC); | ||
| 286 | down(&ptr->sem); | ||
| 287 | |||
| 288 | serio->write(serio, 0); | ||
| 289 | serio->write(serio, 0); | ||
| 290 | serio->write(serio, HIL_PKT_CMD >> 8); | ||
| 291 | serio->write(serio, HIL_CMD_RNM); | ||
| 292 | down(&ptr->sem); | ||
| 293 | |||
| 294 | serio->write(serio, 0); | ||
| 295 | serio->write(serio, 0); | ||
| 296 | serio->write(serio, HIL_PKT_CMD >> 8); | ||
| 297 | serio->write(serio, HIL_CMD_EXD); | ||
| 298 | down(&ptr->sem); | ||
| 299 | |||
| 300 | up(&ptr->sem); | ||
| 301 | |||
| 302 | did = ptr->idd[0]; | ||
| 303 | idd = ptr->idd + 1; | ||
| 304 | txt = "unknown"; | ||
| 305 | |||
| 306 | if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) { | ||
| 307 | ptr->dev->evbit[0] = BIT_MASK(EV_REL); | ||
| 308 | txt = "relative"; | ||
| 309 | } | ||
| 310 | |||
| 311 | if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_ABS) { | ||
| 312 | ptr->dev->evbit[0] = BIT_MASK(EV_ABS); | ||
| 313 | txt = "absolute"; | ||
| 314 | } | ||
| 315 | |||
| 316 | if (!ptr->dev->evbit[0]) { | ||
| 317 | error = -ENODEV; | ||
| 318 | goto bail2; | ||
| 319 | } | ||
| 320 | |||
| 321 | ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd); | ||
| 322 | if (ptr->nbtn) | ||
| 323 | ptr->dev->evbit[0] |= BIT_MASK(EV_KEY); | ||
| 324 | |||
| 325 | naxsets = HIL_IDD_NUM_AXSETS(*idd); | ||
| 326 | ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd); | ||
| 327 | |||
| 328 | printk(KERN_INFO PREFIX "HIL pointer device found (did: 0x%02x, axis: %s)\n", | ||
| 329 | did, txt); | ||
| 330 | printk(KERN_INFO PREFIX "HIL pointer has %i buttons and %i sets of %i axes\n", | ||
| 331 | ptr->nbtn, naxsets, ptr->naxes); | ||
| 332 | |||
| 333 | btntype = BTN_MISC; | ||
| 334 | if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET) | ||
| 335 | #ifdef TABLET_SIMULATES_MOUSE | ||
| 336 | btntype = BTN_TOUCH; | ||
| 337 | #else | ||
| 338 | btntype = BTN_DIGI; | ||
| 339 | #endif | ||
| 340 | if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN) | ||
| 341 | btntype = BTN_TOUCH; | ||
| 342 | |||
| 343 | if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE) | ||
| 344 | btntype = BTN_MOUSE; | ||
| 345 | |||
| 346 | for (i = 0; i < ptr->nbtn; i++) { | ||
| 347 | set_bit(btntype | i, ptr->dev->keybit); | ||
| 348 | ptr->btnmap[i] = btntype | i; | ||
| 349 | } | ||
| 350 | |||
| 351 | if (btntype == BTN_MOUSE) { | ||
| 352 | /* Swap buttons 2 and 3 */ | ||
| 353 | ptr->btnmap[1] = BTN_MIDDLE; | ||
| 354 | ptr->btnmap[2] = BTN_RIGHT; | ||
| 355 | } | ||
| 356 | |||
| 357 | if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) { | ||
| 358 | for (i = 0; i < ptr->naxes; i++) | ||
| 359 | set_bit(REL_X + i, ptr->dev->relbit); | ||
| 360 | for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) | ||
| 361 | set_bit(REL_X + i, ptr->dev->relbit); | ||
| 362 | } else { | ||
| 363 | for (i = 0; i < ptr->naxes; i++) { | ||
| 364 | set_bit(ABS_X + i, ptr->dev->absbit); | ||
| 365 | ptr->dev->absmin[ABS_X + i] = 0; | ||
| 366 | ptr->dev->absmax[ABS_X + i] = | ||
| 367 | HIL_IDD_AXIS_MAX((ptr->idd + 1), i); | ||
| 368 | } | ||
| 369 | for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) { | ||
| 370 | set_bit(ABS_X + i, ptr->dev->absbit); | ||
| 371 | ptr->dev->absmin[ABS_X + i] = 0; | ||
| 372 | ptr->dev->absmax[ABS_X + i] = | ||
| 373 | HIL_IDD_AXIS_MAX((ptr->idd + 1), (i - 3)); | ||
| 374 | } | ||
| 375 | #ifdef TABLET_AUTOADJUST | ||
| 376 | for (i = 0; i < ABS_MAX; i++) { | ||
| 377 | int diff = ptr->dev->absmax[ABS_X + i] / 10; | ||
| 378 | ptr->dev->absmin[ABS_X + i] += diff; | ||
| 379 | ptr->dev->absmax[ABS_X + i] -= diff; | ||
| 380 | } | ||
| 381 | #endif | ||
| 382 | } | ||
| 383 | |||
| 384 | ptr->dev->name = strlen(ptr->rnm) ? ptr->rnm : HIL_GENERIC_NAME; | ||
| 385 | |||
| 386 | ptr->dev->id.bustype = BUS_HIL; | ||
| 387 | ptr->dev->id.vendor = PCI_VENDOR_ID_HP; | ||
| 388 | ptr->dev->id.product = 0x0001; /* TODO: get from ptr->rsc */ | ||
| 389 | ptr->dev->id.version = 0x0100; /* TODO: get from ptr->rsc */ | ||
| 390 | ptr->dev->dev.parent = &serio->dev; | ||
| 391 | |||
| 392 | error = input_register_device(ptr->dev); | ||
| 393 | if (error) { | ||
| 394 | printk(KERN_INFO PREFIX "Unable to register input device\n"); | ||
| 395 | goto bail2; | ||
| 396 | } | ||
| 397 | |||
| 398 | printk(KERN_INFO "input: %s (%s), ID: %d\n", | ||
| 399 | ptr->dev->name, | ||
| 400 | (btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad", | ||
| 401 | did); | ||
| 402 | |||
| 403 | return 0; | ||
| 404 | |||
| 405 | bail2: | ||
| 406 | serio_close(serio); | ||
| 407 | bail1: | ||
| 408 | input_free_device(ptr->dev); | ||
| 409 | bail0: | ||
| 410 | kfree(ptr); | ||
| 411 | serio_set_drvdata(serio, NULL); | ||
| 412 | return error; | ||
| 413 | } | ||
| 414 | |||
| 415 | static struct serio_device_id hil_ptr_ids[] = { | ||
| 416 | { | ||
| 417 | .type = SERIO_HIL_MLC, | ||
| 418 | .proto = SERIO_HIL, | ||
| 419 | .id = SERIO_ANY, | ||
| 420 | .extra = SERIO_ANY, | ||
| 421 | }, | ||
| 422 | { 0 } | ||
| 423 | }; | ||
| 424 | |||
| 425 | static struct serio_driver hil_ptr_serio_driver = { | ||
| 426 | .driver = { | ||
| 427 | .name = "hil_ptr", | ||
| 428 | }, | ||
| 429 | .description = "HP HIL mouse/tablet driver", | ||
| 430 | .id_table = hil_ptr_ids, | ||
| 431 | .connect = hil_ptr_connect, | ||
| 432 | .disconnect = hil_ptr_disconnect, | ||
| 433 | .interrupt = hil_ptr_interrupt | ||
| 434 | }; | ||
| 435 | |||
| 436 | static int __init hil_ptr_init(void) | ||
| 437 | { | ||
| 438 | return serio_register_driver(&hil_ptr_serio_driver); | ||
| 439 | } | ||
| 440 | |||
| 441 | static void __exit hil_ptr_exit(void) | ||
| 442 | { | ||
| 443 | serio_unregister_driver(&hil_ptr_serio_driver); | ||
| 444 | } | ||
| 445 | |||
| 446 | module_init(hil_ptr_init); | ||
| 447 | module_exit(hil_ptr_exit); | ||
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index dcd4236af1e3..5e6308694408 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c | |||
| @@ -33,11 +33,11 @@ static int lifebook_set_serio_phys(const struct dmi_system_id *d) | |||
| 33 | return 0; | 33 | return 0; |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | static unsigned char lifebook_use_6byte_proto; | 36 | static bool lifebook_use_6byte_proto; |
| 37 | 37 | ||
| 38 | static int lifebook_set_6byte_proto(const struct dmi_system_id *d) | 38 | static int lifebook_set_6byte_proto(const struct dmi_system_id *d) |
| 39 | { | 39 | { |
| 40 | lifebook_use_6byte_proto = 1; | 40 | lifebook_use_6byte_proto = true; |
| 41 | return 0; | 41 | return 0; |
| 42 | } | 42 | } |
| 43 | 43 | ||
| @@ -125,7 +125,7 @@ static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) | |||
| 125 | struct input_dev *dev1 = psmouse->dev; | 125 | struct input_dev *dev1 = psmouse->dev; |
| 126 | struct input_dev *dev2 = priv ? priv->dev2 : NULL; | 126 | struct input_dev *dev2 = priv ? priv->dev2 : NULL; |
| 127 | unsigned char *packet = psmouse->packet; | 127 | unsigned char *packet = psmouse->packet; |
| 128 | int relative_packet = packet[0] & 0x08; | 128 | bool relative_packet = packet[0] & 0x08; |
| 129 | 129 | ||
| 130 | if (relative_packet || !lifebook_use_6byte_proto) { | 130 | if (relative_packet || !lifebook_use_6byte_proto) { |
| 131 | if (psmouse->pktcnt != 3) | 131 | if (psmouse->pktcnt != 3) |
| @@ -242,7 +242,7 @@ static void lifebook_disconnect(struct psmouse *psmouse) | |||
| 242 | psmouse->private = NULL; | 242 | psmouse->private = NULL; |
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | int lifebook_detect(struct psmouse *psmouse, int set_properties) | 245 | int lifebook_detect(struct psmouse *psmouse, bool set_properties) |
| 246 | { | 246 | { |
| 247 | if (!dmi_check_system(lifebook_dmi_table)) | 247 | if (!dmi_check_system(lifebook_dmi_table)) |
| 248 | return -1; | 248 | return -1; |
diff --git a/drivers/input/mouse/lifebook.h b/drivers/input/mouse/lifebook.h index c1647cf036c2..407cb226bc0a 100644 --- a/drivers/input/mouse/lifebook.h +++ b/drivers/input/mouse/lifebook.h | |||
| @@ -12,10 +12,10 @@ | |||
| 12 | #define _LIFEBOOK_H | 12 | #define _LIFEBOOK_H |
| 13 | 13 | ||
| 14 | #ifdef CONFIG_MOUSE_PS2_LIFEBOOK | 14 | #ifdef CONFIG_MOUSE_PS2_LIFEBOOK |
| 15 | int lifebook_detect(struct psmouse *psmouse, int set_properties); | 15 | int lifebook_detect(struct psmouse *psmouse, bool set_properties); |
| 16 | int lifebook_init(struct psmouse *psmouse); | 16 | int lifebook_init(struct psmouse *psmouse); |
| 17 | #else | 17 | #else |
| 18 | inline int lifebook_detect(struct psmouse *psmouse, int set_properties) | 18 | inline int lifebook_detect(struct psmouse *psmouse, bool set_properties) |
| 19 | { | 19 | { |
| 20 | return -ENOSYS; | 20 | return -ENOSYS; |
| 21 | } | 21 | } |
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 390f1dbb98a4..de745d751162 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c | |||
| @@ -130,14 +130,11 @@ static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned cha | |||
| 130 | * 0 - disabled | 130 | * 0 - disabled |
| 131 | */ | 131 | */ |
| 132 | 132 | ||
| 133 | static void ps2pp_set_smartscroll(struct psmouse *psmouse, unsigned int smartscroll) | 133 | static void ps2pp_set_smartscroll(struct psmouse *psmouse, bool smartscroll) |
| 134 | { | 134 | { |
| 135 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 135 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
| 136 | unsigned char param[4]; | 136 | unsigned char param[4]; |
| 137 | 137 | ||
| 138 | if (smartscroll > 1) | ||
| 139 | smartscroll = 1; | ||
| 140 | |||
| 141 | ps2pp_cmd(psmouse, param, 0x32); | 138 | ps2pp_cmd(psmouse, param, 0x32); |
| 142 | 139 | ||
| 143 | param[0] = 0; | 140 | param[0] = 0; |
| @@ -149,12 +146,14 @@ static void ps2pp_set_smartscroll(struct psmouse *psmouse, unsigned int smartscr | |||
| 149 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); | 146 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); |
| 150 | } | 147 | } |
| 151 | 148 | ||
| 152 | static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse, void *data, char *buf) | 149 | static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse, |
| 150 | void *data, char *buf) | ||
| 153 | { | 151 | { |
| 154 | return sprintf(buf, "%d\n", psmouse->smartscroll ? 1 : 0); | 152 | return sprintf(buf, "%d\n", psmouse->smartscroll); |
| 155 | } | 153 | } |
| 156 | 154 | ||
| 157 | static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data, const char *buf, size_t count) | 155 | static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data, |
| 156 | const char *buf, size_t count) | ||
| 158 | { | 157 | { |
| 159 | unsigned long value; | 158 | unsigned long value; |
| 160 | 159 | ||
| @@ -261,29 +260,29 @@ static const struct ps2pp_info *get_model_info(unsigned char model) | |||
| 261 | 260 | ||
| 262 | static void ps2pp_set_model_properties(struct psmouse *psmouse, | 261 | static void ps2pp_set_model_properties(struct psmouse *psmouse, |
| 263 | const struct ps2pp_info *model_info, | 262 | const struct ps2pp_info *model_info, |
| 264 | int using_ps2pp) | 263 | bool using_ps2pp) |
| 265 | { | 264 | { |
| 266 | struct input_dev *input_dev = psmouse->dev; | 265 | struct input_dev *input_dev = psmouse->dev; |
| 267 | 266 | ||
| 268 | if (model_info->features & PS2PP_SIDE_BTN) | 267 | if (model_info->features & PS2PP_SIDE_BTN) |
| 269 | set_bit(BTN_SIDE, input_dev->keybit); | 268 | __set_bit(BTN_SIDE, input_dev->keybit); |
| 270 | 269 | ||
| 271 | if (model_info->features & PS2PP_EXTRA_BTN) | 270 | if (model_info->features & PS2PP_EXTRA_BTN) |
| 272 | set_bit(BTN_EXTRA, input_dev->keybit); | 271 | __set_bit(BTN_EXTRA, input_dev->keybit); |
| 273 | 272 | ||
| 274 | if (model_info->features & PS2PP_TASK_BTN) | 273 | if (model_info->features & PS2PP_TASK_BTN) |
| 275 | set_bit(BTN_TASK, input_dev->keybit); | 274 | __set_bit(BTN_TASK, input_dev->keybit); |
| 276 | 275 | ||
| 277 | if (model_info->features & PS2PP_NAV_BTN) { | 276 | if (model_info->features & PS2PP_NAV_BTN) { |
| 278 | set_bit(BTN_FORWARD, input_dev->keybit); | 277 | __set_bit(BTN_FORWARD, input_dev->keybit); |
| 279 | set_bit(BTN_BACK, input_dev->keybit); | 278 | __set_bit(BTN_BACK, input_dev->keybit); |
| 280 | } | 279 | } |
| 281 | 280 | ||
| 282 | if (model_info->features & PS2PP_WHEEL) | 281 | if (model_info->features & PS2PP_WHEEL) |
| 283 | set_bit(REL_WHEEL, input_dev->relbit); | 282 | __set_bit(REL_WHEEL, input_dev->relbit); |
| 284 | 283 | ||
| 285 | if (model_info->features & PS2PP_HWHEEL) | 284 | if (model_info->features & PS2PP_HWHEEL) |
| 286 | set_bit(REL_HWHEEL, input_dev->relbit); | 285 | __set_bit(REL_HWHEEL, input_dev->relbit); |
| 287 | 286 | ||
| 288 | switch (model_info->kind) { | 287 | switch (model_info->kind) { |
| 289 | case PS2PP_KIND_WHEEL: | 288 | case PS2PP_KIND_WHEEL: |
| @@ -321,13 +320,13 @@ static void ps2pp_set_model_properties(struct psmouse *psmouse, | |||
| 321 | * that support it. | 320 | * that support it. |
| 322 | */ | 321 | */ |
| 323 | 322 | ||
| 324 | int ps2pp_init(struct psmouse *psmouse, int set_properties) | 323 | int ps2pp_init(struct psmouse *psmouse, bool set_properties) |
| 325 | { | 324 | { |
| 326 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 325 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
| 327 | unsigned char param[4]; | 326 | unsigned char param[4]; |
| 328 | unsigned char model, buttons; | 327 | unsigned char model, buttons; |
| 329 | const struct ps2pp_info *model_info; | 328 | const struct ps2pp_info *model_info; |
| 330 | int use_ps2pp = 0; | 329 | bool use_ps2pp = false; |
| 331 | int error; | 330 | int error; |
| 332 | 331 | ||
| 333 | param[0] = 0; | 332 | param[0] = 0; |
| @@ -364,7 +363,7 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties) | |||
| 364 | param[0] = 0; | 363 | param[0] = 0; |
| 365 | if (!ps2_command(ps2dev, param, 0x13d1) && | 364 | if (!ps2_command(ps2dev, param, 0x13d1) && |
| 366 | param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14) { | 365 | param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14) { |
| 367 | use_ps2pp = 1; | 366 | use_ps2pp = true; |
| 368 | } | 367 | } |
| 369 | 368 | ||
| 370 | } else { | 369 | } else { |
| @@ -376,8 +375,8 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties) | |||
| 376 | if ((param[0] & 0x78) == 0x48 && | 375 | if ((param[0] & 0x78) == 0x48 && |
| 377 | (param[1] & 0xf3) == 0xc2 && | 376 | (param[1] & 0xf3) == 0xc2 && |
| 378 | (param[2] & 0x03) == ((param[1] >> 2) & 3)) { | 377 | (param[2] & 0x03) == ((param[1] >> 2) & 3)) { |
| 379 | ps2pp_set_smartscroll(psmouse, psmouse->smartscroll); | 378 | ps2pp_set_smartscroll(psmouse, false); |
| 380 | use_ps2pp = 1; | 379 | use_ps2pp = true; |
| 381 | } | 380 | } |
| 382 | } | 381 | } |
| 383 | } | 382 | } |
| @@ -406,7 +405,7 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties) | |||
| 406 | } | 405 | } |
| 407 | 406 | ||
| 408 | if (buttons < 3) | 407 | if (buttons < 3) |
| 409 | clear_bit(BTN_MIDDLE, psmouse->dev->keybit); | 408 | __clear_bit(BTN_MIDDLE, psmouse->dev->keybit); |
| 410 | 409 | ||
| 411 | if (model_info) | 410 | if (model_info) |
| 412 | ps2pp_set_model_properties(psmouse, model_info, use_ps2pp); | 411 | ps2pp_set_model_properties(psmouse, model_info, use_ps2pp); |
diff --git a/drivers/input/mouse/logips2pp.h b/drivers/input/mouse/logips2pp.h index 6e5712525fd6..0c186f0282d9 100644 --- a/drivers/input/mouse/logips2pp.h +++ b/drivers/input/mouse/logips2pp.h | |||
| @@ -12,9 +12,9 @@ | |||
| 12 | #define _LOGIPS2PP_H | 12 | #define _LOGIPS2PP_H |
| 13 | 13 | ||
| 14 | #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP | 14 | #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP |
| 15 | int ps2pp_init(struct psmouse *psmouse, int set_properties); | 15 | int ps2pp_init(struct psmouse *psmouse, bool set_properties); |
| 16 | #else | 16 | #else |
| 17 | inline int ps2pp_init(struct psmouse *psmouse, int set_properties) | 17 | inline int ps2pp_init(struct psmouse *psmouse, bool set_properties) |
| 18 | { | 18 | { |
| 19 | return -ENOSYS; | 19 | return -ENOSYS; |
| 20 | } | 20 | } |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index b407b355dceb..690aed905436 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 | ||
| @@ -108,10 +109,10 @@ static struct workqueue_struct *kpsmoused_wq; | |||
| 108 | 109 | ||
| 109 | struct psmouse_protocol { | 110 | struct psmouse_protocol { |
| 110 | enum psmouse_type type; | 111 | enum psmouse_type type; |
| 112 | bool maxproto; | ||
| 111 | const char *name; | 113 | const char *name; |
| 112 | const char *alias; | 114 | const char *alias; |
| 113 | int maxproto; | 115 | int (*detect)(struct psmouse *, bool); |
| 114 | int (*detect)(struct psmouse *, int); | ||
| 115 | int (*init)(struct psmouse *); | 116 | int (*init)(struct psmouse *); |
| 116 | }; | 117 | }; |
| 117 | 118 | ||
| @@ -216,7 +217,7 @@ void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work, | |||
| 216 | static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) | 217 | static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) |
| 217 | { | 218 | { |
| 218 | psmouse->state = new_state; | 219 | psmouse->state = new_state; |
| 219 | psmouse->pktcnt = psmouse->out_of_sync = 0; | 220 | psmouse->pktcnt = psmouse->out_of_sync_cnt = 0; |
| 220 | psmouse->ps2dev.flags = 0; | 221 | psmouse->ps2dev.flags = 0; |
| 221 | psmouse->last = jiffies; | 222 | psmouse->last = jiffies; |
| 222 | } | 223 | } |
| @@ -249,7 +250,7 @@ static int psmouse_handle_byte(struct psmouse *psmouse) | |||
| 249 | if (psmouse->state == PSMOUSE_ACTIVATED) { | 250 | if (psmouse->state == PSMOUSE_ACTIVATED) { |
| 250 | printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", | 251 | printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", |
| 251 | psmouse->name, psmouse->phys, psmouse->pktcnt); | 252 | psmouse->name, psmouse->phys, psmouse->pktcnt); |
| 252 | if (++psmouse->out_of_sync == psmouse->resetafter) { | 253 | if (++psmouse->out_of_sync_cnt == psmouse->resetafter) { |
| 253 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); | 254 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); |
| 254 | printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); | 255 | printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); |
| 255 | serio_reconnect(psmouse->ps2dev.serio); | 256 | serio_reconnect(psmouse->ps2dev.serio); |
| @@ -261,8 +262,8 @@ static int psmouse_handle_byte(struct psmouse *psmouse) | |||
| 261 | 262 | ||
| 262 | case PSMOUSE_FULL_PACKET: | 263 | case PSMOUSE_FULL_PACKET: |
| 263 | psmouse->pktcnt = 0; | 264 | psmouse->pktcnt = 0; |
| 264 | if (psmouse->out_of_sync) { | 265 | if (psmouse->out_of_sync_cnt) { |
| 265 | psmouse->out_of_sync = 0; | 266 | psmouse->out_of_sync_cnt = 0; |
| 266 | printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", | 267 | printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", |
| 267 | psmouse->name, psmouse->phys); | 268 | psmouse->name, psmouse->phys); |
| 268 | } | 269 | } |
| @@ -408,7 +409,7 @@ int psmouse_reset(struct psmouse *psmouse) | |||
| 408 | /* | 409 | /* |
| 409 | * Genius NetMouse magic init. | 410 | * Genius NetMouse magic init. |
| 410 | */ | 411 | */ |
| 411 | static int genius_detect(struct psmouse *psmouse, int set_properties) | 412 | static int genius_detect(struct psmouse *psmouse, bool set_properties) |
| 412 | { | 413 | { |
| 413 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 414 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
| 414 | unsigned char param[4]; | 415 | unsigned char param[4]; |
| @@ -424,9 +425,9 @@ static int genius_detect(struct psmouse *psmouse, int set_properties) | |||
| 424 | return -1; | 425 | return -1; |
| 425 | 426 | ||
| 426 | if (set_properties) { | 427 | if (set_properties) { |
| 427 | set_bit(BTN_EXTRA, psmouse->dev->keybit); | 428 | __set_bit(BTN_EXTRA, psmouse->dev->keybit); |
| 428 | set_bit(BTN_SIDE, psmouse->dev->keybit); | 429 | __set_bit(BTN_SIDE, psmouse->dev->keybit); |
| 429 | set_bit(REL_WHEEL, psmouse->dev->relbit); | 430 | __set_bit(REL_WHEEL, psmouse->dev->relbit); |
| 430 | 431 | ||
| 431 | psmouse->vendor = "Genius"; | 432 | psmouse->vendor = "Genius"; |
| 432 | psmouse->name = "Mouse"; | 433 | psmouse->name = "Mouse"; |
| @@ -439,7 +440,7 @@ static int genius_detect(struct psmouse *psmouse, int set_properties) | |||
| 439 | /* | 440 | /* |
| 440 | * IntelliMouse magic init. | 441 | * IntelliMouse magic init. |
| 441 | */ | 442 | */ |
| 442 | static int intellimouse_detect(struct psmouse *psmouse, int set_properties) | 443 | static int intellimouse_detect(struct psmouse *psmouse, bool set_properties) |
| 443 | { | 444 | { |
| 444 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 445 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
| 445 | unsigned char param[2]; | 446 | unsigned char param[2]; |
| @@ -456,8 +457,8 @@ static int intellimouse_detect(struct psmouse *psmouse, int set_properties) | |||
| 456 | return -1; | 457 | return -1; |
| 457 | 458 | ||
| 458 | if (set_properties) { | 459 | if (set_properties) { |
| 459 | set_bit(BTN_MIDDLE, psmouse->dev->keybit); | 460 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); |
| 460 | set_bit(REL_WHEEL, psmouse->dev->relbit); | 461 | __set_bit(REL_WHEEL, psmouse->dev->relbit); |
| 461 | 462 | ||
| 462 | if (!psmouse->vendor) psmouse->vendor = "Generic"; | 463 | if (!psmouse->vendor) psmouse->vendor = "Generic"; |
| 463 | if (!psmouse->name) psmouse->name = "Wheel Mouse"; | 464 | if (!psmouse->name) psmouse->name = "Wheel Mouse"; |
| @@ -470,7 +471,7 @@ static int intellimouse_detect(struct psmouse *psmouse, int set_properties) | |||
| 470 | /* | 471 | /* |
| 471 | * Try IntelliMouse/Explorer magic init. | 472 | * Try IntelliMouse/Explorer magic init. |
| 472 | */ | 473 | */ |
| 473 | static int im_explorer_detect(struct psmouse *psmouse, int set_properties) | 474 | static int im_explorer_detect(struct psmouse *psmouse, bool set_properties) |
| 474 | { | 475 | { |
| 475 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 476 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
| 476 | unsigned char param[2]; | 477 | unsigned char param[2]; |
| @@ -497,11 +498,11 @@ static int im_explorer_detect(struct psmouse *psmouse, int set_properties) | |||
| 497 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); | 498 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); |
| 498 | 499 | ||
| 499 | if (set_properties) { | 500 | if (set_properties) { |
| 500 | set_bit(BTN_MIDDLE, psmouse->dev->keybit); | 501 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); |
| 501 | set_bit(REL_WHEEL, psmouse->dev->relbit); | 502 | __set_bit(REL_WHEEL, psmouse->dev->relbit); |
| 502 | set_bit(REL_HWHEEL, psmouse->dev->relbit); | 503 | __set_bit(REL_HWHEEL, psmouse->dev->relbit); |
| 503 | set_bit(BTN_SIDE, psmouse->dev->keybit); | 504 | __set_bit(BTN_SIDE, psmouse->dev->keybit); |
| 504 | set_bit(BTN_EXTRA, psmouse->dev->keybit); | 505 | __set_bit(BTN_EXTRA, psmouse->dev->keybit); |
| 505 | 506 | ||
| 506 | if (!psmouse->vendor) psmouse->vendor = "Generic"; | 507 | if (!psmouse->vendor) psmouse->vendor = "Generic"; |
| 507 | if (!psmouse->name) psmouse->name = "Explorer Mouse"; | 508 | if (!psmouse->name) psmouse->name = "Explorer Mouse"; |
| @@ -514,7 +515,7 @@ static int im_explorer_detect(struct psmouse *psmouse, int set_properties) | |||
| 514 | /* | 515 | /* |
| 515 | * Kensington ThinkingMouse / ExpertMouse magic init. | 516 | * Kensington ThinkingMouse / ExpertMouse magic init. |
| 516 | */ | 517 | */ |
| 517 | static int thinking_detect(struct psmouse *psmouse, int set_properties) | 518 | static int thinking_detect(struct psmouse *psmouse, bool set_properties) |
| 518 | { | 519 | { |
| 519 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 520 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
| 520 | unsigned char param[2]; | 521 | unsigned char param[2]; |
| @@ -535,7 +536,7 @@ static int thinking_detect(struct psmouse *psmouse, int set_properties) | |||
| 535 | return -1; | 536 | return -1; |
| 536 | 537 | ||
| 537 | if (set_properties) { | 538 | if (set_properties) { |
| 538 | set_bit(BTN_EXTRA, psmouse->dev->keybit); | 539 | __set_bit(BTN_EXTRA, psmouse->dev->keybit); |
| 539 | 540 | ||
| 540 | psmouse->vendor = "Kensington"; | 541 | psmouse->vendor = "Kensington"; |
| 541 | psmouse->name = "ThinkingMouse"; | 542 | psmouse->name = "ThinkingMouse"; |
| @@ -547,7 +548,7 @@ static int thinking_detect(struct psmouse *psmouse, int set_properties) | |||
| 547 | /* | 548 | /* |
| 548 | * Bare PS/2 protocol "detection". Always succeeds. | 549 | * Bare PS/2 protocol "detection". Always succeeds. |
| 549 | */ | 550 | */ |
| 550 | static int ps2bare_detect(struct psmouse *psmouse, int set_properties) | 551 | static int ps2bare_detect(struct psmouse *psmouse, bool set_properties) |
| 551 | { | 552 | { |
| 552 | if (set_properties) { | 553 | if (set_properties) { |
| 553 | if (!psmouse->vendor) psmouse->vendor = "Generic"; | 554 | if (!psmouse->vendor) psmouse->vendor = "Generic"; |
| @@ -561,12 +562,12 @@ static int ps2bare_detect(struct psmouse *psmouse, int set_properties) | |||
| 561 | * Cortron PS/2 protocol detection. There's no special way to detect it, so it | 562 | * Cortron PS/2 protocol detection. There's no special way to detect it, so it |
| 562 | * must be forced by sysfs protocol writing. | 563 | * must be forced by sysfs protocol writing. |
| 563 | */ | 564 | */ |
| 564 | static int cortron_detect(struct psmouse *psmouse, int set_properties) | 565 | static int cortron_detect(struct psmouse *psmouse, bool set_properties) |
| 565 | { | 566 | { |
| 566 | if (set_properties) { | 567 | if (set_properties) { |
| 567 | psmouse->vendor = "Cortron"; | 568 | psmouse->vendor = "Cortron"; |
| 568 | psmouse->name = "PS/2 Trackball"; | 569 | psmouse->name = "PS/2 Trackball"; |
| 569 | set_bit(BTN_SIDE, psmouse->dev->keybit); | 570 | __set_bit(BTN_SIDE, psmouse->dev->keybit); |
| 570 | } | 571 | } |
| 571 | 572 | ||
| 572 | return 0; | 573 | return 0; |
| @@ -578,9 +579,9 @@ static int cortron_detect(struct psmouse *psmouse, int set_properties) | |||
| 578 | */ | 579 | */ |
| 579 | 580 | ||
| 580 | static int psmouse_extensions(struct psmouse *psmouse, | 581 | static int psmouse_extensions(struct psmouse *psmouse, |
| 581 | unsigned int max_proto, int set_properties) | 582 | unsigned int max_proto, bool set_properties) |
| 582 | { | 583 | { |
| 583 | int synaptics_hardware = 0; | 584 | bool synaptics_hardware = true; |
| 584 | 585 | ||
| 585 | /* | 586 | /* |
| 586 | * We always check for lifebook because it does not disturb mouse | 587 | * We always check for lifebook because it does not disturb mouse |
| @@ -607,7 +608,7 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
| 607 | * can reset it properly after probing for intellimouse. | 608 | * can reset it properly after probing for intellimouse. |
| 608 | */ | 609 | */ |
| 609 | if (max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse, set_properties) == 0) { | 610 | if (max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse, set_properties) == 0) { |
| 610 | synaptics_hardware = 1; | 611 | synaptics_hardware = true; |
| 611 | 612 | ||
| 612 | if (max_proto > PSMOUSE_IMEX) { | 613 | if (max_proto > PSMOUSE_IMEX) { |
| 613 | if (!set_properties || synaptics_init(psmouse) == 0) | 614 | if (!set_properties || synaptics_init(psmouse) == 0) |
| @@ -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; |
| @@ -718,7 +733,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
| 718 | .type = PSMOUSE_PS2, | 733 | .type = PSMOUSE_PS2, |
| 719 | .name = "PS/2", | 734 | .name = "PS/2", |
| 720 | .alias = "bare", | 735 | .alias = "bare", |
| 721 | .maxproto = 1, | 736 | .maxproto = true, |
| 722 | .detect = ps2bare_detect, | 737 | .detect = ps2bare_detect, |
| 723 | }, | 738 | }, |
| 724 | #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP | 739 | #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP |
| @@ -745,14 +760,14 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
| 745 | .type = PSMOUSE_IMPS, | 760 | .type = PSMOUSE_IMPS, |
| 746 | .name = "ImPS/2", | 761 | .name = "ImPS/2", |
| 747 | .alias = "imps", | 762 | .alias = "imps", |
| 748 | .maxproto = 1, | 763 | .maxproto = true, |
| 749 | .detect = intellimouse_detect, | 764 | .detect = intellimouse_detect, |
| 750 | }, | 765 | }, |
| 751 | { | 766 | { |
| 752 | .type = PSMOUSE_IMEX, | 767 | .type = PSMOUSE_IMEX, |
| 753 | .name = "ImExPS/2", | 768 | .name = "ImExPS/2", |
| 754 | .alias = "exps", | 769 | .alias = "exps", |
| 755 | .maxproto = 1, | 770 | .maxproto = true, |
| 756 | .detect = im_explorer_detect, | 771 | .detect = im_explorer_detect, |
| 757 | }, | 772 | }, |
| 758 | #ifdef CONFIG_MOUSE_PS2_SYNAPTICS | 773 | #ifdef CONFIG_MOUSE_PS2_SYNAPTICS |
| @@ -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", |
| @@ -824,7 +848,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
| 824 | .type = PSMOUSE_AUTO, | 848 | .type = PSMOUSE_AUTO, |
| 825 | .name = "auto", | 849 | .name = "auto", |
| 826 | .alias = "any", | 850 | .alias = "any", |
| 827 | .maxproto = 1, | 851 | .maxproto = true, |
| 828 | }, | 852 | }, |
| 829 | }; | 853 | }; |
| 830 | 854 | ||
| @@ -990,7 +1014,7 @@ static void psmouse_resync(struct work_struct *work) | |||
| 990 | container_of(work, struct psmouse, resync_work.work); | 1014 | container_of(work, struct psmouse, resync_work.work); |
| 991 | struct serio *serio = psmouse->ps2dev.serio; | 1015 | struct serio *serio = psmouse->ps2dev.serio; |
| 992 | psmouse_ret_t rc = PSMOUSE_GOOD_DATA; | 1016 | psmouse_ret_t rc = PSMOUSE_GOOD_DATA; |
| 993 | int failed = 0, enabled = 0; | 1017 | bool failed = false, enabled = false; |
| 994 | int i; | 1018 | int i; |
| 995 | 1019 | ||
| 996 | mutex_lock(&psmouse_mutex); | 1020 | mutex_lock(&psmouse_mutex); |
| @@ -1017,9 +1041,9 @@ static void psmouse_resync(struct work_struct *work) | |||
| 1017 | 1041 | ||
| 1018 | if (ps2_sendbyte(&psmouse->ps2dev, PSMOUSE_CMD_DISABLE, 20)) { | 1042 | if (ps2_sendbyte(&psmouse->ps2dev, PSMOUSE_CMD_DISABLE, 20)) { |
| 1019 | if (psmouse->num_resyncs < 3 || psmouse->acks_disable_command) | 1043 | if (psmouse->num_resyncs < 3 || psmouse->acks_disable_command) |
| 1020 | failed = 1; | 1044 | failed = true; |
| 1021 | } else | 1045 | } else |
| 1022 | psmouse->acks_disable_command = 1; | 1046 | psmouse->acks_disable_command = true; |
| 1023 | 1047 | ||
| 1024 | /* | 1048 | /* |
| 1025 | * Poll the mouse. If it was reset the packet will be shorter than | 1049 | * Poll the mouse. If it was reset the packet will be shorter than |
| @@ -1030,7 +1054,7 @@ static void psmouse_resync(struct work_struct *work) | |||
| 1030 | */ | 1054 | */ |
| 1031 | if (!failed) { | 1055 | if (!failed) { |
| 1032 | if (psmouse->poll(psmouse)) | 1056 | if (psmouse->poll(psmouse)) |
| 1033 | failed = 1; | 1057 | failed = true; |
| 1034 | else { | 1058 | else { |
| 1035 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 1059 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
| 1036 | for (i = 0; i < psmouse->pktsize; i++) { | 1060 | for (i = 0; i < psmouse->pktsize; i++) { |
| @@ -1040,7 +1064,7 @@ static void psmouse_resync(struct work_struct *work) | |||
| 1040 | break; | 1064 | break; |
| 1041 | } | 1065 | } |
| 1042 | if (rc != PSMOUSE_FULL_PACKET) | 1066 | if (rc != PSMOUSE_FULL_PACKET) |
| 1043 | failed = 1; | 1067 | failed = true; |
| 1044 | psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | 1068 | psmouse_set_state(psmouse, PSMOUSE_RESYNCING); |
| 1045 | } | 1069 | } |
| 1046 | } | 1070 | } |
| @@ -1051,7 +1075,7 @@ static void psmouse_resync(struct work_struct *work) | |||
| 1051 | */ | 1075 | */ |
| 1052 | for (i = 0; i < 5; i++) { | 1076 | for (i = 0; i < 5; i++) { |
| 1053 | if (!ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { | 1077 | if (!ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { |
| 1054 | enabled = 1; | 1078 | enabled = true; |
| 1055 | break; | 1079 | break; |
| 1056 | } | 1080 | } |
| 1057 | msleep(200); | 1081 | msleep(200); |
| @@ -1060,7 +1084,7 @@ static void psmouse_resync(struct work_struct *work) | |||
| 1060 | if (!enabled) { | 1084 | if (!enabled) { |
| 1061 | printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n", | 1085 | printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n", |
| 1062 | psmouse->ps2dev.serio->phys); | 1086 | psmouse->ps2dev.serio->phys); |
| 1063 | failed = 1; | 1087 | failed = true; |
| 1064 | } | 1088 | } |
| 1065 | 1089 | ||
| 1066 | if (failed) { | 1090 | if (failed) { |
| @@ -1187,7 +1211,8 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, const struct psmouse | |||
| 1187 | psmouse->type = proto->type; | 1211 | psmouse->type = proto->type; |
| 1188 | } | 1212 | } |
| 1189 | else | 1213 | else |
| 1190 | psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); | 1214 | psmouse->type = psmouse_extensions(psmouse, |
| 1215 | psmouse_max_proto, true); | ||
| 1191 | 1216 | ||
| 1192 | /* | 1217 | /* |
| 1193 | * If mouse's packet size is 3 there is no point in polling the | 1218 | * If mouse's packet size is 3 there is no point in polling the |
| @@ -1342,8 +1367,10 @@ static int psmouse_reconnect(struct serio *serio) | |||
| 1342 | if (psmouse->reconnect(psmouse)) | 1367 | if (psmouse->reconnect(psmouse)) |
| 1343 | goto out; | 1368 | goto out; |
| 1344 | } else if (psmouse_probe(psmouse) < 0 || | 1369 | } else if (psmouse_probe(psmouse) < 0 || |
| 1345 | psmouse->type != psmouse_extensions(psmouse, psmouse_max_proto, 0)) | 1370 | psmouse->type != psmouse_extensions(psmouse, |
| 1371 | psmouse_max_proto, false)) { | ||
| 1346 | goto out; | 1372 | goto out; |
| 1373 | } | ||
| 1347 | 1374 | ||
| 1348 | /* ok, the device type (and capabilities) match the old one, | 1375 | /* ok, the device type (and capabilities) match the old one, |
| 1349 | * we can continue using it, complete intialization | 1376 | * we can continue using it, complete intialization |
| @@ -1528,7 +1555,9 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co | |||
| 1528 | 1555 | ||
| 1529 | while (serio->child) { | 1556 | while (serio->child) { |
| 1530 | if (++retry > 3) { | 1557 | if (++retry > 3) { |
| 1531 | printk(KERN_WARNING "psmouse: failed to destroy child port, protocol change aborted.\n"); | 1558 | printk(KERN_WARNING |
| 1559 | "psmouse: failed to destroy child port, " | ||
| 1560 | "protocol change aborted.\n"); | ||
| 1532 | input_free_device(new_dev); | 1561 | input_free_device(new_dev); |
| 1533 | return -EIO; | 1562 | return -EIO; |
| 1534 | } | 1563 | } |
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 54ed267894bd..e053bdd137ff 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
| @@ -47,10 +47,10 @@ struct psmouse { | |||
| 47 | unsigned char pktcnt; | 47 | unsigned char pktcnt; |
| 48 | unsigned char pktsize; | 48 | unsigned char pktsize; |
| 49 | unsigned char type; | 49 | unsigned char type; |
| 50 | unsigned char acks_disable_command; | 50 | bool acks_disable_command; |
| 51 | unsigned int model; | 51 | unsigned int model; |
| 52 | unsigned long last; | 52 | unsigned long last; |
| 53 | unsigned long out_of_sync; | 53 | unsigned long out_of_sync_cnt; |
| 54 | unsigned long num_resyncs; | 54 | unsigned long num_resyncs; |
| 55 | enum psmouse_state state; | 55 | enum psmouse_state state; |
| 56 | char devname[64]; | 56 | char devname[64]; |
| @@ -60,7 +60,7 @@ struct psmouse { | |||
| 60 | unsigned int resolution; | 60 | unsigned int resolution; |
| 61 | unsigned int resetafter; | 61 | unsigned int resetafter; |
| 62 | unsigned int resync_time; | 62 | unsigned int resync_time; |
| 63 | unsigned int smartscroll; /* Logitech only */ | 63 | bool smartscroll; /* Logitech only */ |
| 64 | 64 | ||
| 65 | psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse); | 65 | psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse); |
| 66 | void (*set_rate)(struct psmouse *psmouse, unsigned int rate); | 66 | void (*set_rate)(struct psmouse *psmouse, unsigned int rate); |
| @@ -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 | ||
| @@ -107,7 +108,7 @@ struct psmouse_attribute { | |||
| 107 | ssize_t (*show)(struct psmouse *psmouse, void *data, char *buf); | 108 | ssize_t (*show)(struct psmouse *psmouse, void *data, char *buf); |
| 108 | ssize_t (*set)(struct psmouse *psmouse, void *data, | 109 | ssize_t (*set)(struct psmouse *psmouse, void *data, |
| 109 | const char *buf, size_t count); | 110 | const char *buf, size_t count); |
| 110 | int protect; | 111 | bool protect; |
| 111 | }; | 112 | }; |
| 112 | #define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr) | 113 | #define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr) |
| 113 | 114 | ||
| @@ -116,9 +117,7 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *at | |||
| 116 | ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr, | 117 | ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr, |
| 117 | const char *buf, size_t count); | 118 | const char *buf, size_t count); |
| 118 | 119 | ||
| 119 | #define __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, _protect) \ | 120 | #define __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, _show, _set, _protect) \ |
| 120 | static ssize_t _show(struct psmouse *, void *data, char *); \ | ||
| 121 | static ssize_t _set(struct psmouse *, void *data, const char *, size_t); \ | ||
| 122 | static struct psmouse_attribute psmouse_attr_##_name = { \ | 121 | static struct psmouse_attribute psmouse_attr_##_name = { \ |
| 123 | .dattr = { \ | 122 | .dattr = { \ |
| 124 | .attr = { \ | 123 | .attr = { \ |
| @@ -134,7 +133,20 @@ static struct psmouse_attribute psmouse_attr_##_name = { \ | |||
| 134 | .protect = _protect, \ | 133 | .protect = _protect, \ |
| 135 | } | 134 | } |
| 136 | 135 | ||
| 137 | #define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \ | 136 | #define __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, _protect) \ |
| 138 | __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, 1) | 137 | static ssize_t _show(struct psmouse *, void *, char *); \ |
| 138 | static ssize_t _set(struct psmouse *, void *, const char *, size_t); \ | ||
| 139 | __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, _show, _set, _protect) | ||
| 140 | |||
| 141 | #define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \ | ||
| 142 | __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, true) | ||
| 143 | |||
| 144 | #define PSMOUSE_DEFINE_RO_ATTR(_name, _mode, _data, _show) \ | ||
| 145 | static ssize_t _show(struct psmouse *, void *, char *); \ | ||
| 146 | __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, _show, NULL, true) | ||
| 147 | |||
| 148 | #define PSMOUSE_DEFINE_WO_ATTR(_name, _mode, _data, _set) \ | ||
| 149 | static ssize_t _set(struct psmouse *, void *, const char *, size_t); \ | ||
| 150 | __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, NULL, _set, true) | ||
| 139 | 151 | ||
| 140 | #endif /* _PSMOUSE_H */ | 152 | #endif /* _PSMOUSE_H */ |
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c new file mode 100644 index 000000000000..84e2fc04d11b --- /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. */ | ||
| 40 | static 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 | */ | ||
| 46 | static 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 | */ | ||
| 65 | static 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 | |||
| 80 | static 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 | |||
| 137 | static 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 */ | ||
| 189 | static 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 | |||
| 209 | static 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 | |||
| 247 | static 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 | |||
| 284 | static 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 | |||
| 292 | static 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 | |||
| 300 | static 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 */ | ||
| 318 | static 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 | |||
| 349 | static 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 | |||
| 370 | static 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 | */ | ||
| 406 | static 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 | |||
| 430 | PSMOUSE_DEFINE_WO_ATTR(setreg, S_IWUSR, NULL, fsp_attr_set_setreg); | ||
| 431 | |||
| 432 | static 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 | */ | ||
| 445 | static 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 > 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 | |||
| 464 | PSMOUSE_DEFINE_ATTR(getreg, S_IWUSR | S_IRUGO, NULL, | ||
| 465 | fsp_attr_show_getreg, fsp_attr_set_getreg); | ||
| 466 | |||
| 467 | static 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 | |||
| 478 | static 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 | |||
| 492 | PSMOUSE_DEFINE_ATTR(page, S_IWUSR | S_IRUGO, NULL, | ||
| 493 | fsp_attr_show_pagereg, fsp_attr_set_pagereg); | ||
| 494 | |||
| 495 | static 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 | |||
| 503 | static 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 | |||
| 516 | PSMOUSE_DEFINE_ATTR(vscroll, S_IWUSR | S_IRUGO, NULL, | ||
| 517 | fsp_attr_show_vscroll, fsp_attr_set_vscroll); | ||
| 518 | |||
| 519 | static 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 | |||
| 527 | static 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 | |||
| 540 | PSMOUSE_DEFINE_ATTR(hscroll, S_IWUSR | S_IRUGO, NULL, | ||
| 541 | fsp_attr_show_hscroll, fsp_attr_set_hscroll); | ||
| 542 | |||
| 543 | static 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 | |||
| 552 | static 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 | |||
| 573 | PSMOUSE_DEFINE_ATTR(flags, S_IWUSR | S_IRUGO, NULL, | ||
| 574 | fsp_attr_show_flags, fsp_attr_set_flags); | ||
| 575 | |||
| 576 | static 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 | |||
| 582 | PSMOUSE_DEFINE_RO_ATTR(ver, S_IRUGO, NULL, fsp_attr_show_ver); | ||
| 583 | |||
| 584 | static 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 | |||
| 595 | static struct attribute_group fsp_attribute_group = { | ||
| 596 | .attrs = fsp_attributes, | ||
| 597 | }; | ||
| 598 | |||
| 599 | #ifdef FSP_DEBUG | ||
| 600 | static 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 | ||
| 618 | static void fsp_packet_debug(unsigned char packet[]) | ||
| 619 | { | ||
| 620 | } | ||
| 621 | #endif | ||
| 622 | |||
| 623 | static 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 | |||
| 699 | static 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 | |||
| 759 | int fsp_detect(struct psmouse *psmouse, bool 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 | |||
| 777 | static 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 | |||
| 784 | static 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 | |||
| 793 | static 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 | |||
| 809 | int 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..ed1395ac7b8b --- /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 | |||
| 68 | struct 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 | ||
| 83 | extern int fsp_detect(struct psmouse *psmouse, bool set_properties); | ||
| 84 | extern int fsp_init(struct psmouse *psmouse); | ||
| 85 | #else | ||
| 86 | inline int fsp_detect(struct psmouse *psmouse, bool set_properties) | ||
| 87 | { | ||
| 88 | return -ENOSYS; | ||
| 89 | } | ||
| 90 | inline 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/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 19984bf06cad..b66ff1ac7dea 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
| @@ -60,7 +60,7 @@ static int synaptics_mode_cmd(struct psmouse *psmouse, unsigned char mode) | |||
| 60 | return 0; | 60 | return 0; |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | int synaptics_detect(struct psmouse *psmouse, int set_properties) | 63 | int synaptics_detect(struct psmouse *psmouse, bool set_properties) |
| 64 | { | 64 | { |
| 65 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 65 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
| 66 | unsigned char param[4]; | 66 | unsigned char param[4]; |
| @@ -556,38 +556,38 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
| 556 | { | 556 | { |
| 557 | int i; | 557 | int i; |
| 558 | 558 | ||
| 559 | set_bit(EV_ABS, dev->evbit); | 559 | __set_bit(EV_ABS, dev->evbit); |
| 560 | input_set_abs_params(dev, ABS_X, XMIN_NOMINAL, XMAX_NOMINAL, 0, 0); | 560 | input_set_abs_params(dev, ABS_X, XMIN_NOMINAL, XMAX_NOMINAL, 0, 0); |
| 561 | input_set_abs_params(dev, ABS_Y, YMIN_NOMINAL, YMAX_NOMINAL, 0, 0); | 561 | input_set_abs_params(dev, ABS_Y, YMIN_NOMINAL, YMAX_NOMINAL, 0, 0); |
| 562 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); | 562 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); |
| 563 | set_bit(ABS_TOOL_WIDTH, dev->absbit); | 563 | __set_bit(ABS_TOOL_WIDTH, dev->absbit); |
| 564 | 564 | ||
| 565 | set_bit(EV_KEY, dev->evbit); | 565 | __set_bit(EV_KEY, dev->evbit); |
| 566 | set_bit(BTN_TOUCH, dev->keybit); | 566 | __set_bit(BTN_TOUCH, dev->keybit); |
| 567 | set_bit(BTN_TOOL_FINGER, dev->keybit); | 567 | __set_bit(BTN_TOOL_FINGER, dev->keybit); |
| 568 | set_bit(BTN_LEFT, dev->keybit); | 568 | __set_bit(BTN_LEFT, dev->keybit); |
| 569 | set_bit(BTN_RIGHT, dev->keybit); | 569 | __set_bit(BTN_RIGHT, dev->keybit); |
| 570 | 570 | ||
| 571 | if (SYN_CAP_MULTIFINGER(priv->capabilities)) { | 571 | if (SYN_CAP_MULTIFINGER(priv->capabilities)) { |
| 572 | set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); | 572 | __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); |
| 573 | set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); | 573 | __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); |
| 574 | } | 574 | } |
| 575 | 575 | ||
| 576 | if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) | 576 | if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) |
| 577 | set_bit(BTN_MIDDLE, dev->keybit); | 577 | __set_bit(BTN_MIDDLE, dev->keybit); |
| 578 | 578 | ||
| 579 | if (SYN_CAP_FOUR_BUTTON(priv->capabilities) || | 579 | if (SYN_CAP_FOUR_BUTTON(priv->capabilities) || |
| 580 | SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { | 580 | SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { |
| 581 | set_bit(BTN_FORWARD, dev->keybit); | 581 | __set_bit(BTN_FORWARD, dev->keybit); |
| 582 | set_bit(BTN_BACK, dev->keybit); | 582 | __set_bit(BTN_BACK, dev->keybit); |
| 583 | } | 583 | } |
| 584 | 584 | ||
| 585 | for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) | 585 | for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) |
| 586 | set_bit(BTN_0 + i, dev->keybit); | 586 | __set_bit(BTN_0 + i, dev->keybit); |
| 587 | 587 | ||
| 588 | clear_bit(EV_REL, dev->evbit); | 588 | __clear_bit(EV_REL, dev->evbit); |
| 589 | clear_bit(REL_X, dev->relbit); | 589 | __clear_bit(REL_X, dev->relbit); |
| 590 | clear_bit(REL_Y, dev->relbit); | 590 | __clear_bit(REL_Y, dev->relbit); |
| 591 | 591 | ||
| 592 | dev->absres[ABS_X] = priv->x_res; | 592 | dev->absres[ABS_X] = priv->x_res; |
| 593 | dev->absres[ABS_Y] = priv->y_res; | 593 | dev->absres[ABS_Y] = priv->y_res; |
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index 302382151752..871f6fe377f9 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h | |||
| @@ -105,7 +105,7 @@ struct synaptics_data { | |||
| 105 | int scroll; | 105 | int scroll; |
| 106 | }; | 106 | }; |
| 107 | 107 | ||
| 108 | int synaptics_detect(struct psmouse *psmouse, int set_properties); | 108 | int synaptics_detect(struct psmouse *psmouse, bool set_properties); |
| 109 | int synaptics_init(struct psmouse *psmouse); | 109 | int synaptics_init(struct psmouse *psmouse); |
| 110 | void synaptics_reset(struct psmouse *psmouse); | 110 | void synaptics_reset(struct psmouse *psmouse); |
| 111 | 111 | ||
diff --git a/drivers/input/mouse/touchkit_ps2.c b/drivers/input/mouse/touchkit_ps2.c index 3fadb2accac0..0308a0faa94d 100644 --- a/drivers/input/mouse/touchkit_ps2.c +++ b/drivers/input/mouse/touchkit_ps2.c | |||
| @@ -67,7 +67,7 @@ static psmouse_ret_t touchkit_ps2_process_byte(struct psmouse *psmouse) | |||
| 67 | return PSMOUSE_FULL_PACKET; | 67 | return PSMOUSE_FULL_PACKET; |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties) | 70 | int touchkit_ps2_detect(struct psmouse *psmouse, bool set_properties) |
| 71 | { | 71 | { |
| 72 | struct input_dev *dev = psmouse->dev; | 72 | struct input_dev *dev = psmouse->dev; |
| 73 | unsigned char param[3]; | 73 | unsigned char param[3]; |
| @@ -86,7 +86,7 @@ int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties) | |||
| 86 | 86 | ||
| 87 | if (set_properties) { | 87 | if (set_properties) { |
| 88 | dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 88 | dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
| 89 | set_bit(BTN_TOUCH, dev->keybit); | 89 | __set_bit(BTN_TOUCH, dev->keybit); |
| 90 | input_set_abs_params(dev, ABS_X, 0, TOUCHKIT_MAX_XC, 0, 0); | 90 | input_set_abs_params(dev, ABS_X, 0, TOUCHKIT_MAX_XC, 0, 0); |
| 91 | input_set_abs_params(dev, ABS_Y, 0, TOUCHKIT_MAX_YC, 0, 0); | 91 | input_set_abs_params(dev, ABS_Y, 0, TOUCHKIT_MAX_YC, 0, 0); |
| 92 | 92 | ||
diff --git a/drivers/input/mouse/touchkit_ps2.h b/drivers/input/mouse/touchkit_ps2.h index 8a0dd3574aef..2efe9ea29d0c 100644 --- a/drivers/input/mouse/touchkit_ps2.h +++ b/drivers/input/mouse/touchkit_ps2.h | |||
| @@ -13,10 +13,10 @@ | |||
| 13 | #define _TOUCHKIT_PS2_H | 13 | #define _TOUCHKIT_PS2_H |
| 14 | 14 | ||
| 15 | #ifdef CONFIG_MOUSE_PS2_TOUCHKIT | 15 | #ifdef CONFIG_MOUSE_PS2_TOUCHKIT |
| 16 | int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties); | 16 | int touchkit_ps2_detect(struct psmouse *psmouse, bool set_properties); |
| 17 | #else | 17 | #else |
| 18 | static inline int touchkit_ps2_detect(struct psmouse *psmouse, | 18 | static inline int touchkit_ps2_detect(struct psmouse *psmouse, |
| 19 | int set_properties) | 19 | bool set_properties) |
| 20 | { | 20 | { |
| 21 | return -ENOSYS; | 21 | return -ENOSYS; |
| 22 | } | 22 | } |
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index e68c814c4361..e354362f2971 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c | |||
| @@ -282,7 +282,7 @@ static int trackpoint_reconnect(struct psmouse *psmouse) | |||
| 282 | return 0; | 282 | return 0; |
| 283 | } | 283 | } |
| 284 | 284 | ||
| 285 | int trackpoint_detect(struct psmouse *psmouse, int set_properties) | 285 | int trackpoint_detect(struct psmouse *psmouse, bool set_properties) |
| 286 | { | 286 | { |
| 287 | struct trackpoint_data *priv; | 287 | struct trackpoint_data *priv; |
| 288 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 288 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h index c10a6e7d0101..e558a7096618 100644 --- a/drivers/input/mouse/trackpoint.h +++ b/drivers/input/mouse/trackpoint.h | |||
| @@ -143,9 +143,9 @@ struct trackpoint_data | |||
| 143 | }; | 143 | }; |
| 144 | 144 | ||
| 145 | #ifdef CONFIG_MOUSE_PS2_TRACKPOINT | 145 | #ifdef CONFIG_MOUSE_PS2_TRACKPOINT |
| 146 | int trackpoint_detect(struct psmouse *psmouse, int set_properties); | 146 | int trackpoint_detect(struct psmouse *psmouse, bool set_properties); |
| 147 | #else | 147 | #else |
| 148 | inline int trackpoint_detect(struct psmouse *psmouse, int set_properties) | 148 | inline int trackpoint_detect(struct psmouse *psmouse, bool set_properties) |
| 149 | { | 149 | { |
| 150 | return -ENOSYS; | 150 | return -ENOSYS; |
| 151 | } | 151 | } |
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c index 404eedd5ffa2..70111443678e 100644 --- a/drivers/input/mouse/vsxxxaa.c +++ b/drivers/input/mouse/vsxxxaa.c | |||
| @@ -384,11 +384,11 @@ vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse) | |||
| 384 | printk (KERN_NOTICE "%s on %s: Forceing standard packet format, " | 384 | printk (KERN_NOTICE "%s on %s: Forceing standard packet format, " |
| 385 | "incremental streaming mode and 72 samples/sec\n", | 385 | "incremental streaming mode and 72 samples/sec\n", |
| 386 | mouse->name, mouse->phys); | 386 | mouse->name, mouse->phys); |
| 387 | mouse->serio->write (mouse->serio, 'S'); /* Standard format */ | 387 | serio_write (mouse->serio, 'S'); /* Standard format */ |
| 388 | mdelay (50); | 388 | mdelay (50); |
| 389 | mouse->serio->write (mouse->serio, 'R'); /* Incremental */ | 389 | serio_write (mouse->serio, 'R'); /* Incremental */ |
| 390 | mdelay (50); | 390 | mdelay (50); |
| 391 | mouse->serio->write (mouse->serio, 'L'); /* 72 samples/sec */ | 391 | serio_write (mouse->serio, 'L'); /* 72 samples/sec */ |
| 392 | } | 392 | } |
| 393 | 393 | ||
| 394 | static void | 394 | static void |
| @@ -532,7 +532,7 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv) | |||
| 532 | * Request selftest. Standard packet format and differential | 532 | * Request selftest. Standard packet format and differential |
| 533 | * mode will be requested after the device ID'ed successfully. | 533 | * mode will be requested after the device ID'ed successfully. |
| 534 | */ | 534 | */ |
| 535 | serio->write (serio, 'T'); /* Test */ | 535 | serio_write (serio, 'T'); /* Test */ |
| 536 | 536 | ||
| 537 | err = input_register_device (input_dev); | 537 | err = input_register_device (input_dev); |
| 538 | if (err) | 538 | if (err) |
diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c index 41fda8c67b1e..a6fb7a3dcc46 100644 --- a/drivers/input/serio/at32psif.c +++ b/drivers/input/serio/at32psif.c | |||
| @@ -231,7 +231,7 @@ static int __init psif_probe(struct platform_device *pdev) | |||
| 231 | goto out_free_io; | 231 | goto out_free_io; |
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | psif->regs = ioremap(regs->start, regs->end - regs->start + 1); | 234 | psif->regs = ioremap(regs->start, resource_size(regs)); |
| 235 | if (!psif->regs) { | 235 | if (!psif->regs) { |
| 236 | ret = -ENOMEM; | 236 | ret = -ENOMEM; |
| 237 | dev_dbg(&pdev->dev, "could not map I/O memory\n"); | 237 | dev_dbg(&pdev->dev, "could not map I/O memory\n"); |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index ccbf23ece8e3..a39bc4eb902b 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
| @@ -457,6 +457,34 @@ static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = { | |||
| 457 | }, | 457 | }, |
| 458 | { } | 458 | { } |
| 459 | }; | 459 | }; |
| 460 | |||
| 461 | static struct dmi_system_id __initdata i8042_dmi_laptop_table[] = { | ||
| 462 | { | ||
| 463 | .ident = "Portable", | ||
| 464 | .matches = { | ||
| 465 | DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ | ||
| 466 | }, | ||
| 467 | }, | ||
| 468 | { | ||
| 469 | .ident = "Laptop", | ||
| 470 | .matches = { | ||
| 471 | DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /* Laptop */ | ||
| 472 | }, | ||
| 473 | }, | ||
| 474 | { | ||
| 475 | .ident = "Notebook", | ||
| 476 | .matches = { | ||
| 477 | DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */ | ||
| 478 | }, | ||
| 479 | }, | ||
| 480 | { | ||
| 481 | .ident = "Sub-Notebook", | ||
| 482 | .matches = { | ||
| 483 | DMI_MATCH(DMI_CHASSIS_TYPE, "14"), /* Sub-Notebook */ | ||
| 484 | }, | ||
| 485 | }, | ||
| 486 | { } | ||
| 487 | }; | ||
| 460 | #endif | 488 | #endif |
| 461 | 489 | ||
| 462 | /* | 490 | /* |
| @@ -530,9 +558,9 @@ static struct dmi_system_id __initdata i8042_dmi_dritek_table[] = { | |||
| 530 | #ifdef CONFIG_PNP | 558 | #ifdef CONFIG_PNP |
| 531 | #include <linux/pnp.h> | 559 | #include <linux/pnp.h> |
| 532 | 560 | ||
| 533 | static int i8042_pnp_kbd_registered; | 561 | static bool i8042_pnp_kbd_registered; |
| 534 | static unsigned int i8042_pnp_kbd_devices; | 562 | static unsigned int i8042_pnp_kbd_devices; |
| 535 | static int i8042_pnp_aux_registered; | 563 | static bool i8042_pnp_aux_registered; |
| 536 | static unsigned int i8042_pnp_aux_devices; | 564 | static unsigned int i8042_pnp_aux_devices; |
| 537 | 565 | ||
| 538 | static int i8042_pnp_command_reg; | 566 | static int i8042_pnp_command_reg; |
| @@ -620,12 +648,12 @@ static struct pnp_driver i8042_pnp_aux_driver = { | |||
| 620 | static void i8042_pnp_exit(void) | 648 | static void i8042_pnp_exit(void) |
| 621 | { | 649 | { |
| 622 | if (i8042_pnp_kbd_registered) { | 650 | if (i8042_pnp_kbd_registered) { |
| 623 | i8042_pnp_kbd_registered = 0; | 651 | i8042_pnp_kbd_registered = false; |
| 624 | pnp_unregister_driver(&i8042_pnp_kbd_driver); | 652 | pnp_unregister_driver(&i8042_pnp_kbd_driver); |
| 625 | } | 653 | } |
| 626 | 654 | ||
| 627 | if (i8042_pnp_aux_registered) { | 655 | if (i8042_pnp_aux_registered) { |
| 628 | i8042_pnp_aux_registered = 0; | 656 | i8042_pnp_aux_registered = false; |
| 629 | pnp_unregister_driver(&i8042_pnp_aux_driver); | 657 | pnp_unregister_driver(&i8042_pnp_aux_driver); |
| 630 | } | 658 | } |
| 631 | } | 659 | } |
| @@ -633,12 +661,12 @@ static void i8042_pnp_exit(void) | |||
| 633 | static int __init i8042_pnp_init(void) | 661 | static int __init i8042_pnp_init(void) |
| 634 | { | 662 | { |
| 635 | char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 }; | 663 | char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 }; |
| 636 | int pnp_data_busted = 0; | 664 | int pnp_data_busted = false; |
| 637 | int err; | 665 | int err; |
| 638 | 666 | ||
| 639 | #ifdef CONFIG_X86 | 667 | #ifdef CONFIG_X86 |
| 640 | if (dmi_check_system(i8042_dmi_nopnp_table)) | 668 | if (dmi_check_system(i8042_dmi_nopnp_table)) |
| 641 | i8042_nopnp = 1; | 669 | i8042_nopnp = true; |
| 642 | #endif | 670 | #endif |
| 643 | 671 | ||
| 644 | if (i8042_nopnp) { | 672 | if (i8042_nopnp) { |
| @@ -648,11 +676,11 @@ static int __init i8042_pnp_init(void) | |||
| 648 | 676 | ||
| 649 | err = pnp_register_driver(&i8042_pnp_kbd_driver); | 677 | err = pnp_register_driver(&i8042_pnp_kbd_driver); |
| 650 | if (!err) | 678 | if (!err) |
| 651 | i8042_pnp_kbd_registered = 1; | 679 | i8042_pnp_kbd_registered = true; |
| 652 | 680 | ||
| 653 | err = pnp_register_driver(&i8042_pnp_aux_driver); | 681 | err = pnp_register_driver(&i8042_pnp_aux_driver); |
| 654 | if (!err) | 682 | if (!err) |
| 655 | i8042_pnp_aux_registered = 1; | 683 | i8042_pnp_aux_registered = true; |
| 656 | 684 | ||
| 657 | if (!i8042_pnp_kbd_devices && !i8042_pnp_aux_devices) { | 685 | if (!i8042_pnp_kbd_devices && !i8042_pnp_aux_devices) { |
| 658 | i8042_pnp_exit(); | 686 | i8042_pnp_exit(); |
| @@ -680,9 +708,9 @@ static int __init i8042_pnp_init(void) | |||
| 680 | 708 | ||
| 681 | #if defined(__ia64__) | 709 | #if defined(__ia64__) |
| 682 | if (!i8042_pnp_kbd_devices) | 710 | if (!i8042_pnp_kbd_devices) |
| 683 | i8042_nokbd = 1; | 711 | i8042_nokbd = true; |
| 684 | if (!i8042_pnp_aux_devices) | 712 | if (!i8042_pnp_aux_devices) |
| 685 | i8042_noaux = 1; | 713 | i8042_noaux = true; |
| 686 | #endif | 714 | #endif |
| 687 | 715 | ||
| 688 | if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) && | 716 | if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) && |
| @@ -693,7 +721,7 @@ static int __init i8042_pnp_init(void) | |||
| 693 | "using default %#x\n", | 721 | "using default %#x\n", |
| 694 | i8042_pnp_data_reg, i8042_data_reg); | 722 | i8042_pnp_data_reg, i8042_data_reg); |
| 695 | i8042_pnp_data_reg = i8042_data_reg; | 723 | i8042_pnp_data_reg = i8042_data_reg; |
| 696 | pnp_data_busted = 1; | 724 | pnp_data_busted = true; |
| 697 | } | 725 | } |
| 698 | 726 | ||
| 699 | if (((i8042_pnp_command_reg & ~0xf) == (i8042_command_reg & ~0xf) && | 727 | if (((i8042_pnp_command_reg & ~0xf) == (i8042_command_reg & ~0xf) && |
| @@ -704,7 +732,7 @@ static int __init i8042_pnp_init(void) | |||
| 704 | "using default %#x\n", | 732 | "using default %#x\n", |
| 705 | i8042_pnp_command_reg, i8042_command_reg); | 733 | i8042_pnp_command_reg, i8042_command_reg); |
| 706 | i8042_pnp_command_reg = i8042_command_reg; | 734 | i8042_pnp_command_reg = i8042_command_reg; |
| 707 | pnp_data_busted = 1; | 735 | pnp_data_busted = true; |
| 708 | } | 736 | } |
| 709 | 737 | ||
| 710 | if (!i8042_nokbd && !i8042_pnp_kbd_irq) { | 738 | if (!i8042_nokbd && !i8042_pnp_kbd_irq) { |
| @@ -712,7 +740,7 @@ static int __init i8042_pnp_init(void) | |||
| 712 | "PNP: PS/2 controller doesn't have KBD irq; " | 740 | "PNP: PS/2 controller doesn't have KBD irq; " |
| 713 | "using default %d\n", i8042_kbd_irq); | 741 | "using default %d\n", i8042_kbd_irq); |
| 714 | i8042_pnp_kbd_irq = i8042_kbd_irq; | 742 | i8042_pnp_kbd_irq = i8042_kbd_irq; |
| 715 | pnp_data_busted = 1; | 743 | pnp_data_busted = true; |
| 716 | } | 744 | } |
| 717 | 745 | ||
| 718 | if (!i8042_noaux && !i8042_pnp_aux_irq) { | 746 | if (!i8042_noaux && !i8042_pnp_aux_irq) { |
| @@ -721,7 +749,7 @@ static int __init i8042_pnp_init(void) | |||
| 721 | "PNP: PS/2 appears to have AUX port disabled, " | 749 | "PNP: PS/2 appears to have AUX port disabled, " |
| 722 | "if this is incorrect please boot with " | 750 | "if this is incorrect please boot with " |
| 723 | "i8042.nopnp\n"); | 751 | "i8042.nopnp\n"); |
| 724 | i8042_noaux = 1; | 752 | i8042_noaux = true; |
| 725 | } else { | 753 | } else { |
| 726 | printk(KERN_WARNING | 754 | printk(KERN_WARNING |
| 727 | "PNP: PS/2 controller doesn't have AUX irq; " | 755 | "PNP: PS/2 controller doesn't have AUX irq; " |
| @@ -735,6 +763,11 @@ static int __init i8042_pnp_init(void) | |||
| 735 | i8042_kbd_irq = i8042_pnp_kbd_irq; | 763 | i8042_kbd_irq = i8042_pnp_kbd_irq; |
| 736 | i8042_aux_irq = i8042_pnp_aux_irq; | 764 | i8042_aux_irq = i8042_pnp_aux_irq; |
| 737 | 765 | ||
| 766 | #ifdef CONFIG_X86 | ||
| 767 | i8042_bypass_aux_irq_test = !pnp_data_busted && | ||
| 768 | dmi_check_system(i8042_dmi_laptop_table); | ||
| 769 | #endif | ||
| 770 | |||
| 738 | return 0; | 771 | return 0; |
| 739 | } | 772 | } |
| 740 | 773 | ||
| @@ -763,21 +796,21 @@ static int __init i8042_platform_init(void) | |||
| 763 | return retval; | 796 | return retval; |
| 764 | 797 | ||
| 765 | #if defined(__ia64__) | 798 | #if defined(__ia64__) |
| 766 | i8042_reset = 1; | 799 | i8042_reset = true; |
| 767 | #endif | 800 | #endif |
| 768 | 801 | ||
| 769 | #ifdef CONFIG_X86 | 802 | #ifdef CONFIG_X86 |
| 770 | if (dmi_check_system(i8042_dmi_reset_table)) | 803 | if (dmi_check_system(i8042_dmi_reset_table)) |
| 771 | i8042_reset = 1; | 804 | i8042_reset = true; |
| 772 | 805 | ||
| 773 | if (dmi_check_system(i8042_dmi_noloop_table)) | 806 | if (dmi_check_system(i8042_dmi_noloop_table)) |
| 774 | i8042_noloop = 1; | 807 | i8042_noloop = true; |
| 775 | 808 | ||
| 776 | if (dmi_check_system(i8042_dmi_nomux_table)) | 809 | if (dmi_check_system(i8042_dmi_nomux_table)) |
| 777 | i8042_nomux = 1; | 810 | i8042_nomux = true; |
| 778 | 811 | ||
| 779 | if (dmi_check_system(i8042_dmi_dritek_table)) | 812 | if (dmi_check_system(i8042_dmi_dritek_table)) |
| 780 | i8042_dritek = 1; | 813 | i8042_dritek = true; |
| 781 | #endif /* CONFIG_X86 */ | 814 | #endif /* CONFIG_X86 */ |
| 782 | 815 | ||
| 783 | return retval; | 816 | return retval; |
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 582245c497eb..eb3ff94af58c 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
| @@ -28,35 +28,35 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); | |||
| 28 | MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver"); | 28 | MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver"); |
| 29 | MODULE_LICENSE("GPL"); | 29 | MODULE_LICENSE("GPL"); |
| 30 | 30 | ||
| 31 | static unsigned int i8042_nokbd; | 31 | static bool i8042_nokbd; |
| 32 | module_param_named(nokbd, i8042_nokbd, bool, 0); | 32 | module_param_named(nokbd, i8042_nokbd, bool, 0); |
| 33 | MODULE_PARM_DESC(nokbd, "Do not probe or use KBD port."); | 33 | MODULE_PARM_DESC(nokbd, "Do not probe or use KBD port."); |
| 34 | 34 | ||
| 35 | static unsigned int i8042_noaux; | 35 | static bool i8042_noaux; |
| 36 | module_param_named(noaux, i8042_noaux, bool, 0); | 36 | module_param_named(noaux, i8042_noaux, bool, 0); |
| 37 | MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port."); | 37 | MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port."); |
| 38 | 38 | ||
| 39 | static unsigned int i8042_nomux; | 39 | static bool i8042_nomux; |
| 40 | module_param_named(nomux, i8042_nomux, bool, 0); | 40 | module_param_named(nomux, i8042_nomux, bool, 0); |
| 41 | MODULE_PARM_DESC(nomux, "Do not check whether an active multiplexing conrtoller is present."); | 41 | MODULE_PARM_DESC(nomux, "Do not check whether an active multiplexing conrtoller is present."); |
| 42 | 42 | ||
| 43 | static unsigned int i8042_unlock; | 43 | static bool i8042_unlock; |
| 44 | module_param_named(unlock, i8042_unlock, bool, 0); | 44 | module_param_named(unlock, i8042_unlock, bool, 0); |
| 45 | MODULE_PARM_DESC(unlock, "Ignore keyboard lock."); | 45 | MODULE_PARM_DESC(unlock, "Ignore keyboard lock."); |
| 46 | 46 | ||
| 47 | static unsigned int i8042_reset; | 47 | static bool i8042_reset; |
| 48 | module_param_named(reset, i8042_reset, bool, 0); | 48 | module_param_named(reset, i8042_reset, bool, 0); |
| 49 | MODULE_PARM_DESC(reset, "Reset controller during init and cleanup."); | 49 | MODULE_PARM_DESC(reset, "Reset controller during init and cleanup."); |
| 50 | 50 | ||
| 51 | static unsigned int i8042_direct; | 51 | static bool i8042_direct; |
| 52 | module_param_named(direct, i8042_direct, bool, 0); | 52 | module_param_named(direct, i8042_direct, bool, 0); |
| 53 | MODULE_PARM_DESC(direct, "Put keyboard port into non-translated mode."); | 53 | MODULE_PARM_DESC(direct, "Put keyboard port into non-translated mode."); |
| 54 | 54 | ||
| 55 | static unsigned int i8042_dumbkbd; | 55 | static bool i8042_dumbkbd; |
| 56 | module_param_named(dumbkbd, i8042_dumbkbd, bool, 0); | 56 | module_param_named(dumbkbd, i8042_dumbkbd, bool, 0); |
| 57 | MODULE_PARM_DESC(dumbkbd, "Pretend that controller can only read data from keyboard"); | 57 | MODULE_PARM_DESC(dumbkbd, "Pretend that controller can only read data from keyboard"); |
| 58 | 58 | ||
| 59 | static unsigned int i8042_noloop; | 59 | static bool i8042_noloop; |
| 60 | module_param_named(noloop, i8042_noloop, bool, 0); | 60 | module_param_named(noloop, i8042_noloop, bool, 0); |
| 61 | MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port"); | 61 | MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port"); |
| 62 | 62 | ||
| @@ -65,24 +65,26 @@ module_param_named(panicblink, i8042_blink_frequency, uint, 0600); | |||
| 65 | MODULE_PARM_DESC(panicblink, "Frequency with which keyboard LEDs should blink when kernel panics"); | 65 | MODULE_PARM_DESC(panicblink, "Frequency with which keyboard LEDs should blink when kernel panics"); |
| 66 | 66 | ||
| 67 | #ifdef CONFIG_X86 | 67 | #ifdef CONFIG_X86 |
| 68 | static unsigned int i8042_dritek; | 68 | static bool i8042_dritek; |
| 69 | module_param_named(dritek, i8042_dritek, bool, 0); | 69 | module_param_named(dritek, i8042_dritek, bool, 0); |
| 70 | MODULE_PARM_DESC(dritek, "Force enable the Dritek keyboard extension"); | 70 | MODULE_PARM_DESC(dritek, "Force enable the Dritek keyboard extension"); |
| 71 | #endif | 71 | #endif |
| 72 | 72 | ||
| 73 | #ifdef CONFIG_PNP | 73 | #ifdef CONFIG_PNP |
| 74 | static int i8042_nopnp; | 74 | static bool i8042_nopnp; |
| 75 | module_param_named(nopnp, i8042_nopnp, bool, 0); | 75 | module_param_named(nopnp, i8042_nopnp, bool, 0); |
| 76 | MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings"); | 76 | MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings"); |
| 77 | #endif | 77 | #endif |
| 78 | 78 | ||
| 79 | #define DEBUG | 79 | #define DEBUG |
| 80 | #ifdef DEBUG | 80 | #ifdef DEBUG |
| 81 | static int i8042_debug; | 81 | static bool i8042_debug; |
| 82 | module_param_named(debug, i8042_debug, bool, 0600); | 82 | module_param_named(debug, i8042_debug, bool, 0600); |
| 83 | MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off"); | 83 | MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off"); |
| 84 | #endif | 84 | #endif |
| 85 | 85 | ||
| 86 | static bool i8042_bypass_aux_irq_test; | ||
| 87 | |||
| 86 | #include "i8042.h" | 88 | #include "i8042.h" |
| 87 | 89 | ||
| 88 | static DEFINE_SPINLOCK(i8042_lock); | 90 | static DEFINE_SPINLOCK(i8042_lock); |
| @@ -90,7 +92,7 @@ static DEFINE_SPINLOCK(i8042_lock); | |||
| 90 | struct i8042_port { | 92 | struct i8042_port { |
| 91 | struct serio *serio; | 93 | struct serio *serio; |
| 92 | int irq; | 94 | int irq; |
| 93 | unsigned char exists; | 95 | bool exists; |
| 94 | signed char mux; | 96 | signed char mux; |
| 95 | }; | 97 | }; |
| 96 | 98 | ||
| @@ -103,9 +105,9 @@ static struct i8042_port i8042_ports[I8042_NUM_PORTS]; | |||
| 103 | 105 | ||
| 104 | static unsigned char i8042_initial_ctr; | 106 | static unsigned char i8042_initial_ctr; |
| 105 | static unsigned char i8042_ctr; | 107 | static unsigned char i8042_ctr; |
| 106 | static unsigned char i8042_mux_present; | 108 | static bool i8042_mux_present; |
| 107 | static unsigned char i8042_kbd_irq_registered; | 109 | static bool i8042_kbd_irq_registered; |
| 108 | static unsigned char i8042_aux_irq_registered; | 110 | static bool i8042_aux_irq_registered; |
| 109 | static unsigned char i8042_suppress_kbd_ack; | 111 | static unsigned char i8042_suppress_kbd_ack; |
| 110 | static struct platform_device *i8042_platform_device; | 112 | static struct platform_device *i8042_platform_device; |
| 111 | 113 | ||
| @@ -262,6 +264,49 @@ static int i8042_aux_write(struct serio *serio, unsigned char c) | |||
| 262 | I8042_CMD_MUX_SEND + port->mux); | 264 | I8042_CMD_MUX_SEND + port->mux); |
| 263 | } | 265 | } |
| 264 | 266 | ||
| 267 | |||
| 268 | /* | ||
| 269 | * i8042_aux_close attempts to clear AUX or KBD port state by disabling | ||
| 270 | * and then re-enabling it. | ||
| 271 | */ | ||
| 272 | |||
| 273 | static void i8042_port_close(struct serio *serio) | ||
| 274 | { | ||
| 275 | int irq_bit; | ||
| 276 | int disable_bit; | ||
| 277 | const char *port_name; | ||
| 278 | |||
| 279 | if (serio == i8042_ports[I8042_AUX_PORT_NO].serio) { | ||
| 280 | irq_bit = I8042_CTR_AUXINT; | ||
| 281 | disable_bit = I8042_CTR_AUXDIS; | ||
| 282 | port_name = "AUX"; | ||
| 283 | } else { | ||
| 284 | irq_bit = I8042_CTR_KBDINT; | ||
| 285 | disable_bit = I8042_CTR_KBDDIS; | ||
| 286 | port_name = "KBD"; | ||
| 287 | } | ||
| 288 | |||
| 289 | i8042_ctr &= ~irq_bit; | ||
| 290 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) | ||
| 291 | printk(KERN_WARNING | ||
| 292 | "i8042.c: Can't write CTR while closing %s port.\n", | ||
| 293 | port_name); | ||
| 294 | |||
| 295 | udelay(50); | ||
| 296 | |||
| 297 | i8042_ctr &= ~disable_bit; | ||
| 298 | i8042_ctr |= irq_bit; | ||
| 299 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) | ||
| 300 | printk(KERN_ERR "i8042.c: Can't reactivate %s port.\n", | ||
| 301 | port_name); | ||
| 302 | |||
| 303 | /* | ||
| 304 | * See if there is any data appeared while we were messing with | ||
| 305 | * port state. | ||
| 306 | */ | ||
| 307 | i8042_interrupt(0, NULL); | ||
| 308 | } | ||
| 309 | |||
| 265 | /* | 310 | /* |
| 266 | * i8042_start() is called by serio core when port is about to finish | 311 | * i8042_start() is called by serio core when port is about to finish |
| 267 | * registering. It will mark port as existing so i8042_interrupt can | 312 | * registering. It will mark port as existing so i8042_interrupt can |
| @@ -271,7 +316,7 @@ static int i8042_start(struct serio *serio) | |||
| 271 | { | 316 | { |
| 272 | struct i8042_port *port = serio->port_data; | 317 | struct i8042_port *port = serio->port_data; |
| 273 | 318 | ||
| 274 | port->exists = 1; | 319 | port->exists = true; |
| 275 | mb(); | 320 | mb(); |
| 276 | return 0; | 321 | return 0; |
| 277 | } | 322 | } |
| @@ -285,7 +330,7 @@ static void i8042_stop(struct serio *serio) | |||
| 285 | { | 330 | { |
| 286 | struct i8042_port *port = serio->port_data; | 331 | struct i8042_port *port = serio->port_data; |
| 287 | 332 | ||
| 288 | port->exists = 0; | 333 | port->exists = false; |
| 289 | 334 | ||
| 290 | /* | 335 | /* |
| 291 | * We synchronize with both AUX and KBD IRQs because there is | 336 | * We synchronize with both AUX and KBD IRQs because there is |
| @@ -391,7 +436,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) | |||
| 391 | } | 436 | } |
| 392 | 437 | ||
| 393 | /* | 438 | /* |
| 394 | * i8042_enable_kbd_port enables keybaord port on chip | 439 | * i8042_enable_kbd_port enables keyboard port on chip |
| 395 | */ | 440 | */ |
| 396 | 441 | ||
| 397 | static int i8042_enable_kbd_port(void) | 442 | static int i8042_enable_kbd_port(void) |
| @@ -447,14 +492,15 @@ static int i8042_enable_mux_ports(void) | |||
| 447 | } | 492 | } |
| 448 | 493 | ||
| 449 | /* | 494 | /* |
| 450 | * i8042_set_mux_mode checks whether the controller has an active | 495 | * i8042_set_mux_mode checks whether the controller has an |
| 451 | * multiplexor and puts the chip into Multiplexed (1) or Legacy (0) mode. | 496 | * active multiplexor and puts the chip into Multiplexed (true) |
| 497 | * or Legacy (false) mode. | ||
| 452 | */ | 498 | */ |
| 453 | 499 | ||
| 454 | static int i8042_set_mux_mode(unsigned int mode, unsigned char *mux_version) | 500 | static int i8042_set_mux_mode(bool multiplex, unsigned char *mux_version) |
| 455 | { | 501 | { |
| 456 | 502 | ||
| 457 | unsigned char param; | 503 | unsigned char param, val; |
| 458 | /* | 504 | /* |
| 459 | * Get rid of bytes in the queue. | 505 | * Get rid of bytes in the queue. |
| 460 | */ | 506 | */ |
| @@ -466,14 +512,21 @@ static int i8042_set_mux_mode(unsigned int mode, unsigned char *mux_version) | |||
| 466 | * mouse interface, the last should be version. | 512 | * mouse interface, the last should be version. |
| 467 | */ | 513 | */ |
| 468 | 514 | ||
| 469 | param = 0xf0; | 515 | param = val = 0xf0; |
| 470 | if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0xf0) | 516 | if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != val) |
| 471 | return -1; | 517 | return -1; |
| 472 | param = mode ? 0x56 : 0xf6; | 518 | param = val = multiplex ? 0x56 : 0xf6; |
| 473 | if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != (mode ? 0x56 : 0xf6)) | 519 | if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != val) |
| 474 | return -1; | 520 | return -1; |
| 475 | param = mode ? 0xa4 : 0xa5; | 521 | param = val = multiplex ? 0xa4 : 0xa5; |
| 476 | if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == (mode ? 0xa4 : 0xa5)) | 522 | if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == val) |
| 523 | return -1; | ||
| 524 | |||
| 525 | /* | ||
| 526 | * Workaround for interference with USB Legacy emulation | ||
| 527 | * that causes a v10.12 MUX to be found. | ||
| 528 | */ | ||
| 529 | if (param == 0xac) | ||
| 477 | return -1; | 530 | return -1; |
| 478 | 531 | ||
| 479 | if (mux_version) | 532 | if (mux_version) |
| @@ -488,18 +541,11 @@ static int i8042_set_mux_mode(unsigned int mode, unsigned char *mux_version) | |||
| 488 | * LCS/Telegraphics. | 541 | * LCS/Telegraphics. |
| 489 | */ | 542 | */ |
| 490 | 543 | ||
| 491 | static int __devinit i8042_check_mux(void) | 544 | static int __init i8042_check_mux(void) |
| 492 | { | 545 | { |
| 493 | unsigned char mux_version; | 546 | unsigned char mux_version; |
| 494 | 547 | ||
| 495 | if (i8042_set_mux_mode(1, &mux_version)) | 548 | if (i8042_set_mux_mode(true, &mux_version)) |
| 496 | return -1; | ||
| 497 | |||
| 498 | /* | ||
| 499 | * Workaround for interference with USB Legacy emulation | ||
| 500 | * that causes a v10.12 MUX to be found. | ||
| 501 | */ | ||
| 502 | if (mux_version == 0xAC) | ||
| 503 | return -1; | 549 | return -1; |
| 504 | 550 | ||
| 505 | printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n", | 551 | printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n", |
| @@ -516,7 +562,7 @@ static int __devinit i8042_check_mux(void) | |||
| 516 | return -EIO; | 562 | return -EIO; |
| 517 | } | 563 | } |
| 518 | 564 | ||
| 519 | i8042_mux_present = 1; | 565 | i8042_mux_present = true; |
| 520 | 566 | ||
| 521 | return 0; | 567 | return 0; |
| 522 | } | 568 | } |
| @@ -524,10 +570,10 @@ static int __devinit i8042_check_mux(void) | |||
| 524 | /* | 570 | /* |
| 525 | * The following is used to test AUX IRQ delivery. | 571 | * The following is used to test AUX IRQ delivery. |
| 526 | */ | 572 | */ |
| 527 | static struct completion i8042_aux_irq_delivered __devinitdata; | 573 | static struct completion i8042_aux_irq_delivered __initdata; |
| 528 | static int i8042_irq_being_tested __devinitdata; | 574 | static bool i8042_irq_being_tested __initdata; |
| 529 | 575 | ||
| 530 | static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id) | 576 | static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id) |
| 531 | { | 577 | { |
| 532 | unsigned long flags; | 578 | unsigned long flags; |
| 533 | unsigned char str, data; | 579 | unsigned char str, data; |
| @@ -552,7 +598,7 @@ static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id) | |||
| 552 | * verifies success by readinng CTR. Used when testing for presence of AUX | 598 | * verifies success by readinng CTR. Used when testing for presence of AUX |
| 553 | * port. | 599 | * port. |
| 554 | */ | 600 | */ |
| 555 | static int __devinit i8042_toggle_aux(int on) | 601 | static int __init i8042_toggle_aux(bool on) |
| 556 | { | 602 | { |
| 557 | unsigned char param; | 603 | unsigned char param; |
| 558 | int i; | 604 | int i; |
| @@ -580,11 +626,11 @@ static int __devinit i8042_toggle_aux(int on) | |||
| 580 | * the presence of an AUX interface. | 626 | * the presence of an AUX interface. |
| 581 | */ | 627 | */ |
| 582 | 628 | ||
| 583 | static int __devinit i8042_check_aux(void) | 629 | static int __init i8042_check_aux(void) |
| 584 | { | 630 | { |
| 585 | int retval = -1; | 631 | int retval = -1; |
| 586 | int irq_registered = 0; | 632 | bool irq_registered = false; |
| 587 | int aux_loop_broken = 0; | 633 | bool aux_loop_broken = false; |
| 588 | unsigned long flags; | 634 | unsigned long flags; |
| 589 | unsigned char param; | 635 | unsigned char param; |
| 590 | 636 | ||
| @@ -621,19 +667,19 @@ static int __devinit i8042_check_aux(void) | |||
| 621 | * mark it as broken | 667 | * mark it as broken |
| 622 | */ | 668 | */ |
| 623 | if (!retval) | 669 | if (!retval) |
| 624 | aux_loop_broken = 1; | 670 | aux_loop_broken = true; |
| 625 | } | 671 | } |
| 626 | 672 | ||
| 627 | /* | 673 | /* |
| 628 | * Bit assignment test - filters out PS/2 i8042's in AT mode | 674 | * Bit assignment test - filters out PS/2 i8042's in AT mode |
| 629 | */ | 675 | */ |
| 630 | 676 | ||
| 631 | if (i8042_toggle_aux(0)) { | 677 | if (i8042_toggle_aux(false)) { |
| 632 | printk(KERN_WARNING "Failed to disable AUX port, but continuing anyway... Is this a SiS?\n"); | 678 | printk(KERN_WARNING "Failed to disable AUX port, but continuing anyway... Is this a SiS?\n"); |
| 633 | printk(KERN_WARNING "If AUX port is really absent please use the 'i8042.noaux' option.\n"); | 679 | printk(KERN_WARNING "If AUX port is really absent please use the 'i8042.noaux' option.\n"); |
| 634 | } | 680 | } |
| 635 | 681 | ||
| 636 | if (i8042_toggle_aux(1)) | 682 | if (i8042_toggle_aux(true)) |
| 637 | return -1; | 683 | return -1; |
| 638 | 684 | ||
| 639 | /* | 685 | /* |
| @@ -641,7 +687,7 @@ static int __devinit i8042_check_aux(void) | |||
| 641 | * used it for a PCI card or somethig else. | 687 | * used it for a PCI card or somethig else. |
| 642 | */ | 688 | */ |
| 643 | 689 | ||
| 644 | if (i8042_noloop || aux_loop_broken) { | 690 | if (i8042_noloop || i8042_bypass_aux_irq_test || aux_loop_broken) { |
| 645 | /* | 691 | /* |
| 646 | * Without LOOP command we can't test AUX IRQ delivery. Assume the port | 692 | * Without LOOP command we can't test AUX IRQ delivery. Assume the port |
| 647 | * is working and hope we are right. | 693 | * is working and hope we are right. |
| @@ -654,7 +700,7 @@ static int __devinit i8042_check_aux(void) | |||
| 654 | "i8042", i8042_platform_device)) | 700 | "i8042", i8042_platform_device)) |
| 655 | goto out; | 701 | goto out; |
| 656 | 702 | ||
| 657 | irq_registered = 1; | 703 | irq_registered = true; |
| 658 | 704 | ||
| 659 | if (i8042_enable_aux_port()) | 705 | if (i8042_enable_aux_port()) |
| 660 | goto out; | 706 | goto out; |
| @@ -662,7 +708,7 @@ static int __devinit i8042_check_aux(void) | |||
| 662 | spin_lock_irqsave(&i8042_lock, flags); | 708 | spin_lock_irqsave(&i8042_lock, flags); |
| 663 | 709 | ||
| 664 | init_completion(&i8042_aux_irq_delivered); | 710 | init_completion(&i8042_aux_irq_delivered); |
| 665 | i8042_irq_being_tested = 1; | 711 | i8042_irq_being_tested = true; |
| 666 | 712 | ||
| 667 | param = 0xa5; | 713 | param = 0xa5; |
| 668 | retval = __i8042_command(¶m, I8042_CMD_AUX_LOOP & 0xf0ff); | 714 | retval = __i8042_command(¶m, I8042_CMD_AUX_LOOP & 0xf0ff); |
| @@ -799,7 +845,7 @@ static int i8042_controller_init(void) | |||
| 799 | */ | 845 | */ |
| 800 | 846 | ||
| 801 | if (~i8042_ctr & I8042_CTR_XLATE) | 847 | if (~i8042_ctr & I8042_CTR_XLATE) |
| 802 | i8042_direct = 1; | 848 | i8042_direct = true; |
| 803 | 849 | ||
| 804 | /* | 850 | /* |
| 805 | * Set nontranslated mode for the kbd interface if requested by an option. | 851 | * Set nontranslated mode for the kbd interface if requested by an option. |
| @@ -839,12 +885,15 @@ static void i8042_controller_reset(void) | |||
| 839 | i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS; | 885 | i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS; |
| 840 | i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); | 886 | i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); |
| 841 | 887 | ||
| 888 | if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR)) | ||
| 889 | printk(KERN_WARNING "i8042.c: Can't write CTR while resetting.\n"); | ||
| 890 | |||
| 842 | /* | 891 | /* |
| 843 | * Disable MUX mode if present. | 892 | * Disable MUX mode if present. |
| 844 | */ | 893 | */ |
| 845 | 894 | ||
| 846 | if (i8042_mux_present) | 895 | if (i8042_mux_present) |
| 847 | i8042_set_mux_mode(0, NULL); | 896 | i8042_set_mux_mode(false, NULL); |
| 848 | 897 | ||
| 849 | /* | 898 | /* |
| 850 | * Reset the controller if requested. | 899 | * Reset the controller if requested. |
| @@ -923,41 +972,27 @@ static void i8042_dritek_enable(void) | |||
| 923 | 972 | ||
| 924 | #ifdef CONFIG_PM | 973 | #ifdef CONFIG_PM |
| 925 | 974 | ||
| 926 | static bool i8042_suspended; | ||
| 927 | |||
| 928 | /* | 975 | /* |
| 929 | * Here we try to restore the original BIOS settings. We only want to | 976 | * Here we try to restore the original BIOS settings to avoid |
| 930 | * do that once, when we really suspend, not when we taking memory | 977 | * upsetting it. |
| 931 | * snapshot for swsusp (in this case we'll perform required cleanup | ||
| 932 | * as part of shutdown process). | ||
| 933 | */ | 978 | */ |
| 934 | 979 | ||
| 935 | static int i8042_suspend(struct platform_device *dev, pm_message_t state) | 980 | static int i8042_pm_reset(struct device *dev) |
| 936 | { | 981 | { |
| 937 | if (!i8042_suspended && state.event == PM_EVENT_SUSPEND) | 982 | i8042_controller_reset(); |
| 938 | i8042_controller_reset(); | ||
| 939 | |||
| 940 | i8042_suspended = state.event == PM_EVENT_SUSPEND || | ||
| 941 | state.event == PM_EVENT_FREEZE; | ||
| 942 | 983 | ||
| 943 | return 0; | 984 | return 0; |
| 944 | } | 985 | } |
| 945 | 986 | ||
| 946 | |||
| 947 | /* | 987 | /* |
| 948 | * Here we try to reset everything back to a state in which suspended | 988 | * Here we try to reset everything back to a state we had |
| 989 | * before suspending. | ||
| 949 | */ | 990 | */ |
| 950 | 991 | ||
| 951 | static int i8042_resume(struct platform_device *dev) | 992 | static int i8042_pm_restore(struct device *dev) |
| 952 | { | 993 | { |
| 953 | int error; | 994 | int error; |
| 954 | 995 | ||
| 955 | /* | ||
| 956 | * Do not bother with restoring state if we haven't suspened yet | ||
| 957 | */ | ||
| 958 | if (!i8042_suspended) | ||
| 959 | return 0; | ||
| 960 | |||
| 961 | error = i8042_controller_check(); | 996 | error = i8042_controller_check(); |
| 962 | if (error) | 997 | if (error) |
| 963 | return error; | 998 | return error; |
| @@ -991,7 +1026,7 @@ static int i8042_resume(struct platform_device *dev) | |||
| 991 | #endif | 1026 | #endif |
| 992 | 1027 | ||
| 993 | if (i8042_mux_present) { | 1028 | if (i8042_mux_present) { |
| 994 | if (i8042_set_mux_mode(1, NULL) || i8042_enable_mux_ports()) | 1029 | if (i8042_set_mux_mode(true, NULL) || i8042_enable_mux_ports()) |
| 995 | printk(KERN_WARNING | 1030 | printk(KERN_WARNING |
| 996 | "i8042: failed to resume active multiplexor, " | 1031 | "i8042: failed to resume active multiplexor, " |
| 997 | "mouse won't work.\n"); | 1032 | "mouse won't work.\n"); |
| @@ -1001,11 +1036,18 @@ static int i8042_resume(struct platform_device *dev) | |||
| 1001 | if (i8042_ports[I8042_KBD_PORT_NO].serio) | 1036 | if (i8042_ports[I8042_KBD_PORT_NO].serio) |
| 1002 | i8042_enable_kbd_port(); | 1037 | i8042_enable_kbd_port(); |
| 1003 | 1038 | ||
| 1004 | i8042_suspended = false; | ||
| 1005 | i8042_interrupt(0, NULL); | 1039 | i8042_interrupt(0, NULL); |
| 1006 | 1040 | ||
| 1007 | return 0; | 1041 | return 0; |
| 1008 | } | 1042 | } |
| 1043 | |||
| 1044 | static const struct dev_pm_ops i8042_pm_ops = { | ||
| 1045 | .suspend = i8042_pm_reset, | ||
| 1046 | .resume = i8042_pm_restore, | ||
| 1047 | .poweroff = i8042_pm_reset, | ||
| 1048 | .restore = i8042_pm_restore, | ||
| 1049 | }; | ||
| 1050 | |||
| 1009 | #endif /* CONFIG_PM */ | 1051 | #endif /* CONFIG_PM */ |
| 1010 | 1052 | ||
| 1011 | /* | 1053 | /* |
| @@ -1018,7 +1060,7 @@ static void i8042_shutdown(struct platform_device *dev) | |||
| 1018 | i8042_controller_reset(); | 1060 | i8042_controller_reset(); |
| 1019 | } | 1061 | } |
| 1020 | 1062 | ||
| 1021 | static int __devinit i8042_create_kbd_port(void) | 1063 | static int __init i8042_create_kbd_port(void) |
| 1022 | { | 1064 | { |
| 1023 | struct serio *serio; | 1065 | struct serio *serio; |
| 1024 | struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; | 1066 | struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; |
| @@ -1031,6 +1073,7 @@ static int __devinit i8042_create_kbd_port(void) | |||
| 1031 | serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; | 1073 | serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; |
| 1032 | serio->start = i8042_start; | 1074 | serio->start = i8042_start; |
| 1033 | serio->stop = i8042_stop; | 1075 | serio->stop = i8042_stop; |
| 1076 | serio->close = i8042_port_close; | ||
| 1034 | serio->port_data = port; | 1077 | serio->port_data = port; |
| 1035 | serio->dev.parent = &i8042_platform_device->dev; | 1078 | serio->dev.parent = &i8042_platform_device->dev; |
| 1036 | strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name)); | 1079 | strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name)); |
| @@ -1042,7 +1085,7 @@ static int __devinit i8042_create_kbd_port(void) | |||
| 1042 | return 0; | 1085 | return 0; |
| 1043 | } | 1086 | } |
| 1044 | 1087 | ||
| 1045 | static int __devinit i8042_create_aux_port(int idx) | 1088 | static int __init i8042_create_aux_port(int idx) |
| 1046 | { | 1089 | { |
| 1047 | struct serio *serio; | 1090 | struct serio *serio; |
| 1048 | int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx; | 1091 | int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx; |
| @@ -1061,6 +1104,7 @@ static int __devinit i8042_create_aux_port(int idx) | |||
| 1061 | if (idx < 0) { | 1104 | if (idx < 0) { |
| 1062 | strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name)); | 1105 | strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name)); |
| 1063 | strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); | 1106 | strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); |
| 1107 | serio->close = i8042_port_close; | ||
| 1064 | } else { | 1108 | } else { |
| 1065 | snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx); | 1109 | snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx); |
| 1066 | snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, idx + 1); | 1110 | snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, idx + 1); |
| @@ -1073,13 +1117,13 @@ static int __devinit i8042_create_aux_port(int idx) | |||
| 1073 | return 0; | 1117 | return 0; |
| 1074 | } | 1118 | } |
| 1075 | 1119 | ||
| 1076 | static void __devinit i8042_free_kbd_port(void) | 1120 | static void __init i8042_free_kbd_port(void) |
| 1077 | { | 1121 | { |
| 1078 | kfree(i8042_ports[I8042_KBD_PORT_NO].serio); | 1122 | kfree(i8042_ports[I8042_KBD_PORT_NO].serio); |
| 1079 | i8042_ports[I8042_KBD_PORT_NO].serio = NULL; | 1123 | i8042_ports[I8042_KBD_PORT_NO].serio = NULL; |
| 1080 | } | 1124 | } |
| 1081 | 1125 | ||
| 1082 | static void __devinit i8042_free_aux_ports(void) | 1126 | static void __init i8042_free_aux_ports(void) |
| 1083 | { | 1127 | { |
| 1084 | int i; | 1128 | int i; |
| 1085 | 1129 | ||
| @@ -1089,7 +1133,7 @@ static void __devinit i8042_free_aux_ports(void) | |||
| 1089 | } | 1133 | } |
| 1090 | } | 1134 | } |
| 1091 | 1135 | ||
| 1092 | static void __devinit i8042_register_ports(void) | 1136 | static void __init i8042_register_ports(void) |
| 1093 | { | 1137 | { |
| 1094 | int i; | 1138 | int i; |
| 1095 | 1139 | ||
| @@ -1124,10 +1168,10 @@ static void i8042_free_irqs(void) | |||
| 1124 | if (i8042_kbd_irq_registered) | 1168 | if (i8042_kbd_irq_registered) |
| 1125 | free_irq(I8042_KBD_IRQ, i8042_platform_device); | 1169 | free_irq(I8042_KBD_IRQ, i8042_platform_device); |
| 1126 | 1170 | ||
| 1127 | i8042_aux_irq_registered = i8042_kbd_irq_registered = 0; | 1171 | i8042_aux_irq_registered = i8042_kbd_irq_registered = false; |
| 1128 | } | 1172 | } |
| 1129 | 1173 | ||
| 1130 | static int __devinit i8042_setup_aux(void) | 1174 | static int __init i8042_setup_aux(void) |
| 1131 | { | 1175 | { |
| 1132 | int (*aux_enable)(void); | 1176 | int (*aux_enable)(void); |
| 1133 | int error; | 1177 | int error; |
| @@ -1158,7 +1202,7 @@ static int __devinit i8042_setup_aux(void) | |||
| 1158 | if (aux_enable()) | 1202 | if (aux_enable()) |
| 1159 | goto err_free_irq; | 1203 | goto err_free_irq; |
| 1160 | 1204 | ||
| 1161 | i8042_aux_irq_registered = 1; | 1205 | i8042_aux_irq_registered = true; |
| 1162 | return 0; | 1206 | return 0; |
| 1163 | 1207 | ||
| 1164 | err_free_irq: | 1208 | err_free_irq: |
| @@ -1168,7 +1212,7 @@ static int __devinit i8042_setup_aux(void) | |||
| 1168 | return error; | 1212 | return error; |
| 1169 | } | 1213 | } |
| 1170 | 1214 | ||
| 1171 | static int __devinit i8042_setup_kbd(void) | 1215 | static int __init i8042_setup_kbd(void) |
| 1172 | { | 1216 | { |
| 1173 | int error; | 1217 | int error; |
| 1174 | 1218 | ||
| @@ -1185,7 +1229,7 @@ static int __devinit i8042_setup_kbd(void) | |||
| 1185 | if (error) | 1229 | if (error) |
| 1186 | goto err_free_irq; | 1230 | goto err_free_irq; |
| 1187 | 1231 | ||
| 1188 | i8042_kbd_irq_registered = 1; | 1232 | i8042_kbd_irq_registered = true; |
| 1189 | return 0; | 1233 | return 0; |
| 1190 | 1234 | ||
| 1191 | err_free_irq: | 1235 | err_free_irq: |
| @@ -1195,7 +1239,7 @@ static int __devinit i8042_setup_kbd(void) | |||
| 1195 | return error; | 1239 | return error; |
| 1196 | } | 1240 | } |
| 1197 | 1241 | ||
| 1198 | static int __devinit i8042_probe(struct platform_device *dev) | 1242 | static int __init i8042_probe(struct platform_device *dev) |
| 1199 | { | 1243 | { |
| 1200 | int error; | 1244 | int error; |
| 1201 | 1245 | ||
| @@ -1251,14 +1295,12 @@ static struct platform_driver i8042_driver = { | |||
| 1251 | .driver = { | 1295 | .driver = { |
| 1252 | .name = "i8042", | 1296 | .name = "i8042", |
| 1253 | .owner = THIS_MODULE, | 1297 | .owner = THIS_MODULE, |
| 1298 | #ifdef CONFIG_PM | ||
| 1299 | .pm = &i8042_pm_ops, | ||
| 1300 | #endif | ||
| 1254 | }, | 1301 | }, |
| 1255 | .probe = i8042_probe, | ||
| 1256 | .remove = __devexit_p(i8042_remove), | 1302 | .remove = __devexit_p(i8042_remove), |
| 1257 | .shutdown = i8042_shutdown, | 1303 | .shutdown = i8042_shutdown, |
| 1258 | #ifdef CONFIG_PM | ||
| 1259 | .suspend = i8042_suspend, | ||
| 1260 | .resume = i8042_resume, | ||
| 1261 | #endif | ||
| 1262 | }; | 1304 | }; |
| 1263 | 1305 | ||
| 1264 | static int __init i8042_init(void) | 1306 | static int __init i8042_init(void) |
| @@ -1275,28 +1317,28 @@ static int __init i8042_init(void) | |||
| 1275 | if (err) | 1317 | if (err) |
| 1276 | goto err_platform_exit; | 1318 | goto err_platform_exit; |
| 1277 | 1319 | ||
| 1278 | err = platform_driver_register(&i8042_driver); | ||
| 1279 | if (err) | ||
| 1280 | goto err_platform_exit; | ||
| 1281 | |||
| 1282 | i8042_platform_device = platform_device_alloc("i8042", -1); | 1320 | i8042_platform_device = platform_device_alloc("i8042", -1); |
| 1283 | if (!i8042_platform_device) { | 1321 | if (!i8042_platform_device) { |
| 1284 | err = -ENOMEM; | 1322 | err = -ENOMEM; |
| 1285 | goto err_unregister_driver; | 1323 | goto err_platform_exit; |
| 1286 | } | 1324 | } |
| 1287 | 1325 | ||
| 1288 | err = platform_device_add(i8042_platform_device); | 1326 | err = platform_device_add(i8042_platform_device); |
| 1289 | if (err) | 1327 | if (err) |
| 1290 | goto err_free_device; | 1328 | goto err_free_device; |
| 1291 | 1329 | ||
| 1330 | err = platform_driver_probe(&i8042_driver, i8042_probe); | ||
| 1331 | if (err) | ||
| 1332 | goto err_del_device; | ||
| 1333 | |||
| 1292 | panic_blink = i8042_panic_blink; | 1334 | panic_blink = i8042_panic_blink; |
| 1293 | 1335 | ||
| 1294 | return 0; | 1336 | return 0; |
| 1295 | 1337 | ||
| 1338 | err_del_device: | ||
| 1339 | platform_device_del(i8042_platform_device); | ||
| 1296 | err_free_device: | 1340 | err_free_device: |
| 1297 | platform_device_put(i8042_platform_device); | 1341 | platform_device_put(i8042_platform_device); |
| 1298 | err_unregister_driver: | ||
| 1299 | platform_driver_unregister(&i8042_driver); | ||
| 1300 | err_platform_exit: | 1342 | err_platform_exit: |
| 1301 | i8042_platform_exit(); | 1343 | i8042_platform_exit(); |
| 1302 | 1344 | ||
| @@ -1305,8 +1347,8 @@ static int __init i8042_init(void) | |||
| 1305 | 1347 | ||
| 1306 | static void __exit i8042_exit(void) | 1348 | static void __exit i8042_exit(void) |
| 1307 | { | 1349 | { |
| 1308 | platform_device_unregister(i8042_platform_device); | ||
| 1309 | platform_driver_unregister(&i8042_driver); | 1350 | platform_driver_unregister(&i8042_driver); |
| 1351 | platform_device_unregister(i8042_platform_device); | ||
| 1310 | i8042_platform_exit(); | 1352 | i8042_platform_exit(); |
| 1311 | 1353 | ||
| 1312 | panic_blink = NULL; | 1354 | panic_blink = NULL; |
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 | ||
| 164 | int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | 164 | int __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 | } | ||
| 234 | EXPORT_SYMBOL(__ps2_command); | ||
| 235 | |||
| 236 | int 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 | } |
| 237 | EXPORT_SYMBOL(ps2_command); | 246 | EXPORT_SYMBOL(ps2_command); |
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index d66f4944f2a0..0236f0d5fd91 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
| @@ -931,15 +931,11 @@ static int serio_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
| 931 | #endif /* CONFIG_HOTPLUG */ | 931 | #endif /* CONFIG_HOTPLUG */ |
| 932 | 932 | ||
| 933 | #ifdef CONFIG_PM | 933 | #ifdef CONFIG_PM |
| 934 | static int serio_suspend(struct device *dev, pm_message_t state) | 934 | static int serio_suspend(struct device *dev) |
| 935 | { | 935 | { |
| 936 | struct serio *serio = to_serio_port(dev); | 936 | struct serio *serio = to_serio_port(dev); |
| 937 | 937 | ||
| 938 | if (!serio->suspended && state.event == PM_EVENT_SUSPEND) | 938 | serio_cleanup(serio); |
| 939 | serio_cleanup(serio); | ||
| 940 | |||
| 941 | serio->suspended = state.event == PM_EVENT_SUSPEND || | ||
| 942 | state.event == PM_EVENT_FREEZE; | ||
| 943 | 939 | ||
| 944 | return 0; | 940 | return 0; |
| 945 | } | 941 | } |
| @@ -952,13 +948,17 @@ static int serio_resume(struct device *dev) | |||
| 952 | * Driver reconnect can take a while, so better let kseriod | 948 | * Driver reconnect can take a while, so better let kseriod |
| 953 | * deal with it. | 949 | * deal with it. |
| 954 | */ | 950 | */ |
| 955 | if (serio->suspended) { | 951 | serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT); |
| 956 | serio->suspended = false; | ||
| 957 | serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT); | ||
| 958 | } | ||
| 959 | 952 | ||
| 960 | return 0; | 953 | return 0; |
| 961 | } | 954 | } |
| 955 | |||
| 956 | static const struct dev_pm_ops serio_pm_ops = { | ||
| 957 | .suspend = serio_suspend, | ||
| 958 | .resume = serio_resume, | ||
| 959 | .poweroff = serio_suspend, | ||
| 960 | .restore = serio_resume, | ||
| 961 | }; | ||
| 962 | #endif /* CONFIG_PM */ | 962 | #endif /* CONFIG_PM */ |
| 963 | 963 | ||
| 964 | /* called from serio_driver->connect/disconnect methods under serio_mutex */ | 964 | /* called from serio_driver->connect/disconnect methods under serio_mutex */ |
| @@ -1015,8 +1015,7 @@ static struct bus_type serio_bus = { | |||
| 1015 | .remove = serio_driver_remove, | 1015 | .remove = serio_driver_remove, |
| 1016 | .shutdown = serio_shutdown, | 1016 | .shutdown = serio_shutdown, |
| 1017 | #ifdef CONFIG_PM | 1017 | #ifdef CONFIG_PM |
| 1018 | .suspend = serio_suspend, | 1018 | .pm = &serio_pm_ops, |
| 1019 | .resume = serio_resume, | ||
| 1020 | #endif | 1019 | #endif |
| 1021 | }; | 1020 | }; |
| 1022 | 1021 | ||
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 72e2712c7e2a..87a1ae63bcc4 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
| @@ -366,11 +366,11 @@ config TOUCHSCREEN_WM97XX_ATMEL | |||
| 366 | be called atmel-wm97xx. | 366 | be called atmel-wm97xx. |
| 367 | 367 | ||
| 368 | config TOUCHSCREEN_WM97XX_MAINSTONE | 368 | config TOUCHSCREEN_WM97XX_MAINSTONE |
| 369 | tristate "WM97xx Mainstone accelerated touch" | 369 | tristate "WM97xx Mainstone/Palm accelerated touch" |
| 370 | depends on TOUCHSCREEN_WM97XX && ARCH_PXA | 370 | depends on TOUCHSCREEN_WM97XX && ARCH_PXA |
| 371 | help | 371 | help |
| 372 | Say Y here for support for streaming mode with WM97xx touchscreens | 372 | Say Y here for support for streaming mode with WM97xx touchscreens |
| 373 | on Mainstone systems. | 373 | on Mainstone, Palm Tungsten T5, TX and LifeDrive systems. |
| 374 | 374 | ||
| 375 | If unsure, say N. | 375 | If unsure, say N. |
| 376 | 376 | ||
| @@ -406,6 +406,7 @@ config TOUCHSCREEN_USB_COMPOSITE | |||
| 406 | - IRTOUCHSYSTEMS/UNITOP | 406 | - IRTOUCHSYSTEMS/UNITOP |
| 407 | - IdealTEK URTC1000 | 407 | - IdealTEK URTC1000 |
| 408 | - GoTop Super_Q2/GogoPen/PenPower tablets | 408 | - GoTop Super_Q2/GogoPen/PenPower tablets |
| 409 | - JASTEC USB Touch Controller/DigiTech DTR-02U | ||
| 409 | 410 | ||
| 410 | Have a look at <http://linux.chapter7.ch/touchkit/> for | 411 | Have a look at <http://linux.chapter7.ch/touchkit/> for |
| 411 | a usage description and the required user-space stuff. | 412 | a usage description and the required user-space stuff. |
| @@ -468,6 +469,16 @@ config TOUCHSCREEN_USB_GOTOP | |||
| 468 | bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EMBEDDED | 469 | bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EMBEDDED |
| 469 | depends on TOUCHSCREEN_USB_COMPOSITE | 470 | depends on TOUCHSCREEN_USB_COMPOSITE |
| 470 | 471 | ||
| 472 | config TOUCHSCREEN_USB_JASTEC | ||
| 473 | default y | ||
| 474 | bool "JASTEC/DigiTech DTR-02U USB touch controller device support" if EMBEDDED | ||
| 475 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
| 476 | |||
| 477 | config TOUCHSCREEN_USB_E2I | ||
| 478 | default y | ||
| 479 | bool "e2i Touchscreen controller (e.g. from Mimo 740)" | ||
| 480 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
| 481 | |||
| 471 | config TOUCHSCREEN_TOUCHIT213 | 482 | config TOUCHSCREEN_TOUCHIT213 |
| 472 | tristate "Sahara TouchIT-213 touchscreen" | 483 | tristate "Sahara TouchIT-213 touchscreen" |
| 473 | select SERIO | 484 | select SERIO |
| @@ -492,6 +503,7 @@ config TOUCHSCREEN_TSC2007 | |||
| 492 | 503 | ||
| 493 | config TOUCHSCREEN_W90X900 | 504 | config TOUCHSCREEN_W90X900 |
| 494 | tristate "W90P910 touchscreen driver" | 505 | tristate "W90P910 touchscreen driver" |
| 506 | depends on HAVE_CLK | ||
| 495 | help | 507 | help |
| 496 | Say Y here if you have a W90P910 based touchscreen. | 508 | Say Y here if you have a W90P910 based touchscreen. |
| 497 | 509 | ||
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index 055969e8be13..9c7fce4d74d0 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c | |||
| @@ -204,14 +204,14 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) | |||
| 204 | goto err_free_dev; | 204 | goto err_free_dev; |
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | if (!request_mem_region(res->start, res->end - res->start + 1, | 207 | if (!request_mem_region(res->start, resource_size(res), |
| 208 | "atmel tsadcc regs")) { | 208 | "atmel tsadcc regs")) { |
| 209 | dev_err(&pdev->dev, "resources is unavailable.\n"); | 209 | dev_err(&pdev->dev, "resources is unavailable.\n"); |
| 210 | err = -EBUSY; | 210 | err = -EBUSY; |
| 211 | goto err_free_dev; | 211 | goto err_free_dev; |
| 212 | } | 212 | } |
| 213 | 213 | ||
| 214 | tsc_base = ioremap(res->start, res->end - res->start + 1); | 214 | tsc_base = ioremap(res->start, resource_size(res)); |
| 215 | if (!tsc_base) { | 215 | if (!tsc_base) { |
| 216 | dev_err(&pdev->dev, "failed to map registers.\n"); | 216 | dev_err(&pdev->dev, "failed to map registers.\n"); |
| 217 | err = -ENOMEM; | 217 | err = -ENOMEM; |
| @@ -286,7 +286,7 @@ err_free_irq: | |||
| 286 | err_unmap_regs: | 286 | err_unmap_regs: |
| 287 | iounmap(tsc_base); | 287 | iounmap(tsc_base); |
| 288 | err_release_mem: | 288 | err_release_mem: |
| 289 | release_mem_region(res->start, res->end - res->start + 1); | 289 | release_mem_region(res->start, resource_size(res)); |
| 290 | err_free_dev: | 290 | err_free_dev: |
| 291 | input_free_device(ts_dev->input); | 291 | input_free_device(ts_dev->input); |
| 292 | err_free_mem: | 292 | err_free_mem: |
| @@ -305,7 +305,7 @@ static int __devexit atmel_tsadcc_remove(struct platform_device *pdev) | |||
| 305 | 305 | ||
| 306 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 306 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 307 | iounmap(tsc_base); | 307 | iounmap(tsc_base); |
| 308 | release_mem_region(res->start, res->end - res->start + 1); | 308 | release_mem_region(res->start, resource_size(res)); |
| 309 | 309 | ||
| 310 | clk_disable(ts_dev->clk); | 310 | clk_disable(ts_dev->clk); |
| 311 | clk_put(ts_dev->clk); | 311 | clk_put(ts_dev->clk); |
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 3ab92222a525..9029bd3f34e5 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/i2c.h> | 32 | #include <linux/i2c.h> |
| 33 | #include <linux/timer.h> | 33 | #include <linux/timer.h> |
| 34 | #include <linux/gpio.h> | 34 | #include <linux/gpio.h> |
| 35 | #include <linux/input/eeti_ts.h> | ||
| 35 | 36 | ||
| 36 | static int flip_x; | 37 | static int flip_x; |
| 37 | module_param(flip_x, bool, 0644); | 38 | module_param(flip_x, bool, 0644); |
| @@ -46,7 +47,7 @@ struct eeti_ts_priv { | |||
| 46 | struct input_dev *input; | 47 | struct input_dev *input; |
| 47 | struct work_struct work; | 48 | struct work_struct work; |
| 48 | struct mutex mutex; | 49 | struct mutex mutex; |
| 49 | int irq; | 50 | int irq, irq_active_high; |
| 50 | }; | 51 | }; |
| 51 | 52 | ||
| 52 | #define EETI_TS_BITDEPTH (11) | 53 | #define EETI_TS_BITDEPTH (11) |
| @@ -58,6 +59,11 @@ struct eeti_ts_priv { | |||
| 58 | #define REPORT_BIT_HAS_PRESSURE (1 << 6) | 59 | #define REPORT_BIT_HAS_PRESSURE (1 << 6) |
| 59 | #define REPORT_RES_BITS(v) (((v) >> 1) + EETI_TS_BITDEPTH) | 60 | #define REPORT_RES_BITS(v) (((v) >> 1) + EETI_TS_BITDEPTH) |
| 60 | 61 | ||
| 62 | static inline int eeti_ts_irq_active(struct eeti_ts_priv *priv) | ||
| 63 | { | ||
| 64 | return gpio_get_value(irq_to_gpio(priv->irq)) == priv->irq_active_high; | ||
| 65 | } | ||
| 66 | |||
| 61 | static void eeti_ts_read(struct work_struct *work) | 67 | static void eeti_ts_read(struct work_struct *work) |
| 62 | { | 68 | { |
| 63 | char buf[6]; | 69 | char buf[6]; |
| @@ -67,7 +73,7 @@ static void eeti_ts_read(struct work_struct *work) | |||
| 67 | 73 | ||
| 68 | mutex_lock(&priv->mutex); | 74 | mutex_lock(&priv->mutex); |
| 69 | 75 | ||
| 70 | while (!gpio_get_value(irq_to_gpio(priv->irq)) && --to) | 76 | while (eeti_ts_irq_active(priv) && --to) |
| 71 | i2c_master_recv(priv->client, buf, sizeof(buf)); | 77 | i2c_master_recv(priv->client, buf, sizeof(buf)); |
| 72 | 78 | ||
| 73 | if (!to) { | 79 | if (!to) { |
| @@ -140,8 +146,10 @@ static void eeti_ts_close(struct input_dev *dev) | |||
| 140 | static int __devinit eeti_ts_probe(struct i2c_client *client, | 146 | static int __devinit eeti_ts_probe(struct i2c_client *client, |
| 141 | const struct i2c_device_id *idp) | 147 | const struct i2c_device_id *idp) |
| 142 | { | 148 | { |
| 149 | struct eeti_ts_platform_data *pdata; | ||
| 143 | struct eeti_ts_priv *priv; | 150 | struct eeti_ts_priv *priv; |
| 144 | struct input_dev *input; | 151 | struct input_dev *input; |
| 152 | unsigned int irq_flags; | ||
| 145 | int err = -ENOMEM; | 153 | int err = -ENOMEM; |
| 146 | 154 | ||
| 147 | /* In contrast to what's described in the datasheet, there seems | 155 | /* In contrast to what's described in the datasheet, there seems |
| @@ -180,6 +188,14 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, | |||
| 180 | priv->input = input; | 188 | priv->input = input; |
| 181 | priv->irq = client->irq; | 189 | priv->irq = client->irq; |
| 182 | 190 | ||
| 191 | pdata = client->dev.platform_data; | ||
| 192 | |||
| 193 | if (pdata) | ||
| 194 | priv->irq_active_high = pdata->irq_active_high; | ||
| 195 | |||
| 196 | irq_flags = priv->irq_active_high ? | ||
| 197 | IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING; | ||
| 198 | |||
| 183 | INIT_WORK(&priv->work, eeti_ts_read); | 199 | INIT_WORK(&priv->work, eeti_ts_read); |
| 184 | i2c_set_clientdata(client, priv); | 200 | i2c_set_clientdata(client, priv); |
| 185 | input_set_drvdata(input, priv); | 201 | input_set_drvdata(input, priv); |
| @@ -188,7 +204,7 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, | |||
| 188 | if (err) | 204 | if (err) |
| 189 | goto err1; | 205 | goto err1; |
| 190 | 206 | ||
| 191 | err = request_irq(priv->irq, eeti_ts_isr, IRQF_TRIGGER_FALLING, | 207 | err = request_irq(priv->irq, eeti_ts_isr, irq_flags, |
| 192 | client->name, priv); | 208 | client->name, priv); |
| 193 | if (err) { | 209 | if (err) { |
| 194 | dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); | 210 | dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); |
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c index 4d3139e2099d..b4d7f63deff1 100644 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ b/drivers/input/touchscreen/h3600_ts_input.c | |||
| @@ -148,9 +148,10 @@ unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr) | |||
| 148 | struct h3600_dev *ts = input_get_drvdata(dev); | 148 | struct h3600_dev *ts = input_get_drvdata(dev); |
| 149 | 149 | ||
| 150 | /* Must be in this order */ | 150 | /* Must be in this order */ |
| 151 | ts->serio->write(ts->serio, 1); | 151 | serio_write(ts->serio, 1); |
| 152 | ts->serio->write(ts->serio, pwr); | 152 | serio_write(ts->serio, pwr); |
| 153 | ts->serio->write(ts->serio, brightness); | 153 | serio_write(ts->serio, brightness); |
| 154 | |||
| 154 | return 0; | 155 | return 0; |
| 155 | } | 156 | } |
| 156 | 157 | ||
| @@ -262,7 +263,7 @@ static int h3600ts_event(struct input_dev *dev, unsigned int type, | |||
| 262 | 263 | ||
| 263 | switch (type) { | 264 | switch (type) { |
| 264 | case EV_LED: { | 265 | case EV_LED: { |
| 265 | // ts->serio->write(ts->serio, SOME_CMD); | 266 | // serio_write(ts->serio, SOME_CMD); |
| 266 | return 0; | 267 | return 0; |
| 267 | } | 268 | } |
| 268 | } | 269 | } |
diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c index 4cc047a5116e..8fc3b08deb3b 100644 --- a/drivers/input/touchscreen/mainstone-wm97xx.c +++ b/drivers/input/touchscreen/mainstone-wm97xx.c | |||
| @@ -31,9 +31,11 @@ | |||
| 31 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
| 32 | #include <linux/wm97xx.h> | 32 | #include <linux/wm97xx.h> |
| 33 | #include <linux/io.h> | 33 | #include <linux/io.h> |
| 34 | #include <linux/gpio.h> | ||
| 35 | |||
| 34 | #include <mach/regs-ac97.h> | 36 | #include <mach/regs-ac97.h> |
| 35 | 37 | ||
| 36 | #define VERSION "0.13" | 38 | #include <asm/mach-types.h> |
| 37 | 39 | ||
| 38 | struct continuous { | 40 | struct continuous { |
| 39 | u16 id; /* codec id */ | 41 | u16 id; /* codec id */ |
| @@ -62,6 +64,7 @@ static const struct continuous cinfo[] = { | |||
| 62 | /* continuous speed index */ | 64 | /* continuous speed index */ |
| 63 | static int sp_idx; | 65 | static int sp_idx; |
| 64 | static u16 last, tries; | 66 | static u16 last, tries; |
| 67 | static int irq; | ||
| 65 | 68 | ||
| 66 | /* | 69 | /* |
| 67 | * Pen sampling frequency (Hz) in continuous mode. | 70 | * Pen sampling frequency (Hz) in continuous mode. |
| @@ -171,7 +174,7 @@ up: | |||
| 171 | 174 | ||
| 172 | static int wm97xx_acc_startup(struct wm97xx *wm) | 175 | static int wm97xx_acc_startup(struct wm97xx *wm) |
| 173 | { | 176 | { |
| 174 | int idx = 0; | 177 | int idx = 0, ret = 0; |
| 175 | 178 | ||
| 176 | /* check we have a codec */ | 179 | /* check we have a codec */ |
| 177 | if (wm->ac97 == NULL) | 180 | if (wm->ac97 == NULL) |
| @@ -191,18 +194,40 @@ static int wm97xx_acc_startup(struct wm97xx *wm) | |||
| 191 | "mainstone accelerated touchscreen driver, %d samples/sec\n", | 194 | "mainstone accelerated touchscreen driver, %d samples/sec\n", |
| 192 | cinfo[sp_idx].speed); | 195 | cinfo[sp_idx].speed); |
| 193 | 196 | ||
| 197 | /* IRQ driven touchscreen is used on Palm hardware */ | ||
| 198 | if (machine_is_palmt5() || machine_is_palmtx() || machine_is_palmld()) { | ||
| 199 | pen_int = 1; | ||
| 200 | irq = 27; | ||
| 201 | /* There is some obscure mutant of WM9712 interbred with WM9713 | ||
| 202 | * used on Palm HW */ | ||
| 203 | wm->variant = WM97xx_WM1613; | ||
| 204 | } else if (machine_is_mainstone() && pen_int) | ||
| 205 | irq = 4; | ||
| 206 | |||
| 207 | if (irq) { | ||
| 208 | ret = gpio_request(irq, "Touchscreen IRQ"); | ||
| 209 | if (ret) | ||
| 210 | goto out; | ||
| 211 | |||
| 212 | ret = gpio_direction_input(irq); | ||
| 213 | if (ret) { | ||
| 214 | gpio_free(irq); | ||
| 215 | goto out; | ||
| 216 | } | ||
| 217 | |||
| 218 | wm->pen_irq = gpio_to_irq(irq); | ||
| 219 | set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH); | ||
| 220 | } else /* pen irq not supported */ | ||
| 221 | pen_int = 0; | ||
| 222 | |||
| 194 | /* codec specific irq config */ | 223 | /* codec specific irq config */ |
| 195 | if (pen_int) { | 224 | if (pen_int) { |
| 196 | switch (wm->id) { | 225 | switch (wm->id) { |
| 197 | case WM9705_ID2: | 226 | case WM9705_ID2: |
| 198 | wm->pen_irq = IRQ_GPIO(4); | ||
| 199 | set_irq_type(IRQ_GPIO(4), IRQ_TYPE_EDGE_BOTH); | ||
| 200 | break; | 227 | break; |
| 201 | case WM9712_ID2: | 228 | case WM9712_ID2: |
| 202 | case WM9713_ID2: | 229 | case WM9713_ID2: |
| 203 | /* enable pen down interrupt */ | ||
| 204 | /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */ | 230 | /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */ |
| 205 | wm->pen_irq = MAINSTONE_AC97_IRQ; | ||
| 206 | wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, | 231 | wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, |
| 207 | WM97XX_GPIO_POL_HIGH, | 232 | WM97XX_GPIO_POL_HIGH, |
| 208 | WM97XX_GPIO_STICKY, | 233 | WM97XX_GPIO_STICKY, |
| @@ -220,23 +245,17 @@ static int wm97xx_acc_startup(struct wm97xx *wm) | |||
| 220 | } | 245 | } |
| 221 | } | 246 | } |
| 222 | 247 | ||
| 223 | return 0; | 248 | out: |
| 249 | return ret; | ||
| 224 | } | 250 | } |
| 225 | 251 | ||
| 226 | static void wm97xx_acc_shutdown(struct wm97xx *wm) | 252 | static void wm97xx_acc_shutdown(struct wm97xx *wm) |
| 227 | { | 253 | { |
| 228 | /* codec specific deconfig */ | 254 | /* codec specific deconfig */ |
| 229 | if (pen_int) { | 255 | if (pen_int) { |
| 230 | switch (wm->id & 0xffff) { | 256 | if (irq) |
| 231 | case WM9705_ID2: | 257 | gpio_free(irq); |
| 232 | wm->pen_irq = 0; | 258 | wm->pen_irq = 0; |
| 233 | break; | ||
| 234 | case WM9712_ID2: | ||
| 235 | case WM9713_ID2: | ||
| 236 | /* disable interrupt */ | ||
| 237 | wm->pen_irq = 0; | ||
| 238 | break; | ||
| 239 | } | ||
| 240 | } | 259 | } |
| 241 | } | 260 | } |
| 242 | 261 | ||
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 880f58c6a7c4..7ef0d1420d3c 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c | |||
| @@ -21,15 +21,14 @@ | |||
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 24 | #include <linux/hrtimer.h> | ||
| 25 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
| 26 | #include <linux/input.h> | 25 | #include <linux/input.h> |
| 27 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
| 28 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
| 29 | #include <linux/i2c/tsc2007.h> | 28 | #include <linux/i2c/tsc2007.h> |
| 30 | 29 | ||
| 31 | #define TS_POLL_DELAY (10 * 1000) /* ns delay before the first sample */ | 30 | #define TS_POLL_DELAY 1 /* ms delay between samples */ |
| 32 | #define TS_POLL_PERIOD (5 * 1000) /* ns delay between samples */ | 31 | #define TS_POLL_PERIOD 1 /* ms delay between samples */ |
| 33 | 32 | ||
| 34 | #define TSC2007_MEASURE_TEMP0 (0x0 << 4) | 33 | #define TSC2007_MEASURE_TEMP0 (0x0 << 4) |
| 35 | #define TSC2007_MEASURE_AUX (0x2 << 4) | 34 | #define TSC2007_MEASURE_AUX (0x2 << 4) |
| @@ -70,17 +69,14 @@ struct ts_event { | |||
| 70 | struct tsc2007 { | 69 | struct tsc2007 { |
| 71 | struct input_dev *input; | 70 | struct input_dev *input; |
| 72 | char phys[32]; | 71 | char phys[32]; |
| 73 | struct hrtimer timer; | 72 | struct delayed_work work; |
| 74 | struct ts_event tc; | ||
| 75 | 73 | ||
| 76 | struct i2c_client *client; | 74 | struct i2c_client *client; |
| 77 | 75 | ||
| 78 | spinlock_t lock; | ||
| 79 | |||
| 80 | u16 model; | 76 | u16 model; |
| 81 | u16 x_plate_ohms; | 77 | u16 x_plate_ohms; |
| 82 | 78 | ||
| 83 | unsigned pendown; | 79 | bool pendown; |
| 84 | int irq; | 80 | int irq; |
| 85 | 81 | ||
| 86 | int (*get_pendown_state)(void); | 82 | int (*get_pendown_state)(void); |
| @@ -109,52 +105,96 @@ static inline int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd) | |||
| 109 | return val; | 105 | return val; |
| 110 | } | 106 | } |
| 111 | 107 | ||
| 112 | static void tsc2007_send_event(void *tsc) | 108 | static void tsc2007_read_values(struct tsc2007 *tsc, struct ts_event *tc) |
| 113 | { | 109 | { |
| 114 | struct tsc2007 *ts = tsc; | 110 | /* y- still on; turn on only y+ (and ADC) */ |
| 115 | u32 rt; | 111 | tc->y = tsc2007_xfer(tsc, READ_Y); |
| 116 | u16 x, y, z1, z2; | 112 | |
| 113 | /* turn y- off, x+ on, then leave in lowpower */ | ||
| 114 | tc->x = tsc2007_xfer(tsc, READ_X); | ||
| 115 | |||
| 116 | /* turn y+ off, x- on; we'll use formula #1 */ | ||
| 117 | tc->z1 = tsc2007_xfer(tsc, READ_Z1); | ||
| 118 | tc->z2 = tsc2007_xfer(tsc, READ_Z2); | ||
| 117 | 119 | ||
| 118 | x = ts->tc.x; | 120 | /* Prepare for next touch reading - power down ADC, enable PENIRQ */ |
| 119 | y = ts->tc.y; | 121 | tsc2007_xfer(tsc, PWRDOWN); |
| 120 | z1 = ts->tc.z1; | 122 | } |
| 121 | z2 = ts->tc.z2; | 123 | |
| 124 | static u32 tsc2007_calculate_pressure(struct tsc2007 *tsc, struct ts_event *tc) | ||
| 125 | { | ||
| 126 | u32 rt = 0; | ||
| 122 | 127 | ||
| 123 | /* range filtering */ | 128 | /* range filtering */ |
| 124 | if (x == MAX_12BIT) | 129 | if (tc->x == MAX_12BIT) |
| 125 | x = 0; | 130 | tc->x = 0; |
| 126 | 131 | ||
| 127 | if (likely(x && z1)) { | 132 | if (likely(tc->x && tc->z1)) { |
| 128 | /* compute touch pressure resistance using equation #1 */ | 133 | /* compute touch pressure resistance using equation #1 */ |
| 129 | rt = z2; | 134 | rt = tc->z2 - tc->z1; |
| 130 | rt -= z1; | 135 | rt *= tc->x; |
| 131 | rt *= x; | 136 | rt *= tsc->x_plate_ohms; |
| 132 | rt *= ts->x_plate_ohms; | 137 | rt /= tc->z1; |
| 133 | rt /= z1; | ||
| 134 | rt = (rt + 2047) >> 12; | 138 | rt = (rt + 2047) >> 12; |
| 135 | } else | 139 | } |
| 136 | rt = 0; | 140 | |
| 141 | return rt; | ||
| 142 | } | ||
| 143 | |||
| 144 | static void tsc2007_send_up_event(struct tsc2007 *tsc) | ||
| 145 | { | ||
| 146 | struct input_dev *input = tsc->input; | ||
| 137 | 147 | ||
| 138 | /* Sample found inconsistent by debouncing or pressure is beyond | 148 | dev_dbg(&tsc->client->dev, "UP\n"); |
| 139 | * the maximum. Don't report it to user space, repeat at least | 149 | |
| 140 | * once more the measurement | 150 | input_report_key(input, BTN_TOUCH, 0); |
| 151 | input_report_abs(input, ABS_PRESSURE, 0); | ||
| 152 | input_sync(input); | ||
| 153 | } | ||
| 154 | |||
| 155 | static void tsc2007_work(struct work_struct *work) | ||
| 156 | { | ||
| 157 | struct tsc2007 *ts = | ||
| 158 | container_of(to_delayed_work(work), struct tsc2007, work); | ||
| 159 | struct ts_event tc; | ||
| 160 | u32 rt; | ||
| 161 | |||
| 162 | /* | ||
| 163 | * NOTE: We can't rely on the pressure to determine the pen down | ||
| 164 | * state, even though this controller has a pressure sensor. | ||
| 165 | * The pressure value can fluctuate for quite a while after | ||
| 166 | * lifting the pen and in some cases may not even settle at the | ||
| 167 | * expected value. | ||
| 168 | * | ||
| 169 | * The only safe way to check for the pen up condition is in the | ||
| 170 | * work function by reading the pen signal state (it's a GPIO | ||
| 171 | * and IRQ). Unfortunately such callback is not always available, | ||
| 172 | * in that case we have rely on the pressure anyway. | ||
| 141 | */ | 173 | */ |
| 174 | if (ts->get_pendown_state) { | ||
| 175 | if (unlikely(!ts->get_pendown_state())) { | ||
| 176 | tsc2007_send_up_event(ts); | ||
| 177 | ts->pendown = false; | ||
| 178 | goto out; | ||
| 179 | } | ||
| 180 | |||
| 181 | dev_dbg(&ts->client->dev, "pen is still down\n"); | ||
| 182 | } | ||
| 183 | |||
| 184 | tsc2007_read_values(ts, &tc); | ||
| 185 | |||
| 186 | rt = tsc2007_calculate_pressure(ts, &tc); | ||
| 142 | if (rt > MAX_12BIT) { | 187 | if (rt > MAX_12BIT) { |
| 188 | /* | ||
| 189 | * Sample found inconsistent by debouncing or pressure is | ||
| 190 | * beyond the maximum. Don't report it to user space, | ||
| 191 | * repeat at least once more the measurement. | ||
| 192 | */ | ||
| 143 | dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt); | 193 | dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt); |
| 194 | goto out; | ||
| 144 | 195 | ||
| 145 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), | ||
| 146 | HRTIMER_MODE_REL); | ||
| 147 | return; | ||
| 148 | } | 196 | } |
| 149 | 197 | ||
| 150 | /* NOTE: We can't rely on the pressure to determine the pen down | ||
| 151 | * state, even this controller has a pressure sensor. The pressure | ||
| 152 | * value can fluctuate for quite a while after lifting the pen and | ||
| 153 | * in some cases may not even settle at the expected value. | ||
| 154 | * | ||
| 155 | * The only safe way to check for the pen up condition is in the | ||
| 156 | * timer by reading the pen signal state (it's a GPIO _and_ IRQ). | ||
| 157 | */ | ||
| 158 | if (rt) { | 198 | if (rt) { |
| 159 | struct input_dev *input = ts->input; | 199 | struct input_dev *input = ts->input; |
| 160 | 200 | ||
| @@ -162,102 +202,74 @@ static void tsc2007_send_event(void *tsc) | |||
| 162 | dev_dbg(&ts->client->dev, "DOWN\n"); | 202 | dev_dbg(&ts->client->dev, "DOWN\n"); |
| 163 | 203 | ||
| 164 | input_report_key(input, BTN_TOUCH, 1); | 204 | input_report_key(input, BTN_TOUCH, 1); |
| 165 | ts->pendown = 1; | 205 | ts->pendown = true; |
| 166 | } | 206 | } |
| 167 | 207 | ||
| 168 | input_report_abs(input, ABS_X, x); | 208 | input_report_abs(input, ABS_X, tc.x); |
| 169 | input_report_abs(input, ABS_Y, y); | 209 | input_report_abs(input, ABS_Y, tc.y); |
| 170 | input_report_abs(input, ABS_PRESSURE, rt); | 210 | input_report_abs(input, ABS_PRESSURE, rt); |
| 171 | 211 | ||
| 172 | input_sync(input); | 212 | input_sync(input); |
| 173 | 213 | ||
| 174 | dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure (%4u)\n", | 214 | dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure (%4u)\n", |
| 175 | x, y, rt); | 215 | tc.x, tc.y, rt); |
| 216 | |||
| 217 | } else if (!ts->get_pendown_state && ts->pendown) { | ||
| 218 | /* | ||
| 219 | * We don't have callback to check pendown state, so we | ||
| 220 | * have to assume that since pressure reported is 0 the | ||
| 221 | * pen was lifted up. | ||
| 222 | */ | ||
| 223 | tsc2007_send_up_event(ts); | ||
| 224 | ts->pendown = false; | ||
| 176 | } | 225 | } |
| 177 | 226 | ||
| 178 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), | 227 | out: |
| 179 | HRTIMER_MODE_REL); | 228 | if (ts->pendown) |
| 180 | } | 229 | schedule_delayed_work(&ts->work, |
| 181 | 230 | msecs_to_jiffies(TS_POLL_PERIOD)); | |
| 182 | static int tsc2007_read_values(struct tsc2007 *tsc) | 231 | else |
| 183 | { | ||
| 184 | /* y- still on; turn on only y+ (and ADC) */ | ||
| 185 | tsc->tc.y = tsc2007_xfer(tsc, READ_Y); | ||
| 186 | |||
| 187 | /* turn y- off, x+ on, then leave in lowpower */ | ||
| 188 | tsc->tc.x = tsc2007_xfer(tsc, READ_X); | ||
| 189 | |||
| 190 | /* turn y+ off, x- on; we'll use formula #1 */ | ||
| 191 | tsc->tc.z1 = tsc2007_xfer(tsc, READ_Z1); | ||
| 192 | tsc->tc.z2 = tsc2007_xfer(tsc, READ_Z2); | ||
| 193 | |||
| 194 | /* power down */ | ||
| 195 | tsc2007_xfer(tsc, PWRDOWN); | ||
| 196 | |||
| 197 | return 0; | ||
| 198 | } | ||
| 199 | |||
| 200 | static enum hrtimer_restart tsc2007_timer(struct hrtimer *handle) | ||
| 201 | { | ||
| 202 | struct tsc2007 *ts = container_of(handle, struct tsc2007, timer); | ||
| 203 | unsigned long flags; | ||
| 204 | |||
| 205 | spin_lock_irqsave(&ts->lock, flags); | ||
| 206 | |||
| 207 | if (unlikely(!ts->get_pendown_state() && ts->pendown)) { | ||
| 208 | struct input_dev *input = ts->input; | ||
| 209 | |||
| 210 | dev_dbg(&ts->client->dev, "UP\n"); | ||
| 211 | |||
| 212 | input_report_key(input, BTN_TOUCH, 0); | ||
| 213 | input_report_abs(input, ABS_PRESSURE, 0); | ||
| 214 | input_sync(input); | ||
| 215 | |||
| 216 | ts->pendown = 0; | ||
| 217 | enable_irq(ts->irq); | 232 | enable_irq(ts->irq); |
| 218 | } else { | ||
| 219 | /* pen is still down, continue with the measurement */ | ||
| 220 | dev_dbg(&ts->client->dev, "pen is still down\n"); | ||
| 221 | |||
| 222 | tsc2007_read_values(ts); | ||
| 223 | tsc2007_send_event(ts); | ||
| 224 | } | ||
| 225 | |||
| 226 | spin_unlock_irqrestore(&ts->lock, flags); | ||
| 227 | |||
| 228 | return HRTIMER_NORESTART; | ||
| 229 | } | 233 | } |
| 230 | 234 | ||
| 231 | static irqreturn_t tsc2007_irq(int irq, void *handle) | 235 | static irqreturn_t tsc2007_irq(int irq, void *handle) |
| 232 | { | 236 | { |
| 233 | struct tsc2007 *ts = handle; | 237 | struct tsc2007 *ts = handle; |
| 234 | unsigned long flags; | ||
| 235 | |||
| 236 | spin_lock_irqsave(&ts->lock, flags); | ||
| 237 | 238 | ||
| 238 | if (likely(ts->get_pendown_state())) { | 239 | if (!ts->get_pendown_state || likely(ts->get_pendown_state())) { |
| 239 | disable_irq_nosync(ts->irq); | 240 | disable_irq_nosync(ts->irq); |
| 240 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY), | 241 | schedule_delayed_work(&ts->work, |
| 241 | HRTIMER_MODE_REL); | 242 | msecs_to_jiffies(TS_POLL_DELAY)); |
| 242 | } | 243 | } |
| 243 | 244 | ||
| 244 | if (ts->clear_penirq) | 245 | if (ts->clear_penirq) |
| 245 | ts->clear_penirq(); | 246 | ts->clear_penirq(); |
| 246 | 247 | ||
| 247 | spin_unlock_irqrestore(&ts->lock, flags); | ||
| 248 | |||
| 249 | return IRQ_HANDLED; | 248 | return IRQ_HANDLED; |
| 250 | } | 249 | } |
| 251 | 250 | ||
| 252 | static int tsc2007_probe(struct i2c_client *client, | 251 | static void tsc2007_free_irq(struct tsc2007 *ts) |
| 253 | const struct i2c_device_id *id) | 252 | { |
| 253 | free_irq(ts->irq, ts); | ||
| 254 | if (cancel_delayed_work_sync(&ts->work)) { | ||
| 255 | /* | ||
| 256 | * Work was pending, therefore we need to enable | ||
| 257 | * IRQ here to balance the disable_irq() done in the | ||
| 258 | * interrupt handler. | ||
| 259 | */ | ||
| 260 | enable_irq(ts->irq); | ||
| 261 | } | ||
| 262 | } | ||
| 263 | |||
| 264 | static int __devinit tsc2007_probe(struct i2c_client *client, | ||
| 265 | const struct i2c_device_id *id) | ||
| 254 | { | 266 | { |
| 255 | struct tsc2007 *ts; | 267 | struct tsc2007 *ts; |
| 256 | struct tsc2007_platform_data *pdata = pdata = client->dev.platform_data; | 268 | struct tsc2007_platform_data *pdata = pdata = client->dev.platform_data; |
| 257 | struct input_dev *input_dev; | 269 | struct input_dev *input_dev; |
| 258 | int err; | 270 | int err; |
| 259 | 271 | ||
| 260 | if (!pdata || !pdata->get_pendown_state) { | 272 | if (!pdata) { |
| 261 | dev_err(&client->dev, "platform data is required!\n"); | 273 | dev_err(&client->dev, "platform data is required!\n"); |
| 262 | return -EINVAL; | 274 | return -EINVAL; |
| 263 | } | 275 | } |
| @@ -274,22 +286,15 @@ static int tsc2007_probe(struct i2c_client *client, | |||
| 274 | } | 286 | } |
| 275 | 287 | ||
| 276 | ts->client = client; | 288 | ts->client = client; |
| 277 | i2c_set_clientdata(client, ts); | 289 | ts->irq = client->irq; |
| 278 | |||
| 279 | ts->input = input_dev; | 290 | ts->input = input_dev; |
| 280 | 291 | INIT_DELAYED_WORK(&ts->work, tsc2007_work); | |
| 281 | hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | ||
| 282 | ts->timer.function = tsc2007_timer; | ||
| 283 | |||
| 284 | spin_lock_init(&ts->lock); | ||
| 285 | 292 | ||
| 286 | ts->model = pdata->model; | 293 | ts->model = pdata->model; |
| 287 | ts->x_plate_ohms = pdata->x_plate_ohms; | 294 | ts->x_plate_ohms = pdata->x_plate_ohms; |
| 288 | ts->get_pendown_state = pdata->get_pendown_state; | 295 | ts->get_pendown_state = pdata->get_pendown_state; |
| 289 | ts->clear_penirq = pdata->clear_penirq; | 296 | ts->clear_penirq = pdata->clear_penirq; |
| 290 | 297 | ||
| 291 | pdata->init_platform_hw(); | ||
| 292 | |||
| 293 | snprintf(ts->phys, sizeof(ts->phys), | 298 | snprintf(ts->phys, sizeof(ts->phys), |
| 294 | "%s/input0", dev_name(&client->dev)); | 299 | "%s/input0", dev_name(&client->dev)); |
| 295 | 300 | ||
| @@ -304,9 +309,8 @@ static int tsc2007_probe(struct i2c_client *client, | |||
| 304 | input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); | 309 | input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); |
| 305 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0); | 310 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0); |
| 306 | 311 | ||
| 307 | tsc2007_read_values(ts); | 312 | if (pdata->init_platform_hw) |
| 308 | 313 | pdata->init_platform_hw(); | |
| 309 | ts->irq = client->irq; | ||
| 310 | 314 | ||
| 311 | err = request_irq(ts->irq, tsc2007_irq, 0, | 315 | err = request_irq(ts->irq, tsc2007_irq, 0, |
| 312 | client->dev.driver->name, ts); | 316 | client->dev.driver->name, ts); |
| @@ -315,33 +319,39 @@ static int tsc2007_probe(struct i2c_client *client, | |||
| 315 | goto err_free_mem; | 319 | goto err_free_mem; |
| 316 | } | 320 | } |
| 317 | 321 | ||
| 322 | /* Prepare for touch readings - power down ADC and enable PENIRQ */ | ||
| 323 | err = tsc2007_xfer(ts, PWRDOWN); | ||
| 324 | if (err < 0) | ||
| 325 | goto err_free_irq; | ||
| 326 | |||
| 318 | err = input_register_device(input_dev); | 327 | err = input_register_device(input_dev); |
| 319 | if (err) | 328 | if (err) |
| 320 | goto err_free_irq; | 329 | goto err_free_irq; |
| 321 | 330 | ||
| 322 | dev_info(&client->dev, "registered with irq (%d)\n", ts->irq); | 331 | i2c_set_clientdata(client, ts); |
| 323 | 332 | ||
| 324 | return 0; | 333 | return 0; |
| 325 | 334 | ||
| 326 | err_free_irq: | 335 | err_free_irq: |
| 327 | free_irq(ts->irq, ts); | 336 | tsc2007_free_irq(ts); |
| 328 | hrtimer_cancel(&ts->timer); | 337 | if (pdata->exit_platform_hw) |
| 338 | pdata->exit_platform_hw(); | ||
| 329 | err_free_mem: | 339 | err_free_mem: |
| 330 | input_free_device(input_dev); | 340 | input_free_device(input_dev); |
| 331 | kfree(ts); | 341 | kfree(ts); |
| 332 | return err; | 342 | return err; |
| 333 | } | 343 | } |
| 334 | 344 | ||
| 335 | static int tsc2007_remove(struct i2c_client *client) | 345 | static int __devexit tsc2007_remove(struct i2c_client *client) |
| 336 | { | 346 | { |
| 337 | struct tsc2007 *ts = i2c_get_clientdata(client); | 347 | struct tsc2007 *ts = i2c_get_clientdata(client); |
| 338 | struct tsc2007_platform_data *pdata; | 348 | struct tsc2007_platform_data *pdata = client->dev.platform_data; |
| 339 | 349 | ||
| 340 | pdata = client->dev.platform_data; | 350 | tsc2007_free_irq(ts); |
| 341 | pdata->exit_platform_hw(); | 351 | |
| 352 | if (pdata->exit_platform_hw) | ||
| 353 | pdata->exit_platform_hw(); | ||
| 342 | 354 | ||
| 343 | free_irq(ts->irq, ts); | ||
| 344 | hrtimer_cancel(&ts->timer); | ||
| 345 | input_unregister_device(ts->input); | 355 | input_unregister_device(ts->input); |
| 346 | kfree(ts); | 356 | kfree(ts); |
| 347 | 357 | ||
| @@ -362,7 +372,7 @@ static struct i2c_driver tsc2007_driver = { | |||
| 362 | }, | 372 | }, |
| 363 | .id_table = tsc2007_idtable, | 373 | .id_table = tsc2007_idtable, |
| 364 | .probe = tsc2007_probe, | 374 | .probe = tsc2007_probe, |
| 365 | .remove = tsc2007_remove, | 375 | .remove = __devexit_p(tsc2007_remove), |
| 366 | }; | 376 | }; |
| 367 | 377 | ||
| 368 | static int __init tsc2007_init(void) | 378 | static int __init tsc2007_init(void) |
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 3a7a58222f83..095f84b1f56e 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c | |||
| @@ -128,9 +128,10 @@ static inline unsigned int ucb1400_ts_read_yres(struct ucb1400_ts *ucb) | |||
| 128 | return ucb1400_adc_read(ucb->ac97, 0, adcsync); | 128 | return ucb1400_adc_read(ucb->ac97, 0, adcsync); |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | static inline int ucb1400_ts_pen_down(struct snd_ac97 *ac97) | 131 | static inline int ucb1400_ts_pen_up(struct snd_ac97 *ac97) |
| 132 | { | 132 | { |
| 133 | unsigned short val = ucb1400_reg_read(ac97, UCB_TS_CR); | 133 | unsigned short val = ucb1400_reg_read(ac97, UCB_TS_CR); |
| 134 | |||
| 134 | return val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW); | 135 | return val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW); |
| 135 | } | 136 | } |
| 136 | 137 | ||
| @@ -209,7 +210,7 @@ static int ucb1400_ts_thread(void *_ucb) | |||
| 209 | 210 | ||
| 210 | msleep(10); | 211 | msleep(10); |
| 211 | 212 | ||
| 212 | if (ucb1400_ts_pen_down(ucb->ac97)) { | 213 | if (ucb1400_ts_pen_up(ucb->ac97)) { |
| 213 | ucb1400_ts_irq_enable(ucb->ac97); | 214 | ucb1400_ts_irq_enable(ucb->ac97); |
| 214 | 215 | ||
| 215 | /* | 216 | /* |
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index fb7cb9bdfbd5..68ece5801a58 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | * - IdealTEK URTC1000 | 13 | * - IdealTEK URTC1000 |
| 14 | * - General Touch | 14 | * - General Touch |
| 15 | * - GoTop Super_Q2/GogoPen/PenPower tablets | 15 | * - GoTop Super_Q2/GogoPen/PenPower tablets |
| 16 | * - JASTEC USB touch controller/DigiTech DTR-02U | ||
| 16 | * | 17 | * |
| 17 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> | 18 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> |
| 18 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) | 19 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) |
| @@ -118,6 +119,8 @@ enum { | |||
| 118 | DEVTYPE_IDEALTEK, | 119 | DEVTYPE_IDEALTEK, |
| 119 | DEVTYPE_GENERAL_TOUCH, | 120 | DEVTYPE_GENERAL_TOUCH, |
| 120 | DEVTYPE_GOTOP, | 121 | DEVTYPE_GOTOP, |
| 122 | DEVTYPE_JASTEC, | ||
| 123 | DEVTYPE_E2I, | ||
| 121 | }; | 124 | }; |
| 122 | 125 | ||
| 123 | #define USB_DEVICE_HID_CLASS(vend, prod) \ | 126 | #define USB_DEVICE_HID_CLASS(vend, prod) \ |
| @@ -191,11 +194,51 @@ static struct usb_device_id usbtouch_devices[] = { | |||
| 191 | {USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP}, | 194 | {USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP}, |
| 192 | #endif | 195 | #endif |
| 193 | 196 | ||
| 197 | #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC | ||
| 198 | {USB_DEVICE(0x0f92, 0x0001), .driver_info = DEVTYPE_JASTEC}, | ||
| 199 | #endif | ||
| 200 | |||
| 201 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I | ||
| 202 | {USB_DEVICE(0x1ac7, 0x0001), .driver_info = DEVTYPE_E2I}, | ||
| 203 | #endif | ||
| 194 | {} | 204 | {} |
| 195 | }; | 205 | }; |
| 196 | 206 | ||
| 197 | 207 | ||
| 198 | /***************************************************************************** | 208 | /***************************************************************************** |
| 209 | * e2i Part | ||
| 210 | */ | ||
| 211 | |||
| 212 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I | ||
| 213 | static int e2i_init(struct usbtouch_usb *usbtouch) | ||
| 214 | { | ||
| 215 | int ret; | ||
| 216 | |||
| 217 | ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), | ||
| 218 | 0x01, 0x02, 0x0000, 0x0081, | ||
| 219 | NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
| 220 | |||
| 221 | dbg("%s - usb_control_msg - E2I_RESET - bytes|err: %d", | ||
| 222 | __func__, ret); | ||
| 223 | return ret; | ||
| 224 | } | ||
| 225 | |||
| 226 | static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
| 227 | { | ||
| 228 | int tmp = (pkt[0] << 8) | pkt[1]; | ||
| 229 | dev->x = (pkt[2] << 8) | pkt[3]; | ||
| 230 | dev->y = (pkt[4] << 8) | pkt[5]; | ||
| 231 | |||
| 232 | tmp = tmp - 0xA000; | ||
| 233 | dev->touch = (tmp > 0); | ||
| 234 | dev->press = (tmp > 0 ? tmp : 0); | ||
| 235 | |||
| 236 | return 1; | ||
| 237 | } | ||
| 238 | #endif | ||
| 239 | |||
| 240 | |||
| 241 | /***************************************************************************** | ||
| 199 | * eGalax part | 242 | * eGalax part |
| 200 | */ | 243 | */ |
| 201 | 244 | ||
| @@ -559,6 +602,21 @@ static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |||
| 559 | dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; | 602 | dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; |
| 560 | dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; | 603 | dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; |
| 561 | dev->touch = pkt[0] & 0x01; | 604 | dev->touch = pkt[0] & 0x01; |
| 605 | |||
| 606 | return 1; | ||
| 607 | } | ||
| 608 | #endif | ||
| 609 | |||
| 610 | /***************************************************************************** | ||
| 611 | * JASTEC Part | ||
| 612 | */ | ||
| 613 | #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC | ||
| 614 | static int jastec_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
| 615 | { | ||
| 616 | dev->x = ((pkt[0] & 0x3f) << 6) | (pkt[2] & 0x3f); | ||
| 617 | dev->y = ((pkt[1] & 0x3f) << 6) | (pkt[3] & 0x3f); | ||
| 618 | dev->touch = (pkt[0] & 0x40) >> 6; | ||
| 619 | |||
| 562 | return 1; | 620 | return 1; |
| 563 | } | 621 | } |
| 564 | #endif | 622 | #endif |
| @@ -702,6 +760,29 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { | |||
| 702 | .read_data = gotop_read_data, | 760 | .read_data = gotop_read_data, |
| 703 | }, | 761 | }, |
| 704 | #endif | 762 | #endif |
| 763 | |||
| 764 | #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC | ||
| 765 | [DEVTYPE_JASTEC] = { | ||
| 766 | .min_xc = 0x0, | ||
| 767 | .max_xc = 0x0fff, | ||
| 768 | .min_yc = 0x0, | ||
| 769 | .max_yc = 0x0fff, | ||
| 770 | .rept_size = 4, | ||
| 771 | .read_data = jastec_read_data, | ||
| 772 | }, | ||
| 773 | #endif | ||
| 774 | |||
| 775 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I | ||
| 776 | [DEVTYPE_E2I] = { | ||
| 777 | .min_xc = 0x0, | ||
| 778 | .max_xc = 0x7fff, | ||
| 779 | .min_yc = 0x0, | ||
| 780 | .max_yc = 0x7fff, | ||
| 781 | .rept_size = 6, | ||
| 782 | .init = e2i_init, | ||
| 783 | .read_data = e2i_read_data, | ||
| 784 | }, | ||
| 785 | #endif | ||
| 705 | }; | 786 | }; |
| 706 | 787 | ||
| 707 | 788 | ||
diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c index 937dfe4e9b12..6ccbdbbf33fe 100644 --- a/drivers/input/touchscreen/w90p910_ts.c +++ b/drivers/input/touchscreen/w90p910_ts.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
| 15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
| 16 | #include <linux/clk.h> | ||
| 16 | #include <linux/input.h> | 17 | #include <linux/input.h> |
| 17 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
| 18 | 19 | ||
| @@ -47,8 +48,8 @@ enum ts_state { | |||
| 47 | struct w90p910_ts { | 48 | struct w90p910_ts { |
| 48 | struct input_dev *input; | 49 | struct input_dev *input; |
| 49 | struct timer_list timer; | 50 | struct timer_list timer; |
| 51 | struct clk *clk; | ||
| 50 | int irq_num; | 52 | int irq_num; |
| 51 | void __iomem *clocken; | ||
| 52 | void __iomem *ts_reg; | 53 | void __iomem *ts_reg; |
| 53 | spinlock_t lock; | 54 | spinlock_t lock; |
| 54 | enum ts_state state; | 55 | enum ts_state state; |
| @@ -166,8 +167,7 @@ static int w90p910_open(struct input_dev *dev) | |||
| 166 | unsigned long val; | 167 | unsigned long val; |
| 167 | 168 | ||
| 168 | /* enable the ADC clock */ | 169 | /* enable the ADC clock */ |
| 169 | val = __raw_readl(w90p910_ts->clocken); | 170 | clk_enable(w90p910_ts->clk); |
| 170 | __raw_writel(val | ADC_CLK_EN, w90p910_ts->clocken); | ||
| 171 | 171 | ||
| 172 | __raw_writel(ADC_RST1, w90p910_ts->ts_reg); | 172 | __raw_writel(ADC_RST1, w90p910_ts->ts_reg); |
| 173 | msleep(1); | 173 | msleep(1); |
| @@ -211,8 +211,7 @@ static void w90p910_close(struct input_dev *dev) | |||
| 211 | del_timer_sync(&w90p910_ts->timer); | 211 | del_timer_sync(&w90p910_ts->timer); |
| 212 | 212 | ||
| 213 | /* stop the ADC clock */ | 213 | /* stop the ADC clock */ |
| 214 | val = __raw_readl(w90p910_ts->clocken); | 214 | clk_disable(w90p910_ts->clk); |
| 215 | __raw_writel(val & ~ADC_CLK_EN, w90p910_ts->clocken); | ||
| 216 | } | 215 | } |
| 217 | 216 | ||
| 218 | static int __devinit w90x900ts_probe(struct platform_device *pdev) | 217 | static int __devinit w90x900ts_probe(struct platform_device *pdev) |
| @@ -241,26 +240,24 @@ static int __devinit w90x900ts_probe(struct platform_device *pdev) | |||
| 241 | goto fail1; | 240 | goto fail1; |
| 242 | } | 241 | } |
| 243 | 242 | ||
| 244 | if (!request_mem_region(res->start, res->end - res->start + 1, | 243 | if (!request_mem_region(res->start, resource_size(res), |
| 245 | pdev->name)) { | 244 | pdev->name)) { |
| 246 | err = -EBUSY; | 245 | err = -EBUSY; |
| 247 | goto fail1; | 246 | goto fail1; |
| 248 | } | 247 | } |
| 249 | 248 | ||
| 250 | w90p910_ts->ts_reg = ioremap(res->start, res->end - res->start + 1); | 249 | w90p910_ts->ts_reg = ioremap(res->start, resource_size(res)); |
| 251 | if (!w90p910_ts->ts_reg) { | 250 | if (!w90p910_ts->ts_reg) { |
| 252 | err = -ENOMEM; | 251 | err = -ENOMEM; |
| 253 | goto fail2; | 252 | goto fail2; |
| 254 | } | 253 | } |
| 255 | 254 | ||
| 256 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 255 | w90p910_ts->clk = clk_get(&pdev->dev, NULL); |
| 257 | if (!res) { | 256 | if (IS_ERR(w90p910_ts->clk)) { |
| 258 | err = -ENXIO; | 257 | err = PTR_ERR(w90p910_ts->clk); |
| 259 | goto fail3; | 258 | goto fail3; |
| 260 | } | 259 | } |
| 261 | 260 | ||
| 262 | w90p910_ts->clocken = (void __iomem *)res->start; | ||
| 263 | |||
| 264 | input_dev->name = "W90P910 TouchScreen"; | 261 | input_dev->name = "W90P910 TouchScreen"; |
| 265 | input_dev->phys = "w90p910ts/event0"; | 262 | input_dev->phys = "w90p910ts/event0"; |
| 266 | input_dev->id.bustype = BUS_HOST; | 263 | input_dev->id.bustype = BUS_HOST; |
| @@ -283,20 +280,21 @@ static int __devinit w90x900ts_probe(struct platform_device *pdev) | |||
| 283 | if (request_irq(w90p910_ts->irq_num, w90p910_ts_interrupt, | 280 | if (request_irq(w90p910_ts->irq_num, w90p910_ts_interrupt, |
| 284 | IRQF_DISABLED, "w90p910ts", w90p910_ts)) { | 281 | IRQF_DISABLED, "w90p910ts", w90p910_ts)) { |
| 285 | err = -EBUSY; | 282 | err = -EBUSY; |
| 286 | goto fail3; | 283 | goto fail4; |
| 287 | } | 284 | } |
| 288 | 285 | ||
| 289 | err = input_register_device(w90p910_ts->input); | 286 | err = input_register_device(w90p910_ts->input); |
| 290 | if (err) | 287 | if (err) |
| 291 | goto fail4; | 288 | goto fail5; |
| 292 | 289 | ||
| 293 | platform_set_drvdata(pdev, w90p910_ts); | 290 | platform_set_drvdata(pdev, w90p910_ts); |
| 294 | 291 | ||
| 295 | return 0; | 292 | return 0; |
| 296 | 293 | ||
| 297 | fail4: free_irq(w90p910_ts->irq_num, w90p910_ts); | 294 | fail5: free_irq(w90p910_ts->irq_num, w90p910_ts); |
| 295 | fail4: clk_put(w90p910_ts->clk); | ||
| 298 | fail3: iounmap(w90p910_ts->ts_reg); | 296 | fail3: iounmap(w90p910_ts->ts_reg); |
| 299 | fail2: release_mem_region(res->start, res->end - res->start + 1); | 297 | fail2: release_mem_region(res->start, resource_size(res)); |
| 300 | fail1: input_free_device(input_dev); | 298 | fail1: input_free_device(input_dev); |
| 301 | kfree(w90p910_ts); | 299 | kfree(w90p910_ts); |
| 302 | return err; | 300 | return err; |
| @@ -311,8 +309,10 @@ static int __devexit w90x900ts_remove(struct platform_device *pdev) | |||
| 311 | del_timer_sync(&w90p910_ts->timer); | 309 | del_timer_sync(&w90p910_ts->timer); |
| 312 | iounmap(w90p910_ts->ts_reg); | 310 | iounmap(w90p910_ts->ts_reg); |
| 313 | 311 | ||
| 312 | clk_put(w90p910_ts->clk); | ||
| 313 | |||
| 314 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 314 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 315 | release_mem_region(res->start, res->end - res->start + 1); | 315 | release_mem_region(res->start, resource_size(res)); |
| 316 | 316 | ||
| 317 | input_unregister_device(w90p910_ts->input); | 317 | input_unregister_device(w90p910_ts->input); |
| 318 | kfree(w90p910_ts); | 318 | kfree(w90p910_ts); |
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 2f33a0167644..56dc35c94bb1 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c | |||
| @@ -25,18 +25,16 @@ MODULE_AUTHOR("Jaya Kumar <jayakumar.lkml@gmail.com>"); | |||
| 25 | MODULE_DESCRIPTION(DRIVER_DESC); | 25 | MODULE_DESCRIPTION(DRIVER_DESC); |
| 26 | MODULE_LICENSE("GPL"); | 26 | MODULE_LICENSE("GPL"); |
| 27 | 27 | ||
| 28 | /* | ||
| 29 | * Definitions & global arrays. | ||
| 30 | */ | ||
| 31 | |||
| 32 | #define W8001_MAX_LENGTH 11 | 28 | #define W8001_MAX_LENGTH 11 |
| 33 | #define W8001_PACKET_LEN 11 | 29 | #define W8001_LEAD_MASK 0x80 |
| 34 | #define W8001_LEAD_MASK 0x80 | 30 | #define W8001_LEAD_BYTE 0x80 |
| 35 | #define W8001_LEAD_BYTE 0x80 | 31 | #define W8001_TAB_MASK 0x40 |
| 36 | #define W8001_TAB_MASK 0x40 | 32 | #define W8001_TAB_BYTE 0x40 |
| 37 | #define W8001_TAB_BYTE 0x40 | ||
| 38 | 33 | ||
| 39 | #define W8001_QUERY_PACKET 0x20 | 34 | #define W8001_QUERY_PACKET 0x20 |
| 35 | |||
| 36 | #define W8001_CMD_START '1' | ||
| 37 | #define W8001_CMD_QUERY '*' | ||
| 40 | 38 | ||
| 41 | struct w8001_coord { | 39 | struct w8001_coord { |
| 42 | u8 rdy; | 40 | u8 rdy; |
| @@ -57,18 +55,19 @@ struct w8001_coord { | |||
| 57 | struct w8001 { | 55 | struct w8001 { |
| 58 | struct input_dev *dev; | 56 | struct input_dev *dev; |
| 59 | struct serio *serio; | 57 | struct serio *serio; |
| 60 | struct mutex cmd_mutex; | ||
| 61 | struct completion cmd_done; | 58 | struct completion cmd_done; |
| 62 | int id; | 59 | int id; |
| 63 | int idx; | 60 | int idx; |
| 64 | unsigned char expected_packet; | 61 | unsigned char response_type; |
| 62 | unsigned char response[W8001_MAX_LENGTH]; | ||
| 65 | unsigned char data[W8001_MAX_LENGTH]; | 63 | unsigned char data[W8001_MAX_LENGTH]; |
| 66 | unsigned char response[W8001_PACKET_LEN]; | ||
| 67 | char phys[32]; | 64 | char phys[32]; |
| 68 | }; | 65 | }; |
| 69 | 66 | ||
| 70 | static int parse_data(u8 *data, struct w8001_coord *coord) | 67 | static void parse_data(u8 *data, struct w8001_coord *coord) |
| 71 | { | 68 | { |
| 69 | memset(coord, 0, sizeof(*coord)); | ||
| 70 | |||
| 72 | coord->rdy = data[0] & 0x20; | 71 | coord->rdy = data[0] & 0x20; |
| 73 | coord->tsw = data[0] & 0x01; | 72 | coord->tsw = data[0] & 0x01; |
| 74 | coord->f1 = data[0] & 0x02; | 73 | coord->f1 = data[0] & 0x02; |
| @@ -87,15 +86,15 @@ static int parse_data(u8 *data, struct w8001_coord *coord) | |||
| 87 | 86 | ||
| 88 | coord->tilt_x = data[7] & 0x7F; | 87 | coord->tilt_x = data[7] & 0x7F; |
| 89 | coord->tilt_y = data[8] & 0x7F; | 88 | coord->tilt_y = data[8] & 0x7F; |
| 90 | |||
| 91 | return 0; | ||
| 92 | } | 89 | } |
| 93 | 90 | ||
| 94 | static void w8001_process_data(struct w8001 *w8001, unsigned char data) | 91 | static irqreturn_t w8001_interrupt(struct serio *serio, |
| 92 | unsigned char data, unsigned int flags) | ||
| 95 | { | 93 | { |
| 94 | struct w8001 *w8001 = serio_get_drvdata(serio); | ||
| 96 | struct input_dev *dev = w8001->dev; | 95 | struct input_dev *dev = w8001->dev; |
| 97 | u8 tmp; | ||
| 98 | struct w8001_coord coord; | 96 | struct w8001_coord coord; |
| 97 | unsigned char tmp; | ||
| 99 | 98 | ||
| 100 | w8001->data[w8001->idx] = data; | 99 | w8001->data[w8001->idx] = data; |
| 101 | switch (w8001->idx++) { | 100 | switch (w8001->idx++) { |
| @@ -105,12 +104,13 @@ static void w8001_process_data(struct w8001 *w8001, unsigned char data) | |||
| 105 | w8001->idx = 0; | 104 | w8001->idx = 0; |
| 106 | } | 105 | } |
| 107 | break; | 106 | break; |
| 107 | |||
| 108 | case 8: | 108 | case 8: |
| 109 | tmp = w8001->data[0] & W8001_TAB_MASK; | 109 | tmp = w8001->data[0] & W8001_TAB_MASK; |
| 110 | if (unlikely(tmp == W8001_TAB_BYTE)) | 110 | if (unlikely(tmp == W8001_TAB_BYTE)) |
| 111 | break; | 111 | break; |
| 112 | |||
| 112 | w8001->idx = 0; | 113 | w8001->idx = 0; |
| 113 | memset(&coord, 0, sizeof(coord)); | ||
| 114 | parse_data(w8001->data, &coord); | 114 | parse_data(w8001->data, &coord); |
| 115 | input_report_abs(dev, ABS_X, coord.x); | 115 | input_report_abs(dev, ABS_X, coord.x); |
| 116 | input_report_abs(dev, ABS_Y, coord.y); | 116 | input_report_abs(dev, ABS_Y, coord.y); |
| @@ -118,86 +118,48 @@ static void w8001_process_data(struct w8001 *w8001, unsigned char data) | |||
| 118 | input_report_key(dev, BTN_TOUCH, coord.tsw); | 118 | input_report_key(dev, BTN_TOUCH, coord.tsw); |
| 119 | input_sync(dev); | 119 | input_sync(dev); |
| 120 | break; | 120 | break; |
| 121 | |||
| 121 | case 10: | 122 | case 10: |
| 122 | w8001->idx = 0; | 123 | w8001->idx = 0; |
| 123 | memcpy(w8001->response, &w8001->data, W8001_PACKET_LEN); | 124 | memcpy(w8001->response, w8001->data, W8001_MAX_LENGTH); |
| 124 | w8001->expected_packet = W8001_QUERY_PACKET; | 125 | w8001->response_type = W8001_QUERY_PACKET; |
| 125 | complete(&w8001->cmd_done); | 126 | complete(&w8001->cmd_done); |
| 126 | break; | 127 | break; |
| 127 | } | 128 | } |
| 128 | } | ||
| 129 | |||
| 130 | |||
| 131 | static irqreturn_t w8001_interrupt(struct serio *serio, | ||
| 132 | unsigned char data, unsigned int flags) | ||
| 133 | { | ||
| 134 | struct w8001 *w8001 = serio_get_drvdata(serio); | ||
| 135 | |||
| 136 | w8001_process_data(w8001, data); | ||
| 137 | 129 | ||
| 138 | return IRQ_HANDLED; | 130 | return IRQ_HANDLED; |
| 139 | } | 131 | } |
| 140 | 132 | ||
| 141 | static int w8001_async_command(struct w8001 *w8001, unsigned char *packet, | 133 | static int w8001_command(struct w8001 *w8001, unsigned char command, |
| 142 | int len) | 134 | bool wait_response) |
| 143 | { | ||
| 144 | int rc = -1; | ||
| 145 | int i; | ||
| 146 | |||
| 147 | mutex_lock(&w8001->cmd_mutex); | ||
| 148 | |||
| 149 | for (i = 0; i < len; i++) { | ||
| 150 | if (serio_write(w8001->serio, packet[i])) | ||
| 151 | goto out; | ||
| 152 | } | ||
| 153 | rc = 0; | ||
| 154 | |||
| 155 | out: | ||
| 156 | mutex_unlock(&w8001->cmd_mutex); | ||
| 157 | return rc; | ||
| 158 | } | ||
| 159 | |||
| 160 | static int w8001_command(struct w8001 *w8001, unsigned char *packet, int len) | ||
| 161 | { | 135 | { |
| 162 | int rc = -1; | 136 | int rc; |
| 163 | int i; | ||
| 164 | 137 | ||
| 165 | mutex_lock(&w8001->cmd_mutex); | 138 | w8001->response_type = 0; |
| 166 | |||
| 167 | serio_pause_rx(w8001->serio); | ||
| 168 | init_completion(&w8001->cmd_done); | 139 | init_completion(&w8001->cmd_done); |
| 169 | serio_continue_rx(w8001->serio); | ||
| 170 | |||
| 171 | for (i = 0; i < len; i++) { | ||
| 172 | if (serio_write(w8001->serio, packet[i])) | ||
| 173 | goto out; | ||
| 174 | } | ||
| 175 | 140 | ||
| 176 | wait_for_completion_timeout(&w8001->cmd_done, HZ); | 141 | rc = serio_write(w8001->serio, command); |
| 142 | if (rc == 0 && wait_response) { | ||
| 177 | 143 | ||
| 178 | if (w8001->expected_packet == W8001_QUERY_PACKET) { | 144 | wait_for_completion_timeout(&w8001->cmd_done, HZ); |
| 179 | /* We are back in reporting mode, the query was ACKed */ | 145 | if (w8001->response_type != W8001_QUERY_PACKET) |
| 180 | memcpy(packet, w8001->response, W8001_PACKET_LEN); | 146 | rc = -EIO; |
| 181 | rc = 0; | ||
| 182 | } | 147 | } |
| 183 | 148 | ||
| 184 | out: | ||
| 185 | mutex_unlock(&w8001->cmd_mutex); | ||
| 186 | return rc; | 149 | return rc; |
| 187 | } | 150 | } |
| 188 | 151 | ||
| 189 | static int w8001_setup(struct w8001 *w8001) | 152 | static int w8001_setup(struct w8001 *w8001) |
| 190 | { | 153 | { |
| 191 | struct w8001_coord coord; | ||
| 192 | struct input_dev *dev = w8001->dev; | 154 | struct input_dev *dev = w8001->dev; |
| 193 | unsigned char start[1] = { '1' }; | 155 | struct w8001_coord coord; |
| 194 | unsigned char query[11] = { '*' }; | 156 | int error; |
| 195 | 157 | ||
| 196 | if (w8001_command(w8001, query, 1)) | 158 | error = w8001_command(w8001, W8001_CMD_QUERY, true); |
| 197 | return -1; | 159 | if (error) |
| 160 | return error; | ||
| 198 | 161 | ||
| 199 | memset(&coord, 0, sizeof(coord)); | 162 | parse_data(w8001->response, &coord); |
| 200 | parse_data(query, &coord); | ||
| 201 | 163 | ||
| 202 | input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0); | 164 | input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0); |
| 203 | input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0); | 165 | input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0); |
| @@ -205,10 +167,7 @@ static int w8001_setup(struct w8001 *w8001) | |||
| 205 | input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0); | 167 | input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0); |
| 206 | input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0); | 168 | input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0); |
| 207 | 169 | ||
| 208 | if (w8001_async_command(w8001, start, 1)) | 170 | return w8001_command(w8001, W8001_CMD_START, false); |
| 209 | return -1; | ||
| 210 | |||
| 211 | return 0; | ||
| 212 | } | 171 | } |
| 213 | 172 | ||
| 214 | /* | 173 | /* |
| @@ -249,7 +208,6 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) | |||
| 249 | w8001->serio = serio; | 208 | w8001->serio = serio; |
| 250 | w8001->id = serio->id.id; | 209 | w8001->id = serio->id.id; |
| 251 | w8001->dev = input_dev; | 210 | w8001->dev = input_dev; |
| 252 | mutex_init(&w8001->cmd_mutex); | ||
| 253 | init_completion(&w8001->cmd_done); | 211 | init_completion(&w8001->cmd_done); |
| 254 | snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys); | 212 | snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys); |
| 255 | 213 | ||
| @@ -269,7 +227,8 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) | |||
| 269 | if (err) | 227 | if (err) |
| 270 | goto fail2; | 228 | goto fail2; |
| 271 | 229 | ||
| 272 | if (w8001_setup(w8001)) | 230 | err = w8001_setup(w8001); |
| 231 | if (err) | ||
| 273 | goto fail3; | 232 | goto fail3; |
| 274 | 233 | ||
| 275 | err = input_register_device(w8001->dev); | 234 | err = input_register_device(w8001->dev); |
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index 2957d48e0045..252eb11fe9db 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c | |||
| @@ -204,7 +204,7 @@ void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio, | |||
| 204 | else | 204 | else |
| 205 | reg &= ~gpio; | 205 | reg &= ~gpio; |
| 206 | 206 | ||
| 207 | if (wm->id == WM9712_ID2) | 207 | if (wm->id == WM9712_ID2 && wm->variant != WM97xx_WM1613) |
| 208 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg << 1); | 208 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg << 1); |
| 209 | else | 209 | else |
| 210 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg); | 210 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg); |
| @@ -307,7 +307,7 @@ static void wm97xx_pen_irq_worker(struct work_struct *work) | |||
| 307 | WM97XX_GPIO_13); | 307 | WM97XX_GPIO_13); |
| 308 | } | 308 | } |
| 309 | 309 | ||
| 310 | if (wm->id == WM9712_ID2) | 310 | if (wm->id == WM9712_ID2 && wm->variant != WM97xx_WM1613) |
| 311 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, (status & | 311 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, (status & |
| 312 | ~WM97XX_GPIO_13) << 1); | 312 | ~WM97XX_GPIO_13) << 1); |
| 313 | else | 313 | else |
| @@ -582,6 +582,8 @@ static int wm97xx_probe(struct device *dev) | |||
| 582 | 582 | ||
| 583 | wm->id = wm97xx_reg_read(wm, AC97_VENDOR_ID2); | 583 | wm->id = wm97xx_reg_read(wm, AC97_VENDOR_ID2); |
| 584 | 584 | ||
| 585 | wm->variant = WM97xx_GENERIC; | ||
| 586 | |||
| 585 | dev_info(wm->dev, "detected a wm97%02x codec\n", wm->id & 0xff); | 587 | dev_info(wm->dev, "detected a wm97%02x codec\n", wm->id & 0xff); |
| 586 | 588 | ||
| 587 | switch (wm->id & 0xff) { | 589 | switch (wm->id & 0xff) { |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index f99bc7f089f1..a7eb7277b106 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
| @@ -575,7 +575,7 @@ static void pci_pm_complete(struct device *dev) | |||
| 575 | static int pci_pm_suspend(struct device *dev) | 575 | static int pci_pm_suspend(struct device *dev) |
| 576 | { | 576 | { |
| 577 | struct pci_dev *pci_dev = to_pci_dev(dev); | 577 | struct pci_dev *pci_dev = to_pci_dev(dev); |
| 578 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 578 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
| 579 | 579 | ||
| 580 | if (pci_has_legacy_pm_support(pci_dev)) | 580 | if (pci_has_legacy_pm_support(pci_dev)) |
| 581 | return pci_legacy_suspend(dev, PMSG_SUSPEND); | 581 | return pci_legacy_suspend(dev, PMSG_SUSPEND); |
| @@ -613,7 +613,7 @@ static int pci_pm_suspend(struct device *dev) | |||
| 613 | static int pci_pm_suspend_noirq(struct device *dev) | 613 | static int pci_pm_suspend_noirq(struct device *dev) |
| 614 | { | 614 | { |
| 615 | struct pci_dev *pci_dev = to_pci_dev(dev); | 615 | struct pci_dev *pci_dev = to_pci_dev(dev); |
| 616 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 616 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
| 617 | 617 | ||
| 618 | if (pci_has_legacy_pm_support(pci_dev)) | 618 | if (pci_has_legacy_pm_support(pci_dev)) |
| 619 | return pci_legacy_suspend_late(dev, PMSG_SUSPEND); | 619 | return pci_legacy_suspend_late(dev, PMSG_SUSPEND); |
| @@ -672,7 +672,7 @@ static int pci_pm_resume_noirq(struct device *dev) | |||
| 672 | static int pci_pm_resume(struct device *dev) | 672 | static int pci_pm_resume(struct device *dev) |
| 673 | { | 673 | { |
| 674 | struct pci_dev *pci_dev = to_pci_dev(dev); | 674 | struct pci_dev *pci_dev = to_pci_dev(dev); |
| 675 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 675 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
| 676 | int error = 0; | 676 | int error = 0; |
| 677 | 677 | ||
| 678 | /* | 678 | /* |
| @@ -711,7 +711,7 @@ static int pci_pm_resume(struct device *dev) | |||
| 711 | static int pci_pm_freeze(struct device *dev) | 711 | static int pci_pm_freeze(struct device *dev) |
| 712 | { | 712 | { |
| 713 | struct pci_dev *pci_dev = to_pci_dev(dev); | 713 | struct pci_dev *pci_dev = to_pci_dev(dev); |
| 714 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 714 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
| 715 | 715 | ||
| 716 | if (pci_has_legacy_pm_support(pci_dev)) | 716 | if (pci_has_legacy_pm_support(pci_dev)) |
| 717 | return pci_legacy_suspend(dev, PMSG_FREEZE); | 717 | return pci_legacy_suspend(dev, PMSG_FREEZE); |
| @@ -780,7 +780,7 @@ static int pci_pm_thaw_noirq(struct device *dev) | |||
| 780 | static int pci_pm_thaw(struct device *dev) | 780 | static int pci_pm_thaw(struct device *dev) |
| 781 | { | 781 | { |
| 782 | struct pci_dev *pci_dev = to_pci_dev(dev); | 782 | struct pci_dev *pci_dev = to_pci_dev(dev); |
| 783 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 783 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
| 784 | int error = 0; | 784 | int error = 0; |
| 785 | 785 | ||
| 786 | if (pci_has_legacy_pm_support(pci_dev)) | 786 | if (pci_has_legacy_pm_support(pci_dev)) |
| @@ -799,7 +799,7 @@ static int pci_pm_thaw(struct device *dev) | |||
| 799 | static int pci_pm_poweroff(struct device *dev) | 799 | static int pci_pm_poweroff(struct device *dev) |
| 800 | { | 800 | { |
| 801 | struct pci_dev *pci_dev = to_pci_dev(dev); | 801 | struct pci_dev *pci_dev = to_pci_dev(dev); |
| 802 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 802 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
| 803 | 803 | ||
| 804 | if (pci_has_legacy_pm_support(pci_dev)) | 804 | if (pci_has_legacy_pm_support(pci_dev)) |
| 805 | return pci_legacy_suspend(dev, PMSG_HIBERNATE); | 805 | return pci_legacy_suspend(dev, PMSG_HIBERNATE); |
| @@ -872,7 +872,7 @@ static int pci_pm_restore_noirq(struct device *dev) | |||
| 872 | static int pci_pm_restore(struct device *dev) | 872 | static int pci_pm_restore(struct device *dev) |
| 873 | { | 873 | { |
| 874 | struct pci_dev *pci_dev = to_pci_dev(dev); | 874 | struct pci_dev *pci_dev = to_pci_dev(dev); |
| 875 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 875 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
| 876 | int error = 0; | 876 | int error = 0; |
| 877 | 877 | ||
| 878 | /* | 878 | /* |
| @@ -910,7 +910,7 @@ static int pci_pm_restore(struct device *dev) | |||
| 910 | 910 | ||
| 911 | #endif /* !CONFIG_HIBERNATION */ | 911 | #endif /* !CONFIG_HIBERNATION */ |
| 912 | 912 | ||
| 913 | struct dev_pm_ops pci_dev_pm_ops = { | 913 | const struct dev_pm_ops pci_dev_pm_ops = { |
| 914 | .prepare = pci_pm_prepare, | 914 | .prepare = pci_pm_prepare, |
| 915 | .complete = pci_pm_complete, | 915 | .complete = pci_pm_complete, |
| 916 | .suspend = pci_pm_suspend, | 916 | .suspend = pci_pm_suspend, |
diff --git a/include/linux/device.h b/include/linux/device.h index aebb81036db2..a28642975053 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
| @@ -62,7 +62,7 @@ struct bus_type { | |||
| 62 | int (*suspend)(struct device *dev, pm_message_t state); | 62 | int (*suspend)(struct device *dev, pm_message_t state); |
| 63 | int (*resume)(struct device *dev); | 63 | int (*resume)(struct device *dev); |
| 64 | 64 | ||
| 65 | struct dev_pm_ops *pm; | 65 | const struct dev_pm_ops *pm; |
| 66 | 66 | ||
| 67 | struct bus_type_private *p; | 67 | struct bus_type_private *p; |
| 68 | }; | 68 | }; |
| @@ -132,7 +132,7 @@ struct device_driver { | |||
| 132 | int (*resume) (struct device *dev); | 132 | int (*resume) (struct device *dev); |
| 133 | struct attribute_group **groups; | 133 | struct attribute_group **groups; |
| 134 | 134 | ||
| 135 | struct dev_pm_ops *pm; | 135 | const struct dev_pm_ops *pm; |
| 136 | 136 | ||
| 137 | struct driver_private *p; | 137 | struct driver_private *p; |
| 138 | }; | 138 | }; |
| @@ -200,7 +200,8 @@ struct class { | |||
| 200 | int (*suspend)(struct device *dev, pm_message_t state); | 200 | int (*suspend)(struct device *dev, pm_message_t state); |
| 201 | int (*resume)(struct device *dev); | 201 | int (*resume)(struct device *dev); |
| 202 | 202 | ||
| 203 | struct dev_pm_ops *pm; | 203 | const struct dev_pm_ops *pm; |
| 204 | |||
| 204 | struct class_private *p; | 205 | struct class_private *p; |
| 205 | }; | 206 | }; |
| 206 | 207 | ||
| @@ -291,7 +292,7 @@ struct device_type { | |||
| 291 | char *(*nodename)(struct device *dev); | 292 | char *(*nodename)(struct device *dev); |
| 292 | void (*release)(struct device *dev); | 293 | void (*release)(struct device *dev); |
| 293 | 294 | ||
| 294 | struct dev_pm_ops *pm; | 295 | const struct dev_pm_ops *pm; |
| 295 | }; | 296 | }; |
| 296 | 297 | ||
| 297 | /* interface for exporting device attributes */ | 298 | /* interface for exporting device attributes */ |
diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl4030.h index 0dc80ef24975..3fd21d7cb6bf 100644 --- a/include/linux/i2c/twl4030.h +++ b/include/linux/i2c/twl4030.h | |||
| @@ -25,6 +25,9 @@ | |||
| 25 | #ifndef __TWL4030_H_ | 25 | #ifndef __TWL4030_H_ |
| 26 | #define __TWL4030_H_ | 26 | #define __TWL4030_H_ |
| 27 | 27 | ||
| 28 | #include <linux/types.h> | ||
| 29 | #include <linux/input/matrix_keypad.h> | ||
| 30 | |||
| 28 | /* | 31 | /* |
| 29 | * Using the twl4030 core we address registers using a pair | 32 | * Using the twl4030 core we address registers using a pair |
| 30 | * { module id, relative register offset } | 33 | * { module id, relative register offset } |
| @@ -302,13 +305,17 @@ struct twl4030_madc_platform_data { | |||
| 302 | int irq_line; | 305 | int irq_line; |
| 303 | }; | 306 | }; |
| 304 | 307 | ||
| 308 | /* Boards have uniqe mappings of {col, row} --> keycode. | ||
| 309 | * Column and row are 4 bits, but range only from 0..7. | ||
| 310 | * a PERSISTENT_KEY is "always on" and never reported. | ||
| 311 | */ | ||
| 312 | #define PERSISTENT_KEY(c, r) KEY((c), (r), KEY_RESERVED) | ||
| 313 | |||
| 305 | struct twl4030_keypad_data { | 314 | struct twl4030_keypad_data { |
| 306 | int rows; | 315 | const struct matrix_keymap_data *keymap_data; |
| 307 | int cols; | 316 | unsigned rows; |
| 308 | int *keymap; | 317 | unsigned cols; |
| 309 | int irq; | 318 | bool rep; |
| 310 | unsigned int keymapsize; | ||
| 311 | unsigned int rep:1; | ||
| 312 | }; | 319 | }; |
| 313 | 320 | ||
| 314 | enum twl4030_usb_mode { | 321 | enum twl4030_usb_mode { |
diff --git a/include/linux/input/eeti_ts.h b/include/linux/input/eeti_ts.h new file mode 100644 index 000000000000..f875b316249d --- /dev/null +++ b/include/linux/input/eeti_ts.h | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | #ifndef LINUX_INPUT_EETI_TS_H | ||
| 2 | #define LINUX_INPUT_EETI_TS_H | ||
| 3 | |||
| 4 | struct eeti_ts_platform_data { | ||
| 5 | unsigned int irq_active_high; | ||
| 6 | }; | ||
| 7 | |||
| 8 | #endif /* LINUX_INPUT_EETI_TS_H */ | ||
| 9 | |||
diff --git a/include/linux/input/matrix_keypad.h b/include/linux/input/matrix_keypad.h index 15d5903af2dd..b3cd42d50e16 100644 --- a/include/linux/input/matrix_keypad.h +++ b/include/linux/input/matrix_keypad.h | |||
| @@ -63,4 +63,36 @@ struct matrix_keypad_platform_data { | |||
| 63 | bool wakeup; | 63 | bool wakeup; |
| 64 | }; | 64 | }; |
| 65 | 65 | ||
| 66 | /** | ||
| 67 | * matrix_keypad_build_keymap - convert platform keymap into matrix keymap | ||
| 68 | * @keymap_data: keymap supplied by the platform code | ||
| 69 | * @row_shift: number of bits to shift row value by to advance to the next | ||
| 70 | * line in the keymap | ||
| 71 | * @keymap: expanded version of keymap that is suitable for use by | ||
| 72 | * matrix keyboad driver | ||
| 73 | * @keybit: pointer to bitmap of keys supported by input device | ||
| 74 | * | ||
| 75 | * This function converts platform keymap (encoded with KEY() macro) into | ||
| 76 | * an array of keycodes that is suitable for using in a standard matrix | ||
| 77 | * keyboard driver that uses row and col as indices. | ||
| 78 | */ | ||
| 79 | static inline void | ||
| 80 | matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data, | ||
| 81 | unsigned int row_shift, | ||
| 82 | unsigned short *keymap, unsigned long *keybit) | ||
| 83 | { | ||
| 84 | int i; | ||
| 85 | |||
| 86 | for (i = 0; i < keymap_data->keymap_size; i++) { | ||
| 87 | unsigned int key = keymap_data->keymap[i]; | ||
| 88 | unsigned int row = KEY_ROW(key); | ||
| 89 | unsigned int col = KEY_COL(key); | ||
| 90 | unsigned short code = KEY_VAL(key); | ||
| 91 | |||
| 92 | keymap[MATRIX_SCAN_CODE(row, col, row_shift)] = code; | ||
| 93 | __set_bit(code, keybit); | ||
| 94 | } | ||
| 95 | __clear_bit(KEY_RESERVED, keybit); | ||
| 96 | } | ||
| 97 | |||
| 66 | #endif /* _MATRIX_KEYPAD_H */ | 98 | #endif /* _MATRIX_KEYPAD_H */ |
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 { | |||
| 44 | void ps2_init(struct ps2dev *ps2dev, struct serio *serio); | 44 | void ps2_init(struct ps2dev *ps2dev, struct serio *serio); |
| 45 | int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout); | 45 | int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout); |
| 46 | void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout); | 46 | void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout); |
| 47 | int __ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command); | ||
| 47 | int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command); | 48 | int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command); |
| 48 | int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data); | 49 | int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data); |
| 49 | int ps2_handle_response(struct ps2dev *ps2dev, unsigned char data); | 50 | int ps2_handle_response(struct ps2dev *ps2dev, unsigned char data); |
diff --git a/include/linux/serio.h b/include/linux/serio.h index 126d24c9eaa8..a640bc2afe76 100644 --- a/include/linux/serio.h +++ b/include/linux/serio.h | |||
| @@ -31,8 +31,6 @@ struct serio { | |||
| 31 | 31 | ||
| 32 | bool manual_bind; | 32 | bool manual_bind; |
| 33 | bool registered; /* port has been fully registered with driver core */ | 33 | bool registered; /* port has been fully registered with driver core */ |
| 34 | bool suspended; /* port is suspended */ | ||
| 35 | |||
| 36 | 34 | ||
| 37 | struct serio_device_id id; | 35 | struct serio_device_id id; |
| 38 | 36 | ||
diff --git a/include/linux/wm97xx.h b/include/linux/wm97xx.h index 6f69968eab24..0c9878123d5f 100644 --- a/include/linux/wm97xx.h +++ b/include/linux/wm97xx.h | |||
| @@ -16,6 +16,12 @@ | |||
| 16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
| 17 | 17 | ||
| 18 | /* | 18 | /* |
| 19 | * WM97xx variants | ||
| 20 | */ | ||
| 21 | #define WM97xx_GENERIC 0x0000 | ||
| 22 | #define WM97xx_WM1613 0x1613 | ||
| 23 | |||
| 24 | /* | ||
| 19 | * WM97xx AC97 Touchscreen registers | 25 | * WM97xx AC97 Touchscreen registers |
| 20 | */ | 26 | */ |
| 21 | #define AC97_WM97XX_DIGITISER1 0x76 | 27 | #define AC97_WM97XX_DIGITISER1 0x76 |
| @@ -283,6 +289,7 @@ struct wm97xx { | |||
| 283 | unsigned pen_is_down:1; /* Pen is down */ | 289 | unsigned pen_is_down:1; /* Pen is down */ |
| 284 | unsigned aux_waiting:1; /* aux measurement waiting */ | 290 | unsigned aux_waiting:1; /* aux measurement waiting */ |
| 285 | unsigned pen_probably_down:1; /* used in polling mode */ | 291 | unsigned pen_probably_down:1; /* used in polling mode */ |
| 292 | u16 variant; /* WM97xx chip variant */ | ||
| 286 | u16 suspend_mode; /* PRP in suspend mode */ | 293 | u16 suspend_mode; /* PRP in suspend mode */ |
| 287 | }; | 294 | }; |
| 288 | 295 | ||
