diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-03-20 19:59:44 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-05-17 23:52:56 -0400 |
commit | a3572c34da8dacc78a629211a91cf34e9b408701 (patch) | |
tree | 281efd4d69b68bd4720668fd91cfcf16d1ed3089 /drivers/media/video/saa7134/saa7134-input.c | |
parent | 0210894956cf57d525d56341cc3e0f3d5d2db659 (diff) |
V4L/DVB: ir-core: Add logic to decode IR protocols at the IR core
Adds a method to pass IR raw pulse/code events into ir-core. This is
needed in order to support LIRC. It also helps to move common code
from the drivers into the core.
In order to allow testing, it implements a simple NEC protocol decoder
at ir-nec-decoder.c file. The logic is about the same used at saa7134
driver that handles Avermedia M135A and Encore FM53 boards.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/saa7134/saa7134-input.c')
-rw-r--r-- | drivers/media/video/saa7134/saa7134-input.c | 85 |
1 files changed, 81 insertions, 4 deletions
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 7e6f125e4e31..1a7cf9c8c68c 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -68,6 +68,7 @@ MODULE_PARM_DESC(disable_other_ir, "disable full codes of " | |||
68 | /* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */ | 68 | /* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */ |
69 | static int saa7134_rc5_irq(struct saa7134_dev *dev); | 69 | static int saa7134_rc5_irq(struct saa7134_dev *dev); |
70 | static int saa7134_nec_irq(struct saa7134_dev *dev); | 70 | static int saa7134_nec_irq(struct saa7134_dev *dev); |
71 | static int saa7134_raw_decode_irq(struct saa7134_dev *dev); | ||
71 | static void nec_task(unsigned long data); | 72 | static void nec_task(unsigned long data); |
72 | static void saa7134_nec_timer(unsigned long data); | 73 | static void saa7134_nec_timer(unsigned long data); |
73 | 74 | ||
@@ -403,10 +404,12 @@ void saa7134_input_irq(struct saa7134_dev *dev) | |||
403 | 404 | ||
404 | if (ir->nec_gpio) { | 405 | if (ir->nec_gpio) { |
405 | saa7134_nec_irq(dev); | 406 | saa7134_nec_irq(dev); |
406 | } else if (!ir->polling && !ir->rc5_gpio) { | 407 | } else if (!ir->polling && !ir->rc5_gpio && !ir->raw_decode) { |
407 | build_key(dev); | 408 | build_key(dev); |
408 | } else if (ir->rc5_gpio) { | 409 | } else if (ir->rc5_gpio) { |
409 | saa7134_rc5_irq(dev); | 410 | saa7134_rc5_irq(dev); |
411 | } else if (ir->raw_decode) { | ||
412 | saa7134_raw_decode_irq(dev); | ||
410 | } | 413 | } |
411 | } | 414 | } |
412 | 415 | ||
@@ -419,6 +422,23 @@ static void saa7134_input_timer(unsigned long data) | |||
419 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); | 422 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); |
420 | } | 423 | } |
421 | 424 | ||
425 | void ir_raw_decode_timer_end(unsigned long data) | ||
426 | { | ||
427 | struct saa7134_dev *dev = (struct saa7134_dev *)data; | ||
428 | struct card_ir *ir = dev->remote; | ||
429 | int rc; | ||
430 | |||
431 | /* | ||
432 | * FIXME: the IR key handling code should be called by the decoder, | ||
433 | * after implementing the repeat mode | ||
434 | */ | ||
435 | rc = ir_raw_event_handle(dev->remote->dev); | ||
436 | if (rc >= 0) { | ||
437 | ir_input_keydown(ir->dev, &ir->ir, rc); | ||
438 | ir_input_nokey(ir->dev, &ir->ir); | ||
439 | } | ||
440 | } | ||
441 | |||
422 | void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) | 442 | void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) |
423 | { | 443 | { |
424 | if (ir->running) | 444 | if (ir->running) |
@@ -447,6 +467,11 @@ void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) | |||
447 | setup_timer(&ir->timer_keyup, saa7134_nec_timer, | 467 | setup_timer(&ir->timer_keyup, saa7134_nec_timer, |
448 | (unsigned long)dev); | 468 | (unsigned long)dev); |
449 | tasklet_init(&ir->tlet, nec_task, (unsigned long)dev); | 469 | tasklet_init(&ir->tlet, nec_task, (unsigned long)dev); |
470 | } else if (ir->raw_decode) { | ||
471 | /* set timer_end for code completion */ | ||
472 | init_timer(&ir->timer_end); | ||
473 | ir->timer_end.function = ir_raw_decode_timer_end; | ||
474 | ir->timer_end.data = (unsigned long)dev; | ||
450 | } | 475 | } |
451 | } | 476 | } |
452 | 477 | ||
@@ -462,6 +487,9 @@ void saa7134_ir_stop(struct saa7134_dev *dev) | |||
462 | del_timer_sync(&ir->timer_end); | 487 | del_timer_sync(&ir->timer_end); |
463 | else if (ir->nec_gpio) | 488 | else if (ir->nec_gpio) |
464 | tasklet_kill(&ir->tlet); | 489 | tasklet_kill(&ir->tlet); |
490 | else if (ir->raw_decode) | ||
491 | del_timer_sync(&ir->timer_end); | ||
492 | |||
465 | ir->running = 0; | 493 | ir->running = 0; |
466 | } | 494 | } |
467 | 495 | ||
@@ -509,6 +537,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
509 | int polling = 0; | 537 | int polling = 0; |
510 | int rc5_gpio = 0; | 538 | int rc5_gpio = 0; |
511 | int nec_gpio = 0; | 539 | int nec_gpio = 0; |
540 | int raw_decode = 0; | ||
512 | u64 ir_type = IR_TYPE_OTHER; | 541 | u64 ir_type = IR_TYPE_OTHER; |
513 | int err; | 542 | int err; |
514 | 543 | ||
@@ -574,7 +603,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
574 | ir_codes = &ir_codes_avermedia_m135a_rm_jx_table; | 603 | ir_codes = &ir_codes_avermedia_m135a_rm_jx_table; |
575 | mask_keydown = 0x0040000; | 604 | mask_keydown = 0x0040000; |
576 | mask_keycode = 0xffff; | 605 | mask_keycode = 0xffff; |
577 | nec_gpio = 1; | 606 | raw_decode = 1; |
578 | break; | 607 | break; |
579 | case SAA7134_BOARD_AVERMEDIA_777: | 608 | case SAA7134_BOARD_AVERMEDIA_777: |
580 | case SAA7134_BOARD_AVERMEDIA_A16AR: | 609 | case SAA7134_BOARD_AVERMEDIA_A16AR: |
@@ -755,6 +784,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
755 | ir->polling = polling; | 784 | ir->polling = polling; |
756 | ir->rc5_gpio = rc5_gpio; | 785 | ir->rc5_gpio = rc5_gpio; |
757 | ir->nec_gpio = nec_gpio; | 786 | ir->nec_gpio = nec_gpio; |
787 | ir->raw_decode = raw_decode; | ||
758 | 788 | ||
759 | /* init input device */ | 789 | /* init input device */ |
760 | snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", | 790 | snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", |
@@ -762,7 +792,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
762 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", | 792 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", |
763 | pci_name(dev->pci)); | 793 | pci_name(dev->pci)); |
764 | 794 | ||
765 | if (ir_codes->ir_type != IR_TYPE_OTHER) { | 795 | if (ir_codes->ir_type != IR_TYPE_OTHER && !raw_decode) { |
766 | ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; | 796 | ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; |
767 | ir->props.priv = dev; | 797 | ir->props.priv = dev; |
768 | ir->props.change_protocol = saa7134_ir_change_protocol; | 798 | ir->props.change_protocol = saa7134_ir_change_protocol; |
@@ -790,6 +820,11 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
790 | err = ir_input_register(ir->dev, ir_codes, &ir->props, MODULE_NAME); | 820 | err = ir_input_register(ir->dev, ir_codes, &ir->props, MODULE_NAME); |
791 | if (err) | 821 | if (err) |
792 | goto err_out_stop; | 822 | goto err_out_stop; |
823 | if (ir_codes->ir_type != IR_TYPE_OTHER) { | ||
824 | err = ir_raw_event_register(ir->dev); | ||
825 | if (err) | ||
826 | goto err_out_stop; | ||
827 | } | ||
793 | 828 | ||
794 | saa7134_ir_start(dev, ir); | 829 | saa7134_ir_start(dev, ir); |
795 | 830 | ||
@@ -813,6 +848,7 @@ void saa7134_input_fini(struct saa7134_dev *dev) | |||
813 | return; | 848 | return; |
814 | 849 | ||
815 | saa7134_ir_stop(dev); | 850 | saa7134_ir_stop(dev); |
851 | ir_raw_event_unregister(dev->remote->dev); | ||
816 | ir_input_unregister(dev->remote->dev); | 852 | ir_input_unregister(dev->remote->dev); |
817 | kfree(dev->remote); | 853 | kfree(dev->remote); |
818 | dev->remote = NULL; | 854 | dev->remote = NULL; |
@@ -919,6 +955,48 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) | |||
919 | i2c_new_device(&dev->i2c_adap, &info); | 955 | i2c_new_device(&dev->i2c_adap, &info); |
920 | } | 956 | } |
921 | 957 | ||
958 | static int saa7134_raw_decode_irq(struct saa7134_dev *dev) | ||
959 | { | ||
960 | struct card_ir *ir = dev->remote; | ||
961 | unsigned long timeout; | ||
962 | int count, pulse, oldpulse; | ||
963 | |||
964 | /* Disable IR IRQ line */ | ||
965 | saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); | ||
966 | |||
967 | /* Generate initial event */ | ||
968 | saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
969 | saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
970 | pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; | ||
971 | ir_raw_event_store(dev->remote->dev, pulse? IR_PULSE : IR_SPACE); | ||
972 | |||
973 | #if 1 | ||
974 | /* Wait up to 10 ms for event change */ | ||
975 | oldpulse = pulse; | ||
976 | for (count = 0; count < 1000; count++) { | ||
977 | udelay(10); | ||
978 | /* rising SAA7134_GPIO_GPRESCAN reads the status */ | ||
979 | saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
980 | saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
981 | pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) | ||
982 | & ir->mask_keydown; | ||
983 | if (pulse != oldpulse) | ||
984 | break; | ||
985 | } | ||
986 | |||
987 | /* Store final event */ | ||
988 | ir_raw_event_store(dev->remote->dev, pulse? IR_PULSE : IR_SPACE); | ||
989 | #endif | ||
990 | /* Wait 15 ms before deciding to do something else */ | ||
991 | timeout = jiffies + jiffies_to_msecs(15); | ||
992 | mod_timer(&ir->timer_end, timeout); | ||
993 | |||
994 | /* Enable IR IRQ line */ | ||
995 | saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); | ||
996 | |||
997 | return 1; | ||
998 | } | ||
999 | |||
922 | static int saa7134_rc5_irq(struct saa7134_dev *dev) | 1000 | static int saa7134_rc5_irq(struct saa7134_dev *dev) |
923 | { | 1001 | { |
924 | struct card_ir *ir = dev->remote; | 1002 | struct card_ir *ir = dev->remote; |
@@ -961,7 +1039,6 @@ static int saa7134_rc5_irq(struct saa7134_dev *dev) | |||
961 | return 1; | 1039 | return 1; |
962 | } | 1040 | } |
963 | 1041 | ||
964 | |||
965 | /* On NEC protocol, One has 2.25 ms, and zero has 1.125 ms | 1042 | /* On NEC protocol, One has 2.25 ms, and zero has 1.125 ms |
966 | The first pulse (start) has 9 + 4.5 ms | 1043 | The first pulse (start) has 9 + 4.5 ms |
967 | */ | 1044 | */ |