Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 113802
b: refs/heads/master
c: 622ecb3
h: refs/heads/master
v: v3
  • Loading branch information
Mauro Carvalho Chehab authored and Mauro Carvalho Chehab committed Oct 12, 2008
1 parent bbf2c45 commit af9844a
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 7 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d56dc61265d2527a63ab5b0f03199a43cd89ca36
refs/heads/master: 622ecb300345d308c8b4a983ac112b1985d7d156
140 changes: 134 additions & 6 deletions trunk/drivers/media/video/saa7134/saa7134-input.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,11 @@ MODULE_PARM_DESC(disable_other_ir, "disable full codes of "
#define i2cdprintk(fmt, arg...) if (ir_debug) \
printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg)

/** rc5 functions */
/* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */
static int saa7134_rc5_irq(struct saa7134_dev *dev);
static int saa7134_nec_irq(struct saa7134_dev *dev);
static void nec_task(unsigned long data);
static void saa7134_nec_timer(unsigned long data);

/* -------------------- GPIO generic keycode builder -------------------- */

Expand Down Expand Up @@ -280,7 +283,9 @@ void saa7134_input_irq(struct saa7134_dev *dev)
{
struct card_ir *ir = dev->remote;

if (!ir->polling && !ir->rc5_gpio) {
if (ir->nec_gpio) {
saa7134_nec_irq(dev);
} else if (!ir->polling && !ir->rc5_gpio) {
build_key(dev);
} else if (ir->rc5_gpio) {
saa7134_rc5_irq(dev);
Expand Down Expand Up @@ -316,6 +321,10 @@ void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir)
ir->addr = 0x17;
ir->rc5_key_timeout = ir_rc5_key_timeout;
ir->rc5_remote_gap = ir_rc5_remote_gap;
} else if (ir->nec_gpio) {
setup_timer(&ir->timer_keyup, saa7134_nec_timer,
(unsigned long)dev);
tasklet_init(&ir->tlet, nec_task, (unsigned long)dev);
}
}

Expand All @@ -335,6 +344,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
u32 mask_keyup = 0;
int polling = 0;
int rc5_gpio = 0;
int nec_gpio = 0;
int ir_type = IR_TYPE_OTHER;
int err;

Expand Down Expand Up @@ -533,6 +543,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
ir->mask_keyup = mask_keyup;
ir->polling = polling;
ir->rc5_gpio = rc5_gpio;
ir->nec_gpio = nec_gpio;

/* init input device */
snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)",
Expand Down Expand Up @@ -675,8 +686,125 @@ static int saa7134_rc5_irq(struct saa7134_dev *dev)
return 1;
}

/* ----------------------------------------------------------------------
* Local variables:
* c-basic-offset: 8
* End:

/* On NEC protocol, One has 2.25 ms, and zero has 1.125 ms
The first pulse (start) has 9 + 4.5 ms
*/

static void saa7134_nec_timer(unsigned long data)
{
struct saa7134_dev *dev = (struct saa7134_dev *) data;
struct card_ir *ir = dev->remote;

dprintk("Cancel key repeat\n");

ir_input_nokey(ir->dev, &ir->ir);
}

static void nec_task(unsigned long data)
{
struct saa7134_dev *dev = (struct saa7134_dev *) data;
struct card_ir *ir;
struct timeval tv;
int count, pulse, oldpulse, gap;
u32 ircode = 0, not_code = 0;
int ngap = 0;

if (!data) {
printk(KERN_ERR "saa713x/ir: Can't recover dev struct\n");
/* GPIO will be kept disabled */
return;
}

ir = dev->remote;

/* rising SAA7134_GPIO_GPRESCAN reads the status */
saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);

oldpulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown;
pulse = oldpulse;

do_gettimeofday(&tv);
ir->base_time = tv;

/* Decode NEC pulsecode. This code can take up to 76.5 ms to run.
Unfortunately, using IRQ to decode pulse didn't work, since it uses
a pulse train of 38KHz. This means one pulse on each 52 us
*/
do {
/* Wait until the end of pulse/space or 5 ms */
for (count = 0; count < 500; count++) {
udelay(10);
/* rising SAA7134_GPIO_GPRESCAN reads the status */
saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2)
& ir->mask_keydown;
if (pulse != oldpulse)
break;
}

do_gettimeofday(&tv);
gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
tv.tv_usec - ir->base_time.tv_usec;

if (!pulse) {
/* Bit 0 has 560 us, while bit 1 has 1120 us.
Do something only if bit == 1
*/
if (ngap && (gap > 560 + 280)) {
unsigned int shift = ngap - 1;

/* Address first, then command */
if (shift < 8) {
shift += 8;
ircode |= 1 << shift;
} else if (shift < 16) {
not_code |= 1 << shift;
} else if (shift < 24) {
shift -= 16;
ircode |= 1 << shift;
} else {
shift -= 24;
not_code |= 1 << shift;
}
}
ngap++;
}


ir->base_time = tv;

/* TIMEOUT - Long pulse */
if (gap >= 5000)
break;
oldpulse = pulse;
} while (ngap < 32);

if (ngap == 32) {
/* FIXME: should check if not_code == ~ircode */
ir->code = ir_extract_bits(ircode, ir->mask_keycode);

dprintk("scancode = 0x%02x (code = 0x%02x, notcode= 0x%02x)\n",
ir->code, ircode, not_code);

ir_input_keydown(ir->dev, &ir->ir, ir->code, ir->code);
} else
dprintk("Repeat last key\n");

/* Keep repeating the last key */
mod_timer(&ir->timer_keyup, jiffies + msecs_to_jiffies(150));

saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18);
}

static int saa7134_nec_irq(struct saa7134_dev *dev)
{
struct card_ir *ir = dev->remote;

saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18);
tasklet_schedule(&ir->tlet);

return 1;
}
5 changes: 5 additions & 0 deletions trunk/include/media/ir-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include <linux/input.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>

#define IR_TYPE_RC5 1
#define IR_TYPE_PD 2 /* Pulse distance encoded IR */
Expand Down Expand Up @@ -85,6 +86,10 @@ struct card_ir {
u32 code; /* raw code under construction */
struct timeval base_time; /* time of last seen code */
int active; /* building raw code */

/* NEC decoding */
u32 nec_gpio;
struct tasklet_struct tlet;
};

void ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
Expand Down

0 comments on commit af9844a

Please sign in to comment.