aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/em28xx/em28xx-input.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-input.c')
-rw-r--r--drivers/media/video/em28xx/em28xx-input.c83
1 files changed, 61 insertions, 22 deletions
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c
index 7a0fe3816e3d..af0d935c29be 100644
--- a/drivers/media/video/em28xx/em28xx-input.c
+++ b/drivers/media/video/em28xx/em28xx-input.c
@@ -70,6 +70,7 @@ struct em28xx_IR {
int polling;
struct delayed_work work;
unsigned int last_toggle:1;
+ unsigned int full_code:1;
unsigned int last_readcount;
unsigned int repeat_interval;
@@ -111,10 +112,13 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
unsigned char buf[2];
- unsigned char code;
+ u16 code;
+ int size;
/* poll IR chip */
- if (2 != i2c_master_recv(ir->c, buf, 2))
+ size = i2c_master_recv(ir->c, buf, sizeof(buf));
+
+ if (size != 2)
return -EIO;
/* Does eliminate repeated parity code */
@@ -123,16 +127,30 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
ir->old = buf[1];
- /* Rearranges bits to the right order */
- code = ((buf[0]&0x01)<<5) | /* 0010 0000 */
- ((buf[0]&0x02)<<3) | /* 0001 0000 */
- ((buf[0]&0x04)<<1) | /* 0000 1000 */
- ((buf[0]&0x08)>>1) | /* 0000 0100 */
- ((buf[0]&0x10)>>3) | /* 0000 0010 */
- ((buf[0]&0x20)>>5); /* 0000 0001 */
-
- i2cdprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x)\n",
- code, buf[0]);
+ /*
+ * Rearranges bits to the right order.
+ * The bit order were determined experimentally by using
+ * The original Hauppauge Grey IR and another RC5 that uses addr=0x08
+ * The RC5 code has 14 bits, but we've experimentally determined
+ * the meaning for only 11 bits.
+ * So, the code translation is not complete. Yet, it is enough to
+ * work with the provided RC5 IR.
+ */
+ code =
+ ((buf[0] & 0x01) ? 0x0020 : 0) | /* 0010 0000 */
+ ((buf[0] & 0x02) ? 0x0010 : 0) | /* 0001 0000 */
+ ((buf[0] & 0x04) ? 0x0008 : 0) | /* 0000 1000 */
+ ((buf[0] & 0x08) ? 0x0004 : 0) | /* 0000 0100 */
+ ((buf[0] & 0x10) ? 0x0002 : 0) | /* 0000 0010 */
+ ((buf[0] & 0x20) ? 0x0001 : 0) | /* 0000 0001 */
+ ((buf[1] & 0x08) ? 0x1000 : 0) | /* 0001 0000 */
+ ((buf[1] & 0x10) ? 0x0800 : 0) | /* 0000 1000 */
+ ((buf[1] & 0x20) ? 0x0400 : 0) | /* 0000 0100 */
+ ((buf[1] & 0x40) ? 0x0200 : 0) | /* 0000 0010 */
+ ((buf[1] & 0x80) ? 0x0100 : 0); /* 0000 0001 */
+
+ i2cdprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x%02x)\n",
+ code, buf[1], buf[0]);
/* return key */
*ir_key = code;
@@ -246,9 +264,10 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir)
return;
}
- dprintk("ir->get_key result tb=%02x rc=%02x lr=%02x data=%02x\n",
+ dprintk("ir->get_key result tb=%02x rc=%02x lr=%02x data=%02x%02x\n",
poll_result.toggle_bit, poll_result.read_count,
- ir->last_readcount, poll_result.rc_data[0]);
+ ir->last_readcount, poll_result.rc_address,
+ poll_result.rc_data[0]);
if (ir->dev->chip_id == CHIP_ID_EM2874) {
/* The em2874 clears the readcount field every time the
@@ -282,8 +301,15 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir)
if (do_sendkey) {
dprintk("sending keypress\n");
- ir_input_keydown(ir->input, &ir->ir, poll_result.rc_data[0],
- poll_result.rc_data[0]);
+
+ if (ir->full_code)
+ ir_input_keydown(ir->input, &ir->ir,
+ poll_result.rc_address << 8 |
+ poll_result.rc_data[0]);
+ else
+ ir_input_keydown(ir->input, &ir->ir,
+ poll_result.rc_data[0]);
+
ir_input_nokey(ir->input, &ir->ir);
}
@@ -328,6 +354,19 @@ int em28xx_ir_init(struct em28xx *dev)
goto err_out_free;
ir->input = input_dev;
+ ir_config = EM2874_IR_RC5;
+
+ /* Adjust xclk based o IR table for RC5/NEC tables */
+ if (dev->board.ir_codes->ir_type == IR_TYPE_RC5) {
+ dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE;
+ ir->full_code = 1;
+ } else if (dev->board.ir_codes->ir_type == IR_TYPE_NEC) {
+ dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE;
+ ir_config = EM2874_IR_NEC;
+ ir->full_code = 1;
+ }
+ em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk,
+ EM28XX_XCLK_IR_RC5_MODE);
/* Setup the proper handler based on the chip */
switch (dev->chip_id) {
@@ -337,8 +376,6 @@ int em28xx_ir_init(struct em28xx *dev)
break;
case CHIP_ID_EM2874:
ir->get_key = em2874_polling_getkey;
- /* For now we only support RC5, so enable it */
- ir_config = EM2874_IR_RC5;
em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1);
break;
default:
@@ -356,7 +393,10 @@ int em28xx_ir_init(struct em28xx *dev)
usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
strlcat(ir->phys, "/input0", sizeof(ir->phys));
- ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER, dev->board.ir_codes);
+ err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER);
+ if (err < 0)
+ goto err_out_free;
+
input_dev->name = ir->name;
input_dev->phys = ir->phys;
input_dev->id.bustype = BUS_USB;
@@ -372,7 +412,7 @@ int em28xx_ir_init(struct em28xx *dev)
em28xx_ir_start(ir);
/* all done */
- err = input_register_device(ir->input);
+ err = ir_input_register(ir->input, dev->board.ir_codes);
if (err)
goto err_out_stop;
@@ -381,7 +421,6 @@ int em28xx_ir_init(struct em28xx *dev)
em28xx_ir_stop(ir);
dev->ir = NULL;
err_out_free:
- input_free_device(input_dev);
kfree(ir);
return err;
}
@@ -395,7 +434,7 @@ int em28xx_ir_fini(struct em28xx *dev)
return 0;
em28xx_ir_stop(ir);
- input_unregister_device(ir->input);
+ ir_input_unregister(ir->input);
kfree(ir);
/* done */