diff options
author | David Herrmann <dh.herrmann@googlemail.com> | 2011-09-06 07:50:36 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2011-09-07 07:25:17 -0400 |
commit | fc221cda3b1220bb3d356349bd843fabef3cf96f (patch) | |
tree | 49f36a150c595b9de531bda8e86103ccadb87f05 /drivers/hid | |
parent | 33e84013d7ce80e071c05171543371d6f71438e5 (diff) |
HID: wiimote: Add IR initializer
The wiimote IR cam needs a fairly complex initialization sequence. This adds a
helper function that performs IR initialization synchronously.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/hid-wiimote.c | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c index 59a08933c73c..35dc293db40e 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote.c | |||
@@ -82,8 +82,10 @@ enum wiiproto_reqs { | |||
82 | WIIPROTO_REQ_RUMBLE = 0x10, | 82 | WIIPROTO_REQ_RUMBLE = 0x10, |
83 | WIIPROTO_REQ_LED = 0x11, | 83 | WIIPROTO_REQ_LED = 0x11, |
84 | WIIPROTO_REQ_DRM = 0x12, | 84 | WIIPROTO_REQ_DRM = 0x12, |
85 | WIIPROTO_REQ_IR1 = 0x13, | ||
85 | WIIPROTO_REQ_WMEM = 0x16, | 86 | WIIPROTO_REQ_WMEM = 0x16, |
86 | WIIPROTO_REQ_RMEM = 0x17, | 87 | WIIPROTO_REQ_RMEM = 0x17, |
88 | WIIPROTO_REQ_IR2 = 0x1a, | ||
87 | WIIPROTO_REQ_STATUS = 0x20, | 89 | WIIPROTO_REQ_STATUS = 0x20, |
88 | WIIPROTO_REQ_DATA = 0x21, | 90 | WIIPROTO_REQ_DATA = 0x21, |
89 | WIIPROTO_REQ_RETURN = 0x22, | 91 | WIIPROTO_REQ_RETURN = 0x22, |
@@ -366,6 +368,28 @@ static void wiiproto_req_accel(struct wiimote_data *wdata, __u8 accel) | |||
366 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | 368 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); |
367 | } | 369 | } |
368 | 370 | ||
371 | static void wiiproto_req_ir1(struct wiimote_data *wdata, __u8 flags) | ||
372 | { | ||
373 | __u8 cmd[2]; | ||
374 | |||
375 | cmd[0] = WIIPROTO_REQ_IR1; | ||
376 | cmd[1] = flags; | ||
377 | |||
378 | wiiproto_keep_rumble(wdata, &cmd[1]); | ||
379 | wiimote_queue(wdata, cmd, sizeof(cmd)); | ||
380 | } | ||
381 | |||
382 | static void wiiproto_req_ir2(struct wiimote_data *wdata, __u8 flags) | ||
383 | { | ||
384 | __u8 cmd[2]; | ||
385 | |||
386 | cmd[0] = WIIPROTO_REQ_IR2; | ||
387 | cmd[1] = flags; | ||
388 | |||
389 | wiiproto_keep_rumble(wdata, &cmd[1]); | ||
390 | wiimote_queue(wdata, cmd, sizeof(cmd)); | ||
391 | } | ||
392 | |||
369 | #define wiiproto_req_wreg(wdata, os, buf, sz) \ | 393 | #define wiiproto_req_wreg(wdata, os, buf, sz) \ |
370 | wiiproto_req_wmem((wdata), false, (os), (buf), (sz)) | 394 | wiiproto_req_wmem((wdata), false, (os), (buf), (sz)) |
371 | 395 | ||
@@ -416,6 +440,118 @@ static int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, | |||
416 | return ret; | 440 | return ret; |
417 | } | 441 | } |
418 | 442 | ||
443 | static int wiimote_init_ir(struct wiimote_data *wdata, __u16 mode) | ||
444 | { | ||
445 | int ret; | ||
446 | unsigned long flags; | ||
447 | __u8 format = 0; | ||
448 | static const __u8 data_enable[] = { 0x01 }; | ||
449 | static const __u8 data_sens1[] = { 0x02, 0x00, 0x00, 0x71, 0x01, | ||
450 | 0x00, 0xaa, 0x00, 0x64 }; | ||
451 | static const __u8 data_sens2[] = { 0x63, 0x03 }; | ||
452 | static const __u8 data_fin[] = { 0x08 }; | ||
453 | |||
454 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
455 | |||
456 | if (mode == (wdata->state.flags & WIIPROTO_FLAGS_IR)) { | ||
457 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
458 | return 0; | ||
459 | } | ||
460 | |||
461 | if (mode == 0) { | ||
462 | wdata->state.flags &= ~WIIPROTO_FLAGS_IR; | ||
463 | wiiproto_req_ir1(wdata, 0); | ||
464 | wiiproto_req_ir2(wdata, 0); | ||
465 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | ||
466 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
471 | |||
472 | ret = wiimote_cmd_acquire(wdata); | ||
473 | if (ret) | ||
474 | return ret; | ||
475 | |||
476 | /* send PIXEL CLOCK ENABLE cmd first */ | ||
477 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
478 | wiimote_cmd_set(wdata, WIIPROTO_REQ_IR1, 0); | ||
479 | wiiproto_req_ir1(wdata, 0x06); | ||
480 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
481 | |||
482 | ret = wiimote_cmd_wait(wdata); | ||
483 | if (ret) | ||
484 | goto unlock; | ||
485 | if (wdata->state.cmd_err) { | ||
486 | ret = -EIO; | ||
487 | goto unlock; | ||
488 | } | ||
489 | |||
490 | /* enable IR LOGIC */ | ||
491 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
492 | wiimote_cmd_set(wdata, WIIPROTO_REQ_IR2, 0); | ||
493 | wiiproto_req_ir2(wdata, 0x06); | ||
494 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
495 | |||
496 | ret = wiimote_cmd_wait(wdata); | ||
497 | if (ret) | ||
498 | goto unlock; | ||
499 | if (wdata->state.cmd_err) { | ||
500 | ret = -EIO; | ||
501 | goto unlock; | ||
502 | } | ||
503 | |||
504 | /* enable IR cam but do not make it send data, yet */ | ||
505 | ret = wiimote_cmd_write(wdata, 0xb00030, data_enable, | ||
506 | sizeof(data_enable)); | ||
507 | if (ret) | ||
508 | goto unlock; | ||
509 | |||
510 | /* write first sensitivity block */ | ||
511 | ret = wiimote_cmd_write(wdata, 0xb00000, data_sens1, | ||
512 | sizeof(data_sens1)); | ||
513 | if (ret) | ||
514 | goto unlock; | ||
515 | |||
516 | /* write second sensitivity block */ | ||
517 | ret = wiimote_cmd_write(wdata, 0xb0001a, data_sens2, | ||
518 | sizeof(data_sens2)); | ||
519 | if (ret) | ||
520 | goto unlock; | ||
521 | |||
522 | /* put IR cam into desired state */ | ||
523 | switch (mode) { | ||
524 | case WIIPROTO_FLAG_IR_FULL: | ||
525 | format = 5; | ||
526 | break; | ||
527 | case WIIPROTO_FLAG_IR_EXT: | ||
528 | format = 3; | ||
529 | break; | ||
530 | case WIIPROTO_FLAG_IR_BASIC: | ||
531 | format = 1; | ||
532 | break; | ||
533 | } | ||
534 | ret = wiimote_cmd_write(wdata, 0xb00033, &format, sizeof(format)); | ||
535 | if (ret) | ||
536 | goto unlock; | ||
537 | |||
538 | /* make IR cam send data */ | ||
539 | ret = wiimote_cmd_write(wdata, 0xb00030, data_fin, sizeof(data_fin)); | ||
540 | if (ret) | ||
541 | goto unlock; | ||
542 | |||
543 | /* request new DRM mode compatible to IR mode */ | ||
544 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
545 | wdata->state.flags &= ~WIIPROTO_FLAGS_IR; | ||
546 | wdata->state.flags |= mode & WIIPROTO_FLAGS_IR; | ||
547 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | ||
548 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
549 | |||
550 | unlock: | ||
551 | wiimote_cmd_release(wdata); | ||
552 | return ret; | ||
553 | } | ||
554 | |||
419 | static enum led_brightness wiimote_leds_get(struct led_classdev *led_dev) | 555 | static enum led_brightness wiimote_leds_get(struct led_classdev *led_dev) |
420 | { | 556 | { |
421 | struct wiimote_data *wdata; | 557 | struct wiimote_data *wdata; |