aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/joystick/analog.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/joystick/analog.c')
-rw-r--r--drivers/input/joystick/analog.c71
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>");
43MODULE_DESCRIPTION(DRIVER_DESC); 44MODULE_DESCRIPTION(DRIVER_DESC);
44MODULE_LICENSE("GPL"); 45MODULE_LICENSE("GPL");
45 46
47static bool use_ktime = true;
48module_param(use_ktime, bool, 0400);
49MODULE_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
179static 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
190static 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
226static int analog_cooked_read(struct analog_port *port) 250static 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)
365static void analog_calibrate_timer(struct analog_port *port) 390static 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