[media] em28xx: add support for RC6 mode 0 on devices that support it
Newer em28xx chipsets (em2874 and upper) are capable of supporting RC6 codes, on both mode 0 (command mode, 16 bits payload size, similar to RC5, also called "Philips mode") and mode 6a (OEM command mode, with offers a few alternatives with regards to the payload size). I don't have any mode 6a control ATM to test it, so, I opted to add support only to mode 0. After this patch, adding support to mode 6a should not be hard. Tested with a Philips television remote controller. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Родитель
105e3687ad
Коммит
0dae883923
|
@ -285,6 +285,9 @@ static int em2874_polling_getkey(struct em28xx_IR *ir,
|
|||
else /* Normal NEC */
|
||||
poll_result->scancode = msg[1] << 8 | msg[3];
|
||||
break;
|
||||
case RC_BIT_RC6_0:
|
||||
poll_result->scancode = msg[1] << 8 | msg[2];
|
||||
break;
|
||||
default:
|
||||
poll_result->scancode = (msg[1] << 24) | (msg[2] << 16) |
|
||||
(msg[3] << 8) | msg[4];
|
||||
|
@ -361,15 +364,42 @@ static void em28xx_ir_stop(struct rc_dev *rc)
|
|||
cancel_delayed_work_sync(&ir->work);
|
||||
}
|
||||
|
||||
static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type)
|
||||
static int em2860_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type)
|
||||
{
|
||||
struct em28xx_IR *ir = rc_dev->priv;
|
||||
struct em28xx *dev = ir->dev;
|
||||
|
||||
/* Adjust xclk based on IR table for RC5/NEC tables */
|
||||
if (*rc_type & RC_BIT_RC5) {
|
||||
dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE;
|
||||
ir->full_code = 1;
|
||||
*rc_type = RC_BIT_RC5;
|
||||
} else if (*rc_type & RC_BIT_NEC) {
|
||||
dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE;
|
||||
ir->full_code = 1;
|
||||
*rc_type = RC_BIT_NEC;
|
||||
} else if (*rc_type & RC_BIT_UNKNOWN) {
|
||||
*rc_type = RC_BIT_UNKNOWN;
|
||||
} else {
|
||||
*rc_type = ir->rc_type;
|
||||
return -EINVAL;
|
||||
}
|
||||
ir->get_key = default_polling_getkey;
|
||||
em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk,
|
||||
EM28XX_XCLK_IR_RC5_MODE);
|
||||
|
||||
ir->rc_type = *rc_type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int em2874_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type)
|
||||
{
|
||||
int rc = 0;
|
||||
struct em28xx_IR *ir = rc_dev->priv;
|
||||
struct em28xx *dev = ir->dev;
|
||||
u8 ir_config = EM2874_IR_RC5;
|
||||
|
||||
/* Adjust xclk based o IR table for RC5/NEC tables */
|
||||
|
||||
/* Adjust xclk and set type based on IR table for RC5/NEC/RC6 tables */
|
||||
if (*rc_type & RC_BIT_RC5) {
|
||||
dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE;
|
||||
ir->full_code = 1;
|
||||
|
@ -379,33 +409,47 @@ static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type)
|
|||
ir_config = EM2874_IR_NEC | EM2874_IR_NEC_NO_PARITY;
|
||||
ir->full_code = 1;
|
||||
*rc_type = RC_BIT_NEC;
|
||||
} else if (*rc_type != RC_BIT_UNKNOWN)
|
||||
rc = -EINVAL;
|
||||
} else if (*rc_type & RC_BIT_RC6_0) {
|
||||
dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE;
|
||||
ir_config = EM2874_IR_RC6_MODE_0;
|
||||
ir->full_code = 1;
|
||||
*rc_type = RC_BIT_RC6_0;
|
||||
} else if (*rc_type & RC_BIT_UNKNOWN) {
|
||||
*rc_type = RC_BIT_UNKNOWN;
|
||||
} else {
|
||||
*rc_type = ir->rc_type;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ir->rc_type = *rc_type;
|
||||
ir->get_key = em2874_polling_getkey;
|
||||
em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1);
|
||||
|
||||
em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk,
|
||||
EM28XX_XCLK_IR_RC5_MODE);
|
||||
|
||||
ir->rc_type = *rc_type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type)
|
||||
{
|
||||
struct em28xx_IR *ir = rc_dev->priv;
|
||||
struct em28xx *dev = ir->dev;
|
||||
|
||||
/* Setup the proper handler based on the chip */
|
||||
switch (dev->chip_id) {
|
||||
case CHIP_ID_EM2860:
|
||||
case CHIP_ID_EM2883:
|
||||
ir->get_key = default_polling_getkey;
|
||||
break;
|
||||
return em2860_ir_change_protocol(rc_dev, rc_type);
|
||||
case CHIP_ID_EM2884:
|
||||
case CHIP_ID_EM2874:
|
||||
case CHIP_ID_EM28174:
|
||||
ir->get_key = em2874_polling_getkey;
|
||||
em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1);
|
||||
break;
|
||||
return em2874_ir_change_protocol(rc_dev, rc_type);
|
||||
default:
|
||||
printk("Unrecognized em28xx chip id 0x%02x: IR not supported\n",
|
||||
dev->chip_id);
|
||||
rc = -EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void em28xx_register_i2c_ir(struct em28xx *dev)
|
||||
|
@ -573,6 +617,21 @@ static int em28xx_ir_init(struct em28xx *dev)
|
|||
rc->open = em28xx_ir_start;
|
||||
rc->close = em28xx_ir_stop;
|
||||
|
||||
switch (dev->chip_id) {
|
||||
case CHIP_ID_EM2860:
|
||||
case CHIP_ID_EM2883:
|
||||
rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC;
|
||||
break;
|
||||
case CHIP_ID_EM2884:
|
||||
case CHIP_ID_EM2874:
|
||||
case CHIP_ID_EM28174:
|
||||
rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC | RC_BIT_RC6_0;
|
||||
break;
|
||||
default:
|
||||
err = -ENODEV;
|
||||
goto err_out_free;
|
||||
}
|
||||
|
||||
/* By default, keep protocol field untouched */
|
||||
rc_type = RC_BIT_UNKNOWN;
|
||||
err = em28xx_ir_change_protocol(rc, &rc_type);
|
||||
|
@ -615,9 +674,9 @@ static int em28xx_ir_init(struct em28xx *dev)
|
|||
|
||||
return 0;
|
||||
|
||||
err_out_stop:
|
||||
err_out_stop:
|
||||
dev->ir = NULL;
|
||||
err_out_free:
|
||||
err_out_free:
|
||||
rc_free_device(rc);
|
||||
kfree(ir);
|
||||
return err;
|
||||
|
|
Загрузка…
Ссылка в новой задаче