Many decoders require a trailing space (period without IR illumination) to be delivered before completing a decode. Since the gpio-ir-recv driver only delivers events on gpio transitions, a single IR symbol (caused by a quick touch on an IR remote) will not be properly decoded without the use of a timer to flush the tail end state of the IR receiver. This patch adds an optional device tree node "flush-ms" which, if present, will use a jiffie-based timer to complete the last pulse stream and allow decode. The "flush-ms" value should be chosen with a value that will convert well to jiffies (multiples of 10 are good). Signed-off-by: Eric Nelson <eric@xxxxxxxxxx> --- Re-sending with expanded CC list. .../devicetree/bindings/media/gpio-ir-receiver.txt | 1 + drivers/media/rc/gpio-ir-recv.c | 39 ++++++++++++++++++---- include/media/gpio-ir-recv.h | 1 + 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/media/gpio-ir-receiver.txt b/Documentation/devicetree/bindings/media/gpio-ir-receiver.txt index 56e726e..13ff92d 100644 --- a/Documentation/devicetree/bindings/media/gpio-ir-receiver.txt +++ b/Documentation/devicetree/bindings/media/gpio-ir-receiver.txt @@ -6,6 +6,7 @@ Required properties: Optional properties: - linux,rc-map-name: Linux specific remote control map name. + - flush-ms: time for final flush of 'space' pulse (period with no IR) Example node: diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c index 7dbc9ca..e3c353e 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c @@ -29,7 +29,9 @@ struct gpio_rc_dev { struct rc_dev *rcdev; int gpio_nr; + int flush_jiffies; bool active_low; + struct timer_list flush_timer; }; #ifdef CONFIG_OF @@ -42,6 +44,7 @@ static int gpio_ir_recv_get_devtree_pdata(struct device *dev, struct device_node *np = dev->of_node; enum of_gpio_flags flags; int gpio; + u32 flush_ms = 0; gpio = of_get_gpio_flags(np, 0, &flags); if (gpio < 0) { @@ -50,6 +53,9 @@ static int gpio_ir_recv_get_devtree_pdata(struct device *dev, return gpio; } + of_property_read_u32(np, "flush-ms", &flush_ms); + pdata->flush_jiffies = msecs_to_jiffies(flush_ms); + pdata->gpio_nr = gpio; pdata->active_low = (flags & OF_GPIO_ACTIVE_LOW); /* probe() takes care of map_name == NULL or allowed_protos == 0 */ @@ -71,9 +77,8 @@ MODULE_DEVICE_TABLE(of, gpio_ir_recv_of_match); #endif -static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id) +static void flush_gp(struct gpio_rc_dev *gpio_dev) { - struct gpio_rc_dev *gpio_dev = dev_id; int gval; int rc = 0; enum raw_event_type type = IR_SPACE; @@ -81,7 +86,7 @@ static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id) gval = gpio_get_value(gpio_dev->gpio_nr); if (gval < 0) - goto err_get_value; + return; if (gpio_dev->active_low) gval = !gval; @@ -90,15 +95,30 @@ static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id) type = IR_PULSE; rc = ir_raw_event_store_edge(gpio_dev->rcdev, type); - if (rc < 0) - goto err_get_value; + if (rc >= 0) + ir_raw_event_handle(gpio_dev->rcdev); +} - ir_raw_event_handle(gpio_dev->rcdev); +static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id) +{ + struct gpio_rc_dev *gpio_dev = dev_id; + + flush_gp(gpio_dev); + + if (gpio_dev->flush_jiffies) + mod_timer(&gpio_dev->flush_timer, + jiffies + gpio_dev->flush_jiffies); -err_get_value: return IRQ_HANDLED; } +static void flush_timer(unsigned long arg) +{ + struct gpio_rc_dev *gpio_dev = (struct gpio_rc_dev *)arg; + + flush_gp(gpio_dev); +} + static int gpio_ir_recv_probe(struct platform_device *pdev) { struct gpio_rc_dev *gpio_dev; @@ -152,8 +172,13 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) gpio_dev->rcdev = rcdev; gpio_dev->gpio_nr = pdata->gpio_nr; + gpio_dev->flush_jiffies = pdata->flush_jiffies; gpio_dev->active_low = pdata->active_low; + init_timer(&gpio_dev->flush_timer); + gpio_dev->flush_timer.function = flush_timer; + gpio_dev->flush_timer.data = (unsigned long)gpio_dev; + rc = gpio_request(pdata->gpio_nr, "gpio-ir-recv"); if (rc < 0) goto err_gpio_request; diff --git a/include/media/gpio-ir-recv.h b/include/media/gpio-ir-recv.h index 0142736..88fae78 100644 --- a/include/media/gpio-ir-recv.h +++ b/include/media/gpio-ir-recv.h @@ -17,6 +17,7 @@ struct gpio_ir_recv_platform_data { int gpio_nr; bool active_low; u64 allowed_protos; + int flush_jiffies; const char *map_name; }; -- 2.5.1 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html