rc: gpio-ir-recv: allow flush space on idle
Subsystems (3)
PATCH 1/1 rc: gpio-ir-recv: allow flush space on idle
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 <[email protected]>
--- .../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(-)
Documentation/devicetree/bindings/media/gpio-ir-receiver.txt +1 -0
@@ -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:
drivers/media/rc/gpio-ir-recv.c +32 -7
@@ -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;
include/media/gpio-ir-recv.h +1 -0
@@ -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; };
Signature · 1 line
2.5.1