diff options
Diffstat (limited to 'drivers/media/IR')
-rw-r--r-- | drivers/media/IR/Kconfig | 36 | ||||
-rw-r--r-- | drivers/media/IR/Makefile | 2 | ||||
-rw-r--r-- | drivers/media/IR/ene_ir.c | 1023 | ||||
-rw-r--r-- | drivers/media/IR/ene_ir.h | 235 | ||||
-rw-r--r-- | drivers/media/IR/imon.c | 20 | ||||
-rw-r--r-- | drivers/media/IR/ir-core-priv.h | 13 | ||||
-rw-r--r-- | drivers/media/IR/ir-jvc-decoder.c | 14 | ||||
-rw-r--r-- | drivers/media/IR/ir-keytable.c | 13 | ||||
-rw-r--r-- | drivers/media/IR/ir-lirc-codec.c | 124 | ||||
-rw-r--r-- | drivers/media/IR/ir-nec-decoder.c | 25 | ||||
-rw-r--r-- | drivers/media/IR/ir-raw-event.c | 159 | ||||
-rw-r--r-- | drivers/media/IR/ir-sysfs.c | 2 | ||||
-rw-r--r-- | drivers/media/IR/keymaps/Makefile | 2 | ||||
-rw-r--r-- | drivers/media/IR/keymaps/rc-empty.c | 44 | ||||
-rw-r--r-- | drivers/media/IR/keymaps/rc-rc5-streamzap.c | 81 | ||||
-rw-r--r-- | drivers/media/IR/keymaps/rc-rc6-mce.c | 2 | ||||
-rw-r--r-- | drivers/media/IR/mceusb.c | 21 | ||||
-rw-r--r-- | drivers/media/IR/rc-map.c | 23 | ||||
-rw-r--r-- | drivers/media/IR/streamzap.c | 741 |
19 files changed, 2434 insertions, 146 deletions
diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig index 999a8250b3ce..30e04915a256 100644 --- a/drivers/media/IR/Kconfig +++ b/drivers/media/IR/Kconfig | |||
@@ -1,8 +1,10 @@ | |||
1 | config IR_CORE | 1 | menuconfig IR_CORE |
2 | tristate | 2 | tristate "Infrared remote controller adapters" |
3 | depends on INPUT | 3 | depends on INPUT |
4 | default INPUT | 4 | default INPUT |
5 | 5 | ||
6 | if IR_CORE | ||
7 | |||
6 | config VIDEO_IR | 8 | config VIDEO_IR |
7 | tristate | 9 | tristate |
8 | depends on IR_CORE | 10 | depends on IR_CORE |
@@ -16,7 +18,7 @@ config LIRC | |||
16 | Enable this option to build the Linux Infrared Remote | 18 | Enable this option to build the Linux Infrared Remote |
17 | Control (LIRC) core device interface driver. The LIRC | 19 | Control (LIRC) core device interface driver. The LIRC |
18 | interface passes raw IR to and from userspace, where the | 20 | interface passes raw IR to and from userspace, where the |
19 | LIRC daemon handles protocol decoding for IR reception ann | 21 | LIRC daemon handles protocol decoding for IR reception and |
20 | encoding for IR transmitting (aka "blasting"). | 22 | encoding for IR transmitting (aka "blasting"). |
21 | 23 | ||
22 | source "drivers/media/IR/keymaps/Kconfig" | 24 | source "drivers/media/IR/keymaps/Kconfig" |
@@ -103,3 +105,31 @@ config IR_MCEUSB | |||
103 | 105 | ||
104 | To compile this driver as a module, choose M here: the | 106 | To compile this driver as a module, choose M here: the |
105 | module will be called mceusb. | 107 | module will be called mceusb. |
108 | |||
109 | config IR_ENE | ||
110 | tristate "ENE eHome Receiver/Transciever (pnp id: ENE0100/ENE02xxx)" | ||
111 | depends on PNP | ||
112 | depends on IR_CORE | ||
113 | ---help--- | ||
114 | Say Y here to enable support for integrated infrared receiver | ||
115 | /transciever made by ENE. | ||
116 | |||
117 | You can see if you have it by looking at lspnp output. | ||
118 | Output should include ENE0100 ENE0200 or something similiar. | ||
119 | |||
120 | To compile this driver as a module, choose M here: the | ||
121 | module will be called ene_ir. | ||
122 | |||
123 | config IR_STREAMZAP | ||
124 | tristate "Streamzap PC Remote IR Receiver" | ||
125 | depends on USB_ARCH_HAS_HCD | ||
126 | depends on IR_CORE | ||
127 | select USB | ||
128 | ---help--- | ||
129 | Say Y here if you want to use a Streamzap PC Remote | ||
130 | Infrared Receiver. | ||
131 | |||
132 | To compile this driver as a module, choose M here: the | ||
133 | module will be called streamzap. | ||
134 | |||
135 | endif #IR_CORE | ||
diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile index 2ae4f3abfdbd..53676838fe97 100644 --- a/drivers/media/IR/Makefile +++ b/drivers/media/IR/Makefile | |||
@@ -16,3 +16,5 @@ obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o | |||
16 | # stand-alone IR receivers/transmitters | 16 | # stand-alone IR receivers/transmitters |
17 | obj-$(CONFIG_IR_IMON) += imon.o | 17 | obj-$(CONFIG_IR_IMON) += imon.o |
18 | obj-$(CONFIG_IR_MCEUSB) += mceusb.o | 18 | obj-$(CONFIG_IR_MCEUSB) += mceusb.o |
19 | obj-$(CONFIG_IR_ENE) += ene_ir.o | ||
20 | obj-$(CONFIG_IR_STREAMZAP) += streamzap.o | ||
diff --git a/drivers/media/IR/ene_ir.c b/drivers/media/IR/ene_ir.c new file mode 100644 index 000000000000..5447750f5e38 --- /dev/null +++ b/drivers/media/IR/ene_ir.c | |||
@@ -0,0 +1,1023 @@ | |||
1 | /* | ||
2 | * driver for ENE KB3926 B/C/D CIR (pnp id: ENE0XXX) | ||
3 | * | ||
4 | * Copyright (C) 2010 Maxim Levitsky <maximlevitsky@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation; either version 2 of the | ||
9 | * License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
19 | * USA | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/pnp.h> | ||
25 | #include <linux/io.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/sched.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/input.h> | ||
30 | #include <media/ir-core.h> | ||
31 | #include <media/ir-common.h> | ||
32 | #include "ene_ir.h" | ||
33 | |||
34 | |||
35 | static int sample_period = -1; | ||
36 | static int enable_idle = 1; | ||
37 | static int input = 1; | ||
38 | static int debug; | ||
39 | static int txsim; | ||
40 | |||
41 | static int ene_irq_status(struct ene_device *dev); | ||
42 | |||
43 | /* read a hardware register */ | ||
44 | static u8 ene_hw_read_reg(struct ene_device *dev, u16 reg) | ||
45 | { | ||
46 | u8 retval; | ||
47 | outb(reg >> 8, dev->hw_io + ENE_ADDR_HI); | ||
48 | outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO); | ||
49 | retval = inb(dev->hw_io + ENE_IO); | ||
50 | |||
51 | ene_dbg_verbose("reg %04x == %02x", reg, retval); | ||
52 | return retval; | ||
53 | } | ||
54 | |||
55 | /* write a hardware register */ | ||
56 | static void ene_hw_write_reg(struct ene_device *dev, u16 reg, u8 value) | ||
57 | { | ||
58 | outb(reg >> 8, dev->hw_io + ENE_ADDR_HI); | ||
59 | outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO); | ||
60 | outb(value, dev->hw_io + ENE_IO); | ||
61 | |||
62 | ene_dbg_verbose("reg %04x <- %02x", reg, value); | ||
63 | } | ||
64 | |||
65 | /* change specific bits in hardware register */ | ||
66 | static void ene_hw_write_reg_mask(struct ene_device *dev, | ||
67 | u16 reg, u8 value, u8 mask) | ||
68 | { | ||
69 | u8 regvalue; | ||
70 | |||
71 | outb(reg >> 8, dev->hw_io + ENE_ADDR_HI); | ||
72 | outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO); | ||
73 | |||
74 | regvalue = inb(dev->hw_io + ENE_IO) & ~mask; | ||
75 | regvalue |= (value & mask); | ||
76 | outb(regvalue, dev->hw_io + ENE_IO); | ||
77 | |||
78 | ene_dbg_verbose("reg %04x <- %02x (mask=%02x)", reg, value, mask); | ||
79 | } | ||
80 | |||
81 | /* detect hardware features */ | ||
82 | static int ene_hw_detect(struct ene_device *dev) | ||
83 | { | ||
84 | u8 chip_major, chip_minor; | ||
85 | u8 hw_revision, old_ver; | ||
86 | u8 tmp; | ||
87 | u8 fw_capabilities; | ||
88 | int pll_freq; | ||
89 | |||
90 | tmp = ene_hw_read_reg(dev, ENE_HW_UNK); | ||
91 | ene_hw_write_reg(dev, ENE_HW_UNK, tmp & ~ENE_HW_UNK_CLR); | ||
92 | |||
93 | chip_major = ene_hw_read_reg(dev, ENE_HW_VER_MAJOR); | ||
94 | chip_minor = ene_hw_read_reg(dev, ENE_HW_VER_MINOR); | ||
95 | |||
96 | ene_hw_write_reg(dev, ENE_HW_UNK, tmp); | ||
97 | hw_revision = ene_hw_read_reg(dev, ENE_HW_VERSION); | ||
98 | old_ver = ene_hw_read_reg(dev, ENE_HW_VER_OLD); | ||
99 | |||
100 | pll_freq = (ene_hw_read_reg(dev, ENE_PLLFRH) << 4) + | ||
101 | (ene_hw_read_reg(dev, ENE_PLLFRL) >> 4); | ||
102 | |||
103 | if (pll_freq != 1000) | ||
104 | dev->rx_period_adjust = 4; | ||
105 | else | ||
106 | dev->rx_period_adjust = 2; | ||
107 | |||
108 | |||
109 | ene_printk(KERN_NOTICE, "PLL freq = %d\n", pll_freq); | ||
110 | |||
111 | if (hw_revision == 0xFF) { | ||
112 | |||
113 | ene_printk(KERN_WARNING, "device seems to be disabled\n"); | ||
114 | ene_printk(KERN_WARNING, | ||
115 | "send a mail to lirc-list@lists.sourceforge.net\n"); | ||
116 | ene_printk(KERN_WARNING, "please attach output of acpidump\n"); | ||
117 | return -ENODEV; | ||
118 | } | ||
119 | |||
120 | if (chip_major == 0x33) { | ||
121 | ene_printk(KERN_WARNING, "chips 0x33xx aren't supported\n"); | ||
122 | return -ENODEV; | ||
123 | } | ||
124 | |||
125 | if (chip_major == 0x39 && chip_minor == 0x26 && hw_revision == 0xC0) { | ||
126 | dev->hw_revision = ENE_HW_C; | ||
127 | } else if (old_ver == 0x24 && hw_revision == 0xC0) { | ||
128 | dev->hw_revision = ENE_HW_B; | ||
129 | ene_printk(KERN_NOTICE, "KB3926B detected\n"); | ||
130 | } else { | ||
131 | dev->hw_revision = ENE_HW_D; | ||
132 | ene_printk(KERN_WARNING, | ||
133 | "unknown ENE chip detected, assuming KB3926D\n"); | ||
134 | ene_printk(KERN_WARNING, | ||
135 | "driver support might be not complete"); | ||
136 | |||
137 | } | ||
138 | |||
139 | ene_printk(KERN_DEBUG, | ||
140 | "chip is 0x%02x%02x - kbver = 0x%02x, rev = 0x%02x\n", | ||
141 | chip_major, chip_minor, old_ver, hw_revision); | ||
142 | |||
143 | /* detect features hardware supports */ | ||
144 | if (dev->hw_revision < ENE_HW_C) | ||
145 | return 0; | ||
146 | |||
147 | fw_capabilities = ene_hw_read_reg(dev, ENE_FW2); | ||
148 | ene_dbg("Firmware capabilities: %02x", fw_capabilities); | ||
149 | |||
150 | dev->hw_gpio40_learning = fw_capabilities & ENE_FW2_GP40_AS_LEARN; | ||
151 | dev->hw_learning_and_tx_capable = fw_capabilities & ENE_FW2_LEARNING; | ||
152 | |||
153 | dev->hw_fan_as_normal_input = dev->hw_learning_and_tx_capable && | ||
154 | (fw_capabilities & ENE_FW2_FAN_AS_NRML_IN); | ||
155 | |||
156 | ene_printk(KERN_NOTICE, "hardware features:\n"); | ||
157 | ene_printk(KERN_NOTICE, | ||
158 | "learning and transmit %s, gpio40_learn %s, fan_in %s\n", | ||
159 | dev->hw_learning_and_tx_capable ? "on" : "off", | ||
160 | dev->hw_gpio40_learning ? "on" : "off", | ||
161 | dev->hw_fan_as_normal_input ? "on" : "off"); | ||
162 | |||
163 | if (dev->hw_learning_and_tx_capable) { | ||
164 | ene_printk(KERN_WARNING, | ||
165 | "Device supports transmitting, but that support is\n"); | ||
166 | ene_printk(KERN_WARNING, | ||
167 | "lightly tested. Please test it and mail\n"); | ||
168 | ene_printk(KERN_WARNING, | ||
169 | "lirc-list@lists.sourceforge.net\n"); | ||
170 | } | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | /* this enables/disables IR input via gpio40*/ | ||
175 | static void ene_enable_gpio40_receive(struct ene_device *dev, int enable) | ||
176 | { | ||
177 | ene_hw_write_reg_mask(dev, ENE_CIR_CONF2, enable ? | ||
178 | 0 : ENE_CIR_CONF2_GPIO40DIS, | ||
179 | ENE_CIR_CONF2_GPIO40DIS); | ||
180 | } | ||
181 | |||
182 | /* this enables/disables IR via standard input */ | ||
183 | static void ene_enable_normal_receive(struct ene_device *dev, int enable) | ||
184 | { | ||
185 | ene_hw_write_reg(dev, ENE_CIR_CONF1, enable ? ENE_CIR_CONF1_RX_ON : 0); | ||
186 | } | ||
187 | |||
188 | /* this enables/disables IR input via unused fan tachtometer input */ | ||
189 | static void ene_enable_fan_receive(struct ene_device *dev, int enable) | ||
190 | { | ||
191 | if (!enable) | ||
192 | ene_hw_write_reg(dev, ENE_FAN_AS_IN1, 0); | ||
193 | else { | ||
194 | ene_hw_write_reg(dev, ENE_FAN_AS_IN1, ENE_FAN_AS_IN1_EN); | ||
195 | ene_hw_write_reg(dev, ENE_FAN_AS_IN2, ENE_FAN_AS_IN2_EN); | ||
196 | } | ||
197 | dev->rx_fan_input_inuse = enable; | ||
198 | } | ||
199 | |||
200 | |||
201 | /* Sense current received carrier */ | ||
202 | static int ene_rx_sense_carrier(struct ene_device *dev) | ||
203 | { | ||
204 | int period = ene_hw_read_reg(dev, ENE_RX_CARRIER); | ||
205 | int carrier; | ||
206 | ene_dbg("RX: hardware carrier period = %02x", period); | ||
207 | |||
208 | if (!(period & ENE_RX_CARRIER_VALID)) | ||
209 | return 0; | ||
210 | |||
211 | period &= ~ENE_RX_CARRIER_VALID; | ||
212 | |||
213 | if (!period) | ||
214 | return 0; | ||
215 | |||
216 | carrier = 2000000 / period; | ||
217 | ene_dbg("RX: sensed carrier = %d Hz", carrier); | ||
218 | return carrier; | ||
219 | } | ||
220 | |||
221 | /* determine which input to use*/ | ||
222 | static void ene_rx_set_inputs(struct ene_device *dev) | ||
223 | { | ||
224 | int learning_mode = dev->learning_enabled; | ||
225 | |||
226 | ene_dbg("RX: setup receiver, learning mode = %d", learning_mode); | ||
227 | |||
228 | ene_enable_normal_receive(dev, 1); | ||
229 | |||
230 | /* old hardware doesn't support learning mode for sure */ | ||
231 | if (dev->hw_revision <= ENE_HW_B) | ||
232 | return; | ||
233 | |||
234 | /* receiver not learning capable, still set gpio40 correctly */ | ||
235 | if (!dev->hw_learning_and_tx_capable) { | ||
236 | ene_enable_gpio40_receive(dev, !dev->hw_gpio40_learning); | ||
237 | return; | ||
238 | } | ||
239 | |||
240 | /* enable learning mode */ | ||
241 | if (learning_mode) { | ||
242 | ene_enable_gpio40_receive(dev, dev->hw_gpio40_learning); | ||
243 | |||
244 | /* fan input is not used for learning */ | ||
245 | if (dev->hw_fan_as_normal_input) | ||
246 | ene_enable_fan_receive(dev, 0); | ||
247 | |||
248 | /* disable learning mode */ | ||
249 | } else { | ||
250 | if (dev->hw_fan_as_normal_input) { | ||
251 | ene_enable_fan_receive(dev, 1); | ||
252 | ene_enable_normal_receive(dev, 0); | ||
253 | } else | ||
254 | ene_enable_gpio40_receive(dev, | ||
255 | !dev->hw_gpio40_learning); | ||
256 | } | ||
257 | |||
258 | /* set few additional settings for this mode */ | ||
259 | ene_hw_write_reg_mask(dev, ENE_CIR_CONF1, learning_mode ? | ||
260 | ENE_CIR_CONF1_LEARN1 : 0, ENE_CIR_CONF1_LEARN1); | ||
261 | |||
262 | ene_hw_write_reg_mask(dev, ENE_CIR_CONF2, learning_mode ? | ||
263 | ENE_CIR_CONF2_LEARN2 : 0, ENE_CIR_CONF2_LEARN2); | ||
264 | |||
265 | if (dev->rx_fan_input_inuse) { | ||
266 | dev->props->rx_resolution = ENE_SAMPLE_PERIOD_FAN * 1000; | ||
267 | |||
268 | dev->props->timeout = | ||
269 | ENE_FAN_VALUE_MASK * ENE_SAMPLE_PERIOD_FAN * 1000; | ||
270 | } else { | ||
271 | dev->props->rx_resolution = sample_period * 1000; | ||
272 | dev->props->timeout = ENE_MAXGAP * 1000; | ||
273 | } | ||
274 | } | ||
275 | |||
276 | /* Enable the device for receive */ | ||
277 | static void ene_rx_enable(struct ene_device *dev) | ||
278 | { | ||
279 | u8 reg_value; | ||
280 | |||
281 | if (dev->hw_revision < ENE_HW_C) { | ||
282 | ene_hw_write_reg(dev, ENEB_IRQ, dev->irq << 1); | ||
283 | ene_hw_write_reg(dev, ENEB_IRQ_UNK1, 0x01); | ||
284 | } else { | ||
285 | reg_value = ene_hw_read_reg(dev, ENEC_IRQ) & 0xF0; | ||
286 | reg_value |= ENEC_IRQ_UNK_EN; | ||
287 | reg_value &= ~ENEC_IRQ_STATUS; | ||
288 | reg_value |= (dev->irq & ENEC_IRQ_MASK); | ||
289 | ene_hw_write_reg(dev, ENEC_IRQ, reg_value); | ||
290 | ene_hw_write_reg(dev, ENE_TX_UNK1, 0x63); | ||
291 | } | ||
292 | |||
293 | ene_hw_write_reg(dev, ENE_CIR_CONF2, 0x00); | ||
294 | ene_rx_set_inputs(dev); | ||
295 | |||
296 | /* set sampling period */ | ||
297 | ene_hw_write_reg(dev, ENE_CIR_SAMPLE_PERIOD, sample_period); | ||
298 | |||
299 | /* ack any pending irqs - just in case */ | ||
300 | ene_irq_status(dev); | ||
301 | |||
302 | /* enable firmware bits */ | ||
303 | ene_hw_write_reg_mask(dev, ENE_FW1, | ||
304 | ENE_FW1_ENABLE | ENE_FW1_IRQ, | ||
305 | ENE_FW1_ENABLE | ENE_FW1_IRQ); | ||
306 | |||
307 | /* enter idle mode */ | ||
308 | ir_raw_event_set_idle(dev->idev, 1); | ||
309 | ir_raw_event_reset(dev->idev); | ||
310 | |||
311 | } | ||
312 | |||
313 | /* Disable the device receiver */ | ||
314 | static void ene_rx_disable(struct ene_device *dev) | ||
315 | { | ||
316 | /* disable inputs */ | ||
317 | ene_enable_normal_receive(dev, 0); | ||
318 | |||
319 | if (dev->hw_fan_as_normal_input) | ||
320 | ene_enable_fan_receive(dev, 0); | ||
321 | |||
322 | /* disable hardware IRQ and firmware flag */ | ||
323 | ene_hw_write_reg_mask(dev, ENE_FW1, 0, ENE_FW1_ENABLE | ENE_FW1_IRQ); | ||
324 | |||
325 | ir_raw_event_set_idle(dev->idev, 1); | ||
326 | ir_raw_event_reset(dev->idev); | ||
327 | } | ||
328 | |||
329 | |||
330 | /* prepare transmission */ | ||
331 | static void ene_tx_prepare(struct ene_device *dev) | ||
332 | { | ||
333 | u8 conf1; | ||
334 | |||
335 | conf1 = ene_hw_read_reg(dev, ENE_CIR_CONF1); | ||
336 | dev->saved_conf1 = conf1; | ||
337 | |||
338 | if (dev->hw_revision == ENE_HW_C) | ||
339 | conf1 &= ~ENE_CIR_CONF1_TX_CLEAR; | ||
340 | |||
341 | /* Enable TX engine */ | ||
342 | conf1 |= ENE_CIR_CONF1_TX_ON; | ||
343 | |||
344 | /* Set carrier */ | ||
345 | if (dev->tx_period) { | ||
346 | |||
347 | /* NOTE: duty cycle handling is just a guess, it might | ||
348 | not be aviable. Default values were tested */ | ||
349 | int tx_period_in500ns = dev->tx_period * 2; | ||
350 | |||
351 | int tx_pulse_width_in_500ns = | ||
352 | tx_period_in500ns / (100 / dev->tx_duty_cycle); | ||
353 | |||
354 | if (!tx_pulse_width_in_500ns) | ||
355 | tx_pulse_width_in_500ns = 1; | ||
356 | |||
357 | ene_dbg("TX: pulse distance = %d * 500 ns", tx_period_in500ns); | ||
358 | ene_dbg("TX: pulse width = %d * 500 ns", | ||
359 | tx_pulse_width_in_500ns); | ||
360 | |||
361 | ene_hw_write_reg(dev, ENE_TX_PERIOD, ENE_TX_PERIOD_UNKBIT | | ||
362 | tx_period_in500ns); | ||
363 | |||
364 | ene_hw_write_reg(dev, ENE_TX_PERIOD_PULSE, | ||
365 | tx_pulse_width_in_500ns); | ||
366 | |||
367 | conf1 |= ENE_CIR_CONF1_TX_CARR; | ||
368 | } else | ||
369 | conf1 &= ~ENE_CIR_CONF1_TX_CARR; | ||
370 | |||
371 | ene_hw_write_reg(dev, ENE_CIR_CONF1, conf1); | ||
372 | |||
373 | } | ||
374 | |||
375 | /* end transmission */ | ||
376 | static void ene_tx_complete(struct ene_device *dev) | ||
377 | { | ||
378 | ene_hw_write_reg(dev, ENE_CIR_CONF1, dev->saved_conf1); | ||
379 | dev->tx_buffer = NULL; | ||
380 | } | ||
381 | |||
382 | /* set transmit mask */ | ||
383 | static void ene_tx_hw_set_transmiter_mask(struct ene_device *dev) | ||
384 | { | ||
385 | u8 txport1 = ene_hw_read_reg(dev, ENE_TX_PORT1) & ~ENE_TX_PORT1_EN; | ||
386 | u8 txport2 = ene_hw_read_reg(dev, ENE_TX_PORT2) & ~ENE_TX_PORT2_EN; | ||
387 | |||
388 | if (dev->transmitter_mask & 0x01) | ||
389 | txport1 |= ENE_TX_PORT1_EN; | ||
390 | |||
391 | if (dev->transmitter_mask & 0x02) | ||
392 | txport2 |= ENE_TX_PORT2_EN; | ||
393 | |||
394 | ene_hw_write_reg(dev, ENE_TX_PORT1, txport1); | ||
395 | ene_hw_write_reg(dev, ENE_TX_PORT2, txport2); | ||
396 | } | ||
397 | |||
398 | /* TX one sample - must be called with dev->hw_lock*/ | ||
399 | static void ene_tx_sample(struct ene_device *dev) | ||
400 | { | ||
401 | u8 raw_tx; | ||
402 | u32 sample; | ||
403 | |||
404 | if (!dev->tx_buffer) { | ||
405 | ene_dbg("TX: attempt to transmit NULL buffer"); | ||
406 | return; | ||
407 | } | ||
408 | |||
409 | /* Grab next TX sample */ | ||
410 | if (!dev->tx_sample) { | ||
411 | again: | ||
412 | if (dev->tx_pos == dev->tx_len + 1) { | ||
413 | if (!dev->tx_done) { | ||
414 | ene_dbg("TX: no more data to send"); | ||
415 | dev->tx_done = 1; | ||
416 | goto exit; | ||
417 | } else { | ||
418 | ene_dbg("TX: last sample sent by hardware"); | ||
419 | ene_tx_complete(dev); | ||
420 | complete(&dev->tx_complete); | ||
421 | return; | ||
422 | } | ||
423 | } | ||
424 | |||
425 | sample = dev->tx_buffer[dev->tx_pos++]; | ||
426 | dev->tx_sample_pulse = !dev->tx_sample_pulse; | ||
427 | |||
428 | ene_dbg("TX: sample %8d (%s)", sample, dev->tx_sample_pulse ? | ||
429 | "pulse" : "space"); | ||
430 | |||
431 | dev->tx_sample = DIV_ROUND_CLOSEST(sample, ENE_TX_SMPL_PERIOD); | ||
432 | |||
433 | /* guard against too short samples */ | ||
434 | if (!dev->tx_sample) | ||
435 | goto again; | ||
436 | } | ||
437 | |||
438 | raw_tx = min(dev->tx_sample , (unsigned int)ENE_TX_SMLP_MASK); | ||
439 | dev->tx_sample -= raw_tx; | ||
440 | |||
441 | if (dev->tx_sample_pulse) | ||
442 | raw_tx |= ENE_TX_PULSE_MASK; | ||
443 | |||
444 | ene_hw_write_reg(dev, ENE_TX_INPUT1 + dev->tx_reg, raw_tx); | ||
445 | dev->tx_reg = !dev->tx_reg; | ||
446 | exit: | ||
447 | /* simulate TX done interrupt */ | ||
448 | if (txsim) | ||
449 | mod_timer(&dev->tx_sim_timer, jiffies + HZ / 500); | ||
450 | } | ||
451 | |||
452 | /* timer to simulate tx done interrupt */ | ||
453 | static void ene_tx_irqsim(unsigned long data) | ||
454 | { | ||
455 | struct ene_device *dev = (struct ene_device *)data; | ||
456 | unsigned long flags; | ||
457 | |||
458 | spin_lock_irqsave(&dev->hw_lock, flags); | ||
459 | ene_tx_sample(dev); | ||
460 | spin_unlock_irqrestore(&dev->hw_lock, flags); | ||
461 | } | ||
462 | |||
463 | |||
464 | /* read irq status and ack it */ | ||
465 | static int ene_irq_status(struct ene_device *dev) | ||
466 | { | ||
467 | u8 irq_status; | ||
468 | u8 fw_flags1, fw_flags2; | ||
469 | int cur_rx_pointer; | ||
470 | int retval = 0; | ||
471 | |||
472 | fw_flags2 = ene_hw_read_reg(dev, ENE_FW2); | ||
473 | cur_rx_pointer = !!(fw_flags2 & ENE_FW2_BUF_HIGH); | ||
474 | |||
475 | if (dev->hw_revision < ENE_HW_C) { | ||
476 | irq_status = ene_hw_read_reg(dev, ENEB_IRQ_STATUS); | ||
477 | |||
478 | if (!(irq_status & ENEB_IRQ_STATUS_IR)) | ||
479 | return 0; | ||
480 | |||
481 | ene_hw_write_reg(dev, ENEB_IRQ_STATUS, | ||
482 | irq_status & ~ENEB_IRQ_STATUS_IR); | ||
483 | dev->rx_pointer = cur_rx_pointer; | ||
484 | return ENE_IRQ_RX; | ||
485 | } | ||
486 | |||
487 | irq_status = ene_hw_read_reg(dev, ENEC_IRQ); | ||
488 | |||
489 | if (!(irq_status & ENEC_IRQ_STATUS)) | ||
490 | return 0; | ||
491 | |||
492 | /* original driver does that twice - a workaround ? */ | ||
493 | ene_hw_write_reg(dev, ENEC_IRQ, irq_status & ~ENEC_IRQ_STATUS); | ||
494 | ene_hw_write_reg(dev, ENEC_IRQ, irq_status & ~ENEC_IRQ_STATUS); | ||
495 | |||
496 | /* clear unknown flag in F8F9 */ | ||
497 | if (fw_flags2 & ENE_FW2_IRQ_CLR) | ||
498 | ene_hw_write_reg(dev, ENE_FW2, fw_flags2 & ~ENE_FW2_IRQ_CLR); | ||
499 | |||
500 | /* check if this is a TX interrupt */ | ||
501 | fw_flags1 = ene_hw_read_reg(dev, ENE_FW1); | ||
502 | if (fw_flags1 & ENE_FW1_TXIRQ) { | ||
503 | ene_hw_write_reg(dev, ENE_FW1, fw_flags1 & ~ENE_FW1_TXIRQ); | ||
504 | retval |= ENE_IRQ_TX; | ||
505 | } | ||
506 | |||
507 | /* Check if this is RX interrupt */ | ||
508 | if (dev->rx_pointer != cur_rx_pointer) { | ||
509 | retval |= ENE_IRQ_RX; | ||
510 | dev->rx_pointer = cur_rx_pointer; | ||
511 | |||
512 | } else if (!(retval & ENE_IRQ_TX)) { | ||
513 | ene_dbg("RX: interrupt without change in RX pointer(%d)", | ||
514 | dev->rx_pointer); | ||
515 | retval |= ENE_IRQ_RX; | ||
516 | } | ||
517 | |||
518 | if ((retval & ENE_IRQ_RX) && (retval & ENE_IRQ_TX)) | ||
519 | ene_dbg("both RX and TX interrupt at same time"); | ||
520 | |||
521 | return retval; | ||
522 | } | ||
523 | |||
524 | /* interrupt handler */ | ||
525 | static irqreturn_t ene_isr(int irq, void *data) | ||
526 | { | ||
527 | u16 hw_value; | ||
528 | int i, hw_sample; | ||
529 | int pulse; | ||
530 | int irq_status; | ||
531 | unsigned long flags; | ||
532 | int carrier = 0; | ||
533 | irqreturn_t retval = IRQ_NONE; | ||
534 | struct ene_device *dev = (struct ene_device *)data; | ||
535 | struct ir_raw_event ev; | ||
536 | |||
537 | |||
538 | spin_lock_irqsave(&dev->hw_lock, flags); | ||
539 | irq_status = ene_irq_status(dev); | ||
540 | |||
541 | if (!irq_status) | ||
542 | goto unlock; | ||
543 | |||
544 | retval = IRQ_HANDLED; | ||
545 | |||
546 | if (irq_status & ENE_IRQ_TX) { | ||
547 | |||
548 | if (!dev->hw_learning_and_tx_capable) { | ||
549 | ene_dbg("TX interrupt on unsupported device!"); | ||
550 | goto unlock; | ||
551 | } | ||
552 | ene_tx_sample(dev); | ||
553 | } | ||
554 | |||
555 | if (!(irq_status & ENE_IRQ_RX)) | ||
556 | goto unlock; | ||
557 | |||
558 | |||
559 | if (dev->carrier_detect_enabled || debug) | ||
560 | carrier = ene_rx_sense_carrier(dev); | ||
561 | #if 0 | ||
562 | /* TODO */ | ||
563 | if (dev->carrier_detect_enabled && carrier) | ||
564 | ir_raw_event_report_frequency(dev->idev, carrier); | ||
565 | #endif | ||
566 | |||
567 | for (i = 0; i < ENE_SAMPLES_SIZE; i++) { | ||
568 | hw_value = ene_hw_read_reg(dev, | ||
569 | ENE_SAMPLE_BUFFER + dev->rx_pointer * 4 + i); | ||
570 | |||
571 | if (dev->rx_fan_input_inuse) { | ||
572 | /* read high part of the sample */ | ||
573 | hw_value |= ene_hw_read_reg(dev, | ||
574 | ENE_SAMPLE_BUFFER_FAN + | ||
575 | dev->rx_pointer * 4 + i) << 8; | ||
576 | pulse = hw_value & ENE_FAN_SMPL_PULS_MSK; | ||
577 | |||
578 | /* clear space bit, and other unused bits */ | ||
579 | hw_value &= ENE_FAN_VALUE_MASK; | ||
580 | hw_sample = hw_value * ENE_SAMPLE_PERIOD_FAN; | ||
581 | |||
582 | } else { | ||
583 | pulse = !(hw_value & ENE_SAMPLE_SPC_MASK); | ||
584 | hw_value &= ENE_SAMPLE_VALUE_MASK; | ||
585 | hw_sample = hw_value * sample_period; | ||
586 | |||
587 | if (dev->rx_period_adjust) { | ||
588 | hw_sample *= (100 - dev->rx_period_adjust); | ||
589 | hw_sample /= 100; | ||
590 | } | ||
591 | } | ||
592 | /* no more data */ | ||
593 | if (!(hw_value)) | ||
594 | break; | ||
595 | |||
596 | ene_dbg("RX: %d (%s)", hw_sample, pulse ? "pulse" : "space"); | ||
597 | |||
598 | |||
599 | ev.duration = hw_sample * 1000; | ||
600 | ev.pulse = pulse; | ||
601 | ir_raw_event_store_with_filter(dev->idev, &ev); | ||
602 | } | ||
603 | |||
604 | ir_raw_event_handle(dev->idev); | ||
605 | unlock: | ||
606 | spin_unlock_irqrestore(&dev->hw_lock, flags); | ||
607 | return retval; | ||
608 | } | ||
609 | |||
610 | /* Initialize default settings */ | ||
611 | static void ene_setup_settings(struct ene_device *dev) | ||
612 | { | ||
613 | dev->tx_period = 32; | ||
614 | dev->tx_duty_cycle = 25; /*%*/ | ||
615 | dev->transmitter_mask = 3; | ||
616 | |||
617 | /* Force learning mode if (input == 2), otherwise | ||
618 | let user set it with LIRC_SET_REC_CARRIER */ | ||
619 | dev->learning_enabled = | ||
620 | (input == 2 && dev->hw_learning_and_tx_capable); | ||
621 | |||
622 | dev->rx_pointer = -1; | ||
623 | |||
624 | } | ||
625 | |||
626 | /* outside interface: called on first open*/ | ||
627 | static int ene_open(void *data) | ||
628 | { | ||
629 | struct ene_device *dev = (struct ene_device *)data; | ||
630 | unsigned long flags; | ||
631 | |||
632 | spin_lock_irqsave(&dev->hw_lock, flags); | ||
633 | dev->in_use = 1; | ||
634 | ene_setup_settings(dev); | ||
635 | ene_rx_enable(dev); | ||
636 | spin_unlock_irqrestore(&dev->hw_lock, flags); | ||
637 | return 0; | ||
638 | } | ||
639 | |||
640 | /* outside interface: called on device close*/ | ||
641 | static void ene_close(void *data) | ||
642 | { | ||
643 | struct ene_device *dev = (struct ene_device *)data; | ||
644 | unsigned long flags; | ||
645 | spin_lock_irqsave(&dev->hw_lock, flags); | ||
646 | |||
647 | ene_rx_disable(dev); | ||
648 | dev->in_use = 0; | ||
649 | spin_unlock_irqrestore(&dev->hw_lock, flags); | ||
650 | } | ||
651 | |||
652 | /* outside interface: set transmitter mask */ | ||
653 | static int ene_set_tx_mask(void *data, u32 tx_mask) | ||
654 | { | ||
655 | struct ene_device *dev = (struct ene_device *)data; | ||
656 | unsigned long flags; | ||
657 | ene_dbg("TX: attempt to set transmitter mask %02x", tx_mask); | ||
658 | |||
659 | /* invalid txmask */ | ||
660 | if (!tx_mask || tx_mask & ~0x3) { | ||
661 | ene_dbg("TX: invalid mask"); | ||
662 | /* return count of transmitters */ | ||
663 | return 2; | ||
664 | } | ||
665 | |||
666 | spin_lock_irqsave(&dev->hw_lock, flags); | ||
667 | dev->transmitter_mask = tx_mask; | ||
668 | spin_unlock_irqrestore(&dev->hw_lock, flags); | ||
669 | return 0; | ||
670 | } | ||
671 | |||
672 | /* outside interface : set tx carrier */ | ||
673 | static int ene_set_tx_carrier(void *data, u32 carrier) | ||
674 | { | ||
675 | struct ene_device *dev = (struct ene_device *)data; | ||
676 | unsigned long flags; | ||
677 | u32 period = 1000000 / carrier; /* (1 / freq) (* # usec in 1 sec) */ | ||
678 | |||
679 | ene_dbg("TX: attempt to set tx carrier to %d kHz", carrier); | ||
680 | |||
681 | if (period && (period > ENE_TX_PERIOD_MAX || | ||
682 | period < ENE_TX_PERIOD_MIN)) { | ||
683 | |||
684 | ene_dbg("TX: out of range %d-%d carrier, " | ||
685 | "falling back to 32 kHz", | ||
686 | 1000 / ENE_TX_PERIOD_MIN, | ||
687 | 1000 / ENE_TX_PERIOD_MAX); | ||
688 | |||
689 | period = 32; /* this is just a coincidence!!! */ | ||
690 | } | ||
691 | ene_dbg("TX: set carrier to %d kHz", carrier); | ||
692 | |||
693 | spin_lock_irqsave(&dev->hw_lock, flags); | ||
694 | dev->tx_period = period; | ||
695 | spin_unlock_irqrestore(&dev->hw_lock, flags); | ||
696 | return 0; | ||
697 | } | ||
698 | |||
699 | |||
700 | /* outside interface: enable learning mode */ | ||
701 | static int ene_set_learning_mode(void *data, int enable) | ||
702 | { | ||
703 | struct ene_device *dev = (struct ene_device *)data; | ||
704 | unsigned long flags; | ||
705 | if (enable == dev->learning_enabled) | ||
706 | return 0; | ||
707 | |||
708 | spin_lock_irqsave(&dev->hw_lock, flags); | ||
709 | dev->learning_enabled = enable; | ||
710 | ene_rx_set_inputs(dev); | ||
711 | spin_unlock_irqrestore(&dev->hw_lock, flags); | ||
712 | return 0; | ||
713 | } | ||
714 | |||
715 | /* outside interface: set rec carrier */ | ||
716 | static int ene_set_rec_carrier(void *data, u32 min, u32 max) | ||
717 | { | ||
718 | struct ene_device *dev = (struct ene_device *)data; | ||
719 | ene_set_learning_mode(dev, | ||
720 | max > ENE_NORMAL_RX_HI || min < ENE_NORMAL_RX_LOW); | ||
721 | return 0; | ||
722 | } | ||
723 | |||
724 | /* outside interface: enable or disable idle mode */ | ||
725 | static void ene_rx_set_idle(void *data, int idle) | ||
726 | { | ||
727 | struct ene_device *dev = (struct ene_device *)data; | ||
728 | ene_dbg("%sabling idle mode", idle ? "en" : "dis"); | ||
729 | |||
730 | ene_hw_write_reg_mask(dev, ENE_CIR_SAMPLE_PERIOD, | ||
731 | (enable_idle && idle) ? 0 : ENE_CIR_SAMPLE_OVERFLOW, | ||
732 | ENE_CIR_SAMPLE_OVERFLOW); | ||
733 | } | ||
734 | |||
735 | |||
736 | /* outside interface: transmit */ | ||
737 | static int ene_transmit(void *data, int *buf, u32 n) | ||
738 | { | ||
739 | struct ene_device *dev = (struct ene_device *)data; | ||
740 | unsigned long flags; | ||
741 | |||
742 | dev->tx_buffer = buf; | ||
743 | dev->tx_len = n / sizeof(int); | ||
744 | dev->tx_pos = 0; | ||
745 | dev->tx_reg = 0; | ||
746 | dev->tx_done = 0; | ||
747 | dev->tx_sample = 0; | ||
748 | dev->tx_sample_pulse = 0; | ||
749 | |||
750 | ene_dbg("TX: %d samples", dev->tx_len); | ||
751 | |||
752 | spin_lock_irqsave(&dev->hw_lock, flags); | ||
753 | |||
754 | ene_tx_hw_set_transmiter_mask(dev); | ||
755 | ene_tx_prepare(dev); | ||
756 | |||
757 | /* Transmit first two samples */ | ||
758 | ene_tx_sample(dev); | ||
759 | ene_tx_sample(dev); | ||
760 | |||
761 | spin_unlock_irqrestore(&dev->hw_lock, flags); | ||
762 | |||
763 | if (wait_for_completion_timeout(&dev->tx_complete, 2 * HZ) == 0) { | ||
764 | ene_dbg("TX: timeout"); | ||
765 | spin_lock_irqsave(&dev->hw_lock, flags); | ||
766 | ene_tx_complete(dev); | ||
767 | spin_unlock_irqrestore(&dev->hw_lock, flags); | ||
768 | } else | ||
769 | ene_dbg("TX: done"); | ||
770 | return n; | ||
771 | } | ||
772 | |||
773 | |||
774 | /* probe entry */ | ||
775 | static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) | ||
776 | { | ||
777 | int error = -ENOMEM; | ||
778 | struct ir_dev_props *ir_props; | ||
779 | struct input_dev *input_dev; | ||
780 | struct ene_device *dev; | ||
781 | |||
782 | /* allocate memory */ | ||
783 | input_dev = input_allocate_device(); | ||
784 | ir_props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); | ||
785 | dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL); | ||
786 | |||
787 | if (!input_dev || !ir_props || !dev) | ||
788 | goto error; | ||
789 | |||
790 | /* validate resources */ | ||
791 | error = -ENODEV; | ||
792 | |||
793 | if (!pnp_port_valid(pnp_dev, 0) || | ||
794 | pnp_port_len(pnp_dev, 0) < ENE_MAX_IO) | ||
795 | goto error; | ||
796 | |||
797 | if (!pnp_irq_valid(pnp_dev, 0)) | ||
798 | goto error; | ||
799 | |||
800 | dev->hw_io = pnp_port_start(pnp_dev, 0); | ||
801 | dev->irq = pnp_irq(pnp_dev, 0); | ||
802 | spin_lock_init(&dev->hw_lock); | ||
803 | |||
804 | /* claim the resources */ | ||
805 | error = -EBUSY; | ||
806 | if (!request_region(dev->hw_io, ENE_MAX_IO, ENE_DRIVER_NAME)) | ||
807 | goto error; | ||
808 | |||
809 | if (request_irq(dev->irq, ene_isr, | ||
810 | IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) | ||
811 | goto error; | ||
812 | |||
813 | pnp_set_drvdata(pnp_dev, dev); | ||
814 | dev->pnp_dev = pnp_dev; | ||
815 | |||
816 | /* detect hardware version and features */ | ||
817 | error = ene_hw_detect(dev); | ||
818 | if (error) | ||
819 | goto error; | ||
820 | |||
821 | ene_setup_settings(dev); | ||
822 | |||
823 | if (!dev->hw_learning_and_tx_capable && txsim) { | ||
824 | dev->hw_learning_and_tx_capable = 1; | ||
825 | setup_timer(&dev->tx_sim_timer, ene_tx_irqsim, | ||
826 | (long unsigned int)dev); | ||
827 | ene_printk(KERN_WARNING, | ||
828 | "Simulation of TX activated\n"); | ||
829 | } | ||
830 | |||
831 | ir_props->driver_type = RC_DRIVER_IR_RAW; | ||
832 | ir_props->allowed_protos = IR_TYPE_ALL; | ||
833 | ir_props->priv = dev; | ||
834 | ir_props->open = ene_open; | ||
835 | ir_props->close = ene_close; | ||
836 | ir_props->min_timeout = ENE_MINGAP * 1000; | ||
837 | ir_props->max_timeout = ENE_MAXGAP * 1000; | ||
838 | ir_props->timeout = ENE_MAXGAP * 1000; | ||
839 | |||
840 | if (dev->hw_revision == ENE_HW_B) | ||
841 | ir_props->s_idle = ene_rx_set_idle; | ||
842 | |||
843 | |||
844 | dev->props = ir_props; | ||
845 | dev->idev = input_dev; | ||
846 | |||
847 | /* don't allow too short/long sample periods */ | ||
848 | if (sample_period < 5 || sample_period > 0x7F) | ||
849 | sample_period = -1; | ||
850 | |||
851 | /* choose default sample period */ | ||
852 | if (sample_period == -1) { | ||
853 | |||
854 | sample_period = 50; | ||
855 | |||
856 | /* on revB, hardware idle mode eats first sample | ||
857 | if we set too low sample period */ | ||
858 | if (dev->hw_revision == ENE_HW_B && enable_idle) | ||
859 | sample_period = 75; | ||
860 | } | ||
861 | |||
862 | ir_props->rx_resolution = sample_period * 1000; | ||
863 | |||
864 | if (dev->hw_learning_and_tx_capable) { | ||
865 | |||
866 | ir_props->s_learning_mode = ene_set_learning_mode; | ||
867 | |||
868 | if (input == 0) | ||
869 | ir_props->s_rx_carrier_range = ene_set_rec_carrier; | ||
870 | |||
871 | init_completion(&dev->tx_complete); | ||
872 | ir_props->tx_ir = ene_transmit; | ||
873 | ir_props->s_tx_mask = ene_set_tx_mask; | ||
874 | ir_props->s_tx_carrier = ene_set_tx_carrier; | ||
875 | ir_props->tx_resolution = ENE_TX_SMPL_PERIOD * 1000; | ||
876 | /* ir_props->s_carrier_report = ene_set_carrier_report; */ | ||
877 | } | ||
878 | |||
879 | |||
880 | device_set_wakeup_capable(&pnp_dev->dev, 1); | ||
881 | device_set_wakeup_enable(&pnp_dev->dev, 1); | ||
882 | |||
883 | if (dev->hw_learning_and_tx_capable) | ||
884 | input_dev->name = "ENE eHome Infrared Remote Transceiver"; | ||
885 | else | ||
886 | input_dev->name = "ENE eHome Infrared Remote Receiver"; | ||
887 | |||
888 | |||
889 | error = -ENODEV; | ||
890 | if (ir_input_register(input_dev, RC_MAP_RC6_MCE, ir_props, | ||
891 | ENE_DRIVER_NAME)) | ||
892 | goto error; | ||
893 | |||
894 | |||
895 | ene_printk(KERN_NOTICE, "driver has been succesfully loaded\n"); | ||
896 | return 0; | ||
897 | error: | ||
898 | if (dev->irq) | ||
899 | free_irq(dev->irq, dev); | ||
900 | if (dev->hw_io) | ||
901 | release_region(dev->hw_io, ENE_MAX_IO); | ||
902 | |||
903 | input_free_device(input_dev); | ||
904 | kfree(ir_props); | ||
905 | kfree(dev); | ||
906 | return error; | ||
907 | } | ||
908 | |||
909 | /* main unload function */ | ||
910 | static void ene_remove(struct pnp_dev *pnp_dev) | ||
911 | { | ||
912 | struct ene_device *dev = pnp_get_drvdata(pnp_dev); | ||
913 | unsigned long flags; | ||
914 | |||
915 | spin_lock_irqsave(&dev->hw_lock, flags); | ||
916 | ene_rx_disable(dev); | ||
917 | spin_unlock_irqrestore(&dev->hw_lock, flags); | ||
918 | |||
919 | free_irq(dev->irq, dev); | ||
920 | release_region(dev->hw_io, ENE_MAX_IO); | ||
921 | ir_input_unregister(dev->idev); | ||
922 | kfree(dev->props); | ||
923 | kfree(dev); | ||
924 | } | ||
925 | |||
926 | /* enable wake on IR (wakes on specific button on original remote) */ | ||
927 | static void ene_enable_wake(struct ene_device *dev, int enable) | ||
928 | { | ||
929 | enable = enable && device_may_wakeup(&dev->pnp_dev->dev); | ||
930 | |||
931 | ene_dbg("wake on IR %s", enable ? "enabled" : "disabled"); | ||
932 | |||
933 | ene_hw_write_reg_mask(dev, ENE_FW1, enable ? | ||
934 | ENE_FW1_WAKE : 0, ENE_FW1_WAKE); | ||
935 | } | ||
936 | |||
937 | #ifdef CONFIG_PM | ||
938 | static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state) | ||
939 | { | ||
940 | struct ene_device *dev = pnp_get_drvdata(pnp_dev); | ||
941 | ene_enable_wake(dev, 1); | ||
942 | return 0; | ||
943 | } | ||
944 | |||
945 | static int ene_resume(struct pnp_dev *pnp_dev) | ||
946 | { | ||
947 | struct ene_device *dev = pnp_get_drvdata(pnp_dev); | ||
948 | if (dev->in_use) | ||
949 | ene_rx_enable(dev); | ||
950 | |||
951 | ene_enable_wake(dev, 0); | ||
952 | return 0; | ||
953 | } | ||
954 | #endif | ||
955 | |||
956 | static void ene_shutdown(struct pnp_dev *pnp_dev) | ||
957 | { | ||
958 | struct ene_device *dev = pnp_get_drvdata(pnp_dev); | ||
959 | ene_enable_wake(dev, 1); | ||
960 | } | ||
961 | |||
962 | static const struct pnp_device_id ene_ids[] = { | ||
963 | {.id = "ENE0100",}, | ||
964 | {.id = "ENE0200",}, | ||
965 | {.id = "ENE0201",}, | ||
966 | {.id = "ENE0202",}, | ||
967 | {}, | ||
968 | }; | ||
969 | |||
970 | static struct pnp_driver ene_driver = { | ||
971 | .name = ENE_DRIVER_NAME, | ||
972 | .id_table = ene_ids, | ||
973 | .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, | ||
974 | |||
975 | .probe = ene_probe, | ||
976 | .remove = __devexit_p(ene_remove), | ||
977 | #ifdef CONFIG_PM | ||
978 | .suspend = ene_suspend, | ||
979 | .resume = ene_resume, | ||
980 | #endif | ||
981 | .shutdown = ene_shutdown, | ||
982 | }; | ||
983 | |||
984 | static int __init ene_init(void) | ||
985 | { | ||
986 | return pnp_register_driver(&ene_driver); | ||
987 | } | ||
988 | |||
989 | static void ene_exit(void) | ||
990 | { | ||
991 | pnp_unregister_driver(&ene_driver); | ||
992 | } | ||
993 | |||
994 | module_param(sample_period, int, S_IRUGO); | ||
995 | MODULE_PARM_DESC(sample_period, "Hardware sample period (50 us default)"); | ||
996 | |||
997 | module_param(enable_idle, bool, S_IRUGO | S_IWUSR); | ||
998 | MODULE_PARM_DESC(enable_idle, | ||
999 | "Enables turning off signal sampling after long inactivity time; " | ||
1000 | "if disabled might help detecting input signal (default: enabled)" | ||
1001 | " (KB3926B only)"); | ||
1002 | |||
1003 | module_param(input, bool, S_IRUGO); | ||
1004 | MODULE_PARM_DESC(input, "select which input to use " | ||
1005 | "0 - auto, 1 - standard, 2 - wideband(KB3926C+)"); | ||
1006 | |||
1007 | module_param(debug, int, S_IRUGO | S_IWUSR); | ||
1008 | MODULE_PARM_DESC(debug, "Enable debug (debug=2 verbose debug output)"); | ||
1009 | |||
1010 | module_param(txsim, bool, S_IRUGO); | ||
1011 | MODULE_PARM_DESC(txsim, | ||
1012 | "Simulate TX features on unsupported hardware (dangerous)"); | ||
1013 | |||
1014 | MODULE_DEVICE_TABLE(pnp, ene_ids); | ||
1015 | MODULE_DESCRIPTION | ||
1016 | ("Infrared input driver for KB3926B/KB3926C/KB3926D " | ||
1017 | "(aka ENE0100/ENE0200/ENE0201) CIR port"); | ||
1018 | |||
1019 | MODULE_AUTHOR("Maxim Levitsky"); | ||
1020 | MODULE_LICENSE("GPL"); | ||
1021 | |||
1022 | module_init(ene_init); | ||
1023 | module_exit(ene_exit); | ||
diff --git a/drivers/media/IR/ene_ir.h b/drivers/media/IR/ene_ir.h new file mode 100644 index 000000000000..54c76af0d033 --- /dev/null +++ b/drivers/media/IR/ene_ir.h | |||
@@ -0,0 +1,235 @@ | |||
1 | /* | ||
2 | * driver for ENE KB3926 B/C/D CIR (also known as ENE0XXX) | ||
3 | * | ||
4 | * Copyright (C) 2010 Maxim Levitsky <maximlevitsky@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation; either version 2 of the | ||
9 | * License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
19 | * USA | ||
20 | */ | ||
21 | #include <linux/spinlock.h> | ||
22 | |||
23 | |||
24 | /* hardware address */ | ||
25 | #define ENE_STATUS 0 /* hardware status - unused */ | ||
26 | #define ENE_ADDR_HI 1 /* hi byte of register address */ | ||
27 | #define ENE_ADDR_LO 2 /* low byte of register address */ | ||
28 | #define ENE_IO 3 /* read/write window */ | ||
29 | #define ENE_MAX_IO 4 | ||
30 | |||
31 | /* 8 bytes of samples, divided in 2 halfs*/ | ||
32 | #define ENE_SAMPLE_BUFFER 0xF8F0 /* regular sample buffer */ | ||
33 | #define ENE_SAMPLE_SPC_MASK 0x80 /* sample is space */ | ||
34 | #define ENE_SAMPLE_VALUE_MASK 0x7F | ||
35 | #define ENE_SAMPLE_OVERFLOW 0x7F | ||
36 | #define ENE_SAMPLES_SIZE 4 | ||
37 | |||
38 | /* fan input sample buffer */ | ||
39 | #define ENE_SAMPLE_BUFFER_FAN 0xF8FB /* this buffer holds high byte of */ | ||
40 | /* each sample of normal buffer */ | ||
41 | #define ENE_FAN_SMPL_PULS_MSK 0x8000 /* this bit of combined sample */ | ||
42 | /* if set, says that sample is pulse */ | ||
43 | #define ENE_FAN_VALUE_MASK 0x0FFF /* mask for valid bits of the value */ | ||
44 | |||
45 | /* first firmware register */ | ||
46 | #define ENE_FW1 0xF8F8 | ||
47 | #define ENE_FW1_ENABLE 0x01 /* enable fw processing */ | ||
48 | #define ENE_FW1_TXIRQ 0x02 /* TX interrupt pending */ | ||
49 | #define ENE_FW1_WAKE 0x40 /* enable wake from S3 */ | ||
50 | #define ENE_FW1_IRQ 0x80 /* enable interrupt */ | ||
51 | |||
52 | /* second firmware register */ | ||
53 | #define ENE_FW2 0xF8F9 | ||
54 | #define ENE_FW2_BUF_HIGH 0x01 /* which half of the buffer to read */ | ||
55 | #define ENE_FW2_IRQ_CLR 0x04 /* clear this on IRQ */ | ||
56 | #define ENE_FW2_GP40_AS_LEARN 0x08 /* normal input is used as */ | ||
57 | /* learning input */ | ||
58 | #define ENE_FW2_FAN_AS_NRML_IN 0x40 /* fan is used as normal input */ | ||
59 | #define ENE_FW2_LEARNING 0x80 /* hardware supports learning and TX */ | ||
60 | |||
61 | /* transmitter ports */ | ||
62 | #define ENE_TX_PORT2 0xFC01 /* this enables one or both */ | ||
63 | #define ENE_TX_PORT2_EN 0x20 /* TX ports */ | ||
64 | #define ENE_TX_PORT1 0xFC08 | ||
65 | #define ENE_TX_PORT1_EN 0x02 | ||
66 | |||
67 | /* IRQ registers block (for revision B) */ | ||
68 | #define ENEB_IRQ 0xFD09 /* IRQ number */ | ||
69 | #define ENEB_IRQ_UNK1 0xFD17 /* unknown setting = 1 */ | ||
70 | #define ENEB_IRQ_STATUS 0xFD80 /* irq status */ | ||
71 | #define ENEB_IRQ_STATUS_IR 0x20 /* IR irq */ | ||
72 | |||
73 | /* fan as input settings - only if learning capable */ | ||
74 | #define ENE_FAN_AS_IN1 0xFE30 /* fan init reg 1 */ | ||
75 | #define ENE_FAN_AS_IN1_EN 0xCD | ||
76 | #define ENE_FAN_AS_IN2 0xFE31 /* fan init reg 2 */ | ||
77 | #define ENE_FAN_AS_IN2_EN 0x03 | ||
78 | #define ENE_SAMPLE_PERIOD_FAN 61 /* fan input has fixed sample period */ | ||
79 | |||
80 | /* IRQ registers block (for revision C,D) */ | ||
81 | #define ENEC_IRQ 0xFE9B /* new irq settings register */ | ||
82 | #define ENEC_IRQ_MASK 0x0F /* irq number mask */ | ||
83 | #define ENEC_IRQ_UNK_EN 0x10 /* always enabled */ | ||
84 | #define ENEC_IRQ_STATUS 0x20 /* irq status and ACK */ | ||
85 | |||
86 | /* CIR block settings */ | ||
87 | #define ENE_CIR_CONF1 0xFEC0 | ||
88 | #define ENE_CIR_CONF1_TX_CLEAR 0x01 /* clear that on revC */ | ||
89 | /* while transmitting */ | ||
90 | #define ENE_CIR_CONF1_RX_ON 0x07 /* normal receiver enabled */ | ||
91 | #define ENE_CIR_CONF1_LEARN1 0x08 /* enabled on learning mode */ | ||
92 | #define ENE_CIR_CONF1_TX_ON 0x30 /* enabled on transmit */ | ||
93 | #define ENE_CIR_CONF1_TX_CARR 0x80 /* send TX carrier or not */ | ||
94 | |||
95 | #define ENE_CIR_CONF2 0xFEC1 /* unknown setting = 0 */ | ||
96 | #define ENE_CIR_CONF2_LEARN2 0x10 /* set on enable learning */ | ||
97 | #define ENE_CIR_CONF2_GPIO40DIS 0x20 /* disable input via gpio40 */ | ||
98 | |||
99 | #define ENE_CIR_SAMPLE_PERIOD 0xFEC8 /* sample period in us */ | ||
100 | #define ENE_CIR_SAMPLE_OVERFLOW 0x80 /* interrupt on overflows if set */ | ||
101 | |||
102 | |||
103 | /* Two byte tx buffer */ | ||
104 | #define ENE_TX_INPUT1 0xFEC9 | ||
105 | #define ENE_TX_INPUT2 0xFECA | ||
106 | #define ENE_TX_PULSE_MASK 0x80 /* Transmitted sample is pulse */ | ||
107 | #define ENE_TX_SMLP_MASK 0x7F | ||
108 | #define ENE_TX_SMPL_PERIOD 50 /* transmit sample period - fixed */ | ||
109 | |||
110 | |||
111 | /* Unknown TX setting - TX sample period ??? */ | ||
112 | #define ENE_TX_UNK1 0xFECB /* set to 0x63 */ | ||
113 | |||
114 | /* Current received carrier period */ | ||
115 | #define ENE_RX_CARRIER 0xFECC /* RX period (500 ns) */ | ||
116 | #define ENE_RX_CARRIER_VALID 0x80 /* Register content valid */ | ||
117 | |||
118 | |||
119 | /* TX period (1/carrier) */ | ||
120 | #define ENE_TX_PERIOD 0xFECE /* TX period (500 ns) */ | ||
121 | #define ENE_TX_PERIOD_UNKBIT 0x80 /* This bit set on transmit*/ | ||
122 | #define ENE_TX_PERIOD_PULSE 0xFECF /* TX pulse period (500 ns)*/ | ||
123 | |||
124 | /* Hardware versions */ | ||
125 | #define ENE_HW_VERSION 0xFF00 /* hardware revision */ | ||
126 | #define ENE_PLLFRH 0xFF16 | ||
127 | #define ENE_PLLFRL 0xFF17 | ||
128 | |||
129 | #define ENE_HW_UNK 0xFF1D | ||
130 | #define ENE_HW_UNK_CLR 0x04 | ||
131 | #define ENE_HW_VER_MAJOR 0xFF1E /* chip version */ | ||
132 | #define ENE_HW_VER_MINOR 0xFF1F | ||
133 | #define ENE_HW_VER_OLD 0xFD00 | ||
134 | |||
135 | /* Normal/Learning carrier ranges - only valid if we have learning input*/ | ||
136 | /* TODO: test */ | ||
137 | #define ENE_NORMAL_RX_LOW 34 | ||
138 | #define ENE_NORMAL_RX_HI 38 | ||
139 | |||
140 | /* Tx carrier range */ | ||
141 | /* Hardware might be able to do more, but this range is enough for | ||
142 | all purposes */ | ||
143 | #define ENE_TX_PERIOD_MAX 32 /* corresponds to 29.4 kHz */ | ||
144 | #define ENE_TX_PERIOD_MIN 16 /* corrsponds to 62.5 kHz */ | ||
145 | |||
146 | |||
147 | |||
148 | /* Minimal and maximal gaps */ | ||
149 | |||
150 | /* Normal case: | ||
151 | Minimal gap is 0x7F * sample period | ||
152 | Maximum gap depends on hardware. | ||
153 | For KB3926B, it is unlimited, for newer models its around | ||
154 | 250000, after which HW stops sending samples, and that is | ||
155 | not possible to change */ | ||
156 | |||
157 | /* Fan case: | ||
158 | Both minimal and maximal gaps are same, and equal to 0xFFF * 0x61 | ||
159 | And there is nothing to change this setting | ||
160 | */ | ||
161 | |||
162 | #define ENE_MAXGAP 250000 | ||
163 | #define ENE_MINGAP (127 * sample_period) | ||
164 | |||
165 | /******************************************************************************/ | ||
166 | |||
167 | #define ENE_DRIVER_NAME "ene_ir" | ||
168 | |||
169 | #define ENE_IRQ_RX 1 | ||
170 | #define ENE_IRQ_TX 2 | ||
171 | |||
172 | #define ENE_HW_B 1 /* 3926B */ | ||
173 | #define ENE_HW_C 2 /* 3926C */ | ||
174 | #define ENE_HW_D 3 /* 3926D */ | ||
175 | |||
176 | #define ene_printk(level, text, ...) \ | ||
177 | printk(level ENE_DRIVER_NAME ": " text, ## __VA_ARGS__) | ||
178 | |||
179 | #define ene_dbg(text, ...) \ | ||
180 | if (debug) \ | ||
181 | printk(KERN_DEBUG \ | ||
182 | ENE_DRIVER_NAME ": " text "\n" , ## __VA_ARGS__) | ||
183 | |||
184 | #define ene_dbg_verbose(text, ...) \ | ||
185 | if (debug > 1) \ | ||
186 | printk(KERN_DEBUG \ | ||
187 | ENE_DRIVER_NAME ": " text "\n" , ## __VA_ARGS__) | ||
188 | |||
189 | |||
190 | struct ene_device { | ||
191 | struct pnp_dev *pnp_dev; | ||
192 | struct input_dev *idev; | ||
193 | struct ir_dev_props *props; | ||
194 | int in_use; | ||
195 | |||
196 | /* hw IO settings */ | ||
197 | unsigned long hw_io; | ||
198 | int irq; | ||
199 | spinlock_t hw_lock; | ||
200 | |||
201 | /* HW features */ | ||
202 | int hw_revision; /* hardware revision */ | ||
203 | bool hw_learning_and_tx_capable; /* learning capable */ | ||
204 | bool hw_gpio40_learning; /* gpio40 is learning */ | ||
205 | bool hw_fan_as_normal_input; /* fan input is used as */ | ||
206 | /* regular input */ | ||
207 | /* HW state*/ | ||
208 | int rx_pointer; /* hw pointer to rx buffer */ | ||
209 | bool rx_fan_input_inuse; /* is fan input in use for rx*/ | ||
210 | int tx_reg; /* current reg used for TX */ | ||
211 | u8 saved_conf1; /* saved FEC0 reg */ | ||
212 | |||
213 | /* TX sample handling */ | ||
214 | unsigned int tx_sample; /* current sample for TX */ | ||
215 | bool tx_sample_pulse; /* current sample is pulse */ | ||
216 | |||
217 | /* TX buffer */ | ||
218 | int *tx_buffer; /* input samples buffer*/ | ||
219 | int tx_pos; /* position in that bufer */ | ||
220 | int tx_len; /* current len of tx buffer */ | ||
221 | int tx_done; /* done transmitting */ | ||
222 | /* one more sample pending*/ | ||
223 | struct completion tx_complete; /* TX completion */ | ||
224 | struct timer_list tx_sim_timer; | ||
225 | |||
226 | /* TX settings */ | ||
227 | int tx_period; | ||
228 | int tx_duty_cycle; | ||
229 | int transmitter_mask; | ||
230 | |||
231 | /* RX settings */ | ||
232 | bool learning_enabled; /* learning input enabled */ | ||
233 | bool carrier_detect_enabled; /* carrier detect enabled */ | ||
234 | int rx_period_adjust; | ||
235 | }; | ||
diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c index 65c125e44e96..c185422ef28c 100644 --- a/drivers/media/IR/imon.c +++ b/drivers/media/IR/imon.c | |||
@@ -87,7 +87,6 @@ static ssize_t lcd_write(struct file *file, const char *buf, | |||
87 | struct imon_context { | 87 | struct imon_context { |
88 | struct device *dev; | 88 | struct device *dev; |
89 | struct ir_dev_props *props; | 89 | struct ir_dev_props *props; |
90 | struct ir_input_dev *ir; | ||
91 | /* Newer devices have two interfaces */ | 90 | /* Newer devices have two interfaces */ |
92 | struct usb_device *usbdev_intf0; | 91 | struct usb_device *usbdev_intf0; |
93 | struct usb_device *usbdev_intf1; | 92 | struct usb_device *usbdev_intf1; |
@@ -1656,7 +1655,6 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx) | |||
1656 | { | 1655 | { |
1657 | struct input_dev *idev; | 1656 | struct input_dev *idev; |
1658 | struct ir_dev_props *props; | 1657 | struct ir_dev_props *props; |
1659 | struct ir_input_dev *ir; | ||
1660 | int ret, i; | 1658 | int ret, i; |
1661 | 1659 | ||
1662 | idev = input_allocate_device(); | 1660 | idev = input_allocate_device(); |
@@ -1671,12 +1669,6 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx) | |||
1671 | goto props_alloc_failed; | 1669 | goto props_alloc_failed; |
1672 | } | 1670 | } |
1673 | 1671 | ||
1674 | ir = kzalloc(sizeof(struct ir_input_dev), GFP_KERNEL); | ||
1675 | if (!ir) { | ||
1676 | dev_err(ictx->dev, "remote ir input dev allocation failed\n"); | ||
1677 | goto ir_dev_alloc_failed; | ||
1678 | } | ||
1679 | |||
1680 | snprintf(ictx->name_idev, sizeof(ictx->name_idev), | 1672 | snprintf(ictx->name_idev, sizeof(ictx->name_idev), |
1681 | "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product); | 1673 | "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product); |
1682 | idev->name = ictx->name_idev; | 1674 | idev->name = ictx->name_idev; |
@@ -1706,14 +1698,9 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx) | |||
1706 | props->change_protocol = imon_ir_change_protocol; | 1698 | props->change_protocol = imon_ir_change_protocol; |
1707 | ictx->props = props; | 1699 | ictx->props = props; |
1708 | 1700 | ||
1709 | ictx->ir = ir; | ||
1710 | memcpy(&ir->dev, ictx->dev, sizeof(struct device)); | ||
1711 | |||
1712 | usb_to_input_id(ictx->usbdev_intf0, &idev->id); | 1701 | usb_to_input_id(ictx->usbdev_intf0, &idev->id); |
1713 | idev->dev.parent = ictx->dev; | 1702 | idev->dev.parent = ictx->dev; |
1714 | 1703 | ||
1715 | input_set_drvdata(idev, ir); | ||
1716 | |||
1717 | ret = ir_input_register(idev, RC_MAP_IMON_PAD, props, MOD_NAME); | 1704 | ret = ir_input_register(idev, RC_MAP_IMON_PAD, props, MOD_NAME); |
1718 | if (ret < 0) { | 1705 | if (ret < 0) { |
1719 | dev_err(ictx->dev, "remote input dev register failed\n"); | 1706 | dev_err(ictx->dev, "remote input dev register failed\n"); |
@@ -1723,8 +1710,6 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx) | |||
1723 | return idev; | 1710 | return idev; |
1724 | 1711 | ||
1725 | idev_register_failed: | 1712 | idev_register_failed: |
1726 | kfree(ir); | ||
1727 | ir_dev_alloc_failed: | ||
1728 | kfree(props); | 1713 | kfree(props); |
1729 | props_alloc_failed: | 1714 | props_alloc_failed: |
1730 | input_free_device(idev); | 1715 | input_free_device(idev); |
@@ -1944,7 +1929,6 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf) | |||
1944 | 1929 | ||
1945 | urb_submit_failed: | 1930 | urb_submit_failed: |
1946 | ir_input_unregister(ictx->idev); | 1931 | ir_input_unregister(ictx->idev); |
1947 | input_free_device(ictx->idev); | ||
1948 | idev_setup_failed: | 1932 | idev_setup_failed: |
1949 | find_endpoint_failed: | 1933 | find_endpoint_failed: |
1950 | mutex_unlock(&ictx->lock); | 1934 | mutex_unlock(&ictx->lock); |
@@ -2014,10 +1998,8 @@ static struct imon_context *imon_init_intf1(struct usb_interface *intf, | |||
2014 | return ictx; | 1998 | return ictx; |
2015 | 1999 | ||
2016 | urb_submit_failed: | 2000 | urb_submit_failed: |
2017 | if (ictx->touch) { | 2001 | if (ictx->touch) |
2018 | input_unregister_device(ictx->touch); | 2002 | input_unregister_device(ictx->touch); |
2019 | input_free_device(ictx->touch); | ||
2020 | } | ||
2021 | touch_setup_failed: | 2003 | touch_setup_failed: |
2022 | find_endpoint_failed: | 2004 | find_endpoint_failed: |
2023 | mutex_unlock(&ictx->lock); | 2005 | mutex_unlock(&ictx->lock); |
diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h index babd52061bc3..a85a8c7c905a 100644 --- a/drivers/media/IR/ir-core-priv.h +++ b/drivers/media/IR/ir-core-priv.h | |||
@@ -32,7 +32,7 @@ struct ir_raw_handler { | |||
32 | 32 | ||
33 | struct ir_raw_event_ctrl { | 33 | struct ir_raw_event_ctrl { |
34 | struct list_head list; /* to keep track of raw clients */ | 34 | struct list_head list; /* to keep track of raw clients */ |
35 | struct work_struct rx_work; /* for the rx decoding workqueue */ | 35 | struct task_struct *thread; |
36 | struct kfifo kfifo; /* fifo for the pulse/space durations */ | 36 | struct kfifo kfifo; /* fifo for the pulse/space durations */ |
37 | ktime_t last_event; /* when last event occurred */ | 37 | ktime_t last_event; /* when last event occurred */ |
38 | enum raw_event_type last_type; /* last event type */ | 38 | enum raw_event_type last_type; /* last event type */ |
@@ -41,10 +41,13 @@ struct ir_raw_event_ctrl { | |||
41 | 41 | ||
42 | /* raw decoder state follows */ | 42 | /* raw decoder state follows */ |
43 | struct ir_raw_event prev_ev; | 43 | struct ir_raw_event prev_ev; |
44 | struct ir_raw_event this_ev; | ||
44 | struct nec_dec { | 45 | struct nec_dec { |
45 | int state; | 46 | int state; |
46 | unsigned count; | 47 | unsigned count; |
47 | u32 bits; | 48 | u32 bits; |
49 | bool is_nec_x; | ||
50 | bool necx_repeat; | ||
48 | } nec; | 51 | } nec; |
49 | struct rc5_dec { | 52 | struct rc5_dec { |
50 | int state; | 53 | int state; |
@@ -76,7 +79,7 @@ struct ir_raw_event_ctrl { | |||
76 | struct lirc_codec { | 79 | struct lirc_codec { |
77 | struct ir_input_dev *ir_dev; | 80 | struct ir_input_dev *ir_dev; |
78 | struct lirc_driver *drv; | 81 | struct lirc_driver *drv; |
79 | int lircdata; | 82 | int carrier_low; |
80 | } lirc; | 83 | } lirc; |
81 | }; | 84 | }; |
82 | 85 | ||
@@ -104,10 +107,9 @@ static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration) | |||
104 | ev->duration -= duration; | 107 | ev->duration -= duration; |
105 | } | 108 | } |
106 | 109 | ||
107 | #define TO_US(duration) (((duration) + 500) / 1000) | 110 | #define TO_US(duration) DIV_ROUND_CLOSEST((duration), 1000) |
108 | #define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space") | 111 | #define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space") |
109 | #define IS_RESET(ev) (ev.duration == 0) | 112 | #define IS_RESET(ev) (ev.duration == 0) |
110 | |||
111 | /* | 113 | /* |
112 | * Routines from ir-sysfs.c - Meant to be called only internally inside | 114 | * Routines from ir-sysfs.c - Meant to be called only internally inside |
113 | * ir-core | 115 | * ir-core |
@@ -126,7 +128,8 @@ int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); | |||
126 | void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); | 128 | void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); |
127 | void ir_raw_init(void); | 129 | void ir_raw_init(void); |
128 | 130 | ||
129 | 131 | int ir_rcmap_init(void); | |
132 | void ir_rcmap_cleanup(void); | ||
130 | /* | 133 | /* |
131 | * Decoder initialization code | 134 | * Decoder initialization code |
132 | * | 135 | * |
diff --git a/drivers/media/IR/ir-jvc-decoder.c b/drivers/media/IR/ir-jvc-decoder.c index 8894d8b36048..77a89c4de014 100644 --- a/drivers/media/IR/ir-jvc-decoder.c +++ b/drivers/media/IR/ir-jvc-decoder.c | |||
@@ -32,6 +32,7 @@ enum jvc_state { | |||
32 | STATE_BIT_SPACE, | 32 | STATE_BIT_SPACE, |
33 | STATE_TRAILER_PULSE, | 33 | STATE_TRAILER_PULSE, |
34 | STATE_TRAILER_SPACE, | 34 | STATE_TRAILER_SPACE, |
35 | STATE_CHECK_REPEAT, | ||
35 | }; | 36 | }; |
36 | 37 | ||
37 | /** | 38 | /** |
@@ -60,6 +61,7 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev) | |||
60 | IR_dprintk(2, "JVC decode started at state %d (%uus %s)\n", | 61 | IR_dprintk(2, "JVC decode started at state %d (%uus %s)\n", |
61 | data->state, TO_US(ev.duration), TO_STR(ev.pulse)); | 62 | data->state, TO_US(ev.duration), TO_STR(ev.pulse)); |
62 | 63 | ||
64 | again: | ||
63 | switch (data->state) { | 65 | switch (data->state) { |
64 | 66 | ||
65 | case STATE_INACTIVE: | 67 | case STATE_INACTIVE: |
@@ -149,8 +151,18 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev) | |||
149 | } | 151 | } |
150 | 152 | ||
151 | data->count = 0; | 153 | data->count = 0; |
152 | data->state = STATE_BIT_PULSE; | 154 | data->state = STATE_CHECK_REPEAT; |
153 | return 0; | 155 | return 0; |
156 | |||
157 | case STATE_CHECK_REPEAT: | ||
158 | if (!ev.pulse) | ||
159 | break; | ||
160 | |||
161 | if (eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2)) | ||
162 | data->state = STATE_INACTIVE; | ||
163 | else | ||
164 | data->state = STATE_BIT_PULSE; | ||
165 | goto again; | ||
154 | } | 166 | } |
155 | 167 | ||
156 | out: | 168 | out: |
diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index 15a0f192d413..7e82a9df726b 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c | |||
@@ -339,6 +339,8 @@ void ir_repeat(struct input_dev *dev) | |||
339 | 339 | ||
340 | spin_lock_irqsave(&ir->keylock, flags); | 340 | spin_lock_irqsave(&ir->keylock, flags); |
341 | 341 | ||
342 | input_event(dev, EV_MSC, MSC_SCAN, ir->last_scancode); | ||
343 | |||
342 | if (!ir->keypressed) | 344 | if (!ir->keypressed) |
343 | goto out; | 345 | goto out; |
344 | 346 | ||
@@ -370,6 +372,8 @@ void ir_keydown(struct input_dev *dev, int scancode, u8 toggle) | |||
370 | 372 | ||
371 | spin_lock_irqsave(&ir->keylock, flags); | 373 | spin_lock_irqsave(&ir->keylock, flags); |
372 | 374 | ||
375 | input_event(dev, EV_MSC, MSC_SCAN, scancode); | ||
376 | |||
373 | /* Repeat event? */ | 377 | /* Repeat event? */ |
374 | if (ir->keypressed && | 378 | if (ir->keypressed && |
375 | ir->last_scancode == scancode && | 379 | ir->last_scancode == scancode && |
@@ -383,9 +387,11 @@ void ir_keydown(struct input_dev *dev, int scancode, u8 toggle) | |||
383 | ir->last_toggle = toggle; | 387 | ir->last_toggle = toggle; |
384 | ir->last_keycode = keycode; | 388 | ir->last_keycode = keycode; |
385 | 389 | ||
390 | |||
386 | if (keycode == KEY_RESERVED) | 391 | if (keycode == KEY_RESERVED) |
387 | goto out; | 392 | goto out; |
388 | 393 | ||
394 | |||
389 | /* Register a keypress */ | 395 | /* Register a keypress */ |
390 | ir->keypressed = true; | 396 | ir->keypressed = true; |
391 | IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n", | 397 | IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n", |
@@ -428,7 +434,7 @@ static void ir_close(struct input_dev *input_dev) | |||
428 | */ | 434 | */ |
429 | int __ir_input_register(struct input_dev *input_dev, | 435 | int __ir_input_register(struct input_dev *input_dev, |
430 | const struct ir_scancode_table *rc_tab, | 436 | const struct ir_scancode_table *rc_tab, |
431 | const struct ir_dev_props *props, | 437 | struct ir_dev_props *props, |
432 | const char *driver_name) | 438 | const char *driver_name) |
433 | { | 439 | { |
434 | struct ir_input_dev *ir_dev; | 440 | struct ir_input_dev *ir_dev; |
@@ -480,6 +486,8 @@ int __ir_input_register(struct input_dev *input_dev, | |||
480 | 486 | ||
481 | set_bit(EV_KEY, input_dev->evbit); | 487 | set_bit(EV_KEY, input_dev->evbit); |
482 | set_bit(EV_REP, input_dev->evbit); | 488 | set_bit(EV_REP, input_dev->evbit); |
489 | set_bit(EV_MSC, input_dev->evbit); | ||
490 | set_bit(MSC_SCAN, input_dev->mscbit); | ||
483 | 491 | ||
484 | if (ir_setkeytable(input_dev, &ir_dev->rc_tab, rc_tab)) { | 492 | if (ir_setkeytable(input_dev, &ir_dev->rc_tab, rc_tab)) { |
485 | rc = -ENOMEM; | 493 | rc = -ENOMEM; |
@@ -499,7 +507,8 @@ int __ir_input_register(struct input_dev *input_dev, | |||
499 | 507 | ||
500 | IR_dprintk(1, "Registered input device on %s for %s remote%s.\n", | 508 | IR_dprintk(1, "Registered input device on %s for %s remote%s.\n", |
501 | driver_name, rc_tab->name, | 509 | driver_name, rc_tab->name, |
502 | ir_dev->props->driver_type == RC_DRIVER_IR_RAW ? " in raw mode" : ""); | 510 | (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ? |
511 | " in raw mode" : ""); | ||
503 | 512 | ||
504 | return 0; | 513 | return 0; |
505 | 514 | ||
diff --git a/drivers/media/IR/ir-lirc-codec.c b/drivers/media/IR/ir-lirc-codec.c index 3ba482d96c4b..77b5946413c0 100644 --- a/drivers/media/IR/ir-lirc-codec.c +++ b/drivers/media/IR/ir-lirc-codec.c | |||
@@ -32,6 +32,7 @@ | |||
32 | static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) | 32 | static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) |
33 | { | 33 | { |
34 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | 34 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); |
35 | int sample; | ||
35 | 36 | ||
36 | if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC)) | 37 | if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC)) |
37 | return 0; | 38 | return 0; |
@@ -39,18 +40,20 @@ static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) | |||
39 | if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf) | 40 | if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf) |
40 | return -EINVAL; | 41 | return -EINVAL; |
41 | 42 | ||
43 | if (IS_RESET(ev)) | ||
44 | return 0; | ||
45 | |||
42 | IR_dprintk(2, "LIRC data transfer started (%uus %s)\n", | 46 | IR_dprintk(2, "LIRC data transfer started (%uus %s)\n", |
43 | TO_US(ev.duration), TO_STR(ev.pulse)); | 47 | TO_US(ev.duration), TO_STR(ev.pulse)); |
44 | 48 | ||
45 | ir_dev->raw->lirc.lircdata += ev.duration / 1000; | 49 | sample = ev.duration / 1000; |
46 | if (ev.pulse) | 50 | if (ev.pulse) |
47 | ir_dev->raw->lirc.lircdata |= PULSE_BIT; | 51 | sample |= PULSE_BIT; |
48 | 52 | ||
49 | lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, | 53 | lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, |
50 | (unsigned char *) &ir_dev->raw->lirc.lircdata); | 54 | (unsigned char *) &sample); |
51 | wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll); | 55 | wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll); |
52 | 56 | ||
53 | ir_dev->raw->lirc.lircdata = 0; | ||
54 | 57 | ||
55 | return 0; | 58 | return 0; |
56 | } | 59 | } |
@@ -92,13 +95,14 @@ out: | |||
92 | return ret; | 95 | return ret; |
93 | } | 96 | } |
94 | 97 | ||
95 | static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) | 98 | static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, |
99 | unsigned long __user arg) | ||
96 | { | 100 | { |
97 | struct lirc_codec *lirc; | 101 | struct lirc_codec *lirc; |
98 | struct ir_input_dev *ir_dev; | 102 | struct ir_input_dev *ir_dev; |
99 | int ret = 0; | 103 | int ret = 0; |
100 | void *drv_data; | 104 | void *drv_data; |
101 | unsigned long val; | 105 | unsigned long val = 0; |
102 | 106 | ||
103 | lirc = lirc_get_pdata(filep); | 107 | lirc = lirc_get_pdata(filep); |
104 | if (!lirc) | 108 | if (!lirc) |
@@ -110,47 +114,106 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long ar | |||
110 | 114 | ||
111 | drv_data = ir_dev->props->priv; | 115 | drv_data = ir_dev->props->priv; |
112 | 116 | ||
113 | switch (cmd) { | 117 | if (_IOC_DIR(cmd) & _IOC_WRITE) { |
114 | case LIRC_SET_TRANSMITTER_MASK: | ||
115 | ret = get_user(val, (unsigned long *)arg); | 118 | ret = get_user(val, (unsigned long *)arg); |
116 | if (ret) | 119 | if (ret) |
117 | return ret; | 120 | return ret; |
121 | } | ||
122 | |||
123 | switch (cmd) { | ||
118 | 124 | ||
119 | if (ir_dev->props && ir_dev->props->s_tx_mask) | 125 | /* legacy support */ |
126 | case LIRC_GET_SEND_MODE: | ||
127 | val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK; | ||
128 | break; | ||
129 | |||
130 | case LIRC_SET_SEND_MODE: | ||
131 | if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK)) | ||
132 | return -EINVAL; | ||
133 | break; | ||
134 | |||
135 | /* TX settings */ | ||
136 | case LIRC_SET_TRANSMITTER_MASK: | ||
137 | if (ir_dev->props->s_tx_mask) | ||
120 | ret = ir_dev->props->s_tx_mask(drv_data, (u32)val); | 138 | ret = ir_dev->props->s_tx_mask(drv_data, (u32)val); |
121 | else | 139 | else |
122 | return -EINVAL; | 140 | return -EINVAL; |
123 | break; | 141 | break; |
124 | 142 | ||
125 | case LIRC_SET_SEND_CARRIER: | 143 | case LIRC_SET_SEND_CARRIER: |
126 | ret = get_user(val, (unsigned long *)arg); | 144 | if (ir_dev->props->s_tx_carrier) |
127 | if (ret) | ||
128 | return ret; | ||
129 | |||
130 | if (ir_dev->props && ir_dev->props->s_tx_carrier) | ||
131 | ir_dev->props->s_tx_carrier(drv_data, (u32)val); | 145 | ir_dev->props->s_tx_carrier(drv_data, (u32)val); |
132 | else | 146 | else |
133 | return -EINVAL; | 147 | return -EINVAL; |
134 | break; | 148 | break; |
135 | 149 | ||
136 | case LIRC_GET_SEND_MODE: | 150 | case LIRC_SET_SEND_DUTY_CYCLE: |
137 | val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK; | 151 | if (!ir_dev->props->s_tx_duty_cycle) |
138 | ret = put_user(val, (unsigned long *)arg); | 152 | return -ENOSYS; |
153 | |||
154 | if (val <= 0 || val >= 100) | ||
155 | return -EINVAL; | ||
156 | |||
157 | ir_dev->props->s_tx_duty_cycle(ir_dev->props->priv, val); | ||
139 | break; | 158 | break; |
140 | 159 | ||
141 | case LIRC_SET_SEND_MODE: | 160 | /* RX settings */ |
142 | ret = get_user(val, (unsigned long *)arg); | 161 | case LIRC_SET_REC_CARRIER: |
143 | if (ret) | 162 | if (ir_dev->props->s_rx_carrier_range) |
144 | return ret; | 163 | ret = ir_dev->props->s_rx_carrier_range( |
164 | ir_dev->props->priv, | ||
165 | ir_dev->raw->lirc.carrier_low, val); | ||
166 | else | ||
167 | return -ENOSYS; | ||
145 | 168 | ||
146 | if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK)) | 169 | if (!ret) |
170 | ir_dev->raw->lirc.carrier_low = 0; | ||
171 | break; | ||
172 | |||
173 | case LIRC_SET_REC_CARRIER_RANGE: | ||
174 | if (val >= 0) | ||
175 | ir_dev->raw->lirc.carrier_low = val; | ||
176 | break; | ||
177 | |||
178 | |||
179 | case LIRC_GET_REC_RESOLUTION: | ||
180 | val = ir_dev->props->rx_resolution; | ||
181 | break; | ||
182 | |||
183 | case LIRC_SET_WIDEBAND_RECEIVER: | ||
184 | if (ir_dev->props->s_learning_mode) | ||
185 | return ir_dev->props->s_learning_mode( | ||
186 | ir_dev->props->priv, !!val); | ||
187 | else | ||
188 | return -ENOSYS; | ||
189 | |||
190 | /* Generic timeout support */ | ||
191 | case LIRC_GET_MIN_TIMEOUT: | ||
192 | if (!ir_dev->props->max_timeout) | ||
193 | return -ENOSYS; | ||
194 | val = ir_dev->props->min_timeout / 1000; | ||
195 | break; | ||
196 | |||
197 | case LIRC_GET_MAX_TIMEOUT: | ||
198 | if (!ir_dev->props->max_timeout) | ||
199 | return -ENOSYS; | ||
200 | val = ir_dev->props->max_timeout / 1000; | ||
201 | break; | ||
202 | |||
203 | case LIRC_SET_REC_TIMEOUT: | ||
204 | if (val < ir_dev->props->min_timeout || | ||
205 | val > ir_dev->props->max_timeout) | ||
147 | return -EINVAL; | 206 | return -EINVAL; |
207 | ir_dev->props->timeout = val * 1000; | ||
148 | break; | 208 | break; |
149 | 209 | ||
150 | default: | 210 | default: |
151 | return lirc_dev_fop_ioctl(filep, cmd, arg); | 211 | return lirc_dev_fop_ioctl(filep, cmd, arg); |
152 | } | 212 | } |
153 | 213 | ||
214 | if (_IOC_DIR(cmd) & _IOC_READ) | ||
215 | ret = put_user(val, (unsigned long *)arg); | ||
216 | |||
154 | return ret; | 217 | return ret; |
155 | } | 218 | } |
156 | 219 | ||
@@ -196,13 +259,28 @@ static int ir_lirc_register(struct input_dev *input_dev) | |||
196 | 259 | ||
197 | features = LIRC_CAN_REC_MODE2; | 260 | features = LIRC_CAN_REC_MODE2; |
198 | if (ir_dev->props->tx_ir) { | 261 | if (ir_dev->props->tx_ir) { |
262 | |||
199 | features |= LIRC_CAN_SEND_PULSE; | 263 | features |= LIRC_CAN_SEND_PULSE; |
200 | if (ir_dev->props->s_tx_mask) | 264 | if (ir_dev->props->s_tx_mask) |
201 | features |= LIRC_CAN_SET_TRANSMITTER_MASK; | 265 | features |= LIRC_CAN_SET_TRANSMITTER_MASK; |
202 | if (ir_dev->props->s_tx_carrier) | 266 | if (ir_dev->props->s_tx_carrier) |
203 | features |= LIRC_CAN_SET_SEND_CARRIER; | 267 | features |= LIRC_CAN_SET_SEND_CARRIER; |
268 | |||
269 | if (ir_dev->props->s_tx_duty_cycle) | ||
270 | features |= LIRC_CAN_SET_REC_DUTY_CYCLE; | ||
204 | } | 271 | } |
205 | 272 | ||
273 | if (ir_dev->props->s_rx_carrier_range) | ||
274 | features |= LIRC_CAN_SET_REC_CARRIER | | ||
275 | LIRC_CAN_SET_REC_CARRIER_RANGE; | ||
276 | |||
277 | if (ir_dev->props->s_learning_mode) | ||
278 | features |= LIRC_CAN_USE_WIDEBAND_RECEIVER; | ||
279 | |||
280 | if (ir_dev->props->max_timeout) | ||
281 | features |= LIRC_CAN_SET_REC_TIMEOUT; | ||
282 | |||
283 | |||
206 | snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)", | 284 | snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)", |
207 | ir_dev->driver_name); | 285 | ir_dev->driver_name); |
208 | drv->minor = -1; | 286 | drv->minor = -1; |
@@ -224,8 +302,6 @@ static int ir_lirc_register(struct input_dev *input_dev) | |||
224 | 302 | ||
225 | ir_dev->raw->lirc.drv = drv; | 303 | ir_dev->raw->lirc.drv = drv; |
226 | ir_dev->raw->lirc.ir_dev = ir_dev; | 304 | ir_dev->raw->lirc.ir_dev = ir_dev; |
227 | ir_dev->raw->lirc.lircdata = PULSE_MASK; | ||
228 | |||
229 | return 0; | 305 | return 0; |
230 | 306 | ||
231 | lirc_register_failed: | 307 | lirc_register_failed: |
diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index 52e0f378ae3d..d597421d6547 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c | |||
@@ -20,12 +20,13 @@ | |||
20 | #define NEC_HEADER_PULSE (16 * NEC_UNIT) | 20 | #define NEC_HEADER_PULSE (16 * NEC_UNIT) |
21 | #define NECX_HEADER_PULSE (8 * NEC_UNIT) /* Less common NEC variant */ | 21 | #define NECX_HEADER_PULSE (8 * NEC_UNIT) /* Less common NEC variant */ |
22 | #define NEC_HEADER_SPACE (8 * NEC_UNIT) | 22 | #define NEC_HEADER_SPACE (8 * NEC_UNIT) |
23 | #define NEC_REPEAT_SPACE (8 * NEC_UNIT) | 23 | #define NEC_REPEAT_SPACE (4 * NEC_UNIT) |
24 | #define NEC_BIT_PULSE (1 * NEC_UNIT) | 24 | #define NEC_BIT_PULSE (1 * NEC_UNIT) |
25 | #define NEC_BIT_0_SPACE (1 * NEC_UNIT) | 25 | #define NEC_BIT_0_SPACE (1 * NEC_UNIT) |
26 | #define NEC_BIT_1_SPACE (3 * NEC_UNIT) | 26 | #define NEC_BIT_1_SPACE (3 * NEC_UNIT) |
27 | #define NEC_TRAILER_PULSE (1 * NEC_UNIT) | 27 | #define NEC_TRAILER_PULSE (1 * NEC_UNIT) |
28 | #define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */ | 28 | #define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */ |
29 | #define NECX_REPEAT_BITS 1 | ||
29 | 30 | ||
30 | enum nec_state { | 31 | enum nec_state { |
31 | STATE_INACTIVE, | 32 | STATE_INACTIVE, |
@@ -67,8 +68,12 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) | |||
67 | if (!ev.pulse) | 68 | if (!ev.pulse) |
68 | break; | 69 | break; |
69 | 70 | ||
70 | if (!eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2) && | 71 | if (eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2)) { |
71 | !eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2)) | 72 | data->is_nec_x = false; |
73 | data->necx_repeat = false; | ||
74 | } else if (eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2)) | ||
75 | data->is_nec_x = true; | ||
76 | else | ||
72 | break; | 77 | break; |
73 | 78 | ||
74 | data->count = 0; | 79 | data->count = 0; |
@@ -105,6 +110,17 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) | |||
105 | if (ev.pulse) | 110 | if (ev.pulse) |
106 | break; | 111 | break; |
107 | 112 | ||
113 | if (data->necx_repeat && data->count == NECX_REPEAT_BITS && | ||
114 | geq_margin(ev.duration, | ||
115 | NEC_TRAILER_SPACE, NEC_UNIT / 2)) { | ||
116 | IR_dprintk(1, "Repeat last key\n"); | ||
117 | ir_repeat(input_dev); | ||
118 | data->state = STATE_INACTIVE; | ||
119 | return 0; | ||
120 | |||
121 | } else if (data->count > NECX_REPEAT_BITS) | ||
122 | data->necx_repeat = false; | ||
123 | |||
108 | data->bits <<= 1; | 124 | data->bits <<= 1; |
109 | if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2)) | 125 | if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2)) |
110 | data->bits |= 1; | 126 | data->bits |= 1; |
@@ -159,6 +175,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) | |||
159 | IR_dprintk(1, "NEC scancode 0x%04x\n", scancode); | 175 | IR_dprintk(1, "NEC scancode 0x%04x\n", scancode); |
160 | } | 176 | } |
161 | 177 | ||
178 | if (data->is_nec_x) | ||
179 | data->necx_repeat = true; | ||
180 | |||
162 | ir_keydown(input_dev, scancode, 0); | 181 | ir_keydown(input_dev, scancode, 0); |
163 | data->state = STATE_INACTIVE; | 182 | data->state = STATE_INACTIVE; |
164 | return 0; | 183 | return 0; |
diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 6f192ef31db1..43094e7eccfa 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c | |||
@@ -12,9 +12,10 @@ | |||
12 | * GNU General Public License for more details. | 12 | * GNU General Public License for more details. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/workqueue.h> | 15 | #include <linux/kthread.h> |
16 | #include <linux/spinlock.h> | 16 | #include <linux/mutex.h> |
17 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
18 | #include <linux/freezer.h> | ||
18 | #include "ir-core-priv.h" | 19 | #include "ir-core-priv.h" |
19 | 20 | ||
20 | /* Define the max number of pulse/space transitions to buffer */ | 21 | /* Define the max number of pulse/space transitions to buffer */ |
@@ -24,7 +25,7 @@ | |||
24 | static LIST_HEAD(ir_raw_client_list); | 25 | static LIST_HEAD(ir_raw_client_list); |
25 | 26 | ||
26 | /* Used to handle IR raw handler extensions */ | 27 | /* Used to handle IR raw handler extensions */ |
27 | static DEFINE_SPINLOCK(ir_raw_handler_lock); | 28 | static DEFINE_MUTEX(ir_raw_handler_lock); |
28 | static LIST_HEAD(ir_raw_handler_list); | 29 | static LIST_HEAD(ir_raw_handler_list); |
29 | static u64 available_protocols; | 30 | static u64 available_protocols; |
30 | 31 | ||
@@ -33,20 +34,30 @@ static u64 available_protocols; | |||
33 | static struct work_struct wq_load; | 34 | static struct work_struct wq_load; |
34 | #endif | 35 | #endif |
35 | 36 | ||
36 | static void ir_raw_event_work(struct work_struct *work) | 37 | static int ir_raw_event_thread(void *data) |
37 | { | 38 | { |
38 | struct ir_raw_event ev; | 39 | struct ir_raw_event ev; |
39 | struct ir_raw_handler *handler; | 40 | struct ir_raw_handler *handler; |
40 | struct ir_raw_event_ctrl *raw = | 41 | struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data; |
41 | container_of(work, struct ir_raw_event_ctrl, rx_work); | 42 | |
42 | 43 | while (!kthread_should_stop()) { | |
43 | while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) { | 44 | try_to_freeze(); |
44 | spin_lock(&ir_raw_handler_lock); | 45 | |
45 | list_for_each_entry(handler, &ir_raw_handler_list, list) | 46 | mutex_lock(&ir_raw_handler_lock); |
46 | handler->decode(raw->input_dev, ev); | 47 | |
47 | spin_unlock(&ir_raw_handler_lock); | 48 | while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) { |
48 | raw->prev_ev = ev; | 49 | list_for_each_entry(handler, &ir_raw_handler_list, list) |
50 | handler->decode(raw->input_dev, ev); | ||
51 | raw->prev_ev = ev; | ||
52 | } | ||
53 | |||
54 | mutex_unlock(&ir_raw_handler_lock); | ||
55 | |||
56 | set_current_state(TASK_INTERRUPTIBLE); | ||
57 | schedule(); | ||
49 | } | 58 | } |
59 | |||
60 | return 0; | ||
50 | } | 61 | } |
51 | 62 | ||
52 | /** | 63 | /** |
@@ -66,6 +77,9 @@ int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev) | |||
66 | if (!ir->raw) | 77 | if (!ir->raw) |
67 | return -EINVAL; | 78 | return -EINVAL; |
68 | 79 | ||
80 | IR_dprintk(2, "sample: (05%dus %s)\n", | ||
81 | TO_US(ev->duration), TO_STR(ev->pulse)); | ||
82 | |||
69 | if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) | 83 | if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) |
70 | return -ENOMEM; | 84 | return -ENOMEM; |
71 | 85 | ||
@@ -126,6 +140,90 @@ int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type typ | |||
126 | EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); | 140 | EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); |
127 | 141 | ||
128 | /** | 142 | /** |
143 | * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing | ||
144 | * @input_dev: the struct input_dev device descriptor | ||
145 | * @type: the type of the event that has occurred | ||
146 | * | ||
147 | * This routine (which may be called from an interrupt context) works | ||
148 | * in similiar manner to ir_raw_event_store_edge. | ||
149 | * This routine is intended for devices with limited internal buffer | ||
150 | * It automerges samples of same type, and handles timeouts | ||
151 | */ | ||
152 | int ir_raw_event_store_with_filter(struct input_dev *input_dev, | ||
153 | struct ir_raw_event *ev) | ||
154 | { | ||
155 | struct ir_input_dev *ir = input_get_drvdata(input_dev); | ||
156 | struct ir_raw_event_ctrl *raw = ir->raw; | ||
157 | |||
158 | if (!raw || !ir->props) | ||
159 | return -EINVAL; | ||
160 | |||
161 | /* Ignore spaces in idle mode */ | ||
162 | if (ir->idle && !ev->pulse) | ||
163 | return 0; | ||
164 | else if (ir->idle) | ||
165 | ir_raw_event_set_idle(input_dev, 0); | ||
166 | |||
167 | if (!raw->this_ev.duration) { | ||
168 | raw->this_ev = *ev; | ||
169 | } else if (ev->pulse == raw->this_ev.pulse) { | ||
170 | raw->this_ev.duration += ev->duration; | ||
171 | } else { | ||
172 | ir_raw_event_store(input_dev, &raw->this_ev); | ||
173 | raw->this_ev = *ev; | ||
174 | } | ||
175 | |||
176 | /* Enter idle mode if nessesary */ | ||
177 | if (!ev->pulse && ir->props->timeout && | ||
178 | raw->this_ev.duration >= ir->props->timeout) | ||
179 | ir_raw_event_set_idle(input_dev, 1); | ||
180 | return 0; | ||
181 | } | ||
182 | EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter); | ||
183 | |||
184 | void ir_raw_event_set_idle(struct input_dev *input_dev, int idle) | ||
185 | { | ||
186 | struct ir_input_dev *ir = input_get_drvdata(input_dev); | ||
187 | struct ir_raw_event_ctrl *raw = ir->raw; | ||
188 | ktime_t now; | ||
189 | u64 delta; | ||
190 | |||
191 | if (!ir->props) | ||
192 | return; | ||
193 | |||
194 | if (!ir->raw) | ||
195 | goto out; | ||
196 | |||
197 | if (idle) { | ||
198 | IR_dprintk(2, "enter idle mode\n"); | ||
199 | raw->last_event = ktime_get(); | ||
200 | } else { | ||
201 | IR_dprintk(2, "exit idle mode\n"); | ||
202 | |||
203 | now = ktime_get(); | ||
204 | delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event)); | ||
205 | |||
206 | WARN_ON(raw->this_ev.pulse); | ||
207 | |||
208 | raw->this_ev.duration = | ||
209 | min(raw->this_ev.duration + delta, | ||
210 | (u64)IR_MAX_DURATION); | ||
211 | |||
212 | ir_raw_event_store(input_dev, &raw->this_ev); | ||
213 | |||
214 | if (raw->this_ev.duration == IR_MAX_DURATION) | ||
215 | ir_raw_event_reset(input_dev); | ||
216 | |||
217 | raw->this_ev.duration = 0; | ||
218 | } | ||
219 | out: | ||
220 | if (ir->props->s_idle) | ||
221 | ir->props->s_idle(ir->props->priv, idle); | ||
222 | ir->idle = idle; | ||
223 | } | ||
224 | EXPORT_SYMBOL_GPL(ir_raw_event_set_idle); | ||
225 | |||
226 | /** | ||
129 | * ir_raw_event_handle() - schedules the decoding of stored ir data | 227 | * ir_raw_event_handle() - schedules the decoding of stored ir data |
130 | * @input_dev: the struct input_dev device descriptor | 228 | * @input_dev: the struct input_dev device descriptor |
131 | * | 229 | * |
@@ -138,7 +236,7 @@ void ir_raw_event_handle(struct input_dev *input_dev) | |||
138 | if (!ir->raw) | 236 | if (!ir->raw) |
139 | return; | 237 | return; |
140 | 238 | ||
141 | schedule_work(&ir->raw->rx_work); | 239 | wake_up_process(ir->raw->thread); |
142 | } | 240 | } |
143 | EXPORT_SYMBOL_GPL(ir_raw_event_handle); | 241 | EXPORT_SYMBOL_GPL(ir_raw_event_handle); |
144 | 242 | ||
@@ -147,9 +245,9 @@ u64 | |||
147 | ir_raw_get_allowed_protocols() | 245 | ir_raw_get_allowed_protocols() |
148 | { | 246 | { |
149 | u64 protocols; | 247 | u64 protocols; |
150 | spin_lock(&ir_raw_handler_lock); | 248 | mutex_lock(&ir_raw_handler_lock); |
151 | protocols = available_protocols; | 249 | protocols = available_protocols; |
152 | spin_unlock(&ir_raw_handler_lock); | 250 | mutex_unlock(&ir_raw_handler_lock); |
153 | return protocols; | 251 | return protocols; |
154 | } | 252 | } |
155 | 253 | ||
@@ -167,7 +265,7 @@ int ir_raw_event_register(struct input_dev *input_dev) | |||
167 | return -ENOMEM; | 265 | return -ENOMEM; |
168 | 266 | ||
169 | ir->raw->input_dev = input_dev; | 267 | ir->raw->input_dev = input_dev; |
170 | INIT_WORK(&ir->raw->rx_work, ir_raw_event_work); | 268 | |
171 | ir->raw->enabled_protocols = ~0; | 269 | ir->raw->enabled_protocols = ~0; |
172 | rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, | 270 | rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, |
173 | GFP_KERNEL); | 271 | GFP_KERNEL); |
@@ -177,12 +275,21 @@ int ir_raw_event_register(struct input_dev *input_dev) | |||
177 | return rc; | 275 | return rc; |
178 | } | 276 | } |
179 | 277 | ||
180 | spin_lock(&ir_raw_handler_lock); | 278 | ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw, |
279 | "rc%u", (unsigned int)ir->devno); | ||
280 | |||
281 | if (IS_ERR(ir->raw->thread)) { | ||
282 | kfree(ir->raw); | ||
283 | ir->raw = NULL; | ||
284 | return PTR_ERR(ir->raw->thread); | ||
285 | } | ||
286 | |||
287 | mutex_lock(&ir_raw_handler_lock); | ||
181 | list_add_tail(&ir->raw->list, &ir_raw_client_list); | 288 | list_add_tail(&ir->raw->list, &ir_raw_client_list); |
182 | list_for_each_entry(handler, &ir_raw_handler_list, list) | 289 | list_for_each_entry(handler, &ir_raw_handler_list, list) |
183 | if (handler->raw_register) | 290 | if (handler->raw_register) |
184 | handler->raw_register(ir->raw->input_dev); | 291 | handler->raw_register(ir->raw->input_dev); |
185 | spin_unlock(&ir_raw_handler_lock); | 292 | mutex_unlock(&ir_raw_handler_lock); |
186 | 293 | ||
187 | return 0; | 294 | return 0; |
188 | } | 295 | } |
@@ -195,14 +302,14 @@ void ir_raw_event_unregister(struct input_dev *input_dev) | |||
195 | if (!ir->raw) | 302 | if (!ir->raw) |
196 | return; | 303 | return; |
197 | 304 | ||
198 | cancel_work_sync(&ir->raw->rx_work); | 305 | kthread_stop(ir->raw->thread); |
199 | 306 | ||
200 | spin_lock(&ir_raw_handler_lock); | 307 | mutex_lock(&ir_raw_handler_lock); |
201 | list_del(&ir->raw->list); | 308 | list_del(&ir->raw->list); |
202 | list_for_each_entry(handler, &ir_raw_handler_list, list) | 309 | list_for_each_entry(handler, &ir_raw_handler_list, list) |
203 | if (handler->raw_unregister) | 310 | if (handler->raw_unregister) |
204 | handler->raw_unregister(ir->raw->input_dev); | 311 | handler->raw_unregister(ir->raw->input_dev); |
205 | spin_unlock(&ir_raw_handler_lock); | 312 | mutex_unlock(&ir_raw_handler_lock); |
206 | 313 | ||
207 | kfifo_free(&ir->raw->kfifo); | 314 | kfifo_free(&ir->raw->kfifo); |
208 | kfree(ir->raw); | 315 | kfree(ir->raw); |
@@ -217,13 +324,13 @@ int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) | |||
217 | { | 324 | { |
218 | struct ir_raw_event_ctrl *raw; | 325 | struct ir_raw_event_ctrl *raw; |
219 | 326 | ||
220 | spin_lock(&ir_raw_handler_lock); | 327 | mutex_lock(&ir_raw_handler_lock); |
221 | list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); | 328 | list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); |
222 | if (ir_raw_handler->raw_register) | 329 | if (ir_raw_handler->raw_register) |
223 | list_for_each_entry(raw, &ir_raw_client_list, list) | 330 | list_for_each_entry(raw, &ir_raw_client_list, list) |
224 | ir_raw_handler->raw_register(raw->input_dev); | 331 | ir_raw_handler->raw_register(raw->input_dev); |
225 | available_protocols |= ir_raw_handler->protocols; | 332 | available_protocols |= ir_raw_handler->protocols; |
226 | spin_unlock(&ir_raw_handler_lock); | 333 | mutex_unlock(&ir_raw_handler_lock); |
227 | 334 | ||
228 | return 0; | 335 | return 0; |
229 | } | 336 | } |
@@ -233,13 +340,13 @@ void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) | |||
233 | { | 340 | { |
234 | struct ir_raw_event_ctrl *raw; | 341 | struct ir_raw_event_ctrl *raw; |
235 | 342 | ||
236 | spin_lock(&ir_raw_handler_lock); | 343 | mutex_lock(&ir_raw_handler_lock); |
237 | list_del(&ir_raw_handler->list); | 344 | list_del(&ir_raw_handler->list); |
238 | if (ir_raw_handler->raw_unregister) | 345 | if (ir_raw_handler->raw_unregister) |
239 | list_for_each_entry(raw, &ir_raw_client_list, list) | 346 | list_for_each_entry(raw, &ir_raw_client_list, list) |
240 | ir_raw_handler->raw_unregister(raw->input_dev); | 347 | ir_raw_handler->raw_unregister(raw->input_dev); |
241 | available_protocols &= ~ir_raw_handler->protocols; | 348 | available_protocols &= ~ir_raw_handler->protocols; |
242 | spin_unlock(&ir_raw_handler_lock); | 349 | mutex_unlock(&ir_raw_handler_lock); |
243 | } | 350 | } |
244 | EXPORT_SYMBOL(ir_raw_handler_unregister); | 351 | EXPORT_SYMBOL(ir_raw_handler_unregister); |
245 | 352 | ||
diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 6273047e915b..96dafc425c8e 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c | |||
@@ -325,6 +325,7 @@ static int __init ir_core_init(void) | |||
325 | 325 | ||
326 | /* Initialize/load the decoders/keymap code that will be used */ | 326 | /* Initialize/load the decoders/keymap code that will be used */ |
327 | ir_raw_init(); | 327 | ir_raw_init(); |
328 | ir_rcmap_init(); | ||
328 | 329 | ||
329 | return 0; | 330 | return 0; |
330 | } | 331 | } |
@@ -332,6 +333,7 @@ static int __init ir_core_init(void) | |||
332 | static void __exit ir_core_exit(void) | 333 | static void __exit ir_core_exit(void) |
333 | { | 334 | { |
334 | class_unregister(&ir_input_class); | 335 | class_unregister(&ir_input_class); |
336 | ir_rcmap_cleanup(); | ||
335 | } | 337 | } |
336 | 338 | ||
337 | module_init(ir_core_init); | 339 | module_init(ir_core_init); |
diff --git a/drivers/media/IR/keymaps/Makefile b/drivers/media/IR/keymaps/Makefile index cbee06243b51..950e5d953c6f 100644 --- a/drivers/media/IR/keymaps/Makefile +++ b/drivers/media/IR/keymaps/Makefile | |||
@@ -19,7 +19,6 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ | |||
19 | rc-dm1105-nec.o \ | 19 | rc-dm1105-nec.o \ |
20 | rc-dntv-live-dvb-t.o \ | 20 | rc-dntv-live-dvb-t.o \ |
21 | rc-dntv-live-dvbt-pro.o \ | 21 | rc-dntv-live-dvbt-pro.o \ |
22 | rc-empty.o \ | ||
23 | rc-em-terratec.o \ | 22 | rc-em-terratec.o \ |
24 | rc-encore-enltv2.o \ | 23 | rc-encore-enltv2.o \ |
25 | rc-encore-enltv.o \ | 24 | rc-encore-enltv.o \ |
@@ -59,6 +58,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ | |||
59 | rc-purpletv.o \ | 58 | rc-purpletv.o \ |
60 | rc-pv951.o \ | 59 | rc-pv951.o \ |
61 | rc-rc5-hauppauge-new.o \ | 60 | rc-rc5-hauppauge-new.o \ |
61 | rc-rc5-streamzap.o \ | ||
62 | rc-rc5-tv.o \ | 62 | rc-rc5-tv.o \ |
63 | rc-rc6-mce.o \ | 63 | rc-rc6-mce.o \ |
64 | rc-real-audio-220-32-keys.o \ | 64 | rc-real-audio-220-32-keys.o \ |
diff --git a/drivers/media/IR/keymaps/rc-empty.c b/drivers/media/IR/keymaps/rc-empty.c deleted file mode 100644 index 3b338d84b476..000000000000 --- a/drivers/media/IR/keymaps/rc-empty.c +++ /dev/null | |||
@@ -1,44 +0,0 @@ | |||
1 | /* empty.h - Keytable for empty Remote Controller | ||
2 | * | ||
3 | * keymap imported from ir-keymaps.c | ||
4 | * | ||
5 | * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <media/rc-map.h> | ||
14 | |||
15 | /* empty keytable, can be used as placeholder for not-yet created keytables */ | ||
16 | |||
17 | static struct ir_scancode empty[] = { | ||
18 | { 0x2a, KEY_COFFEE }, | ||
19 | }; | ||
20 | |||
21 | static struct rc_keymap empty_map = { | ||
22 | .map = { | ||
23 | .scan = empty, | ||
24 | .size = ARRAY_SIZE(empty), | ||
25 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
26 | .name = RC_MAP_EMPTY, | ||
27 | } | ||
28 | }; | ||
29 | |||
30 | static int __init init_rc_map_empty(void) | ||
31 | { | ||
32 | return ir_register_map(&empty_map); | ||
33 | } | ||
34 | |||
35 | static void __exit exit_rc_map_empty(void) | ||
36 | { | ||
37 | ir_unregister_map(&empty_map); | ||
38 | } | ||
39 | |||
40 | module_init(init_rc_map_empty) | ||
41 | module_exit(exit_rc_map_empty) | ||
42 | |||
43 | MODULE_LICENSE("GPL"); | ||
44 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-rc5-streamzap.c b/drivers/media/IR/keymaps/rc-rc5-streamzap.c new file mode 100644 index 000000000000..4c19c58b46d8 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-rc5-streamzap.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* rc-rc5-streamzap.c - Keytable for Streamzap PC Remote, for use | ||
2 | * with the Streamzap PC Remote IR Receiver. | ||
3 | * | ||
4 | * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com> | ||
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 | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <media/rc-map.h> | ||
13 | |||
14 | static struct ir_scancode rc5_streamzap[] = { | ||
15 | /* | ||
16 | * FIXME: The Streamzap remote isn't actually true RC-5, it has an extra | ||
17 | * bit in it, which presently throws the in-kernel RC-5 decoder for a loop. | ||
18 | * We either have to enhance the decoder to support it, add a new decoder, | ||
19 | * or just rely on lirc userspace decoding. | ||
20 | */ | ||
21 | { 0x00, KEY_NUMERIC_0 }, | ||
22 | { 0x01, KEY_NUMERIC_1 }, | ||
23 | { 0x02, KEY_NUMERIC_2 }, | ||
24 | { 0x03, KEY_NUMERIC_3 }, | ||
25 | { 0x04, KEY_NUMERIC_4 }, | ||
26 | { 0x05, KEY_NUMERIC_5 }, | ||
27 | { 0x06, KEY_NUMERIC_6 }, | ||
28 | { 0x07, KEY_NUMERIC_7 }, | ||
29 | { 0x08, KEY_NUMERIC_8 }, | ||
30 | { 0x0a, KEY_POWER }, | ||
31 | { 0x0b, KEY_MUTE }, | ||
32 | { 0x0c, KEY_CHANNELUP }, | ||
33 | { 0x0d, KEY_VOLUMEUP }, | ||
34 | { 0x0e, KEY_CHANNELDOWN }, | ||
35 | { 0x0f, KEY_VOLUMEDOWN }, | ||
36 | { 0x10, KEY_UP }, | ||
37 | { 0x11, KEY_LEFT }, | ||
38 | { 0x12, KEY_OK }, | ||
39 | { 0x13, KEY_RIGHT }, | ||
40 | { 0x14, KEY_DOWN }, | ||
41 | { 0x15, KEY_MENU }, | ||
42 | { 0x16, KEY_EXIT }, | ||
43 | { 0x17, KEY_PLAY }, | ||
44 | { 0x18, KEY_PAUSE }, | ||
45 | { 0x19, KEY_STOP }, | ||
46 | { 0x1a, KEY_BACK }, | ||
47 | { 0x1b, KEY_FORWARD }, | ||
48 | { 0x1c, KEY_RECORD }, | ||
49 | { 0x1d, KEY_REWIND }, | ||
50 | { 0x1e, KEY_FASTFORWARD }, | ||
51 | { 0x20, KEY_RED }, | ||
52 | { 0x21, KEY_GREEN }, | ||
53 | { 0x22, KEY_YELLOW }, | ||
54 | { 0x23, KEY_BLUE }, | ||
55 | |||
56 | }; | ||
57 | |||
58 | static struct rc_keymap rc5_streamzap_map = { | ||
59 | .map = { | ||
60 | .scan = rc5_streamzap, | ||
61 | .size = ARRAY_SIZE(rc5_streamzap), | ||
62 | .ir_type = IR_TYPE_RC5, | ||
63 | .name = RC_MAP_RC5_STREAMZAP, | ||
64 | } | ||
65 | }; | ||
66 | |||
67 | static int __init init_rc_map_rc5_streamzap(void) | ||
68 | { | ||
69 | return ir_register_map(&rc5_streamzap_map); | ||
70 | } | ||
71 | |||
72 | static void __exit exit_rc_map_rc5_streamzap(void) | ||
73 | { | ||
74 | ir_unregister_map(&rc5_streamzap_map); | ||
75 | } | ||
76 | |||
77 | module_init(init_rc_map_rc5_streamzap) | ||
78 | module_exit(exit_rc_map_rc5_streamzap) | ||
79 | |||
80 | MODULE_LICENSE("GPL"); | ||
81 | MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>"); | ||
diff --git a/drivers/media/IR/keymaps/rc-rc6-mce.c b/drivers/media/IR/keymaps/rc-rc6-mce.c index c6726a8039be..64264f7f838f 100644 --- a/drivers/media/IR/keymaps/rc-rc6-mce.c +++ b/drivers/media/IR/keymaps/rc-rc6-mce.c | |||
@@ -74,6 +74,8 @@ static struct ir_scancode rc6_mce[] = { | |||
74 | { 0x800f045a, KEY_SUBTITLE }, /* Caption/Teletext */ | 74 | { 0x800f045a, KEY_SUBTITLE }, /* Caption/Teletext */ |
75 | { 0x800f044d, KEY_TITLE }, | 75 | { 0x800f044d, KEY_TITLE }, |
76 | 76 | ||
77 | { 0x800f044e, KEY_PRINT }, /* Print - HP OEM version of remote */ | ||
78 | |||
77 | { 0x800f040c, KEY_POWER }, | 79 | { 0x800f040c, KEY_POWER }, |
78 | { 0x800f040d, KEY_PROG1 }, /* Windows MCE button */ | 80 | { 0x800f040d, KEY_PROG1 }, /* Windows MCE button */ |
79 | 81 | ||
diff --git a/drivers/media/IR/mceusb.c b/drivers/media/IR/mceusb.c index 78bf7f77a1a0..ac6bb2c01a48 100644 --- a/drivers/media/IR/mceusb.c +++ b/drivers/media/IR/mceusb.c | |||
@@ -228,7 +228,6 @@ static struct usb_device_id std_tx_mask_list[] = { | |||
228 | /* data structure for each usb transceiver */ | 228 | /* data structure for each usb transceiver */ |
229 | struct mceusb_dev { | 229 | struct mceusb_dev { |
230 | /* ir-core bits */ | 230 | /* ir-core bits */ |
231 | struct ir_input_dev *irdev; | ||
232 | struct ir_dev_props *props; | 231 | struct ir_dev_props *props; |
233 | struct ir_raw_event rawir; | 232 | struct ir_raw_event rawir; |
234 | 233 | ||
@@ -428,7 +427,7 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, | |||
428 | } | 427 | } |
429 | } | 428 | } |
430 | 429 | ||
431 | static void usb_async_callback(struct urb *urb, struct pt_regs *regs) | 430 | static void mce_async_callback(struct urb *urb, struct pt_regs *regs) |
432 | { | 431 | { |
433 | struct mceusb_dev *ir; | 432 | struct mceusb_dev *ir; |
434 | int len; | 433 | int len; |
@@ -477,7 +476,7 @@ static void mce_request_packet(struct mceusb_dev *ir, | |||
477 | /* outbound data */ | 476 | /* outbound data */ |
478 | usb_fill_int_urb(async_urb, ir->usbdev, | 477 | usb_fill_int_urb(async_urb, ir->usbdev, |
479 | usb_sndintpipe(ir->usbdev, ep->bEndpointAddress), | 478 | usb_sndintpipe(ir->usbdev, ep->bEndpointAddress), |
480 | async_buf, size, (usb_complete_t) usb_async_callback, | 479 | async_buf, size, (usb_complete_t)mce_async_callback, |
481 | ir, ep->bInterval); | 480 | ir, ep->bInterval); |
482 | memcpy(async_buf, data, size); | 481 | memcpy(async_buf, data, size); |
483 | 482 | ||
@@ -739,7 +738,7 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs) | |||
739 | 738 | ||
740 | if (ir->send_flags == RECV_FLAG_IN_PROGRESS) { | 739 | if (ir->send_flags == RECV_FLAG_IN_PROGRESS) { |
741 | ir->send_flags = SEND_FLAG_COMPLETE; | 740 | ir->send_flags = SEND_FLAG_COMPLETE; |
742 | dev_dbg(&ir->irdev->dev, "setup answer received %d bytes\n", | 741 | dev_dbg(ir->dev, "setup answer received %d bytes\n", |
743 | buf_len); | 742 | buf_len); |
744 | } | 743 | } |
745 | 744 | ||
@@ -861,7 +860,6 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir) | |||
861 | { | 860 | { |
862 | struct input_dev *idev; | 861 | struct input_dev *idev; |
863 | struct ir_dev_props *props; | 862 | struct ir_dev_props *props; |
864 | struct ir_input_dev *irdev; | ||
865 | struct device *dev = ir->dev; | 863 | struct device *dev = ir->dev; |
866 | int ret = -ENODEV; | 864 | int ret = -ENODEV; |
867 | 865 | ||
@@ -878,12 +876,6 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir) | |||
878 | goto props_alloc_failed; | 876 | goto props_alloc_failed; |
879 | } | 877 | } |
880 | 878 | ||
881 | irdev = kzalloc(sizeof(struct ir_input_dev), GFP_KERNEL); | ||
882 | if (!irdev) { | ||
883 | dev_err(dev, "remote ir input dev allocation failed\n"); | ||
884 | goto ir_dev_alloc_failed; | ||
885 | } | ||
886 | |||
887 | snprintf(ir->name, sizeof(ir->name), "Media Center Ed. eHome " | 879 | snprintf(ir->name, sizeof(ir->name), "Media Center Ed. eHome " |
888 | "Infrared Remote Transceiver (%04x:%04x)", | 880 | "Infrared Remote Transceiver (%04x:%04x)", |
889 | le16_to_cpu(ir->usbdev->descriptor.idVendor), | 881 | le16_to_cpu(ir->usbdev->descriptor.idVendor), |
@@ -902,9 +894,6 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir) | |||
902 | props->tx_ir = mceusb_tx_ir; | 894 | props->tx_ir = mceusb_tx_ir; |
903 | 895 | ||
904 | ir->props = props; | 896 | ir->props = props; |
905 | ir->irdev = irdev; | ||
906 | |||
907 | input_set_drvdata(idev, irdev); | ||
908 | 897 | ||
909 | ret = ir_input_register(idev, RC_MAP_RC6_MCE, props, DRIVER_NAME); | 898 | ret = ir_input_register(idev, RC_MAP_RC6_MCE, props, DRIVER_NAME); |
910 | if (ret < 0) { | 899 | if (ret < 0) { |
@@ -915,8 +904,6 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir) | |||
915 | return idev; | 904 | return idev; |
916 | 905 | ||
917 | irdev_failed: | 906 | irdev_failed: |
918 | kfree(irdev); | ||
919 | ir_dev_alloc_failed: | ||
920 | kfree(props); | 907 | kfree(props); |
921 | props_alloc_failed: | 908 | props_alloc_failed: |
922 | input_free_device(idev); | 909 | input_free_device(idev); |
@@ -932,7 +919,6 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf, | |||
932 | struct usb_endpoint_descriptor *ep = NULL; | 919 | struct usb_endpoint_descriptor *ep = NULL; |
933 | struct usb_endpoint_descriptor *ep_in = NULL; | 920 | struct usb_endpoint_descriptor *ep_in = NULL; |
934 | struct usb_endpoint_descriptor *ep_out = NULL; | 921 | struct usb_endpoint_descriptor *ep_out = NULL; |
935 | struct usb_host_config *config; | ||
936 | struct mceusb_dev *ir = NULL; | 922 | struct mceusb_dev *ir = NULL; |
937 | int pipe, maxp, i; | 923 | int pipe, maxp, i; |
938 | char buf[63], name[128] = ""; | 924 | char buf[63], name[128] = ""; |
@@ -942,7 +928,6 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf, | |||
942 | 928 | ||
943 | dev_dbg(&intf->dev, ": %s called\n", __func__); | 929 | dev_dbg(&intf->dev, ": %s called\n", __func__); |
944 | 930 | ||
945 | config = dev->actconfig; | ||
946 | idesc = intf->cur_altsetting; | 931 | idesc = intf->cur_altsetting; |
947 | 932 | ||
948 | is_gen3 = usb_match_id(intf, gen3_list) ? 1 : 0; | 933 | is_gen3 = usb_match_id(intf, gen3_list) ? 1 : 0; |
diff --git a/drivers/media/IR/rc-map.c b/drivers/media/IR/rc-map.c index 46a8f1524b5b..689143f2fff0 100644 --- a/drivers/media/IR/rc-map.c +++ b/drivers/media/IR/rc-map.c | |||
@@ -82,3 +82,26 @@ void ir_unregister_map(struct rc_keymap *map) | |||
82 | } | 82 | } |
83 | EXPORT_SYMBOL_GPL(ir_unregister_map); | 83 | EXPORT_SYMBOL_GPL(ir_unregister_map); |
84 | 84 | ||
85 | |||
86 | static struct ir_scancode empty[] = { | ||
87 | { 0x2a, KEY_COFFEE }, | ||
88 | }; | ||
89 | |||
90 | static struct rc_keymap empty_map = { | ||
91 | .map = { | ||
92 | .scan = empty, | ||
93 | .size = ARRAY_SIZE(empty), | ||
94 | .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ | ||
95 | .name = RC_MAP_EMPTY, | ||
96 | } | ||
97 | }; | ||
98 | |||
99 | int ir_rcmap_init(void) | ||
100 | { | ||
101 | return ir_register_map(&empty_map); | ||
102 | } | ||
103 | |||
104 | void ir_rcmap_cleanup(void) | ||
105 | { | ||
106 | ir_unregister_map(&empty_map); | ||
107 | } | ||
diff --git a/drivers/media/IR/streamzap.c b/drivers/media/IR/streamzap.c new file mode 100644 index 000000000000..058e29fd478c --- /dev/null +++ b/drivers/media/IR/streamzap.c | |||
@@ -0,0 +1,741 @@ | |||
1 | /* | ||
2 | * Streamzap Remote Control driver | ||
3 | * | ||
4 | * Copyright (c) 2005 Christoph Bartelmus <lirc@bartelmus.de> | ||
5 | * Copyright (c) 2010 Jarod Wilson <jarod@wilsonet.com> | ||
6 | * | ||
7 | * This driver was based on the work of Greg Wickham and Adrian | ||
8 | * Dewhurst. It was substantially rewritten to support correct signal | ||
9 | * gaps and now maintains a delay buffer, which is used to present | ||
10 | * consistent timing behaviour to user space applications. Without the | ||
11 | * delay buffer an ugly hack would be required in lircd, which can | ||
12 | * cause sluggish signal decoding in certain situations. | ||
13 | * | ||
14 | * Ported to in-kernel ir-core interface by Jarod Wilson | ||
15 | * | ||
16 | * This driver is based on the USB skeleton driver packaged with the | ||
17 | * kernel; copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com) | ||
18 | * | ||
19 | * This program is free software; you can redistribute it and/or modify | ||
20 | * it under the terms of the GNU General Public License as published by | ||
21 | * the Free Software Foundation; either version 2 of the License, or | ||
22 | * (at your option) any later version. | ||
23 | * | ||
24 | * This program is distributed in the hope that it will be useful, | ||
25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
27 | * GNU General Public License for more details. | ||
28 | * | ||
29 | * You should have received a copy of the GNU General Public License | ||
30 | * along with this program; if not, write to the Free Software | ||
31 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
32 | */ | ||
33 | |||
34 | #include <linux/device.h> | ||
35 | #include <linux/module.h> | ||
36 | #include <linux/slab.h> | ||
37 | #include <linux/usb.h> | ||
38 | #include <linux/input.h> | ||
39 | #include <media/ir-core.h> | ||
40 | |||
41 | #define DRIVER_VERSION "1.60" | ||
42 | #define DRIVER_NAME "streamzap" | ||
43 | #define DRIVER_DESC "Streamzap Remote Control driver" | ||
44 | |||
45 | #ifdef CONFIG_USB_DEBUG | ||
46 | static int debug = 1; | ||
47 | #else | ||
48 | static int debug; | ||
49 | #endif | ||
50 | |||
51 | #define USB_STREAMZAP_VENDOR_ID 0x0e9c | ||
52 | #define USB_STREAMZAP_PRODUCT_ID 0x0000 | ||
53 | |||
54 | /* table of devices that work with this driver */ | ||
55 | static struct usb_device_id streamzap_table[] = { | ||
56 | /* Streamzap Remote Control */ | ||
57 | { USB_DEVICE(USB_STREAMZAP_VENDOR_ID, USB_STREAMZAP_PRODUCT_ID) }, | ||
58 | /* Terminating entry */ | ||
59 | { } | ||
60 | }; | ||
61 | |||
62 | MODULE_DEVICE_TABLE(usb, streamzap_table); | ||
63 | |||
64 | #define STREAMZAP_PULSE_MASK 0xf0 | ||
65 | #define STREAMZAP_SPACE_MASK 0x0f | ||
66 | #define STREAMZAP_TIMEOUT 0xff | ||
67 | #define STREAMZAP_RESOLUTION 256 | ||
68 | |||
69 | /* number of samples buffered */ | ||
70 | #define SZ_BUF_LEN 128 | ||
71 | |||
72 | enum StreamzapDecoderState { | ||
73 | PulseSpace, | ||
74 | FullPulse, | ||
75 | FullSpace, | ||
76 | IgnorePulse | ||
77 | }; | ||
78 | |||
79 | /* structure to hold our device specific stuff */ | ||
80 | struct streamzap_ir { | ||
81 | |||
82 | /* ir-core */ | ||
83 | struct ir_dev_props *props; | ||
84 | struct ir_raw_event rawir; | ||
85 | |||
86 | /* core device info */ | ||
87 | struct device *dev; | ||
88 | struct input_dev *idev; | ||
89 | |||
90 | /* usb */ | ||
91 | struct usb_device *usbdev; | ||
92 | struct usb_interface *interface; | ||
93 | struct usb_endpoint_descriptor *endpoint; | ||
94 | struct urb *urb_in; | ||
95 | |||
96 | /* buffer & dma */ | ||
97 | unsigned char *buf_in; | ||
98 | dma_addr_t dma_in; | ||
99 | unsigned int buf_in_len; | ||
100 | |||
101 | /* timer used to support delay buffering */ | ||
102 | struct timer_list delay_timer; | ||
103 | bool timer_running; | ||
104 | spinlock_t timer_lock; | ||
105 | struct timer_list flush_timer; | ||
106 | bool flush; | ||
107 | |||
108 | /* delay buffer */ | ||
109 | struct kfifo fifo; | ||
110 | bool fifo_initialized; | ||
111 | |||
112 | /* track what state we're in */ | ||
113 | enum StreamzapDecoderState decoder_state; | ||
114 | /* tracks whether we are currently receiving some signal */ | ||
115 | bool idle; | ||
116 | /* sum of signal lengths received since signal start */ | ||
117 | unsigned long sum; | ||
118 | /* start time of signal; necessary for gap tracking */ | ||
119 | struct timeval signal_last; | ||
120 | struct timeval signal_start; | ||
121 | /* bool timeout_enabled; */ | ||
122 | |||
123 | char name[128]; | ||
124 | char phys[64]; | ||
125 | }; | ||
126 | |||
127 | |||
128 | /* local function prototypes */ | ||
129 | static int streamzap_probe(struct usb_interface *interface, | ||
130 | const struct usb_device_id *id); | ||
131 | static void streamzap_disconnect(struct usb_interface *interface); | ||
132 | static void streamzap_callback(struct urb *urb); | ||
133 | static int streamzap_suspend(struct usb_interface *intf, pm_message_t message); | ||
134 | static int streamzap_resume(struct usb_interface *intf); | ||
135 | |||
136 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
137 | static struct usb_driver streamzap_driver = { | ||
138 | .name = DRIVER_NAME, | ||
139 | .probe = streamzap_probe, | ||
140 | .disconnect = streamzap_disconnect, | ||
141 | .suspend = streamzap_suspend, | ||
142 | .resume = streamzap_resume, | ||
143 | .id_table = streamzap_table, | ||
144 | }; | ||
145 | |||
146 | static void streamzap_stop_timer(struct streamzap_ir *sz) | ||
147 | { | ||
148 | unsigned long flags; | ||
149 | |||
150 | spin_lock_irqsave(&sz->timer_lock, flags); | ||
151 | if (sz->timer_running) { | ||
152 | sz->timer_running = false; | ||
153 | spin_unlock_irqrestore(&sz->timer_lock, flags); | ||
154 | del_timer_sync(&sz->delay_timer); | ||
155 | } else { | ||
156 | spin_unlock_irqrestore(&sz->timer_lock, flags); | ||
157 | } | ||
158 | } | ||
159 | |||
160 | static void streamzap_flush_timeout(unsigned long arg) | ||
161 | { | ||
162 | struct streamzap_ir *sz = (struct streamzap_ir *)arg; | ||
163 | |||
164 | dev_info(sz->dev, "%s: callback firing\n", __func__); | ||
165 | |||
166 | /* finally start accepting data */ | ||
167 | sz->flush = false; | ||
168 | } | ||
169 | |||
170 | static void streamzap_delay_timeout(unsigned long arg) | ||
171 | { | ||
172 | struct streamzap_ir *sz = (struct streamzap_ir *)arg; | ||
173 | struct ir_raw_event rawir = { .pulse = false, .duration = 0 }; | ||
174 | unsigned long flags; | ||
175 | int len, ret; | ||
176 | static unsigned long delay; | ||
177 | bool wake = false; | ||
178 | |||
179 | /* deliver data every 10 ms */ | ||
180 | delay = msecs_to_jiffies(10); | ||
181 | |||
182 | spin_lock_irqsave(&sz->timer_lock, flags); | ||
183 | |||
184 | if (kfifo_len(&sz->fifo) > 0) { | ||
185 | ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir)); | ||
186 | if (ret != sizeof(rawir)) | ||
187 | dev_err(sz->dev, "Problem w/kfifo_out...\n"); | ||
188 | ir_raw_event_store(sz->idev, &rawir); | ||
189 | wake = true; | ||
190 | } | ||
191 | |||
192 | len = kfifo_len(&sz->fifo); | ||
193 | if (len > 0) { | ||
194 | while ((len < SZ_BUF_LEN / 2) && | ||
195 | (len < SZ_BUF_LEN * sizeof(int))) { | ||
196 | ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir)); | ||
197 | if (ret != sizeof(rawir)) | ||
198 | dev_err(sz->dev, "Problem w/kfifo_out...\n"); | ||
199 | ir_raw_event_store(sz->idev, &rawir); | ||
200 | wake = true; | ||
201 | len = kfifo_len(&sz->fifo); | ||
202 | } | ||
203 | if (sz->timer_running) | ||
204 | mod_timer(&sz->delay_timer, jiffies + delay); | ||
205 | |||
206 | } else { | ||
207 | sz->timer_running = false; | ||
208 | } | ||
209 | |||
210 | if (wake) | ||
211 | ir_raw_event_handle(sz->idev); | ||
212 | |||
213 | spin_unlock_irqrestore(&sz->timer_lock, flags); | ||
214 | } | ||
215 | |||
216 | static void streamzap_flush_delay_buffer(struct streamzap_ir *sz) | ||
217 | { | ||
218 | struct ir_raw_event rawir = { .pulse = false, .duration = 0 }; | ||
219 | bool wake = false; | ||
220 | int ret; | ||
221 | |||
222 | while (kfifo_len(&sz->fifo) > 0) { | ||
223 | ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir)); | ||
224 | if (ret != sizeof(rawir)) | ||
225 | dev_err(sz->dev, "Problem w/kfifo_out...\n"); | ||
226 | ir_raw_event_store(sz->idev, &rawir); | ||
227 | wake = true; | ||
228 | } | ||
229 | |||
230 | if (wake) | ||
231 | ir_raw_event_handle(sz->idev); | ||
232 | } | ||
233 | |||
234 | static void sz_push(struct streamzap_ir *sz) | ||
235 | { | ||
236 | struct ir_raw_event rawir = { .pulse = false, .duration = 0 }; | ||
237 | unsigned long flags; | ||
238 | int ret; | ||
239 | |||
240 | spin_lock_irqsave(&sz->timer_lock, flags); | ||
241 | if (kfifo_len(&sz->fifo) >= sizeof(int) * SZ_BUF_LEN) { | ||
242 | ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir)); | ||
243 | if (ret != sizeof(rawir)) | ||
244 | dev_err(sz->dev, "Problem w/kfifo_out...\n"); | ||
245 | ir_raw_event_store(sz->idev, &rawir); | ||
246 | } | ||
247 | |||
248 | kfifo_in(&sz->fifo, &sz->rawir, sizeof(rawir)); | ||
249 | |||
250 | if (!sz->timer_running) { | ||
251 | sz->delay_timer.expires = jiffies + (HZ / 10); | ||
252 | add_timer(&sz->delay_timer); | ||
253 | sz->timer_running = true; | ||
254 | } | ||
255 | |||
256 | spin_unlock_irqrestore(&sz->timer_lock, flags); | ||
257 | } | ||
258 | |||
259 | static void sz_push_full_pulse(struct streamzap_ir *sz, | ||
260 | unsigned char value) | ||
261 | { | ||
262 | if (sz->idle) { | ||
263 | long deltv; | ||
264 | |||
265 | sz->signal_last = sz->signal_start; | ||
266 | do_gettimeofday(&sz->signal_start); | ||
267 | |||
268 | deltv = sz->signal_start.tv_sec - sz->signal_last.tv_sec; | ||
269 | sz->rawir.pulse = false; | ||
270 | if (deltv > 15) { | ||
271 | /* really long time */ | ||
272 | sz->rawir.duration = IR_MAX_DURATION; | ||
273 | } else { | ||
274 | sz->rawir.duration = (int)(deltv * 1000000 + | ||
275 | sz->signal_start.tv_usec - | ||
276 | sz->signal_last.tv_usec); | ||
277 | sz->rawir.duration -= sz->sum; | ||
278 | sz->rawir.duration *= 1000; | ||
279 | sz->rawir.duration &= IR_MAX_DURATION; | ||
280 | } | ||
281 | dev_dbg(sz->dev, "ls %u\n", sz->rawir.duration); | ||
282 | sz_push(sz); | ||
283 | |||
284 | sz->idle = 0; | ||
285 | sz->sum = 0; | ||
286 | } | ||
287 | |||
288 | sz->rawir.pulse = true; | ||
289 | sz->rawir.duration = ((int) value) * STREAMZAP_RESOLUTION; | ||
290 | sz->rawir.duration += STREAMZAP_RESOLUTION / 2; | ||
291 | sz->sum += sz->rawir.duration; | ||
292 | sz->rawir.duration *= 1000; | ||
293 | sz->rawir.duration &= IR_MAX_DURATION; | ||
294 | dev_dbg(sz->dev, "p %u\n", sz->rawir.duration); | ||
295 | sz_push(sz); | ||
296 | } | ||
297 | |||
298 | static void sz_push_half_pulse(struct streamzap_ir *sz, | ||
299 | unsigned char value) | ||
300 | { | ||
301 | sz_push_full_pulse(sz, (value & STREAMZAP_PULSE_MASK) >> 4); | ||
302 | } | ||
303 | |||
304 | static void sz_push_full_space(struct streamzap_ir *sz, | ||
305 | unsigned char value) | ||
306 | { | ||
307 | sz->rawir.pulse = false; | ||
308 | sz->rawir.duration = ((int) value) * STREAMZAP_RESOLUTION; | ||
309 | sz->rawir.duration += STREAMZAP_RESOLUTION / 2; | ||
310 | sz->sum += sz->rawir.duration; | ||
311 | sz->rawir.duration *= 1000; | ||
312 | dev_dbg(sz->dev, "s %u\n", sz->rawir.duration); | ||
313 | sz_push(sz); | ||
314 | } | ||
315 | |||
316 | static void sz_push_half_space(struct streamzap_ir *sz, | ||
317 | unsigned long value) | ||
318 | { | ||
319 | sz_push_full_space(sz, value & STREAMZAP_SPACE_MASK); | ||
320 | } | ||
321 | |||
322 | /** | ||
323 | * streamzap_callback - usb IRQ handler callback | ||
324 | * | ||
325 | * This procedure is invoked on reception of data from | ||
326 | * the usb remote. | ||
327 | */ | ||
328 | static void streamzap_callback(struct urb *urb) | ||
329 | { | ||
330 | struct streamzap_ir *sz; | ||
331 | unsigned int i; | ||
332 | int len; | ||
333 | #if 0 | ||
334 | static int timeout = (((STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION) & | ||
335 | IR_MAX_DURATION) | 0x03000000); | ||
336 | #endif | ||
337 | |||
338 | if (!urb) | ||
339 | return; | ||
340 | |||
341 | sz = urb->context; | ||
342 | len = urb->actual_length; | ||
343 | |||
344 | switch (urb->status) { | ||
345 | case -ECONNRESET: | ||
346 | case -ENOENT: | ||
347 | case -ESHUTDOWN: | ||
348 | /* | ||
349 | * this urb is terminated, clean up. | ||
350 | * sz might already be invalid at this point | ||
351 | */ | ||
352 | dev_err(sz->dev, "urb terminated, status: %d\n", urb->status); | ||
353 | return; | ||
354 | default: | ||
355 | break; | ||
356 | } | ||
357 | |||
358 | dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len); | ||
359 | if (!sz->flush) { | ||
360 | for (i = 0; i < urb->actual_length; i++) { | ||
361 | dev_dbg(sz->dev, "%d: %x\n", i, | ||
362 | (unsigned char)sz->buf_in[i]); | ||
363 | switch (sz->decoder_state) { | ||
364 | case PulseSpace: | ||
365 | if ((sz->buf_in[i] & STREAMZAP_PULSE_MASK) == | ||
366 | STREAMZAP_PULSE_MASK) { | ||
367 | sz->decoder_state = FullPulse; | ||
368 | continue; | ||
369 | } else if ((sz->buf_in[i] & STREAMZAP_SPACE_MASK) | ||
370 | == STREAMZAP_SPACE_MASK) { | ||
371 | sz_push_half_pulse(sz, sz->buf_in[i]); | ||
372 | sz->decoder_state = FullSpace; | ||
373 | continue; | ||
374 | } else { | ||
375 | sz_push_half_pulse(sz, sz->buf_in[i]); | ||
376 | sz_push_half_space(sz, sz->buf_in[i]); | ||
377 | } | ||
378 | break; | ||
379 | case FullPulse: | ||
380 | sz_push_full_pulse(sz, sz->buf_in[i]); | ||
381 | sz->decoder_state = IgnorePulse; | ||
382 | break; | ||
383 | case FullSpace: | ||
384 | if (sz->buf_in[i] == STREAMZAP_TIMEOUT) { | ||
385 | sz->idle = 1; | ||
386 | streamzap_stop_timer(sz); | ||
387 | #if 0 | ||
388 | if (sz->timeout_enabled) { | ||
389 | sz->rawir.pulse = false; | ||
390 | sz->rawir.duration = timeout; | ||
391 | sz->rawir.duration *= 1000; | ||
392 | sz_push(sz); | ||
393 | } | ||
394 | #endif | ||
395 | streamzap_flush_delay_buffer(sz); | ||
396 | } else | ||
397 | sz_push_full_space(sz, sz->buf_in[i]); | ||
398 | sz->decoder_state = PulseSpace; | ||
399 | break; | ||
400 | case IgnorePulse: | ||
401 | if ((sz->buf_in[i]&STREAMZAP_SPACE_MASK) == | ||
402 | STREAMZAP_SPACE_MASK) { | ||
403 | sz->decoder_state = FullSpace; | ||
404 | continue; | ||
405 | } | ||
406 | sz_push_half_space(sz, sz->buf_in[i]); | ||
407 | sz->decoder_state = PulseSpace; | ||
408 | break; | ||
409 | } | ||
410 | } | ||
411 | } | ||
412 | |||
413 | usb_submit_urb(urb, GFP_ATOMIC); | ||
414 | |||
415 | return; | ||
416 | } | ||
417 | |||
418 | static struct input_dev *streamzap_init_input_dev(struct streamzap_ir *sz) | ||
419 | { | ||
420 | struct input_dev *idev; | ||
421 | struct ir_dev_props *props; | ||
422 | struct device *dev = sz->dev; | ||
423 | int ret; | ||
424 | |||
425 | idev = input_allocate_device(); | ||
426 | if (!idev) { | ||
427 | dev_err(dev, "remote input dev allocation failed\n"); | ||
428 | goto idev_alloc_failed; | ||
429 | } | ||
430 | |||
431 | props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); | ||
432 | if (!props) { | ||
433 | dev_err(dev, "remote ir dev props allocation failed\n"); | ||
434 | goto props_alloc_failed; | ||
435 | } | ||
436 | |||
437 | snprintf(sz->name, sizeof(sz->name), "Streamzap PC Remote Infrared " | ||
438 | "Receiver (%04x:%04x)", | ||
439 | le16_to_cpu(sz->usbdev->descriptor.idVendor), | ||
440 | le16_to_cpu(sz->usbdev->descriptor.idProduct)); | ||
441 | |||
442 | idev->name = sz->name; | ||
443 | usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys)); | ||
444 | strlcat(sz->phys, "/input0", sizeof(sz->phys)); | ||
445 | idev->phys = sz->phys; | ||
446 | |||
447 | props->priv = sz; | ||
448 | props->driver_type = RC_DRIVER_IR_RAW; | ||
449 | /* FIXME: not sure about supported protocols, check on this */ | ||
450 | props->allowed_protos = IR_TYPE_RC5 | IR_TYPE_RC6; | ||
451 | |||
452 | sz->props = props; | ||
453 | |||
454 | ret = ir_input_register(idev, RC_MAP_RC5_STREAMZAP, props, DRIVER_NAME); | ||
455 | if (ret < 0) { | ||
456 | dev_err(dev, "remote input device register failed\n"); | ||
457 | goto irdev_failed; | ||
458 | } | ||
459 | |||
460 | return idev; | ||
461 | |||
462 | irdev_failed: | ||
463 | kfree(props); | ||
464 | props_alloc_failed: | ||
465 | input_free_device(idev); | ||
466 | idev_alloc_failed: | ||
467 | return NULL; | ||
468 | } | ||
469 | |||
470 | static int streamzap_delay_buf_init(struct streamzap_ir *sz) | ||
471 | { | ||
472 | int ret; | ||
473 | |||
474 | ret = kfifo_alloc(&sz->fifo, sizeof(int) * SZ_BUF_LEN, | ||
475 | GFP_KERNEL); | ||
476 | if (ret == 0) | ||
477 | sz->fifo_initialized = 1; | ||
478 | |||
479 | return ret; | ||
480 | } | ||
481 | |||
482 | static void streamzap_start_flush_timer(struct streamzap_ir *sz) | ||
483 | { | ||
484 | sz->flush_timer.expires = jiffies + HZ; | ||
485 | sz->flush = true; | ||
486 | add_timer(&sz->flush_timer); | ||
487 | |||
488 | sz->urb_in->dev = sz->usbdev; | ||
489 | if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) | ||
490 | dev_err(sz->dev, "urb submit failed\n"); | ||
491 | } | ||
492 | |||
493 | /** | ||
494 | * streamzap_probe | ||
495 | * | ||
496 | * Called by usb-core to associated with a candidate device | ||
497 | * On any failure the return value is the ERROR | ||
498 | * On success return 0 | ||
499 | */ | ||
500 | static int __devinit streamzap_probe(struct usb_interface *intf, | ||
501 | const struct usb_device_id *id) | ||
502 | { | ||
503 | struct usb_device *usbdev = interface_to_usbdev(intf); | ||
504 | struct usb_host_interface *iface_host; | ||
505 | struct streamzap_ir *sz = NULL; | ||
506 | char buf[63], name[128] = ""; | ||
507 | int retval = -ENOMEM; | ||
508 | int pipe, maxp; | ||
509 | |||
510 | /* Allocate space for device driver specific data */ | ||
511 | sz = kzalloc(sizeof(struct streamzap_ir), GFP_KERNEL); | ||
512 | if (!sz) | ||
513 | return -ENOMEM; | ||
514 | |||
515 | sz->usbdev = usbdev; | ||
516 | sz->interface = intf; | ||
517 | |||
518 | /* Check to ensure endpoint information matches requirements */ | ||
519 | iface_host = intf->cur_altsetting; | ||
520 | |||
521 | if (iface_host->desc.bNumEndpoints != 1) { | ||
522 | dev_err(&intf->dev, "%s: Unexpected desc.bNumEndpoints (%d)\n", | ||
523 | __func__, iface_host->desc.bNumEndpoints); | ||
524 | retval = -ENODEV; | ||
525 | goto free_sz; | ||
526 | } | ||
527 | |||
528 | sz->endpoint = &(iface_host->endpoint[0].desc); | ||
529 | if ((sz->endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | ||
530 | != USB_DIR_IN) { | ||
531 | dev_err(&intf->dev, "%s: endpoint doesn't match input device " | ||
532 | "02%02x\n", __func__, sz->endpoint->bEndpointAddress); | ||
533 | retval = -ENODEV; | ||
534 | goto free_sz; | ||
535 | } | ||
536 | |||
537 | if ((sz->endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | ||
538 | != USB_ENDPOINT_XFER_INT) { | ||
539 | dev_err(&intf->dev, "%s: endpoint attributes don't match xfer " | ||
540 | "02%02x\n", __func__, sz->endpoint->bmAttributes); | ||
541 | retval = -ENODEV; | ||
542 | goto free_sz; | ||
543 | } | ||
544 | |||
545 | pipe = usb_rcvintpipe(usbdev, sz->endpoint->bEndpointAddress); | ||
546 | maxp = usb_maxpacket(usbdev, pipe, usb_pipeout(pipe)); | ||
547 | |||
548 | if (maxp == 0) { | ||
549 | dev_err(&intf->dev, "%s: endpoint Max Packet Size is 0!?!\n", | ||
550 | __func__); | ||
551 | retval = -ENODEV; | ||
552 | goto free_sz; | ||
553 | } | ||
554 | |||
555 | /* Allocate the USB buffer and IRQ URB */ | ||
556 | sz->buf_in = usb_alloc_coherent(usbdev, maxp, GFP_ATOMIC, &sz->dma_in); | ||
557 | if (!sz->buf_in) | ||
558 | goto free_sz; | ||
559 | |||
560 | sz->urb_in = usb_alloc_urb(0, GFP_KERNEL); | ||
561 | if (!sz->urb_in) | ||
562 | goto free_buf_in; | ||
563 | |||
564 | sz->dev = &intf->dev; | ||
565 | sz->buf_in_len = maxp; | ||
566 | |||
567 | if (usbdev->descriptor.iManufacturer | ||
568 | && usb_string(usbdev, usbdev->descriptor.iManufacturer, | ||
569 | buf, sizeof(buf)) > 0) | ||
570 | strlcpy(name, buf, sizeof(name)); | ||
571 | |||
572 | if (usbdev->descriptor.iProduct | ||
573 | && usb_string(usbdev, usbdev->descriptor.iProduct, | ||
574 | buf, sizeof(buf)) > 0) | ||
575 | snprintf(name + strlen(name), sizeof(name) - strlen(name), | ||
576 | " %s", buf); | ||
577 | |||
578 | retval = streamzap_delay_buf_init(sz); | ||
579 | if (retval) { | ||
580 | dev_err(&intf->dev, "%s: delay buffer init failed\n", __func__); | ||
581 | goto free_urb_in; | ||
582 | } | ||
583 | |||
584 | sz->idev = streamzap_init_input_dev(sz); | ||
585 | if (!sz->idev) | ||
586 | goto input_dev_fail; | ||
587 | |||
588 | sz->idle = true; | ||
589 | sz->decoder_state = PulseSpace; | ||
590 | #if 0 | ||
591 | /* not yet supported, depends on patches from maxim */ | ||
592 | /* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */ | ||
593 | sz->timeout_enabled = false; | ||
594 | sz->min_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION * 1000; | ||
595 | sz->max_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION * 1000; | ||
596 | #endif | ||
597 | |||
598 | init_timer(&sz->delay_timer); | ||
599 | sz->delay_timer.function = streamzap_delay_timeout; | ||
600 | sz->delay_timer.data = (unsigned long)sz; | ||
601 | spin_lock_init(&sz->timer_lock); | ||
602 | |||
603 | init_timer(&sz->flush_timer); | ||
604 | sz->flush_timer.function = streamzap_flush_timeout; | ||
605 | sz->flush_timer.data = (unsigned long)sz; | ||
606 | |||
607 | do_gettimeofday(&sz->signal_start); | ||
608 | |||
609 | /* Complete final initialisations */ | ||
610 | usb_fill_int_urb(sz->urb_in, usbdev, pipe, sz->buf_in, | ||
611 | maxp, (usb_complete_t)streamzap_callback, | ||
612 | sz, sz->endpoint->bInterval); | ||
613 | sz->urb_in->transfer_dma = sz->dma_in; | ||
614 | sz->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
615 | |||
616 | usb_set_intfdata(intf, sz); | ||
617 | |||
618 | streamzap_start_flush_timer(sz); | ||
619 | |||
620 | dev_info(sz->dev, "Registered %s on usb%d:%d\n", name, | ||
621 | usbdev->bus->busnum, usbdev->devnum); | ||
622 | |||
623 | return 0; | ||
624 | |||
625 | input_dev_fail: | ||
626 | kfifo_free(&sz->fifo); | ||
627 | free_urb_in: | ||
628 | usb_free_urb(sz->urb_in); | ||
629 | free_buf_in: | ||
630 | usb_free_coherent(usbdev, maxp, sz->buf_in, sz->dma_in); | ||
631 | free_sz: | ||
632 | kfree(sz); | ||
633 | |||
634 | return retval; | ||
635 | } | ||
636 | |||
637 | /** | ||
638 | * streamzap_disconnect | ||
639 | * | ||
640 | * Called by the usb core when the device is removed from the system. | ||
641 | * | ||
642 | * This routine guarantees that the driver will not submit any more urbs | ||
643 | * by clearing dev->usbdev. It is also supposed to terminate any currently | ||
644 | * active urbs. Unfortunately, usb_bulk_msg(), used in streamzap_read(), | ||
645 | * does not provide any way to do this. | ||
646 | */ | ||
647 | static void streamzap_disconnect(struct usb_interface *interface) | ||
648 | { | ||
649 | struct streamzap_ir *sz = usb_get_intfdata(interface); | ||
650 | struct usb_device *usbdev = interface_to_usbdev(interface); | ||
651 | |||
652 | usb_set_intfdata(interface, NULL); | ||
653 | |||
654 | if (!sz) | ||
655 | return; | ||
656 | |||
657 | if (sz->flush) { | ||
658 | sz->flush = false; | ||
659 | del_timer_sync(&sz->flush_timer); | ||
660 | } | ||
661 | |||
662 | streamzap_stop_timer(sz); | ||
663 | |||
664 | sz->usbdev = NULL; | ||
665 | ir_input_unregister(sz->idev); | ||
666 | usb_kill_urb(sz->urb_in); | ||
667 | usb_free_urb(sz->urb_in); | ||
668 | usb_free_coherent(usbdev, sz->buf_in_len, sz->buf_in, sz->dma_in); | ||
669 | |||
670 | kfree(sz); | ||
671 | } | ||
672 | |||
673 | static int streamzap_suspend(struct usb_interface *intf, pm_message_t message) | ||
674 | { | ||
675 | struct streamzap_ir *sz = usb_get_intfdata(intf); | ||
676 | |||
677 | if (sz->flush) { | ||
678 | sz->flush = false; | ||
679 | del_timer_sync(&sz->flush_timer); | ||
680 | } | ||
681 | |||
682 | streamzap_stop_timer(sz); | ||
683 | |||
684 | usb_kill_urb(sz->urb_in); | ||
685 | |||
686 | return 0; | ||
687 | } | ||
688 | |||
689 | static int streamzap_resume(struct usb_interface *intf) | ||
690 | { | ||
691 | struct streamzap_ir *sz = usb_get_intfdata(intf); | ||
692 | |||
693 | if (sz->fifo_initialized) | ||
694 | kfifo_reset(&sz->fifo); | ||
695 | |||
696 | sz->flush_timer.expires = jiffies + HZ; | ||
697 | sz->flush = true; | ||
698 | add_timer(&sz->flush_timer); | ||
699 | |||
700 | if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) { | ||
701 | dev_err(sz->dev, "Error sumbiting urb\n"); | ||
702 | return -EIO; | ||
703 | } | ||
704 | |||
705 | return 0; | ||
706 | } | ||
707 | |||
708 | /** | ||
709 | * streamzap_init | ||
710 | */ | ||
711 | static int __init streamzap_init(void) | ||
712 | { | ||
713 | int ret; | ||
714 | |||
715 | /* register this driver with the USB subsystem */ | ||
716 | ret = usb_register(&streamzap_driver); | ||
717 | if (ret < 0) | ||
718 | printk(KERN_ERR DRIVER_NAME ": usb register failed, " | ||
719 | "result = %d\n", ret); | ||
720 | |||
721 | return ret; | ||
722 | } | ||
723 | |||
724 | /** | ||
725 | * streamzap_exit | ||
726 | */ | ||
727 | static void __exit streamzap_exit(void) | ||
728 | { | ||
729 | usb_deregister(&streamzap_driver); | ||
730 | } | ||
731 | |||
732 | |||
733 | module_init(streamzap_init); | ||
734 | module_exit(streamzap_exit); | ||
735 | |||
736 | MODULE_AUTHOR("Jarod Wilson <jarod@wilsonet.com>"); | ||
737 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
738 | MODULE_LICENSE("GPL"); | ||
739 | |||
740 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
741 | MODULE_PARM_DESC(debug, "Enable debugging messages"); | ||