Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * ImgTec IR Raw Decoder found in PowerDown Controller.
0004  *
0005  * Copyright 2010-2014 Imagination Technologies Ltd.
0006  *
0007  * This ties into the input subsystem using the RC-core in raw mode. Raw IR
0008  * signal edges are reported and decoded by generic software decoders.
0009  */
0010 
0011 #include <linux/spinlock.h>
0012 #include <media/rc-core.h>
0013 #include "img-ir.h"
0014 
0015 #define ECHO_TIMEOUT_MS 150 /* ms between echos */
0016 
0017 /* must be called with priv->lock held */
0018 static void img_ir_refresh_raw(struct img_ir_priv *priv, u32 irq_status)
0019 {
0020     struct img_ir_priv_raw *raw = &priv->raw;
0021     struct rc_dev *rc_dev = priv->raw.rdev;
0022     int multiple;
0023     u32 ir_status;
0024 
0025     /* find whether both rise and fall was detected */
0026     multiple = ((irq_status & IMG_IR_IRQ_EDGE) == IMG_IR_IRQ_EDGE);
0027     /*
0028      * If so, we need to see if the level has actually changed.
0029      * If it's just noise that we didn't have time to process,
0030      * there's no point reporting it.
0031      */
0032     ir_status = img_ir_read(priv, IMG_IR_STATUS) & IMG_IR_IRRXD;
0033     if (multiple && ir_status == raw->last_status)
0034         return;
0035     raw->last_status = ir_status;
0036 
0037     /* report the edge to the IR raw decoders */
0038     if (ir_status) /* low */
0039         ir_raw_event_store_edge(rc_dev, false);
0040     else /* high */
0041         ir_raw_event_store_edge(rc_dev, true);
0042     ir_raw_event_handle(rc_dev);
0043 }
0044 
0045 /* called with priv->lock held */
0046 void img_ir_isr_raw(struct img_ir_priv *priv, u32 irq_status)
0047 {
0048     struct img_ir_priv_raw *raw = &priv->raw;
0049 
0050     /* check not removing */
0051     if (!raw->rdev)
0052         return;
0053 
0054     img_ir_refresh_raw(priv, irq_status);
0055 
0056     /* start / push back the echo timer */
0057     mod_timer(&raw->timer, jiffies + msecs_to_jiffies(ECHO_TIMEOUT_MS));
0058 }
0059 
0060 /*
0061  * Echo timer callback function.
0062  * The raw decoders expect to get a final sample even if there are no edges, in
0063  * order to be assured of the final space. If there are no edges for a certain
0064  * time we use this timer to emit a final sample to satisfy them.
0065  */
0066 static void img_ir_echo_timer(struct timer_list *t)
0067 {
0068     struct img_ir_priv *priv = from_timer(priv, t, raw.timer);
0069 
0070     spin_lock_irq(&priv->lock);
0071 
0072     /* check not removing */
0073     if (priv->raw.rdev)
0074         /*
0075          * It's safe to pass irq_status=0 since it's only used to check
0076          * for double edges.
0077          */
0078         img_ir_refresh_raw(priv, 0);
0079 
0080     spin_unlock_irq(&priv->lock);
0081 }
0082 
0083 void img_ir_setup_raw(struct img_ir_priv *priv)
0084 {
0085     u32 irq_en;
0086 
0087     if (!priv->raw.rdev)
0088         return;
0089 
0090     /* clear and enable edge interrupts */
0091     spin_lock_irq(&priv->lock);
0092     irq_en = img_ir_read(priv, IMG_IR_IRQ_ENABLE);
0093     irq_en |= IMG_IR_IRQ_EDGE;
0094     img_ir_write(priv, IMG_IR_IRQ_CLEAR, IMG_IR_IRQ_EDGE);
0095     img_ir_write(priv, IMG_IR_IRQ_ENABLE, irq_en);
0096     spin_unlock_irq(&priv->lock);
0097 }
0098 
0099 int img_ir_probe_raw(struct img_ir_priv *priv)
0100 {
0101     struct img_ir_priv_raw *raw = &priv->raw;
0102     struct rc_dev *rdev;
0103     int error;
0104 
0105     /* Set up the echo timer */
0106     timer_setup(&raw->timer, img_ir_echo_timer, 0);
0107 
0108     /* Allocate raw decoder */
0109     raw->rdev = rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
0110     if (!rdev) {
0111         dev_err(priv->dev, "cannot allocate raw input device\n");
0112         return -ENOMEM;
0113     }
0114     rdev->priv = priv;
0115     rdev->map_name = RC_MAP_EMPTY;
0116     rdev->device_name = "IMG Infrared Decoder Raw";
0117 
0118     /* Register raw decoder */
0119     error = rc_register_device(rdev);
0120     if (error) {
0121         dev_err(priv->dev, "failed to register raw IR input device\n");
0122         rc_free_device(rdev);
0123         raw->rdev = NULL;
0124         return error;
0125     }
0126 
0127     return 0;
0128 }
0129 
0130 void img_ir_remove_raw(struct img_ir_priv *priv)
0131 {
0132     struct img_ir_priv_raw *raw = &priv->raw;
0133     struct rc_dev *rdev = raw->rdev;
0134     u32 irq_en;
0135 
0136     if (!rdev)
0137         return;
0138 
0139     /* switch off and disable raw (edge) interrupts */
0140     spin_lock_irq(&priv->lock);
0141     raw->rdev = NULL;
0142     irq_en = img_ir_read(priv, IMG_IR_IRQ_ENABLE);
0143     irq_en &= ~IMG_IR_IRQ_EDGE;
0144     img_ir_write(priv, IMG_IR_IRQ_ENABLE, irq_en);
0145     img_ir_write(priv, IMG_IR_IRQ_CLEAR, IMG_IR_IRQ_EDGE);
0146     spin_unlock_irq(&priv->lock);
0147 
0148     rc_unregister_device(rdev);
0149 
0150     del_timer_sync(&raw->timer);
0151 }