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 a30254bed311..efe849981ab7 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c | |||
@@ -12,6 +12,10 @@ | |||
12 | * Markus Rechberger <mrechberger@gmail.com> | 12 | * Markus Rechberger <mrechberger@gmail.com> |
13 | * modified for DViCO Fusion HDTV 5 RT GOLD by | 13 | * modified for DViCO Fusion HDTV 5 RT GOLD by |
14 | * Chaogui Zhang <czhang1974@gmail.com> | 14 | * Chaogui Zhang <czhang1974@gmail.com> |
15 | * modified for MSI TV@nywhere Plus by | ||
16 | * Henry Wong <henry@stuffedcow.net> | ||
17 | * Mark Schultz <n9xmj@yahoo.com> | ||
18 | * Brian Rogers <brian_rogers@comcast.net> | ||
15 | * | 19 | * |
16 | * This program is free software; you can redistribute it and/or modify | 20 | * This program is free software; you can redistribute it and/or modify |
17 | * it under the terms of the GNU General Public License as published by | 21 | * 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, | |||
65 | int size, int offset) | 69 | int size, int offset) |
66 | { | 70 | { |
67 | unsigned char buf[6]; | 71 | unsigned char buf[6]; |
68 | int start, range, toggle, dev, code; | 72 | int start, range, toggle, dev, code, ircode; |
69 | 73 | ||
70 | /* poll IR chip */ | 74 | /* poll IR chip */ |
71 | if (size != i2c_master_recv(&ir->c,buf,size)) | 75 | 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, | |||
85 | if (!start) | 89 | if (!start) |
86 | /* no key pressed */ | 90 | /* no key pressed */ |
87 | return 0; | 91 | return 0; |
92 | /* | ||
93 | * Hauppauge remotes (black/silver) always use | ||
94 | * specific device ids. If we do not filter the | ||
95 | * device ids then messages destined for devices | ||
96 | * such as TVs (id=0) will get through causing | ||
97 | * mis-fired events. | ||
98 | * | ||
99 | * We also filter out invalid key presses which | ||
100 | * produce annoying debug log entries. | ||
101 | */ | ||
102 | ircode= (start << 12) | (toggle << 11) | (dev << 6) | code; | ||
103 | if ((ircode & 0x1fff)==0x1fff) | ||
104 | /* invalid key press */ | ||
105 | return 0; | ||
106 | |||
107 | if (dev!=0x1e && dev!=0x1f) | ||
108 | /* not a hauppauge remote */ | ||
109 | return 0; | ||
88 | 110 | ||
89 | if (!range) | 111 | if (!range) |
90 | code += 64; | 112 | code += 64; |
@@ -94,7 +116,7 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, | |||
94 | 116 | ||
95 | /* return key */ | 117 | /* return key */ |
96 | *ir_key = code; | 118 | *ir_key = code; |
97 | *ir_raw = (start << 12) | (toggle << 11) | (dev << 6) | code; | 119 | *ir_raw = ircode; |
98 | return 1; | 120 | return 1; |
99 | } | 121 | } |
100 | 122 | ||
@@ -224,9 +246,15 @@ static void ir_timer(unsigned long data) | |||
224 | static void ir_work(struct work_struct *work) | 246 | static void ir_work(struct work_struct *work) |
225 | { | 247 | { |
226 | struct IR_i2c *ir = container_of(work, struct IR_i2c, work); | 248 | struct IR_i2c *ir = container_of(work, struct IR_i2c, work); |
249 | int polling_interval = 100; | ||
250 | |||
251 | /* MSI TV@nywhere Plus requires more frequent polling | ||
252 | otherwise it will miss some keypresses */ | ||
253 | if (ir->c.adapter->id == I2C_HW_SAA7134 && ir->c.addr == 0x30) | ||
254 | polling_interval = 50; | ||
227 | 255 | ||
228 | ir_key_poll(ir); | 256 | ir_key_poll(ir); |
229 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(100)); | 257 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(polling_interval)); |
230 | } | 258 | } |
231 | 259 | ||
232 | /* ----------------------------------------------------------------------- */ | 260 | /* ----------------------------------------------------------------------- */ |
@@ -465,9 +493,37 @@ static int ir_probe(struct i2c_adapter *adap) | |||
465 | (1 == rc) ? "yes" : "no"); | 493 | (1 == rc) ? "yes" : "no"); |
466 | if (1 == rc) { | 494 | if (1 == rc) { |
467 | ir_attach(adap, probe[i], 0, 0); | 495 | ir_attach(adap, probe[i], 0, 0); |
468 | break; | 496 | return 0; |
469 | } | 497 | } |
470 | } | 498 | } |
499 | |||
500 | /* Special case for MSI TV@nywhere Plus remote */ | ||
501 | if (adap->id == I2C_HW_SAA7134) { | ||
502 | u8 temp; | ||
503 | |||
504 | /* MSI TV@nywhere Plus controller doesn't seem to | ||
505 | respond to probes unless we read something from | ||
506 | an existing device. Weird... */ | ||
507 | |||
508 | msg.addr = 0x50; | ||
509 | rc = i2c_transfer(adap, &msg, 1); | ||
510 | dprintk(1, "probe 0x%02x @ %s: %s\n", | ||
511 | msg.addr, adap->name, | ||
512 | (1 == rc) ? "yes" : "no"); | ||
513 | |||
514 | /* Now do the probe. The controller does not respond | ||
515 | to 0-byte reads, so we use a 1-byte read instead. */ | ||
516 | msg.addr = 0x30; | ||
517 | msg.len = 1; | ||
518 | msg.buf = &temp; | ||
519 | rc = i2c_transfer(adap, &msg, 1); | ||
520 | dprintk(1, "probe 0x%02x @ %s: %s\n", | ||
521 | msg.addr, adap->name, | ||
522 | (1 == rc) ? "yes" : "no"); | ||
523 | if (1 == rc) | ||
524 | ir_attach(adap, msg.addr, 0, 0); | ||
525 | } | ||
526 | |||
471 | return 0; | 527 | return 0; |
472 | } | 528 | } |
473 | 529 | ||