diff options
Diffstat (limited to 'drivers/media/IR/ene_ir.c')
-rw-r--r-- | drivers/media/IR/ene_ir.c | 1023 |
1 files changed, 1023 insertions, 0 deletions
diff --git a/drivers/media/IR/ene_ir.c b/drivers/media/IR/ene_ir.c new file mode 100644 index 00000000000..5447750f5e3 --- /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); | ||