aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/rc/rc-ir-raw.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-03 17:16:59 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-03 17:16:59 -0700
commitef1c4a6fa91bbbe9b09f770d28eba31a9edf770c (patch)
tree52f5d175031c553160d14890e876ffc5432d2467 /drivers/media/rc/rc-ir-raw.c
parent147a89bc71e7db40f011454a40add7ff2d10f8d8 (diff)
parentf8a695c4b43d02c89b8bba9ba6058fd5db1bc71d (diff)
downloadlinux-ef1c4a6fa91bbbe9b09f770d28eba31a9edf770c.tar.gz
linux-ef1c4a6fa91bbbe9b09f770d28eba31a9edf770c.tar.bz2
linux-ef1c4a6fa91bbbe9b09f770d28eba31a9edf770c.zip
Merge tag 'media/v4.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - new CEC pin injection code for testing purposes - DVB frontend cxd2099 promoted from staging - new platform driver for Sony cxd2880 DVB devices - new sensor drivers: mt9t112, ov2685, ov5695, ov772x, tda1997x, tw9910.c - removal of unused cx18 and ivtv alsa mixers - the reneseas-ceu driver doesn't depend on soc_camera anymore and moved from staging - removed the mantis_vp3028 driver, unused since 2009 - s5p-mfc: add support for version 10 of the MSP - added a decoder for imon protocol - atomisp: lots of cleanups - imx074 and mt9t031: don't depend on soc_camera anymore, being promoted from staging - added helper functions to better support DVB I2C binding - lots of driver improvements and cleanups * tag 'media/v4.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (438 commits) media: v4l2-ioctl: rename a temp var that stores _IOC_SIZE(cmd) media: fimc-capture: get rid of two warnings media: dvb-usb-v2: fix a missing dependency of I2C_MUX media: uvc: to the right check at uvc_ioctl_enum_framesizes() media: cec-core: fix a bug at cec_error_inj_write() media: tda9840: cleanup a warning media: tm6000: avoid casting just to print pointer address media: em28xx-input: improve error handling code media: zr364xx: avoid casting just to print pointer address media: vivid-radio-rx: add a cast to avoid a warning media: saa7134-alsa: don't use casts to print a buffer address media: solo6x10: get rid of an address space warning media: zoran: don't cast pointers to print them media: ir-kbd-i2c: change the if logic to avoid a warning media: ir-kbd-i2c: improve error handling code media: saa7134-input: improve error handling media: s2255drv: fix a casting warning media: ivtvfb: Cleanup some warnings media: videobuf-dma-sg: Fix a weird cast soc_camera: fix a weird cast on printk ...
Diffstat (limited to 'drivers/media/rc/rc-ir-raw.c')
-rw-r--r--drivers/media/rc/rc-ir-raw.c60
1 files changed, 51 insertions, 9 deletions
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 18504870b9f0..374f83105a23 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -65,8 +65,8 @@ int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev)
if (!dev->raw)
return -EINVAL;
- IR_dprintk(2, "sample: (%05dus %s)\n",
- TO_US(ev->duration), TO_STR(ev->pulse));
+ dev_dbg(&dev->dev, "sample: (%05dus %s)\n",
+ TO_US(ev->duration), TO_STR(ev->pulse));
if (!kfifo_put(&dev->raw->kfifo, *ev)) {
dev_err(&dev->dev, "IR event FIFO is full!\n");
@@ -92,7 +92,6 @@ int ir_raw_event_store_edge(struct rc_dev *dev, bool pulse)
{
ktime_t now;
DEFINE_IR_RAW_EVENT(ev);
- int rc = 0;
if (!dev->raw)
return -EINVAL;
@@ -101,7 +100,33 @@ int ir_raw_event_store_edge(struct rc_dev *dev, bool pulse)
ev.duration = ktime_to_ns(ktime_sub(now, dev->raw->last_event));
ev.pulse = !pulse;
- rc = ir_raw_event_store(dev, &ev);
+ return ir_raw_event_store_with_timeout(dev, &ev);
+}
+EXPORT_SYMBOL_GPL(ir_raw_event_store_edge);
+
+/*
+ * ir_raw_event_store_with_timeout() - pass a pulse/space duration to the raw
+ * ir decoders, schedule decoding and
+ * timeout
+ * @dev: the struct rc_dev device descriptor
+ * @ev: the struct ir_raw_event descriptor of the pulse/space
+ *
+ * This routine (which may be called from an interrupt context) stores a
+ * pulse/space duration for the raw ir decoding state machines, schedules
+ * decoding and generates a timeout.
+ */
+int ir_raw_event_store_with_timeout(struct rc_dev *dev, struct ir_raw_event *ev)
+{
+ ktime_t now;
+ int rc = 0;
+
+ if (!dev->raw)
+ return -EINVAL;
+
+ now = ktime_get();
+
+ spin_lock(&dev->raw->edge_spinlock);
+ rc = ir_raw_event_store(dev, ev);
dev->raw->last_event = now;
@@ -112,10 +137,11 @@ int ir_raw_event_store_edge(struct rc_dev *dev, bool pulse)
mod_timer(&dev->raw->edge_handle,
jiffies + msecs_to_jiffies(15));
}
+ spin_unlock(&dev->raw->edge_spinlock);
return rc;
}
-EXPORT_SYMBOL_GPL(ir_raw_event_store_edge);
+EXPORT_SYMBOL_GPL(ir_raw_event_store_with_timeout);
/**
* ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing
@@ -168,7 +194,7 @@ void ir_raw_event_set_idle(struct rc_dev *dev, bool idle)
if (!dev->raw)
return;
- IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave");
+ dev_dbg(&dev->dev, "%s idle mode\n", idle ? "enter" : "leave");
if (idle) {
dev->raw->this_ev.timeout = true;
@@ -462,12 +488,26 @@ int ir_raw_encode_scancode(enum rc_proto protocol, u32 scancode,
}
EXPORT_SYMBOL(ir_raw_encode_scancode);
-static void edge_handle(struct timer_list *t)
+/**
+ * ir_raw_edge_handle() - Handle ir_raw_event_store_edge() processing
+ *
+ * @t: timer_list
+ *
+ * This callback is armed by ir_raw_event_store_edge(). It does two things:
+ * first of all, rather than calling ir_raw_event_handle() for each
+ * edge and waking up the rc thread, 15 ms after the first edge
+ * ir_raw_event_handle() is called. Secondly, generate a timeout event
+ * no more IR is received after the rc_dev timeout.
+ */
+static void ir_raw_edge_handle(struct timer_list *t)
{
struct ir_raw_event_ctrl *raw = from_timer(raw, t, edge_handle);
struct rc_dev *dev = raw->dev;
- ktime_t interval = ktime_sub(ktime_get(), dev->raw->last_event);
+ unsigned long flags;
+ ktime_t interval;
+ spin_lock_irqsave(&dev->raw->edge_spinlock, flags);
+ interval = ktime_sub(ktime_get(), dev->raw->last_event);
if (ktime_to_ns(interval) >= dev->timeout) {
DEFINE_IR_RAW_EVENT(ev);
@@ -480,6 +520,7 @@ static void edge_handle(struct timer_list *t)
jiffies + nsecs_to_jiffies(dev->timeout -
ktime_to_ns(interval)));
}
+ spin_unlock_irqrestore(&dev->raw->edge_spinlock, flags);
ir_raw_event_handle(dev);
}
@@ -528,7 +569,8 @@ int ir_raw_event_prepare(struct rc_dev *dev)
dev->raw->dev = dev;
dev->change_protocol = change_protocol;
- timer_setup(&dev->raw->edge_handle, edge_handle, 0);
+ spin_lock_init(&dev->raw->edge_spinlock);
+ timer_setup(&dev->raw->edge_handle, ir_raw_edge_handle, 0);
INIT_KFIFO(dev->raw->kfifo);
return 0;