1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <linux/spinlock.h>
16#include <media/rc-core.h>
17#include "img-ir.h"
18
19#define ECHO_TIMEOUT_MS 150
20
21
22static void img_ir_refresh_raw(struct img_ir_priv *priv, u32 irq_status)
23{
24 struct img_ir_priv_raw *raw = &priv->raw;
25 struct rc_dev *rc_dev = priv->raw.rdev;
26 int multiple;
27 u32 ir_status;
28
29
30 multiple = ((irq_status & IMG_IR_IRQ_EDGE) == IMG_IR_IRQ_EDGE);
31
32
33
34
35
36 ir_status = img_ir_read(priv, IMG_IR_STATUS) & IMG_IR_IRRXD;
37 if (multiple && ir_status == raw->last_status)
38 return;
39 raw->last_status = ir_status;
40
41
42 if (ir_status)
43 ir_raw_event_store_edge(rc_dev, false);
44 else
45 ir_raw_event_store_edge(rc_dev, true);
46 ir_raw_event_handle(rc_dev);
47}
48
49
50void img_ir_isr_raw(struct img_ir_priv *priv, u32 irq_status)
51{
52 struct img_ir_priv_raw *raw = &priv->raw;
53
54
55 if (!raw->rdev)
56 return;
57
58 img_ir_refresh_raw(priv, irq_status);
59
60
61 mod_timer(&raw->timer, jiffies + msecs_to_jiffies(ECHO_TIMEOUT_MS));
62}
63
64
65
66
67
68
69
70static void img_ir_echo_timer(struct timer_list *t)
71{
72 struct img_ir_priv *priv = from_timer(priv, t, raw.timer);
73
74 spin_lock_irq(&priv->lock);
75
76
77 if (priv->raw.rdev)
78
79
80
81
82 img_ir_refresh_raw(priv, 0);
83
84 spin_unlock_irq(&priv->lock);
85}
86
87void img_ir_setup_raw(struct img_ir_priv *priv)
88{
89 u32 irq_en;
90
91 if (!priv->raw.rdev)
92 return;
93
94
95 spin_lock_irq(&priv->lock);
96 irq_en = img_ir_read(priv, IMG_IR_IRQ_ENABLE);
97 irq_en |= IMG_IR_IRQ_EDGE;
98 img_ir_write(priv, IMG_IR_IRQ_CLEAR, IMG_IR_IRQ_EDGE);
99 img_ir_write(priv, IMG_IR_IRQ_ENABLE, irq_en);
100 spin_unlock_irq(&priv->lock);
101}
102
103int img_ir_probe_raw(struct img_ir_priv *priv)
104{
105 struct img_ir_priv_raw *raw = &priv->raw;
106 struct rc_dev *rdev;
107 int error;
108
109
110 timer_setup(&raw->timer, img_ir_echo_timer, 0);
111
112
113 raw->rdev = rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
114 if (!rdev) {
115 dev_err(priv->dev, "cannot allocate raw input device\n");
116 return -ENOMEM;
117 }
118 rdev->priv = priv;
119 rdev->map_name = RC_MAP_EMPTY;
120 rdev->device_name = "IMG Infrared Decoder Raw";
121
122
123 error = rc_register_device(rdev);
124 if (error) {
125 dev_err(priv->dev, "failed to register raw IR input device\n");
126 rc_free_device(rdev);
127 raw->rdev = NULL;
128 return error;
129 }
130
131 return 0;
132}
133
134void img_ir_remove_raw(struct img_ir_priv *priv)
135{
136 struct img_ir_priv_raw *raw = &priv->raw;
137 struct rc_dev *rdev = raw->rdev;
138 u32 irq_en;
139
140 if (!rdev)
141 return;
142
143
144 spin_lock_irq(&priv->lock);
145 raw->rdev = NULL;
146 irq_en = img_ir_read(priv, IMG_IR_IRQ_ENABLE);
147 irq_en &= ~IMG_IR_IRQ_EDGE;
148 img_ir_write(priv, IMG_IR_IRQ_ENABLE, irq_en);
149 img_ir_write(priv, IMG_IR_IRQ_CLEAR, IMG_IR_IRQ_EDGE);
150 spin_unlock_irq(&priv->lock);
151
152 rc_unregister_device(rdev);
153
154 del_timer_sync(&raw->timer);
155}
156