diff options
Diffstat (limited to 'drivers/media/video/ir-kbd-i2c.c')
-rw-r--r-- | drivers/media/video/ir-kbd-i2c.c | 64 |
1 files changed, 60 insertions, 4 deletions
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index a30254bed31..efe849981ab 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -12,6 +12,10 @@ * Markus Rechberger <mrechberger@gmail.com> * modified for DViCO Fusion HDTV 5 RT GOLD by * Chaogui Zhang <czhang1974@gmail.com> + * modified for MSI TV@nywhere Plus by + * Henry Wong <henry@stuffedcow.net> + * Mark Schultz <n9xmj@yahoo.com> + * Brian Rogers <brian_rogers@comcast.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -65,7 +69,7 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, int size, int offset) { unsigned char buf[6]; - int start, range, toggle, dev, code; + int start, range, toggle, dev, code, ircode; /* poll IR chip */ if (size != i2c_master_recv(&ir->c,buf,size)) @@ -85,6 +89,24 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, if (!start) /* no key pressed */ return 0; + /* + * Hauppauge remotes (black/silver) always use + * specific device ids. If we do not filter the + * device ids then messages destined for devices + * such as TVs (id=0) will get through causing + * mis-fired events. + * + * We also filter out invalid key presses which + * produce annoying debug log entries. + */ + ircode= (start << 12) | (toggle << 11) | (dev << 6) | code; + if ((ircode & 0x1fff)==0x1fff) + /* invalid key press */ + return 0; + + if (dev!=0x1e && dev!=0x1f) + /* not a hauppauge remote */ + return 0; if (!range) code += 64; @@ -94,7 +116,7 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, /* return key */ *ir_key = code; - *ir_raw = (start << 12) | (toggle << 11) | (dev << 6) | code; + *ir_raw = ircode; return 1; } @@ -224,9 +246,15 @@ static void ir_timer(unsigned long data) static void ir_work(struct work_struct *work) { struct IR_i2c *ir = container_of(work, struct IR_i2c, work); + int polling_interval = 100; + + /* MSI TV@nywhere Plus requires more frequent polling + otherwise it will miss some keypresses */ + if (ir->c.adapter->id == I2C_HW_SAA7134 && ir->c.addr == 0x30) + polling_interval = 50; ir_key_poll(ir); - mod_timer(&ir->timer, jiffies + msecs_to_jiffies(100)); + mod_timer(&ir->timer, jiffies + msecs_to_jiffies(polling_interval)); } /* ----------------------------------------------------------------------- */ @@ -465,9 +493,37 @@ static int ir_probe(struct i2c_adapter *adap) (1 == rc) ? "yes" : "no"); if (1 == rc) { ir_attach(adap, probe[i], 0, 0); - break; + return 0; } } + + /* Special case for MSI TV@nywhere Plus remote */ + if (adap->id == I2C_HW_SAA7134) { + u8 temp; + + /* MSI TV@nywhere Plus controller doesn't seem to + respond to probes unless we read something from + an existing device. Weird... */ + + msg.addr = 0x50; + rc = i2c_transfer(adap, &msg, 1); + dprintk(1, "probe 0x%02x @ %s: %s\n", + msg.addr, adap->name, + (1 == rc) ? "yes" : "no"); + + /* Now do the probe. The controller does not respond + to 0-byte reads, so we use a 1-byte read instead. */ + msg.addr = 0x30; + msg.len = 1; + msg.buf = &temp; + rc = i2c_transfer(adap, &msg, 1); + dprintk(1, "probe 0x%02x @ %s: %s\n", + msg.addr, adap->name, + (1 == rc) ? "yes" : "no"); + if (1 == rc) + ir_attach(adap, msg.addr, 0, 0); + } + return 0; } |