diff options
Diffstat (limited to 'drivers/input/joystick/analog.c')
-rw-r--r-- | drivers/input/joystick/analog.c | 71 |
1 files changed, 52 insertions, 19 deletions
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index ab0fdcd36e18..4284080e481d 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/gameport.h> | 36 | #include <linux/gameport.h> |
37 | #include <linux/jiffies.h> | 37 | #include <linux/jiffies.h> |
38 | #include <linux/timex.h> | 38 | #include <linux/timex.h> |
39 | #include <linux/timekeeping.h> | ||
39 | 40 | ||
40 | #define DRIVER_DESC "Analog joystick and gamepad driver" | 41 | #define DRIVER_DESC "Analog joystick and gamepad driver" |
41 | 42 | ||
@@ -43,6 +44,10 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | |||
43 | MODULE_DESCRIPTION(DRIVER_DESC); | 44 | MODULE_DESCRIPTION(DRIVER_DESC); |
44 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
45 | 46 | ||
47 | static bool use_ktime = true; | ||
48 | module_param(use_ktime, bool, 0400); | ||
49 | MODULE_PARM_DESC(use_ktime, "Use ktime for measuring I/O speed"); | ||
50 | |||
46 | /* | 51 | /* |
47 | * Option parsing. | 52 | * Option parsing. |
48 | */ | 53 | */ |
@@ -171,6 +176,25 @@ static unsigned long analog_faketime = 0; | |||
171 | #warning Precise timer not defined for this architecture. | 176 | #warning Precise timer not defined for this architecture. |
172 | #endif | 177 | #endif |
173 | 178 | ||
179 | static inline u64 get_time(void) | ||
180 | { | ||
181 | if (use_ktime) { | ||
182 | return ktime_get_ns(); | ||
183 | } else { | ||
184 | unsigned int x; | ||
185 | GET_TIME(x); | ||
186 | return x; | ||
187 | } | ||
188 | } | ||
189 | |||
190 | static inline unsigned int delta(u64 x, u64 y) | ||
191 | { | ||
192 | if (use_ktime) | ||
193 | return y - x; | ||
194 | else | ||
195 | return DELTA((unsigned int)x, (unsigned int)y); | ||
196 | } | ||
197 | |||
174 | /* | 198 | /* |
175 | * analog_decode() decodes analog joystick data and reports input events. | 199 | * analog_decode() decodes analog joystick data and reports input events. |
176 | */ | 200 | */ |
@@ -226,7 +250,8 @@ static void analog_decode(struct analog *analog, int *axes, int *initial, int bu | |||
226 | static int analog_cooked_read(struct analog_port *port) | 250 | static int analog_cooked_read(struct analog_port *port) |
227 | { | 251 | { |
228 | struct gameport *gameport = port->gameport; | 252 | struct gameport *gameport = port->gameport; |
229 | unsigned int time[4], start, loop, now, loopout, timeout; | 253 | u64 time[4], start, loop, now; |
254 | unsigned int loopout, timeout; | ||
230 | unsigned char data[4], this, last; | 255 | unsigned char data[4], this, last; |
231 | unsigned long flags; | 256 | unsigned long flags; |
232 | int i, j; | 257 | int i, j; |
@@ -236,7 +261,7 @@ static int analog_cooked_read(struct analog_port *port) | |||
236 | 261 | ||
237 | local_irq_save(flags); | 262 | local_irq_save(flags); |
238 | gameport_trigger(gameport); | 263 | gameport_trigger(gameport); |
239 | GET_TIME(now); | 264 | now = get_time(); |
240 | local_irq_restore(flags); | 265 | local_irq_restore(flags); |
241 | 266 | ||
242 | start = now; | 267 | start = now; |
@@ -249,16 +274,16 @@ static int analog_cooked_read(struct analog_port *port) | |||
249 | 274 | ||
250 | local_irq_disable(); | 275 | local_irq_disable(); |
251 | this = gameport_read(gameport) & port->mask; | 276 | this = gameport_read(gameport) & port->mask; |
252 | GET_TIME(now); | 277 | now = get_time(); |
253 | local_irq_restore(flags); | 278 | local_irq_restore(flags); |
254 | 279 | ||
255 | if ((last ^ this) && (DELTA(loop, now) < loopout)) { | 280 | if ((last ^ this) && (delta(loop, now) < loopout)) { |
256 | data[i] = last ^ this; | 281 | data[i] = last ^ this; |
257 | time[i] = now; | 282 | time[i] = now; |
258 | i++; | 283 | i++; |
259 | } | 284 | } |
260 | 285 | ||
261 | } while (this && (i < 4) && (DELTA(start, now) < timeout)); | 286 | } while (this && (i < 4) && (delta(start, now) < timeout)); |
262 | 287 | ||
263 | this <<= 4; | 288 | this <<= 4; |
264 | 289 | ||
@@ -266,7 +291,7 @@ static int analog_cooked_read(struct analog_port *port) | |||
266 | this |= data[i]; | 291 | this |= data[i]; |
267 | for (j = 0; j < 4; j++) | 292 | for (j = 0; j < 4; j++) |
268 | if (data[i] & (1 << j)) | 293 | if (data[i] & (1 << j)) |
269 | port->axes[j] = (DELTA(start, time[i]) << ANALOG_FUZZ_BITS) / port->loop; | 294 | port->axes[j] = (delta(start, time[i]) << ANALOG_FUZZ_BITS) / port->loop; |
270 | } | 295 | } |
271 | 296 | ||
272 | return -(this != port->mask); | 297 | return -(this != port->mask); |
@@ -365,31 +390,39 @@ static void analog_close(struct input_dev *dev) | |||
365 | static void analog_calibrate_timer(struct analog_port *port) | 390 | static void analog_calibrate_timer(struct analog_port *port) |
366 | { | 391 | { |
367 | struct gameport *gameport = port->gameport; | 392 | struct gameport *gameport = port->gameport; |
368 | unsigned int i, t, tx, t1, t2, t3; | 393 | unsigned int i, t, tx; |
394 | u64 t1, t2, t3; | ||
369 | unsigned long flags; | 395 | unsigned long flags; |
370 | 396 | ||
371 | local_irq_save(flags); | 397 | if (use_ktime) { |
372 | GET_TIME(t1); | 398 | port->speed = 1000000; |
399 | } else { | ||
400 | local_irq_save(flags); | ||
401 | t1 = get_time(); | ||
373 | #ifdef FAKE_TIME | 402 | #ifdef FAKE_TIME |
374 | analog_faketime += 830; | 403 | analog_faketime += 830; |
375 | #endif | 404 | #endif |
376 | mdelay(1); | 405 | mdelay(1); |
377 | GET_TIME(t2); | 406 | t2 = get_time(); |
378 | GET_TIME(t3); | 407 | t3 = get_time(); |
379 | local_irq_restore(flags); | 408 | local_irq_restore(flags); |
380 | 409 | ||
381 | port->speed = DELTA(t1, t2) - DELTA(t2, t3); | 410 | port->speed = delta(t1, t2) - delta(t2, t3); |
411 | } | ||
382 | 412 | ||
383 | tx = ~0; | 413 | tx = ~0; |
384 | 414 | ||
385 | for (i = 0; i < 50; i++) { | 415 | for (i = 0; i < 50; i++) { |
386 | local_irq_save(flags); | 416 | local_irq_save(flags); |
387 | GET_TIME(t1); | 417 | t1 = get_time(); |
388 | for (t = 0; t < 50; t++) { gameport_read(gameport); GET_TIME(t2); } | 418 | for (t = 0; t < 50; t++) { |
389 | GET_TIME(t3); | 419 | gameport_read(gameport); |
420 | t2 = get_time(); | ||
421 | } | ||
422 | t3 = get_time(); | ||
390 | local_irq_restore(flags); | 423 | local_irq_restore(flags); |
391 | udelay(i); | 424 | udelay(i); |
392 | t = DELTA(t1, t2) - DELTA(t2, t3); | 425 | t = delta(t1, t2) - delta(t2, t3); |
393 | if (t < tx) tx = t; | 426 | if (t < tx) tx = t; |
394 | } | 427 | } |
395 | 428 | ||