GNU Linux-libre 4.14.290-gnu1
[releases.git] / drivers / media / rc / img-ir / img-ir-raw.c
1 /*
2  * ImgTec IR Raw Decoder found in PowerDown Controller.
3  *
4  * Copyright 2010-2014 Imagination Technologies Ltd.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by the
8  * Free Software Foundation; either version 2 of the License, or (at your
9  * option) any later version.
10  *
11  * This ties into the input subsystem using the RC-core in raw mode. Raw IR
12  * signal edges are reported and decoded by generic software decoders.
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     /* ms between echos */
20
21 /* must be called with priv->lock held */
22 static 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         /* find whether both rise and fall was detected */
30         multiple = ((irq_status & IMG_IR_IRQ_EDGE) == IMG_IR_IRQ_EDGE);
31         /*
32          * If so, we need to see if the level has actually changed.
33          * If it's just noise that we didn't have time to process,
34          * there's no point reporting it.
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         /* report the edge to the IR raw decoders */
42         if (ir_status) /* low */
43                 ir_raw_event_store_edge(rc_dev, false);
44         else /* high */
45                 ir_raw_event_store_edge(rc_dev, true);
46         ir_raw_event_handle(rc_dev);
47 }
48
49 /* called with priv->lock held */
50 void img_ir_isr_raw(struct img_ir_priv *priv, u32 irq_status)
51 {
52         struct img_ir_priv_raw *raw = &priv->raw;
53
54         /* check not removing */
55         if (!raw->rdev)
56                 return;
57
58         img_ir_refresh_raw(priv, irq_status);
59
60         /* start / push back the echo timer */
61         mod_timer(&raw->timer, jiffies + msecs_to_jiffies(ECHO_TIMEOUT_MS));
62 }
63
64 /*
65  * Echo timer callback function.
66  * The raw decoders expect to get a final sample even if there are no edges, in
67  * order to be assured of the final space. If there are no edges for a certain
68  * time we use this timer to emit a final sample to satisfy them.
69  */
70 static void img_ir_echo_timer(unsigned long arg)
71 {
72         struct img_ir_priv *priv = (struct img_ir_priv *)arg;
73
74         spin_lock_irq(&priv->lock);
75
76         /* check not removing */
77         if (priv->raw.rdev)
78                 /*
79                  * It's safe to pass irq_status=0 since it's only used to check
80                  * for double edges.
81                  */
82                 img_ir_refresh_raw(priv, 0);
83
84         spin_unlock_irq(&priv->lock);
85 }
86
87 void img_ir_setup_raw(struct img_ir_priv *priv)
88 {
89         u32 irq_en;
90
91         if (!priv->raw.rdev)
92                 return;
93
94         /* clear and enable edge interrupts */
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
103 int 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         /* Set up the echo timer */
110         setup_timer(&raw->timer, img_ir_echo_timer, (unsigned long)priv);
111
112         /* Allocate raw decoder */
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         /* Register raw decoder */
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
134 void 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         /* switch off and disable raw (edge) interrupts */
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 }