aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2010-04-04 13:06:55 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-05-19 11:56:58 -0400
commit9dfe4e8339499bfe8e9a362fefc290b4cb9c3803 (patch)
treea42ab74108d03f8009f01e2fc896df15638dfc06
parent4f9256b496677adf799342cee7d406dd46e566d9 (diff)
V4L/DVB: ir-core: Add support for badly-implemented hardware decoders
A few hardware Remote Controller decoders, even using a standard protocol, aren't able to provide the entire scancode. Due to that, the capability of using other IR's are limited on those hardware. Adds a way to indicate to ir-core what are the bits that the hardware provides, from a scancode, allowing the addition of a complete IR table to the kernel and allowing a limited support for changing the Remote Controller on those devices. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/IR/ir-keytable.c25
-rw-r--r--drivers/media/IR/keymaps/Makefile1
-rw-r--r--drivers/media/IR/keymaps/rc-pixelview-mk12.c83
-rw-r--r--drivers/media/video/cx88/cx88-input.c30
-rw-r--r--include/media/ir-core.h24
-rw-r--r--include/media/rc-map.h3
6 files changed, 153 insertions, 13 deletions
diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c
index a89456932f7c..af7400bc906f 100644
--- a/drivers/media/IR/ir-keytable.c
+++ b/drivers/media/IR/ir-keytable.c
@@ -89,6 +89,18 @@ static int ir_do_setkeycode(struct input_dev *dev,
89{ 89{
90 unsigned int i; 90 unsigned int i;
91 int old_keycode = KEY_RESERVED; 91 int old_keycode = KEY_RESERVED;
92 struct ir_input_dev *ir_dev = input_get_drvdata(dev);
93
94 /*
95 * Unfortunately, some hardware-based IR decoders don't provide
96 * all bits for the complete IR code. In general, they provide only
97 * the command part of the IR code. Yet, as it is possible to replace
98 * the provided IR with another one, it is needed to allow loading
99 * IR tables from other remotes. So,
100 */
101 if (ir_dev->props && ir_dev->props->scanmask) {
102 scancode &= ir_dev->props->scanmask;
103 }
92 104
93 /* First check if we already have a mapping for this ir command */ 105 /* First check if we already have a mapping for this ir command */
94 for (i = 0; i < rc_tab->len; i++) { 106 for (i = 0; i < rc_tab->len; i++) {
@@ -448,6 +460,13 @@ int __ir_input_register(struct input_dev *input_dev,
448 sizeof(struct ir_scancode)); 460 sizeof(struct ir_scancode));
449 ir_dev->rc_tab.scan = kmalloc(ir_dev->rc_tab.alloc, GFP_KERNEL); 461 ir_dev->rc_tab.scan = kmalloc(ir_dev->rc_tab.alloc, GFP_KERNEL);
450 ir_dev->rc_tab.size = ir_dev->rc_tab.alloc / sizeof(struct ir_scancode); 462 ir_dev->rc_tab.size = ir_dev->rc_tab.alloc / sizeof(struct ir_scancode);
463 if (props) {
464 ir_dev->props = props;
465 if (props->open)
466 input_dev->open = ir_open;
467 if (props->close)
468 input_dev->close = ir_close;
469 }
451 470
452 if (!ir_dev->rc_tab.scan) { 471 if (!ir_dev->rc_tab.scan) {
453 rc = -ENOMEM; 472 rc = -ENOMEM;
@@ -465,12 +484,6 @@ int __ir_input_register(struct input_dev *input_dev,
465 goto out_table; 484 goto out_table;
466 } 485 }
467 486
468 ir_dev->props = props;
469 if (props && props->open)
470 input_dev->open = ir_open;
471 if (props && props->close)
472 input_dev->close = ir_close;
473
474 rc = ir_register_class(input_dev); 487 rc = ir_register_class(input_dev);
475 if (rc < 0) 488 if (rc < 0)
476 goto out_table; 489 goto out_table;
diff --git a/drivers/media/IR/keymaps/Makefile b/drivers/media/IR/keymaps/Makefile
index 937b7db9c9d2..c4d891d79491 100644
--- a/drivers/media/IR/keymaps/Makefile
+++ b/drivers/media/IR/keymaps/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
46 rc-pinnacle-grey.o \ 46 rc-pinnacle-grey.o \
47 rc-pinnacle-pctv-hd.o \ 47 rc-pinnacle-pctv-hd.o \
48 rc-pixelview.o \ 48 rc-pixelview.o \
49 rc-pixelview-mk12.o \
49 rc-pixelview-new.o \ 50 rc-pixelview-new.o \
50 rc-powercolor-real-angel.o \ 51 rc-powercolor-real-angel.o \
51 rc-proteus-2309.o \ 52 rc-proteus-2309.o \
diff --git a/drivers/media/IR/keymaps/rc-pixelview-mk12.c b/drivers/media/IR/keymaps/rc-pixelview-mk12.c
new file mode 100644
index 000000000000..5a735d569a8b
--- /dev/null
+++ b/drivers/media/IR/keymaps/rc-pixelview-mk12.c
@@ -0,0 +1,83 @@
1/* rc-pixelview-mk12.h - Keytable for pixelview Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/*
16 * Keytable for MK-F12 IR remote provided together with Pixelview
17 * Ultra Pro Remote Controller. Uses NEC extended format.
18 */
19static struct ir_scancode pixelview_mk12[] = {
20 { 0x866b03, KEY_TUNER }, /* Timeshift */
21 { 0x866b1e, KEY_POWER2 }, /* power */
22
23 { 0x866b01, KEY_1 },
24 { 0x866b0b, KEY_2 },
25 { 0x866b1b, KEY_3 },
26 { 0x866b05, KEY_4 },
27 { 0x866b09, KEY_5 },
28 { 0x866b15, KEY_6 },
29 { 0x866b06, KEY_7 },
30 { 0x866b0a, KEY_8 },
31 { 0x866b12, KEY_9 },
32 { 0x866b02, KEY_0 },
33
34 { 0x866b13, KEY_AGAIN }, /* loop */
35 { 0x866b10, KEY_DIGITS }, /* +100 */
36
37 { 0x866b00, KEY_MEDIA }, /* source */
38 { 0x866b18, KEY_MUTE }, /* mute */
39 { 0x866b19, KEY_CAMERA }, /* snapshot */
40 { 0x866b1a, KEY_SEARCH }, /* scan */
41
42 { 0x866b16, KEY_CHANNELUP }, /* chn + */
43 { 0x866b14, KEY_CHANNELDOWN }, /* chn - */
44 { 0x866b1f, KEY_VOLUMEUP }, /* vol + */
45 { 0x866b17, KEY_VOLUMEDOWN }, /* vol - */
46 { 0x866b1c, KEY_ZOOM }, /* zoom */
47
48 { 0x866b04, KEY_REWIND },
49 { 0x866b0e, KEY_RECORD },
50 { 0x866b0c, KEY_FORWARD },
51
52 { 0x866b1d, KEY_STOP },
53 { 0x866b08, KEY_PLAY },
54 { 0x866b0f, KEY_PAUSE },
55
56 { 0x866b0d, KEY_TV },
57 { 0x866b07, KEY_RADIO }, /* FM */
58};
59
60static struct rc_keymap pixelview_map = {
61 .map = {
62 .scan = pixelview_mk12,
63 .size = ARRAY_SIZE(pixelview_mk12),
64 .ir_type = IR_TYPE_NEC,
65 .name = RC_MAP_PIXELVIEW_MK12,
66 }
67};
68
69static int __init init_rc_map_pixelview(void)
70{
71 return ir_register_map(&pixelview_map);
72}
73
74static void __exit exit_rc_map_pixelview(void)
75{
76 ir_unregister_map(&pixelview_map);
77}
78
79module_init(init_rc_map_pixelview)
80module_exit(exit_rc_map_pixelview)
81
82MODULE_LICENSE("GPL");
83MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index 7ddc8bb463f8..76733349c6cc 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -248,6 +248,9 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
248 char *ir_codes = NULL; 248 char *ir_codes = NULL;
249 u64 ir_type = IR_TYPE_OTHER; 249 u64 ir_type = IR_TYPE_OTHER;
250 int err = -ENOMEM; 250 int err = -ENOMEM;
251 u32 hardware_mask = 0; /* For devices with a hardware mask, when
252 * used with a full-code IR table
253 */
251 254
252 ir = kzalloc(sizeof(*ir), GFP_KERNEL); 255 ir = kzalloc(sizeof(*ir), GFP_KERNEL);
253 input_dev = input_allocate_device(); 256 input_dev = input_allocate_device();
@@ -314,11 +317,18 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
314 break; 317 break;
315 case CX88_BOARD_PROLINK_PLAYTVPVR: 318 case CX88_BOARD_PROLINK_PLAYTVPVR:
316 case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO: 319 case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO:
317 ir_codes = RC_MAP_PIXELVIEW; 320 /*
321 * It seems that this hardware is paired with NEC extended
322 * address 0x866b. So, unfortunately, its usage with other
323 * IR's with different address won't work. Still, there are
324 * other IR's from the same manufacturer that works, like the
325 * 002-T mini RC, provided with newer PV hardware
326 */
327 ir_codes = RC_MAP_PIXELVIEW_MK12;
318 ir->gpio_addr = MO_GP1_IO; 328 ir->gpio_addr = MO_GP1_IO;
319 ir->mask_keycode = 0x1f; /* Only command is retrieved */
320 ir->mask_keyup = 0x80; 329 ir->mask_keyup = 0x80;
321 ir->polling = 10; /* ms */ 330 ir->polling = 10; /* ms */
331 hardware_mask = 0x3f; /* Hardware returns only 6 bits from command part */
322 break; 332 break;
323 case CX88_BOARD_PROLINK_PV_8000GT: 333 case CX88_BOARD_PROLINK_PV_8000GT:
324 case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: 334 case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
@@ -410,6 +420,21 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
410 goto err_out_free; 420 goto err_out_free;
411 } 421 }
412 422
423 /*
424 * The usage of mask_keycode were very convenient, due to several
425 * reasons. Among others, the scancode tables were using the scancode
426 * as the index elements. So, the less bits it was used, the smaller
427 * the table were stored. After the input changes, the better is to use
428 * the full scancodes, since it allows replacing the IR remote by
429 * another one. Unfortunately, there are still some hardware, like
430 * Pixelview Ultra Pro, where only part of the scancode is sent via
431 * GPIO. So, there's no way to get the full scancode. Due to that,
432 * hardware_mask were introduced here: it represents those hardware
433 * that has such limits.
434 */
435 if (hardware_mask && !ir->mask_keycode)
436 ir->mask_keycode = hardware_mask;
437
413 /* init input device */ 438 /* init input device */
414 snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name); 439 snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name);
415 snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci)); 440 snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci));
@@ -437,6 +462,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
437 ir->props.priv = core; 462 ir->props.priv = core;
438 ir->props.open = cx88_ir_open; 463 ir->props.open = cx88_ir_open;
439 ir->props.close = cx88_ir_close; 464 ir->props.close = cx88_ir_close;
465 ir->props.scanmask = hardware_mask;
440 466
441 /* all done */ 467 /* all done */
442 err = ir_input_register(ir->input, ir_codes, &ir->props, MODULE_NAME); 468 err = ir_input_register(ir->input, ir_codes, &ir->props, MODULE_NAME);
diff --git a/include/media/ir-core.h b/include/media/ir-core.h
index 0f64b48ecd90..4397ea3d9754 100644
--- a/include/media/ir-core.h
+++ b/include/media/ir-core.h
@@ -33,12 +33,28 @@ enum raw_event_type {
33 IR_STOP_EVENT = (1 << 3), 33 IR_STOP_EVENT = (1 << 3),
34}; 34};
35 35
36/**
37 * struct ir_dev_props - Allow caller drivers to set special properties
38 * @allowed_protos: bitmask with the supported IR_TYPE_* protocols
39 * @scanmask: some hardware decoders are not capable of providing the full
40 * scancode to the application. As this is a hardware limit, we can't do
41 * anything with it. Yet, as the same keycode table can be used with other
42 * devices, a mask is provided to allow its usage. Drivers should generally
43 * leave this field in blank
44 * @priv: driver-specific data, to be used on the callbacks
45 * @change_protocol: allow changing the protocol used on hardware decoders
46 * @open: callback to allow drivers to enable polling/irq when IR input device
47 * is opened.
48 * @close: callback to allow drivers to disable polling/irq when IR input device
49 * is opened.
50 */
36struct ir_dev_props { 51struct ir_dev_props {
37 unsigned long allowed_protos; 52 unsigned long allowed_protos;
53 u32 scanmask;
38 void *priv; 54 void *priv;
39 int (*change_protocol)(void *priv, u64 ir_type); 55 int (*change_protocol)(void *priv, u64 ir_type);
40 int (*open)(void *priv); 56 int (*open)(void *priv);
41 void (*close)(void *priv); 57 void (*close)(void *priv);
42}; 58};
43 59
44struct ir_raw_event { 60struct ir_raw_event {
diff --git a/include/media/rc-map.h b/include/media/rc-map.h
index b10990d1749d..3b7fe5a0dc72 100644
--- a/include/media/rc-map.h
+++ b/include/media/rc-map.h
@@ -18,7 +18,7 @@
18#define IR_TYPE_OTHER (1u << 31) 18#define IR_TYPE_OTHER (1u << 31)
19 19
20struct ir_scancode { 20struct ir_scancode {
21 u16 scancode; 21 u32 scancode;
22 u32 keycode; 22 u32 keycode;
23}; 23};
24 24
@@ -95,6 +95,7 @@ void rc_map_init(void);
95#define RC_MAP_PINNACLE_PCTV_HD "rc-pinnacle-pctv-hd" 95#define RC_MAP_PINNACLE_PCTV_HD "rc-pinnacle-pctv-hd"
96#define RC_MAP_PIXELVIEW_NEW "rc-pixelview-new" 96#define RC_MAP_PIXELVIEW_NEW "rc-pixelview-new"
97#define RC_MAP_PIXELVIEW "rc-pixelview" 97#define RC_MAP_PIXELVIEW "rc-pixelview"
98#define RC_MAP_PIXELVIEW_MK12 "rc-pixelview-mk12"
98#define RC_MAP_POWERCOLOR_REAL_ANGEL "rc-powercolor-real-angel" 99#define RC_MAP_POWERCOLOR_REAL_ANGEL "rc-powercolor-real-angel"
99#define RC_MAP_PROTEUS_2309 "rc-proteus-2309" 100#define RC_MAP_PROTEUS_2309 "rc-proteus-2309"
100#define RC_MAP_PURPLETV "rc-purpletv" 101#define RC_MAP_PURPLETV "rc-purpletv"