sched: Remove double_rq_lock() from __migrate_task()
[linux/fpc-iii.git] / drivers / media / rc / img-ir / img-ir-raw.c
blobcfb01d9e571a12ba79242f3cb1852902f2f94afd
1 /*
2 * ImgTec IR Raw Decoder found in PowerDown Controller.
4 * Copyright 2010-2014 Imagination Technologies Ltd.
6 * This ties into the input subsystem using the RC-core in raw mode. Raw IR
7 * signal edges are reported and decoded by generic software decoders.
8 */
10 #include <linux/spinlock.h>
11 #include <media/rc-core.h>
12 #include "img-ir.h"
14 #define ECHO_TIMEOUT_MS 150 /* ms between echos */
16 /* must be called with priv->lock held */
17 static void img_ir_refresh_raw(struct img_ir_priv *priv, u32 irq_status)
19 struct img_ir_priv_raw *raw = &priv->raw;
20 struct rc_dev *rc_dev = priv->raw.rdev;
21 int multiple;
22 u32 ir_status;
24 /* find whether both rise and fall was detected */
25 multiple = ((irq_status & IMG_IR_IRQ_EDGE) == IMG_IR_IRQ_EDGE);
27 * If so, we need to see if the level has actually changed.
28 * If it's just noise that we didn't have time to process,
29 * there's no point reporting it.
31 ir_status = img_ir_read(priv, IMG_IR_STATUS) & IMG_IR_IRRXD;
32 if (multiple && ir_status == raw->last_status)
33 return;
34 raw->last_status = ir_status;
36 /* report the edge to the IR raw decoders */
37 if (ir_status) /* low */
38 ir_raw_event_store_edge(rc_dev, IR_SPACE);
39 else /* high */
40 ir_raw_event_store_edge(rc_dev, IR_PULSE);
41 ir_raw_event_handle(rc_dev);
44 /* called with priv->lock held */
45 void img_ir_isr_raw(struct img_ir_priv *priv, u32 irq_status)
47 struct img_ir_priv_raw *raw = &priv->raw;
49 /* check not removing */
50 if (!raw->rdev)
51 return;
53 img_ir_refresh_raw(priv, irq_status);
55 /* start / push back the echo timer */
56 mod_timer(&raw->timer, jiffies + msecs_to_jiffies(ECHO_TIMEOUT_MS));
60 * Echo timer callback function.
61 * The raw decoders expect to get a final sample even if there are no edges, in
62 * order to be assured of the final space. If there are no edges for a certain
63 * time we use this timer to emit a final sample to satisfy them.
65 static void img_ir_echo_timer(unsigned long arg)
67 struct img_ir_priv *priv = (struct img_ir_priv *)arg;
69 spin_lock_irq(&priv->lock);
71 /* check not removing */
72 if (priv->raw.rdev)
74 * It's safe to pass irq_status=0 since it's only used to check
75 * for double edges.
77 img_ir_refresh_raw(priv, 0);
79 spin_unlock_irq(&priv->lock);
82 void img_ir_setup_raw(struct img_ir_priv *priv)
84 u32 irq_en;
86 if (!priv->raw.rdev)
87 return;
89 /* clear and enable edge interrupts */
90 spin_lock_irq(&priv->lock);
91 irq_en = img_ir_read(priv, IMG_IR_IRQ_ENABLE);
92 irq_en |= IMG_IR_IRQ_EDGE;
93 img_ir_write(priv, IMG_IR_IRQ_CLEAR, IMG_IR_IRQ_EDGE);
94 img_ir_write(priv, IMG_IR_IRQ_ENABLE, irq_en);
95 spin_unlock_irq(&priv->lock);
98 int img_ir_probe_raw(struct img_ir_priv *priv)
100 struct img_ir_priv_raw *raw = &priv->raw;
101 struct rc_dev *rdev;
102 int error;
104 /* Set up the echo timer */
105 setup_timer(&raw->timer, img_ir_echo_timer, (unsigned long)priv);
107 /* Allocate raw decoder */
108 raw->rdev = rdev = rc_allocate_device();
109 if (!rdev) {
110 dev_err(priv->dev, "cannot allocate raw input device\n");
111 return -ENOMEM;
113 rdev->priv = priv;
114 rdev->map_name = RC_MAP_EMPTY;
115 rdev->input_name = "IMG Infrared Decoder Raw";
116 rdev->driver_type = RC_DRIVER_IR_RAW;
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;
127 return 0;
130 void img_ir_remove_raw(struct img_ir_priv *priv)
132 struct img_ir_priv_raw *raw = &priv->raw;
133 struct rc_dev *rdev = raw->rdev;
134 u32 irq_en;
136 if (!rdev)
137 return;
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);
148 rc_unregister_device(rdev);
150 del_timer_sync(&raw->timer);