aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/IR
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/IR')
-rw-r--r--drivers/media/IR/imon.c151
-rw-r--r--drivers/media/IR/keymaps/rc-imon-mce.c4
-rw-r--r--drivers/media/IR/keymaps/rc-imon-pad.c3
3 files changed, 69 insertions, 89 deletions
diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c
index d941b98eed3..b65c31ab4a4 100644
--- a/drivers/media/IR/imon.c
+++ b/drivers/media/IR/imon.c
@@ -127,8 +127,7 @@ struct imon_context {
127 127
128 u32 kc; /* current input keycode */ 128 u32 kc; /* current input keycode */
129 u32 last_keycode; /* last reported input keycode */ 129 u32 last_keycode; /* last reported input keycode */
130 u8 ir_protocol; /* iMON or MCE (RC6) IR protocol? */ 130 u64 ir_type; /* iMON or MCE (RC6) IR protocol? */
131 u8 ir_proto_mask; /* supported IR protocol mask */
132 u8 mce_toggle_bit; /* last mce toggle bit */ 131 u8 mce_toggle_bit; /* last mce toggle bit */
133 bool release_code; /* some keys send a release code */ 132 bool release_code; /* some keys send a release code */
134 133
@@ -174,20 +173,6 @@ enum {
174}; 173};
175 174
176enum { 175enum {
177 IMON_IR_PROTOCOL_AUTO = 0x0,
178 IMON_IR_PROTOCOL_MCE = 0x1,
179 IMON_IR_PROTOCOL_IMON = 0x2,
180 IMON_IR_PROTOCOL_IMON_NOPAD = 0x4,
181};
182
183enum {
184 IMON_IR_PROTO_MASK_NONE = 0x0,
185 IMON_IR_PROTO_MASK_MCE = IMON_IR_PROTOCOL_MCE,
186 IMON_IR_PROTO_MASK_IMON = IMON_IR_PROTOCOL_IMON |
187 IMON_IR_PROTOCOL_IMON_NOPAD,
188};
189
190enum {
191 IMON_KEY_IMON = 0, 176 IMON_KEY_IMON = 0,
192 IMON_KEY_MCE = 1, 177 IMON_KEY_MCE = 1,
193 IMON_KEY_PANEL = 2, 178 IMON_KEY_PANEL = 2,
@@ -330,12 +315,10 @@ module_param(display_type, int, S_IRUGO);
330MODULE_PARM_DESC(display_type, "Type of attached display. 0=autodetect, " 315MODULE_PARM_DESC(display_type, "Type of attached display. 0=autodetect, "
331 "1=vfd, 2=lcd, 3=vga, 4=none (default: autodetect)"); 316 "1=vfd, 2=lcd, 3=vga, 4=none (default: autodetect)");
332 317
333/* IR protocol: native iMON, Windows MCE (RC-6), or iMON w/o PAD stabilize */ 318static int pad_stabilize = 1;
334static int ir_protocol; 319module_param(pad_stabilize, int, S_IRUGO | S_IWUSR);
335module_param(ir_protocol, int, S_IRUGO | S_IWUSR); 320MODULE_PARM_DESC(pad_stabilize, "Apply stabilization algorithm to iMON PAD "
336MODULE_PARM_DESC(ir_protocol, "Which IR protocol to use. 0=auto-detect, " 321 "presses in arrow key mode. 0=disable, 1=enable (default).");
337 "1=Windows Media Center Ed. (RC-6), 2=iMON native, "
338 "4=iMON w/o PAD stabilize (default: auto-detect)");
339 322
340/* 323/*
341 * In certain use cases, mouse mode isn't really helpful, and could actually 324 * In certain use cases, mouse mode isn't really helpful, and could actually
@@ -1007,72 +990,67 @@ static void imon_touch_display_timeout(unsigned long data)
1007 * really just RC-6), but only one or the other at a time, as the signals 990 * really just RC-6), but only one or the other at a time, as the signals
1008 * are decoded onboard the receiver. 991 * are decoded onboard the receiver.
1009 */ 992 */
1010static void imon_set_ir_protocol(struct imon_context *ictx) 993int imon_ir_change_protocol(void *priv, u64 ir_type)
1011{ 994{
1012 int retval; 995 int retval;
996 struct imon_context *ictx = priv;
1013 struct device *dev = ictx->dev; 997 struct device *dev = ictx->dev;
998 bool pad_mouse;
1014 unsigned char ir_proto_packet[] = { 999 unsigned char ir_proto_packet[] = {
1015 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 }; 1000 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
1016 1001
1017 if (ir_protocol && !(ir_protocol & ictx->ir_proto_mask)) 1002 if (!(ir_type & ictx->props->allowed_protos))
1018 dev_warn(dev, "Looks like you're trying to use an IR protocol " 1003 dev_warn(dev, "Looks like you're trying to use an IR protocol "
1019 "this device does not support\n"); 1004 "this device does not support\n");
1020 1005
1021 switch (ir_protocol) { 1006 switch (ir_type) {
1022 case IMON_IR_PROTOCOL_AUTO: 1007 case IR_TYPE_RC6:
1023 if (ictx->product == 0xffdc) {
1024 if (ictx->ir_proto_mask & IMON_IR_PROTO_MASK_MCE) {
1025 ir_proto_packet[0] = 0x01;
1026 ictx->ir_protocol = IMON_IR_PROTOCOL_MCE;
1027 ictx->pad_mouse = 0;
1028 init_timer(&ictx->itimer);
1029 ictx->itimer.data = (unsigned long)ictx;
1030 ictx->itimer.function = imon_mce_timeout;
1031 } else {
1032 ictx->ir_protocol = IMON_IR_PROTOCOL_IMON;
1033 ictx->pad_mouse = 1;
1034 }
1035 }
1036 break;
1037 case IMON_IR_PROTOCOL_MCE:
1038 dev_dbg(dev, "Configuring IR receiver for MCE protocol\n"); 1008 dev_dbg(dev, "Configuring IR receiver for MCE protocol\n");
1039 ir_proto_packet[0] = 0x01; 1009 ir_proto_packet[0] = 0x01;
1040 ictx->ir_protocol = IMON_IR_PROTOCOL_MCE; 1010 pad_mouse = false;
1041 ictx->pad_mouse = 0;
1042 init_timer(&ictx->itimer); 1011 init_timer(&ictx->itimer);
1043 ictx->itimer.data = (unsigned long)ictx; 1012 ictx->itimer.data = (unsigned long)ictx;
1044 ictx->itimer.function = imon_mce_timeout; 1013 ictx->itimer.function = imon_mce_timeout;
1045 break; 1014 break;
1046 case IMON_IR_PROTOCOL_IMON: 1015 case IR_TYPE_UNKNOWN:
1047 dev_dbg(dev, "Configuring IR receiver for iMON protocol\n"); 1016 case IR_TYPE_OTHER:
1048 /* ir_proto_packet[0] = 0x00; // already the default */ 1017 dev_dbg(dev, "Configuring IR receiver for iMON protocol");
1049 ictx->ir_protocol = IMON_IR_PROTOCOL_IMON; 1018 if (pad_stabilize) {
1050 ictx->pad_mouse = 1; 1019 printk(KERN_CONT "\n");
1051 break; 1020 pad_mouse = true;
1052 case IMON_IR_PROTOCOL_IMON_NOPAD: 1021 } else {
1053 dev_dbg(dev, "Configuring IR receiver for iMON protocol " 1022 printk(KERN_CONT " (without PAD stabilization)\n");
1054 "without PAD stabilize function enabled\n"); 1023 pad_mouse = false;
1024 }
1055 /* ir_proto_packet[0] = 0x00; // already the default */ 1025 /* ir_proto_packet[0] = 0x00; // already the default */
1056 ictx->ir_protocol = IMON_IR_PROTOCOL_IMON_NOPAD; 1026 ir_type = IR_TYPE_OTHER;
1057 ictx->pad_mouse = 0;
1058 break; 1027 break;
1059 default: 1028 default:
1060 dev_info(dev, "%s: unknown IR protocol specified, will " 1029 dev_warn(dev, "Unsupported IR protocol specified, overriding "
1061 "just default to iMON protocol\n", __func__); 1030 "to iMON IR protocol");
1062 ictx->ir_protocol = IMON_IR_PROTOCOL_IMON; 1031 if (pad_stabilize) {
1063 ictx->pad_mouse = 1; 1032 printk(KERN_CONT "\n");
1033 pad_mouse = true;
1034 } else {
1035 printk(KERN_CONT " (without PAD stabilization)\n");
1036 pad_mouse = false;
1037 }
1038 /* ir_proto_packet[0] = 0x00; // already the default */
1039 ir_type = IR_TYPE_OTHER;
1064 break; 1040 break;
1065 } 1041 }
1066 1042
1067 memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet)); 1043 memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet));
1068 1044
1069 retval = send_packet(ictx); 1045 retval = send_packet(ictx);
1070 if (retval) { 1046 if (retval)
1071 dev_info(dev, "%s: failed to set IR protocol, falling back " 1047 goto out;
1072 "to standard iMON protocol mode\n", __func__); 1048
1073 ir_protocol = IMON_IR_PROTOCOL_IMON; 1049 ictx->ir_type = ir_type;
1074 ictx->ir_protocol = IMON_IR_PROTOCOL_IMON; 1050 ictx->pad_mouse = pad_mouse;
1075 } 1051
1052out:
1053 return retval;
1076} 1054}
1077 1055
1078static inline int tv2int(const struct timeval *a, const struct timeval *b) 1056static inline int tv2int(const struct timeval *a, const struct timeval *b)
@@ -1329,7 +1307,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf)
1329 rel_x = buf[2]; 1307 rel_x = buf[2];
1330 rel_y = buf[3]; 1308 rel_y = buf[3];
1331 1309
1332 if (ictx->ir_protocol == IMON_IR_PROTOCOL_IMON) { 1310 if (ictx->ir_type == IR_TYPE_OTHER && pad_stabilize) {
1333 if ((buf[1] == 0) && ((rel_x != 0) || (rel_y != 0))) { 1311 if ((buf[1] == 0) && ((rel_x != 0) || (rel_y != 0))) {
1334 dir = stabilize((int)rel_x, (int)rel_y, 1312 dir = stabilize((int)rel_x, (int)rel_y,
1335 timeout, threshold); 1313 timeout, threshold);
@@ -1386,7 +1364,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf)
1386 buf[0] = 0x01; 1364 buf[0] = 0x01;
1387 buf[1] = buf[4] = buf[5] = buf[6] = buf[7] = 0; 1365 buf[1] = buf[4] = buf[5] = buf[6] = buf[7] = 0;
1388 1366
1389 if (ictx->ir_protocol == IMON_IR_PROTOCOL_IMON) { 1367 if (ictx->ir_type == IR_TYPE_OTHER && pad_stabilize) {
1390 dir = stabilize((int)rel_x, (int)rel_y, 1368 dir = stabilize((int)rel_x, (int)rel_y,
1391 timeout, threshold); 1369 timeout, threshold);
1392 if (!dir) { 1370 if (!dir) {
@@ -1499,7 +1477,7 @@ static void imon_incoming_packet(struct imon_context *ictx,
1499 kc = imon_panel_key_lookup(panel_key); 1477 kc = imon_panel_key_lookup(panel_key);
1500 } else { 1478 } else {
1501 remote_key = (u32) (le64_to_cpu(temp_key) & 0xffffffff); 1479 remote_key = (u32) (le64_to_cpu(temp_key) & 0xffffffff);
1502 if (ictx->ir_protocol == IMON_IR_PROTOCOL_MCE) { 1480 if (ictx->ir_type == IR_TYPE_RC6) {
1503 if (buf[0] == 0x80) 1481 if (buf[0] == 0x80)
1504 ktype = IMON_KEY_MCE; 1482 ktype = IMON_KEY_MCE;
1505 kc = imon_mce_key_lookup(ictx, remote_key); 1483 kc = imon_mce_key_lookup(ictx, remote_key);
@@ -1680,12 +1658,6 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx)
1680 struct ir_dev_props *props; 1658 struct ir_dev_props *props;
1681 struct ir_input_dev *ir; 1659 struct ir_input_dev *ir;
1682 int ret, i; 1660 int ret, i;
1683 char *ir_codes = NULL;
1684
1685 if (ir_protocol == IMON_IR_PROTOCOL_MCE)
1686 ir_codes = RC_MAP_IMON_MCE;
1687 else
1688 ir_codes = RC_MAP_IMON_PAD;
1689 1661
1690 idev = input_allocate_device(); 1662 idev = input_allocate_device();
1691 if (!idev) { 1663 if (!idev) {
@@ -1727,8 +1699,12 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx)
1727 __set_bit(kc, idev->keybit); 1699 __set_bit(kc, idev->keybit);
1728 } 1700 }
1729 1701
1702 props->priv = ictx;
1730 props->driver_type = RC_DRIVER_SCANCODE; 1703 props->driver_type = RC_DRIVER_SCANCODE;
1731 props->allowed_protos = IR_TYPE_UNKNOWN; 1704 /* IR_TYPE_OTHER maps to iMON PAD remote, IR_TYPE_RC6 to MCE remote */
1705 props->allowed_protos = IR_TYPE_OTHER | IR_TYPE_RC6;
1706 props->change_protocol = imon_ir_change_protocol;
1707 ictx->props = props;
1732 1708
1733 ictx->ir = ir; 1709 ictx->ir = ir;
1734 memcpy(&ir->dev, ictx->dev, sizeof(struct device)); 1710 memcpy(&ir->dev, ictx->dev, sizeof(struct device));
@@ -1738,7 +1714,7 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx)
1738 1714
1739 input_set_drvdata(idev, ir); 1715 input_set_drvdata(idev, ir);
1740 1716
1741 ret = ir_input_register(idev, ir_codes, props, MOD_NAME); 1717 ret = ir_input_register(idev, RC_MAP_IMON_PAD, props, MOD_NAME);
1742 if (ret < 0) { 1718 if (ret < 0) {
1743 dev_err(ictx->dev, "remote input dev register failed\n"); 1719 dev_err(ictx->dev, "remote input dev register failed\n");
1744 goto idev_register_failed; 1720 goto idev_register_failed;
@@ -2058,13 +2034,14 @@ rx_urb_alloc_failed:
2058 * is no actual data to report. However, byte 6 of this buffer looks like 2034 * is no actual data to report. However, byte 6 of this buffer looks like
2059 * its unique across device variants, so we're trying to key off that to 2035 * its unique across device variants, so we're trying to key off that to
2060 * figure out which display type (if any) and what IR protocol the device 2036 * figure out which display type (if any) and what IR protocol the device
2061 * actually supports. 2037 * actually supports. These devices have their IR protocol hard-coded into
2038 * their firmware, they can't be changed on the fly like the newer hardware.
2062 */ 2039 */
2063static void imon_get_ffdc_type(struct imon_context *ictx) 2040static void imon_get_ffdc_type(struct imon_context *ictx)
2064{ 2041{
2065 u8 ffdc_cfg_byte = ictx->usb_rx_buf[6]; 2042 u8 ffdc_cfg_byte = ictx->usb_rx_buf[6];
2066 u8 detected_display_type = IMON_DISPLAY_TYPE_NONE; 2043 u8 detected_display_type = IMON_DISPLAY_TYPE_NONE;
2067 u8 ir_proto_mask = IMON_IR_PROTO_MASK_IMON; 2044 u64 allowed_protos = IR_TYPE_OTHER;
2068 2045
2069 switch (ffdc_cfg_byte) { 2046 switch (ffdc_cfg_byte) {
2070 /* iMON Knob, no display, iMON IR + vol knob */ 2047 /* iMON Knob, no display, iMON IR + vol knob */
@@ -2076,7 +2053,6 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
2076 case 0x35: 2053 case 0x35:
2077 dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR"); 2054 dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR");
2078 detected_display_type = IMON_DISPLAY_TYPE_VFD; 2055 detected_display_type = IMON_DISPLAY_TYPE_VFD;
2079 ir_proto_mask = IMON_IR_PROTO_MASK_NONE;
2080 break; 2056 break;
2081 /* iMON VFD, iMON IR */ 2057 /* iMON VFD, iMON IR */
2082 case 0x24: 2058 case 0x24:
@@ -2088,7 +2064,7 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
2088 case 0x9f: 2064 case 0x9f:
2089 dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR"); 2065 dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR");
2090 detected_display_type = IMON_DISPLAY_TYPE_LCD; 2066 detected_display_type = IMON_DISPLAY_TYPE_LCD;
2091 ir_proto_mask = IMON_IR_PROTO_MASK_MCE; 2067 allowed_protos = IR_TYPE_RC6;
2092 break; 2068 break;
2093 default: 2069 default:
2094 dev_info(ictx->dev, "Unknown 0xffdc device, " 2070 dev_info(ictx->dev, "Unknown 0xffdc device, "
@@ -2097,10 +2073,11 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
2097 break; 2073 break;
2098 } 2074 }
2099 2075
2100 printk(" (id 0x%02x)\n", ffdc_cfg_byte); 2076 printk(KERN_CONT " (id 0x%02x)\n", ffdc_cfg_byte);
2101 2077
2102 ictx->display_type = detected_display_type; 2078 ictx->display_type = detected_display_type;
2103 ictx->ir_proto_mask = ir_proto_mask; 2079 ictx->props->allowed_protos = allowed_protos;
2080 ictx->ir_type = allowed_protos;
2104} 2081}
2105 2082
2106static void imon_set_display_type(struct imon_context *ictx, 2083static void imon_set_display_type(struct imon_context *ictx,
@@ -2255,9 +2232,6 @@ static int __devinit imon_probe(struct usb_interface *interface,
2255 2232
2256 if (product == 0xffdc) 2233 if (product == 0xffdc)
2257 imon_get_ffdc_type(ictx); 2234 imon_get_ffdc_type(ictx);
2258 else
2259 ictx->ir_proto_mask = IMON_IR_PROTO_MASK_MCE |
2260 IMON_IR_PROTO_MASK_IMON;
2261 2235
2262 imon_set_display_type(ictx, interface); 2236 imon_set_display_type(ictx, interface);
2263 2237
@@ -2266,7 +2240,12 @@ static int __devinit imon_probe(struct usb_interface *interface,
2266 } 2240 }
2267 2241
2268 /* set IR protocol/remote type */ 2242 /* set IR protocol/remote type */
2269 imon_set_ir_protocol(ictx); 2243 ret = imon_ir_change_protocol(ictx, ictx->ir_type);
2244 if (ret) {
2245 dev_warn(dev, "%s: failed to set IR protocol, falling back "
2246 "to standard iMON protocol mode\n", __func__);
2247 ictx->ir_type = IR_TYPE_OTHER;
2248 }
2270 2249
2271 dev_info(dev, "iMON device (%04x:%04x, intf%d) on " 2250 dev_info(dev, "iMON device (%04x:%04x, intf%d) on "
2272 "usb<%d:%d> initialized\n", vendor, product, ifnum, 2251 "usb<%d:%d> initialized\n", vendor, product, ifnum,
@@ -2343,7 +2322,7 @@ static void __devexit imon_disconnect(struct usb_interface *interface)
2343 if (!ictx->display_isopen) 2322 if (!ictx->display_isopen)
2344 free_imon_context(ictx); 2323 free_imon_context(ictx);
2345 } else { 2324 } else {
2346 if (ictx->ir_protocol == IMON_IR_PROTOCOL_MCE) 2325 if (ictx->ir_type == IR_TYPE_RC6)
2347 del_timer_sync(&ictx->itimer); 2326 del_timer_sync(&ictx->itimer);
2348 mutex_unlock(&ictx->lock); 2327 mutex_unlock(&ictx->lock);
2349 } 2328 }
diff --git a/drivers/media/IR/keymaps/rc-imon-mce.c b/drivers/media/IR/keymaps/rc-imon-mce.c
index 9c6dda30c64..e49f350e3a0 100644
--- a/drivers/media/IR/keymaps/rc-imon-mce.c
+++ b/drivers/media/IR/keymaps/rc-imon-mce.c
@@ -119,8 +119,8 @@ static struct rc_keymap imon_mce_map = {
119 .map = { 119 .map = {
120 .scan = imon_mce, 120 .scan = imon_mce,
121 .size = ARRAY_SIZE(imon_mce), 121 .size = ARRAY_SIZE(imon_mce),
122 /* its actually RC6, but w/a hardware decoder */ 122 /* its RC6, but w/a hardware decoder */
123 .ir_type = IR_TYPE_UNKNOWN, 123 .ir_type = IR_TYPE_RC6,
124 .name = RC_MAP_IMON_MCE, 124 .name = RC_MAP_IMON_MCE,
125 } 125 }
126}; 126};
diff --git a/drivers/media/IR/keymaps/rc-imon-pad.c b/drivers/media/IR/keymaps/rc-imon-pad.c
index 331ba9066b4..bc4db72f02e 100644
--- a/drivers/media/IR/keymaps/rc-imon-pad.c
+++ b/drivers/media/IR/keymaps/rc-imon-pad.c
@@ -133,7 +133,8 @@ static struct rc_keymap imon_pad_map = {
133 .map = { 133 .map = {
134 .scan = imon_pad, 134 .scan = imon_pad,
135 .size = ARRAY_SIZE(imon_pad), 135 .size = ARRAY_SIZE(imon_pad),
136 .ir_type = IR_TYPE_UNKNOWN, 136 /* actual protocol details unknown, hardware decoder */
137 .ir_type = IR_TYPE_OTHER,
137 .name = RC_MAP_IMON_PAD, 138 .name = RC_MAP_IMON_PAD,
138 } 139 }
139}; 140};