diff options
-rw-r--r-- | drivers/media/video/saa7134/saa7134-input.c | 140 | ||||
-rw-r--r-- | include/media/ir-common.h | 5 |
2 files changed, 139 insertions, 6 deletions
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index ad08d13dffdd..ac6beb2df83d 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -62,8 +62,11 @@ MODULE_PARM_DESC(disable_other_ir, "disable full codes of " | |||
62 | #define i2cdprintk(fmt, arg...) if (ir_debug) \ | 62 | #define i2cdprintk(fmt, arg...) if (ir_debug) \ |
63 | printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) | 63 | printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) |
64 | 64 | ||
65 | /** rc5 functions */ | 65 | /* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */ |
66 | static int saa7134_rc5_irq(struct saa7134_dev *dev); | 66 | static int saa7134_rc5_irq(struct saa7134_dev *dev); |
67 | static int saa7134_nec_irq(struct saa7134_dev *dev); | ||
68 | static void nec_task(unsigned long data); | ||
69 | static void saa7134_nec_timer(unsigned long data); | ||
67 | 70 | ||
68 | /* -------------------- GPIO generic keycode builder -------------------- */ | 71 | /* -------------------- GPIO generic keycode builder -------------------- */ |
69 | 72 | ||
@@ -280,7 +283,9 @@ void saa7134_input_irq(struct saa7134_dev *dev) | |||
280 | { | 283 | { |
281 | struct card_ir *ir = dev->remote; | 284 | struct card_ir *ir = dev->remote; |
282 | 285 | ||
283 | if (!ir->polling && !ir->rc5_gpio) { | 286 | if (ir->nec_gpio) { |
287 | saa7134_nec_irq(dev); | ||
288 | } else if (!ir->polling && !ir->rc5_gpio) { | ||
284 | build_key(dev); | 289 | build_key(dev); |
285 | } else if (ir->rc5_gpio) { | 290 | } else if (ir->rc5_gpio) { |
286 | saa7134_rc5_irq(dev); | 291 | saa7134_rc5_irq(dev); |
@@ -316,6 +321,10 @@ void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) | |||
316 | ir->addr = 0x17; | 321 | ir->addr = 0x17; |
317 | ir->rc5_key_timeout = ir_rc5_key_timeout; | 322 | ir->rc5_key_timeout = ir_rc5_key_timeout; |
318 | ir->rc5_remote_gap = ir_rc5_remote_gap; | 323 | ir->rc5_remote_gap = ir_rc5_remote_gap; |
324 | } else if (ir->nec_gpio) { | ||
325 | setup_timer(&ir->timer_keyup, saa7134_nec_timer, | ||
326 | (unsigned long)dev); | ||
327 | tasklet_init(&ir->tlet, nec_task, (unsigned long)dev); | ||
319 | } | 328 | } |
320 | } | 329 | } |
321 | 330 | ||
@@ -335,6 +344,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
335 | u32 mask_keyup = 0; | 344 | u32 mask_keyup = 0; |
336 | int polling = 0; | 345 | int polling = 0; |
337 | int rc5_gpio = 0; | 346 | int rc5_gpio = 0; |
347 | int nec_gpio = 0; | ||
338 | int ir_type = IR_TYPE_OTHER; | 348 | int ir_type = IR_TYPE_OTHER; |
339 | int err; | 349 | int err; |
340 | 350 | ||
@@ -533,6 +543,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
533 | ir->mask_keyup = mask_keyup; | 543 | ir->mask_keyup = mask_keyup; |
534 | ir->polling = polling; | 544 | ir->polling = polling; |
535 | ir->rc5_gpio = rc5_gpio; | 545 | ir->rc5_gpio = rc5_gpio; |
546 | ir->nec_gpio = nec_gpio; | ||
536 | 547 | ||
537 | /* init input device */ | 548 | /* init input device */ |
538 | snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", | 549 | snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", |
@@ -675,8 +686,125 @@ static int saa7134_rc5_irq(struct saa7134_dev *dev) | |||
675 | return 1; | 686 | return 1; |
676 | } | 687 | } |
677 | 688 | ||
678 | /* ---------------------------------------------------------------------- | 689 | |
679 | * Local variables: | 690 | /* On NEC protocol, One has 2.25 ms, and zero has 1.125 ms |
680 | * c-basic-offset: 8 | 691 | The first pulse (start) has 9 + 4.5 ms |
681 | * End: | ||
682 | */ | 692 | */ |
693 | |||
694 | static void saa7134_nec_timer(unsigned long data) | ||
695 | { | ||
696 | struct saa7134_dev *dev = (struct saa7134_dev *) data; | ||
697 | struct card_ir *ir = dev->remote; | ||
698 | |||
699 | dprintk("Cancel key repeat\n"); | ||
700 | |||
701 | ir_input_nokey(ir->dev, &ir->ir); | ||
702 | } | ||
703 | |||
704 | static void nec_task(unsigned long data) | ||
705 | { | ||
706 | struct saa7134_dev *dev = (struct saa7134_dev *) data; | ||
707 | struct card_ir *ir; | ||
708 | struct timeval tv; | ||
709 | int count, pulse, oldpulse, gap; | ||
710 | u32 ircode = 0, not_code = 0; | ||
711 | int ngap = 0; | ||
712 | |||
713 | if (!data) { | ||
714 | printk(KERN_ERR "saa713x/ir: Can't recover dev struct\n"); | ||
715 | /* GPIO will be kept disabled */ | ||
716 | return; | ||
717 | } | ||
718 | |||
719 | ir = dev->remote; | ||
720 | |||
721 | /* rising SAA7134_GPIO_GPRESCAN reads the status */ | ||
722 | saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
723 | saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
724 | |||
725 | oldpulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; | ||
726 | pulse = oldpulse; | ||
727 | |||
728 | do_gettimeofday(&tv); | ||
729 | ir->base_time = tv; | ||
730 | |||
731 | /* Decode NEC pulsecode. This code can take up to 76.5 ms to run. | ||
732 | Unfortunately, using IRQ to decode pulse didn't work, since it uses | ||
733 | a pulse train of 38KHz. This means one pulse on each 52 us | ||
734 | */ | ||
735 | do { | ||
736 | /* Wait until the end of pulse/space or 5 ms */ | ||
737 | for (count = 0; count < 500; count++) { | ||
738 | udelay(10); | ||
739 | /* rising SAA7134_GPIO_GPRESCAN reads the status */ | ||
740 | saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
741 | saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
742 | pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) | ||
743 | & ir->mask_keydown; | ||
744 | if (pulse != oldpulse) | ||
745 | break; | ||
746 | } | ||
747 | |||
748 | do_gettimeofday(&tv); | ||
749 | gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + | ||
750 | tv.tv_usec - ir->base_time.tv_usec; | ||
751 | |||
752 | if (!pulse) { | ||
753 | /* Bit 0 has 560 us, while bit 1 has 1120 us. | ||
754 | Do something only if bit == 1 | ||
755 | */ | ||
756 | if (ngap && (gap > 560 + 280)) { | ||
757 | unsigned int shift = ngap - 1; | ||
758 | |||
759 | /* Address first, then command */ | ||
760 | if (shift < 8) { | ||
761 | shift += 8; | ||
762 | ircode |= 1 << shift; | ||
763 | } else if (shift < 16) { | ||
764 | not_code |= 1 << shift; | ||
765 | } else if (shift < 24) { | ||
766 | shift -= 16; | ||
767 | ircode |= 1 << shift; | ||
768 | } else { | ||
769 | shift -= 24; | ||
770 | not_code |= 1 << shift; | ||
771 | } | ||
772 | } | ||
773 | ngap++; | ||
774 | } | ||
775 | |||
776 | |||
777 | ir->base_time = tv; | ||
778 | |||
779 | /* TIMEOUT - Long pulse */ | ||
780 | if (gap >= 5000) | ||
781 | break; | ||
782 | oldpulse = pulse; | ||
783 | } while (ngap < 32); | ||
784 | |||
785 | if (ngap == 32) { | ||
786 | /* FIXME: should check if not_code == ~ircode */ | ||
787 | ir->code = ir_extract_bits(ircode, ir->mask_keycode); | ||
788 | |||
789 | dprintk("scancode = 0x%02x (code = 0x%02x, notcode= 0x%02x)\n", | ||
790 | ir->code, ircode, not_code); | ||
791 | |||
792 | ir_input_keydown(ir->dev, &ir->ir, ir->code, ir->code); | ||
793 | } else | ||
794 | dprintk("Repeat last key\n"); | ||
795 | |||
796 | /* Keep repeating the last key */ | ||
797 | mod_timer(&ir->timer_keyup, jiffies + msecs_to_jiffies(150)); | ||
798 | |||
799 | saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); | ||
800 | } | ||
801 | |||
802 | static int saa7134_nec_irq(struct saa7134_dev *dev) | ||
803 | { | ||
804 | struct card_ir *ir = dev->remote; | ||
805 | |||
806 | saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); | ||
807 | tasklet_schedule(&ir->tlet); | ||
808 | |||
809 | return 1; | ||
810 | } | ||
diff --git a/include/media/ir-common.h b/include/media/ir-common.h index b8e8aa91905a..f5566d43894c 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | #include <linux/input.h> | 26 | #include <linux/input.h> |
27 | #include <linux/workqueue.h> | 27 | #include <linux/workqueue.h> |
28 | #include <linux/interrupt.h> | ||
28 | 29 | ||
29 | #define IR_TYPE_RC5 1 | 30 | #define IR_TYPE_RC5 1 |
30 | #define IR_TYPE_PD 2 /* Pulse distance encoded IR */ | 31 | #define IR_TYPE_PD 2 /* Pulse distance encoded IR */ |
@@ -85,6 +86,10 @@ struct card_ir { | |||
85 | u32 code; /* raw code under construction */ | 86 | u32 code; /* raw code under construction */ |
86 | struct timeval base_time; /* time of last seen code */ | 87 | struct timeval base_time; /* time of last seen code */ |
87 | int active; /* building raw code */ | 88 | int active; /* building raw code */ |
89 | |||
90 | /* NEC decoding */ | ||
91 | u32 nec_gpio; | ||
92 | struct tasklet_struct tlet; | ||
88 | }; | 93 | }; |
89 | 94 | ||
90 | void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, | 95 | void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, |