aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2012-12-15 06:29:11 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-12-21 18:15:52 -0500
commit105e3687ada4ebe6dfbda7abc3b16106f86a787d (patch)
tree5ee99fa789d1dee9ca1c1ad8e56c354c92b8c37d
parent37285bf2a516a808f1282540badcaf847340a154 (diff)
[media] em28xx: add support for NEC proto variants on em2874 and upper
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>
-rw-r--r--drivers/media/usb/em28xx/em28xx-input.c58
-rw-r--r--drivers/media/usb/em28xx/em28xx-reg.h1
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 660bf803c9e4..507370c5217d 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]");
57struct em28xx_ir_poll_result { 57struct em28xx_ir_poll_result {
58 unsigned int toggle_bit:1; 58 unsigned int toggle_bit:1;
59 unsigned int read_count:7; 59 unsigned int read_count:7;
60 u8 rc_address; 60
61 u8 rc_data[4]; /* 1 byte on em2860/2880, 4 on em2874 */ 61 u32 scancode;
62}; 62};
63 63
64struct em28xx_IR { 64struct em28xx_IR {
@@ -72,6 +72,7 @@ struct em28xx_IR {
72 struct delayed_work work; 72 struct delayed_work work;
73 unsigned int full_code:1; 73 unsigned int full_code:1;
74 unsigned int last_readcount; 74 unsigned int last_readcount;
75 u64 rc_type;
75 76
76 int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *); 77 int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *);
77}; 78};
@@ -236,11 +237,8 @@ static int default_polling_getkey(struct em28xx_IR *ir,
236 /* Infrared read count (Reg 0x45[6:0] */ 237 /* Infrared read count (Reg 0x45[6:0] */
237 poll_result->read_count = (msg[0] & 0x7f); 238 poll_result->read_count = (msg[0] & 0x7f);
238 239
239 /* Remote Control Address (Reg 0x46) */ 240 /* Remote Control Address/Data (Regs 0x46/0x47) */
240 poll_result->rc_address = msg[1]; 241 poll_result->scancode = msg[1] << 8 | msg[2];
241
242 /* Remote Control Data (Reg 0x47) */
243 poll_result->rc_data[0] = msg[2];
244 242
245 return 0; 243 return 0;
246} 244}
@@ -266,13 +264,32 @@ static int em2874_polling_getkey(struct em28xx_IR *ir,
266 /* Infrared read count (Reg 0x51[6:0] */ 264 /* Infrared read count (Reg 0x51[6:0] */
267 poll_result->read_count = (msg[0] & 0x7f); 265 poll_result->read_count = (msg[0] & 0x7f);
268 266
269 /* Remote Control Address (Reg 0x52) */ 267 /*
270 poll_result->rc_address = msg[1]; 268 * Remote Control Address (Reg 0x52)
271 269 * Remote Control Data (Reg 0x53-0x55)
272 /* Remote Control Data (Reg 0x53-55) */ 270 */
273 poll_result->rc_data[0] = msg[2]; 271 switch (ir->rc_type) {
274 poll_result->rc_data[1] = msg[3]; 272 case RC_BIT_RC5:
275 poll_result->rc_data[2] = msg[4]; 273 poll_result->scancode = msg[1] << 8 | msg[2];
274 break;
275 case RC_BIT_NEC:
276 if ((msg[3] ^ msg[4]) != 0xff) /* 32 bits NEC */
277 poll_result->scancode = (msg[1] << 24) |
278 (msg[2] << 16) |
279 (msg[3] << 8) |
280 msg[4];
281 else if ((msg[1] ^ msg[2]) != 0xff) /* 24 bits NEC */
282 poll_result->scancode = (msg[1] << 16) |
283 (msg[2] << 8) |
284 msg[3];
285 else /* Normal NEC */
286 poll_result->scancode = msg[1] << 8 | msg[3];
287 break;
288 default:
289 poll_result->scancode = (msg[1] << 24) | (msg[2] << 16) |
290 (msg[3] << 8) | msg[4];
291 break;
292 }
276 293
277 return 0; 294 return 0;
278} 295}
@@ -294,17 +311,16 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir)
294 } 311 }
295 312
296 if (unlikely(poll_result.read_count != ir->last_readcount)) { 313 if (unlikely(poll_result.read_count != ir->last_readcount)) {
297 dprintk("%s: toggle: %d, count: %d, key 0x%02x%02x\n", __func__, 314 dprintk("%s: toggle: %d, count: %d, key 0x%04x\n", __func__,
298 poll_result.toggle_bit, poll_result.read_count, 315 poll_result.toggle_bit, poll_result.read_count,
299 poll_result.rc_address, poll_result.rc_data[0]); 316 poll_result.scancode);
300 if (ir->full_code) 317 if (ir->full_code)
301 rc_keydown(ir->rc, 318 rc_keydown(ir->rc,
302 poll_result.rc_address << 8 | 319 poll_result.scancode,
303 poll_result.rc_data[0],
304 poll_result.toggle_bit); 320 poll_result.toggle_bit);
305 else 321 else
306 rc_keydown(ir->rc, 322 rc_keydown(ir->rc,
307 poll_result.rc_data[0], 323 poll_result.scancode & 0xff,
308 poll_result.toggle_bit); 324 poll_result.toggle_bit);
309 325
310 if (ir->dev->chip_id == CHIP_ID_EM2874 || 326 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)
360 *rc_type = RC_BIT_RC5; 376 *rc_type = RC_BIT_RC5;
361 } else if (*rc_type & RC_BIT_NEC) { 377 } else if (*rc_type & RC_BIT_NEC) {
362 dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; 378 dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE;
363 ir_config = EM2874_IR_NEC; 379 ir_config = EM2874_IR_NEC | EM2874_IR_NEC_NO_PARITY;
364 ir->full_code = 1; 380 ir->full_code = 1;
365 *rc_type = RC_BIT_NEC; 381 *rc_type = RC_BIT_NEC;
366 } else if (*rc_type != RC_BIT_UNKNOWN) 382 } else if (*rc_type != RC_BIT_UNKNOWN)
367 rc = -EINVAL; 383 rc = -EINVAL;
368 384
385 ir->rc_type = *rc_type;
386
369 em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, 387 em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk,
370 EM28XX_XCLK_IR_RC5_MODE); 388 EM28XX_XCLK_IR_RC5_MODE);
371 389
diff --git a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h
index 6ff368297f6e..2ad357354d81 100644
--- a/drivers/media/usb/em28xx/em28xx-reg.h
+++ b/drivers/media/usb/em28xx/em28xx-reg.h
@@ -177,6 +177,7 @@
177 177
178/* em2874 IR config register (0x50) */ 178/* em2874 IR config register (0x50) */
179#define EM2874_IR_NEC 0x00 179#define EM2874_IR_NEC 0x00
180#define EM2874_IR_NEC_NO_PARITY 0x01
180#define EM2874_IR_RC5 0x04 181#define EM2874_IR_RC5 0x04
181#define EM2874_IR_RC6_MODE_0 0x08 182#define EM2874_IR_RC6_MODE_0 0x08
182#define EM2874_IR_RC6_MODE_6A 0x0b 183#define EM2874_IR_RC6_MODE_6A 0x0b