aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/rc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-07 12:34:37 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-07 12:34:37 -0700
commit3036bc45364f98515a2c446d7fac2c34dcfbeff4 (patch)
treef565c03254413b779981ee5e9ed81b19d5b62c78 /drivers/media/rc
parentMerge tag 'powerpc-4.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux (diff)
parentmedia: omap2: fix compile-testing with FB_OMAP2=m (diff)
downloadlinux-dev-3036bc45364f98515a2c446d7fac2c34dcfbeff4.tar.xz
linux-dev-3036bc45364f98515a2c446d7fac2c34dcfbeff4.zip
Merge tag 'media/v4.18-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - remove of atomisp driver from staging, as nobody would have time to dedicate huge efforts to fix all the problems there. Also, we have a feeling that the driver may not even run the way it is. - move Zoran driver to staging, in order to be either fixed to use VB2 and the proper media kAPIs or to be removed - remove videobuf-dvb driver, with is unused for a while - some V4L2 documentation fixes/improvements - new sensor drivers: imx258 and ov7251 - a new driver was added to allow using I2C transparent drivers - several improvements at the ddbridge driver - several improvements at the ISDB pt1 driver, making it more coherent with the DVB framework - added a new platform driver for MIPI CSI-2 RX: cadence - now, all media drivers can be compiled on x86 with COMPILE_TEST - almost all media drivers now build on non-x86 architectures with COMPILE_TEST - lots of other random stuff: cleanups, support for new board models, bug fixes, etc * tag 'media/v4.18-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (464 commits) media: omap2: fix compile-testing with FB_OMAP2=m media: media/radio/Kconfig: add back RADIO_ISA media: v4l2-ioctl.c: fix missing unlock in __video_do_ioctl() media: pxa_camera: ignore -ENOIOCTLCMD from v4l2_subdev_call for s_power media: arch: sh: migor: Fix TW9910 PDN gpio media: staging: tegra-vde: Reset VDE regardless of memory client resetting failure media: marvel-ccic: mmp: select VIDEOBUF2_VMALLOC/DMA_CONTIG media: marvel-ccic: allow ccic and mmp drivers to coexist media: uvcvideo: Prevent setting unavailable flags media: ddbridge: conditionally enable fast TS for stv0910-equipped bridges media: dvb-frontends/stv0910: make TS speed configurable media: ddbridge/mci: add identifiers to function definition arguments media: ddbridge/mci: protect against out-of-bounds array access in stop() media: rc: ensure input/lirc device can be opened after register media: rc: nuvoton: Keep device enabled during reg init media: rc: nuvoton: Keep track of users on CIR enable/disable media: rc: nuvoton: Tweak the interrupt enabling dance media: uvcvideo: Support realtek's UVC 1.5 device media: uvcvideo: Fix driver reference counting media: gspca_zc3xx: Enable short exposure times for OV7648 ...
Diffstat (limited to 'drivers/media/rc')
-rw-r--r--drivers/media/rc/Kconfig10
-rw-r--r--drivers/media/rc/ir-imon-decoder.c136
-rw-r--r--drivers/media/rc/ir-jvc-decoder.c1
-rw-r--r--drivers/media/rc/ir-mce_kbd-decoder.c64
-rw-r--r--drivers/media/rc/ir-nec-decoder.c1
-rw-r--r--drivers/media/rc/ir-rc5-decoder.c4
-rw-r--r--drivers/media/rc/ir-rc6-decoder.c11
-rw-r--r--drivers/media/rc/ir-sanyo-decoder.c1
-rw-r--r--drivers/media/rc/ir-sharp-decoder.c1
-rw-r--r--drivers/media/rc/ir-sony-decoder.c1
-rw-r--r--drivers/media/rc/ir-spi.c4
-rw-r--r--drivers/media/rc/ir-xmp-decoder.c1
-rw-r--r--drivers/media/rc/ite-cir.c8
-rw-r--r--drivers/media/rc/ite-cir.h7
-rw-r--r--drivers/media/rc/lirc_dev.c31
-rw-r--r--drivers/media/rc/mceusb.c53
-rw-r--r--drivers/media/rc/mtk-cir.c4
-rw-r--r--drivers/media/rc/nuvoton-cir.c89
-rw-r--r--drivers/media/rc/rc-core-priv.h6
-rw-r--r--drivers/media/rc/rc-ir-raw.c81
-rw-r--r--drivers/media/rc/rc-main.c72
-rw-r--r--drivers/media/rc/st_rc.c16
-rw-r--r--drivers/media/rc/winbond-cir.c4
23 files changed, 430 insertions, 176 deletions
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index d5b35a6ba899..1021c08a9ba4 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -162,7 +162,7 @@ config RC_ATI_REMOTE
config IR_ENE
tristate "ENE eHome Receiver/Transceiver (pnp id: ENE0100/ENE02xxx)"
- depends on PNP
+ depends on PNP || COMPILE_TEST
depends on RC_CORE
---help---
Say Y here to enable support for integrated infrared receiver
@@ -223,7 +223,7 @@ config IR_MCEUSB
config IR_ITE_CIR
tristate "ITE Tech Inc. IT8712/IT8512 Consumer Infrared Transceiver"
- depends on PNP
+ depends on PNP || COMPILE_TEST
depends on RC_CORE
---help---
Say Y here to enable support for integrated infrared receivers
@@ -236,7 +236,7 @@ config IR_ITE_CIR
config IR_FINTEK
tristate "Fintek Consumer Infrared Transceiver"
- depends on PNP
+ depends on PNP || COMPILE_TEST
depends on RC_CORE
---help---
Say Y here to enable support for integrated infrared receiver
@@ -270,7 +270,7 @@ config IR_MTK
config IR_NUVOTON
tristate "Nuvoton w836x7hg Consumer Infrared Transceiver"
- depends on PNP
+ depends on PNP || COMPILE_TEST
depends on RC_CORE
---help---
Say Y here to enable support for integrated infrared receiver
@@ -318,7 +318,7 @@ config IR_STREAMZAP
config IR_WINBOND_CIR
tristate "Winbond IR remote control"
- depends on X86 && PNP
+ depends on (X86 && PNP) || COMPILE_TEST
depends on RC_CORE
select NEW_LEDS
select LEDS_CLASS
diff --git a/drivers/media/rc/ir-imon-decoder.c b/drivers/media/rc/ir-imon-decoder.c
index a1ff06a26542..67c1b0c15aae 100644
--- a/drivers/media/rc/ir-imon-decoder.c
+++ b/drivers/media/rc/ir-imon-decoder.c
@@ -31,9 +31,69 @@ enum imon_state {
STATE_INACTIVE,
STATE_BIT_CHK,
STATE_BIT_START,
- STATE_FINISHED
+ STATE_FINISHED,
+ STATE_ERROR,
};
+static void ir_imon_decode_scancode(struct rc_dev *dev)
+{
+ struct imon_dec *imon = &dev->raw->imon;
+
+ /* Keyboard/Mouse toggle */
+ if (imon->bits == 0x299115b7)
+ imon->stick_keyboard = !imon->stick_keyboard;
+
+ if ((imon->bits & 0xfc0000ff) == 0x680000b7) {
+ int rel_x, rel_y;
+ u8 buf;
+
+ buf = imon->bits >> 16;
+ rel_x = (buf & 0x08) | (buf & 0x10) >> 2 |
+ (buf & 0x20) >> 4 | (buf & 0x40) >> 6;
+ if (imon->bits & 0x02000000)
+ rel_x |= ~0x0f;
+ buf = imon->bits >> 8;
+ rel_y = (buf & 0x08) | (buf & 0x10) >> 2 |
+ (buf & 0x20) >> 4 | (buf & 0x40) >> 6;
+ if (imon->bits & 0x01000000)
+ rel_y |= ~0x0f;
+
+ if (rel_x && rel_y && imon->stick_keyboard) {
+ if (abs(rel_y) > abs(rel_x))
+ imon->bits = rel_y > 0 ?
+ 0x289515b7 : /* KEY_DOWN */
+ 0x2aa515b7; /* KEY_UP */
+ else
+ imon->bits = rel_x > 0 ?
+ 0x2ba515b7 : /* KEY_RIGHT */
+ 0x29a515b7; /* KEY_LEFT */
+ }
+
+ if (!imon->stick_keyboard) {
+ struct lirc_scancode lsc = {
+ .scancode = imon->bits,
+ .rc_proto = RC_PROTO_IMON,
+ };
+
+ ir_lirc_scancode_event(dev, &lsc);
+
+ input_event(imon->idev, EV_MSC, MSC_SCAN, imon->bits);
+
+ input_report_rel(imon->idev, REL_X, rel_x);
+ input_report_rel(imon->idev, REL_Y, rel_y);
+
+ input_report_key(imon->idev, BTN_LEFT,
+ (imon->bits & 0x00010000) != 0);
+ input_report_key(imon->idev, BTN_RIGHT,
+ (imon->bits & 0x00040000) != 0);
+ input_sync(imon->idev);
+ return;
+ }
+ }
+
+ rc_keydown(dev, RC_PROTO_IMON, imon->bits, 0);
+}
+
/**
* ir_imon_decode() - Decode one iMON pulse or space
* @dev: the struct rc_dev descriptor of the device
@@ -56,6 +116,22 @@ static int ir_imon_decode(struct rc_dev *dev, struct ir_raw_event ev)
data->state, data->count, TO_US(ev.duration),
TO_STR(ev.pulse));
+ /*
+ * Since iMON protocol is a series of bits, if at any point
+ * we encounter an error, make sure that any remaining bits
+ * aren't parsed as a scancode made up of less bits.
+ *
+ * Note that if the stick is held, then the remote repeats
+ * the scancode with about 12ms between them. So, make sure
+ * we have at least 10ms of space after an error. That way,
+ * we're at a new scancode.
+ */
+ if (data->state == STATE_ERROR) {
+ if (!ev.pulse && ev.duration > MS_TO_NS(10))
+ data->state = STATE_INACTIVE;
+ return 0;
+ }
+
for (;;) {
if (!geq_margin(ev.duration, IMON_UNIT, IMON_UNIT / 2))
return 0;
@@ -95,7 +171,7 @@ static int ir_imon_decode(struct rc_dev *dev, struct ir_raw_event ev)
case STATE_FINISHED:
if (ev.pulse)
goto err_out;
- rc_keydown(dev, RC_PROTO_IMON, data->bits, 0);
+ ir_imon_decode_scancode(dev);
data->state = STATE_INACTIVE;
break;
}
@@ -107,7 +183,7 @@ err_out:
data->state, data->count, TO_US(ev.duration),
TO_STR(ev.pulse));
- data->state = STATE_INACTIVE;
+ data->state = STATE_ERROR;
return -EINVAL;
}
@@ -165,11 +241,65 @@ static int ir_imon_encode(enum rc_proto protocol, u32 scancode,
return e - events;
}
+static int ir_imon_register(struct rc_dev *dev)
+{
+ struct input_dev *idev;
+ struct imon_dec *imon = &dev->raw->imon;
+ int ret;
+
+ idev = input_allocate_device();
+ if (!idev)
+ return -ENOMEM;
+
+ snprintf(imon->name, sizeof(imon->name),
+ "iMON PAD Stick (%s)", dev->device_name);
+ idev->name = imon->name;
+ idev->phys = dev->input_phys;
+
+ /* Mouse bits */
+ set_bit(EV_REL, idev->evbit);
+ set_bit(EV_KEY, idev->evbit);
+ set_bit(REL_X, idev->relbit);
+ set_bit(REL_Y, idev->relbit);
+ set_bit(BTN_LEFT, idev->keybit);
+ set_bit(BTN_RIGHT, idev->keybit);
+
+ /* Report scancodes too */
+ set_bit(EV_MSC, idev->evbit);
+ set_bit(MSC_SCAN, idev->mscbit);
+
+ input_set_drvdata(idev, imon);
+
+ ret = input_register_device(idev);
+ if (ret < 0) {
+ input_free_device(idev);
+ return -EIO;
+ }
+
+ imon->idev = idev;
+ imon->stick_keyboard = false;
+
+ return 0;
+}
+
+static int ir_imon_unregister(struct rc_dev *dev)
+{
+ struct imon_dec *imon = &dev->raw->imon;
+
+ input_unregister_device(imon->idev);
+ imon->idev = NULL;
+
+ return 0;
+}
+
static struct ir_raw_handler imon_handler = {
.protocols = RC_PROTO_BIT_IMON,
.decode = ir_imon_decode,
.encode = ir_imon_encode,
.carrier = 38000,
+ .raw_register = ir_imon_register,
+ .raw_unregister = ir_imon_unregister,
+ .min_timeout = IMON_UNIT * IMON_BITS * 2,
};
static int __init ir_imon_decode_init(void)
diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c
index 8cb68ae43282..5706cfe60027 100644
--- a/drivers/media/rc/ir-jvc-decoder.c
+++ b/drivers/media/rc/ir-jvc-decoder.c
@@ -213,6 +213,7 @@ static struct ir_raw_handler jvc_handler = {
.decode = ir_jvc_decode,
.encode = ir_jvc_encode,
.carrier = 38000,
+ .min_timeout = JVC_TRAILER_SPACE,
};
static int __init ir_jvc_decode_init(void)
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index c110984ca671..64ea42927669 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -119,17 +119,25 @@ static void mce_kbd_rx_timeout(struct timer_list *t)
{
struct ir_raw_event_ctrl *raw = from_timer(raw, t, mce_kbd.rx_timeout);
unsigned char maskcode;
+ unsigned long flags;
int i;
dev_dbg(&raw->dev->dev, "timer callback clearing all keys\n");
- for (i = 0; i < 7; i++) {
- maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i];
- input_report_key(raw->mce_kbd.idev, maskcode, 0);
- }
+ spin_lock_irqsave(&raw->mce_kbd.keylock, flags);
+
+ if (time_is_before_eq_jiffies(raw->mce_kbd.rx_timeout.expires)) {
+ for (i = 0; i < 7; i++) {
+ maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i];
+ input_report_key(raw->mce_kbd.idev, maskcode, 0);
+ }
+
+ for (i = 0; i < MCIR2_MASK_KEYS_START; i++)
+ input_report_key(raw->mce_kbd.idev, kbd_keycodes[i], 0);
- for (i = 0; i < MCIR2_MASK_KEYS_START; i++)
- input_report_key(raw->mce_kbd.idev, kbd_keycodes[i], 0);
+ input_sync(raw->mce_kbd.idev);
+ }
+ spin_unlock_irqrestore(&raw->mce_kbd.keylock, flags);
}
static enum mce_kbd_mode mce_kbd_mode(struct mce_kbd_dec *data)
@@ -147,13 +155,14 @@ static enum mce_kbd_mode mce_kbd_mode(struct mce_kbd_dec *data)
static void ir_mce_kbd_process_keyboard_data(struct rc_dev *dev, u32 scancode)
{
struct mce_kbd_dec *data = &dev->raw->mce_kbd;
- u8 keydata = (scancode >> 8) & 0xff;
+ u8 keydata1 = (scancode >> 8) & 0xff;
+ u8 keydata2 = (scancode >> 16) & 0xff;
u8 shiftmask = scancode & 0xff;
- unsigned char keycode, maskcode;
+ unsigned char maskcode;
int i, keystate;
- dev_dbg(&dev->dev, "keyboard: keydata = 0x%02x, shiftmask = 0x%02x\n",
- keydata, shiftmask);
+ dev_dbg(&dev->dev, "keyboard: keydata2 = 0x%02x, keydata1 = 0x%02x, shiftmask = 0x%02x\n",
+ keydata2, keydata1, shiftmask);
for (i = 0; i < 7; i++) {
maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i];
@@ -164,10 +173,12 @@ static void ir_mce_kbd_process_keyboard_data(struct rc_dev *dev, u32 scancode)
input_report_key(data->idev, maskcode, keystate);
}
- if (keydata) {
- keycode = kbd_keycodes[keydata];
- input_report_key(data->idev, keycode, 1);
- } else {
+ if (keydata1)
+ input_report_key(data->idev, kbd_keycodes[keydata1], 1);
+ if (keydata2)
+ input_report_key(data->idev, kbd_keycodes[keydata2], 1);
+
+ if (!keydata1 && !keydata2) {
for (i = 0; i < MCIR2_MASK_KEYS_START; i++)
input_report_key(data->idev, kbd_keycodes[i], 0);
}
@@ -263,9 +274,6 @@ again:
return 0;
case STATE_HEADER_BIT_END:
- if (!is_transition(&ev, &dev->raw->prev_ev))
- break;
-
decrease_duration(&ev, MCIR2_BIT_END);
if (data->count != MCIR2_HEADER_NBITS) {
@@ -302,9 +310,6 @@ again:
return 0;
case STATE_BODY_BIT_END:
- if (!is_transition(&ev, &dev->raw->prev_ev))
- break;
-
if (data->count == data->wanted_bits)
data->state = STATE_FINISHED;
else
@@ -319,16 +324,20 @@ again:
switch (data->wanted_bits) {
case MCIR2_KEYBOARD_NBITS:
- scancode = data->body & 0xffff;
+ scancode = data->body & 0xffffff;
dev_dbg(&dev->dev, "keyboard data 0x%08x\n",
data->body);
- if (dev->timeout)
- delay = usecs_to_jiffies(dev->timeout / 1000);
- else
- delay = msecs_to_jiffies(100);
- mod_timer(&data->rx_timeout, jiffies + delay);
+ spin_lock(&data->keylock);
+ if (scancode) {
+ delay = nsecs_to_jiffies(dev->timeout) +
+ msecs_to_jiffies(100);
+ mod_timer(&data->rx_timeout, jiffies + delay);
+ } else {
+ del_timer(&data->rx_timeout);
+ }
/* Pass data to keyboard buffer parser */
ir_mce_kbd_process_keyboard_data(dev, scancode);
+ spin_unlock(&data->keylock);
lsc.rc_proto = RC_PROTO_MCIR2_KBD;
break;
case MCIR2_MOUSE_NBITS:
@@ -355,7 +364,6 @@ out:
dev_dbg(&dev->dev, "failed at state %i (%uus %s)\n",
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
- input_sync(data->idev);
return -EINVAL;
}
@@ -394,6 +402,7 @@ static int ir_mce_kbd_register(struct rc_dev *dev)
set_bit(MSC_SCAN, idev->mscbit);
timer_setup(&mce_kbd->rx_timeout, mce_kbd_rx_timeout, 0);
+ spin_lock_init(&mce_kbd->keylock);
input_set_drvdata(idev, mce_kbd);
@@ -475,6 +484,7 @@ static struct ir_raw_handler mce_kbd_handler = {
.raw_register = ir_mce_kbd_register,
.raw_unregister = ir_mce_kbd_unregister,
.carrier = 36000,
+ .min_timeout = MCIR2_MAX_LEN + MCIR2_UNIT / 2,
};
static int __init ir_mce_kbd_decode_init(void)
diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c
index 21647b809e6f..6a8973ae3684 100644
--- a/drivers/media/rc/ir-nec-decoder.c
+++ b/drivers/media/rc/ir-nec-decoder.c
@@ -253,6 +253,7 @@ static struct ir_raw_handler nec_handler = {
.decode = ir_nec_decode,
.encode = ir_nec_encode,
.carrier = 38000,
+ .min_timeout = NEC_TRAILER_SPACE,
};
static int __init ir_nec_decode_init(void)
diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
index 74d3b859c3a2..63624654a71e 100644
--- a/drivers/media/rc/ir-rc5-decoder.c
+++ b/drivers/media/rc/ir-rc5-decoder.c
@@ -88,9 +88,6 @@ again:
return 0;
case STATE_BIT_END:
- if (!is_transition(&ev, &dev->raw->prev_ev))
- break;
-
if (data->count == CHECK_RC5X_NBITS)
data->state = STATE_CHECK_RC5X;
else
@@ -274,6 +271,7 @@ static struct ir_raw_handler rc5_handler = {
.decode = ir_rc5_decode,
.encode = ir_rc5_encode,
.carrier = 36000,
+ .min_timeout = RC5_TRAILER,
};
static int __init ir_rc5_decode_init(void)
diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c
index 8314da32453f..68487ce9f79b 100644
--- a/drivers/media/rc/ir-rc6-decoder.c
+++ b/drivers/media/rc/ir-rc6-decoder.c
@@ -145,9 +145,6 @@ again:
return 0;
case STATE_HEADER_BIT_END:
- if (!is_transition(&ev, &dev->raw->prev_ev))
- break;
-
if (data->count == RC6_HEADER_NBITS)
data->state = STATE_TOGGLE_START;
else
@@ -165,10 +162,6 @@ again:
return 0;
case STATE_TOGGLE_END:
- if (!is_transition(&ev, &dev->raw->prev_ev) ||
- !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2))
- break;
-
if (!(data->header & RC6_STARTBIT_MASK)) {
dev_dbg(&dev->dev, "RC6 invalid start bit\n");
break;
@@ -210,9 +203,6 @@ again:
break;
case STATE_BODY_BIT_END:
- if (!is_transition(&ev, &dev->raw->prev_ev))
- break;
-
if (data->count == data->wanted_bits)
data->state = STATE_FINISHED;
else
@@ -394,6 +384,7 @@ static struct ir_raw_handler rc6_handler = {
.decode = ir_rc6_decode,
.encode = ir_rc6_encode,
.carrier = 36000,
+ .min_timeout = RC6_SUFFIX_SPACE,
};
static int __init ir_rc6_decode_init(void)
diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c
index 4efe6db5376a..dd6ee1e339d6 100644
--- a/drivers/media/rc/ir-sanyo-decoder.c
+++ b/drivers/media/rc/ir-sanyo-decoder.c
@@ -210,6 +210,7 @@ static struct ir_raw_handler sanyo_handler = {
.decode = ir_sanyo_decode,
.encode = ir_sanyo_encode,
.carrier = 38000,
+ .min_timeout = SANYO_TRAILER_SPACE,
};
static int __init ir_sanyo_decode_init(void)
diff --git a/drivers/media/rc/ir-sharp-decoder.c b/drivers/media/rc/ir-sharp-decoder.c
index 6a38c50566a4..f96e0c992eed 100644
--- a/drivers/media/rc/ir-sharp-decoder.c
+++ b/drivers/media/rc/ir-sharp-decoder.c
@@ -226,6 +226,7 @@ static struct ir_raw_handler sharp_handler = {
.decode = ir_sharp_decode,
.encode = ir_sharp_encode,
.carrier = 38000,
+ .min_timeout = SHARP_ECHO_SPACE + SHARP_ECHO_SPACE / 4,
};
static int __init ir_sharp_decode_init(void)
diff --git a/drivers/media/rc/ir-sony-decoder.c b/drivers/media/rc/ir-sony-decoder.c
index 6764ec9de646..5065c081238d 100644
--- a/drivers/media/rc/ir-sony-decoder.c
+++ b/drivers/media/rc/ir-sony-decoder.c
@@ -224,6 +224,7 @@ static struct ir_raw_handler sony_handler = {
.decode = ir_sony_decode,
.encode = ir_sony_encode,
.carrier = 40000,
+ .min_timeout = SONY_TRAILER_SPACE,
};
static int __init ir_sony_decode_init(void)
diff --git a/drivers/media/rc/ir-spi.c b/drivers/media/rc/ir-spi.c
index 7163d5ce2e64..66334e8d63ba 100644
--- a/drivers/media/rc/ir-spi.c
+++ b/drivers/media/rc/ir-spi.c
@@ -2,7 +2,7 @@
// SPI driven IR LED device driver
//
// Copyright (c) 2016 Samsung Electronics Co., Ltd.
-// Copyright (c) Andi Shyti <andi.shyti@samsung.com>
+// Copyright (c) Andi Shyti <andi@etezian.org>
#include <linux/delay.h>
#include <linux/fs.h>
@@ -173,6 +173,6 @@ static struct spi_driver ir_spi_driver = {
module_spi_driver(ir_spi_driver);
-MODULE_AUTHOR("Andi Shyti <andi.shyti@samsung.com>");
+MODULE_AUTHOR("Andi Shyti <andi@etezian.org>");
MODULE_DESCRIPTION("SPI IR LED");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/rc/ir-xmp-decoder.c b/drivers/media/rc/ir-xmp-decoder.c
index 58b47af1a763..c965f51df1c1 100644
--- a/drivers/media/rc/ir-xmp-decoder.c
+++ b/drivers/media/rc/ir-xmp-decoder.c
@@ -199,6 +199,7 @@ static int ir_xmp_decode(struct rc_dev *dev, struct ir_raw_event ev)
static struct ir_raw_handler xmp_handler = {
.protocols = RC_PROTO_BIT_XMP,
.decode = ir_xmp_decode,
+ .min_timeout = XMP_TRAILER_SPACE,
};
static int __init ir_xmp_decode_init(void)
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
index 65e104c7ddfc..de77d22c30a7 100644
--- a/drivers/media/rc/ite-cir.c
+++ b/drivers/media/rc/ite-cir.c
@@ -1561,9 +1561,11 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
rdev->close = ite_close;
rdev->s_idle = ite_s_idle;
rdev->s_rx_carrier_range = ite_set_rx_carrier_range;
- rdev->min_timeout = ITE_MIN_IDLE_TIMEOUT;
- rdev->max_timeout = ITE_MAX_IDLE_TIMEOUT;
- rdev->timeout = ITE_IDLE_TIMEOUT;
+ /* FIFO threshold is 17 bytes, so 17 * 8 samples minimum */
+ rdev->min_timeout = 17 * 8 * ITE_BAUDRATE_DIVISOR *
+ itdev->params.sample_period;
+ rdev->timeout = IR_DEFAULT_TIMEOUT;
+ rdev->max_timeout = 10 * IR_DEFAULT_TIMEOUT;
rdev->rx_resolution = ITE_BAUDRATE_DIVISOR *
itdev->params.sample_period;
rdev->tx_resolution = ITE_BAUDRATE_DIVISOR *
diff --git a/drivers/media/rc/ite-cir.h b/drivers/media/rc/ite-cir.h
index 0e8ebc880d1f..9cb24ac01350 100644
--- a/drivers/media/rc/ite-cir.h
+++ b/drivers/media/rc/ite-cir.h
@@ -154,13 +154,6 @@ struct ite_dev {
/* default carrier freq for when demodulator is off (Hz) */
#define ITE_DEFAULT_CARRIER_FREQ 38000
-/* default idling timeout in ns (0.2 seconds) */
-#define ITE_IDLE_TIMEOUT 200000000UL
-
-/* limit timeout values */
-#define ITE_MIN_IDLE_TIMEOUT 100000000UL
-#define ITE_MAX_IDLE_TIMEOUT 1000000000UL
-
/* convert bits to us */
#define ITE_BITS_TO_NS(bits, sample_period) \
((u32) ((bits) * ITE_BAUDRATE_DIVISOR * sample_period))
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index da7013a12a58..f862f1b7f996 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -582,10 +582,17 @@ static long ir_lirc_ioctl(struct file *file, unsigned int cmd,
}
break;
- case LIRC_SET_REC_TIMEOUT_REPORTS:
+ case LIRC_GET_REC_TIMEOUT:
if (!dev->timeout)
ret = -ENOTTY;
else
+ val = DIV_ROUND_UP(dev->timeout, 1000);
+ break;
+
+ case LIRC_SET_REC_TIMEOUT_REPORTS:
+ if (dev->driver_type != RC_DRIVER_IR_RAW)
+ ret = -ENOTTY;
+ else
fh->send_timeout_reports = !!val;
break;
@@ -742,6 +749,7 @@ static void lirc_release_device(struct device *ld)
int ir_lirc_register(struct rc_dev *dev)
{
+ const char *rx_type, *tx_type;
int err, minor;
minor = ida_simple_get(&lirc_ida, 0, RC_DEV_MAX, GFP_KERNEL);
@@ -766,8 +774,25 @@ int ir_lirc_register(struct rc_dev *dev)
get_device(&dev->dev);
- dev_info(&dev->dev, "lirc_dev: driver %s registered at minor = %d",
- dev->driver_name, minor);
+ switch (dev->driver_type) {
+ case RC_DRIVER_SCANCODE:
+ rx_type = "scancode";
+ break;
+ case RC_DRIVER_IR_RAW:
+ rx_type = "raw IR";
+ break;
+ default:
+ rx_type = "no";
+ break;
+ }
+
+ if (dev->tx_ir)
+ tx_type = "raw IR";
+ else
+ tx_type = "no";
+
+ dev_info(&dev->dev, "lirc_dev: driver %s registered at minor = %d, %s receiver, %s transmitter",
+ dev->driver_name, minor, rx_type, tx_type);
return 0;
diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index 69ba57372c05..4c0c8008872a 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -181,6 +181,7 @@ enum mceusb_model_type {
MCE_GEN2 = 0, /* Most boards */
MCE_GEN1,
MCE_GEN3,
+ MCE_GEN3_BROKEN_IRTIMEOUT,
MCE_GEN2_TX_INV,
MCE_GEN2_TX_INV_RX_GOOD,
POLARIS_EVK,
@@ -199,6 +200,7 @@ struct mceusb_model {
u32 mce_gen3:1;
u32 tx_mask_normal:1;
u32 no_tx:1;
+ u32 broken_irtimeout:1;
/*
* 2nd IR receiver (short-range, wideband) for learning mode:
* 0, absent 2nd receiver (rx2)
@@ -242,6 +244,12 @@ static const struct mceusb_model mceusb_model[] = {
.tx_mask_normal = 1,
.rx2 = 2,
},
+ [MCE_GEN3_BROKEN_IRTIMEOUT] = {
+ .mce_gen3 = 1,
+ .tx_mask_normal = 1,
+ .rx2 = 2,
+ .broken_irtimeout = 1
+ },
[POLARIS_EVK] = {
/*
* In fact, the EVK is shipped without
@@ -352,7 +360,7 @@ static const struct usb_device_id mceusb_dev_table[] = {
.driver_info = MCE_GEN2_TX_INV },
/* Topseed eHome Infrared Transceiver */
{ USB_DEVICE(VENDOR_TOPSEED, 0x0011),
- .driver_info = MCE_GEN3 },
+ .driver_info = MCE_GEN3_BROKEN_IRTIMEOUT },
/* Ricavision internal Infrared Transceiver */
{ USB_DEVICE(VENDOR_RICAVISION, 0x0010) },
/* Itron ione Libra Q-11 */
@@ -564,6 +572,7 @@ static int mceusb_cmd_datasize(u8 cmd, u8 subcmd)
datasize = 1;
break;
}
+ break;
case MCE_CMD_PORT_IR:
switch (subcmd) {
case MCE_CMD_UNKNOWN:
@@ -982,6 +991,25 @@ static int mceusb_set_tx_carrier(struct rc_dev *dev, u32 carrier)
return 0;
}
+static int mceusb_set_timeout(struct rc_dev *dev, unsigned int timeout)
+{
+ u8 cmdbuf[4] = { MCE_CMD_PORT_IR, MCE_CMD_SETIRTIMEOUT, 0, 0 };
+ struct mceusb_dev *ir = dev->priv;
+ unsigned int units;
+
+ units = DIV_ROUND_CLOSEST(timeout, US_TO_NS(MCE_TIME_UNIT));
+
+ cmdbuf[2] = units >> 8;
+ cmdbuf[3] = units;
+
+ mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
+
+ /* get receiver timeout value */
+ mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT));
+
+ return 0;
+}
+
/*
* Select or deselect the 2nd receiver port.
* Second receiver is learning mode, wide-band, short-range receiver.
@@ -1150,6 +1178,11 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
init_ir_raw_event(&rawir);
rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0);
rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK);
+ if (unlikely(!rawir.duration)) {
+ dev_warn(ir->dev, "nonsensical irdata %02x with duration 0",
+ ir->buf_in[i]);
+ break;
+ }
if (rawir.pulse) {
ir->pulse_tunit += rawir.duration;
ir->pulse_count++;
@@ -1182,7 +1215,12 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
if (ir->rem) {
ir->parser_state = PARSE_IRDATA;
} else {
- ir_raw_event_reset(ir->rc);
+ init_ir_raw_event(&rawir);
+ rawir.timeout = 1;
+ rawir.duration = ir->rc->timeout;
+ if (ir_raw_event_store_with_filter(ir->rc,
+ &rawir))
+ event = true;
ir->pulse_tunit = 0;
ir->pulse_count = 0;
}
@@ -1415,7 +1453,18 @@ static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
rc->dev.parent = dev;
rc->priv = ir;
rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
+ rc->min_timeout = US_TO_NS(MCE_TIME_UNIT);
rc->timeout = MS_TO_NS(100);
+ if (!mceusb_model[ir->model].broken_irtimeout) {
+ rc->s_timeout = mceusb_set_timeout;
+ rc->max_timeout = 10 * IR_DEFAULT_TIMEOUT;
+ } else {
+ /*
+ * If we can't set the timeout using CMD_SETIRTIMEOUT, we can
+ * rely on software timeouts for timeouts < 100ms.
+ */
+ rc->max_timeout = rc->timeout;
+ }
if (!ir->flags.no_tx) {
rc->s_tx_mask = mceusb_set_tx_mask;
rc->s_tx_carrier = mceusb_set_tx_carrier;
diff --git a/drivers/media/rc/mtk-cir.c b/drivers/media/rc/mtk-cir.c
index e88eb64e8e69..e42efd9d382e 100644
--- a/drivers/media/rc/mtk-cir.c
+++ b/drivers/media/rc/mtk-cir.c
@@ -299,8 +299,6 @@ static int mtk_ir_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *dn = dev->of_node;
- const struct of_device_id *of_id =
- of_match_device(mtk_ir_match, &pdev->dev);
struct resource *res;
struct mtk_ir *ir;
u32 val;
@@ -312,7 +310,7 @@ static int mtk_ir_probe(struct platform_device *pdev)
return -ENOMEM;
ir->dev = dev;
- ir->data = of_id->data;
+ ir->data = of_device_get_match_data(dev);
ir->clk = devm_clk_get(dev, "clk");
if (IS_ERR(ir->clk)) {
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 5e1d866a61a5..b8299c9a9744 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -535,6 +535,8 @@ static void nvt_set_cir_iren(struct nvt_dev *nvt)
static void nvt_cir_regs_init(struct nvt_dev *nvt)
{
+ nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR);
+
/* set sample limit count (PE interrupt raised when reached) */
nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_SLCH);
nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_SLCL);
@@ -543,31 +545,17 @@ static void nvt_cir_regs_init(struct nvt_dev *nvt)
nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV |
CIR_FIFOCON_RX_TRIGGER_LEV, CIR_FIFOCON);
- /*
- * Enable TX and RX, specify carrier on = low, off = high, and set
- * sample period (currently 50us)
- */
- nvt_cir_reg_write(nvt,
- CIR_IRCON_TXEN | CIR_IRCON_RXEN |
- CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL,
- CIR_IRCON);
-
/* clear hardware rx and tx fifos */
nvt_clear_cir_fifo(nvt);
nvt_clear_tx_fifo(nvt);
- /* clear any and all stray interrupts */
- nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
-
- /* and finally, enable interrupts */
- nvt_set_cir_iren(nvt);
-
- /* enable the CIR logical device */
- nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR);
+ nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR);
}
static void nvt_cir_wake_regs_init(struct nvt_dev *nvt)
{
+ nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
+
/*
* Disable RX, set specific carrier on = low, off = high,
* and sample period (currently 50us)
@@ -579,9 +567,6 @@ static void nvt_cir_wake_regs_init(struct nvt_dev *nvt)
/* clear any and all stray interrupts */
nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS);
-
- /* enable the CIR WAKE logical device */
- nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
}
static void nvt_enable_wake(struct nvt_dev *nvt)
@@ -892,6 +877,32 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
return IRQ_HANDLED;
}
+static void nvt_enable_cir(struct nvt_dev *nvt)
+{
+ unsigned long flags;
+
+ /* enable the CIR logical device */
+ nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR);
+
+ spin_lock_irqsave(&nvt->lock, flags);
+
+ /*
+ * Enable TX and RX, specify carrier on = low, off = high, and set
+ * sample period (currently 50us)
+ */
+ nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN |
+ CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL,
+ CIR_IRCON);
+
+ /* clear all pending interrupts */
+ nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
+
+ /* enable interrupts */
+ nvt_set_cir_iren(nvt);
+
+ spin_unlock_irqrestore(&nvt->lock, flags);
+}
+
static void nvt_disable_cir(struct nvt_dev *nvt)
{
unsigned long flags;
@@ -920,25 +931,8 @@ static void nvt_disable_cir(struct nvt_dev *nvt)
static int nvt_open(struct rc_dev *dev)
{
struct nvt_dev *nvt = dev->priv;
- unsigned long flags;
-
- spin_lock_irqsave(&nvt->lock, flags);
-
- /* set function enable flags */
- nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN |
- CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL,
- CIR_IRCON);
-
- /* clear all pending interrupts */
- nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
-
- /* enable interrupts */
- nvt_set_cir_iren(nvt);
- spin_unlock_irqrestore(&nvt->lock, flags);
-
- /* enable the CIR logical device */
- nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR);
+ nvt_enable_cir(nvt);
return 0;
}
@@ -1093,19 +1087,13 @@ static void nvt_remove(struct pnp_dev *pdev)
static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state)
{
struct nvt_dev *nvt = pnp_get_drvdata(pdev);
- unsigned long flags;
nvt_dbg("%s called", __func__);
- spin_lock_irqsave(&nvt->lock, flags);
-
- /* disable all CIR interrupts */
- nvt_cir_reg_write(nvt, 0, CIR_IREN);
-
- spin_unlock_irqrestore(&nvt->lock, flags);
-
- /* disable cir logical dev */
- nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR);
+ mutex_lock(&nvt->rdev->lock);
+ if (nvt->rdev->users)
+ nvt_disable_cir(nvt);
+ mutex_unlock(&nvt->rdev->lock);
/* make sure wake is enabled */
nvt_enable_wake(nvt);
@@ -1122,6 +1110,11 @@ static int nvt_resume(struct pnp_dev *pdev)
nvt_cir_regs_init(nvt);
nvt_cir_wake_regs_init(nvt);
+ mutex_lock(&nvt->rdev->lock);
+ if (nvt->rdev->users)
+ nvt_enable_cir(nvt);
+ mutex_unlock(&nvt->rdev->lock);
+
return 0;
}
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index eb004757038b..e847bdad5c51 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -38,6 +38,7 @@ struct ir_raw_handler {
int (*encode)(enum rc_proto protocol, u32 scancode,
struct ir_raw_event *events, unsigned int max);
u32 carrier;
+ u32 min_timeout;
/* These two should only be used by the mce kbd decoder */
int (*raw_register)(struct rc_dev *dev);
@@ -110,6 +111,8 @@ struct ir_raw_event_ctrl {
} sharp;
struct mce_kbd_dec {
struct input_dev *idev;
+ /* locks key up timer */
+ spinlock_t keylock;
struct timer_list rx_timeout;
char name[64];
char phys[64];
@@ -129,6 +132,9 @@ struct ir_raw_event_ctrl {
int count;
int last_chk;
unsigned int bits;
+ bool stick_keyboard;
+ struct input_dev *idev;
+ char name[64];
} imon;
};
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 7675b7ee5bc7..2e0066b1a31c 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -22,16 +22,27 @@ static int ir_raw_event_thread(void *data)
{
struct ir_raw_event ev;
struct ir_raw_handler *handler;
- struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data;
+ struct ir_raw_event_ctrl *raw = data;
+ struct rc_dev *dev = raw->dev;
while (1) {
mutex_lock(&ir_raw_handler_lock);
while (kfifo_out(&raw->kfifo, &ev, 1)) {
+ if (is_timing_event(ev)) {
+ if (ev.duration == 0)
+ dev_err(&dev->dev, "nonsensical timing event of duration 0");
+ if (is_timing_event(raw->prev_ev) &&
+ !is_transition(&ev, &raw->prev_ev))
+ dev_err(&dev->dev, "two consecutive events of type %s",
+ TO_STR(ev.pulse));
+ if (raw->prev_ev.reset && ev.pulse == 0)
+ dev_err(&dev->dev, "timing event after reset should be pulse");
+ }
list_for_each_entry(handler, &ir_raw_handler_list, list)
- if (raw->dev->enabled_protocols &
+ if (dev->enabled_protocols &
handler->protocols || !handler->protocols)
- handler->decode(raw->dev, ev);
- ir_lirc_raw_event(raw->dev, ev);
+ handler->decode(dev, ev);
+ ir_lirc_raw_event(dev, ev);
raw->prev_ev = ev;
}
mutex_unlock(&ir_raw_handler_lock);
@@ -233,7 +244,49 @@ ir_raw_get_allowed_protocols(void)
static int change_protocol(struct rc_dev *dev, u64 *rc_proto)
{
- /* the caller will update dev->enabled_protocols */
+ struct ir_raw_handler *handler;
+ u32 timeout = 0;
+
+ mutex_lock(&ir_raw_handler_lock);
+ list_for_each_entry(handler, &ir_raw_handler_list, list) {
+ if (!(dev->enabled_protocols & handler->protocols) &&
+ (*rc_proto & handler->protocols) && handler->raw_register)
+ handler->raw_register(dev);
+
+ if ((dev->enabled_protocols & handler->protocols) &&
+ !(*rc_proto & handler->protocols) &&
+ handler->raw_unregister)
+ handler->raw_unregister(dev);
+ }
+ mutex_unlock(&ir_raw_handler_lock);
+
+ if (!dev->max_timeout)
+ return 0;
+
+ mutex_lock(&ir_raw_handler_lock);
+ list_for_each_entry(handler, &ir_raw_handler_list, list) {
+ if (handler->protocols & *rc_proto) {
+ if (timeout < handler->min_timeout)
+ timeout = handler->min_timeout;
+ }
+ }
+ mutex_unlock(&ir_raw_handler_lock);
+
+ if (timeout == 0)
+ timeout = IR_DEFAULT_TIMEOUT;
+ else
+ timeout += MS_TO_NS(10);
+
+ if (timeout < dev->min_timeout)
+ timeout = dev->min_timeout;
+ else if (timeout > dev->max_timeout)
+ timeout = dev->max_timeout;
+
+ if (dev->s_timeout)
+ dev->s_timeout(dev, timeout);
+ else
+ dev->timeout = timeout;
+
return 0;
}
@@ -569,6 +622,7 @@ int ir_raw_event_prepare(struct rc_dev *dev)
dev->raw->dev = dev;
dev->change_protocol = change_protocol;
+ dev->idle = true;
spin_lock_init(&dev->raw->edge_spinlock);
timer_setup(&dev->raw->edge_handle, ir_raw_edge_handle, 0);
INIT_KFIFO(dev->raw->kfifo);
@@ -578,7 +632,6 @@ int ir_raw_event_prepare(struct rc_dev *dev)
int ir_raw_event_register(struct rc_dev *dev)
{
- struct ir_raw_handler *handler;
struct task_struct *thread;
thread = kthread_run(ir_raw_event_thread, dev->raw, "rc%u", dev->minor);
@@ -589,9 +642,6 @@ int ir_raw_event_register(struct rc_dev *dev)
mutex_lock(&ir_raw_handler_lock);
list_add_tail(&dev->raw->list, &ir_raw_client_list);
- list_for_each_entry(handler, &ir_raw_handler_list, list)
- if (handler->raw_register)
- handler->raw_register(dev);
mutex_unlock(&ir_raw_handler_lock);
return 0;
@@ -619,7 +669,8 @@ void ir_raw_event_unregister(struct rc_dev *dev)
mutex_lock(&ir_raw_handler_lock);
list_del(&dev->raw->list);
list_for_each_entry(handler, &ir_raw_handler_list, list)
- if (handler->raw_unregister)
+ if (handler->raw_unregister &&
+ (handler->protocols & dev->enabled_protocols))
handler->raw_unregister(dev);
lirc_bpf_free(dev);
@@ -640,13 +691,8 @@ void ir_raw_event_unregister(struct rc_dev *dev)
int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler)
{
- struct ir_raw_event_ctrl *raw;
-
mutex_lock(&ir_raw_handler_lock);
list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list);
- if (ir_raw_handler->raw_register)
- list_for_each_entry(raw, &ir_raw_client_list, list)
- ir_raw_handler->raw_register(raw->dev);
atomic64_or(ir_raw_handler->protocols, &available_protocols);
mutex_unlock(&ir_raw_handler_lock);
@@ -662,9 +708,10 @@ void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
mutex_lock(&ir_raw_handler_lock);
list_del(&ir_raw_handler->list);
list_for_each_entry(raw, &ir_raw_client_list, list) {
- ir_raw_disable_protocols(raw->dev, protocols);
- if (ir_raw_handler->raw_unregister)
+ if (ir_raw_handler->raw_unregister &&
+ (raw->dev->enabled_protocols & protocols))
ir_raw_handler->raw_unregister(raw->dev);
+ ir_raw_disable_protocols(raw->dev, protocols);
}
atomic64_andnot(protocols, &available_protocols);
mutex_unlock(&ir_raw_handler_lock);
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index b67be33bd62f..2e222d9ee01f 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -26,50 +26,50 @@ static const struct {
unsigned int repeat_period;
unsigned int scancode_bits;
} protocols[] = {
- [RC_PROTO_UNKNOWN] = { .name = "unknown", .repeat_period = 250 },
- [RC_PROTO_OTHER] = { .name = "other", .repeat_period = 250 },
+ [RC_PROTO_UNKNOWN] = { .name = "unknown", .repeat_period = 125 },
+ [RC_PROTO_OTHER] = { .name = "other", .repeat_period = 125 },
[RC_PROTO_RC5] = { .name = "rc-5",
- .scancode_bits = 0x1f7f, .repeat_period = 250 },
+ .scancode_bits = 0x1f7f, .repeat_period = 114 },
[RC_PROTO_RC5X_20] = { .name = "rc-5x-20",
- .scancode_bits = 0x1f7f3f, .repeat_period = 250 },
+ .scancode_bits = 0x1f7f3f, .repeat_period = 114 },
[RC_PROTO_RC5_SZ] = { .name = "rc-5-sz",
- .scancode_bits = 0x2fff, .repeat_period = 250 },
+ .scancode_bits = 0x2fff, .repeat_period = 114 },
[RC_PROTO_JVC] = { .name = "jvc",
- .scancode_bits = 0xffff, .repeat_period = 250 },
+ .scancode_bits = 0xffff, .repeat_period = 125 },
[RC_PROTO_SONY12] = { .name = "sony-12",
- .scancode_bits = 0x1f007f, .repeat_period = 250 },
+ .scancode_bits = 0x1f007f, .repeat_period = 100 },
[RC_PROTO_SONY15] = { .name = "sony-15",
- .scancode_bits = 0xff007f, .repeat_period = 250 },
+ .scancode_bits = 0xff007f, .repeat_period = 100 },
[RC_PROTO_SONY20] = { .name = "sony-20",
- .scancode_bits = 0x1fff7f, .repeat_period = 250 },
+ .scancode_bits = 0x1fff7f, .repeat_period = 100 },
[RC_PROTO_NEC] = { .name = "nec",
- .scancode_bits = 0xffff, .repeat_period = 250 },
+ .scancode_bits = 0xffff, .repeat_period = 110 },
[RC_PROTO_NECX] = { .name = "nec-x",
- .scancode_bits = 0xffffff, .repeat_period = 250 },
+ .scancode_bits = 0xffffff, .repeat_period = 110 },
[RC_PROTO_NEC32] = { .name = "nec-32",
- .scancode_bits = 0xffffffff, .repeat_period = 250 },
+ .scancode_bits = 0xffffffff, .repeat_period = 110 },
[RC_PROTO_SANYO] = { .name = "sanyo",
- .scancode_bits = 0x1fffff, .repeat_period = 250 },
+ .scancode_bits = 0x1fffff, .repeat_period = 125 },
[RC_PROTO_MCIR2_KBD] = { .name = "mcir2-kbd",
- .scancode_bits = 0xffff, .repeat_period = 250 },
+ .scancode_bits = 0xffffff, .repeat_period = 100 },
[RC_PROTO_MCIR2_MSE] = { .name = "mcir2-mse",
- .scancode_bits = 0x1fffff, .repeat_period = 250 },
+ .scancode_bits = 0x1fffff, .repeat_period = 100 },
[RC_PROTO_RC6_0] = { .name = "rc-6-0",
- .scancode_bits = 0xffff, .repeat_period = 250 },
+ .scancode_bits = 0xffff, .repeat_period = 114 },
[RC_PROTO_RC6_6A_20] = { .name = "rc-6-6a-20",
- .scancode_bits = 0xfffff, .repeat_period = 250 },
+ .scancode_bits = 0xfffff, .repeat_period = 114 },
[RC_PROTO_RC6_6A_24] = { .name = "rc-6-6a-24",
- .scancode_bits = 0xffffff, .repeat_period = 250 },
+ .scancode_bits = 0xffffff, .repeat_period = 114 },
[RC_PROTO_RC6_6A_32] = { .name = "rc-6-6a-32",
- .scancode_bits = 0xffffffff, .repeat_period = 250 },
+ .scancode_bits = 0xffffffff, .repeat_period = 114 },
[RC_PROTO_RC6_MCE] = { .name = "rc-6-mce",
- .scancode_bits = 0xffff7fff, .repeat_period = 250 },
+ .scancode_bits = 0xffff7fff, .repeat_period = 114 },
[RC_PROTO_SHARP] = { .name = "sharp",
- .scancode_bits = 0x1fff, .repeat_period = 250 },
- [RC_PROTO_XMP] = { .name = "xmp", .repeat_period = 250 },
- [RC_PROTO_CEC] = { .name = "cec", .repeat_period = 550 },
+ .scancode_bits = 0x1fff, .repeat_period = 125 },
+ [RC_PROTO_XMP] = { .name = "xmp", .repeat_period = 125 },
+ [RC_PROTO_CEC] = { .name = "cec", .repeat_period = 0 },
[RC_PROTO_IMON] = { .name = "imon",
- .scancode_bits = 0x7fffffff, .repeat_period = 250 },
+ .scancode_bits = 0x7fffffff, .repeat_period = 114 },
};
/* Used to keep track of known keymaps */
@@ -690,7 +690,8 @@ static void ir_timer_repeat(struct timer_list *t)
void rc_repeat(struct rc_dev *dev)
{
unsigned long flags;
- unsigned int timeout = protocols[dev->last_protocol].repeat_period;
+ unsigned int timeout = nsecs_to_jiffies(dev->timeout) +
+ msecs_to_jiffies(protocols[dev->last_protocol].repeat_period);
struct lirc_scancode sc = {
.scancode = dev->last_scancode, .rc_proto = dev->last_protocol,
.keycode = dev->keypressed ? dev->last_keycode : KEY_RESERVED,
@@ -706,7 +707,7 @@ void rc_repeat(struct rc_dev *dev)
input_sync(dev->input_dev);
if (dev->keypressed) {
- dev->keyup_jiffies = jiffies + msecs_to_jiffies(timeout);
+ dev->keyup_jiffies = jiffies + timeout;
mod_timer(&dev->timer_keyup, dev->keyup_jiffies);
}
@@ -801,7 +802,7 @@ void rc_keydown(struct rc_dev *dev, enum rc_proto protocol, u32 scancode,
ir_do_keydown(dev, protocol, scancode, keycode, toggle);
if (dev->keypressed) {
- dev->keyup_jiffies = jiffies +
+ dev->keyup_jiffies = jiffies + nsecs_to_jiffies(dev->timeout) +
msecs_to_jiffies(protocols[protocol].repeat_period);
mod_timer(&dev->timer_keyup, dev->keyup_jiffies);
}
@@ -1241,6 +1242,9 @@ static ssize_t store_protocols(struct device *device,
if (rc < 0)
goto out;
+ if (dev->driver_type == RC_DRIVER_IR_RAW)
+ ir_raw_load_modules(&new_protocols);
+
rc = dev->change_protocol(dev, &new_protocols);
if (rc < 0) {
dev_dbg(&dev->dev, "Error setting protocols to 0x%llx\n",
@@ -1248,9 +1252,6 @@ static ssize_t store_protocols(struct device *device,
goto out;
}
- if (dev->driver_type == RC_DRIVER_IR_RAW)
- ir_raw_load_modules(&new_protocols);
-
if (new_protocols != old_protocols) {
*current_protocols = new_protocols;
dev_dbg(&dev->dev, "Protocols changed to 0x%llx\n",
@@ -1647,6 +1648,7 @@ struct rc_dev *rc_allocate_device(enum rc_driver_type type)
dev->input_dev->setkeycode = ir_setkeycode;
input_set_drvdata(dev->input_dev, dev);
+ dev->timeout = IR_DEFAULT_TIMEOUT;
timer_setup(&dev->timer_keyup, ir_timer_keyup, 0);
timer_setup(&dev->timer_repeat, ir_timer_repeat, 0);
@@ -1735,6 +1737,9 @@ static int rc_prepare_rx_device(struct rc_dev *dev)
if (dev->driver_type == RC_DRIVER_SCANCODE && !dev->change_protocol)
dev->enabled_protocols = dev->allowed_protocols;
+ if (dev->driver_type == RC_DRIVER_IR_RAW)
+ ir_raw_load_modules(&rc_proto);
+
if (dev->change_protocol) {
rc = dev->change_protocol(dev, &rc_proto);
if (rc < 0)
@@ -1742,9 +1747,6 @@ static int rc_prepare_rx_device(struct rc_dev *dev)
dev->enabled_protocols = rc_proto;
}
- if (dev->driver_type == RC_DRIVER_IR_RAW)
- ir_raw_load_modules(&rc_proto);
-
set_bit(EV_KEY, dev->input_dev->evbit);
set_bit(EV_REP, dev->input_dev->evbit);
set_bit(EV_MSC, dev->input_dev->evbit);
@@ -1860,6 +1862,8 @@ int rc_register_device(struct rc_dev *dev)
dev->device_name ?: "Unspecified device", path ?: "N/A");
kfree(path);
+ dev->registered = true;
+
if (dev->driver_type != RC_DRIVER_IR_RAW_TX) {
rc = rc_setup_rx_device(dev);
if (rc)
@@ -1879,8 +1883,6 @@ int rc_register_device(struct rc_dev *dev)
goto out_lirc;
}
- dev->registered = true;
-
dev_dbg(&dev->dev, "Registered rc%u (driver: %s)\n", dev->minor,
dev->driver_name ? dev->driver_name : "unknown");
diff --git a/drivers/media/rc/st_rc.c b/drivers/media/rc/st_rc.c
index d2efd7b2c3bc..c855b177103c 100644
--- a/drivers/media/rc/st_rc.c
+++ b/drivers/media/rc/st_rc.c
@@ -96,19 +96,24 @@ static void st_rc_send_lirc_timeout(struct rc_dev *rdev)
static irqreturn_t st_rc_rx_interrupt(int irq, void *data)
{
+ unsigned long timeout;
unsigned int symbol, mark = 0;
struct st_rc_device *dev = data;
int last_symbol = 0;
- u32 status;
+ u32 status, int_status;
DEFINE_IR_RAW_EVENT(ev);
if (dev->irq_wake)
pm_wakeup_event(dev->dev, 0);
- status = readl(dev->rx_base + IRB_RX_STATUS);
+ /* FIXME: is 10ms good enough ? */
+ timeout = jiffies + msecs_to_jiffies(10);
+ do {
+ status = readl(dev->rx_base + IRB_RX_STATUS);
+ if (!(status & (IRB_FIFO_NOT_EMPTY | IRB_OVERFLOW)))
+ break;
- while (status & (IRB_FIFO_NOT_EMPTY | IRB_OVERFLOW)) {
- u32 int_status = readl(dev->rx_base + IRB_RX_INT_STATUS);
+ int_status = readl(dev->rx_base + IRB_RX_INT_STATUS);
if (unlikely(int_status & IRB_RX_OVERRUN_INT)) {
/* discard the entire collection in case of errors! */
ir_raw_event_reset(dev->rdev);
@@ -148,8 +153,7 @@ static irqreturn_t st_rc_rx_interrupt(int irq, void *data)
}
last_symbol = 0;
- status = readl(dev->rx_base + IRB_RX_STATUS);
- }
+ } while (time_is_after_jiffies(timeout));
writel(IRB_RX_INTS, dev->rx_base + IRB_RX_INT_CLEAR);
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
index 0adf0991f5ab..851acba9b436 100644
--- a/drivers/media/rc/winbond-cir.c
+++ b/drivers/media/rc/winbond-cir.c
@@ -989,8 +989,7 @@ wbcir_init_hw(struct wbcir_data *data)
/* Clear RX state */
data->rxstate = WBCIR_RXSTATE_INACTIVE;
- ir_raw_event_reset(data->dev);
- ir_raw_event_set_idle(data->dev, true);
+ wbcir_idle_rx(data->dev, true);
/* Clear TX state */
if (data->txstate == WBCIR_TXSTATE_ACTIVE) {
@@ -1009,6 +1008,7 @@ wbcir_resume(struct pnp_dev *device)
struct wbcir_data *data = pnp_get_drvdata(device);
wbcir_init_hw(data);
+ ir_raw_event_reset(data->dev);
enable_irq(data->irq);
led_classdev_resume(&data->led);