diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-12-15 06:29:12 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-12-21 18:16:19 -0500 |
commit | 0dae88392395e228e67436cd08f084d395b39df5 (patch) | |
tree | 602c98d27267dcefefc03a71323fb075fa0fe767 /drivers/media/usb/em28xx/em28xx-input.c | |
parent | 105e3687ada4ebe6dfbda7abc3b16106f86a787d (diff) |
[media] em28xx: add support for RC6 mode 0 on devices that support it
Newer em28xx chipsets (em2874 and upper) are capable of supporting
RC6 codes, on both mode 0 (command mode, 16 bits payload size, similar
to RC5, also called "Philips mode") and mode 6a (OEM command mode,
with offers a few alternatives with regards to the payload size).
I don't have any mode 6a control ATM to test it, so, I opted to add
support only to mode 0.
After this patch, adding support to mode 6a should not be hard.
Tested with a Philips television remote controller.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/usb/em28xx/em28xx-input.c')
-rw-r--r-- | drivers/media/usb/em28xx/em28xx-input.c | 93 |
1 files changed, 76 insertions, 17 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index 507370c5217d..3899ea823336 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c | |||
@@ -285,6 +285,9 @@ static int em2874_polling_getkey(struct em28xx_IR *ir, | |||
285 | else /* Normal NEC */ | 285 | else /* Normal NEC */ |
286 | poll_result->scancode = msg[1] << 8 | msg[3]; | 286 | poll_result->scancode = msg[1] << 8 | msg[3]; |
287 | break; | 287 | break; |
288 | case RC_BIT_RC6_0: | ||
289 | poll_result->scancode = msg[1] << 8 | msg[2]; | ||
290 | break; | ||
288 | default: | 291 | default: |
289 | poll_result->scancode = (msg[1] << 24) | (msg[2] << 16) | | 292 | poll_result->scancode = (msg[1] << 24) | (msg[2] << 16) | |
290 | (msg[3] << 8) | msg[4]; | 293 | (msg[3] << 8) | msg[4]; |
@@ -361,15 +364,42 @@ static void em28xx_ir_stop(struct rc_dev *rc) | |||
361 | cancel_delayed_work_sync(&ir->work); | 364 | cancel_delayed_work_sync(&ir->work); |
362 | } | 365 | } |
363 | 366 | ||
364 | static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type) | 367 | static int em2860_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type) |
365 | { | 368 | { |
366 | int rc = 0; | ||
367 | struct em28xx_IR *ir = rc_dev->priv; | 369 | struct em28xx_IR *ir = rc_dev->priv; |
368 | struct em28xx *dev = ir->dev; | 370 | struct em28xx *dev = ir->dev; |
369 | u8 ir_config = EM2874_IR_RC5; | ||
370 | 371 | ||
371 | /* Adjust xclk based o IR table for RC5/NEC tables */ | 372 | /* Adjust xclk based on IR table for RC5/NEC tables */ |
373 | if (*rc_type & RC_BIT_RC5) { | ||
374 | dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE; | ||
375 | ir->full_code = 1; | ||
376 | *rc_type = RC_BIT_RC5; | ||
377 | } else if (*rc_type & RC_BIT_NEC) { | ||
378 | dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; | ||
379 | ir->full_code = 1; | ||
380 | *rc_type = RC_BIT_NEC; | ||
381 | } else if (*rc_type & RC_BIT_UNKNOWN) { | ||
382 | *rc_type = RC_BIT_UNKNOWN; | ||
383 | } else { | ||
384 | *rc_type = ir->rc_type; | ||
385 | return -EINVAL; | ||
386 | } | ||
387 | ir->get_key = default_polling_getkey; | ||
388 | em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, | ||
389 | EM28XX_XCLK_IR_RC5_MODE); | ||
390 | |||
391 | ir->rc_type = *rc_type; | ||
372 | 392 | ||
393 | return 0; | ||
394 | } | ||
395 | |||
396 | static int em2874_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type) | ||
397 | { | ||
398 | struct em28xx_IR *ir = rc_dev->priv; | ||
399 | struct em28xx *dev = ir->dev; | ||
400 | u8 ir_config = EM2874_IR_RC5; | ||
401 | |||
402 | /* Adjust xclk and set type based on IR table for RC5/NEC/RC6 tables */ | ||
373 | if (*rc_type & RC_BIT_RC5) { | 403 | if (*rc_type & RC_BIT_RC5) { |
374 | dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE; | 404 | dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE; |
375 | ir->full_code = 1; | 405 | ir->full_code = 1; |
@@ -379,33 +409,47 @@ static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type) | |||
379 | ir_config = EM2874_IR_NEC | EM2874_IR_NEC_NO_PARITY; | 409 | ir_config = EM2874_IR_NEC | EM2874_IR_NEC_NO_PARITY; |
380 | ir->full_code = 1; | 410 | ir->full_code = 1; |
381 | *rc_type = RC_BIT_NEC; | 411 | *rc_type = RC_BIT_NEC; |
382 | } else if (*rc_type != RC_BIT_UNKNOWN) | 412 | } else if (*rc_type & RC_BIT_RC6_0) { |
383 | rc = -EINVAL; | 413 | dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE; |
414 | ir_config = EM2874_IR_RC6_MODE_0; | ||
415 | ir->full_code = 1; | ||
416 | *rc_type = RC_BIT_RC6_0; | ||
417 | } else if (*rc_type & RC_BIT_UNKNOWN) { | ||
418 | *rc_type = RC_BIT_UNKNOWN; | ||
419 | } else { | ||
420 | *rc_type = ir->rc_type; | ||
421 | return -EINVAL; | ||
422 | } | ||
384 | 423 | ||
385 | ir->rc_type = *rc_type; | 424 | ir->get_key = em2874_polling_getkey; |
425 | em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1); | ||
386 | 426 | ||
387 | em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, | 427 | em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, |
388 | EM28XX_XCLK_IR_RC5_MODE); | 428 | EM28XX_XCLK_IR_RC5_MODE); |
389 | 429 | ||
430 | ir->rc_type = *rc_type; | ||
431 | |||
432 | return 0; | ||
433 | } | ||
434 | static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type) | ||
435 | { | ||
436 | struct em28xx_IR *ir = rc_dev->priv; | ||
437 | struct em28xx *dev = ir->dev; | ||
438 | |||
390 | /* Setup the proper handler based on the chip */ | 439 | /* Setup the proper handler based on the chip */ |
391 | switch (dev->chip_id) { | 440 | switch (dev->chip_id) { |
392 | case CHIP_ID_EM2860: | 441 | case CHIP_ID_EM2860: |
393 | case CHIP_ID_EM2883: | 442 | case CHIP_ID_EM2883: |
394 | ir->get_key = default_polling_getkey; | 443 | return em2860_ir_change_protocol(rc_dev, rc_type); |
395 | break; | ||
396 | case CHIP_ID_EM2884: | 444 | case CHIP_ID_EM2884: |
397 | case CHIP_ID_EM2874: | 445 | case CHIP_ID_EM2874: |
398 | case CHIP_ID_EM28174: | 446 | case CHIP_ID_EM28174: |
399 | ir->get_key = em2874_polling_getkey; | 447 | return em2874_ir_change_protocol(rc_dev, rc_type); |
400 | em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1); | ||
401 | break; | ||
402 | default: | 448 | default: |
403 | printk("Unrecognized em28xx chip id 0x%02x: IR not supported\n", | 449 | printk("Unrecognized em28xx chip id 0x%02x: IR not supported\n", |
404 | dev->chip_id); | 450 | dev->chip_id); |
405 | rc = -EINVAL; | 451 | return -EINVAL; |
406 | } | 452 | } |
407 | |||
408 | return rc; | ||
409 | } | 453 | } |
410 | 454 | ||
411 | static void em28xx_register_i2c_ir(struct em28xx *dev) | 455 | static void em28xx_register_i2c_ir(struct em28xx *dev) |
@@ -573,6 +617,21 @@ static int em28xx_ir_init(struct em28xx *dev) | |||
573 | rc->open = em28xx_ir_start; | 617 | rc->open = em28xx_ir_start; |
574 | rc->close = em28xx_ir_stop; | 618 | rc->close = em28xx_ir_stop; |
575 | 619 | ||
620 | switch (dev->chip_id) { | ||
621 | case CHIP_ID_EM2860: | ||
622 | case CHIP_ID_EM2883: | ||
623 | rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC; | ||
624 | break; | ||
625 | case CHIP_ID_EM2884: | ||
626 | case CHIP_ID_EM2874: | ||
627 | case CHIP_ID_EM28174: | ||
628 | rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC | RC_BIT_RC6_0; | ||
629 | break; | ||
630 | default: | ||
631 | err = -ENODEV; | ||
632 | goto err_out_free; | ||
633 | } | ||
634 | |||
576 | /* By default, keep protocol field untouched */ | 635 | /* By default, keep protocol field untouched */ |
577 | rc_type = RC_BIT_UNKNOWN; | 636 | rc_type = RC_BIT_UNKNOWN; |
578 | err = em28xx_ir_change_protocol(rc, &rc_type); | 637 | err = em28xx_ir_change_protocol(rc, &rc_type); |
@@ -615,9 +674,9 @@ static int em28xx_ir_init(struct em28xx *dev) | |||
615 | 674 | ||
616 | return 0; | 675 | return 0; |
617 | 676 | ||
618 | err_out_stop: | 677 | err_out_stop: |
619 | dev->ir = NULL; | 678 | dev->ir = NULL; |
620 | err_out_free: | 679 | err_out_free: |
621 | rc_free_device(rc); | 680 | rc_free_device(rc); |
622 | kfree(ir); | 681 | kfree(ir); |
623 | return err; | 682 | return err; |