diff options
author | Yunhong Jiang <yunhong.jiang@intel.com> | 2015-08-04 12:17:53 -0700 |
---|---|---|
committer | Yunhong Jiang <yunhong.jiang@intel.com> | 2015-08-04 15:44:42 -0700 |
commit | 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (patch) | |
tree | 1c9cafbcd35f783a87880a10f85d1a060db1a563 /kernel/drivers/media/rc/img-ir/img-ir-raw.c | |
parent | 98260f3884f4a202f9ca5eabed40b1354c489b29 (diff) |
Add the rt linux 4.1.3-rt3 as base
Import the rt linux 4.1.3-rt3 as OPNFV kvm base.
It's from git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git linux-4.1.y-rt and
the base is:
commit 0917f823c59692d751951bf5ea699a2d1e2f26a2
Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Sat Jul 25 12:13:34 2015 +0200
Prepare v4.1.3-rt3
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
We lose all the git history this way and it's not good. We
should apply another opnfv project repo in future.
Change-Id: I87543d81c9df70d99c5001fbdf646b202c19f423
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
Diffstat (limited to 'kernel/drivers/media/rc/img-ir/img-ir-raw.c')
-rw-r--r-- | kernel/drivers/media/rc/img-ir/img-ir-raw.c | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/kernel/drivers/media/rc/img-ir/img-ir-raw.c b/kernel/drivers/media/rc/img-ir/img-ir-raw.c new file mode 100644 index 000000000..33f37ed87 --- /dev/null +++ b/kernel/drivers/media/rc/img-ir/img-ir-raw.c @@ -0,0 +1,156 @@ +/* + * ImgTec IR Raw Decoder found in PowerDown Controller. + * + * Copyright 2010-2014 Imagination Technologies Ltd. + * + * 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; either version 2 of the License, or (at your + * option) any later version. + * + * This ties into the input subsystem using the RC-core in raw mode. Raw IR + * signal edges are reported and decoded by generic software decoders. + */ + +#include <linux/spinlock.h> +#include <media/rc-core.h> +#include "img-ir.h" + +#define ECHO_TIMEOUT_MS 150 /* ms between echos */ + +/* must be called with priv->lock held */ +static void img_ir_refresh_raw(struct img_ir_priv *priv, u32 irq_status) +{ + struct img_ir_priv_raw *raw = &priv->raw; + struct rc_dev *rc_dev = priv->raw.rdev; + int multiple; + u32 ir_status; + + /* find whether both rise and fall was detected */ + multiple = ((irq_status & IMG_IR_IRQ_EDGE) == IMG_IR_IRQ_EDGE); + /* + * If so, we need to see if the level has actually changed. + * If it's just noise that we didn't have time to process, + * there's no point reporting it. + */ + ir_status = img_ir_read(priv, IMG_IR_STATUS) & IMG_IR_IRRXD; + if (multiple && ir_status == raw->last_status) + return; + raw->last_status = ir_status; + + /* report the edge to the IR raw decoders */ + if (ir_status) /* low */ + ir_raw_event_store_edge(rc_dev, IR_SPACE); + else /* high */ + ir_raw_event_store_edge(rc_dev, IR_PULSE); + ir_raw_event_handle(rc_dev); +} + +/* called with priv->lock held */ +void img_ir_isr_raw(struct img_ir_priv *priv, u32 irq_status) +{ + struct img_ir_priv_raw *raw = &priv->raw; + + /* check not removing */ + if (!raw->rdev) + return; + + img_ir_refresh_raw(priv, irq_status); + + /* start / push back the echo timer */ + mod_timer(&raw->timer, jiffies + msecs_to_jiffies(ECHO_TIMEOUT_MS)); +} + +/* + * Echo timer callback function. + * The raw decoders expect to get a final sample even if there are no edges, in + * order to be assured of the final space. If there are no edges for a certain + * time we use this timer to emit a final sample to satisfy them. + */ +static void img_ir_echo_timer(unsigned long arg) +{ + struct img_ir_priv *priv = (struct img_ir_priv *)arg; + + spin_lock_irq(&priv->lock); + + /* check not removing */ + if (priv->raw.rdev) + /* + * It's safe to pass irq_status=0 since it's only used to check + * for double edges. + */ + img_ir_refresh_raw(priv, 0); + + spin_unlock_irq(&priv->lock); +} + +void img_ir_setup_raw(struct img_ir_priv *priv) +{ + u32 irq_en; + + if (!priv->raw.rdev) + return; + + /* clear and enable edge interrupts */ + spin_lock_irq(&priv->lock); + irq_en = img_ir_read(priv, IMG_IR_IRQ_ENABLE); + irq_en |= IMG_IR_IRQ_EDGE; + img_ir_write(priv, IMG_IR_IRQ_CLEAR, IMG_IR_IRQ_EDGE); + img_ir_write(priv, IMG_IR_IRQ_ENABLE, irq_en); + spin_unlock_irq(&priv->lock); +} + +int img_ir_probe_raw(struct img_ir_priv *priv) +{ + struct img_ir_priv_raw *raw = &priv->raw; + struct rc_dev *rdev; + int error; + + /* Set up the echo timer */ + setup_timer(&raw->timer, img_ir_echo_timer, (unsigned long)priv); + + /* Allocate raw decoder */ + raw->rdev = rdev = rc_allocate_device(); + if (!rdev) { + dev_err(priv->dev, "cannot allocate raw input device\n"); + return -ENOMEM; + } + rdev->priv = priv; + rdev->map_name = RC_MAP_EMPTY; + rdev->input_name = "IMG Infrared Decoder Raw"; + rdev->driver_type = RC_DRIVER_IR_RAW; + + /* Register raw decoder */ + error = rc_register_device(rdev); + if (error) { + dev_err(priv->dev, "failed to register raw IR input device\n"); + rc_free_device(rdev); + raw->rdev = NULL; + return error; + } + + return 0; +} + +void img_ir_remove_raw(struct img_ir_priv *priv) +{ + struct img_ir_priv_raw *raw = &priv->raw; + struct rc_dev *rdev = raw->rdev; + u32 irq_en; + + if (!rdev) + return; + + /* switch off and disable raw (edge) interrupts */ + spin_lock_irq(&priv->lock); + raw->rdev = NULL; + irq_en = img_ir_read(priv, IMG_IR_IRQ_ENABLE); + irq_en &= ~IMG_IR_IRQ_EDGE; + img_ir_write(priv, IMG_IR_IRQ_ENABLE, irq_en); + img_ir_write(priv, IMG_IR_IRQ_CLEAR, IMG_IR_IRQ_EDGE); + spin_unlock_irq(&priv->lock); + + rc_unregister_device(rdev); + + del_timer_sync(&raw->timer); +} |