root/drivers/media/rc/img-ir/img-ir-raw.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. img_ir_refresh_raw
  2. img_ir_isr_raw
  3. img_ir_echo_timer
  4. img_ir_setup_raw
  5. img_ir_probe_raw
  6. img_ir_remove_raw

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * ImgTec IR Raw Decoder found in PowerDown Controller.
   4  *
   5  * Copyright 2010-2014 Imagination Technologies Ltd.
   6  *
   7  * This ties into the input subsystem using the RC-core in raw mode. Raw IR
   8  * signal edges are reported and decoded by generic software decoders.
   9  */
  10 
  11 #include <linux/spinlock.h>
  12 #include <media/rc-core.h>
  13 #include "img-ir.h"
  14 
  15 #define ECHO_TIMEOUT_MS 150     /* ms between echos */
  16 
  17 /* must be called with priv->lock held */
  18 static void img_ir_refresh_raw(struct img_ir_priv *priv, u32 irq_status)
  19 {
  20         struct img_ir_priv_raw *raw = &priv->raw;
  21         struct rc_dev *rc_dev = priv->raw.rdev;
  22         int multiple;
  23         u32 ir_status;
  24 
  25         /* find whether both rise and fall was detected */
  26         multiple = ((irq_status & IMG_IR_IRQ_EDGE) == IMG_IR_IRQ_EDGE);
  27         /*
  28          * If so, we need to see if the level has actually changed.
  29          * If it's just noise that we didn't have time to process,
  30          * there's no point reporting it.
  31          */
  32         ir_status = img_ir_read(priv, IMG_IR_STATUS) & IMG_IR_IRRXD;
  33         if (multiple && ir_status == raw->last_status)
  34                 return;
  35         raw->last_status = ir_status;
  36 
  37         /* report the edge to the IR raw decoders */
  38         if (ir_status) /* low */
  39                 ir_raw_event_store_edge(rc_dev, false);
  40         else /* high */
  41                 ir_raw_event_store_edge(rc_dev, true);
  42         ir_raw_event_handle(rc_dev);
  43 }
  44 
  45 /* called with priv->lock held */
  46 void img_ir_isr_raw(struct img_ir_priv *priv, u32 irq_status)
  47 {
  48         struct img_ir_priv_raw *raw = &priv->raw;
  49 
  50         /* check not removing */
  51         if (!raw->rdev)
  52                 return;
  53 
  54         img_ir_refresh_raw(priv, irq_status);
  55 
  56         /* start / push back the echo timer */
  57         mod_timer(&raw->timer, jiffies + msecs_to_jiffies(ECHO_TIMEOUT_MS));
  58 }
  59 
  60 /*
  61  * Echo timer callback function.
  62  * The raw decoders expect to get a final sample even if there are no edges, in
  63  * order to be assured of the final space. If there are no edges for a certain
  64  * time we use this timer to emit a final sample to satisfy them.
  65  */
  66 static void img_ir_echo_timer(struct timer_list *t)
  67 {
  68         struct img_ir_priv *priv = from_timer(priv, t, raw.timer);
  69 
  70         spin_lock_irq(&priv->lock);
  71 
  72         /* check not removing */
  73         if (priv->raw.rdev)
  74                 /*
  75                  * It's safe to pass irq_status=0 since it's only used to check
  76                  * for double edges.
  77                  */
  78                 img_ir_refresh_raw(priv, 0);
  79 
  80         spin_unlock_irq(&priv->lock);
  81 }
  82 
  83 void img_ir_setup_raw(struct img_ir_priv *priv)
  84 {
  85         u32 irq_en;
  86 
  87         if (!priv->raw.rdev)
  88                 return;
  89 
  90         /* clear and enable edge interrupts */
  91         spin_lock_irq(&priv->lock);
  92         irq_en = img_ir_read(priv, IMG_IR_IRQ_ENABLE);
  93         irq_en |= IMG_IR_IRQ_EDGE;
  94         img_ir_write(priv, IMG_IR_IRQ_CLEAR, IMG_IR_IRQ_EDGE);
  95         img_ir_write(priv, IMG_IR_IRQ_ENABLE, irq_en);
  96         spin_unlock_irq(&priv->lock);
  97 }
  98 
  99 int img_ir_probe_raw(struct img_ir_priv *priv)
 100 {
 101         struct img_ir_priv_raw *raw = &priv->raw;
 102         struct rc_dev *rdev;
 103         int error;
 104 
 105         /* Set up the echo timer */
 106         timer_setup(&raw->timer, img_ir_echo_timer, 0);
 107 
 108         /* Allocate raw decoder */
 109         raw->rdev = rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
 110         if (!rdev) {
 111                 dev_err(priv->dev, "cannot allocate raw input device\n");
 112                 return -ENOMEM;
 113         }
 114         rdev->priv = priv;
 115         rdev->map_name = RC_MAP_EMPTY;
 116         rdev->device_name = "IMG Infrared Decoder Raw";
 117 
 118         /* Register raw decoder */
 119         error = rc_register_device(rdev);
 120         if (error) {
 121                 dev_err(priv->dev, "failed to register raw IR input device\n");
 122                 rc_free_device(rdev);
 123                 raw->rdev = NULL;
 124                 return error;
 125         }
 126 
 127         return 0;
 128 }
 129 
 130 void img_ir_remove_raw(struct img_ir_priv *priv)
 131 {
 132         struct img_ir_priv_raw *raw = &priv->raw;
 133         struct rc_dev *rdev = raw->rdev;
 134         u32 irq_en;
 135 
 136         if (!rdev)
 137                 return;
 138 
 139         /* switch off and disable raw (edge) interrupts */
 140         spin_lock_irq(&priv->lock);
 141         raw->rdev = NULL;
 142         irq_en = img_ir_read(priv, IMG_IR_IRQ_ENABLE);
 143         irq_en &= ~IMG_IR_IRQ_EDGE;
 144         img_ir_write(priv, IMG_IR_IRQ_ENABLE, irq_en);
 145         img_ir_write(priv, IMG_IR_IRQ_CLEAR, IMG_IR_IRQ_EDGE);
 146         spin_unlock_irq(&priv->lock);
 147 
 148         rc_unregister_device(rdev);
 149 
 150         del_timer_sync(&raw->timer);
 151 }

/* [<][>][^][v][top][bottom][index][help] */