* [PATCH 0/2] Add more protocols to em28xx IR
@ 2012-12-15 12:29 Mauro Carvalho Chehab
2012-12-15 12:29 ` [PATCH 1/2] [media] em28xx: add support for NEC proto variants on em2874 and upper Mauro Carvalho Chehab
2012-12-15 12:29 ` [PATCH 2/2] [media] em28xx: add support for RC6 mode 0 on devices that support it Mauro Carvalho Chehab
0 siblings, 2 replies; 4+ messages in thread
From: Mauro Carvalho Chehab @ 2012-12-15 12:29 UTC (permalink / raw)
Cc: Mauro Carvalho Chehab, Linux Media Mailing List
This patch series add support for NEC protocol variants and to RC6
mode 0 on em2874 and newer devices.
It was tested with a Terratec HTC device, and using 4 different remote
control models:
- RC5 Hauppauge Grey remote;
- NEC Terratec remote;
- NEC-like 24-bits protocol Pixelview remote;
- Philips RC6 remote.
It work properly with all the above remotes.
Mauro Carvalho Chehab (2):
[media] em28xx: add support for NEC proto variants on em2874 and
upper
[media] em28xx: add support for RC6 mode 0 on devices that support it
drivers/media/usb/em28xx/em28xx-input.c | 149 ++++++++++++++++++++++++--------
drivers/media/usb/em28xx/em28xx-reg.h | 1 +
2 files changed, 114 insertions(+), 36 deletions(-)
--
1.7.11.7
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH 1/2] [media] em28xx: add support for NEC proto variants on em2874 and upper 2012-12-15 12:29 [PATCH 0/2] Add more protocols to em28xx IR Mauro Carvalho Chehab @ 2012-12-15 12:29 ` Mauro Carvalho Chehab 2012-12-15 16:10 ` Frank Schäfer 2012-12-15 12:29 ` [PATCH 2/2] [media] em28xx: add support for RC6 mode 0 on devices that support it Mauro Carvalho Chehab 1 sibling, 1 reply; 4+ messages in thread From: Mauro Carvalho Chehab @ 2012-12-15 12:29 UTC (permalink / raw) Cc: Mauro Carvalho Chehab, Linux Media Mailing List By disabling the NEC parity check, it is possible to handle all 3 NEC protocol variants (32, 24 or 16 bits). Change the driver in order to handle all of them. Unfortunately, em2860/em2863 provide only 16 bits for the IR scancode, even when NEC parity is disabled. So, this change should affect only em2874 and newer devices, with provides up to 32 bits for the scancode. Tested with one NEC-16, one NEC-24 and one RC5 IR. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/usb/em28xx/em28xx-input.c | 58 +++++++++++++++++++++------------ drivers/media/usb/em28xx/em28xx-reg.h | 1 + 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index 660bf80..507370c 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c @@ -57,8 +57,8 @@ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); struct em28xx_ir_poll_result { unsigned int toggle_bit:1; unsigned int read_count:7; - u8 rc_address; - u8 rc_data[4]; /* 1 byte on em2860/2880, 4 on em2874 */ + + u32 scancode; }; struct em28xx_IR { @@ -72,6 +72,7 @@ struct em28xx_IR { struct delayed_work work; unsigned int full_code:1; unsigned int last_readcount; + u64 rc_type; int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *); }; @@ -236,11 +237,8 @@ static int default_polling_getkey(struct em28xx_IR *ir, /* Infrared read count (Reg 0x45[6:0] */ poll_result->read_count = (msg[0] & 0x7f); - /* Remote Control Address (Reg 0x46) */ - poll_result->rc_address = msg[1]; - - /* Remote Control Data (Reg 0x47) */ - poll_result->rc_data[0] = msg[2]; + /* Remote Control Address/Data (Regs 0x46/0x47) */ + poll_result->scancode = msg[1] << 8 | msg[2]; return 0; } @@ -266,13 +264,32 @@ static int em2874_polling_getkey(struct em28xx_IR *ir, /* Infrared read count (Reg 0x51[6:0] */ poll_result->read_count = (msg[0] & 0x7f); - /* Remote Control Address (Reg 0x52) */ - poll_result->rc_address = msg[1]; - - /* Remote Control Data (Reg 0x53-55) */ - poll_result->rc_data[0] = msg[2]; - poll_result->rc_data[1] = msg[3]; - poll_result->rc_data[2] = msg[4]; + /* + * Remote Control Address (Reg 0x52) + * Remote Control Data (Reg 0x53-0x55) + */ + switch (ir->rc_type) { + case RC_BIT_RC5: + poll_result->scancode = msg[1] << 8 | msg[2]; + break; + case RC_BIT_NEC: + if ((msg[3] ^ msg[4]) != 0xff) /* 32 bits NEC */ + poll_result->scancode = (msg[1] << 24) | + (msg[2] << 16) | + (msg[3] << 8) | + msg[4]; + else if ((msg[1] ^ msg[2]) != 0xff) /* 24 bits NEC */ + poll_result->scancode = (msg[1] << 16) | + (msg[2] << 8) | + msg[3]; + else /* Normal NEC */ + poll_result->scancode = msg[1] << 8 | msg[3]; + break; + default: + poll_result->scancode = (msg[1] << 24) | (msg[2] << 16) | + (msg[3] << 8) | msg[4]; + break; + } return 0; } @@ -294,17 +311,16 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir) } if (unlikely(poll_result.read_count != ir->last_readcount)) { - dprintk("%s: toggle: %d, count: %d, key 0x%02x%02x\n", __func__, + dprintk("%s: toggle: %d, count: %d, key 0x%04x\n", __func__, poll_result.toggle_bit, poll_result.read_count, - poll_result.rc_address, poll_result.rc_data[0]); + poll_result.scancode); if (ir->full_code) rc_keydown(ir->rc, - poll_result.rc_address << 8 | - poll_result.rc_data[0], + poll_result.scancode, poll_result.toggle_bit); else rc_keydown(ir->rc, - poll_result.rc_data[0], + poll_result.scancode & 0xff, poll_result.toggle_bit); if (ir->dev->chip_id == CHIP_ID_EM2874 || @@ -360,12 +376,14 @@ static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type) *rc_type = RC_BIT_RC5; } else if (*rc_type & RC_BIT_NEC) { dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; - ir_config = EM2874_IR_NEC; + 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; + ir->rc_type = *rc_type; + em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, EM28XX_XCLK_IR_RC5_MODE); diff --git a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h index 6ff3682..2ad3573 100644 --- a/drivers/media/usb/em28xx/em28xx-reg.h +++ b/drivers/media/usb/em28xx/em28xx-reg.h @@ -177,6 +177,7 @@ /* em2874 IR config register (0x50) */ #define EM2874_IR_NEC 0x00 +#define EM2874_IR_NEC_NO_PARITY 0x01 #define EM2874_IR_RC5 0x04 #define EM2874_IR_RC6_MODE_0 0x08 #define EM2874_IR_RC6_MODE_6A 0x0b -- 1.7.11.7 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 1/2] [media] em28xx: add support for NEC proto variants on em2874 and upper 2012-12-15 12:29 ` [PATCH 1/2] [media] em28xx: add support for NEC proto variants on em2874 and upper Mauro Carvalho Chehab @ 2012-12-15 16:10 ` Frank Schäfer 0 siblings, 0 replies; 4+ messages in thread From: Frank Schäfer @ 2012-12-15 16:10 UTC (permalink / raw) To: Mauro Carvalho Chehab Am 15.12.2012 13:29, schrieb Mauro Carvalho Chehab: > By disabling the NEC parity check, it is possible to handle all 3 NEC > protocol variants (32, 24 or 16 bits). > > Change the driver in order to handle all of them. > > Unfortunately, em2860/em2863 provide only 16 bits for the IR scancode, > even when NEC parity is disabled. So, this change should affect only > em2874 and newer devices, with provides up to 32 bits for the scancode. > > Tested with one NEC-16, one NEC-24 and one RC5 IR. > > Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> > --- > drivers/media/usb/em28xx/em28xx-input.c | 58 +++++++++++++++++++++------------ > drivers/media/usb/em28xx/em28xx-reg.h | 1 + > 2 files changed, 39 insertions(+), 20 deletions(-) > > diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c > index 660bf80..507370c 100644 > --- a/drivers/media/usb/em28xx/em28xx-input.c > +++ b/drivers/media/usb/em28xx/em28xx-input.c > @@ -57,8 +57,8 @@ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); > struct em28xx_ir_poll_result { > unsigned int toggle_bit:1; > unsigned int read_count:7; > - u8 rc_address; > - u8 rc_data[4]; /* 1 byte on em2860/2880, 4 on em2874 */ > + > + u32 scancode; > }; > > struct em28xx_IR { > @@ -72,6 +72,7 @@ struct em28xx_IR { > struct delayed_work work; > unsigned int full_code:1; > unsigned int last_readcount; > + u64 rc_type; > > int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *); > }; > @@ -236,11 +237,8 @@ static int default_polling_getkey(struct em28xx_IR *ir, > /* Infrared read count (Reg 0x45[6:0] */ > poll_result->read_count = (msg[0] & 0x7f); > > - /* Remote Control Address (Reg 0x46) */ > - poll_result->rc_address = msg[1]; > - > - /* Remote Control Data (Reg 0x47) */ > - poll_result->rc_data[0] = msg[2]; > + /* Remote Control Address/Data (Regs 0x46/0x47) */ > + poll_result->scancode = msg[1] << 8 | msg[2]; > > return 0; > } > @@ -266,13 +264,32 @@ static int em2874_polling_getkey(struct em28xx_IR *ir, > /* Infrared read count (Reg 0x51[6:0] */ > poll_result->read_count = (msg[0] & 0x7f); > > - /* Remote Control Address (Reg 0x52) */ > - poll_result->rc_address = msg[1]; > - > - /* Remote Control Data (Reg 0x53-55) */ > - poll_result->rc_data[0] = msg[2]; > - poll_result->rc_data[1] = msg[3]; > - poll_result->rc_data[2] = msg[4]; > + /* > + * Remote Control Address (Reg 0x52) > + * Remote Control Data (Reg 0x53-0x55) > + */ Should be + /* + * Remote Control Scan Code (Reg 0x52-0x55) + */ > + switch (ir->rc_type) { > + case RC_BIT_RC5: > + poll_result->scancode = msg[1] << 8 | msg[2]; > + break; > + case RC_BIT_NEC: > + if ((msg[3] ^ msg[4]) != 0xff) /* 32 bits NEC */ > + poll_result->scancode = (msg[1] << 24) | > + (msg[2] << 16) | > + (msg[3] << 8) | > + msg[4]; > + else if ((msg[1] ^ msg[2]) != 0xff) /* 24 bits NEC */ > + poll_result->scancode = (msg[1] << 16) | > + (msg[2] << 8) | > + msg[3]; > + else /* Normal NEC */ > + poll_result->scancode = msg[1] << 8 | msg[3]; > + break; > + default: > + poll_result->scancode = (msg[1] << 24) | (msg[2] << 16) | > + (msg[3] << 8) | msg[4]; > + break; > + } > > return 0; > } > @@ -294,17 +311,16 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir) > } > > if (unlikely(poll_result.read_count != ir->last_readcount)) { > - dprintk("%s: toggle: %d, count: %d, key 0x%02x%02x\n", __func__, > + dprintk("%s: toggle: %d, count: %d, key 0x%04x\n", __func__, > poll_result.toggle_bit, poll_result.read_count, > - poll_result.rc_address, poll_result.rc_data[0]); > + poll_result.scancode); > if (ir->full_code) > rc_keydown(ir->rc, > - poll_result.rc_address << 8 | > - poll_result.rc_data[0], > + poll_result.scancode, > poll_result.toggle_bit); > else > rc_keydown(ir->rc, > - poll_result.rc_data[0], > + poll_result.scancode & 0xff, > poll_result.toggle_bit); > > if (ir->dev->chip_id == CHIP_ID_EM2874 || > @@ -360,12 +376,14 @@ static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type) > *rc_type = RC_BIT_RC5; > } else if (*rc_type & RC_BIT_NEC) { > dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; > - ir_config = EM2874_IR_NEC; > + 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; > > + ir->rc_type = *rc_type; > + This is actually a bug fix, right ? The patch looks good. Regards, Frank > em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, > EM28XX_XCLK_IR_RC5_MODE); > > diff --git a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h > index 6ff3682..2ad3573 100644 > --- a/drivers/media/usb/em28xx/em28xx-reg.h > +++ b/drivers/media/usb/em28xx/em28xx-reg.h > @@ -177,6 +177,7 @@ > > /* em2874 IR config register (0x50) */ > #define EM2874_IR_NEC 0x00 > +#define EM2874_IR_NEC_NO_PARITY 0x01 > #define EM2874_IR_RC5 0x04 > #define EM2874_IR_RC6_MODE_0 0x08 > #define EM2874_IR_RC6_MODE_6A 0x0b ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 2/2] [media] em28xx: add support for RC6 mode 0 on devices that support it 2012-12-15 12:29 [PATCH 0/2] Add more protocols to em28xx IR Mauro Carvalho Chehab 2012-12-15 12:29 ` [PATCH 1/2] [media] em28xx: add support for NEC proto variants on em2874 and upper Mauro Carvalho Chehab @ 2012-12-15 12:29 ` Mauro Carvalho Chehab 1 sibling, 0 replies; 4+ messages in thread From: Mauro Carvalho Chehab @ 2012-12-15 12:29 UTC (permalink / raw) Cc: Mauro Carvalho Chehab, Linux Media Mailing List 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> --- drivers/media/usb/em28xx/em28xx-input.c | 93 +++++++++++++++++++++++++++------ 1 file changed, 76 insertions(+), 17 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index 507370c..3899ea8 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c @@ -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) { - 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 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) +{ + struct em28xx_IR *ir = rc_dev->priv; + struct em28xx *dev = ir->dev; + u8 ir_config = EM2874_IR_RC5; + + /* 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; -- 1.7.11.7 ^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2012-12-15 16:10 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-12-15 12:29 [PATCH 0/2] Add more protocols to em28xx IR Mauro Carvalho Chehab 2012-12-15 12:29 ` [PATCH 1/2] [media] em28xx: add support for NEC proto variants on em2874 and upper Mauro Carvalho Chehab 2012-12-15 16:10 ` Frank Schäfer 2012-12-15 12:29 ` [PATCH 2/2] [media] em28xx: add support for RC6 mode 0 on devices that support it Mauro Carvalho Chehab
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).