Merge branch 'next-lockdown' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[linux-2.6-microblaze.git] / drivers / media / rc / img-ir / img-ir-raw.c
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 }