summaryrefslogtreecommitdiff
path: root/drivers/media/rc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-15 12:49:56 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-15 12:49:56 -0800
commit122804ecb59493fbb4d31b3ba9ac59faaf45276f (patch)
treecff4d8a158c412e4a8d3abc8d91bb0eb52b01c9a /drivers/media/rc
parent16008d641670571ff4cd750b416c7caf2d89f467 (diff)
parent126400033940afb658123517a2e80eb68259fbd7 (diff)
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (655 commits) [media] revert patch: HDIC HD29L2 DMB-TH USB2.0 reference design driver mb86a20s: Add a few more register settings at the init seq mb86a20s: Group registers into the same line [media] [PATCH] don't reset the delivery system on DTV_CLEAR [media] [BUG] it913x-fe fix typo error making SNR levels unstable [media] cx23885: Query the CX25840 during enum_input for status [media] cx25840: Add support for g_input_status [media] rc-videomate-m1f.c Rename to match remote controler name [media] drivers: media: au0828: Fix dependency for VIDEO_AU0828 [media] convert drivers/media/* to use module_platform_driver() [media] drivers: video: cx231xx: Fix dependency for VIDEO_CX231XX_DVB [media] Exynos4 JPEG codec v4l2 driver [media] doc: v4l: selection: choose pixels as units for selection rectangles [media] v4l: s5p-tv: mixer: fix setup of VP scaling [media] v4l: s5p-tv: mixer: add support for selection API [media] v4l: emulate old crop API using extended crop/compose API [media] doc: v4l: add documentation for selection API [media] doc: v4l: add binary images for selection API [media] v4l: add support for selection api [media] hd29l2: fix review findings ...
Diffstat (limited to 'drivers/media/rc')
-rw-r--r--drivers/media/rc/Kconfig10
-rw-r--r--drivers/media/rc/Makefile1
-rw-r--r--drivers/media/rc/ir-nec-decoder.c4
-rw-r--r--drivers/media/rc/ir-raw.c1
-rw-r--r--drivers/media/rc/ir-rc6-decoder.c67
-rw-r--r--drivers/media/rc/ir-sanyo-decoder.c205
-rw-r--r--drivers/media/rc/keymaps/rc-hauppauge.c51
-rw-r--r--drivers/media/rc/keymaps/rc-videomate-m1f.c24
-rw-r--r--drivers/media/rc/rc-core-priv.h12
-rw-r--r--drivers/media/rc/rc-main.c1
-rw-r--r--drivers/media/rc/redrat3.c52
11 files changed, 354 insertions, 74 deletions
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index aeb7f43dfb65..4df4affeea5f 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -87,6 +87,16 @@ config IR_RC5_SZ_DECODER
uses an IR protocol that is almost standard RC-5, but not quite,
as it uses an additional bit).
+config IR_SANYO_DECODER
+ tristate "Enable IR raw decoder for the Sanyo protocol"
+ depends on RC_CORE
+ default y
+
+ ---help---
+ Enable this option if you have an infrared remote control which
+ uses the Sanyo protocol (Sanyo, Aiwa, Chinon remotes),
+ and you need software decoding support.
+
config IR_MCE_KBD_DECODER
tristate "Enable IR raw decoder for the MCE keyboard/mouse protocol"
depends on RC_CORE
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index 2156e786b557..fb3dee2dd845 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o
+obj-$(CONFIG_IR_SANYO_DECODER) += ir-sanyo-decoder.o
obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o
obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c
index 17f8db00435a..3c9431a9f62d 100644
--- a/drivers/media/rc/ir-nec-decoder.c
+++ b/drivers/media/rc/ir-nec-decoder.c
@@ -194,8 +194,8 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
return 0;
}
- IR_dprintk(1, "NEC decode failed at state %d (%uus %s)\n",
- data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+ IR_dprintk(1, "NEC decode failed at count %d state %d (%uus %s)\n",
+ data->count, data->state, TO_US(ev.duration), TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
return -EINVAL;
}
diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c
index 2e5cd3100b64..95e630998aaf 100644
--- a/drivers/media/rc/ir-raw.c
+++ b/drivers/media/rc/ir-raw.c
@@ -357,6 +357,7 @@ static void init_decoders(struct work_struct *work)
load_rc6_decode();
load_jvc_decode();
load_sony_decode();
+ load_sanyo_decode();
load_mce_kbd_decode();
load_lirc_codec();
diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c
index 140fb67e2f89..4cfdd7fa4bbd 100644
--- a/drivers/media/rc/ir-rc6-decoder.c
+++ b/drivers/media/rc/ir-rc6-decoder.c
@@ -18,24 +18,31 @@
/*
* This decoder currently supports:
* RC6-0-16 (standard toggle bit in header)
+ * RC6-6A-20 (no toggle bit)
* RC6-6A-24 (no toggle bit)
* RC6-6A-32 (MCE version with toggle bit in body)
*/
-#define RC6_UNIT 444444 /* us */
+#define RC6_UNIT 444444 /* nanosecs */
#define RC6_HEADER_NBITS 4 /* not including toggle bit */
#define RC6_0_NBITS 16
-#define RC6_6A_SMALL_NBITS 24
-#define RC6_6A_LARGE_NBITS 32
+#define RC6_6A_32_NBITS 32
+#define RC6_6A_NBITS 128 /* Variable 8..128 */
#define RC6_PREFIX_PULSE (6 * RC6_UNIT)
#define RC6_PREFIX_SPACE (2 * RC6_UNIT)
#define RC6_BIT_START (1 * RC6_UNIT)
#define RC6_BIT_END (1 * RC6_UNIT)
#define RC6_TOGGLE_START (2 * RC6_UNIT)
#define RC6_TOGGLE_END (2 * RC6_UNIT)
+#define RC6_SUFFIX_SPACE (6 * RC6_UNIT)
#define RC6_MODE_MASK 0x07 /* for the header bits */
#define RC6_STARTBIT_MASK 0x08 /* for the header bits */
#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */
+#define RC6_6A_LCC_MASK 0xffff0000 /* RC6-6A-32 long customer code mask */
+#define RC6_6A_MCE_CC 0x800f0000 /* MCE customer code */
+#ifndef CHAR_BIT
+#define CHAR_BIT 8 /* Normally in <limits.h> */
+#endif
enum rc6_mode {
RC6_MODE_0,
@@ -125,6 +132,7 @@ again:
break;
data->state = STATE_HEADER_BIT_START;
+ data->header = 0;
return 0;
case STATE_HEADER_BIT_START:
@@ -171,20 +179,14 @@ again:
data->state = STATE_BODY_BIT_START;
decrease_duration(&ev, RC6_TOGGLE_END);
data->count = 0;
+ data->body = 0;
switch (rc6_mode(data)) {
case RC6_MODE_0:
data->wanted_bits = RC6_0_NBITS;
break;
case RC6_MODE_6A:
- /* This might look weird, but we basically
- check the value of the first body bit to
- determine the number of bits in mode 6A */
- if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) ||
- geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
- data->wanted_bits = RC6_6A_LARGE_NBITS;
- else
- data->wanted_bits = RC6_6A_SMALL_NBITS;
+ data->wanted_bits = RC6_6A_NBITS;
break;
default:
IR_dprintk(1, "RC6 unknown mode\n");
@@ -193,15 +195,21 @@ again:
goto again;
case STATE_BODY_BIT_START:
- if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
- break;
-
- data->body <<= 1;
- if (ev.pulse)
- data->body |= 1;
- data->count++;
- data->state = STATE_BODY_BIT_END;
- return 0;
+ if (eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) {
+ /* Discard LSB's that won't fit in data->body */
+ if (data->count++ < CHAR_BIT * sizeof data->body) {
+ data->body <<= 1;
+ if (ev.pulse)
+ data->body |= 1;
+ }
+ data->state = STATE_BODY_BIT_END;
+ return 0;
+ } else if (RC6_MODE_6A == rc6_mode(data) && !ev.pulse &&
+ geq_margin(ev.duration, RC6_SUFFIX_SPACE, RC6_UNIT / 2)) {
+ data->state = STATE_FINISHED;
+ goto again;
+ }
+ break;
case STATE_BODY_BIT_END:
if (!is_transition(&ev, &dev->raw->prev_ev))
@@ -221,20 +229,27 @@ again:
switch (rc6_mode(data)) {
case RC6_MODE_0:
- scancode = data->body & 0xffff;
+ scancode = data->body;
toggle = data->toggle;
IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n",
scancode, toggle);
break;
case RC6_MODE_6A:
- if (data->wanted_bits == RC6_6A_LARGE_NBITS) {
- toggle = data->body & RC6_6A_MCE_TOGGLE_MASK ? 1 : 0;
- scancode = data->body & ~RC6_6A_MCE_TOGGLE_MASK;
+ if (data->count > CHAR_BIT * sizeof data->body) {
+ IR_dprintk(1, "RC6 too many (%u) data bits\n",
+ data->count);
+ goto out;
+ }
+
+ scancode = data->body;
+ if (data->count == RC6_6A_32_NBITS &&
+ (scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) {
+ /* MCE RC */
+ toggle = (scancode & RC6_6A_MCE_TOGGLE_MASK) ? 1 : 0;
+ scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
} else {
toggle = 0;
- scancode = data->body & 0xffffff;
}
-
IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n",
scancode, toggle);
break;
diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c
new file mode 100644
index 000000000000..d38fbdd0b25a
--- /dev/null
+++ b/drivers/media/rc/ir-sanyo-decoder.c
@@ -0,0 +1,205 @@
+/* ir-sanyo-decoder.c - handle SANYO IR Pulse/Space protocol
+ *
+ * Copyright (C) 2011 by Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This protocol uses the NEC protocol timings. However, data is formatted as:
+ * 13 bits Custom Code
+ * 13 bits NOT(Custom Code)
+ * 8 bits Key data
+ * 8 bits NOT(Key data)
+ *
+ * According with LIRC, this protocol is used on Sanyo, Aiwa and Chinon
+ * Information for this protocol is available at the Sanyo LC7461 datasheet.
+ */
+
+#include <linux/module.h>
+#include <linux/bitrev.h>
+#include "rc-core-priv.h"
+
+#define SANYO_NBITS (13+13+8+8)
+#define SANYO_UNIT 562500 /* ns */
+#define SANYO_HEADER_PULSE (16 * SANYO_UNIT)
+#define SANYO_HEADER_SPACE (8 * SANYO_UNIT)
+#define SANYO_BIT_PULSE (1 * SANYO_UNIT)
+#define SANYO_BIT_0_SPACE (1 * SANYO_UNIT)
+#define SANYO_BIT_1_SPACE (3 * SANYO_UNIT)
+#define SANYO_REPEAT_SPACE (150 * SANYO_UNIT)
+#define SANYO_TRAILER_PULSE (1 * SANYO_UNIT)
+#define SANYO_TRAILER_SPACE (10 * SANYO_UNIT) /* in fact, 42 */
+
+enum sanyo_state {
+ STATE_INACTIVE,
+ STATE_HEADER_SPACE,
+ STATE_BIT_PULSE,
+ STATE_BIT_SPACE,
+ STATE_TRAILER_PULSE,
+ STATE_TRAILER_SPACE,
+};
+
+/**
+ * ir_sanyo_decode() - Decode one SANYO pulse or space
+ * @dev: the struct rc_dev descriptor of the device
+ * @duration: the struct ir_raw_event descriptor of the pulse/space
+ *
+ * This function returns -EINVAL if the pulse violates the state machine
+ */
+static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev)
+{
+ struct sanyo_dec *data = &dev->raw->sanyo;
+ u32 scancode;
+ u8 address, not_address, command, not_command;
+
+ if (!(dev->raw->enabled_protocols & RC_TYPE_SANYO))
+ return 0;
+
+ if (!is_timing_event(ev)) {
+ if (ev.reset) {
+ IR_dprintk(1, "SANYO event reset received. reset to state 0\n");
+ data->state = STATE_INACTIVE;
+ }
+ return 0;
+ }
+
+ IR_dprintk(2, "SANYO decode started at state %d (%uus %s)\n",
+ data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+
+ switch (data->state) {
+
+ case STATE_INACTIVE:
+ if (!ev.pulse)
+ break;
+
+ if (eq_margin(ev.duration, SANYO_HEADER_PULSE, SANYO_UNIT / 2)) {
+ data->count = 0;
+ data->state = STATE_HEADER_SPACE;
+ return 0;
+ }
+ break;
+
+
+ case STATE_HEADER_SPACE:
+ if (ev.pulse)
+ break;
+
+ if (eq_margin(ev.duration, SANYO_HEADER_SPACE, SANYO_UNIT / 2)) {
+ data->state = STATE_BIT_PULSE;
+ return 0;
+ }
+
+ break;
+
+ case STATE_BIT_PULSE:
+ if (!ev.pulse)
+ break;
+
+ if (!eq_margin(ev.duration, SANYO_BIT_PULSE, SANYO_UNIT / 2))
+ break;
+
+ data->state = STATE_BIT_SPACE;
+ return 0;
+
+ case STATE_BIT_SPACE:
+ if (ev.pulse)
+ break;
+
+ if (!data->count && geq_margin(ev.duration, SANYO_REPEAT_SPACE, SANYO_UNIT / 2)) {
+ if (!dev->keypressed) {
+ IR_dprintk(1, "SANYO discarding last key repeat: event after key up\n");
+ } else {
+ rc_repeat(dev);
+ IR_dprintk(1, "SANYO repeat last key\n");
+ data->state = STATE_INACTIVE;
+ }
+ return 0;
+ }
+
+ data->bits <<= 1;
+ if (eq_margin(ev.duration, SANYO_BIT_1_SPACE, SANYO_UNIT / 2))
+ data->bits |= 1;
+ else if (!eq_margin(ev.duration, SANYO_BIT_0_SPACE, SANYO_UNIT / 2))
+ break;
+ data->count++;
+
+ if (data->count == SANYO_NBITS)
+ data->state = STATE_TRAILER_PULSE;
+ else
+ data->state = STATE_BIT_PULSE;
+
+ return 0;
+
+ case STATE_TRAILER_PULSE:
+ if (!ev.pulse)
+ break;
+
+ if (!eq_margin(ev.duration, SANYO_TRAILER_PULSE, SANYO_UNIT / 2))
+ break;
+
+ data->state = STATE_TRAILER_SPACE;
+ return 0;
+
+ case STATE_TRAILER_SPACE:
+ if (ev.pulse)
+ break;
+
+ if (!geq_margin(ev.duration, SANYO_TRAILER_SPACE, SANYO_UNIT / 2))
+ break;
+
+ address = bitrev16((data->bits >> 29) & 0x1fff) >> 3;
+ not_address = bitrev16((data->bits >> 16) & 0x1fff) >> 3;
+ command = bitrev8((data->bits >> 8) & 0xff);
+ not_command = bitrev8((data->bits >> 0) & 0xff);
+
+ if ((command ^ not_command) != 0xff) {
+ IR_dprintk(1, "SANYO checksum error: received 0x%08Lx\n",
+ data->bits);
+ data->state = STATE_INACTIVE;
+ return 0;
+ }
+
+ scancode = address << 8 | command;
+ IR_dprintk(1, "SANYO scancode: 0x%06x\n", scancode);
+ rc_keydown(dev, scancode, 0);
+ data->state = STATE_INACTIVE;
+ return 0;
+ }
+
+ IR_dprintk(1, "SANYO decode failed at count %d state %d (%uus %s)\n",
+ data->count, data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+ data->state = STATE_INACTIVE;
+ return -EINVAL;
+}
+
+static struct ir_raw_handler sanyo_handler = {
+ .protocols = RC_TYPE_SANYO,
+ .decode = ir_sanyo_decode,
+};
+
+static int __init ir_sanyo_decode_init(void)
+{
+ ir_raw_handler_register(&sanyo_handler);
+
+ printk(KERN_INFO "IR SANYO protocol handler initialized\n");
+ return 0;
+}
+
+static void __exit ir_sanyo_decode_exit(void)
+{
+ ir_raw_handler_unregister(&sanyo_handler);
+}
+
+module_init(ir_sanyo_decode_init);
+module_exit(ir_sanyo_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
+MODULE_DESCRIPTION("SANYO IR protocol decoder");
diff --git a/drivers/media/rc/keymaps/rc-hauppauge.c b/drivers/media/rc/keymaps/rc-hauppauge.c
index e51c6163378b..929bbbc16393 100644
--- a/drivers/media/rc/keymaps/rc-hauppauge.c
+++ b/drivers/media/rc/keymaps/rc-hauppauge.c
@@ -183,6 +183,57 @@ static struct rc_map_table rc5_hauppauge_new[] = {
{ 0x1d3f, KEY_HOME },
/*
+ * Keycodes for PT# R-005 remote bundled with Haupauge HVR-930C
+ * Keycodes start with address = 0x1c
+ */
+ { 0x1c3b, KEY_GOTO },
+ { 0x1c3d, KEY_POWER },
+
+ { 0x1c14, KEY_UP },
+ { 0x1c15, KEY_DOWN },
+ { 0x1c16, KEY_LEFT },
+ { 0x1c17, KEY_RIGHT },
+ { 0x1c25, KEY_OK },
+
+ { 0x1c00, KEY_0 },
+ { 0x1c01, KEY_1 },
+ { 0x1c02, KEY_2 },
+ { 0x1c03, KEY_3 },
+ { 0x1c04, KEY_4 },
+ { 0x1c05, KEY_5 },
+ { 0x1c06, KEY_6 },
+ { 0x1c07, KEY_7 },
+ { 0x1c08, KEY_8 },
+ { 0x1c09, KEY_9 },
+
+ { 0x1c1f, KEY_EXIT }, /* BACK */
+ { 0x1c0d, KEY_MENU },
+ { 0x1c1c, KEY_TV },
+
+ { 0x1c10, KEY_VOLUMEUP },
+ { 0x1c11, KEY_VOLUMEDOWN },
+
+ { 0x1c20, KEY_CHANNELUP },
+ { 0x1c21, KEY_CHANNELDOWN },
+
+ { 0x1c0f, KEY_MUTE },
+ { 0x1c12, KEY_PREVIOUS }, /* Prev */
+
+ { 0x1c36, KEY_STOP },
+ { 0x1c37, KEY_RECORD },
+
+ { 0x1c24, KEY_LAST }, /* <| */
+ { 0x1c1e, KEY_NEXT }, /* >| */
+
+ { 0x1c0a, KEY_TEXT },
+ { 0x1c0e, KEY_SUBTITLE }, /* CC */
+
+ { 0x1c32, KEY_REWIND },
+ { 0x1c30, KEY_PAUSE },
+ { 0x1c35, KEY_PLAY },
+ { 0x1c34, KEY_FASTFORWARD },
+
+ /*
* Keycodes for the old Black Remote Controller
* This one also uses RC-5 protocol
* Keycodes start with address = 0x00
diff --git a/drivers/media/rc/keymaps/rc-videomate-m1f.c b/drivers/media/rc/keymaps/rc-videomate-m1f.c
index 3bd1de1f585c..23ee05e53949 100644
--- a/drivers/media/rc/keymaps/rc-videomate-m1f.c
+++ b/drivers/media/rc/keymaps/rc-videomate-m1f.c
@@ -1,4 +1,4 @@
-/* videomate-m1f.h - Keytable for videomate_m1f Remote Controller
+/* videomate-k100.h - Keytable for videomate_k100 Remote Controller
*
* keymap imported from ir-keymaps.c
*
@@ -13,7 +13,7 @@
#include <media/rc-map.h>
#include <linux/module.h>
-static struct rc_map_table videomate_m1f[] = {
+static struct rc_map_table videomate_k100[] = {
{ 0x01, KEY_POWER },
{ 0x31, KEY_TUNER },
{ 0x33, KEY_VIDEO },
@@ -67,27 +67,27 @@ static struct rc_map_table videomate_m1f[] = {
{ 0x18, KEY_TEXT },
};
-static struct rc_map_list videomate_m1f_map = {
+static struct rc_map_list videomate_k100_map = {
.map = {
- .scan = videomate_m1f,
- .size = ARRAY_SIZE(videomate_m1f),
+ .scan = videomate_k100,
+ .size = ARRAY_SIZE(videomate_k100),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
- .name = RC_MAP_VIDEOMATE_M1F,
+ .name = RC_MAP_VIDEOMATE_K100,
}
};
-static int __init init_rc_map_videomate_m1f(void)
+static int __init init_rc_map_videomate_k100(void)
{
- return rc_map_register(&videomate_m1f_map);
+ return rc_map_register(&videomate_k100_map);
}
-static void __exit exit_rc_map_videomate_m1f(void)
+static void __exit exit_rc_map_videomate_k100(void)
{
- rc_map_unregister(&videomate_m1f_map);
+ rc_map_unregister(&videomate_k100_map);
}
-module_init(init_rc_map_videomate_m1f)
-module_exit(exit_rc_map_videomate_m1f)
+module_init(init_rc_map_videomate_k100)
+module_exit(exit_rc_map_videomate_k100)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Pavel Osnova <pvosnova@gmail.com>");
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index c6ca870e8b7e..b72f8580e317 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -84,6 +84,11 @@ struct ir_raw_event_ctrl {
unsigned count;
unsigned wanted_bits;
} rc5_sz;
+ struct sanyo_dec {
+ int state;
+ unsigned count;
+ u64 bits;
+ } sanyo;
struct mce_kbd_dec {
struct input_dev *idev;
struct timer_list rx_timeout;
@@ -193,6 +198,13 @@ static inline void load_jvc_decode(void) { }
static inline void load_sony_decode(void) { }
#endif
+/* from ir-sanyo-decoder.c */
+#ifdef CONFIG_IR_SANYO_DECODER_MODULE
+#define load_sanyo_decode() request_module("ir-sanyo-decoder")
+#else
+static inline void load_sanyo_decode(void) { }
+#endif
+
/* from ir-mce_kbd-decoder.c */
#ifdef CONFIG_IR_MCE_KBD_DECODER_MODULE
#define load_mce_kbd_decode() request_module("ir-mce_kbd-decoder")
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index f5db8b949bc3..f6a930b70c69 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -736,6 +736,7 @@ static struct {
{ RC_TYPE_JVC, "jvc" },
{ RC_TYPE_SONY, "sony" },
{ RC_TYPE_RC5_SZ, "rc-5-sz" },
+ { RC_TYPE_SANYO, "sanyo" },
{ RC_TYPE_MCE_KBD, "mce_kbd" },
{ RC_TYPE_LIRC, "lirc" },
{ RC_TYPE_OTHER, "other" },
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index 07322fb75eff..ad95c67a4dba 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -286,12 +286,6 @@ static void redrat3_issue_async(struct redrat3_dev *rr3)
rr3_ftr(rr3->dev, "Entering %s\n", __func__);
- if (!rr3->det_enabled) {
- dev_warn(rr3->dev, "not issuing async read, "
- "detector not enabled\n");
- return;
- }
-
memset(rr3->bulk_in_buf, 0, rr3->ep_in->wMaxPacketSize);
res = usb_submit_urb(rr3->read_urb, GFP_ATOMIC);
if (res)
@@ -827,6 +821,7 @@ out:
static void redrat3_handle_async(struct urb *urb, struct pt_regs *regs)
{
struct redrat3_dev *rr3;
+ int ret;
if (!urb)
return;
@@ -840,15 +835,13 @@ static void redrat3_handle_async(struct urb *urb, struct pt_regs *regs)
rr3_ftr(rr3->dev, "Entering %s\n", __func__);
- if (!rr3->det_enabled) {
- rr3_dbg(rr3->dev, "received a read callback but detector "
- "disabled - ignoring\n");
- return;
- }
-
switch (urb->status) {
case 0:
- redrat3_get_ir_data(rr3, urb->actual_length);
+ ret = redrat3_get_ir_data(rr3, urb->actual_length);
+ if (!ret) {
+ /* no error, prepare to read more */
+ redrat3_issue_async(rr3);
+ }
break;
case -ECONNRESET:
@@ -865,11 +858,6 @@ static void redrat3_handle_async(struct urb *urb, struct pt_regs *regs)
rr3->pkttype = 0;
break;
}
-
- if (!rr3->transmitting)
- redrat3_issue_async(rr3);
- else
- rr3_dbg(rr3->dev, "IR transmit in progress\n");
}
static void redrat3_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
@@ -896,21 +884,24 @@ static u16 mod_freq_to_val(unsigned int mod_freq)
return (u16)(65536 - (mult / mod_freq));
}
-static int redrat3_set_tx_carrier(struct rc_dev *dev, u32 carrier)
+static int redrat3_set_tx_carrier(struct rc_dev *rcdev, u32 carrier)
{
- struct redrat3_dev *rr3 = dev->priv;
+ struct redrat3_dev *rr3 = rcdev->priv;
+ struct device *dev = rr3->dev;
+ rr3_dbg(dev, "Setting modulation frequency to %u", carrier);
rr3->carrier = carrier;
return carrier;
}
-static int redrat3_transmit_ir(struct rc_dev *rcdev, int *txbuf, u32 n)
+static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf,
+ unsigned count)
{
struct redrat3_dev *rr3 = rcdev->priv;
struct device *dev = rr3->dev;
struct redrat3_signal_header header;
- int i, j, count, ret, ret_len, offset;
+ int i, j, ret, ret_len, offset;
int lencheck, cur_sample_len, pipe;
char *buffer = NULL, *sigdata = NULL;
int *sample_lens = NULL;
@@ -928,20 +919,13 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, int *txbuf, u32 n)
return -EAGAIN;
}
- count = n / sizeof(int);
if (count > (RR3_DRIVER_MAXLENS * 2))
return -EINVAL;
+ /* rr3 will disable rc detector on transmit */
+ rr3->det_enabled = false;
rr3->transmitting = true;
- redrat3_disable_detector(rr3);
-
- if (rr3->det_enabled) {
- dev_err(dev, "%s: cannot tx while rx is enabled\n", __func__);
- ret = -EIO;
- goto out;
- }
-
sample_lens = kzalloc(sizeof(int) * RR3_DRIVER_MAXLENS, GFP_KERNEL);
if (!sample_lens) {
ret = -ENOMEM;
@@ -1055,7 +1039,7 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, int *txbuf, u32 n)
if (ret < 0)
dev_err(dev, "Error: control msg send failed, rc %d\n", ret);
else
- ret = n;
+ ret = count;
out:
kfree(sample_lens);
@@ -1063,8 +1047,8 @@ out:
kfree(sigdata);
rr3->transmitting = false;
-
- redrat3_enable_detector(rr3);
+ /* rr3 re-enables rc detector because it was enabled before */
+ rr3->det_enabled = true;
return ret;
}