Commit 812738e11158e9b92c4f0e9278de48377cfa3cc8
Committed by
Mauro Carvalho Chehab
1 parent
2ccb24ff3b
Exists in
master
and in
7 other branches
[media] lirc: remove staging lirc_it87 and lirc_ite8709 drivers
Remove older drivers lirc_it87 and lirc_ite8709 from the LIRC staging area, since they're now superceded by ite-cir. Signed-off-by: Juan J. Garcia de Soria <skandalfo@gmail.com> Tested-by: Stephan Raue <stephan@openelec.tv> Signed-off-by: Jarod Wilson <jarod@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Showing 5 changed files with 0 additions and 1699 deletions Side-by-side Diff
drivers/staging/lirc/Kconfig
... | ... | @@ -32,18 +32,6 @@ |
32 | 32 | |
33 | 33 | Current generation iMON devices use the input layer imon driver. |
34 | 34 | |
35 | -config LIRC_IT87 | |
36 | - tristate "ITE IT87XX CIR Port Receiver" | |
37 | - depends on LIRC && PNP | |
38 | - help | |
39 | - Driver for the ITE IT87xx IR Receiver | |
40 | - | |
41 | -config LIRC_ITE8709 | |
42 | - tristate "ITE8709 CIR Port Receiver" | |
43 | - depends on LIRC && PNP | |
44 | - help | |
45 | - Driver for the ITE8709 IR Receiver | |
46 | - | |
47 | 35 | config LIRC_PARALLEL |
48 | 36 | tristate "Homebrew Parallel Port Receiver" |
49 | 37 | depends on LIRC && PARPORT |
drivers/staging/lirc/Makefile
... | ... | @@ -6,8 +6,6 @@ |
6 | 6 | obj-$(CONFIG_LIRC_BT829) += lirc_bt829.o |
7 | 7 | obj-$(CONFIG_LIRC_IGORPLUGUSB) += lirc_igorplugusb.o |
8 | 8 | obj-$(CONFIG_LIRC_IMON) += lirc_imon.o |
9 | -obj-$(CONFIG_LIRC_IT87) += lirc_it87.o | |
10 | -obj-$(CONFIG_LIRC_ITE8709) += lirc_ite8709.o | |
11 | 9 | obj-$(CONFIG_LIRC_PARALLEL) += lirc_parallel.o |
12 | 10 | obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o |
13 | 11 | obj-$(CONFIG_LIRC_SERIAL) += lirc_serial.o |
drivers/staging/lirc/lirc_it87.c
Changes suppressed. Click to show
1 | -/* | |
2 | - * LIRC driver for ITE IT8712/IT8705 CIR port | |
3 | - * | |
4 | - * Copyright (C) 2001 Hans-Gunter Lutke Uphues <hg_lu@web.de> | |
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 | - * ITE IT8705 and IT8712(not tested) and IT8720 CIR-port support for lirc based | |
22 | - * via cut and paste from lirc_sir.c (C) 2000 Milan Pikula | |
23 | - * | |
24 | - * Attention: Sendmode only tested with debugging logs | |
25 | - * | |
26 | - * 2001/02/27 Christoph Bartelmus <lirc@bartelmus.de> : | |
27 | - * reimplemented read function | |
28 | - * 2005/06/05 Andrew Calkin implemented support for Asus Digimatrix, | |
29 | - * based on work of the following member of the Outertrack Digimatrix | |
30 | - * Forum: Art103 <r_tay@hotmail.com> | |
31 | - * 2009/12/24 James Edwards <jimbo-lirc@edwardsclan.net> implemeted support | |
32 | - * for ITE8704/ITE8718, on my machine, the DSDT reports 8704, but the | |
33 | - * chip identifies as 18. | |
34 | - */ | |
35 | - | |
36 | -#include <linux/module.h> | |
37 | -#include <linux/sched.h> | |
38 | -#include <linux/errno.h> | |
39 | -#include <linux/signal.h> | |
40 | -#include <linux/fs.h> | |
41 | -#include <linux/interrupt.h> | |
42 | -#include <linux/ioport.h> | |
43 | -#include <linux/kernel.h> | |
44 | -#include <linux/time.h> | |
45 | -#include <linux/string.h> | |
46 | -#include <linux/types.h> | |
47 | -#include <linux/wait.h> | |
48 | -#include <linux/mm.h> | |
49 | -#include <linux/delay.h> | |
50 | -#include <linux/poll.h> | |
51 | -#include <asm/system.h> | |
52 | -#include <linux/io.h> | |
53 | -#include <linux/irq.h> | |
54 | -#include <linux/fcntl.h> | |
55 | - | |
56 | -#include <linux/timer.h> | |
57 | -#include <linux/pnp.h> | |
58 | - | |
59 | -#include <media/lirc.h> | |
60 | -#include <media/lirc_dev.h> | |
61 | - | |
62 | -#include "lirc_it87.h" | |
63 | - | |
64 | -#ifdef LIRC_IT87_DIGIMATRIX | |
65 | -static int digimatrix = 1; | |
66 | -static int it87_freq = 36; /* kHz */ | |
67 | -static int irq = 9; | |
68 | -#else | |
69 | -static int digimatrix; | |
70 | -static int it87_freq = 38; /* kHz */ | |
71 | -static int irq = IT87_CIR_DEFAULT_IRQ; | |
72 | -#endif | |
73 | - | |
74 | -static unsigned long it87_bits_in_byte_out; | |
75 | -static unsigned long it87_send_counter; | |
76 | -static unsigned char it87_RXEN_mask = IT87_CIR_RCR_RXEN; | |
77 | - | |
78 | -#define RBUF_LEN 1024 | |
79 | - | |
80 | -#define LIRC_DRIVER_NAME "lirc_it87" | |
81 | - | |
82 | -/* timeout for sequences in jiffies (=5/100s) */ | |
83 | -/* must be longer than TIME_CONST */ | |
84 | -#define IT87_TIMEOUT (HZ*5/100) | |
85 | - | |
86 | -/* module parameters */ | |
87 | -static int debug; | |
88 | -#define dprintk(fmt, args...) \ | |
89 | - do { \ | |
90 | - if (debug) \ | |
91 | - printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ | |
92 | - fmt, ## args); \ | |
93 | - } while (0) | |
94 | - | |
95 | -static int io = IT87_CIR_DEFAULT_IOBASE; | |
96 | -/* receiver demodulator default: off */ | |
97 | -static int it87_enable_demodulator; | |
98 | - | |
99 | -static int timer_enabled; | |
100 | -static DEFINE_SPINLOCK(timer_lock); | |
101 | -static struct timer_list timerlist; | |
102 | -/* time of last signal change detected */ | |
103 | -static struct timeval last_tv = {0, 0}; | |
104 | -/* time of last UART data ready interrupt */ | |
105 | -static struct timeval last_intr_tv = {0, 0}; | |
106 | -static int last_value; | |
107 | - | |
108 | -static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue); | |
109 | - | |
110 | -static DEFINE_SPINLOCK(hardware_lock); | |
111 | -static DEFINE_SPINLOCK(dev_lock); | |
112 | -static bool device_open; | |
113 | - | |
114 | -static int rx_buf[RBUF_LEN]; | |
115 | -unsigned int rx_tail, rx_head; | |
116 | - | |
117 | -static struct pnp_driver it87_pnp_driver; | |
118 | - | |
119 | -/* SECTION: Prototypes */ | |
120 | - | |
121 | -/* Communication with user-space */ | |
122 | -static int lirc_open(struct inode *inode, struct file *file); | |
123 | -static int lirc_close(struct inode *inode, struct file *file); | |
124 | -static unsigned int lirc_poll(struct file *file, poll_table *wait); | |
125 | -static ssize_t lirc_read(struct file *file, char *buf, | |
126 | - size_t count, loff_t *ppos); | |
127 | -static ssize_t lirc_write(struct file *file, const char *buf, | |
128 | - size_t n, loff_t *pos); | |
129 | -static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | |
130 | -static void add_read_queue(int flag, unsigned long val); | |
131 | -static int init_chrdev(void); | |
132 | -static void drop_chrdev(void); | |
133 | -/* Hardware */ | |
134 | -static irqreturn_t it87_interrupt(int irq, void *dev_id); | |
135 | -static void send_space(unsigned long len); | |
136 | -static void send_pulse(unsigned long len); | |
137 | -static void init_send(void); | |
138 | -static void terminate_send(unsigned long len); | |
139 | -static int init_hardware(void); | |
140 | -static void drop_hardware(void); | |
141 | -/* Initialisation */ | |
142 | -static int init_port(void); | |
143 | -static void drop_port(void); | |
144 | - | |
145 | - | |
146 | -/* SECTION: Communication with user-space */ | |
147 | - | |
148 | -static int lirc_open(struct inode *inode, struct file *file) | |
149 | -{ | |
150 | - spin_lock(&dev_lock); | |
151 | - if (device_open) { | |
152 | - spin_unlock(&dev_lock); | |
153 | - return -EBUSY; | |
154 | - } | |
155 | - device_open = true; | |
156 | - spin_unlock(&dev_lock); | |
157 | - return 0; | |
158 | -} | |
159 | - | |
160 | - | |
161 | -static int lirc_close(struct inode *inode, struct file *file) | |
162 | -{ | |
163 | - spin_lock(&dev_lock); | |
164 | - device_open = false; | |
165 | - spin_unlock(&dev_lock); | |
166 | - return 0; | |
167 | -} | |
168 | - | |
169 | - | |
170 | -static unsigned int lirc_poll(struct file *file, poll_table *wait) | |
171 | -{ | |
172 | - poll_wait(file, &lirc_read_queue, wait); | |
173 | - if (rx_head != rx_tail) | |
174 | - return POLLIN | POLLRDNORM; | |
175 | - return 0; | |
176 | -} | |
177 | - | |
178 | - | |
179 | -static ssize_t lirc_read(struct file *file, char *buf, | |
180 | - size_t count, loff_t *ppos) | |
181 | -{ | |
182 | - int n = 0; | |
183 | - int retval = 0; | |
184 | - | |
185 | - while (n < count) { | |
186 | - if (file->f_flags & O_NONBLOCK && rx_head == rx_tail) { | |
187 | - retval = -EAGAIN; | |
188 | - break; | |
189 | - } | |
190 | - retval = wait_event_interruptible(lirc_read_queue, | |
191 | - rx_head != rx_tail); | |
192 | - if (retval) | |
193 | - break; | |
194 | - | |
195 | - if (copy_to_user((void *) buf + n, (void *) (rx_buf + rx_head), | |
196 | - sizeof(int))) { | |
197 | - retval = -EFAULT; | |
198 | - break; | |
199 | - } | |
200 | - rx_head = (rx_head + 1) & (RBUF_LEN - 1); | |
201 | - n += sizeof(int); | |
202 | - } | |
203 | - if (n) | |
204 | - return n; | |
205 | - return retval; | |
206 | -} | |
207 | - | |
208 | - | |
209 | -static ssize_t lirc_write(struct file *file, const char *buf, | |
210 | - size_t n, loff_t *pos) | |
211 | -{ | |
212 | - int i = 0; | |
213 | - int *tx_buf; | |
214 | - | |
215 | - if (n % sizeof(int)) | |
216 | - return -EINVAL; | |
217 | - tx_buf = memdup_user(buf, n); | |
218 | - if (IS_ERR(tx_buf)) | |
219 | - return PTR_ERR(tx_buf); | |
220 | - n /= sizeof(int); | |
221 | - init_send(); | |
222 | - while (1) { | |
223 | - if (i >= n) | |
224 | - break; | |
225 | - if (tx_buf[i]) | |
226 | - send_pulse(tx_buf[i]); | |
227 | - i++; | |
228 | - if (i >= n) | |
229 | - break; | |
230 | - if (tx_buf[i]) | |
231 | - send_space(tx_buf[i]); | |
232 | - i++; | |
233 | - } | |
234 | - terminate_send(tx_buf[i - 1]); | |
235 | - kfree(tx_buf); | |
236 | - return n; | |
237 | -} | |
238 | - | |
239 | - | |
240 | -static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) | |
241 | -{ | |
242 | - int retval = 0; | |
243 | - __u32 value = 0; | |
244 | - unsigned long hw_flags; | |
245 | - | |
246 | - if (cmd == LIRC_GET_FEATURES) | |
247 | - value = LIRC_CAN_SEND_PULSE | | |
248 | - LIRC_CAN_SET_SEND_CARRIER | | |
249 | - LIRC_CAN_REC_MODE2; | |
250 | - else if (cmd == LIRC_GET_SEND_MODE) | |
251 | - value = LIRC_MODE_PULSE; | |
252 | - else if (cmd == LIRC_GET_REC_MODE) | |
253 | - value = LIRC_MODE_MODE2; | |
254 | - | |
255 | - switch (cmd) { | |
256 | - case LIRC_GET_FEATURES: | |
257 | - case LIRC_GET_SEND_MODE: | |
258 | - case LIRC_GET_REC_MODE: | |
259 | - retval = put_user(value, (__u32 *) arg); | |
260 | - break; | |
261 | - | |
262 | - case LIRC_SET_SEND_MODE: | |
263 | - case LIRC_SET_REC_MODE: | |
264 | - retval = get_user(value, (__u32 *) arg); | |
265 | - break; | |
266 | - | |
267 | - case LIRC_SET_SEND_CARRIER: | |
268 | - retval = get_user(value, (__u32 *) arg); | |
269 | - if (retval) | |
270 | - return retval; | |
271 | - value /= 1000; | |
272 | - if (value > IT87_CIR_FREQ_MAX || | |
273 | - value < IT87_CIR_FREQ_MIN) | |
274 | - return -EINVAL; | |
275 | - | |
276 | - it87_freq = value; | |
277 | - | |
278 | - spin_lock_irqsave(&hardware_lock, hw_flags); | |
279 | - outb(((inb(io + IT87_CIR_TCR2) & IT87_CIR_TCR2_TXMPW) | | |
280 | - (it87_freq - IT87_CIR_FREQ_MIN) << 3), | |
281 | - io + IT87_CIR_TCR2); | |
282 | - spin_unlock_irqrestore(&hardware_lock, hw_flags); | |
283 | - dprintk("demodulation frequency: %d kHz\n", it87_freq); | |
284 | - | |
285 | - break; | |
286 | - | |
287 | - default: | |
288 | - retval = -EINVAL; | |
289 | - } | |
290 | - | |
291 | - if (retval) | |
292 | - return retval; | |
293 | - | |
294 | - if (cmd == LIRC_SET_REC_MODE) { | |
295 | - if (value != LIRC_MODE_MODE2) | |
296 | - retval = -ENOSYS; | |
297 | - } else if (cmd == LIRC_SET_SEND_MODE) { | |
298 | - if (value != LIRC_MODE_PULSE) | |
299 | - retval = -ENOSYS; | |
300 | - } | |
301 | - return retval; | |
302 | -} | |
303 | - | |
304 | -static void add_read_queue(int flag, unsigned long val) | |
305 | -{ | |
306 | - unsigned int new_rx_tail; | |
307 | - int newval; | |
308 | - | |
309 | - dprintk("add flag %d with val %lu\n", flag, val); | |
310 | - | |
311 | - newval = val & PULSE_MASK; | |
312 | - | |
313 | - /* | |
314 | - * statistically, pulses are ~TIME_CONST/2 too long. we could | |
315 | - * maybe make this more exact, but this is good enough | |
316 | - */ | |
317 | - if (flag) { | |
318 | - /* pulse */ | |
319 | - if (newval > TIME_CONST / 2) | |
320 | - newval -= TIME_CONST / 2; | |
321 | - else /* should not ever happen */ | |
322 | - newval = 1; | |
323 | - newval |= PULSE_BIT; | |
324 | - } else | |
325 | - newval += TIME_CONST / 2; | |
326 | - new_rx_tail = (rx_tail + 1) & (RBUF_LEN - 1); | |
327 | - if (new_rx_tail == rx_head) { | |
328 | - dprintk("Buffer overrun.\n"); | |
329 | - return; | |
330 | - } | |
331 | - rx_buf[rx_tail] = newval; | |
332 | - rx_tail = new_rx_tail; | |
333 | - wake_up_interruptible(&lirc_read_queue); | |
334 | -} | |
335 | - | |
336 | - | |
337 | -static const struct file_operations lirc_fops = { | |
338 | - .owner = THIS_MODULE, | |
339 | - .read = lirc_read, | |
340 | - .write = lirc_write, | |
341 | - .poll = lirc_poll, | |
342 | - .unlocked_ioctl = lirc_ioctl, | |
343 | -#ifdef CONFIG_COMPAT | |
344 | - .compat_ioctl = lirc_ioctl, | |
345 | -#endif | |
346 | - .open = lirc_open, | |
347 | - .release = lirc_close, | |
348 | - .llseek = noop_llseek, | |
349 | -}; | |
350 | - | |
351 | -static int set_use_inc(void *data) | |
352 | -{ | |
353 | - return 0; | |
354 | -} | |
355 | - | |
356 | -static void set_use_dec(void *data) | |
357 | -{ | |
358 | -} | |
359 | - | |
360 | -static struct lirc_driver driver = { | |
361 | - .name = LIRC_DRIVER_NAME, | |
362 | - .minor = -1, | |
363 | - .code_length = 1, | |
364 | - .sample_rate = 0, | |
365 | - .data = NULL, | |
366 | - .add_to_buf = NULL, | |
367 | - .set_use_inc = set_use_inc, | |
368 | - .set_use_dec = set_use_dec, | |
369 | - .fops = &lirc_fops, | |
370 | - .dev = NULL, | |
371 | - .owner = THIS_MODULE, | |
372 | -}; | |
373 | - | |
374 | - | |
375 | -static int init_chrdev(void) | |
376 | -{ | |
377 | - driver.minor = lirc_register_driver(&driver); | |
378 | - | |
379 | - if (driver.minor < 0) { | |
380 | - printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n"); | |
381 | - return -EIO; | |
382 | - } | |
383 | - return 0; | |
384 | -} | |
385 | - | |
386 | - | |
387 | -static void drop_chrdev(void) | |
388 | -{ | |
389 | - lirc_unregister_driver(driver.minor); | |
390 | -} | |
391 | - | |
392 | - | |
393 | -/* SECTION: Hardware */ | |
394 | -static long delta(struct timeval *tv1, struct timeval *tv2) | |
395 | -{ | |
396 | - unsigned long deltv; | |
397 | - | |
398 | - deltv = tv2->tv_sec - tv1->tv_sec; | |
399 | - if (deltv > 15) | |
400 | - deltv = 0xFFFFFF; | |
401 | - else | |
402 | - deltv = deltv*1000000 + tv2->tv_usec - tv1->tv_usec; | |
403 | - return deltv; | |
404 | -} | |
405 | - | |
406 | -static void it87_timeout(unsigned long data) | |
407 | -{ | |
408 | - unsigned long flags; | |
409 | - | |
410 | - /* avoid interference with interrupt */ | |
411 | - spin_lock_irqsave(&timer_lock, flags); | |
412 | - | |
413 | - if (digimatrix) { | |
414 | - /* We have timed out. Disable the RX mechanism. */ | |
415 | - | |
416 | - outb((inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN) | | |
417 | - IT87_CIR_RCR_RXACT, io + IT87_CIR_RCR); | |
418 | - if (it87_RXEN_mask) | |
419 | - outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN, | |
420 | - io + IT87_CIR_RCR); | |
421 | - dprintk(" TIMEOUT\n"); | |
422 | - timer_enabled = 0; | |
423 | - | |
424 | - /* fifo clear */ | |
425 | - outb(inb(io + IT87_CIR_TCR1) | IT87_CIR_TCR1_FIFOCLR, | |
426 | - io+IT87_CIR_TCR1); | |
427 | - | |
428 | - } else { | |
429 | - /* | |
430 | - * if last received signal was a pulse, but receiving stopped | |
431 | - * within the 9 bit frame, we need to finish this pulse and | |
432 | - * simulate a signal change to from pulse to space. Otherwise | |
433 | - * upper layers will receive two sequences next time. | |
434 | - */ | |
435 | - | |
436 | - if (last_value) { | |
437 | - unsigned long pulse_end; | |
438 | - | |
439 | - /* determine 'virtual' pulse end: */ | |
440 | - pulse_end = delta(&last_tv, &last_intr_tv); | |
441 | - dprintk("timeout add %d for %lu usec\n", | |
442 | - last_value, pulse_end); | |
443 | - add_read_queue(last_value, pulse_end); | |
444 | - last_value = 0; | |
445 | - last_tv = last_intr_tv; | |
446 | - } | |
447 | - } | |
448 | - spin_unlock_irqrestore(&timer_lock, flags); | |
449 | -} | |
450 | - | |
451 | -static irqreturn_t it87_interrupt(int irq, void *dev_id) | |
452 | -{ | |
453 | - unsigned char data; | |
454 | - struct timeval curr_tv; | |
455 | - static unsigned long deltv; | |
456 | - unsigned long deltintrtv; | |
457 | - unsigned long flags, hw_flags; | |
458 | - int iir, lsr; | |
459 | - int fifo = 0; | |
460 | - static char lastbit; | |
461 | - char bit; | |
462 | - | |
463 | - /* Bit duration in microseconds */ | |
464 | - const unsigned long bit_duration = 1000000ul / | |
465 | - (115200 / IT87_CIR_BAUDRATE_DIVISOR); | |
466 | - | |
467 | - | |
468 | - iir = inb(io + IT87_CIR_IIR); | |
469 | - | |
470 | - switch (iir & IT87_CIR_IIR_IID) { | |
471 | - case 0x4: | |
472 | - case 0x6: | |
473 | - lsr = inb(io + IT87_CIR_RSR) & (IT87_CIR_RSR_RXFTO | | |
474 | - IT87_CIR_RSR_RXFBC); | |
475 | - fifo = lsr & IT87_CIR_RSR_RXFBC; | |
476 | - dprintk("iir: 0x%x fifo: 0x%x\n", iir, lsr); | |
477 | - | |
478 | - /* avoid interference with timer */ | |
479 | - spin_lock_irqsave(&timer_lock, flags); | |
480 | - spin_lock_irqsave(&hardware_lock, hw_flags); | |
481 | - if (digimatrix) { | |
482 | - static unsigned long acc_pulse; | |
483 | - static unsigned long acc_space; | |
484 | - | |
485 | - do { | |
486 | - data = inb(io + IT87_CIR_DR); | |
487 | - data = ~data; | |
488 | - fifo--; | |
489 | - if (data != 0x00) { | |
490 | - if (timer_enabled) | |
491 | - del_timer(&timerlist); | |
492 | - /* | |
493 | - * start timer for end of | |
494 | - * sequence detection | |
495 | - */ | |
496 | - timerlist.expires = jiffies + | |
497 | - IT87_TIMEOUT; | |
498 | - add_timer(&timerlist); | |
499 | - timer_enabled = 1; | |
500 | - } | |
501 | - /* Loop through */ | |
502 | - for (bit = 0; bit < 8; ++bit) { | |
503 | - if ((data >> bit) & 1) { | |
504 | - ++acc_pulse; | |
505 | - if (lastbit == 0) { | |
506 | - add_read_queue(0, | |
507 | - acc_space * | |
508 | - bit_duration); | |
509 | - acc_space = 0; | |
510 | - } | |
511 | - } else { | |
512 | - ++acc_space; | |
513 | - if (lastbit == 1) { | |
514 | - add_read_queue(1, | |
515 | - acc_pulse * | |
516 | - bit_duration); | |
517 | - acc_pulse = 0; | |
518 | - } | |
519 | - } | |
520 | - lastbit = (data >> bit) & 1; | |
521 | - } | |
522 | - | |
523 | - } while (fifo != 0); | |
524 | - } else { /* Normal Operation */ | |
525 | - do { | |
526 | - del_timer(&timerlist); | |
527 | - data = inb(io + IT87_CIR_DR); | |
528 | - | |
529 | - dprintk("data=%02x\n", data); | |
530 | - do_gettimeofday(&curr_tv); | |
531 | - deltv = delta(&last_tv, &curr_tv); | |
532 | - deltintrtv = delta(&last_intr_tv, &curr_tv); | |
533 | - | |
534 | - dprintk("t %lu , d %d\n", | |
535 | - deltintrtv, (int)data); | |
536 | - | |
537 | - /* | |
538 | - * if nothing came in last 2 cycles, | |
539 | - * it was gap | |
540 | - */ | |
541 | - if (deltintrtv > TIME_CONST * 2) { | |
542 | - if (last_value) { | |
543 | - dprintk("GAP\n"); | |
544 | - | |
545 | - /* simulate signal change */ | |
546 | - add_read_queue(last_value, | |
547 | - deltv - | |
548 | - deltintrtv); | |
549 | - last_value = 0; | |
550 | - last_tv.tv_sec = | |
551 | - last_intr_tv.tv_sec; | |
552 | - last_tv.tv_usec = | |
553 | - last_intr_tv.tv_usec; | |
554 | - deltv = deltintrtv; | |
555 | - } | |
556 | - } | |
557 | - data = 1; | |
558 | - if (data ^ last_value) { | |
559 | - /* | |
560 | - * deltintrtv > 2*TIME_CONST, | |
561 | - * remember ? the other case is | |
562 | - * timeout | |
563 | - */ | |
564 | - add_read_queue(last_value, | |
565 | - deltv-TIME_CONST); | |
566 | - last_value = data; | |
567 | - last_tv = curr_tv; | |
568 | - if (last_tv.tv_usec >= TIME_CONST) | |
569 | - last_tv.tv_usec -= TIME_CONST; | |
570 | - else { | |
571 | - last_tv.tv_sec--; | |
572 | - last_tv.tv_usec += 1000000 - | |
573 | - TIME_CONST; | |
574 | - } | |
575 | - } | |
576 | - last_intr_tv = curr_tv; | |
577 | - if (data) { | |
578 | - /* | |
579 | - * start timer for end of | |
580 | - * sequence detection | |
581 | - */ | |
582 | - timerlist.expires = | |
583 | - jiffies + IT87_TIMEOUT; | |
584 | - add_timer(&timerlist); | |
585 | - } | |
586 | - outb((inb(io + IT87_CIR_RCR) & | |
587 | - ~IT87_CIR_RCR_RXEN) | | |
588 | - IT87_CIR_RCR_RXACT, | |
589 | - io + IT87_CIR_RCR); | |
590 | - if (it87_RXEN_mask) | |
591 | - outb(inb(io + IT87_CIR_RCR) | | |
592 | - IT87_CIR_RCR_RXEN, | |
593 | - io + IT87_CIR_RCR); | |
594 | - fifo--; | |
595 | - } while (fifo != 0); | |
596 | - } | |
597 | - spin_unlock_irqrestore(&hardware_lock, hw_flags); | |
598 | - spin_unlock_irqrestore(&timer_lock, flags); | |
599 | - | |
600 | - return IRQ_RETVAL(IRQ_HANDLED); | |
601 | - | |
602 | - default: | |
603 | - /* not our irq */ | |
604 | - dprintk("unknown IRQ (shouldn't happen) !!\n"); | |
605 | - return IRQ_RETVAL(IRQ_NONE); | |
606 | - } | |
607 | -} | |
608 | - | |
609 | - | |
610 | -static void send_it87(unsigned long len, unsigned long stime, | |
611 | - unsigned char send_byte, unsigned int count_bits) | |
612 | -{ | |
613 | - long count = len / stime; | |
614 | - long time_left = 0; | |
615 | - static unsigned char byte_out; | |
616 | - unsigned long hw_flags; | |
617 | - | |
618 | - dprintk("%s: len=%ld, sb=%d\n", __func__, len, send_byte); | |
619 | - | |
620 | - time_left = (long)len - (long)count * (long)stime; | |
621 | - count += ((2 * time_left) / stime); | |
622 | - while (count) { | |
623 | - long i = 0; | |
624 | - for (i = 0; i < count_bits; i++) { | |
625 | - byte_out = (byte_out << 1) | (send_byte & 1); | |
626 | - it87_bits_in_byte_out++; | |
627 | - } | |
628 | - if (it87_bits_in_byte_out == 8) { | |
629 | - dprintk("out=0x%x, tsr_txfbc: 0x%x\n", | |
630 | - byte_out, | |
631 | - inb(io + IT87_CIR_TSR) & | |
632 | - IT87_CIR_TSR_TXFBC); | |
633 | - | |
634 | - while ((inb(io + IT87_CIR_TSR) & | |
635 | - IT87_CIR_TSR_TXFBC) >= IT87_CIR_FIFO_SIZE) | |
636 | - ; | |
637 | - | |
638 | - spin_lock_irqsave(&hardware_lock, hw_flags); | |
639 | - outb(byte_out, io + IT87_CIR_DR); | |
640 | - spin_unlock_irqrestore(&hardware_lock, hw_flags); | |
641 | - | |
642 | - it87_bits_in_byte_out = 0; | |
643 | - it87_send_counter++; | |
644 | - byte_out = 0; | |
645 | - } | |
646 | - count--; | |
647 | - } | |
648 | -} | |
649 | - | |
650 | - | |
651 | -/*TODO: maybe exchange space and pulse because it8705 only modulates 0-bits */ | |
652 | - | |
653 | -static void send_space(unsigned long len) | |
654 | -{ | |
655 | - send_it87(len, TIME_CONST, IT87_CIR_SPACE, IT87_CIR_BAUDRATE_DIVISOR); | |
656 | -} | |
657 | - | |
658 | -static void send_pulse(unsigned long len) | |
659 | -{ | |
660 | - send_it87(len, TIME_CONST, IT87_CIR_PULSE, IT87_CIR_BAUDRATE_DIVISOR); | |
661 | -} | |
662 | - | |
663 | - | |
664 | -static void init_send() | |
665 | -{ | |
666 | - unsigned long flags; | |
667 | - | |
668 | - spin_lock_irqsave(&hardware_lock, flags); | |
669 | - /* RXEN=0: receiver disable */ | |
670 | - it87_RXEN_mask = 0; | |
671 | - outb(inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN, | |
672 | - io + IT87_CIR_RCR); | |
673 | - spin_unlock_irqrestore(&hardware_lock, flags); | |
674 | - it87_bits_in_byte_out = 0; | |
675 | - it87_send_counter = 0; | |
676 | -} | |
677 | - | |
678 | - | |
679 | -static void terminate_send(unsigned long len) | |
680 | -{ | |
681 | - unsigned long flags; | |
682 | - unsigned long last = 0; | |
683 | - | |
684 | - last = it87_send_counter; | |
685 | - /* make sure all necessary data has been sent */ | |
686 | - while (last == it87_send_counter) | |
687 | - send_space(len); | |
688 | - /* wait until all data sent */ | |
689 | - while ((inb(io + IT87_CIR_TSR) & IT87_CIR_TSR_TXFBC) != 0) | |
690 | - ; | |
691 | - /* then re-enable receiver */ | |
692 | - spin_lock_irqsave(&hardware_lock, flags); | |
693 | - it87_RXEN_mask = IT87_CIR_RCR_RXEN; | |
694 | - outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN, | |
695 | - io + IT87_CIR_RCR); | |
696 | - spin_unlock_irqrestore(&hardware_lock, flags); | |
697 | -} | |
698 | - | |
699 | - | |
700 | -static int init_hardware(void) | |
701 | -{ | |
702 | - unsigned long flags; | |
703 | - unsigned char it87_rcr = 0; | |
704 | - | |
705 | - spin_lock_irqsave(&hardware_lock, flags); | |
706 | - /* init cir-port */ | |
707 | - /* enable r/w-access to Baudrate-Register */ | |
708 | - outb(IT87_CIR_IER_BR, io + IT87_CIR_IER); | |
709 | - outb(IT87_CIR_BAUDRATE_DIVISOR % 0x100, io+IT87_CIR_BDLR); | |
710 | - outb(IT87_CIR_BAUDRATE_DIVISOR / 0x100, io+IT87_CIR_BDHR); | |
711 | - /* Baudrate Register off, define IRQs: Input only */ | |
712 | - if (digimatrix) { | |
713 | - outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RFOIE, io + IT87_CIR_IER); | |
714 | - /* RX: HCFS=0, RXDCR = 001b (33,75..38,25 kHz), RXEN=1 */ | |
715 | - } else { | |
716 | - outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RDAIE, io + IT87_CIR_IER); | |
717 | - /* RX: HCFS=0, RXDCR = 001b (35,6..40,3 kHz), RXEN=1 */ | |
718 | - } | |
719 | - it87_rcr = (IT87_CIR_RCR_RXEN & it87_RXEN_mask) | 0x1; | |
720 | - if (it87_enable_demodulator) | |
721 | - it87_rcr |= IT87_CIR_RCR_RXEND; | |
722 | - outb(it87_rcr, io + IT87_CIR_RCR); | |
723 | - if (digimatrix) { | |
724 | - /* Set FIFO depth to 1 byte, and disable TX */ | |
725 | - outb(inb(io + IT87_CIR_TCR1) | 0x00, | |
726 | - io + IT87_CIR_TCR1); | |
727 | - | |
728 | - /* | |
729 | - * TX: it87_freq (36kHz), 'reserved' sensitivity | |
730 | - * setting (0x00) | |
731 | - */ | |
732 | - outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x00, | |
733 | - io + IT87_CIR_TCR2); | |
734 | - } else { | |
735 | - /* TX: 38kHz, 13,3us (pulse-width) */ | |
736 | - outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x06, | |
737 | - io + IT87_CIR_TCR2); | |
738 | - } | |
739 | - spin_unlock_irqrestore(&hardware_lock, flags); | |
740 | - return 0; | |
741 | -} | |
742 | - | |
743 | - | |
744 | -static void drop_hardware(void) | |
745 | -{ | |
746 | - unsigned long flags; | |
747 | - | |
748 | - spin_lock_irqsave(&hardware_lock, flags); | |
749 | - disable_irq(irq); | |
750 | - /* receiver disable */ | |
751 | - it87_RXEN_mask = 0; | |
752 | - outb(0x1, io + IT87_CIR_RCR); | |
753 | - /* turn off irqs */ | |
754 | - outb(0, io + IT87_CIR_IER); | |
755 | - /* fifo clear */ | |
756 | - outb(IT87_CIR_TCR1_FIFOCLR, io+IT87_CIR_TCR1); | |
757 | - /* reset */ | |
758 | - outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER); | |
759 | - enable_irq(irq); | |
760 | - spin_unlock_irqrestore(&hardware_lock, flags); | |
761 | -} | |
762 | - | |
763 | - | |
764 | -static unsigned char it87_read(unsigned char port) | |
765 | -{ | |
766 | - outb(port, IT87_ADRPORT); | |
767 | - return inb(IT87_DATAPORT); | |
768 | -} | |
769 | - | |
770 | - | |
771 | -static void it87_write(unsigned char port, unsigned char data) | |
772 | -{ | |
773 | - outb(port, IT87_ADRPORT); | |
774 | - outb(data, IT87_DATAPORT); | |
775 | -} | |
776 | - | |
777 | - | |
778 | -/* SECTION: Initialisation */ | |
779 | - | |
780 | -static int init_port(void) | |
781 | -{ | |
782 | - unsigned long hw_flags; | |
783 | - int retval = 0; | |
784 | - | |
785 | - unsigned char init_bytes[4] = IT87_INIT; | |
786 | - unsigned char it87_chipid = 0; | |
787 | - unsigned char ldn = 0; | |
788 | - unsigned int it87_io = 0; | |
789 | - unsigned int it87_irq = 0; | |
790 | - | |
791 | - /* Enter MB PnP Mode */ | |
792 | - outb(init_bytes[0], IT87_ADRPORT); | |
793 | - outb(init_bytes[1], IT87_ADRPORT); | |
794 | - outb(init_bytes[2], IT87_ADRPORT); | |
795 | - outb(init_bytes[3], IT87_ADRPORT); | |
796 | - | |
797 | - /* 8712 or 8705 ? */ | |
798 | - it87_chipid = it87_read(IT87_CHIP_ID1); | |
799 | - if (it87_chipid != 0x87) { | |
800 | - retval = -ENXIO; | |
801 | - return retval; | |
802 | - } | |
803 | - it87_chipid = it87_read(IT87_CHIP_ID2); | |
804 | - if ((it87_chipid != 0x05) && | |
805 | - (it87_chipid != 0x12) && | |
806 | - (it87_chipid != 0x18) && | |
807 | - (it87_chipid != 0x20)) { | |
808 | - printk(KERN_INFO LIRC_DRIVER_NAME | |
809 | - ": no IT8704/05/12/18/20 found (claimed IT87%02x), " | |
810 | - "exiting..\n", it87_chipid); | |
811 | - retval = -ENXIO; | |
812 | - return retval; | |
813 | - } | |
814 | - printk(KERN_INFO LIRC_DRIVER_NAME | |
815 | - ": found IT87%02x.\n", | |
816 | - it87_chipid); | |
817 | - | |
818 | - /* get I/O-Port and IRQ */ | |
819 | - if (it87_chipid == 0x12 || it87_chipid == 0x18) | |
820 | - ldn = IT8712_CIR_LDN; | |
821 | - else | |
822 | - ldn = IT8705_CIR_LDN; | |
823 | - it87_write(IT87_LDN, ldn); | |
824 | - | |
825 | - it87_io = it87_read(IT87_CIR_BASE_MSB) * 256 + | |
826 | - it87_read(IT87_CIR_BASE_LSB); | |
827 | - if (it87_io == 0) { | |
828 | - if (io == 0) | |
829 | - io = IT87_CIR_DEFAULT_IOBASE; | |
830 | - printk(KERN_INFO LIRC_DRIVER_NAME | |
831 | - ": set default io 0x%x\n", | |
832 | - io); | |
833 | - it87_write(IT87_CIR_BASE_MSB, io / 0x100); | |
834 | - it87_write(IT87_CIR_BASE_LSB, io % 0x100); | |
835 | - } else | |
836 | - io = it87_io; | |
837 | - | |
838 | - it87_irq = it87_read(IT87_CIR_IRQ); | |
839 | - if (digimatrix || it87_irq == 0) { | |
840 | - if (irq == 0) | |
841 | - irq = IT87_CIR_DEFAULT_IRQ; | |
842 | - printk(KERN_INFO LIRC_DRIVER_NAME | |
843 | - ": set default irq 0x%x\n", | |
844 | - irq); | |
845 | - it87_write(IT87_CIR_IRQ, irq); | |
846 | - } else | |
847 | - irq = it87_irq; | |
848 | - | |
849 | - spin_lock_irqsave(&hardware_lock, hw_flags); | |
850 | - /* reset */ | |
851 | - outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER); | |
852 | - /* fifo clear */ | |
853 | - outb(IT87_CIR_TCR1_FIFOCLR | | |
854 | - /* IT87_CIR_TCR1_ILE | */ | |
855 | - IT87_CIR_TCR1_TXRLE | | |
856 | - IT87_CIR_TCR1_TXENDF, io+IT87_CIR_TCR1); | |
857 | - spin_unlock_irqrestore(&hardware_lock, hw_flags); | |
858 | - | |
859 | - /* get I/O port access and IRQ line */ | |
860 | - if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) { | |
861 | - printk(KERN_ERR LIRC_DRIVER_NAME | |
862 | - ": i/o port 0x%.4x already in use.\n", io); | |
863 | - /* Leaving MB PnP Mode */ | |
864 | - it87_write(IT87_CFGCTRL, 0x2); | |
865 | - return -EBUSY; | |
866 | - } | |
867 | - | |
868 | - /* activate CIR-Device */ | |
869 | - it87_write(IT87_CIR_ACT, 0x1); | |
870 | - | |
871 | - /* Leaving MB PnP Mode */ | |
872 | - it87_write(IT87_CFGCTRL, 0x2); | |
873 | - | |
874 | - retval = request_irq(irq, it87_interrupt, 0 /*IRQF_DISABLED*/, | |
875 | - LIRC_DRIVER_NAME, NULL); | |
876 | - if (retval < 0) { | |
877 | - printk(KERN_ERR LIRC_DRIVER_NAME | |
878 | - ": IRQ %d already in use.\n", | |
879 | - irq); | |
880 | - release_region(io, 8); | |
881 | - return retval; | |
882 | - } | |
883 | - | |
884 | - printk(KERN_INFO LIRC_DRIVER_NAME | |
885 | - ": I/O port 0x%.4x, IRQ %d.\n", io, irq); | |
886 | - | |
887 | - init_timer(&timerlist); | |
888 | - timerlist.function = it87_timeout; | |
889 | - timerlist.data = 0xabadcafe; | |
890 | - | |
891 | - return 0; | |
892 | -} | |
893 | - | |
894 | - | |
895 | -static void drop_port(void) | |
896 | -{ | |
897 | -#if 0 | |
898 | - unsigned char init_bytes[4] = IT87_INIT; | |
899 | - | |
900 | - /* Enter MB PnP Mode */ | |
901 | - outb(init_bytes[0], IT87_ADRPORT); | |
902 | - outb(init_bytes[1], IT87_ADRPORT); | |
903 | - outb(init_bytes[2], IT87_ADRPORT); | |
904 | - outb(init_bytes[3], IT87_ADRPORT); | |
905 | - | |
906 | - /* deactivate CIR-Device */ | |
907 | - it87_write(IT87_CIR_ACT, 0x0); | |
908 | - | |
909 | - /* Leaving MB PnP Mode */ | |
910 | - it87_write(IT87_CFGCTRL, 0x2); | |
911 | -#endif | |
912 | - | |
913 | - del_timer_sync(&timerlist); | |
914 | - free_irq(irq, NULL); | |
915 | - release_region(io, 8); | |
916 | -} | |
917 | - | |
918 | - | |
919 | -static int init_lirc_it87(void) | |
920 | -{ | |
921 | - int retval; | |
922 | - | |
923 | - init_waitqueue_head(&lirc_read_queue); | |
924 | - retval = init_port(); | |
925 | - if (retval < 0) | |
926 | - return retval; | |
927 | - init_hardware(); | |
928 | - printk(KERN_INFO LIRC_DRIVER_NAME ": Installed.\n"); | |
929 | - return 0; | |
930 | -} | |
931 | - | |
932 | -static int it87_probe(struct pnp_dev *pnp_dev, | |
933 | - const struct pnp_device_id *dev_id) | |
934 | -{ | |
935 | - int retval; | |
936 | - | |
937 | - driver.dev = &pnp_dev->dev; | |
938 | - | |
939 | - retval = init_chrdev(); | |
940 | - if (retval < 0) | |
941 | - return retval; | |
942 | - | |
943 | - retval = init_lirc_it87(); | |
944 | - if (retval) | |
945 | - goto init_lirc_it87_failed; | |
946 | - | |
947 | - return 0; | |
948 | - | |
949 | -init_lirc_it87_failed: | |
950 | - drop_chrdev(); | |
951 | - | |
952 | - return retval; | |
953 | -} | |
954 | - | |
955 | -static int __init lirc_it87_init(void) | |
956 | -{ | |
957 | - return pnp_register_driver(&it87_pnp_driver); | |
958 | -} | |
959 | - | |
960 | - | |
961 | -static void __exit lirc_it87_exit(void) | |
962 | -{ | |
963 | - drop_hardware(); | |
964 | - drop_chrdev(); | |
965 | - drop_port(); | |
966 | - pnp_unregister_driver(&it87_pnp_driver); | |
967 | - printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n"); | |
968 | -} | |
969 | - | |
970 | -/* SECTION: PNP for ITE8704/13/18 */ | |
971 | - | |
972 | -static const struct pnp_device_id pnp_dev_table[] = { | |
973 | - {"ITE8704", 0}, | |
974 | - {"ITE8713", 0}, | |
975 | - {} | |
976 | -}; | |
977 | - | |
978 | -MODULE_DEVICE_TABLE(pnp, pnp_dev_table); | |
979 | - | |
980 | -static struct pnp_driver it87_pnp_driver = { | |
981 | - .name = LIRC_DRIVER_NAME, | |
982 | - .id_table = pnp_dev_table, | |
983 | - .probe = it87_probe, | |
984 | -}; | |
985 | - | |
986 | -module_init(lirc_it87_init); | |
987 | -module_exit(lirc_it87_exit); | |
988 | - | |
989 | -MODULE_DESCRIPTION("LIRC driver for ITE IT8704/05/12/18/20 CIR port"); | |
990 | -MODULE_AUTHOR("Hans-Gunter Lutke Uphues"); | |
991 | -MODULE_LICENSE("GPL"); | |
992 | - | |
993 | -module_param(io, int, S_IRUGO); | |
994 | -MODULE_PARM_DESC(io, "I/O base address (default: 0x310)"); | |
995 | - | |
996 | -module_param(irq, int, S_IRUGO); | |
997 | -#ifdef LIRC_IT87_DIGIMATRIX | |
998 | -MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 9)"); | |
999 | -#else | |
1000 | -MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 7)"); | |
1001 | -#endif | |
1002 | - | |
1003 | -module_param(it87_enable_demodulator, bool, S_IRUGO); | |
1004 | -MODULE_PARM_DESC(it87_enable_demodulator, | |
1005 | - "Receiver demodulator enable/disable (1/0), default: 0"); | |
1006 | - | |
1007 | -module_param(debug, bool, S_IRUGO | S_IWUSR); | |
1008 | -MODULE_PARM_DESC(debug, "Enable debugging messages"); | |
1009 | - | |
1010 | -module_param(digimatrix, bool, S_IRUGO | S_IWUSR); | |
1011 | -#ifdef LIRC_IT87_DIGIMATRIX | |
1012 | -MODULE_PARM_DESC(digimatrix, | |
1013 | - "Asus Digimatrix it87 compat. enable/disable (1/0), default: 1"); | |
1014 | -#else | |
1015 | -MODULE_PARM_DESC(digimatrix, | |
1016 | - "Asus Digimatrix it87 compat. enable/disable (1/0), default: 0"); | |
1017 | -#endif | |
1018 | - | |
1019 | - | |
1020 | -module_param(it87_freq, int, S_IRUGO); | |
1021 | -#ifdef LIRC_IT87_DIGIMATRIX | |
1022 | -MODULE_PARM_DESC(it87_freq, | |
1023 | - "Carrier demodulator frequency (kHz), (default: 36)"); | |
1024 | -#else | |
1025 | -MODULE_PARM_DESC(it87_freq, | |
1026 | - "Carrier demodulator frequency (kHz), (default: 38)"); | |
1027 | -#endif |
drivers/staging/lirc/lirc_it87.h
1 | -/* lirc_it87.h */ | |
2 | -/* SECTION: Definitions */ | |
3 | - | |
4 | -/********************************* ITE IT87xx ************************/ | |
5 | - | |
6 | -/* based on the following documentation from ITE: | |
7 | - a) IT8712F Preliminary CIR Programming Guide V0.1 | |
8 | - b) IT8705F Simple LPC I/O Preliminary Specification V0.3 | |
9 | - c) IT8712F EC-LPC I/O Preliminary Specification V0.5 | |
10 | -*/ | |
11 | - | |
12 | -/* IT8712/05 Ports: */ | |
13 | -#define IT87_ADRPORT 0x2e | |
14 | -#define IT87_DATAPORT 0x2f | |
15 | -#define IT87_INIT {0x87, 0x01, 0x55, 0x55} | |
16 | - | |
17 | -/* alternate Ports: */ | |
18 | -/* | |
19 | -#define IT87_ADRPORT 0x4e | |
20 | -#define IT87_DATAPORT 0x4f | |
21 | -#define IT87_INIT {0x87, 0x01, 0x55, 0xaa} | |
22 | - */ | |
23 | - | |
24 | -/* IT8712/05 Registers */ | |
25 | -#define IT87_CFGCTRL 0x2 | |
26 | -#define IT87_LDN 0x7 | |
27 | -#define IT87_CHIP_ID1 0x20 | |
28 | -#define IT87_CHIP_ID2 0x21 | |
29 | -#define IT87_CFG_VERSION 0x22 | |
30 | -#define IT87_SWSUSPEND 0x23 | |
31 | - | |
32 | -#define IT8712_CIR_LDN 0xa | |
33 | -#define IT8705_CIR_LDN 0x7 | |
34 | - | |
35 | -/* CIR Configuration Registers: */ | |
36 | -#define IT87_CIR_ACT 0x30 | |
37 | -#define IT87_CIR_BASE_MSB 0x60 | |
38 | -#define IT87_CIR_BASE_LSB 0x61 | |
39 | -#define IT87_CIR_IRQ 0x70 | |
40 | -#define IT87_CIR_CONFIG 0xf0 | |
41 | - | |
42 | -/* List of IT87_CIR registers: offset to BaseAddr */ | |
43 | -#define IT87_CIR_DR 0 | |
44 | -#define IT87_CIR_IER 1 | |
45 | -#define IT87_CIR_RCR 2 | |
46 | -#define IT87_CIR_TCR1 3 | |
47 | -#define IT87_CIR_TCR2 4 | |
48 | -#define IT87_CIR_TSR 5 | |
49 | -#define IT87_CIR_RSR 6 | |
50 | -#define IT87_CIR_BDLR 5 | |
51 | -#define IT87_CIR_BDHR 6 | |
52 | -#define IT87_CIR_IIR 7 | |
53 | - | |
54 | -/* Bit Definition */ | |
55 | -/* IER: */ | |
56 | -#define IT87_CIR_IER_TM_EN 0x80 | |
57 | -#define IT87_CIR_IER_RESEVED 0x40 | |
58 | -#define IT87_CIR_IER_RESET 0x20 | |
59 | -#define IT87_CIR_IER_BR 0x10 | |
60 | -#define IT87_CIR_IER_IEC 0x8 | |
61 | -#define IT87_CIR_IER_RFOIE 0x4 | |
62 | -#define IT87_CIR_IER_RDAIE 0x2 | |
63 | -#define IT87_CIR_IER_TLDLIE 0x1 | |
64 | - | |
65 | -/* RCR: */ | |
66 | -#define IT87_CIR_RCR_RDWOS 0x80 | |
67 | -#define IT87_CIR_RCR_HCFS 0x40 | |
68 | -#define IT87_CIR_RCR_RXEN 0x20 | |
69 | -#define IT87_CIR_RCR_RXEND 0x10 | |
70 | -#define IT87_CIR_RCR_RXACT 0x8 | |
71 | -#define IT87_CIR_RCR_RXDCR 0x7 | |
72 | - | |
73 | -/* TCR1: */ | |
74 | -#define IT87_CIR_TCR1_FIFOCLR 0x80 | |
75 | -#define IT87_CIR_TCR1_ILE 0x40 | |
76 | -#define IT87_CIR_TCR1_FIFOTL 0x30 | |
77 | -#define IT87_CIR_TCR1_TXRLE 0x8 | |
78 | -#define IT87_CIR_TCR1_TXENDF 0x4 | |
79 | -#define IT87_CIR_TCR1_TXMPM 0x3 | |
80 | - | |
81 | -/* TCR2: */ | |
82 | -#define IT87_CIR_TCR2_CFQ 0xf8 | |
83 | -#define IT87_CIR_TCR2_TXMPW 0x7 | |
84 | - | |
85 | -/* TSR: */ | |
86 | -#define IT87_CIR_TSR_RESERVED 0xc0 | |
87 | -#define IT87_CIR_TSR_TXFBC 0x3f | |
88 | - | |
89 | -/* RSR: */ | |
90 | -#define IT87_CIR_RSR_RXFTO 0x80 | |
91 | -#define IT87_CIR_RSR_RESERVED 0x40 | |
92 | -#define IT87_CIR_RSR_RXFBC 0x3f | |
93 | - | |
94 | -/* IIR: */ | |
95 | -#define IT87_CIR_IIR_RESERVED 0xf8 | |
96 | -#define IT87_CIR_IIR_IID 0x6 | |
97 | -#define IT87_CIR_IIR_IIP 0x1 | |
98 | - | |
99 | -/* TM: */ | |
100 | -#define IT87_CIR_TM_IL_SEL 0x80 | |
101 | -#define IT87_CIR_TM_RESERVED 0x40 | |
102 | -#define IT87_CIR_TM_TM_REG 0x3f | |
103 | - | |
104 | -#define IT87_CIR_FIFO_SIZE 32 | |
105 | - | |
106 | -/* Baudratedivisor for IT87: power of 2: only 1,2,4 or 8) */ | |
107 | -#define IT87_CIR_BAUDRATE_DIVISOR 0x1 | |
108 | -#define IT87_CIR_DEFAULT_IOBASE 0x310 | |
109 | -#define IT87_CIR_DEFAULT_IRQ 0x7 | |
110 | -#define IT87_CIR_SPACE 0x00 | |
111 | -#define IT87_CIR_PULSE 0xff | |
112 | -#define IT87_CIR_FREQ_MIN 27 | |
113 | -#define IT87_CIR_FREQ_MAX 58 | |
114 | -#define TIME_CONST (IT87_CIR_BAUDRATE_DIVISOR * 8000000ul / 115200ul) | |
115 | - | |
116 | -/********************************* ITE IT87xx ************************/ |
drivers/staging/lirc/lirc_ite8709.c
1 | -/* | |
2 | - * LIRC driver for ITE8709 CIR port | |
3 | - * | |
4 | - * Copyright (C) 2008 Grégory Lardière <spmf2004-lirc@yahoo.fr> | |
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/module.h> | |
23 | -#include <linux/interrupt.h> | |
24 | -#include <linux/sched.h> | |
25 | -#include <linux/delay.h> | |
26 | -#include <linux/pnp.h> | |
27 | -#include <linux/io.h> | |
28 | - | |
29 | -#include <media/lirc.h> | |
30 | -#include <media/lirc_dev.h> | |
31 | - | |
32 | -#define LIRC_DRIVER_NAME "lirc_ite8709" | |
33 | - | |
34 | -#define BUF_CHUNK_SIZE sizeof(int) | |
35 | -#define BUF_SIZE (128*BUF_CHUNK_SIZE) | |
36 | - | |
37 | -/* | |
38 | - * The ITE8709 device seems to be the combination of IT8512 superIO chip and | |
39 | - * a specific firmware running on the IT8512's embedded micro-controller. | |
40 | - * In addition of the embedded micro-controller, the IT8512 chip contains a | |
41 | - * CIR module and several other modules. A few modules are directly accessible | |
42 | - * by the host CPU, but most of them are only accessible by the | |
43 | - * micro-controller. The CIR module is only accessible by the micro-controller. | |
44 | - * The battery-backed SRAM module is accessible by the host CPU and the | |
45 | - * micro-controller. So one of the MC's firmware role is to act as a bridge | |
46 | - * between the host CPU and the CIR module. The firmware implements a kind of | |
47 | - * communication protocol using the SRAM module as a shared memory. The IT8512 | |
48 | - * specification is publicly available on ITE's web site, but the communication | |
49 | - * protocol is not, so it was reverse-engineered. | |
50 | - */ | |
51 | - | |
52 | -/* ITE8709 Registers addresses and values (reverse-engineered) */ | |
53 | -#define ITE8709_MODE 0x1a | |
54 | -#define ITE8709_REG_ADR 0x1b | |
55 | -#define ITE8709_REG_VAL 0x1c | |
56 | -#define ITE8709_IIR 0x1e /* Interrupt identification register */ | |
57 | -#define ITE8709_RFSR 0x1f /* Receiver FIFO status register */ | |
58 | -#define ITE8709_FIFO_START 0x20 | |
59 | - | |
60 | -#define ITE8709_MODE_READY 0X00 | |
61 | -#define ITE8709_MODE_WRITE 0X01 | |
62 | -#define ITE8709_MODE_READ 0X02 | |
63 | -#define ITE8709_IIR_RDAI 0x02 /* Receiver data available interrupt */ | |
64 | -#define ITE8709_IIR_RFOI 0x04 /* Receiver FIFO overrun interrupt */ | |
65 | -#define ITE8709_RFSR_MASK 0x3f /* FIFO byte count mask */ | |
66 | - | |
67 | -/* | |
68 | - * IT8512 CIR-module registers addresses and values | |
69 | - * (from IT8512 E/F specification v0.4.1) | |
70 | - */ | |
71 | -#define IT8512_REG_MSTCR 0x01 /* Master control register */ | |
72 | -#define IT8512_REG_IER 0x02 /* Interrupt enable register */ | |
73 | -#define IT8512_REG_CFR 0x04 /* Carrier frequency register */ | |
74 | -#define IT8512_REG_RCR 0x05 /* Receive control register */ | |
75 | -#define IT8512_REG_BDLR 0x08 /* Baud rate divisor low byte register */ | |
76 | -#define IT8512_REG_BDHR 0x09 /* Baud rate divisor high byte register */ | |
77 | - | |
78 | -#define IT8512_MSTCR_RESET 0x01 /* Reset registers to default value */ | |
79 | -#define IT8512_MSTCR_FIFOCLR 0x02 /* Clear FIFO */ | |
80 | -#define IT8512_MSTCR_FIFOTL_7 0x04 /* FIFO threshold level : 7 */ | |
81 | -#define IT8512_MSTCR_FIFOTL_25 0x0c /* FIFO threshold level : 25 */ | |
82 | -#define IT8512_IER_RDAIE 0x02 /* Enable data interrupt request */ | |
83 | -#define IT8512_IER_RFOIE 0x04 /* Enable FIFO overrun interrupt req */ | |
84 | -#define IT8512_IER_IEC 0x80 /* Enable interrupt request */ | |
85 | -#define IT8512_CFR_CF_36KHZ 0x09 /* Carrier freq : low speed, 36kHz */ | |
86 | -#define IT8512_RCR_RXDCR_1 0x01 /* Demodulation carrier range : 1 */ | |
87 | -#define IT8512_RCR_RXACT 0x08 /* Receiver active */ | |
88 | -#define IT8512_RCR_RXEN 0x80 /* Receiver enable */ | |
89 | -#define IT8512_BDR_6 6 /* Baud rate divisor : 6 */ | |
90 | - | |
91 | -/* Actual values used by this driver */ | |
92 | -#define CFG_FIFOTL IT8512_MSTCR_FIFOTL_25 | |
93 | -#define CFG_CR_FREQ IT8512_CFR_CF_36KHZ | |
94 | -#define CFG_DCR IT8512_RCR_RXDCR_1 | |
95 | -#define CFG_BDR IT8512_BDR_6 | |
96 | -#define CFG_TIMEOUT 100000 /* Rearm interrupt when a space is > 100 ms */ | |
97 | - | |
98 | -static int debug; | |
99 | - | |
100 | -struct ite8709_device { | |
101 | - int use_count; | |
102 | - int io; | |
103 | - int irq; | |
104 | - spinlock_t hardware_lock; | |
105 | - __u64 acc_pulse; | |
106 | - __u64 acc_space; | |
107 | - char lastbit; | |
108 | - struct timeval last_tv; | |
109 | - struct lirc_driver driver; | |
110 | - struct tasklet_struct tasklet; | |
111 | - char force_rearm; | |
112 | - char rearmed; | |
113 | - char device_busy; | |
114 | -}; | |
115 | - | |
116 | -#define dprintk(fmt, args...) \ | |
117 | - do { \ | |
118 | - if (debug) \ | |
119 | - printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ | |
120 | - fmt, ## args); \ | |
121 | - } while (0) | |
122 | - | |
123 | - | |
124 | -static unsigned char ite8709_read(struct ite8709_device *dev, | |
125 | - unsigned char port) | |
126 | -{ | |
127 | - outb(port, dev->io); | |
128 | - return inb(dev->io+1); | |
129 | -} | |
130 | - | |
131 | -static void ite8709_write(struct ite8709_device *dev, unsigned char port, | |
132 | - unsigned char data) | |
133 | -{ | |
134 | - outb(port, dev->io); | |
135 | - outb(data, dev->io+1); | |
136 | -} | |
137 | - | |
138 | -static void ite8709_wait_device(struct ite8709_device *dev) | |
139 | -{ | |
140 | - int i = 0; | |
141 | - /* | |
142 | - * loop until device tells it's ready to continue | |
143 | - * iterations count is usually ~750 but can sometimes achieve 13000 | |
144 | - */ | |
145 | - for (i = 0; i < 15000; i++) { | |
146 | - udelay(2); | |
147 | - if (ite8709_read(dev, ITE8709_MODE) == ITE8709_MODE_READY) | |
148 | - break; | |
149 | - } | |
150 | -} | |
151 | - | |
152 | -static void ite8709_write_register(struct ite8709_device *dev, | |
153 | - unsigned char reg_adr, unsigned char reg_value) | |
154 | -{ | |
155 | - ite8709_wait_device(dev); | |
156 | - | |
157 | - ite8709_write(dev, ITE8709_REG_VAL, reg_value); | |
158 | - ite8709_write(dev, ITE8709_REG_ADR, reg_adr); | |
159 | - ite8709_write(dev, ITE8709_MODE, ITE8709_MODE_WRITE); | |
160 | -} | |
161 | - | |
162 | -static void ite8709_init_hardware(struct ite8709_device *dev) | |
163 | -{ | |
164 | - spin_lock_irq(&dev->hardware_lock); | |
165 | - dev->device_busy = 1; | |
166 | - spin_unlock_irq(&dev->hardware_lock); | |
167 | - | |
168 | - ite8709_write_register(dev, IT8512_REG_BDHR, (CFG_BDR >> 8) & 0xff); | |
169 | - ite8709_write_register(dev, IT8512_REG_BDLR, CFG_BDR & 0xff); | |
170 | - ite8709_write_register(dev, IT8512_REG_CFR, CFG_CR_FREQ); | |
171 | - ite8709_write_register(dev, IT8512_REG_IER, | |
172 | - IT8512_IER_IEC | IT8512_IER_RFOIE | IT8512_IER_RDAIE); | |
173 | - ite8709_write_register(dev, IT8512_REG_RCR, CFG_DCR); | |
174 | - ite8709_write_register(dev, IT8512_REG_MSTCR, | |
175 | - CFG_FIFOTL | IT8512_MSTCR_FIFOCLR); | |
176 | - ite8709_write_register(dev, IT8512_REG_RCR, | |
177 | - IT8512_RCR_RXEN | IT8512_RCR_RXACT | CFG_DCR); | |
178 | - | |
179 | - spin_lock_irq(&dev->hardware_lock); | |
180 | - dev->device_busy = 0; | |
181 | - spin_unlock_irq(&dev->hardware_lock); | |
182 | - | |
183 | - tasklet_enable(&dev->tasklet); | |
184 | -} | |
185 | - | |
186 | -static void ite8709_drop_hardware(struct ite8709_device *dev) | |
187 | -{ | |
188 | - tasklet_disable(&dev->tasklet); | |
189 | - | |
190 | - spin_lock_irq(&dev->hardware_lock); | |
191 | - dev->device_busy = 1; | |
192 | - spin_unlock_irq(&dev->hardware_lock); | |
193 | - | |
194 | - ite8709_write_register(dev, IT8512_REG_RCR, 0); | |
195 | - ite8709_write_register(dev, IT8512_REG_MSTCR, | |
196 | - IT8512_MSTCR_RESET | IT8512_MSTCR_FIFOCLR); | |
197 | - | |
198 | - spin_lock_irq(&dev->hardware_lock); | |
199 | - dev->device_busy = 0; | |
200 | - spin_unlock_irq(&dev->hardware_lock); | |
201 | -} | |
202 | - | |
203 | -static int ite8709_set_use_inc(void *data) | |
204 | -{ | |
205 | - struct ite8709_device *dev; | |
206 | - dev = data; | |
207 | - if (dev->use_count == 0) | |
208 | - ite8709_init_hardware(dev); | |
209 | - dev->use_count++; | |
210 | - return 0; | |
211 | -} | |
212 | - | |
213 | -static void ite8709_set_use_dec(void *data) | |
214 | -{ | |
215 | - struct ite8709_device *dev; | |
216 | - dev = data; | |
217 | - dev->use_count--; | |
218 | - if (dev->use_count == 0) | |
219 | - ite8709_drop_hardware(dev); | |
220 | -} | |
221 | - | |
222 | -static void ite8709_add_read_queue(struct ite8709_device *dev, int flag, | |
223 | - __u64 val) | |
224 | -{ | |
225 | - int value; | |
226 | - | |
227 | - dprintk("add a %llu usec %s\n", val, flag ? "pulse" : "space"); | |
228 | - | |
229 | - value = (val > PULSE_MASK) ? PULSE_MASK : val; | |
230 | - if (flag) | |
231 | - value |= PULSE_BIT; | |
232 | - | |
233 | - if (!lirc_buffer_full(dev->driver.rbuf)) { | |
234 | - lirc_buffer_write(dev->driver.rbuf, (void *) &value); | |
235 | - wake_up(&dev->driver.rbuf->wait_poll); | |
236 | - } | |
237 | -} | |
238 | - | |
239 | -static irqreturn_t ite8709_interrupt(int irq, void *dev_id) | |
240 | -{ | |
241 | - unsigned char data; | |
242 | - int iir, rfsr, i; | |
243 | - int fifo = 0; | |
244 | - char bit; | |
245 | - struct timeval curr_tv; | |
246 | - | |
247 | - /* Bit duration in microseconds */ | |
248 | - const unsigned long bit_duration = 1000000ul / (115200 / CFG_BDR); | |
249 | - | |
250 | - struct ite8709_device *dev; | |
251 | - dev = dev_id; | |
252 | - | |
253 | - /* | |
254 | - * If device is busy, we simply discard data because we are in one of | |
255 | - * these two cases : shutting down or rearming the device, so this | |
256 | - * doesn't really matter and this avoids waiting too long in IRQ ctx | |
257 | - */ | |
258 | - spin_lock(&dev->hardware_lock); | |
259 | - if (dev->device_busy) { | |
260 | - spin_unlock(&dev->hardware_lock); | |
261 | - return IRQ_RETVAL(IRQ_HANDLED); | |
262 | - } | |
263 | - | |
264 | - iir = ite8709_read(dev, ITE8709_IIR); | |
265 | - | |
266 | - switch (iir) { | |
267 | - case ITE8709_IIR_RFOI: | |
268 | - dprintk("fifo overrun, scheduling forced rearm just in case\n"); | |
269 | - dev->force_rearm = 1; | |
270 | - tasklet_schedule(&dev->tasklet); | |
271 | - spin_unlock(&dev->hardware_lock); | |
272 | - return IRQ_RETVAL(IRQ_HANDLED); | |
273 | - | |
274 | - case ITE8709_IIR_RDAI: | |
275 | - rfsr = ite8709_read(dev, ITE8709_RFSR); | |
276 | - fifo = rfsr & ITE8709_RFSR_MASK; | |
277 | - if (fifo > 32) | |
278 | - fifo = 32; | |
279 | - dprintk("iir: 0x%x rfsr: 0x%x fifo: %d\n", iir, rfsr, fifo); | |
280 | - | |
281 | - if (dev->rearmed) { | |
282 | - do_gettimeofday(&curr_tv); | |
283 | - dev->acc_space += 1000000ull | |
284 | - * (curr_tv.tv_sec - dev->last_tv.tv_sec) | |
285 | - + (curr_tv.tv_usec - dev->last_tv.tv_usec); | |
286 | - dev->rearmed = 0; | |
287 | - } | |
288 | - for (i = 0; i < fifo; i++) { | |
289 | - data = ite8709_read(dev, i+ITE8709_FIFO_START); | |
290 | - data = ~data; | |
291 | - /* Loop through */ | |
292 | - for (bit = 0; bit < 8; ++bit) { | |
293 | - if ((data >> bit) & 1) { | |
294 | - dev->acc_pulse += bit_duration; | |
295 | - if (dev->lastbit == 0) { | |
296 | - ite8709_add_read_queue(dev, 0, | |
297 | - dev->acc_space); | |
298 | - dev->acc_space = 0; | |
299 | - } | |
300 | - } else { | |
301 | - dev->acc_space += bit_duration; | |
302 | - if (dev->lastbit == 1) { | |
303 | - ite8709_add_read_queue(dev, 1, | |
304 | - dev->acc_pulse); | |
305 | - dev->acc_pulse = 0; | |
306 | - } | |
307 | - } | |
308 | - dev->lastbit = (data >> bit) & 1; | |
309 | - } | |
310 | - } | |
311 | - ite8709_write(dev, ITE8709_RFSR, 0); | |
312 | - | |
313 | - if (dev->acc_space > CFG_TIMEOUT) { | |
314 | - dprintk("scheduling rearm IRQ\n"); | |
315 | - do_gettimeofday(&dev->last_tv); | |
316 | - dev->force_rearm = 0; | |
317 | - tasklet_schedule(&dev->tasklet); | |
318 | - } | |
319 | - | |
320 | - spin_unlock(&dev->hardware_lock); | |
321 | - return IRQ_RETVAL(IRQ_HANDLED); | |
322 | - | |
323 | - default: | |
324 | - /* not our irq */ | |
325 | - dprintk("unknown IRQ (shouldn't happen) !!\n"); | |
326 | - spin_unlock(&dev->hardware_lock); | |
327 | - return IRQ_RETVAL(IRQ_NONE); | |
328 | - } | |
329 | -} | |
330 | - | |
331 | -static void ite8709_rearm_irq(unsigned long data) | |
332 | -{ | |
333 | - struct ite8709_device *dev; | |
334 | - unsigned long flags; | |
335 | - dev = (struct ite8709_device *) data; | |
336 | - | |
337 | - spin_lock_irqsave(&dev->hardware_lock, flags); | |
338 | - dev->device_busy = 1; | |
339 | - spin_unlock_irqrestore(&dev->hardware_lock, flags); | |
340 | - | |
341 | - if (dev->force_rearm || dev->acc_space > CFG_TIMEOUT) { | |
342 | - dprintk("rearming IRQ\n"); | |
343 | - ite8709_write_register(dev, IT8512_REG_RCR, | |
344 | - IT8512_RCR_RXACT | CFG_DCR); | |
345 | - ite8709_write_register(dev, IT8512_REG_MSTCR, | |
346 | - CFG_FIFOTL | IT8512_MSTCR_FIFOCLR); | |
347 | - ite8709_write_register(dev, IT8512_REG_RCR, | |
348 | - IT8512_RCR_RXEN | IT8512_RCR_RXACT | CFG_DCR); | |
349 | - if (!dev->force_rearm) | |
350 | - dev->rearmed = 1; | |
351 | - dev->force_rearm = 0; | |
352 | - } | |
353 | - | |
354 | - spin_lock_irqsave(&dev->hardware_lock, flags); | |
355 | - dev->device_busy = 0; | |
356 | - spin_unlock_irqrestore(&dev->hardware_lock, flags); | |
357 | -} | |
358 | - | |
359 | -static int ite8709_cleanup(struct ite8709_device *dev, int stage, int errno, | |
360 | - char *msg) | |
361 | -{ | |
362 | - if (msg != NULL) | |
363 | - printk(KERN_ERR LIRC_DRIVER_NAME ": %s\n", msg); | |
364 | - | |
365 | - switch (stage) { | |
366 | - case 6: | |
367 | - if (dev->use_count > 0) | |
368 | - ite8709_drop_hardware(dev); | |
369 | - case 5: | |
370 | - free_irq(dev->irq, dev); | |
371 | - case 4: | |
372 | - release_region(dev->io, 2); | |
373 | - case 3: | |
374 | - lirc_unregister_driver(dev->driver.minor); | |
375 | - case 2: | |
376 | - lirc_buffer_free(dev->driver.rbuf); | |
377 | - kfree(dev->driver.rbuf); | |
378 | - case 1: | |
379 | - kfree(dev); | |
380 | - case 0: | |
381 | - ; | |
382 | - } | |
383 | - | |
384 | - return errno; | |
385 | -} | |
386 | - | |
387 | -static int __devinit ite8709_pnp_probe(struct pnp_dev *dev, | |
388 | - const struct pnp_device_id *dev_id) | |
389 | -{ | |
390 | - struct lirc_driver *driver; | |
391 | - struct ite8709_device *ite8709_dev; | |
392 | - int ret; | |
393 | - | |
394 | - /* Check resources validity */ | |
395 | - if (!pnp_irq_valid(dev, 0)) | |
396 | - return ite8709_cleanup(NULL, 0, -ENODEV, "invalid IRQ"); | |
397 | - if (!pnp_port_valid(dev, 2)) | |
398 | - return ite8709_cleanup(NULL, 0, -ENODEV, "invalid IO port"); | |
399 | - | |
400 | - /* Allocate memory for device struct */ | |
401 | - ite8709_dev = kzalloc(sizeof(struct ite8709_device), GFP_KERNEL); | |
402 | - if (ite8709_dev == NULL) | |
403 | - return ite8709_cleanup(NULL, 0, -ENOMEM, "kzalloc failed"); | |
404 | - pnp_set_drvdata(dev, ite8709_dev); | |
405 | - | |
406 | - /* Initialize device struct */ | |
407 | - ite8709_dev->use_count = 0; | |
408 | - ite8709_dev->irq = pnp_irq(dev, 0); | |
409 | - ite8709_dev->io = pnp_port_start(dev, 2); | |
410 | - ite8709_dev->hardware_lock = | |
411 | - __SPIN_LOCK_UNLOCKED(ite8709_dev->hardware_lock); | |
412 | - ite8709_dev->acc_pulse = 0; | |
413 | - ite8709_dev->acc_space = 0; | |
414 | - ite8709_dev->lastbit = 0; | |
415 | - do_gettimeofday(&ite8709_dev->last_tv); | |
416 | - tasklet_init(&ite8709_dev->tasklet, ite8709_rearm_irq, | |
417 | - (long) ite8709_dev); | |
418 | - ite8709_dev->force_rearm = 0; | |
419 | - ite8709_dev->rearmed = 0; | |
420 | - ite8709_dev->device_busy = 0; | |
421 | - | |
422 | - /* Initialize driver struct */ | |
423 | - driver = &ite8709_dev->driver; | |
424 | - strcpy(driver->name, LIRC_DRIVER_NAME); | |
425 | - driver->minor = -1; | |
426 | - driver->code_length = sizeof(int) * 8; | |
427 | - driver->sample_rate = 0; | |
428 | - driver->features = LIRC_CAN_REC_MODE2; | |
429 | - driver->data = ite8709_dev; | |
430 | - driver->add_to_buf = NULL; | |
431 | - driver->set_use_inc = ite8709_set_use_inc; | |
432 | - driver->set_use_dec = ite8709_set_use_dec; | |
433 | - driver->dev = &dev->dev; | |
434 | - driver->owner = THIS_MODULE; | |
435 | - | |
436 | - /* Initialize LIRC buffer */ | |
437 | - driver->rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); | |
438 | - if (!driver->rbuf) | |
439 | - return ite8709_cleanup(ite8709_dev, 1, -ENOMEM, | |
440 | - "can't allocate lirc_buffer"); | |
441 | - if (lirc_buffer_init(driver->rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) | |
442 | - return ite8709_cleanup(ite8709_dev, 1, -ENOMEM, | |
443 | - "lirc_buffer_init() failed"); | |
444 | - | |
445 | - /* Register LIRC driver */ | |
446 | - ret = lirc_register_driver(driver); | |
447 | - if (ret < 0) | |
448 | - return ite8709_cleanup(ite8709_dev, 2, ret, | |
449 | - "lirc_register_driver() failed"); | |
450 | - | |
451 | - /* Reserve I/O port access */ | |
452 | - if (!request_region(ite8709_dev->io, 2, LIRC_DRIVER_NAME)) | |
453 | - return ite8709_cleanup(ite8709_dev, 3, -EBUSY, | |
454 | - "i/o port already in use"); | |
455 | - | |
456 | - /* Reserve IRQ line */ | |
457 | - ret = request_irq(ite8709_dev->irq, ite8709_interrupt, 0, | |
458 | - LIRC_DRIVER_NAME, ite8709_dev); | |
459 | - if (ret < 0) | |
460 | - return ite8709_cleanup(ite8709_dev, 4, ret, | |
461 | - "IRQ already in use"); | |
462 | - | |
463 | - /* Initialize hardware */ | |
464 | - ite8709_drop_hardware(ite8709_dev); /* Shutdown hw until first use */ | |
465 | - | |
466 | - printk(KERN_INFO LIRC_DRIVER_NAME ": device found : irq=%d io=0x%x\n", | |
467 | - ite8709_dev->irq, ite8709_dev->io); | |
468 | - | |
469 | - return 0; | |
470 | -} | |
471 | - | |
472 | -static void __devexit ite8709_pnp_remove(struct pnp_dev *dev) | |
473 | -{ | |
474 | - struct ite8709_device *ite8709_dev; | |
475 | - ite8709_dev = pnp_get_drvdata(dev); | |
476 | - | |
477 | - ite8709_cleanup(ite8709_dev, 6, 0, NULL); | |
478 | - | |
479 | - printk(KERN_INFO LIRC_DRIVER_NAME ": device removed\n"); | |
480 | -} | |
481 | - | |
482 | -#ifdef CONFIG_PM | |
483 | -static int ite8709_pnp_suspend(struct pnp_dev *dev, pm_message_t state) | |
484 | -{ | |
485 | - struct ite8709_device *ite8709_dev; | |
486 | - ite8709_dev = pnp_get_drvdata(dev); | |
487 | - | |
488 | - if (ite8709_dev->use_count > 0) | |
489 | - ite8709_drop_hardware(ite8709_dev); | |
490 | - | |
491 | - return 0; | |
492 | -} | |
493 | - | |
494 | -static int ite8709_pnp_resume(struct pnp_dev *dev) | |
495 | -{ | |
496 | - struct ite8709_device *ite8709_dev; | |
497 | - ite8709_dev = pnp_get_drvdata(dev); | |
498 | - | |
499 | - if (ite8709_dev->use_count > 0) | |
500 | - ite8709_init_hardware(ite8709_dev); | |
501 | - | |
502 | - return 0; | |
503 | -} | |
504 | -#else | |
505 | -#define ite8709_pnp_suspend NULL | |
506 | -#define ite8709_pnp_resume NULL | |
507 | -#endif | |
508 | - | |
509 | -static const struct pnp_device_id pnp_dev_table[] = { | |
510 | - {"ITE8709", 0}, | |
511 | - {} | |
512 | -}; | |
513 | - | |
514 | -MODULE_DEVICE_TABLE(pnp, pnp_dev_table); | |
515 | - | |
516 | -static struct pnp_driver ite8709_pnp_driver = { | |
517 | - .name = LIRC_DRIVER_NAME, | |
518 | - .probe = ite8709_pnp_probe, | |
519 | - .remove = __devexit_p(ite8709_pnp_remove), | |
520 | - .suspend = ite8709_pnp_suspend, | |
521 | - .resume = ite8709_pnp_resume, | |
522 | - .id_table = pnp_dev_table, | |
523 | -}; | |
524 | - | |
525 | -static int __init ite8709_init_module(void) | |
526 | -{ | |
527 | - return pnp_register_driver(&ite8709_pnp_driver); | |
528 | -} | |
529 | -module_init(ite8709_init_module); | |
530 | - | |
531 | -static void __exit ite8709_cleanup_module(void) | |
532 | -{ | |
533 | - pnp_unregister_driver(&ite8709_pnp_driver); | |
534 | -} | |
535 | -module_exit(ite8709_cleanup_module); | |
536 | - | |
537 | -MODULE_DESCRIPTION("LIRC driver for ITE8709 CIR port"); | |
538 | -MODULE_AUTHOR("Grégory Lardière"); | |
539 | -MODULE_LICENSE("GPL"); | |
540 | - | |
541 | -module_param(debug, bool, S_IRUGO | S_IWUSR); | |
542 | -MODULE_PARM_DESC(debug, "Enable debugging messages"); |